@hexclave/dashboard-ui-components 1.0.82 → 1.0.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/data-grid/data-grid.js +10 -1
- package/dist/components/data-grid/data-grid.js.map +1 -1
- package/dist/components/data-grid/data-grid.test.js +7 -2
- package/dist/components/data-grid/data-grid.test.js.map +1 -1
- package/dist/dashboard-ui-components.global.js +8 -2
- package/dist/dashboard-ui-components.global.js.map +2 -2
- package/dist/esm/components/data-grid/data-grid.js +10 -1
- package/dist/esm/components/data-grid/data-grid.js.map +1 -1
- package/dist/esm/components/data-grid/data-grid.test.js +7 -2
- package/dist/esm/components/data-grid/data-grid.test.js.map +1 -1
- package/package.json +3 -3
- package/src/components/data-grid/data-grid.test.tsx +9 -1
- package/src/components/data-grid/data-grid.tsx +7 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-grid.test.js","names":[],"sources":["../../../../src/components/data-grid/data-grid.test.tsx"],"sourcesContent":["// @vitest-environment jsdom\n\nimport { act, cleanup, fireEvent, render, waitFor } from \"@testing-library/react\";\nimport { useMemo, useState } from \"react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport {\n createDefaultDataGridState,\n DATA_GRID_DEFAULT_STRINGS,\n DataGrid,\n DataGridToolbar,\n isDataGridInteractiveRowClickTarget,\n useDataSource,\n type DataGridColumnDef,\n type DataGridDataSource,\n type DataGridProps,\n} from \"./index\";\n\ntype Row = {\n id: string,\n name: string,\n};\n\nconst columns: DataGridColumnDef<Row>[] = [\n {\n id: \"name\",\n header: \"Name\",\n accessor: (row) => row.name,\n width: 160,\n minWidth: 80,\n sortable: true,\n type: \"string\",\n },\n];\n\nconst wideColumns: DataGridColumnDef<Row>[] = [\n {\n id: \"name\",\n header: \"Name\",\n accessor: (row) => row.name,\n width: 320,\n minWidth: 80,\n type: \"string\",\n },\n {\n id: \"email\",\n header: \"Email\",\n accessor: (row) => `${row.name.toLowerCase().replaceAll(\" \", \".\")}@example.com`,\n width: 420,\n minWidth: 80,\n type: \"string\",\n },\n];\n\ndescribe(\"DataGridToolbar action divider\", () => {\n const ctx = {\n state: createDefaultDataGridState(columns),\n onChange: vi.fn(),\n columns,\n visibleColumns: columns,\n totalRowCount: 1,\n selectedRowCount: 0,\n strings: DATA_GRID_DEFAULT_STRINGS,\n exportCsv: vi.fn(),\n };\n\n afterEach(cleanup);\n\n it(\"does not render a divider for an empty React node\", () => {\n const { container } = render(\n <DataGridToolbar ctx={ctx} extraActions={false} />,\n );\n\n expect(container.querySelector(\".mx-0\\\\.5.h-4.w-px\")).toBeNull();\n });\n\n it(\"renders the divider when an action is visible\", () => {\n const { container, getByRole } = render(\n <DataGridToolbar\n ctx={ctx}\n extraActions={<button type=\"button\">Refresh</button>}\n />,\n );\n\n expect(getByRole(\"button\", { name: \"Refresh\" })).not.toBeNull();\n expect(container.querySelector(\".mx-0\\\\.5.h-4.w-px\")).not.toBeNull();\n });\n});\n\ntype ObserverRecord = {\n options?: IntersectionObserverInit,\n};\n\nlet intersectionObserverRecords: ObserverRecord[] = [];\nlet intersectionObserverInstances: MockIntersectionObserver[] = [];\n\nclass MockIntersectionObserver implements IntersectionObserver {\n readonly root: Element | Document | null;\n readonly rootMargin: string;\n readonly scrollMargin: string;\n readonly thresholds: ReadonlyArray<number>;\n private readonly callback: IntersectionObserverCallback;\n private readonly record: ObserverRecord;\n\n constructor(\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n ) {\n this.callback = callback;\n this.root = options?.root ?? null;\n this.rootMargin = options?.rootMargin ?? \"\";\n this.scrollMargin = \"\";\n this.thresholds = Array.isArray(options?.threshold)\n ? options.threshold\n : [options?.threshold ?? 0];\n this.record = { options };\n intersectionObserverRecords.push(this.record);\n intersectionObserverInstances.push(this);\n }\n\n disconnect() {}\n observe() {}\n takeRecords(): IntersectionObserverEntry[] {\n return [];\n }\n unobserve() {}\n\n trigger(entry: Partial<IntersectionObserverEntry> = {}) {\n this.callback(\n [\n {\n boundingClientRect: {} as DOMRectReadOnly,\n intersectionRatio: 1,\n intersectionRect: {} as DOMRectReadOnly,\n isIntersecting: true,\n rootBounds: null,\n target: document.createElement(\"div\"),\n time: 0,\n ...entry,\n },\n ],\n this,\n );\n }\n}\n\nclass MockResizeObserver implements ResizeObserver {\n private readonly callback: ResizeObserverCallback;\n\n constructor(callback: ResizeObserverCallback) {\n this.callback = callback;\n }\n\n disconnect() {}\n observe(target: Element) {\n const el = target instanceof HTMLElement ? target : null;\n const parentWidth = el?.parentElement instanceof HTMLElement ? el.parentElement.clientWidth : 0;\n const width = (el?.clientWidth ?? 0) > 0 ? (el?.clientWidth ?? 320) : parentWidth > 0 ? parentWidth : 320;\n const height = (el?.clientHeight ?? 0) > 0 ? (el?.clientHeight ?? 400) : 400;\n this.callback(\n [\n {\n target,\n contentRect: {\n x: 0,\n y: 0,\n width,\n height,\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n toJSON() {\n return this;\n },\n } as DOMRectReadOnly,\n borderBoxSize: [],\n contentBoxSize: [],\n devicePixelContentBoxSize: [],\n },\n ],\n this,\n );\n }\n unobserve() {}\n}\n\nfunction DataGridHarness(props: { fillHeight?: boolean }) {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n\n return (\n <div style={{ height: 400 }}>\n <DataGrid<Row>\n columns={columns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n paginationMode=\"infinite\"\n hasMore\n fillHeight={props.fillHeight}\n />\n </div>\n );\n}\n\nfunction PaginatedDataGridHarness() {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n\n return (\n <div style={{ height: 400 }}>\n <DataGrid<Row>\n columns={columns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n paginationMode=\"paginated\"\n fillHeight={false}\n />\n </div>\n );\n}\n\nfunction InteractiveDataGridHarness(props: {\n onSortChange?: DataGridProps<Row>[\"onSortChange\"],\n onSelectionChange?: DataGridProps<Row>[\"onSelectionChange\"],\n}) {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n\n return (\n <DataGrid<Row>\n columns={columns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n selectionMode=\"multiple\"\n onSortChange={props.onSortChange}\n onSelectionChange={props.onSelectionChange}\n />\n );\n}\n\nfunction WideDataGridHarness(props: {\n horizontalScrollbarPosition?: \"top\" | \"bottom\",\n} = {}) {\n const [state, setState] = useState(() => createDefaultDataGridState(wideColumns));\n\n return (\n <div style={{ width: 320 }}>\n <DataGrid<Row>\n columns={wideColumns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n horizontalScrollbarPosition={props.horizontalScrollbarPosition}\n />\n </div>\n );\n}\n\ndescribe(\"DataGrid infinite scroll observer\", () => {\n beforeEach(() => {\n intersectionObserverRecords = [];\n\n vi.stubGlobal(\"IntersectionObserver\", MockIntersectionObserver);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"observes against the grid body when the grid owns vertical scrolling\", async () => {\n const { container } = render(<DataGridHarness fillHeight />);\n\n await waitFor(() => {\n expect(intersectionObserverRecords.length).toBeGreaterThan(0);\n });\n\n const grid = container.querySelector('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n const scrollContainer = grid?.children.item(1);\n\n expect(intersectionObserverRecords.at(-1)?.options?.root).toBe(scrollContainer);\n });\n\n // Regression: an infinite grid left unbounded (`fillHeight={false}`, no `maxHeight`) used to\n // grow its scroll container to fit every loaded row, which defeats virtualization (the\n // virtualizer measures the container as fully visible and mounts every row) and OOMs the tab on\n // large datasets. Such grids now fall back to a default `maxHeight`, so the grid owns its own\n // bounded scroll container and observes against it rather than the viewport.\n it(\"bounds an unbounded infinite grid and observes against its own scroll container\", async () => {\n const { container } = render(<DataGridHarness fillHeight={false} />);\n\n await waitFor(() => {\n expect(intersectionObserverRecords.length).toBeGreaterThan(0);\n });\n\n const grid = container.querySelector('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n const scrollContainer = grid?.children.item(1);\n\n expect(intersectionObserverRecords.at(-1)?.options?.root).toBe(scrollContainer);\n });\n\n it(\"applies a default maxHeight to an otherwise-unbounded infinite grid\", () => {\n const { container } = render(<DataGridHarness fillHeight={false} />);\n\n const grid = container.querySelector<HTMLElement>('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n expect(grid?.style.maxHeight).toBe(\"calc(100dvh - 16rem)\");\n });\n\n it(\"does not force a maxHeight onto a paginated grid\", () => {\n const { container } = render(<PaginatedDataGridHarness />);\n\n const grid = container.querySelector<HTMLElement>('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n expect(grid?.style.maxHeight).toBe(\"\");\n });\n});\n\n// Drives a real `useDataSource` infinite-scroll grid whose data source\n// always reports `hasMore: true`, mirroring a project with a long\n// transaction / customer history (e.g. the transactions table and customers\n// tab). Used to prove the sentinel doesn't thrash its IntersectionObserver.\nfunction InfiniteScrollLoadMoreHarness({ onFetch }: { onFetch: () => void }) {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n const dataSource = useMemo<DataGridDataSource<Row>>(\n () => {\n let page = 0;\n return async function* () {\n onFetch();\n const current = page++;\n yield {\n rows: [{ id: `row-${current}`, name: `Row ${current}` }],\n hasMore: true,\n nextCursor: `cursor-${current}`,\n };\n };\n },\n [onFetch],\n );\n\n const gridData = useDataSource<Row>({\n dataSource,\n columns,\n getRowId: (row) => row.id,\n sorting: state.sorting,\n quickSearch: state.quickSearch,\n pagination: state.pagination,\n paginationMode: \"infinite\",\n });\n\n return (\n <div style={{ height: 400 }}>\n <DataGrid<Row>\n columns={columns}\n rows={gridData.rows}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n paginationMode=\"infinite\"\n hasMore={gridData.hasMore}\n isLoading={gridData.isLoading}\n isLoadingMore={gridData.isLoadingMore}\n onLoadMore={gridData.loadMore}\n />\n </div>\n );\n}\n\ndescribe(\"DataGrid infinite scroll observer stability\", () => {\n beforeEach(() => {\n intersectionObserverRecords = [];\n intersectionObserverInstances = [];\n\n vi.stubGlobal(\"IntersectionObserver\", MockIntersectionObserver);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n // Regression: the sentinel used to re-create its IntersectionObserver every\n // time the `onLoadMore` callback changed identity (which happens on every\n // `isLoadingMore` / `hasMore` toggle). A freshly-created observer re-reports\n // the sentinel's current intersection state, so a sentinel that stays in\n // view fires `onLoadMore` again after every page — auto-loading the entire\n // history back-to-back and OOM-crashing the tab (\"Aw snap\") on large\n // datasets. The observer must stay stable across load-more cycles.\n it(\"does not re-create the observer on load-more cycles\", async () => {\n const onFetch = vi.fn();\n render(<InfiniteScrollLoadMoreHarness onFetch={onFetch} />);\n\n // Initial page load, after which the sentinel (and its observer) mounts.\n await waitFor(() => expect(onFetch).toHaveBeenCalledTimes(1));\n await waitFor(() => expect(intersectionObserverInstances.length).toBeGreaterThan(0));\n\n const observersBeforeLoadMore = intersectionObserverInstances.length;\n\n // Simulate the sentinel scrolling into view exactly once.\n await act(async () => {\n intersectionObserverInstances.at(-1)?.trigger();\n await Promise.resolve();\n });\n\n await waitFor(() => expect(onFetch).toHaveBeenCalledTimes(2));\n\n // A single scroll-in must trigger a single fetch, without spawning new\n // observers — otherwise each new observer would re-fire and runaway.\n expect(intersectionObserverInstances.length).toBe(observersBeforeLoadMore);\n });\n});\n\ndescribe(\"DataGrid controlled callbacks\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"fires onSortChange from the current controlled sort state\", () => {\n const onSortChange = vi.fn();\n const { getByRole } = render(<InteractiveDataGridHarness onSortChange={onSortChange} />);\n\n fireEvent.click(getByRole(\"columnheader\", { name: /name/i }));\n\n expect(onSortChange).toHaveBeenCalledTimes(1);\n expect(onSortChange).toHaveBeenCalledWith([{ columnId: \"name\", direction: \"asc\" }]);\n });\n\n it(\"fires onSelectionChange when selecting all rows\", () => {\n const onSelectionChange = vi.fn();\n const { getByRole } = render(<InteractiveDataGridHarness onSelectionChange={onSelectionChange} />);\n\n fireEvent.click(getByRole(\"checkbox\", { name: /select all rows/i }));\n\n expect(onSelectionChange).toHaveBeenCalledTimes(1);\n const [selectedIds, selectedRows] = onSelectionChange.mock.calls[0];\n expect([...selectedIds]).toEqual([\"row-1\"]);\n expect(selectedRows).toEqual([{ id: \"row-1\", name: \"Row 1\" }]);\n });\n\n it(\"identifies nested interactive controls as row-click blockers\", () => {\n const cell = document.createElement(\"div\");\n const button = document.createElement(\"button\");\n const label = document.createElement(\"span\");\n label.textContent = \"Open menu\";\n button.append(label);\n cell.append(button);\n\n expect(isDataGridInteractiveRowClickTarget(label.firstChild)).toBe(true);\n expect(isDataGridInteractiveRowClickTarget(cell)).toBe(false);\n });\n});\n\ndescribe(\"DataGrid horizontal scrolling\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n Object.defineProperty(HTMLElement.prototype, \"clientWidth\", {\n configurable: true,\n get() {\n return 320;\n },\n });\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"sizes the sticky clipping layer to the full row width\", () => {\n const { container } = render(<WideDataGridHarness />);\n\n const rowsClip = container.querySelector(\"[data-data-grid-rows-clip]\");\n\n expect(rowsClip).toBeInstanceOf(HTMLElement);\n expect((rowsClip as HTMLElement).style.minWidth).toBe(\"740px\");\n });\n\n it(\"lets the columns popover escape the sticky toolbar bounds\", () => {\n const { container, getByTitle } = render(<WideDataGridHarness />);\n\n fireEvent.click(getByTitle(\"Columns\"));\n\n const stickyChrome = container.querySelector('[role=\"grid\"]')?.firstElementChild;\n expect(stickyChrome).toBeInstanceOf(HTMLElement);\n expect((stickyChrome as HTMLElement).className).toContain(\"overflow-visible\");\n expect(container.textContent).toContain(\"Email\");\n });\n\n it(\"puts the horizontal scrollbar under the column headers when position is top\", () => {\n const { container } = render(<WideDataGridHarness horizontalScrollbarPosition=\"top\" />);\n\n const stickyChrome = container.querySelector('[role=\"grid\"]')?.firstElementChild;\n expect(stickyChrome).toBeInstanceOf(HTMLElement);\n const headerScroll = stickyChrome?.querySelector(\".overflow-x-auto\");\n expect(headerScroll).toBeInstanceOf(HTMLElement);\n\n const bodyScroll = container.querySelector('[role=\"grid\"]')?.children.item(1);\n expect(bodyScroll).toBeInstanceOf(HTMLElement);\n expect((bodyScroll as HTMLElement).className).toContain(\"overflow-x-hidden\");\n expect((bodyScroll as HTMLElement).className).toContain(\"overflow-y-auto\");\n\n Object.defineProperty(headerScroll as HTMLElement, \"scrollLeft\", {\n configurable: true,\n writable: true,\n value: 0,\n });\n Object.defineProperty(bodyScroll as HTMLElement, \"scrollLeft\", {\n configurable: true,\n writable: true,\n value: 0,\n });\n\n (headerScroll as HTMLElement).scrollLeft = 120;\n fireEvent.scroll(headerScroll as HTMLElement);\n expect((bodyScroll as HTMLElement).scrollLeft).toBe(120);\n });\n});\n\ndescribe(\"DataGrid loading skeleton\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"shows a full-width shimmer when loading before any columns are known\", () => {\n function SchemaPendingHarness() {\n const [state, setState] = useState(() => createDefaultDataGridState([]));\n return (\n <DataGrid<Row>\n columns={[]}\n rows={[]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n isLoading\n />\n );\n }\n\n const { container } = render(<SchemaPendingHarness />);\n\n const skeleton = container.querySelector(\"[data-data-grid-schema-pending-skeleton]\");\n expect(skeleton).toBeInstanceOf(HTMLElement);\n // Five placeholder columns × 10 rows → visible shimmer cells, not an empty pane.\n expect(skeleton?.querySelectorAll(\"[role='row']\").length).toBe(10);\n });\n\n it(\"uses per-column skeleton rows once the schema is known\", () => {\n function KnownSchemaHarness() {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n return (\n <DataGrid<Row>\n columns={columns}\n rows={[]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n isLoading\n />\n );\n }\n\n const { container } = render(<KnownSchemaHarness />);\n\n expect(container.querySelector(\"[data-data-grid-schema-pending-skeleton]\")).toBeNull();\n const rowsClip = container.querySelector(\"[data-data-grid-rows-clip]\");\n expect(rowsClip?.querySelectorAll(\"[role='row']\").length).toBe(8);\n });\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data-grid.test.js","names":[],"sources":["../../../../src/components/data-grid/data-grid.test.tsx"],"sourcesContent":["// @vitest-environment jsdom\n\nimport { act, cleanup, fireEvent, render, waitFor } from \"@testing-library/react\";\nimport { useMemo, useState } from \"react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport {\n createDefaultDataGridState,\n DATA_GRID_DEFAULT_STRINGS,\n DataGrid,\n DataGridToolbar,\n isDataGridInteractiveRowClickTarget,\n useDataSource,\n type DataGridColumnDef,\n type DataGridDataSource,\n type DataGridProps,\n} from \"./index\";\n\ntype Row = {\n id: string,\n name: string,\n};\n\nconst columns: DataGridColumnDef<Row>[] = [\n {\n id: \"name\",\n header: \"Name\",\n accessor: (row) => row.name,\n width: 160,\n minWidth: 80,\n sortable: true,\n type: \"string\",\n },\n];\n\nconst wideColumns: DataGridColumnDef<Row>[] = [\n {\n id: \"name\",\n header: \"Name\",\n accessor: (row) => row.name,\n width: 320,\n minWidth: 80,\n type: \"string\",\n },\n {\n id: \"email\",\n header: \"Email\",\n accessor: (row) => `${row.name.toLowerCase().replaceAll(\" \", \".\")}@example.com`,\n width: 420,\n minWidth: 80,\n type: \"string\",\n },\n];\n\ndescribe(\"DataGridToolbar action divider\", () => {\n const ctx = {\n state: createDefaultDataGridState(columns),\n onChange: vi.fn(),\n columns,\n visibleColumns: columns,\n totalRowCount: 1,\n selectedRowCount: 0,\n strings: DATA_GRID_DEFAULT_STRINGS,\n exportCsv: vi.fn(),\n };\n\n afterEach(cleanup);\n\n it(\"does not render a divider for an empty React node\", () => {\n const { container } = render(\n <DataGridToolbar ctx={ctx} extraActions={false} />,\n );\n\n expect(container.querySelector(\".mx-0\\\\.5.h-4.w-px\")).toBeNull();\n });\n\n it(\"renders the divider when an action is visible\", () => {\n const { container, getByRole } = render(\n <DataGridToolbar\n ctx={ctx}\n extraActions={<button type=\"button\">Refresh</button>}\n />,\n );\n\n expect(getByRole(\"button\", { name: \"Refresh\" })).not.toBeNull();\n expect(container.querySelector(\".mx-0\\\\.5.h-4.w-px\")).not.toBeNull();\n });\n});\n\ntype ObserverRecord = {\n options?: IntersectionObserverInit,\n};\n\nlet intersectionObserverRecords: ObserverRecord[] = [];\nlet intersectionObserverInstances: MockIntersectionObserver[] = [];\n\nclass MockIntersectionObserver implements IntersectionObserver {\n readonly root: Element | Document | null;\n readonly rootMargin: string;\n readonly scrollMargin: string;\n readonly thresholds: ReadonlyArray<number>;\n private readonly callback: IntersectionObserverCallback;\n private readonly record: ObserverRecord;\n\n constructor(\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n ) {\n this.callback = callback;\n this.root = options?.root ?? null;\n this.rootMargin = options?.rootMargin ?? \"\";\n this.scrollMargin = \"\";\n this.thresholds = Array.isArray(options?.threshold)\n ? options.threshold\n : [options?.threshold ?? 0];\n this.record = { options };\n intersectionObserverRecords.push(this.record);\n intersectionObserverInstances.push(this);\n }\n\n disconnect() {}\n observe() {}\n takeRecords(): IntersectionObserverEntry[] {\n return [];\n }\n unobserve() {}\n\n trigger(entry: Partial<IntersectionObserverEntry> = {}) {\n this.callback(\n [\n {\n boundingClientRect: {} as DOMRectReadOnly,\n intersectionRatio: 1,\n intersectionRect: {} as DOMRectReadOnly,\n isIntersecting: true,\n rootBounds: null,\n target: document.createElement(\"div\"),\n time: 0,\n ...entry,\n },\n ],\n this,\n );\n }\n}\n\nclass MockResizeObserver implements ResizeObserver {\n private readonly callback: ResizeObserverCallback;\n\n constructor(callback: ResizeObserverCallback) {\n this.callback = callback;\n }\n\n disconnect() {}\n observe(target: Element) {\n const el = target instanceof HTMLElement ? target : null;\n const parentWidth = el?.parentElement instanceof HTMLElement ? el.parentElement.clientWidth : 0;\n const width = (el?.clientWidth ?? 0) > 0 ? (el?.clientWidth ?? 320) : parentWidth > 0 ? parentWidth : 320;\n const height = (el?.clientHeight ?? 0) > 0 ? (el?.clientHeight ?? 400) : 400;\n this.callback(\n [\n {\n target,\n contentRect: {\n x: 0,\n y: 0,\n width,\n height,\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n toJSON() {\n return this;\n },\n } as DOMRectReadOnly,\n borderBoxSize: [],\n contentBoxSize: [],\n devicePixelContentBoxSize: [],\n },\n ],\n this,\n );\n }\n unobserve() {}\n}\n\nfunction DataGridHarness(props: { fillHeight?: boolean }) {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n\n return (\n <div style={{ height: 400 }}>\n <DataGrid<Row>\n columns={columns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n paginationMode=\"infinite\"\n hasMore\n fillHeight={props.fillHeight}\n />\n </div>\n );\n}\n\nfunction PaginatedDataGridHarness(props: { stickyTop?: number | string } = {}) {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n\n return (\n <div style={{ height: 400 }}>\n <DataGrid<Row>\n columns={columns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n paginationMode=\"paginated\"\n fillHeight={false}\n stickyTop={props.stickyTop}\n />\n </div>\n );\n}\n\nfunction InteractiveDataGridHarness(props: {\n onSortChange?: DataGridProps<Row>[\"onSortChange\"],\n onSelectionChange?: DataGridProps<Row>[\"onSelectionChange\"],\n}) {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n\n return (\n <DataGrid<Row>\n columns={columns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n selectionMode=\"multiple\"\n onSortChange={props.onSortChange}\n onSelectionChange={props.onSelectionChange}\n />\n );\n}\n\nfunction WideDataGridHarness(props: {\n horizontalScrollbarPosition?: \"top\" | \"bottom\",\n} = {}) {\n const [state, setState] = useState(() => createDefaultDataGridState(wideColumns));\n\n return (\n <div style={{ width: 320 }}>\n <DataGrid<Row>\n columns={wideColumns}\n rows={[{ id: \"row-1\", name: \"Row 1\" }]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n horizontalScrollbarPosition={props.horizontalScrollbarPosition}\n />\n </div>\n );\n}\n\ndescribe(\"DataGrid infinite scroll observer\", () => {\n beforeEach(() => {\n intersectionObserverRecords = [];\n\n vi.stubGlobal(\"IntersectionObserver\", MockIntersectionObserver);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"observes against the grid body when the grid owns vertical scrolling\", async () => {\n const { container } = render(<DataGridHarness fillHeight />);\n\n await waitFor(() => {\n expect(intersectionObserverRecords.length).toBeGreaterThan(0);\n });\n\n const grid = container.querySelector('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n const scrollContainer = grid?.children.item(1);\n\n expect(intersectionObserverRecords.at(-1)?.options?.root).toBe(scrollContainer);\n });\n\n // Regression: an infinite grid left unbounded (`fillHeight={false}`, no `maxHeight`) used to\n // grow its scroll container to fit every loaded row, which defeats virtualization (the\n // virtualizer measures the container as fully visible and mounts every row) and OOMs the tab on\n // large datasets. Such grids now fall back to a default `maxHeight`, so the grid owns its own\n // bounded scroll container and observes against it rather than the viewport.\n it(\"bounds an unbounded infinite grid and observes against its own scroll container\", async () => {\n const { container } = render(<DataGridHarness fillHeight={false} />);\n\n await waitFor(() => {\n expect(intersectionObserverRecords.length).toBeGreaterThan(0);\n });\n\n const grid = container.querySelector('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n const scrollContainer = grid?.children.item(1);\n\n expect(intersectionObserverRecords.at(-1)?.options?.root).toBe(scrollContainer);\n });\n\n it(\"applies a default maxHeight to an otherwise-unbounded infinite grid\", () => {\n const { container } = render(<DataGridHarness fillHeight={false} />);\n\n const grid = container.querySelector<HTMLElement>('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n expect(grid?.style.maxHeight).toBe(\"calc(100dvh - 16rem)\");\n });\n\n it(\"does not force a maxHeight onto a paginated grid\", () => {\n const { container } = render(<PaginatedDataGridHarness />);\n\n const grid = container.querySelector<HTMLElement>('[role=\"grid\"]');\n expect(grid).not.toBeNull();\n expect(grid?.style.maxHeight).toBe(\"\");\n });\n\n it(\"writes an explicit sticky offset to the grid contract\", () => {\n const { container } = render(<PaginatedDataGridHarness stickyTop={0} />);\n\n const grid = container.querySelector<HTMLElement>('[role=\"grid\"]');\n expect(grid?.style.getPropertyValue(\"--data-grid-sticky-top\")).toBe(\"0px\");\n });\n});\n\n// Drives a real `useDataSource` infinite-scroll grid whose data source\n// always reports `hasMore: true`, mirroring a project with a long\n// transaction / customer history (e.g. the transactions table and customers\n// tab). Used to prove the sentinel doesn't thrash its IntersectionObserver.\nfunction InfiniteScrollLoadMoreHarness({ onFetch }: { onFetch: () => void }) {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n const dataSource = useMemo<DataGridDataSource<Row>>(\n () => {\n let page = 0;\n return async function* () {\n onFetch();\n const current = page++;\n yield {\n rows: [{ id: `row-${current}`, name: `Row ${current}` }],\n hasMore: true,\n nextCursor: `cursor-${current}`,\n };\n };\n },\n [onFetch],\n );\n\n const gridData = useDataSource<Row>({\n dataSource,\n columns,\n getRowId: (row) => row.id,\n sorting: state.sorting,\n quickSearch: state.quickSearch,\n pagination: state.pagination,\n paginationMode: \"infinite\",\n });\n\n return (\n <div style={{ height: 400 }}>\n <DataGrid<Row>\n columns={columns}\n rows={gridData.rows}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n paginationMode=\"infinite\"\n hasMore={gridData.hasMore}\n isLoading={gridData.isLoading}\n isLoadingMore={gridData.isLoadingMore}\n onLoadMore={gridData.loadMore}\n />\n </div>\n );\n}\n\ndescribe(\"DataGrid infinite scroll observer stability\", () => {\n beforeEach(() => {\n intersectionObserverRecords = [];\n intersectionObserverInstances = [];\n\n vi.stubGlobal(\"IntersectionObserver\", MockIntersectionObserver);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n // Regression: the sentinel used to re-create its IntersectionObserver every\n // time the `onLoadMore` callback changed identity (which happens on every\n // `isLoadingMore` / `hasMore` toggle). A freshly-created observer re-reports\n // the sentinel's current intersection state, so a sentinel that stays in\n // view fires `onLoadMore` again after every page — auto-loading the entire\n // history back-to-back and OOM-crashing the tab (\"Aw snap\") on large\n // datasets. The observer must stay stable across load-more cycles.\n it(\"does not re-create the observer on load-more cycles\", async () => {\n const onFetch = vi.fn();\n render(<InfiniteScrollLoadMoreHarness onFetch={onFetch} />);\n\n // Initial page load, after which the sentinel (and its observer) mounts.\n await waitFor(() => expect(onFetch).toHaveBeenCalledTimes(1));\n await waitFor(() => expect(intersectionObserverInstances.length).toBeGreaterThan(0));\n\n const observersBeforeLoadMore = intersectionObserverInstances.length;\n\n // Simulate the sentinel scrolling into view exactly once.\n await act(async () => {\n intersectionObserverInstances.at(-1)?.trigger();\n await Promise.resolve();\n });\n\n await waitFor(() => expect(onFetch).toHaveBeenCalledTimes(2));\n\n // A single scroll-in must trigger a single fetch, without spawning new\n // observers — otherwise each new observer would re-fire and runaway.\n expect(intersectionObserverInstances.length).toBe(observersBeforeLoadMore);\n });\n});\n\ndescribe(\"DataGrid controlled callbacks\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"fires onSortChange from the current controlled sort state\", () => {\n const onSortChange = vi.fn();\n const { getByRole } = render(<InteractiveDataGridHarness onSortChange={onSortChange} />);\n\n fireEvent.click(getByRole(\"columnheader\", { name: /name/i }));\n\n expect(onSortChange).toHaveBeenCalledTimes(1);\n expect(onSortChange).toHaveBeenCalledWith([{ columnId: \"name\", direction: \"asc\" }]);\n });\n\n it(\"fires onSelectionChange when selecting all rows\", () => {\n const onSelectionChange = vi.fn();\n const { getByRole } = render(<InteractiveDataGridHarness onSelectionChange={onSelectionChange} />);\n\n fireEvent.click(getByRole(\"checkbox\", { name: /select all rows/i }));\n\n expect(onSelectionChange).toHaveBeenCalledTimes(1);\n const [selectedIds, selectedRows] = onSelectionChange.mock.calls[0];\n expect([...selectedIds]).toEqual([\"row-1\"]);\n expect(selectedRows).toEqual([{ id: \"row-1\", name: \"Row 1\" }]);\n });\n\n it(\"identifies nested interactive controls as row-click blockers\", () => {\n const cell = document.createElement(\"div\");\n const button = document.createElement(\"button\");\n const label = document.createElement(\"span\");\n label.textContent = \"Open menu\";\n button.append(label);\n cell.append(button);\n\n expect(isDataGridInteractiveRowClickTarget(label.firstChild)).toBe(true);\n expect(isDataGridInteractiveRowClickTarget(cell)).toBe(false);\n });\n});\n\ndescribe(\"DataGrid horizontal scrolling\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n Object.defineProperty(HTMLElement.prototype, \"clientWidth\", {\n configurable: true,\n get() {\n return 320;\n },\n });\n vi.spyOn(HTMLElement.prototype, \"getBoundingClientRect\").mockImplementation(\n function getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: 320,\n height: 44,\n top: 0,\n left: 0,\n right: 320,\n bottom: 44,\n toJSON() {\n return this;\n },\n } as DOMRect;\n },\n );\n Object.defineProperty(HTMLElement.prototype, \"clientHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n Object.defineProperty(HTMLElement.prototype, \"scrollHeight\", {\n configurable: true,\n get() {\n return 400;\n },\n });\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"sizes the sticky clipping layer to the full row width\", () => {\n const { container } = render(<WideDataGridHarness />);\n\n const rowsClip = container.querySelector(\"[data-data-grid-rows-clip]\");\n\n expect(rowsClip).toBeInstanceOf(HTMLElement);\n expect((rowsClip as HTMLElement).style.minWidth).toBe(\"740px\");\n });\n\n it(\"lets the columns popover escape the sticky toolbar bounds\", () => {\n const { container, getByTitle } = render(<WideDataGridHarness />);\n\n fireEvent.click(getByTitle(\"Columns\"));\n\n const stickyChrome = container.querySelector('[role=\"grid\"]')?.firstElementChild;\n expect(stickyChrome).toBeInstanceOf(HTMLElement);\n expect((stickyChrome as HTMLElement).className).toContain(\"overflow-visible\");\n expect(container.textContent).toContain(\"Email\");\n });\n\n it(\"puts the horizontal scrollbar under the column headers when position is top\", () => {\n const { container } = render(<WideDataGridHarness horizontalScrollbarPosition=\"top\" />);\n\n const stickyChrome = container.querySelector('[role=\"grid\"]')?.firstElementChild;\n expect(stickyChrome).toBeInstanceOf(HTMLElement);\n const headerScroll = stickyChrome?.querySelector(\".overflow-x-auto\");\n expect(headerScroll).toBeInstanceOf(HTMLElement);\n\n const bodyScroll = container.querySelector('[role=\"grid\"]')?.children.item(1);\n expect(bodyScroll).toBeInstanceOf(HTMLElement);\n expect((bodyScroll as HTMLElement).className).toContain(\"overflow-x-hidden\");\n expect((bodyScroll as HTMLElement).className).toContain(\"overflow-y-auto\");\n\n Object.defineProperty(headerScroll as HTMLElement, \"scrollLeft\", {\n configurable: true,\n writable: true,\n value: 0,\n });\n Object.defineProperty(bodyScroll as HTMLElement, \"scrollLeft\", {\n configurable: true,\n writable: true,\n value: 0,\n });\n\n (headerScroll as HTMLElement).scrollLeft = 120;\n fireEvent.scroll(headerScroll as HTMLElement);\n expect((bodyScroll as HTMLElement).scrollLeft).toBe(120);\n });\n});\n\ndescribe(\"DataGrid loading skeleton\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n });\n\n afterEach(() => {\n cleanup();\n vi.restoreAllMocks();\n vi.unstubAllGlobals();\n });\n\n it(\"shows a full-width shimmer when loading before any columns are known\", () => {\n function SchemaPendingHarness() {\n const [state, setState] = useState(() => createDefaultDataGridState([]));\n return (\n <DataGrid<Row>\n columns={[]}\n rows={[]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n isLoading\n />\n );\n }\n\n const { container } = render(<SchemaPendingHarness />);\n\n const skeleton = container.querySelector(\"[data-data-grid-schema-pending-skeleton]\");\n expect(skeleton).toBeInstanceOf(HTMLElement);\n // Five placeholder columns × 10 rows → visible shimmer cells, not an empty pane.\n expect(skeleton?.querySelectorAll(\"[role='row']\").length).toBe(10);\n });\n\n it(\"uses per-column skeleton rows once the schema is known\", () => {\n function KnownSchemaHarness() {\n const [state, setState] = useState(() => createDefaultDataGridState(columns));\n return (\n <DataGrid<Row>\n columns={columns}\n rows={[]}\n getRowId={(row) => row.id}\n state={state}\n onChange={setState}\n isLoading\n />\n );\n }\n\n const { container } = render(<KnownSchemaHarness />);\n\n expect(container.querySelector(\"[data-data-grid-schema-pending-skeleton]\")).toBeNull();\n const rowsClip = container.querySelector(\"[data-data-grid-rows-clip]\");\n expect(rowsClip?.querySelectorAll(\"[role='row']\").length).toBe(8);\n });\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexclave/dashboard-ui-components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.83",
|
|
4
4
|
"repository": "https://github.com/hexclave/hexclave",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"@tanstack/react-table": "^8.21.3",
|
|
48
48
|
"@tanstack/react-virtual": "^3.13.0",
|
|
49
49
|
"class-variance-authority": "^0.7.0",
|
|
50
|
-
"@hexclave/shared": "1.0.
|
|
51
|
-
"@hexclave/ui": "1.0.
|
|
50
|
+
"@hexclave/shared": "1.0.83",
|
|
51
|
+
"@hexclave/ui": "1.0.83"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/react": "^19.0.0",
|
|
@@ -203,7 +203,7 @@ function DataGridHarness(props: { fillHeight?: boolean }) {
|
|
|
203
203
|
);
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
function PaginatedDataGridHarness() {
|
|
206
|
+
function PaginatedDataGridHarness(props: { stickyTop?: number | string } = {}) {
|
|
207
207
|
const [state, setState] = useState(() => createDefaultDataGridState(columns));
|
|
208
208
|
|
|
209
209
|
return (
|
|
@@ -216,6 +216,7 @@ function PaginatedDataGridHarness() {
|
|
|
216
216
|
onChange={setState}
|
|
217
217
|
paginationMode="paginated"
|
|
218
218
|
fillHeight={false}
|
|
219
|
+
stickyTop={props.stickyTop}
|
|
219
220
|
/>
|
|
220
221
|
</div>
|
|
221
222
|
);
|
|
@@ -351,6 +352,13 @@ describe("DataGrid infinite scroll observer", () => {
|
|
|
351
352
|
expect(grid).not.toBeNull();
|
|
352
353
|
expect(grid?.style.maxHeight).toBe("");
|
|
353
354
|
});
|
|
355
|
+
|
|
356
|
+
it("writes an explicit sticky offset to the grid contract", () => {
|
|
357
|
+
const { container } = render(<PaginatedDataGridHarness stickyTop={0} />);
|
|
358
|
+
|
|
359
|
+
const grid = container.querySelector<HTMLElement>('[role="grid"]');
|
|
360
|
+
expect(grid?.style.getPropertyValue("--data-grid-sticky-top")).toBe("0px");
|
|
361
|
+
});
|
|
354
362
|
});
|
|
355
363
|
|
|
356
364
|
// Drives a real `useDataSource` infinite-scroll grid whose data source
|
|
@@ -951,11 +951,14 @@ export function DataGrid<TRow>(props: DataGridProps<TRow>) {
|
|
|
951
951
|
|
|
952
952
|
const cssVars = useMemo<CSSProperties>(() => {
|
|
953
953
|
const vars: Record<string, string | number> = { "--grid-total-w": `${totalContentWidth}px` };
|
|
954
|
+
if (stickyTop != null) {
|
|
955
|
+
vars["--data-grid-sticky-top"] = typeof stickyTop === "number" ? `${stickyTop}px` : stickyTop;
|
|
956
|
+
}
|
|
954
957
|
for (const col of visibleColumns) {
|
|
955
958
|
vars[`--col-${col.id}-size`] = columnSizes[col.id];
|
|
956
959
|
}
|
|
957
960
|
return vars as CSSProperties;
|
|
958
|
-
}, [visibleColumns, columnSizes, totalContentWidth]);
|
|
961
|
+
}, [stickyTop, visibleColumns, columnSizes, totalContentWidth]);
|
|
959
962
|
|
|
960
963
|
// ── Selection handlers ───────────────────────────────────────
|
|
961
964
|
const fireSelection = useCallback(
|
|
@@ -1037,6 +1040,7 @@ export function DataGrid<TRow>(props: DataGridProps<TRow>) {
|
|
|
1037
1040
|
clipEl.style.setProperty("--data-grid-sticky-overlap", `${overlap}px`);
|
|
1038
1041
|
};
|
|
1039
1042
|
updateClip();
|
|
1043
|
+
const frame = requestAnimationFrame(updateClip);
|
|
1040
1044
|
bodyEl.addEventListener("scroll", updateClip);
|
|
1041
1045
|
window.addEventListener("scroll", updateClip, true);
|
|
1042
1046
|
window.addEventListener("resize", updateClip);
|
|
@@ -1048,9 +1052,10 @@ export function DataGrid<TRow>(props: DataGridProps<TRow>) {
|
|
|
1048
1052
|
bodyEl.removeEventListener("scroll", updateClip);
|
|
1049
1053
|
window.removeEventListener("scroll", updateClip, true);
|
|
1050
1054
|
window.removeEventListener("resize", updateClip);
|
|
1055
|
+
cancelAnimationFrame(frame);
|
|
1051
1056
|
observer.disconnect();
|
|
1052
1057
|
};
|
|
1053
|
-
}, []);
|
|
1058
|
+
}, [isLoading, rows.length, totalRowCount, visibleColumns.length]);
|
|
1054
1059
|
|
|
1055
1060
|
// Keep header + body horizontal offsets locked. When the scrollbar lives under
|
|
1056
1061
|
// the column headers (`horizontalScrollbarPosition="top"`), the header is the
|