/** * @fileoverview * Utility functions for drag interactions, e.g. sorting items in a grid/list. */ /** * From an xy position and a list of boxes {top, left, bottom, right}, return there * corresponding box index the position is over. The boxes are in a (possibly wrapped) * list, the only requirement being all boxes are flush against the edges, that is, * if they are along an outer edge, the position of that edge is identical. * This functionality works for a single column of items, a wrapped list with * many rows, or a single row of items. * @param {{x: number, y: number}} position The xy coordinates to retreive the corresponding index of. * @param {Array.} boxes The rects of the items, returned from `getBoundingClientRect` * @param {bool} isRtl are the boxes in RTL order. * @return {?number} index of the corresponding box, or null if one could not be found. */ const indexForPositionOnList = ({x, y}, boxes, isRtl) => { if (boxes.length === 0) return null; let index = null; const leftEdge = Math.min.apply(null, boxes.map(b => b.left)); const rightEdge = Math.max.apply(null, boxes.map(b => b.right)); const topEdge = Math.min.apply(null, boxes.map(b => b.top)); const bottomEdge = Math.max.apply(null, boxes.map(b => b.bottom)); for (let n = 0; n < boxes.length; n++) { const box = boxes[n]; // Construct an "extended" box for each, extending out to infinity if // the box is along a boundary. let minX = box.left === leftEdge ? -Infinity : box.left; let maxX = box.right === rightEdge ? Infinity : box.right; const minY = box.top === topEdge ? -Infinity : box.top; const maxY = box.bottom === bottomEdge ? Infinity : box.bottom; // The last item in the wrapped list gets a right edge at infinity, even // if it isn't the farthest right, in RTL mode. In LTR mode, it gets a // left edge at infinity. if (n === boxes.length - 1) { if (isRtl) { minX = -Infinity; } else { maxX = Infinity; } } // Check if the point is in the bounds. if (x >= minX && x <= maxX && y >= minY && y <= maxY) { index = n; break; // No need to keep looking. } } return index; }; export { indexForPositionOnList };