UNPKG

@zag-js/numeric-range

Version:
145 lines (142 loc) 5.39 kB
'use strict'; // src/index.ts function getMinValueAtIndex(index, values, minValue) { return index === 0 ? minValue : values[index - 1]; } function getMaxValueAtIndex(index, values, maxValue) { return index === values.length - 1 ? maxValue : values[index + 1]; } function isValueAtMax(value, maxValue) { return value >= maxValue; } function isValueAtMin(value, minValue) { return value <= minValue; } function isValueWithinRange(value, minValue, maxValue) { return value >= minValue && value <= maxValue; } function getRoundedValue(value, minValue, step) { return Math.round((value - minValue) / step) * step + minValue; } function clampValue(value, minValue, maxValue) { return Math.min(Math.max(value, minValue), maxValue); } function getValuePercent(value, minValue, maxValue) { return (value - minValue) / (maxValue - minValue); } function getPercentValue(percent, minValue, maxValue, step) { const value = percent * (maxValue - minValue) + minValue; const roundedValue = getRoundedValue(value, minValue, step); return clampValue(roundedValue, minValue, maxValue); } function roundToStepPrecision(value, step) { let roundedValue = value; let stepString = step.toString(); let pointIndex = stepString.indexOf("."); let precision = pointIndex >= 0 ? stepString.length - pointIndex : 0; if (precision > 0) { let pow = Math.pow(10, precision); roundedValue = Math.round(roundedValue * pow) / pow; } return roundedValue; } function snapValueToStep(value, min, max, step) { min = Number(min); max = Number(max); let remainder = (value - (isNaN(min) ? 0 : min)) % step; let snappedValue = roundToStepPrecision( Math.abs(remainder) * 2 >= step ? value + Math.sign(remainder) * (step - Math.abs(remainder)) : value - remainder, step ); if (!isNaN(min)) { if (snappedValue < min) { snappedValue = min; } else if (!isNaN(max) && snappedValue > max) { snappedValue = min + Math.floor(roundToStepPrecision((max - min) / step, step)) * step; } } else if (!isNaN(max) && snappedValue > max) { snappedValue = Math.floor(roundToStepPrecision(max / step, step)) * step; } snappedValue = roundToStepPrecision(snappedValue, step); return snappedValue; } function setValueAtIndex(values, index, value) { if (values[index] === value) return values; return [...values.slice(0, index), value, ...values.slice(index + 1)]; } function getValueSetterAtIndex(index, ctx) { const minValueAtIndex = getMinValueAtIndex(index, ctx.values, ctx.min); const maxValueAtIndex = getMaxValueAtIndex(index, ctx.values, ctx.max); let nextValues = ctx.values.slice(); return function setValue(value) { let nextValue = snapValueToStep(value, minValueAtIndex, maxValueAtIndex, ctx.step); nextValues = setValueAtIndex(nextValues, index, value); nextValues[index] = nextValue; return nextValues; }; } function getNextStepValue(index, ctx) { const nextValue = ctx.values[index] + ctx.step; return getValueSetterAtIndex(index, ctx)(nextValue); } function getPreviousStepValue(index, ctx) { const nextValue = ctx.values[index] - ctx.step; return getValueSetterAtIndex(index, ctx)(nextValue); } function getClosestValueIndex(values, targetValue) { let targetIndex = values.findIndex((value) => targetValue - value < 0); if (targetIndex === 0) { return targetIndex; } if (targetIndex === -1) { return values.length - 1; } let valueBefore = values[targetIndex - 1]; let valueAfter = values[targetIndex]; if (Math.abs(valueBefore - targetValue) < Math.abs(valueAfter - targetValue)) { return targetIndex - 1; } return targetIndex; } function getValueRanges(values, minValue, maxValue, gap) { return values.map((value, index) => { const min = index === 0 ? minValue : values[index - 1] + gap; const max = index === values.length - 1 ? maxValue : values[index + 1] - gap; return { min, max, value }; }); } function getValueTransformer(valueA, valueB) { const input = { min: valueA[0], max: valueA[1] }; const output = { min: valueB[0], max: valueB[1] }; return function getValue(value) { if (input.min === input.max || output.min === output.max) return output.min; const ratio = (output.max - output.min) / (input.max - input.min); return output.min + ratio * (value - input.min); }; } function toFixedNumber(value, digits = 0, base = 10) { const pow = Math.pow(base, digits); return Math.round(value * pow) / pow; } function mod(value, modulo) { return (value % modulo + modulo) % modulo; } exports.clampValue = clampValue; exports.getClosestValueIndex = getClosestValueIndex; exports.getMaxValueAtIndex = getMaxValueAtIndex; exports.getMinValueAtIndex = getMinValueAtIndex; exports.getNextStepValue = getNextStepValue; exports.getPercentValue = getPercentValue; exports.getPreviousStepValue = getPreviousStepValue; exports.getRoundedValue = getRoundedValue; exports.getValuePercent = getValuePercent; exports.getValueRanges = getValueRanges; exports.getValueSetterAtIndex = getValueSetterAtIndex; exports.getValueTransformer = getValueTransformer; exports.isValueAtMax = isValueAtMax; exports.isValueAtMin = isValueAtMin; exports.isValueWithinRange = isValueWithinRange; exports.mod = mod; exports.roundToStepPrecision = roundToStepPrecision; exports.snapValueToStep = snapValueToStep; exports.toFixedNumber = toFixedNumber;