vintage-frames 0.18.0 → 0.19.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.
Files changed (47) hide show
  1. package/README.md +1 -1
  2. package/custom-elements.json +278 -51
  3. package/dist/build/app-file.d.ts +2 -2
  4. package/dist/build/app-file.js +1 -0
  5. package/dist/build/plugins.d.ts +2 -2
  6. package/dist/build/plugins.js +62 -59
  7. package/dist/components/vf-icon.d.ts +7 -0
  8. package/dist/components/vf-icon.js +101 -81
  9. package/dist/components/vf-menu-bar.d.ts +6 -4
  10. package/dist/components/vf-menu-bar.js +26 -56
  11. package/dist/components/vf-menu-item.d.ts +33 -5
  12. package/dist/components/vf-menu-item.js +128 -61
  13. package/dist/components/vf-menu.d.ts +35 -0
  14. package/dist/components/vf-menu.js +171 -111
  15. package/dist/glyphs.d.ts +6 -0
  16. package/dist/glyphs.js +18 -14
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +15 -14
  19. package/dist/menu-navigation.d.ts +34 -0
  20. package/dist/menu-navigation.js +53 -0
  21. package/dist/menu-press.d.ts +25 -7
  22. package/dist/menu-press.js +78 -44
  23. package/dist/motion.d.ts +10 -0
  24. package/dist/shell/app-file.d.ts +20 -4
  25. package/dist/shell/app-file.js +65 -53
  26. package/dist/shell/catalog.d.ts +79 -1
  27. package/dist/shell/catalog.js +206 -153
  28. package/dist/shell/finder.d.ts +28 -9
  29. package/dist/shell/finder.js +339 -267
  30. package/dist/shell/geometry.d.ts +7 -0
  31. package/dist/shell/geometry.js +19 -3
  32. package/dist/shell/index.d.ts +4 -4
  33. package/dist/shell/index.js +12 -12
  34. package/dist/shell/pure.d.ts +1 -1
  35. package/dist/shell/pure.js +6 -6
  36. package/dist/shell/shell.d.ts +14 -10
  37. package/dist/shell/shell.js +148 -116
  38. package/dist/shell/version.d.ts +1 -1
  39. package/dist/shell/version.js +1 -1
  40. package/dist/styles/body-italic-font.d.ts +2 -0
  41. package/dist/styles/body-italic-font.js +10 -0
  42. package/dist/styles/register-embedded-font.d.ts +5 -4
  43. package/dist/styles/register-embedded-font.js +11 -10
  44. package/docs/SPEC.md +11 -7
  45. package/editor/vscode.html-custom-data.json +15 -5
  46. package/editor/web-types.json +55 -9
  47. package/package.json +7 -3
@@ -1,33 +1,48 @@
1
1
  import { deferActivation as e, emit as t } from "../events.js";
2
2
  import { vfElement as n } from "../define.js";
3
- import { ScaleController as r } from "../scale.js";
4
- import i from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
5
- import { VfPositioned as a } from "../position.js";
6
- import { vfDisplay as o } from "../styles/recipes/display-face.js";
7
- import { vfBase as s } from "../styles/recipes/host.js";
8
- import { vfPanel as c } from "../styles/recipes/surface.js";
9
- import { vfFocusUnderline as l } from "../styles/recipes/focus.js";
10
- import { GridSnapController as u } from "../grid-snap.js";
11
- import { DocumentListenersController as d, releaseAfterGesture as f } from "../document-listeners.js";
12
- import { runSelectionBlink as p } from "../motion.js";
13
- import { FocusRuleController as m } from "../focus-modality.js";
14
- import { TypeAheadBuffer as h } from "../type-ahead.js";
15
- import { MenuPressController as g } from "../menu-press.js";
16
- import { LitElement as _, css as v, html as y, nothing as b } from "lit";
17
- import { property as x, query as S, queryAssignedElements as C, state as w } from "lit/decorators.js";
3
+ import { ScaleController as r, sys as i } from "../scale.js";
4
+ import a from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
5
+ import { VfPositioned as o } from "../position.js";
6
+ import { vfDisplay as s } from "../styles/recipes/display-face.js";
7
+ import { vfBase as c } from "../styles/recipes/host.js";
8
+ import { vfPanel as l } from "../styles/recipes/surface.js";
9
+ import { vfFocusUnderline as u } from "../styles/recipes/focus.js";
10
+ import { GridSnapController as d } from "../grid-snap.js";
11
+ import { DocumentListenersController as f, releaseAfterGesture as p } from "../document-listeners.js";
12
+ import { runSelectionBlink as m } from "../motion.js";
13
+ import { FocusRuleController as h } from "../focus-modality.js";
14
+ import { TypeAheadBuffer as g } from "../type-ahead.js";
15
+ import { navigateMenus as _ } from "../menu-navigation.js";
16
+ import { MenuPressController as v } from "../menu-press.js";
17
+ import { LitElement as y, css as b, html as x, nothing as S } from "lit";
18
+ import { property as C, query as w, queryAssignedElements as T, state as E } from "lit/decorators.js";
18
19
  //#region src/components/vf-menu.ts
19
- var T = /* @__PURE__ */ new Set([
20
+ var D = /* @__PURE__ */ new Set([
20
21
  "vf-img",
21
22
  "img",
22
23
  "svg",
23
24
  "picture",
24
25
  "canvas"
25
- ]), E = class extends a(_) {
26
+ ]);
27
+ function O(e) {
28
+ let t = document.documentElement, n = 0, r = 0, a = t.clientWidth, o = t.clientHeight, s = e.closest("vf-desktop");
29
+ if (s) {
30
+ let t = (s.shadowRoot?.querySelector(".screen") ?? s).getBoundingClientRect();
31
+ n = Math.max(n, t.left), r = Math.max(r, t.top + i(s.workArea.top, e)), a = Math.min(a, t.right), o = Math.min(o, t.bottom);
32
+ }
33
+ return {
34
+ left: n,
35
+ top: r,
36
+ right: a,
37
+ bottom: o
38
+ };
39
+ }
40
+ var k = class extends o(y) {
26
41
  constructor(...e) {
27
- super(...e), this.scale = new r(this), this.gridSnap = new u(this), this.#e = new m(this), this.label = "", this.open = !1, this.shortcuts = !1, this.barTabIndex = 0, this._artTitle = !1, this.#t = (e) => {
42
+ super(...e), this.scale = new r(this), this.gridSnap = new d(this), this.#e = new h(this), this.label = "", this.open = !1, this.shortcuts = !1, this.barTabIndex = 0, this._artTitle = !1, this.#t = (e) => {
28
43
  let t = e.target.assignedElements();
29
- this._artTitle = t.length > 0 && t.every((e) => T.has(e.localName));
30
- }, this.#n = new g(this, {
44
+ this._artTitle = t.length > 0 && t.every((e) => D.has(e.localName));
45
+ }, this.#n = new v(this, {
31
46
  menus: () => [this],
32
47
  open: (e) => {
33
48
  e.open = !0;
@@ -35,70 +50,48 @@ var T = /* @__PURE__ */ new Set([
35
50
  close: () => {
36
51
  this.open = !1;
37
52
  }
38
- }), this.#i = this.attachInternals(), this.#a = new h(), this.#o = !1, this.#s = () => {
39
- this.#r || this.focus(), this.open = !1;
40
- }, this._flashOn = !1, this.#l = () => {
41
- this.open || (this.#u(), this.#c = p((e) => {
53
+ }), this.#a = null, this.#o = void 0, this.#s = "right", this.#u = this.attachInternals(), this.#d = new g(), this.#f = !1, this.#p = () => {
54
+ this.#i || (this.#r || this.focus(), this.open = !1);
55
+ }, this._flashOn = !1, this.#h = () => {
56
+ this.open || this.#i || (this.#g(), this.#m = m((e) => {
42
57
  this._flashOn = e;
