@prairielearn/ui 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # @prairielearn/ui
2
+
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - c0b1c74: Enable `declarationMap`
8
+ - Updated dependencies [c0b1c74]
9
+ - @prairielearn/browser-utils@2.5.1
10
+ - @prairielearn/preact-cjs@1.1.5
11
+
12
+ ## 1.1.0
13
+
14
+ ### Minor Changes
15
+
16
+ - 0ee5e51: Add support for both a empty state and a "no results" state
@@ -22,3 +22,4 @@ export declare function CategoricalColumnFilter<T extends readonly any[]>({ colu
22
22
  columnValuesFilter: T[number][];
23
23
  setColumnValuesFilter: (value: T[number][]) => void;
24
24
  }): JSX.Element;
25
+ //# sourceMappingURL=CategoricalColumnFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CategoricalColumnFilter.d.ts","sourceRoot":"","sources":["../../src/components/CategoricalColumnFilter.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,GAAG,EAAqB,MAAM,eAAe,CAAC;AAiB5D;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,SAAS,GAAG,EAAE,EAAE,EAChE,QAAQ,EACR,WAAW,EACX,eAAe,EACf,gBAA0C,EAC1C,kBAAkB,EAClB,qBAAqB,GACtB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,CAAC,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,KAAK,GAAG,CAAC,OAAO,CAAC;IACrF,kBAAkB,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IAChC,qBAAqB,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC;CACrD,eA8FA"}
@@ -2,3 +2,4 @@ import { type Table } from '@tanstack/react-table';
2
2
  export declare function ColumnManager<RowDataModel>({ table }: {
3
3
  table: Table<RowDataModel>;
4
4
  }): import("preact/compat").JSX.Element;
5
+ //# sourceMappingURL=ColumnManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColumnManager.d.ts","sourceRoot":"","sources":["../../src/components/ColumnManager.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,uBAAuB,CAAC;AA6FhE,wBAAgB,aAAa,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAA;CAAE,uCA2HpF"}
@@ -3,10 +3,12 @@ import type { JSX } from 'preact/jsx-runtime';
3
3
  import { type TanstackTableDownloadButtonProps } from './TanstackTableDownloadButton.js';
4
4
  interface TanstackTableProps<RowDataModel> {
5
5
  table: Table<RowDataModel>;
6
+ title: string;
6
7
  filters?: Record<string, (props: {
7
8
  header: Header<RowDataModel, unknown>;
8
9
  }) => JSX.Element>;
9
10
  rowHeight?: number;
11
+ noResultsState?: JSX.Element;
10
12
  emptyState?: JSX.Element;
11
13
  }
12
14
  /**
@@ -16,17 +18,10 @@ interface TanstackTableProps<RowDataModel> {
16
18
  * @param params.title - The title of the table
17
19
  * @param params.filters - The filters for the table
18
20
  * @param params.rowHeight - The height of the rows in the table
21
+ * @param params.noResultsState - The no results state for the table
19
22
  * @param params.emptyState - The empty state for the table
20
23
  */
21
- export declare function TanstackTable<RowDataModel>({ table, title, filters, rowHeight, emptyState, }: {
22
- table: Table<RowDataModel>;
23
- title: string;
24
- emptyState?: JSX.Element;
25
- rowHeight?: number;
26
- filters?: Record<string, (props: {
27
- header: Header<RowDataModel, unknown>;
28
- }) => JSX.Element>;
29
- }): JSX.Element;
24
+ export declare function TanstackTable<RowDataModel>({ table, title, filters, rowHeight, noResultsState, emptyState, }: TanstackTableProps<RowDataModel>): JSX.Element;
30
25
  /**
31
26
  * A generic component that wraps the TanstackTable component in a card.
32
27
  * @param params
@@ -53,3 +48,4 @@ export declare function TanstackTableCard<RowDataModel>({ table, title, headerBu
53
48
  downloadButtonOptions?: Omit<TanstackTableDownloadButtonProps<RowDataModel>, 'table'> | null;
54
49
  }): JSX.Element;
55
50
  export {};
51
+ //# sourceMappingURL=TanstackTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TanstackTable.d.ts","sourceRoot":"","sources":["../../src/components/TanstackTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAsB,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAG9C,OAAO,EAEL,KAAK,gCAAgC,EACtC,MAAM,kCAAkC,CAAC;AA0F1C,UAAU,kBAAkB,CAAC,YAAY;IACvC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAC7B,UAAU,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CAC1B;AAID;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,EAC1C,KAAK,EACL,KAAK,EACL,OAA4B,EAC5B,SAAc,EACd,cAAsC,EACtC,UAA8B,GAC/B,EAAE,kBAAkB,CAAC,YAAY,CAAC,eAkUlC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,EAC9C,KAAK,EACL,KAAK,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,qBAA4B,GAC7B,EAAE;IACD,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC;IAC3B,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,qBAAqB,CAAC,EAAE,IAAI,CAAC,gCAAgC,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9F,eAgGA"}
@@ -48,7 +48,8 @@ function ResizeHandle({ header, setColumnSizing, }) {
48
48
  transition: 'background-color 0.2s',
49
49
  }, onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler(), onKeyDown: handleKeyDown }) }));
50
50
  }
51
- const DefaultEmptyState = (_jsxs(_Fragment, { children: [_jsx("i", { class: "bi bi-search display-4 mb-2", "aria-hidden": "true" }), _jsx("p", { class: "mb-0", children: "No results found matching your search criteria." })] }));
51
+ const DefaultNoResultsState = (_jsxs(_Fragment, { children: [_jsx("i", { class: "bi bi-search display-4 mb-2", "aria-hidden": "true" }), _jsx("p", { class: "mb-0", children: "No results found matching your search criteria." })] }));
52
+ const DefaultEmptyState = (_jsxs(_Fragment, { children: [_jsx("i", { class: "bi bi-eye-slash display-4 mb-2", "aria-hidden": "true" }), _jsx("p", { class: "mb-0", children: "No results found." })] }));
52
53
  const DEFAULT_FILTER_MAP = {};
53
54
  /**
54
55
  * A generic component that renders a full-width, resizeable Tanstack Table.
@@ -57,9 +58,10 @@ const DEFAULT_FILTER_MAP = {};
57
58
  * @param params.title - The title of the table
58
59
  * @param params.filters - The filters for the table
59
60
  * @param params.rowHeight - The height of the rows in the table
61
+ * @param params.noResultsState - The no results state for the table
60
62
  * @param params.emptyState - The empty state for the table
61
63
  */
62
- export function TanstackTable({ table, title, filters = DEFAULT_FILTER_MAP, rowHeight = 42, emptyState = DefaultEmptyState, }) {
64
+ export function TanstackTable({ table, title, filters = DEFAULT_FILTER_MAP, rowHeight = 42, noResultsState = DefaultNoResultsState, emptyState = DefaultEmptyState, }) {
63
65
  const parentRef = useRef(null);
64
66
  const tableRef = useRef(null);
65
67
  const rows = [...table.getTopRows(), ...table.getCenterRows()];
@@ -149,6 +151,8 @@ export function TanstackTable({ table, title, filters = DEFAULT_FILTER_MAP, rowH
149
151
  return 'none';
150
152
  }
151
153
  };
154
+ const displayedCount = table.getRowModel().rows.length;
155
+ const totalCount = table.getCoreRowModel().rows.length;
152
156
  return (_jsxs("div", { style: { position: 'relative' }, class: "d-flex flex-column h-100", children: [_jsx("div", { ref: parentRef, style: {
153
157
  position: 'absolute',
154
158
  top: 0,
@@ -224,14 +228,14 @@ export function TanstackTable({ table, title, filters = DEFAULT_FILTER_MAP, rowH
224
228
  right: 0,
225
229
  bottom: 0,
226
230
  background: 'var(--bs-body-bg)',
227
- }, role: "status", "aria-live": "polite", children: [_jsx("i", { class: "bi bi-eye-slash display-4 mb-2", "aria-hidden": "true" }), _jsx("p", { class: "mb-0", children: "No columns selected. Use the View menu to show columns." })] }) })), table.getRowModel().rows.length === 0 && (_jsx("div", { class: "d-flex flex-column justify-content-center align-items-center text-muted py-4", style: {
231
+ }, role: "status", "aria-live": "polite", children: [_jsx("i", { class: "bi bi-eye-slash display-4 mb-2", "aria-hidden": "true" }), _jsx("p", { class: "mb-0", children: "No columns selected. Use the View menu to show columns." })] }) })), displayedCount === 0 && (_jsx("div", { class: "d-flex flex-column justify-content-center align-items-center text-muted py-4", style: {
228
232
  position: 'absolute',
229
233
  top: 0,
230
234
  left: 0,
231
235
  right: 0,
232
236
  bottom: 0,
233
237
  background: 'var(--bs-body-bg)',
234
- }, role: "status", "aria-live": "polite", children: emptyState }))] }));
238
+ }, role: "status", "aria-live": "polite", children: totalCount > 0 ? noResultsState : emptyState }))] }));
235
239
  }
