react-virtual-renderer 1.0.3
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/README.md +170 -0
- package/dist/App.d.ts +3 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +7 -0
- package/dist/App.js.map +1 -0
- package/dist/accessibility/a11y.d.ts +111 -0
- package/dist/accessibility/a11y.d.ts.map +1 -0
- package/dist/accessibility/a11y.js +254 -0
- package/dist/accessibility/a11y.js.map +1 -0
- package/dist/components/VirtualGrid.d.ts +8 -0
- package/dist/components/VirtualGrid.d.ts.map +1 -0
- package/dist/components/VirtualGrid.js +187 -0
- package/dist/components/VirtualGrid.js.map +1 -0
- package/dist/components/VirtualList.d.ts +8 -0
- package/dist/components/VirtualList.d.ts.map +1 -0
- package/dist/components/VirtualList.js +102 -0
- package/dist/components/VirtualList.js.map +1 -0
- package/dist/core/MeasurementSystem.d.ts +52 -0
- package/dist/core/MeasurementSystem.d.ts.map +1 -0
- package/dist/core/MeasurementSystem.js +138 -0
- package/dist/core/MeasurementSystem.js.map +1 -0
- package/dist/core/VirtualizationEngine.d.ts +65 -0
- package/dist/core/VirtualizationEngine.d.ts.map +1 -0
- package/dist/core/VirtualizationEngine.js +203 -0
- package/dist/core/VirtualizationEngine.js.map +1 -0
- package/dist/examples/AdvancedExamples.d.ts +24 -0
- package/dist/examples/AdvancedExamples.d.ts.map +1 -0
- package/dist/examples/AdvancedExamples.js +216 -0
- package/dist/examples/AdvancedExamples.js.map +1 -0
- package/dist/examples/Example.d.ts +26 -0
- package/dist/examples/Example.d.ts.map +1 -0
- package/dist/examples/Example.js +186 -0
- package/dist/examples/Example.js.map +1 -0
- package/dist/hooks/useInfiniteScroll.d.ts +17 -0
- package/dist/hooks/useInfiniteScroll.d.ts.map +1 -0
- package/dist/hooks/useInfiniteScroll.js +41 -0
- package/dist/hooks/useInfiniteScroll.js.map +1 -0
- package/dist/hooks/useLazyLoad.d.ts +16 -0
- package/dist/hooks/useLazyLoad.d.ts.map +1 -0
- package/dist/hooks/useLazyLoad.js +34 -0
- package/dist/hooks/useLazyLoad.js.map +1 -0
- package/dist/hooks/useScrollRestoration.d.ts +10 -0
- package/dist/hooks/useScrollRestoration.d.ts.map +1 -0
- package/dist/hooks/useScrollRestoration.js +63 -0
- package/dist/hooks/useScrollRestoration.js.map +1 -0
- package/dist/hooks/useVirtualList.d.ts +33 -0
- package/dist/hooks/useVirtualList.d.ts.map +1 -0
- package/dist/hooks/useVirtualList.js +226 -0
- package/dist/hooks/useVirtualList.js.map +1 -0
- package/dist/hooks/useVirtualizedSearch.d.ts +40 -0
- package/dist/hooks/useVirtualizedSearch.d.ts.map +1 -0
- package/dist/hooks/useVirtualizedSearch.js +168 -0
- package/dist/hooks/useVirtualizedSearch.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +11 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +6 -0
- package/dist/main.js.map +1 -0
- package/dist/performance/metrics.d.ts +110 -0
- package/dist/performance/metrics.d.ts.map +1 -0
- package/dist/performance/metrics.js +310 -0
- package/dist/performance/metrics.js.map +1 -0
- package/dist/plugin.d.ts +182 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +409 -0
- package/dist/plugin.js.map +1 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/helpers.d.ts +66 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +166 -0
- package/dist/utils/helpers.js.map +1 -0
- package/package.json +111 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { useState, useCallback, useRef, useEffect, } from 'react';
|
|
2
|
+
import { VirtualizationEngine } from '../core/VirtualizationEngine';
|
|
3
|
+
import { MeasurementSystem } from '../core/MeasurementSystem';
|
|
4
|
+
/**
|
|
5
|
+
* Virtualized list hook
|
|
6
|
+
*/
|
|
7
|
+
export function useVirtualList(params) {
|
|
8
|
+
const { items, containerHeight, overscan = 5, scrollDirection = 'forward', estimatedItemSize = 35, onScroll, onScrollEnd, stickyIndices = [], } = params;
|
|
9
|
+
/**
|
|
10
|
+
* Core systems
|
|
11
|
+
*/
|
|
12
|
+
const engineRef = useRef(new VirtualizationEngine(estimatedItemSize));
|
|
13
|
+
const measurementRef = useRef(new MeasurementSystem());
|
|
14
|
+
/**
|
|
15
|
+
* DOM refs
|
|
16
|
+
*/
|
|
17
|
+
const containerRef = useRef(null);
|
|
18
|
+
const innerRef = useRef(null);
|
|
19
|
+
/**
|
|
20
|
+
* Scroll state
|
|
21
|
+
*/
|
|
22
|
+
const [scrollOffset, setScrollOffset] = useState(0);
|
|
23
|
+
const [isScrolling, setIsScrolling] = useState(false);
|
|
24
|
+
const scrollTimeoutRef = useRef(null);
|
|
25
|
+
const lastScrollOffsetRef = useRef(0);
|
|
26
|
+
const scrollDirectionRef = useRef(scrollDirection);
|
|
27
|
+
/**
|
|
28
|
+
* Virtual items
|
|
29
|
+
*/
|
|
30
|
+
const [virtualItems, setVirtualItems] = useState([]);
|
|
31
|
+
/**
|
|
32
|
+
* Calculate visible items
|
|
33
|
+
*/
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const engine = engineRef.current;
|
|
36
|
+
const visibleItems = engine.getVisibleItems(scrollOffset, containerHeight, items.length, overscan, scrollDirectionRef.current);
|
|
37
|
+
const nextVirtualItems = visibleItems.map((item) => ({
|
|
38
|
+
index: item.index,
|
|
39
|
+
offset: item.offset,
|
|
40
|
+
size: item.size,
|
|
41
|
+
isSticky: stickyIndices.includes(item.index),
|
|
42
|
+
}));
|
|
43
|
+
/**
|
|
44
|
+
* Prevent infinite re-renders
|
|
45
|
+
*/
|
|
46
|
+
setVirtualItems((prev) => {
|
|
47
|
+
if (prev.length ===
|
|
48
|
+
nextVirtualItems.length) {
|
|
49
|
+
let changed = false;
|
|
50
|
+
for (let i = 0; i < prev.length; i++) {
|
|
51
|
+
const prevItem = prev[i];
|
|
52
|
+
const nextItem = nextVirtualItems[i];
|
|
53
|
+
if (prevItem.index !==
|
|
54
|
+
nextItem.index ||
|
|
55
|
+
prevItem.offset !==
|
|
56
|
+
nextItem.offset ||
|
|
57
|
+
prevItem.size !==
|
|
58
|
+
nextItem.size ||
|
|
59
|
+
prevItem.isSticky !==
|
|
60
|
+
nextItem.isSticky) {
|
|
61
|
+
changed = true;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (!changed) {
|
|
66
|
+
return prev;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return nextVirtualItems;
|
|
70
|
+
});
|
|
71
|
+
}, [
|
|
72
|
+
scrollOffset,
|
|
73
|
+
containerHeight,
|
|
74
|
+
items.length,
|
|
75
|
+
overscan,
|
|
76
|
+
stickyIndices,
|
|
77
|
+
]);
|
|
78
|
+
/**
|
|
79
|
+
* Handle scrolling
|
|
80
|
+
*/
|
|
81
|
+
const handleScroll = useCallback((e) => {
|
|
82
|
+
const target = e.currentTarget;
|
|
83
|
+
const newScrollOffset = target.scrollTop;
|
|
84
|
+
/**
|
|
85
|
+
* Skip duplicate updates
|
|
86
|
+
*/
|
|
87
|
+
if (newScrollOffset ===
|
|
88
|
+
lastScrollOffsetRef.current) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Detect direction
|
|
93
|
+
*/
|
|
94
|
+
const direction = newScrollOffset >
|
|
95
|
+
lastScrollOffsetRef.current
|
|
96
|
+
? 'forward'
|
|
97
|
+
: 'reverse';
|
|
98
|
+
scrollDirectionRef.current =
|
|
99
|
+
direction;
|
|
100
|
+
lastScrollOffsetRef.current =
|
|
101
|
+
newScrollOffset;
|
|
102
|
+
setScrollOffset(newScrollOffset);
|
|
103
|
+
setIsScrolling(true);
|
|
104
|
+
/**
|
|
105
|
+
* User callback
|
|
106
|
+
*/
|
|
107
|
+
if (onScroll) {
|
|
108
|
+
onScroll(newScrollOffset, direction);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Debounce scroll end
|
|
112
|
+
*/
|
|
113
|
+
if (scrollTimeoutRef.current) {
|
|
114
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
115
|
+
}
|
|
116
|
+
scrollTimeoutRef.current =
|
|
117
|
+
setTimeout(() => {
|
|
118
|
+
setIsScrolling(false);
|
|
119
|
+
if (onScrollEnd) {
|
|
120
|
+
onScrollEnd();
|
|
121
|
+
}
|
|
122
|
+
}, 150);
|
|
123
|
+
}, [onScroll, onScrollEnd]);
|
|
124
|
+
/**
|
|
125
|
+
* Attach scroll listener
|
|
126
|
+
*/
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
const container = containerRef.current;
|
|
129
|
+
if (!container) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const listener = (e) => {
|
|
133
|
+
handleScroll(e);
|
|
134
|
+
};
|
|
135
|
+
container.addEventListener('scroll', listener);
|
|
136
|
+
return () => {
|
|
137
|
+
container.removeEventListener('scroll', listener);
|
|
138
|
+
};
|
|
139
|
+
}, [handleScroll]);
|
|
140
|
+
/**
|
|
141
|
+
* Measure item sizes
|
|
142
|
+
*/
|
|
143
|
+
const handleItemMeasure = useCallback((index, size) => {
|
|
144
|
+
engineRef.current.recordItemSize(index, size);
|
|
145
|
+
}, []);
|
|
146
|
+
/**
|
|
147
|
+
* Start measuring
|
|
148
|
+
*/
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
const container = containerRef.current;
|
|
151
|
+
if (container) {
|
|
152
|
+
measurementRef.current.startMeasuring(container, handleItemMeasure);
|
|
153
|
+
}
|
|
154
|
+
return () => {
|
|
155
|
+
measurementRef.current.stopMeasuring();
|
|
156
|
+
};
|
|
157
|
+
}, [handleItemMeasure]);
|
|
158
|
+
/**
|
|
159
|
+
* Scroll to item
|
|
160
|
+
*/
|
|
161
|
+
const scrollToItem = useCallback((index, alignment = 'start') => {
|
|
162
|
+
const offset = engineRef.current.getScrollOffsetForIndex(index, containerHeight, alignment);
|
|
163
|
+
if (containerRef.current) {
|
|
164
|
+
containerRef.current.scrollTop =
|
|
165
|
+
offset;
|
|
166
|
+
}
|
|
167
|
+
}, [containerHeight]);
|
|
168
|
+
/**
|
|
169
|
+
* Scroll to offset
|
|
170
|
+
*/
|
|
171
|
+
const scrollToOffset = useCallback((offset) => {
|
|
172
|
+
if (containerRef.current) {
|
|
173
|
+
containerRef.current.scrollTop =
|
|
174
|
+
offset;
|
|
175
|
+
}
|
|
176
|
+
}, []);
|
|
177
|
+
/**
|
|
178
|
+
* Get item style
|
|
179
|
+
*/
|
|
180
|
+
const getItemStyle = useCallback((index, size) => {
|
|
181
|
+
const offset = engineRef.current.getItemOffset(index);
|
|
182
|
+
const isStickyItem = stickyIndices.includes(index);
|
|
183
|
+
return {
|
|
184
|
+
position: isStickyItem
|
|
185
|
+
? 'sticky'
|
|
186
|
+
: 'absolute',
|
|
187
|
+
top: isStickyItem
|
|
188
|
+
? 0
|
|
189
|
+
: offset,
|
|
190
|
+
left: 0,
|
|
191
|
+
width: '100%',
|
|
192
|
+
height: size,
|
|
193
|
+
zIndex: isStickyItem
|
|
194
|
+
? 10
|
|
195
|
+
: 0,
|
|
196
|
+
};
|
|
197
|
+
}, [stickyIndices]);
|
|
198
|
+
/**
|
|
199
|
+
* Cleanup
|
|
200
|
+
*/
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
return () => {
|
|
203
|
+
if (scrollTimeoutRef.current) {
|
|
204
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
205
|
+
}
|
|
206
|
+
measurementRef.current.destroy();
|
|
207
|
+
};
|
|
208
|
+
}, []);
|
|
209
|
+
/**
|
|
210
|
+
* Total size
|
|
211
|
+
*/
|
|
212
|
+
const totalSize = engineRef.current.getTotalSize();
|
|
213
|
+
return {
|
|
214
|
+
virtualItems,
|
|
215
|
+
isScrolling,
|
|
216
|
+
scrollOffset,
|
|
217
|
+
totalSize,
|
|
218
|
+
scrollToItem,
|
|
219
|
+
scrollToOffset,
|
|
220
|
+
setScrollOffset,
|
|
221
|
+
containerRef,
|
|
222
|
+
innerRef,
|
|
223
|
+
getItemStyle,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=useVirtualList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useVirtualList.js","sourceRoot":"","sources":["../../src/hooks/useVirtualList.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface UseVirtualizedSearchParams<T> {
|
|
3
|
+
items: T[];
|
|
4
|
+
searchValue: string;
|
|
5
|
+
searchFields: (keyof T)[];
|
|
6
|
+
matchThreshold?: number;
|
|
7
|
+
caseSensitive?: boolean;
|
|
8
|
+
highlightColor?: string;
|
|
9
|
+
}
|
|
10
|
+
interface UseVirtualizedSearchReturn<T> {
|
|
11
|
+
filteredItems: T[];
|
|
12
|
+
highlightMatch: (text: string) => React.ReactNode;
|
|
13
|
+
resultCount: number;
|
|
14
|
+
hasMatch: (item: T) => boolean;
|
|
15
|
+
isSearching: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook for efficient searching within virtualized lists
|
|
19
|
+
* Filters items without re-measuring
|
|
20
|
+
*/
|
|
21
|
+
export declare function useVirtualizedSearch<T>({ items, searchValue, searchFields, caseSensitive, highlightColor, }: UseVirtualizedSearchParams<T>): UseVirtualizedSearchReturn<T>;
|
|
22
|
+
export default useVirtualizedSearch;
|
|
23
|
+
interface UseVirtualizedSearchParams<T> {
|
|
24
|
+
items: T[];
|
|
25
|
+
searchValue: string;
|
|
26
|
+
searchFields: (keyof T)[];
|
|
27
|
+
caseSensitive?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Hook for efficient searching within virtualized lists
|
|
31
|
+
* Returns filtered items and match detection
|
|
32
|
+
* JSX rendering is handled in useVirtualizedSearch.tsx
|
|
33
|
+
*/
|
|
34
|
+
export declare function virtualizedSearch<T>({ items, searchValue, searchFields, caseSensitive, }: UseVirtualizedSearchParams<T>): {
|
|
35
|
+
filteredItems: T[];
|
|
36
|
+
hasMatch: (item: T) => boolean;
|
|
37
|
+
resultCount: number;
|
|
38
|
+
query: string;
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=useVirtualizedSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useVirtualizedSearch.d.ts","sourceRoot":"","sources":["../../src/hooks/useVirtualizedSearch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,UAAU,0BAA0B,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,0BAA0B,CAAC,CAAC;IAClC,aAAa,EAAE,CAAC,EAAE,CAAC;IACnB,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAC/B,WAAW,EAAE,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,EACpC,KAAK,EACL,WAAW,EACX,YAAY,EACZ,aAAqB,EACrB,cAA0B,GAC7B,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,0BAA0B,CAAC,CAAC,CAAC,CAuI/D;AAED,eAAe,oBAAoB,CAAC;AAEpC,UAAU,0BAA0B,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,EACjC,KAAK,EACL,WAAW,EACX,YAAY,EACZ,aAAqB,GACxB,EAAE,0BAA0B,CAAC,CAAC,CAAC;;qBA2BJ,CAAC,KAAG,OAAO;;;EA0BtC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useMemo, useCallback, useDeferredValue } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Hook for efficient searching within virtualized lists
|
|
5
|
+
* Filters items without re-measuring
|
|
6
|
+
*/
|
|
7
|
+
export function useVirtualizedSearch({ items, searchValue, searchFields, caseSensitive = false, highlightColor = '#ffeb3b', }) {
|
|
8
|
+
// FIX #1: Memoize the normalized query string
|
|
9
|
+
const normalizedQuery = useMemo(() => {
|
|
10
|
+
const trimmed = searchValue.trim();
|
|
11
|
+
return caseSensitive ? trimmed : trimmed.toLowerCase();
|
|
12
|
+
}, [searchValue, caseSensitive]);
|
|
13
|
+
// FIX #2: Memoize the regex pattern to avoid recompilation
|
|
14
|
+
const queryPattern = useMemo(() => {
|
|
15
|
+
if (!normalizedQuery)
|
|
16
|
+
return null;
|
|
17
|
+
try {
|
|
18
|
+
const escaped = normalizedQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
19
|
+
return new RegExp(`(${escaped})`, caseSensitive ? 'g' : 'gi');
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.warn('Invalid search pattern:', error);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}, [normalizedQuery, caseSensitive]);
|
|
26
|
+
// FIX #5: Use deferred value for non-blocking search
|
|
27
|
+
const deferredQuery = useDeferredValue(normalizedQuery);
|
|
28
|
+
const isSearching = deferredQuery !== normalizedQuery;
|
|
29
|
+
// FIX #3 & #6: Improved filtering with proper error handling
|
|
30
|
+
const filteredItems = useMemo(() => {
|
|
31
|
+
if (!deferredQuery)
|
|
32
|
+
return items;
|
|
33
|
+
return items.filter((item) => {
|
|
34
|
+
return searchFields.some((field) => {
|
|
35
|
+
try {
|
|
36
|
+
const value = item[field];
|
|
37
|
+
if (value === null || value === undefined) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const stringValue = String(value).trim();
|
|
41
|
+
if (!stringValue) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const normalizedValue = caseSensitive
|
|
45
|
+
? stringValue
|
|
46
|
+
: stringValue.toLowerCase();
|
|
47
|
+
return normalizedValue.includes(deferredQuery);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.warn(`Error accessing field ${String(field)}:`, error);
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}, [items, deferredQuery, searchFields, caseSensitive]);
|
|
56
|
+
// Helper function to check if item matches
|
|
57
|
+
const hasMatch = useCallback((item) => {
|
|
58
|
+
if (!deferredQuery)
|
|
59
|
+
return true;
|
|
60
|
+
return searchFields.some((field) => {
|
|
61
|
+
try {
|
|
62
|
+
const value = item[field];
|
|
63
|
+
if (value === null || value === undefined)
|
|
64
|
+
return false;
|
|
65
|
+
const stringValue = String(value).trim();
|
|
66
|
+
const normalizedValue = caseSensitive
|
|
67
|
+
? stringValue
|
|
68
|
+
: stringValue.toLowerCase();
|
|
69
|
+
return normalizedValue.includes(deferredQuery);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}, [deferredQuery, searchFields, caseSensitive]);
|
|
76
|
+
// FIX #4 & #7: Improved highlighting with accessibility support
|
|
77
|
+
const highlightMatch = useCallback((text) => {
|
|
78
|
+
if (!normalizedQuery || !queryPattern)
|
|
79
|
+
return text;
|
|
80
|
+
if (!text)
|
|
81
|
+
return null;
|
|
82
|
+
try {
|
|
83
|
+
queryPattern.lastIndex = 0;
|
|
84
|
+
const parts = String(text).split(queryPattern);
|
|
85
|
+
return parts.map((part, index) => {
|
|
86
|
+
// Even indices are non-matching parts
|
|
87
|
+
if (index % 2 === 0) {
|
|
88
|
+
return part ? (_jsx(React.Fragment, { children: part }, index)) : null;
|
|
89
|
+
}
|
|
90
|
+
// Odd indices are matching parts
|
|
91
|
+
return (_jsx("mark", { style: {
|
|
92
|
+
backgroundColor: highlightColor,
|
|
93
|
+
padding: '0 2px',
|
|
94
|
+
borderRadius: '2px',
|
|
95
|
+
}, "aria-label": `Highlighted search result: ${part}`, children: part }, index));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
console.warn('Error highlighting match:', error);
|
|
100
|
+
return text;
|
|
101
|
+
}
|
|
102
|
+
}, [normalizedQuery, queryPattern, highlightColor]);
|
|
103
|
+
return {
|
|
104
|
+
filteredItems,
|
|
105
|
+
highlightMatch,
|
|
106
|
+
resultCount: filteredItems.length,
|
|
107
|
+
hasMatch,
|
|
108
|
+
isSearching,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export default useVirtualizedSearch;
|
|
112
|
+
/**
|
|
113
|
+
* Hook for efficient searching within virtualized lists
|
|
114
|
+
* Returns filtered items and match detection
|
|
115
|
+
* JSX rendering is handled in useVirtualizedSearch.tsx
|
|
116
|
+
*/
|
|
117
|
+
export function virtualizedSearch({ items, searchValue, searchFields, caseSensitive = false, }) {
|
|
118
|
+
const normalizedQuery = searchValue.trim();
|
|
119
|
+
const query = caseSensitive ? normalizedQuery : normalizedQuery.toLowerCase();
|
|
120
|
+
const filteredItems = items.filter((item) => {
|
|
121
|
+
if (!query)
|
|
122
|
+
return true;
|
|
123
|
+
return searchFields.some((field) => {
|
|
124
|
+
try {
|
|
125
|
+
const value = item[field];
|
|
126
|
+
if (value === null || value === undefined)
|
|
127
|
+
return false;
|
|
128
|
+
const stringValue = String(value).trim();
|
|
129
|
+
if (!stringValue)
|
|
130
|
+
return false;
|
|
131
|
+
const normalizedValue = caseSensitive
|
|
132
|
+
? stringValue
|
|
133
|
+
: stringValue.toLowerCase();
|
|
134
|
+
return normalizedValue.includes(query);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.warn(`Error accessing field ${String(field)}:`, error);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
const hasMatch = (item) => {
|
|
143
|
+
if (!query)
|
|
144
|
+
return true;
|
|
145
|
+
return searchFields.some((field) => {
|
|
146
|
+
try {
|
|
147
|
+
const value = item[field];
|
|
148
|
+
if (value === null || value === undefined)
|
|
149
|
+
return false;
|
|
150
|
+
const stringValue = String(value).trim();
|
|
151
|
+
const normalizedValue = caseSensitive
|
|
152
|
+
? stringValue
|
|
153
|
+
: stringValue.toLowerCase();
|
|
154
|
+
return normalizedValue.includes(query);
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
return {
|
|
162
|
+
filteredItems,
|
|
163
|
+
hasMatch,
|
|
164
|
+
resultCount: filteredItems.length,
|
|
165
|
+
query,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=useVirtualizedSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useVirtualizedSearch.js","sourceRoot":"","sources":["../../src/hooks/useVirtualizedSearch.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { VirtualList } from './components/VirtualList';
|
|
2
|
+
export { VirtualGrid } from './components/VirtualGrid';
|
|
3
|
+
export { useVirtualList } from './hooks/useVirtualList';
|
|
4
|
+
export { useVirtualizedSearch } from './hooks/useVirtualizedSearch';
|
|
5
|
+
export { useLazyLoad } from './hooks/useLazyLoad';
|
|
6
|
+
export { useInfiniteScroll } from './hooks/useInfiniteScroll';
|
|
7
|
+
export { useScrollRestoration } from './hooks/useScrollRestoration';
|
|
8
|
+
export { VirtualizationEngine } from './core/VirtualizationEngine';
|
|
9
|
+
export { MeasurementSystem } from './core/MeasurementSystem';
|
|
10
|
+
export type { ScrollDirection, LayoutMode, ItemSize, VirtualItem, ScrollState, MeasurementCache, VirtualListProps, VirtualGridProps, RenderItemProps, UseVirtualListOptions, VirtualRange, } from './types';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,YAAY,EACR,eAAe,EACf,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,YAAY,GACf,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import e,{useRef as t,useState as r,useEffect as n,useCallback as i,forwardRef as o,useImperativeHandle as s,useMemo as a,useDeferredValue as c}from"react";var l,u={exports:{}},f={};var p,d,h={};
|
|
2
|
+
/**
|
|
3
|
+
* @license React
|
|
4
|
+
* react-jsx-runtime.development.js
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
7
|
+
*
|
|
8
|
+
* This source code is licensed under the MIT license found in the
|
|
9
|
+
* LICENSE file in the root directory of this source tree.
|
|
10
|
+
*/function m(){return p||(p=1,"production"!==process.env.NODE_ENV&&function(){var t=e,r=Symbol.for("react.element"),n=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),a=Symbol.for("react.provider"),c=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),u=Symbol.for("react.suspense"),f=Symbol.for("react.suspense_list"),p=Symbol.for("react.memo"),d=Symbol.for("react.lazy"),m=Symbol.for("react.offscreen"),y=Symbol.iterator;var g=t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;function v(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];!function(e,t,r){var n=g.ReactDebugCurrentFrame,i=n.getStackAddendum();""!==i&&(t+="%s",r=r.concat([i]));var o=r.map(function(e){return String(e)});o.unshift("Warning: "+t),Function.prototype.apply.call(console[e],console,o)}("error",e,r)}var b;function S(e){return e.displayName||"Context"}function w(e){if(null==e)return null;if("number"==typeof e.tag&&v("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),"function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case i:return"Fragment";case n:return"Portal";case s:return"Profiler";case o:return"StrictMode";case u:return"Suspense";case f:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case c:return S(e)+".Consumer";case a:return S(e._context)+".Provider";case l:return function(e,t,r){var n=e.displayName;if(n)return n;var i=t.displayName||t.name||"";return""!==i?r+"("+i+")":r}(e,e.render,"ForwardRef");case p:var t=e.displayName||null;return null!==t?t:w(e.type)||"Memo";case d:var r=e,h=r._payload,m=r._init;try{return w(m(h))}catch(e){return null}}return null}b=Symbol.for("react.module.reference");var O,x,k,z,I,_,j,R=Object.assign,M=0;function E(){}E.__reactDisabledLog=!0;var T,P=g.ReactCurrentDispatcher;function N(e,t,r){if(void 0===T)try{throw Error()}catch(e){var n=e.stack.trim().match(/\n( *(at )?)/);T=n&&n[1]||""}return"\n"+T+e}var $,C=!1,F="function"==typeof WeakMap?WeakMap:Map;function D(e,t){if(!e||C)return"";var r,n=$.get(e);if(void 0!==n)return n;C=!0;var i,o=Error.prepareStackTrace;Error.prepareStackTrace=void 0,i=P.current,P.current=null,function(){if(0===M){O=console.log,x=console.info,k=console.warn,z=console.error,I=console.group,_=console.groupCollapsed,j=console.groupEnd;var e={configurable:!0,enumerable:!0,value:E,writable:!0};Object.defineProperties(console,{info:e,log:e,warn:e,error:e,group:e,groupCollapsed:e,groupEnd:e})}M++}();try{if(t){var s=function(){throw Error()};if(Object.defineProperty(s.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(s,[])}catch(e){r=e}Reflect.construct(e,[],s)}else{try{s.call()}catch(e){r=e}e.call(s.prototype)}}else{try{throw Error()}catch(e){r=e}e()}}catch(t){if(t&&r&&"string"==typeof t.stack){for(var a=t.stack.split("\n"),c=r.stack.split("\n"),l=a.length-1,u=c.length-1;l>=1&&u>=0&&a[l]!==c[u];)u--;for(;l>=1&&u>=0;l--,u--)if(a[l]!==c[u]){if(1!==l||1!==u)do{if(l--,--u<0||a[l]!==c[u]){var f="\n"+a[l].replace(" at new "," at ");return e.displayName&&f.includes("<anonymous>")&&(f=f.replace("<anonymous>",e.displayName)),"function"==typeof e&&$.set(e,f),f}}while(l>=1&&u>=0);break}}}finally{C=!1,P.current=i,function(){if(0===--M){var e={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:R({},e,{value:O}),info:R({},e,{value:x}),warn:R({},e,{value:k}),error:R({},e,{value:z}),group:R({},e,{value:I}),groupCollapsed:R({},e,{value:_}),groupEnd:R({},e,{value:j})})}M<0&&v("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}(),Error.prepareStackTrace=o}var p=e?e.displayName||e.name:"",d=p?N(p):"";return"function"==typeof e&&$.set(e,d),d}function L(e,t,r){if(null==e)return"";if("function"==typeof e)return D(e,!(!(n=e.prototype)||!n.isReactComponent));var n;if("string"==typeof e)return N(e);switch(e){case u:return N("Suspense");case f:return N("SuspenseList")}if("object"==typeof e)switch(e.$$typeof){case l:return D(e.render,!1);case p:return L(e.type,t,r);case d:var i=e,o=i._payload,s=i._init;try{return L(s(o),t,r)}catch(e){}}return""}$=new F;var A=Object.prototype.hasOwnProperty,V={},W=g.ReactDebugCurrentFrame;function H(e){if(e){var t=e._owner,r=L(e.type,e._source,t?t.type:null);W.setExtraStackFrame(r)}else W.setExtraStackFrame(null)}var U=Array.isArray;function K(e){return U(e)}function Y(e){return""+e}function B(e){if(function(e){try{return Y(e),!1}catch(e){return!0}}(e))return v("The provided key is an unsupported type %s. This value must be coerced to a string before before using it here.",function(e){return"function"==typeof Symbol&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object"}(e)),Y(e)}var J,q,X,G=g.ReactCurrentOwner,Q={key:!0,ref:!0,__self:!0,__source:!0};X={};function Z(e,t,n,i,o){var s,a={},c=null,l=null;for(s in void 0!==n&&(B(n),c=""+n),function(e){if(A.call(e,"key")){var t=Object.getOwnPropertyDescriptor(e,"key").get;if(t&&t.isReactWarning)return!1}return void 0!==e.key}(t)&&(B(t.key),c=""+t.key),function(e){if(A.call(e,"ref")){var t=Object.getOwnPropertyDescriptor(e,"ref").get;if(t&&t.isReactWarning)return!1}return void 0!==e.ref}(t)&&(l=t.ref,function(e,t){if("string"==typeof e.ref&&G.current&&t&&G.current.stateNode!==t){var r=w(G.current.type);X[r]||(v('Component "%s" contains the string ref "%s". Support for string refs will be removed in a future major release. This case cannot be automatically converted to an arrow function. We ask you to manually fix this case by using useRef() or createRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref',w(G.current.type),e.ref),X[r]=!0)}}(t,o)),t)A.call(t,s)&&!Q.hasOwnProperty(s)&&(a[s]=t[s]);if(e&&e.defaultProps){var u=e.defaultProps;for(s in u)void 0===a[s]&&(a[s]=u[s])}if(c||l){var f="function"==typeof e?e.displayName||e.name||"Unknown":e;c&&function(e,t){var r=function(){J||(J=!0,v("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)",t))};r.isReactWarning=!0,Object.defineProperty(e,"key",{get:r,configurable:!0})}(a,f),l&&function(e,t){var r=function(){q||(q=!0,v("%s: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)",t))};r.isReactWarning=!0,Object.defineProperty(e,"ref",{get:r,configurable:!0})}(a,f)}return function(e,t,n,i,o,s,a){var c={$$typeof:r,type:e,key:t,ref:n,props:a,_owner:s,_store:{}};return Object.defineProperty(c._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:!1}),Object.defineProperty(c,"_self",{configurable:!1,enumerable:!1,writable:!1,value:i}),Object.defineProperty(c,"_source",{configurable:!1,enumerable:!1,writable:!1,value:o}),Object.freeze&&(Object.freeze(c.props),Object.freeze(c)),c}(e,c,l,o,i,G.current,a)}var ee,te=g.ReactCurrentOwner,re=g.ReactDebugCurrentFrame;function ne(e){if(e){var t=e._owner,r=L(e.type,e._source,t?t.type:null);re.setExtraStackFrame(r)}else re.setExtraStackFrame(null)}function ie(e){return"object"==typeof e&&null!==e&&e.$$typeof===r}function oe(){if(te.current){var e=w(te.current.type);if(e)return"\n\nCheck the render method of `"+e+"`."}return""}ee=!1;var se={};function ae(e,t){if(e._store&&!e._store.validated&&null==e.key){e._store.validated=!0;var r=function(e){var t=oe();if(!t){var r="string"==typeof e?e:e.displayName||e.name;r&&(t="\n\nCheck the top-level render call using <"+r+">.")}return t}(t);if(!se[r]){se[r]=!0;var n="";e&&e._owner&&e._owner!==te.current&&(n=" It was passed a child from "+w(e._owner.type)+"."),ne(e),v('Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.',r,n),ne(null)}}}function ce(e,t){if("object"==typeof e)if(K(e))for(var r=0;r<e.length;r++){var n=e[r];ie(n)&&ae(n,t)}else if(ie(e))e._store&&(e._store.validated=!0);else if(e){var i=function(e){if(null===e||"object"!=typeof e)return null;var t=y&&e[y]||e["@@iterator"];return"function"==typeof t?t:null}(e);if("function"==typeof i&&i!==e.entries)for(var o,s=i.call(e);!(o=s.next()).done;)ie(o.value)&&ae(o.value,t)}}function le(e){var t,r=e.type;if(null!=r&&"string"!=typeof r){if("function"==typeof r)t=r.propTypes;else{if("object"!=typeof r||r.$$typeof!==l&&r.$$typeof!==p)return;t=r.propTypes}if(t){var n=w(r);!function(e,t,r,n,i){var o=Function.call.bind(A);for(var s in e)if(o(e,s)){var a=void 0;try{if("function"!=typeof e[s]){var c=Error((n||"React class")+": "+r+" type `"+s+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof e[s]+"`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.");throw c.name="Invariant Violation",c}a=e[s](t,s,n,r,null,"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED")}catch(e){a=e}!a||a instanceof Error||(H(i),v("%s: type specification of %s `%s` is invalid; the type checker function must return `null` or an `Error` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).",n||"React class",r,s,typeof a),H(null)),a instanceof Error&&!(a.message in V)&&(V[a.message]=!0,H(i),v("Failed %s type: %s",r,a.message),H(null))}}(t,e.props,"prop",n,e)}else if(void 0!==r.PropTypes&&!ee){ee=!0,v("Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?",w(r)||"Unknown")}"function"!=typeof r.getDefaultProps||r.getDefaultProps.isReactClassApproved||v("getDefaultProps is only used on classic React.createClass definitions. Use a static property named `defaultProps` instead.")}}var ue={};function fe(e,t,n,h,y,g){var S=function(e){return"string"==typeof e||"function"==typeof e||e===i||e===s||e===o||e===u||e===f||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===d||e.$$typeof===p||e.$$typeof===a||e.$$typeof===c||e.$$typeof===l||e.$$typeof===b||void 0!==e.getModuleId)}(e);if(!S){var O="";(void 0===e||"object"==typeof e&&null!==e&&0===Object.keys(e).length)&&(O+=" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.");var x,k=function(e){return void 0!==e?"\n\nCheck your code at "+e.fileName.replace(/^.*[\\\/]/,"")+":"+e.lineNumber+".":""}(y);O+=k||oe(),null===e?x="null":K(e)?x="array":void 0!==e&&e.$$typeof===r?(x="<"+(w(e.type)||"Unknown")+" />",O=" Did you accidentally export a JSX literal instead of a component?"):x=typeof e,v("React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",x,O)}var z=Z(e,t,n,y,g);if(null==z)return z;if(S){var I=t.children;if(void 0!==I)if(h)if(K(I)){for(var _=0;_<I.length;_++)ce(I[_],e);Object.freeze&&Object.freeze(I)}else v("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else ce(I,e)}if(A.call(t,"key")){var j=w(e),R=Object.keys(t).filter(function(e){return"key"!==e}),M=R.length>0?"{key: someKey, "+R.join(": ..., ")+": ...}":"{key: someKey}";if(!ue[j+M])v('A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',M,j,R.length>0?"{"+R.join(": ..., ")+": ...}":"{}",j),ue[j+M]=!0}return e===i?function(e){for(var t=Object.keys(e.props),r=0;r<t.length;r++){var n=t[r];if("children"!==n&&"key"!==n){ne(e),v("Invalid prop `%s` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.",n),ne(null);break}}null!==e.ref&&(ne(e),v("Invalid attribute `ref` supplied to `React.Fragment`."),ne(null))}(z):le(z),z}var pe=function(e,t,r){return fe(e,t,r,!1)},de=function(e,t,r){return fe(e,t,r,!0)};h.Fragment=i,h.jsx=pe,h.jsxs=de}()),h}var y=(d||(d=1,"production"===process.env.NODE_ENV?u.exports=function(){if(l)return f;l=1;var t=e,r=Symbol.for("react.element"),n=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,o=t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,s={key:!0,ref:!0,__self:!0,__source:!0};function a(e,t,n){var a,c={},l=null,u=null;for(a in void 0!==n&&(l=""+n),void 0!==t.key&&(l=""+t.key),void 0!==t.ref&&(u=t.ref),t)i.call(t,a)&&!s.hasOwnProperty(a)&&(c[a]=t[a]);if(e&&e.defaultProps)for(a in t=e.defaultProps)void 0===c[a]&&(c[a]=t[a]);return{$$typeof:r,type:e,key:l,ref:u,props:c,_owner:o.current}}return f.Fragment=n,f.jsx=a,f.jsxs=a,f}():u.exports=m()),u.exports);class g{constructor(e=35){Object.defineProperty(this,"itemSizeMap",{enumerable:!0,configurable:!0,writable:!0,value:{}}),Object.defineProperty(this,"itemOffsets",{enumerable:!0,configurable:!0,writable:!0,value:[0]}),Object.defineProperty(this,"totalSize",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"estimatedItemSize",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.estimatedItemSize=e}recordItemSize(e,t){this.itemSizeMap[e]!==t&&(this.itemSizeMap[e]=t,this.recalculateOffsets())}recalculateOffsets(){let e=0;this.itemOffsets=[0];const t=Object.keys(this.itemSizeMap).map(Number).sort((e,t)=>e-t);for(const r of t){e+=this.itemSizeMap[r]??this.estimatedItemSize,this.itemOffsets[r+1]=e}this.totalSize=e}getItemSize(e){return this.itemSizeMap[e]??this.estimatedItemSize}getItemOffset(e){if(void 0!==this.itemOffsets[e])return this.itemOffsets[e];let t=0;for(let r=0;r<e;r++)t+=this.getItemSize(r);return t}getTotalSize(){return this.totalSize}getVisibleRange(e,t,r,n=5,i="forward"){if("reverse"===i)return this.getVisibleRangeReverse(e,t,r,n);let o=0,s=r-1;for(let t=0;t<r;t++){if(this.getItemOffset(t)+this.getItemSize(t)>=e){o=t;break}}for(let n=o;n<r;n++){if(this.getItemOffset(n)>=e+t){s=n;break}}return{startIndex:Math.max(0,o-n),endIndex:Math.min(r-1,s+n),overscanStartIndex:o,overscanEndIndex:s}}getVisibleRangeReverse(e,t,r,n){const i=this.getTotalSize(),o=Math.max(0,i-e-t);return this.getVisibleRange(o,t,r,n,"forward")}getVisibleItems(e,t,r,n,i="forward"){const o=this.getVisibleRange(e,t,r,n,i),s=[];for(let e=o.startIndex;e<=o.endIndex&&e<r;e++)s.push({index:e,size:this.getItemSize(e),offset:this.getItemOffset(e)});return s}getScrollOffsetForIndex(e,t,r="start"){const n=this.getItemOffset(e),i=this.getItemSize(e);switch(r){case"center":return Math.max(0,n-(t-i)/2);case"end":return Math.max(0,n-t+i);default:return Math.max(0,n)}}clearCache(){this.itemSizeMap={},this.itemOffsets=[0],this.totalSize=0}getCache(){return{...this.itemSizeMap}}getAdaptiveOverscan(e,t=5){const r=Math.min(3,Math.max(1,e/10));return Math.ceil(t*r)}}class v{constructor(){Object.defineProperty(this,"resizeObserver",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"measurements",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"pendingMeasurements",{enumerable:!0,configurable:!0,writable:!0,value:new Set}),Object.defineProperty(this,"onMeasure",{enumerable:!0,configurable:!0,writable:!0,value:null}),"undefined"!=typeof window&&"ResizeObserver"in window&&(this.resizeObserver=new ResizeObserver(this.handleResize.bind(this)))}startMeasuring(e,t){if(this.onMeasure=t,this.resizeObserver){e.querySelectorAll("[data-virtualize-index]").forEach(e=>{this.resizeObserver?.observe(e)})}}stopMeasuring(){this.resizeObserver&&this.resizeObserver.disconnect(),this.measurements.clear(),this.pendingMeasurements.clear()}handleResize(e){e.forEach(e=>{const t=e.target,r=t.getAttribute("data-virtualize-index");if(r){const n=e.contentRect.height||t.offsetHeight,i=parseInt(r,10);this.measurements.get(i)!==n&&(this.measurements.set(i,n),this.pendingMeasurements.add(i),this.onMeasure&&this.onMeasure(i,n))}})}observeItem(e,t){t.setAttribute("data-virtualize-index",String(e)),this.resizeObserver&&this.resizeObserver.observe(t),this.syncMeasure(e,t)}syncMeasure(e,t){const r=t.offsetHeight;r>0&&this.measurements.get(e)!==r&&(this.measurements.set(e,r),this.onMeasure&&this.onMeasure(e,r))}unobserveItem(e){this.resizeObserver&&this.resizeObserver.unobserve(e)}getMeasurement(e){return this.measurements.get(e)}getAllMeasurements(){return new Map(this.measurements)}clearPending(){this.pendingMeasurements.clear()}destroy(){this.stopMeasuring(),this.measurements.clear(),this.pendingMeasurements.clear(),this.onMeasure=null}}function b(e){const{items:o,containerHeight:s,overscan:a=5,scrollDirection:c="forward",estimatedItemSize:l=35,onScroll:u,onScrollEnd:f,stickyIndices:p=[]}=e,d=t(new g(l)),h=t(new v),m=t(null),y=t(null),[b,S]=r(0),[w,O]=r(!1),x=t(null),k=t(0),z=t(c),[I,_]=r([]);n(()=>{const e=d.current.getVisibleItems(b,s,o.length,a,z.current).map(e=>({index:e.index,offset:e.offset,size:e.size,isSticky:p.includes(e.index)}));_(t=>{if(t.length===e.length){let r=!1;for(let n=0;n<t.length;n++){const i=t[n],o=e[n];if(i.index!==o.index||i.offset!==o.offset||i.size!==o.size||i.isSticky!==o.isSticky){r=!0;break}}if(!r)return t}return e})},[b,s,o.length,a,p]);const j=i(e=>{const t=e.currentTarget.scrollTop;if(t===k.current)return;const r=t>k.current?"forward":"reverse";z.current=r,k.current=t,S(t),O(!0),u&&u(t,r),x.current&&clearTimeout(x.current),x.current=setTimeout(()=>{O(!1),f&&f()},150)},[u,f]);n(()=>{const e=m.current;if(!e)return;const t=e=>{j(e)};return e.addEventListener("scroll",t),()=>{e.removeEventListener("scroll",t)}},[j]);const R=i((e,t)=>{d.current.recordItemSize(e,t)},[]);n(()=>{const e=m.current;return e&&h.current.startMeasuring(e,R),()=>{h.current.stopMeasuring()}},[R]);const M=i((e,t="start")=>{const r=d.current.getScrollOffsetForIndex(e,s,t);m.current&&(m.current.scrollTop=r)},[s]),E=i(e=>{m.current&&(m.current.scrollTop=e)},[]),T=i((e,t)=>{const r=d.current.getItemOffset(e),n=p.includes(e);return{position:n?"sticky":"absolute",top:n?0:r,left:0,width:"100%",height:t,zIndex:n?10:0}},[p]);n(()=>()=>{x.current&&clearTimeout(x.current),h.current.destroy()},[]);const P=d.current.getTotalSize();return{virtualItems:I,isScrolling:w,scrollOffset:b,totalSize:P,scrollToItem:M,scrollToOffset:E,setScrollOffset:S,containerRef:m,innerRef:y,getItemStyle:T}}const S=o(({items:e,renderItem:r,itemKey:o,height:a=400,width:c=500,itemSize:l,overscan:u=5,scrollDirection:f="forward",onScroll:p,className:d="",style:h={},estimatedItemSize:m=35,getItemSize:g,stickyIndices:v=[],onScrollEnd:S,innerRef:w,scrollOffsetRef:O},x)=>{const{virtualItems:k,isScrolling:z,scrollOffset:I,totalSize:_,containerRef:j,innerRef:R,getItemStyle:M}=b({items:e,getItemKey:o,containerHeight:a,containerWidth:c,itemSize:g||l,overscan:u,scrollDirection:f,estimatedItemSize:m,onScroll:p,onScrollEnd:S,stickyIndices:v}),E=t(null),T=t(null);s(x,()=>E.current),s(w,()=>T.current),n(()=>{O&&(O.current=I)},[I,O]);const P=t(new Map),N=i((e,t)=>{e?P.current.set(t,e):P.current.delete(t)},[]),$={height:a,width:c,overflow:"auto",position:"relative",...h},C={position:"relative",height:_,width:"100%"};return y.jsx("div",{ref:e=>{E.current=e,j.current=e},className:`virtualize-container ${d}`,style:$,onScroll:e=>{const t=r?.__scrollHandler;t&&t(e),p&&p(e.target.scrollTop,"auto")},children:y.jsx("div",{ref:e=>{T.current=e,R.current=e},style:C,className:"virtualize-inner",children:k.map(t=>{const n=e[t.index],i=o?o(t.index,n):t.index,s={item:n,index:t.index,style:M(t.index,t.size),isScrolling:z};return y.jsx("div",{ref:e=>{N(e,t.index)},style:s.style,"data-virtualize-index":t.index,children:r(s)},i)})})})});S.displayName="VirtualList";const w=o(({items:e,renderItem:n,itemKey:i,height:o,width:c,columnCount:l=3,rowHeight:u=200,columnWidth:f,layout:p="grid",overscan:d=3,gap:h=16,onScroll:m,className:g="",style:v={}},b)=>{const[S,w]=r(0),[O,x]=r(!1),k=t(null),z=t(null),I=t([]);s(b,()=>k.current);const _="number"==typeof l?l:Math.floor(c/("number"==typeof f?f:200)),j="number"==typeof f?f:c/_,R=a(()=>{const t=[];if("masonry"===p){const r=Array(_).fill(0);e.forEach((e,n)=>{const i=r.indexOf(Math.min(...r)),o="function"==typeof u?u(n):u,s={row:0,col:i,x:i*(j+h),y:r[i],width:j,height:o};t.push(s),r[i]+=o+h}),I.current=r}else e.forEach((e,r)=>{const n=Math.floor(r/_),i=r%_,o="function"==typeof u?u(r):u;t.push({row:n,col:i,x:i*(j+h),y:n*(o+h),width:j,height:o})});return t},[e,_,j,h,p,u]),M=a(()=>{const t=R.findIndex(e=>e.y+e.height>S),r=R.findIndex(e=>e.y>S+o);return{start:Math.max(0,(-1===t?0:t)-d),end:-1===r?e.length:Math.min(e.length,r+d)}},[R,S,o,d,e.length]),E=a(()=>{if("masonry"===p)return Math.max(...I.current.length?I.current:[0]);return Math.ceil(e.length/_)*(Math.max(...Array.from({length:e.length||1},(e,t)=>"function"==typeof u?u(t):u))+h)},[e.length,_,h,p,u]),T={height:o,width:c,overflow:"auto",position:"relative",...v},P={position:"relative",height:E,width:"100%"};return y.jsx("div",{ref:k,className:`virtualize-grid ${g}`,style:T,onScroll:e=>{const t=e.currentTarget.scrollTop;w(t),x(!0),m&&m(t),z.current&&clearTimeout(z.current),z.current=setTimeout(()=>{x(!1)},150)},children:y.jsx("div",{style:P,className:"virtualize-grid-inner",children:e.map((e,t)=>{if(t<M.start||t>=M.end)return null;const r=R[t];if(!r)return null;const o={item:e,index:t,style:{position:"absolute",left:r.x,top:r.y,width:r.width,height:r.height},isScrolling:O},s=i?i(t,e):t;return y.jsx("div",{style:o.style,"data-virtualize-index":t,children:n(o)},s)})})})});function O({items:t,searchValue:r,searchFields:n,caseSensitive:o=!1,highlightColor:s="#ffeb3b"}){const l=a(()=>{const e=r.trim();return o?e:e.toLowerCase()},[r,o]),u=a(()=>{if(!l)return null;try{const e=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(${e})`,o?"g":"gi")}catch(e){return console.warn("Invalid search pattern:",e),null}},[l,o]),f=c(l),p=f!==l,d=a(()=>f?t.filter(e=>n.some(t=>{try{const r=e[t];if(null==r)return!1;const n=String(r).trim();if(!n)return!1;return(o?n:n.toLowerCase()).includes(f)}catch(e){return console.warn(`Error accessing field ${String(t)}:`,e),!1}})):t,[t,f,n,o]),h=i(e=>!f||n.some(t=>{try{const r=e[t];if(null==r)return!1;const n=String(r).trim();return(o?n:n.toLowerCase()).includes(f)}catch{return!1}}),[f,n,o]);return{filteredItems:d,highlightMatch:i(t=>{if(!l||!u)return t;if(!t)return null;try{u.lastIndex=0;return String(t).split(u).map((t,r)=>r%2==0?t?y.jsx(e.Fragment,{children:t},r):null:y.jsx("mark",{style:{backgroundColor:s,padding:"0 2px",borderRadius:"2px"},"aria-label":`Highlighted search result: ${t}`,children:t},r))}catch(e){return console.warn("Error highlighting match:",e),t}},[l,u,s]),resultCount:d.length,hasMatch:h,isSearching:p}}function x({threshold:e=.1,onVisible:n}){const[o,s]=r(!1),a=t(null),c=i(()=>{if(!a.current||!("IntersectionObserver"in window))return s(!0),void n?.();const t=new IntersectionObserver(([e])=>{e.isIntersecting&&(s(!0),n?.(),t.unobserve(e.target))},{threshold:e});return t.observe(a.current),()=>t.disconnect()},[e,n]);return{ref:a,isVisible:o,setupObserver:c}}function k({onLoadMore:e,threshold:o=500,isLoading:s=!1}){const a=t(null),[c,l]=r(!1),u=t(!1),f=i(()=>{if(!a.current||s)return;const{scrollTop:t,scrollHeight:r,clientHeight:n}=a.current,i=r-t-n<o;l(i),!i||u.current||s||(u.current=!0,e().finally(()=>{u.current=!1}))},[e,o,s]);return n(()=>{const e=a.current;if(!e)return;const t=()=>{f()};return e.addEventListener("scroll",t),()=>e.removeEventListener("scroll",t)},[f]),{containerRef:a,isAtBottom:c,isLoading:s}}w.displayName="VirtualGrid";const z="virtualize-scroll-positions";function I(e,r){const o=t(new Map),s=i(()=>{if(!r.current)return;const t={key:e,offset:r.current.scrollTop,timestamp:Date.now()};o.current.set(e,t);try{const e=Array.from(o.current.values());localStorage.setItem(z,JSON.stringify(e))}catch(e){console.warn("Failed to save scroll position:",e)}},[e,r]),a=i(()=>{if(r.current)try{const t=localStorage.getItem(z);if(!t)return;const n=JSON.parse(t).find(t=>t.key===e);n&&requestAnimationFrame(()=>{r.current&&(r.current.scrollTop=n.offset)})}catch(e){console.warn("Failed to restore scroll position:",e)}},[e,r]);return n(()=>(a(),()=>{s()}),[a,s]),{savePosition:s,restorePosition:a}}export{v as MeasurementSystem,w as VirtualGrid,S as VirtualList,g as VirtualizationEngine,k as useInfiniteScroll,x as useLazyLoad,I as useScrollRestoration,b as useVirtualList,O as useVirtualizedSearch};
|
|
11
|
+
//# sourceMappingURL=index.esm.js.map
|