@mks2508/waapi-animation-primitives 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +296 -72
- package/dist/index.cjs +49 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +207 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +1692 -401
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +1692 -401
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -63
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,85 +1,1448 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import React from
|
|
1
|
+
import * as react0 from "react";
|
|
2
|
+
import React$1, { ElementType, ReactNode, RefObject } from "react";
|
|
3
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
4
|
|
|
5
|
+
//#region src/styles/injectStyles.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Inyecta las CSS variables en el documento.
|
|
8
|
+
* Se llama automáticamente al importar el package.
|
|
9
|
+
* Es idempotente - solo inyecta una vez.
|
|
10
|
+
*/
|
|
11
|
+
declare const injectCSSVariables: () => void;
|
|
12
|
+
/**
|
|
13
|
+
* Remueve las CSS variables inyectadas.
|
|
14
|
+
* Útil para cleanup en tests o hot reload.
|
|
15
|
+
*/
|
|
16
|
+
declare const removeCSSVariables: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Fuerza la re-inyección de CSS variables.
|
|
19
|
+
* Útil cuando cambian los valores dinámicamente.
|
|
20
|
+
*/
|
|
21
|
+
declare const reinjectCSSVariables: () => void;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/components/SlidingNumber.d.ts
|
|
4
24
|
interface FormatOptions {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
25
|
+
style?: "decimal" | "currency" | "percent";
|
|
26
|
+
currency?: string;
|
|
27
|
+
locale?: string;
|
|
28
|
+
minimumFractionDigits?: number;
|
|
29
|
+
maximumFractionDigits?: number;
|
|
30
|
+
useGrouping?: boolean;
|
|
11
31
|
}
|
|
12
32
|
interface SlidingNumberProps {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
declare function SlidingNumber({
|
|
30
|
-
|
|
33
|
+
value: number;
|
|
34
|
+
duration?: number;
|
|
35
|
+
fontSize?: string;
|
|
36
|
+
fontWeight?: string;
|
|
37
|
+
color?: string;
|
|
38
|
+
digitHeight?: number;
|
|
39
|
+
stagger?: number;
|
|
40
|
+
motionBlur?: boolean;
|
|
41
|
+
format?: FormatOptions;
|
|
42
|
+
trend?: -1 | 0 | 1;
|
|
43
|
+
animationConfig?: {
|
|
44
|
+
overshoot?: number;
|
|
45
|
+
mass?: number;
|
|
46
|
+
stiffness?: number;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
declare function SlidingNumber({
|
|
50
|
+
value,
|
|
51
|
+
duration,
|
|
52
|
+
fontSize,
|
|
53
|
+
fontWeight,
|
|
54
|
+
color,
|
|
55
|
+
digitHeight,
|
|
56
|
+
stagger,
|
|
57
|
+
motionBlur,
|
|
58
|
+
format,
|
|
59
|
+
trend,
|
|
60
|
+
animationConfig
|
|
61
|
+
}: SlidingNumberProps): react_jsx_runtime0.JSX.Element;
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/components/SlidingText.d.ts
|
|
31
64
|
interface SlidingTextProps {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
declare const SlidingText: React.FC<SlidingTextProps>;
|
|
48
|
-
|
|
65
|
+
text: string;
|
|
66
|
+
mode?: 'word' | 'character' | 'none';
|
|
67
|
+
direction?: 'vertical' | 'horizontal';
|
|
68
|
+
staggerDelay?: number;
|
|
69
|
+
duration?: number;
|
|
70
|
+
easing?: string;
|
|
71
|
+
blur?: boolean;
|
|
72
|
+
widthAnimation?: boolean;
|
|
73
|
+
initial?: 'initial' | false;
|
|
74
|
+
animate?: 'animate';
|
|
75
|
+
exit?: 'exit';
|
|
76
|
+
onAnimationComplete?: () => void;
|
|
77
|
+
className?: string;
|
|
78
|
+
style?: React$1.CSSProperties;
|
|
79
|
+
}
|
|
80
|
+
declare const SlidingText: React$1.FC<SlidingTextProps>;
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/components/AnimatedTokens.d.ts
|
|
49
83
|
interface Token {
|
|
50
|
-
|
|
51
|
-
|
|
84
|
+
id: string;
|
|
85
|
+
text: string;
|
|
52
86
|
}
|
|
53
87
|
interface AnimatedTokensProps {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
declare const AnimatedTokens: React.FC<AnimatedTokensProps>;
|
|
68
|
-
|
|
88
|
+
tokens: Token[];
|
|
89
|
+
placeholder?: string;
|
|
90
|
+
maxVisible?: number;
|
|
91
|
+
textAnimationMode?: 'character' | 'word';
|
|
92
|
+
textDirection?: 'vertical' | 'horizontal';
|
|
93
|
+
textStaggerDelay?: number;
|
|
94
|
+
separator?: string;
|
|
95
|
+
enableWidthAnimation?: boolean;
|
|
96
|
+
className?: string;
|
|
97
|
+
tokenClassName?: string;
|
|
98
|
+
placeholderClassName?: string;
|
|
99
|
+
separatorClassName?: string;
|
|
100
|
+
}
|
|
101
|
+
declare const AnimatedTokens: React$1.FC<AnimatedTokensProps>;
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/hooks/useListFormat.d.ts
|
|
104
|
+
type ListFormatType = 'conjunction' | 'disjunction' | 'unit';
|
|
105
|
+
type ListFormatStyle = 'long' | 'short' | 'narrow';
|
|
106
|
+
interface IntlListFormatPart {
|
|
107
|
+
type: 'element' | 'literal';
|
|
108
|
+
value: string;
|
|
109
|
+
}
|
|
110
|
+
interface IntlListFormatOptions {
|
|
111
|
+
type?: ListFormatType;
|
|
112
|
+
style?: ListFormatStyle;
|
|
113
|
+
}
|
|
114
|
+
interface IntlListFormat {
|
|
115
|
+
format(list: string[]): string;
|
|
116
|
+
formatToParts(list: string[]): IntlListFormatPart[];
|
|
117
|
+
}
|
|
118
|
+
interface IntlListFormatConstructor {
|
|
119
|
+
new (locale?: string | string[], options?: IntlListFormatOptions): IntlListFormat;
|
|
120
|
+
}
|
|
121
|
+
declare global {
|
|
122
|
+
namespace Intl {
|
|
123
|
+
const ListFormat: IntlListFormatConstructor;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
interface UseListFormatOptions {
|
|
127
|
+
locale?: string;
|
|
128
|
+
type?: ListFormatType;
|
|
129
|
+
style?: ListFormatStyle;
|
|
130
|
+
separator?: string;
|
|
131
|
+
}
|
|
132
|
+
interface ListPart {
|
|
133
|
+
type: 'element' | 'literal';
|
|
134
|
+
value: string;
|
|
135
|
+
index: number;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Hook for locale-aware list formatting using Intl.ListFormat
|
|
139
|
+
*
|
|
140
|
+
* Provides parts that can be rendered individually with animations.
|
|
141
|
+
* Uses browser's Intl.ListFormat API for proper locale handling.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```tsx
|
|
145
|
+
* // Automatic locale detection
|
|
146
|
+
* const parts = useListFormat(['Apple', 'Banana', 'Cherry']);
|
|
147
|
+
* // en: [{ type: 'element', value: 'Apple' }, { type: 'literal', value: ', ' }, ...]
|
|
148
|
+
*
|
|
149
|
+
* // Spanish
|
|
150
|
+
* const parts = useListFormat(['Apple', 'Banana', 'Cherry'], { locale: 'es' });
|
|
151
|
+
* // es: [..., { type: 'literal', value: ' y ' }, { type: 'element', value: 'Cherry' }]
|
|
152
|
+
*
|
|
153
|
+
* // Disjunction (or)
|
|
154
|
+
* const parts = useListFormat(['A', 'B', 'C'], { type: 'disjunction' });
|
|
155
|
+
* // en: "A, B, or C"
|
|
156
|
+
*
|
|
157
|
+
* // Manual override
|
|
158
|
+
* const parts = useListFormat(['A', 'B', 'C'], { separator: ' | ' });
|
|
159
|
+
* // "A | B | C"
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
declare function useListFormat(items: string[], options?: UseListFormatOptions): ListPart[];
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/components/AnimatedTokensV2.d.ts
|
|
165
|
+
interface Token$1 {
|
|
166
|
+
id: string;
|
|
167
|
+
text: string;
|
|
168
|
+
}
|
|
169
|
+
interface AnimatedTokensV2Props {
|
|
170
|
+
tokens: Token$1[];
|
|
171
|
+
placeholder?: string;
|
|
172
|
+
maxVisible?: number;
|
|
173
|
+
textAnimationMode?: 'character' | 'word';
|
|
174
|
+
textDirection?: 'vertical' | 'horizontal';
|
|
175
|
+
textStaggerDelay?: number;
|
|
176
|
+
locale?: string;
|
|
177
|
+
listType?: ListFormatType;
|
|
178
|
+
listStyle?: ListFormatStyle;
|
|
179
|
+
separator?: string;
|
|
180
|
+
enableWidthAnimation?: boolean;
|
|
181
|
+
className?: string;
|
|
182
|
+
tokenClassName?: string;
|
|
183
|
+
placeholderClassName?: string;
|
|
184
|
+
separatorClassName?: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* AnimatedTokensV2 - Locale-aware animated token list component
|
|
188
|
+
*
|
|
189
|
+
* Built on the Reorder primitive, provides smooth FLIP animations for token lists
|
|
190
|
+
* with proper locale-aware separators using Intl.ListFormat.
|
|
191
|
+
*
|
|
192
|
+
* ## Features
|
|
193
|
+
*
|
|
194
|
+
* - **Locale-aware separators**: Uses `Intl.ListFormat` for proper localization
|
|
195
|
+
* - **Smooth FLIP animations**: Coordinated enter/exit transitions
|
|
196
|
+
* - **Separator coordination**: Animates separators when tokens are removed
|
|
197
|
+
* - **Overflow handling**: Shows "+N more" when tokens exceed `maxVisible`
|
|
198
|
+
* - **Text animation**: Each token's text animates character-by-character
|
|
199
|
+
*
|
|
200
|
+
* ## Locale Support
|
|
201
|
+
*
|
|
202
|
+
* By default, uses the browser's locale. Supports:
|
|
203
|
+
* - `conjunction`: "A, B, and C" (default)
|
|
204
|
+
* - `disjunction`: "A, B, or C"
|
|
205
|
+
* - `unit`: "A B C" (space-separated)
|
|
206
|
+
*
|
|
207
|
+
* ## Examples
|
|
208
|
+
*
|
|
209
|
+
* ### Basic usage
|
|
210
|
+
* ```tsx
|
|
211
|
+
* import { AnimatedTokensV2 } from '@mks2508/waapi-animation-primitives';
|
|
212
|
+
*
|
|
213
|
+
* const tags = [
|
|
214
|
+
* { id: '1', text: 'React' },
|
|
215
|
+
* { id: '2', text: 'TypeScript' },
|
|
216
|
+
* { id: '3', text: 'WAAPI' }
|
|
217
|
+
* ];
|
|
218
|
+
*
|
|
219
|
+
* <AnimatedTokensV2 tokens={tags} />
|
|
220
|
+
* ```
|
|
221
|
+
*
|
|
222
|
+
* ### Locale-aware separators
|
|
223
|
+
* ```tsx
|
|
224
|
+
* // en-US: "React, TypeScript, and WAAPI"
|
|
225
|
+
* // es-ES: "React, TypeScript y WAAPI"
|
|
226
|
+
* <AnimatedTokensV2 tokens={tags} locale="es" listStyle="long" />
|
|
227
|
+
* ```
|
|
228
|
+
*
|
|
229
|
+
* ### Disjunction (or)
|
|
230
|
+
* ```tsx
|
|
231
|
+
* // "React, TypeScript, or WAAPI"
|
|
232
|
+
* <AnimatedTokensV2 tokens={tags} listType="disjunction" />
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* ### Manual separator override
|
|
236
|
+
* ```tsx
|
|
237
|
+
* // "React | TypeScript | WAAPI"
|
|
238
|
+
* <AnimatedTokensV2 tokens={tags} separator=" | " />
|
|
239
|
+
* ```
|
|
240
|
+
*
|
|
241
|
+
* ### With overflow
|
|
242
|
+
* ```tsx
|
|
243
|
+
* const tags = [
|
|
244
|
+
* { id: '1', text: 'React' },
|
|
245
|
+
* { id: '2', text: 'Vue' },
|
|
246
|
+
* { id: '3', text: 'Svelte' },
|
|
247
|
+
* { id: '4', text: 'Angular' },
|
|
248
|
+
* { id: '5', text: 'Solid' }
|
|
249
|
+
* ];
|
|
250
|
+
*
|
|
251
|
+
* // Shows: "React, Vue, Svelte + 2 more"
|
|
252
|
+
* <AnimatedTokensV2 tokens={tags} maxVisible={3} />
|
|
253
|
+
* ```
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```tsx
|
|
257
|
+
* import { AnimatedTokensV2 } from '@mks2508/waapi-animation-primitives';
|
|
258
|
+
*
|
|
259
|
+
* function TagList({ tags }) {
|
|
260
|
+
* return (
|
|
261
|
+
* <AnimatedTokensV2
|
|
262
|
+
* tokens={tags}
|
|
263
|
+
* locale="en-US"
|
|
264
|
+
* listType="conjunction"
|
|
265
|
+
* maxVisible={5}
|
|
266
|
+
* textAnimationMode="character"
|
|
267
|
+
* textDirection="vertical"
|
|
268
|
+
* enableWidthAnimation={true}
|
|
269
|
+
* tokenClassName="text-lg font-medium"
|
|
270
|
+
* />
|
|
271
|
+
* );
|
|
272
|
+
* }
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @alias TextFlow
|
|
276
|
+
*/
|
|
277
|
+
declare const AnimatedTokensV2: React.FC<AnimatedTokensV2Props>;
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/hooks/useWAAPIAnimations.d.ts
|
|
280
|
+
interface SeparatorState {
|
|
281
|
+
tokenId: string;
|
|
282
|
+
isVisible: boolean;
|
|
283
|
+
isAnimating: boolean;
|
|
284
|
+
animationPhase: 'idle' | 'exit-coordinated' | 'flip-coordinated' | 'completed';
|
|
285
|
+
startTime?: number;
|
|
286
|
+
expectedEndTime?: number;
|
|
287
|
+
}
|
|
69
288
|
interface AnimationConfig {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
289
|
+
onComplete: (id: string) => void;
|
|
290
|
+
exitDuration?: number;
|
|
291
|
+
flipDuration?: number;
|
|
292
|
+
exitEasing?: string;
|
|
293
|
+
flipEasing?: string;
|
|
75
294
|
}
|
|
76
295
|
declare const useWAAPIAnimations: (config: AnimationConfig) => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
296
|
+
registerElement: (id: string, el: HTMLElement | null) => void;
|
|
297
|
+
startExit: (id: string, additionalSeparatorIds?: string[]) => Promise<void>;
|
|
298
|
+
isAnimating: (id?: string) => boolean;
|
|
299
|
+
cancelAnimations: (id: string) => void;
|
|
300
|
+
registerSeparator: (tokenId: string, el: HTMLElement | null) => void;
|
|
301
|
+
getSeparatorState: (tokenId: string) => SeparatorState | undefined;
|
|
302
|
+
startSeparatorAnimation: (tokenId: string) => Promise<void>;
|
|
303
|
+
cleanupSeparatorStates: (visibleTokenIds: Set<string>) => void;
|
|
81
304
|
};
|
|
82
|
-
|
|
305
|
+
//#endregion
|
|
306
|
+
//#region src/contexts/DebugContext.d.ts
|
|
307
|
+
interface TimingData {
|
|
308
|
+
startTime: number;
|
|
309
|
+
endTime?: number;
|
|
310
|
+
expectedDuration: number;
|
|
311
|
+
actualDuration?: number;
|
|
312
|
+
deviation?: number;
|
|
313
|
+
deviationPercent?: number;
|
|
314
|
+
}
|
|
315
|
+
interface StyleData {
|
|
316
|
+
property: string;
|
|
317
|
+
expected: string;
|
|
318
|
+
actual: string;
|
|
319
|
+
matches: boolean;
|
|
320
|
+
}
|
|
321
|
+
interface PositionData {
|
|
322
|
+
element: string;
|
|
323
|
+
x: number;
|
|
324
|
+
y: number;
|
|
325
|
+
width: number;
|
|
326
|
+
height: number;
|
|
327
|
+
delta?: {
|
|
328
|
+
x: number;
|
|
329
|
+
y: number;
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
interface AnimationData {
|
|
333
|
+
name: string;
|
|
334
|
+
phase: 'start' | 'running' | 'complete' | 'cancelled';
|
|
335
|
+
progress?: number;
|
|
336
|
+
easing?: string;
|
|
337
|
+
fill?: string;
|
|
338
|
+
}
|
|
339
|
+
type DebugEventType = 'token-add' | 'token-remove' | 'token-reorder' | 'token-exit-start' | 'token-exit-complete' | 'token-dom-remove' | 'overflow-token-remove' | 'flip-animation' | 'flip-animation-complete' | 'flip-all-animations-complete' | 'flip-executing-callback' | 'flip-measure-start' | 'flip-position-measured' | 'flip-invalid-rect' | 'flip-invalid-delta' | 'flip-manual-trigger' | 'flip-capture-positions' | 'flip-position-captured' | 'flip-skipped' | 'waapi-exit-start' | 'waapi-exit-complete' | 'waapi-flip-animation' | 'exit-fade-complete' | 'orchestration-complete' | 'animation-start-detailed' | 'animation-complete-detailed' | 'animation-timing' | 'style-capture' | 'style-mismatch' | 'position-capture' | 'position-delta' | 'choreography-overlap' | 'choreography-sequence' | 'text-enter-start' | 'text-enter-complete' | 'reorder-item-enter' | 'reorder-item-exit' | 'reorder-item-exit-complete' | 'reorder-flip-start' | 'reorder-flip-complete' | 'reorder-flip-before-capture' | 'reorder-flip-after-capture' | 'reorder-flip-after-positions' | 'reorder-flip-after-precaptured' | 'reorder-flip-delta' | 'reorder-flip-reflow-trigger' | 'reorder-flip-skipped' | 'reorder-flip-filter' | 'reorder-stagger-start' | 'reorder-ghost-created' | 'reorder-ghost-removed' | 'reorder-register-element' | 'reorder-animation-start' | 'reorder-animation-complete' | 'reorder-animation-setup' | 'reorder-animation-created' | 'reorder-animation-init' | 'reorder-animation-error' | 'reorder-exit-check' | 'reorder-exit-rejected' | 'reorder-reflow-triggered' | 'reorder-transform-applied' | 'reorder-display-none' | 'reorder-position-absolute' | 'reorder-after-immediate' | 'reorder-exit-cleanup' | 'reorder-await-start' | 'reorder-await-complete' | 'reorder-enter-start' | 'reorder-enter-complete' | 'separator-animation-start' | 'separator-animation-state-only' | 'separator-animation-skipped' | 'separator-flip-start' | 'separator-animation-complete' | 'separator-state-cleanup' | 'test-suite-start' | 'test-suite-complete' | 'test-suite-error' | 'test-suite-stopped' | 'test-start' | 'test-complete' | 'test-error' | 'test-progress' | 'test-flip-capture' | 'test-export' | 'test-manual-remove' | 'triggering-flip-before-absolute' | 'state-change' | 'render' | 'animation-complete-called' | 'scheduling-raf' | 'raf-executed' | 'component-unmounted' | 'token-removing-from-layout' | 'exit-completed-ids-updated' | 'exit-completed-change' | 'registering-callback' | 'callback-fired';
|
|
340
|
+
interface DebugEvent {
|
|
341
|
+
timestamp: number;
|
|
342
|
+
perfNow?: number;
|
|
343
|
+
type: DebugEventType;
|
|
344
|
+
source: string;
|
|
345
|
+
message: string;
|
|
346
|
+
timing?: TimingData;
|
|
347
|
+
styles?: StyleData[];
|
|
348
|
+
position?: PositionData;
|
|
349
|
+
animation?: AnimationData;
|
|
350
|
+
data?: Record<string, unknown>;
|
|
351
|
+
}
|
|
352
|
+
interface DebugContextValue {
|
|
353
|
+
events: DebugEvent[];
|
|
354
|
+
isEnabled: boolean;
|
|
355
|
+
enableDebug: () => void;
|
|
356
|
+
disableDebug: () => void;
|
|
357
|
+
toggleDebug: () => void;
|
|
358
|
+
logEvent: (event: Omit<DebugEvent, 'timestamp' | 'perfNow'>) => void;
|
|
359
|
+
clearEvents: () => void;
|
|
360
|
+
getEventLog: () => string;
|
|
361
|
+
exportToCSV: () => string;
|
|
362
|
+
startCollecting: () => void;
|
|
363
|
+
stopCollecting: () => DebugEvent[];
|
|
364
|
+
isCollecting: boolean;
|
|
365
|
+
flushEvents: () => void;
|
|
366
|
+
}
|
|
367
|
+
declare const useDebug: () => DebugContextValue;
|
|
368
|
+
declare const DebugProvider: React$1.FC<{
|
|
369
|
+
children: React$1.ReactNode;
|
|
370
|
+
}>;
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/utils/choreographyTracker.d.ts
|
|
373
|
+
interface AnimationInfo {
|
|
374
|
+
id: string;
|
|
375
|
+
type: 'exit-fade' | 'exit-collapse' | 'flip' | 'enter' | 'width-collapse' | 'separator-exit';
|
|
376
|
+
elementId: string;
|
|
377
|
+
startTime: number;
|
|
378
|
+
expectedDuration: number;
|
|
379
|
+
endTime?: number;
|
|
380
|
+
actualDuration?: number;
|
|
381
|
+
}
|
|
382
|
+
interface TimelineEvent {
|
|
383
|
+
time: number;
|
|
384
|
+
event: 'animation-start' | 'animation-end' | 'overlap-detected';
|
|
385
|
+
animationId: string;
|
|
386
|
+
type?: string;
|
|
387
|
+
overlappingWith?: string[];
|
|
388
|
+
expectedDuration?: number;
|
|
389
|
+
actualDuration?: number;
|
|
390
|
+
deviation?: number;
|
|
391
|
+
}
|
|
392
|
+
interface OverlapInfo {
|
|
393
|
+
animation1: string;
|
|
394
|
+
animation2: string;
|
|
395
|
+
overlapStart: number;
|
|
396
|
+
overlapDuration: number;
|
|
397
|
+
}
|
|
398
|
+
interface ChoreographySummary {
|
|
399
|
+
totalAnimations: number;
|
|
400
|
+
totalDuration: number;
|
|
401
|
+
overlaps: OverlapInfo[];
|
|
402
|
+
timeline: TimelineEvent[];
|
|
403
|
+
activeAnimations: AnimationInfo[];
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* ChoreographyTracker - Singleton for tracking animation choreography
|
|
407
|
+
* Detects overlaps, generates timeline, measures actual vs expected timing
|
|
408
|
+
*/
|
|
409
|
+
declare class ChoreographyTrackerClass {
|
|
410
|
+
private activeAnimations;
|
|
411
|
+
private timeline;
|
|
412
|
+
private completedAnimations;
|
|
413
|
+
private sessionStartTime;
|
|
414
|
+
/**
|
|
415
|
+
* Start a new tracking session (call when debug panel is cleared)
|
|
416
|
+
*/
|
|
417
|
+
startSession(): void;
|
|
418
|
+
/**
|
|
419
|
+
* Get relative time since session start
|
|
420
|
+
*/
|
|
421
|
+
private getRelativeTime;
|
|
422
|
+
/**
|
|
423
|
+
* Start tracking an animation
|
|
424
|
+
*/
|
|
425
|
+
startAnimation(id: string, type: AnimationInfo['type'], elementId: string, expectedDuration: number): void;
|
|
426
|
+
/**
|
|
427
|
+
* End tracking an animation
|
|
428
|
+
*/
|
|
429
|
+
endAnimation(id: string): AnimationInfo | undefined;
|
|
430
|
+
/**
|
|
431
|
+
* Detect which animations are overlapping with the given animation
|
|
432
|
+
*/
|
|
433
|
+
private detectOverlaps;
|
|
434
|
+
/**
|
|
435
|
+
* Get all overlap pairs with duration
|
|
436
|
+
*/
|
|
437
|
+
getOverlaps(): OverlapInfo[];
|
|
438
|
+
/**
|
|
439
|
+
* Get current timeline
|
|
440
|
+
*/
|
|
441
|
+
getTimeline(): TimelineEvent[];
|
|
442
|
+
/**
|
|
443
|
+
* Get active animation count
|
|
444
|
+
*/
|
|
445
|
+
getActiveCount(): number;
|
|
446
|
+
/**
|
|
447
|
+
* Get active animations
|
|
448
|
+
*/
|
|
449
|
+
getActiveAnimations(): AnimationInfo[];
|
|
450
|
+
/**
|
|
451
|
+
* Get completed animations
|
|
452
|
+
*/
|
|
453
|
+
getCompletedAnimations(): AnimationInfo[];
|
|
454
|
+
/**
|
|
455
|
+
* Get full choreography summary
|
|
456
|
+
*/
|
|
457
|
+
getSummary(): ChoreographySummary;
|
|
458
|
+
/**
|
|
459
|
+
* Get timeline for visualization (normalized to 0-100%)
|
|
460
|
+
*/
|
|
461
|
+
getTimelineForVisualization(): Array<{
|
|
462
|
+
id: string;
|
|
463
|
+
type: string;
|
|
464
|
+
elementId: string;
|
|
465
|
+
startPercent: number;
|
|
466
|
+
widthPercent: number;
|
|
467
|
+
duration: number;
|
|
468
|
+
isActive: boolean;
|
|
469
|
+
}>;
|
|
470
|
+
}
|
|
471
|
+
declare const choreographyTracker: ChoreographyTrackerClass;
|
|
472
|
+
//#endregion
|
|
473
|
+
//#region src/core/types.d.ts
|
|
474
|
+
/**
|
|
475
|
+
* Core types for headless animation primitives
|
|
476
|
+
* Based on WAAPI (Web Animations API) patterns
|
|
477
|
+
*/
|
|
478
|
+
interface FLIPDelta {
|
|
479
|
+
id: string;
|
|
480
|
+
deltaX: number;
|
|
481
|
+
deltaY: number;
|
|
482
|
+
deltaWidth: number;
|
|
483
|
+
deltaHeight: number;
|
|
484
|
+
isSignificant: boolean;
|
|
485
|
+
}
|
|
486
|
+
interface AnimationTiming {
|
|
487
|
+
duration: number;
|
|
488
|
+
delay?: number;
|
|
489
|
+
easing: string;
|
|
490
|
+
fill?: FillMode;
|
|
491
|
+
}
|
|
492
|
+
interface PositionRect {
|
|
493
|
+
x: number;
|
|
494
|
+
y: number;
|
|
495
|
+
width: number;
|
|
496
|
+
height: number;
|
|
497
|
+
}
|
|
498
|
+
interface ElementRegistryAPI {
|
|
499
|
+
register: (id: string, el: HTMLElement | null) => void;
|
|
500
|
+
unregister: (id: string) => void;
|
|
501
|
+
get: (id: string) => HTMLElement | undefined;
|
|
502
|
+
getAll: () => Map<string, HTMLElement>;
|
|
503
|
+
has: (id: string) => boolean;
|
|
504
|
+
clear: () => void;
|
|
505
|
+
size: number;
|
|
506
|
+
}
|
|
507
|
+
interface ElementRegistryCallbacks {
|
|
508
|
+
onRegister?: (id: string, el: HTMLElement) => void;
|
|
509
|
+
onUnregister?: (id: string) => void;
|
|
510
|
+
}
|
|
511
|
+
interface PositionCaptureAPI {
|
|
512
|
+
capture: (excludeIds?: Set<string>) => Map<string, DOMRect>;
|
|
513
|
+
getPosition: (id: string) => DOMRect | undefined;
|
|
514
|
+
calculateDeltas: (before: Map<string, DOMRect>, after: Map<string, DOMRect>) => Map<string, FLIPDelta>;
|
|
515
|
+
getLastCapture: () => Map<string, DOMRect>;
|
|
516
|
+
clear: () => void;
|
|
517
|
+
}
|
|
518
|
+
interface PositionCaptureOptions {
|
|
519
|
+
minDeltaPx?: number;
|
|
520
|
+
}
|
|
521
|
+
interface FLIPAnimationOptions {
|
|
522
|
+
duration?: number;
|
|
523
|
+
easing?: string;
|
|
524
|
+
onStart?: (id: string) => void;
|
|
525
|
+
onComplete?: (id: string) => void;
|
|
526
|
+
}
|
|
527
|
+
interface FLIPAnimationAPI {
|
|
528
|
+
animate: (element: HTMLElement, delta: FLIPDelta, options?: FLIPAnimationOptions) => Animation;
|
|
529
|
+
animateAll: (elements: Map<string, HTMLElement>, deltas: Map<string, FLIPDelta>, options?: FLIPAnimationOptions) => Promise<void>;
|
|
530
|
+
cancel: (id: string) => void;
|
|
531
|
+
cancelAll: () => void;
|
|
532
|
+
isAnimating: (id?: string) => boolean;
|
|
533
|
+
}
|
|
534
|
+
interface ExitOptions {
|
|
535
|
+
duration?: number;
|
|
536
|
+
easing?: string;
|
|
537
|
+
collapseWidth?: boolean;
|
|
538
|
+
additionalIds?: string[];
|
|
539
|
+
onComplete?: () => void;
|
|
540
|
+
}
|
|
541
|
+
interface EnterOptions {
|
|
542
|
+
duration?: number;
|
|
543
|
+
easing?: string;
|
|
544
|
+
stagger?: number;
|
|
545
|
+
onComplete?: () => void;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Controls which elements animate when an item exits
|
|
549
|
+
* - 'all': All remaining elements animate to fill the gap (default)
|
|
550
|
+
* - 'siblings-after': Only elements after the exiting one animate
|
|
551
|
+
* - 'none': No FLIP animation, item exits in-place
|
|
552
|
+
*/
|
|
553
|
+
type FLIPBehavior = 'all' | 'siblings-after' | 'none';
|
|
554
|
+
/**
|
|
555
|
+
* Controls how the exiting element is positioned during exit animation
|
|
556
|
+
* - 'absolute-fixed': Position absolute with fixed coordinates (current default)
|
|
557
|
+
* - 'in-place': Stay in flow, no position change
|
|
558
|
+
* - 'custom': Consumer handles positioning via CSS/callbacks
|
|
559
|
+
*/
|
|
560
|
+
type ExitPositionStrategy = 'absolute-fixed' | 'in-place' | 'custom';
|
|
561
|
+
interface AnimationOrchestratorConfig {
|
|
562
|
+
exitDuration?: number;
|
|
563
|
+
flipDuration?: number;
|
|
564
|
+
enterDuration?: number;
|
|
565
|
+
exitEasing?: string;
|
|
566
|
+
flipEasing?: string;
|
|
567
|
+
enterEasing?: string;
|
|
568
|
+
flipBehavior?: FLIPBehavior;
|
|
569
|
+
exitPositionStrategy?: ExitPositionStrategy;
|
|
570
|
+
minDeltaPx?: number;
|
|
571
|
+
onExitComplete?: (id: string) => void;
|
|
572
|
+
onEnterComplete?: (id: string) => void;
|
|
573
|
+
}
|
|
574
|
+
interface AnimationOrchestratorAPI {
|
|
575
|
+
registry: ElementRegistryAPI;
|
|
576
|
+
positions: PositionCaptureAPI;
|
|
577
|
+
flip: FLIPAnimationAPI;
|
|
578
|
+
registerElement: (id: string, el: HTMLElement | null) => void;
|
|
579
|
+
startExit: (id: string, options?: ExitOptions) => Promise<void>;
|
|
580
|
+
startEnter: (id: string, options?: EnterOptions) => Promise<void>;
|
|
581
|
+
isAnimating: (id?: string) => boolean;
|
|
582
|
+
cancelAnimation: (id: string) => void;
|
|
583
|
+
cancelAllAnimations: () => void;
|
|
584
|
+
capturePositions: (excludeIds?: Set<string>) => Map<string, DOMRect>;
|
|
585
|
+
}
|
|
586
|
+
interface OrchestratorState {
|
|
587
|
+
animatingIds: Set<string>;
|
|
588
|
+
positions: Map<string, DOMRect>;
|
|
589
|
+
activeAnimations: Map<string, Animation[]>;
|
|
590
|
+
}
|
|
591
|
+
type AnimationPhase = 'idle' | 'exit' | 'flip' | 'enter' | 'completed';
|
|
592
|
+
interface AnimationEvent {
|
|
593
|
+
id: string;
|
|
594
|
+
phase: AnimationPhase;
|
|
595
|
+
timestamp: number;
|
|
596
|
+
duration?: number;
|
|
597
|
+
}
|
|
598
|
+
//#endregion
|
|
599
|
+
//#region src/core/useElementRegistry.d.ts
|
|
600
|
+
/**
|
|
601
|
+
* Hook for tracking DOM elements by ID
|
|
602
|
+
* Extracted from useWAAPIAnimations element registration logic
|
|
603
|
+
*
|
|
604
|
+
* @example
|
|
605
|
+
* ```tsx
|
|
606
|
+
* const registry = useElementRegistry({
|
|
607
|
+
* onRegister: (id) => console.log(`Registered: ${id}`),
|
|
608
|
+
* onUnregister: (id) => console.log(`Unregistered: ${id}`)
|
|
609
|
+
* });
|
|
610
|
+
*
|
|
611
|
+
* // In render:
|
|
612
|
+
* <div ref={el => registry.register('item-1', el)} />
|
|
613
|
+
* ```
|
|
614
|
+
*/
|
|
615
|
+
declare function useElementRegistry(callbacks?: ElementRegistryCallbacks): ElementRegistryAPI;
|
|
616
|
+
//#endregion
|
|
617
|
+
//#region src/core/usePositionCapture.d.ts
|
|
618
|
+
/**
|
|
619
|
+
* Hook for capturing element positions and calculating FLIP deltas
|
|
620
|
+
* Extracted from useWAAPIAnimations position capture logic
|
|
621
|
+
*
|
|
622
|
+
* @example
|
|
623
|
+
* ```tsx
|
|
624
|
+
* const registry = useElementRegistry();
|
|
625
|
+
* const positions = usePositionCapture(registry.getAll);
|
|
626
|
+
*
|
|
627
|
+
* // Before layout change:
|
|
628
|
+
* const before = positions.capture();
|
|
629
|
+
*
|
|
630
|
+
* // After layout change:
|
|
631
|
+
* const after = positions.capture();
|
|
632
|
+
* const deltas = positions.calculateDeltas(before, after);
|
|
633
|
+
* ```
|
|
634
|
+
*/
|
|
635
|
+
declare function usePositionCapture(getElements: () => Map<string, HTMLElement>, options?: PositionCaptureOptions): PositionCaptureAPI;
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region src/core/useFLIPAnimation.d.ts
|
|
638
|
+
/**
|
|
639
|
+
* Hook for executing FLIP (First-Last-Invert-Play) animations
|
|
640
|
+
* Extracted from useWAAPIAnimations FLIP logic
|
|
641
|
+
*
|
|
642
|
+
* Uses spring easing for natural motion with slight overshoot
|
|
643
|
+
*
|
|
644
|
+
* @example
|
|
645
|
+
* ```tsx
|
|
646
|
+
* const flip = useFLIPAnimation();
|
|
647
|
+
*
|
|
648
|
+
* // After calculating deltas:
|
|
649
|
+
* await flip.animateAll(elements, deltas, {
|
|
650
|
+
* duration: 300,
|
|
651
|
+
* onComplete: (id) => console.log(`${id} completed`)
|
|
652
|
+
* });
|
|
653
|
+
* ```
|
|
654
|
+
*/
|
|
655
|
+
declare function useFLIPAnimation(): FLIPAnimationAPI;
|
|
656
|
+
//#endregion
|
|
657
|
+
//#region src/core/useAnimationOrchestrator.d.ts
|
|
658
|
+
/**
|
|
659
|
+
* Main animation orchestrator hook
|
|
660
|
+
* Composes useElementRegistry, usePositionCapture, and useFLIPAnimation
|
|
661
|
+
*
|
|
662
|
+
* Handles the full exit animation sequence:
|
|
663
|
+
* 1. Capture positions of remaining elements
|
|
664
|
+
* 2. Run exit animation (fade + width collapse)
|
|
665
|
+
* 3. Start FLIP animations at 25% of exit (overlap)
|
|
666
|
+
* 4. Cleanup and notify completion
|
|
667
|
+
*
|
|
668
|
+
* @example
|
|
669
|
+
* ```tsx
|
|
670
|
+
* const orchestrator = useAnimationOrchestrator({
|
|
671
|
+
* onExitComplete: (id) => removeFromList(id)
|
|
672
|
+
* });
|
|
673
|
+
*
|
|
674
|
+
* // Register elements:
|
|
675
|
+
* <div ref={el => orchestrator.registerElement('item-1', el)} />
|
|
676
|
+
*
|
|
677
|
+
* // Trigger exit:
|
|
678
|
+
* await orchestrator.startExit('item-1');
|
|
679
|
+
* ```
|
|
680
|
+
*/
|
|
681
|
+
declare function useAnimationOrchestrator(config?: AnimationOrchestratorConfig): AnimationOrchestratorAPI;
|
|
682
|
+
//#endregion
|
|
683
|
+
//#region src/primitives/reorder/types.d.ts
|
|
684
|
+
/**
|
|
685
|
+
* Layout direction for reorder items
|
|
686
|
+
*
|
|
687
|
+
* - `auto`: No layout applied (consumer handles positioning)
|
|
688
|
+
* - `horizontal`: Flexbox row layout with wrapping
|
|
689
|
+
* - `vertical`: Flexbox column layout
|
|
690
|
+
* - `grid`: CSS Grid with auto-fill columns
|
|
691
|
+
*
|
|
692
|
+
* @default 'auto'
|
|
693
|
+
*/
|
|
694
|
+
type ReorderLayout = 'auto' | 'horizontal' | 'vertical' | 'grid';
|
|
695
|
+
/**
|
|
696
|
+
* Stagger configuration for animations
|
|
697
|
+
*
|
|
698
|
+
* Can be a single number applied to both enter/exit, or separate values:
|
|
699
|
+
* - `number`: Same stagger delay for enter and exit (in ms per item index)
|
|
700
|
+
* - `{ enter, exit }`: Different stagger delays for enter vs exit
|
|
701
|
+
*
|
|
702
|
+
* @example
|
|
703
|
+
* ```tsx
|
|
704
|
+
* // 15ms stagger per item
|
|
705
|
+
* stagger={15}
|
|
706
|
+
*
|
|
707
|
+
* // Different stagger for enter/exit
|
|
708
|
+
* stagger={{ enter: 30, exit: 0 }}
|
|
709
|
+
* ```
|
|
710
|
+
*/
|
|
711
|
+
type StaggerConfig = number | {
|
|
712
|
+
enter: number;
|
|
713
|
+
exit: number;
|
|
714
|
+
};
|
|
715
|
+
/**
|
|
716
|
+
* Duration configuration for animations
|
|
717
|
+
*
|
|
718
|
+
* Can be a single number applied to both enter/exit, or separate values:
|
|
719
|
+
* - `number`: Same duration for enter and exit (in ms)
|
|
720
|
+
* - `{ enter, exit }`: Different durations for enter vs exit
|
|
721
|
+
*
|
|
722
|
+
* @example
|
|
723
|
+
* ```tsx
|
|
724
|
+
* // 300ms for both
|
|
725
|
+
* duration={300}
|
|
726
|
+
*
|
|
727
|
+
* // Different durations
|
|
728
|
+
* duration={{ enter: 400, exit: 200 }}
|
|
729
|
+
* ```
|
|
730
|
+
*/
|
|
731
|
+
type DurationConfig = number | {
|
|
732
|
+
enter: number;
|
|
733
|
+
exit: number;
|
|
734
|
+
};
|
|
735
|
+
/**
|
|
736
|
+
* Props for {@link Reorder} container component
|
|
737
|
+
*
|
|
738
|
+
* Reorder is an agnostic primitive for animated list reordering using FLIP technique.
|
|
739
|
+
* It automatically handles enter/exit animations while leaving layout to consumers.
|
|
740
|
+
*
|
|
741
|
+
* @example
|
|
742
|
+
* ```tsx
|
|
743
|
+
* import { Reorder } from '@mks2508/waapi-animation-primitives';
|
|
744
|
+
*
|
|
745
|
+
* function TodoList() {
|
|
746
|
+
* const [todos, setTodos] = useState([
|
|
747
|
+
* { id: '1', text: 'Buy milk' },
|
|
748
|
+
* { id: '2', text: 'Write code' }
|
|
749
|
+
* ]);
|
|
750
|
+
*
|
|
751
|
+
* const handleRemove = (id: string) => {
|
|
752
|
+
* setTodos(prev => prev.filter(t => t.id !== id));
|
|
753
|
+
* };
|
|
754
|
+
*
|
|
755
|
+
* return (
|
|
756
|
+
* <Reorder
|
|
757
|
+
* layout="horizontal"
|
|
758
|
+
* stagger={15}
|
|
759
|
+
* onItemExit={handleRemove}
|
|
760
|
+
* >
|
|
761
|
+
* {todos.map(todo => (
|
|
762
|
+
* <div key={todo.id}>{todo.text}</div>
|
|
763
|
+
* ))}
|
|
764
|
+
* </Reorder>
|
|
765
|
+
* );
|
|
766
|
+
* }
|
|
767
|
+
* ```
|
|
768
|
+
*/
|
|
769
|
+
interface ReorderProps {
|
|
770
|
+
/** Child elements to be animated. Each child should have a unique `key` prop. */
|
|
771
|
+
children: ReactNode;
|
|
772
|
+
/**
|
|
773
|
+
* Enable automatic enter animations for new children.
|
|
774
|
+
* When true, new children animate in automatically when added.
|
|
775
|
+
*
|
|
776
|
+
* @default true
|
|
777
|
+
*/
|
|
778
|
+
autoAnimate?: boolean;
|
|
779
|
+
/**
|
|
780
|
+
* Stagger delay between item animations.
|
|
781
|
+
* Can be a single number (ms) or separate enter/exit values.
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* ```tsx
|
|
785
|
+
* stagger={15} // 15ms per item index
|
|
786
|
+
* stagger={{ enter: 30, exit: 0 }} // Custom values
|
|
787
|
+
* ```
|
|
788
|
+
*/
|
|
789
|
+
stagger?: StaggerConfig;
|
|
790
|
+
/**
|
|
791
|
+
* Animation duration in milliseconds.
|
|
792
|
+
* Can be a single number or separate enter/exit values.
|
|
793
|
+
*
|
|
794
|
+
* @default 300 (enter), 200 (exit)
|
|
795
|
+
*/
|
|
796
|
+
duration?: DurationConfig;
|
|
797
|
+
/**
|
|
798
|
+
* Layout arrangement for child elements.
|
|
799
|
+
* Use 'auto' to handle positioning yourself.
|
|
800
|
+
*
|
|
801
|
+
* @default 'auto'
|
|
802
|
+
*/
|
|
803
|
+
layout?: ReorderLayout;
|
|
804
|
+
/** Additional CSS class name for the container. */
|
|
805
|
+
className?: string;
|
|
806
|
+
/**
|
|
807
|
+
* FLIP animation behavior strategy.
|
|
808
|
+
* Controls how position changes are animated.
|
|
809
|
+
*
|
|
810
|
+
* @default 'smooth'
|
|
811
|
+
*/
|
|
812
|
+
flipBehavior?: FLIPBehavior;
|
|
813
|
+
/**
|
|
814
|
+
* Strategy for positioning elements during exit animation.
|
|
815
|
+
* Controls whether exiting elements stay in place or are removed from layout.
|
|
816
|
+
*
|
|
817
|
+
* @default 'keep-pace'
|
|
818
|
+
*/
|
|
819
|
+
exitPositionStrategy?: ExitPositionStrategy;
|
|
820
|
+
/**
|
|
821
|
+
* Callback fired when an item starts its exit animation.
|
|
822
|
+
* Use this to update your state - the item will be removed from DOM after animation completes.
|
|
823
|
+
*
|
|
824
|
+
* @param id - The key of the child that is exiting
|
|
825
|
+
*
|
|
826
|
+
* @example
|
|
827
|
+
* ```tsx
|
|
828
|
+
* const onItemExit = (id) => {
|
|
829
|
+
* // Don't remove yet - let animation play out
|
|
830
|
+
* // Animation will call onComplete when finished
|
|
831
|
+
* console.log('Exiting:', id);
|
|
832
|
+
* };
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
835
|
+
onItemExit?: (id: string) => void;
|
|
836
|
+
/**
|
|
837
|
+
* Callback fired when an item completes its enter animation.
|
|
838
|
+
*
|
|
839
|
+
* @param id - The key of the child that entered
|
|
840
|
+
*/
|
|
841
|
+
onItemEnter?: (id: string) => void;
|
|
842
|
+
/**
|
|
843
|
+
* Callback for drag-and-drop reordering.
|
|
844
|
+
*
|
|
845
|
+
* @future Not yet implemented - planned for future version with @dnd-kit integration.
|
|
846
|
+
*
|
|
847
|
+
* @param oldIndex - Original index before reorder
|
|
848
|
+
* @param newIndex - New index after reorder
|
|
849
|
+
*/
|
|
850
|
+
onReorder?: (oldIndex: number, newIndex: number) => void;
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Animation state passed to {@link ReorderItem} render prop function
|
|
854
|
+
*
|
|
855
|
+
* Use this to conditionally render content based on animation state.
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```tsx
|
|
859
|
+
* <ReorderItem id="item-1">
|
|
860
|
+
* {(state) => (
|
|
861
|
+
* <div style={{ opacity: state.isExiting ? 0.5 : 1 }}>
|
|
862
|
+
* Content
|
|
863
|
+
* </div>
|
|
864
|
+
* )}
|
|
865
|
+
* </ReorderItem>
|
|
866
|
+
* ```
|
|
867
|
+
*/
|
|
868
|
+
interface ReorderItemState {
|
|
869
|
+
/** True when the item is currently animating out. */
|
|
870
|
+
isExiting: boolean;
|
|
871
|
+
/** True when the item is currently animating in. */
|
|
872
|
+
isEntering: boolean;
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Props for {@link ReorderItem} component
|
|
876
|
+
*
|
|
877
|
+
* Wrapper component for individual items in a Reorder list.
|
|
878
|
+
* Automatically registers with the parent Reorder context.
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* ```tsx
|
|
882
|
+
* import { Reorder, ReorderItem } from '@mks2508/waapi-animation-primitives';
|
|
883
|
+
*
|
|
884
|
+
* <Reorder>
|
|
885
|
+
* <ReorderItem id="item-1">
|
|
886
|
+
* <div>Item 1</div>
|
|
887
|
+
* </ReorderItem>
|
|
888
|
+
* </Reorder>
|
|
889
|
+
* ```
|
|
890
|
+
*/
|
|
891
|
+
interface ReorderItemProps {
|
|
892
|
+
/**
|
|
893
|
+
* Child content or render prop function.
|
|
894
|
+
* Pass a function to receive animation state.
|
|
895
|
+
*
|
|
896
|
+
* @example
|
|
897
|
+
* ```tsx
|
|
898
|
+
* // Static content
|
|
899
|
+
* <ReorderItem id="1"><div>Content</div></ReorderItem>
|
|
900
|
+
*
|
|
901
|
+
* // Render prop with state
|
|
902
|
+
* <ReorderItem id="1">
|
|
903
|
+
* {(state) => <div style={{ opacity: state.isExiting ? 0.5 : 1 }}>Content</div>}
|
|
904
|
+
* </ReorderItem>
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
907
|
+
children: ReactNode | ((state: ReorderItemState) => ReactNode);
|
|
908
|
+
/** Unique identifier for this item (used for tracking animations). */
|
|
909
|
+
id: string;
|
|
910
|
+
/** Optional index for manual control (usually auto-detected from position). */
|
|
911
|
+
index?: number;
|
|
912
|
+
/** Whether to animate this item (default: true). */
|
|
913
|
+
animate?: boolean;
|
|
914
|
+
/** Additional CSS class name. */
|
|
915
|
+
className?: string;
|
|
916
|
+
/** HTML tag to render as (default: 'div'). */
|
|
917
|
+
as?: ElementType;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Return type for {@link useReorder} hook
|
|
921
|
+
*
|
|
922
|
+
* Provides methods for orchestrating FLIP animations on registered elements.
|
|
923
|
+
* Extends the base AnimationOrchestratorAPI with exit/enter helpers.
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* ```tsx
|
|
927
|
+
* const reorder = useReorder();
|
|
928
|
+
*
|
|
929
|
+
* // Register an element
|
|
930
|
+
* <div ref={el => reorder.registerElement('item-1', el)}>Item</div>
|
|
931
|
+
*
|
|
932
|
+
* // Trigger exit animation
|
|
933
|
+
* await reorder.startItemExit('item-1');
|
|
934
|
+
*
|
|
935
|
+
* // Check if animating
|
|
936
|
+
* if (reorder.isAnimating('item-1')) {
|
|
937
|
+
* console.log('Still animating...');
|
|
938
|
+
* }
|
|
939
|
+
* ```
|
|
940
|
+
*/
|
|
941
|
+
interface UseReorderReturn extends AnimationOrchestratorAPI {
|
|
942
|
+
/**
|
|
943
|
+
* Start exit animation for an item.
|
|
944
|
+
* The item stays in DOM until animation completes.
|
|
945
|
+
*
|
|
946
|
+
* @param id - The unique identifier of the item
|
|
947
|
+
* @returns Promise that resolves when exit animation completes
|
|
948
|
+
*/
|
|
949
|
+
startItemExit: (id: string) => Promise<void>;
|
|
950
|
+
/**
|
|
951
|
+
* Start enter animation for an item.
|
|
952
|
+
*
|
|
953
|
+
* @param id - The unique identifier of the item
|
|
954
|
+
* @returns Promise that resolves when enter animation completes
|
|
955
|
+
*/
|
|
956
|
+
startItemEnter: (id: string) => Promise<void>;
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Configuration options for {@link useReorder} hook
|
|
960
|
+
*
|
|
961
|
+
* All timing values are in milliseconds.
|
|
962
|
+
*
|
|
963
|
+
* @example
|
|
964
|
+
* ```tsx
|
|
965
|
+
* const reorder = useReorder({
|
|
966
|
+
* enterDuration: 400,
|
|
967
|
+
* exitDuration: 200,
|
|
968
|
+
* flipDuration: 300,
|
|
969
|
+
* onComplete: (id) => console.log('Done:', id)
|
|
970
|
+
* });
|
|
971
|
+
* ```
|
|
972
|
+
*/
|
|
973
|
+
interface UseReorderConfig {
|
|
974
|
+
/** Duration of enter animation in milliseconds. @default 300 */
|
|
975
|
+
enterDuration?: number;
|
|
976
|
+
/** Duration of exit animation in milliseconds. @default 200 */
|
|
977
|
+
exitDuration?: number;
|
|
978
|
+
/** Duration of FLIP animation in milliseconds. @default 300 */
|
|
979
|
+
flipDuration?: number;
|
|
980
|
+
/** Easing function for enter animation (CSS cubic-bezier or linear()). @default 'cubic-bezier(0.33, 1, 0.68, 1)' */
|
|
981
|
+
enterEasing?: string;
|
|
982
|
+
/** Easing function for exit animation. @default 'cubic-bezier(0.32, 0, 0.67, 0)' */
|
|
983
|
+
exitEasing?: string;
|
|
984
|
+
/** Easing function for FLIP animation. @default 'cubic-bezier(0.2, 0, 0.2, 1)' */
|
|
985
|
+
flipEasing?: string;
|
|
986
|
+
/** FLIP animation behavior strategy. @default 'smooth' */
|
|
987
|
+
flipBehavior?: FLIPBehavior;
|
|
988
|
+
/** Strategy for positioning elements during exit animation. @default 'keep-pace' */
|
|
989
|
+
exitPositionStrategy?: ExitPositionStrategy;
|
|
990
|
+
/**
|
|
991
|
+
* Callback called when an item's exit animation completes.
|
|
992
|
+
* Use this to remove the item from your state.
|
|
993
|
+
*
|
|
994
|
+
* @param id - The unique identifier of the completed item
|
|
995
|
+
*/
|
|
996
|
+
onComplete?: (id: string) => void;
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Context value passed to Reorder children
|
|
1000
|
+
*
|
|
1001
|
+
* @internal Consumed by ReorderItem component
|
|
1002
|
+
*/
|
|
1003
|
+
interface ReorderContextValue {
|
|
1004
|
+
/** Reorder instance with animation methods. */
|
|
1005
|
+
reorder: UseReorderReturn;
|
|
1006
|
+
/** Current layout setting. */
|
|
1007
|
+
layout: ReorderLayout;
|
|
1008
|
+
/** Check if an item is currently exiting. */
|
|
1009
|
+
isExiting: (id: string) => boolean;
|
|
1010
|
+
/** Check if an item is currently entering. */
|
|
1011
|
+
isEntering: (id: string) => boolean;
|
|
1012
|
+
/** Array of item IDs currently exiting. */
|
|
1013
|
+
exitingIds: string[];
|
|
1014
|
+
/** Array of item IDs currently entering. */
|
|
1015
|
+
enteringIds: string[];
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Configuration for {@link useReorderPresence} hook
|
|
1019
|
+
*
|
|
1020
|
+
* An alternative to using the Reorder component, giving you full control
|
|
1021
|
+
* over rendering while handling animation orchestration.
|
|
1022
|
+
*
|
|
1023
|
+
* @example
|
|
1024
|
+
* ```tsx
|
|
1025
|
+
* const { presentChildren, triggerExit } = useReorderPresence(
|
|
1026
|
+
* items.map(item => <div key={item.id}>{item.name}</div>),
|
|
1027
|
+
* {
|
|
1028
|
+
* stagger: 15,
|
|
1029
|
+
* onItemExit: (id) => removeItem(id)
|
|
1030
|
+
* }
|
|
1031
|
+
* );
|
|
1032
|
+
*
|
|
1033
|
+
* const handleDelete = (id: string) => {
|
|
1034
|
+
* triggerExit(id); // Triggers animation, then calls onItemExit
|
|
1035
|
+
* };
|
|
1036
|
+
*
|
|
1037
|
+
* return <div>{presentChildren}</div>;
|
|
1038
|
+
* ```
|
|
1039
|
+
*/
|
|
1040
|
+
interface UseReorderPresenceConfig {
|
|
1041
|
+
/**
|
|
1042
|
+
* Enable automatic enter animations for new children.
|
|
1043
|
+
*
|
|
1044
|
+
* @default true
|
|
1045
|
+
*/
|
|
1046
|
+
autoAnimate?: boolean;
|
|
1047
|
+
/** Stagger delay between item animations. */
|
|
1048
|
+
stagger?: StaggerConfig;
|
|
1049
|
+
/** Duration of enter animation in milliseconds. @default 300 */
|
|
1050
|
+
enterDuration?: number;
|
|
1051
|
+
/** Duration of exit animation in milliseconds. @default 200 */
|
|
1052
|
+
exitDuration?: number;
|
|
1053
|
+
/** Duration of FLIP animation in milliseconds. @default 300 */
|
|
1054
|
+
flipDuration?: number;
|
|
1055
|
+
/** Easing function for enter animation. */
|
|
1056
|
+
enterEasing?: string;
|
|
1057
|
+
/** Easing function for exit animation. */
|
|
1058
|
+
exitEasing?: string;
|
|
1059
|
+
/** Easing function for FLIP animation. */
|
|
1060
|
+
flipEasing?: string;
|
|
1061
|
+
/** FLIP animation behavior strategy. */
|
|
1062
|
+
flipBehavior?: FLIPBehavior;
|
|
1063
|
+
/** Strategy for positioning elements during exit animation. */
|
|
1064
|
+
exitPositionStrategy?: ExitPositionStrategy;
|
|
1065
|
+
/** Callback fired when an item starts its exit animation. */
|
|
1066
|
+
onItemExit?: (id: string) => void;
|
|
1067
|
+
/** Callback fired when an item completes its enter animation. */
|
|
1068
|
+
onItemEnter?: (id: string) => void;
|
|
1069
|
+
/**
|
|
1070
|
+
* Callback fired when an item's exit animation completes.
|
|
1071
|
+
* Use this to remove the item from your state.
|
|
1072
|
+
*/
|
|
1073
|
+
onAnimationComplete?: (id: string) => void;
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Return type for {@link useReorderPresence} hook
|
|
1077
|
+
*
|
|
1078
|
+
* Provides rendered children and methods for triggering animations.
|
|
1079
|
+
*
|
|
1080
|
+
* @example
|
|
1081
|
+
* ```tsx
|
|
1082
|
+
* const { presentChildren, triggerExit, isExiting } = useReorderPresence(
|
|
1083
|
+
* children,
|
|
1084
|
+
* config
|
|
1085
|
+
* );
|
|
1086
|
+
*
|
|
1087
|
+
* return (
|
|
1088
|
+
* <>
|
|
1089
|
+
* {presentChildren}
|
|
1090
|
+
* <button onClick={() => triggerExit('item-1')} disabled={isExiting('item-1')}>
|
|
1091
|
+
* Remove
|
|
1092
|
+
* </button>
|
|
1093
|
+
* </>
|
|
1094
|
+
* );
|
|
1095
|
+
* ```
|
|
1096
|
+
*/
|
|
1097
|
+
interface UseReorderPresenceReturn {
|
|
1098
|
+
/**
|
|
1099
|
+
* Rendered children with animation data attributes applied.
|
|
1100
|
+
* Render this directly in your component.
|
|
1101
|
+
*/
|
|
1102
|
+
presentChildren: ReactNode;
|
|
1103
|
+
/**
|
|
1104
|
+
* Trigger exit animation for an item.
|
|
1105
|
+
* The item stays in DOM until onAnimationComplete callback.
|
|
1106
|
+
*
|
|
1107
|
+
* @param id - The unique identifier of the item to remove
|
|
1108
|
+
*/
|
|
1109
|
+
triggerExit: (id: string) => void;
|
|
1110
|
+
/** Check if an item is currently exiting. */
|
|
1111
|
+
isExiting: (id: string) => boolean;
|
|
1112
|
+
/** Check if an item is currently entering. */
|
|
1113
|
+
isEntering: (id: string) => boolean;
|
|
1114
|
+
/** Array of item IDs currently exiting. */
|
|
1115
|
+
exitingIds: string[];
|
|
1116
|
+
/** Array of item IDs currently entering. */
|
|
1117
|
+
enteringIds: string[];
|
|
1118
|
+
/** Underlying reorder instance with animation methods. */
|
|
1119
|
+
reorder: UseReorderReturn;
|
|
1120
|
+
}
|
|
1121
|
+
//#endregion
|
|
1122
|
+
//#region src/primitives/reorder/useReorder.d.ts
|
|
1123
|
+
/**
|
|
1124
|
+
* Hook for managing reorderable lists with FLIP animations.
|
|
1125
|
+
*
|
|
1126
|
+
* Architecture: Thin wrapper around useAnimationOrchestrator
|
|
1127
|
+
* - Delegates all animation logic to orchestrator
|
|
1128
|
+
* - Provides stable API surface for Reorder component
|
|
1129
|
+
*
|
|
1130
|
+
* @example
|
|
1131
|
+
* ```tsx
|
|
1132
|
+
* const reorder = useReorder({
|
|
1133
|
+
* onComplete: (id) => removeFromList(id)
|
|
1134
|
+
* });
|
|
1135
|
+
*
|
|
1136
|
+
* // Register elements:
|
|
1137
|
+
* <div ref={el => reorder.registerElement('item-1', el)}>
|
|
1138
|
+
* Item 1
|
|
1139
|
+
* </div>
|
|
1140
|
+
*
|
|
1141
|
+
* // Trigger exit:
|
|
1142
|
+
* await reorder.startItemExit('item-1');
|
|
1143
|
+
* ```
|
|
1144
|
+
*/
|
|
1145
|
+
declare function useReorder(config?: UseReorderConfig): UseReorderReturn;
|
|
1146
|
+
//#endregion
|
|
1147
|
+
//#region src/primitives/reorder/useReorderPresence.d.ts
|
|
1148
|
+
/**
|
|
1149
|
+
* Hook for managing presence animations in reorderable lists
|
|
1150
|
+
*
|
|
1151
|
+
* IMPORTANT: This hook follows the AnimatedTokens pattern where:
|
|
1152
|
+
* - Elements stay in DOM until animation completes
|
|
1153
|
+
* - Consumer must keep items in their state until onAnimationComplete fires
|
|
1154
|
+
* - No "ghost" cloning - animations run on actual DOM elements
|
|
1155
|
+
*
|
|
1156
|
+
* @example
|
|
1157
|
+
* ```tsx
|
|
1158
|
+
* const [items, setItems] = useState(INITIAL_ITEMS);
|
|
1159
|
+
*
|
|
1160
|
+
* const { presentChildren, triggerExit } = useReorderPresence(
|
|
1161
|
+
* items.map(item => <div key={item.id}>{item.name}</div>),
|
|
1162
|
+
* {
|
|
1163
|
+
* onAnimationComplete: (id) => {
|
|
1164
|
+
* // Only remove from state AFTER animation completes
|
|
1165
|
+
* setItems(prev => prev.filter(item => item.id !== id));
|
|
1166
|
+
* }
|
|
1167
|
+
* }
|
|
1168
|
+
* );
|
|
1169
|
+
*
|
|
1170
|
+
* const handleDelete = (id: string) => {
|
|
1171
|
+
* // DON'T remove from state - just trigger animation
|
|
1172
|
+
* triggerExit(id);
|
|
1173
|
+
* };
|
|
1174
|
+
* ```
|
|
1175
|
+
*/
|
|
1176
|
+
declare function useReorderPresence(children: ReactNode, config?: UseReorderPresenceConfig): UseReorderPresenceReturn;
|
|
1177
|
+
//#endregion
|
|
1178
|
+
//#region src/primitives/reorder/Reorder.d.ts
|
|
1179
|
+
/**
|
|
1180
|
+
* Agnostic container for reorderable items with FLIP animations.
|
|
1181
|
+
*
|
|
1182
|
+
* Architecture: CSS + WAAPI (no React state for animation tracking)
|
|
1183
|
+
* - CSS handles initial states ([data-reorder-state="entering"] starts hidden)
|
|
1184
|
+
* - WAAPI handles all animations
|
|
1185
|
+
* - React only manages displayChildren (what's in DOM)
|
|
1186
|
+
*
|
|
1187
|
+
* @example
|
|
1188
|
+
* ```tsx
|
|
1189
|
+
* <Reorder
|
|
1190
|
+
* layout="horizontal"
|
|
1191
|
+
* onItemExit={(id) => handleRemove(id)}
|
|
1192
|
+
* >
|
|
1193
|
+
* {items.map(item => (
|
|
1194
|
+
* <div key={item.id}>{item.name}</div>
|
|
1195
|
+
* ))}
|
|
1196
|
+
* </Reorder>
|
|
1197
|
+
* ```
|
|
1198
|
+
*/
|
|
1199
|
+
declare const ReorderRoot: React$1.ForwardRefExoticComponent<ReorderProps & React$1.RefAttributes<{
|
|
1200
|
+
startItemExit: (id: string) => Promise<void>;
|
|
1201
|
+
startItemEnter: (id: string) => Promise<void>;
|
|
1202
|
+
isAnimating: (id?: string) => boolean;
|
|
1203
|
+
}>>;
|
|
1204
|
+
//#endregion
|
|
1205
|
+
//#region src/primitives/morph/types.d.ts
|
|
1206
|
+
/**
|
|
1207
|
+
* Available morphing techniques
|
|
1208
|
+
*/
|
|
1209
|
+
type MorphTechnique = 'flip-clip-path' | 'css-grid' | 'view-transitions';
|
|
1210
|
+
/**
|
|
1211
|
+
* FLIP + clip-path specific options
|
|
1212
|
+
*/
|
|
1213
|
+
interface FLIPClipPathOptions {
|
|
1214
|
+
duration?: number;
|
|
1215
|
+
easing?: string;
|
|
1216
|
+
clipPathStart?: string;
|
|
1217
|
+
clipPathEnd?: string;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* CSS Grid specific options
|
|
1221
|
+
*/
|
|
1222
|
+
interface CSSGridMorphOptions {
|
|
1223
|
+
duration?: number;
|
|
1224
|
+
easing?: string;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* View Transitions API specific options
|
|
1228
|
+
*/
|
|
1229
|
+
interface ViewTransitionsOptions {
|
|
1230
|
+
name?: string;
|
|
1231
|
+
types?: string[];
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Configuration for useMorph hook
|
|
1235
|
+
*/
|
|
1236
|
+
interface UseMorphOptions {
|
|
1237
|
+
technique?: MorphTechnique;
|
|
1238
|
+
duration?: number;
|
|
1239
|
+
easing?: string;
|
|
1240
|
+
onMorphStart?: () => void;
|
|
1241
|
+
onMorphEnd?: () => void;
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* FLIP + clip-path API
|
|
1245
|
+
*/
|
|
1246
|
+
interface FLIPClipPathAPI {
|
|
1247
|
+
isMorphing: boolean;
|
|
1248
|
+
morph: (fromElement: HTMLElement, toElement: HTMLElement) => Promise<void>;
|
|
1249
|
+
cancel: () => void;
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* CSS Grid morph API
|
|
1253
|
+
*/
|
|
1254
|
+
interface CSSGridMorphAPI {
|
|
1255
|
+
isExpanded: boolean;
|
|
1256
|
+
expand: () => void;
|
|
1257
|
+
collapse: () => void;
|
|
1258
|
+
toggle: () => void;
|
|
1259
|
+
containerRef: RefObject<HTMLElement | null>;
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* View Transitions API
|
|
1263
|
+
*/
|
|
1264
|
+
interface ViewTransitionsAPI {
|
|
1265
|
+
isSupported: boolean;
|
|
1266
|
+
startTransition: (callback: () => void | Promise<void>) => Promise<void>;
|
|
1267
|
+
setTypes: (types: string[]) => void;
|
|
1268
|
+
}
|
|
1269
|
+
/**
|
|
1270
|
+
* Return type for useMorph hook
|
|
1271
|
+
*/
|
|
1272
|
+
interface UseMorphReturn {
|
|
1273
|
+
isMorphing: boolean;
|
|
1274
|
+
technique: MorphTechnique;
|
|
1275
|
+
isViewTransitionsSupported: boolean;
|
|
1276
|
+
morph: (fromElement: HTMLElement, toElement: HTMLElement) => Promise<void>;
|
|
1277
|
+
cancel: () => void;
|
|
1278
|
+
flipClipPath: FLIPClipPathAPI;
|
|
1279
|
+
cssGrid: CSSGridMorphAPI;
|
|
1280
|
+
viewTransitions: ViewTransitionsAPI;
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Props for Morph component
|
|
1284
|
+
*/
|
|
1285
|
+
interface MorphProps {
|
|
1286
|
+
children: ReactNode;
|
|
1287
|
+
technique?: MorphTechnique;
|
|
1288
|
+
duration?: number;
|
|
1289
|
+
easing?: string;
|
|
1290
|
+
className?: string;
|
|
1291
|
+
onMorphStart?: () => void;
|
|
1292
|
+
onMorphEnd?: () => void;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Context value for Morph components
|
|
1296
|
+
*/
|
|
1297
|
+
interface MorphContextValue {
|
|
1298
|
+
morph: UseMorphReturn;
|
|
1299
|
+
}
|
|
1300
|
+
//#endregion
|
|
1301
|
+
//#region src/primitives/morph/MorphContext.d.ts
|
|
1302
|
+
/**
|
|
1303
|
+
* Context for sharing Morph state between components
|
|
1304
|
+
*/
|
|
1305
|
+
declare const MorphContext: react0.Context<MorphContextValue | null>;
|
|
1306
|
+
/**
|
|
1307
|
+
* Hook to access Morph context
|
|
1308
|
+
* Must be used within a Morph component
|
|
1309
|
+
*
|
|
1310
|
+
* @throws Error if used outside Morph component
|
|
1311
|
+
*/
|
|
1312
|
+
declare function useMorphContext(): MorphContextValue;
|
|
1313
|
+
//#endregion
|
|
1314
|
+
//#region src/primitives/morph/useMorph.d.ts
|
|
1315
|
+
/**
|
|
1316
|
+
* Unified hook for morphing animations
|
|
1317
|
+
*
|
|
1318
|
+
* Provides access to multiple morphing techniques:
|
|
1319
|
+
* - FLIP + clip-path (default): Best for element-to-element transitions
|
|
1320
|
+
* - CSS Grid: Best for expand/collapse animations
|
|
1321
|
+
* - View Transitions: Best for page/route transitions (requires browser support)
|
|
1322
|
+
*
|
|
1323
|
+
* @example
|
|
1324
|
+
* ```tsx
|
|
1325
|
+
* const morph = useMorph({ technique: 'flip-clip-path' });
|
|
1326
|
+
*
|
|
1327
|
+
* // Using unified API:
|
|
1328
|
+
* await morph.morph(fromElement, toElement);
|
|
1329
|
+
*
|
|
1330
|
+
* // Or using individual techniques:
|
|
1331
|
+
* morph.cssGrid.toggle();
|
|
1332
|
+
* ```
|
|
1333
|
+
*/
|
|
1334
|
+
declare function useMorph(options?: UseMorphOptions): UseMorphReturn;
|
|
1335
|
+
//#endregion
|
|
1336
|
+
//#region src/primitives/morph/Morph.d.ts
|
|
1337
|
+
/**
|
|
1338
|
+
* Container component for morphable elements
|
|
1339
|
+
*
|
|
1340
|
+
* Provides morphing capabilities to child components through context.
|
|
1341
|
+
*
|
|
1342
|
+
* @example
|
|
1343
|
+
* ```tsx
|
|
1344
|
+
* <Morph technique="flip-clip-path" duration={300}>
|
|
1345
|
+
* <MorphSource ref={fromRef}>From Content</MorphSource>
|
|
1346
|
+
* <MorphTarget ref={toRef}>To Content</MorphTarget>
|
|
1347
|
+
* <button onClick={() => morph(fromRef.current, toRef.current)}>
|
|
1348
|
+
* Morph
|
|
1349
|
+
* </button>
|
|
1350
|
+
* </Morph>
|
|
1351
|
+
* ```
|
|
1352
|
+
*/
|
|
1353
|
+
declare function Morph({
|
|
1354
|
+
children,
|
|
1355
|
+
technique,
|
|
1356
|
+
duration,
|
|
1357
|
+
easing,
|
|
1358
|
+
className,
|
|
1359
|
+
onMorphStart,
|
|
1360
|
+
onMorphEnd
|
|
1361
|
+
}: MorphProps): ReactNode;
|
|
1362
|
+
//#endregion
|
|
1363
|
+
//#region src/primitives/morph/techniques/useFLIPClipPath.d.ts
|
|
1364
|
+
/**
|
|
1365
|
+
* Hook for FLIP + clip-path morphing technique
|
|
1366
|
+
*
|
|
1367
|
+
* This technique combines:
|
|
1368
|
+
* 1. FLIP for position/size transitions
|
|
1369
|
+
* 2. clip-path for shape morphing
|
|
1370
|
+
* 3. Opacity crossfade for smooth visual transition
|
|
1371
|
+
*
|
|
1372
|
+
* @example
|
|
1373
|
+
* ```tsx
|
|
1374
|
+
* const { isMorphing, morph, cancel } = useFLIPClipPath({ duration: 300 });
|
|
1375
|
+
*
|
|
1376
|
+
* const handleMorph = async () => {
|
|
1377
|
+
* await morph(fromRef.current, toRef.current);
|
|
1378
|
+
* };
|
|
1379
|
+
* ```
|
|
1380
|
+
*/
|
|
1381
|
+
declare function useFLIPClipPath(options?: FLIPClipPathOptions): FLIPClipPathAPI;
|
|
1382
|
+
//#endregion
|
|
1383
|
+
//#region src/primitives/morph/techniques/useCSSGridMorph.d.ts
|
|
1384
|
+
/**
|
|
1385
|
+
* Hook for CSS Grid-based expand/collapse animations
|
|
1386
|
+
*
|
|
1387
|
+
* Uses the grid-template-rows: 0fr/1fr technique for smooth height animations
|
|
1388
|
+
* without needing to know the content height in advance.
|
|
1389
|
+
*
|
|
1390
|
+
* CSS required on container:
|
|
1391
|
+
* ```css
|
|
1392
|
+
* .morph-container {
|
|
1393
|
+
* display: grid;
|
|
1394
|
+
* grid-template-rows: 0fr;
|
|
1395
|
+
* transition: grid-template-rows 300ms ease;
|
|
1396
|
+
* }
|
|
1397
|
+
* .morph-container.expanded {
|
|
1398
|
+
* grid-template-rows: 1fr;
|
|
1399
|
+
* }
|
|
1400
|
+
* .morph-content {
|
|
1401
|
+
* overflow: hidden;
|
|
1402
|
+
* }
|
|
1403
|
+
* ```
|
|
1404
|
+
*
|
|
1405
|
+
* @example
|
|
1406
|
+
* ```tsx
|
|
1407
|
+
* const { isExpanded, toggle, containerRef } = useCSSGridMorph();
|
|
1408
|
+
*
|
|
1409
|
+
* return (
|
|
1410
|
+
* <div ref={containerRef} className={isExpanded ? 'expanded' : ''}>
|
|
1411
|
+
* <div className="morph-content">
|
|
1412
|
+
* Collapsible content
|
|
1413
|
+
* </div>
|
|
1414
|
+
* </div>
|
|
1415
|
+
* );
|
|
1416
|
+
* ```
|
|
1417
|
+
*/
|
|
1418
|
+
declare function useCSSGridMorph(options?: CSSGridMorphOptions): CSSGridMorphAPI;
|
|
1419
|
+
//#endregion
|
|
1420
|
+
//#region src/primitives/morph/techniques/useViewTransitions.d.ts
|
|
1421
|
+
/**
|
|
1422
|
+
* Hook for View Transitions API
|
|
1423
|
+
*
|
|
1424
|
+
* Provides a wrapper around the native View Transitions API
|
|
1425
|
+
* with automatic feature detection and fallback handling.
|
|
1426
|
+
*
|
|
1427
|
+
* Browser support (as of 2025):
|
|
1428
|
+
* - Chrome 111+: ✅
|
|
1429
|
+
* - Firefox 144+: ✅
|
|
1430
|
+
* - Safari latest: ✅
|
|
1431
|
+
*
|
|
1432
|
+
* @example
|
|
1433
|
+
* ```tsx
|
|
1434
|
+
* const { isSupported, startTransition } = useViewTransitions({ name: 'hero' });
|
|
1435
|
+
*
|
|
1436
|
+
* const handleTransition = async () => {
|
|
1437
|
+
* await startTransition(() => {
|
|
1438
|
+
* setActiveImage(nextImage);
|
|
1439
|
+
* });
|
|
1440
|
+
* };
|
|
1441
|
+
* ```
|
|
1442
|
+
*/
|
|
1443
|
+
declare function useViewTransitions(options?: ViewTransitionsOptions): ViewTransitionsAPI;
|
|
1444
|
+
//#endregion
|
|
1445
|
+
//#region src/utils/animationUtils.d.ts
|
|
83
1446
|
/**
|
|
84
1447
|
* Obtiene duración de animación responsiva para el dispositivo actual
|
|
85
1448
|
* @param baseDuration - Duración base en ms
|
|
@@ -93,362 +1456,289 @@ declare const getResponsiveDuration: (baseDuration: number) => number;
|
|
|
93
1456
|
*/
|
|
94
1457
|
declare const getResponsiveStagger: (baseDelay: number) => number;
|
|
95
1458
|
declare const TIMING: {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
1459
|
+
readonly ENTER_DURATION: 200;
|
|
1460
|
+
readonly EXIT_DURATION: 180;
|
|
1461
|
+
readonly COLLAPSE_DURATION: 200;
|
|
1462
|
+
readonly FLIP_DURATION: 300;
|
|
1463
|
+
readonly ENTER_STAGGER: 15;
|
|
1464
|
+
readonly EXIT_STAGGER: 0;
|
|
1465
|
+
readonly COLLAPSE_DELAY: 30;
|
|
1466
|
+
readonly FLIP_DELAY_PERCENT: 0.25;
|
|
1467
|
+
readonly MIN_DELTA_PX: 1;
|
|
105
1468
|
};
|
|
106
1469
|
declare const TRANSFORMS: {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
1470
|
+
readonly OFFSET_Y_ENTER: 8;
|
|
1471
|
+
readonly OFFSET_Y_EXIT: -8;
|
|
1472
|
+
readonly OFFSET_X: 16;
|
|
1473
|
+
readonly SCALE_ENTER: 0.85;
|
|
1474
|
+
readonly SCALE_EXIT: 0.85;
|
|
1475
|
+
readonly ROTATE_EXIT: 0;
|
|
112
1476
|
};
|
|
113
1477
|
declare const EFFECTS: {
|
|
114
|
-
|
|
115
|
-
|
|
1478
|
+
readonly BLUR_ENTER: 4;
|
|
1479
|
+
readonly BLUR_EXIT: 2;
|
|
116
1480
|
};
|
|
117
1481
|
declare const EASINGS: {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
1482
|
+
readonly MATERIAL_DECELERATE: "cubic-bezier(0, 0, 0.2, 1)";
|
|
1483
|
+
readonly MATERIAL_ACCELERATE: "cubic-bezier(0.4, 0, 1, 1)";
|
|
1484
|
+
readonly MATERIAL_STANDARD: "cubic-bezier(0.4, 0, 0.2, 1)";
|
|
1485
|
+
readonly EASE_REORDER: "cubic-bezier(0.215, 0.61, 0.355, 1)";
|
|
1486
|
+
readonly EASE_OUT_CUBIC: "cubic-bezier(0.33, 1, 0.68, 1)";
|
|
1487
|
+
readonly EASE_IN_CUBIC: "cubic-bezier(0.32, 0, 0.67, 0)";
|
|
1488
|
+
readonly EASE_IN_OUT: "cubic-bezier(0.42, 0, 0.58, 1)";
|
|
1489
|
+
readonly EASE_OUT_EXPO: "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
1490
|
+
readonly EASE_FLIP: "cubic-bezier(0.2, 0, 0.2, 1)";
|
|
1491
|
+
readonly SPRING_GENTLE: "linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%, 0.938 16.7%, 1.017 19.4%, 1.067, 1.099 24.3%, 1.108 26%, 1.100, 1.078 30.1%, 1.049 32.5%, 0.994 37.3%, 0.981 40.2%, 0.974 43.4%, 0.975 50.2%, 0.997 62.5%, 1.001 74.7%, 1)";
|
|
1492
|
+
readonly SPRING_SNAPPY: "linear(0, 0.006, 0.024 2%, 0.096 4.2%, 0.397 9.3%, 0.861 15.8%, 1.002 18.7%, 1.093 21.4%, 1.143 24%, 1.156, 1.149 28.3%, 1.115 31.5%, 1.022 40%, 0.988 47.1%, 0.984 55.1%, 0.998 72.3%, 1.001 85.4%, 1)";
|
|
125
1493
|
};
|
|
126
1494
|
/**
|
|
127
1495
|
* Configuración de animación responsiva con accessibility
|
|
128
1496
|
*/
|
|
129
1497
|
declare const RESPONSIVE_CONFIGS: {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
1498
|
+
readonly tokenEnter: {
|
|
1499
|
+
readonly duration: number;
|
|
1500
|
+
readonly stagger: number;
|
|
1501
|
+
readonly easing: "cubic-bezier(0, 0, 0.2, 1)";
|
|
1502
|
+
readonly blur: 4;
|
|
1503
|
+
readonly offsetY: 8;
|
|
1504
|
+
readonly scale: 0.85;
|
|
1505
|
+
};
|
|
1506
|
+
readonly tokenExit: {
|
|
1507
|
+
readonly duration: number;
|
|
1508
|
+
readonly stagger: number;
|
|
1509
|
+
readonly easing: "cubic-bezier(0.4, 0, 1, 1)";
|
|
1510
|
+
readonly blur: 2;
|
|
1511
|
+
readonly offsetY: -8;
|
|
1512
|
+
readonly scale: 0.85;
|
|
1513
|
+
};
|
|
1514
|
+
readonly collapse: {
|
|
1515
|
+
readonly duration: number;
|
|
1516
|
+
readonly delay: 30;
|
|
1517
|
+
readonly easing: "cubic-bezier(0.4, 0, 0.2, 1)";
|
|
1518
|
+
};
|
|
1519
|
+
readonly flip: {
|
|
1520
|
+
readonly duration: number;
|
|
1521
|
+
readonly delayPercent: 0.25;
|
|
1522
|
+
readonly easing: "cubic-bezier(0.215, 0.61, 0.355, 1)";
|
|
1523
|
+
};
|
|
155
1524
|
};
|
|
156
1525
|
declare const ANIMATION_DEFAULTS: {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
1526
|
+
DURATION_ENTER: 200;
|
|
1527
|
+
DURATION_EXIT: 180;
|
|
1528
|
+
DURATION_FLIP: 300;
|
|
1529
|
+
STAGGER_DELAY: 15;
|
|
1530
|
+
OFFSET_VERTICAL: 8;
|
|
1531
|
+
OFFSET_HORIZONTAL: 16;
|
|
1532
|
+
BLUR_AMOUNT: 4;
|
|
1533
|
+
EASING_ENTER: "cubic-bezier(0.33, 1, 0.68, 1)";
|
|
1534
|
+
EASING_EXIT: "cubic-bezier(0.32, 0, 0.67, 0)";
|
|
1535
|
+
EASING_FLIP: "linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%, 0.938 16.7%, 1.017 19.4%, 1.067, 1.099 24.3%, 1.108 26%, 1.100, 1.078 30.1%, 1.049 32.5%, 0.994 37.3%, 0.981 40.2%, 0.974 43.4%, 0.975 50.2%, 0.997 62.5%, 1.001 74.7%, 1)";
|
|
1536
|
+
SPRING_EASING: "linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%, 0.938 16.7%, 1.017 19.4%, 1.067, 1.099 24.3%, 1.108 26%, 1.100, 1.078 30.1%, 1.049 32.5%, 0.994 37.3%, 0.981 40.2%, 0.974 43.4%, 0.975 50.2%, 0.997 62.5%, 1.001 74.7%, 1)";
|
|
168
1537
|
};
|
|
169
1538
|
declare const ANIMATION_CONFIGS: {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
1539
|
+
readonly tokenEnter: {
|
|
1540
|
+
readonly duration: 200;
|
|
1541
|
+
readonly stagger: 15;
|
|
1542
|
+
readonly easing: "cubic-bezier(0, 0, 0.2, 1)";
|
|
1543
|
+
readonly blur: 4;
|
|
1544
|
+
readonly offsetY: 8;
|
|
1545
|
+
readonly scale: 0.85;
|
|
1546
|
+
};
|
|
1547
|
+
readonly tokenExit: {
|
|
1548
|
+
readonly duration: 180;
|
|
1549
|
+
readonly stagger: 0;
|
|
1550
|
+
readonly easing: "cubic-bezier(0.4, 0, 1, 1)";
|
|
1551
|
+
readonly blur: 2;
|
|
1552
|
+
readonly offsetY: -8;
|
|
1553
|
+
readonly scale: 0.85;
|
|
1554
|
+
};
|
|
1555
|
+
readonly collapse: {
|
|
1556
|
+
readonly duration: 200;
|
|
1557
|
+
readonly delay: 30;
|
|
1558
|
+
readonly easing: "cubic-bezier(0.4, 0, 0.2, 1)";
|
|
1559
|
+
};
|
|
1560
|
+
readonly flip: {
|
|
1561
|
+
readonly duration: 300;
|
|
1562
|
+
readonly delayPercent: 0.25;
|
|
1563
|
+
readonly easing: "cubic-bezier(0.215, 0.61, 0.355, 1)";
|
|
1564
|
+
};
|
|
195
1565
|
};
|
|
196
1566
|
declare const PRESETS: {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
1567
|
+
newToken: {
|
|
1568
|
+
mode: "character";
|
|
1569
|
+
direction: "vertical";
|
|
1570
|
+
staggerDelay: number;
|
|
1571
|
+
blur: boolean;
|
|
1572
|
+
widthAnimation: boolean;
|
|
1573
|
+
duration: number;
|
|
1574
|
+
initial: "initial";
|
|
1575
|
+
};
|
|
1576
|
+
existingToken: {
|
|
1577
|
+
mode: "none";
|
|
1578
|
+
blur: boolean;
|
|
1579
|
+
widthAnimation: boolean;
|
|
1580
|
+
initial: false;
|
|
1581
|
+
};
|
|
1582
|
+
placeholder: {
|
|
1583
|
+
mode: "word";
|
|
1584
|
+
direction: "vertical";
|
|
1585
|
+
blur: boolean;
|
|
1586
|
+
widthAnimation: boolean;
|
|
1587
|
+
duration: number;
|
|
1588
|
+
};
|
|
1589
|
+
separator: {
|
|
1590
|
+
duration: number;
|
|
1591
|
+
widthAnimation: boolean;
|
|
1592
|
+
};
|
|
223
1593
|
};
|
|
224
|
-
|
|
1594
|
+
//#endregion
|
|
1595
|
+
//#region src/styles/cssTokens.d.ts
|
|
1596
|
+
declare const CSS_VAR_NAMES: {
|
|
1597
|
+
readonly durationEnter: "--waapi-duration-enter";
|
|
1598
|
+
readonly durationExit: "--waapi-duration-exit";
|
|
1599
|
+
readonly durationCollapse: "--waapi-duration-collapse";
|
|
1600
|
+
readonly durationFlip: "--waapi-duration-flip";
|
|
1601
|
+
readonly staggerEnter: "--waapi-stagger-enter";
|
|
1602
|
+
readonly staggerExit: "--waapi-stagger-exit";
|
|
1603
|
+
readonly offsetYEnter: "--waapi-offset-y-enter";
|
|
1604
|
+
readonly offsetYExit: "--waapi-offset-y-exit";
|
|
1605
|
+
readonly offsetX: "--waapi-offset-x";
|
|
1606
|
+
readonly scaleExit: "--waapi-scale-exit";
|
|
1607
|
+
readonly blurEnter: "--waapi-blur-enter";
|
|
1608
|
+
readonly blurExit: "--waapi-blur-exit";
|
|
1609
|
+
readonly easeEnter: "--waapi-ease-enter";
|
|
1610
|
+
readonly easeExit: "--waapi-ease-exit";
|
|
1611
|
+
readonly easeCollapse: "--waapi-ease-collapse";
|
|
1612
|
+
readonly easeFlip: "--waapi-ease-flip";
|
|
1613
|
+
readonly separatorDuration: "--waapi-separator-duration";
|
|
1614
|
+
readonly separatorDelay: "--waapi-separator-delay";
|
|
1615
|
+
readonly separatorEasing: "--waapi-separator-easing";
|
|
1616
|
+
};
|
|
1617
|
+
type CSSVarName = typeof CSS_VAR_NAMES[keyof typeof CSS_VAR_NAMES];
|
|
1618
|
+
declare const CSS_VAR_VALUES: {
|
|
1619
|
+
readonly "--waapi-duration-enter": "200ms";
|
|
1620
|
+
readonly "--waapi-duration-exit": "180ms";
|
|
1621
|
+
readonly "--waapi-duration-collapse": "200ms";
|
|
1622
|
+
readonly "--waapi-duration-flip": "300ms";
|
|
1623
|
+
readonly "--waapi-stagger-enter": "15ms";
|
|
1624
|
+
readonly "--waapi-stagger-exit": "0ms";
|
|
1625
|
+
readonly "--waapi-offset-y-enter": "8px";
|
|
1626
|
+
readonly "--waapi-offset-y-exit": "-8px";
|
|
1627
|
+
readonly "--waapi-offset-x": "16px";
|
|
1628
|
+
readonly "--waapi-scale-exit": "0.85";
|
|
1629
|
+
readonly "--waapi-blur-enter": "4px";
|
|
1630
|
+
readonly "--waapi-blur-exit": "2px";
|
|
1631
|
+
readonly "--waapi-ease-enter": "cubic-bezier(0.33, 1, 0.68, 1)";
|
|
1632
|
+
readonly "--waapi-ease-exit": "cubic-bezier(0.32, 0, 0.67, 0)";
|
|
1633
|
+
readonly "--waapi-ease-collapse": "cubic-bezier(0.42, 0, 0.58, 1)";
|
|
1634
|
+
readonly "--waapi-ease-flip": "cubic-bezier(0.2, 0, 0.2, 1)";
|
|
1635
|
+
readonly "--waapi-separator-duration": "300ms";
|
|
1636
|
+
readonly "--waapi-separator-delay": `${number}ms`;
|
|
1637
|
+
readonly "--waapi-separator-easing": "cubic-bezier(0.2, 0, 0.2, 1)";
|
|
1638
|
+
};
|
|
1639
|
+
declare const cssVar: (name: CSSVarName) => string;
|
|
1640
|
+
declare const animatedTokensBaseStyles: {
|
|
1641
|
+
readonly container: React$1.CSSProperties;
|
|
1642
|
+
readonly placeholder: React$1.CSSProperties;
|
|
1643
|
+
readonly tokenWrapper: React$1.CSSProperties;
|
|
1644
|
+
readonly tokenWrapperExitCompleted: React$1.CSSProperties;
|
|
1645
|
+
readonly separator: React$1.CSSProperties;
|
|
1646
|
+
readonly separatorExitCoordinated: React$1.CSSProperties;
|
|
1647
|
+
readonly separatorExitCompleted: React$1.CSSProperties;
|
|
1648
|
+
readonly overflow: React$1.CSSProperties;
|
|
1649
|
+
};
|
|
1650
|
+
declare const slidingTextBaseStyles: {
|
|
1651
|
+
readonly container: React$1.CSSProperties;
|
|
1652
|
+
readonly content: React$1.CSSProperties;
|
|
1653
|
+
readonly token: React$1.CSSProperties;
|
|
1654
|
+
readonly enterFrom: React$1.CSSProperties;
|
|
1655
|
+
readonly enterTo: React$1.CSSProperties;
|
|
1656
|
+
readonly exitActive: React$1.CSSProperties;
|
|
1657
|
+
readonly verticalEnterFrom: React$1.CSSProperties;
|
|
1658
|
+
readonly verticalExitActive: React$1.CSSProperties;
|
|
1659
|
+
readonly horizontalEnterFrom: React$1.CSSProperties;
|
|
1660
|
+
readonly horizontalExitActive: React$1.CSSProperties;
|
|
1661
|
+
};
|
|
1662
|
+
declare const responsiveOverrides: {
|
|
1663
|
+
readonly mobile: React$1.CSSProperties;
|
|
1664
|
+
readonly smallMobile: React$1.CSSProperties;
|
|
1665
|
+
readonly reducedMotion: React$1.CSSProperties;
|
|
1666
|
+
readonly highContrast: React$1.CSSProperties;
|
|
1667
|
+
};
|
|
1668
|
+
declare const getResponsiveTokenStyles: () => React$1.CSSProperties;
|
|
1669
|
+
declare const generateCSSVariables: () => string;
|
|
1670
|
+
declare const generateResponsiveCSS: () => string;
|
|
1671
|
+
//#endregion
|
|
1672
|
+
//#region src/styles/slidingText.styles.d.ts
|
|
225
1673
|
declare const slidingTextStyles: {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
1674
|
+
readonly container: React$1.CSSProperties;
|
|
1675
|
+
readonly content: React$1.CSSProperties;
|
|
1676
|
+
readonly token: React$1.CSSProperties;
|
|
1677
|
+
readonly enterFrom: React$1.CSSProperties;
|
|
1678
|
+
readonly enterTo: React$1.CSSProperties;
|
|
1679
|
+
readonly exitActive: React$1.CSSProperties;
|
|
1680
|
+
readonly verticalEnterFrom: React$1.CSSProperties;
|
|
1681
|
+
readonly verticalExitActive: React$1.CSSProperties;
|
|
1682
|
+
readonly horizontalEnterFrom: React$1.CSSProperties;
|
|
1683
|
+
readonly horizontalExitActive: React$1.CSSProperties;
|
|
236
1684
|
};
|
|
237
|
-
declare const getSlidingTextTokenStyle: (state: "enter-from" | "enter-to" | "exit-active", direction: "vertical" | "horizontal") => React.CSSProperties;
|
|
238
|
-
|
|
1685
|
+
declare const getSlidingTextTokenStyle: (state: "enter-from" | "enter-to" | "exit-active", direction: "vertical" | "horizontal") => React$1.CSSProperties;
|
|
1686
|
+
declare const getResponsiveSlidingTextStyle: () => React$1.CSSProperties;
|
|
1687
|
+
//#endregion
|
|
1688
|
+
//#region src/styles/animatedTokens.styles.d.ts
|
|
239
1689
|
declare const animatedTokensStyles: {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
readonly overflowExiting: React.CSSProperties;
|
|
1690
|
+
readonly container: React$1.CSSProperties;
|
|
1691
|
+
readonly placeholder: React$1.CSSProperties;
|
|
1692
|
+
readonly tokenWrapper: React$1.CSSProperties;
|
|
1693
|
+
readonly tokenWrapperExitCompleted: React$1.CSSProperties;
|
|
1694
|
+
readonly separator: React$1.CSSProperties;
|
|
1695
|
+
readonly separatorExitCoordinated: React$1.CSSProperties;
|
|
1696
|
+
readonly separatorExitCompleted: React$1.CSSProperties;
|
|
1697
|
+
readonly overflow: React$1.CSSProperties;
|
|
249
1698
|
};
|
|
250
|
-
declare const getResponsiveAnimatedTokensStyle: () => React.CSSProperties;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
startTime: number;
|
|
254
|
-
endTime?: number;
|
|
255
|
-
expectedDuration: number;
|
|
256
|
-
actualDuration?: number;
|
|
257
|
-
deviation?: number;
|
|
258
|
-
deviationPercent?: number;
|
|
259
|
-
}
|
|
260
|
-
interface StyleData {
|
|
261
|
-
property: string;
|
|
262
|
-
expected: string;
|
|
263
|
-
actual: string;
|
|
264
|
-
matches: boolean;
|
|
265
|
-
}
|
|
266
|
-
interface PositionData {
|
|
267
|
-
element: string;
|
|
268
|
-
x: number;
|
|
269
|
-
y: number;
|
|
270
|
-
width: number;
|
|
271
|
-
height: number;
|
|
272
|
-
delta?: {
|
|
273
|
-
x: number;
|
|
274
|
-
y: number;
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
interface AnimationData {
|
|
278
|
-
name: string;
|
|
279
|
-
phase: 'start' | 'running' | 'complete' | 'cancelled';
|
|
280
|
-
progress?: number;
|
|
281
|
-
easing?: string;
|
|
282
|
-
fill?: string;
|
|
283
|
-
}
|
|
284
|
-
type DebugEventType = 'token-add' | 'token-remove' | 'token-reorder' | 'token-exit-start' | 'token-exit-complete' | 'token-dom-remove' | 'overflow-token-remove' | 'flip-animation' | 'flip-animation-complete' | 'flip-all-animations-complete' | 'flip-executing-callback' | 'flip-measure-start' | 'flip-position-measured' | 'flip-invalid-rect' | 'flip-invalid-delta' | 'flip-manual-trigger' | 'flip-capture-positions' | 'flip-position-captured' | 'waapi-exit-start' | 'waapi-exit-complete' | 'waapi-flip-animation' | 'exit-fade-complete' | 'orchestration-complete' | 'animation-start-detailed' | 'animation-complete-detailed' | 'animation-timing' | 'style-capture' | 'style-mismatch' | 'position-capture' | 'position-delta' | 'choreography-overlap' | 'choreography-sequence' | 'text-enter-start' | 'text-enter-complete' | 'triggering-flip-before-absolute' | 'state-change' | 'render' | 'animation-complete-called' | 'scheduling-raf' | 'raf-executed' | 'component-unmounted' | 'token-removing-from-layout' | 'exit-completed-ids-updated' | 'exit-completed-change' | 'registering-callback' | 'callback-fired';
|
|
285
|
-
interface DebugEvent {
|
|
286
|
-
timestamp: number;
|
|
287
|
-
type: DebugEventType;
|
|
288
|
-
source: string;
|
|
289
|
-
message: string;
|
|
290
|
-
timing?: TimingData;
|
|
291
|
-
styles?: StyleData[];
|
|
292
|
-
position?: PositionData;
|
|
293
|
-
animation?: AnimationData;
|
|
294
|
-
data?: Record<string, unknown>;
|
|
295
|
-
}
|
|
296
|
-
interface DebugContextValue {
|
|
297
|
-
events: DebugEvent[];
|
|
298
|
-
isEnabled: boolean;
|
|
299
|
-
enableDebug: () => void;
|
|
300
|
-
disableDebug: () => void;
|
|
301
|
-
toggleDebug: () => void;
|
|
302
|
-
logEvent: (event: Omit<DebugEvent, 'timestamp'>) => void;
|
|
303
|
-
clearEvents: () => void;
|
|
304
|
-
getEventLog: () => string;
|
|
305
|
-
exportToCSV: () => string;
|
|
306
|
-
}
|
|
307
|
-
declare const useDebug: () => DebugContextValue;
|
|
308
|
-
declare const DebugProvider: React.FC<{
|
|
309
|
-
children: React.ReactNode;
|
|
310
|
-
}>;
|
|
311
|
-
|
|
312
|
-
interface AnimationInfo {
|
|
313
|
-
id: string;
|
|
314
|
-
type: 'exit-fade' | 'exit-collapse' | 'flip' | 'enter' | 'width-collapse';
|
|
315
|
-
elementId: string;
|
|
316
|
-
startTime: number;
|
|
317
|
-
expectedDuration: number;
|
|
318
|
-
endTime?: number;
|
|
319
|
-
actualDuration?: number;
|
|
320
|
-
}
|
|
321
|
-
interface TimelineEvent {
|
|
322
|
-
time: number;
|
|
323
|
-
event: 'animation-start' | 'animation-end' | 'overlap-detected';
|
|
324
|
-
animationId: string;
|
|
325
|
-
type?: string;
|
|
326
|
-
overlappingWith?: string[];
|
|
327
|
-
expectedDuration?: number;
|
|
328
|
-
actualDuration?: number;
|
|
329
|
-
deviation?: number;
|
|
330
|
-
}
|
|
331
|
-
interface OverlapInfo {
|
|
332
|
-
animation1: string;
|
|
333
|
-
animation2: string;
|
|
334
|
-
overlapStart: number;
|
|
335
|
-
overlapDuration: number;
|
|
336
|
-
}
|
|
337
|
-
interface ChoreographySummary {
|
|
338
|
-
totalAnimations: number;
|
|
339
|
-
totalDuration: number;
|
|
340
|
-
overlaps: OverlapInfo[];
|
|
341
|
-
timeline: TimelineEvent[];
|
|
342
|
-
activeAnimations: AnimationInfo[];
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* ChoreographyTracker - Singleton for tracking animation choreography
|
|
346
|
-
* Detects overlaps, generates timeline, measures actual vs expected timing
|
|
347
|
-
*/
|
|
348
|
-
declare class ChoreographyTrackerClass {
|
|
349
|
-
private activeAnimations;
|
|
350
|
-
private timeline;
|
|
351
|
-
private completedAnimations;
|
|
352
|
-
private sessionStartTime;
|
|
353
|
-
/**
|
|
354
|
-
* Start a new tracking session (call when debug panel is cleared)
|
|
355
|
-
*/
|
|
356
|
-
startSession(): void;
|
|
357
|
-
/**
|
|
358
|
-
* Get relative time since session start
|
|
359
|
-
*/
|
|
360
|
-
private getRelativeTime;
|
|
361
|
-
/**
|
|
362
|
-
* Start tracking an animation
|
|
363
|
-
*/
|
|
364
|
-
startAnimation(id: string, type: AnimationInfo['type'], elementId: string, expectedDuration: number): void;
|
|
365
|
-
/**
|
|
366
|
-
* End tracking an animation
|
|
367
|
-
*/
|
|
368
|
-
endAnimation(id: string): AnimationInfo | undefined;
|
|
369
|
-
/**
|
|
370
|
-
* Detect which animations are overlapping with the given animation
|
|
371
|
-
*/
|
|
372
|
-
private detectOverlaps;
|
|
373
|
-
/**
|
|
374
|
-
* Get all overlap pairs with duration
|
|
375
|
-
*/
|
|
376
|
-
getOverlaps(): OverlapInfo[];
|
|
377
|
-
/**
|
|
378
|
-
* Get current timeline
|
|
379
|
-
*/
|
|
380
|
-
getTimeline(): TimelineEvent[];
|
|
381
|
-
/**
|
|
382
|
-
* Get active animation count
|
|
383
|
-
*/
|
|
384
|
-
getActiveCount(): number;
|
|
385
|
-
/**
|
|
386
|
-
* Get active animations
|
|
387
|
-
*/
|
|
388
|
-
getActiveAnimations(): AnimationInfo[];
|
|
389
|
-
/**
|
|
390
|
-
* Get completed animations
|
|
391
|
-
*/
|
|
392
|
-
getCompletedAnimations(): AnimationInfo[];
|
|
393
|
-
/**
|
|
394
|
-
* Get full choreography summary
|
|
395
|
-
*/
|
|
396
|
-
getSummary(): ChoreographySummary;
|
|
397
|
-
/**
|
|
398
|
-
* Get timeline for visualization (normalized to 0-100%)
|
|
399
|
-
*/
|
|
400
|
-
getTimelineForVisualization(): Array<{
|
|
401
|
-
id: string;
|
|
402
|
-
type: string;
|
|
403
|
-
elementId: string;
|
|
404
|
-
startPercent: number;
|
|
405
|
-
widthPercent: number;
|
|
406
|
-
duration: number;
|
|
407
|
-
isActive: boolean;
|
|
408
|
-
}>;
|
|
409
|
-
}
|
|
410
|
-
declare const choreographyTracker: ChoreographyTrackerClass;
|
|
411
|
-
|
|
1699
|
+
declare const getResponsiveAnimatedTokensStyle: () => React$1.CSSProperties;
|
|
1700
|
+
//#endregion
|
|
1701
|
+
//#region src/utils/debugCapture.d.ts
|
|
412
1702
|
interface StyleCapture {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
1703
|
+
opacity: string;
|
|
1704
|
+
transform: string;
|
|
1705
|
+
filter: string;
|
|
1706
|
+
width: string;
|
|
1707
|
+
height: string;
|
|
1708
|
+
marginRight: string;
|
|
1709
|
+
marginLeft: string;
|
|
1710
|
+
position: string;
|
|
1711
|
+
visibility: string;
|
|
1712
|
+
pointerEvents: string;
|
|
423
1713
|
}
|
|
424
1714
|
interface PositionCapture {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
1715
|
+
x: number;
|
|
1716
|
+
y: number;
|
|
1717
|
+
width: number;
|
|
1718
|
+
height: number;
|
|
1719
|
+
top: number;
|
|
1720
|
+
left: number;
|
|
1721
|
+
right: number;
|
|
1722
|
+
bottom: number;
|
|
433
1723
|
}
|
|
434
1724
|
interface StyleComparison {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
1725
|
+
property: string;
|
|
1726
|
+
expected: string;
|
|
1727
|
+
actual: string;
|
|
1728
|
+
matches: boolean;
|
|
439
1729
|
}
|
|
440
1730
|
interface TimingResult {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
1731
|
+
startTime: number;
|
|
1732
|
+
endTime: number;
|
|
1733
|
+
expectedDuration: number;
|
|
1734
|
+
actualDuration: number;
|
|
1735
|
+
deviation: number;
|
|
1736
|
+
deviationPercent: number;
|
|
447
1737
|
}
|
|
448
1738
|
interface AnimationTimer {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
1739
|
+
start: number;
|
|
1740
|
+
expectedDuration: number;
|
|
1741
|
+
end: () => TimingResult;
|
|
452
1742
|
}
|
|
453
1743
|
/**
|
|
454
1744
|
* Capture relevant computed styles from an element
|
|
@@ -471,10 +1761,10 @@ declare function capturePositionForLog(el: HTMLElement): Record<string, number>;
|
|
|
471
1761
|
* Calculate delta between two positions
|
|
472
1762
|
*/
|
|
473
1763
|
declare function calculatePositionDelta(before: PositionCapture, after: PositionCapture): {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
1764
|
+
deltaX: number;
|
|
1765
|
+
deltaY: number;
|
|
1766
|
+
deltaWidth: number;
|
|
1767
|
+
deltaHeight: number;
|
|
478
1768
|
};
|
|
479
1769
|
/**
|
|
480
1770
|
* Compare expected styles vs actual computed styles
|
|
@@ -498,5 +1788,6 @@ declare function captureAnimationInfo(animation: Animation): Record<string, unkn
|
|
|
498
1788
|
* Capture all active animations on an element
|
|
499
1789
|
*/
|
|
500
1790
|
declare function captureElementAnimations(el: HTMLElement): Record<string, unknown>[];
|
|
501
|
-
|
|
502
|
-
export { ANIMATION_CONFIGS, ANIMATION_DEFAULTS, AnimatedTokens, type AnimatedTokensProps, type
|
|
1791
|
+
//#endregion
|
|
1792
|
+
export { ANIMATION_CONFIGS, ANIMATION_DEFAULTS, AnimatedTokens, type AnimatedTokensProps, AnimatedTokensV2, AnimatedTokensV2 as TextFlow, type AnimatedTokensV2Props, type AnimatedTokensV2Props as TextFlowProps, type AnimationData, AnimationEvent, AnimationOrchestratorAPI, AnimationOrchestratorConfig, AnimationPhase, type AnimationTimer, AnimationTiming, type CSSGridMorphAPI, type CSSGridMorphOptions, CSS_VAR_NAMES, CSS_VAR_VALUES, type DebugEvent, type DebugEventType, DebugProvider, type DurationConfig, EASINGS, EFFECTS, ElementRegistryAPI, ElementRegistryCallbacks, EnterOptions, ExitOptions, ExitPositionStrategy, FLIPAnimationAPI, FLIPAnimationOptions, FLIPBehavior, type FLIPClipPathAPI, type FLIPClipPathOptions, FLIPDelta, type FormatOptions, type ListFormatStyle, type ListFormatType, type ListPart, Morph, MorphContext, type MorphContextValue, type MorphProps, type MorphTechnique, OrchestratorState, PRESETS, type PositionCapture, PositionCaptureAPI, PositionCaptureOptions, type PositionData, PositionRect, RESPONSIVE_CONFIGS, ReorderRoot as Reorder, type ReorderContextValue, type ReorderItemProps, type ReorderItemState, type ReorderLayout, type ReorderProps, SlidingNumber, type SlidingNumberProps, SlidingText, type SlidingTextProps, type StaggerConfig, type StyleCapture, type StyleComparison, type StyleData, TIMING, TRANSFORMS, type TimingData, type TimingResult, type Token, type UseListFormatOptions, type UseMorphOptions, type UseMorphReturn, type UseReorderConfig, type UseReorderPresenceConfig, type UseReorderPresenceReturn, type UseReorderReturn, type ViewTransitionsAPI, type ViewTransitionsOptions, animatedTokensBaseStyles, animatedTokensStyles, calculatePositionDelta, captureAnimationInfo, captureComputedStyles, captureElementAnimations, capturePosition, capturePositionForLog, captureStylesForLog, choreographyTracker, compareStyles, createAnimationTimer, cssVar, formatTimingResult, generateCSSVariables, generateResponsiveCSS, getResponsiveAnimatedTokensStyle, getResponsiveDuration, getResponsiveSlidingTextStyle, getResponsiveStagger, getResponsiveTokenStyles, getSlidingTextTokenStyle, injectCSSVariables, reinjectCSSVariables, removeCSSVariables, responsiveOverrides, slidingTextBaseStyles, slidingTextStyles, useAnimationOrchestrator, useCSSGridMorph, useDebug, useElementRegistry, useFLIPAnimation, useFLIPClipPath, useListFormat, useMorph, useMorphContext, usePositionCapture, useReorder, useReorderPresence, useViewTransitions, useWAAPIAnimations };
|
|
1793
|
+
//# sourceMappingURL=index.d.ts.map
|