@vizejs/composable 0.426.3 → 0.428.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 (544) hide show
  1. package/dist/abort-signal.d.mts +1 -1
  2. package/dist/active-element.d.mts +37 -0
  3. package/dist/active-element.mjs +56 -0
  4. package/dist/animate.d.mts +114 -0
  5. package/dist/animate.mjs +157 -0
  6. package/dist/battery.d.mts +61 -0
  7. package/dist/battery.mjs +90 -0
  8. package/dist/breakpoints.d.mts +82 -0
  9. package/dist/breakpoints.mjs +91 -0
  10. package/dist/catalog-BeTXFKxF.d.mts +4188 -0
  11. package/dist/catalog-r4Z5nptX.mjs +5144 -0
  12. package/dist/catalog.d.mts +1 -1
  13. package/dist/catalog.mjs +1 -1
  14. package/dist/color-mode.d.mts +131 -0
  15. package/dist/color-mode.mjs +133 -0
  16. package/dist/computed-async.d.mts +63 -0
  17. package/dist/computed-async.mjs +43 -0
  18. package/dist/computed-with-control.d.mts +44 -0
  19. package/dist/computed-with-control.mjs +54 -0
  20. package/dist/create-event-hook.d.mts +77 -0
  21. package/dist/create-event-hook.mjs +66 -0
  22. package/dist/create-global-state.d.mts +24 -0
  23. package/dist/create-global-state.mjs +34 -0
  24. package/dist/create-injection-state.d.mts +51 -0
  25. package/dist/create-injection-state.mjs +19 -0
  26. package/dist/create-shared-composable.d.mts +38 -0
  27. package/dist/create-shared-composable.mjs +54 -0
  28. package/dist/device-motion.d.mts +71 -0
  29. package/dist/device-motion.mjs +75 -0
  30. package/dist/device-orientation.d.mts +82 -0
  31. package/dist/device-orientation.mjs +86 -0
  32. package/dist/device-pixel-ratio.d.mts +45 -0
  33. package/dist/device-pixel-ratio.mjs +50 -0
  34. package/dist/document-visibility.mjs +6 -2
  35. package/dist/draggable.d.mts +121 -0
  36. package/dist/draggable.mjs +153 -0
  37. package/dist/element-bounding.d.mts +87 -0
  38. package/dist/element-bounding.mjs +95 -0
  39. package/dist/element-by-point.d.mts +70 -0
  40. package/dist/element-by-point.mjs +69 -0
  41. package/dist/element-hover.d.mts +42 -0
  42. package/dist/element-hover.mjs +70 -0
  43. package/dist/element-ref.d.mts +34 -0
  44. package/dist/element-ref.mjs +23 -0
  45. package/dist/element-target-Crpxl4D9.d.mts +60 -0
  46. package/dist/element-target.d.mts +2 -0
  47. package/dist/element-target.mjs +58 -0
  48. package/dist/event-listener.mjs +7 -3
  49. package/dist/focus.d.mts +69 -0
  50. package/dist/focus.mjs +124 -0
  51. package/dist/fps.d.mts +59 -0
  52. package/dist/fps.mjs +64 -0
  53. package/dist/geolocation.d.mts +98 -0
  54. package/dist/geolocation.mjs +86 -0
  55. package/dist/i18n.d.mts +237 -0
  56. package/dist/i18n.mjs +215 -0
  57. package/dist/icu-message.d.mts +235 -0
  58. package/dist/icu-message.mjs +343 -0
  59. package/dist/idle.d.mts +79 -0
  60. package/dist/idle.mjs +90 -0
  61. package/dist/index.d.mts +172 -6
  62. package/dist/index.mjs +173 -7
  63. package/dist/infinite-scroll.d.mts +56 -0
  64. package/dist/infinite-scroll.mjs +72 -0
  65. package/dist/intersection-observer.d.mts +122 -0
  66. package/dist/intersection-observer.mjs +117 -0
  67. package/dist/magic-keys.d.mts +121 -0
  68. package/dist/magic-keys.mjs +163 -0
  69. package/dist/math.d.mts +96 -0
  70. package/dist/math.mjs +84 -0
  71. package/dist/media-query.d.mts +3 -1
  72. package/dist/media-query.mjs +5 -3
  73. package/dist/mouse-in-element.d.mts +49 -0
  74. package/dist/mouse-in-element.mjs +66 -0
  75. package/dist/mouse.d.mts +77 -0
  76. package/dist/mouse.mjs +100 -0
  77. package/dist/mutation-observer.d.mts +98 -0
  78. package/dist/mutation-observer.mjs +69 -0
  79. package/dist/network.d.mts +96 -0
  80. package/dist/network.mjs +117 -0
  81. package/dist/on-click-outside.d.mts +69 -0
  82. package/dist/on-click-outside.mjs +115 -0
  83. package/dist/on-key-stroke.d.mts +71 -0
  84. package/dist/on-key-stroke.mjs +79 -0
  85. package/dist/on-long-press.d.mts +82 -0
  86. package/dist/on-long-press.mjs +105 -0
  87. package/dist/on-start-typing.d.mts +44 -0
  88. package/dist/on-start-typing.mjs +61 -0
  89. package/dist/page-leave.d.mts +26 -0
  90. package/dist/page-leave.mjs +40 -0
  91. package/dist/parent-element.d.mts +16 -0
  92. package/dist/parent-element.mjs +27 -0
  93. package/dist/pinch.d.mts +73 -0
  94. package/dist/pinch.mjs +138 -0
  95. package/dist/pointer-lock.d.mts +79 -0
  96. package/dist/pointer-lock.mjs +126 -0
  97. package/dist/pointer.d.mts +78 -0
  98. package/dist/pointer.mjs +95 -0
  99. package/dist/preferences.d.mts +55 -0
  100. package/dist/preferences.mjs +63 -0
  101. package/dist/preferred-languages.d.mts +43 -0
  102. package/dist/preferred-languages.mjs +44 -0
  103. package/dist/reactify.d.mts +28 -0
  104. package/dist/reactify.mjs +7 -0
  105. package/dist/ref-auto-reset.d.mts +47 -0
  106. package/dist/ref-auto-reset.mjs +70 -0
  107. package/dist/ref-debounced.d.mts +29 -0
  108. package/dist/ref-debounced.mjs +29 -0
  109. package/dist/ref-default.d.mts +27 -0
  110. package/dist/ref-default.mjs +33 -0
  111. package/dist/resize-observer.d.mts +96 -0
  112. package/dist/resize-observer.mjs +111 -0
  113. package/dist/resolver.d.mts +124 -0
  114. package/dist/resolver.mjs +138 -0
  115. package/dist/retry-async.d.mts +2 -2
  116. package/dist/retry-delay-DYsdq4SE.d.mts +73 -0
  117. package/dist/retry-delay.d.mts +1 -72
  118. package/dist/screen-orientation.d.mts +77 -0
  119. package/dist/screen-orientation.mjs +74 -0
  120. package/dist/scroll-lock.d.mts +37 -0
  121. package/dist/scroll-lock.mjs +50 -0
  122. package/dist/scroll.d.mts +158 -0
  123. package/dist/scroll.mjs +172 -0
  124. package/dist/standard-schema-DmNgFVK5.d.mts +107 -0
  125. package/dist/standard-schema.d.mts +2 -0
  126. package/dist/standard-schema.mjs +60 -0
  127. package/dist/swipe.d.mts +125 -0
  128. package/dist/swipe.mjs +225 -0
  129. package/dist/sync-ref.d.mts +80 -0
  130. package/dist/sync-ref.mjs +43 -0
  131. package/dist/text-selection.d.mts +46 -0
  132. package/dist/text-selection.mjs +62 -0
  133. package/dist/textarea-autosize.d.mts +58 -0
  134. package/dist/textarea-autosize.mjs +54 -0
  135. package/dist/timeout-scheduler-CI8RVLZs.d.mts +18 -0
  136. package/dist/timeout-scheduler.d.mts +1 -17
  137. package/dist/to-reactive.d.mts +26 -0
  138. package/dist/to-reactive.mjs +46 -0
  139. package/dist/transition.d.mts +125 -0
  140. package/dist/transition.mjs +266 -0
  141. package/dist/until.d.mts +177 -0
  142. package/dist/until.mjs +111 -0
  143. package/dist/use-array.d.mts +112 -0
  144. package/dist/use-array.mjs +90 -0
  145. package/dist/use-async-queue.d.mts +109 -0
  146. package/dist/use-async-queue.mjs +96 -0
  147. package/dist/use-async-state.d.mts +86 -0
  148. package/dist/use-async-state.mjs +41 -0
  149. package/dist/use-barcode-detector.d.mts +159 -0
  150. package/dist/use-barcode-detector.mjs +143 -0
  151. package/dist/use-bluetooth.d.mts +164 -0
  152. package/dist/use-bluetooth.mjs +183 -0
  153. package/dist/use-broadcast-channel.d.mts +115 -0
  154. package/dist/use-broadcast-channel.mjs +121 -0
  155. package/dist/use-builtin-ai.d.mts +342 -0
  156. package/dist/use-builtin-ai.mjs +261 -0
  157. package/dist/use-clipboard.d.mts +169 -0
  158. package/dist/use-clipboard.mjs +226 -0
  159. package/dist/use-compression-stream.d.mts +173 -0
  160. package/dist/use-compression-stream.mjs +166 -0
  161. package/dist/use-confirm-dialog.d.mts +70 -0
  162. package/dist/use-confirm-dialog.mjs +57 -0
  163. package/dist/use-contact-picker.d.mts +117 -0
  164. package/dist/use-contact-picker.mjs +103 -0
  165. package/dist/use-cookie.d.mts +196 -0
  166. package/dist/use-cookie.mjs +259 -0
  167. package/dist/use-countdown.d.mts +85 -0
  168. package/dist/use-countdown.mjs +74 -0
  169. package/dist/use-css-var.d.mts +96 -0
  170. package/dist/use-css-var.mjs +104 -0
  171. package/dist/use-cycle-list.d.mts +76 -0
  172. package/dist/use-cycle-list.mjs +39 -0
  173. package/dist/use-date-format.d.mts +103 -0
  174. package/dist/use-date-format.mjs +147 -0
  175. package/dist/use-date-time-format.d.mts +75 -0
  176. package/dist/use-date-time-format.mjs +53 -0
  177. package/dist/use-debounced.d.mts +1 -1
  178. package/dist/use-display-media.d.mts +62 -0
  179. package/dist/use-display-media.mjs +46 -0
  180. package/dist/use-display-names.d.mts +75 -0
  181. package/dist/use-display-names.mjs +52 -0
  182. package/dist/use-document-title.d.mts +88 -0
  183. package/dist/use-document-title.mjs +100 -0
  184. package/dist/use-drop-zone.d.mts +128 -0
  185. package/dist/use-drop-zone.mjs +154 -0
  186. package/dist/use-event-source.d.mts +184 -0
  187. package/dist/use-event-source.mjs +226 -0
  188. package/dist/use-eye-dropper.d.mts +79 -0
  189. package/dist/use-eye-dropper.mjs +68 -0
  190. package/dist/use-favicon.d.mts +78 -0
  191. package/dist/use-favicon.mjs +68 -0
  192. package/dist/use-fetch.d.mts +230 -0
  193. package/dist/use-fetch.mjs +263 -0
  194. package/dist/use-field.d.mts +107 -0
  195. package/dist/use-field.mjs +117 -0
  196. package/dist/use-file-dialog.d.mts +139 -0
  197. package/dist/use-file-dialog.mjs +101 -0
  198. package/dist/use-file-system-access.d.mts +184 -0
  199. package/dist/use-file-system-access.mjs +151 -0
  200. package/dist/use-form-field-props.d.mts +235 -0
  201. package/dist/use-form-field-props.mjs +164 -0
  202. package/dist/use-form.d.mts +324 -0
  203. package/dist/use-form.mjs +482 -0
  204. package/dist/use-fullscreen.d.mts +104 -0
  205. package/dist/use-fullscreen.mjs +95 -0
  206. package/dist/use-gamepad.d.mts +242 -0
  207. package/dist/use-gamepad.mjs +218 -0
  208. package/dist/use-hid.d.mts +160 -0
  209. package/dist/use-hid.mjs +156 -0
  210. package/dist/use-id-generator.d.mts +44 -0
  211. package/dist/use-id-generator.mjs +38 -0
  212. package/dist/use-image.d.mts +125 -0
  213. package/dist/use-image.mjs +109 -0
  214. package/dist/use-indexed-db.d.mts +207 -0
  215. package/dist/use-indexed-db.mjs +251 -0
  216. package/dist/use-interval-BA55gTHT.d.mts +140 -0
  217. package/dist/use-interval.d.mts +2 -0
  218. package/dist/use-interval.mjs +100 -0
  219. package/dist/use-list-format.d.mts +60 -0
  220. package/dist/use-list-format.mjs +40 -0
  221. package/dist/use-machine.d.mts +90 -0
  222. package/dist/use-machine.mjs +78 -0
  223. package/dist/use-map.d.mts +90 -0
  224. package/dist/use-map.mjs +70 -0
  225. package/dist/use-media-controls.d.mts +198 -0
  226. package/dist/use-media-controls.mjs +264 -0
  227. package/dist/use-memoize.d.mts +73 -0
  228. package/dist/use-memoize.mjs +28 -0
  229. package/dist/use-mounted.d.mts +24 -0
  230. package/dist/use-mounted.mjs +29 -0
  231. package/dist/use-navigation-api.d.mts +360 -0
  232. package/dist/use-navigation-api.mjs +231 -0
  233. package/dist/use-notification.d.mts +139 -0
  234. package/dist/use-notification.mjs +131 -0
  235. package/dist/use-now.d.mts +137 -0
  236. package/dist/use-now.mjs +44 -0
  237. package/dist/use-number-format.d.mts +73 -0
  238. package/dist/use-number-format.mjs +58 -0
  239. package/dist/use-object-url.d.mts +47 -0
  240. package/dist/use-object-url.mjs +54 -0
  241. package/dist/use-offset-pagination.d.mts +91 -0
  242. package/dist/use-offset-pagination.mjs +80 -0
  243. package/dist/use-payment-request.d.mts +239 -0
  244. package/dist/use-payment-request.mjs +206 -0
  245. package/dist/use-performance-observer.d.mts +285 -0
  246. package/dist/use-performance-observer.mjs +132 -0
  247. package/dist/use-permission.d.mts +99 -0
  248. package/dist/use-permission.mjs +92 -0
  249. package/dist/use-plural-rules.d.mts +79 -0
  250. package/dist/use-plural-rules.mjs +59 -0
  251. package/dist/use-push-subscription.d.mts +154 -0
  252. package/dist/use-push-subscription.mjs +146 -0
  253. package/dist/use-queue.d.mts +89 -0
  254. package/dist/use-queue.mjs +116 -0
  255. package/dist/use-raf-fn.d.mts +87 -0
  256. package/dist/use-raf-fn.mjs +99 -0
  257. package/dist/use-relative-time-format.d.mts +111 -0
  258. package/dist/use-relative-time-format.mjs +119 -0
  259. package/dist/use-request-idle-callback.d.mts +122 -0
  260. package/dist/use-request-idle-callback.mjs +147 -0
  261. package/dist/use-route-query.d.mts +149 -0
  262. package/dist/use-route-query.mjs +86 -0
  263. package/dist/use-scheduler-post-task.d.mts +156 -0
  264. package/dist/use-scheduler-post-task.mjs +182 -0
  265. package/dist/use-screen-details.d.mts +205 -0
  266. package/dist/use-screen-details.mjs +188 -0
  267. package/dist/use-script-tag.d.mts +162 -0
  268. package/dist/use-script-tag.mjs +171 -0
  269. package/dist/use-segmenter.d.mts +78 -0
  270. package/dist/use-segmenter.mjs +66 -0
  271. package/dist/use-selection.d.mts +125 -0
  272. package/dist/use-selection.mjs +77 -0
  273. package/dist/use-serial.d.mts +165 -0
  274. package/dist/use-serial.mjs +205 -0
  275. package/dist/use-service-worker.d.mts +177 -0
  276. package/dist/use-service-worker.mjs +178 -0
  277. package/dist/use-set.d.mts +96 -0
  278. package/dist/use-set.mjs +74 -0
  279. package/dist/use-share.d.mts +92 -0
  280. package/dist/use-share.mjs +99 -0
  281. package/dist/use-sorted-locale.d.mts +62 -0
  282. package/dist/use-sorted-locale.mjs +52 -0
  283. package/dist/use-sorted.d.mts +29 -0
  284. package/dist/use-sorted.mjs +14 -0
  285. package/dist/use-speech-recognition.d.mts +150 -0
  286. package/dist/use-speech-recognition.mjs +168 -0
  287. package/dist/use-speech-synthesis.d.mts +148 -0
  288. package/dist/use-speech-synthesis.mjs +152 -0
  289. package/dist/use-stack.d.mts +83 -0
  290. package/dist/use-stack.mjs +93 -0
  291. package/dist/use-stepper.d.mts +79 -0
  292. package/dist/use-stepper.mjs +52 -0
  293. package/dist/use-storage-estimate.d.mts +151 -0
  294. package/dist/use-storage-estimate.mjs +170 -0
  295. package/dist/use-storage.d.mts +214 -0
  296. package/dist/use-storage.mjs +415 -0
  297. package/dist/use-style-tag.d.mts +102 -0
  298. package/dist/use-style-tag.mjs +91 -0
  299. package/dist/use-supported.d.mts +23 -0
  300. package/dist/use-supported.mjs +26 -0
  301. package/dist/use-throttled.d.mts +1 -1
  302. package/dist/use-time-ago.d.mts +163 -0
  303. package/dist/use-time-ago.mjs +95 -0
  304. package/dist/use-timeout.d.mts +122 -0
  305. package/dist/use-timeout.mjs +65 -0
  306. package/dist/use-url-hash.d.mts +88 -0
  307. package/dist/use-url-hash.mjs +145 -0
  308. package/dist/use-url-search-params.d.mts +223 -0
  309. package/dist/use-url-search-params.mjs +295 -0
  310. package/dist/use-usb.d.mts +212 -0
  311. package/dist/use-usb.mjs +137 -0
  312. package/dist/use-user-activation.d.mts +83 -0
  313. package/dist/use-user-activation.mjs +113 -0
  314. package/dist/use-user-media.d.mts +194 -0
  315. package/dist/use-user-media.mjs +214 -0
  316. package/dist/use-v-model.d.mts +113 -0
  317. package/dist/use-v-model.mjs +40 -0
  318. package/dist/use-vibrate.d.mts +81 -0
  319. package/dist/use-vibrate.mjs +90 -0
  320. package/dist/use-view-transition.d.mts +106 -0
  321. package/dist/use-view-transition.mjs +101 -0
  322. package/dist/use-visual-viewport.d.mts +105 -0
  323. package/dist/use-visual-viewport.mjs +104 -0
  324. package/dist/use-wake-lock.d.mts +96 -0
  325. package/dist/use-wake-lock.mjs +106 -0
  326. package/dist/use-web-authn.d.mts +404 -0
  327. package/dist/use-web-authn.mjs +323 -0
  328. package/dist/use-web-locks.d.mts +180 -0
  329. package/dist/use-web-locks.mjs +136 -0
  330. package/dist/use-web-midi.d.mts +148 -0
  331. package/dist/use-web-midi.mjs +140 -0
  332. package/dist/use-web-vitals.d.mts +142 -0
  333. package/dist/use-web-vitals.mjs +248 -0
  334. package/dist/use-websocket.d.mts +218 -0
  335. package/dist/use-websocket.mjs +257 -0
  336. package/dist/use-worker-fn.d.mts +119 -0
  337. package/dist/use-worker-fn.mjs +162 -0
  338. package/dist/virtual-list.d.mts +105 -0
  339. package/dist/virtual-list.mjs +128 -0
  340. package/dist/watch-debounced.d.mts +84 -0
  341. package/dist/watch-debounced.mjs +84 -0
  342. package/dist/watch-ignorable.d.mts +47 -0
  343. package/dist/watch-ignorable.mjs +61 -0
  344. package/dist/watch-once.d.mts +29 -0
  345. package/dist/watch-once.mjs +10 -0
  346. package/dist/watch-pausable.d.mts +51 -0
  347. package/dist/watch-pausable.mjs +23 -0
  348. package/dist/watch-source.d.mts +29 -0
  349. package/dist/watch-source.mjs +1 -0
  350. package/dist/watch-throttled.d.mts +70 -0
  351. package/dist/watch-throttled.mjs +94 -0
  352. package/dist/whenever.d.mts +39 -0
  353. package/dist/whenever.mjs +41 -0
  354. package/dist/window-size.d.mts +87 -0
  355. package/dist/window-size.mjs +65 -0
  356. package/package.json +846 -5
  357. package/registry/files/abort-signal.ts +292 -0
  358. package/registry/files/active-element.ts +93 -0
  359. package/registry/files/animate.ts +322 -0
  360. package/registry/files/async-resource.ts +190 -0
  361. package/registry/files/battery.ts +166 -0
  362. package/registry/files/breakpoints.ts +166 -0
  363. package/registry/files/capability.ts +171 -0
  364. package/registry/files/color-mode.ts +274 -0
  365. package/registry/files/computed-async.ts +123 -0
  366. package/registry/files/computed-with-control.ts +80 -0
  367. package/registry/files/create-event-hook.ts +139 -0
  368. package/registry/files/create-global-state.ts +34 -0
  369. package/registry/files/create-injection-state.ts +75 -0
  370. package/registry/files/create-shared-composable.ts +74 -0
  371. package/registry/files/device-motion.ts +152 -0
  372. package/registry/files/device-orientation.ts +168 -0
  373. package/registry/files/device-pixel-ratio.ts +100 -0
  374. package/registry/files/disposal-scope.ts +201 -0
  375. package/registry/files/document-visibility.ts +152 -0
  376. package/registry/files/draggable.ts +273 -0
  377. package/registry/files/element-bounding.ts +175 -0
  378. package/registry/files/element-by-point.ts +149 -0
  379. package/registry/files/element-hover.ts +104 -0
  380. package/registry/files/element-ref.ts +58 -0
  381. package/registry/files/element-target.ts +99 -0
  382. package/registry/files/event-listener.ts +188 -0
  383. package/registry/files/focus.ts +181 -0
  384. package/registry/files/fps.ts +133 -0
  385. package/registry/files/geolocation.ts +214 -0
  386. package/registry/files/i18n.ts +524 -0
  387. package/registry/files/icu-message.ts +701 -0
  388. package/registry/files/idle.ts +176 -0
  389. package/registry/files/infinite-scroll.ts +135 -0
  390. package/registry/files/intersection-observer.ts +261 -0
  391. package/registry/files/locale.ts +148 -0
  392. package/registry/files/magic-keys.ts +298 -0
  393. package/registry/files/math.ts +175 -0
  394. package/registry/files/media-query.ts +102 -0
  395. package/registry/files/mouse-in-element.ts +107 -0
  396. package/registry/files/mouse.ts +167 -0
  397. package/registry/files/mutation-observer.ts +183 -0
  398. package/registry/files/network.ts +229 -0
  399. package/registry/files/on-click-outside.ts +178 -0
  400. package/registry/files/on-key-stroke.ts +135 -0
  401. package/registry/files/on-long-press.ts +188 -0
  402. package/registry/files/on-start-typing.ts +88 -0
  403. package/registry/files/page-leave.ts +57 -0
  404. package/registry/files/parent-element.ts +29 -0
  405. package/registry/files/pinch.ts +187 -0
  406. package/registry/files/pointer-lock.ts +232 -0
  407. package/registry/files/pointer.ts +153 -0
  408. package/registry/files/preferences.ts +98 -0
  409. package/registry/files/preferred-languages.ts +88 -0
  410. package/registry/files/reactify.ts +39 -0
  411. package/registry/files/ref-auto-reset.ts +102 -0
  412. package/registry/files/ref-debounced.ts +34 -0
  413. package/registry/files/ref-default.ts +35 -0
  414. package/registry/files/resize-observer.ts +220 -0
  415. package/registry/files/retry-async.ts +261 -0
  416. package/registry/files/retry-delay.ts +132 -0
  417. package/registry/files/scope.ts +21 -0
  418. package/registry/files/screen-orientation.ts +165 -0
  419. package/registry/files/scroll-lock.ts +80 -0
  420. package/registry/files/scroll.ts +338 -0
  421. package/registry/files/standard-schema.ts +163 -0
  422. package/registry/files/swipe.ts +321 -0
  423. package/registry/files/sync-ref.ts +166 -0
  424. package/registry/files/temporal.ts +182 -0
  425. package/registry/files/text-selection.ts +110 -0
  426. package/registry/files/textarea-autosize.ts +114 -0
  427. package/registry/files/timeout-scheduler.ts +16 -0
  428. package/registry/files/to-reactive.ts +44 -0
  429. package/registry/files/transition.ts +271 -0
  430. package/registry/files/until.ts +352 -0
  431. package/registry/files/use-array.ts +201 -0
  432. package/registry/files/use-async-queue.ts +278 -0
  433. package/registry/files/use-async-state.ts +139 -0
  434. package/registry/files/use-barcode-detector.ts +321 -0
  435. package/registry/files/use-bluetooth.ts +409 -0
  436. package/registry/files/use-broadcast-channel.ts +250 -0
  437. package/registry/files/use-builtin-ai.ts +674 -0
  438. package/registry/files/use-clipboard.ts +425 -0
  439. package/registry/files/use-compression-stream.ts +364 -0
  440. package/registry/files/use-confirm-dialog.ts +137 -0
  441. package/registry/files/use-contact-picker.ts +246 -0
  442. package/registry/files/use-cookie.ts +500 -0
  443. package/registry/files/use-countdown.ts +161 -0
  444. package/registry/files/use-counter.ts +147 -0
  445. package/registry/files/use-css-var.ts +191 -0
  446. package/registry/files/use-cycle-list.ts +136 -0
  447. package/registry/files/use-date-format.ts +281 -0
  448. package/registry/files/use-date-time-format.ts +113 -0
  449. package/registry/files/use-debounced.ts +163 -0
  450. package/registry/files/use-display-media.ts +89 -0
  451. package/registry/files/use-display-names.ts +122 -0
  452. package/registry/files/use-document-title.ts +196 -0
  453. package/registry/files/use-drop-zone.ts +287 -0
  454. package/registry/files/use-event-source.ts +470 -0
  455. package/registry/files/use-eye-dropper.ts +134 -0
  456. package/registry/files/use-favicon.ts +140 -0
  457. package/registry/files/use-fetch.ts +578 -0
  458. package/registry/files/use-field.ts +247 -0
  459. package/registry/files/use-file-dialog.ts +257 -0
  460. package/registry/files/use-file-system-access.ts +383 -0
  461. package/registry/files/use-form-field-props.ts +381 -0
  462. package/registry/files/use-form.ts +980 -0
  463. package/registry/files/use-fullscreen.ts +214 -0
  464. package/registry/files/use-gamepad.ts +463 -0
  465. package/registry/files/use-hid.ts +359 -0
  466. package/registry/files/use-history.ts +231 -0
  467. package/registry/files/use-id-generator.ts +61 -0
  468. package/registry/files/use-image.ts +253 -0
  469. package/registry/files/use-indexed-db.ts +508 -0
  470. package/registry/files/use-interval.ts +253 -0
  471. package/registry/files/use-list-format.ts +85 -0
  472. package/registry/files/use-machine.ts +171 -0
  473. package/registry/files/use-map.ts +145 -0
  474. package/registry/files/use-media-controls.ts +545 -0
  475. package/registry/files/use-memoize.ts +118 -0
  476. package/registry/files/use-mounted.ts +30 -0
  477. package/registry/files/use-navigation-api.ts +641 -0
  478. package/registry/files/use-notification.ts +285 -0
  479. package/registry/files/use-now.ts +194 -0
  480. package/registry/files/use-number-format.ts +120 -0
  481. package/registry/files/use-object-url.ts +87 -0
  482. package/registry/files/use-offset-pagination.ts +168 -0
  483. package/registry/files/use-payment-request.ts +465 -0
  484. package/registry/files/use-performance-observer.ts +469 -0
  485. package/registry/files/use-permission.ts +220 -0
  486. package/registry/files/use-plural-rules.ts +134 -0
  487. package/registry/files/use-previous.ts +62 -0
  488. package/registry/files/use-push-subscription.ts +352 -0
  489. package/registry/files/use-queue.ts +197 -0
  490. package/registry/files/use-raf-fn.ts +176 -0
  491. package/registry/files/use-relative-time-format.ts +201 -0
  492. package/registry/files/use-request-idle-callback.ts +278 -0
  493. package/registry/files/use-route-query.ts +300 -0
  494. package/registry/files/use-scheduler-post-task.ts +397 -0
  495. package/registry/files/use-screen-details.ts +393 -0
  496. package/registry/files/use-script-tag.ts +341 -0
  497. package/registry/files/use-segmenter.ts +147 -0
  498. package/registry/files/use-selection.ts +233 -0
  499. package/registry/files/use-serial.ts +404 -0
  500. package/registry/files/use-service-worker.ts +413 -0
  501. package/registry/files/use-set.ts +154 -0
  502. package/registry/files/use-share.ts +168 -0
  503. package/registry/files/use-sorted-locale.ts +130 -0
  504. package/registry/files/use-sorted.ts +49 -0
  505. package/registry/files/use-speech-recognition.ts +357 -0
  506. package/registry/files/use-speech-synthesis.ts +333 -0
  507. package/registry/files/use-stack.ts +164 -0
  508. package/registry/files/use-stepper.ts +166 -0
  509. package/registry/files/use-storage-estimate.ts +352 -0
  510. package/registry/files/use-storage.ts +635 -0
  511. package/registry/files/use-style-tag.ts +200 -0
  512. package/registry/files/use-supported.ts +26 -0
  513. package/registry/files/use-throttled.ts +215 -0
  514. package/registry/files/use-time-ago.ts +276 -0
  515. package/registry/files/use-timeout.ts +218 -0
  516. package/registry/files/use-toggle.ts +54 -0
  517. package/registry/files/use-url-hash.ts +280 -0
  518. package/registry/files/use-url-search-params.ts +497 -0
  519. package/registry/files/use-usb.ts +395 -0
  520. package/registry/files/use-user-activation.ts +215 -0
  521. package/registry/files/use-user-media.ts +422 -0
  522. package/registry/files/use-v-model.ts +210 -0
  523. package/registry/files/use-vibrate.ts +174 -0
  524. package/registry/files/use-view-transition.ts +229 -0
  525. package/registry/files/use-visual-viewport.ts +228 -0
  526. package/registry/files/use-wake-lock.ts +206 -0
  527. package/registry/files/use-web-authn.ts +793 -0
  528. package/registry/files/use-web-locks.ts +363 -0
  529. package/registry/files/use-web-midi.ts +306 -0
  530. package/registry/files/use-web-vitals.ts +409 -0
  531. package/registry/files/use-websocket.ts +553 -0
  532. package/registry/files/use-worker-fn.ts +306 -0
  533. package/registry/files/virtual-list.ts +230 -0
  534. package/registry/files/watch-debounced.ts +206 -0
  535. package/registry/files/watch-ignorable.ts +128 -0
  536. package/registry/files/watch-once.ts +46 -0
  537. package/registry/files/watch-pausable.ts +93 -0
  538. package/registry/files/watch-source.ts +51 -0
  539. package/registry/files/watch-throttled.ts +201 -0
  540. package/registry/files/whenever.ts +70 -0
  541. package/registry/files/window-size.ts +151 -0
  542. package/registry/registry.json +5792 -0
  543. package/dist/catalog-D2AL3xYl.d.mts +0 -523
  544. package/dist/catalog-D5SYCsgW.mjs +0 -549
