Weave.js

Text (native editing)

Text node with editing drawn natively on the canvas

The Text (native editing) node is a drop-in replacement for the Text node. Instead of overlaying a DOM textarea while you edit, it draws the caret and the selection directly on the canvas, so the text looks the same while editing and while idle, at any zoom level.

It keeps the same node type (text), so existing documents work unchanged.

Usage

Import the Node

Start by importing the node:

import { WeaveTextV2Node } from "@inditextech/weave-sdk";

Register the Node

Register it on the Weave class instance instead of WeaveTextNode. Both use the text node type, so only one of them can be registered.

const instance = new Weave({
  ...
  nodes: [
    ...,
    new WeaveTextV2Node(), (1)
  ]
})
1 Replaces new WeaveTextNode().

The Text Tool works with either node.

What editing feels like

  • Entering edit mode on existing text selects all of it, as in Figma, so typing replaces it. A node you just created starts with the caret.

  • The mouse pointer is a text cursor (I-beam) over the text box while editing, and the default one outside it.

  • An outline of the text box is drawn while editing. It is especially useful when the width or the height are fixed.

  • Click, drag, double-click (word), triple-click (paragraph), the arrow keys, Home, End and Up / Down move and select as expected, and IME composition works.

  • Ctrl/Cmd + Z undoes your typing while you edit, without touching the rest of the canvas history. Leaving edit mode (Esc or clicking outside) saves everything as one undoable step.

  • Copy and paste use plain text; pasted text takes the formatting at the caret.

  • The canvas pans to follow the caret when you type past the edge of the view. Configure the margin with edition.followPadding (default 40 px per side), for example to keep the caret clear of your toolbars.

  • To build a formatting toolbar that keeps the editor open, add the attribute data-weave-text-edit-keep to the toolbar element (and to any portaled popup it opens). Clicks on it then no longer end editing and rich text commands apply to the current selection.

Customize the outline

new WeaveTextV2Node({
  config: {
    edition: {
      outline: { enabled: true, color: "#0074ff", width: 1, padding: 0 },
    },
  },
});
edition.borderSize from the Text node does not exist here. Use edition.outline.

Rich text

Turn on formatting per selection (bold, italic, underline, strikethrough, colour, size, line height, font family and links), per-paragraph alignment and bulleted or numbered lists with nesting:

new WeaveTextV2Node({
  config: { richText: { enabled: true, indentStep: 1.5 } },
});

While editing, Ctrl/Cmd + B, I and U work, Enter continues a list and Tab / Shift+Tab change its depth. The toolbar is yours: call the node commands (for example from a modal; setRunLink adds a URL to a range) and listen to onTextSelectionChange and onTextFormatChange. Formatting survives move, resize, copy, duplicate, undo and image export.

Rich text is decided per node (the richText attribute); richText.enabled is only the default for nodes without it. To offer a plain and a rich Text Tool, see Text Tool.

Per-paragraph alignment (setAlign), per-selection line height and links per range (setRunLink) are also commands. On a server render (skia-canvas or node-canvas) italic text in fonts without an italic file is slanted like in the browser; see the reference.

Lists and marks already in a document render for everyone, even when rich text is off.

See the reference for the commands.

Plain and rich text nodes together

You do not have to choose one or the other. A single registered WeaveTextV2Node handles both, because whether a node is rich is a property of the node (the boolean attribute richText), not of the handler. Both kinds use the same text node type, live in the same document and can sit side by side on the same canvas.

Plain node Rich node

richText attribute

absent or false

true

Formatting commands, shortcuts and list key rules

off

on

Whole-node style (font, size, colour, alignment)

yes

yes

Marks, lists and links already in the document

rendered

rendered

The simplest way to offer both is two Text Tools. Register the node once and the action twice, with different names, and give the second one the richText prop:

const instance = new Weave({
  ...
  nodes: [..., new WeaveTextV2Node()],
  actions: [
    ...,
    new WeaveTextToolAction(), (1)
    new WeaveTextToolAction({ name: "richTextTool", props: { richText: true } }), (2)
  ],
});

instance.triggerAction("textTool");     // creates a plain node
instance.triggerAction("richTextTool"); // creates a rich node
1 The existing tool: plain nodes.
2 A second tool whose nodes are created with richText: true.

Notes:

  • config.richText.enabled is only the default for nodes that have no richText attribute, such as documents created before this feature. Leave it false if you want plain nodes by default.

  • Your toolbar can read handler.isRich(node) to show formatting controls only for rich nodes. On a plain node every formatting command returns false and does nothing.

  • Switching a node’s richText to false does not remove its formatting: marks and lists stay and still render, only the commands go away. Switching it to true makes an existing plain node editable with the formatting commands.

  • richText.indentStep is read by the handler, not the node, so use the same value on every client.

Large texts

There is no size limit. When the serialized content passes sizeWarning.threshold (200000 characters by default) the onTextSizeWarning event is emitted, so your application can warn users or decide what to do.

See WeaveTextV2Node for the full reference: configuration, events and the content model.