@wheelhouse/ui 0.2.4 → 0.2.6

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 (61) hide show
  1. package/dist/blocks/columns/columns-types.d.ts +25 -1
  2. package/dist/blocks/columns/columns-types.d.ts.map +1 -1
  3. package/dist/blocks/columns/columns-types.js +4 -0
  4. package/dist/blocks/columns/columns-utils.d.ts +31 -1
  5. package/dist/blocks/columns/columns-utils.d.ts.map +1 -1
  6. package/dist/blocks/columns/columns-utils.js +86 -1
  7. package/dist/blocks/columns/columns.d.ts +1 -1
  8. package/dist/blocks/columns/columns.d.ts.map +1 -1
  9. package/dist/blocks/columns/columns.js +81 -20
  10. package/dist/blocks/columns/columns.stories.d.ts +1 -0
  11. package/dist/blocks/columns/columns.stories.d.ts.map +1 -1
  12. package/dist/blocks/columns/columns.stories.js +21 -1
  13. package/dist/blocks/columns/index.d.ts +1 -1
  14. package/dist/blocks/columns/index.d.ts.map +1 -1
  15. package/dist/components/data-grid/data-grid-column-filter.d.ts +15 -0
  16. package/dist/components/data-grid/data-grid-column-filter.d.ts.map +1 -0
  17. package/dist/components/data-grid/data-grid-column-filter.js +36 -0
  18. package/dist/components/data-grid/data-grid-column-header.d.ts +15 -0
  19. package/dist/components/data-grid/data-grid-column-header.d.ts.map +1 -0
  20. package/dist/components/data-grid/data-grid-column-header.js +137 -0
  21. package/dist/components/data-grid/data-grid-column-visibility.d.ts +8 -0
  22. package/dist/components/data-grid/data-grid-column-visibility.d.ts.map +1 -0
  23. package/dist/components/data-grid/data-grid-column-visibility.js +13 -0
  24. package/dist/components/data-grid/data-grid-pagination.d.ts +20 -0
  25. package/dist/components/data-grid/data-grid-pagination.d.ts.map +1 -0
  26. package/dist/components/data-grid/data-grid-pagination.js +76 -0
  27. package/dist/components/data-grid/data-grid-scroll-area.d.ts +11 -0
  28. package/dist/components/data-grid/data-grid-scroll-area.d.ts.map +1 -0
  29. package/dist/components/data-grid/data-grid-scroll-area.js +218 -0
  30. package/dist/components/data-grid/data-grid-table-dnd-rows.d.ts +12 -0
  31. package/dist/components/data-grid/data-grid-table-dnd-rows.d.ts.map +1 -0
  32. package/dist/components/data-grid/data-grid-table-dnd-rows.js +91 -0
  33. package/dist/components/data-grid/data-grid-table-dnd.d.ts +8 -0
  34. package/dist/components/data-grid/data-grid-table-dnd.d.ts.map +1 -0
  35. package/dist/components/data-grid/data-grid-table-dnd.js +95 -0
  36. package/dist/components/data-grid/data-grid-table-virtual.d.ts +28 -0
  37. package/dist/components/data-grid/data-grid-table-virtual.d.ts.map +1 -0
  38. package/dist/components/data-grid/data-grid-table-virtual.js +133 -0
  39. package/dist/components/data-grid/data-grid-table.d.ts +98 -0
  40. package/dist/components/data-grid/data-grid-table.d.ts.map +1 -0
  41. package/dist/components/data-grid/data-grid-table.js +560 -0
  42. package/dist/components/data-grid/data-grid.d.ts +94 -0
  43. package/dist/components/data-grid/data-grid.d.ts.map +1 -0
  44. package/dist/components/data-grid/data-grid.js +123 -0
  45. package/dist/components/data-grid/data-grid.stories.d.ts +14 -0
  46. package/dist/components/data-grid/data-grid.stories.d.ts.map +1 -0
  47. package/dist/components/data-grid/data-grid.stories.js +47 -0
  48. package/dist/components/data-grid/index.d.ts +14 -0
  49. package/dist/components/data-grid/index.d.ts.map +1 -0
  50. package/dist/components/data-grid/index.js +10 -0
  51. package/dist/components/index.d.ts +1 -0
  52. package/dist/components/index.d.ts.map +1 -1
  53. package/dist/components/index.js +1 -0
  54. package/dist/components/sidebar/sidebar.stories.d.ts.map +1 -1
  55. package/dist/components/sidebar/sidebar.stories.js +2 -5
  56. package/dist/components/sortable/sortable.d.ts +4 -2
  57. package/dist/components/sortable/sortable.d.ts.map +1 -1
  58. package/dist/components/sortable/sortable.js +4 -2
  59. package/dist/tsconfig.tsbuildinfo +1 -1
  60. package/package.json +7 -4
  61. package/src/styles/globals.css +26 -0
