vintage-frames 0.13.0 → 0.14.1

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.
Files changed (79) hide show
  1. package/README.md +16 -0
  2. package/custom-elements.json +184 -20
  3. package/dist/components/vf-checkbox.d.ts +6 -5
  4. package/dist/components/vf-checkbox.js +41 -37
  5. package/dist/components/vf-container.d.ts +14 -14
  6. package/dist/components/vf-container.js +58 -28
  7. package/dist/components/vf-desktop.d.ts +114 -12
  8. package/dist/components/vf-desktop.js +119 -58
  9. package/dist/components/vf-fieldset.js +30 -22
  10. package/dist/components/vf-icon-field.d.ts +1 -1
  11. package/dist/components/vf-icon.js +111 -104
  12. package/dist/components/vf-list.js +30 -29
  13. package/dist/components/vf-menu-bar.d.ts +5 -0
  14. package/dist/components/vf-menu-bar.js +67 -43
  15. package/dist/components/vf-menu.js +24 -22
  16. package/dist/components/vf-number-field.js +32 -30
  17. package/dist/components/vf-progress-bar.js +28 -29
  18. package/dist/components/vf-radio.js +3 -4
  19. package/dist/components/vf-scroll-area.js +27 -26
  20. package/dist/components/vf-select.js +108 -90
  21. package/dist/components/vf-separator.d.ts +5 -5
  22. package/dist/components/vf-separator.js +36 -10
  23. package/dist/components/vf-swatch.js +47 -45
  24. package/dist/components/vf-text-area.js +37 -35
  25. package/dist/components/vf-text-field.js +20 -18
  26. package/dist/components/vf-window.d.ts +13 -0
  27. package/dist/components/vf-window.js +101 -72
  28. package/dist/index.d.ts +12 -1
  29. package/dist/index.js +61 -59
  30. package/dist/pattern-fill.d.ts +11 -8
  31. package/dist/pattern-fill.js +2 -4
  32. package/dist/position.d.ts +25 -7
  33. package/dist/position.js +6 -3
  34. package/dist/shell/alert.d.ts +32 -0
  35. package/dist/shell/alert.js +44 -0
  36. package/dist/shell/catalog.d.ts +168 -0
  37. package/dist/shell/catalog.js +278 -0
  38. package/dist/shell/clock.d.ts +16 -0
  39. package/dist/shell/clock.js +36 -0
  40. package/dist/shell/filing.d.ts +39 -0
  41. package/dist/shell/filing.js +68 -0
  42. package/dist/shell/finder.d.ts +116 -0
  43. package/dist/shell/finder.js +564 -0
  44. package/dist/shell/geometry.d.ts +196 -0
  45. package/dist/shell/geometry.js +241 -0
  46. package/dist/shell/index.d.ts +29 -0
  47. package/dist/shell/index.js +11 -0
  48. package/dist/shell/shell.d.ts +150 -0
  49. package/dist/shell/shell.js +213 -0
  50. package/dist/shell/state.d.ts +88 -0
  51. package/dist/shell/state.js +103 -0
  52. package/dist/shell/storage.d.ts +14 -0
  53. package/dist/shell/storage.js +41 -0
  54. package/dist/shell/windows.d.ts +215 -0
  55. package/dist/shell/windows.js +343 -0
  56. package/dist/styles/base.d.ts +3 -1
  57. package/dist/styles/recipes/field.d.ts +10 -6
  58. package/dist/styles/recipes/field.js +8 -7
  59. package/dist/styles/recipes/focus.d.ts +7 -3
  60. package/dist/styles/recipes/rule.d.ts +11 -8
  61. package/dist/styles/recipes/rule.js +31 -13
  62. package/dist/styles/recipes/scroll-rail.d.ts +7 -6
  63. package/dist/styles/recipes/scroll-rail.js +18 -18
  64. package/dist/styles/recipes/shadow.d.ts +10 -6
  65. package/dist/styles/recipes/shadow.js +4 -2
  66. package/dist/styles/recipes/stroke.d.ts +85 -0
  67. package/dist/styles/recipes/stroke.js +53 -0
  68. package/dist/styles/recipes/surface.d.ts +8 -4
  69. package/dist/styles/recipes/surface.js +23 -17
  70. package/dist/styles/recipes/title-bar.d.ts +7 -0
  71. package/dist/styles/recipes/title-bar.js +25 -22
  72. package/dist/styles/recipes/toggle.js +3 -3
  73. package/dist/window-chrome.d.ts +43 -0
  74. package/dist/window-chrome.js +13 -0
  75. package/dist/zoom.d.ts +9 -9
  76. package/docs/SPEC.md +34 -32
  77. package/editor/vscode.html-custom-data.json +12 -7
  78. package/editor/web-types.json +50 -14
  79. package/package.json +10 -2
