import type * as React from 'react'; import { rescale } from '../../helpers/math'; import type { InternalDraggingType, InternalValueState } from './types'; export const toPercent = (v: number, min: number, max: number): number => ((v - min) / (max - min)) * 100; export const offsetToValue = ( startX: number, width: number, min: number, max: number, step?: number, ): number => { return rescale(startX, [0, width], [min, max], { step }); }; const restrictValueByMinMax = (value: number, min: number, max: number) => { if (value < min) { return min; } if (value > max) { return max; } return value; }; export const updateInternalStateValue = ( prevValue: InternalValueState, nextValue: number, min: number, max: number, dragging: InternalDraggingType | null, ): InternalValueState => { const [prevStartValue, prevEndValue] = prevValue; if (prevEndValue === null) { return [restrictValueByMinMax(nextValue, min, max), null]; } switch (dragging) { case 'start': return nextValue > prevEndValue ? [prevEndValue, prevEndValue] : [restrictValueByMinMax(nextValue, min, max), prevEndValue]; case 'end': return nextValue < prevStartValue ? [prevStartValue, prevStartValue] : [prevStartValue, restrictValueByMinMax(nextValue, min, max)]; case null: default: return prevValue; } }; export const updateInternalStateValueByNativeChange = ( prevValue: InternalValueState, nextValue: number, dragging: InternalDraggingType | null, ): InternalValueState => { const [prevStartValue, prevEndValue] = prevValue; switch (dragging) { case 'start': return [nextValue, prevEndValue]; case 'end': return [prevStartValue, nextValue]; case null: default: return prevValue; } }; export function isMultipleValues(value: InternalValueState): value is [number, number] { return value[1] !== null; } export const snapDirection = ( prevValue: InternalValueState, nextValue: number, type: InternalDraggingType | null, ): 'start' | 'end' => { if (type === 'start') { return 'start'; } if (type === 'end') { return 'end'; } const [startRaw, endRaw] = prevValue; /* startRaw и endRaw могут быть равны, поэтому насильно добавляем разницу. */ const FORCE_DIFF_VALUE = 0.1; const start = endRaw !== null ? startRaw - FORCE_DIFF_VALUE : startRaw; const end = endRaw !== null ? endRaw + FORCE_DIFF_VALUE : 0; return Math.abs(start - nextValue) <= Math.abs(end - nextValue) ? 'start' : 'end'; }; export const getDraggingTypeByTargetDataset = ( target: T, ): 'start' | 'end' | null => { if (target) { if (target.dataset.type === 'start') { return 'start'; } if (target.dataset.type === 'end') { return 'end'; } } return null; }; const resetProps = { 'aria-label': undefined, 'aria-valuetext': undefined, 'aria-labelledby': undefined, }; export const extractSliderAriaAttributesFromRestProps = ( restProps: T, ): T & { ariaLabel: string | undefined; ariaValueText: string | undefined; ariaLabelledBy: string | undefined; } => { const ariaLabel = restProps['aria-label']; const ariaValueText = restProps['aria-valuetext']; const ariaLabelledBy = restProps['aria-labelledby']; return { ...restProps, ...resetProps, ariaLabel, ariaValueText, ariaLabelledBy }; };