@bug-on/m3-expressive 1.3.5 → 1.3.6

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/forms.d.mts +2 -2
  3. package/dist/forms.d.ts +2 -2
  4. package/dist/forms.js +16 -6
  5. package/dist/forms.js.map +1 -1
  6. package/dist/forms.mjs +16 -6
  7. package/dist/forms.mjs.map +1 -1
  8. package/dist/index.d.mts +4 -4
  9. package/dist/index.d.ts +4 -4
  10. package/dist/index.js +722 -187
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +718 -188
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/{md3-expressive-shapes-CPcfl_Hf.d.mts → md3-expressive-shapes-wk_98LJh.d.mts} +20 -1
  15. package/dist/{md3-expressive-shapes-CPcfl_Hf.d.ts → md3-expressive-shapes-wk_98LJh.d.ts} +20 -1
  16. package/dist/navigation.d.mts +1 -1
  17. package/dist/navigation.d.ts +1 -1
  18. package/dist/navigation.js +73 -20
  19. package/dist/navigation.js.map +1 -1
  20. package/dist/navigation.mjs +73 -20
  21. package/dist/navigation.mjs.map +1 -1
  22. package/dist/overlays.d.mts +4 -2
  23. package/dist/overlays.d.ts +4 -2
  24. package/dist/overlays.js +84 -43
  25. package/dist/overlays.js.map +1 -1
  26. package/dist/overlays.mjs +84 -43
  27. package/dist/overlays.mjs.map +1 -1
  28. package/dist/pickers.js +88 -55
  29. package/dist/pickers.js.map +1 -1
  30. package/dist/pickers.mjs +88 -55
  31. package/dist/pickers.mjs.map +1 -1
  32. package/dist/shapes.d.mts +141 -15
  33. package/dist/shapes.d.ts +141 -15
  34. package/dist/shapes.js +618 -126
  35. package/dist/shapes.js.map +1 -1
  36. package/dist/shapes.mjs +614 -127
  37. package/dist/shapes.mjs.map +1 -1
  38. package/dist/{side-sheet-modal-64FGhDxL.d.mts → side-sheet-modal-BycxrabB.d.mts} +70 -0
  39. package/dist/{side-sheet-modal-Bd5Qqvp9.d.ts → side-sheet-modal-Cw4vemKx.d.ts} +70 -0
  40. package/dist/{text-field-4OlT9o8s.d.mts → text-field-B1fLh5Sh.d.mts} +22 -3
  41. package/dist/{text-field-DARNdj14.d.ts → text-field-C0VQLp8Y.d.ts} +22 -3
  42. package/llms-full.txt +7 -0
  43. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -310,6 +310,13 @@ function transformFeature(feature, fn) {
310
310
  }
311
311
  return edgeFeature(cubics);
312
312
  }
313
+ function reverseFeature(feature) {
314
+ const cubics = feature.cubics.slice().reverse().map((c) => c.reverse());
315
+ if (feature.type === "corner") {
316
+ return cornerFeature(cubics, feature.convex);
317
+ }
318
+ return edgeFeature(cubics);
319
+ }
313
320
 
314
321
  // src/shapes/math/corner-rounding.ts
