@verifiedinc-public/shared-ui-elements 11.0.3-beta.1 → 11.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.
Files changed (46) hide show
  1. package/dist/components/DataTable/DataTable.context.d.ts +102 -0
  2. package/dist/components/DataTable/DataTable.context.mjs +1 -0
  3. package/dist/components/DataTable/DataTable.d.ts +8 -0
  4. package/dist/components/DataTable/DataTable.export.d.ts +37 -0
  5. package/dist/components/DataTable/DataTable.export.mjs +8 -0
  6. package/dist/components/DataTable/DataTable.filters.d.ts +51 -0
  7. package/dist/components/DataTable/DataTable.filters.mjs +1 -0
  8. package/dist/components/DataTable/DataTable.hooks.d.ts +43 -0
  9. package/dist/components/DataTable/DataTable.hooks.mjs +1 -0
  10. package/dist/components/DataTable/DataTable.mjs +1 -0
  11. package/dist/components/DataTable/DataTable.types.d.ts +525 -0
  12. package/dist/components/DataTable/DataTable.utils.d.ts +39 -0
  13. package/dist/components/DataTable/DataTable.utils.mjs +1 -0
  14. package/dist/components/DataTable/DataTableBody.d.ts +7 -0
  15. package/dist/components/DataTable/DataTableBody.mjs +1 -0
  16. package/dist/components/DataTable/DataTableColumnMenu.d.ts +22 -0
  17. package/dist/components/DataTable/DataTableColumnMenu.mjs +1 -0
  18. package/dist/components/DataTable/DataTableExportMenu.d.ts +16 -0
  19. package/dist/components/DataTable/DataTableExportMenu.mjs +1 -0
  20. package/dist/components/DataTable/DataTableFilterPanel.d.ts +36 -0
  21. package/dist/components/DataTable/DataTableFilterPanel.mjs +1 -0
  22. package/dist/components/DataTable/DataTableFooter.d.ts +6 -0
  23. package/dist/components/DataTable/DataTableFooter.mjs +1 -0
  24. package/dist/components/DataTable/DataTableHead.d.ts +8 -0
  25. package/dist/components/DataTable/DataTableHead.mjs +1 -0
  26. package/dist/components/DataTable/DataTableHeaderCell.d.ts +16 -0
  27. package/dist/components/DataTable/DataTableHeaderCell.mjs +1 -0
  28. package/dist/components/DataTable/DataTableManageColumnsPanel.d.ts +30 -0
  29. package/dist/components/DataTable/DataTableManageColumnsPanel.mjs +1 -0
  30. package/dist/components/DataTable/DataTablePanels.d.ts +6 -0
  31. package/dist/components/DataTable/DataTablePanels.mjs +1 -0
  32. package/dist/components/DataTable/DataTableToolbar.d.ts +7 -0
  33. package/dist/components/DataTable/DataTableToolbar.mjs +1 -0
  34. package/dist/components/DataTable/index.d.ts +5 -0
  35. package/dist/components/chart/BillableEventsTable/BillableEventsTable.mjs +1 -1
  36. package/dist/components/chart/BillableEventsTable/BillableEventsTable.types.d.ts +0 -23
  37. package/dist/components/chart/BillableEventsTable/BrandDetailsPanel.d.ts +1 -2
  38. package/dist/components/chart/BillableEventsTable/BrandDetailsPanel.mjs +1 -1
  39. package/dist/components/chart/BillableEventsTable/exportBillableEventsToCsv.d.ts +2 -4
  40. package/dist/components/chart/BillableEventsTable/exportBillableEventsToCsv.mjs +3 -3
  41. package/dist/components/index.d.ts +1 -0
  42. package/dist/components/index.mjs +1 -1
  43. package/dist/hooks/useBidirectionalScroll.d.ts +8 -1
  44. package/dist/hooks/useBidirectionalScroll.mjs +1 -1
  45. package/dist/index.mjs +1 -1
  46. package/package.json +2 -1
