@hone-ui/editor
Dev-only visual editor for @hone-ui/react apps. It reads the data-hn-source attributes the
@hone-ui/sx plugin stamps in dev, and writes edits back to the source files.
Use
import { DevEditor } from '@hone-ui/editor';
// once, near the root
<DevEditor />;
In development, Alt+Shift+E turns edit mode on. Hover outlines the nearest component, a click
selects it and opens the panel. While edit mode is on, the page ignores clicks and other pointer
input. Escape closes the panel, and a second Escape leaves edit mode. Selects and switches
save to the source file 150 ms after a change. Text and number fields save when you press Enter,
press Escape or leave the field, so a typed value is one write and one undo step. An arrow-key or
spinner step on a number field saves after 150 ms, like a select. The dev server's own hot reload
repaints the page. DevEditor renders null unless process.env.NODE_ENV === 'development'.
The sx section lists each key of a static sx object. Spacing keys and borderRadius get
number fields, color keys a select of palette paths plus free text, and a responsive object one
field per breakpoint. You can add and remove keys. An sx that is not an object literal, and any
spread, computed key or non-literal value, shows read-only.
The panel lives in a shadow root on <html>, with the Minimal look's CSS inlined, so app CSS
never reaches it. Props written as expressions show read-only with a "set in code" note, and
local wrapper components show read-only entries.
Ctrl+Z undoes the last save and Ctrl+Shift+Z (or Ctrl+Y) redoes it, wherever focus is
except inside a textarea or a field in your own app. The endpoint returns the reverse ops with
every save, so undo works for any op. One history covers every element until you leave edit mode.
Undo reverses the newest edit anywhere and selects the element it changed. A save that moves
lines tells the panel where, so the history of other elements stays correct. When the file changed
underneath the panel (a 409), the panel reloads the element, shows a message and clears its
history. If the element disappears after a save, the panel closes.
The docs page "Visual editor" covers setup for Vite and Next.js. An AI guide ships at
@hone-ui/editor/ai/DevEditor.md.
Package contents
@hone-ui/editor:DevEditorand the edit protocol types (Op,SourceResponse,EditRequest, and so on).@hone-ui/editor/server:applyEdit,readElementandreverseOps, which rewrite and read one JSX element with exact-range edits and compute the ops that undo an edit, andcreateEditorHandler, a plain Node(req, res, next)handler forGET /sourceandPOST /edit. It answers only loopback peers. The Vite plugin in@hone-ui/sxmounts it at/__hone/editor, andwithSxserves it from a loopback port for Next, withcrossOrigin: true. A dev server inside Docker with published ports gets a 403, because its connections arrive from the bridge address, not from loopback.
Develop
pnpm test runs the rewriter tests in Node and the panel tests in Chromium. pnpm test:e2e
starts the Vite playground on a free port, drives it with headless Chromium and restores the
file it edits. Build the workspace first (pnpm build), because the playground uses built
packages.
The panel's CSS is generated by scripts/build-panel-css.mjs from the built @hone-ui/react
package. It runs before build, lint, typecheck and test.
The panel uses a native select for string unions. React Aria's Select popover does portal
into the shadow root, but option clicks with a real pointer do not register there yet.