@caspeco/casper-ui-library 9.10.0 → 9.11.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.
@@ -1,70 +1,80 @@
1
- import { memo as p, notUndefined as M, approxEqual as R, debounce as _ } from "./utils.js";
2
- const I = (l) => {
3
- const { offsetWidth: a, offsetHeight: t } = l;
1
+ import { createLazyMeasurementsView as F } from "./lazy-measurements.js";
2
+ import { memo as M, notUndefined as w, approxEqual as R, debounce as D } from "./utils.js";
3
+ let I;
4
+ const y = () => {
5
+ if (I !== void 0) return I;
6
+ if (typeof navigator > "u") return I = !1;
7
+ if (/iP(hone|od|ad)/.test(navigator.userAgent)) return I = !0;
8
+ const r = navigator.maxTouchPoints;
9
+ return I = navigator.platform === "MacIntel" && r !== void 0 && r > 0;
10
+ }, C = (r) => {
11
+ const { offsetWidth: a, offsetHeight: t } = r;
4
12
  return { width: a, height: t };
5
- }, F = (l) => l, W = (l) => {
6
- const a = Math.max(l.startIndex - l.overscan, 0), t = Math.min(l.endIndex + l.overscan, l.count - 1), e = [];
7
- for (let s = a; s <= t; s++)
8
- e.push(s);
9
- return e;
10
- }, k = (l, a) => {
11
- const t = l.scrollElement;
13
+ }, k = (r) => r, W = (r) => {
14
+ const a = Math.max(r.startIndex - r.overscan, 0), e = Math.min(r.endIndex + r.overscan, r.count - 1) - a + 1, s = new Array(e);
15
+ for (let i = 0; i < e; i++)
16
+ s[i] = a + i;
17
+ return s;
18
+ }, H = (r, a) => {
19
+ const t = r.scrollElement;
12
20
  if (!t)
13
21
  return;
14
- const e = l.targetWindow;
22
+ const e = r.targetWindow;
15
23
  if (!e)
16
24
  return;
17
- const s = (o) => {
18
- const { width: n, height: r } = o;
19
- a({ width: Math.round(n), height: Math.round(r) });
25
+ const s = (n) => {
26
+ const { width: o, height: l } = n;
27
+ a({ width: Math.round(o), height: Math.round(l) });
20
28
  };
21
- if (s(I(t)), !e.ResizeObserver)
29
+ if (s(C(t)), !e.ResizeObserver)
22
30
  return () => {
23
31
  };
24
- const i = new e.ResizeObserver((o) => {
25
- const n = () => {
26
- const r = o[0];
27
- if (r?.borderBoxSize) {
28
- const u = r.borderBoxSize[0];
32
+ const i = new e.ResizeObserver((n) => {
33
+ const o = () => {
34
+ const l = n[0];
35
+ if (l?.borderBoxSize) {
36
+ const u = l.borderBoxSize[0];
29
37
  if (u) {
30
38
  s({ width: u.inlineSize, height: u.blockSize });
31
39
  return;
32
40
  }
33
41
  }
34
- s(I(t));
42
+ s(C(t));
35
43
  };
36
- l.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(n) : n();
44
+ r.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(o) : o();
37
45
  });
38
46
  return i.observe(t, { box: "border-box" }), () => {
39
47
  i.unobserve(t);
40
48
  };
41
- }, w = {
49
+ }, x = {
42
50
  passive: !0
43
- }, z = typeof window > "u" ? !0 : "onscrollend" in window, D = (l, a) => {
44
- const t = l.scrollElement;
45
- if (!t)
46
- return;
47
- const e = l.targetWindow;
51
+ }, L = typeof window > "u" ? !0 : "onscrollend" in window, j = (r, a, t) => {
52
+ const e = r.scrollElement;
48
53
  if (!e)
49
54
  return;
50
- let s = 0;
51
- const i = l.options.useScrollendEvent && z ? () => {
52
- } : _(
53
- e,
54
- () => {
55
- a(s, !1);
56
- },
57
- l.options.isScrollingResetDelay
58
- ), o = (c) => () => {
59
- const { horizontal: d, isRtl: v } = l.options;
60
- s = d ? t.scrollLeft * (v && -1 || 1) : t.scrollTop, i(), a(s, c);
61
- }, n = o(!0), r = o(!1);
62
- t.addEventListener("scroll", n, w);
63
- const u = l.options.useScrollendEvent && z;
64
- return u && t.addEventListener("scrollend", r, w), () => {
65
- t.removeEventListener("scroll", n), u && t.removeEventListener("scrollend", r);
55
+ const s = r.targetWindow;
56
+ if (!s)
57
+ return;
58
+ const i = r.options.useScrollendEvent && L;
59
+ let n = 0;
60
+ const o = i ? null : D(
61
+ s,
62
+ () => a(n, !1),
63
+ r.options.isScrollingResetDelay
64
+ ), l = (m) => () => {
65
+ n = t(e), o?.(), a(n, m);
66
+ }, u = l(!0), d = l(!1);
67
+ return e.addEventListener("scroll", u, x), i && e.addEventListener("scrollend", d, x), () => {
68
+ e.removeEventListener("scroll", u), i && e.removeEventListener("scrollend", d);
66
69
  };
67
- }, N = (l, a, t) => {
70
+ }, J = (r, a) => j(r, a, (t) => {
71
+ const { horizontal: e, isRtl: s } = r.options;
72
+ return e ? t.scrollLeft * (s && -1 || 1) : t.scrollTop;
73
+ }), V = (r, a, t) => {
74
+ if (t.options.useCachedMeasurements) {
75
+ const e = t.indexFromElement(r), s = t.options.getItemKey(e);
76
+ return t.itemSizeCache.get(s) ?? t.options.estimateSize(e);
77
+ }
68
78
  if (a?.borderBoxSize) {
69
79
  const e = a.borderBoxSize[0];
70
80
  if (e)
@@ -72,39 +82,48 @@ const I = (l) => {
72
82
  e[t.options.horizontal ? "inlineSize" : "blockSize"]
73
83
  );
74
84
  }
75
- return l[t.options.horizontal ? "offsetWidth" : "offsetHeight"];
76
- }, V = (l, {
85
+ if (!a) {
86
+ const e = t.indexFromElement(r), s = t.options.getItemKey(e), i = t.itemSizeCache.get(s);
87
+ if (i !== void 0)
88
+ return i;
89
+ }
90
+ return r[t.options.horizontal ? "offsetWidth" : "offsetHeight"];
91
+ }, N = (r, {
77
92
  adjustments: a = 0,
78
93
  behavior: t
79
94
  }, e) => {
80
95
  var s, i;
81
- const o = l + a;
82
96
  (i = (s = e.scrollElement) == null ? void 0 : s.scrollTo) == null || i.call(s, {
83
- [e.options.horizontal ? "left" : "top"]: o,
97
+ [e.options.horizontal ? "left" : "top"]: r + a,
84
98
  behavior: t
85
99
  });
86
- };
87
- class j {
100
+ }, q = N;
101
+ class U {
88
102
  constructor(a) {
89
- this.unsubs = [], this.scrollElement = null, this.targetWindow = null, this.isScrolling = !1, this.scrollState = null, this.measurementsCache = [], this.itemSizeCache = /* @__PURE__ */ new Map(), this.laneAssignments = /* @__PURE__ */ new Map(), this.pendingMeasuredCacheIndexes = [], this.prevLanes = void 0, this.lanesChangedFlag = !1, this.lanesSettling = !1, this.scrollRect = null, this.scrollOffset = null, this.scrollDirection = null, this.scrollAdjustments = 0, this.elementsCache = /* @__PURE__ */ new Map(), this.now = () => {
103
+ this.unsubs = [], this.scrollElement = null, this.targetWindow = null, this.isScrolling = !1, this.scrollState = null, this.measurementsCache = [], this._flatMeasurements = null, this.itemSizeCache = /* @__PURE__ */ new Map(), this.itemSizeCacheVersion = 0, this.laneAssignments = /* @__PURE__ */ new Map(), this.pendingMin = null, this.prevLanes = void 0, this.lanesChangedFlag = !1, this.lanesSettling = !1, this.pendingScrollAnchor = null, this.scrollRect = null, this.scrollOffset = null, this.scrollDirection = null, this.scrollAdjustments = 0, this._iosDeferredAdjustment = 0, this._iosTouching = !1, this._iosJustTouchEnded = !1, this._iosTouchEndTimerId = null, this._intendedScrollOffset = null, this.elementsCache = /* @__PURE__ */ new Map(), this.now = () => {
90
104
  var t, e, s;
91
105
  return ((s = (e = (t = this.targetWindow) == null ? void 0 : t.performance) == null ? void 0 : e.now) == null ? void 0 : s.call(e)) ?? Date.now();
92
106
  }, this.observer = /* @__PURE__ */ (() => {
93
107
  let t = null;
94
108
  const e = () => t || (!this.targetWindow || !this.targetWindow.ResizeObserver ? null : t = new this.targetWindow.ResizeObserver((s) => {
95
109
  s.forEach((i) => {
96
- const o = () => {
97
- const n = i.target, r = this.indexFromElement(n);
98
- if (!n.isConnected) {
99
- this.observer.unobserve(n);
110
+ const n = () => {
111
+ const o = i.target, l = this.indexFromElement(o);
112
+ if (!o.isConnected) {
113
+ this.observer.unobserve(o);
114
+ for (const [u, d] of this.elementsCache)
115
+ if (d === o) {
116
+ this.elementsCache.delete(u);
117
+ break;
118
+ }
100
119
  return;
101
120
  }
102
- this.shouldMeasureDuringScroll(r) && this.resizeItem(
103
- r,
104
- this.options.measureElement(n, i, this)
121
+ this.shouldMeasureDuringScroll(l) && this.resizeItem(
122
+ l,
123
+ this.options.measureElement(o, i, this)
105
124
  );
106
125
  };
107
- this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(o) : o();
126
+ this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(n) : n();
108
127
  });
109
128
  }));
110
129
  return {
@@ -122,9 +141,8 @@ class j {
122
141
  }
123
142
  };
124
143
  })(), this.range = null, this.setOptions = (t) => {
125
- Object.entries(t).forEach(([e, s]) => {
126
- typeof s > "u" && delete t[e];
127
- }), this.options = {
144
+ var e, s;
145
+ const i = {
128
146
  debug: !1,
129
147
  initialOffset: 0,
130
148
  overscan: 1,
@@ -133,29 +151,69 @@ class j {
133
151
  scrollPaddingStart: 0,
134
152
  scrollPaddingEnd: 0,
135
153
  horizontal: !1,
136
- getItemKey: F,
154
+ getItemKey: k,
137
155
  rangeExtractor: W,
138
156
  onChange: () => {
139
157
  },
140
- measureElement: N,
158
+ measureElement: V,
141
159
  initialRect: { width: 0, height: 0 },
142
160
  scrollMargin: 0,
143
161
  gap: 0,
144
162
  indexAttribute: "data-index",
145
163
  initialMeasurementsCache: [],
146
164
  lanes: 1,
165
+ anchorTo: "start",
166
+ followOnAppend: !1,
167
+ scrollEndThreshold: 1,
147
168
  isScrollingResetDelay: 150,
148
169
  enabled: !0,
149
170
  isRtl: !1,
150
171
  useScrollendEvent: !1,
151
172
  useAnimationFrameWithResizeObserver: !1,
152
173
  laneAssignmentMode: "estimate",
153
- ...t
174
+ useCachedMeasurements: !1
154
175
  };
176
+ for (const h in t) {
177
+ const S = t[h];
178
+ S !== void 0 && (i[h] = S);
179
+ }
180
+ const n = this.options;
181
+ let o = null, l = null, u = !1;
182
+ if (n !== void 0 && n.enabled && i.enabled && i.anchorTo === "end" && this.scrollElement !== null) {
183
+ const h = n.count, S = i.count, c = this.getMeasurements(), v = h > 0 ? ((e = c[0]) == null ? void 0 : e.key) ?? n.getItemKey(0) : null, g = h > 0 ? ((s = c[h - 1]) == null ? void 0 : s.key) ?? n.getItemKey(h - 1) : null;
184
+ if (S !== h || h > 0 && S > 0 && (i.getItemKey(0) !== v || i.getItemKey(S - 1) !== g)) {
185
+ u = !0;
186
+ const f = h > 0 ? this.getVirtualItemForOffset(this.getScrollOffset()) ?? c[0] : null;
187
+ f && (o = [f.key, this.getScrollOffset() - f.start]);
188
+ const b = i.followOnAppend === !0 ? "auto" : i.followOnAppend || null;
189
+ b && S > h && this.isAtEnd(n.scrollEndThreshold) && (h === 0 || i.getItemKey(S - 1) !== g) && (l = b);
190
+ }
191
+ }
192
+ this.options = i, u && (this.pendingMin = 0, this.itemSizeCacheVersion++);
193
+ let d = !1, m = 0;
194
+ if (o && this.scrollOffset !== null) {
195
+ const [h, S] = o, c = this.getMeasurements(), { count: v, getItemKey: g } = this.options;
196
+ let p = 0;
197
+ for (; p < v && g(p) !== h; )
198
+ p++;
199
+ if (p < v) {
200
+ const E = c[p];
201
+ if (E) {
202
+ const f = E.start + S;
203
+ f !== this.scrollOffset && (m = f - this.scrollOffset, this.scrollOffset = f, d = !0);
204
+ }
205
+ }
206
+ }
207
+ (d || l) && (this.pendingScrollAnchor = [
208
+ d ? o[0] : null,
209
+ d ? o[1] : 0,
210
+ l,
211
+ m
212
+ ]);
155
213
  }, this.notify = (t) => {
156
214
  var e, s;
157
215
  (s = (e = this.options).onChange) == null || s.call(e, this, t);
158
- }, this.maybeNotify = p(
216
+ }, this.maybeNotify = M(
159
217
  () => (this.calculateRange(), [
160
218
  this.isScrolling,
161
219
  this.range ? this.range.startIndex : null,
@@ -185,35 +243,72 @@ class j {
185
243
  this.maybeNotify();
186
244
  return;
187
245
  }
188
- this.scrollElement = e, this.scrollElement && "ownerDocument" in this.scrollElement ? this.targetWindow = this.scrollElement.ownerDocument.defaultView : this.targetWindow = ((t = this.scrollElement) == null ? void 0 : t.window) ?? null, this.elementsCache.forEach((s) => {
189
- this.observer.observe(s);
246
+ if (this.scrollElement = e, this.scrollElement && "ownerDocument" in this.scrollElement ? this.targetWindow = this.scrollElement.ownerDocument.defaultView : this.targetWindow = ((t = this.scrollElement) == null ? void 0 : t.window) ?? null, this.elementsCache.forEach((i) => {
247
+ this.observer.observe(i);
190
248
  }), this.unsubs.push(
191
- this.options.observeElementRect(this, (s) => {
192
- this.scrollRect = s, this.maybeNotify();
249
+ this.options.observeElementRect(this, (i) => {
250
+ this.scrollRect = i, this.maybeNotify();
193
251
  })
194
252
  ), this.unsubs.push(
195
- this.options.observeElementOffset(this, (s, i) => {
196
- this.scrollAdjustments = 0, this.scrollDirection = i ? this.getScrollOffset() < s ? "forward" : "backward" : null, this.scrollOffset = s, this.isScrolling = i, this.scrollState && this.scheduleScrollReconcile(), this.maybeNotify();
253
+ this.options.observeElementOffset(this, (i, n) => {
254
+ this._intendedScrollOffset !== null && Math.abs(i - this._intendedScrollOffset) < 1.5 && (i = this._intendedScrollOffset), this._intendedScrollOffset = null, this.scrollAdjustments = 0, this.scrollDirection = n ? this.getScrollOffset() < i ? "forward" : "backward" : null, this.scrollOffset = i, this.isScrolling = n, this._flushIosDeferredIfReady(), this.scrollState && this.scheduleScrollReconcile(), this.maybeNotify();
197
255
  })
198
- ), this._scrollToOffset(this.getScrollOffset(), {
256
+ ), "addEventListener" in this.scrollElement) {
257
+ const i = this.scrollElement, n = () => {
258
+ this._iosTouching = !0, this._iosJustTouchEnded = !1, this._iosTouchEndTimerId !== null && this.targetWindow != null && (this.targetWindow.clearTimeout(this._iosTouchEndTimerId), this._iosTouchEndTimerId = null);
259
+ }, o = () => {
260
+ this._iosTouching = !1, !(!y() || this.targetWindow == null) && (this._iosJustTouchEnded = !0, this._iosTouchEndTimerId = this.targetWindow.setTimeout(() => {
261
+ this._iosJustTouchEnded = !1, this._iosTouchEndTimerId = null, this._flushIosDeferredIfReady();
262
+ }, 150));
263
+ };
264
+ i.addEventListener(
265
+ "touchstart",
266
+ n,
267
+ x
268
+ ), i.addEventListener(
269
+ "touchend",
270
+ o,
271
+ x
272
+ ), this.unsubs.push(() => {
273
+ i.removeEventListener("touchstart", n), i.removeEventListener("touchend", o), this._iosTouchEndTimerId !== null && this.targetWindow != null && (this.targetWindow.clearTimeout(this._iosTouchEndTimerId), this._iosTouchEndTimerId = null);
274
+ });
275
+ }
276
+ this._scrollToOffset(this.getScrollOffset(), {
199
277
  adjustments: void 0,
200
278
  behavior: void 0
201
279
  });
202
280
  }
281
+ const s = this.pendingScrollAnchor;
282
+ if (this.pendingScrollAnchor = null, s && this.scrollElement && this.options.enabled) {
283
+ const [i, n, o, l] = s;
284
+ i !== null && !o && (y() && (this.isScrolling || this._iosTouching || this._iosJustTouchEnded) ? l !== 0 && (this._iosDeferredAdjustment += l) : this._scrollToOffset(this.getScrollOffset(), {
285
+ adjustments: void 0,
286
+ behavior: void 0
287
+ })), o && this.scrollToEnd({ behavior: o });
288
+ }
289
+ }, this._flushIosDeferredIfReady = () => {
290
+ if (this._iosDeferredAdjustment === 0 || this.isScrolling || this._iosTouching || this._iosJustTouchEnded) return;
291
+ const t = this.getScrollOffset(), e = this.getMaxScrollOffset();
292
+ if (t < 0 || t > e) return;
293
+ const s = this._iosDeferredAdjustment;
294
+ this._iosDeferredAdjustment = 0, this._scrollToOffset(t, {
295
+ adjustments: this.scrollAdjustments += s,
296
+ behavior: void 0
297
+ });
203
298
  }, this.rafId = null, this.getSize = () => this.options.enabled ? (this.scrollRect = this.scrollRect ?? this.options.initialRect, this.scrollRect[this.options.horizontal ? "width" : "height"]) : (this.scrollRect = null, 0), this.getScrollOffset = () => this.options.enabled ? (this.scrollOffset = this.scrollOffset ?? (typeof this.options.initialOffset == "function" ? this.options.initialOffset() : this.options.initialOffset), this.scrollOffset) : (this.scrollOffset = null, 0), this.getFurthestMeasurement = (t, e) => {
204
299
  const s = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
205
- for (let o = e - 1; o >= 0; o--) {
206
- const n = t[o];
207
- if (s.has(n.lane))
300
+ for (let n = e - 1; n >= 0; n--) {
301
+ const o = t[n];
302
+ if (s.has(o.lane))
208
303
  continue;
209
- const r = i.get(
210
- n.lane
304
+ const l = i.get(
305
+ o.lane
211
306
  );
212
- if (r == null || n.end > r.end ? i.set(n.lane, n) : n.end < r.end && s.set(n.lane, !0), s.size === this.options.lanes)
307
+ if (l == null || o.end > l.end ? i.set(o.lane, o) : o.end < l.end && s.set(o.lane, !0), s.size === this.options.lanes)
213
308
  break;
214
309
  }
215
- return i.size === this.options.lanes ? Array.from(i.values()).sort((o, n) => o.end === n.end ? o.index - n.index : o.end - n.end)[0] : void 0;
216
- }, this.getMeasurementOptions = p(
310
+ return i.size === this.options.lanes ? Array.from(i.values()).sort((n, o) => n.end === o.end ? n.index - o.index : n.end - o.end)[0] : void 0;
311
+ }, this.getMeasurementOptions = M(
217
312
  () => [
218
313
  this.options.count,
219
314
  this.options.paddingStart,
@@ -223,92 +318,117 @@ class j {
223
318
  this.options.lanes,
224
319
  this.options.laneAssignmentMode
225
320
  ],
226
- (t, e, s, i, o, n, r) => (this.prevLanes !== void 0 && this.prevLanes !== n && (this.lanesChangedFlag = !0), this.prevLanes = n, this.pendingMeasuredCacheIndexes = [], {
321
+ (t, e, s, i, n, o, l) => (this.prevLanes !== void 0 && this.prevLanes !== o && (this.lanesChangedFlag = !0), this.prevLanes = o, this.pendingMin = null, {
227
322
  count: t,
228
323
  paddingStart: e,
229
324
  scrollMargin: s,
230
325
  getItemKey: i,
231
- enabled: o,
232
- lanes: n,
233
- laneAssignmentMode: r
326
+ enabled: n,
327
+ lanes: o,
328
+ laneAssignmentMode: l
234
329
  }),
235
330
  {
236
331
  key: !1
237
332
  }
238
- ), this.getMeasurements = p(
239
- () => [this.getMeasurementOptions(), this.itemSizeCache],
333
+ ), this.getMeasurements = M(
334
+ () => [this.getMeasurementOptions(), this.itemSizeCacheVersion],
240
335
  ({
241
336
  count: t,
242
337
  paddingStart: e,
243
338
  scrollMargin: s,
244
339
  getItemKey: i,
245
- enabled: o,
246
- lanes: n,
247
- laneAssignmentMode: r
340
+ enabled: n,
341
+ lanes: o,
342
+ laneAssignmentMode: l
248
343
  }, u) => {
249
- if (!o)
344
+ const d = this.itemSizeCache;
345
+ if (!n)
250
346
  return this.measurementsCache = [], this.itemSizeCache.clear(), this.laneAssignments.clear(), [];
251
347
  if (this.laneAssignments.size > t)
252
- for (const h of this.laneAssignments.keys())
253
- h >= t && this.laneAssignments.delete(h);
254
- this.lanesChangedFlag && (this.lanesChangedFlag = !1, this.lanesSettling = !0, this.measurementsCache = [], this.itemSizeCache.clear(), this.laneAssignments.clear(), this.pendingMeasuredCacheIndexes = []), this.measurementsCache.length === 0 && !this.lanesSettling && (this.measurementsCache = this.options.initialMeasurementsCache, this.measurementsCache.forEach((h) => {
255
- this.itemSizeCache.set(h.key, h.size);
348
+ for (const c of this.laneAssignments.keys())
349
+ c >= t && this.laneAssignments.delete(c);
350
+ this.lanesChangedFlag && (this.lanesChangedFlag = !1, this.lanesSettling = !0, this.measurementsCache = [], this.itemSizeCache.clear(), this.laneAssignments.clear(), this.pendingMin = null), this.measurementsCache.length === 0 && !this.lanesSettling && (this.measurementsCache = this.options.initialMeasurementsCache, this.measurementsCache.forEach((c) => {
351
+ this.itemSizeCache.set(c.key, c.size);
256
352
  }));
257
- const c = this.lanesSettling ? 0 : this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0;
258
- this.pendingMeasuredCacheIndexes = [], this.lanesSettling && this.measurementsCache.length === t && (this.lanesSettling = !1);
259
- const d = this.measurementsCache.slice(0, c), v = new Array(n).fill(
353
+ const m = this.lanesSettling ? 0 : this.pendingMin ?? 0;
354
+ if (this.pendingMin = null, this.lanesSettling && this.measurementsCache.length === t && (this.lanesSettling = !1), o === 1) {
355
+ const c = this.options.gap, v = t * 2;
356
+ let g = this._flatMeasurements;
357
+ if (!g || g.length < v) {
358
+ const f = new Float64Array(v);
359
+ g && m > 0 && f.set(g.subarray(0, m * 2)), g = f, this._flatMeasurements = g;
360
+ }
361
+ let p;
362
+ if (m === 0)
363
+ p = e + s;
364
+ else {
365
+ const f = m - 1;
366
+ p = g[f * 2] + g[f * 2 + 1] + c;
367
+ }
368
+ for (let f = m; f < t; f++) {
369
+ const b = i(f), _ = d.get(b), z = typeof _ == "number" ? _ : this.options.estimateSize(f);
370
+ g[f * 2] = p, g[f * 2 + 1] = z, p += z + c;
371
+ }
372
+ const E = F(t, g, i);
373
+ return this.measurementsCache = E, E;
374
+ }
375
+ const h = this.measurementsCache.slice(0, m), S = new Array(o).fill(
260
376
  void 0
261
377
  );
262
- for (let h = 0; h < c; h++) {
263
- const m = d[h];
264
- m && (v[m.lane] = h);
378
+ for (let c = 0; c < m; c++) {
379
+ const v = h[c];
380
+ v && (S[v.lane] = c);
265
381
  }
266
- for (let h = c; h < t; h++) {
267
- const m = i(h), b = this.laneAssignments.get(h);
268
- let g, S;
269
- const y = r === "estimate" || u.has(m);
270
- if (b !== void 0 && this.options.lanes > 1) {
271
- g = b;
272
- const f = v[g], O = f !== void 0 ? d[f] : void 0;
273
- S = O ? O.end + this.options.gap : e + s;
382
+ for (let c = m; c < t; c++) {
383
+ const v = i(c), g = this.laneAssignments.get(c);
384
+ let p, E;
385
+ const f = l === "estimate" || d.has(v);
386
+ if (g !== void 0 && this.options.lanes > 1) {
387
+ p = g;
388
+ const O = S[p], T = O !== void 0 ? h[O] : void 0;
389
+ E = T ? T.end + this.options.gap : e + s;
274
390
  } else {
275
- const f = this.options.lanes === 1 ? d[h - 1] : this.getFurthestMeasurement(d, h);
276
- S = f ? f.end + this.options.gap : e + s, g = f ? f.lane : h % this.options.lanes, this.options.lanes > 1 && y && this.laneAssignments.set(h, g);
391
+ const O = this.options.lanes === 1 ? h[c - 1] : this.getFurthestMeasurement(h, c);
392
+ E = O ? O.end + this.options.gap : e + s, p = O ? O.lane : c % this.options.lanes, this.options.lanes > 1 && f && this.laneAssignments.set(c, p);
277
393
  }
278
- const E = u.get(m), x = typeof E == "number" ? E : this.options.estimateSize(h), A = S + x;
279
- d[h] = {
280
- index: h,
281
- start: S,
282
- size: x,
283
- end: A,
284
- key: m,
285
- lane: g
286
- }, v[g] = h;
394
+ const b = d.get(v), _ = typeof b == "number" ? b : this.options.estimateSize(c), z = E + _;
395
+ h[c] = {
396
+ index: c,
397
+ start: E,
398
+ size: _,
399
+ end: z,
400
+ key: v,
401
+ lane: p
402
+ }, S[p] = c;
287
403
  }
288
- return this.measurementsCache = d, d;
404
+ return this.measurementsCache = h, h;
289
405
  },
290
406
  {
291
407
  key: process.env.NODE_ENV !== "production" && "getMeasurements",
292
408
  debug: () => this.options.debug
293
409
  }
294
- ), this.calculateRange = p(
410
+ ), this.calculateRange = M(
295
411
  () => [
296
412
  this.getMeasurements(),
297
413
  this.getSize(),
298
414
  this.getScrollOffset(),
299
415
  this.options.lanes
300
416
  ],
301
- (t, e, s, i) => this.range = t.length > 0 && e > 0 ? T({
417
+ (t, e, s, i) => this.range = t.length > 0 && e > 0 ? K({
302
418
  measurements: t,
303
419
  outerSize: e,
304
420
  scrollOffset: s,
305
- lanes: i
421
+ lanes: i,
422
+ // Pass the typed array so binary search + forward-walk can
423
+ // read start/end directly from Float64Array, skipping the
424
+ // Proxy traps that materialize a full VirtualItem per probe.
425
+ flat: i === 1 && this._flatMeasurements != null ? this._flatMeasurements : null
306
426
  }) : null,
307
427
  {
308
428
  key: process.env.NODE_ENV !== "production" && "calculateRange",
309
429
  debug: () => this.options.debug
310
430
  }
311
- ), this.getVirtualIndexes = p(
431
+ ), this.getVirtualIndexes = M(
312
432
  () => {
313
433
  let t = null, e = null;
314
434
  const s = this.calculateRange();
@@ -320,9 +440,9 @@ class j {
320
440
  e
321
441
  ];
322
442
  },
323
- (t, e, s, i, o) => i === null || o === null ? [] : t({
443
+ (t, e, s, i, n) => i === null || n === null ? [] : t({
324
444
  startIndex: i,
325
- endIndex: o,
445
+ endIndex: n,
326
446
  overscan: e,
327
447
  count: s
328
448
  }),
@@ -344,38 +464,67 @@ class j {
344
464
  const i = Math.max(
345
465
  this.options.overscan,
346
466
  Math.ceil((this.range.endIndex - this.range.startIndex) / 2)
347
- ), o = Math.max(0, s - i), n = Math.min(
467
+ ), n = Math.max(0, s - i), o = Math.min(
348
468
  this.options.count - 1,
349
469
  s + i
350
470
  );
351
- return t >= o && t <= n;
471
+ return t >= n && t <= o;
352
472
  }
353
473
  return !0;
354
474
  }, this.measureElement = (t) => {
355
475
  if (!t) {
356
- this.elementsCache.forEach((o, n) => {
357
- o.isConnected || (this.observer.unobserve(o), this.elementsCache.delete(n));
476
+ this.elementsCache.forEach((n, o) => {
477
+ n.isConnected || (this.observer.unobserve(n), this.elementsCache.delete(o));
358
478
  });
359
479
  return;
360
480
  }
361
481
  const e = this.indexFromElement(t), s = this.options.getItemKey(e), i = this.elementsCache.get(s);
362
482
  i !== t && (i && this.observer.unobserve(i), this.observer.observe(t), this.elementsCache.set(s, t)), (!this.isScrolling || this.scrollState) && this.shouldMeasureDuringScroll(e) && this.resizeItem(e, this.options.measureElement(t, void 0, this));
363
483
  }, this.resizeItem = (t, e) => {
364
- var s;
365
- const i = this.measurementsCache[t];
366
- if (!i) return;
367
- const o = this.itemSizeCache.get(i.key) ?? i.size, n = e - o;
368
- n !== 0 && (((s = this.scrollState) == null ? void 0 : s.behavior) !== "smooth" && (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(i, n, this) : i.start < this.getScrollOffset() + this.scrollAdjustments) && (process.env.NODE_ENV !== "production" && this.options.debug && console.info("correction", n), this._scrollToOffset(this.getScrollOffset(), {
369
- adjustments: this.scrollAdjustments += n,
370
- behavior: void 0
371
- })), this.pendingMeasuredCacheIndexes.push(i.index), this.itemSizeCache = new Map(this.itemSizeCache.set(i.key, e)), this.notify(!1));
372
- }, this.getVirtualItems = p(
484
+ var s, i;
485
+ if (t < 0 || t >= this.options.count) return;
486
+ let n, o, l;
487
+ const u = this._flatMeasurements;
488
+ if (this.options.lanes === 1 && u !== null)
489
+ l = this.options.getItemKey(t), o = u[t * 2], n = u[t * 2 + 1];
490
+ else {
491
+ const h = this.measurementsCache[t];
492
+ if (!h) return;
493
+ l = h.key, o = h.start, n = h.size;
494
+ }
495
+ const d = this.itemSizeCache.get(l) ?? n, m = e - d;
496
+ if (m !== 0) {
497
+ const h = this.options.anchorTo === "end" && ((s = this.scrollState) == null ? void 0 : s.behavior) !== "smooth" && this.getVirtualDistanceFromEnd() <= this.options.scrollEndThreshold, S = h ? this.getTotalSize() : 0, c = ((i = this.scrollState) == null ? void 0 : i.behavior) !== "smooth" && (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(
498
+ // The callback expects a VirtualItem; build one lazily only
499
+ // when the consumer actually supplied a custom predicate.
500
+ this.measurementsCache[t] ?? {
501
+ index: t,
502
+ key: l,
503
+ start: o,
504
+ size: n,
505
+ end: o + n,
506
+ lane: 0
507
+ },
508
+ m,
509
+ this
510
+ ) : (
511
+ // Default: adjust scrollTop only when the resize is an above-
512
+ // viewport item AND we're not actively scrolling backward.
513
+ // Adjusting during backward scroll fights the user's scroll
514
+ // direction and produces the "items jump while scrolling up"
515
+ // jank reported across many issues. Users who want the old
516
+ // behavior can pass shouldAdjustScrollPositionOnItemSizeChange.
517
+ o < this.getScrollOffset() + this.scrollAdjustments && this.scrollDirection !== "backward"
518
+ ));
519
+ (this.pendingMin === null || t < this.pendingMin) && (this.pendingMin = t), this.itemSizeCache.set(l, e), this.itemSizeCacheVersion++, h ? this.applyScrollAdjustment(this.getTotalSize() - S) : c && this.applyScrollAdjustment(m), this.notify(!1);
520
+ }
521
+ }, this.getVirtualItems = M(
373
522
  () => [this.getVirtualIndexes(), this.getMeasurements()],
374
523
  (t, e) => {
375
524
  const s = [];
376
- for (let i = 0, o = t.length; i < o; i++) {
377
- const n = t[i], r = e[n];
378
- s.push(r);
525
+ for (let i = 0, n = t.length; i < n; i++) {
526
+ const o = t[i], l = e[o];
527
+ s.push(l);
379
528
  }
380
529
  return s;
381
530
  },
@@ -385,15 +534,15 @@ class j {
385
534
  }
386
535
  ), this.getVirtualItemForOffset = (t) => {
387
536
  const e = this.getMeasurements();
388
- if (e.length !== 0)
389
- return M(
390
- e[C(
391
- 0,
392
- e.length - 1,
393
- (s) => M(e[s]).start,
394
- t
395
- )]
396
- );
537
+ if (e.length === 0)
538
+ return;
539
+ const s = this._flatMeasurements, i = this.options.lanes === 1 && s != null, n = A(
540
+ 0,
541
+ e.length - 1,
542
+ i ? (o) => s[o * 2] : (o) => w(e[o]).start,
543
+ t
544
+ );
545
+ return w(e[n]);
397
546
  }, this.getMaxScrollOffset = () => {
398
547
  if (!this.scrollElement) return 0;
399
548
  if ("scrollHeight" in this.scrollElement)
@@ -402,37 +551,40 @@ class j {
402
551
  const t = this.scrollElement.document.documentElement;
403
552
  return this.options.horizontal ? t.scrollWidth - this.scrollElement.innerWidth : t.scrollHeight - this.scrollElement.innerHeight;
404
553
  }
405
- }, this.getOffsetForAlignment = (t, e, s = 0) => {
554
+ }, this.getVirtualDistanceFromEnd = () => Math.max(
555
+ this.getTotalSize() - this.getSize() - this.getScrollOffset(),
556
+ 0
557
+ ), this.getDistanceFromEnd = () => Math.max(this.getMaxScrollOffset() - this.getScrollOffset(), 0), this.isAtEnd = (t = this.options.scrollEndThreshold) => this.getDistanceFromEnd() <= t, this.getOffsetForAlignment = (t, e, s = 0) => {
406
558
  if (!this.scrollElement) return 0;
407
- const i = this.getSize(), o = this.getScrollOffset();
408
- e === "auto" && (e = t >= o + i ? "end" : "start"), e === "center" ? t += (s - i) / 2 : e === "end" && (t -= i);
409
- const n = this.getMaxScrollOffset();
410
- return Math.max(Math.min(n, t), 0);
559
+ const i = this.getSize(), n = this.getScrollOffset();
560
+ e === "auto" && (e = t >= n + i ? "end" : "start"), e === "center" ? t += (s - i) / 2 : e === "end" && (t -= i);
561
+ const o = this.getMaxScrollOffset();
562
+ return Math.max(Math.min(o, t), 0);
411
563
  }, this.getOffsetForIndex = (t, e = "auto") => {
412
564
  t = Math.max(0, Math.min(t, this.options.count - 1));
413
- const s = this.getSize(), i = this.getScrollOffset(), o = this.measurementsCache[t];
414
- if (!o) return;
565
+ const s = this.getSize(), i = this.getScrollOffset(), n = this.measurementsCache[t];
566
+ if (!n) return;
415
567
  if (e === "auto")
416
- if (o.end >= i + s - this.options.scrollPaddingEnd)
568
+ if (n.end >= i + s - this.options.scrollPaddingEnd)
417
569
  e = "end";
418
- else if (o.start <= i + this.options.scrollPaddingStart)
570
+ else if (n.start <= i + this.options.scrollPaddingStart)
419
571
  e = "start";
420
572
  else
421
573
  return [i, e];
422
574
  if (e === "end" && t === this.options.count - 1)
423
575
  return [this.getMaxScrollOffset(), e];
424
- const n = e === "end" ? o.end + this.options.scrollPaddingEnd : o.start - this.options.scrollPaddingStart;
576
+ const o = e === "end" ? n.end + this.options.scrollPaddingEnd : n.start - this.options.scrollPaddingStart;
425
577
  return [
426
- this.getOffsetForAlignment(n, e, o.size),
578
+ this.getOffsetForAlignment(o, e, n.size),
427
579
  e
428
580
  ];
429
581
  }, this.scrollToOffset = (t, { align: e = "start", behavior: s = "auto" } = {}) => {
430
- const i = this.getOffsetForAlignment(t, e), o = this.now();
582
+ const i = this.getOffsetForAlignment(t, e), n = this.now();
431
583
  this.scrollState = {
432
584
  index: null,
433
585
  align: e,
434
586
  behavior: s,
435
- startedAt: o,
587
+ startedAt: n,
436
588
  lastTargetOffset: i,
437
589
  stableFrames: 0
438
590
  }, this._scrollToOffset(i, { adjustments: void 0, behavior: s }), this.scheduleScrollReconcile();
@@ -444,15 +596,15 @@ class j {
444
596
  const i = this.getOffsetForIndex(t, e);
445
597
  if (!i)
446
598
  return;
447
- const [o, n] = i, r = this.now();
599
+ const [n, o] = i, l = this.now();
448
600
  this.scrollState = {
449
601
  index: t,
450
- align: n,
602
+ align: o,
451
603
  behavior: s,
452
- startedAt: r,
453
- lastTargetOffset: o,
604
+ startedAt: l,
605
+ lastTargetOffset: n,
454
606
  stableFrames: 0
455
- }, this._scrollToOffset(o, { adjustments: void 0, behavior: s }), this.scheduleScrollReconcile();
607
+ }, this._scrollToOffset(n, { adjustments: void 0, behavior: s }), this.scheduleScrollReconcile();
456
608
  }, this.scrollBy = (t, { behavior: e = "auto" } = {}) => {
457
609
  const s = this.getScrollOffset() + t, i = this.now();
458
610
  this.scrollState = {
@@ -463,36 +615,68 @@ class j {
463
615
  lastTargetOffset: s,
464
616
  stableFrames: 0
465
617
  }, this._scrollToOffset(s, { adjustments: void 0, behavior: e }), this.scheduleScrollReconcile();
618
+ }, this.scrollToEnd = ({ behavior: t = "auto" } = {}) => {
619
+ if (this.options.count > 0) {
620
+ this.scrollToIndex(this.options.count - 1, {
621
+ align: "end",
622
+ behavior: t
623
+ });
624
+ return;
625
+ }
626
+ this.scrollToOffset(Math.max(this.getTotalSize() - this.getSize(), 0), {
627
+ behavior: t
628
+ });
466
629
  }, this.getTotalSize = () => {
467
630
  var t;
468
631
  const e = this.getMeasurements();
469
632
  let s;
470
633
  if (e.length === 0)
471
634
  s = this.options.paddingStart;
472
- else if (this.options.lanes === 1)
473
- s = ((t = e[e.length - 1]) == null ? void 0 : t.end) ?? 0;
474
- else {
635
+ else if (this.options.lanes === 1) {
636
+ const i = e.length - 1, n = this._flatMeasurements;
637
+ n != null ? s = n[i * 2] + n[i * 2 + 1] : s = ((t = e[i]) == null ? void 0 : t.end) ?? 0;
638
+ } else {
475
639
  const i = Array(this.options.lanes).fill(null);
476
- let o = e.length - 1;
477
- for (; o >= 0 && i.some((n) => n === null); ) {
478
- const n = e[o];
479
- i[n.lane] === null && (i[n.lane] = n.end), o--;
640
+ let n = e.length - 1;
641
+ for (; n >= 0 && i.some((o) => o === null); ) {
642
+ const o = e[n];
643
+ i[o.lane] === null && (i[o.lane] = o.end), n--;
480
644
  }
481
- s = Math.max(...i.filter((n) => n !== null));
645
+ s = Math.max(...i.filter((o) => o !== null));
482
646
  }
483
647
  return Math.max(
484
648
  s - this.options.scrollMargin + this.options.paddingEnd,
485
649
  0
486
650
  );
651
+ }, this.takeSnapshot = () => {
652
+ const t = [];
653
+ if (this.itemSizeCache.size === 0) return t;
654
+ const e = this.getMeasurements();
655
+ for (const s of e)
656
+ s && this.itemSizeCache.has(s.key) && t.push({
657
+ index: s.index,
658
+ key: s.key,
659
+ start: s.start,
660
+ size: s.size,
661
+ end: s.end,
662
+ lane: s.lane
663
+ });
664
+ return t;
487
665
  }, this._scrollToOffset = (t, {
488
666
  adjustments: e,
489
667
  behavior: s
490
668
  }) => {
491
- this.options.scrollToFn(t, { behavior: s, adjustments: e }, this);
669
+ this._intendedScrollOffset = t + (e ?? 0), this.options.scrollToFn(t, { behavior: s, adjustments: e }, this);
492
670
  }, this.measure = () => {
493
- this.itemSizeCache = /* @__PURE__ */ new Map(), this.laneAssignments = /* @__PURE__ */ new Map(), this.notify(!1);
671
+ this.pendingMin = null, this.itemSizeCache.clear(), this.laneAssignments.clear(), this.itemSizeCacheVersion++, this.notify(!1);
494
672
  }, this.setOptions(a);
495
673
  }
674
+ applyScrollAdjustment(a, t) {
675
+ a !== 0 && (process.env.NODE_ENV !== "production" && this.options.debug && console.info("correction", a), y() && (this.isScrolling || this._iosTouching || this._iosJustTouchEnded) ? this._iosDeferredAdjustment += a : this._scrollToOffset(this.getScrollOffset(), {
676
+ adjustments: this.scrollAdjustments += a,
677
+ behavior: t
678
+ }));
679
+ }
496
680
  scheduleScrollReconcile() {
497
681
  if (!this.targetWindow) {
498
682
  this.scrollState = null;
@@ -508,78 +692,79 @@ class j {
508
692
  this.scrollState = null;
509
693
  return;
510
694
  }
511
- const e = this.scrollState.index != null ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align) : void 0, s = e ? e[0] : this.scrollState.lastTargetOffset, i = 1, o = s !== this.scrollState.lastTargetOffset;
512
- if (!o && R(s, this.getScrollOffset())) {
695
+ const e = this.scrollState.index != null ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align) : void 0, s = e ? e[0] : this.scrollState.lastTargetOffset, i = 1, n = s !== this.scrollState.lastTargetOffset;
696
+ if (!n && R(s, this.getScrollOffset())) {
513
697
  if (this.scrollState.stableFrames++, this.scrollState.stableFrames >= i) {
514
- this.scrollState = null;
698
+ this.getScrollOffset() !== s && this._scrollToOffset(s, {
699
+ adjustments: void 0,
700
+ behavior: "auto"
701
+ }), this.scrollState = null;
515
702
  return;
516
703
  }
517
- } else
518
- this.scrollState.stableFrames = 0, o && (this.scrollState.lastTargetOffset = s, this.scrollState.behavior = "auto", this._scrollToOffset(s, {
704
+ } else if (this.scrollState.stableFrames = 0, n) {
705
+ const o = this.getSize() || 600, l = Math.abs(s - this.getScrollOffset()), u = this.scrollState.behavior === "smooth" && l > o;
706
+ this.scrollState.lastTargetOffset = s, u || (this.scrollState.behavior = "auto"), this._scrollToOffset(s, {
519
707
  adjustments: void 0,
520
- behavior: "auto"
521
- }));
708
+ behavior: u ? "smooth" : "auto"
709
+ });
710
+ }
522
711
  this.scheduleScrollReconcile();
523
712
  }
524
713
  }
525
- const C = (l, a, t, e) => {
526
- for (; l <= a; ) {
527
- const s = (l + a) / 2 | 0, i = t(s);
714
+ const A = (r, a, t, e) => {
715
+ for (; r <= a; ) {
716
+ const s = (r + a) / 2 | 0, i = t(s);
528
717
  if (i < e)
529
- l = s + 1;
718
+ r = s + 1;
530
719
  else if (i > e)
531
720
  a = s - 1;
532
721
  else
533
722
  return s;
534
723
  }
535
- return l > 0 ? l - 1 : 0;
724
+ return r > 0 ? r - 1 : 0;
536
725
  };
537
- function T({
538
- measurements: l,
726
+ function K({
727
+ measurements: r,
539
728
  outerSize: a,
540
729
  scrollOffset: t,
541
- lanes: e
730
+ lanes: e,
731
+ flat: s
542
732
  }) {
543
- const s = l.length - 1, i = (r) => l[r].start;
544
- if (l.length <= e)
733
+ const i = r.length - 1, n = s ? (d) => s[d * 2] : (d) => r[d].start, o = s ? (d) => s[d * 2] + s[d * 2 + 1] : (d) => r[d].end;
734
+ if (r.length <= e)
545
735
  return {
546
736
  startIndex: 0,
547
- endIndex: s
737
+ endIndex: i
548
738
  };
549
- let o = C(
550
- 0,
551
- s,
552
- i,
553
- t
554
- ), n = o;
739
+ let l = A(0, i, n, t), u = l;
555
740
  if (e === 1)
556
- for (; n < s && l[n].end < t + a; )
557
- n++;
741
+ for (; u < i && o(u) < t + a; )
742
+ u++;
558
743
  else if (e > 1) {
559
- const r = Array(e).fill(0);
560
- for (; n < s && r.some((c) => c < t + a); ) {
561
- const c = l[n];
562
- r[c.lane] = c.end, n++;
744
+ const d = Array(e).fill(0);
745
+ for (; u < i && d.some((h) => h < t + a); ) {
746
+ const h = r[u];
747
+ d[h.lane] = h.end, u++;
563
748
  }
564
- const u = Array(e).fill(t + a);
565
- for (; o >= 0 && u.some((c) => c >= t); ) {
566
- const c = l[o];
567
- u[c.lane] = c.start, o--;
749
+ const m = Array(e).fill(t + a);
750
+ for (; l >= 0 && m.some((h) => h >= t); ) {
751
+ const h = r[l];
752
+ m[h.lane] = h.start, l--;
568
753
  }
569
- o = Math.max(0, o - o % e), n = Math.min(s, n + (e - 1 - n % e));
754
+ l = Math.max(0, l - l % e), u = Math.min(i, u + (e - 1 - u % e));
570
755
  }
571
- return { startIndex: o, endIndex: n };
756
+ return { startIndex: l, endIndex: u };
572
757
  }
573
758
  export {
574
- j as Virtualizer,
759
+ U as Virtualizer,
575
760
  R as approxEqual,
576
- _ as debounce,
577
- F as defaultKeyExtractor,
761
+ D as debounce,
762
+ k as defaultKeyExtractor,
578
763
  W as defaultRangeExtractor,
579
- V as elementScroll,
580
- N as measureElement,
581
- p as memo,
582
- M as notUndefined,
583
- D as observeElementOffset,
584
- k as observeElementRect
764
+ q as elementScroll,
765
+ V as measureElement,
766
+ M as memo,
767
+ w as notUndefined,
768
+ J as observeElementOffset,
769
+ H as observeElementRect
585
770
  };