@aphrody/m3-motion 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,754 @@
1
+ 'use client';
2
+ import * as React5 from 'react';
3
+ import { motion, AnimatePresence, useAnimate } from 'motion/react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/springs.ts
7
+ var m3Springs = {
8
+ fast: {
9
+ spatial: {
10
+ type: "spring",
11
+ stiffness: 400,
12
+ damping: 24,
13
+ mass: 0.8
14
+ },
15
+ effects: {
16
+ type: "spring",
17
+ stiffness: 350,
18
+ damping: 37,
19
+ mass: 0.8
20
+ }
21
+ },
22
+ default: {
23
+ spatial: {
24
+ type: "spring",
25
+ stiffness: 220,
26
+ damping: 17,
27
+ mass: 1
28
+ },
29
+ effects: {
30
+ type: "spring",
31
+ stiffness: 180,
32
+ damping: 26,
33
+ mass: 1
34
+ }
35
+ },
36
+ slow: {
37
+ spatial: {
38
+ type: "spring",
39
+ stiffness: 80,
40
+ damping: 12,
41
+ mass: 1.2
42
+ },
43
+ effects: {
44
+ type: "spring",
45
+ stiffness: 70,
46
+ damping: 16,
47
+ mass: 1.2
48
+ }
49
+ }
50
+ };
51
+
52
+ // src/easings.ts
53
+ var m3Easings = {
54
+ /** Closest single-bezier approximation. Use emphasizedDecelerate/Accelerate for transitions. */
55
+ emphasized: [0.2, 0, 0, 1],
56
+ emphasizedDecelerate: [0.05, 0.7, 0.1, 1],
57
+ emphasizedAccelerate: [0.3, 0, 0.8, 0.15],
58
+ standard: [0.2, 0, 0, 1],
59
+ standardDecelerate: [0, 0, 0, 1],
60
+ standardAccelerate: [0.3, 0, 1, 1],
61
+ linear: [0, 0, 1, 1],
62
+ /** Legacy (M2 default) — kept for migration compatibility. */
63
+ legacy: [0.4, 0, 0.2, 1],
64
+ legacyDecelerate: [0, 0, 0.2, 1],
65
+ legacyAccelerate: [0.4, 0, 1, 1]
66
+ };
67
+ var m3Durations = {
68
+ short1: 0.05,
69
+ short2: 0.1,
70
+ short3: 0.15,
71
+ short4: 0.2,
72
+ medium1: 0.25,
73
+ medium2: 0.3,
74
+ medium3: 0.35,
75
+ medium4: 0.4,
76
+ long1: 0.45,
77
+ long2: 0.5,
78
+ long3: 0.55,
79
+ long4: 0.6,
80
+ extraLong1: 0.7,
81
+ extraLong2: 0.8,
82
+ extraLong3: 0.9,
83
+ extraLong4: 1
84
+ };
85
+
86
+ // src/spring-interpolation.ts
87
+ var MIN_DURATION_MS = 50;
88
+ var MAX_DURATION_MS = 2e3;
89
+ var SETTLE_THRESHOLD = 5e-3;
90
+ var DEFAULT_MASS = 1;
91
+ var DEFAULT_STEPS = 60;
92
+ function clamp(value, min, max) {
93
+ if (value < min) return min;
94
+ if (value > max) return max;
95
+ return value;
96
+ }
97
+ function normalize(params) {
98
+ const m = params.mass != null && params.mass > 0 ? params.mass : DEFAULT_MASS;
99
+ const k = params.stiffness > 0 ? params.stiffness : 1;
100
+ const c = params.damping >= 0 ? params.damping : 0;
101
+ return { k, c, m };
102
+ }
103
+ function naturalFrequency(k, m) {
104
+ return Math.sqrt(k / m);
105
+ }
106
+ function dampingRatio(k, c, m) {
107
+ const denom = 2 * Math.sqrt(k * m);
108
+ return denom > 0 ? c / denom : 0;
109
+ }
110
+ function springDurationMs(params) {
111
+ const { k, c, m } = normalize(params);
112
+ const w0 = naturalFrequency(k, m);
113
+ const zeta = dampingRatio(k, c, m);
114
+ let decayRate;
115
+ if (zeta > 1) {
116
+ const root = Math.sqrt(zeta * zeta - 1);
117
+ decayRate = w0 * (zeta - root);
118
+ } else {
119
+ decayRate = zeta * w0;
120
+ }
121
+ if (!(decayRate > 0) || !Number.isFinite(decayRate)) {
122
+ return MAX_DURATION_MS;
123
+ }
124
+ const settleSeconds = -Math.log(SETTLE_THRESHOLD) / decayRate;
125
+ const settleMs = settleSeconds * 1e3;
126
+ return clamp(settleMs, MIN_DURATION_MS, MAX_DURATION_MS);
127
+ }
128
+ function springToCssEasing(params) {
129
+ const { k, c, m } = normalize(params);
130
+ const zeta = dampingRatio(k, c, m);
131
+ if (zeta < 0.85) {
132
+ const [x12, y12, x22, y22] = [0.05, 0.7, 0.1, 1];
133
+ return `cubic-bezier(${x12}, ${y12}, ${x22}, ${y22})`;
134
+ }
135
+ const t = clamp((zeta - 0.85) / (1.6 - 0.85), 0, 1);
136
+ const x1 = lerp(0.1, 0, t);
137
+ const y1 = lerp(0.65, 0, t);
138
+ const x2 = lerp(0.2, 0, t);
139
+ const y2 = 1;
140
+ return `cubic-bezier(${round(x1)}, ${round(y1)}, ${round(x2)}, ${round(y2)})`;
141
+ }
142
+ function lerp(a, b, t) {
143
+ return a + (b - a) * t;
144
+ }
145
+ function round(n) {
146
+ return Math.round(n * 1e3) / 1e3;
147
+ }
148
+ function springPosition(t, w0, zeta) {
149
+ if (t <= 0) return 0;
150
+ if (zeta < 1 - 1e-6) {
151
+ const wd = w0 * Math.sqrt(1 - zeta * zeta);
152
+ const envelope = Math.exp(-zeta * w0 * t);
153
+ const osc = Math.cos(wd * t) + zeta * w0 / wd * Math.sin(wd * t);
154
+ return 1 - envelope * osc;
155
+ }
156
+ if (zeta <= 1 + 1e-6) {
157
+ const envelope = Math.exp(-w0 * t);
158
+ return 1 - envelope * (1 + w0 * t);
159
+ }
160
+ const root = Math.sqrt(zeta * zeta - 1);
161
+ const s1 = -w0 * (zeta - root);
162
+ const s2 = -w0 * (zeta + root);
163
+ const e1 = Math.exp(s1 * t);
164
+ const e2 = Math.exp(s2 * t);
165
+ return 1 - (s2 * e1 - s1 * e2) / (s2 - s1);
166
+ }
167
+ function springToWaapiKeyframes(params, opts) {
168
+ const { k, c, m } = normalize(params);
169
+ const w0 = naturalFrequency(k, m);
170
+ const zeta = dampingRatio(k, c, m);
171
+ const steps = Math.max(2, Math.floor(opts?.steps ?? DEFAULT_STEPS));
172
+ const from = opts?.from ?? 0;
173
+ const to = opts?.to ?? 1;
174
+ const span = to - from;
175
+ const duration = springDurationMs(params);
176
+ const durationSeconds = duration / 1e3;
177
+ const samples = [];
178
+ for (let i = 0; i < steps; i++) {
179
+ const offset = i / (steps - 1);
180
+ let value;
181
+ if (i === 0) {
182
+ value = from;
183
+ } else if (i === steps - 1) {
184
+ value = to;
185
+ } else {
186
+ const t = offset * durationSeconds;
187
+ const progress = springPosition(t, w0, zeta);
188
+ value = from + span * progress;
189
+ }
190
+ samples.push({ offset, value });
191
+ }
192
+ const keyframes = opts?.property ? buildKeyframes(samples, opts.property, opts.format, opts.unit) : samples.map((s) => ({ offset: s.offset }));
193
+ return {
194
+ samples,
195
+ keyframes,
196
+ // Easing is linear: the spring's shape is encoded in the samples
197
+ // themselves, so the browser must interpolate them at constant rate.
198
+ options: { duration, easing: "linear" }
199
+ };
200
+ }
201
+ function springKeyframesForProperty(samples, property, format, unit) {
202
+ return buildKeyframes(samples, property, format, unit);
203
+ }
204
+ function buildKeyframes(samples, property, format, unit) {
205
+ const suffix = unit ?? "";
206
+ return samples.map((s) => {
207
+ const css = format ? format(s.value) : `${s.value}${suffix}`;
208
+ return { offset: s.offset, [property]: css };
209
+ });
210
+ }
211
+ function springFromPreset(preset) {
212
+ return {
213
+ stiffness: preset.stiffness != null && preset.stiffness > 0 ? preset.stiffness : 220,
214
+ damping: preset.damping != null && preset.damping >= 0 ? preset.damping : 17,
215
+ mass: preset.mass != null && preset.mass > 0 ? preset.mass : DEFAULT_MASS
216
+ };
217
+ }
218
+ var M3Fade = React5.forwardRef(
219
+ ({ in: inProp, appear = true, children, ...props }, ref) => {
220
+ const variants = {
221
+ initial: { opacity: 0 },
222
+ animate: {
223
+ opacity: 1,
224
+ transition: {
225
+ ease: m3Easings.emphasizedDecelerate,
226
+ duration: m3Durations.medium2
227
+ }
228
+ },
229
+ exit: {
230
+ opacity: 0,
231
+ transition: {
232
+ ease: m3Easings.emphasizedAccelerate,
233
+ duration: m3Durations.short4
234
+ }
235
+ }
236
+ };
237
+ const content = /* @__PURE__ */ jsx(
238
+ motion.div,
239
+ {
240
+ ref,
241
+ variants,
242
+ initial: appear ? "initial" : false,
243
+ animate: "animate",
244
+ exit: "exit",
245
+ style: { willChange: "opacity" },
246
+ ...props,
247
+ children
248
+ }
249
+ );
250
+ if (inProp !== void 0) {
251
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: inProp ? content : null });
252
+ }
253
+ return content;
254
+ }
255
+ );
256
+ M3Fade.displayName = "M3Fade";
257
+ var M3SharedAxis = React5.forwardRef(
258
+ ({ in: inProp, axis = "x", forward = true, appear = true, transition: customTransition, variants: customVariants, children, ...props }, ref) => {
259
+ const translateOffset = 30;
260
+ const scaleOffset = 0.08;
261
+ const defaultVariants = {
262
+ initial: {
263
+ opacity: 0,
264
+ x: axis === "x" ? forward ? translateOffset : -translateOffset : 0,
265
+ y: axis === "y" ? forward ? translateOffset : -translateOffset : 0,
266
+ scale: axis === "z" ? forward ? 1 - scaleOffset : 1 + scaleOffset : 1
267
+ },
268
+ animate: {
269
+ opacity: 1,
270
+ x: 0,
271
+ y: 0,
272
+ scale: 1,
273
+ transition: customTransition || {
274
+ x: { ease: m3Easings.emphasizedDecelerate, duration: m3Durations.medium2 },
275
+ y: { ease: m3Easings.emphasizedDecelerate, duration: m3Durations.medium2 },
276
+ scale: { ease: m3Easings.emphasizedDecelerate, duration: m3Durations.medium2 },
277
+ opacity: { ease: m3Easings.standard, duration: m3Durations.medium2 }
278
+ }
279
+ },
280
+ exit: {
281
+ opacity: 0,
282
+ x: axis === "x" ? forward ? -translateOffset : translateOffset : 0,
283
+ y: axis === "y" ? forward ? -translateOffset : translateOffset : 0,
284
+ scale: axis === "z" ? forward ? 1 + scaleOffset : 1 - scaleOffset : 1,
285
+ transition: customTransition || {
286
+ x: { ease: m3Easings.emphasizedAccelerate, duration: m3Durations.short4 },
287
+ y: { ease: m3Easings.emphasizedAccelerate, duration: m3Durations.short4 },
288
+ scale: { ease: m3Easings.emphasizedAccelerate, duration: m3Durations.short4 },
289
+ opacity: { ease: m3Easings.standard, duration: m3Durations.short4 }
290
+ }
291
+ }
292
+ };
293
+ const resolvedVariants = customVariants || defaultVariants;
294
+ const content = /* @__PURE__ */ jsx(
295
+ motion.div,
296
+ {
297
+ ref,
298
+ variants: resolvedVariants,
299
+ initial: appear ? "initial" : false,
300
+ animate: "animate",
301
+ exit: "exit",
302
+ style: { willChange: "opacity, transform" },
303
+ ...props,
304
+ children
305
+ }
306
+ );
307
+ if (inProp !== void 0) {
308
+ return /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: inProp ? content : null });
309
+ }
310
+ return content;
311
+ }
312
+ );
313
+ M3SharedAxis.displayName = "M3SharedAxis";
314
+ var M3FadeThrough = ({ stateKey, transition: customTransition, variants: customVariants, children, ...props }) => {
315
+ const defaultVariants = {
316
+ initial: {
317
+ opacity: 0,
318
+ scale: 0.92
319
+ },
320
+ animate: {
321
+ opacity: 1,
322
+ scale: 1,
323
+ transition: customTransition || {
324
+ opacity: {
325
+ ease: m3Easings.emphasizedDecelerate,
326
+ duration: 0.21
327
+ },
328
+ scale: {
329
+ ease: m3Easings.emphasizedDecelerate,
330
+ duration: 0.21
331
+ }
332
+ }
333
+ },
334
+ exit: {
335
+ opacity: 0,
336
+ transition: customTransition || {
337
+ opacity: {
338
+ ease: m3Easings.emphasizedAccelerate,
339
+ duration: 0.09
340
+ }
341
+ }
342
+ }
343
+ };
344
+ const resolvedVariants = customVariants || defaultVariants;
345
+ return /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
346
+ motion.div,
347
+ {
348
+ variants: resolvedVariants,
349
+ initial: "initial",
350
+ animate: "animate",
351
+ exit: "exit",
352
+ style: { willChange: "opacity, transform" },
353
+ ...props,
354
+ children
355
+ },
356
+ stateKey
357
+ ) });
358
+ };
359
+ M3FadeThrough.displayName = "M3FadeThrough";
360
+ var M3Collapse = React5.forwardRef(
361
+ ({ in: inProp, appear = false, children, ...props }, ref) => {
362
+ const variants = {
363
+ initial: { height: 0, opacity: 0 },
364
+ animate: {
365
+ height: "auto",
366
+ opacity: 1,
367
+ transition: {
368
+ height: {
369
+ ease: m3Easings.emphasized,
370
+ duration: m3Durations.medium4
371
+ },
372
+ opacity: {
373
+ ease: m3Easings.standard,
374
+ duration: m3Durations.medium2
375
+ }
376
+ }
377
+ },
378
+ exit: {
379
+ height: 0,
380
+ opacity: 0,
381
+ transition: {
382
+ height: {
383
+ ease: m3Easings.emphasized,
384
+ duration: m3Durations.medium4
385
+ },
386
+ opacity: {
387
+ ease: m3Easings.standard,
388
+ duration: m3Durations.medium2
389
+ }
390
+ }
391
+ }
392
+ };
393
+ const content = /* @__PURE__ */ jsx(
394
+ motion.div,
395
+ {
396
+ ref,
397
+ variants,
398
+ initial: appear ? "initial" : false,
399
+ animate: "animate",
400
+ exit: "exit",
401
+ style: { overflow: "hidden", willChange: "height, opacity" },
402
+ ...props,
403
+ children
404
+ }
405
+ );
406
+ if (inProp !== void 0) {
407
+ return /* @__PURE__ */ jsx(AnimatePresence, { initial: appear, children: inProp ? content : null });
408
+ }
409
+ return content;
410
+ }
411
+ );
412
+ M3Collapse.displayName = "M3Collapse";
413
+ var M3ContainerTransformContext = React5.createContext(null);
414
+ function getDefaultTransition(isActive, speed) {
415
+ if (speed === "fast") {
416
+ return isActive ? { delay: 0.05, duration: 0.15, ease: m3Easings.emphasizedDecelerate } : { duration: 0.08, ease: m3Easings.emphasizedAccelerate };
417
+ }
418
+ if (speed === "slow") {
419
+ return isActive ? { delay: 0.2, duration: 0.6, ease: m3Easings.emphasizedDecelerate } : { duration: 0.25, ease: m3Easings.emphasizedAccelerate };
420
+ }
421
+ return isActive ? { delay: 0.1, duration: 0.35, ease: m3Easings.emphasizedDecelerate } : { duration: 0.15, ease: m3Easings.emphasizedAccelerate };
422
+ }
423
+ var M3ContainerTransform = React5.forwardRef(
424
+ ({ layoutId, speed = "default", isExpanded = false, children, transition, style, ...props }, ref) => {
425
+ const springConfig = m3Springs[speed].spatial;
426
+ const contextValue = React5.useMemo(
427
+ () => ({ isExpanded, speed }),
428
+ [isExpanded, speed]
429
+ );
430
+ return /* @__PURE__ */ jsx(M3ContainerTransformContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
431
+ motion.div,
432
+ {
433
+ ref,
434
+ layoutId,
435
+ layout: true,
436
+ transition: transition || springConfig,
437
+ style: {
438
+ willChange: "transform, border-radius",
439
+ overflow: "hidden",
440
+ ...style
441
+ },
442
+ ...props,
443
+ children
444
+ }
445
+ ) });
446
+ }
447
+ );
448
+ M3ContainerTransform.displayName = "M3ContainerTransform";
449
+ var M3ContainerTransformStart = React5.forwardRef(
450
+ ({ active, children, style, transition, layout = "position", ...props }, ref) => {
451
+ const context = React5.useContext(M3ContainerTransformContext);
452
+ const isActive = active ?? (context ? !context.isExpanded : true);
453
+ const speed = context?.speed ?? "default";
454
+ const baseStyle = {
455
+ width: "100%",
456
+ height: "100%",
457
+ boxSizing: "border-box",
458
+ pointerEvents: isActive ? "auto" : "none",
459
+ ...!isActive && {
460
+ position: "absolute",
461
+ top: 0,
462
+ left: 0
463
+ },
464
+ ...style
465
+ };
466
+ const resolvedTransition = transition || getDefaultTransition(isActive, speed);
467
+ return /* @__PURE__ */ jsx(
468
+ motion.div,
469
+ {
470
+ ref,
471
+ layout,
472
+ animate: { opacity: isActive ? 1 : 0 },
473
+ transition: resolvedTransition,
474
+ style: baseStyle,
475
+ ...props,
476
+ children
477
+ }
478
+ );
479
+ }
480
+ );
481
+ M3ContainerTransformStart.displayName = "M3ContainerTransformStart";
482
+ var M3ContainerTransformEnd = React5.forwardRef(
483
+ ({ active, children, style, transition, layout = "position", ...props }, ref) => {
484
+ const context = React5.useContext(M3ContainerTransformContext);
485
+ const isActive = active ?? (context ? context.isExpanded : true);
486
+ const speed = context?.speed ?? "default";
487
+ const baseStyle = {
488
+ width: "100%",
489
+ height: "100%",
490
+ boxSizing: "border-box",
491
+ pointerEvents: isActive ? "auto" : "none",
492
+ ...!isActive && {
493
+ position: "absolute",
494
+ top: 0,
495
+ left: 0
496
+ },
497
+ ...style
498
+ };
499
+ const resolvedTransition = transition || getDefaultTransition(isActive, speed);
500
+ return /* @__PURE__ */ jsx(
501
+ motion.div,
502
+ {
503
+ ref,
504
+ layout,
505
+ initial: { opacity: 0 },
506
+ animate: { opacity: isActive ? 1 : 0 },
507
+ transition: resolvedTransition,
508
+ style: baseStyle,
509
+ ...props,
510
+ children
511
+ }
512
+ );
513
+ }
514
+ );
515
+ M3ContainerTransformEnd.displayName = "M3ContainerTransformEnd";
516
+ var OFFSET = 30;
517
+ var SCALE_OFFSET = 0.08;
518
+ function buildVariants(pattern, forward) {
519
+ const enterTransition = {
520
+ ease: m3Easings.emphasizedDecelerate,
521
+ duration: m3Durations.medium2
522
+ };
523
+ const exitTransition = {
524
+ ease: m3Easings.emphasizedAccelerate,
525
+ duration: m3Durations.short4
526
+ };
527
+ switch (pattern) {
528
+ case "fade-through":
529
+ return {
530
+ initial: { opacity: 0, scale: 0.92 },
531
+ animate: {
532
+ opacity: 1,
533
+ scale: 1,
534
+ transition: {
535
+ opacity: { ease: m3Easings.emphasizedDecelerate, duration: 0.21 },
536
+ scale: { ease: m3Easings.emphasizedDecelerate, duration: 0.21 }
537
+ }
538
+ },
539
+ exit: {
540
+ opacity: 0,
541
+ transition: { opacity: { ease: m3Easings.emphasizedAccelerate, duration: 0.09 } }
542
+ }
543
+ };
544
+ case "shared-axis-x":
545
+ return {
546
+ initial: { opacity: 0, x: forward ? OFFSET : -OFFSET },
547
+ animate: {
548
+ opacity: 1,
549
+ x: 0,
550
+ transition: {
551
+ x: enterTransition,
552
+ opacity: { ease: m3Easings.standard, duration: m3Durations.medium2 }
553
+ }
554
+ },
555
+ exit: {
556
+ opacity: 0,
557
+ x: forward ? -OFFSET : OFFSET,
558
+ transition: {
559
+ x: exitTransition,
560
+ opacity: { ease: m3Easings.standard, duration: m3Durations.short4 }
561
+ }
562
+ }
563
+ };
564
+ case "shared-axis-y":
565
+ return {
566
+ initial: { opacity: 0, y: forward ? OFFSET : -OFFSET },
567
+ animate: {
568
+ opacity: 1,
569
+ y: 0,
570
+ transition: {
571
+ y: enterTransition,
572
+ opacity: { ease: m3Easings.standard, duration: m3Durations.medium2 }
573
+ }
574
+ },
575
+ exit: {
576
+ opacity: 0,
577
+ y: forward ? -OFFSET : OFFSET,
578
+ transition: {
579
+ y: exitTransition,
580
+ opacity: { ease: m3Easings.standard, duration: m3Durations.short4 }
581
+ }
582
+ }
583
+ };
584
+ case "shared-axis-z":
585
+ return {
586
+ initial: { opacity: 0, scale: forward ? 1 - SCALE_OFFSET : 1 + SCALE_OFFSET },
587
+ animate: {
588
+ opacity: 1,
589
+ scale: 1,
590
+ transition: {
591
+ scale: enterTransition,
592
+ opacity: { ease: m3Easings.standard, duration: m3Durations.medium2 }
593
+ }
594
+ },
595
+ exit: {
596
+ opacity: 0,
597
+ scale: forward ? 1 + SCALE_OFFSET : 1 - SCALE_OFFSET,
598
+ transition: {
599
+ scale: exitTransition,
600
+ opacity: { ease: m3Easings.standard, duration: m3Durations.short4 }
601
+ }
602
+ }
603
+ };
604
+ case "collapse":
605
+ return {
606
+ initial: { height: 0, opacity: 0 },
607
+ animate: {
608
+ height: "auto",
609
+ opacity: 1,
610
+ transition: {
611
+ height: { ease: m3Easings.emphasized, duration: m3Durations.medium4 },
612
+ opacity: { ease: m3Easings.standard, duration: m3Durations.medium2 }
613
+ }
614
+ },
615
+ exit: {
616
+ height: 0,
617
+ opacity: 0,
618
+ transition: {
619
+ height: { ease: m3Easings.emphasized, duration: m3Durations.medium4 },
620
+ opacity: { ease: m3Easings.standard, duration: m3Durations.medium2 }
621
+ }
622
+ }
623
+ };
624
+ case "fade":
625
+ default:
626
+ return {
627
+ initial: { opacity: 0 },
628
+ animate: { opacity: 1, transition: enterTransition },
629
+ exit: { opacity: 0, transition: exitTransition }
630
+ };
631
+ }
632
+ }
633
+ var M3Transition = React5.forwardRef(
634
+ ({
635
+ stateKey,
636
+ pattern = "fade",
637
+ forward = true,
638
+ mode = "wait",
639
+ variants,
640
+ children,
641
+ style,
642
+ ...props
643
+ }, ref) => {
644
+ const resolvedVariants = variants ?? buildVariants(pattern, forward);
645
+ const baseStyle = pattern === "collapse" ? { overflow: "hidden" } : { willChange: "opacity, transform" };
646
+ const resolvedStyle = { ...baseStyle, ...style };
647
+ return /* @__PURE__ */ jsx(AnimatePresence, { mode, children: /* @__PURE__ */ jsx(
648
+ motion.div,
649
+ {
650
+ ref,
651
+ variants: resolvedVariants,
652
+ initial: "initial",
653
+ animate: "animate",
654
+ exit: "exit",
655
+ style: resolvedStyle,
656
+ ...props,
657
+ children
658
+ },
659
+ stateKey
660
+ ) });
661
+ }
662
+ );
663
+ M3Transition.displayName = "M3Transition";
664
+ var containerVariants = {
665
+ hidden: {},
666
+ visible: (_custom) => ({
667
+ transition: {
668
+ staggerChildren: _custom.staggerDelay,
669
+ delayChildren: _custom.delayChildren
670
+ }
671
+ }),
672
+ exit: {}
673
+ };
674
+ var itemVariants = {
675
+ hidden: { opacity: 0, y: 8 },
676
+ visible: {
677
+ opacity: 1,
678
+ y: 0,
679
+ transition: {
680
+ ease: m3Easings.emphasizedDecelerate,
681
+ duration: m3Durations.medium2
682
+ }
683
+ },
684
+ exit: {
685
+ opacity: 0,
686
+ y: 4,
687
+ transition: {
688
+ ease: m3Easings.emphasizedAccelerate,
689
+ duration: m3Durations.short3
690
+ }
691
+ }
692
+ };
693
+ var M3ListStagger = React5.forwardRef(
694
+ ({ staggerDelay = 0.05, delayChildren = 0, appear = true, children, className, style }, ref) => {
695
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(
696
+ motion.div,
697
+ {
698
+ ref,
699
+ className,
700
+ style,
701
+ variants: containerVariants,
702
+ initial: appear ? "hidden" : false,
703
+ animate: "visible",
704
+ exit: "exit",
705
+ custom: { staggerDelay, delayChildren },
706
+ children
707
+ }
708
+ ) });
709
+ }
710
+ );
711
+ M3ListStagger.displayName = "M3ListStagger";
712
+ var M3ListStaggerItem = React5.forwardRef(
713
+ ({ children, style, ...props }, ref) => {
714
+ return /* @__PURE__ */ jsx(
715
+ motion.div,
716
+ {
717
+ ref,
718
+ variants: itemVariants,
719
+ style: { willChange: "opacity, transform", ...style },
720
+ ...props,
721
+ children
722
+ }
723
+ );
724
+ }
725
+ );
726
+ M3ListStaggerItem.displayName = "M3ListStaggerItem";
727
+ function useM3Animate() {
728
+ const [scope, animate] = useAnimate();
729
+ const m3Animate = (elementOrSelector, keyframes, options) => {
730
+ if (Array.isArray(elementOrSelector)) {
731
+ return animate(
732
+ elementOrSelector,
733
+ keyframes
734
+ );
735
+ }
736
+ if (typeof elementOrSelector === "string" || elementOrSelector instanceof Element || typeof elementOrSelector === "object" && elementOrSelector !== null && "current" in elementOrSelector || typeof elementOrSelector === "number" || typeof elementOrSelector === "object" && elementOrSelector !== null && "get" in elementOrSelector) {
737
+ return animate(elementOrSelector, keyframes, {
738
+ ease: m3Easings.emphasized,
739
+ duration: m3Durations.medium2,
740
+ ...typeof options === "object" && options !== null ? options : {}
741
+ });
742
+ }
743
+ return animate(elementOrSelector, keyframes, {
744
+ ease: m3Easings.emphasized,
745
+ duration: m3Durations.medium2,
746
+ ...typeof options === "object" && options !== null ? options : {}
747
+ });
748
+ };
749
+ return [scope, m3Animate];
750
+ }
751
+
752
+ export { M3Collapse, M3ContainerTransform, M3ContainerTransformContext, M3ContainerTransformEnd, M3ContainerTransformStart, M3Fade, M3FadeThrough, M3ListStagger, M3ListStaggerItem, M3SharedAxis, M3Transition, m3Durations, m3Easings, m3Springs, springDurationMs, springFromPreset, springKeyframesForProperty, springToCssEasing, springToWaapiKeyframes, useM3Animate };
753
+ //# sourceMappingURL=index.js.map
754
+ //# sourceMappingURL=index.js.map