UNPKG

framer-motion

Version:

A simple and powerful JavaScript animation library

96 lines (93 loc) 3.68 kB
import { mixNumber } from 'motion-dom'; import { moveItem } from 'motion-utils'; function checkReorder(order, value, offset, velocity, axis, direction = "ltr") { const index = order.findIndex((item) => item.value === value); if (index === -1) return order; if (axis === "xy") { const { layout } = order[index]; const center = { x: mixNumber(layout.x.min, layout.x.max, 0.5) + offset.x, y: mixNumber(layout.y.min, layout.y.max, 0.5) + offset.y, }; const lines = getLines(order); const sourceLine = lines.find((line) => line.items.includes(order[index])); const targetLine = lines.reduce((closest, line) => distanceToLine(center.y, line) < distanceToLine(center.y, closest) ? line : closest); if (targetLine !== sourceLine) { return moveToLine(order, index, center.x, targetLine, direction); } const currentDistance = distanceToBox(center, layout); let target = -1; let targetDistance = currentDistance; order.forEach((item, targetIndex) => { if (targetIndex === index) return; const distance = distanceToBox(center, item.layout); if (distance < targetDistance) { target = targetIndex; targetDistance = distance; } }); return target === -1 ? order : moveItem(order, index, index + Math.sign(target - index)); } if (!velocity[axis]) return order; const nextOffset = velocity[axis] > 0 ? 1 : -1; const nextItem = order[index + nextOffset]; if (!nextItem) return order; const item = order[index]; const itemLayout = item.layout[axis]; const nextLayout = nextItem.layout[axis]; const nextItemCenter = mixNumber(nextLayout.min, nextLayout.max, 0.5); if ((nextOffset === 1 && itemLayout.max + offset[axis] > nextItemCenter) || (nextOffset === -1 && itemLayout.min + offset[axis] < nextItemCenter)) { return moveItem(order, index, index + nextOffset); } return order; } function getLines(order) { const lines = []; order.forEach((item) => { const { min, max } = item.layout.y; const line = lines[lines.length - 1]; if (!line || min >= line.max || max <= line.min) { lines.push({ items: [item], min, max }); } else { line.items.push(item); line.min = Math.min(line.min, min); line.max = Math.max(line.max, max); } }); return lines; } function distanceToLine(y, line) { return y < line.min ? line.min - y : y > line.max ? y - line.max : 0; } function moveToLine(order, index, x, line, direction) { const remaining = order.filter((_, itemIndex) => itemIndex !== index); const before = line.items.find((item) => { const center = mixNumber(item.layout.x.min, item.layout.x.max, 0.5); return direction === "ltr" ? x < center : x > center; }); const targetIndex = before ? remaining.indexOf(before) : remaining.indexOf(line.items[line.items.length - 1]) + 1; const nextOrder = [...remaining]; nextOrder.splice(targetIndex, 0, order[index]); return nextOrder.every((item, itemIndex) => item === order[itemIndex]) ? order : nextOrder; } function distanceToBox(point, box) { const x = Math.max(box.x.min - point.x, 0, point.x - box.x.max); const y = Math.max(box.y.min - point.y, 0, point.y - box.y.max); return x * x + y * y; } export { checkReorder }; //# sourceMappingURL=check-reorder.mjs.map