@@ -0,0 +1,560 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Fragment, memo, useCallback, useEffect, useMemo, useState, } from 'react';
4
+ import { useDataGrid } from './data-grid';
5
+ import { flexRender } from '@tanstack/react-table';
6
+ import { cva } from 'class-variance-authority';
7
+ import { Checkbox } from '../checkbox';
8
+ import { Spinner } from '../spinner';
9
+ import { cn } from '../../lib/utils';
10
+ const headerCellSpacingVariants = cva('', {
11
+ variants: {
12
+ size: {
13
+ dense: 'h-8 px-2',
14
+ default: 'px-3',
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ size: 'default',
19
+ },
20
+ });
21
+ const bodyCellSpacingVariants = cva('', {
22
+ variants: {
23
+ size: {
24
+ dense: 'px-2 py-1.5',
25
+ default: 'px-3 py-2',
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ size: 'default',
30
+ },
31
+ });
32
+ const footerCellSpacingVariants = cva('', {
33
+ variants: {
34
+ size: {
35
+ dense: 'px-2 py-1.5',
36
+ default: 'px-3 py-2',
37
+ },
38
+ },
39
+ defaultVariants: {
40
+ size: 'default',
41
+ },
42
+ });
43
+ function getPinningStyles(column) {
44
+ const isPinned = column.getIsPinned();
45
+ return {
46
+ left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,
47
+ right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined,
48
+ position: isPinned ? 'sticky' : 'relative',
49
+ width: column.getSize(),
50
+ zIndex: isPinned ? 1 : 0,
51
+ };
52
+ }
53
+ function assignRef(ref, value) {
54
+ if (!ref)
55
+ return;
56
+ if (typeof ref === 'function') {
57
+ ref(value);
58
+ return;
59
+ }
60
+ ref.current = value;
61
+ }
62
+ function isDataGridTouchEvent(event) {
63
+ return 'touches' in event;
64
+ }
65
+ function getDataGridResizeEventClientX(event) {
66
+ if (isDataGridTouchEvent(event)) {
67
+ return event.touches[0]?.clientX ?? event.changedTouches[0]?.clientX;
68
+ }
69
+ return event.clientX;
70
+ }
71
+ function startDataGridColumnResizeOnEnd(event, header, table) {
72
+ const column = table.getColumn(header.column.id);
73
+ if (!column || !column.getCanResize())
74
+ return;
75
+ if (isDataGridTouchEvent(event) && event.touches.length > 1)
76
+ return;
77
+ event.persist?.();
78
+ const ownerDocument = event.currentTarget.ownerDocument;
79
+ const previousBodyCursor = ownerDocument.body.style.cursor;
80
+ const previousDocumentCursor = ownerDocument.documentElement.style.cursor;
81
+ const startSize = header.getSize();
82
+ const dragStartClientX = getDataGridResizeEventClientX(event);
83
+ const headerCell = event.currentTarget.closest('th');
84
+ const headerRect = headerCell?.getBoundingClientRect();
85
+ const startOffset = headerRect && Number.isFinite(table.options.columnResizeDirection === 'rtl' ? headerRect.left : headerRect.right)
86
+ ? table.options.columnResizeDirection === 'rtl'
87
+ ? headerRect.left
88
+ : headerRect.right
89
+ : dragStartClientX;
90
+ if (typeof dragStartClientX !== 'number' || typeof startOffset !== 'number') {
91
+ return;
92
+ }
93
+ ownerDocument.body.style.cursor = 'col-resize';
94
+ ownerDocument.documentElement.style.cursor = 'col-resize';
95
+ const columnSizingStart = header.getLeafHeaders().map((leafHeader) => [leafHeader.column.id, leafHeader.column.getSize()]);
96
+ const directionMultiplier = table.options.columnResizeDirection === 'rtl' ? -1 : 1;
97
+ const updateOffset = (clientXPos, commit = false) => {
98
+ if (typeof clientXPos !== 'number')
99
+ return;
100
+ const nextColumnSizing = {};
101
+ const deltaOffset = (clientXPos - dragStartClientX) * directionMultiplier;
102
+ const deltaPercentage = Math.max(deltaOffset / startSize, -0.999999);
103
+ columnSizingStart.forEach(([columnId, headerSize]) => {
104
+ nextColumnSizing[columnId] = Math.round(Math.max(headerSize + headerSize * deltaPercentage, 0) * 100) / 100;
105
+ });
106
+ table.setColumnSizingInfo((old) => ({
107
+ ...old,
108
+ startOffset,
109
+ startSize,
110
+ deltaOffset,
111
+ deltaPercentage,
112
+ columnSizingStart,
113
+ isResizingColumn: column.id,
114
+ }));
115
+ if (commit) {
116
+ table.setColumnSizing((old) => ({
117
+ ...old,
118
+ ...nextColumnSizing,
119
+ }));
120
+ }
121
+ };
122
+ const endResize = (clientXPos) => {
123
+ updateOffset(clientXPos, true);
124
+ table.setColumnSizingInfo((old) => ({
125
+ ...old,
126
+ isResizingColumn: false,
127
+ startOffset: null,
128
+ startSize: null,
129
+ deltaOffset: null,
130
+ deltaPercentage: null,
131
+ columnSizingStart: [],
132
+ }));
133
+ ownerDocument.body.style.cursor = previousBodyCursor;
134
+ ownerDocument.documentElement.style.cursor = previousDocumentCursor;
135
+ };
136
+ const mouseMoveHandler = (moveEvent) => {
137
+ updateOffset(moveEvent.clientX);
138
+ };
139
+ const mouseUpHandler = (upEvent) => {
140
+ ownerDocument.removeEventListener('mousemove', mouseMoveHandler);
141
+ ownerDocument.removeEventListener('mouseup', mouseUpHandler);
142
+ endResize(upEvent.clientX);
143
+ };
144
+ const touchMoveHandler = (moveEvent) => {
145
+ if (moveEvent.cancelable) {
146
+ moveEvent.preventDefault();
147
+ moveEvent.stopPropagation();
148
+ }
149
+ updateOffset(getDataGridResizeEventClientX(moveEvent));
150
+ };
151
+ const touchEndHandler = (endEvent) => {
152
+ ownerDocument.removeEventListener('touchmove', touchMoveHandler);
153
+ ownerDocument.removeEventListener('touchend', touchEndHandler);
154
+ if (endEvent.cancelable) {
155
+ endEvent.preventDefault();
156
+ endEvent.stopPropagation();
157
+ }
158
+ endResize(getDataGridResizeEventClientX(endEvent));
159
+ };
160
+ const passiveIfSupported = { passive: false };
161
+ if (isDataGridTouchEvent(event)) {
162
+ ownerDocument.addEventListener('touchmove', touchMoveHandler, passiveIfSupported);
163
+ ownerDocument.addEventListener('touchend', touchEndHandler, passiveIfSupported);
164
+ }
165
+ else {
166
+ ownerDocument.addEventListener('mousemove', mouseMoveHandler, passiveIfSupported);
167
+ ownerDocument.addEventListener('mouseup', mouseUpHandler, passiveIfSupported);
168
+ }
169
+ table.setColumnSizingInfo((old) => ({
170
+ ...old,
171
+ startOffset,
172
+ startSize,
173
+ deltaOffset: 0,
174
+ deltaPercentage: 0,
175
+ columnSizingStart,
176
+ isResizingColumn: column.id,
177
+ }));
178
+ }
179
+ function getDataGridTableRowSections(table, rowsPinnable) {
180
+ if (!rowsPinnable) {
181
+ return {
182
+ topRows: [],
183
+ centerRows: table.getRowModel().rows,
184
+ bottomRows: [],
185
+ };
186
+ }
187
+ return {
188
+ topRows: table.getTopRows(),
189
+ centerRows: table.getCenterRows(),
190
+ bottomRows: table.getBottomRows(),
191
+ };
192
+ }
193
+ function getDataGridTableResolvedRows(table, rowsPinnable) {
194
+ const { topRows, centerRows, bottomRows } = getDataGridTableRowSections(table, rowsPinnable);
195
+ const resolvedRows = [];
196
+ topRows.forEach((row, index) => {
197
+ resolvedRows.push({
198
+ row,
199
+ pinnedBoundary: index === topRows.length - 1 && (centerRows.length > 0 || bottomRows.length > 0) ? 'top' : undefined,
200
+ });
201
+ });
202
+ centerRows.forEach((row) => {
203
+ resolvedRows.push({ row });
204
+ });
205
+ bottomRows.forEach((row, index) => {
206
+ resolvedRows.push({
207
+ row,
208
+ pinnedBoundary: index === 0 && (centerRows.length > 0 || topRows.length > 0) ? 'bottom' : undefined,
209
+ });
210
+ });
211
+ return resolvedRows;
212
+ }
213
+ function DataGridTableFillCol() {
214
+ const { props } = useDataGrid();
215
+ if (!props.tableLayout?.columnsResizable)
216
+ return null;
217
+ return _jsx("col", { "data-slot": "data-grid-table-fill-col", style: { width: 'var(--data-grid-fill-size, 0px)' } });
218
+ }
219
+ function DataGridTableFillHeadCell() {
220
+ const { props } = useDataGrid();
221
+ if (!props.tableLayout?.columnsResizable)
222
+ return null;
223
+ return _jsx("th", { "aria-hidden": "true", "data-slot": "data-grid-table-fill-head-cell", style: { width: 'var(--data-grid-fill-size, 0px)' }, className: "p-0" });
224
+ }
225
+ function DataGridTableFillBodyCell() {
226
+ const { props } = useDataGrid();
227
+ if (!props.tableLayout?.columnsResizable)
228
+ return null;
229
+ return _jsx("td", { "aria-hidden": "true", "data-slot": "data-grid-table-fill-body-cell", style: { width: 'var(--data-grid-fill-size, 0px)' }, className: "p-0" });
230
+ }
231
+ function DataGridTableFillFootCell() {
232
+ const { props } = useDataGrid();
233
+ if (!props.tableLayout?.columnsResizable)
234
+ return null;
235
+ return _jsx("td", { "aria-hidden": "true", "data-slot": "data-grid-table-fill-foot-cell", style: { width: 'var(--data-grid-fill-size, 0px)' }, className: "border-t p-0" });
236
+ }
237
+ function DataGridTableBase({ children }) {
238
+ const { props, table } = useDataGrid();
239
+ const visibleColumns = table.getVisibleLeafColumns();
240
+ /**
241
+ * Compute column widths as CSS custom properties once upfront (memoized).
242
+ * Cells reference these via calc(var(--col-X-size) * 1px) so the browser
243
+ * handles width propagation without per-cell getSize() calls or React
244
+ * re-renders of the body.
245
+ */
246
+ const columnSizeVars = useMemo(() => {
247
+ if (!props.tableLayout?.columnsResizable)
248
+ return undefined;
249
+ const headers = table.getFlatHeaders();
250
+ const colSizes = {};
251
+ for (let i = 0; i < headers.length; i++) {
252
+ const header = headers[i];
253
+ colSizes[`--header-${header.id}-size`] = header.getSize();
254
+ colSizes[`--col-${header.column.id}-size`] = header.column.getSize();
255
+ }
256
+ return colSizes;
257
+ // eslint-disable-next-line react-hooks/exhaustive-deps
258
+ }, [
259
+ props.tableLayout?.columnsResizable,
260
+ // eslint-disable-next-line react-hooks/exhaustive-deps
261
+ table.getState().columnSizing,
262
+ ]);
263
+ return (_jsxs("table", { "data-slot": "data-grid-table", className: cn('caption-bottom text-left align-middle text-sm font-normal text-foreground rtl:text-right', props.tableLayout?.columnsResizable ? 'min-w-0' : 'w-full min-w-full', props.tableLayout?.width === 'auto' ? 'table-auto' : 'table-fixed', !props.tableLayout?.columnsResizable && '', !props.tableLayout?.columnsDraggable && 'border-separate border-spacing-0', props.tableClassNames?.base), style: props.tableLayout?.columnsResizable
264
+ ? {
265
+ ...columnSizeVars,
266
+ width: `calc(${table.getTotalSize()}px + var(--data-grid-fill-size, 0px))`,
267
+ }
268
+ : undefined, children: [_jsxs("colgroup", { children: [visibleColumns.map((column) => (_jsx("col", { style: props.tableLayout?.columnsResizable
269
+ ? { width: `calc(var(--col-${column.id}-size) * 1px)` }
270
+ : props.tableLayout?.width === 'fixed'
271
+ ? { width: column.getSize() }
272
+ : undefined }, column.id))), _jsx(DataGridTableFillCol, {})] }), children] }));
273
+ }
274
+ function DataGridTableViewport({ children, className, viewportRef, style, }) {
275
+ const { props, table } = useDataGrid();
276
+ const [viewportElement, setViewportElement] = useState(null);
277
+ const [containerWidth, setContainerWidth] = useState(0);
278
+ const handleViewportRef = useCallback((node) => {
279
+ setViewportElement(node);
280
+ assignRef(viewportRef, node);
281
+ }, [viewportRef]);
282
+ const fillWidth = props.tableLayout?.columnsResizable && containerWidth > 0 ? Math.max(0, containerWidth - table.getTotalSize()) : 0;
283
+ useEffect(() => {
284
+ let cancelled = false;
285
+ const scheduleWidthUpdate = (fn) => {
286
+ queueMicrotask(() => {
287
+ if (!cancelled) {
288
+ fn();
289
+ }
290
+ });
291
+ };
292
+ if (!viewportElement || !props.tableLayout?.columnsResizable) {
293
+ scheduleWidthUpdate(() => setContainerWidth(0));
294
+ return () => {
295
+ cancelled = true;
296
+ };
297
+ }
298
+ const scrollViewport = viewportElement.closest('[data-slot="scroll-area-viewport"]') ?? viewportElement.parentElement;
299
+ const measurementTarget = scrollViewport ?? viewportElement;
300
+ const syncContainerWidth = () => {
301
+ setContainerWidth(measurementTarget.clientWidth);
302
+ };
303
+ scheduleWidthUpdate(syncContainerWidth);
304
+ if (typeof ResizeObserver === 'undefined') {
305
+ return () => {
306
+ cancelled = true;
307
+ };
308
+ }
309
+ const observer = new ResizeObserver(() => {
310
+ if (!cancelled) {
311
+ syncContainerWidth();
312
+ }
313
+ });
314
+ observer.observe(measurementTarget);
315
+ return () => {
316
+ cancelled = true;
317
+ observer.disconnect();
318
+ };
319
+ }, [props.tableLayout?.columnsResizable, viewportElement]);
320
+ return (_jsxs("div", { "data-slot": "data-grid-table-viewport", ref: handleViewportRef, className: cn('relative min-w-full align-top', className), style: {
321
+ ...(props.tableLayout?.columnsResizable
322
+ ? {
323
+ width: `calc(${table.getTotalSize()}px + var(--data-grid-fill-size, 0px))`,
324
+ ['--data-grid-fill-size']: `${fillWidth}px`,
325
+ }
326
+ : undefined),
327
+ ...style,
328
+ }, children: [children, _jsx(DataGridTableResizeIndicator, { viewportElement: viewportElement })] }));
329
+ }
330
+ function DataGridTableHead({ children }) {
331
+ const { props } = useDataGrid();
332
+ return _jsx("thead", { className: cn(props.tableClassNames?.header, props.tableLayout?.headerSticky && props.tableClassNames?.headerSticky), children: children });
333
+ }
334
+ function DataGridTableHeadRow({ children, headerGroup }) {
335
+ const { props } = useDataGrid();
336
+ return (_jsxs("tr", { className: cn('bg-muted/40', props.tableLayout?.headerBorder && '[&>th]:border-b', props.tableLayout?.cellBorder && '*:last:border-e-0', props.tableLayout?.stripped && 'bg-transparent', props.tableLayout?.headerBackground === false && 'bg-transparent', props.tableClassNames?.headerRow), children: [children, _jsx(DataGridTableFillHeadCell, {})] }, headerGroup.id));
337
+ }
338
+ function DataGridTableHeadRowCell({ children, header, dndRef, dndStyle, }) {
339
+ const { props } = useDataGrid();
340
+ const { column } = header;
341
+ const isPinned = column.getIsPinned();
342
+ const isLastLeftPinned = isPinned === 'left' && column.getIsLastColumn('left');
343
+ const isFirstRightPinned = isPinned === 'right' && column.getIsFirstColumn('right');
344
+ const isLastVisibleColumn = column.getIndex() === header.getContext().table.getVisibleLeafColumns().length - 1;
345
+ const headerCellSpacing = headerCellSpacingVariants({
346
+ size: props.tableLayout?.dense ? 'dense' : 'default',
347
+ });
348
+ return (_jsx("th", { ref: dndRef, style: {
349
+ ...(props.tableLayout?.width === 'fixed' &&
350
+ !props.tableLayout?.columnsResizable && {
351
+ width: header.getSize(),
352
+ }),
353
+ ...(props.tableLayout?.columnsPinnable && column.getCanPin() && getPinningStyles(column)),
354
+ ...(props.tableLayout?.columnsResizable && {
355
+ width: `calc(var(--header-${header.id}-size) * 1px)`,
356
+ }),
357
+ ...(dndStyle ? dndStyle : null),
358
+ }, "data-pinned": isPinned || undefined, "data-last-col": isLastLeftPinned ? 'left' : isFirstRightPinned ? 'right' : undefined, className: cn('relative h-9 text-left align-middle font-normal text-secondary-foreground/80 rtl:text-right [&:has([role=checkbox])]:pe-0', headerCellSpacing, props.tableLayout?.cellBorder && 'border-e', props.tableLayout?.columnsResizable && column.getCanResize() && 'overflow-visible', props.tableLayout?.columnsResizable && column.getCanResize() && isLastVisibleColumn && 'pe-8', props.tableLayout?.columnsPinnable &&
359
+ column.getCanPin() &&
360
+ 'data-pinned:bg-muted/90 data-pinned:backdrop-blur-xs [&:not([data-pinned]):has(+[data-pinned])_div.cursor-col-resize:last-child]:opacity-0 [&[data-last-col=left]_div.cursor-col-resize:last-child]:opacity-0 [&[data-pinned=left][data-last-col=left]]:border-e! [&[data-pinned=right]:last-child_div.cursor-col-resize:last-child]:opacity-0 [&[data-pinned=right][data-last-col=right]]:border-s! [&[data-pinned][data-last-col]]:border-border', header.column.columnDef.meta?.headerClassName, column.getIndex() === 0 || column.getIndex() === header.headerGroup.headers.length - 1 ? props.tableClassNames?.edgeCell : ''), children: children }, header.id));
361
+ }
362
+ function DataGridTableHeadRowCellResize({ header }) {
363
+ const { props, table } = useDataGrid();
364
+ const { column } = header;
365
+ const isLastVisibleColumn = column.getIndex() === header.getContext().table.getVisibleLeafColumns().length - 1;
366
+ const isResizeModeOnEnd = (props.tableLayout?.columnsResizeMode ?? table.options.columnResizeMode) === 'onEnd';
367
+ const handleMouseDown = (event) => {
368
+ event.preventDefault();
369
+ event.stopPropagation();
370
+ if (isResizeModeOnEnd) {
371
+ startDataGridColumnResizeOnEnd(event, header, table);
372
+ return;
373
+ }
374
+ header.getResizeHandler()(event);
375
+ };
376
+ const handleTouchStart = (event) => {
377
+ event.preventDefault();
378
+ event.stopPropagation();
379
+ if (isResizeModeOnEnd) {
380
+ startDataGridColumnResizeOnEnd(event, header, table);
381
+ return;
382
+ }
383
+ header.getResizeHandler()(event);
384
+ };
385
+ return (_jsx("div", { onDoubleClick: () => column.resetSize(),
386
+ onMouseDown: handleMouseDown,
387
+ onTouchStart: handleTouchStart,
388
+ className: cn('user-select-none absolute top-0 z-10 flex h-full cursor-col-resize touch-none', isLastVisibleColumn
389
+ ? 'end-0 w-5 justify-end before:hidden'
390
+ : '-end-2 w-5 justify-center before:absolute before:inset-y-0 before:w-px before:-translate-x-px before:bg-border', column.getIsResizing() &&
391
+ (isResizeModeOnEnd
392
+ ? 'opacity-100'
393
+ : isLastVisibleColumn
394
+ ? 'opacity-100 before:absolute before:inset-y-0 before:end-0 before:block before:w-0.5 before:bg-primary'
395
+ : 'opacity-100 before:block before:w-0.5 before:bg-primary')) }));
396
+ }
397
+ function DataGridTableResizeIndicator({ viewportElement }) {
398
+ const { props, table } = useDataGrid();
399
+ const columnSizingInfo = table.getState().columnSizingInfo;
400
+ const resizingColumnId = columnSizingInfo.isResizingColumn;
401
+ const resizeMode = props.tableLayout?.columnsResizeMode ?? table.options.columnResizeMode;
402
+ if (!props.tableLayout?.columnsResizable || resizeMode !== 'onEnd' || !resizingColumnId) {
403
+ return null;
404
+ }
405
+ const resizingHeader = table.getFlatHeaders().find((header) => header.column.id === resizingColumnId || header.id === resizingColumnId);
406
+ if (!resizingHeader)
407
+ return null;
408
+ const deltaOffset = columnSizingInfo.deltaOffset ?? 0;
409
+ const headerHeight = viewportElement?.querySelector('[data-slot="data-grid-table"] thead')?.getBoundingClientRect().height ?? 0;
410
+ const indicatorLeft = typeof columnSizingInfo.startOffset === 'number' && viewportElement
411
+ ? columnSizingInfo.startOffset - viewportElement.getBoundingClientRect().left
412
+ : resizingHeader.getStart() + resizingHeader.getSize();
413
+ return (_jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-y-0 z-20", style: {
414
+ left: indicatorLeft,
415
+ transform: `translateX(${deltaOffset}px)`,
416
+ }, children: [_jsx("div", { className: "absolute inset-y-0 left-0 w-px -translate-x-1/2 bg-primary/85" }), _jsx("div", { className: "absolute top-0 left-0 -translate-x-1/2 rounded-b-sm bg-primary shadow-xs", style: {
417
+ width: 5,
418
+ height: Math.max(headerHeight, 6),
419
+ } })] }));
420
+ }
421
+ function DataGridTableRowSpacer() {
422
+ return _jsx("tbody", { "aria-hidden": "true", className: "h-2" });
423
+ }
424
+ function DataGridTableBody({ children }) {
425
+ const { props } = useDataGrid();
426
+ return (_jsx("tbody", { className: cn('[&_tr:last-child]:border-0', props.tableLayout?.rowRounded && '[&_td:first-child]:rounded-l-lg', props.tableLayout?.rowRounded && '[&_td:last-child]:rounded-r-lg', props.tableClassNames?.body), children: children }));
427
+ }
428
+ function DataGridTableFoot({ children }) {
429
+ const { props } = useDataGrid();
430
+ return _jsx("tfoot", { className: cn('border-t', props.tableClassNames?.footer), children: children });
431
+ }
432
+ function DataGridTableFootRow({ children }) {
433
+ const { props } = useDataGrid();
434
+ return (_jsxs("tr", { className: cn('bg-muted/40 dark:bg-background', props.tableLayout?.cellBorder && '*:last:border-e-0'), children: [children, _jsx(DataGridTableFillFootCell, {})] }));
435
+ }
436
+ function DataGridTableFootRowCell({ children, colSpan, className }) {
437
+ const { props } = useDataGrid();
438
+ const spacing = footerCellSpacingVariants({
439
+ size: props.tableLayout?.dense ? 'dense' : 'default',
440
+ });
441
+ return (_jsx("td", { colSpan: colSpan, className: cn('border-t align-middle font-medium text-secondary-foreground/80', spacing, props.tableLayout?.cellBorder && 'border-e', className), children: children }));
442
+ }
443
+ function DataGridTableBodyRowSkeleton({ children }) {
444
+ const { table, props } = useDataGrid();
445
+ return (_jsxs("tr", { className: cn('hover:bg-muted/40 data-[state=selected]:bg-muted/50', props.onRowClick && 'cursor-pointer', !props.tableLayout?.stripped && props.tableLayout?.rowBorder && 'border-b border-border [&:not(:last-child)>td]:border-b', props.tableLayout?.cellBorder && '*:last:border-e-0', props.tableLayout?.stripped && 'odd:bg-muted/90 hover:bg-transparent odd:hover:bg-muted', table.options.enableRowSelection && '*:first:relative', props.tableClassNames?.bodyRow), children: [children, _jsx(DataGridTableFillBodyCell, {})] }));
446
+ }
447
+ function DataGridTableBodyRowSkeletonCell({ children, column }) {
448
+ const { props, table } = useDataGrid();
449
+ const bodyCellSpacing = bodyCellSpacingVariants({
450
+ size: props.tableLayout?.dense ? 'dense' : 'default',
451
+ });
452
+ return (_jsx("td", { style: props.tableLayout?.columnsResizable ? { width: `calc(var(--col-${column.id}-size) * 1px)` } : undefined, className: cn('align-middle', bodyCellSpacing, props.tableLayout?.cellBorder && 'border-e', props.tableLayout?.columnsResizable && column.getCanResize() && 'truncate', column.columnDef.meta?.cellClassName, props.tableLayout?.columnsPinnable &&
453
+ column.getCanPin() &&
454
+ 'data-pinned:backdrop-blur-xs" data-pinned:bg-background/90 [&[data-pinned=left][data-last-col=left]]:border-e! [&[data-pinned=right][data-last-col=right]]:border-s! [&[data-pinned][data-last-col]]:border-border', column.getIndex() === 0 || column.getIndex() === table.getVisibleFlatColumns().length - 1 ? props.tableClassNames?.edgeCell : ''), children: children }));
455
+ }
456
+ function DataGridTableBodyRow({ children, row, pinnedBoundary, rowRef, dndRef, dndStyle, }) {
457
+ const { props, table } = useDataGrid();
458
+ const isRowPinned = row.getIsPinned();
459
+ return (_jsxs("tr", { ref: (node) => {
460
+ assignRef(rowRef, node);
461
+ assignRef(dndRef, node);
462
+ }, style: { ...(dndStyle ? dndStyle : null) }, "data-state": table.options.enableRowSelection && row.getIsSelected() ? 'selected' : undefined, "data-row-pinned": isRowPinned || undefined, "data-row-pinned-boundary": pinnedBoundary, onClick: () => props.onRowClick && props.onRowClick(row.original), className: cn('hover:bg-muted/40 data-[state=selected]:bg-muted/50', props.onRowClick && 'cursor-pointer', !props.tableLayout?.stripped && props.tableLayout?.rowBorder && 'border-b border-border [&:not(:last-child)>td]:border-b', props.tableLayout?.cellBorder && '*:last:border-e-0', props.tableLayout?.stripped && 'odd:bg-muted/90 hover:bg-transparent odd:hover:bg-muted', table.options.enableRowSelection && '*:first:relative', props.tableLayout?.rowsPinnable && isRowPinned && 'bg-muted/30 hover:bg-muted/50', pinnedBoundary === 'top' && '[&>td]:shadow-[0_2px_0_rgba(0,0,0,0.03)]', pinnedBoundary === 'bottom' && '[&>td]:shadow-[0_2px_0_rgba(0,0,0,0.03)]', props.tableClassNames?.bodyRow), children: [children, _jsx(DataGridTableFillBodyCell, {})] }));
463
+ }
464
+ function DataGridTableBodyRowExpandded({ row }) {
465
+ const { props, table } = useDataGrid();
466
+ return (_jsx("tr", { className: cn(props.tableLayout?.rowBorder && '[&:not(:last-child)>td]:border-b'), children: _jsx("td", { colSpan: row.getVisibleCells().length + (props.tableLayout?.columnsResizable ? 1 : 0), children: table
467
+ .getAllColumns()
468
+ .find((column) => column.columnDef.meta?.expandedContent)
469
+ ?.columnDef.meta?.expandedContent?.(row.original) }) }));
470
+ }
471
+ function DataGridTableBodyRowCell({ children, cell, dndRef, dndStyle, }) {
472
+ const { props } = useDataGrid();
473
+ const { column, row } = cell;
474
+ const isPinned = column.getIsPinned();
475
+ const isLastLeftPinned = isPinned === 'left' && column.getIsLastColumn('left');
476
+ const isFirstRightPinned = isPinned === 'right' && column.getIsFirstColumn('right');
477
+ const bodyCellSpacing = bodyCellSpacingVariants({
478
+ size: props.tableLayout?.dense ? 'dense' : 'default',
479
+ });
480
+ return (_jsx("td", { ref: dndRef, ...(props.tableLayout?.columnsDraggable && !isPinned ? { cell } : {}), style: {
481
+ ...(props.tableLayout?.columnsPinnable && column.getCanPin() && getPinningStyles(column)),
482
+ ...(props.tableLayout?.columnsResizable && {
483
+ width: `calc(var(--col-${column.id}-size) * 1px)`,
484
+ }),
485
+ ...(dndStyle ? dndStyle : null),
486
+ }, "data-pinned": isPinned || undefined, "data-last-col": isLastLeftPinned ? 'left' : isFirstRightPinned ? 'right' : undefined, className: cn('align-middle', bodyCellSpacing, props.tableLayout?.cellBorder && 'border-e', props.tableLayout?.columnsResizable && column.getCanResize() && 'truncate', cell.column.columnDef.meta?.cellClassName, props.tableLayout?.columnsPinnable &&
487
+ column.getCanPin() &&
488
+ 'data-pinned:backdrop-blur-xs" data-pinned:bg-background/90 [&[data-pinned=left][data-last-col=left]]:border-e! [&[data-pinned=right][data-last-col=right]]:border-s! [&[data-pinned][data-last-col]]:border-border', column.getIndex() === 0 || column.getIndex() === row.getVisibleCells().length - 1 ? props.tableClassNames?.edgeCell : ''), children: children }, cell.id));
489
+ }
490
+ function DataGridTableRenderedRow({ row, pinnedBoundary, rowRef, }) {
491
+ return (_jsxs(Fragment, { children: [_jsx(DataGridTableBodyRow, { row: row, pinnedBoundary: pinnedBoundary, rowRef: rowRef, children: row.getVisibleCells().map((cell) => (_jsx(DataGridTableBodyRowCell, { cell: cell, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }), row.getIsExpanded() && _jsx(DataGridTableBodyRowExpandded, { row: row })] }));
492
+ }
493
+ function DataGridTableEmpty() {
494
+ const { table, props } = useDataGrid();
495
+ const visibleColumnCount = table.getVisibleLeafColumns().length + (props.tableLayout?.columnsResizable ? 1 : 0);
496
+ return (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(visibleColumnCount, 1), className: "py-6 text-center text-sm text-muted-foreground", children: props.emptyMessage || 'No data available' }) }));
497
+ }
498
+ function DataGridTableLoader() {
499
+ const { props } = useDataGrid();
500
+ return (_jsx("div", { className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2", children: _jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-card px-4 py-2 text-sm leading-none font-medium text-muted-foreground", children: [_jsx(Spinner, { className: "size-5 opacity-60" }), props.loadingMessage || 'Loading...'] }) }));
501
+ }
502
+ function DataGridTableRowPin({ row }) {
503
+ const isPinned = row.getIsPinned();
504
+ return (_jsx("button", { type: "button", "aria-label": isPinned ? 'Unpin row' : 'Pin row', onClick: () => {
505
+ if (isPinned) {
506
+ row.pin(false);
507
+ }
508
+ else {
509
+ row.pin('top');
510
+ }
511
+ }, className: cn('inline-flex size-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground', isPinned && 'text-primary hover:text-primary/80'), children: isPinned ? (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", stroke: "none", children: _jsx("path", { d: "M16 2l4.585 4.586-2.122 2.121L17.05 7.293l-3.535 3.536 1.413 5.658-2.12 2.121-4.244-4.243L4.322 18.6l-1.414-1.41 4.242-4.244-4.243-4.243 2.122-2.121 5.656 1.414 3.536-3.536-1.414-1.414z" }) })) : (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "12", y1: "17", x2: "12", y2: "22" }), _jsx("path", { d: "M5 17h14v-1.76a2 2 0 00-1.11-1.79l-1.78-.9A2 2 0 0115 10.76V6h1a2 2 0 000-4H8a2 2 0 000 4h1v4.76a2 2 0 01-1.11 1.79l-1.78.9A2 2 0 005 15.24z" })] })) }));
512
+ }
513
+ function DataGridTableRowSelect({ row }) {
514
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: cn('absolute inset-s-0 top-0 bottom-0 hidden w-[2px] bg-primary', row.getIsSelected() && 'block') }), _jsx(Checkbox, { checked: row.getIsSelected(), onCheckedChange: (value) => row.toggleSelected(!!value), "aria-label": "Select row", className: "align-[inherit]" })] }));
515
+ }
516
+ function DataGridTableRowSelectAll() {
517
+ const { table, recordCount, isLoading } = useDataGrid();
518
+ const isAllSelected = table.getIsAllPageRowsSelected();
519
+ const isSomeSelected = table.getIsSomePageRowsSelected();
520
+ return (_jsx(Checkbox, { checked: isAllSelected, indeterminate: isSomeSelected && !isAllSelected, disabled: isLoading || recordCount === 0, onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value), "aria-label": "Select all", className: "align-[inherit]" }));
521
+ }
522
+ function DataGridTableBodyRows({ table }) {
523
+ const { isLoading, props } = useDataGrid();
524
+ const pagination = table.getState().pagination;
525
+ if (isLoading && props.loadingMode === 'skeleton' && pagination?.pageSize) {
526
+ return (_jsx(_Fragment, { children: Array.from({ length: pagination.pageSize }).map((_, rowIndex) => (_jsx(DataGridTableBodyRowSkeleton, { children: table.getVisibleFlatColumns().map((column, colIndex) => (_jsx(DataGridTableBodyRowSkeletonCell, { column: column, children: column.columnDef.meta?.skeleton }, colIndex))) }, rowIndex))) }));
527
+ }
528
+ if (isLoading && props.loadingMode === 'spinner') {
529
+ return (_jsx("tr", { children: _jsx("td", { colSpan: table.getVisibleFlatColumns().length, className: "p-8", children: _jsxs("div", { className: "flex items-center justify-center", children: [_jsxs("svg", { className: "mr-3 -ml-1 h-5 w-5 animate-spin text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), props.loadingMessage || 'Loading...'] }) }) }));
530
+ }
531
+ const resolvedRows = getDataGridTableResolvedRows(table, props.tableLayout?.rowsPinnable);
532
+ if (!resolvedRows.length)
533
+ return _jsx(DataGridTableEmpty, {});
534
+ return (_jsx(_Fragment, { children: resolvedRows.map(({ row, pinnedBoundary }) => (_jsx(DataGridTableRenderedRow, { row: row, pinnedBoundary: pinnedBoundary }, row.id))) }));
535
+ }
536
+ /**
537
+ * Memoized body rows: skip re-renders during active column resize.
538
+ * Column widths update via CSS variables on the <table> element,
539
+ * so the browser handles width changes without React re-renders.
540
+ */
541
+ const MemoizedDataGridTableBodyRows = memo(DataGridTableBodyRows, (_prev, next) => !!next.table.getState().columnSizingInfo.isResizingColumn);
542
+ function DataGridTableHeader() {
543
+ const { table, props } = useDataGrid();
544
+ return (_jsx(DataGridTableViewport, { children: _jsx(DataGridTableBase, { children: _jsx(DataGridTableHead, { children: table.getHeaderGroups().map((headerGroup, index) => {
545
+ return (_jsx(DataGridTableHeadRow, { headerGroup: headerGroup, children: headerGroup.headers.map((header, index) => {
546
+ const { column } = header;
547
+ return (_jsxs(DataGridTableHeadRowCell, { header: header, children: [header.isPlaceholder ? null : props.tableLayout?.columnsResizable && column.getCanResize() ? (_jsx("div", { className: "truncate", children: flexRender(header.column.columnDef.header, header.getContext()) })) : (flexRender(header.column.columnDef.header, header.getContext())), props.tableLayout?.columnsResizable && column.getCanResize() && _jsx(DataGridTableHeadRowCellResize, { header: header })] }, index));
548
+ }) }, index));
549
+ }) }) }) }));
550
+ }
551
+ function DataGridTable({ footerContent, renderHeader = true }) {
552
+ const { table, props } = useDataGrid();
553
+ return (_jsx(DataGridTableViewport, { children: _jsxs(DataGridTableBase, { children: [renderHeader && (_jsx(DataGridTableHead, { children: table.getHeaderGroups().map((headerGroup, index) => {
554
+ return (_jsx(DataGridTableHeadRow, { headerGroup: headerGroup, children: headerGroup.headers.map((header, index) => {
555
+ const { column } = header;
556
+ return (_jsxs(DataGridTableHeadRowCell, { header: header, children: [header.isPlaceholder ? null : props.tableLayout?.columnsResizable && column.getCanResize() ? (_jsx("div", { className: "truncate", children: flexRender(header.column.columnDef.header, header.getContext()) })) : (flexRender(header.column.columnDef.header, header.getContext())), props.tableLayout?.columnsResizable && column.getCanResize() && (_jsx(DataGridTableHeadRowCellResize, { header: header }))] }, index));
557
+ }) }, index));
558
+ }) })), renderHeader && (props.tableLayout?.stripped || !props.tableLayout?.rowBorder) && _jsx(DataGridTableRowSpacer, {}), _jsx(DataGridTableBody, { children: _jsx(MemoizedDataGridTableBodyRows, { table: table }) }), footerContent && _jsx(DataGridTableFoot, { children: footerContent })] }) }));
559
+ }
560
+ export { DataGridTable, DataGridTableBase, DataGridTableBody, DataGridTableBodyRow, DataGridTableBodyRowCell, DataGridTableBodyRowExpandded, DataGridTableRenderedRow, DataGridTableBodyRowSkeleton, DataGridTableBodyRowSkeletonCell, DataGridTableEmpty, DataGridTableFoot, DataGridTableFootRow, DataGridTableFootRowCell, DataGridTableHeader, DataGridTableHead, DataGridTableHeadRow, DataGridTableHeadRowCell, DataGridTableHeadRowCellResize, DataGridTableLoader, DataGridTableRowPin, DataGridTableRowSelect, DataGridTableRowSelectAll, DataGridTableRowSpacer, DataGridTableViewport, getDataGridTableResolvedRows, getDataGridTableRowSections, };
@@ -0,0 +1,94 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type Column, type ColumnFiltersState, type RowData, type SortingState, type Table } from '@tanstack/react-table';
3
+ declare module '@tanstack/react-table' {
4
+ interface ColumnMeta<TData extends RowData, TValue> {
5
+ headerTitle?: string;
6
+ headerClassName?: string;
7
+ cellClassName?: string;
8
+ skeleton?: ReactNode;
9
+ expandedContent?: (row: TData) => ReactNode;
10
+ }
11
+ }
12
+ /** Label for headers / column visibility: `meta.headerTitle`, string `columnDef.header`, or `column.id`. */
13
+ export declare function getColumnHeaderLabel<TData, TValue>(column: Column<TData, TValue>): string;
14
+ export type DataGridApiFetchParams = {
15
+ pageIndex: number;
16
+ pageSize: number;
17
+ sorting?: SortingState;
18
+ filters?: ColumnFiltersState;
19
+ searchQuery?: string;
20
+ };
21
+ export type DataGridApiResponse<T> = {
22
+ data: T[];
23
+ empty: boolean;
24
+ pagination: {
25
+ total: number;
26
+ page: number;
27
+ };
28
+ };
29
+ export interface DataGridContextProps<TData extends object> {
30
+ props: DataGridProps<TData>;
31
+ table: Table<TData>;
32
+ recordCount: number;
33
+ isLoading: boolean;
34
+ }
35
+ export type DataGridRequestParams = {
36
+ pageIndex: number;
37
+ pageSize: number;
38
+ sorting?: SortingState;
39
+ columnFilters?: ColumnFiltersState;
40
+ };
41
+ export interface DataGridProps<TData extends object> {
42
+ className?: string;
43
+ table?: Table<TData>;
44
+ recordCount: number;
45
+ children?: ReactNode;
46
+ onRowClick?: (row: TData) => void;
47
+ isLoading?: boolean;
48
+ loadingMode?: 'skeleton' | 'spinner';
49
+ loadingMessage?: ReactNode | string;
50
+ fetchingMoreMessage?: ReactNode | string;
51
+ allRowsLoadedMessage?: ReactNode | string;
52
+ emptyMessage?: ReactNode | string;
53
+ tableLayout?: {
54
+ dense?: boolean;
55
+ cellBorder?: boolean;
56
+ rowBorder?: boolean;
57
+ rowRounded?: boolean;
58
+ stripped?: boolean;
59
+ headerBackground?: boolean;
60
+ headerBorder?: boolean;
61
+ headerSticky?: boolean;
62
+ width?: 'auto' | 'fixed';
63
+ columnsVisibility?: boolean;
64
+ columnsResizable?: boolean;
65
+ columnsResizeMode?: 'onChange' | 'onEnd';
66
+ columnsPinnable?: boolean;
67
+ columnsMovable?: boolean;
68
+ columnsDraggable?: boolean;
69
+ rowsDraggable?: boolean;
70
+ rowsPinnable?: boolean;
71
+ };
72
+ tableClassNames?: {
73
+ base?: string;
74
+ header?: string;
75
+ headerRow?: string;
76
+ headerSticky?: string;
77
+ body?: string;
78
+ bodyRow?: string;
79
+ footer?: string;
80
+ edgeCell?: string;
81
+ };
82
+ }
83
+ declare function useDataGrid(): DataGridContextProps<any>;
84
+ declare function DataGridProvider<TData extends object>({ children, table, ...props }: DataGridProps<TData> & {
85
+ table: Table<TData>;
86
+ }): import("react/jsx-runtime").JSX.Element;
87
+ declare function DataGrid<TData extends object>({ children, table, ...props }: DataGridProps<TData>): import("react/jsx-runtime").JSX.Element;
88
+ declare function DataGridContainer({ children, className, border }: {
89
+ children: ReactNode;
90
+ className?: string;
91
+ border?: boolean;
92
+ }): import("react/jsx-runtime").JSX.Element;
93
+ export { useDataGrid, DataGridProvider, DataGrid, DataGridContainer };
94
+ //# sourceMappingURL=data-grid.d.ts.map