@zuilib/text-editor 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +180 -17
  2. package/DRAWING_FORMAT.md +23 -21
  3. package/README.md +486 -68
  4. package/dist/chunk-32RX4GZF.js +2 -0
  5. package/dist/chunk-3TZVOXWX.js +16 -0
  6. package/dist/chunk-5VRVC56Y.js +2 -0
  7. package/dist/chunk-7Z3CW6Q3.js +2 -0
  8. package/dist/chunk-A7MCBSAZ.js +2 -0
  9. package/dist/chunk-AGTPMKLK.js +2 -0
  10. package/dist/chunk-C7VEINKX.js +2 -0
  11. package/dist/chunk-LDVPFZCN.js +2 -0
  12. package/dist/chunk-N5JWZ2VW.js +9 -0
  13. package/dist/chunk-QKHMJQO3.js +2 -0
  14. package/dist/chunk-R5PL4Q7X.js +5 -0
  15. package/dist/chunk-SDICQI2B.js +2 -0
  16. package/dist/chunk-TGVEPLDM.js +1 -0
  17. package/dist/chunk-XP3MZRCW.js +2 -0
  18. package/dist/chunk-XRJNLGI4.js +2 -0
  19. package/dist/chunk-YFFSTMIR.js +2 -0
  20. package/dist/chunk-ZXZMYJ7F.js +2 -0
  21. package/dist/comment-markers-BrrrAdSL.d.ts +27 -0
  22. package/dist/comments.d.ts +68 -0
  23. package/dist/comments.js +2 -0
  24. package/dist/drawing-data-EWzEQ1_i.d.ts +111 -0
  25. package/dist/drawing-preset-Ag7a7F9h.d.ts +69 -0
  26. package/dist/drawing.d.ts +7 -0
  27. package/dist/drawing.js +2 -0
  28. package/dist/image-node-kR1Zf5kz.d.ts +70 -0
  29. package/dist/images.d.ts +66 -0
  30. package/dist/images.js +2 -0
  31. package/dist/index-A4S7bRwQ.d.ts +425 -0
  32. package/dist/index.d.ts +36 -1394
  33. package/dist/index.js +2 -7447
  34. package/dist/lexical.d.ts +117 -0
  35. package/dist/lexical.js +2 -0
  36. package/dist/markdown.d.ts +29 -0
  37. package/dist/markdown.js +2 -0
  38. package/dist/mention-node-eSsjUpaE.d.ts +44 -0
  39. package/dist/mentions-plugin-gio3_XKd.d.ts +74 -0
  40. package/dist/mentions.d.ts +5 -0
  41. package/dist/mentions.js +2 -0
  42. package/dist/mermaid-BwGHjwpk.d.ts +553 -0
  43. package/dist/paste.d.ts +45 -0
  44. package/dist/paste.js +2 -0
  45. package/dist/presets-BtNPH0pa.d.ts +78 -0
  46. package/dist/styles.css +406 -99
  47. package/dist/table-grid-D70tNhp2.d.ts +459 -0
  48. package/package.json +57 -12
  49. package/dist/index.css +0 -79
package/CHANGELOG.md CHANGED
@@ -1,6 +1,169 @@
1
1
  # Changelog — @zuilib/text-editor
2
2
 
