vintage-frames 0.5.3 → 0.5.4
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/custom-elements.json
CHANGED
|
@@ -2237,7 +2237,7 @@
|
|
|
2237
2237
|
"declarations": [
|
|
2238
2238
|
{
|
|
2239
2239
|
"kind": "class",
|
|
2240
|
-
"description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first,
|
|
2240
|
+
"description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its top corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).",
|
|
2241
2241
|
"name": "VfDesktop",
|
|
2242
2242
|
"cssProperties": [
|
|
2243
2243
|
{
|
|
@@ -2460,6 +2460,16 @@
|
|
|
2460
2460
|
"default": "false",
|
|
2461
2461
|
"description": "Whether _syncDomOrder is putting focus back after a node move."
|
|
2462
2462
|
},
|
|
2463
|
+
{
|
|
2464
|
+
"kind": "field",
|
|
2465
|
+
"name": "_domSyncTimer",
|
|
2466
|
+
"type": {
|
|
2467
|
+
"text": "number"
|
|
2468
|
+
},
|
|
2469
|
+
"privacy": "private",
|
|
2470
|
+
"default": "0",
|
|
2471
|
+
"description": "The pending DOM-order sync task, or 0 (see _requestDomSync)."
|
|
2472
|
+
},
|
|
2463
2473
|
{
|
|
2464
2474
|
"kind": "field",
|
|
2465
2475
|
"name": "_gestureEnd",
|
|
@@ -2503,7 +2513,7 @@
|
|
|
2503
2513
|
}
|
|
2504
2514
|
}
|
|
2505
2515
|
],
|
|
2506
|
-
"description": "Bring a slotted window to the front of its tier. A document-tier window\nalso becomes the single active window (clearing `active` on the other\ndocument windows); a utility window restacks within the floating tier\nand leaves every `active` state alone.\n\nThe light-DOM order of the slotted windows follows (_syncDomOrder):\nvisual stacking and sequential focus order come from independent channels\n(z-index vs DOM position), and letting them drift apart is how a desktop\ntabs front-to-back one way and back-to-front the other, with widgets\nreachable only travelling backwards.
|
|
2516
|
+
"description": "Bring a slotted window to the front of its tier. A document-tier window\nalso becomes the single active window (clearing `active` on the other\ndocument windows); a utility window restacks within the floating tier\nand leaves every `active` state alone.\n\nThe light-DOM order of the slotted windows follows (_syncDomOrder):\nvisual stacking and sequential focus order come from independent channels\n(z-index vs DOM position), and letting them drift apart is how a desktop\ntabs front-to-back one way and back-to-front the other, with widgets\nreachable only travelling backwards. The sync runs in a task, and not\nbefore any in-flight pointer gesture has ended — moving a node clears the\npointer capture a title-bar drag or grow-box resize holds on it (a\nbackground window must stay draggable in the same gesture that raises\nit), and a node moved between a press's release and its `click` costs a\ncontrol in the raised window that click (see _requestDomSync)."
|
|
2507
2517
|
},
|
|
2508
2518
|
{
|
|
2509
2519
|
"kind": "field",
|
|
@@ -2552,7 +2562,7 @@
|
|
|
2552
2562
|
"text": "void"
|
|
2553
2563
|
}
|
|
2554
2564
|
},
|
|
2555
|
-
"description": "
|
|
2565
|
+
"description": "Schedule the DOM-order sync: one task from now, coalesced, and never\nwhile a pointer is down — the gesture's end schedules it instead.\n\nA task rather than the synchronous move this used to be, because the\nbrowser dispatches a release's pointerup, mouseup and click in ONE task,\nand Chromium drops a click whose mousedown node left the tree before the\nclick was dispatched — and re-inserting a window is a removal. Synced at\npointerup, a raise moved the window between the press and its click, so\na control in a background window (a checkbox in a palette under another\npalette) got its press and release but never its click: it looked\npressed and never acted. Not a microtask either — that runs between the\nlisteners of the same dispatch, still ahead of the click. A task runs\nafter the whole chain, the shape `deferActivation` (src/events.ts) falls\nback on for the same reason."
|
|
2556
2566
|
},
|
|
2557
2567
|
{
|
|
2558
2568
|
"kind": "method",
|
|
@@ -2571,7 +2581,7 @@
|
|
|
2571
2581
|
}
|
|
2572
2582
|
}
|
|
2573
2583
|
],
|
|
2574
|
-
"description": "Raise the window an event originated in, skipping the restack/activation\nchurn when it is already on top of its own tier (and, for a document\nwindow, already active): otherwise every click inside the front window\nwould bump _zCounter and re-run the whole-fleet activation loop for\nnothing.\n\nRestacks z/active only — deliberately no DOM sync. A focus-driven raise\nMUST NOT move nodes: moving the window focus just entered re-orders the\nsequence mid-traversal, and a Shift+Tab that raises each window it\nenters (pushing it forward in the DOM, back the way the traversal came)\nwould revisit it forever. The pointer path
|
|
2584
|
+
"description": "Raise the window an event originated in, skipping the restack/activation\nchurn when it is already on top of its own tier (and, for a document\nwindow, already active): otherwise every click inside the front window\nwould bump _zCounter and re-run the whole-fleet activation loop for\nnothing.\n\nRestacks z/active only — deliberately no DOM sync. A focus-driven raise\nMUST NOT move nodes: moving the window focus just entered re-orders the\nsequence mid-traversal, and a Shift+Tab that raises each window it\nenters (pushing it forward in the DOM, back the way the traversal came)\nwould revisit it forever. The pointer path schedules the sync at gesture\nend instead, which is also the next safe point after any keyboard-session\nstaleness."
|
|
2575
2585
|
},
|
|
2576
2586
|
{
|
|
2577
2587
|
"kind": "field",
|
|
@@ -2583,7 +2593,7 @@
|
|
|
2583
2593
|
"kind": "field",
|
|
2584
2594
|
"name": "_onGestureEnd",
|
|
2585
2595
|
"privacy": "private",
|
|
2586
|
-
"description": "The press ended (or was cancelled) —
|
|
2596
|
+
"description": "The press ended (or was cancelled) — schedule the DOM-order sync.\nUnconditional rather than only-if-raised: the sync no-ops when order\nalready agrees, and running it after every gesture is what heals the\nstaleness a keyboard-only stretch leaves behind (focus-driven raises\nchange z but never move nodes — see _raise)."
|
|
2587
2597
|
},
|
|
2588
2598
|
{
|
|
2589
2599
|
"kind": "field",
|
|
@@ -2715,7 +2725,7 @@
|
|
|
2715
2725
|
"text": "void"
|
|
2716
2726
|
}
|
|
2717
2727
|
},
|
|
2718
|
-
"description": "Re-order the slotted windows in the light DOM to match their z-order\n(bottom-most first), so sequential focus navigation walks the stack the\nway the eye does — and Shift+Tab is its exact mirror. The utility band\nsorts the floating tier after every document window by construction.\n\nMinimal-move: windows already in relative order are never touched (the\ncommon case — after one raise, one window moves). Non-window siblings\n(a menu bar, page content) keep their positions; only a window that must\ncross the stack moves past them. Moving a node containing the focused\nelement drops focus to `<body>`, so it is restored afterwards — behind\n`_restoringFocus`, because the restore re-fires focusin (see\n_onFocusIn) on an element that may sit in a background window.\
|
|
2728
|
+
"description": "Re-order the slotted windows in the light DOM to match their z-order\n(bottom-most first), so sequential focus navigation walks the stack the\nway the eye does — and Shift+Tab is its exact mirror. The utility band\nsorts the floating tier after every document window by construction.\n\nMinimal-move: windows already in relative order are never touched (the\ncommon case — after one raise, one window moves). Non-window siblings\n(a menu bar, page content) keep their positions; only a window that must\ncross the stack moves past them. Moving a node containing the focused\nelement drops focus to `<body>`, so it is restored afterwards — behind\n`_restoringFocus`, because the restore re-fires focusin (see\n_onFocusIn) on an element that may sit in a background window.\nReached only through _requestDomSync's task — after a pointer\ngesture or a programmatic raise, never from a focus-driven one (see\n_raise for why)."
|
|
2719
2729
|
},
|
|
2720
2730
|
{
|
|
2721
2731
|
"kind": "field",
|
|
@@ -9,9 +9,9 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
|
|
|
9
9
|
* `vf-window` children: a `pointerdown` or
|
|
10
10
|
* `focusin` (keyboard focus) anywhere inside a window brings it to the front
|
|
11
11
|
* and makes it the single active window. The windows' light-DOM order is kept
|
|
12
|
-
* in step with the stacking order (bottom-most first,
|
|
13
|
-
*
|
|
14
|
-
* its exact mirror.
|
|
12
|
+
* in step with the stacking order (bottom-most first, synced in a task once
|
|
13
|
+
* any pointer gesture has ended), so tabbing walks the stack the way the eye
|
|
14
|
+
* does and Shift+Tab is its exact mirror.
|
|
15
15
|
*
|
|
16
16
|
* Utility windows (`vf-window[variant="utility"]`) stack in a floating tier
|
|
17
17
|
* above every document-tier window, restack only among themselves, and stand
|
|
@@ -183,6 +183,8 @@ export declare class VfDesktop extends VfDesktop_base {
|
|
|
183
183
|
private _pointerGesture;
|
|
184
184
|
/** Whether {@link _syncDomOrder} is putting focus back after a node move. */
|
|
185
185
|
private _restoringFocus;
|
|
186
|
+
/** The pending DOM-order sync task, or 0 (see {@link _requestDomSync}). */
|
|
187
|
+
private _domSyncTimer;
|
|
186
188
|
/**
|
|
187
189
|
* Ends the pointer-gesture window that defers DOM reordering. Capture-phase
|
|
188
190
|
* on the document so a component's `stopPropagation` can't strand the flag,
|
|
@@ -206,10 +208,12 @@ export declare class VfDesktop extends VfDesktop_base {
|
|
|
206
208
|
* visual stacking and sequential focus order come from independent channels
|
|
207
209
|
* (z-index vs DOM position), and letting them drift apart is how a desktop
|
|
208
210
|
* tabs front-to-back one way and back-to-front the other, with widgets
|
|
209
|
-
* reachable only travelling backwards.
|
|
210
|
-
* pointer gesture — moving a node clears the
|
|
211
|
-
* drag or grow-box resize holds on it
|
|
212
|
-
* draggable in the same gesture that raises
|
|
211
|
+
* reachable only travelling backwards. The sync runs in a task, and not
|
|
212
|
+
* before any in-flight pointer gesture has ended — moving a node clears the
|
|
213
|
+
* pointer capture a title-bar drag or grow-box resize holds on it (a
|
|
214
|
+
* background window must stay draggable in the same gesture that raises
|
|
215
|
+
* it), and a node moved between a press's release and its `click` costs a
|
|
216
|
+
* control in the raised window that click (see {@link _requestDomSync}).
|
|
213
217
|
*/
|
|
214
218
|
bringToFront(win: HTMLElement): void;
|
|
215
219
|
/** The active document-tier window, or null while the tier is deactivated
|
|
@@ -226,7 +230,22 @@ export declare class VfDesktop extends VfDesktop_base {
|
|
|
226
230
|
clearActive(): void;
|
|
227
231
|
/** The z/active half of a raise, shared by every path. */
|
|
228
232
|
private _restack;
|
|
229
|
-
/**
|
|
233
|
+
/**
|
|
234
|
+
* Schedule the DOM-order sync: one task from now, coalesced, and never
|
|
235
|
+
* while a pointer is down — the gesture's end schedules it instead.
|
|
236
|
+
*
|
|
237
|
+
* A task rather than the synchronous move this used to be, because the
|
|
238
|
+
* browser dispatches a release's pointerup, mouseup and click in ONE task,
|
|
239
|
+
* and Chromium drops a click whose mousedown node left the tree before the
|
|
240
|
+
* click was dispatched — and re-inserting a window is a removal. Synced at
|
|
241
|
+
* pointerup, a raise moved the window between the press and its click, so
|
|
242
|
+
* a control in a background window (a checkbox in a palette under another
|
|
243
|
+
* palette) got its press and release but never its click: it looked
|
|
244
|
+
* pressed and never acted. Not a microtask either — that runs between the
|
|
245
|
+
* listeners of the same dispatch, still ahead of the click. A task runs
|
|
246
|
+
* after the whole chain, the shape `deferActivation` (src/events.ts) falls
|
|
247
|
+
* back on for the same reason.
|
|
248
|
+
*/
|
|
230
249
|
private _requestDomSync;
|
|
231
250
|
/**
|
|
232
251
|
* Raise the window an event originated in, skipping the restack/activation
|
|
@@ -239,8 +258,9 @@ export declare class VfDesktop extends VfDesktop_base {
|
|
|
239
258
|
* MUST NOT move nodes: moving the window focus just entered re-orders the
|
|
240
259
|
* sequence mid-traversal, and a Shift+Tab that raises each window it
|
|
241
260
|
* enters (pushing it forward in the DOM, back the way the traversal came)
|
|
242
|
-
* would revisit it forever. The pointer path
|
|
243
|
-
* which is also the next safe point after any keyboard-session
|
|
261
|
+
* would revisit it forever. The pointer path schedules the sync at gesture
|
|
262
|
+
* end instead, which is also the next safe point after any keyboard-session
|
|
263
|
+
* staleness.
|
|
244
264
|
*/
|
|
245
265
|
private _raise;
|
|
246
266
|
/**
|
|
@@ -251,11 +271,11 @@ export declare class VfDesktop extends VfDesktop_base {
|
|
|
251
271
|
*/
|
|
252
272
|
private _onPointerDown;
|
|
253
273
|
/**
|
|
254
|
-
* The press ended (or was cancelled) —
|
|
255
|
-
* rather than only-if-raised: the sync no-ops when order
|
|
256
|
-
* and running it
|
|
257
|
-
* keyboard-only stretch leaves behind (focus-driven raises
|
|
258
|
-
* never move nodes — see {@link _raise}).
|
|
274
|
+
* The press ended (or was cancelled) — schedule the DOM-order sync.
|
|
275
|
+
* Unconditional rather than only-if-raised: the sync no-ops when order
|
|
276
|
+
* already agrees, and running it after every gesture is what heals the
|
|
277
|
+
* staleness a keyboard-only stretch leaves behind (focus-driven raises
|
|
278
|
+
* change z but never move nodes — see {@link _raise}).
|
|
259
279
|
*/
|
|
260
280
|
private _onGestureEnd;
|
|
261
281
|
/**
|
|
@@ -311,8 +331,9 @@ export declare class VfDesktop extends VfDesktop_base {
|
|
|
311
331
|
* element drops focus to `<body>`, so it is restored afterwards — behind
|
|
312
332
|
* `_restoringFocus`, because the restore re-fires focusin (see
|
|
313
333
|
* {@link _onFocusIn}) on an element that may sit in a background window.
|
|
314
|
-
*
|
|
315
|
-
* focus-driven
|
|
334
|
+
* Reached only through {@link _requestDomSync}'s task — after a pointer
|
|
335
|
+
* gesture or a programmatic raise, never from a focus-driven one (see
|
|
336
|
+
* {@link _raise} for why).
|
|
316
337
|
*/
|
|
317
338
|
private _syncDomOrder;
|
|
318
339
|
protected willUpdate(changed: PropertyValues<this>): void;
|
|
@@ -23,7 +23,7 @@ var A = 1e6, j = 2 * A, M = 512, N = 342, P = "gray-50", F = p(d[P], "#000000",
|
|
|
23
23
|
width: this.width ?? M,
|
|
24
24
|
height: this.height ?? N
|
|
25
25
|
})
|
|
26
|
-
}), this._zCounter = 0, this._activeWindow = null, this._deactivated = !1, this._awaitingUpgrade = !1, this._pointerGesture = !1, this._restoringFocus = !1, this._gestureEnd = new b(this, () => [[
|
|
26
|
+
}), this._zCounter = 0, this._activeWindow = null, this._deactivated = !1, this._awaitingUpgrade = !1, this._pointerGesture = !1, this._restoringFocus = !1, this._domSyncTimer = 0, this._gestureEnd = new b(this, () => [[
|
|
27
27
|
document,
|
|
28
28
|
"pointerup",
|
|
29
29
|
this._onGestureEnd,
|
|
@@ -38,7 +38,7 @@ var A = 1e6, j = 2 * A, M = 512, N = 342, P = "gray-50", F = p(d[P], "#000000",
|
|
|
38
38
|
let t = this._windowFromEvent(e);
|
|
39
39
|
t && this._raise(t);
|
|
40
40
|
}, this._onGestureEnd = () => {
|
|
41
|
-
this._gestureEnd.detach(), this._pointerGesture = !1, this.
|
|
41
|
+
this._gestureEnd.detach(), this._pointerGesture = !1, this._requestDomSync();
|
|
42
42
|
}, this._onFocusIn = (e) => {
|
|
43
43
|
if (this._restoringFocus) return;
|
|
44
44
|
let t = this._windowFromEvent(e);
|
|
@@ -185,7 +185,7 @@ var A = 1e6, j = 2 * A, M = 512, N = 342, P = "gray-50", F = p(d[P], "#000000",
|
|
|
185
185
|
super.connectedCallback(), this.addEventListener("pointerdown", this._onPointerDown), this.addEventListener("focusin", this._onFocusIn);
|
|
186
186
|
}
|
|
187
187
|
disconnectedCallback() {
|
|
188
|
-
this.removeEventListener("pointerdown", this._onPointerDown), this.removeEventListener("focusin", this._onFocusIn), this._pointerGesture = !1, super.disconnectedCallback();
|
|
188
|
+
this.removeEventListener("pointerdown", this._onPointerDown), this.removeEventListener("focusin", this._onFocusIn), this._pointerGesture = !1, this._domSyncTimer &&= (clearTimeout(this._domSyncTimer), 0), super.disconnectedCallback();
|
|
189
189
|
}
|
|
190
190
|
_isUtility(e) {
|
|
191
191
|
return e.getAttribute("variant") === "utility";
|
|
@@ -204,7 +204,9 @@ var A = 1e6, j = 2 * A, M = 512, N = 342, P = "gray-50", F = p(d[P], "#000000",
|
|
|
204
204
|
e.style.zIndex = String(++this._zCounter + (t ? A : 0)), t || this._setActive(e);
|
|
205
205
|
}
|
|
206
206
|
_requestDomSync() {
|
|
207
|
-
this._pointerGesture || this.
|
|
207
|
+
this._pointerGesture || this._domSyncTimer || (this._domSyncTimer = window.setTimeout(() => {
|
|
208
|
+
this._domSyncTimer = 0, this._pointerGesture || this._syncDomOrder();
|
|
209
|
+
}, 0));
|
|
208
210
|
}
|
|
209
211
|
_raise(e) {
|
|
210
212
|
let t = this._isUtility(e), n = this._windows.filter((e) => this._isUtility(e) === t);
|
package/docs/SPEC.md
CHANGED
|
@@ -199,7 +199,7 @@ Full-bleed classic desktop container.
|
|
|
199
199
|
- **Visual:** `display: block; position: relative;` — the paint lives on an inner screen surface (part `desktop`, `overflow: hidden` — the whole-system-px raster, inset by `bezel` when one is set). Screen surface = the `pattern` (the classic 50% dither, `gray-50`, by default), painted as the screen's own background by the pattern fill (*Patterns* under *Tiled fills*): black ink on the fill's opaque `--vf-white` paper, one whole-surface raster — the authentic black-on-white dither. A consumer `--vf-desktop-pattern` renders instead as a placed tile grid on the token's 30-system-px tile with no paper, so `var(--vf-desktop, #808080)` beneath shows only under a custom tile with transparent cells (or `none`). Forced colors: flat Canvas.
|
|
200
200
|
- **Slots:** default (menu bar, windows, anything).
|
|
201
201
|
- **Behavior:** manages stacking of slotted `vf-window` children: `pointerdown` *or `focusin`* on a window brings it to front (incrementing z-index counter) and sets its `active` attribute, clearing `active` on the others — the `focusin` half is the keyboard route to activation: Tab landing anywhere in a background window (its undrawn-but-focusable widgets included) raises it. Listens via delegated pointerdown/focusin listeners + `slotchange`. Windows slotted before `vf-window` is defined are re-normalized once `customElements.whenDefined('vf-window')` settles, since the upgrade reflects each window's `active = true` default back out and upgrading a slotted node doesn't re-fire `slotchange`.
|
|
202
|
-
- **DOM order follows z-order** (bottom-most first), so sequential focus order matches the visual stack and Shift+Tab mirrors Tab exactly. The sync runs
|
|
202
|
+
- **DOM order follows z-order** (bottom-most first), so sequential focus order matches the visual stack and Shift+Tab mirrors Tab exactly. The sync runs in a task after a pointer gesture ends, or after a programmatic `bringToFront` — never mid-gesture (a node move would clear the pointer capture a title-bar drag or grow-box resize holds), never between a press's release and its `click` (Chromium drops a click whose mousedown node was re-inserted first, which used to cost a control in a background window its click), and never from a focus-driven raise (moving the window focus just entered would re-order the tab sequence mid-traversal); focus surviving its own window's move is restored without re-raising that window. Non-window children (a menu bar, page content) keep their positions. `npm run verify:window-a11y`.
|
|
203
203
|
- **Floating tier:** `vf-window[variant="utility"]` children stack in a z band `1_000_000` above the document tier (one shared monotonic counter, so a palette stays above every document window), restack only among themselves, and stand outside the single-active invariant both ways: clicking a palette doesn't deactivate the active document window, and activating a document window never clears a palette's `active` — System 7 windoid behavior while the app is frontmost. The tier test reads the `variant` *attribute*, so a not-yet-upgraded element still lands right.
|
|
204
204
|
- **Menu tier:** a slotted `vf-menu-bar` — or a free-standing `vf-menu` placed on the desktop — is restated at `z-index: 2_000_000` by the desktop's own `::slotted(vf-menu-bar), ::slotted(vf-menu)` rule (an outer-tree `::slotted` declaration beats the bar's inner `:host { z-index: 1000 }`), a band above the floating tier, so a dropped menu paints over palettes and document windows alike — the Menu Manager drew menus over every window. Only the screen-corner mask is in front. The full stack inside the screen's isolated context: consumer tile grid (−1) < document windows (counter) < utility windows (counter + 1_000_000) < menu tier (2_000_000) < corner mask (max). A popup *inside* a window (`vf-select`'s fixed panel) is a different case: it stacks within its window's context, so a palette can still cover it — KNOWN-BUGS.md. `npm run verify:archetypes` (MENU TIER).
|
|
205
205
|
- **Deactivation:** on a real System 7 machine clicking the desktop clicked the *Finder* — the frontmost application's windows lost their stripes. `clearActive()` is that gesture's handler: it clears `active` from the whole document tier, and **zero active windows is a legal state**, held until a press or `focusin` re-enters a document window or a new one is slotted (opening a window brings its application forward — a newly slotted window ends a deliberate deactivation, where a mere survivor never does: removing a *background* window while deactivated promotes nothing, while removing the holder outside a deactivation promotes the topmost survivor). The desktop never takes the decision itself — a press on its own bare dither changes nothing; desktop furniture is slotted light DOM, so only the page knows which of its children mean "the Finder". Utility windows keep their `active` through a deactivation (their dots stay drawn). Every change of holder — window to window, window to none, none to window — fires `vf-activate`, once per change; re-asserting the current holder is silent. `npm run verify:desktop-activate`.
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
},
|
|
192
192
|
{
|
|
193
193
|
"name": "vf-desktop",
|
|
194
|
-
"description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first,
|
|
194
|
+
"description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its top corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).\n---\n\n\n### **Events:**\n - **vf-activate** - The active document-tier window changed. Detail `{ window: HTMLElement | null }` — the new holder, or `null` when the document tier deactivated (a {@link clearActive} call, or the active window leaving the DOM with none behind it). Fired once per change of holder, never for a re-assertion of the same one.\n\n### **Slots:**\n - _default_ - Default slot: menu bar, windows, anything.\n\n### **CSS Properties:**\n - **--vf-desktop** - base color under the desktop pattern — occluded by the pattern's opaque paper, so it only shows through a custom `--vf-desktop-pattern` _(default: #808080)_\n- **--vf-desktop-pattern** - a consumer's own desktop tile, in place of `pattern` — the kit's default is the 50% checker drawn as opaque black-on-white rects on a 30-system-px tile. Override the whole tile; consumer art renders as a placed tile grid at that same geometry (raster art magnifies nearest-neighbor, the `vf-img` idiom) _(default: undefined)_\n\n### **CSS Parts:**\n - **desktop** - The patterned screen surface — the whole-system-px raster (inset by `bezel` when one is set).",
|
|
195
195
|
"attributes": [
|
|
196
196
|
{
|
|
197
197
|
"name": "width",
|
package/editor/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
|
|
3
3
|
"name": "vintage-frames",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.4",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
@@ -457,7 +457,7 @@
|
|
|
457
457
|
},
|
|
458
458
|
{
|
|
459
459
|
"name": "vf-desktop",
|
|
460
|
-
"description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first,
|
|
460
|
+
"description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its top corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).\n---\n\n\n### **Events:**\n - **vf-activate** - The active document-tier window changed. Detail `{ window: HTMLElement | null }` — the new holder, or `null` when the document tier deactivated (a {@link clearActive} call, or the active window leaving the DOM with none behind it). Fired once per change of holder, never for a re-assertion of the same one.\n\n### **Slots:**\n - _default_ - Default slot: menu bar, windows, anything.\n\n### **CSS Properties:**\n - **--vf-desktop** - base color under the desktop pattern — occluded by the pattern's opaque paper, so it only shows through a custom `--vf-desktop-pattern` _(default: #808080)_\n- **--vf-desktop-pattern** - a consumer's own desktop tile, in place of `pattern` — the kit's default is the 50% checker drawn as opaque black-on-white rects on a 30-system-px tile. Override the whole tile; consumer art renders as a placed tile grid at that same geometry (raster art magnifies nearest-neighbor, the `vf-img` idiom) _(default: undefined)_\n\n### **CSS Parts:**\n - **desktop** - The patterned screen surface — the whole-system-px raster (inset by `bezel` when one is set).",
|
|
461
461
|
"doc-url": "",
|
|
462
462
|
"attributes": [
|
|
463
463
|
{
|