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