glimmer-motion 0.0.0 → 0.1.0-unstable.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 (118) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +230 -6
  4. package/VENDORED.md +111 -0
  5. package/addon-main.cjs +4 -0
  6. package/declarations/activity.d.ts +42 -0
  7. package/declarations/activity.d.ts.map +1 -0
  8. package/declarations/features.d.ts +2 -0
  9. package/declarations/features.d.ts.map +1 -0
  10. package/declarations/framer-motion-internals.d.ts +65 -0
  11. package/declarations/framer-motion-internals.d.ts.map +1 -0
  12. package/declarations/gestures/drag-controls.d.ts +9 -0
  13. package/declarations/gestures/drag-controls.d.ts.map +1 -0
  14. package/declarations/gestures/drag-gesture.d.ts +28 -0
  15. package/declarations/gestures/drag-gesture.d.ts.map +1 -0
  16. package/declarations/gestures/lock-select.d.ts +3 -0
  17. package/declarations/gestures/lock-select.d.ts.map +1 -0
  18. package/declarations/gestures/transform-page-point.d.ts +18 -0
  19. package/declarations/gestures/transform-page-point.d.ts.map +1 -0
  20. package/declarations/helpers.d.ts +116 -0
  21. package/declarations/helpers.d.ts.map +1 -0
  22. package/declarations/index.d.ts +36 -0
  23. package/declarations/index.d.ts.map +1 -0
  24. package/declarations/layout-group.d.ts +59 -0
  25. package/declarations/layout-group.d.ts.map +1 -0
  26. package/declarations/layout.d.ts +38 -0
  27. package/declarations/layout.d.ts.map +1 -0
  28. package/declarations/motion-config.d.ts +45 -0
  29. package/declarations/motion-config.d.ts.map +1 -0
  30. package/declarations/motion.d.ts +20 -0
  31. package/declarations/motion.d.ts.map +1 -0
  32. package/declarations/node.d.ts +109 -0
  33. package/declarations/node.d.ts.map +1 -0
  34. package/declarations/participant-args.d.ts +10 -0
  35. package/declarations/participant-args.d.ts.map +1 -0
  36. package/declarations/participant.d.ts +84 -0
  37. package/declarations/participant.d.ts.map +1 -0
  38. package/declarations/presence-types.d.ts +23 -0
  39. package/declarations/presence-types.d.ts.map +1 -0
  40. package/declarations/presence.d.ts +89 -0
  41. package/declarations/presence.d.ts.map +1 -0
  42. package/declarations/reorder/capture.d.ts +11 -0
  43. package/declarations/reorder/capture.d.ts.map +1 -0
  44. package/declarations/reorder/group.d.ts +50 -0
  45. package/declarations/reorder/group.d.ts.map +1 -0
  46. package/declarations/reorder/item.d.ts +70 -0
  47. package/declarations/reorder/item.d.ts.map +1 -0
  48. package/declarations/reorder/types.d.ts +16 -0
  49. package/declarations/reorder/types.d.ts.map +1 -0
  50. package/declarations/scheduler.d.ts +10 -0
  51. package/declarations/scheduler.d.ts.map +1 -0
  52. package/declarations/scroll.d.ts +51 -0
  53. package/declarations/scroll.d.ts.map +1 -0
  54. package/declarations/speed.d.ts +25 -0
  55. package/declarations/speed.d.ts.map +1 -0
  56. package/declarations/test-support/index.d.ts +79 -0
  57. package/declarations/test-support/index.d.ts.map +1 -0
  58. package/declarations/unitless.d.ts +3 -0
  59. package/declarations/unitless.d.ts.map +1 -0
  60. package/declarations/view-transition.d.ts +6 -0
  61. package/declarations/view-transition.d.ts.map +1 -0
  62. package/dist/activity.js +69 -0
  63. package/dist/activity.js.map +1 -0
  64. package/dist/features.js +92 -0
  65. package/dist/features.js.map +1 -0
  66. package/dist/framer-motion-internals.js +1783 -0
  67. package/dist/framer-motion-internals.js.map +1 -0
  68. package/dist/gestures/drag-controls.js +12 -0
  69. package/dist/gestures/drag-controls.js.map +1 -0
  70. package/dist/gestures/drag-gesture.js +82 -0
  71. package/dist/gestures/drag-gesture.js.map +1 -0
  72. package/dist/gestures/lock-select.js +37 -0
  73. package/dist/gestures/lock-select.js.map +1 -0
  74. package/dist/gestures/transform-page-point.js +86 -0
  75. package/dist/gestures/transform-page-point.js.map +1 -0
  76. package/dist/helpers.js +106 -0
  77. package/dist/helpers.js.map +1 -0
  78. package/dist/index.js +21 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/layout-group.js +97 -0
  81. package/dist/layout-group.js.map +1 -0
  82. package/dist/layout.js +173 -0
  83. package/dist/layout.js.map +1 -0
  84. package/dist/motion-config.js +48 -0
  85. package/dist/motion-config.js.map +1 -0
  86. package/dist/motion.js +30 -0
  87. package/dist/motion.js.map +1 -0
  88. package/dist/node.js +843 -0
  89. package/dist/node.js.map +1 -0
  90. package/dist/participant-args.js +18 -0
  91. package/dist/participant-args.js.map +1 -0
  92. package/dist/participant.js +90 -0
  93. package/dist/participant.js.map +1 -0
  94. package/dist/presence-types.js +2 -0
  95. package/dist/presence-types.js.map +1 -0
  96. package/dist/presence.js +290 -0
  97. package/dist/presence.js.map +1 -0
  98. package/dist/reorder/capture.js +12 -0
  99. package/dist/reorder/capture.js.map +1 -0
  100. package/dist/reorder/group.js +118 -0
  101. package/dist/reorder/group.js.map +1 -0
  102. package/dist/reorder/item.js +66 -0
  103. package/dist/reorder/item.js.map +1 -0
  104. package/dist/reorder/types.js +2 -0
  105. package/dist/reorder/types.js.map +1 -0
  106. package/dist/scheduler.js +19 -0
  107. package/dist/scheduler.js.map +1 -0
  108. package/dist/scroll.js +125 -0
  109. package/dist/scroll.js.map +1 -0
  110. package/dist/speed.js +91 -0
  111. package/dist/speed.js.map +1 -0
  112. package/dist/test-support/index.js +219 -0
  113. package/dist/test-support/index.js.map +1 -0
  114. package/dist/unitless.js +20 -0
  115. package/dist/unitless.js.map +1 -0
  116. package/dist/view-transition.js +70 -0
  117. package/dist/view-transition.js.map +1 -0
  118. package/package.json +162 -8
