@bug-on/md3-react 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -236,7 +236,7 @@ function generateM3Theme(sourceColorHex, mode = "light") {
236
236
  function applyTheme(sourceColorHex, mode = "light", root = document.documentElement) {
237
237
  const colors = generateM3Theme(sourceColorHex, mode);
238
238
  for (const [key, value] of Object.entries(colors)) {
239
- const kebabKey = key.replace(/[A-Z]/g, (m26) => `-${m26.toLowerCase()}`);
239
+ const kebabKey = key.replace(/[A-Z]/g, (m28) => `-${m28.toLowerCase()}`);
240
240
  root.style.setProperty(`--md-sys-color-${kebabKey}`, value);
241
241
  root.style.setProperty(`--color-m3-${kebabKey}`, value);
242
242
  }
@@ -5515,6 +5515,1748 @@ var RadioGroupComponent = React25__namespace.forwardRef(
5515
5515
  );
5516
5516
  RadioGroupComponent.displayName = "RadioGroup";
5517
5517
  var RadioGroup2 = React25__namespace.memo(RadioGroupComponent);
5518
+ function coerceValue(value, min, max) {
5519
+ return Math.max(min, Math.min(max, value));
5520
+ }
5521
+ function snapToStep(value, min, step) {
5522
+ if (step <= 0) return value;
5523
+ const steps = Math.round((value - min) / step);
5524
+ return Number((min + steps * step).toPrecision(10));
5525
+ }
5526
+ function valueToPercent(value, min, max) {
5527
+ if (max === min) return 0;
5528
+ return (value - min) / (max - min);
5529
+ }
5530
+ function percentToValue(percent, min, max, step) {
5531
+ const raw = min + percent * (max - min);
5532
+ const snapped = snapToStep(raw, min, step);
5533
+ return coerceValue(snapped, min, max);
5534
+ }
5535
+ function getKeyboardDelta(key, step, min, max) {
5536
+ const range = max - min;
5537
+ const discreteStep = step > 0 ? step : range / 100;
5538
+ switch (key) {
5539
+ case "ArrowRight":
5540
+ case "ArrowUp":
5541
+ return discreteStep;
5542
+ case "ArrowLeft":
5543
+ case "ArrowDown":
5544
+ return -discreteStep;
5545
+ case "PageUp":
5546
+ return step > 0 ? snapToStep(range * 0.1, 0, step) : range * 0.1;
5547
+ case "PageDown":
5548
+ return step > 0 ? -snapToStep(range * 0.1, 0, step) : -(range * 0.1);
5549
+ default:
5550
+ return null;
5551
+ }
5552
+ }
5553
+ function generateTicks(min, max, step) {
5554
+ if (step <= 0) return [];
5555
+ const ticks = [];
5556
+ let current = min;
5557
+ while (current <= max) {
5558
+ ticks.push(Number(current.toPrecision(10)));
5559
+ current += step;
5560
+ }
5561
+ if (ticks[ticks.length - 1] !== max) {
5562
+ ticks.push(max);
5563
+ }
5564
+ return ticks;
5565
+ }
5566
+ function useSliderMath({
5567
+ min,
5568
+ max,
5569
+ step
5570
+ }) {
5571
+ return React25.useMemo(
5572
+ () => ({
5573
+ coerce: (v) => coerceValue(v, min, max),
5574
+ snap: (v) => snapToStep(v, min, step),
5575
+ toPercent: (v) => valueToPercent(v, min, max),
5576
+ fromPercent: (pct) => percentToValue(pct, min, max, step),
5577
+ getKeyDelta: (key) => getKeyboardDelta(key, step, min, max),
5578
+ ticks: generateTicks(min, max, step)
5579
+ }),
5580
+ [min, max, step]
5581
+ );
5582
+ }
5583
+
5584
+ // src/ui/slider/slider.tokens.ts
5585
+ var SliderTokens = {
5586
+ // ── Track sizes (height for horizontal, width for vertical) ────────────────
5587
+ trackSizes: {
5588
+ xs: 16,
5589
+ s: 24,
5590
+ m: 40,
5591
+ l: 56,
5592
+ xl: 96
5593
+ },
5594
+ // ── Track shapes (border radius) ──────────────────────────────────────────
5595
+ trackShapes: {
5596
+ xs: 8,
5597
+ s: 8,
5598
+ m: 12,
5599
+ l: 16,
5600
+ xl: 28
5601
+ },
5602
+ // ── Thumb (handle) ────────────────────────────────────────────────────────
5603
+ /** Thumb height grows with track size */
5604
+ thumbHeights: {
5605
+ xs: 44,
5606
+ s: 44,
5607
+ m: 52,
5608
+ l: 68,
5609
+ xl: 108
5610
+ },
5611
+ /**
5612
+ * Thumb width at rest and on hover.
5613
+ * MD3 Expressive handle pill: 4dp wide.
5614
+ */
5615
+ thumbWidthDefault: 4,
5616
+ /**
5617
+ * Thumb width while pressed/dragging.
5618
+ * "Squeeze" animation: 4dp → 2dp (M3 Expressive behavior).
5619
+ */
5620
+ thumbWidthPressed: 2,
5621
+ // ── Track–thumb gap ───────────────────────────────────────────────────────
5622
+ /**
5623
+ * Transparent gap between the active/inactive track segments and the thumb.
5624
+ * Maps to ActiveHandleLeadingSpace / ActiveHandleTrailingSpace = 6dp.
5625
+ *
5626
+ * This gap is rendered by mathematically subtracting it from the track
5627
+ * segment width — NOT using margin/padding.
5628
+ */
5629
+ thumbGap: 6,
5630
+ // ── Track corner radii ────────────────────────────────────────────────────
5631
+ /**
5632
+ * Corner radius on the INNER ends of each track segment (facing the thumb).
5633
+ * Fixed to 2px according to MD3 Expressive Slider specs (TrackInsideCornerSize).
5634
+ * Outer ends use `trackSize / 2` (pill cap) — computed inline per component.
5635
+ */
5636
+ trackInnerRadius: 2,
5637
+ // ── Stop indicator / Tick ─────────────────────────────────────────────────
5638
+ /** Tick dot size (width and height). = 4dp. */
5639
+ tickSize: 4,
5640
+ // ── Touch target ─────────────────────────────────────────────────────────
5641
+ /**
5642
+ * Minimum touch target for the thumb wrapper.
5643
+ * MD3 requires 48dp minimum touch target for interactive elements.
5644
+ */
5645
+ thumbTouchTarget: 48,
5646
+ // ── Value indicator ───────────────────────────────────────────────────────
5647
+ /** Offset above the thumb center for the value indicator tooltip. */
5648
+ valueIndicatorOffset: 52,
5649
+ // ── Inset icon ────────────────────────────────────────────────────────────
5650
+ /** Standard icon size map for inset icons inside the track. */
5651
+ insetIconSizes: {
5652
+ xs: 0,
5653
+ s: 0,
5654
+ m: 24,
5655
+ l: 24,
5656
+ xl: 32
5657
+ },
5658
+ /**
5659
+ * Padding between icon and track edge (horizontal).
5660
+ * Keeps the icon visually centered within the pill track.
5661
+ */
5662
+ insetIconPadding: 4
5663
+ };
5664
+ var SliderColors = {
5665
+ // ── Track ─────────────────────────────────────────────────────────────────
5666
+ /** Active track color. Maps to ActiveTrackColor token. */
5667
+ activeTrack: "var(--md-sys-color-primary)",
5668
+ /** Inactive track color. Maps to InactiveTrackColor token. */
5669
+ inactiveTrack: "var(--md-sys-color-secondary-container)",
5670
+ /**
5671
+ * Disabled track color.
5672
+ * Uses opacity + on-surface per MD3 disabled state spec.
5673
+ */
5674
+ disabledActiveTrack: "var(--md-sys-color-on-surface)",
5675
+ disabledInactiveTrack: "var(--md-sys-color-on-surface)",
5676
+ // ── Thumb ─────────────────────────────────────────────────────────────────
5677
+ /** Thumb (handle) color. Maps to HandleColor token. */
5678
+ thumb: "var(--md-sys-color-primary)",
5679
+ /** Disabled thumb color. */
5680
+ disabledThumb: "var(--md-sys-color-on-surface)",
5681
+ // ── Value indicator ───────────────────────────────────────────────────────
5682
+ /** Value indicator (tooltip) background. Maps to InverseSurface. */
5683
+ valueIndicatorBg: "var(--md-sys-color-inverse-surface)",
5684
+ /** Value indicator (tooltip) text. Maps to InverseOnSurface. */
5685
+ valueIndicatorText: "var(--md-sys-color-inverse-on-surface)",
5686
+ // ── Ticks ────────────────────────────────────────────────────────────────
5687
+ /**
5688
+ * Tick on the INACTIVE portion of the track.
5689
+ * Maps to TickMarkActiveContainerColor (in spec: primary color stands out).
5690
+ */
5691
+ tickOnInactive: "var(--md-sys-color-primary)",
5692
+ /**
5693
+ * Tick on the ACTIVE portion of the track.
5694
+ * Maps to TickMarkInactiveContainerColor (secondary-container blends in).
5695
+ */
5696
+ tickOnActive: "var(--md-sys-color-secondary-container)",
5697
+ disabledTick: "var(--md-sys-color-on-surface)"
5698
+ };
5699
+ var SLIDER_THUMB_SPRING = {
5700
+ type: "spring",
5701
+ stiffness: 500,
5702
+ damping: 40
5703
+ };
5704
+ var SLIDER_INDICATOR_TRANSITION = {
5705
+ type: "spring",
5706
+ stiffness: 450,
5707
+ damping: 32
5708
+ };
5709
+ var ValueIndicator = React25__namespace.memo(function ValueIndicator2({
5710
+ value,
5711
+ visible,
5712
+ orientation,
5713
+ formatValue,
5714
+ prefersReduced,
5715
+ trackSize
5716
+ }) {
5717
+ const label = formatValue ? formatValue(value) : String(Math.round(value));
5718
+ const isHorizontal = orientation === "horizontal";
5719
+ const thumbHeight = SliderTokens.thumbHeights[trackSize];
5720
+ const offsetFromCenter = thumbHeight / 2 + 8;
5721
+ return /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: visible && /* @__PURE__ */ jsxRuntime.jsx(
5722
+ react.m.div,
5723
+ {
5724
+ role: "tooltip",
5725
+ "aria-hidden": "true",
5726
+ initial: prefersReduced ? false : {
5727
+ scale: 0,
5728
+ opacity: 0,
5729
+ y: isHorizontal ? 6 : 0,
5730
+ x: !isHorizontal ? -6 : 0
5731
+ },
5732
+ animate: { scale: 1, opacity: 1, y: 0, x: 0 },
5733
+ exit: prefersReduced ? {} : {
5734
+ scale: 0,
5735
+ opacity: 0,
5736
+ y: isHorizontal ? 6 : 0,
5737
+ x: !isHorizontal ? -6 : 0
5738
+ },
5739
+ transition: prefersReduced ? { duration: 0 } : SLIDER_INDICATOR_TRANSITION,
5740
+ className: cn(
5741
+ "absolute pointer-events-none select-none",
5742
+ "rounded-full px-2.5 py-1 text-xs font-medium leading-none whitespace-nowrap",
5743
+ // Position: above for horizontal, right for vertical
5744
+ isHorizontal ? "-translate-x-1/2 left-1/2" : "translate-y-1/2 bottom-1/2"
5745
+ ),
5746
+ style: __spreadValues({
5747
+ backgroundColor: SliderColors.valueIndicatorBg,
5748
+ color: SliderColors.valueIndicatorText,
5749
+ transformOrigin: isHorizontal ? "bottom center" : "center left"
5750
+ }, isHorizontal ? { bottom: `calc(50% + ${offsetFromCenter}px)` } : { left: `calc(50% + ${offsetFromCenter}px)` }),
5751
+ children: label
5752
+ },
5753
+ "value-indicator"
5754
+ ) });
5755
+ });
5756
+ var SliderThumb = React25__namespace.memo(function SliderThumb2({
5757
+ value,
5758
+ percent,
5759
+ min,
5760
+ max,
5761
+ step,
5762
+ disabled,
5763
+ orientation,
5764
+ showValueIndicator,
5765
+ trackRef,
5766
+ onValueChange,
5767
+ onValueChangeEnd,
5768
+ formatValue,
5769
+ thumbId,
5770
+ trackSize,
5771
+ variant,
5772
+ zIndex = 1,
5773
+ "aria-label": ariaLabel,
5774
+ "aria-labelledby": ariaLabelledBy
5775
+ }) {
5776
+ var _a;
5777
+ const isHorizontal = orientation === "horizontal";
5778
+ const insetLimit = SliderTokens.thumbGap + SliderTokens.thumbWidthDefault / 2;
5779
+ const trackInset = Math.min(
5780
+ SliderTokens.trackSizes[trackSize] / 2,
5781
+ insetLimit
5782
+ );
5783
+ const posTarget = isHorizontal ? "left" : "bottom";
5784
+ const motionStyle = {
5785
+ [posTarget]: `calc(${trackInset}px + ${percent} * (100% - ${trackInset * 2}px))`
5786
+ };
5787
+ const prefersReduced = (_a = react.useReducedMotion()) != null ? _a : false;
5788
+ const [isDragging, setIsDragging] = React25__namespace.useState(false);
5789
+ const [isHovered, setIsHovered] = React25__namespace.useState(false);
5790
+ const [isFocused, setIsFocused] = React25__namespace.useState(false);
5791
+ const pointerIdRef = React25__namespace.useRef(null);
5792
+ const thumbRef = React25__namespace.useRef(null);
5793
+ const showIndicator = showValueIndicator && (isDragging || isHovered || isFocused);
5794
+ const positionStyle = isHorizontal ? __spreadProps(__spreadValues({
5795
+ position: "absolute"
5796
+ }, motionStyle), {
5797
+ top: "50%",
5798
+ transform: "translate(-50%, -50%)",
5799
+ zIndex
5800
+ }) : __spreadProps(__spreadValues({
5801
+ position: "absolute"
5802
+ }, motionStyle), {
5803
+ left: "50%",
5804
+ transform: "translate(-50%, 50%)",
5805
+ zIndex
5806
+ });
5807
+ const getDeltaFromPointer = React25__namespace.useCallback(
5808
+ (e) => {
5809
+ const trackEl = trackRef.current;
5810
+ if (!trackEl) return percent;
5811
+ const rect = trackEl.getBoundingClientRect();
5812
+ const space = isHorizontal ? rect.width : rect.height;
5813
+ const insetLimit2 = SliderTokens.thumbGap + SliderTokens.thumbWidthDefault / 2;
5814
+ const trackInset2 = Math.min(
5815
+ SliderTokens.trackSizes[trackSize] / 2,
5816
+ insetLimit2
5817
+ );
5818
+ const safeSpace = space - trackInset2 * 2;
5819
+ if (safeSpace <= 0) return percent;
5820
+ let rawPercent;
5821
+ if (isHorizontal) {
5822
+ rawPercent = (e.clientX - rect.left - trackInset2) / safeSpace;
5823
+ } else {
5824
+ rawPercent = (rect.bottom - e.clientY - trackInset2) / safeSpace;
5825
+ }
5826
+ const clamped = Math.max(0, Math.min(1, rawPercent));
5827
+ const range = max - min;
5828
+ const rawValue = min + clamped * range;
5829
+ const snapped = step > 0 ? Math.round((rawValue - min) / step) * step + min : rawValue;
5830
+ return Math.max(min, Math.min(max, snapped));
5831
+ },
5832
+ [isHorizontal, max, min, percent, step, trackRef, trackSize]
5833
+ );
5834
+ const handlePointerDown = React25__namespace.useCallback(
5835
+ (e) => {
5836
+ if (disabled) return;
5837
+ e.preventDefault();
5838
+ e.stopPropagation();
5839
+ e.currentTarget.setPointerCapture(e.pointerId);
5840
+ pointerIdRef.current = e.pointerId;
5841
+ setIsDragging(true);
5842
+ },
5843
+ [disabled]
5844
+ );
5845
+ const handlePointerMove = React25__namespace.useCallback(
5846
+ (e) => {
5847
+ if (!isDragging || e.pointerId !== pointerIdRef.current) return;
5848
+ const newValue = getDeltaFromPointer(e.nativeEvent);
5849
+ onValueChange(newValue);
5850
+ },
5851
+ [isDragging, getDeltaFromPointer, onValueChange]
5852
+ );
5853
+ const handlePointerUp = React25__namespace.useCallback(
5854
+ (e) => {
5855
+ if (e.pointerId !== pointerIdRef.current) return;
5856
+ e.currentTarget.releasePointerCapture(e.pointerId);
5857
+ pointerIdRef.current = null;
5858
+ setIsDragging(false);
5859
+ onValueChangeEnd == null ? void 0 : onValueChangeEnd(value);
5860
+ },
5861
+ [onValueChangeEnd, value]
5862
+ );
5863
+ const handleKeyDown = React25__namespace.useCallback(
5864
+ (e) => {
5865
+ if (disabled) return;
5866
+ if (e.key === "Home") {
5867
+ e.preventDefault();
5868
+ onValueChange(min);
5869
+ onValueChangeEnd == null ? void 0 : onValueChangeEnd(min);
5870
+ return;
5871
+ }
5872
+ if (e.key === "End") {
5873
+ e.preventDefault();
5874
+ onValueChange(max);
5875
+ onValueChangeEnd == null ? void 0 : onValueChangeEnd(max);
5876
+ return;
5877
+ }
5878
+ const delta = getKeyboardDelta(e.key, step, min, max);
5879
+ if (delta === null) return;
5880
+ e.preventDefault();
5881
+ const newValue = Math.max(min, Math.min(max, value + delta));
5882
+ onValueChange(newValue);
5883
+ onValueChangeEnd == null ? void 0 : onValueChangeEnd(newValue);
5884
+ },
5885
+ [disabled, max, min, onValueChange, onValueChangeEnd, step, value]
5886
+ );
5887
+ const thumbColor = disabled ? SliderColors.disabledThumb : `var(--md-sys-color-${variant})`;
5888
+ const squeezeSize = isDragging ? SliderTokens.thumbWidthPressed : SliderTokens.thumbWidthDefault;
5889
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5890
+ "div",
5891
+ {
5892
+ style: __spreadProps(__spreadValues({}, positionStyle), {
5893
+ width: SliderTokens.thumbTouchTarget,
5894
+ height: SliderTokens.thumbTouchTarget,
5895
+ display: "flex",
5896
+ alignItems: "center",
5897
+ justifyContent: "center",
5898
+ touchAction: "none"
5899
+ }),
5900
+ className: cn(
5901
+ "cursor-grab",
5902
+ isDragging && "cursor-grabbing",
5903
+ disabled && "cursor-not-allowed"
5904
+ ),
5905
+ onPointerDown: handlePointerDown,
5906
+ onPointerMove: handlePointerMove,
5907
+ onPointerUp: handlePointerUp,
5908
+ onPointerCancel: handlePointerUp,
5909
+ children: [
5910
+ /* @__PURE__ */ jsxRuntime.jsx(
5911
+ ValueIndicator,
5912
+ {
5913
+ value,
5914
+ visible: showIndicator,
5915
+ orientation,
5916
+ formatValue,
5917
+ prefersReduced,
5918
+ trackSize
5919
+ }
5920
+ ),
5921
+ /* @__PURE__ */ jsxRuntime.jsx(
5922
+ react.m.div,
5923
+ {
5924
+ ref: thumbRef,
5925
+ id: thumbId,
5926
+ role: "slider",
5927
+ "aria-valuemin": min,
5928
+ "aria-valuemax": max,
5929
+ "aria-valuenow": value,
5930
+ "aria-orientation": orientation,
5931
+ "aria-disabled": disabled || void 0,
5932
+ "aria-label": ariaLabel,
5933
+ "aria-labelledby": ariaLabelledBy,
5934
+ tabIndex: disabled ? -1 : 0,
5935
+ onKeyDown: handleKeyDown,
5936
+ onFocus: () => setIsFocused(true),
5937
+ onBlur: () => setIsFocused(false),
5938
+ onMouseEnter: () => !disabled && setIsHovered(true),
5939
+ onMouseLeave: () => setIsHovered(false),
5940
+ animate: __spreadProps(__spreadValues({}, isHorizontal ? { width: squeezeSize } : { height: squeezeSize }), {
5941
+ backgroundColor: thumbColor,
5942
+ opacity: disabled ? 0.38 : 1
5943
+ }),
5944
+ transition: prefersReduced ? { duration: 0 } : SLIDER_THUMB_SPRING,
5945
+ className: cn(
5946
+ "relative shrink-0 rounded-full select-none outline-none",
5947
+ "focus-visible:outline-2 focus-visible:outline-offset-2",
5948
+ "focus-visible:outline-(--md-sys-color-secondary)"
5949
+ ),
5950
+ style: __spreadProps(__spreadValues({}, isHorizontal ? {
5951
+ height: SliderTokens.thumbHeights[trackSize],
5952
+ width: SliderTokens.thumbWidthDefault,
5953
+ willChange: "width"
5954
+ } : {
5955
+ width: SliderTokens.thumbHeights[trackSize],
5956
+ height: SliderTokens.thumbWidthDefault,
5957
+ willChange: "height"
5958
+ }), {
5959
+ backgroundColor: thumbColor
5960
+ })
5961
+ }
5962
+ )
5963
+ ]
5964
+ }
5965
+ );
5966
+ });
5967
+ var RangeTrack = React25__namespace.memo(function RangeTrack2({
5968
+ startPercent,
5969
+ endPercent,
5970
+ trackSize,
5971
+ orientation,
5972
+ variant,
5973
+ disabled,
5974
+ ticks,
5975
+ min,
5976
+ max,
5977
+ trackShape = "md3",
5978
+ trackRef,
5979
+ onTrackPointerDown
5980
+ }) {
5981
+ const isHorizontal = orientation === "horizontal";
5982
+ const size = SliderTokens.trackSizes[trackSize];
5983
+ const thumbHeight = SliderTokens.thumbHeights[trackSize];
5984
+ const { thumbGap, thumbWidthDefault, tickSize } = SliderTokens;
5985
+ const thumbHalfWidth = thumbWidthDefault / 2;
5986
+ const activeTrack = disabled ? SliderColors.disabledActiveTrack : `var(--md-sys-color-${variant})`;
5987
+ const inactiveTrack = disabled ? SliderColors.disabledInactiveTrack : `var(--md-sys-color-${variant}-container)`;
5988
+ const innerR = SliderTokens.trackInnerRadius;
5989
+ let outerR = size / 2;
5990
+ if (trackShape === "md3") {
5991
+ outerR = Math.min(SliderTokens.trackShapes[trackSize], size / 2);
5992
+ } else if (typeof trackShape === "number") {
5993
+ outerR = Math.min(trackShape, size / 2);
5994
+ }
5995
+ if (isHorizontal) {
5996
+ const insetLimit2 = thumbGap + thumbWidthDefault / 2;
5997
+ const trackInset2 = Math.min(size / 2, insetLimit2);
5998
+ const cxStart = `calc(${trackInset2}px + ${startPercent} * (100% - ${trackInset2 * 2}px))`;
5999
+ const cxEnd = `calc(${trackInset2}px + ${endPercent} * (100% - ${trackInset2 * 2}px))`;
6000
+ const gapWithThumbStr2 = `${thumbGap + thumbHalfWidth}px`;
6001
+ const leadingWidth = `max(0px, calc(${cxStart} - ${gapWithThumbStr2}))`;
6002
+ const activeLeft = `calc(${cxStart} + ${gapWithThumbStr2})`;
6003
+ const activeWidth = `max(0px, calc(${cxEnd} - ${cxStart} - ${gapWithThumbStr2} * 2))`;
6004
+ const trailingLeft = `calc(${cxEnd} + ${gapWithThumbStr2})`;
6005
+ const trailingWidth = `max(0px, calc(100% - (${cxEnd} + ${gapWithThumbStr2})))`;
6006
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6007
+ "div",
6008
+ {
6009
+ ref: trackRef,
6010
+ className: cn(
6011
+ "relative w-full",
6012
+ disabled ? "cursor-not-allowed" : "cursor-pointer"
6013
+ ),
6014
+ style: { height: thumbHeight },
6015
+ onPointerDown: onTrackPointerDown,
6016
+ "aria-hidden": "true",
6017
+ children: [
6018
+ /* @__PURE__ */ jsxRuntime.jsx(
6019
+ "div",
6020
+ {
6021
+ "aria-hidden": "true",
6022
+ style: {
6023
+ position: "absolute",
6024
+ left: 0,
6025
+ top: "50%",
6026
+ transform: "translateY(-50%)",
6027
+ width: leadingWidth,
6028
+ height: size,
6029
+ backgroundColor: inactiveTrack,
6030
+ opacity: disabled ? 0.38 : 1,
6031
+ borderTopLeftRadius: outerR,
6032
+ borderBottomLeftRadius: outerR,
6033
+ borderTopRightRadius: innerR,
6034
+ borderBottomRightRadius: innerR
6035
+ }
6036
+ }
6037
+ ),
6038
+ /* @__PURE__ */ jsxRuntime.jsx(
6039
+ "div",
6040
+ {
6041
+ "aria-hidden": "true",
6042
+ style: {
6043
+ position: "absolute",
6044
+ left: activeLeft,
6045
+ top: "50%",
6046
+ transform: "translateY(-50%)",
6047
+ width: activeWidth,
6048
+ height: size,
6049
+ backgroundColor: activeTrack,
6050
+ opacity: disabled ? 0.38 : 1,
6051
+ borderTopLeftRadius: startPercent <= 0 ? outerR : innerR,
6052
+ borderBottomLeftRadius: startPercent <= 0 ? outerR : innerR,
6053
+ borderTopRightRadius: endPercent >= 1 ? outerR : innerR,
6054
+ borderBottomRightRadius: endPercent >= 1 ? outerR : innerR
6055
+ }
6056
+ }
6057
+ ),
6058
+ /* @__PURE__ */ jsxRuntime.jsx(
6059
+ "div",
6060
+ {
6061
+ "aria-hidden": "true",
6062
+ style: {
6063
+ position: "absolute",
6064
+ left: trailingLeft,
6065
+ top: "50%",
6066
+ transform: "translateY(-50%)",
6067
+ width: trailingWidth,
6068
+ height: size,
6069
+ backgroundColor: inactiveTrack,
6070
+ opacity: disabled ? 0.38 : 1,
6071
+ borderTopLeftRadius: innerR,
6072
+ borderBottomLeftRadius: innerR,
6073
+ borderTopRightRadius: outerR,
6074
+ borderBottomRightRadius: outerR
6075
+ }
6076
+ }
6077
+ ),
6078
+ ticks.map((tick) => {
6079
+ const tickPct = (tick - min) / (max - min);
6080
+ const isActive = tickPct > startPercent && tickPct < endPercent;
6081
+ return /* @__PURE__ */ jsxRuntime.jsx(
6082
+ "div",
6083
+ {
6084
+ "aria-hidden": "true",
6085
+ style: {
6086
+ position: "absolute",
6087
+ width: tickSize,
6088
+ height: tickSize,
6089
+ borderRadius: "50%",
6090
+ backgroundColor: disabled ? SliderColors.disabledTick : isActive ? `var(--md-sys-color-${variant}-container)` : `var(--md-sys-color-${variant})`,
6091
+ opacity: disabled ? 0.38 : 1,
6092
+ left: `calc(${trackInset2}px + ${tickPct} * (100% - ${trackInset2 * 2}px) - ${tickSize / 2}px)`,
6093
+ top: "50%",
6094
+ transform: "translateY(-50%)"
6095
+ }
6096
+ },
6097
+ tick
6098
+ );
6099
+ })
6100
+ ]
6101
+ }
6102
+ );
6103
+ }
6104
+ const insetLimit = thumbGap + thumbWidthDefault / 2;
6105
+ const trackInset = Math.min(size / 2, insetLimit);
6106
+ const cyStart = `calc(${trackInset}px + ${startPercent} * (100% - ${trackInset * 2}px))`;
6107
+ const cyEnd = `calc(${trackInset}px + ${endPercent} * (100% - ${trackInset * 2}px))`;
6108
+ const gapWithThumbStr = `${thumbGap + thumbHalfWidth}px`;
6109
+ const leadingHeight = `max(0px, calc(${cyStart} - ${gapWithThumbStr}))`;
6110
+ const activeBottom = `calc(${cyStart} + ${gapWithThumbStr})`;
6111
+ const activeHeight = `max(0px, calc(${cyEnd} - ${cyStart} - ${gapWithThumbStr} * 2))`;
6112
+ const trailingBottom = `calc(${cyEnd} + ${gapWithThumbStr})`;
6113
+ const trailingHeight = `max(0px, calc(100% - (${cyEnd} + ${gapWithThumbStr})))`;
6114
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6115
+ "div",
6116
+ {
6117
+ ref: trackRef,
6118
+ className: cn(
6119
+ "relative h-full",
6120
+ disabled ? "cursor-not-allowed" : "cursor-pointer"
6121
+ ),
6122
+ style: { width: thumbHeight },
6123
+ onPointerDown: onTrackPointerDown,
6124
+ "aria-hidden": "true",
6125
+ children: [
6126
+ /* @__PURE__ */ jsxRuntime.jsx(
6127
+ "div",
6128
+ {
6129
+ "aria-hidden": "true",
6130
+ style: {
6131
+ position: "absolute",
6132
+ bottom: 0,
6133
+ left: "50%",
6134
+ transform: "translateX(-50%)",
6135
+ height: leadingHeight,
6136
+ width: size,
6137
+ backgroundColor: inactiveTrack,
6138
+ opacity: disabled ? 0.38 : 1,
6139
+ borderBottomLeftRadius: outerR,
6140
+ borderBottomRightRadius: outerR,
6141
+ borderTopLeftRadius: innerR,
6142
+ borderTopRightRadius: innerR
6143
+ }
6144
+ }
6145
+ ),
6146
+ /* @__PURE__ */ jsxRuntime.jsx(
6147
+ "div",
6148
+ {
6149
+ "aria-hidden": "true",
6150
+ style: {
6151
+ position: "absolute",
6152
+ bottom: activeBottom,
6153
+ left: "50%",
6154
+ transform: "translateX(-50%)",
6155
+ height: activeHeight,
6156
+ width: size,
6157
+ backgroundColor: activeTrack,
6158
+ opacity: disabled ? 0.38 : 1,
6159
+ borderBottomLeftRadius: startPercent <= 0 ? outerR : innerR,
6160
+ borderBottomRightRadius: startPercent <= 0 ? outerR : innerR,
6161
+ borderTopLeftRadius: endPercent >= 1 ? outerR : innerR,
6162
+ borderTopRightRadius: endPercent >= 1 ? outerR : innerR
6163
+ }
6164
+ }
6165
+ ),
6166
+ /* @__PURE__ */ jsxRuntime.jsx(
6167
+ "div",
6168
+ {
6169
+ "aria-hidden": "true",
6170
+ style: {
6171
+ position: "absolute",
6172
+ bottom: trailingBottom,
6173
+ left: "50%",
6174
+ transform: "translateX(-50%)",
6175
+ height: trailingHeight,
6176
+ width: size,
6177
+ backgroundColor: inactiveTrack,
6178
+ opacity: disabled ? 0.38 : 1,
6179
+ borderTopLeftRadius: outerR,
6180
+ borderTopRightRadius: outerR,
6181
+ borderBottomLeftRadius: innerR,
6182
+ borderBottomRightRadius: innerR
6183
+ }
6184
+ }
6185
+ ),
6186
+ ticks.map((tick) => {
6187
+ const tickPct = (tick - min) / (max - min);
6188
+ const isActive = tickPct > startPercent && tickPct < endPercent;
6189
+ return /* @__PURE__ */ jsxRuntime.jsx(
6190
+ "div",
6191
+ {
6192
+ "aria-hidden": "true",
6193
+ style: {
6194
+ position: "absolute",
6195
+ width: tickSize,
6196
+ height: tickSize,
6197
+ borderRadius: "50%",
6198
+ backgroundColor: disabled ? SliderColors.disabledTick : isActive ? `var(--md-sys-color-${variant}-container)` : `var(--md-sys-color-${variant})`,
6199
+ opacity: disabled ? 0.38 : 1,
6200
+ bottom: `calc(${trackInset}px + ${tickPct} * (100% - ${trackInset * 2}px) - ${tickSize / 2}px)`,
6201
+ left: "50%",
6202
+ transform: "translateX(-50%)"
6203
+ }
6204
+ },
6205
+ tick
6206
+ );
6207
+ })
6208
+ ]
6209
+ }
6210
+ );
6211
+ });
6212
+ var RangeSliderComponent = React25__namespace.forwardRef(
6213
+ ({
6214
+ value: controlledValue,
6215
+ defaultValue,
6216
+ onValueChange,
6217
+ onValueChangeEnd,
6218
+ min = 0,
6219
+ max = 100,
6220
+ step = 0,
6221
+ orientation = "horizontal",
6222
+ trackSize = "m",
6223
+ trackShape = "md3",
6224
+ variant = "primary",
6225
+ disabled = false,
6226
+ showValueIndicator = false,
6227
+ showTicks = false,
6228
+ formatValue,
6229
+ className,
6230
+ "aria-label": ariaLabel
6231
+ }, ref) => {
6232
+ var _a, _b;
6233
+ const isHorizontal = orientation === "horizontal";
6234
+ const defaultStart = (_a = defaultValue == null ? void 0 : defaultValue[0]) != null ? _a : min;
6235
+ const defaultEnd = (_b = defaultValue == null ? void 0 : defaultValue[1]) != null ? _b : max;
6236
+ const [internalValue, setInternalValue] = React25__namespace.useState([
6237
+ defaultStart,
6238
+ defaultEnd
6239
+ ]);
6240
+ const resolvedValue = controlledValue !== void 0 ? controlledValue : internalValue;
6241
+ const { coerce, snap, toPercent, ticks } = useSliderMath({
6242
+ min,
6243
+ max,
6244
+ step
6245
+ });
6246
+ const startValue = snap(coerce(resolvedValue[0]));
6247
+ const endValue = snap(coerce(resolvedValue[1]));
6248
+ const startPercent = toPercent(startValue);
6249
+ const endPercent = toPercent(endValue);
6250
+ const [topThumb, setTopThumb] = React25__namespace.useState("end");
6251
+ const trackRef = React25__namespace.useRef(null);
6252
+ const minGap = step > 0 ? step : (max - min) / 1e3;
6253
+ const handleStartChange = React25__namespace.useCallback(
6254
+ (newStart) => {
6255
+ setTopThumb("start");
6256
+ const clamped = Math.min(newStart, endValue - minGap);
6257
+ const final = snap(coerce(clamped));
6258
+ if (controlledValue === void 0) {
6259
+ setInternalValue([final, endValue]);
6260
+ }
6261
+ onValueChange == null ? void 0 : onValueChange([final, endValue]);
6262
+ },
6263
+ [controlledValue, coerce, endValue, minGap, onValueChange, snap]
6264
+ );
6265
+ const handleEndChange = React25__namespace.useCallback(
6266
+ (newEnd) => {
6267
+ setTopThumb("end");
6268
+ const clamped = Math.max(newEnd, startValue + minGap);
6269
+ const final = snap(coerce(clamped));
6270
+ if (controlledValue === void 0) {
6271
+ setInternalValue([startValue, final]);
6272
+ }
6273
+ onValueChange == null ? void 0 : onValueChange([startValue, final]);
6274
+ },
6275
+ [controlledValue, coerce, minGap, onValueChange, snap, startValue]
6276
+ );
6277
+ const handleStartChangeEnd = React25__namespace.useCallback(
6278
+ (v) => onValueChangeEnd == null ? void 0 : onValueChangeEnd([v, endValue]),
6279
+ [endValue, onValueChangeEnd]
6280
+ );
6281
+ const handleEndChangeEnd = React25__namespace.useCallback(
6282
+ (v) => onValueChangeEnd == null ? void 0 : onValueChangeEnd([startValue, v]),
6283
+ [onValueChangeEnd, startValue]
6284
+ );
6285
+ const handleTrackPointerDown = React25__namespace.useCallback(
6286
+ (e) => {
6287
+ if (disabled) return;
6288
+ const trackEl = trackRef.current;
6289
+ if (!trackEl) return;
6290
+ const rect = trackEl.getBoundingClientRect();
6291
+ let clickPercent;
6292
+ const insetLimit = SliderTokens.thumbGap + SliderTokens.thumbWidthDefault / 2;
6293
+ const trackInset = Math.min(SliderTokens.trackSizes[trackSize] / 2, insetLimit);
6294
+ if (isHorizontal) {
6295
+ const x = e.clientX - rect.left;
6296
+ clickPercent = (x - trackInset) / (rect.width - trackInset * 2);
6297
+ } else {
6298
+ const y = rect.bottom - e.clientY;
6299
+ clickPercent = (y - trackInset) / (rect.height - trackInset * 2);
6300
+ }
6301
+ const clamped = Math.max(0, Math.min(1, clickPercent));
6302
+ const rawValue = min + clamped * (max - min);
6303
+ const clickValue = snap(coerce(rawValue));
6304
+ const distStart = Math.abs(clickValue - startValue);
6305
+ const distEnd = Math.abs(clickValue - endValue);
6306
+ if (distStart <= distEnd) {
6307
+ handleStartChange(clickValue);
6308
+ } else {
6309
+ handleEndChange(clickValue);
6310
+ }
6311
+ },
6312
+ [
6313
+ coerce,
6314
+ disabled,
6315
+ endValue,
6316
+ handleEndChange,
6317
+ handleStartChange,
6318
+ isHorizontal,
6319
+ max,
6320
+ min,
6321
+ snap,
6322
+ startValue,
6323
+ trackSize
6324
+ ]
6325
+ );
6326
+ const id = React25__namespace.useId();
6327
+ return /* @__PURE__ */ jsxRuntime.jsx(react.LazyMotion, { features: react.domMax, strict: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
6328
+ "div",
6329
+ {
6330
+ ref,
6331
+ className: cn(
6332
+ "relative flex items-center",
6333
+ isHorizontal ? "w-full flex-row" : "h-full flex-col",
6334
+ disabled && "pointer-events-none",
6335
+ className
6336
+ ),
6337
+ style: isHorizontal ? { minWidth: 0 } : { minHeight: 0 },
6338
+ children: [
6339
+ /* @__PURE__ */ jsxRuntime.jsx(
6340
+ RangeTrack,
6341
+ {
6342
+ startPercent,
6343
+ endPercent,
6344
+ trackSize,
6345
+ trackShape,
6346
+ orientation,
6347
+ variant,
6348
+ disabled,
6349
+ ticks: showTicks ? ticks : [],
6350
+ min,
6351
+ max,
6352
+ trackRef,
6353
+ onTrackPointerDown: handleTrackPointerDown
6354
+ }
6355
+ ),
6356
+ /* @__PURE__ */ jsxRuntime.jsx(
6357
+ SliderThumb,
6358
+ {
6359
+ value: startValue,
6360
+ percent: startPercent,
6361
+ min,
6362
+ max,
6363
+ step,
6364
+ disabled,
6365
+ orientation,
6366
+ trackSize,
6367
+ variant,
6368
+ showValueIndicator,
6369
+ trackRef,
6370
+ onValueChange: handleStartChange,
6371
+ onValueChangeEnd: handleStartChangeEnd,
6372
+ formatValue,
6373
+ thumbId: `${id}-start`,
6374
+ zIndex: topThumb === "start" ? 2 : 1,
6375
+ "aria-label": ariaLabel ? `${ariaLabel} start` : "Range start"
6376
+ }
6377
+ ),
6378
+ /* @__PURE__ */ jsxRuntime.jsx(
6379
+ SliderThumb,
6380
+ {
6381
+ value: endValue,
6382
+ percent: endPercent,
6383
+ min,
6384
+ max,
6385
+ step,
6386
+ disabled,
6387
+ orientation,
6388
+ trackSize,
6389
+ variant,
6390
+ showValueIndicator,
6391
+ trackRef,
6392
+ onValueChange: handleEndChange,
6393
+ onValueChangeEnd: handleEndChangeEnd,
6394
+ formatValue,
6395
+ thumbId: `${id}-end`,
6396
+ zIndex: topThumb === "end" ? 2 : 1,
6397
+ "aria-label": ariaLabel ? `${ariaLabel} end` : "Range end"
6398
+ }
6399
+ )
6400
+ ]
6401
+ }
6402
+ ) });
6403
+ }
6404
+ );
6405
+ RangeSliderComponent.displayName = "RangeSlider";
6406
+ var RangeSlider = React25__namespace.memo(RangeSliderComponent);
6407
+ function getHorizontalRadius(isLeading, innerR, outerR) {
6408
+ if (isLeading) {
6409
+ return {
6410
+ borderTopLeftRadius: outerR,
6411
+ borderBottomLeftRadius: outerR,
6412
+ borderTopRightRadius: innerR,
6413
+ borderBottomRightRadius: innerR
6414
+ };
6415
+ }
6416
+ return {
6417
+ borderTopLeftRadius: innerR,
6418
+ borderBottomLeftRadius: innerR,
6419
+ borderTopRightRadius: outerR,
6420
+ borderBottomRightRadius: outerR
6421
+ };
6422
+ }
6423
+ function getVerticalRadius(isLeading, innerR, outerR) {
6424
+ if (isLeading) {
6425
+ return {
6426
+ borderBottomLeftRadius: outerR,
6427
+ borderBottomRightRadius: outerR,
6428
+ borderTopLeftRadius: innerR,
6429
+ borderTopRightRadius: innerR
6430
+ };
6431
+ }
6432
+ return {
6433
+ borderTopLeftRadius: outerR,
6434
+ borderTopRightRadius: outerR,
6435
+ borderBottomLeftRadius: innerR,
6436
+ borderBottomRightRadius: innerR
6437
+ };
6438
+ }
6439
+ var allInnerRadius = (innerR) => ({
6440
+ borderTopLeftRadius: innerR,
6441
+ borderBottomLeftRadius: innerR,
6442
+ borderTopRightRadius: innerR,
6443
+ borderBottomRightRadius: innerR
6444
+ });
6445
+ var InsetIcon = React25__namespace.memo(function InsetIcon2({
6446
+ icon,
6447
+ isOnActiveSegment,
6448
+ position,
6449
+ orientation,
6450
+ trackSize,
6451
+ trackSizeToken,
6452
+ disabled,
6453
+ variant,
6454
+ prefersReduced
6455
+ }) {
6456
+ const iconSize = Math.min(
6457
+ SliderTokens.insetIconSizes[trackSizeToken],
6458
+ Math.max(4, trackSize - SliderTokens.insetIconPadding * 2)
6459
+ );
6460
+ const activeColor = `var(--md-sys-color-on-${variant})`;
6461
+ const inactiveColor = `var(--md-sys-color-${variant})`;
6462
+ const isHorizontal = orientation === "horizontal";
6463
+ const fastFade = prefersReduced ? { duration: 0 } : { duration: 0.12 };
6464
+ return /* @__PURE__ */ jsxRuntime.jsx(
6465
+ react.m.div,
6466
+ {
6467
+ "aria-hidden": "true",
6468
+ className: "[&_svg]:w-full [&_svg]:h-full",
6469
+ initial: __spreadValues({
6470
+ opacity: 0
6471
+ }, isHorizontal ? { left: position } : { bottom: position }),
6472
+ animate: {
6473
+ [isHorizontal ? "left" : "bottom"]: position,
6474
+ opacity: disabled ? 0.38 : 1,
6475
+ color: isOnActiveSegment ? activeColor : inactiveColor
6476
+ },
6477
+ exit: { opacity: 0, transition: fastFade },
6478
+ transition: prefersReduced ? { duration: 0 } : {
6479
+ left: { type: "spring", stiffness: 500, damping: 40 },
6480
+ bottom: { type: "spring", stiffness: 500, damping: 40 },
6481
+ opacity: fastFade,
6482
+ color: fastFade
6483
+ },
6484
+ style: __spreadValues({
6485
+ position: "absolute",
6486
+ width: iconSize,
6487
+ height: iconSize,
6488
+ display: "flex",
6489
+ alignItems: "center",
6490
+ justifyContent: "center",
6491
+ pointerEvents: "none",
6492
+ zIndex: 1,
6493
+ willChange: isHorizontal ? "left" : "bottom"
6494
+ }, isHorizontal ? { top: "50%", transform: "translateY(-50%)" } : { left: "50%", transform: "translateX(-50%)" }),
6495
+ children: icon
6496
+ }
6497
+ );
6498
+ });
6499
+ function Ticks({
6500
+ ticks,
6501
+ min,
6502
+ max,
6503
+ percent,
6504
+ orientation,
6505
+ variant,
6506
+ isCentered,
6507
+ disabled,
6508
+ trackInset
6509
+ }) {
6510
+ if (ticks.length === 0) return null;
6511
+ const { thumbGap, thumbWidthDefault, tickSize } = SliderTokens;
6512
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: ticks.map((tick) => {
6513
+ const tickPercent = (tick - min) / (max - min);
6514
+ const isOnActive = isCentered ? percent >= 0.5 ? tickPercent >= 0.5 && tickPercent <= percent : tickPercent <= 0.5 && tickPercent >= percent : tickPercent <= percent;
6515
+ const thumbStart = percent - (thumbGap + thumbWidthDefault / 2) / 100;
6516
+ const thumbEnd = percent + (thumbGap + thumbWidthDefault / 2) / 100;
6517
+ if (tickPercent > thumbStart && tickPercent < thumbEnd) return null;
6518
+ const color = disabled ? SliderColors.disabledTick : isOnActive ? `var(--md-sys-color-${variant}-container)` : `var(--md-sys-color-${variant})`;
6519
+ const style = __spreadValues({
6520
+ position: "absolute",
6521
+ width: tickSize,
6522
+ height: tickSize,
6523
+ borderRadius: "50%",
6524
+ backgroundColor: color,
6525
+ opacity: disabled ? 0.38 : 1
6526
+ }, orientation === "horizontal" ? {
6527
+ left: `calc(${trackInset}px + ${tickPercent} * (100% - ${trackInset * 2}px) - ${tickSize / 2}px)`,
6528
+ top: "50%",
6529
+ transform: "translateY(-50%)"
6530
+ } : {
6531
+ // Vertical: bottom=0%, top=100% (inverted Y-axis)
6532
+ bottom: `calc(${trackInset}px + ${tickPercent} * (100% - ${trackInset * 2}px) - ${tickSize / 2}px)`,
6533
+ left: "50%",
6534
+ transform: "translateX(-50%)"
6535
+ });
6536
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style, "aria-hidden": "true" }, tick);
6537
+ }) });
6538
+ }
6539
+ var SliderTrack = React25__namespace.memo(function SliderTrack2({
6540
+ percent,
6541
+ trackSize,
6542
+ orientation,
6543
+ variant,
6544
+ isCentered,
6545
+ min,
6546
+ max,
6547
+ disabled,
6548
+ trackRef,
6549
+ onTrackPointerDown,
6550
+ ticks = [],
6551
+ insetIcon,
6552
+ insetIconAtMin,
6553
+ insetIconTrailing,
6554
+ insetIconAtMax,
6555
+ value,
6556
+ trackShape = "md3"
6557
+ }) {
6558
+ var _a;
6559
+ const isHorizontal = orientation === "horizontal";
6560
+ const size = SliderTokens.trackSizes[trackSize];
6561
+ const thumbHeight = SliderTokens.thumbHeights[trackSize];
6562
+ const { thumbGap, thumbWidthDefault, trackInnerRadius } = SliderTokens;
6563
+ const innerR = trackInnerRadius;
6564
+ let outerR = size / 2;
6565
+ if (trackShape === "md3") {
6566
+ outerR = Math.min(SliderTokens.trackShapes[trackSize], size / 2);
6567
+ } else if (typeof trackShape === "number") {
6568
+ outerR = Math.min(trackShape, size / 2);
6569
+ }
6570
+ const thumbHalfWidth = thumbWidthDefault / 2;
6571
+ const gapWithThumbStr = `${thumbGap + thumbHalfWidth}px`;
6572
+ const hasAnyInsetIcon = Boolean(insetIcon || insetIconTrailing);
6573
+ const prefersReduced = (_a = react.useReducedMotion()) != null ? _a : false;
6574
+ const [trackWidth, setTrackWidth] = React25__namespace.useState(0);
6575
+ React25__namespace.useLayoutEffect(() => {
6576
+ const el = trackRef.current;
6577
+ if (!el || !hasAnyInsetIcon) return;
6578
+ setTrackWidth(isHorizontal ? el.clientWidth : el.clientHeight);
6579
+ const ro = new ResizeObserver(() => {
6580
+ setTrackWidth(isHorizontal ? el.clientWidth : el.clientHeight);
6581
+ });
6582
+ ro.observe(el);
6583
+ return () => ro.disconnect();
6584
+ }, [hasAnyInsetIcon, isHorizontal, trackRef]);
6585
+ const activeIconSize = Math.min(
6586
+ SliderTokens.insetIconSizes[trackSize],
6587
+ Math.max(4, size - SliderTokens.insetIconPadding * 2)
6588
+ );
6589
+ const iconTotalWidth = activeIconSize + SliderTokens.insetIconPadding * 2 + thumbGap + thumbHalfWidth;
6590
+ const iconThreshold = trackWidth > 0 ? iconTotalWidth / trackWidth : 0.15;
6591
+ const HYSTERESIS_GAP = 0.04;
6592
+ const trailingActiveRef = React25__namespace.useRef(1 - percent <= iconThreshold);
6593
+ const leadingActiveRef = React25__namespace.useRef(percent > iconThreshold);
6594
+ const trailingPercent = 1 - percent;
6595
+ if (trailingActiveRef.current) {
6596
+ if (trailingPercent > iconThreshold + HYSTERESIS_GAP) {
6597
+ trailingActiveRef.current = false;
6598
+ }
6599
+ } else {
6600
+ if (trailingPercent <= iconThreshold) {
6601
+ trailingActiveRef.current = true;
6602
+ }
6603
+ }
6604
+ const trailingOnActive = trailingActiveRef.current;
6605
+ if (leadingActiveRef.current) {
6606
+ if (percent <= iconThreshold - HYSTERESIS_GAP) {
6607
+ leadingActiveRef.current = false;
6608
+ }
6609
+ } else {
6610
+ if (percent > iconThreshold) {
6611
+ leadingActiveRef.current = true;
6612
+ }
6613
+ }
6614
+ const leadingOnActive = leadingActiveRef.current;
6615
+ const isAtMin = value !== void 0 && value <= min;
6616
+ const resolvedLeadingIcon = isAtMin && insetIconAtMin ? insetIconAtMin : insetIcon;
6617
+ const isAtMax = value !== void 0 && value >= max;
6618
+ const resolvedTrailingIcon = isAtMax && insetIconAtMax ? insetIconAtMax : insetIconTrailing;
6619
+ const activeColor = disabled ? SliderColors.disabledActiveTrack : `var(--md-sys-color-${variant})`;
6620
+ const inactiveColor = disabled ? SliderColors.disabledInactiveTrack : `var(--md-sys-color-${variant}-container)`;
6621
+ const insetLimit = SliderTokens.thumbGap + SliderTokens.thumbWidthDefault / 2;
6622
+ const trackInset = Math.min(size / 2, insetLimit);
6623
+ const gapTotal = thumbGap + thumbHalfWidth;
6624
+ const thumbCenter = `calc(${trackInset}px + ${percent} * (100% - ${trackInset * 2}px))`;
6625
+ const leadingActiveLeft = `${trackInset + SliderTokens.insetIconPadding}px`;
6626
+ const leadingInactiveLeft = `calc(${thumbCenter} + ${gapTotal}px + ${SliderTokens.insetIconPadding}px)`;
6627
+ const trailingInactiveLeft = `calc(100% - ${trackInset}px - ${activeIconSize}px - ${SliderTokens.insetIconPadding}px)`;
6628
+ const trailingActiveLeft = `calc(${thumbCenter} - ${gapTotal}px - ${activeIconSize}px - ${SliderTokens.insetIconPadding}px)`;
6629
+ if (isHorizontal) {
6630
+ const cxStr = `calc(${trackInset}px + ${percent} * (100% - ${trackInset * 2}px))`;
6631
+ const segments2 = [];
6632
+ if (!isCentered) {
6633
+ const leftSegmentWidth = `max(0px, calc(${cxStr} - ${gapWithThumbStr}))`;
6634
+ const rightSegmentLeft = `calc(${cxStr} + ${gapWithThumbStr})`;
6635
+ const rightSegmentWidth = `max(0px, calc(100% - (${cxStr} + ${gapWithThumbStr})))`;
6636
+ segments2.push(
6637
+ /* @__PURE__ */ jsxRuntime.jsx(
6638
+ "div",
6639
+ {
6640
+ "aria-hidden": "true",
6641
+ style: __spreadValues({
6642
+ position: "absolute",
6643
+ left: 0,
6644
+ top: "50%",
6645
+ transform: "translateY(-50%)",
6646
+ width: leftSegmentWidth,
6647
+ height: size,
6648
+ backgroundColor: activeColor,
6649
+ opacity: disabled ? 0.38 : 1
6650
+ }, getHorizontalRadius(true, innerR, outerR))
6651
+ },
6652
+ "left"
6653
+ )
6654
+ );
6655
+ segments2.push(
6656
+ /* @__PURE__ */ jsxRuntime.jsx(
6657
+ "div",
6658
+ {
6659
+ "aria-hidden": "true",
6660
+ style: __spreadValues({
6661
+ position: "absolute",
6662
+ left: rightSegmentLeft,
6663
+ top: "50%",
6664
+ transform: "translateY(-50%)",
6665
+ width: rightSegmentWidth,
6666
+ height: size,
6667
+ backgroundColor: inactiveColor,
6668
+ opacity: disabled ? 0.38 : 1
6669
+ }, getHorizontalRadius(false, innerR, outerR))
6670
+ },
6671
+ "right"
6672
+ )
6673
+ );
6674
+ } else {
6675
+ const halfCenterGap = SliderTokens.thumbGap / 2;
6676
+ if (percent >= 0.5) {
6677
+ const leftBaseWidth = `max(0px, min(calc(50% - ${halfCenterGap}px), calc(${cxStr} - ${gapWithThumbStr})))`;
6678
+ segments2.push(
6679
+ /* @__PURE__ */ jsxRuntime.jsx(
6680
+ "div",
6681
+ {
6682
+ "aria-hidden": "true",
6683
+ style: __spreadValues({
6684
+ position: "absolute",
6685
+ left: 0,
6686
+ top: "50%",
6687
+ transform: "translateY(-50%)",
6688
+ width: leftBaseWidth,
6689
+ height: size,
6690
+ backgroundColor: inactiveColor,
6691
+ opacity: disabled ? 0.38 : 1
6692
+ }, getHorizontalRadius(true, innerR, outerR))
6693
+ },
6694
+ "left-base"
6695
+ )
6696
+ );
6697
+ const centerActiveLeft = `calc(50% + ${halfCenterGap}px)`;
6698
+ const centerActiveWidth = `max(0px, calc(${cxStr} - ${gapWithThumbStr} - (50% + ${halfCenterGap}px)))`;
6699
+ segments2.push(
6700
+ /* @__PURE__ */ jsxRuntime.jsx(
6701
+ "div",
6702
+ {
6703
+ "aria-hidden": "true",
6704
+ style: __spreadValues({
6705
+ position: "absolute",
6706
+ left: centerActiveLeft,
6707
+ top: "50%",
6708
+ transform: "translateY(-50%)",
6709
+ width: centerActiveWidth,
6710
+ height: size,
6711
+ backgroundColor: activeColor,
6712
+ opacity: disabled ? 0.38 : 1
6713
+ }, allInnerRadius(innerR))
6714
+ },
6715
+ "center-active"
6716
+ )
6717
+ );
6718
+ const rightBaseLeft = `calc(${cxStr} + ${gapWithThumbStr})`;
6719
+ const rightBaseWidth = `max(0px, calc(100% - (${cxStr} + ${gapWithThumbStr})))`;
6720
+ segments2.push(
6721
+ /* @__PURE__ */ jsxRuntime.jsx(
6722
+ "div",
6723
+ {
6724
+ "aria-hidden": "true",
6725
+ style: __spreadValues({
6726
+ position: "absolute",
6727
+ left: rightBaseLeft,
6728
+ top: "50%",
6729
+ transform: "translateY(-50%)",
6730
+ width: rightBaseWidth,
6731
+ height: size,
6732
+ backgroundColor: inactiveColor,
6733
+ opacity: disabled ? 0.38 : 1
6734
+ }, getHorizontalRadius(false, innerR, outerR))
6735
+ },
6736
+ "right-base"
6737
+ )
6738
+ );
6739
+ } else {
6740
+ const leftBaseWidth = `max(0px, calc(${cxStr} - ${gapWithThumbStr}))`;
6741
+ segments2.push(
6742
+ /* @__PURE__ */ jsxRuntime.jsx(
6743
+ "div",
6744
+ {
6745
+ "aria-hidden": "true",
6746
+ style: __spreadValues({
6747
+ position: "absolute",
6748
+ left: 0,
6749
+ top: "50%",
6750
+ transform: "translateY(-50%)",
6751
+ width: leftBaseWidth,
6752
+ height: size,
6753
+ backgroundColor: inactiveColor,
6754
+ opacity: disabled ? 0.38 : 1
6755
+ }, getHorizontalRadius(true, innerR, outerR))
6756
+ },
6757
+ "left-base"
6758
+ )
6759
+ );
6760
+ const centerActiveLeft = `calc(${cxStr} + ${gapWithThumbStr})`;
6761
+ const centerActiveWidth = `max(0px, calc(50% - ${halfCenterGap}px - (${cxStr} + ${gapWithThumbStr})))`;
6762
+ segments2.push(
6763
+ /* @__PURE__ */ jsxRuntime.jsx(
6764
+ "div",
6765
+ {
6766
+ "aria-hidden": "true",
6767
+ style: __spreadValues({
6768
+ position: "absolute",
6769
+ left: centerActiveLeft,
6770
+ top: "50%",
6771
+ transform: "translateY(-50%)",
6772
+ width: centerActiveWidth,
6773
+ height: size,
6774
+ backgroundColor: activeColor,
6775
+ opacity: disabled ? 0.38 : 1
6776
+ }, allInnerRadius(innerR))
6777
+ },
6778
+ "center-active"
6779
+ )
6780
+ );
6781
+ const rightBaseLeft = `max(calc(50% + ${halfCenterGap}px), calc(${cxStr} + ${gapWithThumbStr}))`;
6782
+ const rightBaseWidth = `max(0px, calc(100% - max(calc(50% + ${halfCenterGap}px), calc(${cxStr} + ${gapWithThumbStr}))))`;
6783
+ segments2.push(
6784
+ /* @__PURE__ */ jsxRuntime.jsx(
6785
+ "div",
6786
+ {
6787
+ "aria-hidden": "true",
6788
+ style: __spreadValues({
6789
+ position: "absolute",
6790
+ left: rightBaseLeft,
6791
+ top: "50%",
6792
+ transform: "translateY(-50%)",
6793
+ width: rightBaseWidth,
6794
+ height: size,
6795
+ backgroundColor: inactiveColor,
6796
+ opacity: disabled ? 0.38 : 1
6797
+ }, getHorizontalRadius(false, innerR, outerR))
6798
+ },
6799
+ "right-base"
6800
+ )
6801
+ );
6802
+ }
6803
+ }
6804
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6805
+ "div",
6806
+ {
6807
+ ref: trackRef,
6808
+ className: cn(
6809
+ "relative w-full",
6810
+ disabled ? "cursor-not-allowed" : "cursor-pointer"
6811
+ ),
6812
+ style: { height: thumbHeight },
6813
+ onPointerDown: onTrackPointerDown,
6814
+ "aria-hidden": "true",
6815
+ children: [
6816
+ segments2,
6817
+ ticks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
6818
+ Ticks,
6819
+ {
6820
+ ticks,
6821
+ min,
6822
+ max,
6823
+ percent,
6824
+ orientation,
6825
+ disabled,
6826
+ variant,
6827
+ isCentered,
6828
+ trackInset
6829
+ }
6830
+ ),
6831
+ /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { mode: "wait", children: resolvedLeadingIcon && /* @__PURE__ */ jsxRuntime.jsx(
6832
+ InsetIcon,
6833
+ {
6834
+ icon: resolvedLeadingIcon,
6835
+ isOnActiveSegment: leadingOnActive,
6836
+ position: leadingOnActive ? leadingActiveLeft : leadingInactiveLeft,
6837
+ orientation,
6838
+ trackSize: size,
6839
+ trackSizeToken: trackSize,
6840
+ disabled,
6841
+ variant,
6842
+ prefersReduced
6843
+ },
6844
+ isAtMin ? "lead-min" : leadingOnActive ? "lead-active" : "lead-inactive"
6845
+ ) }),
6846
+ /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { mode: "wait", children: resolvedTrailingIcon && /* @__PURE__ */ jsxRuntime.jsx(
6847
+ InsetIcon,
6848
+ {
6849
+ icon: resolvedTrailingIcon,
6850
+ isOnActiveSegment: trailingOnActive,
6851
+ position: trailingOnActive ? trailingActiveLeft : trailingInactiveLeft,
6852
+ orientation,
6853
+ trackSize: size,
6854
+ trackSizeToken: trackSize,
6855
+ disabled,
6856
+ variant,
6857
+ prefersReduced
6858
+ },
6859
+ isAtMax ? "trail-max" : trailingOnActive ? "trail-active" : "trail-inactive"
6860
+ ) })
6861
+ ]
6862
+ }
6863
+ );
6864
+ }
6865
+ const cyStr = `calc(${trackInset}px + ${percent} * (100% - ${trackInset * 2}px))`;
6866
+ const segments = [];
6867
+ if (!isCentered) {
6868
+ const bottomSegmentHeight = `max(0px, calc(${cyStr} - ${gapWithThumbStr}))`;
6869
+ const topSegmentBottom = `calc(${cyStr} + ${gapWithThumbStr})`;
6870
+ const topSegmentHeight = `max(0px, calc(100% - (${cyStr} + ${gapWithThumbStr})))`;
6871
+ segments.push(
6872
+ /* @__PURE__ */ jsxRuntime.jsx(
6873
+ "div",
6874
+ {
6875
+ "aria-hidden": "true",
6876
+ style: __spreadValues({
6877
+ position: "absolute",
6878
+ bottom: 0,
6879
+ left: "50%",
6880
+ transform: "translateX(-50%)",
6881
+ height: bottomSegmentHeight,
6882
+ width: size,
6883
+ backgroundColor: activeColor,
6884
+ opacity: disabled ? 0.38 : 1
6885
+ }, getVerticalRadius(true, innerR, outerR))
6886
+ },
6887
+ "bottom"
6888
+ )
6889
+ );
6890
+ segments.push(
6891
+ /* @__PURE__ */ jsxRuntime.jsx(
6892
+ "div",
6893
+ {
6894
+ "aria-hidden": "true",
6895
+ style: __spreadValues({
6896
+ position: "absolute",
6897
+ bottom: topSegmentBottom,
6898
+ left: "50%",
6899
+ transform: "translateX(-50%)",
6900
+ height: topSegmentHeight,
6901
+ width: size,
6902
+ backgroundColor: inactiveColor,
6903
+ opacity: disabled ? 0.38 : 1
6904
+ }, getVerticalRadius(false, innerR, outerR))
6905
+ },
6906
+ "top"
6907
+ )
6908
+ );
6909
+ } else {
6910
+ const halfCenterGap = SliderTokens.thumbGap / 2;
6911
+ if (percent >= 0.5) {
6912
+ const bottomBaseHeight = `max(0px, min(calc(50% - ${halfCenterGap}px), calc(${cyStr} - ${gapWithThumbStr})))`;
6913
+ segments.push(
6914
+ /* @__PURE__ */ jsxRuntime.jsx(
6915
+ "div",
6916
+ {
6917
+ "aria-hidden": "true",
6918
+ style: __spreadValues({
6919
+ position: "absolute",
6920
+ bottom: 0,
6921
+ left: "50%",
6922
+ transform: "translateX(-50%)",
6923
+ height: bottomBaseHeight,
6924
+ width: size,
6925
+ backgroundColor: inactiveColor,
6926
+ opacity: disabled ? 0.38 : 1
6927
+ }, getVerticalRadius(true, innerR, outerR))
6928
+ },
6929
+ "bottom-base"
6930
+ )
6931
+ );
6932
+ const centerActiveBottom = `calc(50% + ${halfCenterGap}px)`;
6933
+ const centerActiveHeight = `max(0px, calc(${cyStr} - ${gapWithThumbStr} - (50% + ${halfCenterGap}px)))`;
6934
+ segments.push(
6935
+ /* @__PURE__ */ jsxRuntime.jsx(
6936
+ "div",
6937
+ {
6938
+ "aria-hidden": "true",
6939
+ style: __spreadValues({
6940
+ position: "absolute",
6941
+ bottom: centerActiveBottom,
6942
+ left: "50%",
6943
+ transform: "translateX(-50%)",
6944
+ height: centerActiveHeight,
6945
+ width: size,
6946
+ backgroundColor: activeColor,
6947
+ opacity: disabled ? 0.38 : 1
6948
+ }, allInnerRadius(innerR))
6949
+ },
6950
+ "center-active"
6951
+ )
6952
+ );
6953
+ const topBaseBottom = `calc(${cyStr} + ${gapWithThumbStr})`;
6954
+ const topBaseHeight = `max(0px, calc(100% - (${cyStr} + ${gapWithThumbStr})))`;
6955
+ segments.push(
6956
+ /* @__PURE__ */ jsxRuntime.jsx(
6957
+ "div",
6958
+ {
6959
+ "aria-hidden": "true",
6960
+ style: __spreadValues({
6961
+ position: "absolute",
6962
+ bottom: topBaseBottom,
6963
+ left: "50%",
6964
+ transform: "translateX(-50%)",
6965
+ height: topBaseHeight,
6966
+ width: size,
6967
+ backgroundColor: inactiveColor,
6968
+ opacity: disabled ? 0.38 : 1
6969
+ }, getVerticalRadius(false, innerR, outerR))
6970
+ },
6971
+ "top-base"
6972
+ )
6973
+ );
6974
+ } else {
6975
+ const bottomBaseHeight = `max(0px, calc(${cyStr} - ${gapWithThumbStr}))`;
6976
+ segments.push(
6977
+ /* @__PURE__ */ jsxRuntime.jsx(
6978
+ "div",
6979
+ {
6980
+ "aria-hidden": "true",
6981
+ style: __spreadValues({
6982
+ position: "absolute",
6983
+ bottom: 0,
6984
+ left: "50%",
6985
+ transform: "translateX(-50%)",
6986
+ height: bottomBaseHeight,
6987
+ width: size,
6988
+ backgroundColor: inactiveColor,
6989
+ opacity: disabled ? 0.38 : 1
6990
+ }, getVerticalRadius(true, innerR, outerR))
6991
+ },
6992
+ "bottom-base"
6993
+ )
6994
+ );
6995
+ const centerActiveBottom = `calc(${cyStr} + ${gapWithThumbStr})`;
6996
+ const centerActiveHeight = `max(0px, calc(50% - ${halfCenterGap}px - (${cyStr} + ${gapWithThumbStr})))`;
6997
+ segments.push(
6998
+ /* @__PURE__ */ jsxRuntime.jsx(
6999
+ "div",
7000
+ {
7001
+ "aria-hidden": "true",
7002
+ style: __spreadValues({
7003
+ position: "absolute",
7004
+ bottom: centerActiveBottom,
7005
+ left: "50%",
7006
+ transform: "translateX(-50%)",
7007
+ height: centerActiveHeight,
7008
+ width: size,
7009
+ backgroundColor: activeColor,
7010
+ opacity: disabled ? 0.38 : 1
7011
+ }, allInnerRadius(innerR))
7012
+ },
7013
+ "center-active"
7014
+ )
7015
+ );
7016
+ const topBaseBottom = `max(calc(50% + ${halfCenterGap}px), calc(${cyStr} + ${gapWithThumbStr}))`;
7017
+ const topBaseHeight = `max(0px, calc(100% - max(calc(50% + ${halfCenterGap}px), calc(${cyStr} + ${gapWithThumbStr}))))`;
7018
+ segments.push(
7019
+ /* @__PURE__ */ jsxRuntime.jsx(
7020
+ "div",
7021
+ {
7022
+ "aria-hidden": "true",
7023
+ style: __spreadValues({
7024
+ position: "absolute",
7025
+ bottom: topBaseBottom,
7026
+ left: "50%",
7027
+ transform: "translateX(-50%)",
7028
+ height: topBaseHeight,
7029
+ width: size,
7030
+ backgroundColor: inactiveColor,
7031
+ opacity: disabled ? 0.38 : 1
7032
+ }, getVerticalRadius(false, innerR, outerR))
7033
+ },
7034
+ "top-base"
7035
+ )
7036
+ );
7037
+ }
7038
+ }
7039
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7040
+ "div",
7041
+ {
7042
+ ref: trackRef,
7043
+ className: cn(
7044
+ "relative h-full",
7045
+ disabled ? "cursor-not-allowed" : "cursor-pointer"
7046
+ ),
7047
+ style: { width: thumbHeight },
7048
+ onPointerDown: onTrackPointerDown,
7049
+ "aria-hidden": "true",
7050
+ children: [
7051
+ segments,
7052
+ ticks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
7053
+ Ticks,
7054
+ {
7055
+ ticks,
7056
+ min,
7057
+ max,
7058
+ percent,
7059
+ orientation,
7060
+ disabled,
7061
+ variant,
7062
+ isCentered,
7063
+ trackInset
7064
+ }
7065
+ ),
7066
+ /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { mode: "wait", children: resolvedLeadingIcon && /* @__PURE__ */ jsxRuntime.jsx(
7067
+ InsetIcon,
7068
+ {
7069
+ icon: resolvedLeadingIcon,
7070
+ isOnActiveSegment: leadingOnActive,
7071
+ position: leadingOnActive ? leadingActiveLeft : leadingInactiveLeft,
7072
+ orientation,
7073
+ trackSize: size,
7074
+ trackSizeToken: trackSize,
7075
+ disabled,
7076
+ variant,
7077
+ prefersReduced
7078
+ },
7079
+ isAtMin ? "lead-min" : leadingOnActive ? "lead-active" : "lead-inactive"
7080
+ ) }),
7081
+ /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { mode: "wait", children: resolvedTrailingIcon && /* @__PURE__ */ jsxRuntime.jsx(
7082
+ InsetIcon,
7083
+ {
7084
+ icon: resolvedTrailingIcon,
7085
+ isOnActiveSegment: trailingOnActive,
7086
+ position: trailingOnActive ? trailingActiveLeft : trailingInactiveLeft,
7087
+ orientation,
7088
+ trackSize: size,
7089
+ trackSizeToken: trackSize,
7090
+ disabled,
7091
+ variant,
7092
+ prefersReduced
7093
+ },
7094
+ isAtMax ? "trail-max" : trailingOnActive ? "trail-active" : "trail-inactive"
7095
+ ) })
7096
+ ]
7097
+ }
7098
+ );
7099
+ });
7100
+ var SliderComponent = React25__namespace.forwardRef(
7101
+ ({
7102
+ value: controlledValue,
7103
+ defaultValue,
7104
+ onValueChange,
7105
+ onValueChangeEnd,
7106
+ min = 0,
7107
+ max = 100,
7108
+ step = 0,
7109
+ orientation = "horizontal",
7110
+ trackSize = "m",
7111
+ trackShape = "md3",
7112
+ variant = "primary",
7113
+ isCentered = false,
7114
+ disabled = false,
7115
+ showValueIndicator = false,
7116
+ showTicks = false,
7117
+ insetIcon,
7118
+ insetIconAtMin,
7119
+ insetIconTrailing,
7120
+ insetIconAtMax,
7121
+ formatValue,
7122
+ className,
7123
+ "aria-label": ariaLabel,
7124
+ "aria-labelledby": ariaLabelledBy
7125
+ }, ref) => {
7126
+ const isHorizontal = orientation === "horizontal";
7127
+ const midpoint = min + (max - min) / 2;
7128
+ const initialValue = defaultValue != null ? defaultValue : midpoint;
7129
+ const [internalValue, setInternalValue] = React25__namespace.useState(initialValue);
7130
+ const resolvedValue = controlledValue !== void 0 ? controlledValue : internalValue;
7131
+ const { coerce, snap, toPercent, ticks } = useSliderMath({
7132
+ min,
7133
+ max,
7134
+ step
7135
+ });
7136
+ const safeValue = snap(coerce(resolvedValue));
7137
+ const percent = toPercent(safeValue);
7138
+ const trackRef = React25__namespace.useRef(null);
7139
+ const handleValueChange = React25__namespace.useCallback(
7140
+ (newValue) => {
7141
+ const clamped = snap(coerce(newValue));
7142
+ if (controlledValue === void 0) {
7143
+ setInternalValue(clamped);
7144
+ }
7145
+ onValueChange == null ? void 0 : onValueChange(clamped);
7146
+ },
7147
+ [coerce, controlledValue, onValueChange, snap]
7148
+ );
7149
+ const handleValueChangeEnd = React25__namespace.useCallback(
7150
+ (newValue) => {
7151
+ onValueChangeEnd == null ? void 0 : onValueChangeEnd(snap(coerce(newValue)));
7152
+ },
7153
+ [coerce, onValueChangeEnd, snap]
7154
+ );
7155
+ const handleTrackPointerDown = React25__namespace.useCallback(
7156
+ (e) => {
7157
+ if (disabled) return;
7158
+ const trackEl = trackRef.current;
7159
+ if (!trackEl) return;
7160
+ const rect = trackEl.getBoundingClientRect();
7161
+ let clickPercent;
7162
+ const insetLimit = SliderTokens.thumbGap + SliderTokens.thumbWidthDefault / 2;
7163
+ const trackInset = Math.min(SliderTokens.trackSizes[trackSize] / 2, insetLimit);
7164
+ if (isHorizontal) {
7165
+ const x = e.clientX - rect.left;
7166
+ clickPercent = (x - trackInset) / (rect.width - trackInset * 2);
7167
+ } else {
7168
+ const y = rect.bottom - e.clientY;
7169
+ clickPercent = (y - trackInset) / (rect.height - trackInset * 2);
7170
+ }
7171
+ const clamped = Math.max(0, Math.min(1, clickPercent));
7172
+ const rawValue = min + clamped * (max - min);
7173
+ const newValue = snap(coerce(rawValue));
7174
+ handleValueChange(newValue);
7175
+ },
7176
+ [
7177
+ coerce,
7178
+ disabled,
7179
+ handleValueChange,
7180
+ isHorizontal,
7181
+ max,
7182
+ min,
7183
+ snap,
7184
+ trackSize
7185
+ ]
7186
+ );
7187
+ const id = React25__namespace.useId();
7188
+ const thumbId = `slider-thumb-${id}`;
7189
+ const supportsInsetIcon = !isCentered && SliderTokens.trackSizes[trackSize] >= 40;
7190
+ const hasAnyInsetIcon = !!(insetIcon || insetIconTrailing);
7191
+ if (hasAnyInsetIcon && !supportsInsetIcon) {
7192
+ console.warn(
7193
+ "[Slider] insetIcon is only supported on track sizes >= 40dp (e.g. xl track sizes). See MD3 spec: https://m3.material.io/components/sliders/specs"
7194
+ );
7195
+ }
7196
+ return /* @__PURE__ */ jsxRuntime.jsx(react.LazyMotion, { features: react.domMax, strict: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
7197
+ "div",
7198
+ {
7199
+ ref,
7200
+ className: cn(
7201
+ "relative flex items-center",
7202
+ isHorizontal ? "w-full flex-row" : "h-full flex-col",
7203
+ disabled && "pointer-events-none",
7204
+ className
7205
+ ),
7206
+ style: isHorizontal ? { minWidth: 0 } : { minHeight: 0 },
7207
+ children: [
7208
+ /* @__PURE__ */ jsxRuntime.jsx(
7209
+ SliderTrack,
7210
+ {
7211
+ percent,
7212
+ trackSize,
7213
+ trackShape,
7214
+ orientation,
7215
+ isCentered,
7216
+ min,
7217
+ max,
7218
+ disabled,
7219
+ variant,
7220
+ trackRef,
7221
+ onTrackPointerDown: handleTrackPointerDown,
7222
+ ticks: showTicks ? ticks : [],
7223
+ insetIcon: supportsInsetIcon ? insetIcon : void 0,
7224
+ insetIconAtMin: supportsInsetIcon ? insetIconAtMin : void 0,
7225
+ insetIconTrailing: supportsInsetIcon ? insetIconTrailing : void 0,
7226
+ insetIconAtMax: supportsInsetIcon ? insetIconAtMax : void 0,
7227
+ value: safeValue
7228
+ }
7229
+ ),
7230
+ /* @__PURE__ */ jsxRuntime.jsx(
7231
+ SliderThumb,
7232
+ {
7233
+ value: safeValue,
7234
+ percent,
7235
+ min,
7236
+ max,
7237
+ step,
7238
+ disabled,
7239
+ orientation,
7240
+ trackSize,
7241
+ variant,
7242
+ showValueIndicator,
7243
+ trackRef,
7244
+ onValueChange: handleValueChange,
7245
+ onValueChangeEnd: handleValueChangeEnd,
7246
+ formatValue,
7247
+ thumbId,
7248
+ zIndex: 1,
7249
+ "aria-label": ariaLabel,
7250
+ "aria-labelledby": ariaLabelledBy
7251
+ }
7252
+ )
7253
+ ]
7254
+ }
7255
+ ) });
7256
+ }
7257
+ );
7258
+ SliderComponent.displayName = "Slider";
7259
+ var Slider = React25__namespace.memo(SliderComponent);
5518
7260
  var DURATION_MAP = {
5519
7261
  short: 4e3,
5520
7262
  long: 7e3
@@ -9011,10 +10753,14 @@ exports.PlainTooltip = PlainTooltip;
9011
10753
  exports.ProgressIndicator = ProgressIndicator;
9012
10754
  exports.RadioButton = RadioButton;
9013
10755
  exports.RadioGroup = RadioGroup2;
10756
+ exports.RangeSlider = RangeSlider;
9014
10757
  exports.RichTooltip = RichTooltip;
9015
10758
  exports.Ripple = Ripple;
9016
10759
  exports.ScrollArea = ScrollArea;
9017
10760
  exports.ScrollAreaScrollbar = ScrollAreaScrollbar;
10761
+ exports.Slider = Slider;
10762
+ exports.SliderColors = SliderColors;
10763
+ exports.SliderTokens = SliderTokens;
9018
10764
  exports.Snackbar = Snackbar;
9019
10765
  exports.SnackbarHost = SnackbarHost;
9020
10766
  exports.SnackbarProvider = SnackbarProvider;