UNPKG

@gfazioli/mantine-split-pane

Version:

A Mantine 9 React component for resizable split pane layouts with 7 resizer variants, context-based prop inheritance, responsive orientation, and dynamic pane generation.

108 lines (106 loc) 3.6 kB
'use client'; function clamp(value, min, max) { return Math.min(Math.max(value, min), max); } const DEFAULT_SNAP_TOLERANCE = 10; const PERCENTAGE_PATTERN = /^(\d+(?:\.\d+)?)%$/; function isValidSnapPoint(value) { if (typeof value === "number") { return Number.isFinite(value) && value >= 0; } if (typeof value === "string") { const match = value.trim().match(PERCENTAGE_PATTERN); return match !== null && Number.isFinite(parseFloat(match[1])); } return false; } function resolveSnapPoint(point, totalSize) { if (typeof point === "number") { return point; } const match = point.trim().match(PERCENTAGE_PATTERN); if (!match) { return Number.NaN; } return parseFloat(match[1]) / 100 * totalSize; } function normalizeSnapPoints({ snapPoints, snapTolerance }) { const normalizedTolerance = Math.max(0, snapTolerance ?? DEFAULT_SNAP_TOLERANCE); const raw = Array.isArray(snapPoints) ? snapPoints : []; const valid = raw.filter(isValidSnapPoint); const seen = /* @__PURE__ */ new Set(); const dedup = []; for (const point of valid) { const key = typeof point === "string" ? point.trim() : String(point); if (!seen.has(key)) { seen.add(key); dedup.push(typeof point === "string" ? point.trim() : point); } } return { snapPoints: dedup, snapTolerance: normalizedTolerance }; } function findNearestSnap(value, points, tolerance) { let snappedValue = value; let snappedPoint = null; let shortestDistance = Infinity; for (const point of points) { const distance = Math.abs(value - point); if (distance <= tolerance && (distance < shortestDistance || distance === shortestDistance && point < snappedValue)) { snappedValue = point; snappedPoint = point; shortestDistance = distance; } } return { value: snappedValue, point: snappedPoint }; } function calculateSnappedPaneSizes({ beforeSize, afterSize, delta, minBeforeSize, maxBeforeSize, minAfterSize, maxAfterSize, snapPoints, snapTolerance, snapFrom = "before" }) { const totalSize = beforeSize + afterSize; const safeMinBeforeSize = Math.max(0, minBeforeSize ?? 0); const safeMaxBeforeSize = maxBeforeSize ?? totalSize; const safeMinAfterSize = Math.max(0, minAfterSize ?? 0); const safeMaxAfterSize = maxAfterSize ?? totalSize; const minAllowedBeforeSize = Math.max(safeMinBeforeSize, totalSize - safeMaxAfterSize, 0); const maxAllowedBeforeSize = Math.min(safeMaxBeforeSize, totalSize - safeMinAfterSize, totalSize); if (minAllowedBeforeSize > maxAllowedBeforeSize) { return { beforeSize, afterSize, snappedPoint: null }; } let nextBeforeSize = clamp(beforeSize + delta, minAllowedBeforeSize, maxAllowedBeforeSize); let snappedPoint = null; if (snapPoints.length > 0) { const resolved = snapPoints.map((point) => { const asBefore = resolveSnapPoint(point, totalSize); return snapFrom === "after" ? totalSize - asBefore : asBefore; }).filter( (point) => Number.isFinite(point) && point >= minAllowedBeforeSize && point <= maxAllowedBeforeSize ); const match = findNearestSnap(nextBeforeSize, resolved, snapTolerance); nextBeforeSize = match.value; if (match.point !== null) { snappedPoint = snapFrom === "after" ? totalSize - match.point : match.point; } } return { beforeSize: nextBeforeSize, afterSize: totalSize - nextBeforeSize, snappedPoint }; } export { DEFAULT_SNAP_TOLERANCE, calculateSnappedPaneSizes, isValidSnapPoint, normalizeSnapPoints, resolveSnapPoint }; //# sourceMappingURL=snap.mjs.map