virtua 0.50.2 → 0.50.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ var clamp = (value, minValue, maxValue) => min(maxValue, max(minValue, value));
8
8
  var sort = (arr) => {
9
9
  return [...arr].sort((a, b) => a - b);
10
10
  };
11
+ var timeout = setTimeout;
11
12
  var microtask = typeof queueMicrotask === "function" ? queueMicrotask : (fn) => {
12
13
  Promise.resolve().then(fn);
13
14
  };
@@ -190,7 +191,7 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
190
191
  let _prevRange = [0, isSSR ? max(ssrCount - 1, 0) : -1];
191
192
  let _totalMeasuredSize = 0;
192
193
  let _isViewportMeasured = false;
193
- const cache = initCache(elementsCount, cacheSnapshot ? cacheSnapshot[1] : itemSize, cacheSnapshot && cacheSnapshot[0]);
194
+ const cache = initCache(elementsCount, cacheSnapshot && cacheSnapshot[1] || itemSize, cacheSnapshot && cacheSnapshot[0]);
194
195
  const subscribers = new Set();
195
196
  const getRelativeScrollOffset = () => scrollOffset - startSpacerSize;
196
197
  const getVisibleOffset = () => getRelativeScrollOffset() + pendingJump + jump;
@@ -408,8 +409,21 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
408
409
  };
409
410
 
410
411
  //#endregion
411
- //#region src/core/scroller.ts
412
- var timeout = setTimeout;
412
+ //#region src/core/observer.ts
413
+ var createResizeObserver = (cb) => {
414
+ let ro;
415
+ return {
416
+ _observe(e) {
417
+ (ro || (ro = new (getCurrentWindow(getCurrentDocument(e))).ResizeObserver(cb))).observe(e);
418
+ },
419
+ _unobserve(e) {
420
+ ro.unobserve(e);
421
+ },
422
+ _dispose() {
423
+ ro && ro.disconnect();
424
+ }
425
+ };
426
+ };
413
427
  var debounce = (fn, ms) => {
414
428
  let id;
415
429
  const cancel = () => {
@@ -499,6 +513,9 @@ var createScrollObserver = (store, viewport, isHorizontal, getScrollOffset, upda
499
513
  }
500
514
  };
501
515
  };
