@raystack/apsara 0.56.5 → 0.56.7
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/dist/components/data-table/components/content.cjs +5 -5
- package/dist/components/data-table/components/content.cjs.map +1 -1
- package/dist/components/data-table/components/content.d.ts.map +1 -1
- package/dist/components/data-table/components/content.js +5 -5
- package/dist/components/data-table/components/content.js.map +1 -1
- package/dist/components/data-table/components/virtualized-content.cjs +5 -5
- package/dist/components/data-table/components/virtualized-content.cjs.map +1 -1
- package/dist/components/data-table/components/virtualized-content.d.ts.map +1 -1
- package/dist/components/data-table/components/virtualized-content.js +5 -5
- package/dist/components/data-table/components/virtualized-content.js.map +1 -1
- package/dist/components/data-table/data-table.cjs +29 -23
- package/dist/components/data-table/data-table.cjs.map +1 -1
- package/dist/components/data-table/data-table.d.ts +7 -7
- package/dist/components/data-table/data-table.d.ts.map +1 -1
- package/dist/components/data-table/data-table.js +30 -24
- package/dist/components/data-table/data-table.js.map +1 -1
- package/dist/components/data-table/data-table.types.cjs.map +1 -1
- package/dist/components/data-table/data-table.types.d.ts +1 -0
- package/dist/components/data-table/data-table.types.d.ts.map +1 -1
- package/dist/components/data-table/data-table.types.js.map +1 -1
- package/dist/components/data-table/hooks/useFilters.cjs +6 -5
- package/dist/components/data-table/hooks/useFilters.cjs.map +1 -1
- package/dist/components/data-table/hooks/useFilters.d.ts.map +1 -1
- package/dist/components/data-table/hooks/useFilters.js +6 -5
- package/dist/components/data-table/hooks/useFilters.js.map +1 -1
- package/dist/components/data-table/utils/index.cjs +12 -0
- package/dist/components/data-table/utils/index.cjs.map +1 -1
- package/dist/components/data-table/utils/index.d.ts +5 -0
- package/dist/components/data-table/utils/index.d.ts.map +1 -1
- package/dist/components/data-table/utils/index.js +12 -1
- package/dist/components/data-table/utils/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +2 -2
|
@@ -13,6 +13,7 @@ var skeleton = require('../../skeleton/skeleton.cjs');
|
|
|
13
13
|
var table = require('../../table/table.cjs');
|
|
14
14
|
var dataTable_module = require('../data-table.module.css.cjs');
|
|
15
15
|
var useDataTable = require('../hooks/useDataTable.cjs');
|
|
16
|
+
var index = require('../utils/index.cjs');
|
|
16
17
|
|
|
17
18
|
function Headers({ headerGroups = [], className = '' }) {
|
|
18
19
|
return (jsxRuntime.jsx(table.Table.Header, { className: className, children: headerGroups?.map(headerGroup => (jsxRuntime.jsx(table.Table.Row, { children: headerGroup?.headers?.map(header => {
|
|
@@ -47,7 +48,7 @@ function Rows({ rows = [], onRowClick, classNames, lastRowRef }) {
|
|
|
47
48
|
}
|
|
48
49
|
const DefaultEmptyComponent = () => (jsxRuntime.jsx(emptyState.EmptyState, { icon: jsxRuntime.jsx(reactIcons.TableIcon, {}), heading: 'No Data' }));
|
|
49
50
|
function Content({ emptyState, zeroState, classNames = {} }) {
|
|
50
|
-
const { onRowClick, table: table$1, mode, isLoading, loadMoreData, loadingRowCount = 3, tableQuery } = useDataTable.useDataTable();
|
|
51
|
+
const { onRowClick, table: table$1, mode, isLoading, loadMoreData, loadingRowCount = 3, tableQuery, defaultSort } = useDataTable.useDataTable();
|
|
51
52
|
const headerGroups = table$1?.getHeaderGroups();
|
|
52
53
|
const rowModel = table$1?.getRowModel();
|
|
53
54
|
const { rows = [] } = rowModel || {};
|
|
@@ -81,10 +82,9 @@ function Content({ emptyState, zeroState, classNames = {} }) {
|
|
|
81
82
|
}, [mode, rows.length, handleObserver]);
|
|
82
83
|
const visibleColumnsLength = table$1.getVisibleLeafColumns().length;
|
|
83
84
|
const hasData = rows?.length > 0 || isLoading;
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
const isEmptyState = !hasData && hasFiltersOrSearch;
|
|
85
|
+
const hasChanges = index.hasActiveQuery(tableQuery || {}, defaultSort);
|
|
86
|
+
const isZeroState = !hasData && !hasChanges;
|
|
87
|
+
const isEmptyState = !hasData && hasChanges;
|
|
88
88
|
const stateToShow = isZeroState
|
|
89
89
|
? (zeroState ?? emptyState ?? jsxRuntime.jsx(DefaultEmptyComponent, {}))
|
|
90
90
|
: isEmptyState
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.cjs","sources":["../../../../components/data-table/components/content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useEffect, useRef } from 'react';\n\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport { Table } from '../../table';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n DataTableContentProps,\n GroupedData\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\n\nfunction Headers<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <Table.Header className={className}>\n {headerGroups?.map(headerGroup => (\n <Table.Row key={headerGroup?.id}>\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <Table.Head\n key={header.id}\n colSpan={header.colSpan}\n className={cx(styles.head, columnDef.classNames?.header)}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </Table.Head>\n );\n })}\n </Table.Row>\n ))}\n </Table.Header>\n );\n}\n\ninterface RowsProps<TData> {\n rows: Row<TData>[];\n onRowClick?: (row: TData) => void;\n classNames?: {\n row?: string;\n };\n lastRowRef?: React.RefObject<HTMLTableRowElement | null>;\n}\n\nfunction LoaderRows({\n rowCount,\n columnCount\n}: {\n rowCount: number;\n columnCount: number;\n}) {\n const rows = Array.from({ length: rowCount });\n return rows.map((_, rowIndex) => {\n const columns = Array.from({ length: columnCount });\n return (\n <Table.Row key={'loading-row-' + rowIndex}>\n {columns.map((_, colIndex) => (\n <Table.Cell key={'loading-column-' + colIndex}>\n <Skeleton />\n </Table.Cell>\n ))}\n </Table.Row>\n );\n });\n}\n\nfunction GroupHeader<TData>({\n colSpan,\n data\n}: {\n colSpan: number;\n data: GroupedData<TData>;\n}) {\n return (\n <Table.SectionHeader colSpan={colSpan}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </Table.SectionHeader>\n );\n}\n\nfunction Rows<TData>({\n rows = [],\n onRowClick,\n classNames,\n lastRowRef\n}: RowsProps<TData>) {\n return rows.map((row, idx) => {\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const isLastRow = idx === rows.length - 1;\n\n if (isGroupHeader) {\n return (\n <GroupHeader\n key={row.id}\n colSpan={cells.length}\n data={row.original as GroupedData<unknown>}\n />\n );\n }\n\n return (\n <Table.Row\n key={row.id}\n className={cx(\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n data-state={isSelected && 'selected'}\n ref={isLastRow ? lastRowRef : undefined}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <Table.Cell\n key={cell.id}\n className={cx(styles['cell'], columnDef.classNames?.cell)}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </Table.Cell>\n );\n })}\n </Table.Row>\n );\n });\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function Content({\n emptyState,\n zeroState,\n classNames = {}\n}: DataTableContentProps) {\n const {\n onRowClick,\n table,\n mode,\n isLoading,\n loadMoreData,\n loadingRowCount = 3,\n tableQuery\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const lastRowRef = useRef<HTMLTableRowElement | null>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n\n const handleObserver = useCallback(\n (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && !isLoading) {\n loadMoreData();\n }\n },\n [loadMoreData, isLoading]\n );\n\n useEffect(() => {\n if (mode !== 'server') return;\n\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n\n observerRef.current = new IntersectionObserver(handleObserver, {\n threshold: 0.1\n });\n const lastRow = lastRowRef.current;\n if (lastRow) {\n observerRef.current.observe(lastRow);\n }\n\n return () => {\n if (observerRef.current && lastRow) {\n observerRef.current.unobserve(lastRow);\n observerRef.current.disconnect();\n }\n };\n }, [mode, rows.length, handleObserver]);\n\n const visibleColumnsLength = table.getVisibleLeafColumns().length;\n\n const hasData = rows?.length > 0 || isLoading;\n\n const
|
|
1
|
+
{"version":3,"file":"content.cjs","sources":["../../../../components/data-table/components/content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useEffect, useRef } from 'react';\n\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport { Table } from '../../table';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n DataTableContentProps,\n GroupedData\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\nimport { hasActiveQuery } from '../utils';\n\nfunction Headers<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <Table.Header className={className}>\n {headerGroups?.map(headerGroup => (\n <Table.Row key={headerGroup?.id}>\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <Table.Head\n key={header.id}\n colSpan={header.colSpan}\n className={cx(styles.head, columnDef.classNames?.header)}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </Table.Head>\n );\n })}\n </Table.Row>\n ))}\n </Table.Header>\n );\n}\n\ninterface RowsProps<TData> {\n rows: Row<TData>[];\n onRowClick?: (row: TData) => void;\n classNames?: {\n row?: string;\n };\n lastRowRef?: React.RefObject<HTMLTableRowElement | null>;\n}\n\nfunction LoaderRows({\n rowCount,\n columnCount\n}: {\n rowCount: number;\n columnCount: number;\n}) {\n const rows = Array.from({ length: rowCount });\n return rows.map((_, rowIndex) => {\n const columns = Array.from({ length: columnCount });\n return (\n <Table.Row key={'loading-row-' + rowIndex}>\n {columns.map((_, colIndex) => (\n <Table.Cell key={'loading-column-' + colIndex}>\n <Skeleton />\n </Table.Cell>\n ))}\n </Table.Row>\n );\n });\n}\n\nfunction GroupHeader<TData>({\n colSpan,\n data\n}: {\n colSpan: number;\n data: GroupedData<TData>;\n}) {\n return (\n <Table.SectionHeader colSpan={colSpan}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </Table.SectionHeader>\n );\n}\n\nfunction Rows<TData>({\n rows = [],\n onRowClick,\n classNames,\n lastRowRef\n}: RowsProps<TData>) {\n return rows.map((row, idx) => {\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const isLastRow = idx === rows.length - 1;\n\n if (isGroupHeader) {\n return (\n <GroupHeader\n key={row.id}\n colSpan={cells.length}\n data={row.original as GroupedData<unknown>}\n />\n );\n }\n\n return (\n <Table.Row\n key={row.id}\n className={cx(\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n data-state={isSelected && 'selected'}\n ref={isLastRow ? lastRowRef : undefined}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <Table.Cell\n key={cell.id}\n className={cx(styles['cell'], columnDef.classNames?.cell)}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </Table.Cell>\n );\n })}\n </Table.Row>\n );\n });\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function Content({\n emptyState,\n zeroState,\n classNames = {}\n}: DataTableContentProps) {\n const {\n onRowClick,\n table,\n mode,\n isLoading,\n loadMoreData,\n loadingRowCount = 3,\n tableQuery,\n defaultSort\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const lastRowRef = useRef<HTMLTableRowElement | null>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n\n const handleObserver = useCallback(\n (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && !isLoading) {\n loadMoreData();\n }\n },\n [loadMoreData, isLoading]\n );\n\n useEffect(() => {\n if (mode !== 'server') return;\n\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n\n observerRef.current = new IntersectionObserver(handleObserver, {\n threshold: 0.1\n });\n const lastRow = lastRowRef.current;\n if (lastRow) {\n observerRef.current.observe(lastRow);\n }\n\n return () => {\n if (observerRef.current && lastRow) {\n observerRef.current.unobserve(lastRow);\n observerRef.current.disconnect();\n }\n };\n }, [mode, rows.length, handleObserver]);\n\n const visibleColumnsLength = table.getVisibleLeafColumns().length;\n\n const hasData = rows?.length > 0 || isLoading;\n\n const hasChanges = hasActiveQuery(tableQuery || {}, defaultSort);\n\n const isZeroState = !hasData && !hasChanges;\n const isEmptyState = !hasData && hasChanges;\n\n const stateToShow: React.ReactNode = isZeroState\n ? (zeroState ?? emptyState ?? <DefaultEmptyComponent />)\n : isEmptyState\n ? (emptyState ?? <DefaultEmptyComponent />)\n : null;\n\n return (\n <div className={cx(styles.contentRoot, classNames.root)}>\n <Table className={classNames.table}>\n {hasData && (\n <Headers headerGroups={headerGroups} className={classNames.header} />\n )}\n <Table.Body className={classNames.body}>\n {hasData ? (\n <>\n <Rows\n rows={rows}\n lastRowRef={lastRowRef}\n onRowClick={onRowClick}\n classNames={{\n row: classNames.row\n }}\n />\n {isLoading ? (\n <LoaderRows\n rowCount={loadingRowCount}\n columnCount={visibleColumnsLength}\n />\n ) : null}\n </>\n ) : (\n <Table.Row>\n <Table.Cell\n colSpan={visibleColumnsLength}\n className={styles.emptyStateCell}\n >\n {stateToShow}\n </Table.Cell>\n </Table.Row>\n )}\n </Table.Body>\n </Table>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAsBA;AAOE;AAKU;;;AAmBZ;AAWA;AAOE;;AAEE;AACA;AASF;AACF;AAEA;;AAiBA;AAEA;;AAOI;;AAEA;;;;;AAaA;AAaM;;AAaF;AAGN;AACF;AAEA;AAIM;;AAgBJ;AACA;;AAGA;AACA;AAEA;AAEI;AACA;AACE;;AAEJ;;;;AAOA;AACE;;AAGF;AACE;AACD;AACD;;AAEE;;AAGF;AACE;AACE;AACA;;AAEJ;;;;;AASF;AACA;;;AAIE;AACE;;AAGJ;;;AAsCF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../../../components/data-table/components/content.tsx"],"names":[],"mappings":"AAcA,OAAO,EAEL,qBAAqB,EAEtB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../../../components/data-table/components/content.tsx"],"names":[],"mappings":"AAcA,OAAO,EAEL,qBAAqB,EAEtB,MAAM,qBAAqB,CAAC;AAiJ7B,wBAAgB,OAAO,CAAC,EACtB,UAAU,EACV,SAAS,EACT,UAAe,EAChB,EAAE,qBAAqB,2CAyGvB"}
|
|
@@ -11,6 +11,7 @@ import { Skeleton } from '../../skeleton/skeleton.js';
|
|
|
11
11
|
import { Table } from '../../table/table.js';
|
|
12
12
|
import styles from '../data-table.module.css.js';
|
|
13
13
|
import { useDataTable } from '../hooks/useDataTable.js';
|
|
14
|
+
import { hasActiveQuery } from '../utils/index.js';
|
|
14
15
|
|
|
15
16
|
function Headers({ headerGroups = [], className = '' }) {
|
|
16
17
|
return (jsx(Table.Header, { className: className, children: headerGroups?.map(headerGroup => (jsx(Table.Row, { children: headerGroup?.headers?.map(header => {
|
|
@@ -45,7 +46,7 @@ function Rows({ rows = [], onRowClick, classNames, lastRowRef }) {
|
|
|
45
46
|
}
|
|
46
47
|
const DefaultEmptyComponent = () => (jsx(EmptyState, { icon: jsx(TableIcon, {}), heading: 'No Data' }));
|
|
47
48
|
function Content({ emptyState, zeroState, classNames = {} }) {
|
|
48
|
-
const { onRowClick, table, mode, isLoading, loadMoreData, loadingRowCount = 3, tableQuery } = useDataTable();
|
|
49
|
+
const { onRowClick, table, mode, isLoading, loadMoreData, loadingRowCount = 3, tableQuery, defaultSort } = useDataTable();
|
|
49
50
|
const headerGroups = table?.getHeaderGroups();
|
|
50
51
|
const rowModel = table?.getRowModel();
|
|
51
52
|
const { rows = [] } = rowModel || {};
|
|
@@ -79,10 +80,9 @@ function Content({ emptyState, zeroState, classNames = {} }) {
|
|
|
79
80
|
}, [mode, rows.length, handleObserver]);
|
|
80
81
|
const visibleColumnsLength = table.getVisibleLeafColumns().length;
|
|
81
82
|
const hasData = rows?.length > 0 || isLoading;
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
const isEmptyState = !hasData && hasFiltersOrSearch;
|
|
83
|
+
const hasChanges = hasActiveQuery(tableQuery || {}, defaultSort);
|
|
84
|
+
const isZeroState = !hasData && !hasChanges;
|
|
85
|
+
const isEmptyState = !hasData && hasChanges;
|
|
86
86
|
const stateToShow = isZeroState
|
|
87
87
|
? (zeroState ?? emptyState ?? jsx(DefaultEmptyComponent, {}))
|
|
88
88
|
: isEmptyState
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sources":["../../../../components/data-table/components/content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useEffect, useRef } from 'react';\n\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport { Table } from '../../table';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n DataTableContentProps,\n GroupedData\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\n\nfunction Headers<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <Table.Header className={className}>\n {headerGroups?.map(headerGroup => (\n <Table.Row key={headerGroup?.id}>\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <Table.Head\n key={header.id}\n colSpan={header.colSpan}\n className={cx(styles.head, columnDef.classNames?.header)}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </Table.Head>\n );\n })}\n </Table.Row>\n ))}\n </Table.Header>\n );\n}\n\ninterface RowsProps<TData> {\n rows: Row<TData>[];\n onRowClick?: (row: TData) => void;\n classNames?: {\n row?: string;\n };\n lastRowRef?: React.RefObject<HTMLTableRowElement | null>;\n}\n\nfunction LoaderRows({\n rowCount,\n columnCount\n}: {\n rowCount: number;\n columnCount: number;\n}) {\n const rows = Array.from({ length: rowCount });\n return rows.map((_, rowIndex) => {\n const columns = Array.from({ length: columnCount });\n return (\n <Table.Row key={'loading-row-' + rowIndex}>\n {columns.map((_, colIndex) => (\n <Table.Cell key={'loading-column-' + colIndex}>\n <Skeleton />\n </Table.Cell>\n ))}\n </Table.Row>\n );\n });\n}\n\nfunction GroupHeader<TData>({\n colSpan,\n data\n}: {\n colSpan: number;\n data: GroupedData<TData>;\n}) {\n return (\n <Table.SectionHeader colSpan={colSpan}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </Table.SectionHeader>\n );\n}\n\nfunction Rows<TData>({\n rows = [],\n onRowClick,\n classNames,\n lastRowRef\n}: RowsProps<TData>) {\n return rows.map((row, idx) => {\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const isLastRow = idx === rows.length - 1;\n\n if (isGroupHeader) {\n return (\n <GroupHeader\n key={row.id}\n colSpan={cells.length}\n data={row.original as GroupedData<unknown>}\n />\n );\n }\n\n return (\n <Table.Row\n key={row.id}\n className={cx(\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n data-state={isSelected && 'selected'}\n ref={isLastRow ? lastRowRef : undefined}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <Table.Cell\n key={cell.id}\n className={cx(styles['cell'], columnDef.classNames?.cell)}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </Table.Cell>\n );\n })}\n </Table.Row>\n );\n });\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function Content({\n emptyState,\n zeroState,\n classNames = {}\n}: DataTableContentProps) {\n const {\n onRowClick,\n table,\n mode,\n isLoading,\n loadMoreData,\n loadingRowCount = 3,\n tableQuery\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const lastRowRef = useRef<HTMLTableRowElement | null>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n\n const handleObserver = useCallback(\n (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && !isLoading) {\n loadMoreData();\n }\n },\n [loadMoreData, isLoading]\n );\n\n useEffect(() => {\n if (mode !== 'server') return;\n\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n\n observerRef.current = new IntersectionObserver(handleObserver, {\n threshold: 0.1\n });\n const lastRow = lastRowRef.current;\n if (lastRow) {\n observerRef.current.observe(lastRow);\n }\n\n return () => {\n if (observerRef.current && lastRow) {\n observerRef.current.unobserve(lastRow);\n observerRef.current.disconnect();\n }\n };\n }, [mode, rows.length, handleObserver]);\n\n const visibleColumnsLength = table.getVisibleLeafColumns().length;\n\n const hasData = rows?.length > 0 || isLoading;\n\n const
|
|
1
|
+
{"version":3,"file":"content.js","sources":["../../../../components/data-table/components/content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useEffect, useRef } from 'react';\n\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport { Table } from '../../table';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n DataTableContentProps,\n GroupedData\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\nimport { hasActiveQuery } from '../utils';\n\nfunction Headers<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <Table.Header className={className}>\n {headerGroups?.map(headerGroup => (\n <Table.Row key={headerGroup?.id}>\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <Table.Head\n key={header.id}\n colSpan={header.colSpan}\n className={cx(styles.head, columnDef.classNames?.header)}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </Table.Head>\n );\n })}\n </Table.Row>\n ))}\n </Table.Header>\n );\n}\n\ninterface RowsProps<TData> {\n rows: Row<TData>[];\n onRowClick?: (row: TData) => void;\n classNames?: {\n row?: string;\n };\n lastRowRef?: React.RefObject<HTMLTableRowElement | null>;\n}\n\nfunction LoaderRows({\n rowCount,\n columnCount\n}: {\n rowCount: number;\n columnCount: number;\n}) {\n const rows = Array.from({ length: rowCount });\n return rows.map((_, rowIndex) => {\n const columns = Array.from({ length: columnCount });\n return (\n <Table.Row key={'loading-row-' + rowIndex}>\n {columns.map((_, colIndex) => (\n <Table.Cell key={'loading-column-' + colIndex}>\n <Skeleton />\n </Table.Cell>\n ))}\n </Table.Row>\n );\n });\n}\n\nfunction GroupHeader<TData>({\n colSpan,\n data\n}: {\n colSpan: number;\n data: GroupedData<TData>;\n}) {\n return (\n <Table.SectionHeader colSpan={colSpan}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </Table.SectionHeader>\n );\n}\n\nfunction Rows<TData>({\n rows = [],\n onRowClick,\n classNames,\n lastRowRef\n}: RowsProps<TData>) {\n return rows.map((row, idx) => {\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const isLastRow = idx === rows.length - 1;\n\n if (isGroupHeader) {\n return (\n <GroupHeader\n key={row.id}\n colSpan={cells.length}\n data={row.original as GroupedData<unknown>}\n />\n );\n }\n\n return (\n <Table.Row\n key={row.id}\n className={cx(\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n data-state={isSelected && 'selected'}\n ref={isLastRow ? lastRowRef : undefined}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <Table.Cell\n key={cell.id}\n className={cx(styles['cell'], columnDef.classNames?.cell)}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </Table.Cell>\n );\n })}\n </Table.Row>\n );\n });\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function Content({\n emptyState,\n zeroState,\n classNames = {}\n}: DataTableContentProps) {\n const {\n onRowClick,\n table,\n mode,\n isLoading,\n loadMoreData,\n loadingRowCount = 3,\n tableQuery,\n defaultSort\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const lastRowRef = useRef<HTMLTableRowElement | null>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n\n const handleObserver = useCallback(\n (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && !isLoading) {\n loadMoreData();\n }\n },\n [loadMoreData, isLoading]\n );\n\n useEffect(() => {\n if (mode !== 'server') return;\n\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n\n observerRef.current = new IntersectionObserver(handleObserver, {\n threshold: 0.1\n });\n const lastRow = lastRowRef.current;\n if (lastRow) {\n observerRef.current.observe(lastRow);\n }\n\n return () => {\n if (observerRef.current && lastRow) {\n observerRef.current.unobserve(lastRow);\n observerRef.current.disconnect();\n }\n };\n }, [mode, rows.length, handleObserver]);\n\n const visibleColumnsLength = table.getVisibleLeafColumns().length;\n\n const hasData = rows?.length > 0 || isLoading;\n\n const hasChanges = hasActiveQuery(tableQuery || {}, defaultSort);\n\n const isZeroState = !hasData && !hasChanges;\n const isEmptyState = !hasData && hasChanges;\n\n const stateToShow: React.ReactNode = isZeroState\n ? (zeroState ?? emptyState ?? <DefaultEmptyComponent />)\n : isEmptyState\n ? (emptyState ?? <DefaultEmptyComponent />)\n : null;\n\n return (\n <div className={cx(styles.contentRoot, classNames.root)}>\n <Table className={classNames.table}>\n {hasData && (\n <Headers headerGroups={headerGroups} className={classNames.header} />\n )}\n <Table.Body className={classNames.body}>\n {hasData ? (\n <>\n <Rows\n rows={rows}\n lastRowRef={lastRowRef}\n onRowClick={onRowClick}\n classNames={{\n row: classNames.row\n }}\n />\n {isLoading ? (\n <LoaderRows\n rowCount={loadingRowCount}\n columnCount={visibleColumnsLength}\n />\n ) : null}\n </>\n ) : (\n <Table.Row>\n <Table.Cell\n colSpan={visibleColumnsLength}\n className={styles.emptyStateCell}\n >\n {stateToShow}\n </Table.Cell>\n </Table.Row>\n )}\n </Table.Body>\n </Table>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAsBA;AAOE;AAKU;;;AAmBZ;AAWA;AAOE;;AAEE;AACA;AASF;AACF;AAEA;;AAiBA;AAEA;;AAOI;;AAEA;;;;;AAaA;AAaM;;AAaF;AAGN;AACF;AAEA;AAIM;;AAgBJ;AACA;;AAGA;AACA;AAEA;AAEI;AACA;AACE;;AAEJ;;;;AAOA;AACE;;AAGF;AACE;AACD;AACD;;AAEE;;AAGF;AACE;AACE;AACA;;AAEJ;;;;;AASF;AACA;;;AAIE;AACE;;AAGJ;;;AAsCF;;"}
|
|
@@ -14,6 +14,7 @@ var flex = require('../../flex/flex.cjs');
|
|
|
14
14
|
var skeleton = require('../../skeleton/skeleton.cjs');
|
|
15
15
|
var dataTable_module = require('../data-table.module.css.cjs');
|
|
16
16
|
var useDataTable = require('../hooks/useDataTable.cjs');
|
|
17
|
+
var index = require('../utils/index.cjs');
|
|
17
18
|
|
|
18
19
|
function VirtualHeaders({ headerGroups = [], className = '' }) {
|
|
19
20
|
return (jsxRuntime.jsx("div", { role: 'rowgroup', className: classVarianceAuthority.cx(dataTable_module.default.virtualHeaderGroup, className), children: headerGroups?.map(headerGroup => (jsxRuntime.jsx("div", { role: 'row', className: dataTable_module.default.virtualHeaderRow, children: headerGroup?.headers?.map(header => {
|
|
@@ -55,7 +56,7 @@ function VirtualLoaderRows({ columns, rowHeight, count }) {
|
|
|
55
56
|
}
|
|
56
57
|
const DefaultEmptyComponent = () => (jsxRuntime.jsx(emptyState.EmptyState, { icon: jsxRuntime.jsx(reactIcons.TableIcon, {}), heading: 'No Data' }));
|
|
57
58
|
function VirtualizedContent({ rowHeight = 40, groupHeaderHeight, overscan = 5, loadMoreOffset = 100, emptyState, zeroState, classNames = {} }) {
|
|
58
|
-
const { onRowClick, table, isLoading, loadMoreData, tableQuery, loadingRowCount = 3 } = useDataTable.useDataTable();
|
|
59
|
+
const { onRowClick, table, isLoading, loadMoreData, tableQuery, defaultSort, loadingRowCount = 3 } = useDataTable.useDataTable();
|
|
59
60
|
const headerGroups = table?.getHeaderGroups();
|
|
60
61
|
const rowModel = table?.getRowModel();
|
|
61
62
|
const { rows = [] } = rowModel || {};
|
|
@@ -81,10 +82,9 @@ function VirtualizedContent({ rowHeight = 40, groupHeaderHeight, overscan = 5, l
|
|
|
81
82
|
}, [isLoading, loadMoreData, loadMoreOffset]);
|
|
82
83
|
const totalHeight = virtualizer.getTotalSize();
|
|
83
84
|
const hasData = rows?.length > 0 || isLoading;
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
const isEmptyState = !hasData && hasFiltersOrSearch;
|
|
85
|
+
const hasChanges = index.hasActiveQuery(tableQuery || {}, defaultSort);
|
|
86
|
+
const isZeroState = !hasData && !hasChanges;
|
|
87
|
+
const isEmptyState = !hasData && hasChanges;
|
|
88
88
|
const stateToShow = isZeroState
|
|
89
89
|
? (zeroState ?? emptyState ?? jsxRuntime.jsx(DefaultEmptyComponent, {}))
|
|
90
90
|
: isEmptyState
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualized-content.cjs","sources":["../../../../components/data-table/components/virtualized-content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useRef } from 'react';\nimport tableStyles from '~/components/table/table.module.css';\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n GroupedData,\n VirtualizedContentProps\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\n\nfunction VirtualHeaders<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <div role='rowgroup' className={cx(styles.virtualHeaderGroup, className)}>\n {headerGroups?.map(headerGroup => (\n <div\n role='row'\n key={headerGroup?.id}\n className={styles.virtualHeaderRow}\n >\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <div\n role='columnheader'\n key={header.id}\n className={cx(\n tableStyles.head,\n styles.virtualHead,\n columnDef.classNames?.header\n )}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nfunction VirtualGroupHeader<TData>({\n data,\n style\n}: {\n data: GroupedData<TData>;\n style?: React.CSSProperties;\n}) {\n return (\n <div role='row' className={styles.virtualSectionHeader} style={style}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </div>\n );\n}\n\nfunction VirtualRows<TData>({\n rows,\n virtualizer,\n onRowClick,\n classNames\n}: {\n rows: Row<TData>[];\n virtualizer: ReturnType<typeof useVirtualizer>;\n onRowClick?: (row: TData) => void;\n classNames?: { row?: string };\n}) {\n const items = virtualizer.getVirtualItems();\n\n return items.map((item, idx) => {\n const row = rows[item.index];\n if (!row) return null;\n\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const rowKey = row.id + '-' + item.index;\n\n const positionStyle: React.CSSProperties = {\n height: item.size,\n top: item.start\n };\n\n if (isGroupHeader) {\n return (\n <VirtualGroupHeader\n key={rowKey}\n data={row.original as GroupedData<unknown>}\n style={positionStyle}\n />\n );\n }\n\n return (\n <div\n role='row'\n key={rowKey}\n className={cx(\n styles.virtualRow,\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n style={positionStyle}\n data-state={isSelected && 'selected'}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={cell.id}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </div>\n );\n })}\n </div>\n );\n });\n}\n\nfunction VirtualLoaderRows({\n columns,\n rowHeight,\n count\n}: {\n columns: ReturnType<\n ReturnType<typeof useDataTable>['table']['getVisibleLeafColumns']\n >;\n rowHeight: number;\n count: number;\n}) {\n return (\n <div className={styles.stickyLoaderContainer}>\n {Array.from({ length: count }).map((_, rowIndex) => (\n <div\n role='row'\n key={'loading-row-' + rowIndex}\n className={cx(styles.virtualRow, styles['row'], styles.loaderRow)}\n style={{ height: rowHeight }}\n >\n {columns.map((col, colIndex) => {\n const columnDef = col.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={'loading-column-' + colIndex}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n <Skeleton containerClassName={styles['flex-1']} />\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function VirtualizedContent({\n rowHeight = 40,\n groupHeaderHeight,\n overscan = 5,\n loadMoreOffset = 100,\n emptyState,\n zeroState,\n classNames = {}\n}: VirtualizedContentProps) {\n const {\n onRowClick,\n table,\n isLoading,\n loadMoreData,\n tableQuery,\n loadingRowCount = 3\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n const showLoaderRows = isLoading && rows.length > 0;\n\n const virtualizer = useVirtualizer({\n count: rows.length,\n getScrollElement: () => scrollContainerRef.current,\n estimateSize: index => {\n const row = rows[index];\n const isGroupHeader = row?.subRows && row.subRows.length > 0;\n return isGroupHeader ? (groupHeaderHeight ?? rowHeight) : rowHeight;\n },\n overscan\n });\n\n const handleVirtualScroll = useCallback(() => {\n if (!scrollContainerRef.current || isLoading) return;\n const { scrollTop, scrollHeight, clientHeight } =\n scrollContainerRef.current;\n if (scrollHeight - scrollTop - clientHeight < loadMoreOffset) {\n loadMoreData();\n }\n }, [isLoading, loadMoreData, loadMoreOffset]);\n\n const totalHeight = virtualizer.getTotalSize();\n\n const hasData = rows?.length > 0 || isLoading;\n\n const
|
|
1
|
+
{"version":3,"file":"virtualized-content.cjs","sources":["../../../../components/data-table/components/virtualized-content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useRef } from 'react';\nimport tableStyles from '~/components/table/table.module.css';\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n GroupedData,\n VirtualizedContentProps\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\nimport { hasActiveQuery } from '../utils';\n\nfunction VirtualHeaders<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <div role='rowgroup' className={cx(styles.virtualHeaderGroup, className)}>\n {headerGroups?.map(headerGroup => (\n <div\n role='row'\n key={headerGroup?.id}\n className={styles.virtualHeaderRow}\n >\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <div\n role='columnheader'\n key={header.id}\n className={cx(\n tableStyles.head,\n styles.virtualHead,\n columnDef.classNames?.header\n )}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nfunction VirtualGroupHeader<TData>({\n data,\n style\n}: {\n data: GroupedData<TData>;\n style?: React.CSSProperties;\n}) {\n return (\n <div role='row' className={styles.virtualSectionHeader} style={style}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </div>\n );\n}\n\nfunction VirtualRows<TData>({\n rows,\n virtualizer,\n onRowClick,\n classNames\n}: {\n rows: Row<TData>[];\n virtualizer: ReturnType<typeof useVirtualizer>;\n onRowClick?: (row: TData) => void;\n classNames?: { row?: string };\n}) {\n const items = virtualizer.getVirtualItems();\n\n return items.map((item, idx) => {\n const row = rows[item.index];\n if (!row) return null;\n\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const rowKey = row.id + '-' + item.index;\n\n const positionStyle: React.CSSProperties = {\n height: item.size,\n top: item.start\n };\n\n if (isGroupHeader) {\n return (\n <VirtualGroupHeader\n key={rowKey}\n data={row.original as GroupedData<unknown>}\n style={positionStyle}\n />\n );\n }\n\n return (\n <div\n role='row'\n key={rowKey}\n className={cx(\n styles.virtualRow,\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n style={positionStyle}\n data-state={isSelected && 'selected'}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={cell.id}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </div>\n );\n })}\n </div>\n );\n });\n}\n\nfunction VirtualLoaderRows({\n columns,\n rowHeight,\n count\n}: {\n columns: ReturnType<\n ReturnType<typeof useDataTable>['table']['getVisibleLeafColumns']\n >;\n rowHeight: number;\n count: number;\n}) {\n return (\n <div className={styles.stickyLoaderContainer}>\n {Array.from({ length: count }).map((_, rowIndex) => (\n <div\n role='row'\n key={'loading-row-' + rowIndex}\n className={cx(styles.virtualRow, styles['row'], styles.loaderRow)}\n style={{ height: rowHeight }}\n >\n {columns.map((col, colIndex) => {\n const columnDef = col.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={'loading-column-' + colIndex}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n <Skeleton containerClassName={styles['flex-1']} />\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function VirtualizedContent({\n rowHeight = 40,\n groupHeaderHeight,\n overscan = 5,\n loadMoreOffset = 100,\n emptyState,\n zeroState,\n classNames = {}\n}: VirtualizedContentProps) {\n const {\n onRowClick,\n table,\n isLoading,\n loadMoreData,\n tableQuery,\n defaultSort,\n loadingRowCount = 3\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n const showLoaderRows = isLoading && rows.length > 0;\n\n const virtualizer = useVirtualizer({\n count: rows.length,\n getScrollElement: () => scrollContainerRef.current,\n estimateSize: index => {\n const row = rows[index];\n const isGroupHeader = row?.subRows && row.subRows.length > 0;\n return isGroupHeader ? (groupHeaderHeight ?? rowHeight) : rowHeight;\n },\n overscan\n });\n\n const handleVirtualScroll = useCallback(() => {\n if (!scrollContainerRef.current || isLoading) return;\n const { scrollTop, scrollHeight, clientHeight } =\n scrollContainerRef.current;\n if (scrollHeight - scrollTop - clientHeight < loadMoreOffset) {\n loadMoreData();\n }\n }, [isLoading, loadMoreData, loadMoreOffset]);\n\n const totalHeight = virtualizer.getTotalSize();\n\n const hasData = rows?.length > 0 || isLoading;\n\n const hasChanges = hasActiveQuery(tableQuery || {}, defaultSort);\n\n const isZeroState = !hasData && !hasChanges;\n const isEmptyState = !hasData && hasChanges;\n\n const stateToShow: React.ReactNode = isZeroState\n ? (zeroState ?? emptyState ?? <DefaultEmptyComponent />)\n : isEmptyState\n ? (emptyState ?? <DefaultEmptyComponent />)\n : null;\n\n if (!hasData) {\n return <div className={classNames.root}>{stateToShow}</div>;\n }\n\n const visibleColumns = table.getVisibleLeafColumns();\n\n return (\n <div\n ref={scrollContainerRef}\n className={cx(classNames.root, styles.scrollContainer)}\n onScroll={handleVirtualScroll}\n >\n <div role='table' className={cx(styles.virtualTable, classNames.table)}>\n <VirtualHeaders\n headerGroups={headerGroups}\n className={cx(styles.stickyHeader, classNames.header)}\n />\n <div\n role='rowgroup'\n className={cx(styles.virtualBodyGroup, classNames.body)}\n style={{ height: totalHeight }}\n >\n <VirtualRows\n rows={rows}\n virtualizer={virtualizer}\n onRowClick={onRowClick}\n classNames={{\n row: classNames.row\n }}\n />\n </div>\n </div>\n {showLoaderRows && (\n <VirtualLoaderRows\n columns={visibleColumns}\n rowHeight={rowHeight}\n count={loadingRowCount}\n />\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAsBA;;AAgBY;;;AAuBZ;AAEA;;AAiBA;AAEA;AAWE;;;AAIE;AAAU;AAEV;;AAEA;;AAGA;;;;;AAME;;AASF;AAeM;;AAkBF;AAGN;AACF;AAEA;AAWE;AAUU;;;AAuBZ;AAEA;AAIM;;AAmBJ;AACA;;AAGA;;;;AAME;;AAEE;AACA;AACA;;;AAGH;AAED;AACE;;;;AAIE;;;AAIJ;;;AAMA;AACA;;;AAIE;AACE;;;;;AAOJ;;;;AAqCF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualized-content.d.ts","sourceRoot":"","sources":["../../../../components/data-table/components/virtualized-content.tsx"],"names":[],"mappings":"AAcA,OAAO,EAGL,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"virtualized-content.d.ts","sourceRoot":"","sources":["../../../../components/data-table/components/virtualized-content.tsx"],"names":[],"mappings":"AAcA,OAAO,EAGL,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AA8L7B,wBAAgB,kBAAkB,CAAC,EACjC,SAAc,EACd,iBAAiB,EACjB,QAAY,EACZ,cAAoB,EACpB,UAAU,EACV,SAAS,EACT,UAAe,EAChB,EAAE,uBAAuB,2CA+FzB"}
|
|
@@ -12,6 +12,7 @@ import { Flex } from '../../flex/flex.js';
|
|
|
12
12
|
import { Skeleton } from '../../skeleton/skeleton.js';
|
|
13
13
|
import styles from '../data-table.module.css.js';
|
|
14
14
|
import { useDataTable } from '../hooks/useDataTable.js';
|
|
15
|
+
import { hasActiveQuery } from '../utils/index.js';
|
|
15
16
|
|
|
16
17
|
function VirtualHeaders({ headerGroups = [], className = '' }) {
|
|
17
18
|
return (jsx("div", { role: 'rowgroup', className: cx(styles.virtualHeaderGroup, className), children: headerGroups?.map(headerGroup => (jsx("div", { role: 'row', className: styles.virtualHeaderRow, children: headerGroup?.headers?.map(header => {
|
|
@@ -53,7 +54,7 @@ function VirtualLoaderRows({ columns, rowHeight, count }) {
|
|
|
53
54
|
}
|
|
54
55
|
const DefaultEmptyComponent = () => (jsx(EmptyState, { icon: jsx(TableIcon, {}), heading: 'No Data' }));
|
|
55
56
|
function VirtualizedContent({ rowHeight = 40, groupHeaderHeight, overscan = 5, loadMoreOffset = 100, emptyState, zeroState, classNames = {} }) {
|
|
56
|
-
const { onRowClick, table, isLoading, loadMoreData, tableQuery, loadingRowCount = 3 } = useDataTable();
|
|
57
|
+
const { onRowClick, table, isLoading, loadMoreData, tableQuery, defaultSort, loadingRowCount = 3 } = useDataTable();
|
|
57
58
|
const headerGroups = table?.getHeaderGroups();
|
|
58
59
|
const rowModel = table?.getRowModel();
|
|
59
60
|
const { rows = [] } = rowModel || {};
|
|
@@ -79,10 +80,9 @@ function VirtualizedContent({ rowHeight = 40, groupHeaderHeight, overscan = 5, l
|
|
|
79
80
|
}, [isLoading, loadMoreData, loadMoreOffset]);
|
|
80
81
|
const totalHeight = virtualizer.getTotalSize();
|
|
81
82
|
const hasData = rows?.length > 0 || isLoading;
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
const isEmptyState = !hasData && hasFiltersOrSearch;
|
|
83
|
+
const hasChanges = hasActiveQuery(tableQuery || {}, defaultSort);
|
|
84
|
+
const isZeroState = !hasData && !hasChanges;
|
|
85
|
+
const isEmptyState = !hasData && hasChanges;
|
|
86
86
|
const stateToShow = isZeroState
|
|
87
87
|
? (zeroState ?? emptyState ?? jsx(DefaultEmptyComponent, {}))
|
|
88
88
|
: isEmptyState
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualized-content.js","sources":["../../../../components/data-table/components/virtualized-content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useRef } from 'react';\nimport tableStyles from '~/components/table/table.module.css';\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n GroupedData,\n VirtualizedContentProps\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\n\nfunction VirtualHeaders<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <div role='rowgroup' className={cx(styles.virtualHeaderGroup, className)}>\n {headerGroups?.map(headerGroup => (\n <div\n role='row'\n key={headerGroup?.id}\n className={styles.virtualHeaderRow}\n >\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <div\n role='columnheader'\n key={header.id}\n className={cx(\n tableStyles.head,\n styles.virtualHead,\n columnDef.classNames?.header\n )}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nfunction VirtualGroupHeader<TData>({\n data,\n style\n}: {\n data: GroupedData<TData>;\n style?: React.CSSProperties;\n}) {\n return (\n <div role='row' className={styles.virtualSectionHeader} style={style}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </div>\n );\n}\n\nfunction VirtualRows<TData>({\n rows,\n virtualizer,\n onRowClick,\n classNames\n}: {\n rows: Row<TData>[];\n virtualizer: ReturnType<typeof useVirtualizer>;\n onRowClick?: (row: TData) => void;\n classNames?: { row?: string };\n}) {\n const items = virtualizer.getVirtualItems();\n\n return items.map((item, idx) => {\n const row = rows[item.index];\n if (!row) return null;\n\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const rowKey = row.id + '-' + item.index;\n\n const positionStyle: React.CSSProperties = {\n height: item.size,\n top: item.start\n };\n\n if (isGroupHeader) {\n return (\n <VirtualGroupHeader\n key={rowKey}\n data={row.original as GroupedData<unknown>}\n style={positionStyle}\n />\n );\n }\n\n return (\n <div\n role='row'\n key={rowKey}\n className={cx(\n styles.virtualRow,\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n style={positionStyle}\n data-state={isSelected && 'selected'}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={cell.id}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </div>\n );\n })}\n </div>\n );\n });\n}\n\nfunction VirtualLoaderRows({\n columns,\n rowHeight,\n count\n}: {\n columns: ReturnType<\n ReturnType<typeof useDataTable>['table']['getVisibleLeafColumns']\n >;\n rowHeight: number;\n count: number;\n}) {\n return (\n <div className={styles.stickyLoaderContainer}>\n {Array.from({ length: count }).map((_, rowIndex) => (\n <div\n role='row'\n key={'loading-row-' + rowIndex}\n className={cx(styles.virtualRow, styles['row'], styles.loaderRow)}\n style={{ height: rowHeight }}\n >\n {columns.map((col, colIndex) => {\n const columnDef = col.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={'loading-column-' + colIndex}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n <Skeleton containerClassName={styles['flex-1']} />\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function VirtualizedContent({\n rowHeight = 40,\n groupHeaderHeight,\n overscan = 5,\n loadMoreOffset = 100,\n emptyState,\n zeroState,\n classNames = {}\n}: VirtualizedContentProps) {\n const {\n onRowClick,\n table,\n isLoading,\n loadMoreData,\n tableQuery,\n loadingRowCount = 3\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n const showLoaderRows = isLoading && rows.length > 0;\n\n const virtualizer = useVirtualizer({\n count: rows.length,\n getScrollElement: () => scrollContainerRef.current,\n estimateSize: index => {\n const row = rows[index];\n const isGroupHeader = row?.subRows && row.subRows.length > 0;\n return isGroupHeader ? (groupHeaderHeight ?? rowHeight) : rowHeight;\n },\n overscan\n });\n\n const handleVirtualScroll = useCallback(() => {\n if (!scrollContainerRef.current || isLoading) return;\n const { scrollTop, scrollHeight, clientHeight } =\n scrollContainerRef.current;\n if (scrollHeight - scrollTop - clientHeight < loadMoreOffset) {\n loadMoreData();\n }\n }, [isLoading, loadMoreData, loadMoreOffset]);\n\n const totalHeight = virtualizer.getTotalSize();\n\n const hasData = rows?.length > 0 || isLoading;\n\n const
|
|
1
|
+
{"version":3,"file":"virtualized-content.js","sources":["../../../../components/data-table/components/virtualized-content.tsx"],"sourcesContent":["'use client';\n\nimport { TableIcon } from '@radix-ui/react-icons';\nimport type { HeaderGroup, Row } from '@tanstack/react-table';\nimport { flexRender } from '@tanstack/react-table';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useRef } from 'react';\nimport tableStyles from '~/components/table/table.module.css';\nimport { Badge } from '../../badge';\nimport { EmptyState } from '../../empty-state';\nimport { Flex } from '../../flex';\nimport { Skeleton } from '../../skeleton';\nimport styles from '../data-table.module.css';\nimport {\n DataTableColumnDef,\n GroupedData,\n VirtualizedContentProps\n} from '../data-table.types';\nimport { useDataTable } from '../hooks/useDataTable';\nimport { hasActiveQuery } from '../utils';\n\nfunction VirtualHeaders<TData>({\n headerGroups = [],\n className = ''\n}: {\n headerGroups: HeaderGroup<TData>[];\n className?: string;\n}) {\n return (\n <div role='rowgroup' className={cx(styles.virtualHeaderGroup, className)}>\n {headerGroups?.map(headerGroup => (\n <div\n role='row'\n key={headerGroup?.id}\n className={styles.virtualHeaderRow}\n >\n {headerGroup?.headers?.map(header => {\n const columnDef = header.column.columnDef as DataTableColumnDef<\n TData,\n unknown\n >;\n return (\n <div\n role='columnheader'\n key={header.id}\n className={cx(\n tableStyles.head,\n styles.virtualHead,\n columnDef.classNames?.header\n )}\n style={columnDef.styles?.header}\n >\n {flexRender(columnDef.header, header.getContext())}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nfunction VirtualGroupHeader<TData>({\n data,\n style\n}: {\n data: GroupedData<TData>;\n style?: React.CSSProperties;\n}) {\n return (\n <div role='row' className={styles.virtualSectionHeader} style={style}>\n <Flex gap={3} align='center'>\n {data?.label}\n {data.showGroupCount ? (\n <Badge variant='neutral'>{data?.count}</Badge>\n ) : null}\n </Flex>\n </div>\n );\n}\n\nfunction VirtualRows<TData>({\n rows,\n virtualizer,\n onRowClick,\n classNames\n}: {\n rows: Row<TData>[];\n virtualizer: ReturnType<typeof useVirtualizer>;\n onRowClick?: (row: TData) => void;\n classNames?: { row?: string };\n}) {\n const items = virtualizer.getVirtualItems();\n\n return items.map((item, idx) => {\n const row = rows[item.index];\n if (!row) return null;\n\n const isSelected = row.getIsSelected();\n const cells = row.getVisibleCells() || [];\n const isGroupHeader = row.subRows && row.subRows.length > 0;\n const rowKey = row.id + '-' + item.index;\n\n const positionStyle: React.CSSProperties = {\n height: item.size,\n top: item.start\n };\n\n if (isGroupHeader) {\n return (\n <VirtualGroupHeader\n key={rowKey}\n data={row.original as GroupedData<unknown>}\n style={positionStyle}\n />\n );\n }\n\n return (\n <div\n role='row'\n key={rowKey}\n className={cx(\n styles.virtualRow,\n styles['row'],\n onRowClick ? styles['clickable'] : '',\n classNames?.row\n )}\n style={positionStyle}\n data-state={isSelected && 'selected'}\n onClick={() => onRowClick?.(row.original)}\n >\n {cells.map(cell => {\n const columnDef = cell.column.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={cell.id}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n {flexRender(columnDef.cell, cell.getContext())}\n </div>\n );\n })}\n </div>\n );\n });\n}\n\nfunction VirtualLoaderRows({\n columns,\n rowHeight,\n count\n}: {\n columns: ReturnType<\n ReturnType<typeof useDataTable>['table']['getVisibleLeafColumns']\n >;\n rowHeight: number;\n count: number;\n}) {\n return (\n <div className={styles.stickyLoaderContainer}>\n {Array.from({ length: count }).map((_, rowIndex) => (\n <div\n role='row'\n key={'loading-row-' + rowIndex}\n className={cx(styles.virtualRow, styles['row'], styles.loaderRow)}\n style={{ height: rowHeight }}\n >\n {columns.map((col, colIndex) => {\n const columnDef = col.columnDef as DataTableColumnDef<\n unknown,\n unknown\n >;\n return (\n <div\n role='cell'\n key={'loading-column-' + colIndex}\n className={cx(\n tableStyles.cell,\n styles.virtualCell,\n columnDef.classNames?.cell\n )}\n style={columnDef.styles?.cell}\n >\n <Skeleton containerClassName={styles['flex-1']} />\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n\nconst DefaultEmptyComponent = () => (\n <EmptyState icon={<TableIcon />} heading='No Data' />\n);\n\nexport function VirtualizedContent({\n rowHeight = 40,\n groupHeaderHeight,\n overscan = 5,\n loadMoreOffset = 100,\n emptyState,\n zeroState,\n classNames = {}\n}: VirtualizedContentProps) {\n const {\n onRowClick,\n table,\n isLoading,\n loadMoreData,\n tableQuery,\n defaultSort,\n loadingRowCount = 3\n } = useDataTable();\n\n const headerGroups = table?.getHeaderGroups();\n const rowModel = table?.getRowModel();\n const { rows = [] } = rowModel || {};\n\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n const showLoaderRows = isLoading && rows.length > 0;\n\n const virtualizer = useVirtualizer({\n count: rows.length,\n getScrollElement: () => scrollContainerRef.current,\n estimateSize: index => {\n const row = rows[index];\n const isGroupHeader = row?.subRows && row.subRows.length > 0;\n return isGroupHeader ? (groupHeaderHeight ?? rowHeight) : rowHeight;\n },\n overscan\n });\n\n const handleVirtualScroll = useCallback(() => {\n if (!scrollContainerRef.current || isLoading) return;\n const { scrollTop, scrollHeight, clientHeight } =\n scrollContainerRef.current;\n if (scrollHeight - scrollTop - clientHeight < loadMoreOffset) {\n loadMoreData();\n }\n }, [isLoading, loadMoreData, loadMoreOffset]);\n\n const totalHeight = virtualizer.getTotalSize();\n\n const hasData = rows?.length > 0 || isLoading;\n\n const hasChanges = hasActiveQuery(tableQuery || {}, defaultSort);\n\n const isZeroState = !hasData && !hasChanges;\n const isEmptyState = !hasData && hasChanges;\n\n const stateToShow: React.ReactNode = isZeroState\n ? (zeroState ?? emptyState ?? <DefaultEmptyComponent />)\n : isEmptyState\n ? (emptyState ?? <DefaultEmptyComponent />)\n : null;\n\n if (!hasData) {\n return <div className={classNames.root}>{stateToShow}</div>;\n }\n\n const visibleColumns = table.getVisibleLeafColumns();\n\n return (\n <div\n ref={scrollContainerRef}\n className={cx(classNames.root, styles.scrollContainer)}\n onScroll={handleVirtualScroll}\n >\n <div role='table' className={cx(styles.virtualTable, classNames.table)}>\n <VirtualHeaders\n headerGroups={headerGroups}\n className={cx(styles.stickyHeader, classNames.header)}\n />\n <div\n role='rowgroup'\n className={cx(styles.virtualBodyGroup, classNames.body)}\n style={{ height: totalHeight }}\n >\n <VirtualRows\n rows={rows}\n virtualizer={virtualizer}\n onRowClick={onRowClick}\n classNames={{\n row: classNames.row\n }}\n />\n </div>\n </div>\n {showLoaderRows && (\n <VirtualLoaderRows\n columns={visibleColumns}\n rowHeight={rowHeight}\n count={loadingRowCount}\n />\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAsBA;;AAgBY;;;AAuBZ;AAEA;;AAiBA;AAEA;AAWE;;;AAIE;AAAU;AAEV;;AAEA;;AAGA;;;;;AAME;;AASF;AAeM;;AAkBF;AAGN;AACF;AAEA;AAWE;AAUU;;;AAuBZ;AAEA;AAIM;;AAmBJ;AACA;;AAGA;;;;AAME;;AAEE;AACA;AACA;;;AAGH;AAED;AACE;;;;AAIE;;;AAIJ;;;AAMA;AACA;;;AAIE;AACE;;;;;AAOJ;;;;AAqCF;;"}
|
|
@@ -14,13 +14,13 @@ var context = require('./context.cjs');
|
|
|
14
14
|
var dataTable_types = require('./data-table.types.cjs');
|
|
15
15
|
var index = require('./utils/index.cjs');
|
|
16
16
|
|
|
17
|
-
function DataTableRoot({ data = [], columns, query, mode =
|
|
18
|
-
const defaultTableQuery = index.getDefaultTableQuery(defaultSort, query);
|
|
17
|
+
function DataTableRoot({ data = [], columns, query, mode = 'client', isLoading = false, loadingRowCount = 3, defaultSort, children, onTableQueryChange, onLoadMore, onRowClick, onColumnVisibilityChange }) {
|
|
18
|
+
const defaultTableQuery = React.useMemo(() => index.getDefaultTableQuery(defaultSort, query), [defaultSort, query]);
|
|
19
19
|
const initialColumnVisibility = index.getInitialColumnVisibility(columns);
|
|
20
20
|
const [columnVisibility, setColumnVisibility] = React.useState(initialColumnVisibility);
|
|
21
21
|
const handleColumnVisibilityChange = React.useCallback((value) => {
|
|
22
|
-
setColumnVisibility(
|
|
23
|
-
const newValue = typeof value ===
|
|
22
|
+
setColumnVisibility(prev => {
|
|
23
|
+
const newValue = typeof value === 'function' ? value(prev) : value;
|
|
24
24
|
onColumnVisibilityChange?.(newValue);
|
|
25
25
|
return newValue;
|
|
26
26
|
});
|
|
@@ -29,12 +29,18 @@ function DataTableRoot({ data = [], columns, query, mode = "client", isLoading =
|
|
|
29
29
|
const oldQueryRef = React.useRef(null);
|
|
30
30
|
const reactTableState = React.useMemo(() => index.queryToTableState(tableQuery), [tableQuery]);
|
|
31
31
|
const onDisplaySettingsReset = React.useCallback(() => {
|
|
32
|
-
setTableQuery(
|
|
32
|
+
setTableQuery(prev => ({
|
|
33
|
+
...prev,
|
|
34
|
+
...defaultTableQuery,
|
|
35
|
+
sort: [defaultSort],
|
|
36
|
+
group_by: [dataTable_types.defaultGroupOption.id]
|
|
37
|
+
}));
|
|
33
38
|
handleColumnVisibilityChange(initialColumnVisibility);
|
|
34
39
|
}, [
|
|
40
|
+
defaultSort,
|
|
35
41
|
defaultTableQuery,
|
|
36
42
|
initialColumnVisibility,
|
|
37
|
-
handleColumnVisibilityChange
|
|
43
|
+
handleColumnVisibilityChange
|
|
38
44
|
]);
|
|
39
45
|
const group_by = tableQuery.group_by?.[0];
|
|
40
46
|
const columnsWithFilters = React.useMemo(() => index.getColumnsWithFilterFn(columns, tableQuery.filters), [columns, tableQuery.filters]);
|
|
@@ -43,7 +49,7 @@ function DataTableRoot({ data = [], columns, query, mode = "client", isLoading =
|
|
|
43
49
|
if (tableQuery &&
|
|
44
50
|
onTableQueryChange &&
|
|
45
51
|
index.hasQueryChanged(oldQueryRef.current, tableQuery) &&
|
|
46
|
-
mode ===
|
|
52
|
+
mode === 'server') {
|
|
47
53
|
onTableQueryChange(index.transformToDataTableQuery(tableQuery));
|
|
48
54
|
oldQueryRef.current = tableQuery;
|
|
49
55
|
}
|
|
@@ -53,37 +59,37 @@ function DataTableRoot({ data = [], columns, query, mode = "client", isLoading =
|
|
|
53
59
|
columns: columnsWithFilters,
|
|
54
60
|
getCoreRowModel: reactTable.getCoreRowModel(),
|
|
55
61
|
getExpandedRowModel: reactTable.getExpandedRowModel(),
|
|
56
|
-
getSubRows:
|
|
57
|
-
getSortedRowModel: mode ===
|
|
58
|
-
getFilteredRowModel: mode ===
|
|
59
|
-
manualSorting: mode ===
|
|
60
|
-
manualFiltering: mode ===
|
|
62
|
+
getSubRows: row => row?.subRows || [],
|
|
63
|
+
getSortedRowModel: mode === 'server' ? undefined : reactTable.getSortedRowModel(),
|
|
64
|
+
getFilteredRowModel: mode === 'server' ? undefined : reactTable.getFilteredRowModel(),
|
|
65
|
+
manualSorting: mode === 'server',
|
|
66
|
+
manualFiltering: mode === 'server',
|
|
61
67
|
onColumnVisibilityChange: handleColumnVisibilityChange,
|
|
62
|
-
globalFilterFn: mode ===
|
|
68
|
+
globalFilterFn: mode === 'server' ? undefined : 'auto',
|
|
63
69
|
initialState: {
|
|
64
|
-
columnVisibility: initialColumnVisibility
|
|
70
|
+
columnVisibility: initialColumnVisibility
|
|
65
71
|
},
|
|
66
72
|
filterFromLeafRows: true,
|
|
67
73
|
state: {
|
|
68
74
|
...reactTableState,
|
|
69
75
|
columnVisibility: columnVisibility,
|
|
70
|
-
expanded: group_by && group_by !== dataTable_types.defaultGroupOption.id ? true : undefined
|
|
71
|
-
}
|
|
76
|
+
expanded: group_by && group_by !== dataTable_types.defaultGroupOption.id ? true : undefined
|
|
77
|
+
}
|
|
72
78
|
});
|
|
73
79
|
function updateTableQuery(fn) {
|
|
74
|
-
setTableQuery(
|
|
80
|
+
setTableQuery(prev => fn(prev));
|
|
75
81
|
}
|
|
76
82
|
const loadMoreData = React.useCallback(() => {
|
|
77
|
-
if (mode ===
|
|
83
|
+
if (mode === 'server' && onLoadMore) {
|
|
78
84
|
onLoadMore();
|
|
79
85
|
}
|
|
80
86
|
}, [mode, onLoadMore]);
|
|
81
87
|
const searchQuery = query?.search;
|
|
82
88
|
React.useEffect(() => {
|
|
83
89
|
if (searchQuery) {
|
|
84
|
-
updateTableQuery(
|
|
90
|
+
updateTableQuery(prev => ({
|
|
85
91
|
...prev,
|
|
86
|
-
search: searchQuery
|
|
92
|
+
search: searchQuery
|
|
87
93
|
}));
|
|
88
94
|
}
|
|
89
95
|
}, [searchQuery]);
|
|
@@ -117,7 +123,7 @@ function DataTableRoot({ data = [], columns, query, mode = "client", isLoading =
|
|
|
117
123
|
defaultSort,
|
|
118
124
|
loadingRowCount,
|
|
119
125
|
onRowClick,
|
|
120
|
-
shouldShowFilters
|
|
126
|
+
shouldShowFilters
|
|
121
127
|
};
|
|
122
128
|
}, [
|
|
123
129
|
table,
|
|
@@ -131,7 +137,7 @@ function DataTableRoot({ data = [], columns, query, mode = "client", isLoading =
|
|
|
131
137
|
defaultSort,
|
|
132
138
|
loadingRowCount,
|
|
133
139
|
onRowClick,
|
|
134
|
-
shouldShowFilters
|
|
140
|
+
shouldShowFilters
|
|
135
141
|
]);
|
|
136
142
|
return (jsxRuntime.jsx(context.TableContext.Provider, { value: contextValue, children: children }));
|
|
137
143
|
}
|
|
@@ -141,7 +147,7 @@ const DataTable = Object.assign(DataTableRoot, {
|
|
|
141
147
|
Toolbar: toolbar.Toolbar,
|
|
142
148
|
Search: search.TableSearch,
|
|
143
149
|
Filters: filters.Filters,
|
|
144
|
-
DisplayControls: displaySettings.DisplaySettings
|
|
150
|
+
DisplayControls: displaySettings.DisplaySettings
|
|
145
151
|
});
|
|
146
152
|
|
|
147
153
|
exports.DataTable = DataTable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.cjs","sources":["../../../components/data-table/data-table.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"data-table.cjs","sources":["../../../components/data-table/data-table.tsx"],"sourcesContent":["'use client';\n\nimport {\n getCoreRowModel,\n getExpandedRowModel,\n getFilteredRowModel,\n getSortedRowModel,\n Updater,\n useReactTable,\n VisibilityState\n} from '@tanstack/react-table';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Content } from './components/content';\nimport { DisplaySettings } from './components/display-settings';\nimport { Filters } from './components/filters';\nimport { TableSearch } from './components/search';\nimport { Toolbar } from './components/toolbar';\nimport { VirtualizedContent } from './components/virtualized-content';\nimport { TableContext } from './context';\nimport {\n DataTableProps,\n defaultGroupOption,\n GroupedData,\n InternalQuery,\n TableContextType,\n TableQueryUpdateFn\n} from './data-table.types';\nimport {\n getColumnsWithFilterFn,\n getDefaultTableQuery,\n getInitialColumnVisibility,\n groupData,\n hasQueryChanged,\n queryToTableState,\n transformToDataTableQuery\n} from './utils';\n\nfunction DataTableRoot<TData, TValue>({\n data = [],\n columns,\n query,\n mode = 'client',\n isLoading = false,\n loadingRowCount = 3,\n defaultSort,\n children,\n onTableQueryChange,\n onLoadMore,\n onRowClick,\n onColumnVisibilityChange\n}: React.PropsWithChildren<DataTableProps<TData, TValue>>) {\n const defaultTableQuery = useMemo(\n () => getDefaultTableQuery(defaultSort, query),\n [defaultSort, query]\n );\n const initialColumnVisibility = getInitialColumnVisibility(columns);\n\n const [columnVisibility, setColumnVisibility] = useState<VisibilityState>(\n initialColumnVisibility\n );\n const handleColumnVisibilityChange = useCallback(\n (value: Updater<VisibilityState>) => {\n setColumnVisibility(prev => {\n const newValue = typeof value === 'function' ? value(prev) : value;\n onColumnVisibilityChange?.(newValue);\n return newValue;\n });\n },\n [onColumnVisibilityChange]\n );\n\n const [tableQuery, setTableQuery] =\n useState<InternalQuery>(defaultTableQuery);\n\n const oldQueryRef = useRef<InternalQuery | null>(null);\n\n const reactTableState = useMemo(\n () => queryToTableState(tableQuery),\n [tableQuery]\n );\n\n const onDisplaySettingsReset = useCallback(() => {\n setTableQuery(prev => ({\n ...prev,\n ...defaultTableQuery,\n sort: [defaultSort],\n group_by: [defaultGroupOption.id]\n }));\n handleColumnVisibilityChange(initialColumnVisibility);\n }, [\n defaultSort,\n defaultTableQuery,\n initialColumnVisibility,\n handleColumnVisibilityChange\n ]);\n\n const group_by = tableQuery.group_by?.[0];\n\n const columnsWithFilters = useMemo(\n () => getColumnsWithFilterFn<TData, TValue>(columns, tableQuery.filters),\n [columns, tableQuery.filters]\n );\n\n const groupedData = useMemo(\n () => groupData(data, group_by, columns),\n [data, group_by, columns]\n );\n\n useEffect(() => {\n if (\n tableQuery &&\n onTableQueryChange &&\n hasQueryChanged(oldQueryRef.current, tableQuery) &&\n mode === 'server'\n ) {\n onTableQueryChange(transformToDataTableQuery(tableQuery));\n oldQueryRef.current = tableQuery;\n }\n }, [tableQuery, onTableQueryChange]);\n\n const table = useReactTable({\n data: groupedData as unknown as TData[],\n columns: columnsWithFilters,\n getCoreRowModel: getCoreRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n getSubRows: row => (row as unknown as GroupedData<TData>)?.subRows || [],\n getSortedRowModel: mode === 'server' ? undefined : getSortedRowModel(),\n getFilteredRowModel: mode === 'server' ? undefined : getFilteredRowModel(),\n manualSorting: mode === 'server',\n manualFiltering: mode === 'server',\n onColumnVisibilityChange: handleColumnVisibilityChange,\n globalFilterFn: mode === 'server' ? undefined : 'auto',\n initialState: {\n columnVisibility: initialColumnVisibility\n },\n filterFromLeafRows: true,\n state: {\n ...reactTableState,\n columnVisibility: columnVisibility,\n expanded:\n group_by && group_by !== defaultGroupOption.id ? true : undefined\n }\n });\n\n function updateTableQuery(fn: TableQueryUpdateFn) {\n setTableQuery(prev => fn(prev));\n }\n\n const loadMoreData = useCallback(() => {\n if (mode === 'server' && onLoadMore) {\n onLoadMore();\n }\n }, [mode, onLoadMore]);\n\n const searchQuery = query?.search;\n useEffect(() => {\n if (searchQuery) {\n updateTableQuery(prev => ({\n ...prev,\n search: searchQuery\n }));\n }\n }, [searchQuery]);\n\n // Determine if filters should be visible\n // Filters should be visible if there is data OR if filters are applied (empty state)\n // Filters should NOT be visible if no data AND no filters (zero state)\n // Note: Search alone does not show the filter bar\n const shouldShowFilters = useMemo(() => {\n const hasFilters = tableQuery?.filters && tableQuery.filters.length > 0;\n\n try {\n const rowModel = table.getRowModel();\n const hasData = (rowModel?.rows?.length ?? 0) > 0;\n return hasData || hasFilters;\n } catch {\n // If table is not ready yet, check if we have initial data\n // If no filters and no data, don't show filters\n return hasFilters || data.length > 0;\n }\n }, [table, tableQuery, data.length]);\n\n const contextValue: TableContextType<TData, TValue> = useMemo(() => {\n return {\n table,\n columns,\n mode,\n isLoading,\n loadMoreData,\n tableQuery,\n updateTableQuery,\n onDisplaySettingsReset,\n defaultSort,\n loadingRowCount,\n onRowClick,\n shouldShowFilters\n };\n }, [\n table,\n columns,\n mode,\n isLoading,\n loadMoreData,\n tableQuery,\n updateTableQuery,\n onDisplaySettingsReset,\n defaultSort,\n loadingRowCount,\n onRowClick,\n shouldShowFilters\n ]);\n\n return (\n <TableContext.Provider value={contextValue}>\n {children}\n </TableContext.Provider>\n );\n}\n\nexport const DataTable = Object.assign(DataTableRoot, {\n Content: Content,\n VirtualizedContent: VirtualizedContent,\n Toolbar: Toolbar,\n Search: TableSearch,\n Filters: Filters,\n DisplayControls: DisplaySettings\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAqCA;;AAkBE;;AAKA;;AAGM;AACA;AACA;AACF;AACF;;AAOF;AAEA;AAKA;AACE;AACE;AACA;;AAEA;AACD;;AAEH;;;;;AAKC;;;;;AAeC;;AAGE;;AAGA;AACA;;AAEJ;;AAGE;AACA;;;;AAIA;AACA;;;AAGA;;AAEA;AACE;AACD;AACD;AACA;AACE;AACA;AACA;AAED;AACF;;;;AAMD;AACE;AACE;;AAEJ;AAEA;;;AAGI;AACE;AACA;AACD;;AAEL;;;;;AAMA;AACE;AAEA;AACE;AACA;;;AAEA;;;AAGA;;;AAIJ;;;;;;;;;;;;;;;AAeA;;;;;;;;;;;;;AAaC;AAED;AAKF;;AAGE;AACA;AACA;AACA;AACA;AACA;AACD;;"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Content } from
|
|
2
|
-
import { DisplaySettings } from
|
|
3
|
-
import { Filters } from
|
|
4
|
-
import { Toolbar } from
|
|
5
|
-
import { VirtualizedContent } from
|
|
6
|
-
import { DataTableProps } from
|
|
7
|
-
declare function DataTableRoot<TData, TValue>({ data, columns, query, mode, isLoading, loadingRowCount, defaultSort, children, onTableQueryChange, onLoadMore, onRowClick, onColumnVisibilityChange
|
|
1
|
+
import { Content } from './components/content';
|
|
2
|
+
import { DisplaySettings } from './components/display-settings';
|
|
3
|
+
import { Filters } from './components/filters';
|
|
4
|
+
import { Toolbar } from './components/toolbar';
|
|
5
|
+
import { VirtualizedContent } from './components/virtualized-content';
|
|
6
|
+
import { DataTableProps } from './data-table.types';
|
|
7
|
+
declare function DataTableRoot<TData, TValue>({ data, columns, query, mode, isLoading, loadingRowCount, defaultSort, children, onTableQueryChange, onLoadMore, onRowClick, onColumnVisibilityChange }: React.PropsWithChildren<DataTableProps<TData, TValue>>): import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
export declare const DataTable: typeof DataTableRoot & {
|
|
9
9
|
Content: typeof Content;
|
|
10
10
|
VirtualizedContent: typeof VirtualizedContent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../../components/data-table/data-table.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EACL,cAAc,EAMf,MAAM,oBAAoB,CAAC;AAW5B,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EACpC,IAAS,EACT,OAAO,EACP,KAAK,EACL,IAAe,EACf,SAAiB,EACjB,eAAmB,EACnB,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,wBAAwB,
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../../components/data-table/data-table.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EACL,cAAc,EAMf,MAAM,oBAAoB,CAAC;AAW5B,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EACpC,IAAS,EACT,OAAO,EACP,KAAK,EACL,IAAe,EACf,SAAiB,EACjB,eAAmB,EACnB,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,wBAAwB,EACzB,EAAE,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,2CAuKxD;AAED,eAAO,MAAM,SAAS;;;;;;;CAOpB,CAAC"}
|