@sqlrooms/data-table 0.26.1-rc.7 → 0.27.0-rc.1

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/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright 2025 Ilya Boyandin
3
+ Copyright 2025 SQLRooms Contributors
4
4
 
5
5
  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:
6
6
 
@@ -1,11 +1,15 @@
1
1
  import * as arrow from 'apache-arrow';
2
2
  import { FC } from 'react';
3
3
  import { DataTablePaginatedProps } from './DataTablePaginated';
4
- export declare const DataTableArrowPaginated: FC<{
4
+ import { ArrowDataTableValueFormatter } from './useArrowDataTable';
5
+ export type DataTableArrowPaginatedProps = {
5
6
  className?: string;
6
7
  table: arrow.Table | undefined;
7
8
  fontSize?: DataTablePaginatedProps<any>['fontSize'];
8
9
  footerActions?: DataTablePaginatedProps<any>['footerActions'];
9
10
  pageSize?: number;
10
- }>;
11
+ /** Optional custom value formatter for binary/geometry data */
12
+ formatValue?: ArrowDataTableValueFormatter;
13
+ };
14
+ export declare const DataTableArrowPaginated: FC<DataTableArrowPaginatedProps>;
11
15
  //# sourceMappingURL=DataTableArrowPaginated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTableArrowPaginated.d.ts","sourceRoot":"","sources":["../src/DataTableArrowPaginated.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,EAAE,EAAoB,MAAM,OAAO,CAAC;AAC5C,OAA2B,EACzB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAI9B,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CA8BA,CAAC"}
1
+ {"version":3,"file":"DataTableArrowPaginated.d.ts","sourceRoot":"","sources":["../src/DataTableArrowPaginated.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,EAAE,EAAoB,MAAM,OAAO,CAAC;AAC5C,OAA2B,EACzB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAC9B,OAA0B,EAAC,4BAA4B,EAAC,MAAM,qBAAqB,CAAC;AAGpF,MAAM,MAAM,4BAA4B,GAAG;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,4BAA4B,CAAC;CAC5C,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,4BAA4B,CAqCpE,CAAC"}
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from 'react';
3
3
  import DataTablePaginated from './DataTablePaginated';
4
4
  import useArrowDataTable from './useArrowDataTable';
5
- export const DataTableArrowPaginated = ({ className, table, fontSize, footerActions, pageSize = 100 }) => {
5
+ export const DataTableArrowPaginated = ({ className, table, fontSize, footerActions, pageSize = 100, formatValue, }) => {
6
6
  const [pagination, setPagination] = useState(
7
7
  // If the table has less than pageSize rows, don't show pagination.
8
8
  table?.numRows && table.numRows <= pageSize
@@ -15,7 +15,7 @@ export const DataTableArrowPaginated = ({ className, table, fontSize, footerActi
15
15
  const endIndex = startIndex + pagination.pageSize;
16
16
  return table.slice(startIndex, endIndex);
17
17
  }, [table, pagination]);
18
- const adt = useArrowDataTable(pageData);
18
+ const adt = useArrowDataTable(pageData, { formatValue });
19
19
  if (!adt) {
20
20
  return _jsx("div", { className: "p-4 text-xs", children: "No data" });
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DataTableArrowPaginated.js","sourceRoot":"","sources":["../src/DataTableArrowPaginated.tsx"],"names":[],"mappings":";AACA,OAAO,EAAK,OAAO,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAC5C,OAAO,kBAEN,MAAM,sBAAsB,CAAC;AAC9B,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AAGpD,MAAM,CAAC,MAAM,uBAAuB,GAM/B,CAAC,EAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,GAAG,GAAG,EAAC,EAAE,EAAE;IACnE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ;IAC1C,mEAAmE;IACnE,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,QAAQ;QACzC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,EAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAC,CAC7B,CAAC;IACF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE;QAC5B,IAAI,CAAC,KAAK,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QACxC,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC;QAClD,OAAO,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAExB,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,cAAK,SAAS,EAAC,aAAa,wBAAc,CAAC;IACpD,CAAC;IACD,OAAO,CACL,KAAC,kBAAkB,IACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,GAAG,CAAC,IAAI,EACd,OAAO,EAAE,GAAG,CAAC,OAAO,EACpB,OAAO,EAAE,KAAK,EAAE,OAAO,EACvB,UAAU,EAAE,UAAU,EACtB,kBAAkB,EAAE,aAAa,EACjC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,aAAa,GAC5B,CACH,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import * as arrow from 'apache-arrow';\nimport {FC, useMemo, useState} from 'react';\nimport DataTablePaginated, {\n DataTablePaginatedProps,\n} from './DataTablePaginated';\nimport useArrowDataTable from './useArrowDataTable';\nimport {PaginationState} from '@tanstack/react-table';\n\nexport const DataTableArrowPaginated: FC<{\n className?: string;\n table: arrow.Table | undefined;\n fontSize?: DataTablePaginatedProps<any>['fontSize'];\n footerActions?: DataTablePaginatedProps<any>['footerActions'];\n pageSize?: number;\n}> = ({className, table, fontSize, footerActions, pageSize = 100}) => {\n const [pagination, setPagination] = useState<PaginationState | undefined>(\n // If the table has less than pageSize rows, don't show pagination.\n table?.numRows && table.numRows <= pageSize\n ? undefined\n : {pageIndex: 0, pageSize},\n );\n const pageData = useMemo(() => {\n if (!table || !pagination) return table;\n const startIndex = pagination.pageIndex * pagination.pageSize;\n const endIndex = startIndex + pagination.pageSize;\n return table.slice(startIndex, endIndex);\n }, [table, pagination]);\n\n const adt = useArrowDataTable(pageData);\n if (!adt) {\n return <div className=\"p-4 text-xs\">No data</div>;\n }\n return (\n <DataTablePaginated\n className={className}\n data={adt.data}\n columns={adt.columns}\n numRows={table?.numRows}\n pagination={pagination}\n onPaginationChange={setPagination}\n fontSize={fontSize}\n footerActions={footerActions}\n />\n );\n};\n"]}
1
+ {"version":3,"file":"DataTableArrowPaginated.js","sourceRoot":"","sources":["../src/DataTableArrowPaginated.tsx"],"names":[],"mappings":";AACA,OAAO,EAAK,OAAO,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAC5C,OAAO,kBAEN,MAAM,sBAAsB,CAAC;AAC9B,OAAO,iBAAiD,MAAM,qBAAqB,CAAC;AAapF,MAAM,CAAC,MAAM,uBAAuB,GAAqC,CAAC,EACxE,SAAS,EACT,KAAK,EACL,QAAQ,EACR,aAAa,EACb,QAAQ,GAAG,GAAG,EACd,WAAW,GACZ,EAAE,EAAE;IACH,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ;IAC1C,mEAAmE;IACnE,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,QAAQ;QACzC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,EAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAC,CAC7B,CAAC;IACF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE;QAC5B,IAAI,CAAC,KAAK,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QACxC,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC;QAClD,OAAO,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAExB,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,EAAE,EAAC,WAAW,EAAC,CAAC,CAAC;IACvD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,cAAK,SAAS,EAAC,aAAa,wBAAc,CAAC;IACpD,CAAC;IACD,OAAO,CACL,KAAC,kBAAkB,IACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,GAAG,CAAC,IAAI,EACd,OAAO,EAAE,GAAG,CAAC,OAAO,EACpB,OAAO,EAAE,KAAK,EAAE,OAAO,EACvB,UAAU,EAAE,UAAU,EACtB,kBAAkB,EAAE,aAAa,EACjC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,aAAa,GAC5B,CACH,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import * as arrow from 'apache-arrow';\nimport {FC, useMemo, useState} from 'react';\nimport DataTablePaginated, {\n DataTablePaginatedProps,\n} from './DataTablePaginated';\nimport useArrowDataTable, {ArrowDataTableValueFormatter} from './useArrowDataTable';\nimport {PaginationState} from '@tanstack/react-table';\n\nexport type DataTableArrowPaginatedProps = {\n className?: string;\n table: arrow.Table | undefined;\n fontSize?: DataTablePaginatedProps<any>['fontSize'];\n footerActions?: DataTablePaginatedProps<any>['footerActions'];\n pageSize?: number;\n /** Optional custom value formatter for binary/geometry data */\n formatValue?: ArrowDataTableValueFormatter;\n};\n\nexport const DataTableArrowPaginated: FC<DataTableArrowPaginatedProps> = ({\n className,\n table,\n fontSize,\n footerActions,\n pageSize = 100,\n formatValue,\n}) => {\n const [pagination, setPagination] = useState<PaginationState | undefined>(\n // If the table has less than pageSize rows, don't show pagination.\n table?.numRows && table.numRows <= pageSize\n ? undefined\n : {pageIndex: 0, pageSize},\n );\n const pageData = useMemo(() => {\n if (!table || !pagination) return table;\n const startIndex = pagination.pageIndex * pagination.pageSize;\n const endIndex = startIndex + pagination.pageSize;\n return table.slice(startIndex, endIndex);\n }, [table, pagination]);\n\n const adt = useArrowDataTable(pageData, {formatValue});\n if (!adt) {\n return <div className=\"p-4 text-xs\">No data</div>;\n }\n return (\n <DataTablePaginated\n className={className}\n data={adt.data}\n columns={adt.columns}\n numRows={table?.numRows}\n pagination={pagination}\n onPaginationChange={setPagination}\n fontSize={fontSize}\n footerActions={footerActions}\n />\n );\n};\n"]}
@@ -1,6 +1,7 @@
1
1
  import { UseDisclosureReturnValue } from '@sqlrooms/ui';
2
2
  import { FC } from 'react';
3
3
  import * as arrow from 'apache-arrow';
4
+ import { ArrowDataTableValueFormatter } from './useArrowDataTable';
4
5
  /**
5
6
  * A modal component for displaying a table with data from a SQL query.
6
7
  *
@@ -27,14 +28,19 @@ import * as arrow from 'apache-arrow';
27
28
  * };
28
29
  * ```
29
30
  */
30
- declare const DataTableModal: FC<{
31
+ export type DataTableModalProps = {
31
32
  className?: string;
32
33
  title: string | undefined;
33
34
  tableModal: Pick<UseDisclosureReturnValue, 'isOpen' | 'onClose'>;
35
+ /** Optional custom value formatter for binary/geometry data */
36
+ formatValue?: ArrowDataTableValueFormatter;
34
37
  } & ({
35
38
  query: string | undefined;
39
+ arrowTable?: never;
36
40
  } | {
37
41
  arrowTable: arrow.Table | undefined;
38
- })>;
42
+ query?: never;
43
+ });
44
+ declare const DataTableModal: FC<DataTableModalProps>;
39
45
  export default DataTableModal;
40
46
  //# sourceMappingURL=DataTableModal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTableModal.d.ts","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,wBAAwB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAEzB,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,cAAc,EAAE,EAAE,CACtB;IACE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC,wBAAwB,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;CAClE,GAAG,CACA;IACE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,GACD;IACE,UAAU,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;CACrC,CACJ,CAsCF,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"DataTableModal.d.ts","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,wBAAwB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAEzB,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAC,4BAA4B,EAAC,MAAM,qBAAqB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC,wBAAwB,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;IACjE,+DAA+D;IAC/D,WAAW,CAAC,EAAE,4BAA4B,CAAC;CAC5C,GAAG,CACA;IACE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC;CACpB,GACD;IACE,UAAU,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CACJ,CAAC;AAEF,QAAA,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAqC3C,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -2,35 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { Button, cn, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@sqlrooms/ui';
3
3
  import QueryDataTable from './QueryDataTable';
4
4
  import { DataTableArrowPaginated } from './DataTableArrowPaginated';
5
- /**
6
- * A modal component for displaying a table with data from a SQL query.
7
- *
8
- * @component
9
- * @param props - Component props
10
- * @param props.title - The title of the table
11
- * @param props.query - The SQL query to execute and display in the table
12
- * @param props.tableModal - An object containing the modal's open state and close function
13
- *
14
- * @example
15
- * ```tsx
16
- * import { useState } from 'react';
17
- * import { DataTableModal } from '@sqlrooms/data-table';
18
- *
19
- * const MyComponent = () => {
20
- * const tableModal = useDisclosure();
21
- * return (
22
- * <DataTableModal
23
- * title="Users"
24
- * query="SELECT * FROM users LIMIT 10"
25
- * tableModal={tableModal}
26
- * />
27
- * );
28
- * };
29
- * ```
30
- */
31
5
  const DataTableModal = (props) => {
32
- const { className, title, tableModal } = props;
33
- return (_jsx(Dialog, { open: tableModal.isOpen, onOpenChange: (isOpen) => !isOpen && tableModal.onClose(), children: _jsxs(DialogContent, { className: cn('h-[80vh] max-w-[75vw]', className), "aria-describedby": "data-table-modal", onClick: (e) => e.stopPropagation(), children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title ?? '' }), _jsx(DialogDescription, { className: "hidden", children: title })] }), _jsx("div", { className: "bg-muted flex-1 overflow-hidden", children: tableModal.isOpen && (_jsx(_Fragment, { children: 'query' in props && props.query ? (_jsx(QueryDataTable, { query: props.query })) : 'arrowTable' in props && props.arrowTable ? (_jsx(DataTableArrowPaginated, { table: props.arrowTable })) : (_jsx("div", { className: "p-4 text-xs", children: "No data" })) })) }), _jsx(DialogFooter, { children: _jsx(Button, { variant: "outline", onClick: tableModal.onClose, children: "Close" }) })] }) }));
6
+ const { className, title, tableModal, formatValue } = props;
7
+ return (_jsx(Dialog, { open: tableModal.isOpen, onOpenChange: (isOpen) => !isOpen && tableModal.onClose(), children: _jsxs(DialogContent, { className: cn('h-[80vh] max-w-[75vw]', className), "aria-describedby": "data-table-modal", onClick: (e) => e.stopPropagation(), children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title ?? '' }), _jsx(DialogDescription, { className: "hidden", children: title })] }), _jsx("div", { className: "bg-muted flex-1 overflow-hidden", children: tableModal.isOpen && (_jsx(_Fragment, { children: 'query' in props && props.query ? (_jsx(QueryDataTable, { query: props.query, formatValue: formatValue })) : 'arrowTable' in props && props.arrowTable ? (_jsx(DataTableArrowPaginated, { table: props.arrowTable, formatValue: formatValue })) : (_jsx("div", { className: "p-4 text-xs", children: "No data" })) })) }), _jsx(DialogFooter, { children: _jsx(Button, { variant: "outline", onClick: tableModal.onClose, children: "Close" }) })] }) }));
34
8
  };
