@openleaf-editor/ui 0.1.0-beta.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 +202 -0
- package/dist/dialog.d.ts +25 -0
- package/dist/dialog.d.ts.map +1 -0
- package/dist/dialog.js +266 -0
- package/dist/dialog.js.map +1 -0
- package/dist/icons.d.ts +53 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +143 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/items.d.ts +13 -0
- package/dist/items.d.ts.map +1 -0
- package/dist/items.js +190 -0
- package/dist/items.js.map +1 -0
- package/dist/openleaf.css +426 -0
- package/dist/registry.d.ts +85 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +77 -0
- package/dist/registry.js.map +1 -0
- package/dist/skins.d.ts +114 -0
- package/dist/skins.d.ts.map +1 -0
- package/dist/skins.js +226 -0
- package/dist/skins.js.map +1 -0
- package/dist/styles.d.ts +65 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +532 -0
- package/dist/styles.js.map +1 -0
- package/dist/toolbar.d.ts +76 -0
- package/dist/toolbar.d.ts.map +1 -0
- package/dist/toolbar.js +509 -0
- package/dist/toolbar.js.map +1 -0
- package/package.json +39 -0
package/dist/toolbar.js
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The toolbar.
|
|
3
|
+
*
|
|
4
|
+
* A plain class rather than a custom element: the editor is already a custom
|
|
5
|
+
* element, buttons are just DOM, and per-button custom elements would cost
|
|
6
|
+
* bundle size and upgrade-timing complexity for no benefit.
|
|
7
|
+
*
|
|
8
|
+
* ## Keyboard model
|
|
9
|
+
*
|
|
10
|
+
* `role="toolbar"` with a roving tabindex, so the whole bar is ONE tab stop.
|
|
11
|
+
* Without that, Tab from the editable region walks a keyboard user through
|
|
12
|
+
* twenty buttons before they reach their content.
|
|
13
|
+
*
|
|
14
|
+
* Two details that are easy to get wrong and both matter:
|
|
15
|
+
*
|
|
16
|
+
* 1. **Arrow-key roving is applied only to `<button>` elements.** The block-type
|
|
17
|
+
* control is a native `<select>`, and when focus is on it, Left/Right have two
|
|
18
|
+
* competing owners -- the roving handler wants to move to the next item, the
|
|
19
|
+
* select natively wants to change its value. Intercepting those keys breaks
|
|
20
|
+
* the select; not intercepting them breaks the toolbar contract. The
|
|
21
|
+
* resolution is that the select owns all of its own key events and is a
|
|
22
|
+
* genuine second tab stop rather than part of the roving scheme.
|
|
23
|
+
*
|
|
24
|
+
* 2. **Escape returns focus and the selection to the content.** Preventing mouse
|
|
25
|
+
* clicks from stealing focus solves the mouse case and leaves the keyboard
|
|
26
|
+
* case undefined: once a screen reader user deliberately enters the toolbar,
|
|
27
|
+
* focus really is on a button, and without a return path their only way out
|
|
28
|
+
* is blind-Tabbing through the rest of the host's form. `Alt+F10` enters,
|
|
29
|
+
* Escape leaves, matching TinyMCE and CKEditor 5 so muscle memory transfers.
|
|
30
|
+
*/
|
|
31
|
+
import { activeHeadingLevel, shortcutFor, toggleHeading, setParagraph } from '@openleaf-editor/core';
|
|
32
|
+
import { ensureSprite, iconElement } from './icons.js';
|
|
33
|
+
import { DEFAULT_LAYOUT, getToolbarItem, onRegistryChange, } from './registry.js';
|
|
34
|
+
import { ensureStyles } from './styles.js';
|
|
35
|
+
const BLOCK_TYPE_ID = 'blockType';
|
|
36
|
+
/** Item+callback pairs already reported, so a per-keystroke failure logs once. */
|
|
37
|
+
const reported = new Set();
|
|
38
|
+
/**
|
|
39
|
+
* Call a third-party predicate, falling back rather than propagating.
|
|
40
|
+
*
|
|
41
|
+
* The fallback for BOTH `isActive` and `isEnabled` is `false`. Defaulting
|
|
42
|
+
* `isEnabled` to true would invite a click straight into the code path that just
|
|
43
|
+
* threw; a control whose enablement cannot be computed should read as
|
|
44
|
+
* unavailable, which is the same reasoning the table plugin already applies to
|
|
45
|
+
* commands that are meaningless outside a table.
|
|
46
|
+
*
|
|
47
|
+
* Logged once per item and callback. A predicate that throws on every
|
|
48
|
+
* transaction would otherwise emit thousands of identical lines and bury the
|
|
49
|
+
* first one, which is the only one with a useful stack.
|
|
50
|
+
*/
|
|
51
|
+
function guarded(itemId, kind, run) {
|
|
52
|
+
try {
|
|
53
|
+
return run();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const key = `${itemId}:${kind}`;
|
|
57
|
+
if (!reported.has(key)) {
|
|
58
|
+
reported.add(key);
|
|
59
|
+
console.error(`@openleaf-editor/ui: the ${kind} predicate for toolbar item "${itemId}" threw. ` +
|
|
60
|
+
'The control is shown as unavailable. This is a bug in whatever registered ' +
|
|
61
|
+
'it, not in the editor.', error);
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export class Toolbar {
|
|
67
|
+
el;
|
|
68
|
+
#doc;
|
|
69
|
+
#host;
|
|
70
|
+
#view = null;
|
|
71
|
+
#controls = new Map();
|
|
72
|
+
#select = null;
|
|
73
|
+
#live;
|
|
74
|
+
#liveTimer;
|
|
75
|
+
#layout;
|
|
76
|
+
#unsubscribe;
|
|
77
|
+
/** Focusable buttons in DOM order; the roving tabindex walks this. */
|
|
78
|
+
#focusables = [];
|
|
79
|
+
#rovingIndex = 0;
|
|
80
|
+
constructor(host, doc, options = {}) {
|
|
81
|
+
this.#host = host;
|
|
82
|
+
this.#doc = doc;
|
|
83
|
+
this.#layout = options.layout ?? DEFAULT_LAYOUT;
|
|
84
|
+
ensureStyles(doc);
|
|
85
|
+
ensureSprite(doc);
|
|
86
|
+
this.el = doc.createElement('div');
|
|
87
|
+
this.el.className = 'ol-toolbar';
|
|
88
|
+
this.el.setAttribute('role', 'toolbar');
|
|
89
|
+
this.el.setAttribute('aria-label', options.label ?? 'Formatting');
|
|
90
|
+
this.#live = doc.createElement('div');
|
|
91
|
+
this.#live.className = 'ol-live';
|
|
92
|
+
// Polite and atomic: an assertive region would interrupt the author
|
|
93
|
+
// mid-word, and a non-atomic one can read partial updates.
|
|
94
|
+
this.#live.setAttribute('role', 'status');
|
|
95
|
+
this.#live.setAttribute('aria-live', 'polite');
|
|
96
|
+
this.#live.setAttribute('aria-atomic', 'true');
|
|
97
|
+
this.el.addEventListener('keydown', this.#onKeydown);
|
|
98
|
+
// Re-render when a plugin registers late. Import-time registration races
|
|
99
|
+
// code-split chunks, and a button that silently never appears is worse than
|
|
100
|
+
// a re-render.
|
|
101
|
+
this.#unsubscribe = onRegistryChange(() => {
|
|
102
|
+
this.#rerenderPreservingState();
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/** Attach to a view and build the controls. */
|
|
106
|
+
mount(view) {
|
|
107
|
+
this.#view = view;
|
|
108
|
+
this.#render();
|
|
109
|
+
this.update(view.state);
|
|
110
|
+
}
|
|
111
|
+
destroy() {
|
|
112
|
+
this.#unsubscribe?.();
|
|
113
|
+
clearTimeout(this.#liveTimer);
|
|
114
|
+
this.el.removeEventListener('keydown', this.#onKeydown);
|
|
115
|
+
this.#controls.clear();
|
|
116
|
+
this.#view = null;
|
|
117
|
+
}
|
|
118
|
+
/** The live region element, which the host mounts once. */
|
|
119
|
+
get liveRegion() {
|
|
120
|
+
return this.#live;
|
|
121
|
+
}
|
|
122
|
+
/* -------------------------------------------------------------- *
|
|
123
|
+
* Rendering
|
|
124
|
+
* -------------------------------------------------------------- */
|
|
125
|
+
#render() {
|
|
126
|
+
this.el.replaceChildren();
|
|
127
|
+
this.#controls.clear();
|
|
128
|
+
this.#select = null;
|
|
129
|
+
let group = this.#newGroup();
|
|
130
|
+
for (const token of this.#layout.split(/\s+/).filter(Boolean)) {
|
|
131
|
+
if (token === '|') {
|
|
132
|
+
if (group.childElementCount > 0)
|
|
133
|
+
this.el.appendChild(group);
|
|
134
|
+
this.el.appendChild(this.#newSeparator());
|
|
135
|
+
group = this.#newGroup();
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (token === BLOCK_TYPE_ID) {
|
|
139
|
+
group.appendChild(this.#buildBlockTypeSelect());
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const spec = getToolbarItem(token);
|
|
143
|
+
// Silently skipping an unknown id would hide a typo in an integrator's
|
|
144
|
+
// `toolbar` attribute forever.
|
|
145
|
+
if (!spec) {
|
|
146
|
+
console.warn(`@openleaf-editor/ui: no toolbar item registered for "${token}"`);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
// Only `button` is implemented. The `type` discriminant exists so that
|
|
150
|
+
// adding variants later is not a breaking change to a published config
|
|
151
|
+
// shape -- but a declared-and-inert variant is worse than an absent one,
|
|
152
|
+
// because the author sees a plausible button and no signal that the
|
|
153
|
+
// control they asked for was not built.
|
|
154
|
+
if (spec.type && spec.type !== 'button') {
|
|
155
|
+
console.warn(`@openleaf-editor/ui: toolbar item "${spec.id}" declares type "${spec.type}", ` +
|
|
156
|
+
'which is not implemented yet. It is rendering as a button.');
|
|
157
|
+
}
|
|
158
|
+
group.appendChild(this.#buildButton(spec));
|
|
159
|
+
}
|
|
160
|
+
if (group.childElementCount > 0)
|
|
161
|
+
this.el.appendChild(group);
|
|
162
|
+
this.#refreshFocusables();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Rebuild after a registry change without dropping host-pushed state.
|
|
166
|
+
*
|
|
167
|
+
* Source view's pressed state lives on the control via `setItemState`, not in
|
|
168
|
+
* the document. Replacing every button would flash it off, and would yank
|
|
169
|
+
* focus out of a control the author was on.
|
|
170
|
+
*/
|
|
171
|
+
#rerenderPreservingState() {
|
|
172
|
+
const forced = new Map();
|
|
173
|
+
for (const [id, control] of this.#controls) {
|
|
174
|
+
const next = {};
|
|
175
|
+
if (control.forcedActive !== undefined)
|
|
176
|
+
next.active = control.forcedActive;
|
|
177
|
+
if (control.forcedEnabled !== undefined)
|
|
178
|
+
next.enabled = control.forcedEnabled;
|
|
179
|
+
if (next.active !== undefined || next.enabled !== undefined)
|
|
180
|
+
forced.set(id, next);
|
|
181
|
+
}
|
|
182
|
+
const active = this.#doc.activeElement;
|
|
183
|
+
const focusedId = active instanceof HTMLElement && this.el.contains(active)
|
|
184
|
+
? (active.dataset['olId'] ?? null)
|
|
185
|
+
: null;
|
|
186
|
+
this.#render();
|
|
187
|
+
for (const [id, state] of forced)
|
|
188
|
+
this.setItemState(id, state);
|
|
189
|
+
if (this.#view)
|
|
190
|
+
this.update(this.#view.state);
|
|
191
|
+
if (!focusedId)
|
|
192
|
+
return;
|
|
193
|
+
if (focusedId === BLOCK_TYPE_ID) {
|
|
194
|
+
this.#select?.focus();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const control = this.#controls.get(focusedId);
|
|
198
|
+
if (!control)
|
|
199
|
+
return;
|
|
200
|
+
const index = this.#focusables.indexOf(control.el);
|
|
201
|
+
if (index >= 0) {
|
|
202
|
+
this.#rovingIndex = index;
|
|
203
|
+
this.#applyRoving();
|
|
204
|
+
}
|
|
205
|
+
control.el.focus();
|
|
206
|
+
}
|
|
207
|
+
#newGroup() {
|
|
208
|
+
const group = this.#doc.createElement('div');
|
|
209
|
+
group.className = 'ol-group';
|
|
210
|
+
return group;
|
|
211
|
+
}
|
|
212
|
+
#newSeparator() {
|
|
213
|
+
const sep = this.#doc.createElement('div');
|
|
214
|
+
sep.className = 'ol-sep';
|
|
215
|
+
// Decorative. A separator announced as "separator" twenty times is noise.
|
|
216
|
+
sep.setAttribute('aria-hidden', 'true');
|
|
217
|
+
return sep;
|
|
218
|
+
}
|
|
219
|
+
#buildButton(spec) {
|
|
220
|
+
const button = this.#doc.createElement('button');
|
|
221
|
+
button.type = 'button';
|
|
222
|
+
button.className = 'ol-btn';
|
|
223
|
+
button.dataset['olId'] = spec.id;
|
|
224
|
+
// The accessible name stays constant across states. Baking "pressed" into
|
|
225
|
+
// it would double up with what the platform already announces.
|
|
226
|
+
button.setAttribute('aria-label', spec.label);
|
|
227
|
+
const shortcut = spec.shortcut ? shortcutFor(spec.shortcut) : null;
|
|
228
|
+
button.title = shortcut ? `${spec.label} (${shortcut})` : spec.label;
|
|
229
|
+
if ((spec.kind ?? 'action') === 'toggle') {
|
|
230
|
+
button.setAttribute('aria-pressed', 'false');
|
|
231
|
+
}
|
|
232
|
+
if (spec.icon)
|
|
233
|
+
button.appendChild(iconElement(spec.icon, this.#doc));
|
|
234
|
+
// Keep focus and the selection in the content. Without this the editor
|
|
235
|
+
// blurs on mousedown, the selection collapses, and the command applies to
|
|
236
|
+
// nothing.
|
|
237
|
+
button.addEventListener('mousedown', (event) => event.preventDefault());
|
|
238
|
+
button.addEventListener('click', () => this.#invoke(spec));
|
|
239
|
+
this.#controls.set(spec.id, { spec, el: button, active: null, enabled: null });
|
|
240
|
+
return button;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* The block-type control.
|
|
244
|
+
*
|
|
245
|
+
* A native `<select>`. A custom listbox would be several hundred lines of
|
|
246
|
+
* ARIA that would then owe real screen reader testing to be worth anything,
|
|
247
|
+
* and the native control is already tested by the browser vendors. It carries
|
|
248
|
+
* its own accessible name because the toolbar's own label does not describe it.
|
|
249
|
+
*/
|
|
250
|
+
#buildBlockTypeSelect() {
|
|
251
|
+
const select = this.#doc.createElement('select');
|
|
252
|
+
select.className = 'ol-select';
|
|
253
|
+
select.setAttribute('aria-label', 'Paragraph style');
|
|
254
|
+
select.dataset['olId'] = BLOCK_TYPE_ID;
|
|
255
|
+
const options = [
|
|
256
|
+
['p', 'Paragraph'],
|
|
257
|
+
['1', 'Heading 1'],
|
|
258
|
+
['2', 'Heading 2'],
|
|
259
|
+
['3', 'Heading 3'],
|
|
260
|
+
['4', 'Heading 4'],
|
|
261
|
+
['5', 'Heading 5'],
|
|
262
|
+
['6', 'Heading 6'],
|
|
263
|
+
];
|
|
264
|
+
for (const [value, label] of options) {
|
|
265
|
+
const option = this.#doc.createElement('option');
|
|
266
|
+
option.value = value;
|
|
267
|
+
option.textContent = label;
|
|
268
|
+
select.appendChild(option);
|
|
269
|
+
}
|
|
270
|
+
select.addEventListener('mousedown', (event) => event.stopPropagation());
|
|
271
|
+
/**
|
|
272
|
+
* Whether the pending change came from a pointer rather than the keyboard.
|
|
273
|
+
*
|
|
274
|
+
* This distinction is load-bearing. In Firefox, and on macOS generally,
|
|
275
|
+
* arrow keys on a closed `<select>` change its value on every press. If the
|
|
276
|
+
* change handler returned focus to the content unconditionally, a keyboard
|
|
277
|
+
* user arrowing through the options would be thrown back into the document
|
|
278
|
+
* on the first press -- making the control unusable by keyboard while
|
|
279
|
+
* working perfectly with a mouse. Caught by a cross-browser test that
|
|
280
|
+
* passed in Chromium and failed in Firefox.
|
|
281
|
+
*/
|
|
282
|
+
let pointerDriven = false;
|
|
283
|
+
select.addEventListener('pointerdown', () => {
|
|
284
|
+
pointerDriven = true;
|
|
285
|
+
});
|
|
286
|
+
select.addEventListener('keydown', (event) => {
|
|
287
|
+
pointerDriven = false;
|
|
288
|
+
if (event.key === 'Enter') {
|
|
289
|
+
// A <select> inside a <form> submits it on Enter. The editor almost
|
|
290
|
+
// always sits inside the host's form, so this would post a half-written
|
|
291
|
+
// article.
|
|
292
|
+
event.preventDefault();
|
|
293
|
+
this.returnFocusToContent();
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
select.addEventListener('change', () => {
|
|
297
|
+
const view = this.#view;
|
|
298
|
+
if (!view)
|
|
299
|
+
return;
|
|
300
|
+
const value = select.value;
|
|
301
|
+
const command = value === 'p' ? setParagraph : toggleHeading(Number(value));
|
|
302
|
+
command(view.state, view.dispatch, view);
|
|
303
|
+
// Return the caret to the content only when the author committed the
|
|
304
|
+
// choice by pointer. Keyboard users keep focus and leave with Tab or
|
|
305
|
+
// Escape.
|
|
306
|
+
if (pointerDriven) {
|
|
307
|
+
pointerDriven = false;
|
|
308
|
+
view.focus();
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
this.#select = select;
|
|
312
|
+
return select;
|
|
313
|
+
}
|
|
314
|
+
/* -------------------------------------------------------------- *
|
|
315
|
+
* Invocation
|
|
316
|
+
* -------------------------------------------------------------- */
|
|
317
|
+
#invoke(spec) {
|
|
318
|
+
const view = this.#view;
|
|
319
|
+
if (!view)
|
|
320
|
+
return;
|
|
321
|
+
if (this.#host.hasAttribute('readonly'))
|
|
322
|
+
return;
|
|
323
|
+
const control = this.#controls.get(spec.id);
|
|
324
|
+
if (control && control.enabled === false)
|
|
325
|
+
return;
|
|
326
|
+
try {
|
|
327
|
+
if (spec.run) {
|
|
328
|
+
spec.run({ view, host: this.#host });
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (spec.command) {
|
|
332
|
+
spec.command(view.state, view.dispatch, view);
|
|
333
|
+
view.focus();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
console.error(`@openleaf-editor/ui: toolbar item "${spec.id}" threw when activated. ` +
|
|
338
|
+
'The editor is unaffected.', error);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/* -------------------------------------------------------------- *
|
|
342
|
+
* State synchronisation
|
|
343
|
+
* -------------------------------------------------------------- */
|
|
344
|
+
/**
|
|
345
|
+
* Reflect the editor state onto the controls.
|
|
346
|
+
*
|
|
347
|
+
* Deliberately synchronous, not batched into an animation frame. Twenty cheap
|
|
348
|
+
* predicates plus a diffed attribute write is sub-millisecond work, and
|
|
349
|
+
* batching would trade a perceptible frame of lag between pressing Bold and
|
|
350
|
+
* the button lighting up for a performance problem that does not exist.
|
|
351
|
+
*
|
|
352
|
+
* `tr` is passed so announcements can be gated on a real formatting change.
|
|
353
|
+
*/
|
|
354
|
+
update(state, tr) {
|
|
355
|
+
// Announce only on a discrete formatting transition, never on cursor
|
|
356
|
+
// movement through already-formatted text. That gate is the whole
|
|
357
|
+
// difference between a useful announcement and a chatty one.
|
|
358
|
+
const isFormattingChange = !!tr && (tr.docChanged || tr.storedMarksSet);
|
|
359
|
+
const transitions = [];
|
|
360
|
+
for (const control of this.#controls.values()) {
|
|
361
|
+
const { spec } = control;
|
|
362
|
+
const readonly = this.#host.hasAttribute('readonly');
|
|
363
|
+
const enabled = readonly
|
|
364
|
+
? false
|
|
365
|
+
: control.forcedEnabled ??
|
|
366
|
+
guarded(spec.id, 'isEnabled', () => spec.isEnabled ? spec.isEnabled(state) : spec.command ? spec.command(state) : true);
|
|
367
|
+
if (enabled !== control.enabled) {
|
|
368
|
+
control.enabled = enabled;
|
|
369
|
+
// aria-disabled, never the disabled attribute: a disabled button is
|
|
370
|
+
// removed from the roving tabindex and cannot be reached or announced,
|
|
371
|
+
// so an author using a screen reader cannot discover it exists.
|
|
372
|
+
control.el.setAttribute('aria-disabled', enabled ? 'false' : 'true');
|
|
373
|
+
}
|
|
374
|
+
if ((spec.kind ?? 'action') === 'toggle') {
|
|
375
|
+
const active = control.forcedActive ??
|
|
376
|
+
guarded(spec.id, 'isActive', () => (spec.isActive ? spec.isActive(state) : false));
|
|
377
|
+
if (active !== control.active) {
|
|
378
|
+
const previous = control.active;
|
|
379
|
+
control.active = active;
|
|
380
|
+
control.el.setAttribute('aria-pressed', active ? 'true' : 'false');
|
|
381
|
+
if (isFormattingChange && previous !== null) {
|
|
382
|
+
transitions.push(`${spec.label} ${active ? 'on' : 'off'}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (this.#select) {
|
|
388
|
+
const level = activeHeadingLevel(state);
|
|
389
|
+
const value = level === null ? 'p' : String(level);
|
|
390
|
+
if (this.#select.value !== value)
|
|
391
|
+
this.#select.value = value;
|
|
392
|
+
}
|
|
393
|
+
if (transitions.length > 0)
|
|
394
|
+
this.#announce(transitions.join(', '));
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Push a state a predicate cannot derive.
|
|
398
|
+
*
|
|
399
|
+
* `isActive`/`isEnabled` assume everything follows from the document and
|
|
400
|
+
* selection. Real plugin state does not: "upload in progress", "collab lock
|
|
401
|
+
* held by another user", "rewrite running" all live outside the document, and
|
|
402
|
+
* a pull-on-transaction model cannot see them.
|
|
403
|
+
*/
|
|
404
|
+
setItemState(id, state) {
|
|
405
|
+
const control = this.#controls.get(id);
|
|
406
|
+
if (!control)
|
|
407
|
+
return;
|
|
408
|
+
if (state.active !== undefined) {
|
|
409
|
+
control.forcedActive = state.active;
|
|
410
|
+
control.active = null;
|
|
411
|
+
}
|
|
412
|
+
if (state.enabled !== undefined) {
|
|
413
|
+
control.forcedEnabled = state.enabled;
|
|
414
|
+
control.enabled = null;
|
|
415
|
+
}
|
|
416
|
+
if (this.#view)
|
|
417
|
+
this.update(this.#view.state);
|
|
418
|
+
}
|
|
419
|
+
#announce(message) {
|
|
420
|
+
// Clear then set on a timer: replacing identical text does not re-announce,
|
|
421
|
+
// and the delay coalesces a held shortcut into one utterance.
|
|
422
|
+
this.#live.textContent = '';
|
|
423
|
+
clearTimeout(this.#liveTimer);
|
|
424
|
+
this.#liveTimer = setTimeout(() => {
|
|
425
|
+
this.#live.textContent = message;
|
|
426
|
+
}, 60);
|
|
427
|
+
}
|
|
428
|
+
/* -------------------------------------------------------------- *
|
|
429
|
+
* Roving tabindex
|
|
430
|
+
* -------------------------------------------------------------- */
|
|
431
|
+
#refreshFocusables() {
|
|
432
|
+
this.#focusables = [...this.el.querySelectorAll('button.ol-btn')];
|
|
433
|
+
this.#rovingIndex = 0;
|
|
434
|
+
this.#applyRoving();
|
|
435
|
+
}
|
|
436
|
+
#applyRoving() {
|
|
437
|
+
this.#focusables.forEach((button, index) => {
|
|
438
|
+
button.tabIndex = index === this.#rovingIndex ? 0 : -1;
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
#moveRoving(delta) {
|
|
442
|
+
if (this.#focusables.length === 0)
|
|
443
|
+
return;
|
|
444
|
+
const count = this.#focusables.length;
|
|
445
|
+
this.#rovingIndex = (this.#rovingIndex + delta + count) % count;
|
|
446
|
+
this.#applyRoving();
|
|
447
|
+
this.#focusables[this.#rovingIndex]?.focus();
|
|
448
|
+
}
|
|
449
|
+
#setRoving(index) {
|
|
450
|
+
if (this.#focusables.length === 0)
|
|
451
|
+
return;
|
|
452
|
+
this.#rovingIndex = Math.max(0, Math.min(index, this.#focusables.length - 1));
|
|
453
|
+
this.#applyRoving();
|
|
454
|
+
this.#focusables[this.#rovingIndex]?.focus();
|
|
455
|
+
}
|
|
456
|
+
#onKeydown = (event) => {
|
|
457
|
+
// Escape works from anywhere in the toolbar, including from the select.
|
|
458
|
+
if (event.key === 'Escape') {
|
|
459
|
+
event.preventDefault();
|
|
460
|
+
this.returnFocusToContent();
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const target = event.target;
|
|
464
|
+
// Arrow roving applies ONLY to buttons. The native <select> owns its own
|
|
465
|
+
// key handling; hijacking Left/Right there would break value changing.
|
|
466
|
+
if (!target || target.tagName !== 'BUTTON')
|
|
467
|
+
return;
|
|
468
|
+
const index = this.#focusables.indexOf(target);
|
|
469
|
+
if (index >= 0)
|
|
470
|
+
this.#rovingIndex = index;
|
|
471
|
+
switch (event.key) {
|
|
472
|
+
case 'ArrowRight':
|
|
473
|
+
event.preventDefault();
|
|
474
|
+
this.#moveRoving(1);
|
|
475
|
+
break;
|
|
476
|
+
case 'ArrowLeft':
|
|
477
|
+
event.preventDefault();
|
|
478
|
+
this.#moveRoving(-1);
|
|
479
|
+
break;
|
|
480
|
+
case 'Home':
|
|
481
|
+
event.preventDefault();
|
|
482
|
+
this.#setRoving(0);
|
|
483
|
+
break;
|
|
484
|
+
case 'End':
|
|
485
|
+
event.preventDefault();
|
|
486
|
+
this.#setRoving(this.#focusables.length - 1);
|
|
487
|
+
break;
|
|
488
|
+
default:
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
/** Move focus into the toolbar. Bound to Alt+F10 by the host. */
|
|
493
|
+
focusToolbar() {
|
|
494
|
+
if (this.#focusables.length > 0) {
|
|
495
|
+
this.#applyRoving();
|
|
496
|
+
this.#focusables[this.#rovingIndex]?.focus();
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
// A toolbar that is only the block-type select has no roving buttons.
|
|
500
|
+
// The shortcut is still documented; swallowing it with nowhere to go
|
|
501
|
+
// would make a valid `toolbar` attribute a silent no-op.
|
|
502
|
+
this.#select?.focus();
|
|
503
|
+
}
|
|
504
|
+
/** Return focus and the prior selection to the editable region. */
|
|
505
|
+
returnFocusToContent() {
|
|
506
|
+
this.#view?.focus();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
//# sourceMappingURL=toolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../src/toolbar.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openleaf-editor/ui",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "OpenLeaf toolbar and UI primitives. Plain CSS, no framework, themeable by custom properties.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/PeytonNowlin/openleaf.git",
|
|
12
|
+
"directory": "packages/ui"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://peytonnowlin.github.io/openleaf/",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/PeytonNowlin/openleaf/issues"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./openleaf.css": "./dist/openleaf.css"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"prosemirror-state": "^1.4.3",
|
|
33
|
+
"prosemirror-view": "^1.37.0",
|
|
34
|
+
"@openleaf-editor/core": "0.1.0-beta.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc -p tsconfig.json && node scripts/emit-css.mjs"
|
|
38
|
+
}
|
|
39
|
+
}
|