@sciflow/editor-start 0.0.3 → 0.1.1
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 +21 -0
- package/README.md +50 -29
- package/dist/bundle/sciflow-editor.css +1 -1
- package/dist/bundle/sciflow-editor.js +4020 -3326
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/lib/editor-element.d.ts +97 -1
- package/dist/lib/editor-element.d.ts.map +1 -1
- package/dist/lib/editor-element.js +435 -25
- package/dist/lib/format-bar.d.ts +29 -0
- package/dist/lib/format-bar.d.ts.map +1 -1
- package/dist/lib/format-bar.js +53 -3
- package/dist/lib/outline.d.ts +44 -0
- package/dist/lib/outline.d.ts.map +1 -1
- package/dist/lib/outline.js +120 -6
- package/dist/lib/range-decorations.d.ts +120 -0
- package/dist/lib/range-decorations.d.ts.map +1 -0
- package/dist/lib/range-decorations.js +131 -0
- package/dist/lib/read-only.d.ts +95 -0
- package/dist/lib/read-only.d.ts.map +1 -0
- package/dist/lib/read-only.js +123 -0
- package/dist/lib/selection-editor.d.ts +103 -2
- package/dist/lib/selection-editor.d.ts.map +1 -1
- package/dist/lib/selection-editor.js +222 -13
- package/dist/testing/external-widget-simulator.d.ts +217 -0
- package/dist/testing/external-widget-simulator.d.ts.map +1 -0
- package/dist/testing/external-widget-simulator.js +350 -0
- package/package.json +25 -13
- package/dist/lib/test-fixtures/soak-documents.d.ts +0 -13
- package/dist/lib/test-fixtures/soak-documents.d.ts.map +0 -1
- package/dist/lib/test-fixtures/soak-documents.js +0 -69
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module read-only
|
|
3
|
+
*
|
|
4
|
+
* A generic, toggleable read-only `Feature`: vetoes every doc-changing
|
|
5
|
+
* transaction while leaving selection/scroll transactions free to pass (so
|
|
6
|
+
* browsing — clicking around, selecting text to read it — still works),
|
|
7
|
+
* disables the DOM's own `contenteditable`/caret/IME behavior, and marks the
|
|
8
|
+
* editable surface with a styling hook so consumers can render a muted look.
|
|
9
|
+
*
|
|
10
|
+
* # Mechanism
|
|
11
|
+
*
|
|
12
|
+
* - `filterTransaction: (tr, state) => !tr.docChanged || isExternalSyncTransaction(tr) || key.getState(state) !== true`
|
|
13
|
+
* — `EditorState.applyTransaction` checks this BEFORE running any plugin's
|
|
14
|
+
* `state.apply`, so a vetoed transaction never reaches the doc, the
|
|
15
|
+
* undo-history plugin, or anything else — the state comes back byte-for-
|
|
16
|
+
* byte unchanged (`newState === oldState`). Selection-only and meta-only
|
|
17
|
+
* transactions (`tr.docChanged === false` — e.g. a click, or another
|
|
18
|
+
* feature's own `dispatchMeta` update) are explicitly let through, and so
|
|
19
|
+
* is `Editor`'s own external-doc reconciliation transaction (see the
|
|
20
|
+
* "Programmatic doc replacement" section below) — only an actual user/
|
|
21
|
+
* command edit is vetoed.
|
|
22
|
+
* - `props.editable: (state) => key.getState(state) !== true` — the DOM-level
|
|
23
|
+
* backstop: disables `contenteditable`, so the browser's own caret/IME
|
|
24
|
+
* never engages in the first place. `filterTransaction` alone would still
|
|
25
|
+
* technically block an edit, but a live caret sitting in "dead" text reads
|
|
26
|
+
* as broken, not read-only.
|
|
27
|
+
* - `props.attributes: (state) => (key.getState(state) ? { 'data-readonly': 'true' } : {})`
|
|
28
|
+
* — the styling hook. No baked-in colors here (only a `data-readonly`
|
|
29
|
+
* attribute) — style the muted look with your own token-based CSS, e.g.
|
|
30
|
+
* `.sf-editable-surface .ProseMirror[data-readonly] { opacity: var(--sf-opacity-muted); }`.
|
|
31
|
+
*
|
|
32
|
+
* # Programmatic doc replacement still works while read-only
|
|
33
|
+
*
|
|
34
|
+
* "Read-only" means "the user cannot edit this document" — not "this
|
|
35
|
+
* document can never change from any source." A host that reassigns
|
|
36
|
+
* `editor.doc` (e.g. a revision viewer paging through history) drives
|
|
37
|
+
* `Editor.updateFromSync()`, which reconciles the mounted view via its own
|
|
38
|
+
* transaction (`Editor`'s internal `syncViewWithState()`), tagged with
|
|
39
|
+
* `EXTERNAL_SYNC_TRANSACTION_META`. `filterTransaction` lets THAT transaction
|
|
40
|
+
* through even while read-only, so the view keeps rendering every
|
|
41
|
+
* subsequent doc the host assigns; only a transaction WITHOUT that meta
|
|
42
|
+
* (a real edit) is vetoed. See `@sciflow/editor-core`'s
|
|
43
|
+
* `EXTERNAL_SYNC_TRANSACTION_META`/`isExternalSyncTransaction` doc for the
|
|
44
|
+
* full contract — any custom read-only-style `filterTransaction` should
|
|
45
|
+
* follow the same check, or it will "freeze" the editor's own
|
|
46
|
+
* `updateFromSync()` calls after the first doc assignment, not just block
|
|
47
|
+
* user typing.
|
|
48
|
+
*
|
|
49
|
+
* # Toggling without re-initializing the editor
|
|
50
|
+
*
|
|
51
|
+
* The read-only flag lives in PLUGIN STATE (keyed, like `range-decorations.ts`,
|
|
52
|
+
* so it survives every transaction via a plain `state.apply`), not a value
|
|
53
|
+
* captured once at feature-construction time — `filterTransaction`/`editable`/
|
|
54
|
+
* `attributes` all read the CURRENT state on every check. This means the
|
|
55
|
+
* flag genuinely toggles live, no `configureFeatures()`/re-mount needed:
|
|
56
|
+
*
|
|
57
|
+
* ```typescript
|
|
58
|
+
* import { createReadOnlyFeature } from '@sciflow/editor-start/bundle';
|
|
59
|
+
*
|
|
60
|
+
* const { feature, key } = createReadOnlyFeature('my-read-only');
|
|
61
|
+
* await editor.configureFeatures([...otherFeatures, feature]);
|
|
62
|
+
*
|
|
63
|
+
* editor.plugins.dispatchMeta(key, true); // now read-only
|
|
64
|
+
* editor.plugins.dispatchMeta(key, false); // editable again, same editor instance
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* # A caveat worth stating plainly, not silently
|
|
68
|
+
*
|
|
69
|
+
* `filterTransaction` guarantees the DOC never actually changes for a
|
|
70
|
+
* vetoed transaction, but a host's own `dispatchTransaction` handler that
|
|
71
|
+
* inspects the REJECTED transaction object directly (rather than comparing
|
|
72
|
+
* before/after state) can still be misled: `tr.docChanged` reflects what the
|
|
73
|
+
* transaction WOULD have done, not whether it was applied. A consumer
|
|
74
|
+
* wiring up its own change-tracking on a read-only editor should compare
|
|
75
|
+
* `newState !== oldState` (or `newState.doc.eq(oldState.doc)`) rather than
|
|
76
|
+
* trusting `tr.docChanged` alone. `@sciflow/editor-core`'s own
|
|
77
|
+
* `handleTransaction` does inspect `tr.docChanged` directly — this is a
|
|
78
|
+
* known, narrow gap for the (unusual) case of listening to `editor-change`
|
|
79
|
+
* on a read-only instance, not something this feature can close from a
|
|
80
|
+
* plugin alone. Not a concern for the ordinary "browse a read-view editor,
|
|
81
|
+
* nobody listens to its `editor-change`" case.
|
|
82
|
+
*/
|
|
83
|
+
import { PluginKey } from 'prosemirror-state';
|
|
84
|
+
import { type Feature } from '@sciflow/editor-core';
|
|
85
|
+
/**
|
|
86
|
+
* Build a fresh, independently-keyed read-only `Feature`. `initialReadOnly`
|
|
87
|
+
* sets the STARTING value (default `false` — editable, matching an ordinary
|
|
88
|
+
* editor's least-surprising default); flip it live afterward via
|
|
89
|
+
* `editor.plugins.dispatchMeta(key, true | false)`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function createReadOnlyFeature(name: string, initialReadOnly?: boolean): {
|
|
92
|
+
feature: Feature;
|
|
93
|
+
key: PluginKey<boolean>;
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=read-only.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-only.d.ts","sourceRoot":"","sources":["../../src/lib/read-only.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AAEH,OAAO,EAAU,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/E;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,eAAe,UAAQ,GACtB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CAAE,CAiC/C"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module read-only
|
|
3
|
+
*
|
|
4
|
+
* A generic, toggleable read-only `Feature`: vetoes every doc-changing
|
|
5
|
+
* transaction while leaving selection/scroll transactions free to pass (so
|
|
6
|
+
* browsing — clicking around, selecting text to read it — still works),
|
|
7
|
+
* disables the DOM's own `contenteditable`/caret/IME behavior, and marks the
|
|
8
|
+
* editable surface with a styling hook so consumers can render a muted look.
|
|
9
|
+
*
|
|
10
|
+
* # Mechanism
|
|
11
|
+
*
|
|
12
|
+
* - `filterTransaction: (tr, state) => !tr.docChanged || isExternalSyncTransaction(tr) || key.getState(state) !== true`
|
|
13
|
+
* — `EditorState.applyTransaction` checks this BEFORE running any plugin's
|
|
14
|
+
* `state.apply`, so a vetoed transaction never reaches the doc, the
|
|
15
|
+
* undo-history plugin, or anything else — the state comes back byte-for-
|
|
16
|
+
* byte unchanged (`newState === oldState`). Selection-only and meta-only
|
|
17
|
+
* transactions (`tr.docChanged === false` — e.g. a click, or another
|
|
18
|
+
* feature's own `dispatchMeta` update) are explicitly let through, and so
|
|
19
|
+
* is `Editor`'s own external-doc reconciliation transaction (see the
|
|
20
|
+
* "Programmatic doc replacement" section below) — only an actual user/
|
|
21
|
+
* command edit is vetoed.
|
|
22
|
+
* - `props.editable: (state) => key.getState(state) !== true` — the DOM-level
|
|
23
|
+
* backstop: disables `contenteditable`, so the browser's own caret/IME
|
|
24
|
+
* never engages in the first place. `filterTransaction` alone would still
|
|
25
|
+
* technically block an edit, but a live caret sitting in "dead" text reads
|
|
26
|
+
* as broken, not read-only.
|
|
27
|
+
* - `props.attributes: (state) => (key.getState(state) ? { 'data-readonly': 'true' } : {})`
|
|
28
|
+
* — the styling hook. No baked-in colors here (only a `data-readonly`
|
|
29
|
+
* attribute) — style the muted look with your own token-based CSS, e.g.
|
|
30
|
+
* `.sf-editable-surface .ProseMirror[data-readonly] { opacity: var(--sf-opacity-muted); }`.
|
|
31
|
+
*
|
|
32
|
+
* # Programmatic doc replacement still works while read-only
|
|
33
|
+
*
|
|
34
|
+
* "Read-only" means "the user cannot edit this document" — not "this
|
|
35
|
+
* document can never change from any source." A host that reassigns
|
|
36
|
+
* `editor.doc` (e.g. a revision viewer paging through history) drives
|
|
37
|
+
* `Editor.updateFromSync()`, which reconciles the mounted view via its own
|
|
38
|
+
* transaction (`Editor`'s internal `syncViewWithState()`), tagged with
|
|
39
|
+
* `EXTERNAL_SYNC_TRANSACTION_META`. `filterTransaction` lets THAT transaction
|
|
40
|
+
* through even while read-only, so the view keeps rendering every
|
|
41
|
+
* subsequent doc the host assigns; only a transaction WITHOUT that meta
|
|
42
|
+
* (a real edit) is vetoed. See `@sciflow/editor-core`'s
|
|
43
|
+
* `EXTERNAL_SYNC_TRANSACTION_META`/`isExternalSyncTransaction` doc for the
|
|
44
|
+
* full contract — any custom read-only-style `filterTransaction` should
|
|
45
|
+
* follow the same check, or it will "freeze" the editor's own
|
|
46
|
+
* `updateFromSync()` calls after the first doc assignment, not just block
|
|
47
|
+
* user typing.
|
|
48
|
+
*
|
|
49
|
+
* # Toggling without re-initializing the editor
|
|
50
|
+
*
|
|
51
|
+
* The read-only flag lives in PLUGIN STATE (keyed, like `range-decorations.ts`,
|
|
52
|
+
* so it survives every transaction via a plain `state.apply`), not a value
|
|
53
|
+
* captured once at feature-construction time — `filterTransaction`/`editable`/
|
|
54
|
+
* `attributes` all read the CURRENT state on every check. This means the
|
|
55
|
+
* flag genuinely toggles live, no `configureFeatures()`/re-mount needed:
|
|
56
|
+
*
|
|
57
|
+
* ```typescript
|
|
58
|
+
* import { createReadOnlyFeature } from '@sciflow/editor-start/bundle';
|
|
59
|
+
*
|
|
60
|
+
* const { feature, key } = createReadOnlyFeature('my-read-only');
|
|
61
|
+
* await editor.configureFeatures([...otherFeatures, feature]);
|
|
62
|
+
*
|
|
63
|
+
* editor.plugins.dispatchMeta(key, true); // now read-only
|
|
64
|
+
* editor.plugins.dispatchMeta(key, false); // editable again, same editor instance
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* # A caveat worth stating plainly, not silently
|
|
68
|
+
*
|
|
69
|
+
* `filterTransaction` guarantees the DOC never actually changes for a
|
|
70
|
+
* vetoed transaction, but a host's own `dispatchTransaction` handler that
|
|
71
|
+
* inspects the REJECTED transaction object directly (rather than comparing
|
|
72
|
+
* before/after state) can still be misled: `tr.docChanged` reflects what the
|
|
73
|
+
* transaction WOULD have done, not whether it was applied. A consumer
|
|
74
|
+
* wiring up its own change-tracking on a read-only editor should compare
|
|
75
|
+
* `newState !== oldState` (or `newState.doc.eq(oldState.doc)`) rather than
|
|
76
|
+
* trusting `tr.docChanged` alone. `@sciflow/editor-core`'s own
|
|
77
|
+
* `handleTransaction` does inspect `tr.docChanged` directly — this is a
|
|
78
|
+
* known, narrow gap for the (unusual) case of listening to `editor-change`
|
|
79
|
+
* on a read-only instance, not something this feature can close from a
|
|
80
|
+
* plugin alone. Not a concern for the ordinary "browse a read-view editor,
|
|
81
|
+
* nobody listens to its `editor-change`" case.
|
|
82
|
+
*/
|
|
83
|
+
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
84
|
+
import { isExternalSyncTransaction } from '@sciflow/editor-core';
|
|
85
|
+
/**
|
|
86
|
+
* Build a fresh, independently-keyed read-only `Feature`. `initialReadOnly`
|
|
87
|
+
* sets the STARTING value (default `false` — editable, matching an ordinary
|
|
88
|
+
* editor's least-surprising default); flip it live afterward via
|
|
89
|
+
* `editor.plugins.dispatchMeta(key, true | false)`.
|
|
90
|
+
*/
|
|
91
|
+
export function createReadOnlyFeature(name, initialReadOnly = false) {
|
|
92
|
+
const key = new PluginKey(name);
|
|
93
|
+
const plugin = new Plugin({
|
|
94
|
+
key,
|
|
95
|
+
state: {
|
|
96
|
+
init: () => initialReadOnly,
|
|
97
|
+
apply(tr, readOnly) {
|
|
98
|
+
const meta = tr.getMeta(key);
|
|
99
|
+
return typeof meta === 'boolean' ? meta : readOnly;
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
filterTransaction(tr, state) {
|
|
103
|
+
if (!tr.docChanged)
|
|
104
|
+
return true;
|
|
105
|
+
// The editor's OWN external-doc reconciliation (Editor.updateFromSync /
|
|
106
|
+
// .applyOps, via syncViewWithState) — not a user edit. Letting it
|
|
107
|
+
// through is what makes `editor.doc = nextSnapshot` keep rendering on a
|
|
108
|
+
// read-only instance after the first assignment; see the module doc.
|
|
109
|
+
if (isExternalSyncTransaction(tr))
|
|
110
|
+
return true;
|
|
111
|
+
return key.getState(state) !== true;
|
|
112
|
+
},
|
|
113
|
+
props: {
|
|
114
|
+
editable: (state) => key.getState(state) !== true,
|
|
115
|
+
attributes: (state) => (key.getState(state) ? { 'data-readonly': 'true' } : {}),
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
const feature = {
|
|
119
|
+
name,
|
|
120
|
+
addPlugins: () => [plugin],
|
|
121
|
+
};
|
|
122
|
+
return { feature, key };
|
|
123
|
+
}
|
|
@@ -96,9 +96,39 @@ export declare class SciFlowSelectionEditorElement extends LitElement {
|
|
|
96
96
|
/** Convenience getter mirroring `editor.getCommands()`. */
|
|
97
97
|
private getCommandRunner;
|
|
98
98
|
/**
|
|
99
|
-
*
|
|
99
|
+
* Whether the bound editor currently accepts edits. Every path in this panel
|
|
100
|
+
* that writes to the document asks first, and fails closed when there is no
|
|
101
|
+
* view to ask.
|
|
102
|
+
*
|
|
103
|
+
* A host can turn editing off at any time
|
|
104
|
+
* (`view.setProps({ editable: () => false })`) and expects the whole surface
|
|
105
|
+
* to go quiet — a side panel that still writes would make a read-only
|
|
106
|
+
* document change under the reader. `view.editable` is the same signal the
|
|
107
|
+
* editor's own key and click handling reads, so the panel cannot drift from
|
|
108
|
+
* the editing surface. The guards sit on the write itself rather than only on
|
|
109
|
+
* the controls: the panel re-renders on selection changes, so editability can
|
|
110
|
+
* flip while a button from the editable render is still on screen.
|
|
100
111
|
*/
|
|
112
|
+
private isEditorEditable;
|
|
113
|
+
/**
|
|
114
|
+
* The panel's own name for a node type in the active locale, or `null` when it
|
|
115
|
+
* has none. Cased for use inside a sentence, so callers that need a heading
|
|
116
|
+
* capitalise it themselves — English writes these names lower case, German
|
|
117
|
+
* capitalises every noun, and only the dictionary knows which.
|
|
118
|
+
*/
|
|
119
|
+
private getNodeTypeName;
|
|
101
120
|
private getNodeTypeLabel;
|
|
121
|
+
/**
|
|
122
|
+
* The node this panel is currently describing, read back from the live
|
|
123
|
+
* document, or `null` when the panel is describing a mark or nothing at all.
|
|
124
|
+
*/
|
|
125
|
+
private getSelectedNode;
|
|
126
|
+
/**
|
|
127
|
+
* A table is a `figure` whose first child is a `table` rather than an image,
|
|
128
|
+
* so the content is what tells a reader which one is selected — the node type
|
|
129
|
+
* is `figure` either way.
|
|
130
|
+
*/
|
|
131
|
+
private isTableFigure;
|
|
102
132
|
private renderAttributeField;
|
|
103
133
|
/**
|
|
104
134
|
* Convert a raw attribute name like 'text-align' to a human-readable label.
|
|
@@ -119,7 +149,18 @@ export declare class SciFlowSelectionEditorElement extends LitElement {
|
|
|
119
149
|
private unmountCitationSourceAdapter;
|
|
120
150
|
private handleDraftAttrChange;
|
|
121
151
|
/**
|
|
122
|
-
* Render the figure sidebar: type,
|
|
152
|
+
* Render the figure sidebar: type, image address, alt text.
|
|
153
|
+
*
|
|
154
|
+
* The image address is editable here because this panel is the only place a
|
|
155
|
+
* reader can change it: clicking an image selects the figure rather than
|
|
156
|
+
* opening a picker, so the address has to be reachable as an ordinary field.
|
|
157
|
+
* It is a plain text input, so a URL, a relative path or a data URI are all
|
|
158
|
+
* accepted; the value is written on `change` like every other draft attribute
|
|
159
|
+
* and committed with Apply.
|
|
160
|
+
*
|
|
161
|
+
* A table is a `figure` too, so the heading and the form's accessible name
|
|
162
|
+
* both come from the selected node rather than from the node type alone —
|
|
163
|
+
* otherwise a selected table would be titled "Figure".
|
|
123
164
|
*/
|
|
124
165
|
private renderFigureSidebar;
|
|
125
166
|
/**
|
|
@@ -155,8 +196,68 @@ export declare class SciFlowSelectionEditorElement extends LitElement {
|
|
|
155
196
|
private setDraftAttr;
|
|
156
197
|
private applyDraftAttrs;
|
|
157
198
|
private revertDraftAttrs;
|
|
199
|
+
/**
|
|
200
|
+
* Apply/Revert for pending attribute edits.
|
|
201
|
+
*
|
|
202
|
+
* Withheld when the editor is not editable: `applyDraftAttrs` refuses to write
|
|
203
|
+
* either way — that guard is the barrier — but offering an Apply that cannot
|
|
204
|
+
* act reads as a broken control rather than a read-only document.
|
|
205
|
+
*/
|
|
158
206
|
private renderDraftActions;
|
|
207
|
+
/**
|
|
208
|
+
* Controls that act on the selection itself rather than on its attributes.
|
|
209
|
+
*
|
|
210
|
+
* The delete action sits here, at the top of the panel, deliberately far from
|
|
211
|
+
* the Apply/Update primary at the bottom: a destructive verb never shares a
|
|
212
|
+
* region with the action a user is aiming for. It is a plain `<button>` with
|
|
213
|
+
* visible text, so it is keyboard reachable and its accessible name is the
|
|
214
|
+
* label itself. Removal is undoable through editor history, so it commits
|
|
215
|
+
* straight away rather than opening a confirmation step.
|
|
216
|
+
*/
|
|
159
217
|
private renderSelectionControls;
|
|
218
|
+
/**
|
|
219
|
+
* The node the delete action would remove, or `null` when there is none the
|
|
220
|
+
* panel may act on.
|
|
221
|
+
*
|
|
222
|
+
* Only a `NodeSelection` qualifies: a text range inside a caption or paragraph
|
|
223
|
+
* belongs to the editing surface, not to a panel-level "delete this element"
|
|
224
|
+
* verb. `deleteSelection` is probed with `dispatch` omitted, so the check
|
|
225
|
+
* cannot edit the document.
|
|
226
|
+
*
|
|
227
|
+
* A view that is not editable never yields a target. A host can turn editing
|
|
228
|
+
* off at any time (`view.setProps({ editable: () => false })`) and expects the
|
|
229
|
+
* whole surface to go quiet — a side panel that still removes content would
|
|
230
|
+
* make a read-only document lose it. `view.editable` is the same signal the
|
|
231
|
+
* editor's own key and click handling reads, so the panel cannot drift from
|
|
232
|
+
* the editing surface.
|
|
233
|
+
*
|
|
234
|
+
* Withheld while the panel is pinned, and that is a limitation rather than a
|
|
235
|
+
* design goal. A pinned panel stops following the editor selection and
|
|
236
|
+
* therefore stops re-rendering, while `elementInfo.position` is never remapped
|
|
237
|
+
* through the transaction mapping — so every pinned control already acts on a
|
|
238
|
+
* position that may have drifted, and the attribute fields cope only because
|
|
239
|
+
* they re-check the node type at that position before writing. Removal has no
|
|
240
|
+
* such recheck available: after one deletion the frozen panel would still show
|
|
241
|
+
* the control, now aimed at whatever moved into that position. Making the pin
|
|
242
|
+
* remap its stored position on every document change would fix this for all
|
|
243
|
+
* pinned controls at once; until then the destructive one stays out.
|
|
244
|
+
*/
|
|
245
|
+
private getDeletableNode;
|
|
246
|
+
/**
|
|
247
|
+
* Label for the delete action, naming what is about to be removed. The visible
|
|
248
|
+
* text is the button's accessible name, so naming the node here keeps the two
|
|
249
|
+
* identical — no `aria-label` to drift from what is on screen. Anything the
|
|
250
|
+
* panel has no name for falls back to the generic wording.
|
|
251
|
+
*/
|
|
252
|
+
private getDeleteLabel;
|
|
253
|
+
/**
|
|
254
|
+
* Remove the selected node through ProseMirror's own deletion command, so the
|
|
255
|
+
* change is a normal transaction and stays undoable and collab-safe. The state
|
|
256
|
+
* is read from the view at call time rather than reused from render, and the
|
|
257
|
+
* editability guard is repeated here: a host can switch the view to read-only
|
|
258
|
+
* after the button was rendered, and the rendered panel would not know.
|
|
259
|
+
*/
|
|
260
|
+
private deleteSelectedNode;
|
|
160
261
|
private togglePinSelection;
|
|
161
262
|
private handleGenericKeydown;
|
|
162
263
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-editor.d.ts","sourceRoot":"","sources":["../../src/lib/selection-editor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAa,UAAU,
|
|
1
|
+
{"version":3,"file":"selection-editor.d.ts","sourceRoot":"","sources":["../../src/lib/selection-editor.ts"],"names":[],"mappings":"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"}
|