@yamada-ui/slider
Version:
Yamada UI slider components
1,319 lines (1,316 loc) • 44.1 kB
JavaScript
"use client"
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/range-slider.tsx
var range_slider_exports = {};
__export(range_slider_exports, {
RangeSlider: () => RangeSlider,
RangeSliderEndThumb: () => RangeSliderEndThumb,
RangeSliderFilledTrack: () => RangeSliderFilledTrack,
RangeSliderMark: () => RangeSliderMark,
RangeSliderStartThumb: () => RangeSliderStartThumb,
RangeSliderTrack: () => RangeSliderTrack,
useRangeSlider: () => useRangeSlider
});
module.exports = __toCommonJS(range_slider_exports);
var import_core2 = require("@yamada-ui/core");
var import_form_control2 = require("@yamada-ui/form-control");
var import_use_controllable_state2 = require("@yamada-ui/use-controllable-state");
var import_use_latest_ref2 = require("@yamada-ui/use-latest-ref");
var import_use_pan_event2 = require("@yamada-ui/use-pan-event");
var import_use_size2 = require("@yamada-ui/use-size");
var import_utils2 = require("@yamada-ui/utils");
var import_react2 = require("react");
// src/slider.tsx
var import_core = require("@yamada-ui/core");
var import_form_control = require("@yamada-ui/form-control");
var import_use_controllable_state = require("@yamada-ui/use-controllable-state");
var import_use_latest_ref = require("@yamada-ui/use-latest-ref");
var import_use_pan_event = require("@yamada-ui/use-pan-event");
var import_use_size = require("@yamada-ui/use-size");
var import_utils = require("@yamada-ui/utils");
var import_react = require("react");
var import_jsx_runtime = require("react/jsx-runtime");
var getThumbSize = (thumbSize, styles) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
return (_t = (_s = (_q = (_o = (_m = (_k = (_i = (_g = (_e = (_c = thumbSize != null ? thumbSize : (_a = styles.thumb) == null ? void 0 : _a.boxSize) != null ? _c : (_b = styles.thumb) == null ? void 0 : _b.minBoxSize) != null ? _e : (_d = styles.thumb) == null ? void 0 : _d.width) != null ? _g : (_f = styles.thumb) == null ? void 0 : _f.w) != null ? _i : (_h = styles.thumb) == null ? void 0 : _h.minWidth) != null ? _k : (_j = styles.thumb) == null ? void 0 : _j.minW) != null ? _m : (_l = styles.thumb) == null ? void 0 : _l.height) != null ? _o : (_n = styles.thumb) == null ? void 0 : _n.h) != null ? _q : (_p = styles.thumb) == null ? void 0 : _p.minHeight) != null ? _s : (_r = styles.thumb) == null ? void 0 : _r.minH) != null ? _t : "3.5";
};
var useSlider = ({
focusThumbOnChange = true,
...props
}) => {
if (!focusThumbOnChange) props.isReadOnly = true;
const {
id,
name,
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
"aria-valuetext": ariaValueText,
defaultValue,
getAriaValueText: getAriaValueTextProp,
isReversed,
max = 100,
min = 0,
orientation = "horizontal",
reversed = isReversed,
step = 1,
thumbSize: thumbSizeProp,
value: valueProp,
onChange,
onChangeEnd: onChangeEndProp,
onChangeStart: onChangeStartProp,
...rest
} = (0, import_form_control.useFormControlProps)(props);
if (max < min)
throw new Error("Do not assign a number less than 'min' to 'max'");
const {
"aria-readonly": ariaReadonly,
disabled,
readOnly,
required,
onBlur,
onFocus,
...formControlProps
} = (0, import_utils.pickObject)(rest, import_form_control.formControlProperties);
const [computedValue, setValue] = (0, import_use_controllable_state.useControllableState)({
defaultValue: defaultValue != null ? defaultValue : min + (max - min) / 2,
value: valueProp,
onChange
});
const [dragging, setDragging] = (0, import_react.useState)(false);
const [focused, setFocused] = (0, import_react.useState)(false);
const interactive = !(disabled || readOnly);
const tenStep = (max - min) / 10;
const oneStep = step || (max - min) / 100;
const value = (0, import_utils.clampNumber)(computedValue, min, max);
const reversedValue = max - value + min;
const thumbValue = reversed ? reversedValue : value;
const thumbPercent = (0, import_utils.valueToPercent)(thumbValue, min, max);
const vertical = orientation === "vertical";
const latestRef = (0, import_use_latest_ref.useLatestRef)({
focusThumbOnChange,
interactive,
max,
min,
step,
value
});
const eventSourceRef = (0, import_react.useRef)(null);
const containerRef = (0, import_react.useRef)(null);
const trackRef = (0, import_react.useRef)(null);
const thumbRef = (0, import_react.useRef)(null);
const thumbSize = (0, import_use_size.useSize)(thumbRef);
const onChangeStart = (0, import_utils.useCallbackRef)(onChangeStartProp);
const onChangeEnd = (0, import_utils.useCallbackRef)(onChangeEndProp);
const getAriaValueText = (0, import_utils.useCallbackRef)(getAriaValueTextProp);
(0, import_use_pan_event.usePanEvent)(containerRef, {
onMove: (ev) => {
const { interactive: interactive2 } = latestRef.current;
if (!interactive2) return;
setValueFromPointer(ev);
},
onSessionEnd: () => {
const { interactive: interactive2, value: value2 } = latestRef.current;
if (!interactive2) return;
setDragging(false);
onChangeEnd(value2);
},
onSessionStart: (ev) => {
const { interactive: interactive2, value: value2 } = latestRef.current;
if (!interactive2) return;
setDragging(true);
focusThumb();
setValueFromPointer(ev);
onChangeStart(value2);
}
});
const getValueFromPointer = (0, import_react.useCallback)(
(ev) => {
var _a, _b;
if (!trackRef.current) return;
const { max: max2, min: min2, step: step2 } = latestRef.current;
eventSourceRef.current = "pointer";
const { bottom, height, left, width } = trackRef.current.getBoundingClientRect();
const { clientX, clientY } = (_b = (_a = ev.touches) == null ? void 0 : _a[0]) != null ? _b : ev;
const diff = vertical ? bottom - clientY : clientX - left;
const length = vertical ? height : width;
let percent = diff / length;
if (reversed) percent = 1 - percent;
let nextValue = (0, import_utils.percentToValue)(percent, min2, max2);
if (step2) nextValue = parseFloat((0, import_utils.roundNumberToStep)(nextValue, min2, step2));
nextValue = (0, import_utils.clampNumber)(nextValue, min2, max2);
return nextValue;
},
[vertical, reversed, latestRef]
);
const setValueFromPointer = (ev) => {
const { value: value2 } = latestRef.current;
const nextValue = getValueFromPointer(ev);
if (nextValue != null && nextValue !== value2) setValue(nextValue);
};
const focusThumb = (0, import_react.useCallback)(() => {
const { focusThumbOnChange: focusThumbOnChange2 } = latestRef.current;
if (focusThumbOnChange2) setTimeout(() => {
var _a;
return (_a = thumbRef.current) == null ? void 0 : _a.focus();
});
}, [latestRef]);
const constrain = (0, import_react.useCallback)(
(value2) => {
const { interactive: interactive2, max: max2, min: min2 } = latestRef.current;
if (!interactive2) return;
value2 = parseFloat((0, import_utils.roundNumberToStep)(value2, min2, oneStep));
value2 = (0, import_utils.clampNumber)(value2, min2, max2);
setValue(value2);
},
[oneStep, setValue, latestRef]
);
const stepUp = (0, import_react.useCallback)(
(step2 = oneStep) => constrain(reversed ? value - step2 : value + step2),
[constrain, reversed, oneStep, value]
);
const stepDown = (0, import_react.useCallback)(
(step2 = oneStep) => constrain(reversed ? value + step2 : value - step2),
[constrain, reversed, oneStep, value]
);
const reset = (0, import_react.useCallback)(
() => constrain(defaultValue || 0),
[constrain, defaultValue]
);
const stepTo = (0, import_react.useCallback)((value2) => constrain(value2), [constrain]);
const onKeyDown = (0, import_react.useCallback)(
(ev) => {
const { max: max2, min: min2 } = latestRef.current;
const actions = {
ArrowDown: () => stepDown(),
ArrowLeft: () => stepDown(),
ArrowRight: () => stepUp(),
ArrowUp: () => stepUp(),
End: () => constrain(max2),
Home: () => constrain(min2),
PageDown: () => stepDown(tenStep),
PageUp: () => stepUp(tenStep)
};
const action = actions[ev.key];
if (!action) return;
ev.preventDefault();
ev.stopPropagation();
action(ev);
eventSourceRef.current = "keyboard";
},
[constrain, latestRef, stepDown, stepUp, tenStep]
);
(0, import_utils.useUpdateEffect)(() => {
const { value: value2 } = latestRef.current;
focusThumb();
if (eventSourceRef.current === "keyboard") onChangeEnd(value2);
}, [value, onChangeEnd]);
const getContainerProps = (0, import_react.useCallback)(
(props2 = {}, ref = null) => {
let { height: h, width: w } = thumbSize != null ? thumbSize : {
height: "var(--ui-thumb-size)",
width: "var(--ui-thumb-size)"
};
if ((0, import_utils.isNumber)(w)) w = `${w}px`;
if ((0, import_utils.isNumber)(h)) h = `${h}px`;
const paddingStyle = vertical ? { paddingLeft: `calc(${w} / 2)`, paddingRight: `calc(${w} / 2)` } : { paddingBottom: `calc(${h} / 2)`, paddingTop: `calc(${h} / 2)` };
const style = {
...props2.style,
outline: 0,
position: "relative",
touchAction: "none",
userSelect: "none",
WebkitTapHighlightColor: "rgba(0, 0, 0, 0)",
...paddingStyle
};
return {
...rest,
...props2,
ref: (0, import_utils.mergeRefs)(ref, containerRef),
style,
tabIndex: -1,
vars: (0, import_core.mergeVars)(rest.vars, [
{
name: "thumb-size",
token: "sizes",
value: thumbSizeProp,
__prefix: "ui"
}
])
};
},
[vertical, rest, thumbSize, thumbSizeProp]
);
const getInputProps = (0, import_react.useCallback)(
(props2 = {}, ref = null) => ({
"aria-readonly": ariaReadonly,
...formControlProps,
...props2,
id,
ref,
type: "hidden",
name,
disabled,
readOnly,
required,
value
}),
[
ariaReadonly,
disabled,
formControlProps,
id,
name,
readOnly,
required,
value
]
);
const getTrackProps = (0, import_react.useCallback)(
(props2 = {}, ref = null) => {
const style = {
...props2.style,
position: "absolute",
...vertical ? {
height: "100%",
left: "50%",
transform: "translateX(-50%)"
} : {
top: "50%",
transform: "translateY(-50%)",
width: "100%"
}
};
return {
...formControlProps,
...props2,
ref: (0, import_utils.mergeRefs)(ref, trackRef),
style
};
},
[vertical, formControlProps]
);
const getFilledTrackProps = (0, import_react.useCallback)(
(props2 = {}, ref = null) => {
const n = Math.abs(reversed ? 100 - thumbPercent : thumbPercent);
const style = {
...props2.style,
position: "absolute",
...vertical ? {
height: `${n}%`,
left: "50%",
transform: "translateX(-50%)",
...reversed ? { top: "0%" } : { bottom: "0%" }
} : {
top: "50%",
transform: "translateY(-50%)",
width: `${n}%`,
...reversed ? { right: "0%" } : { left: "0%" }
}
};
return {
...formControlProps,
...props2,
ref,
style
};
},
[reversed, vertical, formControlProps, thumbPercent]
);
const getMarkProps = (0, import_react.useCallback)(
(props2, ref = null) => {
let n = (0, import_utils.valueToPercent)(props2.value, min, max);
n = reversed ? 100 - n : n;
const style = {
...props2.style,
pointerEvents: "none",
position: "absolute",
...vertical ? { bottom: `${n}%` } : { left: `${n}%` }
};
return {
...formControlProps,
...props2,
ref,
style,
"aria-hidden": true,
"data-highlighted": (0, import_utils.dataAttr)(props2.value <= value),
"data-invalid": (0, import_utils.dataAttr)(props2.value < min || max < props2.value)
};
},
[reversed, vertical, max, min, formControlProps, value]
);
const getThumbProps = (0, import_react.useCallback)(
(props2 = {}, ref = null) => {
var _a;
const n = thumbPercent;
let w = "var(--ui-thumb-size)";
let h = "var(--ui-thumb-size)";
if (thumbSize) {
w = `${thumbSize.width}px`;
h = `${thumbSize.height}px`;
}
const bottom = `calc(${n}% - (${h} / 2))`;
const left = `calc(${n}% - (${w} / 2))`;
const style = {
...props2.style,
position: "absolute",
touchAction: "none",
userSelect: "none",
...vertical ? { bottom } : { left }
};
return {
"aria-label": ariaLabel != null ? ariaLabel : "Slider thumb",
"aria-labelledby": ariaLabelledBy,
"aria-readonly": ariaReadonly,
...formControlProps,
...props2,
ref: (0, import_utils.mergeRefs)(ref, thumbRef),
style,
"aria-orientation": orientation,
"aria-valuemax": max,
"aria-valuemin": min,
"aria-valuenow": value,
"aria-valuetext": (_a = ariaValueText != null ? ariaValueText : getAriaValueText(value)) != null ? _a : value.toString(),
"data-active": (0, import_utils.dataAttr)(dragging && focusThumbOnChange),
role: "slider",
tabIndex: interactive && focusThumbOnChange ? 0 : void 0,
onBlur: (0, import_utils.handlerAll)(props2.onBlur, onBlur, () => setFocused(false)),
onFocus: (0, import_utils.handlerAll)(props2.onFocus, onFocus, () => setFocused(true)),
onKeyDown: (0, import_utils.handlerAll)(props2.onKeyDown, onKeyDown)
};
},
[
thumbPercent,
thumbSize,
vertical,
ariaLabel,
ariaLabelledBy,
ariaReadonly,
formControlProps,
orientation,
max,
min,
value,
ariaValueText,
getAriaValueText,
dragging,
focusThumbOnChange,
interactive,
onBlur,
onFocus,
onKeyDown
]
);
return {
dragging,
focused,
/**
* @deprecated Use `dragging` instead.
*/
isDragging: dragging,
/**
* @deprecated Use `focused` instead.
*/
isFocused: focused,
/**
* @deprecated Use `vertical` instead.
*/
isVertical: vertical,
reset,
stepDown,
stepTo,
stepUp,
value,
vertical,
getContainerProps,
getFilledTrackProps,
getInputProps,
getMarkProps,
getThumbProps,
getTrackProps
};
};
var [SliderProvider, useSliderContext] = (0, import_utils.createContext)({
name: "SliderContext",
errorMessage: `useSliderContext returned is 'undefined'. Seems you forgot to wrap the components in "<Slider />" `
});
var Slider = (0, import_core.forwardRef)((props, ref) => {
const [styles, mergedProps] = (0, import_core.useComponentMultiStyle)("Slider", props);
const {
className,
children,
filledTrackColor,
thumbColor,
thumbSize,
trackColor,
trackSize,
filledTrackProps,
inputProps,
thumbProps,
trackProps,
...rest
} = (0, import_core.omitThemeProps)(mergedProps);
const {
isVertical,
getContainerProps,
getFilledTrackProps,
getInputProps,
getMarkProps,
getThumbProps,
getTrackProps
} = useSlider({ ...rest, thumbSize: getThumbSize(thumbSize, styles) });
const css = { ...styles.container };
const validChildren = (0, import_utils.getValidChildren)(children);
const customSliderTrack = (0, import_utils.findChild)(validChildren, SliderTrack);
const customSliderThumb = (0, import_utils.findChild)(validChildren, SliderThumb);
const hasSliderThumb = (0, import_utils.includesChildren)(validChildren, SliderThumb);
const cloneChildren = !(0, import_utils.isEmpty)(validChildren) ? (0, import_utils.omitChildren)(validChildren, SliderTrack, SliderThumb) : children;
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SliderProvider,
{
value: {
filledTrackColor,
isVertical,
styles,
thumbColor,
thumbSize,
trackColor,
trackSize,
filledTrackProps,
getFilledTrackProps,
getMarkProps,
getThumbProps,
getTrackProps,
thumbProps,
trackProps
},
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
import_core.ui.div,
{
className: (0, import_utils.cx)("ui-slider", className),
__css: css,
...getContainerProps(),
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.ui.input, { ...getInputProps(inputProps, ref) }),
customSliderTrack != null ? customSliderTrack : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SliderTrack, {}),
cloneChildren,
customSliderThumb != null ? customSliderThumb : !hasSliderThumb ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SliderThumb, {}) : null
]
}
)
}
);
});
Slider.displayName = "Slider";
Slider.__ui__ = "Slider";
var SliderTrack = (0, import_core.forwardRef)(
({ className, children, filledTrackProps, ...rest }, ref) => {
const {
isVertical,
styles,
trackColor,
trackSize,
getTrackProps,
trackProps
} = useSliderContext();
const css = { ...styles.track };
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_core.ui.div,
{
className: (0, import_utils.cx)("ui-slider__track", className),
__css: css,
...getTrackProps(
{
...trackColor ? { bg: trackColor } : {},
...trackSize ? isVertical ? { w: trackSize } : { h: trackSize } : {},
...trackProps,
...rest
},
ref
),
children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SliderFilledTrack, { ...filledTrackProps })
}
);
}
);
SliderTrack.displayName = "SliderTrack";
SliderTrack.__ui__ = "SliderTrack";
var SliderFilledTrack = (0, import_core.forwardRef)(
({ className, ...rest }, ref) => {
const { filledTrackColor, styles, filledTrackProps, getFilledTrackProps } = useSliderContext();
const css = { ...styles.filledTrack };
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_core.ui.div,
{
className: (0, import_utils.cx)("ui-slider__track-filled", className),
__css: css,
...getFilledTrackProps(
{
...filledTrackColor ? { bg: filledTrackColor } : {},
...filledTrackProps,
...rest
},
ref
)
}
);
}
);
SliderFilledTrack.displayName = "SliderFilledTrack";
SliderFilledTrack.__ui__ = "SliderFilledTrack";
var SliderMark = (0, import_core.forwardRef)(
({ className, ...rest }, ref) => {
const { styles, getMarkProps } = useSliderContext();
const css = {
alignItems: "center",
display: "inline-flex",
justifyContent: "center",
...styles.mark
};
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_core.ui.div,
{
className: (0, import_utils.cx)("ui-slider__mark", className),
__css: css,
...getMarkProps(rest, ref)
}
);
}
);
SliderMark.displayName = "SliderMark";
SliderMark.__ui__ = "SliderMark";
var SliderThumb = (0, import_core.forwardRef)(
({ className, ...rest }, ref) => {
const { styles, thumbColor, thumbSize, getThumbProps, thumbProps } = useSliderContext();
const css = { ...styles.thumb };
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_core.ui.div,
{
className: (0, import_utils.cx)("ui-slider__thumb", className),
__css: css,
...getThumbProps(
{
...thumbColor ? { bg: thumbColor } : {},
...thumbSize ? { boxSize: thumbSize } : {},
...thumbProps,
...rest
},
ref
)
}
);
}
);
SliderThumb.displayName = "SliderThumb";
SliderThumb.__ui__ = "SliderThumb";
// src/range-slider.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var useRangeSlider = ({
focusThumbOnChange = true,
...props
}) => {
if (!focusThumbOnChange) props.isReadOnly = true;
const uuid = (0, import_react2.useId)();
const {
id = uuid,
name = id,
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
"aria-valuetext": ariaValueText,
betweenThumbs = 0,
max = 100,
min = 0,
defaultValue = [min + (max - min) / 4, max - (max - min) / 4],
getAriaValueText: getAriaValueTextProp,
isReversed,
orientation = "horizontal",
reversed = isReversed,
step = 1,
thumbSize: thumbSizeProp,
value: valueProp,
onChange,
onChangeEnd: onChangeEndProp,
onChangeStart: onChangeStartProp,
...rest
} = (0, import_form_control2.useFormControlProps)(props);
if (max < min)
throw new Error("Do not assign a number less than 'min' to 'max'");
const {
"aria-readonly": ariaReadonly,
disabled,
readOnly,
required,
onBlur,
onFocus,
...formControlProps
} = (0, import_utils2.pickObject)(rest, import_form_control2.formControlProperties);
const [computedValues, setValues] = (0, import_use_controllable_state2.useControllableState)({
defaultValue,
value: valueProp,
onChange
});
const [dragging, setDragging] = (0, import_react2.useState)(false);
const [focused, setFocused] = (0, import_react2.useState)(false);
const interactive = !(disabled || readOnly);
const tenStep = (max - min) / 10;
const oneStep = step || (max - min) / 100;
const spacing = betweenThumbs * step;
const values = computedValues.map(
(value) => (0, import_utils2.clampNumber)(value, min, max)
);
const [startValue, endValue] = values;
const reversedValues = values.map((value) => max - value + min);
const thumbValues = reversed ? reversedValues : values;
const thumbPercents = thumbValues.map(
(value) => (0, import_utils2.valueToPercent)(value, min, max)
);
const valueBounds = [
{ max: endValue - spacing, min },
{ max, min: startValue + spacing }
];
const vertical = orientation === "vertical";
const latestRef = (0, import_use_latest_ref2.useLatestRef)({
betweenThumbs,
disabled,
focusThumbOnChange,
interactive,
max,
min,
orientation,
reversed,
step,
valueBounds,
values,
vertical
});
const activeIndexRef = (0, import_react2.useRef)(-1);
const eventSourceRef = (0, import_react2.useRef)(null);
const containerRef = (0, import_react2.useRef)(null);
const trackRef = (0, import_react2.useRef)(null);
const thumbSizes = (0, import_use_size2.useSizes)({
getNodes: () => {
var _a;
const nodes = (_a = containerRef.current) == null ? void 0 : _a.querySelectorAll("[role=slider]");
return nodes ? Array.from(nodes) : [];
}
});
const onChangeStart = (0, import_utils2.useCallbackRef)(onChangeStartProp);
const onChangeEnd = (0, import_utils2.useCallbackRef)(onChangeEndProp);
const getAriaValueText = (0, import_utils2.useCallbackRef)(getAriaValueTextProp);
const getThumbId = (0, import_react2.useCallback)((i) => `slider-thumb-${id}-${i}`, [id]);
const getInputId = (0, import_react2.useCallback)((i) => `slider-input-${id}-${i}`, [id]);
const getMarkerId = (0, import_react2.useCallback)(
(i) => `slider-marker-${id}-${i}`,
[id]
);
(0, import_use_pan_event2.usePanEvent)(containerRef, {
onMove: (ev) => {
const activeIndex = activeIndexRef.current;
const { interactive: interactive2 } = latestRef.current;
if (!interactive2 || activeIndex == -1) return;
const pointValue = getValueFromPointer(ev) || 0;
constrain(activeIndex, pointValue);
focusThumb(activeIndex);
},
onSessionEnd: () => {
const { interactive: interactive2, values: values2 } = latestRef.current;
if (!interactive2) return;
setDragging(false);
onChangeEnd(values2);
},
onSessionStart: (ev) => {
const { interactive: interactive2, values: values2 } = latestRef.current;
if (!interactive2) return;
setDragging(true);
const pointValue = getValueFromPointer(ev) || 0;
const distances = values2.map((value) => Math.abs(value - pointValue));
const closest = Math.min(...distances);
let i = distances.indexOf(closest);
const thumbsPosition = distances.filter(
(distance) => distance === closest
);
const isThumbStacked = thumbsPosition.length > 1;
if (isThumbStacked && pointValue > values2[i])
i = i + thumbsPosition.length - 1;
activeIndexRef.current = i;
constrain(i, pointValue);
focusThumb(i);
onChangeStart(values2);
}
});
const getValueFromPointer = (0, import_react2.useCallback)(
(ev) => {
var _a, _b;
if (!trackRef.current) return;
const { max: max2, min: min2 } = latestRef.current;
eventSourceRef.current = "pointer";
const { bottom, height, left, width } = trackRef.current.getBoundingClientRect();
const { clientX, clientY } = (_b = (_a = ev.touches) == null ? void 0 : _a[0]) != null ? _b : ev;
const diff = vertical ? bottom - clientY : clientX - left;
const length = vertical ? height : width;
let percent = diff / length;
if (reversed) percent = 1 - percent;
let nextValue = (0, import_utils2.percentToValue)(percent, min2, max2);
return nextValue;
},
[latestRef, vertical, reversed]
);
const focusThumb = (0, import_react2.useCallback)(
(i) => {
var _a;
if (i === -1 || !focusThumbOnChange) return;
const id2 = getThumbId(i);
const el = (_a = containerRef.current) == null ? void 0 : _a.ownerDocument.getElementById(id2);
if (el) setTimeout(() => el.focus());
},
[focusThumbOnChange, getThumbId]
);
const constrain = (0, import_react2.useCallback)(
(i, value) => {
var _a;
const { interactive: interactive2, valueBounds: valueBounds2, values: values2 } = latestRef.current;
if (!interactive2) return;
const { max: max2 = 100, min: min2 = 0 } = (_a = valueBounds2[i]) != null ? _a : {};
value = parseFloat((0, import_utils2.roundNumberToStep)(value, min2, oneStep));
value = (0, import_utils2.clampNumber)(value, min2, max2);
const nextValues = [...values2];
nextValues[i] = value;
setValues(nextValues);
},
[latestRef, oneStep, setValues]
);
const stepUp = (0, import_react2.useCallback)(
(i, step2 = oneStep) => {
const { values: values2 } = latestRef.current;
const value = values2[i];
constrain(i, reversed ? value - step2 : value + step2);
},
[constrain, reversed, latestRef, oneStep]
);
const stepDown = (0, import_react2.useCallback)(
(i, step2 = oneStep) => {
const { values: values2 } = latestRef.current;
const value = values2[i];
constrain(i, reversed ? value + step2 : value - step2);
},
[constrain, reversed, latestRef, oneStep]
);
const reset = (0, import_react2.useCallback)(
() => setValues(defaultValue),
[defaultValue, setValues]
);
const onKeyDown = (0, import_react2.useCallback)(
(ev) => {
var _a;
const activeIndex = activeIndexRef.current;
const { valueBounds: valueBounds2 } = latestRef.current;
const { max: max2 = 100, min: min2 = 0 } = (_a = valueBounds2[activeIndex]) != null ? _a : {};
const actions = {
ArrowDown: () => stepDown(activeIndex),
ArrowLeft: () => stepDown(activeIndex),
ArrowRight: () => stepUp(activeIndex),
ArrowUp: () => stepUp(activeIndex),
End: () => constrain(activeIndex, max2),
Home: () => constrain(activeIndex, min2),
PageDown: () => stepDown(activeIndex, tenStep),
PageUp: () => stepUp(activeIndex, tenStep)
};
const action = actions[ev.key];
if (!action) return;
ev.preventDefault();
ev.stopPropagation();
action(ev);
eventSourceRef.current = "keyboard";
},
[constrain, latestRef, stepDown, stepUp, tenStep]
);
(0, import_utils2.useUpdateEffect)(() => {
const { values: values2 } = latestRef.current;
if (eventSourceRef.current === "keyboard") onChangeEnd(values2);
}, [startValue, endValue, onChangeEnd]);
const getContainerProps = (0, import_react2.useCallback)(
(props2 = {}, ref = null) => {
var _a;
let w = "var(--ui-thumb-size)";
let h = "var(--ui-thumb-size)";
if (thumbSizes.length) {
const p = vertical ? "height" : "width";
const z = { height: 0, width: 0 };
const { height, width } = (_a = thumbSizes.reduce((a = z, b = z) => a[p] > b[p] ? a : b, z)) != null ? _a : {};
if (width) w = `${width}px`;
if (height) h = `${height}px`;
}
const paddingStyle = vertical ? { paddingLeft: `calc(${w} / 2)`, paddingRight: `calc(${w} / 2)` } : { paddingBottom: `calc(${h} / 2)`, paddingTop: `calc(${h} / 2)` };
const style = {
...props2.style,
outline: 0,
position: "relative",
touchAction: "none",
userSelect: "none",
WebkitTapHighlightColor: "rgba(0, 0, 0, 0)",
...paddingStyle
};
return {
...rest,
...props2,
id: `slider-container-${id}`,
ref: (0, import_utils2.mergeRefs)(ref, containerRef),
style,
tabIndex: -1,
vars: (0, import_core2.mergeVars)(rest.vars, [
{
name: "thumb-size",
token: "sizes",
value: thumbSizeProp,
__prefix: "ui"
}
])
};
},
[id, vertical, rest, thumbSizeProp, thumbSizes]
);
const getInputProps = (0, import_react2.useCallback)(
({ index: i, ...props2 }, ref = null) => ({
"aria-readonly": ariaReadonly,
...formControlProps,
...props2,
id: getInputId(i),
ref,
type: "hidden",
name: (0, import_utils2.isArray)(name) ? name[i] : `${name}-${i}`,
disabled,
readOnly,
required,
value: values[i]
}),
[
ariaReadonly,
disabled,
getInputId,
name,
readOnly,
required,
formControlProps,
values
]
);
const getTrackProps = (0, import_react2.useCallback)(
(props2 = {}, ref = null) => {
const style = {
...props2.style,
position: "absolute",
...vertical ? {
height: "100%",
left: "50%",
transform: "translateX(-50%)"
} : {
top: "50%",
transform: "translateY(-50%)",
width: "100%"
}
};
return {
...formControlProps,
...props2,
id: `slider-track-${id}`,
ref: (0, import_utils2.mergeRefs)(ref, trackRef),
style
};
},
[id, vertical, formControlProps]
);
const getFilledTrackProps = (0, import_react2.useCallback)(
(props2 = {}, ref = null) => {
const n = Math.abs(thumbPercents[1] - thumbPercents[0]);
const s = reversed ? 100 - thumbPercents[0] : thumbPercents[0];
const style = {
...props2.style,
position: "absolute",
...vertical ? {
height: `${n}%`,
left: "50%",
transform: "translateX(-50%)",
...reversed ? { top: `${s}%` } : { bottom: `${s}%` }
} : {
top: "50%",
transform: "translateY(-50%)",
width: `${n}%`,
...reversed ? { right: `${s}%` } : { left: `${s}%` }
}
};
return {
...formControlProps,
...props2,
id: `slider-filled-track-${id}`,
ref,
style
};
},
[id, reversed, vertical, formControlProps, thumbPercents]
);
const getMarkProps = (0, import_react2.useCallback)(
(props2, ref = null) => {
let n = (0, import_utils2.valueToPercent)(props2.value, min, max);
n = reversed ? 100 - n : n;
const style = {
...props2.style,
pointerEvents: "none",
position: "absolute",
...vertical ? { bottom: `${n}%` } : { left: `${n}%` }
};
return {
...formControlProps,
...props2,
id: getMarkerId(props2.value),
ref,
style,
"aria-hidden": true,
"data-highlighted": (0, import_utils2.dataAttr)(
values[0] <= props2.value && props2.value <= values[1]
),
"data-invalid": (0, import_utils2.dataAttr)(props2.value < min || max < props2.value)
};
},
[getMarkerId, reversed, vertical, max, min, formControlProps, values]
);
const getThumbProps = (0, import_react2.useCallback)(
({ index: i, ...props2 }, ref = null) => {
var _a, _b, _c;
const n = thumbPercents[i];
let w = "var(--ui-thumb-size)";
let h = "var(--ui-thumb-size)";
if (thumbSizes[i]) {
w = `${(_a = thumbSizes[i]) == null ? void 0 : _a.width}px`;
h = `${(_b = thumbSizes[i]) == null ? void 0 : _b.height}px`;
}
const bottom = `calc(${n}% - (${h} / 2))`;
const left = `calc(${n}% - (${w} / 2))`;
const style = {
...props2.style,
position: "absolute",
touchAction: "none",
userSelect: "none",
...vertical ? { bottom } : { left }
};
const value = values[i];
if (value == null)
throw new Error(
`Cannot find value at index '${i}'. The 'value' or 'defaultValue'`
);
return {
"aria-label": ariaLabel != null ? ariaLabel : "Slider thumb",
"aria-labelledby": ariaLabelledBy,
"aria-readonly": ariaReadonly,
...formControlProps,
...props2,
id: getThumbId(i),
ref,
style,
"aria-orientation": orientation,
"aria-valuemax": max,
"aria-valuemin": min,
"aria-valuenow": value,
"aria-valuetext": (_c = ariaValueText != null ? ariaValueText : getAriaValueText(value)) != null ? _c : value.toString(),
"data-active": (0, import_utils2.dataAttr)(
dragging && focusThumbOnChange && activeIndexRef.current === i
),
role: "slider",
tabIndex: interactive && focusThumbOnChange ? 0 : void 0,
onBlur: (0, import_utils2.handlerAll)(props2.onBlur, onBlur, () => {
activeIndexRef.current = -1;
setFocused(false);
}),
onFocus: (0, import_utils2.handlerAll)(props2.onFocus, onFocus, () => {
activeIndexRef.current = i;
setFocused(true);
}),
onKeyDown: (0, import_utils2.handlerAll)(props2.onKeyDown, onKeyDown)
};
},
[
thumbPercents,
thumbSizes,
vertical,
values,
ariaLabel,
ariaLabelledBy,
ariaReadonly,
formControlProps,
getThumbId,
orientation,
max,
min,
ariaValueText,
getAriaValueText,
dragging,
focusThumbOnChange,
interactive,
onBlur,
onFocus,
onKeyDown
]
);
return {
dragging,
focused,
getInputId,
getMarkerId,
getThumbId,
reset,
stepDown,
stepUp,
values,
vertical,
getContainerProps,
getFilledTrackProps,
getInputProps,
getMarkProps,
getThumbProps,
getTrackProps
};
};
var [RangeSliderProvider, useRangeSliderContext] = (0, import_utils2.createContext)({
name: "RangeSliderContext",
errorMessage: `useRangeSliderContext returned is 'undefined'. Seems you forgot to wrap the components in "<RangeSlider />" `
});
var RangeSlider = (0, import_core2.forwardRef)((props, ref) => {
const [styles, mergedProps] = (0, import_core2.useComponentMultiStyle)("RangeSlider", props);
const {
className,
children,
filledTrackColor,
thumbColor,
thumbSize,
trackColor,
trackSize,
filledTrackProps,
inputProps,
thumbProps,
trackProps,
...rest
} = (0, import_core2.omitThemeProps)(mergedProps);
const {
vertical,
getContainerProps,
getFilledTrackProps,
getInputProps,
getMarkProps,
getThumbProps,
getTrackProps
} = useRangeSlider({ ...rest, thumbSize: getThumbSize(thumbSize, styles) });
const css = { ...styles.container };
const validChildren = (0, import_utils2.getValidChildren)(children);
const customRangeSliderTrack = (0, import_utils2.findChild)(validChildren, RangeSliderTrack);
const customRangeSliderStartThumb = (0, import_utils2.findChild)(
validChildren,
RangeSliderStartThumb
);
const customRangeSliderEndThumb = (0, import_utils2.findChild)(
validChildren,
RangeSliderEndThumb
);
const hasRangeSliderStartThumb = (0, import_utils2.includesChildren)(
validChildren,
RangeSliderStartThumb
);
const hasRangeSliderEndThumb = (0, import_utils2.includesChildren)(
validChildren,
RangeSliderEndThumb
);
const cloneChildren = !(0, import_utils2.isEmpty)(validChildren) ? (0, import_utils2.omitChildren)(
validChildren,
RangeSliderTrack,
RangeSliderStartThumb,
RangeSliderEndThumb
) : children;
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
RangeSliderProvider,
{
value: {
filledTrackColor,
styles,
thumbColor,
thumbSize,
trackColor,
trackSize,
vertical,
filledTrackProps,
getFilledTrackProps,
getInputProps,
getMarkProps,
getThumbProps,
getTrackProps,
inputProps,
thumbProps,
trackProps
},
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
import_core2.ui.div,
{
className: (0, import_utils2.cx)("ui-slider", className),
__css: css,
...getContainerProps({}, ref),
children: [
customRangeSliderTrack != null ? customRangeSliderTrack : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RangeSliderTrack, {}),
cloneChildren,
customRangeSliderStartThumb != null ? customRangeSliderStartThumb : !hasRangeSliderStartThumb ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RangeSliderStartThumb, {}) : null,
customRangeSliderEndThumb != null ? customRangeSliderEndThumb : !hasRangeSliderEndThumb ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RangeSliderEndThumb, {}) : null
]
}
)
}
);
});
RangeSlider.displayName = "RangeSlider";
RangeSlider.__ui__ = "RangeSlider";
var RangeSliderTrack = (0, import_core2.forwardRef)(
({ className, children, filledTrackProps, ...rest }, ref) => {
const {
styles,
trackColor,
trackSize,
vertical,
getTrackProps,
trackProps
} = useRangeSliderContext();
const css = { ...styles.track };
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
import_core2.ui.div,
{
className: (0, import_utils2.cx)("ui-slider__track", className),
__css: css,
...getTrackProps(
{
...trackColor ? { bg: trackColor } : {},
...trackSize ? vertical ? { w: trackSize } : { h: trackSize } : {},
...trackProps,
...rest
},
ref
),
children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RangeSliderFilledTrack, { ...filledTrackProps })
}
);
}
);
RangeSliderTrack.displayName = "RangeSliderTrack";
RangeSliderTrack.__ui__ = "RangeSliderTrack";
var RangeSliderFilledTrack = (0, import_core2.forwardRef)(({ className, ...rest }, ref) => {
const { filledTrackColor, styles, filledTrackProps, getFilledTrackProps } = useRangeSliderContext();
const css = { ...styles.filledTrack };
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
import_core2.ui.div,
{
className: (0, import_utils2.cx)("ui-slider__track-filled", className),
__css: css,
...getFilledTrackProps(
{
...filledTrackColor ? { bg: filledTrackColor } : {},
...filledTrackProps,
...rest
},
ref
)
}
);
});
RangeSliderFilledTrack.displayName = "RangeSliderFilledTrack";
RangeSliderFilledTrack.__ui__ = "RangeSliderFilledTrack";
var RangeSliderMark = (0, import_core2.forwardRef)(
({ className, ...rest }, ref) => {
const { styles, getMarkProps } = useRangeSliderContext();
const css = {
alignItems: "center",
display: "inline-flex",
justifyContent: "center",
...styles.mark
};
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
import_core2.ui.div,
{
className: (0, import_utils2.cx)("ui-slider__mark", className),
__css: css,
...getMarkProps(rest, ref)
}
);
}
);
RangeSliderMark.displayName = "RangeSliderMark";
RangeSliderMark.__ui__ = "RangeSliderMark";
var RangeSliderThumb = (0, import_core2.forwardRef)(({ className, children, index, ...rest }, ref) => {
const {
styles,
thumbColor,
thumbSize,
getInputProps,
getThumbProps,
inputProps,
thumbProps
} = useRangeSliderContext();
const css = { ...styles.thumb };
const { children: propChildren } = thumbProps != null ? thumbProps : {};
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
import_core2.ui.div,
{
className: (0, import_utils2.cx)("ui-slider__thumb", className),
__css: css,
...getThumbProps(
{
index,
...thumbColor ? { bg: thumbColor } : {},
...thumbSize ? { boxSize: thumbSize } : {},
...thumbProps,
...rest
},
ref
),
children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.ui.input, { ...getInputProps({ ...inputProps, index }, ref) }),
children != null ? children : propChildren
]
}
);
});
RangeSliderThumb.displayName = "RangeSliderThumb";
RangeSliderThumb.__ui__ = "RangeSliderThumb";
var RangeSliderStartThumb = (0, import_core2.forwardRef)(
(rest, ref) => {
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RangeSliderThumb, { ref, index: 0, ...rest });
}
);
RangeSliderStartThumb.displayName = "RangeSliderStartThumb";
RangeSliderStartThumb.__ui__ = "RangeSliderStartThumb";
var RangeSliderEndThumb = (0, import_core2.forwardRef)(
(rest, ref) => {
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RangeSliderThumb, { ref, index: 1, ...rest });
}
);
RangeSliderEndThumb.displayName = "RangeSliderEndThumb";
RangeSliderEndThumb.__ui__ = "RangeSliderEndThumb";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
RangeSlider,
RangeSliderEndThumb,
RangeSliderFilledTrack,
RangeSliderMark,
RangeSliderStartThumb,
RangeSliderTrack,
useRangeSlider
});
//# sourceMappingURL=range-slider.js.map