The designer provides a comprehensive set of hooks for managing the state and behavior of the designer. These hooks provide a simple way to access and modify the designer's state, handle user interactions, and manage the design canvas.

## Designer

The core hooks for controlling the designer and the canvas.

### useDesignerAction

Executes designer-level actions like zoom, undo/redo, etc.

```tsx
import { useDesignerAction } from "@shadcn/designer"

function DesignerControls() {
  const designerAction = useDesignerAction()
  
  return (
    <div>
      <button onClick={() => designerAction("ZOOM_IN")}>Zoom In</button>
      <button onClick={() => designerAction("ZOOM_OUT")}>Zoom Out</button>
      <button onClick={() => designerAction("ZOOM_FIT")}>Fit to Screen</button>
      <button onClick={() => designerAction("ZOOM_RESET")}>Reset Zoom</button>
      <button onClick={() => designerAction("ZOOM_100")}>100%</button>
      <button onClick={() => designerAction("UNSELECT_ALL")}>Deselect All</button>
      <button onClick={() => designerAction("HISTORY_UNDO")}>Undo</button>
      <button onClick={() => designerAction("HISTORY_REDO")}>Redo</button>
      <button onClick={() => designerAction("REDRAW")}>Redraw Canvas</button>
    </div>
  )
}
```

**Available Actions:**

| Action | Description |
|--------|-------------|
| `ZOOM_IN` | Increase zoom level by one step |
| `ZOOM_OUT` | Decrease zoom level by one step |
| `ZOOM_RESET` | Reset zoom to default level and center canvas |
| `ZOOM_100` | Set zoom to 100% |
| `ZOOM_FIT` | Fit canvas to viewport and center |
| `REDRAW` | Redraw the canvas and center it |
| `UNSELECT_ALL` | Clear all layer selections |
| `HISTORY_UNDO` | Trigger undo action |
| `HISTORY_REDO` | Trigger redo action |

See also `useUndo` and `useRedo` for undo/redo functionality.

### useDesignerTool

Gets the currently active designer tool.

```tsx
import { useDesignerTool } from "@shadcn/designer"

function ToolIndicator() {
  const tool = useDesignerTool()

  return (
    <div>
      Active tool: {tool === "move" ? "Move Tool" : "Hand Tool"}
    </div>
  )
}
```

**Available Tools:**

| Tool | Description |
|------|-------------|
| `move` | Default tool for selecting and moving layers |
| `hand` | Pan the canvas without selecting layers |

### useSetDesignerTool

Sets the active designer tool.

```tsx
import { useDesignerTool, useSetDesignerTool } from "@shadcn/designer"

function ToolSwitcher() {
  const tool = useDesignerTool()
  const setTool = useSetDesignerTool()

  return (
    <div>
      <button
        onClick={() => setTool("move")}
        disabled={tool === "move"}
      >
        Move Tool (V)
      </button>
      <button
        onClick={() => setTool("hand")}
        disabled={tool === "hand"}
      >
        Hand Tool (H)
      </button>
    </div>
  )
}
```

**Keyboard Shortcuts:**
- **V** - Switch to Move tool
- **H** - Switch to Hand tool

### useFrameSize

Gets the current frame/canvas size.

```tsx
import { useFrameSize } from "@shadcn/designer"

function FrameInfo() {
  const frameSize = useFrameSize()
  
  return (
    <div>
      Canvas: {frameSize.width} × {frameSize.height}
    </div>
  )
}
```

### useSetFrameSize

Sets the frame/canvas size.

```tsx
import { useSetFrameSize } from "@shadcn/designer"

function FrameSizeControl() {
  const setFrameSize = useSetFrameSize()
  
  const handlePreset = (width: number, height: number) => {
    setFrameSize({ width, height })
  }
  
  return (
    <div>
      <button onClick={() => handlePreset(1920, 1080)}>HD</button>
      <button onClick={() => handlePreset(1024, 1024)}>Square</button>
    </div>
  )
}
```

### useZoom

Gets the current zoom level of the canvas.

```tsx
import { useZoom } from "@shadcn/designer"

function ZoomIndicator() {
  const zoom = useZoom()
  
  return <span>{Math.round(zoom * 100)}%</span>
}
```

### useSetZoom

Sets the zoom level of the canvas.