236
240
  /**
237
241
  * A generic component that wraps the TanstackTable component in a card.
@@ -274,10 +278,12 @@ export function TanstackTableCard({ table, title, headerButtons, globalFilter, t
274
278
  document.addEventListener('keydown', onKeyDown);
275
279
  return () => document.removeEventListener('keydown', onKeyDown);
276
280
  }, []);
281
+ const displayedCount = table.getRowModel().rows.length;
282
+ const totalCount = table.getCoreRowModel().rows.length;
277
283
  return (_jsxs("div", { class: "card d-flex flex-column h-100", children: [_jsx("div", { class: "card-header bg-primary text-white", children: _jsxs("div", { class: "d-flex align-items-center justify-content-between gap-2", children: [_jsx("div", { children: title }), _jsxs("div", { class: "d-flex gap-2", children: [headerButtons, downloadButtonOptions && (_jsx(TanstackTableDownloadButton, { table: table, ...downloadButtonOptions }))] })] }) }), _jsxs("div", { class: "card-body d-flex flex-column", children: [_jsxs("div", { class: "d-flex flex-row flex-wrap align-items-center mb-3 gap-2", children: [_jsxs("div", { class: "flex-grow-1 flex-lg-grow-0 col-xl-6 col-lg-7 d-flex flex-row gap-2", children: [_jsxs("div", { class: "input-group", children: [_jsx("input", { ref: searchInputRef, type: "text", class: "form-control", "aria-label": globalFilter.placeholder, placeholder: globalFilter.placeholder, value: globalFilter.value, onInput: (e) => {
278
284
  if (!(e.target instanceof HTMLInputElement))
279
285
  return;
280
286
  globalFilter.setValue(e.target.value);
281
- } }), _jsx("button", { type: "button", class: "btn btn-outline-secondary", "aria-label": "Clear search", title: "Clear search", "data-bs-toggle": "tooltip", onClick: () => globalFilter.setValue(''), children: _jsx("i", { class: "bi bi-x-circle", "aria-hidden": "true" }) })] }), isMediumOrLarger && _jsx(ColumnManager, { table: table })] }), !isMediumOrLarger && _jsx(ColumnManager, { table: table }), _jsx("div", { class: "flex-lg-grow-1 d-flex flex-row justify-content-end", children: _jsxs("div", { class: "text-muted text-nowrap", children: ["Showing ", table.getRowModel().rows.length, " of ", table.getCoreRowModel().rows.length, ' ', title.toLowerCase()] }) })] }), _jsx("div", { class: "flex-grow-1", children: _jsx(TanstackTable, { table: table, title: title, ...tableOptions }) })] })] }));
287
+ } }), _jsx("button", { type: "button", class: "btn btn-outline-secondary", "aria-label": "Clear search", title: "Clear search", "data-bs-toggle": "tooltip", onClick: () => globalFilter.setValue(''), children: _jsx("i", { class: "bi bi-x-circle", "aria-hidden": "true" }) })] }), isMediumOrLarger && _jsx(ColumnManager, { table: table })] }), !isMediumOrLarger && _jsx(ColumnManager, { table: table }), _jsx("div", { class: "flex-lg-grow-1 d-flex flex-row justify-content-end", children: _jsxs("div", { class: "text-muted text-nowrap", children: ["Showing ", displayedCount, " of ", totalCount, " ", title.toLowerCase()] }) })] }), _jsx("div", { class: "flex-grow-1", children: _jsx(TanstackTable, { table: table, title: title, ...tableOptions }) })] })] }));
282
288
  }
283
289
  //# sourceMappingURL=TanstackTable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TanstackTable.js","sourceRoot":"","sources":["../../src/components/TanstackTable.tsx"],"names":[],"mappings":"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","sourcesContent":["import { flexRender } from '@tanstack/react-table';\nimport { notUndefined, useVirtualizer } from '@tanstack/react-virtual';\nimport type { Header, Row, SortDirection, Table } from '@tanstack/table-core';\nimport clsx from 'clsx';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport type { JSX } from 'preact/jsx-runtime';\n\nimport { ColumnManager } from './ColumnManager.js';\nimport {\n TanstackTableDownloadButton,\n type TanstackTableDownloadButtonProps,\n} from './TanstackTableDownloadButton.js';\n\nfunction SortIcon({ sortMethod }: { sortMethod: false | SortDirection }) {\n if (sortMethod === 'asc') {\n return <i class=\"bi bi-sort-up-alt\" aria-hidden=\"true\" />;\n } else if (sortMethod === 'desc') {\n return <i class=\"bi bi-sort-down\" aria-hidden=\"true\" />;\n } else {\n return <i class=\"bi bi-arrow-down-up opacity-75 text-muted\" aria-hidden=\"true\" />;\n }\n}\n\nfunction ResizeHandle<RowDataModel>({\n header,\n setColumnSizing,\n}: {\n header: Header<RowDataModel, unknown>;\n setColumnSizing: Table<RowDataModel>['setColumnSizing'];\n}) {\n const minSize = header.column.columnDef.minSize ?? 0;\n const maxSize = header.column.columnDef.maxSize ?? 0;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n e.preventDefault();\n const currentSize = header.getSize();\n const increment = e.shiftKey ? 20 : 5; // Larger increment with Shift key\n const newSize =\n e.key === 'ArrowLeft'\n ? Math.max(minSize, currentSize - increment)\n : Math.min(maxSize, currentSize + increment);\n\n setColumnSizing((prevSizing) => ({\n ...prevSizing,\n [header.column.id]: newSize,\n }));\n } else if (e.key === 'Home') {\n e.preventDefault();\n header.column.resetSize();\n }\n };\n\n const columnName =\n typeof header.column.columnDef.header === 'string'\n ? header.column.columnDef.header\n : header.column.id;\n\n return (\n <div class=\"py-1 h-100\" style={{ position: 'absolute', right: 0, top: 0, width: '4px' }}>\n {/* separator role is focusable, so these jsx-a11y-x rules are false positives.\n https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/separator_role#focusable_separator\n */}\n {/* eslint-disable-next-line jsx-a11y-x/no-noninteractive-element-interactions */}\n <div\n role=\"separator\"\n aria-label={`Resize '${columnName}' column`}\n aria-valuetext={`${header.getSize()}px`}\n aria-orientation=\"vertical\"\n aria-valuemin={minSize}\n aria-valuemax={maxSize}\n aria-valuenow={header.getSize()}\n // eslint-disable-next-line jsx-a11y-x/no-noninteractive-tabindex\n tabIndex={0}\n class=\"h-100\"\n style={{\n background: header.column.getIsResizing() ? 'var(--bs-primary)' : 'var(--bs-gray-400)',\n cursor: 'col-resize',\n transition: 'background-color 0.2s',\n }}\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n onKeyDown={handleKeyDown}\n />\n </div>\n );\n}\n\nconst DefaultEmptyState = (\n <>\n <i class=\"bi bi-search display-4 mb-2\" aria-hidden=\"true\" />\n <p class=\"mb-0\">No results found matching your search criteria.</p>\n </>\n);\n\ninterface TanstackTableProps<RowDataModel> {\n table: Table<RowDataModel>;\n filters?: Record<string, (props: { header: Header<RowDataModel, unknown> }) => JSX.Element>;\n rowHeight?: number;\n emptyState?: JSX.Element;\n}\n\nconst DEFAULT_FILTER_MAP = {};\n\n/**\n * A generic component that renders a full-width, resizeable Tanstack Table.\n * @param params\n * @param params.table - The table model\n * @param params.title - The title of the table\n * @param params.filters - The filters for the table\n * @param params.rowHeight - The height of the rows in the table\n * @param params.emptyState - The empty state for the table\n */\nexport function TanstackTable<RowDataModel>({\n table,\n title,\n filters = DEFAULT_FILTER_MAP,\n rowHeight = 42,\n emptyState = DefaultEmptyState,\n}: {\n table: Table<RowDataModel>;\n title: string;\n emptyState?: JSX.Element;\n rowHeight?: number;\n filters?: Record<string, (props: { header: Header<RowDataModel, unknown> }) => JSX.Element>;\n}) {\n const parentRef = useRef<HTMLDivElement>(null);\n const tableRef = useRef<HTMLDivElement>(null);\n const rows = [...table.getTopRows(), ...table.getCenterRows()];\n const rowVirtualizer = useVirtualizer({\n count: rows.length,\n getScrollElement: () => parentRef.current,\n estimateSize: () => rowHeight,\n overscan: 10,\n });\n\n // Track focused cell for grid navigation\n const [focusedCell, setFocusedCell] = useState<{ row: number; col: number }>({ row: 0, col: 0 });\n\n const getVisibleCells = (row: Row<RowDataModel>) => [\n ...row.getLeftVisibleCells(),\n ...row.getCenterVisibleCells(),\n ];\n\n const handleGridKeyDown = (e: KeyboardEvent, rowIdx: number, colIdx: number) => {\n const rowLength = getVisibleCells(rows[rowIdx]).length;\n const adjacentCells: Record<KeyboardEvent['key'], { row: number; col: number }> = {\n ArrowDown: {\n row: Math.min(rows.length - 1, rowIdx + 1),\n col: colIdx,\n },\n ArrowUp: {\n row: Math.max(0, rowIdx - 1),\n col: colIdx,\n },\n ArrowRight: {\n row: rowIdx,\n col: Math.min(rowLength - 1, colIdx + 1),\n },\n ArrowLeft: {\n row: rowIdx,\n col: Math.max(0, colIdx - 1),\n },\n };\n\n const next = adjacentCells[e.key];\n\n if (!next) {\n return;\n }\n\n setFocusedCell({ row: next.row, col: next.col });\n // If we are on the leftmost column, we should allow left scrolling.\n if (colIdx === 0 && e.key === 'ArrowLeft') {\n return;\n }\n\n // If we are on the top row, we should allow up scrolling.\n if (rowIdx === 0 && e.key === 'ArrowUp') {\n return;\n }\n\n // If we are on the rightmost column, we should allow right scrolling.\n if (colIdx === rowLength - 1 && e.key === 'ArrowRight') {\n return;\n }\n\n e.preventDefault();\n };\n\n useEffect(() => {\n const selector = `[data-grid-cell-row=\"${focusedCell.row}\"][data-grid-cell-col=\"${focusedCell.col}\"]`;\n const cell = tableRef.current?.querySelector(selector) as HTMLElement | null;\n if (!cell) {\n return;\n }\n cell.focus();\n }, [focusedCell]);\n\n const virtualRows = rowVirtualizer.getVirtualItems();\n const [before, after] =\n virtualRows.length > 0\n ? [\n notUndefined(virtualRows[0]).start - rowVirtualizer.options.scrollMargin,\n rowVirtualizer.getTotalSize() - notUndefined(virtualRows.at(-1)).end,\n ]\n : [0, 0];\n const headerGroups = table.getHeaderGroups();\n const isTableResizing = headerGroups.some((headerGroup) =>\n headerGroup.headers.some((header) => header.column.getIsResizing()),\n );\n const lastColumnId = table.getAllLeafColumns()[table.getAllLeafColumns().length - 1].id;\n\n const tableRect = tableRef.current?.getBoundingClientRect();\n\n // We toggle this here instead of in the parent since this component logically manages all UI for the table.\n // eslint-disable-next-line react-you-might-not-need-an-effect/no-manage-parent\n useEffect(() => {\n document.body.classList.toggle('no-user-select', isTableResizing);\n }, [isTableResizing]);\n\n // Helper function to get aria-sort value\n const getAriaSort = (sortDirection: false | SortDirection) => {\n switch (sortDirection) {\n case 'asc':\n return 'ascending';\n case 'desc':\n return 'descending';\n default:\n return 'none';\n }\n };\n\n return (\n <div style={{ position: 'relative' }} class=\"d-flex flex-column h-100\">\n <div\n ref={parentRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n overflow: 'auto',\n overflowAnchor: 'none',\n }}\n >\n <div\n ref={tableRef}\n style={{\n position: 'relative',\n width: `max(${table.getTotalSize()}px, 100%)`,\n }}\n >\n <table\n class=\"table table-hover mb-0 border border-top-0\"\n style={{ tableLayout: 'fixed' }}\n aria-label={title}\n role=\"grid\"\n >\n <thead>\n {headerGroups.map((headerGroup) => (\n <tr key={headerGroup.id}>\n {headerGroup.headers.map((header, index) => {\n const isPinned = header.column.getIsPinned();\n const sortDirection = header.column.getIsSorted();\n const canSort = header.column.getCanSort();\n const canFilter = header.column.getCanFilter();\n const columnName =\n typeof header.column.columnDef.header === 'string'\n ? header.column.columnDef.header\n : header.column.id;\n\n const style: JSX.CSSProperties = {\n width:\n header.column.id === lastColumnId\n ? `max(100%, ${header.getSize()}px)`\n : header.getSize(),\n position: 'sticky',\n top: 0,\n zIndex: isPinned === 'left' ? 2 : 1,\n left: isPinned === 'left' ? header.getStart() : undefined,\n boxShadow:\n 'inset 0 calc(-1 * var(--bs-border-width)) 0 0 rgba(0, 0, 0, 1), inset 0 var(--bs-border-width) 0 0 var(--bs-border-color)',\n };\n\n return (\n <th\n key={header.id}\n class={clsx(isPinned === 'left' && 'bg-light')}\n style={style}\n aria-sort={canSort ? getAriaSort(sortDirection) : undefined}\n role=\"columnheader\"\n >\n <div class=\"d-flex align-items-center justify-content-between gap-2\">\n <button\n class=\"text-nowrap flex-grow-1 text-start\"\n style={{\n cursor: canSort ? 'pointer' : 'default',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n background: 'transparent',\n border: 'none',\n }}\n type=\"button\"\n aria-label={\n canSort\n ? `'${columnName}' column, current sort is ${getAriaSort(sortDirection)}`\n : undefined\n }\n onClick={canSort ? header.column.getToggleSortingHandler() : undefined}\n onKeyDown={\n canSort\n ? (e) => {\n const handleSort = header.column.getToggleSortingHandler();\n if (e.key === 'Enter' && handleSort) {\n e.preventDefault();\n handleSort(e);\n }\n }\n : undefined\n }\n >\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n {canSort && (\n <span class=\"ms-2\" aria-hidden=\"true\">\n <SortIcon sortMethod={sortDirection || false} />\n </span>\n )}\n {canSort && (\n <span class=\"visually-hidden\">\n , {getAriaSort(sortDirection)}, click to sort\n </span>\n )}\n </button>\n\n {canFilter && filters[header.column.id]?.({ header })}\n </div>\n {tableRect?.width &&\n tableRect.width > table.getTotalSize() &&\n index === headerGroup.headers.length - 1 ? null : (\n <ResizeHandle header={header} setColumnSizing={table.setColumnSizing} />\n )}\n </th>\n );\n })}\n </tr>\n ))}\n </thead>\n <tbody>\n {before > 0 && (\n <tr tabIndex={-1}>\n <td colSpan={headerGroups[0].headers.length} style={{ height: before }} />\n </tr>\n )}\n {virtualRows.map((virtualRow) => {\n const row = rows[virtualRow.index];\n const visibleCells = getVisibleCells(row);\n const rowIdx = virtualRow.index;\n\n return (\n <tr key={row.id} style={{ height: rowHeight }}>\n {visibleCells.map((cell, colIdx) => (\n <td\n key={cell.id}\n // You can tab to the most-recently focused cell.\n tabIndex={focusedCell.row === rowIdx && focusedCell.col === colIdx ? 0 : -1}\n // We store this so you can navigate around the grid.\n data-grid-cell-row={rowIdx}\n data-grid-cell-col={colIdx}\n style={{\n width:\n cell.column.id === lastColumnId\n ? `max(100%, ${cell.column.getSize()}px)`\n : cell.column.getSize(),\n position: cell.column.getIsPinned() === 'left' ? 'sticky' : undefined,\n left:\n cell.column.getIsPinned() === 'left'\n ? cell.column.getStart()\n : undefined,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n onFocus={() => setFocusedCell({ row: rowIdx, col: colIdx })}\n onKeyDown={(e) => handleGridKeyDown(e, rowIdx, colIdx)}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </td>\n ))}\n </tr>\n );\n })}\n {after > 0 && (\n <tr tabIndex={-1}>\n <td colSpan={headerGroups[0].headers.length} style={{ height: after }} />\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n\n {table.getVisibleLeafColumns().length === 0 && (\n <div>\n <div\n class=\"d-flex flex-column justify-content-center align-items-center text-muted py-4\"\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: 'var(--bs-body-bg)',\n }}\n role=\"status\"\n aria-live=\"polite\"\n >\n <i class=\"bi bi-eye-slash display-4 mb-2\" aria-hidden=\"true\" />\n <p class=\"mb-0\">No columns selected. Use the View menu to show columns.</p>\n </div>\n </div>\n )}\n {table.getRowModel().rows.length === 0 && (\n <div\n class=\"d-flex flex-column justify-content-center align-items-center text-muted py-4\"\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: 'var(--bs-body-bg)',\n }}\n role=\"status\"\n aria-live=\"polite\"\n >\n {emptyState}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * A generic component that wraps the TanstackTable component in a card.\n * @param params\n * @param params.table - The table model\n * @param params.title - The title of the card\n * @param params.headerButtons - The buttons to display in the header\n * @param params.globalFilter - State management for the global filter\n * @param params.globalFilter.value\n * @param params.globalFilter.setValue\n * @param params.globalFilter.placeholder\n * @param params.tableOptions - Specific options for the table. See {@link TanstackTableProps} for more details.\n * @param params.downloadButtonOptions - Specific options for the download button. See {@link TanstackTableDownloadButtonProps} for more details.\n */\nexport function TanstackTableCard<RowDataModel>({\n table,\n title,\n headerButtons,\n globalFilter,\n tableOptions,\n downloadButtonOptions = null,\n}: {\n table: Table<RowDataModel>;\n title: string;\n headerButtons: JSX.Element;\n globalFilter: {\n value: string;\n setValue: (value: string) => void;\n placeholder: string;\n };\n tableOptions: Partial<Omit<TanstackTableProps<RowDataModel>, 'table'>>;\n downloadButtonOptions?: Omit<TanstackTableDownloadButtonProps<RowDataModel>, 'table'> | null;\n}) {\n const searchInputRef = useRef<HTMLInputElement>(null);\n\n // Track screen size for aria-hidden\n const mediaQuery = typeof window !== 'undefined' ? window.matchMedia('(min-width: 768px)') : null;\n const [isMediumOrLarger, setIsMediumOrLarger] = useState(false);\n\n useEffect(() => {\n // TODO: This is a workaround to avoid a hydration mismatch.\n // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect\n setIsMediumOrLarger(mediaQuery?.matches ?? true);\n }, [mediaQuery]);\n\n useEffect(() => {\n const handler = (e: MediaQueryListEvent) => setIsMediumOrLarger(e.matches);\n mediaQuery?.addEventListener('change', handler);\n return () => mediaQuery?.removeEventListener('change', handler);\n }, [mediaQuery]);\n\n // Focus the search input when Ctrl+F is pressed\n useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'f') {\n if (searchInputRef.current && searchInputRef.current !== document.activeElement) {\n searchInputRef.current.focus();\n event.preventDefault();\n }\n }\n }\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, []);\n\n return (\n <div class=\"card d-flex flex-column h-100\">\n <div class=\"card-header bg-primary text-white\">\n <div class=\"d-flex align-items-center justify-content-between gap-2\">\n <div>{title}</div>\n <div class=\"d-flex gap-2\">\n {headerButtons}\n\n {downloadButtonOptions && (\n <TanstackTableDownloadButton table={table} {...downloadButtonOptions} />\n )}\n </div>\n </div>\n </div>\n <div class=\"card-body d-flex flex-column\">\n <div class=\"d-flex flex-row flex-wrap align-items-center mb-3 gap-2\">\n <div class=\"flex-grow-1 flex-lg-grow-0 col-xl-6 col-lg-7 d-flex flex-row gap-2\">\n <div class=\"input-group\">\n <input\n ref={searchInputRef}\n type=\"text\"\n class=\"form-control\"\n aria-label={globalFilter.placeholder}\n placeholder={globalFilter.placeholder}\n value={globalFilter.value}\n onInput={(e) => {\n if (!(e.target instanceof HTMLInputElement)) return;\n globalFilter.setValue(e.target.value);\n }}\n />\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n aria-label=\"Clear search\"\n title=\"Clear search\"\n data-bs-toggle=\"tooltip\"\n onClick={() => globalFilter.setValue('')}\n >\n <i class=\"bi bi-x-circle\" aria-hidden=\"true\" />\n </button>\n </div>\n {/* We do this instead of CSS properties for the accessibility checker.\n We can't have two elements with the same id of 'column-manager-button'. */}\n {isMediumOrLarger && <ColumnManager table={table} />}\n </div>\n {/* We do this instead of CSS properties for the accessibility checker.\n We can't have two elements with the same id of 'column-manager-button'. */}\n {!isMediumOrLarger && <ColumnManager table={table} />}\n <div class=\"flex-lg-grow-1 d-flex flex-row justify-content-end\">\n <div class=\"text-muted text-nowrap\">\n Showing {table.getRowModel().rows.length} of {table.getCoreRowModel().rows.length}{' '}\n {title.toLowerCase()}\n </div>\n </div>\n </div>\n <div class=\"flex-grow-1\">\n <TanstackTable table={table} title={title} {...tableOptions} />\n </div>\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"TanstackTable.js","sourceRoot":"","sources":["../../src/components/TanstackTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEvE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,2BAA2B,GAE5B,MAAM,kCAAkC,CAAC;AAE1C,SAAS,QAAQ,CAAC,EAAE,UAAU,EAAyC;IACrE,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,OAAO,YAAG,KAAK,EAAC,mBAAmB,iBAAa,MAAM,GAAG,CAAC;IAC5D,CAAC;SAAM,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACjC,OAAO,YAAG,KAAK,EAAC,iBAAiB,iBAAa,MAAM,GAAG,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,OAAO,YAAG,KAAK,EAAC,2CAA2C,iBAAa,MAAM,GAAG,CAAC;IACpF,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAe,EAClC,MAAM,EACN,eAAe,GAIhB;IACC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,CAAC,CAAgB,EAAE,EAAE;QACzC,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC;YACpD,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YACrC,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kCAAkC;YACzE,MAAM,OAAO,GACX,CAAC,CAAC,GAAG,KAAK,WAAW;gBACnB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;gBAC5C,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC,CAAC;YAEjD,eAAe,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBAC/B,GAAG,UAAU;gBACb,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO;aAC5B,CAAC,CAAC,CAAC;QACN,CAAC;aAAM,IAAI,CAAC,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;YAC5B,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GACd,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,QAAQ;QAChD,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM;QAChC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAEvB,OAAO,CACL,cAAK,KAAK,EAAC,YAAY,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,YAKrF,cACE,IAAI,EAAC,WAAW,gBACJ,WAAW,UAAU,UAAU,oBAC3B,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,sBACtB,UAAU,mBACZ,OAAO,mBACP,OAAO,mBACP,MAAM,CAAC,OAAO,EAAE;YAC/B,iEAAiE;YACjE,QAAQ,EAAE,CAAC,EACX,KAAK,EAAC,OAAO,EACb,KAAK,EAAE;gBACL,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,oBAAoB;gBACtF,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,uBAAuB;aACpC,EACD,WAAW,EAAE,MAAM,CAAC,gBAAgB,EAAE,EACtC,YAAY,EAAE,MAAM,CAAC,gBAAgB,EAAE,EACvC,SAAS,EAAE,aAAa,GACxB,GACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,qBAAqB,GAAG,CAC5B,8BACE,YAAG,KAAK,EAAC,6BAA6B,iBAAa,MAAM,GAAG,EAC5D,YAAG,KAAK,EAAC,MAAM,gEAAoD,IAClE,CACJ,CAAC;AAEF,MAAM,iBAAiB,GAAG,CACxB,8BACE,YAAG,KAAK,EAAC,gCAAgC,iBAAa,MAAM,GAAG,EAC/D,YAAG,KAAK,EAAC,MAAM,kCAAsB,IACpC,CACJ,CAAC;AAWF,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAe,EAC1C,KAAK,EACL,KAAK,EACL,OAAO,GAAG,kBAAkB,EAC5B,SAAS,GAAG,EAAE,EACd,cAAc,GAAG,qBAAqB,EACtC,UAAU,GAAG,iBAAiB,GACG;IACjC,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,EAAE,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;IAC/D,MAAM,cAAc,GAAG,cAAc,CAAC;QACpC,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO;QACzC,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS;QAC7B,QAAQ,EAAE,EAAE;KACb,CAAC,CAAC;IAEH,yCAAyC;IACzC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAA+B,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAEjG,MAAM,eAAe,GAAG,CAAC,GAAsB,EAAE,EAAE,CAAC;QAClD,GAAG,GAAG,CAAC,mBAAmB,EAAE;QAC5B,GAAG,GAAG,CAAC,qBAAqB,EAAE;KAC/B,CAAC;IAEF,MAAM,iBAAiB,GAAG,CAAC,CAAgB,EAAE,MAAc,EAAE,MAAc,EAAE,EAAE;QAC7E,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QACvD,MAAM,aAAa,GAA+D;YAChF,SAAS,EAAE;gBACT,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;gBAC1C,GAAG,EAAE,MAAM;aACZ;YACD,OAAO,EAAE;gBACP,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;gBAC5B,GAAG,EAAE,MAAM;aACZ;YACD,UAAU,EAAE;gBACV,GAAG,EAAE,MAAM;gBACX,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;aACzC;YACD,SAAS,EAAE;gBACT,GAAG,EAAE,MAAM;gBACX,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;aAC7B;SACF,CAAC;QAEF,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,cAAc,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACjD,oEAAoE;QACpE,IAAI,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,0DAA0D;QAC1D,IAAI,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YACxC,OAAO;QACT,CAAC;QAED,sEAAsE;QACtE,IAAI,MAAM,KAAK,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC;YACvD,OAAO;QACT,CAAC;QAED,CAAC,CAAC,cAAc,EAAE,CAAC;IACrB,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,wBAAwB,WAAW,CAAC,GAAG,0BAA0B,WAAW,CAAC,GAAG,IAAI,CAAC;QACtG,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAuB,CAAC;QAC7E,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,WAAW,GAAG,cAAc,CAAC,eAAe,EAAE,CAAC;IACrD,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACnB,WAAW,CAAC,MAAM,GAAG,CAAC;QACpB,CAAC,CAAC;YACE,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,YAAY;YACxE,cAAc,CAAC,YAAY,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;SACrE;QACH,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACb,MAAM,YAAY,GAAG,KAAK,CAAC,eAAe,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CACxD,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CACpE,CAAC;IACF,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAExF,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC;IAE5D,4GAA4G;IAC5G,+EAA+E;IAC/E,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;IACpE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,yCAAyC;IACzC,MAAM,WAAW,GAAG,CAAC,aAAoC,EAAE,EAAE;QAC3D,QAAQ,aAAa,EAAE,CAAC;YACtB,KAAK,KAAK;gBACR,OAAO,WAAW,CAAC;YACrB,KAAK,MAAM;gBACT,OAAO,YAAY,CAAC;YACtB;gBACE,OAAO,MAAM,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;IACvD,MAAM,UAAU,GAAG,KAAK,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;IAEvD,OAAO,CACL,eAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,EAAC,0BAA0B,aACpE,cACE,GAAG,EAAE,SAAS,EACd,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,GAAG,EAAE,CAAC;oBACN,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE,CAAC;oBACR,MAAM,EAAE,CAAC;oBACT,QAAQ,EAAE,MAAM;oBAChB,cAAc,EAAE,MAAM;iBACvB,YAED,cACE,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE;wBACL,QAAQ,EAAE,UAAU;wBACpB,KAAK,EAAE,OAAO,KAAK,CAAC,YAAY,EAAE,WAAW;qBAC9C,YAED,iBACE,KAAK,EAAC,4CAA4C,EAClD,KAAK,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,gBACnB,KAAK,EACjB,IAAI,EAAC,MAAM,aAEX,0BACG,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CACjC,uBACG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;wCACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;wCAC7C,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;wCAClD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;wCAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;wCAC/C,MAAM,UAAU,GACd,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,QAAQ;4CAChD,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM;4CAChC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;wCAEvB,MAAM,KAAK,GAAsB;4CAC/B,KAAK,EACH,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,YAAY;gDAC/B,CAAC,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,KAAK;gDACpC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE;4CACtB,QAAQ,EAAE,QAAQ;4CAClB,GAAG,EAAE,CAAC;4CACN,MAAM,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;4CACnC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;4CACzD,SAAS,EACP,2HAA2H;yCAC9H,CAAC;wCAEF,OAAO,CACL,cAEE,KAAK,EAAE,IAAI,CAAC,QAAQ,KAAK,MAAM,IAAI,UAAU,CAAC,EAC9C,KAAK,EAAE,KAAK,eACD,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,EAC3D,IAAI,EAAC,cAAc,aAEnB,eAAK,KAAK,EAAC,yDAAyD,aAClE,kBACE,KAAK,EAAC,oCAAoC,EAC1C,KAAK,EAAE;gEACL,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;gEACvC,QAAQ,EAAE,QAAQ;gEAClB,YAAY,EAAE,UAAU;gEACxB,UAAU,EAAE,aAAa;gEACzB,MAAM,EAAE,MAAM;6DACf,EACD,IAAI,EAAC,QAAQ,gBAEX,OAAO;gEACL,CAAC,CAAC,IAAI,UAAU,6BAA6B,WAAW,CAAC,aAAa,CAAC,EAAE;gEACzE,CAAC,CAAC,SAAS,EAEf,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC,SAAS,EACtE,SAAS,EACP,OAAO;gEACL,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE;oEACJ,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,CAAC;oEAC3D,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,UAAU,EAAE,CAAC;wEACpC,CAAC,CAAC,cAAc,EAAE,CAAC;wEACnB,UAAU,CAAC,CAAC,CAAC,CAAC;oEAChB,CAAC;gEACH,CAAC;gEACH,CAAC,CAAC,SAAS,aAGd,MAAM,CAAC,aAAa;oEACnB,CAAC,CAAC,IAAI;oEACN,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,EAClE,OAAO,IAAI,CACV,eAAM,KAAK,EAAC,MAAM,iBAAa,MAAM,YACnC,KAAC,QAAQ,IAAC,UAAU,EAAE,aAAa,IAAI,KAAK,GAAI,GAC3C,CACR,EACA,OAAO,IAAI,CACV,gBAAM,KAAK,EAAC,iBAAiB,mBACxB,WAAW,CAAC,aAAa,CAAC,uBACxB,CACR,IACM,EAER,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,IACjD,EACL,SAAS,EAAE,KAAK;oDACjB,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE;oDACtC,KAAK,KAAK,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAChD,KAAC,YAAY,IAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,GAAI,CACzE,KAxDI,MAAM,CAAC,EAAE,CAyDX,CACN,CAAC;oCACJ,CAAC,CAAC,IArFK,WAAW,CAAC,EAAE,CAsFlB,CACN,CAAC,GACI,EACR,4BACG,MAAM,GAAG,CAAC,IAAI,CACb,aAAI,QAAQ,EAAE,CAAC,CAAC,YACd,aAAI,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAI,GACvE,CACN,EACA,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;wCAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;wCACnC,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;wCAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC;wCAEhC,OAAO,CACL,aAAiB,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,YAC1C,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAClC;gDAEE,iDAAiD;gDACjD,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,MAAM,IAAI,WAAW,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAEvD,MAAM,wBACN,MAAM,EAC1B,KAAK,EAAE;oDACL,KAAK,EACH,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,YAAY;wDAC7B,CAAC,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK;wDACzC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;oDAC3B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;oDACrE,IAAI,EACF,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM;wDAClC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;wDACxB,CAAC,CAAC,SAAS;oDACf,UAAU,EAAE,QAAQ;oDACpB,QAAQ,EAAE,QAAQ;oDAClB,YAAY,EAAE,UAAU;iDACzB,EACD,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAC3D,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,YAErD,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,IAvBrD,IAAI,CAAC,EAAE,CAwBT,CACN,CAAC,IA5BK,GAAG,CAAC,EAAE,CA6BV,CACN,CAAC;oCACJ,CAAC,CAAC,EACD,KAAK,GAAG,CAAC,IAAI,CACZ,aAAI,QAAQ,EAAE,CAAC,CAAC,YACd,aAAI,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAI,GACtE,CACN,IACK,IACF,GACJ,GACF,EAEL,KAAK,CAAC,qBAAqB,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,CAC7C,wBACE,eACE,KAAK,EAAC,8EAA8E,EACpF,KAAK,EAAE;wBACL,QAAQ,EAAE,UAAU;wBACpB,GAAG,EAAE,CAAC;wBACN,IAAI,EAAE,CAAC;wBACP,KAAK,EAAE,CAAC;wBACR,MAAM,EAAE,CAAC;wBACT,UAAU,EAAE,mBAAmB;qBAChC,EACD,IAAI,EAAC,QAAQ,eACH,QAAQ,aAElB,YAAG,KAAK,EAAC,gCAAgC,iBAAa,MAAM,GAAG,EAC/D,YAAG,KAAK,EAAC,MAAM,wEAA4D,IACvE,GACF,CACP,EACA,cAAc,KAAK,CAAC,IAAI,CACvB,cACE,KAAK,EAAC,8EAA8E,EACpF,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,GAAG,EAAE,CAAC;oBACN,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE,CAAC;oBACR,MAAM,EAAE,CAAC;oBACT,UAAU,EAAE,mBAAmB;iBAChC,EACD,IAAI,EAAC,QAAQ,eACH,QAAQ,YAEjB,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,GACzC,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAe,EAC9C,KAAK,EACL,KAAK,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,qBAAqB,GAAG,IAAI,GAY7B;IACC,MAAM,cAAc,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAEtD,oCAAoC;IACpC,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClG,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhE,SAAS,CAAC,GAAG,EAAE;QACb,4DAA4D;QAC5D,uFAAuF;QACvF,mBAAmB,CAAC,UAAU,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC;IACnD,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,CAAC,CAAsB,EAAE,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3E,UAAU,EAAE,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO,GAAG,EAAE,CAAC,UAAU,EAAE,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,gDAAgD;IAChD,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,SAAS,CAAC,KAAoB;YACrC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;gBACxE,IAAI,cAAc,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO,KAAK,QAAQ,CAAC,aAAa,EAAE,CAAC;oBAChF,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;oBAC/B,KAAK,CAAC,cAAc,EAAE,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAChD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAClE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;IACvD,MAAM,UAAU,GAAG,KAAK,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;IAEvD,OAAO,CACL,eAAK,KAAK,EAAC,+BAA+B,aACxC,cAAK,KAAK,EAAC,mCAAmC,YAC5C,eAAK,KAAK,EAAC,yDAAyD,aAClE,wBAAM,KAAK,GAAO,EAClB,eAAK,KAAK,EAAC,cAAc,aACtB,aAAa,EAEb,qBAAqB,IAAI,CACxB,KAAC,2BAA2B,IAAC,KAAK,EAAE,KAAK,KAAM,qBAAqB,GAAI,CACzE,IACG,IACF,GACF,EACN,eAAK,KAAK,EAAC,8BAA8B,aACvC,eAAK,KAAK,EAAC,yDAAyD,aAClE,eAAK,KAAK,EAAC,oEAAoE,aAC7E,eAAK,KAAK,EAAC,aAAa,aACtB,gBACE,GAAG,EAAE,cAAc,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,cAAc,gBACR,YAAY,CAAC,WAAW,EACpC,WAAW,EAAE,YAAY,CAAC,WAAW,EACrC,KAAK,EAAE,YAAY,CAAC,KAAK,EACzB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;oDACb,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,YAAY,gBAAgB,CAAC;wDAAE,OAAO;oDACpD,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gDACxC,CAAC,GACD,EACF,iBACE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAC,2BAA2B,gBACtB,cAAc,EACzB,KAAK,EAAC,cAAc,oBACL,SAAS,EACxB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,YAExC,YAAG,KAAK,EAAC,gBAAgB,iBAAa,MAAM,GAAG,GACxC,IACL,EAGL,gBAAgB,IAAI,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,GAAI,IAChD,EAGL,CAAC,gBAAgB,IAAI,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,GAAI,EACrD,cAAK,KAAK,EAAC,oDAAoD,YAC7D,eAAK,KAAK,EAAC,wBAAwB,yBACxB,cAAc,UAAM,UAAU,OAAG,KAAK,CAAC,WAAW,EAAE,IACzD,GACF,IACF,EACN,cAAK,KAAK,EAAC,aAAa,YACtB,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAM,YAAY,GAAI,GAC3D,IACF,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { flexRender } from '@tanstack/react-table';\nimport { notUndefined, useVirtualizer } from '@tanstack/react-virtual';\nimport type { Header, Row, SortDirection, Table } from '@tanstack/table-core';\nimport clsx from 'clsx';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport type { JSX } from 'preact/jsx-runtime';\n\nimport { ColumnManager } from './ColumnManager.js';\nimport {\n TanstackTableDownloadButton,\n type TanstackTableDownloadButtonProps,\n} from './TanstackTableDownloadButton.js';\n\nfunction SortIcon({ sortMethod }: { sortMethod: false | SortDirection }) {\n if (sortMethod === 'asc') {\n return <i class=\"bi bi-sort-up-alt\" aria-hidden=\"true\" />;\n } else if (sortMethod === 'desc') {\n return <i class=\"bi bi-sort-down\" aria-hidden=\"true\" />;\n } else {\n return <i class=\"bi bi-arrow-down-up opacity-75 text-muted\" aria-hidden=\"true\" />;\n }\n}\n\nfunction ResizeHandle<RowDataModel>({\n header,\n setColumnSizing,\n}: {\n header: Header<RowDataModel, unknown>;\n setColumnSizing: Table<RowDataModel>['setColumnSizing'];\n}) {\n const minSize = header.column.columnDef.minSize ?? 0;\n const maxSize = header.column.columnDef.maxSize ?? 0;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n e.preventDefault();\n const currentSize = header.getSize();\n const increment = e.shiftKey ? 20 : 5; // Larger increment with Shift key\n const newSize =\n e.key === 'ArrowLeft'\n ? Math.max(minSize, currentSize - increment)\n : Math.min(maxSize, currentSize + increment);\n\n setColumnSizing((prevSizing) => ({\n ...prevSizing,\n [header.column.id]: newSize,\n }));\n } else if (e.key === 'Home') {\n e.preventDefault();\n header.column.resetSize();\n }\n };\n\n const columnName =\n typeof header.column.columnDef.header === 'string'\n ? header.column.columnDef.header\n : header.column.id;\n\n return (\n <div class=\"py-1 h-100\" style={{ position: 'absolute', right: 0, top: 0, width: '4px' }}>\n {/* separator role is focusable, so these jsx-a11y-x rules are false positives.\n https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/separator_role#focusable_separator\n */}\n {/* eslint-disable-next-line jsx-a11y-x/no-noninteractive-element-interactions */}\n <div\n role=\"separator\"\n aria-label={`Resize '${columnName}' column`}\n aria-valuetext={`${header.getSize()}px`}\n aria-orientation=\"vertical\"\n aria-valuemin={minSize}\n aria-valuemax={maxSize}\n aria-valuenow={header.getSize()}\n // eslint-disable-next-line jsx-a11y-x/no-noninteractive-tabindex\n tabIndex={0}\n class=\"h-100\"\n style={{\n background: header.column.getIsResizing() ? 'var(--bs-primary)' : 'var(--bs-gray-400)',\n cursor: 'col-resize',\n transition: 'background-color 0.2s',\n }}\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n onKeyDown={handleKeyDown}\n />\n </div>\n );\n}\n\nconst DefaultNoResultsState = (\n <>\n <i class=\"bi bi-search display-4 mb-2\" aria-hidden=\"true\" />\n <p class=\"mb-0\">No results found matching your search criteria.</p>\n </>\n);\n\nconst DefaultEmptyState = (\n <>\n <i class=\"bi bi-eye-slash display-4 mb-2\" aria-hidden=\"true\" />\n <p class=\"mb-0\">No results found.</p>\n </>\n);\n\ninterface TanstackTableProps<RowDataModel> {\n table: Table<RowDataModel>;\n title: string;\n filters?: Record<string, (props: { header: Header<RowDataModel, unknown> }) => JSX.Element>;\n rowHeight?: number;\n noResultsState?: JSX.Element;\n emptyState?: JSX.Element;\n}\n\nconst DEFAULT_FILTER_MAP = {};\n\n/**\n * A generic component that renders a full-width, resizeable Tanstack Table.\n * @param params\n * @param params.table - The table model\n * @param params.title - The title of the table\n * @param params.filters - The filters for the table\n * @param params.rowHeight - The height of the rows in the table\n * @param params.noResultsState - The no results state for the table\n * @param params.emptyState - The empty state for the table\n */\nexport function TanstackTable<RowDataModel>({\n table,\n title,\n filters = DEFAULT_FILTER_MAP,\n rowHeight = 42,\n noResultsState = DefaultNoResultsState,\n emptyState = DefaultEmptyState,\n}: TanstackTableProps<RowDataModel>) {\n const parentRef = useRef<HTMLDivElement>(null);\n const tableRef = useRef<HTMLDivElement>(null);\n const rows = [...table.getTopRows(), ...table.getCenterRows()];\n const rowVirtualizer = useVirtualizer({\n count: rows.length,\n getScrollElement: () => parentRef.current,\n estimateSize: () => rowHeight,\n overscan: 10,\n });\n\n // Track focused cell for grid navigation\n const [focusedCell, setFocusedCell] = useState<{ row: number; col: number }>({ row: 0, col: 0 });\n\n const getVisibleCells = (row: Row<RowDataModel>) => [\n ...row.getLeftVisibleCells(),\n ...row.getCenterVisibleCells(),\n ];\n\n const handleGridKeyDown = (e: KeyboardEvent, rowIdx: number, colIdx: number) => {\n const rowLength = getVisibleCells(rows[rowIdx]).length;\n const adjacentCells: Record<KeyboardEvent['key'], { row: number; col: number }> = {\n ArrowDown: {\n row: Math.min(rows.length - 1, rowIdx + 1),\n col: colIdx,\n },\n ArrowUp: {\n row: Math.max(0, rowIdx - 1),\n col: colIdx,\n },\n ArrowRight: {\n row: rowIdx,\n col: Math.min(rowLength - 1, colIdx + 1),\n },\n ArrowLeft: {\n row: rowIdx,\n col: Math.max(0, colIdx - 1),\n },\n };\n\n const next = adjacentCells[e.key];\n\n if (!next) {\n return;\n }\n\n setFocusedCell({ row: next.row, col: next.col });\n // If we are on the leftmost column, we should allow left scrolling.\n if (colIdx === 0 && e.key === 'ArrowLeft') {\n return;\n }\n\n // If we are on the top row, we should allow up scrolling.\n if (rowIdx === 0 && e.key === 'ArrowUp') {\n return;\n }\n\n // If we are on the rightmost column, we should allow right scrolling.\n if (colIdx === rowLength - 1 && e.key === 'ArrowRight') {\n return;\n }\n\n e.preventDefault();\n };\n\n useEffect(() => {\n const selector = `[data-grid-cell-row=\"${focusedCell.row}\"][data-grid-cell-col=\"${focusedCell.col}\"]`;\n const cell = tableRef.current?.querySelector(selector) as HTMLElement | null;\n if (!cell) {\n return;\n }\n cell.focus();\n }, [focusedCell]);\n\n const virtualRows = rowVirtualizer.getVirtualItems();\n const [before, after] =\n virtualRows.length > 0\n ? [\n notUndefined(virtualRows[0]).start - rowVirtualizer.options.scrollMargin,\n rowVirtualizer.getTotalSize() - notUndefined(virtualRows.at(-1)).end,\n ]\n : [0, 0];\n const headerGroups = table.getHeaderGroups();\n const isTableResizing = headerGroups.some((headerGroup) =>\n headerGroup.headers.some((header) => header.column.getIsResizing()),\n );\n const lastColumnId = table.getAllLeafColumns()[table.getAllLeafColumns().length - 1].id;\n\n const tableRect = tableRef.current?.getBoundingClientRect();\n\n // We toggle this here instead of in the parent since this component logically manages all UI for the table.\n // eslint-disable-next-line react-you-might-not-need-an-effect/no-manage-parent\n useEffect(() => {\n document.body.classList.toggle('no-user-select', isTableResizing);\n }, [isTableResizing]);\n\n // Helper function to get aria-sort value\n const getAriaSort = (sortDirection: false | SortDirection) => {\n switch (sortDirection) {\n case 'asc':\n return 'ascending';\n case 'desc':\n return 'descending';\n default:\n return 'none';\n }\n };\n\n const displayedCount = table.getRowModel().rows.length;\n const totalCount = table.getCoreRowModel().rows.length;\n\n return (\n <div style={{ position: 'relative' }} class=\"d-flex flex-column h-100\">\n <div\n ref={parentRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n overflow: 'auto',\n overflowAnchor: 'none',\n }}\n >\n <div\n ref={tableRef}\n style={{\n position: 'relative',\n width: `max(${table.getTotalSize()}px, 100%)`,\n }}\n >\n <table\n class=\"table table-hover mb-0 border border-top-0\"\n style={{ tableLayout: 'fixed' }}\n aria-label={title}\n role=\"grid\"\n >\n <thead>\n {headerGroups.map((headerGroup) => (\n <tr key={headerGroup.id}>\n {headerGroup.headers.map((header, index) => {\n const isPinned = header.column.getIsPinned();\n const sortDirection = header.column.getIsSorted();\n const canSort = header.column.getCanSort();\n const canFilter = header.column.getCanFilter();\n const columnName =\n typeof header.column.columnDef.header === 'string'\n ? header.column.columnDef.header\n : header.column.id;\n\n const style: JSX.CSSProperties = {\n width:\n header.column.id === lastColumnId\n ? `max(100%, ${header.getSize()}px)`\n : header.getSize(),\n position: 'sticky',\n top: 0,\n zIndex: isPinned === 'left' ? 2 : 1,\n left: isPinned === 'left' ? header.getStart() : undefined,\n boxShadow:\n 'inset 0 calc(-1 * var(--bs-border-width)) 0 0 rgba(0, 0, 0, 1), inset 0 var(--bs-border-width) 0 0 var(--bs-border-color)',\n };\n\n return (\n <th\n key={header.id}\n class={clsx(isPinned === 'left' && 'bg-light')}\n style={style}\n aria-sort={canSort ? getAriaSort(sortDirection) : undefined}\n role=\"columnheader\"\n >\n <div class=\"d-flex align-items-center justify-content-between gap-2\">\n <button\n class=\"text-nowrap flex-grow-1 text-start\"\n style={{\n cursor: canSort ? 'pointer' : 'default',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n background: 'transparent',\n border: 'none',\n }}\n type=\"button\"\n aria-label={\n canSort\n ? `'${columnName}' column, current sort is ${getAriaSort(sortDirection)}`\n : undefined\n }\n onClick={canSort ? header.column.getToggleSortingHandler() : undefined}\n onKeyDown={\n canSort\n ? (e) => {\n const handleSort = header.column.getToggleSortingHandler();\n if (e.key === 'Enter' && handleSort) {\n e.preventDefault();\n handleSort(e);\n }\n }\n : undefined\n }\n >\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n {canSort && (\n <span class=\"ms-2\" aria-hidden=\"true\">\n <SortIcon sortMethod={sortDirection || false} />\n </span>\n )}\n {canSort && (\n <span class=\"visually-hidden\">\n , {getAriaSort(sortDirection)}, click to sort\n </span>\n )}\n </button>\n\n {canFilter && filters[header.column.id]?.({ header })}\n </div>\n {tableRect?.width &&\n tableRect.width > table.getTotalSize() &&\n index === headerGroup.headers.length - 1 ? null : (\n <ResizeHandle header={header} setColumnSizing={table.setColumnSizing} />\n )}\n </th>\n );\n })}\n </tr>\n ))}\n </thead>\n <tbody>\n {before > 0 && (\n <tr tabIndex={-1}>\n <td colSpan={headerGroups[0].headers.length} style={{ height: before }} />\n </tr>\n )}\n {virtualRows.map((virtualRow) => {\n const row = rows[virtualRow.index];\n const visibleCells = getVisibleCells(row);\n const rowIdx = virtualRow.index;\n\n return (\n <tr key={row.id} style={{ height: rowHeight }}>\n {visibleCells.map((cell, colIdx) => (\n <td\n key={cell.id}\n // You can tab to the most-recently focused cell.\n tabIndex={focusedCell.row === rowIdx && focusedCell.col === colIdx ? 0 : -1}\n // We store this so you can navigate around the grid.\n data-grid-cell-row={rowIdx}\n data-grid-cell-col={colIdx}\n style={{\n width:\n cell.column.id === lastColumnId\n ? `max(100%, ${cell.column.getSize()}px)`\n : cell.column.getSize(),\n position: cell.column.getIsPinned() === 'left' ? 'sticky' : undefined,\n left:\n cell.column.getIsPinned() === 'left'\n ? cell.column.getStart()\n : undefined,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n onFocus={() => setFocusedCell({ row: rowIdx, col: colIdx })}\n onKeyDown={(e) => handleGridKeyDown(e, rowIdx, colIdx)}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </td>\n ))}\n </tr>\n );\n })}\n {after > 0 && (\n <tr tabIndex={-1}>\n <td colSpan={headerGroups[0].headers.length} style={{ height: after }} />\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n\n {table.getVisibleLeafColumns().length === 0 && (\n <div>\n <div\n class=\"d-flex flex-column justify-content-center align-items-center text-muted py-4\"\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: 'var(--bs-body-bg)',\n }}\n role=\"status\"\n aria-live=\"polite\"\n >\n <i class=\"bi bi-eye-slash display-4 mb-2\" aria-hidden=\"true\" />\n <p class=\"mb-0\">No columns selected. Use the View menu to show columns.</p>\n </div>\n </div>\n )}\n {displayedCount === 0 && (\n <div\n class=\"d-flex flex-column justify-content-center align-items-center text-muted py-4\"\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: 'var(--bs-body-bg)',\n }}\n role=\"status\"\n aria-live=\"polite\"\n >\n {totalCount > 0 ? noResultsState : emptyState}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * A generic component that wraps the TanstackTable component in a card.\n * @param params\n * @param params.table - The table model\n * @param params.title - The title of the card\n * @param params.headerButtons - The buttons to display in the header\n * @param params.globalFilter - State management for the global filter\n * @param params.globalFilter.value\n * @param params.globalFilter.setValue\n * @param params.globalFilter.placeholder\n * @param params.tableOptions - Specific options for the table. See {@link TanstackTableProps} for more details.\n * @param params.downloadButtonOptions - Specific options for the download button. See {@link TanstackTableDownloadButtonProps} for more details.\n */\nexport function TanstackTableCard<RowDataModel>({\n table,\n title,\n headerButtons,\n globalFilter,\n tableOptions,\n downloadButtonOptions = null,\n}: {\n table: Table<RowDataModel>;\n title: string;\n headerButtons: JSX.Element;\n globalFilter: {\n value: string;\n setValue: (value: string) => void;\n placeholder: string;\n };\n tableOptions: Partial<Omit<TanstackTableProps<RowDataModel>, 'table'>>;\n downloadButtonOptions?: Omit<TanstackTableDownloadButtonProps<RowDataModel>, 'table'> | null;\n}) {\n const searchInputRef = useRef<HTMLInputElement>(null);\n\n // Track screen size for aria-hidden\n const mediaQuery = typeof window !== 'undefined' ? window.matchMedia('(min-width: 768px)') : null;\n const [isMediumOrLarger, setIsMediumOrLarger] = useState(false);\n\n useEffect(() => {\n // TODO: This is a workaround to avoid a hydration mismatch.\n // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect\n setIsMediumOrLarger(mediaQuery?.matches ?? true);\n }, [mediaQuery]);\n\n useEffect(() => {\n const handler = (e: MediaQueryListEvent) => setIsMediumOrLarger(e.matches);\n mediaQuery?.addEventListener('change', handler);\n return () => mediaQuery?.removeEventListener('change', handler);\n }, [mediaQuery]);\n\n // Focus the search input when Ctrl+F is pressed\n useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'f') {\n if (searchInputRef.current && searchInputRef.current !== document.activeElement) {\n searchInputRef.current.focus();\n event.preventDefault();\n }\n }\n }\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, []);\n\n const displayedCount = table.getRowModel().rows.length;\n const totalCount = table.getCoreRowModel().rows.length;\n\n return (\n <div class=\"card d-flex flex-column h-100\">\n <div class=\"card-header bg-primary text-white\">\n <div class=\"d-flex align-items-center justify-content-between gap-2\">\n <div>{title}</div>\n <div class=\"d-flex gap-2\">\n {headerButtons}\n\n {downloadButtonOptions && (\n <TanstackTableDownloadButton table={table} {...downloadButtonOptions} />\n )}\n </div>\n </div>\n </div>\n <div class=\"card-body d-flex flex-column\">\n <div class=\"d-flex flex-row flex-wrap align-items-center mb-3 gap-2\">\n <div class=\"flex-grow-1 flex-lg-grow-0 col-xl-6 col-lg-7 d-flex flex-row gap-2\">\n <div class=\"input-group\">\n <input\n ref={searchInputRef}\n type=\"text\"\n class=\"form-control\"\n aria-label={globalFilter.placeholder}\n placeholder={globalFilter.placeholder}\n value={globalFilter.value}\n onInput={(e) => {\n if (!(e.target instanceof HTMLInputElement)) return;\n globalFilter.setValue(e.target.value);\n }}\n />\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n aria-label=\"Clear search\"\n title=\"Clear search\"\n data-bs-toggle=\"tooltip\"\n onClick={() => globalFilter.setValue('')}\n >\n <i class=\"bi bi-x-circle\" aria-hidden=\"true\" />\n </button>\n </div>\n {/* We do this instead of CSS properties for the accessibility checker.\n We can't have two elements with the same id of 'column-manager-button'. */}\n {isMediumOrLarger && <ColumnManager table={table} />}\n </div>\n {/* We do this instead of CSS properties for the accessibility checker.\n We can't have two elements with the same id of 'column-manager-button'. */}\n {!isMediumOrLarger && <ColumnManager table={table} />}\n <div class=\"flex-lg-grow-1 d-flex flex-row justify-content-end\">\n <div class=\"text-muted text-nowrap\">\n Showing {displayedCount} of {totalCount} {title.toLowerCase()}\n </div>\n </div>\n </div>\n <div class=\"flex-grow-1\">\n <TanstackTable table={table} title={title} {...tableOptions} />\n </div>\n </div>\n </div>\n );\n}\n"]}
