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,234 @@
|
|
|
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 { vfDisplay as i } from "../styles/recipes/display-face.js";
|
|
6
|
+
import { vfBase as a } from "../styles/recipes/host.js";
|
|
7
|
+
import { vfFocusUnderline as o } from "../styles/recipes/focus.js";
|
|
8
|
+
import { GridSnapController as s } from "../grid-snap.js";
|
|
9
|
+
import { BUTTON_FACE as c, BUTTON_FRAME as l, RING_FRAME as u, RING_HOLE as d, steppedRectClip as f, steppedRingClip as p } from "../pixel-frame.js";
|
|
10
|
+
import { deferActivation as m } from "../events.js";
|
|
11
|
+
import { VfShadowRoleControl as h } from "../form-control.js";
|
|
12
|
+
import { css as g, html as _, nothing as v, unsafeCSS as y } from "lit";
|
|
13
|
+
import { property as b, query as x } from "lit/decorators.js";
|
|
14
|
+
//#region src/components/vf-button.ts
|
|
15
|
+
var S = "vf-submitter", C = class extends r(h) {
|
|
16
|
+
constructor(...e) {
|
|
17
|
+
super(...e), this.type = "button", this.name = "", this.value = "", this.formAction = "", this.formEnctype = "", this.formMethod = "", this.formNoValidate = !1, this.formTarget = "", this.scale = new t(this), this.gridSnap = new s(this), this.#e = !1, this.handleClick = (e) => {
|
|
18
|
+
this.isDisabled || this.#e || this.resolvedType !== "button" && m(this, e, () => this.activate());
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
static {
|
|
22
|
+
this.shadowRootOptions = {
|
|
23
|
+
...h.shadowRootOptions,
|
|
24
|
+
delegatesFocus: !0
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
static {
|
|
28
|
+
this.styles = [
|
|
29
|
+
a,
|
|
30
|
+
i,
|
|
31
|
+
g`
|
|
32
|
+
:host {
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
position: relative;
|
|
35
|
+
cursor: var(--vf-cursor, default);
|
|
36
|
+
/* Display scaling: metrics are authored in *system pixels* and
|
|
37
|
+
multiplied by --vf-scale (default 1 = today's rendering). Opt a
|
|
38
|
+
subtree into true 72dpi size via applyScale()/--vf-scale — see
|
|
39
|
+
src/scale.ts. The chrome font scales with the control. */
|
|
40
|
+
font-size: calc(var(--vf-scale, 1) * var(--vf-font-size-display, 16px));
|
|
41
|
+
}
|
|
42
|
+
/* Breathing room for the default-button ring drawn at inset -4 system px.
|
|
43
|
+
A vf-button-group zeroes this (via --vf-button-ring-margin) and reserves
|
|
44
|
+
the ring space itself, so grouped button *faces* align instead of their
|
|
45
|
+
margin boxes — see src/components/vf-button-group.ts. */
|
|
46
|
+
:host([variant='default']) {
|
|
47
|
+
margin: calc(
|
|
48
|
+
var(--vf-scale, 1) * var(--vf-button-ring-margin, ${4}px)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
/* The default ring: a 3px stepped band with a transparent 1px gap to the
|
|
52
|
+
button, clipped as an evenodd donut so the gap shows the surface
|
|
53
|
+
behind it (the reference's gap pixels are alpha-0). */
|
|
54
|
+
:host([variant='default'])::before {
|
|
55
|
+
content: '';
|
|
56
|
+
position: absolute;
|
|
57
|
+
/* The ring anchors to the host, not the corrected button, so each
|
|
58
|
+
inset composes the snap offset (see grid-snap.ts) to ride along. */
|
|
59
|
+
top: calc(var(--vf-scale, 1) * -${4}px + var(--vf-snap-dy, 0px));
|
|
60
|
+
left: calc(var(--vf-scale, 1) * -${4}px + var(--vf-snap-dx, 0px));
|
|
61
|
+
bottom: calc(var(--vf-scale, 1) * -${4}px - var(--vf-snap-dy, 0px));
|
|
62
|
+
right: calc(var(--vf-scale, 1) * -${4}px - var(--vf-snap-dx, 0px));
|
|
63
|
+
background: var(--vf-black, #000);
|
|
64
|
+
clip-path: ${y(p(u, d))};
|
|
65
|
+
pointer-events: none;
|
|
66
|
+
}
|
|
67
|
+
/* Disabled default: the fat outer ring dims to gray; the inner button
|
|
68
|
+
border stays solid black (see button:disabled) — the System 7 reading,
|
|
69
|
+
where the ring and the title dim together and the button's own frame
|
|
70
|
+
does not. (The original dimmed with a 50% stipple; gray standing in
|
|
71
|
+
for it is the kit's one liberty here — SPEC §1.)
|
|
72
|
+
|
|
73
|
+
Both disabled routes need a selector, because only one of them is an
|
|
74
|
+
attribute: an ancestor <fieldset disabled> disables the control
|
|
75
|
+
through formDisabledCallback, which sets the form-disabled custom
|
|
76
|
+
state and never touches the disabled attribute. Keyed on the
|
|
77
|
+
attribute alone, a default button inside a disabled fieldset greyed
|
|
78
|
+
its label — that comes from the inner <button>'s own :disabled —
|
|
79
|
+
while its ring stayed solid black. Separate rules rather than one
|
|
80
|
+
:is() list: an engine that doesn't parse :state() drops the whole
|
|
81
|
+
selector it appears in, and the attribute case should survive that
|
|
82
|
+
on its own. */
|
|
83
|
+
:host([variant='default'][disabled])::before {
|
|
84
|
+
background: var(--vf-disabled, #c0c0c0);
|
|
85
|
+
}
|
|
86
|
+
:host([variant='default']:state(form-disabled))::before {
|
|
87
|
+
background: var(--vf-disabled, #c0c0c0);
|
|
88
|
+
}
|
|
89
|
+
/* The native button paints no box of its own — its frame and face are
|
|
90
|
+
the stepped pseudo-element silhouettes below. Keeping the clip-paths
|
|
91
|
+
off the button itself leaves the hit area a plain rectangle, and
|
|
92
|
+
anything painted outside the silhouette (a ring a consumer restores
|
|
93
|
+
on ::part(button)) unclipped. */
|
|
94
|
+
button {
|
|
95
|
+
position: relative;
|
|
96
|
+
/* Own stacking context so the negative-z silhouettes stay inside the
|
|
97
|
+
button: above everything behind it, below the label. */
|
|
98
|
+
z-index: 0;
|
|
99
|
+
display: inline-flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
justify-content: center;
|
|
102
|
+
/* 20px, not the 22px fields: the reference sheets put the button face
|
|
103
|
+
at 80×20 (and the default ring's inner box at exactly that), so the
|
|
104
|
+
ring traces were authored against a 20px face. --vf-control-height
|
|
105
|
+
stays the *field* height — see SPEC §3. */
|
|
106
|
+
height: calc(var(--vf-scale, 1) * var(--vf-button-height, 20px));
|
|
107
|
+
min-width: calc(var(--vf-scale, 1) * 64px);
|
|
108
|
+
/* Fill the host so a vf-button-group can stretch this face to the
|
|
109
|
+
shared column width. Standalone (shrink-wrapped host) it's a no-op. */
|
|
110
|
+
flex: var(--vf-button-flex, 0 1 auto);
|
|
111
|
+
padding: 0 calc(var(--vf-scale, 1) * 14px);
|
|
112
|
+
background: none;
|
|
113
|
+
border: none;
|
|
114
|
+
color: var(--vf-black, #000);
|
|
115
|
+
font-family: inherit;
|
|
116
|
+
font-size: inherit;
|
|
117
|
+
font-weight: inherit;
|
|
118
|
+
line-height: inherit;
|
|
119
|
+
white-space: nowrap;
|
|
120
|
+
cursor: inherit;
|
|
121
|
+
}
|
|
122
|
+
/* Frame: the outer silhouette in solid black. The face below covers all
|
|
123
|
+
but the outline, leaving the reference's exact border pixels — the
|
|
124
|
+
QuickDraw difference-of-silhouettes, not a stroked border. */
|
|
125
|
+
button::before,
|
|
126
|
+
button::after {
|
|
127
|
+
content: '';
|
|
128
|
+
position: absolute;
|
|
129
|
+
inset: 0;
|
|
130
|
+
z-index: -1;
|
|
131
|
+
}
|
|
132
|
+
button::before {
|
|
133
|
+
background: var(--vf-black, #000);
|
|
134
|
+
clip-path: ${y(f(l))};
|
|
135
|
+
}
|
|
136
|
+
/* Face: white fill inset one pixel, with its own traced corner steps. */
|
|
137
|
+
button::after {
|
|
138
|
+
background: var(--vf-white, #fff);
|
|
139
|
+
clip-path: ${y(f(c))};
|
|
140
|
+
}
|
|
141
|
+
/* Pressed: instant white-on-black inversion. */
|
|
142
|
+
button:active:not(:disabled) {
|
|
143
|
+
color: var(--vf-white, #fff);
|
|
144
|
+
}
|
|
145
|
+
button:active:not(:disabled)::after {
|
|
146
|
+
background: var(--vf-black, #000);
|
|
147
|
+
}
|
|
148
|
+
/* The label rides in its own box so the focus underline can span the
|
|
149
|
+
text and not the button's padding: as the flex item it shrink-wraps
|
|
150
|
+
to the label, and its 20px line box puts the baseline a known
|
|
151
|
+
distance above its bottom edge (see vfFocusUnderline). */
|
|
152
|
+
.label {
|
|
153
|
+
position: relative;
|
|
154
|
+
}
|
|
155
|
+
/* Keyboard focus is the dashed rule under the label, not a ring around
|
|
156
|
+
the control — so the UA's own outline goes. */
|
|
157
|
+
button:focus-visible {
|
|
158
|
+
outline: none;
|
|
159
|
+
}
|
|
160
|
+
/* …and off the host too. Blink doesn't currently propagate
|
|
161
|
+
:focus-visible to a delegatesFocus host, so today this paints nothing
|
|
162
|
+
— but SPEC §vf-button claims the ring is off on both, and that claim
|
|
163
|
+
should hold because the component says so, not because one engine
|
|
164
|
+
happens to agree. Its own rule, not a selector list with the above:
|
|
165
|
+
one unparsed selector would drop the other with it. */
|
|
166
|
+
:host(:focus-visible) {
|
|
167
|
+
outline: none;
|
|
168
|
+
}
|
|
169
|
+
button:focus-visible .label::after {
|
|
170
|
+
${o}
|
|
171
|
+
}
|
|
172
|
+
/* Disabled: only the label dims to gray; the solid black border stays. */
|
|
173
|
+
button:disabled {
|
|
174
|
+
color: var(--vf-disabled, #c0c0c0);
|
|
175
|
+
}
|
|
176
|
+
`
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
#e;
|
|
180
|
+
get resolvedType() {
|
|
181
|
+
let e = String(this.type ?? "").toLowerCase();
|
|
182
|
+
return e === "submit" ? "submit" : e === "reset" ? "reset" : "button";
|
|
183
|
+
}
|
|
184
|
+
click() {
|
|
185
|
+
let e = this.buttonEl;
|
|
186
|
+
e ? e.click() : super.click();
|
|
187
|
+
}
|
|
188
|
+
render() {
|
|
189
|
+
return _`
|
|
190
|
+
<button
|
|
191
|
+
part="button"
|
|
192
|
+
class="vf-snap"
|
|
193
|
+
type="button"
|
|
194
|
+
aria-label=${this.hostAriaLabel || v}
|
|
195
|
+
aria-describedby=${this.describedBy}
|
|
196
|
+
?disabled=${this.isDisabled}
|
|
197
|
+
@click=${this.handleClick}
|
|
198
|
+
>
|
|
199
|
+
<span class="label"><slot></slot></span>
|
|
200
|
+
</button>
|
|
201
|
+
${this.renderDescription()}
|
|
202
|
+
`;
|
|
203
|
+
}
|
|
204
|
+
activate() {
|
|
205
|
+
let e = this.resolvedType;
|
|
206
|
+
if (!this.internals.form || e === "button" || this.isDisabled) return;
|
|
207
|
+
let t = document.createElement("button");
|
|
208
|
+
t.type = e, t.slot = S, t.addEventListener("click", (e) => e.stopPropagation()), e === "submit" && (this.name && (t.name = this.name, t.value = this.value), this.formAction && (t.formAction = this.formAction), this.formEnctype && (t.formEnctype = this.formEnctype), this.formMethod && (t.formMethod = this.formMethod), this.formTarget && (t.formTarget = this.formTarget), t.formNoValidate = this.formNoValidate), this.#e = !0;
|
|
209
|
+
try {
|
|
210
|
+
this.append(t), t.click();
|
|
211
|
+
} finally {
|
|
212
|
+
t.remove(), this.#e = !1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
n([b({ reflect: !0 })], C.prototype, "variant", void 0), n([b({ reflect: !0 })], C.prototype, "type", void 0), n([b({ reflect: !0 })], C.prototype, "name", void 0), n([b({ reflect: !0 })], C.prototype, "value", void 0), n([b({
|
|
217
|
+
attribute: "formaction",
|
|
218
|
+
reflect: !0
|
|
219
|
+
})], C.prototype, "formAction", void 0), n([b({
|
|
220
|
+
attribute: "formenctype",
|
|
221
|
+
reflect: !0
|
|
222
|
+
})], C.prototype, "formEnctype", void 0), n([b({
|
|
223
|
+
attribute: "formmethod",
|
|
224
|
+
reflect: !0
|
|
225
|
+
})], C.prototype, "formMethod", void 0), n([b({
|
|
226
|
+
type: Boolean,
|
|
227
|
+
attribute: "formnovalidate",
|
|
228
|
+
reflect: !0
|
|
229
|
+
})], C.prototype, "formNoValidate", void 0), n([b({
|
|
230
|
+
attribute: "formtarget",
|
|
231
|
+
reflect: !0
|
|
232
|
+
})], C.prototype, "formTarget", void 0), n([x("button")], C.prototype, "buttonEl", void 0), C = n([e("vf-button")], C);
|
|
233
|
+
//#endregion
|
|
234
|
+
export { C as VfButton };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type PropertyValues } from 'lit';
|
|
2
|
+
import { VfFormControl } from '../form-control.js';
|
|
3
|
+
declare const VfCheckbox_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & (abstract new (...args: any[]) => import("../toggle-control.js").VfToggleControlInterface) & typeof VfFormControl;
|
|
4
|
+
/**
|
|
5
|
+
* The classic System 7 checkbox: a 13×13 white square with a 1px black
|
|
6
|
+
* border whose checked state is the corner-to-corner ✕ glyph — the pixel-exact
|
|
7
|
+
* cross traced from the Classic Macintosh UI Kit sprite. The border "thickens"
|
|
8
|
+
* while pressed, exactly like the original control.
|
|
9
|
+
*
|
|
10
|
+
* Form-associated: submits `value` under `name` when checked (like a native
|
|
11
|
+
* checkbox) and restores its initial checked state on form reset. Toggles on
|
|
12
|
+
* click and Space.
|
|
13
|
+
*
|
|
14
|
+
* @slot - The label, rendered to the right of the box with a 6px gap.
|
|
15
|
+
* @csspart box - The 13×13 checkbox square.
|
|
16
|
+
* @csspart label - The label wrapper around the slot.
|
|
17
|
+
* @fires vf-change - When toggled by user interaction. `detail: { checked: boolean }`.
|
|
18
|
+
* @fires input - Native event, dispatched from the host per user toggle (with
|
|
19
|
+
* `change`, the pair a native checkbox fires). A programmatic `checked` set
|
|
20
|
+
* fires nothing, as on a native checkbox.
|
|
21
|
+
* @fires change - Native event, dispatched from the host per user toggle so
|
|
22
|
+
* form delegation and framework bindings hear it.
|
|
23
|
+
*/
|
|
24
|
+
export declare class VfCheckbox extends VfCheckbox_base {
|
|
25
|
+
static styles: import("lit").CSSResult[];
|
|
26
|
+
/** Whether the checkbox is checked. */
|
|
27
|
+
checked: boolean;
|
|
28
|
+
/** Form field name used when submitting. */
|
|
29
|
+
name: string;
|
|
30
|
+
/** Value submitted with the form while checked. */
|
|
31
|
+
value: string;
|
|
32
|
+
/** `required` on a checkbox means it must be checked, as on a native one. */
|
|
33
|
+
protected get valueMissing(): boolean;
|
|
34
|
+
/** The message a native `<input type="checkbox" required>` reports. */
|
|
35
|
+
protected get valueMissingMessage(): string;
|
|
36
|
+
constructor();
|
|
37
|
+
connectedCallback(): void;
|
|
38
|
+
/** The handle {@link VfFormControl} already attached. */
|
|
39
|
+
protected get toggleInternals(): ElementInternals;
|
|
40
|
+
/** `disabled`, or an ancestor `<fieldset disabled>`. */
|
|
41
|
+
protected get toggleDisabled(): boolean;
|
|
42
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
43
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
44
|
+
/** Form-associated lifecycle: restores the initial checked state. */
|
|
45
|
+
formResetCallback(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Restored form state means the flag, not `value`: a checkbox only ever
|
|
48
|
+
* stores its submission string while checked, so getting one back IS
|
|
49
|
+
* "checked" (the base default would have overwritten `value` instead).
|
|
50
|
+
*/
|
|
51
|
+
protected applyFormState(): void;
|
|
52
|
+
/** Click/Space on an enabled checkbox flips it. */
|
|
53
|
+
protected activate(): void;
|
|
54
|
+
}
|
|
55
|
+
declare global {
|
|
56
|
+
interface HTMLElementTagNameMap {
|
|
57
|
+
'vf-checkbox': VfCheckbox;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { vfElement as e } from "../define.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
|
|
3
|
+
import { VfPositioned as n } from "../position.js";
|
|
4
|
+
import { vfDisplay as r } from "../styles/recipes/display-face.js";
|
|
5
|
+
import { vfBase as i } from "../styles/recipes/host.js";
|
|
6
|
+
import { vfFocusUnderline as a } from "../styles/recipes/focus.js";
|
|
7
|
+
import { vfToggle as o } from "../styles/recipes/toggle.js";
|
|
8
|
+
import { emit as s, emitNative as c } from "../events.js";
|
|
9
|
+
import { CHECKBOX_X as l, glyphSvg as u } from "../glyphs.js";
|
|
10
|
+
import { VfFormControl as d } from "../form-control.js";
|
|
11
|
+
import { VfToggleControl as f } from "../toggle-control.js";
|
|
12
|
+
import { css as p, html as m } from "lit";
|
|
13
|
+
import { property as h } from "lit/decorators.js";
|
|
14
|
+
import { classMap as g } from "lit/directives/class-map.js";
|
|
15
|
+
//#region src/components/vf-checkbox.ts
|
|
16
|
+
var _ = class extends n(f(d)) {
|
|
17
|
+
static {
|
|
18
|
+
this.styles = [
|
|
19
|
+
i,
|
|
20
|
+
r,
|
|
21
|
+
o,
|
|
22
|
+
p`
|
|
23
|
+
/* Keyboard focus underlines the box itself — not the label, and not a
|
|
24
|
+
ring around either (see vfFocusUnderline). Both adjustments below are
|
|
25
|
+
the 1px border: an absolutely positioned pseudo sizes to the PADDING
|
|
26
|
+
box, which the border sits outside of. So the rule grows 1px each side
|
|
27
|
+
to span the whole well, and its offset counts the border before the
|
|
28
|
+
blank row and the rule itself: −(1 + 1 + 1). */
|
|
29
|
+
:host(:focus-visible) .box::after {
|
|
30
|
+
--vf-focus-underline-offset: -3px;
|
|
31
|
+
${a}
|
|
32
|
+
left: calc(var(--vf-scale, 1) * -1px);
|
|
33
|
+
right: calc(var(--vf-scale, 1) * -1px);
|
|
34
|
+
}
|
|
35
|
+
.box {
|
|
36
|
+
position: relative;
|
|
37
|
+
flex: none;
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: center;
|
|
41
|
+
width: calc(var(--vf-scale, 1) * 13px);
|
|
42
|
+
height: calc(var(--vf-scale, 1) * 13px);
|
|
43
|
+
background: var(--vf-white, #fff);
|
|
44
|
+
border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
|
|
45
|
+
color: var(--vf-black, #000);
|
|
46
|
+
}
|
|
47
|
+
/* Pressed: border thickens to 2px (classic press feedback). */
|
|
48
|
+
:host(:active) .box:not(.dim) {
|
|
49
|
+
box-shadow: inset 0 0 0 calc(var(--vf-scale, 1) * 1px) var(--vf-black, #000);
|
|
50
|
+
}
|
|
51
|
+
/* Forced colors never paints box-shadow, so the press feedback above
|
|
52
|
+
goes silent. The same thickening as a real border-width change: with
|
|
53
|
+
box-sizing: border-box the 13×13 box holds and the extra pixel grows
|
|
54
|
+
inward, exactly where the inset shadow painted. */
|
|
55
|
+
@media (forced-colors: active) {
|
|
56
|
+
:host(:active) .box:not(.dim) {
|
|
57
|
+
border-width: calc(var(--vf-scale, 1) * 2px);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/* Native 12×12 sprite — centered in the 13×13 box; the glyph's own 1px
|
|
61
|
+
transparent margin lets it overhang onto the border harmlessly. Scales
|
|
62
|
+
with the box; crispEdges keeps it whole-device-pixel at any dpr. */
|
|
63
|
+
.check {
|
|
64
|
+
flex: none;
|
|
65
|
+
width: calc(var(--vf-scale, 1) * 12px);
|
|
66
|
+
height: calc(var(--vf-scale, 1) * 12px);
|
|
67
|
+
display: none;
|
|
68
|
+
color: inherit;
|
|
69
|
+
}
|
|
70
|
+
:host([checked]) .check {
|
|
71
|
+
display: block;
|
|
72
|
+
}
|
|
73
|
+
`
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
get valueMissing() {
|
|
77
|
+
return !this.checked;
|
|
78
|
+
}
|
|
79
|
+
get valueMissingMessage() {
|
|
80
|
+
return "Please check this box if you want to proceed.";
|
|
81
|
+
}
|
|
82
|
+
constructor() {
|
|
83
|
+
super(), this.checked = !1, this.name = "", this.value = "on", this.internals.role = "checkbox";
|
|
84
|
+
}
|
|
85
|
+
connectedCallback() {
|
|
86
|
+
super.connectedCallback(), this.latchFormDefault(this.checked);
|
|
87
|
+
}
|
|
88
|
+
get toggleInternals() {
|
|
89
|
+
return this.internals;
|
|
90
|
+
}
|
|
91
|
+
get toggleDisabled() {
|
|
92
|
+
return this.isDisabled;
|
|
93
|
+
}
|
|
94
|
+
render() {
|
|
95
|
+
let e = this.isDisabled;
|
|
96
|
+
return m`
|
|
97
|
+
<span
|
|
98
|
+
class=${g({
|
|
99
|
+
box: !0,
|
|
100
|
+
dim: e,
|
|
101
|
+
"vf-snap": !0
|
|
102
|
+
})}
|
|
103
|
+
part="box"
|
|
104
|
+
aria-hidden="true"
|
|
105
|
+
>
|
|
106
|
+
${u(l, "check")}
|
|
107
|
+
</span>
|
|
108
|
+
<span class=${g({
|
|
109
|
+
label: !0,
|
|
110
|
+
dim: e,
|
|
111
|
+
"vf-snap": !0
|
|
112
|
+
})} part="label">
|
|
113
|
+
<slot></slot>
|
|
114
|
+
</span>
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
updated(e) {
|
|
118
|
+
super.updated(e), (e.has("checked") || e.has("value") || this.disabledChanged(e)) && this.syncFormValue(this.checked ? this.value : null);
|
|
119
|
+
}
|
|
120
|
+
formResetCallback() {
|
|
121
|
+
this.checked = this.formDefault(!1);
|
|
122
|
+
}
|
|
123
|
+
applyFormState() {
|
|
124
|
+
this.checked = !0;
|
|
125
|
+
}
|
|
126
|
+
activate() {
|
|
127
|
+
this.checked = !this.checked, this.focus(), s(this, "vf-change", { checked: this.checked }), c(this, "input"), c(this, "change");
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
t([h({
|
|
131
|
+
type: Boolean,
|
|
132
|
+
reflect: !0
|
|
133
|
+
})], _.prototype, "checked", void 0), t([h({ reflect: !0 })], _.prototype, "name", void 0), t([h()], _.prototype, "value", void 0), _ = t([e("vf-checkbox")], _);
|
|
134
|
+
//#endregion
|
|
135
|
+
export { _ as VfCheckbox };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
declare const VfContainer_base: (new (...args: any[]) => import("../size.js").VfSizedInterface) & (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
|
|
3
|
+
/**
|
|
4
|
+
* `<vf-container>` — a box that is nothing but its declared size.
|
|
5
|
+
*
|
|
6
|
+
* The kit's positioned-placement story (src/position.ts) ends with one line of
|
|
7
|
+
* CSS it can't write for you: children placed with `top`/`left` need a
|
|
8
|
+
* positioned ancestor, and while every kit container is one — a window body, a
|
|
9
|
+
* stack, a fieldset — a region of *your own* needs `position: relative` in a
|
|
10
|
+
* stylesheet. This component is that region as an element: declare `width` and
|
|
11
|
+
* `height` in whole system px, slot anything into it, place children against
|
|
12
|
+
* its origin. A DITL's enclosing rectangle, with nothing drawn in it.
|
|
13
|
+
*
|
|
14
|
+
* ```html
|
|
15
|
+
* <vf-container width="200" height="120">
|
|
16
|
+
* <vf-icon label="System" width="64" top="8" left="12">…</vf-icon>
|
|
17
|
+
* <vf-icon label="Finder" width="64" top="8" left="104">…</vf-icon>
|
|
18
|
+
* </vf-container>
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* The rectangle is the whole API — `width`/`height` here, plus the `top`/`left`
|
|
22
|
+
* pair nearly every component takes ({@link VfPositioned}), so a container is
|
|
23
|
+
* itself placeable: inside a window, a desktop, or another container, at whole
|
|
24
|
+
* system px that keep its box on the device-pixel grid by construction.
|
|
25
|
+
*
|
|
26
|
+
* **It is not a `vf-stack`.** The stack is a flexbox with opinions — it
|
|
27
|
+
* distributes children along an axis, compiles `fill-width`/`fill-height` into
|
|
28
|
+
* flex, defaults a cross-axis alignment. This box has no layout opinion at
|
|
29
|
+
* all: in-flow children get normal flow, placed children get a coordinate
|
|
30
|
+
* system, and that is the whole API. Reach for it when the stack's opinions
|
|
31
|
+
* are the thing in the way — a field of placed icons, a fixed stage for
|
|
32
|
+
* absolutely-positioned art, a consumer's own composition that brings its
|
|
33
|
+
* layout with it.
|
|
34
|
+
*
|
|
35
|
+
* **The declared size is the layout.** `width`/`height` land on the host as a
|
|
36
|
+
* live `calc(var(--vf-scale, 1) * Npx)` ({@link VfSized}), so the box scales
|
|
37
|
+
* with the display and sits on the device-pixel grid by construction. Content
|
|
38
|
+
* that outgrows the box overflows it rather than growing it — the number is
|
|
39
|
+
* the layout, and content that doesn't fit is a number to raise. Leave a
|
|
40
|
+
* dimension off and that axis shrink-wraps: `fit-content`, not the parent's
|
|
41
|
+
* width, because a layout box that silently claimed a size nobody declared
|
|
42
|
+
* would be inventing one (the `vf-stack` rule, held here too).
|
|
43
|
+
*
|
|
44
|
+
* **It paints nothing and means nothing.** No border, background, role,
|
|
45
|
+
* keyboard behavior or selection — what it holds decides what it is.
|
|
46
|
+
*
|
|
47
|
+
* **It holds its box on the device-pixel grid** — with a `GridSnapController`.
|
|
48
|
+
* A container's box is itself the consumer's coordinate system, including for
|
|
49
|
+
* non-`vf` content that cannot correct itself, so the box is the thing to
|
|
50
|
+
* hold on the grid. The shadow box below owns the `position: relative` anchor
|
|
51
|
+
* and the `vf-snap` class together, so under `applyGridSnap()` the correction
|
|
52
|
+
* moves the whole coordinate system — everything placed against it rides
|
|
53
|
+
* along instead of being re-corrected child by child. (`vf-stack` shipped
|
|
54
|
+
* without a controller on the theory that slotted `vf-*` children correct
|
|
55
|
+
* their own origins; this component is where that theory's gap — consumer
|
|
56
|
+
* content — became visible, and the stack has since adopted the same
|
|
57
|
+
* arrangement.)
|
|
58
|
+
*
|
|
59
|
+
* Like the stack it is **typographically transparent**: `vfBase`'s chrome
|
|
60
|
+
* dress is returned to `inherit` on the host, so wrapping content in a sized
|
|
61
|
+
* box changes nothing about how that content reads.
|
|
62
|
+
*
|
|
63
|
+
* `fill-width` / `fill-height` work here the way they do everywhere: read
|
|
64
|
+
* about the host (be as big as *its* parent allows), and compiled for slotted
|
|
65
|
+
* children — `width: 100%` in normal flow, so a child filling the cross of a
|
|
66
|
+
* declared box needs no stylesheet. A height fill needs a declared `height`
|
|
67
|
+
* to resolve against; with none it is inert, not an error.
|
|
68
|
+
*
|
|
69
|
+
* @slot - The content. In flow by default; `top`/`left` on a kit child places
|
|
70
|
+
* it against this box's origin. `fill-width` / `fill-height` on a child
|
|
71
|
+
* fills it to the declared box.
|
|
72
|
+
*/
|
|
73
|
+
export declare class VfContainer extends VfContainer_base {
|
|
74
|
+
static styles: import("lit").CSSResult[];
|
|
75
|
+
/**
|
|
76
|
+
* Default-on display scaling (true 72dpi size); see src/scale.ts. Without
|
|
77
|
+
* one, a lone container on a plain page would resolve its declared size
|
|
78
|
+
* against the `var(--vf-scale, 1)` fallback while its slotted children each
|
|
79
|
+
* self-scaled around it — the vf-stack reasoning, inherited with the rest.
|
|
80
|
+
*/
|
|
81
|
+
private readonly scale;
|
|
82
|
+
/**
|
|
83
|
+
* Hold the box on the device-pixel grid under `applyGridSnap()` — see the
|
|
84
|
+
* class doc. The host is what gets measured; `.box` (vf-snap) is where the
|
|
85
|
+
* correction lands.
|
|
86
|
+
*/
|
|
87
|
+
private readonly gridSnap;
|
|
88
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
89
|
+
}
|
|
90
|
+
declare global {
|
|
91
|
+
interface HTMLElementTagNameMap {
|
|
92
|
+
'vf-container': VfContainer;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
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 { vfBase as i } from "../styles/recipes/host.js";
|
|
6
|
+
import { GridSnapController as a } from "../grid-snap.js";
|
|
7
|
+
import { VfSized as o } from "../size.js";
|
|
8
|
+
import { LitElement as s, css as c, html as l } from "lit";
|
|
9
|
+
//#region src/components/vf-container.ts
|
|
10
|
+
var u = class extends o(r(s)) {
|
|
11
|
+
constructor(...e) {
|
|
12
|
+
super(...e), this.scale = new t(this), this.gridSnap = new a(this);
|
|
13
|
+
}
|
|
14
|
+
static {
|
|
15
|
+
this.styles = [i, c`
|
|
16
|
+
:host {
|
|
17
|
+
display: block;
|
|
18
|
+
/* Shrink-wrap an undeclared axis rather than claim the parent's
|
|
19
|
+
width — the vf-stack rule: a layout box must not hand out a size
|
|
20
|
+
nobody declared. A declared width/height lands on the host's inline
|
|
21
|
+
style (VfSized) and beats this. */
|
|
22
|
+
width: fit-content;
|
|
23
|
+
/* Typographic transparency — the same reset vf-stack carries, for the
|
|
24
|
+
same reason: vfBase dresses a host as chrome (body face, ratio line
|
|
25
|
+
box, black, unselectable), and a box that holds no text of its own
|
|
26
|
+
must not change how slotted content reads. font is a shorthand, so
|
|
27
|
+
it carries the line box back with the family, size and weight. */
|
|
28
|
+
font: inherit;
|
|
29
|
+
-webkit-font-smoothing: inherit;
|
|
30
|
+
color: inherit;
|
|
31
|
+
user-select: inherit;
|
|
32
|
+
-webkit-user-select: inherit;
|
|
33
|
+
text-align: inherit;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* The coordinate system, as one shadow box coinciding with the host box.
|
|
37
|
+
vf-snap (vfBase) gives it position: relative plus the controller's
|
|
38
|
+
--vf-snap-dx/-dy offset — so it is BOTH the positioning anchor for
|
|
39
|
+
children placed with top/left (src/position.ts) AND the element the
|
|
40
|
+
grid-snap correction lands on. One element owning both is the point:
|
|
41
|
+
corrected, it takes every placed child with it, kit or not. */
|
|
42
|
+
.box {
|
|
43
|
+
/* flow-root: contain slotted margins, so the box's top edge — the
|
|
44
|
+
origin placed children measure from — stays glued to the host's
|
|
45
|
+
corner instead of being pushed down by a first child's margin
|
|
46
|
+
collapsing through. */
|
|
47
|
+
display: flow-root;
|
|
48
|
+
/* Coincide with a declared height (100% of a definite host height;
|
|
49
|
+
against an undeclared one it computes to auto and wraps content),
|
|
50
|
+
so slotted percentage fills resolve against the stated box. */
|
|
51
|
+
height: 100%;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* The same two words a child uses, read about the host itself — for the
|
|
55
|
+
parents that can give this box a size: a window body, a filled stack
|
|
56
|
+
column, a grid cell. A percentage is the one fill a page can always
|
|
57
|
+
express; a declared width/height on the inline style beats it. */
|
|
58
|
+
:host([fill-width]) {
|
|
59
|
+
width: 100%;
|
|
60
|
+
}
|
|
61
|
+
:host([fill-height]) {
|
|
62
|
+
height: 100%;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* And compiled for slotted children. Normal flow has no flex axes to
|
|
66
|
+
translate onto, so both fills are the percentage form: width resolves
|
|
67
|
+
against the box always, height only against a declared height —
|
|
68
|
+
percentage-against-auto computes to auto, so a fill with nothing to
|
|
69
|
+
take is inert, not an error (the vf-stack wording, kept true here). A
|
|
70
|
+
light-DOM declaration beats a ::slotted one, so a page can still
|
|
71
|
+
override either on its own children. */
|
|
72
|
+
::slotted([fill-width]) {
|
|
73
|
+
width: 100%;
|
|
74
|
+
}
|
|
75
|
+
::slotted([fill-height]) {
|
|
76
|
+
height: 100%;
|
|
77
|
+
}
|
|
78
|
+
`];
|
|
79
|
+
}
|
|
80
|
+
render() {
|
|
81
|
+
return l`<div class="vf-snap box"><slot></slot></div>`;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
u = n([e("vf-container")], u);
|
|
85
|
+
//#endregion
|
|
86
|
+
export { u as VfContainer };
|