@vizejs/composable 0.426.2 → 0.427.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,359 @@
1
+ import {
2
+ computed,
3
+ hasInjectionContext,
4
+ readonly,
5
+ shallowReadonly,
6
+ shallowRef,
7
+ toValue,
8
+ watch,
9
+ watchPostEffect,
10
+ } from "vue";
11
+ import type { ComputedRef, MaybeRefOrGetter, ShallowRef } from "vue";
12
+
13
+ import { tryOnScopeDispose } from "./scope.ts";
14
+
15
+ /** Device filter for `requestDevice`. */
16
+ export interface HIDDeviceFilter {
17
+ /** USB vendor id. */
18
+ readonly vendorId?: number;
19
+ /** USB product id. */
20
+ readonly productId?: number;
21
+ /** HID usage page. */
22
+ readonly usagePage?: number;
23
+ /** HID usage. */
24
+ readonly usage?: number;
25
+ }
26
+
27
+ /** Minimal `HIDDevice` used by {@link useHID}. */
28
+ export interface HIDDeviceLike extends EventTarget {
29
+ /** Whether the device is open. */
30
+ readonly opened: boolean;
31
+ /** USB vendor id. */
32
+ readonly vendorId: number;
33
+ /** USB product id. */
34
+ readonly productId: number;
35
+ /** Product name. */
36
+ readonly productName: string;
37
+ /** Open the device. */
38
+ open(): Promise<void>;
39
+ /** Close the device. */
40
+ close(): Promise<void>;
41
+ /** Send an output report. */
42
+ sendReport(reportId: number, data: BufferSource): Promise<void>;
43
+ /** Send a feature report. */
44
+ sendFeatureReport(reportId: number, data: BufferSource): Promise<void>;
45
+ /** Read a feature report. */
46
+ receiveFeatureReport(reportId: number): Promise<DataView>;
47
+ }
48
+
49
+ /** `navigator.hid`-like capability used by {@link useHID}. */
50
+ export interface HIDHost extends EventTarget {
51
+ /** Devices the page already has access to. */
52
+ getDevices(): Promise<HIDDeviceLike[]>;
53
+ /** Prompt the user for devices. */
54
+ requestDevice(options: { readonly filters: HIDDeviceFilter[] }): Promise<HIDDeviceLike[]>;
55
+ }
56
+
57
+ /** Plain, reactive-friendly description of a granted device. */
58
+ export interface HIDDeviceInfo {
59
+ /** The live device, for passing back to the actions. */
60
+ readonly device: HIDDeviceLike;
61
+ /** USB vendor id. */
62
+ readonly vendorId: number;
63
+ /** USB product id. */
64
+ readonly productId: number;
65
+ /** Product name. */
66
+ readonly productName: string;
67
+ /** Whether the device was open when the list was refreshed. */
68
+ readonly opened: boolean;
69
+ }
70
+
71
+ /** An input report received from an open device. */
72
+ export interface HIDInputReport {
73
+ /** Device that sent the report. */
74
+ readonly device: HIDDeviceLike;
75
+ /** Report id (`0` when the device does not use report ids). */
76
+ readonly reportId: number;
77
+ /** Report payload. */
78
+ readonly data: DataView;
79
+ }
80
+
81
+ /** Options for {@link useHID}. */
82
+ export interface UseHIDOptions {
83
+ /**
84
+ * `navigator.hid`-like capability.
85
+ *
86
+ * @default window.navigator.hid when it exists
87
+ */
88
+ readonly host?: MaybeRefOrGetter<HIDHost | null | undefined>;
89
+
90
+ /**
91
+ * Receives input reports from every device opened through {@link HIDControls.open}.
92
+ *
93
+ * @default undefined
94
+ */
95
+ readonly onInputReport?: (report: HIDInputReport) => void;
96
+ }
97
+
98
+ /** Reactive state and actions returned by {@link useHID}. */
99
+ export interface HIDControls {
100
+ /** Whether WebHID is available. */
101
+ readonly supported: ComputedRef<boolean>;
102
+ /** Granted devices, refreshed on `connect` / `disconnect`, open and close. */
103
+ readonly devices: Readonly<ShallowRef<readonly HIDDeviceInfo[]>>;
104
+ /** Most recent failure. */
105
+ readonly error: Readonly<ShallowRef<unknown>>;
106
+ /**
107
+ * Prompt the user for devices (requires user activation).
108
+ *
109
+ * @returns The chosen devices (empty when cancelled or failed).
110
+ */
111
+ readonly requestDevice: (filters?: HIDDeviceFilter[]) => Promise<readonly HIDDeviceLike[]>;
112
+ /**
113
+ * Refresh `devices`.
114
+ *
115
+ * @returns The granted devices.
116
+ */
117
+ readonly getDevices: () => Promise<readonly HIDDeviceInfo[]>;
118
+ /**
119
+ * Open a device and start forwarding its input reports.
120
+ *
121
+ * @returns Whether the device is open.
122
+ */
123
+ readonly open: (device: HIDDeviceLike) => Promise<boolean>;
124
+ /**
125
+ * Stop forwarding reports and close a device.
126
+ *
127
+ * @returns Whether the device closed.
128
+ */
129
+ readonly close: (device: HIDDeviceLike) => Promise<boolean>;
130
+ /**
131
+ * Send an output report.
132
+ *
133
+ * @returns Whether the report was sent.
134
+ */
135
+ readonly sendReport: (
136
+ device: HIDDeviceLike,
137
+ reportId: number,
138
+ data: BufferSource,
139
+ ) => Promise<boolean>;
140
+ /**
141
+ * Send a feature report.
142
+ *
143
+ * @returns Whether the report was sent.
144
+ */
145
+ readonly sendFeatureReport: (
146
+ device: HIDDeviceLike,
147
+ reportId: number,
148
+ data: BufferSource,
149
+ ) => Promise<boolean>;
150
+ /**
151
+ * Read a feature report.
152
+ *
153
+ * @returns The report, or `undefined` on failure.
154
+ */
155
+ readonly receiveFeatureReport: (
156
+ device: HIDDeviceLike,
157
+ reportId: number,
158
+ ) => Promise<DataView | undefined>;
159
+ }
160
+
161
+ function browserHIDHost(): HIDHost | undefined {
162
+ if (typeof window === "undefined") return undefined;
163
+ const { navigator } = window;
164
+ // WebHID is not part of the DOM lib; read it through a structural guard.
165
+ const hid: unknown = "hid" in navigator ? navigator.hid : undefined;
166
+ return isHIDHost(hid) ? hid : undefined;
167
+ }
168
+
169
+ function isHIDHost(value: unknown): value is HIDHost {
170
+ return typeof value === "object" && value !== null && "getDevices" in value;
171
+ }
172
+
173
+ function isInputReport(event: Event): event is Event & {
174
+ readonly reportId: number;
175
+ readonly data: DataView;
176
+ } {
177
+ return "reportId" in event && "data" in event;
178
+ }
179
+
180
+ function describe(device: HIDDeviceLike): HIDDeviceInfo {
181
+ return {
182
+ device,
183
+ vendorId: device.vendorId,
184
+ productId: device.productId,
185
+ productName: device.productName,
186
+ opened: device.opened,
187
+ };
188
+ }
189
+
190
+ /**
191
+ * Talk to human-interface devices with the WebHID API.
192
+ *
193
+ * `devices` lists granted devices as plain snapshots and follows the host's
194
+ * `connect` / `disconnect` events. Devices opened through `open()` forward
195
+ * `inputreport` events to `onInputReport`. Every action resolves to a
196
+ * boolean or value and records failures in `error`. Report listeners are
197
+ * removed and opened devices closed when the owning reactive scope stops;
198
+ * outside a scope call `close()` per device.
199
+ *
200
+ * Server rendering: `supported` is false and `devices` is empty.
201
+ * Inside a component the host is resolved after mounting, so hydration
202
+ * renders this server state first.
203
+ *
204
+ * @example
205
+ * ```ts
206
+ * const hid = useHID({ onInputReport: ({ reportId, data }) => read(reportId, data) });
207
+ * const [device] = await hid.requestDevice([{ vendorId: 0x054c }]);
208
+ * if (device) await hid.open(device);
209
+ * ```
210
+ *
211
+ * @param options Host and input report callback.
212
+ * @default options {}
213
+ * @returns HID state and actions.
214
+ */
215
+ export function useHID(options: UseHIDOptions = {}): HIDControls {
216
+ const devices = shallowRef<readonly HIDDeviceInfo[]>([]);
217
+ const error = shallowRef<unknown>(undefined);
218
+ const reportListeners = new Map<HIDDeviceLike, (event: Event) => void>();
219
+ const owned = new Set<HIDDeviceLike>();
220
+
221
+ // Inside a component the host is resolved only after mounting, so a
222
+ // hydrating client renders the server's unsupported state first. Outside
223
+ // components it resolves synchronously.
224
+ const hydrated = shallowRef(!hasInjectionContext());
225
+ if (!hydrated.value) {
226
+ watchPostEffect(() => {
227
+ hydrated.value = true;
228
+ });
229
+ }
230
+
231
+ const resolveHost = (): HIDHost | undefined => {
232
+ if (!hydrated.value) return undefined;
233
+ return options.host === undefined ? browserHIDHost() : (toValue(options.host) ?? undefined);
234
+ };
235
+
236
+ const attempt = async <Value>(
237
+ action: () => Promise<Value>,
238
+ clearError = true,
239
+ ): Promise<Value | undefined> => {
240
+ try {
241
+ const value = await action();
242
+ if (clearError) error.value = undefined;
243
+ return value;
244
+ } catch (cause) {
245
+ error.value = cause;
246
+ return undefined;
247
+ }
248
+ };
249
+
250
+ const getDevices = async (): Promise<readonly HIDDeviceInfo[]> => {
251
+ const host = resolveHost();
252
+ const granted = host ? await attempt(() => host.getDevices(), false) : [];
253
+ if (granted) devices.value = granted.map(describe);
254
+ return devices.value;
255
+ };
256
+
257
+ const requestDevice = async (
258
+ filters: HIDDeviceFilter[] = [],
259
+ ): Promise<readonly HIDDeviceLike[]> => {
260
+ const host = resolveHost();
261
+ if (!host) return [];
262
+ const chosen = await attempt(() => host.requestDevice({ filters }));
263
+ await getDevices();
264
+ return chosen ?? [];
265
+ };
266
+
267
+ const unlisten = (device: HIDDeviceLike): void => {
268
+ const listener = reportListeners.get(device);
269
+ if (!listener) return;
270
+ device.removeEventListener("inputreport", listener);
271
+ reportListeners.delete(device);
272
+ };
273
+
274
+ const open = async (device: HIDDeviceLike): Promise<boolean> => {
275
+ if (!device.opened && (await attempt(() => device.open().then(() => true))) !== true) {
276
+ return false;
277
+ }
278
+ owned.add(device);
279
+ const onInputReport = options.onInputReport;
280
+ if (onInputReport && !reportListeners.has(device)) {
281
+ const listener = (event: Event): void => {
282
+ if (isInputReport(event)) {
283
+ onInputReport({ device, reportId: event.reportId, data: event.data });
284
+ }
285
+ };
286
+ reportListeners.set(device, listener);
287
+ device.addEventListener("inputreport", listener);
288
+ }
289
+ devices.value = devices.value.map((entry) => describe(entry.device));
290
+ return true;
291
+ };
292
+
293
+ const close = async (device: HIDDeviceLike): Promise<boolean> => {
294
+ unlisten(device);
295
+ owned.delete(device);
296
+ const closed =
297
+ !device.opened || (await attempt(() => device.close().then(() => true))) === true;
298
+ devices.value = devices.value.map((entry) => describe(entry.device));
299
+ return closed;
300
+ };
301
+
302
+ const sendReport = async (
303
+ device: HIDDeviceLike,
304
+ reportId: number,
305
+ data: BufferSource,
306
+ ): Promise<boolean> =>
307
+ (await attempt(() => device.sendReport(reportId, data).then(() => true))) === true;
308
+
309
+ const sendFeatureReport = async (
310
+ device: HIDDeviceLike,
311
+ reportId: number,
312
+ data: BufferSource,
313
+ ): Promise<boolean> =>
314
+ (await attempt(() => device.sendFeatureReport(reportId, data).then(() => true))) === true;
315
+
316
+ const receiveFeatureReport = (
317
+ device: HIDDeviceLike,
318
+ reportId: number,
319
+ ): Promise<DataView | undefined> => attempt(() => device.receiveFeatureReport(reportId));
320
+
321
+ const onConnectionChange = (): void => {
322
+ void getDevices();
323
+ };
324
+
325
+ watch(
326
+ resolveHost,
327
+ (host, _previous, onCleanup) => {
328
+ if (!host) {
329
+ devices.value = [];
330
+ return;
331
+ }
332
+ host.addEventListener("connect", onConnectionChange);
333
+ host.addEventListener("disconnect", onConnectionChange);
334
+ onCleanup(() => {
335
+ host.removeEventListener("connect", onConnectionChange);
336
+ host.removeEventListener("disconnect", onConnectionChange);
337
+ });
338
+ void getDevices();
339
+ },
340
+ { immediate: true, flush: "sync" },
341
+ );
342
+
343
+ tryOnScopeDispose(() => {
344
+ for (const device of owned) void close(device);
345
+ });
346
+
347
+ return {
348
+ supported: computed(() => resolveHost() !== undefined),
349
+ devices: shallowReadonly(devices),
350
+ error: readonly(error),
351
+ requestDevice,
352
+ getDevices,
353
+ open,
354
+ close,
355
+ sendReport,
356
+ sendFeatureReport,
357
+ receiveFeatureReport,
358
+ };
359
+ }
@@ -0,0 +1,231 @@
1
+ import { computed, shallowRef, watch } from "vue";
2
+ import type { ComputedRef, Ref, ShallowRef } from "vue";
3
+
4
+ import { tryOnScopeDispose } from "./scope.ts";
5
+
6
+ /** Options for {@link useHistory}. */
7
+ export interface UseHistoryOptions<Value> {
8
+ /**
9
+ * Maximum number of undo entries retained; recording a change beyond it
10
+ * drops the oldest entry. The redo stack is bounded by construction, since
11
+ * redo entries only ever come from undone changes. Must be an integer
12
+ * greater than zero and is fixed at creation.
13
+ *
14
+ * @default 100
15
+ */
16
+ readonly capacity?: number;
17
+
18
+ /**
19
+ * Clone applied to every value captured into history and to every value
20
+ * restored out of it, isolating snapshots from later in-place mutation.
21
+ *
22
+ * @default identity — values are stored and restored by reference
23
+ */
24
+ readonly clone?: (value: Value) => Value;
25
+ }
26
+
27
+ /** Reactive undo/redo controls returned by {@link useHistory}. */
28
+ export interface HistoryControls {
29
+ /** Whether {@link HistoryControls.undo} currently has an entry to restore. */
30
+ readonly canUndo: ComputedRef<boolean>;
31
+
32
+ /** Whether {@link HistoryControls.redo} currently has an entry to restore. */
33
+ readonly canRedo: ComputedRef<boolean>;
34
+
35
+ /** Number of retained undo entries. */
36
+ readonly undoCount: ComputedRef<number>;
37
+
38
+ /** Number of retained redo entries. */
39
+ readonly redoCount: ComputedRef<number>;
40
+
41
+ /**
42
+ * Restore the newest undo entry and move the current value onto the redo
43
+ * stack. The restoring write is not recorded.
44
+ *
45
+ * @returns Whether an entry was restored.
46
+ */
47
+ readonly undo: () => boolean;
48
+
49
+ /**
50
+ * Restore the newest redo entry and move the current value back onto the
51
+ * undo stack. The restoring write is not recorded.
52
+ *
53
+ * @returns Whether an entry was restored.
54
+ */
55
+ readonly redo: () => boolean;
56
+
57
+ /**
58
+ * Group every source write inside `run` into at most one undo entry.
59
+ *
60
+ * The entry restores the value from just before the batch. It is committed
61
+ * only when the final value differs (`Object.is`) from the starting value,
62
+ * and it is committed even when `run` throws, so a partially applied batch
63
+ * stays undoable as one step. Nested calls collapse into the outermost
64
+ * batch. The callback's return value is passed through.
65
+ */
66
+ readonly batch: <Result>(run: () => Result) => Result;
67
+
68
+ /** Drop every undo and redo entry while keeping the current value. */
69
+ readonly clear: () => void;
70
+ }
71
+
72
+ interface HistoryEntry<Value> {
73
+ readonly value: Value;
74
+ }
75
+
76
+ /**
77
+ * Record bounded undo/redo history over the writes of a ref.
78
+ *
79
+ * Recording is shallow and identity-based, matching Vue's own change
80
+ * detection: assignments to `source.value` are recorded (observed with
81
+ * `flush: "sync"`, so every synchronous write counts), writes that are
82
+ * `Object.is`-equal to the current value are not changes, and in-place
83
+ * mutations of object values are invisible — pair mutable values with
84
+ * {@link UseHistoryOptions.clone} and reassign. Undoing and redoing restore
85
+ * values through `clone` as well, so snapshots never share identity with the
86
+ * live value unless the default identity clone is kept. When a
87
+ * user-provided `clone` throws, the failed operation leaves history
88
+ * unchanged and the error propagates.
89
+ *
90
+ * Safe during server rendering: no browser globals are read and no timers
91
+ * start. Cleanup rule: when the owning reactive scope stops, recording stops
92
+ * and every retained snapshot is released, so `undo`/`redo` return `false`
93
+ * afterwards; call inside an active scope, or the watcher lives as long as
94
+ * the source.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const text = shallowRef("");
99
+ * const { undo, redo, batch } = useHistory(text);
100
+ * text.value = "a";
101
+ * batch(() => {
102
+ * text.value = "ab";
103
+ * text.value = "abc";
104
+ * });
105
+ * undo(); // text.value === "a" (the batch is one step)
106
+ * redo(); // text.value === "abc"
107
+ * ```
108
+ *
109
+ * @param source Ref whose writes are recorded.
110
+ * @param options Retention bound and snapshot cloning.
111
+ * @default options {}
112
+ * @throws `RangeError` tagged `VIZE_COMPOSE_HISTORY_INVALID_CAPACITY` when
113
+ * the capacity is not an integer greater than zero.
114
+ * @throws `Error` tagged `VIZE_COMPOSE_HISTORY_IN_BATCH` when `undo`,
115
+ * `redo`, or `clear` is called inside {@link HistoryControls.batch}, where
116
+ * stack movement would corrupt the pending group.
117
+ * @returns Reactive undo/redo state and controls.
118
+ */
119
+ export function useHistory<Value>(
120
+ source: Ref<Value>,
121
+ options: UseHistoryOptions<Value> = {},
122
+ ): HistoryControls {
123
+ const capacity = options.capacity ?? 100;
124
+ if (!Number.isInteger(capacity) || capacity < 1) {
125
+ throw new RangeError(
126
+ `[VIZE_COMPOSE_HISTORY_INVALID_CAPACITY] capacity must be an integer greater than zero; received ${String(capacity)}`,
127
+ );
128
+ }
129
+ const clone = options.clone ?? ((value: Value) => value);
130
+ const undoStack: ShallowRef<readonly HistoryEntry<Value>[]> = shallowRef([]);
131
+ const redoStack: ShallowRef<readonly HistoryEntry<Value>[]> = shallowRef([]);
132
+ let restoring = false;
133
+ let batchDepth = 0;
134
+ let activeBatch: { readonly raw: Value; readonly entry: HistoryEntry<Value> } | undefined;
135
+
136
+ const pushUndo = (entry: HistoryEntry<Value>): void => {
137
+ const next = [...undoStack.value, entry];
138
+ undoStack.value = next.length > capacity ? next.slice(next.length - capacity) : next;
139
+ redoStack.value = [];
140
+ };
141
+
142
+ const writeSilently = (value: Value): void => {
143
+ restoring = true;
144
+ try {
145
+ source.value = value;
146
+ } finally {
147
+ restoring = false;
148
+ }
149
+ };
150
+
151
+ const requireOutsideBatch = (operation: string): void => {
152
+ if (batchDepth > 0) {
153
+ throw new Error(
154
+ `[VIZE_COMPOSE_HISTORY_IN_BATCH] ${operation}() is not available inside batch()`,
155
+ );
156
+ }
157
+ };
158
+
159
+ const undo = (): boolean => {
160
+ requireOutsideBatch("undo");
161
+ const entry = undoStack.value.at(-1);
162
+ if (entry === undefined) return false;
163
+ const restored = clone(entry.value);
164
+ const recorded: HistoryEntry<Value> = { value: clone(source.value) };
165
+ undoStack.value = undoStack.value.slice(0, -1);
166
+ redoStack.value = [...redoStack.value, recorded];
167
+ writeSilently(restored);
168
+ return true;
169
+ };
170
+
171
+ const redo = (): boolean => {
172
+ requireOutsideBatch("redo");
173
+ const entry = redoStack.value.at(-1);
174
+ if (entry === undefined) return false;
175
+ const restored = clone(entry.value);
176
+ const recorded: HistoryEntry<Value> = { value: clone(source.value) };
177
+ redoStack.value = redoStack.value.slice(0, -1);
178
+ undoStack.value = [...undoStack.value, recorded];
179
+ writeSilently(restored);
180
+ return true;
181
+ };
182
+
183
+ const batch = <Result>(run: () => Result): Result => {
184
+ if (batchDepth === 0) {
185
+ activeBatch = { raw: source.value, entry: { value: clone(source.value) } };
186
+ }
187
+ batchDepth += 1;
188
+ try {
189
+ return run();
190
+ } finally {
191
+ batchDepth -= 1;
192
+ if (batchDepth === 0 && activeBatch !== undefined) {
193
+ const finished = activeBatch;
194
+ activeBatch = undefined;
195
+ if (!Object.is(finished.raw, source.value)) pushUndo(finished.entry);
196
+ }
197
+ }
198
+ };
199
+
200
+ const clear = (): void => {
201
+ requireOutsideBatch("clear");
202
+ undoStack.value = [];
203
+ redoStack.value = [];
204
+ };
205
+
206
+ const handle = watch(
207
+ source,
208
+ (_next, replaced) => {
209
+ if (restoring || batchDepth > 0) return;
210
+ pushUndo({ value: clone(replaced) });
211
+ },
212
+ { flush: "sync" },
213
+ );
214
+
215
+ tryOnScopeDispose(() => {
216
+ handle.stop();
217
+ undoStack.value = [];
218
+ redoStack.value = [];
219
+ });
220
+
221
+ return {
222
+ canUndo: computed(() => undoStack.value.length > 0),
223
+ canRedo: computed(() => redoStack.value.length > 0),
224
+ undoCount: computed(() => undoStack.value.length),
225
+ redoCount: computed(() => redoStack.value.length),
226
+ undo,
227
+ redo,
228
+ batch,
229
+ clear,
230
+ };
231
+ }
@@ -0,0 +1,61 @@
1
+ import { hasInjectionContext, useId } from "vue";
2
+
3
+ /** Options for {@link useIdGenerator}. */
4
+ export interface UseIdGeneratorOptions {
5
+ /**
6
+ * Namespace placed in front of every id.
7
+ *
8
+ * @default "vize"
9
+ */
10
+ readonly prefix?: string;
11
+
12
+ /**
13
+ * Stable seed identifying this generator. Defaults to Vue's `useId()`
14
+ * inside a component (identical on server and hydrating client), or to
15
+ * `"root"` outside one.
16
+ *
17
+ * @default useId() or "root"
18
+ */
19
+ readonly seed?: string;
20
+ }
21
+
22
+ /** Id factory returned by {@link useIdGenerator}. */
23
+ export type IdGenerator = (hint?: string) => string;
24
+
25
+ function sanitize(part: string): string {
26
+ return part.replaceAll(/[^\w-]/g, "-");
27
+ }
28
+
29
+ /**
30
+ * Create an SSR-stable id factory for one component.
31
+ *
32
+ * Each call to the returned function yields
33
+ * `<prefix>-<seed>-<hint>-<n>` with a per-generator counter, so as long as
34
+ * ids are generated in the same order on the server and the client (for
35
+ * example during `setup`), the markup hydrates without mismatches. The seed
36
+ * comes from Vue's `useId()` inside components, which is itself stable across
37
+ * SSR and hydration; outside components pass an explicit `seed`. Characters
38
+ * outside `[A-Za-z0-9_-]` are replaced so ids are valid in selectors.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const nextId = useIdGenerator({ prefix: "field" });
43
+ * const inputId = nextId("input"); // "field-v-0-input-0"
44
+ * ```
45
+ *
46
+ * @param options Prefix and seed.
47
+ * @default options {}
48
+ * @returns The id factory.
49
+ */
50
+ export function useIdGenerator(options: UseIdGeneratorOptions = {}): IdGenerator {
51
+ // `hasInjectionContext()` (unlike `getCurrentInstance()`) also detects
52
+ // Vapor components, whose `useId()` is hydration-stable as well.
53
+ const seed = options.seed ?? (hasInjectionContext() ? useId() : "root");
54
+ const base = `${sanitize(options.prefix ?? "vize")}-${sanitize(seed)}`;
55
+ let counter = 0;
56
+ return (hint = "id") => {
57
+ const id = `${base}-${sanitize(hint)}-${counter}`;
58
+ counter += 1;
59
+ return id;
60
+ };
61
+ }