3
- ## 0.11.0
3
+ ## 0.12.0 — Unreleased
4
+
5
+ Not on npm yet: the latest published version is 0.11.1. This entry carries
6
+ everything since then: the library-wide naming overhaul (clean break; only the
7
+ persisted drawing format migrates), the extension API and first-party plugins,
8
+ and the controlled-`value` rewrite. Features new in this release are described
9
+ under their final names.
10
+
11
+ ### Breaking
12
+
13
+ - Value triad: `onChange` → `onValueChange`; `foldable` → `collapsible`;
14
+ `defaultBlockWidth` → `newBlockWidth`; `measure` → `maxTextWidth`;
15
+ mode `'edit-md'` → `'edit-rich'`.
16
+ - Lexical containment: all `$`-helpers, node classes and presets moved to the
17
+ new `@zuilib/text-editor/lexical` entry; the root barrel is Lexical-free.
18
+ - Drawing data v3: shape `w`/`h` → `width`/`height` (v2 documents migrate on
19
+ load); `parseDrawingData` → `deserializeDrawingData`; `BoxType` →
20
+ `NodeShapeType`; geometry internals un-exported.
21
+ - All module files kebab-cased.
22
+ - Optional peer `@zuilib/tokens` is `^0.2.0` (token contract 2.0.0: the
23
+ stylesheet reads `--danger`, `--shadow-2`, …; `--zui-drawing-*` is declared
24
+ here now, not in the tokens package).
25
+ - Peer dependencies added: `@lexical/selection` (block types, max length) and,
26
+ for the plugins, `@lexical/mark`, `@lexical/html`, `@lexical/clipboard`.
27
+ `tailwindcss` (^4) is declared as an optional peer: the document typography
28
+ classes need a Tailwind host that `@source`s this package.
29
+
30
+ ### Added
31
+
32
+ - **Extension API.** `nodes` (appended to the built-in node classes),
33
+ `transformers` (an array goes before the built-ins; a function receives
34
+ them and returns the whole list), `nodeClassNames` (merged over the
35
+ built-in class map one level deep) and `onEditorReady` on `MarkdownEditor` /
36
+ `MarkdownEditor.Root`. All three lists are read on mount (the composer
37
+ cannot change nodes afterwards). Children of the root are plugins and
38
+ share the editor. `createMarkdownEditor(preset)` builds the component
39
+ around an `EditorPreset`
40
+ - New entry points: `@zuilib/text-editor/markdown` (the editor without the
41
+ drawing canvas: no `DrawingNode`, transformers, button or canvas code),
42
+ `@zuilib/text-editor/drawing` (the canvas on its own: node, transformers,
43
+ `DrawingPlugin`, helpers) and `@zuilib/text-editor/lexical` (everything
44
+ Lexical-shaped). Insertion goes through `INSERT_DRAWING_COMMAND` so the
45
+ markdown hook has no drawing dependency
46
+ - Exported the production lists on `./lexical`: `MARKDOWN_NODES`,
47
+ `MARKDOWN_TRANSFORMERS`, `MARKDOWN_PRESET`, `DRAWING_PRESET`,
48
+ `DRAWING_PRESET_NODES`, `DRAWING_PRESET_TRANSFORMERS`, `LISTS`,
49
+ `resolveTransformers`, `shortcutTransformers`, `editorNodeClassNames`,
50
+ `mergeNodeClassNames`
51
+ - **Localisation.** One `EditorLabels` type covers every chrome string
52
+ (toolbar, outline, collapsible headings, table rails and shortcuts, layout
53
+ presets, drawing canvas, placeholder, character count); pass a deep partial
54
+ as `labels`. `DEFAULT_LABELS`, `resolveLabels`, `useLabels` exported. The
55
+ `CollapsibleHeadingsLabels`, `TableRowShortcutsLabels`,
56
+ `TableColumnShortcutsLabels` types are exported and their plugins default
57
+ to the editor's labels
58
+ - **Toolbar.** A new **block** group (heading 1 to 3, bullet / numbered /
59
+ check list, quote) and a link button. `ToolbarItems` gains `block`;
60
+ `BlockButtons` and `MarkdownEditor.BlockButtons` exported.
61
+ `useMarkdownEditor()` gains `blockType` / `setBlockType`, `link` / `setLink`
62
+ and `hasSelection`. Toolbar dividers are `role="separator"`
63
+ - **Link bubble.** The link button opens an edit bubble (URL input, apply,
64
+ remove) rather than inserting a placeholder `https://` link: it needs a
65
+ non-empty selection (disabled for a bare caret, so it cannot link the whole
66
+ text node around the caret) and nothing is written to the document until a
67
+ URL is applied. Escape, moving the caret or focus leaving the bubble
68
+ abandons it without any `onValueChange`. `setLink(url)` is a no-op for a
69
+ collapsed caret outside a link; `EDIT_LINK_COMMAND` opens the bubble
70
+ - **Link safety.** `LinkPlugin` validates URLs with `isSafeUrl`:
71
+ `javascript:`, `data:` and other script-capable schemes are refused for
72
+ typed, pasted and bubble-entered links (`SAFE_LINK_PROTOCOLS`). HTML pastes
73
+ keep only the text of links whose `href` fails `isSafeUrl`, in the paste
74
+ normaliser and, via a paste-time `LinkNode` transform, on Lexical's
75
+ built-in paste path, so `javascript:` URLs never reach the emitted markdown
76
+ - **Form fields.** `id`, `name`, `aria-label`, `aria-labelledby`,
77
+ `aria-describedby`, `aria-invalid`, `aria-required` are forwarded to the
78
+ editable surface (`name` renders a hidden input with the markdown); a
79
+ visible `:focus-visible` ring on the surface (`--ring` / `--primary`)
80
+ replaces the removed outline; `maxLength` rejects input past the
81
+ plain-text limit, `onCharacterCountChange` reports the length,
82
+ `showCharacterCount` / `CharacterCount` render it
83
+ - **Controlled and uncontrolled editing.** `value` is truly controlled:
84
+ whenever the prop differs from the last markdown the editor emitted through
85
+ `onValueChange`, the document is replaced in one update (a single undo
86
+ step) and the caret is kept at the same position when it still exists.
87
+ `value=""` clears the editor. Hosts no longer need to `key`-remount the
88
+ editor to push content in. A remounted sync plugin (e.g. switching
89
+ `edit-raw` → `edit-rich`) always applies the host value, so an emptied raw
90
+ document comes back empty. New `defaultValue` prop for the uncontrolled
91
+ path; `edit-raw` without a `value` keeps its keystrokes (they were
92
+ discarded)
93
+ - **Sync.** `debounceMs` delays `onValueChange` (the document is never
94
+ delayed); a change still pending when the editor unmounts is delivered
95
+ instead of dropped, so the last keystrokes before a dialog closes or a
96
+ route changes reach the host. Updates that dirty no leaf and mark no
97
+ element on purpose skip serialisation, and a serialisation identical to
98
+ the last emitted value is not reported. A controlled `value` equal to one
99
+ of the last 8 emitted values from the last second is treated as a stale
100
+ echo and ignored instead of stomping what has been typed since
101
+ (`EMITTED_HISTORY`, `EMITTED_STALE_MS`); older values are re-imported so a
102
+ deliberate reset still wins
103
+ - **SSR.** `mode="view"` renders a non-editable fallback (the document's
104
+ block text, no `contenteditable`, no placeholder) on the server and until
105
+ hydration; the Lexical surface then mounts with the document already in
106
+ its state so the placeholder never flashes. `readOnly` renders
107
+ `contenteditable="false"` from the first paint
108
+ - New `onError` prop on `MarkdownEditor` / `MarkdownEditor.Root` (default
109
+ `console.error`), forwarded to Lexical
110
+ - **Round-trip escaping.** Image markdown percent-encodes whitespace and
111
+ parentheses in the source (on the node itself, so an uploaded
112
+ "my photo (1).png" stays an image) and backslash-escapes `]` in alt and
113
+ `"` in titles; mention markdown escapes `]` / `\` in names and
114
+ percent-encodes `%`, `)` and whitespace in ids. Values that used to
115
+ degrade to literal text now re-import
116
+ - **Accessibility.** An `aria-invalid` surface keeps the 2px focus ring
117
+ when focused (the danger line sits inside it); the character counter is
118
+ no longer a live region read on every keystroke: a hidden status announces
119
+ only when the document passes `maxLength` or returns within it
120
+ (`labels.limitExceeded` / `labels.limitRestored`)
121
+ - **Performance.** `DrawingNode.getData()` memoizes parsing on the payload
122
+ string; `normalizeDrawingData` takes an `onWarn` callback (default: one
123
+ console warning per session) instead of warning on every parse; the
124
+ toolbar keyboard hook only sweeps elements marked `data-toolbar-item`
125
+ (nested widgets keep their own focus handling) and measures the writing
126
+ direction once, not per keydown
127
+ - **Code highlighting.** TypeScript / TSX is its own grammar (`ts`, `tsx`,
128
+ `mts`, `cts`; type-level keywords, primitive types, utility types and
129
+ type arguments); `javascript` no longer answers to those aliases. 16
130
+ grammars. The registry loads the built-ins on first lookup, so no module
131
+ has import-time side effects apart from the stylesheet and
132
+ `suppress-global-highlighter`, which stops the Prism instance pulled in by
133
+ `@lexical/code` from re-highlighting the host page's own code blocks (both
134
+ are listed in `sideEffects`; keep them in `sideEffects`-sensitive bundler
135
+ configs)
136
+ - **Tokens.** The stylesheet no longer carries a foreign brand colour: the
137
+ outline marker, table selection and rail accent fall back to `--primary`
138
+ / `currentColor`; every radius reads `--radius-sm|md|lg|full`; the code
139
+ palette reads `--zui-code-<type>-light` / `-dark`, the canvas surface and
140
+ grid `--zui-drawing-surface-color` / `--zui-drawing-grid-color`, all with
141
+ the previous literals as fallbacks
142
+ - **Plugins.** Four opt-in first-party plugins, each on its own entry
143
+ point and on the default entry (not on `./markdown`): `./mentions`
144
+ (`MentionNode`, `MENTION`, `MentionsPlugin`: typeahead listbox with
145
+ `aria-activedescendant`, several triggers, `[@name](mention:id)`
146
+ markdown), `./comments` (`CommentsPlugin` on `@lexical/mark`: controlled
147
+ `comments`, floating add button, `Mod+Shift+M`, caret bubble,
148
+ `<!-- zui:comment id -->` markers), `./images` (`ImageNode`, `IMAGE`,
149
+ `ImagesPlugin`, `ImageButton`: paste / drop upload with a progress
150
+ placeholder, `accept` / `maxSize`, alt-text editing, `![alt](src)`
151
+ markdown) and `./paste` (`PastePlugin`, `normalizePastedHtml`: Word,
152
+ Google Docs, Confluence and Outlook HTML reduced to structure)
153
+ - Tests: the round-trip script is a `node --test` file that imports the
154
+ exported production transformer list; jsdom and axe-core are
155
+ devDependencies, so mounted tests fail instead of skipping
156
+ - Build: dist is minified and cleaned on every build (removes the stale
157
+ `dist/index.css`)
158
+
159
+ ## 0.11.1 — 2026-08-29
160
+
161
+ - Fix: mounting an editor no longer steals focus and scrolls to its first
162
+ code block. The initial markdown import and the one-off re-highlight of
163
+ existing code blocks now run with Lexical's `skip-dom-selection` tag, so
164
+ their selection stays internal until the user clicks in
165
+
166
+ ## 0.11.0 — 2026-08-27
4
167
 
5
168
  - Depends on **`@zuilib/tokens`** (optional peer) instead of `@zuilib/core`:
6
169
  the editor only ever consumed the design tokens, never a component.
@@ -10,7 +173,7 @@
10
173
  - Documented that a Tailwind host must `@source` this package for the
11
174
  document-content classes (headings, lists, code) to be generated
12
175
 
13
- ## 0.10.1
176
+ ## 0.10.1 — 2026-08-26
14
177
 
15
178
  - **Table columns** get the same rail as rows: a strip along the table's
16
179
  top edge with a bar on the caret's column and a `+` handle after the
@@ -28,7 +191,7 @@
28
191
  `$insertTableColumnNear`, `$deleteSelectedTableColumn`,
29
192
  `insertableColumnIndices`, `canDeleteColumn`
30
193
 
31
- ## 0.10.0
194
+ ## 0.10.0 — 2026-08-26
32
195
 
33
196
  - **Table rows.** Put the caret in a table and a **row rail** appears along
34
197
  its left edge: a bar marks the caret's row, and a `+` handle rests under
@@ -49,7 +212,7 @@
49
212
  - Rail and toolbar use the theme tokens (`--primary`, `--popover`,
50
213
  `--border`, `--shadow-medium`); motion respects `prefers-reduced-motion`
51
214
 
52
- ## 0.9.0
215
+ ## 0.9.0 — 2026-08-26
53
216
 
54
217
  - **Ink drawing style**: `drawingStyle="ink"` on the editor renders shapes
55
218
  as one seeded, pressure-varying pen stroke with misregistered fills and
@@ -57,7 +220,7 @@
57
220
  axes) when the host loads it. Renderer-only: the drawing format is
58
221
  unchanged. Geometry helpers are exported (`inkStroke`, `seedFrom`, …)
59
222
 
60
- ## 0.8.0
223
+ ## 0.8.0 — 2026-08-26
61
224
 
62
225
  - **Syntax highlighting** for fenced code blocks, driven by the package's
63
226
  own grammars instead of Prism: JavaScript/TypeScript, Kotlin, Java, C/C++,
@@ -72,7 +235,7 @@
72
235
  - Unknown languages get the same line structure as known ones, so cursor
73
236
  movement and indentation behave identically
74
237
 
75
- ## 0.7.2
238
+ ## 0.7.2 — 2026-08-25
76
239
 
77
240
  - Canvas properties are one **color** setting (outline plus its matching
78
241
  fill on boxes: plain (no outline), black, gray, red, green, blue, orange,
@@ -88,7 +251,7 @@
88
251
  - The floating table settings use the theme tokens (`--popover`,
89
252
  `--border`, `--shadow-medium`) instead of fixed light/dark colors
90
253
 
91
- ## 0.7.1
254
+ ## 0.7.1 — 2026-08-25
92
255
 
93
256
  - Fix: free `text` shapes could not be typed into. The text tool's editor
94
257
  opened on pointerdown and was blurred by the same click; it now opens on
@@ -100,7 +263,7 @@
100
263
  - Fix: keyboard shortcuts keep working after committing text (the canvas
101
264
  regains focus); `Home`/`End` work inside the inline text editor
102
265
 
103
- ## 0.7.0
266
+ ## 0.7.0 — 2026-08-25
104
267
 
105
268
  **Themed drawing canvas.** The canvas chrome now follows the host theme
106
269
  instead of shipping its own look.
@@ -119,7 +282,7 @@ instead of shipping its own look.
119
282
  - `--zui-drawing-dark-filter` exposes the dark-mode inversion of the
120
283
  drawing area (`none` opts out)
121
284
 
122
- ## 0.6.0
285
+ ## 0.6.0 — 2026-08-25
123
286
 
124
287
  **Text measure and `text` block width.** Additive: markdown, JSON, class
125
288
  names and props keep their meaning; with no configuration the layout is
@@ -171,7 +334,7 @@ unchanged.
171
334
  - **Adopting**: set `measure` (or the CSS variable) and delete any external
172
335
  `max-width` / `margin-inline` overrides on `.zui-text-editor-content > *`
173
336
 
174
- ## 0.5.0
337
+ ## 0.5.0 — 2026-08-25
175
338
 
176
339
  **Diagram builder rewrite.** The drawing canvas, its payload format and the
177
340
  authoring story for LLMs were rebuilt.
@@ -219,7 +382,7 @@ authoring story for LLMs were rebuilt.
219
382
  `shapes/`, `canvas/`); shape geometry is data-driven so the router,
220
383
  bindings, skeleton expansion and exporters run without a DOM
221
384
 
222
- ## 0.4.0
385
+ ## 0.4.0 — 2026-08-25
223
386
 
224
387
  - **Table density**, Slab-style: the floating table toolbar (caret in a
225
388
  table) gains *compact* / *comfortable* (default) / *spacious* row padding
@@ -234,7 +397,7 @@ authoring story for LLMs were rebuilt.
234
397
  `formatTableSettingsMarker`. `TABLE_WIDTH_MARKER` is deprecated in favour
235
398
  of `formatTableSettingsMarker`
236
399
 
237
- ## 0.3.1
400
+ ## 0.3.1 — 2026-08-25
238
401
 
239
402
  - **Block width** for tables and drawings: switch any table or drawing
240
403
  between *full width* (spans the editor, the previous behaviour) and
@@ -254,7 +417,7 @@ authoring story for LLMs were rebuilt.
254
417
  - New exports: `BlockWidth`, `$getTableWidth`, `$setTableWidth`,
255
418
  `$getSelectedTable`, `TABLE_WIDTH_MARKER`
256
419
 
257
- ## 0.3.0
420
+ ## 0.3.0 — 2026-08-23
258
421
 
259
422
  - **Custom toolbars**
260
423
  - `toolbar` prop accepts a render function receiving the default groups
@@ -270,7 +433,7 @@ authoring story for LLMs were rebuilt.
270
433
  - Internal: `LexicalComposer` is now mounted in `edit-raw` mode too, so
271
434
  hooks keep working across mode switches
272
435
 
273
- ## 0.2.1
436
+ ## 0.2.1 — 2026-08-09
274
437
 
275
438
  - `DRAWING_FORMAT.md`: authoritative spec of the ```drawing JSON payload,
