vintage-frames 0.15.0 → 0.16.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/custom-elements.json +907 -99
  2. package/dist/chrome.d.ts +10 -1
  3. package/dist/chrome.js +8 -3
  4. package/dist/components/vf-desktop.d.ts +5 -2
  5. package/dist/components/vf-desktop.js +5 -5
  6. package/dist/components/vf-dialog.d.ts +14 -8
  7. package/dist/components/vf-dialog.js +27 -27
  8. package/dist/components/vf-menu-bar.js +9 -10
  9. package/dist/components/vf-menu-item.js +18 -13
  10. package/dist/components/vf-menu.d.ts +8 -3
  11. package/dist/components/vf-menu.js +85 -61
  12. package/dist/components/vf-number-field.d.ts +4 -0
  13. package/dist/components/vf-number-field.js +28 -25
  14. package/dist/components/vf-paragraph.d.ts +3 -1
  15. package/dist/components/vf-paragraph.js +7 -0
  16. package/dist/components/vf-scroll-area.d.ts +16 -1
  17. package/dist/components/vf-scroll-area.js +39 -29
  18. package/dist/components/vf-select.d.ts +5 -4
  19. package/dist/components/vf-select.js +26 -17
  20. package/dist/components/vf-text-field.d.ts +5 -5
  21. package/dist/components/vf-text-field.js +1 -1
  22. package/dist/components/vf-window.d.ts +22 -5
  23. package/dist/components/vf-window.js +113 -98
  24. package/dist/cursor.d.ts +8 -0
  25. package/dist/cursor.js +70 -73
  26. package/dist/index.d.ts +2 -1
  27. package/dist/modal-dialog.d.ts +27 -5
  28. package/dist/modal-dialog.js +63 -51
  29. package/dist/shell/catalog.d.ts +1 -1
  30. package/dist/shell/catalog.js +32 -18
  31. package/dist/shell/finder.d.ts +6 -1
  32. package/dist/shell/finder.js +182 -176
  33. package/dist/shell/index.d.ts +1 -1
  34. package/dist/shell/pure.d.ts +10 -0
  35. package/dist/shell/pure.js +4 -0
  36. package/dist/shell/shell.d.ts +16 -3
  37. package/dist/shell/shell.js +141 -126
  38. package/dist/shell/windows.d.ts +57 -13
  39. package/dist/shell/windows.js +214 -154
  40. package/dist/text-control.d.ts +46 -3
  41. package/dist/text-control.js +33 -5
  42. package/dist/top-layer.d.ts +13 -0
  43. package/dist/top-layer.js +16 -0
  44. package/docs/SPEC.md +25 -24
  45. package/editor/vscode.html-custom-data.json +36 -11
  46. package/editor/web-types.json +81 -23
  47. package/package.json +5 -1