35
9
  export default DataTableModal;
36
10
  //# sourceMappingURL=DataTableModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTableModal.js","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,EAAE,EACF,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GAEZ,MAAM,cAAc,CAAC;AAEtB,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAC,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,cAAc,GAahB,CAAC,KAAK,EAAE,EAAE;IACZ,MAAM,EAAC,SAAS,EAAE,KAAK,EAAE,UAAU,EAAC,GAAG,KAAK,CAAC;IAC7C,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,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,sBAChC,kBAAkB,EACnC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,aAEnC,MAAC,YAAY,eACX,KAAC,WAAW,cAAE,KAAK,IAAI,EAAE,GAAe,EACxC,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,YAAE,KAAK,GAAqB,IACpD,EACf,cAAK,SAAS,EAAC,iCAAiC,YAC7C,UAAU,CAAC,MAAM,IAAI,CACpB,4BACG,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CACjC,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAI,CACvC,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAC9C,KAAC,uBAAuB,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAI,CACrD,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAC,aAAa,wBAAc,CAC3C,GACA,CACJ,GACG,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 cn,\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';\nimport * as arrow from 'apache-arrow';\nimport {DataTableArrowPaginated} from './DataTableArrowPaginated';\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 {\n className?: string;\n title: string | undefined;\n tableModal: Pick<UseDisclosureReturnValue, 'isOpen' | 'onClose'>;\n } & (\n | {\n query: string | undefined;\n }\n | {\n arrowTable: arrow.Table | undefined;\n }\n )\n> = (props) => {\n const {className, title, tableModal} = props;\n return (\n <Dialog\n open={tableModal.isOpen}\n onOpenChange={(isOpen: boolean) => !isOpen && tableModal.onClose()}\n >\n <DialogContent\n className={cn('h-[80vh] max-w-[75vw]', className)}\n aria-describedby=\"data-table-modal\"\n onClick={(e) => e.stopPropagation()}\n >\n <DialogHeader>\n <DialogTitle>{title ?? ''}</DialogTitle>\n <DialogDescription className=\"hidden\">{title}</DialogDescription>\n </DialogHeader>\n <div className=\"bg-muted flex-1 overflow-hidden\">\n {tableModal.isOpen && (\n <>\n {'query' in props && props.query ? (\n <QueryDataTable query={props.query} />\n ) : 'arrowTable' in props && props.arrowTable ? (\n <DataTableArrowPaginated table={props.arrowTable} />\n ) : (\n <div className=\"p-4 text-xs\">No data</div>\n )}\n </>\n )}\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