276
439
  written for programmatic/LLM consumption; ships in the npm package
@@ -279,7 +442,7 @@ authoring story for LLMs were rebuilt.
279
442
  - New exports `parseDrawingData` / `serializeDrawingData`
280
443
  - This changelog; README overhaul
281
444
 
282
- ## 0.2.0
445
+ ## 0.2.0 — 2026-08-09
283
446
 
284
447
  - **Outline** (`outline` prop, default off): docked, collapsible
285
448
  table-of-contents sidebar — live heading list, click-to-scroll, current
@@ -288,7 +451,7 @@ authoring story for LLMs were rebuilt.
288
451
  under a heading via a gutter chevron; view-layer only (markdown
289
452
  untouched); auto-expands if the cursor enters a folded section
290
453
 
291
- ## 0.1.0
454
+ ## 0.1.0 — 2026-08-09
292
455
 
293
456
  - **Tables**: GFM pipe tables round-trip through markdown; artifact-style
294
457
  rendering; in-place editing via Lexical `TablePlugin`; new peer deps
@@ -305,7 +468,7 @@ authoring story for LLMs were rebuilt.
305
468
  - Stroke/fill palettes; dark mode via canvas color inversion
306
469
  - Round-trip test suite (`pnpm test`)
307
470
 
308
- ## 0.0.2 and earlier
471
+ ## 0.0.2 and earlier — 2026-04-17 to 2026-07-05
309
472
 
