ropav 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/dist/components/autocomplete/autocomplete-root.js +3 -1
  2. package/dist/components/autocomplete/index.d.ts +3 -0
  3. package/dist/components/avatar/avatar-image.js +13 -2
  4. package/dist/components/avatar/avatar.types.d.ts +7 -1
  5. package/dist/components/breadcrumbs/breadcrumbs-item.js +1 -0
  6. package/dist/components/breadcrumbs/index.d.ts +1 -0
  7. package/dist/components/calendar/calendar-header.js +1 -1
  8. package/dist/components/calendar/index.d.ts +5 -3
  9. package/dist/components/calendar-year-picker/index.d.ts +4 -2
  10. package/dist/components/checkbox/checkbox-content.js +1 -1
  11. package/dist/components/color-field/index.d.ts +3 -2
  12. package/dist/components/color-input-group/color-input-group-root.js +2 -0
  13. package/dist/components/color-input-group/color-input-group.types.d.ts +2 -0
  14. package/dist/components/color-input-group/index.d.ts +2 -0
  15. package/dist/components/combo-box/combo-box-root.js +9 -2
  16. package/dist/components/combo-box/combo-box.types.d.ts +3 -0
  17. package/dist/components/combo-box/index.d.ts +3 -0
  18. package/dist/components/date-field/index.d.ts +1 -0
  19. package/dist/components/date-input-group/date-input-group-root.js +2 -0
  20. package/dist/components/date-input-group/date-input-group-segment.js +1 -1
  21. package/dist/components/date-input-group/date-input-group.types.d.ts +2 -0
  22. package/dist/{composables → components/date-input-group}/use-date-segment.d.ts +2 -2
  23. package/dist/{composables → components/date-input-group}/use-date-segment.js +9 -9
  24. package/dist/components/date-picker/index.d.ts +3 -2
  25. package/dist/components/date-picker/index.js +2 -2
  26. package/dist/components/date-range-picker/date-range-picker-root.js +1 -1
  27. package/dist/components/date-range-picker/index.d.ts +18 -16
  28. package/dist/components/date-range-picker/index.js +2 -2
  29. package/dist/{composables → components/date-range-picker}/use-date-range-picker.d.ts +7 -7
  30. package/dist/{composables → components/date-range-picker}/use-date-range-picker.js +10 -10
  31. package/dist/components/drawer/drawer-dialog.js +1 -1
  32. package/dist/{composables → components/drawer}/use-drawer-drag.d.ts +1 -1
  33. package/dist/{composables → components/drawer}/use-drawer-drag.js +1 -1
  34. package/dist/components/dropdown/dropdown-menu.js +3 -1
  35. package/dist/components/dropdown/dropdown-submenu-trigger.js +1 -1
  36. package/dist/components/dropdown/dropdown.types.d.ts +3 -3
  37. package/dist/components/dropdown/index.d.ts +4 -2
  38. package/dist/{composables → components/dropdown}/use-safely-mouse-to-submenu.js +1 -1
  39. package/dist/components/icons/icon-overlay-arrow.js +1 -1
  40. package/dist/components/index.d.ts +5 -0
  41. package/dist/components/input/index.d.ts +12 -4
  42. package/dist/components/input/input-root.d.ts +5 -2
  43. package/dist/components/input/input-root.js +46 -5
  44. package/dist/components/input/input.types.d.ts +11 -0
  45. package/dist/components/input-group/index.d.ts +2 -0
  46. package/dist/components/input-group/input-group-root.js +3 -0
  47. package/dist/components/input-group/input-group.types.d.ts +5 -0
  48. package/dist/components/input-otp/index.d.ts +6 -4
  49. package/dist/components/link/index.d.ts +2 -0
  50. package/dist/components/link/link-root.js +22 -5
  51. package/dist/components/link/link.types.d.ts +14 -3
  52. package/dist/{composables → components/list-box}/drag-collection.d.ts +2 -2
  53. package/dist/{composables → components/list-box}/drag-collection.js +1 -1
  54. package/dist/components/list-box/index.d.ts +4 -0
  55. package/dist/components/list-box/list-box-root.js +60 -35
  56. package/dist/components/list-box/list-box.types.d.ts +2 -0
  57. package/dist/components/menu/index.d.ts +4 -0
  58. package/dist/components/menu/menu-root.js +9 -2
  59. package/dist/components/menu/menu.types.d.ts +5 -0
  60. package/dist/components/number-field/index.d.ts +3 -0
  61. package/dist/components/number-field/number-field-root.js +2 -0
  62. package/dist/components/number-field/number-field.types.d.ts +2 -0
  63. package/dist/components/overlay/overlay-arrow.js +64 -11
  64. package/dist/components/pagination/index.d.ts +2 -0
  65. package/dist/components/pagination/pagination-root.js +8 -3
  66. package/dist/components/pagination/pagination.types.d.ts +8 -0
  67. package/dist/components/popover/popover-trigger.js +14 -7
  68. package/dist/components/radio/radio-content.js +1 -1
  69. package/dist/components/range-calendar/index.d.ts +18 -15
  70. package/dist/components/range-calendar/range-calendar-header.js +1 -1
  71. package/dist/components/router-provider/index.d.ts +5 -0
  72. package/dist/components/router-provider/index.js +3 -0
  73. package/dist/components/router-provider/router-provider.context.d.ts +40 -0
  74. package/dist/components/router-provider/router-provider.context.js +16 -0
  75. package/dist/components/router-provider/router-provider.d.ts +21 -0
  76. package/dist/components/router-provider/router-provider.js +22 -0
  77. package/dist/components/router-provider/router-provider.types.d.ts +23 -0
  78. package/dist/components/scroll-shadow/scroll-shadow-root.js +7 -1
  79. package/dist/components/scroll-shadow/use-scroll-shadow.js +25 -1
  80. package/dist/components/search-field/index.d.ts +2 -0
  81. package/dist/components/search-field/search-field-root.js +3 -1
  82. package/dist/components/search-field/search-field.types.d.ts +2 -0
  83. package/dist/{composables → components/search-field}/use-search-field.d.ts +2 -2
  84. package/dist/{composables → components/search-field}/use-search-field.js +3 -3
  85. package/dist/components/segmented-control/index.d.ts +134 -0
  86. package/dist/components/segmented-control/index.js +15 -0
  87. package/dist/components/segmented-control/segmented-control-indicator.d.ts +19 -0
  88. package/dist/components/segmented-control/segmented-control-indicator.js +36 -0
  89. package/dist/components/segmented-control/segmented-control-item.d.ts +21 -0
  90. package/dist/components/segmented-control/segmented-control-item.js +96 -0
  91. package/dist/components/segmented-control/segmented-control-root.d.ts +25 -0
  92. package/dist/components/segmented-control/segmented-control-root.js +112 -0
  93. package/dist/components/segmented-control/segmented-control-separator.d.ts +19 -0
  94. package/dist/components/segmented-control/segmented-control-separator.js +18 -0
  95. package/dist/components/segmented-control/segmented-control.context.d.ts +17 -0
  96. package/dist/components/segmented-control/segmented-control.context.js +12 -0
  97. package/dist/components/segmented-control/segmented-control.types.d.ts +67 -0
  98. package/dist/components/select/index.d.ts +3 -0
  99. package/dist/components/select/select-hidden-select.js +1 -1
  100. package/dist/components/select/select-root.js +2 -0
  101. package/dist/components/select/select.types.d.ts +2 -0
  102. package/dist/components/separator/separator-root.js +11 -5
  103. package/dist/components/separator/separator.context.d.ts +7 -0
  104. package/dist/components/sidebar/index.d.ts +544 -0
  105. package/dist/components/sidebar/index.js +47 -0
  106. package/dist/components/sidebar/sidebar-collapsible-trigger.d.ts +21 -0
  107. package/dist/components/sidebar/sidebar-collapsible-trigger.js +70 -0
  108. package/dist/components/sidebar/sidebar-collapsible.d.ts +24 -0
  109. package/dist/components/sidebar/sidebar-collapsible.js +78 -0
  110. package/dist/components/sidebar/sidebar-content.d.ts +21 -0
  111. package/dist/components/sidebar/sidebar-content.js +37 -0
  112. package/dist/components/sidebar/sidebar-footer.d.ts +21 -0
  113. package/dist/components/sidebar/sidebar-footer.js +24 -0
  114. package/dist/components/sidebar/sidebar-group-label.d.ts +21 -0
  115. package/dist/components/sidebar/sidebar-group-label.js +32 -0
  116. package/dist/components/sidebar/sidebar-group.d.ts +21 -0
  117. package/dist/components/sidebar/sidebar-group.js +48 -0
  118. package/dist/components/sidebar/sidebar-header.d.ts +21 -0
  119. package/dist/components/sidebar/sidebar-header.js +24 -0
  120. package/dist/components/sidebar/sidebar-inset.d.ts +21 -0
  121. package/dist/components/sidebar/sidebar-inset.js +24 -0
  122. package/dist/components/sidebar/sidebar-item-icon.d.ts +21 -0
  123. package/dist/components/sidebar/sidebar-item-icon.js +20 -0
  124. package/dist/components/sidebar/sidebar-item-indicator.d.ts +21 -0
  125. package/dist/components/sidebar/sidebar-item-indicator.js +48 -0
  126. package/dist/components/sidebar/sidebar-item-label.d.ts +21 -0
  127. package/dist/components/sidebar/sidebar-item-label.js +28 -0
  128. package/dist/components/sidebar/sidebar-item-tooltip.d.ts +21 -0
  129. package/dist/components/sidebar/sidebar-item-tooltip.js +38 -0
  130. package/dist/components/sidebar/sidebar-item-trailing.d.ts +21 -0
  131. package/dist/components/sidebar/sidebar-item-trailing.js +28 -0
  132. package/dist/components/sidebar/sidebar-item.d.ts +23 -0
  133. package/dist/components/sidebar/sidebar-item.js +160 -0
  134. package/dist/components/sidebar/sidebar-panel.d.ts +21 -0
  135. package/dist/components/sidebar/sidebar-panel.js +88 -0
  136. package/dist/components/sidebar/sidebar-rail.d.ts +21 -0
  137. package/dist/components/sidebar/sidebar-rail.js +210 -0
  138. package/dist/components/sidebar/sidebar-root.d.ts +31 -0
  139. package/dist/components/sidebar/sidebar-root.js +138 -0
  140. package/dist/components/sidebar/sidebar-separator.d.ts +19 -0
  141. package/dist/components/sidebar/sidebar-separator.js +16 -0
  142. package/dist/components/sidebar/sidebar-sub-menu.d.ts +23 -0
  143. package/dist/components/sidebar/sidebar-sub-menu.js +40 -0
  144. package/dist/components/sidebar/sidebar-trigger.d.ts +21 -0
  145. package/dist/components/sidebar/sidebar-trigger.js +69 -0
  146. package/dist/components/sidebar/sidebar.context.d.ts +75 -0
  147. package/dist/components/sidebar/sidebar.context.js +30 -0
  148. package/dist/components/sidebar/sidebar.state.d.ts +73 -0
  149. package/dist/components/sidebar/sidebar.state.js +76 -0
  150. package/dist/components/sidebar/sidebar.storage.d.ts +8 -0
  151. package/dist/components/sidebar/sidebar.storage.js +45 -0
  152. package/dist/components/sidebar/sidebar.types.d.ts +259 -0
  153. package/dist/components/splitter/index.d.ts +143 -0
  154. package/dist/components/splitter/index.js +13 -0
  155. package/dist/components/splitter/splitter-handle.d.ts +21 -0
  156. package/dist/components/splitter/splitter-handle.js +209 -0
  157. package/dist/components/splitter/splitter-panel.d.ts +21 -0
  158. package/dist/components/splitter/splitter-panel.js +70 -0
  159. package/dist/components/splitter/splitter-root.d.ts +31 -0
  160. package/dist/components/splitter/splitter-root.js +152 -0
  161. package/dist/components/splitter/splitter.context.d.ts +15 -0
  162. package/dist/components/splitter/splitter.context.js +5 -0
  163. package/dist/components/splitter/splitter.state.d.ts +87 -0
  164. package/dist/components/splitter/splitter.state.js +322 -0
  165. package/dist/components/splitter/splitter.storage.d.ts +15 -0
  166. package/dist/components/splitter/splitter.storage.js +56 -0
  167. package/dist/components/splitter/splitter.types.d.ts +98 -0
  168. package/dist/components/switch/switch-content.js +1 -1
  169. package/dist/components/table/index.d.ts +10 -9
  170. package/dist/components/table/table-body.js +13 -13
  171. package/dist/components/table/table-cell.js +49 -46
  172. package/dist/components/table/table-column-resizer.js +1 -1
  173. package/dist/components/table/table-column.js +1 -1
  174. package/dist/components/table/table-content.js +37 -18
  175. package/dist/{composables → components/table}/table-drag-collection.d.ts +1 -1
  176. package/dist/{composables → components/table}/table-drag-collection.js +1 -1
  177. package/dist/components/table/table-drop-indicator.js +3 -1
  178. package/dist/components/table/table-resizable-container.d.ts +4 -5
  179. package/dist/components/table/table-row.js +45 -14
  180. package/dist/components/table/table-virtualizer-item.d.ts +2 -7
  181. package/dist/components/table/table-virtualizer-item.js +20 -9
  182. package/dist/components/table/table.context.d.ts +11 -3
  183. package/dist/components/table/table.types.d.ts +1 -1
  184. package/dist/{composables → components/table}/use-grid-keyboard.d.ts +3 -3
  185. package/dist/{composables → components/table}/use-grid-keyboard.js +57 -55
  186. package/dist/{composables → components/table}/use-grid-selection-announcement.d.ts +2 -2
  187. package/dist/{composables → components/table}/use-grid-selection-announcement.js +2 -2
  188. package/dist/{composables → components/table}/use-table-collection.d.ts +2 -2
  189. package/dist/{composables → components/table}/use-table-collection.js +4 -4
  190. package/dist/{composables → components/table}/use-table-column-layout.d.ts +13 -20
  191. package/dist/components/table/use-table-column-layout.js +115 -0
  192. package/dist/components/tabs/tabs-panel.js +5 -1
  193. package/dist/components/tabs/tabs-tab.js +1 -1
  194. package/dist/components/textarea/index.d.ts +12 -4
  195. package/dist/components/textarea/textarea-root.d.ts +5 -2
  196. package/dist/components/textarea/textarea-root.js +40 -5
  197. package/dist/components/textarea/textarea.types.d.ts +11 -0
  198. package/dist/components/textfield/index.d.ts +2 -0
  199. package/dist/components/textfield/textfield-root.js +5 -1
  200. package/dist/components/textfield/textfield.context.d.ts +2 -0
  201. package/dist/components/textfield/textfield.types.d.ts +5 -0
  202. package/dist/components/time-field/index.d.ts +1 -0
  203. package/dist/components/toast/index.d.ts +1 -0
  204. package/dist/components/toast/toast-default-content.js +1 -1
  205. package/dist/components/toggle-button-group/toggle-button-group-root.js +3 -3
  206. package/dist/components/toolbar/index.d.ts +3 -2
  207. package/dist/components/toolbar/toolbar-root.js +3 -3
  208. package/dist/components/tooltip/index.js +1 -1
  209. package/dist/components/tooltip/tooltip-root.js +1 -1
  210. package/dist/components/tooltip/tooltip-trigger.js +13 -5
  211. package/dist/components/virtualizer/index.d.ts +3 -1
  212. package/dist/components/virtualizer/index.js +2 -1
  213. package/dist/components/virtualizer/use-virtualizer-item.d.ts +23 -0
  214. package/dist/components/virtualizer/use-virtualizer-item.js +45 -0
  215. package/dist/components/virtualizer/virtualizer-item.js +7 -41
  216. package/dist/components/virtualizer/virtualizer-scrollbar-track.d.ts +20 -0
  217. package/dist/components/virtualizer/virtualizer-scrollbar-track.js +141 -0
  218. package/dist/components/virtualizer/virtualizer-scrollbar.d.ts +18 -0
  219. package/dist/components/virtualizer/virtualizer-scrollbar.js +55 -0
  220. package/dist/components/virtualizer/virtualizer.context.d.ts +17 -1
  221. package/dist/composables/drag-manager.js +1 -13
  222. package/dist/composables/index.d.ts +3 -71
  223. package/dist/composables/use-collection.d.ts +22 -3
  224. package/dist/composables/use-collection.js +67 -14
  225. package/dist/composables/use-color-area.js +2 -2
  226. package/dist/composables/use-color-field.js +1 -1
  227. package/dist/composables/use-combo-box.js +1 -1
  228. package/dist/composables/use-date-field.js +1 -1
  229. package/dist/composables/use-drag-and-drop.js +1 -1
  230. package/dist/composables/use-drag.d.ts +6 -5
  231. package/dist/composables/use-draggable-item.d.ts +2 -2
  232. package/dist/composables/use-droppable-collection.js +2 -2
  233. package/dist/composables/use-droppable-item.js +1 -1
  234. package/dist/composables/use-form-reset.d.ts +6 -2
  235. package/dist/composables/use-form-reset.js +9 -5
  236. package/dist/composables/use-list-keyboard.js +64 -62
  237. package/dist/composables/use-menu.d.ts +10 -0
  238. package/dist/composables/use-menu.js +22 -0
  239. package/dist/composables/use-number-field.js +1 -1
  240. package/dist/composables/use-select.js +2 -3
  241. package/dist/composables/use-selection-manager.js +4 -4
  242. package/dist/composables/use-single-select-list-state.d.ts +37 -0
  243. package/dist/composables/use-single-select-list-state.js +110 -0
  244. package/dist/composables/use-slider-thumb.js +2 -2
  245. package/dist/composables/use-slider.js +1 -1
  246. package/dist/composables/use-tab-list-state.d.ts +20 -29
  247. package/dist/composables/use-tab-list-state.js +20 -99
  248. package/dist/composables/use-text-field.js +1 -1
  249. package/dist/composables/use-virtualizer-scroll.d.ts +52 -2
  250. package/dist/composables/use-virtualizer-scroll.js +79 -13
  251. package/dist/composables/use-virtualizer.d.ts +24 -4
  252. package/dist/composables/use-virtualizer.js +40 -6
  253. package/dist/index.js +58 -80
  254. package/dist/utils/document-order.d.ts +14 -0
  255. package/dist/utils/document-order.js +17 -0
  256. package/dist/utils/flex-sizing.d.ts +41 -0
  257. package/dist/utils/flex-sizing.js +140 -0
  258. package/dist/utils/index.d.ts +2 -0
  259. package/dist/utils/open-link.d.ts +31 -0
  260. package/dist/utils/open-link.js +32 -0
  261. package/dist/utils/story-truncation.d.ts +20 -0
  262. package/dist/utils/story-users.d.ts +11 -0
  263. package/dist/utils/virtualizer-collection.d.ts +14 -4
  264. package/dist/utils/virtualizer-collection.js +9 -14
  265. package/dist/utils/virtualizer-layout-info.js +3 -2
  266. package/dist/utils/virtualizer-list-layout.d.ts +75 -29
  267. package/dist/utils/virtualizer-list-layout.js +182 -99
  268. package/dist/utils/virtualizer-offsets.d.ts +111 -0
  269. package/dist/utils/virtualizer-offsets.js +159 -0
  270. package/dist/utils/virtualizer-overscan.d.ts +9 -15
  271. package/dist/utils/virtualizer-overscan.js +14 -33
  272. package/dist/utils/virtualizer-table-layout.d.ts +50 -21
  273. package/dist/utils/virtualizer-table-layout.js +130 -89
  274. package/dist/version.js +1 -1
  275. package/package.json +19 -3
  276. package/dist/composables/use-table-column-layout.js +0 -214
  277. /package/dist/{composables → components/dropdown}/use-safely-mouse-to-submenu.d.ts +0 -0
