openpencil/packages/pen-react
Kayshen-X c4e5359596 docs: drop op export from CLI docs and clarify pen-mcp usage
The `op export` command was removed in 0.7.x but the README still
advertised it (#116). The pen-mcp README also documented an
`npx @zseven-w/pen-mcp` quick-start that never worked because the
package ships TypeScript source against workspace-only deps with no
`bin` entry (#117).

- Strip `op export` references from all 15 root and 15 cli READMEs
- Sync AGENTS.md, CLAUDE.md, apps/cli/CLAUDE.md to match the codegen-
  pipeline reality (no standalone export command anymore)
- Rewrite pen-mcp README's quick-start: explain the package ships as
  part of the OpenPencil app and external clients connect over HTTP

Closes #116
Closes #117
2026-04-26 19:20:14 +08:00
..
src V0.7.0 (#95) 2026-04-11 23:25:13 +08:00
CLAUDE.md V0.7.1 (#102) 2026-04-13 21:30:23 +08:00
LICENSE V0.7.1 (#102) 2026-04-13 21:30:23 +08:00
package.json docs: drop op export from CLI docs and clarify pen-mcp usage 2026-04-26 19:20:14 +08:00
README.md V0.7.1 (#102) 2026-04-13 21:30:23 +08:00
tsconfig.json V0.7.0 (#95) 2026-04-11 23:25:13 +08:00

@zseven-w/pen-react

React UI SDK for OpenPencil — a complete set of hooks, components, and panels to build a design editor with React.

Install

npm install @zseven-w/pen-react
# or
bun add @zseven-w/pen-react

Peer dependencies: react@^19, react-dom@^19, @radix-ui/react-* (popover, select, separator, slider, switch, toggle, tooltip)

Overview

pen-react wraps @zseven-w/pen-engine into idiomatic React: a context provider, 10 semantic hooks, and 39 ready-to-use components covering the full editor UI.

<DesignProvider>
  <CoreToolbar />
  <DesignCanvas />
  <LayerPanel />
  <PropertyPanel />
  <PageTabs />
  <StatusBar />
</DesignProvider>

Quick Start

import {
  DesignProvider,
  DesignCanvas,
  CoreToolbar,
  LayerPanel,
  PropertyPanel,
} from '@zseven-w/pen-react';

function Editor() {
  return (
    <DesignProvider initialDocument={myDoc}>
      <div className="flex h-screen">
        <LayerPanel />
        <div className="flex flex-col flex-1">
          <CoreToolbar />
          <DesignCanvas className="flex-1" />
        </div>
        <PropertyPanel />
      </div>
    </DesignProvider>
  );
}

Hooks

All hooks subscribe to the engine and re-render on change:

import {
  useDesignEngine,
  useDocument,
  useSelection,
  useViewport,
  useActiveTool,
  useHistory,
  useActiveNode,
  useActivePage,
  useHover,
  useVariables,
} from '@zseven-w/pen-react';

function Inspector() {
  const node = useActiveNode(); // PenNode | null
  const selection = useSelection(); // string[]
  const { canUndo, undo } = useHistory();
  const viewport = useViewport(); // { zoom, panX, panY }
  const tool = useActiveTool(); // ToolType
  const doc = useDocument(); // PenDocument
  const page = useActivePage(); // PenPage
  const hoverId = useHover(); // string | null
  const variables = useVariables(); // VariableDefinition[]
  const engine = useDesignEngine(); // DesignEngine (escape hatch)

  return <div>Selected: {selection.length} nodes</div>;
}

Provider

Uncontrolled mode

Engine owns the document. Good for standalone editors:

<DesignProvider initialDocument={doc}>{children}</DesignProvider>

Controlled mode

Parent owns the document. Good for integration into existing state:

<DesignProvider document={doc} onDocumentChange={(newDoc) => setDoc(newDoc)}>
  {children}
</DesignProvider>

Echo-loop prevention is built in — onDocumentChange won't fire for changes that originated from the parent.

Components

Canvas

Component Description
DesignCanvas GPU-rendered canvas with CanvasKit/Skia. Handles zoom, pan, resize, and all interactions.
<DesignCanvas
  className="w-full h-full"
  onReady={(engine) => console.log('Canvas ready')}
  loadingFallback={<Spinner />}
/>

Toolbar

Component Description
CoreToolbar Main tool selection bar (select, frame, shapes, text, pen, image)
ToolButton Individual tool button with icon + active state
ShapeToolDropdown Dropdown for shape tools (rectangle, ellipse, polygon, line)
BooleanToolbar Union, subtract, intersect, exclude operations

Panels

Component Description
LayerPanel Hierarchical tree view with drag-and-drop reordering
LayerItem Single layer row — collapse, visibility, lock, rename
LayerContextMenu Right-click menu: copy, paste, delete, group, z-order
PropertyPanel Tabbed property inspector for the selected node
PageTabs Multi-page tab bar with add/rename/reorder/delete
StatusBar Bottom bar with zoom, coordinates, node count

Property Sections

Drop these into your own property panel or use PropertyPanel which includes all of them:

Section Edits
SizeSection x, y, width, height, rotation, constraints
FillSection Solid color, linear/radial gradient
StrokeSection Color, thickness, dash pattern, cap, join
TextSection Font family, size, weight, color, alignment
TextLayoutSection Line height, letter spacing, paragraph spacing
CornerRadiusSection Uniform or per-corner border radius
EffectsSection Drop shadow, inner shadow, blur
LayoutSection Auto-layout direction, gap, justify, align
LayoutPaddingSection Uniform or per-side padding
AppearanceSection Opacity, blend mode
IconSection Icon name picker (Lucide icons)
ImageSection Image source, fit mode
ExportSection Code generation target (React, HTML, Vue, etc.)

Shared UI

Component Description
ColorPicker Color input with swatch palette and hex input
NumberInput Numeric field with drag-to-adjust and arrow keys
SectionHeader Collapsible section header with title + actions
FontPicker Font family selector with preview
VariablePicker Design variable reference picker ($primary, etc.)
IconPickerDialog Modal icon browser with search and categories

UI Store

Ephemeral UI state (panel open/close, drag state) managed by Zustand — separate from engine state:

import { useUIStore } from '@zseven-w/pen-react';

const { layerPanelOpen, toggleLayerPanel } = useUIStore();

Styling

Components use Tailwind CSS + CVA for variant styling, and Radix UI primitives for accessibility. Override styles via className props or Tailwind's design token system.

License

MIT