solidjs-motion 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/LICENSE +21 -0
  3. package/README.md +140 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +2627 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/default-values.d.ts +6 -0
  8. package/dist/src/index.d.ts +16 -0
  9. package/dist/src/motion-config.d.ts +14 -0
  10. package/dist/src/motion-proxy.d.ts +103 -0
  11. package/dist/src/presence-context.d.ts +4 -0
  12. package/dist/src/presence.d.ts +95 -0
  13. package/dist/src/primitives/createDrag.d.ts +16 -0
  14. package/dist/src/primitives/createDragControls.d.ts +30 -0
  15. package/dist/src/primitives/createGestures.d.ts +8 -0
  16. package/dist/src/primitives/createInView.d.ts +51 -0
  17. package/dist/src/primitives/createMotion.d.ts +82 -0
  18. package/dist/src/primitives/createPan.d.ts +83 -0
  19. package/dist/src/primitives/createScroll.d.ts +40 -0
  20. package/dist/src/primitives/gesture-state.d.ts +108 -0
  21. package/dist/src/primitives/motion-value.d.ts +111 -0
  22. package/dist/src/primitives/value-registry.d.ts +34 -0
  23. package/dist/src/reduced-motion.d.ts +29 -0
  24. package/dist/src/style.d.ts +79 -0
  25. package/dist/src/types.d.ts +374 -0
  26. package/dist/src/use-motion.d.ts +35 -0
  27. package/dist/src/variants.d.ts +64 -0
  28. package/package.json +78 -0
  29. package/src/default-values.ts +52 -0
  30. package/src/index.ts +60 -0
  31. package/src/motion-config.tsx +37 -0
  32. package/src/motion-proxy.tsx +377 -0
  33. package/src/presence-context.ts +32 -0
  34. package/src/presence.tsx +466 -0
  35. package/src/primitives/createDrag.ts +670 -0
  36. package/src/primitives/createDragControls.ts +101 -0
  37. package/src/primitives/createGestures.ts +145 -0
  38. package/src/primitives/createInView.ts +124 -0
  39. package/src/primitives/createMotion.ts +638 -0
  40. package/src/primitives/createPan.ts +338 -0
  41. package/src/primitives/createScroll.ts +101 -0
  42. package/src/primitives/gesture-state.ts +772 -0
  43. package/src/primitives/motion-value.ts +328 -0
  44. package/src/primitives/value-registry.ts +114 -0
  45. package/src/reduced-motion.ts +51 -0
  46. package/src/style.ts +266 -0
  47. package/src/types.ts +538 -0
  48. package/src/use-motion.tsx +412 -0
  49. package/src/variants.ts +134 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,117 @@