+ {"version":3,"file":"DataTableModal.js","sourceRoot":"","sources":["../src/DataTableModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,EAAE,EACF,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GAEZ,MAAM,cAAc,CAAC;AAEtB,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAC,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AA8ClE,MAAM,cAAc,GAA4B,CAAC,KAAK,EAAE,EAAE;IACxD,MAAM,EAAC,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAC,GAAG,KAAK,CAAC;IAC1D,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,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,sBAChC,kBAAkB,EACnC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,aAEnC,MAAC,YAAY,eACX,KAAC,WAAW,cAAE,KAAK,IAAI,EAAE,GAAe,EACxC,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,YAAE,KAAK,GAAqB,IACpD,EACf,cAAK,SAAS,EAAC,iCAAiC,YAC7C,UAAU,CAAC,MAAM,IAAI,CACpB,4BACG,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CACjC,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,GAAI,CACjE,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAC9C,KAAC,uBAAuB,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,WAAW,EAAE,WAAW,GAAI,CAC/E,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAC,aAAa,wBAAc,CAC3C,GACA,CACJ,GACG,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 cn,\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';\nimport * as arrow from 'apache-arrow';\nimport {DataTableArrowPaginated} from './DataTableArrowPaginated';\nimport {ArrowDataTableValueFormatter} from './useArrowDataTable';\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 */\nexport type DataTableModalProps = {\n className?: string;\n title: string | undefined;\n tableModal: Pick<UseDisclosureReturnValue, 'isOpen' | 'onClose'>;\n /** Optional custom value formatter for binary/geometry data */\n formatValue?: ArrowDataTableValueFormatter;\n} & (\n | {\n query: string | undefined;\n arrowTable?: never;\n }\n | {\n arrowTable: arrow.Table | undefined;\n query?: never;\n }\n);\n\nconst DataTableModal: FC<DataTableModalProps> = (props) => {\n const {className, title, tableModal, formatValue} = props;\n return (\n <Dialog\n open={tableModal.isOpen}\n onOpenChange={(isOpen: boolean) => !isOpen && tableModal.onClose()}\n >\n <DialogContent\n className={cn('h-[80vh] max-w-[75vw]', className)}\n aria-describedby=\"data-table-modal\"\n onClick={(e) => e.stopPropagation()}\n >\n <DialogHeader>\n <DialogTitle>{title ?? ''}</DialogTitle>\n <DialogDescription className=\"hidden\">{title}</DialogDescription>\n </DialogHeader>\n <div className=\"bg-muted flex-1 overflow-hidden\">\n {tableModal.isOpen && (\n <>\n {'query' in props && props.query ? (\n <QueryDataTable query={props.query} formatValue={formatValue} />\n ) : 'arrowTable' in props && props.arrowTable ? (\n <DataTableArrowPaginated table={props.arrowTable} formatValue={formatValue} />\n ) : (\n <div className=\"p-4 text-xs\">No data</div>\n )}\n </>\n )}\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":"DataTablePaginated.d.ts","sourceRoot":"","sources":["../src/DataTablePaginated.tsx"],"names":[],"mappings":"AA4BA,OAAO,EACL,SAAS,EACT,eAAe,EACf,YAAY,EACZ,GAAG,EAKJ,MAAM,uBAAuB,CAAC;AAI/B,MAAM,MAAM,uBAAuB,CAAC,IAAI,SAAS,MAAM,IAAI;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACnC,OAAO,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,SAAS,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3D,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAClD;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;KAC9C,KAAK,IAAI,CAAC;IACX;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;KAC9C,KAAK,IAAI,CAAC;CACZ,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,IAAI,SAAS,MAAM,EAAE,EAC9D,SAAS,EACT,QAAoB,EACpB,IAAI,EACJ,OAAO,EACP,OAAO,EACP,UAAU,EACV,OAAO,EACP,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,gBAAgB,GACjB,EAAE,uBAAuB,CAAC,IAAI,CAAC,2CAqP/B"}
1
+ {"version":3,"file":"DataTablePaginated.d.ts","sourceRoot":"","sources":["../src/DataTablePaginated.tsx"],"names":[],"mappings":"AA6BA,OAAO,EACL,SAAS,EACT,eAAe,EACf,YAAY,EACZ,GAAG,EAKJ,MAAM,uBAAuB,CAAC;AAI/B,MAAM,MAAM,uBAAuB,CAAC,IAAI,SAAS,MAAM,IAAI;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACnC,OAAO,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,SAAS,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3D,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAClD;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;KAC9C,KAAK,IAAI,CAAC;IACX;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;KAC9C,KAAK,IAAI,CAAC;CACZ,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,IAAI,SAAS,MAAM,EAAE,EAC9D,SAAS,EACT,QAAoB,EACpB,IAAI,EACJ,OAAO,EACP,OAAO,EACP,UAAU,EACV,OAAO,EACP,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,gBAAgB,GACjB,EAAE,uBAAuB,CAAC,IAAI,CAAC,2CAwP/B"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { ChevronDownIcon, ChevronUpIcon, ChevronsLeftIcon as ChevronDoubleLeftIcon, ChevronsRightIcon as ChevronDoubleRightIcon, ChevronLeftIcon, ChevronRightIcon, } from 'lucide-react';
3
- import { Button, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Badge, cn, ScrollArea, ScrollBar, } from '@sqlrooms/ui';
3
+ import { Button, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Badge, cn, ScrollArea, ScrollBar, resolveFontSizeClass, } from '@sqlrooms/ui';
4
4
  import { formatCount } from '@sqlrooms/utils';
5
5
  import { flexRender, getCoreRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table';
6
6
  import { useEffect, useMemo, useState } from 'react';
@@ -11,6 +11,7 @@ import { useEffect, useMemo, useState } from 'react';
11
11
  */
12
12
  export default function DataTablePaginated({ className, fontSize = 'text-xs', data, columns, numRows, pagination, sorting, onPaginationChange, onSortingChange, footerActions, isFetching, onRowClick, onRowDoubleClick, }) {
13
13
  const defaultData = useMemo(() => [], []);
14
+ const fontSizeClass = resolveFontSizeClass(fontSize);
14
15
  const pageCount = pagination && numRows !== undefined
15
16
  ? Math.ceil(numRows / pagination.pageSize)
16
17
  : undefined;
@@ -40,22 +41,22 @@ export default function DataTablePaginated({ className, fontSize = 'text-xs', da
40
41
  useEffect(() => {
41
42
  setInternalPageIndex(pagination?.pageIndex ?? 0);
42
43
  }, [pagination?.pageIndex]);
43
- return (_jsxs("div", { className: cn(`relative flex h-full w-full flex-col`, className), children: [_jsx("div", { className: "border-border flex-1 overflow-hidden border font-mono", children: _jsxs(ScrollArea, { className: "h-full overflow-auto", children: [_jsxs(Table, { disableWrapper: true, children: [_jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => (_jsxs(TableRow, { children: [_jsx(TableHead, { className: `bg-background sticky left-0 top-[-1px] z-10 w-auto whitespace-nowrap border-r py-2 text-center`, children: isFetching ? (_jsx("div", { className: "border-primary h-4 w-4 animate-spin rounded-full border-2 border-t-transparent" })) : null }), headerGroup.headers.map((header) => {
44
+ return (_jsxs("div", { className: cn(`relative flex h-full w-full flex-col`, className), children: [_jsx("div", { className: "border-border flex-1 overflow-hidden border font-mono", children: _jsxs(ScrollArea, { className: "h-full overflow-auto", children: [_jsxs(Table, { disableWrapper: true, children: [_jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => (_jsxs(TableRow, { children: [_jsx(TableHead, { className: `bg-background sticky top-[-1px] left-0 z-10 w-auto border-r py-2 text-center whitespace-nowrap`, children: isFetching ? (_jsx("div", { className: "border-primary h-4 w-4 animate-spin rounded-full border-2 border-t-transparent" })) : null }), headerGroup.headers.map((header) => {
44
45
  const meta = header.column.columnDef
45
46
  .meta;
46
- return (_jsx(TableHead, { colSpan: header.colSpan, className: cn('bg-background hover:bg-muted sticky top-[-1px] z-10 w-auto whitespace-nowrap border-r py-2', pagination ? 'cursor-pointer' : '', meta?.isNumeric ? 'text-right' : 'text-left', fontSize), onClick: header.column.getToggleSortingHandler(), children: _jsxs("div", { className: "flex items-center gap-2", children: [header.isPlaceholder ? null : (_jsx("div", { children: flexRender(header.column.columnDef.header, header.getContext()) })), header.column.getIsSorted() ? (header.column.getIsSorted() === 'desc' ? (_jsx(ChevronDownIcon, { className: "h-4 w-4" })) : (_jsx(ChevronUpIcon, { className: "h-4 w-4" }))) : null, _jsx("div", { className: "flex-1" }), _jsx(Badge, { variant: "outline", className: `max-w-[400px] truncate text-xs opacity-30`, children: String(meta?.type) })] }) }, header.id));
47
- }), _jsx(TableHead, { className: "bg-background sticky top-0 w-full whitespace-nowrap border-r border-t py-2" })] }, headerGroup.id))) }), _jsx(TableBody, { children: table.getRowModel().rows.map((row, i) => (_jsxs(TableRow, { className: "hover:bg-muted bg-background", onClick: (event) => {
47
+ return (_jsx(TableHead, { colSpan: header.colSpan, className: cn('bg-background hover:bg-muted sticky top-[-1px] z-10 w-auto border-r py-2 whitespace-nowrap', pagination ? 'cursor-pointer' : '', meta?.isNumeric ? 'text-right' : 'text-left', fontSizeClass), onClick: header.column.getToggleSortingHandler(), children: _jsxs("div", { className: "flex items-center gap-2", children: [header.isPlaceholder ? null : (_jsx("div", { children: flexRender(header.column.columnDef.header, header.getContext()) })), header.column.getIsSorted() ? (header.column.getIsSorted() === 'desc' ? (_jsx(ChevronDownIcon, { className: "h-4 w-4" })) : (_jsx(ChevronUpIcon, { className: "h-4 w-4" }))) : null, _jsx("div", { className: "flex-1" }), _jsx(Badge, { variant: "outline", className: `max-w-[400px] truncate text-xs opacity-30`, children: String(meta?.type) })] }) }, header.id));
48
+ }), _jsx(TableHead, { className: "bg-background sticky top-0 w-full border-t border-r py-2 whitespace-nowrap" })] }, headerGroup.id))) }), _jsx(TableBody, { children: table.getRowModel().rows.map((row, i) => (_jsxs(TableRow, { className: "hover:bg-muted bg-background", onClick: (event) => {
48
49
  event.preventDefault();
49
50
  onRowClick?.({ row: row, event });
50
51
  }, onDoubleClick: (event) => {
51
52
  event.preventDefault();
52
53
  onRowDoubleClick?.({ row: row, event });
53
- }, children: [_jsx(TableCell, { className: `bg-background text-muted-foreground sticky left-0 border-r text-center ${fontSize}`, children: pagination
54
+ }, children: [_jsx(TableCell, { className: `bg-background text-muted-foreground sticky left-0 border-r text-center ${fontSizeClass}`, children: pagination
54
55
  ? `${pagination.pageIndex * pagination.pageSize + i + 1}`
55
56
  : `${i + 1}` }), row.getVisibleCells().map((cell) => {
56
57
  const meta = cell.column.columnDef.meta;
57
- return (_jsx(TableCell, { className: cn('max-w-[500px] overflow-hidden truncate border-r px-7', fontSize, meta?.isNumeric ? 'text-right' : 'text-left'), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
58
- }), _jsx(TableCell, { className: "border-r", children: "\u00A0" })] }, row.id))) })] }), _jsx(ScrollBar, { orientation: "vertical", className: "z-50" }), _jsx(ScrollBar, { orientation: "horizontal" })] }) }), pagination || footerActions ? (_jsxs("div", { className: "bg-background sticky bottom-0 left-0 flex flex-wrap items-center gap-2 border border-t-0 p-2", children: [pagination ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Button, { variant: "outline", size: "icon", onClick: () => table.setPageIndex(0), disabled: !table.getCanPreviousPage(), children: _jsx(ChevronDoubleLeftIcon, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "outline", size: "icon", onClick: () => table.previousPage(), disabled: !table.getCanPreviousPage(), children: _jsx(ChevronLeftIcon, { className: "h-4 w-4" }) }), _jsxs("div", { className: `ml-1 flex items-center gap-1 ${fontSize}`, children: [_jsx("div", { children: "Page" }), _jsx(Input, { type: "number", min: 1, max: table.getPageCount(), className: "h-8 w-16", value: internalPageIndex + 1, onChange: (e) => {
58
+ return (_jsx(TableCell, { className: cn('max-w-[500px] truncate overflow-hidden border-r px-7', fontSizeClass, meta?.isNumeric ? 'text-right' : 'text-left'), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
59
+ }), _jsx(TableCell, { className: "border-r", children: "\u00A0" })] }, row.id))) })] }), _jsx(ScrollBar, { orientation: "vertical", className: "z-50" }), _jsx(ScrollBar, { orientation: "horizontal" })] }) }), pagination || footerActions ? (_jsxs("div", { className: "bg-background sticky bottom-0 left-0 flex flex-wrap items-center gap-2 border border-t-0 p-2", children: [pagination ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Button, { variant: "outline", size: "icon", onClick: () => table.setPageIndex(0), disabled: !table.getCanPreviousPage(), children: _jsx(ChevronDoubleLeftIcon, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "outline", size: "icon", onClick: () => table.previousPage(), disabled: !table.getCanPreviousPage(), children: _jsx(ChevronLeftIcon, { className: "h-4 w-4" }) }), _jsxs("div", { className: `ml-1 flex items-center gap-1 ${fontSizeClass}`, children: [_jsx("div", { children: "Page" }), _jsx(Input, { type: "number", min: 1, max: table.getPageCount(), className: "h-8 w-16", value: internalPageIndex + 1, onChange: (e) => {
59
60
  const value = e.target.value;
60
61
  if (value) {
61
62
  const page = Math.max(0, Math.min(table.getPageCount() - 1, Number(value) - 1));
@@ -65,6 +66,6 @@ export default function DataTablePaginated({ className, fontSize = 'text-xs', da
65
66
  if (internalPageIndex !== pagination?.pageIndex) {
66
67
  table.setPageIndex(internalPageIndex);
67
68
  }
68
- } }), _jsx("div", { children: `of ${formatCount(table.getPageCount())}` })] }), _jsx(Button, { variant: "outline", size: "icon", onClick: () => table.nextPage(), disabled: !table.getCanNextPage(), children: _jsx(ChevronRightIcon, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "outline", size: "icon", onClick: () => table.setPageIndex(table.getPageCount() - 1), disabled: !table.getCanNextPage(), children: _jsx(ChevronDoubleRightIcon, { className: "h-4 w-4" }) }), _jsxs(Select, { value: String(table.getState().pagination.pageSize), onValueChange: (value) => table.setPageSize(Number(value)), children: [_jsx(SelectTrigger, { className: "h-8 w-[110px]", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: [10, 50, 100, 500, 1000].map((pageSize) => (_jsx(SelectItem, { value: String(pageSize), children: `${pageSize} rows` }, pageSize))) })] })] }), _jsx("div", { className: "flex-1" })] })) : null, _jsx(_Fragment, { children: numRows !== undefined && isFinite(numRows) ? (_jsx("div", { className: `font-normal ${fontSize}`, children: `${formatCount(numRows)} rows` })) : null }), footerActions] })) : null, isFetching ? (_jsx("div", { className: "bg-background/80 absolute inset-0 animate-pulse" })) : null] }));
69
+ } }), _jsx("div", { children: `of ${formatCount(table.getPageCount())}` })] }), _jsx(Button, { variant: "outline", size: "icon", onClick: () => table.nextPage(), disabled: !table.getCanNextPage(), children: _jsx(ChevronRightIcon, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "outline", size: "icon", onClick: () => table.setPageIndex(table.getPageCount() - 1), disabled: !table.getCanNextPage(), children: _jsx(ChevronDoubleRightIcon, { className: "h-4 w-4" }) }), _jsxs(Select, { value: String(table.getState().pagination.pageSize), onValueChange: (value) => table.setPageSize(Number(value)), children: [_jsx(SelectTrigger, { className: "h-8 w-[110px]", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: [10, 50, 100, 500, 1000].map((pageSize) => (_jsx(SelectItem, { value: String(pageSize), children: `${pageSize} rows` }, pageSize))) })] })] }), _jsx("div", { className: "flex-1" })] })) : null, _jsx(_Fragment, { children: numRows !== undefined && isFinite(numRows) ? (_jsx("div", { className: `font-normal ${fontSizeClass}`, children: `${formatCount(numRows)} rows` })) : null }), footerActions] })) : null, isFetching ? (_jsx("div", { className: "bg-background/80 absolute inset-0 animate-pulse" })) : null] }));
69
70
  }
