foldkit-primitives 0.15.4 → 0.16.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/device/fullscreen.d.ts +28 -0
- package/dist/device/fullscreen.d.ts.map +1 -0
- package/dist/device/fullscreen.js +69 -0
- package/dist/device/fullscreen.js.map +1 -0
- package/dist/device/geolocation.d.ts +56 -0
- package/dist/device/geolocation.d.ts.map +1 -0
- package/dist/device/geolocation.js +87 -0
- package/dist/device/geolocation.js.map +1 -0
- package/dist/device/index.d.ts +5 -0
- package/dist/device/index.js +6 -0
- package/dist/device/media-devices.d.ts +88 -0
- package/dist/device/media-devices.d.ts.map +1 -0
- package/dist/device/media-devices.js +117 -0
- package/dist/device/media-devices.js.map +1 -0
- package/dist/device/media-stream.d.ts +93 -0
- package/dist/device/media-stream.d.ts.map +1 -0
- package/dist/device/media-stream.js +106 -0
- package/dist/device/media-stream.js.map +1 -0
- package/dist/device/permissions.d.ts +106 -0
- package/dist/device/permissions.d.ts.map +1 -0
- package/dist/device/permissions.js +143 -0
- package/dist/device/permissions.js.map +1 -0
- package/dist/dom/autofocus.d.ts +15 -0
- package/dist/dom/autofocus.d.ts.map +1 -0
- package/dist/dom/autofocus.js +22 -0
- package/dist/dom/autofocus.js.map +1 -0
- package/dist/dom/clipboard.d.ts +30 -0
- package/dist/dom/clipboard.d.ts.map +1 -0
- package/dist/dom/clipboard.js +50 -0
- package/dist/dom/clipboard.js.map +1 -0
- package/dist/dom/editable-text.d.ts +72 -0
- package/dist/dom/editable-text.d.ts.map +1 -0
- package/dist/dom/editable-text.js +232 -0
- package/dist/dom/editable-text.js.map +1 -0
- package/dist/dom/fluid-hover.d.ts +93 -0
- package/dist/dom/fluid-hover.d.ts.map +1 -0
- package/dist/dom/fluid-hover.js +294 -0
- package/dist/dom/fluid-hover.js.map +1 -0
- package/dist/dom/focus-scope.d.ts +21 -0
- package/dist/dom/focus-scope.d.ts.map +1 -0
- package/dist/dom/focus-scope.js +93 -0
- package/dist/dom/focus-scope.js.map +1 -0
- package/dist/dom/follow-tab-stop.d.ts +11 -0
- package/dist/dom/follow-tab-stop.d.ts.map +1 -0
- package/dist/dom/follow-tab-stop.js +54 -0
- package/dist/dom/follow-tab-stop.js.map +1 -0
- package/dist/dom/image-decode.d.ts +27 -0
- package/dist/dom/image-decode.d.ts.map +1 -0
- package/dist/dom/image-decode.js +50 -0
- package/dist/dom/image-decode.js.map +1 -0
- package/dist/dom/index.d.ts +24 -0
- package/dist/dom/index.js +25 -0
- package/dist/dom/input-mask.d.ts +35 -0
- package/dist/dom/input-mask.d.ts.map +1 -0
- package/dist/dom/input-mask.js +90 -0
- package/dist/dom/input-mask.js.map +1 -0
- package/dist/dom/keep-in-view.d.ts +16 -0
- package/dist/dom/keep-in-view.d.ts.map +1 -0
- package/dist/dom/keep-in-view.js +38 -0
- package/dist/dom/keep-in-view.js.map +1 -0
- package/dist/dom/keyboard-inset.d.ts +29 -0
- package/dist/dom/keyboard-inset.d.ts.map +1 -0
- package/dist/dom/keyboard-inset.js +45 -0
- package/dist/dom/keyboard-inset.js.map +1 -0
- package/dist/dom/layers.d.ts +6 -0
- package/dist/dom/layers.d.ts.map +1 -0
- package/dist/dom/layers.js +35 -0
- package/dist/dom/layers.js.map +1 -0
- package/dist/dom/measure.d.ts +42 -0
- package/dist/dom/measure.d.ts.map +1 -0
- package/dist/dom/measure.js +123 -0
- package/dist/dom/measure.js.map +1 -0
- package/dist/dom/move.d.ts +45 -0
- package/dist/dom/move.d.ts.map +1 -0
- package/dist/dom/move.js +96 -0
- package/dist/dom/move.js.map +1 -0
- package/dist/dom/pointed-links.d.ts +13 -0
- package/dist/dom/pointed-links.d.ts.map +1 -0
- package/dist/dom/pointed-links.js +59 -0
- package/dist/dom/pointed-links.js.map +1 -0
- package/dist/dom/pointer-drag.d.ts +132 -0
- package/dist/dom/pointer-drag.d.ts.map +1 -0
- package/dist/dom/pointer-drag.js +307 -0
- package/dist/dom/pointer-drag.js.map +1 -0
- package/dist/dom/pointer-position.d.ts +133 -0
- package/dist/dom/pointer-position.d.ts.map +1 -0
- package/dist/dom/pointer-position.js +173 -0
- package/dist/dom/pointer-position.js.map +1 -0
- package/dist/dom/script-loader.d.ts +12 -0
- package/dist/dom/script-loader.d.ts.map +1 -0
- package/dist/dom/script-loader.js +54 -0
- package/dist/dom/script-loader.js.map +1 -0
- package/dist/dom/scroll-bars.d.ts +52 -0
- package/dist/dom/scroll-bars.d.ts.map +1 -0
- package/dist/dom/scroll-bars.js +259 -0
- package/dist/dom/scroll-bars.js.map +1 -0
- package/dist/dom/scroll-settle.d.ts +33 -0
- package/dist/dom/scroll-settle.d.ts.map +1 -0
- package/dist/dom/scroll-settle.js +84 -0
- package/dist/dom/scroll-settle.js.map +1 -0
- package/dist/dom/scroll.d.ts +21 -0
- package/dist/dom/scroll.d.ts.map +1 -0
- package/dist/dom/scroll.js +141 -0
- package/dist/dom/scroll.js.map +1 -0
- package/dist/dom/share.d.ts +19 -0
- package/dist/dom/share.d.ts.map +1 -0
- package/dist/dom/share.js +41 -0
- package/dist/dom/share.js.map +1 -0
- package/dist/dom/swipe.d.ts +121 -0
- package/dist/dom/swipe.d.ts.map +1 -0
- package/dist/dom/swipe.js +291 -0
- package/dist/dom/swipe.js.map +1 -0
- package/dist/dom/targets.d.ts +45 -0
- package/dist/dom/targets.d.ts.map +1 -0
- package/dist/dom/targets.js +70 -0
- package/dist/dom/targets.js.map +1 -0
- package/dist/dom/track-box.d.ts +61 -0
- package/dist/dom/track-box.d.ts.map +1 -0
- package/dist/dom/track-box.js +131 -0
- package/dist/dom/track-box.js.map +1 -0
- package/dist/events/active-element.d.ts +15 -0
- package/dist/events/active-element.d.ts.map +1 -0
- package/dist/events/active-element.js +33 -0
- package/dist/events/active-element.js.map +1 -0
- package/dist/events/hotkeys.d.ts +22 -0
- package/dist/events/hotkeys.d.ts.map +1 -0
- package/dist/events/hotkeys.js +56 -0
- package/dist/events/hotkeys.js.map +1 -0
- package/dist/events/idle.d.ts +29 -0
- package/dist/events/idle.d.ts.map +1 -0
- package/dist/events/idle.js +51 -0
- package/dist/events/idle.js.map +1 -0
- package/dist/events/index.d.ts +9 -0
- package/dist/events/index.js +10 -0
- package/dist/{input-modality-l7InESYh.d.mts → events/input-modality.d.ts} +9 -10
- package/dist/events/input-modality.d.ts.map +1 -0
- package/dist/{input-modality-XwQOFLip.mjs → events/input-modality.js} +2 -2
- package/dist/events/input-modality.js.map +1 -0
- package/dist/events/keyboard.d.ts +30 -0
- package/dist/events/keyboard.d.ts.map +1 -0
- package/dist/events/keyboard.js +55 -0
- package/dist/events/keyboard.js.map +1 -0
- package/dist/events/pointer.d.ts +15 -0
- package/dist/events/pointer.d.ts.map +1 -0
- package/dist/events/pointer.js +28 -0
- package/dist/events/pointer.js.map +1 -0
- package/dist/events/scroll.d.ts +16 -0
- package/dist/events/scroll.d.ts.map +1 -0
- package/dist/events/scroll.js +29 -0
- package/dist/events/scroll.js.map +1 -0
- package/dist/events/visibility.d.ts +25 -0
- package/dist/events/visibility.d.ts.map +1 -0
- package/dist/events/visibility.js +28 -0
- package/dist/events/visibility.js.map +1 -0
- package/dist/events/window-size.d.ts +30 -0
- package/dist/events/window-size.d.ts.map +1 -0
- package/dist/events/window-size.js +63 -0
- package/dist/events/window-size.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +10 -0
- package/dist/interaction/bundle-behavior.d.ts +37 -0
- package/dist/interaction/bundle-behavior.d.ts.map +1 -0
- package/dist/interaction/bundle-behavior.js +34 -0
- package/dist/interaction/bundle-behavior.js.map +1 -0
- package/dist/interaction/dismiss-layer.d.ts +100 -0
- package/dist/interaction/dismiss-layer.d.ts.map +1 -0
- package/dist/interaction/dismiss-layer.js +140 -0
- package/dist/interaction/dismiss-layer.js.map +1 -0
- package/dist/interaction/editable-text.d.ts +13 -0
- package/dist/interaction/editable-text.d.ts.map +1 -0
- package/dist/interaction/editable-text.js +17 -0
- package/dist/interaction/editable-text.js.map +1 -0
- package/dist/interaction/focus-scope.d.ts +21 -0
- package/dist/interaction/focus-scope.d.ts.map +1 -0
- package/dist/interaction/focus-scope.js +25 -0
- package/dist/interaction/focus-scope.js.map +1 -0
- package/dist/interaction/focus-visible.d.ts +9 -0
- package/dist/interaction/focus-visible.d.ts.map +1 -0
- package/dist/interaction/focus-visible.js +10 -0
- package/dist/interaction/focus-visible.js.map +1 -0
- package/dist/interaction/grid-navigation.d.ts +73 -0
- package/dist/interaction/grid-navigation.d.ts.map +1 -0
- package/dist/interaction/grid-navigation.js +137 -0
- package/dist/interaction/grid-navigation.js.map +1 -0
- package/dist/interaction/index.d.ts +21 -0
- package/dist/interaction/index.js +21 -0
- package/dist/interaction/layers.d.ts +12 -0
- package/dist/interaction/layers.d.ts.map +1 -0
- package/dist/interaction/layers.js +14 -0
- package/dist/interaction/layers.js.map +1 -0
- package/dist/interaction/list-navigation.d.ts +105 -0
- package/dist/interaction/list-navigation.d.ts.map +1 -0
- package/dist/interaction/list-navigation.js +168 -0
- package/dist/interaction/list-navigation.js.map +1 -0
- package/dist/interaction/live-announce.d.ts +70 -0
- package/dist/interaction/live-announce.d.ts.map +1 -0
- package/dist/interaction/live-announce.js +115 -0
- package/dist/interaction/live-announce.js.map +1 -0
- package/dist/interaction/long-press.d.ts +102 -0
- package/dist/interaction/long-press.d.ts.map +1 -0
- package/dist/interaction/long-press.js +115 -0
- package/dist/interaction/long-press.js.map +1 -0
- package/dist/interaction/move.d.ts +10 -0
- package/dist/interaction/move.d.ts.map +1 -0
- package/dist/interaction/move.js +17 -0
- package/dist/interaction/move.js.map +1 -0
- package/dist/interaction/overlay.d.ts +45 -0
- package/dist/interaction/overlay.d.ts.map +1 -0
- package/dist/interaction/overlay.js +57 -0
- package/dist/interaction/overlay.js.map +1 -0
- package/dist/interaction/placing.d.ts +86 -0
- package/dist/interaction/placing.d.ts.map +1 -0
- package/dist/interaction/placing.js +239 -0
- package/dist/interaction/placing.js.map +1 -0
- package/dist/interaction/pointer-drag.d.ts +23 -0
- package/dist/interaction/pointer-drag.d.ts.map +1 -0
- package/dist/interaction/pointer-drag.js +21 -0
- package/dist/interaction/pointer-drag.js.map +1 -0
- package/dist/interaction/press.d.ts +152 -0
- package/dist/interaction/press.d.ts.map +1 -0
- package/dist/interaction/press.js +229 -0
- package/dist/interaction/press.js.map +1 -0
- package/dist/interaction/roving-tabindex.d.ts +85 -0
- package/dist/interaction/roving-tabindex.d.ts.map +1 -0
- package/dist/interaction/roving-tabindex.js +142 -0
- package/dist/interaction/roving-tabindex.js.map +1 -0
- package/dist/interaction/selection.d.ts +72 -0
- package/dist/interaction/selection.d.ts.map +1 -0
- package/dist/interaction/selection.js +129 -0
- package/dist/interaction/selection.js.map +1 -0
- package/dist/interaction/targets.d.ts +15 -0
- package/dist/interaction/targets.d.ts.map +1 -0
- package/dist/interaction/targets.js +20 -0
- package/dist/interaction/targets.js.map +1 -0
- package/dist/interaction/tree-navigation.d.ts +111 -0
- package/dist/interaction/tree-navigation.d.ts.map +1 -0
- package/dist/interaction/tree-navigation.js +207 -0
- package/dist/interaction/tree-navigation.js.map +1 -0
- package/dist/interaction/typeahead.d.ts +73 -0
- package/dist/interaction/typeahead.d.ts.map +1 -0
- package/dist/interaction/typeahead.js +113 -0
- package/dist/interaction/typeahead.js.map +1 -0
- package/dist/internal.d.ts +16 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/{internal-C4gHodLc.mjs → internal.js} +7 -5
- package/dist/internal.js.map +1 -0
- package/dist/media/breakpoints.d.ts +37 -0
- package/dist/media/breakpoints.d.ts.map +1 -0
- package/dist/media/breakpoints.js +64 -0
- package/dist/media/breakpoints.js.map +1 -0
- package/dist/media/index.d.ts +3 -0
- package/dist/media/index.js +4 -0
- package/dist/media/mediaquery.d.ts +40 -0
- package/dist/media/mediaquery.d.ts.map +1 -0
- package/dist/media/mediaquery.js +42 -0
- package/dist/media/mediaquery.js.map +1 -0
- package/dist/media/platform.d.ts +30 -0
- package/dist/media/platform.d.ts.map +1 -0
- package/dist/media/platform.js +50 -0
- package/dist/media/platform.js.map +1 -0
- package/dist/motion/index.d.ts +5 -0
- package/dist/motion/index.js +5 -0
- package/dist/motion/motion.d.ts +16 -0
- package/dist/motion/motion.d.ts.map +1 -0
- package/dist/motion/motion.js +25 -0
- package/dist/motion/motion.js.map +1 -0
- package/dist/motion/presence.d.ts +37 -0
- package/dist/motion/presence.d.ts.map +1 -0
- package/dist/motion/presence.js +65 -0
- package/dist/motion/presence.js.map +1 -0
- package/dist/motion/spring.d.ts +50 -0
- package/dist/motion/spring.d.ts.map +1 -0
- package/dist/motion/spring.js +92 -0
- package/dist/motion/spring.js.map +1 -0
- package/dist/motion/tween.d.ts +44 -0
- package/dist/motion/tween.d.ts.map +1 -0
- package/dist/motion/tween.js +65 -0
- package/dist/motion/tween.js.map +1 -0
- package/dist/net/broadcast.d.ts +39 -0
- package/dist/net/broadcast.d.ts.map +1 -0
- package/dist/net/broadcast.js +73 -0
- package/dist/net/broadcast.js.map +1 -0
- package/dist/net/index.d.ts +5 -0
- package/dist/net/index.js +6 -0
- package/dist/net/online.d.ts +24 -0
- package/dist/net/online.d.ts.map +1 -0
- package/dist/net/online.js +26 -0
- package/dist/net/online.js.map +1 -0
- package/dist/net/sharedHost.d.ts +64 -0
- package/dist/net/sharedHost.d.ts.map +1 -0
- package/dist/net/sharedHost.js +124 -0
- package/dist/net/sharedHost.js.map +1 -0
- package/dist/net/sse.d.ts +115 -0
- package/dist/net/sse.d.ts.map +1 -0
- package/dist/net/sse.js +138 -0
- package/dist/net/sse.js.map +1 -0
- package/dist/net/websocket.d.ts +172 -0
- package/dist/net/websocket.d.ts.map +1 -0
- package/dist/net/websocket.js +199 -0
- package/dist/net/websocket.js.map +1 -0
- package/dist/observers/bounds.d.ts +24 -0
- package/dist/observers/bounds.d.ts.map +1 -0
- package/dist/observers/bounds.js +51 -0
- package/dist/observers/bounds.js.map +1 -0
- package/dist/observers/index.d.ts +4 -0
- package/dist/observers/index.js +5 -0
- package/dist/observers/intersection.d.ts +18 -0
- package/dist/observers/intersection.d.ts.map +1 -0
- package/dist/observers/intersection.js +33 -0
- package/dist/observers/intersection.js.map +1 -0
- package/dist/observers/mutation.d.ts +25 -0
- package/dist/observers/mutation.d.ts.map +1 -0
- package/dist/observers/mutation.js +53 -0
- package/dist/observers/mutation.js.map +1 -0
- package/dist/observers/resize.d.ts +18 -0
- package/dist/observers/resize.d.ts.map +1 -0
- package/dist/observers/resize.js +33 -0
- package/dist/observers/resize.js.map +1 -0
- package/dist/state/history.d.ts +115 -0
- package/dist/state/history.d.ts.map +1 -0
- package/dist/state/history.js +167 -0
- package/dist/state/history.js.map +1 -0
- package/dist/state/index.d.ts +6 -0
- package/dist/state/index.js +7 -0
- package/dist/state/locale.d.ts +27 -0
- package/dist/state/locale.d.ts.map +1 -0
- package/dist/state/locale.js +25 -0
- package/dist/state/locale.js.map +1 -0
- package/dist/state/pagination.d.ts +53 -0
- package/dist/state/pagination.d.ts.map +1 -0
- package/dist/state/pagination.js +72 -0
- package/dist/state/pagination.js.map +1 -0
- package/dist/state/range.d.ts +9 -0
- package/dist/state/range.d.ts.map +1 -0
- package/dist/state/range.js +18 -0
- package/dist/state/range.js.map +1 -0
- package/dist/state/selection.d.ts +47 -0
- package/dist/state/selection.d.ts.map +1 -0
- package/dist/state/selection.js +39 -0
- package/dist/state/selection.js.map +1 -0
- package/dist/state/virtual.d.ts +201 -0
- package/dist/state/virtual.d.ts.map +1 -0
- package/dist/state/{index.mjs → virtual.js} +10 -306
- package/dist/state/virtual.js.map +1 -0
- package/dist/time/debounce.d.ts +43 -0
- package/dist/time/debounce.d.ts.map +1 -0
- package/dist/time/debounce.js +65 -0
- package/dist/time/debounce.js.map +1 -0
- package/dist/time/index.d.ts +6 -0
- package/dist/time/index.js +7 -0
- package/dist/time/interval.d.ts +37 -0
- package/dist/time/interval.d.ts.map +1 -0
- package/dist/time/interval.js +52 -0
- package/dist/time/interval.js.map +1 -0
- package/dist/time/relative.d.ts +8 -0
- package/dist/time/relative.d.ts.map +1 -0
- package/dist/time/relative.js +27 -0
- package/dist/time/relative.js.map +1 -0
- package/dist/time/throttle.d.ts +38 -0
- package/dist/time/throttle.d.ts.map +1 -0
- package/dist/time/throttle.js +39 -0
- package/dist/time/throttle.js.map +1 -0
- package/dist/time/ticks.d.ts +21 -0
- package/dist/time/ticks.d.ts.map +1 -0
- package/dist/time/ticks.js +30 -0
- package/dist/time/ticks.js.map +1 -0
- package/dist/time/timer.d.ts +32 -0
- package/dist/time/timer.d.ts.map +1 -0
- package/dist/time/timer.js +50 -0
- package/dist/time/timer.js.map +1 -0
- package/package.json +31 -31
- package/dist/device/index.d.mts +0 -335
- package/dist/device/index.d.mts.map +0 -1
- package/dist/device/index.mjs +0 -493
- package/dist/device/index.mjs.map +0 -1
- package/dist/dom/index.d.mts +0 -714
- package/dist/dom/index.d.mts.map +0 -1
- package/dist/dom/index.mjs +0 -1840
- package/dist/dom/index.mjs.map +0 -1
- package/dist/editable-text-Bg7vil7h.d.mts +0 -307
- package/dist/editable-text-Bg7vil7h.d.mts.map +0 -1
- package/dist/events/index.d.mts +0 -168
- package/dist/events/index.d.mts.map +0 -1
- package/dist/events/index.mjs +0 -307
- package/dist/events/index.mjs.map +0 -1
- package/dist/follow-tab-stop-DM5EI4Ci.mjs +0 -856
- package/dist/follow-tab-stop-DM5EI4Ci.mjs.map +0 -1
- package/dist/index-Bomdwb7e.d.mts +0 -142
- package/dist/index-Bomdwb7e.d.mts.map +0 -1
- package/dist/index.d.mts +0 -12
- package/dist/index.mjs +0 -12
- package/dist/input-modality-XwQOFLip.mjs.map +0 -1
- package/dist/input-modality-l7InESYh.d.mts.map +0 -1
- package/dist/interaction/index.d.mts +0 -1193
- package/dist/interaction/index.d.mts.map +0 -1
- package/dist/interaction/index.mjs +0 -1992
- package/dist/interaction/index.mjs.map +0 -1
- package/dist/internal-C4gHodLc.mjs.map +0 -1
- package/dist/media/index.d.mts +0 -103
- package/dist/media/index.d.mts.map +0 -1
- package/dist/media/index.mjs +0 -146
- package/dist/media/index.mjs.map +0 -1
- package/dist/motion/index.d.mts +0 -2
- package/dist/motion/index.mjs +0 -1
- package/dist/motion-BmlJCjn6.mjs +0 -236
- package/dist/motion-BmlJCjn6.mjs.map +0 -1
- package/dist/net/index.d.mts +0 -338
- package/dist/net/index.d.mts.map +0 -1
- package/dist/net/index.mjs +0 -530
- package/dist/net/index.mjs.map +0 -1
- package/dist/observers/index.d.mts +0 -76
- package/dist/observers/index.d.mts.map +0 -1
- package/dist/observers/index.mjs +0 -155
- package/dist/observers/index.mjs.map +0 -1
- package/dist/rolldown-runtime-D8jQpDG7.mjs +0 -12
- package/dist/state/index.d.mts +0 -432
- package/dist/state/index.d.mts.map +0 -1
- package/dist/state/index.mjs.map +0 -1
- package/dist/time/index.d.mts +0 -167
- package/dist/time/index.d.mts.map +0 -1
- package/dist/time/index.mjs +0 -236
- package/dist/time/index.mjs.map +0 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Schema, Stream } from "effect";
|
|
2
|
+
import { defineMessageUnion } from "foldkit/message";
|
|
3
|
+
// src/events/pointer.ts
|
|
4
|
+
/**
|
|
5
|
+
* Pointer position as an entry — not a bundle, because the parent owns what
|
|
6
|
+
* it keeps (a cursor, a drag anchor, hover state): this reports moves, and
|
|
7
|
+
* the parent stores what matters. Element-scoped pointer needs are Mounts,
|
|
8
|
+
* not this window-level entry.
|
|
9
|
+
*/
|
|
10
|
+
const PointerMessage = defineMessageUnion({ Moved: {
|
|
11
|
+
x: Schema.Number,
|
|
12
|
+
y: Schema.Number
|
|
13
|
+
} });
|
|
14
|
+
/**
|
|
15
|
+
* Pointer moves on the window. Without a window the stream is empty instead
|
|
16
|
+
* of throwing. Lift with `Subscription.persistentEntry`, mapping into the
|
|
17
|
+
* parent's Message.
|
|
18
|
+
*/
|
|
19
|
+
const pointerEvents = () => {
|
|
20
|
+
if (typeof window === "undefined") return Stream.empty;
|
|
21
|
+
return Stream.fromEventListener(window, "pointermove").pipe(Stream.map((event) => PointerMessage.Moved({
|
|
22
|
+
x: event.clientX,
|
|
23
|
+
y: event.clientY
|
|
24
|
+
})));
|
|
25
|
+
};
|
|
26
|
+
export { PointerMessage, pointerEvents };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=pointer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer.js","names":[],"sources":["../../src/events/pointer.ts"],"sourcesContent":["/**\n * Pointer position as an entry — not a bundle, because the parent owns what\n * it keeps (a cursor, a drag anchor, hover state): this reports moves, and\n * the parent stores what matters. Element-scoped pointer needs are Mounts,\n * not this window-level entry.\n */\nimport { Schema, Stream } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const PointerMessage = defineMessageUnion({\n Moved: { x: Schema.Number, y: Schema.Number },\n})\nexport type PointerMessage = typeof PointerMessage.Type\n\n/**\n * Pointer moves on the window. Without a window the stream is empty instead\n * of throwing. Lift with `Subscription.persistentEntry`, mapping into the\n * parent's Message.\n */\nexport const pointerEvents = (): Stream.Stream<PointerMessage> => {\n if (typeof window === 'undefined') return Stream.empty\n return Stream.fromEventListener<PointerEvent>(window, 'pointermove').pipe(\n Stream.map(event => PointerMessage.Moved({ x: event.clientX, y: event.clientY })),\n )\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,iBAAiB,mBAAmB,EAC/C,OAAO;CAAE,GAAG,OAAO;CAAQ,GAAG,OAAO;AAAO,EAC9C,CAAC;;;;;;AAQD,MAAa,sBAAqD;CAChE,IAAI,OAAO,WAAW,aAAa,OAAO,OAAO;CACjD,OAAO,OAAO,kBAAgC,QAAQ,aAAa,CAAC,CAAC,KACnE,OAAO,KAAI,UAAS,eAAe,MAAM;EAAE,GAAG,MAAM;EAAS,GAAG,MAAM;CAAQ,CAAC,CAAC,CAClF;AACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Schema, Stream } from "effect";
|
|
2
|
+
export declare const ScrollMessage: import("foldkit/message").MessageUnion<{
|
|
3
|
+
readonly Scrolled: {
|
|
4
|
+
x: Schema.Number;
|
|
5
|
+
y: Schema.Number;
|
|
6
|
+
};
|
|
7
|
+
}>;
|
|
8
|
+
export type ScrollMessage = typeof ScrollMessage.Type;
|
|
9
|
+
/**
|
|
10
|
+
* Scrolls on the window, in the capture phase so container scrolls (which
|
|
11
|
+
* do not bubble) report too. Without a window the stream is empty instead
|
|
12
|
+
* of throwing. Lift with `Subscription.persistentEntry`, mapping into the
|
|
13
|
+
* parent's Message.
|
|
14
|
+
*/
|
|
15
|
+
export declare const scrollEvents: () => Stream.Stream<ScrollMessage>;
|
|
16
|
+
//# sourceMappingURL=scroll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.d.ts","names":[],"sources":["../../src/events/scroll.ts"],"mappings":";qBASa,yCAAa;;IACZ,GAAC,OAAA;IAAiB,GAAC,OAAA;;;YAErB,uBAAuB,cAAc;;;;;;;qBAQpC,oBAAmB,OAAO,OAAO"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Schema, Stream } from "effect";
|
|
2
|
+
import { defineMessageUnion } from "foldkit/message";
|
|
3
|
+
// src/events/scroll.ts
|
|
4
|
+
/**
|
|
5
|
+
* Window scroll position as an entry — not a bundle, because the parent
|
|
6
|
+
* owns what it keeps (a stuck header, a back-to-top gate, restore-on-back):
|
|
7
|
+
* this reports positions, and the parent stores what matters.
|
|
8
|
+
* Element-scoped scrolling needs a Mount, not this window-level entry.
|
|
9
|
+
*/
|
|
10
|
+
const ScrollMessage = defineMessageUnion({ Scrolled: {
|
|
11
|
+
x: Schema.Number,
|
|
12
|
+
y: Schema.Number
|
|
13
|
+
} });
|
|
14
|
+
/**
|
|
15
|
+
* Scrolls on the window, in the capture phase so container scrolls (which
|
|
16
|
+
* do not bubble) report too. Without a window the stream is empty instead
|
|
17
|
+
* of throwing. Lift with `Subscription.persistentEntry`, mapping into the
|
|
18
|
+
* parent's Message.
|
|
19
|
+
*/
|
|
20
|
+
const scrollEvents = () => {
|
|
21
|
+
if (typeof window === "undefined") return Stream.empty;
|
|
22
|
+
return Stream.fromEventListener(window, "scroll", { capture: true }).pipe(Stream.map(() => ScrollMessage.Scrolled({
|
|
23
|
+
x: window.scrollX,
|
|
24
|
+
y: window.scrollY
|
|
25
|
+
})));
|
|
26
|
+
};
|
|
27
|
+
export { ScrollMessage, scrollEvents };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=scroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.js","names":[],"sources":["../../src/events/scroll.ts"],"sourcesContent":["/**\n * Window scroll position as an entry — not a bundle, because the parent\n * owns what it keeps (a stuck header, a back-to-top gate, restore-on-back):\n * this reports positions, and the parent stores what matters.\n * Element-scoped scrolling needs a Mount, not this window-level entry.\n */\nimport { Schema, Stream } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ScrollMessage = defineMessageUnion({\n Scrolled: { x: Schema.Number, y: Schema.Number },\n})\nexport type ScrollMessage = typeof ScrollMessage.Type\n\n/**\n * Scrolls on the window, in the capture phase so container scrolls (which\n * do not bubble) report too. Without a window the stream is empty instead\n * of throwing. Lift with `Subscription.persistentEntry`, mapping into the\n * parent's Message.\n */\nexport const scrollEvents = (): Stream.Stream<ScrollMessage> => {\n if (typeof window === 'undefined') return Stream.empty\n return Stream.fromEventListener(window, 'scroll', { capture: true }).pipe(\n Stream.map(() => ScrollMessage.Scrolled({ x: window.scrollX, y: window.scrollY })),\n )\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,gBAAgB,mBAAmB,EAC9C,UAAU;CAAE,GAAG,OAAO;CAAQ,GAAG,OAAO;AAAO,EACjD,CAAC;;;;;;;AASD,MAAa,qBAAmD;CAC9D,IAAI,OAAO,WAAW,aAAa,OAAO,OAAO;CACjD,OAAO,OAAO,kBAAkB,QAAQ,UAAU,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,KACnE,OAAO,UAAU,cAAc,SAAS;EAAE,GAAG,OAAO;EAAS,GAAG,OAAO;CAAQ,CAAC,CAAC,CACnF;AACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { Bundle } from "foldkit-bundle";
|
|
3
|
+
export declare const VisibilityModel: Schema.Struct<{
|
|
4
|
+
readonly visible: Schema.Boolean;
|
|
5
|
+
}>;
|
|
6
|
+
export type VisibilityModel = typeof VisibilityModel.Type;
|
|
7
|
+
export declare const VisibilityMessage: import("foldkit/message").MessageUnion<{
|
|
8
|
+
readonly Changed: {
|
|
9
|
+
visible: Schema.Boolean;
|
|
10
|
+
};
|
|
11
|
+
}>;
|
|
12
|
+
export type VisibilityMessage = typeof VisibilityMessage.Type;
|
|
13
|
+
/**
|
|
14
|
+
* Page visibility as a bundle: `visible` in the Model, read from the
|
|
15
|
+
* document at startup and kept current by `visibilitychange`. A hidden page
|
|
16
|
+
* is the application's cue to pause polling, animations, and realtime
|
|
17
|
+
* streams; the decision stays in application `update`, not here.
|
|
18
|
+
*/
|
|
19
|
+
export declare const Visibility: Bundle.Bundle<"Visibility", void, {
|
|
20
|
+
readonly visible: boolean;
|
|
21
|
+
}, {
|
|
22
|
+
readonly _tag: "Changed";
|
|
23
|
+
readonly visible: boolean;
|
|
24
|
+
}, never, never, never, void, {}, {}>;
|
|
25
|
+
//# sourceMappingURL=visibility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visibility.d.ts","names":[],"sources":["../../src/events/visibility.ts"],"mappings":";;qBAKa,iBAAe,OAAA;;;YAChB,yBAAyB,gBAAgB;qBAExC,6CAAiB;;IAAmC,SAAO,OAAA;;;YAC5D,2BAA2B,kBAAkB;;;;;;;qBAuB5C,YAAU,OAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Schema, Stream } from "effect";
|
|
2
|
+
import { defineMessageUnion } from "foldkit/message";
|
|
3
|
+
import * as Subscription from "foldkit/subscription";
|
|
4
|
+
import { Bundle } from "foldkit-bundle";
|
|
5
|
+
// src/events/visibility.ts
|
|
6
|
+
const VisibilityModel = Schema.Struct({ visible: Schema.Boolean });
|
|
7
|
+
const VisibilityMessage = defineMessageUnion({ Changed: { visible: Schema.Boolean } });
|
|
8
|
+
const isVisible = () => typeof document === "undefined" || document.visibilityState !== "hidden";
|
|
9
|
+
const visibilityStream = () => {
|
|
10
|
+
if (typeof document === "undefined" || typeof document.addEventListener !== "function") return Stream.empty;
|
|
11
|
+
return Stream.concat(Stream.make(VisibilityMessage.Changed({ visible: isVisible() })), Stream.fromEventListener(document, "visibilitychange").pipe(Stream.map(() => VisibilityMessage.Changed({ visible: isVisible() }))));
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Page visibility as a bundle: `visible` in the Model, read from the
|
|
15
|
+
* document at startup and kept current by `visibilitychange`. A hidden page
|
|
16
|
+
* is the application's cue to pause polling, animations, and realtime
|
|
17
|
+
* streams; the decision stays in application `update`, not here.
|
|
18
|
+
*/
|
|
19
|
+
const Visibility = Bundle.make("Visibility", {
|
|
20
|
+
Model: VisibilityModel,
|
|
21
|
+
Message: VisibilityMessage,
|
|
22
|
+
init: () => ({ model: { visible: isVisible() } }),
|
|
23
|
+
update: (model, message) => message.visible === model.visible ? { model } : { model: { visible: message.visible } },
|
|
24
|
+
subscriptions: () => Subscription.make()(() => ({ changes: Subscription.persistentEntry(visibilityStream()) }))
|
|
25
|
+
});
|
|
26
|
+
export { Visibility, VisibilityMessage, VisibilityModel };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=visibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visibility.js","names":[],"sources":["../../src/events/visibility.ts"],"sourcesContent":["import { Schema, Stream } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\nimport * as Subscription from 'foldkit/subscription'\nimport { Bundle } from 'foldkit-bundle'\n\nexport const VisibilityModel = Schema.Struct({ visible: Schema.Boolean })\nexport type VisibilityModel = typeof VisibilityModel.Type\n\nexport const VisibilityMessage = defineMessageUnion({ Changed: { visible: Schema.Boolean } })\nexport type VisibilityMessage = typeof VisibilityMessage.Type\n\nconst isVisible = (): boolean =>\n typeof document === 'undefined' || document.visibilityState !== 'hidden'\n\nconst visibilityStream = (): Stream.Stream<VisibilityMessage> => {\n if (typeof document === 'undefined' || typeof document.addEventListener !== 'function') {\n return Stream.empty\n }\n return Stream.concat(\n Stream.make(VisibilityMessage.Changed({ visible: isVisible() })),\n Stream.fromEventListener(document, 'visibilitychange').pipe(\n Stream.map(() => VisibilityMessage.Changed({ visible: isVisible() })),\n ),\n )\n}\n\n/**\n * Page visibility as a bundle: `visible` in the Model, read from the\n * document at startup and kept current by `visibilitychange`. A hidden page\n * is the application's cue to pause polling, animations, and realtime\n * streams; the decision stays in application `update`, not here.\n */\nexport const Visibility = Bundle.make('Visibility', {\n Model: VisibilityModel,\n Message: VisibilityMessage,\n // No document (SSR): assume visible; the stream corrects on subscribe.\n init: () => ({ model: { visible: isVisible() } }),\n // The stream opens with the state `init` already read.\n update: (model, message) =>\n message.visible === model.visible ? { model } : { model: { visible: message.visible } },\n subscriptions: (): Subscription.Subscriptions<VisibilityModel, VisibilityMessage> =>\n Subscription.make<VisibilityModel, VisibilityMessage>()(() => ({\n changes: Subscription.persistentEntry(visibilityStream()),\n })),\n})\n"],"mappings":";;;;;AAKA,MAAa,kBAAkB,OAAO,OAAO,EAAE,SAAS,OAAO,QAAQ,CAAC;AAGxE,MAAa,oBAAoB,mBAAmB,EAAE,SAAS,EAAE,SAAS,OAAO,QAAQ,EAAE,CAAC;AAG5F,MAAM,kBACJ,OAAO,aAAa,eAAe,SAAS,oBAAoB;AAElE,MAAM,yBAA2D;CAC/D,IAAI,OAAO,aAAa,eAAe,OAAO,SAAS,qBAAqB,YAC1E,OAAO,OAAO;CAEhB,OAAO,OAAO,OACZ,OAAO,KAAK,kBAAkB,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC,CAAC,GAC/D,OAAO,kBAAkB,UAAU,kBAAkB,CAAC,CAAC,KACrD,OAAO,UAAU,kBAAkB,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC,CAAC,CACtE,CACF;AACF;;;;;;;AAQA,MAAa,aAAa,OAAO,KAAK,cAAc;CAClD,OAAO;CACP,SAAS;CAET,aAAa,EAAE,OAAO,EAAE,SAAS,UAAU,EAAE,EAAE;CAE/C,SAAS,OAAO,YACd,QAAQ,YAAY,MAAM,UAAU,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,SAAS,QAAQ,QAAQ,EAAE;CACxF,qBACE,aAAa,KAAyC,CAAC,QAAQ,EAC7D,SAAS,aAAa,gBAAgB,iBAAiB,CAAC,EAC1D,EAAE;AACN,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { Bundle } from "foldkit-bundle";
|
|
3
|
+
export declare const WindowSizeModel: Schema.Struct<{
|
|
4
|
+
readonly width: Schema.Number;
|
|
5
|
+
readonly height: Schema.Number;
|
|
6
|
+
}>;
|
|
7
|
+
export type WindowSizeModel = typeof WindowSizeModel.Type;
|
|
8
|
+
export declare const WindowSizeMessage: import("foldkit/message").MessageUnion<{
|
|
9
|
+
readonly Changed: {
|
|
10
|
+
width: Schema.Number;
|
|
11
|
+
height: Schema.Number;
|
|
12
|
+
};
|
|
13
|
+
}>;
|
|
14
|
+
export type WindowSizeMessage = typeof WindowSizeMessage.Type;
|
|
15
|
+
/**
|
|
16
|
+
* Window size as a bundle: `{ width, height }` in the Model, read from the
|
|
17
|
+
* window at startup and kept current by one `resize` listener. Breakpoints
|
|
18
|
+
* owns its own listener and derives names; place this one when views need
|
|
19
|
+
* the raw pixels. Placing both doubles resize listeners — pick the one the
|
|
20
|
+
* view reads.
|
|
21
|
+
*/
|
|
22
|
+
export declare const WindowSize: Bundle.Bundle<"WindowSize", void, {
|
|
23
|
+
readonly width: number;
|
|
24
|
+
readonly height: number;
|
|
25
|
+
}, {
|
|
26
|
+
readonly _tag: "Changed";
|
|
27
|
+
readonly width: number;
|
|
28
|
+
readonly height: number;
|
|
29
|
+
}, never, never, never, void, {}, {}>;
|
|
30
|
+
//# sourceMappingURL=window-size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-size.d.ts","names":[],"sources":["../../src/events/window-size.ts"],"mappings":";;qBAMa,iBAAe,OAAA;;;;YAChB,yBAAyB,gBAAgB;qBAExC,6CAAiB;;IACjB,OAAK,OAAA;IAAiB,QAAM,OAAA;;;YAE7B,2BAA2B,kBAAkB;;;;;;;;qBA0C5C,YAAU,OAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Effect, Queue, Schema, Stream } from "effect";
|
|
2
|
+
import { defineMessageUnion } from "foldkit/message";
|
|
3
|
+
import * as Subscription from "foldkit/subscription";
|
|
4
|
+
import { Bundle } from "foldkit-bundle";
|
|
5
|
+
import { unlessSame } from "../internal.js";
|
|
6
|
+
// src/events/window-size.ts
|
|
7
|
+
const WindowSizeModel = Schema.Struct({
|
|
8
|
+
width: Schema.Number,
|
|
9
|
+
height: Schema.Number
|
|
10
|
+
});
|
|
11
|
+
const WindowSizeMessage = defineMessageUnion({ Changed: {
|
|
12
|
+
width: Schema.Number,
|
|
13
|
+
height: Schema.Number
|
|
14
|
+
} });
|
|
15
|
+
const readSize = () => ({
|
|
16
|
+
width: window.innerWidth,
|
|
17
|
+
height: window.innerHeight
|
|
18
|
+
});
|
|
19
|
+
const sizeStream = () => {
|
|
20
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") return Stream.empty;
|
|
21
|
+
return Stream.unwrap(Effect.gen(function* () {
|
|
22
|
+
const queue = yield* Queue.unbounded();
|
|
23
|
+
const onResize = () => {
|
|
24
|
+
const size = readSize();
|
|
25
|
+
Effect.runFork(Queue.offer(queue, WindowSizeMessage.Changed({
|
|
26
|
+
width: size.width,
|
|
27
|
+
height: size.height
|
|
28
|
+
})));
|
|
29
|
+
};
|
|
30
|
+
window.addEventListener("resize", onResize);
|
|
31
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => {
|
|
32
|
+
window.removeEventListener("resize", onResize);
|
|
33
|
+
}));
|
|
34
|
+
const size = readSize();
|
|
35
|
+
return Stream.concat(Stream.make(WindowSizeMessage.Changed({
|
|
36
|
+
width: size.width,
|
|
37
|
+
height: size.height
|
|
38
|
+
})), Stream.fromQueue(queue));
|
|
39
|
+
}));
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Window size as a bundle: `{ width, height }` in the Model, read from the
|
|
43
|
+
* window at startup and kept current by one `resize` listener. Breakpoints
|
|
44
|
+
* owns its own listener and derives names; place this one when views need
|
|
45
|
+
* the raw pixels. Placing both doubles resize listeners — pick the one the
|
|
46
|
+
* view reads.
|
|
47
|
+
*/
|
|
48
|
+
const WindowSize = Bundle.make("WindowSize", {
|
|
49
|
+
Model: WindowSizeModel,
|
|
50
|
+
Message: WindowSizeMessage,
|
|
51
|
+
init: () => ({ model: {
|
|
52
|
+
width: 0,
|
|
53
|
+
height: 0
|
|
54
|
+
} }),
|
|
55
|
+
update: (model, message) => ({ model: unlessSame(model, {
|
|
56
|
+
width: message.width,
|
|
57
|
+
height: message.height
|
|
58
|
+
}) }),
|
|
59
|
+
subscriptions: () => Subscription.make()(() => ({ changes: Subscription.persistentEntry(sizeStream()) }))
|
|
60
|
+
});
|
|
61
|
+
export { WindowSize, WindowSizeMessage, WindowSizeModel };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=window-size.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-size.js","names":[],"sources":["../../src/events/window-size.ts"],"sourcesContent":["import { Effect, Queue, Schema, Stream } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\nimport * as Subscription from 'foldkit/subscription'\nimport { Bundle } from 'foldkit-bundle'\nimport { unlessSame } from '../internal.js'\n\nexport const WindowSizeModel = Schema.Struct({ width: Schema.Number, height: Schema.Number })\nexport type WindowSizeModel = typeof WindowSizeModel.Type\n\nexport const WindowSizeMessage = defineMessageUnion({\n Changed: { width: Schema.Number, height: Schema.Number },\n})\nexport type WindowSizeMessage = typeof WindowSizeMessage.Type\n\nconst readSize = (): { readonly width: number; readonly height: number } => ({\n width: window.innerWidth,\n height: window.innerHeight,\n})\n\nconst sizeStream = (): Stream.Stream<WindowSizeMessage> => {\n if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') {\n return Stream.empty\n }\n return Stream.unwrap(\n Effect.gen(function* () {\n const queue = yield* Queue.unbounded<WindowSizeMessage>()\n const onResize = () => {\n const size = readSize()\n Effect.runFork(\n Queue.offer(queue, WindowSizeMessage.Changed({ width: size.width, height: size.height })),\n )\n }\n window.addEventListener('resize', onResize)\n yield* Effect.addFinalizer(() =>\n Effect.sync(() => {\n window.removeEventListener('resize', onResize)\n }),\n )\n const size = readSize()\n return Stream.concat(\n Stream.make(WindowSizeMessage.Changed({ width: size.width, height: size.height })),\n Stream.fromQueue(queue),\n )\n }),\n )\n}\n\n/**\n * Window size as a bundle: `{ width, height }` in the Model, read from the\n * window at startup and kept current by one `resize` listener. Breakpoints\n * owns its own listener and derives names; place this one when views need\n * the raw pixels. Placing both doubles resize listeners — pick the one the\n * view reads.\n */\nexport const WindowSize = Bundle.make('WindowSize', {\n Model: WindowSizeModel,\n Message: WindowSizeMessage,\n init: () => ({ model: { width: 0, height: 0 } }),\n update: (model, message) => ({\n model: unlessSame(model, { width: message.width, height: message.height }),\n }),\n subscriptions: (): Subscription.Subscriptions<WindowSizeModel, WindowSizeMessage> =>\n Subscription.make<WindowSizeModel, WindowSizeMessage>()(() => ({\n changes: Subscription.persistentEntry(sizeStream()),\n })),\n})\n"],"mappings":";;;;;;AAMA,MAAa,kBAAkB,OAAO,OAAO;CAAE,OAAO,OAAO;CAAQ,QAAQ,OAAO;AAAO,CAAC;AAG5F,MAAa,oBAAoB,mBAAmB,EAClD,SAAS;CAAE,OAAO,OAAO;CAAQ,QAAQ,OAAO;AAAO,EACzD,CAAC;AAGD,MAAM,kBAAuE;CAC3E,OAAO,OAAO;CACd,QAAQ,OAAO;AACjB;AAEA,MAAM,mBAAqD;CACzD,IAAI,OAAO,WAAW,eAAe,OAAO,OAAO,qBAAqB,YACtE,OAAO,OAAO;CAEhB,OAAO,OAAO,OACZ,OAAO,IAAI,aAAa;EACtB,MAAM,QAAQ,OAAO,MAAM,UAA6B;EACxD,MAAM,iBAAiB;GACrB,MAAM,OAAO,SAAS;GACtB,OAAO,QACL,MAAM,MAAM,OAAO,kBAAkB,QAAQ;IAAE,OAAO,KAAK;IAAO,QAAQ,KAAK;GAAO,CAAC,CAAC,CAC1F;EACF;EACA,OAAO,iBAAiB,UAAU,QAAQ;EAC1C,OAAO,OAAO,mBACZ,OAAO,WAAW;GAChB,OAAO,oBAAoB,UAAU,QAAQ;EAC/C,CAAC,CACH;EACA,MAAM,OAAO,SAAS;EACtB,OAAO,OAAO,OACZ,OAAO,KAAK,kBAAkB,QAAQ;GAAE,OAAO,KAAK;GAAO,QAAQ,KAAK;EAAO,CAAC,CAAC,GACjF,OAAO,UAAU,KAAK,CACxB;CACF,CAAC,CACH;AACF;;;;;;;;AASA,MAAa,aAAa,OAAO,KAAK,cAAc;CAClD,OAAO;CACP,SAAS;CACT,aAAa,EAAE,OAAO;EAAE,OAAO;EAAG,QAAQ;CAAE,EAAE;CAC9C,SAAS,OAAO,aAAa,EAC3B,OAAO,WAAW,OAAO;EAAE,OAAO,QAAQ;EAAO,QAAQ,QAAQ;CAAO,CAAC,EAC3E;CACA,qBACE,aAAa,KAAyC,CAAC,QAAQ,EAC7D,SAAS,aAAa,gBAAgB,WAAW,CAAC,EACpD,EAAE;AACN,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./dom/index.js";
|
|
2
|
+
export * from "./device/index.js";
|
|
3
|
+
export * from "./events/index.js";
|
|
4
|
+
export * from "./media/index.js";
|
|
5
|
+
export * from "./motion/index.js";
|
|
6
|
+
export * from "./net/index.js";
|
|
7
|
+
export * from "./observers/index.js";
|
|
8
|
+
export * from "./state/index.js";
|
|
9
|
+
export * from "./time/index.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./dom/index.js";
|
|
2
|
+
export * from "./device/index.js";
|
|
3
|
+
export * from "./events/index.js";
|
|
4
|
+
export * from "./media/index.js";
|
|
5
|
+
export * from "./motion/index.js";
|
|
6
|
+
export * from "./net/index.js";
|
|
7
|
+
export * from "./observers/index.js";
|
|
8
|
+
export * from "./state/index.js";
|
|
9
|
+
export * from "./time/index.js";
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Bundle, Declared } from "foldkit-bundle";
|
|
2
|
+
import { MountAction } from "foldkit/mount";
|
|
3
|
+
import { NamedBehavior, SlotAttributes, SlotItem, SlotRequirements } from "foldkit-mixins";
|
|
4
|
+
import { HtmlBuilder } from "foldkit/html";
|
|
5
|
+
type BundleOf<D extends Declared<any, any>> = D extends Declared<infer B, any> ? B : never;
|
|
6
|
+
/** The Bundle's Model, which the parent's `Input` must hold at `declared.field`. */
|
|
7
|
+
export type BundleModelOf<D extends Declared<any, any>> = Bundle.BundleParts<BundleOf<D>>['Model'];
|
|
8
|
+
/** The Bundle's Message, which `send` wraps for the parent. */
|
|
9
|
+
export type BundleMessageOf<D extends Declared<any, any>> = Bundle.BundleParts<BundleOf<D>>['Message'];
|
|
10
|
+
export interface BundleSlotOptions<D extends Declared<any, any>, Input, ParentMessage> {
|
|
11
|
+
readonly requires?: SlotRequirements;
|
|
12
|
+
readonly attributes?: (context: {
|
|
13
|
+
readonly input: Input;
|
|
14
|
+
readonly h: HtmlBuilder<ParentMessage>;
|
|
15
|
+
readonly item?: SlotItem;
|
|
16
|
+
/** The Bundle's Message as the parent's: what a handler the Behavior writes takes. */
|
|
17
|
+
readonly send: (message: BundleMessageOf<D>) => ParentMessage;
|
|
18
|
+
}) => SlotAttributes<ParentMessage>;
|
|
19
|
+
/** The Bundle's events, mounted on this slot and wrapped for the parent. */
|
|
20
|
+
readonly events?: MountAction<BundleMessageOf<D>, any>;
|
|
21
|
+
}
|
|
22
|
+
export type BundleBehaviorSpec<D extends Declared<any, any>, Input, ParentMessage> = Readonly<Record<string, BundleSlotOptions<D, Input, ParentMessage>>>;
|
|
23
|
+
/**
|
|
24
|
+
* `fromBundle(declared)(slots)<Input, ParentMessage>(spec)` — a Behavior over
|
|
25
|
+
* `declared`, with every `events` mount and every `send` mapped through the
|
|
26
|
+
* placement's wrapper. `Input` must hold the Bundle's Model at the declared
|
|
27
|
+
* field, so attributes read the placed slice; the parent's `Message` includes
|
|
28
|
+
* the declared wrapper cases, so nothing can be sent outside it.
|
|
29
|
+
*/
|
|
30
|
+
export declare const fromBundle: <D extends Declared<any, any>>(declared: D) => <Slots>(slots: Slots) => <Input extends { readonly [K in D['field']]: BundleModelOf<D>; }, ParentMessage>(spec: BundleBehaviorSpec<D, Input, ParentMessage>, options?: {
|
|
31
|
+
readonly name?: string;
|
|
32
|
+
}) => NamedBehavior<Slots, Input, ParentMessage>;
|
|
33
|
+
export declare const BundleBehavior: {
|
|
34
|
+
readonly fromBundle: typeof fromBundle;
|
|
35
|
+
};
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=bundle-behavior.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-behavior.d.ts","names":[],"sources":["../../src/interaction/bundle-behavior.ts"],"mappings":";;;;KA+BK,SAAS,UAAU,sBAAsB,UAAU,eAAe,UAAU;;YAGrE,cAAc,UAAU,sBAAsB,OAAO,YAAY,SAAS;;YAG1E,gBAAgB,UAAU,sBAAsB,OAAO,YACjE,SAAS;iBAGM,kBAAkB,UAAU,oBAAoB,OAAO;WAC7D,WAAW;WACX,cAAc;aACZ,OAAO;aACP,GAAG,YAAY;aACf,OAAO;;aAEP,OAAO,SAAS,gBAAgB,OAAO;QAC5C,eAAe;;WAEZ,SAAS,YAAY,gBAAgB;;YAGpC,mBAAmB,UAAU,oBAAoB,OAAO,iBAAiB,SACnF,eAAe,kBAAkB,GAAG,OAAO;;;;;;;;qBAUhC,aACV,UAAU,oBAAkB,UAAY,OACxC,OAAK,OAAS,WACd,0BAA0B,KAAK,aAAa,cAAc,OAAM,eAAa,MACtE,mBAAmB,GAAG,OAAO,gBAAc;WAC5B;MACpB,cAAc,OAAO,OAAO;qBAiCpB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as Mount from "foldkit/mount";
|
|
2
|
+
import { Behavior } from "foldkit-mixins";
|
|
3
|
+
// src/interaction/bundle-behavior.ts
|
|
4
|
+
/**
|
|
5
|
+
* `fromBundle(declared)(slots)<Input, ParentMessage>(spec)` — a Behavior over
|
|
6
|
+
* `declared`, with every `events` mount and every `send` mapped through the
|
|
7
|
+
* placement's wrapper. `Input` must hold the Bundle's Model at the declared
|
|
8
|
+
* field, so attributes read the placed slice; the parent's `Message` includes
|
|
9
|
+
* the declared wrapper cases, so nothing can be sent outside it.
|
|
10
|
+
*/
|
|
11
|
+
const fromBundle = (declared) => (slots) => (spec, options) => {
|
|
12
|
+
const send = (message) => declared.wrapper.make(message);
|
|
13
|
+
const built = Object.create(null);
|
|
14
|
+
for (const [name, slot] of Object.entries(spec)) {
|
|
15
|
+
if (slot === void 0) continue;
|
|
16
|
+
const { requires, attributes, events } = slot;
|
|
17
|
+
if (requires === void 0 && attributes === void 0 && events === void 0) continue;
|
|
18
|
+
built[name] = {
|
|
19
|
+
...requires === void 0 ? {} : { requires },
|
|
20
|
+
...attributes === void 0 ? {} : { attributes: (context) => attributes({
|
|
21
|
+
input: context.input,
|
|
22
|
+
h: context.h,
|
|
23
|
+
...context.item === void 0 ? {} : { item: context.item },
|
|
24
|
+
send
|
|
25
|
+
}) },
|
|
26
|
+
...events === void 0 ? {} : { mount: () => Mount.mapMessage(events, send) }
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return Behavior.forSlots(slots)(built, options);
|
|
30
|
+
};
|
|
31
|
+
const BundleBehavior = { fromBundle };
|
|
32
|
+
export { BundleBehavior, fromBundle };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=bundle-behavior.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-behavior.js","names":[],"sources":["../../src/interaction/bundle-behavior.ts"],"sourcesContent":["/**\n * The mixin half of a Bundle: a Behavior whose slots are wired to the\n * Bundle's Messages through its `Declared` placement.\n *\n * The Bundle owns the Model, its Message union and the transition; a parent\n * declares and places it (`Bundle.declare(...).at(...)`); this Behavior writes\n * the element's attributes from the placed slice and mounts the Bundle's\n * events, wrapping each Message with the placement's `wrapper` into the\n * parent's universe. A Behavior still owns no state, and a Message still has\n * one update: this is a bridge, not a second runtime.\n *\n * `attributes` receives `send`, the same wrap, for a handler it writes itself\n * (`h.OnClick(send(Message.Activated({ id })))`). `events` receives the\n * Bundle's own Mount (a `Mount.defineStream`), and the helper supplies the\n * mapping, so a caller never repeats `Mount.mapMessage(events, wrapper.make)`.\n */\nimport type { HtmlBuilder } from 'foldkit/html'\nimport type { MountAction } from 'foldkit/mount'\nimport * as Mount from 'foldkit/mount'\nimport type { Bundle, Declared } from 'foldkit-bundle'\nimport {\n Behavior,\n type BehaviorSlotOptions,\n type NamedBehavior,\n type SlotAttributes,\n type SlotItem,\n type SlotRequirements,\n} from 'foldkit-mixins'\n\n// `any` for the bundle and the field so a behavior's own generic `Field`\n// (`Declared<typeof bundle, Field>`) is accepted; the parts stay inferred.\ntype BundleOf<D extends Declared<any, any>> = D extends Declared<infer B, any> ? B : never\n\n/** The Bundle's Model, which the parent's `Input` must hold at `declared.field`. */\nexport type BundleModelOf<D extends Declared<any, any>> = Bundle.BundleParts<BundleOf<D>>['Model']\n\n/** The Bundle's Message, which `send` wraps for the parent. */\nexport type BundleMessageOf<D extends Declared<any, any>> = Bundle.BundleParts<\n BundleOf<D>\n>['Message']\n\nexport interface BundleSlotOptions<D extends Declared<any, any>, Input, ParentMessage> {\n readonly requires?: SlotRequirements\n readonly attributes?: (context: {\n readonly input: Input\n readonly h: HtmlBuilder<ParentMessage>\n readonly item?: SlotItem\n /** The Bundle's Message as the parent's: what a handler the Behavior writes takes. */\n readonly send: (message: BundleMessageOf<D>) => ParentMessage\n }) => SlotAttributes<ParentMessage>\n /** The Bundle's events, mounted on this slot and wrapped for the parent. */\n readonly events?: MountAction<BundleMessageOf<D>, any>\n}\n\nexport type BundleBehaviorSpec<D extends Declared<any, any>, Input, ParentMessage> = Readonly<\n Record<string, BundleSlotOptions<D, Input, ParentMessage>>\n>\n\n/**\n * `fromBundle(declared)(slots)<Input, ParentMessage>(spec)` — a Behavior over\n * `declared`, with every `events` mount and every `send` mapped through the\n * placement's wrapper. `Input` must hold the Bundle's Model at the declared\n * field, so attributes read the placed slice; the parent's `Message` includes\n * the declared wrapper cases, so nothing can be sent outside it.\n */\nexport const fromBundle =\n <D extends Declared<any, any>>(declared: D) =>\n <Slots>(slots: Slots) =>\n <Input extends { readonly [K in D['field']]: BundleModelOf<D> }, ParentMessage>(\n spec: BundleBehaviorSpec<D, Input, ParentMessage>,\n options?: { readonly name?: string },\n ): NamedBehavior<Slots, Input, ParentMessage> => {\n const send = (message: BundleMessageOf<D>): ParentMessage =>\n declared.wrapper.make(message) as unknown as ParentMessage\n const built: Record<string, BehaviorSlotOptions<Input, ParentMessage>> = Object.create(null)\n for (const [name, slot] of Object.entries(\n spec as Record<string, BundleSlotOptions<D, Input, ParentMessage> | undefined>,\n )) {\n if (slot === undefined) continue\n const { requires, attributes, events } = slot\n if (requires === undefined && attributes === undefined && events === undefined) continue\n built[name] = {\n ...(requires === undefined ? {} : { requires }),\n ...(attributes === undefined\n ? {}\n : {\n attributes: context =>\n attributes({\n input: context.input as Input,\n h: context.h,\n ...(context.item === undefined ? {} : { item: context.item }),\n send,\n }),\n }),\n ...(events === undefined ? {} : { mount: () => Mount.mapMessage(events, send) }),\n }\n }\n return Behavior.forSlots(slots)<Input, ParentMessage>(\n // Built slot by slot from the same contract `forSlots` validates.\n built as unknown as Behavior.BehaviorSpec<Slots, Input, ParentMessage>,\n options,\n )\n }\n\nexport const BundleBehavior = { fromBundle } as const\n"],"mappings":";;;;;;;;;;AAiEA,MAAa,cACoB,cACvB,WAEN,MACA,YAC+C;CAC/C,MAAM,QAAQ,YACZ,SAAS,QAAQ,KAAK,OAAO;CAC/B,MAAM,QAAmE,OAAO,OAAO,IAAI;CAC3F,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAChC,IACF,GAAG;EACD,IAAI,SAAS,KAAA,GAAW;EACxB,MAAM,EAAE,UAAU,YAAY,WAAW;EACzC,IAAI,aAAa,KAAA,KAAa,eAAe,KAAA,KAAa,WAAW,KAAA,GAAW;EAChF,MAAM,QAAQ;GACZ,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS;GAC7C,GAAI,eAAe,KAAA,IACf,CAAC,IACD,EACE,aAAY,YACV,WAAW;IACT,OAAO,QAAQ;IACf,GAAG,QAAQ;IACX,GAAI,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,QAAQ,KAAK;IAC3D;GACF,CAAC,EACL;GACJ,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,MAAM,WAAW,QAAQ,IAAI,EAAE;EAChF;CACF;CACA,OAAO,SAAS,SAAS,KAAK,CAAC,CAE7B,OACA,OACF;AACF;AAEF,MAAa,iBAAiB,EAAE,WAAW"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { Bundle, Declared } from "foldkit-bundle";
|
|
3
|
+
import { Behavior } from "foldkit-mixins";
|
|
4
|
+
export declare const LAYER_ATTRIBUTE = "data-foldkit-plus-layer";
|
|
5
|
+
export declare const TRIGGER_ATTRIBUTE = "data-foldkit-plus-layer-trigger";
|
|
6
|
+
/** An open layer as the document showed it: bottom to top is DOM order. */
|
|
7
|
+
export declare const Layer: Schema.Struct<{
|
|
8
|
+
readonly id: Schema.String;
|
|
9
|
+
/** Dismiss on a press outside it. */
|
|
10
|
+
readonly outside: Schema.Boolean;
|
|
11
|
+
/** Dismiss on Escape when topmost. */
|
|
12
|
+
readonly escape: Schema.Boolean;
|
|
13
|
+
}>;
|
|
14
|
+
export type Layer = typeof Layer.Type;
|
|
15
|
+
export declare const Model: Schema.Struct<{
|
|
16
|
+
/** The open layers at the last event, bottom to top. */
|
|
17
|
+
readonly layers: Schema.$Array<Schema.Struct<{
|
|
18
|
+
readonly id: Schema.String;
|
|
19
|
+
/** Dismiss on a press outside it. */
|
|
20
|
+
readonly outside: Schema.Boolean;
|
|
21
|
+
/** Dismiss on Escape when topmost. */
|
|
22
|
+
readonly escape: Schema.Boolean;
|
|
23
|
+
}>>;
|
|
24
|
+
}>;
|
|
25
|
+
export type Model = typeof Model.Type;
|
|
26
|
+
export declare const Message: import("foldkit/message").MessageUnion<{
|
|
27
|
+
/** A pointer went down; `inside` are the layers whose element or trigger was on the event's path. */
|
|
28
|
+
readonly PressedAt: {
|
|
29
|
+
layers: Schema.$Array<Schema.Struct<{
|
|
30
|
+
readonly id: Schema.String;
|
|
31
|
+
/** Dismiss on a press outside it. */
|
|
32
|
+
readonly outside: Schema.Boolean;
|
|
33
|
+
/** Dismiss on Escape when topmost. */
|
|
34
|
+
readonly escape: Schema.Boolean;
|
|
35
|
+
}>>;
|
|
36
|
+
inside: Schema.$Array<Schema.String>;
|
|
37
|
+
};
|
|
38
|
+
readonly PressedEscape: {
|
|
39
|
+
layers: Schema.$Array<Schema.Struct<{
|
|
40
|
+
readonly id: Schema.String;
|
|
41
|
+
/** Dismiss on a press outside it. */
|
|
42
|
+
readonly outside: Schema.Boolean;
|
|
43
|
+
/** Dismiss on Escape when topmost. */
|
|
44
|
+
readonly escape: Schema.Boolean;
|
|
45
|
+
}>>;
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
48
|
+
export type Message = typeof Message.Type;
|
|
49
|
+
export declare const Dismiss: Schema.TaggedStruct<"Dismiss", {
|
|
50
|
+
readonly ids: Schema.$Array<Schema.String>;
|
|
51
|
+
}>;
|
|
52
|
+
export type Dismiss = typeof Dismiss.Type;
|
|
53
|
+
/** Which layers a press inside `inside` dismisses: every layer above the topmost one hit, or all when none was. */
|
|
54
|
+
export declare const toDismiss: (layers: ReadonlyArray<Layer>, inside: ReadonlyArray<string>) => ReadonlyArray<string>;
|
|
55
|
+
export declare const bundle: Bundle.Bundle<"DismissLayer", void, {
|
|
56
|
+
readonly layers: readonly {
|
|
57
|
+
readonly id: string;
|
|
58
|
+
readonly outside: boolean;
|
|
59
|
+
readonly escape: boolean;
|
|
60
|
+
}[];
|
|
61
|
+
}, {
|
|
62
|
+
readonly _tag: "PressedAt";
|
|
63
|
+
readonly layers: readonly {
|
|
64
|
+
readonly id: string;
|
|
65
|
+
readonly outside: boolean;
|
|
66
|
+
readonly escape: boolean;
|
|
67
|
+
}[];
|
|
68
|
+
readonly inside: readonly string[];
|
|
69
|
+
} | {
|
|
70
|
+
readonly _tag: "PressedEscape";
|
|
71
|
+
readonly layers: readonly {
|
|
72
|
+
readonly id: string;
|
|
73
|
+
readonly outside: boolean;
|
|
74
|
+
readonly escape: boolean;
|
|
75
|
+
}[];
|
|
76
|
+
}, {
|
|
77
|
+
readonly _tag: "Dismiss";
|
|
78
|
+
readonly ids: readonly string[];
|
|
79
|
+
}, never, never, void, {}, {}>;
|
|
80
|
+
/** The layer ids whose element or trigger is on the event's composed path. */
|
|
81
|
+
export declare const layersOnPath: (path: ReadonlyArray<EventTarget>) => ReadonlyArray<string>;
|
|
82
|
+
export interface BehaviorOptions<Input, Slots> {
|
|
83
|
+
/** The layer's root, rendered only while the layer is open. */
|
|
84
|
+
readonly layer: keyof Slots & string;
|
|
85
|
+
/** The element that opens the layer, so a press on it is inside. */
|
|
86
|
+
readonly trigger?: keyof Slots & string;
|
|
87
|
+
readonly id: (input: Input) => string;
|
|
88
|
+
/** Dismiss on a press outside. Default `true`. */
|
|
89
|
+
readonly outsidePress?: boolean;
|
|
90
|
+
/** Dismiss on Escape when topmost. Default `true`. */
|
|
91
|
+
readonly escape?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Marks the layer's container and trigger for the placed stack. The layer
|
|
95
|
+
* takes part only while its element is rendered, so an `open` flag in the
|
|
96
|
+
* parent Model is the whole lifecycle. Not for an element with `popover`,
|
|
97
|
+
* which the browser dismisses itself.
|
|
98
|
+
*/
|
|
99
|
+
export declare const behavior: <Field extends string>(_declared: Declared<typeof bundle, Field>) => <Slots>(slots: Slots) => <Input, ParentMessage>(options: BehaviorOptions<Input, Slots>) => Behavior.NamedBehavior<Slots, Input, ParentMessage>;
|
|
100
|
+
//# sourceMappingURL=dismiss-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dismiss-layer.d.ts","names":[],"sources":["../../src/interaction/dismiss-layer.ts"],"mappings":";;;qBAmBa;qBACA;;qBAKA,OAAK,OAAA;;;;;;;YAON,eAAe,MAAM;qBAEpB,OAAK,OAAA;;;;;;;;;;YAIN,eAAe,MAAM;qBAEpB,mCAAO;;;IAEL,QAAM,OAAA,OAAA,OAAA;;;;;;;IAAuB,QAAM,OAAA,OAAA,OAAA;;;IAC/B,QAAM,OAAA,OAAA,OAAA;;;;;;;;;YAEb,iBAAiB,QAAQ;qBAExB,SAAO,OAAA;;;YACR,iBAAiB,QAAQ;;qBAGxB,YAAS,QACZ,cAAc,QAAM,QACpB,0BACP;qBAsBU,QAAM,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;qBAqCN,eAAY,MAAU,cAAc,iBAAe;iBA6C/C,gBAAgB,OAAO;;WAE7B,aAAa;;WAEb,gBAAgB;WAChB,KAAK,OAAO;;WAEZ;;WAEA;;;;;;;;qBASE,WACV,sBAAoB,WAAa,gBAAgB,QAAQ,YACzD,OAAK,OAAS,WACd,OAAO,eAAa,SACV,gBAAgB,OAAO,WAC/B,SAAS,cAAc,OAAO,OAAO"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { Effect, Queue, Schema, Stream } from "effect";
|
|
2
|
+
import { defineMessageUnion } from "foldkit/message";
|
|
3
|
+
import * as Subscription from "foldkit/subscription";
|
|
4
|
+
import { Bundle } from "foldkit-bundle";
|
|
5
|
+
import { Behavior, Capability } from "foldkit-mixins";
|
|
6
|
+
// src/interaction/dismiss-layer.ts
|
|
7
|
+
/**
|
|
8
|
+
* Dismissable layers: Escape closes the topmost open layer, a pointer press
|
|
9
|
+
* outside closes the layers it is outside of. One Bundle, placed once, owns
|
|
10
|
+
* the document listeners; each layer's Behavior marks its container (and its
|
|
11
|
+
* trigger) with data attributes. The stack is the DOM order of the marked
|
|
12
|
+
* elements at the moment of the event, so a layer opening or closing needs no
|
|
13
|
+
* registration. A press inside a parent layer is outside its children, so the
|
|
14
|
+
* parent stays and the children go; a press on a layer's trigger counts as
|
|
15
|
+
* inside it, so a trigger never dismisses and reopens in one click. What a
|
|
16
|
+
* dismissal does is the placement's `onOut`.
|
|
17
|
+
*/
|
|
18
|
+
const LAYER_ATTRIBUTE = "data-foldkit-plus-layer";
|
|
19
|
+
const TRIGGER_ATTRIBUTE = "data-foldkit-plus-layer-trigger";
|
|
20
|
+
const OUTSIDE_ATTRIBUTE = "data-foldkit-plus-layer-outside";
|
|
21
|
+
const ESCAPE_ATTRIBUTE = "data-foldkit-plus-layer-escape";
|
|
22
|
+
/** An open layer as the document showed it: bottom to top is DOM order. */
|
|
23
|
+
const Layer = Schema.Struct({
|
|
24
|
+
id: Schema.String,
|
|
25
|
+
/** Dismiss on a press outside it. */
|
|
26
|
+
outside: Schema.Boolean,
|
|
27
|
+
/** Dismiss on Escape when topmost. */
|
|
28
|
+
escape: Schema.Boolean
|
|
29
|
+
});
|
|
30
|
+
const Model = Schema.Struct({
|
|
31
|
+
/** The open layers at the last event, bottom to top. */
|
|
32
|
+
layers: Schema.Array(Layer) });
|
|
33
|
+
const Message = defineMessageUnion({
|
|
34
|
+
/** A pointer went down; `inside` are the layers whose element or trigger was on the event's path. */
|
|
35
|
+
PressedAt: {
|
|
36
|
+
layers: Schema.Array(Layer),
|
|
37
|
+
inside: Schema.Array(Schema.String)
|
|
38
|
+
},
|
|
39
|
+
PressedEscape: { layers: Schema.Array(Layer) }
|
|
40
|
+
});
|
|
41
|
+
const Dismiss = Schema.TaggedStruct("Dismiss", { ids: Schema.Array(Schema.String) });
|
|
42
|
+
/** Which layers a press inside `inside` dismisses: every layer above the topmost one hit, or all when none was. */
|
|
43
|
+
const toDismiss = (layers, inside) => {
|
|
44
|
+
let topmostHit = -1;
|
|
45
|
+
layers.forEach((layer, index) => {
|
|
46
|
+
if (inside.includes(layer.id)) topmostHit = index;
|
|
47
|
+
});
|
|
48
|
+
return layers.slice(topmostHit + 1).filter((layer) => layer.outside).map((layer) => layer.id);
|
|
49
|
+
};
|
|
50
|
+
const sameLayers = (a, b) => a.length === b.length && a.every((layer, index) => layer.id === b[index].id && layer.outside === b[index].outside && layer.escape === b[index].escape);
|
|
51
|
+
const bundle = Bundle.make("DismissLayer", {
|
|
52
|
+
Model,
|
|
53
|
+
Message,
|
|
54
|
+
init: () => ({ model: { layers: [] } }),
|
|
55
|
+
update: (model, message) => {
|
|
56
|
+
const next = sameLayers(model.layers, message.layers) ? model : { layers: message.layers };
|
|
57
|
+
return Message.match(message, {
|
|
58
|
+
PressedAt: ({ layers, inside }) => {
|
|
59
|
+
const ids = toDismiss(layers, inside);
|
|
60
|
+
return ids.length === 0 ? { model: next } : {
|
|
61
|
+
model: next,
|
|
62
|
+
outMessage: Dismiss.make({ ids })
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
PressedEscape: ({ layers }) => {
|
|
66
|
+
const top = layers[layers.length - 1];
|
|
67
|
+
return top !== void 0 && top.escape ? {
|
|
68
|
+
model: next,
|
|
69
|
+
outMessage: Dismiss.make({ ids: [top.id] })
|
|
70
|
+
} : { model: next };
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
subscriptions: () => Subscription.make()(() => ({ document: Subscription.persistentEntry(documentEvents()) }))
|
|
75
|
+
});
|
|
76
|
+
const openLayers = (root) => Array.from(root.querySelectorAll(`[${LAYER_ATTRIBUTE}]`)).map((element) => ({
|
|
77
|
+
id: element.getAttribute("data-foldkit-plus-layer") ?? "",
|
|
78
|
+
outside: element.getAttribute(OUTSIDE_ATTRIBUTE) !== "false",
|
|
79
|
+
escape: element.getAttribute(ESCAPE_ATTRIBUTE) !== "false"
|
|
80
|
+
}));
|
|
81
|
+
/** The layer ids whose element or trigger is on the event's composed path. */
|
|
82
|
+
const layersOnPath = (path) => {
|
|
83
|
+
const ids = [];
|
|
84
|
+
for (const target of path) {
|
|
85
|
+
if (!(target instanceof Element)) continue;
|
|
86
|
+
const id = target.getAttribute("data-foldkit-plus-layer") ?? target.getAttribute("data-foldkit-plus-layer-trigger");
|
|
87
|
+
if (id !== null && !ids.includes(id)) ids.push(id);
|
|
88
|
+
}
|
|
89
|
+
return ids;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* The facts are read inside the listener, not after: `composedPath()` is
|
|
93
|
+
* empty once dispatch has finished, and the open layers must be the ones the
|
|
94
|
+
* press saw, not the ones a later render left.
|
|
95
|
+
*/
|
|
96
|
+
const documentEvents = () => {
|
|
97
|
+
if (typeof document === "undefined") return Stream.empty;
|
|
98
|
+
return Stream.callback((queue) => Effect.acquireRelease(Effect.sync(() => {
|
|
99
|
+
const onPointerDown = (event) => Queue.offerUnsafe(queue, Message.PressedAt({
|
|
100
|
+
layers: openLayers(document),
|
|
101
|
+
inside: layersOnPath(event.composedPath())
|
|
102
|
+
}));
|
|
103
|
+
const onKeyDown = (event) => {
|
|
104
|
+
if (event.key !== "Escape") return;
|
|
105
|
+
Queue.offerUnsafe(queue, Message.PressedEscape({ layers: openLayers(document) }));
|
|
106
|
+
};
|
|
107
|
+
document.addEventListener("pointerdown", onPointerDown, { capture: true });
|
|
108
|
+
document.addEventListener("keydown", onKeyDown, { capture: true });
|
|
109
|
+
return {
|
|
110
|
+
onPointerDown,
|
|
111
|
+
onKeyDown
|
|
112
|
+
};
|
|
113
|
+
}), ({ onPointerDown, onKeyDown }) => Effect.sync(() => {
|
|
114
|
+
document.removeEventListener("pointerdown", onPointerDown, { capture: true });
|
|
115
|
+
document.removeEventListener("keydown", onKeyDown, { capture: true });
|
|
116
|
+
})));
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Marks the layer's container and trigger for the placed stack. The layer
|
|
120
|
+
* takes part only while its element is rendered, so an `open` flag in the
|
|
121
|
+
* parent Model is the whole lifecycle. Not for an element with `popover`,
|
|
122
|
+
* which the browser dismisses itself.
|
|
123
|
+
*/
|
|
124
|
+
const behavior = (_declared) => (slots) => (options) => Behavior.forSlots(slots)({
|
|
125
|
+
[options.layer]: Behavior.slot({
|
|
126
|
+
requires: { capability: Capability.Container },
|
|
127
|
+
attributes: ({ input, h }) => [
|
|
128
|
+
h.Attribute(LAYER_ATTRIBUTE, options.id(input)),
|
|
129
|
+
...options.outsidePress === false ? [h.Attribute(OUTSIDE_ATTRIBUTE, "false")] : [],
|
|
130
|
+
...options.escape === false ? [h.Attribute(ESCAPE_ATTRIBUTE, "false")] : []
|
|
131
|
+
]
|
|
132
|
+
}),
|
|
133
|
+
...options.trigger === void 0 ? {} : { [options.trigger]: Behavior.slot({
|
|
134
|
+
requires: { capability: Capability.Interactive },
|
|
135
|
+
attributes: ({ input, h }) => [h.Attribute(TRIGGER_ATTRIBUTE, options.id(input))]
|
|
136
|
+
}) }
|
|
137
|
+
}, { name: "DismissLayer" });
|
|
138
|
+
export { Dismiss, LAYER_ATTRIBUTE, Layer, Message, Model, TRIGGER_ATTRIBUTE, behavior, bundle, layersOnPath, toDismiss };
|
|
139
|
+
|
|
140
|
+
//# sourceMappingURL=dismiss-layer.js.map
|