first build
This commit is contained in:
parent
cdb7f2b5ff
commit
f5e7150667
215
LICENSE
215
LICENSE
@ -1,20 +1,201 @@
|
||||
MIT License
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
Copyright (c) 2025 Asadbek Karimov
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
1. Definitions.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (C) 2012-present SheetJS LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
579
README.md
579
README.md
@ -1,24 +1,573 @@
|
||||
# react-native-tabeller
|
||||
<h1 align="center">React Native Tabeller</h1>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/react-native-reanimated-table"><img src="https://img.shields.io/badge/platform-Android%20%7C%20iOS-yellow.svg" /></a>
|
||||
</p>
|
||||
|
||||
This is a table component for react native.
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Examples](#examples)
|
||||
- [Properties](#properties)
|
||||
- [Notice](#notice)
|
||||
- [License](#license)
|
||||
|
||||
React Native table with reanimated and gestures.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install react-native-tabeller
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
```js
|
||||
import { multiply } from 'react-native-tabeller';
|
||||
|
||||
// ...
|
||||
|
||||
const result = await multiply(3, 7);
|
||||
```tsx
|
||||
import { Table, TableWrapper, Row, Rows, Col, Cols, Cell } from 'react-native-tabeller';
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Table
|
||||
<img src="./assets/tabeller_basic_table.png" width="340"/>
|
||||
|
||||
```tsx
|
||||
import { Table, Row, Rows } from 'react-native-tabeller';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
|
||||
export const BasicExample = () => {
|
||||
const tableHead: string[] = ['Name', 'Index'];
|
||||
const tableData: string[][] = [
|
||||
['Bill Clinton', '42'],
|
||||
['GeorgeW Bush', '43'],
|
||||
['Barack Obama', '44'],
|
||||
['Donald Trump', '45'],
|
||||
['Joseph Biden', '46']
|
||||
];
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderWidth: 1 }}>
|
||||
<Row
|
||||
data={tableHead}
|
||||
style={styles.head}
|
||||
textStyle={styles.headText}
|
||||
/>
|
||||
<Rows
|
||||
data={tableData}
|
||||
textStyle={styles.text}
|
||||
/>
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
head: {
|
||||
height: 44,
|
||||
backgroundColor: '#C6F3E0'
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
padding: 5
|
||||
},
|
||||
headText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Scrollable Example
|
||||
<img src="./assets/tabeller_scrollable_table.webp" width="340"/>
|
||||
|
||||
```tsx
|
||||
import { Table, Row, Rows } from 'react-native-tabeller';
|
||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
||||
|
||||
export const ScrollableExample = () => {
|
||||
const tableHead = ['Head', 'Head2', 'Head3', 'Head4', 'Head5', 'Head6', 'Head7', 'Head8'];
|
||||
const widthArr = [40, 69, 80, 100, 120, 140, 160, 180];
|
||||
|
||||
// generate a large table data
|
||||
const tableData = [];
|
||||
for (let i = 0; i < 30; i += 1) {
|
||||
const rowData = [];
|
||||
for (let j = 0; j < 8; j += 1) {
|
||||
rowData.push(`${i}${j}`);
|
||||
}
|
||||
tableData.push(rowData);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView horizontal={true}>
|
||||
<View>
|
||||
<Table borderStyle={{ borderWidth: 2, borderColor: '#00000' }}>
|
||||
<Row
|
||||
data={tableHead}
|
||||
widthArr={widthArr}
|
||||
style={styles.header}
|
||||
textStyle={styles.headerText}
|
||||
/>
|
||||
</Table>
|
||||
<ScrollView style={styles.dataWrapper}>
|
||||
<Table borderStyle={{ borderWidth: 1, borderColor: '#00000' }}>
|
||||
<Rows
|
||||
data={tableData}
|
||||
widthArr={widthArr}
|
||||
style={styles.row}
|
||||
textStyle={styles.text}
|
||||
/>
|
||||
</Table>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
height: 400,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
header: {
|
||||
height: 50,
|
||||
backgroundColor: '#C6F3E0'
|
||||
},
|
||||
headerText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
padding: 5
|
||||
},
|
||||
dataWrapper: {
|
||||
marginTop: -1
|
||||
},
|
||||
row: {
|
||||
height: 40,
|
||||
backgroundColor: '#fff'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Example three
|
||||
<img src="./assets/tabeller_example_three.webp" width="340"/>
|
||||
|
||||
```tsx
|
||||
import { Table, TableWrapper, Row, Rows, Col } from 'react-native-tabeller';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
|
||||
export const ExampleThree = () => {
|
||||
const tableHead = ['', 'Head1', 'Head2', 'Head3'];
|
||||
const tableTitle = ['Title1', 'Title2', 'Title3'];
|
||||
const tableData = [
|
||||
['a', 'b', 'c'],
|
||||
['d', 'e', 'f'],
|
||||
['g', 'h', 'i']
|
||||
];
|
||||
|
||||
const onCellPress = (data: any) => {
|
||||
console.log(`Cell pressed: ${data}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderWidth: 1 }}>
|
||||
<Row
|
||||
data={tableHead}
|
||||
style={styles.head}
|
||||
textStyle={styles.headText}
|
||||
/>
|
||||
<TableWrapper style={styles.wrapper}>
|
||||
<Col
|
||||
data={tableTitle}
|
||||
style={styles.title}
|
||||
heightArr={[28, 28, 28]}
|
||||
textStyle={styles.titleText}
|
||||
/>
|
||||
<Rows
|
||||
data={tableData}
|
||||
flexArr={[1, 1, 1]}
|
||||
style={styles.row}
|
||||
textStyle={styles.text}
|
||||
onPress={onCellPress}
|
||||
/>
|
||||
</TableWrapper>
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
head: {
|
||||
height: 44,
|
||||
backgroundColor: '#C6F3E0'
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
padding: 5
|
||||
},
|
||||
headText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
row: {
|
||||
height: 40,
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
wrapper: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
title: {
|
||||
flex: 1,
|
||||
backgroundColor: '#C6F3E0'
|
||||
},
|
||||
titleText: {
|
||||
textAlign: 'left',
|
||||
marginLeft: 6,
|
||||
fontWeight: '600'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Example Four
|
||||
<img src="./assets/tabeller_example_four.webp" width="340"/>
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { StyleSheet, View, Text, TouchableOpacity, Alert } from 'react-native';
|
||||
import { Table, TableWrapper, Row, Cell } from 'react-native-tabeller';
|
||||
|
||||
type TableDataType = string[][];
|
||||
|
||||
export const ExampleFour: React.FC = () => {
|
||||
const [tableHead] = useState<string[]>(['Head', 'Head2', 'Head3', 'Head4']);
|
||||
const [tableData] = useState<TableDataType>([
|
||||
['1', '2', '3', '4'],
|
||||
['a', 'b', 'c', 'd'],
|
||||
['1', '2', '3', '4'],
|
||||
['a', 'b', 'c', 'd']
|
||||
]);
|
||||
|
||||
const alertIndex = (index: number): void => {
|
||||
Alert.alert(`This is row ${index + 1}`);
|
||||
};
|
||||
|
||||
const element = (data: any, index: number): React.ReactElement => (
|
||||
<TouchableOpacity onPress={() => alertIndex(index)}>
|
||||
<View style={styles.btn}>
|
||||
<Text style={styles.btnText}>button</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderColor: 'transparent' }}>
|
||||
<Row data={tableHead} style={styles.head} textStyle={styles.text} />
|
||||
{
|
||||
tableData.map((rowData, index) => (
|
||||
<TableWrapper key={index} style={styles.row}>
|
||||
{
|
||||
rowData.map((cellData, cellIndex) => (
|
||||
<Cell
|
||||
key={cellIndex}
|
||||
data={cellIndex === 3 ? element(cellData, index) : cellData}
|
||||
textStyle={styles.text}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</TableWrapper>
|
||||
))
|
||||
}
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
|
||||
head: { height: 40, backgroundColor: '#C6F3E0' },
|
||||
text: { margin: 8 },
|
||||
row: { flexDirection: 'row', backgroundColor: '#FFF1C1' },
|
||||
btn: { width: 58, height: 18, backgroundColor: '#78B7BB', borderRadius: 2 },
|
||||
btnText: { textAlign: 'center', color: '#fff' }
|
||||
});
|
||||
|
||||
export default ExampleFour;
|
||||
```
|
||||
|
||||
### Example Five
|
||||
<img src="./assets/tabeller_example_five.png" width="340"/>
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { StyleSheet, View, Text, TouchableOpacity, Alert } from 'react-native';
|
||||
import { Table, TableWrapper, Row, Col, Rows } from 'react-native-tabeller';
|
||||
|
||||
export const ExampleFive: React.FC = () => {
|
||||
const alertIndex = (value: string): void => {
|
||||
Alert.alert(`This is column ${value}`);
|
||||
};
|
||||
|
||||
const elementButton = (value: string): React.ReactElement => (
|
||||
<TouchableOpacity onPress={() => alertIndex(value)}>
|
||||
<View style={styles.btn}>
|
||||
<Text style={styles.btnText}>button</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
const [tableHead] = useState<any[]>(['', elementButton('1'), elementButton('2'), elementButton('3')]);
|
||||
const [sideHead] = useState<string[]>(['H1', 'H2']);
|
||||
const [rowTitles] = useState<string[]>(['Title', 'Title2', 'Title3', 'Title4']);
|
||||
|
||||
// Table data - matching the structure in the screenshot
|
||||
const [tableData] = useState<string[][]>([
|
||||
['a', '1', 'a'],
|
||||
['b', '2', 'b'],
|
||||
['c', '3', 'c'],
|
||||
['d', '4', 'd']
|
||||
]);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderWidth: 1, borderColor: '#C1C0B9' }}>
|
||||
{/* table header row with buttons */}
|
||||
<Row
|
||||
data={tableHead}
|
||||
style={styles.header}
|
||||
textStyle={styles.headerText}
|
||||
flexArr={[1, 1, 1, 1]}
|
||||
/>
|
||||
|
||||
<TableWrapper style={styles.wrapper}>
|
||||
{/* left column with H1, H2 */}
|
||||
<Col
|
||||
data={sideHead}
|
||||
style={styles.sideHeader}
|
||||
heightArr={[60, 60]}
|
||||
textStyle={styles.sideHeaderText}
|
||||
/>
|
||||
|
||||
<TableWrapper style={styles.tableContentWrapper}>
|
||||
{/* row titles column */}
|
||||
<Col
|
||||
data={rowTitles}
|
||||
style={styles.title}
|
||||
heightArr={[30, 30, 30, 30]}
|
||||
textStyle={styles.titleText}
|
||||
/>
|
||||
|
||||
{/* content cells */}
|
||||
<Rows
|
||||
data={tableData}
|
||||
style={styles.row}
|
||||
flexArr={[1, 1, 1]}
|
||||
textStyle={styles.text}
|
||||
/>
|
||||
</TableWrapper>
|
||||
</TableWrapper>
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
header: {
|
||||
height: 40,
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
headerText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: '500'
|
||||
},
|
||||
wrapper: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
sideHeader: {
|
||||
width: 60,
|
||||
backgroundColor: '#C6F3E0'
|
||||
},
|
||||
sideHeaderText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: '500'
|
||||
},
|
||||
tableContentWrapper: {
|
||||
flex: 1,
|
||||
flexDirection: 'row'
|
||||
},
|
||||
title: {
|
||||
width: 80,
|
||||
backgroundColor: '#f6f8fa'
|
||||
},
|
||||
titleText: {
|
||||
textAlign: 'left',
|
||||
paddingLeft: 5
|
||||
},
|
||||
row: {
|
||||
height: 30
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center'
|
||||
},
|
||||
btn: {
|
||||
width: 58,
|
||||
height: 18,
|
||||
backgroundColor: '#c8e1ff',
|
||||
borderRadius: 2,
|
||||
alignSelf: 'center'
|
||||
},
|
||||
btnText: {
|
||||
textAlign: 'center',
|
||||
fontSize: 12
|
||||
}
|
||||
});
|
||||
|
||||
export default ExampleFive;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<br/><br/>
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
### `Table` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **style** | Style | Container style for the table | `null` |
|
||||
| **borderStyle** | Object | Table border line width and color | `{ borderWidth: 0, borderColor: '#000' }` |
|
||||
| **children** | ReactNode | Table content | Required |
|
||||
|
||||
### `TableWrapper` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **style** | Style | Container style | `null` |
|
||||
| **borderStyle** | Object | Table border line width and color | `{ borderWidth: 0, borderColor: '#000' }` |
|
||||
| **children** | ReactNode | TableWrapper content | Required |
|
||||
|
||||
### `Cell` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **data** | string \| number \| null | Cell content | `null` |
|
||||
| **width** | number | Cell width in pixels | `null` |
|
||||
| **height** | number | Cell height in pixels | `null` |
|
||||
| **flex** | number | Flex value for the cell | `1` (if no width, height, or style) |
|
||||
| **style** | Style | Container style | `null` |
|
||||
| **textStyle** | Style | Text style for cell content | `null` |
|
||||
| **borderStyle** | Object | Cell border line width and color | `{ borderWidth: 0, borderColor: '#000' }` |
|
||||
| **cellContainerProps** | ViewProps | Props passed to the cell container | `{}` |
|
||||
| **onPress** | Function | Callback when cell is pressed | `null` |
|
||||
| **children** | ReactNode | Children to render inside the cell | `null` |
|
||||
|
||||
### `Row` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **data** | Array<string \| number \| null> | Array of data items for each cell in the row | Required |
|
||||
| **style** | Style | Container style | `null` |
|
||||
| **widthArr** | number[] | Array of widths for each cell | `[]` |
|
||||
| **height** | number | Height for the entire row | `null` |
|
||||
| **flexArr** | number[] | Array of flex values for each cell in the row | `[]` |
|
||||
| **textStyle** | Style | Text style applied to all cells in the row | `null` |
|
||||
| **borderStyle** | Object | Border line width and color | `{ borderWidth: 0, borderColor: '#000' }` |
|
||||
| **cellTextStyle** | Function | Function to generate custom text styles for individual cells | `null` |
|
||||
| **onPress** | Function | Callback when a cell is pressed | `null` |
|
||||
|
||||
### `Rows` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **data** | Array<Array<string \| number \| null>> | 2D array of data for rows and cells | Required |
|
||||
| **style** | Style | Container style | `null` |
|
||||
| **widthArr** | number[] | Array of widths for each column | `[]` |
|
||||
| **heightArr** | number[] | Array of heights for each row | `[]` |
|
||||
| **flexArr** | number[] | Array of flex values for each column | `[]` |
|
||||
| **textStyle** | Style | Text style applied to all cells | `null` |
|
||||
| **borderStyle** | Object | Border line width and color | `{ borderWidth: 0, borderColor: '#000' }` |
|
||||
| **onPress** | Function | Callback when a cell is pressed | `null` |
|
||||
|
||||
### `Col` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **data** | Array<string \| number \| null> | Array of data items for each cell in the column | Required |
|
||||
| **style** | Style | Container style | `null` |
|
||||
| **width** | number | Width for the entire column | `null` |
|
||||
| **heightArr** | number[] | Array of heights for each cell | `[]` |
|
||||
| **flex** | number | Flex value for the column | `null` |
|
||||
| **textStyle** | Style | Text style applied to all cells in the column | `null` |
|
||||
| **borderStyle** | Object | Border line width and color | `{ borderWidth: 0, borderColor: '#000' }` |
|
||||
|
||||
### `Cols` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **data** | Array<Array<string \| number \| null>> | 2D array of data for columns and cells | Required |
|
||||
| **style** | Style | Container style | `null` |
|
||||
| **widthArr** | number[] | Array of widths for each column | `[]` |
|
||||
| **heightArr** | number[] | Array of heights for each cell in a column | `[]` |
|
||||
| **flexArr** | number[] | Array of flex values for each column | `[]` |
|
||||
| **textStyle** | Style | Text style applied to all cells | `null` |
|
||||
| **borderStyle** | Object | Border line width and color | `{ borderWidth: 0, borderColor: '#000' }` |
|
||||
|
||||
### `StickyTable` Component Properties
|
||||
|
||||
| Prop | Type | Description | Default |
|
||||
|---|---|---|---|
|
||||
| **data** | Array<Array<string \| number \| null>> | Full table data including first column | Required |
|
||||
| **stickyColumnWidth** | number | Width of the sticky column | Required |
|
||||
| **columnWidths** | number[] | Widths for non-sticky columns | `[]` |
|
||||
| **style** | Style | Style for the container | `null` |
|
||||
| **cellStyle** | Style | Style for cells | `null` |
|
||||
| **textStyle** | Style | Text style for cell content | `null` |
|
||||
| **headerStyle** | Style | Style for header row | `null` |
|
||||
| **headerTextStyle** | Style | Text style for header cells | `null` |
|
||||
| **borderStyle** | Object | Border style | `{ borderWidth: 1, borderColor: '#000' }` |
|
||||
---
|
||||
|
||||
|
||||
|
||||
<br/><br/>
|
||||
|
||||
## Notice
|
||||
+ `Col` and `Cols` components do not support automatic height adjustment
|
||||
+ Use the `textStyle` property to set margins - avoid using padding
|
||||
+ If the parent element is Not `Table` component, specify the `borderStyle`
|
||||
|
||||
```tsx
|
||||
<ScrollView horizontal={true}>
|
||||
{/* add borderStyle if the parent is not a Table component */}
|
||||
<TableWrapper borderStyle={{ borderWidth: 2, borderColor: 'green' }}>
|
||||
<Cols data={data} />
|
||||
</TableWrapper>
|
||||
</ScrollView>
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
@ -26,8 +575,4 @@ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
---
|
||||
|
||||
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
||||
Apache License, Version 2.0 [(ALv2)](LICENSE)
|
||||
|
@ -1,20 +1,78 @@
|
||||
import { multiply } from 'react-native-tabeller';
|
||||
import { Text, View, StyleSheet } from 'react-native';
|
||||
|
||||
const result = multiply(3, 7);
|
||||
import { Text, View, StyleSheet, ScrollView } from 'react-native';
|
||||
import { BasicExample } from './BasicExample';
|
||||
import { ScrollableExample } from './ScrollableExample';
|
||||
import { ExampleThree } from './ExampleThree';
|
||||
import { StickyTableExample } from './StickyColumnExample';
|
||||
import { ExampleFour } from './ExampleFour';
|
||||
import { ExampleFive } from './ExampleFive';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>Result: {result}</Text>
|
||||
</View>
|
||||
<ScrollView contentContainerStyle={styles.container}>
|
||||
<Text style={styles.heading}>React Native Tabeller</Text>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.subheading}>Basic Table</Text>
|
||||
<BasicExample />
|
||||
</View>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.subheading}>Scrollable Table</Text>
|
||||
<ScrollableExample />
|
||||
</View>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.subheading}>
|
||||
Scrollable Sticky 1st Column Table
|
||||
</Text>
|
||||
<StickyTableExample />
|
||||
</View>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.subheading}>Example Three</Text>
|
||||
<ExampleThree />
|
||||
</View>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.subheading}>Example Four</Text>
|
||||
<ExampleFour />
|
||||
</View>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.subheading}>Example Five</Text>
|
||||
<ExampleFive />
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexGrow: 1,
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 60,
|
||||
backgroundColor: '#f5f5f5',
|
||||
},
|
||||
heading: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
marginBottom: 20,
|
||||
},
|
||||
section: {
|
||||
marginBottom: 30,
|
||||
padding: 15,
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 4,
|
||||
elevation: 3,
|
||||
},
|
||||
subheading: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
marginBottom: 10,
|
||||
},
|
||||
});
|
||||
|
42
example/src/BasicExample.tsx
Normal file
42
example/src/BasicExample.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { Table, Row, Rows } from 'react-native-tabeller';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
|
||||
export const BasicExample = () => {
|
||||
const tableHead: string[] = ['Name', 'Index'];
|
||||
const tableData: string[][] = [
|
||||
['Bill Clinton', '42'],
|
||||
['GeorgeW Bush', '43'],
|
||||
['Barack Obama', '44'],
|
||||
['Donald Trump', '45'],
|
||||
['Joseph Biden', '46'],
|
||||
];
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderWidth: 1 }}>
|
||||
<Row data={tableHead} style={styles.head} textStyle={styles.headText} />
|
||||
<Rows data={tableData} textStyle={styles.text} />
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
head: {
|
||||
height: 44,
|
||||
backgroundColor: '#C6F3E0',
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
padding: 5,
|
||||
},
|
||||
headText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
136
example/src/ExampleFive.tsx
Normal file
136
example/src/ExampleFive.tsx
Normal file
@ -0,0 +1,136 @@
|
||||
import React, { useState } from 'react';
|
||||
import { StyleSheet, View, Text, TouchableOpacity, Alert } from 'react-native';
|
||||
import { Table, TableWrapper, Row, Col, Rows } from 'react-native-tabeller';
|
||||
|
||||
export const ExampleFive: React.FC = () => {
|
||||
const alertIndex = (value: string): void => {
|
||||
Alert.alert(`This is column ${value}`);
|
||||
};
|
||||
const elementButton = (value: string): React.ReactElement => (
|
||||
<TouchableOpacity onPress={() => alertIndex(value)}>
|
||||
<View style={styles.btn}>
|
||||
<Text style={styles.btnText}>button</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
const [tableHead] = useState<any[]>([
|
||||
'',
|
||||
elementButton('1'),
|
||||
elementButton('2'),
|
||||
elementButton('3'),
|
||||
]);
|
||||
const [sideHead] = useState<string[]>(['H1', 'H2']);
|
||||
const [rowTitles] = useState<string[]>([
|
||||
'Title',
|
||||
'Title2',
|
||||
'Title3',
|
||||
'Title4',
|
||||
]);
|
||||
|
||||
// Table data - matching the structure in the screenshot
|
||||
const [tableData] = useState<string[][]>([
|
||||
['a', '1', 'a'],
|
||||
['b', '2', 'b'],
|
||||
['c', '3', 'c'],
|
||||
['d', '4', 'd'],
|
||||
]);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderWidth: 1, borderColor: '#C1C0B9' }}>
|
||||
{/* table header row with buttons */}
|
||||
<Row
|
||||
data={tableHead}
|
||||
style={styles.header}
|
||||
textStyle={styles.headerText}
|
||||
flexArr={[1, 1, 1, 1]}
|
||||
/>
|
||||
<TableWrapper style={styles.wrapper}>
|
||||
{/* left column with H1, H2 */}
|
||||
<Col
|
||||
data={sideHead}
|
||||
style={styles.sideHeader}
|
||||
heightArr={[60, 60]}
|
||||
textStyle={styles.sideHeaderText}
|
||||
/>
|
||||
<TableWrapper style={styles.tableContentWrapper}>
|
||||
{/* row titles column */}
|
||||
<Col
|
||||
data={rowTitles}
|
||||
style={styles.title}
|
||||
heightArr={[30, 30, 30, 30]}
|
||||
textStyle={styles.titleText}
|
||||
/>
|
||||
{/* content cells */}
|
||||
<Rows
|
||||
data={tableData}
|
||||
style={styles.row}
|
||||
flexArr={[1, 1, 1]}
|
||||
textStyle={styles.text}
|
||||
/>
|
||||
</TableWrapper>
|
||||
</TableWrapper>
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
header: {
|
||||
height: 40,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
headerText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: '500',
|
||||
},
|
||||
wrapper: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
sideHeader: {
|
||||
width: 60,
|
||||
backgroundColor: '#C6F3E0',
|
||||
},
|
||||
sideHeaderText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: '500',
|
||||
},
|
||||
tableContentWrapper: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
title: {
|
||||
width: 80,
|
||||
backgroundColor: '#f6f8fa',
|
||||
},
|
||||
titleText: {
|
||||
textAlign: 'left',
|
||||
paddingLeft: 5,
|
||||
},
|
||||
row: {
|
||||
height: 30,
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
},
|
||||
btn: {
|
||||
width: 58,
|
||||
height: 18,
|
||||
backgroundColor: '#c8e1ff',
|
||||
borderRadius: 2,
|
||||
alignSelf: 'center',
|
||||
},
|
||||
btnText: {
|
||||
textAlign: 'center',
|
||||
fontSize: 12,
|
||||
},
|
||||
});
|
||||
|
||||
export default ExampleFive;
|
57
example/src/ExampleFour.tsx
Normal file
57
example/src/ExampleFour.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import React, { useState } from 'react';
|
||||
import { StyleSheet, View, Text, TouchableOpacity, Alert } from 'react-native';
|
||||
import { Table, TableWrapper, Row, Cell } from 'react-native-tabeller';
|
||||
|
||||
type TableDataType = string[][];
|
||||
|
||||
export const ExampleFour: React.FC = () => {
|
||||
const [tableHead] = useState<string[]>(['Head', 'Head2', 'Head3', 'Head4']);
|
||||
const [tableData] = useState<TableDataType>([
|
||||
['1', '2', '3', '4'],
|
||||
['a', 'b', 'c', 'd'],
|
||||
['1', '2', '3', '4'],
|
||||
['a', 'b', 'c', 'd'],
|
||||
]);
|
||||
|
||||
const alertIndex = (index: number): void => {
|
||||
Alert.alert(`This is row ${index + 1}`);
|
||||
};
|
||||
|
||||
const element = (data: any, index: number): React.ReactElement => (
|
||||
<TouchableOpacity onPress={() => alertIndex(index)}>
|
||||
<View style={styles.btn}>
|
||||
<Text style={styles.btnText}>button</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderColor: 'transparent' }}>
|
||||
<Row data={tableHead} style={styles.head} textStyle={styles.text} />
|
||||
{tableData.map((rowData, index) => (
|
||||
<TableWrapper key={index} style={styles.row}>
|
||||
{rowData.map((cellData, cellIndex) => (
|
||||
<Cell
|
||||
key={cellIndex}
|
||||
data={cellIndex === 3 ? element(cellData, index) : cellData}
|
||||
textStyle={styles.text}
|
||||
/>
|
||||
))}
|
||||
</TableWrapper>
|
||||
))}
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
|
||||
head: { height: 40, backgroundColor: '#C6F3E0' },
|
||||
text: { margin: 8 },
|
||||
row: { flexDirection: 'row', backgroundColor: '#FFF1C1' },
|
||||
btn: { width: 58, height: 18, backgroundColor: '#78B7BB', borderRadius: 2 },
|
||||
btnText: { textAlign: 'center', color: '#fff' },
|
||||
});
|
||||
|
||||
export default ExampleFour;
|
76
example/src/ExampleThree.tsx
Normal file
76
example/src/ExampleThree.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import { Table, TableWrapper, Row, Rows, Col } from 'react-native-tabeller';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
|
||||
export const ExampleThree = () => {
|
||||
const tableHead = ['', 'Head1', 'Head2', 'Head3'];
|
||||
const tableTitle = ['Title1', 'Title2', 'Title3'];
|
||||
const tableData = [
|
||||
['a', 'b', 'c'],
|
||||
['d', 'e', 'f'],
|
||||
['g', 'h', 'i'],
|
||||
];
|
||||
|
||||
const onCellPress = (data: any) => {
|
||||
console.log(`Cell pressed: ${data}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Table borderStyle={{ borderWidth: 1 }}>
|
||||
<Row data={tableHead} style={styles.head} textStyle={styles.headText} />
|
||||
<TableWrapper style={styles.wrapper}>
|
||||
<Col
|
||||
data={tableTitle}
|
||||
style={styles.title}
|
||||
heightArr={[28, 28, 28]}
|
||||
textStyle={styles.titleText}
|
||||
/>
|
||||
<Rows
|
||||
data={tableData}
|
||||
flexArr={[1, 1, 1]}
|
||||
style={styles.row}
|
||||
textStyle={styles.text}
|
||||
onPress={onCellPress}
|
||||
/>
|
||||
</TableWrapper>
|
||||
</Table>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
head: {
|
||||
height: 44,
|
||||
backgroundColor: '#C6F3E0',
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
padding: 5,
|
||||
},
|
||||
headText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
row: {
|
||||
height: 40,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
wrapper: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
title: {
|
||||
flex: 1,
|
||||
backgroundColor: '#C6F3E0',
|
||||
},
|
||||
titleText: {
|
||||
textAlign: 'left',
|
||||
marginLeft: 6,
|
||||
fontWeight: '600',
|
||||
},
|
||||
});
|
82
example/src/ScrollableExample.tsx
Normal file
82
example/src/ScrollableExample.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import { Table, Row, Rows } from 'react-native-tabeller';
|
||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
||||
|
||||
export const ScrollableExample = () => {
|
||||
const tableHead = [
|
||||
'Head',
|
||||
'Head2',
|
||||
'Head3',
|
||||
'Head4',
|
||||
'Head5',
|
||||
'Head6',
|
||||
'Head7',
|
||||
'Head8',
|
||||
];
|
||||
const widthArr = [40, 69, 80, 100, 120, 140, 160, 180];
|
||||
|
||||
// generates large table data
|
||||
const tableData = [];
|
||||
for (let i = 0; i < 30; i += 1) {
|
||||
const rowData = [];
|
||||
for (let j = 0; j < 8; j += 1) {
|
||||
rowData.push(`${i}${j}`);
|
||||
}
|
||||
tableData.push(rowData);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView horizontal={true}>
|
||||
<View>
|
||||
<Table borderStyle={{ borderWidth: 2, borderColor: '#00000' }}>
|
||||
<Row
|
||||
data={tableHead}
|
||||
widthArr={widthArr}
|
||||
style={styles.header}
|
||||
textStyle={styles.headerText}
|
||||
/>
|
||||
</Table>
|
||||
<ScrollView style={styles.dataWrapper}>
|
||||
<Table borderStyle={{ borderWidth: 1, borderColor: '#00000' }}>
|
||||
<Rows
|
||||
data={tableData}
|
||||
widthArr={widthArr}
|
||||
style={styles.row}
|
||||
textStyle={styles.text}
|
||||
/>
|
||||
</Table>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
paddingTop: 30,
|
||||
height: 400,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
header: {
|
||||
height: 50,
|
||||
backgroundColor: '#C6F3E0',
|
||||
},
|
||||
headerText: {
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
padding: 5,
|
||||
},
|
||||
dataWrapper: {
|
||||
marginTop: -1,
|
||||
},
|
||||
row: {
|
||||
height: 40,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
});
|
41
example/src/StickyColumnExample.tsx
Normal file
41
example/src/StickyColumnExample.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { StickyTable } from 'react-native-tabeller';
|
||||
|
||||
export const StickyTableExample = () => {
|
||||
// first column will be sticky
|
||||
const tableData = [
|
||||
['Header', 'Col 1', 'Col 2', 'Col 3', 'Col 4'],
|
||||
['Row 1', 'Data 1-1', 'Data 1-2', 'Data 1-3', 'Data 1-4'],
|
||||
['Row 2', 'Data 2-1', 'Data 2-2', 'Data 2-3', 'Data 2-4'],
|
||||
['Row 3', 'Data 3-1', 'Data 3-2', 'Data 3-3', 'Data 3-4'],
|
||||
];
|
||||
|
||||
const stickyColumnWidth: number = 120;
|
||||
const columnWidths: number[] = [120, 120, 120, 120];
|
||||
|
||||
return (
|
||||
<StickyTable
|
||||
data={tableData}
|
||||
stickyColumnWidth={stickyColumnWidth}
|
||||
columnWidths={columnWidths}
|
||||
borderStyle={{ borderWidth: 1, borderColor: '#000' }}
|
||||
textStyle={styles.text}
|
||||
headerStyle={styles.header}
|
||||
headerTextStyle={styles.headerText}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
header: {
|
||||
backgroundColor: '#C6F3E0',
|
||||
},
|
||||
headerText: {
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
padding: 5,
|
||||
},
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-native-tabeller",
|
||||
"version": "0.1.0",
|
||||
"description": "React Native table with reanimated and gestures.<EFBFBD>",
|
||||
"description": "React Native table with reanimated and gestures.",
|
||||
"source": "./src/index.tsx",
|
||||
"main": "./lib/commonjs/index.js",
|
||||
"module": "./lib/module/index.js",
|
||||
@ -48,14 +48,16 @@
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"ios",
|
||||
"android"
|
||||
"android",
|
||||
"react-native-table",
|
||||
"tabeller"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://git.sheetjs.com/asadbek064/react-native-tabeller.git.git"
|
||||
},
|
||||
"author": "Asadbek Karimov <contact@asadk.dev> (https://asadk.dev)",
|
||||
"license": "MIT",
|
||||
"license": "ALv2",
|
||||
"bugs": {
|
||||
"url": "https://git.sheetjs.com/asadbek064/react-native-tabeller.git/issues"
|
||||
},
|
||||
|
BIN
react-native-tabeller-0.1.0.tgz
Normal file
BIN
react-native-tabeller-0.1.0.tgz
Normal file
Binary file not shown.
81
src/components/cell.tsx
Normal file
81
src/components/cell.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { FC, PropsWithChildren } from 'react';
|
||||
import { View, Text, StyleSheet, TouchableWithoutFeedback } from 'react-native';
|
||||
import type { ViewStyle } from 'react-native';
|
||||
|
||||
import type { CellProps } from '../types';
|
||||
|
||||
/**
|
||||
* cell component - the basic building block of the table
|
||||
*/
|
||||
export const Cell: FC<PropsWithChildren<CellProps>> = ({
|
||||
data,
|
||||
width,
|
||||
height,
|
||||
flex,
|
||||
style,
|
||||
textStyle,
|
||||
borderStyle,
|
||||
children,
|
||||
onPress,
|
||||
cellContainerProps = {},
|
||||
...props
|
||||
}) => {
|
||||
const textDom = children ?? (
|
||||
<Text style={StyleSheet.flatten([textStyle])} {...props}>
|
||||
{data}
|
||||
</Text>
|
||||
);
|
||||
|
||||
const borderTopWidth = borderStyle?.borderWidth ?? 0;
|
||||
const borderRightWidth = borderTopWidth;
|
||||
const borderColor = borderStyle?.borderColor ?? '#000';
|
||||
|
||||
const composedStyles = useMemo(() => {
|
||||
const styles: ViewStyle = {};
|
||||
if (width) styles.width = width;
|
||||
if (height) styles.height = height;
|
||||
if (flex) styles.flex = flex;
|
||||
if (!width && !flex && !height && !style) styles.flex = 1;
|
||||
|
||||
return styles;
|
||||
}, [width, height, flex, style]);
|
||||
|
||||
return (
|
||||
<View
|
||||
{...cellContainerProps}
|
||||
style={StyleSheet.flatten([
|
||||
{
|
||||
borderTopWidth,
|
||||
borderRightWidth,
|
||||
borderColor,
|
||||
},
|
||||
composedStyles,
|
||||
style,
|
||||
cellContainerProps.style,
|
||||
styles.cell,
|
||||
])}
|
||||
>
|
||||
<TouchableWithoutFeedback
|
||||
onPress={onPress ? () => onPress(data) : undefined}
|
||||
disabled={!onPress}
|
||||
>
|
||||
<View style={[styles.touchableContainer, style]}>{textDom}</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
cell: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
touchableContainer: {
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
83
src/components/cols.tsx
Normal file
83
src/components/cols.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import type { FC } from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import { Cell } from './cell';
|
||||
import type { ColProps, ColsProps } from '../types';
|
||||
import { sum } from '../util';
|
||||
|
||||
export const Col: FC<ColProps> = ({
|
||||
data,
|
||||
style,
|
||||
width,
|
||||
heightArr,
|
||||
flex,
|
||||
textStyle,
|
||||
borderStyle,
|
||||
...props
|
||||
}) => {
|
||||
if (!data) return null;
|
||||
|
||||
return (
|
||||
<View
|
||||
style={StyleSheet.flatten([
|
||||
{ width: width ?? (flex ? undefined : 1), flex },
|
||||
style,
|
||||
])}
|
||||
>
|
||||
{data.map((item, i) => {
|
||||
const height = heightArr?.[i];
|
||||
return (
|
||||
<Cell
|
||||
key={i}
|
||||
data={item}
|
||||
width={width}
|
||||
height={height}
|
||||
textStyle={textStyle}
|
||||
borderStyle={borderStyle}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export const Cols: FC<ColsProps> = ({
|
||||
data,
|
||||
style,
|
||||
widthArr,
|
||||
heightArr,
|
||||
flexArr,
|
||||
textStyle,
|
||||
borderStyle,
|
||||
...props
|
||||
}) => {
|
||||
if (!data) return null;
|
||||
|
||||
const width = widthArr ? sum(widthArr) : 0;
|
||||
|
||||
return (
|
||||
<View style={StyleSheet.flatten([styles.cols, width ? { width } : {}])}>
|
||||
{data.map((item, i) => {
|
||||
const flex = flexArr?.[i];
|
||||
const wth = widthArr?.[i];
|
||||
return (
|
||||
<Col
|
||||
key={i}
|
||||
data={item}
|
||||
width={wth}
|
||||
heightArr={heightArr}
|
||||
flex={flex}
|
||||
style={style}
|
||||
textStyle={textStyle}
|
||||
borderStyle={borderStyle}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
cols: { flexDirection: 'row' },
|
||||
});
|
116
src/components/rows.tsx
Normal file
116
src/components/rows.tsx
Normal file
@ -0,0 +1,116 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { FC } from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import type { ViewStyle } from 'react-native';
|
||||
|
||||
import { Cell } from './cell';
|
||||
import type { RowProps, RowsProps } from '../types';
|
||||
import { sum } from '../util';
|
||||
|
||||
/** Row component - Renders a single row of cells*/
|
||||
export const Row: FC<RowProps> = ({
|
||||
data,
|
||||
style,
|
||||
widthArr,
|
||||
height,
|
||||
flexArr,
|
||||
textStyle,
|
||||
borderStyle,
|
||||
onPress,
|
||||
cellTextStyle,
|
||||
...props
|
||||
}) => {
|
||||
// calc total width based on width array
|
||||
const totalWidth = widthArr ? sum(widthArr) : 0;
|
||||
|
||||
// calc row styles based on props
|
||||
const rowStyle = useMemo((): ViewStyle => {
|
||||
const styles: ViewStyle = {};
|
||||
if (totalWidth) styles.width = totalWidth;
|
||||
if (height) styles.height = height;
|
||||
return styles;
|
||||
}, [totalWidth, height]);
|
||||
|
||||
if (!data || !data.length) return null;
|
||||
|
||||
return (
|
||||
<View style={[styles.row, rowStyle, style]}>
|
||||
{data.map((item, index) => {
|
||||
const cellFlex = flexArr?.[index];
|
||||
const cellWidth = widthArr?.[index];
|
||||
const customTextStyle = cellTextStyle
|
||||
? cellTextStyle(item, index)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<Cell
|
||||
key={index}
|
||||
data={item}
|
||||
width={cellWidth}
|
||||
height={height}
|
||||
flex={cellFlex}
|
||||
borderStyle={borderStyle}
|
||||
textStyle={[customTextStyle, textStyle]}
|
||||
onPress={onPress}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
/** Rows component - Renders multiple rows*/
|
||||
export const Rows: FC<RowsProps> = ({
|
||||
data,
|
||||
style,
|
||||
widthArr,
|
||||
heightArr,
|
||||
flexArr,
|
||||
textStyle,
|
||||
borderStyle,
|
||||
...props
|
||||
}) => {
|
||||
// calc total flex and width
|
||||
const totalFlex = flexArr ? sum(flexArr) : 0;
|
||||
const totalWidth = widthArr ? sum(widthArr) : 0;
|
||||
|
||||
// calc container styles
|
||||
const containerStyle = useMemo((): ViewStyle => {
|
||||
const styles: ViewStyle = {};
|
||||
if (totalFlex) styles.flex = totalFlex;
|
||||
if (totalWidth) styles.width = totalWidth;
|
||||
return styles;
|
||||
}, [totalFlex, totalWidth]);
|
||||
|
||||
if (!data || !data.length) return null;
|
||||
|
||||
return (
|
||||
<View style={containerStyle}>
|
||||
{data.map((rowData, index) => {
|
||||
const rowHeight = heightArr?.[index];
|
||||
|
||||
return (
|
||||
<Row
|
||||
key={index}
|
||||
data={rowData}
|
||||
widthArr={widthArr}
|
||||
height={rowHeight}
|
||||
flexArr={flexArr}
|
||||
style={style}
|
||||
textStyle={textStyle}
|
||||
borderStyle={borderStyle}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
});
|
129
src/components/sticky-table.tsx
Normal file
129
src/components/sticky-table.tsx
Normal file
@ -0,0 +1,129 @@
|
||||
import React from 'react';
|
||||
import { View, ScrollView, StyleSheet } from 'react-native';
|
||||
import { Cell } from './cell';
|
||||
import type { StickyTableProps } from '../types';
|
||||
|
||||
/** StickyTable component - Table with sticky first column */
|
||||
export const StickyTable: React.FC<StickyTableProps> = ({
|
||||
data,
|
||||
stickyColumnWidth,
|
||||
columnWidths = [],
|
||||
style,
|
||||
cellStyle,
|
||||
textStyle,
|
||||
headerStyle,
|
||||
headerTextStyle,
|
||||
borderStyle = { borderWidth: 1, borderColor: '#000' },
|
||||
}) => {
|
||||
if (!data || data.length === 0) return null;
|
||||
|
||||
// calc content width
|
||||
const contentWidth = columnWidths.reduce((sum, width) => sum + width, 0);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
{/* sticky Column */}
|
||||
<View style={[styles.stickyColumn, { width: stickyColumnWidth }]}>
|
||||
{data.map((row, rowIndex) => {
|
||||
const isHeader = rowIndex === 0;
|
||||
return (
|
||||
<View
|
||||
key={`sticky-${rowIndex}`}
|
||||
style={[
|
||||
styles.cell,
|
||||
cellStyle,
|
||||
isHeader && headerStyle,
|
||||
borderStyle && {
|
||||
borderTopWidth: borderStyle.borderWidth,
|
||||
borderLeftWidth: borderStyle.borderWidth,
|
||||
borderBottomWidth: borderStyle.borderWidth,
|
||||
borderRightWidth: borderStyle.borderWidth,
|
||||
borderColor: borderStyle.borderColor,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Cell
|
||||
data={row[0]}
|
||||
width={stickyColumnWidth}
|
||||
textStyle={[textStyle, isHeader && headerTextStyle]}
|
||||
borderStyle={{ borderWidth: 0 }} // no borders for inner cell
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
|
||||
{/* scrollable Content */}
|
||||
<ScrollView
|
||||
horizontal={true}
|
||||
style={styles.scrollView}
|
||||
showsHorizontalScrollIndicator={true}
|
||||
>
|
||||
<View style={{ width: contentWidth || undefined }}>
|
||||
{data.map((row, rowIndex) => {
|
||||
const isHeader = rowIndex === 0;
|
||||
// skip first column as it's already in the sticky part
|
||||
const rowData = row.slice(1);
|
||||
|
||||
return (
|
||||
<View key={`row-${rowIndex}`} style={styles.row}>
|
||||
{rowData.map((cellData, cellIndex) => {
|
||||
const colWidth = columnWidths[cellIndex];
|
||||
|
||||
return (
|
||||
<View
|
||||
key={`cell-${rowIndex}-${cellIndex}`}
|
||||
style={[
|
||||
styles.cell,
|
||||
cellStyle,
|
||||
isHeader && headerStyle,
|
||||
{ width: colWidth },
|
||||
borderStyle && {
|
||||
borderTopWidth: borderStyle.borderWidth,
|
||||
borderLeftWidth: borderStyle.borderWidth,
|
||||
borderBottomWidth: borderStyle.borderWidth,
|
||||
borderRightWidth: borderStyle.borderWidth,
|
||||
borderColor: borderStyle.borderColor,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Cell
|
||||
data={cellData}
|
||||
width={colWidth}
|
||||
textStyle={[textStyle, isHeader && headerTextStyle]}
|
||||
borderStyle={{ borderWidth: 0 }} // no borders for inner cell
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
stickyColumn: {
|
||||
zIndex: 1,
|
||||
backgroundColor: 'white',
|
||||
elevation: 3,
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
cell: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'white',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
});
|
82
src/components/table.tsx
Normal file
82
src/components/table.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
|
||||
import type { TableProps, TableWrapperProps } from '../types';
|
||||
|
||||
export const Table: FC<TableProps> = ({ style, borderStyle, children }) => {
|
||||
const borderLeftWidth = borderStyle?.borderWidth ?? 0;
|
||||
const borderBottomWidth = borderLeftWidth;
|
||||
const borderColor = borderStyle?.borderColor ?? '#000';
|
||||
|
||||
const renderChildren = () =>
|
||||
React.Children.map(children, (child) => {
|
||||
if (!React.isValidElement(child)) return child;
|
||||
|
||||
// check if we should add the border style | skip known type names
|
||||
const elementType = child.type as any;
|
||||
const isScrollView =
|
||||
elementType?.displayName === 'ScrollView' ||
|
||||
elementType?.name === 'ScrollView';
|
||||
|
||||
if (borderStyle && !isScrollView) {
|
||||
return React.cloneElement(child, {
|
||||
borderStyle,
|
||||
...child.props,
|
||||
});
|
||||
}
|
||||
|
||||
return child;
|
||||
});
|
||||
|
||||
return (
|
||||
<View
|
||||
style={StyleSheet.flatten([
|
||||
styles.table,
|
||||
style,
|
||||
{
|
||||
borderLeftWidth,
|
||||
borderBottomWidth,
|
||||
borderColor,
|
||||
},
|
||||
])}
|
||||
>
|
||||
{renderChildren()}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableWrapper: FC<TableWrapperProps> = ({
|
||||
style,
|
||||
borderStyle,
|
||||
children,
|
||||
}) => {
|
||||
const renderChildren = () =>
|
||||
React.Children.map(children, (child) => {
|
||||
if (!React.isValidElement(child)) return child;
|
||||
|
||||
if (borderStyle) {
|
||||
return React.cloneElement(child, {
|
||||
borderStyle,
|
||||
...child.props,
|
||||
});
|
||||
}
|
||||
|
||||
return child;
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={StyleSheet.flatten([styles.wrapper, style])}>
|
||||
{renderChildren()}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
table: {
|
||||
overflow: 'hidden',
|
||||
},
|
||||
wrapper: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
@ -1,3 +1,26 @@
|
||||
export function multiply(a: number, b: number): number {
|
||||
return a * b;
|
||||
}
|
||||
/**
|
||||
* Tabeller - Table Components for React Native
|
||||
* A set of lightweight and customizable components to build tables
|
||||
* in React Native apps. Includes rows, columns, cells, and table wrappers.
|
||||
*/
|
||||
|
||||
// components
|
||||
export { Cell } from './components/cell';
|
||||
export { Row, Rows } from './components/rows';
|
||||
export { Col, Cols } from './components/cols';
|
||||
export { Table, TableWrapper } from './components/table';
|
||||
export { StickyTable } from './components/sticky-table';
|
||||
|
||||
// types
|
||||
export type {
|
||||
BorderStyle,
|
||||
BaseTableProps,
|
||||
CellProps,
|
||||
RowProps,
|
||||
RowsProps,
|
||||
ColProps,
|
||||
ColsProps,
|
||||
TableProps,
|
||||
TableWrapperProps,
|
||||
StickyTableProps,
|
||||
} from './types';
|
||||
|
130
src/types.ts
Normal file
130
src/types.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ViewStyle, TextStyle, StyleProp, ViewProps } from 'react-native';
|
||||
|
||||
/** border style configuration for table elements */
|
||||
export interface BorderStyle {
|
||||
borderColor?: string; // defaults to #000
|
||||
borderWidth?: number; // defaults to 0
|
||||
}
|
||||
|
||||
/** base props shared across table components */
|
||||
export interface BaseTableProps {
|
||||
/** custom style for the component */
|
||||
style?: StyleProp<ViewStyle>;
|
||||
/** border style configuration */
|
||||
borderStyle?: BorderStyle;
|
||||
}
|
||||
|
||||
/** props for the Cell component */
|
||||
export interface CellProps extends BaseTableProps {
|
||||
/** cell content */
|
||||
data?: string | number | null;
|
||||
/** cell width (pixels) */
|
||||
width?: number;
|
||||
/** cell height (pixels) */
|
||||
height?: number;
|
||||
/** flex value for the cell */
|
||||
flex?: number;
|
||||
/** text style for cell content */
|
||||
textStyle?: StyleProp<TextStyle>;
|
||||
/** props passed to the cell container */
|
||||
cellContainerProps?: ViewProps;
|
||||
/** callback when cell is pressed */
|
||||
onPress?: (data: any) => void;
|
||||
/** children to render inside the cell */
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
/** props for the Row component */
|
||||
export interface RowProps extends BaseTableProps {
|
||||
/** array of data items for each cell in the row */
|
||||
data: Array<string | number | null>;
|
||||
/** array of widths for each cell */
|
||||
widthArr?: number[];
|
||||
/** height for the entire row */
|
||||
height?: number;
|
||||
/** array of flex values for each cell in the row */
|
||||
flexArr?: number[];
|
||||
/** text style applied to all cell in the row */
|
||||
textStyle?: StyleProp<TextStyle>;
|
||||
/** function to generate custom text styles for individual cell */
|
||||
cellTextStyle?: (item: any, index: number) => StyleProp<TextStyle>;
|
||||
/** callback when a cell is pressed */
|
||||
onPress?: (item: any) => void;
|
||||
}
|
||||
|
||||
/** props for the Rows componen */
|
||||
export interface RowsProps extends BaseTableProps {
|
||||
/** 2D array of data for rows and cells */
|
||||
data: Array<Array<string | number | null>>;
|
||||
/** array of widths for each column */
|
||||
widthArr?: number[];
|
||||
/** array of heights for each cell in a column */
|
||||
heightArr?: number[];
|
||||
/** array of flex values for each column */
|
||||
flexArr?: number[];
|
||||
/** text style applied to all cells */
|
||||
textStyle?: StyleProp<TextStyle>;
|
||||
/** callback when a cell is pressed */
|
||||
onPress?: (item: any) => void;
|
||||
}
|
||||
|
||||
/** props for the Col component */
|
||||
export interface ColProps extends BaseTableProps {
|
||||
/** array of data items for each cell in the column */
|
||||
data: Array<string | number | null>;
|
||||
/** width for the entire column */
|
||||
width?: number;
|
||||
/** array of heights for each cell */
|
||||
heightArr?: number[];
|
||||
/** flex value for the column */
|
||||
flex?: number;
|
||||
/** text style applied to all cells in the column */
|
||||
textStyle?: StyleProp<TextStyle>;
|
||||
}
|
||||
|
||||
/** props for the Cols component */
|
||||
export interface ColsProps extends BaseTableProps {
|
||||
/** 2D array of data for columns and cells */
|
||||
data: Array<Array<string | number | null>>;
|
||||
/** array of widths for each column */
|
||||
widthArr?: number[];
|
||||
/** array of heights for each cell in a column */
|
||||
heightArr?: number[];
|
||||
/** array of flex values for each column */
|
||||
flexArr?: number[];
|
||||
/** text style applied to all cells */
|
||||
textStyle?: StyleProp<TextStyle>;
|
||||
}
|
||||
|
||||
/** props for the Table component */
|
||||
export interface TableProps extends BaseTableProps {
|
||||
children: ReactNode; // Table content
|
||||
}
|
||||
|
||||
/** props for the TableWrapper component */
|
||||
export interface TableWrapperProps extends BaseTableProps {
|
||||
children: ReactNode; // TableWrapper content
|
||||
}
|
||||
|
||||
/** props for the StickyTable component */
|
||||
export interface StickyTableProps {
|
||||
/** full table data including first column */
|
||||
data: (string | number | null)[][];
|
||||
/** width of the sticky column */
|
||||
stickyColumnWidth: number;
|
||||
/** widths for non-sticky columns */
|
||||
columnWidths?: number[];
|
||||
/** style for the container */
|
||||
style?: StyleProp<ViewStyle>;
|
||||
/** style for cells */
|
||||
cellStyle?: StyleProp<ViewStyle>;
|
||||
/** text style for cell content */
|
||||
textStyle?: StyleProp<TextStyle>;
|
||||
/** style for header row */
|
||||
headerStyle?: StyleProp<ViewStyle>;
|
||||
/** text style for header cells */
|
||||
headerTextStyle?: StyleProp<TextStyle>;
|
||||
/** border style */
|
||||
borderStyle?: BorderStyle;
|
||||
}
|
9
src/util/index.ts
Normal file
9
src/util/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* sum all numbers in an array
|
||||
* @param arr - arr of numbers
|
||||
* @returns sum of all numbers
|
||||
*/
|
||||
export const sum = (arr: number[]): number => {
|
||||
if (!arr || !arr.length) return 0;
|
||||
return arr.reduce((acc, n) => acc + n, 0);
|
||||
};
|
Loading…
Reference in New Issue
Block a user