@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.
@@ -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 { AnimationTarget, StaggerVars, SplitType } from '../types';
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: HTMLElement | null;
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: HTMLElement | null, viewportHeight: number): void;
46
+ update(scrollTop: number, triggerElement: Element | null, viewportHeight: number): void;
47
47
  /**
48
48
  * Recache element positions after layout changes (resize, refresh).
49
49
  */
@@ -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
  }
@@ -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.0.8",
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=linked && mkdir -p dist/.cjs-tmp && bun build src/index.ts --outdir dist/.cjs-tmp --format=cjs --minify --sourcemap=linked && 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
+ "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": "^5.3.0"
34
+ "typescript": "^6.0.3"
34
35
  },
35
36
  "keywords": [
36
37
  "animation",