@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
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { ParsedFilterFunction } from '../utils/FilterParser';
|
|
9
9
|
import type { ParsedDrawSVG } from '../utils/DrawSVGParser';
|
|
10
|
-
import type {
|
|
10
|
+
import type { ParsedClipPath } from '../utils/ClipPathParser';
|
|
11
|
+
import type { AnimationTarget, StaggerVars, SplitType, FlapConfig } from '../types';
|
|
11
12
|
import type { TriggerManager } from '../triggers/TriggerManager';
|
|
13
|
+
import type { FlapController, FlapCharDriver, UserPropEntry } from '../utils/TextFlapper';
|
|
12
14
|
interface ColorParserFunctions {
|
|
13
15
|
parseColor: (color: string, element?: Element) => Float32Array | null;
|
|
14
16
|
getCurrentColor: (element: Element, property: string) => Float32Array;
|
|
@@ -32,6 +34,13 @@ interface DrawSVGParserFunctions {
|
|
|
32
34
|
getPathLength: (element: Element) => number;
|
|
33
35
|
applyDrawSVG: (element: Element, start: number, end: number, length: number) => void;
|
|
34
36
|
}
|
|
37
|
+
interface ClipPathParserFunctions {
|
|
38
|
+
parseClipPath: (value: string) => ParsedClipPath | null;
|
|
39
|
+
getCurrentClipPath: (element: Element) => ParsedClipPath | null;
|
|
40
|
+
interpolateClipPaths: (start: ParsedClipPath, end: ParsedClipPath, progress: number) => ParsedClipPath;
|
|
41
|
+
clipPathToString: (parsed: ParsedClipPath) => string;
|
|
42
|
+
canInterpolate: (start: ParsedClipPath, end: ParsedClipPath) => boolean;
|
|
43
|
+
}
|
|
35
44
|
interface TextSplitterFunctions {
|
|
36
45
|
split: (element: Element, type: SplitType, options?: {
|
|
37
46
|
mask?: boolean;
|
|
@@ -49,6 +58,11 @@ interface StyleResetFunctions {
|
|
|
49
58
|
interface FitResolverFunctions {
|
|
50
59
|
registerPendingSetup(animation: import('../core/Animation').Animation, element: Element, fitConfig: import('../types').FitConfig, propTweenPool: typeof import('../memory/PropTweenPool').PropTweenPool): void;
|
|
51
60
|
}
|
|
61
|
+
interface TextFlapperFunctions {
|
|
62
|
+
prepare: (charElements: HTMLElement[], config: FlapConfig, continuous?: boolean, userProps?: UserPropEntry[]) => FlapCharDriver[];
|
|
63
|
+
flap: (charElements: HTMLElement[], config: FlapConfig, staggerDelays?: number[], continuous?: boolean) => FlapController;
|
|
64
|
+
revert: (charElements: HTMLElement[]) => void;
|
|
65
|
+
}
|
|
52
66
|
/**
|
|
53
67
|
* Unified registry for all optional SDK features.
|
|
54
68
|
* Each slot is null until the corresponding module loads and self-registers.
|
|
@@ -57,10 +71,12 @@ export declare const SDKRegistry: {
|
|
|
57
71
|
color: ColorParserFunctions | null;
|
|
58
72
|
filter: FilterParserFunctions | null;
|
|
59
73
|
drawSVG: DrawSVGParserFunctions | null;
|
|
74
|
+
clipPath: ClipPathParserFunctions | null;
|
|
60
75
|
stagger: {
|
|
61
76
|
resolve: (targets: AnimationTarget[], stagger: number | StaggerVars) => number[];
|
|
62
77
|
} | null;
|
|
63
78
|
textSplitter: TextSplitterFunctions | null;
|
|
79
|
+
textFlapper: TextFlapperFunctions | null;
|
|
64
80
|
triggerManager: {
|
|
65
81
|
getInstance: () => TriggerManager;
|
|
66
82
|
} | null;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* - Outside tick → write immediately to DOM (responsiveness for seek/progress/etc.)
|
|
13
13
|
*/
|
|
14
14
|
import type { ParsedFilterFunction } from '../utils/FilterParser';
|
|
15
|
+
import type { ParsedClipPath } from '../utils/ClipPathParser';
|
|
15
16
|
/**
|
|
16
17
|
* Set a CSS property value on an element
|
|
17
18
|
* Automatically batches during animation tick, writes immediately otherwise
|
|
@@ -31,3 +32,12 @@ export declare function getCSSProperty(element: Element, property: string): stri
|
|
|
31
32
|
* Interpolates between start and end filter arrays at given progress
|
|
32
33
|
*/
|
|
33
34
|
export declare function setCSSFilterProperty(element: Element, startFilters: ParsedFilterFunction[], endFilters: ParsedFilterFunction[], progress: number): void;
|
|
35
|
+
/**
|
|
36
|
+
* Set a CSS clip-path property by interpolating two parsed shape functions.
|
|
37
|
+
*
|
|
38
|
+
* Mirrors `setCSSFilterProperty`: looks up the (optional) ClipPathParser
|
|
39
|
+
* through SDKRegistry, interpolates the components at the given progress,
|
|
40
|
+
* serializes the result to a CSS string, then either queues the write or
|
|
41
|
+
* applies it immediately depending on tick context.
|
|
42
|
+
*/
|
|
43
|
+
export declare function setCSSClipPathProperty(element: Element, property: string, startClipPath: ParsedClipPath, endClipPath: ParsedClipPath, progress: number): void;
|
|
@@ -14,6 +14,7 @@ export interface EventTriggerConfig {
|
|
|
14
14
|
secondTarget?: string | Element;
|
|
15
15
|
toggle?: 'reverse' | 'restart' | 'play';
|
|
16
16
|
preventDefault?: boolean;
|
|
17
|
+
onEnter?: 'play' | 'restart';
|
|
17
18
|
onLeave?: 'reverse' | 'pause' | 'stop' | 'restart' | 'none';
|
|
18
19
|
leaveDelay?: number;
|
|
19
20
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import type { MarkerConfig } from '../types';
|
|
10
10
|
interface MarkerSetupConfig {
|
|
11
11
|
scroller: Element | Window;
|
|
12
|
-
triggerElement:
|
|
12
|
+
triggerElement: Element | null;
|
|
13
13
|
startConfig: string;
|
|
14
14
|
endConfig: string;
|
|
15
15
|
markerConfig: MarkerConfig | boolean;
|
|
@@ -43,7 +43,7 @@ export declare class MarkerManager {
|
|
|
43
43
|
* Update marker positions on scroll.
|
|
44
44
|
* Uses cached document-relative positions to avoid getLayoutRect() per frame.
|
|
45
45
|
*/
|
|
46
|
-
update(scrollTop: number, triggerElement:
|
|
46
|
+
update(scrollTop: number, triggerElement: Element | null, viewportHeight: number): void;
|
|
47
47
|
/**
|
|
48
48
|
* Recache element positions after layout changes (resize, refresh).
|
|
49
49
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -131,6 +131,100 @@ export interface PathConfig {
|
|
|
131
131
|
/** Auto-rotate element along path tangent */
|
|
132
132
|
rotate?: boolean;
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Preset character sets available for TextFlapper cycling animations.
|
|
136
|
+
*/
|
|
137
|
+
export type CharsetPreset = 'alphanumeric' | 'alpha' | 'numeric' | 'hex' | 'binary' | 'katakana' | 'symbols' | 'blocks';
|
|
138
|
+
/**
|
|
139
|
+
* Configuration for TextFlapper split-flap display animations.
|
|
140
|
+
* Passed as the `flap` property on an AnimationConfig to enable character cycling.
|
|
141
|
+
*
|
|
142
|
+
* **Per-cycle composition** — When `flap` is present on an AnimationConfig, all
|
|
143
|
+
* `from`/`to` properties automatically animate per character-swap cycle instead of
|
|
144
|
+
* once over the full duration. Each cycle follows a V-curve: rests at `to`, dips to
|
|
145
|
+
* `from` at the midpoint (when the character swaps), then returns to `to`.
|
|
146
|
+
*/
|
|
147
|
+
export interface FlapConfig {
|
|
148
|
+
/**
|
|
149
|
+
* Visual style for each character cycle.
|
|
150
|
+
* - `'flip'` — 3D CSS rotateX transition (default)
|
|
151
|
+
* - `'fade'` — CSS opacity fade out/in
|
|
152
|
+
* - `'slide'` — CSS translateY slide out/in
|
|
153
|
+
* - `'blur'` — CSS filter blur out/in
|
|
154
|
+
* - `'scale'` — CSS scale pop/shrink
|
|
155
|
+
* - `'board'` — mechanical split-flap (departure board)
|
|
156
|
+
* - `'none'` — No built-in visual effect; characters cycle with instant swap.
|
|
157
|
+
* Use with `from`/`to` to create fully custom flap animations — all
|
|
158
|
+
* properties animate per-cycle (V-curve: to→from→to on each swap).
|
|
159
|
+
*/
|
|
160
|
+
type?: 'flip' | 'fade' | 'slide' | 'blur' | 'scale' | 'board' | 'none';
|
|
161
|
+
/**
|
|
162
|
+
* Character set used for intermediate (scrambled) frames.
|
|
163
|
+
* Use a CharsetPreset name or any custom string of characters.
|
|
164
|
+
* @default 'alphanumeric'
|
|
165
|
+
*/
|
|
166
|
+
charset?: CharsetPreset | string;
|
|
167
|
+
/**
|
|
168
|
+
* Number of random cycles each character performs before settling.
|
|
169
|
+
* - `number` : exact cycle count for every character
|
|
170
|
+
* - `[min, max]` : random count in range, chosen independently per character
|
|
171
|
+
* @default [2, 5]
|
|
172
|
+
*/
|
|
173
|
+
cycles?: number | [min: number, max: number];
|
|
174
|
+
/**
|
|
175
|
+
* Perspective depth (px) for the 3D flip/board animation.
|
|
176
|
+
* Only used when `type` is 'flip' or 'board'.
|
|
177
|
+
* @default 400
|
|
178
|
+
*/
|
|
179
|
+
perspective?: number;
|
|
180
|
+
/**
|
|
181
|
+
* When true, board-type flaps get a realistic departure-board look:
|
|
182
|
+
* dark gradient background, rounded corners, and a visible split line.
|
|
183
|
+
* Only applies when `type` is 'board'.
|
|
184
|
+
* @default true
|
|
185
|
+
*/
|
|
186
|
+
styledBoard?: boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Strategy for preventing layout shift while characters cycle:
|
|
189
|
+
*
|
|
190
|
+
* - `false` (default) — no pinning. Text width flexes with each glyph.
|
|
191
|
+
* Fine for same-width charsets (Latin → alphanumeric).
|
|
192
|
+
* - `true` or `'cells'` — pin each character cell to the widest glyph
|
|
193
|
+
* across the target chars AND the charset pool. Every cell is the
|
|
194
|
+
* same width regardless of which random glyph renders at the moment.
|
|
195
|
+
* Good for monospace aesthetics (departure boards, counters). Adds
|
|
196
|
+
* visible horizontal space around narrow Latin letters when paired
|
|
197
|
+
* with wide charsets (katakana, CJK).
|
|
198
|
+
* - `'container'` — pin the parent element's outer width to whatever
|
|
199
|
+
* the text would measure at the widest possible flap state, but
|
|
200
|
+
* DON'T pin individual cells. Characters flow naturally (no extra
|
|
201
|
+
* spacing between Latin letters), while the surrounding layout
|
|
202
|
+
* (rows of links, inline columns, etc.) stays rock-steady because
|
|
203
|
+
* the element's outer box never changes size. Best choice for
|
|
204
|
+
* inline hover flappers on navigation links where cell-pinning
|
|
205
|
+
* would space the letters out unnaturally.
|
|
206
|
+
*
|
|
207
|
+
* Automatically enabled (as `'cells'`) for `board` + `styledBoard: true`.
|
|
208
|
+
* @default false
|
|
209
|
+
*/
|
|
210
|
+
stableWidth?: boolean | 'cells' | 'container';
|
|
211
|
+
/**
|
|
212
|
+
* When true and `type` is 'board', whitespace characters (spaces, tabs,
|
|
213
|
+
* newlines) are rendered as empty board cells — the cell frame, background,
|
|
214
|
+
* perspective, and split line are built as usual, but the cell face is blank
|
|
215
|
+
* (non-breaking space) and no flap animation runs.
|
|
216
|
+
*
|
|
217
|
+
* Rationale: real split-flap departure boards have fixed cells regardless of
|
|
218
|
+
* which positions contain characters. Enabling this lets you animate text of
|
|
219
|
+
* varying lengths without the board width or cell count shifting between
|
|
220
|
+
* lines.
|
|
221
|
+
*
|
|
222
|
+
* Has no effect when `type` is anything other than 'board'. Default `false`
|
|
223
|
+
* preserves existing behavior (whitespace cells are skipped entirely).
|
|
224
|
+
* @default false
|
|
225
|
+
*/
|
|
226
|
+
preserveWhitespaceCells?: boolean;
|
|
227
|
+
}
|
|
134
228
|
/**
|
|
135
229
|
* Configuration for Fit animations.
|
|
136
230
|
* Morphs one element's geometry to match another's — captures source and target
|
|
@@ -182,6 +276,18 @@ export interface AnimationConfig {
|
|
|
182
276
|
* Motion('reveal', 'h1', { split: 'lines', mask: true, from: { y: '100%' }, to: { y: 0 }, stagger: 0.1 })
|
|
183
277
|
*/
|
|
184
278
|
mask?: boolean;
|
|
279
|
+
/**
|
|
280
|
+
* Split-flap display animation configuration.
|
|
281
|
+
* Animates pre-split character elements through random character cycling before
|
|
282
|
+
* settling on the target character. Requires the target elements to already be
|
|
283
|
+
* split into individual character spans (e.g. via TextSplitter with 'chars').
|
|
284
|
+
*
|
|
285
|
+
* Per-character animations are created by the engine; flap preset values
|
|
286
|
+
* (rotateX, opacity, etc.) merge into from/to at low priority — user values always win.
|
|
287
|
+
* @example
|
|
288
|
+
* Motion('scramble', chars, { flap: { type: 'flip', charset: 'alphanumeric', cycles: [2, 5] } })
|
|
289
|
+
*/
|
|
290
|
+
flap?: FlapConfig;
|
|
185
291
|
/**
|
|
186
292
|
* Fit animation configuration.
|
|
187
293
|
* Morphs the source element's geometry toward the target element's geometry.
|
|
@@ -254,6 +360,20 @@ export interface MarkerConfig {
|
|
|
254
360
|
export interface HoverConfig {
|
|
255
361
|
target?: string | Element;
|
|
256
362
|
each?: boolean;
|
|
363
|
+
/**
|
|
364
|
+
* What happens on mouseenter:
|
|
365
|
+
* - `'play'` (default) — `.play()` the timeline. Resumes from current
|
|
366
|
+
* position; silently no-ops when already at the end. Best for
|
|
367
|
+
* reversible hover animations paired with `onLeave: 'reverse'`.
|
|
368
|
+
* - `'restart'` — `.restart()` the timeline ONLY when the previous run
|
|
369
|
+
* has finished (or hasn't started yet). If the timeline is still
|
|
370
|
+
* mid-play, the current run is allowed to finish uninterrupted —
|
|
371
|
+
* jittery cursors at the element edge won't stutter the animation
|
|
372
|
+
* and leaving + re-entering mid-flap won't reset it. Best for
|
|
373
|
+
* one-shot effects (text flappers, shake, decode reveal). Pair with
|
|
374
|
+
* `onLeave: 'none'` so the animation finishes naturally on leave.
|
|
375
|
+
*/
|
|
376
|
+
onEnter?: 'play' | 'restart';
|
|
257
377
|
onLeave?: 'reverse' | 'pause' | 'stop' | 'restart' | 'none';
|
|
258
378
|
leaveDelay?: number;
|
|
259
379
|
}
|
package/dist/types/public.d.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* This file re-exports only the public types intended for SDK users.
|
|
5
5
|
* Internal types are co-located with their implementations.
|
|
6
6
|
*/
|
|
7
|
-
export type { EasingFunction, SplitType, RepeatConfig, StaggerVars, AnimationVars, PathConfig, FitConfig, AnimationConfig, AnimationEntry, ObjectTarget, AnimationTarget, TargetInput, MarkerConfig, HoverConfig, ClickConfig, ScrollConfig, MouseMoveConfig, PageExitConfig, GestureInputType, GestureEvent, GestureAction, GestureConfig, CursorStateVars, CursorSqueezeConfig, CursorConfig, } from './index';
|
|
7
|
+
export type { EasingFunction, SplitType, RepeatConfig, StaggerVars, AnimationVars, PathConfig, FitConfig, CharsetPreset, FlapConfig, AnimationConfig, AnimationEntry, ObjectTarget, AnimationTarget, TargetInput, MarkerConfig, HoverConfig, ClickConfig, ScrollConfig, MouseMoveConfig, PageExitConfig, GestureInputType, GestureEvent, GestureAction, GestureConfig, CursorStateVars, CursorSqueezeConfig, CursorConfig, } from './index';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClipPathParser - Parse and interpolate CSS clip-path shape functions
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - circle(<radius> at <x> <y>)
|
|
6
|
+
* - ellipse(<rx> <ry> at <x> <y>)
|
|
7
|
+
* - inset(<top> <right>? <bottom>? <left>? round <radius>?)
|
|
8
|
+
* - polygon(<x1> <y1>, <x2> <y2>, …)
|
|
9
|
+
* - rect(<top> <right> <bottom> <left> round <radius>?)
|
|
10
|
+
* - xywh(<x> <y> <w> <h> round <radius>?)
|
|
11
|
+
*
|
|
12
|
+
* Interpolation rules:
|
|
13
|
+
* - From and To must use the same shape function — otherwise we snap to the
|
|
14
|
+
* end value at progress >= 0.5 (no shape morphing across types).
|
|
15
|
+
* - polygon vertex counts must match — otherwise we snap to the end value.
|
|
16
|
+
* - Each numeric component is lerped while preserving the unit emitted in the
|
|
17
|
+
* end value (start unit kept when end has none).
|
|
18
|
+
*
|
|
19
|
+
* Loaded conditionally through SDKRegistry so the bundler can drop it when
|
|
20
|
+
* no animation uses clip-path.
|
|
21
|
+
*/
|
|
22
|
+
export type ClipPathShape = 'circle' | 'ellipse' | 'inset' | 'polygon' | 'rect' | 'xywh';
|
|
23
|
+
/**
|
|
24
|
+
* A single numeric component with its CSS unit (e.g. 71 + "%" or 10 + "px").
|
|
25
|
+
*/
|
|
26
|
+
export interface ClipPathComponent {
|
|
27
|
+
value: number;
|
|
28
|
+
unit: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Parsed clip-path shape function.
|
|
32
|
+
*
|
|
33
|
+
* `components` holds the ordered numeric values that get interpolated. The
|
|
34
|
+
* meaning of each slot is shape-specific — see the assemble* helpers.
|
|
35
|
+
*
|
|
36
|
+
* `extras` carries non-numeric tokens (e.g. the `round` keyword for inset/rect/
|
|
37
|
+
* xywh) that we preserve verbatim when re-serializing.
|
|
38
|
+
*/
|
|
39
|
+
export interface ParsedClipPath {
|
|
40
|
+
shape: ClipPathShape;
|
|
41
|
+
components: ClipPathComponent[];
|
|
42
|
+
extras?: {
|
|
43
|
+
hasRound?: boolean;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Parse a clip-path value string into a structured `ParsedClipPath`.
|
|
48
|
+
* Returns null if the value is `none`, empty, or an unsupported shape.
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseClipPath(value: string): ParsedClipPath | null;
|
|
51
|
+
/**
|
|
52
|
+
* Read the current computed clip-path on an element.
|
|
53
|
+
* Returns null when there is no clip-path or it's a non-shape value.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getCurrentClipPath(element: Element): ParsedClipPath | null;
|
|
56
|
+
/**
|
|
57
|
+
* Returns true when start/end are interpolatable: same shape and component
|
|
58
|
+
* count. Polygon morphing requires identical vertex counts.
|
|
59
|
+
*/
|
|
60
|
+
export declare function canInterpolate(start: ParsedClipPath, end: ParsedClipPath): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Interpolate two parsed clip-paths at `progress` (0-1).
|
|
63
|
+
*
|
|
64
|
+
* If shapes/lengths don't match, falls back to a hard swap at progress >= 0.5
|
|
65
|
+
* — no smooth morphing is possible across different shape functions.
|
|
66
|
+
*
|
|
67
|
+
* Returns a `ParsedClipPath` whose `components` array is reused on subsequent
|
|
68
|
+
* calls — consume it (e.g. via `clipPathToString`) before the next invocation.
|
|
69
|
+
*/
|
|
70
|
+
export declare function interpolateClipPaths(start: ParsedClipPath, end: ParsedClipPath, progress: number): ParsedClipPath;
|
|
71
|
+
/**
|
|
72
|
+
* Serialize a parsed clip-path back into a valid CSS clip-path string.
|
|
73
|
+
*/
|
|
74
|
+
export declare function clipPathToString(parsed: ParsedClipPath): string;
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import type { AnimationTarget } from '../types';
|
|
16
16
|
import type { ParsedFilterFunction } from './FilterParser';
|
|
17
17
|
import type { ParsedDrawSVG } from './DrawSVGParser';
|
|
18
|
+
import type { ParsedClipPath } from './ClipPathParser';
|
|
18
19
|
/**
|
|
19
20
|
* Valid property value types for animation
|
|
20
21
|
*/
|
|
@@ -60,6 +61,14 @@ interface ParsedDrawSVGProperty extends ParsedPropertyBase {
|
|
|
60
61
|
endDraw: ParsedDrawSVG;
|
|
61
62
|
length: number;
|
|
62
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Clip-path property (CSS clip-path shape function interpolation)
|
|
66
|
+
*/
|
|
67
|
+
interface ParsedClipPathProperty extends ParsedPropertyBase {
|
|
68
|
+
type: 'clipPath';
|
|
69
|
+
startClipPath: ParsedClipPath;
|
|
70
|
+
endClipPath: ParsedClipPath;
|
|
71
|
+
}
|
|
63
72
|
/**
|
|
64
73
|
* Path property (motion along SVG path)
|
|
65
74
|
*/
|
|
@@ -82,7 +91,7 @@ interface ParsedPathProperty extends ParsedPropertyBase {
|
|
|
82
91
|
/**
|
|
83
92
|
* Discriminated union of all parsed property types
|
|
84
93
|
*/
|
|
85
|
-
export type ParsedProperty = ParsedScalarProperty | ParsedColorProperty | ParsedFilterProperty | ParsedDrawSVGProperty | ParsedPathProperty;
|
|
94
|
+
export type ParsedProperty = ParsedScalarProperty | ParsedColorProperty | ParsedFilterProperty | ParsedDrawSVGProperty | ParsedPathProperty | ParsedClipPathProperty;
|
|
86
95
|
/**
|
|
87
96
|
* Check if a property is a transform property
|
|
88
97
|
*/
|
|
@@ -103,6 +112,10 @@ export declare function isDrawSVGProp(prop: string): boolean;
|
|
|
103
112
|
* Check if a property is the path property (motion path)
|
|
104
113
|
*/
|
|
105
114
|
export declare function isPathProp(prop: string): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Check if a property is the clip-path property (accepts both kebab and camel case)
|
|
117
|
+
*/
|
|
118
|
+
export declare function isClipPathProp(prop: string): boolean;
|
|
106
119
|
/**
|
|
107
120
|
* Check if a property is a CSS variable (custom property)
|
|
108
121
|
*/
|
|
@@ -127,6 +140,25 @@ export declare function getDefaultUnit(prop: string): string;
|
|
|
127
140
|
* Handles both DOM Elements and plain objects
|
|
128
141
|
*/
|
|
129
142
|
export declare function getCurrentValue(target: AnimationTarget, prop: string): number;
|
|
143
|
+
/**
|
|
144
|
+
* Convert a pixel value to a target CSS unit by measuring the element in the DOM.
|
|
145
|
+
*
|
|
146
|
+
* Uses the browser's layout engine: temporarily sets `100{targetUnit}` on the
|
|
147
|
+
* element, reads the computed pixel equivalent, then derives the conversion ratio.
|
|
148
|
+
* This handles %, em, rem, vw, vh, vmin, vmax, ch, ex — any unit the browser supports.
|
|
149
|
+
*
|
|
150
|
+
* When the target unit is 'px' or empty, returns the value unchanged (no conversion).
|
|
151
|
+
* Falls back to the raw pixel value if measurement fails (e.g. detached element).
|
|
152
|
+
*/
|
|
153
|
+
export declare function convertPxToUnit(element: Element, prop: string, pxValue: number, targetUnit: string): number;
|
|
154
|
+
/**
|
|
155
|
+
* Get the current computed value of a property, converted to the specified unit.
|
|
156
|
+
*
|
|
157
|
+
* Combines getCurrentValue (which always returns px for layout properties)
|
|
158
|
+
* with convertPxToUnit to return the value in the desired CSS unit.
|
|
159
|
+
* Only performs conversion for DOM Element targets with non-px units.
|
|
160
|
+
*/
|
|
161
|
+
export declare function getCurrentValueInUnit(target: AnimationTarget, prop: string, targetUnit: string): number;
|
|
130
162
|
/**
|
|
131
163
|
* Get the original CSS value AND unit of a property (excluding inline styles)
|
|
132
164
|
* Returns both value and unit to preserve the original CSS unit (%, rem, em, vh, etc.)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TextFlapper - Split-flap display animation utility
|
|
3
|
+
*
|
|
4
|
+
* Produces per-character render drivers that animate text through random
|
|
5
|
+
* character cycling before settling on the target character — inspired by
|
|
6
|
+
* split-flap departure boards.
|
|
7
|
+
*
|
|
8
|
+
* Seven visual modes:
|
|
9
|
+
* - 'flip' : 3D rotateX (default)
|
|
10
|
+
* - 'fade' : opacity fade
|
|
11
|
+
* - 'slide' : translateY slide
|
|
12
|
+
* - 'blur' : filter blur out/in
|
|
13
|
+
* - 'scale' : scale pop/shrink
|
|
14
|
+
* - 'board' : mechanical split-flap (departure board)
|
|
15
|
+
* - 'none' : instant text swap
|
|
16
|
+
*
|
|
17
|
+
* Integration paths:
|
|
18
|
+
* 1. SDK pipeline — `prepare()` returns drivers consumed by AnimationBuilder,
|
|
19
|
+
* which creates real Animation objects managed by Engine/Timeline.
|
|
20
|
+
* 2. Standalone — `flap()` drives the animation via requestAnimationFrame
|
|
21
|
+
* for direct usage outside the SDK pipeline (e.g. ConnectAI button).
|
|
22
|
+
*
|
|
23
|
+
* Usage (standalone):
|
|
24
|
+
* const ctrl = TextFlapper.flap(charEls, { type: 'flip' });
|
|
25
|
+
* ctrl.kill();
|
|
26
|
+
*
|
|
27
|
+
* Revert:
|
|
28
|
+
* TextFlapper.revert(charEls);
|
|
29
|
+
*/
|
|
30
|
+
import type { FlapConfig } from '../types';
|
|
31
|
+
/**
|
|
32
|
+
* A single numeric property to interpolate per flap cycle.
|
|
33
|
+
* AnimationBuilder populates these from user-provided from/to vars so that
|
|
34
|
+
* CSS properties animate once per character-swap cycle instead of once over
|
|
35
|
+
* the full animation duration.
|
|
36
|
+
*/
|
|
37
|
+
export interface UserPropEntry {
|
|
38
|
+
/** CSS property name or transform shorthand (e.g. 'y', 'opacity', 'rotateX') */
|
|
39
|
+
prop: string;
|
|
40
|
+
/** Start value (from) */
|
|
41
|
+
from: number;
|
|
42
|
+
/** End value (to) */
|
|
43
|
+
to: number;
|
|
44
|
+
/** CSS unit string: 'px', 'deg', '%', or '' for unitless */
|
|
45
|
+
unit: string;
|
|
46
|
+
/** True when prop is a TransformCache property (routes through setTransformValue) */
|
|
47
|
+
isTransform: boolean;
|
|
48
|
+
}
|
|
49
|
+
/** Lightweight controller for standalone flap() usage (ConnectAI, etc.) */
|
|
50
|
+
export interface FlapController {
|
|
51
|
+
kill(): void;
|
|
52
|
+
readonly finished: Promise<void>;
|
|
53
|
+
readonly isComplete: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Per-character render driver returned by `prepare()`.
|
|
57
|
+
* AnimationBuilder uses these to create real Animation objects via Engine.
|
|
58
|
+
*/
|
|
59
|
+
export interface FlapCharDriver {
|
|
60
|
+
/** The character element */
|
|
61
|
+
readonly el: HTMLElement;
|
|
62
|
+
/** Called each frame with progress (0-1). Drives text swaps + visual effects. */
|
|
63
|
+
readonly render: (progress: number) => void;
|
|
64
|
+
/** Snap to resolved final state. Called on animation complete. */
|
|
65
|
+
readonly finalize: () => void;
|
|
66
|
+
}
|
|
67
|
+
export declare class TextFlapper {
|
|
68
|
+
/**
|
|
69
|
+
* Prepare per-character animation drivers for the split-flap effect.
|
|
70
|
+
*
|
|
71
|
+
* Returns one FlapCharDriver per non-whitespace character. Each driver
|
|
72
|
+
* provides `duration`, `render(progress)`, and `finalize()` — intended to
|
|
73
|
+
* be consumed by AnimationBuilder, which creates real Engine-managed
|
|
74
|
+
* Animation objects from them.
|
|
75
|
+
*
|
|
76
|
+
* This method handles:
|
|
77
|
+
* - Recording original textContent for revert
|
|
78
|
+
* - Applying one-time type-specific setup styles
|
|
79
|
+
* - Pre-generating random character sequences
|
|
80
|
+
*
|
|
81
|
+
* @param charElements - Pre-split character span elements
|
|
82
|
+
* @param config - Flap animation configuration
|
|
83
|
+
*/
|
|
84
|
+
static prepare(charElements: HTMLElement[], config: FlapConfig, continuous?: boolean, userProps?: UserPropEntry[]): FlapCharDriver[];
|
|
85
|
+
/**
|
|
86
|
+
* Standalone split-flap animation using requestAnimationFrame.
|
|
87
|
+
*
|
|
88
|
+
* For use outside the SDK pipeline (e.g. ConnectAI button) where Engine
|
|
89
|
+
* may not be initialised. Returns a lightweight FlapController.
|
|
90
|
+
*
|
|
91
|
+
* Duration is computed internally from cycles and a default speed (80ms).
|
|
92
|
+
* Stagger defaults to sequential character start with 2× speed gap.
|
|
93
|
+
*
|
|
94
|
+
* @param charElements - Pre-split character span elements
|
|
95
|
+
* @param config - Flap animation configuration
|
|
96
|
+
* @param staggerDelays - Optional per-element start delays in milliseconds
|
|
97
|
+
* @param continuous - When true, characters cycle indefinitely (never land on target)
|
|
98
|
+
*/
|
|
99
|
+
static flap(charElements: HTMLElement[], config: FlapConfig, staggerDelays?: number[], continuous?: boolean): FlapController;
|
|
100
|
+
/**
|
|
101
|
+
* Revert character elements to their original text content and remove
|
|
102
|
+
* all inline styles applied by TextFlapper.
|
|
103
|
+
*/
|
|
104
|
+
static revert(charElements: HTMLElement[]): void;
|
|
105
|
+
}
|
|
@@ -118,6 +118,14 @@ export declare class TextSplitter {
|
|
|
118
118
|
*
|
|
119
119
|
* Without this, inline-block split spans inherit `-webkit-text-fill-color: transparent`
|
|
120
120
|
* but NOT the parent's gradient background, making the text invisible.
|
|
121
|
+
*
|
|
122
|
+
* IMPORTANT: We copy the computed background-image directly instead of using
|
|
123
|
+
* `background: inherit` because `background` is NOT an inherited CSS property.
|
|
124
|
+
* When the split element contains intermediate wrapper elements (e.g.
|
|
125
|
+
* `<h1><span class="line"><span class="accent">word</span></span></h1>`),
|
|
126
|
+
* `inherit` resolves to `none` at each intermediate element, breaking the chain.
|
|
127
|
+
* Copying the resolved value ensures the gradient reaches every split span
|
|
128
|
+
* regardless of DOM depth.
|
|
121
129
|
*/
|
|
122
130
|
private static _propagateGradientText;
|
|
123
131
|
/**
|
package/llms.txt
CHANGED
|
@@ -42,7 +42,7 @@ For complete SDK documentation, install the motion-page skill: `npx skills add m
|
|
|
42
42
|
## Animation Config
|
|
43
43
|
|
|
44
44
|
- **AnimationConfig**: from, to, duration, delay, ease, stagger, repeat, split, mask, fit, axis, callbacks
|
|
45
|
-
- **AnimationVars**: Transforms, opacity, colors, CSS properties, filter, drawSVG, path, custom properties
|
|
45
|
+
- **AnimationVars**: Transforms, opacity, colors, CSS properties, filter, clip-path, drawSVG, path, custom properties
|
|
46
46
|
- **Easing**: power1-4, sine, expo, circ, back, elastic, bounce — .in/.out/.inOut
|
|
47
47
|
- **Stagger**: each, amount, from (start/center/edges/random/end/index), grid, axis, ease
|
|
48
48
|
- **Position Parameter**: Absolute (number), relative (+=/-=), anchored (<, >, <0.2, >-0.1)
|
|
@@ -52,6 +52,7 @@ For complete SDK documentation, install the motion-page skill: `npx skills add m
|
|
|
52
52
|
- **Text Splitting**: split: chars/words/lines; mask: true for clip reveals; data-split-* attributes
|
|
53
53
|
- **FLIP Morphing**: fit: { target, scale, resize, absolute } — animate between element states
|
|
54
54
|
- **DrawSVG**: String format ("0% 100%") or object ({ start, end } as 0-100 percentages)
|
|
55
|
+
- **Clip Path**: Animate clip-path/clipPath between matching shapes (circle, ellipse, inset, polygon, rect, xywh); same shape on both ends; polygon vertex counts must match; cross-shape hard-swaps at progress >= 0.5; renderer also writes -webkit-clip-path
|
|
55
56
|
- **Motion Path**: path: { target, align, start, end, rotate }
|
|
56
57
|
- **Custom Cursors**: type: basic/text/media; mp-cursor-text and mp-cursor-media HTML attributes
|
|
57
58
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motion.page/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "High-performance CSS animation SDK with scroll, hover, gesture, and cursor triggers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
|
-
"llms.txt"
|
|
18
|
+
"llms.txt",
|
|
19
|
+
"!dist/**/*.map"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
21
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json && bun build src/index.ts --outdir dist --minify --sourcemap=
|
|
22
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && bun build src/index.ts --outdir dist --minify --sourcemap=external && mkdir -p dist/.cjs-tmp && bun build src/index.ts --outdir dist/.cjs-tmp --format=cjs --minify --sourcemap=external && mv dist/.cjs-tmp/index.js dist/index.cjs && mv dist/.cjs-tmp/index.js.map dist/index.cjs.map && rm -rf dist/.cjs-tmp",
|
|
22
23
|
"test": "bun test",
|
|
23
24
|
"test:parity": "bun test tests/parity",
|
|
24
25
|
"test:bench": "bun test --bench",
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"@types/jsdom": "^27.0.0",
|
|
31
32
|
"esbuild": "^0.27.2",
|
|
32
33
|
"jsdom": "^27.3.0",
|
|
33
|
-
"typescript": "^
|
|
34
|
+
"typescript": "^6.0.3"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
|
36
37
|
"animation",
|