@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
@@ -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,2 @@
1
+ import type { DataGridRowProps } from "../DataGrid/DataGridTypes";
2
+ export declare const DataGridRow: ({ className, children, ...rest }: DataGridRowProps) => import("react/jsx-runtime").JSX.Element;
@@ -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 };