@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/dist/index.d.ts CHANGED
@@ -1,85 +1,1448 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import React from 'react';
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
- style?: "decimal" | "currency" | "percent";
6
- currency?: string;
7
- locale?: string;
8
- minimumFractionDigits?: number;
9
- maximumFractionDigits?: number;
10
- useGrouping?: boolean;
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
- value: number;
14
- duration?: number;
15
- fontSize?: string;
16
- fontWeight?: string;
17
- color?: string;
18
- digitHeight?: number;
19
- stagger?: number;
20
- motionBlur?: boolean;
21
- format?: FormatOptions;
22
- trend?: -1 | 0 | 1;
23
- animationConfig?: {
24
- overshoot?: number;
25
- mass?: number;
26
- stiffness?: number;
27
- };
28
- }
29
- declare function SlidingNumber({ value, duration, fontSize, fontWeight, color, digitHeight, stagger, motionBlur, format, trend, animationConfig, }: SlidingNumberProps): react_jsx_runtime.JSX.Element;
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
- text: string;
33
- mode?: 'word' | 'character' | 'none';
34
- direction?: 'vertical' | 'horizontal';
35
- staggerDelay?: number;
36
- duration?: number;
37
- easing?: string;
38
- blur?: boolean;
39
- widthAnimation?: boolean;
40
- initial?: 'initial' | false;
41
- animate?: 'animate';
42
- exit?: 'exit';
43
- onAnimationComplete?: () => void;
44
- className?: string;
45
- style?: React.CSSProperties;
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
- id: string;
51
- text: string;
84
+ id: string;
85
+ text: string;
52
86
  }
53
87
  interface AnimatedTokensProps {
54
- tokens: Token[];
55
- placeholder?: string;
56
- maxVisible?: number;
57
- textAnimationMode?: 'character' | 'word';
58
- textDirection?: 'vertical' | 'horizontal';
59
- textStaggerDelay?: number;
60
- separator?: string;
61
- enableWidthAnimation?: boolean;
62
- className?: string;
63
- tokenClassName?: string;
64
- placeholderClassName?: string;
65
- separatorClassName?: string;
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
- onComplete: (id: string) => void;
71
- exitDuration?: number;
72
- flipDuration?: number;
73
- exitEasing?: string;
74
- flipEasing?: string;
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
- registerElement: (id: string, el: HTMLElement | null) => void;
78
- startExit: (id: string) => Promise<void>;
79
- isAnimating: (id?: string) => boolean;
80
- cancelAnimations: (id: string) => void;
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
- readonly ENTER_DURATION: 200;
97
- readonly EXIT_DURATION: 180;
98
- readonly COLLAPSE_DURATION: 200;
99
- readonly FLIP_DURATION: 300;
100
- readonly ENTER_STAGGER: 15;
101
- readonly EXIT_STAGGER: 0;
102
- readonly COLLAPSE_DELAY: 30;
103
- readonly FLIP_DELAY_PERCENT: 0.25;
104
- readonly MIN_DELTA_PX: 1;
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
- readonly OFFSET_Y_ENTER: 8;
108
- readonly OFFSET_Y_EXIT: -8;
109
- readonly OFFSET_X: 16;
110
- readonly SCALE_EXIT: 0.95;
111
- readonly ROTATE_EXIT: 0;
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
- readonly BLUR_ENTER: 4;
115
- readonly BLUR_EXIT: 2;
1478
+ readonly BLUR_ENTER: 4;
1479
+ readonly BLUR_EXIT: 2;
116
1480
  };
