@pega/lists-react 9.0.0-build.6.9 → 9.0.0-build.7.1

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 (80) hide show
  1. package/lib/Core/Components/ContextMenu/ContextMenuContainer.d.ts.map +1 -1
  2. package/lib/Core/Components/ContextMenu/ContextMenuContainer.js +4 -2
  3. package/lib/Core/Components/ContextMenu/ContextMenuContainer.js.map +1 -1
  4. package/lib/Core/Components/Grouping/GroupingMenu.js +1 -1
  5. package/lib/Core/Components/Grouping/GroupingMenu.js.map +1 -1
  6. package/lib/Core/Components/Toolbar/AdvanceToolbar.d.ts.map +1 -1
  7. package/lib/Core/Components/Toolbar/AdvanceToolbar.js +3 -16
  8. package/lib/Core/Components/Toolbar/AdvanceToolbar.js.map +1 -1
  9. package/lib/Core/Components/Toolbar/SimpleToolbar.d.ts.map +1 -1
  10. package/lib/Core/Components/Toolbar/SimpleToolbar.js +3 -1
  11. package/lib/Core/Components/Toolbar/SimpleToolbar.js.map +1 -1
  12. package/lib/Core/Components/Toolbar/hooks/useGroup/DateFunctionSelector.js +1 -1
  13. package/lib/Core/Components/Toolbar/hooks/useGroup/DateFunctionSelector.js.map +1 -1
  14. package/lib/Core/Components/Toolbar/hooks/useGroup/GroupRenderer.js +1 -1
  15. package/lib/Core/Components/Toolbar/hooks/useGroup/GroupRenderer.js.map +1 -1
  16. package/lib/Core/Components/Toolbar/hooks/useSort/Row.js +1 -1
  17. package/lib/Core/Components/Toolbar/hooks/useSort/Row.js.map +1 -1
  18. package/lib/Core/Components/Toolbar/hooks/useWrapAction.d.ts +6 -0
  19. package/lib/Core/Components/Toolbar/hooks/useWrapAction.d.ts.map +1 -0
  20. package/lib/Core/Components/Toolbar/hooks/useWrapAction.js +17 -0
  21. package/lib/Core/Components/Toolbar/hooks/useWrapAction.js.map +1 -0
  22. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/VariableHeightVirtualizer.d.ts +97 -0
  23. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/VariableHeightVirtualizer.d.ts.map +1 -0
  24. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/VariableHeightVirtualizer.js +249 -0
  25. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/VariableHeightVirtualizer.js.map +1 -0
  26. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useChildrenHeightResizeObserver.d.ts +22 -0
  27. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useChildrenHeightResizeObserver.d.ts.map +1 -0
  28. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useChildrenHeightResizeObserver.js +38 -0
  29. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useChildrenHeightResizeObserver.js.map +1 -0
  30. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useLoaderPositioning.d.ts +22 -0
  31. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useLoaderPositioning.d.ts.map +1 -0
  32. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useLoaderPositioning.js +45 -0
  33. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useLoaderPositioning.js.map +1 -0
  34. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/usePagination.d.ts +49 -0
  35. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/usePagination.d.ts.map +1 -0
  36. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/usePagination.js +55 -0
  37. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/usePagination.js.map +1 -0
  38. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useScroll.d.ts +21 -0
  39. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useScroll.d.ts.map +1 -0
  40. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useScroll.js +39 -0
  41. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useScroll.js.map +1 -0
  42. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useVirtualizerItemCount.d.ts +38 -0
  43. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useVirtualizerItemCount.d.ts.map +1 -0
  44. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useVirtualizerItemCount.js +62 -0
  45. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/useVirtualizerItemCount.js.map +1 -0
  46. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/utils.d.ts +112 -0
  47. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/utils.d.ts.map +1 -0
  48. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/utils.js +213 -0
  49. package/lib/Core/Components/Virtualise/VariableHeightVirtualizer/utils.js.map +1 -0
  50. package/lib/Core/Components/Virtualise/index.js +3 -11
  51. package/lib/Core/Components/Virtualise/index.js.map +1 -1
  52. package/lib/Core/Components/Virtualise/utility.d.ts +1 -1
  53. package/lib/Core/Components/Virtualise/utility.d.ts.map +1 -1
  54. package/lib/Core/Components/Virtualise/utility.js +3 -2
  55. package/lib/Core/Components/Virtualise/utility.js.map +1 -1
  56. package/lib/Core/Hooks/useDragDrop.d.ts.map +1 -1
  57. package/lib/Core/Hooks/useDragDrop.js +2 -0
  58. package/lib/Core/Hooks/useDragDrop.js.map +1 -1
  59. package/lib/Core/Views/Gallery/StyledGalleryContainer.d.ts.map +1 -1
  60. package/lib/Core/Views/Gallery/StyledGalleryContainer.js +1 -0
  61. package/lib/Core/Views/Gallery/StyledGalleryContainer.js.map +1 -1
  62. package/lib/Core/Views/Table/Row.d.ts +3 -1
  63. package/lib/Core/Views/Table/Row.d.ts.map +1 -1
  64. package/lib/Core/Views/Table/Row.js +5 -3
  65. package/lib/Core/Views/Table/Row.js.map +1 -1
  66. package/lib/Core/Views/Table/StyledTableContainer.d.ts.map +1 -1
  67. package/lib/Core/Views/Table/StyledTableContainer.js +4 -0
  68. package/lib/Core/Views/Table/StyledTableContainer.js.map +1 -1
  69. package/lib/Core/Views/Table/VirtualizeWrapper.d.ts +3 -1
  70. package/lib/Core/Views/Table/VirtualizeWrapper.d.ts.map +1 -1
  71. package/lib/Core/Views/Table/VirtualizeWrapper.js +18 -2
  72. package/lib/Core/Views/Table/VirtualizeWrapper.js.map +1 -1
  73. package/lib/Core/Views/Table/index.d.ts.map +1 -1
  74. package/lib/Core/Views/Table/index.js +2 -2
  75. package/lib/Core/Views/Table/index.js.map +1 -1
  76. package/lib/Core/Views/Table/useCountChange.d.ts +10 -0
  77. package/lib/Core/Views/Table/useCountChange.d.ts.map +1 -0
  78. package/lib/Core/Views/Table/useCountChange.js +39 -0
  79. package/lib/Core/Views/Table/useCountChange.js.map +1 -0
  80. package/package.json +8 -8
