react-virtuoso 0.0.0-development → 0.0.0-semantic-release
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -19
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +167 -29
- package/dist/index.mjs +749 -233
- package/package.json +44 -44
- package/dist/react-urx/index.d.ts +0 -111
- package/dist/urx/index.d.ts +0 -7
package/dist/index.mjs
CHANGED
|
@@ -34,6 +34,9 @@ function joinProc(...procs) {
|
|
|
34
34
|
procs.map(call);
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
+
function isDefined(arg) {
|
|
38
|
+
return arg !== void 0;
|
|
39
|
+
}
|
|
37
40
|
function noop() {
|
|
38
41
|
}
|
|
39
42
|
function subscribe(emitter, subscription) {
|
|
@@ -184,7 +187,7 @@ function skip(times) {
|
|
|
184
187
|
};
|
|
185
188
|
}
|
|
186
189
|
function throttleTime(interval) {
|
|
187
|
-
let currentValue;
|
|
190
|
+
let currentValue = null;
|
|
188
191
|
let timeout;
|
|
189
192
|
return (done) => (value) => {
|
|
190
193
|
currentValue = value;
|
|
@@ -392,7 +395,22 @@ function systemToComponent(systemSpec, map2, Root) {
|
|
|
392
395
|
const usePublisher2 = (key) => {
|
|
393
396
|
return React.useCallback(curry2to1(publish, React.useContext(Context)[key]), [key]);
|
|
394
397
|
};
|
|
395
|
-
const
|
|
398
|
+
const useEmitterValue18 = (key) => {
|
|
399
|
+
const system2 = React.useContext(Context);
|
|
400
|
+
const source = system2[key];
|
|
401
|
+
const cb = React.useCallback(
|
|
402
|
+
(c) => {
|
|
403
|
+
return subscribe(source, c);
|
|
404
|
+
},
|
|
405
|
+
[source]
|
|
406
|
+
);
|
|
407
|
+
return React.useSyncExternalStore(
|
|
408
|
+
cb,
|
|
409
|
+
() => getValue(source),
|
|
410
|
+
() => getValue(source)
|
|
411
|
+
);
|
|
412
|
+
};
|
|
413
|
+
const useEmitterValueLegacy = (key) => {
|
|
396
414
|
const system2 = React.useContext(Context);
|
|
397
415
|
const source = system2[key];
|
|
398
416
|
const [value, setValue] = React.useState(curry1to0(getValue, source));
|
|
@@ -406,6 +424,7 @@ function systemToComponent(systemSpec, map2, Root) {
|
|
|
406
424
|
);
|
|
407
425
|
return value;
|
|
408
426
|
};
|
|
427
|
+
const useEmitterValue2 = React.version.startsWith("18") ? useEmitterValue18 : useEmitterValueLegacy;
|
|
409
428
|
const useEmitter2 = (key, callback) => {
|
|
410
429
|
const context = React.useContext(Context);
|
|
411
430
|
const source = context[key];
|
|
@@ -428,17 +447,33 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
428
447
|
return LogLevel2;
|
|
429
448
|
})(LogLevel || {});
|
|
430
449
|
const CONSOLE_METHOD_MAP = {
|
|
431
|
-
[
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
450
|
+
[
|
|
451
|
+
0
|
|
452
|
+
/* DEBUG */
|
|
453
|
+
]: "debug",
|
|
454
|
+
[
|
|
455
|
+
1
|
|
456
|
+
/* INFO */
|
|
457
|
+
]: "log",
|
|
458
|
+
[
|
|
459
|
+
2
|
|
460
|
+
/* WARN */
|
|
461
|
+
]: "warn",
|
|
462
|
+
[
|
|
463
|
+
3
|
|
464
|
+
/* ERROR */
|
|
465
|
+
]: "error"
|
|
435
466
|
};
|
|
436
467
|
const getGlobalThis = () => typeof globalThis === "undefined" ? window : globalThis;
|
|
437
468
|
const loggerSystem = system(
|
|
438
469
|
() => {
|
|
439
|
-
const logLevel = statefulStream(
|
|
470
|
+
const logLevel = statefulStream(
|
|
471
|
+
3
|
|
472
|
+
/* ERROR */
|
|
473
|
+
);
|
|
440
474
|
const log = statefulStream((label, message, level = 1) => {
|
|
441
|
-
|
|
475
|
+
var _a;
|
|
476
|
+
const currentLevel = (_a = getGlobalThis()["VIRTUOSO_LOG_LEVEL"]) != null ? _a : getValue(logLevel);
|
|
442
477
|
if (level >= currentLevel) {
|
|
443
478
|
console[CONSOLE_METHOD_MAP[level]](
|
|
444
479
|
"%creact-virtuoso: %c%s %o",
|
|
@@ -462,12 +497,16 @@ function useSizeWithElRef(callback, enabled = true) {
|
|
|
462
497
|
let callbackRef = (_el) => {
|
|
463
498
|
};
|
|
464
499
|
if (typeof ResizeObserver !== "undefined") {
|
|
465
|
-
const observer =
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
500
|
+
const observer = React.useMemo(() => {
|
|
501
|
+
return new ResizeObserver((entries) => {
|
|
502
|
+
requestAnimationFrame(() => {
|
|
503
|
+
const element = entries[0].target;
|
|
504
|
+
if (element.offsetParent !== null) {
|
|
505
|
+
callback(element);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
}, [callback]);
|
|
471
510
|
callbackRef = (elRef) => {
|
|
472
511
|
if (elRef && enabled) {
|
|
473
512
|
observer.observe(elRef);
|
|
@@ -485,27 +524,33 @@ function useSizeWithElRef(callback, enabled = true) {
|
|
|
485
524
|
function useSize(callback, enabled = true) {
|
|
486
525
|
return useSizeWithElRef(callback, enabled).callbackRef;
|
|
487
526
|
}
|
|
488
|
-
function useChangedListContentsSizes(callback, itemSize, enabled, scrollContainerStateCallback, log, gap, customScrollParent) {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
527
|
+
function useChangedListContentsSizes(callback, itemSize, enabled, scrollContainerStateCallback, log, gap, customScrollParent, horizontalDirection) {
|
|
528
|
+
const memoedCallback = React.useCallback(
|
|
529
|
+
(el) => {
|
|
530
|
+
const ranges = getChangedChildSizes(el.children, itemSize, horizontalDirection ? "offsetWidth" : "offsetHeight", log);
|
|
531
|
+
let scrollableElement = el.parentElement;
|
|
532
|
+
while (!scrollableElement.dataset["virtuosoScroller"]) {
|
|
533
|
+
scrollableElement = scrollableElement.parentElement;
|
|
534
|
+
}
|
|
535
|
+
const windowScrolling = scrollableElement.lastElementChild.dataset["viewportType"] === "window";
|
|
536
|
+
const scrollTop = customScrollParent ? horizontalDirection ? customScrollParent.scrollLeft : customScrollParent.scrollTop : windowScrolling ? horizontalDirection ? window.pageXOffset || document.documentElement.scrollLeft : window.pageYOffset || document.documentElement.scrollTop : horizontalDirection ? scrollableElement.scrollLeft : scrollableElement.scrollTop;
|
|
537
|
+
const scrollHeight = customScrollParent ? horizontalDirection ? customScrollParent.scrollWidth : customScrollParent.scrollHeight : windowScrolling ? horizontalDirection ? document.documentElement.scrollWidth : document.documentElement.scrollHeight : horizontalDirection ? scrollableElement.scrollWidth : scrollableElement.scrollHeight;
|
|
538
|
+
const viewportHeight = customScrollParent ? horizontalDirection ? customScrollParent.offsetWidth : customScrollParent.offsetHeight : windowScrolling ? horizontalDirection ? window.innerWidth : window.innerHeight : horizontalDirection ? scrollableElement.offsetWidth : scrollableElement.offsetHeight;
|
|
539
|
+
scrollContainerStateCallback({
|
|
540
|
+
scrollTop: Math.max(scrollTop, 0),
|
|
541
|
+
scrollHeight,
|
|
542
|
+
viewportHeight
|
|
543
|
+
});
|
|
544
|
+
gap == null ? void 0 : gap(
|
|
545
|
+
horizontalDirection ? resolveGapValue$1("column-gap", getComputedStyle(el).columnGap, log) : resolveGapValue$1("row-gap", getComputedStyle(el).rowGap, log)
|
|
546
|
+
);
|
|
547
|
+
if (ranges !== null) {
|
|
548
|
+
callback(ranges);
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
[callback, itemSize, log, gap, customScrollParent, scrollContainerStateCallback]
|
|
552
|
+
);
|
|
553
|
+
return useSizeWithElRef(memoedCallback, enabled);
|
|
509
554
|
}
|
|
510
555
|
function getChangedChildSizes(children, itemSize, field, log) {
|
|
511
556
|
const length = children.length;
|
|
@@ -543,7 +588,7 @@ function resolveGapValue$1(property, value, log) {
|
|
|
543
588
|
if (value === "normal") {
|
|
544
589
|
return 0;
|
|
545
590
|
}
|
|
546
|
-
return parseInt(value
|
|
591
|
+
return parseInt(value != null ? value : "0", 10);
|
|
547
592
|
}
|
|
548
593
|
function correctItemSize(el, dimension) {
|
|
549
594
|
return Math.round(el.getBoundingClientRect()[dimension]);
|
|
@@ -551,7 +596,7 @@ function correctItemSize(el, dimension) {
|
|
|
551
596
|
function approximatelyEqual(num1, num2) {
|
|
552
597
|
return Math.abs(num1 - num2) < 1.01;
|
|
553
598
|
}
|
|
554
|
-
function useScrollTop(scrollContainerStateCallback, smoothScrollTargetReached, scrollerElement, scrollerRefCallback = noop, customScrollParent) {
|
|
599
|
+
function useScrollTop(scrollContainerStateCallback, smoothScrollTargetReached, scrollerElement, scrollerRefCallback = noop, customScrollParent, horizontalDirection) {
|
|
555
600
|
const scrollerRef = React.useRef(null);
|
|
556
601
|
const scrollTopTarget = React.useRef(null);
|
|
557
602
|
const timeoutRef = React.useRef(null);
|
|
@@ -559,9 +604,9 @@ function useScrollTop(scrollContainerStateCallback, smoothScrollTargetReached, s
|
|
|
559
604
|
(ev) => {
|
|
560
605
|
const el = ev.target;
|
|
561
606
|
const windowScroll = el === window || el === document;
|
|
562
|
-
const scrollTop = windowScroll ? window.pageYOffset || document.documentElement.scrollTop : el.scrollTop;
|
|
563
|
-
const scrollHeight = windowScroll ? document.documentElement.scrollHeight : el.scrollHeight;
|
|
564
|
-
const viewportHeight = windowScroll ? window.innerHeight : el.offsetHeight;
|
|
607
|
+
const scrollTop = horizontalDirection ? windowScroll ? window.pageXOffset || document.documentElement.scrollLeft : el.scrollLeft : windowScroll ? window.pageYOffset || document.documentElement.scrollTop : el.scrollTop;
|
|
608
|
+
const scrollHeight = horizontalDirection ? windowScroll ? document.documentElement.scrollWidth : el.scrollWidth : windowScroll ? document.documentElement.scrollHeight : el.scrollHeight;
|
|
609
|
+
const viewportHeight = horizontalDirection ? windowScroll ? window.innerWidth : el.offsetWidth : windowScroll ? window.innerHeight : el.offsetHeight;
|
|
565
610
|
const call2 = () => {
|
|
566
611
|
scrollContainerStateCallback({
|
|
567
612
|
scrollTop: Math.max(scrollTop, 0),
|
|
@@ -599,7 +644,7 @@ function useScrollTop(scrollContainerStateCallback, smoothScrollTargetReached, s
|
|
|
599
644
|
}, [scrollerRef, handler, scrollerElement, scrollerRefCallback, customScrollParent]);
|
|
600
645
|
function scrollToCallback(location) {
|
|
601
646
|
const scrollerElement2 = scrollerRef.current;
|
|
602
|
-
if (!scrollerElement2 || "offsetHeight" in scrollerElement2 && scrollerElement2.offsetHeight === 0) {
|
|
647
|
+
if (!scrollerElement2 || (horizontalDirection ? "offsetWidth" in scrollerElement2 && scrollerElement2.offsetWidth === 0 : "offsetHeight" in scrollerElement2 && scrollerElement2.offsetHeight === 0)) {
|
|
603
648
|
return;
|
|
604
649
|
}
|
|
605
650
|
const isSmooth = location.behavior === "smooth";
|
|
@@ -607,13 +652,16 @@ function useScrollTop(scrollContainerStateCallback, smoothScrollTargetReached, s
|
|
|
607
652
|
let scrollHeight;
|
|
608
653
|
let scrollTop;
|
|
609
654
|
if (scrollerElement2 === window) {
|
|
610
|
-
scrollHeight = Math.max(
|
|
611
|
-
|
|
612
|
-
|
|
655
|
+
scrollHeight = Math.max(
|
|
656
|
+
correctItemSize(document.documentElement, horizontalDirection ? "width" : "height"),
|
|
657
|
+
horizontalDirection ? document.documentElement.scrollWidth : document.documentElement.scrollHeight
|
|
658
|
+
);
|
|
659
|
+
offsetHeight = horizontalDirection ? window.innerWidth : window.innerHeight;
|
|
660
|
+
scrollTop = horizontalDirection ? document.documentElement.scrollLeft : document.documentElement.scrollTop;
|
|
613
661
|
} else {
|
|
614
|
-
scrollHeight = scrollerElement2
|
|
615
|
-
offsetHeight = correctItemSize(scrollerElement2, "height");
|
|
616
|
-
scrollTop = scrollerElement2
|
|
662
|
+
scrollHeight = scrollerElement2[horizontalDirection ? "scrollWidth" : "scrollHeight"];
|
|
663
|
+
offsetHeight = correctItemSize(scrollerElement2, horizontalDirection ? "width" : "height");
|
|
664
|
+
scrollTop = scrollerElement2[horizontalDirection ? "scrollLeft" : "scrollTop"];
|
|
617
665
|
}
|
|
618
666
|
const maxScrollTop = scrollHeight - offsetHeight;
|
|
619
667
|
location.top = Math.ceil(Math.max(Math.min(maxScrollTop, location.top), 0));
|
|
@@ -637,9 +685,15 @@ function useScrollTop(scrollContainerStateCallback, smoothScrollTargetReached, s
|
|
|
637
685
|
} else {
|
|
638
686
|
scrollTopTarget.current = null;
|
|
639
687
|
}
|
|
688
|
+
if (horizontalDirection) {
|
|
689
|
+
location = { left: location.top, behavior: location.behavior };
|
|
690
|
+
}
|
|
640
691
|
scrollerElement2.scrollTo(location);
|
|
641
692
|
}
|
|
642
693
|
function scrollByCallback(location) {
|
|
694
|
+
if (horizontalDirection) {
|
|
695
|
+
location = { left: location.top, behavior: location.behavior };
|
|
696
|
+
}
|
|
643
697
|
scrollerRef.current.scrollBy(location);
|
|
644
698
|
}
|
|
645
699
|
return { scrollerRef, scrollByCallback, scrollToCallback };
|
|
@@ -660,6 +714,7 @@ const domIOSystem = system(
|
|
|
660
714
|
const scrollTo = stream();
|
|
661
715
|
const scrollBy = stream();
|
|
662
716
|
const scrollingInProgress = statefulStream(false);
|
|
717
|
+
const horizontalDirection = statefulStream(false);
|
|
663
718
|
connect(
|
|
664
719
|
pipe(
|
|
665
720
|
scrollContainerState,
|
|
@@ -676,6 +731,7 @@ const domIOSystem = system(
|
|
|
676
731
|
);
|
|
677
732
|
connect(scrollTop, statefulScrollTop);
|
|
678
733
|
return {
|
|
734
|
+
// input
|
|
679
735
|
scrollContainerState,
|
|
680
736
|
scrollTop,
|
|
681
737
|
viewportHeight,
|
|
@@ -685,8 +741,11 @@ const domIOSystem = system(
|
|
|
685
741
|
footerHeight,
|
|
686
742
|
scrollHeight,
|
|
687
743
|
smoothScrollTargetReached,
|
|
744
|
+
horizontalDirection,
|
|
745
|
+
// signals
|
|
688
746
|
scrollTo,
|
|
689
747
|
scrollBy,
|
|
748
|
+
// state
|
|
690
749
|
statefulScrollTop,
|
|
691
750
|
deviation,
|
|
692
751
|
scrollingInProgress
|
|
@@ -724,14 +783,26 @@ function remove(node, key) {
|
|
|
724
783
|
return adjust(clone(node, { r: remove(r, key) }));
|
|
725
784
|
}
|
|
726
785
|
}
|
|
786
|
+
function find(node, key) {
|
|
787
|
+
if (empty(node)) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
if (key === node.k) {
|
|
791
|
+
return node.v;
|
|
792
|
+
} else if (key < node.k) {
|
|
793
|
+
return find(node.l, key);
|
|
794
|
+
} else {
|
|
795
|
+
return find(node.r, key);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
727
798
|
function findMaxKeyValue(node, value, field = "k") {
|
|
728
799
|
if (empty(node)) {
|
|
729
800
|
return [-Infinity, void 0];
|
|
730
801
|
}
|
|
731
|
-
if (node[field] === value) {
|
|
802
|
+
if (Number(node[field]) === value) {
|
|
732
803
|
return [node.k, node.v];
|
|
733
804
|
}
|
|
734
|
-
if (node[field] < value) {
|
|
805
|
+
if (Number(node[field]) < value) {
|
|
735
806
|
const r = findMaxKeyValue(node.r, value, field);
|
|
736
807
|
if (r[0] === -Infinity) {
|
|
737
808
|
return [node.k, node.v];
|
|
@@ -918,6 +989,16 @@ function rangeIncludes(refRange) {
|
|
|
918
989
|
return range.start === startIndex && (range.end === endIndex || range.end === Infinity) && range.value === size;
|
|
919
990
|
};
|
|
920
991
|
}
|
|
992
|
+
function affectedGroupCount(offset, groupIndices) {
|
|
993
|
+
let recognizedOffsetItems = 0;
|
|
994
|
+
let groupIndex = 0;
|
|
995
|
+
while (recognizedOffsetItems < offset) {
|
|
996
|
+
recognizedOffsetItems += groupIndices[groupIndex + 1] - groupIndices[groupIndex] - 1;
|
|
997
|
+
groupIndex++;
|
|
998
|
+
}
|
|
999
|
+
const offsetIsExact = recognizedOffsetItems === offset;
|
|
1000
|
+
return groupIndex - (offsetIsExact ? 0 : 1);
|
|
1001
|
+
}
|
|
921
1002
|
function insertRanges(sizeTree, ranges) {
|
|
922
1003
|
let syncStart = empty(sizeTree) ? 0 : Infinity;
|
|
923
1004
|
for (const range of ranges) {
|
|
@@ -1086,6 +1167,13 @@ function originalIndexFromItemIndex(itemIndex, sizes) {
|
|
|
1086
1167
|
function hasGroups(sizes) {
|
|
1087
1168
|
return !empty(sizes.groupOffsetTree);
|
|
1088
1169
|
}
|
|
1170
|
+
function sizeTreeToRanges(sizeTree) {
|
|
1171
|
+
return walk(sizeTree).map(({ k: startIndex, v: size }, index, sizeArray) => {
|
|
1172
|
+
const nextSize = sizeArray[index + 1];
|
|
1173
|
+
const endIndex = nextSize ? nextSize.k - 1 : Infinity;
|
|
1174
|
+
return { startIndex, endIndex, size };
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1089
1177
|
const SIZE_MAP = {
|
|
1090
1178
|
offsetHeight: "height",
|
|
1091
1179
|
offsetWidth: "width"
|
|
@@ -1109,6 +1197,18 @@ const sizeSystem = system(
|
|
|
1109
1197
|
pipe(sizeRanges, withLatestFrom(groupIndices, log, gap), scan(sizeStateReducer, initial), distinctUntilChanged()),
|
|
1110
1198
|
initial
|
|
1111
1199
|
);
|
|
1200
|
+
const prevGroupIndices = statefulStreamFromEmitter(
|
|
1201
|
+
pipe(
|
|
1202
|
+
groupIndices,
|
|
1203
|
+
distinctUntilChanged(),
|
|
1204
|
+
scan((prev, curr) => ({ prev: prev.current, current: curr }), {
|
|
1205
|
+
prev: [],
|
|
1206
|
+
current: []
|
|
1207
|
+
}),
|
|
1208
|
+
map(({ prev }) => prev)
|
|
1209
|
+
),
|
|
1210
|
+
[]
|
|
1211
|
+
);
|
|
1112
1212
|
connect(
|
|
1113
1213
|
pipe(
|
|
1114
1214
|
groupIndices,
|
|
@@ -1192,10 +1292,15 @@ const sizeSystem = system(
|
|
|
1192
1292
|
map((val) => val.diff)
|
|
1193
1293
|
),
|
|
1194
1294
|
(offset) => {
|
|
1295
|
+
const { groupIndices: groupIndices2 } = getValue(sizes);
|
|
1195
1296
|
if (offset > 0) {
|
|
1196
1297
|
publish(recalcInProgress, true);
|
|
1197
|
-
publish(unshiftWith, offset);
|
|
1298
|
+
publish(unshiftWith, offset + affectedGroupCount(offset, groupIndices2));
|
|
1198
1299
|
} else if (offset < 0) {
|
|
1300
|
+
const prevGroupIndicesValue = getValue(prevGroupIndices);
|
|
1301
|
+
if (prevGroupIndicesValue.length > 0) {
|
|
1302
|
+
offset -= affectedGroupCount(-offset, prevGroupIndicesValue);
|
|
1303
|
+
}
|
|
1199
1304
|
publish(shiftWith, offset);
|
|
1200
1305
|
}
|
|
1201
1306
|
}
|
|
@@ -1215,8 +1320,59 @@ const sizeSystem = system(
|
|
|
1215
1320
|
unshiftWith,
|
|
1216
1321
|
withLatestFrom(sizes),
|
|
1217
1322
|
map(([unshiftWith2, sizes2]) => {
|
|
1218
|
-
|
|
1219
|
-
|
|
1323
|
+
const groupedMode = sizes2.groupIndices.length > 0;
|
|
1324
|
+
const initialRanges = [];
|
|
1325
|
+
const defaultSize = sizes2.lastSize;
|
|
1326
|
+
if (groupedMode) {
|
|
1327
|
+
const firstGroupSize = find(sizes2.sizeTree, 0);
|
|
1328
|
+
let prependedGroupItemsCount = 0;
|
|
1329
|
+
let groupIndex = 0;
|
|
1330
|
+
while (prependedGroupItemsCount < unshiftWith2) {
|
|
1331
|
+
const theGroupIndex = sizes2.groupIndices[groupIndex];
|
|
1332
|
+
const groupItemCount = sizes2.groupIndices.length === groupIndex + 1 ? Infinity : sizes2.groupIndices[groupIndex + 1] - theGroupIndex - 1;
|
|
1333
|
+
initialRanges.push({
|
|
1334
|
+
startIndex: theGroupIndex,
|
|
1335
|
+
endIndex: theGroupIndex,
|
|
1336
|
+
size: firstGroupSize
|
|
1337
|
+
});
|
|
1338
|
+
initialRanges.push({
|
|
1339
|
+
startIndex: theGroupIndex + 1,
|
|
1340
|
+
endIndex: theGroupIndex + 1 + groupItemCount - 1,
|
|
1341
|
+
size: defaultSize
|
|
1342
|
+
});
|
|
1343
|
+
groupIndex++;
|
|
1344
|
+
prependedGroupItemsCount += groupItemCount + 1;
|
|
1345
|
+
}
|
|
1346
|
+
const sizeTreeKV = walk(sizes2.sizeTree);
|
|
1347
|
+
const firstGroupIsExpanded = prependedGroupItemsCount !== unshiftWith2;
|
|
1348
|
+
if (firstGroupIsExpanded) {
|
|
1349
|
+
sizeTreeKV.shift();
|
|
1350
|
+
}
|
|
1351
|
+
return sizeTreeKV.reduce(
|
|
1352
|
+
(acc, { k: index, v: size }) => {
|
|
1353
|
+
let ranges = acc.ranges;
|
|
1354
|
+
if (acc.prevSize !== 0) {
|
|
1355
|
+
ranges = [
|
|
1356
|
+
...acc.ranges,
|
|
1357
|
+
{
|
|
1358
|
+
startIndex: acc.prevIndex,
|
|
1359
|
+
endIndex: index + unshiftWith2 - 1,
|
|
1360
|
+
size: acc.prevSize
|
|
1361
|
+
}
|
|
1362
|
+
];
|
|
1363
|
+
}
|
|
1364
|
+
return {
|
|
1365
|
+
ranges,
|
|
1366
|
+
prevIndex: index + unshiftWith2,
|
|
1367
|
+
prevSize: size
|
|
1368
|
+
};
|
|
1369
|
+
},
|
|
1370
|
+
{
|
|
1371
|
+
ranges: initialRanges,
|
|
1372
|
+
prevIndex: unshiftWith2,
|
|
1373
|
+
prevSize: 0
|
|
1374
|
+
}
|
|
1375
|
+
).ranges;
|
|
1220
1376
|
}
|
|
1221
1377
|
return walk(sizes2.sizeTree).reduce(
|
|
1222
1378
|
(acc, { k: index, v: size }) => {
|
|
@@ -1229,7 +1385,7 @@ const sizeSystem = system(
|
|
|
1229
1385
|
{
|
|
1230
1386
|
ranges: [],
|
|
1231
1387
|
prevIndex: 0,
|
|
1232
|
-
prevSize:
|
|
1388
|
+
prevSize: defaultSize
|
|
1233
1389
|
}
|
|
1234
1390
|
).ranges;
|
|
1235
1391
|
})
|
|
@@ -1251,22 +1407,53 @@ const sizeSystem = system(
|
|
|
1251
1407
|
shiftWith,
|
|
1252
1408
|
withLatestFrom(sizes, gap),
|
|
1253
1409
|
map(([shiftWith2, sizes2, gap2]) => {
|
|
1254
|
-
|
|
1255
|
-
|
|
1410
|
+
const groupedMode = sizes2.groupIndices.length > 0;
|
|
1411
|
+
if (groupedMode) {
|
|
1412
|
+
if (empty(sizes2.sizeTree)) {
|
|
1413
|
+
return sizes2;
|
|
1414
|
+
}
|
|
1415
|
+
let newSizeTree = newTree();
|
|
1416
|
+
const prevGroupIndicesValue = getValue(prevGroupIndices);
|
|
1417
|
+
let removedItemsCount = 0;
|
|
1418
|
+
let groupIndex = 0;
|
|
1419
|
+
let groupOffset = 0;
|
|
1420
|
+
while (removedItemsCount < -shiftWith2) {
|
|
1421
|
+
groupOffset = prevGroupIndicesValue[groupIndex];
|
|
1422
|
+
const groupItemCount = prevGroupIndicesValue[groupIndex + 1] - groupOffset - 1;
|
|
1423
|
+
groupIndex++;
|
|
1424
|
+
removedItemsCount += groupItemCount + 1;
|
|
1425
|
+
}
|
|
1426
|
+
newSizeTree = walk(sizes2.sizeTree).reduce((acc, { k, v }) => {
|
|
1427
|
+
return insert(acc, Math.max(0, k + shiftWith2), v);
|
|
1428
|
+
}, newSizeTree);
|
|
1429
|
+
const aGroupIsShrunk = removedItemsCount !== -shiftWith2;
|
|
1430
|
+
if (aGroupIsShrunk) {
|
|
1431
|
+
const firstGroupSize = find(sizes2.sizeTree, groupOffset);
|
|
1432
|
+
newSizeTree = insert(newSizeTree, 0, firstGroupSize);
|
|
1433
|
+
const nextItemSize = findMaxKeyValue(sizes2.sizeTree, -shiftWith2 + 1)[1];
|
|
1434
|
+
newSizeTree = insert(newSizeTree, 1, nextItemSize);
|
|
1435
|
+
}
|
|
1436
|
+
return {
|
|
1437
|
+
...sizes2,
|
|
1438
|
+
sizeTree: newSizeTree,
|
|
1439
|
+
...createOffsetTree(sizes2.offsetTree, 0, newSizeTree, gap2)
|
|
1440
|
+
};
|
|
1441
|
+
} else {
|
|
1442
|
+
const newSizeTree = walk(sizes2.sizeTree).reduce((acc, { k, v }) => {
|
|
1443
|
+
return insert(acc, Math.max(0, k + shiftWith2), v);
|
|
1444
|
+
}, newTree());
|
|
1445
|
+
return {
|
|
1446
|
+
...sizes2,
|
|
1447
|
+
sizeTree: newSizeTree,
|
|
1448
|
+
...createOffsetTree(sizes2.offsetTree, 0, newSizeTree, gap2)
|
|
1449
|
+
};
|
|
1256
1450
|
}
|
|
1257
|
-
const newSizeTree = walk(sizes2.sizeTree).reduce((acc, { k, v }) => {
|
|
1258
|
-
return insert(acc, Math.max(0, k + shiftWith2), v);
|
|
1259
|
-
}, newTree());
|
|
1260
|
-
return {
|
|
1261
|
-
...sizes2,
|
|
1262
|
-
sizeTree: newSizeTree,
|
|
1263
|
-
...createOffsetTree(sizes2.offsetTree, 0, newSizeTree, gap2)
|
|
1264
|
-
};
|
|
1265
1451
|
})
|
|
1266
1452
|
),
|
|
1267
1453
|
sizes
|
|
1268
1454
|
);
|
|
1269
1455
|
return {
|
|
1456
|
+
// input
|
|
1270
1457
|
data,
|
|
1271
1458
|
totalCount,
|
|
1272
1459
|
sizeRanges,
|
|
@@ -1279,6 +1466,7 @@ const sizeSystem = system(
|
|
|
1279
1466
|
beforeUnshiftWith,
|
|
1280
1467
|
firstItemIndex,
|
|
1281
1468
|
gap,
|
|
1469
|
+
// output
|
|
1282
1470
|
sizes,
|
|
1283
1471
|
listRefresh,
|
|
1284
1472
|
statefulTotalCount,
|
|
@@ -1319,6 +1507,7 @@ const scrollToIndexSystem = system(
|
|
|
1319
1507
|
{ log }
|
|
1320
1508
|
]) => {
|
|
1321
1509
|
const scrollToIndex = stream();
|
|
1510
|
+
const scrollTargetReached = stream();
|
|
1322
1511
|
const topListHeight = statefulStream(0);
|
|
1323
1512
|
let unsubscribeNextListRefresh = null;
|
|
1324
1513
|
let cleartTimeoutRef = null;
|
|
@@ -1374,6 +1563,7 @@ const scrollToIndexSystem = system(
|
|
|
1374
1563
|
log2("retrying to scroll to", { location }, LogLevel.DEBUG);
|
|
1375
1564
|
publish(scrollToIndex, location);
|
|
1376
1565
|
} else {
|
|
1566
|
+
publish(scrollTargetReached, true);
|
|
1377
1567
|
log2("list did not change, scroll successful", {}, LogLevel.DEBUG);
|
|
1378
1568
|
}
|
|
1379
1569
|
};
|
|
@@ -1402,6 +1592,7 @@ const scrollToIndexSystem = system(
|
|
|
1402
1592
|
);
|
|
1403
1593
|
return {
|
|
1404
1594
|
scrollToIndex,
|
|
1595
|
+
scrollTargetReached,
|
|
1405
1596
|
topListHeight
|
|
1406
1597
|
};
|
|
1407
1598
|
},
|
|
@@ -1581,6 +1772,7 @@ const stateFlagsSystem = system(([{ scrollContainerState, scrollTop, viewportHei
|
|
|
1581
1772
|
pipe(
|
|
1582
1773
|
isScrolling,
|
|
1583
1774
|
filter((value) => !value),
|
|
1775
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1584
1776
|
mapTo(0)
|
|
1585
1777
|
),
|
|
1586
1778
|
scrollVelocity
|
|
@@ -1628,15 +1820,23 @@ const propsReadySystem = system(
|
|
|
1628
1820
|
tup(loggerSystem),
|
|
1629
1821
|
{ singleton: true }
|
|
1630
1822
|
);
|
|
1823
|
+
function skipFrames(frameCount, callback) {
|
|
1824
|
+
if (frameCount == 0) {
|
|
1825
|
+
callback();
|
|
1826
|
+
} else {
|
|
1827
|
+
requestAnimationFrame(() => skipFrames(frameCount - 1, callback));
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1631
1830
|
function getInitialTopMostItemIndexNumber(location, totalCount) {
|
|
1632
1831
|
const lastIndex = totalCount - 1;
|
|
1633
1832
|
const index = typeof location === "number" ? location : location.index === "LAST" ? lastIndex : location.index;
|
|
1634
1833
|
return index;
|
|
1635
1834
|
}
|
|
1636
1835
|
const initialTopMostItemIndexSystem = system(
|
|
1637
|
-
([{ sizes, listRefresh, defaultItemSize }, { scrollTop }, { scrollToIndex }, { didMount }]) => {
|
|
1836
|
+
([{ sizes, listRefresh, defaultItemSize }, { scrollTop }, { scrollToIndex, scrollTargetReached }, { didMount }]) => {
|
|
1638
1837
|
const scrolledToInitialItem = statefulStream(true);
|
|
1639
1838
|
const initialTopMostItemIndex = statefulStream(0);
|
|
1839
|
+
const initialItemFinalLocationReached = statefulStream(true);
|
|
1640
1840
|
connect(
|
|
1641
1841
|
pipe(
|
|
1642
1842
|
didMount,
|
|
@@ -1646,17 +1846,29 @@ const initialTopMostItemIndexSystem = system(
|
|
|
1646
1846
|
),
|
|
1647
1847
|
scrolledToInitialItem
|
|
1648
1848
|
);
|
|
1849
|
+
connect(
|
|
1850
|
+
pipe(
|
|
1851
|
+
didMount,
|
|
1852
|
+
withLatestFrom(initialTopMostItemIndex),
|
|
1853
|
+
filter(([_, location]) => !!location),
|
|
1854
|
+
mapTo(false)
|
|
1855
|
+
),
|
|
1856
|
+
initialItemFinalLocationReached
|
|
1857
|
+
);
|
|
1649
1858
|
subscribe(
|
|
1650
1859
|
pipe(
|
|
1651
1860
|
combineLatest(listRefresh, didMount),
|
|
1652
|
-
withLatestFrom(scrolledToInitialItem, sizes, defaultItemSize),
|
|
1653
|
-
filter(([[, didMount2], scrolledToInitialItem2, { sizeTree }, defaultItemSize2]) => {
|
|
1654
|
-
return didMount2 && (!empty(sizeTree) || defaultItemSize2
|
|
1861
|
+
withLatestFrom(scrolledToInitialItem, sizes, defaultItemSize, initialItemFinalLocationReached),
|
|
1862
|
+
filter(([[, didMount2], scrolledToInitialItem2, { sizeTree }, defaultItemSize2, scrollScheduled]) => {
|
|
1863
|
+
return didMount2 && (!empty(sizeTree) || isDefined(defaultItemSize2)) && !scrolledToInitialItem2 && !scrollScheduled;
|
|
1655
1864
|
}),
|
|
1656
1865
|
withLatestFrom(initialTopMostItemIndex)
|
|
1657
1866
|
),
|
|
1658
1867
|
([, initialTopMostItemIndex2]) => {
|
|
1659
|
-
|
|
1868
|
+
handleNext(scrollTargetReached, () => {
|
|
1869
|
+
publish(initialItemFinalLocationReached, true);
|
|
1870
|
+
});
|
|
1871
|
+
skipFrames(3, () => {
|
|
1660
1872
|
handleNext(scrollTop, () => {
|
|
1661
1873
|
publish(scrolledToInitialItem, true);
|
|
1662
1874
|
});
|
|
@@ -1666,7 +1878,8 @@ const initialTopMostItemIndexSystem = system(
|
|
|
1666
1878
|
);
|
|
1667
1879
|
return {
|
|
1668
1880
|
scrolledToInitialItem,
|
|
1669
|
-
initialTopMostItemIndex
|
|
1881
|
+
initialTopMostItemIndex,
|
|
1882
|
+
initialItemFinalLocationReached
|
|
1670
1883
|
};
|
|
1671
1884
|
},
|
|
1672
1885
|
tup(sizeSystem, domIOSystem, scrollToIndexSystem, propsReadySystem),
|
|
@@ -1754,7 +1967,9 @@ const followOutputSystem = system(
|
|
|
1754
1967
|
withLatestFrom(followOutput, totalCount)
|
|
1755
1968
|
),
|
|
1756
1969
|
([, followOutput2]) => {
|
|
1757
|
-
|
|
1970
|
+
if (getValue(scrolledToInitialItem)) {
|
|
1971
|
+
trapNextSizeIncrease(followOutput2 !== false);
|
|
1972
|
+
}
|
|
1758
1973
|
}
|
|
1759
1974
|
);
|
|
1760
1975
|
subscribe(autoscrollToBottom, () => {
|
|
@@ -1897,10 +2112,12 @@ const sizeRangeSystem = system(
|
|
|
1897
2112
|
[0, 0]
|
|
1898
2113
|
);
|
|
1899
2114
|
return {
|
|
2115
|
+
// input
|
|
1900
2116
|
listBoundary,
|
|
1901
2117
|
overscan,
|
|
1902
2118
|
topListHeight,
|
|
1903
2119
|
increaseViewportBy,
|
|
2120
|
+
// output
|
|
1904
2121
|
visibleRange
|
|
1905
2122
|
};
|
|
1906
2123
|
},
|
|
@@ -1994,6 +2211,26 @@ function buildListState(items, topItems, totalCount, gap, sizes, firstItemIndex)
|
|
|
1994
2211
|
firstItemIndex
|
|
1995
2212
|
};
|
|
1996
2213
|
}
|
|
2214
|
+
function buildListStateFromItemCount(itemCount, initialTopMostItemIndex, sizes, firstItemIndex, gap, data) {
|
|
2215
|
+
let includedGroupsCount = 0;
|
|
2216
|
+
if (sizes.groupIndices.length > 0) {
|
|
2217
|
+
for (const index of sizes.groupIndices) {
|
|
2218
|
+
if (index - includedGroupsCount >= itemCount) {
|
|
2219
|
+
break;
|
|
2220
|
+
}
|
|
2221
|
+
includedGroupsCount++;
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
const adjustedCount = itemCount + includedGroupsCount;
|
|
2225
|
+
const initialTopMostItemIndexNumber = getInitialTopMostItemIndexNumber(initialTopMostItemIndex, adjustedCount);
|
|
2226
|
+
const items = Array.from({ length: adjustedCount }).map((_, index) => ({
|
|
2227
|
+
index: index + initialTopMostItemIndexNumber,
|
|
2228
|
+
size: 0,
|
|
2229
|
+
offset: 0,
|
|
2230
|
+
data: data[index + initialTopMostItemIndexNumber]
|
|
2231
|
+
}));
|
|
2232
|
+
return buildListState(items, [], adjustedCount, gap, sizes, firstItemIndex);
|
|
2233
|
+
}
|
|
1997
2234
|
const listStateSystem = system(
|
|
1998
2235
|
([
|
|
1999
2236
|
{ sizes, totalCount, data, firstItemIndex, gap },
|
|
@@ -2006,6 +2243,7 @@ const listStateSystem = system(
|
|
|
2006
2243
|
{ recalcInProgress }
|
|
2007
2244
|
]) => {
|
|
2008
2245
|
const topItemsIndexes = statefulStream([]);
|
|
2246
|
+
const initialItemCount = statefulStream(0);
|
|
2009
2247
|
const itemsRendered = stream();
|
|
2010
2248
|
connect(groupedListSystem2.topItemsIndexes, topItemsIndexes);
|
|
2011
2249
|
const listState = statefulStreamFromEmitter(
|
|
@@ -2023,8 +2261,9 @@ const listStateSystem = system(
|
|
|
2023
2261
|
duc(gap),
|
|
2024
2262
|
data
|
|
2025
2263
|
),
|
|
2026
|
-
filter(([mount, recalcInProgress2]) => {
|
|
2027
|
-
|
|
2264
|
+
filter(([mount, recalcInProgress2, , totalCount2, , , , , , , data2]) => {
|
|
2265
|
+
const dataChangeInProgress = data2 && data2.length !== totalCount2;
|
|
2266
|
+
return mount && !recalcInProgress2 && !dataChangeInProgress;
|
|
2028
2267
|
}),
|
|
2029
2268
|
map(
|
|
2030
2269
|
([
|
|
@@ -2042,11 +2281,22 @@ const listStateSystem = system(
|
|
|
2042
2281
|
]) => {
|
|
2043
2282
|
const sizesValue = sizes2;
|
|
2044
2283
|
const { sizeTree, offsetTree } = sizesValue;
|
|
2045
|
-
|
|
2284
|
+
const initialItemCountValue = getValue(initialItemCount);
|
|
2285
|
+
if (totalCount2 === 0) {
|
|
2046
2286
|
return { ...EMPTY_LIST_STATE, totalCount: totalCount2 };
|
|
2047
2287
|
}
|
|
2288
|
+
if (startOffset === 0 && endOffset === 0) {
|
|
2289
|
+
if (initialItemCountValue === 0) {
|
|
2290
|
+
return { ...EMPTY_LIST_STATE, totalCount: totalCount2 };
|
|
2291
|
+
} else {
|
|
2292
|
+
return buildListStateFromItemCount(initialItemCountValue, initialTopMostItemIndex2, sizes2, firstItemIndex2, gap2, data2 || []);
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2048
2295
|
if (empty(sizeTree)) {
|
|
2049
|
-
|
|
2296
|
+
if (initialItemCountValue > 0) {
|
|
2297
|
+
return null;
|
|
2298
|
+
}
|
|
2299
|
+
const state = buildListState(
|
|
2050
2300
|
probeItemSet(getInitialTopMostItemIndexNumber(initialTopMostItemIndex2, totalCount2), sizesValue, data2),
|
|
2051
2301
|
[],
|
|
2052
2302
|
totalCount2,
|
|
@@ -2054,6 +2304,7 @@ const listStateSystem = system(
|
|
|
2054
2304
|
sizesValue,
|
|
2055
2305
|
firstItemIndex2
|
|
2056
2306
|
);
|
|
2307
|
+
return state;
|
|
2057
2308
|
}
|
|
2058
2309
|
const topItems = [];
|
|
2059
2310
|
if (topItemsIndexes2.length > 0) {
|
|
@@ -2107,6 +2358,7 @@ const listStateSystem = system(
|
|
|
2107
2358
|
return buildListState(items, topItems, totalCount2, gap2, sizesValue, firstItemIndex2);
|
|
2108
2359
|
}
|
|
2109
2360
|
),
|
|
2361
|
+
//@ts-expect-error filter needs to be fixed
|
|
2110
2362
|
filter((value) => value !== null),
|
|
2111
2363
|
distinctUntilChanged()
|
|
2112
2364
|
),
|
|
@@ -2115,7 +2367,7 @@ const listStateSystem = system(
|
|
|
2115
2367
|
connect(
|
|
2116
2368
|
pipe(
|
|
2117
2369
|
data,
|
|
2118
|
-
filter(
|
|
2370
|
+
filter(isDefined),
|
|
2119
2371
|
map((data2) => data2 == null ? void 0 : data2.length)
|
|
2120
2372
|
),
|
|
2121
2373
|
totalCount
|
|
@@ -2185,7 +2437,7 @@ const listStateSystem = system(
|
|
|
2185
2437
|
distinctUntilChanged(rangeComparator)
|
|
2186
2438
|
)
|
|
2187
2439
|
);
|
|
2188
|
-
return { listState, topItemsIndexes, endReached, startReached, rangeChanged, itemsRendered, ...stateFlags };
|
|
2440
|
+
return { listState, topItemsIndexes, endReached, startReached, rangeChanged, itemsRendered, initialItemCount, ...stateFlags };
|
|
2189
2441
|
},
|
|
2190
2442
|
tup(
|
|
2191
2443
|
sizeSystem,
|
|
@@ -2200,34 +2452,22 @@ const listStateSystem = system(
|
|
|
2200
2452
|
{ singleton: true }
|
|
2201
2453
|
);
|
|
2202
2454
|
const initialItemCountSystem = system(
|
|
2203
|
-
([{ sizes, firstItemIndex, data, gap }, { listState }, { didMount }]) => {
|
|
2204
|
-
const initialItemCount = statefulStream(0);
|
|
2455
|
+
([{ sizes, firstItemIndex, data, gap }, { initialTopMostItemIndex }, { initialItemCount, listState }, { didMount }]) => {
|
|
2205
2456
|
connect(
|
|
2206
2457
|
pipe(
|
|
2207
2458
|
didMount,
|
|
2208
2459
|
withLatestFrom(initialItemCount),
|
|
2209
2460
|
filter(([, count]) => count !== 0),
|
|
2210
|
-
withLatestFrom(sizes, firstItemIndex, gap, data),
|
|
2211
|
-
map(([[, count], sizes2, firstItemIndex2, gap2, data2 = []]) => {
|
|
2212
|
-
|
|
2213
|
-
if (sizes2.groupIndices.length > 0) {
|
|
2214
|
-
for (const index of sizes2.groupIndices) {
|
|
2215
|
-
if (index - includedGroupsCount >= count) {
|
|
2216
|
-
break;
|
|
2217
|
-
}
|
|
2218
|
-
includedGroupsCount++;
|
|
2219
|
-
}
|
|
2220
|
-
}
|
|
2221
|
-
const adjustedCount = count + includedGroupsCount;
|
|
2222
|
-
const items = Array.from({ length: adjustedCount }).map((_, index) => ({ index, size: 0, offset: 0, data: data2[index] }));
|
|
2223
|
-
return buildListState(items, [], adjustedCount, gap2, sizes2, firstItemIndex2);
|
|
2461
|
+
withLatestFrom(initialTopMostItemIndex, sizes, firstItemIndex, gap, data),
|
|
2462
|
+
map(([[, count], initialTopMostItemIndexValue, sizes2, firstItemIndex2, gap2, data2 = []]) => {
|
|
2463
|
+
return buildListStateFromItemCount(count, initialTopMostItemIndexValue, sizes2, firstItemIndex2, gap2, data2);
|
|
2224
2464
|
})
|
|
2225
2465
|
),
|
|
2226
2466
|
listState
|
|
2227
2467
|
);
|
|
2228
|
-
return {
|
|
2468
|
+
return {};
|
|
2229
2469
|
},
|
|
2230
|
-
tup(sizeSystem, listStateSystem, propsReadySystem),
|
|
2470
|
+
tup(sizeSystem, initialTopMostItemIndexSystem, listStateSystem, propsReadySystem),
|
|
2231
2471
|
{ singleton: true }
|
|
2232
2472
|
);
|
|
2233
2473
|
const scrollSeekSystem = system(
|
|
@@ -2343,9 +2583,9 @@ const upwardScrollFixSystem = system(
|
|
|
2343
2583
|
[0, [], 0, 0]
|
|
2344
2584
|
),
|
|
2345
2585
|
filter(([amount]) => amount !== 0),
|
|
2346
|
-
withLatestFrom(scrollTop, scrollDirection, scrollingInProgress, isAtBottom, log),
|
|
2347
|
-
filter(([, scrollTop2, scrollDirection2, scrollingInProgress2]) => {
|
|
2348
|
-
return !scrollingInProgress2 && scrollTop2 !== 0 && scrollDirection2 === UP;
|
|
2586
|
+
withLatestFrom(scrollTop, scrollDirection, scrollingInProgress, isAtBottom, log, recalcInProgress),
|
|
2587
|
+
filter(([, scrollTop2, scrollDirection2, scrollingInProgress2, , , recalcInProgress2]) => {
|
|
2588
|
+
return !recalcInProgress2 && !scrollingInProgress2 && scrollTop2 !== 0 && scrollDirection2 === UP;
|
|
2349
2589
|
}),
|
|
2350
2590
|
map(([[amount], , , , , log2]) => {
|
|
2351
2591
|
log2("Upward scrolling compensation", { amount }, LogLevel.DEBUG);
|
|
@@ -2391,7 +2631,32 @@ const upwardScrollFixSystem = system(
|
|
|
2391
2631
|
pipe(
|
|
2392
2632
|
beforeUnshiftWith,
|
|
2393
2633
|
withLatestFrom(sizes, gap),
|
|
2394
|
-
map(([offset, { lastSize }, gap2]) =>
|
|
2634
|
+
map(([offset, { lastSize: defaultItemSize, groupIndices, sizeTree }, gap2]) => {
|
|
2635
|
+
function getItemOffset(itemCount) {
|
|
2636
|
+
return itemCount * (defaultItemSize + gap2);
|
|
2637
|
+
}
|
|
2638
|
+
if (groupIndices.length === 0) {
|
|
2639
|
+
return getItemOffset(offset);
|
|
2640
|
+
} else {
|
|
2641
|
+
let amount = 0;
|
|
2642
|
+
const defaultGroupSize = find(sizeTree, 0);
|
|
2643
|
+
let recognizedOffsetItems = 0;
|
|
2644
|
+
let groupIndex = 0;
|
|
2645
|
+
while (recognizedOffsetItems < offset) {
|
|
2646
|
+
recognizedOffsetItems++;
|
|
2647
|
+
amount += defaultGroupSize;
|
|
2648
|
+
let groupItemCount = groupIndices.length === groupIndex + 1 ? Infinity : groupIndices[groupIndex + 1] - groupIndices[groupIndex] - 1;
|
|
2649
|
+
if (recognizedOffsetItems + groupItemCount > offset) {
|
|
2650
|
+
amount -= defaultGroupSize;
|
|
2651
|
+
groupItemCount = offset - recognizedOffsetItems + 1;
|
|
2652
|
+
}
|
|
2653
|
+
recognizedOffsetItems += groupItemCount;
|
|
2654
|
+
amount += getItemOffset(groupItemCount);
|
|
2655
|
+
groupIndex++;
|
|
2656
|
+
}
|
|
2657
|
+
return amount;
|
|
2658
|
+
}
|
|
2659
|
+
})
|
|
2395
2660
|
),
|
|
2396
2661
|
(offset) => {
|
|
2397
2662
|
publish(deviation, offset);
|
|
@@ -2409,7 +2674,7 @@ const upwardScrollFixSystem = system(
|
|
|
2409
2674
|
tup(domIOSystem, stateFlagsSystem, listStateSystem, sizeSystem, loggerSystem, recalcSystem)
|
|
2410
2675
|
);
|
|
2411
2676
|
const initialScrollTopSystem = system(
|
|
2412
|
-
([{
|
|
2677
|
+
([{ didMount }, { scrollTo }, { listState }]) => {
|
|
2413
2678
|
const initialScrollTop = statefulStream(0);
|
|
2414
2679
|
subscribe(
|
|
2415
2680
|
pipe(
|
|
@@ -2421,11 +2686,12 @@ const initialScrollTopSystem = system(
|
|
|
2421
2686
|
(location) => {
|
|
2422
2687
|
handleNext(
|
|
2423
2688
|
pipe(
|
|
2424
|
-
|
|
2425
|
-
|
|
2689
|
+
listState,
|
|
2690
|
+
skip(1),
|
|
2691
|
+
filter((state) => state.items.length > 1)
|
|
2426
2692
|
),
|
|
2427
2693
|
() => {
|
|
2428
|
-
|
|
2694
|
+
requestAnimationFrame(() => {
|
|
2429
2695
|
publish(scrollTo, location);
|
|
2430
2696
|
});
|
|
2431
2697
|
}
|
|
@@ -2436,7 +2702,7 @@ const initialScrollTopSystem = system(
|
|
|
2436
2702
|
initialScrollTop
|
|
2437
2703
|
};
|
|
2438
2704
|
},
|
|
2439
|
-
tup(
|
|
2705
|
+
tup(propsReadySystem, domIOSystem, listStateSystem),
|
|
2440
2706
|
{ singleton: true }
|
|
2441
2707
|
);
|
|
2442
2708
|
const alignToBottomSystem = system(
|
|
@@ -2449,6 +2715,7 @@ const alignToBottomSystem = system(
|
|
|
2449
2715
|
map(([, viewportHeight2, totalListHeight2]) => {
|
|
2450
2716
|
return Math.max(0, viewportHeight2 - totalListHeight2);
|
|
2451
2717
|
}),
|
|
2718
|
+
throttleTime(0),
|
|
2452
2719
|
distinctUntilChanged()
|
|
2453
2720
|
),
|
|
2454
2721
|
0
|
|
@@ -2491,13 +2758,31 @@ const windowScrollerSystem = system(([{ scrollTo, scrollContainerState }]) => {
|
|
|
2491
2758
|
windowScrollTo
|
|
2492
2759
|
);
|
|
2493
2760
|
return {
|
|
2761
|
+
// config
|
|
2494
2762
|
useWindowScroll,
|
|
2495
2763
|
customScrollParent,
|
|
2764
|
+
// input
|
|
2496
2765
|
windowScrollContainerState,
|
|
2497
2766
|
windowViewportRect,
|
|
2767
|
+
// signals
|
|
2498
2768
|
windowScrollTo
|
|
2499
2769
|
};
|
|
2500
2770
|
}, tup(domIOSystem));
|
|
2771
|
+
const defaultCalculateViewLocation = ({
|
|
2772
|
+
itemTop: itemTop2,
|
|
2773
|
+
itemBottom,
|
|
2774
|
+
viewportTop,
|
|
2775
|
+
viewportBottom,
|
|
2776
|
+
locationParams: { behavior, align, ...rest }
|
|
2777
|
+
}) => {
|
|
2778
|
+
if (itemTop2 < viewportTop) {
|
|
2779
|
+
return { ...rest, behavior, align: align != null ? align : "start" };
|
|
2780
|
+
}
|
|
2781
|
+
if (itemBottom > viewportBottom) {
|
|
2782
|
+
return { ...rest, behavior, align: align != null ? align : "end" };
|
|
2783
|
+
}
|
|
2784
|
+
return null;
|
|
2785
|
+
};
|
|
2501
2786
|
const scrollIntoViewSystem = system(
|
|
2502
2787
|
([
|
|
2503
2788
|
{ sizes, totalCount, gap },
|
|
@@ -2511,24 +2796,27 @@ const scrollIntoViewSystem = system(
|
|
|
2511
2796
|
withLatestFrom(sizes, viewportHeight, totalCount, headerHeight, fixedHeaderHeight, fixedFooterHeight, scrollTop),
|
|
2512
2797
|
withLatestFrom(gap),
|
|
2513
2798
|
map(([[viewLocation, sizes2, viewportHeight2, totalCount2, headerHeight2, fixedHeaderHeight2, fixedFooterHeight2, scrollTop2], gap2]) => {
|
|
2514
|
-
const { done, behavior, align, ...rest } = viewLocation;
|
|
2515
|
-
let location = null;
|
|
2799
|
+
const { done, behavior, align, calculateViewLocation = defaultCalculateViewLocation, ...rest } = viewLocation;
|
|
2516
2800
|
const actualIndex = originalIndexFromLocation(viewLocation, sizes2, totalCount2 - 1);
|
|
2517
2801
|
const itemTop2 = offsetOf(actualIndex, sizes2.offsetTree, gap2) + headerHeight2 + fixedHeaderHeight2;
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2802
|
+
const itemBottom = itemTop2 + findMaxKeyValue(sizes2.sizeTree, actualIndex)[1];
|
|
2803
|
+
const viewportTop = scrollTop2 + fixedHeaderHeight2;
|
|
2804
|
+
const viewportBottom = scrollTop2 + viewportHeight2 - fixedFooterHeight2;
|
|
2805
|
+
const location = calculateViewLocation({
|
|
2806
|
+
itemTop: itemTop2,
|
|
2807
|
+
itemBottom,
|
|
2808
|
+
viewportTop,
|
|
2809
|
+
viewportBottom,
|
|
2810
|
+
locationParams: { behavior, align, ...rest }
|
|
2811
|
+
});
|
|
2526
2812
|
if (location) {
|
|
2527
2813
|
done && handleNext(
|
|
2528
2814
|
pipe(
|
|
2529
2815
|
scrollingInProgress,
|
|
2530
|
-
|
|
2531
|
-
|
|
2816
|
+
filter((value) => value === false),
|
|
2817
|
+
// skips the initial publish of false, and the cleanup call.
|
|
2818
|
+
// but if scrollingInProgress is true, we skip the initial publish.
|
|
2819
|
+
skip(getValue(scrollingInProgress) ? 1 : 2)
|
|
2532
2820
|
),
|
|
2533
2821
|
done
|
|
2534
2822
|
);
|
|
@@ -2548,6 +2836,53 @@ const scrollIntoViewSystem = system(
|
|
|
2548
2836
|
tup(sizeSystem, domIOSystem, scrollToIndexSystem, listStateSystem, loggerSystem),
|
|
2549
2837
|
{ singleton: true }
|
|
2550
2838
|
);
|
|
2839
|
+
const stateLoadSystem = system(
|
|
2840
|
+
([
|
|
2841
|
+
{ sizes, sizeRanges },
|
|
2842
|
+
{ scrollTop },
|
|
2843
|
+
{ initialTopMostItemIndex },
|
|
2844
|
+
{ didMount },
|
|
2845
|
+
{ useWindowScroll, windowScrollContainerState, windowViewportRect }
|
|
2846
|
+
]) => {
|
|
2847
|
+
const getState = stream();
|
|
2848
|
+
const restoreStateFrom = statefulStream(void 0);
|
|
2849
|
+
const statefulWindowScrollContainerState = statefulStream(null);
|
|
2850
|
+
const statefulWindowViewportRect = statefulStream(null);
|
|
2851
|
+
connect(windowScrollContainerState, statefulWindowScrollContainerState);
|
|
2852
|
+
connect(windowViewportRect, statefulWindowViewportRect);
|
|
2853
|
+
subscribe(
|
|
2854
|
+
pipe(getState, withLatestFrom(sizes, scrollTop, useWindowScroll, statefulWindowScrollContainerState, statefulWindowViewportRect)),
|
|
2855
|
+
([callback, sizes2, scrollTop2, useWindowScroll2, windowScrollContainerState2, windowViewportRect2]) => {
|
|
2856
|
+
const ranges = sizeTreeToRanges(sizes2.sizeTree);
|
|
2857
|
+
if (useWindowScroll2 && windowScrollContainerState2 !== null && windowViewportRect2 !== null) {
|
|
2858
|
+
scrollTop2 = windowScrollContainerState2.scrollTop - windowViewportRect2.offsetTop;
|
|
2859
|
+
}
|
|
2860
|
+
callback({ ranges, scrollTop: scrollTop2 });
|
|
2861
|
+
}
|
|
2862
|
+
);
|
|
2863
|
+
connect(pipe(restoreStateFrom, filter(isDefined), map(locationFromSnapshot)), initialTopMostItemIndex);
|
|
2864
|
+
connect(
|
|
2865
|
+
pipe(
|
|
2866
|
+
didMount,
|
|
2867
|
+
withLatestFrom(restoreStateFrom),
|
|
2868
|
+
filter(([, state]) => state !== void 0),
|
|
2869
|
+
distinctUntilChanged(),
|
|
2870
|
+
map(([, snapshot]) => {
|
|
2871
|
+
return snapshot.ranges;
|
|
2872
|
+
})
|
|
2873
|
+
),
|
|
2874
|
+
sizeRanges
|
|
2875
|
+
);
|
|
2876
|
+
return {
|
|
2877
|
+
getState,
|
|
2878
|
+
restoreStateFrom
|
|
2879
|
+
};
|
|
2880
|
+
},
|
|
2881
|
+
tup(sizeSystem, domIOSystem, initialTopMostItemIndexSystem, propsReadySystem, windowScrollerSystem)
|
|
2882
|
+
);
|
|
2883
|
+
function locationFromSnapshot(snapshot) {
|
|
2884
|
+
return { offset: snapshot.scrollTop, index: 0, align: "start" };
|
|
2885
|
+
}
|
|
2551
2886
|
const featureGroup1System = system(
|
|
2552
2887
|
([
|
|
2553
2888
|
sizeRange,
|
|
@@ -2558,7 +2893,8 @@ const featureGroup1System = system(
|
|
|
2558
2893
|
initialScrollTopSystem2,
|
|
2559
2894
|
alignToBottom,
|
|
2560
2895
|
windowScroller,
|
|
2561
|
-
scrollIntoView
|
|
2896
|
+
scrollIntoView,
|
|
2897
|
+
logger
|
|
2562
2898
|
]) => {
|
|
2563
2899
|
return {
|
|
2564
2900
|
...sizeRange,
|
|
@@ -2569,7 +2905,8 @@ const featureGroup1System = system(
|
|
|
2569
2905
|
...initialScrollTopSystem2,
|
|
2570
2906
|
...alignToBottom,
|
|
2571
2907
|
...windowScroller,
|
|
2572
|
-
...scrollIntoView
|
|
2908
|
+
...scrollIntoView,
|
|
2909
|
+
...logger
|
|
2573
2910
|
};
|
|
2574
2911
|
},
|
|
2575
2912
|
tup(
|
|
@@ -2581,7 +2918,8 @@ const featureGroup1System = system(
|
|
|
2581
2918
|
initialScrollTopSystem,
|
|
2582
2919
|
alignToBottomSystem,
|
|
2583
2920
|
windowScrollerSystem,
|
|
2584
|
-
scrollIntoViewSystem
|
|
2921
|
+
scrollIntoViewSystem,
|
|
2922
|
+
loggerSystem
|
|
2585
2923
|
)
|
|
2586
2924
|
);
|
|
2587
2925
|
const listSystem = system(
|
|
@@ -2597,18 +2935,19 @@ const listSystem = system(
|
|
|
2597
2935
|
firstItemIndex,
|
|
2598
2936
|
groupIndices,
|
|
2599
2937
|
statefulTotalCount,
|
|
2600
|
-
gap
|
|
2938
|
+
gap,
|
|
2939
|
+
sizes
|
|
2601
2940
|
},
|
|
2602
|
-
{ initialTopMostItemIndex, scrolledToInitialItem },
|
|
2941
|
+
{ initialTopMostItemIndex, scrolledToInitialItem, initialItemFinalLocationReached },
|
|
2603
2942
|
domIO,
|
|
2943
|
+
stateLoad,
|
|
2604
2944
|
followOutput,
|
|
2605
2945
|
{ listState, topItemsIndexes, ...flags },
|
|
2606
2946
|
{ scrollToIndex },
|
|
2607
2947
|
_,
|
|
2608
2948
|
{ topItemCount },
|
|
2609
2949
|
{ groupCounts },
|
|
2610
|
-
featureGroup1
|
|
2611
|
-
log
|
|
2950
|
+
featureGroup1
|
|
2612
2951
|
]) => {
|
|
2613
2952
|
connect(flags.rangeChanged, featureGroup1.scrollSeekRangeChanged);
|
|
2614
2953
|
connect(
|
|
@@ -2619,12 +2958,14 @@ const listSystem = system(
|
|
|
2619
2958
|
domIO.viewportHeight
|
|
2620
2959
|
);
|
|
2621
2960
|
return {
|
|
2961
|
+
// input
|
|
2622
2962
|
totalCount,
|
|
2623
2963
|
data,
|
|
2624
2964
|
firstItemIndex,
|
|
2625
2965
|
sizeRanges,
|
|
2626
2966
|
initialTopMostItemIndex,
|
|
2627
2967
|
scrolledToInitialItem,
|
|
2968
|
+
initialItemFinalLocationReached,
|
|
2628
2969
|
topItemsIndexes,
|
|
2629
2970
|
topItemCount,
|
|
2630
2971
|
groupCounts,
|
|
@@ -2632,30 +2973,34 @@ const listSystem = system(
|
|
|
2632
2973
|
defaultItemHeight: defaultItemSize,
|
|
2633
2974
|
gap,
|
|
2634
2975
|
...followOutput,
|
|
2976
|
+
// output
|
|
2635
2977
|
statefulTotalCount,
|
|
2636
2978
|
listState,
|
|
2637
2979
|
scrollToIndex,
|
|
2638
2980
|
trackItemSizes,
|
|
2639
2981
|
itemSize,
|
|
2640
2982
|
groupIndices,
|
|
2983
|
+
// exported from stateFlagsSystem
|
|
2641
2984
|
...flags,
|
|
2985
|
+
// the bag of IO from featureGroup1System
|
|
2642
2986
|
...featureGroup1,
|
|
2643
2987
|
...domIO,
|
|
2644
|
-
|
|
2988
|
+
sizes,
|
|
2989
|
+
...stateLoad
|
|
2645
2990
|
};
|
|
2646
2991
|
},
|
|
2647
2992
|
tup(
|
|
2648
2993
|
sizeSystem,
|
|
2649
2994
|
initialTopMostItemIndexSystem,
|
|
2650
2995
|
domIOSystem,
|
|
2996
|
+
stateLoadSystem,
|
|
2651
2997
|
followOutputSystem,
|
|
2652
2998
|
listStateSystem,
|
|
2653
2999
|
scrollToIndexSystem,
|
|
2654
3000
|
upwardScrollFixSystem,
|
|
2655
3001
|
topItemCountSystem,
|
|
2656
3002
|
groupedListSystem,
|
|
2657
|
-
featureGroup1System
|
|
2658
|
-
loggerSystem
|
|
3003
|
+
featureGroup1System
|
|
2659
3004
|
)
|
|
2660
3005
|
);
|
|
2661
3006
|
const WEBKIT_STICKY = "-webkit-sticky";
|
|
@@ -2703,7 +3048,9 @@ function useWindowViewportRectRef(callback, customScrollParent) {
|
|
|
2703
3048
|
React.useEffect(() => {
|
|
2704
3049
|
if (customScrollParent) {
|
|
2705
3050
|
customScrollParent.addEventListener("scroll", scrollAndResizeEventHandler);
|
|
2706
|
-
const observer = new ResizeObserver(
|
|
3051
|
+
const observer = new ResizeObserver(() => {
|
|
3052
|
+
requestAnimationFrame(scrollAndResizeEventHandler);
|
|
3053
|
+
});
|
|
2707
3054
|
observer.observe(customScrollParent);
|
|
2708
3055
|
return () => {
|
|
2709
3056
|
customScrollParent.removeEventListener("scroll", scrollAndResizeEventHandler);
|
|
@@ -2767,7 +3114,8 @@ const combinedSystem$2 = /* @__PURE__ */ system(([listSystem2, propsSystem]) =>
|
|
|
2767
3114
|
}, tup(listSystem, listComponentPropsSystem));
|
|
2768
3115
|
const DefaultScrollSeekPlaceholder$1 = ({ height }) => /* @__PURE__ */ React.createElement("div", { style: { height } });
|
|
2769
3116
|
const GROUP_STYLE = { position: positionStickyCssValue(), zIndex: 1, overflowAnchor: "none" };
|
|
2770
|
-
const ITEM_STYLE = { overflowAnchor: "none" };
|
|
3117
|
+
const ITEM_STYLE$1 = { overflowAnchor: "none" };
|
|
3118
|
+
const HORIZONTAL_ITEM_STYLE = { ...ITEM_STYLE$1, display: "inline-block", height: "100%" };
|
|
2771
3119
|
const Items$1 = /* @__PURE__ */ React.memo(function VirtuosoItems({ showTopList = false }) {
|
|
2772
3120
|
const listState = useEmitterValue$2("listState");
|
|
2773
3121
|
const sizeRanges = usePublisher$2("sizeRanges");
|
|
@@ -2783,6 +3131,7 @@ const Items$1 = /* @__PURE__ */ React.memo(function VirtuosoItems({ showTopList
|
|
|
2783
3131
|
const itemSize = useEmitterValue$2("itemSize");
|
|
2784
3132
|
const log = useEmitterValue$2("log");
|
|
2785
3133
|
const listGap = usePublisher$2("gap");
|
|
3134
|
+
const horizontalDirection = useEmitterValue$2("horizontalDirection");
|
|
2786
3135
|
const { callbackRef } = useChangedListContentsSizes(
|
|
2787
3136
|
sizeRanges,
|
|
2788
3137
|
itemSize,
|
|
@@ -2790,7 +3139,8 @@ const Items$1 = /* @__PURE__ */ React.memo(function VirtuosoItems({ showTopList
|
|
|
2790
3139
|
showTopList ? noop : scrollContainerStateCallback,
|
|
2791
3140
|
log,
|
|
2792
3141
|
listGap,
|
|
2793
|
-
customScrollParent
|
|
3142
|
+
customScrollParent,
|
|
3143
|
+
horizontalDirection
|
|
2794
3144
|
);
|
|
2795
3145
|
const [deviation, setDeviation] = React.useState(0);
|
|
2796
3146
|
useEmitter$2("deviation", (value) => {
|
|
@@ -2806,12 +3156,23 @@ const Items$1 = /* @__PURE__ */ React.memo(function VirtuosoItems({ showTopList
|
|
|
2806
3156
|
const computeItemKey = useEmitterValue$2("computeItemKey");
|
|
2807
3157
|
const isSeeking = useEmitterValue$2("isSeeking");
|
|
2808
3158
|
const hasGroups2 = useEmitterValue$2("groupIndices").length > 0;
|
|
2809
|
-
const
|
|
3159
|
+
const alignToBottom = useEmitterValue$2("alignToBottom");
|
|
3160
|
+
const initialItemFinalLocationReached = useEmitterValue$2("initialItemFinalLocationReached");
|
|
2810
3161
|
const containerStyle = showTopList ? {} : {
|
|
2811
3162
|
boxSizing: "border-box",
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
3163
|
+
...horizontalDirection ? {
|
|
3164
|
+
whiteSpace: "nowrap",
|
|
3165
|
+
display: "inline-block",
|
|
3166
|
+
height: "100%",
|
|
3167
|
+
paddingLeft: listState.offsetTop,
|
|
3168
|
+
paddingRight: listState.offsetBottom,
|
|
3169
|
+
marginLeft: deviation !== 0 ? deviation : alignToBottom ? "auto" : 0
|
|
3170
|
+
} : {
|
|
3171
|
+
marginTop: deviation !== 0 ? deviation : alignToBottom ? "auto" : 0,
|
|
3172
|
+
paddingTop: listState.offsetTop,
|
|
3173
|
+
paddingBottom: listState.offsetBottom
|
|
3174
|
+
},
|
|
3175
|
+
...initialItemFinalLocationReached ? {} : { visibility: "hidden" }
|
|
2815
3176
|
};
|
|
2816
3177
|
if (!showTopList && listState.totalCount === 0 && EmptyPlaceholder) {
|
|
2817
3178
|
return React.createElement(EmptyPlaceholder, contextPropIfNotDomElement(EmptyPlaceholder, context));
|
|
@@ -2822,7 +3183,7 @@ const Items$1 = /* @__PURE__ */ React.memo(function VirtuosoItems({ showTopList
|
|
|
2822
3183
|
...contextPropIfNotDomElement(ListComponent, context),
|
|
2823
3184
|
ref: callbackRef,
|
|
2824
3185
|
style: containerStyle,
|
|
2825
|
-
"data-
|
|
3186
|
+
"data-testid": showTopList ? "virtuoso-top-item-list" : "virtuoso-item-list"
|
|
2826
3187
|
},
|
|
2827
3188
|
(showTopList ? listState.topItems : listState.items).map((item) => {
|
|
2828
3189
|
const index = item.originalIndex;
|
|
@@ -2848,20 +3209,20 @@ const Items$1 = /* @__PURE__ */ React.memo(function VirtuosoItems({ showTopList
|
|
|
2848
3209
|
"data-item-index": item.index,
|
|
2849
3210
|
style: GROUP_STYLE
|
|
2850
3211
|
},
|
|
2851
|
-
groupContent(item.index)
|
|
3212
|
+
groupContent(item.index, context)
|
|
2852
3213
|
);
|
|
2853
3214
|
} else {
|
|
2854
3215
|
return React.createElement(
|
|
2855
3216
|
ItemComponent,
|
|
2856
3217
|
{
|
|
2857
3218
|
...contextPropIfNotDomElement(ItemComponent, context),
|
|
3219
|
+
...itemPropIfNotDomElement(ItemComponent, item.data),
|
|
2858
3220
|
key,
|
|
2859
3221
|
"data-index": index,
|
|
2860
3222
|
"data-known-size": item.size,
|
|
2861
3223
|
"data-item-index": item.index,
|
|
2862
3224
|
"data-item-group-index": item.groupIndex,
|
|
2863
|
-
|
|
2864
|
-
style: ITEM_STYLE
|
|
3225
|
+
style: horizontalDirection ? HORIZONTAL_ITEM_STYLE : ITEM_STYLE$1
|
|
2865
3226
|
},
|
|
2866
3227
|
hasGroups2 ? itemContent(item.index, item.groupIndex, item.data, context) : itemContent(item.index, item.data, context)
|
|
2867
3228
|
);
|
|
@@ -2876,12 +3237,18 @@ const scrollerStyle = {
|
|
|
2876
3237
|
position: "relative",
|
|
2877
3238
|
WebkitOverflowScrolling: "touch"
|
|
2878
3239
|
};
|
|
2879
|
-
const
|
|
3240
|
+
const horizontalScrollerStyle = {
|
|
3241
|
+
outline: "none",
|
|
3242
|
+
overflowX: "auto",
|
|
3243
|
+
position: "relative"
|
|
3244
|
+
};
|
|
3245
|
+
const viewportStyle = (alignToBottom) => ({
|
|
2880
3246
|
width: "100%",
|
|
2881
3247
|
height: "100%",
|
|
2882
3248
|
position: "absolute",
|
|
2883
|
-
top: 0
|
|
2884
|
-
}
|
|
3249
|
+
top: 0,
|
|
3250
|
+
...alignToBottom ? { display: "flex", flexDirection: "column" } : {}
|
|
3251
|
+
});
|
|
2885
3252
|
const topItemListStyle = {
|
|
2886
3253
|
width: "100%",
|
|
2887
3254
|
position: positionStickyCssValue(),
|
|
@@ -2894,6 +3261,9 @@ function contextPropIfNotDomElement(element, context) {
|
|
|
2894
3261
|
}
|
|
2895
3262
|
return { context };
|
|
2896
3263
|
}
|
|
3264
|
+
function itemPropIfNotDomElement(element, item) {
|
|
3265
|
+
return { item: typeof element === "string" ? void 0 : item };
|
|
3266
|
+
}
|
|
2897
3267
|
const Header$1 = /* @__PURE__ */ React.memo(function VirtuosoHeader() {
|
|
2898
3268
|
const Header2 = useEmitterValue$2("HeaderComponent");
|
|
2899
3269
|
const headerHeight = usePublisher$2("headerHeight");
|
|
@@ -2917,20 +3287,24 @@ function buildScroller({ usePublisher: usePublisher2, useEmitter: useEmitter2, u
|
|
|
2917
3287
|
const smoothScrollTargetReached = usePublisher2("smoothScrollTargetReached");
|
|
2918
3288
|
const scrollerRefCallback = useEmitterValue2("scrollerRef");
|
|
2919
3289
|
const context = useEmitterValue2("context");
|
|
3290
|
+
const horizontalDirection = useEmitterValue2("horizontalDirection") || false;
|
|
2920
3291
|
const { scrollerRef, scrollByCallback, scrollToCallback } = useScrollTop(
|
|
2921
3292
|
scrollContainerStateCallback,
|
|
2922
3293
|
smoothScrollTargetReached,
|
|
2923
3294
|
ScrollerComponent,
|
|
2924
|
-
scrollerRefCallback
|
|
3295
|
+
scrollerRefCallback,
|
|
3296
|
+
void 0,
|
|
3297
|
+
horizontalDirection
|
|
2925
3298
|
);
|
|
2926
3299
|
useEmitter2("scrollTo", scrollToCallback);
|
|
2927
3300
|
useEmitter2("scrollBy", scrollByCallback);
|
|
3301
|
+
const defaultStyle = horizontalDirection ? horizontalScrollerStyle : scrollerStyle;
|
|
2928
3302
|
return React.createElement(
|
|
2929
3303
|
ScrollerComponent,
|
|
2930
3304
|
{
|
|
2931
3305
|
ref: scrollerRef,
|
|
2932
|
-
style: { ...
|
|
2933
|
-
"data-
|
|
3306
|
+
style: { ...defaultStyle, ...style },
|
|
3307
|
+
"data-testid": "virtuoso-scroller",
|
|
2934
3308
|
"data-virtuoso-scroller": true,
|
|
2935
3309
|
tabIndex: 0,
|
|
2936
3310
|
...props,
|
|
@@ -2982,14 +3356,16 @@ const Viewport$2 = ({ children }) => {
|
|
|
2982
3356
|
const ctx = React.useContext(VirtuosoMockContext);
|
|
2983
3357
|
const viewportHeight = usePublisher$2("viewportHeight");
|
|
2984
3358
|
const fixedItemHeight = usePublisher$2("fixedItemHeight");
|
|
2985
|
-
const
|
|
3359
|
+
const alignToBottom = useEmitterValue$2("alignToBottom");
|
|
3360
|
+
const horizontalDirection = useEmitterValue$2("horizontalDirection");
|
|
3361
|
+
const viewportRef = useSize(compose(viewportHeight, (el) => correctItemSize(el, horizontalDirection ? "width" : "height")));
|
|
2986
3362
|
React.useEffect(() => {
|
|
2987
3363
|
if (ctx) {
|
|
2988
3364
|
viewportHeight(ctx.viewportHeight);
|
|
2989
3365
|
fixedItemHeight(ctx.itemHeight);
|
|
2990
3366
|
}
|
|
2991
3367
|
}, [ctx, viewportHeight, fixedItemHeight]);
|
|
2992
|
-
return /* @__PURE__ */ React.createElement("div", { style: viewportStyle, ref: viewportRef, "data-viewport-type": "element" }, children);
|
|
3368
|
+
return /* @__PURE__ */ React.createElement("div", { style: viewportStyle(alignToBottom), ref: viewportRef, "data-viewport-type": "element" }, children);
|
|
2993
3369
|
};
|
|
2994
3370
|
const WindowViewport$2 = ({ children }) => {
|
|
2995
3371
|
const ctx = React.useContext(VirtuosoMockContext);
|
|
@@ -2997,20 +3373,21 @@ const WindowViewport$2 = ({ children }) => {
|
|
|
2997
3373
|
const fixedItemHeight = usePublisher$2("fixedItemHeight");
|
|
2998
3374
|
const customScrollParent = useEmitterValue$2("customScrollParent");
|
|
2999
3375
|
const viewportRef = useWindowViewportRectRef(windowViewportRect, customScrollParent);
|
|
3376
|
+
const alignToBottom = useEmitterValue$2("alignToBottom");
|
|
3000
3377
|
React.useEffect(() => {
|
|
3001
3378
|
if (ctx) {
|
|
3002
3379
|
fixedItemHeight(ctx.itemHeight);
|
|
3003
3380
|
windowViewportRect({ offsetTop: 0, visibleHeight: ctx.viewportHeight, visibleWidth: 100 });
|
|
3004
3381
|
}
|
|
3005
3382
|
}, [ctx, windowViewportRect, fixedItemHeight]);
|
|
3006
|
-
return /* @__PURE__ */ React.createElement("div", { ref: viewportRef, style: viewportStyle, "data-viewport-type": "window" }, children);
|
|
3383
|
+
return /* @__PURE__ */ React.createElement("div", { ref: viewportRef, style: viewportStyle(alignToBottom), "data-viewport-type": "window" }, children);
|
|
3007
3384
|
};
|
|
3008
3385
|
const TopItemListContainer = ({ children }) => {
|
|
3009
|
-
const TopItemList = useEmitterValue$2("TopItemListComponent");
|
|
3386
|
+
const TopItemList = useEmitterValue$2("TopItemListComponent") || "div";
|
|
3010
3387
|
const headerHeight = useEmitterValue$2("headerHeight");
|
|
3011
3388
|
const style = { ...topItemListStyle, marginTop: `${headerHeight}px` };
|
|
3012
3389
|
const context = useEmitterValue$2("context");
|
|
3013
|
-
return React.createElement(TopItemList
|
|
3390
|
+
return React.createElement(TopItemList, { style, ...contextPropIfNotDomElement(TopItemList, context) }, children);
|
|
3014
3391
|
};
|
|
3015
3392
|
const ListRoot = /* @__PURE__ */ React.memo(function VirtuosoRoot(props) {
|
|
3016
3393
|
const useWindowScroll = useEmitterValue$2("useWindowScroll");
|
|
@@ -3030,18 +3407,19 @@ const {
|
|
|
3030
3407
|
{
|
|
3031
3408
|
required: {},
|
|
3032
3409
|
optional: {
|
|
3410
|
+
restoreStateFrom: "restoreStateFrom",
|
|
3033
3411
|
context: "context",
|
|
3034
3412
|
followOutput: "followOutput",
|
|
3035
|
-
firstItemIndex: "firstItemIndex",
|
|
3036
3413
|
itemContent: "itemContent",
|
|
3037
3414
|
groupContent: "groupContent",
|
|
3038
3415
|
overscan: "overscan",
|
|
3039
3416
|
increaseViewportBy: "increaseViewportBy",
|
|
3040
3417
|
totalCount: "totalCount",
|
|
3418
|
+
groupCounts: "groupCounts",
|
|
3041
3419
|
topItemCount: "topItemCount",
|
|
3420
|
+
firstItemIndex: "firstItemIndex",
|
|
3042
3421
|
initialTopMostItemIndex: "initialTopMostItemIndex",
|
|
3043
3422
|
components: "components",
|
|
3044
|
-
groupCounts: "groupCounts",
|
|
3045
3423
|
atBottomThreshold: "atBottomThreshold",
|
|
3046
3424
|
atTopThreshold: "atTopThreshold",
|
|
3047
3425
|
computeItemKey: "computeItemKey",
|
|
@@ -3057,14 +3435,16 @@ const {
|
|
|
3057
3435
|
useWindowScroll: "useWindowScroll",
|
|
3058
3436
|
customScrollParent: "customScrollParent",
|
|
3059
3437
|
scrollerRef: "scrollerRef",
|
|
3060
|
-
logLevel: "logLevel"
|
|
3438
|
+
logLevel: "logLevel",
|
|
3439
|
+
horizontalDirection: "horizontalDirection"
|
|
3061
3440
|
},
|
|
3062
3441
|
methods: {
|
|
3063
3442
|
scrollToIndex: "scrollToIndex",
|
|
3064
3443
|
scrollIntoView: "scrollIntoView",
|
|
3065
3444
|
scrollTo: "scrollTo",
|
|
3066
3445
|
scrollBy: "scrollBy",
|
|
3067
|
-
autoscrollToBottom: "autoscrollToBottom"
|
|
3446
|
+
autoscrollToBottom: "autoscrollToBottom",
|
|
3447
|
+
getState: "getState"
|
|
3068
3448
|
},
|
|
3069
3449
|
events: {
|
|
3070
3450
|
isScrolling: "isScrolling",
|
|
@@ -3110,13 +3490,17 @@ function buildProbeGridState(items) {
|
|
|
3110
3490
|
};
|
|
3111
3491
|
}
|
|
3112
3492
|
function buildItems(startIndex, endIndex, data) {
|
|
3113
|
-
return Array.from({ length: endIndex - startIndex + 1 }).map(
|
|
3114
|
-
|
|
3115
|
-
|
|
3493
|
+
return Array.from({ length: endIndex - startIndex + 1 }).map((_, i) => {
|
|
3494
|
+
const dataItem = data === null ? null : data[i + startIndex];
|
|
3495
|
+
return { index: i + startIndex, data: dataItem };
|
|
3496
|
+
});
|
|
3116
3497
|
}
|
|
3117
3498
|
function gapComparator(prev, next) {
|
|
3118
3499
|
return prev && prev.column === next.column && prev.row === next.row;
|
|
3119
3500
|
}
|
|
3501
|
+
function dimensionComparator(prev, next) {
|
|
3502
|
+
return prev && prev.width === next.width && prev.height === next.height;
|
|
3503
|
+
}
|
|
3120
3504
|
const gridSystem = /* @__PURE__ */ system(
|
|
3121
3505
|
([
|
|
3122
3506
|
{ overscan, visibleRange, listBoundary },
|
|
@@ -3124,7 +3508,7 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3124
3508
|
stateFlags,
|
|
3125
3509
|
scrollSeek,
|
|
3126
3510
|
{ propsReady, didMount },
|
|
3127
|
-
{ windowViewportRect,
|
|
3511
|
+
{ windowViewportRect, useWindowScroll, customScrollParent, windowScrollContainerState, windowScrollTo },
|
|
3128
3512
|
log
|
|
3129
3513
|
]) => {
|
|
3130
3514
|
const totalCount = statefulStream(0);
|
|
@@ -3135,25 +3519,96 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3135
3519
|
const scrollToIndex = stream();
|
|
3136
3520
|
const scrollHeight = stream();
|
|
3137
3521
|
const deviation = statefulStream(0);
|
|
3138
|
-
const data = statefulStream(
|
|
3522
|
+
const data = statefulStream(null);
|
|
3139
3523
|
const gap = statefulStream({ row: 0, column: 0 });
|
|
3140
|
-
|
|
3524
|
+
const stateChanged = stream();
|
|
3525
|
+
const restoreStateFrom = stream();
|
|
3526
|
+
const stateRestoreInProgress = statefulStream(false);
|
|
3527
|
+
const initialTopMostItemIndex = statefulStream(0);
|
|
3528
|
+
const scrolledToInitialItem = statefulStream(true);
|
|
3529
|
+
const scrollScheduled = statefulStream(false);
|
|
3530
|
+
const horizontalDirection = statefulStream(false);
|
|
3531
|
+
subscribe(
|
|
3141
3532
|
pipe(
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3533
|
+
didMount,
|
|
3534
|
+
withLatestFrom(initialTopMostItemIndex),
|
|
3535
|
+
filter(([_, location]) => !!location)
|
|
3536
|
+
),
|
|
3537
|
+
() => {
|
|
3538
|
+
publish(scrolledToInitialItem, false);
|
|
3539
|
+
publish(initialItemCount, 0);
|
|
3540
|
+
}
|
|
3541
|
+
);
|
|
3542
|
+
subscribe(
|
|
3543
|
+
pipe(
|
|
3544
|
+
combineLatest(didMount, scrolledToInitialItem, itemDimensions, viewportDimensions, initialTopMostItemIndex, scrollScheduled),
|
|
3545
|
+
filter(([didMount2, scrolledToInitialItem2, itemDimensions2, viewportDimensions2, , scrollScheduled2]) => {
|
|
3546
|
+
return didMount2 && !scrolledToInitialItem2 && itemDimensions2.height !== 0 && viewportDimensions2.height !== 0 && !scrollScheduled2;
|
|
3154
3547
|
})
|
|
3155
3548
|
),
|
|
3156
|
-
|
|
3549
|
+
([, , , , initialTopMostItemIndex2]) => {
|
|
3550
|
+
publish(scrollScheduled, true);
|
|
3551
|
+
skipFrames(1, () => {
|
|
3552
|
+
publish(scrollToIndex, initialTopMostItemIndex2);
|
|
3553
|
+
});
|
|
3554
|
+
handleNext(pipe(scrollTop), () => {
|
|
3555
|
+
publish(listBoundary, [0, 0]);
|
|
3556
|
+
publish(scrolledToInitialItem, true);
|
|
3557
|
+
});
|
|
3558
|
+
}
|
|
3559
|
+
);
|
|
3560
|
+
connect(
|
|
3561
|
+
pipe(
|
|
3562
|
+
restoreStateFrom,
|
|
3563
|
+
filter((value) => value !== void 0 && value !== null && value.scrollTop > 0),
|
|
3564
|
+
mapTo(0)
|
|
3565
|
+
),
|
|
3566
|
+
initialItemCount
|
|
3567
|
+
);
|
|
3568
|
+
subscribe(
|
|
3569
|
+
pipe(
|
|
3570
|
+
didMount,
|
|
3571
|
+
withLatestFrom(restoreStateFrom),
|
|
3572
|
+
filter(([, snapshot]) => snapshot !== void 0 && snapshot !== null)
|
|
3573
|
+
),
|
|
3574
|
+
([, snapshot]) => {
|
|
3575
|
+
if (!snapshot) {
|
|
3576
|
+
return;
|
|
3577
|
+
}
|
|
3578
|
+
publish(viewportDimensions, snapshot.viewport), publish(itemDimensions, snapshot == null ? void 0 : snapshot.item);
|
|
3579
|
+
publish(gap, snapshot.gap);
|
|
3580
|
+
if (snapshot.scrollTop > 0) {
|
|
3581
|
+
publish(stateRestoreInProgress, true);
|
|
3582
|
+
handleNext(pipe(scrollTop, skip(1)), (_value) => {
|
|
3583
|
+
publish(stateRestoreInProgress, false);
|
|
3584
|
+
});
|
|
3585
|
+
publish(scrollTo, { top: snapshot.scrollTop });
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
);
|
|
3589
|
+
connect(
|
|
3590
|
+
pipe(
|
|
3591
|
+
viewportDimensions,
|
|
3592
|
+
map(({ height }) => height)
|
|
3593
|
+
),
|
|
3594
|
+
viewportHeight
|
|
3595
|
+
);
|
|
3596
|
+
connect(
|
|
3597
|
+
pipe(
|
|
3598
|
+
combineLatest(
|
|
3599
|
+
duc(viewportDimensions, dimensionComparator),
|
|
3600
|
+
duc(itemDimensions, dimensionComparator),
|
|
3601
|
+
duc(gap, (prev, next) => prev && prev.column === next.column && prev.row === next.row),
|
|
3602
|
+
duc(scrollTop)
|
|
3603
|
+
),
|
|
3604
|
+
map(([viewport, item, gap2, scrollTop2]) => ({
|
|
3605
|
+
viewport,
|
|
3606
|
+
item,
|
|
3607
|
+
gap: gap2,
|
|
3608
|
+
scrollTop: scrollTop2
|
|
3609
|
+
}))
|
|
3610
|
+
),
|
|
3611
|
+
stateChanged
|
|
3157
3612
|
);
|
|
3158
3613
|
connect(
|
|
3159
3614
|
pipe(
|
|
@@ -3161,67 +3616,106 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3161
3616
|
duc(totalCount),
|
|
3162
3617
|
visibleRange,
|
|
3163
3618
|
duc(gap, gapComparator),
|
|
3164
|
-
duc(itemDimensions,
|
|
3165
|
-
|
|
3619
|
+
duc(itemDimensions, dimensionComparator),
|
|
3620
|
+
duc(viewportDimensions, dimensionComparator),
|
|
3621
|
+
duc(data),
|
|
3622
|
+
duc(initialItemCount),
|
|
3623
|
+
duc(stateRestoreInProgress),
|
|
3624
|
+
duc(scrolledToInitialItem),
|
|
3625
|
+
duc(initialTopMostItemIndex)
|
|
3166
3626
|
),
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3627
|
+
filter(([, , , , , , , stateRestoreInProgress2]) => {
|
|
3628
|
+
return !stateRestoreInProgress2;
|
|
3629
|
+
}),
|
|
3630
|
+
map(
|
|
3631
|
+
([
|
|
3632
|
+
totalCount2,
|
|
3633
|
+
[startOffset, endOffset],
|
|
3634
|
+
gap2,
|
|
3635
|
+
item,
|
|
3636
|
+
viewport,
|
|
3637
|
+
data2,
|
|
3638
|
+
initialItemCount2,
|
|
3639
|
+
,
|
|
3640
|
+
scrolledToInitialItem2,
|
|
3641
|
+
initialTopMostItemIndex2
|
|
3642
|
+
]) => {
|
|
3643
|
+
const { row: rowGap, column: columnGap } = gap2;
|
|
3644
|
+
const { height: itemHeight, width: itemWidth } = item;
|
|
3645
|
+
const { width: viewportWidth } = viewport;
|
|
3646
|
+
if (initialItemCount2 === 0 && (totalCount2 === 0 || viewportWidth === 0)) {
|
|
3647
|
+
return INITIAL_GRID_STATE;
|
|
3648
|
+
}
|
|
3649
|
+
if (itemWidth === 0) {
|
|
3650
|
+
const startIndex2 = getInitialTopMostItemIndexNumber(initialTopMostItemIndex2, totalCount2);
|
|
3651
|
+
const endIndex2 = startIndex2 === 0 ? Math.max(initialItemCount2 - 1, 0) : startIndex2;
|
|
3652
|
+
return buildProbeGridState(buildItems(startIndex2, endIndex2, data2));
|
|
3653
|
+
}
|
|
3654
|
+
const perRow = itemsPerRow(viewportWidth, itemWidth, columnGap);
|
|
3655
|
+
let startIndex;
|
|
3656
|
+
let endIndex;
|
|
3657
|
+
if (!scrolledToInitialItem2) {
|
|
3658
|
+
startIndex = 0;
|
|
3659
|
+
endIndex = -1;
|
|
3660
|
+
} else if (startOffset === 0 && endOffset === 0 && initialItemCount2 > 0) {
|
|
3661
|
+
startIndex = 0;
|
|
3662
|
+
endIndex = initialItemCount2 - 1;
|
|
3663
|
+
} else {
|
|
3664
|
+
startIndex = perRow * floor((startOffset + rowGap) / (itemHeight + rowGap));
|
|
3665
|
+
endIndex = perRow * ceil((endOffset + rowGap) / (itemHeight + rowGap)) - 1;
|
|
3666
|
+
endIndex = min(totalCount2 - 1, max(endIndex, perRow - 1));
|
|
3667
|
+
startIndex = min(endIndex, max(0, startIndex));
|
|
3668
|
+
}
|
|
3669
|
+
const items = buildItems(startIndex, endIndex, data2);
|
|
3670
|
+
const { top, bottom } = gridLayout(viewport, gap2, item, items);
|
|
3671
|
+
const rowCount = ceil(totalCount2 / perRow);
|
|
3672
|
+
const totalHeight = rowCount * itemHeight + (rowCount - 1) * rowGap;
|
|
3673
|
+
const offsetBottom = totalHeight - bottom;
|
|
3674
|
+
return { items, offsetTop: top, offsetBottom, top, bottom, itemHeight, itemWidth };
|
|
3177
3675
|
}
|
|
3178
|
-
|
|
3179
|
-
let startIndex = perRow * floor((startOffset + rowGap) / (itemHeight + rowGap));
|
|
3180
|
-
let endIndex = perRow * ceil((endOffset + rowGap) / (itemHeight + rowGap)) - 1;
|
|
3181
|
-
endIndex = min(totalCount2 - 1, max(endIndex, perRow - 1));
|
|
3182
|
-
startIndex = min(endIndex, max(0, startIndex));
|
|
3183
|
-
const items = buildItems(startIndex, endIndex, data2);
|
|
3184
|
-
const { top, bottom } = gridLayout(viewport, gap2, item, items);
|
|
3185
|
-
const rowCount = ceil(totalCount2 / perRow);
|
|
3186
|
-
const totalHeight = rowCount * itemHeight + (rowCount - 1) * rowGap;
|
|
3187
|
-
const offsetBottom = totalHeight - bottom;
|
|
3188
|
-
return { items, offsetTop: top, offsetBottom, top, bottom, itemHeight, itemWidth };
|
|
3189
|
-
})
|
|
3676
|
+
)
|
|
3190
3677
|
),
|
|
3191
3678
|
gridState
|
|
3192
3679
|
);
|
|
3193
3680
|
connect(
|
|
3194
3681
|
pipe(
|
|
3195
3682
|
data,
|
|
3196
|
-
filter((data2) => data2 !==
|
|
3683
|
+
filter((data2) => data2 !== null),
|
|
3197
3684
|
map((data2) => data2.length)
|
|
3198
3685
|
),
|
|
3199
3686
|
totalCount
|
|
3200
3687
|
);
|
|
3201
|
-
connect(
|
|
3202
|
-
pipe(
|
|
3203
|
-
viewportDimensions,
|
|
3204
|
-
map(({ height }) => height)
|
|
3205
|
-
),
|
|
3206
|
-
viewportHeight
|
|
3207
|
-
);
|
|
3208
3688
|
connect(
|
|
3209
3689
|
pipe(
|
|
3210
3690
|
combineLatest(viewportDimensions, itemDimensions, gridState, gap),
|
|
3211
|
-
|
|
3212
|
-
|
|
3691
|
+
filter(([viewportDimensions2, itemDimensions2, { items }]) => {
|
|
3692
|
+
return items.length > 0 && itemDimensions2.height !== 0 && viewportDimensions2.height !== 0;
|
|
3693
|
+
}),
|
|
3694
|
+
map(([viewportDimensions2, itemDimensions2, { items }, gap2]) => {
|
|
3695
|
+
const { top, bottom } = gridLayout(viewportDimensions2, gap2, itemDimensions2, items);
|
|
3213
3696
|
return [top, bottom];
|
|
3214
3697
|
}),
|
|
3215
3698
|
distinctUntilChanged(tupleComparator)
|
|
3216
3699
|
),
|
|
3217
3700
|
listBoundary
|
|
3218
3701
|
);
|
|
3702
|
+
const hasScrolled = statefulStream(false);
|
|
3703
|
+
connect(
|
|
3704
|
+
pipe(
|
|
3705
|
+
scrollTop,
|
|
3706
|
+
withLatestFrom(hasScrolled),
|
|
3707
|
+
map(([scrollTop2, hasScrolled2]) => {
|
|
3708
|
+
return hasScrolled2 || scrollTop2 !== 0;
|
|
3709
|
+
})
|
|
3710
|
+
),
|
|
3711
|
+
hasScrolled
|
|
3712
|
+
);
|
|
3219
3713
|
const endReached = streamFromEmitter(
|
|
3220
3714
|
pipe(
|
|
3221
3715
|
duc(gridState),
|
|
3222
3716
|
filter(({ items }) => items.length > 0),
|
|
3223
|
-
withLatestFrom(totalCount),
|
|
3224
|
-
filter(([{ items }, totalCount2]) => items[items.length - 1].index === totalCount2 - 1),
|
|
3717
|
+
withLatestFrom(totalCount, hasScrolled),
|
|
3718
|
+
filter(([{ items }, totalCount2, hasScrolled2]) => hasScrolled2 && items[items.length - 1].index === totalCount2 - 1),
|
|
3225
3719
|
map(([, totalCount2]) => totalCount2 - 1),
|
|
3226
3720
|
distinctUntilChanged()
|
|
3227
3721
|
)
|
|
@@ -3232,6 +3726,7 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3232
3726
|
filter(({ items }) => {
|
|
3233
3727
|
return items.length > 0 && items[0].index === 0;
|
|
3234
3728
|
}),
|
|
3729
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
3235
3730
|
mapTo(0),
|
|
3236
3731
|
distinctUntilChanged()
|
|
3237
3732
|
)
|
|
@@ -3239,14 +3734,16 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3239
3734
|
const rangeChanged = streamFromEmitter(
|
|
3240
3735
|
pipe(
|
|
3241
3736
|
duc(gridState),
|
|
3242
|
-
|
|
3243
|
-
|
|
3737
|
+
withLatestFrom(stateRestoreInProgress),
|
|
3738
|
+
filter(([{ items }, stateRestoreInProgress2]) => items.length > 0 && !stateRestoreInProgress2),
|
|
3739
|
+
map(([{ items }]) => {
|
|
3244
3740
|
return {
|
|
3245
3741
|
startIndex: items[0].index,
|
|
3246
3742
|
endIndex: items[items.length - 1].index
|
|
3247
3743
|
};
|
|
3248
3744
|
}),
|
|
3249
|
-
distinctUntilChanged(rangeComparator)
|
|
3745
|
+
distinctUntilChanged(rangeComparator),
|
|
3746
|
+
throttleTime(0)
|
|
3250
3747
|
)
|
|
3251
3748
|
);
|
|
3252
3749
|
connect(rangeChanged, scrollSeek.scrollSeekRangeChanged);
|
|
@@ -3254,7 +3751,7 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3254
3751
|
pipe(
|
|
3255
3752
|
scrollToIndex,
|
|
3256
3753
|
withLatestFrom(viewportDimensions, itemDimensions, totalCount, gap),
|
|
3257
|
-
map(([location,
|
|
3754
|
+
map(([location, viewportDimensions2, itemDimensions2, totalCount2, gap2]) => {
|
|
3258
3755
|
const normalLocation = normalizeIndexLocation(location);
|
|
3259
3756
|
const { align, behavior, offset } = normalLocation;
|
|
3260
3757
|
let index = normalLocation.index;
|
|
@@ -3262,11 +3759,11 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3262
3759
|
index = totalCount2 - 1;
|
|
3263
3760
|
}
|
|
3264
3761
|
index = max(0, index, min(totalCount2 - 1, index));
|
|
3265
|
-
let top = itemTop(
|
|
3762
|
+
let top = itemTop(viewportDimensions2, gap2, itemDimensions2, index);
|
|
3266
3763
|
if (align === "end") {
|
|
3267
|
-
top = round(top -
|
|
3764
|
+
top = round(top - viewportDimensions2.height + itemDimensions2.height);
|
|
3268
3765
|
} else if (align === "center") {
|
|
3269
|
-
top = round(top -
|
|
3766
|
+
top = round(top - viewportDimensions2.height / 2 + itemDimensions2.height / 2);
|
|
3270
3767
|
}
|
|
3271
3768
|
if (offset) {
|
|
3272
3769
|
top += offset;
|
|
@@ -3293,6 +3790,7 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3293
3790
|
viewportDimensions
|
|
3294
3791
|
);
|
|
3295
3792
|
return {
|
|
3793
|
+
// input
|
|
3296
3794
|
data,
|
|
3297
3795
|
totalCount,
|
|
3298
3796
|
viewportDimensions,
|
|
@@ -3315,14 +3813,20 @@ const gridSystem = /* @__PURE__ */ system(
|
|
|
3315
3813
|
headerHeight,
|
|
3316
3814
|
initialItemCount,
|
|
3317
3815
|
gap,
|
|
3816
|
+
restoreStateFrom,
|
|
3318
3817
|
...scrollSeek,
|
|
3818
|
+
initialTopMostItemIndex,
|
|
3819
|
+
horizontalDirection,
|
|
3820
|
+
// output
|
|
3319
3821
|
gridState,
|
|
3320
3822
|
totalListHeight,
|
|
3321
3823
|
...stateFlags,
|
|
3322
3824
|
startReached,
|
|
3323
3825
|
endReached,
|
|
3324
3826
|
rangeChanged,
|
|
3827
|
+
stateChanged,
|
|
3325
3828
|
propsReady,
|
|
3829
|
+
stateRestoreInProgress,
|
|
3326
3830
|
...log
|
|
3327
3831
|
};
|
|
3328
3832
|
},
|
|
@@ -3344,7 +3848,7 @@ function itemTop(viewport, gap, item, index) {
|
|
|
3344
3848
|
return top > 0 ? top + gap.row : top;
|
|
3345
3849
|
}
|
|
3346
3850
|
function itemsPerRow(viewportWidth, itemWidth, gap) {
|
|
3347
|
-
return max(1, floor((viewportWidth + gap) / (itemWidth + gap)));
|
|
3851
|
+
return max(1, floor((viewportWidth + gap) / (floor(itemWidth) + gap)));
|
|
3348
3852
|
}
|
|
3349
3853
|
const gridComponentPropsSystem = /* @__PURE__ */ system(() => {
|
|
3350
3854
|
const itemContent = statefulStream((index) => `Item ${index}`);
|
|
@@ -3400,18 +3904,23 @@ const GridItems = /* @__PURE__ */ React.memo(function GridItems2() {
|
|
|
3400
3904
|
const itemDimensions = usePublisher$1("itemDimensions");
|
|
3401
3905
|
const gridGap = usePublisher$1("gap");
|
|
3402
3906
|
const log = useEmitterValue$1("log");
|
|
3907
|
+
const stateRestoreInProgress = useEmitterValue$1("stateRestoreInProgress");
|
|
3403
3908
|
const listRef = useSize((el) => {
|
|
3404
3909
|
const scrollHeight = el.parentElement.parentElement.scrollHeight;
|
|
3405
3910
|
scrollHeightCallback(scrollHeight);
|
|
3406
3911
|
const firstItem = el.firstChild;
|
|
3407
3912
|
if (firstItem) {
|
|
3408
|
-
|
|
3913
|
+
const { width, height } = firstItem.getBoundingClientRect();
|
|
3914
|
+
itemDimensions({ width, height });
|
|
3409
3915
|
}
|
|
3410
3916
|
gridGap({
|
|
3411
3917
|
row: resolveGapValue("row-gap", getComputedStyle(el).rowGap, log),
|
|
3412
3918
|
column: resolveGapValue("column-gap", getComputedStyle(el).columnGap, log)
|
|
3413
3919
|
});
|
|
3414
3920
|
});
|
|
3921
|
+
if (stateRestoreInProgress) {
|
|
3922
|
+
return null;
|
|
3923
|
+
}
|
|
3415
3924
|
return React.createElement(
|
|
3416
3925
|
ListComponent,
|
|
3417
3926
|
{
|
|
@@ -3419,7 +3928,7 @@ const GridItems = /* @__PURE__ */ React.memo(function GridItems2() {
|
|
|
3419
3928
|
className: listClassName,
|
|
3420
3929
|
...contextPropIfNotDomElement(ListComponent, context),
|
|
3421
3930
|
style: { paddingTop: gridState.offsetTop, paddingBottom: gridState.offsetBottom },
|
|
3422
|
-
"data-
|
|
3931
|
+
"data-testid": "virtuoso-item-list"
|
|
3423
3932
|
},
|
|
3424
3933
|
gridState.items.map((item) => {
|
|
3425
3934
|
const key = computeItemKey(item.index, item.data, context);
|
|
@@ -3466,7 +3975,7 @@ const Viewport$1 = ({ children }) => {
|
|
|
3466
3975
|
itemDimensions({ height: ctx.itemHeight, width: ctx.itemWidth });
|
|
3467
3976
|
}
|
|
3468
3977
|
}, [ctx, viewportDimensions, itemDimensions]);
|
|
3469
|
-
return /* @__PURE__ */ React.createElement("div", { style: viewportStyle, ref: viewportRef }, children);
|
|
3978
|
+
return /* @__PURE__ */ React.createElement("div", { style: viewportStyle(false), ref: viewportRef }, children);
|
|
3470
3979
|
};
|
|
3471
3980
|
const WindowViewport$1 = ({ children }) => {
|
|
3472
3981
|
const ctx = React.useContext(VirtuosoGridMockContext);
|
|
@@ -3480,7 +3989,7 @@ const WindowViewport$1 = ({ children }) => {
|
|
|
3480
3989
|
windowViewportRect({ offsetTop: 0, visibleHeight: ctx.viewportHeight, visibleWidth: ctx.viewportWidth });
|
|
3481
3990
|
}
|
|
3482
3991
|
}, [ctx, windowViewportRect, itemDimensions]);
|
|
3483
|
-
return /* @__PURE__ */ React.createElement("div", { ref: viewportRef, style: viewportStyle }, children);
|
|
3992
|
+
return /* @__PURE__ */ React.createElement("div", { ref: viewportRef, style: viewportStyle(false) }, children);
|
|
3484
3993
|
};
|
|
3485
3994
|
const GridRoot = /* @__PURE__ */ React.memo(function GridRoot2({ ...props }) {
|
|
3486
3995
|
const useWindowScroll = useEmitterValue$1("useWindowScroll");
|
|
@@ -3512,7 +4021,10 @@ const {
|
|
|
3512
4021
|
itemClassName: "itemClassName",
|
|
3513
4022
|
useWindowScroll: "useWindowScroll",
|
|
3514
4023
|
customScrollParent: "customScrollParent",
|
|
3515
|
-
scrollerRef: "scrollerRef"
|
|
4024
|
+
scrollerRef: "scrollerRef",
|
|
4025
|
+
logLevel: "logLevel",
|
|
4026
|
+
restoreStateFrom: "restoreStateFrom",
|
|
4027
|
+
initialTopMostItemIndex: "initialTopMostItemIndex"
|
|
3516
4028
|
},
|
|
3517
4029
|
methods: {
|
|
3518
4030
|
scrollTo: "scrollTo",
|
|
@@ -3525,7 +4037,8 @@ const {
|
|
|
3525
4037
|
startReached: "startReached",
|
|
3526
4038
|
rangeChanged: "rangeChanged",
|
|
3527
4039
|
atBottomStateChange: "atBottomStateChange",
|
|
3528
|
-
atTopStateChange: "atTopStateChange"
|
|
4040
|
+
atTopStateChange: "atTopStateChange",
|
|
4041
|
+
stateChanged: "stateChanged"
|
|
3529
4042
|
}
|
|
3530
4043
|
},
|
|
3531
4044
|
GridRoot
|
|
@@ -3539,7 +4052,7 @@ function resolveGapValue(property, value, log) {
|
|
|
3539
4052
|
if (value === "normal") {
|
|
3540
4053
|
return 0;
|
|
3541
4054
|
}
|
|
3542
|
-
return parseInt(value
|
|
4055
|
+
return parseInt(value != null ? value : "0", 10);
|
|
3543
4056
|
}
|
|
3544
4057
|
const VirtuosoGrid = Grid;
|
|
3545
4058
|
const tableComponentPropsSystem = /* @__PURE__ */ system(() => {
|
|
@@ -3584,6 +4097,7 @@ const combinedSystem = /* @__PURE__ */ system(([listSystem2, propsSystem]) => {
|
|
|
3584
4097
|
}, tup(listSystem, tableComponentPropsSystem));
|
|
3585
4098
|
const DefaultScrollSeekPlaceholder = ({ height }) => /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("td", { style: { height } }));
|
|
3586
4099
|
const DefaultFillerRow = ({ height }) => /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("td", { style: { height, padding: 0, border: 0 } }));
|
|
4100
|
+
const ITEM_STYLE = { overflowAnchor: "none" };
|
|
3587
4101
|
const Items = /* @__PURE__ */ React.memo(function VirtuosoItems2() {
|
|
3588
4102
|
const listState = useEmitterValue("listState");
|
|
3589
4103
|
const sizeRanges = usePublisher("sizeRanges");
|
|
@@ -3646,19 +4160,19 @@ const Items = /* @__PURE__ */ React.memo(function VirtuosoItems2() {
|
|
|
3646
4160
|
TableRowComponent,
|
|
3647
4161
|
{
|
|
3648
4162
|
...contextPropIfNotDomElement(TableRowComponent, context),
|
|
4163
|
+
...itemPropIfNotDomElement(TableRowComponent, item.data),
|
|
3649
4164
|
key,
|
|
3650
4165
|
"data-index": index,
|
|
3651
4166
|
"data-known-size": item.size,
|
|
3652
4167
|
"data-item-index": item.index,
|
|
3653
|
-
|
|
3654
|
-
style: { overflowAnchor: "none" }
|
|
4168
|
+
style: ITEM_STYLE
|
|
3655
4169
|
},
|
|
3656
4170
|
itemContent(item.index, item.data, context)
|
|
3657
4171
|
);
|
|
3658
4172
|
});
|
|
3659
4173
|
return React.createElement(
|
|
3660
4174
|
TableBodyComponent,
|
|
3661
|
-
{ ref: callbackRef, "data-
|
|
4175
|
+
{ ref: callbackRef, "data-testid": "virtuoso-item-list", ...contextPropIfNotDomElement(TableBodyComponent, context) },
|
|
3662
4176
|
[paddingTopEl, ...items, paddingBottomEl]
|
|
3663
4177
|
);
|
|
3664
4178
|
});
|
|
@@ -3673,7 +4187,7 @@ const Viewport = ({ children }) => {
|
|
|
3673
4187
|
fixedItemHeight(ctx.itemHeight);
|
|
3674
4188
|
}
|
|
3675
4189
|
}, [ctx, viewportHeight, fixedItemHeight]);
|
|
3676
|
-
return /* @__PURE__ */ React.createElement("div", { style: viewportStyle, ref: viewportRef, "data-viewport-type": "element" }, children);
|
|
4190
|
+
return /* @__PURE__ */ React.createElement("div", { style: viewportStyle(false), ref: viewportRef, "data-viewport-type": "element" }, children);
|
|
3677
4191
|
};
|
|
3678
4192
|
const WindowViewport = ({ children }) => {
|
|
3679
4193
|
const ctx = React.useContext(VirtuosoMockContext);
|
|
@@ -3687,7 +4201,7 @@ const WindowViewport = ({ children }) => {
|
|
|
3687
4201
|
windowViewportRect({ offsetTop: 0, visibleHeight: ctx.viewportHeight, visibleWidth: 100 });
|
|
3688
4202
|
}
|
|
3689
4203
|
}, [ctx, windowViewportRect, fixedItemHeight]);
|
|
3690
|
-
return /* @__PURE__ */ React.createElement("div", { ref: viewportRef, style: viewportStyle, "data-viewport-type": "window" }, children);
|
|
4204
|
+
return /* @__PURE__ */ React.createElement("div", { ref: viewportRef, style: viewportStyle(false), "data-viewport-type": "window" }, children);
|
|
3691
4205
|
};
|
|
3692
4206
|
const TableRoot = /* @__PURE__ */ React.memo(function TableVirtuosoRoot(props) {
|
|
3693
4207
|
const useWindowScroll = useEmitterValue("useWindowScroll");
|
|
@@ -3708,7 +4222,7 @@ const TableRoot = /* @__PURE__ */ React.memo(function TableVirtuosoRoot(props) {
|
|
|
3708
4222
|
TheTHead,
|
|
3709
4223
|
{
|
|
3710
4224
|
key: "TableHead",
|
|
3711
|
-
style: { zIndex:
|
|
4225
|
+
style: { zIndex: 2, position: "sticky", top: 0 },
|
|
3712
4226
|
ref: theadRef,
|
|
3713
4227
|
...contextPropIfNotDomElement(TheTHead, context)
|
|
3714
4228
|
},
|
|
@@ -3724,11 +4238,11 @@ const TableRoot = /* @__PURE__ */ React.memo(function TableVirtuosoRoot(props) {
|
|
|
3724
4238
|
},
|
|
3725
4239
|
fixedFooterContent()
|
|
3726
4240
|
) : null;
|
|
3727
|
-
return /* @__PURE__ */ React.createElement(TheScroller, { ...props }, /* @__PURE__ */ React.createElement(TheViewport, null, React.createElement(
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
theFoot
|
|
3731
|
-
|
|
4241
|
+
return /* @__PURE__ */ React.createElement(TheScroller, { ...props }, /* @__PURE__ */ React.createElement(TheViewport, null, React.createElement(
|
|
4242
|
+
TheTable,
|
|
4243
|
+
{ style: { borderSpacing: 0, overflowAnchor: "none" }, ...contextPropIfNotDomElement(TheTable, context) },
|
|
4244
|
+
[theHead, /* @__PURE__ */ React.createElement(Items, { key: "TableBody" }), theFoot]
|
|
4245
|
+
)));
|
|
3732
4246
|
});
|
|
3733
4247
|
const {
|
|
3734
4248
|
Component: Table,
|
|
@@ -3740,6 +4254,7 @@ const {
|
|
|
3740
4254
|
{
|
|
3741
4255
|
required: {},
|
|
3742
4256
|
optional: {
|
|
4257
|
+
restoreStateFrom: "restoreStateFrom",
|
|
3743
4258
|
context: "context",
|
|
3744
4259
|
followOutput: "followOutput",
|
|
3745
4260
|
firstItemIndex: "firstItemIndex",
|
|
@@ -3773,7 +4288,8 @@ const {
|
|
|
3773
4288
|
scrollToIndex: "scrollToIndex",
|
|
3774
4289
|
scrollIntoView: "scrollIntoView",
|
|
3775
4290
|
scrollTo: "scrollTo",
|
|
3776
|
-
scrollBy: "scrollBy"
|
|
4291
|
+
scrollBy: "scrollBy",
|
|
4292
|
+
getState: "getState"
|
|
3777
4293
|
},
|
|
3778
4294
|
events: {
|
|
3779
4295
|
isScrolling: "isScrolling",
|