70
71
  //# sourceMappingURL=DataTablePaginated.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTablePaginated.js","sourceRoot":"","sources":["../src/DataTablePaginated.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n ChevronDownIcon,\n ChevronUpIcon,\n ChevronsLeftIcon as ChevronDoubleLeftIcon,\n ChevronsRightIcon as ChevronDoubleRightIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from 'lucide-react';\nimport {\n Button,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Badge,\n cn,\n ScrollArea,\n ScrollBar,\n} from '@sqlrooms/ui';\nimport {formatCount} from '@sqlrooms/utils';\nimport {\n ColumnDef,\n PaginationState,\n SortingState,\n Row,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable,\n} from '@tanstack/react-table';\nimport {useEffect, useMemo, useState} from 'react';\nimport {ArrowColumnMeta} from './useArrowDataTable';\n\nexport type DataTablePaginatedProps<Data extends object> = {\n className?: string;\n /** Custom font size for the table e.g. text-xs, text-sm, text-md, text-lg, text-base */\n fontSize?: string;\n data?: ArrayLike<Data> | undefined;\n columns?: ColumnDef<Data, any>[] | undefined;\n pageCount?: number | undefined;\n numRows?: number | undefined;\n isFetching?: boolean;\n pagination?: PaginationState | undefined;\n sorting?: SortingState;\n footerActions?: React.ReactNode;\n onPaginationChange?: (pagination: PaginationState) => void;\n onSortingChange?: (sorting: SortingState) => void;\n /**\n * Called when a row is clicked.\n */\n onRowClick?: (args: {\n row: Row<Data>;\n event: React.MouseEvent<HTMLTableRowElement>;\n }) => void;\n /**\n * Called when a row is double-clicked.\n */\n onRowDoubleClick?: (args: {\n row: Row<Data>;\n event: React.MouseEvent<HTMLTableRowElement>;\n }) => void;\n};\n\n/**\n * Data table with pagination, sorting, and custom actions.\n * @param props\n * @returns\n */\nexport default function DataTablePaginated<Data extends object>({\n className,\n fontSize = 'text-xs',\n data,\n columns,\n numRows,\n pagination,\n sorting,\n onPaginationChange,\n onSortingChange,\n footerActions,\n isFetching,\n onRowClick,\n onRowDoubleClick,\n}: DataTablePaginatedProps<Data>) {\n const defaultData = useMemo(() => [], []);\n const pageCount =\n pagination && numRows !== undefined\n ? Math.ceil(numRows / pagination.pageSize)\n : undefined;\n\n const table = useReactTable({\n data: (data ?? defaultData) as any[],\n columns: columns ?? [],\n pageCount: pageCount ?? 0,\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: (update) => {\n if (onSortingChange && sorting && typeof update === 'function') {\n onSortingChange(update(sorting));\n }\n },\n onPaginationChange: (update) => {\n if (pagination && onPaginationChange && typeof update === 'function') {\n onPaginationChange(update(pagination));\n }\n },\n getCoreRowModel: getCoreRowModel(),\n manualPagination: true,\n state: {\n pagination,\n sorting,\n },\n });\n\n const [internalPageIndex, setInternalPageIndex] = useState(\n pagination?.pageIndex ?? 0,\n );\n useEffect(() => {\n setInternalPageIndex(pagination?.pageIndex ?? 0);\n }, [pagination?.pageIndex]);\n\n return (\n <div className={cn(`relative flex h-full w-full flex-col`, className)}>\n <div className=\"border-border flex-1 overflow-hidden border font-mono\">\n <ScrollArea className=\"h-full overflow-auto\">\n <Table disableWrapper>\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n <TableHead\n className={`bg-background sticky left-0 top-[-1px] z-10 w-auto whitespace-nowrap border-r py-2 text-center`}\n >\n {isFetching ? (\n <div className=\"border-primary h-4 w-4 animate-spin rounded-full border-2 border-t-transparent\" />\n ) : null}\n </TableHead>\n {headerGroup.headers.map((header) => {\n const meta = header.column.columnDef\n .meta as ArrowColumnMeta;\n return (\n <TableHead\n key={header.id}\n colSpan={header.colSpan}\n className={cn(\n 'bg-background hover:bg-muted sticky top-[-1px] z-10 w-auto whitespace-nowrap border-r py-2',\n pagination ? 'cursor-pointer' : '',\n meta?.isNumeric ? 'text-right' : 'text-left',\n fontSize,\n )}\n onClick={header.column.getToggleSortingHandler()}\n >\n <div className=\"flex items-center gap-2\">\n {header.isPlaceholder ? null : (\n <div>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </div>\n )}\n {header.column.getIsSorted() ? (\n header.column.getIsSorted() === 'desc' ? (\n <ChevronDownIcon className=\"h-4 w-4\" />\n ) : (\n <ChevronUpIcon className=\"h-4 w-4\" />\n )\n ) : null}\n <div className=\"flex-1\" />\n <Badge\n variant=\"outline\"\n className={`max-w-[400px] truncate text-xs opacity-30`}\n >\n {String(meta?.type)}\n </Badge>\n </div>\n </TableHead>\n );\n })}\n <TableHead className=\"bg-background sticky top-0 w-full whitespace-nowrap border-r border-t py-2\" />\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {table.getRowModel().rows.map((row, i) => (\n <TableRow\n key={row.id}\n className=\"hover:bg-muted bg-background\"\n onClick={(event) => {\n event.preventDefault();\n onRowClick?.({row: row as Row<Data>, event});\n }}\n onDoubleClick={(event) => {\n event.preventDefault();\n onRowDoubleClick?.({row: row as Row<Data>, event});\n }}\n >\n <TableCell\n className={`bg-background text-muted-foreground sticky left-0 border-r text-center ${fontSize}`}\n >\n {pagination\n ? `${pagination.pageIndex * pagination.pageSize + i + 1}`\n : `${i + 1}`}\n </TableCell>\n {row.getVisibleCells().map((cell) => {\n const meta = cell.column.columnDef.meta as ArrowColumnMeta;\n return (\n <TableCell\n key={cell.id}\n className={cn(\n 'max-w-[500px] overflow-hidden truncate border-r px-7',\n fontSize,\n meta?.isNumeric ? 'text-right' : 'text-left',\n )}\n >\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n </TableCell>\n );\n })}\n <TableCell className=\"border-r\">&nbsp;</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n <ScrollBar orientation=\"vertical\" className=\"z-50\" />\n <ScrollBar orientation=\"horizontal\" />\n </ScrollArea>\n </div>\n {pagination || footerActions ? (\n <div className=\"bg-background sticky bottom-0 left-0 flex flex-wrap items-center gap-2 border border-t-0 p-2\">\n {pagination ? (\n <>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.setPageIndex(0)}\n disabled={!table.getCanPreviousPage()}\n >\n <ChevronDoubleLeftIcon className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.previousPage()}\n disabled={!table.getCanPreviousPage()}\n >\n <ChevronLeftIcon className=\"h-4 w-4\" />\n </Button>\n <div className={`ml-1 flex items-center gap-1 ${fontSize}`}>\n <div>Page</div>\n <Input\n type=\"number\"\n min={1}\n max={table.getPageCount()}\n className=\"h-8 w-16\"\n value={internalPageIndex + 1}\n onChange={(e) => {\n const value = e.target.value;\n if (value) {\n const page = Math.max(\n 0,\n Math.min(table.getPageCount() - 1, Number(value) - 1),\n );\n setInternalPageIndex(page);\n }\n }}\n onBlur={() => {\n if (internalPageIndex !== pagination?.pageIndex) {\n table.setPageIndex(internalPageIndex);\n }\n }}\n />\n <div>{`of ${formatCount(table.getPageCount())}`}</div>\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.nextPage()}\n disabled={!table.getCanNextPage()}\n >\n <ChevronRightIcon className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.setPageIndex(table.getPageCount() - 1)}\n disabled={!table.getCanNextPage()}\n >\n <ChevronDoubleRightIcon className=\"h-4 w-4\" />\n </Button>\n <Select\n value={String(table.getState().pagination.pageSize)}\n onValueChange={(value) => table.setPageSize(Number(value))}\n >\n <SelectTrigger className=\"h-8 w-[110px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {[10, 50, 100, 500, 1000].map((pageSize) => (\n <SelectItem key={pageSize} value={String(pageSize)}>\n {`${pageSize} rows`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex-1\" />\n </>\n ) : null}\n\n <>\n {numRows !== undefined && isFinite(numRows) ? (\n <div className={`font-normal ${fontSize}`}>\n {`${formatCount(numRows)} rows`}\n </div>\n ) : null}\n </>\n {footerActions}\n </div>\n ) : null}\n\n {isFetching ? (\n <div className=\"bg-background/80 absolute inset-0 animate-pulse\" />\n ) : null}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"DataTablePaginated.js","sourceRoot":"","sources":["../src/DataTablePaginated.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n ChevronDownIcon,\n ChevronUpIcon,\n ChevronsLeftIcon as ChevronDoubleLeftIcon,\n ChevronsRightIcon as ChevronDoubleRightIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from 'lucide-react';\nimport {\n Button,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Badge,\n cn,\n ScrollArea,\n ScrollBar,\n resolveFontSizeClass,\n} from '@sqlrooms/ui';\nimport {formatCount} from '@sqlrooms/utils';\nimport {\n ColumnDef,\n PaginationState,\n SortingState,\n Row,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable,\n} from '@tanstack/react-table';\nimport {useEffect, useMemo, useState} from 'react';\nimport {ArrowColumnMeta} from './useArrowDataTable';\n\nexport type DataTablePaginatedProps<Data extends object> = {\n className?: string;\n /** Custom font size for the table e.g. text-xs, text-sm, text-md, text-lg, text-base */\n fontSize?: string;\n data?: ArrayLike<Data> | undefined;\n columns?: ColumnDef<Data, any>[] | undefined;\n pageCount?: number | undefined;\n numRows?: number | undefined;\n isFetching?: boolean;\n pagination?: PaginationState | undefined;\n sorting?: SortingState;\n footerActions?: React.ReactNode;\n onPaginationChange?: (pagination: PaginationState) => void;\n onSortingChange?: (sorting: SortingState) => void;\n /**\n * Called when a row is clicked.\n */\n onRowClick?: (args: {\n row: Row<Data>;\n event: React.MouseEvent<HTMLTableRowElement>;\n }) => void;\n /**\n * Called when a row is double-clicked.\n */\n onRowDoubleClick?: (args: {\n row: Row<Data>;\n event: React.MouseEvent<HTMLTableRowElement>;\n }) => void;\n};\n\n/**\n * Data table with pagination, sorting, and custom actions.\n * @param props\n * @returns\n */\nexport default function DataTablePaginated<Data extends object>({\n className,\n fontSize = 'text-xs',\n data,\n columns,\n numRows,\n pagination,\n sorting,\n onPaginationChange,\n onSortingChange,\n footerActions,\n isFetching,\n onRowClick,\n onRowDoubleClick,\n}: DataTablePaginatedProps<Data>) {\n const defaultData = useMemo(() => [], []);\n const fontSizeClass = resolveFontSizeClass(fontSize);\n const pageCount =\n pagination && numRows !== undefined\n ? Math.ceil(numRows / pagination.pageSize)\n : undefined;\n\n const table = useReactTable({\n data: (data ?? defaultData) as any[],\n columns: columns ?? [],\n pageCount: pageCount ?? 0,\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: (update) => {\n if (onSortingChange && sorting && typeof update === 'function') {\n onSortingChange(update(sorting));\n }\n },\n onPaginationChange: (update) => {\n if (pagination && onPaginationChange && typeof update === 'function') {\n onPaginationChange(update(pagination));\n }\n },\n getCoreRowModel: getCoreRowModel(),\n manualPagination: true,\n state: {\n pagination,\n sorting,\n },\n });\n\n const [internalPageIndex, setInternalPageIndex] = useState(\n pagination?.pageIndex ?? 0,\n );\n useEffect(() => {\n setInternalPageIndex(pagination?.pageIndex ?? 0);\n }, [pagination?.pageIndex]);\n\n return (\n <div className={cn(`relative flex h-full w-full flex-col`, className)}>\n <div className=\"border-border flex-1 overflow-hidden border font-mono\">\n <ScrollArea className=\"h-full overflow-auto\">\n <Table disableWrapper>\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n <TableHead\n className={`bg-background sticky top-[-1px] left-0 z-10 w-auto border-r py-2 text-center whitespace-nowrap`}\n >\n {isFetching ? (\n <div className=\"border-primary h-4 w-4 animate-spin rounded-full border-2 border-t-transparent\" />\n ) : null}\n </TableHead>\n {headerGroup.headers.map((header) => {\n const meta = header.column.columnDef\n .meta as ArrowColumnMeta;\n return (\n <TableHead\n key={header.id}\n colSpan={header.colSpan}\n className={cn(\n 'bg-background hover:bg-muted sticky top-[-1px] z-10 w-auto border-r py-2 whitespace-nowrap',\n pagination ? 'cursor-pointer' : '',\n meta?.isNumeric ? 'text-right' : 'text-left',\n fontSizeClass,\n )}\n onClick={header.column.getToggleSortingHandler()}\n >\n <div className=\"flex items-center gap-2\">\n {header.isPlaceholder ? null : (\n <div>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </div>\n )}\n {header.column.getIsSorted() ? (\n header.column.getIsSorted() === 'desc' ? (\n <ChevronDownIcon className=\"h-4 w-4\" />\n ) : (\n <ChevronUpIcon className=\"h-4 w-4\" />\n )\n ) : null}\n <div className=\"flex-1\" />\n <Badge\n variant=\"outline\"\n className={`max-w-[400px] truncate text-xs opacity-30`}\n >\n {String(meta?.type)}\n </Badge>\n </div>\n </TableHead>\n );\n })}\n <TableHead className=\"bg-background sticky top-0 w-full border-t border-r py-2 whitespace-nowrap\" />\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {table.getRowModel().rows.map((row, i) => (\n <TableRow\n key={row.id}\n className=\"hover:bg-muted bg-background\"\n onClick={(event) => {\n event.preventDefault();\n onRowClick?.({row: row as Row<Data>, event});\n }}\n onDoubleClick={(event) => {\n event.preventDefault();\n onRowDoubleClick?.({row: row as Row<Data>, event});\n }}\n >\n <TableCell\n className={`bg-background text-muted-foreground sticky left-0 border-r text-center ${fontSizeClass}`}\n >\n {pagination\n ? `${pagination.pageIndex * pagination.pageSize + i + 1}`\n : `${i + 1}`}\n </TableCell>\n {row.getVisibleCells().map((cell) => {\n const meta = cell.column.columnDef.meta as ArrowColumnMeta;\n return (\n <TableCell\n key={cell.id}\n className={cn(\n 'max-w-[500px] truncate overflow-hidden border-r px-7',\n fontSizeClass,\n meta?.isNumeric ? 'text-right' : 'text-left',\n )}\n >\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n </TableCell>\n );\n })}\n <TableCell className=\"border-r\">&nbsp;</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n <ScrollBar orientation=\"vertical\" className=\"z-50\" />\n <ScrollBar orientation=\"horizontal\" />\n </ScrollArea>\n </div>\n {pagination || footerActions ? (\n <div className=\"bg-background sticky bottom-0 left-0 flex flex-wrap items-center gap-2 border border-t-0 p-2\">\n {pagination ? (\n <>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.setPageIndex(0)}\n disabled={!table.getCanPreviousPage()}\n >\n <ChevronDoubleLeftIcon className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.previousPage()}\n disabled={!table.getCanPreviousPage()}\n >\n <ChevronLeftIcon className=\"h-4 w-4\" />\n </Button>\n <div\n className={`ml-1 flex items-center gap-1 ${fontSizeClass}`}\n >\n <div>Page</div>\n <Input\n type=\"number\"\n min={1}\n max={table.getPageCount()}\n className=\"h-8 w-16\"\n value={internalPageIndex + 1}\n onChange={(e) => {\n const value = e.target.value;\n if (value) {\n const page = Math.max(\n 0,\n Math.min(table.getPageCount() - 1, Number(value) - 1),\n );\n setInternalPageIndex(page);\n }\n }}\n onBlur={() => {\n if (internalPageIndex !== pagination?.pageIndex) {\n table.setPageIndex(internalPageIndex);\n }\n }}\n />\n <div>{`of ${formatCount(table.getPageCount())}`}</div>\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.nextPage()}\n disabled={!table.getCanNextPage()}\n >\n <ChevronRightIcon className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => table.setPageIndex(table.getPageCount() - 1)}\n disabled={!table.getCanNextPage()}\n >\n <ChevronDoubleRightIcon className=\"h-4 w-4\" />\n </Button>\n <Select\n value={String(table.getState().pagination.pageSize)}\n onValueChange={(value) => table.setPageSize(Number(value))}\n >\n <SelectTrigger className=\"h-8 w-[110px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {[10, 50, 100, 500, 1000].map((pageSize) => (\n <SelectItem key={pageSize} value={String(pageSize)}>\n {`${pageSize} rows`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex-1\" />\n </>\n ) : null}\n\n <>\n {numRows !== undefined && isFinite(numRows) ? (\n <div className={`font-normal ${fontSizeClass}`}>\n {`${formatCount(numRows)} rows`}\n </div>\n ) : null}\n </>\n {footerActions}\n </div>\n ) : null}\n\n {isFetching ? (\n <div className=\"bg-background/80 absolute inset-0 animate-pulse\" />\n ) : null}\n </div>\n );\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { FC } from 'react';