43
58
  }, () => {
44
- this._flashOn = !1, this.#c = void 0;
59
+ this._flashOn = !1, this.#m = void 0;
45
60
  }));
46
- }, this.#d = (e) => {
61
+ }, this.#_ = (e) => {
47
62
  e.composedPath().includes(this) || (this.open = !1);
48
- }, this.#f = (e) => {
49
- if (!e.defaultPrevented) switch (e.key) {
50
- case "Escape":
51
- e.preventDefault(), this.open = !1, this.focus();
52
- break;
53
- case "Tab":
54
- this.open = !1;
55
- break;
56
- case "ArrowDown":
57
- case "ArrowUp":
58
- e.preventDefault(), this.#p(e.key === "ArrowDown" ? 1 : -1);
59
- break;
60
- case "Home":
61
- case "End": {
62
- e.preventDefault();
63
- let t = this.items;
64
- t[e.key === "Home" ? 0 : t.length - 1]?.focus();
65
- break;
66
- }
67
- default: {
68
- if (e.key.length !== 1 || e.key === " " || e.metaKey || e.ctrlKey || e.altKey) break;
69
- e.preventDefault();
70
- let t = this.items, n = t.indexOf(document.activeElement);
71
- t[this.#a.feed(e.key, n, t.map((e) => ({
72
- text: e.textContent ?? "",
73
- disabled: !1
74
- })))]?.focus();
75
- break;
63
+ }, this.#v = (e) => {
64
+ _(e, {
65
+ menu: this,
66
+ typeAhead: this.#d,
67
+ close: (e) => {
68
+ e && this.focus(), this.open = !1;
76
69
  }
77
- }
78
- }, this.#m = new d(this, () => [[
70
+ });
71
+ }, this.#y = new f(this, () => [[
79
72
  document,
80
73
  "pointerdown",
81
- this.#d,
74
+ this.#_,
82
75
  !0
83
76
  ], [
84
77
  document,
85
78
  "keydown",
86
- this.#f,
79
+ this.#v,
87
80
  !0
88
- ]]), this.#g = (e) => {
89
- if (!this.open || this.#r) return;
81
+ ]]), this.#x = (e) => {
82
+ if (!this.open || this.#r || this.#i) return;
90
83
  let t = e.relatedTarget;
91
84
  t instanceof Node && (this.contains(t) || this.renderRoot.contains(t)) || (this.open = !1);
92
- }, this.#_ = (e) => {
93
- this.#e.suppress(), !this.#r && this.#n.onPointerDown(e);
85
+ }, this.#S = (e) => {
86
+ this.#e.suppress(), !(this.#r || this.#i) && this.#n.onPointerDown(e);
94
87
  };
95
88
  }