```tsx
import { useSetZoom } from "@shadcn/designer"

function ZoomSlider() {
  const zoom = useZoom()
  const setZoom = useSetZoom()
  
  return (
    <input
      type="range"
      min="0.1"
      max="3"
      step="0.1"
      value={zoom}
      onChange={(e) => setZoom(parseFloat(e.target.value))}
    />
  )
}
```

### useTargets

Gets the current interaction targets on the canvas.

```tsx
import { useTargets } from "@shadcn/designer"

function TargetInfo() {
  const targets = useTargets()
  
  return <div>Active targets: {targets.length}</div>
}
```

### useSetTargets

Sets the interaction targets on the canvas.

```tsx
import { useSetTargets, type Target } from "@shadcn/designer"

function TargetController({ newTargets }) {
  const setTargets = useSetTargets()
  
  React.useEffect(() => {
    const target = document.querySelector(
      `[data-layer-id="SOME_LAYER_ID"].layer`
    ) as Target | null
    setTargets([target])
  }, [setTargets])
  
  return null
}
```

## Layer Management

Essential hooks for working with layers - selecting, creating, modifying, and managing layer state.

### useSelectedLayers

Gets the currently selected layers on the canvas.

```tsx
import { useSelectedLayers } from "@shadcn/designer"

function LayerInfo() {
  const selectedLayers = useSelectedLayers()
  
  return (
    <div>
      {selectedLayers.length > 0 ? (
        <p>Selected: {selectedLayers[0].name}</p>
      ) : (
        <p>No layers selected</p>
      )}
    </div>
  )
}
```

### useSetSelectedLayers

Sets the selected layers on the canvas.

```tsx
import { useSetSelectedLayers } from "@shadcn/designer"

function LayerSelector({ layer }) {
  const setSelectedLayers = useSetSelectedLayers()
  
  const handleSelect = () => {
    setSelectedLayers([layer])
  }
  
  return <button onClick={handleSelect}>Select Layer</button>
}
```

### useSelectedLayerIds

Gets an array of IDs for currently selected layers.

```tsx
import { useSelectedLayerIds } from "@shadcn/designer"

function SelectedLayerCount() {
  const selectedLayerIds = useSelectedLayerIds()
  
  return <span>Selected: {selectedLayerIds.length}</span>
}
```

### useSelectedLayerTypes

Gets the unique types of currently selected layers.

```tsx
import { useSelectedLayerTypes } from "@shadcn/designer"

function LayerTypeIndicator() {
  const selectedLayerTypes = useSelectedLayerTypes()
  
  return (
    <div>
      Types: {selectedLayerTypes.join(", ")}
    </div>
  )
}
```

### useLayers

Gets all layers in the design.

```tsx
import { useLayers } from "@shadcn/designer"

function LayerCount() {
  const layers = useLayers()
  
  return <span>Total layers: {layers.length}</span>
}
```

