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,117 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { PropertyValues } from 'lit';
|
|
3
|
+
declare const VfLabel_base: (new (...args: any[]) => import("../size.js").VfSizedInterface) & (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
|
|
4
|
+
/**
|
|
5
|
+
* `<vf-label>` — a static System 7 caption.
|
|
6
|
+
*
|
|
7
|
+
* The "Name:" beside a field, the "Mode" heading over a group of radios, a
|
|
8
|
+
* numeric readout beside a slider. Text the page was previously setting by hand
|
|
9
|
+
* in the display face — this is that, as a component, on the kit's grid:
|
|
10
|
+
*
|
|
11
|
+
* - the **Chicago-style chrome face** by default (dialog captions are chrome),
|
|
12
|
+
* with `face="body"` to switch to Geneva — which is also the kit's fine
|
|
13
|
+
* print, as it was System 7's: a dialog's small captions are Geneva 9 at
|
|
14
|
+
* its own strike size;
|
|
15
|
+
* - a **whole-system-pixel line box at the face's native pitch**
|
|
16
|
+
* (`--vf-label-line-height`: 16px — Chicago 12's own line, which is also the
|
|
17
|
+
* em; `face="body"` drops to 12px, Geneva 9's), so a column of captions
|
|
18
|
+
* accumulates whole offsets instead of pushing what follows off the
|
|
19
|
+
* device-pixel grid the way a ratio `line-height` does (docs/SIZING.md
|
|
20
|
+
* rule 2);
|
|
21
|
+
* - its own {@link GridSnapController}, so the bitmap stems stay on the grid
|
|
22
|
+
* wherever the page puts it;
|
|
23
|
+
* - a **declared `width`** ({@link VfSized}) — the shared width of a caption
|
|
24
|
+
* column, so a run of label-and-field rows lands every field on one x.
|
|
25
|
+
* Left to its text a caption measures whatever its glyphs measure (the
|
|
26
|
+
* showcase's Apple menu title came to 32.641 system px) and anything sized
|
|
27
|
+
* from it inherits the fraction; a declared width is whole, and so is the
|
|
28
|
+
* row built on it (layout contract rule 3). A caption wider than its column
|
|
29
|
+
* overflows rather than reflowing the row: the number is the column, and a
|
|
30
|
+
* caption that doesn't fit is a number to raise.
|
|
31
|
+
*
|
|
32
|
+
* `for` points at a control by id, as a native `<label>` does — clicking the
|
|
33
|
+
* caption focuses that control, and the caption text becomes its accessible
|
|
34
|
+
* name (see {@link for} for how, and for what it deliberately doesn't do).
|
|
35
|
+
*
|
|
36
|
+
* Chrome text, so the host is not selectable (SPEC §1); prose belongs in
|
|
37
|
+
* `<vf-paragraph>`, which is.
|
|
38
|
+
*
|
|
39
|
+
* @slot - The caption text.
|
|
40
|
+
* @csspart label - The inner text box.
|
|
41
|
+
* @cssprop --vf-label-line-height - The caption's own line box, in system px.
|
|
42
|
+
* Unset (the default) the box follows the face tokens below; set, it
|
|
43
|
+
* overrides both faces for labels alone. Keep any override a whole *even*
|
|
44
|
+
* number — a ratio puts every following line off the grid, and an odd value
|
|
45
|
+
* halves into the em's half-leading and puts the baseline on a half pixel.
|
|
46
|
+
* @cssprop --vf-line-height - The body face's native line (default `12px`,
|
|
47
|
+
* Geneva 9's) — the face-level knob a body-face retheme states alongside
|
|
48
|
+
* `--vf-font-family` / `--vf-font-size`.
|
|
49
|
+
* @cssprop --vf-line-height-display - The display face's native line
|
|
50
|
+
* (default `16px`, Chicago 12's) — the display retheme's third number.
|
|
51
|
+
*/
|
|
52
|
+
export declare class VfLabel extends VfLabel_base {
|
|
53
|
+
#private;
|
|
54
|
+
static styles: import("lit").CSSResult[];
|
|
55
|
+
/** Default-on display scaling (true 72dpi size); see src/scale.ts. */
|
|
56
|
+
private readonly scale;
|
|
57
|
+
/** Device-pixel grid snapping (opt in with applyGridSnap()); see src/grid-snap.ts. */
|
|
58
|
+
private readonly gridSnap;
|
|
59
|
+
/**
|
|
60
|
+
* The id of the control this caption names, resolved in the label's own tree
|
|
61
|
+
* scope (its document or shadow root), like a native `<label for>`.
|
|
62
|
+
*
|
|
63
|
+
* Two things follow from it. **Clicking the caption focuses the control** —
|
|
64
|
+
* a focus shortcut, not an activation: the kit's toggles carry their own
|
|
65
|
+
* labels, so forwarding a click to one would double up on the label they
|
|
66
|
+
* already have. And **the caption text becomes the control's accessible
|
|
67
|
+
* name**, by whichever route reaches it:
|
|
68
|
+
*
|
|
69
|
+
* - a `vf-*` control's focusable element lives in its shadow root, where an
|
|
70
|
+
* `aria-label` on the host cannot reach it — which is why each of them
|
|
71
|
+
* exposes a `label` property that lands on the inner control. That property
|
|
72
|
+
* is what gets filled in, and only when the consumer left it empty.
|
|
73
|
+
* - anything else (a native `<input>`, an element with a role) is in this
|
|
74
|
+
* label's own tree scope, so an `aria-labelledby` id reference works; it is
|
|
75
|
+
* set only when the target has no name of its own — and a name computed
|
|
76
|
+
* from the target's *content* counts: a `vf-checkbox` with slotted text, a
|
|
77
|
+
* `vf-button`, a native `<button>` are already named by what they show, and
|
|
78
|
+
* the caption declines rather than stamping over it.
|
|
79
|
+
*
|
|
80
|
+
* The one target neither route reaches is a control whose focusable element
|
|
81
|
+
* is shadow-internal but which exposes no `label` property because it names
|
|
82
|
+
* from content — `vf-button` is the kit's case. With visible text it needs
|
|
83
|
+
* no caption; an icon-only one should carry its name on the art (`alt` on
|
|
84
|
+
* the slotted `<img>`), which name-from-content picks up the same way.
|
|
85
|
+
*
|
|
86
|
+
* Either way the label puts back what it found when it is removed, the id
|
|
87
|
+
* changes, or the caption text does.
|
|
88
|
+
*
|
|
89
|
+
* Left `undefined` rather than `''` so an unset `for` reflects no attribute
|
|
90
|
+
* at all: `vf-label[for]` is a selector a page will reasonably write, and an
|
|
91
|
+
* empty `for=""` on every plain caption would make it match all of them.
|
|
92
|
+
*/
|
|
93
|
+
for?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Which embedded face to set the caption in — `'display'` (the Chicago-style
|
|
96
|
+
* chrome face, the default) or `'body'` (Geneva). Applied by
|
|
97
|
+
* `vfStaticText`; declared here so it types and reflects.
|
|
98
|
+
*/
|
|
99
|
+
face?: 'display' | 'body';
|
|
100
|
+
/**
|
|
101
|
+
* Greys the caption to `--vf-disabled`. System 7 dims the label, not the
|
|
102
|
+
* control (SPEC §1), so this is what a caption beside a disabled control
|
|
103
|
+
* wears — the control keeps its solid black box.
|
|
104
|
+
*/
|
|
105
|
+
dim: boolean;
|
|
106
|
+
constructor();
|
|
107
|
+
connectedCallback(): void;
|
|
108
|
+
disconnectedCallback(): void;
|
|
109
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
110
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
111
|
+
}
|
|
112
|
+
declare global {
|
|
113
|
+
interface HTMLElementTagNameMap {
|
|
114
|
+
'vf-label': VfLabel;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
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 { VfPositioned as r } from "../position.js";
|
|
5
|
+
import { vfDisplayDecls as i } from "../styles/recipes/display-face.js";
|
|
6
|
+
import { vfBase as a } from "../styles/recipes/host.js";
|
|
7
|
+
import { vfStaticText as o } from "../styles/recipes/static-text.js";
|
|
8
|
+
import { GridSnapController as s } from "../grid-snap.js";
|
|
9
|
+
import { VfSized as c } from "../size.js";
|
|
10
|
+
import { LitElement as l, css as u, html as d } from "lit";
|
|
11
|
+
import { property as f } from "lit/decorators.js";
|
|
12
|
+
//#region src/components/vf-label.ts
|
|
13
|
+
var p = 0, m = /* @__PURE__ */ new Set([
|
|
14
|
+
"button",
|
|
15
|
+
"checkbox",
|
|
16
|
+
"link",
|
|
17
|
+
"menuitem",
|
|
18
|
+
"menuitemcheckbox",
|
|
19
|
+
"menuitemradio",
|
|
20
|
+
"option",
|
|
21
|
+
"radio",
|
|
22
|
+
"switch",
|
|
23
|
+
"tab",
|
|
24
|
+
"treeitem"
|
|
25
|
+
]);
|
|
26
|
+
function h(e) {
|
|
27
|
+
if (!(e.textContent ?? "").trim()) return !1;
|
|
28
|
+
let t = e.getAttribute("role");
|
|
29
|
+
if (t) return m.has(t.split(/\s+/)[0] ?? "");
|
|
30
|
+
let n = e.localName;
|
|
31
|
+
return n.includes("-") ? !0 : n === "button" || n === "summary" || n === "a" && e.hasAttribute("href");
|
|
32
|
+
}
|
|
33
|
+
var g = class extends c(r(l)) {
|
|
34
|
+
static {
|
|
35
|
+
this.styles = [
|
|
36
|
+
a,
|
|
37
|
+
o,
|
|
38
|
+
u`
|
|
39
|
+
:host {
|
|
40
|
+
/* A real box, so a page can give a caption column a shared width
|
|
41
|
+
(layout contract rule 3) — inline text can't take one. */
|
|
42
|
+
display: inline-block;
|
|
43
|
+
/* Chrome by default; vfStaticText's face="body" overrides it. */
|
|
44
|
+
${i}
|
|
45
|
+
/* Whole system px, never a ratio — see the class comment. The pitch
|
|
46
|
+
is the face's, so it reads the face token under a per-component
|
|
47
|
+
override. 16px is Chicago 12's native line and the faces' own em
|
|
48
|
+
(12 above the baseline + 4 below), which is also vf-menu-item's row
|
|
49
|
+
pitch, so a caption beside a menu or a popup sits on the same
|
|
50
|
+
rhythm. */
|
|
51
|
+
line-height: calc(
|
|
52
|
+
var(--vf-scale, 1) *
|
|
53
|
+
var(--vf-label-line-height, var(--vf-line-height-display, 16px))
|
|
54
|
+
);
|
|
55
|
+
cursor: var(--vf-cursor, default);
|
|
56
|
+
}
|
|
57
|
+
/* Fine print sits on Geneva 9's native 12px line, like the paragraph's
|
|
58
|
+
body copy and vf-icon's name plate — the 16px em centers into it,
|
|
59
|
+
baseline at 10. Later sheet than vfStaticText's face rule, so the
|
|
60
|
+
pitch follows the face. */
|
|
61
|
+
:host([face='body']) {
|
|
62
|
+
line-height: calc(
|
|
63
|
+
var(--vf-scale, 1) *
|
|
64
|
+
var(--vf-label-line-height, var(--vf-line-height, 12px))
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
`
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
#e;
|
|
71
|
+
#t;
|
|
72
|
+
constructor() {
|
|
73
|
+
super(), this.scale = new t(this), this.gridSnap = new s(this), this.dim = !1, this.#e = null, this.#r = () => {
|
|
74
|
+
this.for && this.#a();
|
|
75
|
+
}, this.#i = () => {
|
|
76
|
+
this.isConnected && this.#a();
|
|
77
|
+
}, this.#s = () => {
|
|
78
|
+
let e = this.#n();
|
|
79
|
+
e && ((e.isDisabled ?? e.hasAttribute("disabled")) || e.focus());
|
|
80
|
+
}, this.addEventListener("click", this.#s);
|
|
81
|
+
}
|
|
82
|
+
connectedCallback() {
|
|
83
|
+
super.connectedCallback(), this.#t ??= new MutationObserver(() => {
|
|
84
|
+
this.for && this.#i();
|
|
85
|
+
}), this.#t.observe(this, {
|
|
86
|
+
characterData: !0,
|
|
87
|
+
childList: !0,
|
|
88
|
+
subtree: !0
|
|
89
|
+
}), this.#a();
|
|
90
|
+
}
|
|
91
|
+
disconnectedCallback() {
|
|
92
|
+
super.disconnectedCallback(), this.#t?.disconnect(), this.#o();
|
|
93
|
+
}
|
|
94
|
+
updated(e) {
|
|
95
|
+
e.has("for") && this.#a();
|
|
96
|
+
}
|
|
97
|
+
render() {
|
|
98
|
+
return d`<span class="vf-snap" part="label"
|
|
99
|
+
><slot @slotchange=${this.#r}></slot
|
|
100
|
+
></span>`;
|
|
101
|
+
}
|
|
102
|
+
#n() {
|
|
103
|
+
if (!this.for) return null;
|
|
104
|
+
let e = this.getRootNode();
|
|
105
|
+
return e instanceof Document || e instanceof ShadowRoot ? e.getElementById(this.for) : null;
|
|
106
|
+
}
|
|
107
|
+
#r;
|
|
108
|
+
#i;
|
|
109
|
+
#a() {
|
|
110
|
+
this.#o();
|
|
111
|
+
let e = this.#n();
|
|
112
|
+
if (!e) {
|
|
113
|
+
this.for && document.readyState === "loading" && document.addEventListener("DOMContentLoaded", this.#i, { once: !0 });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
let t = e.localName;
|
|
117
|
+
if (t.includes("-") && !customElements.get(t)) {
|
|
118
|
+
customElements.whenDefined(t).then(() => {
|
|
119
|
+
this.isConnected && !this.#e && this.#a();
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
let n = (this.textContent ?? "").trim();
|
|
124
|
+
if (n) {
|
|
125
|
+
if ("label" in e) {
|
|
126
|
+
typeof e.label == "string" && !e.label && (e.label = n, this.#e = {
|
|
127
|
+
target: e,
|
|
128
|
+
via: "property",
|
|
129
|
+
value: n
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby") || h(e) || (this.id ||= `vf-label-${++p}`, e.setAttribute("aria-labelledby", this.id), this.#e = {
|
|
134
|
+
target: e,
|
|
135
|
+
via: "aria",
|
|
136
|
+
value: this.id
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
#o() {
|
|
141
|
+
let e = this.#e;
|
|
142
|
+
this.#e = null, e && (e.via === "property" ? e.target.label === e.value && (e.target.label = "") : e.target.getAttribute("aria-labelledby") === e.value && e.target.removeAttribute("aria-labelledby"));
|
|
143
|
+
}
|
|
144
|
+
#s;
|
|
145
|
+
};
|
|
146
|
+
n([f({ reflect: !0 })], g.prototype, "for", void 0), n([f({ reflect: !0 })], g.prototype, "face", void 0), n([f({
|
|
147
|
+
type: Boolean,
|
|
148
|
+
reflect: !0
|
|
149
|
+
})], g.prototype, "dim", void 0), g = n([e("vf-label")], g);
|
|
150
|
+
//#endregion
|
|
151
|
+
export { g as VfLabel };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* `<vf-list-item>` — a row inside a `<vf-list>` list box.
|
|
4
|
+
*
|
|
5
|
+
* A 20px-tall single-line row; when selected the entire row inverts
|
|
6
|
+
* (white-on-black), the classic System 7 selection style. Selection and
|
|
7
|
+
* keyboard focus are managed by the parent `<vf-list>`.
|
|
8
|
+
*
|
|
9
|
+
* @slot - The row's text/content.
|
|
10
|
+
* @slot icon - A leading graphic — usually a `vf-img` holding a 16×16 System 7
|
|
11
|
+
* small icon, but any element rides here. The row lays it out as the icon
|
|
12
|
+
* gutter: flex-centered vertically (keep the difference between the row
|
|
13
|
+
* height and the icon height even, so the centering offset stays a whole
|
|
14
|
+
* pixel — 16 in a 20px row is a whole 2px), with the reference art's 4px gap
|
|
15
|
+
* to the text. Contributes no text, so first-letter type-ahead still reads
|
|
16
|
+
* the row's words. On a selected row the graphic rides the inverted bar
|
|
17
|
+
* as-is — System 7 left color icons unfiltered on the highlight.
|
|
18
|
+
* @csspart text - The text span beside the icon gutter (ellipsizes).
|
|
19
|
+
*/
|
|
20
|
+
export declare class VfListItem extends LitElement {
|
|
21
|
+
#private;
|
|
22
|
+
static styles: import("lit").CSSResult[];
|
|
23
|
+
private readonly scale;
|
|
24
|
+
/** The value this row contributes to the list's `value`/`values`. */
|
|
25
|
+
value: string;
|
|
26
|
+
/** Whether the row is selected (inverted). Managed by `<vf-list>`. */
|
|
27
|
+
selected: boolean;
|
|
28
|
+
/** Disables the row: dimmed text, not selectable or focusable. */
|
|
29
|
+
disabled: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* True while the containing `<vf-list>` is disabled. Managed by the list —
|
|
32
|
+
* not intended to be set by consumers. Kept distinct from `disabled` so
|
|
33
|
+
* re-enabling the list doesn't clear rows that are disabled in their own
|
|
34
|
+
* right. (The dimming already arrives by inheritance: the list host sets
|
|
35
|
+
* `color: var(--vf-disabled)` and rows inherit it.) Mirrors
|
|
36
|
+
* `vf-radio.groupDisabled`.
|
|
37
|
+
*/
|
|
38
|
+
listDisabled: boolean;
|
|
39
|
+
constructor();
|
|
40
|
+
connectedCallback(): void;
|
|
41
|
+
protected updated(changed: Map<PropertyKey, unknown>): void;
|
|
42
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
43
|
+
}
|
|
44
|
+
declare global {
|
|
45
|
+
interface HTMLElementTagNameMap {
|
|
46
|
+
'vf-list-item': VfListItem;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
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 { vfBase as r } from "../styles/recipes/host.js";
|
|
5
|
+
import { vfFocusRing as i } from "../styles/recipes/focus.js";
|
|
6
|
+
import { emit as a } from "../events.js";
|
|
7
|
+
import { LitElement as o, css as s, html as c } from "lit";
|
|
8
|
+
import { property as l } from "lit/decorators.js";
|
|
9
|
+
//#region src/components/vf-list-item.ts
|
|
10
|
+
var u = class extends o {
|
|
11
|
+
static {
|
|
12
|
+
this.styles = [r, s`
|
|
13
|
+
:host {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
/* Icon-to-text gap, per the reference art (Menus.png's icon-gutter
|
|
17
|
+
popup: 16px icon cell, 4px to the first glyph). Collapses to
|
|
18
|
+
nothing when the icon slot is empty — no icon, no flex item. */
|
|
19
|
+
gap: calc(var(--vf-scale, 1) * 4px);
|
|
20
|
+
height: calc(var(--vf-scale, 1) * 20px);
|
|
21
|
+
line-height: calc(var(--vf-scale, 1) * 20px);
|
|
22
|
+
padding: 0 calc(var(--vf-scale, 1) * 6px);
|
|
23
|
+
cursor: var(--vf-cursor, default);
|
|
24
|
+
background: transparent;
|
|
25
|
+
}
|
|
26
|
+
::slotted([slot='icon']) {
|
|
27
|
+
flex: none;
|
|
28
|
+
}
|
|
29
|
+
.text {
|
|
30
|
+
/* min-width lets the span shrink below its content so the ellipsis
|
|
31
|
+
can happen (flex items otherwise floor at min-content). */
|
|
32
|
+
flex: 1;
|
|
33
|
+
min-width: 0;
|
|
34
|
+
white-space: nowrap;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
text-overflow: ellipsis;
|
|
37
|
+
}
|
|
38
|
+
/* Plain :focus, not :focus-visible — vf-list drives a roving tabindex and
|
|
39
|
+
moves the cursor with item.focus(), and programmatic focus that isn't
|
|
40
|
+
preceded by a keyboard event doesn't match :focus-visible, so a
|
|
41
|
+
mouse-clicked cursor row would show no ring until the next Arrow key.
|
|
42
|
+
The roving tabindex guarantees only the cursor row is focusable, so
|
|
43
|
+
:focus is exactly the cursor. Matches sibling vf-menu-item. On a
|
|
44
|
+
*selected* row the ring rides currentColor (see vfFocusRing) and
|
|
45
|
+
inverts to white on the highlight bar — it has to stay legible there,
|
|
46
|
+
because in multiple mode Ctrl+Arrow deliberately moves the cursor
|
|
47
|
+
across selected rows while Space still acts on it. */
|
|
48
|
+
:host(:focus) {
|
|
49
|
+
--vf-focus-offset: -1px;
|
|
50
|
+
${i}
|
|
51
|
+
}
|
|
52
|
+
:host([selected]) {
|
|
53
|
+
background: var(--vf-highlight, #000);
|
|
54
|
+
color: var(--vf-highlight-text, #fff);
|
|
55
|
+
/* Forced colors: both tokens already remap to the user's
|
|
56
|
+
Highlight/HighlightText pair (vfBase), but the mode also paints an
|
|
57
|
+
opaque Canvas READABILITY BACKPLATE behind any text run whose
|
|
58
|
+
backdrop it doesn't consider a flat opaque color — and Chromium's
|
|
59
|
+
Highlight carries alpha, so the plate lands ON the highlight bar
|
|
60
|
+
and the row's text drowns in it (measured: the bar renders as a
|
|
61
|
+
Canvas slab under HighlightText ink). Opting the inverted row out
|
|
62
|
+
of forced adjustments drops the backplate; every color in play is
|
|
63
|
+
a system pair anyway, so this changes nothing else. The same
|
|
64
|
+
exemption rides every 1-bit inversion in the kit — vf-option,
|
|
65
|
+
vf-menu-item, vf-menu's open label, vf-icon's plate. */
|
|
66
|
+
@media (forced-colors: active) {
|
|
67
|
+
forced-color-adjust: none;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
:host([disabled]) {
|
|
71
|
+
color: var(--vf-disabled, #c0c0c0);
|
|
72
|
+
}
|
|
73
|
+
`];
|
|
74
|
+
}
|
|
75
|
+
#e;
|
|
76
|
+
constructor() {
|
|
77
|
+
super(), this.scale = new t(this), this.value = "", this.selected = !1, this.disabled = !1, this.listDisabled = !1, this.#e = this.attachInternals(), this.#e.role = "option";
|
|
78
|
+
}
|
|
79
|
+
connectedCallback() {
|
|
80
|
+
super.connectedCallback(), this.hasAttribute("tabindex") || (this.tabIndex = -1);
|
|
81
|
+
}
|
|
82
|
+
updated(e) {
|
|
83
|
+
e.has("selected") && (this.#e.ariaSelected = this.selected ? "true" : "false"), (e.has("disabled") || e.has("listDisabled")) && (this.#e.ariaDisabled = this.disabled || this.listDisabled ? "true" : null), e.has("disabled") && e.get("disabled") !== void 0 && a(this, "vf-list-item-disabled-change", { item: this }, { composed: !1 });
|
|
84
|
+
}
|
|
85
|
+
render() {
|
|
86
|
+
return c`<slot name="icon"></slot
|
|
87
|
+
><span class="text" part="text"><slot></slot></span>`;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
n([l()], u.prototype, "value", void 0), n([l({
|
|
91
|
+
type: Boolean,
|
|
92
|
+
reflect: !0
|
|
93
|
+
})], u.prototype, "selected", void 0), n([l({
|
|
94
|
+
type: Boolean,
|
|
95
|
+
reflect: !0
|
|
96
|
+
})], u.prototype, "disabled", void 0), n([l({ attribute: !1 })], u.prototype, "listDisabled", void 0), u = n([e("vf-list-item")], u);
|
|
97
|
+
//#endregion
|
|
98
|
+
export { u as VfListItem };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
declare const VfList_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
|
|
3
|
+
/**
|
|
4
|
+
* `<vf-list>` — the classic System 7 list box.
|
|
5
|
+
*
|
|
6
|
+
* A white, black-bordered scrolling box of `<vf-list-item>` rows with the
|
|
7
|
+
* kit-drawn System 7 scroll rail (dither trough, boxed arrow buttons, fixed
|
|
8
|
+
* thumb — the shared `vfScrollRail` subtree, synced to the native scrolling
|
|
9
|
+
* by {@link ScrollRailController}). The vertical rail is a permanent
|
|
10
|
+
* placeholder — arrows on an empty white channel when the rows fit, the
|
|
11
|
+
* dither and thumb filling in only on overflow (driven by
|
|
12
|
+
* {@link ScrollStateController}). Selection inverts rows. Supports single and
|
|
13
|
+
* multiple selection, roving tabindex, arrow-key navigation, and classic Finder
|
|
14
|
+
* first-letter type-ahead.
|
|
15
|
+
*
|
|
16
|
+
* Max height defaults to 200px; override with `--vf-list-max-height`.
|
|
17
|
+
*
|
|
18
|
+
* @slot - `vf-list-item` elements.
|
|
19
|
+
* @csspart list - The scrolling viewport around the slotted items.
|
|
20
|
+
* @fires vf-change - When the user changes the selection.
|
|
21
|
+
* `detail: { value: string, values: string[] }`.
|
|
22
|
+
* @cssprop [--vf-list-max-height=200px] - `vf-list` max height before its rail
|
|
23
|
+
* takes over (the host adds the 2px frame)
|
|
24
|
+
* @cssprop --vf-scrollbar-thumb - scrollbar thumb/elevator (white)
|
|
25
|
+
* @cssprop --vf-scrollbar-track - the scroll trough's base color under the
|
|
26
|
+
* dot-dither (white)
|
|
27
|
+
*/
|
|
28
|
+
export declare class VfList extends VfList_base {
|
|
29
|
+
#private;
|
|
30
|
+
static styles: import("lit").CSSResult[];
|
|
31
|
+
private readonly scale;
|
|
32
|
+
/** Device-pixel grid snapping (opt in with applyGridSnap()); see src/grid-snap.ts. */
|
|
33
|
+
private readonly gridSnap;
|
|
34
|
+
private viewport;
|
|
35
|
+
private content;
|
|
36
|
+
/** Reserves the vertical rail and toggles it active on overflow. */
|
|
37
|
+
private readonly scrollState;
|
|
38
|
+
/** Syncs the drawn rail to the row viewport and drives its interactions. */
|
|
39
|
+
private readonly rail;
|
|
40
|
+
/** Whether the rows actually overflow the box (either axis). */
|
|
41
|
+
private _scrollable;
|
|
42
|
+
/** Allows multiple selection (Shift extends, Cmd/Ctrl toggles). */
|
|
43
|
+
multiple: boolean;
|
|
44
|
+
/** Value of the (first) selected item. Settable. */
|
|
45
|
+
value: string;
|
|
46
|
+
/** Values of all selected items (multiple mode). Settable. */
|
|
47
|
+
values: string[];
|
|
48
|
+
/** Disables the whole list: dimmed, no interaction. */
|
|
49
|
+
disabled: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Accessible name for the list, applied as `aria-label` on the host (which
|
|
52
|
+
* carries `role="listbox"`). Without it a caption-less list is announced
|
|
53
|
+
* anonymously. A consumer-supplied `aria-label`/`aria-labelledby` attribute
|
|
54
|
+
* is left alone.
|
|
55
|
+
*/
|
|
56
|
+
label: string;
|
|
57
|
+
private _items;
|
|
58
|
+
constructor();
|
|
59
|
+
/**
|
|
60
|
+
* Moves keyboard focus to the row holding the roving tab stop — or, while
|
|
61
|
+
* the list is disabled, to the scrolling viewport (the disabled list's own
|
|
62
|
+
* Tab stop; the rows are all at -1 then). Overridden because the platform's
|
|
63
|
+
* `focus()` is a silent no-op on this host — no `delegatesFocus`, no host
|
|
64
|
+
* tabindex — so `vf-label for` (which calls `target.focus()`) never reached
|
|
65
|
+
* the list.
|
|
66
|
+
*/
|
|
67
|
+
focus(options?: FocusOptions): void;
|
|
68
|
+
disconnectedCallback(): void;
|
|
69
|
+
protected updated(changed: Map<PropertyKey, unknown>): void;
|
|
70
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
71
|
+
}
|
|
72
|
+
declare global {
|
|
73
|
+
interface HTMLElementTagNameMap {
|
|
74
|
+
'vf-list': VfList;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export {};
|