@@ -0,0 +1,102 @@
1
+ import { CSSProperties, MouseEvent, MutableRefObject, ReactNode, RefObject, TouchEvent } from 'react';
2
+ import { Cell, ColumnPinningPosition, Header, OnChangeFn, Row, Table } from '@tanstack/react-table';
3
+ import { Virtualizer } from '@tanstack/react-virtual';
4
+ import { DataTableActiveFilters, DataTableBidirectionalScroll, DataTableCellProps, DataTableData, DataTableIcons, DataTableRowContext } from './DataTable.types';
5
+ /** Where a floating panel opens and which of its top corners pins there. */
6
+ export type DataTablePanelAnchor = {
7
+ anchorPosition: {
8
+ top: number;
9
+ left: number;
10
+ };
11
+ transformHorizontal: 'left' | 'right';
12
+ };
13
+ /**
14
+ * One floating column panel is open at a time: a column's kebab menu
15
+ * (anchored to its button), or the filter / manage columns panels
16
+ * (anchored to a position snapshot, since they can outlive the element
17
+ * that opened them). With the toolbar shown, those two panels anchor to
18
+ * their toolbar button instead, wherever they were opened from.
19
+ */
20
+ export type DataTableColumnPanelState = {
21
+ type: 'menu';
22
+ columnId: string;
23
+ anchorEl: HTMLElement;
24
+ } | ({
25
+ type: 'filter';
26
+ columnId: string;
27
+ } & DataTablePanelAnchor) | ({
28
+ type: 'manageColumns';
29
+ } & DataTablePanelAnchor) | null;
30
+ /**
31
+ * Everything the DataTable subcomponents (toolbar, head, body, footer,
32
+ * floating panels) read from the root component. The value is rebuilt on
33
+ * every DataTable render — the same cadence the single-component render
34
+ * had — so it is intentionally not memoized.
35
+ */
36
+ export interface DataTableContextValue<TData extends DataTableData> {
37
+ /** TanStack table instance. */
38
+ table: Table<TData>;
39
+ /** Unfiltered rows — the filter panel derives value suggestions from them. */
40
+ data: TData[];
41
+ /** Rows of the current page (or all rows when pagination is disabled). */
42
+ rows: Array<Row<TData>>;
43
+ /** Total row count across every page — drives the pagination footer. */
44
+ totalRowCount: number;
45
+ /**
46
+ * Visible leaf column count — drives the colSpan of full-width rows
47
+ * (loading, empty, dividers, virtualizer padding).
48
+ */
49
+ columnCount: number;
50
+ icons: DataTableIcons;
51
+ isLoading: boolean;
52
+ emptyMessage: string;
53
+ tableLayout: 'auto' | 'fixed';
54
+ enableColumnResizing: boolean;
55
+ enableColumnMenu: boolean;
56
+ enableExport: boolean;
57
+ exportFilename: string;
58
+ disablePagination: boolean;
59
+ pageSizeOptions: number[];
60
+ footerLeft?: ReactNode;
61
+ bidirectionalScroll?: DataTableBidirectionalScroll;
62
+ renderLoading?: (columnCount: number) => ReactNode;
63
+ renderRow?: (context: DataTableRowContext<TData>) => ReactNode;
64
+ filters: DataTableActiveFilters;
65
+ onFiltersChange: OnChangeFn<DataTableActiveFilters>;
66
+ search: string;
67
+ onSearchChange: OnChangeFn<string>;
68
+ columnPanel: DataTableColumnPanelState;
69
+ setColumnPanel: (panel: DataTableColumnPanelState) => void;
70
+ closeColumnPanel: () => void;
71
+ openFilterPanel: (columnId: string, opener: HTMLElement) => void;
72
+ openManageColumnsPanel: (opener: HTMLElement) => void;
73
+ toolbarFilterButtonRef: RefObject<HTMLButtonElement>;
74
+ toolbarManageColumnsButtonRef: RefObject<HTMLButtonElement>;
75
+ headerRowRefs: MutableRefObject<Array<HTMLTableRowElement | null>>;
76
+ headerCellRefs: MutableRefObject<Record<string, HTMLTableCellElement | null>>;
77
+ /** Sticky top offsets of the header rows below the first (grouped headers). */
78
+ headerRowTops: number[];
79
+ /**
80
+ * Measured total header height — the loading-newer indicator sticks
81
+ * right below it. 0 unless bidirectional scroll is active.
82
+ */
83
+ headerHeight: number;
84
+ isPinnedEdge: (pinned: ColumnPinningPosition, columnId: string) => boolean;
85
+ getPinnedOffsetStyle: (pinned: ColumnPinningPosition, columnId: string) => CSSProperties | undefined;
86
+ getCellProps: (cell: Cell<TData, unknown>) => DataTableCellProps;
87
+ hasResizedColumns: boolean;
88
+ startColumnResize: (header: Header<TData, unknown>, event: MouseEvent<HTMLElement> | TouchEvent<HTMLElement>) => void;
89
+ virtualizer: Virtualizer<HTMLDivElement, Element>;
90
+ }
91
+ interface DataTableProviderProps<TData extends DataTableData> {
92
+ value: DataTableContextValue<TData>;
93
+ children: ReactNode;
94
+ }
95
+ export declare function DataTableProvider<TData extends DataTableData>({ value, children, }: Readonly<DataTableProviderProps<TData>>): import("react").JSX.Element;
96
+ /**
97
+ * Reads the enclosing DataTable's context. Subcomponents default to the
98
+ * base `DataTableData` row shape; pass the concrete `TData` when a typed
99
+ * view is needed.
100
+ */
101
+ export declare function useDataTableContext<TData extends DataTableData = DataTableData>(): DataTableContextValue<TData>;
102
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";import{createContext as r,useContext as n}from"react";import{jsx as o}from"react/jsx-runtime";const t=r(null);function s({value:e,children:a}){return o(t.Provider,{value:e,children:a})}function u(){const e=n(t);if(!e)throw new Error("useDataTableContext must be used within a <DataTable/>");return e}export{s as DataTableProvider,u as useDataTableContext};
@@ -0,0 +1,8 @@
1
+ import { DataTableData, DataTableProps } from './DataTable.types';
2
+ /**
3
+ * Root of the DataTable: owns every piece of table state and the TanStack
4
+ * instance, shares them with the subcomponents (toolbar, head, body,
5
+ * footer, floating panels) through DataTableProvider, and renders the
6
+ * layout shell around them.
7
+ */
8
+ export declare function DataTable<TData extends DataTableData>({ data, columns, getRowId, renderRow, initialSorting, sorting: controlledSorting, onSortingChange, manualSorting, initialPageSize, pageSizeOptions, pagination: controlledPagination, onPaginationChange, manualPagination, rowCount, disableSorting, disablePagination, bidirectionalScroll, enableColumnResizing, enableColumnMenu, enableColumnPinning, showToolbar, enableExport, exportFilename, initialFilters, filters: controlledFilters, onFiltersChange, manualFiltering, initialSearch, search: controlledSearch, onSearchChange, initialColumnVisibility, columnVisibility: controlledColumnVisibility, onColumnVisibilityChange, initialColumnPinning, columnPinning: controlledColumnPinning, onColumnPinningChange, footerLeft, estimateRowHeight, minWidth, maxHeight, tableLayout, icons, emptyMessage, isLoading, renderLoading, }: Readonly<DataTableProps<TData>>): import("react").JSX.Element;
@@ -0,0 +1,37 @@
1
+ import { Table } from '@tanstack/react-table';
2
+ import { DataTableData } from './DataTable.types';
3
+ /** Cell value shape carried into the export formats. */
4
+ export type DataTableExportValue = string | number | boolean;
5
+ /**
6
+ * Snapshot of the displayed table used by every export format: the
7
+ * filtered + sorted rows across every page and the visible accessor
8
+ * columns in display order.
9
+ */
10
+ export interface DataTableExportModel {
11
+ /**
12
+ * Group header row mirroring the table's grouped header — each group
13
+ * label at the start of its span, blanks elsewhere. Omitted when no
14
+ * visible column is grouped.
15
+ */
16
+ groupHeader?: string[];
17
+ header: string[];
18
+ rows: DataTableExportValue[][];
19
+ }
20
+ /**
21
+ * Builds the export snapshot from the table instance. Rows come from the
22
+ * pre-pagination row model, so they reflect the active filters, quick
23
+ * search and sort order across every page (with manual pagination only
24
+ * the loaded page is available). Display-only columns (no accessor, e.g.
25
+ * expand chevrons) are skipped.
26
+ */
27
+ export declare function getDataTableExportModel<TData extends DataTableData>(table: Table<TData>): DataTableExportModel;
28
+ /** Downloads the export snapshot as `<filename>.csv`. */
29
+ export declare function exportDataTableToCsv(model: DataTableExportModel, filename: string): void;
30
+ /** Downloads the export snapshot as `<filename>.xlsx`. */
31
+ export declare function exportDataTableToExcel(model: DataTableExportModel, filename: string): void;
32
+ /**
33
+ * Opens the browser print dialog with a print-friendly rendering of the
34
+ * export snapshot (via a hidden iframe, so the page itself never
35
+ * navigates). The title becomes the printed document name.
36
+ */
37
+ export declare function printDataTable(model: DataTableExportModel, title: string): void;
@@ -0,0 +1,8 @@
1
+ "use strict";import{getColumnLabel as y}from"./DataTable.utils.mjs";function b(e){return e==null?"":typeof e=="number"||typeof e=="boolean"?e:e instanceof Date?e.toLocaleString():typeof e=="object"?JSON.stringify(e):String(e)}function U(e){const n=e.getVisibleLeafColumns().filter(o=>o.accessorFn!==void 0),t=n.map(o=>{var r;const l=(r=o.parent)==null?void 0:r.columnDef.header;return typeof l=="string"?l:""});return{groupHeader:t.some(o=>o!=="")?t.map((o,r)=>r>0&&t[r-1]===o?"":o):void 0,header:n.map(o=>y(o)),rows:e.getPrePaginationRowModel().rows.map(o=>n.map(r=>b(o.getValue(r.id))))}}function x(e,n){const t=URL.createObjectURL(e),o=document.createElement("a");o.href=t,o.download=n,o.click(),URL.revokeObjectURL(t)}function w(e){const n=String(e);return/[",\n]/.test(n)?`"${n.replace(/"/g,'""')}"`:n}function v(e,n){const t=[...e.groupHeader?[e.groupHeader]:[],e.header,...e.rows].map(r=>r.map(w).join(",")),o=new Blob(["\uFEFF",t.join(`
2
+ `)],{type:"text/csv;charset=utf-8;"});x(o,`${n}.csv`)}function f(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function k(e){let n="",t=e+1;for(;t>0;)n=String.fromCharCode(65+(t-1)%26)+n,t=Math.floor((t-1)/26);return n}function T(e){return`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>${[...e.groupHeader?[e.groupHeader]:[],e.header,...e.rows].map((n,t)=>{const o=n.map((r,l)=>{const s=`${k(l)}${t+1}`;return typeof r=="number"&&Number.isFinite(r)?`<c r="${s}"><v>${r}</v></c>`:typeof r=="boolean"?`<c r="${s}" t="b"><v>${r?1:0}</v></c>`:`<c r="${s}" t="inlineStr"><is><t xml:space="preserve">${f(String(r))}</t></is></c>`}).join("");return`<row r="${t+1}">${o}</row>`}).join("")}</sheetData></worksheet>`}const $=[{name:"[Content_Types].xml",content:'<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/></Types>'},{name:"_rels/.rels",content:'<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>'},{name:"xl/workbook.xml",content:'<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Data" sheetId="1" r:id="rId1"/></sheets></workbook>'},{name:"xl/_rels/workbook.xml.rels",content:'<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/></Relationships>'}],D=(()=>{const e=new Uint32Array(256);for(let n=0;n<256;n++){let t=n;for(let o=0;o<8;o++)t=t&1?3988292384^t>>>1:t>>>1;e[n]=t>>>0}return e})();function R(e){let n=4294967295;for(let t=0;t<e.length;t++)n=D[(n^e[t])&255]^n>>>8;return(n^4294967295)>>>0}function C(e){const n=new TextEncoder,t=[],o=[];let r=0;for(const p of e){const m=n.encode(p.name),c=n.encode(p.content),g=R(c),i=new DataView(new ArrayBuffer(30));i.setUint32(0,67324752,!0),i.setUint16(4,20,!0),i.setUint16(6,2048,!0),i.setUint16(8,0,!0),i.setUint16(10,0,!0),i.setUint16(12,33,!0),i.setUint32(14,g,!0),i.setUint32(18,c.length,!0),i.setUint32(22,c.length,!0),i.setUint16(26,m.length,!0),i.setUint16(28,0,!0),t.push(new Uint8Array(i.buffer),m,c);const a=new DataView(new ArrayBuffer(46));a.setUint32(0,33639248,!0),a.setUint16(4,20,!0),a.setUint16(6,20,!0),a.setUint16(8,2048,!0),a.setUint16(10,0,!0),a.setUint16(12,0,!0),a.setUint16(14,33,!0),a.setUint32(16,g,!0),a.setUint32(20,c.length,!0),a.setUint32(24,c.length,!0),a.setUint16(28,m.length,!0),a.setUint32(42,r,!0),o.push(new Uint8Array(a.buffer),m),r+=30+m.length+c.length}const l=o.reduce((p,m)=>p+m.length,0),s=new DataView(new ArrayBuffer(22));s.setUint32(0,101010256,!0),s.setUint16(8,e.length,!0),s.setUint16(10,e.length,!0),s.setUint32(12,l,!0),s.setUint32(16,r,!0);const h=new Uint8Array(s.buffer),d=new Uint8Array(r+l+h.length);let u=0;for(const p of[...t,...o,h])d.set(p,u),u+=p.length;return d.buffer}function j(e,n){const t=C([...$,{name:"xl/worksheets/sheet1.xml",content:T(e)}]);x(new Blob([t],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}),`${n}.xlsx`)}function F(e,n){const t=(l,s)=>`<tr>${l.map(h=>`<${s}${typeof h=="number"?' class="num"':""}>${f(String(h))}</${s}>`).join("")}</tr>`,o=[...e.groupHeader?[t(e.groupHeader,"th")]:[],t(e.header,"th")].join(""),r=e.rows.map(l=>t(l,"td")).join("");return`<!doctype html><html><head><meta charset="utf-8"><title>${f(n)}</title><style>
3
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; margin: 16px; }
4
+ table { border-collapse: collapse; width: 100%; font-size: 12px; }
5
+ th, td { padding: 6px 8px; border-bottom: 1px solid #ddd; text-align: left; }
6
+ th { text-transform: uppercase; font-size: 10px; }
7
+ .num { text-align: right; }
8
+ </style></head><body><table><thead>${o}</thead><tbody>${r}</tbody></table></body></html>`}function S(e,n){const t=document.createElement("iframe");t.style.position="fixed",t.style.right="0",t.style.bottom="0",t.style.width="0",t.style.height="0",t.style.border="0",t.onload=()=>{const o=t.contentWindow;if(!o){t.remove();return}o.addEventListener("afterprint",()=>t.remove()),o.focus(),o.print()},t.srcdoc=F(e,n),document.body.appendChild(t)}export{v as exportDataTableToCsv,j as exportDataTableToExcel,U as getDataTableExportModel,S as printDataTable};
@@ -0,0 +1,51 @@
1
+ import { ColumnDef, Row } from '@tanstack/react-table';
2
+ import { DataTableActiveFilters, DataTableData, DataTableFilterOperator, DataTableFilterRow } from './DataTable.types';
3
+ /** Option entries for the filter panel operator select, in display order. */
4
+ export declare const dataTableFilterOperators: ReadonlyArray<{
5
+ value: DataTableFilterOperator;
6
+ label: string;
7
+ }>;
8
+ /** Whether the operator needs a value input to be meaningful. */
9
+ export declare function filterOperatorRequiresValue(operator: DataTableFilterOperator): boolean;
10
+ /**
11
+ * Whether the operator takes multiple values — rendered as a chips input
12
+ * in the filter panel instead of a single text field.
13
+ */
14
+ export declare function filterOperatorIsMultiValue(operator: DataTableFilterOperator): boolean;
15
+ /** Empty filter state — no rows, AND logic. */
16
+ export declare const EMPTY_FILTERS: DataTableActiveFilters;
17
+ /**
18
+ * Whether a filter row has a usable value — rows without a value pass all
19
+ * rows through, so they are excluded from the active-filter indicator and
20
+ * from pre-filtering.
21
+ */
22
+ export declare function isFilterRowActive(row: DataTableFilterRow): boolean;
23
+ /**
24
+ * Client-side multi-filter: filters `data` rows using `filters.rows` with
25
+ * AND or OR logic. Rows with incomplete values are skipped. Returns `data`
26
+ * unchanged when there are no active rows (no re-allocation).
27
+ *
28
+ * With `columns`, each filter resolves its value through the targeted
29
+ * column's accessor (so columns reading nested values filter correctly);
30
+ * without them it falls back to the raw row key.
31
+ */
32
+ export declare function applyFilters<TData extends DataTableData>(data: TData[], filters: DataTableActiveFilters, columns?: Array<ColumnDef<TData, unknown>>): TData[];
33
+ /**
34
+ * Client-side quick search: keeps rows where any cell value contains the
35
+ * query (case-insensitive over the stringified value, mirroring
36
+ * `dataTableFilterFn`). Returns `data` unchanged when the query is blank
37
+ * (no re-allocation).
38
+ *
39
+ * With `columns`, the search covers the cell values the columns resolve —
40
+ * searching raw row values instead would also match fields that never
41
+ * render (ids, nested objects). Without them it falls back to every
42
+ * top-level row value.
43
+ */
44
+ export declare function applySearch<TData extends DataTableData>(data: TData[], search: string, columns?: Array<ColumnDef<TData, unknown>>): TData[];
45
+ /**
46
+ * Operator-based filter function backing every filterable column.
47
+ * Comparisons are case-insensitive over the stringified cell value, so it
48
+ * works for the unknown-shape records the table is built around. Filters
49
+ * without a usable value match every row.
50
+ */
51
+ export declare function dataTableFilterFn<TData>(row: Row<TData>, columnId: string, filterValue: unknown): boolean;
@@ -0,0 +1 @@
1
+ "use strict";function d(e){return e.id?e.id:"accessorKey"in e&&e.accessorKey!==void 0?String(e.accessorKey).replace(/\./g,"_"):typeof e.header=="string"?e.header:void 0}function c(e){const n={};for(const s of e){if("columns"in s&&Array.isArray(s.columns)){Object.assign(n,c(s.columns));continue}const t=d(s);if(t!==void 0){if("accessorFn"in s&&s.accessorFn)n[t]=s.accessorFn;else if("accessorKey"in s&&s.accessorKey!==void 0){const i=String(s.accessorKey).split(".");n[t]=l=>i.reduce((r,a)=>r?.[a],l)}}}return n}const m=[{value:"contains",label:"contains"},{value:"doesNotContain",label:"does not contain"},{value:"equals",label:"equals"},{value:"doesNotEqual",label:"does not equal"},{value:"startsWith",label:"starts with"},{value:"endsWith",label:"ends with"},{value:"isEmpty",label:"is empty"},{value:"isNotEmpty",label:"is not empty"},{value:"isAnyOf",label:"is any of"}];function f(e){return e!=="isEmpty"&&e!=="isNotEmpty"}function y(e){return e==="contains"||e==="isAnyOf"}const g={rows:[],logicOperator:"and"};function p(e){return f(e.operator)?Array.isArray(e.value)?y(e.operator)&&e.value.some(n=>n.trim()!==""):e.operator==="isAnyOf"?!1:typeof e.value=="string"&&e.value.trim()!=="":!0}function h(e,n,s){const t=n.rows.filter(p);if(t.length===0)return e;const i=s?c(s):{};return e.filter((l,r)=>{const a={getValue:u=>i[u]?i[u](l,r):l[u]},o=u=>v(a,u.columnId,{operator:u.operator,value:u.value});return n.logicOperator==="and"?t.every(o):t.some(o)})}function b(e,n,s){const t=n.trim().toLowerCase();if(t==="")return e;const i=r=>r!=null&&r!==""&&String(r).toLowerCase().includes(t),l=s?Object.values(c(s)):[];return l.length>0?e.filter((r,a)=>l.some(o=>i(o(r,a)))):e.filter(r=>Object.values(r).some(i))}function v(e,n,s){const t=s;if(!t)return!0;const i=e.getValue(n),l=i==null||i==="",r=l?"":String(i).toLowerCase();switch(t.operator){case"isEmpty":return l;case"isNotEmpty":return!l;case"isAnyOf":{const a=Array.isArray(t.value)?t.value:[];return a.length===0||a.some(o=>r===o.trim().toLowerCase())}case"contains":{const a=(Array.isArray(t.value)?t.value:[t.value??""]).map(o=>o.trim().toLowerCase()).filter(o=>o!=="");return a.length===0||a.some(o=>r.includes(o))}default:{const a=typeof t.value=="string"?t.value.trim().toLowerCase():"";if(a==="")return!0;switch(t.operator){case"doesNotContain":return!r.includes(a);case"equals":return r===a;case"doesNotEqual":return r!==a;case"startsWith":return r.startsWith(a);case"endsWith":return r.endsWith(a);default:return!0}}}}export{g as EMPTY_FILTERS,h as applyFilters,b as applySearch,v as dataTableFilterFn,m as dataTableFilterOperators,y as filterOperatorIsMultiValue,f as filterOperatorRequiresValue,p as isFilterRowActive};
@@ -0,0 +1,43 @@
1
+ import { MutableRefObject } from 'react';
2
+ import { OnChangeFn } from '@tanstack/react-table';
3
+ /**
4
+ * TanStack-style table state that is controlled when the consumer passes
5
+ * the state prop and internal otherwise; the change handler resolves
6
+ * updater functions and reports the next value either way.
7
+ */
8
+ export declare function useControllableState<T>(initialValue: T, controlledValue: T | undefined, onChange?: (next: T) => void): [T, OnChangeFn<T>];
9
+ /**
10
+ * Grouped columns produce multiple header rows. MUI's stickyHeader pins
11
+ * every header cell at top: 0, so rows below the first must be offset by
12
+ * the measured height of the rows above to stack instead of overlapping.
13
+ *
14
+ * `columnsKey` (the resolved column defs) remounts the header rows, so
15
+ * the observer must re-attach to the new nodes whenever it changes.
16
+ */
17
+ export declare function useHeaderRowTops(headerRowCount: number, columnsKey: unknown): {
18
+ headerRowRefs: MutableRefObject<Array<HTMLTableRowElement | null>>;
19
+ headerRowTops: number[];
20
+ };
21
+ /**
22
+ * Measured total height of the sticky header rows — the bidirectional
23
+ * loading-newer indicator sticks right below them, and their height
24
+ * varies with grouped headers and wrapping labels. Only measured while
25
+ * `enabled` (bidirectional scroll is active); 0 otherwise.
26
+ */
27
+ export declare function useStickyHeaderHeight(enabled: boolean, headerRowRefs: MutableRefObject<Array<HTMLTableRowElement | null>>, headerRowCount: number, columnsKey: unknown): number;
28
+ /** Sticky offset maps for pinned columns (column id -> px). */
29
+ export type DataTablePinnedOffsets = {
30
+ left: Record<string, number>;
31
+ right: Record<string, number>;
32
+ };
33
+ /**
34
+ * Sticky offsets for pinned columns, measured from the rendered leaf
35
+ * header cells — TanStack's own sizes assume the defs' sizes, which the
36
+ * browser's table layout does not honor. Also returns the header cell
37
+ * refs: they double as the width source for freezing column widths when a
38
+ * resize drag starts.
39
+ */
40
+ export declare function usePinnedOffsets(leftPinnedIds: string[], rightPinnedIds: string[], columnsKey: unknown): {
41
+ headerCellRefs: MutableRefObject<Record<string, HTMLTableCellElement | null>>;
42
+ pinnedOffsets: DataTablePinnedOffsets;
43
+ };
@@ -0,0 +1 @@
1
+ "use strict";import{useState as b,useRef as O,useLayoutEffect as y}from"react";function j(r,s,t){const[o,a]=b(r),i=s??o;return[i,n=>{const e=typeof n=="function"?n(i):n;s===void 0&&a(e),t?.(e)}]}function k(r,s){const t=O([]),[o,a]=b([]);return y(()=>{if(r<=1){a(e=>e.length===0?e:[]);return}const i=()=>{var e;const c=[];let f=0;for(let u=0;u<r;u+=1)c.push(f),f+=((e=t.current[u])==null?void 0:e.offsetHeight)??0;a(u=>u.length===c.length&&u.every((v,l)=>v===c[l])?u:c)};if(i(),typeof ResizeObserver>"u")return;const n=new ResizeObserver(i);return t.current.slice(0,r).forEach(e=>e&&n.observe(e)),()=>n.disconnect()},[r,s]),{headerRowRefs:t,headerRowTops:o}}function z(r,s,t,o){const[a,i]=b(0);return y(()=>{if(!r)return;const n=()=>{const c=s.current.slice(0,t).reduce((f,u)=>f+(u?.offsetHeight??0),0);i(f=>f===c?f:c)};if(n(),typeof ResizeObserver>"u")return;const e=new ResizeObserver(n);return s.current.slice(0,t).forEach(c=>c&&e.observe(c)),()=>e.disconnect()},[r,s,t,o]),a}function w(r,s){const t=Object.keys(r);return t.length===Object.keys(s).length&&t.every(o=>r[o]===s[o])}function H(r,s,t){const o=O({}),[a,i]=b({left:{},right:{}}),n=r.join(","),e=s.join(",");return y(()=>{if(n===""&&e===""){i(l=>Object.keys(l.left).length===0&&Object.keys(l.right).length===0?l:{left:{},right:{}});return}const c=n===""?[]:n.split(","),f=e===""?[]:e.split(","),u=()=>{var l,g;const R={};let d=0;for(const h of c)R[h]=d,d+=((l=o.current[h])==null?void 0:l.getBoundingClientRect().width)??0;const p={};d=0;for(const h of[...f].reverse())p[h]=d,d+=((g=o.current[h])==null?void 0:g.getBoundingClientRect().width)??0;i(h=>w(h.left,R)&&w(h.right,p)?h:{left:R,right:p})};if(u(),typeof ResizeObserver>"u")return;const v=new ResizeObserver(u);return[...c,...f].forEach(l=>{const g=o.current[l];g&&v.observe(g)}),()=>v.disconnect()},[n,e,t]),{headerCellRefs:o,pinnedOffsets:a}}export{j as useControllableState,k as useHeaderRowTops,H as usePinnedOffsets,z as useStickyHeaderHeight};
@@ -0,0 +1 @@
1
+ "use strict";import{useState as Y,useRef as x,useMemo as _,useEffect as Xe}from"react";import{useReactTable as en,getPaginationRowModel as nn,getSortedRowModel as on,getCoreRowModel as tn}from"@tanstack/react-table";import{useVirtualizer as an}from"@tanstack/react-virtual";import{Box as ln,TableContainer as rn,Table as sn}from"@mui/material";import{useBidirectionalScroll as dn}from"../../hooks/useBidirectionalScroll.mjs";import{DataTableProvider as un}from"./DataTable.context.mjs";import{useControllableState as u,useHeaderRowTops as gn,useStickyHeaderHeight as mn,usePinnedOffsets as fn}from"./DataTable.hooks.mjs";import{applySearch as hn,applyFilters as cn,EMPTY_FILTERS as pn}from"./DataTable.filters.mjs";import{inferColumns as bn,applyMetaWidthsToSizes as Cn,getColumnMeta as q,measureRowGroup as Rn}from"./DataTable.utils.mjs";import{DataTableBody as wn}from"./DataTableBody.mjs";import{DataTableFooter as Sn}from"./DataTableFooter.mjs";import{DataTableHead as Pn}from"./DataTableHead.mjs";import{DataTablePanels as vn}from"./DataTablePanels.mjs";import{DataTableToolbar as yn}from"./DataTableToolbar.mjs";import{jsx as r,jsxs as A}from"react/jsx-runtime";const xn=25,Ln=[10,25,50,100],zn=53,Mn={},Tn={left:[],right:[]},J=()=>{};function Hn({data:a,columns:L,getRowId:z,renderRow:U,initialSorting:Z=[],sorting:Q,onSortingChange:X,manualSorting:M=!1,initialPageSize:ee=xn,pageSizeOptions:ne=Ln,pagination:oe,onPaginationChange:te,manualPagination:g=!1,rowCount:c,disableSorting:p=!1,disablePagination:b=!1,bidirectionalScroll:o,enableColumnResizing:s=!1,enableColumnMenu:ie=!1,enableColumnPinning:m=!1,showToolbar:ae=!1,enableExport:le=!1,exportFilename:re="data",initialFilters:se=pn,filters:de,onFiltersChange:ue,manualFiltering:T=!1,initialSearch:ge="",search:me,onSearchChange:fe,initialColumnVisibility:H={},columnVisibility:he,onColumnVisibilityChange:ce,initialColumnPinning:pe=Tn,columnPinning:be,onColumnPinningChange:Ce,footerLeft:Re,estimateRowHeight:we=zn,minWidth:Se=650,maxHeight:Pe=800,tableLayout:C="auto",icons:ve=Mn,emptyMessage:ye="No data to display.",isLoading:xe=!1,renderLoading:Le}){const[ze,Me]=u(Z,Q,X),[Te,He]=u({pageIndex:0,pageSize:ee},oe,te),[R,Oe]=u(se,de,ue),[w,Ve]=u(ge,me,fe),[Fe,Ee]=u(H,he,ce),[Ie,Be]=u(pe,be,Ce),[S,De]=Y({}),O=s&&Object.keys(S).length>0,[Ne,f]=Y(null),ke=()=>{f(null)},V=x(null),F=x(null),E=(e,n)=>{if(n){const d=n.getBoundingClientRect();return{anchorPosition:{top:d.bottom,left:d.right},transformHorizontal:"right"}}const t=e.getBoundingClientRect();return{anchorPosition:{top:t.bottom,left:t.left},transformHorizontal:"left"}},$e=(e,n)=>{f({type:"filter",columnId:e,...E(n,V.current)})},We=e=>{f({type:"manageColumns",...E(e,F.current)})},P=x(null),l=_(()=>{const e=L??bn(a);return s?Cn(e):e},[L,a,s]),je=_(()=>T?a:hn(cn(a,R,l),w,l),[a,R,w,T,l]),i=en({data:je,columns:l,state:{...p?{}:{sorting:ze},...b?{}:{pagination:Te},...m?{columnPinning:Ie}:{},columnVisibility:Fe,columnSizing:S},initialState:{columnVisibility:H},onSortingChange:Me,onPaginationChange:He,onColumnVisibilityChange:Ee,onColumnPinningChange:Be,onColumnSizingChange:De,enableColumnPinning:m,columnResizeMode:"onChange",enableColumnResizing:s,getCoreRowModel:tn(),defaultColumn:{enableSorting:!1},enableSorting:!p,manualSorting:M,...p||M?{}:{getSortedRowModel:on()},manualPagination:g,...g&&c!==void 0?{rowCount:c}:{},getRowCanExpand:()=>!0,...b||g?{}:{getPaginationRowModel:nn()},...z?{getRowId:z}:{}}),v=i.getRowModel().rows,Ge=g?c??a.length:i.getPrePaginationRowModel().rows.length,Ke=i.getVisibleLeafColumns().length||1,Ye=s&&i.getVisibleLeafColumns().some(e=>{var n;return typeof((n=q(e.columnDef.meta))==null?void 0:n.width)=="number"}),_e=O||Ye,y=m?i.getLeftVisibleLeafColumns().map(e=>e.id):[],I=m?i.getRightVisibleLeafColumns().map(e=>e.id):[],B=i.getHeaderGroups().length,{headerRowRefs:D,headerRowTops:qe}=gn(B,l),N=o!==void 0,Ae=mn(N,D,B,l),{headerCellRefs:k,pinnedOffsets:$}=fn(y,I,l),Je=(e,n)=>{var t;for(const d of i.getVisibleLeafColumns())if(S[d.id]===void 0){const K=(t=k.current[d.id])==null?void 0:t.getBoundingClientRect().width;K&&(d.columnDef.size=Math.round(K))}e.getResizeHandler()(n)},W=(e,n)=>e==="left"?y[y.length-1]===n:I[0]===n,j=(e,n)=>{if(e==="left")return{left:$.left[n]??0};if(e==="right")return{right:$.right[n]??0}},G=C==="fixed"?{overflow:"hidden",textOverflow:"ellipsis"}:void 0,Ue=(e,n)=>e?t=>({...G,position:"sticky",zIndex:1,bgcolor:"background.paper",".MuiTableRow-hover:hover > &":{backgroundImage:`linear-gradient(${t.palette.action.hover}, ${t.palette.action.hover})`},...W(e,n)?{boxShadow:`inset ${e==="left"?-1:1}px 0 0 ${t.palette.divider}`}:{}}):G,Ze=e=>{var n;const t=e.column.getIsPinned();return{align:(n=q(e.column.columnDef.meta))==null?void 0:n.align,style:j(t,e.column.id),sx:Ue(t,e.column.id)}},h=an({count:v.length,getScrollElement:()=>P.current,estimateSize:()=>we,overscan:5,measureElement:Rn});dn({enabled:N,scrollContainerRef:P,virtualizer:h,rowCount:v.length,hasNewer:o?.hasNewer,hasOlder:o?.hasOlder,isLoadingNewer:o?.isLoadingNewer,isLoadingOlder:o?.isLoadingOlder,onLoadNewer:o?.onLoadNewer??J,onLoadOlder:o?.onLoadOlder??J,resetKey:o?.resetKey});const{pageIndex:Qe}=i.getState().pagination;return Xe(()=>{h.scrollToOffset(0)},[Qe,h]),r(un,{value:{table:i,data:a,rows:v,totalRowCount:Ge,columnCount:Ke,icons:ve,isLoading:xe,emptyMessage:ye,tableLayout:C,enableColumnResizing:s,enableColumnMenu:ie,enableExport:le,exportFilename:re,disablePagination:b,pageSizeOptions:ne,footerLeft:Re,bidirectionalScroll:o,renderLoading:Le,renderRow:U,filters:R,onFiltersChange:Oe,search:w,onSearchChange:Ve,columnPanel:Ne,setColumnPanel:f,closeColumnPanel:ke,openFilterPanel:$e,openManageColumnsPanel:We,toolbarFilterButtonRef:V,toolbarManageColumnsButtonRef:F,headerRowRefs:D,headerCellRefs:k,headerRowTops:qe,headerHeight:Ae,isPinnedEdge:W,getPinnedOffsetStyle:j,getCellProps:Ze,hasResizedColumns:O,startColumnResize:Je,virtualizer:h},children:A(ln,{sx:{width:"100%"},children:[ae&&r(yn,{}),r(rn,{ref:P,sx:{maxHeight:Pe,width:0,minWidth:"100%"},children:A(sn,{stickyHeader:!0,sx:{minWidth:Se,tableLayout:C},style:_e?{width:`max(${i.getTotalSize()}px, 100%)`}:void 0,"aria-label":"data table",children:[r(Pn,{}),r(wn,{})]})}),r(vn,{}),r(Sn,{})]})})}export{Hn as DataTable};