117
1481
  declare const EASINGS: {
118
- readonly EASE_OUT_CUBIC: "cubic-bezier(0.33, 1, 0.68, 1)";
119
- readonly EASE_IN_CUBIC: "cubic-bezier(0.32, 0, 0.67, 0)";
120
- readonly EASE_IN_OUT: "cubic-bezier(0.42, 0, 0.58, 1)";
121
- readonly EASE_OUT_EXPO: "cubic-bezier(0.16, 1, 0.3, 1)";
122
- readonly EASE_FLIP: "cubic-bezier(0.2, 0, 0.2, 1)";
123
- 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)";
124
- 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)";
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
- readonly tokenEnter: {
131
- readonly duration: number;
132
- readonly stagger: number;
133
- readonly easing: "cubic-bezier(0.33, 1, 0.68, 1)";
134
- readonly blur: 4;
135
- readonly offsetY: 8;
136
- };
137
- readonly tokenExit: {
138
- readonly duration: number;
139
- readonly stagger: number;
140
- readonly easing: "cubic-bezier(0.32, 0, 0.67, 0)";
141
- readonly blur: 2;
142
- readonly offsetY: -8;
143
- readonly scale: 0.95;
144
- };
145
- readonly collapse: {
146
- readonly duration: number;
147
- readonly delay: 30;
148
- readonly easing: "cubic-bezier(0.42, 0, 0.58, 1)";
149
- };
150
- readonly flip: {
151
- readonly duration: number;
152
- readonly delayPercent: 0.25;
153
- readonly 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)";
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
- DURATION_ENTER: 200;
158
- DURATION_EXIT: 180;
159
- DURATION_FLIP: 300;
160
- STAGGER_DELAY: 15;
161
- OFFSET_VERTICAL: 8;
162
- OFFSET_HORIZONTAL: 16;
163
- BLUR_AMOUNT: 4;
164
- EASING_ENTER: "cubic-bezier(0.33, 1, 0.68, 1)";
165
- EASING_EXIT: "cubic-bezier(0.32, 0, 0.67, 0)";
166
- 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)";
167
- 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)";
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
- readonly tokenEnter: {
171
- readonly duration: 200;
172
- readonly stagger: 15;
173
- readonly easing: "cubic-bezier(0.33, 1, 0.68, 1)";
174
- readonly blur: 4;
175
- readonly offsetY: 8;
176
- };
177
- readonly tokenExit: {
178
- readonly duration: 180;
179
- readonly stagger: 0;
180
- readonly easing: "cubic-bezier(0.32, 0, 0.67, 0)";
181
- readonly blur: 2;
182
- readonly offsetY: -8;
183
- readonly scale: 0.95;
184
- };
185
- readonly collapse: {
186
- readonly duration: 200;
187
- readonly delay: 30;
188
- readonly easing: "cubic-bezier(0.42, 0, 0.58, 1)";
189
- };
190
- readonly flip: {
191
- readonly duration: 300;
192
- readonly delayPercent: 0.25;
193
- readonly 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)";
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
- newToken: {
198
- mode: "character";
199
- direction: "vertical";
200
- staggerDelay: number;
201
- blur: boolean;
202
- widthAnimation: boolean;
203
- duration: number;
204
- initial: "initial";
205
- };
206
- existingToken: {
207
- mode: "none";
208
- blur: boolean;
209
- widthAnimation: boolean;
210
- initial: false;
211
- };
212
- placeholder: {
213
- mode: "word";
214
- direction: "vertical";
215
- blur: boolean;
216
- widthAnimation: boolean;
217
- duration: number;
218
- };
219
- separator: {
220
- duration: number;
221
- widthAnimation: boolean;
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
- readonly container: React.CSSProperties;
227
- readonly content: React.CSSProperties;
228
- readonly token: React.CSSProperties;
229
- readonly enterFrom: React.CSSProperties;
230
- readonly enterTo: React.CSSProperties;
231
- readonly exitActive: React.CSSProperties;
232
- readonly verticalEnterFrom: React.CSSProperties;
233
- readonly verticalExitActive: React.CSSProperties;
234
- readonly horizontalEnterFrom: React.CSSProperties;
235
- readonly horizontalExitActive: React.CSSProperties;
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
- readonly container: React.CSSProperties;
241
- readonly placeholder: React.CSSProperties;
242
- readonly tokenWrapper: React.CSSProperties;
243
- readonly tokenWrapperLast: React.CSSProperties;
244
- readonly tokenWrapperExitCompleted: React.CSSProperties;
245
- readonly separator: React.CSSProperties;
246
- readonly separatorExitActive: React.CSSProperties;
247
- readonly overflow: React.CSSProperties;
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
- interface TimingData {
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
- opacity: string;
414
- transform: string;
415
- filter: string;
416
- width: string;
417
- height: string;
418
- marginRight: string;
419
- marginLeft: string;
420
- position: string;
421
- visibility: string;
422
- pointerEvents: string;
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
- x: number;
426
- y: number;
427
- width: number;
428
- height: number;
429
- top: number;
430
- left: number;
431
- right: number;
432
- bottom: number;
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
- property: string;
436
- expected: string;
437
- actual: string;
438
- matches: boolean;
1725
+ property: string;
1726
+ expected: string;
1727
+ actual: string;
1728
+ matches: boolean;
439
1729
  }
440
1730
  interface TimingResult {
441
- startTime: number;
442
- endTime: number;
443
- expectedDuration: number;
444
- actualDuration: number;
445
- deviation: number;
446
- deviationPercent: number;
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
- start: number;
450
- expectedDuration: number;
451
- end: () => TimingResult;
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
- deltaX: number;
475
- deltaY: number;
476
- deltaWidth: number;
477
- deltaHeight: number;
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 AnimationData, type AnimationInfo, type AnimationTimer, type ChoreographySummary, ChoreographyTrackerClass, type DebugEvent, type DebugEventType, DebugProvider, EASINGS, EFFECTS, type FormatOptions, type OverlapInfo, PRESETS, type PositionCapture, type PositionData, RESPONSIVE_CONFIGS, SlidingNumber, type SlidingNumberProps, SlidingText, type SlidingTextProps, type StyleCapture, type StyleComparison, type StyleData, TIMING, TRANSFORMS, type TimelineEvent, type TimingData, type TimingResult, type Token, animatedTokensStyles, calculatePositionDelta, captureAnimationInfo, captureComputedStyles, captureElementAnimations, capturePosition, capturePositionForLog, captureStylesForLog, choreographyTracker, compareStyles, createAnimationTimer, formatTimingResult, getResponsiveAnimatedTokensStyle, getResponsiveDuration, getResponsiveStagger, getSlidingTextTokenStyle, slidingTextStyles, useDebug, useWAAPIAnimations };
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