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
@@ -1,25 +1,25 @@
1
1
  import { emit as e } from "../events.js";
2
2
  import { vfElement as t } from "../define.js";
3
- import { ScaleController as n, effectiveScale as r, sysLength as i } from "../scale.js";
4
- import a from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
5
- import { VfPositioned as o, placementIn as s } from "../position.js";
6
- import { vfBase as c } from "../styles/recipes/host.js";
7
- import { tileImage as l, tileRects as u, tileSpan as d } from "../styles/recipes/tile.js";
8
- import { patternOverride as f, tileGrid as p, vfTileGrid as m } from "../tile-grid.js";
9
- import { PATTERNS as h, parsePattern as g, patternMotif as _ } from "../patterns.js";
10
- import { PatternFillController as v, vfPatternFill as y } from "../pattern-fill.js";
11
- import { GridSnapController as b } from "../grid-snap.js";
12
- import { DocumentListenersController as x } from "../document-listeners.js";
13
- import { SCREEN_CORNER as S, steppedCornerClip as C } from "../pixel-frame.js";
14
- import { LitElement as w, css as T, html as E, unsafeCSS as D } from "lit";
15
- import { property as O, query as k, queryAssignedElements as A } from "lit/decorators.js";
3
+ import { ScaleController as n, effectiveScale as r, sysLength as i, systemPxQuantum as a } from "../scale.js";
4
+ import o from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
5
+ import { VfPositioned as s, placementIn as c } from "../position.js";
6
+ import { vfBase as l } from "../styles/recipes/host.js";
7
+ import { tileImage as u, tileRects as d, tileSpan as f } from "../styles/recipes/tile.js";
8
+ import { patternOverride as p, tileGrid as m, vfTileGrid as h } from "../tile-grid.js";
9
+ import { PATTERNS as g, parsePattern as _, patternMotif as v } from "../patterns.js";
10
+ import { PatternFillController as y, vfPatternFill as b } from "../pattern-fill.js";
11
+ import { GridSnapController as x } from "../grid-snap.js";
12
+ import { DocumentListenersController as S } from "../document-listeners.js";
13
+ import { SCREEN_CORNER as C, steppedCornerClip as w } from "../pixel-frame.js";
14
+ import { LitElement as T, css as E, html as D, unsafeCSS as O } from "lit";
15
+ import { property as k, query as A, queryAssignedElements as j } from "lit/decorators.js";
16
16
  //#region src/components/vf-desktop.ts
17
- var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I], "#000000", "#ffffff"), R = l(L.width, L.height, u(L.rects)), z = d(L.width), B = class extends o(w) {
17
+ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L], "#000000", "#ffffff"), z = u(R.width, R.height, d(R.rects)), B = f(R.width), V = (e) => Number(e.style.zIndex) || 0, H = class extends s(T) {
18
18
  constructor(...e) {
19
- super(...e), this.width = P, this.height = F, this.bezel = 0, this.pattern = I, this.scale = new n(this), this.gridSnap = new b(this), this._token = "", this._desktopPattern = h[I], this.#e = !1, this.patternFill = new v(this, {
19
+ super(...e), this.width = F, this.height = I, this.bezel = 0, this.pattern = L, this.scale = new n(this), this.gridSnap = new x(this), this._token = "", this._desktopPattern = g[L], this.#e = !1, this.patternFill = new y(this, {
20
20
  getBox: () => this.screen,
21
21
  getPattern: () => this._token ? null : this._desktopPattern
22
- }), this._zCounter = 0, this._activeWindow = null, this._deactivated = !1, this._awaitingUpgrade = !1, this._pointerGesture = !1, this._restoringFocus = !1, this._domSyncTimer = 0, this._gestureEnd = new x(this, () => [[
22
+ }), this._zCounter = 0, this._activeWindow = null, this._deactivated = !1, this._awaitingUpgrade = !1, this.#t = new MutationObserver(() => this._resolveActive()), this._pointerGesture = !1, this._restoringFocus = !1, this._domSyncTimer = 0, this._gestureEnd = new S(this, () => [[
23
23
  document,
24
24
  "pointerup",
25
25
  this._onGestureEnd,
@@ -38,6 +38,15 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
38
38
  }, this._onDragSurfaceRequest = (e) => {
39
39
  let t = e.detail;
40
40
  !t || t.surface || (t.surface = this.dragSurface);
41
+ }, this._onBoundsRequest = (e) => {
42
+ let t = e.detail, n = e.target;
43
+ if (!t || t.bounds || !(n instanceof HTMLElement) || n.offsetParent !== this) return;
44
+ let r = n.localName === "vf-window" ? this.windowArea : this.workArea, i = a(n);
45
+ t.bounds = {
46
+ width: r.left + r.width,
47
+ height: r.top + r.height,
48
+ top: Math.ceil(r.top / i) * i
49
+ };
41
50
  }, this._onFocusIn = (e) => {
42
51
  if (this._restoringFocus) return;
43
52
  let t = this._windowFromEvent(e);
@@ -46,10 +55,10 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
46
55
  }
