@humanspeak/svelte-motion 0.5.4 → 0.6.1
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/dist/components/motionDomProjection.context.d.ts +13 -0
- package/dist/components/motionDomProjection.context.js +18 -0
- package/dist/html/_MotionContainer.svelte +831 -81
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/types.d.ts +87 -3
- package/dist/utils/animationControls.svelte.d.ts +63 -0
- package/dist/utils/animationControls.svelte.js +111 -0
- package/dist/utils/layout.d.ts +9 -6
- package/dist/utils/layout.js +148 -14
- package/dist/utils/motionDomProjection.d.ts +155 -0
- package/dist/utils/motionDomProjection.js +279 -0
- package/dist/utils/optimizedAppear.d.ts +141 -0
- package/dist/utils/optimizedAppear.js +311 -0
- package/dist/utils/presence.d.ts +3 -2
- package/dist/utils/presence.js +49 -12
- package/dist/utils/projection.d.ts +3 -3
- package/dist/utils/projection.js +1 -1
- package/dist/utils/svg.d.ts +4 -4
- package/dist/utils/svg.js +44 -25
- package/package.json +1 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { type IProjectionNode, type ResolvedValues, type Transition, type VisualElement } from 'motion-dom';
|
|
2
|
+
type ProjectionVisualElement = VisualElement & {
|
|
3
|
+
latestValues: ResolvedValues;
|
|
4
|
+
projection?: IProjectionNode<HTMLElement>;
|
|
5
|
+
};
|
|
6
|
+
type LayoutOption = boolean | string | undefined;
|
|
7
|
+
export interface MotionDomProjectionOptions {
|
|
8
|
+
/** Parent adapter used to connect this node into the upstream projection tree. */
|
|
9
|
+
parent?: MotionDomProjectionAdapter | null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Latest layout-related motion props applied to an upstream projection node.
|
|
13
|
+
*/
|
|
14
|
+
export interface MotionDomProjectionUpdateOptions {
|
|
15
|
+
/** Enables layout projection and selects the upstream animation type. */
|
|
16
|
+
layout?: LayoutOption;
|
|
17
|
+
/** Shared layout id used by upstream projection matching. */
|
|
18
|
+
layoutId?: string;
|
|
19
|
+
/** Tracks scroll on this element for descendant layout projection. */
|
|
20
|
+
layoutScroll?: boolean;
|
|
21
|
+
/** Transition passed to the upstream layout animation builder. */
|
|
22
|
+
transition?: Transition;
|
|
23
|
+
/** Inline style props passed through to the visual element. */
|
|
24
|
+
style?: unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Svelte lifecycle adapter for motion-dom's upstream projection node system.
|
|
28
|
+
*
|
|
29
|
+
* The public Svelte API stays unchanged (`layout`, `layoutId`, `transition`).
|
|
30
|
+
* This adapter only translates those props into the same `HTMLProjectionNode`
|
|
31
|
+
* and `HTMLVisualElement` internals Framer Motion uses.
|
|
32
|
+
*/
|
|
33
|
+
export declare class MotionDomProjectionAdapter {
|
|
34
|
+
private static adapters;
|
|
35
|
+
readonly visualElement: ProjectionVisualElement;
|
|
36
|
+
readonly projection: IProjectionNode<HTMLElement>;
|
|
37
|
+
private element;
|
|
38
|
+
private layout;
|
|
39
|
+
private layoutId;
|
|
40
|
+
private transition;
|
|
41
|
+
private lastLayout;
|
|
42
|
+
constructor(options?: MotionDomProjectionOptions);
|
|
43
|
+
/**
|
|
44
|
+
* Update projection options from current Svelte props.
|
|
45
|
+
*
|
|
46
|
+
* @param options Current layout-related motion props.
|
|
47
|
+
* @returns Nothing.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* adapter.updateOptions({ layout, layoutId, transition, style })
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
updateOptions(options: MotionDomProjectionUpdateOptions): void;
|
|
55
|
+
/**
|
|
56
|
+
* Mount the upstream projection node to an element and seed its layout.
|
|
57
|
+
*
|
|
58
|
+
* @param element Element represented by the current motion component.
|
|
59
|
+
* @returns Nothing.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* adapter.mount(element)
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
mount(element: HTMLElement): void;
|
|
67
|
+
/**
|
|
68
|
+
* Unmount the upstream projection node and clear its visual-element store.
|
|
69
|
+
*
|
|
70
|
+
* @returns Nothing.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* adapter.unmount()
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
unmount(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Capture the upstream "before" snapshot.
|
|
80
|
+
*
|
|
81
|
+
* @returns Nothing.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* adapter.willUpdate()
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
willUpdate(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Commit an upstream layout update after Svelte has patched the DOM.
|
|
91
|
+
*
|
|
92
|
+
* @returns Nothing.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* adapter.didUpdate()
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
didUpdate(): void;
|
|
100
|
+
/**
|
|
101
|
+
* Seed the current layout without animating.
|
|
102
|
+
*
|
|
103
|
+
* @returns Nothing.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* adapter.seedLayout()
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
seedLayout(): void;
|
|
111
|
+
/**
|
|
112
|
+
* Animate from the last cached layout to the current observed layout.
|
|
113
|
+
*
|
|
114
|
+
* This covers layout changes discovered after the mutation by observers.
|
|
115
|
+
* Svelte runes mode doesn't expose the same component pre/post-update
|
|
116
|
+
* hooks Framer Motion uses in React, so this adapter reuses upstream
|
|
117
|
+
* projection while the Svelte component controls the snapshot timing.
|
|
118
|
+
*
|
|
119
|
+
* @returns Nothing.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* adapter.commitObservedLayoutChange()
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
commitObservedLayoutChange(): void;
|
|
127
|
+
/**
|
|
128
|
+
* Finish any active upstream layout animation in this subtree.
|
|
129
|
+
*
|
|
130
|
+
* @returns Nothing.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* adapter.finishAnimation()
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
finishAnimation(): void;
|
|
138
|
+
/**
|
|
139
|
+
* Check whether this projection subtree has an active layout animation.
|
|
140
|
+
*
|
|
141
|
+
* @returns `true` when this projection subtree is currently animating.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* if (adapter.isAnimating()) adapter.finishAnimation()
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
isAnimating(): boolean;
|
|
149
|
+
private seedCachedSnapshotsForSubtree;
|
|
150
|
+
private finishAnimationForSubtree;
|
|
151
|
+
private isAnimatingSubtree;
|
|
152
|
+
private updatePathScroll;
|
|
153
|
+
private refreshCachedLayout;
|
|
154
|
+
}
|
|
155
|
+
export {};
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { HTMLProjectionNode, HTMLVisualElement, copyBoxInto, createBox, visualElementStore } from 'motion-dom';
|
|
2
|
+
const createVisualState = () => ({
|
|
3
|
+
latestValues: {},
|
|
4
|
+
renderState: {
|
|
5
|
+
transform: {},
|
|
6
|
+
transformOrigin: {},
|
|
7
|
+
style: {},
|
|
8
|
+
vars: {}
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const cloneMeasurements = (measurements) => {
|
|
12
|
+
if (!measurements)
|
|
13
|
+
return undefined;
|
|
14
|
+
const measuredBox = createBox();
|
|
15
|
+
const layoutBox = createBox();
|
|
16
|
+
copyBoxInto(measuredBox, measurements.measuredBox);
|
|
17
|
+
copyBoxInto(layoutBox, measurements.layoutBox);
|
|
18
|
+
return {
|
|
19
|
+
animationId: measurements.animationId,
|
|
20
|
+
measuredBox,
|
|
21
|
+
layoutBox,
|
|
22
|
+
latestValues: { ...measurements.latestValues },
|
|
23
|
+
source: measurements.source
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const animationTypes = new Set([
|
|
27
|
+
'position',
|
|
28
|
+
'x',
|
|
29
|
+
'y',
|
|
30
|
+
'size',
|
|
31
|
+
'both',
|
|
32
|
+
'preserve-aspect'
|
|
33
|
+
]);
|
|
34
|
+
const animationTypeForLayout = (layout) => typeof layout === 'string' && animationTypes.has(layout)
|
|
35
|
+
? layout
|
|
36
|
+
: 'both';
|
|
37
|
+
/**
|
|
38
|
+
* Svelte lifecycle adapter for motion-dom's upstream projection node system.
|
|
39
|
+
*
|
|
40
|
+
* The public Svelte API stays unchanged (`layout`, `layoutId`, `transition`).
|
|
41
|
+
* This adapter only translates those props into the same `HTMLProjectionNode`
|
|
42
|
+
* and `HTMLVisualElement` internals Framer Motion uses.
|
|
43
|
+
*/
|
|
44
|
+
export class MotionDomProjectionAdapter {
|
|
45
|
+
static adapters = new WeakMap();
|
|
46
|
+
visualElement;
|
|
47
|
+
projection;
|
|
48
|
+
element = null;
|
|
49
|
+
layout;
|
|
50
|
+
layoutId;
|
|
51
|
+
transition;
|
|
52
|
+
lastLayout;
|
|
53
|
+
constructor(options = {}) {
|
|
54
|
+
const parent = options.parent ?? null;
|
|
55
|
+
this.visualElement = new HTMLVisualElement({
|
|
56
|
+
parent: parent?.visualElement,
|
|
57
|
+
props: {},
|
|
58
|
+
presenceContext: null,
|
|
59
|
+
visualState: createVisualState()
|
|
60
|
+
}, { allowProjection: true });
|
|
61
|
+
this.projection = new HTMLProjectionNode(this.visualElement.latestValues, parent?.projection);
|
|
62
|
+
this.visualElement.projection = this.projection;
|
|
63
|
+
MotionDomProjectionAdapter.adapters.set(this.projection, this);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Update projection options from current Svelte props.
|
|
67
|
+
*
|
|
68
|
+
* @param options Current layout-related motion props.
|
|
69
|
+
* @returns Nothing.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* adapter.updateOptions({ layout, layoutId, transition, style })
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
updateOptions(options) {
|
|
77
|
+
this.layout = options.layout;
|
|
78
|
+
this.layoutId = options.layoutId;
|
|
79
|
+
this.transition = options.transition;
|
|
80
|
+
this.visualElement.update({
|
|
81
|
+
transition: options.transition,
|
|
82
|
+
style: options.style
|
|
83
|
+
}, null);
|
|
84
|
+
this.projection.setOptions({
|
|
85
|
+
layout: options.layout,
|
|
86
|
+
layoutId: options.layoutId,
|
|
87
|
+
layoutScroll: options.layoutScroll,
|
|
88
|
+
animationType: animationTypeForLayout(options.layout),
|
|
89
|
+
transition: options.transition,
|
|
90
|
+
visualElement: this.visualElement
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Mount the upstream projection node to an element and seed its layout.
|
|
95
|
+
*
|
|
96
|
+
* @param element Element represented by the current motion component.
|
|
97
|
+
* @returns Nothing.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* adapter.mount(element)
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
mount(element) {
|
|
105
|
+
if (this.element === element)
|
|
106
|
+
return;
|
|
107
|
+
if (this.element)
|
|
108
|
+
this.unmount();
|
|
109
|
+
this.element = element;
|
|
110
|
+
MotionDomProjectionAdapter.adapters.set(this.projection, this);
|
|
111
|
+
this.visualElement.mount(element);
|
|
112
|
+
this.seedLayout();
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Unmount the upstream projection node and clear its visual-element store.
|
|
116
|
+
*
|
|
117
|
+
* @returns Nothing.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* adapter.unmount()
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
unmount() {
|
|
125
|
+
if (!this.element)
|
|
126
|
+
return;
|
|
127
|
+
const element = this.element;
|
|
128
|
+
this.projection.scheduleCheckAfterUnmount();
|
|
129
|
+
this.visualElement.unmount();
|
|
130
|
+
visualElementStore.delete(element);
|
|
131
|
+
MotionDomProjectionAdapter.adapters.delete(this.projection);
|
|
132
|
+
this.element = null;
|
|
133
|
+
this.lastLayout = undefined;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Capture the upstream "before" snapshot.
|
|
137
|
+
*
|
|
138
|
+
* @returns Nothing.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* adapter.willUpdate()
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
willUpdate() {
|
|
146
|
+
if (!this.element || !this.layout)
|
|
147
|
+
return;
|
|
148
|
+
this.projection.willUpdate();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Commit an upstream layout update after Svelte has patched the DOM.
|
|
152
|
+
*
|
|
153
|
+
* @returns Nothing.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* adapter.didUpdate()
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
didUpdate() {
|
|
161
|
+
if (!this.element || !this.layout)
|
|
162
|
+
return;
|
|
163
|
+
this.projection.root?.didUpdate();
|
|
164
|
+
this.refreshCachedLayout();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Seed the current layout without animating.
|
|
168
|
+
*
|
|
169
|
+
* @returns Nothing.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* adapter.seedLayout()
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
seedLayout() {
|
|
177
|
+
if (!this.element)
|
|
178
|
+
return;
|
|
179
|
+
this.updatePathScroll();
|
|
180
|
+
this.projection.isLayoutDirty = true;
|
|
181
|
+
this.projection.updateLayout();
|
|
182
|
+
this.lastLayout = cloneMeasurements(this.projection.layout);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Animate from the last cached layout to the current observed layout.
|
|
186
|
+
*
|
|
187
|
+
* This covers layout changes discovered after the mutation by observers.
|
|
188
|
+
* Svelte runes mode doesn't expose the same component pre/post-update
|
|
189
|
+
* hooks Framer Motion uses in React, so this adapter reuses upstream
|
|
190
|
+
* projection while the Svelte component controls the snapshot timing.
|
|
191
|
+
*
|
|
192
|
+
* @returns Nothing.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* adapter.commitObservedLayoutChange()
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
commitObservedLayoutChange() {
|
|
200
|
+
if (!this.element || !this.layout)
|
|
201
|
+
return;
|
|
202
|
+
if (!this.lastLayout) {
|
|
203
|
+
this.seedLayout();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
this.projection.root?.startUpdate();
|
|
207
|
+
this.seedCachedSnapshotsForSubtree(this.projection);
|
|
208
|
+
this.projection.root?.didUpdate();
|
|
209
|
+
this.refreshCachedLayout();
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Finish any active upstream layout animation in this subtree.
|
|
213
|
+
*
|
|
214
|
+
* @returns Nothing.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```ts
|
|
218
|
+
* adapter.finishAnimation()
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
finishAnimation() {
|
|
222
|
+
if (!this.element || !this.layout)
|
|
223
|
+
return;
|
|
224
|
+
this.finishAnimationForSubtree(this.projection);
|
|
225
|
+
this.seedLayout();
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Check whether this projection subtree has an active layout animation.
|
|
229
|
+
*
|
|
230
|
+
* @returns `true` when this projection subtree is currently animating.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* if (adapter.isAnimating()) adapter.finishAnimation()
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
isAnimating() {
|
|
238
|
+
return this.isAnimatingSubtree(this.projection);
|
|
239
|
+
}
|
|
240
|
+
seedCachedSnapshotsForSubtree(projection) {
|
|
241
|
+
const adapter = MotionDomProjectionAdapter.adapters.get(projection);
|
|
242
|
+
const snapshot = cloneMeasurements(adapter?.lastLayout);
|
|
243
|
+
if (snapshot && projection.options.layout) {
|
|
244
|
+
projection.snapshot = snapshot;
|
|
245
|
+
projection.isLayoutDirty = true;
|
|
246
|
+
}
|
|
247
|
+
for (const child of projection.children) {
|
|
248
|
+
this.seedCachedSnapshotsForSubtree(child);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
finishAnimationForSubtree(projection) {
|
|
252
|
+
projection.finishAnimation();
|
|
253
|
+
projection.targetDelta = projection.relativeTarget = projection.target = undefined;
|
|
254
|
+
projection.isProjectionDirty = true;
|
|
255
|
+
projection.scheduleRender();
|
|
256
|
+
for (const child of projection.children) {
|
|
257
|
+
this.finishAnimationForSubtree(child);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
isAnimatingSubtree(projection) {
|
|
261
|
+
if (projection.currentAnimation)
|
|
262
|
+
return true;
|
|
263
|
+
for (const child of projection.children) {
|
|
264
|
+
if (this.isAnimatingSubtree(child))
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
updatePathScroll() {
|
|
270
|
+
for (const node of this.projection.path) {
|
|
271
|
+
node.updateScroll();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
refreshCachedLayout() {
|
|
275
|
+
requestAnimationFrame(() => {
|
|
276
|
+
this.lastLayout = cloneMeasurements(this.projection.layout);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { type AnimationOptions } from 'motion';
|
|
2
|
+
import { optimizedAppearDataAttribute } from 'motion-dom';
|
|
3
|
+
type AppearValueName = 'opacity' | 'transform';
|
|
4
|
+
type OptimizedAppearEntry = {
|
|
5
|
+
name: AppearValueName;
|
|
6
|
+
keyframes: [string | number, string | number];
|
|
7
|
+
options: KeyframeAnimationOptions;
|
|
8
|
+
};
|
|
9
|
+
type AppearStoreEntry = {
|
|
10
|
+
animation: Animation;
|
|
11
|
+
startTime: number | null;
|
|
12
|
+
};
|
|
13
|
+
type SvelteMotionAppearStore = {
|
|
14
|
+
animations: Map<string, AppearStoreEntry>;
|
|
15
|
+
complete: Map<string, boolean>;
|
|
16
|
+
started: Array<{
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
}>;
|
|
20
|
+
readyAnimation?: Animation;
|
|
21
|
+
startFrameTime?: number;
|
|
22
|
+
};
|
|
23
|
+
declare global {
|
|
24
|
+
interface Window {
|
|
25
|
+
__SvelteMotionAppear?: SvelteMotionAppearStore;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build serialisable optimized-appear animation entries from an initial and
|
|
30
|
+
* animate pair.
|
|
31
|
+
*
|
|
32
|
+
* @param initial Initial keyframes reflected into SSR markup.
|
|
33
|
+
* @param animate Target keyframes for the enter animation.
|
|
34
|
+
* @param transition Motion transition options.
|
|
35
|
+
* @returns Appear entries for WAAPI-supported opacity and transform values.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const entries = createOptimizedAppearData(
|
|
40
|
+
* { opacity: 0, scale: 0.8 },
|
|
41
|
+
* { opacity: 1, scale: 1 },
|
|
42
|
+
* { duration: 0.6, ease: [0.16, 1, 0.3, 1] }
|
|
43
|
+
* )
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const createOptimizedAppearData: (initial: Record<string, unknown> | null | undefined, animate: Record<string, unknown> | null | undefined, transition?: AnimationOptions) => OptimizedAppearEntry[];
|
|
47
|
+
/**
|
|
48
|
+
* Create the inline SSR bootstrap that starts appear animations before Svelte
|
|
49
|
+
* hydrates the component tree.
|
|
50
|
+
*
|
|
51
|
+
* @param appearId Stable optimized-appear id attached to the motion element.
|
|
52
|
+
* @param entries WAAPI animation entries to start.
|
|
53
|
+
* @returns A script tag string, or an empty string when no entries exist.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* const script = createOptimizedAppearScript('appear-1', [
|
|
58
|
+
* { name: 'opacity', keyframes: [0, 1], options: { duration: 300, fill: 'both' } }
|
|
59
|
+
* ])
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare const createOptimizedAppearScript: (appearId: string | undefined, entries: OptimizedAppearEntry[]) => string;
|
|
63
|
+
/**
|
|
64
|
+
* Start an optimized appear animation imperatively.
|
|
65
|
+
*
|
|
66
|
+
* Mirrors Framer Motion's `startOptimizedAppearAnimation`: if Motion has
|
|
67
|
+
* already mounted, this intentionally does nothing.
|
|
68
|
+
*
|
|
69
|
+
* @param element Element carrying `data-framer-appear-id`.
|
|
70
|
+
* @param name CSS property to animate.
|
|
71
|
+
* @param keyframes WAAPI keyframes for the property.
|
|
72
|
+
* @param options Motion animation options.
|
|
73
|
+
* @param onReady Optional callback receiving the started animation.
|
|
74
|
+
* @returns Nothing.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* const element = document.querySelector('[data-framer-appear-id]')
|
|
79
|
+
* if (element instanceof HTMLElement) {
|
|
80
|
+
* startOptimizedAppearAnimation(element, 'opacity', [0, 1], { duration: 0.3 })
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare const startOptimizedAppearAnimation: (element: HTMLElement, name: AppearValueName, keyframes: string[] | number[], options: AnimationOptions, onReady?: (animation: Animation) => void) => void;
|
|
85
|
+
/**
|
|
86
|
+
* Commit and cancel optimized appear animations for an element.
|
|
87
|
+
*
|
|
88
|
+
* @param elementId Optimized appear id.
|
|
89
|
+
* @returns `true` when at least one optimized animation was handed off.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const wasHandedOff = handoffOptimizedAppearAnimation('appear-1')
|
|
94
|
+
* if (wasHandedOff) {
|
|
95
|
+
* console.log('Animation handed off to runtime')
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare const handoffOptimizedAppearAnimation: (elementId: string | undefined) => boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Let active optimized appear animations finish before handing their final
|
|
102
|
+
* styles back to Svelte Motion.
|
|
103
|
+
*
|
|
104
|
+
* @param elementId Optimized appear id.
|
|
105
|
+
* @returns Whether at least one optimized animation was adopted.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* const wasAdopted = await finishOptimizedAppearAnimation('appear-1')
|
|
110
|
+
* if (wasAdopted) {
|
|
111
|
+
* console.log('Animation finished and adopted')
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export declare const finishOptimizedAppearAnimation: (elementId: string | undefined) => Promise<boolean>;
|
|
116
|
+
/**
|
|
117
|
+
* Check whether an optimized appear animation is active for an element.
|
|
118
|
+
*
|
|
119
|
+
* @param elementId Optimized appear id.
|
|
120
|
+
* @returns Whether any optimized appear animation is currently registered.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* if (hasOptimizedAppearAnimation('appear-1')) {
|
|
125
|
+
* console.log('Animation is active')
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare const hasOptimizedAppearAnimation: (elementId: string | undefined) => boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Mark Motion as mounted so late optimized-appear starters no-op.
|
|
132
|
+
*
|
|
133
|
+
* @returns Nothing.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* markMotionMounted()
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export declare const markMotionMounted: () => void;
|
|
141
|
+
export { optimizedAppearDataAttribute };
|