@@ -16,3 +16,4 @@ export interface TanstackTableDownloadButtonProps<RowDataModel> {
16
16
  * the row will be skipped.
17
17
  */
18
18
  export declare function TanstackTableDownloadButton<RowDataModel>({ table, filenameBase, mapRowToData, pluralLabel, }: TanstackTableDownloadButtonProps<RowDataModel>): import("original-preact").JSX.Element;
19
+ //# sourceMappingURL=TanstackTableDownloadButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TanstackTableDownloadButton.d.ts","sourceRoot":"","sources":["../../src/components/TanstackTableDownloadButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAInD,MAAM,WAAW,gCAAgC,CAAC,YAAY;IAC5D,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACnF,WAAW,EAAE,MAAM,CAAC;CACrB;AACD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,EACxD,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,EAAE,gCAAgC,CAAC,YAAY,CAAC,yCAoFhD"}
package/dist/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export { TanstackTable, TanstackTableCard } from './components/TanstackTable.js'
2
2
  export { ColumnManager } from './components/ColumnManager.js';
3
3
  export { TanstackTableDownloadButton } from './components/TanstackTableDownloadButton.js';
4
4
  export { CategoricalColumnFilter } from './components/CategoricalColumnFilter.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prairielearn/ui",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,8 +16,8 @@
16
16
  "dev": "tsc --watch --preserveWatchOutput & tscp --watch"
17
17
  },
