Skip to content

Editor

Editor is a focusable, scrollable multiline text editor. It has a modern (or classic WordStar) keymap, multi-level undo/redo, cut/copy/paste through a shared clipboard, and find/replace. Add it to a Group, give it a size, and drive it through the event loop or programmatically (setText/getText/insertText/execute). A set of reactive signals — curPos, modified, canUndo, and more — let you reflect the editor's state in a status line or indicator. For scroll bars and a line:col indicator wired in for you, use EditWindow; to bind the content to a signal inside a dialog, use Memo.

Usage

ts
import { Group, Editor, createEventLoop, effect } from '@jsvision/ui';

const editor = new Editor({ clipboard: new Editor() }); // share one hidden editor as the clipboard
const root = new Group();
root.add(editor);

const loop = createEventLoop({ width: 60, height: 20 }, {});
loop.mount(root);
loop.focusView(editor);
editor.setText('The quick brown fox\nSecond line.');

effect(() => {
  const { line, col } = editor.curPos();
  console.log(`caret at ${line}:${col}`);
});

Live example

🚧 Live demo coming soon

An interactive, in-browser demo of Editor lands in a later update. Until then, the reference below covers its full API.

Props

new Editor(options) — every field is optional; a bare new Editor() is fully usable.

PropTypeDefaultDescription
clipboardEditorAn optional dedicated clipboard editor that takes precedence for Cut/Copy/Paste. Without one, the editor uses the event loop's shared app-local buffer, so clipboard still works and text moves between widgets.
keyBindings'modern' | 'wordstar''modern''modern' overlays Ctrl+X/C/V/A; 'wordstar' is the classic WordStar layout.
undoDepthnumber1000Maximum retained undo steps.
autoIndentbooleanfalseCopy the previous line's leading whitespace on Enter.
overwritebooleanfalseStart in overwrite mode (Insert toggles it).
editorDialogEditorDialogHandlercancel-allHandler for find/replace/save prompts.
commandsEditorCommandSeamHook for greying out Cut/Copy/Paste as selection/undo state changes.

Reactive state

Subscribe or bind these to reflect the editor in your UI: modified, curPos ({line, col}, 1-based), hasSelection, insertMode, lineCount, canUndo, canRedo, and delta (the {x, y} scroll offset — also the value channel a scroll bar binds to).

Methods

setText / getText / insertText / selectionText, execute(action) (run one keymap action — e.g. 'lineDown', 'textEnd', 'selectAll'), copy / cut / paste, undo / redo, and find / replace / searchAgain (async, resolve when the interaction is done).

Keyboard & mouse

The editor claims keys before app chrome (so it can own the WordStar Ctrl-Q / Ctrl-K prefixes). With the default 'modern' bindings:

InputResult
Arrows / PgUp / PgDn / Home / EndMove the caret; Shift extends the selection.
Ctrl+X / Ctrl+C / Ctrl+VCut / copy / paste through the shared clipboard.
Ctrl+ASelect all.
InsertToggle insert / overwrite mode.
Mouse click / dragPlace the caret / select; double-click a word, triple-click a line.
WheelScroll the view.

Choose keyBindings: 'wordstar' for the classic control-key diamond instead.

Sizing & layout

Give it an absolute rect or a flex size. The editor scrolls its content within that box and keeps the caret in view; bind a scroll bar to editor.delta.x / editor.delta.y to scroll it from the side.

Best practices

  • A shared clipboard is built in. Under the event loop, Cut/Copy/Paste use an app-local buffer shared with every widget, so copying in an Input and pasting into an Editor (or between two editors) just works — see Keyboard & clipboard. Pass a dedicated clipboard editor only when you want a separate, scoped clipboard that takes precedence.
  • Drive the UI from the signals. Read curPos/modified/canUndo in an effect or bind them to a status line rather than polling the editor.
  • Modern keys are the default. Ctrl+C is copy, not the WordStar break — a deliberate, documented choice. Opt into 'wordstar' explicitly if you want the classic layout.

Theming

Text uses the editorNormal / editorSelected roles (Memo overrides them to the gray-dialog palette).

  • Edit window — an Editor framed with scroll bars + a line:col indicator.
  • Memo — a signal-bound editor for placing inside a dialog.
  • API reference — the generated Editor signature.