@@ -0,0 +1,306 @@
1
+ import { readonly, shallowRef, toValue } from "vue";
2
+ import type { MaybeRefOrGetter, Ref } from "vue";
3
+
4
+ import { tryOnScopeDispose } from "./scope.ts";
5
+ import type { TimeoutScheduler } from "./timeout-scheduler.ts";
6
+
7
+ /** Lifecycle status of a {@link useWorkerFn} worker. */
8
+ export type WorkerFnStatus = "idle" | "running" | "success" | "error" | "timeout";
9
+
10
+ /** Minimal dedicated worker used by {@link useWorkerFn}. */
11
+ export interface WorkerLike {
12
+ /** Send a structured-clonable message to the worker. */
13
+ postMessage(message: unknown): void;
14
+ /** Stop the worker immediately. */
15
+ terminate(): void;
16
+ /** Subscribe to `message`, `messageerror`, or `error`. */
17
+ addEventListener(type: "message" | "messageerror" | "error", listener: EventListener): void;
18
+ /** Remove a listener registered with `addEventListener`. */
19
+ removeEventListener(type: "message" | "messageerror" | "error", listener: EventListener): void;
20
+ }
21
+
22
+ /** Constructor creating {@link WorkerLike} instances from a script URL. */
23
+ export type WorkerConstructorLike = new (url: string) => WorkerLike;
24
+
25
+ /** Capabilities needed to run a function in a Blob-URL worker. */
26
+ export interface WorkerFnHost {
27
+ /** Worker constructor (e.g. `Worker`). */
28
+ readonly Worker: WorkerConstructorLike;
29
+ /** Create a URL for the generated worker script (e.g. `URL.createObjectURL`). */
30
+ readonly createObjectURL: (script: Blob) => string;
31
+ /** Release a URL returned by `createObjectURL`. */
32
+ readonly revokeObjectURL: (url: string) => void;
33
+ }
34
+
35
+ /** Stable error codes used in {@link useWorkerFn} rejection messages. */
36
+ export type WorkerFnErrorCode =
37
+ | "VIZE_COMPOSE_WORKER_FN_UNSUPPORTED"
38
+ | "VIZE_COMPOSE_WORKER_FN_BUSY"
39
+ | "VIZE_COMPOSE_WORKER_FN_TIMEOUT"
40
+ | "VIZE_COMPOSE_WORKER_FN_TERMINATED"
41
+ | "VIZE_COMPOSE_WORKER_FN_FAILED";
42
+
43
+ /** Options for {@link useWorkerFn}. */
44
+ export interface UseWorkerFnOptions {
45
+ /**
46
+ * Reject and terminate a run after this many milliseconds.
47
+ *
48
+ * @default undefined (no timeout)
49
+ */
50
+ readonly timeoutMs?: number;
51
+
52
+ /**
53
+ * Absolute script URLs loaded with `importScripts` before the function runs.
54
+ *
55
+ * @default []
56
+ */
57
+ readonly dependencies?: readonly string[];
58
+
59
+ /**
60
+ * Named standalone functions inlined into the worker so `fn` can call them.
61
+ *
62
+ * @default []
63
+ */
64
+ readonly localDependencies?: readonly ((...arguments_: never[]) => unknown)[];
65
+
66
+ /**
67
+ * Worker capabilities for alternate runtimes and tests.
68
+ *
69
+ * @default window.Worker and window.URL when a browser window exists
70
+ */
71
+ readonly host?: MaybeRefOrGetter<WorkerFnHost | null | undefined>;
72
+
73
+ /**
74
+ * Timer host for `timeoutMs`.
75
+ *
76
+ * @default globalThis timer functions
77
+ */
78
+ readonly scheduler?: TimeoutScheduler;
79
+ }
80
+
81
+ /** Reactive state and controls returned by {@link useWorkerFn}. */
82
+ export interface WorkerFnControls<Arguments extends readonly unknown[], Result> {
83
+ /** Lifecycle status of the latest run. */
84
+ readonly status: Readonly<Ref<WorkerFnStatus>>;
85
+ /** Whether worker capabilities are available. */
86
+ readonly supported: Readonly<Ref<boolean>>;
87
+ /**
88
+ * Run the function in a fresh worker. Arguments and result must be
89
+ * structured-clonable. Rejects with a tagged `Error` whose message starts
90
+ * with a {@link WorkerFnErrorCode}.
91
+ */
92
+ readonly run: (...arguments_: Arguments) => Promise<Awaited<Result>>;
93
+ /** Terminate the running worker, rejecting its pending run. */
94
+ readonly terminate: () => void;
95
+ }
96
+
97
+ function browserHost(): WorkerFnHost | undefined {
98
+ if (typeof window === "undefined" || typeof window.Worker !== "function") return undefined;
99
+ const { URL: url } = window;
100
+ return {
101
+ Worker: window.Worker,
102
+ createObjectURL: (script) => url.createObjectURL(script),
103
+ revokeObjectURL: (target) => url.revokeObjectURL(target),
104
+ };
105
+ }
106
+
107
+ function defaultScheduler(): TimeoutScheduler {
108
+ return {
109
+ setTimeout: (callback, delayMs) => {
110
+ const handle = globalThis.setTimeout(callback, delayMs);
111
+ return () => globalThis.clearTimeout(handle);
112
+ },
113
+ clearTimeout: (cancel) => {
114
+ if (typeof cancel === "function") cancel();
115
+ },
116
+ };
117
+ }
118
+
119
+ function workerError(code: WorkerFnErrorCode, message: string, cause?: unknown): Error {
120
+ return cause === undefined
121
+ ? new Error(`[${code}] ${message}`)
122
+ : new Error(`[${code}] ${message}`, { cause });
123
+ }
124
+
125
+ /**
126
+ * Build the worker script for `fn`. Exposed for inspection and testing.
127
+ *
128
+ * The function source is embedded with `Function.prototype.toString`, so it
129
+ * must be self-contained: no closures over module variables, only its
130
+ * arguments, `localDependencies`, `dependencies`, and worker globals.
131
+ *
132
+ * @param fn Function to embed.
133
+ * @param options Imported scripts and inlined helper functions.
134
+ * @default options {}
135
+ * @returns JavaScript source for a dedicated worker.
136
+ */
137
+ export function createWorkerFnScript(
138
+ fn: (...arguments_: never[]) => unknown,
139
+ options: Pick<UseWorkerFnOptions, "dependencies" | "localDependencies"> = {},
140
+ ): string {
141
+ const imports = (options.dependencies ?? []).map((url) => JSON.stringify(url)).join(", ");
142
+ const helpers = (options.localDependencies ?? [])
143
+ .map((helper) => {
144
+ if (helper.name === "") {
145
+ throw new TypeError(
146
+ "[VIZE_COMPOSE_WORKER_FN_ANONYMOUS_DEPENDENCY] localDependencies must be named functions",
147
+ );
148
+ }
149
+ return `const ${helper.name} = ${helper.toString()};`;
150
+ })
151
+ .join("\n");
152
+ return [
153
+ imports === "" ? "" : `importScripts(${imports});`,
154
+ helpers,
155
+ `const __vizeWorkerFn = (${fn.toString()});`,
156
+ "self.onmessage = async (event) => {",
157
+ " try {",
158
+ ' self.postMessage(["success", await __vizeWorkerFn(...event.data)]);',
159
+ " } catch (error) {",
160
+ ' self.postMessage(["error", error instanceof Error ? error.message : String(error)]);',
161
+ " }",
162
+ "};",
163
+ ]
164
+ .filter((line) => line !== "")
165
+ .join("\n");
166
+ }
167
+
168
+ /**
169
+ * Run a CPU-heavy function in a dedicated Blob-URL worker, off the main thread.
170
+ *
171
+ * Each `run` spawns a fresh worker, posts the arguments, and resolves with the
172
+ * function's (awaited) result; the worker is terminated and its URL revoked
173
+ * once the run settles, times out, or is terminated. Concurrent runs reject
174
+ * with `VIZE_COMPOSE_WORKER_FN_BUSY`. The running worker is terminated when
175
+ * the owning reactive scope stops. Server rendering never spawns workers:
176
+ * `supported` is `false` and `run` rejects with
177
+ * `VIZE_COMPOSE_WORKER_FN_UNSUPPORTED`.
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * const { run, status } = useWorkerFn((values: number[]) =>
182
+ * [...values].sort((a, b) => a - b),
183
+ * );
184
+ * const sorted = await run(bigArray);
185
+ * ```
186
+ *
187
+ * @param fn Self-contained function; see {@link createWorkerFnScript}.
188
+ * @param options Timeout, dependencies, host, and scheduler.
189
+ * @default options {}
190
+ * @throws {RangeError} `[VIZE_COMPOSE_WORKER_FN_INVALID_TIMEOUT]` for an invalid timeout.
191
+ * @returns Reactive status and run controls.
192
+ */
193
+ export function useWorkerFn<Arguments extends readonly unknown[], Result>(
194
+ fn: (...arguments_: Arguments) => Result,
195
+ options: UseWorkerFnOptions = {},
196
+ ): WorkerFnControls<Arguments, Result> {
197
+ const { timeoutMs } = options;
198
+ if (timeoutMs !== undefined && (!Number.isFinite(timeoutMs) || timeoutMs < 0)) {
199
+ throw new RangeError(
200
+ `[VIZE_COMPOSE_WORKER_FN_INVALID_TIMEOUT] timeoutMs must be a finite non-negative number; received ${String(timeoutMs)}`,
201
+ );
202
+ }
203
+ const status = shallowRef<WorkerFnStatus>("idle");
204
+ const resolveHost = (): WorkerFnHost | undefined =>
205
+ options.host === undefined ? browserHost() : (toValue(options.host) ?? undefined);
206
+ const supported = shallowRef(resolveHost() !== undefined);
207
+ const scheduler = options.scheduler ?? defaultScheduler();
208
+ let cancelActive: ((error: Error, next: WorkerFnStatus) => void) | undefined;
209
+
210
+ const run = (...arguments_: Arguments): Promise<Awaited<Result>> => {
211
+ const host = resolveHost();
212
+ supported.value = host !== undefined;
213
+ if (host === undefined) {
214
+ return Promise.reject(
215
+ workerError("VIZE_COMPOSE_WORKER_FN_UNSUPPORTED", "workers are not available"),
216
+ );
217
+ }
218
+ if (cancelActive !== undefined) {
219
+ return Promise.reject(
220
+ workerError("VIZE_COMPOSE_WORKER_FN_BUSY", "a run is already in progress"),
221
+ );
222
+ }
223
+ const script = createWorkerFnScript(fn, options);
224
+ const url = host.createObjectURL(new Blob([script], { type: "text/javascript" }));
225
+ let worker: WorkerLike;
226
+ try {
227
+ worker = new host.Worker(url);
228
+ } catch (cause) {
229
+ host.revokeObjectURL(url);
230
+ status.value = "error";
231
+ return Promise.reject(
232
+ workerError("VIZE_COMPOSE_WORKER_FN_FAILED", "the worker could not start", cause),
233
+ );
234
+ }
235
+ status.value = "running";
236
+
237
+ return new Promise<Awaited<Result>>((resolve, reject) => {
238
+ let timer: unknown;
239
+ const cleanup = (): void => {
240
+ cancelActive = undefined;
241
+ if (timer !== undefined) scheduler.clearTimeout(timer);
242
+ worker.removeEventListener("message", onMessage);
243
+ worker.removeEventListener("messageerror", onFailure);
244
+ worker.removeEventListener("error", onFailure);
245
+ worker.terminate();
246
+ host.revokeObjectURL(url);
247
+ };
248
+ const settleError = (error: Error, next: WorkerFnStatus): void => {
249
+ cleanup();
250
+ status.value = next;
251
+ reject(error);
252
+ };
253
+ const onMessage: EventListener = (event) => {
254
+ const payload: unknown = "data" in event ? event.data : undefined;
255
+ if (!Array.isArray(payload) || payload.length !== 2) return;
256
+ const [kind, value]: readonly unknown[] = payload;
257
+ if (kind === "success") {
258
+ cleanup();
259
+ status.value = "success";
260
+ resolve(workerResult<Result>(value));
261
+ } else {
262
+ settleError(workerError("VIZE_COMPOSE_WORKER_FN_FAILED", String(value)), "error");
263
+ }
264
+ };
265
+ const onFailure: EventListener = (event) => {
266
+ const message =
267
+ "message" in event && typeof event.message === "string" ? event.message : event.type;
268
+ settleError(workerError("VIZE_COMPOSE_WORKER_FN_FAILED", message, event), "error");
269
+ };
270
+ cancelActive = settleError;
271
+ worker.addEventListener("message", onMessage);
272
+ worker.addEventListener("messageerror", onFailure);
273
+ worker.addEventListener("error", onFailure);
274
+ if (timeoutMs !== undefined) {
275
+ timer = scheduler.setTimeout(() => {
276
+ timer = undefined;
277
+ settleError(
278
+ workerError(
279
+ "VIZE_COMPOSE_WORKER_FN_TIMEOUT",
280
+ `the run exceeded ${String(timeoutMs)} ms`,
281
+ ),
282
+ "timeout",
283
+ );
284
+ }, timeoutMs);
285
+ }
286
+ worker.postMessage(arguments_);
287
+ });
288
+ };
289
+
290
+ const terminate = (): void => {
291
+ cancelActive?.(
292
+ workerError("VIZE_COMPOSE_WORKER_FN_TERMINATED", "the worker was terminated"),
293
+ "idle",
294
+ );
295
+ };
296
+
297
+ tryOnScopeDispose(terminate);
298
+
299
+ return { status: readonly(status), supported: readonly(supported), run, terminate };
300
+ }
301
+
302
+ function workerResult<Result>(value: unknown): Awaited<Result> {
303
+ // The worker executes `fn` itself and posts back its awaited return value
304
+ // through structured cloning; the type cannot be re-checked at runtime.
305
+ return value as Awaited<Result>;
306
+ }
@@ -0,0 +1,230 @@
1
+ import { computed, shallowRef, toValue } from "vue";
2
+ import type { ComputedRef, MaybeRefOrGetter } from "vue";
3
+
4
+ import { useElementRef } from "./element-ref.ts";
5
+ import type { ElementRefSetter } from "./element-ref.ts";
6
+ import { useResizeObserver } from "./resize-observer.ts";
7
+ import type { ResizeObserverHost } from "./resize-observer.ts";
8
+
9
+ /** Item size: a fixed size in CSS pixels or a per-item function. */
10
+ export type VirtualItemSize<Item> = number | ((index: number, item: Item) => number);
11
+
12
+ /** Scroll axis of {@link useVirtualList}. */
13
+ export type VirtualListOrientation = "vertical" | "horizontal";
14
+
15
+ /** Options for {@link useVirtualList}. */
16
+ export interface UseVirtualListOptions<Item> {
17
+ /** Item size along the scroll axis. */
18
+ readonly itemSize: VirtualItemSize<Item>;
19
+
20
+ /**
21
+ * Extra items rendered before and after the visible range.
22
+ *
23
+ * @default 5
24
+ */
25
+ readonly overscan?: number;
26
+
27
+ /**
28
+ * Scroll axis.
29
+ *
30
+ * @default "vertical"
31
+ */
32
+ readonly orientation?: VirtualListOrientation;
33
+
34
+ /**
35
+ * Items rendered before the container is measured (every server render).
36
+ * Keeps SSR output deterministic and non-empty for crawlers.
37
+ *
38
+ * @default 10
39
+ */
40
+ readonly initialItemCount?: number;
41
+
42
+ /**
43
+ * Resize-observer capability used to measure the container.
44
+ *
45
+ * @default globalThis when it provides `ResizeObserver`
46
+ */
47
+ readonly host?: MaybeRefOrGetter<ResizeObserverHost | null | undefined>;
48
+ }
49
+
50
+ /** One rendered row/column of {@link useVirtualList}. */
51
+ export interface VirtualListItem<Item> {
52
+ /** Source item. */
53
+ readonly data: Item;
54
+ /** Index in the source list. */
55
+ readonly index: number;
56
+ /** Start offset along the scroll axis. */
57
+ readonly offset: number;
58
+ /** Size along the scroll axis. */
59
+ readonly size: number;
60
+ }
61
+
62
+ /** Inline style for the scroll container. */
63
+ export interface VirtualContainerStyle {
64
+ /** Vertical overflow. */
65
+ readonly overflowY: "auto" | "hidden";
66
+ /** Horizontal overflow. */
67
+ readonly overflowX: "auto" | "hidden";
68
+ }
69
+
70
+ /** Inline style for the inner wrapper that holds the rendered items. */
71
+ export interface VirtualWrapperStyle {
72
+ /** Wrapper width. */
73
+ readonly width: string;
74
+ /** Wrapper height. */
75
+ readonly height: string;
76
+ /** Leading offset (`margin-top` or `margin-left`). */
77
+ readonly marginTop: string;
78
+ /** Leading offset for horizontal lists. */
79
+ readonly marginLeft: string;
80
+ /** Horizontal lists lay items out in a row. */
81
+ readonly display: "block" | "flex";
82
+ }
83
+
84
+ /** State and bindings returned by {@link useVirtualList}. */
85
+ export interface VirtualListControls<Item> {
86
+ /** Items to render. */
87
+ readonly list: ComputedRef<readonly VirtualListItem<Item>[]>;
88
+ /** Total content size along the scroll axis. */
89
+ readonly totalSize: ComputedRef<number>;
90
+ /** Bind on the scroll container: `v-bind="containerProps"`. */
91
+ readonly containerProps: {
92
+ readonly ref: ElementRefSetter;
93
+ readonly onScroll: () => void;
94
+ readonly style: VirtualContainerStyle;
95
+ };
96
+ /** Bind on the inner wrapper: `v-bind="wrapperProps"`. */
97
+ readonly wrapperProps: ComputedRef<{ readonly style: VirtualWrapperStyle }>;
98
+ /** Scroll so that the item at `index` starts at the container edge. */
99
+ readonly scrollTo: (index: number) => void;
100
+ }
101
+
102
+ interface ScrollableElement extends Element {
103
+ scrollTop: number;
104
+ scrollLeft: number;
105
+ readonly clientHeight: number;
106
+ readonly clientWidth: number;
107
+ }
108
+
109
+ /**
110
+ * Render only the visible slice of a long list (fixed or variable item sizes).
111
+ *
112
+ * Offsets are prefix sums recomputed when the items change; the visible range
113
+ * is found by binary search, so scrolling is O(log n). Until the container is
114
+ * measured (always on the server) the first `initialItemCount` items render,
115
+ * so server and first client render match. The container is measured on
116
+ * scroll and via `ResizeObserver`, released with the owning reactive scope.
117
+ *
118
+ * @param items Reactive source list.
119
+ * @param options Item size, overscan, axis, initial count, and capability.
120
+ * @returns Items to render plus container/wrapper bindings.
121
+ */
122
+ export function useVirtualList<Item>(
123
+ items: MaybeRefOrGetter<readonly Item[]>,
124
+ options: UseVirtualListOptions<Item>,
125
+ ): VirtualListControls<Item> {
126
+ const overscan = Math.max(0, Math.floor(options.overscan ?? 5));
127
+ const vertical = (options.orientation ?? "vertical") === "vertical";
128
+ const initialCount = Math.max(0, Math.floor(options.initialItemCount ?? 10));
129
+ const { element: container, setRef } = useElementRef();
130
+ const viewport = shallowRef<number | null>(null);
131
+ const scrollOffset = shallowRef(0);
132
+
133
+ const layout = computed(() => {
134
+ const source = toValue(items);
135
+ const offsets = new Float64Array(source.length + 1);
136
+ const size = options.itemSize;
137
+ for (const [index, item] of source.entries()) {
138
+ const next = typeof size === "number" ? size : size(index, item);
139
+ offsets[index + 1] = (offsets[index] ?? 0) + Math.max(0, next);
140
+ }
141
+ return { source, offsets };
142
+ });
143
+ const totalSize = computed(() => layout.value.offsets[layout.value.source.length] ?? 0);
144
+
145
+ const measure = (): void => {
146
+ const element = container.value;
147
+ if (!element || !isScrollable(element)) return;
148
+ viewport.value = vertical ? element.clientHeight : element.clientWidth;
149
+ scrollOffset.value = vertical ? element.scrollTop : element.scrollLeft;
150
+ };
151
+ useResizeObserver(
152
+ container,
153
+ measure,
154
+ options.host === undefined ? { flush: "sync" } : { host: options.host, flush: "sync" },
155
+ );
156
+
157
+ const range = computed(() => {
158
+ const { source, offsets } = layout.value;
159
+ if (viewport.value === null) return { start: 0, end: Math.min(source.length, initialCount) };
160
+ const first = findIndex(offsets, source.length, scrollOffset.value);
161
+ const last = findIndex(offsets, source.length, scrollOffset.value + viewport.value);
162
+ return {
163
+ start: Math.max(0, first - overscan),
164
+ end: Math.min(source.length, last + 1 + overscan),
165
+ };
166
+ });
167
+
168
+ const list = computed<readonly VirtualListItem<Item>[]>(() => {
169
+ const { source, offsets } = layout.value;
170
+ const { start, end } = range.value;
171
+ return source.slice(start, end).map((data, position) => {
172
+ const index = start + position;
173
+ const offset = offsets[index] ?? 0;
174
+ return { data, index, offset, size: (offsets[index + 1] ?? offset) - offset };
175
+ });
176
+ });
177
+
178
+ const wrapperProps = computed(() => {
179
+ const leading = layout.value.offsets[range.value.start] ?? 0;
180
+ const remaining = `${totalSize.value - leading}px`;
181
+ return {
182
+ style: {
183
+ width: vertical ? "100%" : remaining,
184
+ height: vertical ? remaining : "100%",
185
+ marginTop: vertical ? `${leading}px` : "0px",
186
+ marginLeft: vertical ? "0px" : `${leading}px`,
187
+ display: vertical ? ("block" as const) : ("flex" as const),
188
+ },
189
+ };
190
+ });
191
+
192
+ return {
193
+ list,
194
+ totalSize,
195
+ containerProps: {
196
+ ref: setRef,
197
+ onScroll: measure,
198
+ style: vertical
199
+ ? { overflowY: "auto", overflowX: "hidden" }
200
+ : { overflowY: "hidden", overflowX: "auto" },
201
+ },
202
+ wrapperProps,
203
+ scrollTo: (index) => {
204
+ const element = container.value;
205
+ if (!element || !isScrollable(element)) return;
206
+ const { offsets, source } = layout.value;
207
+ const clamped = Math.min(Math.max(0, Math.floor(index)), source.length);
208
+ const offset = offsets[clamped] ?? 0;
209
+ if (vertical) element.scrollTop = offset;
210
+ else element.scrollLeft = offset;
211
+ measure();
212
+ },
213
+ };
214
+ }
215
+
216
+ /** Largest index whose start offset is ≤ `position`. */
217
+ function findIndex(offsets: Float64Array, count: number, position: number): number {
218
+ let low = 0;
219
+ let high = Math.max(0, count - 1);
220
+ while (low < high) {
221
+ const middle = (low + high + 1) >> 1;
222
+ if ((offsets[middle] ?? 0) <= position) low = middle;
223
+ else high = middle - 1;
224
+ }
225
+ return low;
226
+ }
227
+
228
+ function isScrollable(element: Element): element is ScrollableElement {
229
+ return "scrollTop" in element && "clientHeight" in element;
230
+ }