47
56
  static {
48
57
  this.styles = [
49
- c,
50
- m,
51
- y,
52
- T`
58
+ l,
59
+ h,
60
+ b,
61
+ E`
53
62
  :host {
54
63
  display: block;
55
64
  position: relative;
@@ -110,7 +119,7 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
110
119
  position: absolute;
111
120
  inset: 0;
112
121
  z-index: -1;
113
- --_vf-tile-image: var(--vf-desktop-pattern, ${D(R)});
122
+ --_vf-tile-image: var(--vf-desktop-pattern, ${O(z)});
114
123
  /* Forced colors: hidden with the pattern, same posture. */
115
124
  @media (forced-colors: active) {
116
125
  display: none;
@@ -142,7 +151,7 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
142
151
  ::slotted(vf-menu-bar),
143
152
  ::slotted(vf-menu) {
144
153
  position: relative;
145
- z-index: ${M};
154
+ z-index: ${N};
146
155
  }
147
156
  /* The drag surface (see the class doc): the box an icon's outline is
148
157
  positioned in — the screen's own, bezel excluded — clipped with
@@ -158,7 +167,7 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
158
167
  pointer-events: none;
159
168
  }
160
169
  .drag-surface > * {
161
- z-index: ${N};
170
+ z-index: ${P};
162
171
  }
163
172
  /* With a bezel, the screen's four corners wear the SCREEN_CORNER mask,
164
173
  rounding into the surrounding black; the bottom pair is the same
@@ -169,8 +178,8 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
169
178
  maximal z-index. */
170
179
  .corner {
171
180
  position: absolute;
172
- width: calc(var(--vf-scale, 1) * ${S[0]}px);
173
- height: calc(var(--vf-scale, 1) * ${S.length}px);
181
+ width: calc(var(--vf-scale, 1) * ${C[0]}px);
182
+ height: calc(var(--vf-scale, 1) * ${C.length}px);
174
183
  background: var(--vf-black, #000);
175
184
  pointer-events: none;
176
185
  z-index: 2147483647;
@@ -178,26 +187,43 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
178
187
  .corner.tl {
179
188
  top: 0;
180
189
  left: 0;
181
- clip-path: ${D(C(S, "left"))};
190
+ clip-path: ${O(w(C, "left"))};
182
191
  }
183
192
  .corner.tr {
184
193
  top: 0;
185
194
  right: 0;
186
- clip-path: ${D(C(S, "right"))};
195
+ clip-path: ${O(w(C, "right"))};
187
196
  }
188
197
  .corner.bl {
189
198
  bottom: 0;
190
199
  left: 0;
191
- clip-path: ${D(C(S, "left", "bottom"))};
200
+ clip-path: ${O(w(C, "left", "bottom"))};
192
201
  }
193
202
  .corner.br {
194
203
  bottom: 0;
195
204
  right: 0;
196
- clip-path: ${D(C(S, "right", "bottom"))};
205
+ clip-path: ${O(w(C, "right", "bottom"))};
197
206
  }
198
207
  `
199
208
  ];
200
209
  }
210
+ get workArea() {
211
+ let e = this.width ?? F, t = this.height ?? I, n = Math.min(t, this._menuBarFloor());
212
+ return {
213
+ left: 0,
214
+ top: n,
215
+ width: e,
216
+ height: t - n
217
+ };
218
+ }
219
+ get windowArea() {
220
+ let e = this.workArea, t = Math.min(e.top + e.height, Math.max(e.top, this.windowTop ?? 0));
221
+ return {
222
+ ...e,
223
+ top: t,
224
+ height: e.top + e.height - t
225
+ };
226
+ }
201
227
  fitWithin(e, t) {
202
228
  let n = r(this), i = (e) => Math.max(0, Math.floor(e / n + 1e-6) - 2 * this.bezel);
203
229
  return this.width = i(e), this.height = i(t), {
@@ -206,17 +232,18 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
206
232
  };
207
233
  }
208
234
  placementAt(e, t, n) {
209
- return s(this.screen ?? this, e, t, this, n);
235
+ return c(this.screen ?? this, e, t, this, n);
210
236
  }
211
237
  #e;
238
+ #t;
212
239
  connectedCallback() {
213
- super.connectedCallback(), this.addEventListener("pointerdown", this._onPointerDown), this.addEventListener("focusin", this._onFocusIn), this.addEventListener("vf-drag-surface-request", this._onDragSurfaceRequest);
240
+ super.connectedCallback(), this.addEventListener("pointerdown", this._onPointerDown), this.addEventListener("focusin", this._onFocusIn), this.addEventListener("vf-drag-surface-request", this._onDragSurfaceRequest), this.addEventListener("vf-placement-bounds-request", this._onBoundsRequest), this.hasUpdated && this._observeWindows();
214
241
  }
215
242
  disconnectedCallback() {
216
- this.removeEventListener("pointerdown", this._onPointerDown), this.removeEventListener("focusin", this._onFocusIn), this.removeEventListener("vf-drag-surface-request", this._onDragSurfaceRequest), this._pointerGesture = !1, this._domSyncTimer &&= (clearTimeout(this._domSyncTimer), 0), super.disconnectedCallback();
243
+ this.removeEventListener("pointerdown", this._onPointerDown), this.removeEventListener("focusin", this._onFocusIn), this.removeEventListener("vf-drag-surface-request", this._onDragSurfaceRequest), this.removeEventListener("vf-placement-bounds-request", this._onBoundsRequest), this.#t.disconnect(), this._pointerGesture = !1, this._domSyncTimer &&= (clearTimeout(this._domSyncTimer), 0), super.disconnectedCallback();
217
244
  }
218
245
  _isUtility(e) {
219
- return e.getAttribute("variant") === "utility";
246
+ return ("variant" in e ? e.variant : e.getAttribute("variant")) === "utility";
220
247
  }
221
248
  bringToFront(e) {
222
249
  this._restack(e), this._requestDomSync();
@@ -224,12 +251,15 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
224
251
  get activeWindow() {
225
252
  return this._activeWindow;
226
253
  }
254
+ get stackingOrder() {
255
+ return [...this._windows].sort((e, t) => V(e) - V(t));
256
+ }
227
257
  clearActive() {
228
258
  this._deactivated = !0, this._setActive(null);
229
259
  }
230
260
  _restack(e) {
231
261
  let t = this._isUtility(e);
232
- e.style.zIndex = String(++this._zCounter + (t ? j : 0)), t || this._setActive(e);
262
+ e.style.zIndex = String(++this._zCounter + (t ? M : 0)), !t && !e.hidden && this._setActive(e);
233
263
  }
234
264
  _requestDomSync() {
235
265
  this._pointerGesture || this._domSyncTimer || (this._domSyncTimer = window.setTimeout(() => {
@@ -237,27 +267,47 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
237
267
  }, 0));
238
268
  }
239
269
  _raise(e) {
240
- let t = this._isUtility(e), n = this._windows.filter((e) => this._isUtility(e) === t);
270
+ let t = this._isUtility(e), n = this._windows.filter((e) => this._isUtility(e) === t && !e.hidden);
241
271
  this._topmost(n) === e && (t || e.hasAttribute("active")) || this._restack(e);
242
272
  }
273
+ _menuBarFloor() {
274
+ let e = this.screen;
275
+ if (!e) return 0;
276
+ let t = [...this.children].find((e) => e.localName === "vf-menu-bar" && !e.hidden);
277
+ if (!t) return 0;
278
+ let n = t.getBoundingClientRect();
279
+ if (n.height <= 0) return 0;
280
+ let i = e.getBoundingClientRect(), a = r(this);
281
+ return Math.round((n.top - i.top) / a) > 0 ? 0 : Math.max(0, Math.round((n.bottom - i.top) / a));
282
+ }
243
283
  _windowFromEvent(e) {
244
284
  let t = this._windows;
245
285
  return e.composedPath().find((e) => e instanceof HTMLElement && t.includes(e));
246
286
  }
247
287
  _onSlotChange() {
248
- let e = this._windows, t = null;
288
+ let e = this._windows;
289
+ this._observeWindows();
290
+ let t = null;
249
291
  for (let n of e) if (!n.style.zIndex) {
250
292
  let e = this._isUtility(n);
251
- n.style.zIndex = String(++this._zCounter + (e ? j : 0)), e || (t = n);
293
+ n.style.zIndex = String(++this._zCounter + (e ? M : 0)), !e && !n.hidden && (t = n);
252
294
  }
253
- let n = e.filter((e) => !this._isUtility(e)), r = this._activeWindow && n.includes(this._activeWindow) ? this._activeWindow : null;
254
- this._setActive(t ?? r ?? (this._deactivated ? null : this._topmost(n))), customElements.get("vf-window") || this._normalizeAfterUpgrade();
295
+ t ? this._setActive(t) : this._resolveActive(), customElements.get("vf-window") || this._normalizeAfterUpgrade();
296
+ }
297
+ _resolveActive() {
298
+ let e = this._windows.filter((e) => !this._isUtility(e) && !e.hidden), t = this._activeWindow && e.includes(this._activeWindow) ? this._activeWindow : null;
299
+ this._setActive(t ?? (this._deactivated ? null : this._topmost(e)));
300
+ }
301
+ _observeWindows() {
302
+ this.#t.takeRecords(), this.#t.disconnect();
303
+ for (let e of this._windows) this.#t.observe(e, {
304
+ attributes: !0,
305
+ attributeFilter: ["hidden"]
306
+ });
255
307
  }
256
308
  _normalizeAfterUpgrade() {
257
309
  this._awaitingUpgrade || (this._awaitingUpgrade = !0, customElements.whenDefined("vf-window").then(() => {
258
- if (this._awaitingUpgrade = !1, !this.isConnected) return;
259
- let e = this._windows.filter((e) => !this._isUtility(e)), t = this._activeWindow && e.includes(this._activeWindow) ? this._activeWindow : null;
260
- this._setActive(t ?? (this._deactivated ? null : this._topmost(e)));
310
+ this._awaitingUpgrade = !1, this.isConnected && this._resolveActive();
261
311
  }));
262
312
  }
263
313
  _setActive(t) {
@@ -274,7 +324,7 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
274
324
  _topmost(e) {
275
325
  let t = null, n = -Infinity;
276
326
  for (let r of e) {
277
- let e = Number(r.style.zIndex) || 0;
327
+ let e = V(r);
278
328
  e >= n && (n = e, t = r);
279
329
  }
280
330
  return t;
@@ -288,31 +338,39 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
288
338
  if (!this.isConnected) return;
289
339
  let e = this._windows;
290
340
  if (e.length < 2) return;
291
- let t = [...e].sort((e, t) => (Number(e.style.zIndex) || 0) - (Number(t.style.zIndex) || 0)), n = this._deepActiveElement(), r = !1, i = null;
292
- for (let e of t) i && i.compareDocumentPosition(e) & Node.DOCUMENT_POSITION_PRECEDING && (this.insertBefore(e, i.nextSibling), r = !0), i = e;
341
+ let t = [...e].sort((e, t) => V(e) - V(t)), n = this._deepActiveElement(), r = !1, i = null;
342
+ for (let e of t) i && i.compareDocumentPosition(e) & Node.DOCUMENT_POSITION_PRECEDING && (this._move(e, i.nextSibling), r = !0), i = e;
293
343
  r && n instanceof HTMLElement && n.isConnected && this._deepActiveElement() !== n && (this._restoringFocus = !0, n.focus({ preventScroll: !0 }), this._restoringFocus = !1);
294
344
  }
345
+ _move(e, t) {
346
+ let n = this;
347
+ if (typeof n.moveBefore == "function") try {
348
+ n.moveBefore(e, t);
349
+ return;
350
+ } catch {}
351
+ this.insertBefore(e, t);
352
+ }
295
353
  willUpdate(e) {
296
- if (super.willUpdate(e), this._token = f(this, "--vf-desktop-pattern"), e.has("pattern")) {
297
- let e = g(this.pattern);
298
- e === null && this.pattern?.trim() && !this.#e && (this.#e = !0, console.warn(`vf-desktop: unknown pattern "${this.pattern}" — a library name (docs/PATTERNS.md) or sixteen hex digits. Keeping ${I}.`)), this._desktopPattern = e ?? h[I];
354
+ if (super.willUpdate(e), this._token = p(this, "--vf-desktop-pattern"), e.has("pattern")) {
355
+ let e = _(this.pattern);
356
+ e === null && this.pattern?.trim() && !this.#e && (this.#e = !0, console.warn(`vf-desktop: unknown pattern "${this.pattern}" — a library name (docs/PATTERNS.md) or sixteen hex digits. Keeping ${L}.`)), this._desktopPattern = e ?? g[L];
299
357
  }
300
358
  }
301
359
  updated(e) {
302
360
  if (e.has("bezel") && (this.bezel > 0 ? this.style.setProperty("--vf-desktop-bezel", i(this.bezel)) : this.style.removeProperty("--vf-desktop-bezel")), e.has("width") || e.has("height") || e.has("bezel")) {
303
- let e = this.width ?? P, t = this.height ?? F;
361
+ let e = this.width ?? F, t = this.height ?? I;
304
362
  this.style.width = i(e + 2 * this.bezel), this.style.height = i(t + 2 * this.bezel);
305
363
  }
306
364
  }
307
365
  render() {
308
- let e = this.width ?? P, t = this.height ?? F, n = this._token ? E`<div class="vf-tile-grid">
309
- ${p({
310
- cols: Math.ceil(e / z),
311
- rows: Math.ceil(t / z),
312
- tile: z
366
+ let e = this.width ?? F, t = this.height ?? I, n = this._token ? D`<div class="vf-tile-grid">
367
+ ${m({
368
+ cols: Math.ceil(e / B),
369
+ rows: Math.ceil(t / B),
370
+ tile: B
313
371
  })}
314
372
  </div>` : null;
315
- return E`
373
+ return D`
316
374
  <div class=${this.bezel > 0 ? "desktop vf-snap bezeled" : "desktop vf-snap"}>
317
375
  <div
318
376
  class="screen vf-pattern-fill${this._token ? "" : " vf-patterned"}"
@@ -321,7 +379,7 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
321
379
  ${n}
322
380
  <slot @slotchange=${this._onSlotChange}></slot>
323
381
  <div class="drag-surface"></div>
324
- ${this.bezel > 0 ? E`<div class="corner tl"></div>
382
+ ${this.bezel > 0 ? D`<div class="corner tl"></div>
325
383
  <div class="corner tr"></div>
326
384
  <div class="corner bl"></div>
327
385
  <div class="corner br"></div>` : null}
@@ -330,6 +388,9 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I]
330
388
  `;
331
389
  }
332
390
  };
333
- a([O({ type: Number })], B.prototype, "width", void 0), a([O({ type: Number })], B.prototype, "height", void 0), a([O({ type: Number })], B.prototype, "bezel", void 0), a([O()], B.prototype, "pattern", void 0), a([A({ selector: "vf-window" })], B.prototype, "_windows", void 0), a([k(".screen")], B.prototype, "screen", void 0), a([k(".drag-surface")], B.prototype, "dragSurface", void 0), B = a([t("vf-desktop")], B);
391
+ o([k({ type: Number })], H.prototype, "width", void 0), o([k({ type: Number })], H.prototype, "height", void 0), o([k({ type: Number })], H.prototype, "bezel", void 0), o([k()], H.prototype, "pattern", void 0), o([k({
392
+ type: Number,
393
+ attribute: "window-top"
394
+ })], H.prototype, "windowTop", void 0), o([j({ selector: "vf-window" })], H.prototype, "_windows", void 0), o([A(".screen")], H.prototype, "screen", void 0), o([A(".drag-surface")], H.prototype, "dragSurface", void 0), H = o([t("vf-desktop")], H);
334
395
  //#endregion
335
- export { B as VfDesktop };
396
+ export { H as VfDesktop };
@@ -4,40 +4,48 @@ 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 { vfDisplayDecls as i } from "../styles/recipes/display-face.js";
6
6
  import { vfBase as a } from "../styles/recipes/host.js";
7
- import { GridSnapController as o } from "../grid-snap.js";
8
- import { LitElement as s, css as c, html as l, nothing as u } from "lit";
9
- import { property as d, state as f } from "lit/decorators.js";
10
- import { classMap as p } from "lit/directives/class-map.js";
7
+ import { vfStrokeDecls as o, vfStrokeInset as s } from "../styles/recipes/stroke.js";
8
+ import { GridSnapController as c } from "../grid-snap.js";
9
+ import { LitElement as l, css as u, html as d, nothing as f } from "lit";
10
+ import { property as p, state as m } from "lit/decorators.js";
11
+ import { classMap as h } from "lit/directives/class-map.js";
11
12
  //#region src/components/vf-fieldset.ts
12
- var m = class extends r(s) {
13
+ var g = class extends r(l) {
13
14
  constructor(...e) {
14
- super(...e), this.scale = new t(this), this.gridSnap = new o(this), this.legend = "", this._hasSlottedLegend = !1;
15
+ super(...e), this.scale = new t(this), this.gridSnap = new c(this), this.legend = "", this._hasSlottedLegend = !1;
15
16
  }
16
17
  static {
17
- this.styles = [a, c`
18
+ this.styles = [a, u`
18
19
  :host {
19
20
  display: block;
20
21
  }
21
22
  .fieldset {
22
23
  position: relative;
23
- border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
24
+ margin-top: calc(var(--vf-scale, 1) * 8px);
25
+ ${o()}
26
+ }
27
+ /* The rule is a stroke, so the box's own padding box runs under it: the
28
+ slot is the box inside it, where the content sits 14/12/10px in and
29
+ children placed with top/left measure from the rule's inner edge. */
30
+ .fieldset > slot {
31
+ display: block;
32
+ position: relative;
24
33
  padding: calc(var(--vf-scale, 1) * 14px) calc(var(--vf-scale, 1) * 12px)
25
34
  calc(var(--vf-scale, 1) * 10px);
26
- margin-top: calc(var(--vf-scale, 1) * 8px);
27
35
  }
28
36
  .legend {
29
37
  /* Chicago-style legend (chrome); grouped content keeps the body face. */
30
38
  ${i}
31
39
  position: absolute;
32
- /* Whole system px like every other length here. Authored as -0.7em
33
- this was 11.2px against the 16px display face — off the device grid
34
- at every scale, and it took a slotted legend with it (verify:grid).
35
- 11 keeps the legend straddling the border, a fifth of a system px
36
- lower. */
37
- top: calc(var(--vf-scale, 1) * -11px);
38
- left: calc(var(--vf-scale, 1) * 8px);
40
+ /* Whole system px like every other length here, measured from the
41
+ rule's inner edge. Authored as -0.7em this was 11.2px against the
42
+ 16px display face — off the device grid at every scale, and it took
43
+ a slotted legend with it (verify:grid). 11 keeps the legend
44
+ straddling the rule, a fifth of a system px lower. */
45
+ top: ${s(-11)};
46
+ left: ${s(8)};
39
47
  padding: 0 calc(var(--vf-scale, 1) * 5px);
40
- /* Punches through the border, matching the surface behind it. */
48
+ /* Punches through the rule, matching the surface behind it. */
41
49
  background: var(--vf-surface, var(--vf-white, #fff));
42
50
  white-space: nowrap;
43
51
  }
@@ -48,16 +56,16 @@ var m = class extends r(s) {
48
56
  }
49
57
  render() {
50
58
  let e = !this.legend && !this._hasSlottedLegend;
51
- return l`
59
+ return d`
52
60
  <div
53
61
  class="fieldset vf-snap"
54
62
  part="fieldset"
55
63
  role="group"
56
- aria-labelledby=${e ? u : "legend"}
64
+ aria-labelledby=${e ? f : "legend"}
57
65
  >
58
66
  <span
59
67
  id="legend"
60
- class=${p({
68
+ class=${h({
61
69
  legend: !0,
62
70
  empty: e
63
71
  })}
@@ -76,6 +84,6 @@ var m = class extends r(s) {
76
84
  this._hasSlottedLegend = t.assignedNodes({ flatten: !0 }).length > 0;
77
85
  }
78
86
  };
79
- n([d()], m.prototype, "legend", void 0), n([f()], m.prototype, "_hasSlottedLegend", void 0), m = n([e("vf-fieldset")], m);
87
+ n([p()], g.prototype, "legend", void 0), n([m()], g.prototype, "_hasSlottedLegend", void 0), g = n([e("vf-fieldset")], g);
80
88
  //#endregion
81
- export { m as VfFieldset };
89
+ export { g as VfFieldset };
@@ -67,7 +67,7 @@ declare const VfIconField_base: (new (...args: any[]) => import("../size.js").Vf
67
67
  * the pointer, and the selection follows it live by the Finder's one rule:
68
68
  * **an icon is selected exactly when it was selected at the press XOR the
69
69
  * rectangle touches it.** The press fixes that anchor: a plain press has
70
- * already cleared everything (the way any press outside an icon does), so
70
+ * already cleared everything (a press on a field's background does), so
71
71
  * the rectangle simply selects what it touches and releases what it leaves;
72
72
  * with Shift or ⌘ held the selection survives the press and the rectangle
73
73
  * *toggles* against it — an icon already selected deselects while the