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.
- package/CHANGELOG.md +117 -0
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2627 -0
- package/dist/index.js.map +1 -0
- package/dist/src/default-values.d.ts +6 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/motion-config.d.ts +14 -0
- package/dist/src/motion-proxy.d.ts +103 -0
- package/dist/src/presence-context.d.ts +4 -0
- package/dist/src/presence.d.ts +95 -0
- package/dist/src/primitives/createDrag.d.ts +16 -0
- package/dist/src/primitives/createDragControls.d.ts +30 -0
- package/dist/src/primitives/createGestures.d.ts +8 -0
- package/dist/src/primitives/createInView.d.ts +51 -0
- package/dist/src/primitives/createMotion.d.ts +82 -0
- package/dist/src/primitives/createPan.d.ts +83 -0
- package/dist/src/primitives/createScroll.d.ts +40 -0
- package/dist/src/primitives/gesture-state.d.ts +108 -0
- package/dist/src/primitives/motion-value.d.ts +111 -0
- package/dist/src/primitives/value-registry.d.ts +34 -0
- package/dist/src/reduced-motion.d.ts +29 -0
- package/dist/src/style.d.ts +79 -0
- package/dist/src/types.d.ts +374 -0
- package/dist/src/use-motion.d.ts +35 -0
- package/dist/src/variants.d.ts +64 -0
- package/package.json +78 -0
- package/src/default-values.ts +52 -0
- package/src/index.ts +60 -0
- package/src/motion-config.tsx +37 -0
- package/src/motion-proxy.tsx +377 -0
- package/src/presence-context.ts +32 -0
- package/src/presence.tsx +466 -0
- package/src/primitives/createDrag.ts +670 -0
- package/src/primitives/createDragControls.ts +101 -0
- package/src/primitives/createGestures.ts +145 -0
- package/src/primitives/createInView.ts +124 -0
- package/src/primitives/createMotion.ts +638 -0
- package/src/primitives/createPan.ts +338 -0
- package/src/primitives/createScroll.ts +101 -0
- package/src/primitives/gesture-state.ts +772 -0
- package/src/primitives/motion-value.ts +328 -0
- package/src/primitives/value-registry.ts +114 -0
- package/src/reduced-motion.ts +51 -0
- package/src/style.ts +266 -0
- package/src/types.ts +538 -0
- package/src/use-motion.tsx +412 -0
- 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.
|
package/dist/index.d.ts
ADDED