diff --git a/docs/plans/2026-02-13-phase2-builder-upgrade-design.md b/docs/plans/2026-02-13-phase2-builder-upgrade-design.md new file mode 100644 index 0000000..06943e6 --- /dev/null +++ b/docs/plans/2026-02-13-phase2-builder-upgrade-design.md @@ -0,0 +1,135 @@ +# Phase 2 — Builder Upgrade Design + +**Status:** Approved +**Date:** 2026-02-13 +**Scope:** Drag & drop field reordering, side-by-side live preview, snapshot-based undo/redo + +--- + +## Overview + +Phase 2 upgrades the FormBuilderModal with three features that transform it from a basic editor into a polished builder experience. All changes are scoped to `form-builder.ts` and `styles.css`, with no new modules needed. + +--- + +## 1. Drag & Drop Field Reordering + +### Implementation + +Native HTML5 Drag & Drop on `.ff-builder-field` elements: + +- Each field gets `draggable="true"` and a drag handle (`⠿` gripper icon) in the header +- `dragstart`: Stores source index in instance variable `dragSourceIndex` +- `dragover`: Calculates drop position (above/below element center), shows CSS indicator +- `dragleave`: Removes drop indicator +- `drop`: Reorders `draft.fields` array, calls `this.render()` +- Instance variable `dragSourceIndex: number | null` tracks the dragged field + +### Existing Up/Down buttons remain + +They serve as accessibility fallback for keyboard-only users. + +### CSS Classes + +- `.ff-drag-handle` — Gripper icon, `cursor: grab`, left of field number +- `.ff-builder-field.ff-dragging` — `opacity: 0.4` during drag +- `.ff-builder-field.ff-drop-above` — Blue top border indicator line +- `.ff-builder-field.ff-drop-below` — Blue bottom border indicator line + +--- + +## 2. Side-by-Side Live Preview + +### Layout + +The `render()` method creates a two-column grid layout: + +``` +┌─────────────────────────────────────────────┐ +│ Form Settings (h2) │ +├──────────────────────┬──────────────────────┤ +│ Editor (left) │ Preview (right) │ +│ - General settings │ - Form title │ +│ - Fields list │ - Rendered fields │ +│ - Add field button │ - Submit button │ +├──────────────────────┴──────────────────────┤ +│ Footer: Undo/Redo | Cancel | Save │ +└─────────────────────────────────────────────┘ +``` + +### Preview Panel + +- Calls existing `renderField()` from `field-renderers.ts` for each field +- Fields are fully interactive (users can test how they feel) +- Shows form title and a disabled pseudo-submit button +- Automatically updates on every `render()` call (no separate mechanism) +- Uses `this.app` for note-link and folder-picker autocomplete + +### CSS Changes + +- `.ff-builder-layout` — `display: grid; grid-template-columns: 1fr 1fr; gap: 24px` +- `.ff-builder-preview` — `border-left`, `padding-left`, sticky "Preview" header +- `.ff-builder-modal` — `max-width` increased from 700px to 1100px +- Footer spans full width below the grid + +--- + +## 3. Snapshot-Based Undo/Redo + +### State + +New instance variables on `FormBuilderModal`: + +```typescript +private history: FormDefinition[] = []; +private historyIndex: number = 0; +``` + +### Methods + +- `pushSnapshot()` — `structuredClone(this.draft)` pushed to history. Truncates forward history (everything after `historyIndex`). Max 30 entries. +- `undo()` — Decrements `historyIndex`, restores draft from snapshot, calls `render()` +- `redo()` — Increments `historyIndex`, restores draft from snapshot, calls `render()` + +### When snapshots are pushed + +Before mutations that trigger `render()`: +- Add field +- Delete field +- Move field (drag & drop, up/down) +- Change field type +- Change form mode (create/update) + +NOT on every keystroke — only on `change` events (blur/enter) for text inputs. + +### Keyboard Shortcuts + +- `Ctrl+Z` / `Cmd+Z` → undo +- `Ctrl+Shift+Z` / `Cmd+Shift+Z` → redo +- Keydown listener on `contentEl` + +### Visual Indicators + +- Undo (`↩`) and Redo (`↪`) buttons in footer, left-aligned (before Cancel/Save) +- Buttons are disabled when at start/end of history stack + +### Initialization + +Constructor pushes first snapshot of original form state. + +--- + +## Files Changed + +| File | Change | +|------|--------| +| `src/ui/form-builder.ts` | Drag & drop, preview panel, undo/redo — major rewrite | +| `styles.css` | DnD indicators, grid layout, preview panel, undo/redo buttons | + +## Out of Scope + +- Undo for individual text keystrokes (browser-native handles this) +- External undo manager utility +- Drag & drop between forms +- Preview in a separate modal/window +- Collapsible preview panel