@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.
- package/dist/abort-signal.d.mts +1 -1
- package/dist/active-element.d.mts +37 -0
- package/dist/active-element.mjs +56 -0
- package/dist/animate.d.mts +114 -0
- package/dist/animate.mjs +157 -0
- package/dist/battery.d.mts +61 -0
- package/dist/battery.mjs +90 -0
- package/dist/breakpoints.d.mts +82 -0
- package/dist/breakpoints.mjs +91 -0
- package/dist/catalog-BeTXFKxF.d.mts +4188 -0
- package/dist/catalog-r4Z5nptX.mjs +5144 -0
- package/dist/catalog.d.mts +1 -1
- package/dist/catalog.mjs +1 -1
- package/dist/color-mode.d.mts +131 -0
- package/dist/color-mode.mjs +133 -0
- package/dist/computed-async.d.mts +63 -0
- package/dist/computed-async.mjs +43 -0
- package/dist/computed-with-control.d.mts +44 -0
- package/dist/computed-with-control.mjs +54 -0
- package/dist/create-event-hook.d.mts +77 -0
- package/dist/create-event-hook.mjs +66 -0
- package/dist/create-global-state.d.mts +24 -0
- package/dist/create-global-state.mjs +34 -0
- package/dist/create-injection-state.d.mts +51 -0
- package/dist/create-injection-state.mjs +19 -0
- package/dist/create-shared-composable.d.mts +38 -0
- package/dist/create-shared-composable.mjs +54 -0
- package/dist/device-motion.d.mts +71 -0
- package/dist/device-motion.mjs +75 -0
- package/dist/device-orientation.d.mts +82 -0
- package/dist/device-orientation.mjs +86 -0
- package/dist/device-pixel-ratio.d.mts +45 -0
- package/dist/device-pixel-ratio.mjs +50 -0
- package/dist/document-visibility.mjs +6 -2
- package/dist/draggable.d.mts +121 -0
- package/dist/draggable.mjs +153 -0
- package/dist/element-bounding.d.mts +87 -0
- package/dist/element-bounding.mjs +95 -0
- package/dist/element-by-point.d.mts +70 -0
- package/dist/element-by-point.mjs +69 -0
- package/dist/element-hover.d.mts +42 -0
- package/dist/element-hover.mjs +70 -0
- package/dist/element-ref.d.mts +34 -0
- package/dist/element-ref.mjs +23 -0
- package/dist/element-target-Crpxl4D9.d.mts +60 -0
- package/dist/element-target.d.mts +2 -0
- package/dist/element-target.mjs +58 -0
- package/dist/event-listener.mjs +7 -3
- package/dist/focus.d.mts +69 -0
- package/dist/focus.mjs +124 -0
- package/dist/fps.d.mts +59 -0
- package/dist/fps.mjs +64 -0
- package/dist/geolocation.d.mts +98 -0
- package/dist/geolocation.mjs +86 -0
- package/dist/i18n.d.mts +237 -0
- package/dist/i18n.mjs +215 -0
- package/dist/icu-message.d.mts +235 -0
- package/dist/icu-message.mjs +343 -0
- package/dist/idle.d.mts +79 -0
- package/dist/idle.mjs +90 -0
- package/dist/index.d.mts +172 -6
- package/dist/index.mjs +173 -7
- package/dist/infinite-scroll.d.mts +56 -0
- package/dist/infinite-scroll.mjs +72 -0
- package/dist/intersection-observer.d.mts +122 -0
- package/dist/intersection-observer.mjs +117 -0
- package/dist/magic-keys.d.mts +121 -0
- package/dist/magic-keys.mjs +163 -0
- package/dist/math.d.mts +96 -0
- package/dist/math.mjs +84 -0
- package/dist/media-query.d.mts +3 -1
- package/dist/media-query.mjs +5 -3
- package/dist/mouse-in-element.d.mts +49 -0
- package/dist/mouse-in-element.mjs +66 -0
- package/dist/mouse.d.mts +77 -0
- package/dist/mouse.mjs +100 -0
- package/dist/mutation-observer.d.mts +98 -0
- package/dist/mutation-observer.mjs +69 -0
- package/dist/network.d.mts +96 -0
- package/dist/network.mjs +117 -0
- package/dist/on-click-outside.d.mts +69 -0
- package/dist/on-click-outside.mjs +115 -0
- package/dist/on-key-stroke.d.mts +71 -0
- package/dist/on-key-stroke.mjs +79 -0
- package/dist/on-long-press.d.mts +82 -0
- package/dist/on-long-press.mjs +105 -0
- package/dist/on-start-typing.d.mts +44 -0
- package/dist/on-start-typing.mjs +61 -0
- package/dist/page-leave.d.mts +26 -0
- package/dist/page-leave.mjs +40 -0
- package/dist/parent-element.d.mts +16 -0
- package/dist/parent-element.mjs +27 -0
- package/dist/pinch.d.mts +73 -0
- package/dist/pinch.mjs +138 -0
- package/dist/pointer-lock.d.mts +79 -0
- package/dist/pointer-lock.mjs +126 -0
- package/dist/pointer.d.mts +78 -0
- package/dist/pointer.mjs +95 -0
- package/dist/preferences.d.mts +55 -0
- package/dist/preferences.mjs +63 -0
- package/dist/preferred-languages.d.mts +43 -0
- package/dist/preferred-languages.mjs +44 -0
- package/dist/reactify.d.mts +28 -0
- package/dist/reactify.mjs +7 -0
- package/dist/ref-auto-reset.d.mts +47 -0
- package/dist/ref-auto-reset.mjs +70 -0
- package/dist/ref-debounced.d.mts +29 -0
- package/dist/ref-debounced.mjs +29 -0
- package/dist/ref-default.d.mts +27 -0
- package/dist/ref-default.mjs +33 -0
- package/dist/resize-observer.d.mts +96 -0
- package/dist/resize-observer.mjs +111 -0
- package/dist/resolver.d.mts +124 -0
- package/dist/resolver.mjs +138 -0
- package/dist/retry-async.d.mts +2 -2
- package/dist/retry-delay-DYsdq4SE.d.mts +73 -0
- package/dist/retry-delay.d.mts +1 -72
- package/dist/screen-orientation.d.mts +77 -0
- package/dist/screen-orientation.mjs +74 -0
- package/dist/scroll-lock.d.mts +37 -0
- package/dist/scroll-lock.mjs +50 -0
- package/dist/scroll.d.mts +158 -0
- package/dist/scroll.mjs +172 -0
- package/dist/standard-schema-DmNgFVK5.d.mts +107 -0
- package/dist/standard-schema.d.mts +2 -0
- package/dist/standard-schema.mjs +60 -0
- package/dist/swipe.d.mts +125 -0
- package/dist/swipe.mjs +225 -0
- package/dist/sync-ref.d.mts +80 -0
- package/dist/sync-ref.mjs +43 -0
- package/dist/text-selection.d.mts +46 -0
- package/dist/text-selection.mjs +62 -0
- package/dist/textarea-autosize.d.mts +58 -0
- package/dist/textarea-autosize.mjs +54 -0
- package/dist/timeout-scheduler-CI8RVLZs.d.mts +18 -0
- package/dist/timeout-scheduler.d.mts +1 -17
- package/dist/to-reactive.d.mts +26 -0
- package/dist/to-reactive.mjs +46 -0
- package/dist/transition.d.mts +125 -0
- package/dist/transition.mjs +266 -0
- package/dist/until.d.mts +177 -0
- package/dist/until.mjs +111 -0
- package/dist/use-array.d.mts +112 -0
- package/dist/use-array.mjs +90 -0
- package/dist/use-async-queue.d.mts +109 -0
- package/dist/use-async-queue.mjs +96 -0
- package/dist/use-async-state.d.mts +86 -0
- package/dist/use-async-state.mjs +41 -0
- package/dist/use-barcode-detector.d.mts +159 -0
- package/dist/use-barcode-detector.mjs +143 -0
- package/dist/use-bluetooth.d.mts +164 -0
- package/dist/use-bluetooth.mjs +183 -0
- package/dist/use-broadcast-channel.d.mts +115 -0
- package/dist/use-broadcast-channel.mjs +121 -0
- package/dist/use-builtin-ai.d.mts +342 -0
- package/dist/use-builtin-ai.mjs +261 -0
- package/dist/use-clipboard.d.mts +169 -0
- package/dist/use-clipboard.mjs +226 -0
- package/dist/use-compression-stream.d.mts +173 -0
- package/dist/use-compression-stream.mjs +166 -0
- package/dist/use-confirm-dialog.d.mts +70 -0
- package/dist/use-confirm-dialog.mjs +57 -0
- package/dist/use-contact-picker.d.mts +117 -0
- package/dist/use-contact-picker.mjs +103 -0
- package/dist/use-cookie.d.mts +196 -0
- package/dist/use-cookie.mjs +259 -0
- package/dist/use-countdown.d.mts +85 -0
- package/dist/use-countdown.mjs +74 -0
- package/dist/use-css-var.d.mts +96 -0
- package/dist/use-css-var.mjs +104 -0
- package/dist/use-cycle-list.d.mts +76 -0
- package/dist/use-cycle-list.mjs +39 -0
- package/dist/use-date-format.d.mts +103 -0
- package/dist/use-date-format.mjs +147 -0
- package/dist/use-date-time-format.d.mts +75 -0
- package/dist/use-date-time-format.mjs +53 -0
- package/dist/use-debounced.d.mts +1 -1
- package/dist/use-display-media.d.mts +62 -0
- package/dist/use-display-media.mjs +46 -0
- package/dist/use-display-names.d.mts +75 -0
- package/dist/use-display-names.mjs +52 -0
- package/dist/use-document-title.d.mts +88 -0
- package/dist/use-document-title.mjs +100 -0
- package/dist/use-drop-zone.d.mts +128 -0
- package/dist/use-drop-zone.mjs +154 -0
- package/dist/use-event-source.d.mts +184 -0
- package/dist/use-event-source.mjs +226 -0
- package/dist/use-eye-dropper.d.mts +79 -0
- package/dist/use-eye-dropper.mjs +68 -0
- package/dist/use-favicon.d.mts +78 -0
- package/dist/use-favicon.mjs +68 -0
- package/dist/use-fetch.d.mts +230 -0
- package/dist/use-fetch.mjs +263 -0
- package/dist/use-field.d.mts +107 -0
- package/dist/use-field.mjs +117 -0
- package/dist/use-file-dialog.d.mts +139 -0
- package/dist/use-file-dialog.mjs +101 -0
- package/dist/use-file-system-access.d.mts +184 -0
- package/dist/use-file-system-access.mjs +151 -0
- package/dist/use-form-field-props.d.mts +235 -0
- package/dist/use-form-field-props.mjs +164 -0
- package/dist/use-form.d.mts +324 -0
- package/dist/use-form.mjs +482 -0
- package/dist/use-fullscreen.d.mts +104 -0
- package/dist/use-fullscreen.mjs +95 -0
- package/dist/use-gamepad.d.mts +242 -0
- package/dist/use-gamepad.mjs +218 -0
- package/dist/use-hid.d.mts +160 -0
- package/dist/use-hid.mjs +156 -0
- package/dist/use-id-generator.d.mts +44 -0
- package/dist/use-id-generator.mjs +38 -0
- package/dist/use-image.d.mts +125 -0
- package/dist/use-image.mjs +109 -0
- package/dist/use-indexed-db.d.mts +207 -0
- package/dist/use-indexed-db.mjs +251 -0
- package/dist/use-interval-BA55gTHT.d.mts +140 -0
- package/dist/use-interval.d.mts +2 -0
- package/dist/use-interval.mjs +100 -0
- package/dist/use-list-format.d.mts +60 -0
- package/dist/use-list-format.mjs +40 -0
- package/dist/use-machine.d.mts +90 -0
- package/dist/use-machine.mjs +78 -0
- package/dist/use-map.d.mts +90 -0
- package/dist/use-map.mjs +70 -0
- package/dist/use-media-controls.d.mts +198 -0
- package/dist/use-media-controls.mjs +264 -0
- package/dist/use-memoize.d.mts +73 -0
- package/dist/use-memoize.mjs +28 -0
- package/dist/use-mounted.d.mts +24 -0
- package/dist/use-mounted.mjs +29 -0
- package/dist/use-navigation-api.d.mts +360 -0
- package/dist/use-navigation-api.mjs +231 -0
- package/dist/use-notification.d.mts +139 -0
- package/dist/use-notification.mjs +131 -0
- package/dist/use-now.d.mts +137 -0
- package/dist/use-now.mjs +44 -0
- package/dist/use-number-format.d.mts +73 -0
- package/dist/use-number-format.mjs +58 -0
- package/dist/use-object-url.d.mts +47 -0
- package/dist/use-object-url.mjs +54 -0
- package/dist/use-offset-pagination.d.mts +91 -0
- package/dist/use-offset-pagination.mjs +80 -0
- package/dist/use-payment-request.d.mts +239 -0
- package/dist/use-payment-request.mjs +206 -0
- package/dist/use-performance-observer.d.mts +285 -0
- package/dist/use-performance-observer.mjs +132 -0
- package/dist/use-permission.d.mts +99 -0
- package/dist/use-permission.mjs +92 -0
- package/dist/use-plural-rules.d.mts +79 -0
- package/dist/use-plural-rules.mjs +59 -0
- package/dist/use-push-subscription.d.mts +154 -0
- package/dist/use-push-subscription.mjs +146 -0
- package/dist/use-queue.d.mts +89 -0
- package/dist/use-queue.mjs +116 -0
- package/dist/use-raf-fn.d.mts +87 -0
- package/dist/use-raf-fn.mjs +99 -0
- package/dist/use-relative-time-format.d.mts +111 -0
- package/dist/use-relative-time-format.mjs +119 -0
- package/dist/use-request-idle-callback.d.mts +122 -0
- package/dist/use-request-idle-callback.mjs +147 -0
- package/dist/use-route-query.d.mts +149 -0
- package/dist/use-route-query.mjs +86 -0
- package/dist/use-scheduler-post-task.d.mts +156 -0
- package/dist/use-scheduler-post-task.mjs +182 -0
- package/dist/use-screen-details.d.mts +205 -0
- package/dist/use-screen-details.mjs +188 -0
- package/dist/use-script-tag.d.mts +162 -0
- package/dist/use-script-tag.mjs +171 -0
- package/dist/use-segmenter.d.mts +78 -0
- package/dist/use-segmenter.mjs +66 -0
- package/dist/use-selection.d.mts +125 -0
- package/dist/use-selection.mjs +77 -0
- package/dist/use-serial.d.mts +165 -0
- package/dist/use-serial.mjs +205 -0
- package/dist/use-service-worker.d.mts +177 -0
- package/dist/use-service-worker.mjs +178 -0
- package/dist/use-set.d.mts +96 -0
- package/dist/use-set.mjs +74 -0
- package/dist/use-share.d.mts +92 -0
- package/dist/use-share.mjs +99 -0
- package/dist/use-sorted-locale.d.mts +62 -0
- package/dist/use-sorted-locale.mjs +52 -0
- package/dist/use-sorted.d.mts +29 -0
- package/dist/use-sorted.mjs +14 -0
- package/dist/use-speech-recognition.d.mts +150 -0
- package/dist/use-speech-recognition.mjs +168 -0
- package/dist/use-speech-synthesis.d.mts +148 -0
- package/dist/use-speech-synthesis.mjs +152 -0
- package/dist/use-stack.d.mts +83 -0
- package/dist/use-stack.mjs +93 -0
- package/dist/use-stepper.d.mts +79 -0
- package/dist/use-stepper.mjs +52 -0
- package/dist/use-storage-estimate.d.mts +151 -0
- package/dist/use-storage-estimate.mjs +170 -0
- package/dist/use-storage.d.mts +214 -0
- package/dist/use-storage.mjs +415 -0
- package/dist/use-style-tag.d.mts +102 -0
- package/dist/use-style-tag.mjs +91 -0
- package/dist/use-supported.d.mts +23 -0
- package/dist/use-supported.mjs +26 -0
- package/dist/use-throttled.d.mts +1 -1
- package/dist/use-time-ago.d.mts +163 -0
- package/dist/use-time-ago.mjs +95 -0
- package/dist/use-timeout.d.mts +122 -0
- package/dist/use-timeout.mjs +65 -0
- package/dist/use-url-hash.d.mts +88 -0
- package/dist/use-url-hash.mjs +145 -0
- package/dist/use-url-search-params.d.mts +223 -0
- package/dist/use-url-search-params.mjs +295 -0
- package/dist/use-usb.d.mts +212 -0
- package/dist/use-usb.mjs +137 -0
- package/dist/use-user-activation.d.mts +83 -0
- package/dist/use-user-activation.mjs +113 -0
- package/dist/use-user-media.d.mts +194 -0
- package/dist/use-user-media.mjs +214 -0
- package/dist/use-v-model.d.mts +113 -0
- package/dist/use-v-model.mjs +40 -0
- package/dist/use-vibrate.d.mts +81 -0
- package/dist/use-vibrate.mjs +90 -0
- package/dist/use-view-transition.d.mts +106 -0
- package/dist/use-view-transition.mjs +101 -0
- package/dist/use-visual-viewport.d.mts +105 -0
- package/dist/use-visual-viewport.mjs +104 -0
- package/dist/use-wake-lock.d.mts +96 -0
- package/dist/use-wake-lock.mjs +106 -0
- package/dist/use-web-authn.d.mts +404 -0
- package/dist/use-web-authn.mjs +323 -0
- package/dist/use-web-locks.d.mts +180 -0
- package/dist/use-web-locks.mjs +136 -0
- package/dist/use-web-midi.d.mts +148 -0
- package/dist/use-web-midi.mjs +140 -0
- package/dist/use-web-vitals.d.mts +142 -0
- package/dist/use-web-vitals.mjs +248 -0
- package/dist/use-websocket.d.mts +218 -0
- package/dist/use-websocket.mjs +257 -0
- package/dist/use-worker-fn.d.mts +119 -0
- package/dist/use-worker-fn.mjs +162 -0
- package/dist/virtual-list.d.mts +105 -0
- package/dist/virtual-list.mjs +128 -0
- package/dist/watch-debounced.d.mts +84 -0
- package/dist/watch-debounced.mjs +84 -0
- package/dist/watch-ignorable.d.mts +47 -0
- package/dist/watch-ignorable.mjs +61 -0
- package/dist/watch-once.d.mts +29 -0
- package/dist/watch-once.mjs +10 -0
- package/dist/watch-pausable.d.mts +51 -0
- package/dist/watch-pausable.mjs +23 -0
- package/dist/watch-source.d.mts +29 -0
- package/dist/watch-source.mjs +1 -0
- package/dist/watch-throttled.d.mts +70 -0
- package/dist/watch-throttled.mjs +94 -0
- package/dist/whenever.d.mts +39 -0
- package/dist/whenever.mjs +41 -0
- package/dist/window-size.d.mts +87 -0
- package/dist/window-size.mjs +65 -0
- package/package.json +846 -5
- package/registry/files/abort-signal.ts +292 -0
- package/registry/files/active-element.ts +93 -0
- package/registry/files/animate.ts +322 -0
- package/registry/files/async-resource.ts +190 -0
- package/registry/files/battery.ts +166 -0
- package/registry/files/breakpoints.ts +166 -0
- package/registry/files/capability.ts +171 -0
- package/registry/files/color-mode.ts +274 -0
- package/registry/files/computed-async.ts +123 -0
- package/registry/files/computed-with-control.ts +80 -0
- package/registry/files/create-event-hook.ts +139 -0
- package/registry/files/create-global-state.ts +34 -0
- package/registry/files/create-injection-state.ts +75 -0
- package/registry/files/create-shared-composable.ts +74 -0
- package/registry/files/device-motion.ts +152 -0
- package/registry/files/device-orientation.ts +168 -0
- package/registry/files/device-pixel-ratio.ts +100 -0
- package/registry/files/disposal-scope.ts +201 -0
- package/registry/files/document-visibility.ts +152 -0
- package/registry/files/draggable.ts +273 -0
- package/registry/files/element-bounding.ts +175 -0
- package/registry/files/element-by-point.ts +149 -0
- package/registry/files/element-hover.ts +104 -0
- package/registry/files/element-ref.ts +58 -0
- package/registry/files/element-target.ts +99 -0
- package/registry/files/event-listener.ts +188 -0
- package/registry/files/focus.ts +181 -0
- package/registry/files/fps.ts +133 -0
- package/registry/files/geolocation.ts +214 -0
- package/registry/files/i18n.ts +524 -0
- package/registry/files/icu-message.ts +701 -0
- package/registry/files/idle.ts +176 -0
- package/registry/files/infinite-scroll.ts +135 -0
- package/registry/files/intersection-observer.ts +261 -0
- package/registry/files/locale.ts +148 -0
- package/registry/files/magic-keys.ts +298 -0
- package/registry/files/math.ts +175 -0
- package/registry/files/media-query.ts +102 -0
- package/registry/files/mouse-in-element.ts +107 -0
- package/registry/files/mouse.ts +167 -0
- package/registry/files/mutation-observer.ts +183 -0
- package/registry/files/network.ts +229 -0
- package/registry/files/on-click-outside.ts +178 -0
- package/registry/files/on-key-stroke.ts +135 -0
- package/registry/files/on-long-press.ts +188 -0
- package/registry/files/on-start-typing.ts +88 -0
- package/registry/files/page-leave.ts +57 -0
- package/registry/files/parent-element.ts +29 -0
- package/registry/files/pinch.ts +187 -0
- package/registry/files/pointer-lock.ts +232 -0
- package/registry/files/pointer.ts +153 -0
- package/registry/files/preferences.ts +98 -0
- package/registry/files/preferred-languages.ts +88 -0
- package/registry/files/reactify.ts +39 -0
- package/registry/files/ref-auto-reset.ts +102 -0
- package/registry/files/ref-debounced.ts +34 -0
- package/registry/files/ref-default.ts +35 -0
- package/registry/files/resize-observer.ts +220 -0
- package/registry/files/retry-async.ts +261 -0
- package/registry/files/retry-delay.ts +132 -0
- package/registry/files/scope.ts +21 -0
- package/registry/files/screen-orientation.ts +165 -0
- package/registry/files/scroll-lock.ts +80 -0
- package/registry/files/scroll.ts +338 -0
- package/registry/files/standard-schema.ts +163 -0
- package/registry/files/swipe.ts +321 -0
- package/registry/files/sync-ref.ts +166 -0
- package/registry/files/temporal.ts +182 -0
- package/registry/files/text-selection.ts +110 -0
- package/registry/files/textarea-autosize.ts +114 -0
- package/registry/files/timeout-scheduler.ts +16 -0
- package/registry/files/to-reactive.ts +44 -0
- package/registry/files/transition.ts +271 -0
- package/registry/files/until.ts +352 -0
- package/registry/files/use-array.ts +201 -0
- package/registry/files/use-async-queue.ts +278 -0
- package/registry/files/use-async-state.ts +139 -0
- package/registry/files/use-barcode-detector.ts +321 -0
- package/registry/files/use-bluetooth.ts +409 -0
- package/registry/files/use-broadcast-channel.ts +250 -0
- package/registry/files/use-builtin-ai.ts +674 -0
- package/registry/files/use-clipboard.ts +425 -0
- package/registry/files/use-compression-stream.ts +364 -0
- package/registry/files/use-confirm-dialog.ts +137 -0
- package/registry/files/use-contact-picker.ts +246 -0
- package/registry/files/use-cookie.ts +500 -0
- package/registry/files/use-countdown.ts +161 -0
- package/registry/files/use-counter.ts +147 -0
- package/registry/files/use-css-var.ts +191 -0
- package/registry/files/use-cycle-list.ts +136 -0
- package/registry/files/use-date-format.ts +281 -0
- package/registry/files/use-date-time-format.ts +113 -0
- package/registry/files/use-debounced.ts +163 -0
- package/registry/files/use-display-media.ts +89 -0
- package/registry/files/use-display-names.ts +122 -0
- package/registry/files/use-document-title.ts +196 -0
- package/registry/files/use-drop-zone.ts +287 -0
- package/registry/files/use-event-source.ts +470 -0
- package/registry/files/use-eye-dropper.ts +134 -0
- package/registry/files/use-favicon.ts +140 -0
- package/registry/files/use-fetch.ts +578 -0
- package/registry/files/use-field.ts +247 -0
- package/registry/files/use-file-dialog.ts +257 -0
- package/registry/files/use-file-system-access.ts +383 -0
- package/registry/files/use-form-field-props.ts +381 -0
- package/registry/files/use-form.ts +980 -0
- package/registry/files/use-fullscreen.ts +214 -0
- package/registry/files/use-gamepad.ts +463 -0
- package/registry/files/use-hid.ts +359 -0
- package/registry/files/use-history.ts +231 -0
- package/registry/files/use-id-generator.ts +61 -0
- package/registry/files/use-image.ts +253 -0
- package/registry/files/use-indexed-db.ts +508 -0
- package/registry/files/use-interval.ts +253 -0
- package/registry/files/use-list-format.ts +85 -0
- package/registry/files/use-machine.ts +171 -0
- package/registry/files/use-map.ts +145 -0
- package/registry/files/use-media-controls.ts +545 -0
- package/registry/files/use-memoize.ts +118 -0
- package/registry/files/use-mounted.ts +30 -0
- package/registry/files/use-navigation-api.ts +641 -0
- package/registry/files/use-notification.ts +285 -0
- package/registry/files/use-now.ts +194 -0
- package/registry/files/use-number-format.ts +120 -0
- package/registry/files/use-object-url.ts +87 -0
- package/registry/files/use-offset-pagination.ts +168 -0
- package/registry/files/use-payment-request.ts +465 -0
- package/registry/files/use-performance-observer.ts +469 -0
- package/registry/files/use-permission.ts +220 -0
- package/registry/files/use-plural-rules.ts +134 -0
- package/registry/files/use-previous.ts +62 -0
- package/registry/files/use-push-subscription.ts +352 -0
- package/registry/files/use-queue.ts +197 -0
- package/registry/files/use-raf-fn.ts +176 -0
- package/registry/files/use-relative-time-format.ts +201 -0
- package/registry/files/use-request-idle-callback.ts +278 -0
- package/registry/files/use-route-query.ts +300 -0
- package/registry/files/use-scheduler-post-task.ts +397 -0
- package/registry/files/use-screen-details.ts +393 -0
- package/registry/files/use-script-tag.ts +341 -0
- package/registry/files/use-segmenter.ts +147 -0
- package/registry/files/use-selection.ts +233 -0
- package/registry/files/use-serial.ts +404 -0
- package/registry/files/use-service-worker.ts +413 -0
- package/registry/files/use-set.ts +154 -0
- package/registry/files/use-share.ts +168 -0
- package/registry/files/use-sorted-locale.ts +130 -0
- package/registry/files/use-sorted.ts +49 -0
- package/registry/files/use-speech-recognition.ts +357 -0
- package/registry/files/use-speech-synthesis.ts +333 -0
- package/registry/files/use-stack.ts +164 -0
- package/registry/files/use-stepper.ts +166 -0
- package/registry/files/use-storage-estimate.ts +352 -0
- package/registry/files/use-storage.ts +635 -0
- package/registry/files/use-style-tag.ts +200 -0
- package/registry/files/use-supported.ts +26 -0
- package/registry/files/use-throttled.ts +215 -0
- package/registry/files/use-time-ago.ts +276 -0
- package/registry/files/use-timeout.ts +218 -0
- package/registry/files/use-toggle.ts +54 -0
- package/registry/files/use-url-hash.ts +280 -0
- package/registry/files/use-url-search-params.ts +497 -0
- package/registry/files/use-usb.ts +395 -0
- package/registry/files/use-user-activation.ts +215 -0
- package/registry/files/use-user-media.ts +422 -0
- package/registry/files/use-v-model.ts +210 -0
- package/registry/files/use-vibrate.ts +174 -0
- package/registry/files/use-view-transition.ts +229 -0
- package/registry/files/use-visual-viewport.ts +228 -0
- package/registry/files/use-wake-lock.ts +206 -0
- package/registry/files/use-web-authn.ts +793 -0
- package/registry/files/use-web-locks.ts +363 -0
- package/registry/files/use-web-midi.ts +306 -0
- package/registry/files/use-web-vitals.ts +409 -0
- package/registry/files/use-websocket.ts +553 -0
- package/registry/files/use-worker-fn.ts +306 -0
- package/registry/files/virtual-list.ts +230 -0
- package/registry/files/watch-debounced.ts +206 -0
- package/registry/files/watch-ignorable.ts +128 -0
- package/registry/files/watch-once.ts +46 -0
- package/registry/files/watch-pausable.ts +93 -0
- package/registry/files/watch-source.ts +51 -0
- package/registry/files/watch-throttled.ts +201 -0
- package/registry/files/whenever.ts +70 -0
- package/registry/files/window-size.ts +151 -0
- package/registry/registry.json +5792 -0
- package/dist/catalog-D2AL3xYl.d.mts +0 -523
- package/dist/catalog-D5SYCsgW.mjs +0 -549
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
hasInjectionContext,
|
|
4
|
+
readonly,
|
|
5
|
+
ref,
|
|
6
|
+
shallowRef,
|
|
7
|
+
toValue,
|
|
8
|
+
watchPostEffect,
|
|
9
|
+
} from "vue";
|
|
10
|
+
import type { ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
|
|
11
|
+
|
|
12
|
+
import { tryOnScopeDispose } from "./scope.ts";
|
|
13
|
+
|
|
14
|
+
/** Lock modes defined by the Web Locks API. */
|
|
15
|
+
export type WebLockMode = "exclusive" | "shared";
|
|
16
|
+
|
|
17
|
+
/** Granted lock handed to a request callback. */
|
|
18
|
+
export interface WebLockLike {
|
|
19
|
+
/** Lock name. */
|
|
20
|
+
readonly name: string;
|
|
21
|
+
|
|
22
|
+
/** Granted mode. */
|
|
23
|
+
readonly mode: WebLockMode;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** One entry of a lock manager snapshot. */
|
|
27
|
+
export interface WebLockInfo {
|
|
28
|
+
/** Lock name. */
|
|
29
|
+
readonly name?: string | undefined;
|
|
30
|
+
|
|
31
|
+
/** Requested or granted mode. */
|
|
32
|
+
readonly mode?: WebLockMode | undefined;
|
|
33
|
+
|
|
34
|
+
/** Identifier of the client holding or requesting the lock. */
|
|
35
|
+
readonly clientId?: string | undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Snapshot returned by {@link WebLocksControls.query}. */
|
|
39
|
+
export interface WebLocksSnapshot {
|
|
40
|
+
/** Locks currently held by any client of the origin. */
|
|
41
|
+
readonly held: readonly WebLockInfo[];
|
|
42
|
+
|
|
43
|
+
/** Requests currently waiting for a lock. */
|
|
44
|
+
readonly pending: readonly WebLockInfo[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Options forwarded to `LockManager.request`. */
|
|
48
|
+
export interface WebLockManagerRequestOptions {
|
|
49
|
+
/** Requested mode. */
|
|
50
|
+
readonly mode: WebLockMode;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Only grant the lock when it is immediately available.
|
|
54
|
+
*
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
readonly ifAvailable?: boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Release any held lock of the same name and grant this request.
|
|
61
|
+
*
|
|
62
|
+
* @default false
|
|
63
|
+
*/
|
|
64
|
+
readonly steal?: boolean;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Abort the request while it is pending.
|
|
68
|
+
*
|
|
69
|
+
* @default undefined
|
|
70
|
+
*/
|
|
71
|
+
readonly signal?: AbortSignal;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Minimal `LockManager` (`navigator.locks`) consumed by {@link useWebLocks}. */
|
|
75
|
+
export interface LockManagerLike {
|
|
76
|
+
/** Request a lock and run `callback` while it is held. */
|
|
77
|
+
request(
|
|
78
|
+
name: string,
|
|
79
|
+
options: WebLockManagerRequestOptions,
|
|
80
|
+
callback: (lock: WebLockLike | null) => unknown,
|
|
81
|
+
): Promise<unknown>;
|
|
82
|
+
|
|
83
|
+
/** Snapshot the origin's held and pending locks. */
|
|
84
|
+
query(): Promise<{
|
|
85
|
+
/** Held locks. */
|
|
86
|
+
readonly held?: readonly WebLockInfo[] | undefined;
|
|
87
|
+
/** Pending requests. */
|
|
88
|
+
readonly pending?: readonly WebLockInfo[] | undefined;
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Options for {@link useWebLocks}. */
|
|
93
|
+
export interface UseWebLocksOptions {
|
|
94
|
+
/**
|
|
95
|
+
* Lock manager for alternate runtimes and tests.
|
|
96
|
+
*
|
|
97
|
+
* @default window.navigator.locks when it exists
|
|
98
|
+
*/
|
|
99
|
+
readonly locks?: MaybeRefOrGetter<LockManagerLike | null | undefined>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Per-request options for {@link WebLocksControls.request}. */
|
|
103
|
+
export interface WebLockRequestOptions {
|
|
104
|
+
/**
|
|
105
|
+
* Requested mode.
|
|
106
|
+
*
|
|
107
|
+
* @default "exclusive"
|
|
108
|
+
*/
|
|
109
|
+
readonly mode?: WebLockMode;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Resolve with `{ acquired: false }` instead of waiting when the lock is busy.
|
|
113
|
+
*
|
|
114
|
+
* @default false
|
|
115
|
+
*/
|
|
116
|
+
readonly ifAvailable?: boolean;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Preempt any holder of the lock (exclusive mode only).
|
|
120
|
+
*
|
|
121
|
+
* @default false
|
|
122
|
+
*/
|
|
123
|
+
readonly steal?: boolean;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Abort the request while it is still pending.
|
|
127
|
+
*
|
|
128
|
+
* @default undefined
|
|
129
|
+
*/
|
|
130
|
+
readonly signal?: AbortSignal;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Outcome of an `ifAvailable` request. */
|
|
134
|
+
export type WebLockAttempt<Value> =
|
|
135
|
+
| {
|
|
136
|
+
/** The lock was granted and the callback ran. */
|
|
137
|
+
readonly acquired: true;
|
|
138
|
+
/** Callback result. */
|
|
139
|
+
readonly value: Value;
|
|
140
|
+
}
|
|
141
|
+
| {
|
|
142
|
+
/** The lock was busy; the callback did not run. */
|
|
143
|
+
readonly acquired: false;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/** Request function exposed by {@link WebLocksControls}. */
|
|
147
|
+
export interface WebLockRequest {
|
|
148
|
+
/**
|
|
149
|
+
* Request a lock that is only granted when immediately available.
|
|
150
|
+
*
|
|
151
|
+
* @param name Lock name.
|
|
152
|
+
* @param callback Work to run while the lock is held.
|
|
153
|
+
* @param options Request options with `ifAvailable: true`.
|
|
154
|
+
* @returns The callback result, or `{ acquired: false }` when busy.
|
|
155
|
+
*/
|
|
156
|
+
<Value>(
|
|
157
|
+
name: string,
|
|
158
|
+
callback: (lock: WebLockLike) => Value | PromiseLike<Value>,
|
|
159
|
+
options: WebLockRequestOptions & { readonly ifAvailable: true },
|
|
160
|
+
): Promise<WebLockAttempt<Value>>;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Request a lock and run `callback` while it is held.
|
|
164
|
+
*
|
|
165
|
+
* @param name Lock name.
|
|
166
|
+
* @param callback Work to run while the lock is held.
|
|
167
|
+
* @param options Mode, steal and abort options.
|
|
168
|
+
* @returns The callback result.
|
|
169
|
+
*/
|
|
170
|
+
<Value>(
|
|
171
|
+
name: string,
|
|
172
|
+
callback: (lock: WebLockLike) => Value | PromiseLike<Value>,
|
|
173
|
+
options?: WebLockRequestOptions & { readonly ifAvailable?: false },
|
|
174
|
+
): Promise<Value>;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Reactive state and actions returned by {@link useWebLocks}. */
|
|
178
|
+
export interface WebLocksControls {
|
|
179
|
+
/** Whether the Web Locks API is available. */
|
|
180
|
+
readonly supported: ComputedRef<boolean>;
|
|
181
|
+
|
|
182
|
+
/** Names of locks requested through this composable that are currently held. */
|
|
183
|
+
readonly held: Readonly<Ref<readonly string[]>>;
|
|
184
|
+
|
|
185
|
+
/** Names of locks requested through this composable that are still waiting. */
|
|
186
|
+
readonly pending: Readonly<Ref<readonly string[]>>;
|
|
187
|
+
|
|
188
|
+
/** Most recent request failure (including aborts), cleared by the next grant. */
|
|
189
|
+
readonly error: Readonly<ShallowRef<unknown>>;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Request a lock. Rejects with a tagged `TypeError` for invalid option
|
|
193
|
+
* combinations, a tagged `Error` when unsupported, the host's `AbortError`
|
|
194
|
+
* when aborted, or the callback's rejection.
|
|
195
|
+
*/
|
|
196
|
+
readonly request: WebLockRequest;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Snapshot the origin's locks.
|
|
200
|
+
*
|
|
201
|
+
* @returns Held and pending locks; empty lists when unsupported or on failure.
|
|
202
|
+
*/
|
|
203
|
+
readonly query: () => Promise<WebLocksSnapshot>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function browserLocks(): LockManagerLike | undefined {
|
|
207
|
+
if (typeof window === "undefined") return undefined;
|
|
208
|
+
const { navigator } = window;
|
|
209
|
+
return "locks" in navigator && navigator.locks ? navigator.locks : undefined;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function without(names: readonly string[], name: string): readonly string[] {
|
|
213
|
+
const index = names.indexOf(name);
|
|
214
|
+
return index === -1 ? names : [...names.slice(0, index), ...names.slice(index + 1)];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Coordinate work across tabs and workers with the Web Locks API.
|
|
219
|
+
*
|
|
220
|
+
* `request` runs the callback while the named lock is held and resolves with
|
|
221
|
+
* its result; with `ifAvailable` it resolves with a discriminated
|
|
222
|
+
* `{ acquired }` outcome instead of waiting. `held` and `pending` track the
|
|
223
|
+
* lock names requested through this composable. Requests still waiting when
|
|
224
|
+
* the owning reactive scope stops are aborted; locks already held are
|
|
225
|
+
* released when their callbacks settle. Outside a scope, pass a `signal` to
|
|
226
|
+
* own cancellation.
|
|
227
|
+
*
|
|
228
|
+
* Server rendering: nothing is requested, `supported` is false and the name
|
|
229
|
+
* lists are empty.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* const locks = useWebLocks();
|
|
234
|
+
* await locks.request("sync", async () => syncOutbox());
|
|
235
|
+
* const attempt = await locks.request("leader", runLeader, { ifAvailable: true });
|
|
236
|
+
* ```
|
|
237
|
+
*
|
|
238
|
+
* @param options Lock manager override.
|
|
239
|
+
* @default options {}
|
|
240
|
+
* @returns Lock state and actions.
|
|
241
|
+
*/
|
|
242
|
+
export function useWebLocks(options: UseWebLocksOptions = {}): WebLocksControls {
|
|
243
|
+
const held = ref<readonly string[]>([]);
|
|
244
|
+
const pending = ref<readonly string[]>([]);
|
|
245
|
+
const error = shallowRef<unknown>(undefined);
|
|
246
|
+
const controllers = new Set<AbortController>();
|
|
247
|
+
|
|
248
|
+
// Inside a component the host resolves only after mount (a post-flush
|
|
249
|
+
// job), so a hydrating client first renders the same unsupported state as
|
|
250
|
+
// the server. Outside components it resolves immediately.
|
|
251
|
+
const hydrated = shallowRef(!hasInjectionContext());
|
|
252
|
+
if (!hydrated.value) {
|
|
253
|
+
watchPostEffect(() => {
|
|
254
|
+
hydrated.value = true;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
const resolveLocks = (): LockManagerLike | undefined =>
|
|
258
|
+
!hydrated.value
|
|
259
|
+
? undefined
|
|
260
|
+
: options.locks === undefined
|
|
261
|
+
? browserLocks()
|
|
262
|
+
: (toValue(options.locks) ?? undefined);
|
|
263
|
+
|
|
264
|
+
const run = async (
|
|
265
|
+
name: string,
|
|
266
|
+
callback: (lock: WebLockLike) => unknown,
|
|
267
|
+
requestOptions: WebLockRequestOptions = {},
|
|
268
|
+
): Promise<WebLockAttempt<unknown>> => {
|
|
269
|
+
const { mode = "exclusive", ifAvailable = false, steal = false, signal } = requestOptions;
|
|
270
|
+
if (
|
|
271
|
+
(ifAvailable && steal) ||
|
|
272
|
+
(steal && mode === "shared") ||
|
|
273
|
+
(signal && (ifAvailable || steal))
|
|
274
|
+
) {
|
|
275
|
+
throw new TypeError(
|
|
276
|
+
"[VIZE_COMPOSE_WEB_LOCKS_INVALID_OPTIONS] steal cannot be combined with ifAvailable, shared mode or signal, and signal cannot be combined with ifAvailable.",
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
const locks = resolveLocks();
|
|
280
|
+
if (!locks) {
|
|
281
|
+
throw new Error("[VIZE_COMPOSE_WEB_LOCKS_UNSUPPORTED] The Web Locks API is not available.");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const controller = ifAvailable || steal ? undefined : new AbortController();
|
|
285
|
+
const forwardAbort = (): void => controller?.abort(signal?.reason);
|
|
286
|
+
if (controller) {
|
|
287
|
+
if (signal?.aborted) forwardAbort();
|
|
288
|
+
else signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
289
|
+
controllers.add(controller);
|
|
290
|
+
}
|
|
291
|
+
pending.value = [...pending.value, name];
|
|
292
|
+
let granted = false;
|
|
293
|
+
const managerOptions: WebLockManagerRequestOptions = controller
|
|
294
|
+
? { mode, signal: controller.signal }
|
|
295
|
+
: { mode, ifAvailable, steal };
|
|
296
|
+
|
|
297
|
+
let outcome: WebLockAttempt<unknown> = { acquired: false };
|
|
298
|
+
try {
|
|
299
|
+
await locks.request(name, managerOptions, async (lock) => {
|
|
300
|
+
pending.value = without(pending.value, name);
|
|
301
|
+
if (controller) controllers.delete(controller);
|
|
302
|
+
if (!lock) return;
|
|
303
|
+
granted = true;
|
|
304
|
+
error.value = undefined;
|
|
305
|
+
held.value = [...held.value, name];
|
|
306
|
+
try {
|
|
307
|
+
outcome = { acquired: true, value: await callback(lock) };
|
|
308
|
+
} finally {
|
|
309
|
+
held.value = without(held.value, name);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
return outcome;
|
|
313
|
+
} catch (cause) {
|
|
314
|
+
error.value = cause;
|
|
315
|
+
throw cause;
|
|
316
|
+
} finally {
|
|
317
|
+
if (!granted) pending.value = without(pending.value, name);
|
|
318
|
+
if (controller) controllers.delete(controller);
|
|
319
|
+
signal?.removeEventListener("abort", forwardAbort);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// The overloads share one implementation: `run` reports the attempt and
|
|
324
|
+
// this adapter unwraps it for waiting requests. The cast is confined here.
|
|
325
|
+
const request = ((
|
|
326
|
+
name: string,
|
|
327
|
+
callback: (lock: WebLockLike) => unknown,
|
|
328
|
+
requestOptions?: WebLockRequestOptions,
|
|
329
|
+
): Promise<unknown> => {
|
|
330
|
+
const attempt = run(name, callback, requestOptions);
|
|
331
|
+
return requestOptions?.ifAvailable
|
|
332
|
+
? attempt
|
|
333
|
+
: attempt.then((outcome) => (outcome.acquired ? outcome.value : undefined));
|
|
334
|
+
}) as WebLockRequest;
|
|
335
|
+
|
|
336
|
+
const query = async (): Promise<WebLocksSnapshot> => {
|
|
337
|
+
const locks = resolveLocks();
|
|
338
|
+
if (!locks) return { held: [], pending: [] };
|
|
339
|
+
try {
|
|
340
|
+
const snapshot = await locks.query();
|
|
341
|
+
return { held: snapshot.held ?? [], pending: snapshot.pending ?? [] };
|
|
342
|
+
} catch (cause) {
|
|
343
|
+
error.value = cause;
|
|
344
|
+
return { held: [], pending: [] };
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
tryOnScopeDispose(() => {
|
|
349
|
+
for (const controller of controllers) {
|
|
350
|
+
controller.abort(new DOMException("The owning scope was disposed.", "AbortError"));
|
|
351
|
+
}
|
|
352
|
+
controllers.clear();
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
supported: computed(() => resolveLocks() !== undefined),
|
|
357
|
+
held: readonly(held),
|
|
358
|
+
pending: readonly(pending),
|
|
359
|
+
error: readonly(error),
|
|
360
|
+
request,
|
|
361
|
+
query,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
hasInjectionContext,
|
|
4
|
+
readonly,
|
|
5
|
+
ref,
|
|
6
|
+
shallowReadonly,
|
|
7
|
+
shallowRef,
|
|
8
|
+
toValue,
|
|
9
|
+
watchPostEffect,
|
|
10
|
+
} from "vue";
|
|
11
|
+
import type { ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
|
|
12
|
+
|
|
13
|
+
import { tryOnScopeDispose } from "./scope.ts";
|
|
14
|
+
|
|
15
|
+
/** Minimal `MIDIPort` read by {@link useWebMIDI}. */
|
|
16
|
+
export interface MIDIPortLike extends EventTarget {
|
|
17
|
+
/** Stable port identifier. */
|
|
18
|
+
readonly id: string;
|
|
19
|
+
/** Port name. */
|
|
20
|
+
readonly name?: string | null;
|
|
21
|
+
/** Manufacturer name. */
|
|
22
|
+
readonly manufacturer?: string | null;
|
|
23
|
+
/** Device state. */
|
|
24
|
+
readonly state: string;
|
|
25
|
+
/** Connection state. */
|
|
26
|
+
readonly connection: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Minimal `MIDIOutput` used by {@link useWebMIDI}. */
|
|
30
|
+
export interface MIDIOutputLike extends MIDIPortLike {
|
|
31
|
+
/** Send one or more MIDI messages, optionally scheduled at `timestamp`. */
|
|
32
|
+
send(data: number[], timestamp?: number): void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Minimal `MIDIAccess` used by {@link useWebMIDI}. */
|
|
36
|
+
export interface MIDIAccessLike extends EventTarget {
|
|
37
|
+
/** Available inputs. */
|
|
38
|
+
readonly inputs: { values(): Iterable<MIDIPortLike> };
|
|
39
|
+
/** Available outputs. */
|
|
40
|
+
readonly outputs: { values(): Iterable<MIDIOutputLike> };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Access request flags of `navigator.requestMIDIAccess`. */
|
|
44
|
+
export interface MIDIRequestFlags {
|
|
45
|
+
/** Request system-exclusive message access. */
|
|
46
|
+
readonly sysex?: boolean;
|
|
47
|
+
/** Include software synthesizers. */
|
|
48
|
+
readonly software?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Navigator-like capability used by {@link useWebMIDI}. */
|
|
52
|
+
export interface MIDIHost {
|
|
53
|
+
/** Request MIDI access. */
|
|
54
|
+
requestMIDIAccess(options?: MIDIRequestFlags): Promise<MIDIAccessLike>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Plain description of one MIDI port. */
|
|
58
|
+
export interface MIDIPortInfo {
|
|
59
|
+
/** Stable port identifier. */
|
|
60
|
+
readonly id: string;
|
|
61
|
+
/** Port name (empty when unknown). */
|
|
62
|
+
readonly name: string;
|
|
63
|
+
/** Manufacturer (empty when unknown). */
|
|
64
|
+
readonly manufacturer: string;
|
|
65
|
+
/** Device state, e.g. `"connected"` or `"disconnected"`. */
|
|
66
|
+
readonly state: string;
|
|
67
|
+
/** Connection state, e.g. `"open"`, `"closed"` or `"pending"`. */
|
|
68
|
+
readonly connection: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** A message received on an input port. */
|
|
72
|
+
export interface MIDIInputMessage {
|
|
73
|
+
/** Raw message bytes. */
|
|
74
|
+
readonly data: Uint8Array;
|
|
75
|
+
/** Event timestamp in milliseconds. */
|
|
76
|
+
readonly timeStamp: number;
|
|
77
|
+
/** Identifier of the receiving input. */
|
|
78
|
+
readonly inputId: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Lifecycle of the access request. */
|
|
82
|
+
export type MIDIAccessStatus = "idle" | "pending" | "granted" | "denied";
|
|
83
|
+
|
|
84
|
+
/** Options for {@link useWebMIDI}. */
|
|
85
|
+
export interface UseWebMIDIOptions {
|
|
86
|
+
/**
|
|
87
|
+
* Navigator-like MIDI capability.
|
|
88
|
+
*
|
|
89
|
+
* @default window.navigator when `requestMIDIAccess` exists
|
|
90
|
+
*/
|
|
91
|
+
readonly host?: MaybeRefOrGetter<MIDIHost | null | undefined>;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Request system-exclusive access.
|
|
95
|
+
*
|
|
96
|
+
* @default false
|
|
97
|
+
*/
|
|
98
|
+
readonly sysex?: boolean;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Include software synthesizers.
|
|
102
|
+
*
|
|
103
|
+
* @default false
|
|
104
|
+
*/
|
|
105
|
+
readonly software?: boolean;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Receives every input message. When set, `midimessage` listeners are
|
|
109
|
+
* attached to all inputs (which implicitly opens them).
|
|
110
|
+
*
|
|
111
|
+
* @default undefined
|
|
112
|
+
*/
|
|
113
|
+
readonly onMessage?: (message: MIDIInputMessage) => void;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Reactive state and actions returned by {@link useWebMIDI}. */
|
|
117
|
+
export interface WebMIDIControls {
|
|
118
|
+
/** Whether Web MIDI is available. */
|
|
119
|
+
readonly supported: ComputedRef<boolean>;
|
|
120
|
+
/** Access request status. */
|
|
121
|
+
readonly status: Readonly<Ref<MIDIAccessStatus>>;
|
|
122
|
+
/** Input ports, refreshed on `statechange`. */
|
|
123
|
+
readonly inputs: Readonly<ShallowRef<readonly MIDIPortInfo[]>>;
|
|
124
|
+
/** Output ports, refreshed on `statechange`. */
|
|
125
|
+
readonly outputs: Readonly<ShallowRef<readonly MIDIPortInfo[]>>;
|
|
126
|
+
/** Most recent request or send failure. */
|
|
127
|
+
readonly error: Readonly<ShallowRef<unknown>>;
|
|
128
|
+
/**
|
|
129
|
+
* Request MIDI access (may prompt the user).
|
|
130
|
+
*
|
|
131
|
+
* @returns Whether access was granted.
|
|
132
|
+
*/
|
|
133
|
+
readonly request: () => Promise<boolean>;
|
|
134
|
+
/**
|
|
135
|
+
* Send bytes to an output.
|
|
136
|
+
*
|
|
137
|
+
* @returns Whether the output exists and accepted the message.
|
|
138
|
+
*/
|
|
139
|
+
readonly send: (
|
|
140
|
+
outputId: string,
|
|
141
|
+
data: Uint8Array | readonly number[],
|
|
142
|
+
timestamp?: number,
|
|
143
|
+
) => boolean;
|
|
144
|
+
/** Remove every listener and forget the access object. Idempotent. */
|
|
145
|
+
readonly stop: () => void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function browserMIDIHost(): MIDIHost | undefined {
|
|
149
|
+
if (typeof window === "undefined") return undefined;
|
|
150
|
+
const { navigator } = window;
|
|
151
|
+
return typeof navigator.requestMIDIAccess === "function" ? navigator : undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function describe(port: MIDIPortLike): MIDIPortInfo {
|
|
155
|
+
return {
|
|
156
|
+
id: port.id,
|
|
157
|
+
name: port.name ?? "",
|
|
158
|
+
manufacturer: port.manufacturer ?? "",
|
|
159
|
+
state: port.state,
|
|
160
|
+
connection: port.connection,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function hasMessageData(event: Event): event is Event & { readonly data: Uint8Array | null } {
|
|
165
|
+
return "data" in event;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Access MIDI devices with the Web MIDI API.
|
|
170
|
+
*
|
|
171
|
+
* Nothing is requested until `request()` is called. Once granted, `inputs`
|
|
172
|
+
* and `outputs` follow `statechange` events, and `onMessage` receives
|
|
173
|
+
* messages from every input. Failures land in `error`. Listeners are removed
|
|
174
|
+
* when the owning reactive scope stops; outside a scope call `stop()`.
|
|
175
|
+
*
|
|
176
|
+
* Server rendering: `supported` is false, `status` stays `"idle"` and no
|
|
177
|
+
* access is requested.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* const midi = useWebMIDI({ onMessage: ({ data }) => console.log(data) });
|
|
182
|
+
* await midi.request();
|
|
183
|
+
* midi.send(midi.outputs.value[0]!.id, [0x90, 60, 127]);
|
|
184
|
+
* ```
|
|
185
|
+
*
|
|
186
|
+
* @param options Host, access flags, and message callback.
|
|
187
|
+
* @default options {}
|
|
188
|
+
* @returns MIDI state and actions.
|
|
189
|
+
*/
|
|
190
|
+
export function useWebMIDI(options: UseWebMIDIOptions = {}): WebMIDIControls {
|
|
191
|
+
const status = ref<MIDIAccessStatus>("idle");
|
|
192
|
+
const inputs = shallowRef<readonly MIDIPortInfo[]>([]);
|
|
193
|
+
const outputs = shallowRef<readonly MIDIPortInfo[]>([]);
|
|
194
|
+
const error = shallowRef<unknown>(undefined);
|
|
195
|
+
const listening = new Map<MIDIPortLike, (event: Event) => void>();
|
|
196
|
+
let access: MIDIAccessLike | undefined;
|
|
197
|
+
let generation = 0;
|
|
198
|
+
|
|
199
|
+
// Inside a component the host resolves only after mount (a post-flush
|
|
200
|
+
// job), so a hydrating client first renders the same unsupported state as
|
|
201
|
+
// the server. Outside components it resolves immediately.
|
|
202
|
+
const hydrated = shallowRef(!hasInjectionContext());
|
|
203
|
+
if (!hydrated.value) {
|
|
204
|
+
watchPostEffect(() => {
|
|
205
|
+
hydrated.value = true;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
const resolveHost = (): MIDIHost | undefined =>
|
|
209
|
+
!hydrated.value
|
|
210
|
+
? undefined
|
|
211
|
+
: options.host === undefined
|
|
212
|
+
? browserMIDIHost()
|
|
213
|
+
: (toValue(options.host) ?? undefined);
|
|
214
|
+
|
|
215
|
+
const listen = (input: MIDIPortLike): void => {
|
|
216
|
+
const onMessage = options.onMessage;
|
|
217
|
+
if (!onMessage || listening.has(input)) return;
|
|
218
|
+
const listener = (event: Event): void => {
|
|
219
|
+
if (!hasMessageData(event) || !event.data) return;
|
|
220
|
+
onMessage({ data: event.data, timeStamp: event.timeStamp, inputId: input.id });
|
|
221
|
+
};
|
|
222
|
+
listening.set(input, listener);
|
|
223
|
+
input.addEventListener("midimessage", listener);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const unlisten = (): void => {
|
|
227
|
+
for (const [input, listener] of listening) input.removeEventListener("midimessage", listener);
|
|
228
|
+
listening.clear();
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const refresh = (): void => {
|
|
232
|
+
if (!access) return;
|
|
233
|
+
const inputPorts = [...access.inputs.values()];
|
|
234
|
+
for (const input of inputPorts) listen(input);
|
|
235
|
+
inputs.value = inputPorts.map(describe);
|
|
236
|
+
outputs.value = [...access.outputs.values()].map(describe);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const stop = (): void => {
|
|
240
|
+
generation += 1;
|
|
241
|
+
unlisten();
|
|
242
|
+
access?.removeEventListener("statechange", refresh);
|
|
243
|
+
access = undefined;
|
|
244
|
+
inputs.value = [];
|
|
245
|
+
outputs.value = [];
|
|
246
|
+
if (status.value === "pending") status.value = "idle";
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const request = async (): Promise<boolean> => {
|
|
250
|
+
const host = resolveHost();
|
|
251
|
+
if (!host) return false;
|
|
252
|
+
stop();
|
|
253
|
+
const current = generation;
|
|
254
|
+
status.value = "pending";
|
|
255
|
+
try {
|
|
256
|
+
const next = await host.requestMIDIAccess({
|
|
257
|
+
sysex: options.sysex ?? false,
|
|
258
|
+
software: options.software ?? false,
|
|
259
|
+
});
|
|
260
|
+
if (current !== generation) return false;
|
|
261
|
+
access = next;
|
|
262
|
+
next.addEventListener("statechange", refresh);
|
|
263
|
+
refresh();
|
|
264
|
+
status.value = "granted";
|
|
265
|
+
error.value = undefined;
|
|
266
|
+
return true;
|
|
267
|
+
} catch (cause) {
|
|
268
|
+
if (current !== generation) return false;
|
|
269
|
+
status.value = "denied";
|
|
270
|
+
error.value = cause;
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const send = (
|
|
276
|
+
outputId: string,
|
|
277
|
+
data: Uint8Array | readonly number[],
|
|
278
|
+
timestamp?: number,
|
|
279
|
+
): boolean => {
|
|
280
|
+
const output = access
|
|
281
|
+
? [...access.outputs.values()].find((port) => port.id === outputId)
|
|
282
|
+
: undefined;
|
|
283
|
+
if (!output) return false;
|
|
284
|
+
try {
|
|
285
|
+
if (timestamp === undefined) output.send(Array.from(data));
|
|
286
|
+
else output.send(Array.from(data), timestamp);
|
|
287
|
+
return true;
|
|
288
|
+
} catch (cause) {
|
|
289
|
+
error.value = cause;
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
tryOnScopeDispose(stop);
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
supported: computed(() => resolveHost() !== undefined),
|
|
298
|
+
status: readonly(status),
|
|
299
|
+
inputs: shallowReadonly(inputs),
|
|
300
|
+
outputs: shallowReadonly(outputs),
|
|
301
|
+
error: readonly(error),
|
|
302
|
+
request,
|
|
303
|
+
send,
|
|
304
|
+
stop,
|
|
305
|
+
};
|
|
306
|
+
}
|