{"id":13394444,"url":"https://github.com/react-grid-layout/react-grid-layout","last_synced_at":"2026-03-11T19:31:40.485Z","repository":{"id":25116961,"uuid":"28538501","full_name":"react-grid-layout/react-grid-layout","owner":"react-grid-layout","description":"A draggable and resizable grid layout with responsive breakpoints, for React.","archived":false,"fork":false,"pushed_at":"2026-03-01T02:05:39.000Z","size":18909,"stargazers_count":22091,"open_issues_count":74,"forks_count":2701,"subscribers_count":229,"default_branch":"master","last_synced_at":"2026-03-01T08:44:28.684Z","etag":null,"topics":["drag-and-drop","es2015","grid","javascript","react","resize"],"latest_commit_sha":null,"homepage":"https://react-grid-layout.github.io/react-grid-layout/examples/00-showcase.html","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/react-grid-layout.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-12-27T14:28:40.000Z","updated_at":"2026-03-01T05:56:27.000Z","dependencies_parsed_at":"2024-06-18T10:45:51.432Z","dependency_job_id":"e4a7ef19-7738-4d18-9eed-68e6aec61ebc","html_url":"https://github.com/react-grid-layout/react-grid-layout","commit_stats":{"total_commits":713,"total_committers":132,"mean_commits":5.401515151515151,"dds":0.300140252454418,"last_synced_commit":"915613d54b92afc4dbf6804ffac588d9e2987b09"},"previous_names":["strml/react-grid-layout"],"tags_count":124,"template":false,"template_full_name":null,"purl":"pkg:github/react-grid-layout/react-grid-layout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-grid-layout%2Freact-grid-layout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-grid-layout%2Freact-grid-layout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-grid-layout%2Freact-grid-layout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-grid-layout%2Freact-grid-layout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/react-grid-layout","download_url":"https://codeload.github.com/react-grid-layout/react-grid-layout/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-grid-layout%2Freact-grid-layout/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30395597,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T18:46:22.935Z","status":"ssl_error","status_checked_at":"2026-03-11T18:46:17.045Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drag-and-drop","es2015","grid","javascript","react","resize"],"created_at":"2024-07-30T17:01:19.938Z","updated_at":"2026-03-11T19:31:40.478Z","avatar_url":"https://github.com/react-grid-layout.png","language":"TypeScript","readme":"# React-Grid-Layout\n\n[![npm package](https://img.shields.io/npm/v/react-grid-layout.svg?style=flat-square)](https://www.npmjs.org/package/react-grid-layout)\n[![npm downloads](https://img.shields.io/npm/dt/react-grid-layout.svg?maxAge=2592000)]()\n\nReact-Grid-Layout is a grid layout system much like [Packery](http://packery.metafizzy.co/) or\n[Gridster](http://dsmorse.github.io/gridster.js/), for React.\n\nUnlike those systems, it is responsive and supports breakpoints. Breakpoint layouts can be provided by the user\nor autogenerated.\n\nRGL is React-only and does not require jQuery.\n\n![BitMEX UI](http://i.imgur.com/oo1NT6c.gif)\n\n\u003e GIF from production usage on [BitMEX.com](https://www.bitmex.com)\n\n[**[Demo](https://react-grid-layout.github.io/react-grid-layout/) | [Changelog](/CHANGELOG.md) | [CodeSandbox Editable demo](https://codesandbox.io/p/sandbox/5ywf7c)**]\n\n## Table of Contents\n\n- [What's New in v2](#whats-new-in-v2)\n- [Migrating from v1](#migrating-from-v1)\n- [Demos](#demos)\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Responsive Usage](#responsive-usage)\n- [Providing Grid Width](#providing-grid-width)\n- [Hooks API](#hooks-api)\n- [API Reference](#api-reference)\n- [Extending: Custom Compactors \u0026 Position Strategies](#extending-custom-compactors--position-strategies)\n- [Extras](#extras)\n- [Performance](#performance)\n- [Contribute](#contribute)\n\n## What's New in v2\n\nVersion 2 is a complete TypeScript rewrite with a modernized API:\n\n- **Full TypeScript support** - First-class types, no more `@types/react-grid-layout`\n- **React Hooks** - New `useContainerWidth`, `useGridLayout`, and `useResponsiveLayout` hooks\n- **Composable Configuration** - Group related props into focused interfaces:\n  - `gridConfig` - cols, rowHeight, margin, padding\n  - `dragConfig` - enable, handle, cancel, bounded\n  - `resizeConfig` - enable, handles\n  - `positionStrategy` - transform vs absolute positioning\n  - `compactor` - vertical, horizontal, or custom algorithms\n- **Modular architecture** - Import only what you need:\n  - `react-grid-layout` - React components and hooks (v2 API)\n  - `react-grid-layout/core` - Pure layout algorithms (framework-agnostic)\n  - `react-grid-layout/legacy` - v1 flat props API for migration\n  - `react-grid-layout/extras` - Optional components like `GridBackground`\n- **Smaller bundle** - Tree-shakeable ESM and CJS builds\n\n### Breaking Changes\n\nSee the [RFC](./rfcs/0001-v2-typescript-rewrite.md#breaking-changes-in-v2) for detailed migration examples.\n\n| Change                                                                                                               | Description                                                                                            |\n| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |\n| [`width` prop required](./rfcs/0001-v2-typescript-rewrite.md#breaking-changes-in-v2)                                 | Use `useContainerWidth` hook or provide your own measurement                                           |\n| [`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               |\n| [Immutable callbacks](./rfcs/0001-v2-typescript-rewrite.md#2-immutable-callback-parameters)                          | Callback parameters are read-only. Use `onLayoutChange` or constraints instead of mutation             |\n| [`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`                                 |\n| [Pluggable compaction](./rfcs/0001-v2-typescript-rewrite.md#4-pluggable-compaction-algorithms)                       | Compaction is now pluggable via `Compactor` interface. Optional fast O(n log n) algorithm in `/extras` |\n| UMD bundle removed                                                                                                   | Use a bundler (Vite, webpack, esbuild)                                                                 |\n| `verticalCompact` removed                                                                                            | Use `compactType={null}` or `compactor={noCompactor}`                                                  |\n\n## Migrating from v1\n\n**Quick migration** - change your import to use the legacy wrapper:\n\n```diff\n- import GridLayout, { Responsive, WidthProvider } from 'react-grid-layout';\n+ import GridLayout, { Responsive, WidthProvider } from 'react-grid-layout/legacy';\n```\n\nThis provides **100% runtime API compatibility** with v1.\n\n**TypeScript users**: If you were using `@types/react-grid-layout`, note that v2 includes its own types with some naming changes:\n\n| Old (`@types/react-grid-layout`) | New (v2)            | Notes                   |\n| -------------------------------- | ------------------- | ----------------------- |\n| `RGL.Layout`                     | `LayoutItem`        | Single grid item        |\n| `RGL.Layout[]`                   | `Layout`            | Array of items          |\n| `RGL.Layouts`                    | `ResponsiveLayouts` | Breakpoint → layout map |\n\n```diff\n- import RGL from 'react-grid-layout';\n- const item: RGL.Layout = { i: 'a', x: 0, y: 0, w: 1, h: 1 };\n- const layouts: RGL.Layouts = { lg: [item] };\n+ import { LayoutItem, ResponsiveLayouts } from 'react-grid-layout/legacy';\n+ const item: LayoutItem = { i: 'a', x: 0, y: 0, w: 1, h: 1 };\n+ const layouts: ResponsiveLayouts = { lg: [item] };\n```\n\n**Full migration** - adopt the v2 API for new features and better tree-shaking:\n\n```typescript\nimport ReactGridLayout, { useContainerWidth, verticalCompactor } from 'react-grid-layout';\n\nfunction MyGrid() {\n  const { width, containerRef, mounted } = useContainerWidth();\n\n  return (\n    \u003cdiv ref={containerRef}\u003e\n      {mounted \u0026\u0026 (\n        \u003cReactGridLayout\n          width={width}\n          layout={layout}\n          gridConfig={{ cols: 12, rowHeight: 30 }}\n          dragConfig={{ enabled: true, handle: '.handle' }}\n          compactor={verticalCompactor}\n        \u003e\n          {children}\n        \u003c/ReactGridLayout\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\n| Use Case             | Recommendation                     |\n| -------------------- | ---------------------------------- |\n| Existing v1 codebase | `react-grid-layout/legacy`         |\n| New project          | v2 API with hooks                  |\n| Custom compaction    | v2 with custom `Compactor`         |\n| SSR                  | v2 with `measureBeforeMount: true` |\n\n## Demos\n\n1. [Showcase](https://react-grid-layout.github.io/react-grid-layout/examples/00-showcase.html)\n1. [Basic](https://react-grid-layout.github.io/react-grid-layout/examples/01-basic.html)\n1. [No Dragging/Resizing (Layout Only)](https://react-grid-layout.github.io/react-grid-layout/examples/02-no-dragging.html)\n1. [Messy Layout Autocorrect](https://react-grid-layout.github.io/react-grid-layout/examples/03-messy.html)\n1. [Layout Defined on Children](https://react-grid-layout.github.io/react-grid-layout/examples/04-grid-property.html)\n1. [Static Elements](https://react-grid-layout.github.io/react-grid-layout/examples/05-static-elements.html)\n1. [Adding/Removing Elements](https://react-grid-layout.github.io/react-grid-layout/examples/06-dynamic-add-remove.html)\n1. [Saving Layout to LocalStorage](https://react-grid-layout.github.io/react-grid-layout/examples/07-localstorage.html)\n1. [Saving a Responsive Layout to LocalStorage](https://react-grid-layout.github.io/react-grid-layout/examples/08-localstorage-responsive.html)\n1. [Minimum and Maximum Width/Height](https://react-grid-layout.github.io/react-grid-layout/examples/09-min-max-wh.html)\n1. [Dynamic Minimum and Maximum Width/Height](https://react-grid-layout.github.io/react-grid-layout/examples/10-dynamic-min-max-wh.html)\n1. [Toolbox](https://react-grid-layout.github.io/react-grid-layout/examples/11-toolbox.html)\n1. [Drag From Outside](https://react-grid-layout.github.io/react-grid-layout/examples/12-drag-from-outside.html)\n1. [Bounded Layout](https://react-grid-layout.github.io/react-grid-layout/examples/13-bounded.html)\n1. [Responsive Bootstrap-style Layout](https://react-grid-layout.github.io/react-grid-layout/examples/14-responsive-bootstrap-style.html)\n1. [Scaled Containers](https://react-grid-layout.github.io/react-grid-layout/examples/15-scale.html)\n1. [Allow Overlap](https://react-grid-layout.github.io/react-grid-layout/examples/16-allow-overlap.html)\n1. [All Resizable Handles](https://react-grid-layout.github.io/react-grid-layout/examples/17-resizable-handles.html)\n1. [Compactor Showcase](https://react-grid-layout.github.io/react-grid-layout/examples/18-compactors.html)\n1. [Pluggable Constraints](https://react-grid-layout.github.io/react-grid-layout/examples/19-constraints.html)\n1. [Aspect Ratio Constraints](https://react-grid-layout.github.io/react-grid-layout/examples/20-aspect-ratio.html)\n1. [Custom Constraints](https://react-grid-layout.github.io/react-grid-layout/examples/21-custom-constraints.html)\n\n#### Projects Using React-Grid-Layout\n\n- [Basedash](https://www.basedash.com)\n- [BitMEX](https://www.bitmex.com/)\n- [AWS CloudFront Dashboards](https://aws.amazon.com/blogs/aws/cloudwatch-dashboards-create-use-customized-metrics-views/)\n- [Grafana](https://grafana.com/)\n- [Metabase](http://www.metabase.com/)\n- [HubSpot](http://www.hubspot.com)\n- [Kibana](https://www.elastic.co/products/kibana)\n- [Monday](https://support.monday.com/hc/en-us/articles/360002187819-What-are-the-Dashboards-)\n\n_Know of others? Create a PR to let me know!_\n\n## Features\n\n- 100% React - no jQuery\n- Full TypeScript support\n- Compatible with server-rendered apps\n- Draggable widgets\n- Resizable widgets\n- Static widgets\n- Configurable packing: horizontal, vertical, or off\n- Bounds checking for dragging and resizing\n- Widgets may be added or removed without rebuilding grid\n- Layout can be serialized and restored\n- Responsive breakpoints\n- Separate layouts per responsive breakpoint\n- Grid Items placed using CSS Transforms\n- Compatibility with `\u003cReact.StrictMode\u003e`\n\n| Version   | Compatibility         |\n| --------- | --------------------- |\n| \u003e= 2.0.0  | React 18+, TypeScript |\n| \u003e= 0.17.0 | React 16 \u0026 17         |\n\n## Installation\n\n```bash\nnpm install react-grid-layout\n```\n\nInclude the stylesheets in your application:\n\n```js\nimport \"react-grid-layout/css/styles.css\";\nimport \"react-resizable/css/styles.css\";\n```\n\nOr link them directly:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"/node_modules/react-grid-layout/css/styles.css\" /\u003e\n\u003clink rel=\"stylesheet\" href=\"/node_modules/react-resizable/css/styles.css\" /\u003e\n```\n\n## Quick Start\n\n```tsx\nimport ReactGridLayout, { useContainerWidth } from \"react-grid-layout\";\nimport \"react-grid-layout/css/styles.css\";\nimport \"react-resizable/css/styles.css\";\n\nfunction MyGrid() {\n  const { width, containerRef, mounted } = useContainerWidth();\n\n  const layout = [\n    { i: \"a\", x: 0, y: 0, w: 1, h: 2, static: true },\n    { i: \"b\", x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 },\n    { i: \"c\", x: 4, y: 0, w: 1, h: 2 }\n  ];\n\n  return (\n    \u003cdiv ref={containerRef}\u003e\n      {mounted \u0026\u0026 (\n        \u003cReactGridLayout\n          layout={layout}\n          width={width}\n          gridConfig={{ cols: 12, rowHeight: 30 }}\n        \u003e\n          \u003cdiv key=\"a\"\u003ea\u003c/div\u003e\n          \u003cdiv key=\"b\"\u003eb\u003c/div\u003e\n          \u003cdiv key=\"c\"\u003ec\u003c/div\u003e\n        \u003c/ReactGridLayout\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\nYou can also define layout on children using `data-grid`:\n\n```tsx\n\u003cReactGridLayout width={width} gridConfig={{ cols: 12, rowHeight: 30 }}\u003e\n  \u003cdiv key=\"a\" data-grid={{ x: 0, y: 0, w: 1, h: 2, static: true }}\u003e\n    a\n  \u003c/div\u003e\n  \u003cdiv key=\"b\" data-grid={{ x: 1, y: 0, w: 3, h: 2 }}\u003e\n    b\n  \u003c/div\u003e\n  \u003cdiv key=\"c\" data-grid={{ x: 4, y: 0, w: 1, h: 2 }}\u003e\n    c\n  \u003c/div\u003e\n\u003c/ReactGridLayout\u003e\n```\n\n## Responsive Usage\n\nUse `Responsive` for automatic breakpoint handling:\n\n```tsx\nimport { Responsive, useContainerWidth } from \"react-grid-layout\";\n\nfunction MyResponsiveGrid() {\n  const { width, containerRef, mounted } = useContainerWidth();\n\n  const layouts = {\n    lg: [{ i: \"1\", x: 0, y: 0, w: 2, h: 2 }],\n    md: [{ i: \"1\", x: 0, y: 0, w: 2, h: 2 }]\n  };\n\n  return (\n    \u003cdiv ref={containerRef}\u003e\n      {mounted \u0026\u0026 (\n        \u003cResponsive\n          layouts={layouts}\n          breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}\n          cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}\n          width={width}\n        \u003e\n          \u003cdiv key=\"1\"\u003e1\u003c/div\u003e\n          \u003cdiv key=\"2\"\u003e2\u003c/div\u003e\n          \u003cdiv key=\"3\"\u003e3\u003c/div\u003e\n        \u003c/Responsive\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\n## Providing Grid Width\n\nThe `width` prop is required. You have several options:\n\n### Option 1: useContainerWidth Hook (Recommended)\n\n```tsx\nimport ReactGridLayout, { useContainerWidth } from \"react-grid-layout\";\n\nfunction MyGrid() {\n  const { width, containerRef, mounted } = useContainerWidth();\n\n  return (\n    \u003cdiv ref={containerRef}\u003e\n      {mounted \u0026\u0026 \u003cReactGridLayout width={width}\u003e...\u003c/ReactGridLayout\u003e}\n    \u003c/div\u003e\n  );\n}\n```\n\n### Option 2: Fixed Width\n\n```tsx\n\u003cReactGridLayout width={1200}\u003e...\u003c/ReactGridLayout\u003e\n```\n\n### Option 3: CSS Container Queries or ResizeObserver\n\nUse any width measurement library like [react-sizeme](https://github.com/ctrlplusb/react-sizeme) or your own ResizeObserver implementation.\n\n### Option 4: Legacy WidthProvider HOC\n\nFor backwards compatibility, you can still use `WidthProvider`:\n\n```tsx\nimport ReactGridLayout, { WidthProvider } from \"react-grid-layout/legacy\";\n\nconst GridLayoutWithWidth = WidthProvider(ReactGridLayout);\n\nfunction MyGrid() {\n  return \u003cGridLayoutWithWidth\u003e...\u003c/GridLayoutWithWidth\u003e;\n}\n```\n\n## Hooks API\n\nThe v2 API provides three hooks for different use cases. Choose based on your needs:\n\n| Hook                  | Use When                                                             |\n| --------------------- | -------------------------------------------------------------------- |\n| `useContainerWidth`   | You need responsive width measurement (most common)                  |\n| `useGridLayout`       | You're building a custom grid component or need direct state control |\n| `useResponsiveLayout` | You're building a custom responsive grid with breakpoint logic       |\n\n### useContainerWidth\n\nObserves container width using ResizeObserver and provides reactive width updates. This is the recommended way to provide width to the grid.\n\n**Why use it instead of WidthProvider?**\n\n- Hooks are more composable and easier to test\n- No HOC wrapper means simpler component tree\n- Explicit control over when to render (via `mounted`)\n- Works better with SSR\n\n```tsx\nimport { useContainerWidth } from \"react-grid-layout\";\n\nfunction MyGrid() {\n  const { width, containerRef, mounted, measureWidth } = useContainerWidth({\n    measureBeforeMount: false, // Set true for SSR\n    initialWidth: 1280 // Width before first measurement\n  });\n\n  return (\n    \u003cdiv ref={containerRef}\u003e{mounted \u0026\u0026 \u003cReactGridLayout width={width} /\u003e}\u003c/div\u003e\n  );\n}\n```\n\n**Type Definitions:**\n\n```ts\ninterface UseContainerWidthOptions {\n  /** Delay render until width is measured. Useful for SSR. Default: false */\n  measureBeforeMount?: boolean;\n  /** Initial width before measurement. Default: 1280 */\n  initialWidth?: number;\n}\n\ninterface UseContainerWidthResult {\n  /** Current container width in pixels */\n  width: number;\n  /** Whether the container has been measured at least once */\n  mounted: boolean;\n  /** Ref to attach to the container element */\n  containerRef: RefObject\u003cHTMLDivElement | null\u003e;\n  /** Manually trigger a width measurement */\n  measureWidth: () =\u003e void;\n}\n```\n\n### useGridLayout\n\nCore layout state management hook. Use this when you need direct control over drag/resize/drop state, or when building a custom grid component.\n\n**Why use it instead of the component?**\n\n- Full control over layout state and updates\n- Access to drag/resize/drop state for custom UIs\n- Can integrate with external state management\n- Build headless grid implementations\n\n```tsx\nimport { useGridLayout, horizontalCompactor } from \"react-grid-layout\";\n\nfunction CustomGrid({ initialLayout }) {\n  const {\n    layout,\n    setLayout,\n    dragState,\n    resizeState,\n    onDragStart,\n    onDrag,\n    onDragStop,\n    onResizeStart,\n    onResize,\n    onResizeStop,\n    containerHeight,\n    isInteracting,\n    compactor\n  } = useGridLayout({\n    layout: initialLayout,\n    cols: 12,\n    compactor: horizontalCompactor, // default is verticalCompactor\n    onLayoutChange: newLayout =\u003e console.log(\"Layout changed:\", newLayout)\n  });\n\n  // Access drag state for custom placeholder rendering\n  const placeholder = dragState.activeDrag;\n\n  // Check if any interaction is happening\n  if (isInteracting) {\n    // Disable other UI during drag/resize\n  }\n\n  return (\n    \u003cdiv style={{ height: containerHeight * rowHeight }}\u003e\n      {layout.map(item =\u003e (\n        \u003cdiv\n          key={item.i}\n          onMouseDown={() =\u003e onDragStart(item.i, item.x, item.y)}\n        \u003e\n          {item.i}\n        \u003c/div\u003e\n      ))}\n      {placeholder \u0026\u0026 \u003cdiv className=\"placeholder\" /\u003e}\n    \u003c/div\u003e\n  );\n}\n```\n\n**Type Definitions:**\n\n```ts\ninterface UseGridLayoutOptions {\n  /** Initial layout */\n  layout: Layout;\n  /** Number of columns */\n  cols: number;\n  /** Block movement into occupied space instead of pushing items */\n  preventCollision?: boolean;\n  /** Called when layout changes */\n  onLayoutChange?: (layout: Layout) =\u003e void;\n  /** Compactor for layout compaction (default: verticalCompactor) */\n  compactor?: Compactor;\n}\n\ninterface UseGridLayoutResult {\n  /** Current layout */\n  layout: Layout;\n  /** Set layout directly */\n  setLayout: (layout: Layout) =\u003e void;\n  /** Current drag state (activeDrag, oldDragItem, oldLayout) */\n  dragState: DragState;\n  /** Current resize state (resizing, oldResizeItem, oldLayout) */\n  resizeState: ResizeState;\n  /** Current drop state (droppingDOMNode, droppingPosition) */\n  dropState: DropState;\n  /** Start dragging an item */\n  onDragStart: (itemId: string, x: number, y: number) =\u003e LayoutItem | null;\n  /** Update drag position */\n  onDrag: (itemId: string, x: number, y: number) =\u003e void;\n  /** Stop dragging */\n  onDragStop: (itemId: string, x: number, y: number) =\u003e void;\n  /** Start resizing an item */\n  onResizeStart: (itemId: string) =\u003e LayoutItem | null;\n  /** Update resize dimensions */\n  onResize: (\n    itemId: string,\n    w: number,\n    h: number,\n    x?: number,\n    y?: number\n  ) =\u003e void;\n  /** Stop resizing */\n  onResizeStop: (itemId: string, w: number, h: number) =\u003e void;\n  /** Handle external drag over */\n  onDropDragOver: (\n    droppingItem: LayoutItem,\n    position: DroppingPosition\n  ) =\u003e void;\n  /** Handle external drag leave */\n  onDropDragLeave: () =\u003e void;\n  /** Complete external drop */\n  onDrop: (droppingItem: LayoutItem) =\u003e void;\n  /** Container height in grid rows */\n  containerHeight: number;\n  /** Whether any drag/resize/drop is active */\n  isInteracting: boolean;\n  /** The compactor being used */\n  compactor: Compactor;\n}\n```\n\n### useResponsiveLayout\n\nManages responsive breakpoints and generates layouts for different screen sizes. Use this when building a custom responsive grid.\n\n**Why use it instead of the Responsive component?**\n\n- Direct access to current breakpoint\n- Control over layout generation for new breakpoints\n- Can update layouts for specific breakpoints\n- Build custom breakpoint UIs\n\n```tsx\nimport { useContainerWidth, useResponsiveLayout } from \"react-grid-layout\";\n\nfunction CustomResponsiveGrid() {\n  const { width, containerRef, mounted } = useContainerWidth();\n\n  const {\n    layout, // Current layout for active breakpoint\n    layouts, // All layouts by breakpoint\n    breakpoint, // Current active breakpoint ('lg', 'md', etc.)\n    cols, // Column count for current breakpoint\n    setLayoutForBreakpoint,\n    setLayouts,\n    sortedBreakpoints\n  } = useResponsiveLayout({\n    width,\n    breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 },\n    cols: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },\n    layouts: {\n      lg: [{ i: \"1\", x: 0, y: 0, w: 2, h: 2 }],\n      md: [{ i: \"1\", x: 0, y: 0, w: 3, h: 2 }]\n    },\n    // compactor: verticalCompactor (default)\n    onBreakpointChange: (bp, cols) =\u003e\n      console.log(`Now at ${bp} (${cols} cols)`),\n    onLayoutChange: (layout, allLayouts) =\u003e saveToServer(allLayouts)\n  });\n\n  // Show current breakpoint in UI\n  return (\n    \u003cdiv ref={containerRef}\u003e\n      \u003cdiv\u003e\n        Current breakpoint: {breakpoint} ({cols} columns)\n      \u003c/div\u003e\n      {mounted \u0026\u0026 (\n        \u003cGridLayout width={width} cols={cols} layout={layout}\u003e\n          {/* children */}\n        \u003c/GridLayout\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\n**Type Definitions:**\n\n```ts\ninterface UseResponsiveLayoutOptions\u003cB extends string = DefaultBreakpoints\u003e {\n  /** Current container width */\n  width: number;\n  /** Breakpoint definitions (name → min-width). Default: {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0} */\n  breakpoints?: Record\u003cB, number\u003e;\n  /** Column counts per breakpoint. Default: {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2} */\n  cols?: Record\u003cB, number\u003e;\n  /** Layouts for each breakpoint */\n  layouts?: Partial\u003cRecord\u003cB, Layout\u003e\u003e;\n  /** Compactor for layout compaction (default: verticalCompactor) */\n  compactor?: Compactor;\n  /** Called when breakpoint changes */\n  onBreakpointChange?: (newBreakpoint: B, cols: number) =\u003e void;\n  /** Called when layout changes */\n  onLayoutChange?: (layout: Layout, layouts: Record\u003cB, Layout\u003e) =\u003e void;\n  /** Called when width changes */\n  onWidthChange?: (\n    width: number,\n    margin: [number, number],\n    cols: number,\n    padding: [number, number] | null\n  ) =\u003e void;\n}\n\ninterface UseResponsiveLayoutResult\u003cB extends string = DefaultBreakpoints\u003e {\n  /** Current layout for the active breakpoint */\n  layout: Layout;\n  /** All layouts by breakpoint */\n  layouts: Partial\u003cRecord\u003cB, Layout\u003e\u003e;\n  /** Current active breakpoint */\n  breakpoint: B;\n  /** Column count for the current breakpoint */\n  cols: number;\n  /** Update layout for a specific breakpoint */\n  setLayoutForBreakpoint: (breakpoint: B, layout: Layout) =\u003e void;\n  /** Update all layouts */\n  setLayouts: (layouts: Partial\u003cRecord\u003cB, Layout\u003e\u003e) =\u003e void;\n  /** Sorted array of breakpoint names (smallest to largest) */\n  sortedBreakpoints: B[];\n}\n\ntype DefaultBreakpoints = \"lg\" | \"md\" | \"sm\" | \"xs\" | \"xxs\";\n```\n\n## API Reference\n\n### ReactGridLayout Props\n\nThe v2 API uses composable configuration interfaces for cleaner prop organization:\n\n```ts\ninterface ReactGridLayoutProps {\n  // Required\n  children: React.ReactNode;\n  width: number; // Container width in pixels\n\n  // Configuration interfaces (see below for details)\n  gridConfig?: Partial\u003cGridConfig\u003e; // Grid measurement settings\n  dragConfig?: Partial\u003cDragConfig\u003e; // Drag behavior settings\n  resizeConfig?: Partial\u003cResizeConfig\u003e; // Resize behavior settings\n  dropConfig?: Partial\u003cDropConfig\u003e; // External drop settings\n  positionStrategy?: PositionStrategy; // CSS positioning strategy\n  compactor?: Compactor; // Layout compaction strategy\n\n  // Layout data\n  layout?: Layout; // Layout definition\n  droppingItem?: LayoutItem; // Item configuration when dropping from outside\n\n  // Container\n  autoSize?: boolean; // Auto-size container height (default: true)\n  className?: string;\n  style?: React.CSSProperties;\n  innerRef?: React.Ref\u003cHTMLDivElement\u003e;\n\n  // Callbacks\n  onLayoutChange?: (layout: Layout) =\u003e void;\n  onDragStart?: EventCallback;\n  onDrag?: EventCallback;\n  onDragStop?: EventCallback;\n  onResizeStart?: EventCallback;\n  onResize?: EventCallback;\n  onResizeStop?: EventCallback;\n  onDrop?: (layout: Layout, item: LayoutItem | undefined, e: Event) =\u003e void;\n  onDropDragOver?: (e: DragEvent) =\u003e { w?: number; h?: number } | false | void;\n}\n```\n\n### GridConfig\n\nGrid measurement configuration:\n\n```ts\ninterface GridConfig {\n  cols: number; // Number of columns (default: 12)\n  rowHeight: number; // Row height in pixels (default: 150)\n  margin: [number, number]; // [x, y] margin between items (default: [10, 10])\n  containerPadding: [number, number] | null; // Container padding (default: null, uses margin)\n  maxRows: number; // Maximum rows (default: Infinity)\n}\n```\n\n### DragConfig\n\nDrag behavior configuration:\n\n```ts\ninterface DragConfig {\n  enabled: boolean; // Enable dragging (default: true)\n  bounded: boolean; // Keep items within container (default: false)\n  handle?: string; // CSS selector for drag handle\n  cancel?: string; // CSS selector to cancel dragging\n  threshold: number; // Pixels to move before drag starts (default: 3)\n}\n```\n\n### ResizeConfig\n\nResize behavior configuration:\n\n```ts\ninterface ResizeConfig {\n  enabled: boolean; // Enable resizing (default: true)\n  handles: ResizeHandleAxis[]; // Handle positions (default: ['se'])\n  handleComponent?: React.ReactNode | ((axis, ref) =\u003e React.ReactNode);\n}\n```\n\n### DropConfig\n\nExternal drop configuration:\n\n```ts\ninterface DropConfig {\n  enabled: boolean; // Allow external drops (default: false)\n  defaultItem: { w: number; h: number }; // Default size (default: { w: 1, h: 1 })\n  onDragOver?: (e: DragEvent) =\u003e { w?: number; h?: number } | false | void;\n}\n```\n\n### PositionStrategy\n\nCSS positioning strategy. Built-in options:\n\n```ts\nimport {\n  transformStrategy, // Default: use CSS transforms\n  absoluteStrategy, // Use top/left positioning\n  createScaledStrategy // For scaled containers\n} from \"react-grid-layout/core\";\n\n// Example: scaled container\n\u003cdiv style={{ transform: 'scale(0.5)' }}\u003e\n  \u003cReactGridLayout positionStrategy={createScaledStrategy(0.5)} ... /\u003e\n\u003c/div\u003e\n```\n\n### Compactor\n\nLayout compaction strategy. Built-in options:\n\n```ts\nimport {\n  verticalCompactor, // Default: compact items upward\n  horizontalCompactor, // Compact items leftward\n  noCompactor, // No compaction (free positioning)\n  getCompactor // Factory: getCompactor('vertical', allowOverlap, preventCollision)\n} from \"react-grid-layout/core\";\n```\n\n### ResponsiveGridLayout Props\n\nExtends `GridLayoutProps` with responsive-specific props:\n\n```ts\ninterface ResponsiveGridLayoutProps\u003cB extends string = string\u003e {\n  // Responsive configuration\n  breakpoint?: B; // Current breakpoint (auto-detected)\n  breakpoints?: Record\u003cB, number\u003e; // Breakpoint definitions (default: {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0})\n  cols?: Record\u003cB, number\u003e; // Columns per breakpoint (default: {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2})\n  layouts?: Record\u003cB, Layout\u003e; // Layouts per breakpoint\n\n  // Can be fixed or per-breakpoint\n  margin?: [number, number] | Partial\u003cRecord\u003cB, [number, number]\u003e\u003e;\n  containerPadding?:\n    | [number, number]\n    | Partial\u003cRecord\u003cB, [number, number] | null\u003e\u003e\n    | null;\n\n  // Callbacks\n  onBreakpointChange?: (newBreakpoint: B, cols: number) =\u003e void;\n  onLayoutChange?: (layout: Layout, layouts: Record\u003cB, Layout\u003e) =\u003e void;\n  onWidthChange?: (\n    width: number,\n    margin: [number, number],\n    cols: number,\n    padding: [number, number] | null\n  ) =\u003e void;\n}\n```\n\n### Layout Item\n\n```ts\ninterface LayoutItem {\n  i: string; // Unique identifier (must match child key)\n  x: number; // X position in grid units\n  y: number; // Y position in grid units\n  w: number; // Width in grid units\n  h: number; // Height in grid units\n  minW?: number; // Minimum width (default: 0)\n  maxW?: number; // Maximum width (default: Infinity)\n  minH?: number; // Minimum height (default: 0)\n  maxH?: number; // Maximum height (default: Infinity)\n  static?: boolean; // If true, not draggable or resizable\n  isDraggable?: boolean; // Override grid isDraggable\n  isResizable?: boolean; // Override grid isResizable\n  isBounded?: boolean; // Override grid isBounded\n  resizeHandles?: Array\u003c\"s\" | \"w\" | \"e\" | \"n\" | \"sw\" | \"nw\" | \"se\" | \"ne\"\u003e;\n}\n```\n\n### Core Utilities\n\nImport pure layout functions from `react-grid-layout/core`:\n\n```ts\nimport {\n  verticalCompactor,\n  horizontalCompactor,\n  noCompactor,\n  getCompactor,\n  moveElement,\n  collides,\n  getFirstCollision,\n  validateLayout\n  // ... and more\n} from \"react-grid-layout/core\";\n```\n\n\u003e **Note**: The `compact()` function is not exported. Use compactors instead: `verticalCompactor.compact(layout, cols)` or get one via `getCompactor('vertical')`.\n\n## Extending: Custom Compactors \u0026 Position Strategies\n\n### Creating a Custom Compactor\n\nCompactors control how items are arranged after drag/resize. Create your own for custom layouts like masonry, gravity, or shelf-packing.\n\n**The Compactor Interface:**\n\n```ts\ninterface Compactor {\n  /** Identifies the compaction type */\n  type: \"vertical\" | \"horizontal\" | null | string;\n\n  /**\n   * Whether items can overlap each other.\n   *\n   * When true:\n   * - Items can be placed on top of other items\n   * - Dragging into another item does NOT push it away\n   * - Compaction is skipped after drag/resize\n   *\n   * Use for: layered dashboards, free-form layouts\n   */\n  allowOverlap: boolean;\n\n  /**\n   * Whether to block movement that would cause collision.\n   *\n   * When true (and allowOverlap is false):\n   * - Dragging into another item is blocked (item snaps back)\n   * - Other items are NOT pushed away\n   * - Only affects movement, not compaction\n   *\n   * Use with noCompactor for: fixed grids, slot-based layouts\n   *\n   * Note: Has no effect when allowOverlap is true.\n   */\n  preventCollision?: boolean;\n\n  /**\n   * Compact the entire layout.\n   * Called after any layout change to fill gaps.\n   *\n   * @param layout - Array of layout items (clone before mutating!)\n   * @param cols - Number of grid columns\n   * @returns New compacted layout\n   */\n  compact(layout: Layout, cols: number): Layout;\n}\n```\n\n**Example: Gravity Compactor (items fall to bottom)**\n\n```ts\nimport { cloneLayout, cloneLayoutItem, getStatics, bottom } from \"react-grid-layout/core\";\n\nconst gravityCompactor: Compactor = {\n  type: \"gravity\",\n  allowOverlap: false,\n\n  compact(layout, cols) {\n    const statics = getStatics(layout);\n    const maxY = 100; // arbitrary max height\n    const out = [];\n\n    // Sort by Y descending (process bottom items first)\n    const sorted = [...layout].sort((a, b) =\u003e b.y - a.y);\n\n    for (const item of sorted) {\n      const l = cloneLayoutItem(item);\n\n      if (!l.static) {\n        // Move down as far as possible\n        while (l.y \u003c maxY \u0026\u0026 !collides(l, statics)) {\n          l.y++;\n        }\n        l.y--; // Back up one\n      }\n\n      out.push(l);\n    }\n\n    return out;\n  }\n};\n\n// Usage\n\u003cGridLayout compactor={gravityCompactor} /\u003e\n```\n\n**Example: Single Row Compactor (horizontal shelf)**\n\n```ts\nconst singleRowCompactor: Compactor = {\n  type: \"shelf\",\n  allowOverlap: false,\n\n  compact(layout, cols) {\n    let x = 0;\n    const out = [];\n\n    // Sort by original X position\n    const sorted = [...layout].sort((a, b) =\u003e a.x - b.x);\n\n    for (const item of sorted) {\n      const l = cloneLayoutItem(item);\n      if (!l.static) {\n        l.x = x;\n        l.y = 0; // All items on row 0\n        x += l.w;\n\n        // Wrap to next row if overflow\n        if (x \u003e cols) {\n          l.x = 0;\n          x = l.w;\n        }\n      }\n      out.push(l);\n    }\n\n    return out;\n  }\n};\n```\n\n**Using Helper Functions:**\n\nThe core module exports helpers for building compactors:\n\n```ts\nimport {\n  resolveCompactionCollision, // Move items to resolve overlaps\n  compactItemVertical, // Compact one item upward\n  compactItemHorizontal, // Compact one item leftward\n  getFirstCollision, // Find first collision\n  collides, // Check if two items collide\n  getStatics, // Get static items from layout\n  cloneLayout, // Clone layout array\n  cloneLayoutItem // Clone single item\n} from \"react-grid-layout/core\";\n```\n\n### Creating a Custom Position Strategy\n\nPosition strategies control how items are positioned via CSS. Create custom strategies for special transform handling.\n\n**The PositionStrategy Interface:**\n\n```ts\ninterface PositionStrategy {\n  /** Type identifier */\n  type: \"transform\" | \"absolute\" | string;\n\n  /** Scale factor for coordinate calculations */\n  scale: number;\n\n  /**\n   * Generate CSS styles for positioning an item.\n   *\n   * @param pos - Position with top, left, width, height in pixels\n   * @returns CSS properties object\n   */\n  calcStyle(pos: Position): React.CSSProperties;\n\n  /**\n   * Calculate drag position from mouse coordinates.\n   * Used during drag to convert screen coords to grid coords.\n   *\n   * @param clientX - Mouse X position\n   * @param clientY - Mouse Y position\n   * @param offsetX - Offset from item left edge\n   * @param offsetY - Offset from item top edge\n   * @returns Calculated left/top position\n   */\n  calcDragPosition(\n    clientX: number,\n    clientY: number,\n    offsetX: number,\n    offsetY: number\n  ): { left: number; top: number };\n}\n```\n\n**Example: Rotated Container Strategy**\n\n```ts\nconst createRotatedStrategy = (angleDegrees: number): PositionStrategy =\u003e {\n  const angleRad = (angleDegrees * Math.PI) / 180;\n  const cos = Math.cos(angleRad);\n  const sin = Math.sin(angleRad);\n\n  return {\n    type: \"rotated\",\n    scale: 1,\n\n    calcStyle(pos) {\n      // Apply rotation to position\n      const rotatedX = pos.left * cos - pos.top * sin;\n      const rotatedY = pos.left * sin + pos.top * cos;\n\n      return {\n        transform: `translate(${rotatedX}px, ${rotatedY}px)`,\n        width: `${pos.width}px`,\n        height: `${pos.height}px`,\n        position: \"absolute\"\n      };\n    },\n\n    calcDragPosition(clientX, clientY, offsetX, offsetY) {\n      // Reverse the rotation for drag calculations\n      const x = clientX - offsetX;\n      const y = clientY - offsetY;\n\n      return {\n        left: x * cos + y * sin,\n        top: -x * sin + y * cos\n      };\n    }\n  };\n};\n\n// Usage: grid inside a rotated container\n\u003cdiv style={{ transform: 'rotate(45deg)' }}\u003e\n  \u003cGridLayout positionStrategy={createRotatedStrategy(45)} /\u003e\n\u003c/div\u003e\n```\n\n**Example: 3D Perspective Strategy**\n\n```ts\nconst create3DStrategy = (\n  perspective: number,\n  rotateX: number\n): PositionStrategy =\u003e ({\n  type: \"3d\",\n  scale: 1,\n\n  calcStyle(pos) {\n    return {\n      transform: `\n        perspective(${perspective}px)\n        rotateX(${rotateX}deg)\n        translate3d(${pos.left}px, ${pos.top}px, 0)\n      `,\n      width: `${pos.width}px`,\n      height: `${pos.height}px`,\n      position: \"absolute\",\n      transformStyle: \"preserve-3d\"\n    };\n  },\n\n  calcDragPosition(clientX, clientY, offsetX, offsetY) {\n    // Adjust for perspective foreshortening\n    const perspectiveFactor = 1 + clientY / perspective;\n    return {\n      left: (clientX - offsetX) / perspectiveFactor,\n      top: (clientY - offsetY) / perspectiveFactor\n    };\n  }\n});\n```\n\n## Extras\n\nThe `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.\n\n### GridBackground\n\nRenders an SVG grid background that aligns with GridLayout cells. Use this to visualize the grid structure behind your layout.\n\n\u003e Based on [PR #2175](https://github.com/react-grid-layout/react-grid-layout/pull/2175) by [@dmj900501](https://github.com/dmj900501).\n\n```tsx\nimport { GridBackground } from \"react-grid-layout/extras\";\nimport ReactGridLayout, { useContainerWidth } from \"react-grid-layout\";\n\nfunction MyGrid() {\n  const { width, containerRef, mounted } = useContainerWidth();\n\n  return (\n    \u003cdiv ref={containerRef} style={{ position: \"relative\" }}\u003e\n      {mounted \u0026\u0026 (\n        \u003c\u003e\n          \u003cGridBackground\n            width={width}\n            cols={12}\n            rowHeight={30}\n            margin={[10, 10]}\n            rows={10}\n            color=\"#f0f0f0\"\n            borderRadius={4}\n          /\u003e\n          \u003cReactGridLayout\n            width={width}\n            gridConfig={{ cols: 12, rowHeight: 30, margin: [10, 10] }}\n          \u003e\n            {children}\n          \u003c/ReactGridLayout\u003e\n        \u003c/\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\n**Props:**\n\n```ts\ninterface GridBackgroundProps {\n  // Required - must match your GridLayout config\n  width: number; // Container width\n  cols: number; // Number of columns\n  rowHeight: number; // Row height in pixels\n\n  // Optional\n  margin?: [number, number]; // Gap between cells (default: [10, 10])\n  containerPadding?: [number, number] | null; // Container padding (default: uses margin)\n  rows?: number | \"auto\"; // Number of rows to display (default: 10)\n  height?: number; // Used when rows=\"auto\" to calculate row count\n  color?: string; // Cell background color (default: \"#e0e0e0\")\n  borderRadius?: number; // Cell border radius (default: 4)\n  className?: string; // Additional CSS class\n  style?: React.CSSProperties; // Additional inline styles\n}\n```\n\n### Fast Compactors\n\nFor large layouts (200+ items), the standard compactors can become slow due to O(n²) collision resolution. The fast compactors use optimized algorithms with O(n log n) complexity.\n\n\u003e Based on the \"rising tide\" algorithm from [PR #2152](https://github.com/react-grid-layout/react-grid-layout/pull/2152) by [@morris](https://github.com/morris).\n\n```tsx\nimport {\n  fastVerticalCompactor,\n  fastHorizontalCompactor,\n  fastVerticalOverlapCompactor,\n  fastHorizontalOverlapCompactor\n} from \"react-grid-layout/extras\";\n\n\u003cReactGridLayout\n  compactor={fastVerticalCompactor}\n  // or compactor={fastHorizontalCompactor}\n  layout={layout}\n  width={width}\n/\u003e;\n```\n\n**Performance Benchmarks:**\n\n| Items | Standard Vertical | Fast Vertical | Speedup |\n| ----- | ----------------- | ------------- | ------- |\n| 50    | 112 µs            | 19 µs         | **6x**  |\n| 100   | 203 µs            | 36 µs         | **6x**  |\n| 200   | 821 µs            | 51 µs         | **16x** |\n| 500   | 5.7 ms            | 129 µs        | **45x** |\n\n| Items | Standard Horizontal | Fast Horizontal | Speedup |\n| ----- | ------------------- | --------------- | ------- |\n| 50    | 164 µs              | 12 µs           | **14x** |\n| 100   | 477 µs              | 25 µs           | **19x** |\n| 200   | 1.1 ms              | 42 µs           | **26x** |\n| 500   | 9.5 ms              | 128 µs          | **74x** |\n\n**Correctness:**\n\nThe fast compactors produce layouts identical to the standard compactors:\n\n- **Vertical**: 0% height difference on deterministic 100-item layouts\n- **Horizontal**: 0% width difference on deterministic 100-item layouts\n- Both pass all correctness tests: no overlaps, idempotent, static item handling\n\n**When to use:**\n\n- Use fast compactors for dashboards with 200+ widgets\n- For smaller layouts (\u003c100 items), standard compactors work equally well\n- Both standard and fast compactors produce valid, non-overlapping layouts\n\n### calcGridCellDimensions (Core Utility)\n\nFor building custom grid overlays or backgrounds, use the `calcGridCellDimensions` utility from `react-grid-layout/core`:\n\n```ts\nimport { calcGridCellDimensions } from \"react-grid-layout/core\";\n\nconst dims = calcGridCellDimensions({\n  width: 1200,\n  cols: 12,\n  rowHeight: 30,\n  margin: [10, 10],\n  containerPadding: [20, 20]\n});\n\n// dims = {\n//   cellWidth: 88.33,  // Width of each cell\n//   cellHeight: 30,     // Height of each cell (= rowHeight)\n//   offsetX: 20,        // Left padding\n//   offsetY: 20,        // Top padding\n//   gapX: 10,           // Horizontal gap between cells\n//   gapY: 10,           // Vertical gap between cells\n//   cols: 12,           // Column count\n//   containerWidth: 1200\n// }\n```\n\nThis is useful for building custom visualizations, snap-to-grid functionality, or integrating with canvas/WebGL renderers.\n\n## Performance\n\n### Memoize Children\n\nThe grid compares children by reference. Memoize them for better performance:\n\n```tsx\nfunction MyGrid({ count, width }) {\n  const children = useMemo(() =\u003e {\n    return Array.from({ length: count }, (_, i) =\u003e (\n      \u003cdiv\n        key={i}\n        data-grid={{ x: i % 12, y: Math.floor(i / 12), w: 1, h: 1 }}\n      /\u003e\n    ));\n  }, [count]);\n\n  return (\n    \u003cReactGridLayout width={width} gridConfig={{ cols: 12 }}\u003e\n      {children}\n    \u003c/ReactGridLayout\u003e\n  );\n}\n```\n\n### Avoid Creating Components in Render (Legacy WidthProvider)\n\nIf using the legacy WidthProvider HOC, don't create the component during render:\n\n```tsx\nimport ReactGridLayout, { WidthProvider } from \"react-grid-layout/legacy\";\n\n// Bad - creates new component every render\nfunction MyGrid() {\n  const GridLayoutWithWidth = WidthProvider(ReactGridLayout);\n  return \u003cGridLayoutWithWidth\u003e...\u003c/GridLayoutWithWidth\u003e;\n}\n\n// Good - create once outside or with useMemo\nconst GridLayoutWithWidth = WidthProvider(ReactGridLayout);\n\nfunction MyGrid() {\n  return \u003cGridLayoutWithWidth\u003e...\u003c/GridLayoutWithWidth\u003e;\n}\n```\n\nWith the v2 API, use `useContainerWidth` hook instead to avoid this issue entirely.\n\n## Custom Child Components\n\nGrid children must forward refs and certain props:\n\n```tsx\nconst CustomItem = forwardRef\u003cHTMLDivElement, CustomItemProps\u003e(\n  (\n    {\n      style,\n      className,\n      onMouseDown,\n      onMouseUp,\n      onTouchEnd,\n      children,\n      ...props\n    },\n    ref\n  ) =\u003e {\n    return (\n      \u003cdiv\n        ref={ref}\n        style={style}\n        className={className}\n        onMouseDown={onMouseDown}\n        onMouseUp={onMouseUp}\n        onTouchEnd={onTouchEnd}\n      \u003e\n        {children}\n      \u003c/div\u003e\n    );\n  }\n);\n```\n\n## Contribute\n\nIf you have a feature request, please add it as an issue or make a pull request.\n\nIf you have a bug to report, please reproduce the bug in [CodeSandbox](https://codesandbox.io/p/sandbox/5ywf7c) to help\nus easily isolate it.\n","funding_links":[],"categories":["JavaScript","九、表格与数据网格","Layout","TypeScript","前端开发框架及项目","Uncategorized","UI Components","📖 Categories","前端常见效果库"],"sub_categories":["3.  Immutable 工具（辅助状态管理）","其他_文本生成、文本对话","Uncategorized","Drag and Drop","Tables \u0026 Grids","拖拽类"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-grid-layout%2Freact-grid-layout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freact-grid-layout%2Freact-grid-layout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-grid-layout%2Freact-grid-layout/lists"}