@bug-on/m3-expressive 1.3.4 → 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 (76) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +31 -7
  3. package/dist/assets/material-symbols-cdn.css +17 -23
  4. package/dist/buttons.js +129 -35
  5. package/dist/buttons.js.map +1 -1
  6. package/dist/buttons.mjs +129 -35
  7. package/dist/buttons.mjs.map +1 -1
  8. package/dist/{core-COvZHQ_k.d.ts → core-Cckt8qEm.d.ts} +10 -4
  9. package/dist/{core-CRkixy1y.d.mts → core-DDfG4pym.d.mts} +10 -4
  10. package/dist/core.d.mts +2 -2
  11. package/dist/core.d.ts +2 -2
  12. package/dist/core.js +6 -5
  13. package/dist/core.js.map +1 -1
  14. package/dist/core.mjs +6 -5
  15. package/dist/core.mjs.map +1 -1
  16. package/dist/fading-blur-mask--uZbBKLj.d.mts +77 -0
  17. package/dist/fading-blur-mask--uZbBKLj.d.ts +77 -0
  18. package/dist/feedback.js +1 -1
  19. package/dist/feedback.js.map +1 -1
  20. package/dist/feedback.mjs +1 -1
  21. package/dist/feedback.mjs.map +1 -1
  22. package/dist/forms.d.mts +2 -2
  23. package/dist/forms.d.ts +2 -2
  24. package/dist/forms.js +17 -7
  25. package/dist/forms.js.map +1 -1
  26. package/dist/forms.mjs +17 -7
  27. package/dist/forms.mjs.map +1 -1
  28. package/dist/index.d.mts +9 -8
  29. package/dist/index.d.ts +9 -8
  30. package/dist/index.js +988 -309
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +984 -310
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/layout.d.mts +5 -3
  35. package/dist/layout.d.ts +5 -3
  36. package/dist/layout.js +61 -6
  37. package/dist/layout.js.map +1 -1
  38. package/dist/layout.mjs +61 -7
  39. package/dist/layout.mjs.map +1 -1
  40. package/dist/material-symbols-cdn.css +17 -23
  41. package/dist/{md3-expressive-shapes-CPcfl_Hf.d.mts → md3-expressive-shapes-wk_98LJh.d.mts} +20 -1
  42. package/dist/{md3-expressive-shapes-CPcfl_Hf.d.ts → md3-expressive-shapes-wk_98LJh.d.ts} +20 -1
  43. package/dist/navigation.d.mts +26 -84
  44. package/dist/navigation.d.ts +26 -84
  45. package/dist/navigation.js +95 -29
  46. package/dist/navigation.js.map +1 -1
  47. package/dist/navigation.mjs +95 -29
  48. package/dist/navigation.mjs.map +1 -1
  49. package/dist/overlays.d.mts +4 -2
  50. package/dist/overlays.d.ts +4 -2
  51. package/dist/overlays.js +85 -44
  52. package/dist/overlays.js.map +1 -1
  53. package/dist/overlays.mjs +85 -44
  54. package/dist/overlays.mjs.map +1 -1
  55. package/dist/pickers.d.mts +12 -0
  56. package/dist/pickers.d.ts +12 -0
  57. package/dist/pickers.js +186 -120
  58. package/dist/pickers.js.map +1 -1
  59. package/dist/pickers.mjs +186 -120
  60. package/dist/pickers.mjs.map +1 -1
  61. package/dist/shapes.d.mts +141 -15
  62. package/dist/shapes.d.ts +141 -15
  63. package/dist/shapes.js +618 -126
  64. package/dist/shapes.js.map +1 -1
  65. package/dist/shapes.mjs +614 -127
  66. package/dist/shapes.mjs.map +1 -1
  67. package/dist/{side-sheet-modal-64FGhDxL.d.mts → side-sheet-modal-BycxrabB.d.mts} +70 -0
  68. package/dist/{side-sheet-modal-Bd5Qqvp9.d.ts → side-sheet-modal-Cw4vemKx.d.ts} +70 -0
  69. package/dist/{text-field-4OlT9o8s.d.mts → text-field-B1fLh5Sh.d.mts} +22 -3
  70. package/dist/{text-field-DARNdj14.d.ts → text-field-C0VQLp8Y.d.ts} +22 -3
  71. package/dist/{typography-339RV6v7.d.mts → typography-CKTjvlZ4.d.mts} +25 -0
  72. package/dist/{typography-339RV6v7.d.ts → typography-CKTjvlZ4.d.ts} +25 -0
  73. package/dist/typography.css +1 -1
  74. package/llms-full.txt +24 -13
  75. package/llms.txt +11 -6
  76. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -281,7 +281,8 @@ function schemeToCssVariables(scheme) {
281
281
  return result;
282
282
  }
283
283
  function MaterialSymbolsPreconnect({
284
- variants = ["outlined"]
284
+ variants = ["rounded"],
285
+ display = "block"
285
286
  }) {
286
287
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
287
288
  /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }),