2
2
  import { DataTablePaginatedProps } from './DataTablePaginated';
3
+ import { ArrowDataTableValueFormatter } from './useArrowDataTable';
3
4
  export type QueryDataTableProps = {
4
5
  className?: string;
5
6
  /** Custom font size for the table e.g. text-xs, text-sm, text-md, text-lg, text-base */
@@ -7,6 +8,8 @@ export type QueryDataTableProps = {
7
8
  query: string;
8
9
  queryKeyComponents?: unknown[];
9
10
  renderActions?: (query: string) => React.ReactNode;
11
+ /** Custom value formatter for arrow data */
12
+ formatValue?: ArrowDataTableValueFormatter;
10
13
  };
11
14
  declare const QueryDataTable: FC<QueryDataTableProps>;
12
15
  export default QueryDataTable;
@@ -1 +1 @@
1
- {"version":3,"file":"QueryDataTable.d.ts","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,EAAE,EAAoB,MAAM,OAAO,CAAC;AAC5C,OAA2B,EACzB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAK9B,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CACpD,CAAC;AAEF,QAAA,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAiD3C,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"QueryDataTable.d.ts","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,EAAE,EAAoB,MAAM,OAAO,CAAC;AAC5C,OAA2B,EACzB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAE9B,OAA0B,EAAC,4BAA4B,EAAC,MAAM,qBAAqB,CAAC;AAGpF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IACnD,4CAA4C;IAC5C,WAAW,CAAC,EAAE,4BAA4B,CAAC;CAC5C,CAAC;AAEF,QAAA,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAkD3C,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -5,7 +5,7 @@ import DataTablePaginated from './DataTablePaginated';
5
5
  import { QueryDataTableActionsMenu } from './QueryDataTableActionsMenu';
6
6
  import useArrowDataTable from './useArrowDataTable';
7
7
  import { makePagedQuery } from './utils';
8
- const QueryDataTable = ({ className, fontSize = 'text-xs', query, renderActions = (query) => _jsx(QueryDataTableActionsMenu, { query: query }), }) => {
8
+ const QueryDataTable = ({ className, fontSize = 'text-xs', query, renderActions = (query) => _jsx(QueryDataTableActionsMenu, { query: query }), formatValue, }) => {
9
9
  const [sorting, setSorting] = useState([]);
10
10
  const [pagination, setPagination] = useState({
11
11
  pageIndex: 0,
@@ -18,7 +18,7 @@ const QueryDataTable = ({ className, fontSize = 'text-xs', query, renderActions
18
18
  const countQueryResult = useSql({
19
19
  query: `SELECT COUNT(*)::int AS count FROM (${sanitizedQuery})`,
20
20
  });
21
- const arrowTableData = useArrowDataTable(queryResult.data?.arrowTable);
21
+ const arrowTableData = useArrowDataTable(queryResult.data?.arrowTable, { formatValue });
22
22
  if (queryResult.error) {
23
23
  return (_jsx("div", { className: "h-full w-full overflow-auto p-5", children: _jsx("pre", { className: "text-xs leading-tight text-red-500", children: queryResult.error?.message ?? 'Unknown error' }) }));
24
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"QueryDataTable.js","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,aAAa,EAAE,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAK,OAAO,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAC5C,OAAO,kBAEN,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAC,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACtE,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAWvC,MAAM,cAAc,GAA4B,CAAC,EAC/C,SAAS,EACT,QAAQ,GAAG,SAAS,EACpB,KAAK,EACL,aAAa,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,KAAC,yBAAyB,IAAC,KAAK,EAAE,KAAK,GAAI,GACvE,EAAE,EAAE;IACH,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAe,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAkB;QAC5D,SAAS,EAAE,CAAC;QACZ,QAAQ,EAAE,GAAG;KACd,CAAC,CAAC;IAEH,gGAAgG;IAChG,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACvE,MAAM,WAAW,GAAG,MAAM,CAAC,EAAC,KAAK,EAAE,UAAU,EAAC,CAAC,CAAC;IAChD,MAAM,gBAAgB,GAAG,MAAM,CAAkB;QAC/C,KAAK,EAAE,uCAAuC,cAAc,GAAG;KAChE,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAEvE,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CACL,cAAK,SAAS,EAAC,iCAAiC,YAC9C,cAAK,SAAS,EAAC,oCAAoC,YAChD,WAAW,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,GAC1C,GACF,CACP,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI;QACnC,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;QAClD,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO,CACL,KAAC,kBAAkB,OACb,cAAc,EAClB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,WAAW,CAAC,SAAS,EACjC,UAAU,EAAE,UAAU,EACtB,kBAAkB,EAAE,aAAa,EACjC,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,GACnE,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import {sanitizeQuery, useSql} from '@sqlrooms/duckdb';\nimport {PaginationState, SortingState} from '@tanstack/table-core';\nimport {FC, useMemo, useState} from 'react';\nimport DataTablePaginated, {\n DataTablePaginatedProps,\n} from './DataTablePaginated';\nimport {QueryDataTableActionsMenu} from './QueryDataTableActionsMenu';\nimport useArrowDataTable from './useArrowDataTable';\nimport {makePagedQuery} from './utils';\n\nexport type QueryDataTableProps = {\n className?: string;\n /** Custom font size for the table e.g. text-xs, text-sm, text-md, text-lg, text-base */\n fontSize?: DataTablePaginatedProps<any>['fontSize'];\n query: string;\n queryKeyComponents?: unknown[];\n renderActions?: (query: string) => React.ReactNode;\n};\n\nconst QueryDataTable: FC<QueryDataTableProps> = ({\n className,\n fontSize = 'text-xs',\n query,\n renderActions = (query) => <QueryDataTableActionsMenu query={query} />,\n}) => {\n const [sorting, setSorting] = useState<SortingState>([]);\n const [pagination, setPagination] = useState<PaginationState>({\n pageIndex: 0,\n pageSize: 100,\n });\n\n // Sanitize the query generated by LLM to remove trailing semicolons, comments, and extra spaces\n const sanitizedQuery = useMemo(() => sanitizeQuery(query), [query]);\n const pagedQuery = makePagedQuery(sanitizedQuery, sorting, pagination);\n const queryResult = useSql({query: pagedQuery});\n const countQueryResult = useSql<{count: number}>({\n query: `SELECT COUNT(*)::int AS count FROM (${sanitizedQuery})`,\n });\n const arrowTableData = useArrowDataTable(queryResult.data?.arrowTable);\n\n if (queryResult.error) {\n return (\n <div className=\"h-full w-full overflow-auto p-5\">\n <pre className=\"text-xs leading-tight text-red-500\">\n {queryResult.error?.message ?? 'Unknown error'}\n </pre>\n </div>\n );\n }\n\n const numRows = countQueryResult.data\n ? (countQueryResult.data.toArray()[0]?.count ?? 0)\n : undefined;\n\n return (\n <DataTablePaginated\n {...arrowTableData}\n className={className}\n fontSize={fontSize}\n numRows={numRows}\n isFetching={queryResult.isLoading}\n pagination={pagination}\n onPaginationChange={setPagination}\n sorting={sorting}\n onSortingChange={setSorting}\n footerActions={renderActions ? renderActions(sanitizedQuery) : null}\n />\n );\n};\n\nexport default QueryDataTable;\n"]}
1
+ {"version":3,"file":"QueryDataTable.js","sourceRoot":"","sources":["../src/QueryDataTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,aAAa,EAAE,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAK,OAAO,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAC5C,OAAO,kBAEN,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAC,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACtE,OAAO,iBAAiD,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAavC,MAAM,cAAc,GAA4B,CAAC,EAC/C,SAAS,EACT,QAAQ,GAAG,SAAS,EACpB,KAAK,EACL,aAAa,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,KAAC,yBAAyB,IAAC,KAAK,EAAE,KAAK,GAAI,EACtE,WAAW,GACZ,EAAE,EAAE;IACH,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAe,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAkB;QAC5D,SAAS,EAAE,CAAC;QACZ,QAAQ,EAAE,GAAG;KACd,CAAC,CAAC;IAEH,gGAAgG;IAChG,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACvE,MAAM,WAAW,GAAG,MAAM,CAAC,EAAC,KAAK,EAAE,UAAU,EAAC,CAAC,CAAC;IAChD,MAAM,gBAAgB,GAAG,MAAM,CAAkB;QAC/C,KAAK,EAAE,uCAAuC,cAAc,GAAG;KAChE,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,EAAC,WAAW,EAAC,CAAC,CAAC;IAEtF,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CACL,cAAK,SAAS,EAAC,iCAAiC,YAC9C,cAAK,SAAS,EAAC,oCAAoC,YAChD,WAAW,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,GAC1C,GACF,CACP,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI;QACnC,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;QAClD,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO,CACL,KAAC,kBAAkB,OACb,cAAc,EAClB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,WAAW,CAAC,SAAS,EACjC,UAAU,EAAE,UAAU,EACtB,kBAAkB,EAAE,aAAa,EACjC,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,GACnE,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import {sanitizeQuery, useSql} from '@sqlrooms/duckdb';\nimport {PaginationState, SortingState} from '@tanstack/table-core';\nimport {FC, useMemo, useState} from 'react';\nimport DataTablePaginated, {\n DataTablePaginatedProps,\n} from './DataTablePaginated';\nimport {QueryDataTableActionsMenu} from './QueryDataTableActionsMenu';\nimport useArrowDataTable, {ArrowDataTableValueFormatter} from './useArrowDataTable';\nimport {makePagedQuery} from './utils';\n\nexport type QueryDataTableProps = {\n className?: string;\n /** Custom font size for the table e.g. text-xs, text-sm, text-md, text-lg, text-base */\n fontSize?: DataTablePaginatedProps<any>['fontSize'];\n query: string;\n queryKeyComponents?: unknown[];\n renderActions?: (query: string) => React.ReactNode;\n /** Custom value formatter for arrow data */\n formatValue?: ArrowDataTableValueFormatter;\n};\n\nconst QueryDataTable: FC<QueryDataTableProps> = ({\n className,\n fontSize = 'text-xs',\n query,\n renderActions = (query) => <QueryDataTableActionsMenu query={query} />,\n formatValue,\n}) => {\n const [sorting, setSorting] = useState<SortingState>([]);\n const [pagination, setPagination] = useState<PaginationState>({\n pageIndex: 0,\n pageSize: 100,\n });\n\n // Sanitize the query generated by LLM to remove trailing semicolons, comments, and extra spaces\n const sanitizedQuery = useMemo(() => sanitizeQuery(query), [query]);\n const pagedQuery = makePagedQuery(sanitizedQuery, sorting, pagination);\n const queryResult = useSql({query: pagedQuery});\n const countQueryResult = useSql<{count: number}>({\n query: `SELECT COUNT(*)::int AS count FROM (${sanitizedQuery})`,\n });\n const arrowTableData = useArrowDataTable(queryResult.data?.arrowTable, {formatValue});\n\n if (queryResult.error) {\n return (\n <div className=\"h-full w-full overflow-auto p-5\">\n <pre className=\"text-xs leading-tight text-red-500\">\n {queryResult.error?.message ?? 'Unknown error'}\n </pre>\n </div>\n );\n }\n\n const numRows = countQueryResult.data\n ? (countQueryResult.data.toArray()[0]?.count ?? 0)\n : undefined;\n\n return (\n <DataTablePaginated\n {...arrowTableData}\n className={className}\n fontSize={fontSize}\n numRows={numRows}\n isFetching={queryResult.isLoading}\n pagination={pagination}\n onPaginationChange={setPagination}\n sorting={sorting}\n onSortingChange={setSorting}\n footerActions={renderActions ? renderActions(sanitizedQuery) : null}\n />\n );\n};\n\nexport default QueryDataTable;\n"]}
package/dist/index.d.ts CHANGED
@@ -2,13 +2,13 @@
2
2
  * {@include ../README.md}
3
3
  * @packageDocumentation
4
4
  */
5
- export { default as DataTableModal } from './DataTableModal';
5
+ export { default as DataTableModal, type DataTableModalProps } from './DataTableModal';
6
6
  export { default as DataTablePaginated, type DataTablePaginatedProps, } from './DataTablePaginated';
7
7
  export { default as DataTableVirtualized, type DataTableVirtualizedProps, type DataTableProps, } from './DataTableVirtualized';
8
8
  export { default as QueryDataTable, type QueryDataTableProps, } from './QueryDataTable';
9
- export { default as useArrowDataTable, type ArrowColumnMeta, } from './useArrowDataTable';
9
+ export { default as useArrowDataTable, type ArrowColumnMeta, type ArrowDataTableValueFormatter, type UseArrowDataTableOptions, } from './useArrowDataTable';
10
10
  export { ColumnTypeBadge } from './ColumnTypeBadge';
11
- export { DataTableArrowPaginated } from './DataTableArrowPaginated';
11
+ export { DataTableArrowPaginated, type DataTableArrowPaginatedProps } from './DataTableArrowPaginated';
12
12
  export { QueryDataTableActionsMenu } from './QueryDataTableActionsMenu';
13
13
  export { makePagedQuery } from './utils';
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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,OAAO,EACL,OAAO,IAAI,kBAAkB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,OAAO,IAAI,oBAAoB,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,OAAO,IAAI,cAAc,EACzB,KAAK,mBAAmB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,OAAO,IAAI,iBAAiB,EAC5B,KAAK,eAAe,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAC,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAC,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,OAAO,IAAI,cAAc,EAAE,KAAK,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,OAAO,IAAI,kBAAkB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,OAAO,IAAI,oBAAoB,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,OAAO,IAAI,cAAc,EACzB,KAAK,mBAAmB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,OAAO,IAAI,iBAAiB,EAC5B,KAAK,eAAe,EACpB,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAC,uBAAuB,EAAE,KAAK,4BAA4B,EAAC,MAAM,2BAA2B,CAAC;AACrG,OAAO,EAAC,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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,OAAO,EACL,OAAO,IAAI,kBAAkB,GAE9B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,OAAO,IAAI,oBAAoB,GAGhC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,OAAO,IAAI,cAAc,GAE1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,OAAO,IAAI,iBAAiB,GAE7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAC,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAC,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {default as DataTableModal} from './DataTableModal';\nexport {\n default as DataTablePaginated,\n type DataTablePaginatedProps,\n} from './DataTablePaginated';\nexport {\n default as DataTableVirtualized,\n type DataTableVirtualizedProps,\n type DataTableProps,\n} from './DataTableVirtualized';\nexport {\n default as QueryDataTable,\n type QueryDataTableProps,\n} from './QueryDataTable';\nexport {\n default as useArrowDataTable,\n type ArrowColumnMeta,\n} from './useArrowDataTable';\nexport {ColumnTypeBadge} from './ColumnTypeBadge';\nexport {DataTableArrowPaginated} from './DataTableArrowPaginated';\nexport {QueryDataTableActionsMenu} from './QueryDataTableActionsMenu';\nexport {makePagedQuery} from './utils';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,OAAO,IAAI,cAAc,EAA2B,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,OAAO,IAAI,kBAAkB,GAE9B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,OAAO,IAAI,oBAAoB,GAGhC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,OAAO,IAAI,cAAc,GAE1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,OAAO,IAAI,iBAAiB,GAI7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAC,uBAAuB,EAAoC,MAAM,2BAA2B,CAAC;AACrG,OAAO,EAAC,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {default as DataTableModal, type DataTableModalProps} from './DataTableModal';\nexport {\n default as DataTablePaginated,\n type DataTablePaginatedProps,\n} from './DataTablePaginated';\nexport {\n default as DataTableVirtualized,\n type DataTableVirtualizedProps,\n type DataTableProps,\n} from './DataTableVirtualized';\nexport {\n default as QueryDataTable,\n type QueryDataTableProps,\n} from './QueryDataTable';\nexport {\n default as useArrowDataTable,\n type ArrowColumnMeta,\n type ArrowDataTableValueFormatter,\n type UseArrowDataTableOptions,\n} from './useArrowDataTable';\nexport {ColumnTypeBadge} from './ColumnTypeBadge';\nexport {DataTableArrowPaginated, type DataTableArrowPaginatedProps} from './DataTableArrowPaginated';\nexport {QueryDataTableActionsMenu} from './QueryDataTableActionsMenu';\nexport {makePagedQuery} from './utils';\n"]}
@@ -8,9 +8,37 @@ export type ArrowColumnMeta = {
8
8
  type: arrow.DataType;
9
9
  isNumeric: boolean;
10
10
  };
11
- export default function useArrowDataTable(table: arrow.Table | undefined, options?: {
11
+ /**
12
+ * Formatter for rendering Arrow cell values in data tables.
13
+ * Return a string to override the default formatting.
14
+ * If you don't return anything (or return undefined), the default formatter is used.
15
+ *
16
+ * @param type - The Arrow DataType for the column
17
+ * @param value - The raw cell value
18
+ * @returns A formatted string, or undefined/nothing to fall back to the default
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * formatValue: (type, value) => {
23
+ * if (arrow.DataType.isDecimal(type)) {
24
+ * return `$${value}`;
25
+ * }
26
+ * if (arrow.DataType.isBinary(type) && value instanceof Uint8Array) {
27
+ * return `${value.byteLength} bytes`;
28
+ * }
29
+ * }
30
+ * ```
31
+ */
32
+ export type ArrowDataTableValueFormatter = (type: arrow.DataType, value: unknown) => string | undefined;
33
+ export type UseArrowDataTableOptions = {
12
34
  /** Custom font size for the table e.g. xs, sm, md, lg, base */
13
35
  fontSize?: string;
14
- }): UseArrowDataTableResult | undefined;
36
+ /**
37
+ * Custom value formatter that overrides the default valueToString.
38
+ * Return a string to use your custom formatting, or undefined to fall back to the default.
39
+ */
40
+ formatValue?: ArrowDataTableValueFormatter;
41
+ };
42
+ export default function useArrowDataTable(table: arrow.Table | undefined, options?: UseArrowDataTableOptions): UseArrowDataTableResult | undefined;
15
43
  export {};
16
44
  //# sourceMappingURL=useArrowDataTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useArrowDataTable.d.ts","sourceRoot":"","sources":["../src/useArrowDataTable.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAOtC,KAAK,uBAAuB,GAAG;IAC7B,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;IACrB,OAAO,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAkCF,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACvC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,EAC9B,OAAO,GAAE;IACP,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,GACL,uBAAuB,GAAG,SAAS,CAmErC"}
1
+ {"version":3,"file":"useArrowDataTable.d.ts","sourceRoot":"","sources":["../src/useArrowDataTable.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAOtC,KAAK,uBAAuB,GAAG;IAC7B,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;IACrB,OAAO,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAkFF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,4BAA4B,GAAG,CACzC,IAAI,EAAE,KAAK,CAAC,QAAQ,EACpB,KAAK,EAAE,OAAO,KACX,MAAM,GAAG,SAAS,CAAC;AAExB,MAAM,MAAM,wBAAwB,GAAG;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAC;CAC5C,CAAC;AAGF,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACvC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,EAC9B,OAAO,GAAE,wBAA6B,GACrC,uBAAuB,GAAG,SAAS,CAkGrC"}
@@ -1,16 +1,30 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button, Popover, PopoverContent, PopoverTrigger } from '@sqlrooms/ui';
2
+ import { JsonMonacoEditor } from '@sqlrooms/monaco-editor';
3
+ import { Button, Popover, PopoverContent, PopoverTrigger, resolveFontSizeClass, } from '@sqlrooms/ui';
4
+ import { safeJsonParse, shorten, toDecimalString } from '@sqlrooms/utils';
3
5
  import { ClipboardIcon } from 'lucide-react';
4
- import { shorten } from '@sqlrooms/utils';
5
6
  import { createColumnHelper } from '@tanstack/react-table';
6
7
  import * as arrow from 'apache-arrow';
7
8
  import { useMemo } from 'react';
8
9
  const columnHelper = createColumnHelper();
9
10
  const MAX_VALUE_LENGTH = 64;
11
+ /**
12
+ * Converts an Arrow value into a human-readable string.
13
+ */
10
14
  function valueToString(type, value) {
11
- if (value === null || value === undefined) {
15
+ if (value === null || value === undefined)
12
16
  return 'NULL';
17
+ // --- DECIMAL ---
18
+ if (arrow.DataType.isDecimal(type)) {
19
+ const scale = type.scale ?? 0;
20
+ if (value instanceof Uint32Array) {
21
+ // Use Apache Arrow–style helper to convert Decimal128 buffer to string
22
+ return toDecimalString(value, scale);
23
+ }
24
+ // For non-Uint32Array values, fall back to default string rendering.
25
+ return String(value);
13
26
  }
27
+ // --- TIMESTAMP ---
14
28
  if (arrow.DataType.isTimestamp(type)) {
15
29
  switch (typeof value) {
16
30
  case 'number':
@@ -20,6 +34,7 @@ function valueToString(type, value) {
20
34
  return new Date(value).toISOString();
21
35
  }
22
36
  }
37
+ // --- TIME ---
23
38
  if (arrow.DataType.isTime(type)) {
24
39
  switch (typeof value) {
25
40
  case 'number':
@@ -29,16 +44,43 @@ function valueToString(type, value) {
29
44
  return new Date(value).toISOString().substring(11, 19);
30
45
  }
31
46
  }
47
+ // --- DATE ---
48
+ // Handle Arrow Date32/Date64 values coming from DuckDB-WASM.
49
+ //
50
+ // 1. If `value` is already a JS Date, format it directly.
51
+ // 2. If store config`castTimestampToDate` is true, DuckDB may return a number or bigint:
52
+ // 3. If `value` is a string, try to parse it as a date.
53
+ //
54
+ // This ensures DATE columns are displayed as "YYYY-MM-DD" regardless of underlying Arrow type.
32
55
  if (arrow.DataType.isDate(type)) {
33
- if (value instanceof Date) {
34
- return value.toISOString();
56
+ const dateType = type;
57
+ // Already a JS Date
58
+ if (value instanceof Date)
59
+ return value.toISOString().slice(0, 10);
60
+ if (typeof value === 'number' || typeof value === 'bigint') {
61
+ const num = Number(value);
62
+ if (!Number.isFinite(num))
63
+ return String(num);
64
+ const d = new Date(num);
65
+ if (!Number.isNaN(d.getTime()))
66
+ return d.toISOString().slice(0, 10);
67
+ return String(num);
68
+ }
69
+ // Fallback for strings
70
+ if (typeof value === 'string') {
71
+ const d = new Date(value);
72
+ if (!Number.isNaN(d.getTime()))
73
+ return d.toISOString().slice(0, 10);
35
74
  }
75
+ return String(value);
36
76
  }
77
+ // --- fallback ---
37
78
  return String(value);
38
79
  }
39
80
  // Only use for small tables or in combination with pagination
40
81
  export default function useArrowDataTable(table, options = {}) {
41
- const { fontSize = 'base' } = options ?? {};
82
+ const { fontSize = 'base', formatValue } = options;
83
+ const fontSizeClass = resolveFontSizeClass(fontSize);
42
84
  const data = useMemo(() => ({ length: table?.numRows ?? 0 }), [table]);
43
85
  const columns = useMemo(() => {
44
86
  if (!table)
@@ -48,10 +90,18 @@ export default function useArrowDataTable(table, options = {}) {
48
90
  columns.push(columnHelper.accessor((_row, i) => table.getChild(field.name)?.get(i), {
49
91
  cell: (info) => {
50
92
  const value = info.getValue();
51
- const valueStr = valueToString(field.type, value);
52
- return valueStr.length > MAX_VALUE_LENGTH ? (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("span", { className: "cursor-pointer", children: shorten(`${valueStr}`, MAX_VALUE_LENGTH) }) }), _jsx(PopoverContent, { className: `w-auto max-w-[500px] text-${fontSize}`, children: _jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "font-medium", children: `"${field.name}" (${field.type})` }), _jsxs("div", { className: "relative", children: [_jsx("pre", { className: "whitespace-pre-wrap text-xs", children: valueStr }), _jsx(Button, { variant: "ghost", size: "xs", onClick: () => navigator.clipboard.writeText(valueStr), children: _jsx(ClipboardIcon, { className: "h-3 w-3" }) })] }), _jsx("div", { className: "h-full w-full overflow-auto", style: { maxHeight: '200px', maxWidth: '500px' }, children: _jsx("div", { className: "whitespace-pre-wrap font-mono text-xs", children: valueStr }) })] }) })] })) : (valueStr);
93
+ const valueStr = formatValue?.(field.type, value) ??
94
+ valueToString(field.type, value);
95
+ const parsedJson = safeJsonParse(valueStr);
96
+ const isJsonValue = parsedJson !== undefined;
97
+ return valueStr.length > MAX_VALUE_LENGTH ? (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("span", { className: "cursor-pointer", children: shorten(`${valueStr}`, MAX_VALUE_LENGTH) }) }), _jsx(PopoverContent, { sideOffset: 4, align: "center", className: `w-[400px] max-w-[90vw] p-4 ${fontSizeClass} rounded-md shadow-md`, children: _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx("span", { className: "min-w-0 flex-1 font-medium", title: field.name, children: shorten(field.name, MAX_VALUE_LENGTH) }), _jsx("span", { className: "text-muted-foreground shrink-0", children: `(${field.type})` })] }), _jsx("div", { className: "max-h-[300px] min-h-[100px] overflow-auto", children: isJsonValue && parsedJson ? (_jsx(JsonMonacoEditor, { value: parsedJson, readOnly: true, options: {
98
+ lineNumbers: 'off',
99
+ minimap: { enabled: false },
100
+ scrollBeyondLastLine: false,
101
+ wordWrap: 'on',
102
+ } })) : (_jsx("div", { className: "font-mono text-xs break-words whitespace-pre-wrap", children: valueStr })) }), _jsx("div", { className: "mt-2 flex justify-end", children: _jsx(Button, { variant: "ghost", size: "xs", onClick: () => navigator.clipboard.writeText(valueStr), children: _jsx(ClipboardIcon, { className: "h-3 w-3" }) }) })] }) })] })) : (valueStr);
53
103
  },
