mogh_ui 1.1.3 → 1.1.5
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.cjs +38 -30
- package/dist/components/data-table.cjs.map +1 -1
- package/dist/components/data-table.d.ts +8 -2
- package/dist/components/data-table.d.ts.map +1 -1
- package/dist/components/data-table.js +38 -30
- package/dist/components/data-table.js.map +1 -1
- package/package.json +1 -1
|
@@ -55,6 +55,8 @@ function DataTable({
|
|
|
55
55
|
data,
|
|
56
56
|
loading,
|
|
57
57
|
onRowClick,
|
|
58
|
+
onRowContextMenu,
|
|
59
|
+
rowProps,
|
|
58
60
|
noResults = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Text, { c: "dimmed", children: "No results" }),
|
|
59
61
|
sortDescFirst = false,
|
|
60
62
|
defaultSort = [],
|
|
@@ -171,37 +173,43 @@ function DataTable({
|
|
|
171
173
|
colSpan: table.getAllLeafColumns().length + (selectOptions ? 1 : 0),
|
|
172
174
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Group, { justify: "center", py: "lg", children: noResults })
|
|
173
175
|
}
|
|
174
|
-
) }) : rows.map((row) =>
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
) }) : rows.map((row) => {
|
|
177
|
+
const extraRowProps = rowProps?.(row.original);
|
|
178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
179
|
+
import_core.Table.Tr,
|
|
180
|
+
{
|
|
181
|
+
onContextMenu: onRowContextMenu ? (e) => onRowContextMenu(row.original, e) : void 0,
|
|
182
|
+
...extraRowProps,
|
|
183
|
+
style: {
|
|
184
|
+
cursor: onRowClick ? "pointer" : void 0,
|
|
185
|
+
contentVisibility: "auto",
|
|
186
|
+
containIntrinsicSize: "auto 2em",
|
|
187
|
+
...extraRowProps?.style
|
|
188
|
+
},
|
|
189
|
+
children: [
|
|
190
|
+
selectOptions && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Table.Td, { onClick: () => row.toggleSelected(), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
191
|
+
import_core.Checkbox,
|
|
192
|
+
{
|
|
193
|
+
"aria-label": "Select row",
|
|
194
|
+
color: selectOptions.color ?? "Neutral",
|
|
195
|
+
disabled: !row.getCanSelect(),
|
|
196
|
+
checked: row.getIsSelected()
|
|
197
|
+
}
|
|
198
|
+
) }),
|
|
199
|
+
row.getVisibleCells().map((cell) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
200
|
+
import_core.Table.Td,
|
|
201
|
+
{
|
|
202
|
+
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
203
|
+
style: { flexWrap: "nowrap", textWrap: "nowrap" },
|
|
204
|
+
children: (0, import_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext())
|
|
205
|
+
},
|
|
206
|
+
cell.id
|
|
207
|
+
))
|
|
208
|
+
]
|
|
181
209
|
},
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
{
|
|
186
|
-
"aria-label": "Select row",
|
|
187
|
-
color: selectOptions.color ?? "Neutral",
|
|
188
|
-
disabled: !row.getCanSelect(),
|
|
189
|
-
checked: row.getIsSelected()
|
|
190
|
-
}
|
|
191
|
-
) }),
|
|
192
|
-
row.getVisibleCells().map((cell) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
193
|
-
import_core.Table.Td,
|
|
194
|
-
{
|
|
195
|
-
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
196
|
-
style: { flexWrap: "nowrap", textWrap: "nowrap" },
|
|
197
|
-
children: (0, import_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext())
|
|
198
|
-
},
|
|
199
|
-
cell.id
|
|
200
|
-
))
|
|
201
|
-
]
|
|
202
|
-
},
|
|
203
|
-
row.id
|
|
204
|
-
)) })
|
|
210
|
+
row.id
|
|
211
|
+
);
|
|
212
|
+
}) })
|
|
205
213
|
]
|
|
206
214
|
}
|
|
207
215
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n Dispatch,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<TData extends RowData, TValue = unknown>\n extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => (\n <Table.Tr\n key={row.id}\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n ))\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"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","names":["i"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n ComponentPropsWithoutRef,\n Dispatch,\n MouseEvent,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<\n TData extends RowData,\n TValue = unknown,\n> extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n /** Called when a row is right clicked. The consumer decides whether to\n * `preventDefault` the native context menu. */\n onRowContextMenu?: (row: TData, e: MouseEvent<HTMLTableRowElement>) => void;\n /** Extra props (eg. drag and drop handlers) spread onto each data row's\n * `<tr>`. A returned `style` is merged over the row's base style. */\n rowProps?: (row: TData) => ComponentPropsWithoutRef<\"tr\">;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n onRowContextMenu,\n rowProps,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() &&\n !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => {\n const extraRowProps = rowProps?.(row.original);\n return (\n <Table.Tr\n key={row.id}\n onContextMenu={\n onRowContextMenu\n ? (e) => onRowContextMenu(row.original, e)\n : undefined\n }\n {...extraRowProps}\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n ...extraRowProps?.style,\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n );\n })\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"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","names":["i"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dispatch, ReactNode, SetStateAction } from "react";
|
|
1
|
+
import { ComponentPropsWithoutRef, Dispatch, MouseEvent, ReactNode, SetStateAction } from "react";
|
|
2
2
|
import { Column, ColumnDef, Row, RowData, RowSelectionState, SortingState } from "@tanstack/react-table";
|
|
3
3
|
import { BoxProps, DefaultMantineColor, TableProps } from "@mantine/core";
|
|
4
4
|
declare const features: {
|
|
@@ -25,6 +25,12 @@ export interface DataTableProps<TData extends RowData, TValue = unknown> extends
|
|
|
25
25
|
data: TData[];
|
|
26
26
|
loading?: boolean;
|
|
27
27
|
onRowClick?: (row: TData) => void;
|
|
28
|
+
/** Called when a row is right clicked. The consumer decides whether to
|
|
29
|
+
* `preventDefault` the native context menu. */
|
|
30
|
+
onRowContextMenu?: (row: TData, e: MouseEvent<HTMLTableRowElement>) => void;
|
|
31
|
+
/** Extra props (eg. drag and drop handlers) spread onto each data row's
|
|
32
|
+
* `<tr>`. A returned `style` is merged over the row's base style. */
|
|
33
|
+
rowProps?: (row: TData) => ComponentPropsWithoutRef<"tr">;
|
|
28
34
|
noResults?: ReactNode;
|
|
29
35
|
defaultSort?: SortingState;
|
|
30
36
|
sortDescFirst?: boolean;
|
|
@@ -48,7 +54,7 @@ export interface DataTableProps<TData extends RowData, TValue = unknown> extends
|
|
|
48
54
|
noBox?: boolean;
|
|
49
55
|
noBorder?: boolean;
|
|
50
56
|
}
|
|
51
|
-
export declare function DataTable<TData extends RowData, TValue>({ tableKey, columns, data, loading, onRowClick, noResults, sortDescFirst, defaultSort, manualSorting, onSortingStateChange, selectOptions, caption, tableProps, noBox, noBorder, mah, ...boxProps }: DataTableProps<TData, TValue>): import("react").JSX.Element;
|
|
57
|
+
export declare function DataTable<TData extends RowData, TValue>({ tableKey, columns, data, loading, onRowClick, onRowContextMenu, rowProps, noResults, sortDescFirst, defaultSort, manualSorting, onSortingStateChange, selectOptions, caption, tableProps, noBox, noBorder, mah, ...boxProps }: DataTableProps<TData, TValue>): import("react").JSX.Element;
|
|
52
58
|
export declare const SortableHeader: <T extends RowData, V>({ column, title, description, sortDescFirst, disabled, }: {
|
|
53
59
|
column: Column<DataTableFeatures, T, V>;
|
|
54
60
|
title: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EAIf,MAAM,OAAO,CAAC;AACf,OAAO,EACL,MAAM,EACN,SAAS,EAIT,GAAG,EACH,OAAO,EACP,iBAAiB,EAGjB,YAAY,EASb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,QAAQ,EAGR,mBAAmB,EAKnB,UAAU,EAGX,MAAM,eAAe,CAAC;AAKvB,QAAA,MAAM,QAAQ;;;;;;QAMV,YAAY;QACZ,yBAAyB;QACzB,KAAK;QACL,QAAQ;QACR,IAAI;QACJ,iBAAiB;;CAEnB,CAAC;AAEH;mEACmE;AACnE,MAAM,MAAM,iBAAiB,GAAG,OAAO,QAAQ,CAAC;AAWhD,MAAM,WAAW,cAAc,
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"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"}
|
|
@@ -59,6 +59,8 @@ function DataTable({
|
|
|
59
59
|
data,
|
|
60
60
|
loading,
|
|
61
61
|
onRowClick,
|
|
62
|
+
onRowContextMenu,
|
|
63
|
+
rowProps,
|
|
62
64
|
noResults = /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "No results" }),
|
|
63
65
|
sortDescFirst = false,
|
|
64
66
|
defaultSort = [],
|
|
@@ -175,37 +177,43 @@ function DataTable({
|
|
|
175
177
|
colSpan: table.getAllLeafColumns().length + (selectOptions ? 1 : 0),
|
|
176
178
|
children: /* @__PURE__ */ jsx(Group, { justify: "center", py: "lg", children: noResults })
|
|
177
179
|
}
|
|
178
|
-
) }) : rows.map((row) =>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
) }) : rows.map((row) => {
|
|
181
|
+
const extraRowProps = rowProps?.(row.original);
|
|
182
|
+
return /* @__PURE__ */ jsxs(
|
|
183
|
+
Table.Tr,
|
|
184
|
+
{
|
|
185
|
+
onContextMenu: onRowContextMenu ? (e) => onRowContextMenu(row.original, e) : void 0,
|
|
186
|
+
...extraRowProps,
|
|
187
|
+
style: {
|
|
188
|
+
cursor: onRowClick ? "pointer" : void 0,
|
|
189
|
+
contentVisibility: "auto",
|
|
190
|
+
containIntrinsicSize: "auto 2em",
|
|
191
|
+
...extraRowProps?.style
|
|
192
|
+
},
|
|
193
|
+
children: [
|
|
194
|
+
selectOptions && /* @__PURE__ */ jsx(Table.Td, { onClick: () => row.toggleSelected(), children: /* @__PURE__ */ jsx(
|
|
195
|
+
Checkbox,
|
|
196
|
+
{
|
|
197
|
+
"aria-label": "Select row",
|
|
198
|
+
color: selectOptions.color ?? "Neutral",
|
|
199
|
+
disabled: !row.getCanSelect(),
|
|
200
|
+
checked: row.getIsSelected()
|
|
201
|
+
}
|
|
202
|
+
) }),
|
|
203
|
+
row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(
|
|
204
|
+
Table.Td,
|
|
205
|
+
{
|
|
206
|
+
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
207
|
+
style: { flexWrap: "nowrap", textWrap: "nowrap" },
|
|
208
|
+
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
209
|
+
},
|
|
210
|
+
cell.id
|
|
211
|
+
))
|
|
212
|
+
]
|
|
185
213
|
},
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
{
|
|
190
|
-
"aria-label": "Select row",
|
|
191
|
-
color: selectOptions.color ?? "Neutral",
|
|
192
|
-
disabled: !row.getCanSelect(),
|
|
193
|
-
checked: row.getIsSelected()
|
|
194
|
-
}
|
|
195
|
-
) }),
|
|
196
|
-
row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(
|
|
197
|
-
Table.Td,
|
|
198
|
-
{
|
|
199
|
-
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
200
|
-
style: { flexWrap: "nowrap", textWrap: "nowrap" },
|
|
201
|
-
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
202
|
-
},
|
|
203
|
-
cell.id
|
|
204
|
-
))
|
|
205
|
-
]
|
|
206
|
-
},
|
|
207
|
-
row.id
|
|
208
|
-
)) })
|
|
214
|
+
row.id
|
|
215
|
+
);
|
|
216
|
+
}) })
|
|
209
217
|
]
|
|
210
218
|
}
|
|
211
219
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n Dispatch,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<TData extends RowData, TValue = unknown>\n extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => (\n <Table.Tr\n key={row.id}\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n ))\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"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","names":["i"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n ComponentPropsWithoutRef,\n Dispatch,\n MouseEvent,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<\n TData extends RowData,\n TValue = unknown,\n> extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n /** Called when a row is right clicked. The consumer decides whether to\n * `preventDefault` the native context menu. */\n onRowContextMenu?: (row: TData, e: MouseEvent<HTMLTableRowElement>) => void;\n /** Extra props (eg. drag and drop handlers) spread onto each data row's\n * `<tr>`. A returned `style` is merged over the row's base style. */\n rowProps?: (row: TData) => ComponentPropsWithoutRef<\"tr\">;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n onRowContextMenu,\n rowProps,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() &&\n !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => {\n const extraRowProps = rowProps?.(row.original);\n return (\n <Table.Tr\n key={row.id}\n onContextMenu={\n onRowContextMenu\n ? (e) => onRowContextMenu(row.original, e)\n : undefined\n }\n {...extraRowProps}\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n ...extraRowProps?.style,\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n );\n })\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"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","names":["i"]}
|