@tanstack/virtual-core 3.2.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +58 -66
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +5 -7
- package/dist/cjs/utils.cjs +8 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -0
- package/dist/esm/index.d.ts +5 -7
- package/dist/esm/index.js +59 -67
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +8 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +89 -78
- package/src/utils.ts +8 -0
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { memo, notUndefined, approxEqual } from "./utils.js";
|
|
1
|
+
import { memo, notUndefined, approxEqual, debounce } from "./utils.js";
|
|
2
2
|
const defaultKeyExtractor = (index) => index;
|
|
3
3
|
const defaultRangeExtractor = (range) => {
|
|
4
4
|
const start = Math.max(range.startIndex - range.overscan, 0);
|
|
@@ -39,6 +39,9 @@ const observeElementRect = (instance, cb) => {
|
|
|
39
39
|
observer.unobserve(element);
|
|
40
40
|
};
|
|
41
41
|
};
|
|
42
|
+
const addEventListenerOptions = {
|
|
43
|
+
passive: true
|
|
44
|
+
};
|
|
42
45
|
const observeWindowRect = (instance, cb) => {
|
|
43
46
|
const element = instance.scrollElement;
|
|
44
47
|
if (!element) {
|
|
@@ -48,27 +51,34 @@ const observeWindowRect = (instance, cb) => {
|
|
|
48
51
|
cb({ width: element.innerWidth, height: element.innerHeight });
|
|
49
52
|
};
|
|
50
53
|
handler();
|
|
51
|
-
element.addEventListener("resize", handler,
|
|
52
|
-
passive: true
|
|
53
|
-
});
|
|
54
|
+
element.addEventListener("resize", handler, addEventListenerOptions);
|
|
54
55
|
return () => {
|
|
55
56
|
element.removeEventListener("resize", handler);
|
|
56
57
|
};
|
|
57
58
|
};
|
|
59
|
+
const supportsScrollend = typeof window == "undefined" ? true : "onscrollend" in window;
|
|
58
60
|
const observeElementOffset = (instance, cb) => {
|
|
59
61
|
const element = instance.scrollElement;
|
|
60
62
|
if (!element) {
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
let offset = 0;
|
|
66
|
+
const fallback = supportsScrollend ? () => void 0 : debounce(() => {
|
|
67
|
+
cb(offset, false);
|
|
68
|
+
}, 150);
|
|
69
|
+
const createHandler = (isScrolling) => () => {
|
|
70
|
+
offset = element[instance.options.horizontal ? "scrollLeft" : "scrollTop"];
|
|
71
|
+
fallback();
|
|
72
|
+
cb(offset, isScrolling);
|
|
65
73
|
};
|
|
66
|
-
handler();
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
const handler = createHandler(true);
|
|
75
|
+
const endHandler = createHandler(false);
|
|
76
|
+
endHandler();
|
|
77
|
+
element.addEventListener("scroll", handler, addEventListenerOptions);
|
|
78
|
+
element.addEventListener("scrollend", endHandler, addEventListenerOptions);
|
|
70
79
|
return () => {
|
|
71
80
|
element.removeEventListener("scroll", handler);
|
|
81
|
+
element.removeEventListener("scrollend", endHandler);
|
|
72
82
|
};
|
|
73
83
|
};
|
|
74
84
|
const observeWindowOffset = (instance, cb) => {
|
|
@@ -76,15 +86,23 @@ const observeWindowOffset = (instance, cb) => {
|
|
|
76
86
|
if (!element) {
|
|
77
87
|
return;
|
|
78
88
|
}
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
let offset = 0;
|
|
90
|
+
const fallback = supportsScrollend ? () => void 0 : debounce(() => {
|
|
91
|
+
cb(offset, false);
|
|
92
|
+
}, 150);
|
|
93
|
+
const createHandler = (isScrolling) => () => {
|
|
94
|
+
offset = element[instance.options.horizontal ? "scrollX" : "scrollY"];
|
|
95
|
+
fallback();
|
|
96
|
+
cb(offset, isScrolling);
|
|
81
97
|
};
|
|
82
|
-
handler();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
const handler = createHandler(true);
|
|
99
|
+
const endHandler = createHandler(false);
|
|
100
|
+
endHandler();
|
|
101
|
+
element.addEventListener("scroll", handler, addEventListenerOptions);
|
|
102
|
+
element.addEventListener("scrollend", endHandler, addEventListenerOptions);
|
|
86
103
|
return () => {
|
|
87
104
|
element.removeEventListener("scroll", handler);
|
|
105
|
+
element.removeEventListener("scrollend", endHandler);
|
|
88
106
|
};
|
|
89
107
|
};
|
|
90
108
|
const measureElement = (element, entry, instance) => {
|
|
@@ -128,7 +146,6 @@ class Virtualizer {
|
|
|
128
146
|
this.unsubs = [];
|
|
129
147
|
this.scrollElement = null;
|
|
130
148
|
this.isScrolling = false;
|
|
131
|
-
this.isScrollingTimeoutId = null;
|
|
132
149
|
this.scrollToIndexTimeoutId = null;
|
|
133
150
|
this.measurementsCache = [];
|
|
134
151
|
this.itemSizeCache = /* @__PURE__ */ new Map();
|
|
@@ -189,39 +206,23 @@ class Virtualizer {
|
|
|
189
206
|
initialRect: { width: 0, height: 0 },
|
|
190
207
|
scrollMargin: 0,
|
|
191
208
|
gap: 0,
|
|
192
|
-
scrollingDelay: 150,
|
|
193
209
|
indexAttribute: "data-index",
|
|
194
210
|
initialMeasurementsCache: [],
|
|
195
211
|
lanes: 1,
|
|
196
212
|
...opts2
|
|
197
213
|
};
|
|
198
214
|
};
|
|
199
|
-
this.notify = (sync) => {
|
|
215
|
+
this.notify = (force, sync) => {
|
|
200
216
|
var _a, _b;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
this.range ? this.range.startIndex : null,
|
|
209
|
-
this.range ? this.range.endIndex : null
|
|
210
|
-
];
|
|
211
|
-
},
|
|
212
|
-
(isScrolling) => {
|
|
213
|
-
this.notify(isScrolling);
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
key: process.env.NODE_ENV !== "production" && "maybeNotify",
|
|
217
|
-
debug: () => this.options.debug,
|
|
218
|
-
initialDeps: [
|
|
219
|
-
this.isScrolling,
|
|
220
|
-
this.range ? this.range.startIndex : null,
|
|
221
|
-
this.range ? this.range.endIndex : null
|
|
222
|
-
]
|
|
217
|
+
const { startIndex, endIndex } = this.range ?? {
|
|
218
|
+
startIndex: void 0,
|
|
219
|
+
endIndex: void 0
|
|
220
|
+
};
|
|
221
|
+
const range = this.calculateRange();
|
|
222
|
+
if (force || startIndex !== (range == null ? void 0 : range.startIndex) || endIndex !== (range == null ? void 0 : range.endIndex)) {
|
|
223
|
+
(_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, sync);
|
|
223
224
|
}
|
|
224
|
-
|
|
225
|
+
};
|
|
225
226
|
this.cleanup = () => {
|
|
226
227
|
this.unsubs.filter(Boolean).forEach((d) => d());
|
|
227
228
|
this.unsubs = [];
|
|
@@ -246,29 +247,17 @@ class Virtualizer {
|
|
|
246
247
|
this.unsubs.push(
|
|
247
248
|
this.options.observeElementRect(this, (rect) => {
|
|
248
249
|
this.scrollRect = rect;
|
|
249
|
-
this.
|
|
250
|
+
this.notify(false, false);
|
|
250
251
|
})
|
|
251
252
|
);
|
|
252
253
|
this.unsubs.push(
|
|
253
|
-
this.options.observeElementOffset(this, (offset) => {
|
|
254
|
+
this.options.observeElementOffset(this, (offset, isScrolling) => {
|
|
254
255
|
this.scrollAdjustments = 0;
|
|
255
|
-
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
if (this.isScrollingTimeoutId !== null) {
|
|
259
|
-
clearTimeout(this.isScrollingTimeoutId);
|
|
260
|
-
this.isScrollingTimeoutId = null;
|
|
261
|
-
}
|
|
262
|
-
this.isScrolling = true;
|
|
263
|
-
this.scrollDirection = this.scrollOffset < offset ? "forward" : "backward";
|
|
256
|
+
this.scrollDirection = isScrolling ? this.scrollOffset < offset ? "forward" : "backward" : null;
|
|
264
257
|
this.scrollOffset = offset;
|
|
265
|
-
this.
|
|
266
|
-
this.
|
|
267
|
-
|
|
268
|
-
this.isScrolling = false;
|
|
269
|
-
this.scrollDirection = null;
|
|
270
|
-
this.maybeNotify();
|
|
271
|
-
}, this.options.scrollingDelay);
|
|
258
|
+
const prevIsScrolling = this.isScrolling;
|
|
259
|
+
this.isScrolling = isScrolling;
|
|
260
|
+
this.notify(prevIsScrolling !== isScrolling, isScrolling);
|
|
272
261
|
})
|
|
273
262
|
);
|
|
274
263
|
}
|
|
@@ -276,7 +265,7 @@ class Virtualizer {
|
|
|
276
265
|
this.getSize = () => {
|
|
277
266
|
return this.scrollRect[this.options.horizontal ? "width" : "height"];
|
|
278
267
|
};
|
|
279
|
-
this.
|
|
268
|
+
this.getMeasurementOptions = memo(
|
|
280
269
|
() => [
|
|
281
270
|
this.options.count,
|
|
282
271
|
this.options.paddingStart,
|
|
@@ -324,7 +313,7 @@ class Virtualizer {
|
|
|
324
313
|
})[0] : void 0;
|
|
325
314
|
};
|
|
326
315
|
this.getMeasurements = memo(
|
|
327
|
-
() => [this.
|
|
316
|
+
() => [this.getMeasurementOptions(), this.itemSizeCache],
|
|
328
317
|
({ count, paddingStart, scrollMargin, getItemKey }, itemSizeCache) => {
|
|
329
318
|
const min = this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0;
|
|
330
319
|
this.pendingMeasuredCacheIndexes = [];
|
|
@@ -377,7 +366,8 @@ class Virtualizer {
|
|
|
377
366
|
],
|
|
378
367
|
(rangeExtractor, range, overscan, count) => {
|
|
379
368
|
return range === null ? [] : rangeExtractor({
|
|
380
|
-
|
|
369
|
+
startIndex: range.startIndex,
|
|
370
|
+
endIndex: range.endIndex,
|
|
381
371
|
overscan,
|
|
382
372
|
count
|
|
383
373
|
});
|
|
@@ -424,7 +414,7 @@ class Virtualizer {
|
|
|
424
414
|
const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
|
|
425
415
|
const delta = size - itemSize;
|
|
426
416
|
if (delta !== 0) {
|
|
427
|
-
if (item.start < this.scrollOffset + this.scrollAdjustments) {
|
|
417
|
+
if (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.scrollOffset + this.scrollAdjustments) {
|
|
428
418
|
if (process.env.NODE_ENV !== "production" && this.options.debug) {
|
|
429
419
|
console.info("correction", delta);
|
|
430
420
|
}
|
|
@@ -435,7 +425,7 @@ class Virtualizer {
|
|
|
435
425
|
}
|
|
436
426
|
this.pendingMeasuredCacheIndexes.push(item.index);
|
|
437
427
|
this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size));
|
|
438
|
-
this.notify(false);
|
|
428
|
+
this.notify(true, false);
|
|
439
429
|
}
|
|
440
430
|
};
|
|
441
431
|
this.measureElement = (node) => {
|
|
@@ -587,8 +577,9 @@ class Virtualizer {
|
|
|
587
577
|
this.options.scrollToFn(offset, { behavior, adjustments }, this);
|
|
588
578
|
};
|
|
589
579
|
this.measure = () => {
|
|
580
|
+
var _a, _b;
|
|
590
581
|
this.itemSizeCache = /* @__PURE__ */ new Map();
|
|
591
|
-
this.
|
|
582
|
+
(_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, false);
|
|
592
583
|
};
|
|
593
584
|
this.setOptions(opts);
|
|
594
585
|
this.scrollRect = this.options.initialRect;
|
|
@@ -597,7 +588,7 @@ class Virtualizer {
|
|
|
597
588
|
this.measurementsCache.forEach((item) => {
|
|
598
589
|
this.itemSizeCache.set(item.key, item.size);
|
|
599
590
|
});
|
|
600
|
-
this.
|
|
591
|
+
this.notify(false, false);
|
|
601
592
|
}
|
|
602
593
|
}
|
|
603
594
|
const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
|
|
@@ -635,6 +626,7 @@ function calculateRange({
|
|
|
635
626
|
export {
|
|
636
627
|
Virtualizer,
|
|
637
628
|
approxEqual,
|
|
629
|
+
debounce,
|
|
638
630
|
defaultKeyExtractor,
|
|
639
631
|
defaultRangeExtractor,
|
|
640
632
|
elementScroll,
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import { approxEqual, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n lane: number\n}\n\nexport interface Rect {\n width: number\n height: number\n}\n\n//\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n\n const arr = []\n\n for (let i = start; i <= end; i++) {\n arr.push(i)\n }\n\n return arr\n}\n\nexport const observeElementRect = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = (rect: Rect) => {\n const { width, height } = rect\n cb({ width: Math.round(width), height: Math.round(height) })\n }\n\n handler(element.getBoundingClientRect())\n\n if (typeof ResizeObserver === 'undefined') {\n return () => {}\n }\n\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n handler({ width: box.inlineSize, height: box.blockSize })\n return\n }\n }\n handler(element.getBoundingClientRect())\n })\n\n observer.observe(element, { box: 'border-box' })\n\n return () => {\n observer.unobserve(element)\n }\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<Window, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight })\n }\n handler()\n\n element.addEventListener('resize', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('resize', handler)\n }\n}\n\nexport const observeElementOffset = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (offset: number) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb(element[instance.options.horizontal ? 'scrollLeft' : 'scrollTop'])\n }\n handler()\n\n element.addEventListener('scroll', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('scroll', handler)\n }\n}\n\nexport const observeWindowOffset = (\n instance: Virtualizer<Window, any>,\n cb: (offset: number) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb(element[instance.options.horizontal ? 'scrollX' : 'scrollY'])\n }\n handler()\n\n element.addEventListener('scroll', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('scroll', handler)\n }\n}\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<any, TItemElement>,\n) => {\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],\n )\n return size\n }\n }\n return Math.round(\n element.getBoundingClientRect()[\n instance.options.horizontal ? 'width' : 'height'\n ],\n )\n}\n\nexport const windowScroll = <T extends Window>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport const elementScroll = <T extends Element>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => void\n observeElementRect: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (offset: number) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n sync: boolean,\n ) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => number\n overscan?: number\n horizontal?: boolean\n paddingStart?: number\n paddingEnd?: number\n scrollPaddingStart?: number\n scrollPaddingEnd?: number\n initialOffset?: number | (() => number)\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n gap?: number\n scrollingDelay?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n lanes?: number\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: (void | (() => void))[] = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n isScrolling: boolean = false\n private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null\n private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n measureElementCache = new Map<Key, TItemElement>()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\n if (_ro) {\n return _ro\n } else if (typeof ResizeObserver !== 'undefined') {\n return (_ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, entry)\n })\n }))\n } else {\n return null\n }\n }\n\n return {\n disconnect: () => get()?.disconnect(),\n observe: (target: Element) =>\n get()?.observe(target, { box: 'border-box' }),\n unobserve: (target: Element) => get()?.unobserve(target),\n }\n })()\n range: { startIndex: number; endIndex: number } | null = null\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset =\n typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n\n this.maybeNotify()\n }\n\n setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {\n Object.entries(opts).forEach(([key, value]) => {\n if (typeof value === 'undefined') delete (opts as any)[key]\n })\n\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n gap: 0,\n scrollingDelay: 150,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n lanes: 1,\n ...opts,\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\n )\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.scrollElement = null\n }\n\n _didMount = () => {\n this.measureElementCache.forEach(this.observer.observe)\n return () => {\n this.observer.disconnect()\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.getScrollElement()\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n this.scrollElement = scrollElement\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: undefined,\n behavior: undefined,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.maybeNotify()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n this.scrollAdjustments = 0\n\n if (this.scrollOffset === offset) {\n return\n }\n\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n this.isScrolling = true\n this.scrollDirection =\n this.scrollOffset < offset ? 'forward' : 'backward'\n this.scrollOffset = offset\n\n this.maybeNotify()\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.isScrolling = false\n this.scrollDirection = null\n\n this.maybeNotify()\n }, this.options.scrollingDelay)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private memoOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n ],\n (count, paddingStart, scrollMargin, getItemKey) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n }\n },\n {\n key: false,\n },\n )\n\n private getFurthestMeasurement = (\n measurements: VirtualItem[],\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map<number, true>()\n const furthestMeasurements = new Map<number, VirtualItem>()\n for (let m = index - 1; m >= 0; m--) {\n const measurement = measurements[m]!\n\n if (furthestMeasurementsFound.has(measurement.lane)) {\n continue\n }\n\n const previousFurthestMeasurement = furthestMeasurements.get(\n measurement.lane,\n )\n if (\n previousFurthestMeasurement == null ||\n measurement.end > previousFurthestMeasurement.end\n ) {\n furthestMeasurements.set(measurement.lane, measurement)\n } else if (measurement.end < previousFurthestMeasurement.end) {\n furthestMeasurementsFound.set(measurement.lane, true)\n }\n\n if (furthestMeasurementsFound.size === this.options.lanes) {\n break\n }\n }\n\n return furthestMeasurements.size === this.options.lanes\n ? Array.from(furthestMeasurements.values()).sort((a, b) => {\n if (a.end === b.end) {\n return a.index - b.index\n }\n\n return a.end - b.end\n })[0]\n : undefined\n }\n\n private getMeasurements = memo(\n () => [this.memoOptions(), this.itemSizeCache],\n ({ count, paddingStart, scrollMargin, getItemKey }, itemSizeCache) => {\n const min =\n this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n const measurements = this.measurementsCache.slice(0, min)\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n const start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n\n const end = start + size\n\n const lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [this.getMeasurements(), this.getSize(), this.scrollOffset],\n (measurements, outerSize, scrollOffset) => {\n return (this.range =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n })\n : null)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.calculateRange(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return range === null\n ? []\n : rangeExtractor({\n ...range,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n private _measureElement = (\n node: TItemElement,\n entry: ResizeObserverEntry | undefined,\n ) => {\n const item = this.measurementsCache[this.indexFromElement(node)]\n\n if (!item || !node.isConnected) {\n this.measureElementCache.forEach((cached, key) => {\n if (cached === node) {\n this.observer.unobserve(node)\n this.measureElementCache.delete(key)\n }\n })\n return\n }\n\n const prevNode = this.measureElementCache.get(item.key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.measureElementCache.set(item.key, node)\n }\n\n const measuredItemSize = this.options.measureElement(node, entry, this)\n\n this.resizeItem(item, measuredItemSize)\n }\n\n resizeItem = (item: VirtualItem, size: number) => {\n const itemSize = this.itemSizeCache.get(item.key) ?? item.size\n const delta = size - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset + this.scrollAdjustments) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(item.index)\n this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size))\n\n this.notify(false)\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, undefined)\n }\n\n getVirtualItems = memo(\n () => [this.getIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: VirtualItem[] = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualItemForOffset = (offset: number) => {\n const measurements = this.getMeasurements()\n\n return notUndefined(\n measurements[\n findNearestBinarySearch(\n 0,\n measurements.length - 1,\n (index: number) => notUndefined(measurements[index]).start,\n offset,\n )\n ],\n )\n }\n\n getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= this.scrollOffset) {\n align = 'start'\n } else if (toOffset >= this.scrollOffset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n if (align === 'start') {\n toOffset = toOffset\n } else if (align === 'end') {\n toOffset = toOffset - size\n } else if (align === 'center') {\n toOffset = toOffset - size / 2\n }\n\n const scrollSizeProp = this.options.horizontal\n ? 'scrollWidth'\n : 'scrollHeight'\n const scrollSize = this.scrollElement\n ? 'document' in this.scrollElement\n ? this.scrollElement.document.documentElement[scrollSizeProp]\n : this.scrollElement[scrollSizeProp]\n : 0\n\n const maxOffset = scrollSize - this.getSize()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const measurement = notUndefined(this.getMeasurements()[index])\n\n if (align === 'auto') {\n if (\n measurement.end >=\n this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd\n ) {\n align = 'end'\n } else if (\n measurement.start <=\n this.scrollOffset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return [this.scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n return [this.getOffsetForAlignment(toOffset, align), align] as const\n }\n\n private isDynamicMode = () => this.measureElementCache.size > 0\n\n private cancelScrollToIndex = () => {\n if (this.scrollToIndexTimeoutId !== null) {\n clearTimeout(this.scrollToIndexTimeoutId)\n this.scrollToIndexTimeoutId = null\n }\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {\n adjustments: undefined,\n behavior,\n })\n }\n\n scrollToIndex = (\n index: number,\n { align: initialAlign = 'auto', behavior }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n const [toOffset, align] = this.getOffsetForIndex(index, initialAlign)\n\n this._scrollToOffset(toOffset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode()) {\n this.scrollToIndexTimeoutId = setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM = this.measureElementCache.has(\n this.options.getItemKey(index),\n )\n\n if (elementInDOM) {\n const [toOffset] = this.getOffsetForIndex(index, align)\n\n if (!approxEqual(toOffset, this.scrollOffset)) {\n this.scrollToIndex(index, { align, behavior })\n }\n } else {\n this.scrollToIndex(index, { align, behavior })\n }\n })\n }\n }\n\n scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.scrollOffset + delta, {\n adjustments: undefined,\n behavior,\n })\n }\n\n getTotalSize = () => {\n const measurements = this.getMeasurements()\n\n let end: number\n // If there are no measurements, set the end to paddingStart\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else {\n // If lanes is 1, use the last measurement's end, otherwise find the maximum end value among all measurements\n end =\n this.options.lanes === 1\n ? measurements[measurements.length - 1]?.end ?? 0\n : Math.max(\n ...measurements.slice(-this.options.lanes).map((m) => m.end),\n )\n }\n\n return end - this.options.scrollMargin + this.options.paddingEnd\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = new Map()\n this.notify(false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem[]\n outerSize: number\n scrollOffset: number\n}) {\n const count = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset)\n let endIndex = startIndex\n\n while (\n endIndex < count &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["opts","toOffset"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import { approxEqual, memo, notUndefined, debounce } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n lane: number\n}\n\nexport interface Rect {\n width: number\n height: number\n}\n\n//\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n\n const arr = []\n\n for (let i = start; i <= end; i++) {\n arr.push(i)\n }\n\n return arr\n}\n\nexport const observeElementRect = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = (rect: Rect) => {\n const { width, height } = rect\n cb({ width: Math.round(width), height: Math.round(height) })\n }\n\n handler(element.getBoundingClientRect())\n\n if (typeof ResizeObserver === 'undefined') {\n return () => {}\n }\n\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n handler({ width: box.inlineSize, height: box.blockSize })\n return\n }\n }\n handler(element.getBoundingClientRect())\n })\n\n observer.observe(element, { box: 'border-box' })\n\n return () => {\n observer.unobserve(element)\n }\n}\n\nconst addEventListenerOptions = {\n passive: true,\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<Window, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight })\n }\n handler()\n\n element.addEventListener('resize', handler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('resize', handler)\n }\n}\n\nconst supportsScrollend =\n typeof window == 'undefined' ? true : 'onscrollend' in window\n\nexport const observeElementOffset = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (offset: number, isScrolling: boolean) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(() => {\n cb(offset, false)\n }, 150)\n\n const createHandler = (isScrolling: boolean) => () => {\n offset = element[instance.options.horizontal ? 'scrollLeft' : 'scrollTop']\n fallback()\n cb(offset, isScrolling)\n }\n const handler = createHandler(true)\n const endHandler = createHandler(false)\n endHandler()\n\n element.addEventListener('scroll', handler, addEventListenerOptions)\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('scroll', handler)\n element.removeEventListener('scrollend', endHandler)\n }\n}\n\nexport const observeWindowOffset = (\n instance: Virtualizer<Window, any>,\n cb: (offset: number, isScrolling: boolean) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(() => {\n cb(offset, false)\n }, 150)\n\n const createHandler = (isScrolling: boolean) => () => {\n offset = element[instance.options.horizontal ? 'scrollX' : 'scrollY']\n fallback()\n cb(offset, isScrolling)\n }\n const handler = createHandler(true)\n const endHandler = createHandler(false)\n endHandler()\n\n element.addEventListener('scroll', handler, addEventListenerOptions)\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('scroll', handler)\n element.removeEventListener('scrollend', endHandler)\n }\n}\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<any, TItemElement>,\n) => {\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],\n )\n return size\n }\n }\n return Math.round(\n element.getBoundingClientRect()[\n instance.options.horizontal ? 'width' : 'height'\n ],\n )\n}\n\nexport const windowScroll = <T extends Window>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport const elementScroll = <T extends Element>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => void\n observeElementRect: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (offset: number, isScrolling: boolean) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n sync: boolean,\n ) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => number\n overscan?: number\n horizontal?: boolean\n paddingStart?: number\n paddingEnd?: number\n scrollPaddingStart?: number\n scrollPaddingEnd?: number\n initialOffset?: number | (() => number)\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n lanes?: number\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: (void | (() => void))[] = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n isScrolling: boolean = false\n private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\n delta: number,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => boolean)\n measureElementCache = new Map<Key, TItemElement>()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\n if (_ro) {\n return _ro\n } else if (typeof ResizeObserver !== 'undefined') {\n return (_ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, entry)\n })\n }))\n } else {\n return null\n }\n }\n\n return {\n disconnect: () => get()?.disconnect(),\n observe: (target: Element) =>\n get()?.observe(target, { box: 'border-box' }),\n unobserve: (target: Element) => get()?.unobserve(target),\n }\n })()\n range: { startIndex: number; endIndex: number } | null = null\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset =\n typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n\n this.notify(false, false)\n }\n\n setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {\n Object.entries(opts).forEach(([key, value]) => {\n if (typeof value === 'undefined') delete (opts as any)[key]\n })\n\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n gap: 0,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n lanes: 1,\n ...opts,\n }\n }\n\n private notify = (force: boolean, sync: boolean) => {\n const { startIndex, endIndex } = this.range ?? {\n startIndex: undefined,\n endIndex: undefined,\n }\n const range = this.calculateRange()\n\n if (\n force ||\n startIndex !== range?.startIndex ||\n endIndex !== range?.endIndex\n ) {\n this.options.onChange?.(this, sync)\n }\n }\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.scrollElement = null\n }\n\n _didMount = () => {\n this.measureElementCache.forEach(this.observer.observe)\n return () => {\n this.observer.disconnect()\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.getScrollElement()\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n this.scrollElement = scrollElement\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: undefined,\n behavior: undefined,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.notify(false, false)\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset, isScrolling) => {\n this.scrollAdjustments = 0\n this.scrollDirection = isScrolling\n ? this.scrollOffset < offset\n ? 'forward'\n : 'backward'\n : null\n this.scrollOffset = offset\n\n const prevIsScrolling = this.isScrolling\n this.isScrolling = isScrolling\n\n this.notify(prevIsScrolling !== isScrolling, isScrolling)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n ],\n (count, paddingStart, scrollMargin, getItemKey) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n }\n },\n {\n key: false,\n },\n )\n\n private getFurthestMeasurement = (\n measurements: VirtualItem[],\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map<number, true>()\n const furthestMeasurements = new Map<number, VirtualItem>()\n for (let m = index - 1; m >= 0; m--) {\n const measurement = measurements[m]!\n\n if (furthestMeasurementsFound.has(measurement.lane)) {\n continue\n }\n\n const previousFurthestMeasurement = furthestMeasurements.get(\n measurement.lane,\n )\n if (\n previousFurthestMeasurement == null ||\n measurement.end > previousFurthestMeasurement.end\n ) {\n furthestMeasurements.set(measurement.lane, measurement)\n } else if (measurement.end < previousFurthestMeasurement.end) {\n furthestMeasurementsFound.set(measurement.lane, true)\n }\n\n if (furthestMeasurementsFound.size === this.options.lanes) {\n break\n }\n }\n\n return furthestMeasurements.size === this.options.lanes\n ? Array.from(furthestMeasurements.values()).sort((a, b) => {\n if (a.end === b.end) {\n return a.index - b.index\n }\n\n return a.end - b.end\n })[0]\n : undefined\n }\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCache],\n ({ count, paddingStart, scrollMargin, getItemKey }, itemSizeCache) => {\n const min =\n this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n const measurements = this.measurementsCache.slice(0, min)\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n const start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n\n const end = start + size\n\n const lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [this.getMeasurements(), this.getSize(), this.scrollOffset],\n (measurements, outerSize, scrollOffset) => {\n return (this.range =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n })\n : null)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.calculateRange(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return range === null\n ? []\n : rangeExtractor({\n startIndex: range.startIndex,\n endIndex: range.endIndex,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n private _measureElement = (\n node: TItemElement,\n entry: ResizeObserverEntry | undefined,\n ) => {\n const item = this.measurementsCache[this.indexFromElement(node)]\n\n if (!item || !node.isConnected) {\n this.measureElementCache.forEach((cached, key) => {\n if (cached === node) {\n this.observer.unobserve(node)\n this.measureElementCache.delete(key)\n }\n })\n return\n }\n\n const prevNode = this.measureElementCache.get(item.key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.measureElementCache.set(item.key, node)\n }\n\n const measuredItemSize = this.options.measureElement(node, entry, this)\n\n this.resizeItem(item, measuredItemSize)\n }\n\n resizeItem = (item: VirtualItem, size: number) => {\n const itemSize = this.itemSizeCache.get(item.key) ?? item.size\n const delta = size - itemSize\n\n if (delta !== 0) {\n if (\n this.shouldAdjustScrollPositionOnItemSizeChange !== undefined\n ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this)\n : item.start < this.scrollOffset + this.scrollAdjustments\n ) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(item.index)\n this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size))\n\n this.notify(true, false)\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, undefined)\n }\n\n getVirtualItems = memo(\n () => [this.getIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: VirtualItem[] = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualItemForOffset = (offset: number) => {\n const measurements = this.getMeasurements()\n\n return notUndefined(\n measurements[\n findNearestBinarySearch(\n 0,\n measurements.length - 1,\n (index: number) => notUndefined(measurements[index]).start,\n offset,\n )\n ],\n )\n }\n\n getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= this.scrollOffset) {\n align = 'start'\n } else if (toOffset >= this.scrollOffset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n if (align === 'start') {\n toOffset = toOffset\n } else if (align === 'end') {\n toOffset = toOffset - size\n } else if (align === 'center') {\n toOffset = toOffset - size / 2\n }\n\n const scrollSizeProp = this.options.horizontal\n ? 'scrollWidth'\n : 'scrollHeight'\n const scrollSize = this.scrollElement\n ? 'document' in this.scrollElement\n ? this.scrollElement.document.documentElement[scrollSizeProp]\n : this.scrollElement[scrollSizeProp]\n : 0\n\n const maxOffset = scrollSize - this.getSize()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const measurement = notUndefined(this.getMeasurements()[index])\n\n if (align === 'auto') {\n if (\n measurement.end >=\n this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd\n ) {\n align = 'end'\n } else if (\n measurement.start <=\n this.scrollOffset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return [this.scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n return [this.getOffsetForAlignment(toOffset, align), align] as const\n }\n\n private isDynamicMode = () => this.measureElementCache.size > 0\n\n private cancelScrollToIndex = () => {\n if (this.scrollToIndexTimeoutId !== null) {\n clearTimeout(this.scrollToIndexTimeoutId)\n this.scrollToIndexTimeoutId = null\n }\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {\n adjustments: undefined,\n behavior,\n })\n }\n\n scrollToIndex = (\n index: number,\n { align: initialAlign = 'auto', behavior }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n const [toOffset, align] = this.getOffsetForIndex(index, initialAlign)\n\n this._scrollToOffset(toOffset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode()) {\n this.scrollToIndexTimeoutId = setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM = this.measureElementCache.has(\n this.options.getItemKey(index),\n )\n\n if (elementInDOM) {\n const [toOffset] = this.getOffsetForIndex(index, align)\n\n if (!approxEqual(toOffset, this.scrollOffset)) {\n this.scrollToIndex(index, { align, behavior })\n }\n } else {\n this.scrollToIndex(index, { align, behavior })\n }\n })\n }\n }\n\n scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.scrollOffset + delta, {\n adjustments: undefined,\n behavior,\n })\n }\n\n getTotalSize = () => {\n const measurements = this.getMeasurements()\n\n let end: number\n // If there are no measurements, set the end to paddingStart\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else {\n // If lanes is 1, use the last measurement's end, otherwise find the maximum end value among all measurements\n end =\n this.options.lanes === 1\n ? measurements[measurements.length - 1]?.end ?? 0\n : Math.max(\n ...measurements.slice(-this.options.lanes).map((m) => m.end),\n )\n }\n\n return end - this.options.scrollMargin + this.options.paddingEnd\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = new Map()\n this.options.onChange?.(this, false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem[]\n outerSize: number\n scrollOffset: number\n}) {\n const count = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset)\n let endIndex = startIndex\n\n while (\n endIndex < count &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["opts","toOffset"],"mappings":"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"}
|
package/dist/esm/utils.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export declare function memo<TDeps extends readonly any[], TResult>(getDeps: ()
|
|
|
8
8
|
}): () => TResult;
|
|
9
9
|
export declare function notUndefined<T>(value: T | undefined, msg?: string): T;
|
|
10
10
|
export declare const approxEqual: (a: number, b: number) => boolean;
|
|
11
|
+
export declare const debounce: (fn: Function, ms: number) => (this: any, ...args: any[]) => void;
|
package/dist/esm/utils.js
CHANGED
|
@@ -51,8 +51,16 @@ function notUndefined(value, msg) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
const approxEqual = (a, b) => Math.abs(a - b) < 1;
|
|
54
|
+
const debounce = (fn, ms) => {
|
|
55
|
+
let timeoutId;
|
|
56
|
+
return function(...args) {
|
|
57
|
+
clearTimeout(timeoutId);
|
|
58
|
+
timeoutId = setTimeout(() => fn.apply(this, args), ms);
|
|
59
|
+
};
|
|
60
|
+
};
|
|
54
61
|
export {
|
|
55
62
|
approxEqual,
|
|
63
|
+
debounce,
|
|
56
64
|
memo,
|
|
57
65
|
notUndefined
|
|
58
66
|
};
|
package/dist/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends readonly any[], TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => any\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result!\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n"],"names":[],"mappings":"AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe;AAC3B,MAAA;AAEJ,SAAO,MAAe;AAbR;AAcR,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,gBAAU,KAAK;AAE/C,UAAM,UAAU;AAEhB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IACT;AAEO,WAAA;AAEH,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,mBAAa,KAAK;AAEzC,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QACd;AACO,eAAA;AAAA,MAAA;AAGD,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MAAA;AAAA,IAEV;AAEA,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EAAA;AAEX;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EACT;AACF;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends readonly any[], TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => any\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result!\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n\nexport const debounce = (fn: Function, ms: number) => {\n let timeoutId: ReturnType<typeof setTimeout>\n return function (this: any, ...args: any[]) {\n clearTimeout(timeoutId)\n timeoutId = setTimeout(() => fn.apply(this, args), ms)\n }\n}\n"],"names":[],"mappings":"AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe;AAC3B,MAAA;AAEJ,SAAO,MAAe;AAbR;AAcR,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,gBAAU,KAAK;AAE/C,UAAM,UAAU;AAEhB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IACT;AAEO,WAAA;AAEH,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,mBAAa,KAAK;AAEzC,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QACd;AACO,eAAA;AAAA,MAAA;AAGD,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MAAA;AAAA,IAEV;AAEA,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EAAA;AAEX;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EACT;AACF;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAE1D,MAAA,WAAW,CAAC,IAAc,OAAe;AAChD,MAAA;AACJ,SAAO,YAAwB,MAAa;AAC1C,iBAAa,SAAS;AACtB,gBAAY,WAAW,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG,EAAE;AAAA,EAAA;AAEzD;"}
|