@motion.page/sdk 1.0.8 → 1.1.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/README.md +211 -0
- package/dist/core/AnimationBuilder.d.ts +7 -1
- package/dist/core/Engine.d.ts +15 -1
- package/dist/core/Motion.d.ts +2 -0
- package/dist/core/MotionContext.d.ts +77 -0
- package/dist/core/PropTween.d.ts +8 -1
- package/dist/core/Timeline.d.ts +5 -1
- package/dist/index.cjs +16 -15
- package/dist/index.d.ts +4 -1
- package/dist/index.js +16 -15
- package/dist/registries/SDKRegistry.d.ts +17 -1
- package/dist/render/CSSRenderer.d.ts +10 -0
- package/dist/triggers/EventTrigger.d.ts +1 -0
- package/dist/triggers/MarkerManager.d.ts +2 -2
- package/dist/types/index.d.ts +120 -0
- package/dist/types/public.d.ts +1 -1
- package/dist/utils/ClipPathParser.d.ts +74 -0
- package/dist/utils/PropertyParser.d.ts +33 -1
- package/dist/utils/TextFlapper.d.ts +105 -0
- package/dist/utils/TextSplitter.d.ts +8 -0
- package/llms.txt +2 -1
- package/package.json +5 -4
- package/dist/index.cjs.map +0 -52
- package/dist/index.js.map +0 -52
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ A high-performance animation SDK with a declarative API. Scroll-triggered animat
|
|
|
18
18
|
- [API Reference](#api-reference)
|
|
19
19
|
- [Motion()](#motion-function)
|
|
20
20
|
- [Motion Static Methods](#motion-static-methods)
|
|
21
|
+
- [Motion.context](#motioncontext--dynamic-content--spa)
|
|
21
22
|
- [Motion.utils](#motionutils)
|
|
22
23
|
- [Timeline](#timeline)
|
|
23
24
|
- [Triggers](#triggers)
|
|
@@ -282,6 +283,7 @@ Calling `Motion()` with the same name on an already-existing timeline returns it
|
|
|
282
283
|
| `Motion.reset` | `(targets: TargetInput): void` | Kill animations targeting those elements, revert text splits, clear transform cache and inline animation styles. |
|
|
283
284
|
| `Motion.refreshScrollTriggers` | `(): void` | Recalculate all scroll trigger start/end positions (call after layout changes). |
|
|
284
285
|
| `Motion.cleanup` | `(): void` | Remove ScrollTrigger spacer and marker DOM nodes from the document. |
|
|
286
|
+
| `Motion.context` | `(fn: () => void): MotionContext` | Create a scoped context that tracks all timelines created during `fn()`. Returns a `MotionContext` with `revert()`, `refresh()`, and `add(fn)` methods. Essential for dynamic content (AJAX filters, SPA navigation, infinite scroll). |
|
|
285
287
|
|
|
286
288
|
#### Examples
|
|
287
289
|
|
|
@@ -302,6 +304,46 @@ Motion.cleanup();
|
|
|
302
304
|
Motion.reset('.animated-card');
|
|
303
305
|
```
|
|
304
306
|
|
|
307
|
+
#### Motion.context — Dynamic Content & SPA
|
|
308
|
+
|
|
309
|
+
Use `Motion.context()` when DOM content changes without a full page reload (AJAX filters, SPA routing, infinite scroll, pagination). It tracks all timelines created inside the callback, enabling clean teardown and re-initialization.
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
// Create a context — all Motion() calls inside are tracked
|
|
313
|
+
const ctx = Motion.context(() => {
|
|
314
|
+
Motion('hero', '.title', {
|
|
315
|
+
from: { opacity: 0, y: 30 },
|
|
316
|
+
duration: 0.8,
|
|
317
|
+
}).onPageLoad();
|
|
318
|
+
|
|
319
|
+
Motion('cards', '.card', {
|
|
320
|
+
from: { y: 100 },
|
|
321
|
+
duration: 1,
|
|
322
|
+
}).onScroll({ scrub: true });
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// After AJAX content replacement:
|
|
326
|
+
ctx.refresh(); // kills old animations, re-runs init, selectors re-resolve
|
|
327
|
+
|
|
328
|
+
// React cleanup:
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
const ctx = Motion.context(() => { /* animations */ });
|
|
331
|
+
return () => ctx.revert(); // clean teardown on unmount
|
|
332
|
+
}, []);
|
|
333
|
+
|
|
334
|
+
// Astro view transitions:
|
|
335
|
+
let ctx;
|
|
336
|
+
document.addEventListener('astro:page-load', () => {
|
|
337
|
+
ctx?.revert();
|
|
338
|
+
ctx = Motion.context(() => { /* animations */ });
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// Add more animations to existing context (e.g., lazy-loaded content):
|
|
342
|
+
ctx.add(() => {
|
|
343
|
+
Motion('lazy', '.lazy-card', { from: { opacity: 0 }, duration: 0.5 }).onScroll({ scrub: true });
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
305
347
|
---
|
|
306
348
|
|
|
307
349
|
### Motion.utils
|
|
@@ -919,6 +961,7 @@ interface AnimationConfig {
|
|
|
919
961
|
repeat?: number | RepeatConfig; // Repeat count shorthand or full config (see below)
|
|
920
962
|
split?: SplitType; // Text splitting for per-char/word/line animation
|
|
921
963
|
mask?: boolean; // Wrap split elements in overflow:hidden for reveal effects
|
|
964
|
+
flap?: FlapConfig; // Split-flap / character scramble animation
|
|
922
965
|
fit?: FitConfig; // FLIP-style morph toward another element
|
|
923
966
|
axis?: 'x' | 'y'; // Axis binding for onMouseMove animations
|
|
924
967
|
|
|
@@ -969,6 +1012,9 @@ outlineColor, textDecorationColor, caretColor
|
|
|
969
1012
|
fill, stroke // string (CSS color)
|
|
970
1013
|
drawSVG // string | { start?: number; end?: number }
|
|
971
1014
|
|
|
1015
|
+
// Clipping
|
|
1016
|
+
'clip-path' / clipPath // string (CSS clip-path shape function)
|
|
1017
|
+
|
|
972
1018
|
// Motion path
|
|
973
1019
|
path: {
|
|
974
1020
|
target: string | Element; // SVG <path> selector, element, or raw path data (starts with M/m)
|
|
@@ -1012,6 +1058,49 @@ Motion('draw-partial', '#circle', {
|
|
|
1012
1058
|
}).play();
|
|
1013
1059
|
```
|
|
1014
1060
|
|
|
1061
|
+
### clip-path
|
|
1062
|
+
|
|
1063
|
+
Animate the CSS `clip-path` property by interpolating between two shape functions of the **same type**. Both `clip-path` (kebab) and `clipPath` (camel) are accepted as the property name.
|
|
1064
|
+
|
|
1065
|
+
| Shape | Format |
|
|
1066
|
+
|-------|--------|
|
|
1067
|
+
| `circle()` | `circle(<radius> at <x> <y>)` |
|
|
1068
|
+
| `ellipse()` | `ellipse(<rx> <ry> at <x> <y>)` |
|
|
1069
|
+
| `inset()` | `inset(<top> <right>? <bottom>? <left>? round <radius>?)` |
|
|
1070
|
+
| `polygon()` | `polygon(<x1> <y1>, <x2> <y2>, …)` |
|
|
1071
|
+
| `rect()` | `rect(<top> <right> <bottom> <left> round <radius>?)` |
|
|
1072
|
+
| `xywh()` | `xywh(<x> <y> <w> <h> round <radius>?)` |
|
|
1073
|
+
|
|
1074
|
+
**Interpolation rules:**
|
|
1075
|
+
- Start and end must use the **same shape function** (e.g. `circle → circle`). Cross-shape animations snap to the end value at progress ≥ 0.5 (no smooth morphing across types).
|
|
1076
|
+
- Polygon animations require **the same vertex count** on both ends — otherwise the animation hard-swaps at the midpoint.
|
|
1077
|
+
- Each numeric component is linearly interpolated; CSS units (`%`, `px`, `em`, etc.) are preserved.
|
|
1078
|
+
- The renderer writes both `clip-path` and `-webkit-clip-path` so older Safari renders correctly.
|
|
1079
|
+
|
|
1080
|
+
```ts
|
|
1081
|
+
// Reveal an image by expanding a circular mask
|
|
1082
|
+
Motion('reveal', '.cover', {
|
|
1083
|
+
from: { 'clip-path': 'circle(0% at 50% 50%)' },
|
|
1084
|
+
to: { 'clip-path': 'circle(75% at 50% 50%)' },
|
|
1085
|
+
duration: 0.8,
|
|
1086
|
+
ease: 'power2.out',
|
|
1087
|
+
}).onScroll({ scrub: true });
|
|
1088
|
+
|
|
1089
|
+
// Inset crop animation (camelCase form also works)
|
|
1090
|
+
Motion('crop', '.image', {
|
|
1091
|
+
from: { clipPath: 'inset(0px round 0px)' },
|
|
1092
|
+
to: { clipPath: 'inset(20px round 16px)' },
|
|
1093
|
+
duration: 0.6,
|
|
1094
|
+
}).onHover({ onLeave: 'reverse' });
|
|
1095
|
+
|
|
1096
|
+
// Polygon slide-in (vertex counts must match)
|
|
1097
|
+
Motion('slide', '.panel', {
|
|
1098
|
+
from: { 'clip-path': 'polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)' },
|
|
1099
|
+
to: { 'clip-path': 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' },
|
|
1100
|
+
duration: 0.5,
|
|
1101
|
+
}).onPageLoad();
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1015
1104
|
### path
|
|
1016
1105
|
|
|
1017
1106
|
`path.target` accepts a CSS selector, an `Element`, or raw SVG path data (a string starting with `M` or `m`):
|
|
@@ -1163,6 +1252,126 @@ Motion('reveal', 'h1', {
|
|
|
1163
1252
|
}).onPageLoad();
|
|
1164
1253
|
```
|
|
1165
1254
|
|
|
1255
|
+
### flap
|
|
1256
|
+
|
|
1257
|
+
When `flap` is set (together with `split: 'chars'`), each character cycles through random intermediate characters before landing on its final value — creating split-flap display, scramble, or decode effects.
|
|
1258
|
+
|
|
1259
|
+
```ts
|
|
1260
|
+
interface FlapConfig {
|
|
1261
|
+
/** Visual transition style. Default: 'flip' */
|
|
1262
|
+
type?: 'flip' | 'fade' | 'slide' | 'blur' | 'scale' | 'board' | 'none';
|
|
1263
|
+
/** Character set to cycle through. Default: 'alphanumeric' */
|
|
1264
|
+
charset?: CharsetPreset | string;
|
|
1265
|
+
/** Number of random cycles before resolving. Range tuple [min, max] picks randomly per character. Default: [2, 5] */
|
|
1266
|
+
cycles?: number | [number, number];
|
|
1267
|
+
/** Perspective depth (px) for 3D flip/board transitions. Default: 400 */
|
|
1268
|
+
perspective?: number;
|
|
1269
|
+
/** Realistic departure-board styling for 'board' type (dark gradient, split line). Default: true */
|
|
1270
|
+
styledBoard?: boolean;
|
|
1271
|
+
/**
|
|
1272
|
+
* Strategy for preventing layout shift during cycling:
|
|
1273
|
+
* - false (default) → no pinning; text width flexes naturally
|
|
1274
|
+
* - true | 'cells' → pin each cell to the widest glyph (classic split-flap look)
|
|
1275
|
+
* - 'container' → pin the element's outer width only, letters flow naturally
|
|
1276
|
+
* (best for inline hover flappers on nav links)
|
|
1277
|
+
*/
|
|
1278
|
+
stableWidth?: boolean | 'cells' | 'container';
|
|
1279
|
+
/** Board type: render blank cells for space characters instead of skipping them. Default: false */
|
|
1280
|
+
preserveWhitespaceCells?: boolean;
|
|
1281
|
+
}
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
**Type styles:**
|
|
1285
|
+
- `'flip'` — 3D CSS rotateX card flip
|
|
1286
|
+
- `'fade'` — CSS opacity fade out/in
|
|
1287
|
+
- `'slide'` — CSS translateY slide out/in
|
|
1288
|
+
- `'blur'` — CSS filter blur out/in
|
|
1289
|
+
- `'scale'` — CSS scale pop/shrink
|
|
1290
|
+
- `'board'` — mechanical split-flap departure board with two-sided flap, shadow, and split line
|
|
1291
|
+
- `'none'` — No built-in visual effect. Use with `from`/`to` to create fully custom flap animations
|
|
1292
|
+
|
|
1293
|
+
#### Charset presets
|
|
1294
|
+
|
|
1295
|
+
| Preset | Characters |
|
|
1296
|
+
|--------|-----------|
|
|
1297
|
+
| `'alphanumeric'` | A–Z 0–9 |
|
|
1298
|
+
| `'alpha'` | A–Z |
|
|
1299
|
+
| `'numeric'` | 0–9 |
|
|
1300
|
+
| `'hex'` | 0–9 A–F |
|
|
1301
|
+
| `'binary'` | 0 1 |
|
|
1302
|
+
| `'katakana'` | ァ–ン (Japanese katakana) |
|
|
1303
|
+
| `'symbols'` | `!@#$%^&*` etc. |
|
|
1304
|
+
| `'blocks'` | ░ ▒ ▓ █ |
|
|
1305
|
+
|
|
1306
|
+
Pass any custom string to cycle through your own characters: `charset: 'ABCXYZ'`.
|
|
1307
|
+
|
|
1308
|
+
```ts
|
|
1309
|
+
// Styled departure board with split-flap effect
|
|
1310
|
+
Motion('board', '.departure-text', {
|
|
1311
|
+
split: 'chars',
|
|
1312
|
+
flap: { type: 'board', styledBoard: true },
|
|
1313
|
+
stagger: 0.05,
|
|
1314
|
+
}).onPageLoad();
|
|
1315
|
+
|
|
1316
|
+
// Classic flip animation
|
|
1317
|
+
Motion('flip', '.title', {
|
|
1318
|
+
split: 'chars',
|
|
1319
|
+
flap: { type: 'flip', cycles: 6 },
|
|
1320
|
+
stagger: 0.05,
|
|
1321
|
+
}).onPageLoad();
|
|
1322
|
+
|
|
1323
|
+
// Matrix-style katakana decode with random resolve order
|
|
1324
|
+
Motion('matrix', '.terminal', {
|
|
1325
|
+
split: 'chars',
|
|
1326
|
+
flap: { type: 'fade', charset: 'katakana', cycles: [4, 8] },
|
|
1327
|
+
stagger: { each: 0.03, from: 'random' },
|
|
1328
|
+
}).onPageLoad();
|
|
1329
|
+
|
|
1330
|
+
// Combine flap with CSS opacity + translate
|
|
1331
|
+
Motion('combo', 'h1', {
|
|
1332
|
+
split: 'chars',
|
|
1333
|
+
flap: { type: 'flip', cycles: 4 },
|
|
1334
|
+
from: { opacity: 0, y: 20 },
|
|
1335
|
+
to: { opacity: 1, y: 0 },
|
|
1336
|
+
stagger: 0.04,
|
|
1337
|
+
duration: 0.8,
|
|
1338
|
+
}).onPageLoad();
|
|
1339
|
+
```
|
|
1340
|
+
|
|
1341
|
+
#### Per-cycle composition
|
|
1342
|
+
|
|
1343
|
+
When `flap` is present, all `from`/`to` properties animate **per character-swap cycle** instead of once over the full animation duration. Each cycle follows a V-curve: starts at `to`, dips to `from` at the midpoint (when the character swaps), then returns to `to`.
|
|
1344
|
+
|
|
1345
|
+
This lets you layer any CSS property on top of any flap type:
|
|
1346
|
+
|
|
1347
|
+
```ts
|
|
1348
|
+
// Flip + fade + slide on every cycle
|
|
1349
|
+
Motion('heading', '.title', {
|
|
1350
|
+
split: 'chars',
|
|
1351
|
+
flap: { type: 'flip' },
|
|
1352
|
+
from: { opacity: 0, y: 20 },
|
|
1353
|
+
to: { opacity: 1, y: 0 },
|
|
1354
|
+
duration: 2,
|
|
1355
|
+
stagger: 0.05,
|
|
1356
|
+
}).play();
|
|
1357
|
+
```
|
|
1358
|
+
|
|
1359
|
+
Use `type: 'none'` to build fully custom flap effects — no built-in visual, just character cycling driven entirely by your `from`/`to` properties:
|
|
1360
|
+
|
|
1361
|
+
```ts
|
|
1362
|
+
// Custom scale-bounce flap with no built-in effect
|
|
1363
|
+
Motion('custom-flap', '.label', {
|
|
1364
|
+
split: 'chars',
|
|
1365
|
+
flap: { type: 'none', cycles: 3 },
|
|
1366
|
+
from: { scale: 0, opacity: 0 },
|
|
1367
|
+
to: { scale: 1, opacity: 1 },
|
|
1368
|
+
duration: 1.5,
|
|
1369
|
+
stagger: 0.05,
|
|
1370
|
+
}).play();
|
|
1371
|
+
```
|
|
1372
|
+
|
|
1373
|
+
> **Note:** `fade` owns `opacity` and `blur` owns `filter` — these types strip conflicting user properties. Use `flip`, `scale`, `slide`, `board`, or `none` if you need full `from`/`to` control over those properties.
|
|
1374
|
+
|
|
1166
1375
|
### FitConfig
|
|
1167
1376
|
|
|
1168
1377
|
FLIP-style morph animation. When `fit` is set, `from` and `to` are ignored — the SDK measures both elements' bounding rects at play time and animates the visual delta between them.
|
|
@@ -1246,6 +1455,8 @@ import type {
|
|
|
1246
1455
|
SplitType,
|
|
1247
1456
|
PathConfig,
|
|
1248
1457
|
FitConfig,
|
|
1458
|
+
FlapConfig,
|
|
1459
|
+
CharsetPreset,
|
|
1249
1460
|
|
|
1250
1461
|
// Triggers
|
|
1251
1462
|
HoverConfig,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Creates animations from configuration objects.
|
|
5
5
|
* Used internally by Motion() function.
|
|
6
6
|
*/
|
|
7
|
-
import type { AnimationVars, AnimationTarget, TargetInput, StaggerVars, SplitType, AnimationConfig, FitConfig } from '../types';
|
|
7
|
+
import type { AnimationVars, AnimationTarget, TargetInput, StaggerVars, SplitType, AnimationConfig, FitConfig, FlapConfig } from '../types';
|
|
8
8
|
/**
|
|
9
9
|
* Internal builder configuration for cloning (not exported from SDK)
|
|
10
10
|
*/
|
|
@@ -17,6 +17,7 @@ interface BuilderConfig {
|
|
|
17
17
|
ease: string;
|
|
18
18
|
axis?: 'x' | 'y';
|
|
19
19
|
fit?: FitConfig;
|
|
20
|
+
flap?: FlapConfig;
|
|
20
21
|
split?: SplitType;
|
|
21
22
|
mask?: boolean;
|
|
22
23
|
stagger?: number | StaggerVars;
|
|
@@ -56,6 +57,7 @@ export declare class AnimationBuilder {
|
|
|
56
57
|
private _stagger?;
|
|
57
58
|
private _axis?;
|
|
58
59
|
private _fitConfig?;
|
|
60
|
+
private _flapConfig?;
|
|
59
61
|
private _onStart?;
|
|
60
62
|
private _onUpdate?;
|
|
61
63
|
private _onComplete?;
|
|
@@ -105,6 +107,10 @@ export declare class AnimationBuilder {
|
|
|
105
107
|
* Whether this builder uses text splitting
|
|
106
108
|
*/
|
|
107
109
|
hasSplit(): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Whether this builder uses text flapper
|
|
112
|
+
*/
|
|
113
|
+
hasFlap(): boolean;
|
|
108
114
|
private _resetBuildState;
|
|
109
115
|
/**
|
|
110
116
|
* Get builder configuration for cloning (used by Timeline's each mode)
|
package/dist/core/Engine.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare class Engine {
|
|
|
23
23
|
private totalCreated;
|
|
24
24
|
private _animationSnapshot;
|
|
25
25
|
private timelines;
|
|
26
|
+
private _captureTarget;
|
|
26
27
|
private ticker;
|
|
27
28
|
private animationPool;
|
|
28
29
|
private propTweenPool;
|
|
@@ -79,9 +80,22 @@ export declare class Engine {
|
|
|
79
80
|
*/
|
|
80
81
|
getTotalCreated(): number;
|
|
81
82
|
/**
|
|
82
|
-
* Get or create a named timeline
|
|
83
|
+
* Get or create a named timeline.
|
|
84
|
+
* When a context capture is active, the timeline name is recorded into
|
|
85
|
+
* the capture set so that MotionContext can track ownership.
|
|
83
86
|
*/
|
|
84
87
|
getTimeline(name: string): Timeline;
|
|
88
|
+
/**
|
|
89
|
+
* Start capturing timeline names into the provided set.
|
|
90
|
+
* Used by MotionContext to track which timelines belong to a context.
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
startCapture(target: Set<string>): void;
|
|
94
|
+
/**
|
|
95
|
+
* Stop capturing timeline names.
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
stopCapture(): void;
|
|
85
99
|
/**
|
|
86
100
|
* Check if timeline exists
|
|
87
101
|
*/
|
package/dist/core/Motion.d.ts
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import type { TargetInput, AnimationConfig, AnimationEntry, AnimationVars } from '../types';
|
|
27
27
|
import { Timeline } from './Timeline';
|
|
28
|
+
import { MotionContext } from './MotionContext';
|
|
28
29
|
/**
|
|
29
30
|
* Motion function overloads
|
|
30
31
|
*/
|
|
@@ -41,6 +42,7 @@ declare namespace MotionFunction {
|
|
|
41
42
|
var killAll: () => void;
|
|
42
43
|
var refreshScrollTriggers: () => void;
|
|
43
44
|
var cleanup: () => void;
|
|
45
|
+
var context: (fn: () => void) => MotionContext;
|
|
44
46
|
var utils: {
|
|
45
47
|
readonly toArray: typeof import("../utils/MotionUtils").toArray;
|
|
46
48
|
readonly clamp: typeof import("../utils/MotionUtils").clamp;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MotionContext — Scoped animation lifecycle management
|
|
3
|
+
*
|
|
4
|
+
* Tracks all timelines created during a callback execution, enabling
|
|
5
|
+
* clean teardown and re-initialization when DOM content changes.
|
|
6
|
+
*
|
|
7
|
+
* Solves the universal "dynamic content" problem:
|
|
8
|
+
* - WordPress AJAX filters (Bricks, WooCommerce, Jetpack)
|
|
9
|
+
* - SPA navigation (React, Astro view transitions, Next.js)
|
|
10
|
+
* - Infinite scroll / pagination
|
|
11
|
+
* - Any scenario where DOM elements are replaced without a full page reload
|
|
12
|
+
*
|
|
13
|
+
* @example WordPress (generated code)
|
|
14
|
+
* const ctx = Motion.context(() => {
|
|
15
|
+
* Motion('hero', '.title', { from: { opacity: 0 }, to: { opacity: 1 } }).onPageLoad()
|
|
16
|
+
* Motion('cards', '.card', { from: { y: 100 }, to: { y: 0 } }).onScroll({ scrub: true })
|
|
17
|
+
* })
|
|
18
|
+
* // After AJAX filter replaces content:
|
|
19
|
+
* ctx.refresh()
|
|
20
|
+
*
|
|
21
|
+
* @example React
|
|
22
|
+
* useEffect(() => {
|
|
23
|
+
* const ctx = Motion.context(() => {
|
|
24
|
+
* Motion('fade', '.box', { from: { opacity: 0 }, to: { opacity: 1 } }).onScroll({ scrub: true })
|
|
25
|
+
* })
|
|
26
|
+
* return () => ctx.revert()
|
|
27
|
+
* }, [])
|
|
28
|
+
*
|
|
29
|
+
* @example Astro (view transitions)
|
|
30
|
+
* document.addEventListener('astro:page-load', () => {
|
|
31
|
+
* window._ctx?.revert()
|
|
32
|
+
* window._ctx = Motion.context(() => { ... })
|
|
33
|
+
* })
|
|
34
|
+
*/
|
|
35
|
+
export declare class MotionContext {
|
|
36
|
+
/** The init function that creates animations — re-executed on refresh() */
|
|
37
|
+
private _fn;
|
|
38
|
+
/** Timeline names created within this context */
|
|
39
|
+
private _timelineNames;
|
|
40
|
+
/** Whether this context has been reverted (prevents double-revert) */
|
|
41
|
+
private _reverted;
|
|
42
|
+
constructor(fn: () => void);
|
|
43
|
+
/**
|
|
44
|
+
* Kill all timelines created in this context, restore elements to their
|
|
45
|
+
* initial CSS state, and clean up DOM artifacts (ScrollTrigger spacers/markers).
|
|
46
|
+
*
|
|
47
|
+
* After revert(), the context is empty and can be refreshed or discarded.
|
|
48
|
+
*/
|
|
49
|
+
revert(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Revert all animations and re-execute the init function.
|
|
52
|
+
* Selectors are re-resolved against the current DOM, so new/replaced
|
|
53
|
+
* elements are picked up automatically.
|
|
54
|
+
*
|
|
55
|
+
* This is the primary method for handling dynamic content changes.
|
|
56
|
+
*/
|
|
57
|
+
refresh(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Add more animations to this context without affecting existing ones.
|
|
60
|
+
* Useful for lazy-loaded content or progressive enhancement.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ctx.add(() => {
|
|
64
|
+
* Motion('lazy-section', '.lazy-card', { ... }).onScroll({ scrub: true })
|
|
65
|
+
* })
|
|
66
|
+
*/
|
|
67
|
+
add(fn: () => void): void;
|
|
68
|
+
/**
|
|
69
|
+
* Get the timeline names tracked by this context (for debugging/testing).
|
|
70
|
+
*/
|
|
71
|
+
getTimelineNames(): string[];
|
|
72
|
+
/**
|
|
73
|
+
* Execute a function while capturing timeline names into this context.
|
|
74
|
+
* Uses Engine's capture mechanism for zero-overhead tracking.
|
|
75
|
+
*/
|
|
76
|
+
private _execute;
|
|
77
|
+
}
|
package/dist/core/PropTween.d.ts
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
import type { AnimationTarget } from '../types';
|
|
9
9
|
import type { ParsedFilterFunction } from '../utils/FilterParser';
|
|
10
10
|
import type { ParsedDrawSVG } from '../utils/DrawSVGParser';
|
|
11
|
+
import type { ParsedClipPath } from '../utils/ClipPathParser';
|
|
11
12
|
import { type PathPoint } from '../utils/PathParser';
|
|
12
|
-
type PropTweenValueType = 'scalar' | 'color' | 'filter' | 'drawSVG' | 'path';
|
|
13
|
+
type PropTweenValueType = 'scalar' | 'color' | 'filter' | 'drawSVG' | 'path' | 'clipPath';
|
|
13
14
|
export declare class PropTween {
|
|
14
15
|
target: AnimationTarget | null;
|
|
15
16
|
property: string;
|
|
@@ -27,6 +28,8 @@ export declare class PropTween {
|
|
|
27
28
|
startDraw: ParsedDrawSVG | null;
|
|
28
29
|
endDraw: ParsedDrawSVG | null;
|
|
29
30
|
pathLength: number;
|
|
31
|
+
startClipPath: ParsedClipPath | null;
|
|
32
|
+
endClipPath: ParsedClipPath | null;
|
|
30
33
|
pathData: string | null;
|
|
31
34
|
motionPathLength: number;
|
|
32
35
|
startProgress: number;
|
|
@@ -54,6 +57,10 @@ export declare class PropTween {
|
|
|
54
57
|
* Initialize the PropTween with filter values
|
|
55
58
|
*/
|
|
56
59
|
initFilter(target: AnimationTarget, property: string, startFilters: ParsedFilterFunction[], endFilters: ParsedFilterFunction[]): this;
|
|
60
|
+
/**
|
|
61
|
+
* Initialize the PropTween with clip-path values
|
|
62
|
+
*/
|
|
63
|
+
initClipPath(target: AnimationTarget, property: string, startClipPath: ParsedClipPath, endClipPath: ParsedClipPath): this;
|
|
57
64
|
/**
|
|
58
65
|
* Initialize the PropTween with drawSVG values
|
|
59
66
|
*/
|
package/dist/core/Timeline.d.ts
CHANGED
|
@@ -326,10 +326,14 @@ export declare class Timeline {
|
|
|
326
326
|
/**
|
|
327
327
|
* Kill timeline and all children, reset all state
|
|
328
328
|
* @param clearProps - If true (default), restore elements to their initial CSS values
|
|
329
|
+
*
|
|
330
|
+
* Any text splits owned by this timeline's builders are reverted via
|
|
331
|
+
* SDKRegistry.textSplitter.revert() (reference-counted — safe when
|
|
332
|
+
* other timelines still share the split element).
|
|
329
333
|
*/
|
|
330
334
|
kill(clearProps?: boolean): void;
|
|
331
335
|
/**
|
|
332
|
-
* Check if timeline is currently active
|
|
336
|
+
* Check if timeline is currently active.
|
|
333
337
|
*/
|
|
334
338
|
isActive(): boolean;
|
|
335
339
|
/**
|