vintage-frames 0.1.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/LICENSE +21 -0
- package/README.md +262 -0
- package/custom-elements.json +19807 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js +9 -0
- package/dist/chrome.d.ts +73 -0
- package/dist/chrome.js +94 -0
- package/dist/components/vf-button-group.d.ts +50 -0
- package/dist/components/vf-button-group.js +68 -0
- package/dist/components/vf-button.d.ts +169 -0
- package/dist/components/vf-button.js +234 -0
- package/dist/components/vf-checkbox.d.ts +60 -0
- package/dist/components/vf-checkbox.js +135 -0
- package/dist/components/vf-container.d.ts +95 -0
- package/dist/components/vf-container.js +86 -0
- package/dist/components/vf-desktop.d.ts +243 -0
- package/dist/components/vf-desktop.js +310 -0
- package/dist/components/vf-dialog.d.ts +105 -0
- package/dist/components/vf-dialog.js +280 -0
- package/dist/components/vf-fieldset.d.ts +34 -0
- package/dist/components/vf-fieldset.js +76 -0
- package/dist/components/vf-grid.d.ts +124 -0
- package/dist/components/vf-grid.js +133 -0
- package/dist/components/vf-icon.d.ts +356 -0
- package/dist/components/vf-icon.js +507 -0
- package/dist/components/vf-img.d.ts +63 -0
- package/dist/components/vf-img.js +65 -0
- package/dist/components/vf-label.d.ts +117 -0
- package/dist/components/vf-label.js +151 -0
- package/dist/components/vf-list-item.d.ts +48 -0
- package/dist/components/vf-list-item.js +98 -0
- package/dist/components/vf-list.d.ts +77 -0
- package/dist/components/vf-list.js +256 -0
- package/dist/components/vf-menu-bar.d.ts +64 -0
- package/dist/components/vf-menu-bar.js +236 -0
- package/dist/components/vf-menu-item.d.ts +91 -0
- package/dist/components/vf-menu-item.js +252 -0
- package/dist/components/vf-menu.d.ts +95 -0
- package/dist/components/vf-menu.js +346 -0
- package/dist/components/vf-number-field.d.ts +60 -0
- package/dist/components/vf-number-field.js +248 -0
- package/dist/components/vf-option.d.ts +49 -0
- package/dist/components/vf-option.js +119 -0
- package/dist/components/vf-paragraph.d.ts +73 -0
- package/dist/components/vf-paragraph.js +66 -0
- package/dist/components/vf-progress-bar.d.ts +69 -0
- package/dist/components/vf-progress-bar.js +272 -0
- package/dist/components/vf-radio-group.d.ts +109 -0
- package/dist/components/vf-radio-group.js +105 -0
- package/dist/components/vf-radio.d.ts +59 -0
- package/dist/components/vf-radio.js +135 -0
- package/dist/components/vf-scroll-area.d.ts +75 -0
- package/dist/components/vf-scroll-area.js +124 -0
- package/dist/components/vf-select.d.ts +334 -0
- package/dist/components/vf-select.js +658 -0
- package/dist/components/vf-separator.d.ts +38 -0
- package/dist/components/vf-separator.js +55 -0
- package/dist/components/vf-slider.d.ts +80 -0
- package/dist/components/vf-slider.js +255 -0
- package/dist/components/vf-stack.d.ts +188 -0
- package/dist/components/vf-stack.js +168 -0
- package/dist/components/vf-swatch.d.ts +98 -0
- package/dist/components/vf-swatch.js +201 -0
- package/dist/components/vf-text-area.d.ts +77 -0
- package/dist/components/vf-text-area.js +121 -0
- package/dist/components/vf-text-field.d.ts +53 -0
- package/dist/components/vf-text-field.js +79 -0
- package/dist/components/vf-window.d.ts +157 -0
- package/dist/components/vf-window.js +377 -0
- package/dist/cursor-art.d.ts +37 -0
- package/dist/cursor-art.js +41 -0
- package/dist/cursor.d.ts +49 -0
- package/dist/cursor.js +171 -0
- package/dist/define.d.ts +45 -0
- package/dist/define.js +15 -0
- package/dist/document-listeners.d.ts +62 -0
- package/dist/document-listeners.js +29 -0
- package/dist/drag.d.ts +49 -0
- package/dist/drag.js +30 -0
- package/dist/events.d.ts +79 -0
- package/dist/events.js +25 -0
- package/dist/focus-modality.d.ts +94 -0
- package/dist/focus-modality.js +56 -0
- package/dist/form-control.d.ts +247 -0
- package/dist/form-control.js +127 -0
- package/dist/glyphs.d.ts +117 -0
- package/dist/glyphs.js +100 -0
- package/dist/grid-snap.d.ts +73 -0
- package/dist/grid-snap.js +135 -0
- package/dist/index.d.ts +145 -0
- package/dist/index.js +71 -0
- package/dist/menu-press.d.ts +60 -0
- package/dist/menu-press.js +97 -0
- package/dist/modal-dialog.d.ts +148 -0
- package/dist/modal-dialog.js +155 -0
- package/dist/motion.d.ts +72 -0
- package/dist/motion.js +22 -0
- package/dist/number.d.ts +24 -0
- package/dist/number.js +12 -0
- package/dist/open-art.d.ts +40 -0
- package/dist/open-art.js +35 -0
- package/dist/pixel-frame.d.ts +102 -0
- package/dist/pixel-frame.js +77 -0
- package/dist/popup-overflow.d.ts +157 -0
- package/dist/popup-overflow.js +45 -0
- package/dist/position.d.ts +187 -0
- package/dist/position.js +74 -0
- package/dist/scale.d.ts +259 -0
- package/dist/scale.js +133 -0
- package/dist/scroll-rail.d.ts +112 -0
- package/dist/scroll-rail.js +194 -0
- package/dist/scroll-state.d.ts +113 -0
- package/dist/scroll-state.js +55 -0
- package/dist/size.d.ts +47 -0
- package/dist/size.js +30 -0
- package/dist/styles/base.d.ts +38 -0
- package/dist/styles/body-font.d.ts +7 -0
- package/dist/styles/body-font.js +9 -0
- package/dist/styles/display-font.d.ts +7 -0
- package/dist/styles/display-font.js +9 -0
- package/dist/styles/recipes/body-face.d.ts +14 -0
- package/dist/styles/recipes/body-face.js +6 -0
- package/dist/styles/recipes/display-face.d.ts +23 -0
- package/dist/styles/recipes/display-face.js +10 -0
- package/dist/styles/recipes/field.d.ts +20 -0
- package/dist/styles/recipes/field.js +68 -0
- package/dist/styles/recipes/focus.d.ts +76 -0
- package/dist/styles/recipes/focus.js +39 -0
- package/dist/styles/recipes/host.d.ts +5 -0
- package/dist/styles/recipes/host.js +62 -0
- package/dist/styles/recipes/pattern.d.ts +80 -0
- package/dist/styles/recipes/pattern.js +82 -0
- package/dist/styles/recipes/scroll-rail.d.ts +69 -0
- package/dist/styles/recipes/scroll-rail.js +222 -0
- package/dist/styles/recipes/shadow.d.ts +13 -0
- package/dist/styles/recipes/shadow.js +5 -0
- package/dist/styles/recipes/static-text.d.ts +24 -0
- package/dist/styles/recipes/static-text.js +17 -0
- package/dist/styles/recipes/surface.d.ts +28 -0
- package/dist/styles/recipes/surface.js +27 -0
- package/dist/styles/recipes/tile.d.ts +122 -0
- package/dist/styles/recipes/tile.js +40 -0
- package/dist/styles/recipes/title-bar.d.ts +49 -0
- package/dist/styles/recipes/title-bar.js +134 -0
- package/dist/styles/recipes/toggle.d.ts +10 -0
- package/dist/styles/recipes/toggle.js +20 -0
- package/dist/styles/register-embedded-font.d.ts +64 -0
- package/dist/styles/register-embedded-font.js +30 -0
- package/dist/text-control.d.ts +131 -0
- package/dist/text-control.js +83 -0
- package/dist/tile-grid.d.ts +111 -0
- package/dist/tile-grid.js +53 -0
- package/dist/toggle-control.d.ts +60 -0
- package/dist/toggle-control.js +41 -0
- package/dist/track-width.d.ts +42 -0
- package/dist/track-width.js +30 -0
- package/dist/type-ahead.d.ts +35 -0
- package/dist/type-ahead.js +20 -0
- package/dist/zoom.d.ts +204 -0
- package/dist/zoom.js +105 -0
- package/docs/SPEC.md +2471 -0
- package/editor/vscode.html-custom-data.json +1320 -0
- package/editor/web-types.json +3237 -0
- package/package.json +118 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { vfElement as e } from "../define.js";
|
|
2
|
+
import { ScaleController as t } from "../scale.js";
|
|
3
|
+
import n from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
|
|
4
|
+
import { vfDisplay as r } from "../styles/recipes/display-face.js";
|
|
5
|
+
import { vfBase as i } from "../styles/recipes/host.js";
|
|
6
|
+
import { releaseAfterGesture as a } from "../document-listeners.js";
|
|
7
|
+
import { deferActivation as o, emit as s } from "../events.js";
|
|
8
|
+
import { runSelectionBlink as c } from "../motion.js";
|
|
9
|
+
import { CHECKMARK as l, glyphSvg as u } from "../glyphs.js";
|
|
10
|
+
import { LitElement as d, css as f, html as p, nothing as m } from "lit";
|
|
11
|
+
import { property as h, state as g } from "lit/decorators.js";
|
|
12
|
+
import { classMap as _ } from "lit/directives/class-map.js";
|
|
13
|
+
//#region src/components/vf-menu-item.ts
|
|
14
|
+
var v = /* @__PURE__ */ new Map([
|
|
15
|
+
["⌃", "Control"],
|
|
16
|
+
["⌥", "Alt"],
|
|
17
|
+
["⇧", "Shift"],
|
|
18
|
+
["⌘", "Meta"]
|
|
19
|
+
]);
|
|
20
|
+
function y(e) {
|
|
21
|
+
let t = [...e.trim()], n = [];
|
|
22
|
+
for (; t.length > 0 && v.has(t[0]);) n.push(v.get(t.shift()));
|
|
23
|
+
let r = t.join("");
|
|
24
|
+
return r ? [...n, r].join("+") : "";
|
|
25
|
+
}
|
|
26
|
+
var b = class extends d {
|
|
27
|
+
static {
|
|
28
|
+
this.styles = [
|
|
29
|
+
i,
|
|
30
|
+
r,
|
|
31
|
+
f`
|
|
32
|
+
:host {
|
|
33
|
+
display: block;
|
|
34
|
+
cursor: var(--vf-cursor, default);
|
|
35
|
+
outline: none;
|
|
36
|
+
}
|
|
37
|
+
.item {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
/* Menus.png puts every menu row on a 16px pitch: the New Folder / Open
|
|
41
|
+
/ Print pulldown's nine inter-band gaps are all exact multiples of 16
|
|
42
|
+
(48, 32, 16, 16, 16, 48, 16, 32, 16 — the 32s and 48s are separator
|
|
43
|
+
groups). A row is 3px above + the 9px glyph + 4px below.
|
|
44
|
+
|
|
45
|
+
Its own token rather than a share of --vf-popup-height: the art has
|
|
46
|
+
pulldown and popup rows identical, but tying them would make
|
|
47
|
+
re-theming the popup *pill* move every pulldown row, which is
|
|
48
|
+
semantically wrong. --vf-control-height is scoped to fields (22). */
|
|
49
|
+
height: calc(var(--vf-scale, 1) * var(--vf-menu-row-height, 16px));
|
|
50
|
+
/* Lock the line box to the row box, as vf-option does. vfDisplay's 1.25
|
|
51
|
+
line-height resolves taller than a 16px row, and with align-items:
|
|
52
|
+
center the excess spills equally above and below — invisible per row,
|
|
53
|
+
but it overflowed the panel and summoned a scrollbar the last time a
|
|
54
|
+
row shrank under an inherited line-height. Derived from the same
|
|
55
|
+
expression as the height so a re-theme can't reintroduce the gap. */
|
|
56
|
+
line-height: calc(var(--vf-scale, 1) * var(--vf-menu-row-height, 16px));
|
|
57
|
+
/* Shares --vf-select-gutter with vf-select/vf-option: Menus.png puts a
|
|
58
|
+
pulldown's label ink at the same inset as a popup's, and both hold
|
|
59
|
+
the same 9px ✓. (The token name says "select" for historical
|
|
60
|
+
reasons; it is the checkmark column for every menu surface.) */
|
|
61
|
+
padding: 0 calc(var(--vf-scale, 1) * 12px) 0
|
|
62
|
+
calc(var(--vf-scale, 1) * var(--vf-select-gutter, 16px));
|
|
63
|
+
position: relative;
|
|
64
|
+
white-space: nowrap;
|
|
65
|
+
}
|
|
66
|
+
/* The inherited color deliberately lets a disabled row dim its ✓ along
|
|
67
|
+
with the label. Brief §1 says dimming greys the label only while chrome
|
|
68
|
+
glyphs stay black, but authentic System 7 greyed the whole disabled
|
|
69
|
+
row, check included — and reference behavior wins over the rule of
|
|
70
|
+
thumb. Documented deviation, not an oversight. */
|
|
71
|
+
/* 3px in from the row's left edge on both axes, matching Menus.png (✓ ink
|
|
72
|
+
at +4 from the panel border, i.e. 3 inside it) and vf-option's
|
|
73
|
+
identical rule. The 16px row less the 9px glyph leaves 7 — an odd
|
|
74
|
+
remainder, so it is biased 3 above / 4 below exactly as the art has it
|
|
75
|
+
rather than centred on 3.5 authored px (10.5 device px at the default
|
|
76
|
+
3×), which would fringe at every scale. */
|
|
77
|
+
.check {
|
|
78
|
+
position: absolute;
|
|
79
|
+
left: calc(var(--vf-scale, 1) * 3px);
|
|
80
|
+
top: calc(var(--vf-scale, 1) * 3px);
|
|
81
|
+
display: block;
|
|
82
|
+
color: inherit;
|
|
83
|
+
}
|
|
84
|
+
/* Native 9×9 (1:1, crisp). */
|
|
85
|
+
.check svg {
|
|
86
|
+
display: block;
|
|
87
|
+
width: calc(var(--vf-scale, 1) * 9px);
|
|
88
|
+
height: calc(var(--vf-scale, 1) * 9px);
|
|
89
|
+
}
|
|
90
|
+
.label {
|
|
91
|
+
flex: 1;
|
|
92
|
+
}
|
|
93
|
+
/* The shortcut is LEFT-aligned ink in a right-anchored slot, the way the
|
|
94
|
+
MDEF drew it: in Menus.png's File pulldown every ⌘ starts at the same
|
|
95
|
+
x — 23px left of the right border — whatever the letter, with ⌘W
|
|
96
|
+
running to within 3px of the border. Flexing the label and letting the
|
|
97
|
+
span hug the right edge instead right-aligned the pairs, so the ⌘
|
|
98
|
+
column jagged with each letter's width. The slot is the classic
|
|
99
|
+
reserve: ⌘'s 11px advance + the face's widest letter (M/W, 12px) —
|
|
100
|
+
sized so ⌘W exactly fills it and no pair moves the anchor.
|
|
101
|
+
min-width, not width, so a longer shortcut ("⌘⇧S") widens its own
|
|
102
|
+
slot rather than painting past the row. The 8px margin is the
|
|
103
|
+
label↔shortcut minimum ("Close Window"'s label box ends at +108, the
|
|
104
|
+
slot starts at +116); it only binds in the row that sets the panel's
|
|
105
|
+
intrinsic width. */
|
|
106
|
+
.shortcut {
|
|
107
|
+
flex: none;
|
|
108
|
+
margin-left: calc(var(--vf-scale, 1) * 8px);
|
|
109
|
+
min-width: calc(
|
|
110
|
+
var(--vf-scale, 1) * var(--vf-menu-shortcut-column, 23px)
|
|
111
|
+
);
|
|
112
|
+
text-align: left;
|
|
113
|
+
}
|
|
114
|
+
/* A shortcut row trades the label's 12px right clearance for the art's
|
|
115
|
+
1px — the slot itself is the clearance there (1 + 23 puts the slot
|
|
116
|
+
edge at −24, and ⌘'s 1px bearing lands its ink at −23, as traced).
|
|
117
|
+
Label-only rows keep the 12. */
|
|
118
|
+
.item.has-shortcut {
|
|
119
|
+
padding-right: calc(var(--vf-scale, 1) * 1px);
|
|
120
|
+
}
|
|
121
|
+
:host([disabled]) .item {
|
|
122
|
+
color: var(--vf-disabled, #c0c0c0);
|
|
123
|
+
}
|
|
124
|
+
/* Highlight = full-width inversion (hover, the press-drag's [active],
|
|
125
|
+
keyboard focus, blink "on"). blink-on is scoped to the enabled host
|
|
126
|
+
like its siblings: an item disabled mid-blink has its timer cancelled
|
|
127
|
+
(see updated()), and this keeps it from flashing even for the frame
|
|
128
|
+
before that lands. */
|
|
129
|
+
:host(:not([disabled])) .item:hover,
|
|
130
|
+
:host(:not([disabled])[active]) .item,
|
|
131
|
+
:host(:not([disabled]):focus) .item,
|
|
132
|
+
:host(:not([disabled])) .item.blink-on {
|
|
133
|
+
/* Forced colors: exempt the inverted row from the mode's text
|
|
134
|
+
backplate, which would land a Canvas slab on the highlight bar —
|
|
135
|
+
see vf-list-item's forced-colors note. The pair is already the
|
|
136
|
+
user's own via the vfBase token remap. */
|
|
137
|
+
@media (forced-colors: active) {
|
|
138
|
+
forced-color-adjust: none;
|
|
139
|
+
}
|
|
140
|
+
background: var(--vf-highlight, #000);
|
|
141
|
+
color: var(--vf-highlight-text, #fff);
|
|
142
|
+
}
|
|
143
|
+
/* While blinking, the timer — not the pointer — owns the inversion. Each
|
|
144
|
+
highlight source needs its own override at matching specificity; the
|
|
145
|
+
[active] one is what lets a drag-picked row keep its flag through the
|
|
146
|
+
blink, so the release reads as the highlight flashing off. */
|
|
147
|
+
:host(:not([disabled])) .item.blink-off:hover,
|
|
148
|
+
:host(:not([disabled])[active]) .item.blink-off,
|
|
149
|
+
:host(:not([disabled]):focus) .item.blink-off,
|
|
150
|
+
.item.blink-off {
|
|
151
|
+
background: transparent;
|
|
152
|
+
color: inherit;
|
|
153
|
+
}
|
|
154
|
+
`
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
#e;
|
|
158
|
+
#t;
|
|
159
|
+
#n;
|
|
160
|
+
#r;
|
|
161
|
+
#i;
|
|
162
|
+
constructor() {
|
|
163
|
+
super(), this.scale = new t(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.addEventListener("keydown", this.#u), this.addEventListener("pointerdown", this.#c), this.addEventListener("click", this.#l);
|
|
164
|
+
}
|
|
165
|
+
get #a() {
|
|
166
|
+
return this.checkable || this.#n;
|
|
167
|
+
}
|
|
168
|
+
connectedCallback() {
|
|
169
|
+
super.connectedCallback(), this.#s(), this.#o(), this.hasAttribute("tabindex") || (this.tabIndex = -1);
|
|
170
|
+
}
|
|
171
|
+
disconnectedCallback() {
|
|
172
|
+
super.disconnectedCallback(), this.#d();
|
|
173
|
+
}
|
|
174
|
+
updated(e) {
|
|
175
|
+
e.has("disabled") && (this.#r.ariaDisabled = this.disabled ? "true" : null, this.disabled && this.#d()), e.has("checked") && this.checked && (this.#n = !0), (e.has("checked") || e.has("checkable")) && this.#s(), e.has("shortcut") && this.#o();
|
|
176
|
+
}
|
|
177
|
+
#o() {
|
|
178
|
+
this.#r.ariaKeyShortcuts = y(this.shortcut) || null;
|
|
179
|
+
}
|
|
180
|
+
#s() {
|
|
181
|
+
this.#a ? (this.#r.role = "menuitemcheckbox", this.#r.ariaChecked = this.checked ? "true" : "false") : (this.#r.role = "menuitem", this.#r.ariaChecked = null);
|
|
182
|
+
}
|
|
183
|
+
render() {
|
|
184
|
+
let e = {
|
|
185
|
+
item: !0,
|
|
186
|
+
"has-shortcut": this.shortcut !== "",
|
|
187
|
+
"blink-on": this._blinkPhase === "on",
|
|
188
|
+
"blink-off": this._blinkPhase === "off"
|
|
189
|
+
};
|
|
190
|
+
return p`
|
|
191
|
+
<div class=${_(e)} part="item">
|
|
192
|
+
${this.checked ? p`<span class="check" part="check" aria-hidden="true"
|
|
193
|
+
>${u(l, "checkmark")}</span
|
|
194
|
+
>` : m}
|
|
195
|
+
<span class="label" part="label"><slot></slot></span>
|
|
196
|
+
${this.shortcut ? p`<span class="shortcut" part="shortcut" aria-hidden="true"
|
|
197
|
+
>${this.shortcut}</span
|
|
198
|
+
>` : m}
|
|
199
|
+
</div>
|
|
200
|
+
`;
|
|
201
|
+
}
|
|
202
|
+
#c() {
|
|
203
|
+
this.#i = this.closest("vf-menu") !== null, this.#i && a(() => {
|
|
204
|
+
this.#i = !1;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
#l(e) {
|
|
208
|
+
if (this.#i) {
|
|
209
|
+
this.#i = !1;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
o(this, e, () => this.activate());
|
|
213
|
+
}
|
|
214
|
+
#u(e) {
|
|
215
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), this.activate());
|
|
216
|
+
}
|
|
217
|
+
activate() {
|
|
218
|
+
if (this.disabled || this.#t) return;
|
|
219
|
+
this.#t = !0;
|
|
220
|
+
let e = c((e) => {
|
|
221
|
+
this._blinkPhase = e ? "on" : "off";
|
|
222
|
+
}, () => {
|
|
223
|
+
this._blinkPhase = null, this.#t = !1, this.#e = void 0, this.#f();
|
|
224
|
+
});
|
|
225
|
+
this.#t && (this.#e = e);
|
|
226
|
+
}
|
|
227
|
+
#d() {
|
|
228
|
+
this.#t && (this.#e?.cancel(), this.#e = void 0, this.#t = !1, this._blinkPhase = null);
|
|
229
|
+
}
|
|
230
|
+
#f() {
|
|
231
|
+
let e = this.value ?? (this.textContent ?? "").trim();
|
|
232
|
+
s(this, "vf-menu-select", {
|
|
233
|
+
value: e,
|
|
234
|
+
item: this
|
|
235
|
+
}), s(this, "vf-menu-close-request", { item: this }, { composed: !1 });
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
n([h({
|
|
239
|
+
type: Boolean,
|
|
240
|
+
reflect: !0
|
|
241
|
+
})], b.prototype, "disabled", void 0), n([h({
|
|
242
|
+
type: Boolean,
|
|
243
|
+
reflect: !0
|
|
244
|
+
})], b.prototype, "checked", void 0), n([h({
|
|
245
|
+
type: Boolean,
|
|
246
|
+
reflect: !0
|
|
247
|
+
})], b.prototype, "active", void 0), n([h({
|
|
248
|
+
type: Boolean,
|
|
249
|
+
reflect: !0
|
|
250
|
+
})], b.prototype, "checkable", void 0), n([h()], b.prototype, "shortcut", void 0), n([h()], b.prototype, "value", void 0), n([g()], b.prototype, "_blinkPhase", void 0), b = n([e("vf-menu-item")], b);
|
|
251
|
+
//#endregion
|
|
252
|
+
export { b as VfMenuItem };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { VfMenuItem } from './vf-menu-item.js';
|
|
3
|
+
/**
|
|
4
|
+
* `<vf-menu>` — a pull-down menu: a bar label plus a dropped panel of
|
|
5
|
+
* `<vf-menu-item>` / `<vf-separator>` children.
|
|
6
|
+
*
|
|
7
|
+
* Inside a `<vf-menu-bar>` the bar coordinates open state (only one menu open,
|
|
8
|
+
* hover-switching, outside-click/Escape dismissal) and owns the pointer
|
|
9
|
+
* gesture, which may travel between its menus. Used standalone, the menu
|
|
10
|
+
* toggles itself on label click and manages its own dismissal, its own press
|
|
11
|
+
* gesture and item keyboard navigation (ArrowUp/ArrowDown, Home/End, and the
|
|
12
|
+
* shared first-letter type-ahead — src/type-ahead.ts) while open.
|
|
13
|
+
*
|
|
14
|
+
* Pointer — the two styles `vf-select` supports, on the same terms (see
|
|
15
|
+
* src/menu-press.ts): the System 7 press-drag-release (press the title, slide
|
|
16
|
+
* onto a command, release over it) and a modern quick tap that leaves the menu
|
|
17
|
+
* dropped for a second click.
|
|
18
|
+
*
|
|
19
|
+
* @slot - Menu contents: `vf-menu-item` and `vf-separator` elements.
|
|
20
|
+
* @slot label - Replaces the `label` text in the bar — e.g. a `vf-img` apple
|
|
21
|
+
* icon for the Apple menu. Keep the `label` attribute set too: it stays the
|
|
22
|
+
* menu's accessible name (the bar item's `aria-label` and the panel's) when
|
|
23
|
+
* the visible title is an image.
|
|
24
|
+
* @csspart label - The menu title in the bar (inverts while open).
|
|
25
|
+
* @csspart panel - The dropped `.vf-panel` containing the items.
|
|
26
|
+
* @cssprop [--vf-menubar-height=20px] - `vf-menu-bar`
|
|
27
|
+
* @cssprop [--vf-menu-row-height=16px] - `vf-menu-item` row pitch; the panel
|
|
28
|
+
* also spends one of these on every slotted `vf-separator`, the full row the
|
|
29
|
+
* MDEF gave a divider (rule 8px into it — see the panel CSS)
|
|
30
|
+
*/
|
|
31
|
+
export declare class VfMenu extends LitElement {
|
|
32
|
+
#private;
|
|
33
|
+
static styles: import("lit").CSSResult[];
|
|
34
|
+
private readonly scale;
|
|
35
|
+
/** Device-pixel grid snapping (opt in with applyGridSnap()); see src/grid-snap.ts. */
|
|
36
|
+
private readonly gridSnap;
|
|
37
|
+
/**
|
|
38
|
+
* The menu title shown in the bar, and the menu's accessible name. Slotted
|
|
39
|
+
* `label` content replaces it visually (see the `label` slot) but this text
|
|
40
|
+
* keeps naming the menu for AT.
|
|
41
|
+
*/
|
|
42
|
+
label: string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the panel is dropped. Reflected. Managed by the parent
|
|
45
|
+
* `vf-menu-bar` when present, otherwise by the menu itself.
|
|
46
|
+
*/
|
|
47
|
+
open: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* The bar label's tabindex. A parent `vf-menu-bar` owns a roving tabindex
|
|
50
|
+
* across its menus and sets this to 0 on the active menu, -1 on the rest,
|
|
51
|
+
* so the whole bar is a single Tab stop. Defaults to 0 so a standalone
|
|
52
|
+
* menu is Tab-focusable on its own.
|
|
53
|
+
*/
|
|
54
|
+
barTabIndex: number;
|
|
55
|
+
private _labelEl;
|
|
56
|
+
private _assignedItems;
|
|
57
|
+
/** The enabled `vf-menu-item` children, in document order. */
|
|
58
|
+
get items(): VfMenuItem[];
|
|
59
|
+
/**
|
|
60
|
+
* Every slotted `vf-menu-item`, in document order — **disabled rows
|
|
61
|
+
* included**, unlike {@link items}. The press gesture hit-tests against
|
|
62
|
+
* these: releasing over a disabled row has to cancel, not fall through to
|
|
63
|
+
* whatever the panel covers.
|
|
64
|
+
*/
|
|
65
|
+
get allItems(): VfMenuItem[];
|
|
66
|
+
/**
|
|
67
|
+
* Viewport rect of the bar title, or `null` before the first render. The
|
|
68
|
+
* press gesture hit-tests by coordinates rather than by event target (see
|
|
69
|
+
* src/menu-press.ts), so it wants the box, not the element.
|
|
70
|
+
*/
|
|
71
|
+
get labelRect(): DOMRect | null;
|
|
72
|
+
connectedCallback(): void;
|
|
73
|
+
disconnectedCallback(): void;
|
|
74
|
+
protected updated(changed: Map<PropertyKey, unknown>): void;
|
|
75
|
+
/**
|
|
76
|
+
* Moves keyboard focus to the menu's bar label — the host's one focusable
|
|
77
|
+
* point. Overridden because the platform's `focus()` is a silent no-op here:
|
|
78
|
+
* no `delegatesFocus`, no host tabindex, so the standard method did nothing
|
|
79
|
+
* and `vf-label for` (which calls `target.focus()`) couldn't reach the menu.
|
|
80
|
+
*/
|
|
81
|
+
focus(options?: FocusOptions): void;
|
|
82
|
+
/**
|
|
83
|
+
* @deprecated Use `focus()` — the standard method now does this. (Spelled
|
|
84
|
+
* without a link: a `{@link}` inside a deprecated tag makes the cem
|
|
85
|
+
* analyzer attach the parsed AST node to the manifest, which then fails
|
|
86
|
+
* to serialize — "Converting circular structure to JSON".)
|
|
87
|
+
*/
|
|
88
|
+
focusLabel(): void;
|
|
89
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
90
|
+
}
|
|
91
|
+
declare global {
|
|
92
|
+
interface HTMLElementTagNameMap {
|
|
93
|
+
'vf-menu': VfMenu;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { vfElement as e } from "../define.js";
|
|
2
|
+
import { ScaleController as t } from "../scale.js";
|
|
3
|
+
import n from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
|
|
4
|
+
import { vfDisplay as r } from "../styles/recipes/display-face.js";
|
|
5
|
+
import { vfBase as i } from "../styles/recipes/host.js";
|
|
6
|
+
import { vfPanel as a } from "../styles/recipes/surface.js";
|
|
7
|
+
import { vfFocusUnderline as o } from "../styles/recipes/focus.js";
|
|
8
|
+
import { GridSnapController as s } from "../grid-snap.js";
|
|
9
|
+
import { DocumentListenersController as c, releaseAfterGesture as l } from "../document-listeners.js";
|
|
10
|
+
import { deferActivation as u, emit as d } from "../events.js";
|
|
11
|
+
import { FocusRuleController as f } from "../focus-modality.js";
|
|
12
|
+
import { TypeAheadBuffer as p } from "../type-ahead.js";
|
|
13
|
+
import { MenuPressController as m } from "../menu-press.js";
|
|
14
|
+
import { LitElement as h, css as g, html as _, nothing as v } from "lit";
|
|
15
|
+
import { property as y, query as b, queryAssignedElements as x } from "lit/decorators.js";
|
|
16
|
+
//#region src/components/vf-menu.ts
|
|
17
|
+
var S = class extends h {
|
|
18
|
+
constructor(...e) {
|
|
19
|
+
super(...e), this.scale = new t(this), this.gridSnap = new s(this), this.#e = new f(this), this.label = "", this.open = !1, this.barTabIndex = 0, this.#t = new m(this, {
|
|
20
|
+
menus: () => [this],
|
|
21
|
+
open: (e) => {
|
|
22
|
+
e.open = !0;
|
|
23
|
+
},
|
|
24
|
+
close: () => {
|
|
25
|
+
this.open = !1;
|
|
26
|
+
}
|
|
27
|
+
}), this.#r = this.attachInternals(), this.#i = new p(), this.#a = !1, this.#o = () => {
|
|
28
|
+
this.#n || this.focus(), this.open = !1;
|
|
29
|
+
}, this.#s = (e) => {
|
|
30
|
+
e.composedPath().includes(this) || (this.open = !1);
|
|
31
|
+
}, this.#c = (e) => {
|
|
32
|
+
if (!e.defaultPrevented) switch (e.key) {
|
|
33
|
+
case "Escape":
|
|
34
|
+
e.preventDefault(), this.open = !1, this.focus();
|
|
35
|
+
break;
|
|
36
|
+
case "Tab":
|
|
37
|
+
this.open = !1;
|
|
38
|
+
break;
|
|
39
|
+
case "ArrowDown":
|
|
40
|
+
case "ArrowUp":
|
|
41
|
+
e.preventDefault(), this.#l(e.key === "ArrowDown" ? 1 : -1);
|
|
42
|
+
break;
|
|
43
|
+
case "Home":
|
|
44
|
+
case "End": {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
let t = this.items;
|
|
47
|
+
t[e.key === "Home" ? 0 : t.length - 1]?.focus();
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
default: {
|
|
51
|
+
if (e.key.length !== 1 || e.key === " " || e.metaKey || e.ctrlKey || e.altKey) break;
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
let t = this.items, n = t.indexOf(document.activeElement);
|
|
54
|
+
t[this.#i.feed(e.key, n, t.map((e) => ({
|
|
55
|
+
text: e.textContent ?? "",
|
|
56
|
+
disabled: !1
|
|
57
|
+
})))]?.focus();
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}, this.#u = new c(this, () => [[
|
|
62
|
+
document,
|
|
63
|
+
"pointerdown",
|
|
64
|
+
this.#s,
|
|
65
|
+
!0
|
|
66
|
+
], [
|
|
67
|
+
document,
|
|
68
|
+
"keydown",
|
|
69
|
+
this.#c,
|
|
70
|
+
!0
|
|
71
|
+
]]), this.#f = (e) => {
|
|
72
|
+
if (!this.open || this.#n) return;
|
|
73
|
+
let t = e.relatedTarget;
|
|
74
|
+
t instanceof Node && (this.contains(t) || this.renderRoot.contains(t)) || (this.open = !1);
|
|
75
|
+
}, this.#p = (e) => {
|
|
76
|
+
this.#e.suppress(), !this.#n && this.#t.onPointerDown(e);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
static {
|
|
80
|
+
this.styles = [
|
|
81
|
+
i,
|
|
82
|
+
r,
|
|
83
|
+
a,
|
|
84
|
+
g`
|
|
85
|
+
:host {
|
|
86
|
+
display: inline-block;
|
|
87
|
+
position: relative;
|
|
88
|
+
}
|
|
89
|
+
.label {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
height: calc(var(--vf-scale, 1) * var(--vf-menubar-height, 20px));
|
|
93
|
+
/* The label box IS the title's black plate (and its hit rect), and
|
|
94
|
+
Menus.png puts the plate 10px left / 9px right of the title ink.
|
|
95
|
+
Chicago carries a 1px bearing on each side inside the text box, so
|
|
96
|
+
9/8 in layout lands the plate at ink −10/+9. In a bar, vf-menu-bar
|
|
97
|
+
overlaps adjacent boxes 5px on top of this — the plates share a
|
|
98
|
+
band, as the originals did. */
|
|
99
|
+
padding-inline: calc(var(--vf-scale, 1) * 9px) calc(var(--vf-scale, 1) * 8px);
|
|
100
|
+
white-space: nowrap;
|
|
101
|
+
/* The press-drag gesture owns pointer moves while the title is held;
|
|
102
|
+
suppress the browser's own touch panning/scrolling so a touch drag
|
|
103
|
+
walks the menu instead of scrolling the page. */
|
|
104
|
+
touch-action: none;
|
|
105
|
+
cursor: var(--vf-cursor, default);
|
|
106
|
+
}
|
|
107
|
+
:host([open]) .label {
|
|
108
|
+
/* Forced colors: exempt the inverted title from the mode's text
|
|
109
|
+
backplate, which would land a Canvas slab on the highlight bar —
|
|
110
|
+
see vf-list-item's forced-colors note. The pair is already the
|
|
111
|
+
user's own via the vfBase token remap. */
|
|
112
|
+
@media (forced-colors: active) {
|
|
113
|
+
forced-color-adjust: none;
|
|
114
|
+
}
|
|
115
|
+
background: var(--vf-highlight, #000);
|
|
116
|
+
color: var(--vf-highlight-text, #fff);
|
|
117
|
+
/* The hilite leaves the bar's top row white: System 7's plate is rows
|
|
118
|
+
1..18 of the 20px bar (the Label specimen in Menus.png is 18px of
|
|
119
|
+
plate, and InfiniteMac shows the white row above it). Transparent
|
|
120
|
+
borders + padding-box clip inset the paint without moving the box:
|
|
121
|
+
the top row shows the bar's white through, the bottom row the bar's
|
|
122
|
+
own black rule, and the hit rect stays the full bar height so a
|
|
123
|
+
click slammed against the screen top still opens the menu. The
|
|
124
|
+
18px content box centers the 16px em on the same rows as the
|
|
125
|
+
closed state, so the title never shifts. Declared only while open
|
|
126
|
+
because forced-colors mode repaints transparent borders CanvasText
|
|
127
|
+
on closed labels; here forced-color-adjust above already exempts
|
|
128
|
+
them. */
|
|
129
|
+
border-block: calc(var(--vf-scale, 1) * 1px) solid transparent;
|
|
130
|
+
background-clip: padding-box;
|
|
131
|
+
}
|
|
132
|
+
/* The title rides in its own box so the focus rule spans the title and
|
|
133
|
+
not the bar cell's 10px padding — the same reason vf-button wraps its
|
|
134
|
+
label. A line-height of 1 shrinks that box to the face's own em, whose
|
|
135
|
+
bottom edge IS the descender line (the Chicago 12/4 metrics — see
|
|
136
|
+
register-embedded-font.ts), so the rule below it clears every glyph
|
|
137
|
+
instead of being crossed by a 'g' the way the button's is. A slotted
|
|
138
|
+
icon — the Apple menu's vf-img — sizes the box instead, and the same
|
|
139
|
+
rule lands one blank row under the artwork. The title doesn't move
|
|
140
|
+
either way: symmetric half-leading and align-items:center put the
|
|
141
|
+
baseline in the same place at any line height. */
|
|
142
|
+
.title {
|
|
143
|
+
position: relative;
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
line-height: 1;
|
|
147
|
+
}
|
|
148
|
+
/* Keyboard focus is the kit's dashed rule under the title, not a ring
|
|
149
|
+
around the bar cell (see vfFocusUnderline) — one blank row under the
|
|
150
|
+
box, so −(1 + 1).
|
|
151
|
+
|
|
152
|
+
Gated on a class, not :focus-visible, exactly as vf-select is: the
|
|
153
|
+
press-drag gesture suppresses the browser's own mouse focus and
|
|
154
|
+
MenuPressController calls focus() instead, and Blink reads a
|
|
155
|
+
scripted focus as a visible one. So :focus-visible is true after a
|
|
156
|
+
plain mouse press on a title. FocusRuleController consults the page's
|
|
157
|
+
last input modality instead (see src/focus-modality.ts).
|
|
158
|
+
|
|
159
|
+
Only while CLOSED: a dropped menu already says where focus is, in the
|
|
160
|
+
louder of the two languages — the whole cell inverts. Drawing the rule
|
|
161
|
+
under an inverted title as well just adds a second, quieter mark
|
|
162
|
+
saying the same thing (in white, since it is currentColor). The mark
|
|
163
|
+
is for the state the inversion can't express: focused, not yet open.
|
|
164
|
+
The class stays on through the open state, so the rule comes back by
|
|
165
|
+
itself when the menu closes and hands focus back to the title. */
|
|
166
|
+
.label:focus {
|
|
167
|
+
outline: none;
|
|
168
|
+
}
|
|
169
|
+
:host(:not([open])) .label.vf-focus-rule .title::after {
|
|
170
|
+
--vf-focus-underline-offset: -2px;
|
|
171
|
+
${o}
|
|
172
|
+
}
|
|
173
|
+
.panel {
|
|
174
|
+
position: absolute;
|
|
175
|
+
/* The panel anchors to the host, not the corrected label, so it
|
|
176
|
+
composes the snap offset (see grid-snap.ts) to ride along. */
|
|
177
|
+
top: calc(100% + var(--vf-snap-dy, 0px));
|
|
178
|
+
left: var(--vf-snap-dx, 0px);
|
|
179
|
+
/* A menu is as wide as its widest row, the way the MDEF sized it —
|
|
180
|
+
Menus.png's File pulldown is 141px, its cm/inches popup 94. The old
|
|
181
|
+
180px floor held every smaller panel apart from its own rows, which
|
|
182
|
+
the right-anchored shortcut column would turn into a visible gulf
|
|
183
|
+
between label and ⌘. The floor that remains is the host's own
|
|
184
|
+
width, so a panel is never narrower than the bar title it hangs
|
|
185
|
+
from. (The nowrap rows make min-content the widest row, so the
|
|
186
|
+
shrink-to-fit abspos width IS the MDEF width.) */
|
|
187
|
+
min-width: 100%;
|
|
188
|
+
/* No vertical inset: every panel in Menus.png — both pulldowns, the
|
|
189
|
+
open popup and the closed pill — puts its first row's ink at +4 from
|
|
190
|
+
the border box, which is the 1px border plus the row's own 3px ✓
|
|
191
|
+
bias. The bottom border likewise sits immediately after the last row.
|
|
192
|
+
A 2px inset here displaced every row by 2px against the art; it was
|
|
193
|
+
invisible while the rows themselves were 6px too tall. */
|
|
194
|
+
padding: 0;
|
|
195
|
+
z-index: 1000;
|
|
196
|
+
/* As on the title: the held press, not the browser, owns touch moves
|
|
197
|
+
over the dropped panel. */
|
|
198
|
+
touch-action: none;
|
|
199
|
+
/* Slotted vf-separators render as the classic dimmed dotted menu rule. */
|
|
200
|
+
--vf-separator-color: var(--vf-disabled, #c0c0c0);
|
|
201
|
+
--vf-separator-style: dotted;
|
|
202
|
+
}
|
|
203
|
+
:host(:not([open])) .panel {
|
|
204
|
+
display: none;
|
|
205
|
+
}
|
|
206
|
+
/* A divider is an ITEM: the MDEF gave "-" a full row, so a separator
|
|
207
|
+
spends one whole --vf-menu-row-height, not a thin rule with token
|
|
208
|
+
margins — Menus.png's File pulldown runs a 32px ink pitch across
|
|
209
|
+
every divider group (vs 16 within one), and InfiniteMac's System 7.5
|
|
210
|
+
Edit menu puts the rule 12px under the ⌘ band above and 10px over
|
|
211
|
+
the one below: the neighbor rows' own 4/3px insets plus 8 over /
|
|
212
|
+
7 under the 1px rule. Derived from the row token (8 = H/2,
|
|
213
|
+
7 = H/2 − 1) so a re-themed pitch keeps dividers on it. */
|
|
214
|
+
.panel ::slotted(vf-separator) {
|
|
215
|
+
margin: calc(var(--vf-scale, 1) * var(--vf-menu-row-height, 16px) / 2)
|
|
216
|
+
0
|
|
217
|
+
calc(var(--vf-scale, 1) * (var(--vf-menu-row-height, 16px) / 2 - 1px));
|
|
218
|
+
}
|
|
219
|
+
`
|
|
220
|
+
];
|
|
221
|
+
}
|
|
222
|
+
#e;
|
|
223
|
+
#t;
|
|
224
|
+
get items() {
|
|
225
|
+
return this.allItems.filter((e) => !e.disabled);
|
|
226
|
+
}
|
|
227
|
+
get allItems() {
|
|
228
|
+
return this._assignedItems;
|
|
229
|
+
}
|
|
230
|
+
get labelRect() {
|
|
231
|
+
return this._labelEl?.getBoundingClientRect() ?? null;
|
|
232
|
+
}
|
|
233
|
+
get #n() {
|
|
234
|
+
return this.closest("vf-menu-bar") !== null;
|
|
235
|
+
}
|
|
236
|
+
#r;
|
|
237
|
+
#i;
|
|
238
|
+
#a;
|
|
239
|
+
#o;
|
|
240
|
+
#s;
|
|
241
|
+
#c;
|
|
242
|
+
#l(e) {
|
|
243
|
+
let t = this.items;
|
|
244
|
+
if (t.length === 0) return;
|
|
245
|
+
let n = t.indexOf(document.activeElement), r;
|
|
246
|
+
r = n < 0 ? e === 1 ? 0 : t.length - 1 : (n + e + t.length) % t.length, t[r]?.focus();
|
|
247
|
+
}
|
|
248
|
+
#u;
|
|
249
|
+
connectedCallback() {
|
|
250
|
+
super.connectedCallback(), this.#d(), this.requestUpdate(), this.addEventListener("vf-menu-close-request", this.#o), this.addEventListener("pointerdown", this.#p), this.addEventListener("focusout", this.#f);
|
|
251
|
+
}
|
|
252
|
+
#d() {
|
|
253
|
+
this.#r.role = this.#n ? "none" : null;
|
|
254
|
+
}
|
|
255
|
+
disconnectedCallback() {
|
|
256
|
+
super.disconnectedCallback(), this.removeEventListener("vf-menu-close-request", this.#o), this.removeEventListener("pointerdown", this.#p), this.removeEventListener("focusout", this.#f);
|
|
257
|
+
}
|
|
258
|
+
#f;
|
|
259
|
+
updated(e) {
|
|
260
|
+
if (e.has("open")) {
|
|
261
|
+
if (this.open && !this.#n ? this.#u.attach() : this.#u.detach(), !this.open) for (let e of this.allItems) e.active = !1;
|
|
262
|
+
this.open || this.#i.reset();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
#p;
|
|
266
|
+
focus(e) {
|
|
267
|
+
this._labelEl?.focus(e);
|
|
268
|
+
}
|
|
269
|
+
focusLabel() {
|
|
270
|
+
this.focus();
|
|
271
|
+
}
|
|
272
|
+
render() {
|
|
273
|
+
return _`
|
|
274
|
+
<div
|
|
275
|
+
class="label vf-snap ${this.#e.marked ? "vf-focus-rule" : ""}"
|
|
276
|
+
part="label"
|
|
277
|
+
role=${this.#n ? "menuitem" : "button"}
|
|
278
|
+
tabindex=${this.barTabIndex}
|
|
279
|
+
aria-haspopup="menu"
|
|
280
|
+
aria-expanded=${this.open ? "true" : "false"}
|
|
281
|
+
aria-label=${this.label || v}
|
|
282
|
+
@pointerdown=${this.#h}
|
|
283
|
+
@click=${this.#g}
|
|
284
|
+
@pointerenter=${this.#_}
|
|
285
|
+
@keydown=${this.#v}
|
|
286
|
+
>
|
|
287
|
+
<span class="title"><slot name="label">${this.label}</slot></span>
|
|
288
|
+
</div>
|
|
289
|
+
<div
|
|
290
|
+
class="panel vf-panel"
|
|
291
|
+
part="panel"
|
|
292
|
+
role="menu"
|
|
293
|
+
aria-label=${this.label || v}
|
|
294
|
+
>
|
|
295
|
+
<slot></slot>
|
|
296
|
+
</div>
|
|
297
|
+
`;
|
|
298
|
+
}
|
|
299
|
+
#m() {
|
|
300
|
+
if (!this.#n) {
|
|
301
|
+
this.open = !this.open;
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
d(this, "vf-menu-toggle-request", { menu: this }, {
|
|
305
|
+
cancelable: !0,
|
|
306
|
+
composed: !1
|
|
307
|
+
}) && (this.open = !this.open);
|
|
308
|
+
}
|
|
309
|
+
#h() {
|
|
310
|
+
this.#a = !0, l(() => {
|
|
311
|
+
this.#a = !1;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
#g(e) {
|
|
315
|
+
if (this.#a) {
|
|
316
|
+
this.#a = !1;
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
u(this, e, () => this.#m());
|
|
320
|
+
}
|
|
321
|
+
#_() {
|
|
322
|
+
d(this, "vf-menu-hover", { menu: this }, { composed: !1 });
|
|
323
|
+
}
|
|
324
|
+
#v(e) {
|
|
325
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
326
|
+
e.preventDefault();
|
|
327
|
+
let t = this.open;
|
|
328
|
+
this.#m(), !t && this.open && this.#y();
|
|
329
|
+
} else e.key === "ArrowDown" && !this.open && (e.preventDefault(), this.#m(), this.open && this.#y());
|
|
330
|
+
}
|
|
331
|
+
async #y() {
|
|
332
|
+
await this.updateComplete, this.items[0]?.focus();
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
n([y()], S.prototype, "label", void 0), n([y({
|
|
336
|
+
type: Boolean,
|
|
337
|
+
reflect: !0
|
|
338
|
+
})], S.prototype, "open", void 0), n([y({
|
|
339
|
+
type: Number,
|
|
340
|
+
attribute: !1
|
|
341
|
+
})], S.prototype, "barTabIndex", void 0), n([b(".label")], S.prototype, "_labelEl", void 0), n([x({
|
|
342
|
+
selector: "vf-menu-item",
|
|
343
|
+
flatten: !0
|
|
344
|
+
})], S.prototype, "_assignedItems", void 0), S = n([e("vf-menu")], S);
|
|
345
|
+
//#endregion
|
|
346
|
+
export { S as VfMenu };
|