UNPKG

react-grid-layout

Version:

A draggable and resizable grid layout with responsive breakpoints, for React.

165 lines (153 loc) 6.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calcGridColWidth = calcGridColWidth; exports.calcGridItemPosition = calcGridItemPosition; exports.calcGridItemWHPx = calcGridItemWHPx; exports.calcWH = calcWH; exports.calcXY = calcXY; exports.clamp = clamp; /*:: import type { Position } from "./utils";*/ /*:: export type PositionParams = { margin: [number, number], containerPadding: [number, number], containerWidth: number, cols: number, rowHeight: number, maxRows: number };*/ // Helper for generating column width function calcGridColWidth(positionParams /*: PositionParams*/) /*: number*/{ const { margin, containerPadding, containerWidth, cols } = positionParams; return (containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols; } // This can either be called: // calcGridItemWHPx(w, colWidth, margin[0]) // or // calcGridItemWHPx(h, rowHeight, margin[1]) function calcGridItemWHPx(gridUnits /*: number*/, colOrRowSize /*: number*/, marginPx /*: number*/) /*: number*/{ // 0 * Infinity === NaN, which causes problems with resize contraints if (!Number.isFinite(gridUnits)) return gridUnits; return Math.round(colOrRowSize * gridUnits + Math.max(0, gridUnits - 1) * marginPx); } /** * Return position on the page given an x, y, w, h. * left, top, width, height are all in pixels. * @param {PositionParams} positionParams Parameters of grid needed for coordinates calculations. * @param {Number} x X coordinate in grid units. * @param {Number} y Y coordinate in grid units. * @param {Number} w W coordinate in grid units. * @param {Number} h H coordinate in grid units. * @return {Position} Object containing coords. */ function calcGridItemPosition(positionParams /*: PositionParams*/, x /*: number*/, y /*: number*/, w /*: number*/, h /*: number*/, state /*: ?Object*/) /*: Position*/{ const { margin, containerPadding, rowHeight } = positionParams; const colWidth = calcGridColWidth(positionParams); const out = {}; // If resizing, use the exact width and height as returned from resizing callbacks. if (state && state.resizing) { out.width = Math.round(state.resizing.width); out.height = Math.round(state.resizing.height); } // Otherwise, calculate from grid units. else { out.width = calcGridItemWHPx(w, colWidth, margin[0]); out.height = calcGridItemWHPx(h, rowHeight, margin[1]); } // If dragging, use the exact width and height as returned from dragging callbacks. if (state && state.dragging) { out.top = Math.round(state.dragging.top); out.left = Math.round(state.dragging.left); } else if (state && state.resizing && typeof state.resizing.top === "number" && typeof state.resizing.left === "number") { out.top = Math.round(state.resizing.top); out.left = Math.round(state.resizing.left); } // Otherwise, calculate from grid units. else { out.top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]); out.left = Math.round((colWidth + margin[0]) * x + containerPadding[0]); } return out; } /** * Translate x and y coordinates from pixels to grid units. * @param {PositionParams} positionParams Parameters of grid needed for coordinates calculations. * @param {Number} top Top position (relative to parent) in pixels. * @param {Number} left Left position (relative to parent) in pixels. * @param {Number} w W coordinate in grid units. * @param {Number} h H coordinate in grid units. * @return {Object} x and y in grid units. */ function calcXY(positionParams /*: PositionParams*/, top /*: number*/, left /*: number*/, w /*: number*/, h /*: number*/) /*: { x: number, y: number }*/{ const { margin, containerPadding, cols, rowHeight, maxRows } = positionParams; const colWidth = calcGridColWidth(positionParams); // left = containerPaddingX + x * (colWidth + marginX) // x * (colWidth + marginX) = left - containerPaddingX // x = (left - containerPaddingX) / (colWidth + marginX) let x = Math.round((left - containerPadding[0]) / (colWidth + margin[0])); let y = Math.round((top - containerPadding[1]) / (rowHeight + margin[1])); // Capping x = clamp(x, 0, cols - w); y = clamp(y, 0, maxRows - h); return { x, y }; } /** * Given a height and width in pixel values, calculate grid units. * @param {PositionParams} positionParams Parameters of grid needed for coordinates calcluations. * @param {Number} height Height in pixels. * @param {Number} width Width in pixels. * @param {Number} x X coordinate in grid units. * @param {Number} y Y coordinate in grid units. * @param {String} handle Resize Handle. * @return {Object} w, h as grid units. */ function calcWH(positionParams /*: PositionParams*/, width /*: number*/, height /*: number*/, x /*: number*/, y /*: number*/, handle /*: string*/) /*: { w: number, h: number }*/{ const { margin, maxRows, cols, rowHeight } = positionParams; const colWidth = calcGridColWidth(positionParams); // width = colWidth * w - (margin * (w - 1)) // ... // w = (width + margin) / (colWidth + margin) let w = Math.round((width + margin[0]) / (colWidth + margin[0])); let h = Math.round((height + margin[1]) / (rowHeight + margin[1])); // Capping let _w = clamp(w, 0, cols - x); let _h = clamp(h, 0, maxRows - y); if (["sw", "w", "nw"].indexOf(handle) !== -1) { _w = clamp(w, 0, cols); } if (["nw", "n", "ne"].indexOf(handle) !== -1) { _h = clamp(h, 0, maxRows); } return { w: _w, h: _h }; } // Similar to _.clamp function clamp(num /*: number*/, lowerBound /*: number*/, upperBound /*: number*/) /*: number*/{ return Math.max(Math.min(num, upperBound), lowerBound); }