package/dist/chrome.d.ts CHANGED
@@ -61,6 +61,15 @@ export declare class TitleCenterController implements ReactiveController {
61
61
  * belongs to.
62
62
  */
63
63
  export declare const widgetLabel: (action: string, heading: string) => string;
64
+ /** The modifier keys held on a close box's click, which its `vf-close` carries. */
65
+ export interface VfCloseKeys {
66
+ altKey: boolean;
67
+ shiftKey: boolean;
68
+ metaKey: boolean;
69
+ ctrlKey: boolean;
70
+ }
71
+ /** The modifier keys an event carries. */
72
+ export declare const closeKeys: (event: MouseEvent | KeyboardEvent) => VfCloseKeys;
64
73
  /**
65
74
  * The close box (left of the bar) and zoom box (right of the bar), shared by
66
75
  * `vf-window` and a `closable` `vf-dialog`. Byte-identical markup for the same
@@ -69,5 +78,5 @@ export declare const widgetLabel: (action: string, heading: string) => string;
69
78
  * drag delegates must keep ignoring pointerdowns on `.box` so a press on a
70
79
  * widget never starts a bar drag.
71
80
  */
72
- export declare const closeBox: (label: string, onClick: () => void) => TemplateResult;
81
+ export declare const closeBox: (label: string, onClick: (event: MouseEvent) => void) => TemplateResult;
73
82
  export declare const zoomBox: (label: string, onClick: () => void) => TemplateResult;
package/dist/chrome.js CHANGED
@@ -74,7 +74,12 @@ var a = i`${[
74
74
  reset() {
75
75
  this.written &&= (this.host.style.removeProperty("--vf-title-dx"), this.applied = 0, "");
76
76
  }
77
- }, u = (e, t) => t ? `${e} ${t}` : e, d = (e, t) => i`
77
+ }, u = (e, t) => t ? `${e} ${t}` : e, d = (e) => ({
78
+ altKey: e.altKey,
79
+ shiftKey: e.shiftKey,
80
+ metaKey: e.metaKey,
81
+ ctrlKey: e.ctrlKey
82
+ }), f = (e, t) => i`
78
83
  <button
79
84
  type="button"
80
85
  class="box close vf-focus"
@@ -82,7 +87,7 @@ var a = i`${[
82
87
  aria-label=${e}
83
88
  @click=${t}
84
89
  ></button>
85
- `, f = (e, t) => i`
90
+ `, p = (e, t) => i`
86
91
  <button
87
92
  type="button"
88
93
  class="box zoom vf-focus"
@@ -92,4 +97,4 @@ var a = i`${[
92
97
  ></button>
93
98
  `;
94
99
  //#endregion
95
- export { l as TitleCenterController, o as chromeTitleBar, d as closeBox, u as widgetLabel, f as zoomBox };
100
+ export { l as TitleCenterController, o as chromeTitleBar, f as closeBox, d as closeKeys, u as widgetLabel, p as zoomBox };
@@ -8,7 +8,9 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
8
8
  * setting) — and manages the stacking order and `active` state of slotted
9
9
  * `vf-window` children: a `pointerdown` or
10
10
  * `focusin` (keyboard focus) anywhere inside a window brings it to the front
11
- * and makes it the single active window. The windows' light-DOM order is kept
11
+ * and makes it the single active window. A press on a title bar with ⌘ held
12
+ * raises nothing, so a background window is dragged where it stands in the
13
+ * stack. The windows' light-DOM order is kept
12
14
  * in step with the stacking order (bottom-most first, synced in a task once
13
15
  * any pointer gesture has ended), so tabbing walks the stack the way the eye
14
16
  * does and Shift+Tab is its exact mirror.
@@ -155,7 +157,8 @@ export declare class VfDesktop extends VfDesktop_base {
155
157
  * the whole screen, 1-bit at every density and zoom. A
156
158
  * `--vf-desktop-pattern` token override still wins and renders the
157
159
  * consumer's tile as a placed grid; an unrecognized value warns once and
158
- * keeps the dither.
160
+ * keeps the dither. Reflects, so a change can be observed on the
161
+ * attribute.
159
162
  */
160
163
  pattern: string | null | undefined;
161
164
  /**
@@ -14,7 +14,7 @@ import { SCREEN_CORNER as C, steppedCornerClip as w } from "../pixel-frame.js";
14
14
  import { LitElement as T, css as E, html as D, unsafeCSS as O } from "lit";
15
15
  import { property as k, query as A, queryAssignedElements as j } from "lit/decorators.js";
16
16
  //#region src/components/vf-desktop.ts
17
- var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L], "#000000", "#ffffff"), z = u(R.width, R.height, d(R.rects)), B = f(R.width), V = (e) => Number(e.style.zIndex) || 0, H = class extends s(T) {
17
+ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L], "#000000", "#ffffff"), z = u(R.width, R.height, d(R.rects)), B = f(R.width), V = (e) => Number(e.style.zIndex) || 0, H = (e) => e.composedPath().some((e) => e instanceof Element && e.classList.contains("vf-title-bar")), U = class extends s(T) {
18
18
  constructor(...e) {
19
19
  super(...e), this.width = F, this.height = I, this.bezel = 0, this.pattern = L, this.scale = new n(this), this.gridSnap = new x(this), this._token = "", this._desktopPattern = g[L], this.#e = !1, this.patternFill = new y(this, {
20
20
  getBox: () => this.screen,
@@ -32,7 +32,7 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
32
32
  ]]), this._onPointerDown = (e) => {
33
33
  this._pointerGesture || (this._pointerGesture = !0, this._gestureEnd.attach());
34
34
  let t = this._windowFromEvent(e);
35
- t && this._raise(t);
35
+ t && e.metaKey && H(e) || t && this._raise(t);
36
36
  }, this._onGestureEnd = () => {
37
37
  this._gestureEnd.detach(), this._pointerGesture = !1, this._requestDomSync();
38
38
  }, this._onDragSurfaceRequest = (e) => {
@@ -388,9 +388,9 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
388
388
  `;
389
389
  }
390
390
  };
391
- o([k({ type: Number })], H.prototype, "width", void 0), o([k({ type: Number })], H.prototype, "height", void 0), o([k({ type: Number })], H.prototype, "bezel", void 0), o([k()], H.prototype, "pattern", void 0), o([k({
391
+ o([k({ type: Number })], U.prototype, "width", void 0), o([k({ type: Number })], U.prototype, "height", void 0), o([k({ type: Number })], U.prototype, "bezel", void 0), o([k({ reflect: !0 })], U.prototype, "pattern", void 0), o([k({
392
392
  type: Number,
393
393
  attribute: "window-top"
394
- })], H.prototype, "windowTop", void 0), o([j({ selector: "vf-window" })], H.prototype, "_windows", void 0), o([A(".screen")], H.prototype, "screen", void 0), o([A(".drag-surface")], H.prototype, "dragSurface", void 0), H = o([t("vf-desktop")], H);
394
+ })], U.prototype, "windowTop", void 0), o([j({ selector: "vf-window" })], U.prototype, "_windows", void 0), o([A(".screen")], U.prototype, "screen", void 0), o([A(".drag-surface")], U.prototype, "dragSurface", void 0), U = o([t("vf-desktop")], U);
395
395
  //#endregion
396
- export { H as VfDesktop };
396
+ export { U as VfDesktop };
@@ -32,12 +32,13 @@ import { VfModalDialog } from '../modal-dialog.js';
32
32
  *
33
33
  * Keyboard, the classic Dialog Manager's two rules ({@link VfModalDialog}):
34
34
  * on open, focus goes to the first text-entry control — a slotted control
35
- * with `autofocus` first — or, with none, to the default button
36
- * (`vf-button variant="default"`). Return or Enter activates the default
37
- * button from anywhere in the dialog, a focused Cancel included; Space
38
- * presses the focused control. A link keeps its own Enter, and in a
39
- * multi-line editor Return inserts the newline while the keypad's Enter
40
- * activates the button.
35
+ * with `autofocus` or `autoselect` first — or, with none, to the default
36
+ * button (`vf-button variant="default"`). A field marked `autoselect` opens
37
+ * with its whole text selected, on every open. Return or Enter activates
38
+ * the default button from anywhere in the dialog, a focused Cancel
39
+ * included; Space presses the focused control. A link keeps its own Enter,
40
+ * and in a multi-line editor Return inserts the newline while the keypad's
41
+ * Enter activates the button.
41
42
  *
42
43
  * Slotted children placed with `top`/`left` measure from the content region's
43
44
  * corner — the frame's inner edge, below the title bar — and flow content
@@ -53,9 +54,13 @@ import { VfModalDialog } from '../modal-dialog.js';
53
54
  * @csspart content - The scrolling region inside the body (the slotted
54
55
  * content). Inert while the content fits; over-stuffed, it scrolls under a
55
56
  * System 7 rail and becomes a keyboard stop.
57
+ * @fires vf-show - Dialog opened, placed and given its initial focus. Detail
58
+ * `{ focus }`, the element focused: the moment to measure copy that
59
+ * varies. A field marked `autoselect` has its text selected after it.
56
60
  * @fires vf-close - Dialog closed. Detail `{ reason: 'escape' | 'close' |
57
61
  * 'outside', returnValue: string | null }` — `'outside'` only under
58
- * `light-dismiss`.
62
+ * `light-dismiss` — plus `altKey`, `shiftKey`, `metaKey` and `ctrlKey`
63
+ * when the close box closed it.
59
64
  * @cssprop --vf-dots-pattern - the windoid bar's dot-grid dither — a 2×2 tile,
60
65
  * one black pixel at the origin (`vfDots`; override the whole pattern like
61
66
  * `--vf-desktop-pattern`)
@@ -93,7 +98,8 @@ export declare class VfDialog extends VfModalDialog {
93
98
  /**
94
99
  * Show the close box (left side of the title bar). Off by default — the
95
100
  * bare movable-modal bar. Ignored with `frame="plain"` (no bar). Clicking
96
- * it closes the dialog and fires `vf-close` with `{ reason: 'close' }`.
101
+ * it closes the dialog and fires `vf-close` with `{ reason: 'close' }` and
102
+ * the modifier keys held on the click, as `vf-window`'s close box does.
97
103
  */
98
104
  closable: boolean;
99
105
  /**
@@ -8,15 +8,15 @@ import { vfTitleBar as s, vfWindowWidgets as c } from "../styles/recipes/title-b
8
8
  import { vfFocus as l, vfFocusRing as u } from "../styles/recipes/focus.js";
9
9
  import { vfScrollRail as d } from "../styles/recipes/scroll-rail.js";
10
10
  import { DragController as f } from "../drag.js";
11
- import { TitleCenterController as p, chromeTitleBar as m, closeBox as h, widgetLabel as g } from "../chrome.js";
12
- import { ScrollStateController as _ } from "../scroll-state.js";
13
- import { ScrollRailController as v, renderScrollRail as y } from "../scroll-rail.js";
14
- import { VfModalDialog as b, modalDialogStyles as x } from "../modal-dialog.js";
15
- import { css as S, html as C, nothing as w } from "lit";
16
- import { property as T, query as E, state as D } from "lit/decorators.js";
17
- import { styleMap as O } from "lit/directives/style-map.js";
11
+ import { TitleCenterController as p, chromeTitleBar as m, closeBox as h, closeKeys as g, widgetLabel as _ } from "../chrome.js";
12
+ import { ScrollStateController as v } from "../scroll-state.js";
13
+ import { ScrollRailController as y, renderScrollRail as b } from "../scroll-rail.js";
14
+ import { VfModalDialog as x, modalDialogStyles as S } from "../modal-dialog.js";
15
+ import { css as C, html as w, nothing as T } from "lit";
16
+ import { property as E, query as D, state as O } from "lit/decorators.js";
17
+ import { styleMap as k } from "lit/directives/style-map.js";
18
18
  //#region src/components/vf-dialog.ts
19
- var k = class extends b {
19
+ var A = class extends x {
20
20
  constructor(...e) {
21
21
  super(...e), this._drag = new f(this, {
22
22
  onDragStart: (e) => {
@@ -34,9 +34,9 @@ var k = class extends b {
34
34
  };
35
35
  },
36
36
  onDrag: (e, t) => this.placeAt(e, t)
37
- }), this._titleCenter = new p(this), this.heading = "", this.label = "", this.closable = !1, this._scrollable = !1, this._scrollState = new _(this, () => this._content, void 0, (e) => {
37
+ }), this._titleCenter = new p(this), this.heading = "", this.label = "", this.closable = !1, this._scrollable = !1, this._scrollState = new v(this, () => this._content, void 0, (e) => {
38
38
  this._scrollable = e.y;
39
- }), this._rail = new v(this, { getScroll: () => this._content });
39
+ }), this._rail = new y(this, { getScroll: () => this._content });
40
40
  }
41
41
  static {
42
42
  this.styles = [
@@ -47,8 +47,8 @@ var k = class extends b {
47
47
  s,
48
48
  c,
49
49
  d,
50
- x,
51
- S`
50
+ S,
51
+ C`
52
52
  :host {
53
53
  display: contents;
54
54
  }
@@ -164,34 +164,34 @@ var k = class extends b {
164
164
  _onBodySlotChange() {
165
165
  this._scrollState.measure(), this._rail.sync();
166
166
  }
167
- _onCloseClick() {
168
- this.close();
167
+ _onCloseClick(e) {
168
+ this.closeFromBox(g(e));
169
169
  }
170
170
  render() {
171
- let e = this.frame === "plain", t = !e && !this.label && this.heading !== "", n = C`
171
+ let e = this.frame === "plain", t = !e && !this.label && this.heading !== "", n = w`
172
172
  <div class="body" part="body">
173
173
  <div
174
174
  class="content vf-scroll"
175
175
  part="content"
176
- tabindex=${this._scrollable ? "0" : w}
177
- role=${this._scrollable ? "group" : w}
176
+ tabindex=${this._scrollable ? "0" : T}
177
+ role=${this._scrollable ? "group" : T}
178
178
  >
179
179
  <slot @slotchange=${this._onBodySlotChange}></slot>
180
180
  </div>
181
- ${y(this._rail, "vertical")}
181
+ ${b(this._rail, "vertical")}
182
182
  </div>
183
183
  `;
184
- return C`
184
+ return w`
185
185
  <dialog
186
- style=${O(this.dialogSize)}
187
- aria-labelledby=${t ? "title" : w}
188
- aria-label=${t ? w : this.label || this.heading || "Dialog"}
186
+ style=${k(this.dialogSize)}
187
+ aria-labelledby=${t ? "title" : T}
188
+ aria-label=${t ? T : this.label || this.heading || "Dialog"}
189
189
  @cancel=${this._onNativeCancel}
190
190
  @close=${this._onNativeClose}
191
191
  >
192
192
  <div class="vf-modal-frame" part="frame">
193
- ${e ? w : m(this._drag, C`
194
- ${this.closable ? h(g("Close", this.heading), this._onCloseClick) : w}
193
+ ${e ? T : m(this._drag, w`
194
+ ${this.closable ? h(_("Close", this.heading), this._onCloseClick) : T}
195
195
  <span class="vf-title" part="title" id="title"
196
196
  >${this.heading}</span
197
197
  >
@@ -202,9 +202,9 @@ var k = class extends b {
202
202
  `;
203
203
  }
204
204
  };
205
- r([T()], k.prototype, "heading", void 0), r([T()], k.prototype, "label", void 0), r([T({
205
+ r([E()], A.prototype, "heading", void 0), r([E()], A.prototype, "label", void 0), r([E({
206
206
  type: Boolean,
207
207
  reflect: !0
208
- })], k.prototype, "closable", void 0), r([T({ reflect: !0 })], k.prototype, "frame", void 0), r([E(".content")], k.prototype, "_content", void 0), r([D()], k.prototype, "_scrollable", void 0), k = r([e("vf-dialog")], k);
208
+ })], A.prototype, "closable", void 0), r([E({ reflect: !0 })], A.prototype, "frame", void 0), r([D(".content")], A.prototype, "_content", void 0), r([O()], A.prototype, "_scrollable", void 0), A = r([e("vf-dialog")], A);
209
209
  //#endregion
210
- export { k as VfDialog };
210
+ export { A as VfDialog };
@@ -127,19 +127,18 @@ var y = class extends r(f) {
127
127
  display: flex;
128
128
  align-items: stretch;
129
129
  height: 100%;
130
- /* 9px of bar before the first title's plate (System 7 put the Apple
131
- plate 9 system px from the screen edge, clear of the 5px corner
132
- mask), plus 5px cancelling the first title's share of the overlap
130
+ /* 9px of bar before the first title's plate, clear of the 5px corner
131
+ mask, plus 4px cancelling the first title's share of the overlap
133
132
  below. */
134
- padding-inline-start: calc(var(--vf-scale, 1) * 14px);
133
+ padding-inline-start: calc(var(--vf-scale, 1) * 13px);
135
134
  }
136
- /* Adjacent title plates OVERLAP by 5 system px: Menus.png spaces title
137
- ink 14px apart while each plate runs 10px left / 9px right of its own
138
- ink, so neighboring plates share a 5px band. A title's plate is its
139
- label box (padding in vf-menu), so the overlap is layout: every menu
140
- pulled 5px into its left neighbor. */
135
+ /* Adjacent title plates OVERLAP by 4 system px: title ink sits 15px
136
+ apart while each plate runs 10px left / 9px right of its own ink, so
137
+ neighboring plates share a 4px band. A title's plate is its label box
138
+ (padding in vf-menu), so the overlap is layout: every menu pulled 4px
139
+ into its left neighbor. */
141
140
  ::slotted(vf-menu) {
142
- margin-inline-start: calc(var(--vf-scale, 1) * -5px);
141
+ margin-inline-start: calc(var(--vf-scale, 1) * -4px);
143
142
  }
144
143
  /* The bar's right end (slot="end"): a clock, say. A row of its own,
145
144
  pushed to the end and held 9px in, mirroring the first title's
@@ -17,14 +17,19 @@ var y = /* @__PURE__ */ new Map([
17
17
  ["⌥", "Alt"],
18
18
  ["⇧", "Shift"],
19
19
  ["⌘", "Meta"]
20
- ]);
21
- function b(e) {
20
+ ]), b = /* @__PURE__ */ new Map([
21
+ ["←", "ArrowLeft"],
22
+ ["↑", "ArrowUp"],
23
+ ["→", "ArrowRight"],
24
+ ["↓", "ArrowDown"]
25
+ ]), x = (e) => b.get(e) ?? e;
26
+ function S(e) {
22
27
  let t = [...e.trim()], n = [];
23
28
  for (; t.length > 0 && y.has(t[0]);) n.push(y.get(t.shift()));
24
29
  let r = t.join("");
25
- return r ? [...n, r].join("+") : "";
30
+ return r ? [...n, x(r)].join("+") : "";
26
31
  }
