UNPKG

react-aria-components

Version:

A library of styleable components built using React Aria

209 lines (206 loc) • 10.5 kB
const $7e0f784ed4e400df$var$X_SWITCH_THRESHOLD = 10; const $7e0f784ed4e400df$var$Y_SWITCH_THRESHOLD = 5; class $7e0f784ed4e400df$export$82c13862611c034e { setup(delegate, state, direction) { this.delegate = delegate; this.state = state; this.direction = direction; } getDropTargetFromPoint(x, y, isValidDropTarget) { let baseTarget = this.delegate.getDropTargetFromPoint(x, y, isValidDropTarget); if (!baseTarget || baseTarget.type === 'root') return baseTarget; return this.resolveDropTarget(baseTarget, x, y, isValidDropTarget); } resolveDropTarget(target, x, y, isValidDropTarget) { let tracking = this.pointerTracking; // Calculate movement directions let deltaY = y - tracking.lastY; let deltaX = x - tracking.lastX; let currentYMovement = tracking.yDirection; let currentXMovement = tracking.xDirection; if (Math.abs(deltaY) > $7e0f784ed4e400df$var$Y_SWITCH_THRESHOLD) { currentYMovement = deltaY > 0 ? 'down' : 'up'; tracking.yDirection = currentYMovement; tracking.lastY = y; } if (Math.abs(deltaX) > $7e0f784ed4e400df$var$X_SWITCH_THRESHOLD) { currentXMovement = deltaX > 0 ? 'right' : 'left'; tracking.xDirection = currentXMovement; tracking.lastX = x; } // Normalize to 'after' if (target.dropPosition === 'before') { let keyBefore = this.state.collection.getKeyBefore(target.key); if (keyBefore != null) target = { type: 'item', key: keyBefore, dropPosition: 'after' }; } let potentialTargets = this.getPotentialTargets(target, isValidDropTarget); if (potentialTargets.length === 0) return { type: 'root' }; let resolvedItemTarget; if (potentialTargets.length > 1) resolvedItemTarget = this.selectTarget(potentialTargets, target, x, y, currentYMovement, currentXMovement); else { resolvedItemTarget = potentialTargets[0]; // Reset boundary context since we're not in a boundary case tracking.boundaryContext = null; } return resolvedItemTarget; } // Returns potential targets for an ambiguous drop position (e.g. after the last child of a parent, or after the parent itself) // Ordered by level, from innermost to outermost. getPotentialTargets(originalTarget, isValidDropTarget) { if (originalTarget.dropPosition === 'on') return [ originalTarget ]; let target = originalTarget; let collection = this.state.collection; let currentItem = collection.getItem(target.key); while(currentItem && (currentItem === null || currentItem === void 0 ? void 0 : currentItem.type) !== 'item' && currentItem.nextKey != null){ target.key = currentItem.nextKey; currentItem = collection.getItem(currentItem.nextKey); } let potentialTargets = [ target ]; // If target has children and is expanded, use "before first child" if (currentItem && currentItem.hasChildNodes && this.state.expandedKeys.has(currentItem.key) && collection.getChildren && target.dropPosition === 'after') { let firstChildItemNode = null; for (let child of collection.getChildren(currentItem.key))if (child.type === 'item') { firstChildItemNode = child; break; } if (firstChildItemNode) { const beforeFirstChildTarget = { type: 'item', key: firstChildItemNode.key, dropPosition: 'before' }; if (isValidDropTarget(beforeFirstChildTarget)) return [ beforeFirstChildTarget ]; else return []; } } if ((currentItem === null || currentItem === void 0 ? void 0 : currentItem.nextKey) != null) return [ originalTarget ]; // Walk up the parent chain to find ancestors that are the last child at their level let parentKey = currentItem === null || currentItem === void 0 ? void 0 : currentItem.parentKey; let ancestorTargets = []; while(parentKey){ let parentItem = collection.getItem(parentKey); let nextItem = (parentItem === null || parentItem === void 0 ? void 0 : parentItem.nextKey) ? collection.getItem(parentItem.nextKey) : null; let isLastChildAtLevel = !nextItem || nextItem.parentKey !== parentKey; if (isLastChildAtLevel) { let afterParentTarget = { type: 'item', key: parentKey, dropPosition: 'after' }; if (isValidDropTarget(afterParentTarget)) ancestorTargets.push(afterParentTarget); if (nextItem) break; } parentKey = parentItem === null || parentItem === void 0 ? void 0 : parentItem.parentKey; } if (ancestorTargets.length > 0) potentialTargets.push(...ancestorTargets); // Handle converting "after" to "before next" for non-ambiguous cases if (potentialTargets.length === 1) { let nextKey = collection.getKeyAfter(target.key); let nextNode = nextKey ? collection.getItem(nextKey) : null; if (nextKey != null && nextNode && currentItem && nextNode.level != null && currentItem.level != null && nextNode.level > currentItem.level) { let beforeTarget = { type: 'item', key: nextKey, dropPosition: 'before' }; if (isValidDropTarget(beforeTarget)) return [ beforeTarget ]; } } return potentialTargets.filter(isValidDropTarget); } selectTarget(potentialTargets, originalTarget, x, y, currentYMovement, currentXMovement) { if (potentialTargets.length < 2) return potentialTargets[0]; let tracking = this.pointerTracking; let currentItem = this.state.collection.getItem(originalTarget.key); let parentKey = currentItem === null || currentItem === void 0 ? void 0 : currentItem.parentKey; if (!parentKey) return potentialTargets[0]; // More than 1 potential target - use Y for initial target, then X for switching levels // Initialize boundary context if needed if (!tracking.boundaryContext || tracking.boundaryContext.parentKey !== parentKey) { // If entering from below, start with outer-most let initialTargetIndex = tracking.yDirection === 'up' ? potentialTargets.length - 1 : 0; tracking.boundaryContext = { parentKey: parentKey, preferredTargetIndex: initialTargetIndex, lastSwitchY: y, lastSwitchX: x }; } let boundaryContext = tracking.boundaryContext; let distanceFromLastXSwitch = Math.abs(x - boundaryContext.lastSwitchX); let distanceFromLastYSwitch = Math.abs(y - boundaryContext.lastSwitchY); // Switch between targets based on Y movement if (distanceFromLastYSwitch > $7e0f784ed4e400df$var$Y_SWITCH_THRESHOLD && currentYMovement) { let currentIndex = boundaryContext.preferredTargetIndex || 0; if (currentYMovement === 'down' && currentIndex === 0) // Moving down from inner-most, switch to outer-most boundaryContext.preferredTargetIndex = potentialTargets.length - 1; else if (currentYMovement === 'up' && currentIndex === potentialTargets.length - 1) // Moving up from outer-most, switch to inner-most boundaryContext.preferredTargetIndex = 0; // Reset x tracking so that moving diagonally doesn't cause flickering. tracking.xDirection = null; } // X movement controls level selection if (distanceFromLastXSwitch > $7e0f784ed4e400df$var$X_SWITCH_THRESHOLD && currentXMovement) { let currentTargetIndex = boundaryContext.preferredTargetIndex || 0; if (currentXMovement === 'left') { if (this.direction === 'ltr') // LTR: left = move to higher level in tree (increase index) { if (currentTargetIndex < potentialTargets.length - 1) { boundaryContext.preferredTargetIndex = currentTargetIndex + 1; boundaryContext.lastSwitchX = x; } } else // RTL: left = move to lower level in tree (decrease index) if (currentTargetIndex > 0) { boundaryContext.preferredTargetIndex = currentTargetIndex - 1; boundaryContext.lastSwitchX = x; } } else if (currentXMovement === 'right') { if (this.direction === 'ltr') // LTR: right = move to lower level in tree (decrease index) { if (currentTargetIndex > 0) { boundaryContext.preferredTargetIndex = currentTargetIndex - 1; boundaryContext.lastSwitchX = x; } } else // RTL: right = move to higher level in tree (increase index) if (currentTargetIndex < potentialTargets.length - 1) { boundaryContext.preferredTargetIndex = currentTargetIndex + 1; boundaryContext.lastSwitchX = x; } } // Reset y tracking so that moving diagonally doesn't cause flickering. tracking.yDirection = null; } let targetIndex = Math.max(0, Math.min(boundaryContext.preferredTargetIndex || 0, potentialTargets.length - 1)); return potentialTargets[targetIndex]; } constructor(){ this.delegate = null; this.state = null; this.direction = 'ltr'; this.pointerTracking = { lastY: 0, lastX: 0, yDirection: null, xDirection: null, boundaryContext: null }; } } export {$7e0f784ed4e400df$export$82c13862611c034e as TreeDropTargetDelegate}; //# sourceMappingURL=TreeDropTargetDelegate.module.js.map