@vizejs/composable 0.426.3 → 0.427.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,214 @@
|
|
|
1
|
+
import { computed, readonly, ref, toRaw, toValue, watch } from "vue";
|
|
2
|
+
import type { ComputedRef, MaybeRefOrGetter, Ref } from "vue";
|
|
3
|
+
|
|
4
|
+
import { tryOnScopeDispose } from "./scope.ts";
|
|
5
|
+
|
|
6
|
+
/** Browser navigation UI preference while fullscreen. */
|
|
7
|
+
export type FullscreenNavigationUI = "auto" | "hide" | "show";
|
|
8
|
+
|
|
9
|
+
/** Element that can enter fullscreen (standard or WebKit-prefixed). */
|
|
10
|
+
export interface FullscreenElementLike {
|
|
11
|
+
/** Standard request. */
|
|
12
|
+
requestFullscreen?(options?: { navigationUI?: FullscreenNavigationUI }): Promise<void>;
|
|
13
|
+
|
|
14
|
+
/** Legacy WebKit request (Safari < 16.4). */
|
|
15
|
+
webkitRequestFullscreen?(): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Document-level fullscreen capability (standard or WebKit-prefixed). */
|
|
19
|
+
export interface FullscreenHost extends EventTarget {
|
|
20
|
+
/** Element currently in fullscreen. */
|
|
21
|
+
readonly fullscreenElement?: unknown;
|
|
22
|
+
|
|
23
|
+
/** Legacy WebKit fullscreen element. */
|
|
24
|
+
readonly webkitFullscreenElement?: unknown;
|
|
25
|
+
|
|
26
|
+
/** Whether fullscreen is allowed (for example by permissions policy). */
|
|
27
|
+
readonly fullscreenEnabled?: boolean;
|
|
28
|
+
|
|
29
|
+
/** Legacy WebKit flag. */
|
|
30
|
+
readonly webkitFullscreenEnabled?: boolean;
|
|
31
|
+
|
|
32
|
+
/** Standard exit. */
|
|
33
|
+
exitFullscreen?(): Promise<void>;
|
|
34
|
+
|
|
35
|
+
/** Legacy WebKit exit. */
|
|
36
|
+
webkitExitFullscreen?(): void;
|
|
37
|
+
|
|
38
|
+
/** Default fullscreen target. */
|
|
39
|
+
readonly documentElement?: FullscreenElementLike | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Options for {@link useFullscreen}. */
|
|
43
|
+
export interface UseFullscreenOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Document capability for alternate runtimes and tests.
|
|
46
|
+
*
|
|
47
|
+
* @default window.document when a browser window exists
|
|
48
|
+
*/
|
|
49
|
+
readonly host?: MaybeRefOrGetter<FullscreenHost | null | undefined>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Exit fullscreen when the owning reactive scope stops while this
|
|
53
|
+
* composable's target is fullscreen.
|
|
54
|
+
*
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
readonly autoExit?: boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Navigation UI preference passed to `requestFullscreen`.
|
|
61
|
+
*
|
|
62
|
+
* @default "auto"
|
|
63
|
+
*/
|
|
64
|
+
readonly navigationUI?: FullscreenNavigationUI;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Reactive state and actions returned by {@link useFullscreen}. */
|
|
68
|
+
export interface FullscreenControls {
|
|
69
|
+
/** Whether fullscreen can be requested. */
|
|
70
|
+
readonly supported: ComputedRef<boolean>;
|
|
71
|
+
|
|
72
|
+
/** Whether this composable's target is the current fullscreen element. */
|
|
73
|
+
readonly isFullscreen: Readonly<Ref<boolean>>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Enter fullscreen. Browsers require a user gesture.
|
|
77
|
+
*
|
|
78
|
+
* @returns Whether the target is fullscreen afterwards.
|
|
79
|
+
*/
|
|
80
|
+
readonly enter: () => Promise<boolean>;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Exit fullscreen when this composable's target owns it.
|
|
84
|
+
*
|
|
85
|
+
* @returns Whether the target is fullscreen afterwards.
|
|
86
|
+
*/
|
|
87
|
+
readonly exit: () => Promise<boolean>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Toggle fullscreen.
|
|
91
|
+
*
|
|
92
|
+
* @returns Whether the target is fullscreen afterwards.
|
|
93
|
+
*/
|
|
94
|
+
readonly toggle: () => Promise<boolean>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const changeEvents = ["fullscreenchange", "webkitfullscreenchange"] as const;
|
|
98
|
+
|
|
99
|
+
function browserFullscreenHost(): FullscreenHost | undefined {
|
|
100
|
+
return typeof window === "undefined" ? undefined : window.document;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function currentElement(host: FullscreenHost): unknown {
|
|
104
|
+
return host.fullscreenElement ?? host.webkitFullscreenElement ?? null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Enter, exit, and observe fullscreen for an element.
|
|
109
|
+
*
|
|
110
|
+
* Supports the standard Fullscreen API and the WebKit-prefixed variant.
|
|
111
|
+
* `isFullscreen` is true only while *this* target is the fullscreen element
|
|
112
|
+
* and follows `fullscreenchange`, so pressing Escape is reflected. Listeners
|
|
113
|
+
* are removed when the owning scope stops; with `autoExit` the target also
|
|
114
|
+
* leaves fullscreen then.
|
|
115
|
+
*
|
|
116
|
+
* Server rendering: `supported` and `isFullscreen` are false and nothing is
|
|
117
|
+
* requested.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* const player = useTemplateRef<HTMLElement>("player");
|
|
122
|
+
* const { toggle, isFullscreen } = useFullscreen(player);
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @param target Reactive element; defaults to the document element.
|
|
126
|
+
* @param options Capability, navigation UI, and exit policy.
|
|
127
|
+
* @default options {}
|
|
128
|
+
* @returns Fullscreen state and actions.
|
|
129
|
+
*/
|
|
130
|
+
export function useFullscreen(
|
|
131
|
+
target?: MaybeRefOrGetter<FullscreenElementLike | null | undefined>,
|
|
132
|
+
options: UseFullscreenOptions = {},
|
|
133
|
+
): FullscreenControls {
|
|
134
|
+
const isFullscreen = ref(false);
|
|
135
|
+
const resolveHost = (): FullscreenHost | undefined =>
|
|
136
|
+
options.host === undefined ? browserFullscreenHost() : (toValue(options.host) ?? undefined);
|
|
137
|
+
const resolveTarget = (): FullscreenElementLike | undefined =>
|
|
138
|
+
target === undefined
|
|
139
|
+
? (resolveHost()?.documentElement ?? undefined)
|
|
140
|
+
: (toValue(target) ?? undefined);
|
|
141
|
+
|
|
142
|
+
const update = (): void => {
|
|
143
|
+
const host = resolveHost();
|
|
144
|
+
const element = resolveTarget();
|
|
145
|
+
isFullscreen.value =
|
|
146
|
+
host !== undefined && element !== undefined && toRaw(currentElement(host)) === toRaw(element);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const supported = computed(() => {
|
|
150
|
+
const host = resolveHost();
|
|
151
|
+
const element = resolveTarget();
|
|
152
|
+
if (!host || !element) return false;
|
|
153
|
+
const enabled = host.fullscreenEnabled ?? host.webkitFullscreenEnabled ?? true;
|
|
154
|
+
return (
|
|
155
|
+
enabled &&
|
|
156
|
+
(typeof element.requestFullscreen === "function" ||
|
|
157
|
+
typeof element.webkitRequestFullscreen === "function")
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const enter = async (): Promise<boolean> => {
|
|
162
|
+
const element = resolveTarget();
|
|
163
|
+
if (!supported.value || !element) return false;
|
|
164
|
+
if (isFullscreen.value) return true;
|
|
165
|
+
try {
|
|
166
|
+
if (element.requestFullscreen) {
|
|
167
|
+
await element.requestFullscreen({ navigationUI: options.navigationUI ?? "auto" });
|
|
168
|
+
} else {
|
|
169
|
+
element.webkitRequestFullscreen?.();
|
|
170
|
+
}
|
|
171
|
+
} catch {
|
|
172
|
+
// Rejected requests (no user gesture, permissions policy) leave the
|
|
173
|
+
// state unchanged; `isFullscreen` reports the outcome.
|
|
174
|
+
}
|
|
175
|
+
update();
|
|
176
|
+
return isFullscreen.value;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const exit = async (): Promise<boolean> => {
|
|
180
|
+
const host = resolveHost();
|
|
181
|
+
update();
|
|
182
|
+
if (!host || !isFullscreen.value) return isFullscreen.value;
|
|
183
|
+
try {
|
|
184
|
+
if (host.exitFullscreen) await host.exitFullscreen();
|
|
185
|
+
else host.webkitExitFullscreen?.();
|
|
186
|
+
} catch {
|
|
187
|
+
// Exiting while the document already left fullscreen rejects; the
|
|
188
|
+
// re-read below reports the real state.
|
|
189
|
+
}
|
|
190
|
+
update();
|
|
191
|
+
return isFullscreen.value;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const toggle = (): Promise<boolean> => (isFullscreen.value ? exit() : enter());
|
|
195
|
+
|
|
196
|
+
watch(
|
|
197
|
+
[resolveHost, resolveTarget],
|
|
198
|
+
([host], _previous, onCleanup) => {
|
|
199
|
+
update();
|
|
200
|
+
if (!host) return;
|
|
201
|
+
for (const event of changeEvents) host.addEventListener(event, update);
|
|
202
|
+
onCleanup(() => {
|
|
203
|
+
for (const event of changeEvents) host.removeEventListener(event, update);
|
|
204
|
+
});
|
|
205
|
+
},
|
|
206
|
+
{ immediate: true, flush: "sync" },
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
tryOnScopeDispose(() => {
|
|
210
|
+
if (options.autoExit ?? false) void exit();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return { supported, isFullscreen: readonly(isFullscreen), enter, exit, toggle };
|
|
214
|
+
}
|
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
hasInjectionContext,
|
|
4
|
+
readonly,
|
|
5
|
+
shallowReadonly,
|
|
6
|
+
shallowRef,
|
|
7
|
+
toValue,
|
|
8
|
+
watch,
|
|
9
|
+
watchPostEffect,
|
|
10
|
+
} from "vue";
|
|
11
|
+
import type { ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
|
|
12
|
+
|
|
13
|
+
import { tryOnScopeDispose } from "./scope.ts";
|
|
14
|
+
import { useRafFn } from "./use-raf-fn.ts";
|
|
15
|
+
import type { FrameScheduler } from "./use-raf-fn.ts";
|
|
16
|
+
|
|
17
|
+
/** Button indices of the W3C "standard" gamepad mapping. */
|
|
18
|
+
export const standardGamepadButtons = {
|
|
19
|
+
faceBottom: 0,
|
|
20
|
+
faceRight: 1,
|
|
21
|
+
faceLeft: 2,
|
|
22
|
+
faceTop: 3,
|
|
23
|
+
leftBumper: 4,
|
|
24
|
+
rightBumper: 5,
|
|
25
|
+
leftTrigger: 6,
|
|
26
|
+
rightTrigger: 7,
|
|
27
|
+
select: 8,
|
|
28
|
+
start: 9,
|
|
29
|
+
leftStick: 10,
|
|
30
|
+
rightStick: 11,
|
|
31
|
+
dpadUp: 12,
|
|
32
|
+
dpadDown: 13,
|
|
33
|
+
dpadLeft: 14,
|
|
34
|
+
dpadRight: 15,
|
|
35
|
+
home: 16,
|
|
36
|
+
} as const;
|
|
37
|
+
|
|
38
|
+
/** Axis indices of the W3C "standard" gamepad mapping. */
|
|
39
|
+
export const standardGamepadAxes = {
|
|
40
|
+
leftStickX: 0,
|
|
41
|
+
leftStickY: 1,
|
|
42
|
+
rightStickX: 2,
|
|
43
|
+
rightStickY: 3,
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
/** Minimal `GamepadButton` read by {@link useGamepad}. */
|
|
47
|
+
export interface GamepadButtonLike {
|
|
48
|
+
/** Whether the button is pressed. */
|
|
49
|
+
readonly pressed: boolean;
|
|
50
|
+
/** Whether the button is touched (defaults to `pressed` when absent). */
|
|
51
|
+
readonly touched?: boolean;
|
|
52
|
+
/** Analog value in `[0, 1]`. */
|
|
53
|
+
readonly value: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Minimal `GamepadHapticActuator` used for vibration. */
|
|
57
|
+
export interface GamepadVibrationActuatorLike {
|
|
58
|
+
/** Play a haptic effect. */
|
|
59
|
+
playEffect(type: string, params: GamepadVibrationParams): Promise<unknown>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Minimal live `Gamepad` object read by {@link useGamepad}. */
|
|
63
|
+
export interface GamepadLike {
|
|
64
|
+
/** Device identifier string. */
|
|
65
|
+
readonly id: string;
|
|
66
|
+
/** Slot index in `navigator.getGamepads()`. */
|
|
67
|
+
readonly index: number;
|
|
68
|
+
/** Whether the pad is still connected. */
|
|
69
|
+
readonly connected: boolean;
|
|
70
|
+
/** Layout mapping (`"standard"` or `""`). */
|
|
71
|
+
readonly mapping: string;
|
|
72
|
+
/** Last update timestamp. */
|
|
73
|
+
readonly timestamp: number;
|
|
74
|
+
/** Button states. */
|
|
75
|
+
readonly buttons: ArrayLike<GamepadButtonLike>;
|
|
76
|
+
/** Axis values in `[-1, 1]`. */
|
|
77
|
+
readonly axes: ArrayLike<number>;
|
|
78
|
+
/** Haptic actuator, when the pad supports vibration. */
|
|
79
|
+
readonly vibrationActuator?: GamepadVibrationActuatorLike | null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Window-like capability used by {@link useGamepad}. */
|
|
83
|
+
export interface GamepadHost {
|
|
84
|
+
/** Navigator exposing `getGamepads()`. */
|
|
85
|
+
readonly navigator: {
|
|
86
|
+
/** Read the current pads (live objects, `null` for empty slots). */
|
|
87
|
+
getGamepads(): ArrayLike<GamepadLike | null>;
|
|
88
|
+
};
|
|
89
|
+
/** Subscribe to `gamepadconnected` / `gamepaddisconnected`. */
|
|
90
|
+
addEventListener(type: string, listener: () => void): void;
|
|
91
|
+
/** Unsubscribe from `gamepadconnected` / `gamepaddisconnected`. */
|
|
92
|
+
removeEventListener(type: string, listener: () => void): void;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Parameters of a `dual-rumble` vibration effect. */
|
|
96
|
+
export interface GamepadVibrationParams {
|
|
97
|
+
/** Effect duration in milliseconds. */
|
|
98
|
+
readonly duration: number;
|
|
99
|
+
/** Delay before the effect starts, in milliseconds. */
|
|
100
|
+
readonly startDelay?: number;
|
|
101
|
+
/** Low-frequency motor magnitude in `[0, 1]`. */
|
|
102
|
+
readonly strongMagnitude?: number;
|
|
103
|
+
/** High-frequency motor magnitude in `[0, 1]`. */
|
|
104
|
+
readonly weakMagnitude?: number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Plain, copied state of one button. */
|
|
108
|
+
export interface GamepadButtonState {
|
|
109
|
+
/** Whether the button is pressed. */
|
|
110
|
+
readonly pressed: boolean;
|
|
111
|
+
/** Whether the button is touched. */
|
|
112
|
+
readonly touched: boolean;
|
|
113
|
+
/** Analog value in `[0, 1]`. */
|
|
114
|
+
readonly value: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Immutable copy of a pad taken at one poll; never a live `Gamepad`. */
|
|
118
|
+
export interface GamepadSnapshot {
|
|
119
|
+
/** Device identifier string. */
|
|
120
|
+
readonly id: string;
|
|
121
|
+
/** Slot index. */
|
|
122
|
+
readonly index: number;
|
|
123
|
+
/** Whether the pad was connected when copied. */
|
|
124
|
+
readonly connected: boolean;
|
|
125
|
+
/** Layout mapping (`"standard"` or `""`). */
|
|
126
|
+
readonly mapping: string;
|
|
127
|
+
/** Update timestamp of the copied state. */
|
|
128
|
+
readonly timestamp: number;
|
|
129
|
+
/** Copied button states. */
|
|
130
|
+
readonly buttons: readonly GamepadButtonState[];
|
|
131
|
+
/** Copied axis values. */
|
|
132
|
+
readonly axes: readonly number[];
|
|
133
|
+
/** Whether the pad exposes a vibration actuator. */
|
|
134
|
+
readonly vibration: boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Binds a mapping key to a button; the mapped value is a {@link GamepadButtonState}. */
|
|
138
|
+
export interface GamepadButtonBinding {
|
|
139
|
+
/** Button index (see {@link standardGamepadButtons}). */
|
|
140
|
+
readonly button: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Binds a mapping key to an axis; the mapped value is a number. */
|
|
144
|
+
export interface GamepadAxisBinding {
|
|
145
|
+
/** Axis index (see {@link standardGamepadAxes}). */
|
|
146
|
+
readonly axis: number;
|
|
147
|
+
/** Values with a magnitude below this become `0`; the rest is rescaled to `[-1, 1]`. */
|
|
148
|
+
readonly deadzone?: number;
|
|
149
|
+
/** Negate the axis value. */
|
|
150
|
+
readonly invert?: boolean;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Named bindings from which a typed per-pad state is derived. */
|
|
154
|
+
export type GamepadMapping = Readonly<Record<string, GamepadButtonBinding | GamepadAxisBinding>>;
|
|
155
|
+
|
|
156
|
+
/** Typed state produced by a {@link GamepadMapping}: axes map to numbers, buttons to states. */
|
|
157
|
+
export type MappedGamepad<Mapping extends GamepadMapping> = {
|
|
158
|
+
readonly [Key in keyof Mapping]: Mapping[Key] extends { readonly axis: number }
|
|
159
|
+
? number
|
|
160
|
+
: GamepadButtonState;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/** One connected pad: its snapshot plus the mapped state. */
|
|
164
|
+
export interface ConnectedGamepad<
|
|
165
|
+
Mapping extends GamepadMapping = Record<never, never>,
|
|
166
|
+
> extends GamepadSnapshot {
|
|
167
|
+
/** State derived from the `mapping` option. */
|
|
168
|
+
readonly mapped: MappedGamepad<Mapping>;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Options for {@link useGamepad}. */
|
|
172
|
+
export interface UseGamepadOptions<Mapping extends GamepadMapping = Record<never, never>> {
|
|
173
|
+
/**
|
|
174
|
+
* Window-like host providing `navigator.getGamepads()` and connection events.
|
|
175
|
+
*
|
|
176
|
+
* @default window when `navigator.getGamepads` exists
|
|
177
|
+
*/
|
|
178
|
+
readonly host?: MaybeRefOrGetter<GamepadHost | null | undefined>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Named bindings applied to every pad; the keys and value kinds type `mapped`.
|
|
182
|
+
*
|
|
183
|
+
* @default {}
|
|
184
|
+
*/
|
|
185
|
+
readonly mapping?: Mapping;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Frame host driving the polling loop.
|
|
189
|
+
*
|
|
190
|
+
* @default globalThis animation-frame functions
|
|
191
|
+
*/
|
|
192
|
+
readonly scheduler?: FrameScheduler;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Start polling immediately.
|
|
196
|
+
*
|
|
197
|
+
* @default true
|
|
198
|
+
*/
|
|
199
|
+
readonly immediate?: boolean;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Reactive state and actions returned by {@link useGamepad}. */
|
|
203
|
+
export interface GamepadControls<Mapping extends GamepadMapping = Record<never, never>> {
|
|
204
|
+
/** Whether the Gamepad API is available. */
|
|
205
|
+
readonly supported: ComputedRef<boolean>;
|
|
206
|
+
/** Connected pads, copied on every poll that saw a change. */
|
|
207
|
+
readonly gamepads: Readonly<ShallowRef<readonly ConnectedGamepad<Mapping>[]>>;
|
|
208
|
+
/** Whether polling is running. */
|
|
209
|
+
readonly isActive: Readonly<Ref<boolean>>;
|
|
210
|
+
/** Most recent vibration failure. */
|
|
211
|
+
readonly error: Readonly<ShallowRef<unknown>>;
|
|
212
|
+
/** Stop polling. Idempotent. */
|
|
213
|
+
readonly pause: () => void;
|
|
214
|
+
/** Resume polling. Idempotent. */
|
|
215
|
+
readonly resume: () => void;
|
|
216
|
+
/** Read the pads once, outside the frame loop. */
|
|
217
|
+
readonly refresh: () => void;
|
|
218
|
+
/**
|
|
219
|
+
* Play a vibration effect on the pad at `index`.
|
|
220
|
+
*
|
|
221
|
+
* @returns Whether the effect played; failures land in `error`.
|
|
222
|
+
*/
|
|
223
|
+
readonly vibrate: (
|
|
224
|
+
index: number,
|
|
225
|
+
params: GamepadVibrationParams,
|
|
226
|
+
type?: string,
|
|
227
|
+
) => Promise<boolean>;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function browserGamepadHost(): GamepadHost | undefined {
|
|
231
|
+
if (typeof window === "undefined") return undefined;
|
|
232
|
+
return typeof window.navigator.getGamepads === "function" ? window : undefined;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function invalidMapping(message: string): RangeError {
|
|
236
|
+
return new RangeError(`[VIZE_COMPOSE_GAMEPAD_INVALID_MAPPING] ${message}`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function isAxisBinding(
|
|
240
|
+
binding: GamepadButtonBinding | GamepadAxisBinding,
|
|
241
|
+
): binding is GamepadAxisBinding {
|
|
242
|
+
return "axis" in binding;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function checkIndex(index: number, key: string): void {
|
|
246
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
247
|
+
throw invalidMapping(`"${key}" index must be a non-negative integer; received ${index}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Copy a live pad into an immutable {@link GamepadSnapshot}.
|
|
253
|
+
*
|
|
254
|
+
* @param pad Live `Gamepad` (or compatible) object.
|
|
255
|
+
* @returns The copied state.
|
|
256
|
+
*/
|
|
257
|
+
export function snapshotGamepad(pad: GamepadLike): GamepadSnapshot {
|
|
258
|
+
return {
|
|
259
|
+
id: pad.id,
|
|
260
|
+
index: pad.index,
|
|
261
|
+
connected: pad.connected,
|
|
262
|
+
mapping: pad.mapping,
|
|
263
|
+
timestamp: pad.timestamp,
|
|
264
|
+
buttons: Array.from(pad.buttons, (button) => ({
|
|
265
|
+
pressed: button.pressed,
|
|
266
|
+
touched: button.touched ?? button.pressed,
|
|
267
|
+
value: button.value,
|
|
268
|
+
})),
|
|
269
|
+
axes: Array.from(pad.axes),
|
|
270
|
+
vibration: pad.vibrationActuator != null,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Derive typed named state from a snapshot. Missing buttons read as released
|
|
276
|
+
* and missing axes as `0`; axis dead zones are applied and rescaled.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```ts
|
|
280
|
+
* const state = mapGamepad(pad, { jump: { button: 0 }, moveX: { axis: 0, deadzone: 0.1 } });
|
|
281
|
+
* state.jump.pressed; state.moveX; // boolean, number
|
|
282
|
+
* ```
|
|
283
|
+
*
|
|
284
|
+
* @param snapshot Copied pad state.
|
|
285
|
+
* @param mapping Named button and axis bindings.
|
|
286
|
+
* @throws `RangeError` tagged `VIZE_COMPOSE_GAMEPAD_INVALID_MAPPING` for a
|
|
287
|
+
* negative or fractional index or a dead zone outside `[0, 1)`.
|
|
288
|
+
* @returns State keyed like `mapping`.
|
|
289
|
+
*/
|
|
290
|
+
export function mapGamepad<const Mapping extends GamepadMapping>(
|
|
291
|
+
snapshot: Pick<GamepadSnapshot, "buttons" | "axes">,
|
|
292
|
+
mapping: Mapping,
|
|
293
|
+
): MappedGamepad<Mapping> {
|
|
294
|
+
const result: Record<string, number | GamepadButtonState> = {};
|
|
295
|
+
for (const [key, binding] of Object.entries(mapping)) {
|
|
296
|
+
if (isAxisBinding(binding)) {
|
|
297
|
+
checkIndex(binding.axis, key);
|
|
298
|
+
const deadzone = binding.deadzone ?? 0;
|
|
299
|
+
if (!(deadzone >= 0 && deadzone < 1)) {
|
|
300
|
+
throw invalidMapping(`"${key}" deadzone must be in [0, 1); received ${deadzone}`);
|
|
301
|
+
}
|
|
302
|
+
const raw = snapshot.axes[binding.axis] ?? 0;
|
|
303
|
+
const magnitude = Math.abs(raw);
|
|
304
|
+
const value =
|
|
305
|
+
magnitude < deadzone ? 0 : (Math.sign(raw) * (magnitude - deadzone)) / (1 - deadzone);
|
|
306
|
+
result[key] = (binding.invert ?? false) ? 0 - value : value;
|
|
307
|
+
} else {
|
|
308
|
+
checkIndex(binding.button, key);
|
|
309
|
+
result[key] = snapshot.buttons[binding.button] ?? {
|
|
310
|
+
pressed: false,
|
|
311
|
+
touched: false,
|
|
312
|
+
value: 0,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// The loop above assigns exactly one value of the declared kind per mapping key.
|
|
317
|
+
return result as MappedGamepad<Mapping>;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Track connected gamepads as immutable snapshots, polled on animation
|
|
322
|
+
* frames, with optional typed named bindings.
|
|
323
|
+
*
|
|
324
|
+
* Pads are re-read every frame while active and on `gamepadconnected` /
|
|
325
|
+
* `gamepaddisconnected`; `gamepads` is replaced only when a pad's timestamp
|
|
326
|
+
* or connection changed. Entries are plain copies, so they are safe to keep
|
|
327
|
+
* or serialize. The frame loop and listeners stop with the owning reactive
|
|
328
|
+
* scope; outside a scope call `pause()`.
|
|
329
|
+
*
|
|
330
|
+
* Server rendering: no frames or listeners, `supported` is false and
|
|
331
|
+
* `gamepads` is empty.
|
|
332
|
+
* Inside a component the host is resolved after mounting, so hydration
|
|
333
|
+
* renders this server state first.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* const { gamepads } = useGamepad({ mapping: { jump: { button: 0 }, moveX: { axis: 0, deadzone: 0.1 } } });
|
|
338
|
+
* const player = computed(() => gamepads.value[0]?.mapped);
|
|
339
|
+
* ```
|
|
340
|
+
*
|
|
341
|
+
* @param options Host, mapping, and scheduler.
|
|
342
|
+
* @default options {}
|
|
343
|
+
* @throws `RangeError` tagged `VIZE_COMPOSE_GAMEPAD_INVALID_MAPPING` for an invalid mapping.
|
|
344
|
+
* @returns Pad state and polling controls.
|
|
345
|
+
*/
|
|
346
|
+
export function useGamepad<const Mapping extends GamepadMapping = Record<never, never>>(
|
|
347
|
+
options: UseGamepadOptions<Mapping> = {},
|
|
348
|
+
): GamepadControls<Mapping> {
|
|
349
|
+
const gamepads = shallowRef<readonly ConnectedGamepad<Mapping>[]>([]);
|
|
350
|
+
const error = shallowRef<unknown>(undefined);
|
|
351
|
+
const mapping = options.mapping;
|
|
352
|
+
if (mapping !== undefined) mapGamepad({ buttons: [], axes: [] }, mapping);
|
|
353
|
+
|
|
354
|
+
// Inside a component the host is resolved only after mounting, so a
|
|
355
|
+
// hydrating client renders the server's unsupported state first. Outside
|
|
356
|
+
// components it resolves synchronously.
|
|
357
|
+
const hydrated = shallowRef(!hasInjectionContext());
|
|
358
|
+
if (!hydrated.value) {
|
|
359
|
+
watchPostEffect(() => {
|
|
360
|
+
hydrated.value = true;
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const resolveHost = (): GamepadHost | undefined => {
|
|
365
|
+
if (!hydrated.value) return undefined;
|
|
366
|
+
return options.host === undefined ? browserGamepadHost() : (toValue(options.host) ?? undefined);
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const readPads = (host: GamepadHost): GamepadLike[] =>
|
|
370
|
+
Array.from(host.navigator.getGamepads()).filter(
|
|
371
|
+
(pad): pad is GamepadLike => pad !== null && pad.connected,
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
const refresh = (): void => {
|
|
375
|
+
const host = resolveHost();
|
|
376
|
+
const pads = host ? readPads(host) : [];
|
|
377
|
+
const previous = gamepads.value;
|
|
378
|
+
const unchanged =
|
|
379
|
+
pads.length === previous.length &&
|
|
380
|
+
pads.every(
|
|
381
|
+
(pad, position) =>
|
|
382
|
+
previous[position]?.index === pad.index &&
|
|
383
|
+
previous[position]?.id === pad.id &&
|
|
384
|
+
previous[position]?.timestamp === pad.timestamp,
|
|
385
|
+
);
|
|
386
|
+
if (unchanged) return;
|
|
387
|
+
gamepads.value = pads.map((pad) => {
|
|
388
|
+
const snapshot = snapshotGamepad(pad);
|
|
389
|
+
const mapped = mapGamepad(snapshot, mapping ?? {});
|
|
390
|
+
// Without a mapping `Mapping` defaults to the empty record, which `{}` satisfies.
|
|
391
|
+
return { ...snapshot, mapped: mapped as MappedGamepad<Mapping> };
|
|
392
|
+
});
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const loop = useRafFn(refresh, {
|
|
396
|
+
immediate: false,
|
|
397
|
+
runOnServer: true,
|
|
398
|
+
...(options.scheduler === undefined ? {} : { scheduler: options.scheduler }),
|
|
399
|
+
});
|
|
400
|
+
const wanted = shallowRef(options.immediate ?? true);
|
|
401
|
+
|
|
402
|
+
const resume = (): void => {
|
|
403
|
+
wanted.value = true;
|
|
404
|
+
if (resolveHost()) loop.resume();
|
|
405
|
+
};
|
|
406
|
+
const pause = (): void => {
|
|
407
|
+
wanted.value = false;
|
|
408
|
+
loop.pause();
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
watch(
|
|
412
|
+
resolveHost,
|
|
413
|
+
(host, _previous, onCleanup) => {
|
|
414
|
+
if (!host) {
|
|
415
|
+
loop.pause();
|
|
416
|
+
gamepads.value = [];
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
host.addEventListener("gamepadconnected", refresh);
|
|
420
|
+
host.addEventListener("gamepaddisconnected", refresh);
|
|
421
|
+
onCleanup(() => {
|
|
422
|
+
host.removeEventListener("gamepadconnected", refresh);
|
|
423
|
+
host.removeEventListener("gamepaddisconnected", refresh);
|
|
424
|
+
});
|
|
425
|
+
refresh();
|
|
426
|
+
if (wanted.value) loop.resume();
|
|
427
|
+
},
|
|
428
|
+
{ immediate: true, flush: "sync" },
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
const vibrate = async (
|
|
432
|
+
index: number,
|
|
433
|
+
params: GamepadVibrationParams,
|
|
434
|
+
type = "dual-rumble",
|
|
435
|
+
): Promise<boolean> => {
|
|
436
|
+
const host = resolveHost();
|
|
437
|
+
const actuator = host
|
|
438
|
+
? readPads(host).find((pad) => pad.index === index)?.vibrationActuator
|
|
439
|
+
: undefined;
|
|
440
|
+
if (!actuator) return false;
|
|
441
|
+
try {
|
|
442
|
+
await actuator.playEffect(type, params);
|
|
443
|
+
error.value = undefined;
|
|
444
|
+
return true;
|
|
445
|
+
} catch (cause) {
|
|
446
|
+
error.value = cause;
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
tryOnScopeDispose(pause);
|
|
452
|
+
|
|
453
|
+
return {
|
|
454
|
+
supported: computed(() => resolveHost() !== undefined),
|
|
455
|
+
gamepads: shallowReadonly(gamepads),
|
|
456
|
+
isActive: loop.isActive,
|
|
457
|
+
error: readonly(error),
|
|
458
|
+
pause,
|
|
459
|
+
resume,
|
|
460
|
+
refresh,
|
|
461
|
+
vibrate,
|
|
462
|
+
};
|
|
463
|
+
}
|