@sqlrooms/data-table 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -0
- package/dist/DataTableModal.d.ts +4 -10
- package/dist/DataTableModal.d.ts.map +1 -1
- package/dist/DataTableModal.js +3 -7
- package/dist/DataTableModal.js.map +1 -1
- package/dist/QueryDataTable.d.ts.map +1 -1
- package/dist/QueryDataTable.js +15 -5
- package/dist/QueryDataTable.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
A high-performance data table component library for SQLRooms applications. This package provides flexible and feature-rich table components for displaying and interacting with large datasets, with special support for Apache Arrow data structures.
|
|
2
|
+
|
|
3
|
+
## Features
|
|
4
|
+
|
|
5
|
+
- 📊 **Multiple Table Variants**: Paginated, virtualized, and query-specific tables
|
|
6
|
+
- 🚀 **High Performance**: Optimized for handling large datasets efficiently
|
|
7
|
+
- 🏹 **Arrow Integration**: Native support for Apache Arrow data structures
|
|
8
|
+
- 🔍 **Sorting & Filtering**: Built-in data manipulation capabilities
|
|
9
|
+
- 📱 **Responsive Design**: Tables that work well on all screen sizes
|
|
10
|
+
- 🎨 **Customizable**: Flexible styling and configuration options
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @sqlrooms/data-table
|
|
16
|
+
# or
|
|
17
|
+
yarn add @sqlrooms/data-table
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Basic Usage
|
|
21
|
+
|
|
22
|
+
### Paginated Data Table
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import {DataTablePaginated} from '@sqlrooms/data-table';
|
|
26
|
+
|
|
27
|
+
function MyDataTable() {
|
|
28
|
+
const data = [
|
|
29
|
+
{id: 1, name: 'Alice', age: 28},
|
|
30
|
+
{id: 2, name: 'Bob', age: 34},
|
|
31
|
+
{id: 3, name: 'Charlie', age: 42},
|
|
32
|
+
// More data...
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const columns = [
|
|
36
|
+
{accessorKey: 'id', header: 'ID'},
|
|
37
|
+
{accessorKey: 'name', header: 'Name'},
|
|
38
|
+
{accessorKey: 'age', header: 'Age'},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<DataTablePaginated
|
|
43
|
+
data={data}
|
|
44
|
+
columns={columns}
|
|
45
|
+
pageSize={10}
|
|
46
|
+
enableSorting
|
|
47
|
+
enableFiltering
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Virtualized Data Table for Large Datasets
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import {DataTableVirtualized} from '@sqlrooms/data-table';
|
|
57
|
+
|
|
58
|
+
function LargeDataTable() {
|
|
59
|
+
// Imagine this is a very large dataset
|
|
60
|
+
const largeDataset = generateLargeDataset(10000);
|
|
61
|
+
|
|
62
|
+
const columns = [
|
|
63
|
+
{accessorKey: 'id', header: 'ID'},
|
|
64
|
+
{accessorKey: 'name', header: 'Name'},
|
|
65
|
+
{accessorKey: 'email', header: 'Email'},
|
|
66
|
+
{accessorKey: 'status', header: 'Status'},
|
|
67
|
+
{accessorKey: 'lastActive', header: 'Last Active'},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<DataTableVirtualized
|
|
72
|
+
data={largeDataset}
|
|
73
|
+
columns={columns}
|
|
74
|
+
height={500}
|
|
75
|
+
width="100%"
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Working with SQL Query Results
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import {QueryDataTable} from '@sqlrooms/data-table';
|
|
85
|
+
import {useSql} from '@sqlrooms/duckdb';
|
|
86
|
+
|
|
87
|
+
function QueryResultsTable() {
|
|
88
|
+
const {data, isLoading, error} = useSql({
|
|
89
|
+
query:
|
|
90
|
+
'SELECT id, name, email, created_at FROM users ORDER BY created_at DESC',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (isLoading) return <div>Loading...</div>;
|
|
94
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
95
|
+
if (!data) return null;
|
|
96
|
+
|
|
97
|
+
return <QueryDataTable data={data} />;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Using with Apache Arrow
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import {useArrowDataTable} from '@sqlrooms/data-table';
|
|
105
|
+
import {Table} from 'apache-arrow';
|
|
106
|
+
|
|
107
|
+
function ArrowTable({arrowTable}: {arrowTable: Table}) {
|
|
108
|
+
const {columns, data} = useArrowDataTable(arrowTable);
|
|
109
|
+
|
|
110
|
+
return <DataTablePaginated columns={columns} data={data} pageSize={25} />;
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Advanced Features
|
|
115
|
+
|
|
116
|
+
- **Custom Cell Rendering**: Define custom renderers for specific cell types
|
|
117
|
+
- **Row Selection**: Enable row selection with checkboxes
|
|
118
|
+
- **Expandable Rows**: Show additional details in expandable row sections
|
|
119
|
+
- **Column Resizing**: Allow users to resize columns
|
|
120
|
+
- **Export Options**: Export table data to CSV or other formats
|
|
121
|
+
- **Theming**: Customize the appearance to match your application
|
|
122
|
+
|
|
123
|
+
For more information, visit the SQLRooms documentation.
|
package/dist/DataTableModal.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { UseDisclosureReturnValue } from '@sqlrooms/ui';
|
|
1
2
|
import { FC } from 'react';
|
|
2
3
|
/**
|
|
3
4
|
* A modal component for displaying a table with data from a SQL query.
|
|
@@ -14,16 +15,12 @@ import { FC } from 'react';
|
|
|
14
15
|
* import { DataTableModal } from '@sqlrooms/data-table';
|
|
15
16
|
*
|
|
16
17
|
* const MyComponent = () => {
|
|
17
|
-
* const
|
|
18
|
-
*
|
|
18
|
+
* const tableModal = useDisclosure();
|
|
19
19
|
* return (
|
|
20
20
|
* <DataTableModal
|
|
21
21
|
* title="Users"
|
|
22
22
|
* query="SELECT * FROM users LIMIT 10"
|
|
23
|
-
* tableModal={
|
|
24
|
-
* isOpen,
|
|
25
|
-
* onClose: () => setIsOpen(false)
|
|
26
|
-
* }}
|
|
23
|
+
* tableModal={tableModal}
|
|
27
24
|
* />
|
|
28
25
|
* );
|
|
29
26
|
* };
|
|
@@ -32,10 +29,7 @@ import { FC } from 'react';
|
|
|
32
29
|
declare const DataTableModal: FC<{
|
|
33
30
|
title: string | undefined;
|
|
34
31
|
query: string | undefined;
|
|
35
|
-
tableModal:
|
|
36
|
-
isOpen: boolean;
|
|
37
|
-
onClose: () => void;
|
|
38
|
-
};
|
|
32
|
+
tableModal: Pick<UseDisclosureReturnValue, 'isOpen' | 'onClose'>;
|
|
39
33
|
}>;
|
|
40
34
|
export default DataTableModal;
|
|
41
35
|
//# sourceMappingURL=DataTableModal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTableModal.d.ts","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DataTableModal.d.ts","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,wBAAwB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAGzB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,cAAc,EAAE,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC,wBAAwB,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;CAClE,CAyBA,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
package/dist/DataTableModal.js
CHANGED
|
@@ -16,23 +16,19 @@ import QueryDataTable from './QueryDataTable';
|
|
|
16
16
|
* import { DataTableModal } from '@sqlrooms/data-table';
|
|
17
17
|
*
|
|
18
18
|
* const MyComponent = () => {
|
|
19
|
-
* const
|
|
20
|
-
*
|
|
19
|
+
* const tableModal = useDisclosure();
|
|
21
20
|
* return (
|
|
22
21
|
* <DataTableModal
|
|
23
22
|
* title="Users"
|
|
24
23
|
* query="SELECT * FROM users LIMIT 10"
|
|
25
|
-
* tableModal={
|
|
26
|
-
* isOpen,
|
|
27
|
-
* onClose: () => setIsOpen(false)
|
|
28
|
-
* }}
|
|
24
|
+
* tableModal={tableModal}
|
|
29
25
|
* />
|
|
30
26
|
* );
|
|
31
27
|
* };
|
|
32
28
|
* ```
|
|
33
29
|
*/
|
|
34
30
|
const DataTableModal = ({ title, query, tableModal }) => {
|
|
35
|
-
return (_jsx(Dialog, { open: tableModal.isOpen, onOpenChange: (isOpen) => !isOpen && tableModal.onClose(), children: _jsxs(DialogContent, { className: "h-[80vh] max-w-[75vw]", "aria-describedby": "data-table-modal", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title ? `Table "${title}"` : '' }), _jsx(DialogDescription, { className: "hidden", children: title })] }), _jsx("div", { className: "flex-1
|
|
31
|
+
return (_jsx(Dialog, { open: tableModal.isOpen, onOpenChange: (isOpen) => !isOpen && tableModal.onClose(), children: _jsxs(DialogContent, { className: "h-[80vh] max-w-[75vw]", "aria-describedby": "data-table-modal", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title ? `Table "${title}"` : '' }), _jsx(DialogDescription, { className: "hidden", children: title })] }), _jsx("div", { className: "bg-muted flex-1 overflow-hidden", children: tableModal.isOpen && query ? _jsx(QueryDataTable, { query: query }) : null }), _jsx(DialogFooter, { children: _jsx(Button, { variant: "outline", onClick: tableModal.onClose, children: "Close" }) })] }) }));
|
|
36
32
|
};
|
|
37
33
|
export default DataTableModal;
|
|
38
34
|
//# sourceMappingURL=DataTableModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTableModal.js","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,
|
|
1
|
+
{"version":3,"file":"DataTableModal.js","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GAEZ,MAAM,cAAc,CAAC;AAEtB,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,cAAc,GAIf,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAC,EAAE,EAAE;IAClC,OAAO,CACL,KAAC,MAAM,IACL,IAAI,EAAE,UAAU,CAAC,MAAM,EACvB,YAAY,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,YAElE,MAAC,aAAa,IACZ,SAAS,EAAC,uBAAuB,sBAChB,kBAAkB,aAEnC,MAAC,YAAY,eACX,KAAC,WAAW,cAAE,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,GAAe,EAC5D,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,YAAE,KAAK,GAAqB,IACpD,EACf,cAAK,SAAS,EAAC,iCAAiC,YAC7C,UAAU,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAC,CAAC,IAAI,GACjE,EACN,KAAC,YAAY,cACX,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,UAAU,CAAC,OAAO,sBAE5C,GACI,IACD,GACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n UseDisclosureReturnValue,\n} from '@sqlrooms/ui';\nimport {FC} from 'react';\nimport QueryDataTable from './QueryDataTable';\n\n/**\n * A modal component for displaying a table with data from a SQL query.\n *\n * @component\n * @param props - Component props\n * @param props.title - The title of the table\n * @param props.query - The SQL query to execute and display in the table\n * @param props.tableModal - An object containing the modal's open state and close function\n *\n * @example\n * ```tsx\n * import { useState } from 'react';\n * import { DataTableModal } from '@sqlrooms/data-table';\n *\n * const MyComponent = () => {\n * const tableModal = useDisclosure();\n * return (\n * <DataTableModal\n * title=\"Users\"\n * query=\"SELECT * FROM users LIMIT 10\"\n * tableModal={tableModal}\n * />\n * );\n * };\n * ```\n */\nconst DataTableModal: FC<{\n title: string | undefined;\n query: string | undefined;\n tableModal: Pick<UseDisclosureReturnValue, 'isOpen' | 'onClose'>;\n}> = ({title, query, tableModal}) => {\n return (\n <Dialog\n open={tableModal.isOpen}\n onOpenChange={(isOpen: boolean) => !isOpen && tableModal.onClose()}\n >\n <DialogContent\n className=\"h-[80vh] max-w-[75vw]\"\n aria-describedby=\"data-table-modal\"\n >\n <DialogHeader>\n <DialogTitle>{title ? `Table \"${title}\"` : ''}</DialogTitle>\n <DialogDescription className=\"hidden\">{title}</DialogDescription>\n </DialogHeader>\n <div className=\"bg-muted flex-1 overflow-hidden\">\n {tableModal.isOpen && query ? <QueryDataTable query={query} /> : null}\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={tableModal.onClose}>\n Close\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default DataTableModal;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryDataTable.d.ts","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":"AASA,OAAO,EAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"QueryDataTable.d.ts","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":"AASA,OAAO,EAAC,EAAE,EAAyC,MAAM,OAAO,CAAC;AAIjE,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC;CAChC,CAAC;AAoGF,QAAA,MAAM,0BAA0B,EAAE,EAAE,CAAC,mBAAmB,CASvD,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
|
package/dist/QueryDataTable.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { SpinnerPane } from '@sqlrooms/ui';
|
|
4
4
|
import { escapeId, exportToCsv, getColValAsNumber, useDuckDb, } from '@sqlrooms/duckdb';
|
|
5
5
|
import { genRandomStr } from '@sqlrooms/utils';
|
|
6
|
-
import { Suspense, useEffect, useState } from 'react';
|
|
6
|
+
import { Suspense, useEffect, useMemo, useState } from 'react';
|
|
7
7
|
import DataTablePaginated from './DataTablePaginated';
|
|
8
8
|
import useArrowDataTable from './useArrowDataTable';
|
|
9
9
|
const QueryDataTable = ({ query }) => {
|
|
@@ -17,12 +17,22 @@ const QueryDataTable = ({ query }) => {
|
|
|
17
17
|
const [data, setData] = useState(null);
|
|
18
18
|
const [isFetching, setIsFetching] = useState(false);
|
|
19
19
|
const [isExporting, setIsExporting] = useState(false);
|
|
20
|
+
// Sanitize the query generated by LLM to remove trailing semicolons, comments, and extra spaces
|
|
21
|
+
const sanitizedQuery = useMemo(() => {
|
|
22
|
+
return query
|
|
23
|
+
.trim() // Remove leading/trailing whitespace
|
|
24
|
+
.replace(/;+$/, '') // Remove all trailing semicolons
|
|
25
|
+
.replace(/--.*$/gm, '') // Remove single-line comments
|
|
26
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove multi-line comments
|
|
27
|
+
.replace(/\s+/g, ' '); // Normalize whitespace to single spaces
|
|
28
|
+
}, [query]);
|
|
20
29
|
// Fetch row count
|
|
21
30
|
useEffect(() => {
|
|
22
31
|
const fetchCount = async () => {
|
|
23
32
|
try {
|
|
24
33
|
setIsFetching(true);
|
|
25
|
-
const
|
|
34
|
+
const countQuery = `SELECT COUNT(*)::int FROM (${sanitizedQuery})`;
|
|
35
|
+
const result = await conn.query(countQuery);
|
|
26
36
|
setCount(getColValAsNumber(result));
|
|
27
37
|
}
|
|
28
38
|
catch (error) {
|
|
@@ -33,14 +43,14 @@ const QueryDataTable = ({ query }) => {
|
|
|
33
43
|
}
|
|
34
44
|
};
|
|
35
45
|
fetchCount();
|
|
36
|
-
}, [
|
|
46
|
+
}, [conn, sanitizedQuery]);
|
|
37
47
|
// Fetch data
|
|
38
48
|
useEffect(() => {
|
|
39
49
|
const fetchData = async () => {
|
|
40
50
|
try {
|
|
41
51
|
setIsFetching(true);
|
|
42
52
|
const result = await conn.query(`SELECT * FROM (
|
|
43
|
-
${
|
|
53
|
+
${sanitizedQuery}
|
|
44
54
|
) ${sorting.length > 0
|
|
45
55
|
? `ORDER BY ${sorting
|
|
46
56
|
.map((d) => `${escapeId(d.id)}${d.desc ? ' DESC' : ''}`)
|
|
@@ -58,7 +68,7 @@ const QueryDataTable = ({ query }) => {
|
|
|
58
68
|
}
|
|
59
69
|
};
|
|
60
70
|
fetchData();
|
|
61
|
-
}, [
|
|
71
|
+
}, [pagination, sorting, conn, sanitizedQuery]);
|
|
62
72
|
const arrowTableData = useArrowDataTable(data);
|
|
63
73
|
const handleExport = async () => {
|
|
64
74
|
if (!query)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryDataTable.js","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":";;AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AACzC,OAAO,EACL,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAK,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"QueryDataTable.js","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SpinnerPane} from '@sqlrooms/ui';\nimport {\n escapeId,\n exportToCsv,\n getColValAsNumber,\n useDuckDb,\n} from '@sqlrooms/duckdb';\nimport {genRandomStr} from '@sqlrooms/utils';\nimport {PaginationState, SortingState} from '@tanstack/table-core';\nimport {FC, Suspense, useEffect, useMemo, useState} from 'react';\nimport DataTablePaginated from './DataTablePaginated';\nimport useArrowDataTable from './useArrowDataTable';\n\nexport type QueryDataTableProps = {\n query: string;\n queryKeyComponents?: unknown[];\n};\n\nconst QueryDataTable: FC<QueryDataTableProps> = ({query}) => {\n const {conn} = useDuckDb();\n const [sorting, setSorting] = useState<SortingState>([]);\n const [pagination, setPagination] = useState<PaginationState>({\n pageIndex: 0,\n pageSize: 100,\n });\n\n const [count, setCount] = useState<number | undefined>(undefined);\n const [data, setData] = useState<any>(null);\n const [isFetching, setIsFetching] = useState(false);\n const [isExporting, setIsExporting] = useState(false);\n\n // Sanitize the query generated by LLM to remove trailing semicolons, comments, and extra spaces\n const sanitizedQuery = useMemo(() => {\n return query\n .trim() // Remove leading/trailing whitespace\n .replace(/;+$/, '') // Remove all trailing semicolons\n .replace(/--.*$/gm, '') // Remove single-line comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Remove multi-line comments\n .replace(/\\s+/g, ' '); // Normalize whitespace to single spaces\n }, [query]);\n\n // Fetch row count\n useEffect(() => {\n const fetchCount = async () => {\n try {\n setIsFetching(true);\n const countQuery = `SELECT COUNT(*)::int FROM (${sanitizedQuery})`;\n const result = await conn.query(countQuery);\n setCount(getColValAsNumber(result));\n } catch (error) {\n console.error('Error fetching count:', error);\n } finally {\n setIsFetching(false);\n }\n };\n\n fetchCount();\n }, [conn, sanitizedQuery]);\n\n // Fetch data\n useEffect(() => {\n const fetchData = async () => {\n try {\n setIsFetching(true);\n const result = await conn.query(\n `SELECT * FROM (\n ${sanitizedQuery}\n ) ${\n sorting.length > 0\n ? `ORDER BY ${sorting\n .map((d) => `${escapeId(d.id)}${d.desc ? ' DESC' : ''}`)\n .join(', ')}`\n : ''\n }\n OFFSET ${pagination.pageIndex * pagination.pageSize}\n LIMIT ${pagination.pageSize}`,\n );\n setData(result);\n } catch (error) {\n console.error('Error fetching data:', error);\n } finally {\n setIsFetching(false);\n }\n };\n\n fetchData();\n }, [pagination, sorting, conn, sanitizedQuery]);\n\n const arrowTableData = useArrowDataTable(data);\n\n const handleExport = async () => {\n if (!query) return;\n try {\n setIsExporting(true);\n await exportToCsv(query, `export-${genRandomStr(5)}.csv`);\n } finally {\n setIsExporting(false);\n }\n };\n\n return (\n <DataTablePaginated\n {...arrowTableData}\n pageCount={Math.ceil((count ?? 0) / pagination.pageSize)}\n numRows={count}\n isFetching={isFetching}\n pagination={pagination}\n onPaginationChange={setPagination}\n sorting={sorting}\n onSortingChange={setSorting}\n onExport={handleExport}\n isExporting={isExporting}\n />\n );\n};\n\nconst QueryDataTableWithSuspense: FC<QueryDataTableProps> = (props) => {\n return (\n <Suspense fallback={<SpinnerPane className=\"w-full h-full\" />}>\n <QueryDataTable\n {...props}\n key={props.query} // reset state when query changes\n />\n </Suspense>\n );\n};\n\nexport default QueryDataTableWithSuspense;\n"]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAC,OAAO,IAAI,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAC,OAAO,IAAI,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAC,OAAO,IAAI,iBAAiB,EAAC,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAC,OAAO,IAAI,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAC,OAAO,IAAI,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAC,OAAO,IAAI,iBAAiB,EAAC,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAC,OAAO,IAAI,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAC,OAAO,IAAI,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAC,OAAO,IAAI,iBAAiB,EAAC,MAAM,qBAAqB,CAAC","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAC,OAAO,IAAI,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAC,OAAO,IAAI,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAC,OAAO,IAAI,iBAAiB,EAAC,MAAM,qBAAqB,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {default as DataTableModal} from './DataTableModal';\nexport * from './DataTablePaginated';\nexport {default as DataTablePaginated} from './DataTablePaginated';\nexport {default as DataTableVirtualized} from './DataTableVirtualized';\nexport {default as QueryDataTable} from './QueryDataTable';\nexport {default as useArrowDataTable} from './useArrowDataTable';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/data-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@heroicons/react": "*",
|
|
23
|
-
"@sqlrooms/duckdb": "0.
|
|
24
|
-
"@sqlrooms/ui": "0.
|
|
25
|
-
"@sqlrooms/utils": "0.
|
|
23
|
+
"@sqlrooms/duckdb": "0.8.0",
|
|
24
|
+
"@sqlrooms/ui": "0.8.0",
|
|
25
|
+
"@sqlrooms/utils": "0.8.0",
|
|
26
26
|
"@tanstack/react-table": "^8.10.7",
|
|
27
27
|
"@tanstack/table-core": "^8.10.7",
|
|
28
28
|
"react-virtual": "2.10.4"
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"lint": "eslint .",
|
|
39
39
|
"typedoc": "typedoc"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "99b46a96ab900e6b005bcd30cfbfe7b3c9d51f8d"
|
|
42
42
|
}
|