@bug-on/m3-expressive 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/buttons.d.mts +1 -1
  3. package/dist/buttons.d.ts +1 -1
  4. package/dist/buttons.js +185 -40
  5. package/dist/buttons.js.map +1 -1
  6. package/dist/buttons.mjs +186 -41
  7. package/dist/buttons.mjs.map +1 -1
  8. package/dist/core.js +156 -25
  9. package/dist/core.js.map +1 -1
  10. package/dist/core.mjs +157 -26
  11. package/dist/core.mjs.map +1 -1
  12. package/dist/feedback.d.mts +20 -0
  13. package/dist/feedback.d.ts +20 -0
  14. package/dist/feedback.js +156 -25
  15. package/dist/feedback.js.map +1 -1
  16. package/dist/feedback.mjs +157 -26
  17. package/dist/feedback.mjs.map +1 -1
  18. package/dist/forms.d.mts +3 -2
  19. package/dist/forms.d.ts +3 -2
  20. package/dist/forms.js +88 -100
  21. package/dist/forms.js.map +1 -1
  22. package/dist/forms.mjs +88 -100
  23. package/dist/forms.mjs.map +1 -1
  24. package/dist/index.d.mts +3 -3
  25. package/dist/index.d.ts +3 -3
  26. package/dist/index.js +279 -146
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +280 -147
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/layout.js +158 -27
  31. package/dist/layout.js.map +1 -1
  32. package/dist/layout.mjs +159 -28
  33. package/dist/layout.mjs.map +1 -1
  34. package/dist/navigation.js +156 -25
  35. package/dist/navigation.js.map +1 -1
  36. package/dist/navigation.mjs +157 -26
  37. package/dist/navigation.mjs.map +1 -1
  38. package/dist/overlays.js +156 -25
  39. package/dist/overlays.js.map +1 -1
  40. package/dist/overlays.mjs +157 -26
  41. package/dist/overlays.mjs.map +1 -1
  42. package/dist/pickers.js +156 -25
  43. package/dist/pickers.js.map +1 -1
  44. package/dist/pickers.mjs +157 -26
  45. package/dist/pickers.mjs.map +1 -1
  46. package/dist/{split-button-trailing-uncheckable-26qlZvKT.d.mts → split-button-trailing-uncheckable-CIVEYgjY.d.mts} +2 -0
  47. package/dist/{split-button-trailing-uncheckable-CXUVrH64.d.ts → split-button-trailing-uncheckable-DTQJjzsB.d.ts} +2 -0
  48. package/dist/{text-field-DWC7qOvp.d.mts → text-field-CiOmDM_8.d.ts} +52 -51
  49. package/dist/{text-field-DWC7qOvp.d.ts → text-field-Ear3hCSq.d.mts} +52 -51
  50. package/package.json +3 -3