54
- header: field.name,
104
+ header: shorten(field.name, MAX_VALUE_LENGTH),
55
105
  meta: {
56
106
  type: field.type,
57
107
  isNumeric: arrow.DataType.isFloat(field.type) ||
@@ -61,7 +111,7 @@ export default function useArrowDataTable(table, options = {}) {
61
111
  }));
62
112
  }
63
113
  return columns;
64
- }, [table, fontSize]);
114
+ }, [table, fontSizeClass, formatValue]);
65
115
  return data && columns ? { data, columns } : undefined;
66
116
  }
67
117
  //# sourceMappingURL=useArrowDataTable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useArrowDataTable.js","sourceRoot":"","sources":["../src/useArrowDataTable.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Button, Popover, PopoverContent, PopoverTrigger} from '@sqlrooms/ui';\nimport {ClipboardIcon} from 'lucide-react';\nimport {shorten} from '@sqlrooms/utils';\nimport {createColumnHelper} from '@tanstack/react-table';\nimport {ColumnDef} from '@tanstack/table-core';\nimport * as arrow from 'apache-arrow';\nimport {useMemo} from 'react';\n\nconst columnHelper = createColumnHelper();\n\n// TODO: support fetch the result chunks lazily https://github.com/duckdb/duckdb-wasm/tree/master/packages/duckdb-wasm#query-execution\n\ntype UseArrowDataTableResult = {\n data: ArrayLike<any>;\n columns: ColumnDef<any, any>[];\n};\n\nexport type ArrowColumnMeta = {\n type: arrow.DataType;\n isNumeric: boolean;\n};\n\nconst MAX_VALUE_LENGTH = 64;\n\nfunction valueToString(type: arrow.DataType, value: unknown): string {\n if (value === null || value === undefined) {\n return 'NULL';\n }\n if (arrow.DataType.isTimestamp(type)) {\n switch (typeof value) {\n case 'number':\n case 'bigint':\n return new Date(Number(value)).toISOString();\n case 'string':\n return new Date(value).toISOString();\n }\n }\n if (arrow.DataType.isTime(type)) {\n switch (typeof value) {\n case 'number':\n case 'bigint':\n return new Date(Number(value) / 1000).toISOString().substring(11, 19);\n case 'string':\n return new Date(value).toISOString().substring(11, 19);\n }\n }\n if (arrow.DataType.isDate(type)) {\n if (value instanceof Date) {\n return value.toISOString();\n }\n }\n return String(value);\n}\n// Only use for small tables or in combination with pagination\nexport default function useArrowDataTable(\n table: arrow.Table | undefined,\n options: {\n /** Custom font size for the table e.g. xs, sm, md, lg, base */\n fontSize?: string;\n } = {},\n): UseArrowDataTableResult | undefined {\n const {fontSize = 'base'} = options ?? {};\n const data = useMemo(() => ({length: table?.numRows ?? 0}), [table]);\n const columns = useMemo(() => {\n if (!table) return undefined;\n const columns: ColumnDef<any, any>[] = [];\n for (const field of table.schema.fields) {\n columns.push(\n columnHelper.accessor((_row, i) => table.getChild(field.name)?.get(i), {\n cell: (info) => {\n const value = info.getValue();\n const valueStr = valueToString(field.type, value);\n\n return valueStr.length > MAX_VALUE_LENGTH ? (\n <Popover>\n <PopoverTrigger asChild>\n <span className=\"cursor-pointer\">\n {shorten(`${valueStr}`, MAX_VALUE_LENGTH)}\n </span>\n </PopoverTrigger>\n <PopoverContent\n className={`w-auto max-w-[500px] text-${fontSize}`}\n >\n <div className=\"space-y-2\">\n <div className=\"font-medium\">{`\"${field.name}\" (${field.type})`}</div>\n <div className=\"relative\">\n <pre className=\"whitespace-pre-wrap text-xs\">\n {valueStr}\n </pre>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => navigator.clipboard.writeText(valueStr)}\n >\n <ClipboardIcon className=\"h-3 w-3\" />\n </Button>\n </div>\n <div\n className=\"h-full w-full overflow-auto\"\n style={{maxHeight: '200px', maxWidth: '500px'}}\n >\n <div className=\"whitespace-pre-wrap font-mono text-xs\">\n {valueStr}\n </div>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n ) : (\n valueStr\n );\n },\n header: field.name,\n meta: {\n type: field.type,\n isNumeric:\n arrow.DataType.isFloat(field.type) ||\n arrow.DataType.isDecimal(field.type) ||\n arrow.DataType.isInt(field.type),\n },\n }),\n );\n }\n return columns;\n }, [table, fontSize]);\n\n return data && columns ? {data, columns} : undefined;\n}\n"]}
