@openleaf-editor/ui 0.1.0-beta.2 → 0.1.0-beta.3

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.
Files changed (78) hide show
  1. package/README.md +85 -0
  2. package/dist/block-type.d.ts +5 -0
  3. package/dist/block-type.d.ts.map +1 -0
  4. package/dist/block-type.js +133 -0
  5. package/dist/block-type.js.map +1 -0
  6. package/dist/content-css.d.ts +18 -0
  7. package/dist/content-css.d.ts.map +1 -1
  8. package/dist/content-css.js +231 -16
  9. package/dist/content-css.js.map +1 -1
  10. package/dist/css.d.ts +23 -0
  11. package/dist/css.d.ts.map +1 -0
  12. package/dist/css.js +813 -0
  13. package/dist/css.js.map +1 -0
  14. package/dist/dialog.d.ts +93 -0
  15. package/dist/dialog.d.ts.map +1 -1
  16. package/dist/dialog.js +414 -86
  17. package/dist/dialog.js.map +1 -1
  18. package/dist/floating.d.ts +4 -0
  19. package/dist/floating.d.ts.map +1 -1
  20. package/dist/floating.js +50 -2
  21. package/dist/floating.js.map +1 -1
  22. package/dist/help.d.ts +1 -1
  23. package/dist/help.d.ts.map +1 -1
  24. package/dist/help.js +29 -5
  25. package/dist/help.js.map +1 -1
  26. package/dist/i18n.d.ts +8 -0
  27. package/dist/i18n.d.ts.map +1 -1
  28. package/dist/i18n.js +32 -7
  29. package/dist/i18n.js.map +1 -1
  30. package/dist/icons.d.ts +7 -1
  31. package/dist/icons.d.ts.map +1 -1
  32. package/dist/icons.js +6 -2
  33. package/dist/icons.js.map +1 -1
  34. package/dist/index.d.ts +10 -8
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +8 -6
  37. package/dist/index.js.map +1 -1
  38. package/dist/items.d.ts +0 -1
  39. package/dist/items.d.ts.map +1 -1
  40. package/dist/items.js +226 -20
  41. package/dist/items.js.map +1 -1
  42. package/dist/live.d.ts +42 -0
  43. package/dist/live.d.ts.map +1 -0
  44. package/dist/live.js +83 -0
  45. package/dist/live.js.map +1 -0
  46. package/dist/menu.d.ts +31 -2
  47. package/dist/menu.d.ts.map +1 -1
  48. package/dist/menu.js +163 -23
  49. package/dist/menu.js.map +1 -1
  50. package/dist/openleaf.css +114 -12
  51. package/dist/overflow.d.ts +31 -4
  52. package/dist/overflow.d.ts.map +1 -1
  53. package/dist/overflow.js +267 -82
  54. package/dist/overflow.js.map +1 -1
  55. package/dist/registry.d.ts +72 -18
  56. package/dist/registry.d.ts.map +1 -1
  57. package/dist/registry.js +7 -6
  58. package/dist/registry.js.map +1 -1
  59. package/dist/skins.d.ts.map +1 -1
  60. package/dist/skins.js +48 -14
  61. package/dist/skins.js.map +1 -1
  62. package/dist/styles.d.ts +61 -1
  63. package/dist/styles.d.ts.map +1 -1
  64. package/dist/styles.js +77 -637
  65. package/dist/styles.js.map +1 -1
  66. package/dist/testing.d.ts +3 -0
  67. package/dist/testing.d.ts.map +1 -0
  68. package/dist/testing.js +3 -0
  69. package/dist/testing.js.map +1 -0
  70. package/dist/toolbar.d.ts +71 -12
  71. package/dist/toolbar.d.ts.map +1 -1
  72. package/dist/toolbar.js +410 -166
  73. package/dist/toolbar.js.map +1 -1
  74. package/dist/upload.d.ts +11 -0
  75. package/dist/upload.d.ts.map +1 -1
  76. package/dist/upload.js +15 -1
  77. package/dist/upload.js.map +1 -1
  78. package/package.json +17 -3
