{"version":3,"file":"constraints.mjs","sources":["../../../../../src/gestures/drag/utils/constraints.ts"],"sourcesContent":["import { calcLength, mixNumber, type DragElastic, type ResolvedConstraints } from \"motion-dom\"\nimport {\n Axis,\n BoundingBox,\n Box,\n progress as calcProgress,\n clamp,\n Point,\n} from \"motion-utils\"\n\n/**\n * Apply constraints to a point. These constraints are both physical along an\n * axis, and an elastic factor that determines how much to constrain the point\n * by if it does lie outside the defined parameters.\n */\nexport function applyConstraints(\n point: number,\n { min, max }: Partial,\n elastic?: Axis\n): number {\n if (min !== undefined && point < min) {\n // If we have a min point defined, and this is outside of that, constrain\n point = elastic\n ? mixNumber(min, point, elastic.min)\n : Math.max(point, min)\n } else if (max !== undefined && point > max) {\n // If we have a max point defined, and this is outside of that, constrain\n point = elastic\n ? mixNumber(max, point, elastic.max)\n : Math.min(point, max)\n }\n\n return point\n}\n\n/**\n * Calculates a min projection point based on a pointer, pointer progress\n * within the drag target, and constraints.\n *\n * For instance if an element was 100px width, we were dragging from 0.25\n * along this axis, the pointer is at 200px, and there were no constraints,\n * we would calculate a min projection point of 175px.\n */\nexport function calcConstrainedMinPoint(\n point: number,\n length: number,\n progress: number,\n constraints?: Partial,\n elastic?: Axis\n): number {\n // Calculate a min point for this axis and apply it to the current pointer\n const min = point - length * progress\n\n return constraints ? applyConstraints(min, constraints, elastic) : min\n}\n\n/**\n * Calculate constraints in terms of the viewport when defined relatively to the\n * measured axis. This is measured from the nearest edge, so a max constraint of 200\n * on an axis with a max value of 300 would return a constraint of 500 - axis length\n */\nexport function calcRelativeAxisConstraints(\n axis: Axis,\n min?: number,\n max?: number\n): Partial {\n return {\n min: min !== undefined ? axis.min + min : undefined,\n max:\n max !== undefined\n ? axis.max + max - (axis.max - axis.min)\n : undefined,\n }\n}\n\n/**\n * Calculate constraints in terms of the viewport when\n * defined relatively to the measured bounding box.\n */\nexport function calcRelativeConstraints(\n layoutBox: Box,\n { top, left, bottom, right }: Partial\n): ResolvedConstraints {\n return {\n x: calcRelativeAxisConstraints(layoutBox.x, left, right),\n y: calcRelativeAxisConstraints(layoutBox.y, top, bottom),\n }\n}\n\n/**\n * Calculate viewport constraints when defined as another viewport-relative axis\n */\nexport function calcViewportAxisConstraints(\n layoutAxis: Axis,\n constraintsAxis: Axis\n) {\n let min = constraintsAxis.min - layoutAxis.min\n let max = constraintsAxis.max - layoutAxis.max\n\n // If the constraints axis is actually smaller than the layout axis then we can\n // flip the constraints\n if (\n constraintsAxis.max - constraintsAxis.min <\n layoutAxis.max - layoutAxis.min\n ) {\n ;[min, max] = [max, min]\n }\n\n return { min, max }\n}\n\n/**\n * Calculate viewport constraints when defined as another viewport-relative box\n */\nexport function calcViewportConstraints(layoutBox: Box, constraintsBox: Box) {\n return {\n x: calcViewportAxisConstraints(layoutBox.x, constraintsBox.x),\n y: calcViewportAxisConstraints(layoutBox.y, constraintsBox.y),\n }\n}\n\n/**\n * Calculate a transform origin relative to the source axis, between 0-1, that results\n * in an asthetically pleasing scale/transform needed to project from source to target.\n */\nexport function calcOrigin(source: Axis, target: Axis): number {\n let origin = 0.5\n const sourceLength = calcLength(source)\n const targetLength = calcLength(target)\n\n if (targetLength > sourceLength) {\n origin = calcProgress(target.min, target.max - sourceLength, source.min)\n } else if (sourceLength > targetLength) {\n origin = calcProgress(source.min, source.max - targetLength, target.min)\n }\n\n return clamp(0, 1, origin)\n}\n\n/**\n * Calculate the relative progress of one constraints box relative to another.\n * Imagine a page scroll bar. At the top, this would return 0, at the bottom, 1.\n * Anywhere in-between, a value between 0 and 1.\n *\n * This also handles flipped constraints, for instance a draggable container within\n * a smaller viewport like a scrollable view.\n */\nexport function calcProgressWithinConstraints(\n layoutBox: Box,\n constraintsBox: Box\n): Point {\n return {\n x: calcOrigin(layoutBox.x, constraintsBox.x),\n y: calcOrigin(layoutBox.y, constraintsBox.y),\n }\n}\n\n/**\n * Calculate the an axis position based on two axes and a progress value.\n */\nexport function calcPositionFromProgress(\n axis: Axis,\n constraints: Axis,\n progress: number\n): Axis {\n const axisLength = axis.max - axis.min\n const min = mixNumber(\n constraints.min,\n constraints.max - axisLength,\n progress\n )\n return { min, max: min + axisLength }\n}\n\n/**\n * Rebase the calculated viewport constraints relative to the layout.min point.\n */\nexport function rebaseAxisConstraints(\n layout: Axis,\n constraints: Partial\n): Partial {\n const relativeConstraints: Partial = {}\n\n if (constraints.min !== undefined) {\n relativeConstraints.min = constraints.min - layout.min\n }\n\n if (constraints.max !== undefined) {\n relativeConstraints.max = constraints.max - layout.min\n }\n\n return relativeConstraints\n}\n\nexport const defaultElastic = 0.35\n/**\n * Accepts a dragElastic prop and returns resolved elastic values for each axis.\n */\nexport function resolveDragElastic(\n dragElastic: DragElastic = defaultElastic\n): Box {\n if (dragElastic === false) {\n dragElastic = 0\n } else if (dragElastic === true) {\n dragElastic = defaultElastic\n }\n\n return {\n x: resolveAxisElastic(dragElastic, \"left\", \"right\"),\n y: resolveAxisElastic(dragElastic, \"top\", \"bottom\"),\n }\n}\n\nexport function resolveAxisElastic(\n dragElastic: DragElastic,\n minLabel: string,\n maxLabel: string\n): Axis {\n return {\n min: resolvePointElastic(dragElastic, minLabel),\n max: resolvePointElastic(dragElastic, maxLabel),\n }\n}\n\nexport function resolvePointElastic(\n dragElastic: DragElastic,\n label: string\n): number {\n return typeof dragElastic === \"number\"\n ? dragElastic\n : dragElastic[label as keyof typeof dragElastic] || 0\n}\n"],"names":["calcProgress"],"mappings":"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"}