@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,233 @@
|
|
|
1
|
+
import { computed, shallowRef, toValue } from "vue";
|
|
2
|
+
import type { ComputedRef, MaybeRefOrGetter, ShallowRef } from "vue";
|
|
3
|
+
|
|
4
|
+
/** Options for {@link useSelection}. */
|
|
5
|
+
export interface UseSelectionOptions<Item, Key, Multiple extends boolean> {
|
|
6
|
+
/** Selectable items, in display order. Reactive. */
|
|
7
|
+
readonly items: MaybeRefOrGetter<readonly Item[]>;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Allow several selected items.
|
|
11
|
+
*
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
readonly multiple?: Multiple;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Stable identity of an item, for example its id. Keys survive item
|
|
18
|
+
* objects being replaced (refetches, immutable updates).
|
|
19
|
+
*
|
|
20
|
+
* @default the item itself
|
|
21
|
+
*/
|
|
22
|
+
readonly getKey?: (item: Item) => Key;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Keys selected initially.
|
|
26
|
+
*
|
|
27
|
+
* @default []
|
|
28
|
+
*/
|
|
29
|
+
readonly initial?: readonly Key[];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Maximum number of selected items in multiple mode; selecting beyond it
|
|
33
|
+
* is refused.
|
|
34
|
+
*
|
|
35
|
+
* @default Number.POSITIVE_INFINITY
|
|
36
|
+
*/
|
|
37
|
+
readonly max?: number;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Refuse to deselect the last selected item.
|
|
41
|
+
*
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
readonly required?: boolean;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Veto selecting an item (for example disabled rows).
|
|
48
|
+
*
|
|
49
|
+
* @default undefined (every item is selectable)
|
|
50
|
+
*/
|
|
51
|
+
readonly isSelectable?: (item: Item) => boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Selection state and commands returned by {@link useSelection}. */
|
|
55
|
+
export interface Selection<Item, Key, Multiple extends boolean> {
|
|
56
|
+
/** Selected keys in selection order. */
|
|
57
|
+
readonly selectedKeys: Readonly<ShallowRef<readonly Key[]>>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Selected items in `items` order: an array in multiple mode, the single
|
|
61
|
+
* item (or `undefined`) otherwise. Keys whose item is currently absent are
|
|
62
|
+
* kept but not listed.
|
|
63
|
+
*/
|
|
64
|
+
readonly selected: ComputedRef<Multiple extends true ? Item[] : Item | undefined>;
|
|
65
|
+
|
|
66
|
+
/** Number of selected keys. */
|
|
67
|
+
readonly count: ComputedRef<number>;
|
|
68
|
+
|
|
69
|
+
/** Whether every selectable item is selected (multiple mode). */
|
|
70
|
+
readonly isAllSelected: ComputedRef<boolean>;
|
|
71
|
+
|
|
72
|
+
/** Whether some but not all selectable items are selected (tri-state checkboxes). */
|
|
73
|
+
readonly isIndeterminate: ComputedRef<boolean>;
|
|
74
|
+
|
|
75
|
+
/** Item that anchors range selection (the last explicitly selected one). */
|
|
76
|
+
readonly anchor: Readonly<ShallowRef<Key | undefined>>;
|
|
77
|
+
|
|
78
|
+
/** Whether `item` is selected. */
|
|
79
|
+
readonly isSelected: (item: Item) => boolean;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Select `item` (replacing the selection in single mode).
|
|
83
|
+
*
|
|
84
|
+
* @returns Whether the selection changed.
|
|
85
|
+
*/
|
|
86
|
+
readonly select: (item: Item) => boolean;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Deselect `item`.
|
|
90
|
+
*
|
|
91
|
+
* @returns Whether the selection changed.
|
|
92
|
+
*/
|
|
93
|
+
readonly deselect: (item: Item) => boolean;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Toggle `item`.
|
|
97
|
+
*
|
|
98
|
+
* @returns Whether the selection changed.
|
|
99
|
+
*/
|
|
100
|
+
readonly toggle: (item: Item) => boolean;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Select exactly `item`.
|
|
104
|
+
*
|
|
105
|
+
* @returns Whether the selection changed.
|
|
106
|
+
*/
|
|
107
|
+
readonly selectOnly: (item: Item) => boolean;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Select every item between the anchor and `item` inclusive
|
|
111
|
+
* (shift-click); in single mode this selects `item`.
|
|
112
|
+
*
|
|
113
|
+
* @returns Whether the selection changed.
|
|
114
|
+
*/
|
|
115
|
+
readonly extendTo: (item: Item) => boolean;
|
|
116
|
+
|
|
117
|
+
/** Select every selectable item, up to `max` (multiple mode). */
|
|
118
|
+
readonly selectAll: () => void;
|
|
119
|
+
|
|
120
|
+
/** Clear the selection (ignores `required`). */
|
|
121
|
+
readonly clear: () => void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Generic single- or multi-select state for lists, tables, and grids.
|
|
126
|
+
*
|
|
127
|
+
* Keys (from `getKey`, the item itself by default) identify items, so the
|
|
128
|
+
* selection survives items being replaced. `multiple: true` switches the
|
|
129
|
+
* `selected` type to an array; `max`, `required`, and `isSelectable`
|
|
130
|
+
* constrain changes, and `extendTo` implements shift-click ranges from the
|
|
131
|
+
* anchor in display order. Synchronous state: SSR-safe and nothing to
|
|
132
|
+
* dispose.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```ts
|
|
136
|
+
* const rows = useSelection({ items: users, multiple: true, getKey: (user) => user.id });
|
|
137
|
+
* rows.toggle(user);
|
|
138
|
+
* rows.extendTo(other); // shift-click
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* @param options Items, mode, identity, and constraints.
|
|
142
|
+
* @returns Selection state and commands.
|
|
143
|
+
*/
|
|
144
|
+
export function useSelection<Item, Key = Item, const Multiple extends boolean = false>(
|
|
145
|
+
options: UseSelectionOptions<Item, Key, Multiple>,
|
|
146
|
+
): Selection<Item, Key, Multiple>;
|
|
147
|
+
export function useSelection(
|
|
148
|
+
options: UseSelectionOptions<unknown, unknown, boolean>,
|
|
149
|
+
): Selection<unknown, unknown, boolean> {
|
|
150
|
+
const multiple = options.multiple ?? false;
|
|
151
|
+
const max = multiple ? (options.max ?? Number.POSITIVE_INFINITY) : 1;
|
|
152
|
+
const keyOf = options.getKey ?? ((item: unknown): unknown => item);
|
|
153
|
+
const selectable = options.isSelectable ?? (() => true);
|
|
154
|
+
const selectedKeys = shallowRef<readonly unknown[]>((options.initial ?? []).slice(0, max));
|
|
155
|
+
const anchor = shallowRef<unknown>(selectedKeys.value.at(-1));
|
|
156
|
+
const items = computed(() => toValue(options.items));
|
|
157
|
+
|
|
158
|
+
const has = (key: unknown): boolean => selectedKeys.value.includes(key);
|
|
159
|
+
const commit = (next: readonly unknown[]): boolean => {
|
|
160
|
+
const current = selectedKeys.value;
|
|
161
|
+
if (next.length === current.length && next.every((key, index) => key === current[index]))
|
|
162
|
+
return false;
|
|
163
|
+
selectedKeys.value = next;
|
|
164
|
+
return true;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const select = (item: unknown): boolean => {
|
|
168
|
+
if (!selectable(item)) return false;
|
|
169
|
+
const key = keyOf(item);
|
|
170
|
+
anchor.value = key;
|
|
171
|
+
if (!multiple) return commit([key]);
|
|
172
|
+
if (has(key) || selectedKeys.value.length >= max) return false;
|
|
173
|
+
return commit([...selectedKeys.value, key]);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const deselect = (item: unknown): boolean => {
|
|
177
|
+
const key = keyOf(item);
|
|
178
|
+
if (!has(key)) return false;
|
|
179
|
+
if ((options.required ?? false) && selectedKeys.value.length === 1) return false;
|
|
180
|
+
return commit(selectedKeys.value.filter((candidate) => candidate !== key));
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const selectableKeys = computed(() => items.value.filter(selectable).map(keyOf));
|
|
184
|
+
const selectedItems = computed(() => items.value.filter((item) => has(keyOf(item))));
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
selectedKeys,
|
|
188
|
+
selected: computed(() => (multiple ? selectedItems.value : selectedItems.value[0])),
|
|
189
|
+
count: computed(() => selectedKeys.value.length),
|
|
190
|
+
isAllSelected: computed(
|
|
191
|
+
() => selectableKeys.value.length > 0 && selectableKeys.value.every((key) => has(key)),
|
|
192
|
+
),
|
|
193
|
+
isIndeterminate: computed(() => {
|
|
194
|
+
const chosen = selectableKeys.value.filter((key) => has(key)).length;
|
|
195
|
+
return chosen > 0 && chosen < selectableKeys.value.length;
|
|
196
|
+
}),
|
|
197
|
+
anchor,
|
|
198
|
+
isSelected: (item) => has(keyOf(item)),
|
|
199
|
+
select,
|
|
200
|
+
deselect,
|
|
201
|
+
toggle: (item) => (has(keyOf(item)) ? deselect(item) : select(item)),
|
|
202
|
+
selectOnly: (item) => {
|
|
203
|
+
if (!selectable(item)) return false;
|
|
204
|
+
anchor.value = keyOf(item);
|
|
205
|
+
return commit([keyOf(item)]);
|
|
206
|
+
},
|
|
207
|
+
extendTo: (item) => {
|
|
208
|
+
if (!multiple) return select(item);
|
|
209
|
+
const keys = items.value.map(keyOf);
|
|
210
|
+
const from = keys.indexOf(anchor.value);
|
|
211
|
+
const to = keys.indexOf(keyOf(item));
|
|
212
|
+
if (to === -1) return false;
|
|
213
|
+
if (from === -1) return select(item);
|
|
214
|
+
const [start, end] = from <= to ? [from, to] : [to, from];
|
|
215
|
+
const range = items.value
|
|
216
|
+
.slice(start, end + 1)
|
|
217
|
+
.filter(selectable)
|
|
218
|
+
.map(keyOf)
|
|
219
|
+
.filter((key) => !has(key));
|
|
220
|
+
const room = Math.max(0, max - selectedKeys.value.length);
|
|
221
|
+
return commit([...selectedKeys.value, ...range.slice(0, room)]);
|
|
222
|
+
},
|
|
223
|
+
selectAll: () => {
|
|
224
|
+
if (!multiple) return;
|
|
225
|
+
const missing = selectableKeys.value.filter((key) => !has(key));
|
|
226
|
+
const room = Math.max(0, max - selectedKeys.value.length);
|
|
227
|
+
commit([...selectedKeys.value, ...missing.slice(0, room)]);
|
|
228
|
+
},
|
|
229
|
+
clear: () => {
|
|
230
|
+
commit([]);
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
}
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
hasInjectionContext,
|
|
4
|
+
readonly,
|
|
5
|
+
ref,
|
|
6
|
+
shallowReadonly,
|
|
7
|
+
shallowRef,
|
|
8
|
+
toValue,
|
|
9
|
+
watch,
|
|
10
|
+
watchPostEffect,
|
|
11
|
+
} from "vue";
|
|
12
|
+
import type { ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
|
|
13
|
+
|
|
14
|
+
import { tryOnScopeDispose } from "./scope.ts";
|
|
15
|
+
|
|
16
|
+
/** USB identifiers used to filter `requestPort`. */
|
|
17
|
+
export interface SerialPortFilter {
|
|
18
|
+
/** USB vendor id. */
|
|
19
|
+
readonly usbVendorId?: number;
|
|
20
|
+
/** USB product id. */
|
|
21
|
+
readonly usbProductId?: number;
|
|
22
|
+
/** Bluetooth RFCOMM service class id. */
|
|
23
|
+
readonly bluetoothServiceClassId?: number | string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Line settings passed to `SerialPort.open`. */
|
|
27
|
+
export interface SerialOpenOptions {
|
|
28
|
+
/** Baud rate, e.g. `9600` or `115200`. */
|
|
29
|
+
readonly baudRate: number;
|
|
30
|
+
/**
|
|
31
|
+
* Data bits per frame (7 or 8).
|
|
32
|
+
*
|
|
33
|
+
* @default 8
|
|
34
|
+
*/
|
|
35
|
+
readonly dataBits?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Stop bits (1 or 2).
|
|
38
|
+
*
|
|
39
|
+
* @default 1
|
|
40
|
+
*/
|
|
41
|
+
readonly stopBits?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Parity mode.
|
|
44
|
+
*
|
|
45
|
+
* @default "none"
|
|
46
|
+
*/
|
|
47
|
+
readonly parity?: "none" | "even" | "odd";
|
|
48
|
+
/**
|
|
49
|
+
* Read/write buffer size in bytes.
|
|
50
|
+
*
|
|
51
|
+
* @default 255
|
|
52
|
+
*/
|
|
53
|
+
readonly bufferSize?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Flow control mode.
|
|
56
|
+
*
|
|
57
|
+
* @default "none"
|
|
58
|
+
*/
|
|
59
|
+
readonly flowControl?: "none" | "hardware";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Minimal `SerialPort` used by {@link useSerial}. */
|
|
63
|
+
export interface SerialPortLike extends EventTarget {
|
|
64
|
+
/** Byte stream from the device while open; `null` otherwise or after a fatal error. */
|
|
65
|
+
readonly readable: ReadableStream<Uint8Array> | null;
|
|
66
|
+
/** Byte sink to the device while open. */
|
|
67
|
+
readonly writable: WritableStream<Uint8Array> | null;
|
|
68
|
+
/** Open the port. */
|
|
69
|
+
open(options: SerialOpenOptions): Promise<void>;
|
|
70
|
+
/** Close the port. */
|
|
71
|
+
close(): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** `navigator.serial`-like capability used by {@link useSerial}. */
|
|
75
|
+
export interface SerialHost extends EventTarget {
|
|
76
|
+
/** Ports the page already has access to. */
|
|
77
|
+
getPorts(): Promise<SerialPortLike[]>;
|
|
78
|
+
/** Prompt the user for a port. */
|
|
79
|
+
requestPort(options?: {
|
|
80
|
+
readonly filters?: readonly SerialPortFilter[];
|
|
81
|
+
}): Promise<SerialPortLike>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** How received bytes are delivered. */
|
|
85
|
+
export type SerialDecoding = "bytes" | "text";
|
|
86
|
+
|
|
87
|
+
/** Chunk type delivered for a {@link SerialDecoding}. */
|
|
88
|
+
export type SerialChunk<Decoding extends SerialDecoding> = Decoding extends "text"
|
|
89
|
+
? string
|
|
90
|
+
: Uint8Array;
|
|
91
|
+
|
|
92
|
+
/** Options for {@link useSerial}. */
|
|
93
|
+
export interface UseSerialOptions<Decoding extends SerialDecoding = "bytes"> {
|
|
94
|
+
/**
|
|
95
|
+
* `navigator.serial`-like capability.
|
|
96
|
+
*
|
|
97
|
+
* @default window.navigator.serial when it exists
|
|
98
|
+
*/
|
|
99
|
+
readonly host?: MaybeRefOrGetter<SerialHost | null | undefined>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Deliver raw bytes or text decoded with `encoding` (streaming, so split
|
|
103
|
+
* multi-byte characters are joined).
|
|
104
|
+
*
|
|
105
|
+
* @default "bytes"
|
|
106
|
+
*/
|
|
107
|
+
readonly decode?: Decoding;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Text encoding used when `decode` is `"text"`.
|
|
111
|
+
*
|
|
112
|
+
* @default "utf-8"
|
|
113
|
+
*/
|
|
114
|
+
readonly encoding?: string;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Receives every chunk read from the open port.
|
|
118
|
+
*
|
|
119
|
+
* @default undefined
|
|
120
|
+
*/
|
|
121
|
+
readonly onData?: (chunk: SerialChunk<Decoding>) => void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Reactive state and actions returned by {@link useSerial}. */
|
|
125
|
+
export interface SerialControls {
|
|
126
|
+
/** Whether Web Serial is available. */
|
|
127
|
+
readonly supported: ComputedRef<boolean>;
|
|
128
|
+
/** Ports the page has access to, refreshed on `connect` / `disconnect`. */
|
|
129
|
+
readonly ports: Readonly<ShallowRef<readonly SerialPortLike[]>>;
|
|
130
|
+
/** Currently open port. */
|
|
131
|
+
readonly port: Readonly<ShallowRef<SerialPortLike | undefined>>;
|
|
132
|
+
/** Whether a port is open. */
|
|
133
|
+
readonly connected: Readonly<Ref<boolean>>;
|
|
134
|
+
/** Most recent failure (request, open, read, write). */
|
|
135
|
+
readonly error: Readonly<ShallowRef<unknown>>;
|
|
136
|
+
/**
|
|
137
|
+
* Prompt the user for a port (requires user activation).
|
|
138
|
+
*
|
|
139
|
+
* @returns The chosen port, or `undefined` when cancelled or failed.
|
|
140
|
+
*/
|
|
141
|
+
readonly requestPort: (
|
|
142
|
+
filters?: readonly SerialPortFilter[],
|
|
143
|
+
) => Promise<SerialPortLike | undefined>;
|
|
144
|
+
/**
|
|
145
|
+
* Refresh `ports`.
|
|
146
|
+
*
|
|
147
|
+
* @returns The granted ports.
|
|
148
|
+
*/
|
|
149
|
+
readonly getPorts: () => Promise<readonly SerialPortLike[]>;
|
|
150
|
+
/**
|
|
151
|
+
* Open `port` (closing any other open port) and start the read loop.
|
|
152
|
+
*
|
|
153
|
+
* @returns Whether the port opened.
|
|
154
|
+
*/
|
|
155
|
+
readonly open: (port: SerialPortLike, options: SerialOpenOptions) => Promise<boolean>;
|
|
156
|
+
/**
|
|
157
|
+
* Write text (UTF-8 encoded) or bytes.
|
|
158
|
+
*
|
|
159
|
+
* @returns Whether the data was written.
|
|
160
|
+
*/
|
|
161
|
+
readonly write: (data: string | Uint8Array) => Promise<boolean>;
|
|
162
|
+
/** Stop reading and close the open port. Idempotent. */
|
|
163
|
+
readonly close: () => Promise<void>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function browserSerialHost(): SerialHost | undefined {
|
|
167
|
+
if (typeof window === "undefined") return undefined;
|
|
168
|
+
const { navigator } = window;
|
|
169
|
+
// Web Serial is not part of the DOM lib; read it through a structural guard.
|
|
170
|
+
const serial: unknown = "serial" in navigator ? navigator.serial : undefined;
|
|
171
|
+
return isSerialHost(serial) ? serial : undefined;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function isSerialHost(value: unknown): value is SerialHost {
|
|
175
|
+
return typeof value === "object" && value !== null && "requestPort" in value;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface ReadSession {
|
|
179
|
+
active: boolean;
|
|
180
|
+
reader: ReadableStreamDefaultReader<Uint8Array> | undefined;
|
|
181
|
+
done: Promise<void>;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Talk to serial devices with the Web Serial API.
|
|
186
|
+
*
|
|
187
|
+
* `requestPort()` prompts for a port, `open()` opens it and starts a read
|
|
188
|
+
* loop that feeds `onData` with bytes or decoded text, `write()` sends text
|
|
189
|
+
* or bytes. `ports` follows the host's `connect` / `disconnect` events and a
|
|
190
|
+
* port's own `disconnect` closes the session. Failures land in `error`. The
|
|
191
|
+
* read loop is cancelled and the port closed when the owning reactive scope
|
|
192
|
+
* stops; outside a scope call `close()`.
|
|
193
|
+
*
|
|
194
|
+
* Server rendering: `supported` and `connected` are false, nothing is read.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* const serial = useSerial({ decode: "text", onData: (text) => log(text) });
|
|
199
|
+
* const port = await serial.requestPort([{ usbVendorId: 0x2341 }]);
|
|
200
|
+
* if (port) await serial.open(port, { baudRate: 115200 });
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* @param options Host, decoding, and data callback.
|
|
204
|
+
* @default options {}
|
|
205
|
+
* @throws `RangeError` tagged `VIZE_COMPOSE_SERIAL_INVALID_ENCODING` for an unknown `encoding`.
|
|
206
|
+
* @returns Serial state and actions.
|
|
207
|
+
*/
|
|
208
|
+
export function useSerial<const Decoding extends SerialDecoding = "bytes">(
|
|
209
|
+
options: UseSerialOptions<Decoding> = {},
|
|
210
|
+
): SerialControls {
|
|
211
|
+
const ports = shallowRef<readonly SerialPortLike[]>([]);
|
|
212
|
+
const port = shallowRef<SerialPortLike | undefined>(undefined);
|
|
213
|
+
const connected = ref(false);
|
|
214
|
+
const error = shallowRef<unknown>(undefined);
|
|
215
|
+
const encoding = options.encoding ?? "utf-8";
|
|
216
|
+
const text = options.decode === "text";
|
|
217
|
+
if (text) {
|
|
218
|
+
try {
|
|
219
|
+
new TextDecoder(encoding);
|
|
220
|
+
} catch {
|
|
221
|
+
throw new RangeError(
|
|
222
|
+
`[VIZE_COMPOSE_SERIAL_INVALID_ENCODING] unsupported text encoding "${encoding}"`,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
let session: ReadSession | undefined;
|
|
227
|
+
|
|
228
|
+
// Inside a component the host resolves only after mount (a post-flush
|
|
229
|
+
// job), so a hydrating client first renders the same unsupported state as
|
|
230
|
+
// the server. Outside components it resolves immediately.
|
|
231
|
+
const hydrated = shallowRef(!hasInjectionContext());
|
|
232
|
+
if (!hydrated.value) {
|
|
233
|
+
watchPostEffect(() => {
|
|
234
|
+
hydrated.value = true;
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
const resolveHost = (): SerialHost | undefined =>
|
|
238
|
+
!hydrated.value
|
|
239
|
+
? undefined
|
|
240
|
+
: options.host === undefined
|
|
241
|
+
? browserSerialHost()
|
|
242
|
+
: (toValue(options.host) ?? undefined);
|
|
243
|
+
|
|
244
|
+
const deliver = (chunk: Uint8Array | string): void => {
|
|
245
|
+
// `chunk` is a string exactly when `Decoding` is "text", matching SerialChunk.
|
|
246
|
+
if (chunk.length > 0) options.onData?.(chunk as SerialChunk<Decoding>);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const readLoop = async (target: SerialPortLike, current: ReadSession): Promise<void> => {
|
|
250
|
+
const decoder = text ? new TextDecoder(encoding) : undefined;
|
|
251
|
+
let stream = target.readable;
|
|
252
|
+
while (stream && current.active) {
|
|
253
|
+
const reader = stream.getReader();
|
|
254
|
+
current.reader = reader;
|
|
255
|
+
try {
|
|
256
|
+
for (;;) {
|
|
257
|
+
const { value, done } = await reader.read();
|
|
258
|
+
if (done) break;
|
|
259
|
+
deliver(decoder ? decoder.decode(value, { stream: true }) : value);
|
|
260
|
+
}
|
|
261
|
+
} catch (cause) {
|
|
262
|
+
if (current.active) error.value = cause;
|
|
263
|
+
} finally {
|
|
264
|
+
reader.releaseLock();
|
|
265
|
+
current.reader = undefined;
|
|
266
|
+
}
|
|
267
|
+
// Non-fatal errors replace `readable`; the same stream again means it is finished.
|
|
268
|
+
if (target.readable === stream) break;
|
|
269
|
+
stream = target.readable;
|
|
270
|
+
}
|
|
271
|
+
if (decoder) deliver(decoder.decode());
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const onPortDisconnect = (): void => {
|
|
275
|
+
void close();
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
async function close(): Promise<void> {
|
|
279
|
+
const current = session;
|
|
280
|
+
const target = port.value;
|
|
281
|
+
session = undefined;
|
|
282
|
+
port.value = undefined;
|
|
283
|
+
connected.value = false;
|
|
284
|
+
if (!current || !target) return;
|
|
285
|
+
target.removeEventListener("disconnect", onPortDisconnect);
|
|
286
|
+
current.active = false;
|
|
287
|
+
let failure: unknown;
|
|
288
|
+
try {
|
|
289
|
+
await current.reader?.cancel();
|
|
290
|
+
} catch (cause) {
|
|
291
|
+
failure = cause;
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
await current.done;
|
|
295
|
+
} catch (cause) {
|
|
296
|
+
failure ??= cause;
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
await target.close();
|
|
300
|
+
} catch (cause) {
|
|
301
|
+
failure ??= cause;
|
|
302
|
+
}
|
|
303
|
+
if (failure !== undefined) error.value = failure;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const open = async (target: SerialPortLike, openOptions: SerialOpenOptions): Promise<boolean> => {
|
|
307
|
+
await close();
|
|
308
|
+
try {
|
|
309
|
+
await target.open(openOptions);
|
|
310
|
+
} catch (cause) {
|
|
311
|
+
error.value = cause;
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
const current: ReadSession = { active: true, reader: undefined, done: Promise.resolve() };
|
|
315
|
+
session = current;
|
|
316
|
+
port.value = target;
|
|
317
|
+
connected.value = true;
|
|
318
|
+
error.value = undefined;
|
|
319
|
+
target.addEventListener("disconnect", onPortDisconnect);
|
|
320
|
+
current.done = readLoop(target, current);
|
|
321
|
+
return true;
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const write = async (data: string | Uint8Array): Promise<boolean> => {
|
|
325
|
+
const writable = port.value?.writable;
|
|
326
|
+
if (!writable) return false;
|
|
327
|
+
const writer = writable.getWriter();
|
|
328
|
+
try {
|
|
329
|
+
await writer.write(typeof data === "string" ? new TextEncoder().encode(data) : data);
|
|
330
|
+
return true;
|
|
331
|
+
} catch (cause) {
|
|
332
|
+
error.value = cause;
|
|
333
|
+
return false;
|
|
334
|
+
} finally {
|
|
335
|
+
writer.releaseLock();
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const getPorts = async (): Promise<readonly SerialPortLike[]> => {
|
|
340
|
+
const host = resolveHost();
|
|
341
|
+
if (!host) return [];
|
|
342
|
+
try {
|
|
343
|
+
ports.value = await host.getPorts();
|
|
344
|
+
} catch (cause) {
|
|
345
|
+
error.value = cause;
|
|
346
|
+
}
|
|
347
|
+
return ports.value;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const requestPort = async (
|
|
351
|
+
filters?: readonly SerialPortFilter[],
|
|
352
|
+
): Promise<SerialPortLike | undefined> => {
|
|
353
|
+
const host = resolveHost();
|
|
354
|
+
if (!host) return undefined;
|
|
355
|
+
try {
|
|
356
|
+
const chosen = await host.requestPort(filters === undefined ? {} : { filters });
|
|
357
|
+
error.value = undefined;
|
|
358
|
+
await getPorts();
|
|
359
|
+
return chosen;
|
|
360
|
+
} catch (cause) {
|
|
361
|
+
error.value = cause;
|
|
362
|
+
return undefined;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const onHostChange = (): void => {
|
|
367
|
+
void getPorts();
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
watch(
|
|
371
|
+
resolveHost,
|
|
372
|
+
(host, _previous, onCleanup) => {
|
|
373
|
+
if (!host) {
|
|
374
|
+
ports.value = [];
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
host.addEventListener("connect", onHostChange);
|
|
378
|
+
host.addEventListener("disconnect", onHostChange);
|
|
379
|
+
onCleanup(() => {
|
|
380
|
+
host.removeEventListener("connect", onHostChange);
|
|
381
|
+
host.removeEventListener("disconnect", onHostChange);
|
|
382
|
+
});
|
|
383
|
+
void getPorts();
|
|
384
|
+
},
|
|
385
|
+
{ immediate: true, flush: "sync" },
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
tryOnScopeDispose(() => {
|
|
389
|
+
void close();
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
supported: computed(() => resolveHost() !== undefined),
|
|
394
|
+
ports: shallowReadonly(ports),
|
|
395
|
+
port: shallowReadonly(port),
|
|
396
|
+
connected: readonly(connected),
|
|
397
|
+
error: readonly(error),
|
|
398
|
+
requestPort,
|
|
399
|
+
getPorts,
|
|
400
|
+
open,
|
|
401
|
+
write,
|
|
402
|
+
close,
|
|
403
|
+
};
|
|
404
|
+
}
|