@bug-on/m3-expressive 1.2.6 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/layout.js CHANGED
@@ -537,7 +537,7 @@ function generateWavyCircularPath(center, radius, amplitude, wavelength) {
537
537
  if (i === 0) d += `M ${xAt(t0).toFixed(2)} ${yAt(t0).toFixed(2)}`;
538
538
  d += ` C ${cp1x.toFixed(2)} ${cp1y.toFixed(2)}, ${cp2x.toFixed(2)} ${cp2y.toFixed(2)}, ${xAt(t1).toFixed(2)} ${yAt(t1).toFixed(2)}`;
539
539
  }
540
- return d;
540
+ return `${d} Z`;
541
541
  }
542
542
  function getSinePath(startX, endX, phase, wl, amp) {
543
543
  if (startX >= endX) return "";
@@ -569,6 +569,14 @@ function getSinePath(startX, endX, phase, wl, amp) {
569
569
  }
570
570
  return d;
571
571
  }
572
+ var GLOBAL_ROTATION_DURATION = 6e3;
573
+ var GLOBAL_ROTATION_TARGET = 1080;
574
+ var ADDITIONAL_ROTATION_CYCLE = 1500;
575
+ var ADDITIONAL_ROTATION_STEP = 90;
576
+ var ADDITIONAL_ROTATION_EASE_DURATION = 500;
577
+ var DEFAULT_MIN_PROGRESS = 0.1;
578
+ var DEFAULT_MAX_PROGRESS = 0.8;
579
+ var PROGRESS_CYCLE_DURATION = 1500;
572
580
  var CircularProgress = React18__namespace.forwardRef(
573
581
  (_a, ref) => {
574
582
  var _b = _a, {
@@ -582,6 +590,10 @@ var CircularProgress = React18__namespace.forwardRef(
582
590
  crawlerSpeed = 1,
583
591
  color,
584
592
  trackColor,
593
+ showTrack = "auto",
594
+ minProgress = DEFAULT_MIN_PROGRESS,
595
+ maxProgress = DEFAULT_MAX_PROGRESS,
596
+ amplitudeRange,
585
597
  className,
586
598
  "aria-label": ariaLabel
587
599
  } = _b, restProps = __objRest(_b, [
@@ -595,6 +607,10 @@ var CircularProgress = React18__namespace.forwardRef(
595
607
  "crawlerSpeed",
596
608
  "color",
597
609
  "trackColor",
610
+ "showTrack",
611
+ "minProgress",
612
+ "maxProgress",
613
+ "amplitudeRange",
598
614
  "className",
599
615
  "aria-label"
600
616
  ]);
@@ -605,6 +621,7 @@ var CircularProgress = React18__namespace.forwardRef(
605
621
  const activeColor = color || "var(--md-sys-color-indicator-active)";
606
622
  const bgTrackColor = trackColor || "var(--md-sys-color-indicator-track)";
607
623
  const isWavy = shape === "wavy";
624
+ const shouldShowIndeterminateTrack = showTrack === "auto" ? isWavy : showTrack;
608
625
  const BASELINE_SIZE = 48;
609
626
  const scaleFactor = size / BASELINE_SIZE;
610
627
  const effectiveAmplitude = React18__namespace.useMemo(
@@ -615,6 +632,10 @@ var CircularProgress = React18__namespace.forwardRef(
615
632
  () => wavelength != null ? wavelength : 15 * scaleFactor,
616
633
  [wavelength, scaleFactor]
617
634
  );
635
+ const resolvedAmplitudeRange = React18__namespace.useMemo(
636
+ () => amplitudeRange != null ? amplitudeRange : [0, effectiveAmplitude],
637
+ [amplitudeRange, effectiveAmplitude]
638
+ );
618
639
  const wavyActivePath = React18__namespace.useMemo(
619
640
  () => isWavy ? generateWavyCircularPath(
620
641
  center,
@@ -634,6 +655,145 @@ var CircularProgress = React18__namespace.forwardRef(
634
655
  const trackLength = isDeterminate ? Math.max(1e-3, 1 - activeAngularFraction - 2 * gapForTrack) : 1;
635
656
  const ActiveCircleElem = react.m.circle;
636
657
  const ActivePathElem = react.m.path;
658
+ const indeterminateSvgRef = React18__namespace.useRef(null);
659
+ const indeterminateTrackRef = React18__namespace.useRef(null);
660
+ const indeterminateActiveRef = React18__namespace.useRef(null);
661
+ const indeterminateWavyTrackPathRef = React18__namespace.useRef(null);
662
+ const indeterminateWavyActivePathRef = React18__namespace.useRef(null);
663
+ const cachedPathLengthRef = React18__namespace.useRef(0);
664
+ React18__namespace.useLayoutEffect(() => {
665
+ if (!isWavy || !wavyActivePath) {
666
+ cachedPathLengthRef.current = circumference;
667
+ return;
668
+ }
669
+ const el = indeterminateActiveRef.current;
670
+ if (el && "getTotalLength" in el) {
671
+ try {
672
+ const len = el.getTotalLength();
673
+ if (len > 0) {
674
+ cachedPathLengthRef.current = len;
675
+ return;
676
+ }
677
+ } catch (e) {
678
+ }
679
+ }
680
+ cachedPathLengthRef.current = circumference;
681
+ }, [isWavy, circumference, wavyActivePath]);
682
+ react.useAnimationFrame((time) => {
683
+ if (isDeterminate) return;
684
+ const safeCrawlerSpeed = Math.max(0.1, crawlerSpeed);
685
+ const scaledTime = time * safeCrawlerSpeed;
686
+ const globalCycle = scaledTime % GLOBAL_ROTATION_DURATION;
687
+ const globalAngle = globalCycle / GLOBAL_ROTATION_DURATION * GLOBAL_ROTATION_TARGET;
688
+ const additionalFullCycles = Math.floor(
689
+ scaledTime / ADDITIONAL_ROTATION_CYCLE
690
+ );
691
+ const additionalCycleTime = scaledTime % ADDITIONAL_ROTATION_CYCLE;
692
+ const additionalEaseT = Math.min(
693
+ 1,
694
+ additionalCycleTime / ADDITIONAL_ROTATION_EASE_DURATION
695
+ );
696
+ const additionalAngle = (additionalFullCycles + easeInOutCubic(additionalEaseT)) * ADDITIONAL_ROTATION_STEP;
697
+ const totalRotation = globalAngle + additionalAngle;
698
+ if (indeterminateSvgRef.current) {
699
+ indeterminateSvgRef.current.style.transform = `rotate(${totalRotation - 90}deg)`;
700
+ }
701
+ const progressFullCycle = PROGRESS_CYCLE_DURATION * 2;
702
+ const progressCycleTime = scaledTime % progressFullCycle;
703
+ let progress;
704
+ if (progressCycleTime < PROGRESS_CYCLE_DURATION) {
705
+ const t = progressCycleTime / PROGRESS_CYCLE_DURATION;
706
+ progress = minProgress + (maxProgress - minProgress) * easeInOutCubic(t);
707
+ } else {
708
+ const t = (progressCycleTime - PROGRESS_CYCLE_DURATION) / PROGRESS_CYCLE_DURATION;
709
+ progress = maxProgress - (maxProgress - minProgress) * easeInOutCubic(t);
710
+ }
711
+ if (isWavy) {
712
+ const amplitudeT = (progress - minProgress) / (maxProgress - minProgress);
713
+ const currentAmplitude = resolvedAmplitudeRange[0] + (resolvedAmplitudeRange[1] - resolvedAmplitudeRange[0]) * amplitudeT;
714
+ const dynamicPath = generateWavyCircularPath(
715
+ center,
716
+ radius,
717
+ currentAmplitude,
718
+ effectiveWavelength
719
+ );
720
+ if (indeterminateWavyActivePathRef.current) {
721
+ indeterminateWavyActivePathRef.current.setAttribute("d", dynamicPath);
722
+ }
723
+ if (indeterminateWavyTrackPathRef.current) {
724
+ indeterminateWavyTrackPathRef.current.setAttribute("d", dynamicPath);
725
+ }
726
+ const pathEl = indeterminateWavyActivePathRef.current;
727
+ let totalLen = cachedPathLengthRef.current || circumference;
728
+ if (pathEl) {
729
+ try {
730
+ const len = pathEl.getTotalLength();
731
+ if (len > 0) totalLen = len;
732
+ } catch (e) {
733
+ }
734
+ }
735
+ const gapFrac = (gapSize + trackHeight) / totalLen;
736
+ const activeLen = totalLen * progress;
737
+ const activeOff = 0;
738
+ if (indeterminateWavyActivePathRef.current) {
739
+ indeterminateWavyActivePathRef.current.setAttribute(
740
+ "stroke-dasharray",
741
+ `${activeLen} ${totalLen}`
742
+ );
743
+ indeterminateWavyActivePathRef.current.setAttribute(
744
+ "stroke-dashoffset",
745
+ `${activeOff}`
746
+ );
747
+ }
748
+ if (shouldShowIndeterminateTrack && indeterminateWavyTrackPathRef.current) {
749
+ const trackStartFrac = progress + gapFrac;
750
+ const trackLen = Math.max(
751
+ 1e-3,
752
+ totalLen * (1 - progress - 2 * gapFrac)
753
+ );
754
+ const trackOff = -totalLen * trackStartFrac;
755
+ indeterminateWavyTrackPathRef.current.setAttribute(
756
+ "stroke-dasharray",
757
+ `${trackLen} ${totalLen}`
758
+ );
759
+ indeterminateWavyTrackPathRef.current.setAttribute(
760
+ "stroke-dashoffset",
761
+ `${trackOff}`
762
+ );
763
+ }
764
+ } else {
765
+ const totalLen = circumference;
766
+ const activeLen = totalLen * progress;
767
+ const activeOff = 0;
768
+ if (indeterminateActiveRef.current) {
769
+ indeterminateActiveRef.current.setAttribute(
770
+ "stroke-dasharray",
771
+ `${activeLen} ${totalLen}`
772
+ );
773
+ indeterminateActiveRef.current.setAttribute(
774
+ "stroke-dashoffset",
775
+ `${activeOff}`
776
+ );
777
+ }
778
+ if (shouldShowIndeterminateTrack && indeterminateTrackRef.current) {
779
+ const gapFrac = (gapSize + trackHeight) / totalLen;
780
+ const trackStartFrac = progress + gapFrac;
781
+ const trackLen = Math.max(
782
+ 1e-3,
783
+ totalLen * (1 - progress - 2 * gapFrac)
784
+ );
785
+ const trackOff = -totalLen * trackStartFrac;
786
+ indeterminateTrackRef.current.setAttribute(
787
+ "stroke-dasharray",
788
+ `${trackLen} ${totalLen}`
789
+ );
790
+ indeterminateTrackRef.current.setAttribute(
791
+ "stroke-dashoffset",
792
+ `${trackOff}`
793
+ );
794
+ }
795
+ }
796
+ });
637
797
  return /* @__PURE__ */ jsxRuntime.jsx(
638
798
  "div",
639
799
  __spreadProps(__spreadValues({
@@ -710,9 +870,10 @@ var CircularProgress = React18__namespace.forwardRef(
710
870
  ]
711
871
  }
712
872
  ),
713
- !isDeterminate && /* @__PURE__ */ jsxRuntime.jsxs(
714
- react.m.svg,
873
+ !isDeterminate && /* @__PURE__ */ jsxRuntime.jsx(
874
+ "svg",
715
875
  {
876
+ ref: indeterminateSvgRef,
716
877
  width: size,
717
878
  height: size,
718
879
  viewBox: `0 0 ${size} ${size}`,
@@ -721,84 +882,60 @@ var CircularProgress = React18__namespace.forwardRef(
721
882
  position: "absolute",
722
883
  inset: 0,
723
884
  overflow: "visible",
724
- transformOrigin: "center"
725
- },
726
- animate: { rotate: [0, 360] },
727
- transition: {
728
- duration: 2 / Math.max(0.1, crawlerSpeed),
729
- repeat: Number.POSITIVE_INFINITY,
730
- ease: "linear"
885
+ transformOrigin: "center",
886
+ transform: "rotate(-90deg)"
731
887
  },
732
- children: [
733
- /* @__PURE__ */ jsxRuntime.jsx(
734
- react.m.circle,
888
+ children: isWavy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
889
+ shouldShowIndeterminateTrack && /* @__PURE__ */ jsxRuntime.jsx(
890
+ "path",
735
891
  {
736
- cx: center,
737
- cy: center,
738
- r: radius,
892
+ ref: indeterminateWavyTrackPathRef,
893
+ d: wavyActivePath != null ? wavyActivePath : "",
739
894
  fill: "none",
740
895
  stroke: bgTrackColor,
741
896
  strokeWidth: trackHeight,
742
- strokeLinecap: "round",
743
- animate: {
744
- pathLength: [
745
- Math.max(1e-3, 0.9 - 2 * gapForTrack),
746
- Math.max(1e-3, 0.25 - 2 * gapForTrack),
747
- Math.max(1e-3, 0.9 - 2 * gapForTrack)
748
- ],
749
- pathOffset: [
750
- 0.1 + gapForTrack,
751
- 0.75 + gapForTrack,
752
- 0.1 + gapForTrack
753
- ]
754
- },
755
- transition: {
756
- duration: 2 / Math.max(0.1, crawlerSpeed),
757
- repeat: Number.POSITIVE_INFINITY,
758
- ease: [0.4, 0, 0.2, 1]
759
- }
897
+ strokeLinecap: "round"
760
898
  }
761
899
  ),
762
- isWavy ? /* @__PURE__ */ jsxRuntime.jsx(
763
- ActivePathElem,
900
+ /* @__PURE__ */ jsxRuntime.jsx(
901
+ "path",
764
902
  {
903
+ ref: indeterminateWavyActivePathRef,
765
904
  d: wavyActivePath != null ? wavyActivePath : "",
766
905
  fill: "none",
767
906
  stroke: activeColor,
768
907
  strokeWidth: trackHeight,
769
- strokeLinecap: "round",
770
- animate: {
771
- pathLength: [0.1, 0.75, 0.1],
772
- pathOffset: [0, 0.65, 1]
773
- },
774
- transition: {
775
- duration: 2 / Math.max(0.1, crawlerSpeed),
776
- repeat: Number.POSITIVE_INFINITY,
777
- ease: [0.4, 0, 0.2, 1]
778
- }
908
+ strokeLinecap: "round"
779
909
  }
780
- ) : /* @__PURE__ */ jsxRuntime.jsx(
781
- ActiveCircleElem,
910
+ )
911
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
912
+ shouldShowIndeterminateTrack && /* @__PURE__ */ jsxRuntime.jsx(
913
+ "circle",
914
+ {
915
+ ref: indeterminateTrackRef,
916
+ cx: center,
917
+ cy: center,
918
+ r: radius,
919
+ fill: "none",
920
+ stroke: bgTrackColor,
921
+ strokeWidth: trackHeight,
922
+ strokeLinecap: "round"
923
+ }
924
+ ),
925
+ /* @__PURE__ */ jsxRuntime.jsx(
926
+ "circle",
782
927
  {
928
+ ref: indeterminateActiveRef,
783
929
  cx: center,
784
930
  cy: center,
785
931
  r: radius,
786
932
  fill: "none",
787
933
  stroke: activeColor,
788
934
  strokeWidth: trackHeight,
789
- strokeLinecap: "round",
790
- animate: {
791
- pathLength: [0.1, 0.75, 0.1],
792
- pathOffset: [0, 0.65, 1]
793
- },
794
- transition: {
795
- duration: 2 / Math.max(0.1, crawlerSpeed),
796
- repeat: Number.POSITIVE_INFINITY,
797
- ease: [0.4, 0, 0.2, 1]
798
- }
935
+ strokeLinecap: "round"
799
936
  }
800
937
  )
801
- ]
938
+ ] })
802
939
  }
803
940
  )
804
941
  ] })
@@ -1004,7 +1141,7 @@ var WavyLinearTrack = React18__namespace.memo(function WavyLinearTrack2({
1004
1141
  currentAmp
1005
1142
  );
1006
1143
  } else if (fraction === 0) {
1007
- activePathD = `M ${capWidth} 0 L ${capWidth + 0.01} 0`;
1144
+ activePathD = "";
1008
1145
  }
1009
1146
  const trackStart = adjHead + totalGap;
1010
1147
  if (trackStart < width - capWidth) {
@@ -1036,20 +1173,20 @@ var WavyLinearTrack = React18__namespace.memo(function WavyLinearTrack2({
1036
1173
  activeLines.push({ tail: l1T, head: l1H });
1037
1174
  activeLines.push({ tail: l2T, head: l2H });
1038
1175
  }
1039
- const segments = activeLines.map((line) => {
1040
- const barTail = line.tail * width;
1041
- const barHead = line.head * width;
1176
+ const activeSegments = activeLines.map((line) => {
1177
+ const rawTail = line.tail * width;
1178
+ const rawHead = line.head * width;
1042
1179
  const adjTail = Math.max(
1043
1180
  capWidth,
1044
- Math.min(width - capWidth, barTail)
1181
+ Math.min(width - capWidth, rawTail)
1045
1182
  );
1046
1183
  const adjHead = Math.max(
1047
1184
  capWidth,
1048
- Math.min(width - capWidth, barHead)
1185
+ Math.min(width - capWidth, rawHead)
1049
1186
  );
1050
1187
  return { adjTail, adjHead };
1051
1188
  }).filter((seg) => seg.adjHead - seg.adjTail > 0.1);
1052
- activePathD = segments.map(
1189
+ activePathD = activeSegments.map(
1053
1190
  (seg) => getSinePath(
1054
1191
  seg.adjTail,
1055
1192
  seg.adjHead,
@@ -1058,13 +1195,24 @@ var WavyLinearTrack = React18__namespace.memo(function WavyLinearTrack2({
1058
1195
  currentAmp
1059
1196
  )
1060
1197
  ).join(" ");
1198
+ const validActiveLines = activeLines.filter(
1199
+ (line) => line.head > line.tail && line.head * width > 0 && line.tail * width < width
1200
+ ).sort((a, b) => a.tail - b.tail);
1061
1201
  let currentTrackX = capWidth;
1062
- for (const seg of segments) {
1063
- const trackEnd = seg.adjTail - totalGap;
1202
+ for (const line of validActiveLines) {
1203
+ const blockStart = line.tail * width - totalGap;
1204
+ const blockEnd = line.head * width + totalGap;
1205
+ const trackEnd = Math.min(width - capWidth, blockStart);
1064
1206
  if (trackEnd > currentTrackX) {
1065
- trackD += `${getSinePath(currentTrackX, trackEnd, phase, activeWavelength, trackAmp)} `;
1207
+ trackD += `${getSinePath(
1208
+ currentTrackX,
1209
+ trackEnd,
1210
+ phase,
1211
+ activeWavelength,
1212
+ trackAmp
1213
+ )} `;
1066
1214
  }
1067
- currentTrackX = Math.max(currentTrackX, seg.adjHead + totalGap);
1215
+ currentTrackX = Math.max(currentTrackX, blockEnd);
1068
1216
  }
1069
1217
  if (currentTrackX < width - capWidth) {
1070
1218
  trackD += getSinePath(
@@ -1077,9 +1225,9 @@ var WavyLinearTrack = React18__namespace.memo(function WavyLinearTrack2({
1077
1225
  }
1078
1226
  }
1079
1227
  if (activePathRef.current)
1080
- activePathRef.current.setAttribute("d", activePathD);
1228
+ activePathRef.current.setAttribute("d", activePathD || "");
1081
1229
  if (trackPathRef.current)
1082
- trackPathRef.current.setAttribute("d", trackD.trim());
1230
+ trackPathRef.current.setAttribute("d", trackD.trim() || "");
1083
1231
  });
1084
1232
  return /* @__PURE__ */ jsxRuntime.jsx(
1085
1233
  "div",