310
473
  - Markdown editor wrapping Lexical: `edit-md` / `edit-raw` / `view` modes,
311
474
  markdown shortcuts, checklists, fenced code highlighting, YAML
package/DRAWING_FORMAT.md CHANGED
@@ -7,13 +7,13 @@ fenced code blocks containing a single JSON object. Two languages exist:
7
7
  coordinates. The editor lays it out and expands it into a full drawing on
8
8
  import. **Generators should emit this one.** See
9
9
  [Prefer the ```diagram skeleton](#prefer-the-diagram-skeleton).
10
- - ```` ```drawing ```` holds the **concrete format** (version 2): every shape
10
+ - ```` ```drawing ```` holds the **concrete format** (version 3): every shape
11
11
  with its position, size and style. This is what the editor stores once a
12
12
  drawing has been edited.
13
13
 
14
14
  ````md
15
15
  ```drawing
16
- {"version":2,"canvasHeight":320,"shapes":[ ... ]}
16
+ {"version":3,"canvasHeight":320,"shapes":[ ... ]}
17
17
  ```
18
18
  ````
19
19
 
@@ -26,10 +26,12 @@ from the package as `DRAWING_DATA_JSON_SCHEMA` (concrete) and
26
26
  Malformed payloads never crash the editor: anything that fails validation
27
27
  degrades to an empty canvas (invalid shapes are dropped individually).
28
28
 
29
- Exactly one concrete format is supported: version 2, as written by the
30
- editor. Payloads with any other `version` (or none) render as an empty
31
- canvas. Convenience spellings such as `side` exist only in the ```diagram
32
- skeleton, which is a separate block type.
29
+ The editor writes version 3. Version 2 (identical except shape sizes were
30
+ spelled `w`/`h`) is migrated on read, so persisted drawings keep loading;
31
+ the editor re-serializes them as version 3. Payloads with any other
32
+ `version` (or none) render as an empty canvas. Convenience spellings such
33
+ as `side` exist only in the ```diagram skeleton, which is a separate block
34
+ type.
33
35
 
34
36
  ## Coordinate system
35
37
 
@@ -53,7 +55,7 @@ skeleton, which is a separate block type.
53
55
 
54
56
  | Field | Type | Notes |
55
57
  |----------------|-----------|--------------------------------------------------------------|
56
- | `version` | `2` | Literal `2` |
58
+ | `version` | `3` | Literal `3` (`2` accepted on read: shape `w`/`h` migrate to `width`/`height`) |
57
59
  | `canvasHeight` | `number` | Canvas height in px (min 80) |
58
60
  | `canvasWidth` | `number` | Optional logical width in px (min 120); scales to fit when set |
59
61
  | `width` | `"full"` \| `"text"` \| `"content"` | Optional; default `"full"`. `"text"` aligns with the text column, `"content"` fits the shapes' extent |
@@ -68,7 +70,7 @@ All shapes share these required fields:
68
70
  | `id` | `string` | Unique within the drawing; bindings reference it |
69
71
  | `type` | `string` | One of the types below |
70
72
  | `x`, `y` | `number` | Boxes/text: top-left of the bounding box. Connectors: start point. |
71
- | `w`, `h` | `number` | Boxes/text: size (non-negative). Connectors: delta to the end point (`end = (x+w, y+h)`; may be negative). |
73
+ | `width`, `height` | `number` | Boxes/text: size (non-negative). Connectors: delta to the end point (`end = (x+width, y+height)`; may be negative). |
72
74
  | `stroke` | `string` | CSS color of the outline and of all text on the shape |
73
75
  | `fill` | `string` | CSS color of the interior; `"transparent"` for none |
74
76
  | `strokeWidth` | `number` | Use `2` |
@@ -109,14 +111,14 @@ floating `text` shapes; slot text is attached to the card.
109
111
 
110
112
  ### `text`: free-floating annotation
111
113
 
112
- `text` holds the content. `w`/`h` are advisory (the editor recomputes them
114
+ `text` holds the content. `width`/`height` are advisory (the editor recomputes them
113
115
  from the content); position is the top-left of the first line. Use only for
114
116
  annotations that belong to no box (the editor deletes a text shape when its
115
117
  content is emptied).
116
118
 
117
119
  ### Connectors (`arrow`, `line`)
118
120
 
119
- Geometry: from `(x, y)` to `(x+w, y+h)`. `arrow` has a head at the end;
121
+ Geometry: from `(x, y)` to `(x+width, y+height)`. `arrow` has a head at the end;
120
122
  `line` has none.
121
123
 
122
124
  | Field | Type | Meaning |
@@ -156,7 +158,7 @@ the box moves:
156
158
  (useful for lines that end inside a shape).
157
159
 
158
160
  Bound endpoints are re-anchored by the editor, so the connector's own
159
- `x`/`y`/`w`/`h` only need to be approximately right: place them near the
161
+ `x`/`y`/`width`/`height` only need to be approximately right: place them near the
160
162
  intended boxes and the resolver snaps them. Don't bind both ends of one
161
163
  connector to the same box.
162
164
 
@@ -266,7 +268,7 @@ A decision with attach sides and elbow routing, flowing down:
266
268
  ````
267
269
 
268
270
  Programmatic use: `parseDrawingSkeleton(json)` parses a skeleton,
269
- `expandSkeleton(skeleton)` returns `DrawingData`, and
271
+ `expandDrawingSkeleton(skeleton)` returns `DrawingData`, and
270
272
  `DRAWING_SKELETON_JSON_SCHEMA` is the JSON Schema. Types: `DrawingSkeleton`,
271
273
  `SkeletonBox`, `SkeletonConnector`.
272
274
 
@@ -276,10 +278,10 @@ Two bound cards with a labeled arrow:
276
278
 
277
279
  ````md
278
280
  ```drawing
279
- {"version":2,"canvasHeight":260,"shapes":[
280
- {"id":"web","type":"rect","x":40,"y":70,"w":170,"h":100,"stroke":"#1971c2","fill":"#a5d8ff","strokeWidth":2,"label":"CLIENT","text":"Web App","footer":"React"},
281
- {"id":"api","type":"rect","x":330,"y":70,"w":170,"h":100,"stroke":"#2f9e44","fill":"#b2f2bb","strokeWidth":2,"label":"SERVICE","text":"API","footer":"Kotlin"},
282
- {"id":"e1","type":"arrow","x":216,"y":120,"w":108,"h":0,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"startBinding":{"id":"web"},"endBinding":{"id":"api"},"text":"REST"}
281
+ {"version":3,"canvasHeight":260,"shapes":[
282
+ {"id":"web","type":"rect","x":40,"y":70,"width":170,"height":100,"stroke":"#1971c2","fill":"#a5d8ff","strokeWidth":2,"label":"CLIENT","text":"Web App","footer":"React"},
283
+ {"id":"api","type":"rect","x":330,"y":70,"width":170,"height":100,"stroke":"#2f9e44","fill":"#b2f2bb","strokeWidth":2,"label":"SERVICE","text":"API","footer":"Kotlin"},
284
+ {"id":"e1","type":"arrow","x":216,"y":120,"width":108,"height":0,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"startBinding":{"id":"web"},"endBinding":{"id":"api"},"text":"REST"}
283
285
  ]}
284
286
  ```
285
287
  ````
@@ -289,11 +291,11 @@ line:
289
291
 
290
292
  ````md
291
293
  ```drawing
292
- {"version":2,"canvasHeight":300,"canvasWidth":640,"shapes":[
293
- {"id":"a","type":"rect","x":40,"y":40,"w":150,"h":80,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"text":"A"},
294
- {"id":"b","type":"cylinder","x":420,"y":180,"w":140,"h":110,"stroke":"#7048e8","fill":"#d0bfff","strokeWidth":2,"text":"B"},
295
- {"id":"e1","type":"arrow","x":190,"y":80,"w":300,"h":100,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"startBinding":{"id":"a","fixedPoint":[1,0.5]},"endBinding":{"id":"b","fixedPoint":[0.5,0]},"routing":"elbow"},
296
- {"id":"e2","type":"line","x":115,"y":126,"w":375,"h":54,"stroke":"#1971c2","fill":"transparent","strokeWidth":2,"startBinding":{"id":"a"},"endBinding":{"id":"b"},"waypoints":[{"x":115,"y":260},{"x":490,"y":260}]}
294
+ {"version":3,"canvasHeight":300,"canvasWidth":640,"shapes":[
295
+ {"id":"a","type":"rect","x":40,"y":40,"width":150,"height":80,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"text":"A"},
296
+ {"id":"b","type":"cylinder","x":420,"y":180,"width":140,"height":110,"stroke":"#7048e8","fill":"#d0bfff","strokeWidth":2,"text":"B"},
297
+ {"id":"e1","type":"arrow","x":190,"y":80,"width":300,"height":100,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"startBinding":{"id":"a","fixedPoint":[1,0.5]},"endBinding":{"id":"b","fixedPoint":[0.5,0]},"routing":"elbow"},
298
+ {"id":"e2","type":"line","x":115,"y":126,"width":375,"height":54,"stroke":"#1971c2","fill":"transparent","strokeWidth":2,"startBinding":{"id":"a"},"endBinding":{"id":"b"},"waypoints":[{"x":115,"y":260},{"x":490,"y":260}]}
297
299
  ]}
298
300
  ```
299
301
  ````