516
+
517
+ //#endregion
518
+ //#region src/core/driver.ts
502
519
  var createScrollScheduler = (store, initialized, scroll) => {
503
520
  let cancelScroll;
504
521
  return [async (getTargetOffset, smooth) => {
@@ -564,7 +581,7 @@ var createScrollScheduler = (store, initialized, scroll) => {
564
581
  cancelScroll && cancelScroll();
565
582
  }];
566
583
  };
567
- var createScroller = (store, isHorizontal) => {
584
+ var createContainerDriver = (store, isHorizontal) => {
568
585
  let viewportElement;
569
586
  let scrollObserver;
570
587
  let initialized = createPromise();
@@ -582,9 +599,28 @@ var createScroller = (store, isHorizontal) => {
582
599
  viewportElement[scrollOffsetKey] = offset;
583
600
  }
584
601
  });
602
+ const sizeKey = isHorizontal ? "width" : "height";
603
+ const mountedIndexes = new WeakMap();
604
+ const resizeObserver = createResizeObserver((entries) => {
605
+ const resizes = [];
606
+ for (const { target, contentRect } of entries) {
607
+ if (!target.offsetParent) continue;
608
+ if (target === viewportElement) {
609
+ store.$update(4, contentRect[sizeKey]);
610
+ } else {
611
+ const index = mountedIndexes.get(target);
612
+ if (index != null) {
613
+ resizes.push([index, contentRect[sizeKey]]);
614
+ }
615
+ }
616
+ }
617
+ if (resizes.length) {
618
+ store.$update(3, resizes);
619
+ }
620
+ });
585
621
  return {
586
- $observe(_, viewport) {
587
- viewportElement = viewport;
622
+ $observe(containerElement, viewport = containerElement.parentElement) {
623
+ resizeObserver._observe(viewportElement = viewport);
588
624
  if (isHorizontal) {
589
625
  isNegative = getComputedStyle(viewport).direction === "rtl";
590
626
  }
@@ -605,43 +641,32 @@ var createScroller = (store, isHorizontal) => {
605
641
  initialized[1](true);
606
642
  },
607
643
  $dispose() {
644
+ resizeObserver._dispose();
608
645
  scrollObserver && scrollObserver._dispose();
609
646
  initialized[1](false);
610
647
  initialized = createPromise();
611
648
  },
612
- $isNegative: () => isNegative,
613
- $scrollTo(offset) {
614
- scheduleScroll(() => offset);
615
- },
616
- $scrollBy(offset) {
617
- offset += store.$getScrollOffset();
618
- scheduleScroll(() => offset);
619
- },
620
- $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {
621
- index = clamp(index, 0, store.$getItemsLength() - 1);
622
- if (align === "nearest") {
623
- const itemOffset = store.$getItemOffset(index);
624
- const scrollOffset = store.$getScrollOffset();
625
- if (itemOffset < scrollOffset) {
626
- align = "start";
627
- } else if (itemOffset + store.$getItemSize(index) > scrollOffset + store.$getViewportSize()) {
628
- align = "end";
629
- } else {
630
- return;
631
- }
632
- }
633
- scheduleScroll(() => {
634
- return offset + store.$getStartSpacerSize() + store.$getItemOffset(index) + (align === "end" ? store.$getItemSize(index) - store.$getViewportSize() : align === "center" ? (store.$getItemSize(index) - store.$getViewportSize()) / 2 : 0);
635
- }, smooth);
649
+ $observeItem(el, index) {
650
+ mountedIndexes.set(el, index);
651
+ resizeObserver._observe(el);
652
+ return () => {
653
+ mountedIndexes.delete(el);
654
+ resizeObserver._unobserve(el);
655
+ };
636
656
  },
637
- $fixScrollJump: () => {
657
+ $isNegative: () => isNegative,
658
+ $scheduleScroll: scheduleScroll,
659
+ $fixScrollJump() {
638
660
  scrollObserver && scrollObserver._fixScrollJump();
639
- }
661
+ },
662
+ $getBaseOffset: store.$getStartSpacerSize,
663
+ $getScrollbarSize: () => 0
640
664
  };
641
665
  };
642
- var createWindowScroller = (store, isHorizontal) => {
666
+ var createWindowDriver = (store, isHorizontal) => {
643
667
  let containerElement;
644
668
  let scrollObserver;
669
+ let cleanupOnWindowResize;
645
670
  let initialized = createPromise();
646
671
  let isNegative = false;
647
672
  const scrollToKey = isHorizontal ? "left" : "top";
@@ -657,6 +682,21 @@ var createWindowScroller = (store, isHorizontal) => {
657
682
  window.scroll({ [scrollToKey]: offset });
658
683
  }
659
684
  });
685
+ const sizeKey = isHorizontal ? "width" : "height";
686
+ const mountedIndexes = new WeakMap();
687
+ const resizeObserver = createResizeObserver((entries) => {
688
+ const resizes = [];
689
+ for (const { target, contentRect } of entries) {
690
+ if (!target.offsetParent) continue;
691
+ const index = mountedIndexes.get(target);
692
+ if (index != null) {
693
+ resizes.push([index, contentRect[sizeKey]]);
694
+ }
695
+ }
696
+ if (resizes.length) {
697
+ store.$update(3, resizes);
698
+ }
699
+ });
660
700
  const calcOffsetToViewport = (node, viewport, window, isHorizontal, offset = 0) => {
661
701
  const offsetKey = isHorizontal ? "offsetLeft" : "offsetTop";
662
702
  const offsetSum = offset + (isHorizontal && isNegative ? window.innerWidth - node[offsetKey] - node.offsetWidth : node[offsetKey]);
@@ -672,6 +712,14 @@ var createWindowScroller = (store, isHorizontal) => {
672
712
  const scrollOffsetKey = isHorizontal ? "scrollX" : "scrollY";
673
713
  const document = getCurrentDocument(container);
674
714
  const window = getCurrentWindow(document);
715
+ const onWindowResize = () => {
716
+ store.$update(4, window[isHorizontal ? "innerWidth" : "innerHeight"]);
717
+ };
718
+ window.addEventListener("resize", onWindowResize);
719
+ microtask(onWindowResize);
720
+ cleanupOnWindowResize = () => {
721
+ window.removeEventListener("resize", onWindowResize);
722
+ };
675
723
  if (isHorizontal) {
676
724
  isNegative = getComputedStyle(getDocumentElement(document)).direction === "rtl";
677
725
  }
@@ -685,181 +733,56 @@ var createWindowScroller = (store, isHorizontal) => {
685
733
  initialized[1](true);
686
734
  },
687
735
  $dispose() {
736
+ cleanupOnWindowResize && cleanupOnWindowResize();
737
+ resizeObserver._dispose();
688
738
  scrollObserver && scrollObserver._dispose();
689
739
  containerElement = undefined;
690
740
  initialized[1](false);
691
741
  initialized = createPromise();
692
742
  },
743
+ $observeItem(el, index) {
744
+ mountedIndexes.set(el, index);
745
+ resizeObserver._observe(el);
746
+ return () => {
747
+ mountedIndexes.delete(el);
748
+ resizeObserver._unobserve(el);
749
+ };
750
+ },
693
751
  $isNegative: () => isNegative,
694
- $fixScrollJump: () => {
752
+ $scheduleScroll: scheduleScroll,
753
+ $fixScrollJump() {
695
754
  scrollObserver && scrollObserver._fixScrollJump();
696
755
  },
697
- $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {
698
- if (!containerElement) return;
699
- index = clamp(index, 0, store.$getItemsLength() - 1);
700
- if (align === "nearest") {
701
- const itemOffset = store.$getItemOffset(index);
702
- const scrollOffset = store.$getScrollOffset();
703
- if (itemOffset < scrollOffset) {
704
- align = "start";
705
- } else if (itemOffset + store.$getItemSize(index) > scrollOffset + store.$getViewportSize()) {
706
- align = "end";
707
- } else {
708
- return;
709
- }
710
- }
756
+ $getBaseOffset() {
711
757
  const document = getCurrentDocument(containerElement);
712
- const window = getCurrentWindow(document);
713
- const html = getDocumentElement(document);
714
- const getScrollbarSize = () => store.$getViewportSize() - (isHorizontal ? html.clientWidth : html.clientHeight);
715
- scheduleScroll(() => {
716
- return offset + calcOffsetToViewport(containerElement, document.body, window, isHorizontal) + store.$getItemOffset(index) + (align === "end" ? store.$getItemSize(index) - (store.$getViewportSize() - getScrollbarSize()) : align === "center" ? (store.$getItemSize(index) - (store.$getViewportSize() - getScrollbarSize())) / 2 : 0);
717
- }, smooth);
718
- }
719
- };
720
- };
721
- var createGridScroller = (rowStore, colStore) => {
722
- const rowScroller = createScroller(rowStore, false);
723
- const colScroller = createScroller(colStore, true);
724
- return {
725
- $observe(container, viewport) {
726
- rowScroller.$observe(container, viewport);
727
- colScroller.$observe(container, viewport);
728
- },
729
- $dispose() {
730
- rowScroller.$dispose();
731
- colScroller.$dispose();
732
- },
733
- $isNegative: colScroller.$isNegative,
734
- $scrollTo(row, col) {
735
- if (row != null) {
736
- rowScroller.$scrollTo(row);
737
- }
738
- if (col != null) {
739
- colScroller.$scrollTo(col);
740
- }
741
- },
742
- $scrollBy(row, col) {
743
- if (row != null) {
744
- rowScroller.$scrollBy(row);
745
- }
746
- if (col != null) {
747
- colScroller.$scrollBy(col);
748
- }
749
- },
750
- $scrollToIndex(row, col) {
751
- if (row != null) {
752
- rowScroller.$scrollToIndex(row);
753
- }
754
- if (col != null) {
755
- colScroller.$scrollToIndex(col);
756
- }
757
- },
758
- $fixScrollJump() {
759
- rowScroller.$fixScrollJump();
760
- colScroller.$fixScrollJump();
761
- }
762
- };
763
- };
764
-
765
- //#endregion
766
- //#region src/core/resizer.ts
767
- var createResizeObserver = (cb) => {
768
- let ro;
769
- return {
770
- _observe(e) {
771
- (ro || (ro = new (getCurrentWindow(getCurrentDocument(e))).ResizeObserver(cb))).observe(e);
772
- },
773
- _unobserve(e) {
774
- ro.unobserve(e);
758
+ return calcOffsetToViewport(containerElement, document.body, getCurrentWindow(document), isHorizontal);
775
759
  },
776
- _dispose() {
777
- ro && ro.disconnect();
760
+ $getScrollbarSize() {
761
+ const html = getDocumentElement(getCurrentDocument(containerElement));
762
+ return store.$getViewportSize() - (isHorizontal ? html.clientWidth : html.clientHeight);
778
763
  }
779
764
  };
780
765
  };
781
- var createResizer = (store, isHorizontal) => {
766
+ var createContainerGridDriver = (rowStore, colStore) => {
782
767
  let viewportElement;
783
- const sizeKey = isHorizontal ? "width" : "height";
784
- const mountedIndexes = new WeakMap();
785
- const resizeObserver = createResizeObserver((entries) => {
786
- const resizes = [];
787
- for (const { target, contentRect } of entries) {
788
- if (!target.offsetParent) continue;
789
- if (target === viewportElement) {
790
- store.$update(4, contentRect[sizeKey]);
791
- } else {
792
- const index = mountedIndexes.get(target);
793
- if (index != null) {
794
- resizes.push([index, contentRect[sizeKey]]);
795
- }
796
- }
797
- }
798
- if (resizes.length) {
799
- store.$update(3, resizes);
768
+ let rowScrollObserver;
769
+ let colScrollObserver;
770
+ let initialized = createPromise();
771
+ let isNegative = false;
772
+ const [scheduleScrollX, cancelScrollX] = createScrollScheduler(colStore, () => initialized[0], (offset, smooth) => {
773
+ const opts = { left: normalizeScrollOffset(offset, isNegative) };
774
+ if (smooth) {
775
+ opts.behavior = "smooth";
800
776
  }
777
+ viewportElement.scrollTo(opts);
801
778
  });
802
- return {
803
- $observeRoot(viewport) {
804
- resizeObserver._observe(viewportElement = viewport);
805
- },
806
- $observeItem: (el, i) => {
807
- mountedIndexes.set(el, i);
808
- resizeObserver._observe(el);
809
- return () => {
810
- mountedIndexes.delete(el);
811
- resizeObserver._unobserve(el);
812
- };
813
- },
814
- $dispose: resizeObserver._dispose
815
- };
816
- };
817
- var createWindowResizer = (store, isHorizontal) => {
818
- const sizeKey = isHorizontal ? "width" : "height";
819
- const windowSizeKey = isHorizontal ? "innerWidth" : "innerHeight";
820
- const mountedIndexes = new WeakMap();
821
- const resizeObserver = createResizeObserver((entries) => {
822
- const resizes = [];
823
- for (const { target, contentRect } of entries) {
824
- if (!target.offsetParent) continue;
825
- const index = mountedIndexes.get(target);
826
- if (index != null) {
827
- resizes.push([index, contentRect[sizeKey]]);
828
- }
829
- }
830
- if (resizes.length) {
831
- store.$update(3, resizes);
779
+ const [scheduleScrollY, cancelScrollY] = createScrollScheduler(rowStore, () => initialized[0], (offset, smooth) => {
780
+ const opts = { top: offset };
781
+ if (smooth) {
782
+ opts.behavior = "smooth";
832
783
  }
784
+ viewportElement.scrollTo(opts);
833
785
  });
834
- let cleanupOnWindowResize;
835
- return {
836
- $observeRoot(container) {
837
- const window = getCurrentWindow(getCurrentDocument(container));
838
- const onWindowResize = () => {
839
- store.$update(4, window[windowSizeKey]);
840
- };
841
- window.addEventListener("resize", onWindowResize);
842
- microtask(onWindowResize);
843
- cleanupOnWindowResize = () => {
844
- window.removeEventListener("resize", onWindowResize);
845
- };
846
- },
847
- $observeItem: (el, i) => {
848
- mountedIndexes.set(el, i);
849
- resizeObserver._observe(el);
850
- return () => {
851
- mountedIndexes.delete(el);
852
- resizeObserver._unobserve(el);
853
- };
854
- },
855
- $dispose() {
856
- cleanupOnWindowResize && cleanupOnWindowResize();
857
- resizeObserver._dispose();
858
- }
859
- };
860
- };
861
- var createGridResizer = (rowStore, colStore) => {
862
- let viewportElement;
863
786
  const mountedIndexes = new WeakMap();
864
787
  const maybeCachedRowIndexes = new Set();
865
788
  const maybeCachedColIndexes = new Set();
@@ -936,9 +859,40 @@ var createGridResizer = (rowStore, colStore) => {
936
859
  colStore.$update(3, widthResizes);
937
860
  }
938
861
  });
862
+ const observeAxisScroll = (store, isHorizontal, cancelScroll) => {
863
+ const viewport = viewportElement;
864
+ const scrollOffsetKey = isHorizontal ? "scrollLeft" : "scrollTop";
865
+ const overflowKey = isHorizontal ? "overflowX" : "overflowY";
866
+ const negative = isHorizontal && isNegative;
867
+ return createScrollObserver(store, viewport, isHorizontal, () => normalizeScrollOffset(viewport[scrollOffsetKey], negative), (jump, shift, isMomentumScrolling) => {
868
+ if (isMomentumScrolling) {
869
+ const style = viewport.style;
870
+ const prev = style[overflowKey];
871
+ style[overflowKey] = "hidden";
872
+ timeout(() => {
873
+ style[overflowKey] = prev;
874
+ });
875
+ }
876
+ viewport[scrollOffsetKey] = normalizeScrollOffset(store.$getScrollOffset() + jump, negative);
877
+ if (shift) {
878
+ cancelScroll();
879
+ }
880
+ });
881
+ };
939
882
  return {
940
- $observeRoot(viewport) {
883
+ $observe(containerElement, viewport = containerElement.parentElement) {
941
884
  resizeObserver._observe(viewportElement = viewport);
885
+ isNegative = getComputedStyle(viewport).direction === "rtl";
886
+ rowScrollObserver = observeAxisScroll(rowStore, false, cancelScrollY);
887
+ colScrollObserver = observeAxisScroll(colStore, true, cancelScrollX);
888
+ initialized[1](true);
889
+ },
890
+ $dispose() {
891
+ resizeObserver._dispose();
892
+ rowScrollObserver && rowScrollObserver._dispose();
893
+ colScrollObserver && colScrollObserver._dispose();
894
+ initialized[1](false);
895
+ initialized = createPromise();
942
896
  },
943
897
  $observeItem(el, rowIndex, colIndex) {
944
898
  mountedIndexes.set(el, [rowIndex, colIndex]);
@@ -950,6 +904,14 @@ var createGridResizer = (rowStore, colStore) => {
950
904
  resizeObserver._unobserve(el);
951
905
  };
952
906
  },
907
+ $resizeRows(rows) {
908
+ for (const [r] of rows) {
909
+ for (let c = 0; c < colStore.$getItemsLength(); c++) {
910
+ sizeCache.delete(getKey(r, c));
911
+ }
912
+ }
913
+ rowStore.$update(3, rows);
914
+ },
953
915
  $resizeCols(cols) {
954
916
  for (const [c] of cols) {
955
917
  for (let r = 0; r < rowStore.$getItemsLength(); r++) {
@@ -958,18 +920,71 @@ var createGridResizer = (rowStore, colStore) => {
958
920
  }
959
921
  colStore.$update(3, cols);
960
922
  },
961
- $resizeRows(rows) {
962
- for (const [r] of rows) {
963
- for (let c = 0; c < colStore.$getItemsLength(); c++) {
964
- sizeCache.delete(getKey(r, c));
965
- }
966
- }
967
- rowStore.$update(3, rows);
923
+ $isNegative: () => isNegative,
924
+ $scheduleScrollX: scheduleScrollX,
925
+ $scheduleScrollY: scheduleScrollY,
926
+ $fixScrollJump() {
927
+ rowScrollObserver && rowScrollObserver._fixScrollJump();
928
+ colScrollObserver && colScrollObserver._fixScrollJump();
968
929
  },
969
- $dispose: resizeObserver._dispose
930
+ $getBaseOffset: (isHorizontal) => (isHorizontal ? colStore : rowStore).$getStartSpacerSize()
970
931
  };
971
932
  };
972
933
 
934
+ //#endregion
935
+ //#region src/core/scroll-to.ts
936
+ var scrollTo = (driver, offset) => {
937
+ driver.$scheduleScroll(() => offset);
938
+ };
939
+ var scrollBy = (driver, store, offset) => {
940
+ scrollTo(driver, offset + store.$getScrollOffset());
941
+ };
942
+ var scrollToIndex = (driver, store, index, { align, smooth, offset = 0 } = {}) => {
943
+ index = clamp(index, 0, store.$getItemsLength() - 1);
944
+ if (align === "nearest") {
945
+ const itemOffset = store.$getItemOffset(index);
946
+ const scrollOffset = store.$getScrollOffset();
947
+ if (itemOffset < scrollOffset) {
948
+ align = "start";
949
+ } else if (itemOffset + store.$getItemSize(index) > scrollOffset + store.$getViewportSize()) {
950
+ align = "end";
951
+ } else {
952
+ return;
953
+ }
954
+ }
955
+ driver.$scheduleScroll(() => {
956
+ return offset + driver.$getBaseOffset() + store.$getItemOffset(index) + (align === "end" ? store.$getItemSize(index) - (store.$getViewportSize() - driver.$getScrollbarSize()) : align === "center" ? (store.$getItemSize(index) - (store.$getViewportSize() - driver.$getScrollbarSize())) / 2 : 0);
957
+ }, smooth);
958
+ };
959
+ var gridScrollTo = (driver, row, col) => {
960
+ if (row != null) {
961
+ driver.$scheduleScrollY(() => row);
962
+ }
963
+ if (col != null) {
964
+ driver.$scheduleScrollX(() => col);
965
+ }
966
+ };
967
+ var gridScrollBy = (driver, rowStore, colStore, row, col) => {
968
+ if (row != null) {
969
+ const target = row + rowStore.$getScrollOffset();
970
+ driver.$scheduleScrollY(() => target);
971
+ }
972
+ if (col != null) {
973
+ const target = col + colStore.$getScrollOffset();
974
+ driver.$scheduleScrollX(() => target);
975
+ }
976
+ };
977
+ var gridScrollToIndex = (driver, rowStore, colStore, row, col) => {
978
+ if (row != null) {
979
+ const index = clamp(row, 0, rowStore.$getItemsLength() - 1);
980
+ driver.$scheduleScrollY(() => driver.$getBaseOffset(false) + rowStore.$getItemOffset(index));
981
+ }
982
+ if (col != null) {
983
+ const index = clamp(col, 0, colStore.$getItemsLength() - 1);
984
+ driver.$scheduleScrollX(() => driver.$getBaseOffset(true) + colStore.$getItemOffset(index));
985
+ }
986
+ };
987
+
973
988
  //#endregion
974
989
  //#region src/solid/ListItem.tsx
975
990
  var ListItem = (props) => {
@@ -1012,8 +1027,7 @@ var Virtualizer = (props) => {
1012
1027
  const { itemSize, horizontal = false, cache } = props;
1013
1028
  props = mergeProps({ as: "div" }, props);
1014
1029
  const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
1015
- const resizer = createResizer(store, horizontal);
1016
- const scroller = createScroller(store, horizontal);
1030
+ const driver = createContainerDriver(store, horizontal);
1017
1031
  const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
1018
1032
  store.$subscribe(1, () => {
1019
1033
  setRerender(store.$getStateVersion());
@@ -1034,7 +1048,7 @@ var Virtualizer = (props) => {
1034
1048
  });
1035
1049
  const isScrolling = createMemo(() => stateVersion() && store.$isScrolling());
1036
1050
  const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());
1037
- const isNegative = createMemo(() => stateVersion() && scroller.$isNegative());
1051
+ const isNegative = createMemo(() => stateVersion() && driver.$isNegative());
1038
1052
  onMount(() => {
1039
1053
  if (props.ref) {
1040
1054
  props.ref({
@@ -1053,22 +1067,18 @@ var Virtualizer = (props) => {
1053
1067
  findItemIndex: store.$findItemIndex,
1054
1068
  getItemOffset: store.$getItemOffset,
1055
1069
  getItemSize: store.$getItemSize,
1056
- scrollToIndex: scroller.$scrollToIndex,
1057
- scrollTo: scroller.$scrollTo,
1058
- scrollBy: scroller.$scrollBy
1070
+ scrollToIndex: (index, opts) => scrollToIndex(driver, store, index, opts),
1071
+ scrollTo: (offset) => scrollTo(driver, offset),
1072
+ scrollBy: (offset) => scrollBy(driver, store, offset)
1059
1073
  });
1060
1074
  }
1061
- const container = containerRef;
1062
- const scrollable = props.scrollRef || container.parentElement;
1063
- resizer.$observeRoot(scrollable);
1064
- scroller.$observe(container, scrollable);
1075
+ driver.$observe(containerRef, props.scrollRef);
1065
1076
  onCleanup(() => {
1066
1077
  if (props.ref) {
1067
1078
  props.ref();
1068
1079
  }
1069
1080
  store.$dispose();
1070
- resizer.$dispose();
1071
- scroller.$dispose();
1081
+ driver.$dispose();
1072
1082
  });
1073
1083
  });
1074
1084
  createComputed(on(() => props.startMargin || 0, (value) => {
@@ -1077,7 +1087,7 @@ var Virtualizer = (props) => {
1077
1087
  }
1078
1088
  }));
1079
1089
  createEffect(on(stateVersion, () => {
1080
- scroller.$fixScrollJump();
1090
+ driver.$fixScrollJump();
1081
1091
  }));
1082
1092
  const dataSlice = createMemo(() => {
1083
1093
  const count = props.data.length;
@@ -1120,7 +1130,7 @@ var Virtualizer = (props) => {
1120
1130
  const children = createMemo(() => {
1121
1131
  return untrack(() => props.children(data, index));
1122
1132
  });
1123
- return <ListItem _as={props.item} _index={index()} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} />;
1133
+ return <ListItem _as={props.item} _index={index()} _resizer={driver.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} />;
1124
1134
  };
1125
1135
  return <Dynamic component={props.as} ref={containerRef} style={{
1126
1136
  contain: "size style",
@@ -1178,8 +1188,7 @@ var WindowVirtualizer = (props) => {
1178
1188
  let containerRef;
1179
1189
  const { ref: _ref, data: _data, children: _children, itemSize, shift: _shift, horizontal = false, cache, onScrollEnd: _onScrollEnd } = props;
1180
1190
  const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
1181
- const resizer = createWindowResizer(store, horizontal);
1182
- const scroller = createWindowScroller(store, horizontal);
1191
+ const driver = createWindowDriver(store, horizontal);
1183
1192
  const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
1184
1193
  store.$subscribe(1, () => {
1185
1194
  setRerender(store.$getStateVersion());
@@ -1200,7 +1209,7 @@ var WindowVirtualizer = (props) => {
1200
1209
  });
1201
1210
  const isScrolling = createMemo(() => stateVersion() && store.$isScrolling());
1202
1211
  const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());
1203
- const isNegative = createMemo(() => stateVersion() && scroller.$isNegative());
1212
+ const isNegative = createMemo(() => stateVersion() && driver.$isNegative());
1204
1213
  onMount(() => {
1205
1214
  if (props.ref) {
1206
1215
  props.ref({
@@ -1216,22 +1225,20 @@ var WindowVirtualizer = (props) => {
1216
1225
  findItemIndex: store.$findItemIndex,
1217
1226
  getItemOffset: store.$getItemOffset,
1218
1227
  getItemSize: store.$getItemSize,
1219
- scrollToIndex: scroller.$scrollToIndex
1228
+ scrollToIndex: (index, opts) => scrollToIndex(driver, store, index, opts)
1220
1229
  });
1221
1230
  }
1222
- resizer.$observeRoot(containerRef);
1223
- scroller.$observe(containerRef);
1231
+ driver.$observe(containerRef);
1224
1232
  onCleanup(() => {
1225
1233
  if (props.ref) {
1226
1234
  props.ref();
1227
1235
  }
1228
1236
  store.$dispose();
1229
- resizer.$dispose();
1230
- scroller.$dispose();
1237
+ driver.$dispose();
1231
1238
  });
1232
1239
  });
1233
1240
  createEffect(on(stateVersion, () => {
1234
- scroller.$fixScrollJump();
1241
+ driver.$fixScrollJump();
1235
1242
  }));
1236
1243
  const dataSlice = createMemo(() => {
1237
1244
  const count = props.data.length;
@@ -1269,7 +1276,7 @@ var WindowVirtualizer = (props) => {
1269
1276
  const children = createMemo(() => {
1270
1277
  return untrack(() => props.children(data, itemIndex));
1271
1278
  });
1272
- return <ListItem _index={itemIndex()} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} />;
1279
+ return <ListItem _index={itemIndex()} _resizer={driver.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} />;
1273
1280
  }}
1274
1281
  </For>
1275
1282
  </div>;