@@ -281,6 +281,14 @@ interface CircularProgressProps extends ProgressBaseProps {
281
281
  * - `wavy`: Oscillating wavy line pattern.
282
282
  */
283
283
  shape?: "flat" | "wavy";
284
+ /**
285
+ * Shape profile of the background track in Determinate mode.
286
+ * - `flat`: Smooth circular ring line (default)
287
+ * - `wavy`: Matching wave line contour as the active indicator
288
+ *
289
+ * @default "flat"
290
+ */
291
+ trackShape?: "flat" | "wavy";
284
292
  /**
285
293
  * Wave amplitude profile for `wavy` circular indicators.
286
294
  */
@@ -289,6 +297,10 @@ interface CircularProgressProps extends ProgressBaseProps {
289
297
  wavelength?: number;
290
298
  /** Gap distance separating line ends. */
291
299
  gapSize?: number;
300
+ /**
301
+ * Speed multiplier for wavy animation ripples. Defaults to `1`.
302
+ */
303
+ waveSpeed?: number;
292
304
  /**
293
305
  * Speed multiplier for Indeterminate circular crawler rotation.
294
306
  */
@@ -316,6 +328,14 @@ interface CircularProgressProps extends ProgressBaseProps {
316
328
  * @default 0.8 (matching M3 Kotlin)
317
329
  */
318
330
  maxProgress?: number;
331
+ /**
332
+ * Configuration for wave damping near edge thresholds (<= 10% or >= 95%) in Determinate Wavy mode.
333
+ * - `md3`: Smoothly flattens wave amplitude to zero near edges (Google MD3 standard: Flat → Wavy → Flat).
334
+ * - `continuous`: Ignores damping, preserving wave motion across all percentages (0–100%).
335
+ *
336
+ * @default "md3"
337
+ */
338
+ determinateAnimation?: "md3" | "continuous";
319
339
  /**
320
340
  * Amplitude range for wavy indeterminate mode as `[min, max]`.
321
341
  * The amplitude modulates between these values based on the arc length.
@@ -281,6 +281,14 @@ interface CircularProgressProps extends ProgressBaseProps {
281
281
  * - `wavy`: Oscillating wavy line pattern.
282
282
  */
283
283
  shape?: "flat" | "wavy";
284
+ /**
285
+ * Shape profile of the background track in Determinate mode.
286
+ * - `flat`: Smooth circular ring line (default)
287
+ * - `wavy`: Matching wave line contour as the active indicator
288
+ *
289
+ * @default "flat"
290
+ */
291
+ trackShape?: "flat" | "wavy";
284
292
  /**
285
293
  * Wave amplitude profile for `wavy` circular indicators.
286
294
  */
@@ -289,6 +297,10 @@ interface CircularProgressProps extends ProgressBaseProps {
289
297
  wavelength?: number;
290
298
  /** Gap distance separating line ends. */
291
299
  gapSize?: number;
300
+ /**
301
+ * Speed multiplier for wavy animation ripples. Defaults to `1`.
302
+ */
303
+ waveSpeed?: number;
292
304
  /**
293
305
  * Speed multiplier for Indeterminate circular crawler rotation.
294
306
  */
@@ -316,6 +328,14 @@ interface CircularProgressProps extends ProgressBaseProps {
316
328
  * @default 0.8 (matching M3 Kotlin)
317
329
  */
318
330
  maxProgress?: number;
331
+ /**
332
+ * Configuration for wave damping near edge thresholds (<= 10% or >= 95%) in Determinate Wavy mode.
333
+ * - `md3`: Smoothly flattens wave amplitude to zero near edges (Google MD3 standard: Flat → Wavy → Flat).
334
+ * - `continuous`: Ignores damping, preserving wave motion across all percentages (0–100%).
335
+ *
336
+ * @default "md3"
337
+ */
338
+ determinateAnimation?: "md3" | "continuous";
319
339
  /**
320
340
  * Amplitude range for wavy indeterminate mode as `[min, max]`.
321
341
  * The amplitude modulates between these values based on the arc length.
package/dist/feedback.js CHANGED
@@ -363,7 +363,7 @@ LoadingIndicator.displayName = "LoadingIndicator";
363
363
  function easeInOutCubic(x) {
364
364
  return x < 0.5 ? 4 * x * x * x : 1 - (-2 * x + 2) ** 3 / 2;
365
365
  }
366
- function generateWavyCircularPath(center, radius, amplitude, wavelength) {
366
+ function generateWavyCircularPath(center, radius, amplitude, wavelength, phase = 0) {
367
367
  const circumference = 2 * Math.PI * radius;
368
368
  const numWaves = Math.max(
369
369
  3,
@@ -371,8 +371,8 @@ function generateWavyCircularPath(center, radius, amplitude, wavelength) {
371
371
  );
372
372
  const steps = numWaves * 4;
373
373
  const dt = 2 * Math.PI / steps;
374
- const rAt = (t) => radius + amplitude * Math.sin(numWaves * t);
375
- const drAt = (t) => amplitude * numWaves * Math.cos(numWaves * t);
374
+ const rAt = (t) => radius + amplitude * Math.sin(numWaves * t + phase);
375
+ const drAt = (t) => amplitude * numWaves * Math.cos(numWaves * t + phase);
376
376
  const xAt = (t) => center + rAt(t) * Math.cos(t);
377
377
  const yAt = (t) => center + rAt(t) * Math.sin(t);
378
378
  const dxAt = (t) => drAt(t) * Math.cos(t) - rAt(t) * Math.sin(t);
@@ -437,15 +437,18 @@ var CircularProgress = React3__namespace.forwardRef(
437
437
  size = 48,
438
438
  trackHeight = 4,
439
439
  shape = "flat",
440
+ trackShape = "flat",
440
441
  amplitude,
441
442
  wavelength,
442
443
  gapSize = 4,
444
+ waveSpeed = 1,
443
445
  crawlerSpeed = 1,
444
446
  color,
445
447
  trackColor,
446
448
  showTrack = "auto",
447
449
  minProgress = DEFAULT_MIN_PROGRESS,
448
450
  maxProgress = DEFAULT_MAX_PROGRESS,
451
+ determinateAnimation = "md3",
449
452
  amplitudeRange,
450
453
  className,
451
454
  "aria-label": ariaLabel
@@ -454,15 +457,18 @@ var CircularProgress = React3__namespace.forwardRef(
454
457
  "size",
455
458
  "trackHeight",
456
459
  "shape",
460
+ "trackShape",
457
461
  "amplitude",
458
462
  "wavelength",
459
463
  "gapSize",
464
+ "waveSpeed",
460
465
  "crawlerSpeed",
461
466
  "color",
462
467
  "trackColor",
463
468
  "showTrack",
464
469
  "minProgress",
465
470
  "maxProgress",
471
+ "determinateAnimation",
466
472
  "amplitudeRange",
467
473
  "className",
468
474
  "aria-label"
@@ -475,6 +481,7 @@ var CircularProgress = React3__namespace.forwardRef(
475
481
  const bgTrackColor = trackColor || "var(--md-sys-color-indicator-track)";
476
482
  const isWavy = shape === "wavy";
477
483
  const shouldShowIndeterminateTrack = showTrack === "auto" ? isWavy : showTrack;
484
+ const shouldShowDeterminateTrack = showTrack === "auto" ? true : showTrack;
478
485
  const BASELINE_SIZE = 48;
479
486
  const scaleFactor = size / BASELINE_SIZE;
480
487
  const effectiveAmplitude = React3__namespace.useMemo(
@@ -507,19 +514,50 @@ var CircularProgress = React3__namespace.forwardRef(
507
514
  const trackOffset = isDeterminate ? activeAngularFraction + gapForTrack : 0;
508
515
  const trackLength = isDeterminate ? Math.max(1e-3, 1 - activeAngularFraction - 2 * gapForTrack) : 1;
509
516
  const ActiveCircleElem = react.m.circle;
510
- const ActivePathElem = react.m.path;
511
517
  const indeterminateSvgRef = React3__namespace.useRef(null);
512
518
  const indeterminateTrackRef = React3__namespace.useRef(null);
513
519
  const indeterminateActiveRef = React3__namespace.useRef(null);
514
520
  const indeterminateWavyTrackPathRef = React3__namespace.useRef(null);
515
521
  const indeterminateWavyActivePathRef = React3__namespace.useRef(null);
522
+ const determinateWavyActivePathRef = React3__namespace.useRef(null);
523
+ const determinateWavyTrackPathRef = React3__namespace.useRef(null);
516
524
  const cachedPathLengthRef = React3__namespace.useRef(0);
525
+ const fractionMV = react.useMotionValue(isDeterminate ? clampedValue / 100 : 0);
526
+ const amplitudeMV = react.useMotionValue(isWavy ? effectiveAmplitude : 0);
527
+ React3__namespace.useEffect(() => {
528
+ if (isDeterminate) {
529
+ react.animate(fractionMV, clampedValue / 100, {
530
+ duration: 0.4,
531
+ ease: [0.2, 0, 0, 1]
532
+ });
533
+ }
534
+ }, [clampedValue, isDeterminate, fractionMV]);
535
+ React3__namespace.useEffect(() => {
536
+ if (!isDeterminate || !isWavy) return;
537
+ const fraction = clampedValue / 100;
538
+ let targetAmp = effectiveAmplitude;
539
+ if (determinateAnimation === "md3") {
540
+ targetAmp = fraction <= 0.1 || fraction >= 0.95 ? 0 : effectiveAmplitude;
541
+ }
542
+ react.animate(amplitudeMV, targetAmp, {
543
+ type: "spring",
544
+ bounce: 0,
545
+ duration: 0.5
546
+ });
547
+ }, [
548
+ clampedValue,
549
+ isDeterminate,
550
+ isWavy,
551
+ effectiveAmplitude,
552
+ amplitudeMV,
553
+ determinateAnimation
554
+ ]);
517
555
  React3__namespace.useLayoutEffect(() => {
518
556
  if (!isWavy || !wavyActivePath) {
519
557
  cachedPathLengthRef.current = circumference;
520
558
  return;
521
559
  }
522
- const el = indeterminateActiveRef.current;
560
+ const el = indeterminateActiveRef.current || determinateWavyActivePathRef.current;
523
561
  if (el && "getTotalLength" in el) {
524
562
  try {
525
563
  const len = el.getTotalLength();
@@ -533,7 +571,65 @@ var CircularProgress = React3__namespace.forwardRef(
533
571
  cachedPathLengthRef.current = circumference;
534
572
  }, [isWavy, circumference, wavyActivePath]);
535
573
  react.useAnimationFrame((time) => {
536
- if (isDeterminate) return;
574
+ const safeWaveSpeed = Math.max(0.1, waveSpeed);
575
+ const wavePhase = time / 1e3 * safeWaveSpeed * 2 * Math.PI;
576
+ if (isDeterminate) {
577
+ if (isWavy) {
578
+ const currentAmp = amplitudeMV.get();
579
+ const dynamicPath = generateWavyCircularPath(
580
+ center,
581
+ radius,
582
+ currentAmp,
583
+ effectiveWavelength,
584
+ wavePhase
585
+ );
586
+ if (determinateWavyActivePathRef.current) {
587
+ determinateWavyActivePathRef.current.setAttribute("d", dynamicPath);
588
+ }
589
+ if (trackShape === "wavy" && determinateWavyTrackPathRef.current) {
590
+ determinateWavyTrackPathRef.current.setAttribute("d", dynamicPath);
591
+ }
592
+ const pathEl = determinateWavyActivePathRef.current;
593
+ let totalLen = cachedPathLengthRef.current || circumference;
594
+ if (pathEl) {
595
+ try {
596
+ const len = pathEl.getTotalLength();
597
+ if (len > 0) totalLen = len;
598
+ } catch (e) {
599
+ }
600
+ }
601
+ const activeFrac = Math.max(0, Math.min(1, fractionMV.get()));
602
+ const activeLen = totalLen * activeFrac;
603
+ if (determinateWavyActivePathRef.current) {
604
+ determinateWavyActivePathRef.current.setAttribute(
605
+ "stroke-dasharray",
606
+ `${activeLen} ${totalLen}`
607
+ );
608
+ determinateWavyActivePathRef.current.setAttribute(
609
+ "stroke-dashoffset",
610
+ "0"
611
+ );
612
+ }
613
+ if (shouldShowDeterminateTrack && trackShape === "wavy" && determinateWavyTrackPathRef.current) {
614
+ const gapFrac = (gapSize + trackHeight) / totalLen;
615
+ const trackStartFrac = activeFrac + gapFrac;
616
+ const trackLen = Math.max(
617
+ 1e-3,
618
+ totalLen * (1 - activeFrac - 2 * gapFrac)
619
+ );
620
+ const trackOff = -totalLen * trackStartFrac;
621
+ determinateWavyTrackPathRef.current.setAttribute(
622
+ "stroke-dasharray",
623
+ `${trackLen} ${totalLen}`
624
+ );
625
+ determinateWavyTrackPathRef.current.setAttribute(
626
+ "stroke-dashoffset",
627
+ `${trackOff}`
628
+ );
629
+ }
630
+ }
631
+ return;
632
+ }
537
633
  const safeCrawlerSpeed = Math.max(0.1, crawlerSpeed);
538
634
  const scaledTime = time * safeCrawlerSpeed;
539
635
  const globalCycle = scaledTime % GLOBAL_ROTATION_DURATION;
@@ -568,7 +664,8 @@ var CircularProgress = React3__namespace.forwardRef(
568
664
  center,
569
665
  radius,
570
666
  currentAmplitude,
571
- effectiveWavelength
667
+ effectiveWavelength,
668
+ wavePhase
572
669
  );
573
670
  if (indeterminateWavyActivePathRef.current) {
574
671
  indeterminateWavyActivePathRef.current.setAttribute("d", dynamicPath);
@@ -663,7 +760,7 @@ var CircularProgress = React3__namespace.forwardRef(
663
760
  style: { width: size, height: size }
664
761
  }, restProps), {
665
762
  children: /* @__PURE__ */ jsxRuntime.jsxs(react.LazyMotion, { features: react.domMax, strict: true, children: [
666
- /* @__PURE__ */ jsxRuntime.jsxs(
763
+ /* @__PURE__ */ jsxRuntime.jsx(
667
764
  "svg",
668
765
  {
669
766
  width: size,
@@ -671,8 +768,18 @@ var CircularProgress = React3__namespace.forwardRef(
671
768
  viewBox: `0 0 ${size} ${size}`,
672
769
  "aria-hidden": "true",
673
770
  style: { transform: "rotate(-90deg)", overflow: "visible" },
674
- children: [
675
- isDeterminate ? /* @__PURE__ */ jsxRuntime.jsx(
771
+ children: isDeterminate ? isWavy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
772
+ shouldShowDeterminateTrack && (trackShape === "wavy" ? /* @__PURE__ */ jsxRuntime.jsx(
773
+ "path",
774
+ {
775
+ ref: determinateWavyTrackPathRef,
776
+ d: wavyActivePath != null ? wavyActivePath : "",
777
+ fill: "none",
778
+ stroke: bgTrackColor,
779
+ strokeWidth: trackHeight,
780
+ strokeLinecap: "round"
781
+ }
782
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
676
783
  react.m.circle,
677
784
  {
678
785
  cx: center,
@@ -681,28 +788,52 @@ var CircularProgress = React3__namespace.forwardRef(
681
788
  fill: "none",
682
789
  stroke: bgTrackColor,
683
790
  strokeWidth: trackHeight,
684
- initial: { pathLength: trackLength, pathOffset: trackOffset },
685
- animate: { pathLength: trackLength, pathOffset: trackOffset },
791
+ initial: {
792
+ pathLength: trackLength,
793
+ pathOffset: trackOffset
794
+ },
795
+ animate: {
796
+ pathLength: trackLength,
797
+ pathOffset: trackOffset
798
+ },
686
799
  transition: { duration: 0.4, ease: [0.2, 0, 0, 1] },
687
800
  strokeLinecap: "round"
688
801
  }
689
- ) : null,
690
- isDeterminate && (isWavy ? /* @__PURE__ */ jsxRuntime.jsx(
691
- ActivePathElem,
802
+ )),
803
+ /* @__PURE__ */ jsxRuntime.jsx(
804
+ "path",
692
805
  {
806
+ ref: determinateWavyActivePathRef,
693
807
  d: wavyActivePath != null ? wavyActivePath : "",
694
808
  fill: "none",
695
809
  stroke: activeColor,
696
810
  strokeWidth: trackHeight,
697
- strokeLinecap: "round",
698
- initial: { pathLength: 0 },
699
- animate: { pathLength: clampedValue / 100 },
700
- transition: {
701
- duration: 0.4,
702
- ease: [0.2, 0, 0, 1]
703
- }
811
+ strokeLinecap: "round"
704
812
  }
705
- ) : /* @__PURE__ */ jsxRuntime.jsx(
813
+ )
814
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
815
+ /* @__PURE__ */ jsxRuntime.jsx(
816
+ react.m.circle,
817
+ {
818
+ cx: center,
819
+ cy: center,
820
+ r: radius,
821
+ fill: "none",
822
+ stroke: bgTrackColor,
823
+ strokeWidth: trackHeight,
824
+ initial: {
825
+ pathLength: trackLength,
826
+ pathOffset: trackOffset
827
+ },
828
+ animate: {
829
+ pathLength: trackLength,
830
+ pathOffset: trackOffset
831
+ },
832
+ transition: { duration: 0.4, ease: [0.2, 0, 0, 1] },
833
+ strokeLinecap: "round"
834
+ }
835
+ ),
836
+ /* @__PURE__ */ jsxRuntime.jsx(
706
837
  ActiveCircleElem,
707
838
  {
708
839
  cx: center,
@@ -719,8 +850,8 @@ var CircularProgress = React3__namespace.forwardRef(
719
850
  ease: [0.2, 0, 0, 1]
720
851
  }
721
852
  }
722
- ))
723
- ]
853
+ )
854
+ ] }) : null
724
855
  }
725
856
  ),
726
857
  !isDeterminate && /* @__PURE__ */ jsxRuntime.jsx(