@@ -10,53 +10,53 @@ import { SCREEN_CORNER as c, steppedCornerClip as l } from "../pixel-frame.js";
10
10
  import { TypeAheadBuffer as u } from "../type-ahead.js";
11
11
  import { MenuPressController as d } from "../menu-press.js";
12
12
  import { LitElement as f, css as p, html as m, unsafeCSS as h } from "lit";
13
- import { property as g, queryAssignedElements as _ } from "lit/decorators.js";
13
+ import { property as g, queryAssignedElements as _, state as v } from "lit/decorators.js";
14
14
  //#region src/components/vf-menu-bar.ts
15
- var v = class extends r(f) {
15
+ var y = class extends r(f) {
16
16
  constructor(...e) {
17
- super(...e), this.scale = new t(this), this.gridSnap = new o(this), this.label = "", this.rounded = !1, this.shortcuts = !1, this.#e = null, this.#t = this.attachInternals(), this.#n = new u(), this.#r = null, this.#i = new s(this, () => [[
17
+ super(...e), this.scale = new t(this), this.gridSnap = new o(this), this.label = "", this.rounded = !1, this.shortcuts = !1, this._hasEnd = !1, this.#e = null, this.#t = this.attachInternals(), this.#n = new u(), this.#r = null, this.#i = new s(this, () => [[
18
18
  document,
19
19
  "pointerdown",
20
- this.#h,
20
+ this.#g,
21
21
  !0
22
22
  ], [
23
23
  document,
24
24
  "keydown",
25
- this.#g,
25
+ this.#_,
26
26
  !0
27
27
  ]]), this.#a = new d(this, {
28
28
  menus: () => this._menus,
29
- open: (e) => this.#p(e),
30
- close: () => this.#m()
29
+ open: (e) => this.#m(e),
30
+ close: () => this.#h()
31
31
  }), this.#o = (e) => {
32
32
  if (!this.#e) return;
33
33
  let t = e.relatedTarget;
34
- t instanceof Node && (this.contains(t) || this.renderRoot.contains(t)) || this.#m();
35
- }, this.#u = (e) => {
36
- let t = e.detail;
37
- e.preventDefault(), e.stopPropagation(), t.menu.open ? this.#m() : this.#p(t.menu);
34
+ t instanceof Node && (this.contains(t) || this.renderRoot.contains(t)) || this.#h();
38
35
  }, this.#d = (e) => {
39
36
  let t = e.detail;
40
- this.#e && t.menu !== this.#e && this.#p(t.menu);
41
- }, this.#f = () => {
42
- this.#e?.focus(), this.#m();
43
- }, this.#h = (e) => {
44
- e.composedPath().includes(this) || this.#m();
37
+ e.preventDefault(), e.stopPropagation(), t.menu.open ? this.#h() : this.#m(t.menu);
38
+ }, this.#f = (e) => {
39
+ let t = e.detail;
40
+ this.#e && t.menu !== this.#e && this.#m(t.menu);
41
+ }, this.#p = () => {
42
+ this.#e?.focus(), this.#h();
45
43
  }, this.#g = (e) => {