1
+ {"version":3,"file":"useArrowDataTable.js","sourceRoot":"","sources":["../src/useArrowDataTable.tsx"],"names":[],"mappings":"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","sourcesContent":["import {JsonMonacoEditor} from '@sqlrooms/monaco-editor';\nimport {\n Button,\n Popover,\n PopoverContent,\n PopoverTrigger,\n resolveFontSizeClass,\n} from '@sqlrooms/ui';\nimport {safeJsonParse, shorten, toDecimalString} from '@sqlrooms/utils';\nimport {ClipboardIcon} from 'lucide-react';\nimport {createColumnHelper} from '@tanstack/react-table';\nimport {ColumnDef} from '@tanstack/table-core';\nimport * as arrow from 'apache-arrow';\nimport {useMemo} from 'react';\n\nconst columnHelper = createColumnHelper();\n\n// TODO: support fetch the result chunks lazily https://github.com/duckdb/duckdb-wasm/tree/master/packages/duckdb-wasm#query-execution\n\ntype UseArrowDataTableResult = {\n data: ArrayLike<any>;\n columns: ColumnDef<any, any>[];\n};\n\nexport type ArrowColumnMeta = {\n type: arrow.DataType;\n isNumeric: boolean;\n};\n\nconst MAX_VALUE_LENGTH = 64;\n\n/**\n * Converts an Arrow value into a human-readable string.\n */\nfunction valueToString(type: arrow.DataType, value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n\n // --- DECIMAL ---\n if (arrow.DataType.isDecimal(type)) {\n const scale = (type as any).scale ?? 0;\n\n if (value instanceof Uint32Array) {\n // Use Apache Arrow–style helper to convert Decimal128 buffer to string\n return toDecimalString(value, scale);\n }\n\n // For non-Uint32Array values, fall back to default string rendering.\n return String(value);\n }\n\n // --- TIMESTAMP ---\n if (arrow.DataType.isTimestamp(type)) {\n switch (typeof value) {\n case 'number':\n case 'bigint':\n return new Date(Number(value)).toISOString();\n case 'string':\n return new Date(value).toISOString();\n }\n }\n\n // --- TIME ---\n if (arrow.DataType.isTime(type)) {\n switch (typeof value) {\n case 'number':\n case 'bigint':\n return new Date(Number(value) / 1000).toISOString().substring(11, 19);\n case 'string':\n return new Date(value).toISOString().substring(11, 19);\n }\n }\n\n // --- DATE ---\n // Handle Arrow Date32/Date64 values coming from DuckDB-WASM.\n //\n // 1. If `value` is already a JS Date, format it directly.\n // 2. If store config`castTimestampToDate` is true, DuckDB may return a number or bigint:\n // 3. If `value` is a string, try to parse it as a date.\n //\n // This ensures DATE columns are displayed as \"YYYY-MM-DD\" regardless of underlying Arrow type.\n if (arrow.DataType.isDate(type)) {\n const dateType = type as arrow.Date_;\n\n // Already a JS Date\n if (value instanceof Date) return value.toISOString().slice(0, 10);\n\n if (typeof value === 'number' || typeof value === 'bigint') {\n const num = Number(value);\n if (!Number.isFinite(num)) return String(num);\n\n const d = new Date(num);\n if (!Number.isNaN(d.getTime())) return d.toISOString().slice(0, 10);\n\n return String(num);\n }\n\n // Fallback for strings\n if (typeof value === 'string') {\n const d = new Date(value);\n if (!Number.isNaN(d.getTime())) return d.toISOString().slice(0, 10);\n }\n\n return String(value);\n }\n\n // --- fallback ---\n return String(value);\n}\n\n/**\n * Formatter for rendering Arrow cell values in data tables.\n * Return a string to override the default formatting.\n * If you don't return anything (or return undefined), the default formatter is used.\n *\n * @param type - The Arrow DataType for the column\n * @param value - The raw cell value\n * @returns A formatted string, or undefined/nothing to fall back to the default\n *\n * @example\n * ```ts\n * formatValue: (type, value) => {\n * if (arrow.DataType.isDecimal(type)) {\n * return `$${value}`;\n * }\n * if (arrow.DataType.isBinary(type) && value instanceof Uint8Array) {\n * return `${value.byteLength} bytes`;\n * }\n * }\n * ```\n */\nexport type ArrowDataTableValueFormatter = (\n type: arrow.DataType,\n value: unknown,\n) => string | undefined;\n\nexport type UseArrowDataTableOptions = {\n /** Custom font size for the table e.g. xs, sm, md, lg, base */\n fontSize?: string;\n /**\n * Custom value formatter that overrides the default valueToString.\n * Return a string to use your custom formatting, or undefined to fall back to the default.\n */\n formatValue?: ArrowDataTableValueFormatter;\n};\n\n// Only use for small tables or in combination with pagination\nexport default function useArrowDataTable(\n table: arrow.Table | undefined,\n options: UseArrowDataTableOptions = {},\n): UseArrowDataTableResult | undefined {\n const {fontSize = 'base', formatValue} = options;\n const fontSizeClass = resolveFontSizeClass(fontSize);\n const data = useMemo(() => ({length: table?.numRows ?? 0}), [table]);\n const columns = useMemo(() => {\n if (!table) return undefined;\n const columns: ColumnDef<any, any>[] = [];\n for (const field of table.schema.fields) {\n columns.push(\n columnHelper.accessor((_row, i) => table.getChild(field.name)?.get(i), {\n cell: (info) => {\n const value = info.getValue();\n const valueStr =\n formatValue?.(field.type, value) ??\n valueToString(field.type, value);\n const parsedJson = safeJsonParse<unknown>(valueStr);\n const isJsonValue = parsedJson !== undefined;\n\n return valueStr.length > MAX_VALUE_LENGTH ? (\n <Popover>\n <PopoverTrigger asChild>\n <span className=\"cursor-pointer\">\n {shorten(`${valueStr}`, MAX_VALUE_LENGTH)}\n </span>\n </PopoverTrigger>\n\n {/* Fixed PopoverContent width */}\n <PopoverContent\n sideOffset={4}\n align=\"center\"\n className={`w-[400px] max-w-[90vw] p-4 ${fontSizeClass} rounded-md shadow-md`}\n >\n <div className=\"space-y-2\">\n {/* Header row */}\n <div className=\"flex items-center gap-2 text-xs\">\n <span\n className=\"min-w-0 flex-1 font-medium\"\n title={field.name}\n >\n {shorten(field.name, MAX_VALUE_LENGTH)}\n </span>\n <span className=\"text-muted-foreground shrink-0\">\n {`(${field.type})`}\n </span>\n </div>\n\n {/* Scrollable content - JSON or raw text */}\n <div className=\"max-h-[300px] min-h-[100px] overflow-auto\">\n {isJsonValue && parsedJson ? (\n <JsonMonacoEditor\n value={parsedJson as any}\n readOnly={true}\n options={{\n lineNumbers: 'off',\n minimap: {enabled: false},\n scrollBeyondLastLine: false,\n wordWrap: 'on',\n }}\n />\n ) : (\n <div className=\"font-mono text-xs break-words whitespace-pre-wrap\">\n {valueStr}\n </div>\n )}\n </div>\n\n {/* Copy button */}\n <div className=\"mt-2 flex justify-end\">\n <Button\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => navigator.clipboard.writeText(valueStr)}\n >\n <ClipboardIcon className=\"h-3 w-3\" />\n </Button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n ) : (\n valueStr\n );\n },\n header: shorten(field.name, MAX_VALUE_LENGTH),\n meta: {\n type: field.type,\n isNumeric:\n arrow.DataType.isFloat(field.type) ||\n arrow.DataType.isDecimal(field.type) ||\n arrow.DataType.isInt(field.type),\n },\n }),\n );\n }\n return columns;\n }, [table, fontSizeClass, formatValue]);\n\n return data && columns ? {data, columns} : undefined;\n}\n"]}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@sqlrooms/data-table",
3
- "version": "0.26.1-rc.7",
3
+ "version": "0.27.0-rc.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
7
7
  "type": "module",