@@ -296,7 +297,7 @@ function MaterialSymbolsPreconnect({
296
297
  variants.includes("outlined") && /* @__PURE__ */ jsxRuntime.jsx(
297
298
  "link",
298
299
  {
299
- href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap",
300
+ href: `https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=${display}`,
300
301
  rel: "stylesheet",
301
302
  precedence: "default"
302
303
  }
@@ -304,7 +305,7 @@ function MaterialSymbolsPreconnect({
304
305
  variants.includes("rounded") && /* @__PURE__ */ jsxRuntime.jsx(
305
306
  "link",
306
307
  {
307
- href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap",
308
+ href: `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=${display}`,
308
309
  rel: "stylesheet",
309
310
  precedence: "default"
310
311
  }
@@ -312,7 +313,7 @@ function MaterialSymbolsPreconnect({
312
313
  variants.includes("sharp") && /* @__PURE__ */ jsxRuntime.jsx(
313
314
  "link",
314
315
  {
315
- href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap",
316
+ href: `https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=${display}`,
316
317
  rel: "stylesheet",
317
318
  precedence: "default"
318
319
  }
@@ -334,6 +335,13 @@ function transformFeature(feature, fn) {
334
335
  }
335
336
  return edgeFeature(cubics);
336
337
  }
338
+ function reverseFeature(feature) {
339
+ const cubics = feature.cubics.slice().reverse().map((c) => c.reverse());
340
+ if (feature.type === "corner") {
341
+ return cornerFeature(cubics, feature.convex);
342
+ }
343
+ return edgeFeature(cubics);
344
+ }
337
345
 
338
346
  // src/shapes/math/corner-rounding.ts
339
347
  function cornerRounding(radius = 0, smoothing = 0) {
@@ -378,6 +386,10 @@ function convex(prevX, prevY, currX, currY, nextX, nextY) {
378
386
  const v2y = nextY - currY;
379
387
  return v1x * v2y - v1y * v2x > 0;
380
388
  }
389
+ function formatCoordinate(v) {
390
+ const rounded = Math.round(v * 1e4) / 1e4;
391
+ return (rounded === 0 ? 0 : rounded).toString();
392
+ }
381
393
 
382
394
  // src/shapes/math/point.ts
383
395
  function point(x, y) {
@@ -477,9 +489,16 @@ var Cubic = class _Cubic {
477
489
  */
478
490
  pointOnCurve(t) {
479
491
  const u = 1 - t;
492
+ const uu = u * u;
493
+ const tt = t * t;
494
+ const uuu = uu * u;
495
+ const ttt = tt * t;
496
+ const c0 = 3 * t * uu;
497
+ const c1 = 3 * tt * u;
498
+ const p = this.points;
480
499
  return point(
481
- this.anchor0X * (u * u * u) + this.control0X * (3 * t * u * u) + this.control1X * (3 * t * t * u) + this.anchor1X * (t * t * t),
482
- this.anchor0Y * (u * u * u) + this.control0Y * (3 * t * u * u) + this.control1Y * (3 * t * t * u) + this.anchor1Y * (t * t * t)
500
+ p[0] * uuu + p[2] * c0 + p[4] * c1 + p[6] * ttt,
501
+ p[1] * uuu + p[3] * c0 + p[5] * c1 + p[7] * ttt
483
502
  );
484
503
  }
485
504
  /**
@@ -702,13 +721,17 @@ var MutableCubic = class extends Cubic {
702
721
  * @param progress - Interpolation factor [0, 1]
703
722
  */
704
723
  interpolate(c1, c2, progress) {
705
- for (let i = 0; i < 8; i++) {
706
- this.points[i] = interpolate(
707
- c1.points[i],
708
- c2.points[i],
709
- progress
710
- );
711
- }
724
+ const p1 = c1.points;
725
+ const p2 = c2.points;
726
+ const p = this.points;
727
+ p[0] = p1[0] + (p2[0] - p1[0]) * progress;
728
+ p[1] = p1[1] + (p2[1] - p1[1]) * progress;
729
+ p[2] = p1[2] + (p2[2] - p1[2]) * progress;
730
+ p[3] = p1[3] + (p2[3] - p1[3]) * progress;
731
+ p[4] = p1[4] + (p2[4] - p1[4]) * progress;
732
+ p[5] = p1[5] + (p2[5] - p1[5]) * progress;
733
+ p[6] = p1[6] + (p2[6] - p1[6]) * progress;
734
+ p[7] = p1[7] + (p2[7] - p1[7]) * progress;
712
735
  }
713
736
  /**
714
737
  * Mutably applies a PointTransformer to all points.
@@ -1120,6 +1143,36 @@ var RoundedPolygon = class _RoundedPolygon {
1120
1143
  this.centerY + d
1121
1144
  ];
1122
1145
  }
1146
+ /**
1147
+ * Calculates the approximate signed area of the polygon using anchor points.
1148
+ * Returns > 0 for Clockwise (in screen coords, y down), < 0 for Counter-Clockwise.
1149
+ */
1150
+ calculateSignedArea() {
1151
+ let area = 0;
1152
+ const n = this.cubics.length;
1153
+ for (let i = 0; i < n; i++) {
1154
+ const c = this.cubics[i];
1155
+ area += c.anchor0X * c.anchor1Y - c.anchor1X * c.anchor0Y;
1156
+ }
1157
+ return area / 2;
1158
+ }
1159
+ /**
1160
+ * Returns true if the polygon outline runs in Clockwise order (screen coords).
1161
+ */
1162
+ isClockwise() {
1163
+ return this.calculateSignedArea() > 0;
1164
+ }
1165
+ /**
1166
+ * Returns a reversed copy of the polygon with reversed traversal order.
1167
+ * Flips the winding direction (CW ↔ CCW).
1168
+ */
1169
+ reversed() {
1170
+ const reversedFeatures = this.features.slice().reverse().map((f) => reverseFeature(f));
1171
+ return new _RoundedPolygon(
1172
+ reversedFeatures,
1173
+ point(this.centerX, this.centerY)
1174
+ );
1175
+ }
1123
1176
  };
1124
1177
  function buildCubicsList(features) {
1125
1178
  const result = [];
@@ -1188,10 +1241,21 @@ function validateContiguity(cubics) {
1188
1241
 
1189
1242
  // src/shapes/catalog/md3-expressive-shapes.ts
1190
1243
  function createShape(pts) {
1191
- const cubics = pts.map((p) => new Cubic(p));
1192
- return RoundedPolygon.fromFeatures(
1193
- cubics.map((c) => cornerFeature([c], false))
1194
- );
1244
+ let rawArea = 0;
1245
+ for (const p of pts) {
1246
+ rawArea += p[0] * p[7] - p[6] * p[1];
1247
+ }
1248
+ 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;
1249
+ const cubics = normalizedPts.map((p) => new Cubic(p));
1250
+ const n = cubics.length;
1251
+ const features = cubics.map((c, i) => {
1252
+ const prev = cubics[(i - 1 + n) % n].pointOnCurve(0.5);
1253
+ const curr = c.pointOnCurve(0.5);
1254
+ const next = cubics[(i + 1) % n].pointOnCurve(0.5);
1255
+ const isConvex = convex(prev.x, prev.y, curr.x, curr.y, next.x, next.y);
1256
+ return cornerFeature([c], isConvex);
1257
+ });
1258
+ return RoundedPolygon.fromFeatures(features);
1195
1259
  }
1196
1260
  var archShape = createShape([
1197
1261
  [1, 0.83461, 1, 0.8547, 1, 0.86477, 0.99898, 0.87322],
@@ -2289,6 +2353,94 @@ function resolveShape(ref) {
2289
2353
  return shape;
2290
2354
  }
2291
2355
 
2356
+ // src/shapes/catalog/shape-pairings.ts
2357
+ var MD3_SHAPE_PAIRINGS = {
2358
+ // ─── Organic & Floral ──────────────────────────────────────────
2359
+ circle: "flower",
2360
+ flower: "sunny",
2361
+ sunny: "verySunny",
2362
+ verySunny: "flower",
2363
+ bun: "clamshell",
2364
+ clamshell: "bun",
2365
+ puffy: "circle",
2366
+ // ─── Starburst & Explosive ─────────────────────────────────────
2367
+ burst: "softBurst",
2368
+ softBurst: "boom",
2369
+ boom: "softBoom",
2370
+ softBoom: "burst",
2371
+ cookie12Sided: "softBurst",
2372
+ // ─── Clover, Gem & Diamond ─────────────────────────────────────
2373
+ diamond: "puffyDiamond",
2374
+ puffyDiamond: "diamond",
2375
+ clover4Leaf: "clover8Leaf",
2376
+ clover8Leaf: "clover4Leaf",
2377
+ gem: "diamond",
2378
+ heart: "clover4Leaf",
2379
+ // ─── Cookies & Geometric Multi-sided ───────────────────────────
2380
+ cookie4Sided: "cookie6Sided",
2381
+ cookie6Sided: "cookie9Sided",
2382
+ cookie7Sided: "cookie12Sided",
2383
+ cookie9Sided: "cookie7Sided",
2384
+ square: "cookie4Sided",
2385
+ // ─── Rounded & Architectural ───────────────────────────────────
2386
+ pill: "oval",
2387
+ oval: "arch",
2388
+ arch: "semiCircle",
2389
+ semiCircle: "pill",
2390
+ slanted: "arch",
2391
+ // ─── Polygonal, Directional & Pixel ────────────────────────────
2392
+ triangle: "arrow",
2393
+ arrow: "pentagon",
2394
+ pentagon: "triangle",
2395
+ fan: "ghostish",
2396
+ ghostish: "fan",
2397
+ pixelTriangle: "pixelCircle",
2398
+ pixelCircle: "circle"
2399
+ };
2400
+ var MD3_SHAPE_FAMILIES = {
2401
+ organic: [
2402
+ "circle",
2403
+ "flower",
2404
+ "sunny",
2405
+ "verySunny",
2406
+ "bun",
2407
+ "clamshell",
2408
+ "puffy"
2409
+ ],
2410
+ starburst: ["burst", "softBurst", "boom", "softBoom", "cookie12Sided"],
2411
+ cloverAndGems: [
2412
+ "diamond",
2413
+ "puffyDiamond",
2414
+ "clover4Leaf",
2415
+ "clover8Leaf",
2416
+ "gem",
2417
+ "heart"
2418
+ ],
2419
+ cookiesAndPolygons: [
2420
+ "cookie4Sided",
2421
+ "cookie6Sided",
2422
+ "cookie7Sided",
2423
+ "cookie9Sided",
2424
+ "square"
2425
+ ],
2426
+ roundedContainers: ["pill", "oval", "arch", "semiCircle", "slanted"],
2427
+ directionalAndPixel: [
2428
+ "triangle",
2429
+ "arrow",
2430
+ "pentagon",
2431
+ "fan",
2432
+ "ghostish",
2433
+ "pixelTriangle",
2434
+ "pixelCircle"
2435
+ ]
2436
+ };
2437
+ function getRecommendedMorphShape(shape) {
2438
+ if (typeof shape === "string" && shape in MD3_SHAPE_PAIRINGS) {
2439
+ return MD3_SHAPE_PAIRINGS[shape];
2440
+ }
2441
+ return "circle";
2442
+ }
2443
+
2292
2444
  // src/shapes/catalog/shape-tokens.ts
2293
2445
  var MD3CornerRadius = {
2294
2446
  /** 0dp — Sharp corners */
@@ -2454,6 +2606,56 @@ function pillStarVertices(width, height, numVerticesPerRadius, innerRadiusRatio,
2454
2606
  return result;
2455
2607
  }
2456
2608
 
2609
+ // src/shapes/morph/feature-mapping.ts
2610
+ function angleDiff(a1, a2) {
2611
+ let diff = Math.abs(a1 - a2);
2612
+ if (diff > Math.PI) diff = 2 * Math.PI - diff;
2613
+ return diff;
2614
+ }
2615
+ var TWO_PI_SQ = 4 * Math.PI * Math.PI;
2616
+ function featureMapper(features1, features2) {
2617
+ const convex1 = features1.filter((f) => f.convex);
2618
+ const convex2 = features2.filter((f) => f.convex);
2619
+ const set1 = convex1.length > 0 ? convex1 : features1;
2620
+ const set2 = convex2.length > 0 ? convex2 : features2;
2621
+ if (set1.length === 0 || set2.length === 0) {
2622
+ return { map: (v) => v, mapBack: (v) => v };
2623
+ }
2624
+ let bestShift = 0;
2625
+ let minCost = Number.MAX_VALUE;
2626
+ for (const f1 of set1) {
2627
+ for (const f2 of set2) {
2628
+ const shift = positiveModulo(f2.progress - f1.progress, 1);
2629
+ let cost = 0;
2630
+ for (const c1 of set1) {
2631
+ const expected = positiveModulo(c1.progress + shift, 1);
2632
+ let dMin = Number.MAX_VALUE;
2633
+ let matchedC2 = set2[0];
2634
+ for (const c2 of set2) {
2635
+ const diff = Math.abs(expected - c2.progress);
2636
+ const d = diff > 0.5 ? 1 - diff : diff;
2637
+ if (d < dMin) {
2638
+ dMin = d;
2639
+ matchedC2 = c2;
2640
+ }
2641
+ }
2642
+ const progErrorSq = dMin * dMin * TWO_PI_SQ;
2643
+ const angDiff = c1.angle !== void 0 && matchedC2.angle !== void 0 ? angleDiff(c1.angle, matchedC2.angle) : 0;
2644
+ cost += progErrorSq + angDiff * angDiff;
2645
+ if (cost >= minCost) break;
2646
+ }
2647
+ if (cost < minCost) {
2648
+ minCost = cost;
2649
+ bestShift = shift;
2650
+ }
2651
+ }
2652
+ }
2653
+ return {
2654
+ map: (v) => positiveModulo(v + bestShift, 1),
2655
+ mapBack: (v) => positiveModulo(v - bestShift, 1)
2656
+ };
2657
+ }
2658
+
2457
2659
  // src/shapes/morph/float-mapping.ts
2458
2660
  function mapSegments(value, segments) {
2459
2661
  for (const seg of segments) {
@@ -2498,32 +2700,6 @@ function createDoubleMapper(fromValues, toValues) {
2498
2700
  };
2499
2701
  }
2500
2702
 
2501
- // src/shapes/morph/feature-mapping.ts
2502
- function featureMapper(features1, features2) {
2503
- const convex1 = features1.filter((f) => f.convex);
2504
- const convex2 = features2.filter((f) => f.convex);
2505
- if (convex1.length === 0 || convex2.length === 0) {
2506
- return createDoubleMapper([], []);
2507
- }
2508
- const fromValues = [];
2509
- const toValues = [];
2510
- for (const f1 of convex1) {
2511
- let bestDist = Number.MAX_VALUE;
2512
- let bestProgress = 0;
2513
- for (const f2 of convex2) {
2514
- const diff = Math.abs(f1.progress - f2.progress);
2515
- const dist = Math.min(diff, 1 - diff);
2516
- if (dist < bestDist) {
2517
- bestDist = dist;
2518
- bestProgress = f2.progress;
2519
- }
2520
- }
2521
- fromValues.push(f1.progress);
2522
- toValues.push(bestProgress);
2523
- }
2524
- return createDoubleMapper(fromValues, toValues);
2525
- }
2526
-
2527
2703
  // src/shapes/morph/polygon-measure.ts
2528
2704
  var MeasuredPolygon = class _MeasuredPolygon {
2529
2705
  constructor(measuredCubics, features) {
@@ -2557,9 +2733,8 @@ var MeasuredPolygon = class _MeasuredPolygon {
2557
2733
  const t = segLen > 0 ? (cutPoint - cutCubic.startOutlineProgress) / segLen : 0;
2558
2734
  const [left, right] = cutCubic.cubic.split(t);
2559
2735
  const shift = (p) => {
2560
- let s = p - cutPoint;
2561
- if (s < 0) s += 1;
2562
- return s;
2736
+ const s = p - cutPoint;
2737
+ return s < 0 ? s + 1 : s;
2563
2738
  };
2564
2739
  if (!right.zeroLength()) {
2565
2740
  result.push({
@@ -2568,9 +2743,19 @@ var MeasuredPolygon = class _MeasuredPolygon {
2568
2743
  endOutlineProgress: shift(cutCubic.endOutlineProgress)
2569
2744
  });
2570
2745
  }
2571
- for (let i = 1; i < this.measuredCubics.length; i++) {
2572
- const idx = (cutCubicIdx + i) % this.measuredCubics.length;
2573
- const mc = this.measuredCubics[idx];
2746
+ const totalCubics = this.measuredCubics.length;
2747
+ for (let i = cutCubicIdx + 1; i < totalCubics; i++) {
2748
+ const mc = this.measuredCubics[i];
2749
+ if (!mc.cubic.zeroLength()) {
2750
+ result.push({
2751
+ cubic: mc.cubic,
2752
+ startOutlineProgress: shift(mc.startOutlineProgress),
2753
+ endOutlineProgress: shift(mc.endOutlineProgress)
2754
+ });
2755
+ }
2756
+ }
2757
+ for (let i = 0; i < cutCubicIdx; i++) {
2758
+ const mc = this.measuredCubics[i];
2574
2759
  if (!mc.cubic.zeroLength()) {
2575
2760
  result.push({
2576
2761
  cubic: mc.cubic,
@@ -2652,7 +2837,16 @@ var MeasuredPolygon = class _MeasuredPolygon {
2652
2837
  const mc = measured[Math.min(cubicIdx + middleCubicIdx, measured.length - 1)];
2653
2838
  if (mc) {
2654
2839
  const midProgress = (mc.startOutlineProgress + mc.endOutlineProgress) / 2;
2655
- featureList.push({ progress: midProgress, convex: feature.convex });
2840
+ const pt = mc.cubic.pointOnCurve(0.5);
2841
+ const angle = Math.atan2(
2842
+ pt.y - polygon.centerY,
2843
+ pt.x - polygon.centerX
2844
+ );
2845
+ featureList.push({
2846
+ progress: midProgress,
2847
+ convex: feature.convex,
2848
+ angle
2849
+ });
2656
2850
  }
2657
2851
  }
2658
2852
  cubicIdx += feature.cubics.length;
@@ -2662,18 +2856,30 @@ var MeasuredPolygon = class _MeasuredPolygon {
2662
2856
  };
2663
2857
  function approximateLength(cubic) {
2664
2858
  let len = 0;
2665
- let prevX = cubic.anchor0X, prevY = cubic.anchor0Y;
2859
+ const p = cubic.points;
2860
+ let prevX = p[0];
2861
+ let prevY = p[1];
2666
2862
  const steps = 4;
2667
2863
  for (let i = 1; i <= steps; i++) {
2668
- const p = cubic.pointOnCurve(i / steps);
2669
- len += distance(p.x - prevX, p.y - prevY);
2670
- prevX = p.x;
2671
- prevY = p.y;
2864
+ const t = i / steps;
2865
+ const u = 1 - t;
2866
+ const uu = u * u;
2867
+ const tt = t * t;
2868
+ const uuu = uu * u;
2869
+ const ttt = tt * t;
2870
+ const c0 = 3 * t * uu;
2871
+ const c1 = 3 * tt * u;
2872
+ const px = p[0] * uuu + p[2] * c0 + p[4] * c1 + p[6] * ttt;
2873
+ const py = p[1] * uuu + p[3] * c0 + p[5] * c1 + p[7] * ttt;
2874
+ len += distance(px - prevX, py - prevY);
2875
+ prevX = px;
2876
+ prevY = py;
2672
2877
  }
2673
2878
  return len;
2674
2879
  }
2675
2880
 
2676
2881
  // src/shapes/morph/morph.ts
2882
+ var morphMatchCache = /* @__PURE__ */ new WeakMap();
2677
2883
  var Morph = class _Morph {
2678
2884
  /**
2679
2885
  * Creates a Morph between two shapes.
@@ -2689,23 +2895,79 @@ var Morph = class _Morph {
2689
2895
  * Returns the interpolated shape at the given progress as a list of Cubics.
2690
2896
  *
2691
2897
  * Note: This allocates a new list. For performance-critical animation loops,
2692
- * use {@link forEachCubic} instead.
2898
+ * use {@link toSvgPath} or {@link forEachCubic} instead.
2693
2899
  *
2694
2900
  * @param progress - Value in [0, 1]. 0 = start shape, 1 = end shape.
2695
2901
  * Values outside [0, 1] produce exaggerated shapes (useful for bounce/overshoot).
2696
2902
  * @returns List of interpolated Cubic curves forming the morphed shape
2697
2903
  */
2698
2904
  asCubics(progress) {
2699
- const result = [];
2700
- for (const [c1, c2] of this.morphMatch) {
2701
- result.push(
2702
- new Cubic(
2703
- c1.points.map((v, i) => interpolate(v, c2.points[i], progress))
2704
- )
2705
- );
2905
+ const match = this.morphMatch;
2906
+ const len = match.length;
2907
+ const result = new Array(len);
2908
+ for (let i = 0; i < len; i++) {
2909
+ const [c1, c2] = match[i];
2910
+ const p1 = c1.points;
2911
+ const p2 = c2.points;
2912
+ result[i] = new Cubic([
2913
+ p1[0] + (p2[0] - p1[0]) * progress,
2914
+ p1[1] + (p2[1] - p1[1]) * progress,
2915
+ p1[2] + (p2[2] - p1[2]) * progress,
2916
+ p1[3] + (p2[3] - p1[3]) * progress,
2917
+ p1[4] + (p2[4] - p1[4]) * progress,
2918
+ p1[5] + (p2[5] - p1[5]) * progress,
2919
+ p1[6] + (p2[6] - p1[6]) * progress,
2920
+ p1[7] + (p2[7] - p1[7]) * progress
2921
+ ]);
2706
2922
  }
2707
2923
  return result;
2708
2924
  }
2925
+ /**
2926
+ * Returns an SVG path data string for the morphed shape at the given progress.
2927
+ * Directly evaluates coordinates without allocating intermediate Cubic objects.
2928
+ *
2929
+ * @param progress - Value in [0, 1]
2930
+ * @param width - Target pixel width (default: 1)
2931
+ * @param height - Target pixel height (default: 1)
2932
+ */
2933
+ toSvgPath(progress, width = 1, height = 1) {
2934
+ const match = this.morphMatch;
2935
+ const len = match.length;
2936
+ if (len === 0) return "";
2937
+ const paddingX = width * 0.015;
2938
+ const paddingY = height * 0.015;
2939
+ const sx = width - 2 * paddingX;
2940
+ const sy = height - 2 * paddingY;
2941
+ const [firstC1, firstC2] = match[0];
2942
+ const f1 = firstC1.points;
2943
+ const f2 = firstC2.points;
2944
+ const a0x = f1[0] + (f2[0] - f1[0]) * progress;
2945
+ const a0y = f1[1] + (f2[1] - f1[1]) * progress;
2946
+ let d = `M ${formatCoordinate(paddingX + a0x * sx)} ${formatCoordinate(paddingY + sy * (1 - a0y))}`;
2947
+ for (let i = 0; i < len; i++) {
2948
+ const [c1, c2] = match[i];
2949
+ const p1 = c1.points;
2950
+ const p2 = c2.points;
2951
+ const c0x = p1[2] + (p2[2] - p1[2]) * progress;
2952
+ const c0y = p1[3] + (p2[3] - p1[3]) * progress;
2953
+ const c1x = p1[4] + (p2[4] - p1[4]) * progress;
2954
+ const c1y = p1[5] + (p2[5] - p1[5]) * progress;
2955
+ const a1x = p1[6] + (p2[6] - p1[6]) * progress;
2956
+ const a1y = p1[7] + (p2[7] - p1[7]) * progress;
2957
+ 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))}`;
2958
+ }
2959
+ return `${d} Z`;
2960
+ }
2961
+ /**
2962
+ * Returns a CSS clip-path value for the morphed shape at the given progress.
2963
+ *
2964
+ * @param progress - Value in [0, 1]
2965
+ * @param width - Element width in pixels
2966
+ * @param height - Element height in pixels
2967
+ */
2968
+ toClipPath(progress, width, height) {
2969
+ return `path('${this.toSvgPath(progress, width, height)}')`;
2970
+ }
2709
2971
  /**
2710
2972
  * Iterates over the morphed cubics without allocating new Cubic instances.
2711
2973
  * Reuses a single MutableCubic for each callback invocation.
@@ -2779,8 +3041,15 @@ var Morph = class _Morph {
2779
3041
  * @internal
2780
3042
  */
2781
3043
  static match(p1, p2) {
2782
- const measured1 = MeasuredPolygon.measurePolygon(p1);
2783
- const measured2 = MeasuredPolygon.measurePolygon(p2);
3044
+ let cachedMap = morphMatchCache.get(p1);
3045
+ if (cachedMap) {
3046
+ const cached = cachedMap.get(p2);
3047
+ if (cached) return cached;
3048
+ }
3049
+ const poly1 = p1.isClockwise() ? p1 : p1.reversed();
3050
+ const poly2 = p2.isClockwise() ? p2 : p2.reversed();
3051
+ const measured1 = MeasuredPolygon.measurePolygon(poly1);
3052
+ const measured2 = MeasuredPolygon.measurePolygon(poly2);
2784
3053
  const doubleMapper = featureMapper(measured1.features, measured2.features);
2785
3054
  const polygon2CutPoint = doubleMapper.map(0);
2786
3055
  const bs1 = measured1;
@@ -2791,11 +3060,12 @@ var Morph = class _Morph {
2791
3060
  let b2 = bs2.getOrNull(i2++);
2792
3061
  while (b1 !== null && b2 !== null) {
2793
3062
  const b1a = i1 >= bs1.size ? 1 : b1.endOutlineProgress;
2794
- const b2aRaw = i2 >= bs2.size ? 1 : positiveModulo(b2.endOutlineProgress + polygon2CutPoint, 1);
2795
- const b2a = doubleMapper.mapBack(b2aRaw);
3063
+ const b2a = i2 >= bs2.size ? 1 : b2.endOutlineProgress;
2796
3064
  const minb = Math.min(b1a, b2a);
2797
- let seg1 = b1, newb1 = bs1.getOrNull(i1);
2798
- let seg2 = b2, newb2 = bs2.getOrNull(i2);
3065
+ let seg1 = b1;
3066
+ let newb1 = bs1.getOrNull(i1);
3067
+ let seg2 = b2;
3068
+ let newb2 = bs2.getOrNull(i2);
2799
3069
  if (b1a > minb + ANGLE_EPSILON) {
2800
3070
  const [cut, rest] = bs1.cutAtProgress(b1, minb);
2801
3071
  seg1 = cut;
@@ -2804,11 +3074,7 @@ var Morph = class _Morph {
2804
3074
  i1++;
2805
3075
  }
2806
3076
  if (b2a > minb + ANGLE_EPSILON) {
2807
- const targetProgress = positiveModulo(
2808
- doubleMapper.map(minb) - polygon2CutPoint,
2809
- 1
2810
- );
2811
- const [cut, rest] = bs2.cutAtProgress(b2, targetProgress);
3077
+ const [cut, rest] = bs2.cutAtProgress(b2, minb);
2812
3078
  seg2 = cut;
2813
3079
  newb2 = rest;
2814
3080
  } else {
@@ -2818,39 +3084,37 @@ var Morph = class _Morph {
2818
3084
  b1 = newb1;
2819
3085
  b2 = newb2;
2820
3086
  }
3087
+ if (!cachedMap) {
3088
+ cachedMap = /* @__PURE__ */ new WeakMap();
3089
+ morphMatchCache.set(p1, cachedMap);
3090
+ }
3091
+ cachedMap.set(p2, result);
2821
3092
  return result;
2822
3093
  }
2823
3094
  };
2824
3095
 
2825
3096
  // src/shapes/render/shape-rendering.ts
2826
3097
  function toSvgPath(cubics, width = 1, height = 1) {
2827
- if (cubics.length === 0) return "";
3098
+ const len = cubics.length;
3099
+ if (len === 0) return "";
2828
3100
  const paddingX = width * 0.015;
2829
3101
  const paddingY = height * 0.015;
2830
3102
  const sx = width - 2 * paddingX;
2831
3103
  const sy = height - 2 * paddingY;
2832
- const flipY = (y) => paddingY + sy * (1 - y);
2833
- const parts = [
2834
- `M ${fmt(paddingX + cubics[0].anchor0X * sx)} ${fmt(flipY(cubics[0].anchor0Y))}`
2835
- ];
2836
- for (const c of cubics) {
2837
- parts.push(
2838
- `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))}`
2839
- );
3104
+ const c0 = cubics[0];
3105
+ let d = `M ${formatCoordinate(paddingX + c0.anchor0X * sx)} ${formatCoordinate(paddingY + sy * (1 - c0.anchor0Y))}`;
3106
+ for (let i = 0; i < len; i++) {
3107
+ const c = cubics[i];
3108
+ 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))}`;
2840
3109
  }
2841
- parts.push("Z");
2842
- return parts.join(" ");
3110
+ return `${d} Z`;
2843
3111
  }
2844
3112
  function toClipPath(polygon, width, height) {
2845
3113
  const pathData = toSvgPath(polygon.cubics, width, height);
2846
3114
  return `path('${pathData}')`;
2847
3115
  }
2848
3116
  function interpolatePath(morph, progress, width, height) {
2849
- const cubics = morph.asCubics(progress);
2850
- return toClipPath({ cubics }, width, height);
2851
- }
2852
- function fmt(v) {
2853
- return Number(v.toFixed(4)).toString();
3117
+ return morph.toClipPath(progress, width, height);
2854
3118
  }
2855
3119
  function cn(...inputs) {
2856
3120
  return tailwindMerge.twMerge(clsx.clsx(inputs));
@@ -2860,7 +3124,7 @@ function getMaskGradient(direction) {
2860
3124
  case "bottom":
2861
3125
  return "linear-gradient(to top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 1) 45%, rgba(0, 0, 0, 0.7) 75%, rgba(0, 0, 0, 0) 100%)";
2862
3126
  case "both":
2863
- return "linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 20%, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 1) 60%, rgba(0, 0, 0, 0.7) 80%, rgba(0, 0, 0, 0) 100%)";
3127
+ return "linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.7) 15%, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0.7) 85%, rgba(0, 0, 0, 1) 100%)";
2864
3128
  default:
2865
3129
  return "linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 1) 45%, rgba(0, 0, 0, 0.7) 75%, rgba(0, 0, 0, 0) 100%)";
2866
3130
  }
@@ -2877,11 +3141,16 @@ function FadingBlurMask({
2877
3141
  const shouldReduceMotion = react.useReducedMotion();
2878
3142
  const activeBlur = shouldReduceMotion ? 0 : blurIntensity;
2879
3143
  const maskGradient = getMaskGradient(direction);
3144
+ const isFullHeight = direction === "both" || blurHeight === "100%";
3145
+ const computedHeight = isFullHeight ? "100%" : typeof blurHeight === "number" ? `${blurHeight}px` : blurHeight;
2880
3146
  const maskStyle = __spreadValues({
2881
3147
  position: "absolute",
2882
- inset: 0,
3148
+ top: direction === "bottom" && !isFullHeight ? "auto" : 0,
3149
+ bottom: direction === "top" && !isFullHeight ? "auto" : 0,
3150
+ left: 0,
3151
+ right: 0,
2883
3152
  pointerEvents: "none",
2884
- height: typeof blurHeight === "number" ? `${blurHeight}px` : blurHeight,
3153
+ height: computedHeight,
2885
3154
  backdropFilter: activeBlur > 0 ? `blur(${activeBlur}px)` : void 0,
2886
3155
  WebkitBackdropFilter: activeBlur > 0 ? `blur(${activeBlur}px)` : void 0,
2887
3156
  maskImage: maskGradient,
@@ -2893,7 +3162,7 @@ function FadingBlurMask({
2893
3162
  {
2894
3163
  "aria-hidden": "true",
2895
3164
  className: cn(
2896
- "absolute inset-0 pointer-events-none z-0 rounded-[inherit]",
3165
+ "absolute pointer-events-none z-10 rounded-[inherit]",
2897
3166
  className
2898
3167
  ),
2899
3168
  style: maskStyle,
@@ -4021,7 +4290,7 @@ var IconComponent = React67__namespace.forwardRef(
4021
4290
  (_a, ref) => {
4022
4291
  var _b = _a, {
4023
4292
  name,
4024
- variant = "outlined",
4293
+ variant = "rounded",
4025
4294
  fill = 0,
4026
4295
  weight = 400,
4027
4296
  grade = 0,
@@ -8356,6 +8625,7 @@ var ExtendedFABComponent = React67__namespace.forwardRef(
8356
8625
  onClick,
8357
8626
  onKeyDown,
8358
8627
  layoutId,
8628
+ layout,
8359
8629
  "aria-label": ariaLabel
8360
8630
  } = _b, restProps = __objRest(_b, [
8361
8631
  "className",
@@ -8377,6 +8647,7 @@ var ExtendedFABComponent = React67__namespace.forwardRef(
8377
8647
  "onClick",
8378
8648
  "onKeyDown",
8379
8649
  "layoutId",
8650
+ "layout",
8380
8651
  "aria-label"
8381
8652
  ]);
8382
8653
  var _a2, _b2, _c, _d;
@@ -8401,6 +8672,13 @@ var ExtendedFABComponent = React67__namespace.forwardRef(
8401
8672
  const colors = (_a2 = COLOR_CLASSES[colorStyle]) != null ? _a2 : COLOR_CLASSES.primary;
8402
8673
  const radiusConfig = (_b2 = MORPH_RADIUS[size]) != null ? _b2 : MORPH_RADIUS.sm;
8403
8674
  const sizeIcon = (_c = SIZE_ICON[size]) != null ? _c : SIZE_ICON.sm;
8675
+ const motionRadius = react.useMotionValue(radiusConfig.default);
8676
+ React67__namespace.useEffect(() => {
8677
+ const controls = react.animate(motionRadius, radiusConfig.default, __spreadProps(__spreadValues({}, SPRING_TRANSITION), {
8678
+ type: "spring"
8679
+ }));
8680
+ return () => controls.stop();
8681
+ }, [radiusConfig.default, motionRadius]);
8404
8682
  const { ripples, onPointerDown, removeRipple } = useRippleState({
8405
8683
  disabled: loading
8406
8684
  });
@@ -8495,13 +8773,25 @@ var ExtendedFABComponent = React67__namespace.forwardRef(
8495
8773
  {
8496
8774
  layout: "position",
8497
8775
  initial: { opacity: 0, width: 0 },
8498
- animate: { opacity: 1, width: "auto" },
8499
- exit: { opacity: 0, width: 0 },
8500
- transition: {
8501
- opacity: { duration: 0.15, ease: "linear" },
8502
- width: SPRING_TRANSITION
8776
+ animate: {
8777
+ opacity: 1,
8778
+ width: "auto",
8779
+ transition: {
8780
+ width: SPRING_TRANSITION,
8781
+ opacity: { delay: 0.08, duration: 0.15, ease: "easeIn" },
8782
+ layout: SPRING_TRANSITION
8783
+ }
8784
+ },
8785
+ exit: {
8786
+ opacity: 0,
8787
+ width: 0,
8788
+ transition: {
8789
+ opacity: { duration: 0.1, ease: "linear" },
8790
+ width: __spreadProps(__spreadValues({}, SPRING_TRANSITION), { delay: 0.03 }),
8791
+ layout: SPRING_TRANSITION
8792
+ }
8503
8793
  },
8504
- className: "overflow-hidden whitespace-nowrap",
8794
+ className: "overflow-hidden whitespace-nowrap shrink-0 inline-block",
8505
8795
  children: label
8506
8796
  },
8507
8797
  "label"
@@ -8532,7 +8822,7 @@ var ExtendedFABComponent = React67__namespace.forwardRef(
8532
8822
  __spreadProps(__spreadValues({
8533
8823
  ref: localRef,
8534
8824
  type: "button",
8535
- layout: true,
8825
+ layout: layout !== void 0 ? layout : "position",
8536
8826
  layoutId,
8537
8827
  "aria-label": ariaLabel || label,
8538
8828
  "aria-busy": loading || void 0,
@@ -8540,21 +8830,23 @@ var ExtendedFABComponent = React67__namespace.forwardRef(
8540
8830
  onClick: handleClick,
8541
8831
  onPointerDown,
8542
8832
  onKeyDown: handleKeyDown,
8543
- style,
8833
+ style: __spreadProps(__spreadValues({}, style), {
8834
+ borderRadius: motionRadius
8835
+ }),
8544
8836
  initial: {
8545
8837
  scale: 0.6,
8546
- opacity: 0,
8547
- borderRadius: radiusConfig.default
8838
+ opacity: 0
8548
8839
  },
8549
8840
  animate: {
8550
8841
  scale: 1,
8551
- opacity: 1,
8552
- borderRadius: radiusConfig.default
8842
+ opacity: 1
8553
8843
  },
8554
8844
  exit: { scale: 0.6, opacity: 0 },
8555
- whileTap: { borderRadius: radiusConfig.pressed },
8845
+ whileTap: {
8846
+ borderRadius: radiusConfig.pressed,
8847
+ transition: { borderRadius: SPRING_TRANSITION_FAST }
8848
+ },
8556
8849
  transition: {
8557
- borderRadius: { type: "spring", stiffness: 500, damping: 30 },
8558
8850
  scale: SPRING_TRANSITION,
8559
8851
  opacity: { duration: 0.2, ease: "linear" },
8560
8852
  layout: SPRING_TRANSITION
@@ -8586,6 +8878,18 @@ var SIZE_TEXT_CLASS = {
8586
8878
  lg: "text-xl font-semibold",
8587
8879
  xl: "text-2xl font-semibold"
8588
8880
  };
8881
+ var SIZE_PADDING_COLLAPSED = {
8882
+ sm: "px-2",
8883
+ md: "px-4",
8884
+ lg: "px-8",
8885
+ xl: "px-12"
8886
+ };
8887
+ var SIZE_PADDING_EXTENDED = {
8888
+ sm: "pl-2 pr-4",
8889
+ md: "pl-4 pr-6",
8890
+ lg: "pl-8 pr-8",
8891
+ xl: "pl-12 pr-10"
8892
+ };
8589
8893
  var MORPH_RADIUS2 = {
8590
8894
  sm: { default: 12, pressed: 8, extended: 12, extended_pressed: 8 },
8591
8895
  md: { default: 16, pressed: 10, extended: 16, extended_pressed: 10 },
@@ -8677,7 +8981,7 @@ var FABComponent = React67__namespace.forwardRef(
8677
8981
  "layout",
8678
8982
  "layoutId"
8679
8983
  ]);
8680
- var _a2, _b2, _c, _d;
8984
+ var _a2, _b2, _c, _d, _e, _f;
8681
8985
  const colors = (_a2 = COLOR_CLASSES2[colorStyle]) != null ? _a2 : COLOR_CLASSES2.primary;
8682
8986
  const radiusConfig = (_b2 = MORPH_RADIUS2[size]) != null ? _b2 : MORPH_RADIUS2.md;
8683
8987
  const animateRadius = extended ? radiusConfig.extended : radiusConfig.default;
@@ -8762,22 +9066,37 @@ var FABComponent = React67__namespace.forwardRef(
8762
9066
  react.m.span,
8763
9067
  {
8764
9068
  layout: "position",
8765
- initial: { width: 0, opacity: 0 },
8766
- animate: { width: "auto", opacity: 1 },
8767
- exit: { width: 0, opacity: 0 },
8768
- transition: {
8769
- opacity: { duration: 0.15, ease: "linear" },
8770
- width: SPRING_TRANSITION,
8771
- layout: SPRING_TRANSITION
9069
+ initial: { width: 0, opacity: 0, marginLeft: 0 },
9070
+ animate: {
9071
+ width: "auto",
9072
+ opacity: 1,
9073
+ marginLeft: 12,
9074
+ transition: {
9075
+ width: SPRING_TRANSITION,
9076
+ marginLeft: SPRING_TRANSITION,
9077
+ opacity: { delay: 0.08, duration: 0.15, ease: "easeIn" },
9078
+ layout: SPRING_TRANSITION
9079
+ }
8772
9080
  },
8773
- className: "overflow-hidden whitespace-nowrap ml-3",
9081
+ exit: {
9082
+ width: 0,
9083
+ opacity: 0,
9084
+ marginLeft: 0,
9085
+ transition: {
9086
+ opacity: { duration: 0.1, ease: "linear" },
9087
+ width: __spreadProps(__spreadValues({}, SPRING_TRANSITION), { delay: 0.03 }),
9088
+ marginLeft: __spreadProps(__spreadValues({}, SPRING_TRANSITION), { delay: 0.03 }),
9089
+ layout: SPRING_TRANSITION
9090
+ }
9091
+ },
9092
+ className: "overflow-hidden whitespace-nowrap shrink-0 inline-block",
8774
9093
  children: labelContent
8775
9094
  },
8776
9095
  "label"
8777
9096
  ) })
8778
9097
  ] });
8779
9098
  const containerClassName = cn(
8780
- "relative shrink-0 inline-flex items-center justify-center",
9099
+ "relative shrink-0 inline-flex items-center justify-start",
8781
9100
  "select-none cursor-pointer overflow-hidden",
8782
9101
  "transition-[box-shadow,opacity,filter] duration-200",
8783
9102
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-m3-primary focus-visible:ring-offset-2",
@@ -8786,21 +9105,62 @@ var FABComponent = React67__namespace.forwardRef(
8786
9105
  colors.text,
8787
9106
  lowered ? "shadow-sm" : colors.shadow,
8788
9107
  (_d = SIZE_STYLES[size]) != null ? _d : "h-14 w-14",
8789
- extended && "w-auto pl-4 pr-6",
9108
+ extended ? cn("w-auto", (_e = SIZE_PADDING_EXTENDED[size]) != null ? _e : "pl-4 pr-6") : (_f = SIZE_PADDING_COLLAPSED[size]) != null ? _f : "px-4",
8790
9109
  SIZE_TEXT_CLASS[size],
8791
9110
  loading && "pointer-events-none opacity-75 cursor-not-allowed",
8792
9111
  className
8793
9112
  );
9113
+ const motionRadius = react.useMotionValue(animateRadius);
9114
+ const asChildRef = React67__namespace.useRef(null);
9115
+ const mergedRef = React67__namespace.useCallback(
9116
+ (node) => {
9117
+ asChildRef.current = node;
9118
+ if (typeof ref === "function") ref(node);
9119
+ else if (ref)
9120
+ ref.current = node;
9121
+ },
9122
+ [ref]
9123
+ );
9124
+ React67__namespace.useEffect(() => {
9125
+ if (!asChild) return;
9126
+ return motionRadius.on("change", (v) => {
9127
+ if (asChildRef.current)
9128
+ asChildRef.current.style.borderRadius = `${v}px`;
9129
+ });
9130
+ }, [motionRadius, asChild]);
9131
+ React67__namespace.useEffect(() => {
9132
+ const controls = react.animate(motionRadius, animateRadius, __spreadProps(__spreadValues({}, SPRING_TRANSITION), {
9133
+ type: "spring"
9134
+ }));
9135
+ return () => controls.stop();
9136
+ }, [animateRadius, motionRadius]);
9137
+ const handleAsChildPointerDown = React67__namespace.useCallback(
9138
+ (e) => {
9139
+ onPointerDown(e);
9140
+ react.animate(motionRadius, pressedRadius, __spreadProps(__spreadValues({}, SPRING_TRANSITION_FAST), {
9141
+ type: "spring"
9142
+ }));
9143
+ },
9144
+ [onPointerDown, motionRadius, pressedRadius]
9145
+ );
9146
+ const handleAsChildPointerUp = React67__namespace.useCallback(() => {
9147
+ react.animate(motionRadius, animateRadius, __spreadProps(__spreadValues({}, SPRING_TRANSITION_FAST), {
9148
+ type: "spring"
9149
+ }));
9150
+ }, [motionRadius, animateRadius]);
8794
9151
  const computedAriaLabel = ariaLabel || (typeof children === "string" ? children : void 0);
8795
9152
  return /* @__PURE__ */ jsxRuntime.jsx(react.LazyMotion, { features: react.domMax, strict: true, children: /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: visible && (asChild ? /* @__PURE__ */ jsxRuntime.jsx(
8796
9153
  reactSlot.Slot,
8797
9154
  __spreadProps(__spreadValues({
8798
- ref,
9155
+ ref: mergedRef,
8799
9156
  "aria-label": computedAriaLabel,
8800
9157
  "aria-busy": loading || void 0,
8801
9158
  "aria-disabled": loading || restProps.disabled,
8802
9159
  onClick: handleClick,
8803
- onPointerDown,
9160
+ onPointerDown: handleAsChildPointerDown,
9161
+ onPointerUp: handleAsChildPointerUp,
9162
+ onPointerLeave: handleAsChildPointerUp,
9163
+ onPointerCancel: handleAsChildPointerUp,
8804
9164
  onKeyDown: handleKeyDown,
8805
9165
  style: __spreadProps(__spreadValues({}, style), {
8806
9166
  borderRadius: `${animateRadius}px`
@@ -8817,7 +9177,7 @@ var FABComponent = React67__namespace.forwardRef(
8817
9177
  __spreadProps(__spreadValues({
8818
9178
  ref,
8819
9179
  type: "button",
8820
- layout: layout !== void 0 ? layout : true,
9180
+ layout: layout !== void 0 ? layout : "position",
8821
9181
  layoutId,
8822
9182
  "aria-label": computedAriaLabel,
8823
9183
  "aria-busy": loading || void 0,
@@ -8825,17 +9185,20 @@ var FABComponent = React67__namespace.forwardRef(
8825
9185
  onClick: handleClick,
8826
9186
  onPointerDown,
8827
9187
  onKeyDown: handleKeyDown,
8828
- style,
9188
+ style: __spreadProps(__spreadValues({}, style), {
9189
+ borderRadius: motionRadius
9190
+ }),
8829
9191
  initial: {
8830
9192
  scale: 0.5,
8831
- opacity: 0,
8832
- borderRadius: animateRadius
9193
+ opacity: 0
8833
9194
  },
8834
- animate: { scale: 1, opacity: 1, borderRadius: animateRadius },
9195
+ animate: { scale: 1, opacity: 1 },
8835
9196
  exit: { scale: 0.5, opacity: 0 },
8836
- whileTap: { borderRadius: pressedRadius },
9197
+ whileTap: {
9198
+ borderRadius: pressedRadius,
9199
+ transition: { borderRadius: SPRING_TRANSITION_FAST }
9200
+ },
8837
9201
  transition: {
8838
- borderRadius: SPRING_TRANSITION_FAST,
8839
9202
  scale: SPRING_TRANSITION,
8840
9203
  opacity: { duration: 0.25, ease: "easeOut" },
8841
9204
  layout: SPRING_TRANSITION
@@ -13312,7 +13675,7 @@ var CalendarGrid = ({
13312
13675
  ] });
13313
13676
  };
13314
13677
  CalendarGrid.displayName = "CalendarGrid";
13315
- var selectorClassName = "flex items-center gap-1 rounded-m3-full px-2 py-1 text-[length:var(--md-typescale-title-small-size,14px)] font-[number:var(--md-typescale-title-small-weight,500)] text-m3-on-surface transition-m3-fast-effects hover:bg-m3-on-surface/8 focus-visible:outline-2 focus-visible:outline-m3-primary";
13678
+ var selectorClassName = "flex items-center gap-1 rounded-m3-full px-2 py-1 text-[length:var(--md-typescale-title-small-size,14px)] font-[number:var(--md-typescale-title-small-weight,500)] text-m3-on-surface transition-m3-fast-effects hover:bg-m3-on-surface/8 focus-visible:outline-2 focus-visible:outline-m3-primary whitespace-nowrap select-none min-w-0";
13316
13679
  var CalendarHeader = ({
13317
13680
  displayedMonthMs,
13318
13681
  activeSelector,
@@ -13338,57 +13701,70 @@ var CalendarHeader = ({
13338
13701
  timeZone: "UTC"
13339
13702
  }).format(date);
13340
13703
  const yearLabel = String(date.getUTCFullYear());
13341
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 px-6 pb-4 pt-5", children: [
13342
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-(length:--md-typescale-label-large-size,14px) font-(--md-typescale-label-large-weight,500) text-m3-on-surface-variant", children: title }),
13343
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 leading-tight text-(length:--md-typescale-headline-large-size,32px) font-(--md-typescale-headline-large-weight,400) text-m3-on-surface-variant", children: headline }),
13344
- displayMode === "picker" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-10 items-center gap-0.5", children: [
13345
- activeSelector === null && /* @__PURE__ */ jsxRuntime.jsx(
13346
- IconButton,
13347
- {
13348
- onClick: onPrev,
13349
- "aria-label": "Previous month",
13350
- disabled: !canNavigatePrev,
13351
- size: "xs",
13352
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron_left" })
13353
- }
13354
- ),
13355
- /* @__PURE__ */ jsxRuntime.jsxs(
13356
- "button",
13357
- {
13358
- type: "button",
13359
- onClick: () => onToggleSelector("month"),
13360
- "aria-expanded": activeSelector === "month",
13361
- "aria-controls": "date-picker-selection",
13362
- className: cn(
13363
- selectorClassName,
13364
- activeSelector === "month" && "bg-m3-on-surface/8"
13365
- ),
13366
- children: [
13367
- monthLabel,
13368
- /* @__PURE__ */ jsxRuntime.jsx(
13369
- Icon,
13370
- {
13371
- name: "arrow_drop_down",
13372
- className: cn(
13373
- "text-[20px] transition-transform duration-200",
13374
- activeSelector === "month" && "rotate-180"
13375
- )
13376
- }
13377
- )
13378
- ]
13379
- }
13380
- ),
13381
- activeSelector === null && /* @__PURE__ */ jsxRuntime.jsx(
13382
- IconButton,
13383
- {
13384
- onClick: onNext,
13385
- "aria-label": "Next month",
13386
- disabled: !canNavigateNext,
13387
- size: "xs",
13388
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron_right" })
13389
- }
13390
- ),
13391
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex items-center gap-0.5", children: [
13704
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 px-4 sm:px-6 pb-3 pt-5 w-full", children: [
13705
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-(length:--md-typescale-label-large-size,14px) font-(--md-typescale-label-large-weight,500) text-m3-on-surface-variant truncate", children: title }),
13706
+ /* @__PURE__ */ jsxRuntime.jsx(
13707
+ "div",
13708
+ {
13709
+ className: "mb-2 leading-tight text-[26px] sm:text-[32px] font-(--md-typescale-headline-large-weight,400) text-m3-on-surface-variant truncate",
13710
+ title: typeof headline === "string" ? headline : void 0,
13711
+ children: headline
13712
+ }
13713
+ ),
13714
+ displayMode === "picker" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-10 items-center justify-between gap-0.5 w-full overflow-hidden", children: [
13715
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5 min-w-0 shrink", children: [
13716
+ activeSelector === null && /* @__PURE__ */ jsxRuntime.jsx(
13717
+ IconButton,
13718
+ {
13719
+ onClick: onPrev,
13720
+ "aria-label": "Previous month",
13721
+ disabled: !canNavigatePrev,
13722
+ size: "xs",
13723
+ className: "shrink-0",
13724
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron_left" })
13725
+ }
13726
+ ),
13727
+ /* @__PURE__ */ jsxRuntime.jsxs(
13728
+ "button",
13729
+ {
13730
+ type: "button",
13731
+ onClick: () => onToggleSelector("month"),
13732
+ "aria-expanded": activeSelector === "month",
13733
+ "aria-controls": "date-picker-selection",
13734
+ className: cn(
13735
+ selectorClassName,
13736
+ "min-w-0 max-w-[125px] shrink",
13737
+ activeSelector === "month" && "bg-m3-on-surface/8"
13738
+ ),
13739
+ title: monthLabel,
13740
+ children: [
13741
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: monthLabel }),
13742
+ /* @__PURE__ */ jsxRuntime.jsx(
13743
+ Icon,
13744
+ {
13745
+ name: "arrow_drop_down",
13746
+ className: cn(
13747
+ "text-[20px] shrink-0 transition-transform duration-200",
13748
+ activeSelector === "month" && "rotate-180"
13749
+ )
13750
+ }
13751
+ )
13752
+ ]
13753
+ }
13754
+ ),
13755
+ activeSelector === null && /* @__PURE__ */ jsxRuntime.jsx(
13756
+ IconButton,
13757
+ {
13758
+ onClick: onNext,
13759
+ "aria-label": "Next month",
13760
+ disabled: !canNavigateNext,
13761
+ size: "xs",
13762
+ className: "shrink-0",
13763
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron_right" })
13764
+ }
13765
+ )
13766
+ ] }),
13767
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex items-center gap-0.5 shrink-0", children: [
13392
13768
  activeSelector === null && /* @__PURE__ */ jsxRuntime.jsx(
13393
13769
  IconButton,
13394
13770
  {
@@ -13396,6 +13772,7 @@ var CalendarHeader = ({
13396
13772
  "aria-label": "Previous year",
13397
13773
  disabled: !canNavigatePreviousYear,
13398
13774
  size: "xs",
13775
+ className: "shrink-0",
13399
13776
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron_left" })
13400
13777
  }
13401
13778
  ),
@@ -13408,16 +13785,18 @@ var CalendarHeader = ({
13408
13785
  "aria-controls": "date-picker-selection",
13409
13786
  className: cn(
13410
13787
  selectorClassName,
13788
+ "shrink-0",
13411
13789
  activeSelector === "year" && "bg-m3-on-surface/8"
13412
13790
  ),
13791
+ title: yearLabel,
13413
13792
  children: [
13414
- yearLabel,
13793
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: yearLabel }),
13415
13794
  /* @__PURE__ */ jsxRuntime.jsx(
13416
13795
  Icon,
13417
13796
  {
13418
13797
  name: "arrow_drop_down",
13419
13798
  className: cn(
13420
- "text-[20px] transition-transform duration-200",
13799
+ "text-[20px] shrink-0 transition-transform duration-200",
13421
13800
  activeSelector === "year" && "rotate-180"
13422
13801
  )
13423
13802
  }
@@ -13432,6 +13811,7 @@ var CalendarHeader = ({
13432
13811
  "aria-label": "Next year",
13433
13812
  disabled: !canNavigateNextYear,
13434
13813
  size: "xs",
13814
+ className: "shrink-0",
13435
13815
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron_right" })
13436
13816
  }
13437
13817
  ),
@@ -13441,6 +13821,7 @@ var CalendarHeader = ({
13441
13821
  onClick: onToggleMode,
13442
13822
  "aria-label": "Switch to text input",
13443
13823
  size: "xs",
13824
+ className: "shrink-0",
13444
13825
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "keyboard" })
13445
13826
  }
13446
13827
  )
@@ -13452,7 +13833,7 @@ var CalendarHeader = ({
13452
13833
  onClick: onToggleMode,
13453
13834
  "aria-label": "Switch to calendar",
13454
13835
  size: "xs",
13455
- className: "self-end",
13836
+ className: "self-end shrink-0",
13456
13837
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "calendar_month" })
13457
13838
  }
13458
13839
  ),
@@ -13499,14 +13880,14 @@ var MonthPickerList = ({
13499
13880
  onClick: () => onMonthSelect(month),
13500
13881
  className: cn(
13501
13882
  "flex min-h-12 w-full items-center gap-4 px-6 text-left",
13502
- "text-[length:var(--md-typescale-body-large-size,16px)]",
13883
+ "text-(length:--md-typescale-body-large-size,16px)",
13503
13884
  "text-m3-on-surface transition-m3-fast-effects",
13504
13885
  "hover:bg-m3-on-surface/8 focus-visible:outline-2 focus-visible:outline-m3-primary",
13505
13886
  isSelected && "bg-m3-secondary-container text-m3-on-secondary-container"
13506
13887
  ),
13507
13888
  children: [
13508
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-6", "aria-hidden": true, children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "check", className: "text-[20px]" }) }),
13509
- getMonthLabel(month, locale.locale)
13889
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-6 shrink-0", "aria-hidden": true, children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "check", className: "text-[20px]" }) }),
13890
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: getMonthLabel(month, locale.locale) })
13510
13891
  ]
13511
13892
  },
13512
13893
  month
@@ -13584,7 +13965,9 @@ var DatePicker = ({
13584
13965
  showModeToggle = true,
13585
13966
  title,
13586
13967
  headline,
13587
- className
13968
+ className,
13969
+ width,
13970
+ maxWidth
13588
13971
  }) => {
13589
13972
  const {
13590
13973
  selectedDateMs,
@@ -13665,7 +14048,10 @@ var DatePicker = ({
13665
14048
  "fieldset",
13666
14049
  {
13667
14050
  className: cn("flex flex-col select-none", className),
13668
- style: { width: "min(100%, 360px)" },
14051
+ style: {
14052
+ width: typeof width === "number" ? `${width}px` : width != null ? width : "min(100%, 360px)",
14053
+ maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth
14054
+ },
13669
14055
  "aria-label": computedAriaLabel,
13670
14056
  children: [
13671
14057
  /* @__PURE__ */ jsxRuntime.jsx("legend", { className: "sr-only", children: computedAriaLabel }),
@@ -13912,45 +14298,64 @@ var DialogOverlay = React67__namespace.forwardRef((_a, ref) => {
13912
14298
  ) }));
13913
14299
  });
13914
14300
  DialogOverlay.displayName = "DialogOverlay";
13915
- var DialogContent = React67__namespace.forwardRef((_a, ref) => {
13916
- var _b = _a, { className, children, hideCloseButton = false } = _b, props = __objRest(_b, ["className", "children", "hideCloseButton"]);
13917
- return /* @__PURE__ */ jsxRuntime.jsx(
13918
- RadixDialog__namespace.Content,
13919
- __spreadProps(__spreadValues({
13920
- ref,
13921
- asChild: true,
13922
- "aria-describedby": void 0
13923
- }, props), {
13924
- children: /* @__PURE__ */ jsxRuntime.jsxs(
13925
- react.m.div,
13926
- __spreadProps(__spreadValues({
13927
- className: cn(
13928
- "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
13929
- "w-[calc(100%-2rem)] max-w-140",
13930
- "rounded-[28px] bg-m3-surface-container-high p-6",
13931
- "shadow-lg outline-none focus-visible:ring-2 focus-visible:ring-m3-primary",
13932
- className
13933
- ),
13934
- role: "dialog"
13935
- }, MD3_CONTENT_ANIM), {
13936
- children: [
13937
- children,
13938
- !hideCloseButton && /* @__PURE__ */ jsxRuntime.jsx(RadixDialog__namespace.Close, { asChild: true, "aria-label": "Close dialog", children: /* @__PURE__ */ jsxRuntime.jsx(
13939
- IconButton,
13940
- {
13941
- size: "sm",
13942
- colorStyle: "filled",
13943
- className: "absolute right-4 top-4",
13944
- "aria-label": "Close",
13945
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "close", "aria-hidden": "true" })
13946
- }
13947
- ) })
13948
- ]
13949
- })
13950
- )
13951
- })
13952
- );
13953
- });
14301
+ var DEFAULT_CLOSE_BTN_PROPS = {
14302
+ size: "sm",
14303
+ colorStyle: "standard",
14304
+ className: "absolute right-4 top-4",
14305
+ "aria-label": "Close"
14306
+ };
14307
+ var DialogContent = React67__namespace.forwardRef(
14308
+ (_a, ref) => {
14309
+ var _b = _a, {
14310
+ className,
14311
+ children,
14312
+ hideCloseButton = false,
14313
+ closeButtonProps,
14314
+ closeButton
14315
+ } = _b, props = __objRest(_b, [
14316
+ "className",
14317
+ "children",
14318
+ "hideCloseButton",
14319
+ "closeButtonProps",
14320
+ "closeButton"
14321
+ ]);
14322
+ const closeAriaLabel = (() => {
14323
+ var _a2, _b2, _c;
14324
+ if (closeButton == null) {
14325
+ return (_a2 = closeButtonProps == null ? void 0 : closeButtonProps["aria-label"]) != null ? _a2 : DEFAULT_CLOSE_BTN_PROPS["aria-label"];
14326
+ }
14327
+ const el = closeButton;
14328
+ return (_c = (_b2 = el == null ? void 0 : el.props) == null ? void 0 : _b2["aria-label"]) != null ? _c : "Close";
14329
+ })();
14330
+ return /* @__PURE__ */ jsxRuntime.jsx(
14331
+ RadixDialog__namespace.Content,
14332
+ __spreadProps(__spreadValues({
14333
+ ref,
14334
+ asChild: true,
14335
+ "aria-describedby": void 0
14336
+ }, props), {
14337
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
14338
+ react.m.div,
14339
+ __spreadProps(__spreadValues({
14340
+ className: cn(
14341
+ "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
14342
+ "w-[calc(100%-2rem)] max-w-140",
14343
+ "rounded-[28px] bg-m3-surface-container-high p-6",
14344
+ "shadow-lg outline-none focus-visible:ring-2 focus-visible:ring-m3-primary",
14345
+ className
14346
+ ),
14347
+ role: "dialog"
14348
+ }, MD3_CONTENT_ANIM), {
14349
+ children: [
14350
+ children,
14351
+ closeButton != null ? /* @__PURE__ */ jsxRuntime.jsx(RadixDialog__namespace.Close, { asChild: true, "aria-label": closeAriaLabel, children: closeButton }) : !hideCloseButton ? /* @__PURE__ */ jsxRuntime.jsx(RadixDialog__namespace.Close, { asChild: true, "aria-label": closeAriaLabel, children: /* @__PURE__ */ jsxRuntime.jsx(IconButton, __spreadProps(__spreadValues(__spreadValues({}, DEFAULT_CLOSE_BTN_PROPS), closeButtonProps), { children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "close", "aria-hidden": "true" }) })) }) : null
14352
+ ]
14353
+ })
14354
+ )
14355
+ })
14356
+ );
14357
+ }
14358
+ );
13954
14359
  DialogContent.displayName = "DialogContent";
13955
14360
  var DialogIcon = React67__namespace.forwardRef((_a, ref) => {
13956
14361
  var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
@@ -14041,6 +14446,8 @@ var DialogFullScreenContent = React67__namespace.forwardRef(
14041
14446
  title,
14042
14447
  actionLabel,
14043
14448
  onAction,
14449
+ actionButtonProps,
14450
+ closeButtonProps,
14044
14451
  showDivider
14045
14452
  } = _b, props = __objRest(_b, [
14046
14453
  "className",
@@ -14048,8 +14455,11 @@ var DialogFullScreenContent = React67__namespace.forwardRef(
14048
14455
  "title",
14049
14456
  "actionLabel",
14050
14457
  "onAction",
14458
+ "actionButtonProps",
14459
+ "closeButtonProps",
14051
14460
  "showDivider"
14052
14461
  ]);
14462
+ var _a2;
14053
14463
  return /* @__PURE__ */ jsxRuntime.jsx(
14054
14464
  RadixDialog__namespace.Content,
14055
14465
  __spreadProps(__spreadValues({
@@ -14069,16 +14479,33 @@ var DialogFullScreenContent = React67__namespace.forwardRef(
14069
14479
  }, MD3_FULLSCREEN_ANIM), {
14070
14480
  children: [
14071
14481
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center px-4 h-14 gap-2 bg-m3-surface", children: [
14072
- /* @__PURE__ */ jsxRuntime.jsx(RadixDialog__namespace.Close, { asChild: true, "aria-label": "Close dialog", children: /* @__PURE__ */ jsxRuntime.jsx(IconButton, { size: "sm", colorStyle: "filled", "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "close", "aria-hidden": "true" }) }) }),
14482
+ /* @__PURE__ */ jsxRuntime.jsx(
14483
+ RadixDialog__namespace.Close,
14484
+ {
14485
+ asChild: true,
14486
+ "aria-label": (_a2 = closeButtonProps == null ? void 0 : closeButtonProps["aria-label"]) != null ? _a2 : "Close",
14487
+ children: /* @__PURE__ */ jsxRuntime.jsx(
14488
+ IconButton,
14489
+ __spreadProps(__spreadValues({
14490
+ size: "sm",
14491
+ colorStyle: "standard",
14492
+ "aria-label": "Close"
14493
+ }, closeButtonProps), {
14494
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "close", "aria-hidden": "true" })
14495
+ })
14496
+ )
14497
+ }
14498
+ ),
14073
14499
  title && /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "flex-1 text-[22px] leading-7 font-medium truncate pr-2", children: title }),
14074
14500
  actionLabel && onAction && /* @__PURE__ */ jsxRuntime.jsx(
14075
14501
  "button",
14076
- {
14502
+ __spreadProps(__spreadValues({
14077
14503
  type: "button",
14078
14504
  onClick: onAction,
14079
- 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",
14505
+ 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"
14506
+ }, actionButtonProps), {
14080
14507
  children: actionLabel
14081
- }
14508
+ })
14082
14509
  )
14083
14510
  ] }),
14084
14511
  showDivider && /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-m3-outline-variant w-full shrink-0 m-0" }),
@@ -14106,7 +14533,9 @@ var DatePickerDialog = ({
14106
14533
  dismissButton,
14107
14534
  children,
14108
14535
  className,
14109
- title = "Select date"
14536
+ title = "Select date",
14537
+ width,
14538
+ maxWidth
14110
14539
  }) => {
14111
14540
  return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: (v) => !v && onDismiss(), children: /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { open, children: [
14112
14541
  /* @__PURE__ */ jsxRuntime.jsx(RadixDialog__namespace.Overlay, { asChild: true, forceMount: true, children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -14142,7 +14571,10 @@ var DatePickerDialog = ({
14142
14571
  "elevation-3",
14143
14572
  className
14144
14573
  ),
14145
- style: { width: "min(calc(100vw - 32px), 360px)" },
14574
+ style: {
14575
+ width: typeof width === "number" ? `${width}px` : width != null ? width : "min(calc(100vw - 32px), 360px)",
14576
+ maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth
14577
+ },
14146
14578
  initial: PICKER_CONTENT_ANIM.initial,
14147
14579
  animate: PICKER_CONTENT_ANIM.animate,
14148
14580
  exit: PICKER_CONTENT_ANIM.exit,
@@ -14166,7 +14598,9 @@ var DateRangePicker = ({
14166
14598
  state,
14167
14599
  showModeToggle = false,
14168
14600
  title,
14169
- className
14601
+ className,
14602
+ width,
14603
+ maxWidth
14170
14604
  }) => {
14171
14605
  const {
14172
14606
  selectedStartMs,
@@ -14238,7 +14672,10 @@ var DateRangePicker = ({
14238
14672
  "fieldset",
14239
14673
  {
14240
14674
  className: cn("flex flex-col select-none", className),
14241
- style: { width: "min(100%, 360px)" },
14675
+ style: {
14676
+ width: typeof width === "number" ? `${width}px` : width != null ? width : "min(100%, 360px)",
14677
+ maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth
14678
+ },
14242
14679
  "aria-label": computedAriaLabel,
14243
14680
  children: [
14244
14681
  /* @__PURE__ */ jsxRuntime.jsx("legend", { className: "sr-only", children: computedAriaLabel }),
@@ -15064,21 +15501,13 @@ var normalizeAngle = (angle) => {
15064
15501
  return a;
15065
15502
  };
15066
15503
  var angleToHour12 = (angle) => {
15067
- const hourOffset = RADIANS_PER_HOUR / 2;
15068
- const totalOffset = hourOffset + QUARTER_CIRCLE;
15069
- const hour = Math.round((angle + totalOffset) / RADIANS_PER_HOUR) % 12;
15504
+ const normalized = normalizeAngle(angle + QUARTER_CIRCLE);
15505
+ const hour = Math.round(normalized / RADIANS_PER_HOUR) % 12;
15070
15506
  return hour === 0 ? 12 : hour;
15071
15507
  };
15072
- var angleToMinute = (angle, snap = true) => {
15073
- if (snap) {
15074
- const minuteOffset = RADIANS_PER_MINUTE / 2;
15075
- const totalOffset = minuteOffset + QUARTER_CIRCLE;
15076
- const raw2 = Math.round((angle + totalOffset) / RADIANS_PER_MINUTE) % 60;
15077
- return raw2 < 0 ? raw2 + 60 : raw2;
15078
- }
15508
+ var angleToMinute = (angle, _snap = true) => {
15079
15509
  const normalized = normalizeAngle(angle + QUARTER_CIRCLE);
15080
- const raw = Math.round(normalized / FULL_CIRCLE * 60) % 60;
15081
- return raw < 0 ? raw + 60 : raw;
15510
+ return Math.round(normalized / RADIANS_PER_MINUTE) % 60;
15082
15511
  };
15083
15512
  var getSelectorPosition = (angle, selection, is24hour, isPm) => {
15084
15513
  const useInner = is24hour && isPm && selection === "hour";
@@ -15585,13 +16014,16 @@ var useTimePickerState = (options) => {
15585
16014
  };
15586
16015
  function buildWavePath(startX, endX, amplitude = 2, wavelength = 32, yCenter = 4) {
15587
16016
  if (startX >= endX) return "";
16017
+ const totalWidth = endX - startX;
15588
16018
  const halfCycle = wavelength / 2;
15589
- const numHalfCycles = Math.ceil((endX - startX) / halfCycle);
15590
- const cpDistanceY = amplitude * (4 / 3);
16019
+ const numHalfCycles = Math.max(1, Math.round(totalWidth / halfCycle));
16020
+ const actualHalfCycle = totalWidth / numHalfCycles;
16021
+ const scale = Math.min(1, actualHalfCycle / halfCycle);
16022
+ const cpDistanceY = amplitude * (4 / 3) * scale;
15591
16023
  let d = `M ${startX},${yCenter}`;
15592
16024
  for (let i = 0; i < numHalfCycles; i++) {
15593
- const x0 = startX + i * halfCycle;
15594
- const x1 = Math.min(startX + (i + 1) * halfCycle, endX);
16025
+ const x0 = startX + i * actualHalfCycle;
16026
+ const x1 = i === numHalfCycles - 1 ? endX : startX + (i + 1) * actualHalfCycle;
15595
16027
  const peak = i % 2 === 0 ? yCenter - cpDistanceY : yCenter + cpDistanceY;
15596
16028
  const segLen = x1 - x0;
15597
16029
  const cp1x = x0 + segLen / 3;
@@ -15609,7 +16041,7 @@ var DividerImpl = React67__namespace.forwardRef(
15609
16041
  insetStart = "standard",
15610
16042
  waveConfig,
15611
16043
  decorative = false,
15612
- animate: animate5 = true,
16044
+ animate: animate7 = true,
15613
16045
  className,
15614
16046
  style
15615
16047
  } = _b, props = __objRest(_b, [
@@ -15625,7 +16057,7 @@ var DividerImpl = React67__namespace.forwardRef(
15625
16057
  ]);
15626
16058
  var _a2, _b2, _c;
15627
16059
  const reducedMotion = react.useReducedMotion();
15628
- const shouldAnimate = animate5 && !reducedMotion;
16060
+ const shouldAnimate = animate7 && !reducedMotion;
15629
16061
  const effectiveShape = shape === "wavy" && orientation === "vertical" ? "flat" : shape;
15630
16062
  if (shape === "wavy" && orientation === "vertical") {
15631
16063
  console.warn(
@@ -17366,7 +17798,7 @@ var ListItemImpl = React67__namespace.forwardRef(
17366
17798
  "cursor-grab active:cursor-grabbing text-m3-on-surface-variant p-2 -mr-2"
17367
17799
  )
17368
17800
  }, attributes), listeners), {
17369
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "material-symbols-outlined text-[24px]", children: "drag_handle" })
17801
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "material-symbols-rounded text-[24px]", children: "drag_handle" })
17370
17802
  })
17371
17803
  );
17372
17804
  }
@@ -18719,6 +19151,7 @@ var NavigationRailComponent = React67__namespace.forwardRef(
18719
19151
  react.m.div,
18720
19152
  {
18721
19153
  layout: true,
19154
+ transition: SPRING_TRANSITION,
18722
19155
  className: cn(
18723
19156
  "flex w-full flex-col justify-start shrink-0 empty:hidden",
18724
19157
  isExpanded ? "items-start px-3" : "items-center",
@@ -19025,6 +19458,7 @@ function SearchBar({
19025
19458
  onSearch,
19026
19459
  active,
19027
19460
  onActiveChange,
19461
+ showLeadingIcon = true,
19028
19462
  leadingIcon,
19029
19463
  trailingIcon,
19030
19464
  avatar,
@@ -19087,7 +19521,7 @@ function SearchBar({
19087
19521
  layoutId: shouldReduceMotion ? void 0 : searchId,
19088
19522
  transition: shouldReduceMotion ? void 0 : SEARCH_BAR_EXPAND_SPRING,
19089
19523
  className: cn(
19090
- "relative group select-none",
19524
+ "relative group select-none rounded-full",
19091
19525
  SEARCH_ELEVATION.level3,
19092
19526
  className
19093
19527
  ),
@@ -19127,7 +19561,7 @@ function SearchBar({
19127
19561
  "aria-label": ariaLabel,
19128
19562
  className: "relative flex h-full items-center gap-2 rounded-full px-4",
19129
19563
  children: /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "contents", onSubmit: handleFormSubmit, children: [
19130
- /* @__PURE__ */ jsxRuntime.jsx(
19564
+ showLeadingIcon && /* @__PURE__ */ jsxRuntime.jsx(
19131
19565
  "span",
19132
19566
  {
19133
19567
  className: "flex shrink-0 items-center justify-center",
@@ -19334,6 +19768,7 @@ function SearchViewDocked({
19334
19768
  onSearch,
19335
19769
  active,
19336
19770
  onActiveChange,
19771
+ showLeadingIcon = true,
19337
19772
  leadingIcon,
19338
19773
  trailingIcon,
19339
19774
  avatar,
@@ -19390,7 +19825,7 @@ function SearchViewDocked({
19390
19825
  className: "flex items-center gap-2 px-4",
19391
19826
  style: { height: SearchTokens.heights.dockedHeader },
19392
19827
  children: /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "contents", onSubmit: handleFormSubmit, children: [
19393
- /* @__PURE__ */ jsxRuntime.jsx(
19828
+ showLeadingIcon && /* @__PURE__ */ jsxRuntime.jsx(
19394
19829
  "span",
19395
19830
  {
19396
19831
  className: "flex shrink-0 items-center justify-center",
@@ -19485,6 +19920,7 @@ function SearchViewFullScreen({
19485
19920
  onSearch,
19486
19921
  active,
19487
19922
  onActiveChange,
19923
+ showCloseButton = true,
19488
19924
  leadingIcon,
19489
19925
  trailingIcon,
19490
19926
  avatar,
@@ -19551,7 +19987,7 @@ function SearchViewFullScreen({
19551
19987
  className: "flex shrink-0 items-center gap-2 px-4",
19552
19988
  style: { height: SearchTokens.heights.fullScreenHeader },
19553
19989
  children: /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "contents", onSubmit: handleFormSubmit, children: [
19554
- /* @__PURE__ */ jsxRuntime.jsx(
19990
+ showCloseButton && /* @__PURE__ */ jsxRuntime.jsx(
19555
19991
  IconButton,
19556
19992
  {
19557
19993
  size: "sm",
@@ -19652,6 +20088,8 @@ function SearchComponent({
19652
20088
  variant = "docked",
19653
20089
  styleType = "contained",
19654
20090
  hasGap = false,
20091
+ showLeadingIcon = true,
20092
+ showCloseButton = true,
19655
20093
  leadingIcon,
19656
20094
  trailingIcon,
19657
20095
  avatar,
@@ -19680,6 +20118,7 @@ function SearchComponent({
19680
20118
  onSearch,
19681
20119
  active,
19682
20120
  onActiveChange,
20121
+ showLeadingIcon,
19683
20122
  leadingIcon,
19684
20123
  trailingIcon,
19685
20124
  avatar,
@@ -19696,6 +20135,7 @@ function SearchComponent({
19696
20135
  variant === "fullscreen" ? /* @__PURE__ */ jsxRuntime.jsx(
19697
20136
  SearchViewFullScreen,
19698
20137
  __spreadProps(__spreadValues({}, sharedProps), {
20138
+ showCloseButton,
19699
20139
  styleType,
19700
20140
  viewClassName,
19701
20141
  children
@@ -20348,12 +20788,13 @@ var TextFieldComponent = React67__namespace.forwardRef(
20348
20788
  if (autoResize) {
20349
20789
  textarea.style.height = "auto";
20350
20790
  textarea.style.height = `${textarea.scrollHeight}px`;
20351
- if (maxRows) {
20352
- textarea.style.maxHeight = `${maxRows * LINE_HEIGHT_PX}px`;
20353
- }
20791
+ textarea.style.overflowY = "hidden";
20792
+ } else {
20793
+ textarea.style.height = "";
20794
+ textarea.style.maxHeight = "";
20795
+ textarea.style.overflowY = "";
20354
20796
  }
20355
- textarea.style.overflowY = "hidden";
20356
- }, [type, autoResize, maxRows, currentValue]);
20797
+ }, [type, autoResize, currentValue]);
20357
20798
  const handleValueChange = React67__namespace.useCallback(
20358
20799
  (newValue) => {
20359
20800
  var _a2, _b;
@@ -20576,7 +21017,7 @@ var TextFieldComponent = React67__namespace.forwardRef(
20576
21017
  className: cn(
20577
21018
  inputClass,
20578
21019
  "resize-none mt-2",
20579
- autoResize ? "h-auto" : "h-full"
21020
+ autoResize ? "h-auto" : "min-h-full overflow-y-auto"
20580
21021
  ),
20581
21022
  style: { direction: textDirection || void 0 }
20582
21023
  }, inputProps)
@@ -20715,6 +21156,15 @@ var Select = React67__namespace.forwardRef(
20715
21156
  openRef.current = open;
20716
21157
  const [searchQuery, setSearchQuery] = React67__namespace.useState("");
20717
21158
  const [scrollViewport, setScrollViewport] = React67__namespace.useState(null);
21159
+ React67__namespace.useEffect(() => {
21160
+ var _a3, _b3;
21161
+ const isDev = ((_b3 = (_a3 = globalThis.process) == null ? void 0 : _a3.env) == null ? void 0 : _b3.NODE_ENV) !== "production";
21162
+ if (isDev && onSearchChange && !searchable) {
21163
+ console.warn(
21164
+ "[Select] `onSearchChange` was provided but `searchable` is false. The callback will never be called unless you also set `searchable={true}`."
21165
+ );
21166
+ }
21167
+ }, [onSearchChange, searchable]);
20718
21168
  const selectedOption = React67__namespace.useMemo(
20719
21169
  () => options.find((opt) => opt.value === currentValue),
20720
21170
  [options, currentValue]
@@ -20940,10 +21390,51 @@ function SelectEmpty(_a) {
20940
21390
  })
20941
21391
  );
20942
21392
  }
21393
+
21394
+ // src/ui/shape-media/animation-utils.ts
20943
21395
  function prefersReducedMotion() {
20944
- if (typeof window === "undefined") return false;
21396
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
21397
+ return false;
21398
+ }
20945
21399
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
20946
21400
  }
21401
+ function easeCubicInOut(t) {
21402
+ return t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
21403
+ }
21404
+ function cubicBezier(x1, y1, x2, y2) {
21405
+ return (t) => {
21406
+ if (t === 0 || t === 1) return t;
21407
+ let tParam = t;
21408
+ for (let i = 0; i < 8; i++) {
21409
+ const x = 3 * (1 - tParam) ** 2 * tParam * x1 + 3 * (1 - tParam) * tParam ** 2 * x2 + tParam ** 3;
21410
+ const dx = 3 * (1 - tParam) ** 2 * x1 + 6 * (1 - tParam) * tParam * (x2 - x1) + 3 * tParam ** 2 * (1 - x2);
21411
+ if (Math.abs(dx) < 1e-6) break;
21412
+ tParam -= (x - t) / dx;
21413
+ }
21414
+ return 3 * (1 - tParam) ** 2 * tParam * y1 + 3 * (1 - tParam) * tParam ** 2 * y2 + tParam ** 3;
21415
+ };
21416
+ }
21417
+ function getEasingFunction(easing) {
21418
+ if (Array.isArray(easing)) {
21419
+ if (easing.length === 4) {
21420
+ const [x1, y1, x2, y2] = easing;
21421
+ return cubicBezier(x1, y1, x2, y2);
21422
+ }
21423
+ return easeCubicInOut;
21424
+ }
21425
+ switch (easing) {
21426
+ case "linear":
21427
+ return (t) => t;
21428
+ case "ease-in":
21429
+ return (t) => t * t * t;
21430
+ case "ease-out":
21431
+ return (t) => 1 - (1 - t) ** 3;
21432
+ default:
21433
+ return easeCubicInOut;
21434
+ }
21435
+ }
21436
+
21437
+ // src/ui/shape-media/useShapeMorph.ts
20947
21438
  function useShapeMorph({
20948
21439
  shape,
20949
21440
  morphTo,
@@ -20958,10 +21449,16 @@ function useShapeMorph({
20958
21449
  const duration = (_a = morphOptions == null ? void 0 : morphOptions.duration) != null ? _a : 0.3;
20959
21450
  const easing = (_b = morphOptions == null ? void 0 : morphOptions.easing) != null ? _b : "ease-in-out";
20960
21451
  const easingFunction = React67.useMemo(() => getEasingFunction(easing), [easing]);
21452
+ const resolvedTarget = React67.useMemo(() => {
21453
+ if (morphTo === "auto") {
21454
+ return getRecommendedMorphShape(shape);
21455
+ }
21456
+ return morphTo;
21457
+ }, [morphTo, shape]);
20961
21458
  const startShape = React67.useMemo(() => resolveShape(shape), [shape]);
20962
21459
  const endShape = React67.useMemo(
20963
- () => morphTo ? resolveShape(morphTo) : null,
20964
- [morphTo]
21460
+ () => resolvedTarget ? resolveShape(resolvedTarget) : null,
21461
+ [resolvedTarget]
20965
21462
  );
20966
21463
  const morph = React67.useMemo(
20967
21464
  () => endShape ? new Morph(startShape, endShape) : null,
@@ -20976,7 +21473,45 @@ function useShapeMorph({
20976
21473
  const startProgressRef = React67.useRef(0);
20977
21474
  const targetProgressRef = React67.useRef(0);
20978
21475
  const currentProgressRef = React67.useRef(0);
21476
+ const prevShapeRef = React67.useRef(shape);
20979
21477
  React67.useEffect(() => {
21478
+ if (prevShapeRef.current === shape) return;
21479
+ const oldShape = prevShapeRef.current;
21480
+ prevShapeRef.current = shape;
21481
+ if (disabled || prefersReducedMotion()) {
21482
+ setClipPath(toClipPath(resolveShape(shape), width, height));
21483
+ return;
21484
+ }
21485
+ try {
21486
+ const transitionMorph = new Morph(
21487
+ resolveShape(oldShape),
21488
+ resolveShape(shape)
21489
+ );
21490
+ const start = performance.now();
21491
+ const durationMs = duration * 1e3;
21492
+ const animateTransition = (timestamp) => {
21493
+ const elapsed = timestamp - start;
21494
+ const rawT = Math.min(elapsed / durationMs, 1);
21495
+ const ease = easingFunction(rawT);
21496
+ setClipPath(interpolatePath(transitionMorph, ease, width, height));
21497
+ if (rawT < 1) {
21498
+ animRef.current = requestAnimationFrame(animateTransition);
21499
+ } else {
21500
+ animRef.current = null;
21501
+ }
21502
+ };
21503
+ if (animRef.current !== null) cancelAnimationFrame(animRef.current);
21504
+ animRef.current = requestAnimationFrame(animateTransition);
21505
+ } catch (e) {
21506
+ setClipPath(toClipPath(resolveShape(shape), width, height));
21507
+ }
21508
+ }, [shape, disabled, duration, easingFunction, width, height]);
21509
+ const prevDimsRef = React67.useRef({ width, height, startShape, morph });
21510
+ React67.useEffect(() => {
21511
+ if (prevDimsRef.current.width === width && prevDimsRef.current.height === height && prevDimsRef.current.startShape === startShape && prevDimsRef.current.morph === morph) {
21512
+ return;
21513
+ }
21514
+ prevDimsRef.current = { width, height, startShape, morph };
20980
21515
  if (morph) {
20981
21516
  setClipPath(
20982
21517
  interpolatePath(morph, currentProgressRef.current, width, height)
@@ -20991,7 +21526,7 @@ function useShapeMorph({
20991
21526
  currentProgressRef.current = p;
20992
21527
  setClipPath(interpolatePath(morph, p, width, height));
20993
21528
  }, [scrollProgress, morphOn, morph, width, height]);
20994
- const animate5 = React67.useCallback(
21529
+ const animate7 = React67.useCallback(
20995
21530
  (timestamp) => {
20996
21531
  if (!morph) return;
20997
21532
  const elapsed = timestamp - startTimeRef.current;
@@ -21002,7 +21537,7 @@ function useShapeMorph({
21002
21537
  currentProgressRef.current = progress;
21003
21538
  setClipPath(interpolatePath(morph, progress, width, height));
21004
21539
  if (rawT < 1) {
21005
- animRef.current = requestAnimationFrame(animate5);
21540
+ animRef.current = requestAnimationFrame(animate7);
21006
21541
  } else {
21007
21542
  animRef.current = null;
21008
21543
  }
@@ -21021,9 +21556,9 @@ function useShapeMorph({
21021
21556
  startProgressRef.current = currentProgressRef.current;
21022
21557
  targetProgressRef.current = toProgress;
21023
21558
  startTimeRef.current = performance.now();
21024
- animRef.current = requestAnimationFrame(animate5);
21559
+ animRef.current = requestAnimationFrame(animate7);
21025
21560
  },
21026
- [morph, animate5, width, height]
21561
+ [morph, animate7, width, height]
21027
21562
  );
21028
21563
  React67.useEffect(() => {
21029
21564
  return () => {
@@ -21070,41 +21605,6 @@ function useShapeMorph({
21070
21605
  }, [morphTo, disabled, morphOn, activate, deactivate, isActive]);
21071
21606
  return { clipPath, isActive, activate, deactivate, setProgress, handlers };
21072
21607
  }
21073
- function easeCubicInOut(t) {
21074
- return t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
21075
- }
21076
- function cubicBezier(x1, y1, x2, y2) {
21077
- return (t) => {
21078
- if (t === 0 || t === 1) return t;
21079
- let tParam = t;
21080
- for (let i = 0; i < 8; i++) {
21081
- const x = 3 * (1 - tParam) ** 2 * tParam * x1 + 3 * (1 - tParam) * tParam ** 2 * x2 + tParam ** 3;
21082
- const dx = 3 * (1 - tParam) ** 2 * x1 + 6 * (1 - tParam) * tParam * (x2 - x1) + 3 * tParam ** 2 * (1 - x2);
21083
- if (Math.abs(dx) < 1e-6) break;
21084
- tParam -= (x - t) / dx;
21085
- }
21086
- return 3 * (1 - tParam) ** 2 * tParam * y1 + 3 * (1 - tParam) * tParam ** 2 * y2 + tParam ** 3;
21087
- };
21088
- }
21089
- function getEasingFunction(easing) {
21090
- if (Array.isArray(easing)) {
21091
- if (easing.length === 4) {
21092
- const [x1, y1, x2, y2] = easing;
21093
- return cubicBezier(x1, y1, x2, y2);
21094
- }
21095
- return easeCubicInOut;
21096
- }
21097
- switch (easing) {
21098
- case "linear":
21099
- return (t) => t;
21100
- case "ease-in":
21101
- return (t) => t * t * t;
21102
- case "ease-out":
21103
- return (t) => 1 - (1 - t) ** 3;
21104
- default:
21105
- return easeCubicInOut;
21106
- }
21107
- }
21108
21608
  function ShapeMedia({
21109
21609
  shape,
21110
21610
  morphTo,
@@ -21232,10 +21732,14 @@ function ShapeSvg({
21232
21732
  style,
21233
21733
  "aria-label": ariaLabel
21234
21734
  }) {
21735
+ const resolvedTarget = React67.useMemo(() => {
21736
+ if (morphTo === "auto") return getRecommendedMorphShape(shape);
21737
+ return morphTo;
21738
+ }, [morphTo, shape]);
21235
21739
  const startPolygon = React67.useMemo(() => resolveShape(shape), [shape]);
21236
21740
  const endPolygon = React67.useMemo(
21237
- () => morphTo ? resolveShape(morphTo) : null,
21238
- [morphTo]
21741
+ () => resolvedTarget ? resolveShape(resolvedTarget) : null,
21742
+ [resolvedTarget]
21239
21743
  );
21240
21744
  const morph = React67.useMemo(
21241
21745
  () => endPolygon ? new Morph(startPolygon, endPolygon) : null,
@@ -21269,6 +21773,176 @@ function ShapeSvg({
21269
21773
  }
21270
21774
  );
21271
21775
  }
21776
+ function useShapeSequenceMorph({
21777
+ shapes,
21778
+ duration = 0.6,
21779
+ interval = 2,
21780
+ autoplay = false,
21781
+ loop = true,
21782
+ morphOptions,
21783
+ width,
21784
+ height,
21785
+ disabled = false
21786
+ }) {
21787
+ var _a;
21788
+ const resolvedDuration = (_a = morphOptions == null ? void 0 : morphOptions.duration) != null ? _a : duration;
21789
+ const [currentIndex, setCurrentIndex] = React67.useState(0);
21790
+ const [nextIndex, setNextIndex] = React67.useState(() => shapes.length > 1 ? 1 : 0);
21791
+ const [progress, setProgress] = React67.useState(0);
21792
+ const [isPlaying, setIsPlaying] = React67.useState(autoplay);
21793
+ const animRef = React67.useRef(null);
21794
+ const timerRef = React67.useRef(null);
21795
+ const startTimeRef = React67.useRef(0);
21796
+ const isTransitioningRef = React67.useRef(false);
21797
+ const numShapes = shapes.length;
21798
+ const currentShape = React67.useMemo(() => {
21799
+ if (numShapes === 0) return resolveShape("circle");
21800
+ const safeIdx = (currentIndex % numShapes + numShapes) % numShapes;
21801
+ return resolveShape(shapes[safeIdx]);
21802
+ }, [shapes, currentIndex, numShapes]);
21803
+ const targetShape = React67.useMemo(() => {
21804
+ if (numShapes === 0) return resolveShape("circle");
21805
+ const safeIdx = (nextIndex % numShapes + numShapes) % numShapes;
21806
+ return resolveShape(shapes[safeIdx]);
21807
+ }, [shapes, nextIndex, numShapes]);
21808
+ const morph = React67.useMemo(() => {
21809
+ if (currentShape === targetShape) return null;
21810
+ return new Morph(currentShape, targetShape);
21811
+ }, [currentShape, targetShape]);
21812
+ const [clipPath, setClipPath] = React67.useState(
21813
+ () => toClipPath(currentShape, width, height)
21814
+ );
21815
+ const prevDimsRef = React67.useRef({ width, height, currentShape, morph, progress });
21816
+ React67.useEffect(() => {
21817
+ if (prevDimsRef.current.width === width && prevDimsRef.current.height === height && prevDimsRef.current.currentShape === currentShape && prevDimsRef.current.morph === morph && prevDimsRef.current.progress === progress) {
21818
+ return;
21819
+ }
21820
+ prevDimsRef.current = { width, height, currentShape, morph, progress };
21821
+ if (morph && progress > 0) {
21822
+ setClipPath(interpolatePath(morph, progress, width, height));
21823
+ } else {
21824
+ setClipPath(toClipPath(currentShape, width, height));
21825
+ }
21826
+ }, [width, height, currentShape, morph, progress]);
21827
+ const transitionTo = React67.useCallback(
21828
+ (toIndex) => {
21829
+ if (disabled || numShapes <= 1 || isTransitioningRef.current) return;
21830
+ const targetSafe = (toIndex % numShapes + numShapes) % numShapes;
21831
+ if (targetSafe === currentIndex) return;
21832
+ setNextIndex(targetSafe);
21833
+ if (prefersReducedMotion()) {
21834
+ setCurrentIndex(targetSafe);
21835
+ setNextIndex((targetSafe + 1) % numShapes);
21836
+ setProgress(0);
21837
+ setClipPath(
21838
+ toClipPath(resolveShape(shapes[targetSafe]), width, height)
21839
+ );
21840
+ return;
21841
+ }
21842
+ isTransitioningRef.current = true;
21843
+ startTimeRef.current = performance.now();
21844
+ const fromPoly = resolveShape(shapes[currentIndex]);
21845
+ const toPoly = resolveShape(shapes[targetSafe]);
21846
+ const activeMorph = new Morph(fromPoly, toPoly);
21847
+ const animate7 = (timestamp) => {
21848
+ const elapsed = timestamp - startTimeRef.current;
21849
+ const durationMs = resolvedDuration * 1e3;
21850
+ const rawT = Math.min(elapsed / durationMs, 1);
21851
+ const ease = easeCubicInOut(rawT);
21852
+ setProgress(rawT);
21853
+ setClipPath(interpolatePath(activeMorph, ease, width, height));
21854
+ if (rawT < 1) {
21855
+ animRef.current = requestAnimationFrame(animate7);
21856
+ } else {
21857
+ animRef.current = null;
21858
+ isTransitioningRef.current = false;
21859
+ setCurrentIndex(targetSafe);
21860
+ setNextIndex((targetSafe + 1) % numShapes);
21861
+ setProgress(0);
21862
+ }
21863
+ };
21864
+ if (animRef.current !== null) cancelAnimationFrame(animRef.current);
21865
+ animRef.current = requestAnimationFrame(animate7);
21866
+ },
21867
+ [
21868
+ disabled,
21869
+ numShapes,
21870
+ currentIndex,
21871
+ shapes,
21872
+ resolvedDuration,
21873
+ width,
21874
+ height
21875
+ ]
21876
+ );
21877
+ const next = React67.useCallback(() => {
21878
+ if (numShapes <= 1) return;
21879
+ if (!loop && currentIndex >= numShapes - 1) return;
21880
+ transitionTo((currentIndex + 1) % numShapes);
21881
+ }, [numShapes, loop, currentIndex, transitionTo]);
21882
+ const prev = React67.useCallback(() => {
21883
+ if (numShapes <= 1) return;
21884
+ if (!loop && currentIndex <= 0) return;
21885
+ transitionTo((currentIndex - 1 + numShapes) % numShapes);
21886
+ }, [numShapes, loop, currentIndex, transitionTo]);
21887
+ const goTo = React67.useCallback(
21888
+ (index) => {
21889
+ transitionTo(index);
21890
+ },
21891
+ [transitionTo]
21892
+ );
21893
+ const play = React67.useCallback(() => {
21894
+ setIsPlaying(true);
21895
+ }, []);
21896
+ const pause = React67.useCallback(() => {
21897
+ setIsPlaying(false);
21898
+ if (timerRef.current !== null) {
21899
+ clearTimeout(timerRef.current);
21900
+ timerRef.current = null;
21901
+ }
21902
+ }, []);
21903
+ React67.useEffect(() => {
21904
+ if (!isPlaying || disabled || numShapes <= 1) return;
21905
+ timerRef.current = setTimeout(() => {
21906
+ if (!loop && currentIndex >= numShapes - 1) {
21907
+ setIsPlaying(false);
21908
+ return;
21909
+ }
21910
+ next();
21911
+ }, interval * 1e3);
21912
+ return () => {
21913
+ if (timerRef.current !== null) {
21914
+ clearTimeout(timerRef.current);
21915
+ timerRef.current = null;
21916
+ }
21917
+ };
21918
+ }, [isPlaying, disabled, numShapes, loop, currentIndex, interval, next]);
21919
+ React67.useEffect(() => {
21920
+ return () => {
21921
+ if (animRef.current !== null) cancelAnimationFrame(animRef.current);
21922
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
21923
+ };
21924
+ }, []);
21925
+ React67.useEffect(() => {
21926
+ if (currentIndex >= shapes.length) {
21927
+ setCurrentIndex(0);
21928
+ setNextIndex(shapes.length > 1 ? 1 : 0);
21929
+ }
21930
+ }, [shapes.length, currentIndex]);
21931
+ const safeCurrentIndex = numShapes > 0 ? (currentIndex % numShapes + numShapes) % numShapes : 0;
21932
+ const safeNextIndex = numShapes > 0 ? (nextIndex % numShapes + numShapes) % numShapes : 0;
21933
+ return {
21934
+ clipPath,
21935
+ currentIndex: safeCurrentIndex,
21936
+ nextIndex: safeNextIndex,
21937
+ progress,
21938
+ isPlaying,
21939
+ next,
21940
+ prev,
21941
+ goTo,
21942
+ play,
21943
+ pause
21944
+ };
21945
+ }
21272
21946
  var INDICATOR = "h-1 w-8 rounded-full bg-m3-on-surface-variant/40";
21273
21947
  var DragHandle = React67__namespace.forwardRef(
21274
21948
  ({ className, onCycle, "aria-label": ariaLabel }, ref) => {
@@ -27405,6 +28079,8 @@ exports.MD3CornerRadius = MD3CornerRadius;
27405
28079
  exports.MD3Shapes = MD3Shapes;
27406
28080
  exports.MD3ThemeProvider = MD3ThemeProvider;
27407
28081
  exports.MD3_EXPRESSIVE_FONT_VARIATION = MD3_EXPRESSIVE_FONT_VARIATION;
28082
+ exports.MD3_SHAPE_FAMILIES = MD3_SHAPE_FAMILIES;
28083
+ exports.MD3_SHAPE_PAIRINGS = MD3_SHAPE_PAIRINGS;
27408
28084
  exports.MENU_CHECK_ICON_SIZE = MENU_CHECK_ICON_SIZE;
27409
28085
  exports.MENU_CONTAINER_VARIANTS = MENU_CONTAINER_VARIANTS;
27410
28086
  exports.MENU_GROUP_GAP = MENU_GROUP_GAP;
@@ -27544,12 +28220,14 @@ exports.dividePoint = dividePoint;
27544
28220
  exports.dotProduct = dotProduct;
27545
28221
  exports.edgeFeature = edgeFeature;
27546
28222
  exports.featureMapper = featureMapper;
28223
+ exports.formatCoordinate = formatCoordinate;
27547
28224
  exports.generateM3Theme = generateM3Theme;
27548
28225
  exports.getDirection = getDirection;
27549
28226
  exports.getDistance = getDistance;
27550
28227
  exports.getDistanceSquared = getDistanceSquared;
27551
28228
  exports.getExpressiveShape = getExpressiveShape;
27552
28229
  exports.getListItemHeight = getListItemHeight;
28230
+ exports.getRecommendedMorphShape = getRecommendedMorphShape;
27553
28231
  exports.getToolbarColors = getToolbarColors;
27554
28232
  exports.interpolate = interpolate;
27555
28233
  exports.interpolatePath = interpolatePath;
@@ -27590,6 +28268,7 @@ exports.useRipple = useRipple2;
27590
28268
  exports.useRippleState = useRippleState;
27591
28269
  exports.useSearchKeyboard = useSearchKeyboard;
27592
28270
  exports.useShapeMorph = useShapeMorph;
28271
+ exports.useShapeSequenceMorph = useShapeSequenceMorph;
27593
28272
  exports.useSnackbar = useSnackbar;
27594
28273
  exports.useSnackbarState = useSnackbarState;
27595
28274
  exports.useTheme = useTheme;