openpencil/packages/pen-react/CLAUDE.md
Kayshen-X a7d73ebb62 feat(ai): pencil-style agentic design tool-loop, multi-chat tabs, #27 panel restyle
Built-in design generation now runs as an agentic MCP tool-loop (reusing the
agent-rs BuiltInProvider), gated behind OPENPENCIL_DESIGN_AGENT_LOOP / the
Settings experimental toggle; the orchestrator stays the default.

- design-agent system prompt + in-process design toolset (parity-locked with
  the MCP surface) + flag-gated Intent::Design routing
- spawn_agents execution as sequential sub-loops + live creation-mode badges
  (per-agent glow + 'N/M designing...' header)
- new MCP tools: get_guidelines, ToolSearch, get_screenshot, get_editor_state,
  export_nodes, spawn_agents; style-guide local audit
- #27 AI panel restyle: rounded tool cards + green check-rings, gray user
  bubbles, model-pill bottom toolbar, header, empty-state pills, the
  PARALLEL AGENTS (agent_team_size) 1x-6x chip dropdown
- multi-chat tabs: ChatSessions model (Deref-to-active) + tab row UI
  (switch / close / + / Cmd+T) with each run bound to its tab

Large checkpoint commit spanning the working tree (Rust shell crates).
2026-07-02 21:21:06 +08:00

74 lines
4 KiB
Markdown

# pen-react
React UI SDK for OpenPencil -- provider, hooks, panels, toolbar, and property editor components.
## Structure
### Core
- `src/context.ts` — `DesignEngineContext`: React context holding the `DesignEngine` instance
- `src/provider.tsx` — `DesignProvider`: provides engine to React tree. Supports uncontrolled mode (`initialDocument`) and controlled mode (`document` + `onDocumentChange`) with echo-loop prevention
### Hooks (`src/hooks/`)
- `use-design-engine.ts` — `useDesignEngine()`: gets engine from context, throws if outside provider
- `use-document.ts` — `useDocument()`: returns current `PenDocument`, re-renders on mutation
- `use-selection.ts` — `useSelection()`: returns `string[]` of selected node IDs
- `use-viewport.ts` — `useViewport()`: returns `ViewportState` (zoom, panX, panY)
- `use-active-tool.ts` — `useActiveTool()`: returns current `ToolType`
- `use-history.ts` — `useHistory()`: returns `{ canUndo, canRedo }`
- `use-active-node.ts` — `useActiveNode()`: returns the single active `PenNode` or null
- `use-active-page.ts` — `useActivePage()`: returns active page ID
- `use-hover.ts` — `useHover()`: returns hovered node ID
- `use-variables.ts` — `useVariables()`: returns document variables map
### Utilities (`src/utils/`)
- `use-engine-subscribe.ts` — `useEngineSubscribe(engine, event, getSnapshot)`: generic hook using `useSyncExternalStore` to subscribe to engine events with stable snapshot refs
### Stores (`src/stores/`)
- `ui-store.ts` — `useUIStore` (Zustand): pure UI state -- panel visibility, layer drag state, collapsed nodes. NOT engine state
### Components (`src/components/`)
- `design-canvas.tsx` — `DesignCanvas`: canvas element with CanvasKit rendering via `attachCanvas` + `attachInteraction` from pen-engine browser adapter
- `core-toolbar.tsx` — `CoreToolbar`: main tool selection bar
- `tool-button.tsx` — `ToolButton`: individual tool button with active state
- `shape-tool-dropdown.tsx` — `ShapeToolDropdown`: dropdown for shape tools (rectangle, ellipse, line, polygon)
- `layer-panel.tsx` — `LayerPanel`: document tree panel with drag-and-drop reordering
- `layer-item.tsx` — `LayerItem`: individual layer row with visibility/lock toggles
- `layer-context-menu.tsx` — `LayerContextMenu`: right-click context menu for layers
- `property-panel.tsx` — `PropertyPanel`: right-side property inspector (delegates to section components)
- `color-picker.tsx` — `ColorPicker`: color input with hex/opacity, gradient support
- `number-input.tsx` — `NumberInput`: numeric input with drag-to-adjust
- `section-header.tsx` — `SectionHeader`: collapsible section header
- `font-picker.tsx` — `FontPicker`: font family selector with search
- `variable-picker.tsx` — `VariablePicker`: design variable selector
- `icon-picker-dialog.tsx` — `IconPickerDialog`: icon search and selection
- `boolean-toolbar.tsx` — `BooleanToolbar`: union/subtract/intersect boolean operations
- `page-tabs.tsx` — `PageTabs`: multi-page tab bar
- `status-bar.tsx` — `StatusBar`: bottom status bar (zoom, selection info)
### Property sections (`src/components/sections/`)
- `size-section.tsx` — Width, height, x, y, rotation
- `fill-section.tsx` — Fill array editor (solid, gradient, image)
- `stroke-section.tsx` — Stroke properties (thickness, alignment, dash)
- `text-section.tsx` — Text content, font, size, weight, style
- `text-layout-section.tsx` — Text alignment, growth mode
- `corner-radius-section.tsx` — Corner radius (uniform or per-corner)
- `effects-section.tsx` — Blur and shadow effects
- `layout-section.tsx` — Auto-layout direction, gap, alignment
- `layout-padding-section.tsx` — Padding (uniform or per-side)
- `appearance-section.tsx` — Opacity, blend mode, visibility
- `icon-section.tsx` — Icon font name and family
- `image-section.tsx` — Image source, fit mode, adjustments
- `export-section.tsx` — Export format and code preview
## Testing
```bash
bun --bun vitest run packages/pen-react/src/__tests__/
```