@zuilib/text-editor 0.10.0 → 0.11.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 +28 -0
- package/README.md +41 -25
- package/dist/index.d.ts +54 -27
- package/dist/index.js +283 -270
- package/dist/styles.css +78 -34
- package/package.json +9 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog — @zuilib/text-editor
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
- Depends on **`@zuilib/tokens`** (optional peer) instead of `@zuilib/core`:
|
|
6
|
+
the editor only ever consumed the design tokens, never a component.
|
|
7
|
+
Load `@zuilib/tokens/styles.css` (or `tokens.css` without Tailwind) where
|
|
8
|
+
you previously loaded `@zuilib/core/styles.css`; without it the editor
|
|
9
|
+
falls back to its built-in defaults
|
|
10
|
+
- Documented that a Tailwind host must `@source` this package for the
|
|
11
|
+
document-content classes (headings, lists, code) to be generated
|
|
12
|
+
|
|
13
|
+
## 0.10.1
|
|
14
|
+
|
|
15
|
+
- **Table columns** get the same rail as rows: a strip along the table's
|
|
16
|
+
top edge with a bar on the caret's column and a `+` handle after the
|
|
17
|
+
last column that snaps to column boundaries while hovered
|
|
18
|
+
- **Deleting moves onto the rails.** The handle follows the pointer: near a
|
|
19
|
+
boundary it is a `+` (insert; hover previews the line), over the middle
|
|
20
|
+
of a row / column it is a `−` that removes it (hover tints what goes).
|
|
21
|
+
The three row buttons added to the floating toolbar in 0.10.0 are gone
|
|
22
|
+
- The layout toolbar now floats **above the table**, stacked over the
|
|
23
|
+
column rail at the top-right corner
|
|
24
|
+
- `useMarkdownEditor()`: `tableRow` is now `tableCell` (`{ row, column,
|
|
25
|
+
rows, columns, hasHeader }`); adds `insertTableColumn(position)` and
|
|
26
|
+
`deleteTableColumn()`. Node helpers: `$getTableCellPosition` (was
|
|
27
|
+
`$getTableRowPosition`), `$insertTableColumnAt`, `$deleteTableColumnAt`,
|
|
28
|
+
`$insertTableColumnNear`, `$deleteSelectedTableColumn`,
|
|
29
|
+
`insertableColumnIndices`, `canDeleteColumn`
|
|
30
|
+
|
|
3
31
|
## 0.10.0
|
|
4
32
|
|
|
5
33
|
- **Table rows.** Put the caret in a table and a **row rail** appears along
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ document outline, and collapsible sections.
|
|
|
12
12
|
- **Markdown shortcuts** while typing: headings, lists, checklists,
|
|
13
13
|
blockquotes, links, fenced code (with syntax highlighting), tables
|
|
14
14
|
- **Tables**: GFM pipe tables, edited in place (tab between cells, ranges,
|
|
15
|
-
add / remove rows from
|
|
15
|
+
add / remove rows and columns from hover rails or the keyboard,
|
|
16
16
|
inline formatting), styled like Claude artifacts
|
|
17
17
|
- **Text measure and block width**: an opt-in readable text column
|
|
18
18
|
(`measure="48rem"`); each table and diagram picks *full* / *text* /
|
|
@@ -36,7 +36,7 @@ frontmatter as `---` blocks. Feature history: [CHANGELOG](./CHANGELOG.md).
|
|
|
36
36
|
## Installation
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
pnpm add @zuilib/text-editor @zuilib/
|
|
39
|
+
pnpm add @zuilib/text-editor @zuilib/tokens \
|
|
40
40
|
lexical @lexical/react @lexical/markdown @lexical/rich-text \
|
|
41
41
|
@lexical/code @lexical/list @lexical/link @lexical/table @lexical/utils
|
|
42
42
|
```
|
|
@@ -48,7 +48,7 @@ All `lexical`/`@lexical/*` packages are peer dependencies at `^0.35.0`;
|
|
|
48
48
|
|
|
49
49
|
```tsx
|
|
50
50
|
import { useState } from 'react'
|
|
51
|
-
import '@zuilib/
|
|
51
|
+
import '@zuilib/tokens/styles.css'
|
|
52
52
|
import '@zuilib/text-editor/styles.css'
|
|
53
53
|
import { MarkdownEditor } from '@zuilib/text-editor'
|
|
54
54
|
|
|
@@ -105,15 +105,16 @@ Editing is in place: Tab/arrows between cells, cell range selection, inline
|
|
|
105
105
|
formatting inside cells. Cell content is single-line in markdown; newlines
|
|
106
106
|
are escaped as `\n`.
|
|
107
107
|
|
|
108
|
-
### Rows
|
|
108
|
+
### Rows and columns
|
|
109
109
|
|
|
110
|
-
Click into a table and
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
Click into a table and two slim **rails** appear: one along its left edge
|
|
111
|
+
for rows, one along its top edge for columns. A bar on each marks the row
|
|
112
|
+
and column the caret is in, and a `+` handle rests after the last row /
|
|
113
|
+
column: click it to append one. Move the pointer over a rail and the handle
|
|
114
|
+
follows it — near a boundary it is a `+` that inserts there (hovering it
|
|
115
|
+
previews the insertion as a line across the table), over the middle of a
|
|
116
|
+
row or column it becomes a `−` that removes it (hovering tints what will
|
|
117
|
+
go). The caret moves into whatever was inserted.
|
|
117
118
|
|
|
118
119
|
Keyboard, inside a table:
|
|
119
120
|
|
|
@@ -125,19 +126,21 @@ Keyboard, inside a table:
|
|
|
125
126
|
| `Tab` in the last cell | Append a row |
|
|
126
127
|
|
|
127
128
|
GFM tables have exactly one header row, the first, so nothing is inserted
|
|
128
|
-
above it (`above` there inserts right below the header)
|
|
129
|
-
header row makes the next row the header
|
|
130
|
-
deleted.
|
|
131
|
-
|
|
132
|
-
Programmatic access: `useMarkdownEditor().
|
|
133
|
-
|
|
134
|
-
`deleteTableRow()
|
|
135
|
-
|
|
136
|
-
|
|
129
|
+
above it (`above` there inserts right below the header), deleting the
|
|
130
|
+
header row makes the next row the header, and a new column gets a header
|
|
131
|
+
cell. The last remaining row or column can't be deleted.
|
|
132
|
+
|
|
133
|
+
Programmatic access: `useMarkdownEditor().tableCell` (`{ row, column,
|
|
134
|
+
rows, columns, hasHeader }` or `null`), `insertTableRow('above' | 'below')`,
|
|
135
|
+
`deleteTableRow()`, `insertTableColumn('before' | 'after')` and
|
|
136
|
+
`deleteTableColumn()`; or, inside `editor.update`, `$insertTableRowAt(table,
|
|
137
|
+
index)`, `$deleteTableRowAt(table, index)`, `$insertTableColumnAt(table,
|
|
138
|
+
index)`, `$deleteTableColumnAt(table, index)` and their `*Near` /
|
|
139
|
+
`$deleteSelected*` selection-relative forms.
|
|
137
140
|
|
|
138
141
|
### Table density
|
|
139
142
|
|
|
140
|
-
Place the caret in a table and a small toolbar floats
|
|
143
|
+
Place the caret in a table and a small toolbar floats above its top-right
|
|
141
144
|
corner with the table's width (see [Block width and text
|
|
142
145
|
measure](#block-width-and-text-measure)) and its **density** — *compact*,
|
|
143
146
|
*comfortable* (default), or *spacious* cell padding and font size.
|
|
@@ -303,8 +306,8 @@ It returns `editor` (the Lexical instance), `activeFormats`,
|
|
|
303
306
|
`toggleFormat`, `insertTable`, `insertDrawing`, `blockWidth` /
|
|
304
307
|
`setBlockWidth` (width of the table or drawing containing the selection,
|
|
305
308
|
`null` outside both), `tableDensity` / `setTableDensity` (`null` outside
|
|
306
|
-
tables), `
|
|
307
|
-
[Rows](#rows)), `canUndo`, `canRedo`, `undo`, `redo`. `tableWidth` /
|
|
309
|
+
tables), `tableCell` / `insertTableRow` / `deleteTableRow` / `insertTableColumn` /
|
|
310
|
+
`deleteTableColumn` (see [Rows and columns](#rows-and-columns)), `canUndo`, `canRedo`, `undo`, `redo`. `tableWidth` /
|
|
308
311
|
`setTableWidth` remain as deprecated aliases limited to tables.
|
|
309
312
|
|
|
310
313
|
## Diagrams (drawing canvas)
|
|
@@ -485,10 +488,22 @@ diagrams:
|
|
|
485
488
|
</FormField>
|
|
486
489
|
```
|
|
487
490
|
|
|
488
|
-
Load both CSS entry points (`@zuilib/
|
|
491
|
+
Load both CSS entry points (`@zuilib/tokens/styles.css`,
|
|
489
492
|
`@zuilib/text-editor/styles.css`) in the app layout. Dark mode follows the
|
|
490
493
|
ZUI convention: a `dark` class on `<html>`.
|
|
491
494
|
|
|
495
|
+
`@zuilib/tokens` is an optional peer: the editor's chrome reads the ZUI
|
|
496
|
+
custom properties (`--primary`, `--popover`, `--border`, …) and falls back
|
|
497
|
+
to its own defaults when they are unset. Document content (headings,
|
|
498
|
+
lists, code blocks) is styled with Tailwind utility classes, so a Tailwind
|
|
499
|
+
v4 host must scan this package for them to be generated:
|
|
500
|
+
|
|
501
|
+
```css
|
|
502
|
+
@import "@zuilib/tokens/styles.css";
|
|
503
|
+
@source "../node_modules/@zuilib/text-editor/dist";
|
|
504
|
+
@import "@zuilib/text-editor/styles.css";
|
|
505
|
+
```
|
|
506
|
+
|
|
492
507
|
## Architecture notes (for extenders)
|
|
493
508
|
|
|
494
509
|
- Source: `src/EditorRoot.tsx` (composer + plugins), `src/EditorContent.tsx`,
|
|
@@ -508,7 +523,8 @@ ZUI convention: a `dark` class on `<html>`.
|
|
|
508
523
|
|
|
509
524
|
## Related packages
|
|
510
525
|
|
|
511
|
-
- `@zuilib/
|
|
526
|
+
- `@zuilib/tokens` — design tokens and base styles
|
|
527
|
+
- `@zuilib/components` — the UI primitives (Button, Input, …)
|
|
512
528
|
- `@zuilib/form` — react-hook-form wiring
|
|
513
529
|
|
|
514
530
|
## Build & release (maintainers)
|
package/dist/index.d.ts
CHANGED
|
@@ -266,55 +266,75 @@ declare function parseTableSettingsMarker(text: string): Partial<TableSettings>
|
|
|
266
266
|
declare function formatTableSettingsMarker(settings: TableSettings, options?: TableSettingsOptions): string | null;
|
|
267
267
|
|
|
268
268
|
/**
|
|
269
|
-
* Row operations for GFM tables. Markdown tables have no merged
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
269
|
+
* Row and column operations for GFM tables. Markdown tables have no merged
|
|
270
|
+
* cells, every row has the same number of cells and there is exactly one
|
|
271
|
+
* header row (the first), so these helpers work on plain indices and keep
|
|
272
|
+
* that shape: a row can't be inserted above the header, deleting the
|
|
273
|
+
* header promotes the row below it, and new cells in the header row are
|
|
274
|
+
* header cells.
|
|
273
275
|
*/
|
|
274
|
-
/**
|
|
275
|
-
type
|
|
276
|
-
/** Row index of the caret (or the anchor cell of a cell range) */
|
|
277
|
-
|
|
276
|
+
/** Where the selection sits in its table */
|
|
277
|
+
type TableCellPosition = Readonly<{
|
|
278
|
+
/** Row index of the caret (or of the anchor cell of a cell range) */
|
|
279
|
+
row: number;
|
|
278
280
|
/** Column index of that cell */
|
|
279
281
|
column: number;
|
|
280
282
|
/** Number of rows in the table */
|
|
281
|
-
|
|
283
|
+
rows: number;
|
|
284
|
+
/** Number of columns in the table */
|
|
285
|
+
columns: number;
|
|
282
286
|
/** Whether the first row is a header row */
|
|
283
287
|
hasHeader: boolean;
|
|
284
288
|
}>;
|
|
285
289
|
/** The cell containing the selection (caret or the anchor of a cell range) */
|
|
286
290
|
declare function $getSelectedTableCell(): TableCellNode | null;
|
|
287
291
|
/** Where the selection sits in its table, or null outside tables */
|
|
288
|
-
declare function $
|
|
292
|
+
declare function $getTableCellPosition(): TableCellPosition | null;
|
|
289
293
|
/**
|
|
290
|
-
* The row boundaries a new row may be inserted at: `0..
|
|
294
|
+
* The row boundaries a new row may be inserted at: `0..rows`, minus `0`
|
|
291
295
|
* when the first row is a header (a table's header is always its first row).
|
|
292
296
|
*/
|
|
293
|
-
declare function insertableRowIndices(position: Pick<
|
|
297
|
+
declare function insertableRowIndices(position: Pick<TableCellPosition, 'rows' | 'hasHeader'>): number[];
|
|
294
298
|
/** A row can be removed as long as one row stays */
|
|
295
|
-
declare function canDeleteRow(position: Pick<
|
|
299
|
+
declare function canDeleteRow(position: Pick<TableCellPosition, 'rows'>): boolean;
|
|
296
300
|
/**
|
|
297
|
-
* Insert an empty row so that it becomes row `index` (`0` = first,
|
|
298
|
-
*
|
|
299
|
-
* row
|
|
300
|
-
*
|
|
301
|
-
* `column`-th cell (default: the first).
|
|
301
|
+
* Insert an empty row so that it becomes row `index` (`0` = first, `rows`
|
|
302
|
+
* = last). Column header state is copied from the row above; the header
|
|
303
|
+
* row itself is never displaced, so `index` is clamped to `1` when the
|
|
304
|
+
* table has a header. The caret moves into the new row, at `column`.
|
|
302
305
|
*/
|
|
303
306
|
declare function $insertTableRowAt(table: TableNode, index: number, column?: number): TableRowNode;
|
|
304
307
|
/**
|
|
305
308
|
* Remove row `index`. No-op on a single-row table (see `canDeleteRow`).
|
|
306
309
|
* Removing the header row makes the next row the header so the markdown
|
|
307
|
-
* keeps its divider.
|
|
308
|
-
*
|
|
310
|
+
* keeps its divider. The caret moves to the row that takes the removed
|
|
311
|
+
* row's place (or the last row), at `column`.
|
|
309
312
|
*/
|
|
310
313
|
declare function $deleteTableRowAt(table: TableNode, index: number, column?: number): boolean;
|
|
311
|
-
/**
|
|
312
|
-
* Insert a row next to the selection's row. Returns the new row, or null
|
|
313
|
-
* outside tables.
|
|
314
|
-
*/
|
|
314
|
+
/** Insert a row next to the selection's row. Returns the new row, or null outside tables. */
|
|
315
315
|
declare function $insertTableRowNear(table: TableNode, position: 'above' | 'below'): TableRowNode | null;
|
|
316
316
|
/** Remove the selection's row. Returns false when nothing was removed. */
|
|
317
317
|
declare function $deleteSelectedTableRow(table: TableNode): boolean;
|
|
318
|
+
/** The column boundaries a new column may be inserted at: `0..columns` */
|
|
319
|
+
declare function insertableColumnIndices(position: Pick<TableCellPosition, 'columns'>): number[];
|
|
320
|
+
/** A column can be removed as long as one column stays */
|
|
321
|
+
declare function canDeleteColumn(position: Pick<TableCellPosition, 'columns'>): boolean;
|
|
322
|
+
/**
|
|
323
|
+
* Insert an empty column so that it becomes column `index` (`0` = first,
|
|
324
|
+
* `columns` = last). Cells in the header row are header cells. The caret
|
|
325
|
+
* moves into the new column, at `row`.
|
|
326
|
+
*/
|
|
327
|
+
declare function $insertTableColumnAt(table: TableNode, index: number, row?: number): void;
|
|
328
|
+
/**
|
|
329
|
+
* Remove column `index`. No-op on a single-column table (see
|
|
330
|
+
* `canDeleteColumn`). The caret moves to the column that takes the removed
|
|
331
|
+
* column's place (or the last column), at `row`.
|
|
332
|
+
*/
|
|
333
|
+
declare function $deleteTableColumnAt(table: TableNode, index: number, row?: number): boolean;
|
|
334
|
+
/** Insert a column next to the selection's column; no-op outside tables. */
|
|
335
|
+
declare function $insertTableColumnNear(table: TableNode, position: 'before' | 'after'): boolean;
|
|
336
|
+
/** Remove the selection's column. Returns false when nothing was removed. */
|
|
337
|
+
declare function $deleteSelectedTableColumn(table: TableNode): boolean;
|
|
318
338
|
|
|
319
339
|
type MarkdownEditorApi = Readonly<{
|
|
320
340
|
/** The underlying Lexical editor, for dispatching your own commands */
|
|
@@ -361,8 +381,8 @@ type MarkdownEditorApi = Readonly<{
|
|
|
361
381
|
tableDensity: TableDensity | null;
|
|
362
382
|
/** Change the density of the table containing the selection; no-op outside tables */
|
|
363
383
|
setTableDensity: (density: TableDensity) => void;
|
|
364
|
-
/** The selection's
|
|
365
|
-
|
|
384
|
+
/** The selection's cell in its table (row, column, counts, header); `null` outside tables */
|
|
385
|
+
tableCell: TableCellPosition | null;
|
|
366
386
|
/**
|
|
367
387
|
* Insert an empty row next to the selection's row (default `below`) and
|
|
368
388
|
* move the caret into it; no-op outside tables. A row is never inserted
|
|
@@ -374,6 +394,13 @@ type MarkdownEditorApi = Readonly<{
|
|
|
374
394
|
* remaining row. Deleting the header row makes the next row the header.
|
|
375
395
|
*/
|
|
376
396
|
deleteTableRow: () => void;
|
|
397
|
+
/**
|
|
398
|
+
* Insert an empty column next to the selection's column (default
|
|
399
|
+
* `after`) and move the caret into it; no-op outside tables.
|
|
400
|
+
*/
|
|
401
|
+
insertTableColumn: (position?: 'before' | 'after') => void;
|
|
402
|
+
/** Remove the selection's column; no-op outside tables and on the last remaining column. */
|
|
403
|
+
deleteTableColumn: () => void;
|
|
377
404
|
canUndo: boolean;
|
|
378
405
|
canRedo: boolean;
|
|
379
406
|
undo: () => void;
|
|
@@ -1366,4 +1393,4 @@ declare const codeTokenizer: LexicalTokenizer;
|
|
|
1366
1393
|
*/
|
|
1367
1394
|
declare function registerCodeBlockHighlighting(editor: LexicalEditor): () => void;
|
|
1368
1395
|
|
|
1369
|
-
export { $createDrawingNode, $createFrontmatterNode, $deleteSelectedTableRow, $deleteTableRowAt, $getSelectedTable, $getSelectedTableCell, $
|
|
1396
|
+
export { $createDrawingNode, $createFrontmatterNode, $deleteSelectedTableColumn, $deleteSelectedTableRow, $deleteTableColumnAt, $deleteTableRowAt, $getSelectedTable, $getSelectedTableCell, $getTableCellPosition, $getTableDensity, $getTableSettings, $getTableWidth, $insertTableColumnAt, $insertTableColumnNear, $insertTableRowAt, $insertTableRowNear, $isDrawingNode, $isFrontmatterNode, $isTableWidthExplicit, $setTableDensity, $setTableSettings, $setTableWidth, BLOCK_WIDTHS, BOX_DEFINITIONS, BOX_TYPES, BUILTIN_CODE_LANGUAGES, type Binding, type BindingSide, type BlockWidth, type BlockWidthDefaults, type BoxDefinition, type BoxType, CODE_BLOCK, CODE_TOKEN_TYPES, COLOR_PRESETS, CONNECTOR_TYPES, type CodeGrammar, type CodeRule, type CodeToken, type CodeTokenType, type ColorName, type ConnectorType, DEFAULT_TABLE_SETTINGS, DIAGRAM, DRAWING, DRAWING_DATA_JSON_SCHEMA, DRAWING_SKELETON_JSON_SCHEMA, type DrawingData, DrawingNode, type DrawingShape, type DrawingShapeType, type DrawingSkeleton, type DrawingStyle, EMPTY_DRAWING, type EditorContentProps, type EditorMode, type EditorRootProps, FILL_COLORS, FRONTMATTER, FormatButtons, FrontmatterNode, HistoryButtons, type InkOptions, type InkStroke, InsertButtons, MarkdownEditor, type MarkdownEditorApi, type Props as MarkdownEditorProps, type MermaidDirection, type MermaidOptions, PLAIN_LANGUAGE, type Point, SHAPE_TYPES, SIDE_FIXED_POINTS, STROKE_COLORS, type SerializedDrawingNode, type SerializedFrontmatterNode, type SkeletonBox, type SkeletonConnector, type SkeletonEnd, type SkeletonText, TABLE, TABLE_WIDTH_MARKER, type TableCellPosition, type TableDensity, type TableSettings, type TableSettingsOptions, type TextField, Toolbar, ToolbarButton, ToolbarDivider, type ToolbarItems, anchorPoint, bindEndpoints, boxOutline, canDeleteColumn, canDeleteRow, codeTokenizer, connectorPoints, drawingToMermaid, expandSkeleton, findBoxAt, fixedPointFor, formatTableSettingsMarker, getCodeLanguages, hasCodeLanguage, inkAmplitude, inkFillOffset, inkStroke, insertableColumnIndices, insertableRowIndices, isBlockWidth, isDrawingSkeleton, makeBinding, normalizeDrawingData, parseDrawingData, parseDrawingSkeleton, parseTableSettingsMarker, registerCodeBlockHighlighting, registerCodeLanguage, resolveBindings, resolveCodeLanguage, roundedPolyline, roundedRectPolygon, routeElbow, seedFrom, serializeDrawingData, tokenizeCode, useMarkdownEditor };
|