18
18
  "dependencies": {
19
- "@prairielearn/browser-utils": "^2.4.0",
20
- "@prairielearn/preact-cjs": "^1.1.4",
19
+ "@prairielearn/browser-utils": "^2.5.1",
20
+ "@prairielearn/preact-cjs": "^1.1.5",
21
21
  "@tanstack/react-table": "^8.21.3",
22
22
  "@tanstack/react-virtual": "^3.13.12",
23
23
  "@tanstack/table-core": "^8.21.3",
@@ -85,17 +85,26 @@ function ResizeHandle<RowDataModel>({
85
85
  );
86
86
  }
87
87
 
88
- const DefaultEmptyState = (
88
+ const DefaultNoResultsState = (
89
89
  <>
90
90
  <i class="bi bi-search display-4 mb-2" aria-hidden="true" />
91
91
  <p class="mb-0">No results found matching your search criteria.</p>
92
92
  </>
93
93
  );
94
94
 
95
+ const DefaultEmptyState = (
96
+ <>
97
+ <i class="bi bi-eye-slash display-4 mb-2" aria-hidden="true" />
98
+ <p class="mb-0">No results found.</p>
99
+ </>
100
+ );
101
+
95
102
  interface TanstackTableProps<RowDataModel> {
96
103
  table: Table<RowDataModel>;
104
+ title: string;
97
105
  filters?: Record<string, (props: { header: Header<RowDataModel, unknown> }) => JSX.Element>;
98
106
  rowHeight?: number;
107
+ noResultsState?: JSX.Element;
99
108
  emptyState?: JSX.Element;
100
109
  }
101
110
 
@@ -108,6 +117,7 @@ const DEFAULT_FILTER_MAP = {};
108
117
  * @param params.title - The title of the table
109
118
  * @param params.filters - The filters for the table
110
119
  * @param params.rowHeight - The height of the rows in the table
120
+ * @param params.noResultsState - The no results state for the table
111
121
  * @param params.emptyState - The empty state for the table
112
122
  */
113
123
  export function TanstackTable<RowDataModel>({
@@ -115,14 +125,9 @@ export function TanstackTable<RowDataModel>({
115
125
  title,
116
126
  filters = DEFAULT_FILTER_MAP,
117
127
  rowHeight = 42,
128
+ noResultsState = DefaultNoResultsState,
118
129
  emptyState = DefaultEmptyState,
119
- }: {
120
- table: Table<RowDataModel>;
121
- title: string;
122
- emptyState?: JSX.Element;
123
- rowHeight?: number;
124
- filters?: Record<string, (props: { header: Header<RowDataModel, unknown> }) => JSX.Element>;
125
- }) {
130
+ }: TanstackTableProps<RowDataModel>) {
126
131
  const parentRef = useRef<HTMLDivElement>(null);
127
132
  const tableRef = useRef<HTMLDivElement>(null);
128
133
  const rows = [...table.getTopRows(), ...table.getCenterRows()];
@@ -230,6 +235,9 @@ export function TanstackTable<RowDataModel>({
230
235
  }
231
236
  };
232
237
 
238
+ const displayedCount = table.getRowModel().rows.length;
239
+ const totalCount = table.getCoreRowModel().rows.length;
240
+
233
241
  return (
234
242
  <div style={{ position: 'relative' }} class="d-flex flex-column h-100">
235
243
  <div
@@ -422,7 +430,7 @@ export function TanstackTable<RowDataModel>({
422
430
  </div>
423
431
  </div>
424
432
  )}
425
- {table.getRowModel().rows.length === 0 && (
433
+ {displayedCount === 0 && (
426
434
  <div
427
435
  class="d-flex flex-column justify-content-center align-items-center text-muted py-4"
428
436
  style={{
@@ -436,7 +444,7 @@ export function TanstackTable<RowDataModel>({
436
444
  role="status"
437
445
  aria-live="polite"
438
446
  >
439
- {emptyState}
447
+ {totalCount > 0 ? noResultsState : emptyState}
440
448
  </div>
441
449
  )}
442
450
  </div>
@@ -507,6 +515,9 @@ export function TanstackTableCard<RowDataModel>({
507
515
  return () => document.removeEventListener('keydown', onKeyDown);
508
516
  }, []);
509
517
 
518
+ const displayedCount = table.getRowModel().rows.length;
519
+ const totalCount = table.getCoreRowModel().rows.length;
520
+
510
521
  return (
511
522
  <div class="card d-flex flex-column h-100">
512
523
  <div class="card-header bg-primary text-white">
@@ -557,8 +568,7 @@ export function TanstackTableCard<RowDataModel>({
557
568
  {!isMediumOrLarger && <ColumnManager table={table} />}
558
569
  <div class="flex-lg-grow-1 d-flex flex-row justify-content-end">
559
570
  <div class="text-muted text-nowrap">
560
- Showing {table.getRowModel().rows.length} of {table.getCoreRowModel().rows.length}{' '}
561
- {title.toLowerCase()}
571
+ Showing {displayedCount} of {totalCount} {title.toLowerCase()}
562
572
  </div>
563
573
  </div>
564
574
  </div>