react-grid-layout
Advanced tools
| import { P as Position, d as ResizeHandleAxis } from './types-Cxf4nHNr.mjs'; | ||
| /** | ||
| * Grid calculation utilities. | ||
| * | ||
| * These functions convert between grid units and pixel positions. | ||
| */ | ||
| /** | ||
| * Parameters needed for position calculations. | ||
| */ | ||
| interface PositionParams { | ||
| readonly margin: readonly [number, number]; | ||
| readonly containerPadding: readonly [number, number]; | ||
| readonly containerWidth: number; | ||
| readonly cols: number; | ||
| readonly rowHeight: number; | ||
| readonly maxRows: number; | ||
| } | ||
| /** | ||
| * Calculate the width of a single grid column in pixels. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @returns Column width in pixels | ||
| */ | ||
| declare function calcGridColWidth(positionParams: PositionParams): number; | ||
| /** | ||
| * Calculate the pixel size for a grid unit dimension (width or height). | ||
| * | ||
| * Can be called as: | ||
| * - calcGridItemWHPx(w, colWidth, margin[0]) for width | ||
| * - calcGridItemWHPx(h, rowHeight, margin[1]) for height | ||
| * | ||
| * @param gridUnits - Size in grid units | ||
| * @param colOrRowSize - Column width or row height in pixels | ||
| * @param marginPx - Margin between items in pixels | ||
| * @returns Size in pixels | ||
| */ | ||
| declare function calcGridItemWHPx(gridUnits: number, colOrRowSize: number, marginPx: number): number; | ||
| /** | ||
| * Calculate pixel position for a grid item. | ||
| * | ||
| * Returns left, top, width, height in pixels. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @param x - X coordinate in grid units | ||
| * @param y - Y coordinate in grid units | ||
| * @param w - Width in grid units | ||
| * @param h - Height in grid units | ||
| * @param dragPosition - If present, use exact left/top from drag callbacks | ||
| * @param resizePosition - If present, use exact dimensions from resize callbacks | ||
| * @returns Position in pixels | ||
| */ | ||
| declare function calcGridItemPosition(positionParams: PositionParams, x: number, y: number, w: number, h: number, dragPosition?: { | ||
| top: number; | ||
| left: number; | ||
| } | null, resizePosition?: { | ||
| top: number; | ||
| left: number; | ||
| height: number; | ||
| width: number; | ||
| } | null): Position; | ||
| /** | ||
| * Translate pixel coordinates to grid units. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @param top - Top position in pixels (relative to parent) | ||
| * @param left - Left position in pixels (relative to parent) | ||
| * @param w - Width in grid units (for clamping) | ||
| * @param h - Height in grid units (for clamping) | ||
| * @returns x and y in grid units | ||
| */ | ||
| declare function calcXY(positionParams: PositionParams, top: number, left: number, w: number, h: number): { | ||
| x: number; | ||
| y: number; | ||
| }; | ||
| /** | ||
| * Calculate grid units from pixel dimensions. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @param width - Width in pixels | ||
| * @param height - Height in pixels | ||
| * @param x - X coordinate in grid units (for clamping) | ||
| * @param y - Y coordinate in grid units (for clamping) | ||
| * @param handle - Resize handle being used | ||
| * @returns w, h in grid units | ||
| */ | ||
| declare function calcWH(positionParams: PositionParams, width: number, height: number, x: number, y: number, handle: ResizeHandleAxis): { | ||
| w: number; | ||
| h: number; | ||
| }; | ||
| /** | ||
| * Clamp a number between bounds. | ||
| * | ||
| * @param num - Number to clamp | ||
| * @param lowerBound - Minimum value | ||
| * @param upperBound - Maximum value | ||
| * @returns Clamped value | ||
| */ | ||
| declare function clamp(num: number, lowerBound: number, upperBound: number): number; | ||
| /** | ||
| * Grid cell dimension information for rendering backgrounds or overlays. | ||
| */ | ||
| interface GridCellDimensions { | ||
| /** Width of a single cell in pixels */ | ||
| readonly cellWidth: number; | ||
| /** Height of a single cell in pixels */ | ||
| readonly cellHeight: number; | ||
| /** Horizontal offset from container edge to first cell */ | ||
| readonly offsetX: number; | ||
| /** Vertical offset from container edge to first cell */ | ||
| readonly offsetY: number; | ||
| /** Horizontal gap between cells */ | ||
| readonly gapX: number; | ||
| /** Vertical gap between cells */ | ||
| readonly gapY: number; | ||
| /** Number of columns */ | ||
| readonly cols: number; | ||
| /** Total container width */ | ||
| readonly containerWidth: number; | ||
| } | ||
| /** | ||
| * Configuration for grid cell dimension calculation. | ||
| */ | ||
| interface GridCellConfig { | ||
| /** Container width in pixels */ | ||
| width: number; | ||
| /** Number of columns */ | ||
| cols: number; | ||
| /** Row height in pixels */ | ||
| rowHeight: number; | ||
| /** Margin between items [x, y] */ | ||
| margin?: readonly [number, number]; | ||
| /** Container padding [x, y], defaults to margin if not specified */ | ||
| containerPadding?: readonly [number, number] | null; | ||
| } | ||
| /** | ||
| * Calculate grid cell dimensions for rendering backgrounds or overlays. | ||
| * | ||
| * This function provides all the measurements needed to render a visual | ||
| * grid background that aligns with the actual grid cells. | ||
| * | ||
| * @param config - Grid configuration | ||
| * @returns Cell dimensions and offsets | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * import { calcGridCellDimensions } from 'react-grid-layout/core'; | ||
| * | ||
| * const dims = calcGridCellDimensions({ | ||
| * width: 1200, | ||
| * cols: 12, | ||
| * rowHeight: 30, | ||
| * margin: [10, 10], | ||
| * containerPadding: [10, 10] | ||
| * }); | ||
| * | ||
| * // dims.cellWidth = 88.33... | ||
| * // dims.cellHeight = 30 | ||
| * // dims.offsetX = 10 (containerPadding[0]) | ||
| * // dims.offsetY = 10 (containerPadding[1]) | ||
| * // dims.gapX = 10 (margin[0]) | ||
| * // dims.gapY = 10 (margin[1]) | ||
| * ``` | ||
| */ | ||
| declare function calcGridCellDimensions(config: GridCellConfig): GridCellDimensions; | ||
| export { type GridCellDimensions as G, type PositionParams as P, calcXY as a, calcWH as b, calcGridItemPosition as c, type GridCellConfig as d, calcGridColWidth as e, calcGridItemWHPx as f, clamp as g, calcGridCellDimensions as h }; |
| import { P as Position, d as ResizeHandleAxis } from './types-Cxf4nHNr.js'; | ||
| /** | ||
| * Grid calculation utilities. | ||
| * | ||
| * These functions convert between grid units and pixel positions. | ||
| */ | ||
| /** | ||
| * Parameters needed for position calculations. | ||
| */ | ||
| interface PositionParams { | ||
| readonly margin: readonly [number, number]; | ||
| readonly containerPadding: readonly [number, number]; | ||
| readonly containerWidth: number; | ||
| readonly cols: number; | ||
| readonly rowHeight: number; | ||
| readonly maxRows: number; | ||
| } | ||
| /** | ||
| * Calculate the width of a single grid column in pixels. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @returns Column width in pixels | ||
| */ | ||
| declare function calcGridColWidth(positionParams: PositionParams): number; | ||
| /** | ||
| * Calculate the pixel size for a grid unit dimension (width or height). | ||
| * | ||
| * Can be called as: | ||
| * - calcGridItemWHPx(w, colWidth, margin[0]) for width | ||
| * - calcGridItemWHPx(h, rowHeight, margin[1]) for height | ||
| * | ||
| * @param gridUnits - Size in grid units | ||
| * @param colOrRowSize - Column width or row height in pixels | ||
| * @param marginPx - Margin between items in pixels | ||
| * @returns Size in pixels | ||
| */ | ||
| declare function calcGridItemWHPx(gridUnits: number, colOrRowSize: number, marginPx: number): number; | ||
| /** | ||
| * Calculate pixel position for a grid item. | ||
| * | ||
| * Returns left, top, width, height in pixels. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @param x - X coordinate in grid units | ||
| * @param y - Y coordinate in grid units | ||
| * @param w - Width in grid units | ||
| * @param h - Height in grid units | ||
| * @param dragPosition - If present, use exact left/top from drag callbacks | ||
| * @param resizePosition - If present, use exact dimensions from resize callbacks | ||
| * @returns Position in pixels | ||
| */ | ||
| declare function calcGridItemPosition(positionParams: PositionParams, x: number, y: number, w: number, h: number, dragPosition?: { | ||
| top: number; | ||
| left: number; | ||
| } | null, resizePosition?: { | ||
| top: number; | ||
| left: number; | ||
| height: number; | ||
| width: number; | ||
| } | null): Position; | ||
| /** | ||
| * Translate pixel coordinates to grid units. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @param top - Top position in pixels (relative to parent) | ||
| * @param left - Left position in pixels (relative to parent) | ||
| * @param w - Width in grid units (for clamping) | ||
| * @param h - Height in grid units (for clamping) | ||
| * @returns x and y in grid units | ||
| */ | ||
| declare function calcXY(positionParams: PositionParams, top: number, left: number, w: number, h: number): { | ||
| x: number; | ||
| y: number; | ||
| }; | ||
| /** | ||
| * Calculate grid units from pixel dimensions. | ||
| * | ||
| * @param positionParams - Grid parameters | ||
| * @param width - Width in pixels | ||
| * @param height - Height in pixels | ||
| * @param x - X coordinate in grid units (for clamping) | ||
| * @param y - Y coordinate in grid units (for clamping) | ||
| * @param handle - Resize handle being used | ||
| * @returns w, h in grid units | ||
| */ | ||
| declare function calcWH(positionParams: PositionParams, width: number, height: number, x: number, y: number, handle: ResizeHandleAxis): { | ||
| w: number; | ||
| h: number; | ||
| }; | ||
| /** | ||
| * Clamp a number between bounds. | ||
| * | ||
| * @param num - Number to clamp | ||
| * @param lowerBound - Minimum value | ||
| * @param upperBound - Maximum value | ||
| * @returns Clamped value | ||
| */ | ||
| declare function clamp(num: number, lowerBound: number, upperBound: number): number; | ||
| /** | ||
| * Grid cell dimension information for rendering backgrounds or overlays. | ||
| */ | ||
| interface GridCellDimensions { | ||
| /** Width of a single cell in pixels */ | ||
| readonly cellWidth: number; | ||
| /** Height of a single cell in pixels */ | ||
| readonly cellHeight: number; | ||
| /** Horizontal offset from container edge to first cell */ | ||
| readonly offsetX: number; | ||
| /** Vertical offset from container edge to first cell */ | ||
| readonly offsetY: number; | ||
| /** Horizontal gap between cells */ | ||
| readonly gapX: number; | ||
| /** Vertical gap between cells */ | ||
| readonly gapY: number; | ||
| /** Number of columns */ | ||
| readonly cols: number; | ||
| /** Total container width */ | ||
| readonly containerWidth: number; | ||
| } | ||
| /** | ||
| * Configuration for grid cell dimension calculation. | ||
| */ | ||
| interface GridCellConfig { | ||
| /** Container width in pixels */ | ||
| width: number; | ||
| /** Number of columns */ | ||
| cols: number; | ||
| /** Row height in pixels */ | ||
| rowHeight: number; | ||
| /** Margin between items [x, y] */ | ||
| margin?: readonly [number, number]; | ||
| /** Container padding [x, y], defaults to margin if not specified */ | ||
| containerPadding?: readonly [number, number] | null; | ||
| } | ||
| /** | ||
| * Calculate grid cell dimensions for rendering backgrounds or overlays. | ||
| * | ||
| * This function provides all the measurements needed to render a visual | ||
| * grid background that aligns with the actual grid cells. | ||
| * | ||
| * @param config - Grid configuration | ||
| * @returns Cell dimensions and offsets | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * import { calcGridCellDimensions } from 'react-grid-layout/core'; | ||
| * | ||
| * const dims = calcGridCellDimensions({ | ||
| * width: 1200, | ||
| * cols: 12, | ||
| * rowHeight: 30, | ||
| * margin: [10, 10], | ||
| * containerPadding: [10, 10] | ||
| * }); | ||
| * | ||
| * // dims.cellWidth = 88.33... | ||
| * // dims.cellHeight = 30 | ||
| * // dims.offsetX = 10 (containerPadding[0]) | ||
| * // dims.offsetY = 10 (containerPadding[1]) | ||
| * // dims.gapX = 10 (margin[0]) | ||
| * // dims.gapY = 10 (margin[1]) | ||
| * ``` | ||
| */ | ||
| declare function calcGridCellDimensions(config: GridCellConfig): GridCellDimensions; | ||
| export { type GridCellDimensions as G, type PositionParams as P, calcXY as a, calcWH as b, calcGridItemPosition as c, type GridCellConfig as d, calcGridColWidth as e, calcGridItemWHPx as f, clamp as g, calcGridCellDimensions as h }; |
| // src/core/calculate.ts | ||
| function calcGridColWidth(positionParams) { | ||
| const { margin, containerPadding, containerWidth, cols } = positionParams; | ||
| return (containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols; | ||
| } | ||
| function calcGridItemWHPx(gridUnits, colOrRowSize, marginPx) { | ||
| if (!Number.isFinite(gridUnits)) return gridUnits; | ||
| return Math.round( | ||
| colOrRowSize * gridUnits + Math.max(0, gridUnits - 1) * marginPx | ||
| ); | ||
| } | ||
| function calcGridItemPosition(positionParams, x, y, w, h, dragPosition, resizePosition) { | ||
| const { margin, containerPadding, rowHeight } = positionParams; | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| let width; | ||
| let height; | ||
| let top; | ||
| let left; | ||
| if (resizePosition) { | ||
| width = Math.round(resizePosition.width); | ||
| height = Math.round(resizePosition.height); | ||
| } else { | ||
| width = calcGridItemWHPx(w, colWidth, margin[0]); | ||
| height = calcGridItemWHPx(h, rowHeight, margin[1]); | ||
| } | ||
| if (dragPosition) { | ||
| top = Math.round(dragPosition.top); | ||
| left = Math.round(dragPosition.left); | ||
| } else if (resizePosition) { | ||
| top = Math.round(resizePosition.top); | ||
| left = Math.round(resizePosition.left); | ||
| } else { | ||
| top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]); | ||
| left = Math.round((colWidth + margin[0]) * x + containerPadding[0]); | ||
| } | ||
| return { top, left, width, height }; | ||
| } | ||
| function calcXY(positionParams, top, left, w, h) { | ||
| const { margin, containerPadding, cols, rowHeight, maxRows } = positionParams; | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| let x = Math.round((left - containerPadding[0]) / (colWidth + margin[0])); | ||
| let y = Math.round((top - containerPadding[1]) / (rowHeight + margin[1])); | ||
| x = clamp(x, 0, cols - w); | ||
| y = clamp(y, 0, maxRows - h); | ||
| return { x, y }; | ||
| } | ||
| function calcWH(positionParams, width, height, x, y, handle) { | ||
| const { margin, maxRows, cols, rowHeight } = positionParams; | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| const w = Math.round((width + margin[0]) / (colWidth + margin[0])); | ||
| const h = Math.round((height + margin[1]) / (rowHeight + margin[1])); | ||
| let _w = clamp(w, 0, cols - x); | ||
| let _h = clamp(h, 0, maxRows - y); | ||
| if (handle === "sw" || handle === "w" || handle === "nw") { | ||
| _w = clamp(w, 0, cols); | ||
| } | ||
| if (handle === "nw" || handle === "n" || handle === "ne") { | ||
| _h = clamp(h, 0, maxRows); | ||
| } | ||
| return { w: _w, h: _h }; | ||
| } | ||
| function clamp(num, lowerBound, upperBound) { | ||
| return Math.max(Math.min(num, upperBound), lowerBound); | ||
| } | ||
| function calcGridCellDimensions(config) { | ||
| const { | ||
| width, | ||
| cols, | ||
| rowHeight, | ||
| margin = [10, 10], | ||
| containerPadding | ||
| } = config; | ||
| const padding = containerPadding ?? margin; | ||
| const cellWidth = (width - padding[0] * 2 - margin[0] * (cols - 1)) / cols; | ||
| const cellHeight = rowHeight; | ||
| return { | ||
| cellWidth, | ||
| cellHeight, | ||
| offsetX: padding[0], | ||
| offsetY: padding[1], | ||
| gapX: margin[0], | ||
| gapY: margin[1], | ||
| cols, | ||
| containerWidth: width | ||
| }; | ||
| } | ||
| export { calcGridCellDimensions, calcGridColWidth, calcGridItemPosition, calcGridItemWHPx, calcWH, calcXY, clamp }; | ||
| //# sourceMappingURL=chunk-2KUHNJXF.mjs.map | ||
| //# sourceMappingURL=chunk-2KUHNJXF.mjs.map |
| {"version":3,"sources":["../src/core/calculate.ts"],"names":[],"mappings":"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","file":"chunk-2KUHNJXF.mjs","sourcesContent":["/**\n * Grid calculation utilities.\n *\n * These functions convert between grid units and pixel positions.\n */\n\nimport type { Position, ResizeHandleAxis } from \"./types.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Parameters needed for position calculations.\n */\nexport interface PositionParams {\n readonly margin: readonly [number, number];\n readonly containerPadding: readonly [number, number];\n readonly containerWidth: number;\n readonly cols: number;\n readonly rowHeight: number;\n readonly maxRows: number;\n}\n\n// ============================================================================\n// Grid Column/Row Calculations\n// ============================================================================\n\n/**\n * Calculate the width of a single grid column in pixels.\n *\n * @param positionParams - Grid parameters\n * @returns Column width in pixels\n */\nexport function calcGridColWidth(positionParams: PositionParams): number {\n const { margin, containerPadding, containerWidth, cols } = positionParams;\n return (\n (containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols\n );\n}\n\n/**\n * Calculate the pixel size for a grid unit dimension (width or height).\n *\n * Can be called as:\n * - calcGridItemWHPx(w, colWidth, margin[0]) for width\n * - calcGridItemWHPx(h, rowHeight, margin[1]) for height\n *\n * @param gridUnits - Size in grid units\n * @param colOrRowSize - Column width or row height in pixels\n * @param marginPx - Margin between items in pixels\n * @returns Size in pixels\n */\nexport function calcGridItemWHPx(\n gridUnits: number,\n colOrRowSize: number,\n marginPx: number\n): number {\n // 0 * Infinity === NaN, which causes problems with resize constraints\n if (!Number.isFinite(gridUnits)) return gridUnits;\n return Math.round(\n colOrRowSize * gridUnits + Math.max(0, gridUnits - 1) * marginPx\n );\n}\n\n// ============================================================================\n// Position Calculations\n// ============================================================================\n\n/**\n * Calculate pixel position for a grid item.\n *\n * Returns left, top, width, height in pixels.\n *\n * @param positionParams - Grid parameters\n * @param x - X coordinate in grid units\n * @param y - Y coordinate in grid units\n * @param w - Width in grid units\n * @param h - Height in grid units\n * @param dragPosition - If present, use exact left/top from drag callbacks\n * @param resizePosition - If present, use exact dimensions from resize callbacks\n * @returns Position in pixels\n */\nexport function calcGridItemPosition(\n positionParams: PositionParams,\n x: number,\n y: number,\n w: number,\n h: number,\n dragPosition?: { top: number; left: number } | null,\n resizePosition?: {\n top: number;\n left: number;\n height: number;\n width: number;\n } | null\n): Position {\n const { margin, containerPadding, rowHeight } = positionParams;\n const colWidth = calcGridColWidth(positionParams);\n\n let width: number;\n let height: number;\n let top: number;\n let left: number;\n\n // If resizing, use the exact width and height from resize callbacks\n if (resizePosition) {\n width = Math.round(resizePosition.width);\n height = Math.round(resizePosition.height);\n } else {\n // Calculate from grid units\n width = calcGridItemWHPx(w, colWidth, margin[0]);\n height = calcGridItemWHPx(h, rowHeight, margin[1]);\n }\n\n // If dragging, use the exact left/top from drag callbacks\n if (dragPosition) {\n top = Math.round(dragPosition.top);\n left = Math.round(dragPosition.left);\n } else if (resizePosition) {\n // If resizing, use the exact left/top from resize position\n top = Math.round(resizePosition.top);\n left = Math.round(resizePosition.left);\n } else {\n // Calculate from grid units\n top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]);\n left = Math.round((colWidth + margin[0]) * x + containerPadding[0]);\n }\n\n return { top, left, width, height };\n}\n\n/**\n * Translate pixel coordinates to grid units.\n *\n * @param positionParams - Grid parameters\n * @param top - Top position in pixels (relative to parent)\n * @param left - Left position in pixels (relative to parent)\n * @param w - Width in grid units (for clamping)\n * @param h - Height in grid units (for clamping)\n * @returns x and y in grid units\n */\nexport function calcXY(\n positionParams: PositionParams,\n top: number,\n left: number,\n w: number,\n h: number\n): { x: number; y: number } {\n const { margin, containerPadding, cols, rowHeight, maxRows } = positionParams;\n const colWidth = calcGridColWidth(positionParams);\n\n // left = containerPaddingX + x * (colWidth + marginX)\n // x = (left - containerPaddingX) / (colWidth + marginX)\n let x = Math.round((left - containerPadding[0]) / (colWidth + margin[0]));\n let y = Math.round((top - containerPadding[1]) / (rowHeight + margin[1]));\n\n // Clamp to grid bounds\n x = clamp(x, 0, cols - w);\n y = clamp(y, 0, maxRows - h);\n\n return { x, y };\n}\n\n/**\n * Calculate grid units from pixel dimensions.\n *\n * @param positionParams - Grid parameters\n * @param width - Width in pixels\n * @param height - Height in pixels\n * @param x - X coordinate in grid units (for clamping)\n * @param y - Y coordinate in grid units (for clamping)\n * @param handle - Resize handle being used\n * @returns w, h in grid units\n */\nexport function calcWH(\n positionParams: PositionParams,\n width: number,\n height: number,\n x: number,\n y: number,\n handle: ResizeHandleAxis\n): { w: number; h: number } {\n const { margin, maxRows, cols, rowHeight } = positionParams;\n const colWidth = calcGridColWidth(positionParams);\n\n // width = colWidth * w - (margin * (w - 1))\n // w = (width + margin) / (colWidth + margin)\n const w = Math.round((width + margin[0]) / (colWidth + margin[0]));\n const h = Math.round((height + margin[1]) / (rowHeight + margin[1]));\n\n // Clamp based on resize handle direction\n let _w = clamp(w, 0, cols - x);\n let _h = clamp(h, 0, maxRows - y);\n\n // West handles can resize to full width\n if (handle === \"sw\" || handle === \"w\" || handle === \"nw\") {\n _w = clamp(w, 0, cols);\n }\n\n // North handles can resize to full height\n if (handle === \"nw\" || handle === \"n\" || handle === \"ne\") {\n _h = clamp(h, 0, maxRows);\n }\n\n return { w: _w, h: _h };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Clamp a number between bounds.\n *\n * @param num - Number to clamp\n * @param lowerBound - Minimum value\n * @param upperBound - Maximum value\n * @returns Clamped value\n */\nexport function clamp(\n num: number,\n lowerBound: number,\n upperBound: number\n): number {\n return Math.max(Math.min(num, upperBound), lowerBound);\n}\n\n// ============================================================================\n// Grid Background Calculations\n// ============================================================================\n\n/**\n * Grid cell dimension information for rendering backgrounds or overlays.\n */\nexport interface GridCellDimensions {\n /** Width of a single cell in pixels */\n readonly cellWidth: number;\n /** Height of a single cell in pixels */\n readonly cellHeight: number;\n /** Horizontal offset from container edge to first cell */\n readonly offsetX: number;\n /** Vertical offset from container edge to first cell */\n readonly offsetY: number;\n /** Horizontal gap between cells */\n readonly gapX: number;\n /** Vertical gap between cells */\n readonly gapY: number;\n /** Number of columns */\n readonly cols: number;\n /** Total container width */\n readonly containerWidth: number;\n}\n\n/**\n * Configuration for grid cell dimension calculation.\n */\nexport interface GridCellConfig {\n /** Container width in pixels */\n width: number;\n /** Number of columns */\n cols: number;\n /** Row height in pixels */\n rowHeight: number;\n /** Margin between items [x, y] */\n margin?: readonly [number, number];\n /** Container padding [x, y], defaults to margin if not specified */\n containerPadding?: readonly [number, number] | null;\n}\n\n/**\n * Calculate grid cell dimensions for rendering backgrounds or overlays.\n *\n * This function provides all the measurements needed to render a visual\n * grid background that aligns with the actual grid cells.\n *\n * @param config - Grid configuration\n * @returns Cell dimensions and offsets\n *\n * @example\n * ```tsx\n * import { calcGridCellDimensions } from 'react-grid-layout/core';\n *\n * const dims = calcGridCellDimensions({\n * width: 1200,\n * cols: 12,\n * rowHeight: 30,\n * margin: [10, 10],\n * containerPadding: [10, 10]\n * });\n *\n * // dims.cellWidth = 88.33...\n * // dims.cellHeight = 30\n * // dims.offsetX = 10 (containerPadding[0])\n * // dims.offsetY = 10 (containerPadding[1])\n * // dims.gapX = 10 (margin[0])\n * // dims.gapY = 10 (margin[1])\n * ```\n */\nexport function calcGridCellDimensions(\n config: GridCellConfig\n): GridCellDimensions {\n const {\n width,\n cols,\n rowHeight,\n margin = [10, 10],\n containerPadding\n } = config;\n\n // Container padding defaults to margin if not specified\n const padding = containerPadding ?? margin;\n\n // Calculate cell width: total width minus padding and gaps, divided by columns\n // Formula: width = 2*padding + cols*cellWidth + (cols-1)*gap\n // Solving for cellWidth: cellWidth = (width - 2*padding - (cols-1)*gap) / cols\n const cellWidth = (width - padding[0] * 2 - margin[0] * (cols - 1)) / cols;\n const cellHeight = rowHeight;\n\n return {\n cellWidth,\n cellHeight,\n offsetX: padding[0],\n offsetY: padding[1],\n gapX: margin[0],\n gapY: margin[1],\n cols,\n containerWidth: width\n };\n}\n"]} |
| 'use strict'; | ||
| // src/core/position.ts | ||
| function setTransform({ | ||
| top, | ||
| left, | ||
| width, | ||
| height | ||
| }) { | ||
| const translate = `translate(${left}px,${top}px)`; | ||
| return { | ||
| transform: translate, | ||
| WebkitTransform: translate, | ||
| MozTransform: translate, | ||
| msTransform: translate, | ||
| OTransform: translate, | ||
| width: `${width}px`, | ||
| height: `${height}px`, | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| function setTopLeft({ | ||
| top, | ||
| left, | ||
| width, | ||
| height | ||
| }) { | ||
| return { | ||
| top: `${top}px`, | ||
| left: `${left}px`, | ||
| width: `${width}px`, | ||
| height: `${height}px`, | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| function perc(num) { | ||
| return num * 100 + "%"; | ||
| } | ||
| function constrainWidth(left, currentWidth, newWidth, containerWidth) { | ||
| return left + newWidth > containerWidth ? currentWidth : newWidth; | ||
| } | ||
| function constrainHeight(top, currentHeight, newHeight) { | ||
| return top < 0 ? currentHeight : newHeight; | ||
| } | ||
| function constrainLeft(left) { | ||
| return Math.max(0, left); | ||
| } | ||
| function constrainTop(top) { | ||
| return Math.max(0, top); | ||
| } | ||
| var resizeNorth = (currentSize, newSize, _containerWidth) => { | ||
| const { left, height, width } = newSize; | ||
| const top = currentSize.top - (height - currentSize.height); | ||
| return { | ||
| left, | ||
| width, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }; | ||
| }; | ||
| var resizeEast = (currentSize, newSize, containerWidth) => { | ||
| const { top, left, height, width } = newSize; | ||
| return { | ||
| top, | ||
| height, | ||
| width: constrainWidth( | ||
| currentSize.left, | ||
| currentSize.width, | ||
| width, | ||
| containerWidth | ||
| ), | ||
| left: constrainLeft(left) | ||
| }; | ||
| }; | ||
| var resizeWest = (currentSize, newSize, _containerWidth) => { | ||
| const { top, height, width } = newSize; | ||
| const left = currentSize.left + currentSize.width - width; | ||
| if (left < 0) { | ||
| return { | ||
| height, | ||
| width: currentSize.left + currentSize.width, | ||
| top: constrainTop(top), | ||
| left: 0 | ||
| }; | ||
| } | ||
| return { | ||
| height, | ||
| width, | ||
| top: constrainTop(top), | ||
| left | ||
| }; | ||
| }; | ||
| var resizeSouth = (currentSize, newSize, _containerWidth) => { | ||
| const { top, left, height, width } = newSize; | ||
| return { | ||
| width, | ||
| left, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }; | ||
| }; | ||
| var resizeNorthEast = (currentSize, newSize, containerWidth) => resizeNorth( | ||
| currentSize, | ||
| resizeEast(currentSize, newSize, containerWidth)); | ||
| var resizeNorthWest = (currentSize, newSize, containerWidth) => resizeNorth( | ||
| currentSize, | ||
| resizeWest(currentSize, newSize)); | ||
| var resizeSouthEast = (currentSize, newSize, containerWidth) => resizeSouth( | ||
| currentSize, | ||
| resizeEast(currentSize, newSize, containerWidth)); | ||
| var resizeSouthWest = (currentSize, newSize, containerWidth) => resizeSouth( | ||
| currentSize, | ||
| resizeWest(currentSize, newSize)); | ||
| var resizeHandlerMap = { | ||
| n: resizeNorth, | ||
| ne: resizeNorthEast, | ||
| e: resizeEast, | ||
| se: resizeSouthEast, | ||
| s: resizeSouth, | ||
| sw: resizeSouthWest, | ||
| w: resizeWest, | ||
| nw: resizeNorthWest | ||
| }; | ||
| function resizeItemInDirection(direction, currentSize, newSize, containerWidth) { | ||
| const handler = resizeHandlerMap[direction]; | ||
| if (!handler) { | ||
| return newSize; | ||
| } | ||
| return handler(currentSize, { ...currentSize, ...newSize }, containerWidth); | ||
| } | ||
| var transformStrategy = { | ||
| type: "transform", | ||
| scale: 1, | ||
| calcStyle(pos) { | ||
| return setTransform(pos); | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| return { | ||
| left: clientX - offsetX, | ||
| top: clientY - offsetY | ||
| }; | ||
| } | ||
| }; | ||
| var absoluteStrategy = { | ||
| type: "absolute", | ||
| scale: 1, | ||
| calcStyle(pos) { | ||
| return setTopLeft(pos); | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| return { | ||
| left: clientX - offsetX, | ||
| top: clientY - offsetY | ||
| }; | ||
| } | ||
| }; | ||
| function createScaledStrategy(scale) { | ||
| return { | ||
| type: "transform", | ||
| scale, | ||
| calcStyle(pos) { | ||
| return setTransform(pos); | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| return { | ||
| left: (clientX - offsetX) / scale, | ||
| top: (clientY - offsetY) / scale | ||
| }; | ||
| } | ||
| }; | ||
| } | ||
| var defaultPositionStrategy = transformStrategy; | ||
| // src/core/types.ts | ||
| var defaultGridConfig = { | ||
| cols: 12, | ||
| rowHeight: 150, | ||
| margin: [10, 10], | ||
| containerPadding: null, | ||
| maxRows: Infinity | ||
| }; | ||
| var defaultDragConfig = { | ||
| enabled: true, | ||
| bounded: false, | ||
| threshold: 3 | ||
| }; | ||
| var defaultResizeConfig = { | ||
| enabled: true, | ||
| handles: ["se"] | ||
| }; | ||
| var defaultDropConfig = { | ||
| enabled: false, | ||
| defaultItem: { w: 1, h: 1 } | ||
| }; | ||
| // src/core/collision.ts | ||
| function collides(l1, l2) { | ||
| if (l1.i === l2.i) return false; | ||
| if (l1.x + l1.w <= l2.x) return false; | ||
| if (l1.x >= l2.x + l2.w) return false; | ||
| if (l1.y + l1.h <= l2.y) return false; | ||
| if (l1.y >= l2.y + l2.h) return false; | ||
| return true; | ||
| } | ||
| function getFirstCollision(layout, layoutItem) { | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0 && collides(item, layoutItem)) { | ||
| return item; | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| function getAllCollisions(layout, layoutItem) { | ||
| return layout.filter((l) => collides(l, layoutItem)); | ||
| } | ||
| // src/core/sort.ts | ||
| function sortLayoutItems(layout, compactType) { | ||
| if (compactType === "horizontal") { | ||
| return sortLayoutItemsByColRow(layout); | ||
| } | ||
| if (compactType === "vertical") { | ||
| return sortLayoutItemsByRowCol(layout); | ||
| } | ||
| return [...layout]; | ||
| } | ||
| function sortLayoutItemsByRowCol(layout) { | ||
| return [...layout].sort((a, b) => { | ||
| if (a.y !== b.y) { | ||
| return a.y - b.y; | ||
| } | ||
| return a.x - b.x; | ||
| }); | ||
| } | ||
| function sortLayoutItemsByColRow(layout) { | ||
| return [...layout].sort((a, b) => { | ||
| if (a.x !== b.x) { | ||
| return a.x - b.x; | ||
| } | ||
| return a.y - b.y; | ||
| }); | ||
| } | ||
| // src/core/layout.ts | ||
| function bottom(layout) { | ||
| let max = 0; | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0) { | ||
| const bottomY = item.y + item.h; | ||
| if (bottomY > max) max = bottomY; | ||
| } | ||
| } | ||
| return max; | ||
| } | ||
| function getLayoutItem(layout, id) { | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0 && item.i === id) { | ||
| return item; | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| function getStatics(layout) { | ||
| return layout.filter((l) => l.static === true); | ||
| } | ||
| function cloneLayoutItem(layoutItem) { | ||
| return { | ||
| i: layoutItem.i, | ||
| x: layoutItem.x, | ||
| y: layoutItem.y, | ||
| w: layoutItem.w, | ||
| h: layoutItem.h, | ||
| minW: layoutItem.minW, | ||
| maxW: layoutItem.maxW, | ||
| minH: layoutItem.minH, | ||
| maxH: layoutItem.maxH, | ||
| moved: Boolean(layoutItem.moved), | ||
| static: Boolean(layoutItem.static), | ||
| isDraggable: layoutItem.isDraggable, | ||
| isResizable: layoutItem.isResizable, | ||
| resizeHandles: layoutItem.resizeHandles, | ||
| isBounded: layoutItem.isBounded | ||
| }; | ||
| } | ||
| function cloneLayout(layout) { | ||
| const newLayout = new Array(layout.length); | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0) { | ||
| newLayout[i] = cloneLayoutItem(item); | ||
| } | ||
| } | ||
| return newLayout; | ||
| } | ||
| function modifyLayout(layout, layoutItem) { | ||
| const newLayout = new Array(layout.length); | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0) { | ||
| if (layoutItem.i === item.i) { | ||
| newLayout[i] = layoutItem; | ||
| } else { | ||
| newLayout[i] = item; | ||
| } | ||
| } | ||
| } | ||
| return newLayout; | ||
| } | ||
| function withLayoutItem(layout, itemKey, cb) { | ||
| let item = getLayoutItem(layout, itemKey); | ||
| if (!item) { | ||
| return [[...layout], null]; | ||
| } | ||
| item = cb(cloneLayoutItem(item)); | ||
| const newLayout = modifyLayout(layout, item); | ||
| return [newLayout, item]; | ||
| } | ||
| function correctBounds(layout, bounds) { | ||
| const collidesWith = getStatics(layout); | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const l = layout[i]; | ||
| if (l === void 0) continue; | ||
| if (l.x + l.w > bounds.cols) { | ||
| l.x = bounds.cols - l.w; | ||
| } | ||
| if (l.x < 0) { | ||
| l.x = 0; | ||
| l.w = bounds.cols; | ||
| } | ||
| if (!l.static) { | ||
| collidesWith.push(l); | ||
| } else { | ||
| while (getFirstCollision(collidesWith, l)) { | ||
| l.y++; | ||
| } | ||
| } | ||
| } | ||
| return layout; | ||
| } | ||
| function moveElement(layout, l, x, y, isUserAction, preventCollision, compactType, cols, allowOverlap) { | ||
| if (l.static && l.isDraggable !== true) { | ||
| return [...layout]; | ||
| } | ||
| if (l.y === y && l.x === x) { | ||
| return [...layout]; | ||
| } | ||
| const oldX = l.x; | ||
| const oldY = l.y; | ||
| if (typeof x === "number") l.x = x; | ||
| if (typeof y === "number") l.y = y; | ||
| l.moved = true; | ||
| let sorted = sortLayoutItems(layout, compactType); | ||
| const movingUp = compactType === "vertical" && typeof y === "number" ? oldY >= y : compactType === "horizontal" && typeof x === "number" ? oldX >= x : false; | ||
| if (movingUp) { | ||
| sorted = sorted.reverse(); | ||
| } | ||
| const collisions = getAllCollisions(sorted, l); | ||
| const hasCollisions = collisions.length > 0; | ||
| if (hasCollisions && allowOverlap) { | ||
| return cloneLayout(layout); | ||
| } | ||
| if (hasCollisions && preventCollision) { | ||
| l.x = oldX; | ||
| l.y = oldY; | ||
| l.moved = false; | ||
| return layout; | ||
| } | ||
| let resultLayout = [...layout]; | ||
| for (let i = 0; i < collisions.length; i++) { | ||
| const collision = collisions[i]; | ||
| if (collision === void 0) continue; | ||
| if (collision.moved) continue; | ||
| if (collision.static) { | ||
| resultLayout = moveElementAwayFromCollision( | ||
| resultLayout, | ||
| collision, | ||
| l, | ||
| isUserAction, | ||
| compactType); | ||
| } else { | ||
| resultLayout = moveElementAwayFromCollision( | ||
| resultLayout, | ||
| l, | ||
| collision, | ||
| isUserAction, | ||
| compactType); | ||
| } | ||
| } | ||
| return resultLayout; | ||
| } | ||
| function moveElementAwayFromCollision(layout, collidesWith, itemToMove, isUserAction, compactType, cols) { | ||
| const compactH = compactType === "horizontal"; | ||
| const compactV = compactType === "vertical"; | ||
| const preventCollision = collidesWith.static; | ||
| if (isUserAction) { | ||
| isUserAction = false; | ||
| const fakeItem = { | ||
| x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x, | ||
| y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y, | ||
| w: itemToMove.w, | ||
| h: itemToMove.h, | ||
| i: "-1" | ||
| }; | ||
| const firstCollision = getFirstCollision(layout, fakeItem); | ||
| const collisionNorth = firstCollision !== void 0 && firstCollision.y + firstCollision.h > collidesWith.y; | ||
| const collisionWest = firstCollision !== void 0 && collidesWith.x + collidesWith.w > firstCollision.x; | ||
| if (!firstCollision) { | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| compactH ? fakeItem.x : void 0, | ||
| compactV ? fakeItem.y : void 0, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| if (collisionNorth && compactV) { | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| void 0, | ||
| itemToMove.y + 1, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| if (collisionNorth && compactType === null) { | ||
| collidesWith.y = itemToMove.y; | ||
| itemToMove.y = itemToMove.y + itemToMove.h; | ||
| return [...layout]; | ||
| } | ||
| if (collisionWest && compactH) { | ||
| return moveElement( | ||
| layout, | ||
| collidesWith, | ||
| itemToMove.x, | ||
| void 0, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| } | ||
| const newX = compactH ? itemToMove.x + 1 : void 0; | ||
| const newY = compactV ? itemToMove.y + 1 : void 0; | ||
| if (newX === void 0 && newY === void 0) { | ||
| return [...layout]; | ||
| } | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| newX, | ||
| newY, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| function validateLayout(layout, contextName = "Layout") { | ||
| const requiredProps = ["x", "y", "w", "h"]; | ||
| if (!Array.isArray(layout)) { | ||
| throw new Error(`${contextName} must be an array!`); | ||
| } | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item === void 0) continue; | ||
| for (const key of requiredProps) { | ||
| const value = item[key]; | ||
| if (typeof value !== "number" || Number.isNaN(value)) { | ||
| throw new Error( | ||
| `ReactGridLayout: ${contextName}[${i}].${key} must be a number! Received: ${String(value)} (${typeof value})` | ||
| ); | ||
| } | ||
| } | ||
| if (item.i !== void 0 && typeof item.i !== "string") { | ||
| throw new Error( | ||
| `ReactGridLayout: ${contextName}[${i}].i must be a string! Received: ${String(item.i)} (${typeof item.i})` | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| // src/core/compact-compat.ts | ||
| function getStatics2(layout) { | ||
| return layout.filter((l) => l.static); | ||
| } | ||
| var heightWidth = { x: "w", y: "h" }; | ||
| function resolveCompactionCollision(layout, item, moveToCoord, axis) { | ||
| const sizeProp = heightWidth[axis]; | ||
| item[axis] += 1; | ||
| const itemIndex = layout.findIndex((l) => l.i === item.i); | ||
| for (let i = itemIndex + 1; i < layout.length; i++) { | ||
| const otherItem = layout[i]; | ||
| if (otherItem === void 0) continue; | ||
| if (otherItem.static) continue; | ||
| if (otherItem.y > item.y + item.h) break; | ||
| if (collides(item, otherItem)) { | ||
| resolveCompactionCollision( | ||
| layout, | ||
| otherItem, | ||
| moveToCoord + item[sizeProp], | ||
| axis | ||
| ); | ||
| } | ||
| } | ||
| item[axis] = moveToCoord; | ||
| } | ||
| function compactItemInternal(compareWith, l, compactType, cols, fullLayout, allowOverlap, b) { | ||
| const compactV = compactType === "vertical"; | ||
| const compactH = compactType === "horizontal"; | ||
| if (compactV) { | ||
| if (typeof b === "number") { | ||
| l.y = Math.min(b, l.y); | ||
| } else { | ||
| l.y = Math.min(bottom(compareWith), l.y); | ||
| } | ||
| while (l.y > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.y--; | ||
| } | ||
| } else if (compactH) { | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| let collision; | ||
| while ((collision = getFirstCollision(compareWith, l)) !== void 0 && !(compactType === null && allowOverlap)) { | ||
| if (compactH) { | ||
| resolveCompactionCollision(fullLayout, l, collision.x + collision.w, "x"); | ||
| } else { | ||
| resolveCompactionCollision(fullLayout, l, collision.y + collision.h, "y"); | ||
| } | ||
| if (compactH && l.x + l.w > cols) { | ||
| l.x = cols - l.w; | ||
| l.y++; | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| } | ||
| l.y = Math.max(l.y, 0); | ||
| l.x = Math.max(l.x, 0); | ||
| return l; | ||
| } | ||
| function compact(layout, compactType, cols, allowOverlap) { | ||
| const compareWith = getStatics2(layout); | ||
| let b = bottom(compareWith); | ||
| const sorted = sortLayoutItems(layout, compactType); | ||
| const out = new Array(layout.length); | ||
| for (let i = 0; i < sorted.length; i++) { | ||
| const sortedItem = sorted[i]; | ||
| if (sortedItem === void 0) continue; | ||
| let l = cloneLayoutItem(sortedItem); | ||
| if (!l.static) { | ||
| l = compactItemInternal( | ||
| compareWith, | ||
| l, | ||
| compactType, | ||
| cols, | ||
| sorted, | ||
| allowOverlap, | ||
| b | ||
| ); | ||
| b = Math.max(b, l.y + l.h); | ||
| compareWith.push(l); | ||
| } | ||
| const originalIndex = layout.indexOf(sortedItem); | ||
| out[originalIndex] = l; | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| } | ||
| function compactItem(compareWith, l, compactType, cols, fullLayout, allowOverlap, maxY) { | ||
| return compactItemInternal( | ||
| compareWith, | ||
| cloneLayoutItem(l), | ||
| compactType, | ||
| cols, | ||
| fullLayout, | ||
| allowOverlap, | ||
| maxY | ||
| ); | ||
| } | ||
| // src/core/compactors.ts | ||
| function resolveCompactionCollision2(layout, item, moveToCoord, axis) { | ||
| const sizeProp = axis === "x" ? "w" : "h"; | ||
| item[axis] += 1; | ||
| const itemIndex = layout.findIndex((l) => l.i === item.i); | ||
| for (let i = itemIndex + 1; i < layout.length; i++) { | ||
| const otherItem = layout[i]; | ||
| if (otherItem === void 0) continue; | ||
| if (otherItem.static) continue; | ||
| if (otherItem.y > item.y + item.h) break; | ||
| if (collides(item, otherItem)) { | ||
| resolveCompactionCollision2( | ||
| layout, | ||
| otherItem, | ||
| moveToCoord + item[sizeProp], | ||
| axis | ||
| ); | ||
| } | ||
| } | ||
| item[axis] = moveToCoord; | ||
| } | ||
| function compactItemVertical(compareWith, l, fullLayout, maxY) { | ||
| l.y = Math.min(maxY, l.y); | ||
| while (l.y > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.y--; | ||
| } | ||
| let collision; | ||
| while ((collision = getFirstCollision(compareWith, l)) !== void 0) { | ||
| resolveCompactionCollision2(fullLayout, l, collision.y + collision.h, "y"); | ||
| } | ||
| l.y = Math.max(l.y, 0); | ||
| return l; | ||
| } | ||
| function compactItemHorizontal(compareWith, l, cols, fullLayout) { | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| let collision; | ||
| while ((collision = getFirstCollision(compareWith, l)) !== void 0) { | ||
| resolveCompactionCollision2(fullLayout, l, collision.x + collision.w, "x"); | ||
| if (l.x + l.w > cols) { | ||
| l.x = cols - l.w; | ||
| l.y++; | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| } | ||
| l.x = Math.max(l.x, 0); | ||
| return l; | ||
| } | ||
| var verticalCompactor = { | ||
| type: "vertical", | ||
| allowOverlap: false, | ||
| compact(layout, _cols) { | ||
| const compareWith = getStatics(layout); | ||
| let maxY = bottom(compareWith); | ||
| const sorted = sortLayoutItemsByRowCol(layout); | ||
| const out = new Array(layout.length); | ||
| for (let i = 0; i < sorted.length; i++) { | ||
| const sortedItem = sorted[i]; | ||
| if (sortedItem === void 0) continue; | ||
| let l = cloneLayoutItem(sortedItem); | ||
| if (!l.static) { | ||
| l = compactItemVertical(compareWith, l, sorted, maxY); | ||
| maxY = Math.max(maxY, l.y + l.h); | ||
| compareWith.push(l); | ||
| } | ||
| const originalIndex = layout.indexOf(sortedItem); | ||
| out[originalIndex] = l; | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| }, | ||
| onMove(layout, item, x, y, _cols) { | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find((l) => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = y; | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| var horizontalCompactor = { | ||
| type: "horizontal", | ||
| allowOverlap: false, | ||
| compact(layout, cols) { | ||
| const compareWith = getStatics(layout); | ||
| const sorted = sortLayoutItemsByColRow(layout); | ||
| const out = new Array(layout.length); | ||
| for (let i = 0; i < sorted.length; i++) { | ||
| const sortedItem = sorted[i]; | ||
| if (sortedItem === void 0) continue; | ||
| let l = cloneLayoutItem(sortedItem); | ||
| if (!l.static) { | ||
| l = compactItemHorizontal(compareWith, l, cols, sorted); | ||
| compareWith.push(l); | ||
| } | ||
| const originalIndex = layout.indexOf(sortedItem); | ||
| out[originalIndex] = l; | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| }, | ||
| onMove(layout, item, x, y, _cols) { | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find((l) => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = y; | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| var noCompactor = { | ||
| type: null, | ||
| allowOverlap: false, | ||
| compact(layout, _cols) { | ||
| return cloneLayout(layout); | ||
| }, | ||
| onMove(layout, item, x, y, _cols) { | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find((l) => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = y; | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| var verticalOverlapCompactor = { | ||
| ...verticalCompactor, | ||
| allowOverlap: true, | ||
| compact(layout, _cols) { | ||
| return cloneLayout(layout); | ||
| } | ||
| }; | ||
| var horizontalOverlapCompactor = { | ||
| ...horizontalCompactor, | ||
| allowOverlap: true, | ||
| compact(layout, _cols) { | ||
| return cloneLayout(layout); | ||
| } | ||
| }; | ||
| function getCompactor(compactType, allowOverlap = false, preventCollision = false) { | ||
| let baseCompactor; | ||
| if (allowOverlap) { | ||
| if (compactType === "vertical") baseCompactor = verticalOverlapCompactor; | ||
| else if (compactType === "horizontal") | ||
| baseCompactor = horizontalOverlapCompactor; | ||
| else baseCompactor = noCompactor; | ||
| } else { | ||
| if (compactType === "vertical") baseCompactor = verticalCompactor; | ||
| else if (compactType === "horizontal") baseCompactor = horizontalCompactor; | ||
| else baseCompactor = noCompactor; | ||
| } | ||
| if (preventCollision) { | ||
| return { ...baseCompactor, preventCollision }; | ||
| } | ||
| return baseCompactor; | ||
| } | ||
| // src/core/responsive.ts | ||
| function sortBreakpoints(breakpoints) { | ||
| const keys = Object.keys(breakpoints); | ||
| return keys.sort((a, b) => breakpoints[a] - breakpoints[b]); | ||
| } | ||
| function getBreakpointFromWidth(breakpoints, width) { | ||
| const sorted = sortBreakpoints(breakpoints); | ||
| let matching = sorted[0]; | ||
| if (matching === void 0) { | ||
| throw new Error("No breakpoints defined"); | ||
| } | ||
| for (let i = 1; i < sorted.length; i++) { | ||
| const breakpointName = sorted[i]; | ||
| if (breakpointName === void 0) continue; | ||
| const breakpointWidth = breakpoints[breakpointName]; | ||
| if (width > breakpointWidth) { | ||
| matching = breakpointName; | ||
| } | ||
| } | ||
| return matching; | ||
| } | ||
| function getColsFromBreakpoint(breakpoint, cols) { | ||
| const colCount = cols[breakpoint]; | ||
| if (colCount === void 0) { | ||
| throw new Error( | ||
| `ResponsiveReactGridLayout: \`cols\` entry for breakpoint ${String(breakpoint)} is missing!` | ||
| ); | ||
| } | ||
| return colCount; | ||
| } | ||
| function findOrGenerateResponsiveLayout(layouts, breakpoints, breakpoint, lastBreakpoint, cols, compactType) { | ||
| const existingLayout = layouts[breakpoint]; | ||
| if (existingLayout) { | ||
| return cloneLayout(existingLayout); | ||
| } | ||
| let layout = layouts[lastBreakpoint]; | ||
| const breakpointsSorted = sortBreakpoints(breakpoints); | ||
| const breakpointsAbove = breakpointsSorted.slice( | ||
| breakpointsSorted.indexOf(breakpoint) | ||
| ); | ||
| for (let i = 0; i < breakpointsAbove.length; i++) { | ||
| const b = breakpointsAbove[i]; | ||
| if (b === void 0) continue; | ||
| const layoutForBreakpoint = layouts[b]; | ||
| if (layoutForBreakpoint) { | ||
| layout = layoutForBreakpoint; | ||
| break; | ||
| } | ||
| } | ||
| const clonedLayout = cloneLayout(layout || []); | ||
| return compact(correctBounds(clonedLayout, { cols }), compactType, cols); | ||
| } | ||
| function getIndentationValue(value, breakpoint) { | ||
| if (Array.isArray(value)) { | ||
| return value; | ||
| } | ||
| const breakpointMap = value; | ||
| const breakpointValue = breakpointMap[breakpoint]; | ||
| if (breakpointValue !== void 0) { | ||
| return breakpointValue; | ||
| } | ||
| const keys = Object.keys(breakpointMap); | ||
| for (const key of keys) { | ||
| const v = breakpointMap[key]; | ||
| if (v !== void 0) { | ||
| return v; | ||
| } | ||
| } | ||
| return [10, 10]; | ||
| } | ||
| exports.absoluteStrategy = absoluteStrategy; | ||
| exports.bottom = bottom; | ||
| exports.cloneLayout = cloneLayout; | ||
| exports.cloneLayoutItem = cloneLayoutItem; | ||
| exports.collides = collides; | ||
| exports.compact = compact; | ||
| exports.compactItem = compactItem; | ||
| exports.compactItemHorizontal = compactItemHorizontal; | ||
| exports.compactItemVertical = compactItemVertical; | ||
| exports.correctBounds = correctBounds; | ||
| exports.createScaledStrategy = createScaledStrategy; | ||
| exports.defaultDragConfig = defaultDragConfig; | ||
| exports.defaultDropConfig = defaultDropConfig; | ||
| exports.defaultGridConfig = defaultGridConfig; | ||
| exports.defaultPositionStrategy = defaultPositionStrategy; | ||
| exports.defaultResizeConfig = defaultResizeConfig; | ||
| exports.findOrGenerateResponsiveLayout = findOrGenerateResponsiveLayout; | ||
| exports.getAllCollisions = getAllCollisions; | ||
| exports.getBreakpointFromWidth = getBreakpointFromWidth; | ||
| exports.getColsFromBreakpoint = getColsFromBreakpoint; | ||
| exports.getCompactor = getCompactor; | ||
| exports.getFirstCollision = getFirstCollision; | ||
| exports.getIndentationValue = getIndentationValue; | ||
| exports.getLayoutItem = getLayoutItem; | ||
| exports.getStatics = getStatics; | ||
| exports.horizontalCompactor = horizontalCompactor; | ||
| exports.horizontalOverlapCompactor = horizontalOverlapCompactor; | ||
| exports.modifyLayout = modifyLayout; | ||
| exports.moveElement = moveElement; | ||
| exports.moveElementAwayFromCollision = moveElementAwayFromCollision; | ||
| exports.noCompactor = noCompactor; | ||
| exports.perc = perc; | ||
| exports.resizeItemInDirection = resizeItemInDirection; | ||
| exports.resolveCompactionCollision = resolveCompactionCollision2; | ||
| exports.setTopLeft = setTopLeft; | ||
| exports.setTransform = setTransform; | ||
| exports.sortBreakpoints = sortBreakpoints; | ||
| exports.sortLayoutItems = sortLayoutItems; | ||
| exports.sortLayoutItemsByColRow = sortLayoutItemsByColRow; | ||
| exports.sortLayoutItemsByRowCol = sortLayoutItemsByRowCol; | ||
| exports.transformStrategy = transformStrategy; | ||
| exports.validateLayout = validateLayout; | ||
| exports.verticalCompactor = verticalCompactor; | ||
| exports.verticalOverlapCompactor = verticalOverlapCompactor; | ||
| exports.withLayoutItem = withLayoutItem; | ||
| //# sourceMappingURL=chunk-3WO4SAYB.js.map | ||
| //# sourceMappingURL=chunk-3WO4SAYB.js.map |
Sorry, the diff of this file is too big to display
| // src/core/position.ts | ||
| function setTransform({ | ||
| top, | ||
| left, | ||
| width, | ||
| height | ||
| }) { | ||
| const translate = `translate(${left}px,${top}px)`; | ||
| return { | ||
| transform: translate, | ||
| WebkitTransform: translate, | ||
| MozTransform: translate, | ||
| msTransform: translate, | ||
| OTransform: translate, | ||
| width: `${width}px`, | ||
| height: `${height}px`, | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| function setTopLeft({ | ||
| top, | ||
| left, | ||
| width, | ||
| height | ||
| }) { | ||
| return { | ||
| top: `${top}px`, | ||
| left: `${left}px`, | ||
| width: `${width}px`, | ||
| height: `${height}px`, | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| function perc(num) { | ||
| return num * 100 + "%"; | ||
| } | ||
| function constrainWidth(left, currentWidth, newWidth, containerWidth) { | ||
| return left + newWidth > containerWidth ? currentWidth : newWidth; | ||
| } | ||
| function constrainHeight(top, currentHeight, newHeight) { | ||
| return top < 0 ? currentHeight : newHeight; | ||
| } | ||
| function constrainLeft(left) { | ||
| return Math.max(0, left); | ||
| } | ||
| function constrainTop(top) { | ||
| return Math.max(0, top); | ||
| } | ||
| var resizeNorth = (currentSize, newSize, _containerWidth) => { | ||
| const { left, height, width } = newSize; | ||
| const top = currentSize.top - (height - currentSize.height); | ||
| return { | ||
| left, | ||
| width, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }; | ||
| }; | ||
| var resizeEast = (currentSize, newSize, containerWidth) => { | ||
| const { top, left, height, width } = newSize; | ||
| return { | ||
| top, | ||
| height, | ||
| width: constrainWidth( | ||
| currentSize.left, | ||
| currentSize.width, | ||
| width, | ||
| containerWidth | ||
| ), | ||
| left: constrainLeft(left) | ||
| }; | ||
| }; | ||
| var resizeWest = (currentSize, newSize, _containerWidth) => { | ||
| const { top, height, width } = newSize; | ||
| const left = currentSize.left + currentSize.width - width; | ||
| if (left < 0) { | ||
| return { | ||
| height, | ||
| width: currentSize.left + currentSize.width, | ||
| top: constrainTop(top), | ||
| left: 0 | ||
| }; | ||
| } | ||
| return { | ||
| height, | ||
| width, | ||
| top: constrainTop(top), | ||
| left | ||
| }; | ||
| }; | ||
| var resizeSouth = (currentSize, newSize, _containerWidth) => { | ||
| const { top, left, height, width } = newSize; | ||
| return { | ||
| width, | ||
| left, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }; | ||
| }; | ||
| var resizeNorthEast = (currentSize, newSize, containerWidth) => resizeNorth( | ||
| currentSize, | ||
| resizeEast(currentSize, newSize, containerWidth)); | ||
| var resizeNorthWest = (currentSize, newSize, containerWidth) => resizeNorth( | ||
| currentSize, | ||
| resizeWest(currentSize, newSize)); | ||
| var resizeSouthEast = (currentSize, newSize, containerWidth) => resizeSouth( | ||
| currentSize, | ||
| resizeEast(currentSize, newSize, containerWidth)); | ||
| var resizeSouthWest = (currentSize, newSize, containerWidth) => resizeSouth( | ||
| currentSize, | ||
| resizeWest(currentSize, newSize)); | ||
| var resizeHandlerMap = { | ||
| n: resizeNorth, | ||
| ne: resizeNorthEast, | ||
| e: resizeEast, | ||
| se: resizeSouthEast, | ||
| s: resizeSouth, | ||
| sw: resizeSouthWest, | ||
| w: resizeWest, | ||
| nw: resizeNorthWest | ||
| }; | ||
| function resizeItemInDirection(direction, currentSize, newSize, containerWidth) { | ||
| const handler = resizeHandlerMap[direction]; | ||
| if (!handler) { | ||
| return newSize; | ||
| } | ||
| return handler(currentSize, { ...currentSize, ...newSize }, containerWidth); | ||
| } | ||
| var transformStrategy = { | ||
| type: "transform", | ||
| scale: 1, | ||
| calcStyle(pos) { | ||
| return setTransform(pos); | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| return { | ||
| left: clientX - offsetX, | ||
| top: clientY - offsetY | ||
| }; | ||
| } | ||
| }; | ||
| var absoluteStrategy = { | ||
| type: "absolute", | ||
| scale: 1, | ||
| calcStyle(pos) { | ||
| return setTopLeft(pos); | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| return { | ||
| left: clientX - offsetX, | ||
| top: clientY - offsetY | ||
| }; | ||
| } | ||
| }; | ||
| function createScaledStrategy(scale) { | ||
| return { | ||
| type: "transform", | ||
| scale, | ||
| calcStyle(pos) { | ||
| return setTransform(pos); | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| return { | ||
| left: (clientX - offsetX) / scale, | ||
| top: (clientY - offsetY) / scale | ||
| }; | ||
| } | ||
| }; | ||
| } | ||
| var defaultPositionStrategy = transformStrategy; | ||
| // src/core/types.ts | ||
| var defaultGridConfig = { | ||
| cols: 12, | ||
| rowHeight: 150, | ||
| margin: [10, 10], | ||
| containerPadding: null, | ||
| maxRows: Infinity | ||
| }; | ||
| var defaultDragConfig = { | ||
| enabled: true, | ||
| bounded: false, | ||
| threshold: 3 | ||
| }; | ||
| var defaultResizeConfig = { | ||
| enabled: true, | ||
| handles: ["se"] | ||
| }; | ||
| var defaultDropConfig = { | ||
| enabled: false, | ||
| defaultItem: { w: 1, h: 1 } | ||
| }; | ||
| // src/core/collision.ts | ||
| function collides(l1, l2) { | ||
| if (l1.i === l2.i) return false; | ||
| if (l1.x + l1.w <= l2.x) return false; | ||
| if (l1.x >= l2.x + l2.w) return false; | ||
| if (l1.y + l1.h <= l2.y) return false; | ||
| if (l1.y >= l2.y + l2.h) return false; | ||
| return true; | ||
| } | ||
| function getFirstCollision(layout, layoutItem) { | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0 && collides(item, layoutItem)) { | ||
| return item; | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| function getAllCollisions(layout, layoutItem) { | ||
| return layout.filter((l) => collides(l, layoutItem)); | ||
| } | ||
| // src/core/sort.ts | ||
| function sortLayoutItems(layout, compactType) { | ||
| if (compactType === "horizontal") { | ||
| return sortLayoutItemsByColRow(layout); | ||
| } | ||
| if (compactType === "vertical") { | ||
| return sortLayoutItemsByRowCol(layout); | ||
| } | ||
| return [...layout]; | ||
| } | ||
| function sortLayoutItemsByRowCol(layout) { | ||
| return [...layout].sort((a, b) => { | ||
| if (a.y !== b.y) { | ||
| return a.y - b.y; | ||
| } | ||
| return a.x - b.x; | ||
| }); | ||
| } | ||
| function sortLayoutItemsByColRow(layout) { | ||
| return [...layout].sort((a, b) => { | ||
| if (a.x !== b.x) { | ||
| return a.x - b.x; | ||
| } | ||
| return a.y - b.y; | ||
| }); | ||
| } | ||
| // src/core/layout.ts | ||
| function bottom(layout) { | ||
| let max = 0; | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0) { | ||
| const bottomY = item.y + item.h; | ||
| if (bottomY > max) max = bottomY; | ||
| } | ||
| } | ||
| return max; | ||
| } | ||
| function getLayoutItem(layout, id) { | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0 && item.i === id) { | ||
| return item; | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| function getStatics(layout) { | ||
| return layout.filter((l) => l.static === true); | ||
| } | ||
| function cloneLayoutItem(layoutItem) { | ||
| return { | ||
| i: layoutItem.i, | ||
| x: layoutItem.x, | ||
| y: layoutItem.y, | ||
| w: layoutItem.w, | ||
| h: layoutItem.h, | ||
| minW: layoutItem.minW, | ||
| maxW: layoutItem.maxW, | ||
| minH: layoutItem.minH, | ||
| maxH: layoutItem.maxH, | ||
| moved: Boolean(layoutItem.moved), | ||
| static: Boolean(layoutItem.static), | ||
| isDraggable: layoutItem.isDraggable, | ||
| isResizable: layoutItem.isResizable, | ||
| resizeHandles: layoutItem.resizeHandles, | ||
| isBounded: layoutItem.isBounded | ||
| }; | ||
| } | ||
| function cloneLayout(layout) { | ||
| const newLayout = new Array(layout.length); | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0) { | ||
| newLayout[i] = cloneLayoutItem(item); | ||
| } | ||
| } | ||
| return newLayout; | ||
| } | ||
| function modifyLayout(layout, layoutItem) { | ||
| const newLayout = new Array(layout.length); | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item !== void 0) { | ||
| if (layoutItem.i === item.i) { | ||
| newLayout[i] = layoutItem; | ||
| } else { | ||
| newLayout[i] = item; | ||
| } | ||
| } | ||
| } | ||
| return newLayout; | ||
| } | ||
| function withLayoutItem(layout, itemKey, cb) { | ||
| let item = getLayoutItem(layout, itemKey); | ||
| if (!item) { | ||
| return [[...layout], null]; | ||
| } | ||
| item = cb(cloneLayoutItem(item)); | ||
| const newLayout = modifyLayout(layout, item); | ||
| return [newLayout, item]; | ||
| } | ||
| function correctBounds(layout, bounds) { | ||
| const collidesWith = getStatics(layout); | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const l = layout[i]; | ||
| if (l === void 0) continue; | ||
| if (l.x + l.w > bounds.cols) { | ||
| l.x = bounds.cols - l.w; | ||
| } | ||
| if (l.x < 0) { | ||
| l.x = 0; | ||
| l.w = bounds.cols; | ||
| } | ||
| if (!l.static) { | ||
| collidesWith.push(l); | ||
| } else { | ||
| while (getFirstCollision(collidesWith, l)) { | ||
| l.y++; | ||
| } | ||
| } | ||
| } | ||
| return layout; | ||
| } | ||
| function moveElement(layout, l, x, y, isUserAction, preventCollision, compactType, cols, allowOverlap) { | ||
| if (l.static && l.isDraggable !== true) { | ||
| return [...layout]; | ||
| } | ||
| if (l.y === y && l.x === x) { | ||
| return [...layout]; | ||
| } | ||
| const oldX = l.x; | ||
| const oldY = l.y; | ||
| if (typeof x === "number") l.x = x; | ||
| if (typeof y === "number") l.y = y; | ||
| l.moved = true; | ||
| let sorted = sortLayoutItems(layout, compactType); | ||
| const movingUp = compactType === "vertical" && typeof y === "number" ? oldY >= y : compactType === "horizontal" && typeof x === "number" ? oldX >= x : false; | ||
| if (movingUp) { | ||
| sorted = sorted.reverse(); | ||
| } | ||
| const collisions = getAllCollisions(sorted, l); | ||
| const hasCollisions = collisions.length > 0; | ||
| if (hasCollisions && allowOverlap) { | ||
| return cloneLayout(layout); | ||
| } | ||
| if (hasCollisions && preventCollision) { | ||
| l.x = oldX; | ||
| l.y = oldY; | ||
| l.moved = false; | ||
| return layout; | ||
| } | ||
| let resultLayout = [...layout]; | ||
| for (let i = 0; i < collisions.length; i++) { | ||
| const collision = collisions[i]; | ||
| if (collision === void 0) continue; | ||
| if (collision.moved) continue; | ||
| if (collision.static) { | ||
| resultLayout = moveElementAwayFromCollision( | ||
| resultLayout, | ||
| collision, | ||
| l, | ||
| isUserAction, | ||
| compactType); | ||
| } else { | ||
| resultLayout = moveElementAwayFromCollision( | ||
| resultLayout, | ||
| l, | ||
| collision, | ||
| isUserAction, | ||
| compactType); | ||
| } | ||
| } | ||
| return resultLayout; | ||
| } | ||
| function moveElementAwayFromCollision(layout, collidesWith, itemToMove, isUserAction, compactType, cols) { | ||
| const compactH = compactType === "horizontal"; | ||
| const compactV = compactType === "vertical"; | ||
| const preventCollision = collidesWith.static; | ||
| if (isUserAction) { | ||
| isUserAction = false; | ||
| const fakeItem = { | ||
| x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x, | ||
| y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y, | ||
| w: itemToMove.w, | ||
| h: itemToMove.h, | ||
| i: "-1" | ||
| }; | ||
| const firstCollision = getFirstCollision(layout, fakeItem); | ||
| const collisionNorth = firstCollision !== void 0 && firstCollision.y + firstCollision.h > collidesWith.y; | ||
| const collisionWest = firstCollision !== void 0 && collidesWith.x + collidesWith.w > firstCollision.x; | ||
| if (!firstCollision) { | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| compactH ? fakeItem.x : void 0, | ||
| compactV ? fakeItem.y : void 0, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| if (collisionNorth && compactV) { | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| void 0, | ||
| itemToMove.y + 1, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| if (collisionNorth && compactType === null) { | ||
| collidesWith.y = itemToMove.y; | ||
| itemToMove.y = itemToMove.y + itemToMove.h; | ||
| return [...layout]; | ||
| } | ||
| if (collisionWest && compactH) { | ||
| return moveElement( | ||
| layout, | ||
| collidesWith, | ||
| itemToMove.x, | ||
| void 0, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| } | ||
| const newX = compactH ? itemToMove.x + 1 : void 0; | ||
| const newY = compactV ? itemToMove.y + 1 : void 0; | ||
| if (newX === void 0 && newY === void 0) { | ||
| return [...layout]; | ||
| } | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| newX, | ||
| newY, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType); | ||
| } | ||
| function validateLayout(layout, contextName = "Layout") { | ||
| const requiredProps = ["x", "y", "w", "h"]; | ||
| if (!Array.isArray(layout)) { | ||
| throw new Error(`${contextName} must be an array!`); | ||
| } | ||
| for (let i = 0; i < layout.length; i++) { | ||
| const item = layout[i]; | ||
| if (item === void 0) continue; | ||
| for (const key of requiredProps) { | ||
| const value = item[key]; | ||
| if (typeof value !== "number" || Number.isNaN(value)) { | ||
| throw new Error( | ||
| `ReactGridLayout: ${contextName}[${i}].${key} must be a number! Received: ${String(value)} (${typeof value})` | ||
| ); | ||
| } | ||
| } | ||
| if (item.i !== void 0 && typeof item.i !== "string") { | ||
| throw new Error( | ||
| `ReactGridLayout: ${contextName}[${i}].i must be a string! Received: ${String(item.i)} (${typeof item.i})` | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| // src/core/compact-compat.ts | ||
| function getStatics2(layout) { | ||
| return layout.filter((l) => l.static); | ||
| } | ||
| var heightWidth = { x: "w", y: "h" }; | ||
| function resolveCompactionCollision(layout, item, moveToCoord, axis) { | ||
| const sizeProp = heightWidth[axis]; | ||
| item[axis] += 1; | ||
| const itemIndex = layout.findIndex((l) => l.i === item.i); | ||
| for (let i = itemIndex + 1; i < layout.length; i++) { | ||
| const otherItem = layout[i]; | ||
| if (otherItem === void 0) continue; | ||
| if (otherItem.static) continue; | ||
| if (otherItem.y > item.y + item.h) break; | ||
| if (collides(item, otherItem)) { | ||
| resolveCompactionCollision( | ||
| layout, | ||
| otherItem, | ||
| moveToCoord + item[sizeProp], | ||
| axis | ||
| ); | ||
| } | ||
| } | ||
| item[axis] = moveToCoord; | ||
| } | ||
| function compactItemInternal(compareWith, l, compactType, cols, fullLayout, allowOverlap, b) { | ||
| const compactV = compactType === "vertical"; | ||
| const compactH = compactType === "horizontal"; | ||
| if (compactV) { | ||
| if (typeof b === "number") { | ||
| l.y = Math.min(b, l.y); | ||
| } else { | ||
| l.y = Math.min(bottom(compareWith), l.y); | ||
| } | ||
| while (l.y > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.y--; | ||
| } | ||
| } else if (compactH) { | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| let collision; | ||
| while ((collision = getFirstCollision(compareWith, l)) !== void 0 && !(compactType === null && allowOverlap)) { | ||
| if (compactH) { | ||
| resolveCompactionCollision(fullLayout, l, collision.x + collision.w, "x"); | ||
| } else { | ||
| resolveCompactionCollision(fullLayout, l, collision.y + collision.h, "y"); | ||
| } | ||
| if (compactH && l.x + l.w > cols) { | ||
| l.x = cols - l.w; | ||
| l.y++; | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| } | ||
| l.y = Math.max(l.y, 0); | ||
| l.x = Math.max(l.x, 0); | ||
| return l; | ||
| } | ||
| function compact(layout, compactType, cols, allowOverlap) { | ||
| const compareWith = getStatics2(layout); | ||
| let b = bottom(compareWith); | ||
| const sorted = sortLayoutItems(layout, compactType); | ||
| const out = new Array(layout.length); | ||
| for (let i = 0; i < sorted.length; i++) { | ||
| const sortedItem = sorted[i]; | ||
| if (sortedItem === void 0) continue; | ||
| let l = cloneLayoutItem(sortedItem); | ||
| if (!l.static) { | ||
| l = compactItemInternal( | ||
| compareWith, | ||
| l, | ||
| compactType, | ||
| cols, | ||
| sorted, | ||
| allowOverlap, | ||
| b | ||
| ); | ||
| b = Math.max(b, l.y + l.h); | ||
| compareWith.push(l); | ||
| } | ||
| const originalIndex = layout.indexOf(sortedItem); | ||
| out[originalIndex] = l; | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| } | ||
| function compactItem(compareWith, l, compactType, cols, fullLayout, allowOverlap, maxY) { | ||
| return compactItemInternal( | ||
| compareWith, | ||
| cloneLayoutItem(l), | ||
| compactType, | ||
| cols, | ||
| fullLayout, | ||
| allowOverlap, | ||
| maxY | ||
| ); | ||
| } | ||
| // src/core/compactors.ts | ||
| function resolveCompactionCollision2(layout, item, moveToCoord, axis) { | ||
| const sizeProp = axis === "x" ? "w" : "h"; | ||
| item[axis] += 1; | ||
| const itemIndex = layout.findIndex((l) => l.i === item.i); | ||
| for (let i = itemIndex + 1; i < layout.length; i++) { | ||
| const otherItem = layout[i]; | ||
| if (otherItem === void 0) continue; | ||
| if (otherItem.static) continue; | ||
| if (otherItem.y > item.y + item.h) break; | ||
| if (collides(item, otherItem)) { | ||
| resolveCompactionCollision2( | ||
| layout, | ||
| otherItem, | ||
| moveToCoord + item[sizeProp], | ||
| axis | ||
| ); | ||
| } | ||
| } | ||
| item[axis] = moveToCoord; | ||
| } | ||
| function compactItemVertical(compareWith, l, fullLayout, maxY) { | ||
| l.y = Math.min(maxY, l.y); | ||
| while (l.y > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.y--; | ||
| } | ||
| let collision; | ||
| while ((collision = getFirstCollision(compareWith, l)) !== void 0) { | ||
| resolveCompactionCollision2(fullLayout, l, collision.y + collision.h, "y"); | ||
| } | ||
| l.y = Math.max(l.y, 0); | ||
| return l; | ||
| } | ||
| function compactItemHorizontal(compareWith, l, cols, fullLayout) { | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| let collision; | ||
| while ((collision = getFirstCollision(compareWith, l)) !== void 0) { | ||
| resolveCompactionCollision2(fullLayout, l, collision.x + collision.w, "x"); | ||
| if (l.x + l.w > cols) { | ||
| l.x = cols - l.w; | ||
| l.y++; | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| } | ||
| l.x = Math.max(l.x, 0); | ||
| return l; | ||
| } | ||
| var verticalCompactor = { | ||
| type: "vertical", | ||
| allowOverlap: false, | ||
| compact(layout, _cols) { | ||
| const compareWith = getStatics(layout); | ||
| let maxY = bottom(compareWith); | ||
| const sorted = sortLayoutItemsByRowCol(layout); | ||
| const out = new Array(layout.length); | ||
| for (let i = 0; i < sorted.length; i++) { | ||
| const sortedItem = sorted[i]; | ||
| if (sortedItem === void 0) continue; | ||
| let l = cloneLayoutItem(sortedItem); | ||
| if (!l.static) { | ||
| l = compactItemVertical(compareWith, l, sorted, maxY); | ||
| maxY = Math.max(maxY, l.y + l.h); | ||
| compareWith.push(l); | ||
| } | ||
| const originalIndex = layout.indexOf(sortedItem); | ||
| out[originalIndex] = l; | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| }, | ||
| onMove(layout, item, x, y, _cols) { | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find((l) => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = y; | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| var horizontalCompactor = { | ||
| type: "horizontal", | ||
| allowOverlap: false, | ||
| compact(layout, cols) { | ||
| const compareWith = getStatics(layout); | ||
| const sorted = sortLayoutItemsByColRow(layout); | ||
| const out = new Array(layout.length); | ||
| for (let i = 0; i < sorted.length; i++) { | ||
| const sortedItem = sorted[i]; | ||
| if (sortedItem === void 0) continue; | ||
| let l = cloneLayoutItem(sortedItem); | ||
| if (!l.static) { | ||
| l = compactItemHorizontal(compareWith, l, cols, sorted); | ||
| compareWith.push(l); | ||
| } | ||
| const originalIndex = layout.indexOf(sortedItem); | ||
| out[originalIndex] = l; | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| }, | ||
| onMove(layout, item, x, y, _cols) { | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find((l) => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = y; | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| var noCompactor = { | ||
| type: null, | ||
| allowOverlap: false, | ||
| compact(layout, _cols) { | ||
| return cloneLayout(layout); | ||
| }, | ||
| onMove(layout, item, x, y, _cols) { | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find((l) => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = y; | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| var verticalOverlapCompactor = { | ||
| ...verticalCompactor, | ||
| allowOverlap: true, | ||
| compact(layout, _cols) { | ||
| return cloneLayout(layout); | ||
| } | ||
| }; | ||
| var horizontalOverlapCompactor = { | ||
| ...horizontalCompactor, | ||
| allowOverlap: true, | ||
| compact(layout, _cols) { | ||
| return cloneLayout(layout); | ||
| } | ||
| }; | ||
| function getCompactor(compactType, allowOverlap = false, preventCollision = false) { | ||
| let baseCompactor; | ||
| if (allowOverlap) { | ||
| if (compactType === "vertical") baseCompactor = verticalOverlapCompactor; | ||
| else if (compactType === "horizontal") | ||
| baseCompactor = horizontalOverlapCompactor; | ||
| else baseCompactor = noCompactor; | ||
| } else { | ||
| if (compactType === "vertical") baseCompactor = verticalCompactor; | ||
| else if (compactType === "horizontal") baseCompactor = horizontalCompactor; | ||
| else baseCompactor = noCompactor; | ||
| } | ||
| if (preventCollision) { | ||
| return { ...baseCompactor, preventCollision }; | ||
| } | ||
| return baseCompactor; | ||
| } | ||
| // src/core/responsive.ts | ||
| function sortBreakpoints(breakpoints) { | ||
| const keys = Object.keys(breakpoints); | ||
| return keys.sort((a, b) => breakpoints[a] - breakpoints[b]); | ||
| } | ||
| function getBreakpointFromWidth(breakpoints, width) { | ||
| const sorted = sortBreakpoints(breakpoints); | ||
| let matching = sorted[0]; | ||
| if (matching === void 0) { | ||
| throw new Error("No breakpoints defined"); | ||
| } | ||
| for (let i = 1; i < sorted.length; i++) { | ||
| const breakpointName = sorted[i]; | ||
| if (breakpointName === void 0) continue; | ||
| const breakpointWidth = breakpoints[breakpointName]; | ||
| if (width > breakpointWidth) { | ||
| matching = breakpointName; | ||
| } | ||
| } | ||
| return matching; | ||
| } | ||
| function getColsFromBreakpoint(breakpoint, cols) { | ||
| const colCount = cols[breakpoint]; | ||
| if (colCount === void 0) { | ||
| throw new Error( | ||
| `ResponsiveReactGridLayout: \`cols\` entry for breakpoint ${String(breakpoint)} is missing!` | ||
| ); | ||
| } | ||
| return colCount; | ||
| } | ||
| function findOrGenerateResponsiveLayout(layouts, breakpoints, breakpoint, lastBreakpoint, cols, compactType) { | ||
| const existingLayout = layouts[breakpoint]; | ||
| if (existingLayout) { | ||
| return cloneLayout(existingLayout); | ||
| } | ||
| let layout = layouts[lastBreakpoint]; | ||
| const breakpointsSorted = sortBreakpoints(breakpoints); | ||
| const breakpointsAbove = breakpointsSorted.slice( | ||
| breakpointsSorted.indexOf(breakpoint) | ||
| ); | ||
| for (let i = 0; i < breakpointsAbove.length; i++) { | ||
| const b = breakpointsAbove[i]; | ||
| if (b === void 0) continue; | ||
| const layoutForBreakpoint = layouts[b]; | ||
| if (layoutForBreakpoint) { | ||
| layout = layoutForBreakpoint; | ||
| break; | ||
| } | ||
| } | ||
| const clonedLayout = cloneLayout(layout || []); | ||
| return compact(correctBounds(clonedLayout, { cols }), compactType, cols); | ||
| } | ||
| function getIndentationValue(value, breakpoint) { | ||
| if (Array.isArray(value)) { | ||
| return value; | ||
| } | ||
| const breakpointMap = value; | ||
| const breakpointValue = breakpointMap[breakpoint]; | ||
| if (breakpointValue !== void 0) { | ||
| return breakpointValue; | ||
| } | ||
| const keys = Object.keys(breakpointMap); | ||
| for (const key of keys) { | ||
| const v = breakpointMap[key]; | ||
| if (v !== void 0) { | ||
| return v; | ||
| } | ||
| } | ||
| return [10, 10]; | ||
| } | ||
| export { absoluteStrategy, bottom, cloneLayout, cloneLayoutItem, collides, compact, compactItem, compactItemHorizontal, compactItemVertical, correctBounds, createScaledStrategy, defaultDragConfig, defaultDropConfig, defaultGridConfig, defaultPositionStrategy, defaultResizeConfig, findOrGenerateResponsiveLayout, getAllCollisions, getBreakpointFromWidth, getColsFromBreakpoint, getCompactor, getFirstCollision, getIndentationValue, getLayoutItem, getStatics, horizontalCompactor, horizontalOverlapCompactor, modifyLayout, moveElement, moveElementAwayFromCollision, noCompactor, perc, resizeItemInDirection, resolveCompactionCollision2 as resolveCompactionCollision, setTopLeft, setTransform, sortBreakpoints, sortLayoutItems, sortLayoutItemsByColRow, sortLayoutItemsByRowCol, transformStrategy, validateLayout, verticalCompactor, verticalOverlapCompactor, withLayoutItem }; | ||
| //# sourceMappingURL=chunk-4HNUMWQK.mjs.map | ||
| //# sourceMappingURL=chunk-4HNUMWQK.mjs.map |
Sorry, the diff of this file is too big to display
| 'use strict'; | ||
| var chunk3WO4SAYB_js = require('./chunk-3WO4SAYB.js'); | ||
| var chunkF6NQPYKT_js = require('./chunk-F6NQPYKT.js'); | ||
| var React2 = require('react'); | ||
| var reactDraggable = require('react-draggable'); | ||
| var reactResizable = require('react-resizable'); | ||
| var clsx = require('clsx'); | ||
| var jsxRuntime = require('react/jsx-runtime'); | ||
| var fastEquals = require('fast-equals'); | ||
| function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } | ||
| var React2__default = /*#__PURE__*/_interopDefault(React2); | ||
| var clsx__default = /*#__PURE__*/_interopDefault(clsx); | ||
| function GridItem(props) { | ||
| const { | ||
| children, | ||
| cols, | ||
| containerWidth, | ||
| margin, | ||
| containerPadding, | ||
| rowHeight, | ||
| maxRows, | ||
| isDraggable, | ||
| isResizable, | ||
| isBounded, | ||
| static: isStatic, | ||
| useCSSTransforms = true, | ||
| usePercentages = false, | ||
| transformScale = 1, | ||
| droppingPosition, | ||
| className = "", | ||
| style, | ||
| handle = "", | ||
| cancel = "", | ||
| x, | ||
| y, | ||
| w, | ||
| h, | ||
| minW = 1, | ||
| maxW = Infinity, | ||
| minH = 1, | ||
| maxH = Infinity, | ||
| i, | ||
| resizeHandles, | ||
| resizeHandle, | ||
| onDragStart: onDragStartProp, | ||
| onDrag: onDragProp, | ||
| onDragStop: onDragStopProp, | ||
| onResizeStart: onResizeStartProp, | ||
| onResize: onResizeProp, | ||
| onResizeStop: onResizeStopProp | ||
| } = props; | ||
| const [dragging, setDragging] = React2.useState(false); | ||
| const [resizing, setResizing] = React2.useState(false); | ||
| const elementRef = React2.useRef(null); | ||
| const dragPositionRef = React2.useRef({ left: 0, top: 0 }); | ||
| const resizePositionRef = React2.useRef({ | ||
| top: 0, | ||
| left: 0, | ||
| width: 0, | ||
| height: 0 | ||
| }); | ||
| const prevDroppingPositionRef = React2.useRef( | ||
| void 0 | ||
| ); | ||
| const positionParams = React2.useMemo( | ||
| () => ({ | ||
| cols, | ||
| containerPadding, | ||
| containerWidth, | ||
| margin, | ||
| maxRows, | ||
| rowHeight | ||
| }), | ||
| [cols, containerPadding, containerWidth, margin, maxRows, rowHeight] | ||
| ); | ||
| const createStyle = React2.useCallback( | ||
| (pos2) => { | ||
| if (useCSSTransforms) { | ||
| return chunk3WO4SAYB_js.setTransform(pos2); | ||
| } | ||
| const styleObj = chunk3WO4SAYB_js.setTopLeft(pos2); | ||
| if (usePercentages) { | ||
| return { | ||
| ...styleObj, | ||
| left: chunk3WO4SAYB_js.perc(pos2.left / containerWidth), | ||
| width: chunk3WO4SAYB_js.perc(pos2.width / containerWidth) | ||
| }; | ||
| } | ||
| return styleObj; | ||
| }, | ||
| [useCSSTransforms, usePercentages, containerWidth] | ||
| ); | ||
| const onDragStart = React2.useCallback( | ||
| (e, { node }) => { | ||
| if (!onDragStartProp) return; | ||
| const { offsetParent } = node; | ||
| if (!offsetParent) return; | ||
| const parentRect = offsetParent.getBoundingClientRect(); | ||
| const clientRect = node.getBoundingClientRect(); | ||
| const cLeft = clientRect.left / transformScale; | ||
| const pLeft = parentRect.left / transformScale; | ||
| const cTop = clientRect.top / transformScale; | ||
| const pTop = parentRect.top / transformScale; | ||
| const newPosition = { | ||
| left: cLeft - pLeft + offsetParent.scrollLeft, | ||
| top: cTop - pTop + offsetParent.scrollTop | ||
| }; | ||
| dragPositionRef.current = newPosition; | ||
| setDragging(true); | ||
| const { x: newX, y: newY } = chunkF6NQPYKT_js.calcXY( | ||
| positionParams, | ||
| newPosition.top, | ||
| newPosition.left, | ||
| w, | ||
| h | ||
| ); | ||
| onDragStartProp(i, newX, newY, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }, | ||
| [onDragStartProp, transformScale, positionParams, w, h, i] | ||
| ); | ||
| const onDrag = React2.useCallback( | ||
| (e, { node, deltaX, deltaY }) => { | ||
| if (!onDragProp || !dragging) return; | ||
| let top = dragPositionRef.current.top + deltaY; | ||
| let left = dragPositionRef.current.left + deltaX; | ||
| if (isBounded) { | ||
| const { offsetParent } = node; | ||
| if (offsetParent) { | ||
| const bottomBoundary = offsetParent.clientHeight - chunkF6NQPYKT_js.calcGridItemWHPx(h, rowHeight, margin[1]); | ||
| top = chunkF6NQPYKT_js.clamp(top, 0, bottomBoundary); | ||
| const colWidth = chunkF6NQPYKT_js.calcGridColWidth(positionParams); | ||
| const rightBoundary = containerWidth - chunkF6NQPYKT_js.calcGridItemWHPx(w, colWidth, margin[0]); | ||
| left = chunkF6NQPYKT_js.clamp(left, 0, rightBoundary); | ||
| } | ||
| } | ||
| const newPosition = { top, left }; | ||
| dragPositionRef.current = newPosition; | ||
| const { x: newX, y: newY } = chunkF6NQPYKT_js.calcXY(positionParams, top, left, w, h); | ||
| onDragProp(i, newX, newY, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }, | ||
| [ | ||
| onDragProp, | ||
| dragging, | ||
| isBounded, | ||
| h, | ||
| rowHeight, | ||
| margin, | ||
| positionParams, | ||
| containerWidth, | ||
| w, | ||
| i | ||
| ] | ||
| ); | ||
| const onDragStop = React2.useCallback( | ||
| (e, { node }) => { | ||
| if (!onDragStopProp || !dragging) return; | ||
| const { left, top } = dragPositionRef.current; | ||
| const newPosition = { top, left }; | ||
| setDragging(false); | ||
| dragPositionRef.current = { left: 0, top: 0 }; | ||
| const { x: newX, y: newY } = chunkF6NQPYKT_js.calcXY(positionParams, top, left, w, h); | ||
| onDragStopProp(i, newX, newY, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }, | ||
| [onDragStopProp, dragging, positionParams, w, h, i] | ||
| ); | ||
| const onResizeHandler = React2.useCallback( | ||
| (e, { node, size, handle: resizeHandle2 }, position, handlerName) => { | ||
| const handler = handlerName === "onResizeStart" ? onResizeStartProp : handlerName === "onResize" ? onResizeProp : onResizeStopProp; | ||
| if (!handler) return; | ||
| let updatedSize; | ||
| if (node) { | ||
| updatedSize = chunk3WO4SAYB_js.resizeItemInDirection( | ||
| resizeHandle2, | ||
| position, | ||
| size, | ||
| containerWidth | ||
| ); | ||
| } else { | ||
| updatedSize = { | ||
| ...size, | ||
| top: position.top, | ||
| left: position.left | ||
| }; | ||
| } | ||
| resizePositionRef.current = updatedSize; | ||
| let { w: newW, h: newH } = chunkF6NQPYKT_js.calcWH( | ||
| positionParams, | ||
| updatedSize.width, | ||
| updatedSize.height, | ||
| x, | ||
| y, | ||
| resizeHandle2 | ||
| ); | ||
| newW = chunkF6NQPYKT_js.clamp(newW, Math.max(minW, 1), maxW); | ||
| newH = chunkF6NQPYKT_js.clamp(newH, minH, maxH); | ||
| handler(i, newW, newH, { | ||
| e: e.nativeEvent, | ||
| node, | ||
| size: updatedSize, | ||
| handle: resizeHandle2 | ||
| }); | ||
| }, | ||
| [ | ||
| onResizeStartProp, | ||
| onResizeProp, | ||
| onResizeStopProp, | ||
| containerWidth, | ||
| positionParams, | ||
| x, | ||
| y, | ||
| minW, | ||
| maxW, | ||
| minH, | ||
| maxH, | ||
| i | ||
| ] | ||
| ); | ||
| const handleResizeStart = React2.useCallback( | ||
| (e, data) => { | ||
| setResizing(true); | ||
| const pos2 = chunkF6NQPYKT_js.calcGridItemPosition(positionParams, x, y, w, h); | ||
| const typedData = { | ||
| ...data, | ||
| handle: data.handle | ||
| }; | ||
| onResizeHandler(e, typedData, pos2, "onResizeStart"); | ||
| }, | ||
| [onResizeHandler, positionParams, x, y, w, h] | ||
| ); | ||
| const handleResize = React2.useCallback( | ||
| (e, data) => { | ||
| const pos2 = chunkF6NQPYKT_js.calcGridItemPosition(positionParams, x, y, w, h); | ||
| const typedData = { | ||
| ...data, | ||
| handle: data.handle | ||
| }; | ||
| onResizeHandler(e, typedData, pos2, "onResize"); | ||
| }, | ||
| [onResizeHandler, positionParams, x, y, w, h] | ||
| ); | ||
| const handleResizeStop = React2.useCallback( | ||
| (e, data) => { | ||
| setResizing(false); | ||
| resizePositionRef.current = { top: 0, left: 0, width: 0, height: 0 }; | ||
| const pos2 = chunkF6NQPYKT_js.calcGridItemPosition(positionParams, x, y, w, h); | ||
| const typedData = { | ||
| ...data, | ||
| handle: data.handle | ||
| }; | ||
| onResizeHandler(e, typedData, pos2, "onResizeStop"); | ||
| }, | ||
| [onResizeHandler, positionParams, x, y, w, h] | ||
| ); | ||
| React2.useEffect(() => { | ||
| if (!droppingPosition) return; | ||
| const node = elementRef.current; | ||
| if (!node) return; | ||
| const prevDroppingPosition = prevDroppingPositionRef.current || { | ||
| left: 0, | ||
| top: 0 | ||
| }; | ||
| const shouldDrag = dragging && (droppingPosition.left !== prevDroppingPosition.left || droppingPosition.top !== prevDroppingPosition.top); | ||
| if (!dragging) { | ||
| const fakeData = { | ||
| node, | ||
| deltaX: droppingPosition.left, | ||
| deltaY: droppingPosition.top, | ||
| lastX: 0, | ||
| lastY: 0, | ||
| x: droppingPosition.left, | ||
| y: droppingPosition.top | ||
| }; | ||
| onDragStart(droppingPosition.e, fakeData); | ||
| } else if (shouldDrag) { | ||
| const deltaX = droppingPosition.left - dragPositionRef.current.left; | ||
| const deltaY = droppingPosition.top - dragPositionRef.current.top; | ||
| const fakeData = { | ||
| node, | ||
| deltaX, | ||
| deltaY, | ||
| lastX: dragPositionRef.current.left, | ||
| lastY: dragPositionRef.current.top, | ||
| x: droppingPosition.left, | ||
| y: droppingPosition.top | ||
| }; | ||
| onDrag(droppingPosition.e, fakeData); | ||
| } | ||
| prevDroppingPositionRef.current = droppingPosition; | ||
| }, [droppingPosition, dragging, onDragStart, onDrag]); | ||
| const pos = chunkF6NQPYKT_js.calcGridItemPosition( | ||
| positionParams, | ||
| x, | ||
| y, | ||
| w, | ||
| h, | ||
| dragging ? dragPositionRef.current : null, | ||
| resizing ? resizePositionRef.current : null | ||
| ); | ||
| const child = React2__default.default.Children.only(children); | ||
| const maxWidth = chunkF6NQPYKT_js.calcGridItemPosition(positionParams, 0, 0, cols, 0).width; | ||
| const mins = chunkF6NQPYKT_js.calcGridItemPosition(positionParams, 0, 0, minW, minH); | ||
| const maxes = chunkF6NQPYKT_js.calcGridItemPosition(positionParams, 0, 0, maxW, maxH); | ||
| const minConstraints = [mins.width, mins.height]; | ||
| const maxConstraints = [ | ||
| Math.min(maxes.width, maxWidth), | ||
| Math.min(maxes.height, Infinity) | ||
| ]; | ||
| const childProps = child.props; | ||
| const childClassName = childProps["className"]; | ||
| const childStyle = childProps["style"]; | ||
| let newChild = React2__default.default.cloneElement(child, { | ||
| ref: elementRef, | ||
| className: clsx__default.default("react-grid-item", childClassName, className, { | ||
| static: isStatic, | ||
| resizing, | ||
| "react-draggable": isDraggable, | ||
| "react-draggable-dragging": dragging, | ||
| dropping: Boolean(droppingPosition), | ||
| cssTransforms: useCSSTransforms | ||
| }), | ||
| style: { | ||
| ...style, | ||
| ...childStyle, | ||
| ...createStyle(pos) | ||
| } | ||
| }); | ||
| const resizableHandle = resizeHandle; | ||
| newChild = /* @__PURE__ */ jsxRuntime.jsx( | ||
| reactResizable.Resizable, | ||
| { | ||
| draggableOpts: { disabled: !isResizable }, | ||
| className: isResizable ? void 0 : "react-resizable-hide", | ||
| width: pos.width, | ||
| height: pos.height, | ||
| minConstraints, | ||
| maxConstraints, | ||
| onResizeStart: handleResizeStart, | ||
| onResize: handleResize, | ||
| onResizeStop: handleResizeStop, | ||
| transformScale, | ||
| resizeHandles, | ||
| handle: resizableHandle, | ||
| children: newChild | ||
| } | ||
| ); | ||
| newChild = /* @__PURE__ */ jsxRuntime.jsx( | ||
| reactDraggable.DraggableCore, | ||
| { | ||
| disabled: !isDraggable, | ||
| onStart: onDragStart, | ||
| onDrag, | ||
| onStop: onDragStop, | ||
| handle, | ||
| cancel: ".react-resizable-handle" + (cancel ? "," + cancel : ""), | ||
| scale: transformScale, | ||
| nodeRef: elementRef, | ||
| children: newChild | ||
| } | ||
| ); | ||
| return newChild; | ||
| } | ||
| var noop = () => { | ||
| }; | ||
| var layoutClassName = "react-grid-layout"; | ||
| var isFirefox = false; | ||
| try { | ||
| isFirefox = /firefox/i.test(navigator.userAgent); | ||
| } catch { | ||
| } | ||
| function childrenEqual(a, b) { | ||
| const aArr = React2__default.default.Children.toArray(a); | ||
| const bArr = React2__default.default.Children.toArray(b); | ||
| if (aArr.length !== bArr.length) return false; | ||
| for (let i = 0; i < aArr.length; i++) { | ||
| const aChild = aArr[i]; | ||
| const bChild = bArr[i]; | ||
| if (aChild?.key !== bChild?.key) return false; | ||
| } | ||
| return true; | ||
| } | ||
| function synchronizeLayoutWithChildren(initialLayout, children, cols, compactType, allowOverlap) { | ||
| const layout = []; | ||
| const childKeys = /* @__PURE__ */ new Set(); | ||
| React2__default.default.Children.forEach(children, (child) => { | ||
| if (!React2__default.default.isValidElement(child) || child.key === null) return; | ||
| const key = String(child.key); | ||
| childKeys.add(key); | ||
| const existingItem = initialLayout.find((l) => l.i === key); | ||
| if (existingItem) { | ||
| layout.push(chunk3WO4SAYB_js.cloneLayoutItem(existingItem)); | ||
| } else { | ||
| const childProps = child.props; | ||
| const dataGrid = childProps["data-grid"]; | ||
| if (dataGrid) { | ||
| layout.push({ | ||
| i: key, | ||
| x: dataGrid.x ?? 0, | ||
| y: dataGrid.y ?? 0, | ||
| w: dataGrid.w ?? 1, | ||
| h: dataGrid.h ?? 1, | ||
| minW: dataGrid.minW, | ||
| maxW: dataGrid.maxW, | ||
| minH: dataGrid.minH, | ||
| maxH: dataGrid.maxH, | ||
| static: dataGrid.static, | ||
| isDraggable: dataGrid.isDraggable, | ||
| isResizable: dataGrid.isResizable, | ||
| resizeHandles: dataGrid.resizeHandles, | ||
| isBounded: dataGrid.isBounded | ||
| }); | ||
| } else { | ||
| layout.push({ | ||
| i: key, | ||
| x: 0, | ||
| y: chunk3WO4SAYB_js.bottom(layout), | ||
| w: 1, | ||
| h: 1 | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| const corrected = chunk3WO4SAYB_js.correctBounds(layout, { cols }); | ||
| return chunk3WO4SAYB_js.compact(corrected, compactType, cols, allowOverlap); | ||
| } | ||
| function GridLayout(props) { | ||
| const { | ||
| // Required | ||
| children, | ||
| width, | ||
| // Composable config interfaces | ||
| gridConfig: gridConfigProp, | ||
| dragConfig: dragConfigProp, | ||
| resizeConfig: resizeConfigProp, | ||
| dropConfig: dropConfigProp, | ||
| positionStrategy = chunk3WO4SAYB_js.defaultPositionStrategy, | ||
| compactor: compactorProp, | ||
| // Layout data | ||
| layout: propsLayout = [], | ||
| droppingItem: droppingItemProp, | ||
| // Container props | ||
| autoSize = true, | ||
| className = "", | ||
| style = {}, | ||
| innerRef, | ||
| // Callbacks | ||
| onLayoutChange = noop, | ||
| onDragStart: onDragStartProp = noop, | ||
| onDrag: onDragProp = noop, | ||
| onDragStop: onDragStopProp = noop, | ||
| onResizeStart: onResizeStartProp = noop, | ||
| onResize: onResizeProp = noop, | ||
| onResizeStop: onResizeStopProp = noop, | ||
| onDrop: onDropProp = noop, | ||
| onDropDragOver: onDropDragOverProp = noop | ||
| } = props; | ||
| const gridConfig = React2.useMemo( | ||
| () => ({ ...chunk3WO4SAYB_js.defaultGridConfig, ...gridConfigProp }), | ||
| [gridConfigProp] | ||
| ); | ||
| const dragConfig = React2.useMemo( | ||
| () => ({ ...chunk3WO4SAYB_js.defaultDragConfig, ...dragConfigProp }), | ||
| [dragConfigProp] | ||
| ); | ||
| const resizeConfig = React2.useMemo( | ||
| () => ({ ...chunk3WO4SAYB_js.defaultResizeConfig, ...resizeConfigProp }), | ||
| [resizeConfigProp] | ||
| ); | ||
| const dropConfig = React2.useMemo( | ||
| () => ({ ...chunk3WO4SAYB_js.defaultDropConfig, ...dropConfigProp }), | ||
| [dropConfigProp] | ||
| ); | ||
| const { cols, rowHeight, maxRows, margin, containerPadding } = gridConfig; | ||
| const { | ||
| enabled: isDraggable, | ||
| bounded: isBounded, | ||
| handle: draggableHandle, | ||
| cancel: draggableCancel | ||
| } = dragConfig; | ||
| const { | ||
| enabled: isResizable, | ||
| handles: resizeHandles, | ||
| handleComponent: resizeHandle | ||
| } = resizeConfig; | ||
| const { enabled: isDroppable, defaultItem: defaultDropItem } = dropConfig; | ||
| const compactor = compactorProp ?? chunk3WO4SAYB_js.getCompactor("vertical"); | ||
| const compactType = compactor.type; | ||
| const allowOverlap = compactor.allowOverlap; | ||
| const preventCollision = compactor.preventCollision ?? false; | ||
| const droppingItem = React2.useMemo( | ||
| () => droppingItemProp ?? { | ||
| i: "__dropping-elem__", | ||
| ...defaultDropItem | ||
| }, | ||
| [droppingItemProp, defaultDropItem] | ||
| ); | ||
| const useCSSTransforms = positionStrategy.type === "transform"; | ||
| const transformScale = positionStrategy.scale; | ||
| const effectiveContainerPadding = containerPadding ?? margin; | ||
| const [mounted, setMounted] = React2.useState(false); | ||
| const [layout, setLayout] = React2.useState( | ||
| () => synchronizeLayoutWithChildren( | ||
| propsLayout, | ||
| children, | ||
| cols, | ||
| compactType, | ||
| allowOverlap | ||
| ) | ||
| ); | ||
| const [activeDrag, setActiveDrag] = React2.useState(null); | ||
| const [resizing, setResizing] = React2.useState(false); | ||
| const [droppingDOMNode, setDroppingDOMNode] = React2.useState( | ||
| null | ||
| ); | ||
| const [droppingPosition, setDroppingPosition] = React2.useState(); | ||
| const oldDragItemRef = React2.useRef(null); | ||
| const oldResizeItemRef = React2.useRef(null); | ||
| const oldLayoutRef = React2.useRef(null); | ||
| const dragEnterCounterRef = React2.useRef(0); | ||
| const prevLayoutRef = React2.useRef(layout); | ||
| const prevPropsLayoutRef = React2.useRef(propsLayout); | ||
| const prevChildrenRef = React2.useRef(children); | ||
| const prevCompactTypeRef = React2.useRef(compactType); | ||
| React2.useEffect(() => { | ||
| setMounted(true); | ||
| if (!fastEquals.deepEqual(layout, propsLayout)) { | ||
| onLayoutChange(layout); | ||
| } | ||
| }, []); | ||
| React2.useEffect(() => { | ||
| if (activeDrag) return; | ||
| const layoutChanged = !fastEquals.deepEqual(propsLayout, prevPropsLayoutRef.current); | ||
| const childrenChanged = !childrenEqual(children, prevChildrenRef.current); | ||
| const compactTypeChanged = compactType !== prevCompactTypeRef.current; | ||
| if (layoutChanged || childrenChanged || compactTypeChanged) { | ||
| const baseLayout = layoutChanged ? propsLayout : layout; | ||
| const newLayout = synchronizeLayoutWithChildren( | ||
| baseLayout, | ||
| children, | ||
| cols, | ||
| compactType, | ||
| allowOverlap | ||
| ); | ||
| setLayout(newLayout); | ||
| } | ||
| prevPropsLayoutRef.current = propsLayout; | ||
| prevChildrenRef.current = children; | ||
| prevCompactTypeRef.current = compactType; | ||
| }, [ | ||
| propsLayout, | ||
| children, | ||
| cols, | ||
| compactType, | ||
| allowOverlap, | ||
| activeDrag, | ||
| layout | ||
| ]); | ||
| React2.useEffect(() => { | ||
| if (!activeDrag && !fastEquals.deepEqual(layout, prevLayoutRef.current)) { | ||
| prevLayoutRef.current = layout; | ||
| onLayoutChange(layout); | ||
| } | ||
| }, [layout, activeDrag, onLayoutChange]); | ||
| const containerHeight = React2.useMemo(() => { | ||
| if (!autoSize) return void 0; | ||
| const nbRow = chunk3WO4SAYB_js.bottom(layout); | ||
| const containerPaddingY = effectiveContainerPadding[1]; | ||
| return nbRow * rowHeight + (nbRow - 1) * margin[1] + containerPaddingY * 2 + "px"; | ||
| }, [autoSize, layout, rowHeight, margin, effectiveContainerPadding]); | ||
| const onDragStart = React2.useCallback( | ||
| (i, _x, _y, data) => { | ||
| const l = chunk3WO4SAYB_js.getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i | ||
| }; | ||
| oldDragItemRef.current = chunk3WO4SAYB_js.cloneLayoutItem(l); | ||
| oldLayoutRef.current = layout; | ||
| setActiveDrag(placeholder); | ||
| onDragStartProp(layout, l, l, null, data.e, data.node); | ||
| }, | ||
| [layout, onDragStartProp] | ||
| ); | ||
| const onDrag = React2.useCallback( | ||
| (i, x, y, data) => { | ||
| const oldDragItem = oldDragItemRef.current; | ||
| const l = chunk3WO4SAYB_js.getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i | ||
| }; | ||
| const newLayout = chunk3WO4SAYB_js.moveElement( | ||
| layout, | ||
| l, | ||
| x, | ||
| y, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| onDragProp(newLayout, oldDragItem, l, placeholder, data.e, data.node); | ||
| setLayout( | ||
| allowOverlap ? newLayout : chunk3WO4SAYB_js.compact(newLayout, compactType, cols) | ||
| ); | ||
| setActiveDrag(placeholder); | ||
| }, | ||
| [layout, preventCollision, compactType, cols, allowOverlap, onDragProp] | ||
| ); | ||
| const onDragStop = React2.useCallback( | ||
| (i, x, y, data) => { | ||
| if (!activeDrag) return; | ||
| const oldDragItem = oldDragItemRef.current; | ||
| const l = chunk3WO4SAYB_js.getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| const newLayout = chunk3WO4SAYB_js.moveElement( | ||
| layout, | ||
| l, | ||
| x, | ||
| y, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const finalLayout = allowOverlap ? newLayout : chunk3WO4SAYB_js.compact(newLayout, compactType, cols); | ||
| onDragStopProp(finalLayout, oldDragItem, l, null, data.e, data.node); | ||
| const oldLayout = oldLayoutRef.current; | ||
| oldDragItemRef.current = null; | ||
| oldLayoutRef.current = null; | ||
| setActiveDrag(null); | ||
| setLayout(finalLayout); | ||
| if (oldLayout && !fastEquals.deepEqual(oldLayout, finalLayout)) { | ||
| onLayoutChange(finalLayout); | ||
| } | ||
| }, | ||
| [ | ||
| activeDrag, | ||
| layout, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap, | ||
| onDragStopProp, | ||
| onLayoutChange | ||
| ] | ||
| ); | ||
| const onResizeStart = React2.useCallback( | ||
| (i, _w, _h, data) => { | ||
| const l = chunk3WO4SAYB_js.getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| oldResizeItemRef.current = chunk3WO4SAYB_js.cloneLayoutItem(l); | ||
| oldLayoutRef.current = layout; | ||
| setResizing(true); | ||
| onResizeStartProp(layout, l, l, null, data.e, data.node); | ||
| }, | ||
| [layout, onResizeStartProp] | ||
| ); | ||
| const onResize = React2.useCallback( | ||
| (i, w, h, data) => { | ||
| const oldResizeItem = oldResizeItemRef.current; | ||
| const { handle } = data; | ||
| let shouldMoveItem = false; | ||
| let newX; | ||
| let newY; | ||
| const [newLayout, l] = chunk3WO4SAYB_js.withLayoutItem(layout, i, (item) => { | ||
| newX = item.x; | ||
| newY = item.y; | ||
| if (["sw", "w", "nw", "n", "ne"].includes(handle)) { | ||
| if (["sw", "nw", "w"].includes(handle)) { | ||
| newX = item.x + (item.w - w); | ||
| w = item.x !== newX && newX < 0 ? item.w : w; | ||
| newX = newX < 0 ? 0 : newX; | ||
| } | ||
| if (["ne", "n", "nw"].includes(handle)) { | ||
| newY = item.y + (item.h - h); | ||
| h = item.y !== newY && newY < 0 ? item.h : h; | ||
| newY = newY < 0 ? 0 : newY; | ||
| } | ||
| shouldMoveItem = true; | ||
| } | ||
| if (preventCollision && !allowOverlap) { | ||
| const collisions = chunk3WO4SAYB_js.getAllCollisions(layout, { | ||
| ...item, | ||
| w, | ||
| h, | ||
| x: newX ?? item.x, | ||
| y: newY ?? item.y | ||
| }).filter((layoutItem) => layoutItem.i !== item.i); | ||
| if (collisions.length > 0) { | ||
| newY = item.y; | ||
| h = item.h; | ||
| newX = item.x; | ||
| w = item.w; | ||
| shouldMoveItem = false; | ||
| } | ||
| } | ||
| item.w = w; | ||
| item.h = h; | ||
| return item; | ||
| }); | ||
| if (!l) return; | ||
| let finalLayout = newLayout; | ||
| if (shouldMoveItem && newX !== void 0 && newY !== void 0) { | ||
| finalLayout = chunk3WO4SAYB_js.moveElement( | ||
| newLayout, | ||
| l, | ||
| newX, | ||
| newY, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| } | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i, | ||
| static: true | ||
| }; | ||
| onResizeProp( | ||
| finalLayout, | ||
| oldResizeItem, | ||
| l, | ||
| placeholder, | ||
| data.e, | ||
| data.node | ||
| ); | ||
| setLayout( | ||
| allowOverlap ? finalLayout : chunk3WO4SAYB_js.compact(finalLayout, compactType, cols) | ||
| ); | ||
| setActiveDrag(placeholder); | ||
| }, | ||
| [layout, preventCollision, allowOverlap, compactType, cols, onResizeProp] | ||
| ); | ||
| const onResizeStop = React2.useCallback( | ||
| (i, _w, _h, data) => { | ||
| const oldResizeItem = oldResizeItemRef.current; | ||
| const l = chunk3WO4SAYB_js.getLayoutItem(layout, i); | ||
| const finalLayout = allowOverlap ? layout : chunk3WO4SAYB_js.compact(layout, compactType, cols); | ||
| onResizeStopProp( | ||
| finalLayout, | ||
| oldResizeItem, | ||
| l ?? null, | ||
| null, | ||
| data.e, | ||
| data.node | ||
| ); | ||
| const oldLayout = oldLayoutRef.current; | ||
| oldResizeItemRef.current = null; | ||
| oldLayoutRef.current = null; | ||
| setActiveDrag(null); | ||
| setResizing(false); | ||
| setLayout(finalLayout); | ||
| if (oldLayout && !fastEquals.deepEqual(oldLayout, finalLayout)) { | ||
| onLayoutChange(finalLayout); | ||
| } | ||
| }, | ||
| [layout, allowOverlap, compactType, cols, onResizeStopProp, onLayoutChange] | ||
| ); | ||
| const removeDroppingPlaceholder = React2.useCallback(() => { | ||
| const newLayout = chunk3WO4SAYB_js.compact( | ||
| layout.filter((l) => l.i !== droppingItem.i), | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| setLayout(newLayout); | ||
| setDroppingDOMNode(null); | ||
| setActiveDrag(null); | ||
| setDroppingPosition(void 0); | ||
| }, [layout, droppingItem.i, compactType, cols, allowOverlap]); | ||
| const handleDragOver = React2.useCallback( | ||
| (e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| if (isFirefox && !e.nativeEvent.target?.classList.contains( | ||
| layoutClassName | ||
| )) { | ||
| return false; | ||
| } | ||
| const onDragOverResult = onDropDragOverProp(e); | ||
| if (onDragOverResult === false) { | ||
| if (droppingDOMNode) { | ||
| removeDroppingPlaceholder(); | ||
| } | ||
| return false; | ||
| } | ||
| const finalDroppingItem = { ...droppingItem, ...onDragOverResult }; | ||
| const gridRect = e.currentTarget.getBoundingClientRect(); | ||
| const layerX = e.clientX - gridRect.left; | ||
| const layerY = e.clientY - gridRect.top; | ||
| const newDroppingPosition = { | ||
| left: layerX / transformScale, | ||
| top: layerY / transformScale, | ||
| e: e.nativeEvent | ||
| }; | ||
| if (!droppingDOMNode) { | ||
| const positionParams = { | ||
| cols, | ||
| margin, | ||
| maxRows, | ||
| rowHeight, | ||
| containerWidth: width, | ||
| containerPadding: effectiveContainerPadding | ||
| }; | ||
| const calculatedPosition = chunkF6NQPYKT_js.calcXY( | ||
| positionParams, | ||
| layerY, | ||
| layerX, | ||
| finalDroppingItem.w, | ||
| finalDroppingItem.h | ||
| ); | ||
| setDroppingDOMNode(/* @__PURE__ */ jsxRuntime.jsx("div", {}, finalDroppingItem.i)); | ||
| setDroppingPosition(newDroppingPosition); | ||
| setLayout([ | ||
| ...layout, | ||
| { | ||
| ...finalDroppingItem, | ||
| x: calculatedPosition.x, | ||
| y: calculatedPosition.y, | ||
| static: false, | ||
| isDraggable: true | ||
| } | ||
| ]); | ||
| } else if (droppingPosition) { | ||
| const shouldUpdate = droppingPosition.left !== layerX || droppingPosition.top !== layerY; | ||
| if (shouldUpdate) { | ||
| setDroppingPosition(newDroppingPosition); | ||
| } | ||
| } | ||
| }, | ||
| [ | ||
| droppingDOMNode, | ||
| droppingPosition, | ||
| droppingItem, | ||
| onDropDragOverProp, | ||
| removeDroppingPlaceholder, | ||
| transformScale, | ||
| cols, | ||
| margin, | ||
| maxRows, | ||
| rowHeight, | ||
| width, | ||
| effectiveContainerPadding, | ||
| layout | ||
| ] | ||
| ); | ||
| const handleDragLeave = React2.useCallback( | ||
| (e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| dragEnterCounterRef.current--; | ||
| if (dragEnterCounterRef.current === 0) { | ||
| removeDroppingPlaceholder(); | ||
| } | ||
| }, | ||
| [removeDroppingPlaceholder] | ||
| ); | ||
| const handleDragEnter = React2.useCallback((e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| dragEnterCounterRef.current++; | ||
| }, []); | ||
| const handleDrop = React2.useCallback( | ||
| (e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| const item = layout.find((l) => l.i === droppingItem.i); | ||
| dragEnterCounterRef.current = 0; | ||
| removeDroppingPlaceholder(); | ||
| onDropProp(layout, item, e.nativeEvent); | ||
| }, | ||
| [layout, droppingItem.i, removeDroppingPlaceholder, onDropProp] | ||
| ); | ||
| const processGridItem = React2.useCallback( | ||
| (child, isDroppingItem) => { | ||
| if (!child || !child.key) return null; | ||
| const l = chunk3WO4SAYB_js.getLayoutItem(layout, String(child.key)); | ||
| if (!l) return null; | ||
| const draggable = typeof l.isDraggable === "boolean" ? l.isDraggable : !l.static && isDraggable; | ||
| const resizable = typeof l.isResizable === "boolean" ? l.isResizable : !l.static && isResizable; | ||
| const resizeHandlesOptions = l.resizeHandles || [...resizeHandles]; | ||
| const bounded = draggable && isBounded && l.isBounded !== false; | ||
| const resizeHandleElement = resizeHandle; | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| GridItem, | ||
| { | ||
| containerWidth: width, | ||
| cols, | ||
| margin, | ||
| containerPadding: effectiveContainerPadding, | ||
| maxRows, | ||
| rowHeight, | ||
| cancel: draggableCancel, | ||
| handle: draggableHandle, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| isDraggable: draggable, | ||
| isResizable: resizable, | ||
| isBounded: bounded, | ||
| useCSSTransforms: useCSSTransforms && mounted, | ||
| usePercentages: !mounted, | ||
| transformScale, | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i: l.i, | ||
| minH: l.minH, | ||
| minW: l.minW, | ||
| maxH: l.maxH, | ||
| maxW: l.maxW, | ||
| static: l.static, | ||
| droppingPosition: isDroppingItem ? droppingPosition : void 0, | ||
| resizeHandles: resizeHandlesOptions, | ||
| resizeHandle: resizeHandleElement, | ||
| children: child | ||
| }, | ||
| l.i | ||
| ); | ||
| }, | ||
| [ | ||
| layout, | ||
| width, | ||
| cols, | ||
| margin, | ||
| effectiveContainerPadding, | ||
| maxRows, | ||
| rowHeight, | ||
| draggableCancel, | ||
| draggableHandle, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| isDraggable, | ||
| isResizable, | ||
| isBounded, | ||
| useCSSTransforms, | ||
| mounted, | ||
| transformScale, | ||
| droppingPosition, | ||
| resizeHandles, | ||
| resizeHandle | ||
| ] | ||
| ); | ||
| const renderPlaceholder = () => { | ||
| if (!activeDrag) return null; | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| GridItem, | ||
| { | ||
| w: activeDrag.w, | ||
| h: activeDrag.h, | ||
| x: activeDrag.x, | ||
| y: activeDrag.y, | ||
| i: activeDrag.i, | ||
| className: `react-grid-placeholder ${resizing ? "placeholder-resizing" : ""}`, | ||
| containerWidth: width, | ||
| cols, | ||
| margin, | ||
| containerPadding: effectiveContainerPadding, | ||
| maxRows, | ||
| rowHeight, | ||
| isDraggable: false, | ||
| isResizable: false, | ||
| isBounded: false, | ||
| useCSSTransforms, | ||
| transformScale, | ||
| children: /* @__PURE__ */ jsxRuntime.jsx("div", {}) | ||
| } | ||
| ); | ||
| }; | ||
| const mergedClassName = clsx__default.default(layoutClassName, className); | ||
| const mergedStyle = { | ||
| height: containerHeight, | ||
| ...style | ||
| }; | ||
| return /* @__PURE__ */ jsxRuntime.jsxs( | ||
| "div", | ||
| { | ||
| ref: innerRef, | ||
| className: mergedClassName, | ||
| style: mergedStyle, | ||
| onDrop: isDroppable ? handleDrop : void 0, | ||
| onDragLeave: isDroppable ? handleDragLeave : void 0, | ||
| onDragEnter: isDroppable ? handleDragEnter : void 0, | ||
| onDragOver: isDroppable ? handleDragOver : void 0, | ||
| children: [ | ||
| React2__default.default.Children.map(children, (child) => { | ||
| if (!React2__default.default.isValidElement(child)) return null; | ||
| return processGridItem(child); | ||
| }), | ||
| isDroppable && droppingDOMNode && processGridItem(droppingDOMNode, true), | ||
| renderPlaceholder() | ||
| ] | ||
| } | ||
| ); | ||
| } | ||
| var DEFAULT_BREAKPOINTS = { | ||
| lg: 1200, | ||
| md: 996, | ||
| sm: 768, | ||
| xs: 480, | ||
| xxs: 0 | ||
| }; | ||
| var DEFAULT_COLS = { | ||
| lg: 12, | ||
| md: 10, | ||
| sm: 6, | ||
| xs: 4, | ||
| xxs: 2 | ||
| }; | ||
| var noop2 = () => { | ||
| }; | ||
| function synchronizeLayoutWithChildren2(initialLayout, children, cols, compactType, allowOverlap) { | ||
| const layout = []; | ||
| React2__default.default.Children.forEach(children, (child) => { | ||
| if (!React2__default.default.isValidElement(child) || child.key === null) return; | ||
| const key = String(child.key); | ||
| const existingItem = initialLayout.find((l) => l.i === key); | ||
| if (existingItem) { | ||
| layout.push({ | ||
| ...existingItem, | ||
| i: key | ||
| }); | ||
| } else { | ||
| const childProps = child.props; | ||
| const dataGrid = childProps["data-grid"]; | ||
| if (dataGrid) { | ||
| layout.push({ | ||
| i: key, | ||
| x: dataGrid.x ?? 0, | ||
| y: dataGrid.y ?? 0, | ||
| w: dataGrid.w ?? 1, | ||
| h: dataGrid.h ?? 1, | ||
| minW: dataGrid.minW, | ||
| maxW: dataGrid.maxW, | ||
| minH: dataGrid.minH, | ||
| maxH: dataGrid.maxH, | ||
| static: dataGrid.static, | ||
| isDraggable: dataGrid.isDraggable, | ||
| isResizable: dataGrid.isResizable, | ||
| resizeHandles: dataGrid.resizeHandles, | ||
| isBounded: dataGrid.isBounded | ||
| }); | ||
| } else { | ||
| layout.push({ | ||
| i: key, | ||
| x: 0, | ||
| y: chunk3WO4SAYB_js.bottom(layout), | ||
| w: 1, | ||
| h: 1 | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| const corrected = chunk3WO4SAYB_js.correctBounds(layout, { cols }); | ||
| return chunk3WO4SAYB_js.compact(corrected, compactType, cols, allowOverlap); | ||
| } | ||
| function ResponsiveGridLayout(props) { | ||
| const { | ||
| children, | ||
| width, | ||
| breakpoint: propBreakpoint, | ||
| breakpoints = DEFAULT_BREAKPOINTS, | ||
| cols: colsConfig = DEFAULT_COLS, | ||
| layouts: propsLayouts = {}, | ||
| rowHeight = 150, | ||
| maxRows = Infinity, | ||
| margin: propMargin = [10, 10], | ||
| containerPadding: propContainerPadding = null, | ||
| compactor: compactorProp, | ||
| onBreakpointChange = noop2, | ||
| onLayoutChange = noop2, | ||
| onWidthChange = noop2, | ||
| ...restProps | ||
| } = props; | ||
| const compactor = compactorProp ?? chunk3WO4SAYB_js.getCompactor("vertical"); | ||
| const compactType = compactor.type; | ||
| const allowOverlap = compactor.allowOverlap; | ||
| const initialBreakpoint = React2.useMemo(() => { | ||
| return propBreakpoint ?? chunk3WO4SAYB_js.getBreakpointFromWidth(breakpoints, width); | ||
| }, []); | ||
| const initialCols = React2.useMemo(() => { | ||
| return chunk3WO4SAYB_js.getColsFromBreakpoint(initialBreakpoint, colsConfig); | ||
| }, [initialBreakpoint, colsConfig]); | ||
| const initialLayout = React2.useMemo(() => { | ||
| return chunk3WO4SAYB_js.findOrGenerateResponsiveLayout( | ||
| propsLayouts, | ||
| breakpoints, | ||
| initialBreakpoint, | ||
| initialBreakpoint, | ||
| initialCols, | ||
| compactType | ||
| ); | ||
| }, []); | ||
| const [breakpoint, setBreakpoint] = React2.useState(initialBreakpoint); | ||
| const [cols, setCols] = React2.useState(initialCols); | ||
| const [layout, setLayout] = React2.useState(initialLayout); | ||
| const [layouts, setLayouts] = React2.useState(propsLayouts); | ||
| const prevWidthRef = React2.useRef(width); | ||
| const prevBreakpointRef = React2.useRef(propBreakpoint); | ||
| const prevBreakpointsRef = React2.useRef(breakpoints); | ||
| const prevColsRef = React2.useRef(colsConfig); | ||
| const prevLayoutsRef = React2.useRef(propsLayouts); | ||
| const prevCompactTypeRef = React2.useRef(compactType); | ||
| React2.useEffect(() => { | ||
| if (!fastEquals.deepEqual(propsLayouts, prevLayoutsRef.current)) { | ||
| const newLayout = chunk3WO4SAYB_js.findOrGenerateResponsiveLayout( | ||
| propsLayouts, | ||
| breakpoints, | ||
| breakpoint, | ||
| breakpoint, | ||
| cols, | ||
| compactType | ||
| ); | ||
| setLayout(newLayout); | ||
| setLayouts(propsLayouts); | ||
| prevLayoutsRef.current = propsLayouts; | ||
| } | ||
| }, [propsLayouts, breakpoints, breakpoint, cols, compactType]); | ||
| React2.useEffect(() => { | ||
| if (compactType !== prevCompactTypeRef.current) { | ||
| const newLayout = chunk3WO4SAYB_js.compact( | ||
| chunk3WO4SAYB_js.cloneLayout(layout), | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const newLayouts = { | ||
| ...layouts, | ||
| [breakpoint]: newLayout | ||
| }; | ||
| setLayout(newLayout); | ||
| setLayouts(newLayouts); | ||
| onLayoutChange(newLayout, newLayouts); | ||
| prevCompactTypeRef.current = compactType; | ||
| } | ||
| }, [ | ||
| compactType, | ||
| layout, | ||
| cols, | ||
| allowOverlap, | ||
| layouts, | ||
| breakpoint, | ||
| onLayoutChange | ||
| ]); | ||
| React2.useEffect(() => { | ||
| const widthChanged = width !== prevWidthRef.current; | ||
| const breakpointPropChanged = propBreakpoint !== prevBreakpointRef.current; | ||
| const breakpointsChanged = !fastEquals.deepEqual( | ||
| breakpoints, | ||
| prevBreakpointsRef.current | ||
| ); | ||
| const colsChanged = !fastEquals.deepEqual(colsConfig, prevColsRef.current); | ||
| if (widthChanged || breakpointPropChanged || breakpointsChanged || colsChanged) { | ||
| const newBreakpoint = propBreakpoint ?? chunk3WO4SAYB_js.getBreakpointFromWidth(breakpoints, width); | ||
| const newCols = chunk3WO4SAYB_js.getColsFromBreakpoint(newBreakpoint, colsConfig); | ||
| const lastBreakpoint = breakpoint; | ||
| if (lastBreakpoint !== newBreakpoint || breakpointsChanged || colsChanged) { | ||
| const newLayouts = { ...layouts }; | ||
| if (!newLayouts[lastBreakpoint]) { | ||
| newLayouts[lastBreakpoint] = chunk3WO4SAYB_js.cloneLayout(layout); | ||
| } | ||
| let newLayout = chunk3WO4SAYB_js.findOrGenerateResponsiveLayout( | ||
| newLayouts, | ||
| breakpoints, | ||
| newBreakpoint, | ||
| lastBreakpoint, | ||
| newCols, | ||
| compactType | ||
| ); | ||
| newLayout = synchronizeLayoutWithChildren2( | ||
| newLayout, | ||
| children, | ||
| newCols, | ||
| compactType, | ||
| allowOverlap | ||
| ); | ||
| newLayouts[newBreakpoint] = newLayout; | ||
| setBreakpoint(newBreakpoint); | ||
| setCols(newCols); | ||
| setLayout(newLayout); | ||
| setLayouts(newLayouts); | ||
| onBreakpointChange(newBreakpoint, newCols); | ||
| onLayoutChange(newLayout, newLayouts); | ||
| } | ||
| const currentMargin2 = chunk3WO4SAYB_js.getIndentationValue( | ||
| propMargin, | ||
| newBreakpoint | ||
| ); | ||
| const currentPadding = propContainerPadding ? chunk3WO4SAYB_js.getIndentationValue( | ||
| propContainerPadding, | ||
| newBreakpoint | ||
| ) : null; | ||
| onWidthChange(width, currentMargin2, newCols, currentPadding); | ||
| prevWidthRef.current = width; | ||
| prevBreakpointRef.current = propBreakpoint; | ||
| prevBreakpointsRef.current = breakpoints; | ||
| prevColsRef.current = colsConfig; | ||
| } | ||
| }, [ | ||
| width, | ||
| propBreakpoint, | ||
| breakpoints, | ||
| colsConfig, | ||
| breakpoint, | ||
| cols, | ||
| layout, | ||
| layouts, | ||
| children, | ||
| compactType, | ||
| allowOverlap, | ||
| propMargin, | ||
| propContainerPadding, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange | ||
| ]); | ||
| const handleLayoutChange = React2.useCallback( | ||
| (newLayout) => { | ||
| const newLayouts = { | ||
| ...layouts, | ||
| [breakpoint]: newLayout | ||
| }; | ||
| setLayout(newLayout); | ||
| setLayouts(newLayouts); | ||
| onLayoutChange(newLayout, newLayouts); | ||
| }, | ||
| [layouts, breakpoint, onLayoutChange] | ||
| ); | ||
| const currentMargin = React2.useMemo(() => { | ||
| return chunk3WO4SAYB_js.getIndentationValue( | ||
| propMargin, | ||
| breakpoint | ||
| ); | ||
| }, [propMargin, breakpoint]); | ||
| const currentContainerPadding = React2.useMemo(() => { | ||
| if (propContainerPadding === null) return null; | ||
| return chunk3WO4SAYB_js.getIndentationValue( | ||
| propContainerPadding, | ||
| breakpoint | ||
| ); | ||
| }, [propContainerPadding, breakpoint]); | ||
| const gridConfig = React2.useMemo( | ||
| () => ({ | ||
| cols, | ||
| rowHeight, | ||
| maxRows, | ||
| margin: currentMargin, | ||
| containerPadding: currentContainerPadding | ||
| }), | ||
| [cols, rowHeight, maxRows, currentMargin, currentContainerPadding] | ||
| ); | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| GridLayout, | ||
| { | ||
| ...restProps, | ||
| width, | ||
| gridConfig, | ||
| compactor, | ||
| onLayoutChange: handleLayoutChange, | ||
| layout, | ||
| children | ||
| } | ||
| ); | ||
| } | ||
| exports.GridItem = GridItem; | ||
| exports.GridLayout = GridLayout; | ||
| exports.ResponsiveGridLayout = ResponsiveGridLayout; | ||
| //# sourceMappingURL=chunk-BFTKGAP3.js.map | ||
| //# sourceMappingURL=chunk-BFTKGAP3.js.map |
Sorry, the diff of this file is too big to display
| 'use strict'; | ||
| // src/core/calculate.ts | ||
| function calcGridColWidth(positionParams) { | ||
| const { margin, containerPadding, containerWidth, cols } = positionParams; | ||
| return (containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols; | ||
| } | ||
| function calcGridItemWHPx(gridUnits, colOrRowSize, marginPx) { | ||
| if (!Number.isFinite(gridUnits)) return gridUnits; | ||
| return Math.round( | ||
| colOrRowSize * gridUnits + Math.max(0, gridUnits - 1) * marginPx | ||
| ); | ||
| } | ||
| function calcGridItemPosition(positionParams, x, y, w, h, dragPosition, resizePosition) { | ||
| const { margin, containerPadding, rowHeight } = positionParams; | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| let width; | ||
| let height; | ||
| let top; | ||
| let left; | ||
| if (resizePosition) { | ||
| width = Math.round(resizePosition.width); | ||
| height = Math.round(resizePosition.height); | ||
| } else { | ||
| width = calcGridItemWHPx(w, colWidth, margin[0]); | ||
| height = calcGridItemWHPx(h, rowHeight, margin[1]); | ||
| } | ||
| if (dragPosition) { | ||
| top = Math.round(dragPosition.top); | ||
| left = Math.round(dragPosition.left); | ||
| } else if (resizePosition) { | ||
| top = Math.round(resizePosition.top); | ||
| left = Math.round(resizePosition.left); | ||
| } else { | ||
| top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]); | ||
| left = Math.round((colWidth + margin[0]) * x + containerPadding[0]); | ||
| } | ||
| return { top, left, width, height }; | ||
| } | ||
| function calcXY(positionParams, top, left, w, h) { | ||
| const { margin, containerPadding, cols, rowHeight, maxRows } = positionParams; | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| let x = Math.round((left - containerPadding[0]) / (colWidth + margin[0])); | ||
| let y = Math.round((top - containerPadding[1]) / (rowHeight + margin[1])); | ||
| x = clamp(x, 0, cols - w); | ||
| y = clamp(y, 0, maxRows - h); | ||
| return { x, y }; | ||
| } | ||
| function calcWH(positionParams, width, height, x, y, handle) { | ||
| const { margin, maxRows, cols, rowHeight } = positionParams; | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| const w = Math.round((width + margin[0]) / (colWidth + margin[0])); | ||
| const h = Math.round((height + margin[1]) / (rowHeight + margin[1])); | ||
| let _w = clamp(w, 0, cols - x); | ||
| let _h = clamp(h, 0, maxRows - y); | ||
| if (handle === "sw" || handle === "w" || handle === "nw") { | ||
| _w = clamp(w, 0, cols); | ||
| } | ||
| if (handle === "nw" || handle === "n" || handle === "ne") { | ||
| _h = clamp(h, 0, maxRows); | ||
| } | ||
| return { w: _w, h: _h }; | ||
| } | ||
| function clamp(num, lowerBound, upperBound) { | ||
| return Math.max(Math.min(num, upperBound), lowerBound); | ||
| } | ||
| function calcGridCellDimensions(config) { | ||
| const { | ||
| width, | ||
| cols, | ||
| rowHeight, | ||
| margin = [10, 10], | ||
| containerPadding | ||
| } = config; | ||
| const padding = containerPadding ?? margin; | ||
| const cellWidth = (width - padding[0] * 2 - margin[0] * (cols - 1)) / cols; | ||
| const cellHeight = rowHeight; | ||
| return { | ||
| cellWidth, | ||
| cellHeight, | ||
| offsetX: padding[0], | ||
| offsetY: padding[1], | ||
| gapX: margin[0], | ||
| gapY: margin[1], | ||
| cols, | ||
| containerWidth: width | ||
| }; | ||
| } | ||
| exports.calcGridCellDimensions = calcGridCellDimensions; | ||
| exports.calcGridColWidth = calcGridColWidth; | ||
| exports.calcGridItemPosition = calcGridItemPosition; | ||
| exports.calcGridItemWHPx = calcGridItemWHPx; | ||
| exports.calcWH = calcWH; | ||
| exports.calcXY = calcXY; | ||
| exports.clamp = clamp; | ||
| //# sourceMappingURL=chunk-F6NQPYKT.js.map | ||
| //# sourceMappingURL=chunk-F6NQPYKT.js.map |
| {"version":3,"sources":["../src/core/calculate.ts"],"names":[],"mappings":"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","file":"chunk-F6NQPYKT.js","sourcesContent":["/**\n * Grid calculation utilities.\n *\n * These functions convert between grid units and pixel positions.\n */\n\nimport type { Position, ResizeHandleAxis } from \"./types.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Parameters needed for position calculations.\n */\nexport interface PositionParams {\n readonly margin: readonly [number, number];\n readonly containerPadding: readonly [number, number];\n readonly containerWidth: number;\n readonly cols: number;\n readonly rowHeight: number;\n readonly maxRows: number;\n}\n\n// ============================================================================\n// Grid Column/Row Calculations\n// ============================================================================\n\n/**\n * Calculate the width of a single grid column in pixels.\n *\n * @param positionParams - Grid parameters\n * @returns Column width in pixels\n */\nexport function calcGridColWidth(positionParams: PositionParams): number {\n const { margin, containerPadding, containerWidth, cols } = positionParams;\n return (\n (containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols\n );\n}\n\n/**\n * Calculate the pixel size for a grid unit dimension (width or height).\n *\n * Can be called as:\n * - calcGridItemWHPx(w, colWidth, margin[0]) for width\n * - calcGridItemWHPx(h, rowHeight, margin[1]) for height\n *\n * @param gridUnits - Size in grid units\n * @param colOrRowSize - Column width or row height in pixels\n * @param marginPx - Margin between items in pixels\n * @returns Size in pixels\n */\nexport function calcGridItemWHPx(\n gridUnits: number,\n colOrRowSize: number,\n marginPx: number\n): number {\n // 0 * Infinity === NaN, which causes problems with resize constraints\n if (!Number.isFinite(gridUnits)) return gridUnits;\n return Math.round(\n colOrRowSize * gridUnits + Math.max(0, gridUnits - 1) * marginPx\n );\n}\n\n// ============================================================================\n// Position Calculations\n// ============================================================================\n\n/**\n * Calculate pixel position for a grid item.\n *\n * Returns left, top, width, height in pixels.\n *\n * @param positionParams - Grid parameters\n * @param x - X coordinate in grid units\n * @param y - Y coordinate in grid units\n * @param w - Width in grid units\n * @param h - Height in grid units\n * @param dragPosition - If present, use exact left/top from drag callbacks\n * @param resizePosition - If present, use exact dimensions from resize callbacks\n * @returns Position in pixels\n */\nexport function calcGridItemPosition(\n positionParams: PositionParams,\n x: number,\n y: number,\n w: number,\n h: number,\n dragPosition?: { top: number; left: number } | null,\n resizePosition?: {\n top: number;\n left: number;\n height: number;\n width: number;\n } | null\n): Position {\n const { margin, containerPadding, rowHeight } = positionParams;\n const colWidth = calcGridColWidth(positionParams);\n\n let width: number;\n let height: number;\n let top: number;\n let left: number;\n\n // If resizing, use the exact width and height from resize callbacks\n if (resizePosition) {\n width = Math.round(resizePosition.width);\n height = Math.round(resizePosition.height);\n } else {\n // Calculate from grid units\n width = calcGridItemWHPx(w, colWidth, margin[0]);\n height = calcGridItemWHPx(h, rowHeight, margin[1]);\n }\n\n // If dragging, use the exact left/top from drag callbacks\n if (dragPosition) {\n top = Math.round(dragPosition.top);\n left = Math.round(dragPosition.left);\n } else if (resizePosition) {\n // If resizing, use the exact left/top from resize position\n top = Math.round(resizePosition.top);\n left = Math.round(resizePosition.left);\n } else {\n // Calculate from grid units\n top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]);\n left = Math.round((colWidth + margin[0]) * x + containerPadding[0]);\n }\n\n return { top, left, width, height };\n}\n\n/**\n * Translate pixel coordinates to grid units.\n *\n * @param positionParams - Grid parameters\n * @param top - Top position in pixels (relative to parent)\n * @param left - Left position in pixels (relative to parent)\n * @param w - Width in grid units (for clamping)\n * @param h - Height in grid units (for clamping)\n * @returns x and y in grid units\n */\nexport function calcXY(\n positionParams: PositionParams,\n top: number,\n left: number,\n w: number,\n h: number\n): { x: number; y: number } {\n const { margin, containerPadding, cols, rowHeight, maxRows } = positionParams;\n const colWidth = calcGridColWidth(positionParams);\n\n // left = containerPaddingX + x * (colWidth + marginX)\n // x = (left - containerPaddingX) / (colWidth + marginX)\n let x = Math.round((left - containerPadding[0]) / (colWidth + margin[0]));\n let y = Math.round((top - containerPadding[1]) / (rowHeight + margin[1]));\n\n // Clamp to grid bounds\n x = clamp(x, 0, cols - w);\n y = clamp(y, 0, maxRows - h);\n\n return { x, y };\n}\n\n/**\n * Calculate grid units from pixel dimensions.\n *\n * @param positionParams - Grid parameters\n * @param width - Width in pixels\n * @param height - Height in pixels\n * @param x - X coordinate in grid units (for clamping)\n * @param y - Y coordinate in grid units (for clamping)\n * @param handle - Resize handle being used\n * @returns w, h in grid units\n */\nexport function calcWH(\n positionParams: PositionParams,\n width: number,\n height: number,\n x: number,\n y: number,\n handle: ResizeHandleAxis\n): { w: number; h: number } {\n const { margin, maxRows, cols, rowHeight } = positionParams;\n const colWidth = calcGridColWidth(positionParams);\n\n // width = colWidth * w - (margin * (w - 1))\n // w = (width + margin) / (colWidth + margin)\n const w = Math.round((width + margin[0]) / (colWidth + margin[0]));\n const h = Math.round((height + margin[1]) / (rowHeight + margin[1]));\n\n // Clamp based on resize handle direction\n let _w = clamp(w, 0, cols - x);\n let _h = clamp(h, 0, maxRows - y);\n\n // West handles can resize to full width\n if (handle === \"sw\" || handle === \"w\" || handle === \"nw\") {\n _w = clamp(w, 0, cols);\n }\n\n // North handles can resize to full height\n if (handle === \"nw\" || handle === \"n\" || handle === \"ne\") {\n _h = clamp(h, 0, maxRows);\n }\n\n return { w: _w, h: _h };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Clamp a number between bounds.\n *\n * @param num - Number to clamp\n * @param lowerBound - Minimum value\n * @param upperBound - Maximum value\n * @returns Clamped value\n */\nexport function clamp(\n num: number,\n lowerBound: number,\n upperBound: number\n): number {\n return Math.max(Math.min(num, upperBound), lowerBound);\n}\n\n// ============================================================================\n// Grid Background Calculations\n// ============================================================================\n\n/**\n * Grid cell dimension information for rendering backgrounds or overlays.\n */\nexport interface GridCellDimensions {\n /** Width of a single cell in pixels */\n readonly cellWidth: number;\n /** Height of a single cell in pixels */\n readonly cellHeight: number;\n /** Horizontal offset from container edge to first cell */\n readonly offsetX: number;\n /** Vertical offset from container edge to first cell */\n readonly offsetY: number;\n /** Horizontal gap between cells */\n readonly gapX: number;\n /** Vertical gap between cells */\n readonly gapY: number;\n /** Number of columns */\n readonly cols: number;\n /** Total container width */\n readonly containerWidth: number;\n}\n\n/**\n * Configuration for grid cell dimension calculation.\n */\nexport interface GridCellConfig {\n /** Container width in pixels */\n width: number;\n /** Number of columns */\n cols: number;\n /** Row height in pixels */\n rowHeight: number;\n /** Margin between items [x, y] */\n margin?: readonly [number, number];\n /** Container padding [x, y], defaults to margin if not specified */\n containerPadding?: readonly [number, number] | null;\n}\n\n/**\n * Calculate grid cell dimensions for rendering backgrounds or overlays.\n *\n * This function provides all the measurements needed to render a visual\n * grid background that aligns with the actual grid cells.\n *\n * @param config - Grid configuration\n * @returns Cell dimensions and offsets\n *\n * @example\n * ```tsx\n * import { calcGridCellDimensions } from 'react-grid-layout/core';\n *\n * const dims = calcGridCellDimensions({\n * width: 1200,\n * cols: 12,\n * rowHeight: 30,\n * margin: [10, 10],\n * containerPadding: [10, 10]\n * });\n *\n * // dims.cellWidth = 88.33...\n * // dims.cellHeight = 30\n * // dims.offsetX = 10 (containerPadding[0])\n * // dims.offsetY = 10 (containerPadding[1])\n * // dims.gapX = 10 (margin[0])\n * // dims.gapY = 10 (margin[1])\n * ```\n */\nexport function calcGridCellDimensions(\n config: GridCellConfig\n): GridCellDimensions {\n const {\n width,\n cols,\n rowHeight,\n margin = [10, 10],\n containerPadding\n } = config;\n\n // Container padding defaults to margin if not specified\n const padding = containerPadding ?? margin;\n\n // Calculate cell width: total width minus padding and gaps, divided by columns\n // Formula: width = 2*padding + cols*cellWidth + (cols-1)*gap\n // Solving for cellWidth: cellWidth = (width - 2*padding - (cols-1)*gap) / cols\n const cellWidth = (width - padding[0] * 2 - margin[0] * (cols - 1)) / cols;\n const cellHeight = rowHeight;\n\n return {\n cellWidth,\n cellHeight,\n offsetX: padding[0],\n offsetY: padding[1],\n gapX: margin[0],\n gapY: margin[1],\n cols,\n containerWidth: width\n };\n}\n"]} |
| 'use strict'; | ||
| var chunk3WO4SAYB_js = require('./chunk-3WO4SAYB.js'); | ||
| var react = require('react'); | ||
| var fastEquals = require('fast-equals'); | ||
| function useContainerWidth(options = {}) { | ||
| const { measureBeforeMount = false, initialWidth = 1280 } = options; | ||
| const [width, setWidth] = react.useState(initialWidth); | ||
| const [mounted, setMounted] = react.useState(!measureBeforeMount); | ||
| const containerRef = react.useRef(null); | ||
| const observerRef = react.useRef(null); | ||
| const measureWidth = react.useCallback(() => { | ||
| const node = containerRef.current; | ||
| if (node) { | ||
| const newWidth = node.offsetWidth; | ||
| setWidth(newWidth); | ||
| if (!mounted) { | ||
| setMounted(true); | ||
| } | ||
| } | ||
| }, [mounted]); | ||
| react.useEffect(() => { | ||
| const node = containerRef.current; | ||
| if (!node) return; | ||
| measureWidth(); | ||
| if (typeof ResizeObserver !== "undefined") { | ||
| observerRef.current = new ResizeObserver((entries) => { | ||
| const entry = entries[0]; | ||
| if (entry) { | ||
| const newWidth = entry.contentRect.width; | ||
| setWidth(newWidth); | ||
| } | ||
| }); | ||
| observerRef.current.observe(node); | ||
| } | ||
| return () => { | ||
| if (observerRef.current) { | ||
| observerRef.current.disconnect(); | ||
| observerRef.current = null; | ||
| } | ||
| }; | ||
| }, [measureWidth]); | ||
| return { | ||
| width, | ||
| mounted, | ||
| containerRef, | ||
| measureWidth | ||
| }; | ||
| } | ||
| function useGridLayout(options) { | ||
| const { | ||
| layout: propsLayout, | ||
| cols, | ||
| compactType = "vertical", | ||
| allowOverlap = false, | ||
| preventCollision = false, | ||
| onLayoutChange | ||
| } = options; | ||
| const compactor = react.useMemo( | ||
| () => chunk3WO4SAYB_js.getCompactor(compactType, allowOverlap), | ||
| [compactType, allowOverlap] | ||
| ); | ||
| const isDraggingRef = react.useRef(false); | ||
| const [layout, setLayoutState] = react.useState(() => { | ||
| const corrected = chunk3WO4SAYB_js.correctBounds(chunk3WO4SAYB_js.cloneLayout(propsLayout), { cols }); | ||
| return chunk3WO4SAYB_js.compact(corrected, compactType, cols, allowOverlap); | ||
| }); | ||
| const [dragState, setDragState] = react.useState({ | ||
| activeDrag: null, | ||
| oldDragItem: null, | ||
| oldLayout: null | ||
| }); | ||
| const [resizeState, setResizeState] = react.useState({ | ||
| resizing: false, | ||
| oldResizeItem: null, | ||
| oldLayout: null | ||
| }); | ||
| const [dropState, setDropState] = react.useState({ | ||
| droppingDOMNode: null, | ||
| droppingPosition: null | ||
| }); | ||
| const prevLayoutRef = react.useRef(layout); | ||
| const setLayout = react.useCallback( | ||
| (newLayout) => { | ||
| const corrected = chunk3WO4SAYB_js.correctBounds(chunk3WO4SAYB_js.cloneLayout(newLayout), { cols }); | ||
| const compacted = chunk3WO4SAYB_js.compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [cols, compactType, allowOverlap] | ||
| ); | ||
| react.useEffect(() => { | ||
| if (isDraggingRef.current) return; | ||
| if (!fastEquals.deepEqual(propsLayout, prevLayoutRef.current)) { | ||
| setLayout(propsLayout); | ||
| } | ||
| }, [propsLayout, setLayout]); | ||
| react.useEffect(() => { | ||
| if (!fastEquals.deepEqual(layout, prevLayoutRef.current)) { | ||
| prevLayoutRef.current = layout; | ||
| onLayoutChange?.(layout); | ||
| } | ||
| }, [layout, onLayoutChange]); | ||
| const onDragStart = react.useCallback( | ||
| (itemId, x, y) => { | ||
| const item = chunk3WO4SAYB_js.getLayoutItem(layout, itemId); | ||
| if (!item) return null; | ||
| isDraggingRef.current = true; | ||
| const placeholder = { | ||
| ...chunk3WO4SAYB_js.cloneLayoutItem(item), | ||
| x, | ||
| y, | ||
| static: false, | ||
| moved: false | ||
| }; | ||
| setDragState({ | ||
| activeDrag: placeholder, | ||
| oldDragItem: chunk3WO4SAYB_js.cloneLayoutItem(item), | ||
| oldLayout: chunk3WO4SAYB_js.cloneLayout(layout) | ||
| }); | ||
| return placeholder; | ||
| }, | ||
| [layout] | ||
| ); | ||
| const onDrag = react.useCallback( | ||
| (itemId, x, y) => { | ||
| const item = chunk3WO4SAYB_js.getLayoutItem(layout, itemId); | ||
| if (!item) return; | ||
| setDragState((prev) => ({ | ||
| ...prev, | ||
| activeDrag: prev.activeDrag ? { ...prev.activeDrag, x, y } : null | ||
| })); | ||
| const newLayout = chunk3WO4SAYB_js.moveElement( | ||
| layout, | ||
| item, | ||
| x, | ||
| y, | ||
| true, | ||
| // isUserAction | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const compacted = allowOverlap ? newLayout : chunk3WO4SAYB_js.compact(newLayout, compactType, cols); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [layout, cols, compactType, preventCollision, allowOverlap] | ||
| ); | ||
| const onDragStop = react.useCallback( | ||
| (itemId, x, y) => { | ||
| const item = chunk3WO4SAYB_js.getLayoutItem(layout, itemId); | ||
| if (!item) return; | ||
| const newLayout = chunk3WO4SAYB_js.moveElement( | ||
| layout, | ||
| item, | ||
| x, | ||
| y, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const compacted = chunk3WO4SAYB_js.compact(newLayout, compactType, cols, allowOverlap); | ||
| isDraggingRef.current = false; | ||
| setDragState({ | ||
| activeDrag: null, | ||
| oldDragItem: null, | ||
| oldLayout: null | ||
| }); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [layout, cols, compactType, preventCollision, allowOverlap] | ||
| ); | ||
| const onResizeStart = react.useCallback( | ||
| (itemId) => { | ||
| const item = chunk3WO4SAYB_js.getLayoutItem(layout, itemId); | ||
| if (!item) return null; | ||
| setResizeState({ | ||
| resizing: true, | ||
| oldResizeItem: chunk3WO4SAYB_js.cloneLayoutItem(item), | ||
| oldLayout: chunk3WO4SAYB_js.cloneLayout(layout) | ||
| }); | ||
| return item; | ||
| }, | ||
| [layout] | ||
| ); | ||
| const onResize = react.useCallback( | ||
| (itemId, w, h, x, y) => { | ||
| const newLayout = layout.map((item) => { | ||
| if (item.i === itemId) { | ||
| const updated = { | ||
| ...item, | ||
| w, | ||
| h | ||
| }; | ||
| if (x !== void 0) updated.x = x; | ||
| if (y !== void 0) updated.y = y; | ||
| return updated; | ||
| } | ||
| return item; | ||
| }); | ||
| const corrected = chunk3WO4SAYB_js.correctBounds(newLayout, { cols }); | ||
| const compacted = chunk3WO4SAYB_js.compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [layout, cols, compactType, allowOverlap] | ||
| ); | ||
| const onResizeStop = react.useCallback( | ||
| (itemId, w, h) => { | ||
| onResize(itemId, w, h); | ||
| setResizeState({ | ||
| resizing: false, | ||
| oldResizeItem: null, | ||
| oldLayout: null | ||
| }); | ||
| }, | ||
| [onResize] | ||
| ); | ||
| const onDropDragOver = react.useCallback( | ||
| (droppingItem, position) => { | ||
| const existingItem = chunk3WO4SAYB_js.getLayoutItem(layout, droppingItem.i); | ||
| if (!existingItem) { | ||
| const newLayout = [...layout, droppingItem]; | ||
| const corrected = chunk3WO4SAYB_js.correctBounds(newLayout, { cols }); | ||
| const compacted = chunk3WO4SAYB_js.compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| } | ||
| setDropState({ | ||
| droppingDOMNode: null, | ||
| // Will be set by component | ||
| droppingPosition: position | ||
| }); | ||
| }, | ||
| [layout, cols, compactType, allowOverlap] | ||
| ); | ||
| const onDropDragLeave = react.useCallback(() => { | ||
| const newLayout = layout.filter((item) => item.i !== "__dropping-elem__"); | ||
| setLayoutState(newLayout); | ||
| setDropState({ | ||
| droppingDOMNode: null, | ||
| droppingPosition: null | ||
| }); | ||
| }, [layout]); | ||
| const onDrop = react.useCallback( | ||
| (droppingItem) => { | ||
| const newLayout = layout.map((item) => { | ||
| if (item.i === "__dropping-elem__") { | ||
| return { | ||
| ...item, | ||
| i: droppingItem.i, | ||
| static: false | ||
| }; | ||
| } | ||
| return item; | ||
| }); | ||
| const corrected = chunk3WO4SAYB_js.correctBounds(newLayout, { cols }); | ||
| const compacted = chunk3WO4SAYB_js.compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| setDropState({ | ||
| droppingDOMNode: null, | ||
| droppingPosition: null | ||
| }); | ||
| }, | ||
| [layout, cols, compactType, allowOverlap] | ||
| ); | ||
| const containerHeight = react.useMemo(() => chunk3WO4SAYB_js.bottom(layout), [layout]); | ||
| const isInteracting = dragState.activeDrag !== null || resizeState.resizing || dropState.droppingPosition !== null; | ||
| return { | ||
| layout, | ||
| setLayout, | ||
| dragState, | ||
| resizeState, | ||
| dropState, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDropDragOver, | ||
| onDropDragLeave, | ||
| onDrop, | ||
| containerHeight, | ||
| isInteracting, | ||
| compactor | ||
| }; | ||
| } | ||
| var DEFAULT_BREAKPOINTS = { | ||
| lg: 1200, | ||
| md: 996, | ||
| sm: 768, | ||
| xs: 480, | ||
| xxs: 0 | ||
| }; | ||
| var DEFAULT_COLS = { | ||
| lg: 12, | ||
| md: 10, | ||
| sm: 6, | ||
| xs: 4, | ||
| xxs: 2 | ||
| }; | ||
| function useResponsiveLayout(options) { | ||
| const { | ||
| width, | ||
| breakpoints = DEFAULT_BREAKPOINTS, | ||
| cols: colsConfig = DEFAULT_COLS, | ||
| layouts: propsLayouts = {}, | ||
| compactType = "vertical", | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange | ||
| } = options; | ||
| const sortedBreakpoints = react.useMemo( | ||
| () => chunk3WO4SAYB_js.sortBreakpoints(breakpoints), | ||
| [breakpoints] | ||
| ); | ||
| const initialBreakpoint = react.useMemo( | ||
| () => chunk3WO4SAYB_js.getBreakpointFromWidth(breakpoints, width), | ||
| // Only calculate on mount, not on width changes | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| [] | ||
| ); | ||
| const initialCols = react.useMemo( | ||
| () => chunk3WO4SAYB_js.getColsFromBreakpoint(initialBreakpoint, colsConfig), | ||
| [initialBreakpoint, colsConfig] | ||
| ); | ||
| const [breakpoint, setBreakpoint] = react.useState(initialBreakpoint); | ||
| const [cols, setCols] = react.useState(initialCols); | ||
| const [layouts, setLayoutsState] = react.useState(() => { | ||
| const cloned = {}; | ||
| for (const bp of sortedBreakpoints) { | ||
| const layout2 = propsLayouts[bp]; | ||
| if (layout2) { | ||
| cloned[bp] = chunk3WO4SAYB_js.cloneLayout(layout2); | ||
| } | ||
| } | ||
| return cloned; | ||
| }); | ||
| const prevWidthRef = react.useRef(width); | ||
| const prevBreakpointRef = react.useRef(breakpoint); | ||
| const prevLayoutsRef = react.useRef(layouts); | ||
| const layout = react.useMemo(() => { | ||
| return chunk3WO4SAYB_js.findOrGenerateResponsiveLayout( | ||
| layouts, | ||
| breakpoints, | ||
| breakpoint, | ||
| prevBreakpointRef.current, | ||
| cols, | ||
| compactType | ||
| ); | ||
| }, [layouts, breakpoints, breakpoint, cols, compactType]); | ||
| const setLayoutForBreakpoint = react.useCallback((bp, newLayout) => { | ||
| setLayoutsState((prev) => ({ | ||
| ...prev, | ||
| [bp]: chunk3WO4SAYB_js.cloneLayout(newLayout) | ||
| })); | ||
| }, []); | ||
| const setLayouts = react.useCallback((newLayouts) => { | ||
| const cloned = {}; | ||
| for (const bp of Object.keys(newLayouts)) { | ||
| const layoutForBp = newLayouts[bp]; | ||
| if (layoutForBp) { | ||
| cloned[bp] = chunk3WO4SAYB_js.cloneLayout(layoutForBp); | ||
| } | ||
| } | ||
| setLayoutsState(cloned); | ||
| }, []); | ||
| react.useEffect(() => { | ||
| if (prevWidthRef.current === width) return; | ||
| prevWidthRef.current = width; | ||
| const newBreakpoint = chunk3WO4SAYB_js.getBreakpointFromWidth(breakpoints, width); | ||
| const newCols = chunk3WO4SAYB_js.getColsFromBreakpoint(newBreakpoint, colsConfig); | ||
| onWidthChange?.(width, [10, 10], newCols, null); | ||
| if (newBreakpoint !== breakpoint) { | ||
| const newLayout = chunk3WO4SAYB_js.findOrGenerateResponsiveLayout( | ||
| layouts, | ||
| breakpoints, | ||
| newBreakpoint, | ||
| breakpoint, | ||
| newCols, | ||
| compactType | ||
| ); | ||
| const updatedLayouts = { | ||
| ...layouts, | ||
| [newBreakpoint]: newLayout | ||
| }; | ||
| setLayoutsState(updatedLayouts); | ||
| setBreakpoint(newBreakpoint); | ||
| setCols(newCols); | ||
| onBreakpointChange?.(newBreakpoint, newCols); | ||
| prevBreakpointRef.current = newBreakpoint; | ||
| } | ||
| }, [ | ||
| width, | ||
| breakpoints, | ||
| colsConfig, | ||
| breakpoint, | ||
| layouts, | ||
| compactType, | ||
| onBreakpointChange, | ||
| onWidthChange | ||
| ]); | ||
| react.useEffect(() => { | ||
| if (!fastEquals.deepEqual(propsLayouts, prevLayoutsRef.current)) { | ||
| setLayouts(propsLayouts); | ||
| prevLayoutsRef.current = propsLayouts; | ||
| } | ||
| }, [propsLayouts, setLayouts]); | ||
| react.useEffect(() => { | ||
| if (!fastEquals.deepEqual(layouts, prevLayoutsRef.current)) { | ||
| prevLayoutsRef.current = layouts; | ||
| onLayoutChange?.(layout, layouts); | ||
| } | ||
| }, [layout, layouts, onLayoutChange]); | ||
| return { | ||
| layout, | ||
| layouts, | ||
| breakpoint, | ||
| cols, | ||
| setLayoutForBreakpoint, | ||
| setLayouts, | ||
| sortedBreakpoints | ||
| }; | ||
| } | ||
| exports.DEFAULT_BREAKPOINTS = DEFAULT_BREAKPOINTS; | ||
| exports.DEFAULT_COLS = DEFAULT_COLS; | ||
| exports.useContainerWidth = useContainerWidth; | ||
| exports.useGridLayout = useGridLayout; | ||
| exports.useResponsiveLayout = useResponsiveLayout; | ||
| //# sourceMappingURL=chunk-H5KMDLY3.js.map | ||
| //# sourceMappingURL=chunk-H5KMDLY3.js.map |
| {"version":3,"sources":["../src/react/hooks/useContainerWidth.ts","../src/react/hooks/useGridLayout.ts","../src/react/hooks/useResponsiveLayout.ts"],"names":["useState","useRef","useCallback","useEffect","useMemo","getCompactor","correctBounds","cloneLayout","compact","deepEqual","getLayoutItem","cloneLayoutItem","moveElement","bottom","sortBreakpoints","getBreakpointFromWidth","getColsFromBreakpoint","layout","findOrGenerateResponsiveLayout"],"mappings":"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","file":"chunk-H5KMDLY3.js","sourcesContent":["/**\n * useContainerWidth hook\n *\n * Observes container width using ResizeObserver and provides\n * reactive width updates for responsive layouts.\n */\n\nimport {\n useState,\n useEffect,\n useRef,\n useCallback,\n type RefObject\n} from \"react\";\n\nexport interface UseContainerWidthOptions {\n /**\n * If true, delays initial render until width is measured.\n * Useful for SSR or when you need accurate initial measurements.\n */\n measureBeforeMount?: boolean;\n\n /**\n * Initial width to use before measurement.\n * Defaults to 1280.\n */\n initialWidth?: number;\n}\n\nexport interface UseContainerWidthResult {\n /**\n * Current container width in pixels.\n */\n width: number;\n\n /**\n * Whether the container has been measured at least once.\n */\n mounted: boolean;\n\n /**\n * Ref to attach to the container element.\n */\n containerRef: RefObject<HTMLDivElement | null>;\n\n /**\n * Manually trigger a width measurement.\n * Useful when the container size might change without a resize event.\n */\n measureWidth: () => void;\n}\n\n/**\n * Hook to observe and track container width.\n *\n * Replaces the WidthProvider HOC with a more composable approach.\n *\n * @example\n * ```tsx\n * function MyGrid() {\n * const { width, containerRef, mounted } = useContainerWidth();\n *\n * return (\n * <div ref={containerRef}>\n * {mounted && <GridLayout width={width} {...props} />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useContainerWidth(\n options: UseContainerWidthOptions = {}\n): UseContainerWidthResult {\n const { measureBeforeMount = false, initialWidth = 1280 } = options;\n\n const [width, setWidth] = useState(initialWidth);\n const [mounted, setMounted] = useState(!measureBeforeMount);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const observerRef = useRef<ResizeObserver | null>(null);\n\n const measureWidth = useCallback(() => {\n const node = containerRef.current;\n if (node) {\n const newWidth = node.offsetWidth;\n setWidth(newWidth);\n if (!mounted) {\n setMounted(true);\n }\n }\n }, [mounted]);\n\n useEffect(() => {\n const node = containerRef.current;\n if (!node) return;\n\n // Initial measurement\n measureWidth();\n\n // Set up ResizeObserver\n if (typeof ResizeObserver !== \"undefined\") {\n observerRef.current = new ResizeObserver(entries => {\n const entry = entries[0];\n if (entry) {\n // Use contentRect.width for consistent measurements\n const newWidth = entry.contentRect.width;\n setWidth(newWidth);\n }\n });\n\n observerRef.current.observe(node);\n }\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n };\n }, [measureWidth]);\n\n return {\n width,\n mounted,\n containerRef,\n measureWidth\n };\n}\n\nexport default useContainerWidth;\n","/**\n * useGridLayout hook\n *\n * Core hook for managing grid layout state, including drag, resize, and drop operations.\n * This extracts the state management logic from ReactGridLayout into a reusable hook.\n */\n\nimport { useState, useCallback, useMemo, useRef, useEffect } from \"react\";\nimport { deepEqual } from \"fast-equals\";\nimport type {\n Layout,\n LayoutItem,\n CompactType,\n DroppingPosition,\n Compactor,\n Mutable\n} from \"../../core/types.js\";\nimport {\n cloneLayout,\n cloneLayoutItem,\n moveElement,\n correctBounds,\n bottom,\n getLayoutItem\n} from \"../../core/layout.js\";\nimport { compact } from \"../../core/compact-compat.js\";\nimport { getCompactor } from \"../../core/compactors.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DragState {\n /** Currently dragging item placeholder */\n activeDrag: LayoutItem | null;\n /** Original item before drag started */\n oldDragItem: LayoutItem | null;\n /** Layout before drag started */\n oldLayout: Layout | null;\n}\n\nexport interface ResizeState {\n /** Whether a resize is in progress */\n resizing: boolean;\n /** Original item before resize started */\n oldResizeItem: LayoutItem | null;\n /** Layout before resize started */\n oldLayout: Layout | null;\n}\n\nexport interface DropState {\n /** DOM node for the dropping placeholder */\n droppingDOMNode: React.ReactElement | null;\n /** Current drop position */\n droppingPosition: DroppingPosition | null;\n}\n\nexport interface UseGridLayoutOptions {\n /** Initial layout */\n layout: Layout;\n /** Number of columns */\n cols: number;\n /** Compaction type: 'vertical', 'horizontal', or null */\n compactType?: CompactType;\n /** Allow items to overlap */\n allowOverlap?: boolean;\n /** Prevent collisions when moving items */\n preventCollision?: boolean;\n /** Called when layout changes */\n onLayoutChange?: (layout: Layout) => void;\n}\n\nexport interface UseGridLayoutResult {\n /** Current layout */\n layout: Layout;\n /** Set layout directly */\n setLayout: (layout: Layout) => void;\n /** Drag state */\n dragState: DragState;\n /** Resize state */\n resizeState: ResizeState;\n /** Drop state */\n dropState: DropState;\n /** Start dragging an item */\n onDragStart: (itemId: string, x: number, y: number) => LayoutItem | null;\n /** Update drag position */\n onDrag: (itemId: string, x: number, y: number) => void;\n /** Stop dragging */\n onDragStop: (itemId: string, x: number, y: number) => void;\n /** Start resizing an item */\n onResizeStart: (itemId: string) => LayoutItem | null;\n /** Update resize dimensions */\n onResize: (\n itemId: string,\n w: number,\n h: number,\n x?: number,\n y?: number\n ) => void;\n /** Stop resizing */\n onResizeStop: (itemId: string, w: number, h: number) => void;\n /** Start dropping (external drag-in) */\n onDropDragOver: (\n droppingItem: LayoutItem,\n position: DroppingPosition\n ) => void;\n /** Update drop position */\n onDropDragLeave: () => void;\n /** Complete drop */\n onDrop: (droppingItem: LayoutItem) => void;\n /** Container height in rows */\n containerHeight: number;\n /** Whether any drag/resize is active */\n isInteracting: boolean;\n /** Get the compactor being used */\n compactor: Compactor;\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for managing grid layout state.\n *\n * Handles all layout state including drag, resize, and drop operations.\n * Uses immutable updates and provides callbacks for all interactions.\n *\n * @example\n * ```tsx\n * function MyGrid() {\n * const {\n * layout,\n * onDragStart,\n * onDrag,\n * onDragStop,\n * containerHeight\n * } = useGridLayout({\n * layout: initialLayout,\n * cols: 12,\n * compactType: 'vertical'\n * });\n *\n * return (\n * <div style={{ height: containerHeight }}>\n * {layout.map(item => (\n * <GridItem\n * key={item.i}\n * {...item}\n * onDragStart={() => onDragStart(item.i, item.x, item.y)}\n * />\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useGridLayout(\n options: UseGridLayoutOptions\n): UseGridLayoutResult {\n const {\n layout: propsLayout,\n cols,\n compactType = \"vertical\",\n allowOverlap = false,\n preventCollision = false,\n onLayoutChange\n } = options;\n\n // Get the appropriate compactor\n const compactor = useMemo(\n () => getCompactor(compactType, allowOverlap),\n [compactType, allowOverlap]\n );\n\n // Track if we're currently dragging to block prop updates\n const isDraggingRef = useRef(false);\n\n // Initialize layout with compaction\n const [layout, setLayoutState] = useState<Layout>(() => {\n const corrected = correctBounds(cloneLayout(propsLayout), { cols });\n return compact(corrected, compactType, cols, allowOverlap);\n });\n\n // Drag state\n const [dragState, setDragState] = useState<DragState>({\n activeDrag: null,\n oldDragItem: null,\n oldLayout: null\n });\n\n // Resize state\n const [resizeState, setResizeState] = useState<ResizeState>({\n resizing: false,\n oldResizeItem: null,\n oldLayout: null\n });\n\n // Drop state\n const [dropState, setDropState] = useState<DropState>({\n droppingDOMNode: null,\n droppingPosition: null\n });\n\n // Track previous layout for change detection\n const prevLayoutRef = useRef<Layout>(layout);\n\n // Set layout with optional compaction\n const setLayout = useCallback(\n (newLayout: Layout) => {\n const corrected = correctBounds(cloneLayout(newLayout), { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n setLayoutState(compacted);\n },\n [cols, compactType, allowOverlap]\n );\n\n // Sync layout from props when not dragging\n useEffect(() => {\n if (isDraggingRef.current) return;\n\n if (!deepEqual(propsLayout, prevLayoutRef.current)) {\n setLayout(propsLayout);\n }\n }, [propsLayout, setLayout]);\n\n // Notify layout changes\n useEffect(() => {\n if (!deepEqual(layout, prevLayoutRef.current)) {\n prevLayoutRef.current = layout;\n onLayoutChange?.(layout);\n }\n }, [layout, onLayoutChange]);\n\n // ============================================================================\n // Drag Handlers\n // ============================================================================\n\n const onDragStart = useCallback(\n (itemId: string, x: number, y: number): LayoutItem | null => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return null;\n\n isDraggingRef.current = true;\n\n const placeholder: LayoutItem = {\n ...cloneLayoutItem(item),\n x,\n y,\n static: false,\n moved: false\n };\n\n setDragState({\n activeDrag: placeholder,\n oldDragItem: cloneLayoutItem(item),\n oldLayout: cloneLayout(layout)\n });\n\n return placeholder;\n },\n [layout]\n );\n\n const onDrag = useCallback(\n (itemId: string, x: number, y: number) => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return;\n\n // Update placeholder position\n setDragState(prev => ({\n ...prev,\n activeDrag: prev.activeDrag ? { ...prev.activeDrag, x, y } : null\n }));\n\n // Move element and update layout\n const newLayout = moveElement(\n layout,\n item,\n x,\n y,\n true, // isUserAction\n preventCollision,\n compactType,\n cols,\n allowOverlap\n );\n\n // Compact layout\n const compacted = allowOverlap\n ? newLayout\n : compact(newLayout, compactType, cols);\n\n setLayoutState(compacted);\n },\n [layout, cols, compactType, preventCollision, allowOverlap]\n );\n\n const onDragStop = useCallback(\n (itemId: string, x: number, y: number) => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return;\n\n // Final move\n const newLayout = moveElement(\n layout,\n item,\n x,\n y,\n true,\n preventCollision,\n compactType,\n cols,\n allowOverlap\n );\n\n // Compact and finalize\n const compacted = compact(newLayout, compactType, cols, allowOverlap);\n\n isDraggingRef.current = false;\n\n setDragState({\n activeDrag: null,\n oldDragItem: null,\n oldLayout: null\n });\n\n setLayoutState(compacted);\n },\n [layout, cols, compactType, preventCollision, allowOverlap]\n );\n\n // ============================================================================\n // Resize Handlers\n // ============================================================================\n\n const onResizeStart = useCallback(\n (itemId: string): LayoutItem | null => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return null;\n\n setResizeState({\n resizing: true,\n oldResizeItem: cloneLayoutItem(item),\n oldLayout: cloneLayout(layout)\n });\n\n return item;\n },\n [layout]\n );\n\n const onResize = useCallback(\n (itemId: string, w: number, h: number, x?: number, y?: number) => {\n const newLayout = layout.map(item => {\n if (item.i === itemId) {\n const updated: LayoutItem = {\n ...item,\n w,\n h\n };\n if (x !== undefined) (updated as Mutable<LayoutItem>).x = x;\n if (y !== undefined) (updated as Mutable<LayoutItem>).y = y;\n return updated;\n }\n return item;\n });\n\n // Correct bounds and compact\n const corrected = correctBounds(newLayout, { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n\n setLayoutState(compacted);\n },\n [layout, cols, compactType, allowOverlap]\n );\n\n const onResizeStop = useCallback(\n (itemId: string, w: number, h: number) => {\n // Apply final resize\n onResize(itemId, w, h);\n\n setResizeState({\n resizing: false,\n oldResizeItem: null,\n oldLayout: null\n });\n },\n [onResize]\n );\n\n // ============================================================================\n // Drop Handlers\n // ============================================================================\n\n const onDropDragOver = useCallback(\n (droppingItem: LayoutItem, position: DroppingPosition) => {\n // Check if item already exists in layout\n const existingItem = getLayoutItem(layout, droppingItem.i);\n\n if (!existingItem) {\n // Add dropping item to layout\n const newLayout = [...layout, droppingItem];\n const corrected = correctBounds(newLayout, { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n setLayoutState(compacted);\n }\n\n setDropState({\n droppingDOMNode: null, // Will be set by component\n droppingPosition: position\n });\n },\n [layout, cols, compactType, allowOverlap]\n );\n\n const onDropDragLeave = useCallback(() => {\n // Remove dropping placeholder from layout\n const newLayout = layout.filter(item => item.i !== \"__dropping-elem__\");\n setLayoutState(newLayout);\n\n setDropState({\n droppingDOMNode: null,\n droppingPosition: null\n });\n }, [layout]);\n\n const onDrop = useCallback(\n (droppingItem: LayoutItem) => {\n // Replace placeholder with actual item\n const newLayout = layout.map(item => {\n if (item.i === \"__dropping-elem__\") {\n return {\n ...item,\n i: droppingItem.i,\n static: false\n };\n }\n return item;\n });\n\n const corrected = correctBounds(newLayout, { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n setLayoutState(compacted);\n\n setDropState({\n droppingDOMNode: null,\n droppingPosition: null\n });\n },\n [layout, cols, compactType, allowOverlap]\n );\n\n // ============================================================================\n // Computed Values\n // ============================================================================\n\n const containerHeight = useMemo(() => bottom(layout), [layout]);\n\n const isInteracting =\n dragState.activeDrag !== null ||\n resizeState.resizing ||\n dropState.droppingPosition !== null;\n\n return {\n layout,\n setLayout,\n dragState,\n resizeState,\n dropState,\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize,\n onResizeStop,\n onDropDragOver,\n onDropDragLeave,\n onDrop,\n containerHeight,\n isInteracting,\n compactor\n };\n}\n\nexport default useGridLayout;\n","/**\n * useResponsiveLayout hook\n *\n * Manages responsive breakpoints and layout generation for different screen sizes.\n * Extracts state management from ResponsiveReactGridLayout into a reusable hook.\n */\n\nimport { useState, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { deepEqual } from \"fast-equals\";\nimport type {\n Layout,\n Breakpoint,\n Breakpoints,\n ResponsiveLayouts,\n CompactType\n} from \"../../core/types.js\";\nimport { cloneLayout } from \"../../core/layout.js\";\nimport {\n getBreakpointFromWidth,\n getColsFromBreakpoint,\n findOrGenerateResponsiveLayout,\n sortBreakpoints\n} from \"../../core/responsive.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Default breakpoint names */\nexport type DefaultBreakpoints = \"lg\" | \"md\" | \"sm\" | \"xs\" | \"xxs\";\n\n/** Default breakpoint widths */\nexport const DEFAULT_BREAKPOINTS: Breakpoints<DefaultBreakpoints> = {\n lg: 1200,\n md: 996,\n sm: 768,\n xs: 480,\n xxs: 0\n};\n\n/** Default column counts per breakpoint */\nexport const DEFAULT_COLS: Breakpoints<DefaultBreakpoints> = {\n lg: 12,\n md: 10,\n sm: 6,\n xs: 4,\n xxs: 2\n};\n\nexport interface UseResponsiveLayoutOptions<\n B extends Breakpoint = DefaultBreakpoints\n> {\n /** Current container width */\n width: number;\n /** Breakpoint definitions (name → min-width) */\n breakpoints?: Breakpoints<B>;\n /** Column counts per breakpoint */\n cols?: Breakpoints<B>;\n /** Layouts for each breakpoint */\n layouts?: ResponsiveLayouts<B>;\n /** Compaction type */\n compactType?: CompactType;\n /** Called when breakpoint changes */\n onBreakpointChange?: (newBreakpoint: B, cols: number) => void;\n /** Called when layout changes */\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void;\n /** Called when width changes */\n onWidthChange?: (\n width: number,\n margin: readonly [number, number],\n cols: number,\n containerPadding: readonly [number, number] | null\n ) => void;\n}\n\nexport interface UseResponsiveLayoutResult<\n B extends Breakpoint = DefaultBreakpoints\n> {\n /** Current layout for the active breakpoint */\n layout: Layout;\n /** All layouts by breakpoint */\n layouts: ResponsiveLayouts<B>;\n /** Current active breakpoint */\n breakpoint: B;\n /** Column count for the current breakpoint */\n cols: number;\n /** Update layouts for a specific breakpoint */\n setLayoutForBreakpoint: (breakpoint: B, layout: Layout) => void;\n /** Update all layouts */\n setLayouts: (layouts: ResponsiveLayouts<B>) => void;\n /** Sorted array of breakpoint names (smallest to largest) */\n sortedBreakpoints: B[];\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for managing responsive grid layouts.\n *\n * Automatically selects the appropriate layout based on container width\n * and generates layouts for new breakpoints from existing ones.\n *\n * @example\n * ```tsx\n * function MyResponsiveGrid() {\n * const { width, containerRef } = useContainerWidth();\n * const { layout, breakpoint, cols } = useResponsiveLayout({\n * width,\n * layouts: {\n * lg: [...],\n * md: [...],\n * sm: [...]\n * }\n * });\n *\n * return (\n * <div ref={containerRef}>\n * <GridLayout\n * width={width}\n * cols={cols}\n * layout={layout}\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function useResponsiveLayout<B extends Breakpoint = DefaultBreakpoints>(\n options: UseResponsiveLayoutOptions<B>\n): UseResponsiveLayoutResult<B> {\n const {\n width,\n breakpoints = DEFAULT_BREAKPOINTS as unknown as Breakpoints<B>,\n cols: colsConfig = DEFAULT_COLS as unknown as Breakpoints<B>,\n layouts: propsLayouts = {} as ResponsiveLayouts<B>,\n compactType = \"vertical\",\n onBreakpointChange,\n onLayoutChange,\n onWidthChange\n } = options;\n\n // Sorted breakpoints for consistent ordering\n const sortedBreakpoints = useMemo(\n () => sortBreakpoints(breakpoints),\n [breakpoints]\n );\n\n // Calculate initial breakpoint and cols\n const initialBreakpoint = useMemo(\n () => getBreakpointFromWidth(breakpoints, width),\n // Only calculate on mount, not on width changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n const initialCols = useMemo(\n () => getColsFromBreakpoint(initialBreakpoint, colsConfig),\n [initialBreakpoint, colsConfig]\n );\n\n // State\n const [breakpoint, setBreakpoint] = useState<B>(initialBreakpoint);\n const [cols, setCols] = useState<number>(initialCols);\n const [layouts, setLayoutsState] = useState<ResponsiveLayouts<B>>(() => {\n // Clone initial layouts\n const cloned = {} as ResponsiveLayouts<B>;\n for (const bp of sortedBreakpoints) {\n const layout = propsLayouts[bp];\n if (layout) {\n (cloned as Record<B, Layout>)[bp] = cloneLayout(layout);\n }\n }\n return cloned;\n });\n\n // Track previous values for change detection\n const prevWidthRef = useRef(width);\n const prevBreakpointRef = useRef(breakpoint);\n const prevLayoutsRef = useRef(layouts);\n\n // Current layout for the active breakpoint\n const layout = useMemo(() => {\n return findOrGenerateResponsiveLayout(\n layouts,\n breakpoints,\n breakpoint,\n prevBreakpointRef.current,\n cols,\n compactType\n );\n }, [layouts, breakpoints, breakpoint, cols, compactType]);\n\n // Set layout for a specific breakpoint\n const setLayoutForBreakpoint = useCallback((bp: B, newLayout: Layout) => {\n setLayoutsState((prev: ResponsiveLayouts<B>) => ({\n ...prev,\n [bp]: cloneLayout(newLayout)\n }));\n }, []);\n\n // Set all layouts\n const setLayouts = useCallback((newLayouts: ResponsiveLayouts<B>) => {\n const cloned = {} as ResponsiveLayouts<B>;\n for (const bp of Object.keys(newLayouts) as B[]) {\n const layoutForBp = newLayouts[bp];\n if (layoutForBp) {\n (cloned as Record<B, Layout>)[bp] = cloneLayout(layoutForBp);\n }\n }\n setLayoutsState(cloned);\n }, []);\n\n // Handle width changes\n useEffect(() => {\n if (prevWidthRef.current === width) return;\n prevWidthRef.current = width;\n\n // Determine new breakpoint\n const newBreakpoint = getBreakpointFromWidth(breakpoints, width);\n const newCols = getColsFromBreakpoint(newBreakpoint, colsConfig);\n\n // Notify width change\n onWidthChange?.(width, [10, 10], newCols, null);\n\n // Check if breakpoint changed\n if (newBreakpoint !== breakpoint) {\n // Generate layout for new breakpoint\n const newLayout = findOrGenerateResponsiveLayout(\n layouts,\n breakpoints,\n newBreakpoint,\n breakpoint,\n newCols,\n compactType\n );\n\n // Update layouts with the new breakpoint layout\n const updatedLayouts: ResponsiveLayouts<B> = {\n ...layouts,\n [newBreakpoint]: newLayout\n };\n\n setLayoutsState(updatedLayouts);\n setBreakpoint(newBreakpoint);\n setCols(newCols);\n\n // Notify breakpoint change\n onBreakpointChange?.(newBreakpoint, newCols);\n\n prevBreakpointRef.current = newBreakpoint;\n }\n }, [\n width,\n breakpoints,\n colsConfig,\n breakpoint,\n layouts,\n compactType,\n onBreakpointChange,\n onWidthChange\n ]);\n\n // Sync with prop layouts when they change\n useEffect(() => {\n if (!deepEqual(propsLayouts, prevLayoutsRef.current)) {\n setLayouts(propsLayouts);\n prevLayoutsRef.current = propsLayouts;\n }\n }, [propsLayouts, setLayouts]);\n\n // Notify layout changes\n useEffect(() => {\n if (!deepEqual(layouts, prevLayoutsRef.current)) {\n prevLayoutsRef.current = layouts;\n onLayoutChange?.(layout, layouts);\n }\n }, [layout, layouts, onLayoutChange]);\n\n return {\n layout,\n layouts,\n breakpoint,\n cols,\n setLayoutForBreakpoint,\n setLayouts,\n sortedBreakpoints\n };\n}\n\nexport default useResponsiveLayout;\n"]} |
| 'use strict'; | ||
| //# sourceMappingURL=chunk-PBQSHIID.js.map | ||
| //# sourceMappingURL=chunk-PBQSHIID.js.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-PBQSHIID.js"} |
| import { setTransform, setTopLeft, perc, resizeItemInDirection, defaultPositionStrategy, defaultGridConfig, defaultDragConfig, defaultResizeConfig, defaultDropConfig, getCompactor, bottom, getLayoutItem, cloneLayoutItem, moveElement, compact, withLayoutItem, getAllCollisions, getBreakpointFromWidth, getColsFromBreakpoint, findOrGenerateResponsiveLayout, cloneLayout, getIndentationValue, correctBounds } from './chunk-4HNUMWQK.mjs'; | ||
| import { calcXY, calcGridItemWHPx, clamp, calcGridColWidth, calcWH, calcGridItemPosition } from './chunk-2KUHNJXF.mjs'; | ||
| import React2, { useState, useRef, useMemo, useCallback, useEffect } from 'react'; | ||
| import { DraggableCore } from 'react-draggable'; | ||
| import { Resizable } from 'react-resizable'; | ||
| import clsx from 'clsx'; | ||
| import { jsx, jsxs } from 'react/jsx-runtime'; | ||
| import { deepEqual } from 'fast-equals'; | ||
| function GridItem(props) { | ||
| const { | ||
| children, | ||
| cols, | ||
| containerWidth, | ||
| margin, | ||
| containerPadding, | ||
| rowHeight, | ||
| maxRows, | ||
| isDraggable, | ||
| isResizable, | ||
| isBounded, | ||
| static: isStatic, | ||
| useCSSTransforms = true, | ||
| usePercentages = false, | ||
| transformScale = 1, | ||
| droppingPosition, | ||
| className = "", | ||
| style, | ||
| handle = "", | ||
| cancel = "", | ||
| x, | ||
| y, | ||
| w, | ||
| h, | ||
| minW = 1, | ||
| maxW = Infinity, | ||
| minH = 1, | ||
| maxH = Infinity, | ||
| i, | ||
| resizeHandles, | ||
| resizeHandle, | ||
| onDragStart: onDragStartProp, | ||
| onDrag: onDragProp, | ||
| onDragStop: onDragStopProp, | ||
| onResizeStart: onResizeStartProp, | ||
| onResize: onResizeProp, | ||
| onResizeStop: onResizeStopProp | ||
| } = props; | ||
| const [dragging, setDragging] = useState(false); | ||
| const [resizing, setResizing] = useState(false); | ||
| const elementRef = useRef(null); | ||
| const dragPositionRef = useRef({ left: 0, top: 0 }); | ||
| const resizePositionRef = useRef({ | ||
| top: 0, | ||
| left: 0, | ||
| width: 0, | ||
| height: 0 | ||
| }); | ||
| const prevDroppingPositionRef = useRef( | ||
| void 0 | ||
| ); | ||
| const positionParams = useMemo( | ||
| () => ({ | ||
| cols, | ||
| containerPadding, | ||
| containerWidth, | ||
| margin, | ||
| maxRows, | ||
| rowHeight | ||
| }), | ||
| [cols, containerPadding, containerWidth, margin, maxRows, rowHeight] | ||
| ); | ||
| const createStyle = useCallback( | ||
| (pos2) => { | ||
| if (useCSSTransforms) { | ||
| return setTransform(pos2); | ||
| } | ||
| const styleObj = setTopLeft(pos2); | ||
| if (usePercentages) { | ||
| return { | ||
| ...styleObj, | ||
| left: perc(pos2.left / containerWidth), | ||
| width: perc(pos2.width / containerWidth) | ||
| }; | ||
| } | ||
| return styleObj; | ||
| }, | ||
| [useCSSTransforms, usePercentages, containerWidth] | ||
| ); | ||
| const onDragStart = useCallback( | ||
| (e, { node }) => { | ||
| if (!onDragStartProp) return; | ||
| const { offsetParent } = node; | ||
| if (!offsetParent) return; | ||
| const parentRect = offsetParent.getBoundingClientRect(); | ||
| const clientRect = node.getBoundingClientRect(); | ||
| const cLeft = clientRect.left / transformScale; | ||
| const pLeft = parentRect.left / transformScale; | ||
| const cTop = clientRect.top / transformScale; | ||
| const pTop = parentRect.top / transformScale; | ||
| const newPosition = { | ||
| left: cLeft - pLeft + offsetParent.scrollLeft, | ||
| top: cTop - pTop + offsetParent.scrollTop | ||
| }; | ||
| dragPositionRef.current = newPosition; | ||
| setDragging(true); | ||
| const { x: newX, y: newY } = calcXY( | ||
| positionParams, | ||
| newPosition.top, | ||
| newPosition.left, | ||
| w, | ||
| h | ||
| ); | ||
| onDragStartProp(i, newX, newY, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }, | ||
| [onDragStartProp, transformScale, positionParams, w, h, i] | ||
| ); | ||
| const onDrag = useCallback( | ||
| (e, { node, deltaX, deltaY }) => { | ||
| if (!onDragProp || !dragging) return; | ||
| let top = dragPositionRef.current.top + deltaY; | ||
| let left = dragPositionRef.current.left + deltaX; | ||
| if (isBounded) { | ||
| const { offsetParent } = node; | ||
| if (offsetParent) { | ||
| const bottomBoundary = offsetParent.clientHeight - calcGridItemWHPx(h, rowHeight, margin[1]); | ||
| top = clamp(top, 0, bottomBoundary); | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| const rightBoundary = containerWidth - calcGridItemWHPx(w, colWidth, margin[0]); | ||
| left = clamp(left, 0, rightBoundary); | ||
| } | ||
| } | ||
| const newPosition = { top, left }; | ||
| dragPositionRef.current = newPosition; | ||
| const { x: newX, y: newY } = calcXY(positionParams, top, left, w, h); | ||
| onDragProp(i, newX, newY, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }, | ||
| [ | ||
| onDragProp, | ||
| dragging, | ||
| isBounded, | ||
| h, | ||
| rowHeight, | ||
| margin, | ||
| positionParams, | ||
| containerWidth, | ||
| w, | ||
| i | ||
| ] | ||
| ); | ||
| const onDragStop = useCallback( | ||
| (e, { node }) => { | ||
| if (!onDragStopProp || !dragging) return; | ||
| const { left, top } = dragPositionRef.current; | ||
| const newPosition = { top, left }; | ||
| setDragging(false); | ||
| dragPositionRef.current = { left: 0, top: 0 }; | ||
| const { x: newX, y: newY } = calcXY(positionParams, top, left, w, h); | ||
| onDragStopProp(i, newX, newY, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }, | ||
| [onDragStopProp, dragging, positionParams, w, h, i] | ||
| ); | ||
| const onResizeHandler = useCallback( | ||
| (e, { node, size, handle: resizeHandle2 }, position, handlerName) => { | ||
| const handler = handlerName === "onResizeStart" ? onResizeStartProp : handlerName === "onResize" ? onResizeProp : onResizeStopProp; | ||
| if (!handler) return; | ||
| let updatedSize; | ||
| if (node) { | ||
| updatedSize = resizeItemInDirection( | ||
| resizeHandle2, | ||
| position, | ||
| size, | ||
| containerWidth | ||
| ); | ||
| } else { | ||
| updatedSize = { | ||
| ...size, | ||
| top: position.top, | ||
| left: position.left | ||
| }; | ||
| } | ||
| resizePositionRef.current = updatedSize; | ||
| let { w: newW, h: newH } = calcWH( | ||
| positionParams, | ||
| updatedSize.width, | ||
| updatedSize.height, | ||
| x, | ||
| y, | ||
| resizeHandle2 | ||
| ); | ||
| newW = clamp(newW, Math.max(minW, 1), maxW); | ||
| newH = clamp(newH, minH, maxH); | ||
| handler(i, newW, newH, { | ||
| e: e.nativeEvent, | ||
| node, | ||
| size: updatedSize, | ||
| handle: resizeHandle2 | ||
| }); | ||
| }, | ||
| [ | ||
| onResizeStartProp, | ||
| onResizeProp, | ||
| onResizeStopProp, | ||
| containerWidth, | ||
| positionParams, | ||
| x, | ||
| y, | ||
| minW, | ||
| maxW, | ||
| minH, | ||
| maxH, | ||
| i | ||
| ] | ||
| ); | ||
| const handleResizeStart = useCallback( | ||
| (e, data) => { | ||
| setResizing(true); | ||
| const pos2 = calcGridItemPosition(positionParams, x, y, w, h); | ||
| const typedData = { | ||
| ...data, | ||
| handle: data.handle | ||
| }; | ||
| onResizeHandler(e, typedData, pos2, "onResizeStart"); | ||
| }, | ||
| [onResizeHandler, positionParams, x, y, w, h] | ||
| ); | ||
| const handleResize = useCallback( | ||
| (e, data) => { | ||
| const pos2 = calcGridItemPosition(positionParams, x, y, w, h); | ||
| const typedData = { | ||
| ...data, | ||
| handle: data.handle | ||
| }; | ||
| onResizeHandler(e, typedData, pos2, "onResize"); | ||
| }, | ||
| [onResizeHandler, positionParams, x, y, w, h] | ||
| ); | ||
| const handleResizeStop = useCallback( | ||
| (e, data) => { | ||
| setResizing(false); | ||
| resizePositionRef.current = { top: 0, left: 0, width: 0, height: 0 }; | ||
| const pos2 = calcGridItemPosition(positionParams, x, y, w, h); | ||
| const typedData = { | ||
| ...data, | ||
| handle: data.handle | ||
| }; | ||
| onResizeHandler(e, typedData, pos2, "onResizeStop"); | ||
| }, | ||
| [onResizeHandler, positionParams, x, y, w, h] | ||
| ); | ||
| useEffect(() => { | ||
| if (!droppingPosition) return; | ||
| const node = elementRef.current; | ||
| if (!node) return; | ||
| const prevDroppingPosition = prevDroppingPositionRef.current || { | ||
| left: 0, | ||
| top: 0 | ||
| }; | ||
| const shouldDrag = dragging && (droppingPosition.left !== prevDroppingPosition.left || droppingPosition.top !== prevDroppingPosition.top); | ||
| if (!dragging) { | ||
| const fakeData = { | ||
| node, | ||
| deltaX: droppingPosition.left, | ||
| deltaY: droppingPosition.top, | ||
| lastX: 0, | ||
| lastY: 0, | ||
| x: droppingPosition.left, | ||
| y: droppingPosition.top | ||
| }; | ||
| onDragStart(droppingPosition.e, fakeData); | ||
| } else if (shouldDrag) { | ||
| const deltaX = droppingPosition.left - dragPositionRef.current.left; | ||
| const deltaY = droppingPosition.top - dragPositionRef.current.top; | ||
| const fakeData = { | ||
| node, | ||
| deltaX, | ||
| deltaY, | ||
| lastX: dragPositionRef.current.left, | ||
| lastY: dragPositionRef.current.top, | ||
| x: droppingPosition.left, | ||
| y: droppingPosition.top | ||
| }; | ||
| onDrag(droppingPosition.e, fakeData); | ||
| } | ||
| prevDroppingPositionRef.current = droppingPosition; | ||
| }, [droppingPosition, dragging, onDragStart, onDrag]); | ||
| const pos = calcGridItemPosition( | ||
| positionParams, | ||
| x, | ||
| y, | ||
| w, | ||
| h, | ||
| dragging ? dragPositionRef.current : null, | ||
| resizing ? resizePositionRef.current : null | ||
| ); | ||
| const child = React2.Children.only(children); | ||
| const maxWidth = calcGridItemPosition(positionParams, 0, 0, cols, 0).width; | ||
| const mins = calcGridItemPosition(positionParams, 0, 0, minW, minH); | ||
| const maxes = calcGridItemPosition(positionParams, 0, 0, maxW, maxH); | ||
| const minConstraints = [mins.width, mins.height]; | ||
| const maxConstraints = [ | ||
| Math.min(maxes.width, maxWidth), | ||
| Math.min(maxes.height, Infinity) | ||
| ]; | ||
| const childProps = child.props; | ||
| const childClassName = childProps["className"]; | ||
| const childStyle = childProps["style"]; | ||
| let newChild = React2.cloneElement(child, { | ||
| ref: elementRef, | ||
| className: clsx("react-grid-item", childClassName, className, { | ||
| static: isStatic, | ||
| resizing, | ||
| "react-draggable": isDraggable, | ||
| "react-draggable-dragging": dragging, | ||
| dropping: Boolean(droppingPosition), | ||
| cssTransforms: useCSSTransforms | ||
| }), | ||
| style: { | ||
| ...style, | ||
| ...childStyle, | ||
| ...createStyle(pos) | ||
| } | ||
| }); | ||
| const resizableHandle = resizeHandle; | ||
| newChild = /* @__PURE__ */ jsx( | ||
| Resizable, | ||
| { | ||
| draggableOpts: { disabled: !isResizable }, | ||
| className: isResizable ? void 0 : "react-resizable-hide", | ||
| width: pos.width, | ||
| height: pos.height, | ||
| minConstraints, | ||
| maxConstraints, | ||
| onResizeStart: handleResizeStart, | ||
| onResize: handleResize, | ||
| onResizeStop: handleResizeStop, | ||
| transformScale, | ||
| resizeHandles, | ||
| handle: resizableHandle, | ||
| children: newChild | ||
| } | ||
| ); | ||
| newChild = /* @__PURE__ */ jsx( | ||
| DraggableCore, | ||
| { | ||
| disabled: !isDraggable, | ||
| onStart: onDragStart, | ||
| onDrag, | ||
| onStop: onDragStop, | ||
| handle, | ||
| cancel: ".react-resizable-handle" + (cancel ? "," + cancel : ""), | ||
| scale: transformScale, | ||
| nodeRef: elementRef, | ||
| children: newChild | ||
| } | ||
| ); | ||
| return newChild; | ||
| } | ||
| var noop = () => { | ||
| }; | ||
| var layoutClassName = "react-grid-layout"; | ||
| var isFirefox = false; | ||
| try { | ||
| isFirefox = /firefox/i.test(navigator.userAgent); | ||
| } catch { | ||
| } | ||
| function childrenEqual(a, b) { | ||
| const aArr = React2.Children.toArray(a); | ||
| const bArr = React2.Children.toArray(b); | ||
| if (aArr.length !== bArr.length) return false; | ||
| for (let i = 0; i < aArr.length; i++) { | ||
| const aChild = aArr[i]; | ||
| const bChild = bArr[i]; | ||
| if (aChild?.key !== bChild?.key) return false; | ||
| } | ||
| return true; | ||
| } | ||
| function synchronizeLayoutWithChildren(initialLayout, children, cols, compactType, allowOverlap) { | ||
| const layout = []; | ||
| const childKeys = /* @__PURE__ */ new Set(); | ||
| React2.Children.forEach(children, (child) => { | ||
| if (!React2.isValidElement(child) || child.key === null) return; | ||
| const key = String(child.key); | ||
| childKeys.add(key); | ||
| const existingItem = initialLayout.find((l) => l.i === key); | ||
| if (existingItem) { | ||
| layout.push(cloneLayoutItem(existingItem)); | ||
| } else { | ||
| const childProps = child.props; | ||
| const dataGrid = childProps["data-grid"]; | ||
| if (dataGrid) { | ||
| layout.push({ | ||
| i: key, | ||
| x: dataGrid.x ?? 0, | ||
| y: dataGrid.y ?? 0, | ||
| w: dataGrid.w ?? 1, | ||
| h: dataGrid.h ?? 1, | ||
| minW: dataGrid.minW, | ||
| maxW: dataGrid.maxW, | ||
| minH: dataGrid.minH, | ||
| maxH: dataGrid.maxH, | ||
| static: dataGrid.static, | ||
| isDraggable: dataGrid.isDraggable, | ||
| isResizable: dataGrid.isResizable, | ||
| resizeHandles: dataGrid.resizeHandles, | ||
| isBounded: dataGrid.isBounded | ||
| }); | ||
| } else { | ||
| layout.push({ | ||
| i: key, | ||
| x: 0, | ||
| y: bottom(layout), | ||
| w: 1, | ||
| h: 1 | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| const corrected = correctBounds(layout, { cols }); | ||
| return compact(corrected, compactType, cols, allowOverlap); | ||
| } | ||
| function GridLayout(props) { | ||
| const { | ||
| // Required | ||
| children, | ||
| width, | ||
| // Composable config interfaces | ||
| gridConfig: gridConfigProp, | ||
| dragConfig: dragConfigProp, | ||
| resizeConfig: resizeConfigProp, | ||
| dropConfig: dropConfigProp, | ||
| positionStrategy = defaultPositionStrategy, | ||
| compactor: compactorProp, | ||
| // Layout data | ||
| layout: propsLayout = [], | ||
| droppingItem: droppingItemProp, | ||
| // Container props | ||
| autoSize = true, | ||
| className = "", | ||
| style = {}, | ||
| innerRef, | ||
| // Callbacks | ||
| onLayoutChange = noop, | ||
| onDragStart: onDragStartProp = noop, | ||
| onDrag: onDragProp = noop, | ||
| onDragStop: onDragStopProp = noop, | ||
| onResizeStart: onResizeStartProp = noop, | ||
| onResize: onResizeProp = noop, | ||
| onResizeStop: onResizeStopProp = noop, | ||
| onDrop: onDropProp = noop, | ||
| onDropDragOver: onDropDragOverProp = noop | ||
| } = props; | ||
| const gridConfig = useMemo( | ||
| () => ({ ...defaultGridConfig, ...gridConfigProp }), | ||
| [gridConfigProp] | ||
| ); | ||
| const dragConfig = useMemo( | ||
| () => ({ ...defaultDragConfig, ...dragConfigProp }), | ||
| [dragConfigProp] | ||
| ); | ||
| const resizeConfig = useMemo( | ||
| () => ({ ...defaultResizeConfig, ...resizeConfigProp }), | ||
| [resizeConfigProp] | ||
| ); | ||
| const dropConfig = useMemo( | ||
| () => ({ ...defaultDropConfig, ...dropConfigProp }), | ||
| [dropConfigProp] | ||
| ); | ||
| const { cols, rowHeight, maxRows, margin, containerPadding } = gridConfig; | ||
| const { | ||
| enabled: isDraggable, | ||
| bounded: isBounded, | ||
| handle: draggableHandle, | ||
| cancel: draggableCancel | ||
| } = dragConfig; | ||
| const { | ||
| enabled: isResizable, | ||
| handles: resizeHandles, | ||
| handleComponent: resizeHandle | ||
| } = resizeConfig; | ||
| const { enabled: isDroppable, defaultItem: defaultDropItem } = dropConfig; | ||
| const compactor = compactorProp ?? getCompactor("vertical"); | ||
| const compactType = compactor.type; | ||
| const allowOverlap = compactor.allowOverlap; | ||
| const preventCollision = compactor.preventCollision ?? false; | ||
| const droppingItem = useMemo( | ||
| () => droppingItemProp ?? { | ||
| i: "__dropping-elem__", | ||
| ...defaultDropItem | ||
| }, | ||
| [droppingItemProp, defaultDropItem] | ||
| ); | ||
| const useCSSTransforms = positionStrategy.type === "transform"; | ||
| const transformScale = positionStrategy.scale; | ||
| const effectiveContainerPadding = containerPadding ?? margin; | ||
| const [mounted, setMounted] = useState(false); | ||
| const [layout, setLayout] = useState( | ||
| () => synchronizeLayoutWithChildren( | ||
| propsLayout, | ||
| children, | ||
| cols, | ||
| compactType, | ||
| allowOverlap | ||
| ) | ||
| ); | ||
| const [activeDrag, setActiveDrag] = useState(null); | ||
| const [resizing, setResizing] = useState(false); | ||
| const [droppingDOMNode, setDroppingDOMNode] = useState( | ||
| null | ||
| ); | ||
| const [droppingPosition, setDroppingPosition] = useState(); | ||
| const oldDragItemRef = useRef(null); | ||
| const oldResizeItemRef = useRef(null); | ||
| const oldLayoutRef = useRef(null); | ||
| const dragEnterCounterRef = useRef(0); | ||
| const prevLayoutRef = useRef(layout); | ||
| const prevPropsLayoutRef = useRef(propsLayout); | ||
| const prevChildrenRef = useRef(children); | ||
| const prevCompactTypeRef = useRef(compactType); | ||
| useEffect(() => { | ||
| setMounted(true); | ||
| if (!deepEqual(layout, propsLayout)) { | ||
| onLayoutChange(layout); | ||
| } | ||
| }, []); | ||
| useEffect(() => { | ||
| if (activeDrag) return; | ||
| const layoutChanged = !deepEqual(propsLayout, prevPropsLayoutRef.current); | ||
| const childrenChanged = !childrenEqual(children, prevChildrenRef.current); | ||
| const compactTypeChanged = compactType !== prevCompactTypeRef.current; | ||
| if (layoutChanged || childrenChanged || compactTypeChanged) { | ||
| const baseLayout = layoutChanged ? propsLayout : layout; | ||
| const newLayout = synchronizeLayoutWithChildren( | ||
| baseLayout, | ||
| children, | ||
| cols, | ||
| compactType, | ||
| allowOverlap | ||
| ); | ||
| setLayout(newLayout); | ||
| } | ||
| prevPropsLayoutRef.current = propsLayout; | ||
| prevChildrenRef.current = children; | ||
| prevCompactTypeRef.current = compactType; | ||
| }, [ | ||
| propsLayout, | ||
| children, | ||
| cols, | ||
| compactType, | ||
| allowOverlap, | ||
| activeDrag, | ||
| layout | ||
| ]); | ||
| useEffect(() => { | ||
| if (!activeDrag && !deepEqual(layout, prevLayoutRef.current)) { | ||
| prevLayoutRef.current = layout; | ||
| onLayoutChange(layout); | ||
| } | ||
| }, [layout, activeDrag, onLayoutChange]); | ||
| const containerHeight = useMemo(() => { | ||
| if (!autoSize) return void 0; | ||
| const nbRow = bottom(layout); | ||
| const containerPaddingY = effectiveContainerPadding[1]; | ||
| return nbRow * rowHeight + (nbRow - 1) * margin[1] + containerPaddingY * 2 + "px"; | ||
| }, [autoSize, layout, rowHeight, margin, effectiveContainerPadding]); | ||
| const onDragStart = useCallback( | ||
| (i, _x, _y, data) => { | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i | ||
| }; | ||
| oldDragItemRef.current = cloneLayoutItem(l); | ||
| oldLayoutRef.current = layout; | ||
| setActiveDrag(placeholder); | ||
| onDragStartProp(layout, l, l, null, data.e, data.node); | ||
| }, | ||
| [layout, onDragStartProp] | ||
| ); | ||
| const onDrag = useCallback( | ||
| (i, x, y, data) => { | ||
| const oldDragItem = oldDragItemRef.current; | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i | ||
| }; | ||
| const newLayout = moveElement( | ||
| layout, | ||
| l, | ||
| x, | ||
| y, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| onDragProp(newLayout, oldDragItem, l, placeholder, data.e, data.node); | ||
| setLayout( | ||
| allowOverlap ? newLayout : compact(newLayout, compactType, cols) | ||
| ); | ||
| setActiveDrag(placeholder); | ||
| }, | ||
| [layout, preventCollision, compactType, cols, allowOverlap, onDragProp] | ||
| ); | ||
| const onDragStop = useCallback( | ||
| (i, x, y, data) => { | ||
| if (!activeDrag) return; | ||
| const oldDragItem = oldDragItemRef.current; | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| const newLayout = moveElement( | ||
| layout, | ||
| l, | ||
| x, | ||
| y, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const finalLayout = allowOverlap ? newLayout : compact(newLayout, compactType, cols); | ||
| onDragStopProp(finalLayout, oldDragItem, l, null, data.e, data.node); | ||
| const oldLayout = oldLayoutRef.current; | ||
| oldDragItemRef.current = null; | ||
| oldLayoutRef.current = null; | ||
| setActiveDrag(null); | ||
| setLayout(finalLayout); | ||
| if (oldLayout && !deepEqual(oldLayout, finalLayout)) { | ||
| onLayoutChange(finalLayout); | ||
| } | ||
| }, | ||
| [ | ||
| activeDrag, | ||
| layout, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap, | ||
| onDragStopProp, | ||
| onLayoutChange | ||
| ] | ||
| ); | ||
| const onResizeStart = useCallback( | ||
| (i, _w, _h, data) => { | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| oldResizeItemRef.current = cloneLayoutItem(l); | ||
| oldLayoutRef.current = layout; | ||
| setResizing(true); | ||
| onResizeStartProp(layout, l, l, null, data.e, data.node); | ||
| }, | ||
| [layout, onResizeStartProp] | ||
| ); | ||
| const onResize = useCallback( | ||
| (i, w, h, data) => { | ||
| const oldResizeItem = oldResizeItemRef.current; | ||
| const { handle } = data; | ||
| let shouldMoveItem = false; | ||
| let newX; | ||
| let newY; | ||
| const [newLayout, l] = withLayoutItem(layout, i, (item) => { | ||
| newX = item.x; | ||
| newY = item.y; | ||
| if (["sw", "w", "nw", "n", "ne"].includes(handle)) { | ||
| if (["sw", "nw", "w"].includes(handle)) { | ||
| newX = item.x + (item.w - w); | ||
| w = item.x !== newX && newX < 0 ? item.w : w; | ||
| newX = newX < 0 ? 0 : newX; | ||
| } | ||
| if (["ne", "n", "nw"].includes(handle)) { | ||
| newY = item.y + (item.h - h); | ||
| h = item.y !== newY && newY < 0 ? item.h : h; | ||
| newY = newY < 0 ? 0 : newY; | ||
| } | ||
| shouldMoveItem = true; | ||
| } | ||
| if (preventCollision && !allowOverlap) { | ||
| const collisions = getAllCollisions(layout, { | ||
| ...item, | ||
| w, | ||
| h, | ||
| x: newX ?? item.x, | ||
| y: newY ?? item.y | ||
| }).filter((layoutItem) => layoutItem.i !== item.i); | ||
| if (collisions.length > 0) { | ||
| newY = item.y; | ||
| h = item.h; | ||
| newX = item.x; | ||
| w = item.w; | ||
| shouldMoveItem = false; | ||
| } | ||
| } | ||
| item.w = w; | ||
| item.h = h; | ||
| return item; | ||
| }); | ||
| if (!l) return; | ||
| let finalLayout = newLayout; | ||
| if (shouldMoveItem && newX !== void 0 && newY !== void 0) { | ||
| finalLayout = moveElement( | ||
| newLayout, | ||
| l, | ||
| newX, | ||
| newY, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| } | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i, | ||
| static: true | ||
| }; | ||
| onResizeProp( | ||
| finalLayout, | ||
| oldResizeItem, | ||
| l, | ||
| placeholder, | ||
| data.e, | ||
| data.node | ||
| ); | ||
| setLayout( | ||
| allowOverlap ? finalLayout : compact(finalLayout, compactType, cols) | ||
| ); | ||
| setActiveDrag(placeholder); | ||
| }, | ||
| [layout, preventCollision, allowOverlap, compactType, cols, onResizeProp] | ||
| ); | ||
| const onResizeStop = useCallback( | ||
| (i, _w, _h, data) => { | ||
| const oldResizeItem = oldResizeItemRef.current; | ||
| const l = getLayoutItem(layout, i); | ||
| const finalLayout = allowOverlap ? layout : compact(layout, compactType, cols); | ||
| onResizeStopProp( | ||
| finalLayout, | ||
| oldResizeItem, | ||
| l ?? null, | ||
| null, | ||
| data.e, | ||
| data.node | ||
| ); | ||
| const oldLayout = oldLayoutRef.current; | ||
| oldResizeItemRef.current = null; | ||
| oldLayoutRef.current = null; | ||
| setActiveDrag(null); | ||
| setResizing(false); | ||
| setLayout(finalLayout); | ||
| if (oldLayout && !deepEqual(oldLayout, finalLayout)) { | ||
| onLayoutChange(finalLayout); | ||
| } | ||
| }, | ||
| [layout, allowOverlap, compactType, cols, onResizeStopProp, onLayoutChange] | ||
| ); | ||
| const removeDroppingPlaceholder = useCallback(() => { | ||
| const newLayout = compact( | ||
| layout.filter((l) => l.i !== droppingItem.i), | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| setLayout(newLayout); | ||
| setDroppingDOMNode(null); | ||
| setActiveDrag(null); | ||
| setDroppingPosition(void 0); | ||
| }, [layout, droppingItem.i, compactType, cols, allowOverlap]); | ||
| const handleDragOver = useCallback( | ||
| (e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| if (isFirefox && !e.nativeEvent.target?.classList.contains( | ||
| layoutClassName | ||
| )) { | ||
| return false; | ||
| } | ||
| const onDragOverResult = onDropDragOverProp(e); | ||
| if (onDragOverResult === false) { | ||
| if (droppingDOMNode) { | ||
| removeDroppingPlaceholder(); | ||
| } | ||
| return false; | ||
| } | ||
| const finalDroppingItem = { ...droppingItem, ...onDragOverResult }; | ||
| const gridRect = e.currentTarget.getBoundingClientRect(); | ||
| const layerX = e.clientX - gridRect.left; | ||
| const layerY = e.clientY - gridRect.top; | ||
| const newDroppingPosition = { | ||
| left: layerX / transformScale, | ||
| top: layerY / transformScale, | ||
| e: e.nativeEvent | ||
| }; | ||
| if (!droppingDOMNode) { | ||
| const positionParams = { | ||
| cols, | ||
| margin, | ||
| maxRows, | ||
| rowHeight, | ||
| containerWidth: width, | ||
| containerPadding: effectiveContainerPadding | ||
| }; | ||
| const calculatedPosition = calcXY( | ||
| positionParams, | ||
| layerY, | ||
| layerX, | ||
| finalDroppingItem.w, | ||
| finalDroppingItem.h | ||
| ); | ||
| setDroppingDOMNode(/* @__PURE__ */ jsx("div", {}, finalDroppingItem.i)); | ||
| setDroppingPosition(newDroppingPosition); | ||
| setLayout([ | ||
| ...layout, | ||
| { | ||
| ...finalDroppingItem, | ||
| x: calculatedPosition.x, | ||
| y: calculatedPosition.y, | ||
| static: false, | ||
| isDraggable: true | ||
| } | ||
| ]); | ||
| } else if (droppingPosition) { | ||
| const shouldUpdate = droppingPosition.left !== layerX || droppingPosition.top !== layerY; | ||
| if (shouldUpdate) { | ||
| setDroppingPosition(newDroppingPosition); | ||
| } | ||
| } | ||
| }, | ||
| [ | ||
| droppingDOMNode, | ||
| droppingPosition, | ||
| droppingItem, | ||
| onDropDragOverProp, | ||
| removeDroppingPlaceholder, | ||
| transformScale, | ||
| cols, | ||
| margin, | ||
| maxRows, | ||
| rowHeight, | ||
| width, | ||
| effectiveContainerPadding, | ||
| layout | ||
| ] | ||
| ); | ||
| const handleDragLeave = useCallback( | ||
| (e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| dragEnterCounterRef.current--; | ||
| if (dragEnterCounterRef.current === 0) { | ||
| removeDroppingPlaceholder(); | ||
| } | ||
| }, | ||
| [removeDroppingPlaceholder] | ||
| ); | ||
| const handleDragEnter = useCallback((e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| dragEnterCounterRef.current++; | ||
| }, []); | ||
| const handleDrop = useCallback( | ||
| (e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| const item = layout.find((l) => l.i === droppingItem.i); | ||
| dragEnterCounterRef.current = 0; | ||
| removeDroppingPlaceholder(); | ||
| onDropProp(layout, item, e.nativeEvent); | ||
| }, | ||
| [layout, droppingItem.i, removeDroppingPlaceholder, onDropProp] | ||
| ); | ||
| const processGridItem = useCallback( | ||
| (child, isDroppingItem) => { | ||
| if (!child || !child.key) return null; | ||
| const l = getLayoutItem(layout, String(child.key)); | ||
| if (!l) return null; | ||
| const draggable = typeof l.isDraggable === "boolean" ? l.isDraggable : !l.static && isDraggable; | ||
| const resizable = typeof l.isResizable === "boolean" ? l.isResizable : !l.static && isResizable; | ||
| const resizeHandlesOptions = l.resizeHandles || [...resizeHandles]; | ||
| const bounded = draggable && isBounded && l.isBounded !== false; | ||
| const resizeHandleElement = resizeHandle; | ||
| return /* @__PURE__ */ jsx( | ||
| GridItem, | ||
| { | ||
| containerWidth: width, | ||
| cols, | ||
| margin, | ||
| containerPadding: effectiveContainerPadding, | ||
| maxRows, | ||
| rowHeight, | ||
| cancel: draggableCancel, | ||
| handle: draggableHandle, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| isDraggable: draggable, | ||
| isResizable: resizable, | ||
| isBounded: bounded, | ||
| useCSSTransforms: useCSSTransforms && mounted, | ||
| usePercentages: !mounted, | ||
| transformScale, | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i: l.i, | ||
| minH: l.minH, | ||
| minW: l.minW, | ||
| maxH: l.maxH, | ||
| maxW: l.maxW, | ||
| static: l.static, | ||
| droppingPosition: isDroppingItem ? droppingPosition : void 0, | ||
| resizeHandles: resizeHandlesOptions, | ||
| resizeHandle: resizeHandleElement, | ||
| children: child | ||
| }, | ||
| l.i | ||
| ); | ||
| }, | ||
| [ | ||
| layout, | ||
| width, | ||
| cols, | ||
| margin, | ||
| effectiveContainerPadding, | ||
| maxRows, | ||
| rowHeight, | ||
| draggableCancel, | ||
| draggableHandle, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| isDraggable, | ||
| isResizable, | ||
| isBounded, | ||
| useCSSTransforms, | ||
| mounted, | ||
| transformScale, | ||
| droppingPosition, | ||
| resizeHandles, | ||
| resizeHandle | ||
| ] | ||
| ); | ||
| const renderPlaceholder = () => { | ||
| if (!activeDrag) return null; | ||
| return /* @__PURE__ */ jsx( | ||
| GridItem, | ||
| { | ||
| w: activeDrag.w, | ||
| h: activeDrag.h, | ||
| x: activeDrag.x, | ||
| y: activeDrag.y, | ||
| i: activeDrag.i, | ||
| className: `react-grid-placeholder ${resizing ? "placeholder-resizing" : ""}`, | ||
| containerWidth: width, | ||
| cols, | ||
| margin, | ||
| containerPadding: effectiveContainerPadding, | ||
| maxRows, | ||
| rowHeight, | ||
| isDraggable: false, | ||
| isResizable: false, | ||
| isBounded: false, | ||
| useCSSTransforms, | ||
| transformScale, | ||
| children: /* @__PURE__ */ jsx("div", {}) | ||
| } | ||
| ); | ||
| }; | ||
| const mergedClassName = clsx(layoutClassName, className); | ||
| const mergedStyle = { | ||
| height: containerHeight, | ||
| ...style | ||
| }; | ||
| return /* @__PURE__ */ jsxs( | ||
| "div", | ||
| { | ||
| ref: innerRef, | ||
| className: mergedClassName, | ||
| style: mergedStyle, | ||
| onDrop: isDroppable ? handleDrop : void 0, | ||
| onDragLeave: isDroppable ? handleDragLeave : void 0, | ||
| onDragEnter: isDroppable ? handleDragEnter : void 0, | ||
| onDragOver: isDroppable ? handleDragOver : void 0, | ||
| children: [ | ||
| React2.Children.map(children, (child) => { | ||
| if (!React2.isValidElement(child)) return null; | ||
| return processGridItem(child); | ||
| }), | ||
| isDroppable && droppingDOMNode && processGridItem(droppingDOMNode, true), | ||
| renderPlaceholder() | ||
| ] | ||
| } | ||
| ); | ||
| } | ||
| var DEFAULT_BREAKPOINTS = { | ||
| lg: 1200, | ||
| md: 996, | ||
| sm: 768, | ||
| xs: 480, | ||
| xxs: 0 | ||
| }; | ||
| var DEFAULT_COLS = { | ||
| lg: 12, | ||
| md: 10, | ||
| sm: 6, | ||
| xs: 4, | ||
| xxs: 2 | ||
| }; | ||
| var noop2 = () => { | ||
| }; | ||
| function synchronizeLayoutWithChildren2(initialLayout, children, cols, compactType, allowOverlap) { | ||
| const layout = []; | ||
| React2.Children.forEach(children, (child) => { | ||
| if (!React2.isValidElement(child) || child.key === null) return; | ||
| const key = String(child.key); | ||
| const existingItem = initialLayout.find((l) => l.i === key); | ||
| if (existingItem) { | ||
| layout.push({ | ||
| ...existingItem, | ||
| i: key | ||
| }); | ||
| } else { | ||
| const childProps = child.props; | ||
| const dataGrid = childProps["data-grid"]; | ||
| if (dataGrid) { | ||
| layout.push({ | ||
| i: key, | ||
| x: dataGrid.x ?? 0, | ||
| y: dataGrid.y ?? 0, | ||
| w: dataGrid.w ?? 1, | ||
| h: dataGrid.h ?? 1, | ||
| minW: dataGrid.minW, | ||
| maxW: dataGrid.maxW, | ||
| minH: dataGrid.minH, | ||
| maxH: dataGrid.maxH, | ||
| static: dataGrid.static, | ||
| isDraggable: dataGrid.isDraggable, | ||
| isResizable: dataGrid.isResizable, | ||
| resizeHandles: dataGrid.resizeHandles, | ||
| isBounded: dataGrid.isBounded | ||
| }); | ||
| } else { | ||
| layout.push({ | ||
| i: key, | ||
| x: 0, | ||
| y: bottom(layout), | ||
| w: 1, | ||
| h: 1 | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| const corrected = correctBounds(layout, { cols }); | ||
| return compact(corrected, compactType, cols, allowOverlap); | ||
| } | ||
| function ResponsiveGridLayout(props) { | ||
| const { | ||
| children, | ||
| width, | ||
| breakpoint: propBreakpoint, | ||
| breakpoints = DEFAULT_BREAKPOINTS, | ||
| cols: colsConfig = DEFAULT_COLS, | ||
| layouts: propsLayouts = {}, | ||
| rowHeight = 150, | ||
| maxRows = Infinity, | ||
| margin: propMargin = [10, 10], | ||
| containerPadding: propContainerPadding = null, | ||
| compactor: compactorProp, | ||
| onBreakpointChange = noop2, | ||
| onLayoutChange = noop2, | ||
| onWidthChange = noop2, | ||
| ...restProps | ||
| } = props; | ||
| const compactor = compactorProp ?? getCompactor("vertical"); | ||
| const compactType = compactor.type; | ||
| const allowOverlap = compactor.allowOverlap; | ||
| const initialBreakpoint = useMemo(() => { | ||
| return propBreakpoint ?? getBreakpointFromWidth(breakpoints, width); | ||
| }, []); | ||
| const initialCols = useMemo(() => { | ||
| return getColsFromBreakpoint(initialBreakpoint, colsConfig); | ||
| }, [initialBreakpoint, colsConfig]); | ||
| const initialLayout = useMemo(() => { | ||
| return findOrGenerateResponsiveLayout( | ||
| propsLayouts, | ||
| breakpoints, | ||
| initialBreakpoint, | ||
| initialBreakpoint, | ||
| initialCols, | ||
| compactType | ||
| ); | ||
| }, []); | ||
| const [breakpoint, setBreakpoint] = useState(initialBreakpoint); | ||
| const [cols, setCols] = useState(initialCols); | ||
| const [layout, setLayout] = useState(initialLayout); | ||
| const [layouts, setLayouts] = useState(propsLayouts); | ||
| const prevWidthRef = useRef(width); | ||
| const prevBreakpointRef = useRef(propBreakpoint); | ||
| const prevBreakpointsRef = useRef(breakpoints); | ||
| const prevColsRef = useRef(colsConfig); | ||
| const prevLayoutsRef = useRef(propsLayouts); | ||
| const prevCompactTypeRef = useRef(compactType); | ||
| useEffect(() => { | ||
| if (!deepEqual(propsLayouts, prevLayoutsRef.current)) { | ||
| const newLayout = findOrGenerateResponsiveLayout( | ||
| propsLayouts, | ||
| breakpoints, | ||
| breakpoint, | ||
| breakpoint, | ||
| cols, | ||
| compactType | ||
| ); | ||
| setLayout(newLayout); | ||
| setLayouts(propsLayouts); | ||
| prevLayoutsRef.current = propsLayouts; | ||
| } | ||
| }, [propsLayouts, breakpoints, breakpoint, cols, compactType]); | ||
| useEffect(() => { | ||
| if (compactType !== prevCompactTypeRef.current) { | ||
| const newLayout = compact( | ||
| cloneLayout(layout), | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const newLayouts = { | ||
| ...layouts, | ||
| [breakpoint]: newLayout | ||
| }; | ||
| setLayout(newLayout); | ||
| setLayouts(newLayouts); | ||
| onLayoutChange(newLayout, newLayouts); | ||
| prevCompactTypeRef.current = compactType; | ||
| } | ||
| }, [ | ||
| compactType, | ||
| layout, | ||
| cols, | ||
| allowOverlap, | ||
| layouts, | ||
| breakpoint, | ||
| onLayoutChange | ||
| ]); | ||
| useEffect(() => { | ||
| const widthChanged = width !== prevWidthRef.current; | ||
| const breakpointPropChanged = propBreakpoint !== prevBreakpointRef.current; | ||
| const breakpointsChanged = !deepEqual( | ||
| breakpoints, | ||
| prevBreakpointsRef.current | ||
| ); | ||
| const colsChanged = !deepEqual(colsConfig, prevColsRef.current); | ||
| if (widthChanged || breakpointPropChanged || breakpointsChanged || colsChanged) { | ||
| const newBreakpoint = propBreakpoint ?? getBreakpointFromWidth(breakpoints, width); | ||
| const newCols = getColsFromBreakpoint(newBreakpoint, colsConfig); | ||
| const lastBreakpoint = breakpoint; | ||
| if (lastBreakpoint !== newBreakpoint || breakpointsChanged || colsChanged) { | ||
| const newLayouts = { ...layouts }; | ||
| if (!newLayouts[lastBreakpoint]) { | ||
| newLayouts[lastBreakpoint] = cloneLayout(layout); | ||
| } | ||
| let newLayout = findOrGenerateResponsiveLayout( | ||
| newLayouts, | ||
| breakpoints, | ||
| newBreakpoint, | ||
| lastBreakpoint, | ||
| newCols, | ||
| compactType | ||
| ); | ||
| newLayout = synchronizeLayoutWithChildren2( | ||
| newLayout, | ||
| children, | ||
| newCols, | ||
| compactType, | ||
| allowOverlap | ||
| ); | ||
| newLayouts[newBreakpoint] = newLayout; | ||
| setBreakpoint(newBreakpoint); | ||
| setCols(newCols); | ||
| setLayout(newLayout); | ||
| setLayouts(newLayouts); | ||
| onBreakpointChange(newBreakpoint, newCols); | ||
| onLayoutChange(newLayout, newLayouts); | ||
| } | ||
| const currentMargin2 = getIndentationValue( | ||
| propMargin, | ||
| newBreakpoint | ||
| ); | ||
| const currentPadding = propContainerPadding ? getIndentationValue( | ||
| propContainerPadding, | ||
| newBreakpoint | ||
| ) : null; | ||
| onWidthChange(width, currentMargin2, newCols, currentPadding); | ||
| prevWidthRef.current = width; | ||
| prevBreakpointRef.current = propBreakpoint; | ||
| prevBreakpointsRef.current = breakpoints; | ||
| prevColsRef.current = colsConfig; | ||
| } | ||
| }, [ | ||
| width, | ||
| propBreakpoint, | ||
| breakpoints, | ||
| colsConfig, | ||
| breakpoint, | ||
| cols, | ||
| layout, | ||
| layouts, | ||
| children, | ||
| compactType, | ||
| allowOverlap, | ||
| propMargin, | ||
| propContainerPadding, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange | ||
| ]); | ||
| const handleLayoutChange = useCallback( | ||
| (newLayout) => { | ||
| const newLayouts = { | ||
| ...layouts, | ||
| [breakpoint]: newLayout | ||
| }; | ||
| setLayout(newLayout); | ||
| setLayouts(newLayouts); | ||
| onLayoutChange(newLayout, newLayouts); | ||
| }, | ||
| [layouts, breakpoint, onLayoutChange] | ||
| ); | ||
| const currentMargin = useMemo(() => { | ||
| return getIndentationValue( | ||
| propMargin, | ||
| breakpoint | ||
| ); | ||
| }, [propMargin, breakpoint]); | ||
| const currentContainerPadding = useMemo(() => { | ||
| if (propContainerPadding === null) return null; | ||
| return getIndentationValue( | ||
| propContainerPadding, | ||
| breakpoint | ||
| ); | ||
| }, [propContainerPadding, breakpoint]); | ||
| const gridConfig = useMemo( | ||
| () => ({ | ||
| cols, | ||
| rowHeight, | ||
| maxRows, | ||
| margin: currentMargin, | ||
| containerPadding: currentContainerPadding | ||
| }), | ||
| [cols, rowHeight, maxRows, currentMargin, currentContainerPadding] | ||
| ); | ||
| return /* @__PURE__ */ jsx( | ||
| GridLayout, | ||
| { | ||
| ...restProps, | ||
| width, | ||
| gridConfig, | ||
| compactor, | ||
| onLayoutChange: handleLayoutChange, | ||
| layout, | ||
| children | ||
| } | ||
| ); | ||
| } | ||
| export { GridItem, GridLayout, ResponsiveGridLayout }; | ||
| //# sourceMappingURL=chunk-R35HZZTA.mjs.map | ||
| //# sourceMappingURL=chunk-R35HZZTA.mjs.map |
Sorry, the diff of this file is too big to display
| import { getCompactor, correctBounds, cloneLayout, compact, getLayoutItem, cloneLayoutItem, moveElement, bottom, sortBreakpoints, getBreakpointFromWidth, getColsFromBreakpoint, findOrGenerateResponsiveLayout } from './chunk-4HNUMWQK.mjs'; | ||
| import { useState, useRef, useCallback, useEffect, useMemo } from 'react'; | ||
| import { deepEqual } from 'fast-equals'; | ||
| function useContainerWidth(options = {}) { | ||
| const { measureBeforeMount = false, initialWidth = 1280 } = options; | ||
| const [width, setWidth] = useState(initialWidth); | ||
| const [mounted, setMounted] = useState(!measureBeforeMount); | ||
| const containerRef = useRef(null); | ||
| const observerRef = useRef(null); | ||
| const measureWidth = useCallback(() => { | ||
| const node = containerRef.current; | ||
| if (node) { | ||
| const newWidth = node.offsetWidth; | ||
| setWidth(newWidth); | ||
| if (!mounted) { | ||
| setMounted(true); | ||
| } | ||
| } | ||
| }, [mounted]); | ||
| useEffect(() => { | ||
| const node = containerRef.current; | ||
| if (!node) return; | ||
| measureWidth(); | ||
| if (typeof ResizeObserver !== "undefined") { | ||
| observerRef.current = new ResizeObserver((entries) => { | ||
| const entry = entries[0]; | ||
| if (entry) { | ||
| const newWidth = entry.contentRect.width; | ||
| setWidth(newWidth); | ||
| } | ||
| }); | ||
| observerRef.current.observe(node); | ||
| } | ||
| return () => { | ||
| if (observerRef.current) { | ||
| observerRef.current.disconnect(); | ||
| observerRef.current = null; | ||
| } | ||
| }; | ||
| }, [measureWidth]); | ||
| return { | ||
| width, | ||
| mounted, | ||
| containerRef, | ||
| measureWidth | ||
| }; | ||
| } | ||
| function useGridLayout(options) { | ||
| const { | ||
| layout: propsLayout, | ||
| cols, | ||
| compactType = "vertical", | ||
| allowOverlap = false, | ||
| preventCollision = false, | ||
| onLayoutChange | ||
| } = options; | ||
| const compactor = useMemo( | ||
| () => getCompactor(compactType, allowOverlap), | ||
| [compactType, allowOverlap] | ||
| ); | ||
| const isDraggingRef = useRef(false); | ||
| const [layout, setLayoutState] = useState(() => { | ||
| const corrected = correctBounds(cloneLayout(propsLayout), { cols }); | ||
| return compact(corrected, compactType, cols, allowOverlap); | ||
| }); | ||
| const [dragState, setDragState] = useState({ | ||
| activeDrag: null, | ||
| oldDragItem: null, | ||
| oldLayout: null | ||
| }); | ||
| const [resizeState, setResizeState] = useState({ | ||
| resizing: false, | ||
| oldResizeItem: null, | ||
| oldLayout: null | ||
| }); | ||
| const [dropState, setDropState] = useState({ | ||
| droppingDOMNode: null, | ||
| droppingPosition: null | ||
| }); | ||
| const prevLayoutRef = useRef(layout); | ||
| const setLayout = useCallback( | ||
| (newLayout) => { | ||
| const corrected = correctBounds(cloneLayout(newLayout), { cols }); | ||
| const compacted = compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [cols, compactType, allowOverlap] | ||
| ); | ||
| useEffect(() => { | ||
| if (isDraggingRef.current) return; | ||
| if (!deepEqual(propsLayout, prevLayoutRef.current)) { | ||
| setLayout(propsLayout); | ||
| } | ||
| }, [propsLayout, setLayout]); | ||
| useEffect(() => { | ||
| if (!deepEqual(layout, prevLayoutRef.current)) { | ||
| prevLayoutRef.current = layout; | ||
| onLayoutChange?.(layout); | ||
| } | ||
| }, [layout, onLayoutChange]); | ||
| const onDragStart = useCallback( | ||
| (itemId, x, y) => { | ||
| const item = getLayoutItem(layout, itemId); | ||
| if (!item) return null; | ||
| isDraggingRef.current = true; | ||
| const placeholder = { | ||
| ...cloneLayoutItem(item), | ||
| x, | ||
| y, | ||
| static: false, | ||
| moved: false | ||
| }; | ||
| setDragState({ | ||
| activeDrag: placeholder, | ||
| oldDragItem: cloneLayoutItem(item), | ||
| oldLayout: cloneLayout(layout) | ||
| }); | ||
| return placeholder; | ||
| }, | ||
| [layout] | ||
| ); | ||
| const onDrag = useCallback( | ||
| (itemId, x, y) => { | ||
| const item = getLayoutItem(layout, itemId); | ||
| if (!item) return; | ||
| setDragState((prev) => ({ | ||
| ...prev, | ||
| activeDrag: prev.activeDrag ? { ...prev.activeDrag, x, y } : null | ||
| })); | ||
| const newLayout = moveElement( | ||
| layout, | ||
| item, | ||
| x, | ||
| y, | ||
| true, | ||
| // isUserAction | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const compacted = allowOverlap ? newLayout : compact(newLayout, compactType, cols); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [layout, cols, compactType, preventCollision, allowOverlap] | ||
| ); | ||
| const onDragStop = useCallback( | ||
| (itemId, x, y) => { | ||
| const item = getLayoutItem(layout, itemId); | ||
| if (!item) return; | ||
| const newLayout = moveElement( | ||
| layout, | ||
| item, | ||
| x, | ||
| y, | ||
| true, | ||
| preventCollision, | ||
| compactType, | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| const compacted = compact(newLayout, compactType, cols, allowOverlap); | ||
| isDraggingRef.current = false; | ||
| setDragState({ | ||
| activeDrag: null, | ||
| oldDragItem: null, | ||
| oldLayout: null | ||
| }); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [layout, cols, compactType, preventCollision, allowOverlap] | ||
| ); | ||
| const onResizeStart = useCallback( | ||
| (itemId) => { | ||
| const item = getLayoutItem(layout, itemId); | ||
| if (!item) return null; | ||
| setResizeState({ | ||
| resizing: true, | ||
| oldResizeItem: cloneLayoutItem(item), | ||
| oldLayout: cloneLayout(layout) | ||
| }); | ||
| return item; | ||
| }, | ||
| [layout] | ||
| ); | ||
| const onResize = useCallback( | ||
| (itemId, w, h, x, y) => { | ||
| const newLayout = layout.map((item) => { | ||
| if (item.i === itemId) { | ||
| const updated = { | ||
| ...item, | ||
| w, | ||
| h | ||
| }; | ||
| if (x !== void 0) updated.x = x; | ||
| if (y !== void 0) updated.y = y; | ||
| return updated; | ||
| } | ||
| return item; | ||
| }); | ||
| const corrected = correctBounds(newLayout, { cols }); | ||
| const compacted = compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| }, | ||
| [layout, cols, compactType, allowOverlap] | ||
| ); | ||
| const onResizeStop = useCallback( | ||
| (itemId, w, h) => { | ||
| onResize(itemId, w, h); | ||
| setResizeState({ | ||
| resizing: false, | ||
| oldResizeItem: null, | ||
| oldLayout: null | ||
| }); | ||
| }, | ||
| [onResize] | ||
| ); | ||
| const onDropDragOver = useCallback( | ||
| (droppingItem, position) => { | ||
| const existingItem = getLayoutItem(layout, droppingItem.i); | ||
| if (!existingItem) { | ||
| const newLayout = [...layout, droppingItem]; | ||
| const corrected = correctBounds(newLayout, { cols }); | ||
| const compacted = compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| } | ||
| setDropState({ | ||
| droppingDOMNode: null, | ||
| // Will be set by component | ||
| droppingPosition: position | ||
| }); | ||
| }, | ||
| [layout, cols, compactType, allowOverlap] | ||
| ); | ||
| const onDropDragLeave = useCallback(() => { | ||
| const newLayout = layout.filter((item) => item.i !== "__dropping-elem__"); | ||
| setLayoutState(newLayout); | ||
| setDropState({ | ||
| droppingDOMNode: null, | ||
| droppingPosition: null | ||
| }); | ||
| }, [layout]); | ||
| const onDrop = useCallback( | ||
| (droppingItem) => { | ||
| const newLayout = layout.map((item) => { | ||
| if (item.i === "__dropping-elem__") { | ||
| return { | ||
| ...item, | ||
| i: droppingItem.i, | ||
| static: false | ||
| }; | ||
| } | ||
| return item; | ||
| }); | ||
| const corrected = correctBounds(newLayout, { cols }); | ||
| const compacted = compact(corrected, compactType, cols, allowOverlap); | ||
| setLayoutState(compacted); | ||
| setDropState({ | ||
| droppingDOMNode: null, | ||
| droppingPosition: null | ||
| }); | ||
| }, | ||
| [layout, cols, compactType, allowOverlap] | ||
| ); | ||
| const containerHeight = useMemo(() => bottom(layout), [layout]); | ||
| const isInteracting = dragState.activeDrag !== null || resizeState.resizing || dropState.droppingPosition !== null; | ||
| return { | ||
| layout, | ||
| setLayout, | ||
| dragState, | ||
| resizeState, | ||
| dropState, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDropDragOver, | ||
| onDropDragLeave, | ||
| onDrop, | ||
| containerHeight, | ||
| isInteracting, | ||
| compactor | ||
| }; | ||
| } | ||
| var DEFAULT_BREAKPOINTS = { | ||
| lg: 1200, | ||
| md: 996, | ||
| sm: 768, | ||
| xs: 480, | ||
| xxs: 0 | ||
| }; | ||
| var DEFAULT_COLS = { | ||
| lg: 12, | ||
| md: 10, | ||
| sm: 6, | ||
| xs: 4, | ||
| xxs: 2 | ||
| }; | ||
| function useResponsiveLayout(options) { | ||
| const { | ||
| width, | ||
| breakpoints = DEFAULT_BREAKPOINTS, | ||
| cols: colsConfig = DEFAULT_COLS, | ||
| layouts: propsLayouts = {}, | ||
| compactType = "vertical", | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange | ||
| } = options; | ||
| const sortedBreakpoints = useMemo( | ||
| () => sortBreakpoints(breakpoints), | ||
| [breakpoints] | ||
| ); | ||
| const initialBreakpoint = useMemo( | ||
| () => getBreakpointFromWidth(breakpoints, width), | ||
| // Only calculate on mount, not on width changes | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| [] | ||
| ); | ||
| const initialCols = useMemo( | ||
| () => getColsFromBreakpoint(initialBreakpoint, colsConfig), | ||
| [initialBreakpoint, colsConfig] | ||
| ); | ||
| const [breakpoint, setBreakpoint] = useState(initialBreakpoint); | ||
| const [cols, setCols] = useState(initialCols); | ||
| const [layouts, setLayoutsState] = useState(() => { | ||
| const cloned = {}; | ||
| for (const bp of sortedBreakpoints) { | ||
| const layout2 = propsLayouts[bp]; | ||
| if (layout2) { | ||
| cloned[bp] = cloneLayout(layout2); | ||
| } | ||
| } | ||
| return cloned; | ||
| }); | ||
| const prevWidthRef = useRef(width); | ||
| const prevBreakpointRef = useRef(breakpoint); | ||
| const prevLayoutsRef = useRef(layouts); | ||
| const layout = useMemo(() => { | ||
| return findOrGenerateResponsiveLayout( | ||
| layouts, | ||
| breakpoints, | ||
| breakpoint, | ||
| prevBreakpointRef.current, | ||
| cols, | ||
| compactType | ||
| ); | ||
| }, [layouts, breakpoints, breakpoint, cols, compactType]); | ||
| const setLayoutForBreakpoint = useCallback((bp, newLayout) => { | ||
| setLayoutsState((prev) => ({ | ||
| ...prev, | ||
| [bp]: cloneLayout(newLayout) | ||
| })); | ||
| }, []); | ||
| const setLayouts = useCallback((newLayouts) => { | ||
| const cloned = {}; | ||
| for (const bp of Object.keys(newLayouts)) { | ||
| const layoutForBp = newLayouts[bp]; | ||
| if (layoutForBp) { | ||
| cloned[bp] = cloneLayout(layoutForBp); | ||
| } | ||
| } | ||
| setLayoutsState(cloned); | ||
| }, []); | ||
| useEffect(() => { | ||
| if (prevWidthRef.current === width) return; | ||
| prevWidthRef.current = width; | ||
| const newBreakpoint = getBreakpointFromWidth(breakpoints, width); | ||
| const newCols = getColsFromBreakpoint(newBreakpoint, colsConfig); | ||
| onWidthChange?.(width, [10, 10], newCols, null); | ||
| if (newBreakpoint !== breakpoint) { | ||
| const newLayout = findOrGenerateResponsiveLayout( | ||
| layouts, | ||
| breakpoints, | ||
| newBreakpoint, | ||
| breakpoint, | ||
| newCols, | ||
| compactType | ||
| ); | ||
| const updatedLayouts = { | ||
| ...layouts, | ||
| [newBreakpoint]: newLayout | ||
| }; | ||
| setLayoutsState(updatedLayouts); | ||
| setBreakpoint(newBreakpoint); | ||
| setCols(newCols); | ||
| onBreakpointChange?.(newBreakpoint, newCols); | ||
| prevBreakpointRef.current = newBreakpoint; | ||
| } | ||
| }, [ | ||
| width, | ||
| breakpoints, | ||
| colsConfig, | ||
| breakpoint, | ||
| layouts, | ||
| compactType, | ||
| onBreakpointChange, | ||
| onWidthChange | ||
| ]); | ||
| useEffect(() => { | ||
| if (!deepEqual(propsLayouts, prevLayoutsRef.current)) { | ||
| setLayouts(propsLayouts); | ||
| prevLayoutsRef.current = propsLayouts; | ||
| } | ||
| }, [propsLayouts, setLayouts]); | ||
| useEffect(() => { | ||
| if (!deepEqual(layouts, prevLayoutsRef.current)) { | ||
| prevLayoutsRef.current = layouts; | ||
| onLayoutChange?.(layout, layouts); | ||
| } | ||
| }, [layout, layouts, onLayoutChange]); | ||
| return { | ||
| layout, | ||
| layouts, | ||
| breakpoint, | ||
| cols, | ||
| setLayoutForBreakpoint, | ||
| setLayouts, | ||
| sortedBreakpoints | ||
| }; | ||
| } | ||
| export { DEFAULT_BREAKPOINTS, DEFAULT_COLS, useContainerWidth, useGridLayout, useResponsiveLayout }; | ||
| //# sourceMappingURL=chunk-ZCXE6SR5.mjs.map | ||
| //# sourceMappingURL=chunk-ZCXE6SR5.mjs.map |
| {"version":3,"sources":["../src/react/hooks/useContainerWidth.ts","../src/react/hooks/useGridLayout.ts","../src/react/hooks/useResponsiveLayout.ts"],"names":["useRef","useState","useCallback","useEffect","useMemo","layout","deepEqual"],"mappings":";;;;AAsEO,SAAS,iBAAA,CACd,OAAA,GAAoC,EAAC,EACZ;AACzB,EAAA,MAAM,EAAE,kBAAA,GAAqB,KAAA,EAAO,YAAA,GAAe,MAAK,GAAI,OAAA;AAE5D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,YAAY,CAAA;AAC/C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAS,CAAC,kBAAkB,CAAA;AAC1D,EAAA,MAAM,YAAA,GAAe,OAA8B,IAAI,CAAA;AACvD,EAAA,MAAM,WAAA,GAAc,OAA8B,IAAI,CAAA;AAEtD,EAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,IAAA,MAAM,OAAO,YAAA,CAAa,OAAA;AAC1B,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,MAAM,WAAW,IAAA,CAAK,WAAA;AACtB,MAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,UAAA,CAAW,IAAI,CAAA;AAAA,MACjB;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,OAAO,YAAA,CAAa,OAAA;AAC1B,IAAA,IAAI,CAAC,IAAA,EAAM;AAGX,IAAA,YAAA,EAAa;AAGb,IAAA,IAAI,OAAO,mBAAmB,WAAA,EAAa;AACzC,MAAA,WAAA,CAAY,OAAA,GAAU,IAAI,cAAA,CAAe,CAAA,OAAA,KAAW;AAClD,QAAA,MAAM,KAAA,GAAQ,QAAQ,CAAC,CAAA;AACvB,QAAA,IAAI,KAAA,EAAO;AAET,UAAA,MAAM,QAAA,GAAW,MAAM,WAAA,CAAY,KAAA;AACnC,UAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,QACnB;AAAA,MACF,CAAC,CAAA;AAED,MAAA,WAAA,CAAY,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAAA,IAClC;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,YAAY,OAAA,EAAS;AACvB,QAAA,WAAA,CAAY,QAAQ,UAAA,EAAW;AAC/B,QAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AAAA,MACxB;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF;AC+BO,SAAS,cACd,OAAA,EACqB;AACrB,EAAA,MAAM;AAAA,IACJ,MAAA,EAAQ,WAAA;AAAA,IACR,IAAA;AAAA,IACA,WAAA,GAAc,UAAA;AAAA,IACd,YAAA,GAAe,KAAA;AAAA,IACf,gBAAA,GAAmB,KAAA;AAAA,IACnB;AAAA,GACF,GAAI,OAAA;AAGJ,EAAA,MAAM,SAAA,GAAY,OAAA;AAAA,IAChB,MAAM,YAAA,CAAa,WAAA,EAAa,YAAY,CAAA;AAAA,IAC5C,CAAC,aAAa,YAAY;AAAA,GAC5B;AAGA,EAAA,MAAM,aAAA,GAAgBA,OAAO,KAAK,CAAA;AAGlC,EAAA,MAAM,CAAC,MAAA,EAAQ,cAAc,CAAA,GAAIC,SAAiB,MAAM;AACtD,IAAA,MAAM,YAAY,aAAA,CAAc,WAAA,CAAY,WAAW,CAAA,EAAG,EAAE,MAAM,CAAA;AAClE,IAAA,OAAO,OAAA,CAAQ,SAAA,EAAW,WAAA,EAAa,IAAA,EAAM,YAAY,CAAA;AAAA,EAC3D,CAAC,CAAA;AAGD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,QAAAA,CAAoB;AAAA,IACpD,UAAA,EAAY,IAAA;AAAA,IACZ,WAAA,EAAa,IAAA;AAAA,IACb,SAAA,EAAW;AAAA,GACZ,CAAA;AAGD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIA,QAAAA,CAAsB;AAAA,IAC1D,QAAA,EAAU,KAAA;AAAA,IACV,aAAA,EAAe,IAAA;AAAA,IACf,SAAA,EAAW;AAAA,GACZ,CAAA;AAGD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,QAAAA,CAAoB;AAAA,IACpD,eAAA,EAAiB,IAAA;AAAA,IACjB,gBAAA,EAAkB;AAAA,GACnB,CAAA;AAGD,EAAA,MAAM,aAAA,GAAgBD,OAAe,MAAM,CAAA;AAG3C,EAAA,MAAM,SAAA,GAAYE,WAAAA;AAAA,IAChB,CAAC,SAAA,KAAsB;AACrB,MAAA,MAAM,YAAY,aAAA,CAAc,WAAA,CAAY,SAAS,CAAA,EAAG,EAAE,MAAM,CAAA;AAChE,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,EAAW,WAAA,EAAa,MAAM,YAAY,CAAA;AACpE,MAAA,cAAA,CAAe,SAAS,CAAA;AAAA,IAC1B,CAAA;AAAA,IACA,CAAC,IAAA,EAAM,WAAA,EAAa,YAAY;AAAA,GAClC;AAGA,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,cAAc,OAAA,EAAS;AAE3B,IAAA,IAAI,CAAC,SAAA,CAAU,WAAA,EAAa,aAAA,CAAc,OAAO,CAAA,EAAG;AAClD,MAAA,SAAA,CAAU,WAAW,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,CAAC,WAAA,EAAa,SAAS,CAAC,CAAA;AAG3B,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,CAAU,MAAA,EAAQ,aAAA,CAAc,OAAO,CAAA,EAAG;AAC7C,MAAA,aAAA,CAAc,OAAA,GAAU,MAAA;AACxB,MAAA,cAAA,GAAiB,MAAM,CAAA;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,cAAc,CAAC,CAAA;AAM3B,EAAA,MAAM,WAAA,GAAcD,WAAAA;AAAA,IAClB,CAAC,MAAA,EAAgB,CAAA,EAAW,CAAA,KAAiC;AAC3D,MAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AACzC,MAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,MAAA,aAAA,CAAc,OAAA,GAAU,IAAA;AAExB,MAAA,MAAM,WAAA,GAA0B;AAAA,QAC9B,GAAG,gBAAgB,IAAI,CAAA;AAAA,QACvB,CAAA;AAAA,QACA,CAAA;AAAA,QACA,MAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EAAO;AAAA,OACT;AAEA,MAAA,YAAA,CAAa;AAAA,QACX,UAAA,EAAY,WAAA;AAAA,QACZ,WAAA,EAAa,gBAAgB,IAAI,CAAA;AAAA,QACjC,SAAA,EAAW,YAAY,MAAM;AAAA,OAC9B,CAAA;AAED,MAAA,OAAO,WAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,MAAA,GAASA,WAAAA;AAAA,IACb,CAAC,MAAA,EAAgB,CAAA,EAAW,CAAA,KAAc;AACxC,MAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AACzC,MAAA,IAAI,CAAC,IAAA,EAAM;AAGX,MAAA,YAAA,CAAa,CAAA,IAAA,MAAS;AAAA,QACpB,GAAG,IAAA;AAAA,QACH,UAAA,EAAY,KAAK,UAAA,GAAa,EAAE,GAAG,IAAA,CAAK,UAAA,EAAY,CAAA,EAAG,CAAA,EAAE,GAAI;AAAA,OAC/D,CAAE,CAAA;AAGF,MAAA,MAAM,SAAA,GAAY,WAAA;AAAA,QAChB,MAAA;AAAA,QACA,IAAA;AAAA,QACA,CAAA;AAAA,QACA,CAAA;AAAA,QACA,IAAA;AAAA;AAAA,QACA,gBAAA;AAAA,QACA,WAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,MAAM,YAAY,YAAA,GACd,SAAA,GACA,OAAA,CAAQ,SAAA,EAAW,aAAa,IAAI,CAAA;AAExC,MAAA,cAAA,CAAe,SAAS,CAAA;AAAA,IAC1B,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,WAAA,EAAa,kBAAkB,YAAY;AAAA,GAC5D;AAEA,EAAA,MAAM,UAAA,GAAaA,WAAAA;AAAA,IACjB,CAAC,MAAA,EAAgB,CAAA,EAAW,CAAA,KAAc;AACxC,MAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AACzC,MAAA,IAAI,CAAC,IAAA,EAAM;AAGX,MAAA,MAAM,SAAA,GAAY,WAAA;AAAA,QAChB,MAAA;AAAA,QACA,IAAA;AAAA,QACA,CAAA;AAAA,QACA,CAAA;AAAA,QACA,IAAA;AAAA,QACA,gBAAA;AAAA,QACA,WAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,EAAW,WAAA,EAAa,MAAM,YAAY,CAAA;AAEpE,MAAA,aAAA,CAAc,OAAA,GAAU,KAAA;AAExB,MAAA,YAAA,CAAa;AAAA,QACX,UAAA,EAAY,IAAA;AAAA,QACZ,WAAA,EAAa,IAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ,CAAA;AAED,MAAA,cAAA,CAAe,SAAS,CAAA;AAAA,IAC1B,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,WAAA,EAAa,kBAAkB,YAAY;AAAA,GAC5D;AAMA,EAAA,MAAM,aAAA,GAAgBA,WAAAA;AAAA,IACpB,CAAC,MAAA,KAAsC;AACrC,MAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AACzC,MAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,MAAA,cAAA,CAAe;AAAA,QACb,QAAA,EAAU,IAAA;AAAA,QACV,aAAA,EAAe,gBAAgB,IAAI,CAAA;AAAA,QACnC,SAAA,EAAW,YAAY,MAAM;AAAA,OAC9B,CAAA;AAED,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,QAAA,GAAWA,WAAAA;AAAA,IACf,CAAC,MAAA,EAAgB,CAAA,EAAW,CAAA,EAAW,GAAY,CAAA,KAAe;AAChE,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,CAAA,IAAA,KAAQ;AACnC,QAAA,IAAI,IAAA,CAAK,MAAM,MAAA,EAAQ;AACrB,UAAA,MAAM,OAAA,GAAsB;AAAA,YAC1B,GAAG,IAAA;AAAA,YACH,CAAA;AAAA,YACA;AAAA,WACF;AACA,UAAA,IAAI,CAAA,KAAM,MAAA,EAAY,OAAA,CAAgC,CAAA,GAAI,CAAA;AAC1D,UAAA,IAAI,CAAA,KAAM,MAAA,EAAY,OAAA,CAAgC,CAAA,GAAI,CAAA;AAC1D,UAAA,OAAO,OAAA;AAAA,QACT;AACA,QAAA,OAAO,IAAA;AAAA,MACT,CAAC,CAAA;AAGD,MAAA,MAAM,SAAA,GAAY,aAAA,CAAc,SAAA,EAAW,EAAE,MAAM,CAAA;AACnD,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,EAAW,WAAA,EAAa,MAAM,YAAY,CAAA;AAEpE,MAAA,cAAA,CAAe,SAAS,CAAA;AAAA,IAC1B,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,WAAA,EAAa,YAAY;AAAA,GAC1C;AAEA,EAAA,MAAM,YAAA,GAAeA,WAAAA;AAAA,IACnB,CAAC,MAAA,EAAgB,CAAA,EAAW,CAAA,KAAc;AAExC,MAAA,QAAA,CAAS,MAAA,EAAQ,GAAG,CAAC,CAAA;AAErB,MAAA,cAAA,CAAe;AAAA,QACb,QAAA,EAAU,KAAA;AAAA,QACV,aAAA,EAAe,IAAA;AAAA,QACf,SAAA,EAAW;AAAA,OACZ,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAMA,EAAA,MAAM,cAAA,GAAiBA,WAAAA;AAAA,IACrB,CAAC,cAA0B,QAAA,KAA+B;AAExD,MAAA,MAAM,YAAA,GAAe,aAAA,CAAc,MAAA,EAAQ,YAAA,CAAa,CAAC,CAAA;AAEzD,MAAA,IAAI,CAAC,YAAA,EAAc;AAEjB,QAAA,MAAM,SAAA,GAAY,CAAC,GAAG,MAAA,EAAQ,YAAY,CAAA;AAC1C,QAAA,MAAM,SAAA,GAAY,aAAA,CAAc,SAAA,EAAW,EAAE,MAAM,CAAA;AACnD,QAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,EAAW,WAAA,EAAa,MAAM,YAAY,CAAA;AACpE,QAAA,cAAA,CAAe,SAAS,CAAA;AAAA,MAC1B;AAEA,MAAA,YAAA,CAAa;AAAA,QACX,eAAA,EAAiB,IAAA;AAAA;AAAA,QACjB,gBAAA,EAAkB;AAAA,OACnB,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,WAAA,EAAa,YAAY;AAAA,GAC1C;AAEA,EAAA,MAAM,eAAA,GAAkBA,YAAY,MAAM;AAExC,IAAA,MAAM,YAAY,MAAA,CAAO,MAAA,CAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAM,mBAAmB,CAAA;AACtE,IAAA,cAAA,CAAe,SAAS,CAAA;AAExB,IAAA,YAAA,CAAa;AAAA,MACX,eAAA,EAAiB,IAAA;AAAA,MACjB,gBAAA,EAAkB;AAAA,KACnB,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,MAAM,MAAA,GAASA,WAAAA;AAAA,IACb,CAAC,YAAA,KAA6B;AAE5B,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,CAAA,IAAA,KAAQ;AACnC,QAAA,IAAI,IAAA,CAAK,MAAM,mBAAA,EAAqB;AAClC,UAAA,OAAO;AAAA,YACL,GAAG,IAAA;AAAA,YACH,GAAG,YAAA,CAAa,CAAA;AAAA,YAChB,MAAA,EAAQ;AAAA,WACV;AAAA,QACF;AACA,QAAA,OAAO,IAAA;AAAA,MACT,CAAC,CAAA;AAED,MAAA,MAAM,SAAA,GAAY,aAAA,CAAc,SAAA,EAAW,EAAE,MAAM,CAAA;AACnD,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,EAAW,WAAA,EAAa,MAAM,YAAY,CAAA;AACpE,MAAA,cAAA,CAAe,SAAS,CAAA;AAExB,MAAA,YAAA,CAAa;AAAA,QACX,eAAA,EAAiB,IAAA;AAAA,QACjB,gBAAA,EAAkB;AAAA,OACnB,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,WAAA,EAAa,YAAY;AAAA,GAC1C;AAMA,EAAA,MAAM,eAAA,GAAkB,QAAQ,MAAM,MAAA,CAAO,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAE9D,EAAA,MAAM,gBACJ,SAAA,CAAU,UAAA,KAAe,QACzB,WAAA,CAAY,QAAA,IACZ,UAAU,gBAAA,KAAqB,IAAA;AAEjC,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF;AACF;ACncO,IAAM,mBAAA,GAAuD;AAAA,EAClE,EAAA,EAAI,IAAA;AAAA,EACJ,EAAA,EAAI,GAAA;AAAA,EACJ,EAAA,EAAI,GAAA;AAAA,EACJ,EAAA,EAAI,GAAA;AAAA,EACJ,GAAA,EAAK;AACP;AAGO,IAAM,YAAA,GAAgD;AAAA,EAC3D,EAAA,EAAI,EAAA;AAAA,EACJ,EAAA,EAAI,EAAA;AAAA,EACJ,EAAA,EAAI,CAAA;AAAA,EACJ,EAAA,EAAI,CAAA;AAAA,EACJ,GAAA,EAAK;AACP;AAkFO,SAAS,oBACd,OAAA,EAC8B;AAC9B,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,WAAA,GAAc,mBAAA;AAAA,IACd,MAAM,UAAA,GAAa,YAAA;AAAA,IACnB,OAAA,EAAS,eAAe,EAAC;AAAA,IACzB,WAAA,GAAc,UAAA;AAAA,IACd,kBAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAGJ,EAAA,MAAM,iBAAA,GAAoBE,OAAAA;AAAA,IACxB,MAAM,gBAAgB,WAAW,CAAA;AAAA,IACjC,CAAC,WAAW;AAAA,GACd;AAGA,EAAA,MAAM,iBAAA,GAAoBA,OAAAA;AAAA,IACxB,MAAM,sBAAA,CAAuB,WAAA,EAAa,KAAK,CAAA;AAAA;AAAA;AAAA,IAG/C;AAAC,GACH;AAEA,EAAA,MAAM,WAAA,GAAcA,OAAAA;AAAA,IAClB,MAAM,qBAAA,CAAsB,iBAAA,EAAmB,UAAU,CAAA;AAAA,IACzD,CAAC,mBAAmB,UAAU;AAAA,GAChC;AAGA,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIH,SAAY,iBAAiB,CAAA;AACjE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIA,SAAiB,WAAW,CAAA;AACpD,EAAA,MAAM,CAAC,OAAA,EAAS,eAAe,CAAA,GAAIA,SAA+B,MAAM;AAEtE,IAAA,MAAM,SAAS,EAAC;AAChB,IAAA,KAAA,MAAW,MAAM,iBAAA,EAAmB;AAClC,MAAA,MAAMI,OAAAA,GAAS,aAAa,EAAE,CAAA;AAC9B,MAAA,IAAIA,OAAAA,EAAQ;AACV,QAAC,MAAA,CAA6B,EAAE,CAAA,GAAI,WAAA,CAAYA,OAAM,CAAA;AAAA,MACxD;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAC,CAAA;AAGD,EAAA,MAAM,YAAA,GAAeL,OAAO,KAAK,CAAA;AACjC,EAAA,MAAM,iBAAA,GAAoBA,OAAO,UAAU,CAAA;AAC3C,EAAA,MAAM,cAAA,GAAiBA,OAAO,OAAO,CAAA;AAGrC,EAAA,MAAM,MAAA,GAASI,QAAQ,MAAM;AAC3B,IAAA,OAAO,8BAAA;AAAA,MACL,OAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,iBAAA,CAAkB,OAAA;AAAA,MAClB,IAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,GAAG,CAAC,OAAA,EAAS,aAAa,UAAA,EAAY,IAAA,EAAM,WAAW,CAAC,CAAA;AAGxD,EAAA,MAAM,sBAAA,GAAyBF,WAAAA,CAAY,CAAC,EAAA,EAAO,SAAA,KAAsB;AACvE,IAAA,eAAA,CAAgB,CAAC,IAAA,MAAgC;AAAA,MAC/C,GAAG,IAAA;AAAA,MACH,CAAC,EAAE,GAAG,WAAA,CAAY,SAAS;AAAA,KAC7B,CAAE,CAAA;AAAA,EACJ,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,UAAA,GAAaA,WAAAA,CAAY,CAAC,UAAA,KAAqC;AACnE,IAAA,MAAM,SAAS,EAAC;AAChB,IAAA,KAAA,MAAW,EAAA,IAAM,MAAA,CAAO,IAAA,CAAK,UAAU,CAAA,EAAU;AAC/C,MAAA,MAAM,WAAA,GAAc,WAAW,EAAE,CAAA;AACjC,MAAA,IAAI,WAAA,EAAa;AACf,QAAC,MAAA,CAA6B,EAAE,CAAA,GAAI,WAAA,CAAY,WAAW,CAAA;AAAA,MAC7D;AAAA,IACF;AACA,IAAA,eAAA,CAAgB,MAAM,CAAA;AAAA,EACxB,CAAA,EAAG,EAAE,CAAA;AAGL,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,YAAA,CAAa,YAAY,KAAA,EAAO;AACpC,IAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AAGvB,IAAA,MAAM,aAAA,GAAgB,sBAAA,CAAuB,WAAA,EAAa,KAAK,CAAA;AAC/D,IAAA,MAAM,OAAA,GAAU,qBAAA,CAAsB,aAAA,EAAe,UAAU,CAAA;AAG/D,IAAA,aAAA,GAAgB,OAAO,CAAC,EAAA,EAAI,EAAE,CAAA,EAAG,SAAS,IAAI,CAAA;AAG9C,IAAA,IAAI,kBAAkB,UAAA,EAAY;AAEhC,MAAA,MAAM,SAAA,GAAY,8BAAA;AAAA,QAChB,OAAA;AAAA,QACA,WAAA;AAAA,QACA,aAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,MAAM,cAAA,GAAuC;AAAA,QAC3C,GAAG,OAAA;AAAA,QACH,CAAC,aAAa,GAAG;AAAA,OACnB;AAEA,MAAA,eAAA,CAAgB,cAAc,CAAA;AAC9B,MAAA,aAAA,CAAc,aAAa,CAAA;AAC3B,MAAA,OAAA,CAAQ,OAAO,CAAA;AAGf,MAAA,kBAAA,GAAqB,eAAe,OAAO,CAAA;AAE3C,MAAA,iBAAA,CAAkB,OAAA,GAAU,aAAA;AAAA,IAC9B;AAAA,EACF,CAAA,EAAG;AAAA,IACD,KAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACD,CAAA;AAGD,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAACG,SAAAA,CAAU,YAAA,EAAc,cAAA,CAAe,OAAO,CAAA,EAAG;AACpD,MAAA,UAAA,CAAW,YAAY,CAAA;AACvB,MAAA,cAAA,CAAe,OAAA,GAAU,YAAA;AAAA,IAC3B;AAAA,EACF,CAAA,EAAG,CAAC,YAAA,EAAc,UAAU,CAAC,CAAA;AAG7B,EAAAH,UAAU,MAAM;AACd,IAAA,IAAI,CAACG,SAAAA,CAAU,OAAA,EAAS,cAAA,CAAe,OAAO,CAAA,EAAG;AAC/C,MAAA,cAAA,CAAe,OAAA,GAAU,OAAA;AACzB,MAAA,cAAA,GAAiB,QAAQ,OAAO,CAAA;AAAA,IAClC;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,cAAc,CAAC,CAAA;AAEpC,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,IAAA;AAAA,IACA,sBAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF","file":"chunk-ZCXE6SR5.mjs","sourcesContent":["/**\n * useContainerWidth hook\n *\n * Observes container width using ResizeObserver and provides\n * reactive width updates for responsive layouts.\n */\n\nimport {\n useState,\n useEffect,\n useRef,\n useCallback,\n type RefObject\n} from \"react\";\n\nexport interface UseContainerWidthOptions {\n /**\n * If true, delays initial render until width is measured.\n * Useful for SSR or when you need accurate initial measurements.\n */\n measureBeforeMount?: boolean;\n\n /**\n * Initial width to use before measurement.\n * Defaults to 1280.\n */\n initialWidth?: number;\n}\n\nexport interface UseContainerWidthResult {\n /**\n * Current container width in pixels.\n */\n width: number;\n\n /**\n * Whether the container has been measured at least once.\n */\n mounted: boolean;\n\n /**\n * Ref to attach to the container element.\n */\n containerRef: RefObject<HTMLDivElement | null>;\n\n /**\n * Manually trigger a width measurement.\n * Useful when the container size might change without a resize event.\n */\n measureWidth: () => void;\n}\n\n/**\n * Hook to observe and track container width.\n *\n * Replaces the WidthProvider HOC with a more composable approach.\n *\n * @example\n * ```tsx\n * function MyGrid() {\n * const { width, containerRef, mounted } = useContainerWidth();\n *\n * return (\n * <div ref={containerRef}>\n * {mounted && <GridLayout width={width} {...props} />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useContainerWidth(\n options: UseContainerWidthOptions = {}\n): UseContainerWidthResult {\n const { measureBeforeMount = false, initialWidth = 1280 } = options;\n\n const [width, setWidth] = useState(initialWidth);\n const [mounted, setMounted] = useState(!measureBeforeMount);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const observerRef = useRef<ResizeObserver | null>(null);\n\n const measureWidth = useCallback(() => {\n const node = containerRef.current;\n if (node) {\n const newWidth = node.offsetWidth;\n setWidth(newWidth);\n if (!mounted) {\n setMounted(true);\n }\n }\n }, [mounted]);\n\n useEffect(() => {\n const node = containerRef.current;\n if (!node) return;\n\n // Initial measurement\n measureWidth();\n\n // Set up ResizeObserver\n if (typeof ResizeObserver !== \"undefined\") {\n observerRef.current = new ResizeObserver(entries => {\n const entry = entries[0];\n if (entry) {\n // Use contentRect.width for consistent measurements\n const newWidth = entry.contentRect.width;\n setWidth(newWidth);\n }\n });\n\n observerRef.current.observe(node);\n }\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n };\n }, [measureWidth]);\n\n return {\n width,\n mounted,\n containerRef,\n measureWidth\n };\n}\n\nexport default useContainerWidth;\n","/**\n * useGridLayout hook\n *\n * Core hook for managing grid layout state, including drag, resize, and drop operations.\n * This extracts the state management logic from ReactGridLayout into a reusable hook.\n */\n\nimport { useState, useCallback, useMemo, useRef, useEffect } from \"react\";\nimport { deepEqual } from \"fast-equals\";\nimport type {\n Layout,\n LayoutItem,\n CompactType,\n DroppingPosition,\n Compactor,\n Mutable\n} from \"../../core/types.js\";\nimport {\n cloneLayout,\n cloneLayoutItem,\n moveElement,\n correctBounds,\n bottom,\n getLayoutItem\n} from \"../../core/layout.js\";\nimport { compact } from \"../../core/compact-compat.js\";\nimport { getCompactor } from \"../../core/compactors.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DragState {\n /** Currently dragging item placeholder */\n activeDrag: LayoutItem | null;\n /** Original item before drag started */\n oldDragItem: LayoutItem | null;\n /** Layout before drag started */\n oldLayout: Layout | null;\n}\n\nexport interface ResizeState {\n /** Whether a resize is in progress */\n resizing: boolean;\n /** Original item before resize started */\n oldResizeItem: LayoutItem | null;\n /** Layout before resize started */\n oldLayout: Layout | null;\n}\n\nexport interface DropState {\n /** DOM node for the dropping placeholder */\n droppingDOMNode: React.ReactElement | null;\n /** Current drop position */\n droppingPosition: DroppingPosition | null;\n}\n\nexport interface UseGridLayoutOptions {\n /** Initial layout */\n layout: Layout;\n /** Number of columns */\n cols: number;\n /** Compaction type: 'vertical', 'horizontal', or null */\n compactType?: CompactType;\n /** Allow items to overlap */\n allowOverlap?: boolean;\n /** Prevent collisions when moving items */\n preventCollision?: boolean;\n /** Called when layout changes */\n onLayoutChange?: (layout: Layout) => void;\n}\n\nexport interface UseGridLayoutResult {\n /** Current layout */\n layout: Layout;\n /** Set layout directly */\n setLayout: (layout: Layout) => void;\n /** Drag state */\n dragState: DragState;\n /** Resize state */\n resizeState: ResizeState;\n /** Drop state */\n dropState: DropState;\n /** Start dragging an item */\n onDragStart: (itemId: string, x: number, y: number) => LayoutItem | null;\n /** Update drag position */\n onDrag: (itemId: string, x: number, y: number) => void;\n /** Stop dragging */\n onDragStop: (itemId: string, x: number, y: number) => void;\n /** Start resizing an item */\n onResizeStart: (itemId: string) => LayoutItem | null;\n /** Update resize dimensions */\n onResize: (\n itemId: string,\n w: number,\n h: number,\n x?: number,\n y?: number\n ) => void;\n /** Stop resizing */\n onResizeStop: (itemId: string, w: number, h: number) => void;\n /** Start dropping (external drag-in) */\n onDropDragOver: (\n droppingItem: LayoutItem,\n position: DroppingPosition\n ) => void;\n /** Update drop position */\n onDropDragLeave: () => void;\n /** Complete drop */\n onDrop: (droppingItem: LayoutItem) => void;\n /** Container height in rows */\n containerHeight: number;\n /** Whether any drag/resize is active */\n isInteracting: boolean;\n /** Get the compactor being used */\n compactor: Compactor;\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for managing grid layout state.\n *\n * Handles all layout state including drag, resize, and drop operations.\n * Uses immutable updates and provides callbacks for all interactions.\n *\n * @example\n * ```tsx\n * function MyGrid() {\n * const {\n * layout,\n * onDragStart,\n * onDrag,\n * onDragStop,\n * containerHeight\n * } = useGridLayout({\n * layout: initialLayout,\n * cols: 12,\n * compactType: 'vertical'\n * });\n *\n * return (\n * <div style={{ height: containerHeight }}>\n * {layout.map(item => (\n * <GridItem\n * key={item.i}\n * {...item}\n * onDragStart={() => onDragStart(item.i, item.x, item.y)}\n * />\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useGridLayout(\n options: UseGridLayoutOptions\n): UseGridLayoutResult {\n const {\n layout: propsLayout,\n cols,\n compactType = \"vertical\",\n allowOverlap = false,\n preventCollision = false,\n onLayoutChange\n } = options;\n\n // Get the appropriate compactor\n const compactor = useMemo(\n () => getCompactor(compactType, allowOverlap),\n [compactType, allowOverlap]\n );\n\n // Track if we're currently dragging to block prop updates\n const isDraggingRef = useRef(false);\n\n // Initialize layout with compaction\n const [layout, setLayoutState] = useState<Layout>(() => {\n const corrected = correctBounds(cloneLayout(propsLayout), { cols });\n return compact(corrected, compactType, cols, allowOverlap);\n });\n\n // Drag state\n const [dragState, setDragState] = useState<DragState>({\n activeDrag: null,\n oldDragItem: null,\n oldLayout: null\n });\n\n // Resize state\n const [resizeState, setResizeState] = useState<ResizeState>({\n resizing: false,\n oldResizeItem: null,\n oldLayout: null\n });\n\n // Drop state\n const [dropState, setDropState] = useState<DropState>({\n droppingDOMNode: null,\n droppingPosition: null\n });\n\n // Track previous layout for change detection\n const prevLayoutRef = useRef<Layout>(layout);\n\n // Set layout with optional compaction\n const setLayout = useCallback(\n (newLayout: Layout) => {\n const corrected = correctBounds(cloneLayout(newLayout), { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n setLayoutState(compacted);\n },\n [cols, compactType, allowOverlap]\n );\n\n // Sync layout from props when not dragging\n useEffect(() => {\n if (isDraggingRef.current) return;\n\n if (!deepEqual(propsLayout, prevLayoutRef.current)) {\n setLayout(propsLayout);\n }\n }, [propsLayout, setLayout]);\n\n // Notify layout changes\n useEffect(() => {\n if (!deepEqual(layout, prevLayoutRef.current)) {\n prevLayoutRef.current = layout;\n onLayoutChange?.(layout);\n }\n }, [layout, onLayoutChange]);\n\n // ============================================================================\n // Drag Handlers\n // ============================================================================\n\n const onDragStart = useCallback(\n (itemId: string, x: number, y: number): LayoutItem | null => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return null;\n\n isDraggingRef.current = true;\n\n const placeholder: LayoutItem = {\n ...cloneLayoutItem(item),\n x,\n y,\n static: false,\n moved: false\n };\n\n setDragState({\n activeDrag: placeholder,\n oldDragItem: cloneLayoutItem(item),\n oldLayout: cloneLayout(layout)\n });\n\n return placeholder;\n },\n [layout]\n );\n\n const onDrag = useCallback(\n (itemId: string, x: number, y: number) => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return;\n\n // Update placeholder position\n setDragState(prev => ({\n ...prev,\n activeDrag: prev.activeDrag ? { ...prev.activeDrag, x, y } : null\n }));\n\n // Move element and update layout\n const newLayout = moveElement(\n layout,\n item,\n x,\n y,\n true, // isUserAction\n preventCollision,\n compactType,\n cols,\n allowOverlap\n );\n\n // Compact layout\n const compacted = allowOverlap\n ? newLayout\n : compact(newLayout, compactType, cols);\n\n setLayoutState(compacted);\n },\n [layout, cols, compactType, preventCollision, allowOverlap]\n );\n\n const onDragStop = useCallback(\n (itemId: string, x: number, y: number) => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return;\n\n // Final move\n const newLayout = moveElement(\n layout,\n item,\n x,\n y,\n true,\n preventCollision,\n compactType,\n cols,\n allowOverlap\n );\n\n // Compact and finalize\n const compacted = compact(newLayout, compactType, cols, allowOverlap);\n\n isDraggingRef.current = false;\n\n setDragState({\n activeDrag: null,\n oldDragItem: null,\n oldLayout: null\n });\n\n setLayoutState(compacted);\n },\n [layout, cols, compactType, preventCollision, allowOverlap]\n );\n\n // ============================================================================\n // Resize Handlers\n // ============================================================================\n\n const onResizeStart = useCallback(\n (itemId: string): LayoutItem | null => {\n const item = getLayoutItem(layout, itemId);\n if (!item) return null;\n\n setResizeState({\n resizing: true,\n oldResizeItem: cloneLayoutItem(item),\n oldLayout: cloneLayout(layout)\n });\n\n return item;\n },\n [layout]\n );\n\n const onResize = useCallback(\n (itemId: string, w: number, h: number, x?: number, y?: number) => {\n const newLayout = layout.map(item => {\n if (item.i === itemId) {\n const updated: LayoutItem = {\n ...item,\n w,\n h\n };\n if (x !== undefined) (updated as Mutable<LayoutItem>).x = x;\n if (y !== undefined) (updated as Mutable<LayoutItem>).y = y;\n return updated;\n }\n return item;\n });\n\n // Correct bounds and compact\n const corrected = correctBounds(newLayout, { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n\n setLayoutState(compacted);\n },\n [layout, cols, compactType, allowOverlap]\n );\n\n const onResizeStop = useCallback(\n (itemId: string, w: number, h: number) => {\n // Apply final resize\n onResize(itemId, w, h);\n\n setResizeState({\n resizing: false,\n oldResizeItem: null,\n oldLayout: null\n });\n },\n [onResize]\n );\n\n // ============================================================================\n // Drop Handlers\n // ============================================================================\n\n const onDropDragOver = useCallback(\n (droppingItem: LayoutItem, position: DroppingPosition) => {\n // Check if item already exists in layout\n const existingItem = getLayoutItem(layout, droppingItem.i);\n\n if (!existingItem) {\n // Add dropping item to layout\n const newLayout = [...layout, droppingItem];\n const corrected = correctBounds(newLayout, { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n setLayoutState(compacted);\n }\n\n setDropState({\n droppingDOMNode: null, // Will be set by component\n droppingPosition: position\n });\n },\n [layout, cols, compactType, allowOverlap]\n );\n\n const onDropDragLeave = useCallback(() => {\n // Remove dropping placeholder from layout\n const newLayout = layout.filter(item => item.i !== \"__dropping-elem__\");\n setLayoutState(newLayout);\n\n setDropState({\n droppingDOMNode: null,\n droppingPosition: null\n });\n }, [layout]);\n\n const onDrop = useCallback(\n (droppingItem: LayoutItem) => {\n // Replace placeholder with actual item\n const newLayout = layout.map(item => {\n if (item.i === \"__dropping-elem__\") {\n return {\n ...item,\n i: droppingItem.i,\n static: false\n };\n }\n return item;\n });\n\n const corrected = correctBounds(newLayout, { cols });\n const compacted = compact(corrected, compactType, cols, allowOverlap);\n setLayoutState(compacted);\n\n setDropState({\n droppingDOMNode: null,\n droppingPosition: null\n });\n },\n [layout, cols, compactType, allowOverlap]\n );\n\n // ============================================================================\n // Computed Values\n // ============================================================================\n\n const containerHeight = useMemo(() => bottom(layout), [layout]);\n\n const isInteracting =\n dragState.activeDrag !== null ||\n resizeState.resizing ||\n dropState.droppingPosition !== null;\n\n return {\n layout,\n setLayout,\n dragState,\n resizeState,\n dropState,\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize,\n onResizeStop,\n onDropDragOver,\n onDropDragLeave,\n onDrop,\n containerHeight,\n isInteracting,\n compactor\n };\n}\n\nexport default useGridLayout;\n","/**\n * useResponsiveLayout hook\n *\n * Manages responsive breakpoints and layout generation for different screen sizes.\n * Extracts state management from ResponsiveReactGridLayout into a reusable hook.\n */\n\nimport { useState, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { deepEqual } from \"fast-equals\";\nimport type {\n Layout,\n Breakpoint,\n Breakpoints,\n ResponsiveLayouts,\n CompactType\n} from \"../../core/types.js\";\nimport { cloneLayout } from \"../../core/layout.js\";\nimport {\n getBreakpointFromWidth,\n getColsFromBreakpoint,\n findOrGenerateResponsiveLayout,\n sortBreakpoints\n} from \"../../core/responsive.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Default breakpoint names */\nexport type DefaultBreakpoints = \"lg\" | \"md\" | \"sm\" | \"xs\" | \"xxs\";\n\n/** Default breakpoint widths */\nexport const DEFAULT_BREAKPOINTS: Breakpoints<DefaultBreakpoints> = {\n lg: 1200,\n md: 996,\n sm: 768,\n xs: 480,\n xxs: 0\n};\n\n/** Default column counts per breakpoint */\nexport const DEFAULT_COLS: Breakpoints<DefaultBreakpoints> = {\n lg: 12,\n md: 10,\n sm: 6,\n xs: 4,\n xxs: 2\n};\n\nexport interface UseResponsiveLayoutOptions<\n B extends Breakpoint = DefaultBreakpoints\n> {\n /** Current container width */\n width: number;\n /** Breakpoint definitions (name → min-width) */\n breakpoints?: Breakpoints<B>;\n /** Column counts per breakpoint */\n cols?: Breakpoints<B>;\n /** Layouts for each breakpoint */\n layouts?: ResponsiveLayouts<B>;\n /** Compaction type */\n compactType?: CompactType;\n /** Called when breakpoint changes */\n onBreakpointChange?: (newBreakpoint: B, cols: number) => void;\n /** Called when layout changes */\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void;\n /** Called when width changes */\n onWidthChange?: (\n width: number,\n margin: readonly [number, number],\n cols: number,\n containerPadding: readonly [number, number] | null\n ) => void;\n}\n\nexport interface UseResponsiveLayoutResult<\n B extends Breakpoint = DefaultBreakpoints\n> {\n /** Current layout for the active breakpoint */\n layout: Layout;\n /** All layouts by breakpoint */\n layouts: ResponsiveLayouts<B>;\n /** Current active breakpoint */\n breakpoint: B;\n /** Column count for the current breakpoint */\n cols: number;\n /** Update layouts for a specific breakpoint */\n setLayoutForBreakpoint: (breakpoint: B, layout: Layout) => void;\n /** Update all layouts */\n setLayouts: (layouts: ResponsiveLayouts<B>) => void;\n /** Sorted array of breakpoint names (smallest to largest) */\n sortedBreakpoints: B[];\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for managing responsive grid layouts.\n *\n * Automatically selects the appropriate layout based on container width\n * and generates layouts for new breakpoints from existing ones.\n *\n * @example\n * ```tsx\n * function MyResponsiveGrid() {\n * const { width, containerRef } = useContainerWidth();\n * const { layout, breakpoint, cols } = useResponsiveLayout({\n * width,\n * layouts: {\n * lg: [...],\n * md: [...],\n * sm: [...]\n * }\n * });\n *\n * return (\n * <div ref={containerRef}>\n * <GridLayout\n * width={width}\n * cols={cols}\n * layout={layout}\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function useResponsiveLayout<B extends Breakpoint = DefaultBreakpoints>(\n options: UseResponsiveLayoutOptions<B>\n): UseResponsiveLayoutResult<B> {\n const {\n width,\n breakpoints = DEFAULT_BREAKPOINTS as unknown as Breakpoints<B>,\n cols: colsConfig = DEFAULT_COLS as unknown as Breakpoints<B>,\n layouts: propsLayouts = {} as ResponsiveLayouts<B>,\n compactType = \"vertical\",\n onBreakpointChange,\n onLayoutChange,\n onWidthChange\n } = options;\n\n // Sorted breakpoints for consistent ordering\n const sortedBreakpoints = useMemo(\n () => sortBreakpoints(breakpoints),\n [breakpoints]\n );\n\n // Calculate initial breakpoint and cols\n const initialBreakpoint = useMemo(\n () => getBreakpointFromWidth(breakpoints, width),\n // Only calculate on mount, not on width changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n const initialCols = useMemo(\n () => getColsFromBreakpoint(initialBreakpoint, colsConfig),\n [initialBreakpoint, colsConfig]\n );\n\n // State\n const [breakpoint, setBreakpoint] = useState<B>(initialBreakpoint);\n const [cols, setCols] = useState<number>(initialCols);\n const [layouts, setLayoutsState] = useState<ResponsiveLayouts<B>>(() => {\n // Clone initial layouts\n const cloned = {} as ResponsiveLayouts<B>;\n for (const bp of sortedBreakpoints) {\n const layout = propsLayouts[bp];\n if (layout) {\n (cloned as Record<B, Layout>)[bp] = cloneLayout(layout);\n }\n }\n return cloned;\n });\n\n // Track previous values for change detection\n const prevWidthRef = useRef(width);\n const prevBreakpointRef = useRef(breakpoint);\n const prevLayoutsRef = useRef(layouts);\n\n // Current layout for the active breakpoint\n const layout = useMemo(() => {\n return findOrGenerateResponsiveLayout(\n layouts,\n breakpoints,\n breakpoint,\n prevBreakpointRef.current,\n cols,\n compactType\n );\n }, [layouts, breakpoints, breakpoint, cols, compactType]);\n\n // Set layout for a specific breakpoint\n const setLayoutForBreakpoint = useCallback((bp: B, newLayout: Layout) => {\n setLayoutsState((prev: ResponsiveLayouts<B>) => ({\n ...prev,\n [bp]: cloneLayout(newLayout)\n }));\n }, []);\n\n // Set all layouts\n const setLayouts = useCallback((newLayouts: ResponsiveLayouts<B>) => {\n const cloned = {} as ResponsiveLayouts<B>;\n for (const bp of Object.keys(newLayouts) as B[]) {\n const layoutForBp = newLayouts[bp];\n if (layoutForBp) {\n (cloned as Record<B, Layout>)[bp] = cloneLayout(layoutForBp);\n }\n }\n setLayoutsState(cloned);\n }, []);\n\n // Handle width changes\n useEffect(() => {\n if (prevWidthRef.current === width) return;\n prevWidthRef.current = width;\n\n // Determine new breakpoint\n const newBreakpoint = getBreakpointFromWidth(breakpoints, width);\n const newCols = getColsFromBreakpoint(newBreakpoint, colsConfig);\n\n // Notify width change\n onWidthChange?.(width, [10, 10], newCols, null);\n\n // Check if breakpoint changed\n if (newBreakpoint !== breakpoint) {\n // Generate layout for new breakpoint\n const newLayout = findOrGenerateResponsiveLayout(\n layouts,\n breakpoints,\n newBreakpoint,\n breakpoint,\n newCols,\n compactType\n );\n\n // Update layouts with the new breakpoint layout\n const updatedLayouts: ResponsiveLayouts<B> = {\n ...layouts,\n [newBreakpoint]: newLayout\n };\n\n setLayoutsState(updatedLayouts);\n setBreakpoint(newBreakpoint);\n setCols(newCols);\n\n // Notify breakpoint change\n onBreakpointChange?.(newBreakpoint, newCols);\n\n prevBreakpointRef.current = newBreakpoint;\n }\n }, [\n width,\n breakpoints,\n colsConfig,\n breakpoint,\n layouts,\n compactType,\n onBreakpointChange,\n onWidthChange\n ]);\n\n // Sync with prop layouts when they change\n useEffect(() => {\n if (!deepEqual(propsLayouts, prevLayoutsRef.current)) {\n setLayouts(propsLayouts);\n prevLayoutsRef.current = propsLayouts;\n }\n }, [propsLayouts, setLayouts]);\n\n // Notify layout changes\n useEffect(() => {\n if (!deepEqual(layouts, prevLayoutsRef.current)) {\n prevLayoutsRef.current = layouts;\n onLayoutChange?.(layout, layouts);\n }\n }, [layout, layouts, onLayoutChange]);\n\n return {\n layout,\n layouts,\n breakpoint,\n cols,\n setLayoutForBreakpoint,\n setLayouts,\n sortedBreakpoints\n };\n}\n\nexport default useResponsiveLayout;\n"]} |
| //# sourceMappingURL=chunk-ZWN22PS2.mjs.map | ||
| //# sourceMappingURL=chunk-ZWN22PS2.mjs.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-ZWN22PS2.mjs"} |
| import { L as Layout, C as CompactType, a as LayoutItem } from './types-Cxf4nHNr.mjs'; | ||
| export { A as ArrayElement, B as Breakpoint, n as BreakpointCols, b as Breakpoints, c as Compactor, p as DeepPartial, k as DragConfig, h as DragOverEvent, m as DropConfig, D as DroppingPosition, E as EventCallback, j as GridConfig, G as GridDragEvent, e as GridResizeEvent, M as Mutable, o as OnBreakpointChangeCallback, O as OnLayoutChangeCallback, f as PartialPosition, P as Position, i as PositionStrategy, g as ReactDraggableCallbackData, l as ResizeConfig, d as ResizeHandleAxis, R as ResponsiveLayouts, S as Size, r as defaultDragConfig, t as defaultDropConfig, q as defaultGridConfig, s as defaultResizeConfig } from './types-Cxf4nHNr.mjs'; | ||
| export { c as collides, h as findOrGenerateResponsiveLayout, a as getAllCollisions, e as getBreakpointFromWidth, f as getColsFromBreakpoint, g as getFirstCollision, j as getIndentationValue, i as sortBreakpoints, s as sortLayoutItems, d as sortLayoutItemsByColRow, b as sortLayoutItemsByRowCol } from './responsive-CJxefsYw.mjs'; | ||
| export { z as absoluteStrategy, b as bottom, c as cloneLayout, a as cloneLayoutItem, t as compactItemHorizontal, q as compactItemVertical, k as correctBounds, A as createScaledStrategy, B as defaultPositionStrategy, d as getCompactor, g as getLayoutItem, i as getStatics, h as horizontalCompactor, p as horizontalOverlapCompactor, j as modifyLayout, m as moveElement, l as moveElementAwayFromCollision, n as noCompactor, u as perc, x as resizeItemInDirection, r as resolveCompactionCollision, f as setTopLeft, s as setTransform, y as transformStrategy, v as validateLayout, e as verticalCompactor, o as verticalOverlapCompactor, w as withLayoutItem } from './position-BmN1z36J.mjs'; | ||
| export { d as GridCellConfig, G as GridCellDimensions, P as PositionParams, h as calcGridCellDimensions, e as calcGridColWidth, c as calcGridItemPosition, f as calcGridItemWHPx, b as calcWH, a as calcXY, g as clamp } from './calculate-CwYDW8na.mjs'; | ||
| /** | ||
| * Legacy compaction API - backwards compatibility layer. | ||
| * | ||
| * This file implements the exact v1 compaction algorithm for backwards compatibility. | ||
| * The algorithm matches lib/utils.js compact/compactItem functions exactly. | ||
| */ | ||
| /** | ||
| * Compact a layout by removing gaps between items. | ||
| * | ||
| * This is the exact algorithm from lib/utils.js compact function. | ||
| * | ||
| * @param layout - Layout to compact | ||
| * @param compactType - 'vertical', 'horizontal', or null | ||
| * @param cols - Number of columns in the grid | ||
| * @param allowOverlap - If true, overlapping is allowed | ||
| * @returns Compacted layout | ||
| */ | ||
| declare function compact(layout: Layout, compactType: CompactType, cols: number, allowOverlap?: boolean): LayoutItem[]; | ||
| /** | ||
| * Compact a single item within the layout. | ||
| * | ||
| * @deprecated Use compact() instead, which handles the full layout. | ||
| */ | ||
| declare function compactItem(compareWith: Layout, l: LayoutItem, compactType: CompactType, cols: number, fullLayout: Layout, allowOverlap: boolean | undefined, maxY: number | undefined): LayoutItem; | ||
| export { CompactType, Layout, LayoutItem, compact, compactItem }; |
| import { L as Layout, C as CompactType, a as LayoutItem } from './types-Cxf4nHNr.js'; | ||
| export { A as ArrayElement, B as Breakpoint, n as BreakpointCols, b as Breakpoints, c as Compactor, p as DeepPartial, k as DragConfig, h as DragOverEvent, m as DropConfig, D as DroppingPosition, E as EventCallback, j as GridConfig, G as GridDragEvent, e as GridResizeEvent, M as Mutable, o as OnBreakpointChangeCallback, O as OnLayoutChangeCallback, f as PartialPosition, P as Position, i as PositionStrategy, g as ReactDraggableCallbackData, l as ResizeConfig, d as ResizeHandleAxis, R as ResponsiveLayouts, S as Size, r as defaultDragConfig, t as defaultDropConfig, q as defaultGridConfig, s as defaultResizeConfig } from './types-Cxf4nHNr.js'; | ||
| export { c as collides, h as findOrGenerateResponsiveLayout, a as getAllCollisions, e as getBreakpointFromWidth, f as getColsFromBreakpoint, g as getFirstCollision, j as getIndentationValue, i as sortBreakpoints, s as sortLayoutItems, d as sortLayoutItemsByColRow, b as sortLayoutItemsByRowCol } from './responsive-C4L1ESlm.js'; | ||
| export { z as absoluteStrategy, b as bottom, c as cloneLayout, a as cloneLayoutItem, t as compactItemHorizontal, q as compactItemVertical, k as correctBounds, A as createScaledStrategy, B as defaultPositionStrategy, d as getCompactor, g as getLayoutItem, i as getStatics, h as horizontalCompactor, p as horizontalOverlapCompactor, j as modifyLayout, m as moveElement, l as moveElementAwayFromCollision, n as noCompactor, u as perc, x as resizeItemInDirection, r as resolveCompactionCollision, f as setTopLeft, s as setTransform, y as transformStrategy, v as validateLayout, e as verticalCompactor, o as verticalOverlapCompactor, w as withLayoutItem } from './position-Dk2b4ZMS.js'; | ||
| export { d as GridCellConfig, G as GridCellDimensions, P as PositionParams, h as calcGridCellDimensions, e as calcGridColWidth, c as calcGridItemPosition, f as calcGridItemWHPx, b as calcWH, a as calcXY, g as clamp } from './calculate-mgLpNJ5O.js'; | ||
| /** | ||
| * Legacy compaction API - backwards compatibility layer. | ||
| * | ||
| * This file implements the exact v1 compaction algorithm for backwards compatibility. | ||
| * The algorithm matches lib/utils.js compact/compactItem functions exactly. | ||
| */ | ||
| /** | ||
| * Compact a layout by removing gaps between items. | ||
| * | ||
| * This is the exact algorithm from lib/utils.js compact function. | ||
| * | ||
| * @param layout - Layout to compact | ||
| * @param compactType - 'vertical', 'horizontal', or null | ||
| * @param cols - Number of columns in the grid | ||
| * @param allowOverlap - If true, overlapping is allowed | ||
| * @returns Compacted layout | ||
| */ | ||
| declare function compact(layout: Layout, compactType: CompactType, cols: number, allowOverlap?: boolean): LayoutItem[]; | ||
| /** | ||
| * Compact a single item within the layout. | ||
| * | ||
| * @deprecated Use compact() instead, which handles the full layout. | ||
| */ | ||
| declare function compactItem(compareWith: Layout, l: LayoutItem, compactType: CompactType, cols: number, fullLayout: Layout, allowOverlap: boolean | undefined, maxY: number | undefined): LayoutItem; | ||
| export { CompactType, Layout, LayoutItem, compact, compactItem }; |
+218
| 'use strict'; | ||
| require('./chunk-PBQSHIID.js'); | ||
| var chunk3WO4SAYB_js = require('./chunk-3WO4SAYB.js'); | ||
| var chunkF6NQPYKT_js = require('./chunk-F6NQPYKT.js'); | ||
| Object.defineProperty(exports, "absoluteStrategy", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.absoluteStrategy; } | ||
| }); | ||
| Object.defineProperty(exports, "bottom", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.bottom; } | ||
| }); | ||
| Object.defineProperty(exports, "cloneLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.cloneLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "cloneLayoutItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.cloneLayoutItem; } | ||
| }); | ||
| Object.defineProperty(exports, "collides", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.collides; } | ||
| }); | ||
| Object.defineProperty(exports, "compact", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.compact; } | ||
| }); | ||
| Object.defineProperty(exports, "compactItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.compactItem; } | ||
| }); | ||
| Object.defineProperty(exports, "compactItemHorizontal", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.compactItemHorizontal; } | ||
| }); | ||
| Object.defineProperty(exports, "compactItemVertical", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.compactItemVertical; } | ||
| }); | ||
| Object.defineProperty(exports, "correctBounds", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.correctBounds; } | ||
| }); | ||
| Object.defineProperty(exports, "createScaledStrategy", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.createScaledStrategy; } | ||
| }); | ||
| Object.defineProperty(exports, "defaultDragConfig", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.defaultDragConfig; } | ||
| }); | ||
| Object.defineProperty(exports, "defaultDropConfig", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.defaultDropConfig; } | ||
| }); | ||
| Object.defineProperty(exports, "defaultGridConfig", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.defaultGridConfig; } | ||
| }); | ||
| Object.defineProperty(exports, "defaultPositionStrategy", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.defaultPositionStrategy; } | ||
| }); | ||
| Object.defineProperty(exports, "defaultResizeConfig", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.defaultResizeConfig; } | ||
| }); | ||
| Object.defineProperty(exports, "findOrGenerateResponsiveLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.findOrGenerateResponsiveLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "getAllCollisions", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getAllCollisions; } | ||
| }); | ||
| Object.defineProperty(exports, "getBreakpointFromWidth", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getBreakpointFromWidth; } | ||
| }); | ||
| Object.defineProperty(exports, "getColsFromBreakpoint", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getColsFromBreakpoint; } | ||
| }); | ||
| Object.defineProperty(exports, "getCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "getFirstCollision", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getFirstCollision; } | ||
| }); | ||
| Object.defineProperty(exports, "getIndentationValue", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getIndentationValue; } | ||
| }); | ||
| Object.defineProperty(exports, "getLayoutItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getLayoutItem; } | ||
| }); | ||
| Object.defineProperty(exports, "getStatics", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getStatics; } | ||
| }); | ||
| Object.defineProperty(exports, "horizontalCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.horizontalCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "horizontalOverlapCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.horizontalOverlapCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "modifyLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.modifyLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "moveElement", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.moveElement; } | ||
| }); | ||
| Object.defineProperty(exports, "moveElementAwayFromCollision", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.moveElementAwayFromCollision; } | ||
| }); | ||
| Object.defineProperty(exports, "noCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.noCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "perc", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.perc; } | ||
| }); | ||
| Object.defineProperty(exports, "resizeItemInDirection", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.resizeItemInDirection; } | ||
| }); | ||
| Object.defineProperty(exports, "resolveCompactionCollision", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.resolveCompactionCollision; } | ||
| }); | ||
| Object.defineProperty(exports, "setTopLeft", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.setTopLeft; } | ||
| }); | ||
| Object.defineProperty(exports, "setTransform", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.setTransform; } | ||
| }); | ||
| Object.defineProperty(exports, "sortBreakpoints", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.sortBreakpoints; } | ||
| }); | ||
| Object.defineProperty(exports, "sortLayoutItems", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.sortLayoutItems; } | ||
| }); | ||
| Object.defineProperty(exports, "sortLayoutItemsByColRow", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.sortLayoutItemsByColRow; } | ||
| }); | ||
| Object.defineProperty(exports, "sortLayoutItemsByRowCol", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.sortLayoutItemsByRowCol; } | ||
| }); | ||
| Object.defineProperty(exports, "transformStrategy", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.transformStrategy; } | ||
| }); | ||
| Object.defineProperty(exports, "validateLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.validateLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "verticalCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.verticalCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "verticalOverlapCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.verticalOverlapCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "withLayoutItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.withLayoutItem; } | ||
| }); | ||
| Object.defineProperty(exports, "calcGridCellDimensions", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcGridCellDimensions; } | ||
| }); | ||
| Object.defineProperty(exports, "calcGridColWidth", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcGridColWidth; } | ||
| }); | ||
| Object.defineProperty(exports, "calcGridItemPosition", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcGridItemPosition; } | ||
| }); | ||
| Object.defineProperty(exports, "calcGridItemWHPx", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcGridItemWHPx; } | ||
| }); | ||
| Object.defineProperty(exports, "calcWH", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcWH; } | ||
| }); | ||
| Object.defineProperty(exports, "calcXY", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcXY; } | ||
| }); | ||
| Object.defineProperty(exports, "clamp", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.clamp; } | ||
| }); | ||
| //# sourceMappingURL=core.js.map | ||
| //# sourceMappingURL=core.js.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"core.js"} |
| import './chunk-ZWN22PS2.mjs'; | ||
| export { absoluteStrategy, bottom, cloneLayout, cloneLayoutItem, collides, compact, compactItem, compactItemHorizontal, compactItemVertical, correctBounds, createScaledStrategy, defaultDragConfig, defaultDropConfig, defaultGridConfig, defaultPositionStrategy, defaultResizeConfig, findOrGenerateResponsiveLayout, getAllCollisions, getBreakpointFromWidth, getColsFromBreakpoint, getCompactor, getFirstCollision, getIndentationValue, getLayoutItem, getStatics, horizontalCompactor, horizontalOverlapCompactor, modifyLayout, moveElement, moveElementAwayFromCollision, noCompactor, perc, resizeItemInDirection, resolveCompactionCollision, setTopLeft, setTransform, sortBreakpoints, sortLayoutItems, sortLayoutItemsByColRow, sortLayoutItemsByRowCol, transformStrategy, validateLayout, verticalCompactor, verticalOverlapCompactor, withLayoutItem } from './chunk-4HNUMWQK.mjs'; | ||
| export { calcGridCellDimensions, calcGridColWidth, calcGridItemPosition, calcGridItemWHPx, calcWH, calcXY, clamp } from './chunk-2KUHNJXF.mjs'; | ||
| //# sourceMappingURL=core.mjs.map | ||
| //# sourceMappingURL=core.mjs.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"core.mjs"} |
| import * as React from 'react'; | ||
| import { d as GridCellConfig } from './calculate-CwYDW8na.mjs'; | ||
| import './types-Cxf4nHNr.mjs'; | ||
| /** | ||
| * GridBackground component | ||
| * | ||
| * Renders an SVG grid background that aligns with GridLayout cells. | ||
| * Use this to visualize the grid structure behind your layout. | ||
| */ | ||
| interface GridBackgroundProps extends GridCellConfig { | ||
| /** | ||
| * Number of rows to display. If "auto", calculates based on height. | ||
| * @default 10 | ||
| */ | ||
| rows?: number | "auto"; | ||
| /** | ||
| * Height of the background in pixels. Used when rows="auto". | ||
| */ | ||
| height?: number; | ||
| /** | ||
| * Color of the grid cell backgrounds. | ||
| * @default "#e0e0e0" | ||
| */ | ||
| color?: string; | ||
| /** | ||
| * Border radius of grid cells in pixels. | ||
| * @default 4 | ||
| */ | ||
| borderRadius?: number; | ||
| /** | ||
| * Additional CSS class name. | ||
| */ | ||
| className?: string; | ||
| /** | ||
| * Additional inline styles. | ||
| */ | ||
| style?: React.CSSProperties; | ||
| } | ||
| /** | ||
| * SVG grid background component. | ||
| * | ||
| * Renders a visual grid that aligns with GridLayout cells. Position this | ||
| * behind your GridLayout using CSS positioning. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * import { GridBackground } from 'react-grid-layout/extras'; | ||
| * | ||
| * function MyGrid() { | ||
| * const { width, containerRef, mounted } = useContainerWidth(); | ||
| * | ||
| * return ( | ||
| * <div ref={containerRef} style={{ position: 'relative' }}> | ||
| * {mounted && ( | ||
| * <> | ||
| * <GridBackground | ||
| * width={width} | ||
| * cols={12} | ||
| * rowHeight={30} | ||
| * margin={[10, 10]} | ||
| * rows={10} | ||
| * color="#f0f0f0" | ||
| * /> | ||
| * <GridLayout width={width} gridConfig={{ cols: 12, rowHeight: 30 }}> | ||
| * {children} | ||
| * </GridLayout> | ||
| * </> | ||
| * )} | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function GridBackground({ width, cols, rowHeight, margin, containerPadding, rows, height, color, borderRadius, className, style }: GridBackgroundProps): React.ReactElement; | ||
| export { GridBackground, type GridBackgroundProps }; |
| import * as React from 'react'; | ||
| import { d as GridCellConfig } from './calculate-mgLpNJ5O.js'; | ||
| import './types-Cxf4nHNr.js'; | ||
| /** | ||
| * GridBackground component | ||
| * | ||
| * Renders an SVG grid background that aligns with GridLayout cells. | ||
| * Use this to visualize the grid structure behind your layout. | ||
| */ | ||
| interface GridBackgroundProps extends GridCellConfig { | ||
| /** | ||
| * Number of rows to display. If "auto", calculates based on height. | ||
| * @default 10 | ||
| */ | ||
| rows?: number | "auto"; | ||
| /** | ||
| * Height of the background in pixels. Used when rows="auto". | ||
| */ | ||
| height?: number; | ||
| /** | ||
| * Color of the grid cell backgrounds. | ||
| * @default "#e0e0e0" | ||
| */ | ||
| color?: string; | ||
| /** | ||
| * Border radius of grid cells in pixels. | ||
| * @default 4 | ||
| */ | ||
| borderRadius?: number; | ||
| /** | ||
| * Additional CSS class name. | ||
| */ | ||
| className?: string; | ||
| /** | ||
| * Additional inline styles. | ||
| */ | ||
| style?: React.CSSProperties; | ||
| } | ||
| /** | ||
| * SVG grid background component. | ||
| * | ||
| * Renders a visual grid that aligns with GridLayout cells. Position this | ||
| * behind your GridLayout using CSS positioning. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * import { GridBackground } from 'react-grid-layout/extras'; | ||
| * | ||
| * function MyGrid() { | ||
| * const { width, containerRef, mounted } = useContainerWidth(); | ||
| * | ||
| * return ( | ||
| * <div ref={containerRef} style={{ position: 'relative' }}> | ||
| * {mounted && ( | ||
| * <> | ||
| * <GridBackground | ||
| * width={width} | ||
| * cols={12} | ||
| * rowHeight={30} | ||
| * margin={[10, 10]} | ||
| * rows={10} | ||
| * color="#f0f0f0" | ||
| * /> | ||
| * <GridLayout width={width} gridConfig={{ cols: 12, rowHeight: 30 }}> | ||
| * {children} | ||
| * </GridLayout> | ||
| * </> | ||
| * )} | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function GridBackground({ width, cols, rowHeight, margin, containerPadding, rows, height, color, borderRadius, className, style }: GridBackgroundProps): React.ReactElement; | ||
| export { GridBackground, type GridBackgroundProps }; |
| 'use strict'; | ||
| var chunkF6NQPYKT_js = require('./chunk-F6NQPYKT.js'); | ||
| var react = require('react'); | ||
| var jsxRuntime = require('react/jsx-runtime'); | ||
| function GridBackground({ | ||
| width, | ||
| cols, | ||
| rowHeight, | ||
| margin = [10, 10], | ||
| containerPadding, | ||
| rows = 10, | ||
| height, | ||
| color = "#e0e0e0", | ||
| borderRadius = 4, | ||
| className, | ||
| style | ||
| }) { | ||
| const dims = react.useMemo( | ||
| () => chunkF6NQPYKT_js.calcGridCellDimensions({ | ||
| width, | ||
| cols, | ||
| rowHeight, | ||
| margin, | ||
| containerPadding | ||
| }), | ||
| [width, cols, rowHeight, margin, containerPadding] | ||
| ); | ||
| const rowCount = react.useMemo(() => { | ||
| if (rows !== "auto") return rows; | ||
| if (height) { | ||
| const padding = containerPadding ?? margin; | ||
| return Math.ceil( | ||
| (height - padding[1] * 2 + margin[1]) / (rowHeight + margin[1]) | ||
| ); | ||
| } | ||
| return 10; | ||
| }, [rows, height, rowHeight, margin, containerPadding]); | ||
| const totalHeight = react.useMemo(() => { | ||
| const padding = containerPadding ?? margin; | ||
| return padding[1] * 2 + rowCount * rowHeight + (rowCount - 1) * margin[1]; | ||
| }, [rowCount, rowHeight, margin, containerPadding]); | ||
| const cells = react.useMemo(() => { | ||
| const rects = []; | ||
| const { cellWidth, cellHeight, offsetX, offsetY, gapX, gapY } = dims; | ||
| for (let row = 0; row < rowCount; row++) { | ||
| for (let col = 0; col < cols; col++) { | ||
| const x = offsetX + col * (cellWidth + gapX); | ||
| const y = offsetY + row * (cellHeight + gapY); | ||
| rects.push( | ||
| /* @__PURE__ */ jsxRuntime.jsx( | ||
| "rect", | ||
| { | ||
| x, | ||
| y, | ||
| width: cellWidth, | ||
| height: cellHeight, | ||
| rx: borderRadius, | ||
| ry: borderRadius, | ||
| fill: color | ||
| }, | ||
| `${row}-${col}` | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
| return rects; | ||
| }, [dims, rowCount, cols, borderRadius, color]); | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| "svg", | ||
| { | ||
| className, | ||
| style: { | ||
| position: "absolute", | ||
| top: 0, | ||
| left: 0, | ||
| width, | ||
| height: totalHeight, | ||
| pointerEvents: "none", | ||
| ...style | ||
| }, | ||
| "aria-hidden": "true", | ||
| children: cells | ||
| } | ||
| ); | ||
| } | ||
| exports.GridBackground = GridBackground; | ||
| //# sourceMappingURL=extras.js.map | ||
| //# sourceMappingURL=extras.js.map |
| {"version":3,"sources":["../src/extras/GridBackground.tsx"],"names":["useMemo","calcGridCellDimensions","jsx"],"mappings":"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","file":"extras.js","sourcesContent":["/**\n * GridBackground component\n *\n * Renders an SVG grid background that aligns with GridLayout cells.\n * Use this to visualize the grid structure behind your layout.\n */\n\nimport * as React from \"react\";\nimport { useMemo } from \"react\";\nimport { calcGridCellDimensions } from \"../core/calculate.js\";\nimport type { GridCellConfig } from \"../core/calculate.js\";\n\nexport interface GridBackgroundProps extends GridCellConfig {\n /**\n * Number of rows to display. If \"auto\", calculates based on height.\n * @default 10\n */\n rows?: number | \"auto\";\n\n /**\n * Height of the background in pixels. Used when rows=\"auto\".\n */\n height?: number;\n\n /**\n * Color of the grid cell backgrounds.\n * @default \"#e0e0e0\"\n */\n color?: string;\n\n /**\n * Border radius of grid cells in pixels.\n * @default 4\n */\n borderRadius?: number;\n\n /**\n * Additional CSS class name.\n */\n className?: string;\n\n /**\n * Additional inline styles.\n */\n style?: React.CSSProperties;\n}\n\n/**\n * SVG grid background component.\n *\n * Renders a visual grid that aligns with GridLayout cells. Position this\n * behind your GridLayout using CSS positioning.\n *\n * @example\n * ```tsx\n * import { GridBackground } from 'react-grid-layout/extras';\n *\n * function MyGrid() {\n * const { width, containerRef, mounted } = useContainerWidth();\n *\n * return (\n * <div ref={containerRef} style={{ position: 'relative' }}>\n * {mounted && (\n * <>\n * <GridBackground\n * width={width}\n * cols={12}\n * rowHeight={30}\n * margin={[10, 10]}\n * rows={10}\n * color=\"#f0f0f0\"\n * />\n * <GridLayout width={width} gridConfig={{ cols: 12, rowHeight: 30 }}>\n * {children}\n * </GridLayout>\n * </>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function GridBackground({\n width,\n cols,\n rowHeight,\n margin = [10, 10],\n containerPadding,\n rows = 10,\n height,\n color = \"#e0e0e0\",\n borderRadius = 4,\n className,\n style\n}: GridBackgroundProps): React.ReactElement {\n const dims = useMemo(\n () =>\n calcGridCellDimensions({\n width,\n cols,\n rowHeight,\n margin,\n containerPadding\n }),\n [width, cols, rowHeight, margin, containerPadding]\n );\n\n // Calculate number of rows\n const rowCount = useMemo(() => {\n if (rows !== \"auto\") return rows;\n if (height) {\n // Calculate rows that fit in the given height\n const padding = containerPadding ?? margin;\n return Math.ceil(\n (height - padding[1] * 2 + margin[1]) / (rowHeight + margin[1])\n );\n }\n return 10;\n }, [rows, height, rowHeight, margin, containerPadding]);\n\n // Calculate total height\n const totalHeight = useMemo(() => {\n const padding = containerPadding ?? margin;\n return padding[1] * 2 + rowCount * rowHeight + (rowCount - 1) * margin[1];\n }, [rowCount, rowHeight, margin, containerPadding]);\n\n // Generate cell rectangles\n const cells = useMemo(() => {\n const rects: React.ReactElement[] = [];\n const { cellWidth, cellHeight, offsetX, offsetY, gapX, gapY } = dims;\n\n for (let row = 0; row < rowCount; row++) {\n for (let col = 0; col < cols; col++) {\n const x = offsetX + col * (cellWidth + gapX);\n const y = offsetY + row * (cellHeight + gapY);\n\n rects.push(\n <rect\n key={`${row}-${col}`}\n x={x}\n y={y}\n width={cellWidth}\n height={cellHeight}\n rx={borderRadius}\n ry={borderRadius}\n fill={color}\n />\n );\n }\n }\n\n return rects;\n }, [dims, rowCount, cols, borderRadius, color]);\n\n return (\n <svg\n className={className}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: width,\n height: totalHeight,\n pointerEvents: \"none\",\n ...style\n }}\n aria-hidden=\"true\"\n >\n {cells}\n </svg>\n );\n}\n\nexport default GridBackground;\n"]} |
| import { calcGridCellDimensions } from './chunk-2KUHNJXF.mjs'; | ||
| import { useMemo } from 'react'; | ||
| import { jsx } from 'react/jsx-runtime'; | ||
| function GridBackground({ | ||
| width, | ||
| cols, | ||
| rowHeight, | ||
| margin = [10, 10], | ||
| containerPadding, | ||
| rows = 10, | ||
| height, | ||
| color = "#e0e0e0", | ||
| borderRadius = 4, | ||
| className, | ||
| style | ||
| }) { | ||
| const dims = useMemo( | ||
| () => calcGridCellDimensions({ | ||
| width, | ||
| cols, | ||
| rowHeight, | ||
| margin, | ||
| containerPadding | ||
| }), | ||
| [width, cols, rowHeight, margin, containerPadding] | ||
| ); | ||
| const rowCount = useMemo(() => { | ||
| if (rows !== "auto") return rows; | ||
| if (height) { | ||
| const padding = containerPadding ?? margin; | ||
| return Math.ceil( | ||
| (height - padding[1] * 2 + margin[1]) / (rowHeight + margin[1]) | ||
| ); | ||
| } | ||
| return 10; | ||
| }, [rows, height, rowHeight, margin, containerPadding]); | ||
| const totalHeight = useMemo(() => { | ||
| const padding = containerPadding ?? margin; | ||
| return padding[1] * 2 + rowCount * rowHeight + (rowCount - 1) * margin[1]; | ||
| }, [rowCount, rowHeight, margin, containerPadding]); | ||
| const cells = useMemo(() => { | ||
| const rects = []; | ||
| const { cellWidth, cellHeight, offsetX, offsetY, gapX, gapY } = dims; | ||
| for (let row = 0; row < rowCount; row++) { | ||
| for (let col = 0; col < cols; col++) { | ||
| const x = offsetX + col * (cellWidth + gapX); | ||
| const y = offsetY + row * (cellHeight + gapY); | ||
| rects.push( | ||
| /* @__PURE__ */ jsx( | ||
| "rect", | ||
| { | ||
| x, | ||
| y, | ||
| width: cellWidth, | ||
| height: cellHeight, | ||
| rx: borderRadius, | ||
| ry: borderRadius, | ||
| fill: color | ||
| }, | ||
| `${row}-${col}` | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
| return rects; | ||
| }, [dims, rowCount, cols, borderRadius, color]); | ||
| return /* @__PURE__ */ jsx( | ||
| "svg", | ||
| { | ||
| className, | ||
| style: { | ||
| position: "absolute", | ||
| top: 0, | ||
| left: 0, | ||
| width, | ||
| height: totalHeight, | ||
| pointerEvents: "none", | ||
| ...style | ||
| }, | ||
| "aria-hidden": "true", | ||
| children: cells | ||
| } | ||
| ); | ||
| } | ||
| export { GridBackground }; | ||
| //# sourceMappingURL=extras.mjs.map | ||
| //# sourceMappingURL=extras.mjs.map |
| {"version":3,"sources":["../src/extras/GridBackground.tsx"],"names":[],"mappings":"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","file":"extras.mjs","sourcesContent":["/**\n * GridBackground component\n *\n * Renders an SVG grid background that aligns with GridLayout cells.\n * Use this to visualize the grid structure behind your layout.\n */\n\nimport * as React from \"react\";\nimport { useMemo } from \"react\";\nimport { calcGridCellDimensions } from \"../core/calculate.js\";\nimport type { GridCellConfig } from \"../core/calculate.js\";\n\nexport interface GridBackgroundProps extends GridCellConfig {\n /**\n * Number of rows to display. If \"auto\", calculates based on height.\n * @default 10\n */\n rows?: number | \"auto\";\n\n /**\n * Height of the background in pixels. Used when rows=\"auto\".\n */\n height?: number;\n\n /**\n * Color of the grid cell backgrounds.\n * @default \"#e0e0e0\"\n */\n color?: string;\n\n /**\n * Border radius of grid cells in pixels.\n * @default 4\n */\n borderRadius?: number;\n\n /**\n * Additional CSS class name.\n */\n className?: string;\n\n /**\n * Additional inline styles.\n */\n style?: React.CSSProperties;\n}\n\n/**\n * SVG grid background component.\n *\n * Renders a visual grid that aligns with GridLayout cells. Position this\n * behind your GridLayout using CSS positioning.\n *\n * @example\n * ```tsx\n * import { GridBackground } from 'react-grid-layout/extras';\n *\n * function MyGrid() {\n * const { width, containerRef, mounted } = useContainerWidth();\n *\n * return (\n * <div ref={containerRef} style={{ position: 'relative' }}>\n * {mounted && (\n * <>\n * <GridBackground\n * width={width}\n * cols={12}\n * rowHeight={30}\n * margin={[10, 10]}\n * rows={10}\n * color=\"#f0f0f0\"\n * />\n * <GridLayout width={width} gridConfig={{ cols: 12, rowHeight: 30 }}>\n * {children}\n * </GridLayout>\n * </>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function GridBackground({\n width,\n cols,\n rowHeight,\n margin = [10, 10],\n containerPadding,\n rows = 10,\n height,\n color = \"#e0e0e0\",\n borderRadius = 4,\n className,\n style\n}: GridBackgroundProps): React.ReactElement {\n const dims = useMemo(\n () =>\n calcGridCellDimensions({\n width,\n cols,\n rowHeight,\n margin,\n containerPadding\n }),\n [width, cols, rowHeight, margin, containerPadding]\n );\n\n // Calculate number of rows\n const rowCount = useMemo(() => {\n if (rows !== \"auto\") return rows;\n if (height) {\n // Calculate rows that fit in the given height\n const padding = containerPadding ?? margin;\n return Math.ceil(\n (height - padding[1] * 2 + margin[1]) / (rowHeight + margin[1])\n );\n }\n return 10;\n }, [rows, height, rowHeight, margin, containerPadding]);\n\n // Calculate total height\n const totalHeight = useMemo(() => {\n const padding = containerPadding ?? margin;\n return padding[1] * 2 + rowCount * rowHeight + (rowCount - 1) * margin[1];\n }, [rowCount, rowHeight, margin, containerPadding]);\n\n // Generate cell rectangles\n const cells = useMemo(() => {\n const rects: React.ReactElement[] = [];\n const { cellWidth, cellHeight, offsetX, offsetY, gapX, gapY } = dims;\n\n for (let row = 0; row < rowCount; row++) {\n for (let col = 0; col < cols; col++) {\n const x = offsetX + col * (cellWidth + gapX);\n const y = offsetY + row * (cellHeight + gapY);\n\n rects.push(\n <rect\n key={`${row}-${col}`}\n x={x}\n y={y}\n width={cellWidth}\n height={cellHeight}\n rx={borderRadius}\n ry={borderRadius}\n fill={color}\n />\n );\n }\n }\n\n return rects;\n }, [dims, rowCount, cols, borderRadius, color]);\n\n return (\n <svg\n className={className}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: width,\n height: totalHeight,\n pointerEvents: \"none\",\n ...style\n }}\n aria-hidden=\"true\"\n >\n {cells}\n </svg>\n );\n}\n\nexport default GridBackground;\n"]} |
| export { DEFAULT_BREAKPOINTS, DEFAULT_COLS, DefaultBreakpoints, DragState, DropState, GridItem, GridItemCallback, GridItemProps, ResizeHandle, ResizeState, UseContainerWidthOptions, UseContainerWidthResult, UseGridLayoutOptions, UseGridLayoutResult, UseResponsiveLayoutOptions, UseResponsiveLayoutResult, useContainerWidth, useGridLayout, useResponsiveLayout } from './react.mjs'; | ||
| export { G as GridLayout, a as GridLayoutProps, G as ReactGridLayout, a as ReactGridLayoutProps, R as Responsive, R as ResponsiveGridLayout, b as ResponsiveGridLayoutProps, b as ResponsiveProps, G as default } from './ResponsiveGridLayout-D6lFRE3f.mjs'; | ||
| export { B as Breakpoint, b as Breakpoints, C as CompactType, c as Compactor, D as DroppingPosition, E as EventCallback, G as GridDragEvent, e as GridResizeEvent, L as Layout, a as LayoutItem, P as Position, d as ResizeHandleAxis, R as ResponsiveLayouts } from './types-Cxf4nHNr.mjs'; | ||
| export { c as collides, h as findOrGenerateResponsiveLayout, a as getAllCollisions, e as getBreakpointFromWidth, f as getColsFromBreakpoint, g as getFirstCollision, s as sortLayoutItems, d as sortLayoutItemsByColRow, b as sortLayoutItemsByRowCol } from './responsive-CJxefsYw.mjs'; | ||
| export { b as bottom, c as cloneLayout, a as cloneLayoutItem, d as getCompactor, g as getLayoutItem, h as horizontalCompactor, m as moveElement, n as noCompactor, f as setTopLeft, s as setTransform, v as validateLayout, e as verticalCompactor } from './position-BmN1z36J.mjs'; | ||
| export { c as calcGridItemPosition, b as calcWH, a as calcXY } from './calculate-CwYDW8na.mjs'; | ||
| import 'react'; |
| export { DEFAULT_BREAKPOINTS, DEFAULT_COLS, DefaultBreakpoints, DragState, DropState, GridItem, GridItemCallback, GridItemProps, ResizeHandle, ResizeState, UseContainerWidthOptions, UseContainerWidthResult, UseGridLayoutOptions, UseGridLayoutResult, UseResponsiveLayoutOptions, UseResponsiveLayoutResult, useContainerWidth, useGridLayout, useResponsiveLayout } from './react.js'; | ||
| export { G as GridLayout, a as GridLayoutProps, G as ReactGridLayout, a as ReactGridLayoutProps, R as Responsive, R as ResponsiveGridLayout, b as ResponsiveGridLayoutProps, b as ResponsiveProps, G as default } from './ResponsiveGridLayout-CH4s0tKj.js'; | ||
| export { B as Breakpoint, b as Breakpoints, C as CompactType, c as Compactor, D as DroppingPosition, E as EventCallback, G as GridDragEvent, e as GridResizeEvent, L as Layout, a as LayoutItem, P as Position, d as ResizeHandleAxis, R as ResponsiveLayouts } from './types-Cxf4nHNr.js'; | ||
| export { c as collides, h as findOrGenerateResponsiveLayout, a as getAllCollisions, e as getBreakpointFromWidth, f as getColsFromBreakpoint, g as getFirstCollision, s as sortLayoutItems, d as sortLayoutItemsByColRow, b as sortLayoutItemsByRowCol } from './responsive-C4L1ESlm.js'; | ||
| export { b as bottom, c as cloneLayout, a as cloneLayoutItem, d as getCompactor, g as getLayoutItem, h as horizontalCompactor, m as moveElement, n as noCompactor, f as setTopLeft, s as setTransform, v as validateLayout, e as verticalCompactor } from './position-Dk2b4ZMS.js'; | ||
| export { c as calcGridItemPosition, b as calcWH, a as calcXY } from './calculate-mgLpNJ5O.js'; | ||
| import 'react'; |
+154
| 'use strict'; | ||
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| var chunkH5KMDLY3_js = require('./chunk-H5KMDLY3.js'); | ||
| require('./chunk-PBQSHIID.js'); | ||
| var chunkBFTKGAP3_js = require('./chunk-BFTKGAP3.js'); | ||
| var chunk3WO4SAYB_js = require('./chunk-3WO4SAYB.js'); | ||
| var chunkF6NQPYKT_js = require('./chunk-F6NQPYKT.js'); | ||
| Object.defineProperty(exports, "DEFAULT_BREAKPOINTS", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.DEFAULT_BREAKPOINTS; } | ||
| }); | ||
| Object.defineProperty(exports, "DEFAULT_COLS", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.DEFAULT_COLS; } | ||
| }); | ||
| Object.defineProperty(exports, "useContainerWidth", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.useContainerWidth; } | ||
| }); | ||
| Object.defineProperty(exports, "useGridLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.useGridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "useResponsiveLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.useResponsiveLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "GridItem", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.GridItem; } | ||
| }); | ||
| Object.defineProperty(exports, "GridLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.GridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "ReactGridLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.GridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "Responsive", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.ResponsiveGridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "ResponsiveGridLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.ResponsiveGridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "default", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.GridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "bottom", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.bottom; } | ||
| }); | ||
| Object.defineProperty(exports, "cloneLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.cloneLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "cloneLayoutItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.cloneLayoutItem; } | ||
| }); | ||
| Object.defineProperty(exports, "collides", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.collides; } | ||
| }); | ||
| Object.defineProperty(exports, "findOrGenerateResponsiveLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.findOrGenerateResponsiveLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "getAllCollisions", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getAllCollisions; } | ||
| }); | ||
| Object.defineProperty(exports, "getBreakpointFromWidth", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getBreakpointFromWidth; } | ||
| }); | ||
| Object.defineProperty(exports, "getColsFromBreakpoint", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getColsFromBreakpoint; } | ||
| }); | ||
| Object.defineProperty(exports, "getCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "getFirstCollision", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getFirstCollision; } | ||
| }); | ||
| Object.defineProperty(exports, "getLayoutItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getLayoutItem; } | ||
| }); | ||
| Object.defineProperty(exports, "horizontalCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.horizontalCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "moveElement", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.moveElement; } | ||
| }); | ||
| Object.defineProperty(exports, "noCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.noCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "setTopLeft", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.setTopLeft; } | ||
| }); | ||
| Object.defineProperty(exports, "setTransform", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.setTransform; } | ||
| }); | ||
| Object.defineProperty(exports, "sortLayoutItems", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.sortLayoutItems; } | ||
| }); | ||
| Object.defineProperty(exports, "sortLayoutItemsByColRow", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.sortLayoutItemsByColRow; } | ||
| }); | ||
| Object.defineProperty(exports, "sortLayoutItemsByRowCol", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.sortLayoutItemsByRowCol; } | ||
| }); | ||
| Object.defineProperty(exports, "validateLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.validateLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "verticalCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.verticalCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "calcGridItemPosition", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcGridItemPosition; } | ||
| }); | ||
| Object.defineProperty(exports, "calcWH", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcWH; } | ||
| }); | ||
| Object.defineProperty(exports, "calcXY", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcXY; } | ||
| }); | ||
| //# sourceMappingURL=index.js.map | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"} |
| export { DEFAULT_BREAKPOINTS, DEFAULT_COLS, useContainerWidth, useGridLayout, useResponsiveLayout } from './chunk-ZCXE6SR5.mjs'; | ||
| import './chunk-ZWN22PS2.mjs'; | ||
| export { GridItem, GridLayout, GridLayout as ReactGridLayout, ResponsiveGridLayout as Responsive, ResponsiveGridLayout, GridLayout as default } from './chunk-R35HZZTA.mjs'; | ||
| export { bottom, cloneLayout, cloneLayoutItem, collides, findOrGenerateResponsiveLayout, getAllCollisions, getBreakpointFromWidth, getColsFromBreakpoint, getCompactor, getFirstCollision, getLayoutItem, horizontalCompactor, moveElement, noCompactor, setTopLeft, setTransform, sortLayoutItems, sortLayoutItemsByColRow, sortLayoutItemsByRowCol, validateLayout, verticalCompactor } from './chunk-4HNUMWQK.mjs'; | ||
| export { calcGridItemPosition, calcWH, calcXY } from './chunk-2KUHNJXF.mjs'; | ||
| //# sourceMappingURL=index.mjs.map | ||
| //# sourceMappingURL=index.mjs.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"} |
| import * as react_jsx_runtime from 'react/jsx-runtime'; | ||
| import React__default, { ComponentType } from 'react'; | ||
| import { a as GridLayoutProps, b as ResponsiveGridLayoutProps } from './ResponsiveGridLayout-D6lFRE3f.mjs'; | ||
| import { L as Layout, a as LayoutItem, C as CompactType, d as ResizeHandleAxis, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.mjs'; | ||
| /** | ||
| * Legacy props interface for backwards compatibility with v1 API. | ||
| * These flat props are converted to composable interfaces internally. | ||
| */ | ||
| interface LegacyReactGridLayoutProps { | ||
| children: React__default.ReactNode; | ||
| width: number; | ||
| cols?: number; | ||
| rowHeight?: number; | ||
| maxRows?: number; | ||
| margin?: readonly [number, number]; | ||
| containerPadding?: readonly [number, number] | null; | ||
| layout?: Layout; | ||
| droppingItem?: LayoutItem; | ||
| compactType?: CompactType; | ||
| preventCollision?: boolean; | ||
| allowOverlap?: boolean; | ||
| /** @deprecated Use compactType instead */ | ||
| verticalCompact?: boolean; | ||
| isDraggable?: boolean; | ||
| isBounded?: boolean; | ||
| draggableHandle?: string; | ||
| draggableCancel?: string; | ||
| isResizable?: boolean; | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| resizeHandle?: React__default.ReactElement | ((axis: ResizeHandleAxis, ref: React__default.Ref<HTMLElement>) => React__default.ReactElement); | ||
| isDroppable?: boolean; | ||
| useCSSTransforms?: boolean; | ||
| transformScale?: number; | ||
| autoSize?: boolean; | ||
| className?: string; | ||
| style?: React__default.CSSProperties; | ||
| innerRef?: React__default.Ref<HTMLDivElement>; | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| onDragStart?: GridLayoutProps["onDragStart"]; | ||
| onDrag?: GridLayoutProps["onDrag"]; | ||
| onDragStop?: GridLayoutProps["onDragStop"]; | ||
| onResizeStart?: GridLayoutProps["onResizeStart"]; | ||
| onResize?: GridLayoutProps["onResize"]; | ||
| onResizeStop?: GridLayoutProps["onResizeStop"]; | ||
| onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void; | ||
| onDropDragOver?: (e: React__default.DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** | ||
| * ReactGridLayout - Legacy wrapper component | ||
| * | ||
| * Converts v1 flat props to v2 composable interfaces for backwards compatibility. | ||
| */ | ||
| declare function ReactGridLayout(props: LegacyReactGridLayoutProps): react_jsx_runtime.JSX.Element; | ||
| declare namespace ReactGridLayout { | ||
| var displayName: string; | ||
| } | ||
| /** | ||
| * Legacy props interface for backwards compatibility with v1 API. | ||
| * These flat props are converted to composable interfaces internally. | ||
| */ | ||
| interface LegacyResponsiveReactGridLayoutProps<B extends Breakpoint = string> { | ||
| children: React__default.ReactNode; | ||
| width: number; | ||
| breakpoint?: B; | ||
| breakpoints?: Breakpoints<B>; | ||
| cols?: Breakpoints<B>; | ||
| layouts?: ResponsiveLayouts<B>; | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void; | ||
| onWidthChange?: (containerWidth: number, margin: readonly [number, number], cols: number, containerPadding: readonly [number, number] | null) => void; | ||
| rowHeight?: number; | ||
| maxRows?: number; | ||
| margin?: readonly [number, number] | Partial<Record<B, readonly [number, number]>>; | ||
| containerPadding?: readonly [number, number] | Partial<Record<B, readonly [number, number] | null>> | null; | ||
| droppingItem?: LayoutItem; | ||
| compactType?: CompactType; | ||
| preventCollision?: boolean; | ||
| allowOverlap?: boolean; | ||
| /** @deprecated Use compactType instead */ | ||
| verticalCompact?: boolean; | ||
| isDraggable?: boolean; | ||
| isBounded?: boolean; | ||
| draggableHandle?: string; | ||
| draggableCancel?: string; | ||
| isResizable?: boolean; | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| resizeHandle?: React__default.ReactElement | ((axis: ResizeHandleAxis, ref: React__default.Ref<HTMLElement>) => React__default.ReactElement); | ||
| isDroppable?: boolean; | ||
| useCSSTransforms?: boolean; | ||
| transformScale?: number; | ||
| autoSize?: boolean; | ||
| className?: string; | ||
| style?: React__default.CSSProperties; | ||
| innerRef?: React__default.Ref<HTMLDivElement>; | ||
| onDragStart?: ResponsiveGridLayoutProps<B>["onDragStart"]; | ||
| onDrag?: ResponsiveGridLayoutProps<B>["onDrag"]; | ||
| onDragStop?: ResponsiveGridLayoutProps<B>["onDragStop"]; | ||
| onResizeStart?: ResponsiveGridLayoutProps<B>["onResizeStart"]; | ||
| onResize?: ResponsiveGridLayoutProps<B>["onResize"]; | ||
| onResizeStop?: ResponsiveGridLayoutProps<B>["onResizeStop"]; | ||
| onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void; | ||
| onDropDragOver?: (e: React__default.DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** | ||
| * ResponsiveReactGridLayout - Legacy wrapper component | ||
| * | ||
| * Converts v1 flat props to v2 composable interfaces for backwards compatibility. | ||
| */ | ||
| declare function ResponsiveReactGridLayout<B extends Breakpoint = string>(props: LegacyResponsiveReactGridLayoutProps<B>): react_jsx_runtime.JSX.Element; | ||
| declare namespace ResponsiveReactGridLayout { | ||
| var displayName: string; | ||
| } | ||
| /** | ||
| * WidthProvider HOC | ||
| * | ||
| * A Higher-Order Component that provides width measurement to grid layouts. | ||
| * This wraps any component and provides the container width as a prop. | ||
| */ | ||
| interface WidthProviderProps { | ||
| /** If true, will not render children until mounted */ | ||
| measureBeforeMount?: boolean; | ||
| /** Additional class name */ | ||
| className?: string; | ||
| /** Additional styles */ | ||
| style?: React__default.CSSProperties; | ||
| } | ||
| type WithWidthProps<P> = Omit<P, "width"> & WidthProviderProps; | ||
| /** | ||
| * WidthProvider - HOC that provides container width | ||
| * | ||
| * A simple HOC that provides facility for listening to container resizes. | ||
| * Wraps the provided component and passes down a `width` prop. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * import { GridLayout, WidthProvider } from 'react-grid-layout'; | ||
| * | ||
| * const GridLayoutWithWidth = WidthProvider(GridLayout); | ||
| * | ||
| * function MyGrid() { | ||
| * return ( | ||
| * <GridLayoutWithWidth cols={12} rowHeight={30}> | ||
| * <div key="a">a</div> | ||
| * </GridLayoutWithWidth> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function WidthProvider<P extends { | ||
| width: number; | ||
| }>(ComposedComponent: ComponentType<P>): ComponentType<WithWidthProps<P>>; | ||
| export { Breakpoint, Breakpoints, CompactType, Layout, LayoutItem, type LegacyReactGridLayoutProps, type LegacyResponsiveReactGridLayoutProps, ReactGridLayout, ResizeHandleAxis, ResponsiveReactGridLayout as Responsive, ResponsiveLayouts, ResponsiveReactGridLayout, WidthProvider, ReactGridLayout as default }; |
+163
| import * as react_jsx_runtime from 'react/jsx-runtime'; | ||
| import React__default, { ComponentType } from 'react'; | ||
| import { a as GridLayoutProps, b as ResponsiveGridLayoutProps } from './ResponsiveGridLayout-CH4s0tKj.js'; | ||
| import { L as Layout, a as LayoutItem, C as CompactType, d as ResizeHandleAxis, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.js'; | ||
| /** | ||
| * Legacy props interface for backwards compatibility with v1 API. | ||
| * These flat props are converted to composable interfaces internally. | ||
| */ | ||
| interface LegacyReactGridLayoutProps { | ||
| children: React__default.ReactNode; | ||
| width: number; | ||
| cols?: number; | ||
| rowHeight?: number; | ||
| maxRows?: number; | ||
| margin?: readonly [number, number]; | ||
| containerPadding?: readonly [number, number] | null; | ||
| layout?: Layout; | ||
| droppingItem?: LayoutItem; | ||
| compactType?: CompactType; | ||
| preventCollision?: boolean; | ||
| allowOverlap?: boolean; | ||
| /** @deprecated Use compactType instead */ | ||
| verticalCompact?: boolean; | ||
| isDraggable?: boolean; | ||
| isBounded?: boolean; | ||
| draggableHandle?: string; | ||
| draggableCancel?: string; | ||
| isResizable?: boolean; | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| resizeHandle?: React__default.ReactElement | ((axis: ResizeHandleAxis, ref: React__default.Ref<HTMLElement>) => React__default.ReactElement); | ||
| isDroppable?: boolean; | ||
| useCSSTransforms?: boolean; | ||
| transformScale?: number; | ||
| autoSize?: boolean; | ||
| className?: string; | ||
| style?: React__default.CSSProperties; | ||
| innerRef?: React__default.Ref<HTMLDivElement>; | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| onDragStart?: GridLayoutProps["onDragStart"]; | ||
| onDrag?: GridLayoutProps["onDrag"]; | ||
| onDragStop?: GridLayoutProps["onDragStop"]; | ||
| onResizeStart?: GridLayoutProps["onResizeStart"]; | ||
| onResize?: GridLayoutProps["onResize"]; | ||
| onResizeStop?: GridLayoutProps["onResizeStop"]; | ||
| onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void; | ||
| onDropDragOver?: (e: React__default.DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** | ||
| * ReactGridLayout - Legacy wrapper component | ||
| * | ||
| * Converts v1 flat props to v2 composable interfaces for backwards compatibility. | ||
| */ | ||
| declare function ReactGridLayout(props: LegacyReactGridLayoutProps): react_jsx_runtime.JSX.Element; | ||
| declare namespace ReactGridLayout { | ||
| var displayName: string; | ||
| } | ||
| /** | ||
| * Legacy props interface for backwards compatibility with v1 API. | ||
| * These flat props are converted to composable interfaces internally. | ||
| */ | ||
| interface LegacyResponsiveReactGridLayoutProps<B extends Breakpoint = string> { | ||
| children: React__default.ReactNode; | ||
| width: number; | ||
| breakpoint?: B; | ||
| breakpoints?: Breakpoints<B>; | ||
| cols?: Breakpoints<B>; | ||
| layouts?: ResponsiveLayouts<B>; | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void; | ||
| onWidthChange?: (containerWidth: number, margin: readonly [number, number], cols: number, containerPadding: readonly [number, number] | null) => void; | ||
| rowHeight?: number; | ||
| maxRows?: number; | ||
| margin?: readonly [number, number] | Partial<Record<B, readonly [number, number]>>; | ||
| containerPadding?: readonly [number, number] | Partial<Record<B, readonly [number, number] | null>> | null; | ||
| droppingItem?: LayoutItem; | ||
| compactType?: CompactType; | ||
| preventCollision?: boolean; | ||
| allowOverlap?: boolean; | ||
| /** @deprecated Use compactType instead */ | ||
| verticalCompact?: boolean; | ||
| isDraggable?: boolean; | ||
| isBounded?: boolean; | ||
| draggableHandle?: string; | ||
| draggableCancel?: string; | ||
| isResizable?: boolean; | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| resizeHandle?: React__default.ReactElement | ((axis: ResizeHandleAxis, ref: React__default.Ref<HTMLElement>) => React__default.ReactElement); | ||
| isDroppable?: boolean; | ||
| useCSSTransforms?: boolean; | ||
| transformScale?: number; | ||
| autoSize?: boolean; | ||
| className?: string; | ||
| style?: React__default.CSSProperties; | ||
| innerRef?: React__default.Ref<HTMLDivElement>; | ||
| onDragStart?: ResponsiveGridLayoutProps<B>["onDragStart"]; | ||
| onDrag?: ResponsiveGridLayoutProps<B>["onDrag"]; | ||
| onDragStop?: ResponsiveGridLayoutProps<B>["onDragStop"]; | ||
| onResizeStart?: ResponsiveGridLayoutProps<B>["onResizeStart"]; | ||
| onResize?: ResponsiveGridLayoutProps<B>["onResize"]; | ||
| onResizeStop?: ResponsiveGridLayoutProps<B>["onResizeStop"]; | ||
| onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void; | ||
| onDropDragOver?: (e: React__default.DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** | ||
| * ResponsiveReactGridLayout - Legacy wrapper component | ||
| * | ||
| * Converts v1 flat props to v2 composable interfaces for backwards compatibility. | ||
| */ | ||
| declare function ResponsiveReactGridLayout<B extends Breakpoint = string>(props: LegacyResponsiveReactGridLayoutProps<B>): react_jsx_runtime.JSX.Element; | ||
| declare namespace ResponsiveReactGridLayout { | ||
| var displayName: string; | ||
| } | ||
| /** | ||
| * WidthProvider HOC | ||
| * | ||
| * A Higher-Order Component that provides width measurement to grid layouts. | ||
| * This wraps any component and provides the container width as a prop. | ||
| */ | ||
| interface WidthProviderProps { | ||
| /** If true, will not render children until mounted */ | ||
| measureBeforeMount?: boolean; | ||
| /** Additional class name */ | ||
| className?: string; | ||
| /** Additional styles */ | ||
| style?: React__default.CSSProperties; | ||
| } | ||
| type WithWidthProps<P> = Omit<P, "width"> & WidthProviderProps; | ||
| /** | ||
| * WidthProvider - HOC that provides container width | ||
| * | ||
| * A simple HOC that provides facility for listening to container resizes. | ||
| * Wraps the provided component and passes down a `width` prop. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * import { GridLayout, WidthProvider } from 'react-grid-layout'; | ||
| * | ||
| * const GridLayoutWithWidth = WidthProvider(GridLayout); | ||
| * | ||
| * function MyGrid() { | ||
| * return ( | ||
| * <GridLayoutWithWidth cols={12} rowHeight={30}> | ||
| * <div key="a">a</div> | ||
| * </GridLayoutWithWidth> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function WidthProvider<P extends { | ||
| width: number; | ||
| }>(ComposedComponent: ComponentType<P>): ComponentType<WithWidthProps<P>>; | ||
| export { Breakpoint, Breakpoints, CompactType, Layout, LayoutItem, type LegacyReactGridLayoutProps, type LegacyResponsiveReactGridLayoutProps, ReactGridLayout, ResizeHandleAxis, ResponsiveReactGridLayout as Responsive, ResponsiveLayouts, ResponsiveReactGridLayout, WidthProvider, ReactGridLayout as default }; |
+319
| 'use strict'; | ||
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| var chunkBFTKGAP3_js = require('./chunk-BFTKGAP3.js'); | ||
| var chunk3WO4SAYB_js = require('./chunk-3WO4SAYB.js'); | ||
| require('./chunk-F6NQPYKT.js'); | ||
| var react = require('react'); | ||
| var jsxRuntime = require('react/jsx-runtime'); | ||
| var clsx = require('clsx'); | ||
| function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } | ||
| var clsx__default = /*#__PURE__*/_interopDefault(clsx); | ||
| function ReactGridLayout(props) { | ||
| const { | ||
| // Required | ||
| children, | ||
| width, | ||
| // Grid measurement | ||
| cols = 12, | ||
| rowHeight = 150, | ||
| maxRows = Infinity, | ||
| margin = [10, 10], | ||
| containerPadding = null, | ||
| // Layout data | ||
| layout, | ||
| droppingItem, | ||
| // Compaction | ||
| compactType: compactTypeProp, | ||
| preventCollision = false, | ||
| allowOverlap = false, | ||
| verticalCompact, | ||
| // Drag behavior | ||
| isDraggable = true, | ||
| isBounded = false, | ||
| draggableHandle, | ||
| draggableCancel, | ||
| // Resize behavior | ||
| isResizable = true, | ||
| resizeHandles = ["se"], | ||
| resizeHandle, | ||
| // Drop behavior | ||
| isDroppable = false, | ||
| // Position | ||
| useCSSTransforms = true, | ||
| transformScale = 1, | ||
| // Container props | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| // Callbacks | ||
| onLayoutChange, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver | ||
| } = props; | ||
| let compactType = compactTypeProp === void 0 ? "vertical" : compactTypeProp; | ||
| if (verticalCompact === false) { | ||
| if (process.env["NODE_ENV"] !== "production") { | ||
| console.warn( | ||
| '`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. Use `compactType`: "horizontal" | "vertical" | null.' | ||
| ); | ||
| } | ||
| compactType = null; | ||
| } | ||
| const gridConfig = { | ||
| cols, | ||
| rowHeight, | ||
| maxRows, | ||
| margin, | ||
| containerPadding | ||
| }; | ||
| const dragConfig = { | ||
| enabled: isDraggable, | ||
| bounded: isBounded, | ||
| handle: draggableHandle, | ||
| cancel: draggableCancel | ||
| }; | ||
| const resizeConfig = { | ||
| enabled: isResizable, | ||
| handles: resizeHandles, | ||
| handleComponent: resizeHandle | ||
| }; | ||
| const dropConfig = { | ||
| enabled: isDroppable | ||
| }; | ||
| let positionStrategy; | ||
| if (!useCSSTransforms) { | ||
| positionStrategy = chunk3WO4SAYB_js.absoluteStrategy; | ||
| } else if (transformScale !== 1) { | ||
| positionStrategy = chunk3WO4SAYB_js.createScaledStrategy(transformScale); | ||
| } else { | ||
| positionStrategy = chunk3WO4SAYB_js.transformStrategy; | ||
| } | ||
| const compactor = chunk3WO4SAYB_js.getCompactor(compactType, allowOverlap, preventCollision); | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| chunkBFTKGAP3_js.GridLayout, | ||
| { | ||
| width, | ||
| gridConfig, | ||
| dragConfig, | ||
| resizeConfig, | ||
| dropConfig, | ||
| positionStrategy, | ||
| compactor, | ||
| layout, | ||
| droppingItem, | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| onLayoutChange, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver, | ||
| children | ||
| } | ||
| ); | ||
| } | ||
| ReactGridLayout.displayName = "ReactGridLayout"; | ||
| var ReactGridLayout_default = ReactGridLayout; | ||
| function ResponsiveReactGridLayout(props) { | ||
| const { | ||
| // Required | ||
| children, | ||
| width, | ||
| // Responsive-specific | ||
| breakpoint, | ||
| breakpoints, | ||
| cols, | ||
| layouts, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange, | ||
| // Grid measurement | ||
| rowHeight, | ||
| maxRows, | ||
| margin, | ||
| containerPadding, | ||
| // Layout data | ||
| droppingItem, | ||
| // Compaction | ||
| compactType: compactTypeProp, | ||
| preventCollision = false, | ||
| allowOverlap = false, | ||
| verticalCompact, | ||
| // Drag behavior | ||
| isDraggable = true, | ||
| isBounded = false, | ||
| draggableHandle, | ||
| draggableCancel, | ||
| // Resize behavior | ||
| isResizable = true, | ||
| resizeHandles = ["se"], | ||
| resizeHandle, | ||
| // Drop behavior | ||
| isDroppable = false, | ||
| // Position | ||
| useCSSTransforms = true, | ||
| transformScale = 1, | ||
| // Container props | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| // Callbacks | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver | ||
| } = props; | ||
| let compactType = compactTypeProp === void 0 ? "vertical" : compactTypeProp; | ||
| if (verticalCompact === false) { | ||
| if (process.env["NODE_ENV"] !== "production") { | ||
| console.warn( | ||
| '`verticalCompact` on <ResponsiveReactGridLayout> is deprecated and will be removed soon. Use `compactType`: "horizontal" | "vertical" | null.' | ||
| ); | ||
| } | ||
| compactType = null; | ||
| } | ||
| const dragConfig = { | ||
| enabled: isDraggable, | ||
| bounded: isBounded, | ||
| handle: draggableHandle, | ||
| cancel: draggableCancel | ||
| }; | ||
| const resizeConfig = { | ||
| enabled: isResizable, | ||
| handles: resizeHandles, | ||
| handleComponent: resizeHandle | ||
| }; | ||
| const dropConfig = { | ||
| enabled: isDroppable | ||
| }; | ||
| let positionStrategy; | ||
| if (!useCSSTransforms) { | ||
| positionStrategy = chunk3WO4SAYB_js.absoluteStrategy; | ||
| } else if (transformScale !== 1) { | ||
| positionStrategy = chunk3WO4SAYB_js.createScaledStrategy(transformScale); | ||
| } else { | ||
| positionStrategy = chunk3WO4SAYB_js.transformStrategy; | ||
| } | ||
| const compactor = chunk3WO4SAYB_js.getCompactor(compactType, allowOverlap, preventCollision); | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| chunkBFTKGAP3_js.ResponsiveGridLayout, | ||
| { | ||
| width, | ||
| breakpoint, | ||
| breakpoints, | ||
| cols, | ||
| layouts, | ||
| rowHeight, | ||
| maxRows, | ||
| margin, | ||
| containerPadding, | ||
| compactor, | ||
| dragConfig, | ||
| resizeConfig, | ||
| dropConfig, | ||
| positionStrategy, | ||
| droppingItem, | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver, | ||
| children | ||
| } | ||
| ); | ||
| } | ||
| ResponsiveReactGridLayout.displayName = "ResponsiveReactGridLayout"; | ||
| var ResponsiveReactGridLayout_default = ResponsiveReactGridLayout; | ||
| var layoutClassName = "react-grid-layout"; | ||
| function WidthProvider(ComposedComponent) { | ||
| function WidthProviderWrapper(props) { | ||
| const { measureBeforeMount = false, className, style, ...rest } = props; | ||
| const [width, setWidth] = react.useState(1280); | ||
| const [mounted, setMounted] = react.useState(false); | ||
| const elementRef = react.useRef(null); | ||
| const resizeObserverRef = react.useRef(null); | ||
| react.useEffect(() => { | ||
| setMounted(true); | ||
| resizeObserverRef.current = new ResizeObserver((entries) => { | ||
| const node2 = elementRef.current; | ||
| if (node2 instanceof HTMLElement && entries[0]) { | ||
| const newWidth = entries[0].contentRect.width; | ||
| setWidth(newWidth); | ||
| } | ||
| }); | ||
| const node = elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| resizeObserverRef.current.observe(node); | ||
| } | ||
| return () => { | ||
| if (node instanceof HTMLElement && resizeObserverRef.current) { | ||
| resizeObserverRef.current.unobserve(node); | ||
| } | ||
| resizeObserverRef.current?.disconnect(); | ||
| }; | ||
| }, []); | ||
| if (measureBeforeMount && !mounted) { | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| "div", | ||
| { | ||
| className: clsx__default.default(className, layoutClassName), | ||
| style, | ||
| ref: elementRef | ||
| } | ||
| ); | ||
| } | ||
| return /* @__PURE__ */ jsxRuntime.jsx( | ||
| ComposedComponent, | ||
| { | ||
| innerRef: elementRef, | ||
| className, | ||
| style, | ||
| ...rest, | ||
| width | ||
| } | ||
| ); | ||
| } | ||
| WidthProviderWrapper.displayName = `WidthProvider(${ComposedComponent.displayName || ComposedComponent.name || "Component"})`; | ||
| return WidthProviderWrapper; | ||
| } | ||
| exports.ReactGridLayout = ReactGridLayout; | ||
| exports.Responsive = ResponsiveReactGridLayout_default; | ||
| exports.ResponsiveReactGridLayout = ResponsiveReactGridLayout; | ||
| exports.WidthProvider = WidthProvider; | ||
| exports.default = ReactGridLayout_default; | ||
| //# sourceMappingURL=legacy.js.map | ||
| //# sourceMappingURL=legacy.js.map |
| {"version":3,"sources":["../src/legacy/ReactGridLayout.tsx","../src/legacy/ResponsiveReactGridLayout.tsx","../src/react/components/WidthProvider.tsx"],"names":["absoluteStrategy","createScaledStrategy","transformStrategy","getCompactor","jsx","GridLayout","ResponsiveGridLayout","useState","useRef","useEffect","node","clsx"],"mappings":"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","file":"legacy.js","sourcesContent":["/**\n * Legacy ReactGridLayout wrapper\n *\n * This component wraps the new TypeScript GridLayout to provide\n * backwards compatibility with the v1 API by converting flat props\n * to the new composable interface format.\n */\n\nimport React from \"react\";\nimport {\n GridLayout,\n type GridLayoutProps\n} from \"../react/components/GridLayout.js\";\nimport type {\n Layout,\n LayoutItem,\n CompactType,\n ResizeHandleAxis,\n GridConfig,\n DragConfig,\n ResizeConfig,\n DropConfig,\n PositionStrategy\n} from \"../core/types.js\";\nimport { getCompactor } from \"../core/compactors.js\";\nimport {\n transformStrategy,\n absoluteStrategy,\n createScaledStrategy\n} from \"../core/position.js\";\n\n// ============================================================================\n// Legacy Props Interface\n// ============================================================================\n\n/**\n * Legacy props interface for backwards compatibility with v1 API.\n * These flat props are converted to composable interfaces internally.\n */\nexport interface LegacyReactGridLayoutProps {\n // Required\n children: React.ReactNode;\n width: number;\n\n // Grid measurement (→ gridConfig)\n cols?: number;\n rowHeight?: number;\n maxRows?: number;\n margin?: readonly [number, number];\n containerPadding?: readonly [number, number] | null;\n\n // Layout data\n layout?: Layout;\n droppingItem?: LayoutItem;\n\n // Compaction (→ compactor)\n compactType?: CompactType;\n preventCollision?: boolean;\n allowOverlap?: boolean;\n /** @deprecated Use compactType instead */\n verticalCompact?: boolean;\n\n // Drag behavior (→ dragConfig)\n isDraggable?: boolean;\n isBounded?: boolean;\n draggableHandle?: string;\n draggableCancel?: string;\n\n // Resize behavior (→ resizeConfig)\n isResizable?: boolean;\n resizeHandles?: ResizeHandleAxis[];\n resizeHandle?:\n | React.ReactElement\n | ((\n axis: ResizeHandleAxis,\n ref: React.Ref<HTMLElement>\n ) => React.ReactElement);\n\n // Drop behavior (→ dropConfig)\n isDroppable?: boolean;\n\n // Position (→ positionStrategy)\n useCSSTransforms?: boolean;\n transformScale?: number;\n\n // Container props (passed through)\n autoSize?: boolean;\n className?: string;\n style?: React.CSSProperties;\n innerRef?: React.Ref<HTMLDivElement>;\n\n // Callbacks (passed through)\n onLayoutChange?: (layout: Layout) => void;\n onDragStart?: GridLayoutProps[\"onDragStart\"];\n onDrag?: GridLayoutProps[\"onDrag\"];\n onDragStop?: GridLayoutProps[\"onDragStop\"];\n onResizeStart?: GridLayoutProps[\"onResizeStart\"];\n onResize?: GridLayoutProps[\"onResize\"];\n onResizeStop?: GridLayoutProps[\"onResizeStop\"];\n onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void;\n onDropDragOver?: (\n e: React.DragEvent\n ) => { w?: number; h?: number } | false | void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * ReactGridLayout - Legacy wrapper component\n *\n * Converts v1 flat props to v2 composable interfaces for backwards compatibility.\n */\nfunction ReactGridLayout(props: LegacyReactGridLayoutProps) {\n const {\n // Required\n children,\n width,\n\n // Grid measurement\n cols = 12,\n rowHeight = 150,\n maxRows = Infinity,\n margin = [10, 10],\n containerPadding = null,\n\n // Layout data\n layout,\n droppingItem,\n\n // Compaction\n compactType: compactTypeProp,\n preventCollision = false,\n allowOverlap = false,\n verticalCompact,\n\n // Drag behavior\n isDraggable = true,\n isBounded = false,\n draggableHandle,\n draggableCancel,\n\n // Resize behavior\n isResizable = true,\n resizeHandles = [\"se\"],\n resizeHandle,\n\n // Drop behavior\n isDroppable = false,\n\n // Position\n useCSSTransforms = true,\n transformScale = 1,\n\n // Container props\n autoSize,\n className,\n style,\n innerRef,\n\n // Callbacks\n onLayoutChange,\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize,\n onResizeStop,\n onDrop,\n onDropDragOver\n } = props;\n\n // Handle deprecated verticalCompact prop\n let compactType: CompactType =\n compactTypeProp === undefined ? \"vertical\" : compactTypeProp;\n if (verticalCompact === false) {\n if (process.env[\"NODE_ENV\"] !== \"production\") {\n console.warn(\n \"`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. \" +\n 'Use `compactType`: \"horizontal\" | \"vertical\" | null.'\n );\n }\n compactType = null;\n }\n\n // Convert flat props to composable interfaces\n\n const gridConfig: Partial<GridConfig> = {\n cols,\n rowHeight,\n maxRows,\n margin,\n containerPadding\n };\n\n const dragConfig: Partial<DragConfig> = {\n enabled: isDraggable,\n bounded: isBounded,\n handle: draggableHandle,\n cancel: draggableCancel\n };\n\n const resizeConfig: Partial<ResizeConfig> = {\n enabled: isResizable,\n handles: resizeHandles,\n handleComponent: resizeHandle\n };\n\n const dropConfig: Partial<DropConfig> = {\n enabled: isDroppable\n };\n\n // Build position strategy\n let positionStrategy: PositionStrategy;\n if (!useCSSTransforms) {\n positionStrategy = absoluteStrategy;\n } else if (transformScale !== 1) {\n positionStrategy = createScaledStrategy(transformScale);\n } else {\n positionStrategy = transformStrategy;\n }\n\n // Get compactor from type and options\n const compactor = getCompactor(compactType, allowOverlap, preventCollision);\n\n return (\n <GridLayout\n width={width}\n gridConfig={gridConfig}\n dragConfig={dragConfig}\n resizeConfig={resizeConfig}\n dropConfig={dropConfig}\n positionStrategy={positionStrategy}\n compactor={compactor}\n layout={layout}\n droppingItem={droppingItem}\n autoSize={autoSize}\n className={className}\n style={style}\n innerRef={innerRef}\n onLayoutChange={onLayoutChange}\n onDragStart={onDragStart}\n onDrag={onDrag}\n onDragStop={onDragStop}\n onResizeStart={onResizeStart}\n onResize={onResize}\n onResizeStop={onResizeStop}\n onDrop={onDrop}\n onDropDragOver={onDropDragOver}\n >\n {children}\n </GridLayout>\n );\n}\n\n// Static properties for backwards compatibility\nReactGridLayout.displayName = \"ReactGridLayout\";\n\nexport default ReactGridLayout;\nexport { ReactGridLayout };\n","/**\n * Legacy ResponsiveReactGridLayout wrapper\n *\n * This component wraps the new TypeScript ResponsiveGridLayout to provide\n * backwards compatibility with the v1 API by converting flat props\n * to the new composable interface format.\n */\n\nimport React from \"react\";\nimport {\n ResponsiveGridLayout,\n type ResponsiveGridLayoutProps\n} from \"../react/components/ResponsiveGridLayout.js\";\nimport type {\n Layout,\n LayoutItem,\n CompactType,\n Breakpoint,\n Breakpoints,\n ResponsiveLayouts,\n ResizeHandleAxis,\n DragConfig,\n ResizeConfig,\n DropConfig,\n PositionStrategy\n} from \"../core/types.js\";\nimport { getCompactor } from \"../core/compactors.js\";\nimport {\n transformStrategy,\n absoluteStrategy,\n createScaledStrategy\n} from \"../core/position.js\";\n\n// ============================================================================\n// Legacy Props Interface\n// ============================================================================\n\n/**\n * Legacy props interface for backwards compatibility with v1 API.\n * These flat props are converted to composable interfaces internally.\n */\nexport interface LegacyResponsiveReactGridLayoutProps<\n B extends Breakpoint = string\n> {\n // Required\n children: React.ReactNode;\n width: number;\n\n // Responsive-specific\n breakpoint?: B;\n breakpoints?: Breakpoints<B>;\n cols?: Breakpoints<B>;\n layouts?: ResponsiveLayouts<B>;\n onBreakpointChange?: (newBreakpoint: B, cols: number) => void;\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void;\n onWidthChange?: (\n containerWidth: number,\n margin: readonly [number, number],\n cols: number,\n containerPadding: readonly [number, number] | null\n ) => void;\n\n // Grid measurement\n rowHeight?: number;\n maxRows?: number;\n margin?:\n | readonly [number, number]\n | Partial<Record<B, readonly [number, number]>>;\n containerPadding?:\n | readonly [number, number]\n | Partial<Record<B, readonly [number, number] | null>>\n | null;\n\n // Layout data\n droppingItem?: LayoutItem;\n\n // Compaction (→ compactor)\n compactType?: CompactType;\n preventCollision?: boolean;\n allowOverlap?: boolean;\n /** @deprecated Use compactType instead */\n verticalCompact?: boolean;\n\n // Drag behavior (→ dragConfig)\n isDraggable?: boolean;\n isBounded?: boolean;\n draggableHandle?: string;\n draggableCancel?: string;\n\n // Resize behavior (→ resizeConfig)\n isResizable?: boolean;\n resizeHandles?: ResizeHandleAxis[];\n resizeHandle?:\n | React.ReactElement\n | ((\n axis: ResizeHandleAxis,\n ref: React.Ref<HTMLElement>\n ) => React.ReactElement);\n\n // Drop behavior (→ dropConfig)\n isDroppable?: boolean;\n\n // Position (→ positionStrategy)\n useCSSTransforms?: boolean;\n transformScale?: number;\n\n // Container props (passed through)\n autoSize?: boolean;\n className?: string;\n style?: React.CSSProperties;\n innerRef?: React.Ref<HTMLDivElement>;\n\n // Callbacks (passed through)\n onDragStart?: ResponsiveGridLayoutProps<B>[\"onDragStart\"];\n onDrag?: ResponsiveGridLayoutProps<B>[\"onDrag\"];\n onDragStop?: ResponsiveGridLayoutProps<B>[\"onDragStop\"];\n onResizeStart?: ResponsiveGridLayoutProps<B>[\"onResizeStart\"];\n onResize?: ResponsiveGridLayoutProps<B>[\"onResize\"];\n onResizeStop?: ResponsiveGridLayoutProps<B>[\"onResizeStop\"];\n onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void;\n onDropDragOver?: (\n e: React.DragEvent\n ) => { w?: number; h?: number } | false | void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * ResponsiveReactGridLayout - Legacy wrapper component\n *\n * Converts v1 flat props to v2 composable interfaces for backwards compatibility.\n */\nfunction ResponsiveReactGridLayout<B extends Breakpoint = string>(\n props: LegacyResponsiveReactGridLayoutProps<B>\n) {\n const {\n // Required\n children,\n width,\n\n // Responsive-specific\n breakpoint,\n breakpoints,\n cols,\n layouts,\n onBreakpointChange,\n onLayoutChange,\n onWidthChange,\n\n // Grid measurement\n rowHeight,\n maxRows,\n margin,\n containerPadding,\n\n // Layout data\n droppingItem,\n\n // Compaction\n compactType: compactTypeProp,\n preventCollision = false,\n allowOverlap = false,\n verticalCompact,\n\n // Drag behavior\n isDraggable = true,\n isBounded = false,\n draggableHandle,\n draggableCancel,\n\n // Resize behavior\n isResizable = true,\n resizeHandles = [\"se\"],\n resizeHandle,\n\n // Drop behavior\n isDroppable = false,\n\n // Position\n useCSSTransforms = true,\n transformScale = 1,\n\n // Container props\n autoSize,\n className,\n style,\n innerRef,\n\n // Callbacks\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize,\n onResizeStop,\n onDrop,\n onDropDragOver\n } = props;\n\n // Handle deprecated verticalCompact prop\n let compactType: CompactType =\n compactTypeProp === undefined ? \"vertical\" : compactTypeProp;\n if (verticalCompact === false) {\n if (process.env[\"NODE_ENV\"] !== \"production\") {\n console.warn(\n \"`verticalCompact` on <ResponsiveReactGridLayout> is deprecated and will be removed soon. \" +\n 'Use `compactType`: \"horizontal\" | \"vertical\" | null.'\n );\n }\n compactType = null;\n }\n\n // Convert flat props to composable interfaces\n\n const dragConfig: Partial<DragConfig> = {\n enabled: isDraggable,\n bounded: isBounded,\n handle: draggableHandle,\n cancel: draggableCancel\n };\n\n const resizeConfig: Partial<ResizeConfig> = {\n enabled: isResizable,\n handles: resizeHandles,\n handleComponent: resizeHandle\n };\n\n const dropConfig: Partial<DropConfig> = {\n enabled: isDroppable\n };\n\n // Build position strategy\n let positionStrategy: PositionStrategy;\n if (!useCSSTransforms) {\n positionStrategy = absoluteStrategy;\n } else if (transformScale !== 1) {\n positionStrategy = createScaledStrategy(transformScale);\n } else {\n positionStrategy = transformStrategy;\n }\n\n // Get compactor from type and options\n const compactor = getCompactor(compactType, allowOverlap, preventCollision);\n\n return (\n <ResponsiveGridLayout<B>\n width={width}\n breakpoint={breakpoint}\n breakpoints={breakpoints}\n cols={cols}\n layouts={layouts}\n rowHeight={rowHeight}\n maxRows={maxRows}\n margin={margin}\n containerPadding={containerPadding}\n compactor={compactor}\n dragConfig={dragConfig}\n resizeConfig={resizeConfig}\n dropConfig={dropConfig}\n positionStrategy={positionStrategy}\n droppingItem={droppingItem}\n autoSize={autoSize}\n className={className}\n style={style}\n innerRef={innerRef}\n onBreakpointChange={onBreakpointChange}\n onLayoutChange={onLayoutChange}\n onWidthChange={onWidthChange}\n onDragStart={onDragStart}\n onDrag={onDrag}\n onDragStop={onDragStop}\n onResizeStart={onResizeStart}\n onResize={onResize}\n onResizeStop={onResizeStop}\n onDrop={onDrop}\n onDropDragOver={onDropDragOver}\n >\n {children}\n </ResponsiveGridLayout>\n );\n}\n\n// Static properties for backwards compatibility\nResponsiveReactGridLayout.displayName = \"ResponsiveReactGridLayout\";\n\nexport default ResponsiveReactGridLayout;\nexport { ResponsiveReactGridLayout, ResponsiveReactGridLayout as Responsive };\n","/**\n * WidthProvider HOC\n *\n * A Higher-Order Component that provides width measurement to grid layouts.\n * This wraps any component and provides the container width as a prop.\n */\n\nimport React, { useState, useRef, useEffect, type ComponentType } from \"react\";\nimport clsx from \"clsx\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidthProviderProps {\n /** If true, will not render children until mounted */\n measureBeforeMount?: boolean;\n /** Additional class name */\n className?: string;\n /** Additional styles */\n style?: React.CSSProperties;\n}\n\ntype WithWidthProps<P> = Omit<P, \"width\"> & WidthProviderProps;\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst layoutClassName = \"react-grid-layout\";\n\n// ============================================================================\n// WidthProvider HOC\n// ============================================================================\n\n/**\n * WidthProvider - HOC that provides container width\n *\n * A simple HOC that provides facility for listening to container resizes.\n * Wraps the provided component and passes down a `width` prop.\n *\n * @example\n * ```tsx\n * import { GridLayout, WidthProvider } from 'react-grid-layout';\n *\n * const GridLayoutWithWidth = WidthProvider(GridLayout);\n *\n * function MyGrid() {\n * return (\n * <GridLayoutWithWidth cols={12} rowHeight={30}>\n * <div key=\"a\">a</div>\n * </GridLayoutWithWidth>\n * );\n * }\n * ```\n */\nexport function WidthProvider<P extends { width: number }>(\n ComposedComponent: ComponentType<P>\n): ComponentType<WithWidthProps<P>> {\n function WidthProviderWrapper(props: WithWidthProps<P>) {\n const { measureBeforeMount = false, className, style, ...rest } = props;\n\n const [width, setWidth] = useState(1280);\n const [mounted, setMounted] = useState(false);\n const elementRef = useRef<HTMLDivElement>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n useEffect(() => {\n setMounted(true);\n\n // Set up ResizeObserver\n resizeObserverRef.current = new ResizeObserver(entries => {\n const node = elementRef.current;\n if (node instanceof HTMLElement && entries[0]) {\n const newWidth = entries[0].contentRect.width;\n setWidth(newWidth);\n }\n });\n\n const node = elementRef.current;\n if (node instanceof HTMLElement) {\n resizeObserverRef.current.observe(node);\n }\n\n return () => {\n if (node instanceof HTMLElement && resizeObserverRef.current) {\n resizeObserverRef.current.unobserve(node);\n }\n resizeObserverRef.current?.disconnect();\n };\n }, []);\n\n // If measureBeforeMount is true and not yet mounted, render placeholder\n if (measureBeforeMount && !mounted) {\n return (\n <div\n className={clsx(className, layoutClassName)}\n style={style}\n ref={elementRef}\n />\n );\n }\n\n return (\n <ComposedComponent\n innerRef={elementRef}\n className={className}\n style={style}\n {...(rest as unknown as P)}\n width={width}\n />\n );\n }\n\n WidthProviderWrapper.displayName = `WidthProvider(${ComposedComponent.displayName || ComposedComponent.name || \"Component\"})`;\n\n return WidthProviderWrapper;\n}\n\nexport default WidthProvider;\n"]} |
+307
| import { GridLayout, ResponsiveGridLayout } from './chunk-R35HZZTA.mjs'; | ||
| import { createScaledStrategy, getCompactor, absoluteStrategy, transformStrategy } from './chunk-4HNUMWQK.mjs'; | ||
| import './chunk-2KUHNJXF.mjs'; | ||
| import { useState, useRef, useEffect } from 'react'; | ||
| import { jsx } from 'react/jsx-runtime'; | ||
| import clsx from 'clsx'; | ||
| function ReactGridLayout(props) { | ||
| const { | ||
| // Required | ||
| children, | ||
| width, | ||
| // Grid measurement | ||
| cols = 12, | ||
| rowHeight = 150, | ||
| maxRows = Infinity, | ||
| margin = [10, 10], | ||
| containerPadding = null, | ||
| // Layout data | ||
| layout, | ||
| droppingItem, | ||
| // Compaction | ||
| compactType: compactTypeProp, | ||
| preventCollision = false, | ||
| allowOverlap = false, | ||
| verticalCompact, | ||
| // Drag behavior | ||
| isDraggable = true, | ||
| isBounded = false, | ||
| draggableHandle, | ||
| draggableCancel, | ||
| // Resize behavior | ||
| isResizable = true, | ||
| resizeHandles = ["se"], | ||
| resizeHandle, | ||
| // Drop behavior | ||
| isDroppable = false, | ||
| // Position | ||
| useCSSTransforms = true, | ||
| transformScale = 1, | ||
| // Container props | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| // Callbacks | ||
| onLayoutChange, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver | ||
| } = props; | ||
| let compactType = compactTypeProp === void 0 ? "vertical" : compactTypeProp; | ||
| if (verticalCompact === false) { | ||
| if (process.env["NODE_ENV"] !== "production") { | ||
| console.warn( | ||
| '`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. Use `compactType`: "horizontal" | "vertical" | null.' | ||
| ); | ||
| } | ||
| compactType = null; | ||
| } | ||
| const gridConfig = { | ||
| cols, | ||
| rowHeight, | ||
| maxRows, | ||
| margin, | ||
| containerPadding | ||
| }; | ||
| const dragConfig = { | ||
| enabled: isDraggable, | ||
| bounded: isBounded, | ||
| handle: draggableHandle, | ||
| cancel: draggableCancel | ||
| }; | ||
| const resizeConfig = { | ||
| enabled: isResizable, | ||
| handles: resizeHandles, | ||
| handleComponent: resizeHandle | ||
| }; | ||
| const dropConfig = { | ||
| enabled: isDroppable | ||
| }; | ||
| let positionStrategy; | ||
| if (!useCSSTransforms) { | ||
| positionStrategy = absoluteStrategy; | ||
| } else if (transformScale !== 1) { | ||
| positionStrategy = createScaledStrategy(transformScale); | ||
| } else { | ||
| positionStrategy = transformStrategy; | ||
| } | ||
| const compactor = getCompactor(compactType, allowOverlap, preventCollision); | ||
| return /* @__PURE__ */ jsx( | ||
| GridLayout, | ||
| { | ||
| width, | ||
| gridConfig, | ||
| dragConfig, | ||
| resizeConfig, | ||
| dropConfig, | ||
| positionStrategy, | ||
| compactor, | ||
| layout, | ||
| droppingItem, | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| onLayoutChange, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver, | ||
| children | ||
| } | ||
| ); | ||
| } | ||
| ReactGridLayout.displayName = "ReactGridLayout"; | ||
| var ReactGridLayout_default = ReactGridLayout; | ||
| function ResponsiveReactGridLayout(props) { | ||
| const { | ||
| // Required | ||
| children, | ||
| width, | ||
| // Responsive-specific | ||
| breakpoint, | ||
| breakpoints, | ||
| cols, | ||
| layouts, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange, | ||
| // Grid measurement | ||
| rowHeight, | ||
| maxRows, | ||
| margin, | ||
| containerPadding, | ||
| // Layout data | ||
| droppingItem, | ||
| // Compaction | ||
| compactType: compactTypeProp, | ||
| preventCollision = false, | ||
| allowOverlap = false, | ||
| verticalCompact, | ||
| // Drag behavior | ||
| isDraggable = true, | ||
| isBounded = false, | ||
| draggableHandle, | ||
| draggableCancel, | ||
| // Resize behavior | ||
| isResizable = true, | ||
| resizeHandles = ["se"], | ||
| resizeHandle, | ||
| // Drop behavior | ||
| isDroppable = false, | ||
| // Position | ||
| useCSSTransforms = true, | ||
| transformScale = 1, | ||
| // Container props | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| // Callbacks | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver | ||
| } = props; | ||
| let compactType = compactTypeProp === void 0 ? "vertical" : compactTypeProp; | ||
| if (verticalCompact === false) { | ||
| if (process.env["NODE_ENV"] !== "production") { | ||
| console.warn( | ||
| '`verticalCompact` on <ResponsiveReactGridLayout> is deprecated and will be removed soon. Use `compactType`: "horizontal" | "vertical" | null.' | ||
| ); | ||
| } | ||
| compactType = null; | ||
| } | ||
| const dragConfig = { | ||
| enabled: isDraggable, | ||
| bounded: isBounded, | ||
| handle: draggableHandle, | ||
| cancel: draggableCancel | ||
| }; | ||
| const resizeConfig = { | ||
| enabled: isResizable, | ||
| handles: resizeHandles, | ||
| handleComponent: resizeHandle | ||
| }; | ||
| const dropConfig = { | ||
| enabled: isDroppable | ||
| }; | ||
| let positionStrategy; | ||
| if (!useCSSTransforms) { | ||
| positionStrategy = absoluteStrategy; | ||
| } else if (transformScale !== 1) { | ||
| positionStrategy = createScaledStrategy(transformScale); | ||
| } else { | ||
| positionStrategy = transformStrategy; | ||
| } | ||
| const compactor = getCompactor(compactType, allowOverlap, preventCollision); | ||
| return /* @__PURE__ */ jsx( | ||
| ResponsiveGridLayout, | ||
| { | ||
| width, | ||
| breakpoint, | ||
| breakpoints, | ||
| cols, | ||
| layouts, | ||
| rowHeight, | ||
| maxRows, | ||
| margin, | ||
| containerPadding, | ||
| compactor, | ||
| dragConfig, | ||
| resizeConfig, | ||
| dropConfig, | ||
| positionStrategy, | ||
| droppingItem, | ||
| autoSize, | ||
| className, | ||
| style, | ||
| innerRef, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| onDrop, | ||
| onDropDragOver, | ||
| children | ||
| } | ||
| ); | ||
| } | ||
| ResponsiveReactGridLayout.displayName = "ResponsiveReactGridLayout"; | ||
| var ResponsiveReactGridLayout_default = ResponsiveReactGridLayout; | ||
| var layoutClassName = "react-grid-layout"; | ||
| function WidthProvider(ComposedComponent) { | ||
| function WidthProviderWrapper(props) { | ||
| const { measureBeforeMount = false, className, style, ...rest } = props; | ||
| const [width, setWidth] = useState(1280); | ||
| const [mounted, setMounted] = useState(false); | ||
| const elementRef = useRef(null); | ||
| const resizeObserverRef = useRef(null); | ||
| useEffect(() => { | ||
| setMounted(true); | ||
| resizeObserverRef.current = new ResizeObserver((entries) => { | ||
| const node2 = elementRef.current; | ||
| if (node2 instanceof HTMLElement && entries[0]) { | ||
| const newWidth = entries[0].contentRect.width; | ||
| setWidth(newWidth); | ||
| } | ||
| }); | ||
| const node = elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| resizeObserverRef.current.observe(node); | ||
| } | ||
| return () => { | ||
| if (node instanceof HTMLElement && resizeObserverRef.current) { | ||
| resizeObserverRef.current.unobserve(node); | ||
| } | ||
| resizeObserverRef.current?.disconnect(); | ||
| }; | ||
| }, []); | ||
| if (measureBeforeMount && !mounted) { | ||
| return /* @__PURE__ */ jsx( | ||
| "div", | ||
| { | ||
| className: clsx(className, layoutClassName), | ||
| style, | ||
| ref: elementRef | ||
| } | ||
| ); | ||
| } | ||
| return /* @__PURE__ */ jsx( | ||
| ComposedComponent, | ||
| { | ||
| innerRef: elementRef, | ||
| className, | ||
| style, | ||
| ...rest, | ||
| width | ||
| } | ||
| ); | ||
| } | ||
| WidthProviderWrapper.displayName = `WidthProvider(${ComposedComponent.displayName || ComposedComponent.name || "Component"})`; | ||
| return WidthProviderWrapper; | ||
| } | ||
| export { ReactGridLayout, ResponsiveReactGridLayout_default as Responsive, ResponsiveReactGridLayout, WidthProvider, ReactGridLayout_default as default }; | ||
| //# sourceMappingURL=legacy.mjs.map | ||
| //# sourceMappingURL=legacy.mjs.map |
| {"version":3,"sources":["../src/legacy/ReactGridLayout.tsx","../src/legacy/ResponsiveReactGridLayout.tsx","../src/react/components/WidthProvider.tsx"],"names":["jsx","node"],"mappings":";;;;;;;AAkHA,SAAS,gBAAgB,KAAA,EAAmC;AAC1D,EAAA,MAAM;AAAA;AAAA,IAEJ,QAAA;AAAA,IACA,KAAA;AAAA;AAAA,IAGA,IAAA,GAAO,EAAA;AAAA,IACP,SAAA,GAAY,GAAA;AAAA,IACZ,OAAA,GAAU,QAAA;AAAA,IACV,MAAA,GAAS,CAAC,EAAA,EAAI,EAAE,CAAA;AAAA,IAChB,gBAAA,GAAmB,IAAA;AAAA;AAAA,IAGnB,MAAA;AAAA,IACA,YAAA;AAAA;AAAA,IAGA,WAAA,EAAa,eAAA;AAAA,IACb,gBAAA,GAAmB,KAAA;AAAA,IACnB,YAAA,GAAe,KAAA;AAAA,IACf,eAAA;AAAA;AAAA,IAGA,WAAA,GAAc,IAAA;AAAA,IACd,SAAA,GAAY,KAAA;AAAA,IACZ,eAAA;AAAA,IACA,eAAA;AAAA;AAAA,IAGA,WAAA,GAAc,IAAA;AAAA,IACd,aAAA,GAAgB,CAAC,IAAI,CAAA;AAAA,IACrB,YAAA;AAAA;AAAA,IAGA,WAAA,GAAc,KAAA;AAAA;AAAA,IAGd,gBAAA,GAAmB,IAAA;AAAA,IACnB,cAAA,GAAiB,CAAA;AAAA;AAAA,IAGjB,QAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA;AAAA,IAGA,cAAA;AAAA,IACA,WAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AAGJ,EAAA,IAAI,WAAA,GACF,eAAA,KAAoB,MAAA,GAAY,UAAA,GAAa,eAAA;AAC/C,EAAA,IAAI,oBAAoB,KAAA,EAAO;AAC7B,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,KAAM,YAAA,EAAc;AAC5C,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN;AAAA,OAEF;AAAA,IACF;AACA,IAAA,WAAA,GAAc,IAAA;AAAA,EAChB;AAIA,EAAA,MAAM,UAAA,GAAkC;AAAA,IACtC,IAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,UAAA,GAAkC;AAAA,IACtC,OAAA,EAAS,WAAA;AAAA,IACT,OAAA,EAAS,SAAA;AAAA,IACT,MAAA,EAAQ,eAAA;AAAA,IACR,MAAA,EAAQ;AAAA,GACV;AAEA,EAAA,MAAM,YAAA,GAAsC;AAAA,IAC1C,OAAA,EAAS,WAAA;AAAA,IACT,OAAA,EAAS,aAAA;AAAA,IACT,eAAA,EAAiB;AAAA,GACnB;AAEA,EAAA,MAAM,UAAA,GAAkC;AAAA,IACtC,OAAA,EAAS;AAAA,GACX;AAGA,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,IAAA,gBAAA,GAAmB,gBAAA;AAAA,EACrB,CAAA,MAAA,IAAW,mBAAmB,CAAA,EAAG;AAC/B,IAAA,gBAAA,GAAmB,qBAAqB,cAAc,CAAA;AAAA,EACxD,CAAA,MAAO;AACL,IAAA,gBAAA,GAAmB,iBAAA;AAAA,EACrB;AAGA,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,WAAA,EAAa,YAAA,EAAc,gBAAgB,CAAA;AAE1E,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,gBAAA;AAAA,MACA,SAAA;AAAA,MACA,MAAA;AAAA,MACA,YAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA,WAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA;AAAA,MACA,cAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAGA,eAAA,CAAgB,WAAA,GAAc,iBAAA;AAE9B,IAAO,uBAAA,GAAQ;AC7Hf,SAAS,0BACP,KAAA,EACA;AACA,EAAA,MAAM;AAAA;AAAA,IAEJ,QAAA;AAAA,IACA,KAAA;AAAA;AAAA,IAGA,UAAA;AAAA,IACA,WAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA,kBAAA;AAAA,IACA,cAAA;AAAA,IACA,aAAA;AAAA;AAAA,IAGA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,gBAAA;AAAA;AAAA,IAGA,YAAA;AAAA;AAAA,IAGA,WAAA,EAAa,eAAA;AAAA,IACb,gBAAA,GAAmB,KAAA;AAAA,IACnB,YAAA,GAAe,KAAA;AAAA,IACf,eAAA;AAAA;AAAA,IAGA,WAAA,GAAc,IAAA;AAAA,IACd,SAAA,GAAY,KAAA;AAAA,IACZ,eAAA;AAAA,IACA,eAAA;AAAA;AAAA,IAGA,WAAA,GAAc,IAAA;AAAA,IACd,aAAA,GAAgB,CAAC,IAAI,CAAA;AAAA,IACrB,YAAA;AAAA;AAAA,IAGA,WAAA,GAAc,KAAA;AAAA;AAAA,IAGd,gBAAA,GAAmB,IAAA;AAAA,IACnB,cAAA,GAAiB,CAAA;AAAA;AAAA,IAGjB,QAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA;AAAA,IAGA,WAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AAGJ,EAAA,IAAI,WAAA,GACF,eAAA,KAAoB,MAAA,GAAY,UAAA,GAAa,eAAA;AAC/C,EAAA,IAAI,oBAAoB,KAAA,EAAO;AAC7B,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,KAAM,YAAA,EAAc;AAC5C,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN;AAAA,OAEF;AAAA,IACF;AACA,IAAA,WAAA,GAAc,IAAA;AAAA,EAChB;AAIA,EAAA,MAAM,UAAA,GAAkC;AAAA,IACtC,OAAA,EAAS,WAAA;AAAA,IACT,OAAA,EAAS,SAAA;AAAA,IACT,MAAA,EAAQ,eAAA;AAAA,IACR,MAAA,EAAQ;AAAA,GACV;AAEA,EAAA,MAAM,YAAA,GAAsC;AAAA,IAC1C,OAAA,EAAS,WAAA;AAAA,IACT,OAAA,EAAS,aAAA;AAAA,IACT,eAAA,EAAiB;AAAA,GACnB;AAEA,EAAA,MAAM,UAAA,GAAkC;AAAA,IACtC,OAAA,EAAS;AAAA,GACX;AAGA,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,IAAA,gBAAA,GAAmB,gBAAA;AAAA,EACrB,CAAA,MAAA,IAAW,mBAAmB,CAAA,EAAG;AAC/B,IAAA,gBAAA,GAAmB,qBAAqB,cAAc,CAAA;AAAA,EACxD,CAAA,MAAO;AACL,IAAA,gBAAA,GAAmB,iBAAA;AAAA,EACrB;AAGA,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,WAAA,EAAa,YAAA,EAAc,gBAAgB,CAAA;AAE1E,EAAA,uBACEA,GAAAA;AAAA,IAAC,oBAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA,IAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA;AAAA,MACA,gBAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,gBAAA;AAAA,MACA,YAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,kBAAA;AAAA,MACA,cAAA;AAAA,MACA,aAAA;AAAA,MACA,WAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA;AAAA,MACA,cAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAGA,yBAAA,CAA0B,WAAA,GAAc,2BAAA;AAExC,IAAO,iCAAA,GAAQ;AClQf,IAAM,eAAA,GAAkB,mBAAA;AA2BjB,SAAS,cACd,iBAAA,EACkC;AAClC,EAAA,SAAS,qBAAqB,KAAA,EAA0B;AACtD,IAAA,MAAM,EAAE,kBAAA,GAAqB,KAAA,EAAO,WAAW,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AAElE,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,IAAI,CAAA;AACvC,IAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,IAAA,MAAM,UAAA,GAAa,OAAuB,IAAI,CAAA;AAC9C,IAAA,MAAM,iBAAA,GAAoB,OAA8B,IAAI,CAAA;AAE5D,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,UAAA,CAAW,IAAI,CAAA;AAGf,MAAA,iBAAA,CAAkB,OAAA,GAAU,IAAI,cAAA,CAAe,CAAA,OAAA,KAAW;AACxD,QAAA,MAAMC,QAAO,UAAA,CAAW,OAAA;AACxB,QAAA,IAAIA,KAAAA,YAAgB,WAAA,IAAe,OAAA,CAAQ,CAAC,CAAA,EAAG;AAC7C,UAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,CAAC,CAAA,CAAE,WAAA,CAAY,KAAA;AACxC,UAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,QACnB;AAAA,MACF,CAAC,CAAA;AAED,MAAA,MAAM,OAAO,UAAA,CAAW,OAAA;AACxB,MAAA,IAAI,gBAAgB,WAAA,EAAa;AAC/B,QAAA,iBAAA,CAAkB,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAAA,MACxC;AAEA,MAAA,OAAO,MAAM;AACX,QAAA,IAAI,IAAA,YAAgB,WAAA,IAAe,iBAAA,CAAkB,OAAA,EAAS;AAC5D,UAAA,iBAAA,CAAkB,OAAA,CAAQ,UAAU,IAAI,CAAA;AAAA,QAC1C;AACA,QAAA,iBAAA,CAAkB,SAAS,UAAA,EAAW;AAAA,MACxC,CAAA;AAAA,IACF,CAAA,EAAG,EAAE,CAAA;AAGL,IAAA,IAAI,kBAAA,IAAsB,CAAC,OAAA,EAAS;AAClC,MAAA,uBACED,GAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,IAAA,CAAK,SAAA,EAAW,eAAe,CAAA;AAAA,UAC1C,KAAA;AAAA,UACA,GAAA,EAAK;AAAA;AAAA,OACP;AAAA,IAEJ;AAEA,IAAA,uBACEA,GAAAA;AAAA,MAAC,iBAAA;AAAA,MAAA;AAAA,QACC,QAAA,EAAU,UAAA;AAAA,QACV,SAAA;AAAA,QACA,KAAA;AAAA,QACC,GAAI,IAAA;AAAA,QACL;AAAA;AAAA,KACF;AAAA,EAEJ;AAEA,EAAA,oBAAA,CAAqB,cAAc,CAAA,cAAA,EAAiB,iBAAA,CAAkB,WAAA,IAAe,iBAAA,CAAkB,QAAQ,WAAW,CAAA,CAAA,CAAA;AAE1H,EAAA,OAAO,oBAAA;AACT","file":"legacy.mjs","sourcesContent":["/**\n * Legacy ReactGridLayout wrapper\n *\n * This component wraps the new TypeScript GridLayout to provide\n * backwards compatibility with the v1 API by converting flat props\n * to the new composable interface format.\n */\n\nimport React from \"react\";\nimport {\n GridLayout,\n type GridLayoutProps\n} from \"../react/components/GridLayout.js\";\nimport type {\n Layout,\n LayoutItem,\n CompactType,\n ResizeHandleAxis,\n GridConfig,\n DragConfig,\n ResizeConfig,\n DropConfig,\n PositionStrategy\n} from \"../core/types.js\";\nimport { getCompactor } from \"../core/compactors.js\";\nimport {\n transformStrategy,\n absoluteStrategy,\n createScaledStrategy\n} from \"../core/position.js\";\n\n// ============================================================================\n// Legacy Props Interface\n// ============================================================================\n\n/**\n * Legacy props interface for backwards compatibility with v1 API.\n * These flat props are converted to composable interfaces internally.\n */\nexport interface LegacyReactGridLayoutProps {\n // Required\n children: React.ReactNode;\n width: number;\n\n // Grid measurement (→ gridConfig)\n cols?: number;\n rowHeight?: number;\n maxRows?: number;\n margin?: readonly [number, number];\n containerPadding?: readonly [number, number] | null;\n\n // Layout data\n layout?: Layout;\n droppingItem?: LayoutItem;\n\n // Compaction (→ compactor)\n compactType?: CompactType;\n preventCollision?: boolean;\n allowOverlap?: boolean;\n /** @deprecated Use compactType instead */\n verticalCompact?: boolean;\n\n // Drag behavior (→ dragConfig)\n isDraggable?: boolean;\n isBounded?: boolean;\n draggableHandle?: string;\n draggableCancel?: string;\n\n // Resize behavior (→ resizeConfig)\n isResizable?: boolean;\n resizeHandles?: ResizeHandleAxis[];\n resizeHandle?:\n | React.ReactElement\n | ((\n axis: ResizeHandleAxis,\n ref: React.Ref<HTMLElement>\n ) => React.ReactElement);\n\n // Drop behavior (→ dropConfig)\n isDroppable?: boolean;\n\n // Position (→ positionStrategy)\n useCSSTransforms?: boolean;\n transformScale?: number;\n\n // Container props (passed through)\n autoSize?: boolean;\n className?: string;\n style?: React.CSSProperties;\n innerRef?: React.Ref<HTMLDivElement>;\n\n // Callbacks (passed through)\n onLayoutChange?: (layout: Layout) => void;\n onDragStart?: GridLayoutProps[\"onDragStart\"];\n onDrag?: GridLayoutProps[\"onDrag\"];\n onDragStop?: GridLayoutProps[\"onDragStop\"];\n onResizeStart?: GridLayoutProps[\"onResizeStart\"];\n onResize?: GridLayoutProps[\"onResize\"];\n onResizeStop?: GridLayoutProps[\"onResizeStop\"];\n onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void;\n onDropDragOver?: (\n e: React.DragEvent\n ) => { w?: number; h?: number } | false | void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * ReactGridLayout - Legacy wrapper component\n *\n * Converts v1 flat props to v2 composable interfaces for backwards compatibility.\n */\nfunction ReactGridLayout(props: LegacyReactGridLayoutProps) {\n const {\n // Required\n children,\n width,\n\n // Grid measurement\n cols = 12,\n rowHeight = 150,\n maxRows = Infinity,\n margin = [10, 10],\n containerPadding = null,\n\n // Layout data\n layout,\n droppingItem,\n\n // Compaction\n compactType: compactTypeProp,\n preventCollision = false,\n allowOverlap = false,\n verticalCompact,\n\n // Drag behavior\n isDraggable = true,\n isBounded = false,\n draggableHandle,\n draggableCancel,\n\n // Resize behavior\n isResizable = true,\n resizeHandles = [\"se\"],\n resizeHandle,\n\n // Drop behavior\n isDroppable = false,\n\n // Position\n useCSSTransforms = true,\n transformScale = 1,\n\n // Container props\n autoSize,\n className,\n style,\n innerRef,\n\n // Callbacks\n onLayoutChange,\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize,\n onResizeStop,\n onDrop,\n onDropDragOver\n } = props;\n\n // Handle deprecated verticalCompact prop\n let compactType: CompactType =\n compactTypeProp === undefined ? \"vertical\" : compactTypeProp;\n if (verticalCompact === false) {\n if (process.env[\"NODE_ENV\"] !== \"production\") {\n console.warn(\n \"`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. \" +\n 'Use `compactType`: \"horizontal\" | \"vertical\" | null.'\n );\n }\n compactType = null;\n }\n\n // Convert flat props to composable interfaces\n\n const gridConfig: Partial<GridConfig> = {\n cols,\n rowHeight,\n maxRows,\n margin,\n containerPadding\n };\n\n const dragConfig: Partial<DragConfig> = {\n enabled: isDraggable,\n bounded: isBounded,\n handle: draggableHandle,\n cancel: draggableCancel\n };\n\n const resizeConfig: Partial<ResizeConfig> = {\n enabled: isResizable,\n handles: resizeHandles,\n handleComponent: resizeHandle\n };\n\n const dropConfig: Partial<DropConfig> = {\n enabled: isDroppable\n };\n\n // Build position strategy\n let positionStrategy: PositionStrategy;\n if (!useCSSTransforms) {\n positionStrategy = absoluteStrategy;\n } else if (transformScale !== 1) {\n positionStrategy = createScaledStrategy(transformScale);\n } else {\n positionStrategy = transformStrategy;\n }\n\n // Get compactor from type and options\n const compactor = getCompactor(compactType, allowOverlap, preventCollision);\n\n return (\n <GridLayout\n width={width}\n gridConfig={gridConfig}\n dragConfig={dragConfig}\n resizeConfig={resizeConfig}\n dropConfig={dropConfig}\n positionStrategy={positionStrategy}\n compactor={compactor}\n layout={layout}\n droppingItem={droppingItem}\n autoSize={autoSize}\n className={className}\n style={style}\n innerRef={innerRef}\n onLayoutChange={onLayoutChange}\n onDragStart={onDragStart}\n onDrag={onDrag}\n onDragStop={onDragStop}\n onResizeStart={onResizeStart}\n onResize={onResize}\n onResizeStop={onResizeStop}\n onDrop={onDrop}\n onDropDragOver={onDropDragOver}\n >\n {children}\n </GridLayout>\n );\n}\n\n// Static properties for backwards compatibility\nReactGridLayout.displayName = \"ReactGridLayout\";\n\nexport default ReactGridLayout;\nexport { ReactGridLayout };\n","/**\n * Legacy ResponsiveReactGridLayout wrapper\n *\n * This component wraps the new TypeScript ResponsiveGridLayout to provide\n * backwards compatibility with the v1 API by converting flat props\n * to the new composable interface format.\n */\n\nimport React from \"react\";\nimport {\n ResponsiveGridLayout,\n type ResponsiveGridLayoutProps\n} from \"../react/components/ResponsiveGridLayout.js\";\nimport type {\n Layout,\n LayoutItem,\n CompactType,\n Breakpoint,\n Breakpoints,\n ResponsiveLayouts,\n ResizeHandleAxis,\n DragConfig,\n ResizeConfig,\n DropConfig,\n PositionStrategy\n} from \"../core/types.js\";\nimport { getCompactor } from \"../core/compactors.js\";\nimport {\n transformStrategy,\n absoluteStrategy,\n createScaledStrategy\n} from \"../core/position.js\";\n\n// ============================================================================\n// Legacy Props Interface\n// ============================================================================\n\n/**\n * Legacy props interface for backwards compatibility with v1 API.\n * These flat props are converted to composable interfaces internally.\n */\nexport interface LegacyResponsiveReactGridLayoutProps<\n B extends Breakpoint = string\n> {\n // Required\n children: React.ReactNode;\n width: number;\n\n // Responsive-specific\n breakpoint?: B;\n breakpoints?: Breakpoints<B>;\n cols?: Breakpoints<B>;\n layouts?: ResponsiveLayouts<B>;\n onBreakpointChange?: (newBreakpoint: B, cols: number) => void;\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void;\n onWidthChange?: (\n containerWidth: number,\n margin: readonly [number, number],\n cols: number,\n containerPadding: readonly [number, number] | null\n ) => void;\n\n // Grid measurement\n rowHeight?: number;\n maxRows?: number;\n margin?:\n | readonly [number, number]\n | Partial<Record<B, readonly [number, number]>>;\n containerPadding?:\n | readonly [number, number]\n | Partial<Record<B, readonly [number, number] | null>>\n | null;\n\n // Layout data\n droppingItem?: LayoutItem;\n\n // Compaction (→ compactor)\n compactType?: CompactType;\n preventCollision?: boolean;\n allowOverlap?: boolean;\n /** @deprecated Use compactType instead */\n verticalCompact?: boolean;\n\n // Drag behavior (→ dragConfig)\n isDraggable?: boolean;\n isBounded?: boolean;\n draggableHandle?: string;\n draggableCancel?: string;\n\n // Resize behavior (→ resizeConfig)\n isResizable?: boolean;\n resizeHandles?: ResizeHandleAxis[];\n resizeHandle?:\n | React.ReactElement\n | ((\n axis: ResizeHandleAxis,\n ref: React.Ref<HTMLElement>\n ) => React.ReactElement);\n\n // Drop behavior (→ dropConfig)\n isDroppable?: boolean;\n\n // Position (→ positionStrategy)\n useCSSTransforms?: boolean;\n transformScale?: number;\n\n // Container props (passed through)\n autoSize?: boolean;\n className?: string;\n style?: React.CSSProperties;\n innerRef?: React.Ref<HTMLDivElement>;\n\n // Callbacks (passed through)\n onDragStart?: ResponsiveGridLayoutProps<B>[\"onDragStart\"];\n onDrag?: ResponsiveGridLayoutProps<B>[\"onDrag\"];\n onDragStop?: ResponsiveGridLayoutProps<B>[\"onDragStop\"];\n onResizeStart?: ResponsiveGridLayoutProps<B>[\"onResizeStart\"];\n onResize?: ResponsiveGridLayoutProps<B>[\"onResize\"];\n onResizeStop?: ResponsiveGridLayoutProps<B>[\"onResizeStop\"];\n onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void;\n onDropDragOver?: (\n e: React.DragEvent\n ) => { w?: number; h?: number } | false | void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * ResponsiveReactGridLayout - Legacy wrapper component\n *\n * Converts v1 flat props to v2 composable interfaces for backwards compatibility.\n */\nfunction ResponsiveReactGridLayout<B extends Breakpoint = string>(\n props: LegacyResponsiveReactGridLayoutProps<B>\n) {\n const {\n // Required\n children,\n width,\n\n // Responsive-specific\n breakpoint,\n breakpoints,\n cols,\n layouts,\n onBreakpointChange,\n onLayoutChange,\n onWidthChange,\n\n // Grid measurement\n rowHeight,\n maxRows,\n margin,\n containerPadding,\n\n // Layout data\n droppingItem,\n\n // Compaction\n compactType: compactTypeProp,\n preventCollision = false,\n allowOverlap = false,\n verticalCompact,\n\n // Drag behavior\n isDraggable = true,\n isBounded = false,\n draggableHandle,\n draggableCancel,\n\n // Resize behavior\n isResizable = true,\n resizeHandles = [\"se\"],\n resizeHandle,\n\n // Drop behavior\n isDroppable = false,\n\n // Position\n useCSSTransforms = true,\n transformScale = 1,\n\n // Container props\n autoSize,\n className,\n style,\n innerRef,\n\n // Callbacks\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize,\n onResizeStop,\n onDrop,\n onDropDragOver\n } = props;\n\n // Handle deprecated verticalCompact prop\n let compactType: CompactType =\n compactTypeProp === undefined ? \"vertical\" : compactTypeProp;\n if (verticalCompact === false) {\n if (process.env[\"NODE_ENV\"] !== \"production\") {\n console.warn(\n \"`verticalCompact` on <ResponsiveReactGridLayout> is deprecated and will be removed soon. \" +\n 'Use `compactType`: \"horizontal\" | \"vertical\" | null.'\n );\n }\n compactType = null;\n }\n\n // Convert flat props to composable interfaces\n\n const dragConfig: Partial<DragConfig> = {\n enabled: isDraggable,\n bounded: isBounded,\n handle: draggableHandle,\n cancel: draggableCancel\n };\n\n const resizeConfig: Partial<ResizeConfig> = {\n enabled: isResizable,\n handles: resizeHandles,\n handleComponent: resizeHandle\n };\n\n const dropConfig: Partial<DropConfig> = {\n enabled: isDroppable\n };\n\n // Build position strategy\n let positionStrategy: PositionStrategy;\n if (!useCSSTransforms) {\n positionStrategy = absoluteStrategy;\n } else if (transformScale !== 1) {\n positionStrategy = createScaledStrategy(transformScale);\n } else {\n positionStrategy = transformStrategy;\n }\n\n // Get compactor from type and options\n const compactor = getCompactor(compactType, allowOverlap, preventCollision);\n\n return (\n <ResponsiveGridLayout<B>\n width={width}\n breakpoint={breakpoint}\n breakpoints={breakpoints}\n cols={cols}\n layouts={layouts}\n rowHeight={rowHeight}\n maxRows={maxRows}\n margin={margin}\n containerPadding={containerPadding}\n compactor={compactor}\n dragConfig={dragConfig}\n resizeConfig={resizeConfig}\n dropConfig={dropConfig}\n positionStrategy={positionStrategy}\n droppingItem={droppingItem}\n autoSize={autoSize}\n className={className}\n style={style}\n innerRef={innerRef}\n onBreakpointChange={onBreakpointChange}\n onLayoutChange={onLayoutChange}\n onWidthChange={onWidthChange}\n onDragStart={onDragStart}\n onDrag={onDrag}\n onDragStop={onDragStop}\n onResizeStart={onResizeStart}\n onResize={onResize}\n onResizeStop={onResizeStop}\n onDrop={onDrop}\n onDropDragOver={onDropDragOver}\n >\n {children}\n </ResponsiveGridLayout>\n );\n}\n\n// Static properties for backwards compatibility\nResponsiveReactGridLayout.displayName = \"ResponsiveReactGridLayout\";\n\nexport default ResponsiveReactGridLayout;\nexport { ResponsiveReactGridLayout, ResponsiveReactGridLayout as Responsive };\n","/**\n * WidthProvider HOC\n *\n * A Higher-Order Component that provides width measurement to grid layouts.\n * This wraps any component and provides the container width as a prop.\n */\n\nimport React, { useState, useRef, useEffect, type ComponentType } from \"react\";\nimport clsx from \"clsx\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidthProviderProps {\n /** If true, will not render children until mounted */\n measureBeforeMount?: boolean;\n /** Additional class name */\n className?: string;\n /** Additional styles */\n style?: React.CSSProperties;\n}\n\ntype WithWidthProps<P> = Omit<P, \"width\"> & WidthProviderProps;\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst layoutClassName = \"react-grid-layout\";\n\n// ============================================================================\n// WidthProvider HOC\n// ============================================================================\n\n/**\n * WidthProvider - HOC that provides container width\n *\n * A simple HOC that provides facility for listening to container resizes.\n * Wraps the provided component and passes down a `width` prop.\n *\n * @example\n * ```tsx\n * import { GridLayout, WidthProvider } from 'react-grid-layout';\n *\n * const GridLayoutWithWidth = WidthProvider(GridLayout);\n *\n * function MyGrid() {\n * return (\n * <GridLayoutWithWidth cols={12} rowHeight={30}>\n * <div key=\"a\">a</div>\n * </GridLayoutWithWidth>\n * );\n * }\n * ```\n */\nexport function WidthProvider<P extends { width: number }>(\n ComposedComponent: ComponentType<P>\n): ComponentType<WithWidthProps<P>> {\n function WidthProviderWrapper(props: WithWidthProps<P>) {\n const { measureBeforeMount = false, className, style, ...rest } = props;\n\n const [width, setWidth] = useState(1280);\n const [mounted, setMounted] = useState(false);\n const elementRef = useRef<HTMLDivElement>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n useEffect(() => {\n setMounted(true);\n\n // Set up ResizeObserver\n resizeObserverRef.current = new ResizeObserver(entries => {\n const node = elementRef.current;\n if (node instanceof HTMLElement && entries[0]) {\n const newWidth = entries[0].contentRect.width;\n setWidth(newWidth);\n }\n });\n\n const node = elementRef.current;\n if (node instanceof HTMLElement) {\n resizeObserverRef.current.observe(node);\n }\n\n return () => {\n if (node instanceof HTMLElement && resizeObserverRef.current) {\n resizeObserverRef.current.unobserve(node);\n }\n resizeObserverRef.current?.disconnect();\n };\n }, []);\n\n // If measureBeforeMount is true and not yet mounted, render placeholder\n if (measureBeforeMount && !mounted) {\n return (\n <div\n className={clsx(className, layoutClassName)}\n style={style}\n ref={elementRef}\n />\n );\n }\n\n return (\n <ComposedComponent\n innerRef={elementRef}\n className={className}\n style={style}\n {...(rest as unknown as P)}\n width={width}\n />\n );\n }\n\n WidthProviderWrapper.displayName = `WidthProvider(${ComposedComponent.displayName || ComposedComponent.name || \"Component\"})`;\n\n return WidthProviderWrapper;\n}\n\nexport default WidthProvider;\n"]} |
| import { L as Layout, a as LayoutItem, C as CompactType, M as Mutable, c as Compactor, P as Position, d as ResizeHandleAxis, i as PositionStrategy } from './types-Cxf4nHNr.mjs'; | ||
| /** | ||
| * Core layout manipulation utilities. | ||
| * | ||
| * These functions create, modify, and query grid layouts. | ||
| * All functions treat layouts as immutable - they return new arrays/objects. | ||
| */ | ||
| /** | ||
| * Get the bottom-most Y coordinate of the layout. | ||
| * | ||
| * This is the Y position plus height of the lowest item. | ||
| * | ||
| * @param layout - Layout to measure | ||
| * @returns The bottom Y coordinate (0 if layout is empty) | ||
| */ | ||
| declare function bottom(layout: Layout): number; | ||
| /** | ||
| * Get a layout item by its ID. | ||
| * | ||
| * @param layout - Layout to search | ||
| * @param id - Item ID to find | ||
| * @returns The layout item, or undefined if not found | ||
| */ | ||
| declare function getLayoutItem(layout: Layout, id: string): LayoutItem | undefined; | ||
| /** | ||
| * Get all static items from the layout. | ||
| * | ||
| * Static items cannot be moved or resized by the user. | ||
| * | ||
| * @param layout - Layout to filter | ||
| * @returns Array of static layout items | ||
| */ | ||
| declare function getStatics(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Clone a layout item. | ||
| * | ||
| * Creates a shallow copy with all properties preserved. | ||
| * Boolean properties are normalized (undefined becomes false). | ||
| * | ||
| * @param layoutItem - Item to clone | ||
| * @returns A new layout item with the same properties | ||
| */ | ||
| declare function cloneLayoutItem(layoutItem: LayoutItem): LayoutItem; | ||
| /** | ||
| * Clone an entire layout. | ||
| * | ||
| * Creates a new array with cloned items. | ||
| * | ||
| * @param layout - Layout to clone | ||
| * @returns A new layout with cloned items | ||
| */ | ||
| declare function cloneLayout(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Replace a layout item in a layout. | ||
| * | ||
| * Returns a new layout with the item replaced. Other items are not cloned. | ||
| * | ||
| * @param layout - Layout to modify | ||
| * @param layoutItem - New item (matched by `i` property) | ||
| * @returns New layout with the item replaced | ||
| */ | ||
| declare function modifyLayout(layout: Layout, layoutItem: LayoutItem): LayoutItem[]; | ||
| /** | ||
| * Apply a transformation to a layout item. | ||
| * | ||
| * Finds the item by key, clones it, applies the callback, and returns | ||
| * a new layout with the modified item. | ||
| * | ||
| * @param layout - Layout to modify | ||
| * @param itemKey - Key of the item to modify | ||
| * @param cb - Callback that receives the cloned item and returns the modified item | ||
| * @returns Tuple of [new layout, modified item or null if not found] | ||
| */ | ||
| declare function withLayoutItem(layout: Layout, itemKey: string, cb: (item: LayoutItem) => LayoutItem): [LayoutItem[], LayoutItem | null]; | ||
| /** | ||
| * Ensure all layout items fit within the grid bounds. | ||
| * | ||
| * - Items overflowing right are moved left | ||
| * - Items overflowing left are moved to x=0 and clamped to grid width | ||
| * - Static items that collide with other statics are moved down | ||
| * | ||
| * **IMPORTANT**: This function mutates the layout items in place for performance. | ||
| * The type signature uses `Mutable<LayoutItem>[]` to make this explicit. | ||
| * Clone the layout first (e.g., with `cloneLayout()`) if you need immutability. | ||
| * | ||
| * @param layout - Layout to correct (items WILL be mutated) | ||
| * @param bounds - Grid bounds | ||
| * @returns The same layout array (for chaining) | ||
| */ | ||
| declare function correctBounds(layout: Mutable<LayoutItem>[], bounds: { | ||
| cols: number; | ||
| }): LayoutItem[]; | ||
| /** | ||
| * Move a layout element to a new position. | ||
| * | ||
| * Handles collision detection and cascading movements. | ||
| * Does not compact the layout - call `compact()` separately. | ||
| * | ||
| * **Note**: This function mutates the `l` parameter directly for performance. | ||
| * The item's x, y, and moved properties will be modified. Callers should | ||
| * ideally pass a cloned item if they need to preserve the original. | ||
| * | ||
| * @param layout - Full layout | ||
| * @param l - Item to move (will be mutated) | ||
| * @param x - New X position (or undefined to keep current) | ||
| * @param y - New Y position (or undefined to keep current) | ||
| * @param isUserAction - True if this is a direct user action (affects collision resolution) | ||
| * @param preventCollision - True to prevent movement if it causes collision | ||
| * @param compactType - Compaction type for collision resolution | ||
| * @param cols - Number of columns in the grid | ||
| * @param allowOverlap - True to allow items to overlap | ||
| * @returns The updated layout | ||
| */ | ||
| declare function moveElement(layout: Layout, l: LayoutItem, x: number | undefined, y: number | undefined, isUserAction: boolean | undefined, preventCollision: boolean | undefined, compactType: CompactType, cols: number, allowOverlap?: boolean): LayoutItem[]; | ||
| /** | ||
| * Move an item away from a collision. | ||
| * | ||
| * Attempts to move the item up/left first if there's room, | ||
| * otherwise moves it down/right. | ||
| * | ||
| * @param layout - Full layout | ||
| * @param collidesWith - The item being collided with | ||
| * @param itemToMove - The item to move away | ||
| * @param isUserAction - True if this is a direct user action | ||
| * @param compactType - Compaction type | ||
| * @param cols - Number of columns | ||
| * @returns Updated layout | ||
| */ | ||
| declare function moveElementAwayFromCollision(layout: Layout, collidesWith: LayoutItem, itemToMove: LayoutItem, isUserAction: boolean | undefined, compactType: CompactType, cols: number): LayoutItem[]; | ||
| /** | ||
| * Validate that a layout has the required properties. | ||
| * | ||
| * @param layout - Layout to validate | ||
| * @param contextName - Name for error messages | ||
| * @throws Error if layout is invalid | ||
| */ | ||
| declare function validateLayout(layout: Layout, contextName?: string): void; | ||
| /** | ||
| * Compactor implementations. | ||
| * | ||
| * Compactors are pluggable strategies for removing gaps between grid items. | ||
| * Use the Compactor interface to create custom compaction algorithms. | ||
| */ | ||
| /** | ||
| * Resolve a compaction collision by moving items. | ||
| * | ||
| * Before moving an item to a position, checks if that movement would | ||
| * cause collisions and recursively moves those items first. | ||
| * | ||
| * Useful for implementing custom compactors. | ||
| * | ||
| * @param layout - Full layout (must be sorted for optimization) | ||
| * @param item - Item being moved (will be mutated) | ||
| * @param moveToCoord - Target coordinate | ||
| * @param axis - Which axis to move on ('x' or 'y') | ||
| */ | ||
| declare function resolveCompactionCollision(layout: Layout, item: LayoutItem, moveToCoord: number, axis: "x" | "y"): void; | ||
| /** | ||
| * Compact a single item vertically (move up). | ||
| * | ||
| * Moves the item as far up as possible without colliding. | ||
| * Useful for implementing custom vertical compactors. | ||
| * | ||
| * @param compareWith - Items to check for collisions | ||
| * @param l - Item to compact (will be mutated) | ||
| * @param fullLayout - Full layout for collision resolution | ||
| * @param maxY - Maximum Y to start from | ||
| * @returns The compacted item | ||
| */ | ||
| declare function compactItemVertical(compareWith: Layout, l: LayoutItem, fullLayout: Layout, maxY: number): LayoutItem; | ||
| /** | ||
| * Compact a single item horizontally (move left). | ||
| * | ||
| * Moves the item as far left as possible without colliding. | ||
| * Wraps to the next row if it overflows. | ||
| * Useful for implementing custom horizontal compactors. | ||
| * | ||
| * @param compareWith - Items to check for collisions | ||
| * @param l - Item to compact (will be mutated) | ||
| * @param cols - Number of columns in the grid | ||
| * @param fullLayout - Full layout for collision resolution | ||
| * @returns The compacted item | ||
| */ | ||
| declare function compactItemHorizontal(compareWith: Layout, l: LayoutItem, cols: number, fullLayout: Layout): LayoutItem; | ||
| /** | ||
| * Vertical compactor - moves items up to fill gaps. | ||
| * | ||
| * Items are sorted by row then column, and each item is moved | ||
| * as far up as possible without overlapping other items. | ||
| * | ||
| * This is the default compaction mode for react-grid-layout. | ||
| */ | ||
| declare const verticalCompactor: Compactor; | ||
| /** | ||
| * Horizontal compactor - moves items left to fill gaps. | ||
| * | ||
| * Items are sorted by column then row, and each item is moved | ||
| * as far left as possible without overlapping other items. | ||
| */ | ||
| declare const horizontalCompactor: Compactor; | ||
| /** | ||
| * No compaction - items stay where placed. | ||
| * | ||
| * Use this for free-form layouts where items can be placed anywhere. | ||
| * Items will not automatically move to fill gaps. | ||
| */ | ||
| declare const noCompactor: Compactor; | ||
| /** | ||
| * Vertical compactor that allows overlapping items. | ||
| * | ||
| * Items compact upward but are allowed to overlap each other. | ||
| * Useful for layered layouts or when collision detection is handled externally. | ||
| */ | ||
| declare const verticalOverlapCompactor: Compactor; | ||
| /** | ||
| * Horizontal compactor that allows overlapping items. | ||
| */ | ||
| declare const horizontalOverlapCompactor: Compactor; | ||
| /** | ||
| * Get a compactor by type. | ||
| * | ||
| * This is a convenience function for backwards compatibility with the | ||
| * string-based compactType API. | ||
| * | ||
| * @param compactType - 'vertical', 'horizontal', or null | ||
| * @param allowOverlap - Whether to allow overlapping items | ||
| * @returns The appropriate Compactor | ||
| */ | ||
| declare function getCompactor(compactType: "vertical" | "horizontal" | null, allowOverlap?: boolean, preventCollision?: boolean): Compactor; | ||
| /** | ||
| * Position calculation utilities. | ||
| * | ||
| * These functions convert between grid units and pixel positions, | ||
| * and generate CSS styles for grid items. | ||
| */ | ||
| /** | ||
| * Generate CSS transform-based positioning styles. | ||
| * | ||
| * Using transforms is more performant than top/left positioning | ||
| * because it doesn't trigger layout recalculations. | ||
| * | ||
| * @param position - Position in pixels | ||
| * @returns CSS style object | ||
| */ | ||
| declare function setTransform({ top, left, width, height }: Position): Record<string, string>; | ||
| /** | ||
| * Generate CSS top/left positioning styles. | ||
| * | ||
| * Use this when transforms are not suitable (e.g., for printing | ||
| * or when transform causes issues with child elements). | ||
| * | ||
| * @param position - Position in pixels | ||
| * @returns CSS style object | ||
| */ | ||
| declare function setTopLeft({ top, left, width, height }: Position): Record<string, string>; | ||
| /** | ||
| * Convert a number to a percentage string. | ||
| * | ||
| * @param num - Number to convert (0-1 range typically) | ||
| * @returns Percentage string (e.g., "50%") | ||
| */ | ||
| declare function perc(num: number): string; | ||
| /** | ||
| * Resize an item in a specific direction, clamping to container bounds. | ||
| * | ||
| * This handles the complex logic of resizing from different edges/corners, | ||
| * ensuring the item doesn't overflow the container. | ||
| * | ||
| * @param direction - Which edge/corner is being dragged | ||
| * @param currentSize - Current position and size | ||
| * @param newSize - Requested new position and size | ||
| * @param containerWidth - Width of the container | ||
| * @returns Constrained position and size | ||
| */ | ||
| declare function resizeItemInDirection(direction: ResizeHandleAxis, currentSize: Position, newSize: Position, containerWidth: number): Position; | ||
| /** | ||
| * CSS transform-based positioning strategy. | ||
| * | ||
| * Uses CSS transforms for positioning, which is more performant | ||
| * as it doesn't trigger layout recalculations. | ||
| * | ||
| * This is the default strategy. | ||
| */ | ||
| declare const transformStrategy: PositionStrategy; | ||
| /** | ||
| * Absolute (top/left) positioning strategy. | ||
| * | ||
| * Uses CSS top/left for positioning. Use this when CSS transforms | ||
| * cause issues (e.g., printing, certain child element positioning). | ||
| */ | ||
| declare const absoluteStrategy: PositionStrategy; | ||
| /** | ||
| * Create a scaled transform strategy. | ||
| * | ||
| * Use this when the grid container is inside a scaled element | ||
| * (e.g., `transform: scale(0.5)`). The scale factor adjusts | ||
| * drag/resize calculations to account for the parent transform. | ||
| * | ||
| * @param scale - Scale factor (e.g., 0.5 for half size) | ||
| * @returns Position strategy with scaled calculations | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * <div style={{ transform: 'scale(0.5)' }}> | ||
| * <GridLayout positionStrategy={createScaledStrategy(0.5)} /> | ||
| * </div> | ||
| * ``` | ||
| */ | ||
| declare function createScaledStrategy(scale: number): PositionStrategy; | ||
| /** Default position strategy (transform-based) */ | ||
| declare const defaultPositionStrategy: PositionStrategy; | ||
| export { createScaledStrategy as A, defaultPositionStrategy as B, cloneLayoutItem as a, bottom as b, cloneLayout as c, getCompactor as d, verticalCompactor as e, setTopLeft as f, getLayoutItem as g, horizontalCompactor as h, getStatics as i, modifyLayout as j, correctBounds as k, moveElementAwayFromCollision as l, moveElement as m, noCompactor as n, verticalOverlapCompactor as o, horizontalOverlapCompactor as p, compactItemVertical as q, resolveCompactionCollision as r, setTransform as s, compactItemHorizontal as t, perc as u, validateLayout as v, withLayoutItem as w, resizeItemInDirection as x, transformStrategy as y, absoluteStrategy as z }; |
| import { L as Layout, a as LayoutItem, C as CompactType, M as Mutable, c as Compactor, P as Position, d as ResizeHandleAxis, i as PositionStrategy } from './types-Cxf4nHNr.js'; | ||
| /** | ||
| * Core layout manipulation utilities. | ||
| * | ||
| * These functions create, modify, and query grid layouts. | ||
| * All functions treat layouts as immutable - they return new arrays/objects. | ||
| */ | ||
| /** | ||
| * Get the bottom-most Y coordinate of the layout. | ||
| * | ||
| * This is the Y position plus height of the lowest item. | ||
| * | ||
| * @param layout - Layout to measure | ||
| * @returns The bottom Y coordinate (0 if layout is empty) | ||
| */ | ||
| declare function bottom(layout: Layout): number; | ||
| /** | ||
| * Get a layout item by its ID. | ||
| * | ||
| * @param layout - Layout to search | ||
| * @param id - Item ID to find | ||
| * @returns The layout item, or undefined if not found | ||
| */ | ||
| declare function getLayoutItem(layout: Layout, id: string): LayoutItem | undefined; | ||
| /** | ||
| * Get all static items from the layout. | ||
| * | ||
| * Static items cannot be moved or resized by the user. | ||
| * | ||
| * @param layout - Layout to filter | ||
| * @returns Array of static layout items | ||
| */ | ||
| declare function getStatics(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Clone a layout item. | ||
| * | ||
| * Creates a shallow copy with all properties preserved. | ||
| * Boolean properties are normalized (undefined becomes false). | ||
| * | ||
| * @param layoutItem - Item to clone | ||
| * @returns A new layout item with the same properties | ||
| */ | ||
| declare function cloneLayoutItem(layoutItem: LayoutItem): LayoutItem; | ||
| /** | ||
| * Clone an entire layout. | ||
| * | ||
| * Creates a new array with cloned items. | ||
| * | ||
| * @param layout - Layout to clone | ||
| * @returns A new layout with cloned items | ||
| */ | ||
| declare function cloneLayout(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Replace a layout item in a layout. | ||
| * | ||
| * Returns a new layout with the item replaced. Other items are not cloned. | ||
| * | ||
| * @param layout - Layout to modify | ||
| * @param layoutItem - New item (matched by `i` property) | ||
| * @returns New layout with the item replaced | ||
| */ | ||
| declare function modifyLayout(layout: Layout, layoutItem: LayoutItem): LayoutItem[]; | ||
| /** | ||
| * Apply a transformation to a layout item. | ||
| * | ||
| * Finds the item by key, clones it, applies the callback, and returns | ||
| * a new layout with the modified item. | ||
| * | ||
| * @param layout - Layout to modify | ||
| * @param itemKey - Key of the item to modify | ||
| * @param cb - Callback that receives the cloned item and returns the modified item | ||
| * @returns Tuple of [new layout, modified item or null if not found] | ||
| */ | ||
| declare function withLayoutItem(layout: Layout, itemKey: string, cb: (item: LayoutItem) => LayoutItem): [LayoutItem[], LayoutItem | null]; | ||
| /** | ||
| * Ensure all layout items fit within the grid bounds. | ||
| * | ||
| * - Items overflowing right are moved left | ||
| * - Items overflowing left are moved to x=0 and clamped to grid width | ||
| * - Static items that collide with other statics are moved down | ||
| * | ||
| * **IMPORTANT**: This function mutates the layout items in place for performance. | ||
| * The type signature uses `Mutable<LayoutItem>[]` to make this explicit. | ||
| * Clone the layout first (e.g., with `cloneLayout()`) if you need immutability. | ||
| * | ||
| * @param layout - Layout to correct (items WILL be mutated) | ||
| * @param bounds - Grid bounds | ||
| * @returns The same layout array (for chaining) | ||
| */ | ||
| declare function correctBounds(layout: Mutable<LayoutItem>[], bounds: { | ||
| cols: number; | ||
| }): LayoutItem[]; | ||
| /** | ||
| * Move a layout element to a new position. | ||
| * | ||
| * Handles collision detection and cascading movements. | ||
| * Does not compact the layout - call `compact()` separately. | ||
| * | ||
| * **Note**: This function mutates the `l` parameter directly for performance. | ||
| * The item's x, y, and moved properties will be modified. Callers should | ||
| * ideally pass a cloned item if they need to preserve the original. | ||
| * | ||
| * @param layout - Full layout | ||
| * @param l - Item to move (will be mutated) | ||
| * @param x - New X position (or undefined to keep current) | ||
| * @param y - New Y position (or undefined to keep current) | ||
| * @param isUserAction - True if this is a direct user action (affects collision resolution) | ||
| * @param preventCollision - True to prevent movement if it causes collision | ||
| * @param compactType - Compaction type for collision resolution | ||
| * @param cols - Number of columns in the grid | ||
| * @param allowOverlap - True to allow items to overlap | ||
| * @returns The updated layout | ||
| */ | ||
| declare function moveElement(layout: Layout, l: LayoutItem, x: number | undefined, y: number | undefined, isUserAction: boolean | undefined, preventCollision: boolean | undefined, compactType: CompactType, cols: number, allowOverlap?: boolean): LayoutItem[]; | ||
| /** | ||
| * Move an item away from a collision. | ||
| * | ||
| * Attempts to move the item up/left first if there's room, | ||
| * otherwise moves it down/right. | ||
| * | ||
| * @param layout - Full layout | ||
| * @param collidesWith - The item being collided with | ||
| * @param itemToMove - The item to move away | ||
| * @param isUserAction - True if this is a direct user action | ||
| * @param compactType - Compaction type | ||
| * @param cols - Number of columns | ||
| * @returns Updated layout | ||
| */ | ||
| declare function moveElementAwayFromCollision(layout: Layout, collidesWith: LayoutItem, itemToMove: LayoutItem, isUserAction: boolean | undefined, compactType: CompactType, cols: number): LayoutItem[]; | ||
| /** | ||
| * Validate that a layout has the required properties. | ||
| * | ||
| * @param layout - Layout to validate | ||
| * @param contextName - Name for error messages | ||
| * @throws Error if layout is invalid | ||
| */ | ||
| declare function validateLayout(layout: Layout, contextName?: string): void; | ||
| /** | ||
| * Compactor implementations. | ||
| * | ||
| * Compactors are pluggable strategies for removing gaps between grid items. | ||
| * Use the Compactor interface to create custom compaction algorithms. | ||
| */ | ||
| /** | ||
| * Resolve a compaction collision by moving items. | ||
| * | ||
| * Before moving an item to a position, checks if that movement would | ||
| * cause collisions and recursively moves those items first. | ||
| * | ||
| * Useful for implementing custom compactors. | ||
| * | ||
| * @param layout - Full layout (must be sorted for optimization) | ||
| * @param item - Item being moved (will be mutated) | ||
| * @param moveToCoord - Target coordinate | ||
| * @param axis - Which axis to move on ('x' or 'y') | ||
| */ | ||
| declare function resolveCompactionCollision(layout: Layout, item: LayoutItem, moveToCoord: number, axis: "x" | "y"): void; | ||
| /** | ||
| * Compact a single item vertically (move up). | ||
| * | ||
| * Moves the item as far up as possible without colliding. | ||
| * Useful for implementing custom vertical compactors. | ||
| * | ||
| * @param compareWith - Items to check for collisions | ||
| * @param l - Item to compact (will be mutated) | ||
| * @param fullLayout - Full layout for collision resolution | ||
| * @param maxY - Maximum Y to start from | ||
| * @returns The compacted item | ||
| */ | ||
| declare function compactItemVertical(compareWith: Layout, l: LayoutItem, fullLayout: Layout, maxY: number): LayoutItem; | ||
| /** | ||
| * Compact a single item horizontally (move left). | ||
| * | ||
| * Moves the item as far left as possible without colliding. | ||
| * Wraps to the next row if it overflows. | ||
| * Useful for implementing custom horizontal compactors. | ||
| * | ||
| * @param compareWith - Items to check for collisions | ||
| * @param l - Item to compact (will be mutated) | ||
| * @param cols - Number of columns in the grid | ||
| * @param fullLayout - Full layout for collision resolution | ||
| * @returns The compacted item | ||
| */ | ||
| declare function compactItemHorizontal(compareWith: Layout, l: LayoutItem, cols: number, fullLayout: Layout): LayoutItem; | ||
| /** | ||
| * Vertical compactor - moves items up to fill gaps. | ||
| * | ||
| * Items are sorted by row then column, and each item is moved | ||
| * as far up as possible without overlapping other items. | ||
| * | ||
| * This is the default compaction mode for react-grid-layout. | ||
| */ | ||
| declare const verticalCompactor: Compactor; | ||
| /** | ||
| * Horizontal compactor - moves items left to fill gaps. | ||
| * | ||
| * Items are sorted by column then row, and each item is moved | ||
| * as far left as possible without overlapping other items. | ||
| */ | ||
| declare const horizontalCompactor: Compactor; | ||
| /** | ||
| * No compaction - items stay where placed. | ||
| * | ||
| * Use this for free-form layouts where items can be placed anywhere. | ||
| * Items will not automatically move to fill gaps. | ||
| */ | ||
| declare const noCompactor: Compactor; | ||
| /** | ||
| * Vertical compactor that allows overlapping items. | ||
| * | ||
| * Items compact upward but are allowed to overlap each other. | ||
| * Useful for layered layouts or when collision detection is handled externally. | ||
| */ | ||
| declare const verticalOverlapCompactor: Compactor; | ||
| /** | ||
| * Horizontal compactor that allows overlapping items. | ||
| */ | ||
| declare const horizontalOverlapCompactor: Compactor; | ||
| /** | ||
| * Get a compactor by type. | ||
| * | ||
| * This is a convenience function for backwards compatibility with the | ||
| * string-based compactType API. | ||
| * | ||
| * @param compactType - 'vertical', 'horizontal', or null | ||
| * @param allowOverlap - Whether to allow overlapping items | ||
| * @returns The appropriate Compactor | ||
| */ | ||
| declare function getCompactor(compactType: "vertical" | "horizontal" | null, allowOverlap?: boolean, preventCollision?: boolean): Compactor; | ||
| /** | ||
| * Position calculation utilities. | ||
| * | ||
| * These functions convert between grid units and pixel positions, | ||
| * and generate CSS styles for grid items. | ||
| */ | ||
| /** | ||
| * Generate CSS transform-based positioning styles. | ||
| * | ||
| * Using transforms is more performant than top/left positioning | ||
| * because it doesn't trigger layout recalculations. | ||
| * | ||
| * @param position - Position in pixels | ||
| * @returns CSS style object | ||
| */ | ||
| declare function setTransform({ top, left, width, height }: Position): Record<string, string>; | ||
| /** | ||
| * Generate CSS top/left positioning styles. | ||
| * | ||
| * Use this when transforms are not suitable (e.g., for printing | ||
| * or when transform causes issues with child elements). | ||
| * | ||
| * @param position - Position in pixels | ||
| * @returns CSS style object | ||
| */ | ||
| declare function setTopLeft({ top, left, width, height }: Position): Record<string, string>; | ||
| /** | ||
| * Convert a number to a percentage string. | ||
| * | ||
| * @param num - Number to convert (0-1 range typically) | ||
| * @returns Percentage string (e.g., "50%") | ||
| */ | ||
| declare function perc(num: number): string; | ||
| /** | ||
| * Resize an item in a specific direction, clamping to container bounds. | ||
| * | ||
| * This handles the complex logic of resizing from different edges/corners, | ||
| * ensuring the item doesn't overflow the container. | ||
| * | ||
| * @param direction - Which edge/corner is being dragged | ||
| * @param currentSize - Current position and size | ||
| * @param newSize - Requested new position and size | ||
| * @param containerWidth - Width of the container | ||
| * @returns Constrained position and size | ||
| */ | ||
| declare function resizeItemInDirection(direction: ResizeHandleAxis, currentSize: Position, newSize: Position, containerWidth: number): Position; | ||
| /** | ||
| * CSS transform-based positioning strategy. | ||
| * | ||
| * Uses CSS transforms for positioning, which is more performant | ||
| * as it doesn't trigger layout recalculations. | ||
| * | ||
| * This is the default strategy. | ||
| */ | ||
| declare const transformStrategy: PositionStrategy; | ||
| /** | ||
| * Absolute (top/left) positioning strategy. | ||
| * | ||
| * Uses CSS top/left for positioning. Use this when CSS transforms | ||
| * cause issues (e.g., printing, certain child element positioning). | ||
| */ | ||
| declare const absoluteStrategy: PositionStrategy; | ||
| /** | ||
| * Create a scaled transform strategy. | ||
| * | ||
| * Use this when the grid container is inside a scaled element | ||
| * (e.g., `transform: scale(0.5)`). The scale factor adjusts | ||
| * drag/resize calculations to account for the parent transform. | ||
| * | ||
| * @param scale - Scale factor (e.g., 0.5 for half size) | ||
| * @returns Position strategy with scaled calculations | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * <div style={{ transform: 'scale(0.5)' }}> | ||
| * <GridLayout positionStrategy={createScaledStrategy(0.5)} /> | ||
| * </div> | ||
| * ``` | ||
| */ | ||
| declare function createScaledStrategy(scale: number): PositionStrategy; | ||
| /** Default position strategy (transform-based) */ | ||
| declare const defaultPositionStrategy: PositionStrategy; | ||
| export { createScaledStrategy as A, defaultPositionStrategy as B, cloneLayoutItem as a, bottom as b, cloneLayout as c, getCompactor as d, verticalCompactor as e, setTopLeft as f, getLayoutItem as g, horizontalCompactor as h, getStatics as i, modifyLayout as j, correctBounds as k, moveElementAwayFromCollision as l, moveElement as m, noCompactor as n, verticalOverlapCompactor as o, horizontalOverlapCompactor as p, compactItemVertical as q, resolveCompactionCollision as r, setTransform as s, compactItemHorizontal as t, perc as u, validateLayout as v, withLayoutItem as w, resizeItemInDirection as x, transformStrategy as y, absoluteStrategy as z }; |
+351
| import React__default, { ReactElement, CSSProperties, RefObject } from 'react'; | ||
| import { D as DroppingPosition, d as ResizeHandleAxis, G as GridDragEvent, e as GridResizeEvent, L as Layout, C as CompactType, a as LayoutItem, c as Compactor, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.mjs'; | ||
| export { P as Position } from './types-Cxf4nHNr.mjs'; | ||
| export { E as EventCallback, G as GridLayout, a as GridLayoutProps, R as ResponsiveGridLayout, b as ResponsiveGridLayoutProps } from './ResponsiveGridLayout-D6lFRE3f.mjs'; | ||
| export { b as bottom, c as cloneLayout, a as cloneLayoutItem, d as getCompactor, g as getLayoutItem, h as horizontalCompactor, n as noCompactor, f as setTopLeft, s as setTransform, e as verticalCompactor } from './position-BmN1z36J.mjs'; | ||
| export { c as calcGridItemPosition, b as calcWH, a as calcXY } from './calculate-CwYDW8na.mjs'; | ||
| /** | ||
| * GridItem component | ||
| * | ||
| * An individual item within a grid layout. Handles dragging and resizing. | ||
| */ | ||
| type GridItemCallback<Data extends GridDragEvent | GridResizeEvent> = (i: string, w: number, h: number, data: Data) => void; | ||
| type ResizeHandle = ReactElement | ((resizeHandleAxis: ResizeHandleAxis, ref: React__default.Ref<HTMLElement>) => ReactElement); | ||
| interface GridItemProps { | ||
| /** Child element to render */ | ||
| children: ReactElement; | ||
| /** Number of columns in the grid */ | ||
| cols: number; | ||
| /** Width of the container in pixels */ | ||
| containerWidth: number; | ||
| /** Margin between items [x, y] */ | ||
| margin: readonly [number, number]; | ||
| /** Padding inside the container [x, y] */ | ||
| containerPadding: readonly [number, number]; | ||
| /** Height of each row in pixels */ | ||
| rowHeight: number; | ||
| /** Maximum number of rows */ | ||
| maxRows: number; | ||
| /** Whether the item can be dragged */ | ||
| isDraggable: boolean; | ||
| /** Whether the item can be resized */ | ||
| isResizable: boolean; | ||
| /** Whether the item is bounded within the container */ | ||
| isBounded: boolean; | ||
| /** Whether the item is static (can't be moved/resized) */ | ||
| static?: boolean; | ||
| /** Use CSS transforms instead of top/left */ | ||
| useCSSTransforms?: boolean; | ||
| /** Use percentage widths for server rendering */ | ||
| usePercentages?: boolean; | ||
| /** Scale factor for transforms */ | ||
| transformScale?: number; | ||
| /** Current position of a dropping element */ | ||
| droppingPosition?: DroppingPosition; | ||
| /** Additional class name */ | ||
| className?: string; | ||
| /** Additional styles */ | ||
| style?: CSSProperties; | ||
| /** CSS selector for draggable handle */ | ||
| handle?: string; | ||
| /** CSS selector for cancel handle */ | ||
| cancel?: string; | ||
| /** X position in grid units */ | ||
| x: number; | ||
| /** Y position in grid units */ | ||
| y: number; | ||
| /** Width in grid units */ | ||
| w: number; | ||
| /** Height in grid units */ | ||
| h: number; | ||
| /** Minimum width in grid units */ | ||
| minW?: number; | ||
| /** Maximum width in grid units */ | ||
| maxW?: number; | ||
| /** Minimum height in grid units */ | ||
| minH?: number; | ||
| /** Maximum height in grid units */ | ||
| maxH?: number; | ||
| /** Unique identifier */ | ||
| i: string; | ||
| /** Which resize handles to show */ | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| /** Custom resize handle */ | ||
| resizeHandle?: ResizeHandle; | ||
| /** Called when drag starts */ | ||
| onDragStart?: GridItemCallback<GridDragEvent>; | ||
| /** Called during drag */ | ||
| onDrag?: GridItemCallback<GridDragEvent>; | ||
| /** Called when drag stops */ | ||
| onDragStop?: GridItemCallback<GridDragEvent>; | ||
| /** Called when resize starts */ | ||
| onResizeStart?: GridItemCallback<GridResizeEvent>; | ||
| /** Called during resize */ | ||
| onResize?: GridItemCallback<GridResizeEvent>; | ||
| /** Called when resize stops */ | ||
| onResizeStop?: GridItemCallback<GridResizeEvent>; | ||
| } | ||
| /** | ||
| * GridItem - An individual item within a grid layout. | ||
| * | ||
| * Wraps a child element with drag and resize functionality. | ||
| */ | ||
| declare function GridItem(props: GridItemProps): ReactElement; | ||
| /** | ||
| * useContainerWidth hook | ||
| * | ||
| * Observes container width using ResizeObserver and provides | ||
| * reactive width updates for responsive layouts. | ||
| */ | ||
| interface UseContainerWidthOptions { | ||
| /** | ||
| * If true, delays initial render until width is measured. | ||
| * Useful for SSR or when you need accurate initial measurements. | ||
| */ | ||
| measureBeforeMount?: boolean; | ||
| /** | ||
| * Initial width to use before measurement. | ||
| * Defaults to 1280. | ||
| */ | ||
| initialWidth?: number; | ||
| } | ||
| interface UseContainerWidthResult { | ||
| /** | ||
| * Current container width in pixels. | ||
| */ | ||
| width: number; | ||
| /** | ||
| * Whether the container has been measured at least once. | ||
| */ | ||
| mounted: boolean; | ||
| /** | ||
| * Ref to attach to the container element. | ||
| */ | ||
| containerRef: RefObject<HTMLDivElement | null>; | ||
| /** | ||
| * Manually trigger a width measurement. | ||
| * Useful when the container size might change without a resize event. | ||
| */ | ||
| measureWidth: () => void; | ||
| } | ||
| /** | ||
| * Hook to observe and track container width. | ||
| * | ||
| * Replaces the WidthProvider HOC with a more composable approach. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * function MyGrid() { | ||
| * const { width, containerRef, mounted } = useContainerWidth(); | ||
| * | ||
| * return ( | ||
| * <div ref={containerRef}> | ||
| * {mounted && <GridLayout width={width} {...props} />} | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function useContainerWidth(options?: UseContainerWidthOptions): UseContainerWidthResult; | ||
| /** | ||
| * useGridLayout hook | ||
| * | ||
| * Core hook for managing grid layout state, including drag, resize, and drop operations. | ||
| * This extracts the state management logic from ReactGridLayout into a reusable hook. | ||
| */ | ||
| interface DragState { | ||
| /** Currently dragging item placeholder */ | ||
| activeDrag: LayoutItem | null; | ||
| /** Original item before drag started */ | ||
| oldDragItem: LayoutItem | null; | ||
| /** Layout before drag started */ | ||
| oldLayout: Layout | null; | ||
| } | ||
| interface ResizeState { | ||
| /** Whether a resize is in progress */ | ||
| resizing: boolean; | ||
| /** Original item before resize started */ | ||
| oldResizeItem: LayoutItem | null; | ||
| /** Layout before resize started */ | ||
| oldLayout: Layout | null; | ||
| } | ||
| interface DropState { | ||
| /** DOM node for the dropping placeholder */ | ||
| droppingDOMNode: React.ReactElement | null; | ||
| /** Current drop position */ | ||
| droppingPosition: DroppingPosition | null; | ||
| } | ||
| interface UseGridLayoutOptions { | ||
| /** Initial layout */ | ||
| layout: Layout; | ||
| /** Number of columns */ | ||
| cols: number; | ||
| /** Compaction type: 'vertical', 'horizontal', or null */ | ||
| compactType?: CompactType; | ||
| /** Allow items to overlap */ | ||
| allowOverlap?: boolean; | ||
| /** Prevent collisions when moving items */ | ||
| preventCollision?: boolean; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| } | ||
| interface UseGridLayoutResult { | ||
| /** Current layout */ | ||
| layout: Layout; | ||
| /** Set layout directly */ | ||
| setLayout: (layout: Layout) => void; | ||
| /** Drag state */ | ||
| dragState: DragState; | ||
| /** Resize state */ | ||
| resizeState: ResizeState; | ||
| /** Drop state */ | ||
| dropState: DropState; | ||
| /** Start dragging an item */ | ||
| onDragStart: (itemId: string, x: number, y: number) => LayoutItem | null; | ||
| /** Update drag position */ | ||
| onDrag: (itemId: string, x: number, y: number) => void; | ||
| /** Stop dragging */ | ||
| onDragStop: (itemId: string, x: number, y: number) => void; | ||
| /** Start resizing an item */ | ||
| onResizeStart: (itemId: string) => LayoutItem | null; | ||
| /** Update resize dimensions */ | ||
| onResize: (itemId: string, w: number, h: number, x?: number, y?: number) => void; | ||
| /** Stop resizing */ | ||
| onResizeStop: (itemId: string, w: number, h: number) => void; | ||
| /** Start dropping (external drag-in) */ | ||
| onDropDragOver: (droppingItem: LayoutItem, position: DroppingPosition) => void; | ||
| /** Update drop position */ | ||
| onDropDragLeave: () => void; | ||
| /** Complete drop */ | ||
| onDrop: (droppingItem: LayoutItem) => void; | ||
| /** Container height in rows */ | ||
| containerHeight: number; | ||
| /** Whether any drag/resize is active */ | ||
| isInteracting: boolean; | ||
| /** Get the compactor being used */ | ||
| compactor: Compactor; | ||
| } | ||
| /** | ||
| * Hook for managing grid layout state. | ||
| * | ||
| * Handles all layout state including drag, resize, and drop operations. | ||
| * Uses immutable updates and provides callbacks for all interactions. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * function MyGrid() { | ||
| * const { | ||
| * layout, | ||
| * onDragStart, | ||
| * onDrag, | ||
| * onDragStop, | ||
| * containerHeight | ||
| * } = useGridLayout({ | ||
| * layout: initialLayout, | ||
| * cols: 12, | ||
| * compactType: 'vertical' | ||
| * }); | ||
| * | ||
| * return ( | ||
| * <div style={{ height: containerHeight }}> | ||
| * {layout.map(item => ( | ||
| * <GridItem | ||
| * key={item.i} | ||
| * {...item} | ||
| * onDragStart={() => onDragStart(item.i, item.x, item.y)} | ||
| * /> | ||
| * ))} | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function useGridLayout(options: UseGridLayoutOptions): UseGridLayoutResult; | ||
| /** | ||
| * useResponsiveLayout hook | ||
| * | ||
| * Manages responsive breakpoints and layout generation for different screen sizes. | ||
| * Extracts state management from ResponsiveReactGridLayout into a reusable hook. | ||
| */ | ||
| /** Default breakpoint names */ | ||
| type DefaultBreakpoints = "lg" | "md" | "sm" | "xs" | "xxs"; | ||
| /** Default breakpoint widths */ | ||
| declare const DEFAULT_BREAKPOINTS: Breakpoints<DefaultBreakpoints>; | ||
| /** Default column counts per breakpoint */ | ||
| declare const DEFAULT_COLS: Breakpoints<DefaultBreakpoints>; | ||
| interface UseResponsiveLayoutOptions<B extends Breakpoint = DefaultBreakpoints> { | ||
| /** Current container width */ | ||
| width: number; | ||
| /** Breakpoint definitions (name → min-width) */ | ||
| breakpoints?: Breakpoints<B>; | ||
| /** Column counts per breakpoint */ | ||
| cols?: Breakpoints<B>; | ||
| /** Layouts for each breakpoint */ | ||
| layouts?: ResponsiveLayouts<B>; | ||
| /** Compaction type */ | ||
| compactType?: CompactType; | ||
| /** Called when breakpoint changes */ | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void; | ||
| /** Called when width changes */ | ||
| onWidthChange?: (width: number, margin: readonly [number, number], cols: number, containerPadding: readonly [number, number] | null) => void; | ||
| } | ||
| interface UseResponsiveLayoutResult<B extends Breakpoint = DefaultBreakpoints> { | ||
| /** Current layout for the active breakpoint */ | ||
| layout: Layout; | ||
| /** All layouts by breakpoint */ | ||
| layouts: ResponsiveLayouts<B>; | ||
| /** Current active breakpoint */ | ||
| breakpoint: B; | ||
| /** Column count for the current breakpoint */ | ||
| cols: number; | ||
| /** Update layouts for a specific breakpoint */ | ||
| setLayoutForBreakpoint: (breakpoint: B, layout: Layout) => void; | ||
| /** Update all layouts */ | ||
| setLayouts: (layouts: ResponsiveLayouts<B>) => void; | ||
| /** Sorted array of breakpoint names (smallest to largest) */ | ||
| sortedBreakpoints: B[]; | ||
| } | ||
| /** | ||
| * Hook for managing responsive grid layouts. | ||
| * | ||
| * Automatically selects the appropriate layout based on container width | ||
| * and generates layouts for new breakpoints from existing ones. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * function MyResponsiveGrid() { | ||
| * const { width, containerRef } = useContainerWidth(); | ||
| * const { layout, breakpoint, cols } = useResponsiveLayout({ | ||
| * width, | ||
| * layouts: { | ||
| * lg: [...], | ||
| * md: [...], | ||
| * sm: [...] | ||
| * } | ||
| * }); | ||
| * | ||
| * return ( | ||
| * <div ref={containerRef}> | ||
| * <GridLayout | ||
| * width={width} | ||
| * cols={cols} | ||
| * layout={layout} | ||
| * /> | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function useResponsiveLayout<B extends Breakpoint = DefaultBreakpoints>(options: UseResponsiveLayoutOptions<B>): UseResponsiveLayoutResult<B>; | ||
| export { Breakpoint, Breakpoints, CompactType, Compactor, DEFAULT_BREAKPOINTS, DEFAULT_COLS, type DefaultBreakpoints, type DragState, type DropState, DroppingPosition, GridDragEvent, GridItem, type GridItemCallback, type GridItemProps, GridResizeEvent, Layout, LayoutItem, type ResizeHandle, ResizeHandleAxis, type ResizeState, ResponsiveLayouts, type UseContainerWidthOptions, type UseContainerWidthResult, type UseGridLayoutOptions, type UseGridLayoutResult, type UseResponsiveLayoutOptions, type UseResponsiveLayoutResult, useContainerWidth, useGridLayout, useResponsiveLayout }; |
+351
| import React__default, { ReactElement, CSSProperties, RefObject } from 'react'; | ||
| import { D as DroppingPosition, d as ResizeHandleAxis, G as GridDragEvent, e as GridResizeEvent, L as Layout, C as CompactType, a as LayoutItem, c as Compactor, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.js'; | ||
| export { P as Position } from './types-Cxf4nHNr.js'; | ||
| export { E as EventCallback, G as GridLayout, a as GridLayoutProps, R as ResponsiveGridLayout, b as ResponsiveGridLayoutProps } from './ResponsiveGridLayout-CH4s0tKj.js'; | ||
| export { b as bottom, c as cloneLayout, a as cloneLayoutItem, d as getCompactor, g as getLayoutItem, h as horizontalCompactor, n as noCompactor, f as setTopLeft, s as setTransform, e as verticalCompactor } from './position-Dk2b4ZMS.js'; | ||
| export { c as calcGridItemPosition, b as calcWH, a as calcXY } from './calculate-mgLpNJ5O.js'; | ||
| /** | ||
| * GridItem component | ||
| * | ||
| * An individual item within a grid layout. Handles dragging and resizing. | ||
| */ | ||
| type GridItemCallback<Data extends GridDragEvent | GridResizeEvent> = (i: string, w: number, h: number, data: Data) => void; | ||
| type ResizeHandle = ReactElement | ((resizeHandleAxis: ResizeHandleAxis, ref: React__default.Ref<HTMLElement>) => ReactElement); | ||
| interface GridItemProps { | ||
| /** Child element to render */ | ||
| children: ReactElement; | ||
| /** Number of columns in the grid */ | ||
| cols: number; | ||
| /** Width of the container in pixels */ | ||
| containerWidth: number; | ||
| /** Margin between items [x, y] */ | ||
| margin: readonly [number, number]; | ||
| /** Padding inside the container [x, y] */ | ||
| containerPadding: readonly [number, number]; | ||
| /** Height of each row in pixels */ | ||
| rowHeight: number; | ||
| /** Maximum number of rows */ | ||
| maxRows: number; | ||
| /** Whether the item can be dragged */ | ||
| isDraggable: boolean; | ||
| /** Whether the item can be resized */ | ||
| isResizable: boolean; | ||
| /** Whether the item is bounded within the container */ | ||
| isBounded: boolean; | ||
| /** Whether the item is static (can't be moved/resized) */ | ||
| static?: boolean; | ||
| /** Use CSS transforms instead of top/left */ | ||
| useCSSTransforms?: boolean; | ||
| /** Use percentage widths for server rendering */ | ||
| usePercentages?: boolean; | ||
| /** Scale factor for transforms */ | ||
| transformScale?: number; | ||
| /** Current position of a dropping element */ | ||
| droppingPosition?: DroppingPosition; | ||
| /** Additional class name */ | ||
| className?: string; | ||
| /** Additional styles */ | ||
| style?: CSSProperties; | ||
| /** CSS selector for draggable handle */ | ||
| handle?: string; | ||
| /** CSS selector for cancel handle */ | ||
| cancel?: string; | ||
| /** X position in grid units */ | ||
| x: number; | ||
| /** Y position in grid units */ | ||
| y: number; | ||
| /** Width in grid units */ | ||
| w: number; | ||
| /** Height in grid units */ | ||
| h: number; | ||
| /** Minimum width in grid units */ | ||
| minW?: number; | ||
| /** Maximum width in grid units */ | ||
| maxW?: number; | ||
| /** Minimum height in grid units */ | ||
| minH?: number; | ||
| /** Maximum height in grid units */ | ||
| maxH?: number; | ||
| /** Unique identifier */ | ||
| i: string; | ||
| /** Which resize handles to show */ | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| /** Custom resize handle */ | ||
| resizeHandle?: ResizeHandle; | ||
| /** Called when drag starts */ | ||
| onDragStart?: GridItemCallback<GridDragEvent>; | ||
| /** Called during drag */ | ||
| onDrag?: GridItemCallback<GridDragEvent>; | ||
| /** Called when drag stops */ | ||
| onDragStop?: GridItemCallback<GridDragEvent>; | ||
| /** Called when resize starts */ | ||
| onResizeStart?: GridItemCallback<GridResizeEvent>; | ||
| /** Called during resize */ | ||
| onResize?: GridItemCallback<GridResizeEvent>; | ||
| /** Called when resize stops */ | ||
| onResizeStop?: GridItemCallback<GridResizeEvent>; | ||
| } | ||
| /** | ||
| * GridItem - An individual item within a grid layout. | ||
| * | ||
| * Wraps a child element with drag and resize functionality. | ||
| */ | ||
| declare function GridItem(props: GridItemProps): ReactElement; | ||
| /** | ||
| * useContainerWidth hook | ||
| * | ||
| * Observes container width using ResizeObserver and provides | ||
| * reactive width updates for responsive layouts. | ||
| */ | ||
| interface UseContainerWidthOptions { | ||
| /** | ||
| * If true, delays initial render until width is measured. | ||
| * Useful for SSR or when you need accurate initial measurements. | ||
| */ | ||
| measureBeforeMount?: boolean; | ||
| /** | ||
| * Initial width to use before measurement. | ||
| * Defaults to 1280. | ||
| */ | ||
| initialWidth?: number; | ||
| } | ||
| interface UseContainerWidthResult { | ||
| /** | ||
| * Current container width in pixels. | ||
| */ | ||
| width: number; | ||
| /** | ||
| * Whether the container has been measured at least once. | ||
| */ | ||
| mounted: boolean; | ||
| /** | ||
| * Ref to attach to the container element. | ||
| */ | ||
| containerRef: RefObject<HTMLDivElement | null>; | ||
| /** | ||
| * Manually trigger a width measurement. | ||
| * Useful when the container size might change without a resize event. | ||
| */ | ||
| measureWidth: () => void; | ||
| } | ||
| /** | ||
| * Hook to observe and track container width. | ||
| * | ||
| * Replaces the WidthProvider HOC with a more composable approach. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * function MyGrid() { | ||
| * const { width, containerRef, mounted } = useContainerWidth(); | ||
| * | ||
| * return ( | ||
| * <div ref={containerRef}> | ||
| * {mounted && <GridLayout width={width} {...props} />} | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function useContainerWidth(options?: UseContainerWidthOptions): UseContainerWidthResult; | ||
| /** | ||
| * useGridLayout hook | ||
| * | ||
| * Core hook for managing grid layout state, including drag, resize, and drop operations. | ||
| * This extracts the state management logic from ReactGridLayout into a reusable hook. | ||
| */ | ||
| interface DragState { | ||
| /** Currently dragging item placeholder */ | ||
| activeDrag: LayoutItem | null; | ||
| /** Original item before drag started */ | ||
| oldDragItem: LayoutItem | null; | ||
| /** Layout before drag started */ | ||
| oldLayout: Layout | null; | ||
| } | ||
| interface ResizeState { | ||
| /** Whether a resize is in progress */ | ||
| resizing: boolean; | ||
| /** Original item before resize started */ | ||
| oldResizeItem: LayoutItem | null; | ||
| /** Layout before resize started */ | ||
| oldLayout: Layout | null; | ||
| } | ||
| interface DropState { | ||
| /** DOM node for the dropping placeholder */ | ||
| droppingDOMNode: React.ReactElement | null; | ||
| /** Current drop position */ | ||
| droppingPosition: DroppingPosition | null; | ||
| } | ||
| interface UseGridLayoutOptions { | ||
| /** Initial layout */ | ||
| layout: Layout; | ||
| /** Number of columns */ | ||
| cols: number; | ||
| /** Compaction type: 'vertical', 'horizontal', or null */ | ||
| compactType?: CompactType; | ||
| /** Allow items to overlap */ | ||
| allowOverlap?: boolean; | ||
| /** Prevent collisions when moving items */ | ||
| preventCollision?: boolean; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| } | ||
| interface UseGridLayoutResult { | ||
| /** Current layout */ | ||
| layout: Layout; | ||
| /** Set layout directly */ | ||
| setLayout: (layout: Layout) => void; | ||
| /** Drag state */ | ||
| dragState: DragState; | ||
| /** Resize state */ | ||
| resizeState: ResizeState; | ||
| /** Drop state */ | ||
| dropState: DropState; | ||
| /** Start dragging an item */ | ||
| onDragStart: (itemId: string, x: number, y: number) => LayoutItem | null; | ||
| /** Update drag position */ | ||
| onDrag: (itemId: string, x: number, y: number) => void; | ||
| /** Stop dragging */ | ||
| onDragStop: (itemId: string, x: number, y: number) => void; | ||
| /** Start resizing an item */ | ||
| onResizeStart: (itemId: string) => LayoutItem | null; | ||
| /** Update resize dimensions */ | ||
| onResize: (itemId: string, w: number, h: number, x?: number, y?: number) => void; | ||
| /** Stop resizing */ | ||
| onResizeStop: (itemId: string, w: number, h: number) => void; | ||
| /** Start dropping (external drag-in) */ | ||
| onDropDragOver: (droppingItem: LayoutItem, position: DroppingPosition) => void; | ||
| /** Update drop position */ | ||
| onDropDragLeave: () => void; | ||
| /** Complete drop */ | ||
| onDrop: (droppingItem: LayoutItem) => void; | ||
| /** Container height in rows */ | ||
| containerHeight: number; | ||
| /** Whether any drag/resize is active */ | ||
| isInteracting: boolean; | ||
| /** Get the compactor being used */ | ||
| compactor: Compactor; | ||
| } | ||
| /** | ||
| * Hook for managing grid layout state. | ||
| * | ||
| * Handles all layout state including drag, resize, and drop operations. | ||
| * Uses immutable updates and provides callbacks for all interactions. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * function MyGrid() { | ||
| * const { | ||
| * layout, | ||
| * onDragStart, | ||
| * onDrag, | ||
| * onDragStop, | ||
| * containerHeight | ||
| * } = useGridLayout({ | ||
| * layout: initialLayout, | ||
| * cols: 12, | ||
| * compactType: 'vertical' | ||
| * }); | ||
| * | ||
| * return ( | ||
| * <div style={{ height: containerHeight }}> | ||
| * {layout.map(item => ( | ||
| * <GridItem | ||
| * key={item.i} | ||
| * {...item} | ||
| * onDragStart={() => onDragStart(item.i, item.x, item.y)} | ||
| * /> | ||
| * ))} | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function useGridLayout(options: UseGridLayoutOptions): UseGridLayoutResult; | ||
| /** | ||
| * useResponsiveLayout hook | ||
| * | ||
| * Manages responsive breakpoints and layout generation for different screen sizes. | ||
| * Extracts state management from ResponsiveReactGridLayout into a reusable hook. | ||
| */ | ||
| /** Default breakpoint names */ | ||
| type DefaultBreakpoints = "lg" | "md" | "sm" | "xs" | "xxs"; | ||
| /** Default breakpoint widths */ | ||
| declare const DEFAULT_BREAKPOINTS: Breakpoints<DefaultBreakpoints>; | ||
| /** Default column counts per breakpoint */ | ||
| declare const DEFAULT_COLS: Breakpoints<DefaultBreakpoints>; | ||
| interface UseResponsiveLayoutOptions<B extends Breakpoint = DefaultBreakpoints> { | ||
| /** Current container width */ | ||
| width: number; | ||
| /** Breakpoint definitions (name → min-width) */ | ||
| breakpoints?: Breakpoints<B>; | ||
| /** Column counts per breakpoint */ | ||
| cols?: Breakpoints<B>; | ||
| /** Layouts for each breakpoint */ | ||
| layouts?: ResponsiveLayouts<B>; | ||
| /** Compaction type */ | ||
| compactType?: CompactType; | ||
| /** Called when breakpoint changes */ | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void; | ||
| /** Called when width changes */ | ||
| onWidthChange?: (width: number, margin: readonly [number, number], cols: number, containerPadding: readonly [number, number] | null) => void; | ||
| } | ||
| interface UseResponsiveLayoutResult<B extends Breakpoint = DefaultBreakpoints> { | ||
| /** Current layout for the active breakpoint */ | ||
| layout: Layout; | ||
| /** All layouts by breakpoint */ | ||
| layouts: ResponsiveLayouts<B>; | ||
| /** Current active breakpoint */ | ||
| breakpoint: B; | ||
| /** Column count for the current breakpoint */ | ||
| cols: number; | ||
| /** Update layouts for a specific breakpoint */ | ||
| setLayoutForBreakpoint: (breakpoint: B, layout: Layout) => void; | ||
| /** Update all layouts */ | ||
| setLayouts: (layouts: ResponsiveLayouts<B>) => void; | ||
| /** Sorted array of breakpoint names (smallest to largest) */ | ||
| sortedBreakpoints: B[]; | ||
| } | ||
| /** | ||
| * Hook for managing responsive grid layouts. | ||
| * | ||
| * Automatically selects the appropriate layout based on container width | ||
| * and generates layouts for new breakpoints from existing ones. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * function MyResponsiveGrid() { | ||
| * const { width, containerRef } = useContainerWidth(); | ||
| * const { layout, breakpoint, cols } = useResponsiveLayout({ | ||
| * width, | ||
| * layouts: { | ||
| * lg: [...], | ||
| * md: [...], | ||
| * sm: [...] | ||
| * } | ||
| * }); | ||
| * | ||
| * return ( | ||
| * <div ref={containerRef}> | ||
| * <GridLayout | ||
| * width={width} | ||
| * cols={cols} | ||
| * layout={layout} | ||
| * /> | ||
| * </div> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function useResponsiveLayout<B extends Breakpoint = DefaultBreakpoints>(options: UseResponsiveLayoutOptions<B>): UseResponsiveLayoutResult<B>; | ||
| export { Breakpoint, Breakpoints, CompactType, Compactor, DEFAULT_BREAKPOINTS, DEFAULT_COLS, type DefaultBreakpoints, type DragState, type DropState, DroppingPosition, GridDragEvent, GridItem, type GridItemCallback, type GridItemProps, GridResizeEvent, Layout, LayoutItem, type ResizeHandle, ResizeHandleAxis, type ResizeState, ResponsiveLayouts, type UseContainerWidthOptions, type UseContainerWidthResult, type UseGridLayoutOptions, type UseGridLayoutResult, type UseResponsiveLayoutOptions, type UseResponsiveLayoutResult, useContainerWidth, useGridLayout, useResponsiveLayout }; |
| 'use strict'; | ||
| var chunkH5KMDLY3_js = require('./chunk-H5KMDLY3.js'); | ||
| require('./chunk-PBQSHIID.js'); | ||
| var chunkBFTKGAP3_js = require('./chunk-BFTKGAP3.js'); | ||
| var chunk3WO4SAYB_js = require('./chunk-3WO4SAYB.js'); | ||
| var chunkF6NQPYKT_js = require('./chunk-F6NQPYKT.js'); | ||
| Object.defineProperty(exports, "DEFAULT_BREAKPOINTS", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.DEFAULT_BREAKPOINTS; } | ||
| }); | ||
| Object.defineProperty(exports, "DEFAULT_COLS", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.DEFAULT_COLS; } | ||
| }); | ||
| Object.defineProperty(exports, "useContainerWidth", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.useContainerWidth; } | ||
| }); | ||
| Object.defineProperty(exports, "useGridLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.useGridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "useResponsiveLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkH5KMDLY3_js.useResponsiveLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "GridItem", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.GridItem; } | ||
| }); | ||
| Object.defineProperty(exports, "GridLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.GridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "ResponsiveGridLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunkBFTKGAP3_js.ResponsiveGridLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "bottom", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.bottom; } | ||
| }); | ||
| Object.defineProperty(exports, "cloneLayout", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.cloneLayout; } | ||
| }); | ||
| Object.defineProperty(exports, "cloneLayoutItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.cloneLayoutItem; } | ||
| }); | ||
| Object.defineProperty(exports, "getCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "getLayoutItem", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.getLayoutItem; } | ||
| }); | ||
| Object.defineProperty(exports, "horizontalCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.horizontalCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "noCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.noCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "setTopLeft", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.setTopLeft; } | ||
| }); | ||
| Object.defineProperty(exports, "setTransform", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.setTransform; } | ||
| }); | ||
| Object.defineProperty(exports, "verticalCompactor", { | ||
| enumerable: true, | ||
| get: function () { return chunk3WO4SAYB_js.verticalCompactor; } | ||
| }); | ||
| Object.defineProperty(exports, "calcGridItemPosition", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcGridItemPosition; } | ||
| }); | ||
| Object.defineProperty(exports, "calcWH", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcWH; } | ||
| }); | ||
| Object.defineProperty(exports, "calcXY", { | ||
| enumerable: true, | ||
| get: function () { return chunkF6NQPYKT_js.calcXY; } | ||
| }); | ||
| //# sourceMappingURL=react.js.map | ||
| //# sourceMappingURL=react.js.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"react.js"} |
| export { DEFAULT_BREAKPOINTS, DEFAULT_COLS, useContainerWidth, useGridLayout, useResponsiveLayout } from './chunk-ZCXE6SR5.mjs'; | ||
| import './chunk-ZWN22PS2.mjs'; | ||
| export { GridItem, GridLayout, ResponsiveGridLayout } from './chunk-R35HZZTA.mjs'; | ||
| export { bottom, cloneLayout, cloneLayoutItem, getCompactor, getLayoutItem, horizontalCompactor, noCompactor, setTopLeft, setTransform, verticalCompactor } from './chunk-4HNUMWQK.mjs'; | ||
| export { calcGridItemPosition, calcWH, calcXY } from './chunk-2KUHNJXF.mjs'; | ||
| //# sourceMappingURL=react.mjs.map | ||
| //# sourceMappingURL=react.mjs.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"react.mjs"} |
| import { a as LayoutItem, L as Layout, C as CompactType, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.js'; | ||
| /** | ||
| * Collision detection utilities for grid layouts. | ||
| * | ||
| * These functions determine if and where layout items overlap. | ||
| */ | ||
| /** | ||
| * Check if two layout items collide (overlap). | ||
| * | ||
| * Two items collide if their bounding boxes overlap and they are | ||
| * not the same item. | ||
| * | ||
| * @param l1 - First layout item | ||
| * @param l2 - Second layout item | ||
| * @returns true if the items collide | ||
| */ | ||
| declare function collides(l1: LayoutItem, l2: LayoutItem): boolean; | ||
| /** | ||
| * Find the first item in the layout that collides with the given item. | ||
| * | ||
| * @param layout - Layout to search | ||
| * @param layoutItem - Item to check for collisions | ||
| * @returns The first colliding item, or undefined if none | ||
| */ | ||
| declare function getFirstCollision(layout: Layout, layoutItem: LayoutItem): LayoutItem | undefined; | ||
| /** | ||
| * Find all items in the layout that collide with the given item. | ||
| * | ||
| * @param layout - Layout to search | ||
| * @param layoutItem - Item to check for collisions | ||
| * @returns Array of all colliding items (may be empty) | ||
| */ | ||
| declare function getAllCollisions(layout: Layout, layoutItem: LayoutItem): LayoutItem[]; | ||
| /** | ||
| * Sorting utilities for grid layouts. | ||
| * | ||
| * These functions sort layout items for compaction and iteration. | ||
| */ | ||
| /** | ||
| * Sort layout items based on the compaction type. | ||
| * | ||
| * - Vertical compaction: sort by row (y) then column (x) | ||
| * - Horizontal compaction: sort by column (x) then row (y) | ||
| * - No compaction (null): return original order | ||
| * | ||
| * Does not modify the original layout. | ||
| * | ||
| * @param layout - Layout to sort | ||
| * @param compactType - Type of compaction | ||
| * @returns Sorted layout | ||
| */ | ||
| declare function sortLayoutItems(layout: Layout, compactType: CompactType): LayoutItem[]; | ||
| /** | ||
| * Sort layout items by row ascending, then column ascending. | ||
| * | ||
| * Items are ordered from top-left to bottom-right, row by row. | ||
| * This is the natural reading order for vertical compaction. | ||
| * | ||
| * Does not modify the original layout. | ||
| * | ||
| * @param layout - Layout to sort | ||
| * @returns Sorted array of layout items | ||
| */ | ||
| declare function sortLayoutItemsByRowCol(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Sort layout items by column ascending, then row ascending. | ||
| * | ||
| * Items are ordered from top-left to bottom-right, column by column. | ||
| * This is the natural order for horizontal compaction. | ||
| * | ||
| * Does not modify the original layout. | ||
| * | ||
| * @param layout - Layout to sort | ||
| * @returns Sorted array of layout items | ||
| */ | ||
| declare function sortLayoutItemsByColRow(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Responsive layout utilities. | ||
| * | ||
| * Functions for handling responsive breakpoints and layout generation. | ||
| */ | ||
| /** | ||
| * Sort breakpoints by width (ascending). | ||
| * | ||
| * Returns an array of breakpoint names sorted from smallest to largest. | ||
| * E.g., ['xxs', 'xs', 'sm', 'md', 'lg'] | ||
| * | ||
| * @param breakpoints - Map of breakpoint names to widths | ||
| * @returns Sorted array of breakpoint names | ||
| */ | ||
| declare function sortBreakpoints<B extends Breakpoint>(breakpoints: Breakpoints<B>): B[]; | ||
| /** | ||
| * Get the active breakpoint for a given width. | ||
| * | ||
| * Returns the highest breakpoint that is valid for the width (width > breakpoint). | ||
| * | ||
| * @param breakpoints - Map of breakpoint names to widths | ||
| * @param width - Container width in pixels | ||
| * @returns Active breakpoint name | ||
| */ | ||
| declare function getBreakpointFromWidth<B extends Breakpoint>(breakpoints: Breakpoints<B>, width: number): B; | ||
| /** | ||
| * Get the column count for a breakpoint. | ||
| * | ||
| * @param breakpoint - Breakpoint name | ||
| * @param cols - Map of breakpoint names to column counts | ||
| * @returns Number of columns for the breakpoint | ||
| * @throws Error if breakpoint is not defined in cols | ||
| */ | ||
| declare function getColsFromBreakpoint<B extends Breakpoint>(breakpoint: B, cols: Breakpoints<B>): number; | ||
| /** | ||
| * Find or generate a layout for a breakpoint. | ||
| * | ||
| * If a layout exists for the breakpoint, returns a clone. | ||
| * Otherwise, generates a new layout from the nearest larger breakpoint. | ||
| * | ||
| * @param layouts - Existing layouts by breakpoint | ||
| * @param breakpoints - Breakpoint definitions | ||
| * @param breakpoint - Target breakpoint | ||
| * @param lastBreakpoint - Previous breakpoint (for fallback) | ||
| * @param cols - Column count for the target breakpoint | ||
| * @param compactType - Compaction type | ||
| * @returns Layout for the breakpoint | ||
| */ | ||
| declare function findOrGenerateResponsiveLayout<B extends Breakpoint>(layouts: ResponsiveLayouts<B>, breakpoints: Breakpoints<B>, breakpoint: B, lastBreakpoint: B, cols: number, compactType: CompactType): Layout; | ||
| type IndentationValue<B extends Breakpoint> = readonly [number, number] | Partial<Record<B, readonly [number, number]>>; | ||
| /** | ||
| * Get margin or padding value for a breakpoint. | ||
| * | ||
| * Supports both fixed values ([x, y]) and breakpoint-specific values | ||
| * ({ lg: [x, y], md: [x, y], ... }). | ||
| * | ||
| * @param value - Fixed value or breakpoint-specific map | ||
| * @param breakpoint - Current breakpoint | ||
| * @returns Margin/padding tuple [x, y] | ||
| */ | ||
| declare function getIndentationValue<B extends Breakpoint>(value: IndentationValue<B>, breakpoint: B): readonly [number, number]; | ||
| export { getAllCollisions as a, sortLayoutItemsByRowCol as b, collides as c, sortLayoutItemsByColRow as d, getBreakpointFromWidth as e, getColsFromBreakpoint as f, getFirstCollision as g, findOrGenerateResponsiveLayout as h, sortBreakpoints as i, getIndentationValue as j, sortLayoutItems as s }; |
| import { a as LayoutItem, L as Layout, C as CompactType, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.mjs'; | ||
| /** | ||
| * Collision detection utilities for grid layouts. | ||
| * | ||
| * These functions determine if and where layout items overlap. | ||
| */ | ||
| /** | ||
| * Check if two layout items collide (overlap). | ||
| * | ||
| * Two items collide if their bounding boxes overlap and they are | ||
| * not the same item. | ||
| * | ||
| * @param l1 - First layout item | ||
| * @param l2 - Second layout item | ||
| * @returns true if the items collide | ||
| */ | ||
| declare function collides(l1: LayoutItem, l2: LayoutItem): boolean; | ||
| /** | ||
| * Find the first item in the layout that collides with the given item. | ||
| * | ||
| * @param layout - Layout to search | ||
| * @param layoutItem - Item to check for collisions | ||
| * @returns The first colliding item, or undefined if none | ||
| */ | ||
| declare function getFirstCollision(layout: Layout, layoutItem: LayoutItem): LayoutItem | undefined; | ||
| /** | ||
| * Find all items in the layout that collide with the given item. | ||
| * | ||
| * @param layout - Layout to search | ||
| * @param layoutItem - Item to check for collisions | ||
| * @returns Array of all colliding items (may be empty) | ||
| */ | ||
| declare function getAllCollisions(layout: Layout, layoutItem: LayoutItem): LayoutItem[]; | ||
| /** | ||
| * Sorting utilities for grid layouts. | ||
| * | ||
| * These functions sort layout items for compaction and iteration. | ||
| */ | ||
| /** | ||
| * Sort layout items based on the compaction type. | ||
| * | ||
| * - Vertical compaction: sort by row (y) then column (x) | ||
| * - Horizontal compaction: sort by column (x) then row (y) | ||
| * - No compaction (null): return original order | ||
| * | ||
| * Does not modify the original layout. | ||
| * | ||
| * @param layout - Layout to sort | ||
| * @param compactType - Type of compaction | ||
| * @returns Sorted layout | ||
| */ | ||
| declare function sortLayoutItems(layout: Layout, compactType: CompactType): LayoutItem[]; | ||
| /** | ||
| * Sort layout items by row ascending, then column ascending. | ||
| * | ||
| * Items are ordered from top-left to bottom-right, row by row. | ||
| * This is the natural reading order for vertical compaction. | ||
| * | ||
| * Does not modify the original layout. | ||
| * | ||
| * @param layout - Layout to sort | ||
| * @returns Sorted array of layout items | ||
| */ | ||
| declare function sortLayoutItemsByRowCol(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Sort layout items by column ascending, then row ascending. | ||
| * | ||
| * Items are ordered from top-left to bottom-right, column by column. | ||
| * This is the natural order for horizontal compaction. | ||
| * | ||
| * Does not modify the original layout. | ||
| * | ||
| * @param layout - Layout to sort | ||
| * @returns Sorted array of layout items | ||
| */ | ||
| declare function sortLayoutItemsByColRow(layout: Layout): LayoutItem[]; | ||
| /** | ||
| * Responsive layout utilities. | ||
| * | ||
| * Functions for handling responsive breakpoints and layout generation. | ||
| */ | ||
| /** | ||
| * Sort breakpoints by width (ascending). | ||
| * | ||
| * Returns an array of breakpoint names sorted from smallest to largest. | ||
| * E.g., ['xxs', 'xs', 'sm', 'md', 'lg'] | ||
| * | ||
| * @param breakpoints - Map of breakpoint names to widths | ||
| * @returns Sorted array of breakpoint names | ||
| */ | ||
| declare function sortBreakpoints<B extends Breakpoint>(breakpoints: Breakpoints<B>): B[]; | ||
| /** | ||
| * Get the active breakpoint for a given width. | ||
| * | ||
| * Returns the highest breakpoint that is valid for the width (width > breakpoint). | ||
| * | ||
| * @param breakpoints - Map of breakpoint names to widths | ||
| * @param width - Container width in pixels | ||
| * @returns Active breakpoint name | ||
| */ | ||
| declare function getBreakpointFromWidth<B extends Breakpoint>(breakpoints: Breakpoints<B>, width: number): B; | ||
| /** | ||
| * Get the column count for a breakpoint. | ||
| * | ||
| * @param breakpoint - Breakpoint name | ||
| * @param cols - Map of breakpoint names to column counts | ||
| * @returns Number of columns for the breakpoint | ||
| * @throws Error if breakpoint is not defined in cols | ||
| */ | ||
| declare function getColsFromBreakpoint<B extends Breakpoint>(breakpoint: B, cols: Breakpoints<B>): number; | ||
| /** | ||
| * Find or generate a layout for a breakpoint. | ||
| * | ||
| * If a layout exists for the breakpoint, returns a clone. | ||
| * Otherwise, generates a new layout from the nearest larger breakpoint. | ||
| * | ||
| * @param layouts - Existing layouts by breakpoint | ||
| * @param breakpoints - Breakpoint definitions | ||
| * @param breakpoint - Target breakpoint | ||
| * @param lastBreakpoint - Previous breakpoint (for fallback) | ||
| * @param cols - Column count for the target breakpoint | ||
| * @param compactType - Compaction type | ||
| * @returns Layout for the breakpoint | ||
| */ | ||
| declare function findOrGenerateResponsiveLayout<B extends Breakpoint>(layouts: ResponsiveLayouts<B>, breakpoints: Breakpoints<B>, breakpoint: B, lastBreakpoint: B, cols: number, compactType: CompactType): Layout; | ||
| type IndentationValue<B extends Breakpoint> = readonly [number, number] | Partial<Record<B, readonly [number, number]>>; | ||
| /** | ||
| * Get margin or padding value for a breakpoint. | ||
| * | ||
| * Supports both fixed values ([x, y]) and breakpoint-specific values | ||
| * ({ lg: [x, y], md: [x, y], ... }). | ||
| * | ||
| * @param value - Fixed value or breakpoint-specific map | ||
| * @param breakpoint - Current breakpoint | ||
| * @returns Margin/padding tuple [x, y] | ||
| */ | ||
| declare function getIndentationValue<B extends Breakpoint>(value: IndentationValue<B>, breakpoint: B): readonly [number, number]; | ||
| export { getAllCollisions as a, sortLayoutItemsByRowCol as b, collides as c, sortLayoutItemsByColRow as d, getBreakpointFromWidth as e, getColsFromBreakpoint as f, getFirstCollision as g, findOrGenerateResponsiveLayout as h, sortBreakpoints as i, getIndentationValue as j, sortLayoutItems as s }; |
| import React__default, { CSSProperties, DragEvent, ReactElement } from 'react'; | ||
| import { j as GridConfig, k as DragConfig, l as ResizeConfig, m as DropConfig, i as PositionStrategy, c as Compactor, L as Layout, a as LayoutItem, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.js'; | ||
| /** | ||
| * GridLayout component | ||
| * | ||
| * A reactive, fluid grid layout with draggable, resizable components. | ||
| */ | ||
| type EventCallback = (layout: Layout, oldItem: LayoutItem | null, newItem: LayoutItem | null, placeholder: LayoutItem | null, event: Event, element?: HTMLElement) => void; | ||
| interface GridLayoutProps { | ||
| /** Child elements to render in the grid */ | ||
| children: React__default.ReactNode; | ||
| /** Width of the container in pixels */ | ||
| width: number; | ||
| /** | ||
| * Grid measurement configuration. | ||
| * @see GridConfig | ||
| */ | ||
| gridConfig?: Partial<GridConfig>; | ||
| /** | ||
| * Drag behavior configuration. | ||
| * @see DragConfig | ||
| */ | ||
| dragConfig?: Partial<DragConfig>; | ||
| /** | ||
| * Resize behavior configuration. | ||
| * @see ResizeConfig | ||
| */ | ||
| resizeConfig?: Partial<ResizeConfig>; | ||
| /** | ||
| * External drop configuration. | ||
| * @see DropConfig | ||
| */ | ||
| dropConfig?: Partial<DropConfig>; | ||
| /** | ||
| * CSS positioning strategy. | ||
| * Use transformStrategy (default), absoluteStrategy, or createScaledStrategy(scale). | ||
| * @see PositionStrategy | ||
| */ | ||
| positionStrategy?: PositionStrategy; | ||
| /** | ||
| * Layout compaction strategy. | ||
| * Use verticalCompactor (default), horizontalCompactor, or noCompactor. | ||
| * @see Compactor | ||
| */ | ||
| compactor?: Compactor; | ||
| /** Layout definition */ | ||
| layout?: Layout; | ||
| /** Item to use when dropping from outside */ | ||
| droppingItem?: LayoutItem; | ||
| /** Whether to auto-size the container height */ | ||
| autoSize?: boolean; | ||
| /** Additional class name */ | ||
| className?: string; | ||
| /** Additional styles */ | ||
| style?: CSSProperties; | ||
| /** Ref to the container element */ | ||
| innerRef?: React__default.Ref<HTMLDivElement>; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| /** Called when drag starts */ | ||
| onDragStart?: EventCallback; | ||
| /** Called during drag */ | ||
| onDrag?: EventCallback; | ||
| /** Called when drag stops */ | ||
| onDragStop?: EventCallback; | ||
| /** Called when resize starts */ | ||
| onResizeStart?: EventCallback; | ||
| /** Called during resize */ | ||
| onResize?: EventCallback; | ||
| /** Called when resize stops */ | ||
| onResizeStop?: EventCallback; | ||
| /** Called when an item is dropped from outside */ | ||
| onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void; | ||
| /** Called when dragging over the grid */ | ||
| onDropDragOver?: (e: DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** | ||
| * GridLayout - A reactive, fluid grid layout with draggable, resizable components. | ||
| */ | ||
| declare function GridLayout(props: GridLayoutProps): ReactElement; | ||
| /** | ||
| * ResponsiveGridLayout component | ||
| * | ||
| * A responsive grid layout that automatically adjusts to container width. | ||
| */ | ||
| interface ResponsiveGridLayoutProps<B extends Breakpoint = string> extends Omit<GridLayoutProps, "gridConfig" | "layout" | "onLayoutChange"> { | ||
| /** Current breakpoint (optional, auto-detected from width) */ | ||
| breakpoint?: B; | ||
| /** Breakpoint definitions (name → min-width) */ | ||
| breakpoints?: Breakpoints<B>; | ||
| /** Column counts per breakpoint */ | ||
| cols?: Breakpoints<B>; | ||
| /** Layouts for each breakpoint */ | ||
| layouts?: ResponsiveLayouts<B>; | ||
| /** Row height (default: 150) */ | ||
| rowHeight?: number; | ||
| /** Maximum rows (default: Infinity) */ | ||
| maxRows?: number; | ||
| /** Margin between items - can be fixed or per-breakpoint */ | ||
| margin?: readonly [number, number] | Partial<Record<B, readonly [number, number]>>; | ||
| /** Container padding - can be fixed or per-breakpoint */ | ||
| containerPadding?: readonly [number, number] | Partial<Record<B, readonly [number, number] | null>> | null; | ||
| /** Compactor for layout compaction */ | ||
| compactor?: Compactor; | ||
| /** Called when breakpoint changes */ | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void; | ||
| /** Called when width changes */ | ||
| onWidthChange?: (containerWidth: number, margin: readonly [number, number], cols: number, containerPadding: readonly [number, number] | null) => void; | ||
| } | ||
| /** | ||
| * ResponsiveGridLayout - A responsive grid layout that adjusts to container width. | ||
| */ | ||
| declare function ResponsiveGridLayout<B extends Breakpoint = string>(props: ResponsiveGridLayoutProps<B>): ReactElement; | ||
| export { type EventCallback as E, GridLayout as G, ResponsiveGridLayout as R, type GridLayoutProps as a, type ResponsiveGridLayoutProps as b }; |
| import React__default, { CSSProperties, DragEvent, ReactElement } from 'react'; | ||
| import { j as GridConfig, k as DragConfig, l as ResizeConfig, m as DropConfig, i as PositionStrategy, c as Compactor, L as Layout, a as LayoutItem, B as Breakpoint, b as Breakpoints, R as ResponsiveLayouts } from './types-Cxf4nHNr.mjs'; | ||
| /** | ||
| * GridLayout component | ||
| * | ||
| * A reactive, fluid grid layout with draggable, resizable components. | ||
| */ | ||
| type EventCallback = (layout: Layout, oldItem: LayoutItem | null, newItem: LayoutItem | null, placeholder: LayoutItem | null, event: Event, element?: HTMLElement) => void; | ||
| interface GridLayoutProps { | ||
| /** Child elements to render in the grid */ | ||
| children: React__default.ReactNode; | ||
| /** Width of the container in pixels */ | ||
| width: number; | ||
| /** | ||
| * Grid measurement configuration. | ||
| * @see GridConfig | ||
| */ | ||
| gridConfig?: Partial<GridConfig>; | ||
| /** | ||
| * Drag behavior configuration. | ||
| * @see DragConfig | ||
| */ | ||
| dragConfig?: Partial<DragConfig>; | ||
| /** | ||
| * Resize behavior configuration. | ||
| * @see ResizeConfig | ||
| */ | ||
| resizeConfig?: Partial<ResizeConfig>; | ||
| /** | ||
| * External drop configuration. | ||
| * @see DropConfig | ||
| */ | ||
| dropConfig?: Partial<DropConfig>; | ||
| /** | ||
| * CSS positioning strategy. | ||
| * Use transformStrategy (default), absoluteStrategy, or createScaledStrategy(scale). | ||
| * @see PositionStrategy | ||
| */ | ||
| positionStrategy?: PositionStrategy; | ||
| /** | ||
| * Layout compaction strategy. | ||
| * Use verticalCompactor (default), horizontalCompactor, or noCompactor. | ||
| * @see Compactor | ||
| */ | ||
| compactor?: Compactor; | ||
| /** Layout definition */ | ||
| layout?: Layout; | ||
| /** Item to use when dropping from outside */ | ||
| droppingItem?: LayoutItem; | ||
| /** Whether to auto-size the container height */ | ||
| autoSize?: boolean; | ||
| /** Additional class name */ | ||
| className?: string; | ||
| /** Additional styles */ | ||
| style?: CSSProperties; | ||
| /** Ref to the container element */ | ||
| innerRef?: React__default.Ref<HTMLDivElement>; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| /** Called when drag starts */ | ||
| onDragStart?: EventCallback; | ||
| /** Called during drag */ | ||
| onDrag?: EventCallback; | ||
| /** Called when drag stops */ | ||
| onDragStop?: EventCallback; | ||
| /** Called when resize starts */ | ||
| onResizeStart?: EventCallback; | ||
| /** Called during resize */ | ||
| onResize?: EventCallback; | ||
| /** Called when resize stops */ | ||
| onResizeStop?: EventCallback; | ||
| /** Called when an item is dropped from outside */ | ||
| onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void; | ||
| /** Called when dragging over the grid */ | ||
| onDropDragOver?: (e: DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** | ||
| * GridLayout - A reactive, fluid grid layout with draggable, resizable components. | ||
| */ | ||
| declare function GridLayout(props: GridLayoutProps): ReactElement; | ||
| /** | ||
| * ResponsiveGridLayout component | ||
| * | ||
| * A responsive grid layout that automatically adjusts to container width. | ||
| */ | ||
| interface ResponsiveGridLayoutProps<B extends Breakpoint = string> extends Omit<GridLayoutProps, "gridConfig" | "layout" | "onLayoutChange"> { | ||
| /** Current breakpoint (optional, auto-detected from width) */ | ||
| breakpoint?: B; | ||
| /** Breakpoint definitions (name → min-width) */ | ||
| breakpoints?: Breakpoints<B>; | ||
| /** Column counts per breakpoint */ | ||
| cols?: Breakpoints<B>; | ||
| /** Layouts for each breakpoint */ | ||
| layouts?: ResponsiveLayouts<B>; | ||
| /** Row height (default: 150) */ | ||
| rowHeight?: number; | ||
| /** Maximum rows (default: Infinity) */ | ||
| maxRows?: number; | ||
| /** Margin between items - can be fixed or per-breakpoint */ | ||
| margin?: readonly [number, number] | Partial<Record<B, readonly [number, number]>>; | ||
| /** Container padding - can be fixed or per-breakpoint */ | ||
| containerPadding?: readonly [number, number] | Partial<Record<B, readonly [number, number] | null>> | null; | ||
| /** Compactor for layout compaction */ | ||
| compactor?: Compactor; | ||
| /** Called when breakpoint changes */ | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts<B>) => void; | ||
| /** Called when width changes */ | ||
| onWidthChange?: (containerWidth: number, margin: readonly [number, number], cols: number, containerPadding: readonly [number, number] | null) => void; | ||
| } | ||
| /** | ||
| * ResponsiveGridLayout - A responsive grid layout that adjusts to container width. | ||
| */ | ||
| declare function ResponsiveGridLayout<B extends Breakpoint = string>(props: ResponsiveGridLayoutProps<B>): ReactElement; | ||
| export { type EventCallback as E, GridLayout as G, ResponsiveGridLayout as R, type GridLayoutProps as a, type ResponsiveGridLayoutProps as b }; |
| /** | ||
| * Core types for react-grid-layout v2 | ||
| * | ||
| * These types are framework-agnostic and define the data structures | ||
| * used by the layout algorithms. | ||
| */ | ||
| /** | ||
| * Axis identifiers for resize handles. | ||
| * - Cardinal: 'n', 's', 'e', 'w' (north, south, east, west) | ||
| * - Diagonal: 'ne', 'nw', 'se', 'sw' | ||
| */ | ||
| type ResizeHandleAxis = "s" | "w" | "e" | "n" | "sw" | "nw" | "se" | "ne"; | ||
| /** | ||
| * A single item in the grid layout. | ||
| * | ||
| * Position (x, y) is in grid units, not pixels. | ||
| * Size (w, h) is in grid units. | ||
| */ | ||
| interface LayoutItem { | ||
| /** Unique identifier for this item */ | ||
| i: string; | ||
| /** X position in grid units (0-indexed from left) */ | ||
| x: number; | ||
| /** Y position in grid units (0-indexed from top) */ | ||
| y: number; | ||
| /** Width in grid units */ | ||
| w: number; | ||
| /** Height in grid units */ | ||
| h: number; | ||
| /** Minimum width in grid units */ | ||
| minW?: number; | ||
| /** Minimum height in grid units */ | ||
| minH?: number; | ||
| /** Maximum width in grid units */ | ||
| maxW?: number; | ||
| /** Maximum height in grid units */ | ||
| maxH?: number; | ||
| /** | ||
| * If true, item cannot be dragged or resized, and other items | ||
| * will move around it during compaction. | ||
| */ | ||
| static?: boolean; | ||
| /** | ||
| * If false, item cannot be dragged (but may still be resizable). | ||
| * Overrides grid-level isDraggable for this item. | ||
| */ | ||
| isDraggable?: boolean; | ||
| /** | ||
| * If false, item cannot be resized (but may still be draggable). | ||
| * Overrides grid-level isResizable for this item. | ||
| */ | ||
| isResizable?: boolean; | ||
| /** | ||
| * Which resize handles to show for this item. | ||
| * Overrides grid-level resizeHandles for this item. | ||
| */ | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| /** | ||
| * If true, item is constrained to the grid container bounds. | ||
| * Overrides grid-level isBounded for this item. | ||
| */ | ||
| isBounded?: boolean; | ||
| /** | ||
| * Internal flag set during drag/resize operations to indicate | ||
| * the item has moved from its original position. | ||
| * @internal | ||
| */ | ||
| moved?: boolean; | ||
| } | ||
| /** | ||
| * A layout is a readonly array of layout items. | ||
| * Layouts should be treated as immutable. | ||
| */ | ||
| type Layout = readonly LayoutItem[]; | ||
| /** | ||
| * Pixel position and size of an element. | ||
| */ | ||
| interface Position { | ||
| left: number; | ||
| top: number; | ||
| width: number; | ||
| height: number; | ||
| } | ||
| /** | ||
| * Partial position (just coordinates, no size). | ||
| */ | ||
| interface PartialPosition { | ||
| left: number; | ||
| top: number; | ||
| } | ||
| /** | ||
| * Size in pixels. | ||
| */ | ||
| interface Size { | ||
| width: number; | ||
| height: number; | ||
| } | ||
| /** | ||
| * Position when dropping an external element onto the grid. | ||
| */ | ||
| interface DroppingPosition { | ||
| left: number; | ||
| top: number; | ||
| e: Event; | ||
| } | ||
| /** | ||
| * Data provided by react-draggable during drag operations. | ||
| */ | ||
| interface ReactDraggableCallbackData { | ||
| node: HTMLElement; | ||
| x?: number; | ||
| y?: number; | ||
| deltaX: number; | ||
| deltaY: number; | ||
| lastX?: number; | ||
| lastY?: number; | ||
| } | ||
| /** | ||
| * Grid-level drag event data. | ||
| */ | ||
| interface GridDragEvent { | ||
| e: Event; | ||
| node: HTMLElement; | ||
| newPosition: PartialPosition; | ||
| } | ||
| /** | ||
| * Grid-level resize event data. | ||
| */ | ||
| interface GridResizeEvent { | ||
| e: Event; | ||
| node: HTMLElement; | ||
| size: Size; | ||
| handle: ResizeHandleAxis; | ||
| } | ||
| /** | ||
| * Drag-over event with layer coordinates. | ||
| */ | ||
| interface DragOverEvent extends MouseEvent { | ||
| nativeEvent: Event & { | ||
| layerX: number; | ||
| layerY: number; | ||
| }; | ||
| } | ||
| /** | ||
| * Type of compaction to apply to the layout. | ||
| * - 'vertical': Items compact upward (default) | ||
| * - 'horizontal': Items compact leftward | ||
| * - null: No compaction (free-form positioning) | ||
| */ | ||
| type CompactType = "horizontal" | "vertical" | null; | ||
| /** | ||
| * Standard callback signature for layout change events. | ||
| * | ||
| * @param layout - The current layout after the change | ||
| * @param oldItem - The item before the change (null if not applicable) | ||
| * @param newItem - The item after the change (null if not applicable) | ||
| * @param placeholder - The placeholder item during drag/resize (null at start) | ||
| * @param event - The DOM event that triggered the change | ||
| * @param element - The DOM element being manipulated (null if not applicable) | ||
| */ | ||
| type EventCallback = (layout: Layout, oldItem: LayoutItem | null, newItem: LayoutItem | null, placeholder: LayoutItem | null, event: Event, element: HTMLElement | null) => void; | ||
| /** | ||
| * Callback when layout changes for any reason. | ||
| */ | ||
| type OnLayoutChangeCallback = (layout: Layout) => void; | ||
| /** | ||
| * Interface for layout compaction strategies. | ||
| * | ||
| * Implement this interface to create custom compaction algorithms. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const myCompactor: Compactor = { | ||
| * type: 'vertical', | ||
| * allowOverlap: false, | ||
| * compact(layout, cols) { | ||
| * // Custom compaction logic | ||
| * return compactedLayout; | ||
| * }, | ||
| * onMove(layout, item, x, y, cols) { | ||
| * // Handle item movement | ||
| * return updatedLayout; | ||
| * } | ||
| * }; | ||
| * ``` | ||
| */ | ||
| interface Compactor { | ||
| /** Compaction type identifier */ | ||
| readonly type: CompactType; | ||
| /** Whether overlapping items are allowed */ | ||
| readonly allowOverlap: boolean; | ||
| /** Whether to prevent collisions instead of pushing items */ | ||
| readonly preventCollision?: boolean; | ||
| /** | ||
| * Compact the layout. | ||
| * | ||
| * @param layout - The layout to compact | ||
| * @param cols - Number of columns in the grid | ||
| * @returns The compacted layout | ||
| */ | ||
| compact(layout: Layout, cols: number): Layout; | ||
| /** | ||
| * Handle item movement, returning the updated layout. | ||
| * | ||
| * @param layout - Current layout | ||
| * @param item - The item being moved | ||
| * @param x - New x position | ||
| * @param y - New y position | ||
| * @param cols - Number of columns | ||
| * @returns Updated layout after the move | ||
| */ | ||
| onMove(layout: Layout, item: LayoutItem, x: number, y: number, cols: number): Layout; | ||
| } | ||
| /** | ||
| * Interface for CSS positioning strategies. | ||
| * | ||
| * Implement this interface to customize how items are positioned in the DOM. | ||
| * Built-in strategies: transformStrategy, absoluteStrategy. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Use transform-based positioning (default, better performance) | ||
| * <GridLayout positionStrategy={transformStrategy} /> | ||
| * | ||
| * // Use top/left positioning (for environments where transforms cause issues) | ||
| * <GridLayout positionStrategy={absoluteStrategy} /> | ||
| * | ||
| * // Use scaled transforms (for scaled containers) | ||
| * <GridLayout positionStrategy={createScaledStrategy(0.5)} /> | ||
| * ``` | ||
| */ | ||
| interface PositionStrategy { | ||
| /** Strategy type identifier */ | ||
| readonly type: "transform" | "absolute"; | ||
| /** Scale factor for drag/resize calculations */ | ||
| readonly scale: number; | ||
| /** | ||
| * Convert pixel position to CSS style object. | ||
| * | ||
| * @param pos - Position in pixels | ||
| * @returns CSS properties for positioning the element | ||
| */ | ||
| calcStyle(pos: Position): React.CSSProperties; | ||
| /** | ||
| * Calculate position during drag operations, accounting for transforms and scale. | ||
| * | ||
| * @param clientX - Mouse client X position | ||
| * @param clientY - Mouse client Y position | ||
| * @param offsetX - Offset from element origin X | ||
| * @param offsetY - Offset from element origin Y | ||
| * @returns Adjusted left/top position | ||
| */ | ||
| calcDragPosition(clientX: number, clientY: number, offsetX: number, offsetY: number): PartialPosition; | ||
| } | ||
| /** | ||
| * Grid measurement configuration. | ||
| * Groups all grid metrics (columns, row height, margins). | ||
| */ | ||
| interface GridConfig { | ||
| /** Number of columns in the grid (default: 12) */ | ||
| cols: number; | ||
| /** Height of a single row in pixels (default: 150) */ | ||
| rowHeight: number; | ||
| /** [horizontal, vertical] margin between items in pixels (default: [10, 10]) */ | ||
| margin: readonly [number, number]; | ||
| /** [horizontal, vertical] padding inside the container (default: null, uses margin) */ | ||
| containerPadding: readonly [number, number] | null; | ||
| /** Maximum number of rows (default: Infinity) */ | ||
| maxRows: number; | ||
| } | ||
| /** Default grid configuration */ | ||
| declare const defaultGridConfig: GridConfig; | ||
| /** | ||
| * Drag behavior configuration. | ||
| * Groups all drag-related settings. | ||
| */ | ||
| interface DragConfig { | ||
| /** Whether items can be dragged (default: true) */ | ||
| enabled: boolean; | ||
| /** Whether items are bounded to the container (default: false) */ | ||
| bounded: boolean; | ||
| /** CSS selector for drag handle (e.g., '.drag-handle') */ | ||
| handle?: string; | ||
| /** CSS selector for elements that should not trigger drag */ | ||
| cancel?: string; | ||
| /** | ||
| * Minimum pixels to move before drag starts. | ||
| * Helps distinguish click from drag (fixes #1341, #1401). | ||
| * @default 3 | ||
| */ | ||
| threshold: number; | ||
| } | ||
| /** Default drag configuration */ | ||
| declare const defaultDragConfig: DragConfig; | ||
| /** | ||
| * Resize behavior configuration. | ||
| * Groups all resize-related settings. | ||
| */ | ||
| interface ResizeConfig { | ||
| /** Whether items can be resized (default: true) */ | ||
| enabled: boolean; | ||
| /** Which resize handles to show (default: ['se']) */ | ||
| handles: readonly ResizeHandleAxis[]; | ||
| /** | ||
| * Custom resize handle component. | ||
| * Can be a React node or a function that receives the axis. | ||
| */ | ||
| handleComponent?: React.ReactNode | ((axis: ResizeHandleAxis, ref: React.Ref<HTMLElement>) => React.ReactNode); | ||
| } | ||
| /** Default resize configuration */ | ||
| declare const defaultResizeConfig: ResizeConfig; | ||
| /** | ||
| * Drop configuration (for dropping external elements). | ||
| * Groups all drop-related settings. | ||
| */ | ||
| interface DropConfig { | ||
| /** Whether external elements can be dropped on the grid (default: false) */ | ||
| enabled: boolean; | ||
| /** Default size for dropped items (default: { w: 1, h: 1 }) */ | ||
| defaultItem: { | ||
| w: number; | ||
| h: number; | ||
| }; | ||
| /** | ||
| * Called when dragging over the grid. | ||
| * Return dimensions to override defaultItem, or false to reject the drop. | ||
| */ | ||
| onDragOver?: (e: DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** Default drop configuration */ | ||
| declare const defaultDropConfig: DropConfig; | ||
| /** | ||
| * Breakpoint name (e.g., 'lg', 'md', 'sm', 'xs', 'xxs'). | ||
| */ | ||
| type Breakpoint = string; | ||
| /** | ||
| * Map of breakpoint name to pixel width. | ||
| * Generic type B allows custom breakpoint strings. | ||
| */ | ||
| type Breakpoints<B extends Breakpoint = Breakpoint> = Record<B, number>; | ||
| /** | ||
| * Map of breakpoint name to number of columns. | ||
| * Generic type B allows custom breakpoint strings. | ||
| */ | ||
| type BreakpointCols<B extends Breakpoint = Breakpoint> = Record<B, number>; | ||
| /** | ||
| * Map of breakpoint name to layout. | ||
| * Generic type B allows custom breakpoint strings. | ||
| */ | ||
| type ResponsiveLayouts<B extends Breakpoint = Breakpoint> = Partial<Record<B, Layout>>; | ||
| /** | ||
| * Callback when breakpoint changes. | ||
| */ | ||
| type OnBreakpointChangeCallback<B extends Breakpoint = Breakpoint> = (newBreakpoint: B, cols: number) => void; | ||
| /** | ||
| * Makes all properties in T mutable (removes readonly). | ||
| */ | ||
| type Mutable<T> = { | ||
| -readonly [P in keyof T]: T[P]; | ||
| }; | ||
| /** | ||
| * Deep partial - all properties and nested properties are optional. | ||
| */ | ||
| type DeepPartial<T> = { | ||
| [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; | ||
| }; | ||
| /** | ||
| * Extract the element type from an array type. | ||
| */ | ||
| type ArrayElement<T> = T extends readonly (infer U)[] ? U : never; | ||
| export { type ArrayElement as A, type Breakpoint as B, type CompactType as C, type DroppingPosition as D, type EventCallback as E, type GridDragEvent as G, type Layout as L, type Mutable as M, type OnLayoutChangeCallback as O, type Position as P, type ResponsiveLayouts as R, type Size as S, type LayoutItem as a, type Breakpoints as b, type Compactor as c, type ResizeHandleAxis as d, type GridResizeEvent as e, type PartialPosition as f, type ReactDraggableCallbackData as g, type DragOverEvent as h, type PositionStrategy as i, type GridConfig as j, type DragConfig as k, type ResizeConfig as l, type DropConfig as m, type BreakpointCols as n, type OnBreakpointChangeCallback as o, type DeepPartial as p, defaultGridConfig as q, defaultDragConfig as r, defaultResizeConfig as s, defaultDropConfig as t }; |
| /** | ||
| * Core types for react-grid-layout v2 | ||
| * | ||
| * These types are framework-agnostic and define the data structures | ||
| * used by the layout algorithms. | ||
| */ | ||
| /** | ||
| * Axis identifiers for resize handles. | ||
| * - Cardinal: 'n', 's', 'e', 'w' (north, south, east, west) | ||
| * - Diagonal: 'ne', 'nw', 'se', 'sw' | ||
| */ | ||
| type ResizeHandleAxis = "s" | "w" | "e" | "n" | "sw" | "nw" | "se" | "ne"; | ||
| /** | ||
| * A single item in the grid layout. | ||
| * | ||
| * Position (x, y) is in grid units, not pixels. | ||
| * Size (w, h) is in grid units. | ||
| */ | ||
| interface LayoutItem { | ||
| /** Unique identifier for this item */ | ||
| i: string; | ||
| /** X position in grid units (0-indexed from left) */ | ||
| x: number; | ||
| /** Y position in grid units (0-indexed from top) */ | ||
| y: number; | ||
| /** Width in grid units */ | ||
| w: number; | ||
| /** Height in grid units */ | ||
| h: number; | ||
| /** Minimum width in grid units */ | ||
| minW?: number; | ||
| /** Minimum height in grid units */ | ||
| minH?: number; | ||
| /** Maximum width in grid units */ | ||
| maxW?: number; | ||
| /** Maximum height in grid units */ | ||
| maxH?: number; | ||
| /** | ||
| * If true, item cannot be dragged or resized, and other items | ||
| * will move around it during compaction. | ||
| */ | ||
| static?: boolean; | ||
| /** | ||
| * If false, item cannot be dragged (but may still be resizable). | ||
| * Overrides grid-level isDraggable for this item. | ||
| */ | ||
| isDraggable?: boolean; | ||
| /** | ||
| * If false, item cannot be resized (but may still be draggable). | ||
| * Overrides grid-level isResizable for this item. | ||
| */ | ||
| isResizable?: boolean; | ||
| /** | ||
| * Which resize handles to show for this item. | ||
| * Overrides grid-level resizeHandles for this item. | ||
| */ | ||
| resizeHandles?: ResizeHandleAxis[]; | ||
| /** | ||
| * If true, item is constrained to the grid container bounds. | ||
| * Overrides grid-level isBounded for this item. | ||
| */ | ||
| isBounded?: boolean; | ||
| /** | ||
| * Internal flag set during drag/resize operations to indicate | ||
| * the item has moved from its original position. | ||
| * @internal | ||
| */ | ||
| moved?: boolean; | ||
| } | ||
| /** | ||
| * A layout is a readonly array of layout items. | ||
| * Layouts should be treated as immutable. | ||
| */ | ||
| type Layout = readonly LayoutItem[]; | ||
| /** | ||
| * Pixel position and size of an element. | ||
| */ | ||
| interface Position { | ||
| left: number; | ||
| top: number; | ||
| width: number; | ||
| height: number; | ||
| } | ||
| /** | ||
| * Partial position (just coordinates, no size). | ||
| */ | ||
| interface PartialPosition { | ||
| left: number; | ||
| top: number; | ||
| } | ||
| /** | ||
| * Size in pixels. | ||
| */ | ||
| interface Size { | ||
| width: number; | ||
| height: number; | ||
| } | ||
| /** | ||
| * Position when dropping an external element onto the grid. | ||
| */ | ||
| interface DroppingPosition { | ||
| left: number; | ||
| top: number; | ||
| e: Event; | ||
| } | ||
| /** | ||
| * Data provided by react-draggable during drag operations. | ||
| */ | ||
| interface ReactDraggableCallbackData { | ||
| node: HTMLElement; | ||
| x?: number; | ||
| y?: number; | ||
| deltaX: number; | ||
| deltaY: number; | ||
| lastX?: number; | ||
| lastY?: number; | ||
| } | ||
| /** | ||
| * Grid-level drag event data. | ||
| */ | ||
| interface GridDragEvent { | ||
| e: Event; | ||
| node: HTMLElement; | ||
| newPosition: PartialPosition; | ||
| } | ||
| /** | ||
| * Grid-level resize event data. | ||
| */ | ||
| interface GridResizeEvent { | ||
| e: Event; | ||
| node: HTMLElement; | ||
| size: Size; | ||
| handle: ResizeHandleAxis; | ||
| } | ||
| /** | ||
| * Drag-over event with layer coordinates. | ||
| */ | ||
| interface DragOverEvent extends MouseEvent { | ||
| nativeEvent: Event & { | ||
| layerX: number; | ||
| layerY: number; | ||
| }; | ||
| } | ||
| /** | ||
| * Type of compaction to apply to the layout. | ||
| * - 'vertical': Items compact upward (default) | ||
| * - 'horizontal': Items compact leftward | ||
| * - null: No compaction (free-form positioning) | ||
| */ | ||
| type CompactType = "horizontal" | "vertical" | null; | ||
| /** | ||
| * Standard callback signature for layout change events. | ||
| * | ||
| * @param layout - The current layout after the change | ||
| * @param oldItem - The item before the change (null if not applicable) | ||
| * @param newItem - The item after the change (null if not applicable) | ||
| * @param placeholder - The placeholder item during drag/resize (null at start) | ||
| * @param event - The DOM event that triggered the change | ||
| * @param element - The DOM element being manipulated (null if not applicable) | ||
| */ | ||
| type EventCallback = (layout: Layout, oldItem: LayoutItem | null, newItem: LayoutItem | null, placeholder: LayoutItem | null, event: Event, element: HTMLElement | null) => void; | ||
| /** | ||
| * Callback when layout changes for any reason. | ||
| */ | ||
| type OnLayoutChangeCallback = (layout: Layout) => void; | ||
| /** | ||
| * Interface for layout compaction strategies. | ||
| * | ||
| * Implement this interface to create custom compaction algorithms. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const myCompactor: Compactor = { | ||
| * type: 'vertical', | ||
| * allowOverlap: false, | ||
| * compact(layout, cols) { | ||
| * // Custom compaction logic | ||
| * return compactedLayout; | ||
| * }, | ||
| * onMove(layout, item, x, y, cols) { | ||
| * // Handle item movement | ||
| * return updatedLayout; | ||
| * } | ||
| * }; | ||
| * ``` | ||
| */ | ||
| interface Compactor { | ||
| /** Compaction type identifier */ | ||
| readonly type: CompactType; | ||
| /** Whether overlapping items are allowed */ | ||
| readonly allowOverlap: boolean; | ||
| /** Whether to prevent collisions instead of pushing items */ | ||
| readonly preventCollision?: boolean; | ||
| /** | ||
| * Compact the layout. | ||
| * | ||
| * @param layout - The layout to compact | ||
| * @param cols - Number of columns in the grid | ||
| * @returns The compacted layout | ||
| */ | ||
| compact(layout: Layout, cols: number): Layout; | ||
| /** | ||
| * Handle item movement, returning the updated layout. | ||
| * | ||
| * @param layout - Current layout | ||
| * @param item - The item being moved | ||
| * @param x - New x position | ||
| * @param y - New y position | ||
| * @param cols - Number of columns | ||
| * @returns Updated layout after the move | ||
| */ | ||
| onMove(layout: Layout, item: LayoutItem, x: number, y: number, cols: number): Layout; | ||
| } | ||
| /** | ||
| * Interface for CSS positioning strategies. | ||
| * | ||
| * Implement this interface to customize how items are positioned in the DOM. | ||
| * Built-in strategies: transformStrategy, absoluteStrategy. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Use transform-based positioning (default, better performance) | ||
| * <GridLayout positionStrategy={transformStrategy} /> | ||
| * | ||
| * // Use top/left positioning (for environments where transforms cause issues) | ||
| * <GridLayout positionStrategy={absoluteStrategy} /> | ||
| * | ||
| * // Use scaled transforms (for scaled containers) | ||
| * <GridLayout positionStrategy={createScaledStrategy(0.5)} /> | ||
| * ``` | ||
| */ | ||
| interface PositionStrategy { | ||
| /** Strategy type identifier */ | ||
| readonly type: "transform" | "absolute"; | ||
| /** Scale factor for drag/resize calculations */ | ||
| readonly scale: number; | ||
| /** | ||
| * Convert pixel position to CSS style object. | ||
| * | ||
| * @param pos - Position in pixels | ||
| * @returns CSS properties for positioning the element | ||
| */ | ||
| calcStyle(pos: Position): React.CSSProperties; | ||
| /** | ||
| * Calculate position during drag operations, accounting for transforms and scale. | ||
| * | ||
| * @param clientX - Mouse client X position | ||
| * @param clientY - Mouse client Y position | ||
| * @param offsetX - Offset from element origin X | ||
| * @param offsetY - Offset from element origin Y | ||
| * @returns Adjusted left/top position | ||
| */ | ||
| calcDragPosition(clientX: number, clientY: number, offsetX: number, offsetY: number): PartialPosition; | ||
| } | ||
| /** | ||
| * Grid measurement configuration. | ||
| * Groups all grid metrics (columns, row height, margins). | ||
| */ | ||
| interface GridConfig { | ||
| /** Number of columns in the grid (default: 12) */ | ||
| cols: number; | ||
| /** Height of a single row in pixels (default: 150) */ | ||
| rowHeight: number; | ||
| /** [horizontal, vertical] margin between items in pixels (default: [10, 10]) */ | ||
| margin: readonly [number, number]; | ||
| /** [horizontal, vertical] padding inside the container (default: null, uses margin) */ | ||
| containerPadding: readonly [number, number] | null; | ||
| /** Maximum number of rows (default: Infinity) */ | ||
| maxRows: number; | ||
| } | ||
| /** Default grid configuration */ | ||
| declare const defaultGridConfig: GridConfig; | ||
| /** | ||
| * Drag behavior configuration. | ||
| * Groups all drag-related settings. | ||
| */ | ||
| interface DragConfig { | ||
| /** Whether items can be dragged (default: true) */ | ||
| enabled: boolean; | ||
| /** Whether items are bounded to the container (default: false) */ | ||
| bounded: boolean; | ||
| /** CSS selector for drag handle (e.g., '.drag-handle') */ | ||
| handle?: string; | ||
| /** CSS selector for elements that should not trigger drag */ | ||
| cancel?: string; | ||
| /** | ||
| * Minimum pixels to move before drag starts. | ||
| * Helps distinguish click from drag (fixes #1341, #1401). | ||
| * @default 3 | ||
| */ | ||
| threshold: number; | ||
| } | ||
| /** Default drag configuration */ | ||
| declare const defaultDragConfig: DragConfig; | ||
| /** | ||
| * Resize behavior configuration. | ||
| * Groups all resize-related settings. | ||
| */ | ||
| interface ResizeConfig { | ||
| /** Whether items can be resized (default: true) */ | ||
| enabled: boolean; | ||
| /** Which resize handles to show (default: ['se']) */ | ||
| handles: readonly ResizeHandleAxis[]; | ||
| /** | ||
| * Custom resize handle component. | ||
| * Can be a React node or a function that receives the axis. | ||
| */ | ||
| handleComponent?: React.ReactNode | ((axis: ResizeHandleAxis, ref: React.Ref<HTMLElement>) => React.ReactNode); | ||
| } | ||
| /** Default resize configuration */ | ||
| declare const defaultResizeConfig: ResizeConfig; | ||
| /** | ||
| * Drop configuration (for dropping external elements). | ||
| * Groups all drop-related settings. | ||
| */ | ||
| interface DropConfig { | ||
| /** Whether external elements can be dropped on the grid (default: false) */ | ||
| enabled: boolean; | ||
| /** Default size for dropped items (default: { w: 1, h: 1 }) */ | ||
| defaultItem: { | ||
| w: number; | ||
| h: number; | ||
| }; | ||
| /** | ||
| * Called when dragging over the grid. | ||
| * Return dimensions to override defaultItem, or false to reject the drop. | ||
| */ | ||
| onDragOver?: (e: DragEvent) => { | ||
| w?: number; | ||
| h?: number; | ||
| } | false | void; | ||
| } | ||
| /** Default drop configuration */ | ||
| declare const defaultDropConfig: DropConfig; | ||
| /** | ||
| * Breakpoint name (e.g., 'lg', 'md', 'sm', 'xs', 'xxs'). | ||
| */ | ||
| type Breakpoint = string; | ||
| /** | ||
| * Map of breakpoint name to pixel width. | ||
| * Generic type B allows custom breakpoint strings. | ||
| */ | ||
| type Breakpoints<B extends Breakpoint = Breakpoint> = Record<B, number>; | ||
| /** | ||
| * Map of breakpoint name to number of columns. | ||
| * Generic type B allows custom breakpoint strings. | ||
| */ | ||
| type BreakpointCols<B extends Breakpoint = Breakpoint> = Record<B, number>; | ||
| /** | ||
| * Map of breakpoint name to layout. | ||
| * Generic type B allows custom breakpoint strings. | ||
| */ | ||
| type ResponsiveLayouts<B extends Breakpoint = Breakpoint> = Partial<Record<B, Layout>>; | ||
| /** | ||
| * Callback when breakpoint changes. | ||
| */ | ||
| type OnBreakpointChangeCallback<B extends Breakpoint = Breakpoint> = (newBreakpoint: B, cols: number) => void; | ||
| /** | ||
| * Makes all properties in T mutable (removes readonly). | ||
| */ | ||
| type Mutable<T> = { | ||
| -readonly [P in keyof T]: T[P]; | ||
| }; | ||
| /** | ||
| * Deep partial - all properties and nested properties are optional. | ||
| */ | ||
| type DeepPartial<T> = { | ||
| [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; | ||
| }; | ||
| /** | ||
| * Extract the element type from an array type. | ||
| */ | ||
| type ArrayElement<T> = T extends readonly (infer U)[] ? U : never; | ||
| export { type ArrayElement as A, type Breakpoint as B, type CompactType as C, type DroppingPosition as D, type EventCallback as E, type GridDragEvent as G, type Layout as L, type Mutable as M, type OnLayoutChangeCallback as O, type Position as P, type ResponsiveLayouts as R, type Size as S, type LayoutItem as a, type Breakpoints as b, type Compactor as c, type ResizeHandleAxis as d, type GridResizeEvent as e, type PartialPosition as f, type ReactDraggableCallbackData as g, type DragOverEvent as h, type PositionStrategy as i, type GridConfig as j, type DragConfig as k, type ResizeConfig as l, type DropConfig as m, type BreakpointCols as n, type OnBreakpointChangeCallback as o, type DeepPartial as p, defaultGridConfig as q, defaultDragConfig as r, defaultResizeConfig as s, defaultDropConfig as t }; |
| // Development entry point - uses new TypeScript source directly | ||
| module.exports = require("./src/legacy/ReactGridLayout").default; | ||
| module.exports.utils = require("./src/legacy/utils-compat"); | ||
| module.exports.calculateUtils = require("./src/legacy/calculate-compat"); | ||
| module.exports.Responsive = | ||
| require("./src/legacy/ResponsiveReactGridLayout").default; | ||
| module.exports.Responsive.utils = require("./src/legacy/responsive-compat"); | ||
| module.exports.WidthProvider = require("./src/legacy/WidthProvider").default; |
+6
-4
@@ -8,2 +8,3 @@ .react-grid-layout { | ||
| transition-property: left, top, width, height; | ||
| user-select: none; | ||
| } | ||
@@ -38,6 +39,2 @@ .react-grid-item img { | ||
| z-index: 2; | ||
| -webkit-user-select: none; | ||
| -moz-user-select: none; | ||
| -ms-user-select: none; | ||
| -o-user-select: none; | ||
| user-select: none; | ||
@@ -54,4 +51,9 @@ } | ||
| height: 20px; | ||
| opacity: 0; | ||
| } | ||
| .react-grid-item:hover > .react-resizable-handle { | ||
| opacity: 1; | ||
| } | ||
| .react-grid-item > .react-resizable-handle::after { | ||
@@ -58,0 +60,0 @@ content: ""; |
+132
-40
| { | ||
| "name": "react-grid-layout", | ||
| "version": "1.5.3", | ||
| "version": "2.0.0", | ||
| "description": "A draggable and resizable grid layout with responsive breakpoints, for React.", | ||
| "main": "index.js", | ||
| "main": "dist/index.js", | ||
| "module": "dist/index.mjs", | ||
| "types": "dist/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "import": { | ||
| "types": "./dist/index.d.mts", | ||
| "default": "./dist/index.mjs" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/index.d.ts", | ||
| "default": "./dist/index.js" | ||
| } | ||
| }, | ||
| "./core": { | ||
| "import": { | ||
| "types": "./dist/core.d.mts", | ||
| "default": "./dist/core.mjs" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/core.d.ts", | ||
| "default": "./dist/core.js" | ||
| } | ||
| }, | ||
| "./react": { | ||
| "import": { | ||
| "types": "./dist/react.d.mts", | ||
| "default": "./dist/react.mjs" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/react.d.ts", | ||
| "default": "./dist/react.js" | ||
| } | ||
| }, | ||
| "./legacy": { | ||
| "import": { | ||
| "types": "./dist/legacy.d.mts", | ||
| "default": "./dist/legacy.mjs" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/legacy.d.ts", | ||
| "default": "./dist/legacy.js" | ||
| } | ||
| }, | ||
| "./extras": { | ||
| "import": { | ||
| "types": "./dist/extras.d.mts", | ||
| "default": "./dist/extras.mjs" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/extras.d.ts", | ||
| "default": "./dist/extras.js" | ||
| } | ||
| }, | ||
| "./css/styles.css": "./css/styles.css" | ||
| }, | ||
| "sideEffects": [ | ||
| "*.css" | ||
| ], | ||
| "files": [ | ||
| "dist", | ||
| "css", | ||
| "index.js", | ||
| "index-dev.js" | ||
| ], | ||
| "scripts": { | ||
@@ -10,8 +74,10 @@ "lint": "make lint", | ||
| "build": "make build", | ||
| "build:ts": "tsup", | ||
| "build:ts:watch": "tsup --watch", | ||
| "typecheck": "tsc --noEmit", | ||
| "build-example": "make build-example", | ||
| "view-example": "make view-example", | ||
| "dev": "npx @react-grab/claude-code@latest && make dev", | ||
| "dev": "make dev", | ||
| "prepublishOnly": "make build", | ||
| "validate": "npm ls", | ||
| "flow": "flow", | ||
| "fmt": "prettier --write .", | ||
@@ -37,5 +103,5 @@ "fmt:check": "prettier --check ." | ||
| "bugs": { | ||
| "url": "https://github.com/STRML/react-grid-layout/issues" | ||
| "url": "https://github.com/react-grid-layout/react-grid-layout/issues" | ||
| }, | ||
| "homepage": "https://github.com/STRML/react-grid-layout", | ||
| "homepage": "https://github.com/react-grid-layout/react-grid-layout", | ||
| "dependencies": { | ||
@@ -57,41 +123,47 @@ "clsx": "^2.1.1", | ||
| "@babel/plugin-transform-class-properties": "^7.18.6", | ||
| "@babel/plugin-transform-flow-comments": "^7.27.3", | ||
| "@babel/preset-env": "^7.27.2", | ||
| "@babel/preset-flow": "^7.27.1", | ||
| "@babel/preset-react": "^7.27.1", | ||
| "@babel/preset-typescript": "^7.28.5", | ||
| "@babel/register": "^7.27.1", | ||
| "@webpack-cli/serve": "^2.0.5", | ||
| "babel-jest": "^29.7.0", | ||
| "babel-loader": "^9.1.3", | ||
| "@eslint/compat": "^1.2.0", | ||
| "@eslint/js": "^9.0.0", | ||
| "@testing-library/dom": "^10.4.0", | ||
| "@testing-library/jest-dom": "^6.6.3", | ||
| "@testing-library/react": "^16.1.0", | ||
| "@types/node": "^24.10.1", | ||
| "@types/react": "^19.2.7", | ||
| "@webpack-cli/serve": "^3.0.1", | ||
| "babel-jest": "^30.2.0", | ||
| "babel-loader": "^10.0.0", | ||
| "babel-plugin-preval": "^5.1.0", | ||
| "css-loader": "^6.8.1", | ||
| "css-loader": "^7.1.2", | ||
| "ejs": "^3.1.10", | ||
| "enzyme": "^3.11.0", | ||
| "enzyme-adapter-react-16": "^1.15.8", | ||
| "enzyme-to-json": "^3.6.2", | ||
| "eslint": "^8.54.0", | ||
| "eslint-plugin-flowtype": "^8.0.3", | ||
| "eslint-plugin-mocha": "^10.2.0", | ||
| "eslint": "^9.39.1", | ||
| "eslint-plugin-mocha": "^11.2.0", | ||
| "eslint-plugin-react": "^7.33.2", | ||
| "eslint-plugin-unicorn": "^49.0.0", | ||
| "exports-loader": "^4.0.0", | ||
| "flow-bin": "^0.172.0", | ||
| "husky": "^8.0.3", | ||
| "imports-loader": "^4.0.1", | ||
| "jest": "^29.7.0", | ||
| "jest-environment-jsdom": "^29.7.0", | ||
| "lint-staged": "^15.1.0", | ||
| "eslint-plugin-react-hooks": "^7.0.1", | ||
| "eslint-plugin-unicorn": "^62.0.0", | ||
| "exports-loader": "^5.0.0", | ||
| "globals": "^16.0.0", | ||
| "husky": "^9.1.7", | ||
| "imports-loader": "^5.0.0", | ||
| "jest": "^30.2.0", | ||
| "jest-environment-jsdom": "^30.2.0", | ||
| "lint-staged": "^16.2.7", | ||
| "lodash": "^4.17.21", | ||
| "opener": "^1.5.2", | ||
| "prettier": "^3.1.0", | ||
| "react": "^16.13.1", | ||
| "react-dom": "^16.13.1", | ||
| "react": "^18.3.1", | ||
| "react-dom": "^18.3.1", | ||
| "react-grab": "^0.0.71", | ||
| "react-hot-loader": "^4.13.1", | ||
| "react-transform-hmr": "^1.0.2", | ||
| "style-loader": "^3.3.3", | ||
| "style-loader": "^4.0.0", | ||
| "timsort": "^0.3.0", | ||
| "webpack": "^5.89.0", | ||
| "webpack-cli": "^5.1.4", | ||
| "webpack-dev-server": "^4.15.1" | ||
| "tsup": "^8.5.1", | ||
| "typescript": "^5.9.3", | ||
| "typescript-eslint": "^8.49.0", | ||
| "webpack": "^5.92.0", | ||
| "webpack-cli": "^6.0.1", | ||
| "webpack-dev-server": "^5.2.2" | ||
| }, | ||
@@ -115,7 +187,6 @@ "resolutions": { | ||
| ], | ||
| "snapshotSerializers": [ | ||
| "enzyme-to-json/serializer" | ||
| ], | ||
| "testMatch": [ | ||
| "<rootDir>/test/spec/*.js" | ||
| "<rootDir>/test/spec/*.js", | ||
| "<rootDir>/test/spec/*.ts", | ||
| "<rootDir>/test/spec/*.tsx" | ||
| ], | ||
@@ -128,7 +199,28 @@ "testEnvironment": "jsdom", | ||
| "global": { | ||
| "statements": 77, | ||
| "branches": 72, | ||
| "functions": 77, | ||
| "lines": 78 | ||
| "statements": 65, | ||
| "branches": 60, | ||
| "functions": 65, | ||
| "lines": 65 | ||
| } | ||
| }, | ||
| "transform": { | ||
| "^.+\\.(js|jsx)$": "babel-jest", | ||
| "^.+\\.(ts|tsx)$": [ | ||
| "babel-jest", | ||
| { | ||
| "presets": [ | ||
| "@babel/preset-typescript" | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| "moduleFileExtensions": [ | ||
| "ts", | ||
| "tsx", | ||
| "js", | ||
| "jsx", | ||
| "json" | ||
| ], | ||
| "moduleNameMapper": { | ||
| "^(\\.{1,2}/.*)\\.js$": "$1" | ||
| } | ||
@@ -135,0 +227,0 @@ }, |
+1043
-401
| # React-Grid-Layout | ||
| [](https://travis-ci.org/STRML/react-grid-layout) | ||
| [](https://cdnjs.com/libraries/react-grid-layout) | ||
| [](https://www.npmjs.org/package/react-grid-layout) | ||
@@ -24,16 +22,94 @@ []() | ||
| - [What's New in v2](#whats-new-in-v2) | ||
| - [Migrating from v1](#migrating-from-v1) | ||
| - [Demos](#demos) | ||
| - [Features](#features) | ||
| - [Installation](#installation) | ||
| - [Usage](#usage) | ||
| - [Quick Start](#quick-start) | ||
| - [Responsive Usage](#responsive-usage) | ||
| - [Providing Grid Width](#providing-grid-width) | ||
| - [Grid Layout Props](#grid-layout-props) | ||
| - [Responsive Grid Layout Props](#responsive-grid-layout-props) | ||
| - [Grid Item Props](#grid-item-props) | ||
| - [User Recipes](../../wiki/Users-recipes) | ||
| - [Hooks API](#hooks-api) | ||
| - [API Reference](#api-reference) | ||
| - [Extending: Custom Compactors & Position Strategies](#extending-custom-compactors--position-strategies) | ||
| - [Extras](#extras) | ||
| - [Performance](#performance) | ||
| - [Contribute](#contribute) | ||
| - [TODO List](#todo-list) | ||
| ## What's New in v2 | ||
| Version 2 is a complete TypeScript rewrite with a modernized API: | ||
| - **Full TypeScript support** - First-class types, no more `@types/react-grid-layout` | ||
| - **React Hooks** - New `useContainerWidth`, `useGridLayout`, and `useResponsiveLayout` hooks | ||
| - **Composable Configuration** - Group related props into focused interfaces: | ||
| - `gridConfig` - cols, rowHeight, margin, padding | ||
| - `dragConfig` - enable, handle, cancel, bounded | ||
| - `resizeConfig` - enable, handles | ||
| - `positionStrategy` - transform vs absolute positioning | ||
| - `compactor` - vertical, horizontal, or custom algorithms | ||
| - **Modular architecture** - Import only what you need: | ||
| - `react-grid-layout` - React components and hooks (v2 API) | ||
| - `react-grid-layout/core` - Pure layout algorithms (framework-agnostic) | ||
| - `react-grid-layout/legacy` - v1 flat props API for migration | ||
| - `react-grid-layout/extras` - Optional components like `GridBackground` | ||
| - **Smaller bundle** - Tree-shakeable ESM and CJS builds | ||
| ### Breaking Changes | ||
| See the [RFC](./rfcs/0001-v2-typescript-rewrite.md#breaking-changes-in-v2) for detailed migration examples. | ||
| | Change | Description | | ||
| | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | ||
| | [`width` prop required](./rfcs/0001-v2-typescript-rewrite.md#breaking-changes-in-v2) | Use `useContainerWidth` hook or provide your own measurement | | ||
| | [`onDragStart` threshold](./rfcs/0001-v2-typescript-rewrite.md#1-ondragstart-no-longer-fires-on-click-only-events) | Now fires after 3px movement, not on mousedown. Use `onMouseDown` for immediate response | | ||
| | [Immutable callbacks](./rfcs/0001-v2-typescript-rewrite.md#2-immutable-callback-parameters) | Callback parameters are read-only. Use `onLayoutChange` or constraints instead of mutation | | ||
| | [`data-grid` in legacy only](./rfcs/0001-v2-typescript-rewrite.md#3-data-grid-prop-only-available-in-legacy-wrapper) | v2 requires explicit `layout` prop. Use legacy wrapper for `data-grid` | | ||
| | [Fast compaction](./rfcs/0001-v2-typescript-rewrite.md#4-fast-compaction-algorithm-by-default) | O(n log n) algorithm may differ in edge cases. Use `compact()` from `/core` for exact v1 behavior | | ||
| | UMD bundle removed | Use a bundler (Vite, webpack, esbuild) | | ||
| | `verticalCompact` removed | Use `compactType={null}` or `compactor={noCompactor}` | | ||
| ## Migrating from v1 | ||
| **Quick migration** - change your import to use the legacy wrapper: | ||
| ```diff | ||
| - import GridLayout, { Responsive, WidthProvider } from 'react-grid-layout'; | ||
| + import GridLayout, { Responsive, WidthProvider } from 'react-grid-layout/legacy'; | ||
| ``` | ||
| This provides **100% API compatibility** with v1. | ||
| **Full migration** - adopt the v2 API for new features and better tree-shaking: | ||
| ```typescript | ||
| import ReactGridLayout, { useContainerWidth, verticalCompactor } from 'react-grid-layout'; | ||
| function MyGrid() { | ||
| const { width, containerRef, mounted } = useContainerWidth(); | ||
| return ( | ||
| <div ref={containerRef}> | ||
| {mounted && ( | ||
| <ReactGridLayout | ||
| width={width} | ||
| layout={layout} | ||
| gridConfig={{ cols: 12, rowHeight: 30 }} | ||
| dragConfig={{ enabled: true, handle: '.handle' }} | ||
| compactor={verticalCompactor} | ||
| > | ||
| {children} | ||
| </ReactGridLayout> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
| | Use Case | Recommendation | | ||
| | -------------------- | ---------------------------------- | | ||
| | Existing v1 codebase | `react-grid-layout/legacy` | | ||
| | New project | v2 API with hooks | | ||
| | Custom compaction | v2 with custom `Compactor` | | ||
| | SSR | v2 with `measureBeforeMount: true` | | ||
| ## Demos | ||
@@ -72,15 +148,4 @@ | ||
| - [HubSpot](http://www.hubspot.com) | ||
| - [ComNetViz](http://www.grotto-networking.com/ComNetViz/ComNetViz.html) | ||
| - [Stoplight](https://app.stoplight.io) | ||
| - [Reflect](https://reflect.io) | ||
| - [ez-Dashing](https://github.com/ylacaute/ez-Dashing) | ||
| - [Kibana](https://www.elastic.co/products/kibana) | ||
| - [Graphext](https://graphext.com/) | ||
| - [Monday](https://support.monday.com/hc/en-us/articles/360002187819-What-are-the-Dashboards-) | ||
| - [Quadency](https://quadency.com/) | ||
| - [Hakkiri](https://www.hakkiri.io) | ||
| - [Ubidots](https://help.ubidots.com/en/articles/2400308-create-dashboards-and-widgets) | ||
| - [Statsout](https://statsout.com/) | ||
| - [Datto RMM](https://www.datto.com/uk/products/rmm/) | ||
| - [SquaredUp](https://squaredup.com/) | ||
@@ -92,2 +157,3 @@ _Know of others? Create a PR to let me know!_ | ||
| - 100% React - no jQuery | ||
| - Full TypeScript support | ||
| - Compatible with server-rendered apps | ||
@@ -104,17 +170,11 @@ - Draggable widgets | ||
| - Grid Items placed using CSS Transforms | ||
| - Performance with CSS Transforms: [on](http://i.imgur.com/FTogpLp.jpg) / [off](http://i.imgur.com/gOveMm8.jpg), note paint (green) as % of time | ||
| - Compatibility with `<React.StrictMode>` | ||
| | Version | Compatibility | | ||
| | ------------ | --------------- | | ||
| | >= 0.17.0 | React 16 & 17 | | ||
| | >= 0.11.3 | React 0.14 & 15 | | ||
| | >= 0.10.0 | React 0.14 | | ||
| | 0.8. - 0.9.2 | React 0.13 | | ||
| | < 0.8 | React 0.12 | | ||
| | Version | Compatibility | | ||
| | --------- | --------------------- | | ||
| | >= 2.0.0 | React 18+, TypeScript | | ||
| | >= 0.17.0 | React 16 & 17 | | ||
| ## Installation | ||
| Install the React-Grid-Layout [package](https://www.npmjs.org/package/react-grid-layout) using [npm](https://www.npmjs.com/): | ||
| ```bash | ||
@@ -124,484 +184,1082 @@ npm install react-grid-layout | ||
| Include the following stylesheets in your application: | ||
| Include the stylesheets in your application: | ||
| ```js | ||
| import "react-grid-layout/css/styles.css"; | ||
| import "react-resizable/css/styles.css"; | ||
| ``` | ||
| /node_modules/react-grid-layout/css/styles.css | ||
| /node_modules/react-resizable/css/styles.css | ||
| Or link them directly: | ||
| ```html | ||
| <link rel="stylesheet" href="/node_modules/react-grid-layout/css/styles.css" /> | ||
| <link rel="stylesheet" href="/node_modules/react-resizable/css/styles.css" /> | ||
| ``` | ||
| ## Usage | ||
| ## Quick Start | ||
| Use ReactGridLayout like any other component. The following example below will | ||
| produce a grid with three items where: | ||
| ```tsx | ||
| import ReactGridLayout, { useContainerWidth } from "react-grid-layout"; | ||
| import "react-grid-layout/css/styles.css"; | ||
| import "react-resizable/css/styles.css"; | ||
| - users will not be able to drag or resize item `a` | ||
| - item `b` will be restricted to a minimum width of 2 grid blocks and a maximum width of 4 grid blocks | ||
| - users will be able to freely drag and resize item `c` | ||
| function MyGrid() { | ||
| const { width, containerRef, mounted } = useContainerWidth(); | ||
| ```js | ||
| import GridLayout from "react-grid-layout"; | ||
| const layout = [ | ||
| { i: "a", x: 0, y: 0, w: 1, h: 2, static: true }, | ||
| { i: "b", x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }, | ||
| { i: "c", x: 4, y: 0, w: 1, h: 2 } | ||
| ]; | ||
| class MyFirstGrid extends React.Component { | ||
| render() { | ||
| // layout is an array of objects, see the demo for more complete usage | ||
| const layout = [ | ||
| { i: "a", x: 0, y: 0, w: 1, h: 2, static: true }, | ||
| { i: "b", x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }, | ||
| { i: "c", x: 4, y: 0, w: 1, h: 2 } | ||
| ]; | ||
| return ( | ||
| <GridLayout | ||
| className="layout" | ||
| layout={layout} | ||
| cols={12} | ||
| rowHeight={30} | ||
| width={1200} | ||
| > | ||
| <div key="a">a</div> | ||
| <div key="b">b</div> | ||
| <div key="c">c</div> | ||
| </GridLayout> | ||
| ); | ||
| } | ||
| return ( | ||
| <div ref={containerRef}> | ||
| {mounted && ( | ||
| <ReactGridLayout | ||
| layout={layout} | ||
| width={width} | ||
| gridConfig={{ cols: 12, rowHeight: 30 }} | ||
| > | ||
| <div key="a">a</div> | ||
| <div key="b">b</div> | ||
| <div key="c">c</div> | ||
| </ReactGridLayout> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
| You may also choose to set layout properties directly on the children: | ||
| You can also define layout on children using `data-grid`: | ||
| ```js | ||
| import GridLayout from "react-grid-layout"; | ||
| ```tsx | ||
| <ReactGridLayout width={width} gridConfig={{ cols: 12, rowHeight: 30 }}> | ||
| <div key="a" data-grid={{ x: 0, y: 0, w: 1, h: 2, static: true }}> | ||
| a | ||
| </div> | ||
| <div key="b" data-grid={{ x: 1, y: 0, w: 3, h: 2 }}> | ||
| b | ||
| </div> | ||
| <div key="c" data-grid={{ x: 4, y: 0, w: 1, h: 2 }}> | ||
| c | ||
| </div> | ||
| </ReactGridLayout> | ||
| ``` | ||
| class MyFirstGrid extends React.Component { | ||
| render() { | ||
| return ( | ||
| <GridLayout className="layout" cols={12} rowHeight={30} width={1200}> | ||
| <div key="a" data-grid={{ x: 0, y: 0, w: 1, h: 2, static: true }}> | ||
| a | ||
| </div> | ||
| <div key="b" data-grid={{ x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }}> | ||
| b | ||
| </div> | ||
| <div key="c" data-grid={{ x: 4, y: 0, w: 1, h: 2 }}> | ||
| c | ||
| </div> | ||
| </GridLayout> | ||
| ); | ||
| } | ||
| ## Responsive Usage | ||
| Use `Responsive` for automatic breakpoint handling: | ||
| ```tsx | ||
| import { Responsive, useContainerWidth } from "react-grid-layout"; | ||
| function MyResponsiveGrid() { | ||
| const { width, containerRef, mounted } = useContainerWidth(); | ||
| const layouts = { | ||
| lg: [{ i: "1", x: 0, y: 0, w: 2, h: 2 }], | ||
| md: [{ i: "1", x: 0, y: 0, w: 2, h: 2 }] | ||
| }; | ||
| return ( | ||
| <div ref={containerRef}> | ||
| {mounted && ( | ||
| <Responsive | ||
| layouts={layouts} | ||
| breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} | ||
| cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }} | ||
| width={width} | ||
| > | ||
| <div key="1">1</div> | ||
| <div key="2">2</div> | ||
| <div key="3">3</div> | ||
| </Responsive> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
| ### Usage without Browserify/Webpack | ||
| ## Providing Grid Width | ||
| A module usable in a `<script>` tag is included [here](/dist/react-grid-layout.min.js). It uses a UMD shim and | ||
| excludes `React`, so it must be otherwise available in your application, either via RequireJS or on `window.React`. | ||
| The `width` prop is required. You have several options: | ||
| ### Responsive Usage | ||
| ### Option 1: useContainerWidth Hook (Recommended) | ||
| To make RGL responsive, use the `<ResponsiveReactGridLayout>` element: | ||
| ```tsx | ||
| import ReactGridLayout, { useContainerWidth } from "react-grid-layout"; | ||
| ```js | ||
| import { Responsive as ResponsiveGridLayout } from "react-grid-layout"; | ||
| function MyGrid() { | ||
| const { width, containerRef, mounted } = useContainerWidth(); | ||
| class MyResponsiveGrid extends React.Component { | ||
| render() { | ||
| // {lg: layout1, md: layout2, ...} | ||
| const layouts = getLayoutsFromSomewhere(); | ||
| return ( | ||
| <ResponsiveGridLayout | ||
| className="layout" | ||
| layouts={layouts} | ||
| breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} | ||
| cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }} | ||
| > | ||
| <div key="1">1</div> | ||
| <div key="2">2</div> | ||
| <div key="3">3</div> | ||
| </ResponsiveGridLayout> | ||
| ); | ||
| } | ||
| return ( | ||
| <div ref={containerRef}> | ||
| {mounted && <ReactGridLayout width={width}>...</ReactGridLayout>} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
| When in responsive mode, you should supply at least one breakpoint via the `layouts` property. | ||
| ### Option 2: Fixed Width | ||
| When using `layouts`, it is best to supply as many breakpoints as possible, especially the largest one. | ||
| If the largest is provided, RGL will attempt to interpolate the rest. | ||
| ```tsx | ||
| <ReactGridLayout width={1200}>...</ReactGridLayout> | ||
| ``` | ||
| You will also need to provide a `width`, when using `<ResponsiveReactGridLayout>` it is suggested you use the HOC | ||
| `WidthProvider` as per the instructions below. | ||
| ### Option 3: CSS Container Queries or ResizeObserver | ||
| It is possible to supply default mappings via the `data-grid` property on individual | ||
| items, so that they would be taken into account within layout interpolation. | ||
| Use any width measurement library like [react-sizeme](https://github.com/ctrlplusb/react-sizeme) or your own ResizeObserver implementation. | ||
| ### Providing Grid Width | ||
| ### Option 4: Legacy WidthProvider HOC | ||
| Both `<ResponsiveReactGridLayout>` and `<ReactGridLayout>` take `width` to calculate | ||
| positions on drag events. In simple cases a HOC `WidthProvider` can be used to automatically determine | ||
| width upon initialization and window resize events. | ||
| For backwards compatibility, you can still use `WidthProvider`: | ||
| ```js | ||
| import { Responsive, WidthProvider } from "react-grid-layout"; | ||
| ```tsx | ||
| import ReactGridLayout, { WidthProvider } from "react-grid-layout/legacy"; | ||
| const ResponsiveGridLayout = WidthProvider(Responsive); | ||
| const GridLayoutWithWidth = WidthProvider(ReactGridLayout); | ||
| class MyResponsiveGrid extends React.Component { | ||
| render() { | ||
| // {lg: layout1, md: layout2, ...} | ||
| var layouts = getLayoutsFromSomewhere(); | ||
| return ( | ||
| <ResponsiveGridLayout | ||
| className="layout" | ||
| layouts={layouts} | ||
| breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} | ||
| cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }} | ||
| > | ||
| <div key="1">1</div> | ||
| <div key="2">2</div> | ||
| <div key="3">3</div> | ||
| </ResponsiveGridLayout> | ||
| ); | ||
| function MyGrid() { | ||
| return <GridLayoutWithWidth>...</GridLayoutWithWidth>; | ||
| } | ||
| ``` | ||
| ## Hooks API | ||
| The v2 API provides three hooks for different use cases. Choose based on your needs: | ||
| | Hook | Use When | | ||
| | --------------------- | -------------------------------------------------------------------- | | ||
| | `useContainerWidth` | You need responsive width measurement (most common) | | ||
| | `useGridLayout` | You're building a custom grid component or need direct state control | | ||
| | `useResponsiveLayout` | You're building a custom responsive grid with breakpoint logic | | ||
| ### useContainerWidth | ||
| Observes container width using ResizeObserver and provides reactive width updates. This is the recommended way to provide width to the grid. | ||
| **Why use it instead of WidthProvider?** | ||
| - Hooks are more composable and easier to test | ||
| - No HOC wrapper means simpler component tree | ||
| - Explicit control over when to render (via `mounted`) | ||
| - Works better with SSR | ||
| ```tsx | ||
| import { useContainerWidth } from "react-grid-layout"; | ||
| function MyGrid() { | ||
| const { width, containerRef, mounted, measureWidth } = useContainerWidth({ | ||
| measureBeforeMount: false, // Set true for SSR | ||
| initialWidth: 1280 // Width before first measurement | ||
| }); | ||
| return ( | ||
| <div ref={containerRef}>{mounted && <ReactGridLayout width={width} />}</div> | ||
| ); | ||
| } | ||
| ``` | ||
| **Type Definitions:** | ||
| ```ts | ||
| interface UseContainerWidthOptions { | ||
| /** Delay render until width is measured. Useful for SSR. Default: false */ | ||
| measureBeforeMount?: boolean; | ||
| /** Initial width before measurement. Default: 1280 */ | ||
| initialWidth?: number; | ||
| } | ||
| interface UseContainerWidthResult { | ||
| /** Current container width in pixels */ | ||
| width: number; | ||
| /** Whether the container has been measured at least once */ | ||
| mounted: boolean; | ||
| /** Ref to attach to the container element */ | ||
| containerRef: RefObject<HTMLDivElement | null>; | ||
| /** Manually trigger a width measurement */ | ||
| measureWidth: () => void; | ||
| } | ||
| ``` | ||
| ### useGridLayout | ||
| Core layout state management hook. Use this when you need direct control over drag/resize/drop state, or when building a custom grid component. | ||
| **Why use it instead of the component?** | ||
| - Full control over layout state and updates | ||
| - Access to drag/resize/drop state for custom UIs | ||
| - Can integrate with external state management | ||
| - Build headless grid implementations | ||
| ```tsx | ||
| import { useGridLayout } from "react-grid-layout"; | ||
| function CustomGrid({ initialLayout }) { | ||
| const { | ||
| layout, | ||
| setLayout, | ||
| dragState, | ||
| resizeState, | ||
| onDragStart, | ||
| onDrag, | ||
| onDragStop, | ||
| onResizeStart, | ||
| onResize, | ||
| onResizeStop, | ||
| containerHeight, | ||
| isInteracting, | ||
| compactor | ||
| } = useGridLayout({ | ||
| layout: initialLayout, | ||
| cols: 12, | ||
| compactType: "vertical", | ||
| allowOverlap: false, | ||
| preventCollision: false, | ||
| onLayoutChange: newLayout => console.log("Layout changed:", newLayout) | ||
| }); | ||
| // Access drag state for custom placeholder rendering | ||
| const placeholder = dragState.activeDrag; | ||
| // Check if any interaction is happening | ||
| if (isInteracting) { | ||
| // Disable other UI during drag/resize | ||
| } | ||
| return ( | ||
| <div style={{ height: containerHeight * rowHeight }}> | ||
| {layout.map(item => ( | ||
| <div | ||
| key={item.i} | ||
| onMouseDown={() => onDragStart(item.i, item.x, item.y)} | ||
| > | ||
| {item.i} | ||
| </div> | ||
| ))} | ||
| {placeholder && <div className="placeholder" />} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
| This allows you to easily replace `WidthProvider` with your own Provider HOC if you need more sophisticated logic. | ||
| **Type Definitions:** | ||
| `WidthProvider` accepts a single prop, `measureBeforeMount`. If `true`, `WidthProvider` will measure the | ||
| container's width before mounting children. Use this if you'd like to completely eliminate any resizing animation | ||
| on application/component mount. | ||
| ```ts | ||
| interface UseGridLayoutOptions { | ||
| /** Initial layout */ | ||
| layout: Layout; | ||
| /** Number of columns */ | ||
| cols: number; | ||
| /** Compaction type: 'vertical', 'horizontal', or null */ | ||
| compactType?: CompactType; | ||
| /** Allow items to overlap */ | ||
| allowOverlap?: boolean; | ||
| /** Prevent collisions when moving items */ | ||
| preventCollision?: boolean; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| } | ||
| Have a more complicated layout? `WidthProvider` [is very simple](/lib/components/WidthProvider.jsx) and only | ||
| listens to window `'resize'` events. If you need more power and flexibility, try the | ||
| [SizeMe React HOC](https://github.com/ctrlplusb/react-sizeme) as an alternative to WidthProvider. | ||
| interface UseGridLayoutResult { | ||
| /** Current layout */ | ||
| layout: Layout; | ||
| /** Set layout directly */ | ||
| setLayout: (layout: Layout) => void; | ||
| /** Current drag state (activeDrag, oldDragItem, oldLayout) */ | ||
| dragState: DragState; | ||
| /** Current resize state (resizing, oldResizeItem, oldLayout) */ | ||
| resizeState: ResizeState; | ||
| /** Current drop state (droppingDOMNode, droppingPosition) */ | ||
| dropState: DropState; | ||
| /** Start dragging an item */ | ||
| onDragStart: (itemId: string, x: number, y: number) => LayoutItem | null; | ||
| /** Update drag position */ | ||
| onDrag: (itemId: string, x: number, y: number) => void; | ||
| /** Stop dragging */ | ||
| onDragStop: (itemId: string, x: number, y: number) => void; | ||
| /** Start resizing an item */ | ||
| onResizeStart: (itemId: string) => LayoutItem | null; | ||
| /** Update resize dimensions */ | ||
| onResize: ( | ||
| itemId: string, | ||
| w: number, | ||
| h: number, | ||
| x?: number, | ||
| y?: number | ||
| ) => void; | ||
| /** Stop resizing */ | ||
| onResizeStop: (itemId: string, w: number, h: number) => void; | ||
| /** Handle external drag over */ | ||
| onDropDragOver: ( | ||
| droppingItem: LayoutItem, | ||
| position: DroppingPosition | ||
| ) => void; | ||
| /** Handle external drag leave */ | ||
| onDropDragLeave: () => void; | ||
| /** Complete external drop */ | ||
| onDrop: (droppingItem: LayoutItem) => void; | ||
| /** Container height in grid rows */ | ||
| containerHeight: number; | ||
| /** Whether any drag/resize/drop is active */ | ||
| isInteracting: boolean; | ||
| /** The compactor being used */ | ||
| compactor: Compactor; | ||
| } | ||
| ``` | ||
| ### Grid Layout Props | ||
| ### useResponsiveLayout | ||
| RGL supports the following properties (see the source for the final word on this): | ||
| Manages responsive breakpoints and generates layouts for different screen sizes. Use this when building a custom responsive grid. | ||
| ```js | ||
| // | ||
| // Basic props | ||
| // | ||
| **Why use it instead of the Responsive component?** | ||
| // This allows setting the initial width on the server side. | ||
| // This is required unless using the HOC <WidthProvider> or similar | ||
| width: number, | ||
| - Direct access to current breakpoint | ||
| - Control over layout generation for new breakpoints | ||
| - Can update layouts for specific breakpoints | ||
| - Build custom breakpoint UIs | ||
| // If true, the container height swells and contracts to fit contents | ||
| autoSize: ?boolean = true, | ||
| ```tsx | ||
| import { useContainerWidth, useResponsiveLayout } from "react-grid-layout"; | ||
| // Number of columns in this layout. | ||
| cols: ?number = 12, | ||
| function CustomResponsiveGrid() { | ||
| const { width, containerRef, mounted } = useContainerWidth(); | ||
| // A CSS selector for tags that will not be draggable. | ||
| // For example: draggableCancel:'.MyNonDraggableAreaClassName' | ||
| // If you forget the leading . it will not work. | ||
| // .react-resizable-handle" is always prepended to this value. | ||
| draggableCancel: ?string = '', | ||
| const { | ||
| layout, // Current layout for active breakpoint | ||
| layouts, // All layouts by breakpoint | ||
| breakpoint, // Current active breakpoint ('lg', 'md', etc.) | ||
| cols, // Column count for current breakpoint | ||
| setLayoutForBreakpoint, | ||
| setLayouts, | ||
| sortedBreakpoints | ||
| } = useResponsiveLayout({ | ||
| width, | ||
| breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }, | ||
| cols: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }, | ||
| layouts: { | ||
| lg: [{ i: "1", x: 0, y: 0, w: 2, h: 2 }], | ||
| md: [{ i: "1", x: 0, y: 0, w: 3, h: 2 }] | ||
| }, | ||
| compactType: "vertical", | ||
| onBreakpointChange: (bp, cols) => | ||
| console.log(`Now at ${bp} (${cols} cols)`), | ||
| onLayoutChange: (layout, allLayouts) => saveToServer(allLayouts) | ||
| }); | ||
| // A CSS selector for tags that will act as the draggable handle. | ||
| // For example: draggableHandle:'.MyDragHandleClassName' | ||
| // If you forget the leading . it will not work. | ||
| draggableHandle: ?string = '', | ||
| // Show current breakpoint in UI | ||
| return ( | ||
| <div ref={containerRef}> | ||
| <div> | ||
| Current breakpoint: {breakpoint} ({cols} columns) | ||
| </div> | ||
| {mounted && ( | ||
| <GridLayout width={width} cols={cols} layout={layout}> | ||
| {/* children */} | ||
| </GridLayout> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
| // Compaction type. | ||
| compactType: ?('vertical' | 'horizontal' | null) = 'vertical'; | ||
| **Type Definitions:** | ||
| // Layout is an array of objects with the format: | ||
| // The index into the layout must match the key used on each item component. | ||
| // If you choose to use custom keys, you can specify that key in the layout | ||
| // array objects using the `i` prop. | ||
| layout: ?Array<{i?: string, x: number, y: number, w: number, h: number}> = null, // If not provided, use data-grid props on children | ||
| ```ts | ||
| interface UseResponsiveLayoutOptions<B extends string = DefaultBreakpoints> { | ||
| /** Current container width */ | ||
| width: number; | ||
| /** Breakpoint definitions (name → min-width). Default: {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0} */ | ||
| breakpoints?: Record<B, number>; | ||
| /** Column counts per breakpoint. Default: {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2} */ | ||
| cols?: Record<B, number>; | ||
| /** Layouts for each breakpoint */ | ||
| layouts?: Partial<Record<B, Layout>>; | ||
| /** Compaction type */ | ||
| compactType?: "vertical" | "horizontal" | null; | ||
| /** Called when breakpoint changes */ | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| /** Called when layout changes */ | ||
| onLayoutChange?: (layout: Layout, layouts: Record<B, Layout>) => void; | ||
| /** Called when width changes */ | ||
| onWidthChange?: ( | ||
| width: number, | ||
| margin: [number, number], | ||
| cols: number, | ||
| padding: [number, number] | null | ||
| ) => void; | ||
| } | ||
| // Margin between items [x, y] in px. | ||
| margin: ?[number, number] = [10, 10], | ||
| interface UseResponsiveLayoutResult<B extends string = DefaultBreakpoints> { | ||
| /** Current layout for the active breakpoint */ | ||
| layout: Layout; | ||
| /** All layouts by breakpoint */ | ||
| layouts: Partial<Record<B, Layout>>; | ||
| /** Current active breakpoint */ | ||
| breakpoint: B; | ||
| /** Column count for the current breakpoint */ | ||
| cols: number; | ||
| /** Update layout for a specific breakpoint */ | ||
| setLayoutForBreakpoint: (breakpoint: B, layout: Layout) => void; | ||
| /** Update all layouts */ | ||
| setLayouts: (layouts: Partial<Record<B, Layout>>) => void; | ||
| /** Sorted array of breakpoint names (smallest to largest) */ | ||
| sortedBreakpoints: B[]; | ||
| } | ||
| // Padding inside the container [x, y] in px | ||
| containerPadding: ?[number, number] = margin, | ||
| type DefaultBreakpoints = "lg" | "md" | "sm" | "xs" | "xxs"; | ||
| ``` | ||
| // Rows have a static height, but you can change this based on breakpoints | ||
| // if you like. | ||
| rowHeight: ?number = 150, | ||
| ## API Reference | ||
| // Configuration of a dropping element. Dropping element is a "virtual" element | ||
| // which appears when you drag over some element from outside. | ||
| // It can be changed by passing specific parameters: | ||
| // i - id of an element | ||
| // w - width of an element | ||
| // h - height of an element | ||
| droppingItem?: { i: string, w: number, h: number } | ||
| ### ReactGridLayout Props | ||
| // | ||
| // Flags | ||
| // | ||
| isDraggable: ?boolean = true, | ||
| isResizable: ?boolean = true, | ||
| isBounded: ?boolean = false, | ||
| // Uses CSS3 translate() instead of position top/left. | ||
| // This makes about 6x faster paint performance | ||
| useCSSTransforms: ?boolean = true, | ||
| // If parent DOM node of ResponsiveReactGridLayout or ReactGridLayout has "transform: scale(n)" css property, | ||
| // we should set scale coefficient to avoid render artefacts while dragging. | ||
| transformScale: ?number = 1, | ||
| The v2 API uses composable configuration interfaces for cleaner prop organization: | ||
| // If true, grid can be placed one over the other. | ||
| // If set, implies `preventCollision`. | ||
| allowOverlap: ?boolean = false, | ||
| ```ts | ||
| interface ReactGridLayoutProps { | ||
| // Required | ||
| children: React.ReactNode; | ||
| width: number; // Container width in pixels | ||
| // If true, grid items won't change position when being | ||
| // dragged over. If `allowOverlap` is still false, | ||
| // this simply won't allow one to drop on an existing object. | ||
| preventCollision: ?boolean = false, | ||
| // Configuration interfaces (see below for details) | ||
| gridConfig?: Partial<GridConfig>; // Grid measurement settings | ||
| dragConfig?: Partial<DragConfig>; // Drag behavior settings | ||
| resizeConfig?: Partial<ResizeConfig>; // Resize behavior settings | ||
| dropConfig?: Partial<DropConfig>; // External drop settings | ||
| positionStrategy?: PositionStrategy; // CSS positioning strategy | ||
| compactor?: Compactor; // Layout compaction strategy | ||
| // If true, droppable elements (with `draggable={true}` attribute) | ||
| // can be dropped on the grid. It triggers "onDrop" callback | ||
| // with position and event object as parameters. | ||
| // It can be useful for dropping an element in a specific position | ||
| // | ||
| // NOTE: In case of using Firefox you should add | ||
| // `onDragStart={e => e.dataTransfer.setData('text/plain', '')}` attribute | ||
| // along with `draggable={true}` otherwise this feature will work incorrect. | ||
| // onDragStart attribute is required for Firefox for a dragging initialization | ||
| // @see https://bugzilla.mozilla.org/show_bug.cgi?id=568313 | ||
| isDroppable: ?boolean = false, | ||
| // Defines which resize handles should be rendered. | ||
| // Allows for any combination of: | ||
| // 's' - South handle (bottom-center) | ||
| // 'w' - West handle (left-center) | ||
| // 'e' - East handle (right-center) | ||
| // 'n' - North handle (top-center) | ||
| // 'sw' - Southwest handle (bottom-left) | ||
| // 'nw' - Northwest handle (top-left) | ||
| // 'se' - Southeast handle (bottom-right) | ||
| // 'ne' - Northeast handle (top-right) | ||
| // | ||
| // Note that changing this property dynamically does not work due to a restriction in react-resizable. | ||
| resizeHandles: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se'], | ||
| // Custom component for resize handles | ||
| // See `handle` as used in https://github.com/react-grid-layout/react-resizable#resize-handle | ||
| // Your component should have the class `.react-resizable-handle`, or you should add your custom | ||
| // class to the `draggableCancel` prop. | ||
| resizeHandle?: ReactElement<any> | ((resizeHandleAxis: ResizeHandleAxis, ref: ReactRef<HTMLElement>) => ReactElement<any>), | ||
| // Layout data | ||
| layout?: Layout; // Layout definition | ||
| droppingItem?: LayoutItem; // Item configuration when dropping from outside | ||
| // | ||
| // Callbacks | ||
| // | ||
| // Container | ||
| autoSize?: boolean; // Auto-size container height (default: true) | ||
| className?: string; | ||
| style?: React.CSSProperties; | ||
| innerRef?: React.Ref<HTMLDivElement>; | ||
| // Callback so you can save the layout. | ||
| // Calls back with (currentLayout) after every drag or resize stop. | ||
| onLayoutChange: (layout: Layout) => void, | ||
| // Callbacks | ||
| onLayoutChange?: (layout: Layout) => void; | ||
| onDragStart?: EventCallback; | ||
| onDrag?: EventCallback; | ||
| onDragStop?: EventCallback; | ||
| onResizeStart?: EventCallback; | ||
| onResize?: EventCallback; | ||
| onResizeStop?: EventCallback; | ||
| onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) => void; | ||
| onDropDragOver?: (e: DragEvent) => { w?: number; h?: number } | false | void; | ||
| } | ||
| ``` | ||
| // | ||
| // All callbacks below have signature (layout, oldItem, newItem, placeholder, e, element). | ||
| // 'start' and 'stop' callbacks pass `undefined` for 'placeholder'. | ||
| // | ||
| type ItemCallback = (layout: Layout, oldItem: LayoutItem, newItem: LayoutItem, | ||
| placeholder: LayoutItem, e: MouseEvent, element: HTMLElement) => void, | ||
| ### GridConfig | ||
| // Calls when drag starts. | ||
| onDragStart: ItemCallback, | ||
| // Calls on each drag movement. | ||
| onDrag: ItemCallback, | ||
| // Calls when drag is complete. | ||
| onDragStop: ItemCallback, | ||
| // Calls when resize starts. | ||
| onResizeStart: ItemCallback, | ||
| // Calls when resize movement happens. | ||
| onResize: ItemCallback, | ||
| // Calls when resize is complete. | ||
| onResizeStop: ItemCallback, | ||
| Grid measurement configuration: | ||
| // | ||
| // Dropover functionality | ||
| // | ||
| ```ts | ||
| interface GridConfig { | ||
| cols: number; // Number of columns (default: 12) | ||
| rowHeight: number; // Row height in pixels (default: 150) | ||
| margin: [number, number]; // [x, y] margin between items (default: [10, 10]) | ||
| containerPadding: [number, number] | null; // Container padding (default: null, uses margin) | ||
| maxRows: number; // Maximum rows (default: Infinity) | ||
| } | ||
| ``` | ||
| // Calls when an element has been dropped into the grid from outside. | ||
| onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void, | ||
| // Calls when an element is being dragged over the grid from outside as above. | ||
| // This callback should return an object to dynamically change the droppingItem size | ||
| // Return false to short-circuit the dragover | ||
| onDropDragOver: (e: DragOverEvent) => ?({|w?: number, h?: number|} | false), | ||
| ### DragConfig | ||
| // Ref for getting a reference for the grid's wrapping div. | ||
| // You can use this instead of a regular ref and the deprecated `ReactDOM.findDOMNode()`` function. | ||
| // Note that this type is React.Ref<HTMLDivElement> in TypeScript, Flow has a bug here | ||
| // https://github.com/facebook/flow/issues/8671#issuecomment-862634865 | ||
| innerRef: {current: null | HTMLDivElement}, | ||
| Drag behavior configuration: | ||
| ```ts | ||
| interface DragConfig { | ||
| enabled: boolean; // Enable dragging (default: true) | ||
| bounded: boolean; // Keep items within container (default: false) | ||
| handle?: string; // CSS selector for drag handle | ||
| cancel?: string; // CSS selector to cancel dragging | ||
| threshold: number; // Pixels to move before drag starts (default: 3) | ||
| } | ||
| ``` | ||
| ### Responsive Grid Layout Props | ||
| ### ResizeConfig | ||
| The responsive grid layout can be used instead. It supports all of the props above, excepting `layout`. | ||
| The new properties and changes are: | ||
| Resize behavior configuration: | ||
| ```js | ||
| // {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480} | ||
| // Breakpoint names are arbitrary but must match in the cols and layouts objects. | ||
| breakpoints: ?Object = {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}, | ||
| ```ts | ||
| interface ResizeConfig { | ||
| enabled: boolean; // Enable resizing (default: true) | ||
| handles: ResizeHandleAxis[]; // Handle positions (default: ['se']) | ||
| handleComponent?: React.ReactNode | ((axis, ref) => React.ReactNode); | ||
| } | ||
| ``` | ||
| // # of cols. This is a breakpoint -> cols map, e.g. {lg: 12, md: 10, ...} | ||
| cols: ?Object = {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2}, | ||
| ### DropConfig | ||
| External drop configuration: | ||
| // margin (in pixels). Can be specified either as horizontal and vertical margin, e.g. `[10, 10]` or as a breakpoint -> margin map, e.g. `{lg: [10, 10], md: [10, 10], ...}. | ||
| margin: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}, | ||
| ```ts | ||
| interface DropConfig { | ||
| enabled: boolean; // Allow external drops (default: false) | ||
| defaultItem: { w: number; h: number }; // Default size (default: { w: 1, h: 1 }) | ||
| onDragOver?: (e: DragEvent) => { w?: number; h?: number } | false | void; | ||
| } | ||
| ``` | ||
| ### PositionStrategy | ||
| // containerPadding (in pixels). Can be specified either as horizontal and vertical padding, e.g. `[10, 10]` or as a breakpoint -> containerPadding map, e.g. `{lg: [10, 10], md: [10, 10], ...}. | ||
| containerPadding: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}, | ||
| CSS positioning strategy. Built-in options: | ||
| ```ts | ||
| import { | ||
| transformStrategy, // Default: use CSS transforms | ||
| absoluteStrategy, // Use top/left positioning | ||
| createScaledStrategy // For scaled containers | ||
| } from "react-grid-layout/core"; | ||
| // layouts is an object mapping breakpoints to layouts. | ||
| // e.g. {lg: Layout, md: Layout, ...} | ||
| layouts: {[key: $Keys<breakpoints>]: Layout}, | ||
| // Example: scaled container | ||
| <div style={{ transform: 'scale(0.5)' }}> | ||
| <ReactGridLayout positionStrategy={createScaledStrategy(0.5)} ... /> | ||
| </div> | ||
| ``` | ||
| // | ||
| // Callbacks | ||
| // | ||
| ### Compactor | ||
| // Calls back with breakpoint and new # cols | ||
| onBreakpointChange: (newBreakpoint: string, newCols: number) => void, | ||
| Layout compaction strategy. Built-in options: | ||
| // Callback so you can save the layout. | ||
| // AllLayouts are keyed by breakpoint. | ||
| onLayoutChange: (currentLayout: Layout, allLayouts: {[key: $Keys<breakpoints>]: Layout}) => void, | ||
| ```ts | ||
| import { | ||
| verticalCompactor, // Default: compact items upward | ||
| horizontalCompactor, // Compact items leftward | ||
| noCompactor, // No compaction (free positioning) | ||
| getCompactor // Factory: getCompactor('vertical', allowOverlap, preventCollision) | ||
| } from "react-grid-layout/core"; | ||
| ``` | ||
| // Callback when the width changes, so you can modify the layout as needed. | ||
| onWidthChange: (containerWidth: number, margin: [number, number], cols: number, containerPadding: [number, number]) => void; | ||
| ### ResponsiveGridLayout Props | ||
| Extends `GridLayoutProps` with responsive-specific props: | ||
| ```ts | ||
| interface ResponsiveGridLayoutProps<B extends string = string> { | ||
| // Responsive configuration | ||
| breakpoint?: B; // Current breakpoint (auto-detected) | ||
| breakpoints?: Record<B, number>; // Breakpoint definitions (default: {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}) | ||
| cols?: Record<B, number>; // Columns per breakpoint (default: {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2}) | ||
| layouts?: Record<B, Layout>; // Layouts per breakpoint | ||
| // Can be fixed or per-breakpoint | ||
| margin?: [number, number] | Partial<Record<B, [number, number]>>; | ||
| containerPadding?: | ||
| | [number, number] | ||
| | Partial<Record<B, [number, number] | null>> | ||
| | null; | ||
| // Callbacks | ||
| onBreakpointChange?: (newBreakpoint: B, cols: number) => void; | ||
| onLayoutChange?: (layout: Layout, layouts: Record<B, Layout>) => void; | ||
| onWidthChange?: ( | ||
| width: number, | ||
| margin: [number, number], | ||
| cols: number, | ||
| padding: [number, number] | null | ||
| ) => void; | ||
| } | ||
| ``` | ||
| ### Grid Item Props | ||
| ### Layout Item | ||
| RGL supports the following properties on grid items or layout items. When initializing a grid, | ||
| build a layout array (as in the first example above), or attach this object as the `data-grid` property | ||
| to each of your child elements (as in the second example). | ||
| ```ts | ||
| interface LayoutItem { | ||
| i: string; // Unique identifier (must match child key) | ||
| x: number; // X position in grid units | ||
| y: number; // Y position in grid units | ||
| w: number; // Width in grid units | ||
| h: number; // Height in grid units | ||
| minW?: number; // Minimum width (default: 0) | ||
| maxW?: number; // Maximum width (default: Infinity) | ||
| minH?: number; // Minimum height (default: 0) | ||
| maxH?: number; // Maximum height (default: Infinity) | ||
| static?: boolean; // If true, not draggable or resizable | ||
| isDraggable?: boolean; // Override grid isDraggable | ||
| isResizable?: boolean; // Override grid isResizable | ||
| isBounded?: boolean; // Override grid isBounded | ||
| resizeHandles?: Array<"s" | "w" | "e" | "n" | "sw" | "nw" | "se" | "ne">; | ||
| } | ||
| ``` | ||
| If `data-grid` is provided on an item, it will take precedence over an item in the `layout` with the same key (`i`). | ||
| ### Core Utilities | ||
| Note that if a grid item is provided but incomplete (missing one of `x, y, w, or h`), an error | ||
| will be thrown so you can correct your layout. | ||
| Import pure layout functions from `react-grid-layout/core`: | ||
| If no properties are provided for a grid item, one will be generated with a width and height of `1`. | ||
| ```ts | ||
| import { | ||
| compact, | ||
| moveElement, | ||
| collides, | ||
| getFirstCollision, | ||
| validateLayout | ||
| // ... and more | ||
| } from "react-grid-layout/core"; | ||
| ``` | ||
| You can set minimums and maximums for each dimension. This is for resizing; it of course has no effect if resizing | ||
| is disabled. Errors will be thrown if your mins and maxes overlap incorrectly, or your initial dimensions | ||
| are out of range. | ||
| ## Extending: Custom Compactors & Position Strategies | ||
| Any `<GridItem>` properties defined directly will take precedence over globally-set options. For | ||
| example, if the layout has the property `isDraggable: false`, but the grid item has the prop `isDraggable: true`, the item | ||
| will be draggable, even if the item is marked `static: true`. | ||
| ### Creating a Custom Compactor | ||
| ```js | ||
| { | ||
| Compactors control how items are arranged after drag/resize. Create your own for custom layouts like masonry, gravity, or shelf-packing. | ||
| // A string corresponding to the component key | ||
| i: string, | ||
| **The Compactor Interface:** | ||
| // These are all in grid units, not pixels | ||
| x: number, | ||
| y: number, | ||
| w: number, | ||
| h: number, | ||
| minW: ?number = 0, | ||
| maxW: ?number = Infinity, | ||
| minH: ?number = 0, | ||
| maxH: ?number = Infinity, | ||
| ```ts | ||
| interface Compactor { | ||
| /** Identifies the compaction type */ | ||
| type: "vertical" | "horizontal" | null | string; | ||
| // If true, equal to `isDraggable: false, isResizable: false`. | ||
| static: ?boolean = false, | ||
| // If false, will not be draggable. Overrides `static`. | ||
| isDraggable: ?boolean = true, | ||
| // If false, will not be resizable. Overrides `static`. | ||
| isResizable: ?boolean = true, | ||
| // By default, a handle is only shown on the bottom-right (southeast) corner. | ||
| // As of RGL >= 1.4.0, resizing on any corner works just fine! | ||
| resizeHandles?: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se'] | ||
| // If true and draggable, item will be moved only within grid. | ||
| isBounded: ?boolean = false | ||
| /** Whether this compactor allows overlapping items */ | ||
| allowOverlap: boolean; | ||
| /** Prevent items from moving when another item is dragged into them */ | ||
| preventCollision?: boolean; | ||
| /** | ||
| * Compact the entire layout. | ||
| * Called after any layout change to fill gaps. | ||
| * | ||
| * @param layout - Array of layout items (clone before mutating!) | ||
| * @param cols - Number of grid columns | ||
| * @returns New compacted layout | ||
| */ | ||
| compact(layout: Layout, cols: number): Layout; | ||
| /** | ||
| * Handle moving an item. | ||
| * Called during drag to preview the new position. | ||
| * | ||
| * @param layout - Current layout | ||
| * @param item - Item being moved | ||
| * @param x - New X position in grid units | ||
| * @param y - New Y position in grid units | ||
| * @param cols - Number of grid columns | ||
| * @returns Updated layout with item at new position | ||
| */ | ||
| onMove( | ||
| layout: Layout, | ||
| item: LayoutItem, | ||
| x: number, | ||
| y: number, | ||
| cols: number | ||
| ): Layout; | ||
| } | ||
| ``` | ||
| ### Grid Item Heights and Widths | ||
| **Example: Gravity Compactor (items fall to bottom)** | ||
| Grid item widths are based on container and number of columns. The size of a grid unit's height is based on `rowHeight`. | ||
| ```ts | ||
| import { cloneLayout, cloneLayoutItem, getStatics, bottom } from "react-grid-layout/core"; | ||
| Note that an item that has `h=2` is _not exactly twice as tall as one with `h=1` unless you have no `margin`_! | ||
| const gravityCompactor: Compactor = { | ||
| type: "gravity", | ||
| allowOverlap: false, | ||
| In order for the grid to not be ragged, when an item spans grid units, it must also span margins. So you must add the height or width or the margin you are spanning for each unit. So actual pixel height is `(rowHeight * h) + (marginH * (h - 1)`. | ||
| compact(layout, cols) { | ||
| const statics = getStatics(layout); | ||
| const maxY = 100; // arbitrary max height | ||
| const out = []; | ||
| For example, with `rowHeight=30`, `margin=[10,10]` and a unit with height 4, the calculation is `(30 * 4) + (10 * 3)` | ||
| // Sort by Y descending (process bottom items first) | ||
| const sorted = [...layout].sort((a, b) => b.y - a.y); | ||
|  | ||
| for (const item of sorted) { | ||
| const l = cloneLayoutItem(item); | ||
| If this is a problem for you, set `margin=[0,0]` and handle visual spacing between your elements inside the elements' content. | ||
| if (!l.static) { | ||
| // Move down as far as possible | ||
| while (l.y < maxY && !collides(l, statics)) { | ||
| l.y++; | ||
| } | ||
| l.y--; // Back up one | ||
| } | ||
| ### Performance | ||
| out.push(l); | ||
| } | ||
| `<ReactGridLayout>` has [an optimized `shouldComponentUpdate` implementation](lib/ReactGridLayout.jsx), but it relies on the user memoizing the `children` array: | ||
| return out; | ||
| }, | ||
| ```js | ||
| // lib/ReactGridLayout.jsx | ||
| // ... | ||
| shouldComponentUpdate(nextProps: Props, nextState: State) { | ||
| onMove(layout, item, x, y, cols) { | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find(l => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = y; | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| // Usage | ||
| <GridLayout compactor={gravityCompactor} /> | ||
| ``` | ||
| **Example: Single Row Compactor (horizontal shelf)** | ||
| ```ts | ||
| const singleRowCompactor: Compactor = { | ||
| type: "shelf", | ||
| allowOverlap: false, | ||
| compact(layout, cols) { | ||
| let x = 0; | ||
| const out = []; | ||
| // Sort by original X position | ||
| const sorted = [...layout].sort((a, b) => a.x - b.x); | ||
| for (const item of sorted) { | ||
| const l = cloneLayoutItem(item); | ||
| if (!l.static) { | ||
| l.x = x; | ||
| l.y = 0; // All items on row 0 | ||
| x += l.w; | ||
| // Wrap to next row if overflow | ||
| if (x > cols) { | ||
| l.x = 0; | ||
| x = l.w; | ||
| } | ||
| } | ||
| out.push(l); | ||
| } | ||
| return out; | ||
| }, | ||
| onMove(layout, item, x, y, cols) { | ||
| // Same as default - just update position | ||
| const newLayout = cloneLayout(layout); | ||
| const movedItem = newLayout.find(l => l.i === item.i); | ||
| if (movedItem) { | ||
| movedItem.x = x; | ||
| movedItem.y = 0; // Force row 0 | ||
| movedItem.moved = true; | ||
| } | ||
| return newLayout; | ||
| } | ||
| }; | ||
| ``` | ||
| **Using Helper Functions:** | ||
| The core module exports helpers for building compactors: | ||
| ```ts | ||
| import { | ||
| resolveCompactionCollision, // Move items to resolve overlaps | ||
| compactItemVertical, // Compact one item upward | ||
| compactItemHorizontal, // Compact one item leftward | ||
| getFirstCollision, // Find first collision | ||
| collides, // Check if two items collide | ||
| getStatics, // Get static items from layout | ||
| cloneLayout, // Clone layout array | ||
| cloneLayoutItem // Clone single item | ||
| } from "react-grid-layout/core"; | ||
| ``` | ||
| ### Creating a Custom Position Strategy | ||
| Position strategies control how items are positioned via CSS. Create custom strategies for special transform handling. | ||
| **The PositionStrategy Interface:** | ||
| ```ts | ||
| interface PositionStrategy { | ||
| /** Type identifier */ | ||
| type: "transform" | "absolute" | string; | ||
| /** Scale factor for coordinate calculations */ | ||
| scale: number; | ||
| /** | ||
| * Generate CSS styles for positioning an item. | ||
| * | ||
| * @param pos - Position with top, left, width, height in pixels | ||
| * @returns CSS properties object | ||
| */ | ||
| calcStyle(pos: Position): React.CSSProperties; | ||
| /** | ||
| * Calculate drag position from mouse coordinates. | ||
| * Used during drag to convert screen coords to grid coords. | ||
| * | ||
| * @param clientX - Mouse X position | ||
| * @param clientY - Mouse Y position | ||
| * @param offsetX - Offset from item left edge | ||
| * @param offsetY - Offset from item top edge | ||
| * @returns Calculated left/top position | ||
| */ | ||
| calcDragPosition( | ||
| clientX: number, | ||
| clientY: number, | ||
| offsetX: number, | ||
| offsetY: number | ||
| ): { left: number; top: number }; | ||
| } | ||
| ``` | ||
| **Example: Rotated Container Strategy** | ||
| ```ts | ||
| const createRotatedStrategy = (angleDegrees: number): PositionStrategy => { | ||
| const angleRad = (angleDegrees * Math.PI) / 180; | ||
| const cos = Math.cos(angleRad); | ||
| const sin = Math.sin(angleRad); | ||
| return { | ||
| type: "rotated", | ||
| scale: 1, | ||
| calcStyle(pos) { | ||
| // Apply rotation to position | ||
| const rotatedX = pos.left * cos - pos.top * sin; | ||
| const rotatedY = pos.left * sin + pos.top * cos; | ||
| return { | ||
| transform: `translate(${rotatedX}px, ${rotatedY}px)`, | ||
| width: `${pos.width}px`, | ||
| height: `${pos.height}px`, | ||
| position: "absolute" | ||
| }; | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| // Reverse the rotation for drag calculations | ||
| const x = clientX - offsetX; | ||
| const y = clientY - offsetY; | ||
| return { | ||
| left: x * cos + y * sin, | ||
| top: -x * sin + y * cos | ||
| }; | ||
| } | ||
| }; | ||
| }; | ||
| // Usage: grid inside a rotated container | ||
| <div style={{ transform: 'rotate(45deg)' }}> | ||
| <GridLayout positionStrategy={createRotatedStrategy(45)} /> | ||
| </div> | ||
| ``` | ||
| **Example: 3D Perspective Strategy** | ||
| ```ts | ||
| const create3DStrategy = ( | ||
| perspective: number, | ||
| rotateX: number | ||
| ): PositionStrategy => ({ | ||
| type: "3d", | ||
| scale: 1, | ||
| calcStyle(pos) { | ||
| return { | ||
| transform: ` | ||
| perspective(${perspective}px) | ||
| rotateX(${rotateX}deg) | ||
| translate3d(${pos.left}px, ${pos.top}px, 0) | ||
| `, | ||
| width: `${pos.width}px`, | ||
| height: `${pos.height}px`, | ||
| position: "absolute", | ||
| transformStyle: "preserve-3d" | ||
| }; | ||
| }, | ||
| calcDragPosition(clientX, clientY, offsetX, offsetY) { | ||
| // Adjust for perspective foreshortening | ||
| const perspectiveFactor = 1 + clientY / perspective; | ||
| return { | ||
| left: (clientX - offsetX) / perspectiveFactor, | ||
| top: (clientY - offsetY) / perspectiveFactor | ||
| }; | ||
| } | ||
| }); | ||
| ``` | ||
| ## Extras | ||
| The `react-grid-layout/extras` entry point provides optional components that extend react-grid-layout. These are tree-shakeable and won't be included in your bundle unless explicitly imported. | ||
| ### GridBackground | ||
| Renders an SVG grid background that aligns with GridLayout cells. Use this to visualize the grid structure behind your layout. | ||
| > Based on [PR #2175](https://github.com/react-grid-layout/react-grid-layout/pull/2175) by [@nicosayer](https://github.com/nicosayer). | ||
| ```tsx | ||
| import { GridBackground } from "react-grid-layout/extras"; | ||
| import ReactGridLayout, { useContainerWidth } from "react-grid-layout"; | ||
| function MyGrid() { | ||
| const { width, containerRef, mounted } = useContainerWidth(); | ||
| return ( | ||
| // NOTE: this is almost always unequal. Therefore the only way to get better performance | ||
| // from SCU is if the user intentionally memoizes children. If they do, and they can | ||
| // handle changes properly, performance will increase. | ||
| this.props.children !== nextProps.children || | ||
| !fastRGLPropsEqual(this.props, nextProps, isEqual) || | ||
| !isEqual(this.state.activeDrag, nextState.activeDrag) | ||
| <div ref={containerRef} style={{ position: "relative" }}> | ||
| {mounted && ( | ||
| <> | ||
| <GridBackground | ||
| width={width} | ||
| cols={12} | ||
| rowHeight={30} | ||
| margin={[10, 10]} | ||
| rows={10} | ||
| color="#f0f0f0" | ||
| borderRadius={4} | ||
| /> | ||
| <ReactGridLayout | ||
| width={width} | ||
| gridConfig={{ cols: 12, rowHeight: 30, margin: [10, 10] }} | ||
| > | ||
| {children} | ||
| </ReactGridLayout> | ||
| </> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
| // ... | ||
| ``` | ||
| If you memoize your children, you can take advantage of this, and reap faster rerenders. For example: | ||
| **Props:** | ||
| ```js | ||
| function MyGrid(props) { | ||
| const children = React.useMemo(() => { | ||
| return new Array(props.count).fill(undefined).map((val, idx) => { | ||
| return <div key={idx} data-grid={{ x: idx, y: 1, w: 1, h: 1 }} />; | ||
| }); | ||
| }, [props.count]); | ||
| return <ReactGridLayout cols={12}>{children}</ReactGridLayout>; | ||
| ```ts | ||
| interface GridBackgroundProps { | ||
| // Required - must match your GridLayout config | ||
| width: number; // Container width | ||
| cols: number; // Number of columns | ||
| rowHeight: number; // Row height in pixels | ||
| // Optional | ||
| margin?: [number, number]; // Gap between cells (default: [10, 10]) | ||
| containerPadding?: [number, number] | null; // Container padding (default: uses margin) | ||
| rows?: number | "auto"; // Number of rows to display (default: 10) | ||
| height?: number; // Used when rows="auto" to calculate row count | ||
| color?: string; // Cell background color (default: "#e0e0e0") | ||
| borderRadius?: number; // Cell border radius (default: 4) | ||
| className?: string; // Additional CSS class | ||
| style?: React.CSSProperties; // Additional inline styles | ||
| } | ||
| ``` | ||
| Because the `children` prop doesn't change between rerenders, updates to `<MyGrid>` won't result in new renders, improving performance. | ||
| ### calcGridCellDimensions (Core Utility) | ||
| ### React Hooks Performance | ||
| For building custom grid overlays or backgrounds, use the `calcGridCellDimensions` utility from `react-grid-layout/core`: | ||
| Using hooks to save your layout state on change will cause the layouts to re-render as the ResponsiveGridLayout will change it's value on every render. | ||
| To avoid this you should wrap your WidthProvider in a useMemo: | ||
| ```ts | ||
| import { calcGridCellDimensions } from "react-grid-layout/core"; | ||
| ```js | ||
| const ResponsiveReactGridLayout = useMemo(() => WidthProvider(Responsive), []); | ||
| const dims = calcGridCellDimensions({ | ||
| width: 1200, | ||
| cols: 12, | ||
| rowHeight: 30, | ||
| margin: [10, 10], | ||
| containerPadding: [20, 20] | ||
| }); | ||
| // dims = { | ||
| // cellWidth: 88.33, // Width of each cell | ||
| // cellHeight: 30, // Height of each cell (= rowHeight) | ||
| // offsetX: 20, // Left padding | ||
| // offsetY: 20, // Top padding | ||
| // gapX: 10, // Horizontal gap between cells | ||
| // gapY: 10, // Vertical gap between cells | ||
| // cols: 12, // Column count | ||
| // containerWidth: 1200 | ||
| // } | ||
| ``` | ||
| ### Custom Child Components and Draggable Handles | ||
| This is useful for building custom visualizations, snap-to-grid functionality, or integrating with canvas/WebGL renderers. | ||
| If you use React Components as grid children, they need to do a few things: | ||
| ## Performance | ||
| 1. Forward refs to an underlying DOM node, and | ||
| 2. Forward `style`,`className`, `onMouseDown`, `onMouseUp` and `onTouchEnd` to that same DOM node. | ||
| ### Memoize Children | ||
| For example: | ||
| The grid compares children by reference. Memoize them for better performance: | ||
| ```js | ||
| const CustomGridItemComponent = React.forwardRef(({style, className, onMouseDown, onMouseUp, onTouchEnd, children, ...props}, ref) => { | ||
| ```tsx | ||
| function MyGrid({ count, width }) { | ||
| const children = useMemo(() => { | ||
| return Array.from({ length: count }, (_, i) => ( | ||
| <div | ||
| key={i} | ||
| data-grid={{ x: i % 12, y: Math.floor(i / 12), w: 1, h: 1 }} | ||
| /> | ||
| )); | ||
| }, [count]); | ||
| return ( | ||
| <div style={{ /* styles */, ...style}} className={className} ref={ref} onMouseDown={onMouseDown} onMouseUp={onMouseUp} onTouchEnd={onTouchEnd}> | ||
| {/* Some other content */} | ||
| {children} {/* Make sure to include children to add resizable handle */} | ||
| </div> | ||
| <ReactGridLayout width={width} gridConfig={{ cols: 12 }}> | ||
| {children} | ||
| </ReactGridLayout> | ||
| ); | ||
| }) | ||
| } | ||
| ``` | ||
| The same is true of custom elements as draggable handles using the `draggableHandle` prop. This is so that | ||
| the underlying `react-draggable` library can get a reference to the DOM node underneath, manipulate | ||
| positioning via `style`, and set classes. | ||
| ### Avoid Creating Components in Render (Legacy WidthProvider) | ||
| If using the legacy WidthProvider HOC, don't create the component during render: | ||
| ```tsx | ||
| import ReactGridLayout, { WidthProvider } from "react-grid-layout/legacy"; | ||
| // Bad - creates new component every render | ||
| function MyGrid() { | ||
| const GridLayoutWithWidth = WidthProvider(ReactGridLayout); | ||
| return <GridLayoutWithWidth>...</GridLayoutWithWidth>; | ||
| } | ||
| // Good - create once outside or with useMemo | ||
| const GridLayoutWithWidth = WidthProvider(ReactGridLayout); | ||
| function MyGrid() { | ||
| return <GridLayoutWithWidth>...</GridLayoutWithWidth>; | ||
| } | ||
| ``` | ||
| With the v2 API, use `useContainerWidth` hook instead to avoid this issue entirely. | ||
| ## Custom Child Components | ||
| Grid children must forward refs and certain props: | ||
| ```tsx | ||
| const CustomItem = forwardRef<HTMLDivElement, CustomItemProps>( | ||
| ( | ||
| { | ||
| style, | ||
| className, | ||
| onMouseDown, | ||
| onMouseUp, | ||
| onTouchEnd, | ||
| children, | ||
| ...props | ||
| }, | ||
| ref | ||
| ) => { | ||
| return ( | ||
| <div | ||
| ref={ref} | ||
| style={style} | ||
| className={className} | ||
| onMouseDown={onMouseDown} | ||
| onMouseUp={onMouseUp} | ||
| onTouchEnd={onTouchEnd} | ||
| > | ||
| {children} | ||
| </div> | ||
| ); | ||
| } | ||
| ); | ||
| ``` | ||
| ## Contribute | ||
@@ -613,17 +1271,1 @@ | ||
| us easily isolate it. | ||
| ## TODO List | ||
| - [x] Basic grid layout | ||
| - [x] Fluid grid layout | ||
| - [x] Grid packing | ||
| - [x] Draggable grid items | ||
| - [x] Live grid packing while dragging | ||
| - [x] Resizable grid items | ||
| - [x] Layouts per responsive breakpoint | ||
| - [x] Define grid attributes on children themselves (`data-grid` key) | ||
| - [x] Static elements | ||
| - [x] Persistent id per item for predictable localstorage restores, even when # items changes | ||
| - [x] Min/max w/h per item | ||
| - [x] Resizable handles on other corners | ||
| - [ ] Configurable w/h per breakpoint |
-22
| // @flow | ||
| const es6Compat = | ||
| process.env.BABEL_ES_COMPAT === "6" || process.env.NODE_ENV === "test"; | ||
| module.exports = { | ||
| presets: [ | ||
| [ | ||
| "@babel/preset-env", | ||
| { | ||
| targets: es6Compat ? "maintained node versions" : "> 0.25%, not dead" | ||
| } | ||
| ], | ||
| "@babel/react", | ||
| "@babel/preset-flow" | ||
| ], | ||
| plugins: [ | ||
| "@babel/plugin-transform-flow-comments", | ||
| "@babel/plugin-transform-class-properties", | ||
| "babel-plugin-preval" | ||
| ] | ||
| }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
-17
| { | ||
| "printWidth": 80, | ||
| "tabWidth": 2, | ||
| "useTabs": false, | ||
| "semi": true, | ||
| "singleQuote": false, | ||
| "quoteProps": "as-needed", | ||
| "jsxSingleQuote": false, | ||
| "trailingComma": "none", | ||
| "bracketSpacing": true, | ||
| "arrowParens": "avoid", | ||
| "requirePragma": false, | ||
| "insertPragma": false, | ||
| "proseWrap": "preserve", | ||
| "htmlWhitespaceSensitivity": "css", | ||
| "endOfLine": "auto" | ||
| } |
| "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); | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.default = WidthProvideRGL; | ||
| var React = _interopRequireWildcard(require("react")); | ||
| var _propTypes = _interopRequireDefault(require("prop-types")); | ||
| var _resizeObserverPolyfill = _interopRequireDefault(require("resize-observer-polyfill")); | ||
| var _clsx = _interopRequireDefault(require("clsx")); | ||
| const _excluded = ["measureBeforeMount"]; | ||
| function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
| function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } | ||
| function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } | ||
| function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } | ||
| function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } | ||
| function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } | ||
| function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } | ||
| function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } | ||
| /*:: import type { ReactRef } from "../ReactGridLayoutPropTypes";*/ | ||
| /*:: type WPDefaultProps = {| | ||
| measureBeforeMount: boolean | ||
| |};*/ | ||
| /*:: type WPProps = {| | ||
| className?: string, | ||
| style?: Object, | ||
| ...WPDefaultProps | ||
| |};*/ | ||
| // eslint-disable-next-line no-unused-vars | ||
| /*:: type WPState = {| | ||
| width: number | ||
| |};*/ | ||
| /*:: type ComposedProps<Config> = {| | ||
| ...Config, | ||
| measureBeforeMount?: boolean, | ||
| className?: string, | ||
| style?: Object, | ||
| width?: number | ||
| |};*/ | ||
| const layoutClassName = "react-grid-layout"; | ||
| /* | ||
| * A simple HOC that provides facility for listening to container resizes. | ||
| * | ||
| * The Flow type is pretty janky here. I can't just spread `WPProps` into this returned object - I wish I could - but it triggers | ||
| * a flow bug of some sort that causes it to stop typechecking. | ||
| */ | ||
| function WidthProvideRGL /*:: <Config>*/(ComposedComponent /*: React.AbstractComponent<Config>*/) /*: React.AbstractComponent<ComposedProps<Config>>*/{ | ||
| var _WidthProvider; | ||
| return _WidthProvider = class WidthProvider extends React.Component | ||
| /*:: < | ||
| ComposedProps<Config>, | ||
| WPState | ||
| >*/ | ||
| { | ||
| constructor() { | ||
| super(...arguments); | ||
| _defineProperty(this, "state", { | ||
| width: 1280 | ||
| }); | ||
| _defineProperty(this, "elementRef", /*#__PURE__*/React.createRef()); | ||
| _defineProperty(this, "mounted", false); | ||
| _defineProperty(this, "resizeObserver", void 0); | ||
| } | ||
| componentDidMount() { | ||
| this.mounted = true; | ||
| this.resizeObserver = new _resizeObserverPolyfill.default(entries => { | ||
| const node = this.elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| const width = entries[0].contentRect.width; | ||
| this.setState({ | ||
| width | ||
| }); | ||
| } | ||
| }); | ||
| const node = this.elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| this.resizeObserver.observe(node); | ||
| } | ||
| } | ||
| componentWillUnmount() { | ||
| this.mounted = false; | ||
| const node = this.elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| this.resizeObserver.unobserve(node); | ||
| } | ||
| this.resizeObserver.disconnect(); | ||
| } | ||
| render() { | ||
| const _this$props = this.props, | ||
| { | ||
| measureBeforeMount | ||
| } = _this$props, | ||
| rest = _objectWithoutProperties(_this$props, _excluded); | ||
| if (measureBeforeMount && !this.mounted) { | ||
| return /*#__PURE__*/React.createElement("div", { | ||
| className: (0, _clsx.default)(this.props.className, layoutClassName), | ||
| style: this.props.style | ||
| // $FlowIgnore ref types | ||
| , | ||
| ref: this.elementRef | ||
| }); | ||
| } | ||
| return /*#__PURE__*/React.createElement(ComposedComponent, _extends({ | ||
| innerRef: this.elementRef | ||
| }, rest, this.state)); | ||
| } | ||
| }, _defineProperty(_WidthProvider, "defaultProps", { | ||
| measureBeforeMount: false | ||
| }), _defineProperty(_WidthProvider, "propTypes", { | ||
| // If true, will not render children until mounted. Useful for getting the exact width before | ||
| // rendering, to prevent any unsightly resizing. | ||
| measureBeforeMount: _propTypes.default.bool | ||
| }), _WidthProvider; | ||
| } |
| // this file was prevaled | ||
| module.exports = function fastRGLPropsEqual(a, b, isEqualImpl) { | ||
| if (a === b) return true; | ||
| return a.className === b.className && isEqualImpl(a.style, b.style) && a.width === b.width && a.autoSize === b.autoSize && a.cols === b.cols && a.draggableCancel === b.draggableCancel && a.draggableHandle === b.draggableHandle && isEqualImpl(a.verticalCompact, b.verticalCompact) && isEqualImpl(a.compactType, b.compactType) && isEqualImpl(a.layout, b.layout) && isEqualImpl(a.margin, b.margin) && isEqualImpl(a.containerPadding, b.containerPadding) && a.rowHeight === b.rowHeight && a.maxRows === b.maxRows && a.isBounded === b.isBounded && a.isDraggable === b.isDraggable && a.isResizable === b.isResizable && a.allowOverlap === b.allowOverlap && a.preventCollision === b.preventCollision && a.useCSSTransforms === b.useCSSTransforms && a.transformScale === b.transformScale && a.isDroppable === b.isDroppable && isEqualImpl(a.resizeHandles, b.resizeHandles) && isEqualImpl(a.resizeHandle, b.resizeHandle) && a.onLayoutChange === b.onLayoutChange && a.onDragStart === b.onDragStart && a.onDrag === b.onDrag && a.onDragStop === b.onDragStop && a.onResizeStart === b.onResizeStart && a.onResize === b.onResize && a.onResizeStop === b.onResizeStop && a.onDrop === b.onDrop && isEqualImpl(a.droppingItem, b.droppingItem) && isEqualImpl(a.innerRef, b.innerRef); | ||
| }; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.default = void 0; | ||
| var _react = _interopRequireDefault(require("react")); | ||
| var _reactDom = require("react-dom"); | ||
| var _propTypes = _interopRequireDefault(require("prop-types")); | ||
| var _reactDraggable = require("react-draggable"); | ||
| var _reactResizable = require("react-resizable"); | ||
| var _utils = require("./utils"); | ||
| var _calculateUtils = require("./calculateUtils"); | ||
| var _ReactGridLayoutPropTypes = require("./ReactGridLayoutPropTypes"); | ||
| var _clsx = _interopRequireDefault(require("clsx")); | ||
| function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
| function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
| function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
| function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } | ||
| function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } | ||
| function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } | ||
| /*:: import type { Element as ReactElement, Node as ReactNode } from "react";*/ | ||
| /*:: import type { | ||
| ReactDraggableCallbackData, | ||
| GridDragEvent, | ||
| GridResizeEvent, | ||
| DroppingPosition, | ||
| Position, | ||
| ResizeHandleAxis | ||
| } from "./utils";*/ | ||
| /*:: import type { PositionParams } from "./calculateUtils";*/ | ||
| /*:: import type { ResizeHandle, ReactRef } from "./ReactGridLayoutPropTypes";*/ | ||
| /*:: type PartialPosition = { top: number, left: number };*/ | ||
| /*:: type GridItemCallback<Data: GridDragEvent | GridResizeEvent> = ( | ||
| i: string, | ||
| w: number, | ||
| h: number, | ||
| Data | ||
| ) => void;*/ | ||
| /*:: type ResizeCallbackData = { | ||
| node: HTMLElement, | ||
| size: Position, | ||
| handle: ResizeHandleAxis | ||
| };*/ | ||
| /*:: type GridItemResizeCallback = ( | ||
| e: Event, | ||
| data: ResizeCallbackData, | ||
| position: Position | ||
| ) => void;*/ | ||
| /*:: type State = { | ||
| resizing: ?{ top: number, left: number, width: number, height: number }, | ||
| dragging: ?{ top: number, left: number }, | ||
| className: string | ||
| };*/ | ||
| /*:: type Props = { | ||
| children: ReactElement<any>, | ||
| cols: number, | ||
| containerWidth: number, | ||
| margin: [number, number], | ||
| containerPadding: [number, number], | ||
| rowHeight: number, | ||
| maxRows: number, | ||
| isDraggable: boolean, | ||
| isResizable: boolean, | ||
| isBounded: boolean, | ||
| static?: boolean, | ||
| useCSSTransforms?: boolean, | ||
| usePercentages?: boolean, | ||
| transformScale: number, | ||
| droppingPosition?: DroppingPosition, | ||
| className: string, | ||
| style?: Object, | ||
| // Draggability | ||
| cancel: string, | ||
| handle: string, | ||
| x: number, | ||
| y: number, | ||
| w: number, | ||
| h: number, | ||
| minW: number, | ||
| maxW: number, | ||
| minH: number, | ||
| maxH: number, | ||
| i: string, | ||
| resizeHandles?: ResizeHandleAxis[], | ||
| resizeHandle?: ResizeHandle, | ||
| onDrag?: GridItemCallback<GridDragEvent>, | ||
| onDragStart?: GridItemCallback<GridDragEvent>, | ||
| onDragStop?: GridItemCallback<GridDragEvent>, | ||
| onResize?: GridItemCallback<GridResizeEvent>, | ||
| onResizeStart?: GridItemCallback<GridResizeEvent>, | ||
| onResizeStop?: GridItemCallback<GridResizeEvent> | ||
| };*/ | ||
| /*:: type DefaultProps = { | ||
| className: string, | ||
| cancel: string, | ||
| handle: string, | ||
| minH: number, | ||
| minW: number, | ||
| maxH: number, | ||
| maxW: number, | ||
| transformScale: number | ||
| };*/ | ||
| /** | ||
| * An individual item within a ReactGridLayout. | ||
| */ | ||
| class GridItem extends _react.default.Component /*:: <Props, State>*/{ | ||
| constructor() { | ||
| super(...arguments); | ||
| _defineProperty(this, "state", { | ||
| resizing: null, | ||
| dragging: null, | ||
| className: "" | ||
| }); | ||
| _defineProperty(this, "elementRef", /*#__PURE__*/_react.default.createRef()); | ||
| /** | ||
| * onDragStart event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node, delta and position information | ||
| */ | ||
| _defineProperty(this, "onDragStart", (e, _ref) => { | ||
| let { | ||
| node | ||
| } = _ref; | ||
| const { | ||
| onDragStart, | ||
| transformScale | ||
| } = this.props; | ||
| if (!onDragStart) return; | ||
| const newPosition /*: PartialPosition*/ = { | ||
| top: 0, | ||
| left: 0 | ||
| }; | ||
| // TODO: this wont work on nested parents | ||
| const { | ||
| offsetParent | ||
| } = node; | ||
| if (!offsetParent) return; | ||
| const parentRect = offsetParent.getBoundingClientRect(); | ||
| const clientRect = node.getBoundingClientRect(); | ||
| const cLeft = clientRect.left / transformScale; | ||
| const pLeft = parentRect.left / transformScale; | ||
| const cTop = clientRect.top / transformScale; | ||
| const pTop = parentRect.top / transformScale; | ||
| newPosition.left = cLeft - pLeft + offsetParent.scrollLeft; | ||
| newPosition.top = cTop - pTop + offsetParent.scrollTop; | ||
| this.setState({ | ||
| dragging: newPosition | ||
| }); | ||
| // Call callback with this data | ||
| const { | ||
| x, | ||
| y | ||
| } = (0, _calculateUtils.calcXY)(this.getPositionParams(), newPosition.top, newPosition.left, this.props.w, this.props.h); | ||
| return onDragStart.call(this, this.props.i, x, y, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }); | ||
| /** | ||
| * onDrag event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node, delta and position information | ||
| * @param {boolean} dontFlush if true, will not call flushSync | ||
| */ | ||
| _defineProperty(this, "onDrag", (e, _ref2, dontFlush) => { | ||
| let { | ||
| node, | ||
| deltaX, | ||
| deltaY | ||
| } = _ref2; | ||
| const { | ||
| onDrag | ||
| } = this.props; | ||
| if (!onDrag) return; | ||
| if (!this.state.dragging) { | ||
| throw new Error("onDrag called before onDragStart."); | ||
| } | ||
| let top = this.state.dragging.top + deltaY; | ||
| let left = this.state.dragging.left + deltaX; | ||
| const { | ||
| isBounded, | ||
| i, | ||
| w, | ||
| h, | ||
| containerWidth | ||
| } = this.props; | ||
| const positionParams = this.getPositionParams(); | ||
| // Boundary calculations; keeps items within the grid | ||
| if (isBounded) { | ||
| const { | ||
| offsetParent | ||
| } = node; | ||
| if (offsetParent) { | ||
| const { | ||
| margin, | ||
| rowHeight | ||
| } = this.props; | ||
| const bottomBoundary = offsetParent.clientHeight - (0, _calculateUtils.calcGridItemWHPx)(h, rowHeight, margin[1]); | ||
| top = (0, _calculateUtils.clamp)(top, 0, bottomBoundary); | ||
| const colWidth = (0, _calculateUtils.calcGridColWidth)(positionParams); | ||
| const rightBoundary = containerWidth - (0, _calculateUtils.calcGridItemWHPx)(w, colWidth, margin[0]); | ||
| left = (0, _calculateUtils.clamp)(left, 0, rightBoundary); | ||
| } | ||
| } | ||
| const newPosition /*: PartialPosition*/ = { | ||
| top, | ||
| left | ||
| }; | ||
| // dontFlush is set if we're calling from inside | ||
| if (dontFlush) { | ||
| this.setState({ | ||
| dragging: newPosition | ||
| }); | ||
| } else { | ||
| (0, _reactDom.flushSync)(() => { | ||
| this.setState({ | ||
| dragging: newPosition | ||
| }); | ||
| }); | ||
| } | ||
| // Call callback with this data | ||
| const { | ||
| x, | ||
| y | ||
| } = (0, _calculateUtils.calcXY)(positionParams, top, left, w, h); | ||
| return onDrag.call(this, i, x, y, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }); | ||
| /** | ||
| * onDragStop event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node, delta and position information | ||
| */ | ||
| _defineProperty(this, "onDragStop", (e, _ref3) => { | ||
| let { | ||
| node | ||
| } = _ref3; | ||
| const { | ||
| onDragStop | ||
| } = this.props; | ||
| if (!onDragStop) return; | ||
| if (!this.state.dragging) { | ||
| throw new Error("onDragEnd called before onDragStart."); | ||
| } | ||
| const { | ||
| w, | ||
| h, | ||
| i | ||
| } = this.props; | ||
| const { | ||
| left, | ||
| top | ||
| } = this.state.dragging; | ||
| const newPosition /*: PartialPosition*/ = { | ||
| top, | ||
| left | ||
| }; | ||
| this.setState({ | ||
| dragging: null | ||
| }); | ||
| const { | ||
| x, | ||
| y | ||
| } = (0, _calculateUtils.calcXY)(this.getPositionParams(), top, left, w, h); | ||
| return onDragStop.call(this, i, x, y, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }); | ||
| /** | ||
| * onResizeStop event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node and size information | ||
| */ | ||
| _defineProperty(this, "onResizeStop", (e, callbackData, position) => this.onResizeHandler(e, callbackData, position, "onResizeStop")); | ||
| // onResizeStart event handler | ||
| _defineProperty(this, "onResizeStart", (e, callbackData, position) => this.onResizeHandler(e, callbackData, position, "onResizeStart")); | ||
| // onResize event handler | ||
| _defineProperty(this, "onResize", (e, callbackData, position) => this.onResizeHandler(e, callbackData, position, "onResize")); | ||
| } | ||
| shouldComponentUpdate(nextProps /*: Props*/, nextState /*: State*/) /*: boolean*/{ | ||
| // We can't deeply compare children. If the developer memoizes them, we can | ||
| // use this optimization. | ||
| if (this.props.children !== nextProps.children) return true; | ||
| if (this.props.droppingPosition !== nextProps.droppingPosition) return true; | ||
| // TODO memoize these calculations so they don't take so long? | ||
| const oldPosition = (0, _calculateUtils.calcGridItemPosition)(this.getPositionParams(this.props), this.props.x, this.props.y, this.props.w, this.props.h, this.state); | ||
| const newPosition = (0, _calculateUtils.calcGridItemPosition)(this.getPositionParams(nextProps), nextProps.x, nextProps.y, nextProps.w, nextProps.h, nextState); | ||
| return !(0, _utils.fastPositionEqual)(oldPosition, newPosition) || this.props.useCSSTransforms !== nextProps.useCSSTransforms; | ||
| } | ||
| componentDidMount() { | ||
| this.moveDroppingItem({}); | ||
| } | ||
| componentDidUpdate(prevProps /*: Props*/) { | ||
| this.moveDroppingItem(prevProps); | ||
| } | ||
| // When a droppingPosition is present, this means we should fire a move event, as if we had moved | ||
| // this element by `x, y` pixels. | ||
| moveDroppingItem(prevProps /*: Props*/) { | ||
| const { | ||
| droppingPosition | ||
| } = this.props; | ||
| if (!droppingPosition) return; | ||
| const node = this.elementRef.current; | ||
| // Can't find DOM node (are we unmounted?) | ||
| if (!node) return; | ||
| const prevDroppingPosition = prevProps.droppingPosition || { | ||
| left: 0, | ||
| top: 0 | ||
| }; | ||
| const { | ||
| dragging | ||
| } = this.state; | ||
| const shouldDrag = dragging && droppingPosition.left !== prevDroppingPosition.left || droppingPosition.top !== prevDroppingPosition.top; | ||
| if (!dragging) { | ||
| this.onDragStart(droppingPosition.e, { | ||
| node, | ||
| deltaX: droppingPosition.left, | ||
| deltaY: droppingPosition.top | ||
| }); | ||
| } else if (shouldDrag) { | ||
| const deltaX = droppingPosition.left - dragging.left; | ||
| const deltaY = droppingPosition.top - dragging.top; | ||
| this.onDrag(droppingPosition.e, { | ||
| node, | ||
| deltaX, | ||
| deltaY | ||
| }, true // dontFLush: avoid flushSync to temper warnings | ||
| ); | ||
| } | ||
| } | ||
| getPositionParams() /*: PositionParams*/{ | ||
| let props /*: Props*/ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; | ||
| return { | ||
| cols: props.cols, | ||
| containerPadding: props.containerPadding, | ||
| containerWidth: props.containerWidth, | ||
| margin: props.margin, | ||
| maxRows: props.maxRows, | ||
| rowHeight: props.rowHeight | ||
| }; | ||
| } | ||
| /** | ||
| * This is where we set the grid item's absolute placement. It gets a little tricky because we want to do it | ||
| * well when server rendering, and the only way to do that properly is to use percentage width/left because | ||
| * we don't know exactly what the browser viewport is. | ||
| * Unfortunately, CSS Transforms, which are great for performance, break in this instance because a percentage | ||
| * left is relative to the item itself, not its container! So we cannot use them on the server rendering pass. | ||
| * | ||
| * @param {Object} pos Position object with width, height, left, top. | ||
| * @return {Object} Style object. | ||
| */ | ||
| createStyle(pos /*: Position*/) /*: { [key: string]: ?string }*/{ | ||
| const { | ||
| usePercentages, | ||
| containerWidth, | ||
| useCSSTransforms | ||
| } = this.props; | ||
| let style; | ||
| // CSS Transforms support (default) | ||
| if (useCSSTransforms) { | ||
| style = (0, _utils.setTransform)(pos); | ||
| } else { | ||
| // top,left (slow) | ||
| style = (0, _utils.setTopLeft)(pos); | ||
| // This is used for server rendering. | ||
| if (usePercentages) { | ||
| style.left = (0, _utils.perc)(pos.left / containerWidth); | ||
| style.width = (0, _utils.perc)(pos.width / containerWidth); | ||
| } | ||
| } | ||
| return style; | ||
| } | ||
| /** | ||
| * Mix a Draggable instance into a child. | ||
| * @param {Element} child Child element. | ||
| * @return {Element} Child wrapped in Draggable. | ||
| */ | ||
| mixinDraggable(child /*: ReactElement<any>*/, isDraggable /*: boolean*/) /*: ReactElement<any>*/{ | ||
| return /*#__PURE__*/_react.default.createElement(_reactDraggable.DraggableCore, { | ||
| disabled: !isDraggable, | ||
| onStart: this.onDragStart, | ||
| onDrag: this.onDrag, | ||
| onStop: this.onDragStop, | ||
| handle: this.props.handle, | ||
| cancel: ".react-resizable-handle" + (this.props.cancel ? "," + this.props.cancel : ""), | ||
| scale: this.props.transformScale, | ||
| nodeRef: this.elementRef | ||
| }, child); | ||
| } | ||
| /** | ||
| * Utility function to setup callback handler definitions for | ||
| * similarily structured resize events. | ||
| */ | ||
| curryResizeHandler(position /*: Position*/, handler /*: Function*/) /*: Function*/{ | ||
| return (e /*: Event*/, data /*: ResizeCallbackData*/) => /*: Function*/handler(e, data, position); | ||
| } | ||
| /** | ||
| * Mix a Resizable instance into a child. | ||
| * @param {Element} child Child element. | ||
| * @param {Object} position Position object (pixel values) | ||
| * @return {Element} Child wrapped in Resizable. | ||
| */ | ||
| mixinResizable(child /*: ReactElement<any>*/, position /*: Position*/, isResizable /*: boolean*/) /*: ReactElement<any>*/{ | ||
| const { | ||
| cols, | ||
| minW, | ||
| minH, | ||
| maxW, | ||
| maxH, | ||
| transformScale, | ||
| resizeHandles, | ||
| resizeHandle | ||
| } = this.props; | ||
| const positionParams = this.getPositionParams(); | ||
| // This is the max possible width - doesn't go to infinity because of the width of the window | ||
| const maxWidth = (0, _calculateUtils.calcGridItemPosition)(positionParams, 0, 0, cols, 0).width; | ||
| // Calculate min/max constraints using our min & maxes | ||
| const mins = (0, _calculateUtils.calcGridItemPosition)(positionParams, 0, 0, minW, minH); | ||
| const maxes = (0, _calculateUtils.calcGridItemPosition)(positionParams, 0, 0, maxW, maxH); | ||
| const minConstraints = [mins.width, mins.height]; | ||
| const maxConstraints = [Math.min(maxes.width, maxWidth), Math.min(maxes.height, Infinity)]; | ||
| return /*#__PURE__*/_react.default.createElement(_reactResizable.Resizable | ||
| // These are opts for the resize handle itself | ||
| , { | ||
| draggableOpts: { | ||
| disabled: !isResizable | ||
| }, | ||
| className: isResizable ? undefined : "react-resizable-hide", | ||
| width: position.width, | ||
| height: position.height, | ||
| minConstraints: minConstraints, | ||
| maxConstraints: maxConstraints, | ||
| onResizeStop: this.curryResizeHandler(position, this.onResizeStop), | ||
| onResizeStart: this.curryResizeHandler(position, this.onResizeStart), | ||
| onResize: this.curryResizeHandler(position, this.onResize), | ||
| transformScale: transformScale, | ||
| resizeHandles: resizeHandles, | ||
| handle: resizeHandle | ||
| }, child); | ||
| } | ||
| /** | ||
| * Wrapper around resize events to provide more useful data. | ||
| */ | ||
| onResizeHandler(e /*: Event*/, _ref4 /*:: */, | ||
| // 'size' is updated position | ||
| position /*: Position*/, | ||
| // existing position | ||
| handlerName /*: string*/) /*: void*/{ | ||
| let { | ||
| node, | ||
| size, | ||
| handle | ||
| } /*: ResizeCallbackData*/ = _ref4 /*: ResizeCallbackData*/; | ||
| const handler = this.props[handlerName]; | ||
| if (!handler) return; | ||
| const { | ||
| x, | ||
| y, | ||
| i, | ||
| maxH, | ||
| minH, | ||
| containerWidth | ||
| } = this.props; | ||
| const { | ||
| minW, | ||
| maxW | ||
| } = this.props; | ||
| // Clamping of dimensions based on resize direction | ||
| let updatedSize = size; | ||
| if (node) { | ||
| updatedSize = (0, _utils.resizeItemInDirection)(handle, position, size, containerWidth); | ||
| (0, _reactDom.flushSync)(() => { | ||
| this.setState({ | ||
| resizing: handlerName === "onResizeStop" ? null : updatedSize | ||
| }); | ||
| }); | ||
| } | ||
| // Get new XY based on pixel size | ||
| let { | ||
| w, | ||
| h | ||
| } = (0, _calculateUtils.calcWH)(this.getPositionParams(), updatedSize.width, updatedSize.height, x, y, handle); | ||
| // Min/max capping. | ||
| // minW should be at least 1 (TODO propTypes validation?) | ||
| w = (0, _calculateUtils.clamp)(w, Math.max(minW, 1), maxW); | ||
| h = (0, _calculateUtils.clamp)(h, minH, maxH); | ||
| handler.call(this, i, w, h, { | ||
| e, | ||
| node, | ||
| size: updatedSize, | ||
| handle | ||
| }); | ||
| } | ||
| render() /*: ReactNode*/{ | ||
| const { | ||
| x, | ||
| y, | ||
| w, | ||
| h, | ||
| isDraggable, | ||
| isResizable, | ||
| droppingPosition, | ||
| useCSSTransforms | ||
| } = this.props; | ||
| const pos = (0, _calculateUtils.calcGridItemPosition)(this.getPositionParams(), x, y, w, h, this.state); | ||
| const child = _react.default.Children.only(this.props.children); | ||
| // Create the child element. We clone the existing element but modify its className and style. | ||
| let newChild = /*#__PURE__*/_react.default.cloneElement(child, { | ||
| ref: this.elementRef, | ||
| className: (0, _clsx.default)("react-grid-item", child.props.className, this.props.className, { | ||
| static: this.props.static, | ||
| resizing: Boolean(this.state.resizing), | ||
| "react-draggable": isDraggable, | ||
| "react-draggable-dragging": Boolean(this.state.dragging), | ||
| dropping: Boolean(droppingPosition), | ||
| cssTransforms: useCSSTransforms | ||
| }), | ||
| // We can set the width and height on the child, but unfortunately we can't set the position. | ||
| style: _objectSpread(_objectSpread(_objectSpread({}, this.props.style), child.props.style), this.createStyle(pos)) | ||
| }); | ||
| // Resizable support. This is usually on but the user can toggle it off. | ||
| newChild = this.mixinResizable(newChild, pos, isResizable); | ||
| // Draggable support. This is always on, except for with placeholders. | ||
| newChild = this.mixinDraggable(newChild, isDraggable); | ||
| return newChild; | ||
| } | ||
| } | ||
| exports.default = GridItem; | ||
| _defineProperty(GridItem, "propTypes", { | ||
| // Children must be only a single element | ||
| children: _propTypes.default.element, | ||
| // General grid attributes | ||
| cols: _propTypes.default.number.isRequired, | ||
| containerWidth: _propTypes.default.number.isRequired, | ||
| rowHeight: _propTypes.default.number.isRequired, | ||
| margin: _propTypes.default.array.isRequired, | ||
| maxRows: _propTypes.default.number.isRequired, | ||
| containerPadding: _propTypes.default.array.isRequired, | ||
| // These are all in grid units | ||
| x: _propTypes.default.number.isRequired, | ||
| y: _propTypes.default.number.isRequired, | ||
| w: _propTypes.default.number.isRequired, | ||
| h: _propTypes.default.number.isRequired, | ||
| // All optional | ||
| minW: function (props /*: Props*/, propName /*: string*/) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("minWidth not Number"); | ||
| if (value > props.w || value > props.maxW) return new Error("minWidth larger than item width/maxWidth"); | ||
| }, | ||
| maxW: function (props /*: Props*/, propName /*: string*/) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("maxWidth not Number"); | ||
| if (value < props.w || value < props.minW) return new Error("maxWidth smaller than item width/minWidth"); | ||
| }, | ||
| minH: function (props /*: Props*/, propName /*: string*/) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("minHeight not Number"); | ||
| if (value > props.h || value > props.maxH) return new Error("minHeight larger than item height/maxHeight"); | ||
| }, | ||
| maxH: function (props /*: Props*/, propName /*: string*/) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("maxHeight not Number"); | ||
| if (value < props.h || value < props.minH) return new Error("maxHeight smaller than item height/minHeight"); | ||
| }, | ||
| // ID is nice to have for callbacks | ||
| i: _propTypes.default.string.isRequired, | ||
| // Resize handle options | ||
| resizeHandles: _ReactGridLayoutPropTypes.resizeHandleAxesType, | ||
| resizeHandle: _ReactGridLayoutPropTypes.resizeHandleType, | ||
| // Functions | ||
| onDragStop: _propTypes.default.func, | ||
| onDragStart: _propTypes.default.func, | ||
| onDrag: _propTypes.default.func, | ||
| onResizeStop: _propTypes.default.func, | ||
| onResizeStart: _propTypes.default.func, | ||
| onResize: _propTypes.default.func, | ||
| // Flags | ||
| isDraggable: _propTypes.default.bool.isRequired, | ||
| isResizable: _propTypes.default.bool.isRequired, | ||
| isBounded: _propTypes.default.bool.isRequired, | ||
| static: _propTypes.default.bool, | ||
| // Use CSS transforms instead of top/left | ||
| useCSSTransforms: _propTypes.default.bool.isRequired, | ||
| transformScale: _propTypes.default.number, | ||
| // Others | ||
| className: _propTypes.default.string, | ||
| // Selector for draggable handle | ||
| handle: _propTypes.default.string, | ||
| // Selector for draggable cancel (see react-draggable) | ||
| cancel: _propTypes.default.string, | ||
| // Current position of a dropping element | ||
| droppingPosition: _propTypes.default.shape({ | ||
| e: _propTypes.default.object.isRequired, | ||
| left: _propTypes.default.number.isRequired, | ||
| top: _propTypes.default.number.isRequired | ||
| }) | ||
| }); | ||
| _defineProperty(GridItem, "defaultProps", { | ||
| className: "", | ||
| cancel: "", | ||
| handle: "", | ||
| minH: 1, | ||
| minW: 1, | ||
| maxH: Infinity, | ||
| maxW: Infinity, | ||
| transformScale: 1 | ||
| }); |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.default = void 0; | ||
| var React = _interopRequireWildcard(require("react")); | ||
| var _fastEquals = require("fast-equals"); | ||
| var _clsx = _interopRequireDefault(require("clsx")); | ||
| var _utils = require("./utils"); | ||
| var _calculateUtils = require("./calculateUtils"); | ||
| var _GridItem = _interopRequireDefault(require("./GridItem")); | ||
| var _ReactGridLayoutPropTypes = _interopRequireDefault(require("./ReactGridLayoutPropTypes")); | ||
| function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
| function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } | ||
| function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
| function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
| function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } | ||
| function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } | ||
| function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } | ||
| /*:: import type { | ||
| ChildrenArray as ReactChildrenArray, | ||
| Element as ReactElement | ||
| } from "react";*/ | ||
| /*:: import type { | ||
| CompactType, | ||
| GridResizeEvent, | ||
| GridDragEvent, | ||
| DragOverEvent, | ||
| Layout, | ||
| DroppingPosition, | ||
| LayoutItem | ||
| } from "./utils";*/ | ||
| // Types | ||
| /*:: import type { PositionParams } from "./calculateUtils";*/ | ||
| /*:: type State = { | ||
| activeDrag: ?LayoutItem, | ||
| layout: Layout, | ||
| mounted: boolean, | ||
| oldDragItem: ?LayoutItem, | ||
| oldLayout: ?Layout, | ||
| oldResizeItem: ?LayoutItem, | ||
| resizing: boolean, | ||
| droppingDOMNode: ?ReactElement<any>, | ||
| droppingPosition?: DroppingPosition, | ||
| // Mirrored props | ||
| children: ReactChildrenArray<ReactElement<any>>, | ||
| compactType?: CompactType, | ||
| propsLayout?: Layout | ||
| };*/ | ||
| /*:: import type { Props, DefaultProps } from "./ReactGridLayoutPropTypes";*/ | ||
| // End Types | ||
| const layoutClassName = "react-grid-layout"; | ||
| let isFirefox = false; | ||
| // Try...catch will protect from navigator not existing (e.g. node) or a bad implementation of navigator | ||
| try { | ||
| isFirefox = /firefox/i.test(navigator.userAgent); | ||
| } catch (e) { | ||
| /* Ignore */ | ||
| } | ||
| /** | ||
| * A reactive, fluid grid layout with draggable, resizable components. | ||
| */ | ||
| class ReactGridLayout extends React.Component /*:: <Props, State>*/{ | ||
| constructor() { | ||
| super(...arguments); | ||
| _defineProperty(this, "state", { | ||
| activeDrag: null, | ||
| layout: (0, _utils.synchronizeLayoutWithChildren)(this.props.layout, this.props.children, this.props.cols, | ||
| // Legacy support for verticalCompact: false | ||
| (0, _utils.compactType)(this.props), this.props.allowOverlap), | ||
| mounted: false, | ||
| oldDragItem: null, | ||
| oldLayout: null, | ||
| oldResizeItem: null, | ||
| resizing: false, | ||
| droppingDOMNode: null, | ||
| children: [] | ||
| }); | ||
| _defineProperty(this, "dragEnterCounter", 0); | ||
| /** | ||
| * When dragging starts | ||
| * @param {String} i Id of the child | ||
| * @param {Number} x X position of the move | ||
| * @param {Number} y Y position of the move | ||
| * @param {Event} e The mousedown event | ||
| * @param {Element} node The current dragging DOM element | ||
| */ | ||
| _defineProperty(this, "onDragStart", (i /*: string*/, x /*: number*/, y /*: number*/, _ref /*:: */) => { | ||
| let { | ||
| e, | ||
| node | ||
| } /*: GridDragEvent*/ = _ref /*: GridDragEvent*/; | ||
| const { | ||
| layout | ||
| } = this.state; | ||
| const l = (0, _utils.getLayoutItem)(layout, i); | ||
| if (!l) return; | ||
| // Create placeholder (display only) | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| placeholder: true, | ||
| i: i | ||
| }; | ||
| this.setState({ | ||
| oldDragItem: (0, _utils.cloneLayoutItem)(l), | ||
| oldLayout: layout, | ||
| activeDrag: placeholder | ||
| }); | ||
| return this.props.onDragStart(layout, l, l, null, e, node); | ||
| }); | ||
| /** | ||
| * Each drag movement create a new dragelement and move the element to the dragged location | ||
| * @param {String} i Id of the child | ||
| * @param {Number} x X position of the move | ||
| * @param {Number} y Y position of the move | ||
| * @param {Event} e The mousedown event | ||
| * @param {Element} node The current dragging DOM element | ||
| */ | ||
| _defineProperty(this, "onDrag", (i, x, y, _ref2) => { | ||
| let { | ||
| e, | ||
| node | ||
| } = _ref2; | ||
| const { | ||
| oldDragItem | ||
| } = this.state; | ||
| let { | ||
| layout | ||
| } = this.state; | ||
| const { | ||
| cols, | ||
| allowOverlap, | ||
| preventCollision | ||
| } = this.props; | ||
| const l = (0, _utils.getLayoutItem)(layout, i); | ||
| if (!l) return; | ||
| // Create placeholder (display only) | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| placeholder: true, | ||
| i: i | ||
| }; | ||
| // Move the element to the dragged location. | ||
| const isUserAction = true; | ||
| layout = (0, _utils.moveElement)(layout, l, x, y, isUserAction, preventCollision, (0, _utils.compactType)(this.props), cols, allowOverlap); | ||
| this.props.onDrag(layout, oldDragItem, l, placeholder, e, node); | ||
| this.setState({ | ||
| layout: allowOverlap ? layout : (0, _utils.compact)(layout, (0, _utils.compactType)(this.props), cols), | ||
| activeDrag: placeholder | ||
| }); | ||
| }); | ||
| /** | ||
| * When dragging stops, figure out which position the element is closest to and update its x and y. | ||
| * @param {String} i Index of the child. | ||
| * @param {Number} x X position of the move | ||
| * @param {Number} y Y position of the move | ||
| * @param {Event} e The mousedown event | ||
| * @param {Element} node The current dragging DOM element | ||
| */ | ||
| _defineProperty(this, "onDragStop", (i, x, y, _ref3) => { | ||
| let { | ||
| e, | ||
| node | ||
| } = _ref3; | ||
| if (!this.state.activeDrag) return; | ||
| const { | ||
| oldDragItem | ||
| } = this.state; | ||
| let { | ||
| layout | ||
| } = this.state; | ||
| const { | ||
| cols, | ||
| preventCollision, | ||
| allowOverlap | ||
| } = this.props; | ||
| const l = (0, _utils.getLayoutItem)(layout, i); | ||
| if (!l) return; | ||
| // Move the element here | ||
| const isUserAction = true; | ||
| layout = (0, _utils.moveElement)(layout, l, x, y, isUserAction, preventCollision, (0, _utils.compactType)(this.props), cols, allowOverlap); | ||
| // Set state | ||
| const newLayout = allowOverlap ? layout : (0, _utils.compact)(layout, (0, _utils.compactType)(this.props), cols); | ||
| this.props.onDragStop(newLayout, oldDragItem, l, null, e, node); | ||
| const { | ||
| oldLayout | ||
| } = this.state; | ||
| this.setState({ | ||
| activeDrag: null, | ||
| layout: newLayout, | ||
| oldDragItem: null, | ||
| oldLayout: null | ||
| }); | ||
| this.onLayoutMaybeChanged(newLayout, oldLayout); | ||
| }); | ||
| _defineProperty(this, "onResizeStart", (i, w, h, _ref4) => { | ||
| let { | ||
| e, | ||
| node | ||
| } = _ref4; | ||
| const { | ||
| layout | ||
| } = this.state; | ||
| const l = (0, _utils.getLayoutItem)(layout, i); | ||
| if (!l) return; | ||
| this.setState({ | ||
| oldResizeItem: (0, _utils.cloneLayoutItem)(l), | ||
| oldLayout: this.state.layout, | ||
| resizing: true | ||
| }); | ||
| this.props.onResizeStart(layout, l, l, null, e, node); | ||
| }); | ||
| _defineProperty(this, "onResize", (i, w, h, _ref5) => { | ||
| let { | ||
| e, | ||
| node, | ||
| size, | ||
| handle | ||
| } = _ref5; | ||
| const { | ||
| oldResizeItem | ||
| } = this.state; | ||
| const { | ||
| layout | ||
| } = this.state; | ||
| const { | ||
| cols, | ||
| preventCollision, | ||
| allowOverlap | ||
| } = this.props; | ||
| let shouldMoveItem = false; | ||
| let finalLayout; | ||
| let x; | ||
| let y; | ||
| const [newLayout, l] = (0, _utils.withLayoutItem)(layout, i, l => { | ||
| let hasCollisions; | ||
| x = l.x; | ||
| y = l.y; | ||
| if (["sw", "w", "nw", "n", "ne"].indexOf(handle) !== -1) { | ||
| if (["sw", "nw", "w"].indexOf(handle) !== -1) { | ||
| x = l.x + (l.w - w); | ||
| w = l.x !== x && x < 0 ? l.w : w; | ||
| x = x < 0 ? 0 : x; | ||
| } | ||
| if (["ne", "n", "nw"].indexOf(handle) !== -1) { | ||
| y = l.y + (l.h - h); | ||
| h = l.y !== y && y < 0 ? l.h : h; | ||
| y = y < 0 ? 0 : y; | ||
| } | ||
| shouldMoveItem = true; | ||
| } | ||
| // Something like quad tree should be used | ||
| // to find collisions faster | ||
| if (preventCollision && !allowOverlap) { | ||
| const collisions = (0, _utils.getAllCollisions)(layout, _objectSpread(_objectSpread({}, l), {}, { | ||
| w, | ||
| h, | ||
| x, | ||
| y | ||
| })).filter(layoutItem => layoutItem.i !== l.i); | ||
| hasCollisions = collisions.length > 0; | ||
| // If we're colliding, we need adjust the placeholder. | ||
| if (hasCollisions) { | ||
| // Reset layoutItem dimensions if there were collisions | ||
| y = l.y; | ||
| h = l.h; | ||
| x = l.x; | ||
| w = l.w; | ||
| shouldMoveItem = false; | ||
| } | ||
| } | ||
| l.w = w; | ||
| l.h = h; | ||
| return l; | ||
| }); | ||
| // Shouldn't ever happen, but typechecking makes it necessary | ||
| if (!l) return; | ||
| finalLayout = newLayout; | ||
| if (shouldMoveItem) { | ||
| // Move the element to the new position. | ||
| const isUserAction = true; | ||
| finalLayout = (0, _utils.moveElement)(newLayout, l, x, y, isUserAction, this.props.preventCollision, (0, _utils.compactType)(this.props), cols, allowOverlap); | ||
| } | ||
| // Create placeholder element (display only) | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| static: true, | ||
| i: i | ||
| }; | ||
| this.props.onResize(finalLayout, oldResizeItem, l, placeholder, e, node); | ||
| // Re-compact the newLayout and set the drag placeholder. | ||
| this.setState({ | ||
| layout: allowOverlap ? finalLayout : (0, _utils.compact)(finalLayout, (0, _utils.compactType)(this.props), cols), | ||
| activeDrag: placeholder | ||
| }); | ||
| }); | ||
| _defineProperty(this, "onResizeStop", (i, w, h, _ref6) => { | ||
| let { | ||
| e, | ||
| node | ||
| } = _ref6; | ||
| const { | ||
| layout, | ||
| oldResizeItem | ||
| } = this.state; | ||
| const { | ||
| cols, | ||
| allowOverlap | ||
| } = this.props; | ||
| const l = (0, _utils.getLayoutItem)(layout, i); | ||
| // Set state | ||
| const newLayout = allowOverlap ? layout : (0, _utils.compact)(layout, (0, _utils.compactType)(this.props), cols); | ||
| this.props.onResizeStop(newLayout, oldResizeItem, l, null, e, node); | ||
| const { | ||
| oldLayout | ||
| } = this.state; | ||
| this.setState({ | ||
| activeDrag: null, | ||
| layout: newLayout, | ||
| oldResizeItem: null, | ||
| oldLayout: null, | ||
| resizing: false | ||
| }); | ||
| this.onLayoutMaybeChanged(newLayout, oldLayout); | ||
| }); | ||
| // Called while dragging an element. Part of browser native drag/drop API. | ||
| // Native event target might be the layout itself, or an element within the layout. | ||
| _defineProperty(this, "onDragOver", e => { | ||
| var _e$nativeEvent$target; | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| // we should ignore events from layout's children in Firefox | ||
| // to avoid unpredictable jumping of a dropping placeholder | ||
| // FIXME remove this hack | ||
| if (isFirefox && | ||
| // $FlowIgnore can't figure this out | ||
| !((_e$nativeEvent$target = e.nativeEvent.target) !== null && _e$nativeEvent$target !== void 0 && _e$nativeEvent$target.classList.contains(layoutClassName))) { | ||
| return false; | ||
| } | ||
| const { | ||
| droppingItem, | ||
| onDropDragOver, | ||
| margin, | ||
| cols, | ||
| rowHeight, | ||
| maxRows, | ||
| width, | ||
| containerPadding, | ||
| transformScale | ||
| } = this.props; | ||
| // Allow user to customize the dropping item or short-circuit the drop based on the results | ||
| // of the `onDragOver(e: Event)` callback. | ||
| const onDragOverResult = onDropDragOver === null || onDropDragOver === void 0 ? void 0 : onDropDragOver(e); | ||
| if (onDragOverResult === false) { | ||
| if (this.state.droppingDOMNode) { | ||
| this.removeDroppingPlaceholder(); | ||
| } | ||
| return false; | ||
| } | ||
| const finalDroppingItem = _objectSpread(_objectSpread({}, droppingItem), onDragOverResult); | ||
| const { | ||
| layout | ||
| } = this.state; | ||
| // $FlowIgnore missing def | ||
| const gridRect = e.currentTarget.getBoundingClientRect(); // The grid's position in the viewport | ||
| // Calculate the mouse position relative to the grid | ||
| const layerX = e.clientX - gridRect.left; | ||
| const layerY = e.clientY - gridRect.top; | ||
| const droppingPosition = { | ||
| left: layerX / transformScale, | ||
| top: layerY / transformScale, | ||
| e | ||
| }; | ||
| if (!this.state.droppingDOMNode) { | ||
| const positionParams /*: PositionParams*/ = { | ||
| cols, | ||
| margin, | ||
| maxRows, | ||
| rowHeight, | ||
| containerWidth: width, | ||
| containerPadding: containerPadding || margin | ||
| }; | ||
| const calculatedPosition = (0, _calculateUtils.calcXY)(positionParams, layerY, layerX, finalDroppingItem.w, finalDroppingItem.h); | ||
| this.setState({ | ||
| droppingDOMNode: /*#__PURE__*/React.createElement("div", { | ||
| key: finalDroppingItem.i | ||
| }), | ||
| droppingPosition, | ||
| layout: [...layout, _objectSpread(_objectSpread({}, finalDroppingItem), {}, { | ||
| x: calculatedPosition.x, | ||
| y: calculatedPosition.y, | ||
| static: false, | ||
| isDraggable: true | ||
| })] | ||
| }); | ||
| } else if (this.state.droppingPosition) { | ||
| const { | ||
| left, | ||
| top | ||
| } = this.state.droppingPosition; | ||
| const shouldUpdatePosition = left != layerX || top != layerY; | ||
| if (shouldUpdatePosition) { | ||
| this.setState({ | ||
| droppingPosition | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| _defineProperty(this, "removeDroppingPlaceholder", () => { | ||
| const { | ||
| droppingItem, | ||
| cols | ||
| } = this.props; | ||
| const { | ||
| layout | ||
| } = this.state; | ||
| const newLayout = (0, _utils.compact)(layout.filter(l => l.i !== droppingItem.i), (0, _utils.compactType)(this.props), cols, this.props.allowOverlap); | ||
| this.setState({ | ||
| layout: newLayout, | ||
| droppingDOMNode: null, | ||
| activeDrag: null, | ||
| droppingPosition: undefined | ||
| }); | ||
| }); | ||
| _defineProperty(this, "onDragLeave", e => { | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| this.dragEnterCounter--; | ||
| // onDragLeave can be triggered on each layout's child. | ||
| // But we know that count of dragEnter and dragLeave events | ||
| // will be balanced after leaving the layout's container | ||
| // so we can increase and decrease count of dragEnter and | ||
| // when it'll be equal to 0 we'll remove the placeholder | ||
| if (this.dragEnterCounter === 0) { | ||
| this.removeDroppingPlaceholder(); | ||
| } | ||
| }); | ||
| _defineProperty(this, "onDragEnter", e => { | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| this.dragEnterCounter++; | ||
| }); | ||
| _defineProperty(this, "onDrop", (e /*: Event*/) => { | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| const { | ||
| droppingItem | ||
| } = this.props; | ||
| const { | ||
| layout | ||
| } = this.state; | ||
| const item = layout.find(l => l.i === droppingItem.i); | ||
| // reset dragEnter counter on drop | ||
| this.dragEnterCounter = 0; | ||
| this.removeDroppingPlaceholder(); | ||
| this.props.onDrop(layout, item, e); | ||
| }); | ||
| } | ||
| componentDidMount() { | ||
| this.setState({ | ||
| mounted: true | ||
| }); | ||
| // Possibly call back with layout on mount. This should be done after correcting the layout width | ||
| // to ensure we don't rerender with the wrong width. | ||
| this.onLayoutMaybeChanged(this.state.layout, this.props.layout); | ||
| } | ||
| static getDerivedStateFromProps(nextProps /*: Props*/, prevState /*: State*/) /*: $Shape<State> | null*/{ | ||
| let newLayoutBase; | ||
| if (prevState.activeDrag) { | ||
| return null; | ||
| } | ||
| // Legacy support for compactType | ||
| // Allow parent to set layout directly. | ||
| if (!(0, _fastEquals.deepEqual)(nextProps.layout, prevState.propsLayout) || nextProps.compactType !== prevState.compactType) { | ||
| newLayoutBase = nextProps.layout; | ||
| } else if (!(0, _utils.childrenEqual)(nextProps.children, prevState.children)) { | ||
| // If children change, also regenerate the layout. Use our state | ||
| // as the base in case because it may be more up to date than | ||
| // what is in props. | ||
| newLayoutBase = prevState.layout; | ||
| } | ||
| // We need to regenerate the layout. | ||
| if (newLayoutBase) { | ||
| const newLayout = (0, _utils.synchronizeLayoutWithChildren)(newLayoutBase, nextProps.children, nextProps.cols, (0, _utils.compactType)(nextProps), nextProps.allowOverlap); | ||
| return { | ||
| layout: newLayout, | ||
| // We need to save these props to state for using | ||
| // getDerivedStateFromProps instead of componentDidMount (in which we would get extra rerender) | ||
| compactType: nextProps.compactType, | ||
| children: nextProps.children, | ||
| propsLayout: nextProps.layout | ||
| }; | ||
| } | ||
| return null; | ||
| } | ||
| shouldComponentUpdate(nextProps /*: Props*/, nextState /*: State*/) /*: boolean*/{ | ||
| return ( | ||
| // NOTE: this is almost always unequal. Therefore the only way to get better performance | ||
| // from SCU is if the user intentionally memoizes children. If they do, and they can | ||
| // handle changes properly, performance will increase. | ||
| this.props.children !== nextProps.children || !(0, _utils.fastRGLPropsEqual)(this.props, nextProps, _fastEquals.deepEqual) || this.state.activeDrag !== nextState.activeDrag || this.state.mounted !== nextState.mounted || this.state.droppingPosition !== nextState.droppingPosition | ||
| ); | ||
| } | ||
| componentDidUpdate(prevProps /*: Props*/, prevState /*: State*/) { | ||
| if (!this.state.activeDrag) { | ||
| const newLayout = this.state.layout; | ||
| const oldLayout = prevState.layout; | ||
| this.onLayoutMaybeChanged(newLayout, oldLayout); | ||
| } | ||
| } | ||
| /** | ||
| * Calculates a pixel value for the container. | ||
| * @return {String} Container height in pixels. | ||
| */ | ||
| containerHeight() /*: ?string*/{ | ||
| if (!this.props.autoSize) return; | ||
| const nbRow = (0, _utils.bottom)(this.state.layout); | ||
| const containerPaddingY = this.props.containerPadding ? this.props.containerPadding[1] : this.props.margin[1]; | ||
| return nbRow * this.props.rowHeight + (nbRow - 1) * this.props.margin[1] + containerPaddingY * 2 + "px"; | ||
| } | ||
| onLayoutMaybeChanged(newLayout /*: Layout*/, oldLayout /*: ?Layout*/) { | ||
| if (!oldLayout) oldLayout = this.state.layout; | ||
| if (!(0, _fastEquals.deepEqual)(oldLayout, newLayout)) { | ||
| this.props.onLayoutChange(newLayout); | ||
| } | ||
| } | ||
| /** | ||
| * Create a placeholder object. | ||
| * @return {Element} Placeholder div. | ||
| */ | ||
| placeholder() /*: ?ReactElement<any>*/{ | ||
| const { | ||
| activeDrag | ||
| } = this.state; | ||
| if (!activeDrag) return null; | ||
| const { | ||
| width, | ||
| cols, | ||
| margin, | ||
| containerPadding, | ||
| rowHeight, | ||
| maxRows, | ||
| useCSSTransforms, | ||
| transformScale | ||
| } = this.props; | ||
| // {...this.state.activeDrag} is pretty slow, actually | ||
| return /*#__PURE__*/React.createElement(_GridItem.default, { | ||
| w: activeDrag.w, | ||
| h: activeDrag.h, | ||
| x: activeDrag.x, | ||
| y: activeDrag.y, | ||
| i: activeDrag.i, | ||
| className: "react-grid-placeholder ".concat(this.state.resizing ? "placeholder-resizing" : ""), | ||
| containerWidth: width, | ||
| cols: cols, | ||
| margin: margin, | ||
| containerPadding: containerPadding || margin, | ||
| maxRows: maxRows, | ||
| rowHeight: rowHeight, | ||
| isDraggable: false, | ||
| isResizable: false, | ||
| isBounded: false, | ||
| useCSSTransforms: useCSSTransforms, | ||
| transformScale: transformScale | ||
| }, /*#__PURE__*/React.createElement("div", null)); | ||
| } | ||
| /** | ||
| * Given a grid item, set its style attributes & surround in a <Draggable>. | ||
| * @param {Element} child React element. | ||
| * @return {Element} Element wrapped in draggable and properly placed. | ||
| */ | ||
| processGridItem(child /*: ReactElement<any>*/, isDroppingItem /*: boolean*/) /*: ?ReactElement<any>*/{ | ||
| if (!child || !child.key) return; | ||
| const l = (0, _utils.getLayoutItem)(this.state.layout, String(child.key)); | ||
| if (!l) return null; | ||
| const { | ||
| width, | ||
| cols, | ||
| margin, | ||
| containerPadding, | ||
| rowHeight, | ||
| maxRows, | ||
| isDraggable, | ||
| isResizable, | ||
| isBounded, | ||
| useCSSTransforms, | ||
| transformScale, | ||
| draggableCancel, | ||
| draggableHandle, | ||
| resizeHandles, | ||
| resizeHandle | ||
| } = this.props; | ||
| const { | ||
| mounted, | ||
| droppingPosition | ||
| } = this.state; | ||
| // Determine user manipulations possible. | ||
| // If an item is static, it can't be manipulated by default. | ||
| // Any properties defined directly on the grid item will take precedence. | ||
| const draggable = typeof l.isDraggable === "boolean" ? l.isDraggable : !l.static && isDraggable; | ||
| const resizable = typeof l.isResizable === "boolean" ? l.isResizable : !l.static && isResizable; | ||
| const resizeHandlesOptions = l.resizeHandles || resizeHandles; | ||
| // isBounded set on child if set on parent, and child is not explicitly false | ||
| const bounded = draggable && isBounded && l.isBounded !== false; | ||
| return /*#__PURE__*/React.createElement(_GridItem.default, { | ||
| containerWidth: width, | ||
| cols: cols, | ||
| margin: margin, | ||
| containerPadding: containerPadding || margin, | ||
| maxRows: maxRows, | ||
| rowHeight: rowHeight, | ||
| cancel: draggableCancel, | ||
| handle: draggableHandle, | ||
| onDragStop: this.onDragStop, | ||
| onDragStart: this.onDragStart, | ||
| onDrag: this.onDrag, | ||
| onResizeStart: this.onResizeStart, | ||
| onResize: this.onResize, | ||
| onResizeStop: this.onResizeStop, | ||
| isDraggable: draggable, | ||
| isResizable: resizable, | ||
| isBounded: bounded, | ||
| useCSSTransforms: useCSSTransforms && mounted, | ||
| usePercentages: !mounted, | ||
| transformScale: transformScale, | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| i: l.i, | ||
| minH: l.minH, | ||
| minW: l.minW, | ||
| maxH: l.maxH, | ||
| maxW: l.maxW, | ||
| static: l.static, | ||
| droppingPosition: isDroppingItem ? droppingPosition : undefined, | ||
| resizeHandles: resizeHandlesOptions, | ||
| resizeHandle: resizeHandle | ||
| }, child); | ||
| } | ||
| render() /*: React.Element<"div">*/{ | ||
| const { | ||
| className, | ||
| style, | ||
| isDroppable, | ||
| innerRef | ||
| } = this.props; | ||
| const mergedClassName = (0, _clsx.default)(layoutClassName, className); | ||
| const mergedStyle = _objectSpread({ | ||
| height: this.containerHeight() | ||
| }, style); | ||
| return /*#__PURE__*/React.createElement("div", { | ||
| ref: innerRef, | ||
| className: mergedClassName, | ||
| style: mergedStyle, | ||
| onDrop: isDroppable ? this.onDrop : _utils.noop, | ||
| onDragLeave: isDroppable ? this.onDragLeave : _utils.noop, | ||
| onDragEnter: isDroppable ? this.onDragEnter : _utils.noop, | ||
| onDragOver: isDroppable ? this.onDragOver : _utils.noop | ||
| }, React.Children.map(this.props.children, child => this.processGridItem(child)), isDroppable && this.state.droppingDOMNode && this.processGridItem(this.state.droppingDOMNode, true), this.placeholder()); | ||
| } | ||
| } | ||
| exports.default = ReactGridLayout; | ||
| // TODO publish internal ReactClass displayName transform | ||
| _defineProperty(ReactGridLayout, "displayName", "ReactGridLayout"); | ||
| // Refactored to another module to make way for preval | ||
| _defineProperty(ReactGridLayout, "propTypes", _ReactGridLayoutPropTypes.default); | ||
| _defineProperty(ReactGridLayout, "defaultProps", { | ||
| autoSize: true, | ||
| cols: 12, | ||
| className: "", | ||
| style: {}, | ||
| draggableHandle: "", | ||
| draggableCancel: "", | ||
| containerPadding: null, | ||
| rowHeight: 150, | ||
| maxRows: Infinity, | ||
| // infinite vertical growth | ||
| layout: [], | ||
| margin: [10, 10], | ||
| isBounded: false, | ||
| isDraggable: true, | ||
| isResizable: true, | ||
| allowOverlap: false, | ||
| isDroppable: false, | ||
| useCSSTransforms: true, | ||
| transformScale: 1, | ||
| verticalCompact: true, | ||
| compactType: "vertical", | ||
| preventCollision: false, | ||
| droppingItem: { | ||
| i: "__dropping-elem__", | ||
| h: 1, | ||
| w: 1 | ||
| }, | ||
| resizeHandles: ["se"], | ||
| onLayoutChange: _utils.noop, | ||
| onDragStart: _utils.noop, | ||
| onDrag: _utils.noop, | ||
| onDragStop: _utils.noop, | ||
| onResizeStart: _utils.noop, | ||
| onResize: _utils.noop, | ||
| onResizeStop: _utils.noop, | ||
| onDrop: _utils.noop, | ||
| onDropDragOver: _utils.noop | ||
| }); |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.resizeHandleType = exports.resizeHandleAxesType = exports.default = void 0; | ||
| var _propTypes = _interopRequireDefault(require("prop-types")); | ||
| var _react = _interopRequireDefault(require("react")); | ||
| function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
| /*:: import type { | ||
| Ref, | ||
| ChildrenArray as ReactChildrenArray, | ||
| Element as ReactElement | ||
| } from "react";*/ | ||
| /*:: import type { | ||
| DragOverEvent, | ||
| EventCallback, | ||
| CompactType, | ||
| Layout, | ||
| LayoutItem, | ||
| ResizeHandleAxis | ||
| } from "./utils";*/ | ||
| /*:: export type ReactRef<T: HTMLElement> = {| | ||
| +current: T | null | ||
| |};*/ | ||
| // util | ||
| /*:: export type ResizeHandle = | ||
| | ReactElement<any> | ||
| | (( | ||
| resizeHandleAxis: ResizeHandleAxis, | ||
| ref: ReactRef<HTMLElement> | ||
| ) => ReactElement<any>);*/ | ||
| // Defines which resize handles should be rendered (default: 'se') | ||
| // Allows for any combination of: | ||
| // 's' - South handle (bottom-center) | ||
| // 'w' - West handle (left-center) | ||
| // 'e' - East handle (right-center) | ||
| // 'n' - North handle (top-center) | ||
| // 'sw' - Southwest handle (bottom-left) | ||
| // 'nw' - Northwest handle (top-left) | ||
| // 'se' - Southeast handle (bottom-right) | ||
| // 'ne' - Northeast handle (top-right) | ||
| const resizeHandleAxesType /*: ReactPropsChainableTypeChecker*/ = exports.resizeHandleAxesType = _propTypes.default.arrayOf(_propTypes.default.oneOf(["s", "w", "e", "n", "sw", "nw", "se", "ne"])); | ||
| // Custom component for resize handles | ||
| const resizeHandleType /*: ReactPropsChainableTypeChecker*/ = exports.resizeHandleType = _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]); | ||
| /*:: export type Props = {| | ||
| className: string, | ||
| style: Object, | ||
| width: number, | ||
| autoSize: boolean, | ||
| cols: number, | ||
| draggableCancel: string, | ||
| draggableHandle: string, | ||
| verticalCompact: boolean, | ||
| compactType: CompactType, | ||
| layout: Layout, | ||
| margin: [number, number], | ||
| containerPadding: ?[number, number], | ||
| rowHeight: number, | ||
| maxRows: number, | ||
| isBounded: boolean, | ||
| isDraggable: boolean, | ||
| isResizable: boolean, | ||
| isDroppable: boolean, | ||
| preventCollision: boolean, | ||
| useCSSTransforms: boolean, | ||
| transformScale: number, | ||
| droppingItem: $Shape<LayoutItem>, | ||
| resizeHandles: ResizeHandleAxis[], | ||
| resizeHandle?: ResizeHandle, | ||
| allowOverlap: boolean, | ||
| // Callbacks | ||
| onLayoutChange: Layout => void, | ||
| onDrag: EventCallback, | ||
| onDragStart: EventCallback, | ||
| onDragStop: EventCallback, | ||
| onResize: EventCallback, | ||
| onResizeStart: EventCallback, | ||
| onResizeStop: EventCallback, | ||
| onDropDragOver: (e: DragOverEvent) => ?({| w?: number, h?: number |} | false), | ||
| onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void, | ||
| children: ReactChildrenArray<ReactElement<any>>, | ||
| innerRef?: Ref<"div"> | ||
| |};*/ | ||
| /*:: export type DefaultProps = $Diff< | ||
| Props, | ||
| { | ||
| children: ReactChildrenArray<ReactElement<any>>, | ||
| width: number | ||
| } | ||
| >;*/ | ||
| var _default = exports.default = { | ||
| // | ||
| // Basic props | ||
| // | ||
| className: _propTypes.default.string, | ||
| style: _propTypes.default.object, | ||
| // This can be set explicitly. If it is not set, it will automatically | ||
| // be set to the container width. Note that resizes will *not* cause this to adjust. | ||
| // If you need that behavior, use WidthProvider. | ||
| width: _propTypes.default.number, | ||
| // If true, the container height swells and contracts to fit contents | ||
| autoSize: _propTypes.default.bool, | ||
| // # of cols. | ||
| cols: _propTypes.default.number, | ||
| // A selector that will not be draggable. | ||
| draggableCancel: _propTypes.default.string, | ||
| // A selector for the draggable handler | ||
| draggableHandle: _propTypes.default.string, | ||
| // Deprecated | ||
| verticalCompact: function (props /*: Props*/) { | ||
| if (props.verticalCompact === false && process.env.NODE_ENV !== "production") { | ||
| console.warn( | ||
| // eslint-disable-line no-console | ||
| "`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. " + 'Use `compactType`: "horizontal" | "vertical" | null.'); | ||
| } | ||
| }, | ||
| // Choose vertical or hotizontal compaction | ||
| compactType: (_propTypes.default.oneOf(["vertical", "horizontal"]) /*: ReactPropsChainableTypeChecker*/), | ||
| // layout is an array of object with the format: | ||
| // {x: Number, y: Number, w: Number, h: Number, i: String} | ||
| layout: function (props /*: Props*/) { | ||
| var layout = props.layout; | ||
| // I hope you're setting the data-grid property on the grid items | ||
| if (layout === undefined) return; | ||
| require("./utils").validateLayout(layout, "layout"); | ||
| }, | ||
| // | ||
| // Grid Dimensions | ||
| // | ||
| // Margin between items [x, y] in px | ||
| margin: (_propTypes.default.arrayOf(_propTypes.default.number) /*: ReactPropsChainableTypeChecker*/), | ||
| // Padding inside the container [x, y] in px | ||
| containerPadding: (_propTypes.default.arrayOf(_propTypes.default.number) /*: ReactPropsChainableTypeChecker*/), | ||
| // Rows have a static height, but you can change this based on breakpoints if you like | ||
| rowHeight: _propTypes.default.number, | ||
| // Default Infinity, but you can specify a max here if you like. | ||
| // Note that this isn't fully fleshed out and won't error if you specify a layout that | ||
| // extends beyond the row capacity. It will, however, not allow users to drag/resize | ||
| // an item past the barrier. They can push items beyond the barrier, though. | ||
| // Intentionally not documented for this reason. | ||
| maxRows: _propTypes.default.number, | ||
| // | ||
| // Flags | ||
| // | ||
| isBounded: _propTypes.default.bool, | ||
| isDraggable: _propTypes.default.bool, | ||
| isResizable: _propTypes.default.bool, | ||
| // If true, grid can be placed one over the other. | ||
| allowOverlap: _propTypes.default.bool, | ||
| // If true, grid items won't change position when being dragged over. | ||
| preventCollision: _propTypes.default.bool, | ||
| // Use CSS transforms instead of top/left | ||
| useCSSTransforms: _propTypes.default.bool, | ||
| // parent layout transform scale | ||
| transformScale: _propTypes.default.number, | ||
| // If true, an external element can trigger onDrop callback with a specific grid position as a parameter | ||
| isDroppable: _propTypes.default.bool, | ||
| // Resize handle options | ||
| resizeHandles: resizeHandleAxesType, | ||
| resizeHandle: resizeHandleType, | ||
| // | ||
| // Callbacks | ||
| // | ||
| // Callback so you can save the layout. Calls after each drag & resize stops. | ||
| onLayoutChange: _propTypes.default.func, | ||
| // Calls when drag starts. Callback is of the signature (layout, oldItem, newItem, placeholder, e, ?node). | ||
| // All callbacks below have the same signature. 'start' and 'stop' callbacks omit the 'placeholder'. | ||
| onDragStart: _propTypes.default.func, | ||
| // Calls on each drag movement. | ||
| onDrag: _propTypes.default.func, | ||
| // Calls when drag is complete. | ||
| onDragStop: _propTypes.default.func, | ||
| //Calls when resize starts. | ||
| onResizeStart: _propTypes.default.func, | ||
| // Calls when resize movement happens. | ||
| onResize: _propTypes.default.func, | ||
| // Calls when resize is complete. | ||
| onResizeStop: _propTypes.default.func, | ||
| // Calls when some element is dropped. | ||
| onDrop: _propTypes.default.func, | ||
| // | ||
| // Other validations | ||
| // | ||
| droppingItem: (_propTypes.default.shape({ | ||
| i: _propTypes.default.string.isRequired, | ||
| w: _propTypes.default.number.isRequired, | ||
| h: _propTypes.default.number.isRequired | ||
| }) /*: ReactPropsChainableTypeChecker*/), | ||
| // Children must not have duplicate keys. | ||
| children: function (props /*: Props*/, propName /*: string*/) { | ||
| const children = props[propName]; | ||
| // Check children keys for duplicates. Throw if found. | ||
| const keys = {}; | ||
| _react.default.Children.forEach(children, function (child) { | ||
| if ((child === null || child === void 0 ? void 0 : child.key) == null) return; | ||
| if (keys[child.key]) { | ||
| throw new Error('Duplicate child key "' + child.key + '" found! This will cause problems in ReactGridLayout.'); | ||
| } | ||
| keys[child.key] = true; | ||
| }); | ||
| }, | ||
| // Optional ref for getting a reference for the wrapping div. | ||
| innerRef: _propTypes.default.any | ||
| }; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.default = void 0; | ||
| var React = _interopRequireWildcard(require("react")); | ||
| var _propTypes = _interopRequireDefault(require("prop-types")); | ||
| var _fastEquals = require("fast-equals"); | ||
| var _utils = require("./utils"); | ||
| var _responsiveUtils = require("./responsiveUtils"); | ||
| var _ReactGridLayout = _interopRequireDefault(require("./ReactGridLayout")); | ||
| const _excluded = ["breakpoint", "breakpoints", "cols", "layouts", "margin", "containerPadding", "onBreakpointChange", "onLayoutChange", "onWidthChange"]; | ||
| function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
| function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } | ||
| function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } | ||
| function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } | ||
| function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } | ||
| function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
| function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
| function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } | ||
| function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } | ||
| function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*:: import { type Layout, type Pick } from "./utils";*/ /*:: import { type ResponsiveLayout, type OnLayoutChangeCallback, type Breakpoints } from "./responsiveUtils";*/ | ||
| // $FlowFixMe[method-unbinding] | ||
| const type = obj => Object.prototype.toString.call(obj); | ||
| /** | ||
| * Get a value of margin or containerPadding. | ||
| * | ||
| * @param {Array | Object} param Margin | containerPadding, e.g. [10, 10] | {lg: [10, 10], ...}. | ||
| * @param {String} breakpoint Breakpoint: lg, md, sm, xs and etc. | ||
| * @return {Array} | ||
| */ | ||
| function getIndentationValue /*:: <T: ?[number, number]>*/(param /*: { [key: string]: T } | T*/, breakpoint /*: string*/) /*: T*/{ | ||
| // $FlowIgnore TODO fix this typedef | ||
| if (param == null) return null; | ||
| // $FlowIgnore TODO fix this typedef | ||
| return Array.isArray(param) ? param : param[breakpoint]; | ||
| } | ||
| /*:: type State = { | ||
| layout: Layout, | ||
| breakpoint: string, | ||
| cols: number, | ||
| layouts?: ResponsiveLayout<string> | ||
| };*/ | ||
| /*:: type Props<Breakpoint: string = string> = {| | ||
| ...React.ElementConfig<typeof ReactGridLayout>, | ||
| // Responsive config | ||
| breakpoint?: ?Breakpoint, | ||
| breakpoints: Breakpoints<Breakpoint>, | ||
| cols: { [key: Breakpoint]: number }, | ||
| layouts: ResponsiveLayout<Breakpoint>, | ||
| width: number, | ||
| margin: { [key: Breakpoint]: [number, number] } | [number, number], | ||
| /* prettier-ignore *-/ | ||
| containerPadding: { [key: Breakpoint]: ?[number, number] } | ?[number, number], | ||
| // Callbacks | ||
| onBreakpointChange: (Breakpoint, cols: number) => void, | ||
| onLayoutChange: OnLayoutChangeCallback, | ||
| onWidthChange: ( | ||
| containerWidth: number, | ||
| margin: [number, number], | ||
| cols: number, | ||
| containerPadding: ?[number, number] | ||
| ) => void | ||
| |};*/ | ||
| /*:: type DefaultProps = Pick< | ||
| Props<>, | ||
| {| | ||
| allowOverlap: 0, | ||
| breakpoints: 0, | ||
| cols: 0, | ||
| containerPadding: 0, | ||
| layouts: 0, | ||
| margin: 0, | ||
| onBreakpointChange: 0, | ||
| onLayoutChange: 0, | ||
| onWidthChange: 0 | ||
| |} | ||
| >;*/ | ||
| class ResponsiveReactGridLayout extends React.Component | ||
| /*:: < | ||
| Props<>, | ||
| State | ||
| >*/ | ||
| { | ||
| constructor() { | ||
| super(...arguments); | ||
| _defineProperty(this, "state", this.generateInitialState()); | ||
| // wrap layouts so we do not need to pass layouts to child | ||
| _defineProperty(this, "onLayoutChange", (layout /*: Layout*/) => { | ||
| this.props.onLayoutChange(layout, _objectSpread(_objectSpread({}, this.props.layouts), {}, { | ||
| [this.state.breakpoint]: layout | ||
| })); | ||
| }); | ||
| } | ||
| generateInitialState() /*: State*/{ | ||
| const { | ||
| width, | ||
| breakpoints, | ||
| layouts, | ||
| cols | ||
| } = this.props; | ||
| const breakpoint = (0, _responsiveUtils.getBreakpointFromWidth)(breakpoints, width); | ||
| const colNo = (0, _responsiveUtils.getColsFromBreakpoint)(breakpoint, cols); | ||
| // verticalCompact compatibility, now deprecated | ||
| const compactType = this.props.verticalCompact === false ? null : this.props.compactType; | ||
| // Get the initial layout. This can tricky; we try to generate one however possible if one doesn't exist | ||
| // for this layout. | ||
| const initialLayout = (0, _responsiveUtils.findOrGenerateResponsiveLayout)(layouts, breakpoints, breakpoint, breakpoint, colNo, compactType); | ||
| return { | ||
| layout: initialLayout, | ||
| breakpoint: breakpoint, | ||
| cols: colNo | ||
| }; | ||
| } | ||
| static getDerivedStateFromProps(nextProps /*: Props<*>*/, prevState /*: State*/) /*: ?$Shape<State>*/{ | ||
| if (!(0, _fastEquals.deepEqual)(nextProps.layouts, prevState.layouts)) { | ||
| // Allow parent to set layouts directly. | ||
| const { | ||
| breakpoint, | ||
| cols | ||
| } = prevState; | ||
| // Since we're setting an entirely new layout object, we must generate a new responsive layout | ||
| // if one does not exist. | ||
| const newLayout = (0, _responsiveUtils.findOrGenerateResponsiveLayout)(nextProps.layouts, nextProps.breakpoints, breakpoint, breakpoint, cols, nextProps.compactType); | ||
| return { | ||
| layout: newLayout, | ||
| layouts: nextProps.layouts | ||
| }; | ||
| } | ||
| return null; | ||
| } | ||
| componentDidUpdate(prevProps /*: Props<*>*/) { | ||
| // Allow parent to set width or breakpoint directly. | ||
| if (this.props.width != prevProps.width || this.props.breakpoint !== prevProps.breakpoint || !(0, _fastEquals.deepEqual)(this.props.breakpoints, prevProps.breakpoints) || !(0, _fastEquals.deepEqual)(this.props.cols, prevProps.cols)) { | ||
| this.onWidthChange(prevProps); | ||
| } | ||
| } | ||
| /** | ||
| * When the width changes work through breakpoints and reset state with the new width & breakpoint. | ||
| * Width changes are necessary to figure out the widget widths. | ||
| */ | ||
| onWidthChange(prevProps /*: Props<*>*/) { | ||
| const { | ||
| breakpoints, | ||
| cols, | ||
| layouts, | ||
| compactType | ||
| } = this.props; | ||
| const newBreakpoint = this.props.breakpoint || (0, _responsiveUtils.getBreakpointFromWidth)(this.props.breakpoints, this.props.width); | ||
| const lastBreakpoint = this.state.breakpoint; | ||
| const newCols /*: number*/ = (0, _responsiveUtils.getColsFromBreakpoint)(newBreakpoint, cols); | ||
| const newLayouts = _objectSpread({}, layouts); | ||
| // Breakpoint change | ||
| if (lastBreakpoint !== newBreakpoint || prevProps.breakpoints !== breakpoints || prevProps.cols !== cols) { | ||
| // Preserve the current layout if the current breakpoint is not present in the next layouts. | ||
| if (!(lastBreakpoint in newLayouts)) newLayouts[lastBreakpoint] = (0, _utils.cloneLayout)(this.state.layout); | ||
| // Find or generate a new layout. | ||
| let layout = (0, _responsiveUtils.findOrGenerateResponsiveLayout)(newLayouts, breakpoints, newBreakpoint, lastBreakpoint, newCols, compactType); | ||
| // This adds missing items. | ||
| layout = (0, _utils.synchronizeLayoutWithChildren)(layout, this.props.children, newCols, compactType, this.props.allowOverlap); | ||
| // Store the new layout. | ||
| newLayouts[newBreakpoint] = layout; | ||
| // callbacks | ||
| this.props.onBreakpointChange(newBreakpoint, newCols); | ||
| this.props.onLayoutChange(layout, newLayouts); | ||
| this.setState({ | ||
| breakpoint: newBreakpoint, | ||
| layout: layout, | ||
| cols: newCols | ||
| }); | ||
| } | ||
| const margin = getIndentationValue(this.props.margin, newBreakpoint); | ||
| const containerPadding = getIndentationValue(this.props.containerPadding, newBreakpoint); | ||
| //call onWidthChange on every change of width, not only on breakpoint changes | ||
| this.props.onWidthChange(this.props.width, margin, newCols, containerPadding); | ||
| } | ||
| render() /*: React.Element<typeof ReactGridLayout>*/{ | ||
| /* eslint-disable no-unused-vars */ | ||
| const _this$props = this.props, | ||
| { | ||
| breakpoint, | ||
| breakpoints, | ||
| cols, | ||
| layouts, | ||
| margin, | ||
| containerPadding, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange | ||
| } = _this$props, | ||
| other = _objectWithoutProperties(_this$props, _excluded); | ||
| /* eslint-enable no-unused-vars */ | ||
| return /*#__PURE__*/React.createElement(_ReactGridLayout.default, _extends({}, other, { | ||
| // $FlowIgnore should allow nullable here due to DefaultProps | ||
| margin: getIndentationValue(margin, this.state.breakpoint), | ||
| containerPadding: getIndentationValue(containerPadding, this.state.breakpoint), | ||
| onLayoutChange: this.onLayoutChange, | ||
| layout: this.state.layout, | ||
| cols: this.state.cols | ||
| })); | ||
| } | ||
| } | ||
| exports.default = ResponsiveReactGridLayout; | ||
| // This should only include propTypes needed in this code; RGL itself | ||
| // will do validation of the rest props passed to it. | ||
| _defineProperty(ResponsiveReactGridLayout, "propTypes", { | ||
| // | ||
| // Basic props | ||
| // | ||
| // Optional, but if you are managing width yourself you may want to set the breakpoint | ||
| // yourself as well. | ||
| breakpoint: _propTypes.default.string, | ||
| // {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480} | ||
| breakpoints: _propTypes.default.object, | ||
| allowOverlap: _propTypes.default.bool, | ||
| // # of cols. This is a breakpoint -> cols map | ||
| cols: _propTypes.default.object, | ||
| // # of margin. This is a breakpoint -> margin map | ||
| // e.g. { lg: [5, 5], md: [10, 10], sm: [15, 15] } | ||
| // Margin between items [x, y] in px | ||
| // e.g. [10, 10] | ||
| margin: _propTypes.default.oneOfType([_propTypes.default.array, _propTypes.default.object]), | ||
| // # of containerPadding. This is a breakpoint -> containerPadding map | ||
| // e.g. { lg: [5, 5], md: [10, 10], sm: [15, 15] } | ||
| // Padding inside the container [x, y] in px | ||
| // e.g. [10, 10] | ||
| containerPadding: _propTypes.default.oneOfType([_propTypes.default.array, _propTypes.default.object]), | ||
| // layouts is an object mapping breakpoints to layouts. | ||
| // e.g. {lg: Layout, md: Layout, ...} | ||
| layouts(props /*: Props<>*/, propName /*: string*/) { | ||
| if (type(props[propName]) !== "[object Object]") { | ||
| throw new Error("Layout property must be an object. Received: " + type(props[propName])); | ||
| } | ||
| Object.keys(props[propName]).forEach(key => { | ||
| if (!(key in props.breakpoints)) { | ||
| throw new Error("Each key in layouts must align with a key in breakpoints."); | ||
| } | ||
| (0, _utils.validateLayout)(props.layouts[key], "layouts." + key); | ||
| }); | ||
| }, | ||
| // The width of this component. | ||
| // Required in this propTypes stanza because generateInitialState() will fail without it. | ||
| width: _propTypes.default.number.isRequired, | ||
| // | ||
| // Callbacks | ||
| // | ||
| // Calls back with breakpoint and new # cols | ||
| onBreakpointChange: _propTypes.default.func, | ||
| // Callback so you can save the layout. | ||
| // Calls back with (currentLayout, allLayouts). allLayouts are keyed by breakpoint. | ||
| onLayoutChange: _propTypes.default.func, | ||
| // Calls back with (containerWidth, margin, cols, containerPadding) | ||
| onWidthChange: _propTypes.default.func | ||
| }); | ||
| _defineProperty(ResponsiveReactGridLayout, "defaultProps", { | ||
| breakpoints: { | ||
| lg: 1200, | ||
| md: 996, | ||
| sm: 768, | ||
| xs: 480, | ||
| xxs: 0 | ||
| }, | ||
| cols: { | ||
| lg: 12, | ||
| md: 10, | ||
| sm: 6, | ||
| xs: 4, | ||
| xxs: 2 | ||
| }, | ||
| containerPadding: { | ||
| lg: null, | ||
| md: null, | ||
| sm: null, | ||
| xs: null, | ||
| xxs: null | ||
| }, | ||
| layouts: {}, | ||
| margin: [10, 10], | ||
| allowOverlap: false, | ||
| onBreakpointChange: _utils.noop, | ||
| onLayoutChange: _utils.noop, | ||
| onWidthChange: _utils.noop | ||
| }); |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.findOrGenerateResponsiveLayout = findOrGenerateResponsiveLayout; | ||
| exports.getBreakpointFromWidth = getBreakpointFromWidth; | ||
| exports.getColsFromBreakpoint = getColsFromBreakpoint; | ||
| exports.sortBreakpoints = sortBreakpoints; | ||
| var _utils = require("./utils"); | ||
| /*:: import type { CompactType, Layout } from "./utils";*/ | ||
| /*:: export type Breakpoint = string;*/ | ||
| /*:: export type DefaultBreakpoints = "lg" | "md" | "sm" | "xs" | "xxs";*/ | ||
| /*:: export type ResponsiveLayout<T: Breakpoint> = { | ||
| +[breakpoint: T]: Layout | ||
| };*/ | ||
| // + indicates read-only | ||
| /*:: export type Breakpoints<T: Breakpoint> = { | ||
| +[breakpoint: T]: number | ||
| };*/ | ||
| /*:: export type OnLayoutChangeCallback = ( | ||
| Layout, | ||
| { [key: Breakpoint]: Layout } | ||
| ) => void;*/ | ||
| /** | ||
| * Given a width, find the highest breakpoint that matches is valid for it (width > breakpoint). | ||
| * | ||
| * @param {Object} breakpoints Breakpoints object (e.g. {lg: 1200, md: 960, ...}) | ||
| * @param {Number} width Screen width. | ||
| * @return {String} Highest breakpoint that is less than width. | ||
| */ | ||
| function getBreakpointFromWidth(breakpoints /*: Breakpoints<Breakpoint>*/, width /*: number*/) /*: Breakpoint*/{ | ||
| const sorted = sortBreakpoints(breakpoints); | ||
| let matching = sorted[0]; | ||
| for (let i = 1, len = sorted.length; i < len; i++) { | ||
| const breakpointName = sorted[i]; | ||
| if (width > breakpoints[breakpointName]) matching = breakpointName; | ||
| } | ||
| return matching; | ||
| } | ||
| /** | ||
| * Given a breakpoint, get the # of cols set for it. | ||
| * @param {String} breakpoint Breakpoint name. | ||
| * @param {Object} cols Map of breakpoints to cols. | ||
| * @return {Number} Number of cols. | ||
| */ | ||
| function getColsFromBreakpoint(breakpoint /*: Breakpoint*/, cols /*: Breakpoints<Breakpoint>*/) /*: number*/{ | ||
| if (!cols[breakpoint]) { | ||
| throw new Error("ResponsiveReactGridLayout: `cols` entry for breakpoint " + breakpoint + " is missing!"); | ||
| } | ||
| return cols[breakpoint]; | ||
| } | ||
| /** | ||
| * Given existing layouts and a new breakpoint, find or generate a new layout. | ||
| * | ||
| * This finds the layout above the new one and generates from it, if it exists. | ||
| * | ||
| * @param {Object} layouts Existing layouts. | ||
| * @param {Array} breakpoints All breakpoints. | ||
| * @param {String} breakpoint New breakpoint. | ||
| * @param {String} breakpoint Last breakpoint (for fallback). | ||
| * @param {Number} cols Column count at new breakpoint. | ||
| * @param {Boolean} verticalCompact Whether or not to compact the layout | ||
| * vertically. | ||
| * @return {Array} New layout. | ||
| */ | ||
| function findOrGenerateResponsiveLayout(layouts /*: ResponsiveLayout<Breakpoint>*/, breakpoints /*: Breakpoints<Breakpoint>*/, breakpoint /*: Breakpoint*/, lastBreakpoint /*: Breakpoint*/, cols /*: number*/, compactType /*: CompactType*/) /*: Layout*/{ | ||
| // If it already exists, just return it. | ||
| if (layouts[breakpoint]) return (0, _utils.cloneLayout)(layouts[breakpoint]); | ||
| // Find or generate the next layout | ||
| let layout = layouts[lastBreakpoint]; | ||
| const breakpointsSorted = sortBreakpoints(breakpoints); | ||
| const breakpointsAbove = breakpointsSorted.slice(breakpointsSorted.indexOf(breakpoint)); | ||
| for (let i = 0, len = breakpointsAbove.length; i < len; i++) { | ||
| const b = breakpointsAbove[i]; | ||
| if (layouts[b]) { | ||
| layout = layouts[b]; | ||
| break; | ||
| } | ||
| } | ||
| layout = (0, _utils.cloneLayout)(layout || []); // clone layout so we don't modify existing items | ||
| return (0, _utils.compact)((0, _utils.correctBounds)(layout, { | ||
| cols: cols | ||
| }), compactType, cols); | ||
| } | ||
| /** | ||
| * Given breakpoints, return an array of breakpoints sorted by width. This is usually | ||
| * e.g. ['xxs', 'xs', 'sm', ...] | ||
| * | ||
| * @param {Object} breakpoints Key/value pair of breakpoint names to widths. | ||
| * @return {Array} Sorted breakpoints. | ||
| */ | ||
| function sortBreakpoints(breakpoints /*: Breakpoints<Breakpoint>*/) /*: Array<Breakpoint>*/{ | ||
| const keys /*: Array<string>*/ = Object.keys(breakpoints); | ||
| return keys.sort(function (a, b) { | ||
| return breakpoints[a] - breakpoints[b]; | ||
| }); | ||
| } |
-842
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.bottom = bottom; | ||
| exports.childrenEqual = childrenEqual; | ||
| exports.cloneLayout = cloneLayout; | ||
| exports.cloneLayoutItem = cloneLayoutItem; | ||
| exports.collides = collides; | ||
| exports.compact = compact; | ||
| exports.compactItem = compactItem; | ||
| exports.compactType = compactType; | ||
| exports.correctBounds = correctBounds; | ||
| exports.fastPositionEqual = fastPositionEqual; | ||
| exports.fastRGLPropsEqual = void 0; | ||
| exports.getAllCollisions = getAllCollisions; | ||
| exports.getFirstCollision = getFirstCollision; | ||
| exports.getLayoutItem = getLayoutItem; | ||
| exports.getStatics = getStatics; | ||
| exports.modifyLayout = modifyLayout; | ||
| exports.moveElement = moveElement; | ||
| exports.moveElementAwayFromCollision = moveElementAwayFromCollision; | ||
| exports.noop = void 0; | ||
| exports.perc = perc; | ||
| exports.resizeItemInDirection = resizeItemInDirection; | ||
| exports.setTopLeft = setTopLeft; | ||
| exports.setTransform = setTransform; | ||
| exports.sortLayoutItems = sortLayoutItems; | ||
| exports.sortLayoutItemsByColRow = sortLayoutItemsByColRow; | ||
| exports.sortLayoutItemsByRowCol = sortLayoutItemsByRowCol; | ||
| exports.synchronizeLayoutWithChildren = synchronizeLayoutWithChildren; | ||
| exports.validateLayout = validateLayout; | ||
| exports.withLayoutItem = withLayoutItem; | ||
| var _fastEquals = require("fast-equals"); | ||
| var _react = _interopRequireDefault(require("react")); | ||
| function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
| function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
| function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
| function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } | ||
| function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } | ||
| function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } | ||
| /*:: import type { | ||
| ChildrenArray as ReactChildrenArray, | ||
| Element as ReactElement | ||
| } from "react";*/ | ||
| /*:: export type ResizeHandleAxis = | ||
| | "s" | ||
| | "w" | ||
| | "e" | ||
| | "n" | ||
| | "sw" | ||
| | "nw" | ||
| | "se" | ||
| | "ne";*/ | ||
| /*:: export type LayoutItem = { | ||
| w: number, | ||
| h: number, | ||
| x: number, | ||
| y: number, | ||
| i: string, | ||
| minW?: number, | ||
| minH?: number, | ||
| maxW?: number, | ||
| maxH?: number, | ||
| moved?: boolean, | ||
| static?: boolean, | ||
| isDraggable?: ?boolean, | ||
| isResizable?: ?boolean, | ||
| resizeHandles?: Array<ResizeHandleAxis>, | ||
| isBounded?: ?boolean | ||
| };*/ | ||
| /*:: export type Layout = $ReadOnlyArray<LayoutItem>;*/ | ||
| /*:: export type Position = { | ||
| left: number, | ||
| top: number, | ||
| width: number, | ||
| height: number | ||
| };*/ | ||
| /*:: export type ReactDraggableCallbackData = { | ||
| node: HTMLElement, | ||
| x?: number, | ||
| y?: number, | ||
| deltaX: number, | ||
| deltaY: number, | ||
| lastX?: number, | ||
| lastY?: number | ||
| };*/ | ||
| /*:: export type PartialPosition = { left: number, top: number };*/ | ||
| /*:: export type DroppingPosition = { left: number, top: number, e: Event };*/ | ||
| /*:: export type Size = { width: number, height: number };*/ | ||
| /*:: export type GridDragEvent = { | ||
| e: Event, | ||
| node: HTMLElement, | ||
| newPosition: PartialPosition | ||
| };*/ | ||
| /*:: export type GridResizeEvent = { | ||
| e: Event, | ||
| node: HTMLElement, | ||
| size: Size, | ||
| handle: string | ||
| };*/ | ||
| /*:: export type DragOverEvent = MouseEvent & { | ||
| nativeEvent: { | ||
| layerX: number, | ||
| layerY: number, | ||
| ...Event | ||
| } | ||
| };*/ | ||
| /*:: export type Pick<FromType, Properties: { [string]: 0 }> = $Exact< | ||
| $ObjMapi<Properties, <K, V>(k: K, v: V) => $ElementType<FromType, K>> | ||
| >;*/ | ||
| // Helpful port from TS | ||
| /*:: type REl = ReactElement<any>;*/ | ||
| /*:: export type ReactChildren = ReactChildrenArray<REl>;*/ | ||
| /*:: export type EventCallback = ( | ||
| Layout, | ||
| oldItem: ?LayoutItem, | ||
| newItem: ?LayoutItem, | ||
| placeholder: ?LayoutItem, | ||
| Event, | ||
| ?HTMLElement | ||
| ) => void;*/ | ||
| // All callbacks are of the signature (layout, oldItem, newItem, placeholder, e). | ||
| /*:: export type CompactType = ?("horizontal" | "vertical");*/ | ||
| const isProduction = process.env.NODE_ENV === "production"; | ||
| const DEBUG = false; | ||
| /** | ||
| * Return the bottom coordinate of the layout. | ||
| * | ||
| * @param {Array} layout Layout array. | ||
| * @return {Number} Bottom coordinate. | ||
| */ | ||
| function bottom(layout /*: Layout*/) /*: number*/{ | ||
| let max = 0, | ||
| bottomY; | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| bottomY = layout[i].y + layout[i].h; | ||
| if (bottomY > max) max = bottomY; | ||
| } | ||
| return max; | ||
| } | ||
| function cloneLayout(layout /*: Layout*/) /*: Layout*/{ | ||
| const newLayout = Array(layout.length); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| newLayout[i] = cloneLayoutItem(layout[i]); | ||
| } | ||
| return newLayout; | ||
| } | ||
| // Modify a layoutItem inside a layout. Returns a new Layout, | ||
| // does not mutate. Carries over all other LayoutItems unmodified. | ||
| function modifyLayout(layout /*: Layout*/, layoutItem /*: LayoutItem*/) /*: Layout*/{ | ||
| const newLayout = Array(layout.length); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| if (layoutItem.i === layout[i].i) { | ||
| newLayout[i] = layoutItem; | ||
| } else { | ||
| newLayout[i] = layout[i]; | ||
| } | ||
| } | ||
| return newLayout; | ||
| } | ||
| // Function to be called to modify a layout item. | ||
| // Does defensive clones to ensure the layout is not modified. | ||
| function withLayoutItem(layout /*: Layout*/, itemKey /*: string*/, cb /*: LayoutItem => LayoutItem*/) /*: [Layout, ?LayoutItem]*/{ | ||
| let item = getLayoutItem(layout, itemKey); | ||
| if (!item) return [layout, null]; | ||
| item = cb(cloneLayoutItem(item)); // defensive clone then modify | ||
| // FIXME could do this faster if we already knew the index | ||
| layout = modifyLayout(layout, item); | ||
| return [layout, item]; | ||
| } | ||
| // Fast path to cloning, since this is monomorphic | ||
| function cloneLayoutItem(layoutItem /*: LayoutItem*/) /*: LayoutItem*/{ | ||
| return { | ||
| w: layoutItem.w, | ||
| h: layoutItem.h, | ||
| x: layoutItem.x, | ||
| y: layoutItem.y, | ||
| i: layoutItem.i, | ||
| minW: layoutItem.minW, | ||
| maxW: layoutItem.maxW, | ||
| minH: layoutItem.minH, | ||
| maxH: layoutItem.maxH, | ||
| moved: Boolean(layoutItem.moved), | ||
| static: Boolean(layoutItem.static), | ||
| // These can be null/undefined | ||
| isDraggable: layoutItem.isDraggable, | ||
| isResizable: layoutItem.isResizable, | ||
| resizeHandles: layoutItem.resizeHandles, | ||
| isBounded: layoutItem.isBounded | ||
| }; | ||
| } | ||
| /** | ||
| * Comparing React `children` is a bit difficult. This is a good way to compare them. | ||
| * This will catch differences in keys, order, and length. | ||
| */ | ||
| function childrenEqual(a /*: ReactChildren*/, b /*: ReactChildren*/) /*: boolean*/{ | ||
| return (0, _fastEquals.deepEqual)(_react.default.Children.map(a, c => c === null || c === void 0 ? void 0 : c.key), _react.default.Children.map(b, c => c === null || c === void 0 ? void 0 : c.key)) && (0, _fastEquals.deepEqual)(_react.default.Children.map(a, c => c === null || c === void 0 ? void 0 : c.props["data-grid"]), _react.default.Children.map(b, c => c === null || c === void 0 ? void 0 : c.props["data-grid"])); | ||
| } | ||
| /** | ||
| * See `fastRGLPropsEqual.js`. | ||
| * We want this to run as fast as possible - it is called often - and to be | ||
| * resilient to new props that we add. So rather than call lodash.isEqual, | ||
| * which isn't suited to comparing props very well, we use this specialized | ||
| * function in conjunction with preval to generate the fastest possible comparison | ||
| * function, tuned for exactly our props. | ||
| */ | ||
| /*:: type FastRGLPropsEqual = (Object, Object, Function) => boolean;*/ | ||
| const fastRGLPropsEqual /*: FastRGLPropsEqual*/ = exports.fastRGLPropsEqual = require("./fastRGLPropsEqual"); | ||
| // Like the above, but a lot simpler. | ||
| function fastPositionEqual(a /*: Position*/, b /*: Position*/) /*: boolean*/{ | ||
| return a.left === b.left && a.top === b.top && a.width === b.width && a.height === b.height; | ||
| } | ||
| /** | ||
| * Given two layoutitems, check if they collide. | ||
| */ | ||
| function collides(l1 /*: LayoutItem*/, l2 /*: LayoutItem*/) /*: boolean*/{ | ||
| if (l1.i === l2.i) return false; // same element | ||
| if (l1.x + l1.w <= l2.x) return false; // l1 is left of l2 | ||
| if (l1.x >= l2.x + l2.w) return false; // l1 is right of l2 | ||
| if (l1.y + l1.h <= l2.y) return false; // l1 is above l2 | ||
| if (l1.y >= l2.y + l2.h) return false; // l1 is below l2 | ||
| return true; // boxes overlap | ||
| } | ||
| /** | ||
| * Given a layout, compact it. This involves going down each y coordinate and removing gaps | ||
| * between items. | ||
| * | ||
| * Does not modify layout items (clones). Creates a new layout array. | ||
| * | ||
| * @param {Array} layout Layout. | ||
| * @param {Boolean} verticalCompact Whether or not to compact the layout | ||
| * vertically. | ||
| * @param {Boolean} allowOverlap When `true`, allows overlapping grid items. | ||
| * @return {Array} Compacted Layout. | ||
| */ | ||
| function compact(layout /*: Layout*/, compactType /*: CompactType*/, cols /*: number*/, allowOverlap /*: ?boolean*/) /*: Layout*/{ | ||
| // Statics go in the compareWith array right away so items flow around them. | ||
| const compareWith = getStatics(layout); | ||
| // We keep track of the bottom position. | ||
| let b = bottom(compareWith); | ||
| // We go through the items by row and column. | ||
| const sorted = sortLayoutItems(layout, compactType); | ||
| // Holding for new items. | ||
| const out = Array(layout.length); | ||
| for (let i = 0, len = sorted.length; i < len; i++) { | ||
| let l = cloneLayoutItem(sorted[i]); | ||
| // Don't move static elements | ||
| if (!l.static) { | ||
| l = compactItem(compareWith, l, compactType, cols, sorted, allowOverlap, b); | ||
| b = Math.max(b, l.y + l.h); | ||
| // Add to comparison array. We only collide with items before this one. | ||
| // Statics are already in this array. | ||
| compareWith.push(l); | ||
| } | ||
| // Add to output array to make sure they still come out in the right order. | ||
| out[layout.indexOf(sorted[i])] = l; | ||
| // Clear moved flag, if it exists. | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| } | ||
| const heightWidth = { | ||
| x: "w", | ||
| y: "h" | ||
| }; | ||
| /** | ||
| * Before moving item down, it will check if the movement will cause collisions and move those items down before. | ||
| */ | ||
| function resolveCompactionCollision(layout /*: Layout*/, item /*: LayoutItem*/, moveToCoord /*: number*/, axis /*: "x" | "y"*/) { | ||
| const sizeProp = heightWidth[axis]; | ||
| item[axis] += 1; | ||
| const itemIndex = layout.map(layoutItem => { | ||
| return layoutItem.i; | ||
| }).indexOf(item.i); | ||
| // Go through each item we collide with. | ||
| for (let i = itemIndex + 1; i < layout.length; i++) { | ||
| const otherItem = layout[i]; | ||
| // Ignore static items | ||
| if (otherItem.static) continue; | ||
| // Optimization: we can break early if we know we're past this el | ||
| // We can do this b/c it's a sorted layout | ||
| if (otherItem.y > item.y + item.h) break; | ||
| if (collides(item, otherItem)) { | ||
| resolveCompactionCollision(layout, otherItem, moveToCoord + item[sizeProp], axis); | ||
| } | ||
| } | ||
| item[axis] = moveToCoord; | ||
| } | ||
| /** | ||
| * Compact an item in the layout. | ||
| * | ||
| * Modifies item. | ||
| * | ||
| */ | ||
| function compactItem(compareWith /*: Layout*/, l /*: LayoutItem*/, compactType /*: CompactType*/, cols /*: number*/, fullLayout /*: Layout*/, allowOverlap /*: ?boolean*/, b /*: ?number*/) /*: LayoutItem*/{ | ||
| const compactV = compactType === "vertical"; | ||
| const compactH = compactType === "horizontal"; | ||
| if (compactV) { | ||
| // Bottom 'y' possible is the bottom of the layout. | ||
| // This allows you to do nice stuff like specify {y: Infinity} | ||
| // This is here because the layout must be sorted in order to get the correct bottom `y`. | ||
| if (typeof b === "number") { | ||
| l.y = Math.min(b, l.y); | ||
| } else { | ||
| l.y = Math.min(bottom(compareWith), l.y); | ||
| } | ||
| // Move the element up as far as it can go without colliding. | ||
| while (l.y > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.y--; | ||
| } | ||
| } else if (compactH) { | ||
| // Move the element left as far as it can go without colliding. | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| // Move it down, and keep moving it down if it's colliding. | ||
| let collides; | ||
| // Checking the compactType null value to avoid breaking the layout when overlapping is allowed. | ||
| while ((collides = getFirstCollision(compareWith, l)) && !(compactType === null && allowOverlap)) { | ||
| if (compactH) { | ||
| resolveCompactionCollision(fullLayout, l, collides.x + collides.w, "x"); | ||
| } else { | ||
| resolveCompactionCollision(fullLayout, l, collides.y + collides.h, "y"); | ||
| } | ||
| // Since we can't grow without bounds horizontally, if we've overflown, let's move it down and try again. | ||
| if (compactH && l.x + l.w > cols) { | ||
| l.x = cols - l.w; | ||
| l.y++; | ||
| // ALso move element as left as we can | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| } | ||
| // Ensure that there are no negative positions | ||
| l.y = Math.max(l.y, 0); | ||
| l.x = Math.max(l.x, 0); | ||
| return l; | ||
| } | ||
| /** | ||
| * Given a layout, make sure all elements fit within its bounds. | ||
| * | ||
| * Modifies layout items. | ||
| * | ||
| * @param {Array} layout Layout array. | ||
| * @param {Number} bounds Number of columns. | ||
| */ | ||
| function correctBounds(layout /*: Layout*/, bounds /*: { cols: number }*/) /*: Layout*/{ | ||
| const collidesWith = getStatics(layout); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| const l = layout[i]; | ||
| // Overflows right | ||
| if (l.x + l.w > bounds.cols) l.x = bounds.cols - l.w; | ||
| // Overflows left | ||
| if (l.x < 0) { | ||
| l.x = 0; | ||
| l.w = bounds.cols; | ||
| } | ||
| if (!l.static) collidesWith.push(l);else { | ||
| // If this is static and collides with other statics, we must move it down. | ||
| // We have to do something nicer than just letting them overlap. | ||
| while (getFirstCollision(collidesWith, l)) { | ||
| l.y++; | ||
| } | ||
| } | ||
| } | ||
| return layout; | ||
| } | ||
| /** | ||
| * Get a layout item by ID. Used so we can override later on if necessary. | ||
| * | ||
| * @param {Array} layout Layout array. | ||
| * @param {String} id ID | ||
| * @return {LayoutItem} Item at ID. | ||
| */ | ||
| function getLayoutItem(layout /*: Layout*/, id /*: string*/) /*: ?LayoutItem*/{ | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| if (layout[i].i === id) return layout[i]; | ||
| } | ||
| } | ||
| /** | ||
| * Returns the first item this layout collides with. | ||
| * It doesn't appear to matter which order we approach this from, although | ||
| * perhaps that is the wrong thing to do. | ||
| * | ||
| * @param {Object} layoutItem Layout item. | ||
| * @return {Object|undefined} A colliding layout item, or undefined. | ||
| */ | ||
| function getFirstCollision(layout /*: Layout*/, layoutItem /*: LayoutItem*/) /*: ?LayoutItem*/{ | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| if (collides(layout[i], layoutItem)) return layout[i]; | ||
| } | ||
| } | ||
| function getAllCollisions(layout /*: Layout*/, layoutItem /*: LayoutItem*/) /*: Array<LayoutItem>*/{ | ||
| return layout.filter(l => collides(l, layoutItem)); | ||
| } | ||
| /** | ||
| * Get all static elements. | ||
| * @param {Array} layout Array of layout objects. | ||
| * @return {Array} Array of static layout items.. | ||
| */ | ||
| function getStatics(layout /*: Layout*/) /*: Array<LayoutItem>*/{ | ||
| return layout.filter(l => l.static); | ||
| } | ||
| /** | ||
| * Move an element. Responsible for doing cascading movements of other elements. | ||
| * | ||
| * Modifies layout items. | ||
| * | ||
| * @param {Array} layout Full layout to modify. | ||
| * @param {LayoutItem} l element to move. | ||
| * @param {Number} [x] X position in grid units. | ||
| * @param {Number} [y] Y position in grid units. | ||
| */ | ||
| function moveElement(layout /*: Layout*/, l /*: LayoutItem*/, x /*: ?number*/, y /*: ?number*/, isUserAction /*: ?boolean*/, preventCollision /*: ?boolean*/, compactType /*: CompactType*/, cols /*: number*/, allowOverlap /*: ?boolean*/) /*: Layout*/{ | ||
| // If this is static and not explicitly enabled as draggable, | ||
| // no move is possible, so we can short-circuit this immediately. | ||
| if (l.static && l.isDraggable !== true) return layout; | ||
| // Short-circuit if nothing to do. | ||
| if (l.y === y && l.x === x) return layout; | ||
| log("Moving element ".concat(l.i, " to [").concat(String(x), ",").concat(String(y), "] from [").concat(l.x, ",").concat(l.y, "]")); | ||
| const oldX = l.x; | ||
| const oldY = l.y; | ||
| // This is quite a bit faster than extending the object | ||
| if (typeof x === "number") l.x = x; | ||
| if (typeof y === "number") l.y = y; | ||
| l.moved = true; | ||
| // If this collides with anything, move it. | ||
| // When doing this comparison, we have to sort the items we compare with | ||
| // to ensure, in the case of multiple collisions, that we're getting the | ||
| // nearest collision. | ||
| let sorted = sortLayoutItems(layout, compactType); | ||
| const movingUp = compactType === "vertical" && typeof y === "number" ? oldY >= y : compactType === "horizontal" && typeof x === "number" ? oldX >= x : false; | ||
| // $FlowIgnore acceptable modification of read-only array as it was recently cloned | ||
| if (movingUp) sorted = sorted.reverse(); | ||
| const collisions = getAllCollisions(sorted, l); | ||
| const hasCollisions = collisions.length > 0; | ||
| // We may have collisions. We can short-circuit if we've turned off collisions or | ||
| // allowed overlap. | ||
| if (hasCollisions && allowOverlap) { | ||
| // Easy, we don't need to resolve collisions. But we *did* change the layout, | ||
| // so clone it on the way out. | ||
| return cloneLayout(layout); | ||
| } else if (hasCollisions && preventCollision) { | ||
| // If we are preventing collision but not allowing overlap, we need to | ||
| // revert the position of this element so it goes to where it came from, rather | ||
| // than the user's desired location. | ||
| log("Collision prevented on ".concat(l.i, ", reverting.")); | ||
| l.x = oldX; | ||
| l.y = oldY; | ||
| l.moved = false; | ||
| return layout; // did not change so don't clone | ||
| } | ||
| // Move each item that collides away from this element. | ||
| for (let i = 0, len = collisions.length; i < len; i++) { | ||
| const collision = collisions[i]; | ||
| log("Resolving collision between ".concat(l.i, " at [").concat(l.x, ",").concat(l.y, "] and ").concat(collision.i, " at [").concat(collision.x, ",").concat(collision.y, "]")); | ||
| // Short circuit so we can't infinite loop | ||
| if (collision.moved) continue; | ||
| // Don't move static items - we have to move *this* element away | ||
| if (collision.static) { | ||
| layout = moveElementAwayFromCollision(layout, collision, l, isUserAction, compactType, cols); | ||
| } else { | ||
| layout = moveElementAwayFromCollision(layout, l, collision, isUserAction, compactType, cols); | ||
| } | ||
| } | ||
| return layout; | ||
| } | ||
| /** | ||
| * This is where the magic needs to happen - given a collision, move an element away from the collision. | ||
| * We attempt to move it up if there's room, otherwise it goes below. | ||
| * | ||
| * @param {Array} layout Full layout to modify. | ||
| * @param {LayoutItem} collidesWith Layout item we're colliding with. | ||
| * @param {LayoutItem} itemToMove Layout item we're moving. | ||
| */ | ||
| function moveElementAwayFromCollision(layout /*: Layout*/, collidesWith /*: LayoutItem*/, itemToMove /*: LayoutItem*/, isUserAction /*: ?boolean*/, compactType /*: CompactType*/, cols /*: number*/) /*: Layout*/{ | ||
| const compactH = compactType === "horizontal"; | ||
| // Compact vertically if not set to horizontal | ||
| const compactV = compactType === "vertical"; | ||
| const preventCollision = collidesWith.static; // we're already colliding (not for static items) | ||
| // If there is enough space above the collision to put this element, move it there. | ||
| // We only do this on the main collision as this can get funky in cascades and cause | ||
| // unwanted swapping behavior. | ||
| if (isUserAction) { | ||
| // Reset isUserAction flag because we're not in the main collision anymore. | ||
| isUserAction = false; | ||
| // Make a mock item so we don't modify the item here, only modify in moveElement. | ||
| const fakeItem /*: LayoutItem*/ = { | ||
| x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x, | ||
| y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y, | ||
| w: itemToMove.w, | ||
| h: itemToMove.h, | ||
| i: "-1" | ||
| }; | ||
| const firstCollision = getFirstCollision(layout, fakeItem); | ||
| const collisionNorth = firstCollision && firstCollision.y + firstCollision.h > collidesWith.y; | ||
| const collisionWest = firstCollision && collidesWith.x + collidesWith.w > firstCollision.x; | ||
| // No collision? If so, we can go up there; otherwise, we'll end up moving down as normal | ||
| if (!firstCollision) { | ||
| log("Doing reverse collision on ".concat(itemToMove.i, " up to [").concat(fakeItem.x, ",").concat(fakeItem.y, "].")); | ||
| return moveElement(layout, itemToMove, compactH ? fakeItem.x : undefined, compactV ? fakeItem.y : undefined, isUserAction, preventCollision, compactType, cols); | ||
| } else if (collisionNorth && compactV) { | ||
| return moveElement(layout, itemToMove, undefined, itemToMove.y + 1, isUserAction, preventCollision, compactType, cols); | ||
| } else if (collisionNorth && compactType == null) { | ||
| collidesWith.y = itemToMove.y; | ||
| itemToMove.y = itemToMove.y + itemToMove.h; | ||
| return layout; | ||
| } else if (collisionWest && compactH) { | ||
| return moveElement(layout, collidesWith, itemToMove.x, undefined, isUserAction, preventCollision, compactType, cols); | ||
| } | ||
| } | ||
| const newX = compactH ? itemToMove.x + 1 : undefined; | ||
| const newY = compactV ? itemToMove.y + 1 : undefined; | ||
| if (newX == null && newY == null) { | ||
| return layout; | ||
| } | ||
| return moveElement(layout, itemToMove, compactH ? itemToMove.x + 1 : undefined, compactV ? itemToMove.y + 1 : undefined, isUserAction, preventCollision, compactType, cols); | ||
| } | ||
| /** | ||
| * Helper to convert a number to a percentage string. | ||
| * | ||
| * @param {Number} num Any number | ||
| * @return {String} That number as a percentage. | ||
| */ | ||
| function perc(num /*: number*/) /*: string*/{ | ||
| return num * 100 + "%"; | ||
| } | ||
| /** | ||
| * Helper functions to constrain dimensions of a GridItem | ||
| */ | ||
| const constrainWidth = (left /*: number*/, currentWidth /*: number*/, newWidth /*: number*/, containerWidth /*: number*/) => { | ||
| return left + newWidth > containerWidth ? currentWidth : newWidth; | ||
| }; | ||
| const constrainHeight = (top /*: number*/, currentHeight /*: number*/, newHeight /*: number*/) => { | ||
| return top < 0 ? currentHeight : newHeight; | ||
| }; | ||
| const constrainLeft = (left /*: number*/) => Math.max(0, left); | ||
| const constrainTop = (top /*: number*/) => Math.max(0, top); | ||
| const resizeNorth = (currentSize, _ref, _containerWidth) => { | ||
| let { | ||
| left, | ||
| height, | ||
| width | ||
| } = _ref; | ||
| const top = currentSize.top - (height - currentSize.height); | ||
| return { | ||
| left, | ||
| width, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }; | ||
| }; | ||
| const resizeEast = (currentSize, _ref2, containerWidth) => { | ||
| let { | ||
| top, | ||
| left, | ||
| height, | ||
| width | ||
| } = _ref2; | ||
| return { | ||
| top, | ||
| height, | ||
| width: constrainWidth(currentSize.left, currentSize.width, width, containerWidth), | ||
| left: constrainLeft(left) | ||
| }; | ||
| }; | ||
| const resizeWest = (currentSize, _ref3, containerWidth) => { | ||
| let { | ||
| top, | ||
| height, | ||
| width | ||
| } = _ref3; | ||
| const left = currentSize.left - (width - currentSize.width); | ||
| return { | ||
| height, | ||
| width: left < 0 ? currentSize.width : constrainWidth(currentSize.left, currentSize.width, width, containerWidth), | ||
| top: constrainTop(top), | ||
| left: constrainLeft(left) | ||
| }; | ||
| }; | ||
| const resizeSouth = (currentSize, _ref4, containerWidth) => { | ||
| let { | ||
| top, | ||
| left, | ||
| height, | ||
| width | ||
| } = _ref4; | ||
| return { | ||
| width, | ||
| left, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }; | ||
| }; | ||
| const resizeNorthEast = function () { | ||
| return resizeNorth(arguments.length <= 0 ? undefined : arguments[0], resizeEast(...arguments), arguments.length <= 2 ? undefined : arguments[2]); | ||
| }; | ||
| const resizeNorthWest = function () { | ||
| return resizeNorth(arguments.length <= 0 ? undefined : arguments[0], resizeWest(...arguments), arguments.length <= 2 ? undefined : arguments[2]); | ||
| }; | ||
| const resizeSouthEast = function () { | ||
| return resizeSouth(arguments.length <= 0 ? undefined : arguments[0], resizeEast(...arguments), arguments.length <= 2 ? undefined : arguments[2]); | ||
| }; | ||
| const resizeSouthWest = function () { | ||
| return resizeSouth(arguments.length <= 0 ? undefined : arguments[0], resizeWest(...arguments), arguments.length <= 2 ? undefined : arguments[2]); | ||
| }; | ||
| const ordinalResizeHandlerMap = { | ||
| n: resizeNorth, | ||
| ne: resizeNorthEast, | ||
| e: resizeEast, | ||
| se: resizeSouthEast, | ||
| s: resizeSouth, | ||
| sw: resizeSouthWest, | ||
| w: resizeWest, | ||
| nw: resizeNorthWest | ||
| }; | ||
| /** | ||
| * Helper for clamping width and position when resizing an item. | ||
| */ | ||
| function resizeItemInDirection(direction /*: ResizeHandleAxis*/, currentSize /*: Position*/, newSize /*: Position*/, containerWidth /*: number*/) /*: Position*/{ | ||
| const ordinalHandler = ordinalResizeHandlerMap[direction]; | ||
| // Shouldn't be possible given types; that said, don't fail hard | ||
| if (!ordinalHandler) return newSize; | ||
| return ordinalHandler(currentSize, _objectSpread(_objectSpread({}, currentSize), newSize), containerWidth); | ||
| } | ||
| function setTransform(_ref5 /*:: */) /*: Object*/{ | ||
| let { | ||
| top, | ||
| left, | ||
| width, | ||
| height | ||
| } /*: Position*/ = _ref5 /*: Position*/; | ||
| // Replace unitless items with px | ||
| const translate = "translate(".concat(left, "px,").concat(top, "px)"); | ||
| return { | ||
| transform: translate, | ||
| WebkitTransform: translate, | ||
| MozTransform: translate, | ||
| msTransform: translate, | ||
| OTransform: translate, | ||
| width: "".concat(width, "px"), | ||
| height: "".concat(height, "px"), | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| function setTopLeft(_ref6 /*:: */) /*: Object*/{ | ||
| let { | ||
| top, | ||
| left, | ||
| width, | ||
| height | ||
| } /*: Position*/ = _ref6 /*: Position*/; | ||
| return { | ||
| top: "".concat(top, "px"), | ||
| left: "".concat(left, "px"), | ||
| width: "".concat(width, "px"), | ||
| height: "".concat(height, "px"), | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| /** | ||
| * Get layout items sorted from top left to right and down. | ||
| * | ||
| * @return {Array} Array of layout objects. | ||
| * @return {Array} Layout, sorted static items first. | ||
| */ | ||
| function sortLayoutItems(layout /*: Layout*/, compactType /*: CompactType*/) /*: Layout*/{ | ||
| if (compactType === "horizontal") return sortLayoutItemsByColRow(layout); | ||
| if (compactType === "vertical") return sortLayoutItemsByRowCol(layout);else return layout; | ||
| } | ||
| /** | ||
| * Sort layout items by row ascending and column ascending. | ||
| * | ||
| * Does not modify Layout. | ||
| */ | ||
| function sortLayoutItemsByRowCol(layout /*: Layout*/) /*: Layout*/{ | ||
| // Slice to clone array as sort modifies | ||
| return layout.slice(0).sort(function (a, b) { | ||
| if (a.y > b.y || a.y === b.y && a.x > b.x) { | ||
| return 1; | ||
| } else if (a.y === b.y && a.x === b.x) { | ||
| // Without this, we can get different sort results in IE vs. Chrome/FF | ||
| return 0; | ||
| } | ||
| return -1; | ||
| }); | ||
| } | ||
| /** | ||
| * Sort layout items by column ascending then row ascending. | ||
| * | ||
| * Does not modify Layout. | ||
| */ | ||
| function sortLayoutItemsByColRow(layout /*: Layout*/) /*: Layout*/{ | ||
| return layout.slice(0).sort(function (a, b) { | ||
| if (a.x > b.x || a.x === b.x && a.y > b.y) { | ||
| return 1; | ||
| } | ||
| return -1; | ||
| }); | ||
| } | ||
| /** | ||
| * Generate a layout using the initialLayout and children as a template. | ||
| * Missing entries will be added, extraneous ones will be truncated. | ||
| * | ||
| * Does not modify initialLayout. | ||
| * | ||
| * @param {Array} initialLayout Layout passed in through props. | ||
| * @param {String} breakpoint Current responsive breakpoint. | ||
| * @param {?String} compact Compaction option. | ||
| * @return {Array} Working layout. | ||
| */ | ||
| function synchronizeLayoutWithChildren(initialLayout /*: Layout*/, children /*: ReactChildren*/, cols /*: number*/, compactType /*: CompactType*/, allowOverlap /*: ?boolean*/) /*: Layout*/{ | ||
| initialLayout = initialLayout || []; | ||
| // Generate one layout item per child. | ||
| const layout /*: LayoutItem[]*/ = []; | ||
| _react.default.Children.forEach(children, (child /*: ReactElement<any>*/) => { | ||
| // Child may not exist | ||
| if ((child === null || child === void 0 ? void 0 : child.key) == null) return; | ||
| const exists = getLayoutItem(initialLayout, String(child.key)); | ||
| const g = child.props["data-grid"]; | ||
| // Don't overwrite the layout item if it's already in the initial layout. | ||
| // If it has a `data-grid` property, prefer that over what's in the layout. | ||
| if (exists && g == null) { | ||
| layout.push(cloneLayoutItem(exists)); | ||
| } else { | ||
| // Hey, this item has a data-grid property, use it. | ||
| if (g) { | ||
| if (!isProduction) { | ||
| validateLayout([g], "ReactGridLayout.children"); | ||
| } | ||
| // FIXME clone not really necessary here | ||
| layout.push(cloneLayoutItem(_objectSpread(_objectSpread({}, g), {}, { | ||
| i: child.key | ||
| }))); | ||
| } else { | ||
| // Nothing provided: ensure this is added to the bottom | ||
| // FIXME clone not really necessary here | ||
| layout.push(cloneLayoutItem({ | ||
| w: 1, | ||
| h: 1, | ||
| x: 0, | ||
| y: bottom(layout), | ||
| i: String(child.key) | ||
| })); | ||
| } | ||
| } | ||
| }); | ||
| // Correct the layout. | ||
| const correctedLayout = correctBounds(layout, { | ||
| cols: cols | ||
| }); | ||
| return allowOverlap ? correctedLayout : compact(correctedLayout, compactType, cols); | ||
| } | ||
| /** | ||
| * Validate a layout. Throws errors. | ||
| * | ||
| * @param {Array} layout Array of layout items. | ||
| * @param {String} [contextName] Context name for errors. | ||
| * @throw {Error} Validation error. | ||
| */ | ||
| function validateLayout(layout /*: Layout*/) /*: void*/{ | ||
| let contextName /*: string*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "Layout"; | ||
| const subProps = ["x", "y", "w", "h"]; | ||
| if (!Array.isArray(layout)) throw new Error(contextName + " must be an array!"); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| const item = layout[i]; | ||
| for (let j = 0; j < subProps.length; j++) { | ||
| const key = subProps[j]; | ||
| const value = item[key]; | ||
| if (typeof value !== "number" || Number.isNaN(value)) { | ||
| throw new Error("ReactGridLayout: ".concat(contextName, "[").concat(i, "].").concat(key, " must be a number! Received: ").concat(value, " (").concat(typeof value, ")")); | ||
| } | ||
| } | ||
| if (typeof item.i !== "undefined" && typeof item.i !== "string") { | ||
| throw new Error("ReactGridLayout: ".concat(contextName, "[").concat(i, "].i must be a string! Received: ").concat(item.i, " (").concat(typeof item.i, ")")); | ||
| } | ||
| } | ||
| } | ||
| // Legacy support for verticalCompact: false | ||
| function compactType(props /*: ?{ verticalCompact: boolean, compactType: CompactType }*/) /*: CompactType*/{ | ||
| const { | ||
| verticalCompact, | ||
| compactType | ||
| } = props || {}; | ||
| return verticalCompact === false ? null : compactType; | ||
| } | ||
| function log() { | ||
| if (!DEBUG) return; | ||
| // eslint-disable-next-line no-console | ||
| console.log(...arguments); | ||
| } | ||
| const noop = () => {}; | ||
| exports.noop = noop; |
-985
| # Changelog | ||
| ## 1.5.3 (Dec 5, 2025) | ||
| - Fix collision detection y-coordinate offset. [#2173](https://github.com/react-grid-layout/react-grid-layout/pull/2173) | ||
| - Memoize bottom computation in compact for performance. [#2115](https://github.com/react-grid-layout/react-grid-layout/pull/2115) | ||
| - Make `b` param in `compactItem` optional. [#2165](https://github.com/react-grid-layout/react-grid-layout/pull/2165) | ||
| - Fix example animations and rework example styles. | ||
| - Various devDependency updates and security fixes. [#2179](https://github.com/react-grid-layout/react-grid-layout/pull/2179) | ||
| ## 1.5.2 (Jun 25, 2025) | ||
| - Fix `calcXY` when `isBounded=true` moving items incorrectly. Likely related to #2059. Thanks @wanpan11. [#2102](https://github.com/react-grid-layout/react-grid-layout/pull/2102) | ||
| ## 1.5.1 (Mar 11, 2025) | ||
| - Fix for React 18: wrap state calls in `flushSync`. Thanks @ashharrison90. [#2043](https://github.com/react-grid-layout/react-grid-layout/pull/2043) | ||
| ## 1.5.0 (Oct 9, 2024) | ||
| - Fix `calcXY` moving grid items slightly above and to the left of where they should be. Thanks @MaxMusing. [#2059](https://github.com/react-grid-layout/react-grid-layout/pull/2059) | ||
| - Change `onBreakpointChange`/`onLayoutChange` event order. `onBreakpointChange` now fires first. This should make managing responsive layouts easier, as you can set the current breakpoint in storage, then save the new layout to it. | ||
| ## 1.4.4 (Nov 28, 2023) | ||
| ### Bugfixes | ||
| - Fix position logic when draggable item is dragged into the grid. We no longer use the deprecated / non-standard `e.nativeEvent.layer{X,Y}` properties. [#1915](https://github.com/react-grid-layout/react-grid-layout/pull/1915) | ||
| - Fix drag values according to containerPadding. Previously, when dragging an item, the intuited position within the grid was _not_ modified by `containerPadding`, causing it to off by that value. On most grids, this is only set to `[10, 10]`, so this may not have been noticeable, but for higher values it was very obvious. Thanks @hywlss9. [#1323](https://github.com/react-grid-layout/react-grid-layout/pull/1323) | ||
| - Various lint/dependency fixes. | ||
| ## 1.4.3 (Nov 8, 2023) | ||
| ### Bugfixes | ||
| - Set `activeDrag` in `onDragStart`. Fixes issues where, if no drag is performed, the `onDragStop` handler would error out and the drag would freeze. [#1923](https://github.com/react-grid-layout/react-grid-layout/pull/1923) | ||
| - THis fixes some broader issues with React 18 but testing library support is still not complete. | ||
| ## 1.4.2 (Sep 22, 2023) | ||
| ### Bugfixes | ||
| - Resizing in every directionnow obeys preventCollision restrictions [#1937](https://github.com/react-grid-layout/react-grid-layout/pull/1937) | ||
| ## 1.4.1 (Sep 12, 2023) | ||
| ### Bugfixes | ||
| - Fixed bug where height/width could not be resized if `h = 0` or `w = 0` and 0 `containerPadding`. [#1931](https://github.com/react-grid-layout/react-grid-layout/pull/1931) | ||
| - Revert `fast-equals` to @4. Fixes incompatibility with `Create-React-App@5`. | ||
| ## 1.4.0 (Sep 11, 2023) | ||
| Hey, it's been a long time! Taking a year and a half off is a pretty "open-source" thing to do, thanks for bearing with me. | ||
| ### New Features | ||
| - **Grid items can now be resized left and up!** Thanks to @ludovic and @dseif for all the hard work they did on this. [#1917](https://github.com/react-grid-layout/react-grid-layout/pull/1917) | ||
| - To use, specify `resizeHandles` directions on your `<GridItem>`s. See [the example](/test/examples/20-resizable-handles.jsx) for more on how to do this. | ||
| - See also [the demo](https://react-grid-layout.github.io/react-grid-layout/examples/20-resizable-handles.html). | ||
| - `<WidthProvider>` now uses a `ResizeObserver` instead of hooking into the window's `'resize'` event. [#1839](https://github.com/react-grid-layout/react-grid-layout/pull/1839) | ||
| - This should not be breaking for any users but introduces a new dependency, [resize-observer-polyfill](https://www.npmjs.com/package/resize-observer-polyfill). It will not be imported unless you use `<WidthProvider>`. | ||
| ### Bugfixes | ||
| - Fixed `horizontal` compact not always moving grid elements as far left as possible. [#1822](https://github.com/react-grid-layout/react-grid-layout/pull/1822) | ||
| - Fixed a bug when `allowOverlap={true}` and `compactType={null}`, where collisions would still be processed. [#1782](https://github.com/react-grid-layout/react-grid-layout/pull/1782) | ||
| - Fixed `onResizeStop` and `onDragStop` callbacks not returning updated layout. [#1613](https://github.com/react-grid-layout/react-grid-layout/pull/1613) | ||
| - An item will now rerender when `data-grid` props change. [#718](https://github.com/react-grid-layout/react-grid-layout/issues/718) | ||
| - Corrected draggableHandle configuration in static elements example [#1826](https://github.com/react-grid-layout/react-grid-layout/pull/1826) | ||
| ### Internal Changes | ||
| - Various dependency upgrades and upgraded tests. | ||
| - Removed long-deprecated `_grid` property. | ||
| - Various doc updates. | ||
| ## 1.3.4 (Feb 21, 2022) | ||
| ### Bugfixes | ||
| - Add `e.stopPropagation()` on drag events to better support nested grids. Thanks @rogerfar [#1494](https://github.com/react-grid-layout/react-grid-layout/pull/1494). | ||
| ### Internal Changes | ||
| - Various dependency upgrades. | ||
| ## 1.3.3 (Jan 24, 2022) | ||
| This was a quick release to improve package size and dependency use. Thanks @salvoravida [#1655](https://github.com/react-grid-layout/react-grid-layout/pull/1655) | ||
| ### Bugfixes | ||
| - Removed `coverage/` folder from npm package to save size | ||
| - Moved eslint parser to `devDependencies` | ||
| ## 1.3.2 (Jan 24, 2022) | ||
| ### Internal Changes | ||
| - Package size reduced by ~30% by removing source in `dist/` source maps. | ||
| - Various tests added (thanks @imagineLife!) | ||
| - New GitHub Actions flow for PRs | ||
| ## 1.3.1 (Nov 29, 2021) | ||
| ### Bugfixes | ||
| - Fix `allowOverlap` not firing `onLayoutChange()`. [#1620](https://github.com/react-grid-layout/react-grid-layout/pull/1620) | ||
| - This was due to a short-circuiting of internal logic that did not properly clone the `layout` prop. | ||
| ### Internal Changes | ||
| - Replace `classnames` with `clsx` for smaller package size. (#1543) | ||
| ## 1.3.0 (Aug 27, 2021) | ||
| ### New Features | ||
| - `allowOverlap` prop, when `true`, allows overlapping grid items. [#1470](https://github.com/react-grid-layout/react-grid-layout/pull/1470) | ||
| - Add `onDropDragOver` callback. [#1395](https://github.com/react-grid-layout/react-grid-layout/pull/1395) | ||
| - Use this callback to dynamically adjust the `droppingItem` based on what is being dragged over. Return `w` and `h` to adjust the item. It is then [spread into the dropping placeholder](https://github.com/react-grid-layout/react-grid-layout/pull/1395/files#diff-83ab569936bfd4bf0460a4f23653ecbe8bc88509062c95e75c9402218b2b8733R609). | ||
| - This callback has the type: | ||
| - `onDragOver: (e: DragOverEvent) => { w: number, h: number } | false;` | ||
| - Return `false` to short-circuit the dragover. | ||
| ### Bugfixes | ||
| - Remove sorting when `compactType` is `null`. [#1474](https://github.com/react-grid-layout/react-grid-layout/pull/1474) | ||
| - Droppable fixes for Chrome behavior. [#1442](https://github.com/react-grid-layout/react-grid-layout/issues/1442) [#1448](https://github.com/react-grid-layout/react-grid-layout/issues/1442) | ||
| - Allow `null` children as a convenience so that inline expressions don't break the library. [#1296](https://github.com/react-grid-layout/react-grid-layout/pull/1296) | ||
| - Various dependency upgrades. | ||
| ### Documentation | ||
| - Add docs on using custom components as grid children. | ||
| - Note required class on resizable handles for proper styling. | ||
| ## 1.2.5 (May 10, 2021) | ||
| ### Bugfixes | ||
| - Ensure no negative positions are possible when compacting | ||
| - Thanks @DonnyLi [#829](https://github.com/react-grid-layout/react-grid-layout/pull/829) | ||
| - Fixes [#535](https://github.com/react-grid-layout/react-grid-layout/issues/535) | ||
| - Fix resizing on mobile. This was caused by the `ref` refactor to remove ReactDOM in 1.2.3. | ||
| - Fixes #[1458](https://github.com/react-grid-layout/react-grid-layout/issues/1458) | ||
| - Note: this upgrades `react-resizable` to `3.0.1`, which like our other deps, is only compatible with `React@>=16.3`. | ||
| ### Documentation | ||
| - Document new arity of `resizeHandle` (`(axis: ResizeHandleAxis, ref: ReactRef<HTMLElement>) => React$Element`) | ||
| - Remove references to the deprecated `verticalCompact` prop | ||
| ## 1.2.4 (Mar 18, 2021) | ||
| _This version fixes a serious render bug in `<WidthProvider>`. 1.2.3 should not be used._ | ||
| ### Bugfixes | ||
| - Fix failure to mount when layout is WidthProvider-wrapped and `measureBeforeMount` is `true`. | ||
| - Ref: [#1428](https://github.com/react-grid-layout/react-grid-layout/issues/1428) | ||
| - `<WidthProvider>` no longer updates grid with if it has been set to 0. This prevents unnecessary updates | ||
| if the grid is set to `display: none;`. Thanks @405go [#1427](https://github.com/react-grid-layout/react-grid-layout/pull/1427) | ||
| ## 1.2.3 (Mar 16, 2021) | ||
| ### New Features | ||
| - React-Grid-Layout is now fully compatible with `<React.StrictMode>`. | ||
| - Usage of `ReactDOM` has been removed by using `React.createRef()` inside RGL, and the new [`nodeRef` prop](https://github.com/react-grid-layout/react-draggable/blob/master/CHANGELOG.md#440-may-12-2020) in `react-draggable`. | ||
| ## 1.2.2 (Mar 1, 2021) | ||
| ### Bugfixes | ||
| - `onResize` as changed in 1.2.1 did not correctly save the layout. This is now fixed. | ||
| - As you might guess, we need more test coverage! PRs are very welcome, I'll buy you beers on Cashapp or Patreon or whatever you like. | ||
| ## 1.2.1 (Mar 1, 2021) | ||
| ## Organization Changes | ||
| We have created the [React-Grid-Layout Organization](https://github.com/react-grid-layout)! Therefore the repository | ||
| [has moved](https://github.com/react-grid-layout/react-grid-layout). | ||
| This organization will grow as time goes on, and also contains the dependencies of RGL. | ||
| ### Bugfixes | ||
| - Use `classList` in Firefox onDragOver hack. [#1310](https://github.com/STRML/react-grid-layout/pull/1310) | ||
| - Fix `scale` property. As `scale` support was added to dependencies, this caused double-compensation for scale, causing the dragged element not to follow the cursor. [#1393](https://github.com/STRML/react-grid-layout/pull/1393) | ||
| - Fix horizontal compact mode issue where it inadventently would compact the bottom of the grid. This is not useful nor intended. Thanks @s4m3. [#1390](https://github.com/STRML/react-grid-layout/pull/1390) | ||
| - Fix `onLayoutChange` sometimes not triggering on resize. We weren't cloning the layout item before modifying it. Thanks @xcqwan. [#1289](https://github.com/react-grid-layout/react-grid-layout/pull/1289) | ||
| ### Internal Refactors | ||
| - Updated to the latest versions of all dependencies (enzyme, webpack, jest, flow). | ||
| - Held back React@17 as enzyme is [not yet ready](https://github.com/enzymejs/enzyme/issues/2429). | ||
| ## 1.2.0 (Nov 17, 2020) | ||
| ### New Features | ||
| - You can now customize your resizable handle component as supported by [`react-resizable`](https://github.com/STRML/react-resizable/blob/09fd865c0e1cc570caa8d67e44a2e56172d3d816/examples/ExampleLayout.js#L72). For example: | ||
| ```js | ||
| <ReactGridLayout | ||
| resizeHandle={<span className="custom-handle custom-handle-se" />} | ||
| {...props} | ||
| /> | ||
| ``` | ||
| Thanks @typeetfunc [#1303](https://github.com/STRML/react-grid-layout/pull/1303) | ||
| ### Bugfixes | ||
| - Fix `onDrop` handler not firing on Firefox if you drop over the placeholder. | ||
| - Thanks @Charles-Lamoureux [#1333](https://github.com/STRML/react-grid-layout/pull/1333) | ||
| - Various example style fixes [#1283](https://github.com/STRML/react-grid-layout/pull/1283) [#1299](https://github.com/STRML/react-grid-layout/pull/1299) | ||
| ## 1.1.1 (Sep 10, 2020) | ||
| Republish to add `dist/` folder for unpkg use. | ||
| ## 1.1.0 (Sep 3, 2020) | ||
| ### New Features | ||
| - You can now place resizable handles on all corners. Use the `resizeHandles` prop, which is default `['se']` (for 'southeast'). | ||
| - Allowable values are: | ||
| - 's' - South handle (bottom-center) | ||
| - 'w' - West handle (left-center) | ||
| - 'e' - East handle (right-center) | ||
| - 'n' - North handle (top-center) | ||
| - 'sw' - Southwest handle (bottom-left) | ||
| - 'nw' - Northwest handle (top-left) | ||
| - 'se' - Southeast handle (bottom-right) | ||
| - 'ne' - Northeast handle (top-right) | ||
| - These values may be combined, e.g. `['s', 'se', 'e']`, to place three handles on the bottom side, bottom-right corner, and right side. | ||
| ### Bugfixes | ||
| - Revert `containerPadding` change in #1138. This change was meant to be types-only, but it caused a behavioral change where the default value of `containerPadding` became `[0, 0]`, not `margin`, which is default `[10, 10]`. | ||
| - Add a few more files to `npmignore` to improve package size. | ||
| ## 1.0.0 (July 20, 2020) | ||
| React-Grid-Layout has been in `0.x` status for far too long. With the addition of some new features in this version and a breaking change, I thought it was time to move to a stable semver. | ||
| ### Breaking Changes | ||
| - `onDrop` callback now has a form more consistent with other callbacks. | ||
| - Previous type: `(elemParams: { x: number, y: number, w: number, h: number, e: Event }) => void` | ||
| - New type: `(layout: Layout, item: ?LayoutItem, e: Event) => void` | ||
| - Thanks @ceberhar [#1169](https://github.com/STRML/react-grid-layout/pull/1169) | ||
| - Dropping Node 8 compatibility and testing due to devDep incompatibilities | ||
| ### New Features | ||
| - Add `innerRef: React.Ref<'div'>` prop to expose a ref for the grid layout's outer div. Thanks @paul-sachs [#1176](https://github.com/STRML/react-grid-layout/pull/1176) | ||
| - Add `isBounded` property to prevent dragging items outside of the grid. Thanks @artembykov [#1248](https://github.com/STRML/react-grid-layout/pull/1248) | ||
| ### Bugfixes | ||
| - Fix grid items stuck using percentages on first render. Thanks @rhbg [#1246](https://github.com/STRML/react-grid-layout/pull/1246) | ||
| ## 0.18.3 (Mar 16, 2020) | ||
| ### Bugfixes | ||
| - Fix `shouldComponentUpdate` interfering with droppability ([#1152](https://github.com/STRML/react-grid-layout/issues/1152)) | ||
| ### Internal Changes | ||
| - New Enzyme test suite added to prevent regression. If you have time, we could really use more test cases that reflect your use cases! | ||
| ## 0.18.2 (Feb 26, 2020) | ||
| ### Bugfixes | ||
| - `shouldComponentUpdate`: | ||
| - A too-aggressive implementation of `shouldComponentUpdate` was shipped in 0.18.0-0.18.1 ([#1123](https://github.com/STRML/react-grid-layout/pull/1123)), which did not compare the `children` object. While this works well in many simple implementations of RGL, it breaks in more complex applications. | ||
| - Reference equality of `props.children` and `nextProps.children` is now added to `<ReactGridLayout>` and `<GridItem>`. If you wish to take advantage of the performance improvements from the `shouldComponentUpdate` work, memoize your children. | ||
| - A section has been added to the [README](/README.md#Performance) explaining how this works. | ||
| - Fixed [#1150](https://github.com/STRML/react-grid-layout/issues/1150), [#1151](https://github.com/STRML/react-grid-layout/issues/1151). | ||
| ## 0.18.1 (Feb 25, 2020) | ||
| This release contains typedef changes only. | ||
| ### Bugfixes | ||
| - Flow types: | ||
| - Make Props to `<ReactGridLayout>` and `<ResponsiveReactGridLayout>` exact. | ||
| - Fix loss of props refinement when passing through `WidthProvider`. | ||
| - Fix Flow errors as surfaced in [#1138](https://github.com/STRML/react-grid-layout/pull/1138). | ||
| - Modify examples to use types so that the above type error can't resurface | ||
| ## 0.18.0 (Feb 25, 2020) | ||
| Thanks to all of our maintainers for this big release. 0.18.0 contains a large number of bugfixes that users have been asking for. Please read the full list so you know what to expect. Some of the biggest improvements include fixing changes of `isResizable`/`isDraggable` without a remount ([#892](https://github.com/STRML/react-grid-layout/pull/892)), fixes to prop changes on `ResponsiveReactGridLayout` ([#1090](https://github.com/STRML/react-grid-layout/pull/1090)), `shouldComponentUpdate` improvements for speed ([#1123](https://github.com/STRML/react-grid-layout/pull/1123)), improvements to droppability ([#1127](https://github.com/STRML/react-grid-layout/pull/1127)), and much more. | ||
| ### (Potentially) Breaking Changes | ||
| - You can now locally set `isDraggable`/`isResizable` on a `static` item and it will have that property. This could be useful, but be sure to check your layouts if you use `static`. Relates to [#1060](https://github.com/STRML/react-grid-layout/pull/1060). | ||
| - `shouldComponentUpdate` is now implemented on major components to improve render speed while you manipulate the layout. In our testing there are no issues. If you encounter one, please open an issue asap and we'll get it fixed. See [#1123](https://github.com/STRML/react-grid-layout/pull/1123). | ||
| ### New Features | ||
| - You can now manipulate `isDraggable`/`isResizable` without the child component remounting. We do this by always rendering the child `<Resizable>` and `<Draggable>` wrappers, optionally in a `disabled` state. This feature has been heavily requested. [#892](https://github.com/STRML/react-grid-layout/pull/892) | ||
| - The event is now passed as `e` on the `onDrop` callback. [#1065](https://github.com/STRML/react-grid-layout/pull/1065) | ||
| - Pass `transformScale` to `Resizable`. [#1075](https://github.com/STRML/react-grid-layout/pull/1075) | ||
| ### Bugfixes | ||
| - Fix handling of width changes in `ResponsiveReactGridLayout`. [#1090](https://github.com/STRML/react-grid-layout/pull/1090) | ||
| - Fixes ignored changes of breakpoints and columns. See also [issue #1083](https://github.com/STRML/react-grid-layout/issues/1083). | ||
| - Forbid layout change on click without drag. [#1044](https://github.com/STRML/react-grid-layout/pull/1044) | ||
| - Do not mutate `layouts` prop. [#1064](https://github.com/STRML/react-grid-layout/pull/1064) | ||
| - Ensure locally set `isDraggable`/`isResizable` on a `GridItem` overrides the global setting on the layout. [#1060](https://github.com/STRML/react-grid-layout/pull/1060) | ||
| - Avoid additional element jumping when an item is dropped. [#1127](https://github.com/STRML/react-grid-layout/issues/1127) | ||
| - Don't use `String#includes` for Firefox test. [#1096](https://github.com/STRML/react-grid-layout/pull/1096) | ||
| ### Internal Refactors | ||
| - Added `shouldComponentUpdate` to major elements for speed. Significant [performance improvements](https://github.com/STRML/react-grid-layout/pull/1032#issuecomment-541604763) while dragging. Started in [#1032](https://github.com/STRML/react-grid-layout/pull/1032) and finished in [#1123](https://github.com/STRML/react-grid-layout/pull/1123). | ||
| - A [fun trick for the curious](https://github.com/STRML/react-grid-layout/blob/44e200067b3640c3230f5511e8624a7c629d2f9a/lib/fastRGLPropsEqual.js). | ||
| - Internal refactor of dropping capability. It is now more predictable and uses similar unit labels (`left`, `top`) to other features. [#1128](https://github.com/STRML/react-grid-layout/issues/1128) | ||
| - Upgrade devDependencies. | ||
| - Remove ESPower from test suite (not useful with Jest). | ||
| 0.17.1 (Oct 29, 2019) | ||
| --- | ||
| ### Bugfixes | ||
| - Surround `navigator` check in `try/catch` to avoid problems with mocked navigators [#1057](https://github.com/STRML/react-grid-layout/pull/1054) | ||
| - TransformScale is not applied properly while dragging an element [#1046](https://github.com/STRML/react-grid-layout/pull/1054) | ||
| 0.17.0 (Oct 24, 2019) | ||
| --- | ||
| It's been 18 months since the last release, and this is a pretty large one! For references on the items below, see https://github.com/STRML/react-grid-layout/milestone/1?closed=1. | ||
| Thanks to @daynin and @n1ghtmare for taking an active role in maintaining RGL, and for giving it a much-needed shot in the arm, and thanks to the rest of our contributors. | ||
| ### New Features | ||
| - Added ability to drag items into the grid from outside. [#980](https://github.com/STRML/react-grid-layout/pull/980). See [the example](https://react-grid-layout.github.io/react-grid-layout/examples/15-drag-from-outside.html). | ||
| - This is especially exciting as it opens up new "widget toolbox" use cases such as [Example 14](https://react-grid-layout.github.io/react-grid-layout/examples/14-toolbox.html) with more intuitive interaction. Thanks @daynin. | ||
| - `transformScale` prop [#987](https://github.com/STRML/react-grid-layout/pull/987) | ||
| - `<ResponsiveReactGridLayout>` now supports margin-per-breakpoint [#1016](https://github.com/STRML/react-grid-layout/pull/1016) | ||
| ### Bugfixes | ||
| - `onWidthChange` only called on breakpoint changes [#770](https://github.com/STRML/react-grid-layout/pull/770) | ||
| - Various movement bugs when compaction is off [#766](https://github.com/STRML/react-grid-layout/pull/766) | ||
| - Don't fire `onDragStop` if an item is only clicked, not dragged [#1023](https://github.com/STRML/react-grid-layout/pull/1023) | ||
| - Fix infinite loop when dragging over a static element. [#1019](https://github.com/STRML/react-grid-layout/pull/1019) | ||
| ### Internal Refactors | ||
| - Both `react-draggable` and `react-resizable` dependencies are now React 16.9 compatible, as is now `react-grid-layout`. | ||
| - [RGL PR #990](https://github.com/STRML/react-grid-layout/pull/990) | ||
| - [react-resizable](https://github.com/STRML/react-resizable/pull/112/commits/541dee69b8e45d91a533855609472b481634edee) | ||
| - [react-draggable](https://github.com/mzabriskie/react-draggable/commit/fea778c8e89db2a4e1a35e563b65634f8146e7e4) | ||
| - Webpack 4 [#907](https://github.com/STRML/react-grid-layout/pull/907) | ||
| - Babel 7 [#1013](https://github.com/STRML/react-grid-layout/pull/1013) | ||
| - Flow 0.110 [#995](https://github.com/STRML/react-grid-layout/pull/995) | ||
| - Jest [#774](https://github.com/STRML/react-grid-layout/pull/774) | ||
| - Various build simplifications [#773](https://github.com/STRML/react-grid-layout/pull/773) | ||
| - Various PR bots - thanks @daynin | ||
| 0.16.6 (Mar 8, 2018) | ||
| --- | ||
| - Fixed collision issue where items below could rearrange on a move. | ||
| - The root cause was "teleportation", or practically the same bug that leads to Pac-Man going through | ||
| ghosts now and then. If a large element moves up by a few grid units, the space it vacates can suddenly | ||
| become occupiable by an element below it. Rather than the collision happening properly, they exchange spaces | ||
| atomically. The fix is to move items down one grid unit at a time to ensure | ||
| this rearrangement does not happen. | ||
| - Thanks @torkelo for your hard work on this for Grafana 5, which I very unfortunately managed to break | ||
| when refactoring for 0.16.1. | ||
| - Ref: #650, #739 | ||
| - Added a "Toolbox" demo (thanks @jhob) | ||
| 0.16.5 (Feb 26, 2018) | ||
| --- | ||
| - Minor fix to `isUserAction` on certain types of compaction cascades (#714, #720, #729) | ||
| 0.16.4 (Feb 15, 2018) | ||
| --- | ||
| - Skip null items in processGridItem (#578) | ||
| - Resize is broken for grids with preventCollision: true, fixes #655 (#656) | ||
| - Minor refactoring | ||
| 0.16.3 (Jan 31, 2018) | ||
| --- | ||
| - Fix overriding of `onStart` behaviour (#707, thanks @ersel) | ||
| - Fixed Flow type of WidthProvider | ||
| - Devdep updates | ||
| 0.16.2 (Dec 17, 2017) | ||
| --- | ||
| - Fix `onLayoutChange` not firing properly due to regression introduced in 0.16.1 | ||
| - Ref: https://github.com/STRML/react-grid-layout/issues/683 | ||
| - Simpler resize corner CSS (thanks @TrySound) | ||
| - Reformat code with Prettier & simplify lint configs (thanks @TrySound) | ||
| 0.16.1 (Dec 10, 2017) | ||
| --- | ||
| - Flow def upgrades (thanks @TrySound) | ||
| - DevDep upgrades | ||
| - Fixed WebpackBin demo | ||
| - Addl test cases (thanks @torkelo) | ||
| 0.16.0 (Oct 6, 2017) | ||
| --- | ||
| - Added horizontal compaction option, `compactType` (thanks @Rhjulskov) | ||
| - Added `preventCollision` option for static grids (thanks @EmrysMyrddin) | ||
| 0.15.2 (Sep 5, 2017) | ||
| --- | ||
| - Fix missed `import *` | ||
| - Dependency updates | ||
| 0.15.1 (Sep 5, 2017) | ||
| --- | ||
| - Fix React PropTypes & createClass warnings | ||
| - See https://github.com/facebook/react/issues/10583 | ||
| 0.15.0 (Aug 21, 2017) | ||
| --- | ||
| - Package upgrades, including Webpack 3 | ||
| - Flow typedef upgrades for the 0.53 rework | ||
| - Add faulty key value in duplicate key error message (#602) | ||
| 0.14.7 (Jul 14, 2017) | ||
| --- | ||
| - Fixed a dragging bug when the grid container is scrollable. Thanks @chultquist. | ||
| - Ref: https://github.com/STRML/react-grid-layout/pull/555 | ||
| 0.14.6 (Apr 19, 2017) | ||
| --- | ||
| - Fixed a bad publish (connectivity issue). | ||
| 0.14.5 (Apr 19, 2017) | ||
| --- | ||
| - Moved to `prop-types` package to avoid React.PropTypes deprecation in 15.5. Thanks @inverts! | ||
| 0.14.4 (Mar 9, 2017) | ||
| --- | ||
| #### Fixes: | ||
| - Typecheck in `WidthProvider` to satisfy Flow (and technically, this could be a Text node) | ||
| ##### Dev: | ||
| - Update Flow | ||
| 0.14.3 (Feb 22, 2017) | ||
| --- | ||
| #### Fixes: | ||
| - Reverted #499; `msTransform` is indeed correct. See [discussion](https://github.com/STRML/react-grid-layout/pull/499#issuecomment-281703069). | ||
| 0.14.2 (Feb 22, 2017) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed use of `MSTranform` for IE. Thanks @dvoaviarison (#499) | ||
| - Fix generation of source maps, which was temporarily broken by the webpack 2 upgrade. | ||
| #### Internal: | ||
| - Update development dependencies and babel version. | ||
| 0.14.1 (Feb 20, 2017) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed a minor Flow type issue when a `classnames` typedef is present. | ||
| - Fixed a scoping issue when running `make build-example`. | ||
| 0.14.0 (Feb 13, 2017) | ||
| --- | ||
| #### Features: | ||
| - New test suite - thanks @nikolas | ||
| - Dev Dependency updates | ||
| - Committed yarn.lock | ||
| - Added `react-draggable` classname to draggable grid items. | ||
| 0.13.9 (Oct 13, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed sorting of layout items, which could be different in IE if two items have the same x & y coordinate. | ||
| - See [#369](https://github.com/STRML/react-grid-layout/issues/369). | ||
| 0.13.8 (Oct 13, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed breakage introduced in `0.13.7` when items are added without a layout or `data-grid` property. | ||
| - See [#368](https://github.com/STRML/react-grid-layout/issues/368). | ||
| 0.13.7 (Oct 3, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed an error during layout sync if children was a keyed fragment or had nested arrays. | ||
| - Fixed `onLayoutChange` being called when layout didn't change. | ||
| - Fixed some issues with input layout items being modified in-place rather than cloned. | ||
| - Minor typos. | ||
| 0.13.6 (Sep 26, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed missing HTMLElement in `onResize*` callbacks. | ||
| 0.13.5 (Sep 9, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed a few Flow typing errors in `WidthProvider`. | ||
| 0.13.4 (Sep 9, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed potential call to `ReactDOM.findDOMNode(this)` after unmount of `WidthProvider`. | ||
| - Fixed an issue where layout items using `data-grid` could rearrange on mount depending on how they were ordered. | ||
| - See [#342](https://github.com/STRML/react-grid-layout/pull/342) for reference. | ||
| 0.13.3 (Aug 31, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fixed `lodash.isequal` import, which was ruined by case-insensitive HFS+ _shakes fist_ | ||
| 0.13.2 (Aug 31, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Diffing children in order to regenerate the layout now diffs the `key` props and their order. | ||
| - This will catch more changes, such as sorting, addition, and removal. | ||
| - Only pass `className` and `style` to WidthProvider. Other props were not intended to be supported. | ||
| - I'm aware this could be a breaking change if you were relying on this bad behavior. If so, please | ||
| use your own `WidthProvider`-style HOC. | ||
| - `babel-plugin-transform-flow-comments` had limited support for defining types like transpiled classes. | ||
| - This has been updated to instead copy source to `.js.flow` files, which preserves all type information. | ||
| 0.13.1 (Aug 16, 2016) | ||
| --- | ||
| #### Fixes: | ||
| - Fix remaining `propTypes` warnings. | ||
| 0.13.0 (Aug 3, 2016) | ||
| --- | ||
| #### Changed: | ||
| - Due to a change in React 15.2, passing the `_grid` property on DOM children generates an error. | ||
| To compensate, we now error on the same and suggest using `data-grid` instead. Simply change any use of | ||
| `_grid` to `data-grid`, or add your properties to the layout. | ||
| #### Fixes: | ||
| - Fix React 15.3 warning re: propTypes. | ||
| 0.12.7 (Jun 29, 2016) | ||
| --- | ||
| - Prevent extraenous rerenders in `<ResponsiveReactGridLayout>` by using deep equality on layouts. | ||
| 0.12.6 (Jun 5, 2016) | ||
| --- | ||
| - Fix blindingly obvious bug where mounted isn't set to true. Smack forehead. | ||
| 0.12.5 (Jun 3, 2016) | ||
| --- | ||
| - Fixes for server rendering checksum failures. | ||
| 0.12.4 (May 22, 2016) | ||
| --- | ||
| - Update to React-Draggable v2. Fixes: #241, #239, #24 | ||
| - v2 contains a number of bugfixes & enhancements for touchscreens, multitouch, and scrolling containers. | ||
| 0.12.3 (May 3, 2016) | ||
| --- | ||
| - Bugfix: Rendering with new `breakpoints`/`cols` does not refresh the layout. | ||
| Fixes #208 - thanks @damienleroux | ||
| 0.12.2 (May 1, 2016) | ||
| --- | ||
| - Bugfix: Fix warning about undefined `useCSSTransforms` when server-rendering. | ||
| 0.12.1 (Apr 19, 2016) | ||
| --- | ||
| - Bugfix: Don't set `layout` twice on width change. See #217 - thanks @damienleroux | ||
| - Enhancement: Add Flow type comments | ||
| 0.12.0 (Apr 14, 2016) | ||
| --- | ||
| - `<ReactGridLayout>` will no longer animate so severely on mount. See #212. | ||
| - If you are using `<WidthProvider>`, you may notice that the container's width still shunts on mount. | ||
| If you like, you may delay mounting by setting `measureBeforeMount={true}` on the wrapped element. This | ||
| will eliminate the mounting animation completely. | ||
| - If you enjoyed the old animation, set `useCSSTransforms={this.state.mounted}` and toggle the mounting | ||
| flag. See `0-showcase.jsx` for an example. | ||
| - Set more permissive version ranges for `<Draggable>` and `<Resizable>` dependencies, as they are now stable | ||
| and will only introduce breaking changes on major version ticks. | ||
| 0.11.3 (Apr 8, 2016) | ||
| --- | ||
| - Officially support React v15. | ||
| 0.11.2 (Apr 6, 2016) | ||
| --- | ||
| - Bugfix: Draggable cancel selectors, see #203 - thanks @RiiD | ||
| - README fixes, thanks @bravo-kernel & @ro-savage | ||
| 0.11.1 | ||
| --- | ||
| - Bugfix: `<ResponsiveReactGridLayout>` was using stale data when synchronizing children with the layout | ||
| on a breakpoint change. | ||
| 0.11.0 | ||
| --- | ||
| This release contains potentially breaking changes so I have updated the minor version (as per semver). | ||
| **Breaking Changes**: | ||
| - Layout items now have a fixed set of properties. Other properties will _not_ be merged into the `<GridItem>`, such | ||
| as `className`. To set a `className` on a child, set it on the child directly and it will be merged. | ||
| This allows us to make better assumptions about the layout and use a faster cloning mechanism. | ||
| - Setting individual `handle` and `cancel` selectors per item is no longer supported. If you need this, please | ||
| open a ticket and let me know your use case. | ||
| Other changes: | ||
| - Bugfix: `<ResponsiveReactGridLayout>` `onLayoutChange` callback data could still be stale. | ||
| - Bugfix: Range error when building layout solely from `_grid` properties. | ||
| - This broke a lot of usage and thus `0.10.11` and `0.10.10` have been unpublished. | ||
| - Removed redundant `isPlaceholder` property from `<GridItem>`. | ||
| - README updates to clarify layout/\_grid usage. | ||
| 0.10.11 | ||
| --- | ||
| - Bugfix: `layouts` param on `<ResponsiveReactGridLayout>`'s `onLayoutChange` could have stale data | ||
| for the current breakpoint. | ||
| 0.10.10 | ||
| --- | ||
| - Performance: Prevent V8 deopt in a few methods and add fast layout item cloning. | ||
| 0.10.9 | ||
| --- | ||
| - Bugfix: Typo in children comparison in CWRP. See #169. | ||
| - Bugfix: Missing babel-preset-es2015 in dev. | ||
| 0.10.8 | ||
| --- | ||
| - Rebuild using [ES2015 Loose Mode](https://babeljs.algolia.com/docs/advanced/loose/). | ||
| 0.10.7 | ||
| --- | ||
| - Bugfix: `className` and `style` props on grid children were being incorrectly dropped, a holdover | ||
| from when `cloneWithProps()` used to do this merging for us. They are now merged. | ||
| 0.10.6 | ||
| --- | ||
| - Bugfix: If both `props.layout` and `props.children.length` change in the same tick, | ||
| props.layout would be clobbered. See #162 | ||
| 0.10.5 | ||
| --- | ||
| - Bugfix/Enhancement: Margins were causing subtle error in some of the positioning calculations. This has | ||
| been fixed. | ||
| 0.10.4 | ||
| --- | ||
| - Bugfix: Container height was calculated as less than expected due to improper addition of margin. | ||
| 0.10.3 | ||
| --- | ||
| - Bugfix: Round item positions even if they're currently resizing or dragging (#158, regression of #141) | ||
| - Bugfix: Fix a positioning bug when margins are 0 (#160) | ||
| 0.10.2 | ||
| --- | ||
| - Bugfix: <RGL> would synchronize children with layout if the layout in props didn't match the state; | ||
| this was meant to be a hook for the developer to supply a new layout. The incorrect check could cause the | ||
| layout to reset if the parent rerendered. The check is now between the layout in nextProps and props. | ||
| - Bugfix: Fixed a lot of resizing layout bugs; most of the fixes are in react-resizable. | ||
| - Bugfix: Fixed incorrect typecheck on LayoutItem.i. | ||
| - Bugfix: Make onLayoutChange fire appropriately (#155). | ||
| - Bugfix: Fix `<ResponsiveGridLayout>` not properly reverting when sizing the page up (#154). | ||
| - Remove unused `offsetX` and `offsetY` from layouts. | ||
| - Dependency updates. | ||
| 0.10.1 | ||
| --- | ||
| - Hotfix for default export incompatibility caused by Babel 6. | ||
| 0.10.0 | ||
| --- | ||
| This long-awaited release provides React 0.14 compatibility and a rewrite of the underlying | ||
| `<Draggable>` functionality. | ||
| **Breaking changes:** | ||
| - `ListensToWidth` replaced with `WidthProvider` which must wrap | ||
| `<ResponsiveReactGridLayout>` and `<ReactGridLayout>` to provide width data. See doc for example. | ||
| - Prop `initialWidth` renamed to `width`. | ||
| - Grid Layout keys must be type of string now. | ||
| Other changes: | ||
| - _Finally_ compatible with React 0.14! Big thanks to @menelike for his help. | ||
| - Upgraded to Babel 6. | ||
| - Full typechecking via Flow. | ||
| - Lots of misc bugfixes. | ||
| - See beta releases below for more details. | ||
| 0.10.0-beta1 | ||
| --- | ||
| - Fixed a React import bug on ListensToWidth.jsx (#130; thanks @mrblueblue) | ||
| 0.10.0-beta0 | ||
| --- | ||
| _This release is unstable!_ | ||
| - React 0.14 compatibility. | ||
| - This release includes a rewrite of much of the project in ES6/7 style with Flow typing. | ||
| - This release brings us onto mainline (1.x) react-draggable and react-resizable, eliminating | ||
| the previous github dependency. | ||
| - 0.10.0 is not yet complete. Use this release at your own risk. | ||
| Known bugs: | ||
| - The placeholder box does not properly follow the mouse and stays pinned to the active drag. | ||
| ## 0.9.2 | ||
| - Update `react-draggable` to `v0.8.0` to fix IE11 issues (#29). | ||
| 0.9.1 | ||
| --- | ||
| - Update `react-draggable` to `v0.7.3` to fix a bounds bug (#56). | ||
| 0.9.0 | ||
| --- | ||
| - Move off `react-draggable` fork to mainline `v0.7.2`. Incremented minor (major in the case of | ||
| npm's `^`, since we are pre-v1) version in case of unforeseen conflicts. | ||
| 0.8.3 | ||
| --- | ||
| - Add `verticalCompact` toggle. | ||
| 0.8.2 | ||
| --- | ||
| - Fix a crash when initializing with no children. | ||
| 0.8.1 | ||
| --- | ||
| - Fixed React 0.13 warning about `isMounted()`. | ||
| - Update to babel 5. | ||
| - Added browser build for use with a `<script>` tag or in RequireJS builds. | ||
| - Pinned react-draggable version in anticipation of React 0.13 update. | ||
| 0.8.0 | ||
| --- | ||
| - Changed signature on resize/drag callbacks to allow dynamic max/min W/H per item. | ||
| - Fixed bug in `useCSSTransforms`. | ||
| - Documentation and example fixes. | ||
| 0.7.1 | ||
| --- | ||
| - Added callbacks for resize and drag start/active/stop. | ||
| 0.7.0 | ||
| --- | ||
| **Breaking changes:** | ||
| - `ReactGridLayout.props.handle` renamed to `ReactGridLayout.props.draggableHandle`. | ||
| > This version contains a CSS update. This fixes a visual bug where you may see items quickly reset position | ||
| > and animate back to their original position on load, when you are using CSS transforms. To fix this bug, | ||
| > copy the rules from css/styles.css into your stylesheet. | ||
| Other changes: | ||
| - Fixed #19 (bad new item placement with css transforms). | ||
| - Fixed some placement inconsistencies while RGL is mounting, with css transforms and percentages. | ||
| - Fixed a duplicate className bug. | ||
| 0.6.2 | ||
| --- | ||
| - Fix #21 (error when passing only a single child). | ||
| - Add GridItem.props.cancel. | ||
| - Use React addons directly to save file size. | ||
| - Allow setting draggable/resizable per grid item, as well as existing `static` property. | ||
| - Use object.assign to set `_grid` properties so we can more easily merge PRs in the future. | ||
| 0.6.1 | ||
| --- | ||
| - Fixed #8 (current layout was not properly being stored when provided via \_grid props). | ||
| 0.6.0 | ||
| --- | ||
| - Optionally use CSS transforms for placement, fallback on position top/left. | ||
| - Allow parent to set responsive breakpoint directly. | ||
| 0.5.2 | ||
| --- | ||
| - Fix Responsive import for node users | ||
| 0.5.1 | ||
| --- | ||
| - Add support for min/max dimension attributes. | ||
| - Example tweak | ||
| 0.5.0 | ||
| --- | ||
| - Refactoring and demo tweaks. Update README with new params. | ||
| - Add showcase example, tweak template | ||
| - Refactor: Responsive Grid Layout is a separate element | ||
| - Auto-generate examples from template rather than edit them individually. | ||
| 0.4.0 | ||
| --- | ||
| - Force lodash into commons chunk | ||
| - More tweaks to grid collisions. This should fix bad swaps once and for all. | ||
| - Set unused:"vars" in lint. | ||
| - Add responsive localstorage example and `initialLayouts` support. | ||
| - Fix localstorage example comment. | ||
| - Rework responsive layouts, identify child elements by key rather than index. Added 2 new examples. | ||
| - Fixup GridItem resizing feel a bit. | ||
| ## < 0.4.0 | ||
| - Early development versions, too many changes to list. |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
-47
| /********* Sample code generated by the curl command line tool ********** | ||
| * All curl_easy_setopt() options are documented at: | ||
| * https://curl.se/libcurl/c/curl_easy_setopt.html | ||
| ************************************************************************/ | ||
| #include <curl/curl.h> | ||
| int main(int argc, char *argv[]) | ||
| { | ||
| CURLcode ret; | ||
| CURL *hnd; | ||
| hnd = curl_easy_init(); | ||
| curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); | ||
| curl_easy_setopt(hnd, CURLOPT_URL, "https://ifconfig.me"); | ||
| curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L); | ||
| curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/8.4.0"); | ||
| curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); | ||
| curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); | ||
| curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
| curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
| /* Here is a list of options the curl code used that cannot get generated | ||
| as source easily. You may choose to either not use them or implement | ||
| them yourself. | ||
| CURLOPT_WRITEDATA was set to an object pointer | ||
| CURLOPT_INTERLEAVEDATA was set to an object pointer | ||
| CURLOPT_WRITEFUNCTION was set to a function pointer | ||
| CURLOPT_READDATA was set to an object pointer | ||
| CURLOPT_READFUNCTION was set to a function pointer | ||
| CURLOPT_SEEKDATA was set to an object pointer | ||
| CURLOPT_SEEKFUNCTION was set to a function pointer | ||
| CURLOPT_ERRORBUFFER was set to an object pointer | ||
| CURLOPT_STDERR was set to an object pointer | ||
| CURLOPT_HEADERFUNCTION was set to a function pointer | ||
| CURLOPT_HEADERDATA was set to an object pointer | ||
| */ | ||
| ret = curl_easy_perform(hnd); | ||
| curl_easy_cleanup(hnd); | ||
| hnd = NULL; | ||
| return (int)ret; | ||
| } | ||
| /**** End of sample code ****/ |
| // @flow | ||
| 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 | ||
| export 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]) | ||
| export 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. | ||
| */ | ||
| export 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. | ||
| */ | ||
| export 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. | ||
| */ | ||
| export 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 | ||
| export function clamp( | ||
| num: number, | ||
| lowerBound: number, | ||
| upperBound: number | ||
| ): number { | ||
| return Math.max(Math.min(num, upperBound), lowerBound); | ||
| } |
| // @flow | ||
| import * as React from "react"; | ||
| import PropTypes from "prop-types"; | ||
| import ResizeObserver from "resize-observer-polyfill"; | ||
| import clsx from "clsx"; | ||
| import type { ReactRef } from "../ReactGridLayoutPropTypes"; | ||
| type WPDefaultProps = {| | ||
| measureBeforeMount: boolean | ||
| |}; | ||
| // eslint-disable-next-line no-unused-vars | ||
| type WPProps = {| | ||
| className?: string, | ||
| style?: Object, | ||
| ...WPDefaultProps | ||
| |}; | ||
| type WPState = {| | ||
| width: number | ||
| |}; | ||
| type ComposedProps<Config> = {| | ||
| ...Config, | ||
| measureBeforeMount?: boolean, | ||
| className?: string, | ||
| style?: Object, | ||
| width?: number | ||
| |}; | ||
| const layoutClassName = "react-grid-layout"; | ||
| /* | ||
| * A simple HOC that provides facility for listening to container resizes. | ||
| * | ||
| * The Flow type is pretty janky here. I can't just spread `WPProps` into this returned object - I wish I could - but it triggers | ||
| * a flow bug of some sort that causes it to stop typechecking. | ||
| */ | ||
| export default function WidthProvideRGL<Config>( | ||
| ComposedComponent: React.AbstractComponent<Config> | ||
| ): React.AbstractComponent<ComposedProps<Config>> { | ||
| return class WidthProvider extends React.Component< | ||
| ComposedProps<Config>, | ||
| WPState | ||
| > { | ||
| static defaultProps: WPDefaultProps = { | ||
| measureBeforeMount: false | ||
| }; | ||
| static propTypes = { | ||
| // If true, will not render children until mounted. Useful for getting the exact width before | ||
| // rendering, to prevent any unsightly resizing. | ||
| measureBeforeMount: PropTypes.bool | ||
| }; | ||
| state: WPState = { | ||
| width: 1280 | ||
| }; | ||
| elementRef: ReactRef<HTMLDivElement> = React.createRef(); | ||
| mounted: boolean = false; | ||
| resizeObserver: ResizeObserver; | ||
| componentDidMount() { | ||
| this.mounted = true; | ||
| this.resizeObserver = new ResizeObserver(entries => { | ||
| const node = this.elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| const width = entries[0].contentRect.width; | ||
| this.setState({ width }); | ||
| } | ||
| }); | ||
| const node = this.elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| this.resizeObserver.observe(node); | ||
| } | ||
| } | ||
| componentWillUnmount() { | ||
| this.mounted = false; | ||
| const node = this.elementRef.current; | ||
| if (node instanceof HTMLElement) { | ||
| this.resizeObserver.unobserve(node); | ||
| } | ||
| this.resizeObserver.disconnect(); | ||
| } | ||
| render() { | ||
| const { measureBeforeMount, ...rest } = this.props; | ||
| if (measureBeforeMount && !this.mounted) { | ||
| return ( | ||
| <div | ||
| className={clsx(this.props.className, layoutClassName)} | ||
| style={this.props.style} | ||
| // $FlowIgnore ref types | ||
| ref={this.elementRef} | ||
| /> | ||
| ); | ||
| } | ||
| return ( | ||
| <ComposedComponent | ||
| innerRef={this.elementRef} | ||
| {...rest} | ||
| {...this.state} | ||
| /> | ||
| ); | ||
| } | ||
| }; | ||
| } |
| // @preval | ||
| require("@babel/register"); | ||
| // Fast way to compare RGL props in shouldComponentUpdate. | ||
| // Generates the fastest possible comparison of the type: | ||
| // function (a, b) { return a.className === b.className && a.style === b.style && ... } | ||
| // This avoids enumerating keys, avoids us keeping our own key list, and can be very easily optimized. | ||
| const PropTypes = require("prop-types"); | ||
| const propTypes = require("./ReactGridLayoutPropTypes").default; | ||
| const keys = Object.keys(propTypes); | ||
| // Remove 'children' key as we don't want to compare it | ||
| keys.splice(keys.indexOf("children"), 1); | ||
| // Returns a code string indicating what to do here. | ||
| // In most cases we want to do a simple equality comparison, | ||
| // but we have some arrays and tuples and objects we want | ||
| // to do a shallow comparison on. | ||
| function getEqualType(key) { | ||
| if ( | ||
| [ | ||
| PropTypes.number, | ||
| PropTypes.bool, | ||
| PropTypes.string, | ||
| PropTypes.func | ||
| ].includes(propTypes[key]) | ||
| ) { | ||
| return `(a.${key} === b.${key})`; | ||
| } | ||
| return `isEqualImpl(a.${key}, b.${key})`; | ||
| } | ||
| // Exports a function that compares a and b. `isEqualImpl` is a required | ||
| // third prop, as we can't otherwise access it. | ||
| module.exports = () => | ||
| eval(` | ||
| function fastRGLPropsEqual(a, b, isEqualImpl) { | ||
| if (a === b) return true; | ||
| return ( | ||
| ${keys.map(getEqualType).join(" && ")} | ||
| ); | ||
| } | ||
| fastRGLPropsEqual; | ||
| `); |
-689
| // @flow | ||
| import React from "react"; | ||
| import { flushSync } from "react-dom"; | ||
| import PropTypes from "prop-types"; | ||
| import { DraggableCore } from "react-draggable"; | ||
| import { Resizable } from "react-resizable"; | ||
| import { | ||
| fastPositionEqual, | ||
| perc, | ||
| resizeItemInDirection, | ||
| setTopLeft, | ||
| setTransform | ||
| } from "./utils"; | ||
| import { | ||
| calcGridItemPosition, | ||
| calcGridItemWHPx, | ||
| calcGridColWidth, | ||
| calcXY, | ||
| calcWH, | ||
| clamp | ||
| } from "./calculateUtils"; | ||
| import { | ||
| resizeHandleAxesType, | ||
| resizeHandleType | ||
| } from "./ReactGridLayoutPropTypes"; | ||
| import clsx from "clsx"; | ||
| import type { Element as ReactElement, Node as ReactNode } from "react"; | ||
| import type { | ||
| ReactDraggableCallbackData, | ||
| GridDragEvent, | ||
| GridResizeEvent, | ||
| DroppingPosition, | ||
| Position, | ||
| ResizeHandleAxis | ||
| } from "./utils"; | ||
| import type { PositionParams } from "./calculateUtils"; | ||
| import type { ResizeHandle, ReactRef } from "./ReactGridLayoutPropTypes"; | ||
| type PartialPosition = { top: number, left: number }; | ||
| type GridItemCallback<Data: GridDragEvent | GridResizeEvent> = ( | ||
| i: string, | ||
| w: number, | ||
| h: number, | ||
| Data | ||
| ) => void; | ||
| type ResizeCallbackData = { | ||
| node: HTMLElement, | ||
| size: Position, | ||
| handle: ResizeHandleAxis | ||
| }; | ||
| type GridItemResizeCallback = ( | ||
| e: Event, | ||
| data: ResizeCallbackData, | ||
| position: Position | ||
| ) => void; | ||
| type State = { | ||
| resizing: ?{ top: number, left: number, width: number, height: number }, | ||
| dragging: ?{ top: number, left: number }, | ||
| className: string | ||
| }; | ||
| type Props = { | ||
| children: ReactElement<any>, | ||
| cols: number, | ||
| containerWidth: number, | ||
| margin: [number, number], | ||
| containerPadding: [number, number], | ||
| rowHeight: number, | ||
| maxRows: number, | ||
| isDraggable: boolean, | ||
| isResizable: boolean, | ||
| isBounded: boolean, | ||
| static?: boolean, | ||
| useCSSTransforms?: boolean, | ||
| usePercentages?: boolean, | ||
| transformScale: number, | ||
| droppingPosition?: DroppingPosition, | ||
| className: string, | ||
| style?: Object, | ||
| // Draggability | ||
| cancel: string, | ||
| handle: string, | ||
| x: number, | ||
| y: number, | ||
| w: number, | ||
| h: number, | ||
| minW: number, | ||
| maxW: number, | ||
| minH: number, | ||
| maxH: number, | ||
| i: string, | ||
| resizeHandles?: ResizeHandleAxis[], | ||
| resizeHandle?: ResizeHandle, | ||
| onDrag?: GridItemCallback<GridDragEvent>, | ||
| onDragStart?: GridItemCallback<GridDragEvent>, | ||
| onDragStop?: GridItemCallback<GridDragEvent>, | ||
| onResize?: GridItemCallback<GridResizeEvent>, | ||
| onResizeStart?: GridItemCallback<GridResizeEvent>, | ||
| onResizeStop?: GridItemCallback<GridResizeEvent> | ||
| }; | ||
| type DefaultProps = { | ||
| className: string, | ||
| cancel: string, | ||
| handle: string, | ||
| minH: number, | ||
| minW: number, | ||
| maxH: number, | ||
| maxW: number, | ||
| transformScale: number | ||
| }; | ||
| /** | ||
| * An individual item within a ReactGridLayout. | ||
| */ | ||
| export default class GridItem extends React.Component<Props, State> { | ||
| static propTypes = { | ||
| // Children must be only a single element | ||
| children: PropTypes.element, | ||
| // General grid attributes | ||
| cols: PropTypes.number.isRequired, | ||
| containerWidth: PropTypes.number.isRequired, | ||
| rowHeight: PropTypes.number.isRequired, | ||
| margin: PropTypes.array.isRequired, | ||
| maxRows: PropTypes.number.isRequired, | ||
| containerPadding: PropTypes.array.isRequired, | ||
| // These are all in grid units | ||
| x: PropTypes.number.isRequired, | ||
| y: PropTypes.number.isRequired, | ||
| w: PropTypes.number.isRequired, | ||
| h: PropTypes.number.isRequired, | ||
| // All optional | ||
| minW: function (props: Props, propName: string) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("minWidth not Number"); | ||
| if (value > props.w || value > props.maxW) | ||
| return new Error("minWidth larger than item width/maxWidth"); | ||
| }, | ||
| maxW: function (props: Props, propName: string) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("maxWidth not Number"); | ||
| if (value < props.w || value < props.minW) | ||
| return new Error("maxWidth smaller than item width/minWidth"); | ||
| }, | ||
| minH: function (props: Props, propName: string) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("minHeight not Number"); | ||
| if (value > props.h || value > props.maxH) | ||
| return new Error("minHeight larger than item height/maxHeight"); | ||
| }, | ||
| maxH: function (props: Props, propName: string) { | ||
| const value = props[propName]; | ||
| if (typeof value !== "number") return new Error("maxHeight not Number"); | ||
| if (value < props.h || value < props.minH) | ||
| return new Error("maxHeight smaller than item height/minHeight"); | ||
| }, | ||
| // ID is nice to have for callbacks | ||
| i: PropTypes.string.isRequired, | ||
| // Resize handle options | ||
| resizeHandles: resizeHandleAxesType, | ||
| resizeHandle: resizeHandleType, | ||
| // Functions | ||
| onDragStop: PropTypes.func, | ||
| onDragStart: PropTypes.func, | ||
| onDrag: PropTypes.func, | ||
| onResizeStop: PropTypes.func, | ||
| onResizeStart: PropTypes.func, | ||
| onResize: PropTypes.func, | ||
| // Flags | ||
| isDraggable: PropTypes.bool.isRequired, | ||
| isResizable: PropTypes.bool.isRequired, | ||
| isBounded: PropTypes.bool.isRequired, | ||
| static: PropTypes.bool, | ||
| // Use CSS transforms instead of top/left | ||
| useCSSTransforms: PropTypes.bool.isRequired, | ||
| transformScale: PropTypes.number, | ||
| // Others | ||
| className: PropTypes.string, | ||
| // Selector for draggable handle | ||
| handle: PropTypes.string, | ||
| // Selector for draggable cancel (see react-draggable) | ||
| cancel: PropTypes.string, | ||
| // Current position of a dropping element | ||
| droppingPosition: PropTypes.shape({ | ||
| e: PropTypes.object.isRequired, | ||
| left: PropTypes.number.isRequired, | ||
| top: PropTypes.number.isRequired | ||
| }) | ||
| }; | ||
| static defaultProps: DefaultProps = { | ||
| className: "", | ||
| cancel: "", | ||
| handle: "", | ||
| minH: 1, | ||
| minW: 1, | ||
| maxH: Infinity, | ||
| maxW: Infinity, | ||
| transformScale: 1 | ||
| }; | ||
| state: State = { | ||
| resizing: null, | ||
| dragging: null, | ||
| className: "" | ||
| }; | ||
| elementRef: ReactRef<HTMLDivElement> = React.createRef(); | ||
| shouldComponentUpdate(nextProps: Props, nextState: State): boolean { | ||
| // We can't deeply compare children. If the developer memoizes them, we can | ||
| // use this optimization. | ||
| if (this.props.children !== nextProps.children) return true; | ||
| if (this.props.droppingPosition !== nextProps.droppingPosition) return true; | ||
| // TODO memoize these calculations so they don't take so long? | ||
| const oldPosition = calcGridItemPosition( | ||
| this.getPositionParams(this.props), | ||
| this.props.x, | ||
| this.props.y, | ||
| this.props.w, | ||
| this.props.h, | ||
| this.state | ||
| ); | ||
| const newPosition = calcGridItemPosition( | ||
| this.getPositionParams(nextProps), | ||
| nextProps.x, | ||
| nextProps.y, | ||
| nextProps.w, | ||
| nextProps.h, | ||
| nextState | ||
| ); | ||
| return ( | ||
| !fastPositionEqual(oldPosition, newPosition) || | ||
| this.props.useCSSTransforms !== nextProps.useCSSTransforms | ||
| ); | ||
| } | ||
| componentDidMount() { | ||
| this.moveDroppingItem({}); | ||
| } | ||
| componentDidUpdate(prevProps: Props) { | ||
| this.moveDroppingItem(prevProps); | ||
| } | ||
| // When a droppingPosition is present, this means we should fire a move event, as if we had moved | ||
| // this element by `x, y` pixels. | ||
| moveDroppingItem(prevProps: Props) { | ||
| const { droppingPosition } = this.props; | ||
| if (!droppingPosition) return; | ||
| const node = this.elementRef.current; | ||
| // Can't find DOM node (are we unmounted?) | ||
| if (!node) return; | ||
| const prevDroppingPosition = prevProps.droppingPosition || { | ||
| left: 0, | ||
| top: 0 | ||
| }; | ||
| const { dragging } = this.state; | ||
| const shouldDrag = | ||
| (dragging && droppingPosition.left !== prevDroppingPosition.left) || | ||
| droppingPosition.top !== prevDroppingPosition.top; | ||
| if (!dragging) { | ||
| this.onDragStart(droppingPosition.e, { | ||
| node, | ||
| deltaX: droppingPosition.left, | ||
| deltaY: droppingPosition.top | ||
| }); | ||
| } else if (shouldDrag) { | ||
| const deltaX = droppingPosition.left - dragging.left; | ||
| const deltaY = droppingPosition.top - dragging.top; | ||
| this.onDrag( | ||
| droppingPosition.e, | ||
| { | ||
| node, | ||
| deltaX, | ||
| deltaY | ||
| }, | ||
| true // dontFLush: avoid flushSync to temper warnings | ||
| ); | ||
| } | ||
| } | ||
| getPositionParams(props: Props = this.props): PositionParams { | ||
| return { | ||
| cols: props.cols, | ||
| containerPadding: props.containerPadding, | ||
| containerWidth: props.containerWidth, | ||
| margin: props.margin, | ||
| maxRows: props.maxRows, | ||
| rowHeight: props.rowHeight | ||
| }; | ||
| } | ||
| /** | ||
| * This is where we set the grid item's absolute placement. It gets a little tricky because we want to do it | ||
| * well when server rendering, and the only way to do that properly is to use percentage width/left because | ||
| * we don't know exactly what the browser viewport is. | ||
| * Unfortunately, CSS Transforms, which are great for performance, break in this instance because a percentage | ||
| * left is relative to the item itself, not its container! So we cannot use them on the server rendering pass. | ||
| * | ||
| * @param {Object} pos Position object with width, height, left, top. | ||
| * @return {Object} Style object. | ||
| */ | ||
| createStyle(pos: Position): { [key: string]: ?string } { | ||
| const { usePercentages, containerWidth, useCSSTransforms } = this.props; | ||
| let style; | ||
| // CSS Transforms support (default) | ||
| if (useCSSTransforms) { | ||
| style = setTransform(pos); | ||
| } else { | ||
| // top,left (slow) | ||
| style = setTopLeft(pos); | ||
| // This is used for server rendering. | ||
| if (usePercentages) { | ||
| style.left = perc(pos.left / containerWidth); | ||
| style.width = perc(pos.width / containerWidth); | ||
| } | ||
| } | ||
| return style; | ||
| } | ||
| /** | ||
| * Mix a Draggable instance into a child. | ||
| * @param {Element} child Child element. | ||
| * @return {Element} Child wrapped in Draggable. | ||
| */ | ||
| mixinDraggable( | ||
| child: ReactElement<any>, | ||
| isDraggable: boolean | ||
| ): ReactElement<any> { | ||
| return ( | ||
| <DraggableCore | ||
| disabled={!isDraggable} | ||
| onStart={this.onDragStart} | ||
| onDrag={this.onDrag} | ||
| onStop={this.onDragStop} | ||
| handle={this.props.handle} | ||
| cancel={ | ||
| ".react-resizable-handle" + | ||
| (this.props.cancel ? "," + this.props.cancel : "") | ||
| } | ||
| scale={this.props.transformScale} | ||
| nodeRef={this.elementRef} | ||
| > | ||
| {child} | ||
| </DraggableCore> | ||
| ); | ||
| } | ||
| /** | ||
| * Utility function to setup callback handler definitions for | ||
| * similarily structured resize events. | ||
| */ | ||
| curryResizeHandler(position: Position, handler: Function): Function { | ||
| return (e: Event, data: ResizeCallbackData): Function => | ||
| handler(e, data, position); | ||
| } | ||
| /** | ||
| * Mix a Resizable instance into a child. | ||
| * @param {Element} child Child element. | ||
| * @param {Object} position Position object (pixel values) | ||
| * @return {Element} Child wrapped in Resizable. | ||
| */ | ||
| mixinResizable( | ||
| child: ReactElement<any>, | ||
| position: Position, | ||
| isResizable: boolean | ||
| ): ReactElement<any> { | ||
| const { | ||
| cols, | ||
| minW, | ||
| minH, | ||
| maxW, | ||
| maxH, | ||
| transformScale, | ||
| resizeHandles, | ||
| resizeHandle | ||
| } = this.props; | ||
| const positionParams = this.getPositionParams(); | ||
| // This is the max possible width - doesn't go to infinity because of the width of the window | ||
| const maxWidth = calcGridItemPosition(positionParams, 0, 0, cols, 0).width; | ||
| // Calculate min/max constraints using our min & maxes | ||
| const mins = calcGridItemPosition(positionParams, 0, 0, minW, minH); | ||
| const maxes = calcGridItemPosition(positionParams, 0, 0, maxW, maxH); | ||
| const minConstraints = [mins.width, mins.height]; | ||
| const maxConstraints = [ | ||
| Math.min(maxes.width, maxWidth), | ||
| Math.min(maxes.height, Infinity) | ||
| ]; | ||
| return ( | ||
| <Resizable | ||
| // These are opts for the resize handle itself | ||
| draggableOpts={{ | ||
| disabled: !isResizable | ||
| }} | ||
| className={isResizable ? undefined : "react-resizable-hide"} | ||
| width={position.width} | ||
| height={position.height} | ||
| minConstraints={minConstraints} | ||
| maxConstraints={maxConstraints} | ||
| onResizeStop={this.curryResizeHandler(position, this.onResizeStop)} | ||
| onResizeStart={this.curryResizeHandler(position, this.onResizeStart)} | ||
| onResize={this.curryResizeHandler(position, this.onResize)} | ||
| transformScale={transformScale} | ||
| resizeHandles={resizeHandles} | ||
| handle={resizeHandle} | ||
| > | ||
| {child} | ||
| </Resizable> | ||
| ); | ||
| } | ||
| /** | ||
| * onDragStart event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node, delta and position information | ||
| */ | ||
| onDragStart: (Event, ReactDraggableCallbackData) => void = (e, { node }) => { | ||
| const { onDragStart, transformScale } = this.props; | ||
| if (!onDragStart) return; | ||
| const newPosition: PartialPosition = { top: 0, left: 0 }; | ||
| // TODO: this wont work on nested parents | ||
| const { offsetParent } = node; | ||
| if (!offsetParent) return; | ||
| const parentRect = offsetParent.getBoundingClientRect(); | ||
| const clientRect = node.getBoundingClientRect(); | ||
| const cLeft = clientRect.left / transformScale; | ||
| const pLeft = parentRect.left / transformScale; | ||
| const cTop = clientRect.top / transformScale; | ||
| const pTop = parentRect.top / transformScale; | ||
| newPosition.left = cLeft - pLeft + offsetParent.scrollLeft; | ||
| newPosition.top = cTop - pTop + offsetParent.scrollTop; | ||
| this.setState({ dragging: newPosition }); | ||
| // Call callback with this data | ||
| const { x, y } = calcXY( | ||
| this.getPositionParams(), | ||
| newPosition.top, | ||
| newPosition.left, | ||
| this.props.w, | ||
| this.props.h | ||
| ); | ||
| return onDragStart.call(this, this.props.i, x, y, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }; | ||
| /** | ||
| * onDrag event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node, delta and position information | ||
| * @param {boolean} dontFlush if true, will not call flushSync | ||
| */ | ||
| onDrag: (Event, ReactDraggableCallbackData, boolean) => void = ( | ||
| e, | ||
| { node, deltaX, deltaY }, | ||
| dontFlush | ||
| ) => { | ||
| const { onDrag } = this.props; | ||
| if (!onDrag) return; | ||
| if (!this.state.dragging) { | ||
| throw new Error("onDrag called before onDragStart."); | ||
| } | ||
| let top = this.state.dragging.top + deltaY; | ||
| let left = this.state.dragging.left + deltaX; | ||
| const { isBounded, i, w, h, containerWidth } = this.props; | ||
| const positionParams = this.getPositionParams(); | ||
| // Boundary calculations; keeps items within the grid | ||
| if (isBounded) { | ||
| const { offsetParent } = node; | ||
| if (offsetParent) { | ||
| const { margin, rowHeight } = this.props; | ||
| const bottomBoundary = | ||
| offsetParent.clientHeight - calcGridItemWHPx(h, rowHeight, margin[1]); | ||
| top = clamp(top, 0, bottomBoundary); | ||
| const colWidth = calcGridColWidth(positionParams); | ||
| const rightBoundary = | ||
| containerWidth - calcGridItemWHPx(w, colWidth, margin[0]); | ||
| left = clamp(left, 0, rightBoundary); | ||
| } | ||
| } | ||
| const newPosition: PartialPosition = { top, left }; | ||
| // dontFlush is set if we're calling from inside | ||
| if (dontFlush) { | ||
| this.setState({ dragging: newPosition }); | ||
| } else { | ||
| flushSync(() => { | ||
| this.setState({ dragging: newPosition }); | ||
| }); | ||
| } | ||
| // Call callback with this data | ||
| const { x, y } = calcXY(positionParams, top, left, w, h); | ||
| return onDrag.call(this, i, x, y, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }; | ||
| /** | ||
| * onDragStop event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node, delta and position information | ||
| */ | ||
| onDragStop: (Event, ReactDraggableCallbackData) => void = (e, { node }) => { | ||
| const { onDragStop } = this.props; | ||
| if (!onDragStop) return; | ||
| if (!this.state.dragging) { | ||
| throw new Error("onDragEnd called before onDragStart."); | ||
| } | ||
| const { w, h, i } = this.props; | ||
| const { left, top } = this.state.dragging; | ||
| const newPosition: PartialPosition = { top, left }; | ||
| this.setState({ dragging: null }); | ||
| const { x, y } = calcXY(this.getPositionParams(), top, left, w, h); | ||
| return onDragStop.call(this, i, x, y, { | ||
| e, | ||
| node, | ||
| newPosition | ||
| }); | ||
| }; | ||
| /** | ||
| * onResizeStop event handler | ||
| * @param {Event} e event data | ||
| * @param {Object} callbackData an object with node and size information | ||
| */ | ||
| onResizeStop: GridItemResizeCallback = (e, callbackData, position) => | ||
| this.onResizeHandler(e, callbackData, position, "onResizeStop"); | ||
| // onResizeStart event handler | ||
| onResizeStart: GridItemResizeCallback = (e, callbackData, position) => | ||
| this.onResizeHandler(e, callbackData, position, "onResizeStart"); | ||
| // onResize event handler | ||
| onResize: GridItemResizeCallback = (e, callbackData, position) => | ||
| this.onResizeHandler(e, callbackData, position, "onResize"); | ||
| /** | ||
| * Wrapper around resize events to provide more useful data. | ||
| */ | ||
| onResizeHandler( | ||
| e: Event, | ||
| { node, size, handle }: ResizeCallbackData, // 'size' is updated position | ||
| position: Position, // existing position | ||
| handlerName: string | ||
| ): void { | ||
| const handler = this.props[handlerName]; | ||
| if (!handler) return; | ||
| const { x, y, i, maxH, minH, containerWidth } = this.props; | ||
| const { minW, maxW } = this.props; | ||
| // Clamping of dimensions based on resize direction | ||
| let updatedSize = size; | ||
| if (node) { | ||
| updatedSize = resizeItemInDirection( | ||
| handle, | ||
| position, | ||
| size, | ||
| containerWidth | ||
| ); | ||
| flushSync(() => { | ||
| this.setState({ | ||
| resizing: handlerName === "onResizeStop" ? null : updatedSize | ||
| }); | ||
| }); | ||
| } | ||
| // Get new XY based on pixel size | ||
| let { w, h } = calcWH( | ||
| this.getPositionParams(), | ||
| updatedSize.width, | ||
| updatedSize.height, | ||
| x, | ||
| y, | ||
| handle | ||
| ); | ||
| // Min/max capping. | ||
| // minW should be at least 1 (TODO propTypes validation?) | ||
| w = clamp(w, Math.max(minW, 1), maxW); | ||
| h = clamp(h, minH, maxH); | ||
| handler.call(this, i, w, h, { e, node, size: updatedSize, handle }); | ||
| } | ||
| render(): ReactNode { | ||
| const { | ||
| x, | ||
| y, | ||
| w, | ||
| h, | ||
| isDraggable, | ||
| isResizable, | ||
| droppingPosition, | ||
| useCSSTransforms | ||
| } = this.props; | ||
| const pos = calcGridItemPosition( | ||
| this.getPositionParams(), | ||
| x, | ||
| y, | ||
| w, | ||
| h, | ||
| this.state | ||
| ); | ||
| const child = React.Children.only(this.props.children); | ||
| // Create the child element. We clone the existing element but modify its className and style. | ||
| let newChild = React.cloneElement(child, { | ||
| ref: this.elementRef, | ||
| className: clsx( | ||
| "react-grid-item", | ||
| child.props.className, | ||
| this.props.className, | ||
| { | ||
| static: this.props.static, | ||
| resizing: Boolean(this.state.resizing), | ||
| "react-draggable": isDraggable, | ||
| "react-draggable-dragging": Boolean(this.state.dragging), | ||
| dropping: Boolean(droppingPosition), | ||
| cssTransforms: useCSSTransforms | ||
| } | ||
| ), | ||
| // We can set the width and height on the child, but unfortunately we can't set the position. | ||
| style: { | ||
| ...this.props.style, | ||
| ...child.props.style, | ||
| ...this.createStyle(pos) | ||
| } | ||
| }); | ||
| // Resizable support. This is usually on but the user can toggle it off. | ||
| newChild = this.mixinResizable(newChild, pos, isResizable); | ||
| // Draggable support. This is always on, except for with placeholders. | ||
| newChild = this.mixinDraggable(newChild, isDraggable); | ||
| return newChild; | ||
| } | ||
| } |
| // @flow | ||
| import * as React from "react"; | ||
| import { deepEqual } from "fast-equals"; | ||
| import clsx from "clsx"; | ||
| import { | ||
| bottom, | ||
| childrenEqual, | ||
| cloneLayoutItem, | ||
| compact, | ||
| compactType, | ||
| fastRGLPropsEqual, | ||
| getAllCollisions, | ||
| getLayoutItem, | ||
| moveElement, | ||
| noop, | ||
| synchronizeLayoutWithChildren, | ||
| withLayoutItem | ||
| } from "./utils"; | ||
| import { calcXY } from "./calculateUtils"; | ||
| import GridItem from "./GridItem"; | ||
| import ReactGridLayoutPropTypes from "./ReactGridLayoutPropTypes"; | ||
| import type { | ||
| ChildrenArray as ReactChildrenArray, | ||
| Element as ReactElement | ||
| } from "react"; | ||
| // Types | ||
| import type { | ||
| CompactType, | ||
| GridResizeEvent, | ||
| GridDragEvent, | ||
| DragOverEvent, | ||
| Layout, | ||
| DroppingPosition, | ||
| LayoutItem | ||
| } from "./utils"; | ||
| import type { PositionParams } from "./calculateUtils"; | ||
| type State = { | ||
| activeDrag: ?LayoutItem, | ||
| layout: Layout, | ||
| mounted: boolean, | ||
| oldDragItem: ?LayoutItem, | ||
| oldLayout: ?Layout, | ||
| oldResizeItem: ?LayoutItem, | ||
| resizing: boolean, | ||
| droppingDOMNode: ?ReactElement<any>, | ||
| droppingPosition?: DroppingPosition, | ||
| // Mirrored props | ||
| children: ReactChildrenArray<ReactElement<any>>, | ||
| compactType?: CompactType, | ||
| propsLayout?: Layout | ||
| }; | ||
| import type { Props, DefaultProps } from "./ReactGridLayoutPropTypes"; | ||
| // End Types | ||
| const layoutClassName = "react-grid-layout"; | ||
| let isFirefox = false; | ||
| // Try...catch will protect from navigator not existing (e.g. node) or a bad implementation of navigator | ||
| try { | ||
| isFirefox = /firefox/i.test(navigator.userAgent); | ||
| } catch (e) { | ||
| /* Ignore */ | ||
| } | ||
| /** | ||
| * A reactive, fluid grid layout with draggable, resizable components. | ||
| */ | ||
| export default class ReactGridLayout extends React.Component<Props, State> { | ||
| // TODO publish internal ReactClass displayName transform | ||
| static displayName: ?string = "ReactGridLayout"; | ||
| // Refactored to another module to make way for preval | ||
| static propTypes = ReactGridLayoutPropTypes; | ||
| static defaultProps: DefaultProps = { | ||
| autoSize: true, | ||
| cols: 12, | ||
| className: "", | ||
| style: {}, | ||
| draggableHandle: "", | ||
| draggableCancel: "", | ||
| containerPadding: null, | ||
| rowHeight: 150, | ||
| maxRows: Infinity, // infinite vertical growth | ||
| layout: [], | ||
| margin: [10, 10], | ||
| isBounded: false, | ||
| isDraggable: true, | ||
| isResizable: true, | ||
| allowOverlap: false, | ||
| isDroppable: false, | ||
| useCSSTransforms: true, | ||
| transformScale: 1, | ||
| verticalCompact: true, | ||
| compactType: "vertical", | ||
| preventCollision: false, | ||
| droppingItem: { | ||
| i: "__dropping-elem__", | ||
| h: 1, | ||
| w: 1 | ||
| }, | ||
| resizeHandles: ["se"], | ||
| onLayoutChange: noop, | ||
| onDragStart: noop, | ||
| onDrag: noop, | ||
| onDragStop: noop, | ||
| onResizeStart: noop, | ||
| onResize: noop, | ||
| onResizeStop: noop, | ||
| onDrop: noop, | ||
| onDropDragOver: noop | ||
| }; | ||
| state: State = { | ||
| activeDrag: null, | ||
| layout: synchronizeLayoutWithChildren( | ||
| this.props.layout, | ||
| this.props.children, | ||
| this.props.cols, | ||
| // Legacy support for verticalCompact: false | ||
| compactType(this.props), | ||
| this.props.allowOverlap | ||
| ), | ||
| mounted: false, | ||
| oldDragItem: null, | ||
| oldLayout: null, | ||
| oldResizeItem: null, | ||
| resizing: false, | ||
| droppingDOMNode: null, | ||
| children: [] | ||
| }; | ||
| dragEnterCounter: number = 0; | ||
| componentDidMount() { | ||
| this.setState({ mounted: true }); | ||
| // Possibly call back with layout on mount. This should be done after correcting the layout width | ||
| // to ensure we don't rerender with the wrong width. | ||
| this.onLayoutMaybeChanged(this.state.layout, this.props.layout); | ||
| } | ||
| static getDerivedStateFromProps( | ||
| nextProps: Props, | ||
| prevState: State | ||
| ): $Shape<State> | null { | ||
| let newLayoutBase; | ||
| if (prevState.activeDrag) { | ||
| return null; | ||
| } | ||
| // Legacy support for compactType | ||
| // Allow parent to set layout directly. | ||
| if ( | ||
| !deepEqual(nextProps.layout, prevState.propsLayout) || | ||
| nextProps.compactType !== prevState.compactType | ||
| ) { | ||
| newLayoutBase = nextProps.layout; | ||
| } else if (!childrenEqual(nextProps.children, prevState.children)) { | ||
| // If children change, also regenerate the layout. Use our state | ||
| // as the base in case because it may be more up to date than | ||
| // what is in props. | ||
| newLayoutBase = prevState.layout; | ||
| } | ||
| // We need to regenerate the layout. | ||
| if (newLayoutBase) { | ||
| const newLayout = synchronizeLayoutWithChildren( | ||
| newLayoutBase, | ||
| nextProps.children, | ||
| nextProps.cols, | ||
| compactType(nextProps), | ||
| nextProps.allowOverlap | ||
| ); | ||
| return { | ||
| layout: newLayout, | ||
| // We need to save these props to state for using | ||
| // getDerivedStateFromProps instead of componentDidMount (in which we would get extra rerender) | ||
| compactType: nextProps.compactType, | ||
| children: nextProps.children, | ||
| propsLayout: nextProps.layout | ||
| }; | ||
| } | ||
| return null; | ||
| } | ||
| shouldComponentUpdate(nextProps: Props, nextState: State): boolean { | ||
| return ( | ||
| // NOTE: this is almost always unequal. Therefore the only way to get better performance | ||
| // from SCU is if the user intentionally memoizes children. If they do, and they can | ||
| // handle changes properly, performance will increase. | ||
| this.props.children !== nextProps.children || | ||
| !fastRGLPropsEqual(this.props, nextProps, deepEqual) || | ||
| this.state.activeDrag !== nextState.activeDrag || | ||
| this.state.mounted !== nextState.mounted || | ||
| this.state.droppingPosition !== nextState.droppingPosition | ||
| ); | ||
| } | ||
| componentDidUpdate(prevProps: Props, prevState: State) { | ||
| if (!this.state.activeDrag) { | ||
| const newLayout = this.state.layout; | ||
| const oldLayout = prevState.layout; | ||
| this.onLayoutMaybeChanged(newLayout, oldLayout); | ||
| } | ||
| } | ||
| /** | ||
| * Calculates a pixel value for the container. | ||
| * @return {String} Container height in pixels. | ||
| */ | ||
| containerHeight(): ?string { | ||
| if (!this.props.autoSize) return; | ||
| const nbRow = bottom(this.state.layout); | ||
| const containerPaddingY = this.props.containerPadding | ||
| ? this.props.containerPadding[1] | ||
| : this.props.margin[1]; | ||
| return ( | ||
| nbRow * this.props.rowHeight + | ||
| (nbRow - 1) * this.props.margin[1] + | ||
| containerPaddingY * 2 + | ||
| "px" | ||
| ); | ||
| } | ||
| /** | ||
| * When dragging starts | ||
| * @param {String} i Id of the child | ||
| * @param {Number} x X position of the move | ||
| * @param {Number} y Y position of the move | ||
| * @param {Event} e The mousedown event | ||
| * @param {Element} node The current dragging DOM element | ||
| */ | ||
| onDragStart: (i: string, x: number, y: number, GridDragEvent) => void = ( | ||
| i: string, | ||
| x: number, | ||
| y: number, | ||
| { e, node }: GridDragEvent | ||
| ) => { | ||
| const { layout } = this.state; | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| // Create placeholder (display only) | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| placeholder: true, | ||
| i: i | ||
| }; | ||
| this.setState({ | ||
| oldDragItem: cloneLayoutItem(l), | ||
| oldLayout: layout, | ||
| activeDrag: placeholder | ||
| }); | ||
| return this.props.onDragStart(layout, l, l, null, e, node); | ||
| }; | ||
| /** | ||
| * Each drag movement create a new dragelement and move the element to the dragged location | ||
| * @param {String} i Id of the child | ||
| * @param {Number} x X position of the move | ||
| * @param {Number} y Y position of the move | ||
| * @param {Event} e The mousedown event | ||
| * @param {Element} node The current dragging DOM element | ||
| */ | ||
| onDrag: (i: string, x: number, y: number, GridDragEvent) => void = ( | ||
| i, | ||
| x, | ||
| y, | ||
| { e, node } | ||
| ) => { | ||
| const { oldDragItem } = this.state; | ||
| let { layout } = this.state; | ||
| const { cols, allowOverlap, preventCollision } = this.props; | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| // Create placeholder (display only) | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| placeholder: true, | ||
| i: i | ||
| }; | ||
| // Move the element to the dragged location. | ||
| const isUserAction = true; | ||
| layout = moveElement( | ||
| layout, | ||
| l, | ||
| x, | ||
| y, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType(this.props), | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| this.props.onDrag(layout, oldDragItem, l, placeholder, e, node); | ||
| this.setState({ | ||
| layout: allowOverlap | ||
| ? layout | ||
| : compact(layout, compactType(this.props), cols), | ||
| activeDrag: placeholder | ||
| }); | ||
| }; | ||
| /** | ||
| * When dragging stops, figure out which position the element is closest to and update its x and y. | ||
| * @param {String} i Index of the child. | ||
| * @param {Number} x X position of the move | ||
| * @param {Number} y Y position of the move | ||
| * @param {Event} e The mousedown event | ||
| * @param {Element} node The current dragging DOM element | ||
| */ | ||
| onDragStop: (i: string, x: number, y: number, GridDragEvent) => void = ( | ||
| i, | ||
| x, | ||
| y, | ||
| { e, node } | ||
| ) => { | ||
| if (!this.state.activeDrag) return; | ||
| const { oldDragItem } = this.state; | ||
| let { layout } = this.state; | ||
| const { cols, preventCollision, allowOverlap } = this.props; | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| // Move the element here | ||
| const isUserAction = true; | ||
| layout = moveElement( | ||
| layout, | ||
| l, | ||
| x, | ||
| y, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType(this.props), | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| // Set state | ||
| const newLayout = allowOverlap | ||
| ? layout | ||
| : compact(layout, compactType(this.props), cols); | ||
| this.props.onDragStop(newLayout, oldDragItem, l, null, e, node); | ||
| const { oldLayout } = this.state; | ||
| this.setState({ | ||
| activeDrag: null, | ||
| layout: newLayout, | ||
| oldDragItem: null, | ||
| oldLayout: null | ||
| }); | ||
| this.onLayoutMaybeChanged(newLayout, oldLayout); | ||
| }; | ||
| onLayoutMaybeChanged(newLayout: Layout, oldLayout: ?Layout) { | ||
| if (!oldLayout) oldLayout = this.state.layout; | ||
| if (!deepEqual(oldLayout, newLayout)) { | ||
| this.props.onLayoutChange(newLayout); | ||
| } | ||
| } | ||
| onResizeStart: (i: string, w: number, h: number, GridResizeEvent) => void = ( | ||
| i, | ||
| w, | ||
| h, | ||
| { e, node } | ||
| ) => { | ||
| const { layout } = this.state; | ||
| const l = getLayoutItem(layout, i); | ||
| if (!l) return; | ||
| this.setState({ | ||
| oldResizeItem: cloneLayoutItem(l), | ||
| oldLayout: this.state.layout, | ||
| resizing: true | ||
| }); | ||
| this.props.onResizeStart(layout, l, l, null, e, node); | ||
| }; | ||
| onResize: (i: string, w: number, h: number, GridResizeEvent) => void = ( | ||
| i, | ||
| w, | ||
| h, | ||
| { e, node, size, handle } | ||
| ) => { | ||
| const { oldResizeItem } = this.state; | ||
| const { layout } = this.state; | ||
| const { cols, preventCollision, allowOverlap } = this.props; | ||
| let shouldMoveItem = false; | ||
| let finalLayout; | ||
| let x; | ||
| let y; | ||
| const [newLayout, l] = withLayoutItem(layout, i, l => { | ||
| let hasCollisions; | ||
| x = l.x; | ||
| y = l.y; | ||
| if (["sw", "w", "nw", "n", "ne"].indexOf(handle) !== -1) { | ||
| if (["sw", "nw", "w"].indexOf(handle) !== -1) { | ||
| x = l.x + (l.w - w); | ||
| w = l.x !== x && x < 0 ? l.w : w; | ||
| x = x < 0 ? 0 : x; | ||
| } | ||
| if (["ne", "n", "nw"].indexOf(handle) !== -1) { | ||
| y = l.y + (l.h - h); | ||
| h = l.y !== y && y < 0 ? l.h : h; | ||
| y = y < 0 ? 0 : y; | ||
| } | ||
| shouldMoveItem = true; | ||
| } | ||
| // Something like quad tree should be used | ||
| // to find collisions faster | ||
| if (preventCollision && !allowOverlap) { | ||
| const collisions = getAllCollisions(layout, { | ||
| ...l, | ||
| w, | ||
| h, | ||
| x, | ||
| y | ||
| }).filter(layoutItem => layoutItem.i !== l.i); | ||
| hasCollisions = collisions.length > 0; | ||
| // If we're colliding, we need adjust the placeholder. | ||
| if (hasCollisions) { | ||
| // Reset layoutItem dimensions if there were collisions | ||
| y = l.y; | ||
| h = l.h; | ||
| x = l.x; | ||
| w = l.w; | ||
| shouldMoveItem = false; | ||
| } | ||
| } | ||
| l.w = w; | ||
| l.h = h; | ||
| return l; | ||
| }); | ||
| // Shouldn't ever happen, but typechecking makes it necessary | ||
| if (!l) return; | ||
| finalLayout = newLayout; | ||
| if (shouldMoveItem) { | ||
| // Move the element to the new position. | ||
| const isUserAction = true; | ||
| finalLayout = moveElement( | ||
| newLayout, | ||
| l, | ||
| x, | ||
| y, | ||
| isUserAction, | ||
| this.props.preventCollision, | ||
| compactType(this.props), | ||
| cols, | ||
| allowOverlap | ||
| ); | ||
| } | ||
| // Create placeholder element (display only) | ||
| const placeholder = { | ||
| w: l.w, | ||
| h: l.h, | ||
| x: l.x, | ||
| y: l.y, | ||
| static: true, | ||
| i: i | ||
| }; | ||
| this.props.onResize(finalLayout, oldResizeItem, l, placeholder, e, node); | ||
| // Re-compact the newLayout and set the drag placeholder. | ||
| this.setState({ | ||
| layout: allowOverlap | ||
| ? finalLayout | ||
| : compact(finalLayout, compactType(this.props), cols), | ||
| activeDrag: placeholder | ||
| }); | ||
| }; | ||
| onResizeStop: (i: string, w: number, h: number, GridResizeEvent) => void = ( | ||
| i, | ||
| w, | ||
| h, | ||
| { e, node } | ||
| ) => { | ||
| const { layout, oldResizeItem } = this.state; | ||
| const { cols, allowOverlap } = this.props; | ||
| const l = getLayoutItem(layout, i); | ||
| // Set state | ||
| const newLayout = allowOverlap | ||
| ? layout | ||
| : compact(layout, compactType(this.props), cols); | ||
| this.props.onResizeStop(newLayout, oldResizeItem, l, null, e, node); | ||
| const { oldLayout } = this.state; | ||
| this.setState({ | ||
| activeDrag: null, | ||
| layout: newLayout, | ||
| oldResizeItem: null, | ||
| oldLayout: null, | ||
| resizing: false | ||
| }); | ||
| this.onLayoutMaybeChanged(newLayout, oldLayout); | ||
| }; | ||
| /** | ||
| * Create a placeholder object. | ||
| * @return {Element} Placeholder div. | ||
| */ | ||
| placeholder(): ?ReactElement<any> { | ||
| const { activeDrag } = this.state; | ||
| if (!activeDrag) return null; | ||
| const { | ||
| width, | ||
| cols, | ||
| margin, | ||
| containerPadding, | ||
| rowHeight, | ||
| maxRows, | ||
| useCSSTransforms, | ||
| transformScale | ||
| } = this.props; | ||
| // {...this.state.activeDrag} is pretty slow, actually | ||
| return ( | ||
| <GridItem | ||
| w={activeDrag.w} | ||
| h={activeDrag.h} | ||
| x={activeDrag.x} | ||
| y={activeDrag.y} | ||
| i={activeDrag.i} | ||
| className={`react-grid-placeholder ${ | ||
| this.state.resizing ? "placeholder-resizing" : "" | ||
| }`} | ||
| containerWidth={width} | ||
| cols={cols} | ||
| margin={margin} | ||
| containerPadding={containerPadding || margin} | ||
| maxRows={maxRows} | ||
| rowHeight={rowHeight} | ||
| isDraggable={false} | ||
| isResizable={false} | ||
| isBounded={false} | ||
| useCSSTransforms={useCSSTransforms} | ||
| transformScale={transformScale} | ||
| > | ||
| <div /> | ||
| </GridItem> | ||
| ); | ||
| } | ||
| /** | ||
| * Given a grid item, set its style attributes & surround in a <Draggable>. | ||
| * @param {Element} child React element. | ||
| * @return {Element} Element wrapped in draggable and properly placed. | ||
| */ | ||
| processGridItem( | ||
| child: ReactElement<any>, | ||
| isDroppingItem?: boolean | ||
| ): ?ReactElement<any> { | ||
| if (!child || !child.key) return; | ||
| const l = getLayoutItem(this.state.layout, String(child.key)); | ||
| if (!l) return null; | ||
| const { | ||
| width, | ||
| cols, | ||
| margin, | ||
| containerPadding, | ||
| rowHeight, | ||
| maxRows, | ||
| isDraggable, | ||
| isResizable, | ||
| isBounded, | ||
| useCSSTransforms, | ||
| transformScale, | ||
| draggableCancel, | ||
| draggableHandle, | ||
| resizeHandles, | ||
| resizeHandle | ||
| } = this.props; | ||
| const { mounted, droppingPosition } = this.state; | ||
| // Determine user manipulations possible. | ||
| // If an item is static, it can't be manipulated by default. | ||
| // Any properties defined directly on the grid item will take precedence. | ||
| const draggable = | ||
| typeof l.isDraggable === "boolean" | ||
| ? l.isDraggable | ||
| : !l.static && isDraggable; | ||
| const resizable = | ||
| typeof l.isResizable === "boolean" | ||
| ? l.isResizable | ||
| : !l.static && isResizable; | ||
| const resizeHandlesOptions = l.resizeHandles || resizeHandles; | ||
| // isBounded set on child if set on parent, and child is not explicitly false | ||
| const bounded = draggable && isBounded && l.isBounded !== false; | ||
| return ( | ||
| <GridItem | ||
| containerWidth={width} | ||
| cols={cols} | ||
| margin={margin} | ||
| containerPadding={containerPadding || margin} | ||
| maxRows={maxRows} | ||
| rowHeight={rowHeight} | ||
| cancel={draggableCancel} | ||
| handle={draggableHandle} | ||
| onDragStop={this.onDragStop} | ||
| onDragStart={this.onDragStart} | ||
| onDrag={this.onDrag} | ||
| onResizeStart={this.onResizeStart} | ||
| onResize={this.onResize} | ||
| onResizeStop={this.onResizeStop} | ||
| isDraggable={draggable} | ||
| isResizable={resizable} | ||
| isBounded={bounded} | ||
| useCSSTransforms={useCSSTransforms && mounted} | ||
| usePercentages={!mounted} | ||
| transformScale={transformScale} | ||
| w={l.w} | ||
| h={l.h} | ||
| x={l.x} | ||
| y={l.y} | ||
| i={l.i} | ||
| minH={l.minH} | ||
| minW={l.minW} | ||
| maxH={l.maxH} | ||
| maxW={l.maxW} | ||
| static={l.static} | ||
| droppingPosition={isDroppingItem ? droppingPosition : undefined} | ||
| resizeHandles={resizeHandlesOptions} | ||
| resizeHandle={resizeHandle} | ||
| > | ||
| {child} | ||
| </GridItem> | ||
| ); | ||
| } | ||
| // Called while dragging an element. Part of browser native drag/drop API. | ||
| // Native event target might be the layout itself, or an element within the layout. | ||
| onDragOver: DragOverEvent => void | false = e => { | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| // we should ignore events from layout's children in Firefox | ||
| // to avoid unpredictable jumping of a dropping placeholder | ||
| // FIXME remove this hack | ||
| if ( | ||
| isFirefox && | ||
| // $FlowIgnore can't figure this out | ||
| !e.nativeEvent.target?.classList.contains(layoutClassName) | ||
| ) { | ||
| return false; | ||
| } | ||
| const { | ||
| droppingItem, | ||
| onDropDragOver, | ||
| margin, | ||
| cols, | ||
| rowHeight, | ||
| maxRows, | ||
| width, | ||
| containerPadding, | ||
| transformScale | ||
| } = this.props; | ||
| // Allow user to customize the dropping item or short-circuit the drop based on the results | ||
| // of the `onDragOver(e: Event)` callback. | ||
| const onDragOverResult = onDropDragOver?.(e); | ||
| if (onDragOverResult === false) { | ||
| if (this.state.droppingDOMNode) { | ||
| this.removeDroppingPlaceholder(); | ||
| } | ||
| return false; | ||
| } | ||
| const finalDroppingItem = { ...droppingItem, ...onDragOverResult }; | ||
| const { layout } = this.state; | ||
| // $FlowIgnore missing def | ||
| const gridRect = e.currentTarget.getBoundingClientRect(); // The grid's position in the viewport | ||
| // Calculate the mouse position relative to the grid | ||
| const layerX = e.clientX - gridRect.left; | ||
| const layerY = e.clientY - gridRect.top; | ||
| const droppingPosition = { | ||
| left: layerX / transformScale, | ||
| top: layerY / transformScale, | ||
| e | ||
| }; | ||
| if (!this.state.droppingDOMNode) { | ||
| const positionParams: PositionParams = { | ||
| cols, | ||
| margin, | ||
| maxRows, | ||
| rowHeight, | ||
| containerWidth: width, | ||
| containerPadding: containerPadding || margin | ||
| }; | ||
| const calculatedPosition = calcXY( | ||
| positionParams, | ||
| layerY, | ||
| layerX, | ||
| finalDroppingItem.w, | ||
| finalDroppingItem.h | ||
| ); | ||
| this.setState({ | ||
| droppingDOMNode: <div key={finalDroppingItem.i} />, | ||
| droppingPosition, | ||
| layout: [ | ||
| ...layout, | ||
| { | ||
| ...finalDroppingItem, | ||
| x: calculatedPosition.x, | ||
| y: calculatedPosition.y, | ||
| static: false, | ||
| isDraggable: true | ||
| } | ||
| ] | ||
| }); | ||
| } else if (this.state.droppingPosition) { | ||
| const { left, top } = this.state.droppingPosition; | ||
| const shouldUpdatePosition = left != layerX || top != layerY; | ||
| if (shouldUpdatePosition) { | ||
| this.setState({ droppingPosition }); | ||
| } | ||
| } | ||
| }; | ||
| removeDroppingPlaceholder: () => void = () => { | ||
| const { droppingItem, cols } = this.props; | ||
| const { layout } = this.state; | ||
| const newLayout = compact( | ||
| layout.filter(l => l.i !== droppingItem.i), | ||
| compactType(this.props), | ||
| cols, | ||
| this.props.allowOverlap | ||
| ); | ||
| this.setState({ | ||
| layout: newLayout, | ||
| droppingDOMNode: null, | ||
| activeDrag: null, | ||
| droppingPosition: undefined | ||
| }); | ||
| }; | ||
| onDragLeave: EventHandler = e => { | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| this.dragEnterCounter--; | ||
| // onDragLeave can be triggered on each layout's child. | ||
| // But we know that count of dragEnter and dragLeave events | ||
| // will be balanced after leaving the layout's container | ||
| // so we can increase and decrease count of dragEnter and | ||
| // when it'll be equal to 0 we'll remove the placeholder | ||
| if (this.dragEnterCounter === 0) { | ||
| this.removeDroppingPlaceholder(); | ||
| } | ||
| }; | ||
| onDragEnter: EventHandler = e => { | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| this.dragEnterCounter++; | ||
| }; | ||
| onDrop: EventHandler = (e: Event) => { | ||
| e.preventDefault(); // Prevent any browser native action | ||
| e.stopPropagation(); | ||
| const { droppingItem } = this.props; | ||
| const { layout } = this.state; | ||
| const item = layout.find(l => l.i === droppingItem.i); | ||
| // reset dragEnter counter on drop | ||
| this.dragEnterCounter = 0; | ||
| this.removeDroppingPlaceholder(); | ||
| this.props.onDrop(layout, item, e); | ||
| }; | ||
| render(): React.Element<"div"> { | ||
| const { className, style, isDroppable, innerRef } = this.props; | ||
| const mergedClassName = clsx(layoutClassName, className); | ||
| const mergedStyle = { | ||
| height: this.containerHeight(), | ||
| ...style | ||
| }; | ||
| return ( | ||
| <div | ||
| ref={innerRef} | ||
| className={mergedClassName} | ||
| style={mergedStyle} | ||
| onDrop={isDroppable ? this.onDrop : noop} | ||
| onDragLeave={isDroppable ? this.onDragLeave : noop} | ||
| onDragEnter={isDroppable ? this.onDragEnter : noop} | ||
| onDragOver={isDroppable ? this.onDragOver : noop} | ||
| > | ||
| {React.Children.map(this.props.children, child => | ||
| this.processGridItem(child) | ||
| )} | ||
| {isDroppable && | ||
| this.state.droppingDOMNode && | ||
| this.processGridItem(this.state.droppingDOMNode, true)} | ||
| {this.placeholder()} | ||
| </div> | ||
| ); | ||
| } | ||
| } |
| // @flow | ||
| import PropTypes from "prop-types"; | ||
| import React from "react"; | ||
| import type { | ||
| Ref, | ||
| ChildrenArray as ReactChildrenArray, | ||
| Element as ReactElement | ||
| } from "react"; | ||
| import type { | ||
| DragOverEvent, | ||
| EventCallback, | ||
| CompactType, | ||
| Layout, | ||
| LayoutItem, | ||
| ResizeHandleAxis | ||
| } from "./utils"; | ||
| // util | ||
| export type ReactRef<T: HTMLElement> = {| | ||
| +current: T | null | ||
| |}; | ||
| export type ResizeHandle = | ||
| | ReactElement<any> | ||
| | (( | ||
| resizeHandleAxis: ResizeHandleAxis, | ||
| ref: ReactRef<HTMLElement> | ||
| ) => ReactElement<any>); | ||
| // Defines which resize handles should be rendered (default: 'se') | ||
| // Allows for any combination of: | ||
| // 's' - South handle (bottom-center) | ||
| // 'w' - West handle (left-center) | ||
| // 'e' - East handle (right-center) | ||
| // 'n' - North handle (top-center) | ||
| // 'sw' - Southwest handle (bottom-left) | ||
| // 'nw' - Northwest handle (top-left) | ||
| // 'se' - Southeast handle (bottom-right) | ||
| // 'ne' - Northeast handle (top-right) | ||
| export const resizeHandleAxesType: ReactPropsChainableTypeChecker = | ||
| PropTypes.arrayOf( | ||
| PropTypes.oneOf(["s", "w", "e", "n", "sw", "nw", "se", "ne"]) | ||
| ); | ||
| // Custom component for resize handles | ||
| export const resizeHandleType: ReactPropsChainableTypeChecker = | ||
| PropTypes.oneOfType([PropTypes.node, PropTypes.func]); | ||
| export type Props = {| | ||
| className: string, | ||
| style: Object, | ||
| width: number, | ||
| autoSize: boolean, | ||
| cols: number, | ||
| draggableCancel: string, | ||
| draggableHandle: string, | ||
| verticalCompact: boolean, | ||
| compactType: CompactType, | ||
| layout: Layout, | ||
| margin: [number, number], | ||
| containerPadding: ?[number, number], | ||
| rowHeight: number, | ||
| maxRows: number, | ||
| isBounded: boolean, | ||
| isDraggable: boolean, | ||
| isResizable: boolean, | ||
| isDroppable: boolean, | ||
| preventCollision: boolean, | ||
| useCSSTransforms: boolean, | ||
| transformScale: number, | ||
| droppingItem: $Shape<LayoutItem>, | ||
| resizeHandles: ResizeHandleAxis[], | ||
| resizeHandle?: ResizeHandle, | ||
| allowOverlap: boolean, | ||
| // Callbacks | ||
| onLayoutChange: Layout => void, | ||
| onDrag: EventCallback, | ||
| onDragStart: EventCallback, | ||
| onDragStop: EventCallback, | ||
| onResize: EventCallback, | ||
| onResizeStart: EventCallback, | ||
| onResizeStop: EventCallback, | ||
| onDropDragOver: (e: DragOverEvent) => ?({| w?: number, h?: number |} | false), | ||
| onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void, | ||
| children: ReactChildrenArray<ReactElement<any>>, | ||
| innerRef?: Ref<"div"> | ||
| |}; | ||
| export type DefaultProps = $Diff< | ||
| Props, | ||
| { | ||
| children: ReactChildrenArray<ReactElement<any>>, | ||
| width: number | ||
| } | ||
| >; | ||
| export default { | ||
| // | ||
| // Basic props | ||
| // | ||
| className: PropTypes.string, | ||
| style: PropTypes.object, | ||
| // This can be set explicitly. If it is not set, it will automatically | ||
| // be set to the container width. Note that resizes will *not* cause this to adjust. | ||
| // If you need that behavior, use WidthProvider. | ||
| width: PropTypes.number, | ||
| // If true, the container height swells and contracts to fit contents | ||
| autoSize: PropTypes.bool, | ||
| // # of cols. | ||
| cols: PropTypes.number, | ||
| // A selector that will not be draggable. | ||
| draggableCancel: PropTypes.string, | ||
| // A selector for the draggable handler | ||
| draggableHandle: PropTypes.string, | ||
| // Deprecated | ||
| verticalCompact: function (props: Props) { | ||
| if ( | ||
| props.verticalCompact === false && | ||
| process.env.NODE_ENV !== "production" | ||
| ) { | ||
| console.warn( | ||
| // eslint-disable-line no-console | ||
| "`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. " + | ||
| 'Use `compactType`: "horizontal" | "vertical" | null.' | ||
| ); | ||
| } | ||
| }, | ||
| // Choose vertical or hotizontal compaction | ||
| compactType: (PropTypes.oneOf([ | ||
| "vertical", | ||
| "horizontal" | ||
| ]): ReactPropsChainableTypeChecker), | ||
| // layout is an array of object with the format: | ||
| // {x: Number, y: Number, w: Number, h: Number, i: String} | ||
| layout: function (props: Props) { | ||
| var layout = props.layout; | ||
| // I hope you're setting the data-grid property on the grid items | ||
| if (layout === undefined) return; | ||
| require("./utils").validateLayout(layout, "layout"); | ||
| }, | ||
| // | ||
| // Grid Dimensions | ||
| // | ||
| // Margin between items [x, y] in px | ||
| margin: (PropTypes.arrayOf(PropTypes.number): ReactPropsChainableTypeChecker), | ||
| // Padding inside the container [x, y] in px | ||
| containerPadding: (PropTypes.arrayOf( | ||
| PropTypes.number | ||
| ): ReactPropsChainableTypeChecker), | ||
| // Rows have a static height, but you can change this based on breakpoints if you like | ||
| rowHeight: PropTypes.number, | ||
| // Default Infinity, but you can specify a max here if you like. | ||
| // Note that this isn't fully fleshed out and won't error if you specify a layout that | ||
| // extends beyond the row capacity. It will, however, not allow users to drag/resize | ||
| // an item past the barrier. They can push items beyond the barrier, though. | ||
| // Intentionally not documented for this reason. | ||
| maxRows: PropTypes.number, | ||
| // | ||
| // Flags | ||
| // | ||
| isBounded: PropTypes.bool, | ||
| isDraggable: PropTypes.bool, | ||
| isResizable: PropTypes.bool, | ||
| // If true, grid can be placed one over the other. | ||
| allowOverlap: PropTypes.bool, | ||
| // If true, grid items won't change position when being dragged over. | ||
| preventCollision: PropTypes.bool, | ||
| // Use CSS transforms instead of top/left | ||
| useCSSTransforms: PropTypes.bool, | ||
| // parent layout transform scale | ||
| transformScale: PropTypes.number, | ||
| // If true, an external element can trigger onDrop callback with a specific grid position as a parameter | ||
| isDroppable: PropTypes.bool, | ||
| // Resize handle options | ||
| resizeHandles: resizeHandleAxesType, | ||
| resizeHandle: resizeHandleType, | ||
| // | ||
| // Callbacks | ||
| // | ||
| // Callback so you can save the layout. Calls after each drag & resize stops. | ||
| onLayoutChange: PropTypes.func, | ||
| // Calls when drag starts. Callback is of the signature (layout, oldItem, newItem, placeholder, e, ?node). | ||
| // All callbacks below have the same signature. 'start' and 'stop' callbacks omit the 'placeholder'. | ||
| onDragStart: PropTypes.func, | ||
| // Calls on each drag movement. | ||
| onDrag: PropTypes.func, | ||
| // Calls when drag is complete. | ||
| onDragStop: PropTypes.func, | ||
| //Calls when resize starts. | ||
| onResizeStart: PropTypes.func, | ||
| // Calls when resize movement happens. | ||
| onResize: PropTypes.func, | ||
| // Calls when resize is complete. | ||
| onResizeStop: PropTypes.func, | ||
| // Calls when some element is dropped. | ||
| onDrop: PropTypes.func, | ||
| // | ||
| // Other validations | ||
| // | ||
| droppingItem: (PropTypes.shape({ | ||
| i: PropTypes.string.isRequired, | ||
| w: PropTypes.number.isRequired, | ||
| h: PropTypes.number.isRequired | ||
| }): ReactPropsChainableTypeChecker), | ||
| // Children must not have duplicate keys. | ||
| children: function (props: Props, propName: string) { | ||
| const children = props[propName]; | ||
| // Check children keys for duplicates. Throw if found. | ||
| const keys = {}; | ||
| React.Children.forEach(children, function (child) { | ||
| if (child?.key == null) return; | ||
| if (keys[child.key]) { | ||
| throw new Error( | ||
| 'Duplicate child key "' + | ||
| child.key + | ||
| '" found! This will cause problems in ReactGridLayout.' | ||
| ); | ||
| } | ||
| keys[child.key] = true; | ||
| }); | ||
| }, | ||
| // Optional ref for getting a reference for the wrapping div. | ||
| innerRef: PropTypes.any | ||
| }; |
| // @flow | ||
| import * as React from "react"; | ||
| import PropTypes from "prop-types"; | ||
| import { deepEqual } from "fast-equals"; | ||
| import { | ||
| cloneLayout, | ||
| synchronizeLayoutWithChildren, | ||
| validateLayout, | ||
| noop, | ||
| type Layout, | ||
| type Pick | ||
| } from "./utils"; | ||
| import { | ||
| getBreakpointFromWidth, | ||
| getColsFromBreakpoint, | ||
| findOrGenerateResponsiveLayout, | ||
| type ResponsiveLayout, | ||
| type OnLayoutChangeCallback, | ||
| type Breakpoints | ||
| } from "./responsiveUtils"; | ||
| import ReactGridLayout from "./ReactGridLayout"; | ||
| // $FlowFixMe[method-unbinding] | ||
| const type = obj => Object.prototype.toString.call(obj); | ||
| /** | ||
| * Get a value of margin or containerPadding. | ||
| * | ||
| * @param {Array | Object} param Margin | containerPadding, e.g. [10, 10] | {lg: [10, 10], ...}. | ||
| * @param {String} breakpoint Breakpoint: lg, md, sm, xs and etc. | ||
| * @return {Array} | ||
| */ | ||
| function getIndentationValue<T: ?[number, number]>( | ||
| param: { [key: string]: T } | T, | ||
| breakpoint: string | ||
| ): T { | ||
| // $FlowIgnore TODO fix this typedef | ||
| if (param == null) return null; | ||
| // $FlowIgnore TODO fix this typedef | ||
| return Array.isArray(param) ? param : param[breakpoint]; | ||
| } | ||
| type State = { | ||
| layout: Layout, | ||
| breakpoint: string, | ||
| cols: number, | ||
| layouts?: ResponsiveLayout<string> | ||
| }; | ||
| type Props<Breakpoint: string = string> = {| | ||
| ...React.ElementConfig<typeof ReactGridLayout>, | ||
| // Responsive config | ||
| breakpoint?: ?Breakpoint, | ||
| breakpoints: Breakpoints<Breakpoint>, | ||
| cols: { [key: Breakpoint]: number }, | ||
| layouts: ResponsiveLayout<Breakpoint>, | ||
| width: number, | ||
| margin: { [key: Breakpoint]: [number, number] } | [number, number], | ||
| /* prettier-ignore */ | ||
| containerPadding: { [key: Breakpoint]: ?[number, number] } | ?[number, number], | ||
| // Callbacks | ||
| onBreakpointChange: (Breakpoint, cols: number) => void, | ||
| onLayoutChange: OnLayoutChangeCallback, | ||
| onWidthChange: ( | ||
| containerWidth: number, | ||
| margin: [number, number], | ||
| cols: number, | ||
| containerPadding: ?[number, number] | ||
| ) => void | ||
| |}; | ||
| type DefaultProps = Pick< | ||
| Props<>, | ||
| {| | ||
| allowOverlap: 0, | ||
| breakpoints: 0, | ||
| cols: 0, | ||
| containerPadding: 0, | ||
| layouts: 0, | ||
| margin: 0, | ||
| onBreakpointChange: 0, | ||
| onLayoutChange: 0, | ||
| onWidthChange: 0 | ||
| |} | ||
| >; | ||
| export default class ResponsiveReactGridLayout extends React.Component< | ||
| Props<>, | ||
| State | ||
| > { | ||
| // This should only include propTypes needed in this code; RGL itself | ||
| // will do validation of the rest props passed to it. | ||
| static propTypes = { | ||
| // | ||
| // Basic props | ||
| // | ||
| // Optional, but if you are managing width yourself you may want to set the breakpoint | ||
| // yourself as well. | ||
| breakpoint: PropTypes.string, | ||
| // {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480} | ||
| breakpoints: PropTypes.object, | ||
| allowOverlap: PropTypes.bool, | ||
| // # of cols. This is a breakpoint -> cols map | ||
| cols: PropTypes.object, | ||
| // # of margin. This is a breakpoint -> margin map | ||
| // e.g. { lg: [5, 5], md: [10, 10], sm: [15, 15] } | ||
| // Margin between items [x, y] in px | ||
| // e.g. [10, 10] | ||
| margin: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), | ||
| // # of containerPadding. This is a breakpoint -> containerPadding map | ||
| // e.g. { lg: [5, 5], md: [10, 10], sm: [15, 15] } | ||
| // Padding inside the container [x, y] in px | ||
| // e.g. [10, 10] | ||
| containerPadding: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), | ||
| // layouts is an object mapping breakpoints to layouts. | ||
| // e.g. {lg: Layout, md: Layout, ...} | ||
| layouts(props: Props<>, propName: string) { | ||
| if (type(props[propName]) !== "[object Object]") { | ||
| throw new Error( | ||
| "Layout property must be an object. Received: " + | ||
| type(props[propName]) | ||
| ); | ||
| } | ||
| Object.keys(props[propName]).forEach(key => { | ||
| if (!(key in props.breakpoints)) { | ||
| throw new Error( | ||
| "Each key in layouts must align with a key in breakpoints." | ||
| ); | ||
| } | ||
| validateLayout(props.layouts[key], "layouts." + key); | ||
| }); | ||
| }, | ||
| // The width of this component. | ||
| // Required in this propTypes stanza because generateInitialState() will fail without it. | ||
| width: PropTypes.number.isRequired, | ||
| // | ||
| // Callbacks | ||
| // | ||
| // Calls back with breakpoint and new # cols | ||
| onBreakpointChange: PropTypes.func, | ||
| // Callback so you can save the layout. | ||
| // Calls back with (currentLayout, allLayouts). allLayouts are keyed by breakpoint. | ||
| onLayoutChange: PropTypes.func, | ||
| // Calls back with (containerWidth, margin, cols, containerPadding) | ||
| onWidthChange: PropTypes.func | ||
| }; | ||
| static defaultProps: DefaultProps = { | ||
| breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }, | ||
| cols: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }, | ||
| containerPadding: { lg: null, md: null, sm: null, xs: null, xxs: null }, | ||
| layouts: {}, | ||
| margin: [10, 10], | ||
| allowOverlap: false, | ||
| onBreakpointChange: noop, | ||
| onLayoutChange: noop, | ||
| onWidthChange: noop | ||
| }; | ||
| state: State = this.generateInitialState(); | ||
| generateInitialState(): State { | ||
| const { width, breakpoints, layouts, cols } = this.props; | ||
| const breakpoint = getBreakpointFromWidth(breakpoints, width); | ||
| const colNo = getColsFromBreakpoint(breakpoint, cols); | ||
| // verticalCompact compatibility, now deprecated | ||
| const compactType = | ||
| this.props.verticalCompact === false ? null : this.props.compactType; | ||
| // Get the initial layout. This can tricky; we try to generate one however possible if one doesn't exist | ||
| // for this layout. | ||
| const initialLayout = findOrGenerateResponsiveLayout( | ||
| layouts, | ||
| breakpoints, | ||
| breakpoint, | ||
| breakpoint, | ||
| colNo, | ||
| compactType | ||
| ); | ||
| return { | ||
| layout: initialLayout, | ||
| breakpoint: breakpoint, | ||
| cols: colNo | ||
| }; | ||
| } | ||
| static getDerivedStateFromProps( | ||
| nextProps: Props<*>, | ||
| prevState: State | ||
| ): ?$Shape<State> { | ||
| if (!deepEqual(nextProps.layouts, prevState.layouts)) { | ||
| // Allow parent to set layouts directly. | ||
| const { breakpoint, cols } = prevState; | ||
| // Since we're setting an entirely new layout object, we must generate a new responsive layout | ||
| // if one does not exist. | ||
| const newLayout = findOrGenerateResponsiveLayout( | ||
| nextProps.layouts, | ||
| nextProps.breakpoints, | ||
| breakpoint, | ||
| breakpoint, | ||
| cols, | ||
| nextProps.compactType | ||
| ); | ||
| return { layout: newLayout, layouts: nextProps.layouts }; | ||
| } | ||
| return null; | ||
| } | ||
| componentDidUpdate(prevProps: Props<*>) { | ||
| // Allow parent to set width or breakpoint directly. | ||
| if ( | ||
| this.props.width != prevProps.width || | ||
| this.props.breakpoint !== prevProps.breakpoint || | ||
| !deepEqual(this.props.breakpoints, prevProps.breakpoints) || | ||
| !deepEqual(this.props.cols, prevProps.cols) | ||
| ) { | ||
| this.onWidthChange(prevProps); | ||
| } | ||
| } | ||
| // wrap layouts so we do not need to pass layouts to child | ||
| onLayoutChange: Layout => void = (layout: Layout) => { | ||
| this.props.onLayoutChange(layout, { | ||
| ...this.props.layouts, | ||
| [this.state.breakpoint]: layout | ||
| }); | ||
| }; | ||
| /** | ||
| * When the width changes work through breakpoints and reset state with the new width & breakpoint. | ||
| * Width changes are necessary to figure out the widget widths. | ||
| */ | ||
| onWidthChange(prevProps: Props<*>) { | ||
| const { breakpoints, cols, layouts, compactType } = this.props; | ||
| const newBreakpoint = | ||
| this.props.breakpoint || | ||
| getBreakpointFromWidth(this.props.breakpoints, this.props.width); | ||
| const lastBreakpoint = this.state.breakpoint; | ||
| const newCols: number = getColsFromBreakpoint(newBreakpoint, cols); | ||
| const newLayouts = { ...layouts }; | ||
| // Breakpoint change | ||
| if ( | ||
| lastBreakpoint !== newBreakpoint || | ||
| prevProps.breakpoints !== breakpoints || | ||
| prevProps.cols !== cols | ||
| ) { | ||
| // Preserve the current layout if the current breakpoint is not present in the next layouts. | ||
| if (!(lastBreakpoint in newLayouts)) | ||
| newLayouts[lastBreakpoint] = cloneLayout(this.state.layout); | ||
| // Find or generate a new layout. | ||
| let layout = findOrGenerateResponsiveLayout( | ||
| newLayouts, | ||
| breakpoints, | ||
| newBreakpoint, | ||
| lastBreakpoint, | ||
| newCols, | ||
| compactType | ||
| ); | ||
| // This adds missing items. | ||
| layout = synchronizeLayoutWithChildren( | ||
| layout, | ||
| this.props.children, | ||
| newCols, | ||
| compactType, | ||
| this.props.allowOverlap | ||
| ); | ||
| // Store the new layout. | ||
| newLayouts[newBreakpoint] = layout; | ||
| // callbacks | ||
| this.props.onBreakpointChange(newBreakpoint, newCols); | ||
| this.props.onLayoutChange(layout, newLayouts); | ||
| this.setState({ | ||
| breakpoint: newBreakpoint, | ||
| layout: layout, | ||
| cols: newCols | ||
| }); | ||
| } | ||
| const margin = getIndentationValue(this.props.margin, newBreakpoint); | ||
| const containerPadding = getIndentationValue( | ||
| this.props.containerPadding, | ||
| newBreakpoint | ||
| ); | ||
| //call onWidthChange on every change of width, not only on breakpoint changes | ||
| this.props.onWidthChange( | ||
| this.props.width, | ||
| margin, | ||
| newCols, | ||
| containerPadding | ||
| ); | ||
| } | ||
| render(): React.Element<typeof ReactGridLayout> { | ||
| /* eslint-disable no-unused-vars */ | ||
| const { | ||
| breakpoint, | ||
| breakpoints, | ||
| cols, | ||
| layouts, | ||
| margin, | ||
| containerPadding, | ||
| onBreakpointChange, | ||
| onLayoutChange, | ||
| onWidthChange, | ||
| ...other | ||
| } = this.props; | ||
| /* eslint-enable no-unused-vars */ | ||
| return ( | ||
| <ReactGridLayout | ||
| {...other} | ||
| // $FlowIgnore should allow nullable here due to DefaultProps | ||
| margin={getIndentationValue(margin, this.state.breakpoint)} | ||
| containerPadding={getIndentationValue( | ||
| containerPadding, | ||
| this.state.breakpoint | ||
| )} | ||
| onLayoutChange={this.onLayoutChange} | ||
| layout={this.state.layout} | ||
| cols={this.state.cols} | ||
| /> | ||
| ); | ||
| } | ||
| } |
| // @flow | ||
| import { cloneLayout, compact, correctBounds } from "./utils"; | ||
| import type { CompactType, Layout } from "./utils"; | ||
| export type Breakpoint = string; | ||
| export type DefaultBreakpoints = "lg" | "md" | "sm" | "xs" | "xxs"; | ||
| // + indicates read-only | ||
| export type ResponsiveLayout<T: Breakpoint> = { | ||
| +[breakpoint: T]: Layout | ||
| }; | ||
| export type Breakpoints<T: Breakpoint> = { | ||
| +[breakpoint: T]: number | ||
| }; | ||
| export type OnLayoutChangeCallback = ( | ||
| Layout, | ||
| { [key: Breakpoint]: Layout } | ||
| ) => void; | ||
| /** | ||
| * Given a width, find the highest breakpoint that matches is valid for it (width > breakpoint). | ||
| * | ||
| * @param {Object} breakpoints Breakpoints object (e.g. {lg: 1200, md: 960, ...}) | ||
| * @param {Number} width Screen width. | ||
| * @return {String} Highest breakpoint that is less than width. | ||
| */ | ||
| export function getBreakpointFromWidth( | ||
| breakpoints: Breakpoints<Breakpoint>, | ||
| width: number | ||
| ): Breakpoint { | ||
| const sorted = sortBreakpoints(breakpoints); | ||
| let matching = sorted[0]; | ||
| for (let i = 1, len = sorted.length; i < len; i++) { | ||
| const breakpointName = sorted[i]; | ||
| if (width > breakpoints[breakpointName]) matching = breakpointName; | ||
| } | ||
| return matching; | ||
| } | ||
| /** | ||
| * Given a breakpoint, get the # of cols set for it. | ||
| * @param {String} breakpoint Breakpoint name. | ||
| * @param {Object} cols Map of breakpoints to cols. | ||
| * @return {Number} Number of cols. | ||
| */ | ||
| export function getColsFromBreakpoint( | ||
| breakpoint: Breakpoint, | ||
| cols: Breakpoints<Breakpoint> | ||
| ): number { | ||
| if (!cols[breakpoint]) { | ||
| throw new Error( | ||
| "ResponsiveReactGridLayout: `cols` entry for breakpoint " + | ||
| breakpoint + | ||
| " is missing!" | ||
| ); | ||
| } | ||
| return cols[breakpoint]; | ||
| } | ||
| /** | ||
| * Given existing layouts and a new breakpoint, find or generate a new layout. | ||
| * | ||
| * This finds the layout above the new one and generates from it, if it exists. | ||
| * | ||
| * @param {Object} layouts Existing layouts. | ||
| * @param {Array} breakpoints All breakpoints. | ||
| * @param {String} breakpoint New breakpoint. | ||
| * @param {String} breakpoint Last breakpoint (for fallback). | ||
| * @param {Number} cols Column count at new breakpoint. | ||
| * @param {Boolean} verticalCompact Whether or not to compact the layout | ||
| * vertically. | ||
| * @return {Array} New layout. | ||
| */ | ||
| export function findOrGenerateResponsiveLayout( | ||
| layouts: ResponsiveLayout<Breakpoint>, | ||
| breakpoints: Breakpoints<Breakpoint>, | ||
| breakpoint: Breakpoint, | ||
| lastBreakpoint: Breakpoint, | ||
| cols: number, | ||
| compactType: CompactType | ||
| ): Layout { | ||
| // If it already exists, just return it. | ||
| if (layouts[breakpoint]) return cloneLayout(layouts[breakpoint]); | ||
| // Find or generate the next layout | ||
| let layout = layouts[lastBreakpoint]; | ||
| const breakpointsSorted = sortBreakpoints(breakpoints); | ||
| const breakpointsAbove = breakpointsSorted.slice( | ||
| breakpointsSorted.indexOf(breakpoint) | ||
| ); | ||
| for (let i = 0, len = breakpointsAbove.length; i < len; i++) { | ||
| const b = breakpointsAbove[i]; | ||
| if (layouts[b]) { | ||
| layout = layouts[b]; | ||
| break; | ||
| } | ||
| } | ||
| layout = cloneLayout(layout || []); // clone layout so we don't modify existing items | ||
| return compact(correctBounds(layout, { cols: cols }), compactType, cols); | ||
| } | ||
| /** | ||
| * Given breakpoints, return an array of breakpoints sorted by width. This is usually | ||
| * e.g. ['xxs', 'xs', 'sm', ...] | ||
| * | ||
| * @param {Object} breakpoints Key/value pair of breakpoint names to widths. | ||
| * @return {Array} Sorted breakpoints. | ||
| */ | ||
| export function sortBreakpoints( | ||
| breakpoints: Breakpoints<Breakpoint> | ||
| ): Array<Breakpoint> { | ||
| const keys: Array<string> = Object.keys(breakpoints); | ||
| return keys.sort(function (a, b) { | ||
| return breakpoints[a] - breakpoints[b]; | ||
| }); | ||
| } |
-995
| // @flow | ||
| import { deepEqual } from "fast-equals"; | ||
| import React from "react"; | ||
| import type { | ||
| ChildrenArray as ReactChildrenArray, | ||
| Element as ReactElement | ||
| } from "react"; | ||
| export type ResizeHandleAxis = | ||
| | "s" | ||
| | "w" | ||
| | "e" | ||
| | "n" | ||
| | "sw" | ||
| | "nw" | ||
| | "se" | ||
| | "ne"; | ||
| export type LayoutItem = { | ||
| w: number, | ||
| h: number, | ||
| x: number, | ||
| y: number, | ||
| i: string, | ||
| minW?: number, | ||
| minH?: number, | ||
| maxW?: number, | ||
| maxH?: number, | ||
| moved?: boolean, | ||
| static?: boolean, | ||
| isDraggable?: ?boolean, | ||
| isResizable?: ?boolean, | ||
| resizeHandles?: Array<ResizeHandleAxis>, | ||
| isBounded?: ?boolean | ||
| }; | ||
| export type Layout = $ReadOnlyArray<LayoutItem>; | ||
| export type Position = { | ||
| left: number, | ||
| top: number, | ||
| width: number, | ||
| height: number | ||
| }; | ||
| export type ReactDraggableCallbackData = { | ||
| node: HTMLElement, | ||
| x?: number, | ||
| y?: number, | ||
| deltaX: number, | ||
| deltaY: number, | ||
| lastX?: number, | ||
| lastY?: number | ||
| }; | ||
| export type PartialPosition = { left: number, top: number }; | ||
| export type DroppingPosition = { left: number, top: number, e: Event }; | ||
| export type Size = { width: number, height: number }; | ||
| export type GridDragEvent = { | ||
| e: Event, | ||
| node: HTMLElement, | ||
| newPosition: PartialPosition | ||
| }; | ||
| export type GridResizeEvent = { | ||
| e: Event, | ||
| node: HTMLElement, | ||
| size: Size, | ||
| handle: string | ||
| }; | ||
| export type DragOverEvent = MouseEvent & { | ||
| nativeEvent: { | ||
| layerX: number, | ||
| layerY: number, | ||
| ...Event | ||
| } | ||
| }; | ||
| // Helpful port from TS | ||
| export type Pick<FromType, Properties: { [string]: 0 }> = $Exact< | ||
| $ObjMapi<Properties, <K, V>(k: K, v: V) => $ElementType<FromType, K>> | ||
| >; | ||
| type REl = ReactElement<any>; | ||
| export type ReactChildren = ReactChildrenArray<REl>; | ||
| // All callbacks are of the signature (layout, oldItem, newItem, placeholder, e). | ||
| export type EventCallback = ( | ||
| Layout, | ||
| oldItem: ?LayoutItem, | ||
| newItem: ?LayoutItem, | ||
| placeholder: ?LayoutItem, | ||
| Event, | ||
| ?HTMLElement | ||
| ) => void; | ||
| export type CompactType = ?("horizontal" | "vertical"); | ||
| const isProduction = process.env.NODE_ENV === "production"; | ||
| const DEBUG = false; | ||
| /** | ||
| * Return the bottom coordinate of the layout. | ||
| * | ||
| * @param {Array} layout Layout array. | ||
| * @return {Number} Bottom coordinate. | ||
| */ | ||
| export function bottom(layout: Layout): number { | ||
| let max = 0, | ||
| bottomY; | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| bottomY = layout[i].y + layout[i].h; | ||
| if (bottomY > max) max = bottomY; | ||
| } | ||
| return max; | ||
| } | ||
| export function cloneLayout(layout: Layout): Layout { | ||
| const newLayout = Array(layout.length); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| newLayout[i] = cloneLayoutItem(layout[i]); | ||
| } | ||
| return newLayout; | ||
| } | ||
| // Modify a layoutItem inside a layout. Returns a new Layout, | ||
| // does not mutate. Carries over all other LayoutItems unmodified. | ||
| export function modifyLayout(layout: Layout, layoutItem: LayoutItem): Layout { | ||
| const newLayout = Array(layout.length); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| if (layoutItem.i === layout[i].i) { | ||
| newLayout[i] = layoutItem; | ||
| } else { | ||
| newLayout[i] = layout[i]; | ||
| } | ||
| } | ||
| return newLayout; | ||
| } | ||
| // Function to be called to modify a layout item. | ||
| // Does defensive clones to ensure the layout is not modified. | ||
| export function withLayoutItem( | ||
| layout: Layout, | ||
| itemKey: string, | ||
| cb: LayoutItem => LayoutItem | ||
| ): [Layout, ?LayoutItem] { | ||
| let item = getLayoutItem(layout, itemKey); | ||
| if (!item) return [layout, null]; | ||
| item = cb(cloneLayoutItem(item)); // defensive clone then modify | ||
| // FIXME could do this faster if we already knew the index | ||
| layout = modifyLayout(layout, item); | ||
| return [layout, item]; | ||
| } | ||
| // Fast path to cloning, since this is monomorphic | ||
| export function cloneLayoutItem(layoutItem: LayoutItem): LayoutItem { | ||
| return { | ||
| w: layoutItem.w, | ||
| h: layoutItem.h, | ||
| x: layoutItem.x, | ||
| y: layoutItem.y, | ||
| i: layoutItem.i, | ||
| minW: layoutItem.minW, | ||
| maxW: layoutItem.maxW, | ||
| minH: layoutItem.minH, | ||
| maxH: layoutItem.maxH, | ||
| moved: Boolean(layoutItem.moved), | ||
| static: Boolean(layoutItem.static), | ||
| // These can be null/undefined | ||
| isDraggable: layoutItem.isDraggable, | ||
| isResizable: layoutItem.isResizable, | ||
| resizeHandles: layoutItem.resizeHandles, | ||
| isBounded: layoutItem.isBounded | ||
| }; | ||
| } | ||
| /** | ||
| * Comparing React `children` is a bit difficult. This is a good way to compare them. | ||
| * This will catch differences in keys, order, and length. | ||
| */ | ||
| export function childrenEqual(a: ReactChildren, b: ReactChildren): boolean { | ||
| return ( | ||
| deepEqual( | ||
| React.Children.map(a, c => c?.key), | ||
| React.Children.map(b, c => c?.key) | ||
| ) && | ||
| deepEqual( | ||
| React.Children.map(a, c => c?.props["data-grid"]), | ||
| React.Children.map(b, c => c?.props["data-grid"]) | ||
| ) | ||
| ); | ||
| } | ||
| /** | ||
| * See `fastRGLPropsEqual.js`. | ||
| * We want this to run as fast as possible - it is called often - and to be | ||
| * resilient to new props that we add. So rather than call lodash.isEqual, | ||
| * which isn't suited to comparing props very well, we use this specialized | ||
| * function in conjunction with preval to generate the fastest possible comparison | ||
| * function, tuned for exactly our props. | ||
| */ | ||
| type FastRGLPropsEqual = (Object, Object, Function) => boolean; | ||
| export const fastRGLPropsEqual: FastRGLPropsEqual = require("./fastRGLPropsEqual"); | ||
| // Like the above, but a lot simpler. | ||
| export function fastPositionEqual(a: Position, b: Position): boolean { | ||
| return ( | ||
| a.left === b.left && | ||
| a.top === b.top && | ||
| a.width === b.width && | ||
| a.height === b.height | ||
| ); | ||
| } | ||
| /** | ||
| * Given two layoutitems, check if they collide. | ||
| */ | ||
| export function collides(l1: LayoutItem, l2: LayoutItem): boolean { | ||
| if (l1.i === l2.i) return false; // same element | ||
| if (l1.x + l1.w <= l2.x) return false; // l1 is left of l2 | ||
| if (l1.x >= l2.x + l2.w) return false; // l1 is right of l2 | ||
| if (l1.y + l1.h <= l2.y) return false; // l1 is above l2 | ||
| if (l1.y >= l2.y + l2.h) return false; // l1 is below l2 | ||
| return true; // boxes overlap | ||
| } | ||
| /** | ||
| * Given a layout, compact it. This involves going down each y coordinate and removing gaps | ||
| * between items. | ||
| * | ||
| * Does not modify layout items (clones). Creates a new layout array. | ||
| * | ||
| * @param {Array} layout Layout. | ||
| * @param {Boolean} verticalCompact Whether or not to compact the layout | ||
| * vertically. | ||
| * @param {Boolean} allowOverlap When `true`, allows overlapping grid items. | ||
| * @return {Array} Compacted Layout. | ||
| */ | ||
| export function compact( | ||
| layout: Layout, | ||
| compactType: CompactType, | ||
| cols: number, | ||
| allowOverlap: ?boolean | ||
| ): Layout { | ||
| // Statics go in the compareWith array right away so items flow around them. | ||
| const compareWith = getStatics(layout); | ||
| // We keep track of the bottom position. | ||
| let b = bottom(compareWith); | ||
| // We go through the items by row and column. | ||
| const sorted = sortLayoutItems(layout, compactType); | ||
| // Holding for new items. | ||
| const out = Array(layout.length); | ||
| for (let i = 0, len = sorted.length; i < len; i++) { | ||
| let l = cloneLayoutItem(sorted[i]); | ||
| // Don't move static elements | ||
| if (!l.static) { | ||
| l = compactItem( | ||
| compareWith, | ||
| l, | ||
| compactType, | ||
| cols, | ||
| sorted, | ||
| allowOverlap, | ||
| b | ||
| ); | ||
| b = Math.max(b, l.y + l.h); | ||
| // Add to comparison array. We only collide with items before this one. | ||
| // Statics are already in this array. | ||
| compareWith.push(l); | ||
| } | ||
| // Add to output array to make sure they still come out in the right order. | ||
| out[layout.indexOf(sorted[i])] = l; | ||
| // Clear moved flag, if it exists. | ||
| l.moved = false; | ||
| } | ||
| return out; | ||
| } | ||
| const heightWidth = { x: "w", y: "h" }; | ||
| /** | ||
| * Before moving item down, it will check if the movement will cause collisions and move those items down before. | ||
| */ | ||
| function resolveCompactionCollision( | ||
| layout: Layout, | ||
| item: LayoutItem, | ||
| moveToCoord: number, | ||
| axis: "x" | "y" | ||
| ) { | ||
| const sizeProp = heightWidth[axis]; | ||
| item[axis] += 1; | ||
| const itemIndex = layout | ||
| .map(layoutItem => { | ||
| return layoutItem.i; | ||
| }) | ||
| .indexOf(item.i); | ||
| // Go through each item we collide with. | ||
| for (let i = itemIndex + 1; i < layout.length; i++) { | ||
| const otherItem = layout[i]; | ||
| // Ignore static items | ||
| if (otherItem.static) continue; | ||
| // Optimization: we can break early if we know we're past this el | ||
| // We can do this b/c it's a sorted layout | ||
| if (otherItem.y > item.y + item.h) break; | ||
| if (collides(item, otherItem)) { | ||
| resolveCompactionCollision( | ||
| layout, | ||
| otherItem, | ||
| moveToCoord + item[sizeProp], | ||
| axis | ||
| ); | ||
| } | ||
| } | ||
| item[axis] = moveToCoord; | ||
| } | ||
| /** | ||
| * Compact an item in the layout. | ||
| * | ||
| * Modifies item. | ||
| * | ||
| */ | ||
| export function compactItem( | ||
| compareWith: Layout, | ||
| l: LayoutItem, | ||
| compactType: CompactType, | ||
| cols: number, | ||
| fullLayout: Layout, | ||
| allowOverlap: ?boolean, | ||
| b: ?number | ||
| ): LayoutItem { | ||
| const compactV = compactType === "vertical"; | ||
| const compactH = compactType === "horizontal"; | ||
| if (compactV) { | ||
| // Bottom 'y' possible is the bottom of the layout. | ||
| // This allows you to do nice stuff like specify {y: Infinity} | ||
| // This is here because the layout must be sorted in order to get the correct bottom `y`. | ||
| if (typeof b === "number") { | ||
| l.y = Math.min(b, l.y); | ||
| } else { | ||
| l.y = Math.min(bottom(compareWith), l.y); | ||
| } | ||
| // Move the element up as far as it can go without colliding. | ||
| while (l.y > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.y--; | ||
| } | ||
| } else if (compactH) { | ||
| // Move the element left as far as it can go without colliding. | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| // Move it down, and keep moving it down if it's colliding. | ||
| let collides; | ||
| // Checking the compactType null value to avoid breaking the layout when overlapping is allowed. | ||
| while ( | ||
| (collides = getFirstCollision(compareWith, l)) && | ||
| !(compactType === null && allowOverlap) | ||
| ) { | ||
| if (compactH) { | ||
| resolveCompactionCollision(fullLayout, l, collides.x + collides.w, "x"); | ||
| } else { | ||
| resolveCompactionCollision(fullLayout, l, collides.y + collides.h, "y"); | ||
| } | ||
| // Since we can't grow without bounds horizontally, if we've overflown, let's move it down and try again. | ||
| if (compactH && l.x + l.w > cols) { | ||
| l.x = cols - l.w; | ||
| l.y++; | ||
| // ALso move element as left as we can | ||
| while (l.x > 0 && !getFirstCollision(compareWith, l)) { | ||
| l.x--; | ||
| } | ||
| } | ||
| } | ||
| // Ensure that there are no negative positions | ||
| l.y = Math.max(l.y, 0); | ||
| l.x = Math.max(l.x, 0); | ||
| return l; | ||
| } | ||
| /** | ||
| * Given a layout, make sure all elements fit within its bounds. | ||
| * | ||
| * Modifies layout items. | ||
| * | ||
| * @param {Array} layout Layout array. | ||
| * @param {Number} bounds Number of columns. | ||
| */ | ||
| export function correctBounds( | ||
| layout: Layout, | ||
| bounds: { cols: number } | ||
| ): Layout { | ||
| const collidesWith = getStatics(layout); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| const l = layout[i]; | ||
| // Overflows right | ||
| if (l.x + l.w > bounds.cols) l.x = bounds.cols - l.w; | ||
| // Overflows left | ||
| if (l.x < 0) { | ||
| l.x = 0; | ||
| l.w = bounds.cols; | ||
| } | ||
| if (!l.static) collidesWith.push(l); | ||
| else { | ||
| // If this is static and collides with other statics, we must move it down. | ||
| // We have to do something nicer than just letting them overlap. | ||
| while (getFirstCollision(collidesWith, l)) { | ||
| l.y++; | ||
| } | ||
| } | ||
| } | ||
| return layout; | ||
| } | ||
| /** | ||
| * Get a layout item by ID. Used so we can override later on if necessary. | ||
| * | ||
| * @param {Array} layout Layout array. | ||
| * @param {String} id ID | ||
| * @return {LayoutItem} Item at ID. | ||
| */ | ||
| export function getLayoutItem(layout: Layout, id: string): ?LayoutItem { | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| if (layout[i].i === id) return layout[i]; | ||
| } | ||
| } | ||
| /** | ||
| * Returns the first item this layout collides with. | ||
| * It doesn't appear to matter which order we approach this from, although | ||
| * perhaps that is the wrong thing to do. | ||
| * | ||
| * @param {Object} layoutItem Layout item. | ||
| * @return {Object|undefined} A colliding layout item, or undefined. | ||
| */ | ||
| export function getFirstCollision( | ||
| layout: Layout, | ||
| layoutItem: LayoutItem | ||
| ): ?LayoutItem { | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| if (collides(layout[i], layoutItem)) return layout[i]; | ||
| } | ||
| } | ||
| export function getAllCollisions( | ||
| layout: Layout, | ||
| layoutItem: LayoutItem | ||
| ): Array<LayoutItem> { | ||
| return layout.filter(l => collides(l, layoutItem)); | ||
| } | ||
| /** | ||
| * Get all static elements. | ||
| * @param {Array} layout Array of layout objects. | ||
| * @return {Array} Array of static layout items.. | ||
| */ | ||
| export function getStatics(layout: Layout): Array<LayoutItem> { | ||
| return layout.filter(l => l.static); | ||
| } | ||
| /** | ||
| * Move an element. Responsible for doing cascading movements of other elements. | ||
| * | ||
| * Modifies layout items. | ||
| * | ||
| * @param {Array} layout Full layout to modify. | ||
| * @param {LayoutItem} l element to move. | ||
| * @param {Number} [x] X position in grid units. | ||
| * @param {Number} [y] Y position in grid units. | ||
| */ | ||
| export function moveElement( | ||
| layout: Layout, | ||
| l: LayoutItem, | ||
| x: ?number, | ||
| y: ?number, | ||
| isUserAction: ?boolean, | ||
| preventCollision: ?boolean, | ||
| compactType: CompactType, | ||
| cols: number, | ||
| allowOverlap: ?boolean | ||
| ): Layout { | ||
| // If this is static and not explicitly enabled as draggable, | ||
| // no move is possible, so we can short-circuit this immediately. | ||
| if (l.static && l.isDraggable !== true) return layout; | ||
| // Short-circuit if nothing to do. | ||
| if (l.y === y && l.x === x) return layout; | ||
| log( | ||
| `Moving element ${l.i} to [${String(x)},${String(y)}] from [${l.x},${l.y}]` | ||
| ); | ||
| const oldX = l.x; | ||
| const oldY = l.y; | ||
| // This is quite a bit faster than extending the object | ||
| if (typeof x === "number") l.x = x; | ||
| if (typeof y === "number") l.y = y; | ||
| l.moved = true; | ||
| // If this collides with anything, move it. | ||
| // When doing this comparison, we have to sort the items we compare with | ||
| // to ensure, in the case of multiple collisions, that we're getting the | ||
| // nearest collision. | ||
| let sorted = sortLayoutItems(layout, compactType); | ||
| const movingUp = | ||
| compactType === "vertical" && typeof y === "number" | ||
| ? oldY >= y | ||
| : compactType === "horizontal" && typeof x === "number" | ||
| ? oldX >= x | ||
| : false; | ||
| // $FlowIgnore acceptable modification of read-only array as it was recently cloned | ||
| if (movingUp) sorted = sorted.reverse(); | ||
| const collisions = getAllCollisions(sorted, l); | ||
| const hasCollisions = collisions.length > 0; | ||
| // We may have collisions. We can short-circuit if we've turned off collisions or | ||
| // allowed overlap. | ||
| if (hasCollisions && allowOverlap) { | ||
| // Easy, we don't need to resolve collisions. But we *did* change the layout, | ||
| // so clone it on the way out. | ||
| return cloneLayout(layout); | ||
| } else if (hasCollisions && preventCollision) { | ||
| // If we are preventing collision but not allowing overlap, we need to | ||
| // revert the position of this element so it goes to where it came from, rather | ||
| // than the user's desired location. | ||
| log(`Collision prevented on ${l.i}, reverting.`); | ||
| l.x = oldX; | ||
| l.y = oldY; | ||
| l.moved = false; | ||
| return layout; // did not change so don't clone | ||
| } | ||
| // Move each item that collides away from this element. | ||
| for (let i = 0, len = collisions.length; i < len; i++) { | ||
| const collision = collisions[i]; | ||
| log( | ||
| `Resolving collision between ${l.i} at [${l.x},${l.y}] and ${collision.i} at [${collision.x},${collision.y}]` | ||
| ); | ||
| // Short circuit so we can't infinite loop | ||
| if (collision.moved) continue; | ||
| // Don't move static items - we have to move *this* element away | ||
| if (collision.static) { | ||
| layout = moveElementAwayFromCollision( | ||
| layout, | ||
| collision, | ||
| l, | ||
| isUserAction, | ||
| compactType, | ||
| cols | ||
| ); | ||
| } else { | ||
| layout = moveElementAwayFromCollision( | ||
| layout, | ||
| l, | ||
| collision, | ||
| isUserAction, | ||
| compactType, | ||
| cols | ||
| ); | ||
| } | ||
| } | ||
| return layout; | ||
| } | ||
| /** | ||
| * This is where the magic needs to happen - given a collision, move an element away from the collision. | ||
| * We attempt to move it up if there's room, otherwise it goes below. | ||
| * | ||
| * @param {Array} layout Full layout to modify. | ||
| * @param {LayoutItem} collidesWith Layout item we're colliding with. | ||
| * @param {LayoutItem} itemToMove Layout item we're moving. | ||
| */ | ||
| export function moveElementAwayFromCollision( | ||
| layout: Layout, | ||
| collidesWith: LayoutItem, | ||
| itemToMove: LayoutItem, | ||
| isUserAction: ?boolean, | ||
| compactType: CompactType, | ||
| cols: number | ||
| ): Layout { | ||
| const compactH = compactType === "horizontal"; | ||
| // Compact vertically if not set to horizontal | ||
| const compactV = compactType === "vertical"; | ||
| const preventCollision = collidesWith.static; // we're already colliding (not for static items) | ||
| // If there is enough space above the collision to put this element, move it there. | ||
| // We only do this on the main collision as this can get funky in cascades and cause | ||
| // unwanted swapping behavior. | ||
| if (isUserAction) { | ||
| // Reset isUserAction flag because we're not in the main collision anymore. | ||
| isUserAction = false; | ||
| // Make a mock item so we don't modify the item here, only modify in moveElement. | ||
| const fakeItem: LayoutItem = { | ||
| x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x, | ||
| y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y, | ||
| w: itemToMove.w, | ||
| h: itemToMove.h, | ||
| i: "-1" | ||
| }; | ||
| const firstCollision = getFirstCollision(layout, fakeItem); | ||
| const collisionNorth = | ||
| firstCollision && firstCollision.y + firstCollision.h > collidesWith.y; | ||
| const collisionWest = | ||
| firstCollision && collidesWith.x + collidesWith.w > firstCollision.x; | ||
| // No collision? If so, we can go up there; otherwise, we'll end up moving down as normal | ||
| if (!firstCollision) { | ||
| log( | ||
| `Doing reverse collision on ${itemToMove.i} up to [${fakeItem.x},${fakeItem.y}].` | ||
| ); | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| compactH ? fakeItem.x : undefined, | ||
| compactV ? fakeItem.y : undefined, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType, | ||
| cols | ||
| ); | ||
| } else if (collisionNorth && compactV) { | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| undefined, | ||
| itemToMove.y + 1, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType, | ||
| cols | ||
| ); | ||
| } else if (collisionNorth && compactType == null) { | ||
| collidesWith.y = itemToMove.y; | ||
| itemToMove.y = itemToMove.y + itemToMove.h; | ||
| return layout; | ||
| } else if (collisionWest && compactH) { | ||
| return moveElement( | ||
| layout, | ||
| collidesWith, | ||
| itemToMove.x, | ||
| undefined, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType, | ||
| cols | ||
| ); | ||
| } | ||
| } | ||
| const newX = compactH ? itemToMove.x + 1 : undefined; | ||
| const newY = compactV ? itemToMove.y + 1 : undefined; | ||
| if (newX == null && newY == null) { | ||
| return layout; | ||
| } | ||
| return moveElement( | ||
| layout, | ||
| itemToMove, | ||
| compactH ? itemToMove.x + 1 : undefined, | ||
| compactV ? itemToMove.y + 1 : undefined, | ||
| isUserAction, | ||
| preventCollision, | ||
| compactType, | ||
| cols | ||
| ); | ||
| } | ||
| /** | ||
| * Helper to convert a number to a percentage string. | ||
| * | ||
| * @param {Number} num Any number | ||
| * @return {String} That number as a percentage. | ||
| */ | ||
| export function perc(num: number): string { | ||
| return num * 100 + "%"; | ||
| } | ||
| /** | ||
| * Helper functions to constrain dimensions of a GridItem | ||
| */ | ||
| const constrainWidth = ( | ||
| left: number, | ||
| currentWidth: number, | ||
| newWidth: number, | ||
| containerWidth: number | ||
| ) => { | ||
| return left + newWidth > containerWidth ? currentWidth : newWidth; | ||
| }; | ||
| const constrainHeight = ( | ||
| top: number, | ||
| currentHeight: number, | ||
| newHeight: number | ||
| ) => { | ||
| return top < 0 ? currentHeight : newHeight; | ||
| }; | ||
| const constrainLeft = (left: number) => Math.max(0, left); | ||
| const constrainTop = (top: number) => Math.max(0, top); | ||
| const resizeNorth = (currentSize, { left, height, width }, _containerWidth) => { | ||
| const top = currentSize.top - (height - currentSize.height); | ||
| return { | ||
| left, | ||
| width, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }; | ||
| }; | ||
| const resizeEast = ( | ||
| currentSize, | ||
| { top, left, height, width }, | ||
| containerWidth | ||
| ) => ({ | ||
| top, | ||
| height, | ||
| width: constrainWidth( | ||
| currentSize.left, | ||
| currentSize.width, | ||
| width, | ||
| containerWidth | ||
| ), | ||
| left: constrainLeft(left) | ||
| }); | ||
| const resizeWest = (currentSize, { top, height, width }, containerWidth) => { | ||
| const left = currentSize.left - (width - currentSize.width); | ||
| return { | ||
| height, | ||
| width: | ||
| left < 0 | ||
| ? currentSize.width | ||
| : constrainWidth( | ||
| currentSize.left, | ||
| currentSize.width, | ||
| width, | ||
| containerWidth | ||
| ), | ||
| top: constrainTop(top), | ||
| left: constrainLeft(left) | ||
| }; | ||
| }; | ||
| const resizeSouth = ( | ||
| currentSize, | ||
| { top, left, height, width }, | ||
| containerWidth | ||
| ) => ({ | ||
| width, | ||
| left, | ||
| height: constrainHeight(top, currentSize.height, height), | ||
| top: constrainTop(top) | ||
| }); | ||
| const resizeNorthEast = (...args) => | ||
| resizeNorth(args[0], resizeEast(...args), args[2]); | ||
| const resizeNorthWest = (...args) => | ||
| resizeNorth(args[0], resizeWest(...args), args[2]); | ||
| const resizeSouthEast = (...args) => | ||
| resizeSouth(args[0], resizeEast(...args), args[2]); | ||
| const resizeSouthWest = (...args) => | ||
| resizeSouth(args[0], resizeWest(...args), args[2]); | ||
| const ordinalResizeHandlerMap = { | ||
| n: resizeNorth, | ||
| ne: resizeNorthEast, | ||
| e: resizeEast, | ||
| se: resizeSouthEast, | ||
| s: resizeSouth, | ||
| sw: resizeSouthWest, | ||
| w: resizeWest, | ||
| nw: resizeNorthWest | ||
| }; | ||
| /** | ||
| * Helper for clamping width and position when resizing an item. | ||
| */ | ||
| export function resizeItemInDirection( | ||
| direction: ResizeHandleAxis, | ||
| currentSize: Position, | ||
| newSize: Position, | ||
| containerWidth: number | ||
| ): Position { | ||
| const ordinalHandler = ordinalResizeHandlerMap[direction]; | ||
| // Shouldn't be possible given types; that said, don't fail hard | ||
| if (!ordinalHandler) return newSize; | ||
| return ordinalHandler( | ||
| currentSize, | ||
| { ...currentSize, ...newSize }, | ||
| containerWidth | ||
| ); | ||
| } | ||
| export function setTransform({ top, left, width, height }: Position): Object { | ||
| // Replace unitless items with px | ||
| const translate = `translate(${left}px,${top}px)`; | ||
| return { | ||
| transform: translate, | ||
| WebkitTransform: translate, | ||
| MozTransform: translate, | ||
| msTransform: translate, | ||
| OTransform: translate, | ||
| width: `${width}px`, | ||
| height: `${height}px`, | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| export function setTopLeft({ top, left, width, height }: Position): Object { | ||
| return { | ||
| top: `${top}px`, | ||
| left: `${left}px`, | ||
| width: `${width}px`, | ||
| height: `${height}px`, | ||
| position: "absolute" | ||
| }; | ||
| } | ||
| /** | ||
| * Get layout items sorted from top left to right and down. | ||
| * | ||
| * @return {Array} Array of layout objects. | ||
| * @return {Array} Layout, sorted static items first. | ||
| */ | ||
| export function sortLayoutItems( | ||
| layout: Layout, | ||
| compactType: CompactType | ||
| ): Layout { | ||
| if (compactType === "horizontal") return sortLayoutItemsByColRow(layout); | ||
| if (compactType === "vertical") return sortLayoutItemsByRowCol(layout); | ||
| else return layout; | ||
| } | ||
| /** | ||
| * Sort layout items by row ascending and column ascending. | ||
| * | ||
| * Does not modify Layout. | ||
| */ | ||
| export function sortLayoutItemsByRowCol(layout: Layout): Layout { | ||
| // Slice to clone array as sort modifies | ||
| return layout.slice(0).sort(function (a, b) { | ||
| if (a.y > b.y || (a.y === b.y && a.x > b.x)) { | ||
| return 1; | ||
| } else if (a.y === b.y && a.x === b.x) { | ||
| // Without this, we can get different sort results in IE vs. Chrome/FF | ||
| return 0; | ||
| } | ||
| return -1; | ||
| }); | ||
| } | ||
| /** | ||
| * Sort layout items by column ascending then row ascending. | ||
| * | ||
| * Does not modify Layout. | ||
| */ | ||
| export function sortLayoutItemsByColRow(layout: Layout): Layout { | ||
| return layout.slice(0).sort(function (a, b) { | ||
| if (a.x > b.x || (a.x === b.x && a.y > b.y)) { | ||
| return 1; | ||
| } | ||
| return -1; | ||
| }); | ||
| } | ||
| /** | ||
| * Generate a layout using the initialLayout and children as a template. | ||
| * Missing entries will be added, extraneous ones will be truncated. | ||
| * | ||
| * Does not modify initialLayout. | ||
| * | ||
| * @param {Array} initialLayout Layout passed in through props. | ||
| * @param {String} breakpoint Current responsive breakpoint. | ||
| * @param {?String} compact Compaction option. | ||
| * @return {Array} Working layout. | ||
| */ | ||
| export function synchronizeLayoutWithChildren( | ||
| initialLayout: Layout, | ||
| children: ReactChildren, | ||
| cols: number, | ||
| compactType: CompactType, | ||
| allowOverlap: ?boolean | ||
| ): Layout { | ||
| initialLayout = initialLayout || []; | ||
| // Generate one layout item per child. | ||
| const layout: LayoutItem[] = []; | ||
| React.Children.forEach(children, (child: ReactElement<any>) => { | ||
| // Child may not exist | ||
| if (child?.key == null) return; | ||
| const exists = getLayoutItem(initialLayout, String(child.key)); | ||
| const g = child.props["data-grid"]; | ||
| // Don't overwrite the layout item if it's already in the initial layout. | ||
| // If it has a `data-grid` property, prefer that over what's in the layout. | ||
| if (exists && g == null) { | ||
| layout.push(cloneLayoutItem(exists)); | ||
| } else { | ||
| // Hey, this item has a data-grid property, use it. | ||
| if (g) { | ||
| if (!isProduction) { | ||
| validateLayout([g], "ReactGridLayout.children"); | ||
| } | ||
| // FIXME clone not really necessary here | ||
| layout.push(cloneLayoutItem({ ...g, i: child.key })); | ||
| } else { | ||
| // Nothing provided: ensure this is added to the bottom | ||
| // FIXME clone not really necessary here | ||
| layout.push( | ||
| cloneLayoutItem({ | ||
| w: 1, | ||
| h: 1, | ||
| x: 0, | ||
| y: bottom(layout), | ||
| i: String(child.key) | ||
| }) | ||
| ); | ||
| } | ||
| } | ||
| }); | ||
| // Correct the layout. | ||
| const correctedLayout = correctBounds(layout, { cols: cols }); | ||
| return allowOverlap | ||
| ? correctedLayout | ||
| : compact(correctedLayout, compactType, cols); | ||
| } | ||
| /** | ||
| * Validate a layout. Throws errors. | ||
| * | ||
| * @param {Array} layout Array of layout items. | ||
| * @param {String} [contextName] Context name for errors. | ||
| * @throw {Error} Validation error. | ||
| */ | ||
| export function validateLayout( | ||
| layout: Layout, | ||
| contextName: string = "Layout" | ||
| ): void { | ||
| const subProps = ["x", "y", "w", "h"]; | ||
| if (!Array.isArray(layout)) | ||
| throw new Error(contextName + " must be an array!"); | ||
| for (let i = 0, len = layout.length; i < len; i++) { | ||
| const item = layout[i]; | ||
| for (let j = 0; j < subProps.length; j++) { | ||
| const key = subProps[j]; | ||
| const value = item[key]; | ||
| if (typeof value !== "number" || Number.isNaN(value)) { | ||
| throw new Error( | ||
| `ReactGridLayout: ${contextName}[${i}].${key} must be a number! Received: ${value} (${typeof value})` | ||
| ); | ||
| } | ||
| } | ||
| if (typeof item.i !== "undefined" && typeof item.i !== "string") { | ||
| throw new Error( | ||
| `ReactGridLayout: ${contextName}[${i}].i must be a string! Received: ${ | ||
| item.i | ||
| } (${typeof item.i})` | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| // Legacy support for verticalCompact: false | ||
| export function compactType( | ||
| props: ?{ verticalCompact: boolean, compactType: CompactType } | ||
| ): CompactType { | ||
| const { verticalCompact, compactType } = props || {}; | ||
| return verticalCompact === false ? null : compactType; | ||
| } | ||
| function log(...args) { | ||
| if (!DEBUG) return; | ||
| // eslint-disable-next-line no-console | ||
| console.log(...args); | ||
| } | ||
| export const noop = () => {}; |
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
923362
3.39%66
83.33%8439
26.83%1266
102.88%10
-66.67%1
-75%49
13.95%