package/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ All notable changes to `glimmer-motion` are recorded here.
4
+
5
+ This file follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ `glimmer-motion` and `@cardstack/choreo` release in lockstep: every version
9
+ of one is a version of the other, and `@cardstack/choreo` peer-depends on the
10
+ exact `glimmer-motion` version it was released with.
11
+
12
+ Pre-1.0 caveat: the public API is intentionally unstable. Minor and patch
13
+ versions may change behavior until `1.0.0`.
14
+
15
+ ## [Unreleased]
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cardstack Foundation
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 CHANGED
@@ -1,9 +1,233 @@
1
1
  # glimmer-motion
2
2
 
3
- This version is a placeholder. It reserves the package name so that
4
- releases can be published from the
5
- [cardstack/boxel](https://github.com/cardstack/boxel) monorepo through npm
6
- Trusted Publishing. It contains no code.
3
+ The [Motion](https://motion.dev) engine for Ember. `{{motion}}`, `<Presence>`, `<LayoutGroup>`,
4
+ Reorder and drag, verified by ports of Motion's own test suites.
7
5
 
8
- Real versions are published under the `unstable` dist-tag first, and
9
- under `latest` once a stable release is cut.
6
+ `<Choreo>`, a changeset and a timeline over a whole render pass, is a separate package built on this
7
+ one: [`@cardstack/choreo`](../choreo).
8
+
9
+ ```gts
10
+ import { motion, Presence, LayoutGroup, to, spring } from 'glimmer-motion';
11
+
12
+ <template>
13
+ <LayoutGroup>
14
+ <Presence @items={{this.cards}} @key={{this.keyOf}} as |card h|>
15
+ <div
16
+ {{motion
17
+ presence=h
18
+ layoutId=card.id
19
+ initial=(to opacity=0)
20
+ animate=(to opacity=1)
21
+ exit=(to opacity=0)
22
+ transition=(spring stiffness=300 damping=30)
23
+ drag='x'
24
+ dragSnapToOrigin=true
25
+ }}
26
+ >
27
+ {{card.title}}
28
+ </div>
29
+ </Presence>
30
+ </LayoutGroup>
31
+ </template>
32
+ ```
33
+
34
+ ## Install
35
+
36
+ ```
37
+ pnpm add glimmer-motion motion-dom motion-utils
38
+ ```
39
+
40
+ Peers: `motion-dom` / `motion-utils` (pinned together), `ember-modifier`, `@glimmer/component`,
41
+ `@glimmer/tracking`, `ember-source >= 5.4`. A v2 addon — Embroider and Vite apps consume it directly, with
42
+ TypeScript types and Glint signatures.
43
+
44
+ New here? The [guide](https://github.com/cardstack/choreo/blob/main/docs/guide.md) teaches this
45
+ from a Glimmer card rather than from a React translation table.
46
+
47
+ ## Features
48
+
49
+ - **Animation** — `initial` / `animate` / `exit`, keyframes, springs/tweens/inertia, variants with
50
+ propagation and stagger orchestration, motion values through `style`, SVG attributes, animation lifecycle events
51
+ - **Layout** — `layout` FLIP animation with scale correction, `layoutId` shared-element transitions and
52
+ crossfade, `<LayoutGroup>`, nested/relative projection, portals, `layoutChange()` / `instantLayoutTransition()`
53
+ - **Presence** — `<Presence>` with `sync` / `wait` / `popLayout`, `@initial={{false}}`, `@custom`,
54
+ nested `@propagate`, tracked `h.isPresent`
55
+ - **Drag** — Motion's pan/drag session: axis lock, direction lock, constraints (object / element / ref,
56
+ re-measured on resize), elastic, momentum, snap to origin, `createDragControls()`, `whileDrag`,
57
+ drag + layout, scroll-while-drag, `correctParentTransform()` / `transformViewBoxPoint()`
58
+ - **Gestures** — `whileHover` / `whileTap` / `whileFocus` / `whileInView` and their handlers,
59
+ `<MotionConfig>` tree defaults, `scrollProgress()` / `InView` over Motion's `scroll()` / `inView()`
60
+ - **Reorder** — `<ReorderGroup>` / `<ReorderItem>`, axis `x` / `y` / `xy` (detected), auto-scroll
61
+ - **Glimmer** — `.gts`, Glint signatures, named exports, plain-function template helpers
62
+ (`to` / `spring` / `tween` / `styles` / `start`), and `prefers-reduced-motion` honoured by default
63
+ - **Testing** — `glimmer-motion/test-support`: `animationsSettled()`, `bounds()`, `shape()`,
64
+ `setupMotion(hooks)`, and `registerMotionReset()` for a layer that keeps document-wide state of
65
+ its own. No `sleep()` in a motion test
66
+ - **Re-hostable** — host hooks are ~40 lines plus the components; everything above that line is
67
+ framework-free
68
+
69
+ ## API
70
+
71
+ | export | what |
72
+ | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
73
+ | `motion` | the modifier: Motion's props as named arguments, plus `presence` and `transformPagePoint` |
74
+ | `Presence` | `@items @key @mode @initial @custom @onExitComplete @propagate @parent @anchorX @anchorY`, yields `item, handle` |
75
+ | `LayoutGroup` | `@id @inherit`; hosts the render detector that snapshots layout before the DOM changes |
76
+ | `ReorderGroup`, `ReorderItem` | `@values @onReorder @axis` yielding `group`; `@group @value` + forwarded motion args |
77
+ | `layoutChange(fn)`, `snapshotAll()`, `requestSettle()`, `afterSettle(fn)`, `instantLayoutTransition(fn)` | layout pipeline |
78
+ | `createDragControls()`, `DragControls` | `useDragControls` |
79
+ | `correctParentTransform(elOrRef)`, `transformViewBoxPoint(svgOrRef)` | `transformPagePoint` helpers |
80
+ | `MotionNode`, `postRender`, `setPostRender`, `flushPendingMounts` | for re-hosting on another Glimmer runtime |
81
+ | `setParticipantHost`, `closestParticipantHost`, `defineParticipantArg`, `ParticipantHost`, `MotionParticipant` | the participant-host extension point (below) |
82
+ | `registerBusyProbe`, `BusyProbe` | count a host's own in-flight work as motion (below) |
83
+ | `motionValue`, `MotionValue`, `transformValue`, `styleEffect`, `frame`, `animate` | the engine's imperative surface (below) |
84
+
85
+ Deep imports (`glimmer-motion/motion`, `glimmer-motion/presence`, `glimmer-motion/reorder/group`, …) are the
86
+ same modules.
87
+
88
+ ### Participant hosts
89
+
90
+ `glimmer-motion/participant` lets a component that coordinates many motion elements (a choreography, a
91
+ shared-element transition) take part in their lifecycles without the elements knowing about it. `<Choreo>`
92
+ is built on it. The interface is public API under semver: a change to it is a breaking change for every
93
+ host package.
94
+
95
+ A host is an object that implements `ParticipantHost`, installed on an element it renders:
96
+
97
+ ```gts
98
+ import { modifier } from 'ember-modifier';
99
+ import {
100
+ type MotionParticipant,
101
+ type ParticipantHost,
102
+ setParticipantHost,
103
+ } from 'glimmer-motion/participant';
104
+
105
+ class Stage implements ParticipantHost {
106
+ register(participant: MotionParticipant) {
107
+ // on mount; return what to run on its teardown
108
+ return () => {};
109
+ }
110
+ claim(participant: MotionParticipant) {
111
+ // on teardown: true keeps its VisualElement mounted until participant.release()
112
+ return false;
113
+ }
114
+ }
115
+
116
+ const hosted = modifier((el: Element, [host]: [ParticipantHost]) => {
117
+ setParticipantHost(el, host);
118
+ return () => setParticipantHost(el, undefined);
119
+ });
120
+
121
+ const stage = new Stage();
122
+
123
+ <template>
124
+ <div data-motion-host {{hosted stage}}>
125
+ <div {{motion id='card'}}></div>
126
+ </div>
127
+ </template>
128
+ ```
129
+
130
+ - **Who joins.** A `{{motion}}` element with an `id` or a `role` joins the nearest `data-motion-host`
131
+ ancestor when it mounts. `id` is identity across renders, and `role` is a group the host can select by.
132
+ Elements with neither never join.
133
+ - **Discovery.** The `data-motion-host` attribute belongs in the host's markup, not in its modifier.
134
+ Modifiers install children-first, so a marked element whose host has not installed yet resolves to no host,
135
+ never to an outer one.
136
+ - **Lifecycle.** `register` runs on mount. On teardown the node calls the function `register` returned, then
137
+ asks `claim`. A host that claims a leaving element owns its unmount: it calls `participant.release()` when it
138
+ is done, and `participant.exitComplete()` to let an enclosing `<Presence>` finish the exit.
139
+ - **What a host sees.** `MotionParticipant` exposes `element`, `visualElement`, `id`, `role`, `isPresent`,
140
+ `layoutKey`, `ownAnimation` and `presenceManaged`. `visualElement` is motion-dom's `VisualElement`, so a host
141
+ package and glimmer-motion must resolve the same motion-dom.
142
+ - **Host args.** A host can add named args to `{{motion}}`. It declares each one by augmenting
143
+ `ParticipantArgs` and registers it with `defineParticipantArg(name, apply)`. The modifier keeps the arg away
144
+ from the engine and calls `apply(element, value)` on every pass, with `undefined` when the arg is absent.
145
+ `defineParticipantArg` returns a remover. Put the augmentation in a module that the host package's public
146
+ declarations import, or it won't reach that package's consumers. `<Choreo>` declares `pack` this way:
147
+
148
+ ```ts
149
+ declare module 'glimmer-motion/participant' {
150
+ interface ParticipantArgs {
151
+ pack?: 'box' | 'content';
152
+ }
153
+ }
154
+ defineParticipantArg('pack', (el, pack) => {
155
+ /* … */
156
+ });
157
+ ```
158
+
159
+ - **Busy probes.** A host whose work outlasts the engine's own animations (a timeline between steps, a
160
+ barrier waiting on another region) registers a `BusyProbe` with `registerBusyProbe(probe)`. The probe
161
+ answers `false` at rest or a short reason while busy, and `animationsSettled()` / `whatIsBusy()` from
162
+ `glimmer-motion/test-support` consult it alongside the frame loop and the projection tree. It returns a
163
+ remover: a probe over one host instance's state is removed in that instance's destructor, and a probe over
164
+ module-global state may stay registered for the life of the page.
165
+
166
+ ### The engine's imperative surface
167
+
168
+ A few of the engine's own functions are exported from `glimmer-motion` directly, for code that drives motion
169
+ values by hand rather than through `{{motion}}`. They are the engine's functions, not wrappers, so they run on
170
+ the same frame loop as every `{{motion}}` element.
171
+
172
+ | export | from | what |
173
+ | ---------------------------- | ------------------- | -------------------------------------------------------------------------- |
174
+ | `motionValue`, `MotionValue` | `motion-dom` | create a motion value, and its type; pass one to `{{motion}}` in `style` |
175
+ | `transformValue` | `motion-dom` | a motion value derived from others, recomputed when they change |
176
+ | `styleEffect` | `motion-dom` | bind motion values to an element's style outside `{{motion}}` |
177
+ | `frame` | `motion-dom` | schedule `read` / `update` / `render` work on the engine's frame loop |
178
+ | `animate` | `framer-motion/dom` | animate a motion value, an element or a selector; `motion`'s own `animate` |
179
+
180
+ ```ts
181
+ import { animate, motionValue } from 'glimmer-motion';
182
+
183
+ const x = motionValue(0);
184
+ animate(x, 120, { type: 'spring', visualDuration: 0.4 });
185
+ ```
186
+
187
+ This is the only route by which realm cards reach the engine: `motion-dom` itself is not shimmed into
188
+ realms. The list is deliberately small. The engine's internals (`animateVisualElement`, `visualElementStore`
189
+ and the like) stay unexported, and adding a name to it is an API change to glimmer-motion, reviewed like
190
+ one.
191
+
192
+ ### React → Glimmer
193
+
194
+ | React | here |
195
+ | -------------------------------- | --------------------------------------------------------- |
196
+ | `<motion.div …>` | `<div {{motion …}}>` — any tag, including SVG |
197
+ | `ref` | the element, or a `{current}` object filled by a modifier |
198
+ | `useMotionValue`, `useTransform` | `motionValue`, `transformValue` |
199
+ | `<AnimatePresence>` | `<Presence @items @key>` yielding a handle |
200
+ | `useIsPresent()` | `h.isPresent` |
201
+ | re-render → layout snapshot | a render pass inside `<LayoutGroup>`, or `layoutChange()` |
202
+ | `<MotionConfig>` | pass `transition` / `transformPagePoint` per element |
203
+ | `useDragControls()` | `createDragControls()` |
204
+ | `Reorder.Group` / `.Item` | `<ReorderGroup>` / `<ReorderItem>` |
205
+
206
+ ## How it works
207
+
208
+ Motion's React library is an engine (`motion-dom`) plus glue. This package is only the glue, redone for
209
+ Glimmer, reproducing the ordering React gives the engine: construct parents-first, mount children-first
210
+ after the render pass, snapshot layout before the DOM changes and measure after, announce presence after
211
+ the commit, freeze a leaving element's props. `src/node.ts` (the per-element lifecycle), `src/layout.ts`
212
+ (the settle pipeline) and `src/scheduler.ts` (one `postRender` host hook) have no Ember imports;
213
+ `src/motion.ts` and the components are the Ember host adapter.
214
+
215
+ `scroll()`, `scrollInfo()` and `inView()` are Motion's own, re-exported from `framer-motion/dom`, the
216
+ React-free entry point of Motion's React package. `framer-motion` is a regular dependency; its React peers
217
+ are optional and that entry never imports them.
218
+
219
+ The pan/drag session, the gesture and animation features and the Reorder utilities are Motion's own
220
+ modules too, inlined at build time from framer-motion's build. `VENDORED.md` lists them and the two places
221
+ glimmer-motion's drag deliberately differs.
222
+
223
+ The full story — why the engine is untouched, how the binding was built by porting Motion's test suites and
224
+ what that surfaced — is in the
225
+ [repository README](https://github.com/cardstack/choreo#readme).
226
+
227
+ ## Not ported (yet)
228
+
229
+ `m` / `LazyMotion`, Reorder's `as`, server rendering.
230
+
231
+ ## License
232
+
233
+ MIT. The engine, algorithms and tests are [Motion](https://motion.dev) (MIT, Motion Division).
package/VENDORED.md ADDED
@@ -0,0 +1,111 @@
1
+ # Code from Motion
2
+
3
+ glimmer-motion runs Motion's own code wherever Motion's code is framework-free.
4
+
5
+ - **The engine.** `motion-dom` and `motion-utils` are peer dependencies, shared with the rest of the page.
6
+ - **Scroll and in-view.** `scroll()`, `scrollInfo()` and `inView()` come from `framer-motion/dom`, a
7
+ regular dependency.
8
+ - **Gestures, features and Reorder utilities.** These come from framer-motion's build, which its exports
9
+ map doesn't expose. `src/framer-motion-internals.ts` imports them by their `framer-motion/dist/es/…`
10
+ paths, and `rollup.config.mjs` resolves those paths on disk and inlines the modules into
11
+ `dist/framer-motion-internals.js`. That file carries framer-motion's MIT notice. The build fails if any
12
+ output chunk imports React or a framer-motion path other than `framer-motion/dom`.
13
+
14
+ | inlined from `framer-motion/dist/es/` (and the modules they import) | used by |
15
+ | -------------------------------------------------------------------------------------- | ------------------------------------------------- |
16
+ | `gestures/drag/index`, `gestures/drag/VisualElementDragControls`, `gestures/pan/index` | `src/features.ts`, `src/gestures/drag-gesture.ts` |
17
+ | `gestures/drag/use-drag-controls` (`DragControls` only; the React hook is tree-shaken) | `src/gestures/drag-controls.ts` |
18
+ | `gestures/hover`, `gestures/press`, `gestures/focus`, `motion/features/viewport/index` | `src/features.ts` |
19
+ | `motion/features/animation/index`, `motion/features/animation/exit` | `src/features.ts` |
20
+ | `components/Reorder/utils/{check-reorder,detect-axis,auto-scroll}` | `src/reorder/group.gts`, `src/reorder/item.gts` |
21
+
22
+ framer-motion ships no declarations for these modules. `src/framer-motion-internals.ts` declares the part
23
+ of their surface glimmer-motion uses. A changed signature upstream compiles silently against the old
24
+ declaration, which is why a bump PR diffs these modules' source (see [Bumping Motion](#bumping-motion)).
25
+
26
+ ## One engine, pinned together
27
+
28
+ The workspace catalog in `pnpm-workspace.yaml` pins `framer-motion`, `motion`, `motion-dom` and
29
+ `motion-utils` to exact versions, and a bump moves all four.
30
+
31
+ - **One `motion-dom`.** It holds the engine's shared state: the frame loop, the drag lock, every
32
+ `MotionValue`. A second copy on the page is a second engine that the first can't see. glimmer-motion
33
+ takes `motion-dom` and `motion-utils` as peers, the inlined framer-motion code imports them, and the
34
+ test app and gallery depend on them directly. The root `overrides` resolve `framer-motion`,
35
+ `motion-dom` and `motion-utils` through the catalog, so no caret range pulls in a second copy.
36
+ - **The versions framer-motion was released against.** `motion-dom` and `motion-utils` sit at the lower
37
+ bounds of the ranges the pinned framer-motion declares. glimmer-motion's peer ranges start at the same
38
+ versions, because its dist carries that framer-motion code.
39
+ - **`motion` at framer-motion's version.** The test app and the gallery use `motion`, which depends on
40
+ the `framer-motion` release of its own version.
41
+
42
+ ## Adapted, not inlined
43
+
44
+ Upstream paths in this table and the next are relative to framer-motion's `src/`. `scripts/bump-motion.mjs`
45
+ reads both tables to build a bump PR's report, and fails when an upstream path is in neither release.
46
+
47
+ | here | upstream |
48
+ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
49
+ | `src/gestures/transform-page-point.ts` | `utils/transform-rotated-parent.ts`, `utils/transform-viewbox-point.ts` (React ref → element or `{current}`) |
50
+
51
+ ## Ported by hand
52
+
53
+ The rest of `src/` that follows Motion re-implements its React glue for Glimmer. Each file below ports the
54
+ behavior of the upstream modules beside it.
55
+
56
+ | here | upstream |
57
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
58
+ | `src/node.ts` | `motion/index.tsx`, `motion/utils/use-visual-element.ts`, `motion/features/layout/MeasureLayout.tsx`, `components/AnimatePresence/use-presence.ts` |
59
+ | `src/layout.ts` | `motion/features/layout/MeasureLayout.tsx` |
60
+ | `src/layout-group.gts` | `components/LayoutGroup/index.tsx` |
61
+ | `src/motion-config.gts` | `components/MotionConfig/index.tsx` |
62
+ | `src/presence.gts` | `components/AnimatePresence/index.tsx`, `components/AnimatePresence/PresenceChild.tsx`, `components/AnimatePresence/PopChild.tsx`, `components/AnimatePresence/utils.ts` |
63
+ | `src/reorder/group.gts` | `components/Reorder/Group.tsx` |
64
+ | `src/reorder/item.gts` | `components/Reorder/Item.tsx` |
65
+ | `src/scroll.ts` | `value/use-scroll.ts`, `utils/use-in-view.ts` |
66
+
67
+ glimmer-motion's own suite (`tests/`, run with `pnpm test`) carries the ports of Motion's Jest suites and
68
+ Cypress fixtures that pin the fidelity.
69
+
70
+ ## Deviations
71
+
72
+ Each deviation is a subclass of upstream's class in `src/gestures/drag-gesture.ts`, overriding only the
73
+ methods that differ.
74
+
75
+ | class | change |
76
+ | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
77
+ | `GlimmerDragGesture` (over `DragGesture`) | `unmount()` always calls `controls.cancel()`. Upstream keeps the pan session alive when a component unmounts mid-drag, because React 19 can unmount and remount during reorder reconciliation. Glimmer's keyed `{{#each}}` moves nodes instead, so an unmount really is the end of the gesture. Upstream's branch skips `cancel()`, and with it the release of `setDragLock`'s module-global lock, so an element removed mid-drag silently kills `onDragStart` / `onDragEnd` for every later drag on the page. |
78
+ | `TextLockingDragControls` (over `VisualElementDragControls`) | Holds a document-wide text-selection lock (`src/gestures/lock-select.ts`) while a pan session is open. CSS on the dragged node doesn't stop the browser selecting nearby text once the pointer leaves it. |
79
+
80
+ ## Bumping Motion
81
+
82
+ The Motion Bump workflow (`.github/workflows/motion-bump.yml`) checks npm daily. Once a newer framer-motion
83
+ release is older than pnpm's `minimumReleaseAge`, it runs `scripts/bump-motion.mjs`, which moves the four
84
+ pins and glimmer-motion's peer ranges. The workflow then opens a PR from `motion-bump/<version>` and
85
+ requests review from the reviewer it names (`REVIEWER`). The script runs locally too:
86
+ `node scripts/bump-motion.mjs` prints the release a bump would take, and
87
+ `node scripts/bump-motion.mjs --to <version> --write --report -` moves the pins and prints the PR body.
88
+ Run `pnpm install` after it.
89
+
90
+ Reviewing a bump PR:
91
+
92
+ 1. **CI.** Red CI is the signal. The Glimmer Motion Tests job runs the ported fidelity suites, the Choreo
93
+ Tests and Choreo Test App Tests jobs run the choreo suites, Lint runs `ember-tsc` over the choreo
94
+ packages, and glimmer-motion's build fails if an inlined module imports React or a framer-motion path
95
+ other than `framer-motion/dom`. A PR opened with the workflow's `GITHUB_TOKEN` starts no
96
+ `pull_request` workflows, so the workflow dispatches `ci.yaml` and `ci-lint.yaml` on the branch
97
+ itself. A push to the branch runs the rest.
98
+ 2. **The PR body.** It lists every inlined, adapted or ported module whose TypeScript changed between the
99
+ two releases, with diffs, read from the `sourcesContent` of framer-motion's `dist/es/**/*.mjs.map`.
100
+ - For a changed entry module, compare its exports with the declarations in
101
+ `src/framer-motion-internals.ts`, and its overridden methods with the subclasses in
102
+ `src/gestures/drag-gesture.ts`. Neither fails to compile when upstream changes a signature.
103
+ - Port a change in an adapted source into `src/gestures/transform-page-point.ts` by hand.
104
+ - Read a changed ported module against the Glimmer file the report names, and port what applies to
105
+ Glimmer. Neither typecheck nor the ported suites, which are frozen at the upstream revision they came
106
+ from, catch this drift.
107
+ 3. **Fixes** are ordinary commits on the bump branch.
108
+ 4. **Title.** The PR opens as `fix:`, for a catch-up. Retitle it `feat:` when upstream adds a capability
109
+ glimmer-motion exposes. The prefix covers glimmer-motion and choreo, which release together.
110
+
111
+ To decline a release, close its PR: the workflow skips a release that has a bump PR, open or closed.
package/addon-main.cjs ADDED
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+
3
+ const { addonV1Shim } = require('@embroider/addon-shim');
4
+ module.exports = addonV1Shim(__dirname);
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Is anything still moving?
3
+ *
4
+ * Ember Animated's maturity is not its sprite code, it is `animationsSettled()`
5
+ * — a test can say "when everything has stopped" instead of `sleep(200)` and
6
+ * hoping. This is the machinery under that: every part of the binding that can
7
+ * still have work outstanding registers a probe, and a probe answers with a
8
+ * short reason string while it is busy and `false` when it is not.
9
+ *
10
+ * The reason is not decoration. A test that times out waiting for motion is
11
+ * useless if all it can say is "timed out"; `whatIsBusy()` names the element
12
+ * and the property that never stopped, which is usually the bug itself.
13
+ *
14
+ * Deliberately NOT an `@ember/test-waiters` waiter, which would make plain
15
+ * `await settled()` block until animations finish. That reads well in a doc and
16
+ * is wrong here: the interruption suite exists precisely to click again while
17
+ * something is still in flight, and a blocking waiter would turn every one of
18
+ * those into a wait-for-completion — the tests would pass by no longer testing
19
+ * anything. Waiting for motion is a thing a test asks for, not a thing it gets.
20
+ *
21
+ * Probes are module-global rather than owner-linked because the things they
22
+ * watch are: the engine's frameloop, the projection tree and the beacon
23
+ * registry are all one per document, and a probe that could not see across an
24
+ * owner boundary could not see the far-match barrier at all. A probe over one
25
+ * element's or component's state is removed in its destructor, so nothing
26
+ * outlives its element; a probe over module-global state stays registered.
27
+ */
28
+ /** busy → a short reason; idle → false */
29
+ export type BusyProbe = () => false | string;
30
+ /**
31
+ * Make a layer's own in-flight work count toward "motion is busy", so
32
+ * `animationsSettled()` and `whatIsBusy()` wait on it too. The probe runs on
33
+ * every settle check and answers `false` at rest or a short reason while busy.
34
+ * Returns the remover: a probe over one instance's state is removed in that
35
+ * instance's destructor; a probe over module-global state (Choreo's far-match
36
+ * barrier) may stay registered for the life of the page.
37
+ */
38
+ export declare function registerBusyProbe(probe: BusyProbe): () => void;
39
+ /** every reason the binding is not at rest, for a timeout message */
40
+ export declare function whatIsBusy(): string[];
41
+ export declare function isMotionIdle(): boolean;
42
+ //# sourceMappingURL=activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GAAG,MAAM,KAAK,GAAG,MAAM,CAAC;AAI7C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,IAAI,CAK9D;AAED,qEAAqE;AACrE,wBAAgB,UAAU,IAAI,MAAM,EAAE,CASrC;AAED,wBAAgB,YAAY,IAAI,OAAO,CAOtC"}
@@ -0,0 +1,2 @@
1
+ export declare function initFeatures(): void;
2
+ //# sourceMappingURL=features.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAmDA,wBAAgB,YAAY,SAqE3B"}
@@ -0,0 +1,65 @@
1
+ import type { Feature, VisualElement } from 'motion-dom';
2
+ import type { Box, Point } from 'motion-utils';
3
+ import type { ItemData, ReorderAxis } from './reorder/types.ts';
4
+ type FeatureClass = new (node: VisualElement) => Feature<unknown>;
5
+ export declare const AnimationFeature: FeatureClass;
6
+ export declare const ExitAnimationFeature: FeatureClass;
7
+ export declare const InViewFeature: FeatureClass;
8
+ export declare const PanGesture: FeatureClass;
9
+ export declare const FocusGesture: FeatureClass;
10
+ export declare const HoverGesture: FeatureClass;
11
+ export declare const PressGesture: FeatureClass;
12
+ export interface DragControlOptions {
13
+ /** The distance after which dragging starts and a direction is locked in. */
14
+ distanceThreshold?: number;
15
+ /** Whether to snap to the cursor immediately when dragging starts. */
16
+ snapToCursor?: boolean;
17
+ }
18
+ /** The per-element drag state machine behind the drag feature. */
19
+ export interface VisualElementDragControls {
20
+ addListeners(): () => void;
21
+ cancel(): void;
22
+ endPanSession(): void;
23
+ isDragging: boolean;
24
+ /**
25
+ * Private upstream. Set by `start()` to the session it opens and cleared by
26
+ * `endPanSession()`. The session's `end()` removes its listeners, and runs
27
+ * on every pointerup.
28
+ */
29
+ panSession?: {
30
+ end(): void;
31
+ };
32
+ start(originEvent: PointerEvent, options?: DragControlOptions): void;
33
+ stop(event?: PointerEvent): void;
34
+ }
35
+ export declare const VisualElementDragControls: new (visualElement: VisualElement<HTMLElement>) => VisualElementDragControls;
36
+ export interface DragGesture extends Feature<HTMLElement> {
37
+ controls: VisualElementDragControls;
38
+ mount(): void;
39
+ removeGroupControls(): void;
40
+ removeListeners(): void;
41
+ unmount(): void;
42
+ update(): void;
43
+ }
44
+ export declare const DragGesture: new (node: VisualElement<HTMLElement>) => DragGesture;
45
+ /**
46
+ * Start, stop or cancel a drag on every `motion` element given these controls
47
+ * as `dragControls`, from a pointer event anywhere on the page.
48
+ */
49
+ export interface DragControls {
50
+ /** End the drag where it is: no momentum and no `onDragEnd`. */
51
+ cancel(): void;
52
+ /** Start a drag on every subscribed element, from `event`. */
53
+ start(event: PointerEvent, options?: DragControlOptions): void;
54
+ /** End the drag as a pointerup would: momentum, then `onDragEnd`. */
55
+ stop(): void;
56
+ /** Called by the drag feature of each element given these controls. */
57
+ subscribe(controls: VisualElementDragControls): () => void;
58
+ }
59
+ export declare const DragControls: new () => DragControls;
60
+ export declare const checkReorder: <T>(order: ItemData<T>[], value: T, offset: Point, velocity: Point, axis: ReorderAxis, direction?: 'ltr' | 'rtl') => ItemData<T>[];
61
+ export declare const detectAxis: (layouts: Box[]) => ReorderAxis;
62
+ export declare const autoScrollIfNeeded: (groupElement: Element | null, pointerPosition: number, axis: 'x' | 'y', velocity: number) => void;
63
+ export declare const resetAutoScrollState: () => void;
64
+ export {};
65
+ //# sourceMappingURL=framer-motion-internals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framer-motion-internals.d.ts","sourceRoot":"","sources":["../src/framer-motion-internals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Motion's DragControls (upstream's class, see framer-motion-internals.ts) and
3
+ * the Glimmer stand-in for its `useDragControls()` hook.
4
+ */
5
+ import { DragControls } from '../framer-motion-internals.ts';
6
+ export { type DragControlOptions, DragControls, } from '../framer-motion-internals.ts';
7
+ /** Motion's useDragControls(): one DragControls per owner, created once */
8
+ export declare const createDragControls: () => DragControls;
9
+ //# sourceMappingURL=drag-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drag-controls.d.ts","sourceRoot":"","sources":["../../src/gestures/drag-controls.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EACL,KAAK,kBAAkB,EACvB,YAAY,GACb,MAAM,+BAA+B,CAAC;AAEvC,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,QAAO,YAAkC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Motion's drag feature, with the two places glimmer-motion's drag differs
3
+ * from React's. Everything else is upstream's.
4
+ */
5
+ import type { VisualElement } from 'motion-dom';
6
+ import { DragGesture } from '../framer-motion-internals.ts';
7
+ export declare class GlimmerDragGesture extends DragGesture {
8
+ constructor(node: VisualElement<HTMLElement>);
9
+ /**
10
+ * Upstream keeps the pan session alive when a component unmounts mid-drag,
11
+ * because in React 19 a list reorder can unmount and remount a component
12
+ * while the gesture is still live. Glimmer has no such reconciliation: a
13
+ * keyed `{{#each}}` moves a node rather than tearing it down and building it
14
+ * again, so an unmount here means the element is gone and the gesture has
15
+ * nothing left to move.
16
+ *
17
+ * Upstream's guard skips `cancel()`, and `cancel()` is what releases the
18
+ * module-global `setDragLock`. If the pointerup never arrives (the element
19
+ * was removed mid-gesture, the tab lost the pointer, a module reloaded), the
20
+ * lock is held forever and every later drag on the page bails before
21
+ * `onDragStart`. The pan session still moves elements, so dragging looks
22
+ * fine while `onDragStart` / `onDragEnd` silently stop firing.
23
+ *
24
+ * `cancel()` ends the session, releases the lock and clears `whileDrag`.
25
+ */
26
+ unmount(): void;
27
+ }
28
+ //# sourceMappingURL=drag-gesture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drag-gesture.d.ts","sourceRoot":"","sources":["../../src/gestures/drag-gesture.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EAEL,WAAW,EAEZ,MAAM,+BAA+B,CAAC;AAkDvC,qBAAa,kBAAmB,SAAQ,WAAW;gBACrC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC;IAK5C;;;;;;;;;;;;;;;;OAgBG;IACM,OAAO;CAKjB"}
@@ -0,0 +1,3 @@
1
+ export declare function lockTextSelect(): void;
2
+ export declare function unlockTextSelect(): void;
3
+ //# sourceMappingURL=lock-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock-select.d.ts","sourceRoot":"","sources":["../../src/gestures/lock-select.ts"],"names":[],"mappings":"AAQA,wBAAgB,cAAc,SAa7B;AAED,wBAAgB,gBAAgB,SAc/B"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Motion's correctParentTransform / transformViewBoxPoint (utils/transform-rotated-parent.ts,
3
+ * utils/transform-viewbox-point.ts), with the React ref replaced by an element or a {current} ref.
4
+ */
5
+ type Point = {
6
+ x: number;
7
+ y: number;
8
+ };
9
+ type TransformPoint = (p: Point) => Point;
10
+ type Ref<T> = T | {
11
+ current: T | null;
12
+ } | null | undefined;
13
+ /** pointer coordinates corrected for a parent with a CSS transform (rotation, scale, skew) */
14
+ export declare function correctParentTransform(parentRef: Ref<Element>): TransformPoint;
15
+ /** pointer coordinates scaled into an <svg>'s viewBox coordinate system */
16
+ export declare function transformViewBoxPoint(svgRef: Ref<SVGSVGElement>): TransformPoint;
17
+ export {};
18
+ //# sourceMappingURL=transform-page-point.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-page-point.d.ts","sourceRoot":"","sources":["../../src/gestures/transform-page-point.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,KAAK,KAAK,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACtC,KAAK,cAAc,GAAG,CAAC,CAAC,EAAE,KAAK,KAAK,KAAK,CAAC;AAC1C,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAM3D,8FAA8F;AAC9F,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,GACtB,cAAc,CAiBhB;AA0BD,2EAA2E;AAC3E,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,GACzB,cAAc,CAuBhB"}