diff --git a/LICENSE b/LICENSE
index 1dd7498..4abbe55 100644
--- a/LICENSE
+++ b/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.
\ No newline at end of file
diff --git a/README.md b/README.md
index 7df4e68..8117953 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,573 @@
-# react-native-tabeller
+
React Native Tabeller
+
+
+
+
+
+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
+
+
+```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 (
+
+
+
+ );
+}
+
+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
+
+
+```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 (
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+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
+
+
+```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 (
+
+
+
+ );
+};
+
+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
+
+
+```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(['Head', 'Head2', 'Head3', 'Head4']);
+ const [tableData] = useState([
+ ['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 => (
+ alertIndex(index)}>
+
+ button
+
+
+ );
+
+ return (
+
+
+
+ {
+ tableData.map((rowData, index) => (
+
+ {
+ rowData.map((cellData, cellIndex) => (
+ |
+ ))
+ }
+
+ ))
+ }
+
+
+ );
+};
+
+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
+
+
+```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 => (
+ alertIndex(value)}>
+
+ button
+
+
+ );
+
+ const [tableHead] = useState(['', elementButton('1'), elementButton('2'), elementButton('3')]);
+ const [sideHead] = useState(['H1', 'H2']);
+ const [rowTitles] = useState(['Title', 'Title2', 'Title3', 'Title4']);
+
+ // Table data - matching the structure in the screenshot
+ const [tableData] = useState([
+ ['a', '1', 'a'],
+ ['b', '2', 'b'],
+ ['c', '3', 'c'],
+ ['d', '4', 'd']
+ ]);
+
+ return (
+
+
+ {/* table header row with buttons */}
+
+
+
+ {/* left column with H1, H2 */}
+
+
+
+ {/* row titles column */}
+
+
+ {/* content cells */}
+
+
+
+
+
+ );
+};
+
+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;
+```
+
+---
+
+
+
+
+## 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 | 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> | 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 | 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> | 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> | 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' }` |
+---
+
+
+
+
+
+## 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
+
+ {/* add borderStyle if the parent is not a Table component */}
+
+
+
+
+```
## 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)
diff --git a/example/src/App.tsx b/example/src/App.tsx
index 9d05b24..0548ef5 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -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 (
-
- Result: {result}
-
+
+ React Native Tabeller
+
+
+ Basic Table
+
+
+
+
+ Scrollable Table
+
+
+
+
+
+ Scrollable Sticky 1st Column Table
+
+
+
+
+
+ Example Three
+
+
+
+
+ Example Four
+
+
+
+
+ Example Five
+
+
+
);
}
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,
},
});
diff --git a/example/src/BasicExample.tsx b/example/src/BasicExample.tsx
new file mode 100644
index 0000000..663ef4f
--- /dev/null
+++ b/example/src/BasicExample.tsx
@@ -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 (
+
+
+
+ );
+};
+
+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',
+ },
+});
diff --git a/example/src/ExampleFive.tsx b/example/src/ExampleFive.tsx
new file mode 100644
index 0000000..b33eebc
--- /dev/null
+++ b/example/src/ExampleFive.tsx
@@ -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 => (
+ alertIndex(value)}>
+
+ button
+
+
+ );
+
+ const [tableHead] = useState([
+ '',
+ elementButton('1'),
+ elementButton('2'),
+ elementButton('3'),
+ ]);
+ const [sideHead] = useState(['H1', 'H2']);
+ const [rowTitles] = useState([
+ 'Title',
+ 'Title2',
+ 'Title3',
+ 'Title4',
+ ]);
+
+ // Table data - matching the structure in the screenshot
+ const [tableData] = useState([
+ ['a', '1', 'a'],
+ ['b', '2', 'b'],
+ ['c', '3', 'c'],
+ ['d', '4', 'd'],
+ ]);
+
+ return (
+
+
+ {/* table header row with buttons */}
+
+
+ {/* left column with H1, H2 */}
+
+
+ {/* row titles column */}
+
+ {/* content cells */}
+
+
+
+
+
+ );
+};
+
+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;
diff --git a/example/src/ExampleFour.tsx b/example/src/ExampleFour.tsx
new file mode 100644
index 0000000..f2e296b
--- /dev/null
+++ b/example/src/ExampleFour.tsx
@@ -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(['Head', 'Head2', 'Head3', 'Head4']);
+ const [tableData] = useState([
+ ['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 => (
+ alertIndex(index)}>
+
+ button
+
+
+ );
+
+ return (
+
+
+
+ {tableData.map((rowData, index) => (
+
+ {rowData.map((cellData, cellIndex) => (
+ |
+ ))}
+
+ ))}
+
+
+ );
+};
+
+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;
diff --git a/example/src/ExampleThree.tsx b/example/src/ExampleThree.tsx
new file mode 100644
index 0000000..42f2e30
--- /dev/null
+++ b/example/src/ExampleThree.tsx
@@ -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 (
+
+
+
+ );
+};
+
+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',
+ },
+});
diff --git a/example/src/ScrollableExample.tsx b/example/src/ScrollableExample.tsx
new file mode 100644
index 0000000..93e158a
--- /dev/null
+++ b/example/src/ScrollableExample.tsx
@@ -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 (
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+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',
+ },
+});
diff --git a/example/src/StickyColumnExample.tsx b/example/src/StickyColumnExample.tsx
new file mode 100644
index 0000000..8393918
--- /dev/null
+++ b/example/src/StickyColumnExample.tsx
@@ -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 (
+
+ );
+};
+
+const styles = StyleSheet.create({
+ header: {
+ backgroundColor: '#C6F3E0',
+ },
+ headerText: {
+ fontWeight: 'bold',
+ textAlign: 'center',
+ },
+ text: {
+ textAlign: 'center',
+ padding: 5,
+ },
+});
diff --git a/package.json b/package.json
index b5b5f46..7169917 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "react-native-tabeller",
"version": "0.1.0",
- "description": "React Native table with reanimated and gestures.�",
+ "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 (https://asadk.dev)",
- "license": "MIT",
+ "license": "ALv2",
"bugs": {
"url": "https://git.sheetjs.com/asadbek064/react-native-tabeller.git/issues"
},
diff --git a/react-native-tabeller-0.1.0.tgz b/react-native-tabeller-0.1.0.tgz
new file mode 100644
index 0000000..fab8eaa
Binary files /dev/null and b/react-native-tabeller-0.1.0.tgz differ
diff --git a/src/components/cell.tsx b/src/components/cell.tsx
new file mode 100644
index 0000000..25aba5d
--- /dev/null
+++ b/src/components/cell.tsx
@@ -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> = ({
+ data,
+ width,
+ height,
+ flex,
+ style,
+ textStyle,
+ borderStyle,
+ children,
+ onPress,
+ cellContainerProps = {},
+ ...props
+}) => {
+ const textDom = children ?? (
+
+ {data}
+
+ );
+
+ 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 (
+
+ onPress(data) : undefined}
+ disabled={!onPress}
+ >
+ {textDom}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ cell: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ touchableContainer: {
+ flex: 1,
+ width: '100%',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
diff --git a/src/components/cols.tsx b/src/components/cols.tsx
new file mode 100644
index 0000000..4a6e40d
--- /dev/null
+++ b/src/components/cols.tsx
@@ -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 = ({
+ data,
+ style,
+ width,
+ heightArr,
+ flex,
+ textStyle,
+ borderStyle,
+ ...props
+}) => {
+ if (!data) return null;
+
+ return (
+
+ {data.map((item, i) => {
+ const height = heightArr?.[i];
+ return (
+ |
+ );
+ })}
+
+ );
+};
+
+export const Cols: FC = ({
+ data,
+ style,
+ widthArr,
+ heightArr,
+ flexArr,
+ textStyle,
+ borderStyle,
+ ...props
+}) => {
+ if (!data) return null;
+
+ const width = widthArr ? sum(widthArr) : 0;
+
+ return (
+
+ {data.map((item, i) => {
+ const flex = flexArr?.[i];
+ const wth = widthArr?.[i];
+ return (
+
+ );
+ })}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ cols: { flexDirection: 'row' },
+});
diff --git a/src/components/rows.tsx b/src/components/rows.tsx
new file mode 100644
index 0000000..700298f
--- /dev/null
+++ b/src/components/rows.tsx
@@ -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 = ({
+ 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 (
+
+ {data.map((item, index) => {
+ const cellFlex = flexArr?.[index];
+ const cellWidth = widthArr?.[index];
+ const customTextStyle = cellTextStyle
+ ? cellTextStyle(item, index)
+ : undefined;
+
+ return (
+ |
+ );
+ })}
+
+ );
+};
+
+/** Rows component - Renders multiple rows*/
+export const Rows: FC = ({
+ 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 (
+
+ {data.map((rowData, index) => {
+ const rowHeight = heightArr?.[index];
+
+ return (
+
+ );
+ })}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ row: {
+ flexDirection: 'row',
+ overflow: 'hidden',
+ },
+});
diff --git a/src/components/sticky-table.tsx b/src/components/sticky-table.tsx
new file mode 100644
index 0000000..d185c09
--- /dev/null
+++ b/src/components/sticky-table.tsx
@@ -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 = ({
+ 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 (
+
+ {/* sticky Column */}
+
+ {data.map((row, rowIndex) => {
+ const isHeader = rowIndex === 0;
+ return (
+
+ |
+
+ );
+ })}
+
+
+ {/* scrollable Content */}
+
+
+ {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 (
+
+ {rowData.map((cellData, cellIndex) => {
+ const colWidth = columnWidths[cellIndex];
+
+ return (
+
+ |
+
+ );
+ })}
+
+ );
+ })}
+
+
+
+ );
+};
+
+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',
+ },
+});
diff --git a/src/components/table.tsx b/src/components/table.tsx
new file mode 100644
index 0000000..cf02f7a
--- /dev/null
+++ b/src/components/table.tsx
@@ -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 = ({ 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 (
+
+ {renderChildren()}
+
+ );
+};
+
+export const TableWrapper: FC = ({
+ 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 (
+
+ {renderChildren()}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ table: {
+ overflow: 'hidden',
+ },
+ wrapper: {
+ flex: 1,
+ },
+});
diff --git a/src/index.tsx b/src/index.tsx
index 14289fe..13843e6 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -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';
diff --git a/src/types.ts b/src/types.ts
new file mode 100644
index 0000000..a54c33f
--- /dev/null
+++ b/src/types.ts
@@ -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;
+ /** 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;
+ /** 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;
+ /** 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;
+ /** function to generate custom text styles for individual cell */
+ cellTextStyle?: (item: any, index: number) => StyleProp;
+ /** 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 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;
+ /** 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;
+ /** 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;
+}
+
+/** props for the Cols component */
+export interface ColsProps extends BaseTableProps {
+ /** 2D array of data for columns and cells */
+ data: Array>;
+ /** 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;
+}
+
+/** 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;
+ /** style for cells */
+ cellStyle?: StyleProp;
+ /** text style for cell content */
+ textStyle?: StyleProp;
+ /** style for header row */
+ headerStyle?: StyleProp;
+ /** text style for header cells */
+ headerTextStyle?: StyleProp;
+ /** border style */
+ borderStyle?: BorderStyle;
+}
diff --git a/src/util/index.ts b/src/util/index.ts
new file mode 100644
index 0000000..b87d83d
--- /dev/null
+++ b/src/util/index.ts
@@ -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);
+};