@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.
- package/LICENSE +21 -0
- package/README.md +294 -0
- package/dist/DataGrid/DataGrid.d.ts +2 -0
- package/dist/DataGrid/DataGrid.js +132 -0
- package/dist/DataGrid/DataGridContext.d.ts +2 -0
- package/dist/DataGrid/DataGridContext.js +16 -0
- package/dist/DataGrid/index.d.ts +2 -0
- package/dist/DataGrid/index.js +17 -0
- package/dist/DataGrid/utilities.d.ts +36 -0
- package/dist/DataGrid/utilities.js +99 -0
- package/dist/DataGridAnimated/AnimatedWrapper.d.ts +47 -0
- package/dist/DataGridAnimated/AnimatedWrapper.js +49 -0
- package/dist/DataGridAnimated/index.d.ts +4 -0
- package/dist/DataGridAnimated/index.js +17 -0
- package/dist/DataGridAnimated/useAnimatedHeight.d.ts +49 -0
- package/dist/DataGridAnimated/useAnimatedHeight.js +131 -0
- package/dist/DataGridBody/DataGridBody.d.ts +2 -0
- package/dist/DataGridBody/DataGridBody.js +38 -0
- package/dist/DataGridBody/index.d.ts +1 -0
- package/dist/DataGridBody/index.js +13 -0
- package/dist/DataGridCell/DataGridCell.d.ts +14 -0
- package/dist/DataGridCell/DataGridCell.js +77 -0
- package/dist/DataGridCell/index.d.ts +1 -0
- package/dist/DataGridCell/index.js +13 -0
- package/dist/DataGridCellSort/DataGridCellSort.d.ts +2 -0
- package/dist/DataGridCellSort/DataGridCellSort.js +107 -0
- package/dist/DataGridCellSort/index.d.ts +1 -0
- package/dist/DataGridCellSort/index.js +13 -0
- package/dist/DataGridConstants/DataGridConstants.d.ts +37 -0
- package/dist/DataGridConstants/DataGridConstants.js +38 -0
- package/dist/DataGridConstants/index.d.ts +1 -0
- package/dist/DataGridConstants/index.js +13 -0
- package/dist/DataGridFooter/DataGridFooter.d.ts +12 -0
- package/dist/DataGridFooter/DataGridFooter.js +81 -0
- package/dist/DataGridFooter/index.d.ts +1 -0
- package/dist/DataGridFooter/index.js +13 -0
- package/dist/DataGridHeader/DataGridHeader.d.ts +13 -0
- package/dist/DataGridHeader/DataGridHeader.js +80 -0
- package/dist/DataGridHeader/index.d.ts +1 -0
- package/dist/DataGridHeader/index.js +13 -0
- package/dist/DataGridInfinite/InfiniteScrollMarker.d.ts +35 -0
- package/dist/DataGridInfinite/InfiniteScrollMarker.js +53 -0
- package/dist/DataGridInfinite/index.d.ts +4 -0
- package/dist/DataGridInfinite/index.js +17 -0
- package/dist/DataGridInfinite/useInfiniteScroll.d.ts +81 -0
- package/dist/DataGridInfinite/useInfiniteScroll.js +117 -0
- package/dist/DataGridRow/DataGridRow.d.ts +2 -0
- package/dist/DataGridRow/DataGridRow.js +75 -0
- package/dist/DataGridRow/index.d.ts +1 -0
- package/dist/DataGridRow/index.js +13 -0
- package/dist/DataGridSorting/index.d.ts +2 -0
- package/dist/DataGridSorting/index.js +18 -0
- package/dist/DataGridSorting/sortingUtils.d.ts +138 -0
- package/dist/DataGridSorting/sortingUtils.js +234 -0
- package/dist/DataGridVirtual/VirtualDataGrid.d.ts +114 -0
- package/dist/DataGridVirtual/VirtualDataGrid.js +181 -0
- package/dist/DataGridVirtual/index.d.ts +6 -0
- package/dist/DataGridVirtual/index.js +22 -0
- package/dist/DataGridVirtual/useVirtualDataGrid.d.ts +112 -0
- package/dist/DataGridVirtual/useVirtualDataGrid.js +89 -0
- package/package.json +103 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import clsx from "clsx";
|
|
8
|
+
import { DataGridContext } from "../DataGrid/DataGridContext.js";
|
|
9
|
+
import { getStickyBlurClasses } from "../DataGrid/utilities.js";
|
|
10
|
+
import { BlurEffects, CellWrapper } from "../DataGridConstants/DataGridConstants.js";
|
|
11
|
+
|
|
12
|
+
;// CONCATENATED MODULE: external "react/jsx-runtime"
|
|
13
|
+
|
|
14
|
+
;// CONCATENATED MODULE: external "clsx"
|
|
15
|
+
|
|
16
|
+
;// CONCATENATED MODULE: external "../DataGrid/DataGridContext.js"
|
|
17
|
+
|
|
18
|
+
;// CONCATENATED MODULE: external "../DataGrid/utilities.js"
|
|
19
|
+
|
|
20
|
+
;// CONCATENATED MODULE: external "../DataGridConstants/DataGridConstants.js"
|
|
21
|
+
|
|
22
|
+
;// CONCATENATED MODULE: ./src/DataGridFooter/DataGridFooter.tsx
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Generates classes for the DataGridFooter.
|
|
30
|
+
*/ const getFooterClasses = ({ className, stickyFooter, mode, blurEffect })=>{
|
|
31
|
+
const hasBlur = blurEffect && blurEffect !== BlurEffects.NONE;
|
|
32
|
+
return clsx({
|
|
33
|
+
/**
|
|
34
|
+
* Absolute positioning like Panel's footer: absolute left-0 right-0 z-20
|
|
35
|
+
* bottom-0 rounded-b-lg to match the wrapper's rounded-lg corners.
|
|
36
|
+
*/ "absolute left-0 right-0 z-20 bottom-0 rounded-b-lg": stickyFooter,
|
|
37
|
+
// Shadow for visual depth (upward glow).
|
|
38
|
+
"shadow-[rgb(190_190_190_/20%)_0_-0.5rem_1rem]": stickyFooter && mode === "dark",
|
|
39
|
+
"shadow-[rgb(190_190_190_/20%)_0_-0.5rem_1rem] dark:shadow-[rgb(65_65_65_/30%)_0_-0.5rem_1rem]": stickyFooter && mode === "system",
|
|
40
|
+
"shadow-[rgb(65_65_65_/30%)_0_-0.5rem_1rem]": stickyFooter && mode === "light",
|
|
41
|
+
"shadow-[rgb(65_65_65_/30%)_0_-0.5rem_1rem] dark:shadow-[rgb(190_190_190_/20%)_0_-0.5rem_1rem]": stickyFooter && mode === "alt-system",
|
|
42
|
+
// Semi-transparent backgrounds for blur effect.
|
|
43
|
+
"bg-table-head-dark/50": hasBlur && stickyFooter && (mode === "dark" || mode === "system"),
|
|
44
|
+
"bg-table-head-light/50": hasBlur && stickyFooter && (mode === "light" || mode === "alt-system"),
|
|
45
|
+
"dark:bg-table-head-light/50": hasBlur && stickyFooter && mode === "system",
|
|
46
|
+
"dark:bg-table-head-dark/50": hasBlur && stickyFooter && mode === "alt-system",
|
|
47
|
+
// Solid backgrounds when no blur effect.
|
|
48
|
+
"bg-table-head-dark": !hasBlur && stickyFooter && (mode === "dark" || mode === "system"),
|
|
49
|
+
"bg-table-head-light": !hasBlur && stickyFooter && (mode === "light" || mode === "alt-system"),
|
|
50
|
+
"dark:bg-table-head-light": !hasBlur && stickyFooter && mode === "system",
|
|
51
|
+
"dark:bg-table-head-dark": !hasBlur && stickyFooter && mode === "alt-system"
|
|
52
|
+
}, stickyFooter && getStickyBlurClasses({
|
|
53
|
+
blurEffect
|
|
54
|
+
}), className);
|
|
55
|
+
};
|
|
56
|
+
/* =============================================================================
|
|
57
|
+
* DataGridFooter
|
|
58
|
+
* ========================================================================== */ const DataGridFooter = ({ className, children, ...rest })=>{
|
|
59
|
+
return /*#__PURE__*/ jsx(DataGridContext.Consumer, {
|
|
60
|
+
children: ({ mode, stickyFooter, blurEffect })=>/*#__PURE__*/ jsx(DataGridContext.Consumer, {
|
|
61
|
+
children: (ctx)=>/*#__PURE__*/ jsx(DataGridContext.Provider, {
|
|
62
|
+
value: {
|
|
63
|
+
...ctx,
|
|
64
|
+
cellWrapper: CellWrapper.FOOTER
|
|
65
|
+
},
|
|
66
|
+
children: /*#__PURE__*/ jsx("tfoot", {
|
|
67
|
+
className: getFooterClasses({
|
|
68
|
+
className,
|
|
69
|
+
stickyFooter,
|
|
70
|
+
mode,
|
|
71
|
+
blurEffect
|
|
72
|
+
}),
|
|
73
|
+
...rest,
|
|
74
|
+
children: children
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { DataGridFooter, getFooterClasses };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DataGridFooter } from "./DataGridFooter";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { DataGridFooter } from "./DataGridFooter.js";
|
|
7
|
+
|
|
8
|
+
;// CONCATENATED MODULE: external "./DataGridFooter.js"
|
|
9
|
+
|
|
10
|
+
;// CONCATENATED MODULE: ./src/DataGridFooter/index.ts
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export { DataGridFooter };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DataGridHeaderProps } from "../DataGrid/DataGridTypes";
|
|
2
|
+
import { type BlurEffect, type ThemeMode } from "../DataGridConstants/DataGridConstants";
|
|
3
|
+
/**
|
|
4
|
+
* Generates classes for the DataGridHeader. Uses absolute positioning like
|
|
5
|
+
* Panel - header floats above the scrollable content.
|
|
6
|
+
*/
|
|
7
|
+
export declare const getHeaderClasses: ({ className, stickyHeader, mode, blurEffect, }: {
|
|
8
|
+
mode: ThemeMode;
|
|
9
|
+
blurEffect?: BlurEffect;
|
|
10
|
+
className?: string;
|
|
11
|
+
stickyHeader?: boolean;
|
|
12
|
+
}) => string;
|
|
13
|
+
export declare const DataGridHeader: ({ className, children, ...rest }: DataGridHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import clsx from "clsx";
|
|
8
|
+
import { DataGridContext } from "../DataGrid/DataGridContext.js";
|
|
9
|
+
import { getStickyBlurClasses } from "../DataGrid/utilities.js";
|
|
10
|
+
import { BlurEffects, CellWrapper } from "../DataGridConstants/DataGridConstants.js";
|
|
11
|
+
|
|
12
|
+
;// CONCATENATED MODULE: external "react/jsx-runtime"
|
|
13
|
+
|
|
14
|
+
;// CONCATENATED MODULE: external "clsx"
|
|
15
|
+
|
|
16
|
+
;// CONCATENATED MODULE: external "../DataGrid/DataGridContext.js"
|
|
17
|
+
|
|
18
|
+
;// CONCATENATED MODULE: external "../DataGrid/utilities.js"
|
|
19
|
+
|
|
20
|
+
;// CONCATENATED MODULE: external "../DataGridConstants/DataGridConstants.js"
|
|
21
|
+
|
|
22
|
+
;// CONCATENATED MODULE: ./src/DataGridHeader/DataGridHeader.tsx
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Generates classes for the DataGridHeader. Uses absolute positioning like
|
|
30
|
+
* Panel - header floats above the scrollable content.
|
|
31
|
+
*/ const getHeaderClasses = ({ className, stickyHeader, mode, blurEffect })=>{
|
|
32
|
+
const hasBlur = blurEffect && blurEffect !== BlurEffects.NONE;
|
|
33
|
+
return clsx({
|
|
34
|
+
/**
|
|
35
|
+
* Absolute positioning like Panel's header: absolute left-0 right-0 z-20
|
|
36
|
+
* top-0 rounded-t-lg to match the wrapper's rounded-lg corners.
|
|
37
|
+
*/ "absolute left-0 right-0 z-20 top-0 rounded-t-lg": stickyHeader,
|
|
38
|
+
// Shadow for visual depth (downward glow).
|
|
39
|
+
"shadow-[rgb(190_190_190_/20%)_0_0.5rem_1rem]": stickyHeader && mode === "dark",
|
|
40
|
+
"shadow-[rgb(190_190_190_/20%)_0_0.5rem_1rem] dark:shadow-[rgb(65_65_65_/30%)_0_0.5rem_1rem]": stickyHeader && mode === "system",
|
|
41
|
+
"shadow-[rgb(65_65_65_/30%)_0_0.5rem_1rem]": stickyHeader && mode === "light",
|
|
42
|
+
"shadow-[rgb(65_65_65_/30%)_0_0.5rem_1rem] dark:shadow-[rgb(190_190_190_/20%)_0_0.5rem_1rem]": stickyHeader && mode === "alt-system",
|
|
43
|
+
// Semi-transparent backgrounds for blur effect.
|
|
44
|
+
"bg-table-head-dark/50": hasBlur && stickyHeader && (mode === "dark" || mode === "system"),
|
|
45
|
+
"bg-table-head-light/50": hasBlur && stickyHeader && (mode === "light" || mode === "alt-system"),
|
|
46
|
+
"dark:bg-table-head-light/50": hasBlur && stickyHeader && mode === "system",
|
|
47
|
+
"dark:bg-table-head-dark/50": hasBlur && stickyHeader && mode === "alt-system",
|
|
48
|
+
// Solid backgrounds when no blur effect.
|
|
49
|
+
"bg-table-head-dark": !hasBlur && stickyHeader && (mode === "dark" || mode === "system"),
|
|
50
|
+
"bg-table-head-light": !hasBlur && stickyHeader && (mode === "light" || mode === "alt-system"),
|
|
51
|
+
"dark:bg-table-head-light": !hasBlur && stickyHeader && mode === "system",
|
|
52
|
+
"dark:bg-table-head-dark": !hasBlur && stickyHeader && mode === "alt-system"
|
|
53
|
+
}, stickyHeader && getStickyBlurClasses({
|
|
54
|
+
blurEffect
|
|
55
|
+
}), className);
|
|
56
|
+
};
|
|
57
|
+
/* =============================================================================
|
|
58
|
+
* DataGridHeader
|
|
59
|
+
* ========================================================================== */ const DataGridHeader = ({ className, children, ...rest })=>{
|
|
60
|
+
return /*#__PURE__*/ jsx(DataGridContext.Consumer, {
|
|
61
|
+
children: (ctx)=>/*#__PURE__*/ jsx(DataGridContext.Provider, {
|
|
62
|
+
value: {
|
|
63
|
+
...ctx,
|
|
64
|
+
cellWrapper: CellWrapper.HEADER
|
|
65
|
+
},
|
|
66
|
+
children: /*#__PURE__*/ jsx("thead", {
|
|
67
|
+
className: getHeaderClasses({
|
|
68
|
+
className,
|
|
69
|
+
stickyHeader: ctx.stickyHeader,
|
|
70
|
+
mode: ctx.mode,
|
|
71
|
+
blurEffect: ctx.blurEffect
|
|
72
|
+
}),
|
|
73
|
+
...rest,
|
|
74
|
+
children: children
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export { DataGridHeader, getHeaderClasses };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DataGridHeader } from "./DataGridHeader";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { DataGridHeader } from "./DataGridHeader.js";
|
|
7
|
+
|
|
8
|
+
;// CONCATENATED MODULE: external "./DataGridHeader.js"
|
|
9
|
+
|
|
10
|
+
;// CONCATENATED MODULE: ./src/DataGridHeader/index.ts
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export { DataGridHeader };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type InfiniteScrollMarkerProps = {
|
|
2
|
+
/**
|
|
3
|
+
* Number of columns in the table (for proper colspan).
|
|
4
|
+
*/
|
|
5
|
+
colSpan?: number;
|
|
6
|
+
/**
|
|
7
|
+
* Custom class name for the row.
|
|
8
|
+
*/
|
|
9
|
+
className?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to show the marker (for debugging). In production, the marker is
|
|
12
|
+
* invisible.
|
|
13
|
+
*/
|
|
14
|
+
debug?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Invisible marker row for infinite scroll. Place this at the end of your
|
|
18
|
+
* DataGridBody.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { hasMore, markerRef } = useInfiniteScroll({ totalItems: data.length });
|
|
23
|
+
*
|
|
24
|
+
* return (
|
|
25
|
+
* <DataGridBody>
|
|
26
|
+
* {data.slice(0, visibleCount).map((item) => (
|
|
27
|
+
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
28
|
+
* ))}
|
|
29
|
+
* {hasMore && <InfiniteScrollMarker ref={markerRef} colSpan={5} />}
|
|
30
|
+
* </DataGridBody>
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
export declare const InfiniteScrollMarker: import("react").ForwardRefExoticComponent<InfiniteScrollMarkerProps & import("react").RefAttributes<HTMLTableRowElement>>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import { forwardRef } from "react";
|
|
8
|
+
|
|
9
|
+
;// CONCATENATED MODULE: external "react/jsx-runtime"
|
|
10
|
+
|
|
11
|
+
;// CONCATENATED MODULE: external "react"
|
|
12
|
+
|
|
13
|
+
;// CONCATENATED MODULE: ./src/DataGridInfinite/InfiniteScrollMarker.tsx
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Invisible marker row for infinite scroll. Place this at the end of your
|
|
18
|
+
* DataGridBody.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { hasMore, markerRef } = useInfiniteScroll({ totalItems: data.length });
|
|
23
|
+
*
|
|
24
|
+
* return (
|
|
25
|
+
* <DataGridBody>
|
|
26
|
+
* {data.slice(0, visibleCount).map((item) => (
|
|
27
|
+
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
28
|
+
* ))}
|
|
29
|
+
* {hasMore && <InfiniteScrollMarker ref={markerRef} colSpan={5} />}
|
|
30
|
+
* </DataGridBody>
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
*/ const InfiniteScrollMarker_InfiniteScrollMarker = /*#__PURE__*/ forwardRef(function InfiniteScrollMarker({ colSpan = 1, className, debug = false }, ref) {
|
|
35
|
+
return /*#__PURE__*/ jsx("tr", {
|
|
36
|
+
ref: ref,
|
|
37
|
+
className: className,
|
|
38
|
+
"aria-hidden": "true",
|
|
39
|
+
style: {
|
|
40
|
+
height: debug ? "40px" : "1px",
|
|
41
|
+
background: debug ? "red" : "transparent"
|
|
42
|
+
},
|
|
43
|
+
children: /*#__PURE__*/ jsx("td", {
|
|
44
|
+
colSpan: colSpan,
|
|
45
|
+
style: {
|
|
46
|
+
padding: 0,
|
|
47
|
+
border: 0
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export { InfiniteScrollMarker_InfiniteScrollMarker as InfiniteScrollMarker };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { InfiniteScrollMarkerProps } from "./InfiniteScrollMarker";
|
|
2
|
+
export { InfiniteScrollMarker } from "./InfiniteScrollMarker";
|
|
3
|
+
export type { UseInfiniteScrollOptions, UseInfiniteScrollReturn, } from "./useInfiniteScroll";
|
|
4
|
+
export { useInfiniteScroll } from "./useInfiniteScroll";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { InfiniteScrollMarker } from "./InfiniteScrollMarker.js";
|
|
7
|
+
import { useInfiniteScroll } from "./useInfiniteScroll.js";
|
|
8
|
+
|
|
9
|
+
;// CONCATENATED MODULE: external "./InfiniteScrollMarker.js"
|
|
10
|
+
|
|
11
|
+
;// CONCATENATED MODULE: external "./useInfiniteScroll.js"
|
|
12
|
+
|
|
13
|
+
;// CONCATENATED MODULE: ./src/DataGridInfinite/index.ts
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
export { InfiniteScrollMarker, useInfiniteScroll };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export type UseInfiniteScrollOptions = {
|
|
2
|
+
/**
|
|
3
|
+
* Number of items to show initially and to add on each scroll.
|
|
4
|
+
* @default 20
|
|
5
|
+
*/
|
|
6
|
+
batchSize?: number;
|
|
7
|
+
/**
|
|
8
|
+
* How many items before the end to trigger loading more.
|
|
9
|
+
* @default 5
|
|
10
|
+
*/
|
|
11
|
+
threshold?: number;
|
|
12
|
+
/**
|
|
13
|
+
* IntersectionObserver root margin.
|
|
14
|
+
* @default "20px"
|
|
15
|
+
*/
|
|
16
|
+
rootMargin?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Total number of items in the dataset. Used to determine if more items can be
|
|
19
|
+
* loaded.
|
|
20
|
+
*/
|
|
21
|
+
totalItems: number;
|
|
22
|
+
/**
|
|
23
|
+
* Initial number of visible items (optional). If not provided, uses batchSize.
|
|
24
|
+
* + threshold.
|
|
25
|
+
*/
|
|
26
|
+
initialVisibleCount?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Callback when more items are loaded.
|
|
29
|
+
*/
|
|
30
|
+
onLoadMore?: (newVisibleCount: number) => void;
|
|
31
|
+
};
|
|
32
|
+
export type UseInfiniteScrollReturn = {
|
|
33
|
+
/**
|
|
34
|
+
* Current number of visible items.
|
|
35
|
+
*/
|
|
36
|
+
visibleCount: number;
|
|
37
|
+
/**
|
|
38
|
+
* Whether there are more items to load.
|
|
39
|
+
*/
|
|
40
|
+
hasMore: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Callback ref to attach to the marker element.
|
|
43
|
+
*/
|
|
44
|
+
markerRef: (node: HTMLElement | null) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Reset visible count to initial value.
|
|
47
|
+
*/
|
|
48
|
+
reset: () => void;
|
|
49
|
+
/**
|
|
50
|
+
* Manually set the visible count (useful for scroll-to-item).
|
|
51
|
+
*/
|
|
52
|
+
setVisibleCount: React.Dispatch<React.SetStateAction<number>>;
|
|
53
|
+
/**
|
|
54
|
+
* Expand visible count to include a specific index.
|
|
55
|
+
*/
|
|
56
|
+
expandToInclude: (index: number) => void;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Hook for implementing infinite scroll with IntersectionObserver.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* const { visibleCount, hasMore, markerRef } = useInfiniteScroll({
|
|
64
|
+
* totalItems: data.length,
|
|
65
|
+
* batchSize: 25,
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* return (
|
|
69
|
+
* <DataGrid>
|
|
70
|
+
* <DataGridBody>
|
|
71
|
+
* {data.slice(0, visibleCount).map((item, index) => (
|
|
72
|
+
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
73
|
+
* ))}
|
|
74
|
+
* {hasMore && <InfiniteScrollMarker ref={markerRef} />}
|
|
75
|
+
* </DataGridBody>
|
|
76
|
+
* </DataGrid>
|
|
77
|
+
* );
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
export declare function useInfiniteScroll({ batchSize, threshold, rootMargin, totalItems, initialVisibleCount, onLoadMore, }: UseInfiniteScrollOptions): UseInfiniteScrollReturn;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
7
|
+
|
|
8
|
+
;// CONCATENATED MODULE: external "react"
|
|
9
|
+
|
|
10
|
+
;// CONCATENATED MODULE: ./src/DataGridInfinite/useInfiniteScroll.ts
|
|
11
|
+
|
|
12
|
+
const DEFAULT_BATCH_SIZE = 20;
|
|
13
|
+
const DEFAULT_THRESHOLD = 5;
|
|
14
|
+
const DEFAULT_ROOT_MARGIN = "20px";
|
|
15
|
+
/**
|
|
16
|
+
* Hook for implementing infinite scroll with IntersectionObserver.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const { visibleCount, hasMore, markerRef } = useInfiniteScroll({
|
|
21
|
+
* totalItems: data.length,
|
|
22
|
+
* batchSize: 25,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* return (
|
|
26
|
+
* <DataGrid>
|
|
27
|
+
* <DataGridBody>
|
|
28
|
+
* {data.slice(0, visibleCount).map((item, index) => (
|
|
29
|
+
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
30
|
+
* ))}
|
|
31
|
+
* {hasMore && <InfiniteScrollMarker ref={markerRef} />}
|
|
32
|
+
* </DataGridBody>
|
|
33
|
+
* </DataGrid>
|
|
34
|
+
* );
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
*/ function useInfiniteScroll({ batchSize = DEFAULT_BATCH_SIZE, threshold = DEFAULT_THRESHOLD, rootMargin = DEFAULT_ROOT_MARGIN, totalItems, initialVisibleCount, onLoadMore }) {
|
|
38
|
+
const observerRef = useRef(null);
|
|
39
|
+
const initialCount = initialVisibleCount ?? batchSize + threshold;
|
|
40
|
+
const [visibleCount, setVisibleCount] = useState(Math.min(initialCount, totalItems));
|
|
41
|
+
const hasMore = visibleCount < totalItems;
|
|
42
|
+
/**
|
|
43
|
+
* IntersectionObserver callback - triggered when marker becomes visible.
|
|
44
|
+
*/ const handleIntersection = useCallback((entries)=>{
|
|
45
|
+
const target = entries[0];
|
|
46
|
+
if (target?.isIntersecting) {
|
|
47
|
+
setVisibleCount((prev)=>{
|
|
48
|
+
const newCount = Math.min(prev + batchSize, totalItems);
|
|
49
|
+
if (onLoadMore && newCount > prev) {
|
|
50
|
+
onLoadMore(newCount);
|
|
51
|
+
}
|
|
52
|
+
return newCount;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}, [
|
|
56
|
+
batchSize,
|
|
57
|
+
totalItems,
|
|
58
|
+
onLoadMore
|
|
59
|
+
]);
|
|
60
|
+
/**
|
|
61
|
+
* Callback ref for the marker element. Creates/disconnects observer as needed.
|
|
62
|
+
*/ const markerRef = useCallback((node)=>{
|
|
63
|
+
// Disconnect previous observer.
|
|
64
|
+
if (observerRef.current) {
|
|
65
|
+
observerRef.current.disconnect();
|
|
66
|
+
observerRef.current = null;
|
|
67
|
+
}
|
|
68
|
+
if (node && typeof IntersectionObserver !== "undefined") {
|
|
69
|
+
const options = {
|
|
70
|
+
rootMargin
|
|
71
|
+
};
|
|
72
|
+
observerRef.current = new IntersectionObserver(handleIntersection, options);
|
|
73
|
+
observerRef.current.observe(node);
|
|
74
|
+
}
|
|
75
|
+
}, [
|
|
76
|
+
handleIntersection,
|
|
77
|
+
rootMargin
|
|
78
|
+
]);
|
|
79
|
+
/**
|
|
80
|
+
* Reset to initial count.
|
|
81
|
+
*/ const reset = useCallback(()=>{
|
|
82
|
+
setVisibleCount(Math.min(initialCount, totalItems));
|
|
83
|
+
}, [
|
|
84
|
+
initialCount,
|
|
85
|
+
totalItems
|
|
86
|
+
]);
|
|
87
|
+
/**
|
|
88
|
+
* Expand visible count to include a specific index. Useful for scroll-to-row
|
|
89
|
+
* functionality.
|
|
90
|
+
*/ const expandToInclude = useCallback((index)=>{
|
|
91
|
+
if (index >= visibleCount) {
|
|
92
|
+
setVisibleCount(index + threshold);
|
|
93
|
+
}
|
|
94
|
+
}, [
|
|
95
|
+
visibleCount,
|
|
96
|
+
threshold
|
|
97
|
+
]);
|
|
98
|
+
/**
|
|
99
|
+
* Cleanup observer on unmount.
|
|
100
|
+
*/ useEffect(()=>{
|
|
101
|
+
return ()=>{
|
|
102
|
+
if (observerRef.current) {
|
|
103
|
+
observerRef.current.disconnect();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}, []);
|
|
107
|
+
return {
|
|
108
|
+
visibleCount,
|
|
109
|
+
hasMore,
|
|
110
|
+
markerRef,
|
|
111
|
+
reset,
|
|
112
|
+
setVisibleCount,
|
|
113
|
+
expandToInclude
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export { useInfiniteScroll };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import clsx from "clsx";
|
|
8
|
+
import { DataGridContext } from "../DataGrid/DataGridContext.js";
|
|
9
|
+
import { CellWrapper } from "../DataGridConstants/index.js";
|
|
10
|
+
|
|
11
|
+
;// CONCATENATED MODULE: external "react/jsx-runtime"
|
|
12
|
+
|
|
13
|
+
;// CONCATENATED MODULE: external "clsx"
|
|
14
|
+
|
|
15
|
+
;// CONCATENATED MODULE: external "../DataGrid/DataGridContext.js"
|
|
16
|
+
|
|
17
|
+
;// CONCATENATED MODULE: external "../DataGridConstants/index.js"
|
|
18
|
+
|
|
19
|
+
;// CONCATENATED MODULE: ./src/DataGridRow/DataGridRow.tsx
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
const getRowClasses = ({ mode, className, cellWrapper, stickyHeader, stickyFooter })=>{
|
|
25
|
+
if (cellWrapper === CellWrapper.HEADER || cellWrapper === CellWrapper.FOOTER) {
|
|
26
|
+
/**
|
|
27
|
+
* When in a sticky header/footer, don't apply background to row since the
|
|
28
|
+
* background is applied to thead/tfoot for blur effect to work.
|
|
29
|
+
*/ const isSticky = cellWrapper === CellWrapper.HEADER && stickyHeader || cellWrapper === CellWrapper.FOOTER && stickyFooter;
|
|
30
|
+
if (isSticky) {
|
|
31
|
+
// No background on row - it's on the thead/tfoot.
|
|
32
|
+
return clsx(className);
|
|
33
|
+
}
|
|
34
|
+
// Non-sticky header/footer still gets background on row.
|
|
35
|
+
return clsx({
|
|
36
|
+
"bg-table-head-dark": mode === "dark" || mode === "system",
|
|
37
|
+
"bg-table-head-light": mode === "light" || mode === "alt-system",
|
|
38
|
+
"dark:bg-table-head-light": mode === "system",
|
|
39
|
+
"dark:bg-table-head-dark": mode === "alt-system"
|
|
40
|
+
}, className);
|
|
41
|
+
}
|
|
42
|
+
return clsx("border-b last:border-0", {
|
|
43
|
+
"border-table-dark": mode === "dark" || mode === "system",
|
|
44
|
+
"border-table-light": mode === "light" || mode === "alt-system",
|
|
45
|
+
"dark:border-table-light": mode === "system",
|
|
46
|
+
"dark:border-table-dark": mode === "alt-system",
|
|
47
|
+
"odd:bg-table-dark-odd even:bg-table-dark-even": mode === "dark",
|
|
48
|
+
"hover:bg-table-dark-hover": mode === "dark",
|
|
49
|
+
"odd:bg-table-light-odd even:bg-table-light-even": mode === "light",
|
|
50
|
+
"hover:bg-table-light-hover": mode === "light",
|
|
51
|
+
"odd:bg-table-dark-odd even:bg-table-dark-even dark:odd:bg-table-light-odd dark:even:bg-table-light-even": mode === "system",
|
|
52
|
+
"hover:bg-table-dark-hover dark:hover:bg-table-light-hover": mode === "system",
|
|
53
|
+
"odd:bg-table-light-odd even:bg-table-light-even dark:odd:bg-table-dark-odd dark:even:bg-table-dark-even": mode === "alt-system",
|
|
54
|
+
"hover:bg-table-light-hover dark:hover:bg-table-dark-hover": mode === "alt-system"
|
|
55
|
+
}, className);
|
|
56
|
+
};
|
|
57
|
+
/* =============================================================================
|
|
58
|
+
* DataGridRow
|
|
59
|
+
* ========================================================================== */ const DataGridRow = ({ className, children, ...rest })=>{
|
|
60
|
+
return /*#__PURE__*/ jsx(DataGridContext.Consumer, {
|
|
61
|
+
children: ({ mode, cellWrapper, stickyHeader, stickyFooter })=>/*#__PURE__*/ jsx("tr", {
|
|
62
|
+
className: getRowClasses({
|
|
63
|
+
mode,
|
|
64
|
+
className,
|
|
65
|
+
cellWrapper,
|
|
66
|
+
stickyHeader,
|
|
67
|
+
stickyFooter
|
|
68
|
+
}),
|
|
69
|
+
...rest,
|
|
70
|
+
children: children
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export { DataGridRow };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DataGridRow } from "./DataGridRow";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { DataGridRow } from "./DataGridRow.js";
|
|
7
|
+
|
|
8
|
+
;// CONCATENATED MODULE: external "./DataGridRow.js"
|
|
9
|
+
|
|
10
|
+
;// CONCATENATED MODULE: ./src/DataGridRow/index.ts
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export { DataGridRow };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { type SortDirection, SortDirections } from "../DataGridConstants";
|
|
2
|
+
export { getNextSortConfig, getOppositeSortDirection, type SortComparator, type SortConfig, sortByBoolean, sortByDate, sortByNumber, sortByString, sortItems, toggleSortDirection, } from "./sortingUtils";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
@versini/ui-datagrid v0.1.0
|
|
3
|
+
© 2026 gizmette.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { SortDirections } from "../DataGridConstants/index.js";
|
|
7
|
+
import { getNextSortConfig, getOppositeSortDirection, sortByBoolean, sortByDate, sortByNumber, sortByString, sortItems, toggleSortDirection } from "./sortingUtils.js";
|
|
8
|
+
|
|
9
|
+
;// CONCATENATED MODULE: external "../DataGridConstants/index.js"
|
|
10
|
+
|
|
11
|
+
;// CONCATENATED MODULE: external "./sortingUtils.js"
|
|
12
|
+
|
|
13
|
+
;// CONCATENATED MODULE: ./src/DataGridSorting/index.ts
|
|
14
|
+
// Re-export sort directions from constants for convenience.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export { SortDirections, getNextSortConfig, getOppositeSortDirection, sortByBoolean, sortByDate, sortByNumber, sortByString, sortItems, toggleSortDirection };
|