@@ -0,0 +1,97 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface ItemsHeight {
3
+ [index: number]: number;
4
+ }
5
+ export interface LoadedDataRange {
6
+ startIndex?: number;
7
+ endIndex?: number;
8
+ }
9
+ export interface VariableHeightVirtualizerProps {
10
+ /** Unique identifier for the virtualizer instance. */
11
+ id: string;
12
+ /** The React children elements to render inside the virtualizer. */
13
+ children: ReactNode;
14
+ /** Callback to fetch paginated data. */
15
+ apiCallback: (params: {
16
+ startIndex: number;
17
+ endIndex: number;
18
+ id: string;
19
+ }, options: {
20
+ takeLatestAction: boolean;
21
+ }) => void;
22
+ /** Indicates if data is currently being fetched. */
23
+ isDataFetching: boolean;
24
+ /** Range of data that is already loaded. */
25
+ loadedDataRange: LoadedDataRange;
26
+ /** Default height for items if not measured. */
27
+ defaultItemHeight?: number;
28
+ /** Total number of items in the list. */
29
+ totalItemCount?: number | null;
30
+ /** Number of items to buffer before/after the visible range. */
31
+ buffer?: number;
32
+ /** Maximum number of items to render at once. */
33
+ maxItemsToPaint?: number;
34
+ /** Function to render the header. */
35
+ headerRenderer?: (() => ReactNode) | null;
36
+ /** Function to render the footer. */
37
+ footerRenderer?: (() => ReactNode) | null;
38
+ /** Function to render the no-result state. */
39
+ noResultRenderer?: (() => ReactNode) | null;
40
+ /** CSS class for the item container. */
41
+ itemContainerClass?: string;
42
+ /** Maximum height for the view container. */
43
+ viewMaxHeight?: string | number | null;
44
+ /** Minimum height for the view container. */
45
+ minHeight?: string | number;
46
+ /** Minimum height when no items are rendered. */
47
+ minHeightWhenNoItemsRendered?: string;
48
+ }
49
+ interface VirtualizerRef {
50
+ /** Scrolls the parent container to the top. */
51
+ scrollToTop: () => void;
52
+ /** Returns the parent container element. */
53
+ getParentContainer: () => HTMLElement | null;
54
+ /** Returns the buffer container element. */
55
+ getBufferContainer: () => HTMLElement | null;
56
+ /** Triggers a count change notification. */
57
+ notifyCountChange: () => void;
58
+ }
59
+ /**
60
+ * Flow:
61
+ * 1. First load/user scrolls/screen size change/column resize
62
+ * 2. Calculate new pagination range based on scroll position or if view not filled
63
+ * 3. Consumer executes API call to fetch new data
64
+ * 4. New items are prepared and rendered
65
+ * 5. Update cache of item heights
66
+ * 6. Update buffer height
67
+ * 7. Adjust itemContainer top
68
+ * 8. Adjust scrollTop (if needed) to keep the items at same position visually
69
+ */
70
+ /**
71
+ * VariableHeightVirtualizer is a React component that efficiently renders large lists with items of variable heights,
72
+ * using virtualization techniques to minimize DOM nodes and improve performance.
73
+ *
74
+ * @param props - {@link VariableHeightVirtualizerProps}
75
+ * @param ref - Forwarded ref exposing imperative APIs: scrollToTop, getParentContainer, getBufferContainer, notifyCountChange.
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * <VariableHeightVirtualizer
80
+ * id="my-list"
81
+ * totalItemCount={10000}
82
+ * loadedDataRange={{ startIndex: 0, endIndex: 49 }}
83
+ * isDataFetching={isLoading}
84
+ * apiCallback={fetchData}
85
+ * defaultItemHeight={40}
86
+ * buffer={10}
87
+ * headerRenderer={() => <Header />}
88
+ * footerRenderer={() => <Footer />}
89
+ * noResultRenderer={() => <NoResults />}
90
+ * >
91
+ * {items.map(item => <ListItem key={item.id} {...item} />)}
92
+ * </VariableHeightVirtualizer>
93
+ * ```
94
+ */
95
+ declare const VariableHeightVirtualizer: import("react").ForwardRefExoticComponent<VariableHeightVirtualizerProps & import("react").RefAttributes<VirtualizerRef>>;
96
+ export default VariableHeightVirtualizer;
97
+ //# sourceMappingURL=VariableHeightVirtualizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariableHeightVirtualizer.d.ts","sourceRoot":"","sources":["../../../../../Core/Components/Virtualise/VariableHeightVirtualizer/VariableHeightVirtualizer.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,OAAO,CAAC;AAsBrD,MAAM,WAAW,WAAW;IAC1B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AASD,MAAM,WAAW,8BAA8B;IAC7C,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,QAAQ,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,WAAW,EAAE,CACX,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAC5D,OAAO,EAAE;QAAE,gBAAgB,EAAE,OAAO,CAAA;KAAE,KACnC,IAAI,CAAC;IACV,oDAAoD;IACpD,cAAc,EAAE,OAAO,CAAC;IACxB,4CAA4C;IAC5C,eAAe,EAAE,eAAe,CAAC;IACjC,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qCAAqC;IACrC,cAAc,CAAC,EAAE,CAAC,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC;IAC1C,qCAAqC;IACrC,cAAc,CAAC,EAAE,CAAC,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC;IAC1C,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,CAAC,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC;IAC5C,wCAAwC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACvC,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,iDAAiD;IACjD,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,UAAU,cAAc;IACtB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,4CAA4C;IAC5C,kBAAkB,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAC7C,4CAA4C;IAC5C,kBAAkB,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAC7C,4CAA4C;IAC5C,iBAAiB,EAAE,MAAM,IAAI,CAAC;CAC/B;AAaD;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,QAAA,MAAM,yBAAyB,2HA0T9B,CAAC;AAIF,eAAe,yBAAyB,CAAC"}
@@ -0,0 +1,249 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRef, useEffect, useState, useCallback, useLayoutEffect, forwardRef, useImperativeHandle, useMemo } from 'react';
3
+ import Styled from 'styled-components';
4
+ import { Progress } from '@pega/cosmos-react-core';
5
+ import useResizeObserver from '../UseResizeObserver';
6
+ import useTranslate from '../../../Hooks/useTranslate';
7
+ import useChildrenHeightResizeObserver from './useChildrenHeightResizeObserver';
8
+ import useLoaderPositioning from './useLoaderPositioning';
9
+ import usePagination from './usePagination';
10
+ import useScroll from './useScroll';
11
+ import useVirtualizerItemCount from './useVirtualizerItemCount';
12
+ import { calculateCumulativeItemSizeChange, getMaxHeight, isViewNotFilled, calculateTotalBufferHeight, getChangedItemsHeight, updateItemPositionStyles } from './utils';
13
+ const StyledLoader = Styled.div `
14
+ display: flex;
15
+ justify-content: center;
16
+ padding: 0.5rem;
17
+ position: absolute;
18
+ width: var(--container-width);
19
+ left: ${props => `var(${props.$style.left})`};
20
+ top: ${props => `var(${props.$style.top})`};
21
+ width: 100%;
22
+ `;
23
+ /**
24
+ * Flow:
25
+ * 1. First load/user scrolls/screen size change/column resize
26
+ * 2. Calculate new pagination range based on scroll position or if view not filled
27
+ * 3. Consumer executes API call to fetch new data
28
+ * 4. New items are prepared and rendered
29
+ * 5. Update cache of item heights
30
+ * 6. Update buffer height
31
+ * 7. Adjust itemContainer top
32
+ * 8. Adjust scrollTop (if needed) to keep the items at same position visually
33
+ */
34
+ /**
35
+ * VariableHeightVirtualizer is a React component that efficiently renders large lists with items of variable heights,
36
+ * using virtualization techniques to minimize DOM nodes and improve performance.
37
+ *
38
+ * @param props - {@link VariableHeightVirtualizerProps}
39
+ * @param ref - Forwarded ref exposing imperative APIs: scrollToTop, getParentContainer, getBufferContainer, notifyCountChange.
40
+ *
41
+ * @example
42
+ * ```tsx
43
+ * <VariableHeightVirtualizer
44
+ * id="my-list"
45
+ * totalItemCount={10000}
46
+ * loadedDataRange={{ startIndex: 0, endIndex: 49 }}
47
+ * isDataFetching={isLoading}
48
+ * apiCallback={fetchData}
49
+ * defaultItemHeight={40}
50
+ * buffer={10}
51
+ * headerRenderer={() => <Header />}
52
+ * footerRenderer={() => <Footer />}
53
+ * noResultRenderer={() => <NoResults />}
54
+ * >
55
+ * {items.map(item => <ListItem key={item.id} {...item} />)}
56
+ * </VariableHeightVirtualizer>
57
+ * ```
58
+ */
59
+ const VariableHeightVirtualizer = forwardRef(({ id, children, buffer = 15, apiCallback, loadedDataRange = {}, defaultItemHeight = 30, totalItemCount, maxItemsToPaint = 5000, headerRenderer = null, footerRenderer = null, noResultRenderer = null, itemContainerClass = '', viewMaxHeight = null, minHeight = 'auto', isDataFetching = false, minHeightWhenNoItemsRendered = 'auto' }, ref) => {
60
+ const [startIndex, setStartIndex] = useState(0);
61
+ const [endIndex, setEndIndex] = useState(0);
62
+ const [scrollTop, setScrollTop] = useState(0);
63
+ const [totalBufferHeight, setTotalBufferHeight] = useState(0);
64
+ const [itemsHeight, setItemsHeight] = useState({});
65
+ const [itemContainerHeight, setItemContainerHeight] = useState(0);
66
+ const [countChangeTrigger, setCountChangeTrigger] = useState(0);
67
+ const [itemHeightChangeTrigger, setItemHeightChangeTrigger] = useState(0);
68
+ const [parentContainerDimensionChangeTrigger, setParentContainerDimensionChangeTrigger] = useState(0);
69
+ const parentContainerRef = useRef(null);
70
+ const bufferContainerRef = useRef(null);
71
+ const itemContainerRef = useRef(null);
72
+ const previousItemsHeightRef = useRef({});
73
+ const previousFirstItemDataIndexRef = useRef(null);
74
+ const [translate] = useTranslate();
75
+ const onParentContainerDimensionUpdate = useCallback(() => {
76
+ const { height: parentContainerHeight, width: parentContainerWidth } = parentContainerRef.current?.getBoundingClientRect() ?? {};
77
+ // trigger virtualizer operations only when the container has some height and width
78
+ if (parentContainerHeight && parentContainerWidth) {
79
+ setParentContainerDimensionChangeTrigger(value => value + 1);
80
+ }
81
+ }, []);
82
+ const getParentContainer = useCallback(() => parentContainerRef.current, []);
83
+ useResizeObserver(getParentContainer, onParentContainerDimensionUpdate);
84
+ const { isInfiniteMode, virtualizedCount } = useVirtualizerItemCount({
85
+ totalItemCount,
86
+ startIndex,
87
+ endIndex,
88
+ loadedDataRange,
89
+ isDataFetching,
90
+ itemContainerRef,
91
+ children,
92
+ buffer,
93
+ countResetSignal: countChangeTrigger
94
+ });
95
+ const { triggerPagination, isForceRefreshedPagination } = usePagination({
96
+ apiCallback,
97
+ id,
98
+ buffer,
99
+ maxItemsToPaint,
100
+ startIndex,
101
+ endIndex,
102
+ virtualizedCount,
103
+ isInfiniteMode,
104
+ itemsHeight,
105
+ defaultItemHeight,
106
+ parentContainerRef,
107
+ itemContainerRef,
108
+ setStartIndex,
109
+ setEndIndex,
110
+ previousFirstItemDataIndexRef
111
+ });
112
+ // Listens to the scroll events and trigger pagination when more records are needed to enable smooth scrolling
113
+ useScroll({
114
+ parentContainerRef,
115
+ itemContainerRef,
116
+ onThresholdBreach: (sTop) => {
117
+ setScrollTop(sTop);
118
+ triggerPagination(sTop);
119
+ },
120
+ delay: 150
121
+ });
122
+ // Expose APIs to the consumer
123
+ useImperativeHandle(ref, () => ({
124
+ scrollToTop: () => {
125
+ if (parentContainerRef.current) {
126
+ parentContainerRef.current.scrollTop = 0;
127
+ setScrollTop(0);
128
+ triggerPagination(0, true);
129
+ }
130
+ },
131
+ getParentContainer: () => parentContainerRef.current,
132
+ getBufferContainer: () => itemContainerRef.current,
133
+ notifyCountChange: () => setCountChangeTrigger(value => value + 1)
134
+ }));
135
+ // Measure height of rendered items and cache the heights
136
+ useLayoutEffect(() => {
137
+ if (!itemContainerRef.current)
138
+ return;
139
+ const newHeights = getChangedItemsHeight(itemContainerRef.current, itemsHeight, defaultItemHeight);
140
+ if (Object.keys(newHeights).length > 0) {
141
+ setItemsHeight((prev) => ({ ...prev, ...newHeights }));
142
+ }
143
+ }, [
144
+ startIndex,
145
+ itemsHeight,
146
+ children,
147
+ isDataFetching,
148
+ defaultItemHeight,
149
+ itemHeightChangeTrigger
150
+ ]);
151
+ // buffer height calculation
152
+ useLayoutEffect(() => {
153
+ const newBufferHeight = calculateTotalBufferHeight(virtualizedCount, itemsHeight, defaultItemHeight);
154
+ if (newBufferHeight !== totalBufferHeight) {
155
+ setTotalBufferHeight(newBufferHeight);
156
+ }
157
+ }, [itemsHeight, virtualizedCount, defaultItemHeight, totalBufferHeight]);
158
+ // itemContainer size and position adjustments
159
+ useLayoutEffect(() => {
160
+ if (!itemContainerRef.current)
161
+ return;
162
+ setItemContainerHeight(updateItemPositionStyles(itemContainerRef.current, itemsHeight, defaultItemHeight));
163
+ }, [children, itemsHeight, defaultItemHeight]);
164
+ // scroll position adjustment if rendered height is different than estimated height
165
+ useLayoutEffect(() => {
166
+ if (!parentContainerRef.current)
167
+ return;
168
+ const atTop = parentContainerRef.current.scrollTop === 0;
169
+ if (!atTop) {
170
+ const delta = calculateCumulativeItemSizeChange(startIndex, previousFirstItemDataIndexRef.current, itemsHeight, previousItemsHeightRef.current, defaultItemHeight);
171
+ if (delta !== 0) {
172
+ parentContainerRef.current.scrollTop += delta;
173
+ }
174
+ }
175
+ previousItemsHeightRef.current = { ...itemsHeight };
176
+ }, [startIndex, itemsHeight, defaultItemHeight]);
177
+ // Adjust loader positions
178
+ useLoaderPositioning({
179
+ isDataFetching,
180
+ parentContainerRef,
181
+ itemContainerRef,
182
+ children,
183
+ itemsHeight,
184
+ defaultItemHeight
185
+ });
186
+ // Initial pagination trigger and subsequent triggers if the view is not completely filled
187
+ useEffect(() => {
188
+ // If consumer already has data for initial items, then no need to trigger pagination. Just hydrate the internal state in sync with existing data.
189
+ if (!endIndex &&
190
+ loadedDataRange.startIndex !== undefined &&
191
+ loadedDataRange.startIndex >= 0 &&
192
+ loadedDataRange.endIndex !== undefined &&
193
+ loadedDataRange.endIndex >= 0) {
194
+ setStartIndex(loadedDataRange.startIndex);
195
+ setEndIndex(loadedDataRange.endIndex);
196
+ return;
197
+ }
198
+ // If the consumer doesn't have data or view not filled then trigger pagination
199
+ if (!isDataFetching &&
200
+ (!endIndex ||
201
+ (itemContainerRef.current &&
202
+ parentContainerRef.current &&
203
+ isViewNotFilled(virtualizedCount, itemContainerRef.current, parentContainerRef.current, !!headerRenderer)))) {
204
+ triggerPagination(scrollTop);
205
+ }
206
+ }, [
207
+ loadedDataRange,
208
+ scrollTop,
209
+ virtualizedCount,
210
+ endIndex,
211
+ triggerPagination,
212
+ parentContainerDimensionChangeTrigger,
213
+ isDataFetching,
214
+ headerRenderer
215
+ ]);
216
+ // Resize observer on items to track height changes
217
+ const onItemsHeightUpdate = useCallback(() => {
218
+ setItemHeightChangeTrigger(value => value + 1);
219
+ }, []);
220
+ useChildrenHeightResizeObserver({
221
+ childrenContainerRef: itemContainerRef,
222
+ children,
223
+ itemsHeight,
224
+ defaultItemHeight,
225
+ onItemsHeightUpdate
226
+ });
227
+ const maxHeight = useMemo(() => getMaxHeight(viewMaxHeight), [viewMaxHeight]);
228
+ return (_jsxs("div", { ref: parentContainerRef, style: {
229
+ maxHeight,
230
+ minHeight: virtualizedCount === 0 ? minHeightWhenNoItemsRendered : minHeight,
231
+ overflowY: 'auto',
232
+ position: 'relative',
233
+ width: '100%'
234
+ }, className: 'pContainer variableHeightVirtualizer', children: [headerRenderer && headerRenderer(), _jsxs("div", { className: 'bContainer', ref: bufferContainerRef, style: { height: totalBufferHeight, position: 'relative' }, children: [isDataFetching && !isForceRefreshedPagination && (_jsx(StyledLoader, { "$style": {
235
+ top: '--above-loader-top',
236
+ left: '--loader-left'
237
+ }, children: _jsx(Progress, { className: 'above-loader', placement: 'block', tabIndex: 0, "aria-label": translate('Loading more results') }) })), _jsx("div", { ref: itemContainerRef, style: {
238
+ position: 'absolute',
239
+ left: 0,
240
+ width: '100%',
241
+ height: `${itemContainerHeight}px`
242
+ }, className: `${itemContainerClass} row-container`, children: children }), isDataFetching && !isForceRefreshedPagination && (_jsx(StyledLoader, { "$style": {
243
+ top: '--below-loader-top',
244
+ left: '--loader-left'
245
+ }, children: _jsx(Progress, { className: 'below-loader', placement: 'block', tabIndex: 0, "aria-label": translate('Loading more results') }) }))] }), virtualizedCount === 0 && !isDataFetching && noResultRenderer ? noResultRenderer() : null, footerRenderer && footerRenderer()] }));
246
+ });
247
+ VariableHeightVirtualizer.displayName = 'VariableHeightVirtualizer';
248
+ export default VariableHeightVirtualizer;
249
+ //# sourceMappingURL=VariableHeightVirtualizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariableHeightVirtualizer.js","sourceRoot":"","sources":["../../../../../Core/Components/Virtualise/VariableHeightVirtualizer/VariableHeightVirtualizer.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useRef,\n useEffect,\n useState,\n useCallback,\n useLayoutEffect,\n forwardRef,\n useImperativeHandle,\n useMemo\n} from 'react';\nimport type { ReactNode, ForwardedRef } from 'react';\nimport Styled from 'styled-components';\n\nimport { Progress } from '@pega/cosmos-react-core';\n\nimport useResizeObserver from '../UseResizeObserver';\nimport useTranslate from '../../../Hooks/useTranslate';\n\nimport useChildrenHeightResizeObserver from './useChildrenHeightResizeObserver';\nimport useLoaderPositioning from './useLoaderPositioning';\nimport usePagination from './usePagination';\nimport useScroll from './useScroll';\nimport useVirtualizerItemCount from './useVirtualizerItemCount';\nimport {\n calculateCumulativeItemSizeChange,\n getMaxHeight,\n isViewNotFilled,\n calculateTotalBufferHeight,\n getChangedItemsHeight,\n updateItemPositionStyles\n} from './utils';\n\nexport interface ItemsHeight {\n [index: number]: number;\n}\n\nexport interface LoadedDataRange {\n startIndex?: number;\n endIndex?: number;\n}\n\ninterface StyledLoaderProps {\n $style: {\n top: string;\n left: string;\n };\n}\n\nexport interface VariableHeightVirtualizerProps {\n /** Unique identifier for the virtualizer instance. */\n id: string;\n /** The React children elements to render inside the virtualizer. */\n children: ReactNode;\n /** Callback to fetch paginated data. */\n apiCallback: (\n params: { startIndex: number; endIndex: number; id: string },\n options: { takeLatestAction: boolean }\n ) => void;\n /** Indicates if data is currently being fetched. */\n isDataFetching: boolean;\n /** Range of data that is already loaded. */\n loadedDataRange: LoadedDataRange;\n /** Default height for items if not measured. */\n defaultItemHeight?: number;\n /** Total number of items in the list. */\n totalItemCount?: number | null;\n /** Number of items to buffer before/after the visible range. */\n buffer?: number;\n /** Maximum number of items to render at once. */\n maxItemsToPaint?: number;\n /** Function to render the header. */\n headerRenderer?: (() => ReactNode) | null;\n /** Function to render the footer. */\n footerRenderer?: (() => ReactNode) | null;\n /** Function to render the no-result state. */\n noResultRenderer?: (() => ReactNode) | null;\n /** CSS class for the item container. */\n itemContainerClass?: string;\n /** Maximum height for the view container. */\n viewMaxHeight?: string | number | null;\n /** Minimum height for the view container. */\n minHeight?: string | number;\n /** Minimum height when no items are rendered. */\n minHeightWhenNoItemsRendered?: string;\n}\n\ninterface VirtualizerRef {\n /** Scrolls the parent container to the top. */\n scrollToTop: () => void;\n /** Returns the parent container element. */\n getParentContainer: () => HTMLElement | null;\n /** Returns the buffer container element. */\n getBufferContainer: () => HTMLElement | null;\n /** Triggers a count change notification. */\n notifyCountChange: () => void;\n}\n\nconst StyledLoader = Styled.div<StyledLoaderProps>`\n display: flex;\n justify-content: center;\n padding: 0.5rem;\n position: absolute;\n width: var(--container-width);\n left: ${props => `var(${props.$style.left})`};\n top: ${props => `var(${props.$style.top})`};\n width: 100%;\n`;\n\n/**\n * Flow:\n * 1. First load/user scrolls/screen size change/column resize\n * 2. Calculate new pagination range based on scroll position or if view not filled\n * 3. Consumer executes API call to fetch new data\n * 4. New items are prepared and rendered\n * 5. Update cache of item heights\n * 6. Update buffer height\n * 7. Adjust itemContainer top\n * 8. Adjust scrollTop (if needed) to keep the items at same position visually\n */\n\n/**\n * VariableHeightVirtualizer is a React component that efficiently renders large lists with items of variable heights,\n * using virtualization techniques to minimize DOM nodes and improve performance.\n *\n * @param props - {@link VariableHeightVirtualizerProps}\n * @param ref - Forwarded ref exposing imperative APIs: scrollToTop, getParentContainer, getBufferContainer, notifyCountChange.\n *\n * @example\n * ```tsx\n * <VariableHeightVirtualizer\n * id=\"my-list\"\n * totalItemCount={10000}\n * loadedDataRange={{ startIndex: 0, endIndex: 49 }}\n * isDataFetching={isLoading}\n * apiCallback={fetchData}\n * defaultItemHeight={40}\n * buffer={10}\n * headerRenderer={() => <Header />}\n * footerRenderer={() => <Footer />}\n * noResultRenderer={() => <NoResults />}\n * >\n * {items.map(item => <ListItem key={item.id} {...item} />)}\n * </VariableHeightVirtualizer>\n * ```\n */\nconst VariableHeightVirtualizer = forwardRef<VirtualizerRef, VariableHeightVirtualizerProps>(\n (\n {\n id,\n children,\n buffer = 15,\n apiCallback,\n loadedDataRange = {},\n defaultItemHeight = 30,\n totalItemCount,\n maxItemsToPaint = 5000,\n headerRenderer = null,\n footerRenderer = null,\n noResultRenderer = null,\n itemContainerClass = '',\n viewMaxHeight = null,\n minHeight = 'auto',\n isDataFetching = false,\n minHeightWhenNoItemsRendered = 'auto'\n },\n ref: ForwardedRef<VirtualizerRef>\n ) => {\n const [startIndex, setStartIndex] = useState<number>(0);\n const [endIndex, setEndIndex] = useState<number>(0);\n const [scrollTop, setScrollTop] = useState<number>(0);\n const [totalBufferHeight, setTotalBufferHeight] = useState<number>(0);\n const [itemsHeight, setItemsHeight] = useState<ItemsHeight>({});\n const [itemContainerHeight, setItemContainerHeight] = useState<number>(0);\n\n const [countChangeTrigger, setCountChangeTrigger] = useState<number>(0);\n const [itemHeightChangeTrigger, setItemHeightChangeTrigger] = useState<number>(0);\n const [parentContainerDimensionChangeTrigger, setParentContainerDimensionChangeTrigger] =\n useState<number>(0);\n\n const parentContainerRef = useRef<HTMLDivElement>(null);\n const bufferContainerRef = useRef<HTMLDivElement>(null);\n const itemContainerRef = useRef<HTMLDivElement>(null);\n const previousItemsHeightRef = useRef<ItemsHeight>({});\n const previousFirstItemDataIndexRef = useRef<number | null>(null);\n\n const [translate] = useTranslate();\n\n const onParentContainerDimensionUpdate = useCallback(() => {\n const { height: parentContainerHeight, width: parentContainerWidth } =\n parentContainerRef.current?.getBoundingClientRect() ?? {};\n // trigger virtualizer operations only when the container has some height and width\n if (parentContainerHeight && parentContainerWidth) {\n setParentContainerDimensionChangeTrigger(value => value + 1);\n }\n }, []);\n\n const getParentContainer = useCallback(\n (): HTMLDivElement | null => parentContainerRef.current,\n []\n );\n useResizeObserver(getParentContainer, onParentContainerDimensionUpdate);\n\n const { isInfiniteMode, virtualizedCount } = useVirtualizerItemCount({\n totalItemCount,\n startIndex,\n endIndex,\n loadedDataRange,\n isDataFetching,\n itemContainerRef,\n children,\n buffer,\n countResetSignal: countChangeTrigger\n });\n\n const { triggerPagination, isForceRefreshedPagination } = usePagination({\n apiCallback,\n id,\n buffer,\n maxItemsToPaint,\n startIndex,\n endIndex,\n virtualizedCount,\n isInfiniteMode,\n itemsHeight,\n defaultItemHeight,\n parentContainerRef,\n itemContainerRef,\n setStartIndex,\n setEndIndex,\n previousFirstItemDataIndexRef\n });\n\n // Listens to the scroll events and trigger pagination when more records are needed to enable smooth scrolling\n useScroll({\n parentContainerRef,\n itemContainerRef,\n onThresholdBreach: (sTop: number) => {\n setScrollTop(sTop);\n triggerPagination(sTop);\n },\n delay: 150\n });\n\n // Expose APIs to the consumer\n useImperativeHandle(\n ref,\n (): VirtualizerRef => ({\n scrollToTop: () => {\n if (parentContainerRef.current) {\n parentContainerRef.current.scrollTop = 0;\n setScrollTop(0);\n\n triggerPagination(0, true);\n }\n },\n getParentContainer: () => parentContainerRef.current,\n getBufferContainer: () => itemContainerRef.current,\n notifyCountChange: () => setCountChangeTrigger(value => value + 1)\n })\n );\n\n // Measure height of rendered items and cache the heights\n useLayoutEffect(() => {\n if (!itemContainerRef.current) return;\n\n const newHeights = getChangedItemsHeight(\n itemContainerRef.current,\n itemsHeight,\n defaultItemHeight\n );\n if (Object.keys(newHeights).length > 0) {\n setItemsHeight((prev: ItemsHeight) => ({ ...prev, ...newHeights }));\n }\n }, [\n startIndex,\n itemsHeight,\n children,\n isDataFetching,\n defaultItemHeight,\n itemHeightChangeTrigger\n ]);\n\n // buffer height calculation\n useLayoutEffect(() => {\n const newBufferHeight = calculateTotalBufferHeight(\n virtualizedCount,\n itemsHeight,\n defaultItemHeight\n );\n\n if (newBufferHeight !== totalBufferHeight) {\n setTotalBufferHeight(newBufferHeight);\n }\n }, [itemsHeight, virtualizedCount, defaultItemHeight, totalBufferHeight]);\n\n // itemContainer size and position adjustments\n useLayoutEffect(() => {\n if (!itemContainerRef.current) return;\n\n setItemContainerHeight(\n updateItemPositionStyles(itemContainerRef.current, itemsHeight, defaultItemHeight)\n );\n }, [children, itemsHeight, defaultItemHeight]);\n\n // scroll position adjustment if rendered height is different than estimated height\n useLayoutEffect(() => {\n if (!parentContainerRef.current) return;\n\n const atTop = parentContainerRef.current.scrollTop === 0;\n if (!atTop) {\n const delta = calculateCumulativeItemSizeChange(\n startIndex,\n previousFirstItemDataIndexRef.current,\n itemsHeight,\n previousItemsHeightRef.current,\n defaultItemHeight\n );\n\n if (delta !== 0) {\n parentContainerRef.current.scrollTop += delta;\n }\n }\n\n previousItemsHeightRef.current = { ...itemsHeight };\n }, [startIndex, itemsHeight, defaultItemHeight]);\n\n // Adjust loader positions\n useLoaderPositioning({\n isDataFetching,\n parentContainerRef,\n itemContainerRef,\n children,\n itemsHeight,\n defaultItemHeight\n });\n\n // Initial pagination trigger and subsequent triggers if the view is not completely filled\n useEffect(() => {\n // If consumer already has data for initial items, then no need to trigger pagination. Just hydrate the internal state in sync with existing data.\n if (\n !endIndex &&\n loadedDataRange.startIndex !== undefined &&\n loadedDataRange.startIndex >= 0 &&\n loadedDataRange.endIndex !== undefined &&\n loadedDataRange.endIndex >= 0\n ) {\n setStartIndex(loadedDataRange.startIndex);\n setEndIndex(loadedDataRange.endIndex);\n return;\n }\n\n // If the consumer doesn't have data or view not filled then trigger pagination\n if (\n !isDataFetching &&\n (!endIndex ||\n (itemContainerRef.current &&\n parentContainerRef.current &&\n isViewNotFilled(\n virtualizedCount,\n itemContainerRef.current,\n parentContainerRef.current,\n !!headerRenderer\n )))\n ) {\n triggerPagination(scrollTop);\n }\n }, [\n loadedDataRange,\n scrollTop,\n virtualizedCount,\n endIndex,\n triggerPagination,\n parentContainerDimensionChangeTrigger,\n isDataFetching,\n headerRenderer\n ]);\n\n // Resize observer on items to track height changes\n const onItemsHeightUpdate = useCallback(() => {\n setItemHeightChangeTrigger(value => value + 1);\n }, []);\n useChildrenHeightResizeObserver({\n childrenContainerRef: itemContainerRef,\n children,\n itemsHeight,\n defaultItemHeight,\n onItemsHeightUpdate\n });\n\n const maxHeight = useMemo((): string => getMaxHeight(viewMaxHeight), [viewMaxHeight]);\n\n return (\n <div\n ref={parentContainerRef}\n style={{\n maxHeight,\n minHeight: virtualizedCount === 0 ? minHeightWhenNoItemsRendered : minHeight,\n overflowY: 'auto',\n position: 'relative',\n width: '100%'\n }}\n className='pContainer variableHeightVirtualizer'\n >\n {headerRenderer && headerRenderer()}\n <div\n className='bContainer'\n ref={bufferContainerRef}\n style={{ height: totalBufferHeight, position: 'relative' }}\n >\n {isDataFetching && !isForceRefreshedPagination && (\n <StyledLoader\n $style={{\n top: '--above-loader-top',\n left: '--loader-left'\n }}\n >\n <Progress\n className='above-loader'\n placement='block'\n tabIndex={0}\n aria-label={translate('Loading more results')}\n />\n </StyledLoader>\n )}\n\n <div\n ref={itemContainerRef}\n style={{\n position: 'absolute',\n left: 0,\n width: '100%',\n height: `${itemContainerHeight}px`\n }}\n className={`${itemContainerClass} row-container`}\n >\n {children}\n </div>\n\n {isDataFetching && !isForceRefreshedPagination && (\n <StyledLoader\n $style={{\n top: '--below-loader-top',\n left: '--loader-left'\n }}\n >\n <Progress\n className='below-loader'\n placement='block'\n tabIndex={0}\n aria-label={translate('Loading more results')}\n />\n </StyledLoader>\n )}\n </div>\n {virtualizedCount === 0 && !isDataFetching && noResultRenderer ? noResultRenderer() : null}\n {footerRenderer && footerRenderer()}\n </div>\n );\n }\n);\n\nVariableHeightVirtualizer.displayName = 'VariableHeightVirtualizer';\n\nexport default VariableHeightVirtualizer;\n"]}
@@ -0,0 +1,22 @@
1
+ import type { ReactNode, RefObject } from 'react';
2
+ import type { ItemsHeight } from './VariableHeightVirtualizer';
3
+ interface ChildrenHeightResizeObserverProps {
4
+ /** A ref to the container DOM element whose children will be observed. */
5
+ childrenContainerRef: RefObject<HTMLElement>;
6
+ /** The React children elements rendered inside the container. */
7
+ children: ReactNode;
8
+ /** Mapping of item indices and their actual height. */
9
+ itemsHeight: ItemsHeight;
10
+ /** The default height to use for items if not measured. */
11
+ defaultItemHeight: number;
12
+ /** Callback function invoked when any child's height changes. */
13
+ onItemsHeightUpdate: () => void;
14
+ }
15
+ /**
16
+ * Observes the height of child elements within a container and triggers a callback when any child's height changes.
17
+ *
18
+ * NOTE: Ensure that each child element has correct data attribute 'data-index'.
19
+ */
20
+ export default function useChildrenHeightResizeObserver({ childrenContainerRef, children, itemsHeight, defaultItemHeight, onItemsHeightUpdate }: ChildrenHeightResizeObserverProps): void;
21
+ export {};
22
+ //# sourceMappingURL=useChildrenHeightResizeObserver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChildrenHeightResizeObserver.d.ts","sourceRoot":"","sources":["../../../../../Core/Components/Virtualise/VariableHeightVirtualizer/useChildrenHeightResizeObserver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,UAAU,iCAAiC;IACzC,0EAA0E;IAC1E,oBAAoB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IAC7C,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB,uDAAuD;IACvD,WAAW,EAAE,WAAW,CAAC;IACzB,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,+BAA+B,CAAC,EACtD,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACpB,EAAE,iCAAiC,GAAG,IAAI,CAiC1C"}
@@ -0,0 +1,38 @@
1
+ import { useEffect } from 'react';
2
+ import { getDataIndex } from './utils';
3
+ /**
4
+ * Observes the height of child elements within a container and triggers a callback when any child's height changes.
5
+ *
6
+ * NOTE: Ensure that each child element has correct data attribute 'data-index'.
7
+ */
8
+ export default function useChildrenHeightResizeObserver({ childrenContainerRef, children, itemsHeight, defaultItemHeight, onItemsHeightUpdate }) {
9
+ useEffect(() => {
10
+ if (!childrenContainerRef.current)
11
+ return;
12
+ const items = childrenContainerRef.current.children;
13
+ if (!items?.length)
14
+ return;
15
+ const resizeObserver = new ResizeObserver((entries) => {
16
+ let anyChildHeightChanged = false;
17
+ for (const entry of entries) {
18
+ const itemDataIndex = getDataIndex(entry.target);
19
+ if (itemDataIndex !== null) {
20
+ const newHeight = entry.contentRect.height;
21
+ if (itemsHeight[itemDataIndex] !== newHeight) {
22
+ anyChildHeightChanged = true;
23
+ }
24
+ }
25
+ }
26
+ if (anyChildHeightChanged) {
27
+ onItemsHeightUpdate();
28
+ }
29
+ });
30
+ Array.from(items).forEach((item) => {
31
+ resizeObserver.observe(item);
32
+ });
33
+ return () => {
34
+ resizeObserver.disconnect();
35
+ };
36
+ }, [children, itemsHeight, defaultItemHeight]);
37
+ }
38
+ //# sourceMappingURL=useChildrenHeightResizeObserver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChildrenHeightResizeObserver.js","sourceRoot":"","sources":["../../../../../Core/Components/Virtualise/VariableHeightVirtualizer/useChildrenHeightResizeObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAgBvC;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,+BAA+B,CAAC,EACtD,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACe;IAClC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,oBAAoB,CAAC,OAAO;YAAE,OAAO;QAE1C,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,QAAQ,CAAC;QACpD,IAAI,CAAC,KAAK,EAAE,MAAM;YAAE,OAAO;QAE3B,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,CAAC,OAA8B,EAAE,EAAE;YAC3E,IAAI,qBAAqB,GAAG,KAAK,CAAC;YAElC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACjD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;oBAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;oBAC3C,IAAI,WAAW,CAAC,aAAa,CAAC,KAAK,SAAS,EAAE,CAAC;wBAC7C,qBAAqB,GAAG,IAAI,CAAC;oBAC/B,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,qBAAqB,EAAE,CAAC;gBAC1B,mBAAmB,EAAE,CAAC;YACxB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAa,EAAE,EAAE;YAC1C,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,cAAc,CAAC,UAAU,EAAE,CAAC;QAC9B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC;AACjD,CAAC","sourcesContent":["import { useEffect } from 'react';\nimport type { ReactNode, RefObject } from 'react';\n\nimport { getDataIndex } from './utils';\nimport type { ItemsHeight } from './VariableHeightVirtualizer';\n\ninterface ChildrenHeightResizeObserverProps {\n /** A ref to the container DOM element whose children will be observed. */\n childrenContainerRef: RefObject<HTMLElement>;\n /** The React children elements rendered inside the container. */\n children: ReactNode;\n /** Mapping of item indices and their actual height. */\n itemsHeight: ItemsHeight;\n /** The default height to use for items if not measured. */\n defaultItemHeight: number;\n /** Callback function invoked when any child's height changes. */\n onItemsHeightUpdate: () => void;\n}\n\n/**\n * Observes the height of child elements within a container and triggers a callback when any child's height changes.\n *\n * NOTE: Ensure that each child element has correct data attribute 'data-index'.\n */\nexport default function useChildrenHeightResizeObserver({\n childrenContainerRef,\n children,\n itemsHeight,\n defaultItemHeight,\n onItemsHeightUpdate\n}: ChildrenHeightResizeObserverProps): void {\n useEffect(() => {\n if (!childrenContainerRef.current) return;\n\n const items = childrenContainerRef.current.children;\n if (!items?.length) return;\n\n const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {\n let anyChildHeightChanged = false;\n\n for (const entry of entries) {\n const itemDataIndex = getDataIndex(entry.target);\n if (itemDataIndex !== null) {\n const newHeight = entry.contentRect.height;\n if (itemsHeight[itemDataIndex] !== newHeight) {\n anyChildHeightChanged = true;\n }\n }\n }\n\n if (anyChildHeightChanged) {\n onItemsHeightUpdate();\n }\n });\n\n Array.from(items).forEach((item: Element) => {\n resizeObserver.observe(item);\n });\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [children, itemsHeight, defaultItemHeight]);\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import type { RefObject, ReactNode } from 'react';
2
+ import type { ItemsHeight } from './VariableHeightVirtualizer';
3
+ interface LoaderPositioningProps {
4
+ /** Ref to the parent scrollable container element. */
5
+ parentContainerRef: RefObject<HTMLElement>;
6
+ /** Ref to the container holding the rendered items. */
7
+ itemContainerRef: RefObject<HTMLElement>;
8
+ /** Indicates if data is currently being fetched. */
9
+ isDataFetching: boolean;
10
+ /** The React children elements rendered inside the container. */
11
+ children: ReactNode;
12
+ /** Mapping of item indices and their actual height. */
13
+ itemsHeight: ItemsHeight;
14
+ /** The default height to use for items if not measured. */
15
+ defaultItemHeight: number;
16
+ }
17
+ /**
18
+ * Calculates the positioning of loading indicators.
19
+ */
20
+ export default function useLoaderPositioning({ parentContainerRef, itemContainerRef, isDataFetching, children, itemsHeight, defaultItemHeight }: LoaderPositioningProps): void;
21
+ export {};
22
+ //# sourceMappingURL=useLoaderPositioning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoaderPositioning.d.ts","sourceRoot":"","sources":["../../../../../Core/Components/Virtualise/VariableHeightVirtualizer/useLoaderPositioning.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,UAAU,sBAAsB;IAC9B,sDAAsD;IACtD,kBAAkB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IAC3C,uDAAuD;IACvD,gBAAgB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IACzC,oDAAoD;IACpD,cAAc,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB,uDAAuD;IACvD,WAAW,EAAE,WAAW,CAAC;IACzB,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,WAAW,EACX,iBAAiB,EAClB,EAAE,sBAAsB,QA2CxB"}
@@ -0,0 +1,45 @@
1
+ import { useEffect, useLayoutEffect, useState } from 'react';
2
+ import useThrottle from '../../../Hooks/useThrottle';
3
+ import { getDataIndex } from './utils';
4
+ /**
5
+ * Calculates the positioning of loading indicators.
6
+ */
7
+ export default function useLoaderPositioning({ parentContainerRef, itemContainerRef, isDataFetching, children, itemsHeight, defaultItemHeight }) {
8
+ const [scrollLeft, setScrollLeft] = useState(0);
9
+ useLayoutEffect(() => {
10
+ if (!isDataFetching || !itemContainerRef.current || !parentContainerRef.current)
11
+ return;
12
+ const containerEl = parentContainerRef.current;
13
+ const items = itemContainerRef.current.children;
14
+ if (!items?.length)
15
+ return;
16
+ const topLoaderHeight = 80;
17
+ const topOffset = itemContainerRef.current.offsetTop || 0;
18
+ const firstItemDataIndex = getDataIndex(items[0]);
19
+ if (firstItemDataIndex === null)
20
+ return;
21
+ let itemContainerBottomPosition = topOffset;
22
+ for (let i = 0; i < items.length; i += 1) {
23
+ itemContainerBottomPosition += itemsHeight[firstItemDataIndex + i] ?? defaultItemHeight;
24
+ }
25
+ containerEl.style.setProperty('--above-loader-top', `${topOffset - topLoaderHeight}px`);
26
+ containerEl.style.setProperty('--below-loader-top', `${itemContainerBottomPosition}px`);
27
+ }, [isDataFetching, children, itemsHeight, defaultItemHeight, getDataIndex]);
28
+ useThrottle(scrollLeft, () => {
29
+ const containerEl = parentContainerRef.current;
30
+ if (!containerEl)
31
+ return;
32
+ containerEl.style.setProperty('--loader-left', `${containerEl.scrollLeft}px`);
33
+ });
34
+ useEffect(() => {
35
+ const containerEl = parentContainerRef.current;
36
+ if (!containerEl)
37
+ return;
38
+ const scrollHandler = () => setScrollLeft(containerEl.scrollLeft);
39
+ containerEl.addEventListener('scroll', scrollHandler, { passive: true });
40
+ return () => {
41
+ containerEl.removeEventListener('scroll', scrollHandler);
42
+ };
43
+ }, [parentContainerRef]);
44
+ }
45
+ //# sourceMappingURL=useLoaderPositioning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoaderPositioning.js","sourceRoot":"","sources":["../../../../../Core/Components/Virtualise/VariableHeightVirtualizer/useLoaderPositioning.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG7D,OAAO,WAAW,MAAM,4BAA4B,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAkBvC;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,WAAW,EACX,iBAAiB,EACM;IACvB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEhD,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,cAAc,IAAI,CAAC,gBAAgB,CAAC,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO;YAAE,OAAO;QAExF,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC;QAC/C,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC;QAChD,IAAI,CAAC,KAAK,EAAE,MAAM;YAAE,OAAO;QAE3B,MAAM,eAAe,GAAG,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC;QAE1D,MAAM,kBAAkB,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,IAAI,kBAAkB,KAAK,IAAI;YAAE,OAAO;QAExC,IAAI,2BAA2B,GAAG,SAAS,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,2BAA2B,IAAI,WAAW,CAAC,kBAAkB,GAAG,CAAC,CAAC,IAAI,iBAAiB,CAAC;QAC1F,CAAC;QAED,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,GAAG,SAAS,GAAG,eAAe,IAAI,CAAC,CAAC;QACxF,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,GAAG,2BAA2B,IAAI,CAAC,CAAC;IAC1F,CAAC,EAAE,CAAC,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,CAAC,CAAC,CAAC;IAE7E,WAAW,CAAC,UAAU,EAAE,GAAG,EAAE;QAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC;QAC/C,IAAI,CAAC,WAAW;YAAE,OAAO;QAEzB,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,EAAE,GAAG,WAAW,CAAC,UAAU,IAAI,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC;QAC/C,IAAI,CAAC,WAAW;YAAE,OAAO;QAEzB,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAClE,WAAW,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAEzE,OAAO,GAAG,EAAE;YACV,WAAW,CAAC,mBAAmB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC3D,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["import { useEffect, useLayoutEffect, useState } from 'react';\nimport type { RefObject, ReactNode } from 'react';\n\nimport useThrottle from '../../../Hooks/useThrottle';\n\nimport { getDataIndex } from './utils';\nimport type { ItemsHeight } from './VariableHeightVirtualizer';\n\ninterface LoaderPositioningProps {\n /** Ref to the parent scrollable container element. */\n parentContainerRef: RefObject<HTMLElement>;\n /** Ref to the container holding the rendered items. */\n itemContainerRef: RefObject<HTMLElement>;\n /** Indicates if data is currently being fetched. */\n isDataFetching: boolean;\n /** The React children elements rendered inside the container. */\n children: ReactNode;\n /** Mapping of item indices and their actual height. */\n itemsHeight: ItemsHeight;\n /** The default height to use for items if not measured. */\n defaultItemHeight: number;\n}\n\n/**\n * Calculates the positioning of loading indicators.\n */\nexport default function useLoaderPositioning({\n parentContainerRef,\n itemContainerRef,\n isDataFetching,\n children,\n itemsHeight,\n defaultItemHeight\n}: LoaderPositioningProps) {\n const [scrollLeft, setScrollLeft] = useState(0);\n\n useLayoutEffect(() => {\n if (!isDataFetching || !itemContainerRef.current || !parentContainerRef.current) return;\n\n const containerEl = parentContainerRef.current;\n const items = itemContainerRef.current.children;\n if (!items?.length) return;\n\n const topLoaderHeight = 80;\n const topOffset = itemContainerRef.current.offsetTop || 0;\n\n const firstItemDataIndex = getDataIndex(items[0]);\n if (firstItemDataIndex === null) return;\n\n let itemContainerBottomPosition = topOffset;\n for (let i = 0; i < items.length; i += 1) {\n itemContainerBottomPosition += itemsHeight[firstItemDataIndex + i] ?? defaultItemHeight;\n }\n\n containerEl.style.setProperty('--above-loader-top', `${topOffset - topLoaderHeight}px`);\n containerEl.style.setProperty('--below-loader-top', `${itemContainerBottomPosition}px`);\n }, [isDataFetching, children, itemsHeight, defaultItemHeight, getDataIndex]);\n\n useThrottle(scrollLeft, () => {\n const containerEl = parentContainerRef.current;\n if (!containerEl) return;\n\n containerEl.style.setProperty('--loader-left', `${containerEl.scrollLeft}px`);\n });\n\n useEffect(() => {\n const containerEl = parentContainerRef.current;\n if (!containerEl) return;\n\n const scrollHandler = () => setScrollLeft(containerEl.scrollLeft);\n containerEl.addEventListener('scroll', scrollHandler, { passive: true });\n\n return () => {\n containerEl.removeEventListener('scroll', scrollHandler);\n };\n }, [parentContainerRef]);\n}\n"]}
@@ -0,0 +1,49 @@
1
+ import type { MutableRefObject, RefObject } from 'react';
2
+ import type { ItemsHeight, VariableHeightVirtualizerProps } from './VariableHeightVirtualizer';
3
+ interface PaginationParams {
4
+ /** Callback to fetch paginated data. */
5
+ apiCallback: VariableHeightVirtualizerProps['apiCallback'];
6
+ /** Unique identifier for the virtualizer instance. */
7
+ id: string;
8
+ /** Number of items to buffer before/after the visible range. */
9
+ buffer: number;
10
+ /** Maximum number of items to render at once. */
11
+ maxItemsToPaint: number;
12
+ /** Current start index of the visible items. */
13
+ startIndex: number;
14
+ /** Current end index of the visible items. */
15
+ endIndex: number;
16
+ /** Total number of items in the virtualized list. */
17
+ virtualizedCount: number;
18
+ /** Whether infinite scrolling mode is enabled. */
19
+ isInfiniteMode: boolean;
20
+ /** Mapping of item indices and their actual height. */
21
+ itemsHeight: ItemsHeight;
22
+ /** Default height for items if not measured. */
23
+ defaultItemHeight: number;
24
+ /** Ref to the parent scrollable container element. */
25
+ parentContainerRef: RefObject<HTMLElement>;
26
+ /** Ref to the container holding the rendered items. */
27
+ itemContainerRef: RefObject<HTMLElement>;
28
+ /** Setter for the start index. */
29
+ setStartIndex: (v: number) => void;
30
+ /** Setter for the end index. */
31
+ setEndIndex: (v: number) => void;
32
+ /** Ref to track the previous first item's data index. */
33
+ previousFirstItemDataIndexRef: MutableRefObject<number | null>;
34
+ }
35
+ /**
36
+ * Calculates the indices of items to render based on the current scroll position,
37
+ * buffer, and virtualization settings. It triggers data fetching via the provided `apiCallback`
38
+ * when pagination boundaries change or a force refresh is requested.
39
+ *
40
+ * @returns An object containing:
41
+ * - `triggerPagination`: Function to recalculate pagination indices and trigger data fetching.
42
+ * - `isForceRefreshedPagination`: Boolean indicating if the last pagination was force-refreshed.
43
+ */
44
+ export default function usePagination({ apiCallback, id, buffer, maxItemsToPaint, startIndex, endIndex, virtualizedCount, isInfiniteMode, itemsHeight, defaultItemHeight, parentContainerRef, itemContainerRef, setStartIndex, setEndIndex, previousFirstItemDataIndexRef }: PaginationParams): {
45
+ triggerPagination: (currentScrollTop: number, forceRefresh?: boolean) => void;
46
+ isForceRefreshedPagination: boolean;
47
+ };
48
+ export {};
49
+ //# sourceMappingURL=usePagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePagination.d.ts","sourceRoot":"","sources":["../../../../../Core/Components/Virtualise/VariableHeightVirtualizer/usePagination.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,8BAA8B,EAAE,MAAM,6BAA6B,CAAC;AAG/F,UAAU,gBAAgB;IACxB,wCAAwC;IACxC,WAAW,EAAE,8BAA8B,CAAC,aAAa,CAAC,CAAC;IAC3D,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,gBAAgB,EAAE,MAAM,CAAC;IACzB,kDAAkD;IAClD,cAAc,EAAE,OAAO,CAAC;IACxB,uDAAuD;IACvD,WAAW,EAAE,WAAW,CAAC;IACzB,gDAAgD;IAChD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,kBAAkB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IAC3C,uDAAuD;IACvD,gBAAgB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IACzC,kCAAkC;IAClC,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,gCAAgC;IAChC,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,yDAAyD;IACzD,6BAA6B,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAChE;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACpC,WAAW,EACX,EAAE,EACF,MAAM,EACN,eAAe,EACf,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,6BAA6B,EAC9B,EAAE,gBAAgB;0CAII,MAAM,iBAAiB,OAAO;;EAgDpD"}