@sofereditor/core 0.1.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/LICENSE +661 -0
- package/README.md +21 -0
- package/dist/index.cjs +1874 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +601 -0
- package/dist/index.d.ts +601 -0
- package/dist/index.js +1772 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
export { Y };
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Document-level page configuration: physical size and margins.
|
|
6
|
+
*
|
|
7
|
+
* Everything is stored in **CSS pixels @ 96dpi** for consistency with the
|
|
8
|
+
* pagination engine (`packages/react/src/usePagination.ts` reads these
|
|
9
|
+
* directly). Conversion helpers (`mmToPx`, `pxToMm`) round-trip with millimeter
|
|
10
|
+
* inputs from the UI and the OOXML twip values used by docx import/export.
|
|
11
|
+
*/
|
|
12
|
+
type PagePreset = "a4" | "letter" | "oficio" | "custom";
|
|
13
|
+
interface PageSettings {
|
|
14
|
+
/** Page width in CSS px. */
|
|
15
|
+
width: number;
|
|
16
|
+
/** Page height in CSS px. */
|
|
17
|
+
height: number;
|
|
18
|
+
marginTop: number;
|
|
19
|
+
marginBottom: number;
|
|
20
|
+
marginLeft: number;
|
|
21
|
+
marginRight: number;
|
|
22
|
+
/**
|
|
23
|
+
* The preset whose size the geometry matches, with the ±0.5mm tolerance used
|
|
24
|
+
* by `detectPreset`. "custom" when the dimensions don't match any preset.
|
|
25
|
+
* This is purely a UI hint — it's recomputed from width/height when needed.
|
|
26
|
+
*/
|
|
27
|
+
preset?: PagePreset;
|
|
28
|
+
}
|
|
29
|
+
/** Page sizes in CSS px @ 96dpi. */
|
|
30
|
+
declare const PAGE_PRESETS: {
|
|
31
|
+
readonly a4: {
|
|
32
|
+
readonly width: 794;
|
|
33
|
+
readonly height: 1123;
|
|
34
|
+
};
|
|
35
|
+
readonly letter: {
|
|
36
|
+
readonly width: 816;
|
|
37
|
+
readonly height: 1056;
|
|
38
|
+
};
|
|
39
|
+
readonly oficio: {
|
|
40
|
+
readonly width: 816;
|
|
41
|
+
readonly height: 1248;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
/** Margin presets in CSS px. Match common Word defaults. */
|
|
45
|
+
declare const MARGIN_PRESETS: {
|
|
46
|
+
readonly normal: 96;
|
|
47
|
+
readonly narrow: 48;
|
|
48
|
+
readonly wide: 192;
|
|
49
|
+
};
|
|
50
|
+
declare const DEFAULT_PAGE_SETTINGS: PageSettings;
|
|
51
|
+
declare function mmToPx(mm: number): number;
|
|
52
|
+
declare function pxToMm(px: number): number;
|
|
53
|
+
/**
|
|
54
|
+
* Detect which preset a (width, height) pair matches. Tolerance is ±0.5mm to
|
|
55
|
+
* absorb rounding from the twips↔px conversion used by docx round-trip.
|
|
56
|
+
*/
|
|
57
|
+
declare function detectPreset(width: number, height: number): PagePreset;
|
|
58
|
+
/** Fill missing fields with the default. Useful when reading from a Y.Map that may be partially populated. */
|
|
59
|
+
declare function withDefaults(partial: Partial<PageSettings> | undefined): PageSettings;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Public type definitions for the document model.
|
|
63
|
+
* The runtime representation lives in Y.js (see document.ts);
|
|
64
|
+
* these types describe its shape for consumers.
|
|
65
|
+
*/
|
|
66
|
+
type BlockType = "paragraph" | "heading" | "blockquote" | "codeBlock" | "listItem" | "table";
|
|
67
|
+
type AlignValue = "left" | "center" | "right" | "justify";
|
|
68
|
+
type DirValue = "ltr" | "rtl";
|
|
69
|
+
type ListKind = "bullet" | "ordered";
|
|
70
|
+
/** Maximum supported list nesting (0 = top level). */
|
|
71
|
+
declare const MAX_LIST_LEVEL = 5;
|
|
72
|
+
interface BlockAttrs {
|
|
73
|
+
align?: AlignValue;
|
|
74
|
+
dir?: DirValue;
|
|
75
|
+
/** Only meaningful when `type === "heading"`. 1..6. */
|
|
76
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
77
|
+
/** Only meaningful when `type === "codeBlock"`. Free-form (CSS-style language hint). */
|
|
78
|
+
language?: string;
|
|
79
|
+
/** Only meaningful when `type === "listItem"`. */
|
|
80
|
+
listKind?: ListKind;
|
|
81
|
+
/** Only meaningful when `type === "listItem"`. 0..MAX_LIST_LEVEL. */
|
|
82
|
+
listLevel?: number;
|
|
83
|
+
/** Only meaningful when `type === "table"`. */
|
|
84
|
+
rows?: number;
|
|
85
|
+
/** Only meaningful when `type === "table"`. */
|
|
86
|
+
cols?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Only meaningful when `type === "table"`. Per-column widths in CSS px.
|
|
89
|
+
* Length should equal `cols` when set; missing or short arrays fall back to
|
|
90
|
+
* an auto distribution at render time.
|
|
91
|
+
*/
|
|
92
|
+
colWidths?: number[];
|
|
93
|
+
}
|
|
94
|
+
interface CellAttrs {
|
|
95
|
+
/**
|
|
96
|
+
* Number of rows this cell spans, starting at its row. Default 1.
|
|
97
|
+
* Only meaningful on REAL cells (not covered).
|
|
98
|
+
*/
|
|
99
|
+
rowspan?: number;
|
|
100
|
+
/** Default 1. Only meaningful on REAL cells. */
|
|
101
|
+
colspan?: number;
|
|
102
|
+
/**
|
|
103
|
+
* `true` iff this cell is occluded by an owning cell with a `rowspan`/`colspan`
|
|
104
|
+
* spanning into this position. Covered cells do not render their own `<td>`,
|
|
105
|
+
* never accept input, and are skipped by Tab navigation.
|
|
106
|
+
*
|
|
107
|
+
* The cells array keeps `rows * cols` entries to preserve the row-major index
|
|
108
|
+
* scheme — covered cells are placeholders, not gaps.
|
|
109
|
+
*/
|
|
110
|
+
covered?: true;
|
|
111
|
+
}
|
|
112
|
+
interface Position {
|
|
113
|
+
blockIndex: number;
|
|
114
|
+
/**
|
|
115
|
+
* When the caret is inside a table cell, identifies which cell within the
|
|
116
|
+
* table at `blockIndex`. Flat row-major index: `row * cols + col`.
|
|
117
|
+
* `undefined` means the position addresses the block's own text (or the block
|
|
118
|
+
* itself, for atomic blocks). Tables have no own text — every caret position
|
|
119
|
+
* inside a table block carries a defined `cellIndex`.
|
|
120
|
+
*/
|
|
121
|
+
cellIndex?: number;
|
|
122
|
+
offset: number;
|
|
123
|
+
}
|
|
124
|
+
interface Selection {
|
|
125
|
+
anchor: Position;
|
|
126
|
+
focus: Position;
|
|
127
|
+
}
|
|
128
|
+
type MarkName = "bold" | "italic" | "underline" | "strike" | "color" | "fontFamily" | "fontSize" | "link" | "comment";
|
|
129
|
+
interface LinkAttr {
|
|
130
|
+
href: string;
|
|
131
|
+
title?: string;
|
|
132
|
+
}
|
|
133
|
+
interface CommentAttr {
|
|
134
|
+
/** Identificador estável compartilhado com o backend (ProvaDocumentoComentario.markId). */
|
|
135
|
+
markId: string;
|
|
136
|
+
}
|
|
137
|
+
interface MarkAttrs {
|
|
138
|
+
bold?: true;
|
|
139
|
+
italic?: true;
|
|
140
|
+
underline?: true;
|
|
141
|
+
strike?: true;
|
|
142
|
+
color?: string;
|
|
143
|
+
fontFamily?: string;
|
|
144
|
+
fontSize?: string;
|
|
145
|
+
link?: LinkAttr;
|
|
146
|
+
comment?: CommentAttr;
|
|
147
|
+
}
|
|
148
|
+
type MarkValue<K extends MarkName = MarkName> = NonNullable<MarkAttrs[K]>;
|
|
149
|
+
/**
|
|
150
|
+
* Visual layout mode for an image embed.
|
|
151
|
+
*
|
|
152
|
+
* - `inline` (default): part of the text run, flows like a character.
|
|
153
|
+
* - `wrap-left` / `wrap-right`: image floats to the named side of the anchor
|
|
154
|
+
* paragraph (Word-style "wrap square"). Text in the paragraph wraps around it.
|
|
155
|
+
* - `behind`: image is absolutely positioned beneath the text (z-index < text).
|
|
156
|
+
* - `front`: image is absolutely positioned above the text (z-index > text).
|
|
157
|
+
*
|
|
158
|
+
* In every non-inline mode the embed remains in the Y.Text run at its offset —
|
|
159
|
+
* the offset is its **anchor** (it follows the paragraph during pagination
|
|
160
|
+
* and re-flows). Visual position is offset from the anchor block's content box.
|
|
161
|
+
*/
|
|
162
|
+
type ImageLayout = "inline" | "wrap-left" | "wrap-right" | "behind" | "front";
|
|
163
|
+
interface ImageEmbed {
|
|
164
|
+
type: "image";
|
|
165
|
+
/** Data URL (base64) — self-contained so the embed travels with the Y.Doc. */
|
|
166
|
+
src: string;
|
|
167
|
+
/** Rendered CSS px (display size — may differ from intrinsic dimensions). */
|
|
168
|
+
width: number;
|
|
169
|
+
height: number;
|
|
170
|
+
/** When set (inline mode only), the image renders `display: block` with the matching margin auto. */
|
|
171
|
+
align?: "left" | "center" | "right";
|
|
172
|
+
/** Visual layout. Defaults to "inline" when omitted. */
|
|
173
|
+
layout?: ImageLayout;
|
|
174
|
+
/**
|
|
175
|
+
* Horizontal offset in CSS px from the anchor block's content box.
|
|
176
|
+
* - wrap-left: extra left margin from the paragraph's start edge.
|
|
177
|
+
* - wrap-right: extra right margin from the paragraph's end edge.
|
|
178
|
+
* - behind / front: `left` relative to the anchor block's padding-box.
|
|
179
|
+
* Ignored for `inline`.
|
|
180
|
+
*/
|
|
181
|
+
offsetX?: number;
|
|
182
|
+
/**
|
|
183
|
+
* Vertical offset in CSS px from the anchor block's content box.
|
|
184
|
+
* - wrap-left / wrap-right: extra top margin pushing the float down inside
|
|
185
|
+
* the paragraph.
|
|
186
|
+
* - behind / front: `top` relative to the anchor block's padding-box.
|
|
187
|
+
* Ignored for `inline`.
|
|
188
|
+
*/
|
|
189
|
+
offsetY?: number;
|
|
190
|
+
/**
|
|
191
|
+
* Optional plain-text caption. Renders inside a `<figcaption>` beneath the
|
|
192
|
+
* image in any layout — the figure wraps the image so the caption travels
|
|
193
|
+
* with floats/anchors. Plain text only; rich marks are out of scope (we
|
|
194
|
+
* never want a sub-editor inside an inline embed).
|
|
195
|
+
*/
|
|
196
|
+
caption?: string;
|
|
197
|
+
/**
|
|
198
|
+
* Text alignment for the caption. Defaults to "center" (Word/Google Docs
|
|
199
|
+
* default for figure captions). Only meaningful when `caption` is set.
|
|
200
|
+
* Note: DOCX export emits captions inside the host paragraph, so this
|
|
201
|
+
* setting only affects the editor and HTML/PDF exports — Word displays the
|
|
202
|
+
* caption using the paragraph's own alignment.
|
|
203
|
+
*/
|
|
204
|
+
captionAlign?: "left" | "center" | "right";
|
|
205
|
+
}
|
|
206
|
+
type InsertContent = string | ImageEmbed;
|
|
207
|
+
declare function isImageEmbed(v: unknown): v is ImageEmbed;
|
|
208
|
+
interface DeltaOp {
|
|
209
|
+
insert: InsertContent;
|
|
210
|
+
attributes?: MarkAttrs;
|
|
211
|
+
}
|
|
212
|
+
interface SerializedCell {
|
|
213
|
+
/** Plain concatenated text. */
|
|
214
|
+
text: string;
|
|
215
|
+
/** Delta with marks. */
|
|
216
|
+
delta: DeltaOp[];
|
|
217
|
+
attrs: CellAttrs;
|
|
218
|
+
}
|
|
219
|
+
interface SerializedBlock {
|
|
220
|
+
type: BlockType;
|
|
221
|
+
/** Plain concatenated text (no marks). Kept for ergonomic equality checks. */
|
|
222
|
+
text: string;
|
|
223
|
+
/** Yjs delta — used by the renderer to draw mark-aware spans. */
|
|
224
|
+
delta: DeltaOp[];
|
|
225
|
+
/** Block-level attributes (align, dir, heading level, code language…). */
|
|
226
|
+
attrs: BlockAttrs;
|
|
227
|
+
/** Only present when `type === "table"`. Flat row-major list, length = rows * cols. */
|
|
228
|
+
cells?: SerializedCell[];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Document JSON shape used by `EditorDocument.toJSON` / `fromJSON`, the
|
|
233
|
+
* exporters and the importer. Until Fase 9.5 this was a bare `SerializedBlock[]`;
|
|
234
|
+
* Fase 9.6 promoted it to an object so per-document settings (page size,
|
|
235
|
+
* margins) can travel with the content.
|
|
236
|
+
*
|
|
237
|
+
* `fromJSON` still accepts a legacy array for backwards compatibility — see
|
|
238
|
+
* `isLegacySerializedDocument`.
|
|
239
|
+
*/
|
|
240
|
+
interface SerializedDocument {
|
|
241
|
+
blocks: SerializedBlock[];
|
|
242
|
+
/** Page settings. Optional; omitted means default A4 + 1" margins. */
|
|
243
|
+
pageSettings?: PageSettings;
|
|
244
|
+
}
|
|
245
|
+
/** A `SerializedDocument` produced before Fase 9.6 — just an array of blocks. */
|
|
246
|
+
type LegacySerializedDocument = SerializedBlock[];
|
|
247
|
+
declare function isLegacySerializedDocument(v: SerializedDocument | LegacySerializedDocument): v is LegacySerializedDocument;
|
|
248
|
+
|
|
249
|
+
interface BlockSpec {
|
|
250
|
+
type: BlockType;
|
|
251
|
+
defaultAttrs: BlockAttrs;
|
|
252
|
+
}
|
|
253
|
+
declare const BLOCK_SPECS: Record<BlockType, BlockSpec>;
|
|
254
|
+
declare function isKnownBlockType(t: string): t is BlockType;
|
|
255
|
+
declare function defaultAttrsFor(type: BlockType): BlockAttrs;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Y.js-backed document.
|
|
259
|
+
*
|
|
260
|
+
* Storage layout:
|
|
261
|
+
* ydoc.getArray("blocks") : Y.Array<Y.Map>
|
|
262
|
+
* each Y.Map ("block"):
|
|
263
|
+
* - type: string ("paragraph" | "heading" | "blockquote" | "codeBlock" | "listItem" | "table")
|
|
264
|
+
* - text: Y.Text (NOT present on tables)
|
|
265
|
+
* - attrs: Y.Map<unknown> (align, dir, level, language… plus rows/cols for tables)
|
|
266
|
+
* - cells: Y.Array<Y.Map> (only on tables, length = rows * cols, row-major)
|
|
267
|
+
* each cell map: { text: Y.Text, attrs: Y.Map<unknown> }
|
|
268
|
+
*
|
|
269
|
+
* Block-level attrs live inside a nested Y.Map so concurrent edits (e.g. two users
|
|
270
|
+
* changing alignment at once) reconcile through Yjs' last-write-wins per key.
|
|
271
|
+
*/
|
|
272
|
+
declare class EditorDocument {
|
|
273
|
+
readonly ydoc: Y.Doc;
|
|
274
|
+
readonly blocks: Y.Array<Y.Map<unknown>>;
|
|
275
|
+
/** Document-level settings (page size, margins). See `getPageSettings`. */
|
|
276
|
+
readonly docSettings: Y.Map<unknown>;
|
|
277
|
+
constructor(ydoc?: Y.Doc);
|
|
278
|
+
/**
|
|
279
|
+
* Returns the current page settings. Missing fields fall back to
|
|
280
|
+
* `DEFAULT_PAGE_SETTINGS`. The returned object is a fresh snapshot — mutating
|
|
281
|
+
* it does not write back to the Y.Doc. Use `setPageSettings` for that.
|
|
282
|
+
*/
|
|
283
|
+
getPageSettings(): PageSettings;
|
|
284
|
+
/**
|
|
285
|
+
* Merge `partial` into the docSettings Y.Map. Runs in a `ydoc.transact` with
|
|
286
|
+
* origin `"pageSettings"` (NOT tracked by the UndoManager, mirroring the
|
|
287
|
+
* `"import"` convention from Fase 9.5).
|
|
288
|
+
*/
|
|
289
|
+
setPageSettings(partial: Partial<PageSettings>): void;
|
|
290
|
+
/** Listen for page-settings changes. Returns an unsubscribe function. */
|
|
291
|
+
observePageSettings(cb: () => void): () => void;
|
|
292
|
+
getBlock(index: number): Y.Map<unknown> | undefined;
|
|
293
|
+
getBlockText(index: number): Y.Text | undefined;
|
|
294
|
+
getBlockType(index: number): BlockType | undefined;
|
|
295
|
+
getBlockAttrsMap(index: number): Y.Map<unknown> | undefined;
|
|
296
|
+
getBlockAttrs(index: number): BlockAttrs;
|
|
297
|
+
blockCount(): number;
|
|
298
|
+
isTable(index: number): boolean;
|
|
299
|
+
/** Returns rows/cols read from the block's attrs map. `{0,0}` for non-table blocks. */
|
|
300
|
+
getTableSize(index: number): {
|
|
301
|
+
rows: number;
|
|
302
|
+
cols: number;
|
|
303
|
+
};
|
|
304
|
+
getCells(index: number): Y.Array<Y.Map<unknown>> | undefined;
|
|
305
|
+
getCell(blockIndex: number, cellIndex: number): Y.Map<unknown> | undefined;
|
|
306
|
+
getCellText(blockIndex: number, cellIndex: number): Y.Text | undefined;
|
|
307
|
+
getCellAttrsMap(blockIndex: number, cellIndex: number): Y.Map<unknown> | undefined;
|
|
308
|
+
getCellAttrs(blockIndex: number, cellIndex: number): CellAttrs;
|
|
309
|
+
/**
|
|
310
|
+
* Returns the editable Y.Text targeted by a position:
|
|
311
|
+
* - When `cellIndex` is set: the cell's text (or the owner's text if the
|
|
312
|
+
* target cell is covered by a span — we treat the covered position as
|
|
313
|
+
* addressing the owner).
|
|
314
|
+
* - Otherwise: the block's own text.
|
|
315
|
+
*/
|
|
316
|
+
textAt(blockIndex: number, cellIndex: number | undefined): Y.Text | undefined;
|
|
317
|
+
/**
|
|
318
|
+
* Returns the "real" (non-covered) cell index for a target cell. When the
|
|
319
|
+
* target is already a real cell, returns it unchanged. When covered, walks
|
|
320
|
+
* up-and-left to find the owner.
|
|
321
|
+
*
|
|
322
|
+
* The walk is robust to oversized or non-rectangular spans by skipping
|
|
323
|
+
* candidates whose declared span doesn't actually cover the target.
|
|
324
|
+
*/
|
|
325
|
+
realCellIndex(blockIndex: number, cellIndex: number): number | undefined;
|
|
326
|
+
/**
|
|
327
|
+
* Replace the document contents with a `SerializedDocument`. Runs in a single
|
|
328
|
+
* `ydoc.transact` with origin `"import"` so the UndoManager can group or skip
|
|
329
|
+
* the operation as one step.
|
|
330
|
+
*
|
|
331
|
+
* Reuses `createBlock` / `createTableBlock` so every block ends up with the
|
|
332
|
+
* exact same Y.js shape produced by the rest of the editor.
|
|
333
|
+
*/
|
|
334
|
+
loadFromJSON(serialized: SerializedDocument | LegacySerializedDocument): void;
|
|
335
|
+
/** Build a fresh `EditorDocument` from a `SerializedDocument`. */
|
|
336
|
+
static fromJSON(serialized: SerializedDocument | LegacySerializedDocument): EditorDocument;
|
|
337
|
+
toJSON(): SerializedDocument;
|
|
338
|
+
}
|
|
339
|
+
declare function createBlock(type: BlockType, initialText?: string, attrs?: BlockAttrs): Y.Map<unknown>;
|
|
340
|
+
/**
|
|
341
|
+
* Build a table block with `rows × cols` empty cells.
|
|
342
|
+
* Cells are stored in row-major order: `cell[row * cols + col]`.
|
|
343
|
+
*/
|
|
344
|
+
declare function createTableBlock(rows: number, cols: number): Y.Map<unknown>;
|
|
345
|
+
declare function createCell(attrs?: CellAttrs): Y.Map<unknown>;
|
|
346
|
+
/** Coerce a `rowspan`/`colspan` attribute value into a positive integer. */
|
|
347
|
+
declare function spanOf(value: unknown): number;
|
|
348
|
+
|
|
349
|
+
declare function isCollapsed(sel: Selection): boolean;
|
|
350
|
+
declare function positionsEqual(a: Position, b: Position): boolean;
|
|
351
|
+
declare function comparePositions(a: Position, b: Position): number;
|
|
352
|
+
declare function orderedRange(sel: Selection): {
|
|
353
|
+
start: Position;
|
|
354
|
+
end: Position;
|
|
355
|
+
};
|
|
356
|
+
declare function collapsedSelection(pos: Position): Selection;
|
|
357
|
+
/**
|
|
358
|
+
* Two positions are in the same "editable run" (same Y.Text) when they share
|
|
359
|
+
* the block index AND the cellIndex (treating absent and present-with-undefined
|
|
360
|
+
* the same way: a non-table position has cellIndex === undefined for both).
|
|
361
|
+
*/
|
|
362
|
+
declare function sameTextRun(a: Position, b: Position): boolean;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Returns the marks observed across `[start, end)`. For each mark name encountered:
|
|
366
|
+
* - if every covered character has the same value, returns that value
|
|
367
|
+
* - if values differ OR some characters lack the mark, returns "mixed"
|
|
368
|
+
*/
|
|
369
|
+
declare function getMarksInRange(yText: Y.Text, start: number, end: number): Partial<Record<MarkName, MarkAttrs[MarkName] | "mixed">>;
|
|
370
|
+
declare function isMarkUniformInRange(yText: Y.Text, start: number, end: number, name: MarkName, value?: MarkAttrs[MarkName]): boolean;
|
|
371
|
+
/** Total number of inserted characters. Embeds (non-string inserts) count as 1. */
|
|
372
|
+
declare function deltaLength(delta: DeltaOp[]): number;
|
|
373
|
+
/**
|
|
374
|
+
* Return the subset of `delta` covering `[start, end)` characters.
|
|
375
|
+
* Embeds are atomic length-1 ops: included whole if their slot intersects the range.
|
|
376
|
+
*/
|
|
377
|
+
declare function sliceDelta(delta: DeltaOp[], start: number, end: number): DeltaOp[];
|
|
378
|
+
|
|
379
|
+
declare const COMMAND_ORIGIN: unique symbol;
|
|
380
|
+
interface CommandContext {
|
|
381
|
+
doc: EditorDocument;
|
|
382
|
+
getSelection: () => Selection;
|
|
383
|
+
setSelection: (sel: Selection) => void;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Insert text at the current selection.
|
|
387
|
+
*
|
|
388
|
+
* `marks` is an explicit override map applied to the freshly inserted range.
|
|
389
|
+
* - Entry value: apply that mark value.
|
|
390
|
+
* - Entry value `null`: clear that mark (used when the UI just toggled it off
|
|
391
|
+
* with a collapsed caret and the next typed char must NOT inherit the
|
|
392
|
+
* surrounding run's attribute).
|
|
393
|
+
* - When `marks` is undefined, Y.Text's default inheritance applies (good for
|
|
394
|
+
* normal typing inside a marked run).
|
|
395
|
+
*/
|
|
396
|
+
declare function insertText(ctx: CommandContext, text: string, marks?: Partial<Record<MarkName, MarkAttrs[MarkName] | null>>): void;
|
|
397
|
+
declare function insertParagraph(ctx: CommandContext): void;
|
|
398
|
+
declare function deleteBackward(ctx: CommandContext): void;
|
|
399
|
+
declare function deleteForward(ctx: CommandContext): void;
|
|
400
|
+
/**
|
|
401
|
+
* Toggle a mark across the current selection.
|
|
402
|
+
* - If the selection is collapsed: no-op (the UI layer handles pendingMarks).
|
|
403
|
+
* - Boolean marks (bold/italic/underline/strike): if every character already has
|
|
404
|
+
* the mark, remove it; otherwise apply.
|
|
405
|
+
* - Parametric marks (color, fontFamily, fontSize, link): require `value` to apply;
|
|
406
|
+
* when uniform with that value across the range, remove instead (acts like toggle).
|
|
407
|
+
*/
|
|
408
|
+
declare function toggleMark(ctx: CommandContext, name: MarkName, value?: MarkAttrs[MarkName]): void;
|
|
409
|
+
declare function setMark(ctx: CommandContext, name: MarkName, value: MarkAttrs[MarkName]): void;
|
|
410
|
+
declare function removeMark(ctx: CommandContext, name: MarkName): void;
|
|
411
|
+
/**
|
|
412
|
+
* Change the type of every block covered by the current selection.
|
|
413
|
+
* When `attrs` is provided, merges those on top of the new type's defaults.
|
|
414
|
+
* Preserves `Y.Text` content (and therefore all inline marks) and the selection.
|
|
415
|
+
*/
|
|
416
|
+
declare function setBlockType(ctx: CommandContext, type: BlockType, attrs?: BlockAttrs): void;
|
|
417
|
+
/**
|
|
418
|
+
* Set a single attribute on every block covered by the selection.
|
|
419
|
+
* Passing `value === null` deletes the key.
|
|
420
|
+
*/
|
|
421
|
+
declare function setBlockAttr<K extends keyof BlockAttrs>(ctx: CommandContext, key: K, value: BlockAttrs[K] | null): void;
|
|
422
|
+
/**
|
|
423
|
+
* Convert every block in the selection to/from a `listItem` of `kind`.
|
|
424
|
+
* If every covered block is already a `listItem` of `kind` → convert them all to paragraphs.
|
|
425
|
+
* Otherwise → convert them all to `listItem` (keeping existing `listLevel` when already
|
|
426
|
+
* a listItem, defaulting to 0 otherwise).
|
|
427
|
+
*/
|
|
428
|
+
declare function toggleList(ctx: CommandContext, kind: ListKind): void;
|
|
429
|
+
/** Increase nesting of every listItem in the selection (clamped to MAX_LIST_LEVEL). */
|
|
430
|
+
declare function indentList(ctx: CommandContext): void;
|
|
431
|
+
/**
|
|
432
|
+
* Decrease nesting of every listItem in the selection.
|
|
433
|
+
* When level was 0, demote to paragraph (escape from the list).
|
|
434
|
+
*/
|
|
435
|
+
declare function dedentList(ctx: CommandContext): void;
|
|
436
|
+
/**
|
|
437
|
+
* Enter behavior inside a listItem.
|
|
438
|
+
* - Empty listItem at level > 0 → dedent (stays a listItem, one level out).
|
|
439
|
+
* - Empty listItem at level 0 → convert to paragraph (exit the list).
|
|
440
|
+
* - Non-empty → split: tail moves to a new listItem with same kind/level.
|
|
441
|
+
*
|
|
442
|
+
* Returns `true` when it handled the event; `false` to let the default `insertParagraph` run.
|
|
443
|
+
*/
|
|
444
|
+
declare function splitListItem(ctx: CommandContext): boolean;
|
|
445
|
+
/**
|
|
446
|
+
* Insert a fresh `rows × cols` table after the block currently holding the
|
|
447
|
+
* caret (or at the end of the document if the selection is somehow invalid),
|
|
448
|
+
* and place the caret in the table's first cell.
|
|
449
|
+
*
|
|
450
|
+
* Sub-phase 4.1 doesn't try to be clever: it does NOT replace an empty
|
|
451
|
+
* preceding paragraph. Callers can clean that up themselves; an extra empty
|
|
452
|
+
* paragraph above a table is a small price for predictable behavior.
|
|
453
|
+
*/
|
|
454
|
+
declare function insertTable(ctx: CommandContext, rows: number, cols: number): void;
|
|
455
|
+
/** Remove the entire table at `blockIndex` and place the caret at the start of the next block (or the previous one if removal would leave the doc empty). */
|
|
456
|
+
declare function deleteTable(ctx: CommandContext, blockIndex: number): void;
|
|
457
|
+
/**
|
|
458
|
+
* Sub-phase 4.1 has no rowspan/colspan, so row/col operations are pure splice
|
|
459
|
+
* on the flat `cells` array. The flat index of `(r, c)` is `r * cols + c`.
|
|
460
|
+
*/
|
|
461
|
+
interface TableLocation {
|
|
462
|
+
blockIndex: number;
|
|
463
|
+
row: number;
|
|
464
|
+
col: number;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Derive `{row, col}` from a position inside a table — always pointing at the
|
|
468
|
+
* owner of the targeted cell (covered cells redirect to their owner). Returns
|
|
469
|
+
* null when the position isn't inside a table cell.
|
|
470
|
+
*/
|
|
471
|
+
declare function tableLocationOf(doc: EditorDocument, pos: Position): TableLocation | null;
|
|
472
|
+
/**
|
|
473
|
+
* Insert a fresh row above (`where === "before"`) or below (`"after"`) the
|
|
474
|
+
* given row. Spans that previously crossed the insertion boundary are extended
|
|
475
|
+
* by 1; the corresponding columns of the new row become `covered: true`.
|
|
476
|
+
*/
|
|
477
|
+
declare function insertTableRow(ctx: CommandContext, blockIndex: number, row: number, where: "before" | "after"): void;
|
|
478
|
+
/**
|
|
479
|
+
* Remove `row` from the table. Spans that pass through the row are shortened
|
|
480
|
+
* by one; spans that START at the row are removed AND the cell at row R+1 (in
|
|
481
|
+
* each affected column) is promoted to be the new owner with `rowspan - 1`.
|
|
482
|
+
* When it was the last row, deletes the whole table.
|
|
483
|
+
*/
|
|
484
|
+
declare function deleteTableRow(ctx: CommandContext, blockIndex: number, row: number): void;
|
|
485
|
+
/**
|
|
486
|
+
* Insert a fresh column to the left (`"before"`) or right (`"after"`) of `col`.
|
|
487
|
+
* Spans crossing the insertion column have `colspan += 1`; the new column's
|
|
488
|
+
* cells in covered rows are themselves `covered: true`.
|
|
489
|
+
*
|
|
490
|
+
* Also resizes `colWidths` (if defined) by inserting a default width.
|
|
491
|
+
*/
|
|
492
|
+
declare function insertTableColumn(ctx: CommandContext, blockIndex: number, col: number, where: "before" | "after"): void;
|
|
493
|
+
/**
|
|
494
|
+
* Remove `col` from the table. Spans that pass through the column are
|
|
495
|
+
* shortened by one; spans that START at the column with `colspan > 1` get
|
|
496
|
+
* their owner promoted from (r, C+1) to take over with `colspan - 1`.
|
|
497
|
+
*
|
|
498
|
+
* Also shrinks `colWidths` (if defined). When it was the last column, deletes
|
|
499
|
+
* the whole table.
|
|
500
|
+
*/
|
|
501
|
+
declare function deleteTableColumn(ctx: CommandContext, blockIndex: number, col: number): void;
|
|
502
|
+
interface TableRect {
|
|
503
|
+
blockIndex: number;
|
|
504
|
+
/** Inclusive bounds in OWNER coordinates. */
|
|
505
|
+
top: number;
|
|
506
|
+
left: number;
|
|
507
|
+
bottom: number;
|
|
508
|
+
right: number;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Interpret a `Selection` as a rectangular cell range when:
|
|
512
|
+
* - Both endpoints carry `cellIndex`.
|
|
513
|
+
* - They live in the same table block.
|
|
514
|
+
* - They point to DIFFERENT owner cells.
|
|
515
|
+
*
|
|
516
|
+
* The naive bounds are then EXPANDED until every span fully fits inside —
|
|
517
|
+
* essential so that operations like `mergeSelection` can never produce a
|
|
518
|
+
* non-rectangular shape, and so visual highlights always cover whole spans.
|
|
519
|
+
*/
|
|
520
|
+
declare function tableRectSelection(doc: EditorDocument, sel: Selection): TableRect | null;
|
|
521
|
+
/**
|
|
522
|
+
* Grow a candidate rect until every owner whose span starts within the rect
|
|
523
|
+
* fits entirely, and every covered cell inside it has its owner inside too.
|
|
524
|
+
* Converges in O(rows × cols) iterations in the worst case (each pass either
|
|
525
|
+
* grows a bound or terminates).
|
|
526
|
+
*/
|
|
527
|
+
declare function expandTableRect(doc: EditorDocument, blockIndex: number, initTop: number, initLeft: number, initBottom: number, initRight: number): TableRect;
|
|
528
|
+
/** Enumerate every cell-index (real or covered) contained in `rect`. */
|
|
529
|
+
declare function cellsInRect(doc: EditorDocument, rect: TableRect): number[];
|
|
530
|
+
/**
|
|
531
|
+
* Merge every cell in the current rectangular selection into one owner at the
|
|
532
|
+
* rect's top-left. The owner's text is the concatenation of all non-empty
|
|
533
|
+
* inner texts (space-separated, mark-preserving). Returns true on success, false
|
|
534
|
+
* when there is no rect selection.
|
|
535
|
+
*/
|
|
536
|
+
declare function mergeSelection(ctx: CommandContext): boolean;
|
|
537
|
+
/**
|
|
538
|
+
* Clears the text of every cell in the current rectangular selection (no
|
|
539
|
+
* structural mutation — spans stay intact). Returns the collapsed selection
|
|
540
|
+
* at the rect's top-left when something was cleared, otherwise null.
|
|
541
|
+
*/
|
|
542
|
+
declare function clearRectCells(ctx: CommandContext): Selection | null;
|
|
543
|
+
/**
|
|
544
|
+
* Merge the cell at `(row, col)` with its immediate right neighbor. The right
|
|
545
|
+
* neighbor must be a real cell with matching `rowspan` (otherwise the merge
|
|
546
|
+
* would form a non-rectangle). Returns true on success, false on shape
|
|
547
|
+
* mismatch or when there is no neighbor.
|
|
548
|
+
*
|
|
549
|
+
* After: the owner's `colspan` grows by the neighbor's `colspan`; the
|
|
550
|
+
* neighbor and all its formerly-covered cells in the merged rectangle are
|
|
551
|
+
* marked `covered: true`. The neighbor's text is appended to the owner with a
|
|
552
|
+
* single space delimiter (when both sides had content).
|
|
553
|
+
*/
|
|
554
|
+
declare function mergeRight(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean;
|
|
555
|
+
/** Merge with the immediate bottom neighbor. Mirror of `mergeRight`. */
|
|
556
|
+
declare function mergeDown(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean;
|
|
557
|
+
/**
|
|
558
|
+
* Split a merged cell back into a `rowspan × colspan` grid of independent real
|
|
559
|
+
* cells. Each formerly-covered cell becomes empty and real. Returns true when
|
|
560
|
+
* something was split. No-op (returns false) on a cell with no spans.
|
|
561
|
+
*/
|
|
562
|
+
declare function splitCell(ctx: CommandContext, blockIndex: number, row: number, col: number): boolean;
|
|
563
|
+
/** Set the width (in CSS px) of a specific column. Auto-initializes `colWidths`. */
|
|
564
|
+
declare function setColumnWidth(ctx: CommandContext, blockIndex: number, col: number, widthPx: number): void;
|
|
565
|
+
/**
|
|
566
|
+
* Move the caret to the next cell of the same table (Tab). At the last cell of
|
|
567
|
+
* the last row, creates a new row and lands in its first cell. Returns true
|
|
568
|
+
* when handled. Caret must be inside a table for this to act.
|
|
569
|
+
*/
|
|
570
|
+
declare function moveToNextCell(ctx: CommandContext): boolean;
|
|
571
|
+
/** Move the caret to the previous cell (Shift+Tab). At the first cell, no-op (returns true). */
|
|
572
|
+
declare function moveToPrevCell(ctx: CommandContext): boolean;
|
|
573
|
+
/**
|
|
574
|
+
* Insert an inline image embed at the current selection. Embeds occupy 1 char
|
|
575
|
+
* in offset arithmetic (Y.Text treats them as length-1 inserts).
|
|
576
|
+
*/
|
|
577
|
+
declare function insertImage(ctx: CommandContext, embed: ImageEmbed): void;
|
|
578
|
+
/**
|
|
579
|
+
* Update attributes of an existing image embed at `(blockIndex, embedOffset)`.
|
|
580
|
+
* Implementation: delete the 1-char slot and re-insert the merged embed in the
|
|
581
|
+
* SAME transaction — Y.UndoManager coalesces delete+insert in one transact, so
|
|
582
|
+
* undo treats it as a single step.
|
|
583
|
+
*
|
|
584
|
+
* If `newOffset` is provided and differs from `embedOffset`, the embed is moved
|
|
585
|
+
* to that offset within the same block/cell. Used by wrap-left/wrap-right
|
|
586
|
+
* layouts which must anchor the image at the block start so floated text wraps
|
|
587
|
+
* around it (CSS float only flows text that comes AFTER the float in DOM order).
|
|
588
|
+
*/
|
|
589
|
+
declare function setImageAttrs(ctx: CommandContext, blockIndex: number, embedOffset: number, partial: Partial<ImageEmbed>, cellIndex?: number, newOffset?: number): void;
|
|
590
|
+
declare function isCommandOrigin(origin: unknown): boolean;
|
|
591
|
+
declare const TRACKED_ORIGINS: Set<unknown>;
|
|
592
|
+
|
|
593
|
+
declare class EditorHistory {
|
|
594
|
+
readonly undoManager: Y.UndoManager;
|
|
595
|
+
constructor(doc: EditorDocument);
|
|
596
|
+
undo(): boolean;
|
|
597
|
+
redo(): boolean;
|
|
598
|
+
destroy(): void;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export { type AlignValue, BLOCK_SPECS, type BlockAttrs, type BlockType, COMMAND_ORIGIN, type CellAttrs, type CommandContext, type CommentAttr, DEFAULT_PAGE_SETTINGS, type DeltaOp, type DirValue, EditorDocument, EditorHistory, type ImageEmbed, type ImageLayout, type InsertContent, type LegacySerializedDocument, type LinkAttr, type ListKind, MARGIN_PRESETS, MAX_LIST_LEVEL, type MarkAttrs, type MarkName, type MarkValue, PAGE_PRESETS, type PagePreset, type PageSettings, type Position, type Selection, type SerializedBlock, type SerializedCell, type SerializedDocument, TRACKED_ORIGINS, type TableLocation, type TableRect, cellsInRect, clearRectCells, collapsedSelection, comparePositions, createBlock, createCell, createTableBlock, dedentList, defaultAttrsFor, deleteBackward, deleteForward, deleteTable, deleteTableColumn, deleteTableRow, deltaLength, detectPreset, expandTableRect, getMarksInRange, indentList, insertImage, insertParagraph, insertTable, insertTableColumn, insertTableRow, insertText, isCollapsed, isCommandOrigin, isImageEmbed, isKnownBlockType, isLegacySerializedDocument, isMarkUniformInRange, mergeDown, mergeRight, mergeSelection, mmToPx, moveToNextCell, moveToPrevCell, orderedRange, positionsEqual, pxToMm, removeMark, sameTextRun, setBlockAttr, setBlockType, setColumnWidth, setImageAttrs, setMark, sliceDelta, spanOf, splitCell, splitListItem, tableLocationOf, tableRectSelection, toggleList, toggleMark, withDefaults };
|