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.
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +230 -6
- package/VENDORED.md +111 -0
- package/addon-main.cjs +4 -0
- package/declarations/activity.d.ts +42 -0
- package/declarations/activity.d.ts.map +1 -0
- package/declarations/features.d.ts +2 -0
- package/declarations/features.d.ts.map +1 -0
- package/declarations/framer-motion-internals.d.ts +65 -0
- package/declarations/framer-motion-internals.d.ts.map +1 -0
- package/declarations/gestures/drag-controls.d.ts +9 -0
- package/declarations/gestures/drag-controls.d.ts.map +1 -0
- package/declarations/gestures/drag-gesture.d.ts +28 -0
- package/declarations/gestures/drag-gesture.d.ts.map +1 -0
- package/declarations/gestures/lock-select.d.ts +3 -0
- package/declarations/gestures/lock-select.d.ts.map +1 -0
- package/declarations/gestures/transform-page-point.d.ts +18 -0
- package/declarations/gestures/transform-page-point.d.ts.map +1 -0
- package/declarations/helpers.d.ts +116 -0
- package/declarations/helpers.d.ts.map +1 -0
- package/declarations/index.d.ts +36 -0
- package/declarations/index.d.ts.map +1 -0
- package/declarations/layout-group.d.ts +59 -0
- package/declarations/layout-group.d.ts.map +1 -0
- package/declarations/layout.d.ts +38 -0
- package/declarations/layout.d.ts.map +1 -0
- package/declarations/motion-config.d.ts +45 -0
- package/declarations/motion-config.d.ts.map +1 -0
- package/declarations/motion.d.ts +20 -0
- package/declarations/motion.d.ts.map +1 -0
- package/declarations/node.d.ts +109 -0
- package/declarations/node.d.ts.map +1 -0
- package/declarations/participant-args.d.ts +10 -0
- package/declarations/participant-args.d.ts.map +1 -0
- package/declarations/participant.d.ts +84 -0
- package/declarations/participant.d.ts.map +1 -0
- package/declarations/presence-types.d.ts +23 -0
- package/declarations/presence-types.d.ts.map +1 -0
- package/declarations/presence.d.ts +89 -0
- package/declarations/presence.d.ts.map +1 -0
- package/declarations/reorder/capture.d.ts +11 -0
- package/declarations/reorder/capture.d.ts.map +1 -0
- package/declarations/reorder/group.d.ts +50 -0
- package/declarations/reorder/group.d.ts.map +1 -0
- package/declarations/reorder/item.d.ts +70 -0
- package/declarations/reorder/item.d.ts.map +1 -0
- package/declarations/reorder/types.d.ts +16 -0
- package/declarations/reorder/types.d.ts.map +1 -0
- package/declarations/scheduler.d.ts +10 -0
- package/declarations/scheduler.d.ts.map +1 -0
- package/declarations/scroll.d.ts +51 -0
- package/declarations/scroll.d.ts.map +1 -0
- package/declarations/speed.d.ts +25 -0
- package/declarations/speed.d.ts.map +1 -0
- package/declarations/test-support/index.d.ts +79 -0
- package/declarations/test-support/index.d.ts.map +1 -0
- package/declarations/unitless.d.ts +3 -0
- package/declarations/unitless.d.ts.map +1 -0
- package/declarations/view-transition.d.ts +6 -0
- package/declarations/view-transition.d.ts.map +1 -0
- package/dist/activity.js +69 -0
- package/dist/activity.js.map +1 -0
- package/dist/features.js +92 -0
- package/dist/features.js.map +1 -0
- package/dist/framer-motion-internals.js +1783 -0
- package/dist/framer-motion-internals.js.map +1 -0
- package/dist/gestures/drag-controls.js +12 -0
- package/dist/gestures/drag-controls.js.map +1 -0
- package/dist/gestures/drag-gesture.js +82 -0
- package/dist/gestures/drag-gesture.js.map +1 -0
- package/dist/gestures/lock-select.js +37 -0
- package/dist/gestures/lock-select.js.map +1 -0
- package/dist/gestures/transform-page-point.js +86 -0
- package/dist/gestures/transform-page-point.js.map +1 -0
- package/dist/helpers.js +106 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/layout-group.js +97 -0
- package/dist/layout-group.js.map +1 -0
- package/dist/layout.js +173 -0
- package/dist/layout.js.map +1 -0
- package/dist/motion-config.js +48 -0
- package/dist/motion-config.js.map +1 -0
- package/dist/motion.js +30 -0
- package/dist/motion.js.map +1 -0
- package/dist/node.js +843 -0
- package/dist/node.js.map +1 -0
- package/dist/participant-args.js +18 -0
- package/dist/participant-args.js.map +1 -0
- package/dist/participant.js +90 -0
- package/dist/participant.js.map +1 -0
- package/dist/presence-types.js +2 -0
- package/dist/presence-types.js.map +1 -0
- package/dist/presence.js +290 -0
- package/dist/presence.js.map +1 -0
- package/dist/reorder/capture.js +12 -0
- package/dist/reorder/capture.js.map +1 -0
- package/dist/reorder/group.js +118 -0
- package/dist/reorder/group.js.map +1 -0
- package/dist/reorder/item.js +66 -0
- package/dist/reorder/item.js.map +1 -0
- package/dist/reorder/types.js +2 -0
- package/dist/reorder/types.js.map +1 -0
- package/dist/scheduler.js +19 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/scroll.js +125 -0
- package/dist/scroll.js.map +1 -0
- package/dist/speed.js +91 -0
- package/dist/speed.js.map +1 -0
- package/dist/test-support/index.js +219 -0
- package/dist/test-support/index.js.map +1 -0
- package/dist/unitless.js +20 -0
- package/dist/unitless.js.map +1 -0
- package/dist/view-transition.js +70 -0
- package/dist/view-transition.js.map +1 -0
- 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
|
-
|
|
4
|
-
|
|
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
|
-
|
|
9
|
-
|
|
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,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 @@
|
|
|
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 @@
|
|
|
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"}
|