vintage-frames 0.14.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/custom-elements.json +770 -74
  2. package/dist/chrome.d.ts +10 -1
  3. package/dist/chrome.js +8 -3
  4. package/dist/components/vf-button.d.ts +5 -1
  5. package/dist/components/vf-button.js +1 -1
  6. package/dist/components/vf-desktop.d.ts +5 -2
  7. package/dist/components/vf-desktop.js +5 -5
  8. package/dist/components/vf-dialog.d.ts +13 -2
  9. package/dist/components/vf-dialog.js +27 -27
  10. package/dist/components/vf-menu-bar.js +9 -10
  11. package/dist/components/vf-menu-item.js +18 -13
  12. package/dist/components/vf-menu.d.ts +8 -3
  13. package/dist/components/vf-menu.js +85 -61
  14. package/dist/components/vf-number-field.d.ts +4 -0
  15. package/dist/components/vf-number-field.js +28 -25
  16. package/dist/components/vf-paragraph.d.ts +3 -1
  17. package/dist/components/vf-paragraph.js +7 -0
  18. package/dist/components/vf-scroll-area.d.ts +16 -1
  19. package/dist/components/vf-scroll-area.js +39 -29
  20. package/dist/components/vf-select.d.ts +5 -4
  21. package/dist/components/vf-select.js +26 -17
  22. package/dist/components/vf-text-field.d.ts +5 -5
  23. package/dist/components/vf-text-field.js +1 -1
  24. package/dist/components/vf-window.d.ts +22 -5
  25. package/dist/components/vf-window.js +113 -98
  26. package/dist/cursor.d.ts +8 -0
  27. package/dist/cursor.js +70 -73
  28. package/dist/events.d.ts +3 -2
  29. package/dist/events.js +3 -3
  30. package/dist/index.d.ts +2 -1
  31. package/dist/modal-dialog.d.ts +49 -4
  32. package/dist/modal-dialog.js +115 -87
  33. package/dist/position.js +25 -20
  34. package/dist/shell/alert.d.ts +17 -9
  35. package/dist/shell/alert.js +25 -28
  36. package/dist/shell/catalog.d.ts +1 -1
  37. package/dist/shell/catalog.js +32 -18
  38. package/dist/shell/finder.d.ts +46 -1
  39. package/dist/shell/finder.js +166 -126
  40. package/dist/shell/index.d.ts +2 -4
  41. package/dist/shell/index.js +5 -6
  42. package/dist/shell/pure.d.ts +10 -0
  43. package/dist/shell/pure.js +4 -0
  44. package/dist/shell/shell.d.ts +40 -13
  45. package/dist/shell/shell.js +87 -51
  46. package/dist/shell/windows.d.ts +69 -12
  47. package/dist/shell/windows.js +245 -144
  48. package/dist/text-control.d.ts +30 -1
  49. package/dist/text-control.js +27 -6
  50. package/dist/top-layer.d.ts +13 -0
  51. package/dist/top-layer.js +16 -0
  52. package/docs/SPEC.md +25 -24
  53. package/editor/vscode.html-custom-data.json +22 -12
  54. package/editor/web-types.json +58 -25
  55. 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 };
@@ -75,7 +75,11 @@ export declare class VfButton extends VfButton_base {
75
75
  type: 'button' | 'submit' | 'reset';
76
76
  /** Form field name; submitted as `name=value` when `type="submit"`. */
77
77
  name: string;
78
- /** Value submitted under `name` when `type="submit"`. */
78
+ /**
79
+ * Value submitted under `name` when `type="submit"`. In a
80
+ * `<form method="dialog">` inside a `vf-dialog`, the dialog's answer
81
+ * (`returnValue`), with or without a `name`.
82
+ */
79
83
  value: string;
80
84
  /**
81
85
  * The submission overrides native `<button>` carries, honored on
@@ -253,7 +253,7 @@ var S = "vf-submitter", C = class extends i(h) {
253
253
  let e = this.resolvedType;
254
254
  if (!this.internals.form || e === "button" || this.isDisabled) return;
255
255
  let t = document.createElement("button");
256
- t.type = e, t.slot = S, t.addEventListener("click", (e) => e.stopPropagation()), e === "submit" && (this.name && (t.name = this.name, t.value = this.value), this.formAction && (t.formAction = this.formAction), this.formEnctype && (t.formEnctype = this.formEnctype), this.formMethod && (t.formMethod = this.formMethod), this.formTarget && (t.formTarget = this.formTarget), t.formNoValidate = this.formNoValidate), this.#e = !0;
256
+ t.type = e, t.slot = S, t.addEventListener("click", (e) => e.stopPropagation()), e === "submit" && (this.name && (t.name = this.name), t.value = this.value, this.formAction && (t.formAction = this.formAction), this.formEnctype && (t.formEnctype = this.formEnctype), this.formMethod && (t.formMethod = this.formMethod), this.formTarget && (t.formTarget = this.formTarget), t.formNoValidate = this.formNoValidate), this.#e = !0;
257
257
  try {
258
258
  this.append(t), t.click();
259
259
  } finally {
@@ -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 };
@@ -25,6 +25,11 @@ import { VfModalDialog } from '../modal-dialog.js';
25
25
  * closes it too, with `{ reason: 'outside' }` — for the About box; off by
26
26
  * default, since the classic modal ignored an outside click.
27
27
  *
28
+ * Answers: a `<form method="dialog">` inside it closes it with the
29
+ * submitting button's `value` as `returnValue`, and `close(value)` does the
30
+ * same. `vf-close` carries it as `detail.returnValue`, null when the close
31
+ * carried none (Escape, a click outside, the close box).
32
+ *
28
33
  * Keyboard, the classic Dialog Manager's two rules ({@link VfModalDialog}):
29
34
  * on open, focus goes to the first text-entry control — a slotted control
30
35
  * with `autofocus` first — or, with none, to the default button
@@ -48,8 +53,13 @@ import { VfModalDialog } from '../modal-dialog.js';
48
53
  * @csspart content - The scrolling region inside the body (the slotted
49
54
  * content). Inert while the content fits; over-stuffed, it scrolls under a
50
55
  * System 7 rail and becomes a keyboard stop.
56
+ * @fires vf-show - Dialog opened, placed and given its initial focus. Detail
57
+ * `{ focus }`, the element focused: the moment to select a field's default
58
+ * text (`select()`) or measure copy that varies.
51
59
  * @fires vf-close - Dialog closed. Detail `{ reason: 'escape' | 'close' |
52
- * 'outside' }` — `'outside'` only under `light-dismiss`.
60
+ * 'outside', returnValue: string | null }` — `'outside'` only under
61
+ * `light-dismiss` — plus `altKey`, `shiftKey`, `metaKey` and `ctrlKey`
62
+ * when the close box closed it.
53
63
  * @cssprop --vf-dots-pattern - the windoid bar's dot-grid dither — a 2×2 tile,
54
64
  * one black pixel at the origin (`vfDots`; override the whole pattern like
55
65
  * `--vf-desktop-pattern`)
@@ -87,7 +97,8 @@ export declare class VfDialog extends VfModalDialog {
87
97
  /**
88
98
  * Show the close box (left side of the title bar). Off by default — the
89
99
  * bare movable-modal bar. Ignored with `frame="plain"` (no bar). Clicking
90
- * it closes the dialog and fires `vf-close` with `{ reason: 'close' }`.
100
+ * it closes the dialog and fires `vf-close` with `{ reason: 'close' }` and
101
+ * the modifier keys held on the click, as `vf-window`'s close box does.
91
102
  */
92
103
  closable: boolean;
93
104
  /**
@@ -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[];