8
8
  "sideEffects": false,
9
- "author": "Ilya Boyandin <ilya@boyandin.me>",
9
+ "author": "SQLRooms Contributors",
10
10
  "license": "MIT",
11
11
  "repository": {
12
12
  "type": "git",
@@ -19,12 +19,13 @@
19
19
  "access": "public"
20
20
  },
21
21
  "dependencies": {
22
- "@sqlrooms/duckdb": "0.26.1-rc.7",
23
- "@sqlrooms/ui": "0.26.1-rc.7",
24
- "@sqlrooms/utils": "0.26.1-rc.7",
22
+ "@sqlrooms/duckdb": "0.27.0-rc.1",
23
+ "@sqlrooms/monaco-editor": "0.27.0-rc.1",
24
+ "@sqlrooms/ui": "0.27.0-rc.1",
25
+ "@sqlrooms/utils": "0.27.0-rc.1",
25
26
  "@tanstack/react-table": "^8.21.3",
26
27
  "@tanstack/table-core": "^8.21.3",
27
- "lucide-react": "^0.555.0",
28
+ "lucide-react": "^0.556.0",
28
29
  "react-virtual": "2.10.4"
29
30
  },
30
31
  "peerDependencies": {
@@ -39,5 +40,5 @@
39
40
  "typecheck": "tsc --noEmit",
40
41
  "typedoc": "typedoc"
41
42
  },
42
- "gitHead": "ca84c57cb88c90be981083ee366f83bc805ba899"
43
+ "gitHead": "392da9702a049dc3d57fa467bbbf52bf2db7ffd1"
43
44
  }