@julo-ui/sliders
Version:
A React Slider component that implements input[type='range']
898 lines (876 loc) • 30.1 kB
JavaScript
;
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/RangeSlider.tsx
var RangeSlider_exports = {};
__export(RangeSlider_exports, {
default: () => RangeSlider_default
});
module.exports = __toCommonJS(RangeSlider_exports);
var import_system = require("@julo-ui/system");
// src/range-slider/styles.ts
var import_react = require("@emotion/react");
var rangeSliderCx = import_react.css``;
// src/range-slider/use-range-slider.ts
var import_react7 = require("react");
var import_use_callback_ref = require("@julo-ui/use-callback-ref");
var import_number_utils3 = require("@julo-ui/number-utils");
var import_use_controllable_state = require("@julo-ui/use-controllable-state");
var import_use_watch_element_size = require("@julo-ui/use-watch-element-size");
// src/usecase/use-handle-dragging.ts
var import_react2 = require("react");
function useHandleDragging() {
const [isDragging, setIsDragging] = (0, import_react2.useState)(false);
const onDraggingStart = (0, import_react2.useCallback)(() => {
setIsDragging(true);
}, []);
const onDraggingEnd = (0, import_react2.useCallback)(() => {
setIsDragging(false);
}, []);
return { isDragging, onDraggingStart, onDraggingEnd };
}
var use_handle_dragging_default = useHandleDragging;
// src/usecase/use-handle-focus.ts
var import_react3 = require("react");
function useHandleFocus() {
const [isFocused, setIsFocused] = (0, import_react3.useState)(false);
const onFocus = (0, import_react3.useCallback)(() => {
setIsFocused(true);
}, []);
const onBlur = (0, import_react3.useCallback)(() => {
setIsFocused(false);
}, []);
return { isFocused, onFocus, onBlur };
}
var use_handle_focus_default = useHandleFocus;
// src/usecase/use-handle-reversed.ts
function useHandleReversed(options) {
const { isReversed = false, direction, orientation } = options;
if (direction === "ltr" || orientation === "vertical") {
return isReversed;
}
return !isReversed;
}
var use_handle_reversed_default = useHandleReversed;
// src/usecase/use-handle-style.ts
var import_react4 = require("react");
var defaultSize = { width: 0, height: 0 };
var normalizeSize = (size) => size || defaultSize;
function useHandleStyle(options) {
const {
thumbSizes: thumbRects,
orientation,
isReversed,
thumbPercents
} = options;
const getThumbStyle = (0, import_react4.useCallback)(
(i) => {
var _a;
const rect = (_a = thumbRects[i]) != null ? _a : defaultSize;
return {
position: "absolute",
userSelect: "none",
WebkitUserSelect: "none",
MozUserSelect: "none",
msUserSelect: "none",
touchAction: "none",
...orientation === "vertical" ? { bottom: `calc(${thumbPercents[i]}% - ${rect.height / 2}px)` } : { left: `calc(${thumbPercents[i]}% - ${rect.width / 2}px)` }
};
},
[orientation, thumbPercents, thumbRects]
);
const getMarkerStyle = (0, import_react4.useCallback)(
(percent) => {
return {
position: "absolute",
pointerEvents: "none",
...orientation === "vertical" ? { bottom: `${percent}%`, transform: `translateY(-50%)` } : { left: `${percent}%`, transform: `translateX(-50%)` }
};
},
[orientation]
);
const rootStyle = (0, import_react4.useMemo)(() => {
const size = normalizeSize(
orientation === "vertical" ? thumbRects.reduce(
(a, b) => normalizeSize(a).height > normalizeSize(b).height ? a : b,
defaultSize
) : thumbRects.reduce(
(a, b) => normalizeSize(a).width > normalizeSize(b).width ? a : b,
defaultSize
)
);
return {
position: "relative",
touchAction: "none",
WebkitTapHighlightColor: "rgba(0,0,0,0)",
userSelect: "none",
outline: 0,
...orientation === "vertical" ? {
paddingLeft: size.width / 2,
paddingRight: size.width / 2,
height: "100%"
} : {
paddingTop: size.height / 2,
paddingBottom: size.height / 2,
width: "100%"
}
};
}, [orientation, thumbRects]);
const trackStyle = (0, import_react4.useMemo)(
() => ({
position: "absolute",
...orientation === "vertical" ? { left: "50%", transform: "translateX(-50%)", height: "100%" } : { top: "50%", transform: "translateY(-50%)", width: "100%" }
}),
[orientation]
);
const innerTrackStyle = (0, import_react4.useMemo)(() => {
const isSingleThumb = thumbPercents.length === 1;
const fallback = [
0,
isReversed ? 100 - thumbPercents[0] : thumbPercents[0]
];
const range = isSingleThumb ? fallback : thumbPercents;
let start = range[0];
if (!isSingleThumb && isReversed) {
start = 100 - start;
}
const percent = Math.abs(range[range.length - 1] - range[0]);
return {
...trackStyle,
...orientation === "vertical" ? isReversed ? { height: `${percent}%`, top: `${start}%` } : { height: `${percent}%`, bottom: `${start}%` } : isReversed ? { width: `${percent}%`, right: `${start}%` } : { width: `${percent}%`, left: `${start}%` }
};
}, [isReversed, orientation, thumbPercents, trackStyle]);
return {
getThumbStyle,
rootStyle,
trackStyle,
innerTrackStyle,
getMarkerStyle
};
}
var use_handle_style_default = useHandleStyle;
// src/range-slider/constants.ts
var RANGE_SLIDER_DEFAULT_VALUE = [25, 75];
// src/range-slider/utils.ts
var import_number_utils2 = require("@julo-ui/number-utils");
// src/utils.ts
var import_number_utils = require("@julo-ui/number-utils");
function valueToPercent(value, min, max) {
return (value - min) * 100 / (max - min);
}
function percentToValue(percent, min, max) {
return (max - min) * percent + min;
}
function isMouseEvent(event) {
return !("touches" in event);
}
function roundValueToStep(value, from, step) {
const nextValue = Math.round((value - from) / step) * step + from;
const precision = (0, import_number_utils.countDecimalPlaces)(step);
return (0, import_number_utils.toPreciseDecimal)(nextValue, precision);
}
// src/range-slider/utils.ts
function getValueBounds(value, min, max, spacing) {
return value.map((_v, i) => {
const _min = i === 0 ? min : value[i - 1] + spacing;
const _max = i === value.length - 1 ? max : value[i + 1] - spacing;
return { min: _min, max: _max };
});
}
function getIds(id) {
return {
root: `slider-root-${id}`,
getThumb: (i) => `slider-thumb-${id}-${i}`,
getInput: (i) => `slider-input-${id}-${i}`,
track: `slider-track-${id}`,
innerTrack: `slider-filled-track-${id}`,
getMarker: (i) => `slider-marker-${id}-${i}`,
output: `slider-output-${id}`
};
}
function getThumbStateOnChange({
bounds,
index,
values,
pointerValue,
prevValue,
step,
isDisableSwap,
distanceBetweenThumbs
}) {
const prevValueAtIndex = prevValue[index];
const boundsAtIndex = bounds[index];
let valueAtIndex = (0, import_number_utils2.clampValue)(
parseFloat(roundValueToStep(pointerValue, boundsAtIndex.min, step)),
isDisableSwap ? boundsAtIndex.min : bounds[0].min,
isDisableSwap ? boundsAtIndex.max : bounds[bounds.length - 1].max
);
const isDecreasing = pointerValue < prevValueAtIndex;
const isValueExceedBoundedValue = !isDisableSwap && (isDecreasing ? valueAtIndex <= boundsAtIndex.min - distanceBetweenThumbs : valueAtIndex >= boundsAtIndex.max + distanceBetweenThumbs);
if (isValueExceedBoundedValue) {
const totalThumb = prevValue.length;
let isFoundNewThumb = false;
let isNoMoreThumb = false;
values[index] = isDecreasing ? boundsAtIndex.min : boundsAtIndex.max;
for (let i = isDecreasing ? index - 1 : index + 1; !isFoundNewThumb && !isNoMoreThumb; isDecreasing ? i-- : i++) {
if (i >= totalThumb || i < 0) {
isNoMoreThumb = true;
if (isDecreasing ? valueAtIndex < boundsAtIndex.min : valueAtIndex > boundsAtIndex.max) {
valueAtIndex = isDecreasing ? boundsAtIndex.min : boundsAtIndex.max;
}
continue;
}
if (!isDecreasing ? valueAtIndex >= bounds[i].min && valueAtIndex < bounds[i].max + distanceBetweenThumbs : valueAtIndex > bounds[i].min - distanceBetweenThumbs && valueAtIndex <= bounds[i].max) {
isFoundNewThumb = true;
index = i;
}
}
} else {
if (!isDecreasing && pointerValue > boundsAtIndex.max) {
valueAtIndex = boundsAtIndex.max;
}
if (isDecreasing && pointerValue < boundsAtIndex.min) {
valueAtIndex = boundsAtIndex.min;
}
}
values[index] = valueAtIndex;
return { index, value: values };
}
// src/range-slider/usecase/use-handle-focus-thumb.ts
var import_react5 = require("react");
function useHandleFocusThumb(options) {
const { focusThumbOnChange, rootRef, ids, activeIndex } = options;
const onFocusThumb = (0, import_react5.useCallback)(
(index) => {
var _a;
const targetIndex = index != null ? index : activeIndex;
if (targetIndex === -1 || !focusThumbOnChange)
return;
const id = ids.getThumb(targetIndex);
const thumb = (_a = rootRef.current) == null ? void 0 : _a.ownerDocument.getElementById(id);
if (thumb) {
setTimeout(() => thumb.focus());
}
},
[activeIndex, focusThumbOnChange, ids, rootRef]
);
return { onFocusThumb };
}
var use_handle_focus_thumb_default = useHandleFocusThumb;
// src/range-slider/usecase/use-handle-pan-event.ts
var import_react6 = require("react");
var import_react_use_pan_event = require("@chakra-ui/react-use-pan-event");
var import_function_utils = require("@julo-ui/function-utils");
function useHandlePanEvent(options) {
const {
rootRef,
trackRef,
sliderStates,
activeIndex,
actions,
onFocusThumb,
onDraggingStart,
onDraggingEnd,
onChangeStart = import_function_utils._noop,
onChangeEnd = import_function_utils._noop,
isDisableSwap,
prevValue,
distanceBetweenThumbs
} = options;
const getValueFromPointer = (0, import_react6.useCallback)(
(event) => {
var _a;
if (!trackRef.current)
return;
sliderStates.eventSource = "pointer";
const trackRect = trackRef.current.getBoundingClientRect();
const { clientX, clientY } = !isMouseEvent(event) ? (_a = event.touches) == null ? void 0 : _a[0] : event;
const diff = sliderStates.isVertical ? trackRect.bottom - clientY : clientX - trackRect.left;
const length = sliderStates.isVertical ? trackRect.height : trackRect.width;
let percent = diff / length;
if (sliderStates.isReversed)
percent = 1 - percent;
return percentToValue(percent, sliderStates.min, sliderStates.max);
},
[trackRef, sliderStates]
);
const onPanSessionStart = (0, import_react6.useCallback)(
(event) => {
var _a;
if (!sliderStates.isInteractive)
return;
onDraggingStart();
const pointValue = (_a = getValueFromPointer(event)) != null ? _a : 0;
const distances = sliderStates.value.map(
(value) => Math.abs(value - pointValue)
);
const closest = Math.min(...distances);
let targetIndex = distances.indexOf(closest);
const thumbsPosition = distances.filter(
(distance) => distance === closest
);
const isThumbStacked = thumbsPosition.length > 1;
if (isThumbStacked && pointValue > sliderStates.value[targetIndex]) {
targetIndex = targetIndex + thumbsPosition.length - 1;
}
actions.setActiveIndex(targetIndex);
actions.setValueAtIndex(targetIndex, pointValue);
onFocusThumb(targetIndex);
onChangeStart(sliderStates.value);
},
[
actions,
getValueFromPointer,
onChangeStart,
onDraggingStart,
onFocusThumb,
sliderStates.isInteractive,
sliderStates.value
]
);
const onPan = (0, import_react6.useCallback)(
(event) => {
var _a;
if (!sliderStates.isInteractive || activeIndex === -1)
return;
const pointerValue = (_a = getValueFromPointer(event)) != null ? _a : 0;
const values = [...sliderStates.value];
const bounds = [...sliderStates.valueBounds];
const { index, value } = getThumbStateOnChange({
pointerValue,
values,
bounds,
isDisableSwap,
index: activeIndex,
prevValue: prevValue.current,
step: sliderStates.step,
distanceBetweenThumbs
});
actions.setActiveIndex(index);
actions.setValue(value);
onFocusThumb(index);
},
[
actions,
activeIndex,
distanceBetweenThumbs,
getValueFromPointer,
isDisableSwap,
onFocusThumb,
prevValue,
sliderStates.isInteractive,
sliderStates.step,
sliderStates.value,
sliderStates.valueBounds
]
);
(0, import_react_use_pan_event.usePanEvent)(rootRef, {
onPanSessionStart,
onPanSessionEnd() {
if (!sliderStates.isInteractive)
return;
onDraggingEnd();
prevValue.current = sliderStates.value;
onChangeEnd(sliderStates.value);
},
onPan
});
}
var use_handle_pan_event_default = useHandlePanEvent;
// src/range-slider/use-range-slider.ts
var import_dom_utils = require("@julo-ui/dom-utils");
var import_function_utils2 = require("@julo-ui/function-utils");
function useRangeSlider(props) {
const {
min = 0,
max = 100,
onChange,
value: valueProp,
defaultValue,
isReversed: isReversedProp,
direction = "ltr",
orientation = "horizontal",
id: idProp,
isDisabled = false,
isReadOnly,
onChangeStart: onChangeStartProp,
onChangeEnd: onChangeEndProp,
step = 1,
getAriaValueText: getAriaValueTextProp,
"aria-valuetext": ariaValueText,
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
name,
focusThumbOnChange = true,
minStepsBetweenThumbs = 0,
isDisableSwap = false,
...resRootProps
} = props;
const onChangeStart = (0, import_use_callback_ref.useCallbackRef)(onChangeStartProp);
const onChangeEnd = (0, import_use_callback_ref.useCallbackRef)(onChangeEndProp);
const getAriaValueText = (0, import_use_callback_ref.useCallbackRef)(getAriaValueTextProp);
const isReversed = use_handle_reversed_default({
isReversed: isReversedProp,
direction,
orientation
});
const [computedValue, setComputedValue] = (0, import_use_controllable_state.useControllableState)({
value: valueProp,
defaultValue: defaultValue != null ? defaultValue : RANGE_SLIDER_DEFAULT_VALUE,
onChange
});
if (!Array.isArray(computedValue)) {
throw new TypeError(
`[range-slider] You passed an invalid value for \`value\` or \`defaultValue\`, expected \`Array\` but got \`${typeof computedValue}\``
);
}
const [activeIndex, setActiveIndex] = (0, import_react7.useState)(-1);
const initialValue = (0, import_react7.useRef)(computedValue);
const isInteractive = !(isDisabled || isReadOnly);
const tenSteps = (max - min) / 10;
const oneStep = step || (max - min) / 100;
const value = computedValue.map((val) => (0, import_number_utils3.clampValue)(val, min, max));
const prevValue = (0, import_react7.useRef)(value);
const distanceBetweenThumbs = minStepsBetweenThumbs * step;
const valueBounds = getValueBounds(value, min, max, distanceBetweenThumbs);
const reversedValue = value.map((val) => max - val + min);
const thumbValues = isReversed ? reversedValue : value;
const thumbPercents = thumbValues.map((val) => valueToPercent(val, min, max));
const isVertical = orientation === "vertical";
const trackRef = (0, import_react7.useRef)(null);
const rootRef = (0, import_react7.useRef)(null);
const reactId = (0, import_react7.useId)();
const uuid = idProp != null ? idProp : reactId;
const ids = getIds(uuid);
const thumbSizes = (0, import_use_watch_element_size.useWatchElementsSize)({
getNodes() {
const rootNode = rootRef.current;
const thumbNodes = rootNode == null ? void 0 : rootNode.querySelectorAll("[role=slider]");
return thumbNodes ? Array.from(thumbNodes) : [];
}
});
const { isDragging, onDraggingStart, onDraggingEnd } = use_handle_dragging_default();
const {
isFocused,
onBlur: onInputBlur,
onFocus: onInputFocus
} = use_handle_focus_default();
const sliderStates = (0, import_react7.useMemo)(
() => ({
eventSource: null,
value,
valueBounds,
getThumbMaxValue: (index) => valueBounds[index].max,
getThumbMinValue: (index) => valueBounds[index].min,
getThumbPercent: (index) => thumbPercents[index],
isFocused,
isDragging,
focusThumbOnChange,
isDisabled,
isInteractive,
isReversed,
isVertical,
max,
min,
orientation,
step: oneStep,
tenSteps,
distanceBetweenThumbs
}),
[
distanceBetweenThumbs,
focusThumbOnChange,
isDisabled,
isDragging,
isFocused,
isInteractive,
isReversed,
isVertical,
max,
min,
oneStep,
orientation,
tenSteps,
thumbPercents,
value,
valueBounds
]
);
const { onFocusThumb } = use_handle_focus_thumb_default({
activeIndex,
focusThumbOnChange,
ids,
rootRef
});
const actions = (0, import_react7.useMemo)(
() => ({
setValueAtIndex(index, value2) {
if (!sliderStates.isInteractive)
return;
const bounds = sliderStates.valueBounds[index];
value2 = parseFloat(roundValueToStep(value2, bounds.min, oneStep));
value2 = (0, import_number_utils3.clampValue)(value2, bounds.min, bounds.max);
const next = [...sliderStates.value];
next[index] = value2;
setComputedValue(next);
},
setActiveIndex,
stepUp(index, step2 = oneStep) {
const bounds = [...sliderStates.valueBounds];
const values = [...sliderStates.value];
const valueAtIndex = sliderStates.value[index];
const next = sliderStates.isReversed ? valueAtIndex - step2 : valueAtIndex + step2;
const { index: newIndex, value: value2 } = getThumbStateOnChange({
bounds,
values,
pointerValue: next,
index,
isDisableSwap,
prevValue: prevValue.current,
step: sliderStates.step,
distanceBetweenThumbs
});
actions.setValue(value2);
setActiveIndex(newIndex);
onFocusThumb(newIndex);
},
stepDown(index, step2 = oneStep) {
const bounds = [...sliderStates.valueBounds];
const values = [...sliderStates.value];
const valueAtIndex = sliderStates.value[index];
const next = sliderStates.isReversed ? valueAtIndex + step2 : valueAtIndex - step2;
const { index: newIndex, value: value2 } = getThumbStateOnChange({
bounds,
values,
pointerValue: next,
index,
isDisableSwap,
prevValue: prevValue.current,
step: sliderStates.step,
distanceBetweenThumbs
});
actions.setValue(value2);
setActiveIndex(newIndex);
onFocusThumb(newIndex);
},
setValue: setComputedValue,
reset() {
setComputedValue(initialValue.current);
}
}),
[
distanceBetweenThumbs,
isDisableSwap,
onFocusThumb,
oneStep,
setComputedValue,
sliderStates.isInteractive,
sliderStates.isReversed,
sliderStates.step,
sliderStates.value,
sliderStates.valueBounds
]
);
const {
getThumbStyle,
innerTrackStyle,
getMarkerStyle,
rootStyle,
trackStyle
} = use_handle_style_default({
isReversed: sliderStates.isReversed,
orientation: sliderStates.orientation,
thumbPercents,
thumbSizes
});
use_handle_pan_event_default({
onChangeEnd,
onChangeStart,
onDraggingEnd,
onDraggingStart,
onFocusThumb,
rootRef,
sliderStates,
activeIndex,
trackRef,
actions,
isDisableSwap,
prevValue,
distanceBetweenThumbs
});
const onThumbKeyUp = (0, import_react7.useCallback)(() => {
prevValue.current = sliderStates.value;
}, [sliderStates.value]);
const onThumbKeyDown = (0, import_react7.useCallback)(
(event) => {
const keyMap = {
ArrowRight: () => actions.stepUp(activeIndex),
ArrowUp: () => actions.stepUp(activeIndex),
ArrowLeft: () => actions.stepDown(activeIndex),
ArrowDown: () => actions.stepDown(activeIndex),
PageUp: () => actions.stepUp(activeIndex, tenSteps),
PageDown: () => actions.stepDown(activeIndex, tenSteps),
Home: () => {
const { min: value2 } = valueBounds[activeIndex];
actions.setValueAtIndex(activeIndex, value2);
},
End: () => {
const { max: value2 } = valueBounds[activeIndex];
actions.setValueAtIndex(activeIndex, value2);
}
};
const action = keyMap[event.key];
if (action) {
event.preventDefault();
event.stopPropagation();
action(event);
sliderStates.eventSource = "keyboard";
}
},
[actions, activeIndex, sliderStates, tenSteps, valueBounds]
);
const getRootProps = (0, import_react7.useCallback)(
(props2 = {}, forwardedRef = null) => ({
...resRootProps,
...props2,
id: ids.root,
ref: (0, import_dom_utils.mergeRefs)(forwardedRef, rootRef),
tabIndex: -1,
style: { ...props2.style, ...rootStyle },
"aria-disabled": (0, import_dom_utils.ariaAttr)(isDisabled),
"data-focused": (0, import_dom_utils.dataAttr)(isFocused)
}),
[ids.root, isDisabled, isFocused, resRootProps, rootStyle]
);
const getTrackProps = (0, import_react7.useCallback)(
(props2 = {}, forwardedRef = null) => ({
...props2,
ref: (0, import_dom_utils.mergeRefs)(forwardedRef, trackRef),
id: ids.track,
"data-disabled": (0, import_dom_utils.dataAttr)(isDisabled),
style: { ...props2.style, ...trackStyle }
}),
[ids.track, isDisabled, trackStyle]
);
const getInnerTrackProps = (0, import_react7.useCallback)(
(props2 = {}, forwardedRef = null) => ({
...props2,
ref: forwardedRef,
id: ids.innerTrack,
style: { ...props2.style, ...innerTrackStyle }
}),
[ids.innerTrack, innerTrackStyle]
);
const getThumbProps = (0, import_react7.useCallback)(
(props2, forwardedRef = null) => {
var _a;
const { index, style, onKeyDown, onKeyUp, onFocus, onBlur, ...resProps } = props2;
const valueAtIndex = sliderStates.value[index];
const bounds = sliderStates.valueBounds[index];
if ((0, import_function_utils2.isTrullyEmpty)(valueAtIndex))
throw new TypeError(
`[range-slider > thumb] Cannot find value at index \`${index}\`. The \`value\` or \`defaultValue\` length is : ${sliderStates.value.length}`
);
return {
...resProps,
ref: forwardedRef,
role: "slider",
...isInteractive && { tabIndex: 0 },
id: ids.getThumb(index),
"data-active": (0, import_dom_utils.dataAttr)(isDragging && activeIndex === index),
"aria-valuetext": (_a = getAriaValueText == null ? void 0 : getAriaValueText(valueAtIndex)) != null ? _a : ariaValueText == null ? void 0 : ariaValueText[index],
"aria-valuemin": bounds.min,
"aria-valuemax": bounds.max,
"aria-valuenow": valueAtIndex,
"aria-orientation": orientation,
"aria-disabled": (0, import_dom_utils.ariaAttr)(isDisabled),
"aria-readonly": (0, import_dom_utils.ariaAttr)(isReadOnly),
"aria-label": ariaLabel == null ? void 0 : ariaLabel[index],
...!(ariaLabel == null ? void 0 : ariaLabel[index]) && {
"aria-labelledby": ariaLabelledBy == null ? void 0 : ariaLabelledBy[index]
},
style: { ...style, ...getThumbStyle(index) },
onKeyUp: (0, import_function_utils2.callAllFn)(onThumbKeyUp, onKeyUp),
onKeyDown: (0, import_function_utils2.callAllFn)(onThumbKeyDown, onKeyDown),
onFocus: (0, import_function_utils2.callAllFn)(onInputFocus, () => setActiveIndex(index), onFocus),
onBlur: (0, import_function_utils2.callAllFn)(onInputBlur, () => setActiveIndex(-1), onBlur)
};
},
[
activeIndex,
ariaLabel,
ariaLabelledBy,
ariaValueText,
getAriaValueText,
getThumbStyle,
ids,
isDisabled,
isDragging,
isInteractive,
isReadOnly,
onInputBlur,
onInputFocus,
onThumbKeyDown,
onThumbKeyUp,
orientation,
sliderStates.value,
sliderStates.valueBounds
]
);
const getOutputProps = (0, import_react7.useCallback)(
(props2 = {}, forwardedRef = null) => ({
...props2,
ref: forwardedRef,
id: ids.output,
htmlFor: value.map((_v, i) => ids.getThumb(i)).join(" "),
"aria-live": "off"
}),
[ids, value]
);
const getMarkerProps = (0, import_react7.useCallback)(
(props2, forwardedRef = null) => {
const { value: markerValue, style, ...resProps } = props2;
const isInRange = !(markerValue < sliderStates.min || markerValue || sliderStates.max);
const isHighlighted = markerValue >= sliderStates.value[0] && markerValue <= sliderStates.value[sliderStates.value.length - 1];
const markerPercent = valueToPercent(markerValue, min, max);
const percent = isReversed ? 100 - markerPercent : markerPercent;
return {
...resProps,
ref: forwardedRef,
role: "presentation",
"aria-hidden": true,
"data-disabled": (0, import_dom_utils.dataAttr)(isDisabled),
"data-invalid": (0, import_dom_utils.dataAttr)(!isInRange),
"data-highlighted": (0, import_dom_utils.dataAttr)(isHighlighted),
style: {
...style,
...getMarkerStyle(percent)
}
};
},
[
getMarkerStyle,
isDisabled,
isReversed,
max,
min,
sliderStates.max,
sliderStates.min,
sliderStates.value
]
);
const getInputProps = (0, import_react7.useCallback)(
(props2, forwardedRef = null) => {
const { index, ...resProps } = props2;
return {
...resProps,
ref: forwardedRef,
id: ids.getInput(index),
type: "hidden",
value: sliderStates.value[index],
name: name ? Array.isArray(name) ? name[index] : `${name}-${index}` : `${ids.getInput(index)}-${index}`
};
},
[ids, name, sliderStates.value]
);
(0, import_react7.useEffect)(() => {
if (sliderStates.eventSource === "keyboard") {
onChangeEnd == null ? void 0 : onChangeEnd(sliderStates.value);
}
}, [value, onChangeEnd, sliderStates.eventSource, sliderStates.value]);
return {
state: sliderStates,
actions,
getRootProps,
getTrackProps,
getInnerTrackProps,
getThumbProps,
getMarkerProps,
getInputProps,
getOutputProps
};
}
// src/styles.ts
var import_react8 = require("@emotion/react");
var rootSliderCx = import_react8.css`
--slider-track-size: 0.5rem;
--slider-thumb-size: 1rem;
width: fit-content;
`;
var rootSliderVerticalTrackCx = import_react8.css`
width: var(--slider-track-size);
`;
var rootSliderHorizontalTrackCx = import_react8.css`
height: var(--slider-track-size);
`;
var rootSliderTrackCx = import_react8.css`
overflow: hidden;
border-radius: var(--corner-3xl);
background-color: var(--colors-neutrals-40);
`;
var rootSliderThumbCx = import_react8.css`
z-index: 1;
width: var(--slider-thumb-size);
height: var(--slider-thumb-size);
border-radius: var(--corner-3xl);
background-color: var(--colors-neutrals-10);
box-shadow: var(--shadows-md);
display: flex;
align-items: center;
justify-content: center;
`;
var rootSliderInnerTrackCx = import_react8.css`
background-color: var(--colors-primary-30);
height: inherit;
width: inherit;
`;
// src/range-slider/RangeSliderProvider.tsx
var import_context = require("@julo-ui/context");
var [RangeSliderProvider, useRangeSliderContext] = (0, import_context.createContext)({
name: "SliderContext",
hookName: "useRangeSliderContext",
providerName: "<RangeSliderProvider />"
});
// src/range-slider/RangeSlider.tsx
var import_jsx_runtime = require("react/jsx-runtime");
var RangeSlider = (0, import_system.forwardRef)((props, ref) => {
const {
children,
className,
orientation = "horizontal",
...resProps
} = props;
const { getRootProps, ...rangeSliderContext } = useRangeSlider({
direction: "ltr",
orientation,
...resProps
});
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RangeSliderProvider, { value: rangeSliderContext, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_system.julo.div,
{
className: (0, import_system.cx)("julo-range-slider", className),
...getRootProps({}, ref),
__css: [rootSliderCx, rangeSliderCx],
children
}
) });
});
RangeSlider.displayName = "RangeSlider";
var RangeSlider_default = RangeSlider;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {});