@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,701 @@
1
+ /**
2
+ * ICU MessageFormat support: a type-level parameter extractor and a small
3
+ * runtime parser/formatter built on `Intl`.
4
+ *
5
+ * The type-level parser reads message string literals and produces the
6
+ * parameter object a message needs, so a typo in a parameter name or a
7
+ * wrong value type fails to compile. The runtime implements the same
8
+ * grammar subset: simple arguments, `number`, `date`, `time`, `plural`
9
+ * (with `offset:` and `=N` cases), `selectordinal`, `select`, nesting, and
10
+ * ICU apostrophe quoting.
11
+ */
12
+
13
+ /* -------------------------------------------------------------------------- */
14
+ /* Type-level parser */
15
+ /* -------------------------------------------------------------------------- */
16
+
17
+ /** Whitespace characters skipped around ICU tokens. */
18
+ type Whitespace = " " | "\n" | "\t" | "\r";
19
+
20
+ /** Remove leading and trailing whitespace from a string literal. */
21
+ type Trim<Text extends string> = Text extends `${Whitespace}${infer Rest}`
22
+ ? Trim<Rest>
23
+ : Text extends `${infer Rest}${Whitespace}`
24
+ ? Trim<Rest>
25
+ : Text;
26
+
27
+ /** Characters that start a quoted literal after an apostrophe. */
28
+ type QuoteStarter = "{" | "}" | "#" | "|";
29
+
30
+ /**
31
+ * One parameter occurrence found while scanning: `[name, value type,
32
+ * whether the occurrence carries a format type]`.
33
+ */
34
+ type Occurrence = readonly [name: string, value: unknown, typed: boolean];
35
+
36
+ /** Value type required by an argument's format type. */
37
+ type ArgumentValue<Kind extends string> = Kind extends
38
+ | "number"
39
+ | "spellout"
40
+ | "ordinal"
41
+ | "duration"
42
+ ? number
43
+ : Kind extends "date" | "time"
44
+ ? Date | number
45
+ : string;
46
+
47
+ /** Skip a quoted literal (the text after `'`) up to its closing apostrophe. */
48
+ type SkipQuoted<Text extends string> = Text extends `${string}'${infer Rest}` ? Rest : "";
49
+
50
+ /**
51
+ * Scan message text, collecting argument occurrences. Plain text is skipped
52
+ * in one step up to the next `{` unless it contains an apostrophe, in which
53
+ * case quoting is handled character by character.
54
+ */
55
+ type Scan<
56
+ Text extends string,
57
+ Found extends Occurrence,
58
+ > = Text extends `${infer Plain}{${infer Rest}`
59
+ ? Plain extends `${string}'${string}`
60
+ ? ScanChars<Text, Found>
61
+ : ScanArgument<Rest, Found>
62
+ : Found;
63
+
64
+ /** Character-level scan used around apostrophes. */
65
+ type ScanChars<Text extends string, Found extends Occurrence> = Text extends `''${infer Rest}`
66
+ ? ScanChars<Rest, Found>
67
+ : Text extends `'${infer Next}${infer Rest}`
68
+ ? Next extends QuoteStarter
69
+ ? Scan<SkipQuoted<Rest>, Found>
70
+ : ScanChars<`${Next}${Rest}`, Found>
71
+ : Text extends `{${infer Rest}`
72
+ ? ScanArgument<Rest, Found>
73
+ : Text extends `${string}${infer Rest}`
74
+ ? Text extends ""
75
+ ? Found
76
+ : ScanChars<Rest, Found>
77
+ : Found;
78
+
79
+ /** Parse the argument that starts after a `{`. */
80
+ type ScanArgument<
81
+ Text extends string,
82
+ Found extends Occurrence,
83
+ > = Text extends `${infer Head}}${infer AfterSimple}`
84
+ ? Head extends `${string},${string}`
85
+ ? Text extends `${infer Name},${infer AfterName}`
86
+ ? ScanFormat<Trim<Name>, AfterName, Found>
87
+ : Found
88
+ : Scan<AfterSimple, Found | readonly [Trim<Head>, string, false]>
89
+ : Found;
90
+
91
+ /** Parse `type[, style]}` or `type, cases}` after an argument name. */
92
+ type ScanFormat<
93
+ Name extends string,
94
+ Text extends string,
95
+ Found extends Occurrence,
96
+ > = Text extends `${infer Kind},${infer AfterKind}`
97
+ ? Kind extends `${string}}${string}`
98
+ ? ScanSimpleFormat<Name, Text, Found>
99
+ : Trim<Kind> extends "plural" | "selectordinal"
100
+ ? ScanCases<SkipOffset<AfterKind>, Name, number, never, Found>
101
+ : Trim<Kind> extends "select"
102
+ ? ScanCases<AfterKind, Name, never, never, Found>
103
+ : AfterKind extends `${string}}${infer Rest}`
104
+ ? Scan<Rest, Found | readonly [Name, ArgumentValue<Trim<Kind>>, true]>
105
+ : Found
106
+ : ScanSimpleFormat<Name, Text, Found>;
107
+
108
+ /** Parse `type}` (a format type without style). */
109
+ type ScanSimpleFormat<
110
+ Name extends string,
111
+ Text extends string,
112
+ Found extends Occurrence,
113
+ > = Text extends `${infer Kind}}${infer Rest}`
114
+ ? Scan<Rest, Found | readonly [Name, ArgumentValue<Trim<Kind>>, true]>
115
+ : Found;
116
+
117
+ /** Drop a plural `offset:N` prefix. */
118
+ type SkipOffset<Text extends string> =
119
+ Trim<Text> extends `offset:${infer Rest}`
120
+ ? Rest extends `${infer _Digits}${Whitespace}${infer Cases}`
121
+ ? Cases
122
+ : Rest
123
+ : Text;
124
+
125
+ /**
126
+ * Parse `key {content} key {content} ... }`. `Value` is the fixed argument
127
+ * type (`number` for plural kinds); for `select` it stays `never` and the
128
+ * case keys are collected in `Keys` instead.
129
+ */
130
+ type ScanCases<
131
+ Text extends string,
132
+ Name extends string,
133
+ Value,
134
+ Keys extends string,
135
+ Found extends Occurrence,
136
+ > =
137
+ Trim<Text> extends `}${infer Rest}`
138
+ ? Scan<Rest, Found | readonly [Name, [Value] extends [never] ? Keys : Value, true]>
139
+ : Trim<Text> extends `${infer Key}{${infer Body}`
140
+ ? TakeBalanced<Body, "", []> extends [infer Content extends string, infer Rest extends string]
141
+ ? ScanCases<Rest, Name, Value, Keys | Trim<Key>, Found | Scan<Content, never>>
142
+ : Found
143
+ : Found;
144
+
145
+ /**
146
+ * Split `content}rest` at the `}` that closes the current case, honoring
147
+ * nested braces and apostrophe quoting. Returns `[content, rest]`.
148
+ */
149
+ type TakeBalanced<
150
+ Text extends string,
151
+ Taken extends string,
152
+ Depth extends readonly unknown[],
153
+ > = Text extends `''${infer Rest}`
154
+ ? TakeBalanced<Rest, `${Taken}''`, Depth>
155
+ : Text extends `'${infer Next}${infer Rest}`
156
+ ? Next extends QuoteStarter
157
+ ? Rest extends `${infer Quoted}'${infer After}`
158
+ ? TakeBalanced<After, `${Taken}'${Next}${Quoted}'`, Depth>
159
+ : [`${Taken}'${Next}${Rest}`, ""]
160
+ : TakeBalanced<`${Next}${Rest}`, `${Taken}'`, Depth>
161
+ : Text extends `{${infer Rest}`
162
+ ? TakeBalanced<Rest, `${Taken}{`, [...Depth, unknown]>
163
+ : Text extends `}${infer Rest}`
164
+ ? Depth extends readonly [unknown, ...infer Outer]
165
+ ? TakeBalanced<Rest, `${Taken}}`, Outer>
166
+ : [Taken, Rest]
167
+ : Text extends `${infer Char}${infer Rest}`
168
+ ? TakeBalanced<Rest, `${Taken}${Char}`, Depth>
169
+ : [Taken, ""];
170
+
171
+ /** Flatten an intersection into a single object type. */
172
+ type Simplify<Value> = { [Key in keyof Value]: Value[Key] } & {};
173
+
174
+ /** Intersect the members of a union. */
175
+ type UnionToIntersection<Union> = (Union extends unknown ? (value: Union) => void : never) extends (
176
+ value: infer Intersection,
177
+ ) => void
178
+ ? Intersection
179
+ : never;
180
+
181
+ /**
182
+ * Value type of one parameter: typed occurrences win over plain `{name}`
183
+ * occurrences and are intersected with each other.
184
+ */
185
+ type ResolveOccurrences<Entries extends Occurrence> = [
186
+ Extract<Entries, readonly [string, unknown, true]>,
187
+ ] extends [never]
188
+ ? string
189
+ : UnionToIntersection<BoxTypedValue<Entries>> extends infer Merged
190
+ ? Merged extends { readonly value: unknown }
191
+ ? Merged["value"]
192
+ : never
193
+ : never;
194
+
195
+ /** Box the value of each typed occurrence (distributive over `Entry`). */
196
+ type BoxTypedValue<Entry extends Occurrence> = Entry extends readonly [string, infer Value, true]
197
+ ? { readonly value: Value }
198
+ : never;
199
+
200
+ /**
201
+ * Every argument occurrence of a message literal as a union of
202
+ * `[name, value type, typed]` tuples. Exposed so that several messages (for
203
+ * example the translations of one key) can be merged with the same
204
+ * "typed occurrence wins" rule through {@link ResolveMessageArguments}.
205
+ */
206
+ export type MessageArguments<Message extends string> = Scan<Message, never>;
207
+
208
+ /**
209
+ * Turn a union of {@link MessageArguments} into a parameter object. Typed
210
+ * occurrences win over plain `{name}` ones; conflicting typed occurrences
211
+ * intersect (and become `never` when incompatible).
212
+ */
213
+ export type ResolveMessageArguments<Entries extends Occurrence> = Simplify<CollectValues<Entries>>;
214
+
215
+ /** One argument occurrence: `[name, value type, whether it is typed]`. */
216
+ export type MessageArgument = Occurrence;
217
+
218
+ /** Distribute a union of occurrences into one value type per name. */
219
+ type CollectValues<Entries extends Occurrence> = {
220
+ [Name in Entries[0]]: ResolveOccurrences<Extract<Entries, readonly [Name, unknown, boolean]>>;
221
+ };
222
+
223
+ /**
224
+ * Parameters a single ICU message needs, extracted from its string literal.
225
+ *
226
+ * - `{name}` → `string`
227
+ * - `{n, number}` (also `spellout`, `ordinal`, `duration`) → `number`
228
+ * - `{d, date}` / `{d, time}` → `Date | number`
229
+ * - `{n, plural, …}` / `{n, selectordinal, …}` → `number`
230
+ * - `{g, select, a {…} b {…} other {…}}` → `"a" | "b" | "other"`
231
+ *
232
+ * Nested arguments inside plural/select cases are collected as well. When
233
+ * a name occurs both plainly and with a type, the typed occurrence wins.
234
+ * A non-literal `string` yields `Record<string, unknown>`.
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * type P = MessageParams<"Hi {name}, {count, plural, one {# item} other {# items}}">;
239
+ * // ^? { name: string; count: number }
240
+ * ```
241
+ */
242
+ export type MessageParams<Message extends string> = string extends Message
243
+ ? Record<string, unknown>
244
+ : Simplify<CollectValues<Scan<Message, never>>>;
245
+
246
+ /** Whether a message literal takes no parameters. */
247
+ export type HasNoParams<Message extends string> = keyof MessageParams<Message> extends never
248
+ ? true
249
+ : false;
250
+
251
+ /* -------------------------------------------------------------------------- */
252
+ /* Runtime parser */
253
+ /* -------------------------------------------------------------------------- */
254
+
255
+ /** Node of a parsed ICU message. */
256
+ export type MessageNode =
257
+ | { readonly kind: "text"; readonly value: string }
258
+ | { readonly kind: "pound" }
259
+ | { readonly kind: "argument"; readonly name: string }
260
+ | {
261
+ readonly kind: "number" | "date" | "time";
262
+ readonly name: string;
263
+ readonly style: string | undefined;
264
+ }
265
+ | {
266
+ readonly kind: "plural" | "selectordinal";
267
+ readonly name: string;
268
+ readonly offset: number;
269
+ readonly cases: Readonly<Record<string, readonly MessageNode[]>>;
270
+ }
271
+ | {
272
+ readonly kind: "select";
273
+ readonly name: string;
274
+ readonly cases: Readonly<Record<string, readonly MessageNode[]>>;
275
+ };
276
+
277
+ /** Error code carried by {@link MessageSyntaxError}. */
278
+ export type MessageSyntaxErrorCode = "VIZE_COMPOSE_ICU_SYNTAX";
279
+
280
+ /** Thrown by {@link parseMessage} for malformed ICU messages. */
281
+ export interface MessageSyntaxError extends SyntaxError {
282
+ /** Stable machine-readable code. */
283
+ readonly code: MessageSyntaxErrorCode;
284
+ /** Character offset of the problem. */
285
+ readonly offset: number;
286
+ }
287
+
288
+ function syntaxError(message: string, offset: number): MessageSyntaxError {
289
+ return Object.assign(
290
+ new SyntaxError(`[VIZE_COMPOSE_ICU_SYNTAX] ${message} at offset ${String(offset)}`),
291
+ { code: "VIZE_COMPOSE_ICU_SYNTAX" as const, offset },
292
+ );
293
+ }
294
+
295
+ const quoteStarters = new Set(["{", "}", "#", "|"]);
296
+
297
+ /**
298
+ * Parse an ICU MessageFormat string into an AST.
299
+ *
300
+ * Supports simple arguments, `number`/`date`/`time` with an optional style,
301
+ * `plural` and `selectordinal` (with `offset:` and `=N` cases), `select`,
302
+ * nesting, `#` inside plural cases, and apostrophe quoting (`''` is a
303
+ * literal apostrophe; `'{…}'` is literal text). Pure and deterministic.
304
+ *
305
+ * @example
306
+ * ```ts
307
+ * parseMessage("{n, plural, one {# item} other {# items}}");
308
+ * ```
309
+ *
310
+ * @param message ICU message source.
311
+ * @throws {@link MessageSyntaxError} tagged `VIZE_COMPOSE_ICU_SYNTAX` for
312
+ * malformed messages, including a plural or select without an `other` case.
313
+ * @returns The parsed nodes.
314
+ */
315
+ export function parseMessage(message: string): MessageNode[] {
316
+ let position = 0;
317
+
318
+ const skipSpace = (): void => {
319
+ while (position < message.length && /\s/.test(message.charAt(position))) position += 1;
320
+ };
321
+
322
+ const readIdentifier = (stops: string): string => {
323
+ const start = position;
324
+ while (position < message.length && !stops.includes(message.charAt(position))) position += 1;
325
+ return message.slice(start, position).trim();
326
+ };
327
+
328
+ const expect = (char: string): void => {
329
+ if (message.charAt(position) !== char) {
330
+ throw syntaxError(`expected "${char}"`, position);
331
+ }
332
+ position += 1;
333
+ };
334
+
335
+ const parseNodes = (inPlural: boolean, nested: boolean): MessageNode[] => {
336
+ const nodes: MessageNode[] = [];
337
+ let text = "";
338
+ const flush = (): void => {
339
+ if (text !== "") nodes.push({ kind: "text", value: text });
340
+ text = "";
341
+ };
342
+ while (position < message.length) {
343
+ const char = message.charAt(position);
344
+ if (char === "'") {
345
+ const next = message.charAt(position + 1);
346
+ if (next === "'") {
347
+ text += "'";
348
+ position += 2;
349
+ } else if (quoteStarters.has(next)) {
350
+ const end = message.indexOf("'", position + 1);
351
+ text += message.slice(position + 1, end === -1 ? message.length : end);
352
+ position = end === -1 ? message.length : end + 1;
353
+ } else {
354
+ text += "'";
355
+ position += 1;
356
+ }
357
+ } else if (char === "{") {
358
+ flush();
359
+ position += 1;
360
+ nodes.push(parseArgument());
361
+ } else if (char === "}") {
362
+ if (!nested) throw syntaxError('unexpected "}"', position);
363
+ break;
364
+ } else if (char === "#" && inPlural) {
365
+ flush();
366
+ nodes.push({ kind: "pound" });
367
+ position += 1;
368
+ } else {
369
+ text += char;
370
+ position += 1;
371
+ }
372
+ }
373
+ flush();
374
+ return nodes;
375
+ };
376
+
377
+ const parseCases = (inPlural: boolean): Record<string, MessageNode[]> => {
378
+ const cases: Record<string, MessageNode[]> = {};
379
+ for (;;) {
380
+ skipSpace();
381
+ if (message.charAt(position) === "}") break;
382
+ const key = readIdentifier("{}");
383
+ if (key === "" || /\s/.test(key)) throw syntaxError("invalid case key", position);
384
+ expect("{");
385
+ cases[key] = parseNodes(inPlural, true);
386
+ expect("}");
387
+ }
388
+ if (cases["other"] === undefined) throw syntaxError('missing "other" case', position);
389
+ return cases;
390
+ };
391
+
392
+ const parseArgument = (): MessageNode => {
393
+ skipSpace();
394
+ const name = readIdentifier(",}");
395
+ if (name === "") throw syntaxError("empty argument name", position);
396
+ if (message.charAt(position) === "}") {
397
+ position += 1;
398
+ return { kind: "argument", name };
399
+ }
400
+ expect(",");
401
+ const kind = readIdentifier(",}");
402
+ let node: MessageNode;
403
+ if (kind === "plural" || kind === "selectordinal") {
404
+ expect(",");
405
+ skipSpace();
406
+ let offset = 0;
407
+ const match = /^offset:\s*(\d+)/.exec(message.slice(position));
408
+ if (match?.[1] !== undefined) {
409
+ offset = Number(match[1]);
410
+ position += match[0].length;
411
+ }
412
+ node = { kind, name, offset, cases: parseCases(true) };
413
+ } else if (kind === "select") {
414
+ expect(",");
415
+ node = { kind, name, cases: parseCases(false) };
416
+ } else if (kind === "number" || kind === "date" || kind === "time") {
417
+ let style: string | undefined;
418
+ if (message.charAt(position) === ",") {
419
+ position += 1;
420
+ style = readIdentifier("}");
421
+ }
422
+ node = { kind, name, style };
423
+ } else {
424
+ throw syntaxError(`unsupported argument type "${kind}"`, position);
425
+ }
426
+ skipSpace();
427
+ expect("}");
428
+ return node;
429
+ };
430
+
431
+ const nodes = parseNodes(false, false);
432
+ return nodes;
433
+ }
434
+
435
+ /* -------------------------------------------------------------------------- */
436
+ /* Runtime formatter */
437
+ /* -------------------------------------------------------------------------- */
438
+
439
+ /** Options for {@link formatMessage} and {@link createMessageFormatter}. */
440
+ export interface FormatMessageOptions {
441
+ /**
442
+ * IANA time zone for `date` and `time` arguments. Fixed by default so
443
+ * server and client render identically.
444
+ *
445
+ * @default "UTC"
446
+ */
447
+ readonly timeZone?: string;
448
+
449
+ /**
450
+ * Named `number` styles usable as `{n, number, name}`.
451
+ *
452
+ * @default {}
453
+ */
454
+ readonly numberFormats?: Readonly<Record<string, Intl.NumberFormatOptions>>;
455
+
456
+ /**
457
+ * Named `date`/`time` styles usable as `{d, date, name}`.
458
+ *
459
+ * @default {}
460
+ */
461
+ readonly dateTimeFormats?: Readonly<Record<string, Intl.DateTimeFormatOptions>>;
462
+ }
463
+
464
+ /** Formats parsed messages for one locale, caching `Intl` objects. */
465
+ export interface MessageFormatter {
466
+ /** Locale the formatter renders in. */
467
+ readonly locale: string;
468
+
469
+ /**
470
+ * Render a message source or pre-parsed nodes.
471
+ *
472
+ * @returns The formatted string.
473
+ */
474
+ readonly format: (
475
+ message: string | readonly MessageNode[],
476
+ params?: Readonly<Record<string, unknown>>,
477
+ ) => string;
478
+ }
479
+
480
+ const dateStyles = new Set(["short", "medium", "long", "full"]);
481
+
482
+ function numberOptions(
483
+ style: string | undefined,
484
+ named: Readonly<Record<string, Intl.NumberFormatOptions>>,
485
+ ): Intl.NumberFormatOptions {
486
+ if (style === undefined) return {};
487
+ const custom = named[style];
488
+ if (custom !== undefined) return custom;
489
+ if (style === "integer") return { maximumFractionDigits: 0 };
490
+ if (style === "percent") return { style: "percent" };
491
+ if (!style.startsWith("::")) return {};
492
+ const options: Intl.NumberFormatOptions = {};
493
+ for (const token of style.slice(2).trim().split(/\s+/)) {
494
+ if (token.startsWith("currency/")) {
495
+ Object.assign(options, { style: "currency", currency: token.slice(9) });
496
+ } else if (token === "percent") {
497
+ Object.assign(options, { style: "percent" });
498
+ } else if (token === "compact-short" || token === "K") {
499
+ Object.assign(options, { notation: "compact", compactDisplay: "short" });
500
+ } else if (token === "compact-long" || token === "KK") {
501
+ Object.assign(options, { notation: "compact", compactDisplay: "long" });
502
+ } else if (token === "group-off" || token === ",_") {
503
+ Object.assign(options, { useGrouping: false });
504
+ } else if (/^\.0*#*$/.test(token)) {
505
+ const minimum = token.slice(1).replaceAll("#", "").length;
506
+ Object.assign(options, {
507
+ minimumFractionDigits: minimum,
508
+ maximumFractionDigits: token.length - 1,
509
+ });
510
+ }
511
+ }
512
+ return options;
513
+ }
514
+
515
+ function dateTimeOptions(
516
+ kind: "date" | "time",
517
+ style: string | undefined,
518
+ named: Readonly<Record<string, Intl.DateTimeFormatOptions>>,
519
+ ): Intl.DateTimeFormatOptions {
520
+ const custom = style === undefined ? undefined : named[style];
521
+ if (custom !== undefined) return custom;
522
+ const resolved = style !== undefined && dateStyles.has(style) ? style : "medium";
523
+ const value =
524
+ resolved === "short" || resolved === "long" || resolved === "full" ? resolved : "medium";
525
+ return kind === "date" ? { dateStyle: value } : { timeStyle: value };
526
+ }
527
+
528
+ /** Stringify an argument value; plain objects use JSON rather than `[object Object]`. */
529
+ function stringify(value: unknown): string {
530
+ if (typeof value === "string") return value;
531
+ if (typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol") {
532
+ return value.toString();
533
+ }
534
+ return typeof value === "function" ? "[function]" : JSON.stringify(value);
535
+ }
536
+
537
+ /**
538
+ * Create a caching formatter for one locale.
539
+ *
540
+ * Parsed messages and `Intl` formatters are cached inside the returned
541
+ * object only (no module state), so one formatter per request or per
542
+ * i18n instance keeps server rendering isolated.
543
+ *
544
+ * @example
545
+ * ```ts
546
+ * const formatter = createMessageFormatter("en");
547
+ * formatter.format("{n, plural, one {# file} other {# files}}", { n: 3 }); // "3 files"
548
+ * ```
549
+ *
550
+ * @param locale BCP 47 locale.
551
+ * @param options Time zone and named formats.
552
+ * @default options {}
553
+ * @returns The formatter.
554
+ */
555
+ export function createMessageFormatter(
556
+ locale: string,
557
+ options: FormatMessageOptions = {},
558
+ ): MessageFormatter {
559
+ const timeZone = options.timeZone ?? "UTC";
560
+ const numberFormats = options.numberFormats ?? {};
561
+ const dateTimeFormats = options.dateTimeFormats ?? {};
562
+ const parsed = new Map<string, readonly MessageNode[]>();
563
+ const numbers = new Map<string, Intl.NumberFormat>();
564
+ const dates = new Map<string, Intl.DateTimeFormat>();
565
+ const plurals = new Map<string, Intl.PluralRules>();
566
+
567
+ const number = (style: string | undefined): Intl.NumberFormat => {
568
+ const key = style ?? "";
569
+ let formatter = numbers.get(key);
570
+ if (formatter === undefined) {
571
+ formatter = new Intl.NumberFormat(locale, numberOptions(style, numberFormats));
572
+ numbers.set(key, formatter);
573
+ }
574
+ return formatter;
575
+ };
576
+ const dateTime = (kind: "date" | "time", style: string | undefined): Intl.DateTimeFormat => {
577
+ const key = `${kind}:${style ?? ""}`;
578
+ let formatter = dates.get(key);
579
+ if (formatter === undefined) {
580
+ formatter = new Intl.DateTimeFormat(locale, {
581
+ ...dateTimeOptions(kind, style, dateTimeFormats),
582
+ timeZone,
583
+ });
584
+ dates.set(key, formatter);
585
+ }
586
+ return formatter;
587
+ };
588
+ const pluralRules = (type: Intl.PluralRuleType): Intl.PluralRules => {
589
+ let rules = plurals.get(type);
590
+ if (rules === undefined) {
591
+ rules = new Intl.PluralRules(locale, { type });
592
+ plurals.set(type, rules);
593
+ }
594
+ return rules;
595
+ };
596
+
597
+ const toNumber = (value: unknown): number => (typeof value === "number" ? value : Number(value));
598
+ const toDate = (value: unknown): Date =>
599
+ value instanceof Date ? value : new Date(typeof value === "number" ? value : String(value));
600
+
601
+ const render = (
602
+ nodes: readonly MessageNode[],
603
+ params: Readonly<Record<string, unknown>>,
604
+ pound: number | undefined,
605
+ ): string => {
606
+ let output = "";
607
+ for (const node of nodes) {
608
+ switch (node.kind) {
609
+ case "text":
610
+ output += node.value;
611
+ break;
612
+ case "pound":
613
+ output += pound === undefined ? "#" : number(undefined).format(pound);
614
+ break;
615
+ case "argument": {
616
+ const value = params[node.name];
617
+ output +=
618
+ value instanceof Date
619
+ ? dateTime("date", undefined).format(value)
620
+ : typeof value === "number"
621
+ ? number(undefined).format(value)
622
+ : value === undefined || value === null
623
+ ? `{${node.name}}`
624
+ : stringify(value);
625
+ break;
626
+ }
627
+ case "number":
628
+ output += number(node.style).format(toNumber(params[node.name]));
629
+ break;
630
+ case "date":
631
+ case "time":
632
+ output += dateTime(node.kind, node.style).format(toDate(params[node.name]));
633
+ break;
634
+ case "plural":
635
+ case "selectordinal": {
636
+ const value = toNumber(params[node.name]);
637
+ const exact = node.cases[`=${String(value)}`];
638
+ const shifted = value - node.offset;
639
+ const category = pluralRules(node.kind === "plural" ? "cardinal" : "ordinal").select(
640
+ shifted,
641
+ );
642
+ const branch = exact ?? node.cases[category] ?? node.cases["other"] ?? [];
643
+ output += render(branch, params, shifted);
644
+ break;
645
+ }
646
+ case "select": {
647
+ const value = String(params[node.name]);
648
+ const branch = node.cases[value] ?? node.cases["other"] ?? [];
649
+ output += render(branch, params, pound);
650
+ break;
651
+ }
652
+ }
653
+ }
654
+ return output;
655
+ };
656
+
657
+ return {
658
+ locale,
659
+ format: (message, params = {}) => {
660
+ let nodes: readonly MessageNode[];
661
+ if (typeof message === "string") {
662
+ const cached = parsed.get(message);
663
+ nodes = cached ?? parseMessage(message);
664
+ if (cached === undefined) parsed.set(message, nodes);
665
+ } else {
666
+ nodes = message;
667
+ }
668
+ return render(nodes, params, undefined);
669
+ },
670
+ };
671
+ }
672
+
673
+ /**
674
+ * Format one ICU message with typed parameters.
675
+ *
676
+ * Parameters are checked against the message literal at compile time via
677
+ * {@link MessageParams}. For repeated formatting prefer
678
+ * {@link createMessageFormatter}, which caches parsing and `Intl` objects.
679
+ * Deterministic: `date`/`time` arguments use `timeZone` (UTC by default).
680
+ *
681
+ * @example
682
+ * ```ts
683
+ * formatMessage("en", "Hello {name}!", { name: "Ada" }); // "Hello Ada!"
684
+ * ```
685
+ *
686
+ * @param locale BCP 47 locale.
687
+ * @param message ICU message.
688
+ * @param params Values for the message's arguments.
689
+ * @param options Time zone and named formats.
690
+ * @default options {}
691
+ * @throws {@link MessageSyntaxError} for malformed messages.
692
+ * @returns The formatted string.
693
+ */
694
+ export function formatMessage<const Message extends string>(
695
+ locale: string,
696
+ message: Message,
697
+ params: MessageParams<Message>,
698
+ options: FormatMessageOptions = {},
699
+ ): string {
700
+ return createMessageFormatter(locale, options).format(message, params);
701
+ }