27
- function x(e, t) {
32
+ function C(e, t) {
28
33
  let n = [...t.trim()], r = {
29
34
  Meta: !1,
30
35
  Control: !1,
@@ -35,9 +40,9 @@ function x(e, t) {
35
40
  let i = n.join("");
36
41
  if (!i || !r.Meta && !r.Control && !r.Alt && [...i].length === 1) return !1;
37
42
  let a = r.Meta ? e.metaKey || e.ctrlKey : !e.metaKey, o = r.Control ? e.ctrlKey : r.Meta || !e.ctrlKey;
38
- return a && o && e.altKey === r.Alt && e.shiftKey === r.Shift && e.key.toLowerCase() === i.toLowerCase();
43
+ return a && o && e.altKey === r.Alt && e.shiftKey === r.Shift && e.key.toLowerCase() === x(i).toLowerCase();
39
44
  }
40
- var S = class extends a(f) {
45
+ var w = class extends a(f) {
41
46
  static {
42
47
  this.styles = [
43
48
  s,
@@ -175,7 +180,7 @@ var S = class extends a(f) {
175
180
  #i;
176
181
  constructor() {
177
182
  super(), this.scale = new r(this), this.disabled = !1, this.checked = !1, this.active = !1, this.checkable = !1, this.shortcut = "", this._blinkPhase = null, this.#t = !1, this.#n = !1, this.#r = this.attachInternals(), this.#i = !1, this.#d = (e) => {
178
- e.defaultPrevented || e.isComposing || this.disabled || !this.shortcut || this.closest("vf-menu[shortcuts], vf-menu-bar[shortcuts]") && x(e, this.shortcut) && (e.preventDefault(), !(e.repeat || this.#t) && (t(this, "vf-menu-flash-request", { item: this }, { composed: !1 }), this.activate()));
183
+ e.defaultPrevented || e.isComposing || this.disabled || !this.shortcut || this.closest("vf-menu[shortcuts], vf-menu-bar[shortcuts]") && C(e, this.shortcut) && (e.preventDefault(), !(e.repeat || this.#t) && (t(this, "vf-menu-flash-request", { item: this }, { composed: !1 }), this.activate()));
179
184
  }, this.addEventListener("keydown", this.#u), this.addEventListener("pointerdown", this.#c), this.addEventListener("click", this.#l);
180
185
  }
181
186
  get #a() {
@@ -191,7 +196,7 @@ var S = class extends a(f) {
191
196
  e.has("disabled") && (this.#r.ariaDisabled = this.disabled ? "true" : null, this.disabled && this.#f()), e.has("checked") && this.checked && (this.#n = !0), (e.has("checked") || e.has("checkable")) && this.#s(), e.has("shortcut") && this.#o();
192
197
  }
193
198
  #o() {
194
- this.#r.ariaKeyShortcuts = b(this.shortcut) || null;
199
+ this.#r.ariaKeyShortcuts = S(this.shortcut) || null;
195
200
  }
196
201
  #s() {
197
202
  this.#a ? (this.#r.role = "menuitemcheckbox", this.#r.ariaChecked = this.checked ? "true" : "false") : (this.#r.role = "menuitem", this.#r.ariaChecked = null);
@@ -257,15 +262,15 @@ var S = class extends a(f) {
257
262
  i([g({
258
263
  type: Boolean,
259
264
  reflect: !0
260
- })], S.prototype, "disabled", void 0), i([g({
265
+ })], w.prototype, "disabled", void 0), i([g({
261
266
  type: Boolean,
262
267
  reflect: !0
263
- })], S.prototype, "checked", void 0), i([g({
268
+ })], w.prototype, "checked", void 0), i([g({
264
269
  type: Boolean,
265
270
  reflect: !0
266
- })], S.prototype, "active", void 0), i([g({
271
+ })], w.prototype, "active", void 0), i([g({
267
272
  type: Boolean,
268
273
  reflect: !0
269
- })], S.prototype, "checkable", void 0), i([g()], S.prototype, "shortcut", void 0), i([g()], S.prototype, "value", void 0), i([_()], S.prototype, "_blinkPhase", void 0), S = i([n("vf-menu-item")], S);
274
+ })], w.prototype, "checkable", void 0), i([g()], w.prototype, "shortcut", void 0), i([g()], w.prototype, "value", void 0), i([_()], w.prototype, "_blinkPhase", void 0), w = i([n("vf-menu-item")], w);
270
275
  //#endregion
271
- export { S as VfMenuItem };
276
+ export { w as VfMenuItem };
@@ -28,9 +28,12 @@ declare const VfMenu_base: (new (...args: any[]) => import("../position.js").VfP
28
28
  *
29
29
  * @slot - Menu contents: `vf-menu-item` and `vf-separator` elements.
30
30
  * @slot label - Replaces the `label` text in the bar — e.g. a `vf-img` apple
31
- * icon for the Apple menu. Keep the `label` attribute set too: it stays the
32
- * menu's accessible name (the bar item's `aria-label` and the panel's) when
33
- * the visible title is an image.
31
+ * icon for the Apple menu. An icon (`vf-img`, `img`, `svg`, `picture` or
32
+ * `canvas`) is drawn in a 16×16 cell and placed for one: 6 system px into
33
+ * its plate, 6 short of the plate's end, on the plate's top row. Text
34
+ * keeps the text title's place. Keep the `label` attribute set too: it stays
35
+ * the menu's accessible name (the bar item's `aria-label` and the panel's)
36
+ * when the visible title is an image.
34
37
  * @csspart label - The menu title in the bar (inverts while open; flashes
35
38
  * when a closed menu's item is activated by its key equivalent).
36
39
  * @csspart panel - The dropped `.vf-panel` containing the items.
@@ -74,6 +77,8 @@ export declare class VfMenu extends VfMenu_base {
74
77
  */
75
78
  barTabIndex: number;
76
79
  private _labelEl;
80
+ /** Whether the title is art — only images in the `label` slot — rather than text. */
81
+ private _artTitle;
77
82
  private _assignedItems;
78
83
  /** The enabled `vf-menu-item` children, in document order. */
79
84
  get items(): VfMenuItem[];