1
+ # Changelog
2
+
3
+ All notable changes to `solidjs-motion` / `@solidjs-motion/motion` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] — 2026-05-20
9
+
10
+ First public release. Five phases of the port plan land together: the canonical
11
+ animation surface, gestures + drag, exit animations via `<Presence>`, the
12
+ JSX-level `motion.X` proxy + `motion.create(...)` HOC, and motion values
13
+ embedded directly in `style` (`style={{ x: mv }}`).
14
+
15
+ ### Added — primitives (Phase 1)
16
+
17
+ - `useMotion(opts)` — canonical hook. Returns a callable `m` that merges user
18
+ props with motion's. Accepts a static options object or a function for
19
+ reactive options (Solid signals tracked inside).
20
+ - `createMotion(el, opts)` — imperative primitive underneath `useMotion`.
21
+ - The `MotionValueAccessor<T>` callable-hybrid family — every primitive is
22
+ both a Solid Accessor and an upstream `MotionValue`:
23
+ - `createMotionValue<T>(initial)`
24
+ - `createTransform<I, O>(input, range, output, opts?)`
25
+ - `createSpring(source, opts?)`
26
+ - `createTime()`
27
+ - `createVelocity(source)`
28
+ - `createTemplate\`…\``
29
+ - `createMotionValueEvent(mv, event, cb)`
30
+ - `toSignal(rawMv)` — bridge for raw upstream `motion.motionValue()`
31
+ - `createScroll(opts?)` — scroll progress with four fields, all
32
+ `MotionValueAccessor<number>`.
33
+ - `createInView(ref, opts?)` — boolean Accessor, supports `amount: number[]`
34
+ for live `intersectionRatio` readouts.
35
+ - `createReducedMotion()` — boolean Accessor backed by `matchMedia`.
36
+ - `<MotionConfig>` — flows `reducedMotion`, default `transition`, and CSP
37
+ `nonce` to descendants.
38
+ - Variant resolution: `VariantContext`, `useVariantContext`, `resolveVariant`,
39
+ `effectiveLabels`, `isControllingVariants` — full motion-dom parity for
40
+ variant cascade and the "controlling" rule.
41
+
42
+ ### Added — gestures + drag (Phase 2)
43
+
44
+ - `hover`, `press`, `focus`, `inView` gestures via motion-dom primitives,
45
+ surfaced through `MotionOptions`.
46
+ - `createPan` standalone primitive (Q11 / D3 base) — pointer-pan with
47
+ velocity callbacks.
48
+ - `createDrag` via motion-dom `VisualElement` — axis-locked dragging,
49
+ elastic constraints, release momentum with bounce-back, snap-to-origin,
50
+ `whileDrag` variant.
51
+ - `createDragControls` factory + `dragControls` prop for external drag-handle
52
+ composition (Q9).
53
+ - Solid-native gesture state machine with priority order
54
+ `exit > drag > inView > focus > press > hover > animate > initial`.
55
+ - `ViewportOptions.amount` accepts `number[]` for stepwise viewport progress.
56
+
57
+ ### Added — Presence (Phase 3)
58
+
59
+ - `<Presence>` component for exit animations. Auto-detects single-child
60
+ (`<Show>`-style switch) or list (`<For>`-style) via first resolution.
61
+ - `mode: "sync" | "wait"`, `initial` (default `true`).
62
+ - `useAnimatePresence()` hook — sibling primitive over the same context;
63
+ returns `{ Provider, exit() }` for imperative orchestration.
64
+ - Subtree-walk exit registration: ancestor `<Presence>` waits for nested
65
+ motion descendants with `exit` targets, including reactive subtrees and
66
+ off-DOM nodes.
67
+ - SSR pass-through: server emits the same JSX shape as the client (Solid
68
+ hydration markers align cleanly).
69
+
70
+ ### Added — JSX wrappers (Phase 4)
71
+
72
+ - `motion.div`, `motion.span`, `motion.path`, … — callable `Proxy` with a
73
+ cached per-tag factory. Each tag-component auto-wraps its rendered output
74
+ in the variant `Provider` so motion descendants inherit context without an
75
+ explicit wrapper.
76
+ - `motion.create(Component)` — HOC for user components. Wrapped component
77
+ must spread its props onto a single HTML/SVG element root (same implicit
78
+ contract Solid already requires). Dev-mode wrap-validity check warns on
79
+ misuse.
80
+ - SVG namespace handled via `<Dynamic>` from `solid-js/web`. Element types
81
+ widened to `HTMLElement | SVGElement` (`MotionElement`).
82
+
83
+ ### Added — MotionValues in `style` (Phase 5)
84
+
85
+ - `style={{ x: mv, scale: mv, opacity: mv, … }}` — motion-react fidelity.
86
+ Plain numbers and `MotionValue`s mix freely; the engine cooperates by
87
+ writing animation output back through the MVs (so external subscribers see
88
+ the same stream).
89
+ - Per-element value registry (motion-react's `visualElement.values`).
90
+ - `animate(mv, value, opts)` bridge when a key has a registered MV;
91
+ `animate(el, target, opts)` otherwise.
92
+ - Specialized writer + per-key formatter compiled at registry-shape change
93
+ for transform composition without per-frame string reparsing.
94
+ - `MotionStyle = MotionTransformShortcuts & WithMotionValues<…>` — typed
95
+ intersection that's assignable to both JSX `style` and back to `MotionStyle`
96
+ for chaining.
97
+
98
+ ### Added — tooling, infra, docs
99
+
100
+ - Dual-publish manifests for npm (`solidjs-motion`) and JSR
101
+ (`@solidjs-motion/motion`).
102
+ - Vite library mode build (`vite-plugin-solid` + `vite-plugin-dts`); ship-source
103
+ pattern with the `solid` export condition listed before `types` so consumers
104
+ using `vite-plugin-solid` resolve to raw source.
105
+ - Vitest harness — 141+ tests across browser (jsdom) and SSR (separate
106
+ `vitest.ssr.config.ts`), plus compile-time type tests via `expectTypeOf`.
107
+ - `vitest bench` suite (Phase 4 verification gate) — 8 benches covering
108
+ proxy/explicit, `useMotion` mount, state-machine flip, MotionValue fanout
109
+ + construction, drag tick, variant resolution, Presence roundtrip.
110
+ Baselines in `bench/BASELINES.md`.
111
+ - `MotionConfig` CSP nonce flow.
112
+ - ADRs: 0001 (lean on motion-dom for Phase 2), 0002 (Solid-native gesture
113
+ state machine), 0003 (Presence via transition-group + inverted context),
114
+ 0004 (motion proxy + HOC), 0005 (MV-in-style via per-element value
115
+ registry).
116
+
117
+ [0.1.0]: https://github.com/solidjs-motion/motion/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 solidjs-motion contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # solidjs-motion
2
+
3
+ An animation library for [SolidJS](https://solidjs.com) — a port of `motion/react` patterns
4
+ built on the framework-agnostic [`motion`](https://motion.dev) package.
5
+
6
+ > **Status: pre-alpha (0.0.x).** Phases 1 through 4 are landed — the v0.1
7
+ > public surface is feature-complete and stabilizing. Live demos:
8
+ > [solidjs-motion.github.io/motion](https://solidjs-motion.github.io/motion/).
9
+
10
+ ## Install
11
+
12
+ ### npm
13
+
14
+ ```bash
15
+ bun add solidjs-motion motion solid-js
16
+ # or: npm i solidjs-motion motion solid-js
17
+ ```
18
+
19
+ ### JSR
20
+
21
+ ```bash
22
+ bunx jsr add @solidjs-motion/motion
23
+ ```
24
+
25
+ `motion`, `motion-dom`, and `solid-js` are peer dependencies — install them alongside.
26
+
27
+ ## Quick taste
28
+
29
+ ```tsx
30
+ import { useMotion } from "solidjs-motion"
31
+
32
+ export function Card() {
33
+ const motion = useMotion({
34
+ initial: { opacity: 0, y: 20 },
35
+ animate: { opacity: 1, y: 0 },
36
+ transition: { duration: 0.6 },
37
+ hover: { scale: 1.02 },
38
+ press: { scale: 0.98 },
39
+ })
40
+
41
+ return <div {...motion({ class: "card" })}>Hello, motion.</div>
42
+ }
43
+ ```
44
+
45
+ `useMotion` returns a function that merges your props with motion's. User styles deep-merge
46
+ with motion's initial styles; user refs and motion's ref both fire; the initial style is
47
+ serialized into SSR HTML so the first paint is flicker-free.
48
+
49
+ ## Roadmap
50
+
51
+ ### Shipped
52
+
53
+ **Canonical hook + imperative primitive**
54
+
55
+ - `useMotion(opts | () => opts)` — the public API. Returns a callable `motion(userProps?)` that merges with motion's ref/style/data attributes, plus a `motion.Provider` for opt-in variant context propagation.
56
+ - `createMotion(el, getOpts)` — the imperative primitive `useMotion` wraps, for advanced use (drag controls, custom directives).
57
+
58
+ **MotionValue family** (every value is a callable `MotionValueAccessor<T> = MotionValue<T> & (() => T)`)
59
+
60
+ - `createMotionValue(initial)` — bound to the current owner; auto-disposed on cleanup.
61
+ - `createTransform(input, range, output, opts?)` — map a MV/Accessor through a numeric range.
62
+ - `createSpring(source, opts?)` — physics-smoothed mirror of a numeric input.
63
+ - `createTime()` — frame-driver advancing each animation frame with elapsed ms.
64
+ - `createVelocity(source)` — reports the instantaneous velocity of another MV.
65
+ - `createTemplate\`…\`` — tagged template producing a `MotionValueAccessor<string>` from interpolated MVs/Accessors.
66
+ - `createMotionValueEvent(mv, event, cb)` — subscribe with automatic cleanup.
67
+ - `toSignal(rawMv)` — bridge a raw motion `MotionValue` to a Solid Accessor.
68
+
69
+ **Scroll + viewport**
70
+
71
+ - `createScroll(opts?)` — `{ scrollX, scrollY, scrollXProgress, scrollYProgress }` MotionValueAccessors.
72
+ - `createInView(ref, opts?)` — IntersectionObserver wrapper; `view.isInView()` boolean Accessor, `view.entry()` Accessor of the raw `IntersectionObserverEntry`. Accepts `amount: number[]` for continuous `intersectionRatio` updates.
73
+
74
+ **Gestures** (declarative on `useMotion` options)
75
+
76
+ - `hover` / `press` / `focus` — variant or target object per state. State machine resolves per-property winners across simultaneous states (press > focus > hover > inView > animate).
77
+ - `inView` — viewport-triggered variant; honors `inViewOptions: ViewportOptions` (margin, amount, root, once).
78
+ - Callbacks: `onHoverStart`/`onHoverEnd`, `onPressStart`/`onPress`/`onPressCancel`, `onFocus`/`onBlur`, `onViewportEnter`/`onViewportLeave`.
79
+
80
+ **Drag**
81
+
82
+ - `drag: true | "x" | "y"` axis lock, `dragConstraints` (numeric or container ref), `dragElastic`, `dragMomentum`, `dragSnapToOrigin`, `dragTransition`, `whileDrag` for sibling-axis visual state.
83
+ - `createPan(ref, opts?)` — standalone pan-session primitive. Returns `{ isPanning, point, delta, offset, velocity }` with MotionValueAccessors at the numeric leaves.
84
+ - `createDragControls()` — drag-handle pattern. One element captures the pointer, another moves.
85
+
86
+ **Variants**
87
+
88
+ - Named variants on `variants: { … }`. Parent labels cascade to descendants via `motion.Provider`.
89
+ - "Controlling variants" rule: a child with its own variant label opts out of the parent cascade (motion-dom parity).
90
+ - Dynamic variants: each variant can be a function of `custom` for per-instance staggering and per-index timing.
91
+
92
+ **Presence + exit animations**
93
+
94
+ - `<Presence>` — coordinator that runs each child's `exit` target before unmount. Works with `<Show>`, `<For>`, and arbitrary mount/unmount toggles.
95
+ - `mode: "sync" | "wait"` — synchronous swap (default) or sequential swap where the outgoing child exits fully before the incoming child enters.
96
+ - `initial: false` — suppress the entrance animation for the initial mount; subsequent mounts animate.
97
+ - `useAnimatePresence()` — imperative escape hatch returning `{ Provider, exit() }` for cases where you need to await exit completion before flipping state yourself.
98
+ - Descendant-walk exit registration: passive children inside `m.Provider` with a `variants` map keyed off the parent's exit label exit alongside the parent automatically (the orchestrated-exit cascade).
99
+
100
+ **`<motion.X>` proxy + `motion.create(Component)` HOC**
101
+
102
+ - `motion.div`, `motion.span`, `motion.path` — every HTML/SVG intrinsic element accessed off `motion` returns a typed `Component` whose props are that element's native attributes intersected with `MotionOptions`. SVG namespace handled via `<Dynamic>`.
103
+ - Each tag-component auto-wraps its rendered output in `m.Provider`, so variant cascade reaches descendants without manual wrapping for the common case.
104
+ - `motion.create(MyComponent)` — HOC for custom components. The wrapped component must forward `props.ref` to a single DOM-element root (Solid's "ref forwarding by convention" reality). A dev-mode warning fires if the wrap is broken.
105
+ - See [ADR 0004](../../docs/adr/0004-motion-proxy-and-hoc.md) for the design rationale.
106
+
107
+ **MV-in-style** (`<motion.div style={{ scale: mv }}>`)
108
+
109
+ - Pass any `MotionValue` directly in `style` — motion subscribes to it and writes the corresponding DOM property/transform on every change. No React-style re-render cycle.
110
+ - Composes with `initial`, `animate`, gestures, and `exit` on the same key: the MV is the source of truth, and animate dispatches tween THROUGH the MV (matches motion-react fidelity).
111
+ - Static transform shortcuts (`x: 10`, `scale: 1.5`) also work — motion composes them into the `transform` string in canonical order (translate → scale → rotate).
112
+ - SSR-aware: the MV's snapshot value lands in the rendered HTML so client hydration is flicker-free.
113
+ - `MotionStyle` type widens `JSX.CSSProperties` to accept `MotionValue` in every slot, plus motion's transform shortcuts.
114
+ - See [ADR 0005](../../docs/adr/0005-mv-in-style-value-registry.md) for the per-element value-registry architecture.
115
+
116
+ **Config + reduced motion**
117
+
118
+ - `<MotionConfig transition reducedMotion nonce>` — shared defaults for a subtree.
119
+ - `createReducedMotion()` — reactive system-pref accessor backed by `matchMedia("(prefers-reduced-motion)")`.
120
+
121
+ **SSR**
122
+
123
+ - `useMotion` emits a deterministic inline style + `data-motion-hydrated=""` marker on the server. First paint matches the initial target; the client skips the initial-style application on hydration.
124
+
125
+ **Re-exports from upstream `motion`**
126
+
127
+ - `animate`, `inView`, `isMotionValue`, `motionValue`, `scroll`, `spring` — for direct use where the framework wrapper isn't needed.
128
+
129
+ ### Deferred to v0.2+
130
+
131
+ - Layout animations (`layout` prop, `LayoutGroup`).
132
+ - `layoutId` shared-element transitions.
133
+ - `<Reorder>` drag-to-reorder primitive.
134
+ - SVG path drawing (`<motion.path pathLength>`).
135
+ - `useAnimate` imperative AnimationControls equivalent.
136
+ - `LazyMotion` lazy-loaded feature bundles.
137
+
138
+ ## License
139
+
140
+ [MIT](./LICENSE) — copyright the solidjs-motion contributors.
@@ -0,0 +1,2 @@
1
+ export * from './src/index'
2
+ export {}