To add or remove layers, see [`useAddLayers`](#useaddlayers) and [`useDeleteLayers`](#usedeletelayers).

### useLayersWithStyles

Gets all layers with computed styles applied.

```tsx
import { useLayersWithStyles } from "@shadcn/designer"

function StyledLayerList() {
  const layersWithStyles = useLayersWithStyles()
  
  return (
    <div>
      {layersWithStyles.map(layer => (
        <div key={layer.id} style={layer.style}>
          {layer.name}
        </div>
      ))}
    </div>
  )
}
```

### useAddLayers

Adds new layers to the design canvas.

```tsx
import { useAddLayers } from "@shadcn/designer"

function AddTextButton() {
  const addLayers = useAddLayers()
  
  const handleAddText = () => {
    addLayers([
      {
        type: "text",
        name: "New Text",
        cssVars: {
          "--content": "Hello World",
          "--font-size": "16px"
        }
      }
    ])
  }
  
  return <button onClick={handleAddText}>Add Text Layer</button>
}
```

### useDeleteLayers

Deletes layers from the design canvas.

```tsx
import { useDeleteLayers, useSelectedLayerIds } from "@shadcn/designer"

function DeleteSelectedButton() {
  const deleteLayers = useDeleteLayers()
  const selectedLayerIds = useSelectedLayerIds()
  
  const handleDelete = () => {
    deleteLayers(selectedLayerIds)
  }
  
  return (
    <button 
      onClick={handleDelete}
      disabled={selectedLayerIds.length === 0}
    >
      Delete Selected
    </button>
  )
}
```

### useGetLayers

Gets specific layers by their IDs.

```tsx
import { useGetLayers } from "@shadcn/designer"

function LayerDetails({ layerIds }) {
  const getLayers = useGetLayers()
  const layers = getLayers(layerIds)
  
  return (
    <div>
      {layers.map(layer => (
        <div key={layer.id}>{layer.name}</div>
      ))}
    </div>
  )
}
```

### useSetLayersProperty

Sets a common layer property on multiple layers at once. Use this for shared
fields like `name`, `isLocked`, and `cssVars`. For layer-specific `value` and
`meta`, use [`useSetLayersValue`](#usesetlayersvalue) or
[`useSetLayersMeta`](#usesetlayersmeta) instead.

```tsx
import { useSetLayersProperty } from "@shadcn/designer"

function LockSelectedLayers() {
  const setLayersProperty = useSetLayersProperty()
  const selectedLayerIds = useSelectedLayerIds()
  
  const handleLock = () => {
    setLayersProperty(selectedLayerIds, "isLocked", true)
  }
  
  return <button onClick={handleLock}>Lock Selected</button>
}
```

See the [Layer](/docs/reference/types#layer) type for more information on the properties that can be set and how to use the `meta` property to store arbitrary data on a layer.

### useSetLayersValue

Sets the `value` field on one or more layers. The target can be a layer ID, an
array of layer IDs, a layer object, or an array of layer objects. Pass either the
next value directly or an updater function that receives the previous value.

When the target is a narrowed layer object, the value is inferred from that layer
type:

```tsx
import { useSelectedLayers, useSetLayersValue } from "@shadcn/designer"

function ShapeTypeAction() {
  const selectedLayers = useSelectedLayers()
  const setLayersValue = useSetLayersValue()
  const shapeLayers = selectedLayers.filter((layer) => layer.type === "shape")

  return (
    <button
      onClick={() => setLayersValue(shapeLayers, { type: "circle" })}
      disabled={shapeLayers.length === 0}
    >
      Circle
    </button>
  )
}
```

When the target is an ID or array of IDs, pass the layer type as a generic if you
want the value to be checked against a specific registered layer type:

```tsx
setLayersValue<"shape">(selectedLayerIds, { type: "square" })
```

Use an updater when the next value depends on the current value:

```tsx
setLayersValue<"shape">("shape-1", (prev) => ({
  ...prev,
  type: prev.type === "circle" ? "square" : "circle",
}))
```

Pass `{ history: false }` as the third argument to skip recording the update in
undo history.

### useSetLayersMeta

Sets the `meta` field on one or more layers. It accepts the same targets,
updater form, and `{ history: false }` option as `useSetLayersValue`.

```tsx
import { useSelectedLayers, useSetLayersMeta } from "@shadcn/designer"

function MarkApprovedAction() {
  const selectedLayers = useSelectedLayers()
  const setLayersMeta = useSetLayersMeta()
  const cardLayers = selectedLayers.filter((layer) => layer.type === "card")

  return (
    <button
      onClick={() =>
        setLayersMeta(cardLayers, (prev) => ({
          ...prev,
          approved: true,
        }))
      }
      disabled={cardLayers.length === 0}
    >
      Approve
    </button>
  )
}
```

For ID targets, use the layer type generic to get the registered `meta` shape:

```tsx
setLayersMeta<"card">(selectedLayerIds, (prev) => ({
  ...prev,
  approved: true,
}))
```

### useLayersAction

Executes common layer actions like duplicate, delete, show/hide, etc.

```tsx
import { useLayersAction, useSelectedLayerIds } from "@shadcn/designer"

function LayerActions() {
  const layersAction = useLayersAction()
  const selectedLayerIds = useSelectedLayerIds()
  
  const handleDuplicate = () => {
    layersAction("DUPLICATE_LAYER", selectedLayerIds)
  }
  
  const handleToggleVisibility = () => {
    layersAction("SHOW_HIDE_LAYER", selectedLayerIds)
  }
  
  return (
    <div>
      <button onClick={handleDuplicate}>Duplicate</button>
      <button onClick={handleToggleVisibility}>Toggle Visibility</button>
    </div>
  )
}
```

**Available Actions:**

| Action | Description |
|--------|-------------|
| `DUPLICATE_LAYER` | Duplicate the selected layers |
| `SHOW_HIDE_LAYER` | Show or hide the selected layers |
| `BRING_TO_FRONT` | Bring the selected layers to the front |
| `SEND_TO_BACK` | Send the selected layers to the back |
| `LOCK_UNLOCK_LAYER` | Lock or unlock the selected layers |

### useLayerTypes

Gets the available layer types that can be created.

```tsx
import { useLayerTypes } from "@shadcn/designer"

function LayerTypeMenu() {
  const layerTypes = useLayerTypes()
  
  return (
    <select>
      {layerTypes.map(type => (
        <option key={type.type} value={type.type}>
          {type.name}
        </option>
      ))}
    </select>
  )
}
```

### useLayerCssVarAction

Manages CSS variables for selected layers with type-safe serialization.

```tsx
// Create a typed CSS variable action
const fontSize = createLayerCssVarAction("--font-size", "16px")
```

You can also pass a `serialize` and `deserialize` function to the `createLayerCssVarAction` function to customize the serialization and deserialization of the value.

```tsx
const fontSize = createLayerCssVarAction("--font-size", "16px", {
  serialize: (value: number) => `${value}px`,
  deserialize: (value: string | undefined) => {
    return value ? parseInt(value) : 16
  }
})
``` 

```tsx
import { useLayerCssVarAction, createLayerCssVarAction } from "@shadcn/designer"

// Create a typed CSS variable action
const fontSize = createLayerCssVarAction("--font-size", "16px")

function FontSizeControl() {
  const [value, setValue] = useLayerCssVarAction(fontSize)
  
  return (
    <input
      type="range"
      min="8"
      max="72"
      value={value}
      onChange={(e) => setValue(parseInt(e.target.value))}
    />
  )
}
```

## History Management

Hooks for managing undo/redo functionality and action history.

### useUndo

Triggers an undo action.

```tsx
import { useUndo, useCanUndo } from "@shadcn/designer"

function UndoButton() {
  const undo = useUndo()
  const canUndo = useCanUndo()
  
  return (
    <button onClick={undo} disabled={!canUndo}>
      Undo
    </button>
  )
}
```

### useRedo

Triggers a redo action.

```tsx
import { useRedo, useCanRedo } from "@shadcn/designer"

function RedoButton() {
  const redo = useRedo()
  const canRedo = useCanRedo()
  
  return (
    <button onClick={redo} disabled={!canRedo}>
      Redo
    </button>
  )
}
```

### useCanUndo

Checks if undo is available.

```tsx
import { useCanUndo } from "@shadcn/designer"

function HistoryStatus() {
  const canUndo = useCanUndo()
  
  return canUndo ? "Changes available" : "No changes to undo"
}
```

### useCanRedo

Checks if redo is available.

```tsx
import { useCanRedo } from "@shadcn/designer"

function RedoStatus() {
  const canRedo = useCanRedo()
  
  return canRedo ? "Redo available" : "Nothing to redo"
}
```

## Keyboard Shortcuts

Hooks for handling keyboard interactions and custom shortcuts.

### useShortcut

Registers a keyboard shortcut with a callback.

```tsx
import { useShortcut } from "@shadcn/designer"

function ShortcutHandler() {
  useShortcut("DUPLICATE_LAYER", () => {
    console.log("Duplicate shortcut pressed")
  })
  
  useShortcut("DELETE_LAYER", () => {
    console.log("Delete shortcut pressed")
  })
  
  return null // This component just handles shortcuts
}
```

### useKeybindings

Gets the current keybinding configuration.

```tsx
import { useKeybindings } from "@shadcn/designer"

function ShortcutList() {
  const keybindings = useKeybindings()
  
  return (
    <div>
      {Object.entries(keybindings).map(([key, binding]) => (
        <div key={key}>
          <strong>{binding.name}</strong>: {binding.key}
        </div>
      ))}
    </div>
  )
}
```

### useSetKeybindings

Sets custom keybinding configuration.

```tsx
import { useSetKeybindings } from "@shadcn/designer"

function CustomizeShortcuts() {
  const setKeybindings = useSetKeybindings()
  
  const handleCustomize = () => {
    setKeybindings({
      "DUPLICATE_LAYER": {
        key: "cmd+d",
        name: "Duplicate Layer",
        group: "layer"
      }
      // ... more keybindings
    })
  }
  
  return <button onClick={handleCustomize}>Customize Shortcuts</button>
}
```

## Development

Hooks for debugging and development.

### useDebug

Gets the current debug mode state.

```tsx
import { useDebug } from "@shadcn/designer"

function DebugPanel() {
  const debug = useDebug()
  
  if (!debug) return null
  
  return <div>Debug information...</div>
}
```

### useSetDebug

Sets the debug mode state.

```tsx
import { useSetDebug } from "@shadcn/designer"

function DebugToggle() {
  const debug = useDebug()
  const setDebug = useSetDebug()
  
  return (
    <button onClick={() => setDebug(!debug)}>
      {debug ? "Disable" : "Enable"} Debug
    </button>
  )
}
```

## Unit System

Hooks for managing measurement units and DPI settings. See the [Unit System](/docs/concepts/unit-system) guide for detailed usage.

### useUnitSystem

Gets the current unit system being used for display.

```tsx
import { useUnitSystem } from "@shadcn/designer"

function UnitDisplay() {
  const unitSystem = useUnitSystem() // "px" | "mm" | "in" | "cm" | "pt"

  return <span>Current unit: {unitSystem}</span>
}
```

### useSetUnitSystem

Sets the unit system for displaying values.

```tsx
import { useSetUnitSystem } from "@shadcn/designer"

function UnitSwitcher() {
  const setUnitSystem = useSetUnitSystem()

  return (
    <select onChange={(e) => setUnitSystem(e.target.value)}>
      <option value="px">Pixels</option>
      <option value="mm">Millimeters</option>
      <option value="in">Inches</option>
      <option value="cm">Centimeters</option>
      <option value="pt">Points</option>
    </select>
  )
}
```

### useDPI

Gets the current DPI (dots per inch) setting used for unit conversions.

```tsx
import { useDPI } from "@shadcn/designer"

function DPIIndicator() {
  const dpi = useDPI() // Default: 96

  return <span>DPI: {dpi}</span>
}
```

### useSetDPI

Sets the DPI for unit conversions. Common values are 96 for screen and 300 for print.

```tsx
import { useSetDPI } from "@shadcn/designer"

function DPIControl() {
  const setDPI = useSetDPI()

  return (
    <select onChange={(e) => setDPI(Number(e.target.value))}>
      <option value="96">Screen (96 DPI)</option>
      <option value="300">Print (300 DPI)</option>
      <option value="192">Retina (192 DPI)</option>
    </select>
  )
}
```

## Utilities

Helper hooks for cross-platform compatibility and general utilities.

### useIsMac

Detects if the user is on macOS platform, useful for showing platform-specific keyboard shortcuts and UI elements.

```tsx
import { useIsMac } from "@shadcn/designer"

function ShortcutDisplay({ keybinding }) {
  const isMac = useIsMac()

  const label = isMac
    ? keybinding.labelMac
    : keybinding.label

  return <span>{label}</span>
}
```

### useSharedValues

Derives a single shared value from a list of numeric values. This is useful for grouped controls such as padding, radius, or border width where a collapsed input should only show a value when every side matches.

Pass a flat array for a single layer or nested arrays for multiple selected layers. When any value differs, `value` is `undefined` and `isMixed` is `true`, so the control can render a mixed state instead of showing an arbitrary side value.

```tsx
import { useSharedValues } from "@shadcn/designer"

function PaddingControl({
  values,
  onValueChange,
}: {
  values: Array<number | number[]>
  onValueChange: (value: number) => void
}) {
  const { value, isEqual, isMixed, isEmpty, setValue } = useSharedValues(
    values,
    onValueChange
  )

  return (
    <input
      value={value ?? ""}
      placeholder={isMixed ? "Mixed" : undefined}
      aria-label={isEqual ? "Padding" : "Mixed padding"}
      data-empty={isEmpty}
      onChange={(event) => setValue(Number(event.target.value))}
    />
  )
}
```

**Returns:**

| Property | Description |
|----------|-------------|
| `value` | The shared number when all values match, otherwise `undefined` |
| `isEqual` | `true` when every value is the same |
| `isMixed` | `true` when the values differ |
| `isEmpty` | `true` when every value is `0` |
| `setValue` | Calls `onValueChange` with the new shared value |