@versini/ui-datagrid 0.1.0

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/LICENSE +21 -0
  2. package/README.md +294 -0
  3. package/dist/DataGrid/DataGrid.d.ts +2 -0
  4. package/dist/DataGrid/DataGrid.js +132 -0
  5. package/dist/DataGrid/DataGridContext.d.ts +2 -0
  6. package/dist/DataGrid/DataGridContext.js +16 -0
  7. package/dist/DataGrid/index.d.ts +2 -0
  8. package/dist/DataGrid/index.js +17 -0
  9. package/dist/DataGrid/utilities.d.ts +36 -0
  10. package/dist/DataGrid/utilities.js +99 -0
  11. package/dist/DataGridAnimated/AnimatedWrapper.d.ts +47 -0
  12. package/dist/DataGridAnimated/AnimatedWrapper.js +49 -0
  13. package/dist/DataGridAnimated/index.d.ts +4 -0
  14. package/dist/DataGridAnimated/index.js +17 -0
  15. package/dist/DataGridAnimated/useAnimatedHeight.d.ts +49 -0
  16. package/dist/DataGridAnimated/useAnimatedHeight.js +131 -0
  17. package/dist/DataGridBody/DataGridBody.d.ts +2 -0
  18. package/dist/DataGridBody/DataGridBody.js +38 -0
  19. package/dist/DataGridBody/index.d.ts +1 -0
  20. package/dist/DataGridBody/index.js +13 -0
  21. package/dist/DataGridCell/DataGridCell.d.ts +14 -0
  22. package/dist/DataGridCell/DataGridCell.js +77 -0
  23. package/dist/DataGridCell/index.d.ts +1 -0
  24. package/dist/DataGridCell/index.js +13 -0
  25. package/dist/DataGridCellSort/DataGridCellSort.d.ts +2 -0
  26. package/dist/DataGridCellSort/DataGridCellSort.js +107 -0
  27. package/dist/DataGridCellSort/index.d.ts +1 -0
  28. package/dist/DataGridCellSort/index.js +13 -0
  29. package/dist/DataGridConstants/DataGridConstants.d.ts +37 -0
  30. package/dist/DataGridConstants/DataGridConstants.js +38 -0
  31. package/dist/DataGridConstants/index.d.ts +1 -0
  32. package/dist/DataGridConstants/index.js +13 -0
  33. package/dist/DataGridFooter/DataGridFooter.d.ts +12 -0
  34. package/dist/DataGridFooter/DataGridFooter.js +81 -0
  35. package/dist/DataGridFooter/index.d.ts +1 -0
  36. package/dist/DataGridFooter/index.js +13 -0
  37. package/dist/DataGridHeader/DataGridHeader.d.ts +13 -0
  38. package/dist/DataGridHeader/DataGridHeader.js +80 -0
  39. package/dist/DataGridHeader/index.d.ts +1 -0
  40. package/dist/DataGridHeader/index.js +13 -0
  41. package/dist/DataGridInfinite/InfiniteScrollMarker.d.ts +35 -0
  42. package/dist/DataGridInfinite/InfiniteScrollMarker.js +53 -0
  43. package/dist/DataGridInfinite/index.d.ts +4 -0
  44. package/dist/DataGridInfinite/index.js +17 -0
  45. package/dist/DataGridInfinite/useInfiniteScroll.d.ts +81 -0
  46. package/dist/DataGridInfinite/useInfiniteScroll.js +117 -0
  47. package/dist/DataGridRow/DataGridRow.d.ts +2 -0
  48. package/dist/DataGridRow/DataGridRow.js +75 -0
  49. package/dist/DataGridRow/index.d.ts +1 -0
  50. package/dist/DataGridRow/index.js +13 -0
  51. package/dist/DataGridSorting/index.d.ts +2 -0
  52. package/dist/DataGridSorting/index.js +18 -0
  53. package/dist/DataGridSorting/sortingUtils.d.ts +138 -0
  54. package/dist/DataGridSorting/sortingUtils.js +234 -0
  55. package/dist/DataGridVirtual/VirtualDataGrid.d.ts +114 -0
  56. package/dist/DataGridVirtual/VirtualDataGrid.js +181 -0
  57. package/dist/DataGridVirtual/index.d.ts +6 -0
  58. package/dist/DataGridVirtual/index.js +22 -0
  59. package/dist/DataGridVirtual/useVirtualDataGrid.d.ts +112 -0
  60. package/dist/DataGridVirtual/useVirtualDataGrid.js +89 -0
  61. package/package.json +103 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Arno Versini
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,294 @@
1
+ # @versini/ui-datagrid
2
+
3
+ A high-performance data grid component library for React with support for:
4
+
5
+ - **Virtualization**: Efficiently render thousands of rows using TanStack Virtual
6
+ - **Infinite Scrolling**: Progressive loading with IntersectionObserver
7
+ - **Animated Height**: Smooth height transitions when content changes
8
+ - **Sorting**: Built-in sorting utilities and sortable column headers
9
+ - **Sticky Header/Footer**: With optional blur effects
10
+ - **Loading States**: Built-in loading overlay with spinner
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @versini/ui-datagrid
16
+ ```
17
+
18
+ ## Entry Points
19
+
20
+ Import only what you need for optimal bundle size:
21
+
22
+ ```tsx
23
+ // Core data grid
24
+ import { DataGrid } from "@versini/ui-datagrid/datagrid";
25
+
26
+ // Header, Body, Footer
27
+ import { DataGridHeader } from "@versini/ui-datagrid/header";
28
+ import { DataGridBody } from "@versini/ui-datagrid/body";
29
+ import { DataGridFooter } from "@versini/ui-datagrid/footer";
30
+
31
+ // Row and Cell
32
+ import { DataGridRow } from "@versini/ui-datagrid/row";
33
+ import { DataGridCell } from "@versini/ui-datagrid/cell";
34
+ import { DataGridCellSort } from "@versini/ui-datagrid/cell-sort";
35
+
36
+ // Infinite scroll (progressive loading)
37
+ import {
38
+ useInfiniteScroll,
39
+ InfiniteScrollMarker
40
+ } from "@versini/ui-datagrid/infinite";
41
+
42
+ // True virtualization for large datasets
43
+ import {
44
+ VirtualDataGrid,
45
+ useVirtualDataGrid
46
+ } from "@versini/ui-datagrid/virtual";
47
+
48
+ // Animated height wrapper
49
+ import {
50
+ AnimatedWrapper,
51
+ useAnimatedHeight
52
+ } from "@versini/ui-datagrid/animated";
53
+
54
+ // Sorting utilities
55
+ import {
56
+ sortByDate,
57
+ sortByNumber,
58
+ sortByString,
59
+ sortByBoolean,
60
+ sortItems,
61
+ getNextSortConfig,
62
+ getOppositeSortDirection,
63
+ toggleSortDirection,
64
+ SortDirections
65
+ } from "@versini/ui-datagrid/sorting";
66
+
67
+ // Constants
68
+ import {
69
+ SortDirections,
70
+ BlurEffects,
71
+ ThemeModes,
72
+ CellWrapper
73
+ } from "@versini/ui-datagrid/constants";
74
+ ```
75
+
76
+ ## Basic Usage
77
+
78
+ ```tsx
79
+ import { DataGrid } from "@versini/ui-datagrid/datagrid";
80
+ import { DataGridHeader } from "@versini/ui-datagrid/header";
81
+ import { DataGridBody } from "@versini/ui-datagrid/body";
82
+ import { DataGridRow } from "@versini/ui-datagrid/row";
83
+ import { DataGridCell } from "@versini/ui-datagrid/cell";
84
+
85
+ function MyTable({ data }) {
86
+ return (
87
+ <DataGrid maxHeight="400px" stickyHeader>
88
+ <DataGridHeader>
89
+ <DataGridRow>
90
+ <DataGridCell>Name</DataGridCell>
91
+ <DataGridCell>Email</DataGridCell>
92
+ </DataGridRow>
93
+ </DataGridHeader>
94
+ <DataGridBody>
95
+ {data.map((item) => (
96
+ <DataGridRow key={item.id}>
97
+ <DataGridCell>{item.name}</DataGridCell>
98
+ <DataGridCell>{item.email}</DataGridCell>
99
+ </DataGridRow>
100
+ ))}
101
+ </DataGridBody>
102
+ </DataGrid>
103
+ );
104
+ }
105
+ ```
106
+
107
+ ## Infinite Scroll
108
+
109
+ For datasets with hundreds to thousands of rows, use progressive loading:
110
+
111
+ ```tsx
112
+ import { DataGrid } from "@versini/ui-datagrid/datagrid";
113
+ import { DataGridHeader } from "@versini/ui-datagrid/header";
114
+ import { DataGridBody } from "@versini/ui-datagrid/body";
115
+ import { DataGridRow } from "@versini/ui-datagrid/row";
116
+ import { DataGridCell } from "@versini/ui-datagrid/cell";
117
+ import {
118
+ useInfiniteScroll,
119
+ InfiniteScrollMarker
120
+ } from "@versini/ui-datagrid/infinite";
121
+ import { AnimatedWrapper } from "@versini/ui-datagrid/animated";
122
+
123
+ function MyInfiniteTable({ data }) {
124
+ const { visibleCount, hasMore, markerRef } = useInfiniteScroll({
125
+ totalItems: data.length,
126
+ batchSize: 25
127
+ });
128
+
129
+ const visibleData = data.slice(0, visibleCount);
130
+
131
+ return (
132
+ <AnimatedWrapper dependency={visibleCount}>
133
+ <DataGrid maxHeight="500px" stickyHeader>
134
+ <DataGridHeader>
135
+ <DataGridRow>
136
+ <DataGridCell>Name</DataGridCell>
137
+ <DataGridCell>Date</DataGridCell>
138
+ </DataGridRow>
139
+ </DataGridHeader>
140
+ <DataGridBody>
141
+ {visibleData.map((item) => (
142
+ <DataGridRow key={item.id}>
143
+ <DataGridCell>{item.name}</DataGridCell>
144
+ <DataGridCell>{item.date}</DataGridCell>
145
+ </DataGridRow>
146
+ ))}
147
+ {hasMore && <InfiniteScrollMarker ref={markerRef} colSpan={2} />}
148
+ </DataGridBody>
149
+ </DataGrid>
150
+ </AnimatedWrapper>
151
+ );
152
+ }
153
+ ```
154
+
155
+ ## Virtualization for Large Datasets
156
+
157
+ For datasets with 1000+ rows, use true virtualization:
158
+
159
+ ```tsx
160
+ import { VirtualDataGrid } from "@versini/ui-datagrid/virtual";
161
+
162
+ function MyVirtualTable({ data }) {
163
+ return (
164
+ <VirtualDataGrid
165
+ data={data}
166
+ height="500px"
167
+ columns={[
168
+ { id: "name", header: "Name", cell: (item) => item.name },
169
+ { id: "email", header: "Email", cell: (item) => item.email },
170
+ { id: "date", header: "Date", cell: (item) => formatDate(item.date) }
171
+ ]}
172
+ getRowKey={(item) => item.id}
173
+ estimateSize={48}
174
+ overscan={10}
175
+ />
176
+ );
177
+ }
178
+ ```
179
+
180
+ ## Sorting
181
+
182
+ ```tsx
183
+ import { useState, useMemo } from "react";
184
+ import { DataGrid } from "@versini/ui-datagrid/datagrid";
185
+ import { DataGridHeader } from "@versini/ui-datagrid/header";
186
+ import { DataGridBody } from "@versini/ui-datagrid/body";
187
+ import { DataGridRow } from "@versini/ui-datagrid/row";
188
+ import { DataGridCell } from "@versini/ui-datagrid/cell";
189
+ import { DataGridCellSort } from "@versini/ui-datagrid/cell-sort";
190
+ import {
191
+ sortItems,
192
+ getNextSortConfig,
193
+ SortDirections
194
+ } from "@versini/ui-datagrid/sorting";
195
+
196
+ function MySortableTable({ data }) {
197
+ const [sortConfig, setSortConfig] = useState({
198
+ sortedCell: "name",
199
+ sortDirection: SortDirections.ASC
200
+ });
201
+
202
+ const sortedData = useMemo(() => {
203
+ return sortItems(
204
+ data,
205
+ sortConfig.sortedCell,
206
+ sortConfig.sortDirection,
207
+ "string"
208
+ );
209
+ }, [data, sortConfig]);
210
+
211
+ const handleSort = (cellId) => {
212
+ setSortConfig(getNextSortConfig(sortConfig, cellId));
213
+ };
214
+
215
+ return (
216
+ <DataGrid>
217
+ <DataGridHeader>
218
+ <DataGridRow>
219
+ <DataGridCellSort
220
+ cellId="name"
221
+ onSort={handleSort}
222
+ sortDirection={
223
+ sortConfig.sortedCell === "name"
224
+ ? sortConfig.sortDirection
225
+ : false
226
+ }
227
+ sortedCell={sortConfig.sortedCell}
228
+ >
229
+ Name
230
+ </DataGridCellSort>
231
+ <DataGridCellSort
232
+ cellId="date"
233
+ onSort={handleSort}
234
+ sortDirection={
235
+ sortConfig.sortedCell === "date"
236
+ ? sortConfig.sortDirection
237
+ : false
238
+ }
239
+ sortedCell={sortConfig.sortedCell}
240
+ >
241
+ Date
242
+ </DataGridCellSort>
243
+ </DataGridRow>
244
+ </DataGridHeader>
245
+ <DataGridBody>
246
+ {sortedData.map((item) => (
247
+ <DataGridRow key={item.id}>
248
+ <DataGridCell>{item.name}</DataGridCell>
249
+ <DataGridCell>{item.date}</DataGridCell>
250
+ </DataGridRow>
251
+ ))}
252
+ </DataGridBody>
253
+ </DataGrid>
254
+ );
255
+ }
256
+ ```
257
+
258
+ ## Props
259
+
260
+ ### DataGrid
261
+
262
+ | Prop | Type | Default | Description |
263
+ | -------------- | ----------------------------------------------- | ---------- | ---------------------------------- |
264
+ | `mode` | `'dark' \| 'light' \| 'system' \| 'alt-system'` | `'system'` | Theme mode |
265
+ | `compact` | `boolean` | `false` | Reduced padding |
266
+ | `stickyHeader` | `boolean` | `false` | Fixed header while scrolling |
267
+ | `stickyFooter` | `boolean` | `false` | Fixed footer while scrolling |
268
+ | `blurEffect` | `'none' \| 'small' \| 'medium' \| 'large'` | `'none'` | Blur intensity for sticky elements |
269
+ | `maxHeight` | `string` | - | Max height (required for sticky) |
270
+ | `disabled` | `boolean` | `false` | Show loading overlay |
271
+ | `caption` | `ReactNode` | - | Table caption for accessibility |
272
+
273
+ ### useInfiniteScroll
274
+
275
+ | Option | Type | Default | Description |
276
+ | ------------ | -------- | ------------ | -------------------------------- |
277
+ | `totalItems` | `number` | **required** | Total number of items |
278
+ | `batchSize` | `number` | `20` | Items to load per batch |
279
+ | `threshold` | `number` | `5` | Items before end to trigger load |
280
+ | `rootMargin` | `string` | `'20px'` | IntersectionObserver margin |
281
+
282
+ ### VirtualDataGrid
283
+
284
+ | Prop | Type | Default | Description |
285
+ | -------------- | ---------------------------- | ------------ | ------------------------------- |
286
+ | `data` | `T[]` | **required** | Array of data items |
287
+ | `columns` | `VirtualDataGridColumn<T>[]` | **required** | Column definitions |
288
+ | `height` | `string \| number` | **required** | Container height |
289
+ | `estimateSize` | `number` | `40` | Estimated row height |
290
+ | `overscan` | `number` | `5` | Rows to render outside viewport |
291
+
292
+ ## License
293
+
294
+ MIT
@@ -0,0 +1,2 @@
1
+ import type { DataGridProps } from "./DataGridTypes";
2
+ export declare const DataGrid: ({ caption, className, wrapperClassName, children, mode, compact, stickyHeader, stickyFooter, blurEffect, maxHeight, disabled, ...rest }: DataGridProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,132 @@
1
+ /*!
2
+ @versini/ui-datagrid v0.1.0
3
+ © 2026 gizmette.com
4
+ */
5
+
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { useId, useMemo } from "react";
8
+ import { BlurEffects } from "../DataGridConstants/DataGridConstants.js";
9
+ import { DataGridContext } from "./DataGridContext.js";
10
+ import { getDataGridClasses } from "./utilities.js";
11
+
12
+ ;// CONCATENATED MODULE: external "react/jsx-runtime"
13
+
14
+ ;// CONCATENATED MODULE: external "react"
15
+
16
+ ;// CONCATENATED MODULE: external "../DataGridConstants/DataGridConstants.js"
17
+
18
+ ;// CONCATENATED MODULE: external "./DataGridContext.js"
19
+
20
+ ;// CONCATENATED MODULE: external "./utilities.js"
21
+
22
+ ;// CONCATENATED MODULE: ./src/DataGrid/DataGrid.tsx
23
+
24
+
25
+
26
+
27
+
28
+ /* =============================================================================
29
+ * DataGrid (main component)
30
+ * ========================================================================== */ const DataGrid = ({ caption, className, wrapperClassName, children, mode = "system", compact = false, stickyHeader = false, stickyFooter = false, blurEffect = BlurEffects.NONE, maxHeight, disabled = false, ...rest })=>{
31
+ const captionId = useId();
32
+ const classes = useMemo(()=>getDataGridClasses({
33
+ mode,
34
+ className,
35
+ wrapperClassName,
36
+ stickyHeader,
37
+ stickyFooter,
38
+ disabled
39
+ }), [
40
+ mode,
41
+ className,
42
+ wrapperClassName,
43
+ stickyHeader,
44
+ stickyFooter,
45
+ disabled
46
+ ]);
47
+ const contextValue = useMemo(()=>({
48
+ mode,
49
+ compact,
50
+ stickyHeader,
51
+ stickyFooter,
52
+ blurEffect,
53
+ disabled
54
+ }), [
55
+ mode,
56
+ compact,
57
+ stickyHeader,
58
+ stickyFooter,
59
+ blurEffect,
60
+ disabled
61
+ ]);
62
+ const wrapperStyle = maxHeight ? {
63
+ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight
64
+ } : undefined;
65
+ /**
66
+ * When sticky header/footer is enabled, use Panel-like structure: - Outer
67
+ * wrapper has overflow-hidden - Scrollable content area in the middle with
68
+ * padding - Header/footer are absolutely positioned.
69
+ */ const hasSticky = stickyHeader || stickyFooter;
70
+ return /*#__PURE__*/ jsx(DataGridContext.Provider, {
71
+ value: contextValue,
72
+ children: /*#__PURE__*/ jsxs("div", {
73
+ className: classes.inner,
74
+ children: [
75
+ disabled && /*#__PURE__*/ jsxs(Fragment, {
76
+ children: [
77
+ /*#__PURE__*/ jsx("div", {
78
+ className: classes.overlay,
79
+ "aria-hidden": "true"
80
+ }),
81
+ /*#__PURE__*/ jsx("div", {
82
+ className: classes.spinnerWrapper,
83
+ children: /*#__PURE__*/ jsx("div", {
84
+ className: classes.spinner,
85
+ role: "status",
86
+ children: /*#__PURE__*/ jsx("span", {
87
+ className: "sr-only",
88
+ children: "Loading..."
89
+ })
90
+ })
91
+ })
92
+ ]
93
+ }),
94
+ /*#__PURE__*/ jsx("div", {
95
+ className: classes.wrapper,
96
+ style: wrapperStyle,
97
+ children: hasSticky ? /*#__PURE__*/ jsx("div", {
98
+ className: classes.scrollableContent,
99
+ style: wrapperStyle,
100
+ children: /*#__PURE__*/ jsxs("table", {
101
+ className: classes.table,
102
+ "aria-describedby": caption ? captionId : undefined,
103
+ ...rest,
104
+ children: [
105
+ caption && /*#__PURE__*/ jsx("caption", {
106
+ id: captionId,
107
+ className: classes.caption,
108
+ children: caption
109
+ }),
110
+ children
111
+ ]
112
+ })
113
+ }) : /*#__PURE__*/ jsxs("table", {
114
+ className: classes.table,
115
+ "aria-describedby": caption ? captionId : undefined,
116
+ ...rest,
117
+ children: [
118
+ caption && /*#__PURE__*/ jsx("caption", {
119
+ id: captionId,
120
+ className: classes.caption,
121
+ children: caption
122
+ }),
123
+ children
124
+ ]
125
+ })
126
+ })
127
+ ]
128
+ })
129
+ });
130
+ };
131
+
132
+ export { DataGrid };
@@ -0,0 +1,2 @@
1
+ import type { DataGridContextValue } from "./DataGridTypes";
2
+ export declare const DataGridContext: import("react").Context<DataGridContextValue>;
@@ -0,0 +1,16 @@
1
+ /*!
2
+ @versini/ui-datagrid v0.1.0
3
+ © 2026 gizmette.com
4
+ */
5
+
6
+ import { createContext } from "react";
7
+
8
+ ;// CONCATENATED MODULE: external "react"
9
+
10
+ ;// CONCATENATED MODULE: ./src/DataGrid/DataGridContext.ts
11
+
12
+ const DataGridContext = createContext({
13
+ mode: "system"
14
+ });
15
+
16
+ export { DataGridContext };
@@ -0,0 +1,2 @@
1
+ export { DataGrid } from "./DataGrid";
2
+ export { DataGridContext } from "./DataGridContext";
@@ -0,0 +1,17 @@
1
+ /*!
2
+ @versini/ui-datagrid v0.1.0
3
+ © 2026 gizmette.com
4
+ */
5
+
6
+ import { DataGrid } from "./DataGrid.js";
7
+ import { DataGridContext } from "./DataGridContext.js";
8
+
9
+ ;// CONCATENATED MODULE: external "./DataGrid.js"
10
+
11
+ ;// CONCATENATED MODULE: external "./DataGridContext.js"
12
+
13
+ ;// CONCATENATED MODULE: ./src/DataGrid/index.ts
14
+
15
+
16
+
17
+ export { DataGrid, DataGridContext };
@@ -0,0 +1,36 @@
1
+ import { type BlurEffect, type ThemeMode } from "../DataGridConstants/DataGridConstants";
2
+ /**
3
+ * Common classes for sticky header/footer with optional blur effect.
4
+ */
5
+ export declare const getStickyBlurClasses: ({ blurEffect, }: {
6
+ blurEffect?: BlurEffect;
7
+ }) => string;
8
+ /**
9
+ * Generates classes for the main DataGrid wrapper and table. When sticky
10
+ * header/footer is enabled, uses the Panel-like approach:
11
+ * - Outer wrapper has overflow-hidden
12
+ * - Scrollable area is a separate inner container
13
+ * - Header/footer are absolutely positioned overlays
14
+ */
15
+ export declare const getDataGridClasses: ({ mode, className, wrapperClassName, stickyHeader, stickyFooter, disabled, }: {
16
+ mode: ThemeMode;
17
+ className?: string;
18
+ disabled?: boolean;
19
+ stickyFooter?: boolean;
20
+ stickyHeader?: boolean;
21
+ wrapperClassName?: string;
22
+ }) => {
23
+ overlay: string;
24
+ inner: string;
25
+ spinnerWrapper: string;
26
+ spinner: string;
27
+ wrapper: string;
28
+ /**
29
+ * Scrollable content area - like Panel's scrollableContent Has padding to
30
+ * make room for absolutely positioned header/footer rounded-[inherit] clips
31
+ * the scrollbar at the rounded corners.
32
+ */
33
+ scrollableContent: string;
34
+ table: string;
35
+ caption: string;
36
+ };
@@ -0,0 +1,99 @@
1
+ /*!
2
+ @versini/ui-datagrid v0.1.0
3
+ © 2026 gizmette.com
4
+ */
5
+
6
+ import clsx from "clsx";
7
+ import { BlurEffects } from "../DataGridConstants/DataGridConstants.js";
8
+
9
+ ;// CONCATENATED MODULE: external "clsx"
10
+
11
+ ;// CONCATENATED MODULE: external "../DataGridConstants/DataGridConstants.js"
12
+
13
+ ;// CONCATENATED MODULE: ./src/DataGrid/utilities.ts
14
+
15
+
16
+ /**
17
+ * Generates classes for the loading spinner.
18
+ */ const getSpinnerClasses = ({ mode })=>{
19
+ return clsx("size-8", "align-[-0.125em]", "border-4", "inline-block animate-spin rounded-full border-solid border-current border-r-transparent motion-reduce:animate-[spin_1.5s_linear_infinite]", {
20
+ "text-copy-dark": mode === "light",
21
+ "text-copy-light": mode === "dark",
22
+ "text-copy-dark dark:text-copy-light": mode === "alt-system",
23
+ "text-copy-light dark:text-copy-dark": mode === "system"
24
+ });
25
+ };
26
+ /**
27
+ * Generates classes for the loading overlay.
28
+ */ const getOverlayClasses = ({ mode })=>{
29
+ return {
30
+ inner: "relative",
31
+ overlay: clsx("absolute inset-0 z-20 cursor-not-allowed", "backdrop-blur-xs bg-white/30 dark:bg-black/30"),
32
+ spinnerWrapper: clsx("absolute z-30 top-0 left-0 right-0 h-[min(100%,100vh)]", "flex items-center justify-center", "pointer-events-none"),
33
+ spinner: getSpinnerClasses({
34
+ mode
35
+ })
36
+ };
37
+ };
38
+ /**
39
+ * Common classes for sticky header/footer with optional blur effect.
40
+ */ const getStickyBlurClasses = ({ blurEffect })=>{
41
+ return clsx({
42
+ "backdrop-blur-sm": blurEffect === BlurEffects.SMALL,
43
+ "backdrop-blur-md": blurEffect === BlurEffects.MEDIUM,
44
+ "backdrop-blur-lg": blurEffect === BlurEffects.LARGE
45
+ });
46
+ };
47
+ /**
48
+ * Generates classes for the main DataGrid wrapper and table. When sticky
49
+ * header/footer is enabled, uses the Panel-like approach:
50
+ * - Outer wrapper has overflow-hidden
51
+ * - Scrollable area is a separate inner container
52
+ * - Header/footer are absolutely positioned overlays
53
+ */ const getDataGridClasses = ({ mode, className, wrapperClassName, stickyHeader, stickyFooter, disabled })=>{
54
+ const overlayClasses = disabled ? getOverlayClasses({
55
+ mode
56
+ }) : null;
57
+ const hasSticky = stickyHeader || stickyFooter;
58
+ return {
59
+ overlay: overlayClasses?.overlay ?? "",
60
+ inner: overlayClasses?.inner ?? "",
61
+ spinnerWrapper: overlayClasses?.spinnerWrapper ?? "",
62
+ spinner: overlayClasses?.spinner ?? "",
63
+ // Outer wrapper - overflow-hidden when sticky, like Panel's outerWrapper.
64
+ wrapper: clsx("not-prose relative w-full rounded-lg shadow-md", {
65
+ "overflow-x-auto": !hasSticky && !disabled,
66
+ "overflow-hidden": hasSticky || disabled,
67
+ "bg-surface-darker": mode === "dark" || mode === "system",
68
+ "bg-surface-light": mode === "light" || mode === "alt-system",
69
+ "dark:bg-surface-light": mode === "system",
70
+ "dark:bg-surface-darker": mode === "alt-system",
71
+ "text-copy-light": mode === "dark",
72
+ "text-copy-dark": mode === "light",
73
+ "text-copy-light dark:text-copy-dark": mode === "system",
74
+ "text-copy-dark dark:text-copy-light": mode === "alt-system"
75
+ }, wrapperClassName),
76
+ /**
77
+ * Scrollable content area - like Panel's scrollableContent Has padding to
78
+ * make room for absolutely positioned header/footer rounded-[inherit] clips
79
+ * the scrollbar at the rounded corners.
80
+ */ scrollableContent: clsx("overflow-y-auto overflow-x-hidden rounded-[inherit]", {
81
+ "pt-10": stickyHeader,
82
+ "pb-10": stickyFooter
83
+ }),
84
+ table: clsx("my-0 w-full text-left text-sm", className, {
85
+ "text-copy-light": mode === "dark",
86
+ "text-copy-dark": mode === "light",
87
+ "text-copy-light dark:text-copy-dark": mode === "system",
88
+ "text-copy-dark dark:text-copy-light": mode === "alt-system"
89
+ }),
90
+ caption: clsx("py-2 text-sm font-bold", {
91
+ "text-copy-light": mode === "dark",
92
+ "text-copy-dark": mode === "light",
93
+ "text-copy-light dark:text-copy-dark": mode === "system",
94
+ "text-copy-dark dark:text-copy-light": mode === "alt-system"
95
+ })
96
+ };
97
+ };
98
+
99
+ export { getDataGridClasses, getStickyBlurClasses };
@@ -0,0 +1,47 @@
1
+ export type AnimatedWrapperProps = {
2
+ /**
3
+ * The content to wrap (typically a DataGrid).
4
+ */
5
+ children: React.ReactNode;
6
+ /**
7
+ * Value that triggers animation when changed. Typically the count of items or
8
+ * a key that changes.
9
+ */
10
+ dependency: unknown;
11
+ /**
12
+ * Animation duration in milliseconds.
13
+ * @default 300
14
+ */
15
+ duration?: number;
16
+ /**
17
+ * Whether animation is enabled.
18
+ * @default true
19
+ */
20
+ enabled?: boolean;
21
+ /**
22
+ * Additional class name for the wrapper.
23
+ */
24
+ className?: string;
25
+ };
26
+ /**
27
+ * Wrapper component that animates height changes when content changes.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * const { visibleCount } = useInfiniteScroll({ totalItems: data.length });
32
+ *
33
+ * return (
34
+ * <AnimatedWrapper dependency={visibleCount}>
35
+ * <DataGrid>
36
+ * <DataGridBody>
37
+ * {data.slice(0, visibleCount).map((item) => (
38
+ * <DataGridRow key={item.id}>...</DataGridRow>
39
+ * ))}
40
+ * </DataGridBody>
41
+ * </DataGrid>
42
+ * </AnimatedWrapper>
43
+ * );
44
+ * ```
45
+ *
46
+ */
47
+ export declare const AnimatedWrapper: ({ children, dependency, duration, enabled, className, }: AnimatedWrapperProps) => import("react/jsx-runtime").JSX.Element;