@sobree/core 0.1.23 → 0.1.25
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/dist/editor/index.d.ts +112 -16
- package/dist/editor/internal/frameCaret.d.ts +37 -0
- package/dist/editor/types.d.ts +21 -0
- package/dist/editor/view/docRenderer/anchorLayer.d.ts +10 -0
- package/dist/editor/view/docSerialize/block.d.ts +15 -0
- package/dist/editor/view/docSerialize/index.d.ts +10 -1
- package/dist/editor/view/docSerialize/inline.d.ts +2 -1
- package/dist/editor/wiring.d.ts +3 -0
- package/dist/history/history.d.ts +27 -6
- package/dist/history/types.d.ts +32 -3
- package/dist/index.js +4786 -4511
- package/dist/index.js.map +1 -1
- package/dist/sobree.d.ts +1 -0
- package/package.json +1 -1
package/dist/editor/index.d.ts
CHANGED
|
@@ -20,22 +20,6 @@ export type { ApiRangeType, BlockInfo, ChangePayload, CommandBus, CommandDefinit
|
|
|
20
20
|
export type { CellRef, InsertAt, InsertColumnOpts, InsertRowOpts, MergeCellsOpts, } from './types';
|
|
21
21
|
export { runsLength } from '../doc/runs';
|
|
22
22
|
export type { RunPropertiesPatch };
|
|
23
|
-
/**
|
|
24
|
-
* Public editor surface.
|
|
25
|
-
*
|
|
26
|
-
* Two entry points for every operation:
|
|
27
|
-
* - Core methods take `BlockRef` / `InlinePosition` / `Range` and
|
|
28
|
-
* return `EditResult`. These are the wire-callable API — same
|
|
29
|
-
* contract for in-process toolbars, headless Y peers (HeadlessSobree),
|
|
30
|
-
* and future MCP wrappers.
|
|
31
|
-
* - "AtSelection" sugar reads the live DOM selection, builds the
|
|
32
|
-
* position/range for you, and delegates to the core. Use these in
|
|
33
|
-
* in-process UI code.
|
|
34
|
-
*
|
|
35
|
-
* Mutations enforce optimistic locking via block `version` numbers.
|
|
36
|
-
* Conflicts return `{ ok: false, error: { code: "optimistic-lock", … } }`
|
|
37
|
-
* rather than throwing.
|
|
38
|
-
*/
|
|
39
23
|
export declare class Editor {
|
|
40
24
|
readonly host: HTMLElement;
|
|
41
25
|
readonly selection: EditorSelection;
|
|
@@ -160,6 +144,35 @@ export declare class Editor {
|
|
|
160
144
|
* and `emitChangeNow` sync only when this flag is set.
|
|
161
145
|
*/
|
|
162
146
|
private domDirty;
|
|
147
|
+
/**
|
|
148
|
+
* Ids of editable textbox frames whose DOM the user has edited since
|
|
149
|
+
* the last sync. Frames live in the floating overlay (outside the
|
|
150
|
+
* body content hosts), so they need their own read-back path —
|
|
151
|
+
* `syncFromDom` re-serialises each dirty frame into
|
|
152
|
+
* `anchoredFrames[id].content.body`.
|
|
153
|
+
*/
|
|
154
|
+
private readonly dirtyFrameIds;
|
|
155
|
+
/**
|
|
156
|
+
* Set by `syncFromDom` when the pending change was a pure live frame
|
|
157
|
+
* keystroke; read (and reset) by `emitChangeNow` into the change
|
|
158
|
+
* payload's `liveFrameEdit`. Lets the host skip the overlay repaint
|
|
159
|
+
* that would clobber the caret, while still repainting on undo/remote.
|
|
160
|
+
*/
|
|
161
|
+
private pendingLiveFrameEdit;
|
|
162
|
+
/**
|
|
163
|
+
* The editing context the caret was last in — a frame id, or `"body"`.
|
|
164
|
+
* When it changes, the undo-capture group is closed so each box's edit
|
|
165
|
+
* is a distinct undo step. `null` until the first selection.
|
|
166
|
+
*/
|
|
167
|
+
private lastEditContext;
|
|
168
|
+
/**
|
|
169
|
+
* Selection captured at `beforeinput` (pre-DOM-mutation) for the open
|
|
170
|
+
* undo group — restored on undo so the caret lands where the edit began.
|
|
171
|
+
* `hasPendingPreEdit` distinguishes "nothing stashed" from a stashed
|
|
172
|
+
* `null` (a body `Selection` can legitimately be `null`).
|
|
173
|
+
*/
|
|
174
|
+
private pendingPreEdit;
|
|
175
|
+
private hasPendingPreEdit;
|
|
163
176
|
/**
|
|
164
177
|
* Kernel seam handed to the behaviour modules (`ops/*`, `query`). Built
|
|
165
178
|
* once in the constructor; closes over this instance's privates so the
|
|
@@ -482,6 +495,81 @@ export declare class Editor {
|
|
|
482
495
|
*/
|
|
483
496
|
private ensureCurrent;
|
|
484
497
|
private syncFromDom;
|
|
498
|
+
/**
|
|
499
|
+
* Re-read the DOM of each dirty editable textbox frame into the AST.
|
|
500
|
+
* The frame element IS the serialization host (the block renderer paints
|
|
501
|
+
* its body directly into it), so `serializeHostsToDocument([el])` yields
|
|
502
|
+
* the same `Block[]` shape as a body host. Matched to the AST frame by
|
|
503
|
+
* its stable `data-anchor-id`. Pure body swap — geometry/anchor untouched.
|
|
504
|
+
*
|
|
505
|
+
* `captureRunDefaults` promotes each paragraph's rendered base font to
|
|
506
|
+
* `runDefaults`, so a frame's text keeps its size/family even when a
|
|
507
|
+
* keystroke (or a select-all-retype) strips every run's inline styling —
|
|
508
|
+
* the heading no longer collapses to the default font on the next repaint.
|
|
509
|
+
*/
|
|
510
|
+
private syncFramesFromDom;
|
|
511
|
+
/**
|
|
512
|
+
* The id of the editable textbox frame the caret currently sits in, or
|
|
513
|
+
* null when the selection is in ordinary body flow. Used to route an
|
|
514
|
+
* `input` event to the frame read-back instead of the body read-back.
|
|
515
|
+
*/
|
|
516
|
+
private editedFrameId;
|
|
517
|
+
/** The editable textbox frame element the caret is inside, or null. */
|
|
518
|
+
private focusedFrameEl;
|
|
519
|
+
/** The (freshly-painted) frame element with this `data-anchor-id`, or null. */
|
|
520
|
+
private frameElById;
|
|
521
|
+
/**
|
|
522
|
+
* Capture the live selection for an undo step. A selection inside an
|
|
523
|
+
* editable textbox frame becomes a `FrameSelection` — the body
|
|
524
|
+
* `Selection` model is keyed on registry blocks and can't address frame
|
|
525
|
+
* content — so undo can restore it the same way it restores a body
|
|
526
|
+
* selection. Everything else is an ordinary body selection.
|
|
527
|
+
*/
|
|
528
|
+
private captureSelectionForHistory;
|
|
529
|
+
/**
|
|
530
|
+
* The selection BEFORE the edit that opened the current undo group,
|
|
531
|
+
* stashed by `onBeforeInput` (which fires before the DOM mutates). Falls
|
|
532
|
+
* back to the live selection for edits that bypass `beforeinput`
|
|
533
|
+
* (programmatic mutations, `setDocument`).
|
|
534
|
+
*/
|
|
535
|
+
private capturePreEditSelection;
|
|
536
|
+
/**
|
|
537
|
+
* Stash the pre-edit selection on the first input of a new undo group,
|
|
538
|
+
* so undo can land the caret where the edit began. `beforeinput` fires
|
|
539
|
+
* before the browser mutates the DOM, so the live selection here is the
|
|
540
|
+
* pre-edit position. Only the FIRST input of a group stashes; coalesced
|
|
541
|
+
* inputs leave the group's `before` intact (`History.onGroupSettled`
|
|
542
|
+
* clears the stash once a step has captured).
|
|
543
|
+
*
|
|
544
|
+
* Scoped to textbox frames. The body already restores its caret through
|
|
545
|
+
* the proven `applySelectionToDom` path on `stack-item-popped`; we leave
|
|
546
|
+
* its behaviour byte-for-byte unchanged (no pre-edit stash → `before`
|
|
547
|
+
* falls back to the post-edit selection, same as `after`). Frames had no
|
|
548
|
+
* working restore at all, so they get the full pre-/post-edit treatment.
|
|
549
|
+
*/
|
|
550
|
+
private onBeforeInput;
|
|
551
|
+
/** Drop the pending pre-edit stash — a step has captured (or extended) it. */
|
|
552
|
+
private clearPendingPreEditSelection;
|
|
553
|
+
/**
|
|
554
|
+
* Restore an undo step's selection. Fires on `stack-item-popped`, which
|
|
555
|
+
* runs AFTER the change handler has already repainted the frame overlay
|
|
556
|
+
* (`adoptYDocState` calls `emitChangeNow` synchronously), so a captured
|
|
557
|
+
* frame selection lands on the fresh frame element and sticks — the same
|
|
558
|
+
* lifecycle the body selection restore relies on.
|
|
559
|
+
*/
|
|
560
|
+
private restoreCapturedSelection;
|
|
561
|
+
/**
|
|
562
|
+
* Toggle a mark on the caret inside an editable textbox frame, natively
|
|
563
|
+
* (`document.execCommand`), so the body-selection mark path doesn't have
|
|
564
|
+
* to understand frame coordinates. The resulting `<b>`/`<i>`/`<u>` tags
|
|
565
|
+
* round-trip through the frame read-back (the inline serializer maps them
|
|
566
|
+
* to run properties). Returns false when the caret isn't in a frame, so
|
|
567
|
+
* the mark command falls back to the body path.
|
|
568
|
+
*/
|
|
569
|
+
applyFrameMark(tag: string): boolean;
|
|
570
|
+
/** Active state of `tag` at a frame caret (toolbar highlight), or null
|
|
571
|
+
* when the caret isn't in a frame. */
|
|
572
|
+
frameMarkActive(tag: string): boolean | null;
|
|
485
573
|
/**
|
|
486
574
|
* Schedule a DOM-driven change emit. Called from the `input` listener
|
|
487
575
|
* when the user types — the DOM is the source of truth and we sync the
|
|
@@ -521,6 +609,14 @@ export declare class Editor {
|
|
|
521
609
|
* even when no subscribers exist (the early-return keeps it cheap).
|
|
522
610
|
*/
|
|
523
611
|
private fireSelection;
|
|
612
|
+
/**
|
|
613
|
+
* When the caret moves to a different editing context — another textbox
|
|
614
|
+
* frame, or between a frame and the body — close the undo-capture group
|
|
615
|
+
* so the next edit there is its own undo step. Without this, two edits
|
|
616
|
+
* to different boxes within `captureTimeout` coalesce and a single undo
|
|
617
|
+
* reverts both, unlike Word (where each box is a distinct action).
|
|
618
|
+
*/
|
|
619
|
+
private breakUndoOnContextChange;
|
|
524
620
|
private fireKeyDown;
|
|
525
621
|
}
|
|
526
622
|
export { countBlocks };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Selection <-> character-offset helpers for editable textbox frames.
|
|
3
|
+
*
|
|
4
|
+
* A frame's body is a contentEditable island whose text isn't addressable
|
|
5
|
+
* by the body's block-registry `Selection` model. Undo/redo still needs to
|
|
6
|
+
* capture the caret (or selection) on a frame edit and put it back, so we
|
|
7
|
+
* model a frame selection as a `{ start, end }` character span across the
|
|
8
|
+
* frame's text nodes — stable enough to survive the AST round-trip and
|
|
9
|
+
* clamp cleanly to the (possibly shorter) post-undo text. A collapsed
|
|
10
|
+
* caret is `start === end`.
|
|
11
|
+
*/
|
|
12
|
+
export interface FrameOffsets {
|
|
13
|
+
/** Character offset of the selection start within the frame. */
|
|
14
|
+
start: number;
|
|
15
|
+
/** Character offset of the selection end (=== start for a caret). */
|
|
16
|
+
end: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The current selection's `{ start, end }` character offsets within `root`,
|
|
20
|
+
* or `null` when the selection isn't anchored inside `root`. Normalised so
|
|
21
|
+
* `start <= end` regardless of selection direction.
|
|
22
|
+
*/
|
|
23
|
+
export declare function frameSelectionOffsets(root: HTMLElement, doc: Document): FrameOffsets | null;
|
|
24
|
+
/**
|
|
25
|
+
* Character offset of the collapsed caret within `root` (selection start),
|
|
26
|
+
* or `null` when the selection isn't inside `root`. Thin wrapper over
|
|
27
|
+
* {@link frameSelectionOffsets} for caret-only callers.
|
|
28
|
+
*/
|
|
29
|
+
export declare function caretCharOffset(root: HTMLElement, doc: Document): number | null;
|
|
30
|
+
/**
|
|
31
|
+
* Select `start..end` characters within `root` (a collapsed caret when
|
|
32
|
+
* equal), clamping each end to the available text — an undo can revert to
|
|
33
|
+
* shorter text. No-op-safe when `root` has no text nodes.
|
|
34
|
+
*/
|
|
35
|
+
export declare function applyFrameSelection(root: HTMLElement, offsets: FrameOffsets, doc: Document): void;
|
|
36
|
+
/** Place a collapsed caret `offset` chars into `root` (clamped). */
|
|
37
|
+
export declare function placeCaretAtOffset(root: HTMLElement, offset: number, doc: Document): void;
|
package/dist/editor/types.d.ts
CHANGED
|
@@ -94,6 +94,15 @@ export interface ChangePayload {
|
|
|
94
94
|
document: SobreeDocument;
|
|
95
95
|
revision: number;
|
|
96
96
|
documentVersion: number;
|
|
97
|
+
/**
|
|
98
|
+
* True when this change came from a live keystroke inside an editable
|
|
99
|
+
* textbox frame — the frame's DOM already holds the edit, so the host
|
|
100
|
+
* can skip repainting the floating overlay (which would clobber the
|
|
101
|
+
* caret). Absent / false for body edits, API mutations, undo/redo, and
|
|
102
|
+
* remote (Y.Doc-driven) changes — those re-render from the AST, so the
|
|
103
|
+
* overlay IS stale and must repaint.
|
|
104
|
+
*/
|
|
105
|
+
liveFrameEdit?: boolean;
|
|
97
106
|
}
|
|
98
107
|
/** Summary of a top-level block, for `getBlocks()` and list-style UIs. */
|
|
99
108
|
export interface BlockInfo {
|
|
@@ -171,6 +180,18 @@ export interface EditorLike {
|
|
|
171
180
|
expect?: Record<string, number>;
|
|
172
181
|
}): EditResult<void>;
|
|
173
182
|
readonly selection: EditorSelectionLike;
|
|
183
|
+
/**
|
|
184
|
+
* When the caret sits in an editable textbox frame, toggle a mark
|
|
185
|
+
* (`"strong"`/`"em"`/`"u"`/`"s"`/`"sup"`/`"sub"`) natively on that
|
|
186
|
+
* frame's selection — the frame read-back captures the result. Returns
|
|
187
|
+
* `true` when handled (caret was in a frame), `false` otherwise so the
|
|
188
|
+
* caller falls back to the body mark path. Optional: implemented by the
|
|
189
|
+
* DOM Editor, absent on headless peers (which have no frame DOM).
|
|
190
|
+
*/
|
|
191
|
+
applyFrameMark?(tag: string): boolean;
|
|
192
|
+
/** Active state of `tag` at the frame caret, or `null` when the caret
|
|
193
|
+
* isn't in a frame (caller uses the body `isMarkActive`). */
|
|
194
|
+
frameMarkActive?(tag: string): boolean | null;
|
|
174
195
|
}
|
|
175
196
|
export type EditorEvent = "change" | "selection" | "keydown" | "track-changes-change";
|
|
176
197
|
export type EditorEventPayload = {
|
|
@@ -16,6 +16,16 @@ export interface AnchorLayerContext {
|
|
|
16
16
|
* stacked text (test/headless fallback).
|
|
17
17
|
*/
|
|
18
18
|
renderBody?: (blocks: Block[], host: HTMLElement) => void;
|
|
19
|
+
/**
|
|
20
|
+
* When true, textbox frames become editable islands: the frame turns
|
|
21
|
+
* into its own `contentEditable` host (`pointer-events:auto`) so the
|
|
22
|
+
* user can click in and type. The editor wires the read-back that
|
|
23
|
+
* serialises the frame's DOM into `anchoredFrames[id].content.body`.
|
|
24
|
+
* False / absent → display-only overlay (read-only mode, decorations,
|
|
25
|
+
* headless). Pictures, shapes, and groups stay non-interactive
|
|
26
|
+
* regardless — only textbox prose is editable.
|
|
27
|
+
*/
|
|
28
|
+
editable?: boolean;
|
|
19
29
|
}
|
|
20
30
|
/**
|
|
21
31
|
* Build the per-page anchor layer. Returns a single `<div>` whose
|
|
@@ -10,5 +10,20 @@ export interface BlockSerializeContext {
|
|
|
10
10
|
numId: number;
|
|
11
11
|
ordered: boolean;
|
|
12
12
|
} | null;
|
|
13
|
+
/**
|
|
14
|
+
* Capture each paragraph's effective base run style (from the rendered
|
|
15
|
+
* `<p>`'s inline font) into `ParagraphProperties.runDefaults`.
|
|
16
|
+
*
|
|
17
|
+
* Used for textbox-frame read-back only. A frame's text carries its font
|
|
18
|
+
* on the runs, with no named style to fall back on; so when a keystroke
|
|
19
|
+
* lands in a bare text node — or a select-all-retype replaces every
|
|
20
|
+
* styled span with one unstyled node — the runs lose their font and a
|
|
21
|
+
* repaint renders the whole line at the default tiny size. The `<p>`
|
|
22
|
+
* element keeps its inline font through these DOM edits, so promoting it
|
|
23
|
+
* to a paragraph-level default makes the font survive run-level loss.
|
|
24
|
+
* Body flow leaves this off: its runs legitimately inherit from named
|
|
25
|
+
* styles, which must stay style-linked across edits.
|
|
26
|
+
*/
|
|
27
|
+
captureRunDefaults?: boolean;
|
|
13
28
|
}
|
|
14
29
|
export declare function blocksFromNodes(nodes: readonly Node[], ctx: BlockSerializeContext): Block[];
|
|
@@ -5,4 +5,13 @@ import { SobreeDocument } from '../../../doc/types';
|
|
|
5
5
|
* produced here — the Sobree façade injects those from its current page
|
|
6
6
|
* setup state before handing the document off to the exporter.
|
|
7
7
|
*/
|
|
8
|
-
export
|
|
8
|
+
export interface SerializeHostsOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Capture each paragraph's effective base run style into
|
|
11
|
+
* `ParagraphProperties.runDefaults`. Set for textbox-frame read-back so a
|
|
12
|
+
* frame's font survives run-level styling loss; left off for body flow,
|
|
13
|
+
* which stays style-linked. See `BlockSerializeContext.captureRunDefaults`.
|
|
14
|
+
*/
|
|
15
|
+
captureRunDefaults?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function serializeHostsToDocument(hosts: readonly HTMLElement[], options?: SerializeHostsOptions): SobreeDocument;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InlineRun } from '../../../doc/types';
|
|
1
|
+
import { InlineRun, RunProperties } from '../../../doc/types';
|
|
2
2
|
/**
|
|
3
3
|
* Serialise DOM children of `el` into a flat `InlineRun[]`. Nested
|
|
4
4
|
* formatting wrappers (`<strong><em>...`) are flattened — each leaf text
|
|
@@ -9,3 +9,4 @@ import { InlineRun } from '../../../doc/types';
|
|
|
9
9
|
* children (their own flat run list).
|
|
10
10
|
*/
|
|
11
11
|
export declare function serializeInlineChildren(el: HTMLElement): InlineRun[];
|
|
12
|
+
export declare function mergeStyleAttribute(base: RunProperties, styleAttr: string | null): RunProperties;
|
package/dist/editor/wiring.d.ts
CHANGED
|
@@ -24,6 +24,9 @@ export interface EditorDomHooks {
|
|
|
24
24
|
trackedInput: TrackedInput;
|
|
25
25
|
/** Tracked-changes authoring mode is on right now. */
|
|
26
26
|
isTrackedEnabled: () => boolean;
|
|
27
|
+
/** A real edit is about to mutate the DOM (`beforeinput`, before the
|
|
28
|
+
* mutation). Lets the editor stash the pre-edit selection for undo. */
|
|
29
|
+
onBeforeInput: () => void;
|
|
27
30
|
/** Mark the DOM dirty + schedule a debounced change. */
|
|
28
31
|
onInput: () => void;
|
|
29
32
|
/** Fire the editor's `selection` event. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { CapturedSelection, HistoryConfig, HistoryDepth } from './types';
|
|
2
|
+
import { Selection as PublicSelection } from '../doc/api';
|
|
3
3
|
/**
|
|
4
4
|
* Undo / redo for the Sobree editor — backed by `Y.UndoManager`.
|
|
5
5
|
*
|
|
@@ -51,22 +51,43 @@ export interface HistoryOptions extends Partial<HistoryConfig> {
|
|
|
51
51
|
* local writes. UndoManager only tracks operations whose origin
|
|
52
52
|
* is in this set. Defaults to `"local"`. */
|
|
53
53
|
localOrigin?: unknown;
|
|
54
|
-
/** Capture the *current* live selection — called as a
|
|
55
|
-
* is
|
|
56
|
-
|
|
54
|
+
/** Capture the *current* (post-edit) live selection — called as a
|
|
55
|
+
* stack item is added/updated, stashed as the step's `after`. Returns
|
|
56
|
+
* a body `Selection` or a frame selection; `History` keeps it opaque. */
|
|
57
|
+
captureSelection: () => CapturedSelection;
|
|
58
|
+
/** Capture the selection as it was BEFORE the edit that opened the
|
|
59
|
+
* current undo step — stashed as the step's `before` and restored on
|
|
60
|
+
* undo. Defaults to {@link captureSelection} when not provided (callers
|
|
61
|
+
* without a pre-edit hook, e.g. headless, get post-edit on both). */
|
|
62
|
+
capturePreEditSelection?: () => CapturedSelection;
|
|
57
63
|
/** Restore a previously-captured selection to the live DOM /
|
|
58
64
|
* EditorSelection. Called on undo / redo after the Y.Doc has been
|
|
59
65
|
* re-projected and re-rendered. */
|
|
60
|
-
restoreSelection: (sel:
|
|
66
|
+
restoreSelection: (sel: CapturedSelection) => void;
|
|
67
|
+
/** Notify the caller that the current undo group has captured (or
|
|
68
|
+
* extended) its selection, so it can drop any pending pre-edit stash.
|
|
69
|
+
* Fires on every `stack-item-added` / `stack-item-updated`. */
|
|
70
|
+
onGroupSettled?: () => void;
|
|
61
71
|
}
|
|
62
72
|
export declare class History {
|
|
63
73
|
private readonly mgr;
|
|
64
74
|
private readonly listeners;
|
|
65
75
|
private readonly captureSelection;
|
|
76
|
+
private readonly capturePreEditSelection;
|
|
66
77
|
private readonly restoreSelection;
|
|
78
|
+
private readonly onGroupSettled;
|
|
67
79
|
constructor(opts: HistoryOptions);
|
|
68
80
|
undo(): boolean;
|
|
69
81
|
redo(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Close the current undo-capture group so the NEXT local edit starts a
|
|
84
|
+
* fresh undo step instead of coalescing into the previous one (within
|
|
85
|
+
* `captureTimeout`). The editor calls this when the editing context
|
|
86
|
+
* changes — e.g. the caret moves to a different textbox frame, or
|
|
87
|
+
* between a frame and the body — so two distinct edits don't collapse
|
|
88
|
+
* into a single undo. No-op when there's nothing pending to capture.
|
|
89
|
+
*/
|
|
90
|
+
stopCapturing(): void;
|
|
70
91
|
canUndo(): boolean;
|
|
71
92
|
canRedo(): boolean;
|
|
72
93
|
clear(): void;
|
package/dist/history/types.d.ts
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
|
+
import { Selection } from '../doc/api';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
* the
|
|
4
|
-
*
|
|
3
|
+
* Selection inside an editable textbox frame. Frame bodies aren't body
|
|
4
|
+
* registry blocks, so the public `Selection` model can't address them —
|
|
5
|
+
* but undo/redo still needs to put the caret (or range) back. The editor
|
|
6
|
+
* captures this on a frame edit and restores it on undo, exactly as it
|
|
7
|
+
* does the body `Selection`; `History` treats the stashed value as opaque.
|
|
8
|
+
* A collapsed caret has `start === end`.
|
|
5
9
|
*/
|
|
10
|
+
export interface FrameSelection {
|
|
11
|
+
kind: "frame-selection";
|
|
12
|
+
/** `data-anchor-id` of the frame the selection was in. */
|
|
13
|
+
frameId: string;
|
|
14
|
+
/** Character offset of the selection start across the frame's text. */
|
|
15
|
+
start: number;
|
|
16
|
+
/** Character offset of the selection end (=== start for a caret). */
|
|
17
|
+
end: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* What the editor stashes for an undo step: a body `Selection` (incl.
|
|
21
|
+
* `null` when focus is outside) or a {@link FrameSelection}. Restored
|
|
22
|
+
* verbatim on undo/redo so the cursor lands where the body's would.
|
|
23
|
+
*/
|
|
24
|
+
export type CapturedSelection = Selection | FrameSelection;
|
|
25
|
+
/**
|
|
26
|
+
* Both ends of an undo step's cursor: where it sat BEFORE the edit and
|
|
27
|
+
* AFTER it. Undo restores `before` (you land where you started the edit);
|
|
28
|
+
* redo restores `after` (you land where the edit left you) — Word/Docs
|
|
29
|
+
* behaviour. Stashed on each `Y.UndoManager` stack item's meta.
|
|
30
|
+
*/
|
|
31
|
+
export interface UndoSelections {
|
|
32
|
+
before: CapturedSelection;
|
|
33
|
+
after: CapturedSelection;
|
|
34
|
+
}
|
|
6
35
|
export interface HistoryConfig {
|
|
7
36
|
/** Hard cap on entry count (per stack). UndoManager doesn't expose
|
|
8
37
|
* a max-depth knob directly — kept here for forward-compat in case
|