@@ -1 +1 @@
1
- {"version":3,"file":"overflow.d.ts","sourceRoot":"","sources":["../src/overflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,qBAAa,eAAe;;gBAOd,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ;IAmClE,QAAQ,IAAI,IAAI;IAKhB,OAAO,IAAI,IAAI;IAQf,MAAM,IAAI,IAAI;CA6Ef"}
1
+ {"version":3,"file":"overflow.d.ts","sourceRoot":"","sources":["../src/overflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAUH,qBAAa,eAAe;;gBAiBd,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI;IA+CzF,kEAAkE;IAClE,QAAQ,IAAI,IAAI;IA6BhB,OAAO,IAAI,IAAI;IAcf,MAAM,IAAI,IAAI;CAyLf"}
package/dist/overflow.js CHANGED
@@ -1,135 +1,320 @@
1
1
  /**
2
- * Collapse overflowing toolbar groups into a "More" menu.
2
+ * Collapse overflowing toolbar groups into a "More" panel.
3
3
  *
4
4
  * Wrapping is the default for a reason: a control that moved behind a click is
5
5
  * a control the author does not have. Overflow is therefore opt-in. When it is
6
- * on, groups that do not fit the current width are hidden in the bar and
7
- * offered in a menu at the end, so a narrow CMS sidebar still has every item
6
+ * on, groups that do not fit the current width are moved out of the bar and
7
+ * offered in a panel at the end, so a narrow CMS sidebar still has every item
8
8
  * without a two-row bar.
9
+ *
10
+ * ## Why the real controls move rather than being cloned
11
+ *
12
+ * The first implementation cloned each control into a `role="menu"`. Cloning a
13
+ * live control produces a listener-free copy that has to forward every
14
+ * interaction back to an original it can only find by id, duplicates that id
15
+ * and the accessible name, and goes stale the moment the caret moves -- three
16
+ * bugs that only exist because there were two of everything. Moving the group
17
+ * node itself has none of them: the control in the panel IS the control, so it
18
+ * carries its own listeners, its own state and its own accessible name, and
19
+ * nothing can drift.
20
+ *
21
+ * ## The keyboard pattern
22
+ *
23
+ * The panel is a vertical `role="toolbar"`, not a `role="menu"`: a menu owns a
24
+ * content model of `menuitem` children, and a `<select>` is not one -- the
25
+ * default bar has four. So the panel is the same widget as the bar it came
26
+ * from, turned ninety degrees, and it keeps the same contract: one tab stop,
27
+ * arrow keys to move, Home/End to the ends, Escape back to the trigger. Tab
28
+ * closes, because a panel a keyboard user can walk out of and leave open is the
29
+ * failure mode of every hand-rolled popup.
30
+ *
31
+ * Up/Down are taken from a `<select>` inside the panel the same way Left/Right
32
+ * are taken from one in the bar; Alt+Down still opens its list, and typeahead
33
+ * still selects. Home/End are left to the select, which uses them for its own
34
+ * first and last option.
9
35
  */
10
36
  import { t } from './i18n.js';
11
37
  import { iconElement } from './icons.js';
38
+ /** Focusable controls, matching what the toolbar's own roving walks. */
39
+ const FOCUSABLE = 'button.ol-btn, select.ol-select';
40
+ let panelCounter = 0;
12
41
  export class ToolbarOverflow {
13
42
  #toolbar;
14
43
  #host;
44
+ #doc;
15
45
  #more;
16
- #menu;
46
+ #panel;
17
47
  #observer = null;
18
- constructor(toolbar, host, doc) {
48
+ #onLayout;
49
+ /**
50
+ * A pending coalesced layout.
51
+ *
52
+ * A ResizeObserver fires once per observed element, so a ten-group bar paid
53
+ * for ten layouts in one frame. One rAF collapses them, and the frame is
54
+ * cancelled on destroy so a queued layout cannot run against a torn-down bar.
55
+ */
56
+ #frame = null;
57
+ constructor(toolbar, host, doc, onLayout) {
19
58
  this.#toolbar = toolbar;
20
59
  this.#host = host;
60
+ this.#doc = doc;
61
+ this.#onLayout = onLayout;
21
62
  toolbar.classList.add('ol-toolbar--overflow');
63
+ this.#panel = doc.createElement('div');
64
+ this.#panel.className = 'ol-menu ol-overflow-menu';
65
+ this.#panel.id = `ol-overflow-${(panelCounter += 1)}`;
66
+ this.#panel.setAttribute('role', 'toolbar');
67
+ this.#panel.setAttribute('aria-orientation', 'vertical');
68
+ this.#panel.setAttribute('aria-label', t('More formatting'));
69
+ this.#panel.hidden = true;
70
+ this.#panel.addEventListener('keydown', this.#onKeydown);
22
71
  this.#more = doc.createElement('button');
23
72
  this.#more.type = 'button';
24
73
  this.#more.className = 'ol-btn ol-overflow-more';
25
74
  this.#more.setAttribute('aria-label', t('More'));
26
- this.#more.setAttribute('aria-haspopup', 'true');
75
+ // Not `aria-haspopup`: none of its values describes a toolbar, and "true"
76
+ // means menu, which is what this deliberately is not. Expanded plus a
77
+ // pointer at the panel is the honest relationship.
27
78
  this.#more.setAttribute('aria-expanded', 'false');
79
+ this.#more.setAttribute('aria-controls', this.#panel.id);
28
80
  this.#more.hidden = true;
29
81
  this.#more.appendChild(iconElement('more', doc));
30
- this.#menu = doc.createElement('div');
31
- this.#menu.className = 'ol-menu ol-overflow-menu';
32
- this.#menu.setAttribute('role', 'menu');
33
- this.#menu.hidden = true;
82
+ this.#more.addEventListener('mousedown', (event) => event.preventDefault());
34
83
  this.#more.addEventListener('click', () => {
35
- const open = this.#menu.hidden;
36
- this.#menu.hidden = !open;
37
- this.#more.setAttribute('aria-expanded', open ? 'true' : 'false');
84
+ if (this.#panel.hidden)
85
+ this.#open();
86
+ else
87
+ this.#close(true);
38
88
  });
39
- host.appendChild(this.#menu);
89
+ // Immediately after the bar, never at the end of the editor: appended to the
90
+ // host it landed after the editable region, so Tab from More walked into the
91
+ // content and the panel could only be reached by going backwards.
92
+ if (toolbar.parentNode)
93
+ toolbar.after(this.#panel);
94
+ else
95
+ host.appendChild(this.#panel);
40
96
  toolbar.appendChild(this.#more);
41
97
  if (typeof ResizeObserver !== 'undefined') {
42
- this.#observer = new ResizeObserver(() => this.layout());
98
+ this.#observer = new ResizeObserver(() => this.#schedule());
43
99
  this.#observer.observe(toolbar);
44
100
  }
45
101
  this.layout();
46
102
  }
103
+ /** Re-home the trigger after the toolbar rebuilt its children. */
47
104
  reattach() {
105
+ // The groups in the panel belong to the render that was just thrown away.
106
+ // Restoring them would put two of every control in the bar.
107
+ this.#panel.replaceChildren();
48
108
  if (!this.#more.isConnected)
49
109
  this.#toolbar.appendChild(this.#more);
50
110
  this.layout();
51
111
  }
112
+ /**
113
+ * Coalesce resize notifications into one layout per frame.
114
+ *
115
+ * The observer watches the very element `layout` resizes, so an unthrottled
116
+ * callback fed itself: hiding a group changes the bar's size, which notifies
117
+ * the observer, which lays out again. A frame is the right budget for work
118
+ * whose only purpose is deciding what the next paint shows.
119
+ */
120
+ #schedule() {
121
+ if (this.#frame !== null)
122
+ return;
123
+ const win = this.#toolbar.ownerDocument.defaultView;
124
+ if (!win?.requestAnimationFrame) {
125
+ this.layout();
126
+ return;
127
+ }
128
+ this.#frame = win.requestAnimationFrame(() => {
129
+ this.#frame = null;
130
+ this.layout();
131
+ });
132
+ }
52
133
  destroy() {
134
+ // A queued frame outlives destroy() and would lay out a torn-down bar.
135
+ if (this.#frame !== null) {
136
+ this.#toolbar.ownerDocument.defaultView?.cancelAnimationFrame(this.#frame);
137
+ this.#frame = null;
138
+ }
53
139
  this.#observer?.disconnect();
140
+ this.#close();
141
+ this.#restore();
54
142
  this.#more.remove();
55
- this.#menu.remove();
143
+ this.#panel.remove();
56
144
  this.#toolbar.classList.remove('ol-toolbar--overflow');
57
- for (const group of this.#groups())
58
- group.hidden = false;
59
145
  }
60
146
  layout() {
61
- const groups = this.#groups();
62
- for (const group of groups)
63
- group.hidden = false;
64
- this.#more.hidden = true;
65
- this.#menu.hidden = true;
66
- this.#menu.replaceChildren();
147
+ this.#restore();
148
+ // Revealed BEFORE the reads, not after the compute. The trigger takes a
149
+ // width and a gap in the row the moment it is shown, and it cannot be
150
+ // measured while hidden -- `display: none` reports 0. Showing it here means
151
+ // its footprint is inside the same `scrollWidth` as everything else, so the
152
+ // arithmetic needs no second measurement and no second layout pass.
153
+ //
154
+ // Measured every time rather than cached: the width follows
155
+ // `--openleaf-button-size`, which a skin or an integrator token changes at
156
+ // runtime (compact is 28px, the default 32px, coarse-pointer 40px), so a
157
+ // value pinned at first layout goes quietly wrong on the next density
158
+ // change.
159
+ this.#more.hidden = false;
160
+ this.#close();
161
+ // READ. Every measurement is taken here, while the bar is fully expanded,
162
+ // because a width read after a style write forces the browser to lay the
163
+ // whole bar out again. The old loop alternated the two once per group, so a
164
+ // ten-group bar paid for ten layouts -- from a ResizeObserver watching the
165
+ // element it was resizing.
67
166
  const budget = this.#toolbar.clientWidth;
68
- if (budget === 0)
167
+ const groups = this.#groups();
168
+ const total = this.#toolbar.scrollWidth;
169
+ const widths = groups.map((group) => group.offsetWidth);
170
+ const moreWidth = this.#more.offsetWidth;
171
+ const gap = Number.parseFloat(this.#toolbar.ownerDocument.defaultView?.getComputedStyle(this.#toolbar).columnGap ?? '') || 0;
172
+ if (budget === 0) {
173
+ this.#more.hidden = true;
69
174
  return;
70
- const overflowing = [];
71
- for (let i = groups.length - 1; i >= 0; i -= 1) {
72
- const fits = this.#toolbar.scrollWidth <= budget + 1;
73
- if (fits)
74
- break;
75
- const group = groups[i];
76
- if (!group)
77
- break;
78
- group.hidden = true;
79
- overflowing.unshift(group);
80
175
  }
81
- if (overflowing.length === 0)
176
+ // COMPUTE. In overflow mode the bar is a nowrap flex row with one uniform
177
+ // gap, so moving the last k groups out takes exactly their widths and k
178
+ // gaps off the scroll width. Nothing has to be re-measured between them.
179
+ //
180
+ // The trigger's footprint has to come back OUT to answer "does this bar
181
+ // overflow at all", because a bar that fits never shows one -- and charging
182
+ // it for a button it will not show would collapse a group for nothing.
183
+ const trigger = moreWidth > 0 ? moreWidth + gap : 0;
184
+ if (total - trigger <= budget + 1) {
185
+ this.#more.hidden = true;
82
186
  return;
83
- this.#more.hidden = false;
84
- for (const group of overflowing) {
85
- for (const control of group.querySelectorAll('[aria-label], select')) {
86
- const item = control.cloneNode(true);
87
- item.removeAttribute('tabindex');
88
- // cloneNode copies the option elements but not the select's current
89
- // value, which the toolbar sets as a property rather than an attribute.
90
- // Without this the menu opens showing the first option instead of the
91
- // block the caret is actually in.
92
- if (control instanceof HTMLSelectElement && item instanceof HTMLSelectElement) {
93
- item.value = control.value;
94
- }
95
- this.#menu.appendChild(item);
96
- }
97
187
  }
98
- // Cloning controls duplicates listener-less buttons. Activation on a clone is
99
- // forwarded to the original, which still owns the command.
100
- this.#menu.onclick = (event) => {
101
- const target = event.target;
102
- // A <select> is driven by `change`, not `click`. Forwarding a click here
103
- // fired before any option was chosen and carried no value with it.
104
- if (target?.closest('select'))
105
- return;
106
- const clone = target?.closest('[data-ol-id]');
107
- if (!clone)
108
- return;
109
- const original = this.#toolbar.querySelector(`[data-ol-id="${clone.dataset['olId']}"]`);
110
- original?.click();
111
- this.#close();
112
- };
113
- // The clone has no listeners of its own, so a chosen value has to be written
114
- // onto the real control and announced there. Clicking the original was the
115
- // previous behaviour and never carried the value, so headings and custom
116
- // formats could not be applied from the overflow menu at all.
117
- this.#menu.onchange = (event) => {
118
- const clone = event.target;
119
- if (!(clone instanceof HTMLSelectElement))
120
- return;
121
- const original = this.#toolbar.querySelector('select');
122
- if (!original)
123
- return;
124
- original.value = clone.value;
125
- original.dispatchEvent(new Event('change', { bubbles: true }));
126
- this.#close();
127
- };
188
+ // Past here the trigger stays, so `total` -- which already includes it -- is
189
+ // the right starting point. Leaving it out is what let a bar stay
190
+ // overflowing by roughly the width of the More button: the groups fit, then
191
+ // revealing the trigger pushed the row back over its budget, and it
192
+ // converged only on the next ResizeObserver pass, with a visible flash in
193
+ // between.
194
+ let used = total;
195
+ let count = 0;
196
+ while (used > budget + 1 && count < groups.length) {
197
+ used -= (widths[groups.length - 1 - count] ?? 0) + gap;
198
+ count += 1;
199
+ }
200
+ if (count === 0) {
201
+ this.#more.hidden = true;
202
+ return;
203
+ }
204
+ // WRITE. Backwards, inserted at the front, so the panel keeps the bar's
205
+ // order. The controls themselves move -- they are not cloned -- which is
206
+ // what makes the panel operable rather than a picture of the bar.
207
+ for (let i = groups.length - 1; i >= groups.length - count; i -= 1) {
208
+ const group = groups[i];
209
+ if (group)
210
+ this.#panel.insertBefore(group, this.#panel.firstChild);
211
+ }
212
+ // The trigger is already visible -- revealed before the reads, above. And
213
+ // there are no separator elements to hide: the divider is a border on the
214
+ // group, so a group that moved into the panel takes its own rule with it
215
+ // and cannot leave one stranded at the end of the bar.
216
+ this.#onLayout?.();
128
217
  void this.#host;
129
218
  }
130
- #close() {
131
- this.#menu.hidden = true;
219
+ /* -------------------------------------------------------------- *
220
+ * Open, close, and the keyboard
221
+ * -------------------------------------------------------------- */
222
+ #open() {
223
+ this.#panel.hidden = false;
224
+ this.#more.setAttribute('aria-expanded', 'true');
225
+ this.#position();
226
+ this.#doc.addEventListener('pointerdown', this.#onPointerDown, true);
227
+ this.#doc.defaultView?.addEventListener('scroll', this.#onViewportChange, true);
228
+ this.#doc.defaultView?.addEventListener('resize', this.#onViewportChange);
229
+ this.#focus(0);
230
+ }
231
+ #close(returnFocus = false) {
232
+ if (this.#panel.hidden)
233
+ return;
234
+ this.#panel.hidden = true;
132
235
  this.#more.setAttribute('aria-expanded', 'false');
236
+ this.#doc.removeEventListener('pointerdown', this.#onPointerDown, true);
237
+ this.#doc.defaultView?.removeEventListener('scroll', this.#onViewportChange, true);
238
+ this.#doc.defaultView?.removeEventListener('resize', this.#onViewportChange);
239
+ if (returnFocus)
240
+ this.#more.focus();
241
+ }
242
+ /**
243
+ * Under the trigger, in viewport coordinates and clamped to it.
244
+ *
245
+ * Fixed rather than absolute because the bar may sit inside a host with
246
+ * `overflow: hidden`, which is the case the whole feature exists for.
247
+ */
248
+ #position() {
249
+ const rect = this.#more.getBoundingClientRect();
250
+ const box = this.#panel.getBoundingClientRect();
251
+ const view = this.#doc.defaultView;
252
+ const width = view?.innerWidth ?? 0;
253
+ const height = view?.innerHeight ?? 0;
254
+ const below = rect.bottom + 4;
255
+ const top = below + box.height > height ? Math.max(4, rect.top - box.height - 4) : below;
256
+ this.#panel.style.position = 'fixed';
257
+ this.#panel.style.left = `${Math.round(Math.max(4, Math.min(rect.left, width - box.width - 4)))}px`;
258
+ this.#panel.style.top = `${Math.round(top)}px`;
259
+ }
260
+ #focusables() {
261
+ return [...this.#panel.querySelectorAll(FOCUSABLE)];
262
+ }
263
+ #focus(index) {
264
+ const items = this.#focusables();
265
+ if (items.length === 0)
266
+ return;
267
+ const next = items[(index + items.length) % items.length];
268
+ for (const item of items)
269
+ item.tabIndex = item === next ? 0 : -1;
270
+ next?.focus();
271
+ }
272
+ #onKeydown = (event) => {
273
+ const target = event.target;
274
+ if (event.key === 'Escape' || event.key === 'Tab') {
275
+ event.preventDefault();
276
+ this.#close(true);
277
+ return;
278
+ }
279
+ const items = this.#focusables();
280
+ const index = items.indexOf(target);
281
+ if (index < 0)
282
+ return;
283
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
284
+ // Alt+Down is how a keyboard user opens a native select's list.
285
+ if (event.altKey)
286
+ return;
287
+ event.preventDefault();
288
+ this.#focus(index + (event.key === 'ArrowDown' ? 1 : -1));
289
+ return;
290
+ }
291
+ if (event.key === 'Home' || event.key === 'End') {
292
+ // Left to the select, which uses them for its own first and last option.
293
+ if (target?.tagName === 'SELECT')
294
+ return;
295
+ event.preventDefault();
296
+ this.#focus(event.key === 'Home' ? 0 : items.length - 1);
297
+ }
298
+ };
299
+ #onPointerDown = (event) => {
300
+ const target = event.target;
301
+ if (!(target instanceof Node))
302
+ return;
303
+ if (this.#panel.contains(target) || this.#more.contains(target))
304
+ return;
305
+ this.#close();
306
+ };
307
+ #onViewportChange = () => this.#close();
308
+ /* -------------------------------------------------------------- *
309
+ * Moving groups back and forth
310
+ * -------------------------------------------------------------- */
311
+ #restore() {
312
+ for (const group of [...this.#panel.children])
313
+ this.#toolbar.appendChild(group);
314
+ // Overflow always takes a suffix of the groups, so appending in panel order
315
+ // puts them back where they were. The trigger stays last.
316
+ if (this.#more.isConnected)
317
+ this.#toolbar.appendChild(this.#more);
133
318
  }
134
319
  #groups() {
135
320
  return [...this.#toolbar.querySelectorAll(':scope > .ol-group')];
@@ -1 +1 @@
1
- {"version":3,"file":"overflow.js","sourceRoot":"","sources":["../src/overflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"overflow.js","sourceRoot":"","sources":["../src/overflow.ts"],"names":[],"mappings":"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"}
@@ -19,27 +19,42 @@
19
19
  import type { Command, EditorState } from 'prosemirror-state';
20
20
  import type { EditorView } from 'prosemirror-view';
21
21
  import type { IconName } from './icons.js';
22
+ import type { FormatSpec } from '@openleaf-editor/core';
22
23
  /** What a custom `run` handler receives. */
23
24
  export interface ToolbarContext {
24
25
  view: EditorView;
26
+ /**
27
+ * The id this item was registered under.
28
+ *
29
+ * A custom control must put it in `data-ol-id`, which is what the toolbar
30
+ * reads back to restore focus across a re-render. Every custom control in the
31
+ * tree wrote its human LABEL there instead, so focus restoration silently
32
+ * failed for all of them -- passing the id here is what makes getting it right
33
+ * the default rather than something each plugin has to remember.
34
+ */
35
+ id?: string;
25
36
  /** The `<openleaf-editor>` element, for dispatching events or hosting dialogs. */
26
37
  host: HTMLElement;
38
+ /** Extra host-defined block formats available to select controls. */
39
+ formats?: readonly FormatSpec[];
27
40
  }
28
41
  /**
29
42
  * A control a `custom` item builds for itself.
30
43
  *
31
44
  * The contract is narrow on purpose. A custom item owns its own markup, so it
32
45
  * can be a colour grid or a table-size picker, but it does not get to own the
33
- * toolbar's keyboard model: the element it returns must contain exactly one
34
- * focusable `button.ol-btn`, because that is what the roving tabindex walks. A
35
- * control with two focusable buttons in the bar would make the toolbar two tab
36
- * stops where the author expects one; a control with none would be unreachable
37
- * by keyboard. Anything else the control needs -- a popover, a grid of swatches
38
- * -- belongs outside the toolbar element, in the top layer or on the host.
46
+ * toolbar's keyboard model. Button-like custom controls participate in the
47
+ * roving tabindex through one `button.ol-btn`; select controls identify their
48
+ * native focus target with `focusable`. A control with two focusable elements
49
+ * in the bar would make the toolbar two tab stops where the author expects one.
50
+ * Anything else the control needs -- a popover, a grid of swatches -- belongs
51
+ * outside the toolbar element, in the top layer or on the host.
39
52
  */
40
53
  export interface ToolbarControl {
41
54
  /** The element placed in the toolbar. */
42
55
  el: HTMLElement;
56
+ /** Focus target when the control is not a standard toolbar button. */
57
+ focusable?: HTMLElement;
43
58
  /**
44
59
  * Reflect the editor state. Called on every transaction, so it must be cheap
45
60
  * and must not throw; a throw is caught and logged once, like a predicate.
@@ -48,6 +63,11 @@ export interface ToolbarControl {
48
63
  /** Release listeners, and remove anything the control put in the document. */
49
64
  destroy?: () => void;
50
65
  }
66
+ /** One choice in a `type: 'select'` toolbar item. */
67
+ export interface ToolbarSelectOption {
68
+ value: string;
69
+ label: string;
70
+ }
51
71
  export interface ToolbarItemSpec {
52
72
  /** Stable id used in the `toolbar` layout attribute. */
53
73
  id: string;
@@ -55,17 +75,22 @@ export interface ToolbarItemSpec {
55
75
  * What kind of control this is.
56
76
  *
57
77
  * `button` is the common case. `custom` hands the item a chance to build its
78
+ * own DOM through `render`, which is how the colour picker and block-type
79
+ * select exist without id-specific branches in the toolbar.
80
+ *
81
+ * `select` and `custom` both build through `render`; the distinct name keeps
82
+ * the public declaration honest about the control users will receive.
58
83
  * own DOM through `render`, which is how the colour picker exists at all: a
59
84
  * swatch grid is not a button, and modelling it as one would have meant
60
- * special-casing it in the toolbar by id, the way the block-type `select`
61
- * still is.
85
+ * special-casing it in the toolbar by id.
62
86
  *
63
- * `select` remains unimplemented, and the block-type control is special-cased
64
- * by id rather than being one. Declaring it logs a warning rather than
65
- * rendering a plausible-looking button that is not the control asked for.
87
+ * `select` builds a native `<select>` from `options` / `getValue` /
88
+ * `applyValue`. The block-type control stays special-cased by id because it
89
+ * owns formats the host injects at mount time; everything else that is a
90
+ * preset list (font family, size, line height) uses this type.
66
91
  */
67
92
  type?: 'button' | 'select' | 'custom';
68
- /** Accessible name. Kept constant across states -- the platform announces pressed. */
93
+ /** Accessible name. Use `labelFor` when the same control does insert versus edit. */
69
94
  label: string;
70
95
  icon?: IconName;
71
96
  /**
@@ -78,10 +103,38 @@ export interface ToolbarItemSpec {
78
103
  /** For items needing more than the editor state -- dialogs, mode switches. */
79
104
  run?: (ctx: ToolbarContext) => void;
80
105
  /**
81
- * For `type: 'custom'`: build the control. Required for that type, ignored
82
- * otherwise.
106
+ * For `type: 'custom'` or `type: 'select'`: build the control.
83
107
  */
84
108
  render?: (ctx: ToolbarContext) => ToolbarControl;
109
+ /**
110
+ * For `type: 'select'`: the choices shown. Required for that type. An empty
111
+ * `value` is the "Default" / clear option.
112
+ */
113
+ options?: readonly ToolbarSelectOption[];
114
+ /**
115
+ * For `type: 'select'`: the value that matches the selection. Empty string
116
+ * means no explicit formatting (the Default option).
117
+ */
118
+ getValue?: (state: EditorState) => string;
119
+ /**
120
+ * For `type: 'select'`: turn a chosen value into a command. Empty string
121
+ * clears.
122
+ */
123
+ applyValue?: (value: string) => Command;
124
+ /**
125
+ * Optional CSS modifier for a select (e.g. `wide` for long font names).
126
+ * Becomes `ol-select--{mod}` on the element.
127
+ */
128
+ selectMod?: string;
129
+ /**
130
+ * Accessible name that depends on the selection.
131
+ *
132
+ * `label` stays the default. Use this when the same control does two
133
+ * different things -- insert versus edit -- so the name can say which.
134
+ * Do not use it to bake "pressed" into a toggle; the platform already
135
+ * announces that.
136
+ */
137
+ labelFor?: (state: EditorState) => string;
85
138
  isActive?: (state: EditorState) => boolean;
86
139
  /** Defaults to asking `command` whether it would apply. */
87
140
  isEnabled?: (state: EditorState) => boolean;
@@ -104,10 +157,11 @@ export declare function clearToolbarItems(): void;
104
157
  * Order reasoning: history sits leftmost because it is the control an author
105
158
  * reaches for under stress and muscle memory puts it at the start of the bar in
106
159
  * every office application. Block type comes next because choosing what a
107
- * paragraph *is* precedes decorating it. Then character marks, then block
108
- * structure, then insertions, and finally source view -- the one control that
109
- * changes the editor's mode rather than the document, kept away from the rest
110
- * so it is not hit by accident.
160
+ * paragraph *is* precedes decorating it. Font family, size and line height sit
161
+ * beside it as the next layer of look. Then character marks, alignment, indent,
162
+ * lists, insertions, and finally source view -- the one control that changes
163
+ * the editor's mode rather than the document, kept away from the rest so it is
164
+ * not hit by accident.
111
165
  */
112
166
  export declare const DEFAULT_LAYOUT: string;
113
167
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAA;IAChB,kFAAkF;IAClF,IAAI,EAAE,WAAW,CAAA;CAClB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,EAAE,EAAE,WAAW,CAAA;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;IACrC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAA;IACV;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACrC,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC1B,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAA;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,cAAc,CAAA;IAChD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;IAC1C,2DAA2D;IAC3D,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;IAC3C,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAcD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAGjE;AAcD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAG/D;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEtE;AAED,wBAAgB,eAAe,IAAI,eAAe,EAAE,CAEnD;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,QAGgE,CAAA;AAE3F;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,QAG9B,CAAA"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}