315
322
  function cornerRounding(radius = 0, smoothing = 0) {
@@ -354,6 +361,10 @@ function convex(prevX, prevY, currX, currY, nextX, nextY) {
354
361
  const v2y = nextY - currY;
355
362
  return v1x * v2y - v1y * v2x > 0;
356
363
  }
364
+ function formatCoordinate(v) {
365
+ const rounded = Math.round(v * 1e4) / 1e4;
366
+ return (rounded === 0 ? 0 : rounded).toString();
367
+ }
357
368
 
358
369
  // src/shapes/math/point.ts
359
370
  function point(x, y) {
@@ -453,9 +464,16 @@ var Cubic = class _Cubic {
453
464
  */
454
465
  pointOnCurve(t) {
455
466
  const u = 1 - t;
467
+ const uu = u * u;
468
+ const tt = t * t;
469
+ const uuu = uu * u;
470
+ const ttt = tt * t;
471
+ const c0 = 3 * t * uu;
472
+ const c1 = 3 * tt * u;
473
+ const p = this.points;
456
474
  return point(
457
- this.anchor0X * (u * u * u) + this.control0X * (3 * t * u * u) + this.control1X * (3 * t * t * u) + this.anchor1X * (t * t * t),
458
- this.anchor0Y * (u * u * u) + this.control0Y * (3 * t * u * u) + this.control1Y * (3 * t * t * u) + this.anchor1Y * (t * t * t)
475
+ p[0] * uuu + p[2] * c0 + p[4] * c1 + p[6] * ttt,
476
+ p[1] * uuu + p[3] * c0 + p[5] * c1 + p[7] * ttt
459
477
  );
460
478
  }
461
479
  /**
@@ -678,13 +696,17 @@ var MutableCubic = class extends Cubic {
678
696
  * @param progress - Interpolation factor [0, 1]
679
697
  */
680
698
  interpolate(c1, c2, progress) {
681
- for (let i = 0; i < 8; i++) {
682
- this.points[i] = interpolate(
683
- c1.points[i],
684
- c2.points[i],
685
- progress
686
- );
687
- }
699
+ const p1 = c1.points;
700
+ const p2 = c2.points;
701
+ const p = this.points;
702
+ p[0] = p1[0] + (p2[0] - p1[0]) * progress;
703
+ p[1] = p1[1] + (p2[1] - p1[1]) * progress;
704
+ p[2] = p1[2] + (p2[2] - p1[2]) * progress;
705
+ p[3] = p1[3] + (p2[3] - p1[3]) * progress;
706
+ p[4] = p1[4] + (p2[4] - p1[4]) * progress;
707
+ p[5] = p1[5] + (p2[5] - p1[5]) * progress;
708
+ p[6] = p1[6] + (p2[6] - p1[6]) * progress;
709
+ p[7] = p1[7] + (p2[7] - p1[7]) * progress;
688
710
  }
689
711
  /**
690
712
  * Mutably applies a PointTransformer to all points.
@@ -1096,6 +1118,36 @@ var RoundedPolygon = class _RoundedPolygon {
1096
1118
  this.centerY + d
1097
1119
  ];
1098
1120
  }
1121
+ /**
1122
+ * Calculates the approximate signed area of the polygon using anchor points.
1123
+ * Returns > 0 for Clockwise (in screen coords, y down), < 0 for Counter-Clockwise.
1124
+ */
1125
+ calculateSignedArea() {
1126
+ let area = 0;
1127
+ const n = this.cubics.length;
1128
+ for (let i = 0; i < n; i++) {
1129
+ const c = this.cubics[i];
1130
+ area += c.anchor0X * c.anchor1Y - c.anchor1X * c.anchor0Y;
1131
+ }
1132
+ return area / 2;
1133
+ }
1134
+ /**
1135
+ * Returns true if the polygon outline runs in Clockwise order (screen coords).
1136
+ */
1137
+ isClockwise() {
1138
+ return this.calculateSignedArea() > 0;
1139
+ }
1140
+ /**
1141
+ * Returns a reversed copy of the polygon with reversed traversal order.
1142
+ * Flips the winding direction (CW ↔ CCW).
1143
+ */
1144
+ reversed() {
1145
+ const reversedFeatures = this.features.slice().reverse().map((f) => reverseFeature(f));
1146
+ return new _RoundedPolygon(
1147
+ reversedFeatures,
1148
+ point(this.centerX, this.centerY)
1149
+ );
1150
+ }
1099
1151
  };
1100
1152
  function buildCubicsList(features) {
1101
1153
  const result = [];
@@ -1164,10 +1216,21 @@ function validateContiguity(cubics) {
1164
1216
 
1165
1217
  // src/shapes/catalog/md3-expressive-shapes.ts
1166
1218
  function createShape(pts) {
1167
- const cubics = pts.map((p) => new Cubic(p));
1168
- return RoundedPolygon.fromFeatures(
1169
- cubics.map((c) => cornerFeature([c], false))
1170
- );
1219
+ let rawArea = 0;
1220
+ for (const p of pts) {
1221
+ rawArea += p[0] * p[7] - p[6] * p[1];
1222
+ }
1223
+ const normalizedPts = rawArea < 0 ? pts.slice().reverse().map((p) => [p[6], p[7], p[4], p[5], p[2], p[3], p[0], p[1]]) : pts;
1224
+ const cubics = normalizedPts.map((p) => new Cubic(p));
1225
+ const n = cubics.length;
1226
+ const features = cubics.map((c, i) => {
1227
+ const prev = cubics[(i - 1 + n) % n].pointOnCurve(0.5);
1228
+ const curr = c.pointOnCurve(0.5);
1229
+ const next = cubics[(i + 1) % n].pointOnCurve(0.5);
1230
+ const isConvex = convex(prev.x, prev.y, curr.x, curr.y, next.x, next.y);
1231
+ return cornerFeature([c], isConvex);
1232
+ });
1233
+ return RoundedPolygon.fromFeatures(features);
1171
1234
  }
1172
1235
  var archShape = createShape([
1173
1236
  [1, 0.83461, 1, 0.8547, 1, 0.86477, 0.99898, 0.87322],
@@ -2265,6 +2328,94 @@ function resolveShape(ref) {
2265
2328
  return shape;
2266
2329
  }
2267
2330
 
2331
+ // src/shapes/catalog/shape-pairings.ts
2332
+ var MD3_SHAPE_PAIRINGS = {
2333
+ // ─── Organic & Floral ──────────────────────────────────────────
2334
+ circle: "flower",
2335
+ flower: "sunny",
2336
+ sunny: "verySunny",
2337
+ verySunny: "flower",
2338
+ bun: "clamshell",
2339
+ clamshell: "bun",
2340
+ puffy: "circle",
2341
+ // ─── Starburst & Explosive ─────────────────────────────────────
2342
+ burst: "softBurst",
2343
+ softBurst: "boom",
2344
+ boom: "softBoom",
2345
+ softBoom: "burst",
2346
+ cookie12Sided: "softBurst",
2347
+ // ─── Clover, Gem & Diamond ─────────────────────────────────────
2348
+ diamond: "puffyDiamond",
2349
+ puffyDiamond: "diamond",
2350
+ clover4Leaf: "clover8Leaf",
2351
+ clover8Leaf: "clover4Leaf",
2352
+ gem: "diamond",
2353
+ heart: "clover4Leaf",
2354
+ // ─── Cookies & Geometric Multi-sided ───────────────────────────
2355
+ cookie4Sided: "cookie6Sided",
2356
+ cookie6Sided: "cookie9Sided",
2357
+ cookie7Sided: "cookie12Sided",
2358
+ cookie9Sided: "cookie7Sided",
2359
+ square: "cookie4Sided",
2360
+ // ─── Rounded & Architectural ───────────────────────────────────
2361
+ pill: "oval",
2362
+ oval: "arch",
2363
+ arch: "semiCircle",
2364
+ semiCircle: "pill",
2365
+ slanted: "arch",
2366
+ // ─── Polygonal, Directional & Pixel ────────────────────────────
2367
+ triangle: "arrow",
2368
+ arrow: "pentagon",
2369
+ pentagon: "triangle",
2370
+ fan: "ghostish",
2371
+ ghostish: "fan",
2372
+ pixelTriangle: "pixelCircle",
2373
+ pixelCircle: "circle"
2374
+ };
2375
+ var MD3_SHAPE_FAMILIES = {
2376
+ organic: [
2377
+ "circle",
2378
+ "flower",
2379
+ "sunny",
2380
+ "verySunny",
2381
+ "bun",
2382
+ "clamshell",
2383
+ "puffy"
2384
+ ],
2385
+ starburst: ["burst", "softBurst", "boom", "softBoom", "cookie12Sided"],
2386
+ cloverAndGems: [
2387
+ "diamond",
2388
+ "puffyDiamond",
2389
+ "clover4Leaf",
2390
+ "clover8Leaf",
2391
+ "gem",
2392
+ "heart"
2393
+ ],
2394
+ cookiesAndPolygons: [
2395
+ "cookie4Sided",
2396
+ "cookie6Sided",
2397
+ "cookie7Sided",
2398
+ "cookie9Sided",
2399
+ "square"
2400
+ ],
2401
+ roundedContainers: ["pill", "oval", "arch", "semiCircle", "slanted"],
2402
+ directionalAndPixel: [
2403
+ "triangle",
2404
+ "arrow",
2405
+ "pentagon",
2406
+ "fan",
2407
+ "ghostish",
2408
+ "pixelTriangle",
2409
+ "pixelCircle"
2410
+ ]
2411
+ };
2412
+ function getRecommendedMorphShape(shape) {
2413
+ if (typeof shape === "string" && shape in MD3_SHAPE_PAIRINGS) {
2414
+ return MD3_SHAPE_PAIRINGS[shape];
2415
+ }
2416
+ return "circle";
2417
+ }
2418
+
2268
2419
  // src/shapes/catalog/shape-tokens.ts
2269
2420
  var MD3CornerRadius = {
2270
2421
  /** 0dp — Sharp corners */
@@ -2430,6 +2581,56 @@ function pillStarVertices(width, height, numVerticesPerRadius, innerRadiusRatio,
2430
2581
  return result;
2431
2582
  }
2432
2583
 
2584
+ // src/shapes/morph/feature-mapping.ts
2585
+ function angleDiff(a1, a2) {
2586
+ let diff = Math.abs(a1 - a2);
2587
+ if (diff > Math.PI) diff = 2 * Math.PI - diff;
2588
+ return diff;
2589
+ }
2590
+ var TWO_PI_SQ = 4 * Math.PI * Math.PI;
2591
+ function featureMapper(features1, features2) {
2592
+ const convex1 = features1.filter((f) => f.convex);
2593
+ const convex2 = features2.filter((f) => f.convex);
2594
+ const set1 = convex1.length > 0 ? convex1 : features1;
2595
+ const set2 = convex2.length > 0 ? convex2 : features2;
2596
+ if (set1.length === 0 || set2.length === 0) {
2597
+ return { map: (v) => v, mapBack: (v) => v };
2598
+ }
2599
+ let bestShift = 0;
2600
+ let minCost = Number.MAX_VALUE;
2601
+ for (const f1 of set1) {
2602
+ for (const f2 of set2) {
2603
+ const shift = positiveModulo(f2.progress - f1.progress, 1);
2604
+ let cost = 0;
2605
+ for (const c1 of set1) {
2606
+ const expected = positiveModulo(c1.progress + shift, 1);
2607
+ let dMin = Number.MAX_VALUE;
2608
+ let matchedC2 = set2[0];
2609
+ for (const c2 of set2) {
2610
+ const diff = Math.abs(expected - c2.progress);
2611
+ const d = diff > 0.5 ? 1 - diff : diff;
2612
+ if (d < dMin) {
2613
+ dMin = d;
2614
+ matchedC2 = c2;
2615
+ }
2616
+ }
2617
+ const progErrorSq = dMin * dMin * TWO_PI_SQ;
2618
+ const angDiff = c1.angle !== void 0 && matchedC2.angle !== void 0 ? angleDiff(c1.angle, matchedC2.angle) : 0;
2619
+ cost += progErrorSq + angDiff * angDiff;
2620
+ if (cost >= minCost) break;
2621
+ }
2622
+ if (cost < minCost) {
2623
+ minCost = cost;
2624
+ bestShift = shift;
2625
+ }
2626
+ }
2627
+ }
2628
+ return {
2629
+ map: (v) => positiveModulo(v + bestShift, 1),
2630
+ mapBack: (v) => positiveModulo(v - bestShift, 1)
2631
+ };
2632
+ }
2633
+
2433
2634
  // src/shapes/morph/float-mapping.ts
2434
2635
  function mapSegments(value, segments) {
2435
2636
  for (const seg of segments) {
@@ -2474,32 +2675,6 @@ function createDoubleMapper(fromValues, toValues) {
2474
2675
  };
2475
2676
  }
2476
2677
 
2477
- // src/shapes/morph/feature-mapping.ts
2478
- function featureMapper(features1, features2) {
2479
- const convex1 = features1.filter((f) => f.convex);
2480
- const convex2 = features2.filter((f) => f.convex);
2481
- if (convex1.length === 0 || convex2.length === 0) {
2482
- return createDoubleMapper([], []);
2483
- }
2484
- const fromValues = [];
2485
- const toValues = [];
2486
- for (const f1 of convex1) {
2487
- let bestDist = Number.MAX_VALUE;
2488
- let bestProgress = 0;
2489
- for (const f2 of convex2) {
2490
- const diff = Math.abs(f1.progress - f2.progress);
2491
- const dist = Math.min(diff, 1 - diff);
2492
- if (dist < bestDist) {
2493
- bestDist = dist;
2494
- bestProgress = f2.progress;
2495
- }
2496
- }
2497
- fromValues.push(f1.progress);
2498
- toValues.push(bestProgress);
2499
- }
2500
- return createDoubleMapper(fromValues, toValues);
2501
- }
2502
-
2503
2678
  // src/shapes/morph/polygon-measure.ts
2504
2679
  var MeasuredPolygon = class _MeasuredPolygon {
2505
2680
  constructor(measuredCubics, features) {
@@ -2533,9 +2708,8 @@ var MeasuredPolygon = class _MeasuredPolygon {
2533
2708
  const t = segLen > 0 ? (cutPoint - cutCubic.startOutlineProgress) / segLen : 0;
2534
2709
  const [left, right] = cutCubic.cubic.split(t);
2535
2710
  const shift = (p) => {
2536
- let s = p - cutPoint;
2537
- if (s < 0) s += 1;
2538
- return s;
2711
+ const s = p - cutPoint;
2712
+ return s < 0 ? s + 1 : s;
2539
2713
  };
2540
2714
  if (!right.zeroLength()) {
2541
2715
  result.push({
@@ -2544,9 +2718,19 @@ var MeasuredPolygon = class _MeasuredPolygon {
2544
2718
  endOutlineProgress: shift(cutCubic.endOutlineProgress)
2545
2719
  });
2546
2720
  }
2547
- for (let i = 1; i < this.measuredCubics.length; i++) {
2548
- const idx = (cutCubicIdx + i) % this.measuredCubics.length;
2549
- const mc = this.measuredCubics[idx];
2721
+ const totalCubics = this.measuredCubics.length;
2722
+ for (let i = cutCubicIdx + 1; i < totalCubics; i++) {
2723
+ const mc = this.measuredCubics[i];
2724
+ if (!mc.cubic.zeroLength()) {
2725
+ result.push({
2726
+ cubic: mc.cubic,
2727
+ startOutlineProgress: shift(mc.startOutlineProgress),
2728
+ endOutlineProgress: shift(mc.endOutlineProgress)
2729
+ });
2730
+ }
2731
+ }
2732
+ for (let i = 0; i < cutCubicIdx; i++) {
2733
+ const mc = this.measuredCubics[i];
2550
2734
  if (!mc.cubic.zeroLength()) {
2551
2735
  result.push({
2552
2736
  cubic: mc.cubic,
@@ -2628,7 +2812,16 @@ var MeasuredPolygon = class _MeasuredPolygon {
2628
2812
  const mc = measured[Math.min(cubicIdx + middleCubicIdx, measured.length - 1)];
2629
2813
  if (mc) {
2630
2814
  const midProgress = (mc.startOutlineProgress + mc.endOutlineProgress) / 2;
2631
- featureList.push({ progress: midProgress, convex: feature.convex });
2815
+ const pt = mc.cubic.pointOnCurve(0.5);
2816
+ const angle = Math.atan2(
2817
+ pt.y - polygon.centerY,
2818
+ pt.x - polygon.centerX
2819
+ );
2820
+ featureList.push({
2821
+ progress: midProgress,
2822
+ convex: feature.convex,
2823
+ angle
2824
+ });
2632
2825
  }
2633
2826
  }
2634
2827
  cubicIdx += feature.cubics.length;
@@ -2638,18 +2831,30 @@ var MeasuredPolygon = class _MeasuredPolygon {
2638
2831
  };
2639
2832
  function approximateLength(cubic) {
2640
2833
  let len = 0;
2641
- let prevX = cubic.anchor0X, prevY = cubic.anchor0Y;
2834
+ const p = cubic.points;
2835
+ let prevX = p[0];
2836
+ let prevY = p[1];
2642
2837
  const steps = 4;
2643
2838
  for (let i = 1; i <= steps; i++) {
2644
- const p = cubic.pointOnCurve(i / steps);
2645
- len += distance(p.x - prevX, p.y - prevY);
2646
- prevX = p.x;
2647
- prevY = p.y;
2839
+ const t = i / steps;
2840
+ const u = 1 - t;
2841
+ const uu = u * u;
2842
+ const tt = t * t;
2843
+ const uuu = uu * u;
2844
+ const ttt = tt * t;
2845
+ const c0 = 3 * t * uu;
2846
+ const c1 = 3 * tt * u;
2847
+ const px = p[0] * uuu + p[2] * c0 + p[4] * c1 + p[6] * ttt;
2848
+ const py = p[1] * uuu + p[3] * c0 + p[5] * c1 + p[7] * ttt;
2849
+ len += distance(px - prevX, py - prevY);
2850
+ prevX = px;
2851
+ prevY = py;
2648
2852
  }
2649
2853
  return len;
2650
2854
  }
2651
2855
 
2652
2856
  // src/shapes/morph/morph.ts
2857
+ var morphMatchCache = /* @__PURE__ */ new WeakMap();
2653
2858
  var Morph = class _Morph {
2654
2859
  /**
2655
2860
  * Creates a Morph between two shapes.
@@ -2665,23 +2870,79 @@ var Morph = class _Morph {
2665
2870
  * Returns the interpolated shape at the given progress as a list of Cubics.
2666
2871
  *
2667
2872
  * Note: This allocates a new list. For performance-critical animation loops,
2668
- * use {@link forEachCubic} instead.
2873
+ * use {@link toSvgPath} or {@link forEachCubic} instead.
2669
2874
  *
2670
2875
  * @param progress - Value in [0, 1]. 0 = start shape, 1 = end shape.
2671
2876
  * Values outside [0, 1] produce exaggerated shapes (useful for bounce/overshoot).
2672
2877
  * @returns List of interpolated Cubic curves forming the morphed shape
2673
2878
  */
2674
2879
  asCubics(progress) {
2675
- const result = [];
2676
- for (const [c1, c2] of this.morphMatch) {
2677
- result.push(
2678
- new Cubic(
2679
- c1.points.map((v, i) => interpolate(v, c2.points[i], progress))
2680
- )
2681
- );
2880
+ const match = this.morphMatch;
2881
+ const len = match.length;
2882
+ const result = new Array(len);
2883
+ for (let i = 0; i < len; i++) {
2884
+ const [c1, c2] = match[i];
2885
+ const p1 = c1.points;
2886
+ const p2 = c2.points;
2887
+ result[i] = new Cubic([
2888
+ p1[0] + (p2[0] - p1[0]) * progress,
2889
+ p1[1] + (p2[1] - p1[1]) * progress,
2890
+ p1[2] + (p2[2] - p1[2]) * progress,
2891
+ p1[3] + (p2[3] - p1[3]) * progress,
2892
+ p1[4] + (p2[4] - p1[4]) * progress,
2893
+ p1[5] + (p2[5] - p1[5]) * progress,
2894
+ p1[6] + (p2[6] - p1[6]) * progress,
2895
+ p1[7] + (p2[7] - p1[7]) * progress
2896
+ ]);
2682
2897
  }
2683
2898
  return result;
2684
2899
  }
2900
+ /**
2901
+ * Returns an SVG path data string for the morphed shape at the given progress.
2902
+ * Directly evaluates coordinates without allocating intermediate Cubic objects.
2903
+ *
2904
+ * @param progress - Value in [0, 1]
2905
+ * @param width - Target pixel width (default: 1)
2906
+ * @param height - Target pixel height (default: 1)
2907
+ */
2908
+ toSvgPath(progress, width = 1, height = 1) {
2909
+ const match = this.morphMatch;
2910
+ const len = match.length;
2911
+ if (len === 0) return "";
2912
+ const paddingX = width * 0.015;
2913
+ const paddingY = height * 0.015;
2914
+ const sx = width - 2 * paddingX;
2915
+ const sy = height - 2 * paddingY;
2916
+ const [firstC1, firstC2] = match[0];
2917
+ const f1 = firstC1.points;
2918
+ const f2 = firstC2.points;
2919
+ const a0x = f1[0] + (f2[0] - f1[0]) * progress;
2920
+ const a0y = f1[1] + (f2[1] - f1[1]) * progress;
2921
+ let d = `M ${formatCoordinate(paddingX + a0x * sx)} ${formatCoordinate(paddingY + sy * (1 - a0y))}`;
2922
+ for (let i = 0; i < len; i++) {
2923
+ const [c1, c2] = match[i];
2924
+ const p1 = c1.points;
2925
+ const p2 = c2.points;
2926
+ const c0x = p1[2] + (p2[2] - p1[2]) * progress;
2927
+ const c0y = p1[3] + (p2[3] - p1[3]) * progress;
2928
+ const c1x = p1[4] + (p2[4] - p1[4]) * progress;
2929
+ const c1y = p1[5] + (p2[5] - p1[5]) * progress;
2930
+ const a1x = p1[6] + (p2[6] - p1[6]) * progress;
2931
+ const a1y = p1[7] + (p2[7] - p1[7]) * progress;
2932
+ d += ` C ${formatCoordinate(paddingX + c0x * sx)} ${formatCoordinate(paddingY + sy * (1 - c0y))},${formatCoordinate(paddingX + c1x * sx)} ${formatCoordinate(paddingY + sy * (1 - c1y))},${formatCoordinate(paddingX + a1x * sx)} ${formatCoordinate(paddingY + sy * (1 - a1y))}`;
2933
+ }
2934
+ return `${d} Z`;
2935
+ }
2936
+ /**
2937
+ * Returns a CSS clip-path value for the morphed shape at the given progress.
2938
+ *
2939
+ * @param progress - Value in [0, 1]
2940
+ * @param width - Element width in pixels
2941
+ * @param height - Element height in pixels
2942
+ */
2943
+ toClipPath(progress, width, height) {
2944
+ return `path('${this.toSvgPath(progress, width, height)}')`;
2945
+ }
2685
2946
  /**
2686
2947
  * Iterates over the morphed cubics without allocating new Cubic instances.
2687
2948
  * Reuses a single MutableCubic for each callback invocation.
@@ -2755,8 +3016,15 @@ var Morph = class _Morph {
2755
3016
  * @internal
2756
3017
  */
2757
3018
  static match(p1, p2) {
2758
- const measured1 = MeasuredPolygon.measurePolygon(p1);
2759
- const measured2 = MeasuredPolygon.measurePolygon(p2);
3019
+ let cachedMap = morphMatchCache.get(p1);
3020
+ if (cachedMap) {
3021
+ const cached = cachedMap.get(p2);
3022
+ if (cached) return cached;
3023
+ }
3024
+ const poly1 = p1.isClockwise() ? p1 : p1.reversed();
3025
+ const poly2 = p2.isClockwise() ? p2 : p2.reversed();
3026
+ const measured1 = MeasuredPolygon.measurePolygon(poly1);
3027
+ const measured2 = MeasuredPolygon.measurePolygon(poly2);
2760
3028
  const doubleMapper = featureMapper(measured1.features, measured2.features);
2761
3029
  const polygon2CutPoint = doubleMapper.map(0);
2762
3030
  const bs1 = measured1;
@@ -2767,11 +3035,12 @@ var Morph = class _Morph {
2767
3035
  let b2 = bs2.getOrNull(i2++);
2768
3036
  while (b1 !== null && b2 !== null) {
2769
3037
  const b1a = i1 >= bs1.size ? 1 : b1.endOutlineProgress;
2770
- const b2aRaw = i2 >= bs2.size ? 1 : positiveModulo(b2.endOutlineProgress + polygon2CutPoint, 1);
2771
- const b2a = doubleMapper.mapBack(b2aRaw);
3038
+ const b2a = i2 >= bs2.size ? 1 : b2.endOutlineProgress;
2772
3039
  const minb = Math.min(b1a, b2a);
2773
- let seg1 = b1, newb1 = bs1.getOrNull(i1);
2774
- let seg2 = b2, newb2 = bs2.getOrNull(i2);
3040
+ let seg1 = b1;
3041
+ let newb1 = bs1.getOrNull(i1);
3042
+ let seg2 = b2;
3043
+ let newb2 = bs2.getOrNull(i2);
2775
3044
  if (b1a > minb + ANGLE_EPSILON) {
2776
3045
  const [cut, rest] = bs1.cutAtProgress(b1, minb);
2777
3046
  seg1 = cut;
@@ -2780,11 +3049,7 @@ var Morph = class _Morph {
2780
3049
  i1++;
2781
3050
  }
2782
3051
  if (b2a > minb + ANGLE_EPSILON) {
2783
- const targetProgress = positiveModulo(
2784
- doubleMapper.map(minb) - polygon2CutPoint,
2785
- 1
2786
- );
2787
- const [cut, rest] = bs2.cutAtProgress(b2, targetProgress);
3052
+ const [cut, rest] = bs2.cutAtProgress(b2, minb);
2788
3053
  seg2 = cut;
2789
3054
  newb2 = rest;
2790
3055
  } else {
@@ -2794,39 +3059,37 @@ var Morph = class _Morph {
2794
3059
  b1 = newb1;
2795
3060
  b2 = newb2;
2796
3061
  }
3062
+ if (!cachedMap) {
3063
+ cachedMap = /* @__PURE__ */ new WeakMap();
3064
+ morphMatchCache.set(p1, cachedMap);
3065
+ }
3066
+ cachedMap.set(p2, result);
2797
3067
  return result;
2798
3068
  }
2799
3069
  };
2800
3070
 
2801
3071
  // src/shapes/render/shape-rendering.ts
2802
3072
  function toSvgPath(cubics, width = 1, height = 1) {
2803
- if (cubics.length === 0) return "";
3073
+ const len = cubics.length;
3074
+ if (len === 0) return "";
2804
3075
  const paddingX = width * 0.015;
2805
3076
  const paddingY = height * 0.015;
2806
3077
  const sx = width - 2 * paddingX;
2807
3078
  const sy = height - 2 * paddingY;
2808
- const flipY = (y) => paddingY + sy * (1 - y);
2809
- const parts = [
2810
- `M ${fmt(paddingX + cubics[0].anchor0X * sx)} ${fmt(flipY(cubics[0].anchor0Y))}`
2811
- ];
2812
- for (const c of cubics) {
2813
- parts.push(
2814
- `C ${fmt(paddingX + c.control0X * sx)} ${fmt(flipY(c.control0Y))},${fmt(paddingX + c.control1X * sx)} ${fmt(flipY(c.control1Y))},${fmt(paddingX + c.anchor1X * sx)} ${fmt(flipY(c.anchor1Y))}`
2815
- );
3079
+ const c0 = cubics[0];
3080
+ let d = `M ${formatCoordinate(paddingX + c0.anchor0X * sx)} ${formatCoordinate(paddingY + sy * (1 - c0.anchor0Y))}`;
3081
+ for (let i = 0; i < len; i++) {
3082
+ const c = cubics[i];
3083
+ d += ` C ${formatCoordinate(paddingX + c.control0X * sx)} ${formatCoordinate(paddingY + sy * (1 - c.control0Y))},${formatCoordinate(paddingX + c.control1X * sx)} ${formatCoordinate(paddingY + sy * (1 - c.control1Y))},${formatCoordinate(paddingX + c.anchor1X * sx)} ${formatCoordinate(paddingY + sy * (1 - c.anchor1Y))}`;
2816
3084
  }
2817
- parts.push("Z");
2818
- return parts.join(" ");
3085
+ return `${d} Z`;
2819
3086
  }
2820
3087
  function toClipPath(polygon, width, height) {
2821
3088
  const pathData = toSvgPath(polygon.cubics, width, height);
2822
3089
  return `path('${pathData}')`;
2823
3090
  }
2824
3091
  function interpolatePath(morph, progress, width, height) {
2825
- const cubics = morph.asCubics(progress);
2826
- return toClipPath({ cubics }, width, height);
2827
- }
2828
- function fmt(v) {
2829
- return Number(v.toFixed(4)).toString();
3092
+ return morph.toClipPath(progress, width, height);
2830
3093
  }
2831
3094
  function cn(...inputs) {
2832
3095
  return twMerge(clsx(inputs));
@@ -14010,45 +14273,64 @@ var DialogOverlay = React67.forwardRef((_a, ref) => {
14010
14273
  ) }));
14011
14274
  });
14012
14275
  DialogOverlay.displayName = "DialogOverlay";
14013
- var DialogContent = React67.forwardRef((_a, ref) => {
14014
- var _b = _a, { className, children, hideCloseButton = false } = _b, props = __objRest(_b, ["className", "children", "hideCloseButton"]);
14015
- return /* @__PURE__ */ jsx(
14016
- RadixDialog.Content,
14017
- __spreadProps(__spreadValues({
14018
- ref,
14019
- asChild: true,
14020
- "aria-describedby": void 0
14021
- }, props), {
14022
- children: /* @__PURE__ */ jsxs(
14023
- m.div,
14024
- __spreadProps(__spreadValues({
14025
- className: cn(
14026
- "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
14027
- "w-[calc(100%-2rem)] max-w-140",
14028
- "rounded-[28px] bg-m3-surface-container-high p-6",
14029
- "shadow-lg outline-none focus-visible:ring-2 focus-visible:ring-m3-primary",
14030
- className
14031
- ),
14032
- role: "dialog"
14033
- }, MD3_CONTENT_ANIM), {
14034
- children: [
14035
- children,
14036
- !hideCloseButton && /* @__PURE__ */ jsx(RadixDialog.Close, { asChild: true, "aria-label": "Close dialog", children: /* @__PURE__ */ jsx(
14037
- IconButton,
14038
- {
14039
- size: "sm",
14040
- colorStyle: "filled",
14041
- className: "absolute right-4 top-4",
14042
- "aria-label": "Close",
14043
- children: /* @__PURE__ */ jsx(Icon, { name: "close", "aria-hidden": "true" })
14044
- }
14045
- ) })
14046
- ]
14047
- })
14048
- )
14049
- })
14050
- );
14051
- });
14276
+ var DEFAULT_CLOSE_BTN_PROPS = {
14277
+ size: "sm",
14278
+ colorStyle: "standard",
14279
+ className: "absolute right-4 top-4",
14280
+ "aria-label": "Close"
14281
+ };
14282
+ var DialogContent = React67.forwardRef(
14283
+ (_a, ref) => {
14284
+ var _b = _a, {
14285
+ className,
14286
+ children,
14287
+ hideCloseButton = false,
14288
+ closeButtonProps,
14289
+ closeButton
14290
+ } = _b, props = __objRest(_b, [
14291
+ "className",
14292
+ "children",
14293
+ "hideCloseButton",
14294
+ "closeButtonProps",
14295
+ "closeButton"
14296
+ ]);
14297
+ const closeAriaLabel = (() => {
14298
+ var _a2, _b2, _c;
14299
+ if (closeButton == null) {
14300
+ return (_a2 = closeButtonProps == null ? void 0 : closeButtonProps["aria-label"]) != null ? _a2 : DEFAULT_CLOSE_BTN_PROPS["aria-label"];
14301
+ }
14302
+ const el = closeButton;
14303
+ return (_c = (_b2 = el == null ? void 0 : el.props) == null ? void 0 : _b2["aria-label"]) != null ? _c : "Close";
14304
+ })();
14305
+ return /* @__PURE__ */ jsx(
14306
+ RadixDialog.Content,
14307
+ __spreadProps(__spreadValues({
14308
+ ref,
14309
+ asChild: true,
14310
+ "aria-describedby": void 0
14311
+ }, props), {
14312
+ children: /* @__PURE__ */ jsxs(
14313
+ m.div,
14314
+ __spreadProps(__spreadValues({
14315
+ className: cn(
14316
+ "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
14317
+ "w-[calc(100%-2rem)] max-w-140",
14318
+ "rounded-[28px] bg-m3-surface-container-high p-6",
14319
+ "shadow-lg outline-none focus-visible:ring-2 focus-visible:ring-m3-primary",
14320
+ className
14321
+ ),
14322
+ role: "dialog"
14323
+ }, MD3_CONTENT_ANIM), {
14324
+ children: [
14325
+ children,
14326
+ closeButton != null ? /* @__PURE__ */ jsx(RadixDialog.Close, { asChild: true, "aria-label": closeAriaLabel, children: closeButton }) : !hideCloseButton ? /* @__PURE__ */ jsx(RadixDialog.Close, { asChild: true, "aria-label": closeAriaLabel, children: /* @__PURE__ */ jsx(IconButton, __spreadProps(__spreadValues(__spreadValues({}, DEFAULT_CLOSE_BTN_PROPS), closeButtonProps), { children: /* @__PURE__ */ jsx(Icon, { name: "close", "aria-hidden": "true" }) })) }) : null
14327
+ ]
14328
+ })
14329
+ )
14330
+ })
14331
+ );
14332
+ }
14333
+ );
14052
14334
  DialogContent.displayName = "DialogContent";
14053
14335
  var DialogIcon = React67.forwardRef((_a, ref) => {
14054
14336
  var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
@@ -14139,6 +14421,8 @@ var DialogFullScreenContent = React67.forwardRef(
14139
14421
  title,
14140
14422
  actionLabel,
14141
14423
  onAction,
14424
+ actionButtonProps,
14425
+ closeButtonProps,
14142
14426
  showDivider
14143
14427
  } = _b, props = __objRest(_b, [
14144
14428
  "className",
@@ -14146,8 +14430,11 @@ var DialogFullScreenContent = React67.forwardRef(
14146
14430
  "title",
14147
14431
  "actionLabel",
14148
14432
  "onAction",
14433
+ "actionButtonProps",
14434
+ "closeButtonProps",
14149
14435
  "showDivider"
14150
14436
  ]);
14437
+ var _a2;
14151
14438
  return /* @__PURE__ */ jsx(
14152
14439
  RadixDialog.Content,
14153
14440
  __spreadProps(__spreadValues({
@@ -14167,16 +14454,33 @@ var DialogFullScreenContent = React67.forwardRef(
14167
14454
  }, MD3_FULLSCREEN_ANIM), {
14168
14455
  children: [
14169
14456
  /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center px-4 h-14 gap-2 bg-m3-surface", children: [
14170
- /* @__PURE__ */ jsx(RadixDialog.Close, { asChild: true, "aria-label": "Close dialog", children: /* @__PURE__ */ jsx(IconButton, { size: "sm", colorStyle: "filled", "aria-label": "Close", children: /* @__PURE__ */ jsx(Icon, { name: "close", "aria-hidden": "true" }) }) }),
14457
+ /* @__PURE__ */ jsx(
14458
+ RadixDialog.Close,
14459
+ {
14460
+ asChild: true,
14461
+ "aria-label": (_a2 = closeButtonProps == null ? void 0 : closeButtonProps["aria-label"]) != null ? _a2 : "Close",
14462
+ children: /* @__PURE__ */ jsx(
14463
+ IconButton,
14464
+ __spreadProps(__spreadValues({
14465
+ size: "sm",
14466
+ colorStyle: "standard",
14467
+ "aria-label": "Close"
14468
+ }, closeButtonProps), {
14469
+ children: /* @__PURE__ */ jsx(Icon, { name: "close", "aria-hidden": "true" })
14470
+ })
14471
+ )
14472
+ }
14473
+ ),
14171
14474
  title && /* @__PURE__ */ jsx(DialogTitle, { className: "flex-1 text-[22px] leading-7 font-medium truncate pr-2", children: title }),
14172
14475
  actionLabel && onAction && /* @__PURE__ */ jsx(
14173
14476
  "button",
14174
- {
14477
+ __spreadProps(__spreadValues({
14175
14478
  type: "button",
14176
14479
  onClick: onAction,
14177
- className: "text-sm font-medium text-m3-primary px-3 py-2 rounded-full hover:bg-m3-primary/8 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-m3-primary transition-colors whitespace-nowrap",
14480
+ className: "text-sm font-medium text-m3-primary px-3 py-2 rounded-full hover:bg-m3-primary/8 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-m3-primary transition-colors whitespace-nowrap disabled:opacity-[0.38] disabled:pointer-events-none"
14481
+ }, actionButtonProps), {
14178
14482
  children: actionLabel
14179
- }
14483
+ })
14180
14484
  )
14181
14485
  ] }),
14182
14486
  showDivider && /* @__PURE__ */ jsx("hr", { className: "border-m3-outline-variant w-full shrink-0 m-0" }),
@@ -15172,21 +15476,13 @@ var normalizeAngle = (angle) => {
15172
15476
  return a;
15173
15477
  };
15174
15478
  var angleToHour12 = (angle) => {
15175
- const hourOffset = RADIANS_PER_HOUR / 2;
15176
- const totalOffset = hourOffset + QUARTER_CIRCLE;
15177
- const hour = Math.round((angle + totalOffset) / RADIANS_PER_HOUR) % 12;
15479
+ const normalized = normalizeAngle(angle + QUARTER_CIRCLE);
15480
+ const hour = Math.round(normalized / RADIANS_PER_HOUR) % 12;
15178
15481
  return hour === 0 ? 12 : hour;
15179
15482
  };
15180
- var angleToMinute = (angle, snap = true) => {
15181
- if (snap) {
15182
- const minuteOffset = RADIANS_PER_MINUTE / 2;
15183
- const totalOffset = minuteOffset + QUARTER_CIRCLE;
15184
- const raw2 = Math.round((angle + totalOffset) / RADIANS_PER_MINUTE) % 60;
15185
- return raw2 < 0 ? raw2 + 60 : raw2;
15186
- }
15483
+ var angleToMinute = (angle, _snap = true) => {
15187
15484
  const normalized = normalizeAngle(angle + QUARTER_CIRCLE);
15188
- const raw = Math.round(normalized / FULL_CIRCLE * 60) % 60;
15189
- return raw < 0 ? raw + 60 : raw;
15485
+ return Math.round(normalized / RADIANS_PER_MINUTE) % 60;
15190
15486
  };
15191
15487
  var getSelectorPosition = (angle, selection, is24hour, isPm) => {
15192
15488
  const useInner = is24hour && isPm && selection === "hour";
@@ -20467,12 +20763,13 @@ var TextFieldComponent = React67.forwardRef(
20467
20763
  if (autoResize) {
20468
20764
  textarea.style.height = "auto";
20469
20765
  textarea.style.height = `${textarea.scrollHeight}px`;
20470
- if (maxRows) {
20471
- textarea.style.maxHeight = `${maxRows * LINE_HEIGHT_PX}px`;
20472
- }
20766
+ textarea.style.overflowY = "hidden";
20767
+ } else {
20768
+ textarea.style.height = "";
20769
+ textarea.style.maxHeight = "";
20770
+ textarea.style.overflowY = "";
20473
20771
  }
20474
- textarea.style.overflowY = "hidden";
20475
- }, [type, autoResize, maxRows, currentValue]);
20772
+ }, [type, autoResize, currentValue]);
20476
20773
  const handleValueChange = React67.useCallback(
20477
20774
  (newValue) => {
20478
20775
  var _a2, _b;
@@ -20695,7 +20992,7 @@ var TextFieldComponent = React67.forwardRef(
20695
20992
  className: cn(
20696
20993
  inputClass,
20697
20994
  "resize-none mt-2",
20698
- autoResize ? "h-auto" : "h-full"
20995
+ autoResize ? "h-auto" : "min-h-full overflow-y-auto"
20699
20996
  ),
20700
20997
  style: { direction: textDirection || void 0 }
20701
20998
  }, inputProps)
@@ -20834,6 +21131,15 @@ var Select = React67.forwardRef(
20834
21131
  openRef.current = open;
20835
21132
  const [searchQuery, setSearchQuery] = React67.useState("");
20836
21133
  const [scrollViewport, setScrollViewport] = React67.useState(null);
21134
+ React67.useEffect(() => {
21135
+ var _a3, _b3;
21136
+ const isDev = ((_b3 = (_a3 = globalThis.process) == null ? void 0 : _a3.env) == null ? void 0 : _b3.NODE_ENV) !== "production";
21137
+ if (isDev && onSearchChange && !searchable) {
21138
+ console.warn(
21139
+ "[Select] `onSearchChange` was provided but `searchable` is false. The callback will never be called unless you also set `searchable={true}`."
21140
+ );
21141
+ }
21142
+ }, [onSearchChange, searchable]);
20837
21143
  const selectedOption = React67.useMemo(
20838
21144
  () => options.find((opt) => opt.value === currentValue),
20839
21145
  [options, currentValue]
@@ -21059,10 +21365,51 @@ function SelectEmpty(_a) {
21059
21365
  })
21060
21366
  );
21061
21367
  }
21368
+
21369
+ // src/ui/shape-media/animation-utils.ts
21062
21370
  function prefersReducedMotion() {
21063
- if (typeof window === "undefined") return false;
21371
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
21372
+ return false;
21373
+ }
21064
21374
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
21065
21375
  }
21376
+ function easeCubicInOut(t) {
21377
+ return t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
21378
+ }
21379
+ function cubicBezier(x1, y1, x2, y2) {
21380
+ return (t) => {
21381
+ if (t === 0 || t === 1) return t;
21382
+ let tParam = t;
21383
+ for (let i = 0; i < 8; i++) {
21384
+ const x = 3 * (1 - tParam) ** 2 * tParam * x1 + 3 * (1 - tParam) * tParam ** 2 * x2 + tParam ** 3;
21385
+ const dx = 3 * (1 - tParam) ** 2 * x1 + 6 * (1 - tParam) * tParam * (x2 - x1) + 3 * tParam ** 2 * (1 - x2);
21386
+ if (Math.abs(dx) < 1e-6) break;
21387
+ tParam -= (x - t) / dx;
21388
+ }
21389
+ return 3 * (1 - tParam) ** 2 * tParam * y1 + 3 * (1 - tParam) * tParam ** 2 * y2 + tParam ** 3;
21390
+ };
21391
+ }
21392
+ function getEasingFunction(easing) {
21393
+ if (Array.isArray(easing)) {
21394
+ if (easing.length === 4) {
21395
+ const [x1, y1, x2, y2] = easing;
21396
+ return cubicBezier(x1, y1, x2, y2);
21397
+ }
21398
+ return easeCubicInOut;
21399
+ }
21400
+ switch (easing) {
21401
+ case "linear":
21402
+ return (t) => t;
21403
+ case "ease-in":
21404
+ return (t) => t * t * t;
21405
+ case "ease-out":
21406
+ return (t) => 1 - (1 - t) ** 3;
21407
+ default:
21408
+ return easeCubicInOut;
21409
+ }
21410
+ }
21411
+
21412
+ // src/ui/shape-media/useShapeMorph.ts
21066
21413
  function useShapeMorph({
21067
21414
  shape,
21068
21415
  morphTo,
@@ -21077,10 +21424,16 @@ function useShapeMorph({
21077
21424
  const duration = (_a = morphOptions == null ? void 0 : morphOptions.duration) != null ? _a : 0.3;
21078
21425
  const easing = (_b = morphOptions == null ? void 0 : morphOptions.easing) != null ? _b : "ease-in-out";
21079
21426
  const easingFunction = useMemo(() => getEasingFunction(easing), [easing]);
21427
+ const resolvedTarget = useMemo(() => {
21428
+ if (morphTo === "auto") {
21429
+ return getRecommendedMorphShape(shape);
21430
+ }
21431
+ return morphTo;
21432
+ }, [morphTo, shape]);
21080
21433
  const startShape = useMemo(() => resolveShape(shape), [shape]);
21081
21434
  const endShape = useMemo(
21082
- () => morphTo ? resolveShape(morphTo) : null,
21083
- [morphTo]
21435
+ () => resolvedTarget ? resolveShape(resolvedTarget) : null,
21436
+ [resolvedTarget]
21084
21437
  );
21085
21438
  const morph = useMemo(
21086
21439
  () => endShape ? new Morph(startShape, endShape) : null,
@@ -21095,7 +21448,45 @@ function useShapeMorph({
21095
21448
  const startProgressRef = useRef(0);
21096
21449
  const targetProgressRef = useRef(0);
21097
21450
  const currentProgressRef = useRef(0);
21451
+ const prevShapeRef = useRef(shape);
21452
+ useEffect(() => {
21453
+ if (prevShapeRef.current === shape) return;
21454
+ const oldShape = prevShapeRef.current;
21455
+ prevShapeRef.current = shape;
21456
+ if (disabled || prefersReducedMotion()) {
21457
+ setClipPath(toClipPath(resolveShape(shape), width, height));
21458
+ return;
21459
+ }
21460
+ try {
21461
+ const transitionMorph = new Morph(
21462
+ resolveShape(oldShape),
21463
+ resolveShape(shape)
21464
+ );
21465
+ const start = performance.now();
21466
+ const durationMs = duration * 1e3;
21467
+ const animateTransition = (timestamp) => {
21468
+ const elapsed = timestamp - start;
21469
+ const rawT = Math.min(elapsed / durationMs, 1);
21470
+ const ease = easingFunction(rawT);
21471
+ setClipPath(interpolatePath(transitionMorph, ease, width, height));
21472
+ if (rawT < 1) {
21473
+ animRef.current = requestAnimationFrame(animateTransition);
21474
+ } else {
21475
+ animRef.current = null;
21476
+ }
21477
+ };
21478
+ if (animRef.current !== null) cancelAnimationFrame(animRef.current);
21479
+ animRef.current = requestAnimationFrame(animateTransition);
21480
+ } catch (e) {
21481
+ setClipPath(toClipPath(resolveShape(shape), width, height));
21482
+ }
21483
+ }, [shape, disabled, duration, easingFunction, width, height]);
21484
+ const prevDimsRef = useRef({ width, height, startShape, morph });
21098
21485
  useEffect(() => {
21486
+ if (prevDimsRef.current.width === width && prevDimsRef.current.height === height && prevDimsRef.current.startShape === startShape && prevDimsRef.current.morph === morph) {
21487
+ return;
21488
+ }
21489
+ prevDimsRef.current = { width, height, startShape, morph };
21099
21490
  if (morph) {
21100
21491
  setClipPath(
21101
21492
  interpolatePath(morph, currentProgressRef.current, width, height)
@@ -21189,41 +21580,6 @@ function useShapeMorph({
21189
21580
  }, [morphTo, disabled, morphOn, activate, deactivate, isActive]);
21190
21581
  return { clipPath, isActive, activate, deactivate, setProgress, handlers };
21191
21582
  }
21192
- function easeCubicInOut(t) {
21193
- return t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
21194
- }
21195
- function cubicBezier(x1, y1, x2, y2) {
21196
- return (t) => {
21197
- if (t === 0 || t === 1) return t;
21198
- let tParam = t;
21199
- for (let i = 0; i < 8; i++) {
21200
- const x = 3 * (1 - tParam) ** 2 * tParam * x1 + 3 * (1 - tParam) * tParam ** 2 * x2 + tParam ** 3;
21201
- const dx = 3 * (1 - tParam) ** 2 * x1 + 6 * (1 - tParam) * tParam * (x2 - x1) + 3 * tParam ** 2 * (1 - x2);
21202
- if (Math.abs(dx) < 1e-6) break;
21203
- tParam -= (x - t) / dx;
21204
- }
21205
- return 3 * (1 - tParam) ** 2 * tParam * y1 + 3 * (1 - tParam) * tParam ** 2 * y2 + tParam ** 3;
21206
- };
21207
- }
21208
- function getEasingFunction(easing) {
21209
- if (Array.isArray(easing)) {
21210
- if (easing.length === 4) {
21211
- const [x1, y1, x2, y2] = easing;
21212
- return cubicBezier(x1, y1, x2, y2);
21213
- }
21214
- return easeCubicInOut;
21215
- }
21216
- switch (easing) {
21217
- case "linear":
21218
- return (t) => t;
21219
- case "ease-in":
21220
- return (t) => t * t * t;
21221
- case "ease-out":
21222
- return (t) => 1 - (1 - t) ** 3;
21223
- default:
21224
- return easeCubicInOut;
21225
- }
21226
- }
21227
21583
  function ShapeMedia({
21228
21584
  shape,
21229
21585
  morphTo,
@@ -21351,10 +21707,14 @@ function ShapeSvg({
21351
21707
  style,
21352
21708
  "aria-label": ariaLabel
21353
21709
  }) {
21710
+ const resolvedTarget = useMemo(() => {
21711
+ if (morphTo === "auto") return getRecommendedMorphShape(shape);
21712
+ return morphTo;
21713
+ }, [morphTo, shape]);
21354
21714
  const startPolygon = useMemo(() => resolveShape(shape), [shape]);
21355
21715
  const endPolygon = useMemo(
21356
- () => morphTo ? resolveShape(morphTo) : null,
21357
- [morphTo]
21716
+ () => resolvedTarget ? resolveShape(resolvedTarget) : null,
21717
+ [resolvedTarget]
21358
21718
  );
21359
21719
  const morph = useMemo(
21360
21720
  () => endPolygon ? new Morph(startPolygon, endPolygon) : null,
@@ -21388,6 +21748,176 @@ function ShapeSvg({
21388
21748
  }
21389
21749
  );
21390
21750
  }
21751
+ function useShapeSequenceMorph({
21752
+ shapes,
21753
+ duration = 0.6,
21754
+ interval = 2,
21755
+ autoplay = false,
21756
+ loop = true,
21757
+ morphOptions,
21758
+ width,
21759
+ height,
21760
+ disabled = false
21761
+ }) {
21762
+ var _a;
21763
+ const resolvedDuration = (_a = morphOptions == null ? void 0 : morphOptions.duration) != null ? _a : duration;
21764
+ const [currentIndex, setCurrentIndex] = useState(0);
21765
+ const [nextIndex, setNextIndex] = useState(() => shapes.length > 1 ? 1 : 0);
21766
+ const [progress, setProgress] = useState(0);
21767
+ const [isPlaying, setIsPlaying] = useState(autoplay);
21768
+ const animRef = useRef(null);
21769
+ const timerRef = useRef(null);
21770
+ const startTimeRef = useRef(0);
21771
+ const isTransitioningRef = useRef(false);
21772
+ const numShapes = shapes.length;
21773
+ const currentShape = useMemo(() => {
21774
+ if (numShapes === 0) return resolveShape("circle");
21775
+ const safeIdx = (currentIndex % numShapes + numShapes) % numShapes;
21776
+ return resolveShape(shapes[safeIdx]);
21777
+ }, [shapes, currentIndex, numShapes]);
21778
+ const targetShape = useMemo(() => {
21779
+ if (numShapes === 0) return resolveShape("circle");
21780
+ const safeIdx = (nextIndex % numShapes + numShapes) % numShapes;
21781
+ return resolveShape(shapes[safeIdx]);
21782
+ }, [shapes, nextIndex, numShapes]);
21783
+ const morph = useMemo(() => {
21784
+ if (currentShape === targetShape) return null;
21785
+ return new Morph(currentShape, targetShape);
21786
+ }, [currentShape, targetShape]);
21787
+ const [clipPath, setClipPath] = useState(
21788
+ () => toClipPath(currentShape, width, height)
21789
+ );
21790
+ const prevDimsRef = useRef({ width, height, currentShape, morph, progress });
21791
+ useEffect(() => {
21792
+ if (prevDimsRef.current.width === width && prevDimsRef.current.height === height && prevDimsRef.current.currentShape === currentShape && prevDimsRef.current.morph === morph && prevDimsRef.current.progress === progress) {
21793
+ return;
21794
+ }
21795
+ prevDimsRef.current = { width, height, currentShape, morph, progress };
21796
+ if (morph && progress > 0) {
21797
+ setClipPath(interpolatePath(morph, progress, width, height));
21798
+ } else {
21799
+ setClipPath(toClipPath(currentShape, width, height));
21800
+ }
21801
+ }, [width, height, currentShape, morph, progress]);
21802
+ const transitionTo = useCallback(
21803
+ (toIndex) => {
21804
+ if (disabled || numShapes <= 1 || isTransitioningRef.current) return;
21805
+ const targetSafe = (toIndex % numShapes + numShapes) % numShapes;
21806
+ if (targetSafe === currentIndex) return;
21807
+ setNextIndex(targetSafe);
21808
+ if (prefersReducedMotion()) {
21809
+ setCurrentIndex(targetSafe);
21810
+ setNextIndex((targetSafe + 1) % numShapes);
21811
+ setProgress(0);
21812
+ setClipPath(
21813
+ toClipPath(resolveShape(shapes[targetSafe]), width, height)
21814
+ );
21815
+ return;
21816
+ }
21817
+ isTransitioningRef.current = true;
21818
+ startTimeRef.current = performance.now();
21819
+ const fromPoly = resolveShape(shapes[currentIndex]);
21820
+ const toPoly = resolveShape(shapes[targetSafe]);
21821
+ const activeMorph = new Morph(fromPoly, toPoly);
21822
+ const animate7 = (timestamp) => {
21823
+ const elapsed = timestamp - startTimeRef.current;
21824
+ const durationMs = resolvedDuration * 1e3;
21825
+ const rawT = Math.min(elapsed / durationMs, 1);
21826
+ const ease = easeCubicInOut(rawT);
21827
+ setProgress(rawT);
21828
+ setClipPath(interpolatePath(activeMorph, ease, width, height));
21829
+ if (rawT < 1) {
21830
+ animRef.current = requestAnimationFrame(animate7);
21831
+ } else {
21832
+ animRef.current = null;
21833
+ isTransitioningRef.current = false;
21834
+ setCurrentIndex(targetSafe);
21835
+ setNextIndex((targetSafe + 1) % numShapes);
21836
+ setProgress(0);
21837
+ }
21838
+ };
21839
+ if (animRef.current !== null) cancelAnimationFrame(animRef.current);
21840
+ animRef.current = requestAnimationFrame(animate7);
21841
+ },
21842
+ [
21843
+ disabled,
21844
+ numShapes,
21845
+ currentIndex,
21846
+ shapes,
21847
+ resolvedDuration,
21848
+ width,
21849
+ height
21850
+ ]
21851
+ );
21852
+ const next = useCallback(() => {
21853
+ if (numShapes <= 1) return;
21854
+ if (!loop && currentIndex >= numShapes - 1) return;
21855
+ transitionTo((currentIndex + 1) % numShapes);
21856
+ }, [numShapes, loop, currentIndex, transitionTo]);
21857
+ const prev = useCallback(() => {
21858
+ if (numShapes <= 1) return;
21859
+ if (!loop && currentIndex <= 0) return;
21860
+ transitionTo((currentIndex - 1 + numShapes) % numShapes);
21861
+ }, [numShapes, loop, currentIndex, transitionTo]);
21862
+ const goTo = useCallback(
21863
+ (index) => {
21864
+ transitionTo(index);
21865
+ },
21866
+ [transitionTo]
21867
+ );
21868
+ const play = useCallback(() => {
21869
+ setIsPlaying(true);
21870
+ }, []);
21871
+ const pause = useCallback(() => {
21872
+ setIsPlaying(false);
21873
+ if (timerRef.current !== null) {
21874
+ clearTimeout(timerRef.current);
21875
+ timerRef.current = null;
21876
+ }
21877
+ }, []);
21878
+ useEffect(() => {
21879
+ if (!isPlaying || disabled || numShapes <= 1) return;
21880
+ timerRef.current = setTimeout(() => {
21881
+ if (!loop && currentIndex >= numShapes - 1) {
21882
+ setIsPlaying(false);
21883
+ return;
21884
+ }
21885
+ next();
21886
+ }, interval * 1e3);
21887
+ return () => {
21888
+ if (timerRef.current !== null) {
21889
+ clearTimeout(timerRef.current);
21890
+ timerRef.current = null;
21891
+ }
21892
+ };
21893
+ }, [isPlaying, disabled, numShapes, loop, currentIndex, interval, next]);
21894
+ useEffect(() => {
21895
+ return () => {
21896
+ if (animRef.current !== null) cancelAnimationFrame(animRef.current);
21897
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
21898
+ };
21899
+ }, []);
21900
+ useEffect(() => {
21901
+ if (currentIndex >= shapes.length) {
21902
+ setCurrentIndex(0);
21903
+ setNextIndex(shapes.length > 1 ? 1 : 0);
21904
+ }
21905
+ }, [shapes.length, currentIndex]);
21906
+ const safeCurrentIndex = numShapes > 0 ? (currentIndex % numShapes + numShapes) % numShapes : 0;
21907
+ const safeNextIndex = numShapes > 0 ? (nextIndex % numShapes + numShapes) % numShapes : 0;
21908
+ return {
21909
+ clipPath,
21910
+ currentIndex: safeCurrentIndex,
21911
+ nextIndex: safeNextIndex,
21912
+ progress,
21913
+ isPlaying,
21914
+ next,
21915
+ prev,
21916
+ goTo,
21917
+ play,
21918
+ pause
21919
+ };
21920
+ }
21391
21921
  var INDICATOR = "h-1 w-8 rounded-full bg-m3-on-surface-variant/40";
21392
21922
  var DragHandle = React67.forwardRef(
21393
21923
  ({ className, onCycle, "aria-label": ariaLabel }, ref) => {
@@ -27416,6 +27946,6 @@ function TooltipBox({
27416
27946
  ] });
27417
27947
  }
27418
27948
 
27419
- export { ANGLE_EPSILON, APP_BAR_BOTTOM_SPRING, APP_BAR_COLORS, APP_BAR_COLOR_TRANSITION, APP_BAR_ENTER_ALWAYS_SPRING, APP_BAR_TITLE_FADE, AppBarColumn, AppBarOverflowIndicator, AppBarRow, AppBarTokens, BUTTON_COLOR_TOKENS, BUTTON_SIZE_TOKENS, Badge, BadgedBox, BottomAppBar, BottomDockedToolbar, BottomSheet, BottomSheetModal, Button, ButtonDistribute, ButtonGroup, CHECK_ICON_VARIANTS, Card, CardContent, CardFooter, CardHeader, CardMedia, Carousel, CarouselGrid, CarouselItem, CarouselScrollClient, CarouselTokens, Checkbox, Chip, CodeBlock, ContextMenu, ContextMenuContent, ContextMenuTrigger, Cubic, DISTANCE_EPSILON, DIVIDER_COLOR, DIVIDER_PADDING, DP_CLASSES, DP_COLORS, DP_SHAPE, DP_SIZE, DatePicker, DatePickerDialog, DatePickerInput, DateRangePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogFullScreenContent, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Divider, DockedToolbar, DragHandle, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, ElevatedSplitButtonLeading, ElevatedSplitButtonTrailing, ElevatedSplitButtonTrailingUncheckable, ExtendedFAB, FAB, FABMenu, FABMenuItem, FABPosition, FAST_EFFECTS_TRANSITION, FAST_SPATIAL_SPRING, FLOAT_PI, FadingBlurMask, FilledSplitButtonLeading, FilledSplitButtonTrailing, FilledSplitButtonTrailingUncheckable, GROUP_SHAPES, HorizontalFloatingToolbar, HorizontalFloatingToolbarWithFab, ITEM_SHAPE_CLASSES, Icon, IconButton, LIST_TOKENS, LargeFlexibleAppBar, List, ListContext, ListDivider, ListItem, LoadingIndicator, MD3CornerRadius, MD3Shapes, MD3ThemeProvider, MD3_EXPRESSIVE_FONT_VARIATION, MENU_CHECK_ICON_SIZE, MENU_CONTAINER_VARIANTS, MENU_GROUP_GAP, MENU_ICON_SIZE, MENU_ITEM_MIN_HEIGHT, MENU_MAX_WIDTH, MENU_MIN_WIDTH, MaterialSymbolsPreconnect, MeasuredPolygon, MediumFlexibleAppBar, Menu, MenuContent, MenuDivider, MenuGroup, MenuItem, MenuProvider, MenuTrigger, Morph, MutableCubic, NavigationBar, NavigationBarItem, NavigationRail, NavigationRailItem, OutlinedSplitButtonLeading, OutlinedSplitButtonTrailing, OutlinedSplitButtonTrailingUncheckable, PlainTooltip, ProgressIndicator, RadioButton, RadioGroup, RangeSlider, RichTooltip, Ripple, RoundedPolygon, SEARCH_BAR_EXPAND_SPRING, SEARCH_COLORS, SEARCH_DOCKED_REVEAL_SPRING, SEARCH_FULLSCREEN_SPRING, SEARCH_TYPOGRAPHY, SEARCH_VIEW_SPRING, STANDARD_COLORS, SUBMENU_CONTAINER_VARIANTS, Scrim, ScrollArea, ScrollAreaScrollbar, Search, SearchAppBar, SearchBar, SearchTokens, SearchView, SearchViewContainer, SearchViewDocked, SearchViewFullScreen, Select, ShapeIcon, ShapeMedia, ShapeMediaServer, ShapeSvg, SideSheet, SideSheetModal, Slider, SliderColors, SliderTokens, SmallAppBar, Snackbar, SnackbarContext, SnackbarHost, SnackbarProvider, SplitButtonLayout, SplitButtonLeading, SplitButtonTrailing, SplitButtonTrailingUncheckable, SubMenu, Switch, SwitchColors, SwitchTokens, TP_CLASSES, TP_COLORS, TP_SHAPE, TP_SIZE, Tab, TableOfContents, Tabs, TabsColors, TabsContent, TabsList, TabsTokens, Text, TextField, TimeInput, TimePicker, TimePickerDialog, ToggleFAB, TonalSplitButtonLeading, TonalSplitButtonTrailing, TonalSplitButtonTrailingUncheckable, ToolbarDivider, ToolbarDividerTokens, ToolbarIconButton, ToolbarIconButtonTokens, ToolbarToggleButton, ToolbarToggleButtonTokens, TooltipBox, TooltipCaretShape, TooltipTokens, TriStateCheckbox, TypeScaleTokens, Typography, TypographyContext, TypographyKeyTokens, TypographyProvider, TypographyTokens, UNROUNDED, VIBRANT_COLORS, VerticalFloatingToolbar, VerticalFloatingToolbarWithFab, VerticalMenu, VerticalMenuContent, VerticalMenuDivider, VerticalMenuGroup, addPoints, appBarTypography, applyTheme, buildWavePath, cardVariants, circle, clockwise, convex, cornerFeature, cornerRounding, createDoubleMapper, createMd3ExpressiveTheme, directionVector, distance, distanceSquared, dividePoint, dotProduct, edgeFeature, featureMapper, generateM3Theme, getDirection, getDistance, getDistanceSquared, getExpressiveShape, getListItemHeight, getToolbarColors, interpolate, interpolatePath, lerpPoint, pill, pillStar, point, positiveModulo, radialToCartesian, rectangle, resolveMode, rotate90, scalePoint, shouldTopAlign, square, standardFloatingToolbarColors, star, subtractPoints, surfaceContainerHighFloatingToolbarColors, surfaceContainerHighestFloatingToolbarColors, tertiaryContainerFloatingToolbarColors, toClipPath, toSvgPath, transformFeature, transformPoint, useAppBarScroll, useBottomSheet, useCarouselA11y, useCarouselKeylines, useRipple as useDOMRipple, useDatePickerState, useDateRangePickerState, useFloatingToolbarScrollBehavior, useListContext, useMediaQuery, useMenuContext, useRipple2 as useRipple, useRippleState, useSearchKeyboard, useShapeMorph, useSnackbar, useSnackbarState, useTheme, useThemeMode, useTimePickerState, useTooltipPosition, useTooltipState, useTypography, vibrantFloatingToolbarColors, xrFloatingToolbarColors };
27949
+ export { ANGLE_EPSILON, APP_BAR_BOTTOM_SPRING, APP_BAR_COLORS, APP_BAR_COLOR_TRANSITION, APP_BAR_ENTER_ALWAYS_SPRING, APP_BAR_TITLE_FADE, AppBarColumn, AppBarOverflowIndicator, AppBarRow, AppBarTokens, BUTTON_COLOR_TOKENS, BUTTON_SIZE_TOKENS, Badge, BadgedBox, BottomAppBar, BottomDockedToolbar, BottomSheet, BottomSheetModal, Button, ButtonDistribute, ButtonGroup, CHECK_ICON_VARIANTS, Card, CardContent, CardFooter, CardHeader, CardMedia, Carousel, CarouselGrid, CarouselItem, CarouselScrollClient, CarouselTokens, Checkbox, Chip, CodeBlock, ContextMenu, ContextMenuContent, ContextMenuTrigger, Cubic, DISTANCE_EPSILON, DIVIDER_COLOR, DIVIDER_PADDING, DP_CLASSES, DP_COLORS, DP_SHAPE, DP_SIZE, DatePicker, DatePickerDialog, DatePickerInput, DateRangePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogFullScreenContent, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Divider, DockedToolbar, DragHandle, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, ElevatedSplitButtonLeading, ElevatedSplitButtonTrailing, ElevatedSplitButtonTrailingUncheckable, ExtendedFAB, FAB, FABMenu, FABMenuItem, FABPosition, FAST_EFFECTS_TRANSITION, FAST_SPATIAL_SPRING, FLOAT_PI, FadingBlurMask, FilledSplitButtonLeading, FilledSplitButtonTrailing, FilledSplitButtonTrailingUncheckable, GROUP_SHAPES, HorizontalFloatingToolbar, HorizontalFloatingToolbarWithFab, ITEM_SHAPE_CLASSES, Icon, IconButton, LIST_TOKENS, LargeFlexibleAppBar, List, ListContext, ListDivider, ListItem, LoadingIndicator, MD3CornerRadius, MD3Shapes, MD3ThemeProvider, MD3_EXPRESSIVE_FONT_VARIATION, MD3_SHAPE_FAMILIES, MD3_SHAPE_PAIRINGS, MENU_CHECK_ICON_SIZE, MENU_CONTAINER_VARIANTS, MENU_GROUP_GAP, MENU_ICON_SIZE, MENU_ITEM_MIN_HEIGHT, MENU_MAX_WIDTH, MENU_MIN_WIDTH, MaterialSymbolsPreconnect, MeasuredPolygon, MediumFlexibleAppBar, Menu, MenuContent, MenuDivider, MenuGroup, MenuItem, MenuProvider, MenuTrigger, Morph, MutableCubic, NavigationBar, NavigationBarItem, NavigationRail, NavigationRailItem, OutlinedSplitButtonLeading, OutlinedSplitButtonTrailing, OutlinedSplitButtonTrailingUncheckable, PlainTooltip, ProgressIndicator, RadioButton, RadioGroup, RangeSlider, RichTooltip, Ripple, RoundedPolygon, SEARCH_BAR_EXPAND_SPRING, SEARCH_COLORS, SEARCH_DOCKED_REVEAL_SPRING, SEARCH_FULLSCREEN_SPRING, SEARCH_TYPOGRAPHY, SEARCH_VIEW_SPRING, STANDARD_COLORS, SUBMENU_CONTAINER_VARIANTS, Scrim, ScrollArea, ScrollAreaScrollbar, Search, SearchAppBar, SearchBar, SearchTokens, SearchView, SearchViewContainer, SearchViewDocked, SearchViewFullScreen, Select, ShapeIcon, ShapeMedia, ShapeMediaServer, ShapeSvg, SideSheet, SideSheetModal, Slider, SliderColors, SliderTokens, SmallAppBar, Snackbar, SnackbarContext, SnackbarHost, SnackbarProvider, SplitButtonLayout, SplitButtonLeading, SplitButtonTrailing, SplitButtonTrailingUncheckable, SubMenu, Switch, SwitchColors, SwitchTokens, TP_CLASSES, TP_COLORS, TP_SHAPE, TP_SIZE, Tab, TableOfContents, Tabs, TabsColors, TabsContent, TabsList, TabsTokens, Text, TextField, TimeInput, TimePicker, TimePickerDialog, ToggleFAB, TonalSplitButtonLeading, TonalSplitButtonTrailing, TonalSplitButtonTrailingUncheckable, ToolbarDivider, ToolbarDividerTokens, ToolbarIconButton, ToolbarIconButtonTokens, ToolbarToggleButton, ToolbarToggleButtonTokens, TooltipBox, TooltipCaretShape, TooltipTokens, TriStateCheckbox, TypeScaleTokens, Typography, TypographyContext, TypographyKeyTokens, TypographyProvider, TypographyTokens, UNROUNDED, VIBRANT_COLORS, VerticalFloatingToolbar, VerticalFloatingToolbarWithFab, VerticalMenu, VerticalMenuContent, VerticalMenuDivider, VerticalMenuGroup, addPoints, appBarTypography, applyTheme, buildWavePath, cardVariants, circle, clockwise, convex, cornerFeature, cornerRounding, createDoubleMapper, createMd3ExpressiveTheme, directionVector, distance, distanceSquared, dividePoint, dotProduct, edgeFeature, featureMapper, formatCoordinate, generateM3Theme, getDirection, getDistance, getDistanceSquared, getExpressiveShape, getListItemHeight, getRecommendedMorphShape, getToolbarColors, interpolate, interpolatePath, lerpPoint, pill, pillStar, point, positiveModulo, radialToCartesian, rectangle, resolveMode, rotate90, scalePoint, shouldTopAlign, square, standardFloatingToolbarColors, star, subtractPoints, surfaceContainerHighFloatingToolbarColors, surfaceContainerHighestFloatingToolbarColors, tertiaryContainerFloatingToolbarColors, toClipPath, toSvgPath, transformFeature, transformPoint, useAppBarScroll, useBottomSheet, useCarouselA11y, useCarouselKeylines, useRipple as useDOMRipple, useDatePickerState, useDateRangePickerState, useFloatingToolbarScrollBehavior, useListContext, useMediaQuery, useMenuContext, useRipple2 as useRipple, useRippleState, useSearchKeyboard, useShapeMorph, useShapeSequenceMorph, useSnackbar, useSnackbarState, useTheme, useThemeMode, useTimePickerState, useTooltipPosition, useTooltipState, useTypography, vibrantFloatingToolbarColors, xrFloatingToolbarColors };
27420
27950
  //# sourceMappingURL=index.mjs.map
27421
27951
  //# sourceMappingURL=index.mjs.map