@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.
- package/CHANGELOG.md +180 -17
- package/DRAWING_FORMAT.md +23 -21
- package/README.md +486 -68
- package/dist/chunk-32RX4GZF.js +2 -0
- package/dist/chunk-3TZVOXWX.js +16 -0
- package/dist/chunk-5VRVC56Y.js +2 -0
- package/dist/chunk-7Z3CW6Q3.js +2 -0
- package/dist/chunk-A7MCBSAZ.js +2 -0
- package/dist/chunk-AGTPMKLK.js +2 -0
- package/dist/chunk-C7VEINKX.js +2 -0
- package/dist/chunk-LDVPFZCN.js +2 -0
- package/dist/chunk-N5JWZ2VW.js +9 -0
- package/dist/chunk-QKHMJQO3.js +2 -0
- package/dist/chunk-R5PL4Q7X.js +5 -0
- package/dist/chunk-SDICQI2B.js +2 -0
- package/dist/chunk-TGVEPLDM.js +1 -0
- package/dist/chunk-XP3MZRCW.js +2 -0
- package/dist/chunk-XRJNLGI4.js +2 -0
- package/dist/chunk-YFFSTMIR.js +2 -0
- package/dist/chunk-ZXZMYJ7F.js +2 -0
- package/dist/comment-markers-BrrrAdSL.d.ts +27 -0
- package/dist/comments.d.ts +68 -0
- package/dist/comments.js +2 -0
- package/dist/drawing-data-EWzEQ1_i.d.ts +111 -0
- package/dist/drawing-preset-Ag7a7F9h.d.ts +69 -0
- package/dist/drawing.d.ts +7 -0
- package/dist/drawing.js +2 -0
- package/dist/image-node-kR1Zf5kz.d.ts +70 -0
- package/dist/images.d.ts +66 -0
- package/dist/images.js +2 -0
- package/dist/index-A4S7bRwQ.d.ts +425 -0
- package/dist/index.d.ts +36 -1394
- package/dist/index.js +2 -7447
- package/dist/lexical.d.ts +117 -0
- package/dist/lexical.js +2 -0
- package/dist/markdown.d.ts +29 -0
- package/dist/markdown.js +2 -0
- package/dist/mention-node-eSsjUpaE.d.ts +44 -0
- package/dist/mentions-plugin-gio3_XKd.d.ts +74 -0
- package/dist/mentions.d.ts +5 -0
- package/dist/mentions.js +2 -0
- package/dist/mermaid-BwGHjwpk.d.ts +553 -0
- package/dist/paste.d.ts +45 -0
- package/dist/paste.js +2 -0
- package/dist/presets-BtNPH0pa.d.ts +78 -0
- package/dist/styles.css +406 -99
- package/dist/table-grid-D70tNhp2.d.ts +459 -0
- package/package.json +57 -12
- package/dist/index.css +0 -79
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,169 @@
|
|
|
1
1
|
# Changelog — @zuilib/text-editor
|
|
2
2
|
|
|
3
|
-
## 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, ``
|
|
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
|
|
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":
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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` | `
|
|
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
|
-
| `
|
|
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. `
|
|
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+
|
|
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`/`
|
|
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
|
-
`
|
|
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":
|
|
280
|
-
{"id":"web","type":"rect","x":40,"y":70,"
|
|
281
|
-
{"id":"api","type":"rect","x":330,"y":70,"
|
|
282
|
-
{"id":"e1","type":"arrow","x":216,"y":120,"
|
|
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":
|
|
293
|
-
{"id":"a","type":"rect","x":40,"y":40,"
|
|
294
|
-
{"id":"b","type":"cylinder","x":420,"y":180,"
|
|
295
|
-
{"id":"e1","type":"arrow","x":190,"y":80,"
|
|
296
|
-
{"id":"e2","type":"line","x":115,"y":126,"
|
|
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
|
````
|