# `src/dex` — Diagram Builder Utility

A self-contained React package for building visual Mermaid sequence diagrams via a form-driven UI. Designed for future extraction as an npm package — no imports from `src/client`, `src/server`, or `src/shared`.

---

## Entry Points

### `DiagramBuilder` component

```tsx
import { DiagramBuilder } from '../dex'

// Standalone mode — fills a section, no sub-toolbar
<DiagramBuilder
  mode="standalone"
  colorScheme="light"       // or "dark"
  height="100%"
  initialModel={existingModel}     // optional, load for editing
  onSave={(code, model) => {}}     // called when user saves
/>

// Insert mode — shows Back/Insert sub-toolbar
<DiagramBuilder
  mode="insert"
  colorScheme="light"
  onInsert={(code) => {}}   // called with mermaid fenced string
  onCancel={() => {}}       // called on Back click
/>
```

### `serialize` — model → Mermaid string

```typescript
import { serialize } from '../dex'

const code = serialize(model)
// → "sequenceDiagram\n  participant Client\n  Client->>Server: login()\n..."
```

### `parseMermaid` — Mermaid string → model

```typescript
import { parseMermaid } from '../dex'

const model = parseMermaid(code)
// Parses a sequenceDiagram block back into a DiagramModel for editing.
// Round-trip safe: serialize(parseMermaid(serialize(model))) === serialize(model)
```

Supports all syntax emitted by `serialize`: `title`, `autonumber`, `participant`/`actor` with aliases and `box` colour, all 8 arrow types, `activate`/`deactivate`, `note left of`/`right of`/`over`, and nested `loop`/`opt`/`alt`/`par` blocks. Mermaid `%%` comments are stripped.

### `useDiagramState` — hook for custom UIs

```typescript
import { useDiagramState } from '../dex'

const [model, actions] = useDiagramState(initialModel)
// actions: addParticipant, updateParticipant, removeParticipant,
//          addStep, updateStep, removeStep, reorderSteps,
//          updateSettings, loadModel, reset
```

---

## Data Model

```typescript
DiagramModel {
  settings: { autonumber: boolean; title?: string }
  participants: Participant[]
  steps: Step[]              // top-level; blocks recurse
}

Participant { id, name, alias?, type: 'participant' | 'actor', boxColor? }
Message    { id, from, to, label, arrowType, activateReceiver?, deactivateReceiver? }
Note       { id, position: 'left of'|'right of'|'over', participants, text }
Block      { id, type: 'loop'|'alt'|'opt'|'par', label, steps?, branches?, andBranches? }

Step = { kind: 'message'; data: Message }
     | { kind: 'note';    data: Note    }
     | { kind: 'block';   data: Block   }

ArrowType: '->>' | '-->>' | '->' | '-->' | '-x' | '--x' | '-)' | '--)'
```

---

## File Map

```
src/dex/
├── index.ts                  ← public API barrel
├── types.ts                  ← all TypeScript types
├── mermaidSerializer.ts      ← serialize(model): string (pure)
├── mermaidParser.ts          ← parseMermaid(code): DiagramModel (pure)
├── useDiagramState.ts        ← React hook: model + actions
├── exportDiagram.ts          ← pure export utils (SVG, PNG, .mmd, clipboard)
├── DiagramBuilder.tsx        ← root component (toolbar + canvas column layout)
├── canvas/
│   ├── DiagramCanvas.tsx     ← mermaid SVG + react-zoom-pan-pinch + onSvgChange
│   └── ZoomControls.tsx      ← zoom button group shared with fullscreen modal
├── toolbar/
│   ├── DiagramToolbar.tsx    ← toolbar coordinator: all icon buttons + modal state
│   ├── ExportMenu.tsx        ← export dropdown (reused in toolbar and fullscreen modal)
│   └── modals/
│       ├── AddParticipantModal.tsx  ← add/edit participant or actor
│       ├── AddMessageModal.tsx      ← add/edit message with block assignment
│       ├── AddBlockModal.tsx        ← add/edit block
│       ├── EditElementsModal.tsx    ← searchable flat list, edit/delete all elements
│       ├── ReorderModal.tsx         ← two-zone dnd-kit tree (participants + steps)
│       └── ViewCodeModal.tsx        ← editable Mermaid textarea with Apply-back
└── panel/
    └── forms/
        ├── ParticipantForm.tsx
        ├── MessageForm.tsx
        ├── NoteForm.tsx
        └── BlockForm.tsx
```

---

## Integration Points in `src/client`

| Location | What it does |
|----------|-------------|
| `App.tsx` | "Diagrams" tab → standalone DiagramBuilder fills main area |
| `EditorWorkspace.tsx` | Toolbar "Diagram" button → insert mode → inserts ` ```mermaid``` ` block at cursor |
| `EditorWorkspace.tsx` | Clicking edit on a diagram in Preview mode → `parseMermaid(code)` → builder opens pre-populated |
| `MarkdownPreview.tsx` | Renders each mermaid block; hover shows Edit and Full Screen buttons; Full Screen opens a zoom/pan modal with ExportMenu footer |

---

## Dependencies

| Package | Purpose |
|---------|---------|
| `mermaid` v11 | SVG rendering (already in project) |
| `react-zoom-pan-pinch` | Pan/zoom canvas |
| `@dnd-kit/core` + `@dnd-kit/sortable` + `@dnd-kit/utilities` | Drag-to-reorder in Advanced mode |

---

## Out of Scope

- Other diagram types (flowchart, class, ER, Gantt) — architecture supports via future `diagramType` prop
- Undo/redo within builder
- Export to PDF (requires a third-party library)
- Export filename customisation (always `diagram.*`)
- Syntax highlighting in the View/Edit Code modal
- Mermaid `+`/`-` activation shorthand in arrows (e.g. `A->>+B: msg`) — parser does not handle this; use `activate`/`deactivate` lines instead
