@zuilib/text-editor 0.3.1 → 0.5.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 +63 -0
- package/DRAWING_FORMAT.md +240 -66
- package/README.md +121 -48
- package/dist/index.d.ts +522 -58
- package/dist/index.js +3308 -1361
- package/dist/styles.css +336 -91
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,11 +13,14 @@ document outline, and collapsible sections.
|
|
|
13
13
|
blockquotes, links, fenced code (with syntax highlighting), tables
|
|
14
14
|
- **Tables**: GFM pipe tables, edited in place (tab between cells, ranges,
|
|
15
15
|
inline formatting), styled like Claude artifacts
|
|
16
|
-
- **
|
|
17
|
-
content width
|
|
18
|
-
- **Diagrams**: a drawing canvas embedded in the document
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
- **Table settings**: full/content width and row density per table;
|
|
17
|
+
diagrams switch between full and content width too — Slab-style
|
|
18
|
+
- **Diagrams**: a drawing canvas embedded in the document. Eight box
|
|
19
|
+
shapes (rectangle, ellipse, diamond, note, database, cloud, queue, actor)
|
|
20
|
+
with attached text slots, bound arrows that follow their boxes and attach
|
|
21
|
+
to a chosen side, auto-routed elbows that avoid other boxes, multi-select,
|
|
22
|
+
color palettes, dark mode, Mermaid export. LLMs author diagrams as a
|
|
23
|
+
coordinate-free ` ```diagram ` skeleton that the editor lays out
|
|
21
24
|
- **Outline**: optional table-of-contents sidebar with click-to-scroll and
|
|
22
25
|
current-section highlight
|
|
23
26
|
- **Section folding**: collapse everything under a heading, view-layer only
|
|
@@ -98,26 +101,33 @@ Editing is in place: Tab/arrows between cells, cell range selection, inline
|
|
|
98
101
|
formatting inside cells. Cell content is single-line in markdown; newlines
|
|
99
102
|
are escaped as `\n`.
|
|
100
103
|
|
|
101
|
-
###
|
|
104
|
+
### Table settings: width and density
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
Place the caret in a table and a small toolbar floats at its top-right
|
|
107
|
+
corner:
|
|
108
|
+
|
|
109
|
+
- **Width** — *full* (default: columns share the editor width) or
|
|
110
|
+
*content* (the table shrinks to fit its columns, left-aligned with the
|
|
111
|
+
text, never wider than the editor).
|
|
112
|
+
- **Density** — *compact*, *comfortable* (default), or *spacious* cell
|
|
113
|
+
padding and font size.
|
|
114
|
+
|
|
115
|
+
Non-default settings are persisted as one HTML comment on the line directly
|
|
116
|
+
above the table — other markdown renderers hide it:
|
|
109
117
|
|
|
110
118
|
```md
|
|
111
|
-
<!-- width: content -->
|
|
119
|
+
<!-- width: content; density: compact -->
|
|
112
120
|
| Key | Value |
|
|
113
121
|
| --- | --- |
|
|
114
122
|
| Region | eu-west-1 |
|
|
115
123
|
```
|
|
116
124
|
|
|
117
|
-
Programmatic access: `useMarkdownEditor().tableWidth` / `setTableWidth`
|
|
118
|
-
(for custom toolbars), or
|
|
119
|
-
|
|
120
|
-
`
|
|
125
|
+
Programmatic access: `useMarkdownEditor().tableWidth` / `setTableWidth` and
|
|
126
|
+
`tableDensity` / `setTableDensity` (for custom toolbars), or
|
|
127
|
+
`$getTableSettings(node)` / `$setTableSettings(node, { width, density })`
|
|
128
|
+
inside `editor.update`. `parseTableSettingsMarker` /
|
|
129
|
+
`formatTableSettingsMarker` convert between the comment line and a
|
|
130
|
+
`TableSettings` object.
|
|
121
131
|
|
|
122
132
|
## Toolbar & custom toolbars
|
|
123
133
|
|
|
@@ -203,35 +213,86 @@ function BoldButton() {
|
|
|
203
213
|
|
|
204
214
|
It returns `editor` (the Lexical instance), `activeFormats`,
|
|
205
215
|
`toggleFormat`, `insertTable`, `insertDrawing`, `tableWidth` /
|
|
206
|
-
`setTableWidth`
|
|
207
|
-
outside tables), `canUndo`,
|
|
216
|
+
`setTableWidth` and `tableDensity` / `setTableDensity` (settings of the
|
|
217
|
+
table containing the selection, `null` outside tables), `canUndo`,
|
|
218
|
+
`canRedo`, `undo`, `redo`.
|
|
208
219
|
|
|
209
220
|
## Diagrams (drawing canvas)
|
|
210
221
|
|
|
211
222
|
The toolbar's insert-drawing button embeds a canvas; the drawing persists
|
|
212
|
-
in the markdown as a ` ```drawing ` fenced JSON block
|
|
213
|
-
**[DRAWING_FORMAT.md](./DRAWING_FORMAT.md)**.
|
|
223
|
+
in the markdown as a ` ```drawing ` fenced JSON block (format version 2),
|
|
224
|
+
fully specified in **[DRAWING_FORMAT.md](./DRAWING_FORMAT.md)**.
|
|
214
225
|
|
|
215
|
-
- **Shapes**: rectangle, ellipse,
|
|
216
|
-
|
|
226
|
+
- **Shapes**: rectangle, ellipse, diamond, note (sticky note), database
|
|
227
|
+
(cylinder), cloud, queue, actor (stick figure), arrow, line, text. The
|
|
228
|
+
toolbar shows the common tools and a "more shapes" popover for the rest.
|
|
229
|
+
Draw by picking a tool and dragging.
|
|
217
230
|
- **Cards**: every box carries three text slots that move, resize, and wrap
|
|
218
|
-
with it
|
|
219
|
-
**footer** at the bottom
|
|
220
|
-
top/middle/bottom strip, or
|
|
231
|
+
with it: a bold **label** on top, **content** in the center, a dim
|
|
232
|
+
**footer** at the bottom (actor has only the name under the figure).
|
|
233
|
+
Click a selected box (or double-click its top/middle/bottom strip, or
|
|
234
|
+
press Enter) to edit a slot.
|
|
221
235
|
- **Bound connectors**: an arrow drawn from one card to another attaches to
|
|
222
|
-
both
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
236
|
+
both; moving a card moves its arrows, endpoints anchored to the outline.
|
|
237
|
+
An endpoint either auto-aims at the other end or sticks to a fixed point
|
|
238
|
+
on the box (a side, or a ratio inside the box). Drag an endpoint off/onto
|
|
239
|
+
a card to detach/re-attach.
|
|
240
|
+
- **Routing**: straight (diagonal) by default; toggle **elbow** for an
|
|
241
|
+
auto-routed right-angled path that leaves the box perpendicular to its
|
|
242
|
+
attach side and avoids the other boxes, or drag the dashed "+" handles on
|
|
243
|
+
a selected connector to add any number of **waypoints** (they snap to
|
|
244
|
+
neighbors' axes for clean 90° bends). One-way / two-way arrowhead toggle;
|
|
245
|
+
midpoint **labels**.
|
|
246
|
+
- **Multi-select**: shift-click, or drag a marquee on empty canvas, then
|
|
247
|
+
move, delete, or recolor the selection together. A contextual property
|
|
248
|
+
bar shows the options for whatever is selected.
|
|
249
|
+
- **Copy as Mermaid**: a canvas button copies the drawing as a Mermaid
|
|
250
|
+
`flowchart` (also available as `drawingToMermaid(data)`).
|
|
228
251
|
- **Canvas**: resizable height, dot grid, white surface that inverts
|
|
229
|
-
Excalidraw-style in dark mode (`.dark` ancestor class).
|
|
252
|
+
Excalidraw-style in dark mode (`.dark` ancestor class). An optional
|
|
253
|
+
`canvasWidth` scales the drawing to fit narrower layouts.
|
|
230
254
|
- **Width**: the toggle at the right end of the canvas toolbar switches
|
|
231
255
|
between **full width** (spans the editor) and **content width** (the
|
|
232
256
|
canvas fits the rightmost shape and grows as shapes move). Stored as
|
|
233
257
|
`"width":"content"` in the payload; omitted when full.
|
|
234
258
|
|
|
259
|
+
A stored drawing looks like this:
|
|
260
|
+
|
|
261
|
+
````md
|
|
262
|
+
```drawing
|
|
263
|
+
{"version":2,"canvasHeight":260,"shapes":[
|
|
264
|
+
{"id":"web","type":"rect","x":40,"y":70,"w":170,"h":100,"stroke":"#1971c2","fill":"#a5d8ff","strokeWidth":2,"label":"CLIENT","text":"Web App"},
|
|
265
|
+
{"id":"api","type":"rect","x":330,"y":70,"w":170,"h":100,"stroke":"#2f9e44","fill":"#b2f2bb","strokeWidth":2,"label":"SERVICE","text":"API"},
|
|
266
|
+
{"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"}
|
|
267
|
+
]}
|
|
268
|
+
```
|
|
269
|
+
````
|
|
270
|
+
|
|
271
|
+
### The ` ```diagram ` skeleton
|
|
272
|
+
|
|
273
|
+
Generators (LLMs, scripts) do not need coordinates. A ` ```diagram ` block
|
|
274
|
+
holds a skeleton: boxes, connectors, colors. On import the editor lays it
|
|
275
|
+
out along `direction` (`right` by default, or `down`), sizes boxes to their
|
|
276
|
+
text, and stores the result as a normal ` ```drawing ` block (one-way
|
|
277
|
+
expansion).
|
|
278
|
+
|
|
279
|
+
````md
|
|
280
|
+
```diagram
|
|
281
|
+
{"boxes":[
|
|
282
|
+
{"id":"web","label":"CLIENT","text":"Web App","color":"blue"},
|
|
283
|
+
{"id":"api","label":"SERVICE","text":"API","color":"green"},
|
|
284
|
+
{"id":"db","type":"cylinder","text":"Postgres"}
|
|
285
|
+
],"connectors":[
|
|
286
|
+
{"from":"web","to":"api","text":"REST"},
|
|
287
|
+
{"from":"api","to":"db","routing":"elbow"}
|
|
288
|
+
]}
|
|
289
|
+
```
|
|
290
|
+
````
|
|
291
|
+
|
|
292
|
+
The full skeleton spec (attach sides, explicit positions, free texts) is
|
|
293
|
+
in [DRAWING_FORMAT.md](./DRAWING_FORMAT.md). Programmatic access:
|
|
294
|
+
`parseDrawingSkeleton`, `expandSkeleton`, `DRAWING_SKELETON_JSON_SCHEMA`.
|
|
295
|
+
|
|
235
296
|
## Outline & section folding
|
|
236
297
|
|
|
237
298
|
`outline` docks a collapsible table-of-contents sidebar: live heading list
|
|
@@ -248,14 +309,19 @@ remount; a folded section auto-expands if the cursor enters it.
|
|
|
248
309
|
Documents are plain markdown, so LLMs can generate them — including
|
|
249
310
|
diagrams:
|
|
250
311
|
|
|
251
|
-
-
|
|
252
|
-
` ```drawing `
|
|
253
|
-
|
|
254
|
-
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
- `
|
|
258
|
-
|
|
312
|
+
- Emit ` ```diagram ` skeleton blocks: no coordinates, the editor lays them
|
|
313
|
+
out. Use ` ```drawing ` (format v2) only to edit an existing concrete
|
|
314
|
+
payload.
|
|
315
|
+
- **[DRAWING_FORMAT.md](./DRAWING_FORMAT.md)** is the authoritative spec of
|
|
316
|
+
both payloads, written to be pasted into a prompt (ships in the npm
|
|
317
|
+
package next to this README).
|
|
318
|
+
- `DRAWING_SKELETON_JSON_SCHEMA` and `DRAWING_DATA_JSON_SCHEMA` (exported)
|
|
319
|
+
are the same contracts as JSON Schema: use them to validate generated
|
|
320
|
+
payloads or as structured-output/tool schemas.
|
|
321
|
+
- `parseDrawingSkeleton(json)` / `expandSkeleton(skeleton)` turn a skeleton
|
|
322
|
+
into `DrawingData`. `parseDrawingData(json)` is the editor's own lenient
|
|
323
|
+
parser (invalid shapes drop out; never throws); `serializeDrawingData` is
|
|
324
|
+
its inverse. `drawingToMermaid(data)` exports a Mermaid `flowchart`.
|
|
259
325
|
- A ready-made Claude Code skill lives in the monorepo at
|
|
260
326
|
`.claude/skills/text-editor-documents/` — copy it into consuming repos so
|
|
261
327
|
agents there know the dialect.
|
|
@@ -269,12 +335,17 @@ diagrams:
|
|
|
269
335
|
| `Toolbar`, `ToolbarButton`, `ToolbarDivider`, `FormatButtons`, `InsertButtons`, `HistoryButtons` | Toolbar primitives |
|
|
270
336
|
| `@zuilib/text-editor/styles.css` | Editor chrome + theme styles (required) |
|
|
271
337
|
| `TABLE` | GFM table markdown transformer |
|
|
272
|
-
| `BlockWidth`,
|
|
273
|
-
|
|
|
338
|
+
| `BlockWidth`, `TableDensity`, `TableSettings`, `DEFAULT_TABLE_SETTINGS` | Table setting types |
|
|
339
|
+
| `$getTableSettings`, `$setTableSettings`, `$getTableWidth`, `$setTableWidth`, `$getTableDensity`, `$setTableDensity`, `$getSelectedTable` | Table setting helpers (inside `editor.update`/`read`) |
|
|
340
|
+
| `parseTableSettingsMarker`, `formatTableSettingsMarker` | Marker comment ⇄ `TableSettings` |
|
|
341
|
+
| `DRAWING`, `DIAGRAM`, `DrawingNode`, `$createDrawingNode`, `$isDrawingNode` | Drawing node + markdown transformers (` ```drawing ` and ` ```diagram `) |
|
|
274
342
|
| `FRONTMATTER`, `FrontmatterNode`, `$createFrontmatterNode`, `$isFrontmatterNode` | Frontmatter node + transformer |
|
|
275
343
|
| `DrawingData`, `DrawingShape`, `DrawingShapeType` | Drawing payload types |
|
|
276
344
|
| `parseDrawingData`, `serializeDrawingData` | Drawing payload (de)serialization |
|
|
277
345
|
| `DRAWING_DATA_JSON_SCHEMA` | JSON Schema of the drawing payload |
|
|
346
|
+
| `DrawingSkeleton`, `SkeletonBox`, `SkeletonConnector` | Skeleton types |
|
|
347
|
+
| `parseDrawingSkeleton`, `expandSkeleton`, `DRAWING_SKELETON_JSON_SCHEMA` | Skeleton parsing, expansion to `DrawingData`, JSON Schema |
|
|
348
|
+
| `drawingToMermaid` | Mermaid `flowchart` export |
|
|
278
349
|
|
|
279
350
|
## Form integration
|
|
280
351
|
|
|
@@ -295,13 +366,15 @@ ZUI convention: a `dark` class on `<html>`.
|
|
|
295
366
|
- Source: `src/EditorRoot.tsx` (composer + plugins), `src/EditorContent.tsx`,
|
|
296
367
|
`src/MarkdownEditor.tsx` (default composition), `src/useMarkdownEditor.ts`,
|
|
297
368
|
`src/components/Toolbar.tsx`; plugins in `src/plugins/`; drawing
|
|
298
|
-
canvas in `src/
|
|
369
|
+
canvas in `src/drawing/`; custom nodes in `src/nodes/`;
|
|
299
370
|
transformers in `src/transformers/`
|
|
300
371
|
- Markdown import/export via `@lexical/markdown` transformers; order
|
|
301
|
-
matters: `FRONTMATTER` and `
|
|
302
|
-
`CHECK_LIST` before `UNORDERED_LIST`
|
|
303
|
-
-
|
|
304
|
-
|
|
372
|
+
matters: `FRONTMATTER`, `DRAWING` and `DIAGRAM` claim their blocks before
|
|
373
|
+
`CODE`, `CHECK_LIST` before `UNORDERED_LIST`
|
|
374
|
+
- `src/drawing/` keeps the format (`types.ts`, `schema.ts`), shape
|
|
375
|
+
definitions (`shapes/`), pure geometry (`geometry.ts`), the Mermaid
|
|
376
|
+
exporter (`mermaid.ts`) and the React canvas (`canvas/`) apart, so the
|
|
377
|
+
router, bindings and skeleton expansion run without a DOM
|
|
305
378
|
- Tests: `pnpm test` runs a headless-Lexical markdown round-trip suite
|
|
306
379
|
(`tests/roundtrip.mjs`)
|
|
307
380
|
|