# Designer
> The mental model behind the editor - state, actions, and the Editor.* compound namespace that ties them together.
Source: https://docs.docmosaic.com/docs/concepts/designer
The DocMosaic editor is a **designer for printable documents** - users arrange image sections on a virtual page and export a PDF. `@docmosaic/react` exposes that designer as a small set of compound primitives that snap together; `@docmosaic/core` is the headless state machine they all read from. Same model, two surfaces.
## Mental model
Think of the editor as three concentric layers:
1. **State** - a single `Document` carrying `pages`, a flat `sections` array, and metadata (`name`, `pageSize`, `orientation`). All geometry is in [PDF points](/docs/concepts/unit-system).
2. **Actions** - a stable 18-method surface (`addSection`, `updateSection`, `bringToFront`, `undo`, …) that produces the next document. The bundled reducer wraps these with a history timeline so undo/redo "just work."
3. **UI** - the `Editor.*` compound namespace. Every primitive reads its slice of state from context and dispatches actions back; nothing is prop-drilled.
```text
Editor.Root ← owns Document + history + DnD provider
├─ Editor.Properties ← document name, page size, orientation
├─ Editor.Toolbar ← undo/redo, preview, download, add-section
├─ Editor.Pages ← left rail of page thumbnails
├─ Editor.Canvas ← interactive workspace (drag, resize, zoom)
│ └─ Editor.Section ← one image rectangle on the canvas
└─ Editor.Preview ← full-document preview dialog
```
`Editor.Root` arranges its children into the default shell automatically - `Pages` is forced to the left of `Canvas` regardless of source order - so the flat composition above works out of the box.
## Composition
```tsx
import { Editor } from '@docmosaic/react';
import '@docmosaic/react/styles.css';
export function MyEditor() {
return (
);
}
```
The CSS import seeds the `--editor-*` tokens documented in [Theming](/docs/theming). Drop any primitive - or build your own from `useEditor()` - and the rest of the tree keeps working.
## Selection model
The editor tracks a **single selected section** at a time (`ui.selectedSectionId`). Selection drives:
- The visible toolbar on `Editor.Section` (fit / layer / duplicate / delete buttons).
- Keyboard nudge + delete bindings (see [Keybindings](/docs/concepts/keybindings)).
- Resize handles and the focus outline.
Clicking a section selects it; clicking the canvas background, hitting `Escape`, or deleting the selected section clears the selection. Multi-select is intentionally not part of the v1 surface - most flows that "want" multi-select are better expressed via layer actions on a single section.
## Drag, resize, upload
The Canvas wires every section to three gestures:
- **Drag** - pointer down on a section, move, pointer up. The reducer applies `UPDATE_SECTION` with the new `(x, y)`.
- **Resize** - drag the right, bottom, or bottom-right handle. The Canvas captures the start size and dispatches incremental `UPDATE_SECTION` calls.
- **Image upload** - drop a file onto a section (or click the empty-state). The reader produces a data URL, which becomes `section.imageUrl`.
Drag-and-drop is powered by `react-dnd` with a multi-backend (HTML5 on desktop, auto-transitioning to touch on mobile). `Editor.Root` mounts a single `` for the whole tree - don't nest another.
## Headless mode
When the compound shell isn't a fit (custom layout, native app, Server Components downstream), use the headless hook directly. It owns the same reducer + history:
```tsx
import { createDocument } from '@docmosaic/core';
import { useDocumentState } from '@docmosaic/react';
function CustomEditor() {
const { document, canUndo, canRedo, actions } = useDocumentState({
initialDocument: createDocument(),
});
return (
);
}
```
`actions` is referentially stable; `document`, `canUndo`, and `canRedo` re-render on every change. Wrap the same value in `EditorProvider` if you want compound primitives to see your custom-built state.
## Controlled vs. uncontrolled
`Editor.Root` works in both modes:
- **Uncontrolled** (default) - omit `document`. The root owns state internally. Pass `defaultDocument` to seed it.
- **Controlled** - pass `document` + `onDocumentChange`. Every mutation calls back out; the parent is responsible for re-rendering. Undo/redo are disabled because the timeline lives outside.
```tsx
const [doc, setDoc] = useState(createDocument());
{/* … */}
;
```
Don't mix modes mid-render - the root warns in development if you do.
## Read-only mode
`Editor.Root` accepts a `readOnly` boolean that flips the editor into viewer mode. Every mutating interaction (drag, resize, drop, file upload, page add/delete/reorder, undo/redo, keyboard nudge/delete, drawing-mode strokes) is suppressed. Mutating toolbar buttons (`Add*`, `Draw`, `Undo`, `Redo`) hide themselves; `Preview`, `Print`, and `Download` stay live so the viewer can still export.
```tsx
```
Selection (click, marquee), zoom, and pan all keep working - read-only is about mutation, not navigation. For a canvas-level override (read-only canvas inside an editable root), use `Editor.StaticCanvas`.
## See also
- [Document model](/docs/concepts/document-model) - the `Document` / `Page` / `Section` hierarchy in detail
- [History](/docs/concepts/history) - undo/redo and the timeline
- [Unit system](/docs/concepts/unit-system) - why geometry is stored in points
- [Theming](/docs/theming) - the `--editor-*` CSS-variable surface
- [Keybindings](/docs/concepts/keybindings) - default shortcuts and how to override
- [Layers](/docs/concepts/layers) - z-index actions for overlapping sections