vintage-frames 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -18
- package/custom-elements.json +247 -59
- package/dist/components/vf-menu-bar.d.ts +6 -4
- package/dist/components/vf-menu-bar.js +26 -56
- package/dist/components/vf-menu-item.d.ts +33 -5
- package/dist/components/vf-menu-item.js +128 -61
- package/dist/components/vf-menu.d.ts +35 -0
- package/dist/components/vf-menu.js +171 -111
- package/dist/glyphs.d.ts +6 -0
- package/dist/glyphs.js +18 -14
- package/dist/menu-navigation.d.ts +34 -0
- package/dist/menu-navigation.js +53 -0
- package/dist/menu-press.d.ts +25 -7
- package/dist/menu-press.js +78 -44
- package/dist/motion.d.ts +10 -0
- package/dist/text-control.d.ts +3 -3
- package/docs/SPEC.md +13 -9
- package/editor/vscode.html-custom-data.json +13 -8
- package/editor/web-types.json +51 -15
- package/package.json +4 -34
- package/dist/build/app-file.d.ts +0 -21
- package/dist/build/app-file.js +0 -42
- package/dist/build/box.d.ts +0 -57
- package/dist/build/box.js +0 -93
- package/dist/build/client.d.ts +0 -12
- package/dist/build/frame-picture.d.ts +0 -6
- package/dist/build/frame-picture.js +0 -4
- package/dist/build/frame.d.ts +0 -11
- package/dist/build/frame.js +0 -44
- package/dist/build/index.d.ts +0 -14
- package/dist/build/index.js +0 -4
- package/dist/build/plugins.d.ts +0 -41
- package/dist/build/plugins.js +0 -134
- package/dist/build/png.d.ts +0 -24
- package/dist/build/png.js +0 -116
- package/dist/shell/alert.d.ts +0 -40
- package/dist/shell/alert.js +0 -41
- package/dist/shell/app-file.d.ts +0 -115
- package/dist/shell/app-file.js +0 -189
- package/dist/shell/catalog.d.ts +0 -212
- package/dist/shell/catalog.js +0 -317
- package/dist/shell/clock.d.ts +0 -16
- package/dist/shell/clock.js +0 -36
- package/dist/shell/filing.d.ts +0 -39
- package/dist/shell/filing.js +0 -68
- package/dist/shell/finder.d.ts +0 -179
- package/dist/shell/finder.js +0 -662
- package/dist/shell/geometry.d.ts +0 -203
- package/dist/shell/geometry.js +0 -257
- package/dist/shell/index.d.ts +0 -30
- package/dist/shell/index.js +0 -12
- package/dist/shell/pure.d.ts +0 -13
- package/dist/shell/pure.js +0 -6
- package/dist/shell/shell.d.ts +0 -177
- package/dist/shell/shell.js +0 -272
- package/dist/shell/state.d.ts +0 -88
- package/dist/shell/state.js +0 -103
- package/dist/shell/storage.d.ts +0 -14
- package/dist/shell/storage.js +0 -41
- package/dist/shell/version.d.ts +0 -2
- package/dist/shell/version.js +0 -4
- package/dist/shell/windows.d.ts +0 -278
- package/dist/shell/windows.js +0 -447
- package/dist/styles/body-strike.d.ts +0 -12
- package/dist/styles/body-strike.js +0 -3961
- package/dist/styles/display-strike.d.ts +0 -12
- package/dist/styles/display-strike.js +0 -4343
- package/dist/styles/strike.d.ts +0 -30
|
@@ -8,11 +8,12 @@ import { GridSnapController as o } from "../grid-snap.js";
|
|
|
8
8
|
import { DocumentListenersController as s } from "../document-listeners.js";
|
|
9
9
|
import { SCREEN_CORNER as c, steppedCornerClip as l } from "../pixel-frame.js";
|
|
10
10
|
import { TypeAheadBuffer as u } from "../type-ahead.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
import { navigateMenus as d } from "../menu-navigation.js";
|
|
12
|
+
import { MenuPressController as f } from "../menu-press.js";
|
|
13
|
+
import { LitElement as p, css as m, html as h, unsafeCSS as g } from "lit";
|
|
14
|
+
import { property as _, queryAssignedElements as v, state as y } from "lit/decorators.js";
|
|
14
15
|
//#region src/components/vf-menu-bar.ts
|
|
15
|
-
var
|
|
16
|
+
var b = class extends r(p) {
|
|
16
17
|
constructor(...e) {
|
|
17
18
|
super(...e), this.scale = new t(this), this.gridSnap = new o(this), this.label = "", this.rounded = !1, this.shortcuts = !1, this._hasEnd = !1, this.#e = null, this.#t = this.attachInternals(), this.#n = new u(), this.#r = null, this.#i = new s(this, () => [[
|
|
18
19
|
document,
|
|
@@ -24,7 +25,7 @@ var y = class extends r(f) {
|
|
|
24
25
|
"keydown",
|
|
25
26
|
this.#_,
|
|
26
27
|
!0
|
|
27
|
-
]]), this.#a = new
|
|
28
|
+
]]), this.#a = new f(this, {
|
|
28
29
|
menus: () => this._menus,
|
|
29
30
|
open: (e) => this.#m(e),
|
|
30
31
|
close: () => this.#h()
|
|
@@ -43,39 +44,15 @@ var y = class extends r(f) {
|
|
|
43
44
|
}, this.#g = (e) => {
|
|
44
45
|
e.composedPath().includes(this) || this.#h();
|
|
45
46
|
}, this.#_ = (e) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.#h();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
e.preventDefault(), this.#y(e.key === "ArrowRight" ? 1 : -1);
|
|
56
|
-
break;
|
|
57
|
-
case "ArrowDown":
|
|
58
|
-
case "ArrowUp":
|
|
59
|
-
e.preventDefault(), this.#b(e.key === "ArrowDown" ? 1 : -1);
|
|
60
|
-
break;
|
|
61
|
-
case "Home":
|
|
62
|
-
case "End": {
|
|
63
|
-
e.preventDefault();
|
|
64
|
-
let t = this.#e.items;
|
|
65
|
-
t[e.key === "Home" ? 0 : t.length - 1]?.focus();
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
default: {
|
|
69
|
-
if (e.key.length !== 1 || e.key === " " || e.metaKey || e.ctrlKey || e.altKey) break;
|
|
70
|
-
e.preventDefault();
|
|
71
|
-
let t = this.#e.items, n = t.indexOf(document.activeElement);
|
|
72
|
-
t[this.#n.feed(e.key, n, t.map((e) => ({
|
|
73
|
-
text: e.textContent ?? "",
|
|
74
|
-
disabled: !1
|
|
75
|
-
})))]?.focus();
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
47
|
+
let t = this.#e;
|
|
48
|
+
t && d(e, {
|
|
49
|
+
menu: t,
|
|
50
|
+
typeAhead: this.#n,
|
|
51
|
+
close: (e) => {
|
|
52
|
+
e && t.focus(), this.#h();
|
|
53
|
+
},
|
|
54
|
+
switchMenu: (e) => this.#y(e)
|
|
55
|
+
});
|
|
79
56
|
}, this.#v = (e) => {
|
|
80
57
|
if (this.#e) return;
|
|
81
58
|
let t = this._menus;
|
|
@@ -105,7 +82,7 @@ var y = class extends r(f) {
|
|
|
105
82
|
this.styles = [
|
|
106
83
|
i,
|
|
107
84
|
a,
|
|
108
|
-
|
|
85
|
+
m`
|
|
109
86
|
:host {
|
|
110
87
|
display: block;
|
|
111
88
|
/* 19 white system px over the 1px black rule — Menus.png's bar strip
|
|
@@ -177,11 +154,11 @@ var y = class extends r(f) {
|
|
|
177
154
|
}
|
|
178
155
|
:host([rounded]) .bar::before {
|
|
179
156
|
left: 0;
|
|
180
|
-
clip-path: ${
|
|
157
|
+
clip-path: ${g(l(c, "left"))};
|
|
181
158
|
}
|
|
182
159
|
:host([rounded]) .bar::after {
|
|
183
160
|
right: 0;
|
|
184
|
-
clip-path: ${
|
|
161
|
+
clip-path: ${g(l(c, "right"))};
|
|
185
162
|
}
|
|
186
163
|
`
|
|
187
164
|
];
|
|
@@ -206,7 +183,7 @@ var y = class extends r(f) {
|
|
|
206
183
|
e.has("label") && (this.#t.ariaLabel = this.label || null);
|
|
207
184
|
}
|
|
208
185
|
render() {
|
|
209
|
-
return
|
|
186
|
+
return h`
|
|
210
187
|
<div class="bar vf-snap vf-rule-bottom" part="bar" role="presentation">
|
|
211
188
|
<slot @slotchange=${this.#c}></slot>
|
|
212
189
|
<slot
|
|
@@ -235,11 +212,11 @@ var y = class extends r(f) {
|
|
|
235
212
|
#p;
|
|
236
213
|
#m(e) {
|
|
237
214
|
for (let t of this._menus) t !== e && (t.open = !1);
|
|
238
|
-
e.open = !0, this.#e = e, this.#r = e, this.#n.reset(), this.#l(), this.#i.attach();
|
|
215
|
+
e.open = !0, this.#e = e, this.#r = e, this.#n.reset(), this.#l(), this.#i.attach(), this.#a.track(!0);
|
|
239
216
|
}
|
|
240
217
|
#h() {
|
|
241
218
|
for (let e of this._menus) e.open = !1;
|
|
242
|
-
this.#e = null, this.#n.reset(), this.#i.detach(), this.#l();
|
|
219
|
+
this.#e = null, this.#n.reset(), this.#i.detach(), this.#a.track(!1), this.#l();
|
|
243
220
|
}
|
|
244
221
|
#g;
|
|
245
222
|
#_;
|
|
@@ -250,23 +227,16 @@ var y = class extends r(f) {
|
|
|
250
227
|
let n = t[(t.indexOf(this.#e) + e + t.length) % t.length];
|
|
251
228
|
n && n !== this.#e && (this.#m(n), n.focus());
|
|
252
229
|
}
|
|
253
|
-
#b(e) {
|
|
254
|
-
if (!this.#e) return;
|
|
255
|
-
let t = this.#e.items;
|
|
256
|
-
if (t.length === 0) return;
|
|
257
|
-
let n = t.indexOf(document.activeElement), r;
|
|
258
|
-
r = n < 0 ? e === 1 ? 0 : t.length - 1 : (n + e + t.length) % t.length, t[r]?.focus();
|
|
259
|
-
}
|
|
260
230
|
};
|
|
261
|
-
n([
|
|
231
|
+
n([_()], b.prototype, "label", void 0), n([_({
|
|
262
232
|
type: Boolean,
|
|
263
233
|
reflect: !0
|
|
264
|
-
})],
|
|
234
|
+
})], b.prototype, "rounded", void 0), n([_({
|
|
265
235
|
type: Boolean,
|
|
266
236
|
reflect: !0
|
|
267
|
-
})],
|
|
237
|
+
})], b.prototype, "shortcuts", void 0), n([v({
|
|
268
238
|
selector: "vf-menu",
|
|
269
239
|
flatten: !0
|
|
270
|
-
})],
|
|
240
|
+
})], b.prototype, "_menus", void 0), n([y()], b.prototype, "_hasEnd", void 0), b = n([e("vf-menu-bar")], b);
|
|
271
241
|
//#endregion
|
|
272
|
-
export {
|
|
242
|
+
export { b as VfMenuBar };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
|
+
import type { VfMenu } from './vf-menu.js';
|
|
2
3
|
declare const VfMenuItem_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
|
|
3
4
|
/**
|
|
4
5
|
* `<vf-menu-item>` — a single command inside a `<vf-menu>` panel.
|
|
@@ -10,6 +11,11 @@ declare const VfMenuItem_base: (new (...args: any[]) => import("../position.js")
|
|
|
10
11
|
* 3-blink inversion (~250ms), then dispatches `vf-menu-select` and asks its
|
|
11
12
|
* ancestors to close the menu.
|
|
12
13
|
*
|
|
14
|
+
* A `<vf-menu>` in the `submenu` slot makes the item open a submenu: it ends
|
|
15
|
+
* in ▶ where a shortcut would go, and choosing it opens the submenu beside
|
|
16
|
+
* it rather than firing `vf-menu-select`. The item stays highlighted while
|
|
17
|
+
* its submenu is open.
|
|
18
|
+
*
|
|
13
19
|
* Takes `top`/`left` like every other element ({@link VfPositioned}), for the
|
|
14
20
|
* consumer who wants a row somewhere other than a pulldown. Inside its parent
|
|
15
21
|
* `<vf-menu>` the panel is as wide as its widest row and stacks them in flow,
|
|
@@ -18,10 +24,12 @@ declare const VfMenuItem_base: (new (...args: any[]) => import("../position.js")
|
|
|
18
24
|
* it says — but not how a pulldown is laid out.
|
|
19
25
|
*
|
|
20
26
|
* @slot - The item label.
|
|
27
|
+
* @slot submenu - A `vf-menu`, the submenu the item opens.
|
|
21
28
|
* @csspart item - The row container.
|
|
22
29
|
* @csspart check - The ✓ checkmark glyph (rendered when `checked`).
|
|
23
30
|
* @csspart label - The label wrapper around the default slot.
|
|
24
31
|
* @csspart shortcut - The shortcut text, left-aligned in the shared column.
|
|
32
|
+
* @csspart arrow - The ▶ of an item that opens a submenu.
|
|
25
33
|
* @fires vf-menu-select - After the blink completes. `detail: { value, item }`.
|
|
26
34
|
* Named for the menu rather than plain `vf-select`, which would collide with
|
|
27
35
|
* the `<vf-select>` popup on any delegated ancestor listener (that component
|
|
@@ -46,12 +54,19 @@ export declare class VfMenuItem extends VfMenuItem_base {
|
|
|
46
54
|
/** Shows the classic ✓ checkmark in the left gutter. */
|
|
47
55
|
checked: boolean;
|
|
48
56
|
/**
|
|
49
|
-
* Transient highlight — the full-row inversion the
|
|
50
|
-
*
|
|
51
|
-
* captured by the title the press started on)
|
|
52
|
-
*
|
|
57
|
+
* Transient highlight — the full-row inversion on the row under the pointer
|
|
58
|
+
* while its menu is open, button down or not (`:hover` can't: under touch
|
|
59
|
+
* the pointer is captured by the title the press started on), or on the
|
|
60
|
+
* item whose submenu is open while the pointer is elsewhere. Managed by the
|
|
61
|
+
* menu, mirroring `vf-option[active]`; not part of the authoring API.
|
|
53
62
|
*/
|
|
54
63
|
active: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Whether this item's submenu is open. Reflected, and announced as
|
|
66
|
+
* `aria-expanded`. Managed by the menu ({@link VfMenu.expand}), like
|
|
67
|
+
* {@link active}; not part of the authoring API.
|
|
68
|
+
*/
|
|
69
|
+
expanded: boolean;
|
|
55
70
|
/**
|
|
56
71
|
* Declares the item a *checkable* toggle up front, so it carries
|
|
57
72
|
* `role="menuitemcheckbox"` and `aria-checked="false"` from the first render
|
|
@@ -78,11 +93,21 @@ export declare class VfMenuItem extends VfMenuItem_base {
|
|
|
78
93
|
shortcut: string;
|
|
79
94
|
/**
|
|
80
95
|
* Value reported in the `vf-menu-select` event detail. Defaults to the item's
|
|
81
|
-
*
|
|
96
|
+
* {@link labelText} when unset.
|
|
82
97
|
*/
|
|
83
98
|
value?: string;
|
|
84
99
|
/** `'on' | 'off'` while the selection blink runs, otherwise `null`. */
|
|
85
100
|
private _blinkPhase;
|
|
101
|
+
/** Whether a `vf-menu` sits in the `submenu` slot. */
|
|
102
|
+
private _hasSubmenu;
|
|
103
|
+
/** The submenu this item opens: the `vf-menu` in its `submenu` slot, or null. */
|
|
104
|
+
get submenu(): VfMenu | null;
|
|
105
|
+
/**
|
|
106
|
+
* The item's label as text: what its default slot holds, trimmed, without
|
|
107
|
+
* the rows of a submenu. The default {@link value} and the menus'
|
|
108
|
+
* type-ahead read it, and it names an item that opens a submenu.
|
|
109
|
+
*/
|
|
110
|
+
get labelText(): string;
|
|
86
111
|
constructor();
|
|
87
112
|
connectedCallback(): void;
|
|
88
113
|
disconnectedCallback(): void;
|
|
@@ -95,6 +120,9 @@ export declare class VfMenuItem extends VfMenuItem_base {
|
|
|
95
120
|
* over, which the row's own `click` never sees (a press that started on the
|
|
96
121
|
* title dispatches its click above both of them). No-op while disabled or
|
|
97
122
|
* already blinking.
|
|
123
|
+
*
|
|
124
|
+
* An item that opens a submenu is never chosen: it opens the submenu and
|
|
125
|
+
* moves focus to its first enabled item, as Enter, Space and → do.
|
|
98
126
|
*/
|
|
99
127
|
activate(): void;
|
|
100
128
|
}
|
|
@@ -7,47 +7,47 @@ import { vfDisplay as o } from "../styles/recipes/display-face.js";
|
|
|
7
7
|
import { vfBase as s } from "../styles/recipes/host.js";
|
|
8
8
|
import { releaseAfterGesture as c } from "../document-listeners.js";
|
|
9
9
|
import { runSelectionBlink as l } from "../motion.js";
|
|
10
|
-
import {
|
|
11
|
-
import { LitElement as
|
|
12
|
-
import { property as
|
|
13
|
-
import { classMap as
|
|
10
|
+
import { CARET_RIGHT as u, CHECKMARK as d, glyphSvg as f } from "../glyphs.js";
|
|
11
|
+
import { LitElement as p, css as m, html as h, nothing as g } from "lit";
|
|
12
|
+
import { property as _, state as v } from "lit/decorators.js";
|
|
13
|
+
import { classMap as y } from "lit/directives/class-map.js";
|
|
14
14
|
//#region src/components/vf-menu-item.ts
|
|
15
|
-
var
|
|
15
|
+
var b = /* @__PURE__ */ new Map([
|
|
16
16
|
["⌃", "Control"],
|
|
17
17
|
["⌥", "Alt"],
|
|
18
18
|
["⇧", "Shift"],
|
|
19
19
|
["⌘", "Meta"]
|
|
20
|
-
]),
|
|
20
|
+
]), x = /* @__PURE__ */ new Map([
|
|
21
21
|
["←", "ArrowLeft"],
|
|
22
22
|
["↑", "ArrowUp"],
|
|
23
23
|
["→", "ArrowRight"],
|
|
24
24
|
["↓", "ArrowDown"]
|
|
25
|
-
]),
|
|
26
|
-
function
|
|
25
|
+
]), S = (e) => x.get(e) ?? e;
|
|
26
|
+
function C(e) {
|
|
27
27
|
let t = [...e.trim()], n = [];
|
|
28
|
-
for (; t.length > 0 &&
|
|
28
|
+
for (; t.length > 0 && b.has(t[0]);) n.push(b.get(t.shift()));
|
|
29
29
|
let r = t.join("");
|
|
30
|
-
return r ? [...n,
|
|
30
|
+
return r ? [...n, S(r)].join("+") : "";
|
|
31
31
|
}
|
|
32
|
-
function
|
|
32
|
+
function w(e, t) {
|
|
33
33
|
let n = [...t.trim()], r = {
|
|
34
34
|
Meta: !1,
|
|
35
35
|
Control: !1,
|
|
36
36
|
Alt: !1,
|
|
37
37
|
Shift: !1
|
|
38
38
|
};
|
|
39
|
-
for (; n.length > 0 &&
|
|
39
|
+
for (; n.length > 0 && b.has(n[0]);) r[b.get(n.shift())] = !0;
|
|
40
40
|
let i = n.join("");
|
|
41
41
|
if (!i || !r.Meta && !r.Control && !r.Alt && [...i].length === 1) return !1;
|
|
42
42
|
let a = r.Meta ? e.metaKey || e.ctrlKey : !e.metaKey, o = r.Control ? e.ctrlKey : r.Meta || !e.ctrlKey;
|
|
43
|
-
return a && o && e.altKey === r.Alt && e.shiftKey === r.Shift && e.key.toLowerCase() ===
|
|
43
|
+
return a && o && e.altKey === r.Alt && e.shiftKey === r.Shift && e.key.toLowerCase() === S(i).toLowerCase();
|
|
44
44
|
}
|
|
45
|
-
var
|
|
45
|
+
var T = class extends a(p) {
|
|
46
46
|
static {
|
|
47
47
|
this.styles = [
|
|
48
48
|
s,
|
|
49
49
|
o,
|
|
50
|
-
|
|
50
|
+
m`
|
|
51
51
|
:host {
|
|
52
52
|
display: block;
|
|
53
53
|
cursor: var(--vf-cursor, default);
|
|
@@ -137,15 +137,46 @@ var w = class extends a(f) {
|
|
|
137
137
|
.item.has-shortcut {
|
|
138
138
|
padding-right: calc(var(--vf-scale, 1) * 1px);
|
|
139
139
|
}
|
|
140
|
+
/* An item that opens a submenu ends in ▶ where a shortcut would go: 8px
|
|
141
|
+
in from the row's end, as in Menus.png's submenu rows and a System 7.5
|
|
142
|
+
capture alike, and 2 rows down the 16px row (centered, the odd row
|
|
143
|
+
below). The 8px before it is the label↔▶ minimum, as the shortcut's
|
|
144
|
+
is, and only binds in the row that sets the panel's width. */
|
|
145
|
+
.item.has-submenu {
|
|
146
|
+
padding-right: calc(var(--vf-scale, 1) * 8px);
|
|
147
|
+
}
|
|
148
|
+
.arrow {
|
|
149
|
+
flex: none;
|
|
150
|
+
align-self: flex-start;
|
|
151
|
+
display: block;
|
|
152
|
+
margin: calc(var(--vf-scale, 1) * 2px) 0 0 calc(var(--vf-scale, 1) * 8px);
|
|
153
|
+
}
|
|
154
|
+
.arrow svg {
|
|
155
|
+
display: block;
|
|
156
|
+
width: calc(var(--vf-scale, 1) * 6px);
|
|
157
|
+
height: calc(var(--vf-scale, 1) * 11px);
|
|
158
|
+
}
|
|
159
|
+
/* What the submenu hangs from: a box as wide as the row at the row's
|
|
160
|
+
top, which the submenu's panel places itself against (vf-menu). Out
|
|
161
|
+
of flow, so the submenu never adds to its parent panel's width. */
|
|
162
|
+
.submenu {
|
|
163
|
+
position: absolute;
|
|
164
|
+
top: 0;
|
|
165
|
+
left: 0;
|
|
166
|
+
right: 0;
|
|
167
|
+
}
|
|
140
168
|
:host([disabled]) .item {
|
|
141
169
|
color: var(--vf-disabled, #c0c0c0);
|
|
142
170
|
}
|
|
143
|
-
/* Highlight = full-width inversion (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
171
|
+
/* Highlight = full-width inversion (the menu's [active], keyboard
|
|
172
|
+
focus, blink "on"; hover only for a row outside a menu). Inside a
|
|
173
|
+
menu the pointer's row is the menu's to say, since the item whose
|
|
174
|
+
submenu is open stays lit while the pointer is in the submenu, and
|
|
175
|
+
:hover would light a second row. blink-on is scoped to the enabled
|
|
176
|
+
host like its siblings: an item disabled mid-blink has its timer
|
|
177
|
+
cancelled (see updated()), and this keeps it from flashing even for
|
|
178
|
+
the frame before that lands. */
|
|
179
|
+
:host(:not([disabled])) .item:not(.in-menu):hover,
|
|
149
180
|
:host(:not([disabled])[active]) .item,
|
|
150
181
|
:host(:not([disabled]):focus) .item,
|
|
151
182
|
:host(:not([disabled])) .item.blink-on {
|
|
@@ -173,84 +204,117 @@ var w = class extends a(f) {
|
|
|
173
204
|
`
|
|
174
205
|
];
|
|
175
206
|
}
|
|
207
|
+
get submenu() {
|
|
208
|
+
for (let e of this.children) if (e.localName === "vf-menu" && e.slot === "submenu") return e;
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
get labelText() {
|
|
212
|
+
let e = "";
|
|
213
|
+
for (let t of this.childNodes) t instanceof Element ? t.slot || (e += t.textContent ?? "") : t.nodeType === Node.TEXT_NODE && (e += t.textContent ?? "");
|
|
214
|
+
return e.trim();
|
|
215
|
+
}
|
|
176
216
|
#e;
|
|
177
217
|
#t;
|
|
178
218
|
#n;
|
|
179
219
|
#r;
|
|
180
220
|
#i;
|
|
181
221
|
constructor() {
|
|
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.#
|
|
183
|
-
|
|
184
|
-
|
|
222
|
+
super(), this.scale = new r(this), this.disabled = !1, this.checked = !1, this.active = !1, this.expanded = !1, this.checkable = !1, this.shortcut = "", this._blinkPhase = null, this._hasSubmenu = !1, this.#t = !1, this.#n = !1, this.#r = this.attachInternals(), this.#i = !1, this.#s = () => {
|
|
223
|
+
let e = this._hasSubmenu;
|
|
224
|
+
this.#r.ariaHasPopup = e ? "menu" : null, this.#r.ariaExpanded = e ? String(this.expanded) : null, this.#r.ariaLabel = e && this.labelText || null;
|
|
225
|
+
}, this.#c = () => {
|
|
226
|
+
this._hasSubmenu = this.submenu !== null;
|
|
227
|
+
}, this.#m = (e) => {
|
|
228
|
+
e.defaultPrevented || e.isComposing || this.disabled || !this.shortcut || this._hasSubmenu || this.closest("vf-menu[shortcuts], vf-menu-bar[shortcuts]") && w(e, this.shortcut) && (e.preventDefault(), !(e.repeat || this.#t) && (t(this, "vf-menu-flash-request", { item: this }, { composed: !1 }), this.activate()));
|
|
229
|
+
}, this.addEventListener("keydown", this.#p), this.addEventListener("pointerdown", this.#d), this.addEventListener("click", this.#f);
|
|
185
230
|
}
|
|
186
231
|
get #a() {
|
|
187
232
|
return this.checkable || this.#n;
|
|
188
233
|
}
|
|
189
234
|
connectedCallback() {
|
|
190
|
-
super.connectedCallback(), this.#
|
|
235
|
+
super.connectedCallback(), this._hasSubmenu = this.submenu !== null, this.#u(), this.#o(), this.#s(), this.requestUpdate(), this.hasAttribute("tabindex") || (this.tabIndex = -1), document.addEventListener("keydown", this.#m);
|
|
191
236
|
}
|
|
192
237
|
disconnectedCallback() {
|
|
193
|
-
super.disconnectedCallback(), document.removeEventListener("keydown", this.#
|
|
238
|
+
super.disconnectedCallback(), document.removeEventListener("keydown", this.#m), this.#h();
|
|
194
239
|
}
|
|
195
240
|
updated(e) {
|
|
196
|
-
e.has("disabled") && (this.#r.ariaDisabled = this.disabled ? "true" : null, this.disabled && this.#
|
|
241
|
+
e.has("disabled") && (this.#r.ariaDisabled = this.disabled ? "true" : null, this.disabled && this.#h()), e.has("checked") && this.checked && (this.#n = !0), (e.has("checked") || e.has("checkable")) && this.#u(), (e.has("shortcut") || e.has("_hasSubmenu")) && this.#o(), (e.has("expanded") || e.has("_hasSubmenu")) && this.#s();
|
|
197
242
|
}
|
|
198
243
|
#o() {
|
|
199
|
-
this.#r.ariaKeyShortcuts =
|
|
244
|
+
this.#r.ariaKeyShortcuts = !this._hasSubmenu && C(this.shortcut) || null;
|
|
245
|
+
}
|
|
246
|
+
#s;
|
|
247
|
+
#c;
|
|
248
|
+
#l(e) {
|
|
249
|
+
let t = this.submenu;
|
|
250
|
+
return t !== null && e.composedPath().includes(t);
|
|
200
251
|
}
|
|
201
|
-
#
|
|
252
|
+
#u() {
|
|
202
253
|
this.#a ? (this.#r.role = "menuitemcheckbox", this.#r.ariaChecked = this.checked ? "true" : "false") : (this.#r.role = "menuitem", this.#r.ariaChecked = null);
|
|
203
254
|
}
|
|
204
255
|
render() {
|
|
205
|
-
let e = {
|
|
256
|
+
let e = this._hasSubmenu, t = {
|
|
206
257
|
item: !0,
|
|
207
|
-
"
|
|
258
|
+
"in-menu": this.closest("vf-menu") !== null,
|
|
259
|
+
"has-shortcut": !e && this.shortcut !== "",
|
|
260
|
+
"has-submenu": e,
|
|
208
261
|
"blink-on": this._blinkPhase === "on",
|
|
209
262
|
"blink-off": this._blinkPhase === "off"
|
|
210
263
|
};
|
|
211
|
-
return
|
|
212
|
-
<div class=${
|
|
213
|
-
${this.checked ?
|
|
214
|
-
>${d
|
|
215
|
-
>` :
|
|
216
|
-
<span class="label" part="label"><slot></slot></span>
|
|
217
|
-
${
|
|
218
|
-
>${
|
|
219
|
-
>` : h
|
|
264
|
+
return h`
|
|
265
|
+
<div class=${y(t)} part="item">
|
|
266
|
+
${this.checked ? h`<span class="check" part="check" aria-hidden="true"
|
|
267
|
+
>${f(d, "checkmark")}</span
|
|
268
|
+
>` : g}
|
|
269
|
+
<span class="label" part="label"><slot @slotchange=${this.#s}></slot></span>
|
|
270
|
+
${e ? h`<span class="arrow" part="arrow" aria-hidden="true"
|
|
271
|
+
>${f(u, "caret")}</span
|
|
272
|
+
>` : this.shortcut ? h`<span class="shortcut" part="shortcut" aria-hidden="true"
|
|
273
|
+
>${this.shortcut}</span
|
|
274
|
+
>` : g}
|
|
275
|
+
<div class="submenu">
|
|
276
|
+
<slot name="submenu" @slotchange=${this.#c}></slot>
|
|
277
|
+
</div>
|
|
220
278
|
</div>
|
|
221
279
|
`;
|
|
222
280
|
}
|
|
223
|
-
#
|
|
224
|
-
this.#i = this.closest("vf-menu") !== null, this.#i && c(() => {
|
|
281
|
+
#d(e) {
|
|
282
|
+
this.#l(e) || (this.#i = this.closest("vf-menu") !== null, this.#i && c(() => {
|
|
225
283
|
this.#i = !1;
|
|
226
|
-
});
|
|
284
|
+
}));
|
|
227
285
|
}
|
|
228
|
-
#
|
|
229
|
-
if (this.#
|
|
230
|
-
this.#i
|
|
231
|
-
|
|
286
|
+
#f(t) {
|
|
287
|
+
if (!this.#l(t)) {
|
|
288
|
+
if (this.#i) {
|
|
289
|
+
this.#i = !1;
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
e(this, t, () => this.activate());
|
|
232
293
|
}
|
|
233
|
-
e(this, t, () => this.activate());
|
|
234
294
|
}
|
|
235
|
-
#
|
|
236
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), this.activate());
|
|
295
|
+
#p(e) {
|
|
296
|
+
this.#l(e) || (e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), this.activate());
|
|
237
297
|
}
|
|
238
|
-
#
|
|
298
|
+
#m;
|
|
239
299
|
activate() {
|
|
240
300
|
if (this.disabled || this.#t) return;
|
|
301
|
+
if (this._hasSubmenu) {
|
|
302
|
+
this.closest("vf-menu")?.expand(this, { focus: !0 });
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
241
305
|
this.#t = !0;
|
|
242
306
|
let e = l((e) => {
|
|
243
307
|
this._blinkPhase = e ? "on" : "off";
|
|
244
308
|
}, () => {
|
|
245
|
-
this._blinkPhase = null, this.#t = !1, this.#e = void 0, this.#
|
|
309
|
+
this._blinkPhase = null, this.#t = !1, this.#e = void 0, this.#g();
|
|
246
310
|
});
|
|
247
311
|
this.#t && (this.#e = e);
|
|
248
312
|
}
|
|
249
|
-
#
|
|
313
|
+
#h() {
|
|
250
314
|
this.#t && (this.#e?.cancel(), this.#e = void 0, this.#t = !1, this._blinkPhase = null);
|
|
251
315
|
}
|
|
252
|
-
#
|
|
253
|
-
let e = this.value ??
|
|
316
|
+
#g() {
|
|
317
|
+
let e = this.value ?? this.labelText;
|
|
254
318
|
t(this, "vf-menu-select", {
|
|
255
319
|
value: e,
|
|
256
320
|
item: this
|
|
@@ -259,18 +323,21 @@ var w = class extends a(f) {
|
|
|
259
323
|
(!n || n.hasAttribute("open")) && t(this, "vf-menu-close-request", { item: this }, { composed: !1 });
|
|
260
324
|
}
|
|
261
325
|
};
|
|
262
|
-
i([
|
|
326
|
+
i([_({
|
|
327
|
+
type: Boolean,
|
|
328
|
+
reflect: !0
|
|
329
|
+
})], T.prototype, "disabled", void 0), i([_({
|
|
263
330
|
type: Boolean,
|
|
264
331
|
reflect: !0
|
|
265
|
-
})],
|
|
332
|
+
})], T.prototype, "checked", void 0), i([_({
|
|
266
333
|
type: Boolean,
|
|
267
334
|
reflect: !0
|
|
268
|
-
})],
|
|
335
|
+
})], T.prototype, "active", void 0), i([_({
|
|
269
336
|
type: Boolean,
|
|
270
337
|
reflect: !0
|
|
271
|
-
})],
|
|
338
|
+
})], T.prototype, "expanded", void 0), i([_({
|
|
272
339
|
type: Boolean,
|
|
273
340
|
reflect: !0
|
|
274
|
-
})],
|
|
341
|
+
})], T.prototype, "checkable", void 0), i([_()], T.prototype, "shortcut", void 0), i([_()], T.prototype, "value", void 0), i([v()], T.prototype, "_blinkPhase", void 0), i([v()], T.prototype, "_hasSubmenu", void 0), T = i([n("vf-menu-item")], T);
|
|
275
342
|
//#endregion
|
|
276
|
-
export {
|
|
343
|
+
export { T as VfMenuItem };
|
|
@@ -17,6 +17,16 @@ declare const VfMenu_base: (new (...args: any[]) => import("../position.js").VfP
|
|
|
17
17
|
* onto a command, release over it) and a modern quick tap that leaves the menu
|
|
18
18
|
* dropped for a second click.
|
|
19
19
|
*
|
|
20
|
+
* A `vf-menu` in a `vf-menu-item`'s `submenu` slot is a **submenu**: no title,
|
|
21
|
+
* only its panel, opened beside its item by the menu holding the item
|
|
22
|
+
* ({@link expand}). The pointer resting on the item opens it in either style,
|
|
23
|
+
* and so do a click or tap on the item, →, Enter and Space. It overlaps its
|
|
24
|
+
* parent as System 7.5's did: its first row level with its item, its frame
|
|
25
|
+
* 5px inside the parent's right edge, covering the parent's frame and
|
|
26
|
+
* shadow. It opens on the side its parent opened toward, the right first,
|
|
27
|
+
* flips where that side has no room, and moves up to fit the screen. Menus
|
|
28
|
+
* nest to any depth.
|
|
29
|
+
*
|
|
20
30
|
* Takes `top`/`left` like every other element ({@link VfPositioned}) — the
|
|
21
31
|
* natural fit being a standalone menu, which is a free-standing menu button and
|
|
22
32
|
* places like any other control. The panel is anchored to the host's own box
|
|
@@ -95,6 +105,31 @@ export declare class VfMenu extends VfMenu_base {
|
|
|
95
105
|
* src/menu-press.ts), so it wants the box, not the element.
|
|
96
106
|
*/
|
|
97
107
|
get labelRect(): DOMRect | null;
|
|
108
|
+
private _panelEl;
|
|
109
|
+
/**
|
|
110
|
+
* Viewport rect of the dropped panel, or `null` while closed. The press
|
|
111
|
+
* gesture hit-tests the open menus by their panels, deepest first.
|
|
112
|
+
*/
|
|
113
|
+
get panelRect(): DOMRect | null;
|
|
114
|
+
/** The item in this menu whose submenu is open, or `null`. */
|
|
115
|
+
get expandedItem(): VfMenuItem | null;
|
|
116
|
+
/**
|
|
117
|
+
* Opens `item`'s submenu, closing the one open in this menu and everything
|
|
118
|
+
* under it; `null` closes it. With `focus`, keyboard focus goes on to the
|
|
119
|
+
* submenu's first enabled item. The press gesture, the keyboard and an
|
|
120
|
+
* item's `activate()` all open submenus through here. Does nothing while
|
|
121
|
+
* this menu is closed, or for a disabled item or one without a submenu.
|
|
122
|
+
*/
|
|
123
|
+
expand(item: VfMenuItem | null, options?: {
|
|
124
|
+
focus?: boolean;
|
|
125
|
+
}): void;
|
|
126
|
+
/**
|
|
127
|
+
* Where the pointer is, from the press gesture: on `row` of this menu's
|
|
128
|
+
* panel, on none of its rows (`null`), or not in its panel (`undefined`).
|
|
129
|
+
* The row under the pointer is highlighted; with the pointer elsewhere, the
|
|
130
|
+
* item whose submenu is open is. Not part of the authoring API.
|
|
131
|
+
*/
|
|
132
|
+
pointerOver(row: VfMenuItem | null | undefined): void;
|
|
98
133
|
/** `true` while the key-equivalent flash paints the title inverted. */
|
|
99
134
|
private _flashOn;
|
|
100
135
|
connectedCallback(): void;
|