44
+ e.composedPath().includes(this) || this.#h();
45
+ }, this.#_ = (e) => {
46
46
  if (!(e.defaultPrevented || !this.#e)) switch (e.key) {
47
47
  case "Escape":
48
- e.preventDefault(), this.#e.focus(), this.#m();
48
+ e.preventDefault(), this.#e.focus(), this.#h();
49
49
  break;
50
50
  case "Tab":
51
- this.#m();
51
+ this.#h();
52
52
  break;
53
53
  case "ArrowLeft":
54
54
  case "ArrowRight":
55
- e.preventDefault(), this.#v(e.key === "ArrowRight" ? 1 : -1);
55
+ e.preventDefault(), this.#y(e.key === "ArrowRight" ? 1 : -1);
56
56
  break;
57
57
  case "ArrowDown":
58
58
  case "ArrowUp":
59
- e.preventDefault(), this.#y(e.key === "ArrowDown" ? 1 : -1);
59
+ e.preventDefault(), this.#b(e.key === "ArrowDown" ? 1 : -1);
60
60
  break;
61
61
  case "Home":
62
62
  case "End": {
@@ -76,7 +76,7 @@ var v = class extends r(f) {
76
76
  break;
77
77
  }
78
78
  }
79
- }, this.#_ = (e) => {
79
+ }, this.#v = (e) => {
80
80
  if (this.#e) return;
81
81
  let t = this._menus;
82
82
  if (t.length === 0) return;
@@ -98,7 +98,7 @@ var v = class extends r(f) {
98
98
  break;
99
99
  default: return;
100
100
  }
101
- e.preventDefault(), i && (this.#l(i), i.focus());
101
+ e.preventDefault(), i && (this.#u(i), i.focus());
102
102
  };
103
103
  }
104
104
  static {
@@ -141,6 +141,22 @@ var v = class extends r(f) {
141
141
  ::slotted(vf-menu) {
142
142
  margin-inline-start: calc(var(--vf-scale, 1) * -5px);
143
143
  }
144
+ /* The bar's right end (slot="end"): a clock, say. A row of its own,
145
+ pushed to the end and held 9px in, mirroring the first title's
146
+ inset. A caption in it rides the bar's line, so its baseline is the
147
+ titles'. */
148
+ slot[name='end'] {
149
+ display: flex;
150
+ align-items: stretch;
151
+ margin-inline-start: auto;
152
+ padding-inline-end: calc(var(--vf-scale, 1) * 9px);
153
+ --vf-label-line-height: var(--vf-menubar-height, 20px);
154
+ }
155
+ /* Empty, it takes no part in the row: a page that pushes its own item
156
+ to the end with an auto margin keeps the whole of the slack. */
157
+ slot[name='end'].empty {
158
+ display: none;
159
+ }
144
160
  /* rounded: the screen-corner mask. The corners aren't a shape of the
145
161
  bar's own — they're the black staircase the ROM painted over the
146
162
  CRT's rounded corners, worn by the menu bar because it sat flush with
@@ -178,10 +194,10 @@ var v = class extends r(f) {
178
194
  #i;
179
195
  #a;
180
196
  connectedCallback() {
181
- super.connectedCallback(), this.#t.role = "menubar", this.addEventListener("vf-menu-toggle-request", this.#u), this.addEventListener("vf-menu-hover", this.#d), this.addEventListener("vf-menu-close-request", this.#f), this.addEventListener("keydown", this.#_), this.addEventListener("pointerdown", this.#a.onPointerDown), this.addEventListener("focusout", this.#o);
197
+ super.connectedCallback(), this.#t.role = "menubar", this.addEventListener("vf-menu-toggle-request", this.#d), this.addEventListener("vf-menu-hover", this.#f), this.addEventListener("vf-menu-close-request", this.#p), this.addEventListener("keydown", this.#v), this.addEventListener("pointerdown", this.#a.onPointerDown), this.addEventListener("focusout", this.#o);
182
198
  }
183
199
  disconnectedCallback() {
184
- super.disconnectedCallback(), this.removeEventListener("vf-menu-toggle-request", this.#u), this.removeEventListener("vf-menu-hover", this.#d), this.removeEventListener("vf-menu-close-request", this.#f), this.removeEventListener("keydown", this.#_), this.removeEventListener("pointerdown", this.#a.onPointerDown), this.removeEventListener("focusout", this.#o), this.#e = null, this.#r = null;
200
+ super.disconnectedCallback(), this.removeEventListener("vf-menu-toggle-request", this.#d), this.removeEventListener("vf-menu-hover", this.#f), this.removeEventListener("vf-menu-close-request", this.#p), this.removeEventListener("keydown", this.#v), this.removeEventListener("pointerdown", this.#a.onPointerDown), this.removeEventListener("focusout", this.#o), this.#e = null, this.#r = null;
185
201
  }
186
202
  focus(e) {
187
203
  (this.#e ?? this.#r ?? this._menus[0])?.focus(e);
@@ -193,41 +209,49 @@ var v = class extends r(f) {
193
209
  render() {
194
210
  return m`
195
211
  <div class="bar vf-snap vf-rule-bottom" part="bar" role="presentation">
196
- <slot @slotchange=${this.#s}></slot>
212
+ <slot @slotchange=${this.#c}></slot>
213
+ <slot
214
+ name="end"
215
+ class=${this._hasEnd ? "" : "empty"}
216
+ @slotchange=${this.#s}
217
+ ></slot>
197
218
  </div>
198
219
  `;
199
220
  }
200
- #s() {
201
- this.#e && !this._menus.includes(this.#e) && this.#m(), this.#r && !this._menus.includes(this.#r) && (this.#r = null), this.#c();
221
+ #s(e) {
222
+ this._hasEnd = e.target.assignedElements().length > 0;
202
223
  }
203
224
  #c() {
225
+ this.#e && !this._menus.includes(this.#e) && this.#h(), this.#r && !this._menus.includes(this.#r) && (this.#r = null), this.#l();
226
+ }
227
+ #l() {
204
228
  let e = this._menus, t = this.#e ?? this.#r ?? e[0];
205
229
  for (let n of e) n.barTabIndex = n === t ? 0 : -1;
206
230
  }
207
- #l(e) {
208
- this.#r = e, this.#c();
231
+ #u(e) {
232
+ this.#r = e, this.#l();
209
233
  }
210
- #u;
211
234
  #d;
212
235
  #f;
213
- #p(e) {
236
+ #p;
237
+ #m(e) {
214
238
  for (let t of this._menus) t !== e && (t.open = !1);
215
- e.open = !0, this.#e = e, this.#r = e, this.#n.reset(), this.#c(), this.#i.attach();
239
+ e.open = !0, this.#e = e, this.#r = e, this.#n.reset(), this.#l(), this.#i.attach();
216
240
  }
217
- #m() {
241
+ #h() {
218
242
  for (let e of this._menus) e.open = !1;
219
- this.#e = null, this.#n.reset(), this.#i.detach(), this.#c();
243
+ this.#e = null, this.#n.reset(), this.#i.detach(), this.#l();
220
244
  }
221
- #h;
222
245
  #g;
223
246
  #_;
224
- #v(e) {
247
+ #v;
248
+ #y(e) {
225
249
  let t = this._menus;
226
250
  if (!this.#e || t.length === 0) return;
227
251
  let n = t[(t.indexOf(this.#e) + e + t.length) % t.length];
228
- n && n !== this.#e && (this.#p(n), n.focus());
252
+ n && n !== this.#e && (this.#m(n), n.focus());
229
253
  }
230
- #y(e) {
254
+ #b(e) {
231
255
  if (!this.#e) return;
232
256
  let t = this.#e.items;
233
257
  if (t.length === 0) return;
@@ -235,15 +259,15 @@ var v = class extends r(f) {
235
259
  r = n < 0 ? e === 1 ? 0 : t.length - 1 : (n + e + t.length) % t.length, t[r]?.focus();
236
260
  }
237
261
  };
238
- n([g()], v.prototype, "label", void 0), n([g({
262
+ n([g()], y.prototype, "label", void 0), n([g({
239
263
  type: Boolean,
240
264
  reflect: !0
241
- })], v.prototype, "rounded", void 0), n([g({
265
+ })], y.prototype, "rounded", void 0), n([g({
242
266
  type: Boolean,
243
267
  reflect: !0
244
- })], v.prototype, "shortcuts", void 0), n([_({
268
+ })], y.prototype, "shortcuts", void 0), n([_({
245
269
  selector: "vf-menu",
246
270
  flatten: !0
247
- })], v.prototype, "_menus", void 0), v = n([e("vf-menu-bar")], v);
271
+ })], y.prototype, "_menus", void 0), n([v()], y.prototype, "_hasEnd", void 0), y = n([e("vf-menu-bar")], y);
248
272
  //#endregion
249
- export { v as VfMenuBar };
273
+ export { y as VfMenuBar };
@@ -125,22 +125,23 @@ var T = class extends a(_) {
125
125
  @media (forced-colors: active) {
126
126
  forced-color-adjust: none;
127
127
  }
128
- background: var(--vf-highlight, #000);
129
128
  color: var(--vf-highlight-text, #fff);
130
- /* The hilite leaves the bar's top row white: System 7's plate is rows
131
- 1..18 of the 20px bar (the Label specimen in Menus.png is 18px of
132
- plate, and InfiniteMac shows the white row above it). Transparent
133
- borders + padding-box clip inset the paint without moving the box:
134
- the top row shows the bar's white through, the bottom row the bar's
135
- own black rule, and the hit rect stays the full bar height so a
136
- click slammed against the screen top still opens the menu. The
137
- 18px content box centers the 16px em on the same rows as the
138
- closed state, so the title never shifts. Declared only while open
139
- because forced-colors mode repaints transparent borders CanvasText
140
- on closed labels; here forced-color-adjust above already exempts
141
- them. */
142
- border-block: calc(var(--vf-scale, 1) * 1px) solid transparent;
143
- background-clip: padding-box;
129
+ }
130
+ /* The hilite leaves the bar's top row white: System 7's plate is rows
131
+ 1..18 of the 20px bar (the Label specimen in Menus.png is 18px of
132
+ plate, and InfiniteMac shows the white row above it). So the plate is
133
+ a layer inset a row top and bottom rather than the label's own
134
+ background: the top row shows the bar's white through, the bottom row
135
+ the bar's own black rule, and the hit rect stays the full bar height
136
+ so a click slammed against the screen top still opens the menu. The
137
+ title doesn't move. The label is positioned (vf-snap), and the title
138
+ is too, so the plate paints under it in tree order. */
139
+ :host([open]) .label::before,
140
+ .label.flash-on::before {
141
+ content: '';
142
+ position: absolute;
143
+ inset: calc(var(--vf-scale, 1) * 1px) 0;
144
+ background: var(--vf-highlight, #000);
144
145
  }
145
146
  /* The title rides in its own box so the focus rule spans the title and
146
147
  not the bar cell's 10px padding — the same reason vf-button wraps its
@@ -198,13 +199,14 @@ var T = class extends a(_) {
198
199
  from. (The nowrap rows make min-content the widest row, so the
199
200
  shrink-to-fit abspos width IS the MDEF width.) */
200
201
  min-width: 100%;
201
- /* No vertical inset: every panel in Menus.png — both pulldowns, the
202
- open popup and the closed pill — puts its first row's ink at +4 from
203
- the border box, which is the 1px border plus the row's own 3px ✓
204
- bias. The bottom border likewise sits immediately after the last row.
205
- A 2px inset here displaced every row by 2px against the art; it was
206
- invisible while the rows themselves were 6px too tall. */
207
- padding: 0;
202
+ /* No inset of its own beyond the frame, whose 1px stroke is the
203
+ panel's padding (vfPanel): every panel in Menus.png — both
204
+ pulldowns, the open popup and the closed pill — puts its first
205
+ row's ink at +4 from the border box, which is the 1px frame plus
206
+ the row's own 3px ✓ bias. The bottom line likewise sits
207
+ immediately after the last row. A 2px inset here displaced every
208
+ row by 2px against the art; it was invisible while the rows
209
+ themselves were 6px too tall. */
208
210
  z-index: 1000;
209
211
  /* As on the title: the held press, not the browser, owns touch moves
210
212
  over the dropped panel. */
@@ -3,16 +3,17 @@ import { vfElement as t } from "../define.js";
3
3
  import n from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
4
4
  import { VfPositioned as r } from "../position.js";
5
5
  import { vfBase as i } from "../styles/recipes/host.js";
6
- import { vfField as a } from "../styles/recipes/field.js";
7
- import { STEPPER as o, STEPPER_DOWN_FILL as s, STEPPER_UP_FILL as c } from "../glyphs.js";
8
- import { VfTextControlBase as l } from "../text-control.js";
9
- import { decimalsOf as u } from "../number.js";
10
- import { css as d, html as f, nothing as p } from "lit";
11
- import { property as m, query as h, state as g } from "lit/decorators.js";
12
- import { classMap as _ } from "lit/directives/class-map.js";
13
- import { live as v } from "lit/directives/live.js";
6
+ import { vfStrokeInset as a } from "../styles/recipes/stroke.js";
7
+ import { vfField as o } from "../styles/recipes/field.js";
8
+ import { STEPPER as s, STEPPER_DOWN_FILL as c, STEPPER_UP_FILL as l } from "../glyphs.js";
9
+ import { VfTextControlBase as u } from "../text-control.js";
10
+ import { decimalsOf as d } from "../number.js";
11
+ import { css as f, html as p, nothing as m } from "lit";
12
+ import { property as h, query as g, state as _ } from "lit/decorators.js";
13
+ import { classMap as v } from "lit/directives/class-map.js";
14
+ import { live as y } from "lit/directives/live.js";
14
15
  //#region src/components/vf-number-field.ts
15
- var y = class extends r(l) {
16
+ var b = class extends r(u) {
16
17
  constructor(...t) {
17
18
  super(...t), this.step = 1, this.pressed = null, this.#l = (e) => {
18
19
  if (this.isDisabled || this.readonly) return;
@@ -48,14 +49,14 @@ var y = class extends r(l) {
48
49
  this.value = e.target.value, this.#o("vf-input");
49
50
  }, this.#p = (t) => {
50
51
  let n = t.target.value, r = parseFloat(n);
51
- this.value = Number.isNaN(r) ? n : String(Number(this.#r(r).toFixed(u(this.step)))), this.#o("vf-change"), e(this, "change");
52
+ this.value = Number.isNaN(r) ? n : String(Number(this.#r(r).toFixed(d(this.step)))), this.#o("vf-change"), e(this, "change");
52
53
  };
53
54
  }
54
55
  static {
55
56
  this.styles = [
56
57
  i,
57
- a,
58
- d`
58
+ o,
59
+ f`
59
60
  :host {
60
61
  display: inline-flex;
61
62
  /* NOT stretch: that sized the well to the stepper's 25px, making this
@@ -82,7 +83,7 @@ var y = class extends r(l) {
82
83
  (1 above / 2 below) — optically centered, still on the device grid. */
83
84
  margin-top: calc(var(--vf-scale, 1) * 1px);
84
85
  }
85
- input {
86
+ input.vf-field {
86
87
  flex: 1 1 auto;
87
88
  width: var(--vf-number-field-width, 4em);
88
89
  min-width: 2em;
@@ -94,7 +95,8 @@ var y = class extends r(l) {
94
95
  fills it, and a user stylesheet raising line-height grows the well
95
96
  instead of clipping the digits. */
96
97
  min-height: calc(var(--vf-scale, 1) * var(--vf-control-height, 22px));
97
- padding: 0 calc(var(--vf-scale, 1) * 6px);
98
+ /* The 6px text inset, inside the well's stroke (vfField). */
99
+ padding: ${a(0)} ${a(6)};
98
100
  text-align: right;
99
101
  }
100
102
 
@@ -152,7 +154,7 @@ var y = class extends r(l) {
152
154
  return this.min != null && e < this.min ? this.min : this.max != null && e > this.max ? this.max : e;
153
155
  }
154
156
  #i(t) {
155
- let n = String(Number(this.#r(t).toFixed(u(this.step))));
157
+ let n = String(Number(this.#r(t).toFixed(d(this.step))));
156
158
  n !== this.value && (this.value = n, this.#o("vf-change"), e(this, "input"), e(this, "change"));
157
159
  }
158
160
  #a(e) {
@@ -181,7 +183,7 @@ var y = class extends r(l) {
181
183
  #p;
182
184
  render() {
183
185
  let e = this.isDisabled, t = this.#n();
184
- return f`
186
+ return p`
185
187
  <div class=${this.wellClass}>
186
188
  <input
187
189
  part="input"
@@ -194,14 +196,14 @@ var y = class extends r(l) {
194
196
  maxlength=${this.forwardedAttr("maxlength")}
195
197
  spellcheck=${this.forwardedAttr("spellcheck")}
196
198
  autocapitalize=${this.forwardedAttr("autocapitalize")}
197
- aria-label=${this.label || this.hostLabel || p}
199
+ aria-label=${this.label || this.hostLabel || m}
198
200
  aria-describedby=${this.describedBy}
199
- aria-required=${this.required ? "true" : p}
200
- aria-invalid=${this.validity.valid ? p : "true"}
201
- aria-valuenow=${Number.isNaN(t) ? p : t}
202
- aria-valuemin=${this.min ?? p}
203
- aria-valuemax=${this.max ?? p}
204
- .value=${v(this.value)}
201
+ aria-required=${this.required ? "true" : m}
202
+ aria-invalid=${this.validity.valid ? m : "true"}
203
+ aria-valuenow=${Number.isNaN(t) ? m : t}
204
+ aria-valuemin=${this.min ?? m}
205
+ aria-valuemax=${this.max ?? m}
206
+ .value=${y(this.value)}
205
207
  placeholder=${this.placeholder}
206
208
  ?disabled=${e}
207
209
  ?readonly=${this.readonly}
@@ -212,15 +214,15 @@ var y = class extends r(l) {
212
214
  </div>
213
215
  <span class="stepper vf-snap" part="stepper">
214
216
  <svg viewBox="0 0 15 25" shape-rendering="crispEdges" fill="currentColor" aria-hidden="true">
215
- <path d=${o.d}></path>
216
- <path class=${_({
217
+ <path d=${s.d}></path>
218
+ <path class=${v({
217
219
  fill: !0,
218
220
  on: this.pressed === "up"
219
- })} d=${c.d}></path>
220
- <path class=${_({
221
+ })} d=${l.d}></path>
222
+ <path class=${v({
221
223
  fill: !0,
222
224
  on: this.pressed === "down"
223
- })} d=${s.d}></path>
225
+ })} d=${c.d}></path>
224
226
  </svg>
225
227
  <span
226
228
  class="hit up"
@@ -243,6 +245,6 @@ var y = class extends r(l) {
243
245
  `;
244
246
  }
245
247
  };
246
- n([m({ type: Number })], y.prototype, "min", void 0), n([m({ type: Number })], y.prototype, "max", void 0), n([m({ type: Number })], y.prototype, "step", void 0), n([g()], y.prototype, "pressed", void 0), n([h("input")], y.prototype, "input", void 0), y = n([t("vf-number-field")], y);
248
+ n([h({ type: Number })], b.prototype, "min", void 0), n([h({ type: Number })], b.prototype, "max", void 0), n([h({ type: Number })], b.prototype, "step", void 0), n([_()], b.prototype, "pressed", void 0), n([g("input")], b.prototype, "input", void 0), b = n([t("vf-number-field")], b);
247
249
  //#endregion
248
- export { y as VfNumberField };
250
+ export { b as VfNumberField };
@@ -5,12 +5,13 @@ import { VfPositioned as a } from "../position.js";
5
5
  import { vfBase as o } from "../styles/recipes/host.js";
6
6
  import { tileImage as s, tileRects as c, tileSpan as l, vfTileMaskSize as u } from "../styles/recipes/tile.js";
7
7
  import { RepeatTileController as d, patternOverride as f, tileGrid as p, vfRepeatTileSize 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";
8
+ import { vfStrokeDecls as g } from "../styles/recipes/stroke.js";
9
+ import { GridSnapController as _ } from "../grid-snap.js";
10
+ import { TrackWidthController as v } from "../track-width.js";
11
+ import { LitElement as y, css as b, html as x, unsafeCSS as S } from "lit";
12
+ import { property as C, query as w } from "lit/decorators.js";
12
13
  //#region src/components/vf-progress-bar.ts
13
- var w = 12, T = [
14
+ var T = 12, E = [
14
15
  [
15
16
  0,
16
17
  0,
@@ -113,16 +114,16 @@ var w = 12, T = [
113
114
  1,
114
115
  1
115
116
  ]
116
- ], E = {
117
- width: w,
118
- height: w,
119
- rects: T
120
- }, D = s(w, w, c(T)), O = l(w), k = class extends a(v) {
117
+ ], D = {
118
+ width: T,
119
+ height: T,
120
+ rects: E
121
+ }, O = s(T, T, c(E)), k = l(T), A = class extends a(y) {
121
122
  static {
122
123
  this.styles = [
123
124
  o,
124
125
  h,
125
- y`
126
+ b`
126
127
  :host {
127
128
  display: block;
128
129
  height: calc(var(--vf-scale, 1) * 14px);
@@ -131,22 +132,20 @@ var w = 12, T = [
131
132
  position: relative;
132
133
  height: 100%;
133
134
  background: var(--vf-progress-track, #ffffff);
134
- border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
135
135
  border-radius: 0;
136
136
  overflow: hidden;
137
+ ${g()}
137
138
  }
138
139
  .fill {
139
140
  height: 100%;
140
141
  background: var(--vf-progress-fill, #000000);
141
- /* The classic 1px black leading edge. */
142
- border-right: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
143
142
  }
144
- .fill.empty {
145
- border-right: none;
143
+ /* The classic 1px black leading edge, on a fill with any width. */
144
+ .fill:not(.empty):not(.stripes) {
145
+ ${g({ edges: ["right"] })}
146
146
  }
147
147
  .fill.stripes {
148
148
  width: 100%;
149
- border-right: none;
150
149
  /* Chunky 45° barber stripes: a 12×12 system-px cell whose two black
151
150
  \ bands are a staircase of axis-aligned 1px rects (genuine pixel
152
151
  art — a *diagonal* edge would blur where these stay pixel-exact)
@@ -157,7 +156,7 @@ var w = 12, T = [
157
156
  strip's containing block and its clip. */
158
157
  position: relative;
159
158
  background-color: var(--vf-white, #fff);
160
- --_vf-tile-image: var(--vf-progress-stripes, ${x(D)});
159
+ --_vf-tile-image: var(--vf-progress-stripes, ${S(O)});
161
160
  }
162
161
  /* The animated strip: the fill's width plus one 12px cell, resting
163
162
  that cell to the left (fully covering the fill), and each cycle
@@ -201,8 +200,8 @@ var w = 12, T = [
201
200
  }
202
201
  .fill.stripes {
203
202
  background-color: var(--vf-progress-fill, CanvasText);
204
- mask-image: var(--vf-progress-stripes, ${x(D)});
205
- ${u(w)}
203
+ mask-image: var(--vf-progress-stripes, ${S(O)});
204
+ ${u(T)}
206
205
  animation: vf-barber-mask 0.4s steps(4, end) infinite;
207
206
  }
208
207
  .fill.stripes .vf-tile-strip {
@@ -229,9 +228,9 @@ var w = 12, T = [
229
228
  #e;
230
229
  #t;
231
230
  constructor() {
232
- 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 d(this, {
231
+ super(), this.scale = new t(this), this.gridSnap = new _(this), this.value = 0, this.max = 100, this.indeterminate = !1, this.label = "", this.trackSize = new v(this, () => this.track), this._pattern = "", this.#e = new d(this, {
233
232
  getBox: () => this.renderRoot?.querySelector(".vf-tile-strip"),
234
- getArt: () => this.indeterminate && !this._pattern ? E : null,
233
+ getArt: () => this.indeterminate && !this._pattern ? D : null,
235
234
  property: "--_vf-barber-tile"
236
235
  }), this.#t = this.attachInternals(), this.#t.role = "progressbar", this.#t.ariaValueMin = "0";
237
236
  }
@@ -251,14 +250,14 @@ var w = 12, T = [
251
250
  if (this.indeterminate) {
252
251
  let e = null;
253
252
  if (this._pattern) {
254
- let t = r(this.trackSize.width, this), n = Math.max(1, Math.ceil((t + w) / O));
253
+ let t = r(this.trackSize.width, this), n = Math.max(1, Math.ceil((t + T) / k));
255
254
  e = p({
256
255
  cols: n,
257
256
  rows: 1,
258
- tile: O
257
+ tile: k
259
258
  });
260
259
  }
261
- return b`
260
+ return x`
262
261
  <div class="track vf-snap" part="track">
263
262
  <div class="fill stripes vf-tile-grid" part="fill">
264
263
  <div class="vf-tile-strip">${e}</div>
@@ -267,7 +266,7 @@ var w = 12, T = [
267
266
  `;
268
267
  }
269
268
  let e = this.clampedValue / this.effectiveMax, t = r(this.trackSize.width, this), i = t > 0 ? `${n(Math.round(e * t), this)}px` : `${e * 100}%`;
270
- return b`
269
+ return x`
271
270
  <div class="track vf-snap" part="track">
272
271
  <div
273
272
  class="fill ${e <= 0 ? "empty" : ""}"
@@ -278,9 +277,9 @@ var w = 12, T = [
278
277
  `;
279
278
  }
280
279
  };
281
- i([S({ type: Number })], k.prototype, "value", void 0), i([S({ type: Number })], k.prototype, "max", void 0), i([S({
280
+ i([C({ type: Number })], A.prototype, "value", void 0), i([C({ type: Number })], A.prototype, "max", void 0), i([C({
282
281
  type: Boolean,
283
282
  reflect: !0
284
- })], k.prototype, "indeterminate", void 0), i([S()], k.prototype, "label", void 0), i([C(".track")], k.prototype, "track", void 0), k = i([e("vf-progress-bar")], k);
283
+ })], A.prototype, "indeterminate", void 0), i([C()], A.prototype, "label", void 0), i([w(".track")], A.prototype, "track", void 0), A = i([e("vf-progress-bar")], A);
285
284
  //#endregion
286
- export { k as VfProgressBar };
285
+ export { A as VfProgressBar };
@@ -21,10 +21,9 @@ var y = class extends r(f(p)) {
21
21
  m`
22
22
  /* Keyboard focus underlines the circle itself — not the label, and not a
23
23
  ring around either (see vfFocusUnderline). One blank row below the
24
- well, which is where vf-checkbox puts its own: −2 rather than that
25
- control's −3 only because this well is unbordered, so the two rules
26
- land on the same row of a mixed list. The 12px sprite sits half a
27
- pixel proud of the 13px well, so the gap reads as one row or two
24
+ well, which ends on the same row as vf-checkbox's box, so the two
25
+ rules land on the same row of a mixed list. The 12px sprite sits half
26
+ a pixel proud of the 13px well, so the gap reads as one row or two
28
27
  depending on which way that rounds — the well is the anchor, not the
29
28
  sprite. */
30
29
  :host(:focus-visible) .circle::after {