96
89
  static {
97
90
  this.styles = [
98
- s,
99
- o,
100
91
  c,
101
- v`
92
+ s,
93
+ l,
94
+ b`
102
95
  :host {
103
96
  display: inline-block;
104
97
  position: relative;
@@ -203,7 +196,7 @@ var T = /* @__PURE__ */ new Set([
203
196
  }
204
197
  :host(:not([open])) .label.vf-focus-rule .title::after {
205
198
  --vf-focus-underline-offset: -2px;
206
- ${l}
199
+ ${u}
207
200
  }
208
201
  .panel {
209
202
  position: absolute;
@@ -239,6 +232,29 @@ var T = /* @__PURE__ */ new Set([
239
232
  :host(:not([open])) .panel {
240
233
  display: none;
241
234
  }
235
+ /* A submenu: the host is a box as wide as its item's row at the row's
236
+ top (vf-menu-item's .submenu), and the panel hangs from it the way
237
+ System 7.5's did (traced from a 3× Infinite Mac capture): its top
238
+ frame the row above the item's, so its first row is level with the
239
+ item, and its left frame 5px left of the parent's right frame, which
240
+ is the row's right edge. It covers the parent's last 4px, its frame
241
+ and its shadow. Flipped (.left), the same in mirror: its right frame
242
+ 5px right of the parent's left frame, a px left of the row. --_lift
243
+ is the whole system px #place() raises it by to fit the screen. */
244
+ :host([slot='submenu']) {
245
+ display: block;
246
+ }
247
+ :host([slot='submenu']) .panel {
248
+ min-width: 0;
249
+ top: calc(
250
+ var(--vf-scale, 1) * (-1px - var(--_lift, 0) * 1px) + var(--vf-snap-dy, 0px)
251
+ );
252
+ left: calc(100% - var(--vf-scale, 1) * 5px + var(--vf-snap-dx, 0px));
253
+ }
254
+ :host([slot='submenu']) .panel.left {
255
+ left: auto;
256
+ right: calc(100% - var(--vf-scale, 1) * 5px - var(--vf-snap-dx, 0px));
257
+ }
242
258
  /* A divider is an ITEM: the MDEF gave "-" a full row, so a separator
243
259
  spends one whole --vf-menu-row-height, not a thin rule with token
244
260
  margins — Menus.png's File pulldown runs a 32px ink pitch across
@@ -270,41 +286,76 @@ var T = /* @__PURE__ */ new Set([
270
286
  get #r() {
271
287
  return this.closest("vf-menu-bar") !== null;
272
288
  }
273
- #i;
289
+ get #i() {
290
+ return this.slot === "submenu" && this.parentElement?.localName === "vf-menu-item";
291
+ }
292
+ get panelRect() {
293
+ return this.open ? this._panelEl?.getBoundingClientRect() ?? null : null;
294
+ }
274
295
  #a;
275
296
  #o;
276
297
  #s;
277
- #c;
278
- #l;
279
- #u() {
280
- this.#c?.cancel(), this.#c = void 0, this._flashOn = !1;
298
+ get expandedItem() {
299
+ return this.#a;
281
300
  }
301
+ expand(e, t = {}) {
302
+ if (!(e && (!this.open || e.disabled || !e.submenu || !this.allItems.includes(e)))) {
303
+ if (e !== this.#a) {
304
+ let t = this.#a;
305
+ if (this.#a = e, t) {
306
+ let e = t.submenu, n = this.getRootNode();
307
+ e && n.activeElement && e.contains(n.activeElement) && t.focus(), t.expanded = !1, e && (e.open = !1);
308
+ }
309
+ e && (e.expanded = !0, e.submenu.open = !0), this.#c();
310
+ }
311
+ e && t.focus && e.submenu.#O();
312
+ }
313
+ }
314
+ pointerOver(e) {
315
+ e !== this.#o && (this.#o = e, this.#c());
316
+ }
317
+ #c() {
318
+ let e = this.#o === void 0 ? this.#a : this.#o;
319
+ for (let t of this.allItems) t.active = t === e && !t.disabled;
320
+ }
321
+ #l() {
322
+ let e = this.parentElement, t = this._panelEl;
323
+ if (!e || !t) return;
324
+ let n = e.getBoundingClientRect(), r = t.getBoundingClientRect(), a = O(this), o = i(1, this), s = n.right - 5 * o + r.width + o <= a.right + .5, c = n.left + 5 * o - r.width >= a.left - .5, l = e.closest("vf-menu"), u = l ? l.#s : "right";
325
+ u === "right" && !s && c ? u = "left" : u === "left" && !c && s && (u = "right");
326
+ let d = n.top - o, f = d + r.height + o - a.bottom, p = Math.floor((d - a.top) / o + .01), m = Math.max(0, Math.min(Math.ceil(f / o - .01), p));
327
+ this.#s = u, t.classList.toggle("left", u === "left"), m > 0 ? t.style.setProperty("--_lift", String(m)) : t.style.removeProperty("--_lift");
328
+ }
329
+ #u;
282
330
  #d;
283
331
  #f;
284
- #p(e) {
285
- let t = this.items;
286
- if (t.length === 0) return;
287
- let n = t.indexOf(document.activeElement), r;
288
- r = n < 0 ? e === 1 ? 0 : t.length - 1 : (n + e + t.length) % t.length, t[r]?.focus();
289
- }
332
+ #p;
290
333
  #m;
334
+ #h;
335
+ #g() {
336
+ this.#m?.cancel(), this.#m = void 0, this._flashOn = !1;
337
+ }
338
+ #_;
339
+ #v;
340
+ #y;
291
341
  connectedCallback() {
292
- super.connectedCallback(), this.#h(), this.requestUpdate(), this.addEventListener("vf-menu-close-request", this.#s), this.addEventListener("vf-menu-flash-request", this.#l), this.addEventListener("pointerdown", this.#_), this.addEventListener("focusout", this.#g);
342
+ super.connectedCallback(), this.#b(), this.requestUpdate(), this.addEventListener("vf-menu-close-request", this.#p), this.addEventListener("vf-menu-flash-request", this.#h), this.addEventListener("pointerdown", this.#S), this.addEventListener("focusout", this.#x);
293
343
  }
294
- #h() {
295
- this.#i.role = this.#r ? "none" : null;
344
+ #b() {
345
+ this.#u.role = this.#r || this.#i ? "none" : null;
296
346
  }
297
347
  disconnectedCallback() {
298
- super.disconnectedCallback(), this.removeEventListener("vf-menu-close-request", this.#s), this.removeEventListener("vf-menu-flash-request", this.#l), this.removeEventListener("pointerdown", this.#_), this.removeEventListener("focusout", this.#g), this.#u();
348
+ super.disconnectedCallback(), this.removeEventListener("vf-menu-close-request", this.#p), this.removeEventListener("vf-menu-flash-request", this.#h), this.removeEventListener("pointerdown", this.#S), this.removeEventListener("focusout", this.#x), this.#g();
299
349
  }
300
- #g;
350
+ #x;
301
351
  updated(e) {
302
352
  if (e.has("open")) {
303
- if (this.open && this.#u(), this.open && !this.#r ? this.#m.attach() : this.#m.detach(), !this.open) for (let e of this.allItems) e.active = !1;
304
- this.open || this.#a.reset();
353
+ this.open && this.#g();
354
+ let e = !this.#r && !this.#i;
355
+ this.open && e ? this.#y.attach() : this.#y.detach(), e && this.#n.track(this.open), this.open ? this.#i && this.#l() : (this.expand(null), this.#o = void 0, this.#c(), this.#d.reset());
305
356
  }
306
357
  }
307
- #_;
358
+ #S;
308
359
  focus(e) {
309
360
  this._labelEl?.focus(e);
310
361
  }
@@ -312,7 +363,16 @@ var T = /* @__PURE__ */ new Set([
312
363
  this.focus();
313
364
  }
314
365
  render() {
315
- return y`
366
+ return this.#i ? x`
367
+ <div
368
+ class="panel vf-panel"
369
+ part="panel"
370
+ role="menu"
371
+ aria-label=${this.label || this.parentElement?.labelText || S}
372
+ >
373
+ <slot></slot>
374
+ </div>
375
+ ` : x`
316
376
  <div
317
377
  class="label vf-snap ${this.#e.marked ? "vf-focus-rule" : ""} ${this._flashOn ? "flash-on" : ""} ${this._artTitle ? "art" : ""}"
318
378
  part="label"
@@ -320,11 +380,11 @@ var T = /* @__PURE__ */ new Set([
320
380
  tabindex=${this.barTabIndex}
321
381
  aria-haspopup="menu"
322
382
  aria-expanded=${this.open ? "true" : "false"}
323
- aria-label=${this.label || b}
324
- @pointerdown=${this.#y}
325
- @click=${this.#b}
326
- @pointerenter=${this.#x}
327
- @keydown=${this.#S}
383
+ aria-label=${this.label || S}
384
+ @pointerdown=${this.#w}
385
+ @click=${this.#T}
386
+ @pointerenter=${this.#E}
387
+ @keydown=${this.#D}
328
388
  >
329
389
  <span class="title"
330
390
  ><slot name="label" @slotchange=${this.#t}>${this.label}</slot></span
@@ -334,13 +394,13 @@ var T = /* @__PURE__ */ new Set([
334
394
  class="panel vf-panel"
335
395
  part="panel"
336
396
  role="menu"
337
- aria-label=${this.label || b}
397
+ aria-label=${this.label || S}
338
398
  >
339
399
  <slot></slot>
340
400
  </div>
341
401
  `;
342
402
  }
343
- #v() {
403
+ #C() {
344
404
  if (!this.#r) {
345
405
  this.open = !this.open;
346
406
  return;
@@ -350,44 +410,44 @@ var T = /* @__PURE__ */ new Set([
350
410
  composed: !1
351
411
  }) && (this.open = !this.open);
352
412
  }
353
- #y() {
354
- this.#o = !0, f(() => {
355
- this.#o = !1;
413
+ #w() {
414
+ this.#f = !0, p(() => {
415
+ this.#f = !1;
356
416
  });
357
417
  }
358
- #b(t) {
359
- if (this.#o) {
360
- this.#o = !1;
418
+ #T(t) {
419
+ if (this.#f) {
420
+ this.#f = !1;
361
421
  return;
362
422
  }
363
- e(this, t, () => this.#v());
423
+ e(this, t, () => this.#C());
364
424
  }
365
- #x() {
425
+ #E() {
366
426
  t(this, "vf-menu-hover", { menu: this }, { composed: !1 });
367
427
  }
368
- #S(e) {
428
+ #D(e) {
369
429
  if (e.key === "Enter" || e.key === " ") {
370
430
  e.preventDefault();
371
431
  let t = this.open;
372
- this.#v(), !t && this.open && this.#C();
373
- } else e.key === "ArrowDown" && !this.open && (e.preventDefault(), this.#v(), this.open && this.#C());
432
+ this.#C(), !t && this.open && this.#O();
433
+ } else e.key === "ArrowDown" && !this.open && (e.preventDefault(), this.#C(), this.open && this.#O());
374
434
  }
375
- async #C() {
435
+ async #O() {
376
436
  await this.updateComplete, this.items[0]?.focus();
377
437
  }
378
438
  };
379
- i([x()], E.prototype, "label", void 0), i([x({
439
+ a([C()], k.prototype, "label", void 0), a([C({
380
440
  type: Boolean,
381
441
  reflect: !0
382
- })], E.prototype, "open", void 0), i([x({
442
+ })], k.prototype, "open", void 0), a([C({
383
443
  type: Boolean,
384
444
  reflect: !0
385
- })], E.prototype, "shortcuts", void 0), i([x({
445
+ })], k.prototype, "shortcuts", void 0), a([C({
386
446
  type: Number,
387
447
  attribute: !1
388
- })], E.prototype, "barTabIndex", void 0), i([S(".label")], E.prototype, "_labelEl", void 0), i([w()], E.prototype, "_artTitle", void 0), i([C({
448
+ })], k.prototype, "barTabIndex", void 0), a([w(".label")], k.prototype, "_labelEl", void 0), a([E()], k.prototype, "_artTitle", void 0), a([T({
389
449
  selector: "vf-menu-item",
390
450
  flatten: !0
391
- })], E.prototype, "_assignedItems", void 0), i([w()], E.prototype, "_flashOn", void 0), E = i([n("vf-menu")], E);
451
+ })], k.prototype, "_assignedItems", void 0), a([w(".panel")], k.prototype, "_panelEl", void 0), a([E()], k.prototype, "_flashOn", void 0), k = a([n("vf-menu")], k);
392
452
  //#endregion
393
- export { E as VfMenu };
453
+ export { k as VfMenu };
package/dist/glyphs.d.ts CHANGED
@@ -62,6 +62,12 @@ export declare const CARET_UP: Glyph;
62
62
  export declare const CARET_DOWN_SMALL: Glyph;
63
63
  /** {@link CARET_DOWN_SMALL} mirrored vertically: the small panel's top scroll arrow. */
64
64
  export declare const CARET_UP_SMALL: Glyph;
65
+ /**
66
+ * The ▶ at the end of a menu item that opens a submenu: {@link CARET_DOWN}
67
+ * turned on its side, 6×11. Traced from the submenu rows of `Menus.png`, and
68
+ * the same shape in a capture of a System 7.5 Apple menu (Infinite Mac, 3×).
69
+ */
70
+ export declare const CARET_RIGHT: Glyph;
65
71
  /**
66
72
  * The "little arrows" stepper at rest — a rounded 1-bit frame enclosing hollow
67
73
  * up/down arrows (`Little arrows.png`), used by `vf-number-field`.
package/dist/glyphs.js CHANGED
@@ -41,59 +41,63 @@ var t = {
41
41
  h: 5,
42
42
  d: "M4 0h1v1h-1zM3 1h3v1h-3zM2 2h5v1h-5zM1 3h7v1h-7zM0 4h9v1h-9z"
43
43
  }, d = {
44
+ w: 6,
45
+ h: 11,
46
+ d: "M0 0h1v1h-1zM0 1h2v1h-2zM0 2h3v1h-3zM0 3h4v1h-4zM0 4h5v1h-5zM0 5h6v1h-6zM0 6h5v1h-5zM0 7h4v1h-4zM0 8h3v1h-3zM0 9h2v1h-2zM0 10h1v1h-1z"
47
+ }, f = {
44
48
  w: 15,
45
49
  h: 25,
46
50
  d: "M2 0h11v1h-11zM1 1h1v1h-1zM13 1h1v1h-1zM0 2h1v1h-1zM14 2h1v1h-1zM0 3h1v1h-1zM7 3h1v1h-1zM14 3h1v1h-1zM0 4h1v1h-1zM6 4h1v1h-1zM8 4h1v1h-1zM14 4h1v1h-1zM0 5h1v1h-1zM5 5h1v1h-1zM9 5h1v1h-1zM14 5h1v1h-1zM0 6h1v1h-1zM4 6h1v1h-1zM10 6h1v1h-1zM14 6h1v1h-1zM0 7h1v1h-1zM3 7h3v1h-3zM9 7h3v1h-3zM14 7h1v1h-1zM0 8h1v1h-1zM5 8h1v1h-1zM9 8h1v1h-1zM14 8h1v1h-1zM0 9h1v1h-1zM5 9h1v1h-1zM9 9h1v1h-1zM14 9h1v1h-1zM0 10h1v1h-1zM5 10h5v1h-5zM14 10h1v1h-1zM0 11h1v1h-1zM14 11h1v1h-1zM0 12h1v1h-1zM14 12h1v1h-1zM0 13h1v1h-1zM14 13h1v1h-1zM0 14h1v1h-1zM5 14h5v1h-5zM14 14h1v1h-1zM0 15h1v1h-1zM5 15h1v1h-1zM9 15h1v1h-1zM14 15h1v1h-1zM0 16h1v1h-1zM5 16h1v1h-1zM9 16h1v1h-1zM14 16h1v1h-1zM0 17h1v1h-1zM3 17h3v1h-3zM9 17h3v1h-3zM14 17h1v1h-1zM0 18h1v1h-1zM4 18h1v1h-1zM10 18h1v1h-1zM14 18h1v1h-1zM0 19h1v1h-1zM5 19h1v1h-1zM9 19h1v1h-1zM14 19h1v1h-1zM0 20h1v1h-1zM6 20h1v1h-1zM8 20h1v1h-1zM14 20h1v1h-1zM0 21h1v1h-1zM7 21h1v1h-1zM14 21h1v1h-1zM0 22h1v1h-1zM14 22h1v1h-1zM1 23h1v1h-1zM13 23h1v1h-1zM2 24h11v1h-11z"
47
- }, f = {
51
+ }, p = {
48
52
  w: 11,
49
53
  h: 12,
50
54
  d: "M1 0h9v1h-9zM0 1h1v1h-1zM10 1h1v1h-1zM0 2h1v1h-1zM10 2h1v1h-1zM0 3h1v1h-1zM3 3h1v1h-1zM5 3h1v1h-1zM7 3h1v1h-1zM10 3h1v1h-1zM0 4h1v1h-1zM3 4h1v1h-1zM5 4h1v1h-1zM7 4h1v1h-1zM10 4h1v1h-1zM0 5h1v1h-1zM3 5h1v1h-1zM5 5h1v1h-1zM7 5h1v1h-1zM10 5h1v1h-1zM0 6h1v1h-1zM3 6h1v1h-1zM5 6h1v1h-1zM7 6h1v1h-1zM10 6h1v1h-1zM0 7h1v1h-1zM3 7h1v1h-1zM5 7h1v1h-1zM7 7h1v1h-1zM10 7h1v1h-1zM1 8h1v1h-1zM9 8h1v1h-1zM2 9h1v1h-1zM8 9h1v1h-1zM3 10h1v1h-1zM7 10h1v1h-1zM4 11h3v1h-3z"
51
- }, p = {
55
+ }, m = {
52
56
  w: 11,
53
57
  h: 12,
54
58
  d: "M1 0h9v1h-9zM0 1h11v1h-11zM0 2h11v1h-11zM0 3h11v1h-11zM0 4h11v1h-11zM0 5h11v1h-11zM0 6h11v1h-11zM0 7h11v1h-11zM1 8h9v1h-9zM2 9h7v1h-7zM3 10h5v1h-5zM4 11h3v1h-3z"
55
- }, m = {
59
+ }, h = {
56
60
  w: 15,
57
61
  h: 25,
58
62
  d: "M7 3h1v1h-1zM6 4h3v1h-3zM5 5h5v1h-5zM4 6h7v1h-7zM3 7h9v1h-9zM5 8h5v1h-5zM5 9h5v1h-5zM5 10h5v1h-5z"
59
- }, h = {
63
+ }, g = {
60
64
  w: 15,
61
65
  h: 25,
62
66
  d: "M5 14h5v1h-5zM5 15h5v1h-5zM5 16h5v1h-5zM3 17h9v1h-9zM4 18h7v1h-7zM5 19h5v1h-5zM6 20h3v1h-3zM7 21h1v1h-1z"
63
- }, g = {
67
+ }, _ = {
64
68
  w: 16,
65
69
  h: 16,
66
70
  d: "M7 3h2v1h-2zM6 4h1v1h-1zM9 4h1v1h-1zM5 5h1v1h-1zM10 5h1v1h-1zM4 6h1v1h-1zM11 6h1v1h-1zM3 7h1v1h-1zM12 7h1v1h-1zM2 8h4v1h-4zM10 8h4v1h-4zM5 9h1v1h-1zM10 9h1v1h-1zM5 10h1v1h-1zM10 10h1v1h-1zM5 11h1v1h-1zM10 11h1v1h-1zM5 12h6v1h-6z"
67
- }, _ = {
71
+ }, v = {
68
72
  w: 16,
69
73
  h: 16,
70
74
  d: "M7 3h2v1h-2zM6 4h4v1h-4zM5 5h6v1h-6zM4 6h8v1h-8zM3 7h10v1h-10zM2 8h12v1h-12zM5 9h6v1h-6zM5 10h6v1h-6zM5 11h6v1h-6zM5 12h6v1h-6z"
71
- }, v = {
75
+ }, y = {
72
76
  w: 16,
73
77
  h: 16,
74
78
  d: "M5 3h6v1h-6zM5 4h1v1h-1zM10 4h1v1h-1zM5 5h1v1h-1zM10 5h1v1h-1zM5 6h1v1h-1zM10 6h1v1h-1zM2 7h4v1h-4zM10 7h4v1h-4zM3 8h1v1h-1zM12 8h1v1h-1zM4 9h1v1h-1zM11 9h1v1h-1zM5 10h1v1h-1zM10 10h1v1h-1zM6 11h1v1h-1zM9 11h1v1h-1zM7 12h2v1h-2z"
75
- }, y = {
79
+ }, b = {
76
80
  w: 16,
77
81
  h: 16,
78
82
  d: "M5 3h6v1h-6zM5 4h6v1h-6zM5 5h6v1h-6zM5 6h6v1h-6zM2 7h12v1h-12zM3 8h10v1h-10zM4 9h8v1h-8zM5 10h6v1h-6zM6 11h4v1h-4zM7 12h2v1h-2z"
79
- }, b = {
83
+ }, x = {
80
84
  w: 16,
81
85
  h: 16,
82
86
  d: "M8 2h1v1h-1zM7 3h2v1h-2zM6 4h1v1h-1zM8 4h1v1h-1zM5 5h1v1h-1zM8 5h5v1h-5zM4 6h1v1h-1zM12 6h1v1h-1zM3 7h1v1h-1zM12 7h1v1h-1zM3 8h1v1h-1zM12 8h1v1h-1zM4 9h1v1h-1zM12 9h1v1h-1zM5 10h1v1h-1zM8 10h5v1h-5zM6 11h1v1h-1zM8 11h1v1h-1zM7 12h2v1h-2zM8 13h1v1h-1z"
83
- }, x = {
87
+ }, S = {
84
88
  w: 16,
85
89
  h: 16,
86
90
  d: "M8 2h1v1h-1zM7 3h2v1h-2zM6 4h3v1h-3zM5 5h8v1h-8zM4 6h9v1h-9zM3 7h10v1h-10zM3 8h10v1h-10zM4 9h9v1h-9zM5 10h8v1h-8zM6 11h3v1h-3zM7 12h2v1h-2zM8 13h1v1h-1z"
87
- }, S = {
91
+ }, C = {
88
92
  w: 16,
89
93
  h: 16,
90
94
  d: "M7 2h1v1h-1zM7 3h2v1h-2zM7 4h1v1h-1zM9 4h1v1h-1zM3 5h5v1h-5zM10 5h1v1h-1zM3 6h1v1h-1zM11 6h1v1h-1zM3 7h1v1h-1zM12 7h1v1h-1zM3 8h1v1h-1zM12 8h1v1h-1zM3 9h1v1h-1zM11 9h1v1h-1zM3 10h5v1h-5zM10 10h1v1h-1zM7 11h1v1h-1zM9 11h1v1h-1zM7 12h2v1h-2zM7 13h1v1h-1z"
91
- }, C = {
95
+ }, w = {
92
96
  w: 16,
93
97
  h: 16,
94
98
  d: "M7 2h1v1h-1zM7 3h2v1h-2zM7 4h3v1h-3zM3 5h8v1h-8zM3 6h9v1h-9zM3 7h10v1h-10zM3 8h10v1h-10zM3 9h9v1h-9zM3 10h8v1h-8zM7 11h3v1h-3zM7 12h2v1h-2zM7 13h1v1h-1z"
95
99
  };
96
- function w(t, n) {
100
+ function T(t, n) {
97
101
  return e`<svg
98
102
  class=${n}
99
103
  viewBox="0 0 ${t.w} ${t.h}"
@@ -105,4 +109,4 @@ function w(t, n) {
105
109
  </svg>`;
106
110
  }
107
111
  //#endregion
108
- export { s as CARET_DOWN, l as CARET_DOWN_SMALL, c as CARET_UP, u as CARET_UP_SMALL, t as CHECKBOX_X, o as CHECKMARK, a as RADIO_DOT, n as RADIO_FACE, r as RADIO_RING, i as RADIO_RING_PRESSED, v as SCROLL_ARROW_DOWN, y as SCROLL_ARROW_DOWN_FILL, b as SCROLL_ARROW_LEFT, x as SCROLL_ARROW_LEFT_FILL, S as SCROLL_ARROW_RIGHT, C as SCROLL_ARROW_RIGHT_FILL, g as SCROLL_ARROW_UP, _ as SCROLL_ARROW_UP_FILL, f as SLIDER_THUMB, p as SLIDER_THUMB_FACE, d as STEPPER, h as STEPPER_DOWN_FILL, m as STEPPER_UP_FILL, w as glyphSvg };
112
+ export { s as CARET_DOWN, l as CARET_DOWN_SMALL, d as CARET_RIGHT, c as CARET_UP, u as CARET_UP_SMALL, t as CHECKBOX_X, o as CHECKMARK, a as RADIO_DOT, n as RADIO_FACE, r as RADIO_RING, i as RADIO_RING_PRESSED, y as SCROLL_ARROW_DOWN, b as SCROLL_ARROW_DOWN_FILL, x as SCROLL_ARROW_LEFT, S as SCROLL_ARROW_LEFT_FILL, C as SCROLL_ARROW_RIGHT, w as SCROLL_ARROW_RIGHT_FILL, _ as SCROLL_ARROW_UP, v as SCROLL_ARROW_UP_FILL, p as SLIDER_THUMB, m as SLIDER_THUMB_FACE, f as STEPPER, g as STEPPER_DOWN_FILL, h as STEPPER_UP_FILL, T as glyphSvg };
package/dist/index.d.ts CHANGED
@@ -181,3 +181,4 @@ export { registerEmbeddedFont, PIXEL_GRID_METRICS } from './styles/register-embe
181
181
  export type { EmbeddedFontMetrics } from './styles/register-embedded-font.js';
182
182
  export { registerDisplayFace, VF_DISPLAY_FAMILY } from './styles/display-font.js';
183
183
  export { registerBodyFace, VF_BODY_FAMILY } from './styles/body-font.js';
184
+ export { registerBodyItalicFace } from './styles/body-italic-font.js';
package/dist/index.js CHANGED
@@ -61,17 +61,18 @@ import { VfSlider as nn } from "./components/vf-slider.js";
61
61
  import { VfLabel as rn } from "./components/vf-label.js";
62
62
  import { VfParagraph as an } from "./components/vf-paragraph.js";
63
63
  import { VfImg as on } from "./components/vf-img.js";
64
- import { VfIcon as sn } from "./components/vf-icon.js";
65
- import { VfIconField as cn } from "./components/vf-icon-field.js";
66
- import { VfMenuBar as ln } from "./components/vf-menu-bar.js";
67
- import { VfMenu as un } from "./components/vf-menu.js";
68
- import { VfMenuItem as dn } from "./components/vf-menu-item.js";
69
- import { VfList as fn } from "./components/vf-list.js";
70
- import { VfListItem as pn } from "./components/vf-list-item.js";
71
- import { VfFieldset as mn } from "./components/vf-fieldset.js";
72
- import { VfGrid as hn } from "./components/vf-grid.js";
73
- import { VfStack as gn } from "./components/vf-stack.js";
74
- import { VfContainer as _n } from "./components/vf-container.js";
75
- import { CURSOR_ARROW as vn, CURSOR_CROSSHAIR as yn, CURSOR_I_BEAM as bn, CURSOR_WAIT as xn } from "./cursor-art.js";
76
- import { applyCursor as Sn } from "./cursor.js";
77
- export { Ge as BLINK_FLIPS, Ke as BLINK_INTERVAL_MS, Ne as BUTTON_FACE, Pe as BUTTON_FRAME, ht as CARET_DOWN, gt as CARET_DOWN_SMALL, _t as CHECKBOX_X, vt as CHECKMARK, r as CLASSIC_DPI, i as CSS_REFERENCE_DPI, vn as CURSOR_ARROW, yn as CURSOR_CROSSHAIR, bn as CURSOR_I_BEAM, xn as CURSOR_WAIT, qe as DRAG_SLOP_COARSE_PX, Je as DRAG_SLOP_PX, Me as DocumentListenersController, We as DragController, Gt as FocusRuleController, Ae as GridSnapController, $ as PATTERNS, ee as PATTERN_NAMES, te as PATTERN_SIZE, D as PIXEL_GRID_METRICS, Ye as PRESS_HOLD_MS, Oe as PatternFillController, T as PlacementController, yt as RADIO_DOT, bt as RADIO_FACE, xt as RADIO_RING, St as RADIO_RING_PRESSED, Xe as RENAME_DELAY_MS, G as REPEAT_TILE, Fe as RING_FRAME, Ie as RING_HOLE, Le as RING_INSET, ge as RULE_EDGES, K as RepeatTileController, Re as SCREEN_CORNER, Ct as SLIDER_THUMB, wt as SLIDER_THUMB_FACE, Tt as STEPPER, Et as STEPPER_DOWN_FILL, Dt as STEPPER_UP_FILL, a as SYSTEM_PX_IN_CSS_PX, d as ScaleController, kt as ScrollRailController, mt as ScrollStateController, Ze as TAP_PAIR_MS, Qe as TAP_PAIR_SLOP_PX, R as TILE_LATTICE, en as TrackWidthController, k as VF_BODY_FAMILY, M as VF_DISPLAY_FAMILY, Rt as VfButton, zt as VfButtonGroup, Ht as VfCheckbox, _n as VfContainer, He as VfDesktop, Ft as VfDialog, mn as VfFieldset, Lt as VfFormControl, hn as VfGrid, sn as VfIcon, cn as VfIconField, on as VfImg, rn as VfLabel, fn as VfList, pn as VfListItem, un as VfMenu, ln as VfMenuBar, dn as VfMenuItem, Nt as VfModalDialog, Zt as VfNumberField, Qt as VfOption, an as VfParagraph, E as VfPositioned, tn as VfProgressBar, Ut as VfRadio, Wt as VfRadioGroup, jt as VfScrollArea, $t as VfSelect, It as VfSeparator, Ue as VfSized, nn as VfSlider, gn as VfStack, Bt as VfSwatch, Xt as VfTextArea, Jt as VfTextControlBase, Yt as VfTextField, Vt as VfToggleControl, Mt as VfWindow, $e as WALK_BEAT_MS, et as WALK_STEP_MS, tt as WALK_STEP_PX, dt as WINDOW_MIN_HEIGHT, ft as WINDOW_MIN_WIDTH, nt as WINDOW_RECTS_VISIBLE, rt as WINDOW_RECT_RATIO, it as WINDOW_RECT_STEPS, at as WINDOW_RECT_STEP_MS, Sn as applyCursor, f as applyScale, t as defineElement, q as devicePxAt, o as devicePxPerSystemPx, ot as dragSlop, p as effectiveScale, e as emit, Kt as focusModality, m as getScale, s as getZoom, Ot as glyphSvg, Pt as modalDialogStyles, h as onScaleChange, c as onZoomChange, ne as parsePattern, _e as parseRule, re as patternHex, ie as patternMotif, J as patternOverride, ae as patternRects, st as prefersReducedMotion, A as registerBodyFace, N as registerDisplayFace, O as registerEmbeddedFont, At as renderScrollRail, Y as repeatTile, je as requestGridSnap, l as resetZoomBaseline, ve as ruleClasses, ct as runOutlineTravel, lt as runSelectionBlink, g as snapSys, _ as snapToDevicePx, v as snapToSystemPx, ze as steppedCornerClip, Be as steppedRectClip, Ve as steppedRingClip, y as sys, b as sysLength, x as sysLengths, S as systemPxQuantum, X as tileGrid, z as tileImage, B as tileRaster, V as tileRects, H as tileSpan, C as toSys, w as toSysExact, qt as trackFocusModality, u as truePixelRatio, I as vfBase, j as vfBodyDecls, pe as vfChromeFrame, P as vfDisplay, F as vfDisplayDecls, oe as vfDots, n as vfElement, Ee as vfField, Se as vfFocus, Ce as vfFocusRing, we as vfFocusUnderline, ce as vfHardShadow, le as vfHardShadowDecls, me as vfModalFrame, he as vfPanel, ke as vfPatternFill, Z as vfRepeatTileSize, ye as vfRule, De as vfScrollRail, L as vfStaticText, se as vfStripes, ue as vfStrokeDecls, de as vfStrokeInset, fe as vfStrokeShadow, Q as vfTileGrid, U as vfTileMaskSize, W as vfTileSize, be as vfTitleBar, Te as vfToggle, xe as vfWindowWidgets, pt as windowChrome, ut as windowRectFraction };
64
+ import { registerBodyItalicFace as sn } from "./styles/body-italic-font.js";
65
+ import { VfIcon as cn } from "./components/vf-icon.js";
66
+ import { VfIconField as ln } from "./components/vf-icon-field.js";
67
+ import { VfMenuBar as un } from "./components/vf-menu-bar.js";
68
+ import { VfMenu as dn } from "./components/vf-menu.js";
69
+ import { VfMenuItem as fn } from "./components/vf-menu-item.js";
70
+ import { VfList as pn } from "./components/vf-list.js";
71
+ import { VfListItem as mn } from "./components/vf-list-item.js";
72
+ import { VfFieldset as hn } from "./components/vf-fieldset.js";
73
+ import { VfGrid as gn } from "./components/vf-grid.js";
74
+ import { VfStack as _n } from "./components/vf-stack.js";
75
+ import { VfContainer as vn } from "./components/vf-container.js";
76
+ import { CURSOR_ARROW as yn, CURSOR_CROSSHAIR as bn, CURSOR_I_BEAM as xn, CURSOR_WAIT as Sn } from "./cursor-art.js";
77
+ import { applyCursor as Cn } from "./cursor.js";
78
+ export { Ge as BLINK_FLIPS, Ke as BLINK_INTERVAL_MS, Ne as BUTTON_FACE, Pe as BUTTON_FRAME, ht as CARET_DOWN, gt as CARET_DOWN_SMALL, _t as CHECKBOX_X, vt as CHECKMARK, r as CLASSIC_DPI, i as CSS_REFERENCE_DPI, yn as CURSOR_ARROW, bn as CURSOR_CROSSHAIR, xn as CURSOR_I_BEAM, Sn as CURSOR_WAIT, qe as DRAG_SLOP_COARSE_PX, Je as DRAG_SLOP_PX, Me as DocumentListenersController, We as DragController, Gt as FocusRuleController, Ae as GridSnapController, $ as PATTERNS, ee as PATTERN_NAMES, te as PATTERN_SIZE, D as PIXEL_GRID_METRICS, Ye as PRESS_HOLD_MS, Oe as PatternFillController, T as PlacementController, yt as RADIO_DOT, bt as RADIO_FACE, xt as RADIO_RING, St as RADIO_RING_PRESSED, Xe as RENAME_DELAY_MS, G as REPEAT_TILE, Fe as RING_FRAME, Ie as RING_HOLE, Le as RING_INSET, ge as RULE_EDGES, K as RepeatTileController, Re as SCREEN_CORNER, Ct as SLIDER_THUMB, wt as SLIDER_THUMB_FACE, Tt as STEPPER, Et as STEPPER_DOWN_FILL, Dt as STEPPER_UP_FILL, a as SYSTEM_PX_IN_CSS_PX, d as ScaleController, kt as ScrollRailController, mt as ScrollStateController, Ze as TAP_PAIR_MS, Qe as TAP_PAIR_SLOP_PX, R as TILE_LATTICE, en as TrackWidthController, k as VF_BODY_FAMILY, M as VF_DISPLAY_FAMILY, Rt as VfButton, zt as VfButtonGroup, Ht as VfCheckbox, vn as VfContainer, He as VfDesktop, Ft as VfDialog, hn as VfFieldset, Lt as VfFormControl, gn as VfGrid, cn as VfIcon, ln as VfIconField, on as VfImg, rn as VfLabel, pn as VfList, mn as VfListItem, dn as VfMenu, un as VfMenuBar, fn as VfMenuItem, Nt as VfModalDialog, Zt as VfNumberField, Qt as VfOption, an as VfParagraph, E as VfPositioned, tn as VfProgressBar, Ut as VfRadio, Wt as VfRadioGroup, jt as VfScrollArea, $t as VfSelect, It as VfSeparator, Ue as VfSized, nn as VfSlider, _n as VfStack, Bt as VfSwatch, Xt as VfTextArea, Jt as VfTextControlBase, Yt as VfTextField, Vt as VfToggleControl, Mt as VfWindow, $e as WALK_BEAT_MS, et as WALK_STEP_MS, tt as WALK_STEP_PX, dt as WINDOW_MIN_HEIGHT, ft as WINDOW_MIN_WIDTH, nt as WINDOW_RECTS_VISIBLE, rt as WINDOW_RECT_RATIO, it as WINDOW_RECT_STEPS, at as WINDOW_RECT_STEP_MS, Cn as applyCursor, f as applyScale, t as defineElement, q as devicePxAt, o as devicePxPerSystemPx, ot as dragSlop, p as effectiveScale, e as emit, Kt as focusModality, m as getScale, s as getZoom, Ot as glyphSvg, Pt as modalDialogStyles, h as onScaleChange, c as onZoomChange, ne as parsePattern, _e as parseRule, re as patternHex, ie as patternMotif, J as patternOverride, ae as patternRects, st as prefersReducedMotion, A as registerBodyFace, sn as registerBodyItalicFace, N as registerDisplayFace, O as registerEmbeddedFont, At as renderScrollRail, Y as repeatTile, je as requestGridSnap, l as resetZoomBaseline, ve as ruleClasses, ct as runOutlineTravel, lt as runSelectionBlink, g as snapSys, _ as snapToDevicePx, v as snapToSystemPx, ze as steppedCornerClip, Be as steppedRectClip, Ve as steppedRingClip, y as sys, b as sysLength, x as sysLengths, S as systemPxQuantum, X as tileGrid, z as tileImage, B as tileRaster, V as tileRects, H as tileSpan, C as toSys, w as toSysExact, qt as trackFocusModality, u as truePixelRatio, I as vfBase, j as vfBodyDecls, pe as vfChromeFrame, P as vfDisplay, F as vfDisplayDecls, oe as vfDots, n as vfElement, Ee as vfField, Se as vfFocus, Ce as vfFocusRing, we as vfFocusUnderline, ce as vfHardShadow, le as vfHardShadowDecls, me as vfModalFrame, he as vfPanel, ke as vfPatternFill, Z as vfRepeatTileSize, ye as vfRule, De as vfScrollRail, L as vfStaticText, se as vfStripes, ue as vfStrokeDecls, de as vfStrokeInset, fe as vfStrokeShadow, Q as vfTileGrid, U as vfTileMaskSize, W as vfTileSize, be as vfTitleBar, Te as vfToggle, xe as vfWindowWidgets, pt as windowChrome, ut as windowRectFraction };
@@ -0,0 +1,34 @@
1
+ import type { VfMenu } from './components/vf-menu.js';
2
+ import type { TypeAheadBuffer } from './type-ahead.js';
3
+ /**
4
+ * The keyboard of an open menu and its submenus, shared by the two hosts that
5
+ * own one: `vf-menu-bar` for its open menu, and a `vf-menu` standing alone.
6
+ * Each listens on the document while a menu is open and hands the keydown to
7
+ * {@link navigateMenus}, which acts on the deepest open menu holding focus,
8
+ * after the APG menubar and menu patterns:
9
+ *
10
+ * - ↓/↑ walk that menu's enabled items, wrapping; Home/End jump to its first
11
+ * and last; printable keys run the shared first-letter type-ahead
12
+ * (src/type-ahead.ts), Space and modified keys aside.
13
+ * - → on an item that opens a submenu opens it and moves focus to its first
14
+ * enabled item, as Enter and Space do from the item itself. On any other
15
+ * item in a bar, → opens the next menu.
16
+ * - ← in a submenu closes it and puts focus back on its item; at the top of a
17
+ * bar, ← opens the previous menu.
18
+ * - Escape closes one level: a submenu back to its item, the top menu back to
19
+ * its title. Tab closes every menu and lets focus move on.
20
+ */
21
+ export interface MenuKeyboard {
22
+ /** The open top-level menu. */
23
+ readonly menu: VfMenu;
24
+ /** The host's own first-letter type-ahead buffer. */
25
+ readonly typeAhead: TypeAheadBuffer;
26
+ /** Close every menu, putting focus back on the title when `refocus`. */
27
+ close(refocus: boolean): void;
28
+ /** In a bar: open the next (1) or previous (-1) menu. */
29
+ switchMenu?(direction: 1 | -1): void;
30
+ }
31
+ /** The open menus from `menu` down: each the submenu of an item in the one before. */
32
+ export declare function openPath(menu: VfMenu): VfMenu[];
33
+ /** Handles one keydown for an open menu and the submenus open under it. */
34
+ export declare function navigateMenus(event: KeyboardEvent, keys: MenuKeyboard): void;
@@ -0,0 +1,53 @@
1
+ //#region src/menu-navigation.ts
2
+ function e(e) {
3
+ let t = [e];
4
+ for (let n = e.expandedItem?.submenu; n?.open; n = n.expandedItem?.submenu) t.push(n);
5
+ return t;
6
+ }
7
+ function t(t, n) {
8
+ if (t.defaultPrevented) return;
9
+ let r = e(n.menu), i = n.menu.getRootNode().activeElement, a = 0;
10
+ for (let e = r.length - 1; e > 0; e--) if (r[e].allItems.includes(i)) {
11
+ a = e;
12
+ break;
13
+ }
14
+ let o = r[a], s = o.items, c = s.indexOf(i), l = (e) => {
15
+ let t = e.parentElement;
16
+ n.typeAhead.reset(), t.focus(), t.closest("vf-menu")?.expand(null);
17
+ };
18
+ switch (t.key) {
19
+ case "Escape":
20
+ t.preventDefault(), a > 0 ? l(o) : n.close(!0);
21
+ break;
22
+ case "Tab":
23
+ n.close(!1);
24
+ break;
25
+ case "ArrowDown":
26
+ case "ArrowUp": {
27
+ if (t.preventDefault(), s.length === 0) break;
28
+ let e = t.key === "ArrowDown" ? 1 : -1;
29
+ s[c < 0 ? e === 1 ? 0 : s.length - 1 : (c + e + s.length) % s.length]?.focus();
30
+ break;
31
+ }
32
+ case "Home":
33
+ case "End":
34
+ t.preventDefault(), s[t.key === "Home" ? 0 : s.length - 1]?.focus();
35
+ break;
36
+ case "ArrowRight": {
37
+ let e = s[c];
38
+ e?.submenu ? (t.preventDefault(), n.typeAhead.reset(), o.expand(e, { focus: !0 })) : n.switchMenu && (t.preventDefault(), n.switchMenu(1));
39
+ break;
40
+ }
41
+ case "ArrowLeft":
42
+ a > 0 ? (t.preventDefault(), l(o)) : n.switchMenu && (t.preventDefault(), n.switchMenu(-1));
43
+ break;
44
+ default:
45
+ if (t.key.length !== 1 || t.key === " " || t.metaKey || t.ctrlKey || t.altKey) break;
46
+ t.preventDefault(), s[n.typeAhead.feed(t.key, c, s.map((e) => ({
47
+ text: e.labelText,
48
+ disabled: !1
49
+ })))]?.focus();
50
+ }
51
+ }
52
+ //#endregion
53
+ export { t as navigateMenus, e as openPath };