@julo-ui/sliders
Version:
A React Slider component that implements input[type='range']
133 lines (130 loc) • 3.81 kB
JavaScript
import {
getThumbStateOnChange
} from "./chunk-XX7IAI35.mjs";
import {
isMouseEvent,
percentToValue
} from "./chunk-Y2VS5NAR.mjs";
// src/range-slider/usecase/use-handle-pan-event.ts
import { useCallback } from "react";
import { usePanEvent } from "@chakra-ui/react-use-pan-event";
import { _noop } from "@julo-ui/function-utils";
function useHandlePanEvent(options) {
const {
rootRef,
trackRef,
sliderStates,
activeIndex,
actions,
onFocusThumb,
onDraggingStart,
onDraggingEnd,
onChangeStart = _noop,
onChangeEnd = _noop,
isDisableSwap,
prevValue,
distanceBetweenThumbs
} = options;
const getValueFromPointer = 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 = 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 = 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
]
);
usePanEvent(rootRef, {
onPanSessionStart,
onPanSessionEnd() {
if (!sliderStates.isInteractive)
return;
onDraggingEnd();
prevValue.current = sliderStates.value;
onChangeEnd(sliderStates.value);
},
onPan
});
}
var use_handle_pan_event_default = useHandlePanEvent;
export {
use_handle_pan_event_default
};