@wardic/solid 0.0.0-stage → 1.0.0-rc.2
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/LICENSE +21 -0
- package/README.md +26 -2
- package/THIRD_PARTY_NOTICES.md +145 -0
- package/dist/browser/animation-controls.js +150 -0
- package/dist/browser/animation-controls.js.map +1 -0
- package/dist/browser/animation-frame.js +29 -0
- package/dist/browser/animation-frame.js.map +1 -0
- package/dist/browser/appear.js +727 -0
- package/dist/browser/appear.js.map +1 -0
- package/dist/browser/arc.js +21 -0
- package/dist/browser/arc.js.map +1 -0
- package/dist/browser/bridge.js +69 -0
- package/dist/browser/bridge.js.map +1 -0
- package/dist/browser/complete.js +30 -0
- package/dist/browser/complete.js.map +1 -0
- package/dist/browser/config.js +2 -0
- package/dist/browser/config.js.map +1 -0
- package/dist/browser/create-animate.js +41 -0
- package/dist/browser/create-animate.js.map +1 -0
- package/dist/browser/create-ward.js +1001 -0
- package/dist/browser/create-ward.js.map +1 -0
- package/dist/browser/cycle-index.js +17 -0
- package/dist/browser/cycle-index.js.map +1 -0
- package/dist/browser/cycle.js +31 -0
- package/dist/browser/cycle.js.map +1 -0
- package/dist/browser/directive.js +80 -0
- package/dist/browser/directive.js.map +1 -0
- package/dist/browser/drag-constraints.js +76 -0
- package/dist/browser/drag-constraints.js.map +1 -0
- package/dist/browser/drag-controls.js +51 -0
- package/dist/browser/drag-controls.js.map +1 -0
- package/dist/browser/drag-samples.js +40 -0
- package/dist/browser/drag-samples.js.map +1 -0
- package/dist/browser/drag-sensor.js +35 -0
- package/dist/browser/drag-sensor.js.map +1 -0
- package/dist/browser/drag-track.js +817 -0
- package/dist/browser/drag-track.js.map +1 -0
- package/dist/browser/drag-transition.js +56 -0
- package/dist/browser/drag-transition.js.map +1 -0
- package/dist/browser/drag.js +44 -0
- package/dist/browser/drag.js.map +1 -0
- package/dist/browser/element-style.js +67 -0
- package/dist/browser/element-style.js.map +1 -0
- package/dist/browser/element.js +353 -0
- package/dist/browser/element.js.map +1 -0
- package/dist/browser/feature-section.js +17 -0
- package/dist/browser/feature-section.js.map +1 -0
- package/dist/browser/feature.js +261 -0
- package/dist/browser/feature.js.map +1 -0
- package/dist/browser/features/all.js +10 -0
- package/dist/browser/features/all.js.map +1 -0
- package/dist/browser/features/colors.js +33 -0
- package/dist/browser/features/colors.js.map +1 -0
- package/dist/browser/features/dom-animation.js +7 -0
- package/dist/browser/features/dom-animation.js.map +1 -0
- package/dist/browser/features/dom-max.js +4 -0
- package/dist/browser/features/dom-max.js.map +1 -0
- package/dist/browser/features/drag.js +28 -0
- package/dist/browser/features/drag.js.map +1 -0
- package/dist/browser/features/focus.js +18 -0
- package/dist/browser/features/focus.js.map +1 -0
- package/dist/browser/features/hover.js +18 -0
- package/dist/browser/features/hover.js.map +1 -0
- package/dist/browser/features/in-view.js +18 -0
- package/dist/browser/features/in-view.js.map +1 -0
- package/dist/browser/features/input.js +30 -0
- package/dist/browser/features/input.js.map +1 -0
- package/dist/browser/features/keys.js +19 -0
- package/dist/browser/features/keys.js.map +1 -0
- package/dist/browser/features/layout.js +33 -0
- package/dist/browser/features/layout.js.map +1 -0
- package/dist/browser/features/pan.js +18 -0
- package/dist/browser/features/pan.js.map +1 -0
- package/dist/browser/features/press.js +12 -0
- package/dist/browser/features/press.js.map +1 -0
- package/dist/browser/focus-sensor.js +23 -0
- package/dist/browser/focus-sensor.js.map +1 -0
- package/dist/browser/frame-time.js +40 -0
- package/dist/browser/frame-time.js.map +1 -0
- package/dist/browser/gesture-callbacks.js +172 -0
- package/dist/browser/gesture-callbacks.js.map +1 -0
- package/dist/browser/gesture-features.js +29 -0
- package/dist/browser/gesture-features.js.map +1 -0
- package/dist/browser/gesture-info.js +43 -0
- package/dist/browser/gesture-info.js.map +1 -0
- package/dist/browser/hover-sensor.js +29 -0
- package/dist/browser/hover-sensor.js.map +1 -0
- package/dist/browser/imperative.js +614 -0
- package/dist/browser/imperative.js.map +1 -0
- package/dist/browser/index.js +165 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/instant.js +51 -0
- package/dist/browser/instant.js.map +1 -0
- package/dist/browser/layout-group.js +27 -0
- package/dist/browser/layout-group.js.map +1 -0
- package/dist/browser/layout-member.js +362 -0
- package/dist/browser/layout-member.js.map +1 -0
- package/dist/browser/layout-projection.js +19 -0
- package/dist/browser/layout-projection.js.map +1 -0
- package/dist/browser/layout.js +91 -0
- package/dist/browser/layout.js.map +1 -0
- package/dist/browser/live-style.js +313 -0
- package/dist/browser/live-style.js.map +1 -0
- package/dist/browser/live-value.js +252 -0
- package/dist/browser/live-value.js.map +1 -0
- package/dist/browser/motion-props.js +172 -0
- package/dist/browser/motion-props.js.map +1 -0
- package/dist/browser/owner-scope.js +29 -0
- package/dist/browser/owner-scope.js.map +1 -0
- package/dist/browser/page-point.js +92 -0
- package/dist/browser/page-point.js.map +1 -0
- package/dist/browser/presence-controller.js +1324 -0
- package/dist/browser/presence-controller.js.map +1 -0
- package/dist/browser/presence-record.js +27 -0
- package/dist/browser/presence-record.js.map +1 -0
- package/dist/browser/presence.js +207 -0
- package/dist/browser/presence.js.map +1 -0
- package/dist/browser/press-sensor.js +30 -0
- package/dist/browser/press-sensor.js.map +1 -0
- package/dist/browser/press.js +24 -0
- package/dist/browser/press.js.map +1 -0
- package/dist/browser/provider.js +445 -0
- package/dist/browser/provider.js.map +1 -0
- package/dist/browser/reactivity.js +9 -0
- package/dist/browser/reactivity.js.map +1 -0
- package/dist/browser/reorder-input.js +46 -0
- package/dist/browser/reorder-input.js.map +1 -0
- package/dist/browser/reorder.js +543 -0
- package/dist/browser/reorder.js.map +1 -0
- package/dist/browser/retarget-legs.js +1019 -0
- package/dist/browser/retarget-legs.js.map +1 -0
- package/dist/browser/runtime.js +249 -0
- package/dist/browser/runtime.js.map +1 -0
- package/dist/browser/sensors.js +172 -0
- package/dist/browser/sensors.js.map +1 -0
- package/dist/browser/server-interpolators.js +20 -0
- package/dist/browser/server-interpolators.js.map +1 -0
- package/dist/browser/server.js +20 -0
- package/dist/browser/server.js.map +1 -0
- package/dist/browser/solid-reactivity.js +26 -0
- package/dist/browser/solid-reactivity.js.map +1 -0
- package/dist/browser/spine.js +2939 -0
- package/dist/browser/spine.js.map +1 -0
- package/dist/browser/stagger.js +13 -0
- package/dist/browser/stagger.js.map +1 -0
- package/dist/browser/unstable/v2/bridge.js +76 -0
- package/dist/browser/unstable/v2/bridge.js.map +1 -0
- package/dist/browser/unstable/v2/complete.js +29 -0
- package/dist/browser/unstable/v2/complete.js.map +1 -0
- package/dist/browser/unstable/v2/config-view.js +111 -0
- package/dist/browser/unstable/v2/config-view.js.map +1 -0
- package/dist/browser/unstable/v2/create-animate.js +102 -0
- package/dist/browser/unstable/v2/create-animate.js.map +1 -0
- package/dist/browser/unstable/v2/cycle.js +30 -0
- package/dist/browser/unstable/v2/cycle.js.map +1 -0
- package/dist/browser/unstable/v2/drag-sensor.js +34 -0
- package/dist/browser/unstable/v2/drag-sensor.js.map +1 -0
- package/dist/browser/unstable/v2/element.js +393 -0
- package/dist/browser/unstable/v2/element.js.map +1 -0
- package/dist/browser/unstable/v2/feature-section.js +27 -0
- package/dist/browser/unstable/v2/feature-section.js.map +1 -0
- package/dist/browser/unstable/v2/focus-sensor.js +23 -0
- package/dist/browser/unstable/v2/focus-sensor.js.map +1 -0
- package/dist/browser/unstable/v2/hover-sensor.js +28 -0
- package/dist/browser/unstable/v2/hover-sensor.js.map +1 -0
- package/dist/browser/unstable/v2/index.js +114 -0
- package/dist/browser/unstable/v2/index.js.map +1 -0
- package/dist/browser/unstable/v2/layout-projection.js +18 -0
- package/dist/browser/unstable/v2/layout-projection.js.map +1 -0
- package/dist/browser/unstable/v2/layout.js +71 -0
- package/dist/browser/unstable/v2/layout.js.map +1 -0
- package/dist/browser/unstable/v2/lifecycle.js +455 -0
- package/dist/browser/unstable/v2/lifecycle.js.map +1 -0
- package/dist/browser/unstable/v2/live-value.js +264 -0
- package/dist/browser/unstable/v2/live-value.js.map +1 -0
- package/dist/browser/unstable/v2/presence-handle.js +146 -0
- package/dist/browser/unstable/v2/presence-handle.js.map +1 -0
- package/dist/browser/unstable/v2/presence-hooks.js +142 -0
- package/dist/browser/unstable/v2/presence-hooks.js.map +1 -0
- package/dist/browser/unstable/v2/presence.js +124 -0
- package/dist/browser/unstable/v2/presence.js.map +1 -0
- package/dist/browser/unstable/v2/press-sensor.js +29 -0
- package/dist/browser/unstable/v2/press-sensor.js.map +1 -0
- package/dist/browser/unstable/v2/provider.js +457 -0
- package/dist/browser/unstable/v2/provider.js.map +1 -0
- package/dist/browser/unstable/v2/reorder.js +663 -0
- package/dist/browser/unstable/v2/reorder.js.map +1 -0
- package/dist/browser/unstable/v2/sensors.js +138 -0
- package/dist/browser/unstable/v2/sensors.js.map +1 -0
- package/dist/browser/unstable/v2/solid-reactivity.js +82 -0
- package/dist/browser/unstable/v2/solid-reactivity.js.map +1 -0
- package/dist/browser/unstable/v2/variant-node.js +395 -0
- package/dist/browser/unstable/v2/variant-node.js.map +1 -0
- package/dist/browser/unstable/v2/w.js +23 -0
- package/dist/browser/unstable/v2/w.js.map +1 -0
- package/dist/browser/unstable/v2/waiters.js +185 -0
- package/dist/browser/unstable/v2/waiters.js.map +1 -0
- package/dist/browser/unstable/v2/ward.js +1620 -0
- package/dist/browser/unstable/v2/ward.js.map +1 -0
- package/dist/browser/unstable/v2/wardic-config.js +40 -0
- package/dist/browser/unstable/v2/wardic-config.js.map +1 -0
- package/dist/browser/unstable/v2/wardic.js +16 -0
- package/dist/browser/unstable/v2/wardic.js.map +1 -0
- package/dist/browser/variant-node.js +308 -0
- package/dist/browser/variant-node.js.map +1 -0
- package/dist/browser/variant-target.js +224 -0
- package/dist/browser/variant-target.js.map +1 -0
- package/dist/browser/variant-tree.js +394 -0
- package/dist/browser/variant-tree.js.map +1 -0
- package/dist/browser/variants.js +43 -0
- package/dist/browser/variants.js.map +1 -0
- package/dist/browser/w.js +25 -0
- package/dist/browser/w.js.map +1 -0
- package/dist/browser/ward-keys.js +2 -0
- package/dist/browser/ward-keys.js.map +1 -0
- package/dist/browser/wardic-component.js +74 -0
- package/dist/browser/wardic-component.js.map +1 -0
- package/dist/browser/wardic-config-value.js +91 -0
- package/dist/browser/wardic-config-value.js.map +1 -0
- package/dist/browser/wardic-config.js +42 -0
- package/dist/browser/wardic-config.js.map +1 -0
- package/dist/browser/wardic.js +31 -0
- package/dist/browser/wardic.js.map +1 -0
- package/dist/server/animation-controls.js +150 -0
- package/dist/server/animation-controls.js.map +1 -0
- package/dist/server/animation-frame.js +29 -0
- package/dist/server/animation-frame.js.map +1 -0
- package/dist/server/appear.js +727 -0
- package/dist/server/appear.js.map +1 -0
- package/dist/server/arc.js +21 -0
- package/dist/server/arc.js.map +1 -0
- package/dist/server/bridge.js +69 -0
- package/dist/server/bridge.js.map +1 -0
- package/dist/server/complete.js +30 -0
- package/dist/server/complete.js.map +1 -0
- package/dist/server/config.js +2 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/create-animate.js +41 -0
- package/dist/server/create-animate.js.map +1 -0
- package/dist/server/create-ward.js +1001 -0
- package/dist/server/create-ward.js.map +1 -0
- package/dist/server/cycle-index.js +17 -0
- package/dist/server/cycle-index.js.map +1 -0
- package/dist/server/cycle.js +31 -0
- package/dist/server/cycle.js.map +1 -0
- package/dist/server/directive.js +80 -0
- package/dist/server/directive.js.map +1 -0
- package/dist/server/drag-constraints.js +76 -0
- package/dist/server/drag-constraints.js.map +1 -0
- package/dist/server/drag-controls.js +51 -0
- package/dist/server/drag-controls.js.map +1 -0
- package/dist/server/drag-samples.js +40 -0
- package/dist/server/drag-samples.js.map +1 -0
- package/dist/server/drag-sensor.js +35 -0
- package/dist/server/drag-sensor.js.map +1 -0
- package/dist/server/drag-track.js +817 -0
- package/dist/server/drag-track.js.map +1 -0
- package/dist/server/drag-transition.js +56 -0
- package/dist/server/drag-transition.js.map +1 -0
- package/dist/server/drag.js +44 -0
- package/dist/server/drag.js.map +1 -0
- package/dist/server/element-style.js +67 -0
- package/dist/server/element-style.js.map +1 -0
- package/dist/server/element.js +353 -0
- package/dist/server/element.js.map +1 -0
- package/dist/server/feature-section.js +17 -0
- package/dist/server/feature-section.js.map +1 -0
- package/dist/server/feature.js +261 -0
- package/dist/server/feature.js.map +1 -0
- package/dist/server/features/all.js +10 -0
- package/dist/server/features/all.js.map +1 -0
- package/dist/server/features/colors.js +33 -0
- package/dist/server/features/colors.js.map +1 -0
- package/dist/server/features/dom-animation.js +7 -0
- package/dist/server/features/dom-animation.js.map +1 -0
- package/dist/server/features/dom-max.js +4 -0
- package/dist/server/features/dom-max.js.map +1 -0
- package/dist/server/features/drag.js +28 -0
- package/dist/server/features/drag.js.map +1 -0
- package/dist/server/features/focus.js +18 -0
- package/dist/server/features/focus.js.map +1 -0
- package/dist/server/features/hover.js +18 -0
- package/dist/server/features/hover.js.map +1 -0
- package/dist/server/features/in-view.js +18 -0
- package/dist/server/features/in-view.js.map +1 -0
- package/dist/server/features/input.js +30 -0
- package/dist/server/features/input.js.map +1 -0
- package/dist/server/features/keys.js +19 -0
- package/dist/server/features/keys.js.map +1 -0
- package/dist/server/features/layout.js +33 -0
- package/dist/server/features/layout.js.map +1 -0
- package/dist/server/features/pan.js +18 -0
- package/dist/server/features/pan.js.map +1 -0
- package/dist/server/features/press.js +12 -0
- package/dist/server/features/press.js.map +1 -0
- package/dist/server/focus-sensor.js +23 -0
- package/dist/server/focus-sensor.js.map +1 -0
- package/dist/server/frame-time.js +40 -0
- package/dist/server/frame-time.js.map +1 -0
- package/dist/server/gesture-callbacks.js +172 -0
- package/dist/server/gesture-callbacks.js.map +1 -0
- package/dist/server/gesture-features.js +29 -0
- package/dist/server/gesture-features.js.map +1 -0
- package/dist/server/gesture-info.js +43 -0
- package/dist/server/gesture-info.js.map +1 -0
- package/dist/server/hover-sensor.js +29 -0
- package/dist/server/hover-sensor.js.map +1 -0
- package/dist/server/imperative.js +614 -0
- package/dist/server/imperative.js.map +1 -0
- package/dist/server/index.js +165 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/instant.js +51 -0
- package/dist/server/instant.js.map +1 -0
- package/dist/server/layout-group.js +27 -0
- package/dist/server/layout-group.js.map +1 -0
- package/dist/server/layout-member.js +362 -0
- package/dist/server/layout-member.js.map +1 -0
- package/dist/server/layout-projection.js +19 -0
- package/dist/server/layout-projection.js.map +1 -0
- package/dist/server/layout.js +90 -0
- package/dist/server/layout.js.map +1 -0
- package/dist/server/live-style.js +313 -0
- package/dist/server/live-style.js.map +1 -0
- package/dist/server/live-value.js +252 -0
- package/dist/server/live-value.js.map +1 -0
- package/dist/server/motion-props.js +172 -0
- package/dist/server/motion-props.js.map +1 -0
- package/dist/server/owner-scope.js +29 -0
- package/dist/server/owner-scope.js.map +1 -0
- package/dist/server/page-point.js +92 -0
- package/dist/server/page-point.js.map +1 -0
- package/dist/server/presence-controller.js +1324 -0
- package/dist/server/presence-controller.js.map +1 -0
- package/dist/server/presence-record.js +27 -0
- package/dist/server/presence-record.js.map +1 -0
- package/dist/server/presence.js +207 -0
- package/dist/server/presence.js.map +1 -0
- package/dist/server/press-sensor.js +30 -0
- package/dist/server/press-sensor.js.map +1 -0
- package/dist/server/press.js +24 -0
- package/dist/server/press.js.map +1 -0
- package/dist/server/provider.js +439 -0
- package/dist/server/provider.js.map +1 -0
- package/dist/server/reactivity.js +9 -0
- package/dist/server/reactivity.js.map +1 -0
- package/dist/server/reorder-input.js +46 -0
- package/dist/server/reorder-input.js.map +1 -0
- package/dist/server/reorder.js +543 -0
- package/dist/server/reorder.js.map +1 -0
- package/dist/server/retarget-legs.js +1019 -0
- package/dist/server/retarget-legs.js.map +1 -0
- package/dist/server/runtime.js +249 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/sensors.js +172 -0
- package/dist/server/sensors.js.map +1 -0
- package/dist/server/server-interpolators.js +20 -0
- package/dist/server/server-interpolators.js.map +1 -0
- package/dist/server/server.js +20 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/solid-reactivity.js +26 -0
- package/dist/server/solid-reactivity.js.map +1 -0
- package/dist/server/spine.js +2939 -0
- package/dist/server/spine.js.map +1 -0
- package/dist/server/stagger.js +13 -0
- package/dist/server/stagger.js.map +1 -0
- package/dist/server/unstable/v2/bridge.js +76 -0
- package/dist/server/unstable/v2/bridge.js.map +1 -0
- package/dist/server/unstable/v2/complete.js +29 -0
- package/dist/server/unstable/v2/complete.js.map +1 -0
- package/dist/server/unstable/v2/config-view.js +111 -0
- package/dist/server/unstable/v2/config-view.js.map +1 -0
- package/dist/server/unstable/v2/create-animate.js +102 -0
- package/dist/server/unstable/v2/create-animate.js.map +1 -0
- package/dist/server/unstable/v2/cycle.js +30 -0
- package/dist/server/unstable/v2/cycle.js.map +1 -0
- package/dist/server/unstable/v2/drag-sensor.js +34 -0
- package/dist/server/unstable/v2/drag-sensor.js.map +1 -0
- package/dist/server/unstable/v2/element.js +402 -0
- package/dist/server/unstable/v2/element.js.map +1 -0
- package/dist/server/unstable/v2/feature-section.js +27 -0
- package/dist/server/unstable/v2/feature-section.js.map +1 -0
- package/dist/server/unstable/v2/focus-sensor.js +23 -0
- package/dist/server/unstable/v2/focus-sensor.js.map +1 -0
- package/dist/server/unstable/v2/hover-sensor.js +28 -0
- package/dist/server/unstable/v2/hover-sensor.js.map +1 -0
- package/dist/server/unstable/v2/index.js +114 -0
- package/dist/server/unstable/v2/index.js.map +1 -0
- package/dist/server/unstable/v2/layout-projection.js +18 -0
- package/dist/server/unstable/v2/layout-projection.js.map +1 -0
- package/dist/server/unstable/v2/layout.js +88 -0
- package/dist/server/unstable/v2/layout.js.map +1 -0
- package/dist/server/unstable/v2/lifecycle.js +455 -0
- package/dist/server/unstable/v2/lifecycle.js.map +1 -0
- package/dist/server/unstable/v2/live-value.js +264 -0
- package/dist/server/unstable/v2/live-value.js.map +1 -0
- package/dist/server/unstable/v2/presence-handle.js +146 -0
- package/dist/server/unstable/v2/presence-handle.js.map +1 -0
- package/dist/server/unstable/v2/presence-hooks.js +142 -0
- package/dist/server/unstable/v2/presence-hooks.js.map +1 -0
- package/dist/server/unstable/v2/presence.js +142 -0
- package/dist/server/unstable/v2/presence.js.map +1 -0
- package/dist/server/unstable/v2/press-sensor.js +29 -0
- package/dist/server/unstable/v2/press-sensor.js.map +1 -0
- package/dist/server/unstable/v2/provider.js +475 -0
- package/dist/server/unstable/v2/provider.js.map +1 -0
- package/dist/server/unstable/v2/reorder.js +733 -0
- package/dist/server/unstable/v2/reorder.js.map +1 -0
- package/dist/server/unstable/v2/sensors.js +138 -0
- package/dist/server/unstable/v2/sensors.js.map +1 -0
- package/dist/server/unstable/v2/solid-reactivity.js +82 -0
- package/dist/server/unstable/v2/solid-reactivity.js.map +1 -0
- package/dist/server/unstable/v2/variant-node.js +395 -0
- package/dist/server/unstable/v2/variant-node.js.map +1 -0
- package/dist/server/unstable/v2/w.js +23 -0
- package/dist/server/unstable/v2/w.js.map +1 -0
- package/dist/server/unstable/v2/waiters.js +185 -0
- package/dist/server/unstable/v2/waiters.js.map +1 -0
- package/dist/server/unstable/v2/ward.js +1653 -0
- package/dist/server/unstable/v2/ward.js.map +1 -0
- package/dist/server/unstable/v2/wardic-config.js +49 -0
- package/dist/server/unstable/v2/wardic-config.js.map +1 -0
- package/dist/server/unstable/v2/wardic.js +16 -0
- package/dist/server/unstable/v2/wardic.js.map +1 -0
- package/dist/server/variant-node.js +308 -0
- package/dist/server/variant-node.js.map +1 -0
- package/dist/server/variant-target.js +224 -0
- package/dist/server/variant-target.js.map +1 -0
- package/dist/server/variant-tree.js +394 -0
- package/dist/server/variant-tree.js.map +1 -0
- package/dist/server/variants.js +43 -0
- package/dist/server/variants.js.map +1 -0
- package/dist/server/w.js +25 -0
- package/dist/server/w.js.map +1 -0
- package/dist/server/ward-keys.js +2 -0
- package/dist/server/ward-keys.js.map +1 -0
- package/dist/server/wardic-component.js +74 -0
- package/dist/server/wardic-component.js.map +1 -0
- package/dist/server/wardic-config-value.js +91 -0
- package/dist/server/wardic-config-value.js.map +1 -0
- package/dist/server/wardic-config.js +42 -0
- package/dist/server/wardic-config.js.map +1 -0
- package/dist/server/wardic.js +31 -0
- package/dist/server/wardic.js.map +1 -0
- package/dist/solid/animation-controls.d.ts +104 -0
- package/dist/solid/animation-controls.d.ts.map +1 -0
- package/dist/solid/animation-controls.js +129 -0
- package/dist/solid/animation-controls.js.map +1 -0
- package/dist/solid/animation-frame.d.ts +11 -0
- package/dist/solid/animation-frame.d.ts.map +1 -0
- package/dist/solid/animation-frame.js +31 -0
- package/dist/solid/animation-frame.js.map +1 -0
- package/dist/solid/appear.d.ts +205 -0
- package/dist/solid/appear.d.ts.map +1 -0
- package/dist/solid/appear.js +519 -0
- package/dist/solid/appear.js.map +1 -0
- package/dist/solid/arc.d.ts +25 -0
- package/dist/solid/arc.d.ts.map +1 -0
- package/dist/solid/arc.js +21 -0
- package/dist/solid/arc.js.map +1 -0
- package/dist/solid/bridge.d.ts +53 -0
- package/dist/solid/bridge.d.ts.map +1 -0
- package/dist/solid/bridge.js +66 -0
- package/dist/solid/bridge.js.map +1 -0
- package/dist/solid/complete.d.ts +31 -0
- package/dist/solid/complete.d.ts.map +1 -0
- package/dist/solid/complete.js +27 -0
- package/dist/solid/complete.js.map +1 -0
- package/dist/solid/config.d.ts +693 -0
- package/dist/solid/config.d.ts.map +1 -0
- package/dist/solid/config.js +2 -0
- package/dist/solid/config.js.map +1 -0
- package/dist/solid/create-animate.d.ts +17 -0
- package/dist/solid/create-animate.d.ts.map +1 -0
- package/dist/solid/create-animate.js +42 -0
- package/dist/solid/create-animate.js.map +1 -0
- package/dist/solid/create-ward.d.ts +278 -0
- package/dist/solid/create-ward.d.ts.map +1 -0
- package/dist/solid/create-ward.jsx +874 -0
- package/dist/solid/create-ward.jsx.map +1 -0
- package/dist/solid/cycle-index.d.ts +7 -0
- package/dist/solid/cycle-index.d.ts.map +1 -0
- package/dist/solid/cycle-index.js +17 -0
- package/dist/solid/cycle-index.js.map +1 -0
- package/dist/solid/cycle.d.ts +21 -0
- package/dist/solid/cycle.d.ts.map +1 -0
- package/dist/solid/cycle.js +31 -0
- package/dist/solid/cycle.js.map +1 -0
- package/dist/solid/directive.d.ts +21 -0
- package/dist/solid/directive.d.ts.map +1 -0
- package/dist/solid/directive.js +76 -0
- package/dist/solid/directive.js.map +1 -0
- package/dist/solid/drag-constraints.d.ts +46 -0
- package/dist/solid/drag-constraints.d.ts.map +1 -0
- package/dist/solid/drag-constraints.js +49 -0
- package/dist/solid/drag-constraints.js.map +1 -0
- package/dist/solid/drag-controls.d.ts +50 -0
- package/dist/solid/drag-controls.d.ts.map +1 -0
- package/dist/solid/drag-controls.js +51 -0
- package/dist/solid/drag-controls.js.map +1 -0
- package/dist/solid/drag-samples.d.ts +34 -0
- package/dist/solid/drag-samples.d.ts.map +1 -0
- package/dist/solid/drag-samples.js +28 -0
- package/dist/solid/drag-samples.js.map +1 -0
- package/dist/solid/drag-sensor.d.ts +23 -0
- package/dist/solid/drag-sensor.d.ts.map +1 -0
- package/dist/solid/drag-sensor.js +33 -0
- package/dist/solid/drag-sensor.js.map +1 -0
- package/dist/solid/drag-track.d.ts +227 -0
- package/dist/solid/drag-track.d.ts.map +1 -0
- package/dist/solid/drag-track.js +631 -0
- package/dist/solid/drag-track.js.map +1 -0
- package/dist/solid/drag-transition.d.ts +20 -0
- package/dist/solid/drag-transition.d.ts.map +1 -0
- package/dist/solid/drag-transition.js +31 -0
- package/dist/solid/drag-transition.js.map +1 -0
- package/dist/solid/drag.d.ts +23 -0
- package/dist/solid/drag.d.ts.map +1 -0
- package/dist/solid/drag.js +44 -0
- package/dist/solid/drag.js.map +1 -0
- package/dist/solid/element-style.d.ts +60 -0
- package/dist/solid/element-style.d.ts.map +1 -0
- package/dist/solid/element-style.js +50 -0
- package/dist/solid/element-style.js.map +1 -0
- package/dist/solid/element.d.ts +73 -0
- package/dist/solid/element.d.ts.map +1 -0
- package/dist/solid/element.jsx +326 -0
- package/dist/solid/element.jsx.map +1 -0
- package/dist/solid/feature-section.d.ts +18 -0
- package/dist/solid/feature-section.d.ts.map +1 -0
- package/dist/solid/feature-section.js +13 -0
- package/dist/solid/feature-section.js.map +1 -0
- package/dist/solid/feature.d.ts +114 -0
- package/dist/solid/feature.d.ts.map +1 -0
- package/dist/solid/feature.js +248 -0
- package/dist/solid/feature.js.map +1 -0
- package/dist/solid/features/all.d.ts +10 -0
- package/dist/solid/features/all.d.ts.map +1 -0
- package/dist/solid/features/all.js +10 -0
- package/dist/solid/features/all.js.map +1 -0
- package/dist/solid/features/colors.d.ts +12 -0
- package/dist/solid/features/colors.d.ts.map +1 -0
- package/dist/solid/features/colors.js +34 -0
- package/dist/solid/features/colors.js.map +1 -0
- package/dist/solid/features/dom-animation.d.ts +11 -0
- package/dist/solid/features/dom-animation.d.ts.map +1 -0
- package/dist/solid/features/dom-animation.js +7 -0
- package/dist/solid/features/dom-animation.js.map +1 -0
- package/dist/solid/features/dom-max.d.ts +10 -0
- package/dist/solid/features/dom-max.d.ts.map +1 -0
- package/dist/solid/features/dom-max.js +4 -0
- package/dist/solid/features/dom-max.js.map +1 -0
- package/dist/solid/features/drag.d.ts +5 -0
- package/dist/solid/features/drag.d.ts.map +1 -0
- package/dist/solid/features/drag.js +28 -0
- package/dist/solid/features/drag.js.map +1 -0
- package/dist/solid/features/focus.d.ts +5 -0
- package/dist/solid/features/focus.d.ts.map +1 -0
- package/dist/solid/features/focus.js +16 -0
- package/dist/solid/features/focus.js.map +1 -0
- package/dist/solid/features/hover.d.ts +5 -0
- package/dist/solid/features/hover.d.ts.map +1 -0
- package/dist/solid/features/hover.js +16 -0
- package/dist/solid/features/hover.js.map +1 -0
- package/dist/solid/features/in-view.d.ts +5 -0
- package/dist/solid/features/in-view.d.ts.map +1 -0
- package/dist/solid/features/in-view.js +16 -0
- package/dist/solid/features/in-view.js.map +1 -0
- package/dist/solid/features/input.d.ts +26 -0
- package/dist/solid/features/input.d.ts.map +1 -0
- package/dist/solid/features/input.js +31 -0
- package/dist/solid/features/input.js.map +1 -0
- package/dist/solid/features/keys.d.ts +70 -0
- package/dist/solid/features/keys.d.ts.map +1 -0
- package/dist/solid/features/keys.js +26 -0
- package/dist/solid/features/keys.js.map +1 -0
- package/dist/solid/features/layout.d.ts +32 -0
- package/dist/solid/features/layout.d.ts.map +1 -0
- package/dist/solid/features/layout.js +34 -0
- package/dist/solid/features/layout.js.map +1 -0
- package/dist/solid/features/pan.d.ts +5 -0
- package/dist/solid/features/pan.d.ts.map +1 -0
- package/dist/solid/features/pan.js +16 -0
- package/dist/solid/features/pan.js.map +1 -0
- package/dist/solid/features/press.d.ts +11 -0
- package/dist/solid/features/press.d.ts.map +1 -0
- package/dist/solid/features/press.js +10 -0
- package/dist/solid/features/press.js.map +1 -0
- package/dist/solid/focus-sensor.d.ts +19 -0
- package/dist/solid/focus-sensor.d.ts.map +1 -0
- package/dist/solid/focus-sensor.js +23 -0
- package/dist/solid/focus-sensor.js.map +1 -0
- package/dist/solid/frame-time.d.ts +21 -0
- package/dist/solid/frame-time.d.ts.map +1 -0
- package/dist/solid/frame-time.js +41 -0
- package/dist/solid/frame-time.js.map +1 -0
- package/dist/solid/gesture-callbacks.d.ts +53 -0
- package/dist/solid/gesture-callbacks.d.ts.map +1 -0
- package/dist/solid/gesture-callbacks.js +184 -0
- package/dist/solid/gesture-callbacks.js.map +1 -0
- package/dist/solid/gesture-features.d.ts +28 -0
- package/dist/solid/gesture-features.d.ts.map +1 -0
- package/dist/solid/gesture-features.js +29 -0
- package/dist/solid/gesture-features.js.map +1 -0
- package/dist/solid/gesture-info.d.ts +59 -0
- package/dist/solid/gesture-info.d.ts.map +1 -0
- package/dist/solid/gesture-info.js +23 -0
- package/dist/solid/gesture-info.js.map +1 -0
- package/dist/solid/hover-sensor.d.ts +19 -0
- package/dist/solid/hover-sensor.d.ts.map +1 -0
- package/dist/solid/hover-sensor.js +23 -0
- package/dist/solid/hover-sensor.js.map +1 -0
- package/dist/solid/imperative.d.ts +195 -0
- package/dist/solid/imperative.d.ts.map +1 -0
- package/dist/solid/imperative.js +536 -0
- package/dist/solid/imperative.js.map +1 -0
- package/dist/solid/index.d.ts +180 -0
- package/dist/solid/index.d.ts.map +1 -0
- package/dist/solid/index.js +165 -0
- package/dist/solid/index.js.map +1 -0
- package/dist/solid/instant.d.ts +44 -0
- package/dist/solid/instant.d.ts.map +1 -0
- package/dist/solid/instant.js +49 -0
- package/dist/solid/instant.js.map +1 -0
- package/dist/solid/layout-group.d.ts +14 -0
- package/dist/solid/layout-group.d.ts.map +1 -0
- package/dist/solid/layout-group.js +27 -0
- package/dist/solid/layout-group.js.map +1 -0
- package/dist/solid/layout-member.d.ts +117 -0
- package/dist/solid/layout-member.d.ts.map +1 -0
- package/dist/solid/layout-member.js +164 -0
- package/dist/solid/layout-member.js.map +1 -0
- package/dist/solid/layout-projection.d.ts +22 -0
- package/dist/solid/layout-projection.d.ts.map +1 -0
- package/dist/solid/layout-projection.js +19 -0
- package/dist/solid/layout-projection.js.map +1 -0
- package/dist/solid/layout.d.ts +76 -0
- package/dist/solid/layout.d.ts.map +1 -0
- package/dist/solid/layout.jsx +80 -0
- package/dist/solid/layout.jsx.map +1 -0
- package/dist/solid/live-style.d.ts +147 -0
- package/dist/solid/live-style.d.ts.map +1 -0
- package/dist/solid/live-style.js +304 -0
- package/dist/solid/live-style.js.map +1 -0
- package/dist/solid/live-value.d.ts +144 -0
- package/dist/solid/live-value.d.ts.map +1 -0
- package/dist/solid/live-value.js +223 -0
- package/dist/solid/live-value.js.map +1 -0
- package/dist/solid/motion-props.d.ts +75 -0
- package/dist/solid/motion-props.d.ts.map +1 -0
- package/dist/solid/motion-props.js +314 -0
- package/dist/solid/motion-props.js.map +1 -0
- package/dist/solid/owner-scope.d.ts +16 -0
- package/dist/solid/owner-scope.d.ts.map +1 -0
- package/dist/solid/owner-scope.js +31 -0
- package/dist/solid/owner-scope.js.map +1 -0
- package/dist/solid/page-point.d.ts +35 -0
- package/dist/solid/page-point.d.ts.map +1 -0
- package/dist/solid/page-point.js +87 -0
- package/dist/solid/page-point.js.map +1 -0
- package/dist/solid/presence-controller.d.ts +122 -0
- package/dist/solid/presence-controller.d.ts.map +1 -0
- package/dist/solid/presence-controller.js +1207 -0
- package/dist/solid/presence-controller.js.map +1 -0
- package/dist/solid/presence-record.d.ts +167 -0
- package/dist/solid/presence-record.d.ts.map +1 -0
- package/dist/solid/presence-record.js +26 -0
- package/dist/solid/presence-record.js.map +1 -0
- package/dist/solid/presence.d.ts +95 -0
- package/dist/solid/presence.d.ts.map +1 -0
- package/dist/solid/presence.jsx +195 -0
- package/dist/solid/presence.jsx.map +1 -0
- package/dist/solid/press-sensor.d.ts +20 -0
- package/dist/solid/press-sensor.d.ts.map +1 -0
- package/dist/solid/press-sensor.js +24 -0
- package/dist/solid/press-sensor.js.map +1 -0
- package/dist/solid/press.d.ts +24 -0
- package/dist/solid/press.d.ts.map +1 -0
- package/dist/solid/press.js +19 -0
- package/dist/solid/press.js.map +1 -0
- package/dist/solid/provider.d.ts +263 -0
- package/dist/solid/provider.d.ts.map +1 -0
- package/dist/solid/provider.jsx +411 -0
- package/dist/solid/provider.jsx.map +1 -0
- package/dist/solid/reactivity.d.ts +27 -0
- package/dist/solid/reactivity.d.ts.map +1 -0
- package/dist/solid/reactivity.js +9 -0
- package/dist/solid/reactivity.js.map +1 -0
- package/dist/solid/reorder-input.d.ts +22 -0
- package/dist/solid/reorder-input.d.ts.map +1 -0
- package/dist/solid/reorder-input.js +45 -0
- package/dist/solid/reorder-input.js.map +1 -0
- package/dist/solid/reorder.d.ts +241 -0
- package/dist/solid/reorder.d.ts.map +1 -0
- package/dist/solid/reorder.jsx +427 -0
- package/dist/solid/reorder.jsx.map +1 -0
- package/dist/solid/retarget-legs.d.ts +189 -0
- package/dist/solid/retarget-legs.d.ts.map +1 -0
- package/dist/solid/retarget-legs.js +825 -0
- package/dist/solid/retarget-legs.js.map +1 -0
- package/dist/solid/runtime.d.ts +179 -0
- package/dist/solid/runtime.d.ts.map +1 -0
- package/dist/solid/runtime.js +237 -0
- package/dist/solid/runtime.js.map +1 -0
- package/dist/solid/sensors.d.ts +95 -0
- package/dist/solid/sensors.d.ts.map +1 -0
- package/dist/solid/sensors.js +154 -0
- package/dist/solid/sensors.js.map +1 -0
- package/dist/solid/server-interpolators.d.ts +13 -0
- package/dist/solid/server-interpolators.d.ts.map +1 -0
- package/dist/solid/server-interpolators.js +20 -0
- package/dist/solid/server-interpolators.js.map +1 -0
- package/dist/solid/server.d.ts +9 -0
- package/dist/solid/server.d.ts.map +1 -0
- package/dist/solid/server.js +20 -0
- package/dist/solid/server.js.map +1 -0
- package/dist/solid/solid-reactivity.d.ts +3 -0
- package/dist/solid/solid-reactivity.d.ts.map +1 -0
- package/dist/solid/solid-reactivity.js +19 -0
- package/dist/solid/solid-reactivity.js.map +1 -0
- package/dist/solid/spine.d.ts +597 -0
- package/dist/solid/spine.d.ts.map +1 -0
- package/dist/solid/spine.js +2761 -0
- package/dist/solid/spine.js.map +1 -0
- package/dist/solid/stagger.d.ts +29 -0
- package/dist/solid/stagger.d.ts.map +1 -0
- package/dist/solid/stagger.js +13 -0
- package/dist/solid/stagger.js.map +1 -0
- package/dist/solid/unstable/v2/bridge.d.ts +33 -0
- package/dist/solid/unstable/v2/bridge.d.ts.map +1 -0
- package/dist/solid/unstable/v2/bridge.js +76 -0
- package/dist/solid/unstable/v2/bridge.js.map +1 -0
- package/dist/solid/unstable/v2/complete.d.ts +21 -0
- package/dist/solid/unstable/v2/complete.d.ts.map +1 -0
- package/dist/solid/unstable/v2/complete.js +27 -0
- package/dist/solid/unstable/v2/complete.js.map +1 -0
- package/dist/solid/unstable/v2/config-view.d.ts +49 -0
- package/dist/solid/unstable/v2/config-view.d.ts.map +1 -0
- package/dist/solid/unstable/v2/config-view.js +114 -0
- package/dist/solid/unstable/v2/config-view.js.map +1 -0
- package/dist/solid/unstable/v2/create-animate.d.ts +31 -0
- package/dist/solid/unstable/v2/create-animate.d.ts.map +1 -0
- package/dist/solid/unstable/v2/create-animate.js +102 -0
- package/dist/solid/unstable/v2/create-animate.js.map +1 -0
- package/dist/solid/unstable/v2/cycle.d.ts +20 -0
- package/dist/solid/unstable/v2/cycle.d.ts.map +1 -0
- package/dist/solid/unstable/v2/cycle.js +30 -0
- package/dist/solid/unstable/v2/cycle.js.map +1 -0
- package/dist/solid/unstable/v2/drag-sensor.d.ts +23 -0
- package/dist/solid/unstable/v2/drag-sensor.d.ts.map +1 -0
- package/dist/solid/unstable/v2/drag-sensor.js +32 -0
- package/dist/solid/unstable/v2/drag-sensor.js.map +1 -0
- package/dist/solid/unstable/v2/element.d.ts +178 -0
- package/dist/solid/unstable/v2/element.d.ts.map +1 -0
- package/dist/solid/unstable/v2/element.jsx +325 -0
- package/dist/solid/unstable/v2/element.jsx.map +1 -0
- package/dist/solid/unstable/v2/feature-section.d.ts +12 -0
- package/dist/solid/unstable/v2/feature-section.d.ts.map +1 -0
- package/dist/solid/unstable/v2/feature-section.js +23 -0
- package/dist/solid/unstable/v2/feature-section.js.map +1 -0
- package/dist/solid/unstable/v2/focus-sensor.d.ts +13 -0
- package/dist/solid/unstable/v2/focus-sensor.d.ts.map +1 -0
- package/dist/solid/unstable/v2/focus-sensor.js +23 -0
- package/dist/solid/unstable/v2/focus-sensor.js.map +1 -0
- package/dist/solid/unstable/v2/hover-sensor.d.ts +12 -0
- package/dist/solid/unstable/v2/hover-sensor.d.ts.map +1 -0
- package/dist/solid/unstable/v2/hover-sensor.js +22 -0
- package/dist/solid/unstable/v2/hover-sensor.js.map +1 -0
- package/dist/solid/unstable/v2/index.d.ts +131 -0
- package/dist/solid/unstable/v2/index.d.ts.map +1 -0
- package/dist/solid/unstable/v2/index.js +114 -0
- package/dist/solid/unstable/v2/index.js.map +1 -0
- package/dist/solid/unstable/v2/layout-projection.d.ts +21 -0
- package/dist/solid/unstable/v2/layout-projection.d.ts.map +1 -0
- package/dist/solid/unstable/v2/layout-projection.js +18 -0
- package/dist/solid/unstable/v2/layout-projection.js.map +1 -0
- package/dist/solid/unstable/v2/layout.d.ts +47 -0
- package/dist/solid/unstable/v2/layout.d.ts.map +1 -0
- package/dist/solid/unstable/v2/layout.jsx +62 -0
- package/dist/solid/unstable/v2/layout.jsx.map +1 -0
- package/dist/solid/unstable/v2/lifecycle.d.ts +267 -0
- package/dist/solid/unstable/v2/lifecycle.d.ts.map +1 -0
- package/dist/solid/unstable/v2/lifecycle.js +457 -0
- package/dist/solid/unstable/v2/lifecycle.js.map +1 -0
- package/dist/solid/unstable/v2/live-value.d.ts +146 -0
- package/dist/solid/unstable/v2/live-value.d.ts.map +1 -0
- package/dist/solid/unstable/v2/live-value.js +235 -0
- package/dist/solid/unstable/v2/live-value.js.map +1 -0
- package/dist/solid/unstable/v2/presence-handle.d.ts +55 -0
- package/dist/solid/unstable/v2/presence-handle.d.ts.map +1 -0
- package/dist/solid/unstable/v2/presence-handle.js +119 -0
- package/dist/solid/unstable/v2/presence-handle.js.map +1 -0
- package/dist/solid/unstable/v2/presence-hooks.d.ts +51 -0
- package/dist/solid/unstable/v2/presence-hooks.d.ts.map +1 -0
- package/dist/solid/unstable/v2/presence-hooks.js +115 -0
- package/dist/solid/unstable/v2/presence-hooks.js.map +1 -0
- package/dist/solid/unstable/v2/presence.d.ts +89 -0
- package/dist/solid/unstable/v2/presence.d.ts.map +1 -0
- package/dist/solid/unstable/v2/presence.jsx +107 -0
- package/dist/solid/unstable/v2/presence.jsx.map +1 -0
- package/dist/solid/unstable/v2/press-sensor.d.ts +13 -0
- package/dist/solid/unstable/v2/press-sensor.d.ts.map +1 -0
- package/dist/solid/unstable/v2/press-sensor.js +23 -0
- package/dist/solid/unstable/v2/press-sensor.js.map +1 -0
- package/dist/solid/unstable/v2/provider.d.ts +239 -0
- package/dist/solid/unstable/v2/provider.d.ts.map +1 -0
- package/dist/solid/unstable/v2/provider.jsx +423 -0
- package/dist/solid/unstable/v2/provider.jsx.map +1 -0
- package/dist/solid/unstable/v2/reorder.d.ts +292 -0
- package/dist/solid/unstable/v2/reorder.d.ts.map +1 -0
- package/dist/solid/unstable/v2/reorder.jsx +525 -0
- package/dist/solid/unstable/v2/reorder.jsx.map +1 -0
- package/dist/solid/unstable/v2/sensors.d.ts +91 -0
- package/dist/solid/unstable/v2/sensors.d.ts.map +1 -0
- package/dist/solid/unstable/v2/sensors.js +124 -0
- package/dist/solid/unstable/v2/sensors.js.map +1 -0
- package/dist/solid/unstable/v2/solid-reactivity.d.ts +61 -0
- package/dist/solid/unstable/v2/solid-reactivity.d.ts.map +1 -0
- package/dist/solid/unstable/v2/solid-reactivity.js +62 -0
- package/dist/solid/unstable/v2/solid-reactivity.js.map +1 -0
- package/dist/solid/unstable/v2/variant-node.d.ts +51 -0
- package/dist/solid/unstable/v2/variant-node.d.ts.map +1 -0
- package/dist/solid/unstable/v2/variant-node.js +336 -0
- package/dist/solid/unstable/v2/variant-node.js.map +1 -0
- package/dist/solid/unstable/v2/w.d.ts +42 -0
- package/dist/solid/unstable/v2/w.d.ts.map +1 -0
- package/dist/solid/unstable/v2/w.jsx +22 -0
- package/dist/solid/unstable/v2/w.jsx.map +1 -0
- package/dist/solid/unstable/v2/waiters.d.ts +72 -0
- package/dist/solid/unstable/v2/waiters.d.ts.map +1 -0
- package/dist/solid/unstable/v2/waiters.js +175 -0
- package/dist/solid/unstable/v2/waiters.js.map +1 -0
- package/dist/solid/unstable/v2/ward.d.ts +393 -0
- package/dist/solid/unstable/v2/ward.d.ts.map +1 -0
- package/dist/solid/unstable/v2/ward.jsx +1475 -0
- package/dist/solid/unstable/v2/ward.jsx.map +1 -0
- package/dist/solid/unstable/v2/wardic-config.d.ts +68 -0
- package/dist/solid/unstable/v2/wardic-config.d.ts.map +1 -0
- package/dist/solid/unstable/v2/wardic-config.jsx +28 -0
- package/dist/solid/unstable/v2/wardic-config.jsx.map +1 -0
- package/dist/solid/unstable/v2/wardic.d.ts +28 -0
- package/dist/solid/unstable/v2/wardic.d.ts.map +1 -0
- package/dist/solid/unstable/v2/wardic.jsx +16 -0
- package/dist/solid/unstable/v2/wardic.jsx.map +1 -0
- package/dist/solid/variant-node.d.ts +32 -0
- package/dist/solid/variant-node.d.ts.map +1 -0
- package/dist/solid/variant-node.js +257 -0
- package/dist/solid/variant-node.js.map +1 -0
- package/dist/solid/variant-target.d.ts +102 -0
- package/dist/solid/variant-target.d.ts.map +1 -0
- package/dist/solid/variant-target.js +180 -0
- package/dist/solid/variant-target.js.map +1 -0
- package/dist/solid/variant-tree.d.ts +349 -0
- package/dist/solid/variant-tree.d.ts.map +1 -0
- package/dist/solid/variant-tree.js +358 -0
- package/dist/solid/variant-tree.js.map +1 -0
- package/dist/solid/variants.d.ts +21 -0
- package/dist/solid/variants.d.ts.map +1 -0
- package/dist/solid/variants.js +43 -0
- package/dist/solid/variants.js.map +1 -0
- package/dist/solid/w.d.ts +42 -0
- package/dist/solid/w.d.ts.map +1 -0
- package/dist/solid/w.jsx +23 -0
- package/dist/solid/w.jsx.map +1 -0
- package/dist/solid/ward-keys.d.ts +236 -0
- package/dist/solid/ward-keys.d.ts.map +1 -0
- package/dist/solid/ward-keys.js +2 -0
- package/dist/solid/ward-keys.js.map +1 -0
- package/dist/solid/wardic-component.d.ts +50 -0
- package/dist/solid/wardic-component.d.ts.map +1 -0
- package/dist/solid/wardic-component.js +74 -0
- package/dist/solid/wardic-component.js.map +1 -0
- package/dist/solid/wardic-config-value.d.ts +87 -0
- package/dist/solid/wardic-config-value.d.ts.map +1 -0
- package/dist/solid/wardic-config-value.js +106 -0
- package/dist/solid/wardic-config-value.js.map +1 -0
- package/dist/solid/wardic-config.d.ts +69 -0
- package/dist/solid/wardic-config.d.ts.map +1 -0
- package/dist/solid/wardic-config.jsx +30 -0
- package/dist/solid/wardic-config.jsx.map +1 -0
- package/dist/solid/wardic.d.ts +45 -0
- package/dist/solid/wardic.d.ts.map +1 -0
- package/dist/solid/wardic.jsx +31 -0
- package/dist/solid/wardic.jsx.map +1 -0
- package/package.json +98 -4
- package/src/animation-controls.ts +204 -0
- package/src/animation-frame.ts +32 -0
- package/src/appear.ts +804 -0
- package/src/arc.ts +34 -0
- package/src/bridge.ts +98 -0
- package/src/complete.ts +45 -0
- package/src/config.ts +805 -0
- package/src/create-animate.ts +41 -0
- package/src/create-ward.tsx +1271 -0
- package/src/cycle-index.ts +18 -0
- package/src/cycle.ts +34 -0
- package/src/directive.ts +87 -0
- package/src/drag-constraints.ts +103 -0
- package/src/drag-controls.ts +94 -0
- package/src/drag-samples.ts +54 -0
- package/src/drag-sensor.ts +46 -0
- package/src/drag-track.ts +937 -0
- package/src/drag-transition.ts +43 -0
- package/src/drag.ts +58 -0
- package/src/element-style.ts +112 -0
- package/src/element.tsx +400 -0
- package/src/feature-section.ts +33 -0
- package/src/feature.ts +342 -0
- package/src/features/all.ts +18 -0
- package/src/features/colors.ts +36 -0
- package/src/features/dom-animation.ts +15 -0
- package/src/features/dom-max.ts +11 -0
- package/src/features/drag.ts +30 -0
- package/src/features/focus.ts +17 -0
- package/src/features/hover.ts +17 -0
- package/src/features/in-view.ts +17 -0
- package/src/features/input.ts +42 -0
- package/src/features/keys.ts +89 -0
- package/src/features/layout.ts +54 -0
- package/src/features/pan.ts +17 -0
- package/src/features/press.ts +17 -0
- package/src/focus-sensor.ts +32 -0
- package/src/frame-time.ts +45 -0
- package/src/gesture-callbacks.ts +212 -0
- package/src/gesture-features.ts +35 -0
- package/src/gesture-info.ts +81 -0
- package/src/hover-sensor.ts +32 -0
- package/src/imperative.ts +782 -0
- package/src/index.ts +334 -0
- package/src/instant.ts +90 -0
- package/src/layout-group.ts +32 -0
- package/src/layout-member.ts +300 -0
- package/src/layout-projection.ts +28 -0
- package/src/layout.tsx +127 -0
- package/src/live-style.ts +449 -0
- package/src/live-value.ts +378 -0
- package/src/motion-props.ts +325 -0
- package/src/owner-scope.ts +31 -0
- package/src/page-point.ts +98 -0
- package/src/presence-controller.ts +1483 -0
- package/src/presence-record.ts +189 -0
- package/src/presence.tsx +269 -0
- package/src/press-sensor.ts +33 -0
- package/src/press.ts +40 -0
- package/src/provider.tsx +526 -0
- package/src/reactivity.ts +29 -0
- package/src/reorder-input.ts +53 -0
- package/src/reorder.tsx +703 -0
- package/src/retarget-legs.ts +1048 -0
- package/src/runtime.ts +388 -0
- package/src/sensors.ts +189 -0
- package/src/server-interpolators.ts +33 -0
- package/src/server.ts +21 -0
- package/src/solid-reactivity.ts +21 -0
- package/src/spine.ts +3385 -0
- package/src/stagger.ts +31 -0
- package/src/unstable/v2/bridge.ts +79 -0
- package/src/unstable/v2/complete.ts +47 -0
- package/src/unstable/v2/config-view.ts +156 -0
- package/src/unstable/v2/create-animate.ts +123 -0
- package/src/unstable/v2/cycle.ts +33 -0
- package/src/unstable/v2/drag-sensor.ts +44 -0
- package/src/unstable/v2/element.tsx +478 -0
- package/src/unstable/v2/feature-section.ts +32 -0
- package/src/unstable/v2/focus-sensor.ts +31 -0
- package/src/unstable/v2/hover-sensor.ts +30 -0
- package/src/unstable/v2/index.ts +270 -0
- package/src/unstable/v2/layout-projection.ts +27 -0
- package/src/unstable/v2/layout.tsx +89 -0
- package/src/unstable/v2/lifecycle.ts +612 -0
- package/src/unstable/v2/live-value.ts +414 -0
- package/src/unstable/v2/presence-handle.ts +159 -0
- package/src/unstable/v2/presence-hooks.ts +157 -0
- package/src/unstable/v2/presence.tsx +174 -0
- package/src/unstable/v2/press-sensor.ts +31 -0
- package/src/unstable/v2/provider.tsx +524 -0
- package/src/unstable/v2/reorder.tsx +880 -0
- package/src/unstable/v2/sensors.ts +169 -0
- package/src/unstable/v2/solid-reactivity.ts +69 -0
- package/src/unstable/v2/variant-node.ts +446 -0
- package/src/unstable/v2/w.tsx +49 -0
- package/src/unstable/v2/waiters.ts +212 -0
- package/src/unstable/v2/ward.tsx +2068 -0
- package/src/unstable/v2/wardic-config.tsx +84 -0
- package/src/unstable/v2/wardic.tsx +41 -0
- package/src/variant-node.ts +368 -0
- package/src/variant-target.ts +234 -0
- package/src/variant-tree.ts +638 -0
- package/src/variants.ts +47 -0
- package/src/w.tsx +59 -0
- package/src/ward-keys.ts +343 -0
- package/src/wardic-component.ts +96 -0
- package/src/wardic-config-value.ts +150 -0
- package/src/wardic-config.tsx +78 -0
- package/src/wardic.tsx +59 -0
|
@@ -0,0 +1,2939 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The motion spine's Retarget (ADR-0005), Solid-free (#209): what an element does from its mount on
|
|
3
|
+
* when its target changes, for the Solid 1 binding (`create-ward.tsx`'s `runSpine`) and the Solid 2
|
|
4
|
+
* one (`unstable/v2/ward.tsx`) alike. A binding mounts the element, resolves its Override stack
|
|
5
|
+
* reactively ({@link resolutionOf}), and calls {@link ElementSpine.retarget} on each change, read
|
|
6
|
+
* where its Solid doesn't track; everything a Retarget does is here:
|
|
7
|
+
*
|
|
8
|
+
* end the running legs -> carry the keys no entry sets back to their Base values (ADR-0022) ->
|
|
9
|
+
* start each key from its Snapshot (ADR-0024) -> take over an Appear animation (ADR-0044) ->
|
|
10
|
+
* build the legs (`retarget-legs.ts`) and run each into the gate -> `gate.write`.
|
|
11
|
+
*
|
|
12
|
+
* With it, the helpers both bindings' Wards share: the Starting values, the Base values' start links,
|
|
13
|
+
* the sink wrappers, and what a server render reads.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import * as BaseValue from "@wardic/core/BaseValue";
|
|
18
|
+
import * as InterpolatorRegistry from "@wardic/core/InterpolatorRegistry";
|
|
19
|
+
import * as Machine from "@wardic/core/Machine";
|
|
20
|
+
import * as Override from "@wardic/core/Override";
|
|
21
|
+
import * as Playback from "@wardic/core/Playback";
|
|
22
|
+
import * as Projection from "@wardic/core/Projection";
|
|
23
|
+
import * as Supersede from "@wardic/core/Supersede";
|
|
24
|
+
import * as Values from "@wardic/core/Values";
|
|
25
|
+
import * as Appear from "@wardic/dom/Appear";
|
|
26
|
+
import * as DomRenderer from "@wardic/dom/DomRenderer";
|
|
27
|
+
import * as OwnValues from "@wardic/dom/OwnValues";
|
|
28
|
+
import * as Report from "@wardic/dom/Report";
|
|
29
|
+
import * as MeasuredPair from "@wardic/dom/MeasuredPair";
|
|
30
|
+
import * as Style from "@wardic/dom/Style";
|
|
31
|
+
import * as Variables from "@wardic/dom/Variables";
|
|
32
|
+
import * as Arr from "effect/Array";
|
|
33
|
+
import * as Bool from "effect/Boolean";
|
|
34
|
+
import * as Cause from "effect/Cause";
|
|
35
|
+
import * as Effect from "effect/Effect";
|
|
36
|
+
import * as Equivalence from "effect/Equivalence";
|
|
37
|
+
import * as Exit from "effect/Exit";
|
|
38
|
+
import * as Fiber from "effect/Fiber";
|
|
39
|
+
import { constFalse, constUndefined, constVoid, identity } from "effect/Function";
|
|
40
|
+
import * as Iter from "effect/Iterable";
|
|
41
|
+
import * as Match from "effect/Match";
|
|
42
|
+
import * as Option from "effect/Option";
|
|
43
|
+
import * as Predicate from "effect/Predicate";
|
|
44
|
+
import * as Rec from "effect/Record";
|
|
45
|
+
import { AtomRegistry } from "effect/reactivity";
|
|
46
|
+
import * as UndefinedOr from "effect/UndefinedOr";
|
|
47
|
+
import { enterServer, keyOf, repeatsForever, skippedField, startAtOf } from "./appear.js";
|
|
48
|
+
import { join, leave } from "./animation-controls.js";
|
|
49
|
+
import { clockNowOf, frameNow, MAX_VELOCITY_DELTA, NOMINAL_FRAME } from "./frame-time.js";
|
|
50
|
+
import { serverRegistryOf, turnsWillChangeOn, valuesOf } from "./live-style.js";
|
|
51
|
+
import { presenceMade } from "./presence-record.js";
|
|
52
|
+
import { delayedBy, hasManyStops, keyframesFrom, legsOf, mapMachine, startingAt, transitionForKey, withPathAxes } from "./retarget-legs.js";
|
|
53
|
+
import { changesContext, hasOwnVariants, GESTURE_LAYERS, activeNamesOf, gesturesOn, handDownFrom, handDownOf, NO_GESTURE_STATES, NO_HAND_DOWN, isVariantChild, nameOf, NO_GESTURE_NAMES, ownOrInherited, sameGestureNames, startingValuesOf, startsAtAnimate, startsQuiet } from "./variant-tree.js";
|
|
54
|
+
import { mergedOf, NO_VARIANT_STATE, resolveTarget, resolveTargets, sameLabels, transitionOfTarget } from "./variant-target.js";
|
|
55
|
+
export { NO_VARIANT_STATE, resolveTarget, transitionOfTarget } from "./variant-target.js";
|
|
56
|
+
/** No exit: an element outside a presence never resolves one. */
|
|
57
|
+
export const NO_EXIT_CONFIG = {
|
|
58
|
+
exit: undefined,
|
|
59
|
+
variants: undefined,
|
|
60
|
+
custom: undefined,
|
|
61
|
+
transition: undefined
|
|
62
|
+
};
|
|
63
|
+
/** A record's place in the variant tree (#290), from its config at setup. */
|
|
64
|
+
export const presenceTreeOf = c => ({
|
|
65
|
+
joins: isVariantChild(c),
|
|
66
|
+
provides: changesContext(c),
|
|
67
|
+
twin: Predicate.isNotUndefined(c.layoutId)
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* An element's ref that tells its presence it was made (#286, ADR-0048): its `key`, read once, and
|
|
71
|
+
* whether it's a twin. With no presence, `set` itself: nothing is made per element.
|
|
72
|
+
*/
|
|
73
|
+
export const madeWith = (presence, set, c) => {
|
|
74
|
+
if (Predicate.isUndefined(presence)) return set;
|
|
75
|
+
const key = c.key;
|
|
76
|
+
const twin = Predicate.isNotUndefined(c.layoutId);
|
|
77
|
+
return el => {
|
|
78
|
+
presenceMade(presence, el, key, twin);
|
|
79
|
+
set(el);
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
/** An element's {@link ExitConfig} from its config now. */
|
|
83
|
+
export const exitConfigOf = (c, parent) => ({
|
|
84
|
+
exit: c.exit,
|
|
85
|
+
variants: c.variants,
|
|
86
|
+
custom: c.custom,
|
|
87
|
+
transition: ownOrInherited(c.transition, parent)
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* Resolve an element's exit as it leaves (#277): with its `<AnimatePresence custom>` when that's
|
|
91
|
+
* given (Motion's: the leaving element's own props can't change any more), else its own `custom`; on
|
|
92
|
+
* its own transition, else the element's.
|
|
93
|
+
*/
|
|
94
|
+
export const exitTargetOf = (config, presenceCustom, state, inherited) => {
|
|
95
|
+
const custom = UndefinedOr.match(presenceCustom, {
|
|
96
|
+
onUndefined: () => config.custom,
|
|
97
|
+
onDefined: identity
|
|
98
|
+
});
|
|
99
|
+
// Its own `exit` wins; a Variant child with none exits on the name its provider hands down (#290).
|
|
100
|
+
const entry = UndefinedOr.match(config.exit, {
|
|
101
|
+
onDefined: identity,
|
|
102
|
+
onUndefined: () => inherited
|
|
103
|
+
});
|
|
104
|
+
const name = UndefinedOr.match(nameOf(config.exit), {
|
|
105
|
+
onDefined: identity,
|
|
106
|
+
onUndefined: () => inherited
|
|
107
|
+
});
|
|
108
|
+
if (Arr.isArray(entry)) {
|
|
109
|
+
// A list (#297): merged, and each name's own keys on its own transition.
|
|
110
|
+
const targets = resolveTargets(entry, config.variants, custom, state);
|
|
111
|
+
const merged = mergedOf(targets);
|
|
112
|
+
return {
|
|
113
|
+
values: merged.values,
|
|
114
|
+
transition: transitionOfTarget(merged.transition, config.transition),
|
|
115
|
+
name,
|
|
116
|
+
groups: exitGroupsOf(targets, config.transition),
|
|
117
|
+
keyframes: merged.keyframes
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const target = resolveTarget(entry, config.variants, custom, state);
|
|
121
|
+
return {
|
|
122
|
+
values: target.values,
|
|
123
|
+
transition: transitionOfTarget(target.transition, config.transition),
|
|
124
|
+
name,
|
|
125
|
+
keyframes: target.keyframes
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
/** A list's exit groups (#297): each name, with the keys it's the last to set, on its own transition else `element`. */
|
|
129
|
+
const exitGroupsOf = (targets, element) => Arr.map(targets, (target, i) => ({
|
|
130
|
+
name: target.name,
|
|
131
|
+
values: Rec.filter(target.values, (_, key) => Bool.not(Arr.some(Arr.drop(targets, i + 1), later => Object.hasOwn(later.values, key)))),
|
|
132
|
+
transition: transitionOfTarget(target.transition, element)
|
|
133
|
+
}));
|
|
134
|
+
/** A config given as a value or as an accessor, as an accessor. A config is always an object, so a function is the accessor. */
|
|
135
|
+
export const accessorOf = config => Bool.match(Predicate.isFunction(config), {
|
|
136
|
+
onTrue: () => config,
|
|
137
|
+
onFalse: () => () => config
|
|
138
|
+
});
|
|
139
|
+
/**
|
|
140
|
+
* `transition` with a stagger delay folded into its own and its entries' (ADR-0007, #301), reused
|
|
141
|
+
* while its fields are (#66).
|
|
142
|
+
*/
|
|
143
|
+
const staggeredOf = (transition, extra, reuse) => UndefinedOr.map(delayedBy(transition, extra), reuse);
|
|
144
|
+
/**
|
|
145
|
+
* A Retarget's keys by the entry that drives each (#291), when an active entry (the base's included)
|
|
146
|
+
* has its own transition: the highest active entry that sets it, and the base for a key none sets (a
|
|
147
|
+
* return). `undefined` when none has: one transition for every key.
|
|
148
|
+
*/
|
|
149
|
+
const keysByLayerOf = (t, layers, extraDelay, extra, listed, shut) => {
|
|
150
|
+
// Per Retarget (#460): statements.
|
|
151
|
+
if (!Arr.some(layers, hasOwnTransition) && !delaysDiffer(layers, extraDelay, extra) && !anyShutOf(shut)) return undefined;
|
|
152
|
+
// A list's returns in a group of their own, after its entries' (#297).
|
|
153
|
+
let returnsAt = 0;
|
|
154
|
+
if (listed) returnsAt = layers.length;
|
|
155
|
+
const groups = Arr.makeBy(Math.max(layers.length, returnsAt + 1), () => new Set());
|
|
156
|
+
Arr.forEach(Rec.keys(t), key => {
|
|
157
|
+
// A key only a Transition end sets (#428) is in its entry's group too, as the entry's own.
|
|
158
|
+
const at = Option.getOrElse(Arr.findLastIndex(layers, layer => Bool.and(layer.active, Bool.or(Object.hasOwn(layer.values, key), Object.hasOwn(layer.ends, key)))), () => returnsAt);
|
|
159
|
+
UndefinedOr.map(groups[at], group => group.add(key));
|
|
160
|
+
});
|
|
161
|
+
return groups;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* The transition `key` animates on in a Retarget: its group's (#277, #297), else the Retarget's one,
|
|
165
|
+
* with no stagger (#448 reads its fields, not its delay).
|
|
166
|
+
*/
|
|
167
|
+
const keyTransitionOf = (resolution, groups, key, transition, element) => {
|
|
168
|
+
if (Predicate.isUndefined(groups)) return transition;
|
|
169
|
+
return groupTransitionOf(resolution, groups, Option.getOrElse(Arr.findFirstIndex(groups, group => group.has(key)), () => -1), transition, element, undefined, identity);
|
|
170
|
+
};
|
|
171
|
+
/** Whether `given` gives `key` a velocity (#448, Motion's `valueTransition.velocity`): it kicks the key, so it animates though at its target. */
|
|
172
|
+
const givesVelocity = (given, key) => {
|
|
173
|
+
const own = transitionForKey(given, key);
|
|
174
|
+
if (Predicate.isUndefined(own)) return false;
|
|
175
|
+
return Bool.and(Predicate.isNumber(own.velocity), own.velocity !== 0);
|
|
176
|
+
};
|
|
177
|
+
/** A key's velocity in the Snapshot, 0 with none (#448). Per key, per Retarget: a guard. */
|
|
178
|
+
const velocityOf = (snapshot, key) => {
|
|
179
|
+
const velocity = snapshot.velocities[key];
|
|
180
|
+
if (Predicate.isUndefined(velocity)) return 0;
|
|
181
|
+
return velocity;
|
|
182
|
+
};
|
|
183
|
+
/** `t`'s keys in the `i`th group, or all of them when there are no groups. */
|
|
184
|
+
const pickKeys = (t, groups, i) => {
|
|
185
|
+
if (Predicate.isUndefined(groups)) return t;
|
|
186
|
+
const group = groups[i];
|
|
187
|
+
if (Predicate.isUndefined(group)) return {};
|
|
188
|
+
return Rec.filter(t, (_, key) => group.has(key));
|
|
189
|
+
};
|
|
190
|
+
/** A transition's `delay`, 0 without one. */
|
|
191
|
+
export const delayOf = transition => UndefinedOr.match(transition, {
|
|
192
|
+
onUndefined: () => 0,
|
|
193
|
+
onDefined: ({
|
|
194
|
+
delay = 0
|
|
195
|
+
}) => delay
|
|
196
|
+
});
|
|
197
|
+
/** No keys: what a drag moves on a projected element, or one with no drag. */
|
|
198
|
+
const NO_KEYS = [];
|
|
199
|
+
/** The keys a drag of `axis` moves directly. Built once, at module load. */
|
|
200
|
+
const dragMovesOf = Match.type().pipe(Match.when("x", () => ["x"]), Match.when("y", () => ["y"]), Match.orElse(() => ["x", "y"]));
|
|
201
|
+
/** Whether a start link's value takes its target's shape: both numbers, or both strings. */
|
|
202
|
+
const isSameKind = (value, like) => Predicate.isNumber(value) === Predicate.isNumber(like);
|
|
203
|
+
/** The keys a drag direct-sets (ADR-0004). */
|
|
204
|
+
const TRANSLATE_KEYS = new Set(["x", "y", "translateX", "translateY"]);
|
|
205
|
+
const TRANSLATE_KEY_LIST = Arr.fromIterable(TRANSLATE_KEYS);
|
|
206
|
+
/** Whether a value map has any key. */
|
|
207
|
+
const hasKeys = Predicate.not(Rec.isEmptyRecord);
|
|
208
|
+
/**
|
|
209
|
+
* Whether two transitions have the same keys, each holding the same value (`===`), an entry the
|
|
210
|
+
* same fields (#301: a stagger makes each entry anew).
|
|
211
|
+
*/
|
|
212
|
+
const sameFields = (a, b) => {
|
|
213
|
+
const ra = a;
|
|
214
|
+
const rb = b;
|
|
215
|
+
const keys = Rec.keys(ra);
|
|
216
|
+
return Bool.and(keys.length === Rec.keys(rb).length, Arr.every(keys, key => Bool.and(key in rb, sameField(ra[key], rb[key]))));
|
|
217
|
+
};
|
|
218
|
+
/** Whether two fields are the same: `===`, or two entries with the same fields (#301). */
|
|
219
|
+
const sameField = (a, b) => {
|
|
220
|
+
if (a === b) return true;
|
|
221
|
+
if (Bool.and(Predicate.isObject(a), Predicate.isObject(b))) return sameFields(a, b);
|
|
222
|
+
return false;
|
|
223
|
+
};
|
|
224
|
+
/** A gesture layer that's off: nothing is resolved for it. */
|
|
225
|
+
const OFF = {
|
|
226
|
+
active: false,
|
|
227
|
+
values: {},
|
|
228
|
+
transition: undefined,
|
|
229
|
+
name: undefined,
|
|
230
|
+
ends: {},
|
|
231
|
+
keyframes: undefined
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* A gesture layer (#291), while it's on (its own, or its provider's): its own `while*` (a target, or
|
|
235
|
+
* a variant name), else the label its provider hands down. Off, or with neither, nothing is resolved.
|
|
236
|
+
* Whether it set values or a Transition end (#470).
|
|
237
|
+
*/
|
|
238
|
+
const gestureLayersInto = (layers, own, on, label, variants, custom, state) => {
|
|
239
|
+
if (Bool.not(on)) {
|
|
240
|
+
layers.push(OFF);
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
const entry = UndefinedOr.match(own, {
|
|
244
|
+
onDefined: identity,
|
|
245
|
+
onUndefined: () => label
|
|
246
|
+
});
|
|
247
|
+
if (Predicate.isUndefined(entry)) {
|
|
248
|
+
layers.push(OFF);
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
// A list is an entry a name, in order (#297): the last name that sets a key drives it.
|
|
252
|
+
if (Arr.isArray(entry)) {
|
|
253
|
+
let sets = false;
|
|
254
|
+
Arr.forEach(resolveTargets(entry, variants, custom, state), target => {
|
|
255
|
+
const layer = namedLayerOf(target);
|
|
256
|
+
layers.push(layer);
|
|
257
|
+
if (setsValues(layer)) sets = true;
|
|
258
|
+
});
|
|
259
|
+
return sets;
|
|
260
|
+
}
|
|
261
|
+
const layer = layerOf(resolveTarget(entry, variants, custom, state), labelOrUndefined(entry));
|
|
262
|
+
layers.push(layer);
|
|
263
|
+
return setsValues(layer);
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* Whether a gesture layer sets values or a Transition end (#470). A values map with none sets
|
|
267
|
+
* nothing; a name that resolves none is told by its name (`names`), as Motion animates it.
|
|
268
|
+
*/
|
|
269
|
+
const setsValues = layer => {
|
|
270
|
+
if (hasKeys(layer.values)) return true;
|
|
271
|
+
return hasKeys(layer.ends);
|
|
272
|
+
};
|
|
273
|
+
/** A single entry's name: itself, if a name; `undefined` for a values map. */
|
|
274
|
+
const labelOrUndefined = entry => Bool.match(Predicate.isString(entry), {
|
|
275
|
+
onTrue: () => entry,
|
|
276
|
+
onFalse: constUndefined
|
|
277
|
+
});
|
|
278
|
+
/** Each gesture on: the element's own, or its provider's too when it has one handing any down. */
|
|
279
|
+
const gesturesOnOf = (active, above) => {
|
|
280
|
+
if (above === NO_HAND_DOWN) return active;
|
|
281
|
+
return gesturesOn(active, above.on);
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* The name each gesture layer resolves while it's on (#291): its own `while*`, if a name, else the
|
|
285
|
+
* label it took. With none on, the shared empty one: nothing made.
|
|
286
|
+
*/
|
|
287
|
+
const activeNamesFor = (c, on, labels) => {
|
|
288
|
+
if (Bool.not(anyOn(on))) return NO_GESTURE_NAMES;
|
|
289
|
+
return activeNamesOf(handDownOf(c, on, {
|
|
290
|
+
on: NO_GESTURE_STATES,
|
|
291
|
+
names: labels
|
|
292
|
+
}));
|
|
293
|
+
};
|
|
294
|
+
/** Whether any gesture is on: per Retarget, so no closure. */
|
|
295
|
+
const anyOn = on => on.inView || on.focused || on.hovered || on.pressed || on.dragged;
|
|
296
|
+
/**
|
|
297
|
+
* Whether an active entry's name delays its keys otherwise than the first entry's (#297): a Variant
|
|
298
|
+
* child's names each take their own stagger slot. Never for an element that joins none, nor for one
|
|
299
|
+
* entry.
|
|
300
|
+
*/
|
|
301
|
+
const delaysDiffer = (layers, extraDelay, extra) => {
|
|
302
|
+
if (Bool.or(Predicate.isUndefined(extraDelay), layers.length < 2)) return false;
|
|
303
|
+
return Arr.some(layers, layer => Bool.and(layer.active, extraOf(extraDelay, layer) !== extra));
|
|
304
|
+
};
|
|
305
|
+
/** An entry's stagger delay (ADR-0007, #297): its name's, for a Variant child; 0 for any other element. */
|
|
306
|
+
const extraOf = (extraDelay, layer) => {
|
|
307
|
+
if (Predicate.isUndefined(extraDelay)) return 0;
|
|
308
|
+
if (Predicate.isUndefined(layer)) return extraDelay(undefined);
|
|
309
|
+
return extraDelay(layer.name);
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* The transition a key group runs on (#291, #297): unsplit, the base's (`transition`, its delay
|
|
313
|
+
* folded in); split, its entry's own, else the element's, at its name's delay. A list's first
|
|
314
|
+
* group carries its returns too, which run on the element's transition, as a list's base has no one
|
|
315
|
+
* transition of its own.
|
|
316
|
+
*/
|
|
317
|
+
const groupTransitionOf = (resolution, groups, i, transition, element, extraDelay, reuse) => {
|
|
318
|
+
if (Predicate.isUndefined(groups)) return transition;
|
|
319
|
+
if (Bool.and(i === 0, Bool.not(Arr.isArray(resolution.variant)))) return transition;
|
|
320
|
+
const layer = resolution.layers[i];
|
|
321
|
+
// A list's returns: the element's, at its whole orchestration's delay.
|
|
322
|
+
if (Predicate.isUndefined(layer)) return staggeredOf(element, extraOf(extraDelay, undefined), reuse);
|
|
323
|
+
return staggeredOf(transitionOfTarget(layer.transition, element), extraOf(extraDelay, layer), reuse);
|
|
324
|
+
};
|
|
325
|
+
/** No names. */
|
|
326
|
+
const NO_NAMES = [];
|
|
327
|
+
/** No legs. */
|
|
328
|
+
const NO_LEGS = [];
|
|
329
|
+
/**
|
|
330
|
+
* A gated Retarget's landing (ADR-0007 `when`, #325): the legs it carries report the element
|
|
331
|
+
* unsettled, as it still owes an animation, and land nothing; the Retarget once the gate opens
|
|
332
|
+
* counts them.
|
|
333
|
+
*/
|
|
334
|
+
const gatedLandingOf = onFrame => ({
|
|
335
|
+
report: () => {
|
|
336
|
+
if (Predicate.isNotUndefined(onFrame)) onFrame(false);
|
|
337
|
+
},
|
|
338
|
+
settled: constVoid,
|
|
339
|
+
failed: constVoid
|
|
340
|
+
});
|
|
341
|
+
/** No running legs. */
|
|
342
|
+
const NO_RUNNING = [];
|
|
343
|
+
/**
|
|
344
|
+
* The waiting Transition ends of element `id` (#508): made at its first end, so an element with none,
|
|
345
|
+
* nearly every one, pays nothing for them. `owners` holds the leg drawing each key.
|
|
346
|
+
*/
|
|
347
|
+
const waitingEndsOf = (owners, snapshot, gate, id, recordFrame) => {
|
|
348
|
+
const pending = [];
|
|
349
|
+
let disposed = false;
|
|
350
|
+
/** Whether `key`'s leg has landed: it drew its last frame, or none draws it. */
|
|
351
|
+
const keyLanded = key => ownerLanded(owners.get(key));
|
|
352
|
+
/** `end` off the list. */
|
|
353
|
+
const remove = end => {
|
|
354
|
+
const at = pending.indexOf(end);
|
|
355
|
+
if (at >= 0) pending.splice(at, 1);
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* An end written, at the flush after its keys landed: the frame its leg's write would have drawn in,
|
|
359
|
+
* and Motion's (`frame.update` once its animations resolve). It counts toward its landing as that leg
|
|
360
|
+
* did, so the landing's settle, told after the next flush, sees it (ADR-0057 Q4).
|
|
361
|
+
*/
|
|
362
|
+
const write = end => {
|
|
363
|
+
if (Bool.or(disposed, end.state !== "due")) return;
|
|
364
|
+
end.state = "written";
|
|
365
|
+
remove(end);
|
|
366
|
+
const running = end.running;
|
|
367
|
+
const value = running.values(end.writes);
|
|
368
|
+
snapshot.values = {
|
|
369
|
+
...snapshot.values,
|
|
370
|
+
...value
|
|
371
|
+
};
|
|
372
|
+
gate.write(id, value);
|
|
373
|
+
recordFrame(value);
|
|
374
|
+
drew(running, true, snapshot.now());
|
|
375
|
+
running.landing.settled();
|
|
376
|
+
const tell = running.names;
|
|
377
|
+
if (Predicate.isNotUndefined(tell)) tell(undefined);
|
|
378
|
+
};
|
|
379
|
+
/** Whether a key-less end's target was interrupted: a leg it waits for given up or replaced before it landed. */
|
|
380
|
+
const interrupted = end => {
|
|
381
|
+
const legs = end.legs;
|
|
382
|
+
if (Predicate.isUndefined(legs)) return false;
|
|
383
|
+
return Arr.some(end.animated, (key, i) => {
|
|
384
|
+
const leg = legs[i];
|
|
385
|
+
if (Predicate.isUndefined(leg)) return false;
|
|
386
|
+
if (leg.done) return false;
|
|
387
|
+
return owners.get(key) !== leg;
|
|
388
|
+
});
|
|
389
|
+
};
|
|
390
|
+
/** An end due once every key it waits for has landed, written at the next flush; dropped when its target was interrupted. */
|
|
391
|
+
const landOne = end => {
|
|
392
|
+
if (end.state !== "waiting") return;
|
|
393
|
+
if (interrupted(end)) {
|
|
394
|
+
end.state = "dropped";
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (Bool.not(Arr.every(end.animated, keyLanded))) return;
|
|
398
|
+
end.state = "due";
|
|
399
|
+
gate.afterFlush(() => write(end));
|
|
400
|
+
};
|
|
401
|
+
const dropped = end => end.state === "dropped";
|
|
402
|
+
const land = () => {
|
|
403
|
+
Arr.forEach(pending, landOne);
|
|
404
|
+
if (Arr.some(pending, dropped)) {
|
|
405
|
+
const kept = Arr.filter(pending, Predicate.not(dropped));
|
|
406
|
+
pending.length = 0;
|
|
407
|
+
pending.push(...kept);
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
return {
|
|
411
|
+
add: end => {
|
|
412
|
+
pending.push(end);
|
|
413
|
+
land();
|
|
414
|
+
},
|
|
415
|
+
land,
|
|
416
|
+
drop: running => Option.match(Arr.findFirst(pending, end => end.running === running), {
|
|
417
|
+
onNone: constVoid,
|
|
418
|
+
onSome: end => {
|
|
419
|
+
end.state = "dropped";
|
|
420
|
+
remove(end);
|
|
421
|
+
}
|
|
422
|
+
}),
|
|
423
|
+
dispose: () => {
|
|
424
|
+
disposed = true;
|
|
425
|
+
pending.length = 0;
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
/** A leg's last frame lands the Transition ends waiting on it (#508); an element with none has nothing to ask. */
|
|
430
|
+
const landEndsOf = waiting => {
|
|
431
|
+
if (Predicate.isNotUndefined(waiting)) waiting.land();
|
|
432
|
+
};
|
|
433
|
+
/**
|
|
434
|
+
* The resolution an **Imperative animation**'s legs run under (#433): none of the Override stack's,
|
|
435
|
+
* so a Retarget that takes a key back never carries one as its own Keyframes or names.
|
|
436
|
+
*/
|
|
437
|
+
const IMPERATIVE = {
|
|
438
|
+
resolved: {},
|
|
439
|
+
base: {},
|
|
440
|
+
dragging: false,
|
|
441
|
+
variant: undefined,
|
|
442
|
+
active: {
|
|
443
|
+
inView: false,
|
|
444
|
+
focused: false,
|
|
445
|
+
hovered: false,
|
|
446
|
+
pressed: false,
|
|
447
|
+
dragged: false,
|
|
448
|
+
dragging: false
|
|
449
|
+
},
|
|
450
|
+
transition: undefined,
|
|
451
|
+
layers: [],
|
|
452
|
+
names: NO_GESTURE_NAMES,
|
|
453
|
+
layersOn: NO_GESTURE_STATES,
|
|
454
|
+
ends: undefined,
|
|
455
|
+
keyframes: undefined,
|
|
456
|
+
change: undefined
|
|
457
|
+
};
|
|
458
|
+
/** No values: what a spine's Retarget keys are before its first. */
|
|
459
|
+
const NO_VALUES = {};
|
|
460
|
+
/** Whether a key's Keyframes stops hold a Variable value (#55). Built once (#460). */
|
|
461
|
+
const stopsHoldVariable = stops => Arr.some(stops, Variables.isValue);
|
|
462
|
+
/**
|
|
463
|
+
* Whether a change's starts, targets or Keyframes stops hold a Variable value (#542): only then can
|
|
464
|
+
* the element's Key rule, its Variable values (#55), take a pair, so only then is a leg's machine
|
|
465
|
+
* built under it. It declines every pair with no `var()` at either end.
|
|
466
|
+
*/
|
|
467
|
+
const holdsVariable = (from, to, stops) => {
|
|
468
|
+
// Per Retarget (#460): statements, Effect's calls data-first.
|
|
469
|
+
if (Rec.some(from, Variables.isValue)) return true;
|
|
470
|
+
if (Rec.some(to, Variables.isValue)) return true;
|
|
471
|
+
if (Predicate.isUndefined(stops)) return false;
|
|
472
|
+
return Rec.some(stops, stopsHoldVariable);
|
|
473
|
+
};
|
|
474
|
+
/** A Path's turn (#438, ADR-0065): the reserved key the dom transform adds onto `rotate`. */
|
|
475
|
+
const PATH_ROTATION = "pathRotation";
|
|
476
|
+
/** The turn back at 0, written once no leg draws it (#460). */
|
|
477
|
+
const TURNED_BACK = {
|
|
478
|
+
[PATH_ROTATION]: 0
|
|
479
|
+
};
|
|
480
|
+
/** A leg over the keys of `to` (#325), counting toward `landing`: the spine gives it the keys. */
|
|
481
|
+
const runningOf = (to, resolution, landing, kind) => ({
|
|
482
|
+
supersede: Supersede.make(),
|
|
483
|
+
targets: to,
|
|
484
|
+
resolution,
|
|
485
|
+
count: 0,
|
|
486
|
+
values: identity,
|
|
487
|
+
velocities: identity,
|
|
488
|
+
done: false,
|
|
489
|
+
losing: false,
|
|
490
|
+
fiber: undefined,
|
|
491
|
+
landing,
|
|
492
|
+
names: undefined,
|
|
493
|
+
kind,
|
|
494
|
+
frames: 0,
|
|
495
|
+
// Doubles from the start (#464): a field made an integer turns every leg's shape when its first double
|
|
496
|
+
// comes, and a read of each leg made before goes the slow way (the bench's unmount, +6%).
|
|
497
|
+
lastAt: Number.NEGATIVE_INFINITY,
|
|
498
|
+
last: undefined,
|
|
499
|
+
before: undefined,
|
|
500
|
+
beforeAt: Number.NEGATIVE_INFINITY
|
|
501
|
+
});
|
|
502
|
+
/**
|
|
503
|
+
* A Blend leg's velocity for `key` (#464, Motion's `getVelocity`): its last two frames' change over
|
|
504
|
+
* their time apart, at most `MAX_VELOCITY_DELTA`; none for a string, nor for a Snap, a leg that landed
|
|
505
|
+
* on its first frame (a `set`, a `duration: 0`).
|
|
506
|
+
*/
|
|
507
|
+
const blendVelocityOf = (running, key) => {
|
|
508
|
+
if (Bool.and(running.done, running.frames < 2)) return 0;
|
|
509
|
+
// Per key, per Retarget: guards, nothing made.
|
|
510
|
+
const lastValues = running.last;
|
|
511
|
+
const beforeValues = running.before;
|
|
512
|
+
if (Predicate.isUndefined(lastValues)) return 0;
|
|
513
|
+
if (Predicate.isUndefined(beforeValues)) return 0;
|
|
514
|
+
const last = lastValues[key];
|
|
515
|
+
const before = beforeValues[key];
|
|
516
|
+
if (Bool.not(Predicate.isNumber(last))) return 0;
|
|
517
|
+
if (Bool.not(Predicate.isNumber(before))) return 0;
|
|
518
|
+
const apart = Math.min(running.lastAt - running.beforeAt, MAX_VELOCITY_DELTA);
|
|
519
|
+
if (apart <= 0) return 0;
|
|
520
|
+
return (last - before) * 1000 / apart;
|
|
521
|
+
};
|
|
522
|
+
/** A leg's frame drawn (#325) at `now`: its last lands the keys it draws. Per frame: plain calls. */
|
|
523
|
+
const drew = (running, done, now) => {
|
|
524
|
+
if (done) running.done = true;
|
|
525
|
+
running.frames++;
|
|
526
|
+
running.lastAt = now;
|
|
527
|
+
running.landing.report(done);
|
|
528
|
+
};
|
|
529
|
+
/**
|
|
530
|
+
* A frame's values for `kept` alone (#325): a leg a later Retarget took keys from draws only the
|
|
531
|
+
* rest. Built once, when it gives them up; each frame copies into the one object it returns.
|
|
532
|
+
*/
|
|
533
|
+
const keepingOnly = kept => {
|
|
534
|
+
const out = {};
|
|
535
|
+
let frame = out;
|
|
536
|
+
const copy = key => {
|
|
537
|
+
out[key] = frame[key];
|
|
538
|
+
};
|
|
539
|
+
return value => {
|
|
540
|
+
frame = value;
|
|
541
|
+
Arr.forEach(kept, copy);
|
|
542
|
+
return out;
|
|
543
|
+
};
|
|
544
|
+
};
|
|
545
|
+
/**
|
|
546
|
+
* Where `axis` rests when `target` leaves it out (#574): a leg drawing it though its own Retarget
|
|
547
|
+
* didn't resolve it, a Path's whose target left it out too (#438) or an Imperative animation's (#433,
|
|
548
|
+
* whose legs resolve nothing), was taking it somewhere, and it rests there. `undefined` with none in
|
|
549
|
+
* flight.
|
|
550
|
+
*/
|
|
551
|
+
const restOf = (owners, target, axis) => {
|
|
552
|
+
if (Object.hasOwn(target, axis)) return undefined;
|
|
553
|
+
const owner = owners.get(axis);
|
|
554
|
+
if (Predicate.isUndefined(owner)) return undefined;
|
|
555
|
+
if (owner.done) return undefined;
|
|
556
|
+
if (Object.hasOwn(owner.resolution.resolved, axis)) return undefined;
|
|
557
|
+
return owner.targets[axis];
|
|
558
|
+
};
|
|
559
|
+
/**
|
|
560
|
+
* Where a Path's axes that `target` leaves out rest (#574), read before their legs give them up: a
|
|
561
|
+
* new Path ends them there, so a toss caught mid-air curves back to its line. `undefined` for none:
|
|
562
|
+
* every element's Retarget asks, nearly always with no Path in flight, so guards, nothing built.
|
|
563
|
+
*/
|
|
564
|
+
const restsOf = (owners, target) => {
|
|
565
|
+
const x = restOf(owners, target, "x");
|
|
566
|
+
const y = restOf(owners, target, "y");
|
|
567
|
+
if (Bool.and(Predicate.isUndefined(x), Predicate.isUndefined(y))) return undefined;
|
|
568
|
+
if (Predicate.isUndefined(x)) return {
|
|
569
|
+
y: UndefinedOr.getOrThrow(y)
|
|
570
|
+
};
|
|
571
|
+
if (Predicate.isUndefined(y)) return {
|
|
572
|
+
x
|
|
573
|
+
};
|
|
574
|
+
return {
|
|
575
|
+
x,
|
|
576
|
+
y
|
|
577
|
+
};
|
|
578
|
+
};
|
|
579
|
+
/** The groups of the keys a carried leg draws (#297, #325): the first alone when the keys aren't split. */
|
|
580
|
+
const groupsOfLeg = (running, groups, owners) => {
|
|
581
|
+
if (Predicate.isUndefined(groups)) return [0];
|
|
582
|
+
const keys = Arr.filter(Rec.keys(running.targets), key => owners.get(key) === running);
|
|
583
|
+
return Arr.filter(Arr.makeBy(groups.length, identity), g => Arr.some(keys, key => UndefinedOr.match(groups[g], {
|
|
584
|
+
onUndefined: constFalse,
|
|
585
|
+
onDefined: group => group.has(key)
|
|
586
|
+
})));
|
|
587
|
+
};
|
|
588
|
+
/** Each entry's gate shut now (#297's PR 2): a named one whose `when` holds its keys back. */
|
|
589
|
+
const shutOf = (layers, byName) => {
|
|
590
|
+
if (Predicate.isUndefined(byName)) return undefined;
|
|
591
|
+
return Arr.map(layers, layer => {
|
|
592
|
+
const name = layer.name;
|
|
593
|
+
if (Predicate.isUndefined(name)) return false;
|
|
594
|
+
return Bool.not(byName.mayStart(name));
|
|
595
|
+
});
|
|
596
|
+
};
|
|
597
|
+
/** Whether any entry's gate is shut (#297's PR 2): none without a list. */
|
|
598
|
+
const anyShutOf = shut => {
|
|
599
|
+
if (Predicate.isUndefined(shut)) return false;
|
|
600
|
+
return Arr.some(shut, identity);
|
|
601
|
+
};
|
|
602
|
+
/**
|
|
603
|
+
* A split Retarget's legs (#291, #297): each key group on its transition, over the keys that start a
|
|
604
|
+
* leg (`t`, #325). A group with none of them makes no leg: a list's settles at once as Motion's empty
|
|
605
|
+
* variant does, unless keys it drives stay running. A list's returns' Live values follow with its
|
|
606
|
+
* returns' group, last; any other's with the first group.
|
|
607
|
+
*/
|
|
608
|
+
const splitLegsOf = (t, from, groups, resolution, listed, transition, element, extraDelay, reuse, reduce, skipped, positionalKeys, defaultTransition, velocities, follow, stops, measured, current, rests) => {
|
|
609
|
+
let returnsAt = 0;
|
|
610
|
+
if (listed) returnsAt = resolution.layers.length;
|
|
611
|
+
const legs = [];
|
|
612
|
+
const tags = [];
|
|
613
|
+
Arr.forEach(groups, (_, i) => {
|
|
614
|
+
// A group whose keys all stay starts none (#325), as one that drives no key.
|
|
615
|
+
const picked = pickKeys(t, groups, i);
|
|
616
|
+
if (Rec.isEmptyRecord(picked)) return;
|
|
617
|
+
let followed;
|
|
618
|
+
if (i === returnsAt) followed = follow;
|
|
619
|
+
const groupLegs = legsOf(from, picked, groupTransitionOf(resolution, groups, i, transition, element, extraDelay, reuse), reduce, skipped, positionalKeys, defaultTransition, velocities, followed, stops, measured, current, rests);
|
|
620
|
+
Arr.forEach(groupLegs, built => {
|
|
621
|
+
legs.push(built);
|
|
622
|
+
tags.push(i);
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
return {
|
|
626
|
+
legs,
|
|
627
|
+
tags
|
|
628
|
+
};
|
|
629
|
+
};
|
|
630
|
+
/**
|
|
631
|
+
* A list's names at a Retarget (#297): told settled as the legs of the keys each drives settle, to
|
|
632
|
+
* the binding's callbacks (Solid 1's, PR 1) and to its orchestration (PR 2), told moving now; and each
|
|
633
|
+
* shut name's legs waiting on its gate (PR 2), its keys held where they start, so another name's first
|
|
634
|
+
* commit, which hands the element's style back (ADR-0034), doesn't drop them to their CSS value.
|
|
635
|
+
*/
|
|
636
|
+
const listingOf = of => {
|
|
637
|
+
const {
|
|
638
|
+
listed,
|
|
639
|
+
told,
|
|
640
|
+
byName,
|
|
641
|
+
resolution,
|
|
642
|
+
groups,
|
|
643
|
+
legGroups,
|
|
644
|
+
legCount,
|
|
645
|
+
carriedGroups,
|
|
646
|
+
shut,
|
|
647
|
+
config
|
|
648
|
+
} = of;
|
|
649
|
+
const listNames = Bool.match(listed, {
|
|
650
|
+
onTrue: () => resolution.variant,
|
|
651
|
+
onFalse: () => NO_NAMES
|
|
652
|
+
});
|
|
653
|
+
const orchestrated = Bool.and(listed, Predicate.isNotUndefined(byName));
|
|
654
|
+
const toldNames = UndefinedOr.match(told, {
|
|
655
|
+
onUndefined: () => NO_NAMES,
|
|
656
|
+
onDefined: list => list.names
|
|
657
|
+
});
|
|
658
|
+
let names;
|
|
659
|
+
if (Bool.or(orchestrated, Predicate.isNotUndefined(told))) {
|
|
660
|
+
if (orchestrated) byName.moving(listNames);
|
|
661
|
+
names = nameSettlesOf(Arr.dedupe([...listNames, ...toldNames]), resolution, groups, legGroups, legCount, carriedGroups, settled => of.afterFlush(() => {
|
|
662
|
+
UndefinedOr.map(told, list => {
|
|
663
|
+
const mine = Arr.filter(settled, name => Arr.contains(list.names, name));
|
|
664
|
+
if (mine.length > 0) list.tell(mine, config);
|
|
665
|
+
});
|
|
666
|
+
if (orchestrated) byName.settled(Arr.filter(settled, name => Arr.contains(listNames, name)));
|
|
667
|
+
}));
|
|
668
|
+
}
|
|
669
|
+
let legGates;
|
|
670
|
+
if (Bool.and(anyShutOf(shut), Predicate.isNotUndefined(legGroups))) {
|
|
671
|
+
const closed = shut;
|
|
672
|
+
legGates = Arr.map(legGroups, g => gateNameOf(resolution.layers, closed, g));
|
|
673
|
+
Arr.forEach(closed, (isShut, g) => {
|
|
674
|
+
if (isShut) of.hold(g);
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
return {
|
|
678
|
+
names,
|
|
679
|
+
legGates
|
|
680
|
+
};
|
|
681
|
+
};
|
|
682
|
+
/** The name a leg of key group `g` waits for, if its entry's gate is shut (#297's PR 2): a list's returns wait for none. */
|
|
683
|
+
const gateNameOf = (layers, shut, g) => {
|
|
684
|
+
if (shut[g] !== true) return undefined;
|
|
685
|
+
return UndefinedOr.match(layers[g], {
|
|
686
|
+
onUndefined: constUndefined,
|
|
687
|
+
onDefined: layer => layer.name
|
|
688
|
+
});
|
|
689
|
+
};
|
|
690
|
+
/** A gate's wait (#297's PR 2): done once `open()` says so, read each tick. */
|
|
691
|
+
const gateWaitOf = open => Machine.make({
|
|
692
|
+
settles: true,
|
|
693
|
+
span: GATE_SPAN,
|
|
694
|
+
start: () => () => ({
|
|
695
|
+
value: undefined,
|
|
696
|
+
done: open()
|
|
697
|
+
})
|
|
698
|
+
});
|
|
699
|
+
const GATE_SPAN = {
|
|
700
|
+
name: "wardic.spine.whenGate",
|
|
701
|
+
attributes: {}
|
|
702
|
+
};
|
|
703
|
+
/** Nothing drawn while a gate is waited on. */
|
|
704
|
+
const NO_SINK = () => undefined;
|
|
705
|
+
/** Whether a key's leg has landed (#428): its owner's done, or it has none. A guard: asked at each leg's landing while a Transition end waits (#508). */
|
|
706
|
+
const ownerLanded = owner => {
|
|
707
|
+
if (Predicate.isUndefined(owner)) return true;
|
|
708
|
+
return owner.done;
|
|
709
|
+
};
|
|
710
|
+
/** Whether `runtime` keeps a Debug log: read once a runtime, so a log no level keeps forks nothing (#618). */
|
|
711
|
+
// Module state (#460, Q7): each runtime's answer, held weakly by the runtime.
|
|
712
|
+
const logsDebug = new WeakMap();
|
|
713
|
+
const logsDebugOn = runtime => {
|
|
714
|
+
const known = logsDebug.get(runtime);
|
|
715
|
+
if (Predicate.isNotUndefined(known)) return known;
|
|
716
|
+
const on = runtime.runSync(Report.debugKept);
|
|
717
|
+
logsDebug.set(runtime, on);
|
|
718
|
+
return on;
|
|
719
|
+
};
|
|
720
|
+
/**
|
|
721
|
+
* No key taken by an Imperative animation (#433): every spine's until its first, shared, so an element
|
|
722
|
+
* none animates holds no map of its own (#460). Never written: a spine sets keys in a map of its own,
|
|
723
|
+
* and deletes only from one that has some.
|
|
724
|
+
*/
|
|
725
|
+
// Module state (#460, Q7): a constant: an empty map every spine shares until its first, which none writes.
|
|
726
|
+
const NONE_TAKEN = new Map();
|
|
727
|
+
/**
|
|
728
|
+
* A leg that waits for its name's gate first (#297's PR 2), as Motion runs a variant's `when` per
|
|
729
|
+
* name: started once the gate opens, on the same token, so a later Retarget ends the wait as it ends
|
|
730
|
+
* a leg. Without a name, the leg as it is.
|
|
731
|
+
*/
|
|
732
|
+
const gatedBy = (name, byName, options, program) => {
|
|
733
|
+
if (Bool.or(Predicate.isUndefined(name), Predicate.isUndefined(byName))) return program;
|
|
734
|
+
const orchestration = byName;
|
|
735
|
+
const gated = name;
|
|
736
|
+
return gateWaitOf(() => orchestration.mayStart(gated)).pipe(Machine.run(NO_SINK, options), Effect.flatMap(end => Bool.match(Supersede.isSuperseded(end), {
|
|
737
|
+
onTrue: () => Effect.succeed(end),
|
|
738
|
+
onFalse: () => program
|
|
739
|
+
})));
|
|
740
|
+
};
|
|
741
|
+
/** Whether an entry is on with its own transition: hoisted, as it's asked per Retarget. */
|
|
742
|
+
const hasOwnTransition = layer => Bool.and(layer.active, Predicate.isNotUndefined(layer.transition));
|
|
743
|
+
/** A target as an active entry, with the name it resolved. */
|
|
744
|
+
const layerOf = (target, name) => ({
|
|
745
|
+
active: true,
|
|
746
|
+
values: target.values,
|
|
747
|
+
transition: target.transition,
|
|
748
|
+
name,
|
|
749
|
+
ends: endsOfTarget(target),
|
|
750
|
+
keyframes: target.keyframes
|
|
751
|
+
});
|
|
752
|
+
/** A list's target as an active entry (#297). */
|
|
753
|
+
const namedLayerOf = target => layerOf(target, target.name);
|
|
754
|
+
/** A target's Transition end as an entry's (#428): none shared, so the common case allocates nothing. Per entry, per Retarget (#460): a guard. */
|
|
755
|
+
const endsOfTarget = target => {
|
|
756
|
+
if (Predicate.isUndefined(target.transitionEnd)) return NO_VALUES;
|
|
757
|
+
return target.transitionEnd;
|
|
758
|
+
};
|
|
759
|
+
/** Whether an entry is on with a Transition end (#428). */
|
|
760
|
+
const hasEnds = layer => Bool.and(layer.active, layer.ends !== NO_VALUES);
|
|
761
|
+
/** The highest active entry that sets `key`, in its values or its Transition end (#428). */
|
|
762
|
+
const driverOf = (layers, key) => Option.getOrElse(Arr.findLastIndex(layers, layer => Bool.and(layer.active, Bool.or(Object.hasOwn(layer.values, key), Object.hasOwn(layer.ends, key)))), () => -1);
|
|
763
|
+
/**
|
|
764
|
+
* The Override stack resolved (#428): `Override.resolve` as before when no active entry has a
|
|
765
|
+
* Transition end; else over each entry's values and Transition end, its values winning a key both set, so
|
|
766
|
+
* a key only an end sets is the entry's (Motion's `{ ...target, ...transitionEnd }`), and the ends
|
|
767
|
+
* each entry drives.
|
|
768
|
+
*/
|
|
769
|
+
const resolvedOf = layers => {
|
|
770
|
+
if (!Arr.some(layers, hasEnds)) {
|
|
771
|
+
const resolved = Override.resolve(layers);
|
|
772
|
+
return {
|
|
773
|
+
resolved,
|
|
774
|
+
ends: undefined,
|
|
775
|
+
keyframes: keyframesNowOf(layers, resolved)
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
const merged = Arr.map(layers, layer => Bool.match(hasEnds(layer), {
|
|
779
|
+
onTrue: () => ({
|
|
780
|
+
...layer,
|
|
781
|
+
values: {
|
|
782
|
+
...layer.ends,
|
|
783
|
+
...layer.values
|
|
784
|
+
}
|
|
785
|
+
}),
|
|
786
|
+
onFalse: () => layer
|
|
787
|
+
}));
|
|
788
|
+
const resolved = Override.resolve(merged);
|
|
789
|
+
const endOnly = new Map();
|
|
790
|
+
const byLayer = Arr.makeBy(layers.length, constUndefined);
|
|
791
|
+
Arr.forEach(Rec.keys(resolved), key => {
|
|
792
|
+
const at = driverOf(layers, key);
|
|
793
|
+
const layer = layers[at];
|
|
794
|
+
if (Bool.or(Predicate.isUndefined(layer), Bool.not(Object.hasOwn(layer.ends, key)))) return;
|
|
795
|
+
const driving = layer;
|
|
796
|
+
if (Bool.not(Object.hasOwn(driving.values, key))) endOnly.set(key, at);
|
|
797
|
+
const into = UndefinedOr.match(byLayer[at], {
|
|
798
|
+
onUndefined: () => ({}),
|
|
799
|
+
onDefined: identity
|
|
800
|
+
});
|
|
801
|
+
into[key] = driving.ends[key];
|
|
802
|
+
byLayer[at] = into;
|
|
803
|
+
});
|
|
804
|
+
return {
|
|
805
|
+
resolved,
|
|
806
|
+
ends: {
|
|
807
|
+
endOnly,
|
|
808
|
+
byLayer
|
|
809
|
+
},
|
|
810
|
+
keyframes: keyframesNowOf(layers, resolved)
|
|
811
|
+
};
|
|
812
|
+
};
|
|
813
|
+
/** Whether an entry is on with Keyframes (#429). Per entry, per Retarget (#452): guards, nothing built. */
|
|
814
|
+
const hasKeyframes = layer => {
|
|
815
|
+
if (Predicate.isUndefined(layer.keyframes)) return false;
|
|
816
|
+
return layer.active;
|
|
817
|
+
};
|
|
818
|
+
/**
|
|
819
|
+
* Each resolved key's Keyframes (#429): the stops of the entry that drives it, when that entry gives
|
|
820
|
+
* it Keyframes. `undefined`, with nothing made, when no active entry has any: every element's common
|
|
821
|
+
* case.
|
|
822
|
+
*/
|
|
823
|
+
const keyframesNowOf = (layers, resolved) => {
|
|
824
|
+
if (!Arr.some(layers, hasKeyframes)) return undefined;
|
|
825
|
+
const now = {};
|
|
826
|
+
Arr.forEach(Rec.keys(resolved), key => {
|
|
827
|
+
const at = driverOf(layers, key);
|
|
828
|
+
const layer = layers[at];
|
|
829
|
+
if (Predicate.isUndefined(layer)) return;
|
|
830
|
+
const stops = UndefinedOr.map(layer.keyframes, byKey => byKey[key]);
|
|
831
|
+
if (Bool.or(Predicate.isUndefined(stops), Bool.not(Object.hasOwn(layer.values, key)))) return;
|
|
832
|
+
now[key] = {
|
|
833
|
+
stops: stops,
|
|
834
|
+
layer: at,
|
|
835
|
+
name: layer.name
|
|
836
|
+
};
|
|
837
|
+
});
|
|
838
|
+
return Bool.match(Rec.isEmptyRecord(now), {
|
|
839
|
+
onTrue: constUndefined,
|
|
840
|
+
onFalse: () => now
|
|
841
|
+
});
|
|
842
|
+
};
|
|
843
|
+
/** Two values maps with the same keys, each holding the same value. Built once, at module load. */
|
|
844
|
+
const sameValues = Rec.makeEquivalence(Equivalence.strictEqual());
|
|
845
|
+
/**
|
|
846
|
+
* Whether two resolutions are the same target (#209, #470): the same values for the same keys, in
|
|
847
|
+
* the base entry and resolved, the same drag, the same variant name, Keyframes and Transition ends,
|
|
848
|
+
* and the same gesture layers on, with the same names. Motion's rule: a config that resolves to the
|
|
849
|
+
* same values doesn't animate (a `transition` change applies from the next change), and a new
|
|
850
|
+
* variant name does, even to the same values, as a gesture turning on or off does. Both bindings'
|
|
851
|
+
* target memos compare with it, so a `style`, `transition` or callback change doesn't Retarget.
|
|
852
|
+
*/
|
|
853
|
+
export const sameResolution = (a, b) => a.dragging === b.dragging && sameLabels(a.variant, b.variant) && a.change === b.change && sameValues(a.resolved, b.resolved) && sameValues(a.base, b.base) && sameKeyframesNow(a.keyframes, b.keyframes) && sameLayersOn(a.layersOn, b.layersOn) && sameNamesOn(a.names, b.names) && sameEnds(a.ends, b.ends);
|
|
854
|
+
/** Two resolutions' gesture layers on that set values (#470): none on both, the common case, at once. */
|
|
855
|
+
const sameLayersOn = (a, b) => {
|
|
856
|
+
if (a === b) return true;
|
|
857
|
+
return a.inView === b.inView && a.focused === b.focused && a.hovered === b.hovered && a.pressed === b.pressed && a.dragged === b.dragged;
|
|
858
|
+
};
|
|
859
|
+
/** Two resolutions' active gesture names (#470): a named entry turning on or off, or a new name. None on both, the common case, at once. */
|
|
860
|
+
const sameNamesOn = (a, b) => {
|
|
861
|
+
if (a === b) return true;
|
|
862
|
+
return sameGestureNames(a, b);
|
|
863
|
+
};
|
|
864
|
+
/**
|
|
865
|
+
* Two resolutions' Transition ends the same (#470), entry by entry: a key an entry both animates and
|
|
866
|
+
* ends resolves to its value, so its end is compared here. `undefined` on both, the common case, at once.
|
|
867
|
+
*/
|
|
868
|
+
const sameEnds = (a, b) => {
|
|
869
|
+
if (a === b) return true;
|
|
870
|
+
if (Predicate.isUndefined(a)) return false;
|
|
871
|
+
if (Predicate.isUndefined(b)) return false;
|
|
872
|
+
const y = b.byLayer;
|
|
873
|
+
return Bool.and(a.byLayer.length === y.length, Arr.every(a.byLayer, (ends, i) => sameEndsAt(ends, y[i])));
|
|
874
|
+
};
|
|
875
|
+
/** The value `key`'s Transition end sets it to in `ends` (#470): its driving entry's, the one entry that ends it. */
|
|
876
|
+
const endFor = (ends, key) => {
|
|
877
|
+
if (Predicate.isUndefined(ends)) return undefined;
|
|
878
|
+
return Option.match(Arr.findFirst(ends.byLayer, values => endsKey(values, key)), {
|
|
879
|
+
onNone: constUndefined,
|
|
880
|
+
onSome: values => values[key]
|
|
881
|
+
});
|
|
882
|
+
};
|
|
883
|
+
/** Whether an entry's Transition end sets `key`. */
|
|
884
|
+
const endsKey = (values, key) => {
|
|
885
|
+
if (Predicate.isUndefined(values)) return false;
|
|
886
|
+
return Object.hasOwn(values, key);
|
|
887
|
+
};
|
|
888
|
+
/**
|
|
889
|
+
* Whether `key`'s Transition end changed since the last Retarget (#470): Motion compares a target's
|
|
890
|
+
* `transitionEnd` with its values, so a new end animates its key again. None on either, the common
|
|
891
|
+
* case, at once.
|
|
892
|
+
*/
|
|
893
|
+
const endMoved = (last, now, key) => {
|
|
894
|
+
if (Predicate.isUndefined(last)) return false;
|
|
895
|
+
if (last.ends === now.ends) return false;
|
|
896
|
+
return endFor(last.ends, key) !== endFor(now.ends, key);
|
|
897
|
+
};
|
|
898
|
+
/** An entry's Transition end the same in two resolutions (#470): none on both, or the same values. */
|
|
899
|
+
const sameEndsAt = (a, b) => {
|
|
900
|
+
if (a === b) return true;
|
|
901
|
+
if (Predicate.isUndefined(a)) return false;
|
|
902
|
+
if (Predicate.isUndefined(b)) return false;
|
|
903
|
+
return sameValues(a, b);
|
|
904
|
+
};
|
|
905
|
+
/** Two lists of stops equal stop by stop (#429, Motion's `shallowCompare`). */
|
|
906
|
+
const sameStops = (a, b) => Bool.or(a === b, Bool.and(a.length === b.length, Arr.every(a, (stop, i) => stop === b[i])));
|
|
907
|
+
/**
|
|
908
|
+
* Whether a start that can't take its target's shape stays as it is (#430): it makes a Measured pair
|
|
909
|
+
* with it, so its leg measures both ends rather than starting at the target.
|
|
910
|
+
*/
|
|
911
|
+
const keepsStart = (key, start, target) => {
|
|
912
|
+
if (Predicate.isUndefined(start)) return false;
|
|
913
|
+
return MeasuredPair.needs(key, start, target);
|
|
914
|
+
};
|
|
915
|
+
/** The keys that may be Measured pairs (#430): those found, and each Keyframes key, its start now its first stop. */
|
|
916
|
+
const measuringOf = (found, keyframes) => Arr.appendAll(UndefinedOr.match(found, {
|
|
917
|
+
onUndefined: () => [],
|
|
918
|
+
onDefined: identity
|
|
919
|
+
}), UndefinedOr.match(keyframes, {
|
|
920
|
+
onUndefined: () => [],
|
|
921
|
+
onDefined: Rec.keys
|
|
922
|
+
}));
|
|
923
|
+
/**
|
|
924
|
+
* A Retarget's Measured pairs (#430): each of `keys` whose start and target are one, asked of the
|
|
925
|
+
* end-of-task batch with the values the element draws now, but a key with Keyframes of more than two
|
|
926
|
+
* stops (`many`, #460). `undefined` with none.
|
|
927
|
+
*/
|
|
928
|
+
const measuredOf = (element, keys, from, to, values, many) => {
|
|
929
|
+
const pairs = {};
|
|
930
|
+
Arr.forEach(keys, key => {
|
|
931
|
+
if (hasManyStops(many, key)) return;
|
|
932
|
+
const start = from[key];
|
|
933
|
+
const target = to[key];
|
|
934
|
+
if (Bool.or(Predicate.isUndefined(start), Predicate.isUndefined(target))) return;
|
|
935
|
+
if (MeasuredPair.needs(key, start, target)) pairs[key] = {
|
|
936
|
+
from: start,
|
|
937
|
+
to: target
|
|
938
|
+
};
|
|
939
|
+
});
|
|
940
|
+
if (Rec.isEmptyRecord(pairs)) return undefined;
|
|
941
|
+
return MeasuredPair.measure(element, pairs, values);
|
|
942
|
+
};
|
|
943
|
+
/** A key's Keyframes in `keyframes` (#429): per key, per Retarget, so a guard, nothing made. */
|
|
944
|
+
const keyframesAtOf = (keyframes, key) => {
|
|
945
|
+
if (Predicate.isUndefined(keyframes)) return undefined;
|
|
946
|
+
return keyframes[key];
|
|
947
|
+
};
|
|
948
|
+
/** Whether a key's Keyframes are the same (#429, {@link KeyframesAt}): its stops, its entry and that entry's name. */
|
|
949
|
+
export const sameKeyframesAt = (a, b) => {
|
|
950
|
+
// Per key, per Retarget (#452): guards, the common case (neither) first.
|
|
951
|
+
if (a === b) return true;
|
|
952
|
+
if (Predicate.isUndefined(a)) return false;
|
|
953
|
+
if (Predicate.isUndefined(b)) return false;
|
|
954
|
+
return Bool.and(Bool.and(a.layer === b.layer, a.name === b.name), sameStops(a.stops, b.stops));
|
|
955
|
+
};
|
|
956
|
+
/** Whether two resolutions' Keyframes are the same, key by key (#429): `undefined` on both, the common case, at once. */
|
|
957
|
+
const sameKeyframesNow = (a, b) => {
|
|
958
|
+
if (Bool.or(Predicate.isUndefined(a), Predicate.isUndefined(b))) return a === b;
|
|
959
|
+
const x = a;
|
|
960
|
+
const y = b;
|
|
961
|
+
const keys = Rec.keys(x);
|
|
962
|
+
return Bool.and(keys.length === Rec.keys(y).length, Arr.every(keys, key => sameKeyframesAt(x[key], y[key])));
|
|
963
|
+
};
|
|
964
|
+
/** Whether `resolution` is `last` with only its `dragging` handed back (#340). */
|
|
965
|
+
const handsBackOnly = (resolution, last) => UndefinedOr.match(last, {
|
|
966
|
+
onUndefined: () => false,
|
|
967
|
+
onDefined: l => sameResolution({
|
|
968
|
+
...resolution,
|
|
969
|
+
dragging: l.dragging
|
|
970
|
+
}, l)
|
|
971
|
+
});
|
|
972
|
+
/**
|
|
973
|
+
* A Retarget's `definition`, as Motion's `onAnimationStart` / `onAnimationComplete` hand it over
|
|
974
|
+
* (#257): the variant name its base entry resolved, when that name differs from the last started
|
|
975
|
+
* Retarget's (`previous`), else the target's values. Motion's definition is per animation type: a
|
|
976
|
+
* new `animate` variant animates as its name, and a gesture turning on or off as values (its own,
|
|
977
|
+
* or the keys it leaves falling back), so a variant's name is only told when the variant changed.
|
|
978
|
+
*/
|
|
979
|
+
export const definitionOf = (resolution, previous) => {
|
|
980
|
+
const name = resolution.variant;
|
|
981
|
+
// A list is told as a list (#297): a change name by name, as Motion's `checkVariantsDidChange`.
|
|
982
|
+
if (Bool.and(Predicate.isNotUndefined(name), Bool.not(sameLabels(name, UndefinedOr.map(previous, p => p.variant))))) return name;
|
|
983
|
+
// A gesture's name that just came on (#291), the highest first, as Motion's names its type's.
|
|
984
|
+
const before = UndefinedOr.match(previous, {
|
|
985
|
+
onUndefined: () => NO_GESTURE_NAMES,
|
|
986
|
+
onDefined: p => p.names
|
|
987
|
+
});
|
|
988
|
+
const started = Arr.findFirst(GESTURES_DOWN, layer => Bool.and(Predicate.isNotUndefined(resolution.names[layer]), Bool.not(sameLabels(resolution.names[layer], before[layer]))));
|
|
989
|
+
return Option.match(started, {
|
|
990
|
+
onNone: () => resolution.resolved,
|
|
991
|
+
onSome: layer => resolution.names[layer]
|
|
992
|
+
});
|
|
993
|
+
};
|
|
994
|
+
/** The gesture layers, highest first. */
|
|
995
|
+
const GESTURES_DOWN = Arr.reverse(GESTURE_LAYERS);
|
|
996
|
+
/** Whether a resolution resolved a list (#297): its base, or an active gesture's. Cheap for the common case. */
|
|
997
|
+
const hasList = resolution => {
|
|
998
|
+
if (Arr.isArray(resolution.variant)) return true;
|
|
999
|
+
if (resolution.names === NO_GESTURE_NAMES) return false;
|
|
1000
|
+
return Arr.some(GESTURE_LAYERS, layer => Arr.isArray(resolution.names[layer]));
|
|
1001
|
+
};
|
|
1002
|
+
/** The list a Retarget tells settled name by name (#297): when its binding is told so, and its definition is a list. */
|
|
1003
|
+
const namesToldOf = (animation, resolution, previous) => {
|
|
1004
|
+
if (Predicate.isUndefined(animation)) return undefined;
|
|
1005
|
+
const tell = animation.namesSettled;
|
|
1006
|
+
if (Predicate.isUndefined(tell)) return undefined;
|
|
1007
|
+
if (Bool.not(hasList(resolution))) return undefined;
|
|
1008
|
+
const definition = definitionOf(resolution, previous);
|
|
1009
|
+
if (Bool.not(Arr.isArray(definition))) return undefined;
|
|
1010
|
+
return {
|
|
1011
|
+
names: definition,
|
|
1012
|
+
tell
|
|
1013
|
+
};
|
|
1014
|
+
};
|
|
1015
|
+
/**
|
|
1016
|
+
* A list's names, each told settled with the last leg of the keys it drives (#297): its entry's group,
|
|
1017
|
+
* or every leg's when the keys aren't split, the running legs the Retarget carries among them (#325).
|
|
1018
|
+
* A name that drives none is told at once.
|
|
1019
|
+
*/
|
|
1020
|
+
const nameSettlesOf = (names, resolution, groups, legGroups, legCount, carriedGroups, tell) => {
|
|
1021
|
+
const groupOf = name => {
|
|
1022
|
+
if (Predicate.isUndefined(groups)) return 0;
|
|
1023
|
+
return Option.getOrElse(Arr.findFirstIndex(resolution.layers, layer => layer.name === name), () => 0);
|
|
1024
|
+
};
|
|
1025
|
+
// The legs still running in each group.
|
|
1026
|
+
const left = new Map();
|
|
1027
|
+
const add = g => {
|
|
1028
|
+
left.set(g, Option.getOrElse(Option.fromUndefinedOr(left.get(g)), () => 0) + 1);
|
|
1029
|
+
};
|
|
1030
|
+
UndefinedOr.match(legGroups, {
|
|
1031
|
+
onUndefined: () => {
|
|
1032
|
+
if (legCount > 0) left.set(0, legCount);
|
|
1033
|
+
},
|
|
1034
|
+
onDefined: tags => Arr.forEach(tags, add)
|
|
1035
|
+
});
|
|
1036
|
+
Arr.forEach(carriedGroups, gs => Arr.forEach(gs, add));
|
|
1037
|
+
const running = name => left.has(groupOf(name));
|
|
1038
|
+
let pending = Arr.filter(names, running);
|
|
1039
|
+
const idle = Arr.filter(names, name => Bool.not(running(name)));
|
|
1040
|
+
if (idle.length > 0) tell(idle);
|
|
1041
|
+
// A leg in group `g` ended: the names of that group are told once its last has.
|
|
1042
|
+
const endIn = g => {
|
|
1043
|
+
const n = Option.getOrElse(Option.fromUndefinedOr(left.get(g)), () => 1) - 1;
|
|
1044
|
+
if (n > 0) {
|
|
1045
|
+
left.set(g, n);
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
left.delete(g);
|
|
1049
|
+
const done = Arr.filter(pending, name => groupOf(name) === g);
|
|
1050
|
+
pending = Arr.filter(pending, name => groupOf(name) !== g);
|
|
1051
|
+
if (done.length > 0) tell(done);
|
|
1052
|
+
};
|
|
1053
|
+
let next = 0;
|
|
1054
|
+
return {
|
|
1055
|
+
leg: () => {
|
|
1056
|
+
const g = UndefinedOr.match(legGroups, {
|
|
1057
|
+
onUndefined: () => 0,
|
|
1058
|
+
onDefined: tags => Option.getOrElse(Option.fromUndefinedOr(tags[next]), () => 0)
|
|
1059
|
+
});
|
|
1060
|
+
next++;
|
|
1061
|
+
return end => {
|
|
1062
|
+
// A Superseded leg (#200) settles nothing: the next Retarget's tells.
|
|
1063
|
+
if (Supersede.isSuperseded(end)) return;
|
|
1064
|
+
endIn(g);
|
|
1065
|
+
};
|
|
1066
|
+
},
|
|
1067
|
+
carried: i => end => {
|
|
1068
|
+
if (Supersede.isSuperseded(end)) return;
|
|
1069
|
+
Arr.forEach(UndefinedOr.match(carriedGroups[i], {
|
|
1070
|
+
onUndefined: () => [],
|
|
1071
|
+
onDefined: identity
|
|
1072
|
+
}), endIn);
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
};
|
|
1076
|
+
/**
|
|
1077
|
+
* Solid 1's animation callbacks (#257, Motion's props): each Retarget's start and settle told to the
|
|
1078
|
+
* config's `onAnimationStart` / `onAnimationComplete`, with its `definition`, as the Retarget read
|
|
1079
|
+
* the config. A callback that throws is reported, and the element animates on. The Solid 2 binding's
|
|
1080
|
+
* config has neither: it hands the same facts over as async values.
|
|
1081
|
+
*/
|
|
1082
|
+
export const animationCallbacks = (runtime, id) => {
|
|
1083
|
+
// Per Retarget, per element: the callback looked up first, and nothing made without one.
|
|
1084
|
+
const tell = (name, callback, definition) => {
|
|
1085
|
+
try {
|
|
1086
|
+
callback(definition);
|
|
1087
|
+
} catch (defect) {
|
|
1088
|
+
runtime.runFork(Report.failure(`wardic.spine: ${name} failed`, Cause.die(defect)).pipe(Effect.annotateLogs({
|
|
1089
|
+
id
|
|
1090
|
+
})));
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
return {
|
|
1094
|
+
// A list starts as each of its names, in order (#297, Motion's `animateVisualElement` a name).
|
|
1095
|
+
started: (resolution, previous, config) => {
|
|
1096
|
+
const callback = config.onAnimationStart;
|
|
1097
|
+
if (Predicate.isUndefined(callback)) return;
|
|
1098
|
+
const definition = definitionOf(resolution, previous);
|
|
1099
|
+
if (Arr.isArray(definition)) {
|
|
1100
|
+
Arr.forEach(definition, name => tell("onAnimationStart", callback, name));
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
tell("onAnimationStart", callback, definition);
|
|
1104
|
+
},
|
|
1105
|
+
// A list's names were each told as they settled (`namesSettled`).
|
|
1106
|
+
settled: (resolution, previous, config) => {
|
|
1107
|
+
const callback = config.onAnimationComplete;
|
|
1108
|
+
if (Predicate.isUndefined(callback)) return;
|
|
1109
|
+
const definition = definitionOf(resolution, previous);
|
|
1110
|
+
if (Arr.isArray(definition)) return;
|
|
1111
|
+
tell("onAnimationComplete", callback, definition);
|
|
1112
|
+
},
|
|
1113
|
+
namesSettled: (names, config) => {
|
|
1114
|
+
const callback = config.onAnimationComplete;
|
|
1115
|
+
if (Predicate.isUndefined(callback)) return;
|
|
1116
|
+
Arr.forEach(names, name => tell("onAnimationComplete", callback, name));
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
};
|
|
1120
|
+
/** The variant name an element animates to: its own `animate`'s, else the one its provider hands down. */
|
|
1121
|
+
const variantOf = (animate, parent) => {
|
|
1122
|
+
if (Predicate.isNotUndefined(animate)) return nameOf(animate);
|
|
1123
|
+
if (Predicate.isUndefined(parent)) return undefined;
|
|
1124
|
+
return parent.variant();
|
|
1125
|
+
};
|
|
1126
|
+
/** The base target (ADR-0007): its own `animate`'s, else the inherited name's, else the seeded `initial`. */
|
|
1127
|
+
const baseTargetOf = (own, variant, variants, custom, state, initialLink) => {
|
|
1128
|
+
if (Predicate.isNotUndefined(own)) return resolveTarget(own, variants, custom, state);
|
|
1129
|
+
if (Predicate.isNotUndefined(variant)) return resolveTarget(variant, variants, custom, state);
|
|
1130
|
+
return {
|
|
1131
|
+
values: initialLink,
|
|
1132
|
+
transition: undefined,
|
|
1133
|
+
transitionEnd: undefined,
|
|
1134
|
+
keyframes: undefined
|
|
1135
|
+
};
|
|
1136
|
+
};
|
|
1137
|
+
/**
|
|
1138
|
+
* The Override stack resolved (ascending priority, Motion's `variantPriorityOrder`): base (animate, or
|
|
1139
|
+
* initial when no animate) -> whileInView -> whileFocus -> whileHover -> whileTap -> whileDrag (#273
|
|
1140
|
+
* added the first two). `Override.resolve` picks the last active entry per key. Pure:
|
|
1141
|
+
* a binding computes it in a memo, so a config change, an inherited variant name's
|
|
1142
|
+
* (`parent.variant()`, read only when there's no `animate`) or an entry's drives a Retarget.
|
|
1143
|
+
*/
|
|
1144
|
+
export const resolutionOf = (c, parent, initialLink, active, state, own) => {
|
|
1145
|
+
// The Controls change in effect (#433): its own controls', else its provider's, read here so a new one Retargets.
|
|
1146
|
+
const change = changeIn(own, parent);
|
|
1147
|
+
const variants = c.variants;
|
|
1148
|
+
// Base target resolution priority (ADR-0007):
|
|
1149
|
+
// (1) local `animate` (a Values map or a variant name) — overrides any
|
|
1150
|
+
// inherited variant entirely;
|
|
1151
|
+
// (2) else an INHERITED variant name from the parent context, resolved
|
|
1152
|
+
// against THIS child's OWN `variants` (a child's "open" != its
|
|
1153
|
+
// sibling's "open"); read parent.variant() here so a parent flip
|
|
1154
|
+
// recomputes the memo and retargets;
|
|
1155
|
+
// (3) else the SSR-seeded `initial`.
|
|
1156
|
+
// Per Retarget, per element (#460, compose once): statements.
|
|
1157
|
+
const variant = variantOf(c.animate, parent);
|
|
1158
|
+
// A list of names (#297, Motion's `VariantLabels`): a base entry a name, in order, so the last name
|
|
1159
|
+
// that sets a key drives it. A single name or a values map takes the path below, as before.
|
|
1160
|
+
if (Arr.isArray(c.animate) || Predicate.isUndefined(c.animate) && Arr.isArray(variant)) {
|
|
1161
|
+
const targets = resolveTargets(variant, variants, c.custom, state);
|
|
1162
|
+
const merged = mergedOf(targets);
|
|
1163
|
+
const listLayers = Arr.map(targets, namedLayerOf);
|
|
1164
|
+
return withGestures(c, parent, listLayers, merged.values, variant, active, merged.transition, state, change);
|
|
1165
|
+
}
|
|
1166
|
+
// A dynamic variant resolves with this element's own `custom` (#277), as Motion's each child's.
|
|
1167
|
+
// Animation controls never reach here: its binding reads them once, each change its entry (#433).
|
|
1168
|
+
const target = baseTargetOf(c.animate, variant, variants, c.custom, state, initialLink);
|
|
1169
|
+
const base = target.values;
|
|
1170
|
+
const baseLayer = layerOf(target, variant);
|
|
1171
|
+
// A Variant child's gestures are on while its provider's are (#291, Motion's `setActive`), each on
|
|
1172
|
+
// its own `while*`, else the label the provider hands down. With no provider, its own: nothing made.
|
|
1173
|
+
// The common case: nothing handed down and no gesture on. The base entry alone, and nothing else
|
|
1174
|
+
// made or called, at every element's mount and Retarget.
|
|
1175
|
+
if (handDownFrom(parent) === NO_HAND_DOWN && !anyOn(active)) {
|
|
1176
|
+
const alone = [baseLayer];
|
|
1177
|
+
const {
|
|
1178
|
+
resolved,
|
|
1179
|
+
ends,
|
|
1180
|
+
keyframes
|
|
1181
|
+
} = resolvedOf(alone);
|
|
1182
|
+
return {
|
|
1183
|
+
resolved,
|
|
1184
|
+
base,
|
|
1185
|
+
dragging: active.dragging,
|
|
1186
|
+
variant,
|
|
1187
|
+
active,
|
|
1188
|
+
transition: target.transition,
|
|
1189
|
+
layers: alone,
|
|
1190
|
+
names: NO_GESTURE_NAMES,
|
|
1191
|
+
layersOn: NO_GESTURE_STATES,
|
|
1192
|
+
ends,
|
|
1193
|
+
keyframes,
|
|
1194
|
+
change
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
return withGestures(c, parent, [baseLayer], base, variant, active, target.transition, state, change);
|
|
1198
|
+
};
|
|
1199
|
+
/** The **Controls change** in effect for an element (#433): its own, else its provider's; per Retarget, a guard. */
|
|
1200
|
+
const changeIn = (own, parent) => {
|
|
1201
|
+
if (Predicate.isNotUndefined(own)) return own;
|
|
1202
|
+
if (Predicate.isUndefined(parent)) return undefined;
|
|
1203
|
+
const inherited = parent.change;
|
|
1204
|
+
if (Predicate.isUndefined(inherited)) return undefined;
|
|
1205
|
+
return inherited();
|
|
1206
|
+
};
|
|
1207
|
+
/**
|
|
1208
|
+
* `resolution` run on its Controls change's override (#433, Motion's `transitionOverride`): its base
|
|
1209
|
+
* entries' own transitions beaten by it, its gestures' kept. The first Retarget for the change only.
|
|
1210
|
+
*/
|
|
1211
|
+
const overriddenOf = (resolution, override) => {
|
|
1212
|
+
const variant = resolution.variant;
|
|
1213
|
+
let base = 1;
|
|
1214
|
+
if (Arr.isArray(variant)) base = variant.length;
|
|
1215
|
+
return {
|
|
1216
|
+
...resolution,
|
|
1217
|
+
transition: override,
|
|
1218
|
+
layers: Arr.map(resolution.layers, (layer, i) => Bool.match(i < base, {
|
|
1219
|
+
onTrue: () => ({
|
|
1220
|
+
...layer,
|
|
1221
|
+
transition: override
|
|
1222
|
+
}),
|
|
1223
|
+
onFalse: () => layer
|
|
1224
|
+
}))
|
|
1225
|
+
};
|
|
1226
|
+
};
|
|
1227
|
+
/**
|
|
1228
|
+
* A resolution from its base entries (one, or one a name of a list, #297) and its gesture layers on
|
|
1229
|
+
* top (#291), each gesture's an entry a name too: the Override stack resolved, and the names its
|
|
1230
|
+
* active gestures resolved.
|
|
1231
|
+
*/
|
|
1232
|
+
const withGestures = (c, parent, layers, base, variant, active, transition, state, change) => {
|
|
1233
|
+
const variants = c.variants;
|
|
1234
|
+
const above = handDownFrom(parent);
|
|
1235
|
+
if (Bool.and(above === NO_HAND_DOWN, Bool.not(anyOn(active)))) {
|
|
1236
|
+
const {
|
|
1237
|
+
resolved,
|
|
1238
|
+
ends,
|
|
1239
|
+
keyframes
|
|
1240
|
+
} = resolvedOf(layers);
|
|
1241
|
+
return {
|
|
1242
|
+
resolved,
|
|
1243
|
+
base,
|
|
1244
|
+
dragging: active.dragging,
|
|
1245
|
+
variant,
|
|
1246
|
+
active,
|
|
1247
|
+
transition,
|
|
1248
|
+
layers,
|
|
1249
|
+
names: NO_GESTURE_NAMES,
|
|
1250
|
+
layersOn: NO_GESTURE_STATES,
|
|
1251
|
+
ends,
|
|
1252
|
+
keyframes,
|
|
1253
|
+
change
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
const on = gesturesOnOf(active, above);
|
|
1257
|
+
const labels = above.names;
|
|
1258
|
+
// In Motion's priority, lowest first: a literal's fields are evaluated in order.
|
|
1259
|
+
const layersOn = {
|
|
1260
|
+
inView: gestureLayersInto(layers, c.whileInView, on.inView, labels.inView, variants, c.custom, state),
|
|
1261
|
+
focused: gestureLayersInto(layers, c.whileFocus, on.focused, labels.focused, variants, c.custom, state),
|
|
1262
|
+
hovered: gestureLayersInto(layers, c.whileHover, on.hovered, labels.hovered, variants, c.custom, state),
|
|
1263
|
+
pressed: gestureLayersInto(layers, c.whileTap, on.pressed, labels.pressed, variants, c.custom, state),
|
|
1264
|
+
// whileDrag sits ABOVE tap (highest priority) — driven by the spring,
|
|
1265
|
+
// NOT stripped, so e.g. `scale: 1.1` animates while held and returns
|
|
1266
|
+
// after release.
|
|
1267
|
+
dragged: gestureLayersInto(layers, c.whileDrag, on.dragged, labels.dragged, variants, c.custom, state)
|
|
1268
|
+
};
|
|
1269
|
+
const {
|
|
1270
|
+
resolved,
|
|
1271
|
+
ends,
|
|
1272
|
+
keyframes
|
|
1273
|
+
} = resolvedOf(layers);
|
|
1274
|
+
const names = activeNamesFor(c, on, labels);
|
|
1275
|
+
return {
|
|
1276
|
+
resolved,
|
|
1277
|
+
base,
|
|
1278
|
+
dragging: active.dragging,
|
|
1279
|
+
variant,
|
|
1280
|
+
active,
|
|
1281
|
+
transition,
|
|
1282
|
+
layers,
|
|
1283
|
+
names,
|
|
1284
|
+
layersOn,
|
|
1285
|
+
ends,
|
|
1286
|
+
keyframes,
|
|
1287
|
+
change
|
|
1288
|
+
};
|
|
1289
|
+
};
|
|
1290
|
+
/**
|
|
1291
|
+
* An element's {@link Start}, from its config read once and the context it inherits from. With
|
|
1292
|
+
* `initial={false}` (its own, inherited, or an `<AnimatePresence initial={false}>`'s first render)
|
|
1293
|
+
* it starts at its `animate`, and nothing animates at mount (#134).
|
|
1294
|
+
*/
|
|
1295
|
+
export const startOf = (config, parent, presenceBlocks, untrack) => {
|
|
1296
|
+
const startedAtAnimate = startsAtAnimate(config, parent, presenceBlocks);
|
|
1297
|
+
const initialValues = startingValuesOf(config, parent, presenceBlocks, untrack);
|
|
1298
|
+
return {
|
|
1299
|
+
quiet: startsQuiet(config, parent, presenceBlocks, untrack),
|
|
1300
|
+
initialValues,
|
|
1301
|
+
initialLink: Bool.match(startedAtAnimate, {
|
|
1302
|
+
onTrue: () => ({}),
|
|
1303
|
+
onFalse: () => initialValues
|
|
1304
|
+
}),
|
|
1305
|
+
startedLink: Bool.match(startedAtAnimate, {
|
|
1306
|
+
onTrue: () => initialValues,
|
|
1307
|
+
onFalse: () => ({})
|
|
1308
|
+
})
|
|
1309
|
+
};
|
|
1310
|
+
};
|
|
1311
|
+
/** A Snapshot seeded from the Starting values, velocities 0, so frame 1 flows out of the seed (no snap). */
|
|
1312
|
+
export const snapshotOf = start => emptySnapshotOf({
|
|
1313
|
+
...start.initialValues
|
|
1314
|
+
});
|
|
1315
|
+
/** A Snapshot of `values`, nothing moving: read as it is until a spine reads it. */
|
|
1316
|
+
export const emptySnapshotOf = values => ({
|
|
1317
|
+
values,
|
|
1318
|
+
velocities: {},
|
|
1319
|
+
drawnAt: {},
|
|
1320
|
+
owners: undefined,
|
|
1321
|
+
now: frameNow
|
|
1322
|
+
});
|
|
1323
|
+
// --- Velocities (#464) ---------------------------------------------------------------------------
|
|
1324
|
+
/** A leg's velocity for `key`: a Blend leg's from its frames, a Snap's none, a spring's or a follow's as it wrote it. */
|
|
1325
|
+
const legVelocityOf = (snapshot, running, key) => {
|
|
1326
|
+
if (running.kind === "Blend") return blendVelocityOf(running, key);
|
|
1327
|
+
if (running.kind === "Snap") return 0;
|
|
1328
|
+
return velocityOf(snapshot, key);
|
|
1329
|
+
};
|
|
1330
|
+
/**
|
|
1331
|
+
* `key`'s velocity at `now` (#464, Motion's `getVelocity`): the leg drawing it, once it has drawn a
|
|
1332
|
+
* frame, else what the Snapshot holds for it (the last leg to let it go left it, a drag or a seed set
|
|
1333
|
+
* it), whichever drew it last; 0 once nothing has moved it for `MAX_VELOCITY_DELTA`. Read only for a
|
|
1334
|
+
* key a spring or a follow starts, or one a leg lets go: guards, nothing made.
|
|
1335
|
+
*/
|
|
1336
|
+
const velocityAt = (snapshot, owner, key, now) => {
|
|
1337
|
+
const at = snapshot.drawnAt[key];
|
|
1338
|
+
// Guards, not `Bool.and`, which reads both sides: a leg that hasn't drawn yet stands for nothing.
|
|
1339
|
+
if (Predicate.isNotUndefined(owner)) {
|
|
1340
|
+
if (owner.frames > 0) {
|
|
1341
|
+
if (Predicate.isUndefined(at) || owner.lastAt >= at) {
|
|
1342
|
+
if (now - owner.lastAt > MAX_VELOCITY_DELTA) return 0;
|
|
1343
|
+
return legVelocityOf(snapshot, owner, key);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
if (Predicate.isUndefined(at)) return 0;
|
|
1348
|
+
if (now - at > MAX_VELOCITY_DELTA) return 0;
|
|
1349
|
+
return velocityOf(snapshot, key);
|
|
1350
|
+
};
|
|
1351
|
+
/**
|
|
1352
|
+
* `running` lets `key` go, having drawn it (#464): the velocity it gives the key now (0 once it's drawn
|
|
1353
|
+
* nothing for 30 ms) and its last frame's time stay on the Snapshot, as numbers. Keeping the leg itself
|
|
1354
|
+
* kept its Retarget's closures alive until the unmount, which paid for them. A string carries none.
|
|
1355
|
+
*/
|
|
1356
|
+
const letGo = (snapshot, key, running) => {
|
|
1357
|
+
if (running.frames === 0) return;
|
|
1358
|
+
if (!Predicate.isNumber(snapshot.values[key])) return;
|
|
1359
|
+
snapshot.velocities[key] = velocityAt(snapshot, running, key, snapshot.now());
|
|
1360
|
+
snapshot.drawnAt[key] = running.lastAt;
|
|
1361
|
+
};
|
|
1362
|
+
/** Every numeric key's velocity now (#464): a presence's exit and takeover read it (#286). */
|
|
1363
|
+
export const velocitiesNowOf = snapshot => {
|
|
1364
|
+
const now = snapshot.now();
|
|
1365
|
+
const owners = snapshot.owners;
|
|
1366
|
+
return Rec.map(Rec.filter(snapshot.values, Predicate.isNumber), (_, key) => velocityAt(snapshot, UndefinedOr.match(owners, {
|
|
1367
|
+
onUndefined: constUndefined,
|
|
1368
|
+
onDefined: map => map.get(key)
|
|
1369
|
+
}), key, now));
|
|
1370
|
+
};
|
|
1371
|
+
/**
|
|
1372
|
+
* The transition a Retarget runs on (#66): the element's last one when the new one has the same
|
|
1373
|
+
* fields, so core's decode cache hits when the object is rebuilt with the same values (a staggered
|
|
1374
|
+
* child's, ADR-0007, or one Solid rebuilds as it reads a signal). One per element.
|
|
1375
|
+
*/
|
|
1376
|
+
export const makeReuse = () => {
|
|
1377
|
+
let lastTransition;
|
|
1378
|
+
// Per Retarget (#460, compose once): statements.
|
|
1379
|
+
return transition => {
|
|
1380
|
+
if (Predicate.isNotUndefined(lastTransition) && sameFields(lastTransition, transition)) return lastTransition;
|
|
1381
|
+
lastTransition = transition;
|
|
1382
|
+
return transition;
|
|
1383
|
+
};
|
|
1384
|
+
};
|
|
1385
|
+
/**
|
|
1386
|
+
* A mounted element's Base-value links (ADR-0022): a key with no value starts from its `style`
|
|
1387
|
+
* value, else its Own value. The Own value is read from the element once per key, at first need
|
|
1388
|
+
* (D3): after mount, so never on a server (ADR-0021). Each link is coerced to the shape of the
|
|
1389
|
+
* key's target (`like`). `styleNow` reads the user's style untracked; a Live value in it is read now.
|
|
1390
|
+
*/
|
|
1391
|
+
export const startLinksOf = (element, styleNow, live) => {
|
|
1392
|
+
const ownValue = OwnValues.of(element);
|
|
1393
|
+
// A `style` value read now: a Live value's current value (#130), anything else as it is.
|
|
1394
|
+
const readStyle = raw => {
|
|
1395
|
+
if (Predicate.isUndefined(live)) return raw;
|
|
1396
|
+
return live.read(raw);
|
|
1397
|
+
};
|
|
1398
|
+
const linksFor = like => ({
|
|
1399
|
+
style: key => Option.flatMap(Option.fromUndefinedOr(styleNow), now => Option.flatMap(OwnValues.styleValueOf(now(), key), raw => OwnValues.valueLike(readStyle(raw), like))),
|
|
1400
|
+
own: key => Option.flatMap(ownValue(key), raw => OwnValues.valueLike(raw, like))
|
|
1401
|
+
});
|
|
1402
|
+
const startLinkOf = (key, like) => BaseValue.start(key, linksFor(like));
|
|
1403
|
+
return {
|
|
1404
|
+
ownValue,
|
|
1405
|
+
linksFor,
|
|
1406
|
+
startLinkOf
|
|
1407
|
+
};
|
|
1408
|
+
};
|
|
1409
|
+
/**
|
|
1410
|
+
* An element's presence record (ADR-0007 exit): seeded with its Starting values, so an exit that
|
|
1411
|
+
* fires before any frame still has a `from`, and its `exit` ref, which the ward keeps current. An exit key with no value starts
|
|
1412
|
+
* from its Base value's start links (ADR-0022), read from the retained node at the exit.
|
|
1413
|
+
*/
|
|
1414
|
+
export const presenceRecordOf = (element, start, exitOf, links, tree, snapshot, reducedMotion, skipAnimations) => ({
|
|
1415
|
+
element,
|
|
1416
|
+
snapshot: {
|
|
1417
|
+
current: {
|
|
1418
|
+
...start.initialValues
|
|
1419
|
+
}
|
|
1420
|
+
},
|
|
1421
|
+
exitOf,
|
|
1422
|
+
tree,
|
|
1423
|
+
startOf: (key, like) => Option.getOrUndefined(Option.map(links.startLinkOf(key, like), s => s.value)),
|
|
1424
|
+
// Its spine's, read when a child back under its key takes over from it (#286): its running legs' too (#464).
|
|
1425
|
+
velocities: () => velocitiesNowOf(snapshot),
|
|
1426
|
+
// Its own, under its nearest WardicConfig (#434): its exit honours it, not the presence's.
|
|
1427
|
+
reducedMotion,
|
|
1428
|
+
// Its nearest WardicConfig's (#468): an exit is skipped as its element's animations are.
|
|
1429
|
+
skipAnimations
|
|
1430
|
+
});
|
|
1431
|
+
/**
|
|
1432
|
+
* Merge an emitted frame's value-map into a presence record's snapshot (nothing without one). It
|
|
1433
|
+
* mirrors what the gate accumulates, so an exit departs from the element's actual resting value-map.
|
|
1434
|
+
*/
|
|
1435
|
+
export const recordFrameOf = presence => value => {
|
|
1436
|
+
if (Predicate.isNotUndefined(presence)) Object.assign(presence.snapshot.current, value);
|
|
1437
|
+
};
|
|
1438
|
+
/**
|
|
1439
|
+
* Turn the element's will-change value on (#443, Motion's `addValueToWillChange`) when its `style`
|
|
1440
|
+
* gives it one and one of `legs` animates a transform key or one a browser composites. A key already
|
|
1441
|
+
* at its target starts no leg (#448), and a layout animation runs none, so neither does. Per start:
|
|
1442
|
+
* a lookup in its routed keys, none for a style that routes nothing.
|
|
1443
|
+
*/
|
|
1444
|
+
const turnWillChangeOn = (live, legs) => {
|
|
1445
|
+
if (Predicate.isUndefined(live)) return;
|
|
1446
|
+
const turnOn = live.willChange();
|
|
1447
|
+
if (Predicate.isUndefined(turnOn)) return;
|
|
1448
|
+
if (Arr.some(legs, leg => Arr.some(Rec.keys(leg.to), turnsWillChangeOn))) turnOn();
|
|
1449
|
+
};
|
|
1450
|
+
/**
|
|
1451
|
+
* A binding's `setDragging`, turning the element's will-change value on as a drag starts (#443,
|
|
1452
|
+
* Motion's): `"transform"`, as its drag draws `x` and `y`.
|
|
1453
|
+
*/
|
|
1454
|
+
export const draggingWithWillChange = (live, setDragging) => UndefinedOr.match(live, {
|
|
1455
|
+
onUndefined: () => setDragging,
|
|
1456
|
+
onDefined: style => on => {
|
|
1457
|
+
if (on) UndefinedOr.map(style.willChange(), turnOn => turnOn());
|
|
1458
|
+
setDragging(on);
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
/**
|
|
1462
|
+
* A mounted element's spine: its Retarget, the returns to its Base values, the follower of its
|
|
1463
|
+
* Live values, and its legs' lifetime. Every leg is a fiber of its provider's runtime, and joins
|
|
1464
|
+
* its Retarget's token: a Retarget ends the token before it starts its own legs, and {@link
|
|
1465
|
+
* ElementSpine.dispose} ends every leg's (#542). Both end the legs in the calling task: each leg's
|
|
1466
|
+
* run leaves the loop at once, and its fiber ends Superseded, inline (ADR-0027, decision 5,
|
|
1467
|
+
* *Amendment (#200)*). A leg the token didn't reach is interrupted (`endLeg`). The runtime's own
|
|
1468
|
+
* fiber Scope interrupts what's left when the provider ends.
|
|
1469
|
+
*/
|
|
1470
|
+
export const makeElementSpine = options => {
|
|
1471
|
+
const {
|
|
1472
|
+
animation,
|
|
1473
|
+
byName,
|
|
1474
|
+
canStart,
|
|
1475
|
+
config,
|
|
1476
|
+
defaultTransition,
|
|
1477
|
+
element,
|
|
1478
|
+
extraDelay,
|
|
1479
|
+
gate,
|
|
1480
|
+
id,
|
|
1481
|
+
links,
|
|
1482
|
+
live,
|
|
1483
|
+
onFrame,
|
|
1484
|
+
parent,
|
|
1485
|
+
positionalKeys,
|
|
1486
|
+
presence,
|
|
1487
|
+
runtime,
|
|
1488
|
+
snapshot,
|
|
1489
|
+
start,
|
|
1490
|
+
styleNow,
|
|
1491
|
+
tag
|
|
1492
|
+
} = options;
|
|
1493
|
+
const {
|
|
1494
|
+
initialLink,
|
|
1495
|
+
initialValues,
|
|
1496
|
+
startedLink
|
|
1497
|
+
} = start;
|
|
1498
|
+
const {
|
|
1499
|
+
linksFor,
|
|
1500
|
+
ownValue,
|
|
1501
|
+
startLinkOf
|
|
1502
|
+
} = links;
|
|
1503
|
+
let handoff = options.handoff;
|
|
1504
|
+
// Its mount tells nothing when it starts at its `animate` (#448): on until its first Retarget.
|
|
1505
|
+
let quiet = start.quiet;
|
|
1506
|
+
// Its Variable values (#55, ADR-0035 *Amendment (#55)*): the Key rule bound to this element,
|
|
1507
|
+
// added to each leg it starts, so a `var()` end blends what it resolves to here.
|
|
1508
|
+
const elementRules = [Variables.values(element)];
|
|
1509
|
+
const recordFrame = recordFrameOf(presence);
|
|
1510
|
+
// Whether its animations are skipped (#468): never, with nothing given.
|
|
1511
|
+
const skipAnimations = UndefinedOr.match(options.skipAnimations, {
|
|
1512
|
+
onUndefined: () => constFalse,
|
|
1513
|
+
onDefined: identity
|
|
1514
|
+
});
|
|
1515
|
+
// A routed key a return handed back: written by the follower from now on (#130). Set by
|
|
1516
|
+
// `follow`; a return settles a tick after it runs at the earliest.
|
|
1517
|
+
let handBack = constVoid;
|
|
1518
|
+
// The keys a Retarget drove, each with its last target value (its shape), and the
|
|
1519
|
+
// ones returning to their Base value until that return settles (ADR-0022). Both are
|
|
1520
|
+
// the spine's: a Retarget mid-return carries them again, so a return is never
|
|
1521
|
+
// frozen half-way, and a key that settled has left them, so a Retarget of the same
|
|
1522
|
+
// target (a `when` gate reopening, ADR-0007) leaves it be. On a drag element, the keys
|
|
1523
|
+
// the drag moves leave the return while it runs, so they stay where it dropped them (C9)
|
|
1524
|
+
// until an entry sets them again; a projected element's drag moves none, its projection
|
|
1525
|
+
// target does (ADR-0016), and its own translate returns as any key does (#363).
|
|
1526
|
+
const driven = new Map();
|
|
1527
|
+
let returning = new Map();
|
|
1528
|
+
// Read as a drag holds them: `projected` is a getter while the track waits for `drag` (#551), whose
|
|
1529
|
+
// track may drive a layout node that arrived with it (#582).
|
|
1530
|
+
const dragMoves = () => {
|
|
1531
|
+
if (options.projected) return NO_KEYS;
|
|
1532
|
+
return UndefinedOr.match(options.dragAxis, {
|
|
1533
|
+
onUndefined: () => NO_KEYS,
|
|
1534
|
+
onDefined: dragMovesOf
|
|
1535
|
+
});
|
|
1536
|
+
};
|
|
1537
|
+
// A Retarget's returns have settled (ADR-0022, D4). A key back at its `style` value is
|
|
1538
|
+
// handed back to the element's style, so a later style change shows at rest and the
|
|
1539
|
+
// next gesture starts from it; any other key rests inline at its Base value and leaves
|
|
1540
|
+
// the target. A key a later Retarget took over is left alone. A routed key (#130) stays
|
|
1541
|
+
// in the gate, handed to the follower, which writes its value from now on.
|
|
1542
|
+
const settleReturns = returns => {
|
|
1543
|
+
// The returns still this Retarget's: a later one took over the rest.
|
|
1544
|
+
const settled = Arr.filter(returns, ([key, source]) => returning.get(key) === source);
|
|
1545
|
+
Arr.forEach(settled, ([key]) => {
|
|
1546
|
+
returning.delete(key);
|
|
1547
|
+
driven.delete(key);
|
|
1548
|
+
owners.set(key, undefined);
|
|
1549
|
+
});
|
|
1550
|
+
const toStyle = Arr.map(Arr.filter(settled, ([, source]) => source === "style"), ([key]) => key);
|
|
1551
|
+
const routedNow = key => UndefinedOr.match(live, {
|
|
1552
|
+
onUndefined: constFalse,
|
|
1553
|
+
onDefined: routes => routes.routes(key)
|
|
1554
|
+
});
|
|
1555
|
+
Arr.forEach(Arr.filter(toStyle, routedNow), key => handBack(key));
|
|
1556
|
+
const handedBack = Arr.filter(toStyle, Predicate.not(routedNow));
|
|
1557
|
+
if (Arr.isReadonlyArrayEmpty(handedBack)) return;
|
|
1558
|
+
// The gate writes the user's current value back, as the element's `style` would
|
|
1559
|
+
// (ADR-0034). A key gone from the user's style by now is cleared, not restored stale.
|
|
1560
|
+
const restore = UndefinedOr.map(styleNow, now => {
|
|
1561
|
+
const style = now();
|
|
1562
|
+
return Object.fromEntries(Arr.map(handedBack, key => [key, Option.match(OwnValues.styleValueOf(style, key), {
|
|
1563
|
+
onNone: () => "",
|
|
1564
|
+
onSome: value => String(value)
|
|
1565
|
+
})]));
|
|
1566
|
+
});
|
|
1567
|
+
gate.release(id, handedBack, restore);
|
|
1568
|
+
Arr.forEach(handedBack, key => {
|
|
1569
|
+
delete snapshot.values[key];
|
|
1570
|
+
delete snapshot.velocities[key];
|
|
1571
|
+
if (Predicate.isNotUndefined(presence)) delete presence.snapshot.current[key];
|
|
1572
|
+
});
|
|
1573
|
+
};
|
|
1574
|
+
// Cold path: once per Retarget that started a key from its Base value or returned one,
|
|
1575
|
+
// run at the head of that Retarget's first leg (no fiber of its own: forking one per
|
|
1576
|
+
// element cost 10-20 µs each at a 1000-element mount).
|
|
1577
|
+
const baseLog = (started, returns) => Effect.logDebug("wardic.base: a key with no value started from, or returned to, its Base value (ADR-0022)").pipe(Effect.annotateLogs({
|
|
1578
|
+
id,
|
|
1579
|
+
started,
|
|
1580
|
+
returned: Object.fromEntries(returns)
|
|
1581
|
+
}));
|
|
1582
|
+
// Each key's leg (#325, Motion's per-key rule): the running leg that draws it, or the last one that
|
|
1583
|
+
// did, landed. A Retarget leaves a key its running leg when it resolves it to the same target, starts
|
|
1584
|
+
// none for a key whose last leg landed there, and starts every other key afresh. Each leg has its
|
|
1585
|
+
// own token (#200, ADR-0027 *Amendment (#200)*), ended once it has no key left: Superseded, not
|
|
1586
|
+
// interrupted, so off the loop at once and its fiber ended normally, at about a sixth of an
|
|
1587
|
+
// interrupt's cost.
|
|
1588
|
+
const owners = new Map();
|
|
1589
|
+
// The keys an Imperative animation took (#433), each with the target the Override stack had for it
|
|
1590
|
+
// then: a Retarget leaves each where the animation leaves it while its target is still that one, and
|
|
1591
|
+
// takes it back once it isn't, as a newer animation of Motion's value takes it (latest-wins).
|
|
1592
|
+
// Every element reads it, nearly none sets it (#460): the shared empty one until the first key taken.
|
|
1593
|
+
let taken = NONE_TAKEN;
|
|
1594
|
+
// The legs that gave up a key in this Retarget: what each still draws is worked out at its end.
|
|
1595
|
+
const losing = [];
|
|
1596
|
+
// The landing every running leg counts toward: the last Retarget's.
|
|
1597
|
+
let current;
|
|
1598
|
+
// A gated Retarget's (ADR-0007 `when`, #325): made at the first.
|
|
1599
|
+
let gated;
|
|
1600
|
+
// The variant name the last started Retarget resolved, for its successor's `definition` (#257).
|
|
1601
|
+
let lastResolution;
|
|
1602
|
+
// The Controls change (#433) it last joined, whether it's still counted there (until a landing),
|
|
1603
|
+
// and the one its last started Retarget ran for: only the first runs on its override.
|
|
1604
|
+
let joined;
|
|
1605
|
+
let counted = false;
|
|
1606
|
+
let startedChange;
|
|
1607
|
+
/** Its Retargets' change is `change` now: it leaves the last, and joins this one, held or not. */
|
|
1608
|
+
const joinChange = change => {
|
|
1609
|
+
if (counted) leave(joined);
|
|
1610
|
+
joined = change;
|
|
1611
|
+
counted = Predicate.isNotUndefined(change);
|
|
1612
|
+
if (counted) join(change);
|
|
1613
|
+
};
|
|
1614
|
+
/** It landed, or can't (a leg failed, its unmount): it leaves its change. */
|
|
1615
|
+
const leaveChange = () => {
|
|
1616
|
+
if (!counted) return;
|
|
1617
|
+
counted = false;
|
|
1618
|
+
leave(joined);
|
|
1619
|
+
};
|
|
1620
|
+
/** It landed: it leaves its change once the gate has flushed its last frame, unless it joined another meanwhile. */
|
|
1621
|
+
const leaveAfterFlush = () => {
|
|
1622
|
+
if (!counted) return;
|
|
1623
|
+
const change = joined;
|
|
1624
|
+
gate.afterFlush(() => {
|
|
1625
|
+
if (joined === change) leaveChange();
|
|
1626
|
+
});
|
|
1627
|
+
};
|
|
1628
|
+
// The element's waiting Transition ends (#508), made at its first: most elements never have one.
|
|
1629
|
+
let waiting;
|
|
1630
|
+
// A leg with no key left ends. Its fiber ends inline (ADR-0027, *Amendment (#200)*); one its token
|
|
1631
|
+
// didn't reach, none of its runs on the loop, is interrupted. A Transition end it is (#508) is
|
|
1632
|
+
// dropped, written never, as its leg was.
|
|
1633
|
+
const endLeg = running => {
|
|
1634
|
+
Supersede.end(running.supersede);
|
|
1635
|
+
if (Predicate.isNotUndefined(waiting)) waiting.drop(running);
|
|
1636
|
+
const fiber = running.fiber;
|
|
1637
|
+
if (Predicate.isUndefined(fiber)) return;
|
|
1638
|
+
if (Predicate.isNotUndefined(fiber.pollUnsafe())) return;
|
|
1639
|
+
// Interrupted here, nothing waiting on its end, as `runCallback`'s interruptor does: a forked
|
|
1640
|
+
// `Fiber.interrupt` was a fiber of its own per ended leg (#618, L2).
|
|
1641
|
+
fiber.interruptUnsafe();
|
|
1642
|
+
};
|
|
1643
|
+
// A leg takes its keys (#325): each key's owner from now on. One callback a spine, not one a leg.
|
|
1644
|
+
let owning;
|
|
1645
|
+
const ownKey = key => {
|
|
1646
|
+
owners.set(key, owning);
|
|
1647
|
+
};
|
|
1648
|
+
const own = running => {
|
|
1649
|
+
const keys = Rec.keys(running.targets);
|
|
1650
|
+
running.count = keys.length;
|
|
1651
|
+
owning = running;
|
|
1652
|
+
Arr.forEach(keys, ownKey);
|
|
1653
|
+
};
|
|
1654
|
+
// The legs drawing each key: a running leg's velocity is read from it (#464).
|
|
1655
|
+
snapshot.owners = owners;
|
|
1656
|
+
// Its time, its provider's Clock's (#460, Q7).
|
|
1657
|
+
snapshot.now = clockNowOf(runtime);
|
|
1658
|
+
// Each key's velocity, at the time the Retarget or Imperative animation reading it read (#464).
|
|
1659
|
+
let readAt = 0;
|
|
1660
|
+
const readVelocity = key => velocityAt(snapshot, owners.get(key), key, readAt);
|
|
1661
|
+
// `key`'s leg gives it up: a leg ends with its last key, and draws only the rest before.
|
|
1662
|
+
const giveUp = (key, running) => {
|
|
1663
|
+
letGo(snapshot, key, running);
|
|
1664
|
+
owners.set(key, undefined);
|
|
1665
|
+
if (running.done) return;
|
|
1666
|
+
running.count--;
|
|
1667
|
+
if (running.count === 0) return endLeg(running);
|
|
1668
|
+
if (running.losing) return;
|
|
1669
|
+
running.losing = true;
|
|
1670
|
+
losing.push(running);
|
|
1671
|
+
};
|
|
1672
|
+
// The keys the Retarget being worked out resolves, for `giveUpUnresolved`: one callback a spine,
|
|
1673
|
+
// not one a Retarget.
|
|
1674
|
+
let resolvedNow = NO_VALUES;
|
|
1675
|
+
// Whether `running` is whole: it still draws every key it was started for, each held now, resolved
|
|
1676
|
+
// by the Retarget being worked out or taken by its Imperative animation. A key its Retarget didn't
|
|
1677
|
+
// resolve, a Path's turn or the axis its target leaves out (#438), is the leg's own: not counted.
|
|
1678
|
+
const holdsWhole = running => Arr.every(Rec.keys(running.targets), key => {
|
|
1679
|
+
if (taken.has(key)) return owners.get(key) === running;
|
|
1680
|
+
if (Bool.not(Object.hasOwn(running.resolution.resolved, key))) return true;
|
|
1681
|
+
return Bool.and(owners.get(key) === running, Object.hasOwn(resolvedNow, key));
|
|
1682
|
+
});
|
|
1683
|
+
const giveUpUnresolved = (owner, key) => {
|
|
1684
|
+
if (Predicate.isUndefined(owner)) return;
|
|
1685
|
+
// An Imperative animation's key (#433) is its own while taken.
|
|
1686
|
+
if (taken.has(key)) return;
|
|
1687
|
+
if (Object.hasOwn(resolvedNow, key)) return;
|
|
1688
|
+
if (Object.hasOwn(owner.resolution.resolved, key)) return giveUp(key, owner);
|
|
1689
|
+
// A key its leg draws though its own Retarget didn't resolve it rides on with that leg while the
|
|
1690
|
+
// leg is whole (#460, ADR-0065): a Retarget of another key leaves a Path as it was. Once the leg
|
|
1691
|
+
// loses a key, its turn goes back to 0 (`turnBack`) and an axis its target left out stays.
|
|
1692
|
+
if (holdsWhole(owner)) return;
|
|
1693
|
+
giveUp(key, owner);
|
|
1694
|
+
};
|
|
1695
|
+
// A Path's turn goes back to 0 once no leg draws it (#460, ADR-0065 decision 3): after a Retarget
|
|
1696
|
+
// whose legs don't turn, a stop, a cancel. Most elements never turn: a guard.
|
|
1697
|
+
const turnBack = () => {
|
|
1698
|
+
const turn = snapshot.values[PATH_ROTATION];
|
|
1699
|
+
if (Bool.or(Predicate.isUndefined(turn), turn === 0)) return;
|
|
1700
|
+
if (Predicate.isNotUndefined(owners.get(PATH_ROTATION))) return;
|
|
1701
|
+
snapshot.values = {
|
|
1702
|
+
...snapshot.values,
|
|
1703
|
+
...TURNED_BACK
|
|
1704
|
+
};
|
|
1705
|
+
snapshot.velocities = {
|
|
1706
|
+
...snapshot.velocities,
|
|
1707
|
+
[PATH_ROTATION]: 0
|
|
1708
|
+
};
|
|
1709
|
+
snapshot.drawnAt[PATH_ROTATION] = snapshot.now();
|
|
1710
|
+
gate.write(id, TURNED_BACK);
|
|
1711
|
+
recordFrame(TURNED_BACK);
|
|
1712
|
+
};
|
|
1713
|
+
// Each leg that gave up keys draws the ones it kept from now on: once per such leg, a Retarget.
|
|
1714
|
+
const keepTheRest = () => {
|
|
1715
|
+
if (losing.length === 0) return;
|
|
1716
|
+
Arr.forEach(losing, running => {
|
|
1717
|
+
running.losing = false;
|
|
1718
|
+
if (running.count === 0) return;
|
|
1719
|
+
const kept = Arr.filter(Rec.keys(running.targets), key => owners.get(key) === running);
|
|
1720
|
+
running.values = keepingOnly(kept);
|
|
1721
|
+
running.velocities = keepingOnly(kept);
|
|
1722
|
+
});
|
|
1723
|
+
losing.length = 0;
|
|
1724
|
+
};
|
|
1725
|
+
/**
|
|
1726
|
+
* Where `key` starts toward `like` (ADR-0024, D1; ADR-0022, D3): its Snapshot value, coerced to its
|
|
1727
|
+
* target's shape; one of another type on a positional key as it is, a Measured pair (#430); else
|
|
1728
|
+
* its Base value's start link, read at its first need, noted in `started`; with none, at its target
|
|
1729
|
+
* (no motion). Guards, not a match: per key, per Retarget, and a key with a value builds nothing.
|
|
1730
|
+
*/
|
|
1731
|
+
const startKey = (key, like, started) => {
|
|
1732
|
+
const coerced = OwnValues.valueLike(snapshot.values[key], like);
|
|
1733
|
+
if (Option.isSome(coerced)) snapshot.values[key] = coerced.value;
|
|
1734
|
+
// A start of another type than its target's, on a positional key, stays as it is: a Measured
|
|
1735
|
+
// pair (#430), measured at the end of the task.
|
|
1736
|
+
if (Option.isSome(coerced)) return;
|
|
1737
|
+
if (keepsStart(key, snapshot.values[key], like)) return;
|
|
1738
|
+
const link = startLinkOf(key, like);
|
|
1739
|
+
if (Option.isSome(link) && isSameKind(link.value.value, like)) {
|
|
1740
|
+
snapshot.values[key] = link.value.value;
|
|
1741
|
+
started[key] = link.value.source;
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
snapshot.values[key] = like;
|
|
1745
|
+
started[key] = "target";
|
|
1746
|
+
};
|
|
1747
|
+
// A key's leg ended by a failure (#257 item 4): nothing draws its keys, so a later Retarget starts them afresh.
|
|
1748
|
+
const forget = running => Arr.forEach(Rec.keys(running.targets), key => {
|
|
1749
|
+
if (owners.get(key) !== running) return;
|
|
1750
|
+
letGo(snapshot, key, running);
|
|
1751
|
+
owners.set(key, undefined);
|
|
1752
|
+
});
|
|
1753
|
+
/**
|
|
1754
|
+
* A leg's run into its sink: one dispatcher, each sink built for the leg that needs it, a
|
|
1755
|
+
* Retarget's and an Imperative animation's (#433). A blend's machine is built under the element's
|
|
1756
|
+
* Key rules when its change holds a Variable value (`variables`, #542).
|
|
1757
|
+
*/
|
|
1758
|
+
const legProgram = (leg, running, variables) => {
|
|
1759
|
+
if (leg._tag === "Follow") {
|
|
1760
|
+
const key = leg.key;
|
|
1761
|
+
const out = {
|
|
1762
|
+
[key]: 0
|
|
1763
|
+
};
|
|
1764
|
+
// Per leg (#460): Machine's calls data-first; per frame, statements.
|
|
1765
|
+
return Effect.suspend(() => Machine.run(leg.machine(), frame => {
|
|
1766
|
+
out[key] = frame.value;
|
|
1767
|
+
snapshot.values[key] = frame.value;
|
|
1768
|
+
let velocity = frame.velocity;
|
|
1769
|
+
if (Predicate.isUndefined(velocity)) velocity = 0;
|
|
1770
|
+
snapshot.velocities[key] = velocity;
|
|
1771
|
+
gate.write(id, out);
|
|
1772
|
+
recordFrame(out);
|
|
1773
|
+
drew(running, frame.done, snapshot.now());
|
|
1774
|
+
if (frame.done) landEndsOf(waiting);
|
|
1775
|
+
return undefined;
|
|
1776
|
+
}, running));
|
|
1777
|
+
}
|
|
1778
|
+
if (leg._tag === "Numbers") {
|
|
1779
|
+
return Effect.suspend(() => Machine.run(leg.machine(), frame => {
|
|
1780
|
+
// MULTI-OWNER MERGE (ADR-0004): merge the spring's keys into the snapshot
|
|
1781
|
+
// rather than replacing it, so the drag's direct-set x/y survive alongside the
|
|
1782
|
+
// spring's keys (drag owns x/y, spring owns the rest) and the post-drag
|
|
1783
|
+
// handoff continues from the rested position. Only the keys it still draws (#325).
|
|
1784
|
+
const value = running.values(frame.value);
|
|
1785
|
+
snapshot.values = {
|
|
1786
|
+
...snapshot.values,
|
|
1787
|
+
...value
|
|
1788
|
+
};
|
|
1789
|
+
snapshot.velocities = {
|
|
1790
|
+
...snapshot.velocities,
|
|
1791
|
+
...running.velocities(frame.velocity)
|
|
1792
|
+
};
|
|
1793
|
+
gate.write(id, value);
|
|
1794
|
+
recordFrame(value);
|
|
1795
|
+
drew(running, frame.done, snapshot.now());
|
|
1796
|
+
if (frame.done) landEndsOf(waiting);
|
|
1797
|
+
return undefined;
|
|
1798
|
+
}, running));
|
|
1799
|
+
}
|
|
1800
|
+
// A snap's or a blend's frames: merged into the Snapshot (ADR-0004), as the spring's are. A blend's
|
|
1801
|
+
// last two are kept, its keys' velocities read from them (#464): the frame's own values, which a
|
|
1802
|
+
// blend makes anew each frame (`values` writes one object for a leg that lost keys).
|
|
1803
|
+
const sink = frame => {
|
|
1804
|
+
const value = running.values(frame.value);
|
|
1805
|
+
let before = running.last;
|
|
1806
|
+
let beforeAt = running.lastAt;
|
|
1807
|
+
// Its first frame: from the Snapshot's values, a nominal frame before it.
|
|
1808
|
+
if (Predicate.isUndefined(before)) {
|
|
1809
|
+
before = snapshot.values;
|
|
1810
|
+
beforeAt = snapshot.now() - NOMINAL_FRAME;
|
|
1811
|
+
}
|
|
1812
|
+
running.before = before;
|
|
1813
|
+
running.beforeAt = beforeAt;
|
|
1814
|
+
running.last = frame.value;
|
|
1815
|
+
snapshot.values = {
|
|
1816
|
+
...snapshot.values,
|
|
1817
|
+
...value
|
|
1818
|
+
};
|
|
1819
|
+
gate.write(id, value);
|
|
1820
|
+
recordFrame(value);
|
|
1821
|
+
drew(running, frame.done, snapshot.now());
|
|
1822
|
+
if (frame.done) landEndsOf(waiting);
|
|
1823
|
+
return undefined;
|
|
1824
|
+
};
|
|
1825
|
+
if (leg._tag === "Snap") {
|
|
1826
|
+
// A snapped key comes to rest, so a later spring starts it at rest.
|
|
1827
|
+
snapshot.velocities = {
|
|
1828
|
+
...snapshot.velocities,
|
|
1829
|
+
...Rec.fromEntries(Arr.map(leg.keys, key => [key, 0]))
|
|
1830
|
+
};
|
|
1831
|
+
return Effect.suspend(() => Machine.run(leg.machine(), sink, running));
|
|
1832
|
+
}
|
|
1833
|
+
// Per leg (#460): a statement, Effect's calls data-first.
|
|
1834
|
+
let built = Effect.suspend(leg.machine);
|
|
1835
|
+
if (variables) built = InterpolatorRegistry.withKeyRules(built, elementRules);
|
|
1836
|
+
return Effect.flatMap(built, machine => Machine.run(machine, sink, running));
|
|
1837
|
+
};
|
|
1838
|
+
// A leg's end, told its landing: a Retarget's legs' and an Imperative animation's (#433).
|
|
1839
|
+
const legEnded = running => exit => {
|
|
1840
|
+
// Its fiber has ended, and is let go: a leg kept for its keys' velocity (#464) keeps no fiber alive.
|
|
1841
|
+
running.fiber = undefined;
|
|
1842
|
+
// Per leg (#460): statements.
|
|
1843
|
+
if (Exit.isSuccess(exit)) {
|
|
1844
|
+
// A Superseded leg (#200) counts toward nothing, nor tells a name: the next Retarget's legs
|
|
1845
|
+
// land. Nothing made for it: a Retarget ends its element's legs inline.
|
|
1846
|
+
const end = exit.value;
|
|
1847
|
+
if (Supersede.isSuperseded(end)) return Effect.void;
|
|
1848
|
+
return Effect.sync(() => {
|
|
1849
|
+
running.landing.settled();
|
|
1850
|
+
const tell = running.names;
|
|
1851
|
+
if (Predicate.isNotUndefined(tell)) tell(end);
|
|
1852
|
+
});
|
|
1853
|
+
}
|
|
1854
|
+
// A leg its token didn't reach is interrupted: its keys are given up already, and it isn't a failure.
|
|
1855
|
+
const cause = exit.cause;
|
|
1856
|
+
if (Cause.hasInterruptsOnly(cause)) return Effect.void;
|
|
1857
|
+
return Report.failure("wardic.spine: a leg failed", cause).pipe(Effect.annotateLogs({
|
|
1858
|
+
id
|
|
1859
|
+
}), Effect.andThen(Effect.sync(() => {
|
|
1860
|
+
forget(running);
|
|
1861
|
+
running.landing.failed(cause);
|
|
1862
|
+
})));
|
|
1863
|
+
};
|
|
1864
|
+
// A gated Retarget (ADR-0007 `when`, #325): a running key it resolves to its leg's target runs on,
|
|
1865
|
+
// the element reported unsettled meanwhile, when an earlier change started that leg; every other
|
|
1866
|
+
// running key freezes where it is. The change the gate holds may have started legs just before
|
|
1867
|
+
// it shut (a child Retargets before its provider's effect resets its `beforeChildren` wait; an
|
|
1868
|
+
// `afterChildren` provider starts before its children report): those freeze too, as before.
|
|
1869
|
+
const hold = resolution => {
|
|
1870
|
+
if (Predicate.isUndefined(gated)) gated = gatedLandingOf(onFrame);
|
|
1871
|
+
const landing = gated;
|
|
1872
|
+
const resolved = resolution.resolved;
|
|
1873
|
+
current = landing;
|
|
1874
|
+
owners.forEach((running, key) => {
|
|
1875
|
+
if (Predicate.isUndefined(running)) return;
|
|
1876
|
+
if (running.done) return;
|
|
1877
|
+
// An Imperative animation's key (#433) is its own while taken.
|
|
1878
|
+
if (taken.has(key)) return;
|
|
1879
|
+
if (Object.hasOwn(resolved, key) && running.targets[key] === resolved[key] && !sameResolution(running.resolution, resolution)) {
|
|
1880
|
+
running.landing = landing;
|
|
1881
|
+
running.names = undefined;
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
giveUp(key, running);
|
|
1885
|
+
});
|
|
1886
|
+
keepTheRest();
|
|
1887
|
+
};
|
|
1888
|
+
// The translate targets of the last Retarget that ran, held or not: what a takeover of the drag's
|
|
1889
|
+
// release looks for a change in (#340).
|
|
1890
|
+
let lastX = undefined;
|
|
1891
|
+
let lastY = undefined;
|
|
1892
|
+
// A Retarget took `x`/`y` from the release, and the hand-back of `dragging` hasn't come yet.
|
|
1893
|
+
let tookRelease = false;
|
|
1894
|
+
/**
|
|
1895
|
+
* Whether the drag holds `x`/`y` for this Retarget (ADR-0004): while its pointer is down and
|
|
1896
|
+
* through its release, unless this Retarget gives the release's axis a new target. Then it takes
|
|
1897
|
+
* them from the release (#340, ADR-0016 *Amendment (#340)*), as a newer animation of Motion's value
|
|
1898
|
+
* stops the one running, and they go on from where the release has them, at its velocity. A key a
|
|
1899
|
+
* entry stops setting is no new target: it stays where the drag dropped it (ADR-0022).
|
|
1900
|
+
*/
|
|
1901
|
+
const dragHolds = resolution => {
|
|
1902
|
+
const {
|
|
1903
|
+
x,
|
|
1904
|
+
y
|
|
1905
|
+
} = resolution.resolved;
|
|
1906
|
+
// Per Retarget (#460, compose once): statements.
|
|
1907
|
+
const newX = Predicate.isNotUndefined(x) && x !== lastX;
|
|
1908
|
+
const newY = Predicate.isNotUndefined(y) && y !== lastY;
|
|
1909
|
+
lastX = x;
|
|
1910
|
+
lastY = y;
|
|
1911
|
+
if (!resolution.dragging) return false;
|
|
1912
|
+
// From a takeover to the hand-back of `dragging` at the end of its task, the drag holds nothing.
|
|
1913
|
+
if (tookRelease) return false;
|
|
1914
|
+
const drag = options.drag;
|
|
1915
|
+
if (Predicate.isUndefined(drag)) return true;
|
|
1916
|
+
if (!newX && !newY) return true;
|
|
1917
|
+
tookRelease = drag.takeRelease({
|
|
1918
|
+
x: newX,
|
|
1919
|
+
y: newY
|
|
1920
|
+
});
|
|
1921
|
+
return !tookRelease;
|
|
1922
|
+
};
|
|
1923
|
+
const retarget = given => {
|
|
1924
|
+
// A Controls change (#433): the element is in it from the Retarget it makes it run, held or not.
|
|
1925
|
+
if (given.change !== joined) joinChange(given.change);
|
|
1926
|
+
// `when` start-gate (ADR-0007): when canStart() is false, the keys whose target changed freeze
|
|
1927
|
+
// where they are (#325: the rest run on), and the element waits; the binding retargets once
|
|
1928
|
+
// the gate flips true.
|
|
1929
|
+
if (Predicate.isNotUndefined(canStart) && !canStart()) {
|
|
1930
|
+
hold(given);
|
|
1931
|
+
// Report NOT settled: a gated child sits at its snapshot, still
|
|
1932
|
+
// owing an animation, so it must not count as settled (afterChildren).
|
|
1933
|
+
if (Predicate.isNotUndefined(onFrame)) onFrame(false);
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
// The first Retarget a Controls change starts here runs on its override (#433); a later one, a
|
|
1937
|
+
// gesture's, on the targets' own.
|
|
1938
|
+
let resolution = given;
|
|
1939
|
+
// On an override, every key starts again on it, a running leg toward the same target too: `set`
|
|
1940
|
+
// lands it at once, as Motion's.
|
|
1941
|
+
let restarting = false;
|
|
1942
|
+
if (given.change !== startedChange) {
|
|
1943
|
+
startedChange = given.change;
|
|
1944
|
+
const override = UndefinedOr.map(given.change, change => change.override);
|
|
1945
|
+
if (Predicate.isNotUndefined(override)) {
|
|
1946
|
+
resolution = overriddenOf(given, override);
|
|
1947
|
+
restarting = true;
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
const {
|
|
1951
|
+
resolved,
|
|
1952
|
+
base
|
|
1953
|
+
} = resolution;
|
|
1954
|
+
// The hand-back of `dragging` after a takeover (#340): the last Retarget already ran with `x`/`y`
|
|
1955
|
+
// its own, so one that changes nothing else is no new animation, as Motion's has none. It goes
|
|
1956
|
+
// on, and lands and is told as itself.
|
|
1957
|
+
if (tookRelease && !resolution.dragging) {
|
|
1958
|
+
tookRelease = false;
|
|
1959
|
+
if (handsBackOnly(resolution, lastResolution)) {
|
|
1960
|
+
lastResolution = resolution;
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
const held = dragHolds(resolution);
|
|
1965
|
+
// The keys an Imperative animation took (#433): one whose target here isn't the one it had when
|
|
1966
|
+
// taken is the Override stack's again.
|
|
1967
|
+
if (taken.size > 0) Iter.forEach(taken, ([key, was]) => {
|
|
1968
|
+
if (resolved[key] !== was) taken.delete(key);
|
|
1969
|
+
});
|
|
1970
|
+
// A key a Retarget drove and no entry sets now returns to its Base value
|
|
1971
|
+
// (ADR-0022); with none, it stays where it is (as before #47).
|
|
1972
|
+
const t = {
|
|
1973
|
+
...resolved
|
|
1974
|
+
};
|
|
1975
|
+
Arr.forEach(Rec.keys(resolved), key => {
|
|
1976
|
+
driven.set(key, resolved[key]);
|
|
1977
|
+
});
|
|
1978
|
+
if (held) Arr.forEach(dragMoves(), key => driven.delete(key));
|
|
1979
|
+
returning = new Map();
|
|
1980
|
+
// Over the Map itself: copying it into an array first costs ~20 times the walk, per element
|
|
1981
|
+
// per Retarget (#69's PR 4). Deleting the entry being visited is safe in a Map's iteration.
|
|
1982
|
+
Iter.forEach(driven, ([key, like]) => {
|
|
1983
|
+
// A translate key the strip below holds back returns once the drag lets go.
|
|
1984
|
+
if (Object.hasOwn(resolved, key) || held && TRANSLATE_KEYS.has(key)) return;
|
|
1985
|
+
// One an Imperative animation holds (#433) stays where it leaves it.
|
|
1986
|
+
if (taken.has(key)) return;
|
|
1987
|
+
const back = BaseValue.of(key, {
|
|
1988
|
+
base,
|
|
1989
|
+
initial: initialLink,
|
|
1990
|
+
started: startedLink,
|
|
1991
|
+
...linksFor(like)
|
|
1992
|
+
});
|
|
1993
|
+
if (Option.isNone(back)) {
|
|
1994
|
+
driven.delete(key);
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1997
|
+
t[key] = back.value.value;
|
|
1998
|
+
returning.set(key, back.value.source);
|
|
1999
|
+
});
|
|
2000
|
+
// MULTI-OWNER strip (ADR-0004): while dragging, x/y are DIRECT-SET by the
|
|
2001
|
+
// drag track, so strip the translate keys from the spring's target — the
|
|
2002
|
+
// spring must never fight the direct-set. Once dragging is false the
|
|
2003
|
+
// keys re-enter normally (post-drag handoff: the spring continues x/y only
|
|
2004
|
+
// if `animate` sets them, from the snapshot's rested position).
|
|
2005
|
+
if (held) Arr.forEach(TRANSLATE_KEY_LIST, key => delete t[key]);
|
|
2006
|
+
// Every key an Imperative animation holds stays where it leaves it (#433).
|
|
2007
|
+
if (taken.size > 0) Iter.forEach(taken, ([key]) => {
|
|
2008
|
+
delete t[key];
|
|
2009
|
+
});
|
|
2010
|
+
// The keys this Retarget returns; once it lands, a key back at its `style` value is
|
|
2011
|
+
// handed back to the element's style (D4) and the rest rest inline.
|
|
2012
|
+
const returns = [...returning];
|
|
2013
|
+
// The transition, read at Retarget time so a change applies to the next Retarget. A child
|
|
2014
|
+
// with no local transition inherits the parent context's (ADR-0007).
|
|
2015
|
+
const c = config();
|
|
2016
|
+
// This Retarget's landing (#257, #325): it lands when every leg drawing a key it resolves has
|
|
2017
|
+
// settled, its own and the ones it carries. A leg's end, told apart (ADR-0027, decision 7): a
|
|
2018
|
+
// settle counts; a Superseded end (a Retarget, an unmount, #200) or an interruption (a leg its
|
|
2019
|
+
// token didn't reach) is nothing; anything else (a step or a sink that threw, the Frame loop's
|
|
2020
|
+
// own failure) is logged and reported (ADR-0030, decision 4), and doesn't count.
|
|
2021
|
+
let legs = 0;
|
|
2022
|
+
// The variant the Retarget before this one resolved, set once this one starts (#257).
|
|
2023
|
+
let previous;
|
|
2024
|
+
const legDone = () => {
|
|
2025
|
+
if (current !== landing) return;
|
|
2026
|
+
if (--legs !== 0) return;
|
|
2027
|
+
settleReturns(returns);
|
|
2028
|
+
// The Retarget settled with its last leg (#257): told once the gate has flushed its last frame,
|
|
2029
|
+
// so the element shows where it landed. Its Controls change hears it then too (#433).
|
|
2030
|
+
if (Predicate.isNotUndefined(animation)) gate.afterFlush(() => animation.settled(resolution, previous, c));
|
|
2031
|
+
leaveAfterFlush();
|
|
2032
|
+
};
|
|
2033
|
+
// A leg's failure (#257 item 4): the Retarget can't land, so a binding waiting on it is told,
|
|
2034
|
+
// once, at once: a leg that fails before it writes leaves no flush to wait for. A leg failing
|
|
2035
|
+
// as it's built, before `started` is told, is told right after it.
|
|
2036
|
+
let failedTold = false;
|
|
2037
|
+
let startedTold = false;
|
|
2038
|
+
let failedEarly;
|
|
2039
|
+
const tellFailed = error => {
|
|
2040
|
+
const hooks = animation;
|
|
2041
|
+
// Called on its hooks, which may be a class's: not taken off them.
|
|
2042
|
+
if (Predicate.isNotUndefined(hooks.failed)) hooks.failed(resolution, error);
|
|
2043
|
+
};
|
|
2044
|
+
const legFailed = cause => {
|
|
2045
|
+
// It can't land: its Controls change waits for it no longer (#433).
|
|
2046
|
+
if (current === landing) leaveChange();
|
|
2047
|
+
if (failedTold || Predicate.isUndefined(animation)) return;
|
|
2048
|
+
failedTold = true;
|
|
2049
|
+
const error = Cause.squash(cause);
|
|
2050
|
+
if (startedTold) return tellFailed(error);
|
|
2051
|
+
failedEarly = {
|
|
2052
|
+
error
|
|
2053
|
+
};
|
|
2054
|
+
};
|
|
2055
|
+
// The element settles with its last leg (ADR-0024, D5): a string leg can outlast the
|
|
2056
|
+
// numeric one, so each leg's frames report, and only the last leg's settle reports done.
|
|
2057
|
+
let reporting = 0;
|
|
2058
|
+
let settled = 0;
|
|
2059
|
+
const report = done => {
|
|
2060
|
+
if (done) settled++;
|
|
2061
|
+
if (Predicate.isNotUndefined(onFrame)) onFrame(settled === reporting);
|
|
2062
|
+
};
|
|
2063
|
+
const landing = {
|
|
2064
|
+
report,
|
|
2065
|
+
settled: legDone,
|
|
2066
|
+
failed: legFailed
|
|
2067
|
+
};
|
|
2068
|
+
current = landing;
|
|
2069
|
+
// The Retarget's transitions, read before its keys: a key already there asks its own for a
|
|
2070
|
+
// velocity (#448).
|
|
2071
|
+
const elementTransition = ownOrInherited(c.transition, parent);
|
|
2072
|
+
// The base target's own transition (#277): the keys its entry drives animate on it.
|
|
2073
|
+
const baseTransition = transitionOfTarget(resolution.transition, elementTransition);
|
|
2074
|
+
// Fold the per-child stagger delay (ADR-0007) into the effective
|
|
2075
|
+
// transition.delay = base.delay + computedDelay. extraDelay() is read
|
|
2076
|
+
// at Retarget time so a re-snapshot before this start is reflected. Each name's keys take that
|
|
2077
|
+
// name's delay (#297): the base's, its first name's.
|
|
2078
|
+
const layers = resolution.layers;
|
|
2079
|
+
const extra = extraOf(extraDelay, layers[0]);
|
|
2080
|
+
const transition = staggeredOf(baseTransition, extra, options.reuse);
|
|
2081
|
+
// With an entry's own transition (#277, #291), each key animates on its entry's: the base's keys
|
|
2082
|
+
// on the base target's, each active gesture's on its target's, else the element's, as Motion's
|
|
2083
|
+
// each animation type runs on its own.
|
|
2084
|
+
// A list's names (#297) split them too, each name's at its own delay; a list's returns run on the
|
|
2085
|
+
// element's transition, in a group of their own, last.
|
|
2086
|
+
// Guards, not matches: per Retarget, per element. A list's work (#297) is done apart, for a list:
|
|
2087
|
+
// the Retarget's other calls keep their inlining (docs/agents/effect-first.md).
|
|
2088
|
+
const listed = Arr.isArray(resolution.variant);
|
|
2089
|
+
// A list's names each wait for their own `when` (#297's PR 2): the entries whose gate is shut now.
|
|
2090
|
+
let shut;
|
|
2091
|
+
if (listed) shut = shutOf(layers, byName);
|
|
2092
|
+
// Every key the Retarget resolves goes in its entry's group, the ones that stay too (#325): a
|
|
2093
|
+
// name's settle waits for them.
|
|
2094
|
+
const groups = keysByLayerOf(t, layers, extraDelay, extra, listed, shut);
|
|
2095
|
+
// Per key (#325, Motion's): a key whose running leg heads where this Retarget resolves it runs
|
|
2096
|
+
// on, counted toward this landing; one whose last leg landed there stays; every other's leg
|
|
2097
|
+
// gives it up, and it starts from its Snapshot value, coerced to its target's shape (ADR-0024,
|
|
2098
|
+
// D1). A key with no value yet, or one whose value can't take that shape, starts from its Base
|
|
2099
|
+
// value's start links, read here at its first need (ADR-0022, D3); with none, it starts at its
|
|
2100
|
+
// target (no motion).
|
|
2101
|
+
//
|
|
2102
|
+
// Every key's Own value is read first, at its first need, before anything writes it, so a return
|
|
2103
|
+
// later finds the element's value, not Wardic's (ADR-0022, D3). The read is kept: a later need is
|
|
2104
|
+
// a lookup. A transform key reads nothing.
|
|
2105
|
+
let stays;
|
|
2106
|
+
let carried;
|
|
2107
|
+
let there;
|
|
2108
|
+
const started = {};
|
|
2109
|
+
// Each key's Keyframes (#429), when any entry gives some: a key's carries on only toward the same.
|
|
2110
|
+
const keyframesNow = resolution.keyframes;
|
|
2111
|
+
// The keys whose two ends may be a Measured pair (#430), found in the pass below.
|
|
2112
|
+
let measuring;
|
|
2113
|
+
// Each key's velocity, read now (#464), for a key a spring starts or one already there.
|
|
2114
|
+
readAt = snapshot.now();
|
|
2115
|
+
// Where a Path's axis this target leaves out rests (#574), before the pass below gives up its leg.
|
|
2116
|
+
const rests = restsOf(owners, t);
|
|
2117
|
+
Arr.forEach(Rec.keys(t), key => {
|
|
2118
|
+
if (!Object.hasOwn(initialValues, key)) ownValue(key);
|
|
2119
|
+
const like = t[key];
|
|
2120
|
+
const owner = owners.get(key);
|
|
2121
|
+
const stops = keyframesAtOf(keyframesNow, key);
|
|
2122
|
+
// A leg drawing it toward another target: it's moving, so it's never already there (#448).
|
|
2123
|
+
let drawn = false;
|
|
2124
|
+
if (Predicate.isNotUndefined(owner)) {
|
|
2125
|
+
drawn = !owner.done;
|
|
2126
|
+
// A key whose Transition end changed starts again (#470), as Motion's value does, its end in
|
|
2127
|
+
// its resolved values.
|
|
2128
|
+
if (owner.targets[key] === like && !restarting && sameKeyframesAt(keyframesAtOf(owner.resolution.keyframes, key), stops) && !endMoved(lastResolution, resolution, key)) {
|
|
2129
|
+
if (Predicate.isUndefined(stays)) stays = new Set();
|
|
2130
|
+
stays.add(key);
|
|
2131
|
+
if (owner.done || owner.landing === landing) return;
|
|
2132
|
+
owner.landing = landing;
|
|
2133
|
+
owner.names = undefined;
|
|
2134
|
+
legs++;
|
|
2135
|
+
reporting++;
|
|
2136
|
+
if (Predicate.isUndefined(carried)) carried = [];
|
|
2137
|
+
carried.push(owner);
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
giveUp(key, owner);
|
|
2141
|
+
}
|
|
2142
|
+
startKey(key, like, started);
|
|
2143
|
+
// A Measured pair (#430): its two ends of different types, found in this pass, so a Retarget
|
|
2144
|
+
// with none builds nothing for them.
|
|
2145
|
+
if (MeasuredPair.needs(key, UndefinedOr.getOrThrow(snapshot.values[key]), like)) {
|
|
2146
|
+
if (Predicate.isUndefined(measuring)) measuring = [];
|
|
2147
|
+
measuring.push(key);
|
|
2148
|
+
}
|
|
2149
|
+
// Already there (#448, Motion's `visual-element-target.ts`): a key at its target, coerced to its
|
|
2150
|
+
// shape, with no leg drawing it, at rest and given no velocity by its transition, starts none.
|
|
2151
|
+
// It stays, as a carried key does, and is written once more (below), as Motion sets it on the
|
|
2152
|
+
// next frame. One that started at its target had no value to show, so its leg writes it, as
|
|
2153
|
+
// Motion's does for a value it has none of. Keyframes are never there (#429): they play.
|
|
2154
|
+
// Its velocity read last, for a key there alone (#464): per key, per Retarget.
|
|
2155
|
+
let still = !drawn && started[key] !== "target";
|
|
2156
|
+
if (still) still = snapshot.values[key] === like;
|
|
2157
|
+
if (still) still = readVelocity(key) === 0;
|
|
2158
|
+
// Its transition asked last, for a key already there alone: per key, per Retarget. A quiet
|
|
2159
|
+
// mount's never asks (#475): Motion animates nothing at a first render that starts at its
|
|
2160
|
+
// `animate`, whatever velocity its transition gives (`animation-state.ts`, `shouldAnimate`).
|
|
2161
|
+
if (still && Predicate.isUndefined(stops) && (quiet || !givesVelocity(keyTransitionOf(resolution, groups, key, transition, elementTransition), key))) {
|
|
2162
|
+
if (Predicate.isUndefined(stays)) stays = new Set();
|
|
2163
|
+
stays.add(key);
|
|
2164
|
+
if (Predicate.isUndefined(there)) there = {};
|
|
2165
|
+
there[key] = like;
|
|
2166
|
+
}
|
|
2167
|
+
// A quiet mount's Keyframes (#429): Motion animates nothing at a first render that starts at its
|
|
2168
|
+
// `animate`, so they stay where they start, `animate`'s last stop with `initial={false}`.
|
|
2169
|
+
if (quiet && Predicate.isNotUndefined(stops)) {
|
|
2170
|
+
if (Predicate.isUndefined(stays)) stays = new Set();
|
|
2171
|
+
stays.add(key);
|
|
2172
|
+
if (Predicate.isUndefined(there)) there = {};
|
|
2173
|
+
there[key] = UndefinedOr.getOrThrow(snapshot.values[key]);
|
|
2174
|
+
}
|
|
2175
|
+
});
|
|
2176
|
+
// A key no longer resolved (one the drag holds, or one with no Base value) is given up: it stays
|
|
2177
|
+
// where it is.
|
|
2178
|
+
resolvedNow = t;
|
|
2179
|
+
owners.forEach(giveUpUnresolved);
|
|
2180
|
+
keepTheRest();
|
|
2181
|
+
// The keys this Retarget starts legs for: all of them, unless some stay.
|
|
2182
|
+
let fresh = t;
|
|
2183
|
+
if (Predicate.isNotUndefined(stays)) {
|
|
2184
|
+
const kept = stays;
|
|
2185
|
+
fresh = Rec.filter(t, (_, key) => !kept.has(key));
|
|
2186
|
+
// A Path couples `x` and `y` (#438): either retargeted, the other goes along it to its target.
|
|
2187
|
+
fresh = withPathAxes(fresh, t, transition);
|
|
2188
|
+
}
|
|
2189
|
+
// A mount that starts at its `animate`, with nothing to animate, tells no one (#448, Motion's):
|
|
2190
|
+
// no start, no landing, and no list's names. It starts no leg, so it lands at once.
|
|
2191
|
+
const silent = quiet && Rec.isEmptyRecord(fresh) && Predicate.isUndefined(carried);
|
|
2192
|
+
quiet = false;
|
|
2193
|
+
// A key only a Transition end sets (#428) starts no leg of its own: its entry's end leg holds it
|
|
2194
|
+
// where it is, and sets it once the entry's animated keys land.
|
|
2195
|
+
const ends = resolution.ends;
|
|
2196
|
+
let freshEnds = NO_VALUES;
|
|
2197
|
+
if (Predicate.isNotUndefined(ends)) {
|
|
2198
|
+
const endOnly = ends.endOnly;
|
|
2199
|
+
freshEnds = Rec.filter(fresh, (_, key) => endOnly.has(key));
|
|
2200
|
+
if (hasKeys(freshEnds)) fresh = Rec.filter(fresh, (_, key) => !endOnly.has(key));
|
|
2201
|
+
}
|
|
2202
|
+
let from = Rec.map(fresh, (_, key) => UndefinedOr.getOrThrow(snapshot.values[key]));
|
|
2203
|
+
// Keyframes (#429) start at their first stop, a `null` one where the key is; those of more than
|
|
2204
|
+
// two stops run through them.
|
|
2205
|
+
let manyStops;
|
|
2206
|
+
if (Predicate.isNotUndefined(keyframesNow)) {
|
|
2207
|
+
const begun = keyframesFrom(from, fresh, Rec.map(keyframesNow, at => at.stops));
|
|
2208
|
+
from = begun.from;
|
|
2209
|
+
manyStops = begun.stops;
|
|
2210
|
+
}
|
|
2211
|
+
// Each leg: the base-value log at the head of the first, and, once the leg's run
|
|
2212
|
+
// settles, a count toward this landing, so the per-frame handlers stay as they were.
|
|
2213
|
+
let pendingLog;
|
|
2214
|
+
if (returns.length > 0 || !Rec.isEmptyRecord(started)) pendingLog = baseLog(started, returns);
|
|
2215
|
+
// A list's names told settled one by one (#297, Solid 1's callbacks): each as the legs of the keys
|
|
2216
|
+
// it drives settle. Made only for a list with a binding that's told so.
|
|
2217
|
+
let names;
|
|
2218
|
+
const leg = (running, program) => {
|
|
2219
|
+
legs++;
|
|
2220
|
+
const log = pendingLog;
|
|
2221
|
+
pendingLog = undefined;
|
|
2222
|
+
// Per leg (#460): statements, Effect's calls data-first.
|
|
2223
|
+
let run = program;
|
|
2224
|
+
if (Predicate.isNotUndefined(log)) run = Effect.andThen(log, program);
|
|
2225
|
+
if (Predicate.isNotUndefined(names)) running.names = names.leg();
|
|
2226
|
+
return Effect.asVoid(Effect.onExit(run, legEnded(running)));
|
|
2227
|
+
};
|
|
2228
|
+
// Start a leg: forked on the provider's runtime, which runs it inline up to its add on the
|
|
2229
|
+
// loop, so every leg started in a task is on the loop by the end of that task and takes its
|
|
2230
|
+
// first step at the next tick (ADR-0027 decision 5, ADR-0033). Forked from a `runSync`, a leg
|
|
2231
|
+
// would inherit that call's scheduler (ADR-0027, decision 6). The runtime keeps it in its own
|
|
2232
|
+
// fiber Scope, which interrupts it if it's still running when the provider ends (#542).
|
|
2233
|
+
// The name the leg being started waits for (#297's PR 2), set as each is started; none for most.
|
|
2234
|
+
let gateNow;
|
|
2235
|
+
const runLeg = (running, program) => {
|
|
2236
|
+
let run = program;
|
|
2237
|
+
if (Predicate.isNotUndefined(gateNow)) run = gatedBy(gateNow, byName, running, program);
|
|
2238
|
+
running.fiber = runtime.runFork(leg(running, run));
|
|
2239
|
+
};
|
|
2240
|
+
// The legs (#48, ADR-0044 decision 8): one pure builder, which a server render's Appear
|
|
2241
|
+
// animation samples too, so the two can't drift. Built here; each leg's machine is built
|
|
2242
|
+
// in its own fiber, so a transition core rejects (#66, ADR-0025 *Amendment (#66)*) fails
|
|
2243
|
+
// that leg alone, reported as any leg's failure is, while the element's other legs run on.
|
|
2244
|
+
// The returns to a moving Live value (#130, ADR-0043 decision 6): a number's follows it,
|
|
2245
|
+
// in a leg of its own, and lands on it; the rest return to where it is now. Looked for
|
|
2246
|
+
// only when this Retarget returns a key.
|
|
2247
|
+
let follow;
|
|
2248
|
+
if (returning.size > 0 && Predicate.isNotUndefined(live)) {
|
|
2249
|
+
const routes = live;
|
|
2250
|
+
follow = {
|
|
2251
|
+
keysOf: rest => followingOf(routes, rest, returning),
|
|
2252
|
+
targetOf: (key, start) => liveTargetOf(routes, key, start)
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
const reduce = options.reducedMotion();
|
|
2256
|
+
const skipped = skipAnimations();
|
|
2257
|
+
// Measured pairs (#430), asked of the end-of-task batch, unless reduced motion snaps them or the
|
|
2258
|
+
// animation is skipped (#468): the keys found above, and those Keyframes of two stops start from their first.
|
|
2259
|
+
let measured;
|
|
2260
|
+
if (!reduce && !skipped && (Predicate.isNotUndefined(measuring) || Predicate.isNotUndefined(keyframesNow))) {
|
|
2261
|
+
measured = measuredOf(element, measuringOf(measuring, keyframesNow), from, fresh, snapshot.values, manyStops);
|
|
2262
|
+
}
|
|
2263
|
+
let told;
|
|
2264
|
+
if (!silent) told = namesToldOf(animation, resolution, lastResolution);
|
|
2265
|
+
// Every key on one transition when they aren't split, as before; else each group's legs, tagged.
|
|
2266
|
+
// A key that stays starts none, and no keys make no leg (#325).
|
|
2267
|
+
let retargetLegs = NO_LEGS;
|
|
2268
|
+
let legGroups;
|
|
2269
|
+
if (Predicate.isUndefined(groups) && hasKeys(fresh)) {
|
|
2270
|
+
// Where every key is now: a Path's axis the target leaves out starts there (#438), and ends where
|
|
2271
|
+
// it rests (#574).
|
|
2272
|
+
retargetLegs = legsOf(from, fresh, transition, reduce, skipped, positionalKeys, defaultTransition, readVelocity, follow, manyStops, measured, snapshot.values, rests);
|
|
2273
|
+
}
|
|
2274
|
+
if (Predicate.isNotUndefined(groups)) {
|
|
2275
|
+
const split = splitLegsOf(fresh, from, groups, resolution, listed, transition, elementTransition, extraDelay, options.reuse, reduce, skipped, positionalKeys, defaultTransition, readVelocity, follow, manyStops, measured, snapshot.values, rests);
|
|
2276
|
+
retargetLegs = split.legs;
|
|
2277
|
+
legGroups = split.tags;
|
|
2278
|
+
}
|
|
2279
|
+
// The Handoff (#48, ADR-0044 decision 6): the first Retarget that starts picks the Appear
|
|
2280
|
+
// animation up as far in as its CSS has got, read at the legs' first tick.
|
|
2281
|
+
if (Predicate.isNotUndefined(handoff)) {
|
|
2282
|
+
const taken = handoff;
|
|
2283
|
+
handoff = undefined;
|
|
2284
|
+
checkHandoff(runtime, id, taken, {
|
|
2285
|
+
tag,
|
|
2286
|
+
from,
|
|
2287
|
+
to: fresh,
|
|
2288
|
+
transition: baseTransition,
|
|
2289
|
+
reduced: reduce,
|
|
2290
|
+
layout: isLayoutNode(c),
|
|
2291
|
+
stops: manyStops,
|
|
2292
|
+
...skippedField(skipped),
|
|
2293
|
+
...templateField(c.transformTemplate)
|
|
2294
|
+
});
|
|
2295
|
+
const at = startAtOf(taken, baseTransition, delayOf(transition));
|
|
2296
|
+
retargetLegs = Arr.map(retargetLegs, one => startingAt(one, at));
|
|
2297
|
+
}
|
|
2298
|
+
reporting += retargetLegs.length;
|
|
2299
|
+
// A list's names (#297): told settled with the legs of the keys each drives, the ones a key that
|
|
2300
|
+
// stays carries too (#325), to the binding's callbacks and its orchestration, and each shut
|
|
2301
|
+
// one's legs waiting on its gate (PR 2).
|
|
2302
|
+
let legGates;
|
|
2303
|
+
if (listed || Predicate.isNotUndefined(told)) {
|
|
2304
|
+
const carriedLegs = UndefinedOr.match(carried, {
|
|
2305
|
+
onUndefined: () => NO_RUNNING,
|
|
2306
|
+
onDefined: identity
|
|
2307
|
+
});
|
|
2308
|
+
const listing = listingOf({
|
|
2309
|
+
listed,
|
|
2310
|
+
told,
|
|
2311
|
+
byName,
|
|
2312
|
+
resolution,
|
|
2313
|
+
groups,
|
|
2314
|
+
legGroups,
|
|
2315
|
+
legCount: retargetLegs.length,
|
|
2316
|
+
carriedGroups: Arr.map(carriedLegs, running => groupsOfLeg(running, groups, owners)),
|
|
2317
|
+
shut,
|
|
2318
|
+
hold: g => {
|
|
2319
|
+
const kept = pickKeys(from, groups, g);
|
|
2320
|
+
if (Bool.not(Rec.isEmptyRecord(kept))) gate.write(id, kept);
|
|
2321
|
+
},
|
|
2322
|
+
afterFlush: fn => gate.afterFlush(fn),
|
|
2323
|
+
config: c
|
|
2324
|
+
});
|
|
2325
|
+
names = listing.names;
|
|
2326
|
+
legGates = listing.legGates;
|
|
2327
|
+
UndefinedOr.map(names, settles => Arr.forEach(carriedLegs, (running, i) => {
|
|
2328
|
+
running.names = settles.carried(i);
|
|
2329
|
+
}));
|
|
2330
|
+
}
|
|
2331
|
+
// Its `style`'s will-change value turns on as a leg starts a key Motion's would (#443).
|
|
2332
|
+
turnWillChangeOn(live, retargetLegs);
|
|
2333
|
+
// The element's Key rules only for a change a Variable value is in (#542).
|
|
2334
|
+
const variables = holdsVariable(from, fresh, manyStops);
|
|
2335
|
+
// Each leg into its sink, in the builder's order (#69's PR 2: a Retarget is per element). Each
|
|
2336
|
+
// leg draws the keys it animates (#325) until a later Retarget takes them.
|
|
2337
|
+
Arr.forEach(retargetLegs, (leg, i) => {
|
|
2338
|
+
if (Predicate.isNotUndefined(legGates)) gateNow = legGates[i];
|
|
2339
|
+
const running = runningOf(leg.to, resolution, landing, leg._tag);
|
|
2340
|
+
own(running);
|
|
2341
|
+
runLeg(running, legProgram(leg, running, variables));
|
|
2342
|
+
});
|
|
2343
|
+
// Each entry's Transition end (#428): a leg holding the keys only its end sets where they are,
|
|
2344
|
+
// waiting for the keys the entry animates to land (the legs drawing them now, this Retarget's or
|
|
2345
|
+
// carried), then setting its end values, the keys it also animates among them. It counts toward
|
|
2346
|
+
// this landing, so the landing includes it. A later Retarget that resolves its keys to the same
|
|
2347
|
+
// values carries it (#325); one that doesn't gives them up, and it never sets them.
|
|
2348
|
+
if (Predicate.isNotUndefined(ends)) {
|
|
2349
|
+
gateNow = undefined;
|
|
2350
|
+
Arr.forEach(ends.byLayer, (writes, at) => {
|
|
2351
|
+
if (Predicate.isUndefined(writes)) return;
|
|
2352
|
+
const owned = Rec.filter(freshEnds, (_, key) => ends.endOnly.get(key) === at);
|
|
2353
|
+
// Its end starts again when a key it also animates starts again, or its end for one changed
|
|
2354
|
+
// (#470, one already there starts none), or a key only it sets does.
|
|
2355
|
+
const anew = Bool.or(hasKeys(owned), Arr.some(Rec.keys(writes), key => Bool.and(Bool.not(ends.endOnly.has(key)), Bool.or(Object.hasOwn(fresh, key), endMoved(lastResolution, resolution, key)))));
|
|
2356
|
+
if (Bool.not(anew)) return;
|
|
2357
|
+
const animated = Arr.filter(Rec.keys(resolved), key => Bool.and(Bool.not(ends.endOnly.has(key)), driverOf(layers, key) === at));
|
|
2358
|
+
// Its keys set at their end, at once: no motion, so no velocity (#464).
|
|
2359
|
+
const running = runningOf(owned, resolution, landing, "Snap");
|
|
2360
|
+
own(running);
|
|
2361
|
+
// Held where they are: a key with nothing to start from (it would start at its target, no
|
|
2362
|
+
// motion) is left unset until its end, not set to it now.
|
|
2363
|
+
const holding = Rec.map(Rec.filter(owned, (_, key) => started[key] !== "target"), (_, key) => UndefinedOr.getOrThrow(snapshot.values[key]));
|
|
2364
|
+
if (hasKeys(holding)) gate.write(id, holding);
|
|
2365
|
+
snapshot.velocities = {
|
|
2366
|
+
...snapshot.velocities,
|
|
2367
|
+
...Rec.map(owned, () => 0)
|
|
2368
|
+
};
|
|
2369
|
+
// Counted toward this landing as a leg is (#508), with no fiber of its own: the landing of its
|
|
2370
|
+
// keys' last leg writes it, or the next flush when they've landed already.
|
|
2371
|
+
reporting++;
|
|
2372
|
+
legs++;
|
|
2373
|
+
const log = pendingLog;
|
|
2374
|
+
pendingLog = undefined;
|
|
2375
|
+
// Forked only where a Debug log is kept (#618); a leg's runs inside the leg's own fiber.
|
|
2376
|
+
if (Predicate.isNotUndefined(log)) {
|
|
2377
|
+
if (logsDebugOn(runtime)) runtime.runFork(log);
|
|
2378
|
+
}
|
|
2379
|
+
if (Predicate.isNotUndefined(names)) running.names = names.leg();
|
|
2380
|
+
// One that owns no key records the legs it waits for: their interrupt drops it (ADR-0057 Q1).
|
|
2381
|
+
let waitsOn;
|
|
2382
|
+
if (Bool.not(hasKeys(owned))) waitsOn = Arr.map(animated, key => owners.get(key));
|
|
2383
|
+
if (Predicate.isUndefined(waiting)) waiting = waitingEndsOf(owners, snapshot, gate, id, recordFrame);
|
|
2384
|
+
waiting.add({
|
|
2385
|
+
running,
|
|
2386
|
+
animated,
|
|
2387
|
+
writes,
|
|
2388
|
+
legs: waitsOn,
|
|
2389
|
+
state: "waiting"
|
|
2390
|
+
});
|
|
2391
|
+
});
|
|
2392
|
+
}
|
|
2393
|
+
// A turn none of its legs draws now goes back (#460).
|
|
2394
|
+
turnBack();
|
|
2395
|
+
// The keys already there (#448), written with each key the Retarget moves at where it starts, as
|
|
2396
|
+
// its leg's first frame writes it: the element's first commit, which takes its Starting style off,
|
|
2397
|
+
// holds every key, whatever frame the legs first draw in (a gated name's draws later).
|
|
2398
|
+
if (Predicate.isNotUndefined(there)) {
|
|
2399
|
+
const written = {
|
|
2400
|
+
...from,
|
|
2401
|
+
...there
|
|
2402
|
+
};
|
|
2403
|
+
gate.write(id, written);
|
|
2404
|
+
recordFrame(written);
|
|
2405
|
+
}
|
|
2406
|
+
// The Retarget started, its legs on their way (#257); with none, its own or carried, it landed
|
|
2407
|
+
// at once (#325): its returns settle, and the element reports settled at the gate's next flush,
|
|
2408
|
+
// after the effects that start its orchestration's wait (ADR-0007).
|
|
2409
|
+
previous = lastResolution;
|
|
2410
|
+
lastResolution = resolution;
|
|
2411
|
+
const landed = legs === 0;
|
|
2412
|
+
if (landed) {
|
|
2413
|
+
settleReturns(returns);
|
|
2414
|
+
leaveAfterFlush();
|
|
2415
|
+
if (Predicate.isNotUndefined(pendingLog)) {
|
|
2416
|
+
if (logsDebugOn(runtime)) runtime.runFork(pendingLog);
|
|
2417
|
+
}
|
|
2418
|
+
if (Predicate.isNotUndefined(onFrame)) {
|
|
2419
|
+
const tell = onFrame;
|
|
2420
|
+
gate.afterFlush(() => {
|
|
2421
|
+
if (current === landing) tell(true);
|
|
2422
|
+
});
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
if (Predicate.isNotUndefined(animation) && !silent) {
|
|
2426
|
+
const hooks = animation;
|
|
2427
|
+
hooks.started(resolution, previous, c);
|
|
2428
|
+
startedTold = true;
|
|
2429
|
+
if (landed) hooks.settled(resolution, previous, c);
|
|
2430
|
+
if (Predicate.isNotUndefined(failedEarly)) tellFailed(failedEarly.error);
|
|
2431
|
+
}
|
|
2432
|
+
};
|
|
2433
|
+
// --- Live values in `style` (#130, ADR-0043) ------------------------------
|
|
2434
|
+
// A routed key (a Live value, or a transform key) is its `style` link, live: while no entry of
|
|
2435
|
+
// the Override stack sets it, no return is running to it and no drag moves it, the element
|
|
2436
|
+
// follows it, written through the gate on every change. A return hands it back here when it
|
|
2437
|
+
// settles (`settleReturns`). The Starting style showed each one's value at render; from mount
|
|
2438
|
+
// the gate holds them.
|
|
2439
|
+
const follow = now => {
|
|
2440
|
+
if (Predicate.isUndefined(live)) return;
|
|
2441
|
+
const routes = live;
|
|
2442
|
+
// Built at the first routed key, at mount or later: an element whose `style` routes none builds nothing.
|
|
2443
|
+
routes.whenRouted(() => {
|
|
2444
|
+
// Read at each ask: `projected` is a getter while the track waits for `drag` (#551, #582).
|
|
2445
|
+
const dragHolds = () => Bool.and(Bool.not(options.projected), Predicate.isNotUndefined(options.dragAxis));
|
|
2446
|
+
// Whether something other than the follower moves `key` now.
|
|
2447
|
+
const owned = key => Bool.some([driven.has(key), Object.hasOwn(now.resolved(), key),
|
|
2448
|
+
// An Imperative animation's (#433).
|
|
2449
|
+
taken.has(key),
|
|
2450
|
+
// The drag direct-sets both translate keys while it, and its release, run (ADR-0004).
|
|
2451
|
+
Bool.and(dragHolds(), Bool.and(now.dragging(), Bool.or(key === "x", key === "y")))]);
|
|
2452
|
+
// Written as any frame is: into the gate, the Snapshot (at rest) and the presence record.
|
|
2453
|
+
const put = values => {
|
|
2454
|
+
Arr.forEach(Rec.keys(values), key => {
|
|
2455
|
+
snapshot.values[key] = UndefinedOr.getOrThrow(values[key]);
|
|
2456
|
+
delete snapshot.velocities[key];
|
|
2457
|
+
});
|
|
2458
|
+
gate.write(id, values);
|
|
2459
|
+
recordFrame(values);
|
|
2460
|
+
};
|
|
2461
|
+
handBack = key => {
|
|
2462
|
+
Option.match(Option.filter(routes.valueOf(key), isValue), {
|
|
2463
|
+
onNone: constVoid,
|
|
2464
|
+
onSome: value => put({
|
|
2465
|
+
[key]: value
|
|
2466
|
+
})
|
|
2467
|
+
});
|
|
2468
|
+
};
|
|
2469
|
+
// Every routed key nothing owns, with, before anything's committed, the values the Override
|
|
2470
|
+
// stack's keys start from, so a held start (a `when` gate) keeps showing them.
|
|
2471
|
+
const first = Rec.filter(routes.values(), (_, key) => Bool.not(owned(key)));
|
|
2472
|
+
if (hasKeys(first)) put({
|
|
2473
|
+
...Values.pick(snapshot.values, now.resolved()),
|
|
2474
|
+
...first
|
|
2475
|
+
});
|
|
2476
|
+
return {
|
|
2477
|
+
change: (key, value) => {
|
|
2478
|
+
if (Bool.or(owned(key), Bool.not(isValue(value)))) return;
|
|
2479
|
+
put({
|
|
2480
|
+
[key]: value
|
|
2481
|
+
});
|
|
2482
|
+
},
|
|
2483
|
+
removed: key => {
|
|
2484
|
+
if (owned(key)) return;
|
|
2485
|
+
delete snapshot.values[key];
|
|
2486
|
+
delete snapshot.velocities[key];
|
|
2487
|
+
if (Predicate.isNotUndefined(presence)) delete presence.snapshot.current[key];
|
|
2488
|
+
// Gone from `style`: the element's own value comes back, or the key's CSS value now.
|
|
2489
|
+
const restore = Option.match(OwnValues.styleValueOf(UndefinedOr.match(styleNow, {
|
|
2490
|
+
onUndefined: constUndefined,
|
|
2491
|
+
onDefined: style => style()
|
|
2492
|
+
}), key), {
|
|
2493
|
+
onNone: () => "",
|
|
2494
|
+
onSome: String
|
|
2495
|
+
});
|
|
2496
|
+
gate.release(id, [key], {
|
|
2497
|
+
[key]: restore
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
};
|
|
2501
|
+
});
|
|
2502
|
+
};
|
|
2503
|
+
const dispose = () => {
|
|
2504
|
+
// Unmounted, it lands in no Controls change (#433).
|
|
2505
|
+
leaveChange();
|
|
2506
|
+
if (Predicate.isNotUndefined(live)) live.stop();
|
|
2507
|
+
// The legs end normally first, so closing the Scope has nothing left to interrupt. A Transition
|
|
2508
|
+
// end waiting or due writes nothing (#508).
|
|
2509
|
+
if (Predicate.isNotUndefined(waiting)) waiting.dispose();
|
|
2510
|
+
// Each leg not landed ends as a Retarget ends one (#542): by its token, and interrupted if its
|
|
2511
|
+
// token didn't reach it. Nothing else ends them before the provider does.
|
|
2512
|
+
owners.forEach(running => {
|
|
2513
|
+
if (Predicate.isUndefined(running)) return;
|
|
2514
|
+
if (!running.done) endLeg(running);
|
|
2515
|
+
});
|
|
2516
|
+
};
|
|
2517
|
+
// A child back under its key (#286): its values and velocities from where the leaver is drawn, a
|
|
2518
|
+
// projected element's own translate among them (#363). Drawn at the end of the task, so nothing
|
|
2519
|
+
// paints the element at its `initial` first: not in the mount effect it's called in, where the
|
|
2520
|
+
// first commit's Starting-style switch would flush Solid 2 inside an effect.
|
|
2521
|
+
const seed = from => {
|
|
2522
|
+
const values = from.values;
|
|
2523
|
+
Object.assign(snapshot.values, values);
|
|
2524
|
+
snapshot.velocities = {
|
|
2525
|
+
...snapshot.velocities,
|
|
2526
|
+
...from.velocities
|
|
2527
|
+
};
|
|
2528
|
+
// Drawn now, by the leaver (#464).
|
|
2529
|
+
const now = snapshot.now();
|
|
2530
|
+
Arr.forEach(Rec.keys(from.velocities), key => {
|
|
2531
|
+
snapshot.drawnAt[key] = now;
|
|
2532
|
+
});
|
|
2533
|
+
if (Predicate.isNotUndefined(presence)) Object.assign(presence.snapshot.current, values);
|
|
2534
|
+
Arr.forEach(Rec.keys(values), key => {
|
|
2535
|
+
driven.set(key, values[key]);
|
|
2536
|
+
});
|
|
2537
|
+
queueMicrotask(() => gate.flushPass(() => gate.write(id, values)));
|
|
2538
|
+
};
|
|
2539
|
+
// --- Imperative animations (#433) -------------------------------------------
|
|
2540
|
+
/** A leg of an Imperative animation, forked as a Retarget's are; it lands on its track. */
|
|
2541
|
+
// Data-first: a pipe's curried forms are two closures more for every leg (#618, H1).
|
|
2542
|
+
const runImperative = (running, program) => {
|
|
2543
|
+
running.fiber = runtime.runFork(Effect.asVoid(Effect.onExit(program, legEnded(running))));
|
|
2544
|
+
};
|
|
2545
|
+
const animate = (target, given, head, hooks) => {
|
|
2546
|
+
const to = target.values;
|
|
2547
|
+
const before = UndefinedOr.match(lastResolution, {
|
|
2548
|
+
onUndefined: () => NO_VALUES,
|
|
2549
|
+
onDefined: last => last.resolved
|
|
2550
|
+
});
|
|
2551
|
+
const started = {};
|
|
2552
|
+
let measuring;
|
|
2553
|
+
// Each key taken from whatever runs it, noted with its target now, and started where it's drawn.
|
|
2554
|
+
// Its velocity read now (#464), as its legs are built.
|
|
2555
|
+
readAt = snapshot.now();
|
|
2556
|
+
// Where a Path's axis this target leaves out rests (#574), before its keys are taken below.
|
|
2557
|
+
const rests = restsOf(owners, to);
|
|
2558
|
+
if (taken === NONE_TAKEN) taken = new Map();
|
|
2559
|
+
const takenNow = taken;
|
|
2560
|
+
Arr.forEach(Rec.keys(to), key => {
|
|
2561
|
+
takenNow.set(key, before[key]);
|
|
2562
|
+
returning.delete(key);
|
|
2563
|
+
const owner = owners.get(key);
|
|
2564
|
+
if (Predicate.isNotUndefined(owner)) giveUp(key, owner);
|
|
2565
|
+
if (!Object.hasOwn(initialValues, key)) ownValue(key);
|
|
2566
|
+
const like = UndefinedOr.getOrThrow(to[key]);
|
|
2567
|
+
startKey(key, like, started);
|
|
2568
|
+
if (MeasuredPair.needs(key, UndefinedOr.getOrThrow(snapshot.values[key]), like)) {
|
|
2569
|
+
if (Predicate.isUndefined(measuring)) measuring = [];
|
|
2570
|
+
measuring.push(key);
|
|
2571
|
+
}
|
|
2572
|
+
});
|
|
2573
|
+
keepTheRest();
|
|
2574
|
+
let from = Rec.map(to, (_, key) => UndefinedOr.getOrThrow(snapshot.values[key]));
|
|
2575
|
+
let stops;
|
|
2576
|
+
if (Predicate.isNotUndefined(target.keyframes)) {
|
|
2577
|
+
const begun = keyframesFrom(from, to, target.keyframes);
|
|
2578
|
+
from = begun.from;
|
|
2579
|
+
stops = begun.stops;
|
|
2580
|
+
}
|
|
2581
|
+
const reduce = options.reducedMotion();
|
|
2582
|
+
const skipped = skipAnimations();
|
|
2583
|
+
let measured;
|
|
2584
|
+
if (Bool.and(Bool.not(Bool.or(reduce, skipped)), Predicate.isNotUndefined(measuring))) measured = measuredOf(element, UndefinedOr.getOrThrow(measuring), from, to, snapshot.values, stops);
|
|
2585
|
+
// Built once: a seek or a replay runs the same legs, from the same start, with the same velocities.
|
|
2586
|
+
const built = legsOf(from, to, given, reduce, skipped, positionalKeys, defaultTransition, readVelocity, undefined, stops, measured, snapshot.values, rests);
|
|
2587
|
+
const variables = holdsVariable(from, to, stops);
|
|
2588
|
+
const legs = Arr.map(built, leg => mapMachine(leg, Playback.drive(head)));
|
|
2589
|
+
let runnings = NO_RUNNING;
|
|
2590
|
+
let left = 0;
|
|
2591
|
+
const landing = {
|
|
2592
|
+
report: constVoid,
|
|
2593
|
+
settled: () => {
|
|
2594
|
+
left--;
|
|
2595
|
+
if (left === 0) gate.afterFlush(hooks.settled);
|
|
2596
|
+
},
|
|
2597
|
+
failed: hooks.failed
|
|
2598
|
+
};
|
|
2599
|
+
// Its legs ended where they are: the keys they draw are drawn by none.
|
|
2600
|
+
const end = () => Arr.forEach(runnings, running => {
|
|
2601
|
+
forget(running);
|
|
2602
|
+
if (Bool.not(running.done)) endLeg(running);
|
|
2603
|
+
});
|
|
2604
|
+
const run = () => {
|
|
2605
|
+
end();
|
|
2606
|
+
left = legs.length;
|
|
2607
|
+
turnWillChangeOn(live, legs);
|
|
2608
|
+
runnings = Arr.map(legs, leg => {
|
|
2609
|
+
const running = runningOf(leg.to, IMPERATIVE, landing, leg._tag);
|
|
2610
|
+
own(running);
|
|
2611
|
+
runImperative(running, legProgram(leg, running, variables));
|
|
2612
|
+
return running;
|
|
2613
|
+
});
|
|
2614
|
+
// A target with no key lands at once.
|
|
2615
|
+
if (left === 0) gate.afterFlush(hooks.settled);
|
|
2616
|
+
};
|
|
2617
|
+
const cancel = () => {
|
|
2618
|
+
end();
|
|
2619
|
+
turnBack();
|
|
2620
|
+
snapshot.values = {
|
|
2621
|
+
...snapshot.values,
|
|
2622
|
+
...from
|
|
2623
|
+
};
|
|
2624
|
+
snapshot.velocities = {
|
|
2625
|
+
...snapshot.velocities,
|
|
2626
|
+
...Rec.map(from, () => 0)
|
|
2627
|
+
};
|
|
2628
|
+
// Put back at once: at rest, newer than the legs that let them go (#464).
|
|
2629
|
+
const now = snapshot.now();
|
|
2630
|
+
Arr.forEach(Rec.keys(from), key => {
|
|
2631
|
+
snapshot.drawnAt[key] = now;
|
|
2632
|
+
});
|
|
2633
|
+
gate.write(id, from);
|
|
2634
|
+
recordFrame(from);
|
|
2635
|
+
};
|
|
2636
|
+
// Each leg's machine, run from its start to rest, apart from the Playhead, which it would move: a
|
|
2637
|
+
// blend's built with the element's Key rules.
|
|
2638
|
+
const duration = () => Arr.reduce(built, 0, (longest, leg) => Math.max(longest, Machine.durationOf(machineOf(leg))));
|
|
2639
|
+
const machineOf = leg => {
|
|
2640
|
+
if (leg._tag === "Blend") return runtime.runSync(Effect.suspend(leg.machine).pipe(InterpolatorRegistry.withKeyRules(elementRules)));
|
|
2641
|
+
return leg.machine();
|
|
2642
|
+
};
|
|
2643
|
+
const stop = () => {
|
|
2644
|
+
end();
|
|
2645
|
+
turnBack();
|
|
2646
|
+
};
|
|
2647
|
+
return {
|
|
2648
|
+
run,
|
|
2649
|
+
stop,
|
|
2650
|
+
cancel,
|
|
2651
|
+
duration
|
|
2652
|
+
};
|
|
2653
|
+
};
|
|
2654
|
+
// **Animation controls**' `stop` (#433): every running leg ends where it is, its keys given up, so
|
|
2655
|
+
// the next Retarget starts them from where they're drawn.
|
|
2656
|
+
const stop = () => {
|
|
2657
|
+
owners.forEach(running => {
|
|
2658
|
+
if (Predicate.isUndefined(running)) return;
|
|
2659
|
+
forget(running);
|
|
2660
|
+
if (Bool.not(running.done)) endLeg(running);
|
|
2661
|
+
});
|
|
2662
|
+
turnBack();
|
|
2663
|
+
};
|
|
2664
|
+
return {
|
|
2665
|
+
retarget,
|
|
2666
|
+
follow,
|
|
2667
|
+
dispose,
|
|
2668
|
+
seed,
|
|
2669
|
+
animate,
|
|
2670
|
+
stop
|
|
2671
|
+
};
|
|
2672
|
+
};
|
|
2673
|
+
/**
|
|
2674
|
+
* `sink` with an `onCommit` that calls the config's current `onUpdate` (#233), when the config had
|
|
2675
|
+
* one at mount; `sink` as it is otherwise. `config` reads it untracked.
|
|
2676
|
+
*/
|
|
2677
|
+
export const withOnUpdate = (sink, atMount, config) => {
|
|
2678
|
+
// Per element at mount: most have none, and pay a check.
|
|
2679
|
+
if (Predicate.isUndefined(atMount)) return sink;
|
|
2680
|
+
return {
|
|
2681
|
+
...sink,
|
|
2682
|
+
onCommit: latest => {
|
|
2683
|
+
const onUpdate = config().onUpdate;
|
|
2684
|
+
if (Predicate.isNotUndefined(onUpdate)) onUpdate(latest);
|
|
2685
|
+
}
|
|
2686
|
+
};
|
|
2687
|
+
};
|
|
2688
|
+
/**
|
|
2689
|
+
* `sink`, removing the element's Appear animation in its first commit (#48, ADR-0044 decision 6):
|
|
2690
|
+
* in the task that writes the engine's first frame, so no paint falls between. Without one, `sink`.
|
|
2691
|
+
*/
|
|
2692
|
+
export const releasingAppear = (sink, handoff, element) => {
|
|
2693
|
+
if (Predicate.isUndefined(handoff)) return sink;
|
|
2694
|
+
const before = sink.beforeFirstCommit;
|
|
2695
|
+
return {
|
|
2696
|
+
...sink,
|
|
2697
|
+
beforeFirstCommit: () => {
|
|
2698
|
+
Appear.release(element);
|
|
2699
|
+
if (Predicate.isNotUndefined(before)) before();
|
|
2700
|
+
}
|
|
2701
|
+
};
|
|
2702
|
+
};
|
|
2703
|
+
/**
|
|
2704
|
+
* A Handoff whose Appear animation the server sampled from another mount animation than the
|
|
2705
|
+
* client's: the app rendered differently on the server, or a function it gave has no easing name.
|
|
2706
|
+
* Noted once (cold path, `wardic.hydration`); the client's own animation goes on from the same time.
|
|
2707
|
+
*/
|
|
2708
|
+
const checkHandoff = (runtime, id, handoff, mount) => {
|
|
2709
|
+
// A templated element's rule is named by its stops (#443), which the client doesn't sample to check.
|
|
2710
|
+
if (Predicate.isNotUndefined(mount.template)) return;
|
|
2711
|
+
const same = Option.exists(keyOf(mount), key => Appear.matches(handoff.animation, {
|
|
2712
|
+
key,
|
|
2713
|
+
tag: mount.tag,
|
|
2714
|
+
infinite: repeatsForever(mount.transition),
|
|
2715
|
+
projected: mount.layout
|
|
2716
|
+
}));
|
|
2717
|
+
if (same) return;
|
|
2718
|
+
runtime.runFork(Effect.logDebug("wardic.hydration: the server's Appear animation was sampled from another mount animation than this element's; it goes on from the same time").pipe(Effect.annotateLogs({
|
|
2719
|
+
id
|
|
2720
|
+
})));
|
|
2721
|
+
};
|
|
2722
|
+
/** The keys a Retarget returns to a Live value that's a number: each one's return follows it (#130). */
|
|
2723
|
+
const followingOf = (routes, rest, returning) => Arr.filter(Rec.keys(rest), key => Bool.and(returning.get(key) === "style", Bool.and(routes.isLive(key), Predicate.isNumber(rest[key]))));
|
|
2724
|
+
/** Where `key`'s Live value is now, a number; where it last was when it's none (#130). */
|
|
2725
|
+
const liveTargetOf = (routes, key, start) => {
|
|
2726
|
+
let last = start;
|
|
2727
|
+
return () => {
|
|
2728
|
+
const now = Option.flatMap(routes.valueOf(key), raw => OwnValues.valueLike(raw, last));
|
|
2729
|
+
if (Option.isSome(now)) last = now.value;
|
|
2730
|
+
return last;
|
|
2731
|
+
};
|
|
2732
|
+
};
|
|
2733
|
+
/** Whether a value is one an element can take: a number or a string. */
|
|
2734
|
+
const isValue = value => Bool.or(Predicate.isNumber(value), Predicate.isString(value));
|
|
2735
|
+
/**
|
|
2736
|
+
* Where `key` rests outside the gate (#130): its `initial`, else its `style` value (a Live value's
|
|
2737
|
+
* now), else a transform key's identity, else `undefined`.
|
|
2738
|
+
*/
|
|
2739
|
+
export const restingOf = (key, initial, style, read) => Option.getOrUndefined(Option.fromUndefinedOr(initial[key]).pipe(Option.orElse(() => Option.flatMap(OwnValues.styleValueOf(style, key), raw => Option.fromNullishOr(read(raw)))), Option.orElse(() => BaseValue.transformIdentity(key))));
|
|
2740
|
+
/** A provider runtime's `AtomRegistry`, read on first need: an element with no Atom never reads it. */
|
|
2741
|
+
export const registryOf = runtime => {
|
|
2742
|
+
let registry;
|
|
2743
|
+
return () => {
|
|
2744
|
+
if (Predicate.isUndefined(registry)) registry = runtime.runSync(AtomRegistry.AtomRegistry);
|
|
2745
|
+
return registry;
|
|
2746
|
+
};
|
|
2747
|
+
};
|
|
2748
|
+
/** Log, once per element, that a `transform` string gave way to the transform keys in its `style` (#130). */
|
|
2749
|
+
export const warnDroppedTransform = (runtime, id) => {
|
|
2750
|
+
runtime.runFork(Effect.logWarning("wardic.style: a `transform` string is dropped while `style` sets a transform key (x, scale, rotate…); " + "the keys win, as Motion's do. Give the transform as keys, or drop them").pipe(Effect.annotateLogs({
|
|
2751
|
+
id
|
|
2752
|
+
})));
|
|
2753
|
+
};
|
|
2754
|
+
/**
|
|
2755
|
+
* Log, at debug level, the keys whose Starting style the Environment's Renderer projects
|
|
2756
|
+
* differently from the DOM's `project`, which rendered the server markup. Hydration keeps
|
|
2757
|
+
* the server's values (the Hydration hold); the Renderer's take over at the first frame.
|
|
2758
|
+
* Hydration only, once per element. Internal.
|
|
2759
|
+
*/
|
|
2760
|
+
export const flagStartingStyle = (runtime, id, server, client) => {
|
|
2761
|
+
const keys = Arr.appendAll(Arr.filter(Rec.keys(server), key => String(server[key]) !== String(client[key])), Arr.filter(Rec.keys(client), key => Bool.not(key in server)));
|
|
2762
|
+
if (Arr.isReadonlyArrayEmpty(keys)) return;
|
|
2763
|
+
const pick = patch => Object.fromEntries(keys.map(key => [key, patch[key]]));
|
|
2764
|
+
runtime.runFork(Effect.logDebug("wardic.hydration: the Environment's Renderer projects the Starting style differently from the DOM's; " + "hydration keeps the server's until the first frame, and an element that never animates keeps it").pipe(Effect.annotateLogs({
|
|
2765
|
+
id,
|
|
2766
|
+
keys,
|
|
2767
|
+
server: pick(server),
|
|
2768
|
+
client: pick(client)
|
|
2769
|
+
})));
|
|
2770
|
+
};
|
|
2771
|
+
/** No Appear animation: a provider with `appear={false}`. */
|
|
2772
|
+
const NO_APPEAR_ENTRY = provided => ({
|
|
2773
|
+
style: undefined,
|
|
2774
|
+
provided,
|
|
2775
|
+
veto: constVoid,
|
|
2776
|
+
late: false,
|
|
2777
|
+
chunkRoot: false,
|
|
2778
|
+
state: undefined
|
|
2779
|
+
});
|
|
2780
|
+
/**
|
|
2781
|
+
* An element's entry in the server render's Appear animations (#48, ADR-0044): its starting
|
|
2782
|
+
* values, its targets at mount (`animate`, or an inherited variant name against its `variants`),
|
|
2783
|
+
* its transition, its place in its parent's group, and its nearest `WardicConfig`'s reduced motion
|
|
2784
|
+
* (#434). `state` is the provider's, `undefined` with `appear={false}`: each binding reads it from its
|
|
2785
|
+
* own context.
|
|
2786
|
+
*/
|
|
2787
|
+
export const appearEntryOf = (state, c, tag, initialValues, node, quiet, reducedMotion, skipAnimations = false) => UndefinedOr.match(state, {
|
|
2788
|
+
onUndefined: () => NO_APPEAR_ENTRY(node.provided),
|
|
2789
|
+
onDefined: state => {
|
|
2790
|
+
// The target's own transition (#277) drives its mount animation, and its orchestration.
|
|
2791
|
+
const target = serverTargetOf(c, node.inherited);
|
|
2792
|
+
const own = Option.getOrUndefined(Option.flatMap(target, t => Option.fromUndefinedOr(t.transition)));
|
|
2793
|
+
const entered = enterServer(state, {
|
|
2794
|
+
appear: c.appear,
|
|
2795
|
+
tag,
|
|
2796
|
+
initial: initialValues,
|
|
2797
|
+
to: Option.map(target, t => t.values),
|
|
2798
|
+
keyframes: Option.getOrUndefined(Option.flatMap(target, t => Option.fromUndefinedOr(t.keyframes))),
|
|
2799
|
+
quiet,
|
|
2800
|
+
transition: transitionOfTarget(own, ownOrInherited(c.transition, node.inherited)),
|
|
2801
|
+
layout: isLayoutNode(c),
|
|
2802
|
+
template: c.transformTemplate,
|
|
2803
|
+
group: Option.flatMap(Option.fromUndefinedOr(node.inherited), inherited => Option.fromUndefinedOr(inherited.appearGroup)),
|
|
2804
|
+
leads: hasOwnVariants(c),
|
|
2805
|
+
ownTransition: transitionOfTarget(own, c.transition),
|
|
2806
|
+
reducedMotion,
|
|
2807
|
+
skipAnimations
|
|
2808
|
+
});
|
|
2809
|
+
return {
|
|
2810
|
+
style: Option.match(entered.animation, {
|
|
2811
|
+
onNone: constUndefined,
|
|
2812
|
+
onSome: animation => ({
|
|
2813
|
+
animation
|
|
2814
|
+
})
|
|
2815
|
+
}),
|
|
2816
|
+
provided: Option.match(entered.group, {
|
|
2817
|
+
onNone: () => node.provided,
|
|
2818
|
+
onSome: appearGroup => UndefinedOr.map(node.provided, provided => ({
|
|
2819
|
+
...provided,
|
|
2820
|
+
appearGroup
|
|
2821
|
+
}))
|
|
2822
|
+
}),
|
|
2823
|
+
veto: entered.veto,
|
|
2824
|
+
late: entered.late,
|
|
2825
|
+
chunkRoot: entered.chunkRoot,
|
|
2826
|
+
state
|
|
2827
|
+
};
|
|
2828
|
+
}
|
|
2829
|
+
});
|
|
2830
|
+
/**
|
|
2831
|
+
* An element's target at mount on a server: its `animate`, else an inherited variant name resolved
|
|
2832
|
+
* against its own `variants`, a dynamic one with its `custom` and no values yet (#277).
|
|
2833
|
+
*/
|
|
2834
|
+
export const serverTargetOf = (c, inherited) => UndefinedOr.match(c.animate, {
|
|
2835
|
+
onDefined: own => Option.some(resolveTarget(own, c.variants, c.custom, NO_VARIANT_STATE)),
|
|
2836
|
+
onUndefined: () => Option.map(Option.flatMap(Option.fromUndefinedOr(inherited), context => Option.fromUndefinedOr(context.variant())), name => resolveTarget(name, c.variants, c.custom, NO_VARIANT_STATE))
|
|
2837
|
+
});
|
|
2838
|
+
/**
|
|
2839
|
+
* A server's Starting style for an element whose `style` has routed keys (#130): the projected
|
|
2840
|
+
* `initial` with their values under it. With none, its Starting style as it was.
|
|
2841
|
+
*/
|
|
2842
|
+
export const serverStartingStyle = (tag, starting, initialValues, routed, layout, untrack, template) => Bool.match(Rec.isEmptyRecord(routed), {
|
|
2843
|
+
onTrue: () => starting,
|
|
2844
|
+
onFalse: () => Style.starting(tag, drawnAtRest({
|
|
2845
|
+
...valuesOf(routed, serverRegistryOf, untrack),
|
|
2846
|
+
...initialValues
|
|
2847
|
+
}, layout, template)).style
|
|
2848
|
+
});
|
|
2849
|
+
/** Whether a config makes its element a layout node: `layout` (or a mode), or a `layoutId`. */
|
|
2850
|
+
export const isLayoutNode = c => Bool.or(Bool.and(Predicate.isNotUndefined(c.layout), c.layout !== false), Predicate.isNotUndefined(c.layoutId));
|
|
2851
|
+
/**
|
|
2852
|
+
* The values a layout node's Starting style is drawn from (#245, ADR-0044 *Amendment (#245)*):
|
|
2853
|
+
* through its projection at rest, as its first commit draws it, its own translate on top (#363).
|
|
2854
|
+
* Any other element's, as they are. A templated element's, with its Transform template (#443).
|
|
2855
|
+
*/
|
|
2856
|
+
export const drawnAtRest = (values, layout, template) => {
|
|
2857
|
+
// Per mount (#460): guards, nothing built for an element neither a layout node nor templated.
|
|
2858
|
+
if (Bool.not(layout)) return withTemplate(values, template);
|
|
2859
|
+
return withTemplate({
|
|
2860
|
+
...values,
|
|
2861
|
+
[Projection.KEY]: Projection.AT_REST
|
|
2862
|
+
}, template);
|
|
2863
|
+
};
|
|
2864
|
+
/** `values` with `template` under the renderer's reserved key, as its projection rides (#443); as they are with none. */
|
|
2865
|
+
export const withTemplate = (values, template) => {
|
|
2866
|
+
if (Predicate.isUndefined(template)) return values;
|
|
2867
|
+
return {
|
|
2868
|
+
...values,
|
|
2869
|
+
[DomRenderer.TEMPLATE_KEY]: template
|
|
2870
|
+
};
|
|
2871
|
+
};
|
|
2872
|
+
/**
|
|
2873
|
+
* What an element registers with in the gate (#443): its Transform template at mount, under the
|
|
2874
|
+
* renderer's reserved key, drawn with its first write (a write of its own would take its Starting
|
|
2875
|
+
* style off early). Nothing with none.
|
|
2876
|
+
*/
|
|
2877
|
+
export const registeredValuesOf = template => {
|
|
2878
|
+
if (Predicate.isUndefined(template)) return undefined;
|
|
2879
|
+
return {
|
|
2880
|
+
[DomRenderer.TEMPLATE_KEY]: template
|
|
2881
|
+
};
|
|
2882
|
+
};
|
|
2883
|
+
/**
|
|
2884
|
+
* What an element's projection node is held at for a Measure pass (#443, Motion's
|
|
2885
|
+
* `transformTemplate(values, "")`): its Transform template's, from its values now, when it had one
|
|
2886
|
+
* at mount. `undefined` otherwise, so a node without one pays a field read a pass.
|
|
2887
|
+
*/
|
|
2888
|
+
export const heldTransformFor = (snapshot, atMount, template) => {
|
|
2889
|
+
if (Predicate.isUndefined(atMount)) return undefined;
|
|
2890
|
+
return () => DomRenderer.heldTransformOf(withTemplate(snapshot.values, template()));
|
|
2891
|
+
};
|
|
2892
|
+
/**
|
|
2893
|
+
* Follow an element's Transform template after mount (#443): `write` is called with each other one
|
|
2894
|
+
* its config gives, and draws it at the next frame. Only for an element with one at mount, as
|
|
2895
|
+
* `onUpdate` (#233): its caller asks only then, so another makes nothing (#460). Returns the stop.
|
|
2896
|
+
*/
|
|
2897
|
+
export const followTemplate = (atMount, template, watch, write) => {
|
|
2898
|
+
let last = atMount;
|
|
2899
|
+
return watch(template, next => {
|
|
2900
|
+
if (next === last) return;
|
|
2901
|
+
last = next;
|
|
2902
|
+
write(next);
|
|
2903
|
+
});
|
|
2904
|
+
};
|
|
2905
|
+
/** A mount animation's template field (#443): left out with none, as its key reads it. */
|
|
2906
|
+
export const templateField = template => UndefinedOr.match(template, {
|
|
2907
|
+
onUndefined: () => ({}),
|
|
2908
|
+
onDefined: t => ({
|
|
2909
|
+
template: t
|
|
2910
|
+
})
|
|
2911
|
+
});
|
|
2912
|
+
/** A plain element's drag internals: none. */
|
|
2913
|
+
const NO_DRAG_INTERNALS = {};
|
|
2914
|
+
/**
|
|
2915
|
+
* The drag axis a spine runs with: its static `drag` config, else `true` for a
|
|
2916
|
+
* `<Reorder>` item (its gesture's axis comes from `dragAxis`), else none.
|
|
2917
|
+
*/
|
|
2918
|
+
export const dragAxisOf = (config, internal = NO_DRAG_INTERNALS) => Option.getOrUndefined(Option.orElse(Option.filter(Option.fromUndefinedOr(config.drag), drag => drag !== false), () => Option.map(Option.fromUndefinedOr(internal.dragAxis), () => true)));
|
|
2919
|
+
/**
|
|
2920
|
+
* A drag element's defaults (ADR-0019 *Amendment (Reorder)*): its axis's, unless its own presses don't
|
|
2921
|
+
* drag it (`dragListener={false}`, #431), as Motion's come with its listener.
|
|
2922
|
+
*/
|
|
2923
|
+
export const dragDefaultsOf = (config, internal = NO_DRAG_INTERNALS) => {
|
|
2924
|
+
if (config.dragListener === false) return undefined;
|
|
2925
|
+
return UndefinedOr.map(dragAxisOf(config, internal), Style.dragDefaults);
|
|
2926
|
+
};
|
|
2927
|
+
/**
|
|
2928
|
+
* Set each of a drag element's defaults its inline style doesn't already set, and
|
|
2929
|
+
* `draggable="false"` unless it has the attribute, at mount: for an element whose props don't carry
|
|
2930
|
+
* them, a directive's (`use:wardic`, `use:w`) and a `wardic.create(Component)` wrap's, whose
|
|
2931
|
+
* component may not pass them on.
|
|
2932
|
+
*/
|
|
2933
|
+
export const applyDragDefaults = (element, defaults) => {
|
|
2934
|
+
Arr.forEach(Rec.keys(defaults), key => {
|
|
2935
|
+
if (element.style.getPropertyValue(key) === "") element.style.setProperty(key, UndefinedOr.getOrThrow(defaults[key]));
|
|
2936
|
+
});
|
|
2937
|
+
if (!element.hasAttribute("draggable")) element.setAttribute("draggable", Style.DRAG_DEFAULT_ATTRIBUTES.draggable);
|
|
2938
|
+
};
|
|
2939
|
+
//# sourceMappingURL=spine.js.map
|