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,69 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { PropertyValues } from 'lit';
|
|
3
|
+
declare const VfProgressBar_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
|
|
4
|
+
/**
|
|
5
|
+
* `<vf-progress-bar>` — the System 7 progress indicator.
|
|
6
|
+
*
|
|
7
|
+
* A 14px white track (`--vf-progress-track`) with a 1px black border.
|
|
8
|
+
* Determinate mode fills from the left in solid black
|
|
9
|
+
* (`--vf-progress-fill`) with a 1px black leading edge. Indeterminate
|
|
10
|
+
* mode shows chunky, stepped diagonal black/white barber stripes (the classic
|
|
11
|
+
* "busy" bar) animated with `steps()` timing so movement is deliberately
|
|
12
|
+
* steppy, not smooth.
|
|
13
|
+
*
|
|
14
|
+
* Exposes `role="progressbar"` with `aria-valuemin/max` and, when
|
|
15
|
+
* determinate, `aria-valuenow`.
|
|
16
|
+
*
|
|
17
|
+
* @csspart track - The outer bordered track.
|
|
18
|
+
* @csspart fill - The determinate fill or the indeterminate stripe layer.
|
|
19
|
+
* @cssprop [--vf-progress-fill=#000000] - determinate progress fill (solid
|
|
20
|
+
* black)
|
|
21
|
+
* @cssprop --vf-progress-stripes - the indeterminate barber stripes — a 12×12
|
|
22
|
+
* motif drawn as rects so the staircase stays whole system px at any scale,
|
|
23
|
+
* on a 60-system-px tile (override the whole tile — consumer art renders as
|
|
24
|
+
* a placed tile grid at that same geometry)
|
|
25
|
+
* @cssprop [--vf-progress-track=#ffffff] - progress track (white)
|
|
26
|
+
*/
|
|
27
|
+
export declare class VfProgressBar extends VfProgressBar_base {
|
|
28
|
+
#private;
|
|
29
|
+
static styles: import("lit").CSSResult[];
|
|
30
|
+
private readonly scale;
|
|
31
|
+
/** Device-pixel grid snapping (opt in with applyGridSnap()); see src/grid-snap.ts. */
|
|
32
|
+
private readonly gridSnap;
|
|
33
|
+
/** Current progress, from 0 to `max`. Clamped for display and ARIA. */
|
|
34
|
+
value: number;
|
|
35
|
+
/** Maximum value (default 100). */
|
|
36
|
+
max: number;
|
|
37
|
+
/** Barber-pole "busy" mode; ignores `value` and omits `aria-valuenow`. */
|
|
38
|
+
indeterminate: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Accessible name for the bar, applied as the host's `aria-label` (which
|
|
41
|
+
* carries `role="progressbar"`). Especially useful in `indeterminate` mode,
|
|
42
|
+
* where there is no `aria-valuenow` to describe the bar. A consumer-supplied
|
|
43
|
+
* `aria-label`/`aria-labelledby` attribute is left alone.
|
|
44
|
+
*/
|
|
45
|
+
label: string;
|
|
46
|
+
private track;
|
|
47
|
+
/** Track the fill area's width so the determinate fill can snap to it. */
|
|
48
|
+
private readonly trackSize;
|
|
49
|
+
/**
|
|
50
|
+
* The consumer's `--vf-progress-stripes` override, or `''` for the kit
|
|
51
|
+
* barber — which exact-fill path the strip takes (src/tile-grid.ts).
|
|
52
|
+
* Re-read every update; a runtime token swap wants a `requestUpdate()`.
|
|
53
|
+
*/
|
|
54
|
+
private _pattern;
|
|
55
|
+
constructor();
|
|
56
|
+
/** Effective maximum: a non-positive `max` is treated as the default 100. */
|
|
57
|
+
private get effectiveMax();
|
|
58
|
+
/** `value` clamped to `[0, effectiveMax]`. */
|
|
59
|
+
private get clampedValue();
|
|
60
|
+
protected willUpdate(changed: PropertyValues<this>): void;
|
|
61
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
62
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
63
|
+
}
|
|
64
|
+
declare global {
|
|
65
|
+
interface HTMLElementTagNameMap {
|
|
66
|
+
'vf-progress-bar': VfProgressBar;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { vfElement as e } from "../define.js";
|
|
2
|
+
import { ScaleController as t, sys as n, sysLength as r, toSys as i } from "../scale.js";
|
|
3
|
+
import a from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
|
|
4
|
+
import { VfPositioned as o } from "../position.js";
|
|
5
|
+
import { vfBase as s } from "../styles/recipes/host.js";
|
|
6
|
+
import { tileImage as c, tileRects as l, tileSpan as u, vfTileMaskSize as d } from "../styles/recipes/tile.js";
|
|
7
|
+
import { TileRasterCache as f, patternOverride as p, tileGrid as m, vfTileGrid as h } from "../tile-grid.js";
|
|
8
|
+
import { GridSnapController as g } from "../grid-snap.js";
|
|
9
|
+
import { TrackWidthController as _ } from "../track-width.js";
|
|
10
|
+
import { LitElement as v, css as y, html as b, unsafeCSS as x } from "lit";
|
|
11
|
+
import { property as S, query as C } from "lit/decorators.js";
|
|
12
|
+
//#region src/components/vf-progress-bar.ts
|
|
13
|
+
var w = 12, T = [
|
|
14
|
+
[
|
|
15
|
+
0,
|
|
16
|
+
0,
|
|
17
|
+
6,
|
|
18
|
+
1
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
1,
|
|
22
|
+
1,
|
|
23
|
+
6,
|
|
24
|
+
1
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
2,
|
|
28
|
+
2,
|
|
29
|
+
6,
|
|
30
|
+
1
|
|
31
|
+
],
|
|
32
|
+
[
|
|
33
|
+
3,
|
|
34
|
+
3,
|
|
35
|
+
6,
|
|
36
|
+
1
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
4,
|
|
40
|
+
4,
|
|
41
|
+
6,
|
|
42
|
+
1
|
|
43
|
+
],
|
|
44
|
+
[
|
|
45
|
+
5,
|
|
46
|
+
5,
|
|
47
|
+
6,
|
|
48
|
+
1
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
6,
|
|
52
|
+
6,
|
|
53
|
+
6,
|
|
54
|
+
1
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
0,
|
|
58
|
+
7,
|
|
59
|
+
1,
|
|
60
|
+
1
|
|
61
|
+
],
|
|
62
|
+
[
|
|
63
|
+
7,
|
|
64
|
+
7,
|
|
65
|
+
5,
|
|
66
|
+
1
|
|
67
|
+
],
|
|
68
|
+
[
|
|
69
|
+
0,
|
|
70
|
+
8,
|
|
71
|
+
2,
|
|
72
|
+
1
|
|
73
|
+
],
|
|
74
|
+
[
|
|
75
|
+
8,
|
|
76
|
+
8,
|
|
77
|
+
4,
|
|
78
|
+
1
|
|
79
|
+
],
|
|
80
|
+
[
|
|
81
|
+
0,
|
|
82
|
+
9,
|
|
83
|
+
3,
|
|
84
|
+
1
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
9,
|
|
88
|
+
9,
|
|
89
|
+
3,
|
|
90
|
+
1
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
0,
|
|
94
|
+
10,
|
|
95
|
+
4,
|
|
96
|
+
1
|
|
97
|
+
],
|
|
98
|
+
[
|
|
99
|
+
10,
|
|
100
|
+
10,
|
|
101
|
+
2,
|
|
102
|
+
1
|
|
103
|
+
],
|
|
104
|
+
[
|
|
105
|
+
0,
|
|
106
|
+
11,
|
|
107
|
+
5,
|
|
108
|
+
1
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
11,
|
|
112
|
+
11,
|
|
113
|
+
1,
|
|
114
|
+
1
|
|
115
|
+
]
|
|
116
|
+
], E = c(w, w, l(T)), D = u(w), O = class extends o(v) {
|
|
117
|
+
static {
|
|
118
|
+
this.styles = [
|
|
119
|
+
s,
|
|
120
|
+
h,
|
|
121
|
+
y`
|
|
122
|
+
:host {
|
|
123
|
+
display: block;
|
|
124
|
+
height: calc(var(--vf-scale, 1) * 14px);
|
|
125
|
+
}
|
|
126
|
+
.track {
|
|
127
|
+
position: relative;
|
|
128
|
+
height: 100%;
|
|
129
|
+
background: var(--vf-progress-track, #ffffff);
|
|
130
|
+
border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
|
|
131
|
+
border-radius: 0;
|
|
132
|
+
overflow: hidden;
|
|
133
|
+
}
|
|
134
|
+
.fill {
|
|
135
|
+
height: 100%;
|
|
136
|
+
background: var(--vf-progress-fill, #000000);
|
|
137
|
+
/* The classic 1px black leading edge. */
|
|
138
|
+
border-right: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
|
|
139
|
+
}
|
|
140
|
+
.fill.empty {
|
|
141
|
+
border-right: none;
|
|
142
|
+
}
|
|
143
|
+
.fill.stripes {
|
|
144
|
+
width: 100%;
|
|
145
|
+
border-right: none;
|
|
146
|
+
/* Chunky 45° barber stripes: a 12×12 system-px cell whose two black
|
|
147
|
+
\ bands are a staircase of axis-aligned 1px rects (genuine pixel
|
|
148
|
+
art — a *diagonal* edge would blur where these stay pixel-exact)
|
|
149
|
+
over this themeable white ground. The art itself rides the
|
|
150
|
+
.vf-tile-strip child (src/tile-grid.ts): the kit's whole-surface
|
|
151
|
+
raster, or a consumer --vf-progress-stripes token's placed tile
|
|
152
|
+
grid at the token's documented 60-px tile geometry. This layer is
|
|
153
|
+
the strip's containing block and its clip. */
|
|
154
|
+
position: relative;
|
|
155
|
+
background-color: var(--vf-white, #fff);
|
|
156
|
+
--_vf-tile-image: var(--vf-progress-stripes, ${x(E)});
|
|
157
|
+
}
|
|
158
|
+
/* The animated strip: rests one 12px cell to the left (fully covering
|
|
159
|
+
the fill), and each cycle advances one whole cell in 4 chunky steps —
|
|
160
|
+
steppy, not smooth, wrapping with zero phase jump because the art's
|
|
161
|
+
period is the cell. The animated value is a layout property, so
|
|
162
|
+
every step is one quantized length paint-snapped like any placed
|
|
163
|
+
box — no CSS length ever accumulates a phase. */
|
|
164
|
+
.vf-tile-strip {
|
|
165
|
+
position: absolute;
|
|
166
|
+
top: 0;
|
|
167
|
+
height: 100%;
|
|
168
|
+
left: calc(var(--vf-scale, 1) * -12px);
|
|
169
|
+
animation: vf-barber 0.4s steps(4, end) infinite;
|
|
170
|
+
}
|
|
171
|
+
@keyframes vf-barber {
|
|
172
|
+
from {
|
|
173
|
+
left: calc(var(--vf-scale, 1) * -12px);
|
|
174
|
+
}
|
|
175
|
+
to {
|
|
176
|
+
left: 0;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/* Forced colors: the fill and track are the bar's whole reading, and
|
|
180
|
+
both have their own tokens with literal fallbacks the override
|
|
181
|
+
flattens to Canvas — remapped here like the palette tokens in vfBase.
|
|
182
|
+
The strip's raster art would keep its literal black ink (invisible on
|
|
183
|
+
a dark theme), so the strip hides and the layer repaints as a mask
|
|
184
|
+
over the ink token — same tile, same token a consumer overrides —
|
|
185
|
+
with the animation on the mask's position. The span-tiled mask keeps
|
|
186
|
+
the zoom caveat (no mask pipeline rasterizes exactly at a zoom-minted
|
|
187
|
+
scale); forced-colors-plus-zoom stays the accepted residual. */
|
|
188
|
+
@media (forced-colors: active) {
|
|
189
|
+
:host {
|
|
190
|
+
--vf-progress-fill: CanvasText;
|
|
191
|
+
--vf-progress-track: Canvas;
|
|
192
|
+
}
|
|
193
|
+
.fill.stripes {
|
|
194
|
+
background-color: var(--vf-progress-fill, CanvasText);
|
|
195
|
+
mask-image: var(--vf-progress-stripes, ${x(E)});
|
|
196
|
+
${d(w)}
|
|
197
|
+
animation: vf-barber-mask 0.4s steps(4, end) infinite;
|
|
198
|
+
}
|
|
199
|
+
.fill.stripes .vf-tile-strip {
|
|
200
|
+
display: none;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
@keyframes vf-barber-mask {
|
|
204
|
+
from {
|
|
205
|
+
mask-position: 0 0;
|
|
206
|
+
}
|
|
207
|
+
to {
|
|
208
|
+
mask-position: calc(var(--vf-scale, 1) * 12px) 0;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
@media (prefers-reduced-motion: reduce) {
|
|
212
|
+
.fill.stripes,
|
|
213
|
+
.vf-tile-strip {
|
|
214
|
+
animation: none;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
`
|
|
218
|
+
];
|
|
219
|
+
}
|
|
220
|
+
#e;
|
|
221
|
+
#t;
|
|
222
|
+
constructor() {
|
|
223
|
+
super(), this.scale = new t(this), this.gridSnap = new g(this), this.value = 0, this.max = 100, this.indeterminate = !1, this.label = "", this.trackSize = new _(this, () => this.track), this._pattern = "", this.#e = new f(), this.#t = this.attachInternals(), this.#t.role = "progressbar", this.#t.ariaValueMin = "0";
|
|
224
|
+
}
|
|
225
|
+
get effectiveMax() {
|
|
226
|
+
return this.max > 0 ? this.max : 100;
|
|
227
|
+
}
|
|
228
|
+
get clampedValue() {
|
|
229
|
+
return Math.min(Math.max(this.value, 0), this.effectiveMax);
|
|
230
|
+
}
|
|
231
|
+
willUpdate(e) {
|
|
232
|
+
super.willUpdate(e), this.indeterminate && (this._pattern = p(this, "--vf-progress-stripes"));
|
|
233
|
+
}
|
|
234
|
+
updated(e) {
|
|
235
|
+
e.has("label") && (this.#t.ariaLabel = this.label || null), e.has("max") && (this.#t.ariaValueMax = String(this.effectiveMax)), (e.has("value") || e.has("max") || e.has("indeterminate")) && (this.#t.ariaValueNow = this.indeterminate ? null : String(this.clampedValue));
|
|
236
|
+
}
|
|
237
|
+
render() {
|
|
238
|
+
if (this.indeterminate) {
|
|
239
|
+
let e = i(this.trackSize.width, this), t = Math.max(D, Math.ceil((e + w) / D) * D), n = this._pattern ? m({
|
|
240
|
+
cols: t / D,
|
|
241
|
+
rows: 1,
|
|
242
|
+
tile: D
|
|
243
|
+
}) : b`<div
|
|
244
|
+
class="vf-tile-raster"
|
|
245
|
+
style="width:${r(t)};height:${r(24)};background-image:${this.#e.for(w, w, T, t, 24)}"
|
|
246
|
+
></div>`;
|
|
247
|
+
return b`
|
|
248
|
+
<div class="track vf-snap" part="track">
|
|
249
|
+
<div class="fill stripes vf-tile-grid" part="fill">
|
|
250
|
+
<div class="vf-tile-strip">${n}</div>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
`;
|
|
254
|
+
}
|
|
255
|
+
let e = this.clampedValue / this.effectiveMax, t = i(this.trackSize.width, this), a = t > 0 ? `${n(Math.round(e * t), this)}px` : `${e * 100}%`;
|
|
256
|
+
return b`
|
|
257
|
+
<div class="track vf-snap" part="track">
|
|
258
|
+
<div
|
|
259
|
+
class="fill ${e <= 0 ? "empty" : ""}"
|
|
260
|
+
part="fill"
|
|
261
|
+
style="width: ${a}"
|
|
262
|
+
></div>
|
|
263
|
+
</div>
|
|
264
|
+
`;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
a([S({ type: Number })], O.prototype, "value", void 0), a([S({ type: Number })], O.prototype, "max", void 0), a([S({
|
|
268
|
+
type: Boolean,
|
|
269
|
+
reflect: !0
|
|
270
|
+
})], O.prototype, "indeterminate", void 0), a([S()], O.prototype, "label", void 0), a([C(".track")], O.prototype, "track", void 0), O = a([e("vf-progress-bar")], O);
|
|
271
|
+
//#endregion
|
|
272
|
+
export { O as VfProgressBar };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { PropertyValues } from 'lit';
|
|
2
|
+
import { VfFormControl } from '../form-control.js';
|
|
3
|
+
declare const VfRadioGroup_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof VfFormControl;
|
|
4
|
+
/**
|
|
5
|
+
* Groups `vf-radio` children, owning selection, keyboard navigation and the
|
|
6
|
+
* form value. Renders no chrome of its own; directly slotted radios stack
|
|
7
|
+
* vertically with a 6px gap (override with your own layout if needed —
|
|
8
|
+
* arbitrary markup containing radios also works).
|
|
9
|
+
*
|
|
10
|
+
* Form-associated: submits `value` under `name`, restores the initial value
|
|
11
|
+
* on form reset. Keeps children in sync — the child whose `value` matches
|
|
12
|
+
* the group's `value` is checked, all others unchecked.
|
|
13
|
+
*
|
|
14
|
+
* Keyboard (classic Mac behavior): the group is one tab stop (roving
|
|
15
|
+
* tabindex on the selected radio); ArrowUp/ArrowLeft and
|
|
16
|
+
* ArrowDown/ArrowRight move the selection AND select it, wrapping around
|
|
17
|
+
* and skipping disabled radios.
|
|
18
|
+
*
|
|
19
|
+
* @slot - `vf-radio` elements, or arbitrary markup containing them.
|
|
20
|
+
* @fires vf-change - When the selection changes via user interaction. `detail: { value: string }`.
|
|
21
|
+
* @fires input - Native event, dispatched from the group (the form-associated
|
|
22
|
+
* surface) per user pick. A programmatic `value` set fires nothing.
|
|
23
|
+
* @fires change - Native event, dispatched from the group per user pick so
|
|
24
|
+
* form delegation and framework bindings hear it.
|
|
25
|
+
*/
|
|
26
|
+
export declare class VfRadioGroup extends VfRadioGroup_base {
|
|
27
|
+
static styles: import("lit").CSSResult[];
|
|
28
|
+
/**
|
|
29
|
+
* The value of the selected radio. An empty string means no selection
|
|
30
|
+
* (and nothing is submitted with the form).
|
|
31
|
+
*/
|
|
32
|
+
value: string;
|
|
33
|
+
/** Form field name used when submitting. */
|
|
34
|
+
name: string;
|
|
35
|
+
/**
|
|
36
|
+
* Accessible name for the group, exposed as the `radiogroup`'s `aria-label`.
|
|
37
|
+
* Without it a caption-less group is announced anonymously.
|
|
38
|
+
*/
|
|
39
|
+
label: string;
|
|
40
|
+
/** No radio checked — the state `required` calls a missing value. */
|
|
41
|
+
protected get valueMissing(): boolean;
|
|
42
|
+
/** The message a native required radio group reports. */
|
|
43
|
+
protected get valueMissingMessage(): string;
|
|
44
|
+
private readonly scale;
|
|
45
|
+
/**
|
|
46
|
+
* Re-syncs the group when its radios change structurally or by value —
|
|
47
|
+
* covers radios added/removed inside arbitrary wrapper markup (no top-level
|
|
48
|
+
* slotchange fires) and a child radio's value/disabled changing at runtime.
|
|
49
|
+
*/
|
|
50
|
+
private mutationObserver;
|
|
51
|
+
constructor();
|
|
52
|
+
connectedCallback(): void;
|
|
53
|
+
disconnectedCallback(): void;
|
|
54
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
55
|
+
protected willUpdate(changed: PropertyValues<this>): void;
|
|
56
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
57
|
+
/** Form-associated lifecycle: restores the initial value. */
|
|
58
|
+
formResetCallback(): void;
|
|
59
|
+
/** All descendant radios belonging to this group (nested groups excluded). */
|
|
60
|
+
private get radios();
|
|
61
|
+
/**
|
|
62
|
+
* Identity of the state {@link syncRadios} pushes down, and the value it
|
|
63
|
+
* last pushed. Everything the children receive derives from these two, so
|
|
64
|
+
* comparing them tells `updated()` whether a sync would be a no-op.
|
|
65
|
+
*
|
|
66
|
+
* It intentionally doesn't track the children themselves: a structural or
|
|
67
|
+
* value/disabled change reaches `syncRadios()` directly (via the mutation
|
|
68
|
+
* observer or slotchange), never through this gate.
|
|
69
|
+
*/
|
|
70
|
+
private get syncKey();
|
|
71
|
+
private syncedKey;
|
|
72
|
+
/**
|
|
73
|
+
* Push group state down to the children: checked flags, group-disabled
|
|
74
|
+
* dimming, and the roving tabindex (the checked radio is the tab stop;
|
|
75
|
+
* with no selection, the first enabled radio is).
|
|
76
|
+
*/
|
|
77
|
+
private syncRadios;
|
|
78
|
+
/**
|
|
79
|
+
* Moves keyboard focus to the group's roving tab stop — the checked radio,
|
|
80
|
+
* else the first enabled one. Overridden because the platform's `focus()`
|
|
81
|
+
* is a silent no-op on this host (no `delegatesFocus`, no host tabindex),
|
|
82
|
+
* so `vf-label for` (which calls `target.focus()`) never reached the group.
|
|
83
|
+
*/
|
|
84
|
+
focus(options?: FocusOptions): void;
|
|
85
|
+
/**
|
|
86
|
+
* Select a radio, sync everything, and fire `vf-change` if value changed.
|
|
87
|
+
*
|
|
88
|
+
* The sync stays synchronous — a `vf-change` listener must see the children
|
|
89
|
+
* already carrying the new selection, not the state of a pending update —
|
|
90
|
+
* and `updated()` then skips its own pass via the sync key.
|
|
91
|
+
*/
|
|
92
|
+
private selectRadio;
|
|
93
|
+
/** A child radio was clicked or Space-selected: adopt it. */
|
|
94
|
+
private handleRadioChange;
|
|
95
|
+
/** Arrow keys move the selection AND select (classic Mac behavior). */
|
|
96
|
+
private handleKeydown;
|
|
97
|
+
/**
|
|
98
|
+
* With no value of its own, adopt a pre-checked radio's value — and treat
|
|
99
|
+
* it as the form-reset default.
|
|
100
|
+
*/
|
|
101
|
+
private adoptPreChecked;
|
|
102
|
+
private handleSlotChange;
|
|
103
|
+
}
|
|
104
|
+
declare global {
|
|
105
|
+
interface HTMLElementTagNameMap {
|
|
106
|
+
'vf-radio-group': VfRadioGroup;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
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 { emit as a, emitNative as o } from "../events.js";
|
|
7
|
+
import { VfFormControl as s } from "../form-control.js";
|
|
8
|
+
import { VfRadio as c } from "./vf-radio.js";
|
|
9
|
+
import { css as l, html as u } from "lit";
|
|
10
|
+
import { property as d } from "lit/decorators.js";
|
|
11
|
+
//#region src/components/vf-radio-group.ts
|
|
12
|
+
var f = class extends r(s) {
|
|
13
|
+
static {
|
|
14
|
+
this.styles = [i, l`
|
|
15
|
+
:host {
|
|
16
|
+
display: block;
|
|
17
|
+
}
|
|
18
|
+
::slotted(vf-radio) {
|
|
19
|
+
display: flex;
|
|
20
|
+
}
|
|
21
|
+
::slotted(vf-radio:not(:first-child)) {
|
|
22
|
+
margin-top: calc(var(--vf-scale, 1) * 6px);
|
|
23
|
+
}
|
|
24
|
+
`];
|
|
25
|
+
}
|
|
26
|
+
get valueMissing() {
|
|
27
|
+
return this.value === "";
|
|
28
|
+
}
|
|
29
|
+
get valueMissingMessage() {
|
|
30
|
+
return "Please select one of these options.";
|
|
31
|
+
}
|
|
32
|
+
constructor() {
|
|
33
|
+
super(), this.value = "", this.name = "", this.label = "", this.scale = new t(this), this.mutationObserver = null, this.syncedKey = null, this.handleRadioChange = (e) => {
|
|
34
|
+
let t = e.target;
|
|
35
|
+
t === this || !(t instanceof c) || t.closest("vf-radio-group") === this && (this.isDisabled || t.disabled || this.selectRadio(t, !1));
|
|
36
|
+
}, this.handleKeydown = (e) => {
|
|
37
|
+
if (this.isDisabled) return;
|
|
38
|
+
let t = e.key, n = 0;
|
|
39
|
+
if (t === "ArrowDown" || t === "ArrowRight") n = 1;
|
|
40
|
+
else if (t === "ArrowUp" || t === "ArrowLeft") n = -1;
|
|
41
|
+
else return;
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
let r = this.radios.filter((e) => !e.disabled);
|
|
44
|
+
if (r.length === 0) return;
|
|
45
|
+
let i = e.target instanceof c ? e.target : this.radios.find((e) => e.checked), a = i ? r.indexOf(i) : -1, o = r[a === -1 ? n > 0 ? 0 : r.length - 1 : (a + n + r.length) % r.length];
|
|
46
|
+
o && this.selectRadio(o, !0);
|
|
47
|
+
}, this.handleSlotChange = () => {
|
|
48
|
+
this.adoptPreChecked(), this.syncRadios();
|
|
49
|
+
}, this.internals.role = "radiogroup", this.addEventListener("keydown", this.handleKeydown), this.addEventListener("vf-change", this.handleRadioChange);
|
|
50
|
+
}
|
|
51
|
+
connectedCallback() {
|
|
52
|
+
super.connectedCallback(), this.value !== "" && this.latchFormDefault(this.value), this.mutationObserver ??= new MutationObserver((e) => {
|
|
53
|
+
e.every((e) => e.type === "attributes" && e.target === this) || this.syncRadios();
|
|
54
|
+
}), this.mutationObserver.observe(this, {
|
|
55
|
+
childList: !0,
|
|
56
|
+
subtree: !0,
|
|
57
|
+
attributes: !0,
|
|
58
|
+
attributeFilter: ["value", "disabled"]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
disconnectedCallback() {
|
|
62
|
+
super.disconnectedCallback(), this.mutationObserver?.disconnect();
|
|
63
|
+
}
|
|
64
|
+
render() {
|
|
65
|
+
return u`<slot @slotchange=${this.handleSlotChange}></slot>`;
|
|
66
|
+
}
|
|
67
|
+
willUpdate(e) {
|
|
68
|
+
this.hasUpdated || this.adoptPreChecked(), super.willUpdate(e);
|
|
69
|
+
}
|
|
70
|
+
updated(e) {
|
|
71
|
+
let t = this.disabledChanged(e);
|
|
72
|
+
(e.has("value") || t) && this.syncFormValue(this.value === "" ? null : this.value), e.has("label") && (this.internals.ariaLabel = this.label || null), t && (this.internals.ariaDisabled = this.isDisabled ? "true" : "false"), this.syncedKey !== this.syncKey && this.syncRadios();
|
|
73
|
+
}
|
|
74
|
+
formResetCallback() {
|
|
75
|
+
this.value = this.formDefault("");
|
|
76
|
+
}
|
|
77
|
+
get radios() {
|
|
78
|
+
return [...this.querySelectorAll("vf-radio")].filter((e) => e.closest("vf-radio-group") === this);
|
|
79
|
+
}
|
|
80
|
+
get syncKey() {
|
|
81
|
+
return `${this.isDisabled ? "d" : "e"}:${this.value}`;
|
|
82
|
+
}
|
|
83
|
+
syncRadios() {
|
|
84
|
+
let e = this.radios, t = this.isDisabled;
|
|
85
|
+
this.syncedKey = this.syncKey;
|
|
86
|
+
let n = this.value === "" ? void 0 : e.find((e) => e.value === this.value), r = n && !n.disabled ? n : void 0;
|
|
87
|
+
r ||= e.find((e) => !e.disabled);
|
|
88
|
+
for (let i of e) i.checked = i === n, i.groupDisabled = t, i.tabIndex = !t && i === r ? 0 : -1;
|
|
89
|
+
}
|
|
90
|
+
focus(e) {
|
|
91
|
+
this.radios.find((e) => e.tabIndex === 0)?.focus(e);
|
|
92
|
+
}
|
|
93
|
+
selectRadio(e, t) {
|
|
94
|
+
let n = this.value !== e.value;
|
|
95
|
+
this.value = e.value, this.syncRadios(), t && e.focus(), n && (a(this, "vf-change", { value: this.value }), o(this, "input"), o(this, "change"));
|
|
96
|
+
}
|
|
97
|
+
adoptPreChecked() {
|
|
98
|
+
if (this.value !== "") return;
|
|
99
|
+
let e = this.radios.find((e) => e.checked);
|
|
100
|
+
e && e.value !== "" && (this.value = e.value, this.latchFormDefault(this.value));
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
n([d()], f.prototype, "value", void 0), n([d({ reflect: !0 })], f.prototype, "name", void 0), n([d()], f.prototype, "label", void 0), f = n([e("vf-radio-group")], f);
|
|
104
|
+
//#endregion
|
|
105
|
+
export { f as VfRadioGroup };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
declare const VfRadio_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & (abstract new (...args: any[]) => import("../toggle-control.js").VfToggleControlInterface) & typeof LitElement;
|
|
3
|
+
/**
|
|
4
|
+
* A single System 7 radio button: a 13×13 white circle with the pixel-exact
|
|
5
|
+
* 1-bit ring and centered dot traced from the Classic Macintosh UI Kit sprite
|
|
6
|
+
* (replacing the anti-aliased `border-radius` rendering). The ring thickens
|
|
7
|
+
* while pressed, exactly like the original control.
|
|
8
|
+
*
|
|
9
|
+
* Radios are meant to live inside a `vf-radio-group`, which owns selection
|
|
10
|
+
* state, the form value and the roving tabindex. A `vf-radio` is NOT itself
|
|
11
|
+
* form-associated. Clicking (or pressing Space on) an unselected radio
|
|
12
|
+
* dispatches `vf-change`; the containing group listens, selects it and
|
|
13
|
+
* unselects its siblings.
|
|
14
|
+
*
|
|
15
|
+
* @slot - The label, rendered to the right of the circle with a 6px gap.
|
|
16
|
+
* @csspart circle - The 13×13 radio circle.
|
|
17
|
+
* @csspart label - The label wrapper around the slot.
|
|
18
|
+
* @fires vf-change - When selected by user interaction. `detail: { value: string }`.
|
|
19
|
+
*/
|
|
20
|
+
export declare class VfRadio extends VfRadio_base {
|
|
21
|
+
static styles: import("lit").CSSResult[];
|
|
22
|
+
/** Whether this radio is selected. Managed by the containing group. */
|
|
23
|
+
checked: boolean;
|
|
24
|
+
/** Disables this single radio: the label dims to gray; circle and dot stay black. */
|
|
25
|
+
disabled: boolean;
|
|
26
|
+
/** The value the containing `vf-radio-group` reports when selected. */
|
|
27
|
+
value: string;
|
|
28
|
+
/**
|
|
29
|
+
* True while the containing `vf-radio-group` is disabled. Managed by the
|
|
30
|
+
* group — not intended to be set by consumers.
|
|
31
|
+
*/
|
|
32
|
+
groupDisabled: boolean;
|
|
33
|
+
private readonly internals;
|
|
34
|
+
constructor();
|
|
35
|
+
/**
|
|
36
|
+
* A radio attaches its own internals: it is deliberately NOT form-associated
|
|
37
|
+
* (the enclosing `vf-radio-group` is the form surface), so there is no
|
|
38
|
+
* `VfFormControl` handle to inherit.
|
|
39
|
+
*/
|
|
40
|
+
protected get toggleInternals(): ElementInternals;
|
|
41
|
+
/** This radio's own `disabled`, or its group's. */
|
|
42
|
+
protected get toggleDisabled(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Inside a `vf-radio-group` the group is the single source of truth: it runs
|
|
45
|
+
* the roving tabindex and flips `checked` on the whole set. Standalone, this
|
|
46
|
+
* radio owns both — otherwise a bare radio would be keyboard-dead (its Space
|
|
47
|
+
* handler unreachable) and would never visibly toggle.
|
|
48
|
+
*/
|
|
49
|
+
protected get externallyCoordinated(): boolean;
|
|
50
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
51
|
+
/** Click/Space on an enabled, unselected radio selects it. */
|
|
52
|
+
protected activate(): void;
|
|
53
|
+
}
|
|
54
|
+
declare global {
|
|
55
|
+
interface HTMLElementTagNameMap {
|
|
56
|
+
'vf-radio': VfRadio;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export {};
|