UNPKG

@base-ui-components/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

134 lines (133 loc) 5.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveThumbCollision = resolveThumbCollision; var _clamp = require("../../utils/clamp"); var _getPushedThumbValues = require("./getPushedThumbValues"); function resolveThumbCollision({ behavior, values, currentValues, initialValues, pressedIndex, nextValue, min, max, step, minStepsBetweenValues }) { const activeValues = currentValues ?? values; const baselineValues = initialValues ?? values; const range = activeValues.length > 1; if (!range) { return { value: nextValue, thumbIndex: 0, didSwap: false }; } const minValueDifference = step * minStepsBetweenValues; switch (behavior) { case 'swap': { const pressedInitialValue = activeValues[pressedIndex]; const epsilon = 1e-7; const candidateValues = activeValues.slice(); const previousNeighbor = candidateValues[pressedIndex - 1]; const nextNeighbor = candidateValues[pressedIndex + 1]; const lowerBound = previousNeighbor != null ? previousNeighbor + minValueDifference : min; const upperBound = nextNeighbor != null ? nextNeighbor - minValueDifference : max; const constrainedValue = (0, _clamp.clamp)(nextValue, lowerBound, upperBound); const pressedValueAfterClamp = Number(constrainedValue.toFixed(12)); candidateValues[pressedIndex] = pressedValueAfterClamp; const movingForward = nextValue > pressedInitialValue; const movingBackward = nextValue < pressedInitialValue; const shouldSwapForward = movingForward && nextNeighbor != null && nextValue >= nextNeighbor - epsilon; const shouldSwapBackward = movingBackward && previousNeighbor != null && nextValue <= previousNeighbor + epsilon; if (!shouldSwapForward && !shouldSwapBackward) { return { value: candidateValues, thumbIndex: pressedIndex, didSwap: false }; } const targetIndex = shouldSwapForward ? pressedIndex + 1 : pressedIndex - 1; const initialValuesForPush = candidateValues.map((_, index) => { if (index === pressedIndex) { return pressedValueAfterClamp; } const baseline = baselineValues[index]; if (baseline != null) { return baseline; } return activeValues[index]; }); let nextValueForTarget = nextValue; if (shouldSwapForward) { nextValueForTarget = Math.max(nextValue, candidateValues[targetIndex]); } else { nextValueForTarget = Math.min(nextValue, candidateValues[targetIndex]); } const adjustedValues = (0, _getPushedThumbValues.getPushedThumbValues)({ values: candidateValues, index: targetIndex, nextValue: nextValueForTarget, min, max, step, minStepsBetweenValues, initialValues: initialValuesForPush }); const neighborIndex = shouldSwapForward ? targetIndex - 1 : targetIndex + 1; if (neighborIndex >= 0 && neighborIndex < adjustedValues.length) { const previousValue = adjustedValues[neighborIndex - 1]; const nextValueAfter = adjustedValues[neighborIndex + 1]; let neighborLowerBound = previousValue != null ? previousValue + minValueDifference : min; neighborLowerBound = Math.max(neighborLowerBound, min + neighborIndex * minValueDifference); let neighborUpperBound = nextValueAfter != null ? nextValueAfter - minValueDifference : max; neighborUpperBound = Math.min(neighborUpperBound, max - (adjustedValues.length - 1 - neighborIndex) * minValueDifference); const restoredValue = (0, _clamp.clamp)(pressedValueAfterClamp, neighborLowerBound, neighborUpperBound); adjustedValues[neighborIndex] = Number(restoredValue.toFixed(12)); } return { value: adjustedValues, thumbIndex: targetIndex, didSwap: true }; } case 'push': { const nextValues = (0, _getPushedThumbValues.getPushedThumbValues)({ values: activeValues, index: pressedIndex, nextValue, min, max, step, minStepsBetweenValues }); return { value: nextValues, thumbIndex: pressedIndex, didSwap: false }; } case 'none': default: { const candidateValues = activeValues.slice(); const previousNeighbor = candidateValues[pressedIndex - 1]; const nextNeighbor = candidateValues[pressedIndex + 1]; const lowerBound = previousNeighbor != null ? previousNeighbor + minValueDifference : min; const upperBound = nextNeighbor != null ? nextNeighbor - minValueDifference : max; const constrainedValue = (0, _clamp.clamp)(nextValue, lowerBound, upperBound); candidateValues[pressedIndex] = Number(constrainedValue.toFixed(12)); return { value: candidateValues, thumbIndex: pressedIndex, didSwap: false }; } } }