forked from sheetjs/docs.sheetjs.com
		
	added a full Lynx demo
This commit is contained in:
		
							parent
							
								
									28453f2273
								
							
						
					
					
						commit
						1e69f93451
					
				
							
								
								
									
										388
									
								
								docz/docs/03-demos/17-mobile/07-lynx.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										388
									
								
								docz/docs/03-demos/17-mobile/07-lynx.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,388 @@
 | 
			
		||||
---
 | 
			
		||||
title: Sheets at Native Speed with Lynx
 | 
			
		||||
sidebar_label: Lynx
 | 
			
		||||
description: Build data-intensive mobile apps with Lynx. Seamlessly integrate spreadsheets into your app using SheetJS. Securely process and generate Excel files in the field.
 | 
			
		||||
pagination_prev: demos/static/index
 | 
			
		||||
pagination_next: demos/desktop/index
 | 
			
		||||
sidebar_position: 7
 | 
			
		||||
sidebar_custom_props:
 | 
			
		||||
  summary: Lynx + Native Rendering
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
import current from '/version.js';
 | 
			
		||||
import Tabs from '@theme/Tabs';
 | 
			
		||||
import TabItem from '@theme/TabItem';
 | 
			
		||||
import CodeBlock from '@theme/CodeBlock';
 | 
			
		||||
 | 
			
		||||
export const r = {style: {color:"red"}};
 | 
			
		||||
export const g = {style: {color:"green"}};
 | 
			
		||||
export const y = {style: {color:"gold"}};
 | 
			
		||||
export const gr = {style: {color:"gray"}};
 | 
			
		||||
 | 
			
		||||
