updates to react demo

- bump react and babel
- converted to functional components

removed preact demo

renamed jsx to js for next make instruction

removed image component
added pod install for pod linking
This commit is contained in:
Taher 2021-03-30 15:28:10 -07:00
parent 333deae63f
commit 58e59dcfd5
7 changed files with 192 additions and 241 deletions

View File

@ -5,7 +5,7 @@ react: init ## Simple server for react and clones
.PHONY: next
next: init ## next.js demo
mkdir -p pages static
cat nexthdr.js sheetjs.jsx > pages/sheetjs.js
cat nexthdr.js sheetjs.js > pages/sheetjs.js
cp ../../shim.js static/shim.js
next
@ -15,7 +15,7 @@ native: ## Build react-native project
.PHONY: ios
ios: native ## react-native ios sim
cd SheetJS; react-native run-ios --simulator="iPhone X"; cd -
cd SheetJS; cd ios; pod install; cd -; react-native run-ios --simulator="iPhone X"; cd -
.PHONY: android
android: native ## react-native android sim

View File

@ -13,19 +13,19 @@ The library can also be imported directly from JSX code with:
import XLSX from 'xlsx';
```
This demo shows a simple JSX component transpiled in the browser using the babel
This demo shows a simple React component transpiled in the browser using the babel
standalone library. Since there is no standard React table model, this demo
settles on the array of arrays approach.
Other scripts in this demo show:
- server-rendered React component (with `next.js`)
- `preact` using the react compatibility library
- `react-native` deployment for iOS and android
## How to run
Run `make react` to run the browser demo for React, or run `make next` to run
the server-rendered demo using `next.js`.
## Internal State
The simplest state representation is an array of arrays. To avoid having the
@ -116,15 +116,6 @@ set in the iOS project `Info.plist` file.
To run the React Native demo, run either `make ios` or `make android` while
connected to a device or emulator.
## Other Demos
#### Preact
`preact-compat` is an easy-to-use compatibility layer that provides equivalents
for `React` and `ReactDOM`. The `preact` demo uses the same JSX component code!
[The docs](https://npm.im/preact-compat#use-without-webpackbrowserify) explain
how to convert the in-browser React demo to Preact.
#### Server-Rendered React Components with Next.js
The demo uses the same component code as the in-browser version, but the build

View File

@ -6,9 +6,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SheetJS React Demo</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="node_modules/xlsx/dist/shim.min.js"></script>
<script src="node_modules/xlsx/dist/xlsx.full.min.js"></script>
<style>body, #app { height: 100%; };</style>
@ -21,18 +21,7 @@
<a href="https://github.com/SheetJS/js-xlsx/issues">Issues? Something look weird? Click here and report an issue</a><br /><br />
</div>
<div id="app" class="container-fluid"></div>
<script type="text/babel" src="sheetjs.jsx"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-36810333-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<script type="text/babel" src="sheetjs.js"></script>
<script type="text/babel">
ReactDOM.render( <SheetJSApp />, document.getElementById('app') );
</script>

View File

@ -1,42 +0,0 @@
<!DOCTYPE html>
<!-- xlsx.js (C) 2013-present SheetJS http://sheetjs.com -->
<!-- vim: set ts=2: -->
<html lang="en" style="height: 100%">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SheetJS Preact Demo</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="//unpkg.com/preact"></script>
<script src="//unpkg.com/proptypes"></script>
<script src="//unpkg.com/preact-compat"></script>
<script>var React = preactCompat, ReactDOM = preactCompat;</script>
<script src="node_modules/xlsx/dist/shim.min.js"></script>
<script src="node_modules/xlsx/dist/xlsx.full.min.js"></script>
<style>body, #app { height: 100%; };</style>
</head>
<body>
<div class="container-fluid">
<h1><a href="http://sheetjs.com">SheetJS Preact Demo</a></h1>
<br />
<a href="https://github.com/SheetJS/js-xlsx">Source Code Repo</a><br />
<a href="https://github.com/SheetJS/js-xlsx/issues">Issues? Something look weird? Click here and report an issue</a><br /><br />
</div>
<div id="app" class="container-fluid"></div>
<script type="text/babel" src="sheetjs.jsx"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-36810333-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<script type="text/babel">
ReactDOM.render( <SheetJSApp />, document.getElementById('app') );
</script>
</body>
</html>

View File

@ -1,8 +1,17 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
import XLSX from 'xlsx';
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View, Button, Alert, Image, ScrollView, TouchableWithoutFeedback } from 'react-native';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button,
Alert,
Image,
ScrollView,
TouchableWithoutFeedback
} from 'react-native';
import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
// react-native-fs
@ -68,34 +77,36 @@ export default class SheetJS extends Component {
Alert.alert("exportFile success", "Exported to " + file);
}).catch((err) => { Alert.alert("exportFile Error", "Error " + err.message); });
};
render() { return (
<ScrollView contentContainerStyle={styles.container} vertical={true}>
<Text style={styles.welcome}> </Text>
<Image style={{width: 128, height: 128}} source={require('./logo.png')} />
<Text style={styles.welcome}>SheetJS React Native Demo</Text>
<Text style={styles.instructions}>Import Data</Text>
<Button onPress={this.importFile} title="Import data from a spreadsheet" color="#841584" />
<Text style={styles.instructions}>Export Data</Text>
<Button disabled={!this.state.data.length} onPress={this.exportFile} title="Export data to XLSX" color="#841584" />
<Text style={styles.instructions}>Current Data</Text>
render() {
return (
<ScrollView contentContainerStyle={styles.container} vertical={true}>
<Text style={styles.welcome}> </Text>
<Text style={styles.welcome}>SheetJS React Native Demo</Text>
<Text style={styles.instructions}>Import Data</Text>
<Button onPress={this.importFile} title="Import data from a spreadsheet" color="#841584" />
<Text style={styles.instructions}>Export Data</Text>
<Button disabled={!this.state.data.length} onPress={this.exportFile} title="Export data to XLSX" color="#841584" />
<ScrollView style={styles.table} horizontal={true} >
<Table style={styles.table}>
<TableWrapper>
<Row data={this.state.cols} style={styles.thead} textStyle={styles.text} widthArr={this.state.widthArr}/>
</TableWrapper>
<TouchableWithoutFeedback>
<ScrollView vertical={true}>
<TableWrapper>
<Rows data={this.state.data} style={styles.tr} textStyle={styles.text} widthArr={this.state.widthArr}/>
</TableWrapper>
<Text style={styles.instructions}>Current Data</Text>
<ScrollView style={styles.table} horizontal={true} >
<Table style={styles.table}>
<TableWrapper>
<Row data={this.state.cols} style={styles.thead} textStyle={styles.text} widthArr={this.state.widthArr}/>
</TableWrapper>
<TouchableWithoutFeedback>
<ScrollView vertical={true}>
<TableWrapper>
<Rows data={this.state.data} style={styles.tr} textStyle={styles.text} widthArr={this.state.widthArr}/>
</TableWrapper>
</ScrollView>
</TouchableWithoutFeedback>
</Table>
</ScrollView>
</TouchableWithoutFeedback>
</Table>
</ScrollView>
</ScrollView>
); };
</ScrollView>
);
};
};
const styles = StyleSheet.create({

145
demos/react/sheetjs.js Normal file
View File

@ -0,0 +1,145 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* Notes:
- usage: `ReactDOM.render( <SheetJSApp />, document.getElementById('app') );`
- xlsx.full.min.js is loaded in the head of the HTML page
- this script should be referenced with type="text/babel"
- babel.js in-browser transpiler should be loaded before this script
*/
function SheetJSApp() {
const [data, setData] = React.useState([]);
const [cols, setCols] = React.useState([]);
const handleFile = (file) => {
const reader = new FileReader();
const rABS = !!reader.readAsBinaryString;
reader.onload = (e) => {
/* Parse data */
const bstr = e.target.result;
const wb = XLSX.read(bstr, {type:rABS ? 'binary' : 'array'});
/* Get first worksheet */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* Convert array of arrays */
const data = XLSX.utils.sheet_to_json(ws, {header:1});
/* Update state */
setData(data);
setCols(make_cols(ws['!ref']))
};
if(rABS) reader.readAsBinaryString(file); else reader.readAsArrayBuffer(file);
}
const exportFile = () => {
/* convert state to workbook */
const ws = XLSX.utils.aoa_to_sheet(data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
/* generate XLSX file and send to client */
XLSX.writeFile(wb, "sheetjs.xlsx")
};
return (
<DragDropFile handleFile={handleFile}>
<div className="row"><div className="col-xs-12">
<DataInput handleFile={handleFile} />
</div></div>
<div className="row"><div className="col-xs-12">
<button disabled={!data.length} className="btn btn-success" onClick={exportFile}>Export</button>
</div></div>
<div className="row"><div className="col-xs-12">
<OutTable data={data} cols={cols} />
</div></div>
</DragDropFile>
);
}
if(typeof module !== 'undefined') module.exports = SheetJSApp
/* -------------------------------------------------------------------------- */
/*
Simple HTML5 file drag-and-drop wrapper
usage: <DragDropFile handleFile={handleFile}>...</DragDropFile>
handleFile(file:File):void;
*/
function DragDropFile({ handleFile, children }) {
const suppress = (e) => { e.stopPropagation(); e.preventDefault(); };
const handleDrop = (e) => { e.stopPropagation(); e.preventDefault();
const files = e.dataTransfer.files;
if(files && files[0]) handleFile(files[0]);
};
return (
<div
onDrop={handleDrop}
onDragEnter={suppress}
onDragOver={suppress}
>
{children}
</div>
);
}
/*
Simple HTML5 file input wrapper
usage: <DataInput handleFile={callback} />
handleFile(file:File):void;
*/
function DataInput({ handleFile }) {
const handleChange = (e) => {
const files = e.target.files;
if(files && files[0]) handleFile(files[0]);
};
return (
<form className="form-inline">
<div className="form-group">
<label htmlFor="file">Drag or choose a spreadsheet file</label>
<br />
<input
type="file"
className="form-control"
id="file"
accept={SheetJSFT}
onChange={handleChange}
/>
</div>
</form>
)
}
/*
Simple HTML Table
usage: <OutTable data={data} cols={cols} />
data:Array<Array<any> >;
cols:Array<{name:string, key:number|string}>;
*/
function OutTable({ data, cols }) {
return (
<div className="table-responsive">
<table className="table table-striped">
<thead>
<tr>{cols.map((c) => <th key={c.key}>{c.name}</th>)}</tr>
</thead>
<tbody>
{data.map((r,i) => <tr key={i}>
{cols.map(c => <td key={c.key}>{ r[c.key] }</td>)}
</tr>)}
</tbody>
</table>
</div>
);
}
/* list of supported file types */
const SheetJSFT = [
"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
].map(x => `.${x}`).join(",");
/* generate an array of column objects */
const make_cols = refstr => {
let o = [], C = XLSX.utils.decode_range(refstr).e.c + 1;
for(var i = 0; i < C; ++i) o[i] = {name:XLSX.utils.encode_col(i), key:i}
return o;
};

View File

@ -1,143 +0,0 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* Notes:
- usage: `ReactDOM.render( <SheetJSApp />, document.getElementById('app') );`
- xlsx.full.min.js is loaded in the head of the HTML page
- this script should be referenced with type="text/babel"
- babel.js in-browser transpiler should be loaded before this script
*/
class SheetJSApp extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [], /* Array of Arrays e.g. [["a","b"],[1,2]] */
cols: [] /* Array of column objects e.g. { name: "C", K: 2 } */
};
this.handleFile = this.handleFile.bind(this);
this.exportFile = this.exportFile.bind(this);
};
handleFile(file/*:File*/) {
/* Boilerplate to set up FileReader */
const reader = new FileReader();
const rABS = !!reader.readAsBinaryString;
reader.onload = (e) => {
/* Parse data */
const bstr = e.target.result;
const wb = XLSX.read(bstr, {type:rABS ? 'binary' : 'array'});
/* Get first worksheet */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* Convert array of arrays */
const data = XLSX.utils.sheet_to_json(ws, {header:1});
/* Update state */
this.setState({ data: data, cols: make_cols(ws['!ref']) });
};
if(rABS) reader.readAsBinaryString(file); else reader.readAsArrayBuffer(file);
};
exportFile() {
/* convert state to workbook */
const ws = XLSX.utils.aoa_to_sheet(this.state.data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
/* generate XLSX file and send to client */
XLSX.writeFile(wb, "sheetjs.xlsx")
};
render() { return (
<DragDropFile handleFile={this.handleFile}>
<div className="row"><div className="col-xs-12">
<DataInput handleFile={this.handleFile} />
</div></div>
<div className="row"><div className="col-xs-12">
<button disabled={!this.state.data.length} className="btn btn-success" onClick={this.exportFile}>Export</button>
</div></div>
<div className="row"><div className="col-xs-12">
<OutTable data={this.state.data} cols={this.state.cols} />
</div></div>
</DragDropFile>
); };
};
if(typeof module !== 'undefined') module.exports = SheetJSApp
/* -------------------------------------------------------------------------- */
/*
Simple HTML5 file drag-and-drop wrapper
usage: <DragDropFile handleFile={handleFile}>...</DragDropFile>
handleFile(file:File):void;
*/
class DragDropFile extends React.Component {
constructor(props) {
super(props);
this.onDrop = this.onDrop.bind(this);
};
suppress(evt) { evt.stopPropagation(); evt.preventDefault(); };
onDrop(evt) { evt.stopPropagation(); evt.preventDefault();
const files = evt.dataTransfer.files;
if(files && files[0]) this.props.handleFile(files[0]);
};
render() { return (
<div onDrop={this.onDrop} onDragEnter={this.suppress} onDragOver={this.suppress}>
{this.props.children}
</div>
); };
};
/*
Simple HTML5 file input wrapper
usage: <DataInput handleFile={callback} />
handleFile(file:File):void;
*/
class DataInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
};
handleChange(e) {
const files = e.target.files;
if(files && files[0]) this.props.handleFile(files[0]);
};
render() { return (
<form className="form-inline">
<div className="form-group">
<label htmlFor="file">Spreadsheet</label>
<input type="file" className="form-control" id="file" accept={SheetJSFT} onChange={this.handleChange} />
</div>
</form>
); };
}
/*
Simple HTML Table
usage: <OutTable data={data} cols={cols} />
data:Array<Array<any> >;
cols:Array<{name:string, key:number|string}>;
*/
class OutTable extends React.Component {
constructor(props) { super(props); };
render() { return (
<div className="table-responsive">
<table className="table table-striped">
<thead>
<tr>{this.props.cols.map((c) => <th key={c.key}>{c.name}</th>)}</tr>
</thead>
<tbody>
{this.props.data.map((r,i) => <tr key={i}>
{this.props.cols.map(c => <td key={c.key}>{ r[c.key] }</td>)}
</tr>)}
</tbody>
</table>
</div>
); };
};
/* list of supported file types */
const SheetJSFT = [
"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
].map(function(x) { return "." + x; }).join(",");
/* generate an array of column objects */
const make_cols = refstr => {
let o = [], C = XLSX.utils.decode_range(refstr).e.c + 1;
for(var i = 0; i < C; ++i) o[i] = {name:XLSX.utils.encode_col(i), key:i}
return o;
};