@@ -1,5 +1,5 @@
1
1
  import { Point, Rect, Size } from "../utils/virtualizer-geometry.js";
2
- import { computed, onScopeDispose, toValue, watch } from "vue";
2
+ import { computed, onScopeDispose, shallowRef, toValue, watch } from "vue";
3
3
  //#region src/composables/use-virtualizer-scroll.ts
4
4
  /**
5
5
  * Measuring the scroll container a virtualizer lives in, ported from React Aria's `useScrollView`.
@@ -30,8 +30,44 @@ var useVirtualizerScroll = (options) => {
30
30
  viewportOffset: new Point(),
31
31
  viewportSize: new Size()
32
32
  };
33
+ const scrollOffset = shallowRef(new Point());
34
+ const scrollSize = shallowRef(new Size());
35
+ const scrollBox = shallowRef({
36
+ direction: "ltr",
37
+ paddingInlineStart: 0,
38
+ paddingTop: 0,
39
+ scrollsX: false,
40
+ scrollsY: false
41
+ });
33
42
  let isMeasuring = false;
34
43
  const getElement = () => toValue(options.element) ?? null;
44
+ /** Whether an overflow value is one the browser scrolls, rather than clips or lets out. */
45
+ const scrolls = (overflow) => overflow === "auto" || overflow === "scroll" || overflow === "overlay";
46
+ /** Reads what the container's style says about it, for the scrollbar drawn against it. */
47
+ const readBox = (element) => {
48
+ const style = getComputedStyle(element);
49
+ const next = {
50
+ direction: style.direction === "rtl" ? "rtl" : "ltr",
51
+ paddingInlineStart: Number.parseFloat(style.paddingInlineStart) || 0,
52
+ paddingTop: Number.parseFloat(style.paddingTop) || 0,
53
+ scrollsX: scrolls(style.overflowX),
54
+ scrollsY: scrolls(style.overflowY)
55
+ };
56
+ const current = scrollBox.value;
57
+ if (current.direction !== next.direction || current.paddingInlineStart !== next.paddingInlineStart || current.paddingTop !== next.paddingTop || current.scrollsX !== next.scrollsX || current.scrollsY !== next.scrollsY) scrollBox.value = next;
58
+ };
59
+ /** Reads where the element is scrolled to, and how far it could go. */
60
+ const readScroll = (element) => {
61
+ const scrollWidth = element.scrollWidth;
62
+ const scrollHeight = element.scrollHeight;
63
+ const left = element.scrollLeft;
64
+ const top = element.scrollTop;
65
+ state.scrollPosition = new Point(Math.max(0, Math.min(left, scrollWidth - state.size.width)), Math.max(0, Math.min(top, scrollHeight - state.size.height)));
66
+ if (scrollSize.value.width !== scrollWidth || scrollSize.value.height !== scrollHeight) scrollSize.value = new Size(scrollWidth, scrollHeight);
67
+ const inlineRange = Math.max(0, scrollWidth - state.size.width);
68
+ const offset = new Point(Math.sign(left) * Math.min(Math.abs(left), inlineRange), state.scrollPosition.y);
69
+ if (!scrollOffset.value.equals(offset)) scrollOffset.value = offset;
70
+ };
35
71
  const updateVisibleRect = () => {
36
72
  const visibleRect = new Rect(state.viewportOffset.x + state.scrollPosition.x, state.viewportOffset.y + state.scrollPosition.y, Math.max(0, Math.min(state.size.width - state.viewportOffset.x, state.viewportSize.width)), Math.max(0, Math.min(state.size.height - state.viewportOffset.y, state.viewportSize.height)));
37
73
  if (visibleRect.area > 0 || state.lastVisibleRect.area > 0) {
@@ -51,14 +87,19 @@ var useVirtualizerScroll = (options) => {
51
87
  if (state.scrollTimeout != null) clearTimeout(state.scrollTimeout);
52
88
  state.scrollTimeout = setTimeout(endScrolling, SCROLL_END_DELAY);
53
89
  };
90
+ const markScrolling = () => {
91
+ if (!state.isScrolling) {
92
+ state.isScrolling = true;
93
+ options.onScrollStart?.();
94
+ }
95
+ scheduleScrollEnd();
96
+ };
54
97
  const onScroll = (event) => {
55
98
  const element = getElement();
56
99
  const target = event.target;
57
100
  if (!element || !(target instanceof Node) || !target.contains(element)) return;
58
- if (target === element) {
59
- const contentSize = options.contentSize();
60
- state.scrollPosition = new Point(Math.max(0, Math.min(element.scrollLeft, contentSize.width - state.size.width)), Math.max(0, Math.min(element.scrollTop, contentSize.height - state.size.height)));
61
- } else {
101
+ if (target === element) readScroll(element);
102
+ else {
62
103
  const bounds = element.getBoundingClientRect();
63
104
  const x = bounds.x < 0 ? -bounds.x : 0;
64
105
  const y = bounds.y < 0 ? -bounds.y : 0;
@@ -66,11 +107,16 @@ var useVirtualizerScroll = (options) => {
66
107
  state.viewportOffset = new Point(x, y);
67
108
  }
68
109
  updateVisibleRect();
69
- if (!state.isScrolling) {
70
- state.isScrolling = true;
71
- options.onScrollStart?.();
72
- }
73
- scheduleScrollEnd();
110
+ markScrolling();
111
+ };
112
+ const scrollTo = (offset) => {
113
+ const element = getElement();
114
+ if (!element) return;
115
+ if (offset.left != null) element.scrollLeft = offset.left;
116
+ if (offset.top != null) element.scrollTop = offset.top;
117
+ readScroll(element);
118
+ updateVisibleRect();
119
+ markScrolling();
74
120
  };
75
121
  /**
76
122
  * Re-measures the container.
@@ -87,14 +133,17 @@ var useVirtualizerScroll = (options) => {
87
133
  const viewportHeight = window.innerHeight;
88
134
  const viewportChanged = state.viewportSize.width !== viewportWidth || state.viewportSize.height !== viewportHeight;
89
135
  if (viewportChanged) state.viewportSize = new Size(viewportWidth, viewportHeight);
136
+ readBox(element);
90
137
  const clientWidth = element.clientWidth;
91
138
  const clientHeight = element.clientHeight;
92
139
  if (state.size.width !== clientWidth || state.size.height !== clientHeight || viewportChanged) {
93
140
  state.size = new Size(clientWidth, clientHeight);
141
+ readScroll(element);
94
142
  updateVisibleRect();
95
143
  options.onSizeChange(state.size);
96
144
  if (element.clientWidth !== clientWidth || element.clientHeight !== clientHeight) {
97
145
  state.size = new Size(element.clientWidth, element.clientHeight);
146
+ readScroll(element);
98
147
  updateVisibleRect();
99
148
  options.onSizeChange(state.size);
100
149
  }
@@ -104,13 +153,16 @@ var useVirtualizerScroll = (options) => {
104
153
  watch(() => getElement(), (element, _previous, onCleanup) => {
105
154
  if (!element) return;
106
155
  const document = element.ownerDocument;
107
- document.addEventListener("scroll", onScroll, true);
156
+ document.addEventListener("scroll", onScroll, {
157
+ capture: true,
158
+ passive: true
159
+ });
108
160
  window.addEventListener("resize", measure);
109
161
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => measure());
110
162
  observer?.observe(element, { box: "border-box" });
111
163
  measure();
112
164
  onCleanup(() => {
113
- document.removeEventListener("scroll", onScroll, true);
165
+ document.removeEventListener("scroll", onScroll, { capture: true });
114
166
  window.removeEventListener("resize", measure);
115
167
  observer?.disconnect();
116
168
  });
@@ -118,6 +170,16 @@ var useVirtualizerScroll = (options) => {
118
170
  flush: "post",
119
171
  immediate: true
120
172
  });
173
+ watch(() => options.contentSize(), () => {
174
+ const element = getElement();
175
+ if (element) readScroll(element);
176
+ }, { flush: "post" });
177
+ watch(() => options.scrollAdjustment?.() ?? 0, (adjustment) => {
178
+ const element = getElement();
179
+ if (!element || adjustment === 0) return;
180
+ options.takeScrollAdjustment?.();
181
+ element.scrollTop += adjustment;
182
+ }, { flush: "post" });
121
183
  onScopeDispose(() => {
122
184
  if (state.scrollTimeout != null) clearTimeout(state.scrollTimeout);
123
185
  });
@@ -131,7 +193,11 @@ var useVirtualizerScroll = (options) => {
131
193
  width: px(contentSize.width)
132
194
  };
133
195
  }),
134
- measure
196
+ measure,
197
+ scrollBox: computed(() => scrollBox.value),
198
+ scrollOffset: computed(() => scrollOffset.value),
199
+ scrollSize: computed(() => scrollSize.value),
200
+ scrollTo
135
201
  };
136
202
  };
137
203
  //#endregion
@@ -11,10 +11,12 @@ import { Rect, Size } from "../utils/virtualizer-geometry.js";
11
11
  *
12
12
  * Two pieces of upstream are deliberately gone:
13
13
  *
14
- * `ReusableView` and its recycling. React swaps the content of existing elements as they scroll
15
- * out of view, and defers reordering the DOM until scrolling stops because reordering is what
16
- * costs. A keyed `v-for` does the same swapping for free here, and it keeps the DOM in
17
- * collection order at every moment which is what a screen reader walks.
14
+ * `ReusableView` as a class. Its idea is kept see {@link VirtualizerView.slot} because a
15
+ * keyed `v-for` on its own cannot spare a window that moved wholesale: every key in it is new, so
16
+ * every row mounts anew, and a scrollbar dragged across a long collection lands on nothing for as
17
+ * long as the mounting takes. Reordering is not deferred as React defers it: the rendered set is
18
+ * kept in collection order at every moment, which is what a screen reader walks, and moving an
19
+ * element is cheap next to mounting one.
18
20
  *
19
21
  * The scroll anchor. Upstream calls `UNSTABLE_getScrollAnchorInfo` on the layout, but no layout
20
22
  * implements it, so the whole tracker resolves to nothing for every collection in this build.
@@ -22,6 +24,15 @@ import { Rect, Size } from "../utils/virtualizer-geometry.js";
22
24
  /** One rendered element: a layout info, what it was built from, and anything nested inside it. */
23
25
  export interface VirtualizerView {
24
26
  key: VirtualizerKey;
27
+ /**
28
+ * The element this view is rendered into, as a number that outlives the key.
29
+ *
30
+ * A key that leaves the window frees its slot, and the next key to arrive takes it. A collection
31
+ * that keys its rendered items by this rather than by `key` keeps the element and its component
32
+ * when the window moves and changes what they show — which is what makes a window that moved
33
+ * wholesale cost a screenful of updates rather than a screenful of mounts.
34
+ */
35
+ slot: number;
25
36
  layoutInfo: LayoutInfo;
26
37
  parentKey: VirtualizerKey | null;
27
38
  node?: VirtualizerNode;
@@ -48,6 +59,15 @@ export interface UseVirtualizerReturn {
48
59
  endScrolling: () => void;
49
60
  /** Records a measured size, and lays out again when it moved anything. */
50
61
  updateItemSize: (key: VirtualizerKey, size: Size) => void;
62
+ /**
63
+ * How far the content under the window has been pushed by rows measured above it.
64
+ *
65
+ * Adding this to the scroll offset is what holds the collection still while the rows above it
66
+ * settle. Nothing here applies it — only whoever owns the scrolling element can.
67
+ */
68
+ scrollAdjustment: ComputedRef<number>;
69
+ /** Reads the accumulated shift and clears it, so it is applied once. */
70
+ takeScrollAdjustment: () => number;
51
71
  getLayoutInfo: (key: VirtualizerKey) => LayoutInfo | null;
52
72
  isPersistedKey: (key: VirtualizerKey) => boolean;
53
73
  }
@@ -1,5 +1,5 @@
1
1
  import { Rect, Size } from "../utils/virtualizer-geometry.js";
2
- import { OverscanManager } from "../utils/virtualizer-overscan.js";
2
+ import { overscannedRect } from "../utils/virtualizer-overscan.js";
3
3
  import { computed, shallowRef } from "vue";
4
4
  //#region src/composables/use-virtualizer.ts
5
5
  var useVirtualizer = (options) => {
@@ -8,7 +8,7 @@ var useVirtualizer = (options) => {
8
8
  const isScrolling = shallowRef(false);
9
9
  /** Bumped when something outside the reactive inputs invalidates the layout. */
10
10
  const revision = shallowRef(0);
11
- const overscan = new OverscanManager();
11
+ const scrollAdjustment = shallowRef(0);
12
12
  const persistedKeys = () => options.persistedKeys?.() ?? /* @__PURE__ */ new Set();
13
13
  /**
14
14
  * Whether a key, or anything containing it, must stay rendered.
@@ -91,9 +91,33 @@ var useVirtualizer = (options) => {
91
91
  return {
92
92
  contentSize: layout.getContentSize(),
93
93
  layout,
94
- layoutInfos: layout.getVisibleLayoutInfos(overscan.getOverscannedRect())
94
+ layoutInfos: layout.getVisibleLayoutInfos(overscannedRect(rect))
95
95
  };
96
96
  });
97
+ /** Which slot each key of the last pass held. Plain state: it is history, not something derived. */
98
+ let slotByKey = /* @__PURE__ */ new Map();
99
+ let nextSlot = 0;
100
+ /**
101
+ * Hands every key in the pass a slot, keeping the one it had.
102
+ *
103
+ * The slots of the keys that left are handed out in the order their keys were rendered, to the
104
+ * arriving keys in the order they will be: a window that moved wholesale therefore keeps every
105
+ * slot in place, and a window that moved by a row moves one element.
106
+ */
107
+ const assignSlots = (layoutInfos) => {
108
+ const next = /* @__PURE__ */ new Map();
109
+ const arriving = [];
110
+ for (const { key } of layoutInfos) {
111
+ const slot = slotByKey.get(key);
112
+ if (slot == null) arriving.push(key);
113
+ else next.set(key, slot);
114
+ }
115
+ const freed = [];
116
+ for (const [key, slot] of slotByKey) if (!next.has(key)) freed.push(slot);
117
+ for (const key of arriving) next.set(key, freed.length > 0 ? freed.shift() : nextSlot++);
118
+ slotByKey = next;
119
+ return next;
120
+ };
97
121
  /**
98
122
  * The layout infos arrive parents first, so a child always finds its parent already built. One
99
123
  * whose parent is not in the window is treated as a root rather than dropped — losing it would
@@ -104,13 +128,15 @@ var useVirtualizer = (options) => {
104
128
  const collection = options.collection();
105
129
  const views = /* @__PURE__ */ new Map();
106
130
  const roots = [];
131
+ const slots = assignSlots(layoutInfos);
107
132
  for (const layoutInfo of layoutInfos) {
108
133
  const view = {
109
134
  children: [],
110
135
  key: layoutInfo.key,
111
136
  layoutInfo,
112
137
  node: collection.getNode(layoutInfo.key),
113
- parentKey: layoutInfo.parentKey
138
+ parentKey: layoutInfo.parentKey,
139
+ slot: slots.get(layoutInfo.key)
114
140
  };
115
141
  views.set(view.key, view);
116
142
  const parent = layoutInfo.parentKey != null ? views.get(layoutInfo.parentKey) : void 0;
@@ -127,20 +153,28 @@ var useVirtualizer = (options) => {
127
153
  getLayoutInfo: (key) => pass.value.layout.getLayoutInfo(key),
128
154
  isPersistedKey,
129
155
  isScrolling: computed(() => isScrolling.value),
156
+ scrollAdjustment: computed(() => scrollAdjustment.value),
130
157
  setSize: (next) => {
131
158
  if (!size.value.equals(next)) size.value = next;
132
159
  },
133
160
  setVisibleRect: (rect) => {
134
161
  if (visibleRect.value.equals(rect)) return;
135
- overscan.setVisibleRect(rect);
136
162
  visibleRect.value = rect;
137
163
  },
138
164
  size: computed(() => size.value),
139
165
  startScrolling: () => {
140
166
  isScrolling.value = true;
141
167
  },
168
+ takeScrollAdjustment: () => {
169
+ const pending = scrollAdjustment.value;
170
+ scrollAdjustment.value = 0;
171
+ return pending;
172
+ },
142
173
  updateItemSize: (key, measured) => {
143
- if (!pass.value.layout.updateItemSize?.(key, measured)) return;
174
+ const layout = attachedLayout ?? pass.value.layout;
175
+ const placed = layout.getLayoutInfo(key)?.rect;
176
+ if (!layout.updateItemSize?.(key, measured)) return;
177
+ if (placed != null && placed.y < visibleRect.value.y) scrollAdjustment.value += measured.height - placed.height;
144
178
  pendingItemSizeChange = true;
145
179
  revision.value += 1;
146
180
  },