[Lynx](https://lynxjs.org/) is a modern cross-platform framework. It builds iOS, Android
 | 
			
		||||
and Web apps that use JavaScript for describing layouts and events.
 | 
			
		||||
 | 
			
		||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
 | 
			
		||||
data from spreadsheets.
 | 
			
		||||
 | 
			
		||||
:::caution Lynx support is considered experimental.
 | 
			
		||||
 | 
			
		||||
Lynx is a great, fast, open-source alternative to React Native. Any issues should be reported to the Lynx project for
 | 
			
		||||
further diagnosis.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
This demo uses [ReactLynx](https://lynxjs.org/react) and SheetJS to process and generate
 | 
			
		||||
spreadsheets. We'll explore how to load SheetJS in ReactLynx app in a few ways:
 | 
			
		||||
 | 
			
		||||
- ["Fetching Remote Data"](#fetching-remote-data) uses the built-in `fetch` to download
 | 
			
		||||
and parse remote workbook files.
 | 
			
		||||
 | 
			
		||||
The "Fetching Remote Data" example creates an app that looks like the screenshots below:
 | 
			
		||||
 | 
			
		||||
<table><thead><tr>
 | 
			
		||||
    <th><a href="#demo">iOS</a></th>
 | 
			
		||||
    <th><a href="#demo">Android</a></th>
 | 
			
		||||
</tr></thead><tbody><tr><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
:::caution pass
 | 
			
		||||
**Before testing this demo, follow the official React Lynx Guide!**[^1]
 | 
			
		||||
 | 
			
		||||
Follow the instructions for iOS (requires macOS) and for Android. They will
 | 
			
		||||
cover installation and system configuration. You should be able to build and run
 | 
			
		||||
a sample app in the Android and the iOS (if applicable) simulators.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Integration Detail
 | 
			
		||||
 | 
			
		||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
 | 
			
		||||
imported from any component or script in the app.
 | 
			
		||||
 | 
			
		||||
### Internal State
 | 
			
		||||
 | 
			
		||||
For simplicity, this demo uses an "Array of Arrays"[^2] as the internal state.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<table>
 | 
			
		||||
  <thead><tr><th>Spreadsheet</th><th>Array of Arrays</th></tr></thead>
 | 
			
		||||
  <tbody><tr><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
[
 | 
			
		||||
  ["Name", "Index"],
 | 
			
		||||
  ["Bill Clinton", 42],
 | 
			
		||||
  ["GeorgeW Bush", 43],
 | 
			
		||||
  ["Barack Obama", 44],
 | 
			
		||||
  ["Donald Trump", 45],
 | 
			
		||||
  ["Joseph Biden", 46]
 | 
			
		||||
]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
Each array represents a row in the table.
 | 
			
		||||
 | 
			
		||||
This demo also keeps track of the column widths as a single array of numbers.
 | 
			
		||||
The widths are used by the display component.
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
const [data, setData] = useState<any[]>([
 | 
			
		||||
    "SheetJS".split(""),
 | 
			
		||||
    [5, 4, 3, 3, 7, 9, 5],
 | 
			
		||||
    [8, 6, 7, 5, 3, 0, 9]
 | 
			
		||||
  ]);
 | 
			
		||||
const [widths, setWidths] = useState<number[]>(Array.from({ length: 7 }, () => 20));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Updating State
 | 
			
		||||
 | 
			
		||||
Starting from a SheetJS worksheet object, `sheet_to_json`[^3] with the `header`
 | 
			
		||||
option can generate an array of arrays:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* assuming `wb` is a SheetJS workbook */
 | 
			
		||||
function update_state(wb) {
 | 
			
		||||
  /* convert first worksheet to AOA */
 | 
			
		||||
  const wsname = wb.SheetNames[0];
 | 
			
		||||
  const ws = wb.Sheets[wsname];
 | 
			
		||||
  const data = utils.sheet_to_json(ws, {header:1});
 | 
			
		||||
 | 
			
		||||
  /* update state */
 | 
			
		||||
  setData(data);
 | 
			
		||||
 | 
			
		||||
  /* update column widths */
 | 
			
		||||
  setWidths(make_width(data));
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
_Calculating Column Widths_
 | 
			
		||||
 | 
			
		||||
Column widths can be calculated by walking each column and calculating the max
 | 
			
		||||
data width. Using the array of arrays:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* this function takes an array of arrays and generates widths */
 | 
			
		||||
function make_width(aoa) {
 | 
			
		||||
  /* walk each row */
 | 
			
		||||
  aoa.forEach((r) => {
 | 
			
		||||
    /* walk each column */
 | 
			
		||||
    r.forEach((c, C) => {
 | 
			
		||||
      /* update column width based on the length of the cell contents */
 | 
			
		||||
      res[C] = Math.max(res[C]||60, String(c).length * 10);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
  /* use a default value for columns with no data */
 | 
			
		||||
  for(let C = 0; C < res.length; ++C) if(!res[C]) res[C] = 60;
 | 
			
		||||
  return res;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Displaying Data
 | 
			
		||||
 | 
			
		||||
The demo uses Lynx builtin element `<view/>` and `<text/>` to display the first worksheet.
 | 
			
		||||
 | 
			
		||||
The demo uses components similar to the example below:
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
{/* Table container */}
 | 
			
		||||
<view className='Table'>
 | 
			
		||||
    {/* Map through each row in the data array */}
 | 
			
		||||
    {data.map((row, rowIndex) => (
 | 
			
		||||
      <view key={`row-${rowIndex}`} className="Row">
 | 
			
		||||
        {/* Map through each cell in the current row */}
 | 
			
		||||
        {Array.isArray(row) && row.map((cell, cellIndex) => (
 | 
			
		||||
          {/* Cell with dynamic width based on content */}
 | 
			
		||||
          <view 
 | 
			
		||||
            key={`cell-${rowIndex}-${cellIndex}`}  className="Cell"
 | 
			
		||||
            style={{ width: `${widths[cellIndex]}px` }}>
 | 
			
		||||
            {/* Display cell content as text */}
 | 
			
		||||
            <text>{String(cell)}</text>
 | 
			
		||||
          </view>
 | 
			
		||||
        ))}
 | 
			
		||||
      </view>
 | 
			
		||||
    ))}
 | 
			
		||||
</view>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Fetching Remote Data
 | 
			
		||||
 | 
			
		||||
This snippet downloads and parses https://docs.sheetjs.com/pres.xlsx:
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
/* fetch data into an ArrayBuffer */
 | 
			
		||||
const ab = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer();
 | 
			
		||||
/* parse data */
 | 
			
		||||
const wb = XLSX.read(ab);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `data.map()` approach allows direct rendering of the worksheet data in a tabular format, with each cell
 | 
			
		||||
width dynamically calculated based on content.
 | 
			
		||||
 | 
			
		||||
### Fetch Demo
 | 
			
		||||
 | 
			
		||||
:::note Tested Deployments
 | 
			
		||||
 | 
			
		||||
This demo was tested in the following environments:
 | 
			
		||||
 | 
			
		||||
**Simulators**
 | 
			
		||||
 | 
			
		||||
| OS         | Device              | Lynx     | LynxExplorer | Dev Platform | Date       |
 | 
			
		||||
|:-----------|:--------------------|:---------|:-------------|:-------------|:-----------|
 | 
			
		||||
| Android 35 | Pixel 3a            | `0.8.3`  | `3.2.0-rc.0` | `darwin-arm` | 2025-03-11 |
 | 
			
		||||
| iOS 18.3   | iPhone 16 Pro       | `0.8.3`  | `3.2.0-rc.0` | `darwin-arm` | 2025-03-11 |
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::danger Real Devices
 | 
			
		||||
 | 
			
		||||
As of `2025-03-11`, there is no simple, standalone guide on how to build your Lynx app for real devices.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
First install Lynx by following the Guide![^1]. Make sure you can run a basic test app on your
 | 
			
		||||
simulator before continuing!
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
0) Install Lynx dependencies
 | 
			
		||||
 | 
			
		||||
1) Create project:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
pnpm create rspeedy@0.8.3 -d SheetJSLynxFetch -t react-ts --tools biome
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install shared dependencies:
 | 
			
		||||
 | 
			
		||||
<CodeBlock language="bash">{`\
 | 
			
		||||
cd SheetJSLynxFetch
 | 
			
		||||
curl -o ./src/assets/SheetJS-logo.png https://docs.sheetjs.com/logo.png
 | 
			
		||||
pnpm install
 | 
			
		||||
pnpm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
3) Download [`App.tsx`](pathname:///lynx/App.tsx) and replace:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -o ./src/App.tsx https://docs.sheetjs.com/lynx/App.tsx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
4) Download [`App.css`](pathname://lynx/App.css) and replace:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -o ./src/App.css https://docs.sheetjs.com/lynx/App.css
 | 
			
		||||
```
 | 
			
		||||
<a id="step5"></a>
 | 
			
		||||
5) Start the development server, run:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
pnpm run dev
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
6) Start the Android emulator:
 | 
			
		||||
 | 
			
		||||
<details open>
 | 
			
		||||
  <summary><b>Details</b> (click to hide)</summary>
 | 
			
		||||
 | 
			
		||||
**Android Studio**
 | 
			
		||||
 | 
			
		||||
In Android Studio, click "More actions" > "Virtual Device Manager". Look for the
 | 
			
		||||
emulated device in the list and click the ▶ button to play.
 | 
			
		||||
 | 
			
		||||
**Command Line**
 | 
			
		||||
List the available emulators with `emulator -list-avds`
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
shjs@sheetjs SheetJSLynxFetch % emulator -list-avds
 | 
			
		||||
Medium_Phone_API_35
 | 
			
		||||
^^^^^^^^^^^^^^^^^^^--- emulator name
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Emulator name should be passed to `emulator -avd`. In a previous test, the name was
 | 
			
		||||
`Medium_Phone_API_35` and the launch command was:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
emulator -avd Medium_Phone_API_35
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
On macOS, `~/Library/Android/sdk/emulator/` is the typical location
 | 
			
		||||
for the `emulator` binary. If it cannot be found, add the folder to `PATH`:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
export PATH="$PATH":~/Library/Android/sdk/emulator
 | 
			
		||||
emulator -avd Medium_Phone_API_35
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
7) While the Android emulator is open, download LynxExplorer[^4] - (Is a sandbox for trying out Lynx quickly)
 | 
			
		||||
 | 
			
		||||
<Tabs groupId="lang">
 | 
			
		||||
  <TabItem name="Android" value="Android">
 | 
			
		||||
   1. Download the pre-build app from the [GitHub Release](https://github.com/lynx-family/lynx/releases/tag/3.2.0-rc.0) and
 | 
			
		||||
   select the APK `LynxExplorer-noasan-release.apk`.
 | 
			
		||||
   2. Drag and drop the APK `LynxExplorer-noasan-release.apk` in to your Android simulator.
 | 
			
		||||
  </TabItem>
 | 
			
		||||
</Tabs>
 | 
			
		||||
 | 
			
		||||
--- 
 | 
			
		||||
8) From [step 5](#step5), you will see a QR code appear in the terminal with a hyperlink like this. Copy the HTTP link.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
9) In the simulator, open the _LynxExplorer_ app. In the input field labeled **Enter Card URL**, paste the link and
 | 
			
		||||
click **Go**.
 | 
			
		||||
 | 
			
		||||
10) When opened, the app should look like the "Before" screenshot below. After tapping "Import data from a spreadsheet",
 | 
			
		||||
verify that the app shows new data:
 | 
			
		||||
 | 
			
		||||
<table><thead><tr>
 | 
			
		||||
  <th>Before</th>
 | 
			
		||||
  <th>After</th>
 | 
			
		||||
</tr></thead><tbody><tr><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**iOS Testing**
 | 
			
		||||
 | 
			
		||||
:::danger pass
 | 
			
		||||
 | 
			
		||||
**iOS testing can only be performed on Apple hardware running macOS!**
 | 
			
		||||
 | 
			
		||||
Xcode and iOS simulators are not available on Windows or Linux.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
<Tabs groupId="lang">
 | 
			
		||||
<TabItem name="iOS Simulator" value="iOS Simulator">
 | 
			
		||||
   1. Install Xcode open up the Mac App Store, search for [Xcode](https://apps.apple.com/us/app/xcode/id497799835), and
 | 
			
		||||
   click Install (or Update if you have it already).
 | 
			
		||||
   2. Download [`LynxExplorer-arm64.app.tar.gz`](https://github.com/lynx-family/lynx/releases/latest/download/LynxExplorer-arm64.app.tar.gz).
 | 
			
		||||
   3. Then, extract the downloaded archive:
 | 
			
		||||
 | 
			
		||||
    ```bash
 | 
			
		||||
    mkdir -p LynxExplorer-arm64.app/
 | 
			
		||||
    tar -zxf LynxExplorer-arm64.app.tar.gz -C LynxExplorer-arm64.app/
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
    4. Install LynxExplorer[^4] on simulator open Xcode, and choose Open Developer Tool from the Xcode menu. Click the
 | 
			
		||||
    Simulator to launch one. Drag "LynxExplorer-arm64.app" into it.
 | 
			
		||||
 | 
			
		||||
  </TabItem>
 | 
			
		||||
</Tabs>
 | 
			
		||||
 | 
			
		||||
11) From [step 5](#step5), you will see a QR code appear in the terminal with a hyperlink like this. Copy the HTTP link.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
12) In the simulator, open the _LynxExplorer_ app. In the input field labeled **Enter Card URL**, paste the link and
 | 
			
		||||
   click **Go**.
 | 
			
		||||
 | 
			
		||||
13) When opened, the app should look like the "Before" screenshot below. After tapping "Import data from a spreadsheet",
 | 
			
		||||
    verify that the app shows new data:
 | 
			
		||||
 | 
			
		||||
<table><thead><tr>
 | 
			
		||||
  <th>Before</th>
 | 
			
		||||
  <th>After</th>
 | 
			
		||||
</tr></thead><tbody><tr><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
[^1]: Follow the ["Quick Start guide](https://lynxjs.org/guide/start/quick-start.html) and select the appropriate
 | 
			
		||||
"Lynx Explorer sandbox"
 | 
			
		||||
[^2]: See ["Array of Arrays" in the API reference](/docs/api/utilities/array#array-of-arrays)
 | 
			
		||||
[^3]: See ["Array Output" in "Utility Functions"](/docs/api/utilities/array#array-output)
 | 
			
		||||
[^4]: See ["LynxExplorer sandbox"](https://github.com/lynx-family/lynx/releases/tag/3.2.0-rc.0/)
 | 
			
		||||
							
								
								
									
										62
									
								
								docz/static/lynx/App.css
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										62
									
								
								docz/static/lynx/App.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
:root {
 | 
			
		||||
    background-color: #fff;
 | 
			
		||||
    --color-text: #000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.App {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    min-height: 100vh;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    margin-top: 100px
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
text {
 | 
			
		||||
    color: var(--color-text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Title {
 | 
			
		||||
    font-size: 24px;
 | 
			
		||||
    font-weight: 400;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Button {
 | 
			
		||||
    margin-top: 12px;
 | 
			
		||||
    background-color: #841584;
 | 
			
		||||
    --color-text: #fff;
 | 
			
		||||
    padding: 12px;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Logo {
 | 
			
		||||
    height: 24px;
 | 
			
		||||
    width: 24px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Table {
 | 
			
		||||
    margin-top: 16px;
 | 
			
		||||
    border: 1px solid #000;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Row {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    border-bottom: 1px solid #000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Cell {
 | 
			
		||||
    padding: 8px;
 | 
			
		||||
    border-right: 1px solid #000;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
    min-width: 40px;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								docz/static/lynx/App.tsx
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										69
									
								
								docz/static/lynx/App.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
			
		||||
/* sheetjs (C) SheetJS -- https://sheetjs.com */
 | 
			
		||||
 | 
			
		||||
import './App.css'
 | 
			
		||||
import { useCallback, useState } from '@lynx-js/react'
 | 
			
		||||
import SheetJSLogo from './assets/SheetJS-logo.png';
 | 
			
		||||
import { read, utils, WorkSheet } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
const make_width = (ws: WorkSheet): number[] => {
 | 
			
		||||
    const aoa = utils.sheet_to_json(ws, { header: 1 }), res: number[] = [];
 | 
			
		||||
    aoa.forEach((r: any) => { r.forEach((c: any, C: any) => { res[C] = Math.max(res[C] || 60, String(c).length * 10); }); });
 | 
			
		||||
    for (let C = 0; C < res.length; ++C) if (!res[C]) res[C] = 60;
 | 
			
		||||
    return res;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function App() {
 | 
			
		||||
    const [data, setData] = useState<any[]>([
 | 
			
		||||
        "SheetJS".split(""),
 | 
			
		||||
        [5, 4, 3, 3, 7, 9, 5],
 | 
			
		||||
        [8, 6, 7, 5, 3, 0, 9]
 | 
			
		||||
    ]);
 | 
			
		||||
    const [widths, setWidths] = useState<number[]>(Array.from({ length: 7 }, () => 20));
 | 
			
		||||
 | 
			
		||||
    const importFile = useCallback(async () => {
 | 
			
		||||
        try {
 | 
			
		||||
            const ab = await (await fetch("https://docs.sheetjs.com/pres.numbers")).arrayBuffer();
 | 
			
		||||
            const wb = read(ab);
 | 
			
		||||
 | 
			
		||||
            /* convert first worksheet to AOA */
 | 
			
		||||
            const wsname = wb.SheetNames[0];
 | 
			
		||||
            const ws = wb.Sheets[wsname];
 | 
			
		||||
            const data = utils.sheet_to_json(ws, { header: 1 });
 | 
			
		||||
            /* update state */
 | 
			
		||||
            setData(data);
 | 
			
		||||
            console.log(data);
 | 
			
		||||
 | 
			
		||||
            setWidths(make_width(ws));
 | 
			
		||||
        } catch (err) {
 | 
			
		||||
            console.log("importFile Error", "Error " + ((err as any).message || err));
 | 
			
		||||
        }
 | 
			
		||||
    }, []);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <view className='App'>
 | 
			
		||||
            <text className="Title">
 | 
			
		||||
                <image className="Logo" src={SheetJSLogo} />   SheetJS × React Lynx
 | 
			
		||||
            </text>
 | 
			
		||||
            <view className="Button" bindtap={importFile}>
 | 
			
		||||
                <text>IMPORT DATA FROM A SPREADSHEET</text>
 | 
			
		||||
            </view>
 | 
			
		||||
            <text style={{ margin: '8px', fontWeight: '600'}}>Current Data</text>
 | 
			
		||||
            <view className='Table'>
 | 
			
		||||
                {data.map((row, rowIndex) => (
 | 
			
		||||
                    <view key={`row-${rowIndex}`} className="Row">
 | 
			
		||||
                        {Array.isArray(row) && row.map((cell, cellIndex) => (
 | 
			
		||||
                            <view
 | 
			
		||||
                                key={`cell-${rowIndex}-${cellIndex}`}
 | 
			
		||||
                                className="Cell"
 | 
			
		||||
                                style={{ width: `${widths[cellIndex]}px` }}
 | 
			
		||||
                            >
 | 
			
		||||
                                <text>{cell}</text>
 | 
			
		||||
                            </view>
 | 
			
		||||
                        ))}
 | 
			
		||||
                    </view>
 | 
			
		||||
                ))}
 | 
			
		||||
            </view>
 | 
			
		||||
            <view style={{ flex: 1 }}></view>
 | 
			
		||||
        </view>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/lynx/lynx_live_server_link.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/lynx/lynx_live_server_link.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 47 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_android_1.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_android_1.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 66 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_android_2.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_android_2.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 84 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_ios_1.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_ios_1.jpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 107 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_ios_2.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/lynx/react_lynx_fetch_demo_ios_2.jpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 132 KiB  | 
		Loading…
	
		Reference in New Issue
	
	Block a user