> ## Documentation Index
> Fetch the complete documentation index at: https://dnd-grid.blode.md/llms.txt
> Use this file to discover all available pages before exploring further.

# Headless wrapper

<div className="not-prose my-6 rounded-lg border border-zinc-200/70 bg-white/70 shadow-sm dark:border-white/10 dark:bg-white/5">
  <iframe
    title="Headless wrapper preview"
    src="https://dnd-grid.com/examples/headless-example?embed=1"
    className="h-[640px] w-full"
    loading="lazy"
  />
</div>

[View source on GitHub](https://github.com/mblode/dnd-grid/blob/main/apps/web/examples/dnd-grid-headless-example.tsx)

## Installation

<Tabs>
<Tab title="CLI">

```bash
npx shadcn@latest add https://dnd-grid.com/r/headless-example.json
```

</Tab>
<Tab title="Manual">

```bash
npm install @dnd-grid/react
```

```css
@import "@dnd-grid/react/styles.css";
```

```tsx title="components/dnd-grid-headless-example.tsx"
"use client";

import {
  GridItem,
  type Layout,
  useContainerWidth,
  useDndGrid,
} from "@dnd-grid/react";
import * as React from "react";

const initialLayout: Layout = [
  { id: "a", x: 0, y: 0, w: 3, h: 2 },
  { id: "b", x: 3, y: 0, w: 3, h: 2 },
  { id: "c", x: 6, y: 0, w: 3, h: 2 },
];

export function HeadlessExample() {
  const [layout, setLayout] = React.useState(initialLayout);
  const { width, containerRef, mounted } = useContainerWidth({
    measureBeforeMount: true,
  });
  const children = layout.map((item) => (
    <div key={item.id} className="grid-item">
      {item.id}
    </div>
  ));

  const { gridProps, itemProps, liveRegionElement } = useDndGrid({
    layout,
    onLayoutChange: setLayout,
    cols: 12,
    rowHeight: 50,
    width,
    children,
  });

  const { ref: gridRef, ...restGridProps } = gridProps;
  const setGridRef = React.useCallback(
    (node: HTMLDivElement | null) => {
      containerRef.current = node;
      if (typeof gridRef === "function") {
        gridRef(node);
        return;
      }
      if (gridRef) {
        (gridRef as React.MutableRefObject<HTMLDivElement | null>).current =
          node;
      }
    },
    [containerRef, gridRef],
  );

  const droppingProps = itemProps.getDroppingItemProps();
  const placeholderProps = itemProps.getPlaceholderProps();

  return (
    <div className="space-y-2">
      <div className="text-xs text-zinc-500">Custom wrapper</div>
      <div {...restGridProps} ref={setGridRef}>
        {mounted && (
          <>
            {liveRegionElement}
            {React.Children.map(children, (child) => {
              const props = itemProps.getItemProps(child);
              return props ? <GridItem {...props} /> : null;
            })}
            {droppingProps && <GridItem {...droppingProps} />}
            {placeholderProps && <GridItem {...placeholderProps} />}
          </>
        )}
      </div>
    </div>
  );
}
```

</Tab>
</Tabs>

## Usage

```tsx
import { HeadlessExample } from "@/components/dnd-grid-headless-example";

export default function Page() {
  return <HeadlessExample />;
}
```