vintage-frames 0.19.1 → 0.20.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 (59) hide show
  1. package/README.md +1 -18
  2. package/custom-elements.json +72 -13
  3. package/dist/components/vf-desktop.d.ts +36 -6
  4. package/dist/components/vf-desktop.js +41 -23
  5. package/dist/components/vf-window.d.ts +19 -0
  6. package/dist/components/vf-window.js +33 -3
  7. package/dist/text-control.d.ts +3 -3
  8. package/docs/SPEC.md +8 -6
  9. package/editor/vscode.html-custom-data.json +10 -5
  10. package/editor/web-types.json +25 -10
  11. package/package.json +4 -34
  12. package/dist/build/app-file.d.ts +0 -21
  13. package/dist/build/app-file.js +0 -42
  14. package/dist/build/box.d.ts +0 -57
  15. package/dist/build/box.js +0 -93
  16. package/dist/build/client.d.ts +0 -12
  17. package/dist/build/frame-picture.d.ts +0 -6
  18. package/dist/build/frame-picture.js +0 -4
  19. package/dist/build/frame.d.ts +0 -11
  20. package/dist/build/frame.js +0 -44
  21. package/dist/build/index.d.ts +0 -14
  22. package/dist/build/index.js +0 -4
  23. package/dist/build/plugins.d.ts +0 -41
  24. package/dist/build/plugins.js +0 -134
  25. package/dist/build/png.d.ts +0 -24
  26. package/dist/build/png.js +0 -116
  27. package/dist/shell/alert.d.ts +0 -40
  28. package/dist/shell/alert.js +0 -41
  29. package/dist/shell/app-file.d.ts +0 -115
  30. package/dist/shell/app-file.js +0 -189
  31. package/dist/shell/catalog.d.ts +0 -250
  32. package/dist/shell/catalog.js +0 -349
  33. package/dist/shell/clock.d.ts +0 -16
  34. package/dist/shell/clock.js +0 -36
  35. package/dist/shell/filing.d.ts +0 -39
  36. package/dist/shell/filing.js +0 -68
  37. package/dist/shell/finder.d.ts +0 -180
  38. package/dist/shell/finder.js +0 -676
  39. package/dist/shell/geometry.d.ts +0 -203
  40. package/dist/shell/geometry.js +0 -257
  41. package/dist/shell/index.d.ts +0 -30
  42. package/dist/shell/index.js +0 -12
  43. package/dist/shell/pure.d.ts +0 -13
  44. package/dist/shell/pure.js +0 -6
  45. package/dist/shell/shell.d.ts +0 -177
  46. package/dist/shell/shell.js +0 -277
  47. package/dist/shell/state.d.ts +0 -88
  48. package/dist/shell/state.js +0 -103
  49. package/dist/shell/storage.d.ts +0 -14
  50. package/dist/shell/storage.js +0 -41
  51. package/dist/shell/version.d.ts +0 -2
  52. package/dist/shell/version.js +0 -4
  53. package/dist/shell/windows.d.ts +0 -278
  54. package/dist/shell/windows.js +0 -447
  55. package/dist/styles/body-strike.d.ts +0 -12
  56. package/dist/styles/body-strike.js +0 -3961
  57. package/dist/styles/display-strike.d.ts +0 -12
  58. package/dist/styles/display-strike.js +0 -4343
  59. package/dist/styles/strike.d.ts +0 -30
package/README.md CHANGED
@@ -23,24 +23,7 @@ import 'vintage-frames/vf-checkbox.js'
23
23
 
24
24
  There is no need to import a stylesheet. The components carry their styles with them.
25
25
 
26
- ## The shell
27
-
28
- `vintage-frames/shell` is an experimental second entry point that runs applications over one desktop: a window manager, a menu bar that shows the front application's menus, and a Finder with folders, aliases, filing, Clean Up and the Trash. A System Folder's contents set the Apple menu and what opens at startup.
29
-
30
- ```ts
31
- import 'vintage-frames'
32
- import { createShell, finder, memoryStorage } from 'vintage-frames/shell'
33
-
34
- createShell(document.querySelector('vf-desktop'), {
35
- apps: [finder({ storage: memoryStorage(), seed: 'markup', art })],
36
- fit: 'viewport',
37
- })
38
- ```
39
-
40
- See [docs/SHELL.md](https://github.com/aportilla/vintage-frames/blob/main/docs/SHELL.md). Its API may change in any minor release while it is experimental.
41
-
42
- An application on the shell can ship as one PNG, its app file. `vintage-frames/build` holds the Vite plugins that write app files and build them into a site; it runs in the build only. See [docs/APP-FILES.md](https://github.com/aportilla/vintage-frames/blob/main/docs/APP-FILES.md).
43
-
26
+ To run applications over a desktop of these elements, with a window manager, a menu bar and a Finder, see [system-online-sdk](https://github.com/aportilla/system-online-sdk).
44
27
 
45
28
  ## Sizing
46
29
 
@@ -2563,7 +2563,7 @@
2563
2563
  "declarations": [
2564
2564
  {
2565
2565
  "kind": "class",
2566
- "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. A press on a title bar with ⌘ held\nraises nothing, so a background window is dragged where it stands in the\nstack. 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\n**Hidden windows.** A window with `hidden` — closed by a page that hides\nits windows rather than removing them, through `vf-window.hide()` or the\nattribute itself — never holds the active state. One slotted hidden waits\nto be shown; `bringToFront()` on one gives it its place in the stack and\nactivates nothing; the holder hiding hands the state to the topmost shown\ndocument window, or to none. A window shown into a tier where none is\nactive, unless the tier was deliberately deactivated, takes it.\nstackingOrder lists the windows as they stand, bottom-most first.\n\n**The work area.** A slotted `vf-menu-bar` along the top takes its band\noff the screen: workArea is what is left, and the gestures on the\nscreen stay in it — a window dragged up stops with its title bar under the\nbar, where it can still be grabbed, and an icon dropped, nudged or walked\non the desktop lands below the bar. `window-top` deepens the area for\nwindows alone (windowArea), for a page with a strip of its own\nunder the bar. A gesture asks for the box it is clamped into with\n`vf-placement-bounds-request` (bubbles, non-composed), the drag surface's\nhandshake, and the desktop answers for the hosts placed on its screen.\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 four 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, a repeating tile drawn at the display's resolution, 1-bit at every\ndensity and zoom (src/pattern-fill.ts).\n\n**The drag surface.** The Finder dragged an icon as a dotted outline drawn\non the *screen*, clipped at its edge and phase-locked to its raster, so\nthe screen hosts the layer that outline draws on: a full-bleed child of\nthe screen, `pointer-events: none` (never a hit for the page's\n`elementsFromPoint`), whose children paint one tier above the menu bar\nand under the corner mask — the layer itself is deliberately no stacking\ncontext, since a blend inside one would composite against nothing. An\nicon reaches it without an import, the menu-handshake idiom: on a drag's\nfirst step it dispatches `vf-drag-surface-request` (bubbles, non-composed,\n`detail.surface` null), and the nearest desktop on its light-DOM path\nfills the detail with the layer. A window asks the same way and draws\nthere with the same pen: its zoom rects when it opens from a rect\n(`vf-window.show({ from })`), its outline under an `outline-drag`. Not the\ntop layer: stable Safari cannot\nblend an element there against the page (src/cursor.ts), and a second\nkit entry in the top layer would need a re-promotion handshake.\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`).",
2566
+ "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. A press on a title bar with ⌘ held\nraises nothing, so a background window is dragged where it stands in the\nstack. 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 drag outline, the full-screen tier and the screen-corner\nmask are in front of it.\n\n**The full-screen tier.** fullScreenWindow puts one slotted window\nabove everything else the screen shows — both window tiers, the menu bar\nand its dropped menus, the drag outline and the rects — and under the\ncorner mask alone: the tier a window takes the whole screen on. The page\nsets it and clears it, and sizes, draws and activates the window itself\n(`vf-window`'s `frameless`, the screen's `width` and `height`,\nbringToFront); cleared, the window goes back to its tier where it\nstood.\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\n**Hidden windows.** A window with `hidden` — closed by a page that hides\nits windows rather than removing them, through `vf-window.hide()` or the\nattribute itself — never holds the active state. One slotted hidden waits\nto be shown; `bringToFront()` on one gives it its place in the stack and\nactivates nothing; the holder hiding hands the state to the topmost shown\ndocument window, or to none. A window shown into a tier where none is\nactive, unless the tier was deliberately deactivated, takes it.\nstackingOrder lists the windows as they stand, bottom-most first.\n\n**The work area.** A slotted `vf-menu-bar` along the top takes its band\noff the screen: workArea is what is left, and the gestures on the\nscreen stay in it — a window dragged up stops with its title bar under the\nbar, where it can still be grabbed, and an icon dropped, nudged or walked\non the desktop lands below the bar. `window-top` deepens the area for\nwindows alone (windowArea), for a page with a strip of its own\nunder the bar. A gesture asks for the box it is clamped into with\n`vf-placement-bounds-request` (bubbles, non-composed), the drag surface's\nhandshake, and the desktop answers for the hosts placed on its screen.\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 four 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, a repeating tile drawn at the display's resolution, 1-bit at every\ndensity and zoom (src/pattern-fill.ts).\n\n**The drag surface.** The Finder dragged an icon as a dotted outline drawn\non the *screen*, clipped at its edge and phase-locked to its raster, so\nthe screen hosts the layer that outline draws on: a full-bleed child of\nthe screen, `pointer-events: none` (never a hit for the page's\n`elementsFromPoint`), whose children paint one tier above the menu bar\nand under the corner mask — the layer itself is deliberately no stacking\ncontext, since a blend inside one would composite against nothing. An\nicon reaches it without an import, the menu-handshake idiom: on a drag's\nfirst step it dispatches `vf-drag-surface-request` (bubbles, non-composed,\n`detail.surface` null), and the nearest desktop on its light-DOM path\nfills the detail with the layer. A window asks the same way and draws\nthere with the same pen: its zoom rects when it opens from a rect\n(`vf-window.show({ from })`), its outline under an `outline-drag`. Not the\ntop layer: stable Safari cannot\nblend an element there against the page (src/cursor.ts), and a second\nkit entry in the top layer would need a re-promotion handshake.\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`).",
2567
2567
  "name": "VfDesktop",
2568
2568
  "cssProperties": [
2569
2569
  {
@@ -2933,7 +2933,7 @@
2933
2933
  "type": {
2934
2934
  "text": "HTMLElement[]"
2935
2935
  },
2936
- "description": "The slotted windows in stacking order, bottom-most first: the document\ntier, then the floating tier above it, each in the order its windows\nwere last raised. Hidden windows are included where they stand. This is\nthe order the eye sees; the windows' light-DOM order catches up with it\nonly once a gesture ends, and a raise by keyboard focus moves no node.",
2936
+ "description": "The slotted windows in stacking order, bottom-most first: the document\ntier, then the floating tier above it, each in the order its windows\nwere last raised, and the window on the full-screen tier last. Hidden\nwindows are included where they stand. This is the order the eye sees;\nthe windows' light-DOM order catches up with it only once a gesture\nends, a raise by keyboard focus moves no node, and the full-screen\nwindow keeps the light-DOM place of where it stood.",
2937
2937
  "readonly": true
2938
2938
  },
2939
2939
  {
@@ -2946,6 +2946,45 @@
2946
2946
  },
2947
2947
  "description": "Deactivate the whole document tier — clear `active` from every document\nwindow, leaving none the holder. Pages route \"the user clicked the\nFinder\" presses — on the bare dither, on their own desktop furniture\n(an icon layer) — through here; the deactivated state holds until a\ndocument window is pressed, focused, brought to front, or newly\nslotted."
2948
2948
  },
2949
+ {
2950
+ "kind": "field",
2951
+ "name": "fullScreenWindow",
2952
+ "type": {
2953
+ "text": "HTMLElement | null"
2954
+ },
2955
+ "description": "The window on the full-screen tier, or null. A slotted window set here\nstacks above everything else the screen shows — both window tiers, the\nmenu bar and any dropped menu, the drag outline and the window rects —\nand under the corner mask alone, so the screen keeps its rounded\ncorners: the tier for a window that takes the whole screen. Sizing it to\nthe screen and drawing it without chrome (`vf-window`'s `frameless`) are\nthe page's, and so is bringing it forward: setting this activates\nnothing. One window holds the tier at a time: setting another puts the\nfirst back, and null puts the holder back in its own tier where it\nstood — a raise meanwhile moves that place, as it would have moved the\nwindow. A holder that leaves the desktop gives the tier up. Anything but\na window slotted here warns and changes nothing."
2956
+ },
2957
+ {
2958
+ "kind": "field",
2959
+ "name": "#screenHolder",
2960
+ "privacy": "private",
2961
+ "type": {
2962
+ "text": "HTMLElement | null"
2963
+ },
2964
+ "default": "null",
2965
+ "description": "The window on the full-screen tier, or null (see fullScreenWindow)."
2966
+ },
2967
+ {
2968
+ "kind": "field",
2969
+ "name": "#screenPlace",
2970
+ "privacy": "private",
2971
+ "type": {
2972
+ "text": "string"
2973
+ },
2974
+ "default": "''",
2975
+ "description": "The holder's z-index in its own tier: the place it goes back to."
2976
+ },
2977
+ {
2978
+ "kind": "method",
2979
+ "name": "#leaveScreenTier",
2980
+ "privacy": "private",
2981
+ "return": {
2982
+ "type": {
2983
+ "text": "void"
2984
+ }
2985
+ },
2986
+ "description": "The holder back in its own tier, where it stood."
2987
+ },
2949
2988
  {
2950
2989
  "kind": "method",
2951
2990
  "name": "_restack",
@@ -2963,7 +3002,7 @@
2963
3002
  }
2964
3003
  }
2965
3004
  ],
2966
- "description": "The z/active half of a raise, shared by every path. A hidden window\ntakes its place in the stack and nothing else: it activates when it is\nshown and raised."
3005
+ "description": "The z/active half of a raise, shared by every path. A hidden window\ntakes its place in the stack and nothing else: it activates when it is\nshown and raised. The full-screen window stays on its tier, and the\nraise moves the place it goes back to."
2967
3006
  },
2968
3007
  {
2969
3008
  "kind": "method",
@@ -3182,7 +3221,7 @@
3182
3221
  "text": "void"
3183
3222
  }
3184
3223
  },
3185
- "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. `moveBefore()` keeps the focus inside a\nmoved window where the browser has it (_move); re-inserting a\nnode containing the focused element drops focus to `<body>`, so it is\nrestored afterwards — behind `_restoringFocus`, because the restore\nre-fires focusin (see _onFocusIn) on an element that may sit in a\nbackground 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)."
3224
+ "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. `moveBefore()` keeps the focus inside a\nmoved window where the browser has it (_move); re-inserting a\nnode containing the focused element drops focus to `<body>`, so it is\nrestored afterwards — behind `_restoringFocus`, because the restore\nre-fires focusin (see _onFocusIn) on an element that may sit in a\nbackground window. The full-screen window is ordered by the place it\ngoes back to, so taking and leaving the tier move no node.\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)."
3186
3225
  },
3187
3226
  {
3188
3227
  "kind": "method",
@@ -10567,7 +10606,7 @@
10567
10606
  "text": "boolean"
10568
10607
  },
10569
10608
  "default": "false",
10570
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
10609
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
10571
10610
  "attribute": "autoselect",
10572
10611
  "reflects": true,
10573
10612
  "inheritedFrom": {
@@ -11581,7 +11620,7 @@
11581
11620
  "text": "boolean"
11582
11621
  },
11583
11622
  "default": "false",
11584
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
11623
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
11585
11624
  "fieldName": "autoselect",
11586
11625
  "inheritedFrom": {
11587
11626
  "name": "VfTextControlBase",
@@ -18667,7 +18706,7 @@
18667
18706
  "text": "boolean"
18668
18707
  },
18669
18708
  "default": "false",
18670
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
18709
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
18671
18710
  "attribute": "autoselect",
18672
18711
  "reflects": true,
18673
18712
  "inheritedFrom": {
@@ -19695,7 +19734,7 @@
19695
19734
  "text": "boolean"
19696
19735
  },
19697
19736
  "default": "false",
19698
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
19737
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
19699
19738
  "fieldName": "autoselect",
19700
19739
  "inheritedFrom": {
19701
19740
  "name": "VfTextControlBase",
@@ -19997,7 +20036,7 @@
19997
20036
  "text": "boolean"
19998
20037
  },
19999
20038
  "default": "false",
20000
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
20039
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
20001
20040
  "attribute": "autoselect",
20002
20041
  "reflects": true,
20003
20042
  "inheritedFrom": {
@@ -21032,7 +21071,7 @@
21032
21071
  "text": "boolean"
21033
21072
  },
21034
21073
  "default": "false",
21035
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
21074
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
21036
21075
  "fieldName": "autoselect",
21037
21076
  "inheritedFrom": {
21038
21077
  "name": "VfTextControlBase",
@@ -21144,7 +21183,7 @@
21144
21183
  "declarations": [
21145
21184
  {
21146
21185
  "kind": "class",
21147
- "description": "`<vf-window>` — the System 7 desktop-window shell.\n\nStriped title bar with optional close box (left) and zoom box (right), a\nsolid-white frame with a hard offset shadow, an optional grow box for\nresizing, optional edge scroll rails (`scrollbars`), and the slim windoid\nchrome (`variant=\"utility\"`). The HIG's window archetypes are parameter\nrecipes over this shell rather than fixed anatomies — the component enables\nHIG compliance, it doesn't enforce it (see docs/LAYOUT.md \"Window archetypes\"):\nthe full document window is `closable zoomable movable resizable\nscrollbars=\"both\"`, a modeless dialog box is `closable movable`, a utility\nwindow is `variant=\"utility\" closable movable`. Place inside `<vf-desktop>` to get\nclick-to-front stacking and automatic `active` management (utility windows\nfloat above the document tier).\n\nEvery recipe also declares `width` AND `height` (VfSized), in whole\nsystem px — the art's own unit, so the window keeps its proportions to the\nchrome inside it at every display density (a CSS-px size stays put while\nthe components in it triple). A window is a fixed box in both axes, the way\nthe WIND resource carried it: left to layout it takes whatever its\ncontainer or content hands it, which is how a title bar ends up wider than\nthe screen or a dialog reflows as it moves — and a window that grows with\nits body is one the user can neither predict nor (via the grow box) own.\nContent taller than the declared box is clipped at the frame the way the\nclassic content region was; `scrollbars` lets the user reach the rest.\nUnset, the window still renders — normal block layout, as before — and\nsays so once in the console.\n\n**Opening from a rect.** show clears `hidden`, and given `from` — a\nbox in viewport CSS px, an icon's `cellRect()` or a button's rect — opens\nthe window from it: dotted rectangles grow from that box toward the\nwindow's frame, four on screen at a time, bunched at the box and opening\nout toward the window, drawn with the icon drag outline's XOR pen on the\ndesktop's drag surface; the window draws once they have drained, eighteen\nsteps later. Until then it matches `:state(opening)` and paints nothing —\nstill laid out, focusable and a hit target, so a page can place it, raise\nit and focus into it at once, and a press finishes the rects and lands on\nthe window. Under `prefers-reduced-motion`, with no `vf-desktop` on its\npath, or without `from`, the window shows at once.\n\n**Closing to a rect.** hide sets `hidden`, and given `to` closes\nthe window to it: the same rectangles run the other way, from where the\nframe was in toward the box, the window gone from the first step. A press\nfinishes them, and removing the window leaves them running. Under\n`prefers-reduced-motion`, with no `vf-desktop` on its path, or without\n`to`, the window hides at once. The window knows nothing about icons:\n`from` and `to` are any rect.\n\n**Dragging as an outline.** A `movable` window moves live under the\npointer. With `outline-drag` a press on the title bar draws a dotted\noutline around the window on the desktop's drag surface instead, with the\nsame pen; the drag moves the outline, held where the window can land, and\nthe window moves there on the release. Escape cancels.",
21186
+ "description": "`<vf-window>` — the System 7 desktop-window shell.\n\nStriped title bar with optional close box (left) and zoom box (right), a\nsolid-white frame with a hard offset shadow, an optional grow box for\nresizing, optional edge scroll rails (`scrollbars`), and the slim windoid\nchrome (`variant=\"utility\"`). The HIG's window archetypes are parameter\nrecipes over this shell rather than fixed anatomies — the component enables\nHIG compliance, it doesn't enforce it (see docs/LAYOUT.md \"Window archetypes\"):\nthe full document window is `closable zoomable movable resizable\nscrollbars=\"both\"`, a modeless dialog box is `closable movable`, a utility\nwindow is `variant=\"utility\" closable movable`. Place inside `<vf-desktop>` to get\nclick-to-front stacking and automatic `active` management (utility windows\nfloat above the document tier).\n\nEvery recipe also declares `width` AND `height` (VfSized), in whole\nsystem px — the art's own unit, so the window keeps its proportions to the\nchrome inside it at every display density (a CSS-px size stays put while\nthe components in it triple). A window is a fixed box in both axes, the way\nthe WIND resource carried it: left to layout it takes whatever its\ncontainer or content hands it, which is how a title bar ends up wider than\nthe screen or a dialog reflows as it moves — and a window that grows with\nits body is one the user can neither predict nor (via the grow box) own.\nContent taller than the declared box is clipped at the frame the way the\nclassic content region was; `scrollbars` lets the user reach the rest.\nUnset, the window still renders — normal block layout, as before — and\nsays so once in the console.\n\n**Opening from a rect.** show clears `hidden`, and given `from` — a\nbox in viewport CSS px, an icon's `cellRect()` or a button's rect — opens\nthe window from it: dotted rectangles grow from that box toward the\nwindow's frame, four on screen at a time, bunched at the box and opening\nout toward the window, drawn with the icon drag outline's XOR pen on the\ndesktop's drag surface; the window draws once they have drained, eighteen\nsteps later. Until then it matches `:state(opening)` and paints nothing —\nstill laid out, focusable and a hit target, so a page can place it, raise\nit and focus into it at once, and a press finishes the rects and lands on\nthe window. Under `prefers-reduced-motion`, with no `vf-desktop` on its\npath, or without `from`, the window shows at once.\n\n**Closing to a rect.** hide sets `hidden`, and given `to` closes\nthe window to it: the same rectangles run the other way, from where the\nframe was in toward the box, the window gone from the first step. A press\nfinishes them, and removing the window leaves them running. Under\n`prefers-reduced-motion`, with no `vf-desktop` on its path, or without\n`to`, the window hides at once. The window knows nothing about icons:\n`from` and `to` are any rect.\n\n**Dragging as an outline.** A `movable` window moves live under the\npointer. With `outline-drag` a press on the title bar draws a dotted\noutline around the window on the desktop's drag surface instead, with the\nsame pen; the drag moves the outline, held where the window can land, and\nthe window moves there on the release. Escape cancels.\n\n**Frameless.** With `frameless` the window draws no chrome — no title bar\nor widgets, no frame or shadow, no grow box, no header or status strip —\nand the body is the whole box: a window that takes the whole screen, say,\non `vf-desktop`'s full-screen tier. The chrome is hidden, not torn down, so\nthe switch moves no node and the focus in the body stays where it is.",
21148
21187
  "name": "VfWindow",
21149
21188
  "cssProperties": [
21150
21189
  {
@@ -21238,6 +21277,17 @@
21238
21277
  "attribute": "variant",
21239
21278
  "reflects": true
21240
21279
  },
21280
+ {
21281
+ "kind": "field",
21282
+ "name": "frameless",
21283
+ "type": {
21284
+ "text": "boolean"
21285
+ },
21286
+ "default": "false",
21287
+ "description": "Draw no chrome: no title bar, so no close or zoom box, no frame or\nshadow, no grow box, and no header or status strip, whatever their slots\nhold. The body is the whole box, `pattern` filling it and a placed child\nmeasured from its corner; under `scrollbars` the built-in scroll area\nfills the box, its own frame line on the box's edge. `heading` still\nnames the window. The chrome is hidden rather than left out of the\nrender, so switching this on a connected window moves no node and the\nfocus in the body stays where it is. In a `vf-desktop` the window keeps\nits tier for activation and `hidden`, and `show()` and `hide()` run\ntheir rects from and to its box.",
21288
+ "attribute": "frameless",
21289
+ "reflects": true
21290
+ },
21241
21291
  {
21242
21292
  "kind": "field",
21243
21293
  "name": "heading",
@@ -22154,6 +22204,15 @@
22154
22204
  "description": "Chrome variant. Omit for the standard 18px striped bar; `'utility'` for\nthe slim windoid bar (dot-grid dither, 7×7 widgets, no title patch — the\nheading still names the widgets). Inside a `vf-desktop`, utility windows\nfloat above the document tier and never take the single-active state.",
22155
22205
  "fieldName": "variant"
22156
22206
  },
22207
+ {
22208
+ "name": "frameless",
22209
+ "type": {
22210
+ "text": "boolean"
22211
+ },
22212
+ "default": "false",
22213
+ "description": "Draw no chrome: no title bar, so no close or zoom box, no frame or\nshadow, no grow box, and no header or status strip, whatever their slots\nhold. The body is the whole box, `pattern` filling it and a placed child\nmeasured from its corner; under `scrollbars` the built-in scroll area\nfills the box, its own frame line on the box's edge. `heading` still\nnames the window. The chrome is hidden rather than left out of the\nrender, so switching this on a connected window moves no node and the\nfocus in the body stays where it is. In a `vf-desktop` the window keeps\nits tier for activation and `hidden`, and `show()` and `hide()` run\ntheir rects from and to its box.",
22214
+ "fieldName": "frameless"
22215
+ },
22157
22216
  {
22158
22217
  "name": "heading",
22159
22218
  "type": {
@@ -23375,7 +23434,7 @@
23375
23434
  "text": "boolean"
23376
23435
  },
23377
23436
  "default": "false",
23378
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
23437
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
23379
23438
  "attribute": "autoselect",
23380
23439
  "reflects": true
23381
23440
  },
@@ -24250,7 +24309,7 @@
24250
24309
  "text": "boolean"
24251
24310
  },
24252
24311
  "default": "false",
24253
- "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
24312
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window system-online-sdk's window manager opens.\nA dialog selects the text on every open, a window on its first open only.\nA click still places the caret.",
24254
24313
  "fieldName": "autoselect"
24255
24314
  },
24256
24315
  {
@@ -22,7 +22,17 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
22
22
  * System 7's floating windoids behaved while their application was frontmost.
23
23
  * A slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier
24
24
  * above both, so its dropped menus cover palettes and document windows
25
- * alike; only the screen-corner mask is in front of it.
25
+ * alike; only the drag outline, the full-screen tier and the screen-corner
26
+ * mask are in front of it.
27
+ *
28
+ * **The full-screen tier.** {@link fullScreenWindow} puts one slotted window
29
+ * above everything else the screen shows — both window tiers, the menu bar
30
+ * and its dropped menus, the drag outline and the rects — and under the
31
+ * corner mask alone: the tier a window takes the whole screen on. The page
32
+ * sets it and clears it, and sizes, draws and activates the window itself
33
+ * (`vf-window`'s `frameless`, the screen's `width` and `height`,
34
+ * {@link bringToFront}); cleared, the window goes back to its tier where it
35
+ * stood.
26
36
  *
27
37
  * **Deactivation.** On a real System 7 machine clicking the desktop clicked
28
38
  * the *Finder* — the frontmost application's windows lost their stripes.
@@ -310,9 +320,11 @@ export declare class VfDesktop extends VfDesktop_base {
310
320
  /**
311
321
  * The slotted windows in stacking order, bottom-most first: the document
312
322
  * tier, then the floating tier above it, each in the order its windows
313
- * were last raised. Hidden windows are included where they stand. This is
314
- * the order the eye sees; the windows' light-DOM order catches up with it
315
- * only once a gesture ends, and a raise by keyboard focus moves no node.
323
+ * were last raised, and the window on the full-screen tier last. Hidden
324
+ * windows are included where they stand. This is the order the eye sees;
325
+ * the windows' light-DOM order catches up with it only once a gesture
326
+ * ends, a raise by keyboard focus moves no node, and the full-screen
327
+ * window keeps the light-DOM place of where it stood.
316
328
  */
317
329
  get stackingOrder(): HTMLElement[];
318
330
  /**
@@ -324,10 +336,27 @@ export declare class VfDesktop extends VfDesktop_base {
324
336
  * slotted.
325
337
  */
326
338
  clearActive(): void;
339
+ /**
340
+ * The window on the full-screen tier, or null. A slotted window set here
341
+ * stacks above everything else the screen shows — both window tiers, the
342
+ * menu bar and any dropped menu, the drag outline and the window rects —
343
+ * and under the corner mask alone, so the screen keeps its rounded
344
+ * corners: the tier for a window that takes the whole screen. Sizing it to
345
+ * the screen and drawing it without chrome (`vf-window`'s `frameless`) are
346
+ * the page's, and so is bringing it forward: setting this activates
347
+ * nothing. One window holds the tier at a time: setting another puts the
348
+ * first back, and null puts the holder back in its own tier where it
349
+ * stood — a raise meanwhile moves that place, as it would have moved the
350
+ * window. A holder that leaves the desktop gives the tier up. Anything but
351
+ * a window slotted here warns and changes nothing.
352
+ */
353
+ get fullScreenWindow(): HTMLElement | null;
354
+ set fullScreenWindow(win: HTMLElement | null);
327
355
  /**
328
356
  * The z/active half of a raise, shared by every path. A hidden window
329
357
  * takes its place in the stack and nothing else: it activates when it is
330
- * shown and raised.
358
+ * shown and raised. The full-screen window stays on its tier, and the
359
+ * raise moves the place it goes back to.
331
360
  */
332
361
  private _restack;
333
362
  /**
@@ -466,7 +495,8 @@ export declare class VfDesktop extends VfDesktop_base {
466
495
  * node containing the focused element drops focus to `<body>`, so it is
467
496
  * restored afterwards — behind `_restoringFocus`, because the restore
468
497
  * re-fires focusin (see {@link _onFocusIn}) on an element that may sit in a
469
- * background window.
498
+ * background window. The full-screen window is ordered by the place it
499
+ * goes back to, so taking and leaving the tier move no node.
470
500
  * Reached only through {@link _requestDomSync}'s task — after a pointer
471
501
  * gesture or a programmatic raise, never from a focus-driven one (see
472
502
  * {@link _raise} for why).
@@ -14,9 +14,9 @@ import { SCREEN_CORNER as C, steppedCornerClip as w } from "../pixel-frame.js";
14
14
  import { LitElement as T, css as E, html as D, unsafeCSS as O } from "lit";
15
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 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 = (e) => e.composedPath().some((e) => e instanceof Element && e.classList.contains("vf-title-bar")), U = class extends s(T) {
17
+ var M = 1e6, N = 2 * M, P = 2000001, F = 3e6, I = 512, L = 342, R = "gray-50", z = v(g[R], "#000000", "#ffffff"), B = u(z.width, z.height, d(z.rects)), V = f(z.width), H = (e) => Number(e.style.zIndex) || 0, U = (e) => e.composedPath().some((e) => e instanceof Element && e.classList.contains("vf-title-bar")), W = class extends s(T) {
18
18
  constructor(...e) {
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, {
19
+ super(...e), this.width = I, this.height = L, this.bezel = 0, this.pattern = R, this.scale = new n(this), this.gridSnap = new x(this), this._token = "", this._desktopPattern = g[R], this.#e = !1, this.patternFill = new y(this, {
20
20
  getBox: () => this.screen,
21
21
  getPattern: () => this._token ? null : this._desktopPattern
22
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, () => [[
@@ -29,10 +29,10 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
29
29
  "pointercancel",
30
30
  this._onGestureEnd,
31
31
  !0
32
- ]]), this._onPointerDown = (e) => {
32
+ ]]), this.#n = null, this.#r = "", this._onPointerDown = (e) => {
33
33
  this._pointerGesture || (this._pointerGesture = !0, this._gestureEnd.attach());
34
34
  let t = this._windowFromEvent(e);
35
- t && e.metaKey && H(e) || t && this._raise(t);
35
+ t && e.metaKey && U(e) || t && this._raise(t);
36
36
  }, this._onGestureEnd = () => {
37
37
  this._gestureEnd.detach(), this._pointerGesture = !1, this._requestDomSync();
38
38
  }, this._onDragSurfaceRequest = (e) => {
@@ -119,7 +119,7 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
119
119
  position: absolute;
120
120
  inset: 0;
121
121
  z-index: -1;
122
- --_vf-tile-image: var(--vf-desktop-pattern, ${O(z)});
122
+ --_vf-tile-image: var(--vf-desktop-pattern, ${O(B)});
123
123
  /* Forced colors: hidden with the pattern, same posture. */
124
124
  @media (forced-colors: active) {
125
125
  display: none;
@@ -208,7 +208,7 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
208
208
  ];
209
209
  }
210
210
  get workArea() {
211
- let e = this.width ?? F, t = this.height ?? I, n = Math.min(t, this._menuBarFloor());
211
+ let e = this.width ?? I, t = this.height ?? L, n = Math.min(t, this._menuBarFloor());
212
212
  return {
213
213
  left: 0,
214
214
  top: n,
@@ -252,14 +252,32 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
252
252
  return this._activeWindow;
253
253
  }
254
254
  get stackingOrder() {
255
- return [...this._windows].sort((e, t) => V(e) - V(t));
255
+ return [...this._windows].sort((e, t) => H(e) - H(t));
256
256
  }
257
257
  clearActive() {
258
258
  this._deactivated = !0, this._setActive(null);
259
259
  }
260
+ get fullScreenWindow() {
261
+ return this.#n;
262
+ }
263
+ set fullScreenWindow(e) {
264
+ if (e !== this.#n) {
265
+ if (e && !this._windows.includes(e)) {
266
+ console.warn("vf-desktop: fullScreenWindow takes a window slotted in this desktop, or null.", e);
267
+ return;
268
+ }
269
+ this.#i(), e && (this.#n = e, this.#r = e.style.zIndex, e.style.zIndex = String(F));
270
+ }
271
+ }
272
+ #n;
273
+ #r;
274
+ #i() {
275
+ let e = this.#n;
276
+ e && (this.#n = null, e.style.zIndex = this.#r);
277
+ }
260
278
  _restack(e) {
261
- let t = this._isUtility(e);
262
- e.style.zIndex = String(++this._zCounter + (t ? M : 0)), !t && !e.hidden && this._setActive(e);
279
+ let t = this._isUtility(e), n = String(++this._zCounter + (t ? M : 0));
280
+ e === this.#n ? this.#r = n : e.style.zIndex = n, !t && !e.hidden && this._setActive(e);
263
281
  }
264
282
  _requestDomSync() {
265
283
  this._pointerGesture || this._domSyncTimer || (this._domSyncTimer = window.setTimeout(() => {
@@ -286,7 +304,7 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
286
304
  }
287
305
  _onSlotChange() {
288
306
  let e = this._windows;
289
- this._observeWindows();
307
+ this.#n && !e.includes(this.#n) && this.#i(), this._observeWindows();
290
308
  let t = null;
291
309
  for (let n of e) if (!n.style.zIndex) {
292
310
  let e = this._isUtility(n);
@@ -324,7 +342,7 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
324
342
  _topmost(e) {
325
343
  let t = null, n = -Infinity;
326
344
  for (let r of e) {
327
- let e = V(r);
345
+ let e = H(r);
328
346
  e >= n && (n = e, t = r);
329
347
  }
330
348
  return t;
@@ -338,9 +356,9 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
338
356
  if (!this.isConnected) return;
339
357
  let e = this._windows;
340
358
  if (e.length < 2) return;
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;
343
- r && n instanceof HTMLElement && n.isConnected && this._deepActiveElement() !== n && (this._restoringFocus = !0, n.focus({ preventScroll: !0 }), this._restoringFocus = !1);
359
+ let t = (e) => e === this.#n ? Number(this.#r) || 0 : H(e), n = [...e].sort((e, n) => t(e) - t(n)), r = this._deepActiveElement(), i = !1, a = null;
360
+ for (let e of n) a && a.compareDocumentPosition(e) & Node.DOCUMENT_POSITION_PRECEDING && (this._move(e, a.nextSibling), i = !0), a = e;
361
+ i && r instanceof HTMLElement && r.isConnected && this._deepActiveElement() !== r && (this._restoringFocus = !0, r.focus({ preventScroll: !0 }), this._restoringFocus = !1);
344
362
  }
345
363
  _move(e, t) {
346
364
  let n = this;
@@ -353,21 +371,21 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
353
371
  willUpdate(e) {
354
372
  if (super.willUpdate(e), this._token = p(this, "--vf-desktop-pattern"), e.has("pattern")) {
355
373
  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];
374
+ 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 ${R}.`)), this._desktopPattern = e ?? g[R];
357
375
  }
358
376
  }
359
377
  updated(e) {
360
378
  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")) {
361
- let e = this.width ?? F, t = this.height ?? I;
379
+ let e = this.width ?? I, t = this.height ?? L;
362
380
  this.style.width = i(e + 2 * this.bezel), this.style.height = i(t + 2 * this.bezel);
363
381
  }
364
382
  }
365
383
  render() {
366
- let e = this.width ?? F, t = this.height ?? I, n = this._token ? D`<div class="vf-tile-grid">
384
+ let e = this.width ?? I, t = this.height ?? L, n = this._token ? D`<div class="vf-tile-grid">
367
385
  ${m({
368
- cols: Math.ceil(e / B),
369
- rows: Math.ceil(t / B),
370
- tile: B
386
+ cols: Math.ceil(e / V),
387
+ rows: Math.ceil(t / V),
388
+ tile: V
371
389
  })}
372
390
  </div>` : null;
373
391
  return D`
@@ -388,9 +406,9 @@ var M = 1e6, N = 2 * M, P = 2000001, F = 512, I = 342, L = "gray-50", R = v(g[L]
388
406
  `;
389
407
  }
390
408
  };
391
- o([k({ type: Number })], U.prototype, "width", void 0), o([k({ type: Number })], U.prototype, "height", void 0), o([k({ type: Number })], U.prototype, "bezel", void 0), o([k({ reflect: !0 })], U.prototype, "pattern", void 0), o([k({
409
+ o([k({ type: Number })], W.prototype, "width", void 0), o([k({ type: Number })], W.prototype, "height", void 0), o([k({ type: Number })], W.prototype, "bezel", void 0), o([k({ reflect: !0 })], W.prototype, "pattern", void 0), o([k({
392
410
  type: Number,
393
411
  attribute: "window-top"
394
- })], U.prototype, "windowTop", void 0), o([j({ selector: "vf-window" })], U.prototype, "_windows", void 0), o([A(".screen")], U.prototype, "screen", void 0), o([A(".drag-surface")], U.prototype, "dragSurface", void 0), U = o([t("vf-desktop")], U);
412
+ })], W.prototype, "windowTop", void 0), o([j({ selector: "vf-window" })], W.prototype, "_windows", void 0), o([A(".screen")], W.prototype, "screen", void 0), o([A(".drag-surface")], W.prototype, "dragSurface", void 0), W = o([t("vf-desktop")], W);
395
413
  //#endregion
396
- export { U as VfDesktop };
414
+ export { W as VfDesktop };
@@ -80,6 +80,12 @@ declare const VfWindow_base: (new (...args: any[]) => import("../size.js").VfSiz
80
80
  * same pen; the drag moves the outline, held where the window can land, and
81
81
  * the window moves there on the release. Escape cancels.
82
82
  *
83
+ * **Frameless.** With `frameless` the window draws no chrome — no title bar
84
+ * or widgets, no frame or shadow, no grow box, no header or status strip —
85
+ * and the body is the whole box: a window that takes the whole screen, say,
86
+ * on `vf-desktop`'s full-screen tier. The chrome is hidden, not torn down, so
87
+ * the switch moves no node and the focus in the body stays where it is.
88
+ *
83
89
  * @slot - Default slot: window body content.
84
90
  * @slot header - Optional header content — a band between the title bar and
85
91
  * the body, the full width of the window (the Finder window's header
@@ -141,6 +147,19 @@ export declare class VfWindow extends VfWindow_base {
141
147
  * float above the document tier and never take the single-active state.
142
148
  */
143
149
  variant?: 'utility';
150
+ /**
151
+ * Draw no chrome: no title bar, so no close or zoom box, no frame or
152
+ * shadow, no grow box, and no header or status strip, whatever their slots
153
+ * hold. The body is the whole box, `pattern` filling it and a placed child
154
+ * measured from its corner; under `scrollbars` the built-in scroll area
155
+ * fills the box, its own frame line on the box's edge. `heading` still
156
+ * names the window. The chrome is hidden rather than left out of the
157
+ * render, so switching this on a connected window moves no node and the
158
+ * focus in the body stays where it is. In a `vf-desktop` the window keeps
159
+ * its tier for activation and `hidden`, and `show()` and `hide()` run
160
+ * their rects from and to its box.
161
+ */
162
+ frameless: boolean;
144
163
  /** Title text shown centered in the title bar. */
145
164
  heading: string;
146
165
  /**
@@ -32,7 +32,7 @@ function Z(e, t, n) {
32
32
  }
33
33
  var Q = 24, $ = class extends j(l(H)) {
34
34
  constructor(...e) {
35
- super(...e), this.heading = "", this.active = !0, this.closable = !1, this.zoomable = !1, this.movable = !1, this.outlineDrag = !1, this.resizable = !1, this._pattern = null, this.#e = !1, this._hasHeader = !1, this._hasStatus = !1, this.scale = new n(this), this.gridSnap = new k(this), this.titleCenter = new re(this), this._dotsPattern = "", this.#t = new p(this, {
35
+ super(...e), this.frameless = !1, this.heading = "", this.active = !0, this.closable = !1, this.zoomable = !1, this.movable = !1, this.outlineDrag = !1, this.resizable = !1, this._pattern = null, this.#e = !1, this._hasHeader = !1, this._hasStatus = !1, this.scale = new n(this), this.gridSnap = new k(this), this.titleCenter = new re(this), this._dotsPattern = "", this.#t = new p(this, {
36
36
  getBox: () => this.renderRoot?.querySelector(".vf-dots"),
37
37
  getArt: () => this.variant === "utility" && !this._dotsPattern ? _ : null,
38
38
  property: "--_vf-dots-tile"
@@ -214,6 +214,33 @@ var Q = 24, $ = class extends j(l(H)) {
214
214
  height: calc(var(--vf-scale, 1) * 3px);
215
215
  }
216
216
 
217
+ /* --- Frameless ------------------------------------------------- */
218
+ /* No chrome: the frame's stroke and shadow go, and the bars and the
219
+ grow box with them, so the body is the whole box. Hidden rather than
220
+ left out of the render, so switching moves no node and the focus in
221
+ the body stays; the title patch stays in the tree to name the window
222
+ (AccName reads a hidden aria-labelledby target, as the utility
223
+ variant's does). The border is the stroke's forced-colors form. */
224
+ :host([frameless]) .vf-frame {
225
+ padding: 0;
226
+ border: 0;
227
+ box-shadow: none;
228
+ }
229
+ :host([frameless]) .vf-title-bar,
230
+ :host([frameless]) .header,
231
+ :host([frameless]) .status,
232
+ :host([frameless]) .grow {
233
+ display: none;
234
+ }
235
+ /* The edge rails' overhang lands the scroll area's frame on the
236
+ window's; with no frame to land on, the area fills the box instead,
237
+ its own frame line on the box's edge. */
238
+ :host([frameless]) .edge-scroll {
239
+ width: 100%;
240
+ height: 100%;
241
+ margin: 0;
242
+ }
243
+
217
244
  /* --- Body ------------------------------------------------------ */
218
245
  /* Clipped at the frame, the way the classic content region was: the
219
246
  window is a fixed box (width and height are both declared), so content
@@ -636,7 +663,7 @@ var Q = 24, $ = class extends j(l(H)) {
636
663
  <vf-scroll-area
637
664
  class="edge-scroll"
638
665
  axis=${this.scrollbars}
639
- ?corner=${this.resizable && !this._hasStatus}
666
+ ?corner=${this.resizable && !this._hasStatus && !this.frameless}
640
667
  label=${this.heading || G}
641
668
  pattern=${this._pattern ? this.pattern : G}
642
669
  exportparts="viewport"
@@ -663,7 +690,10 @@ var Q = 24, $ = class extends j(l(H)) {
663
690
  `;
664
691
  }
665
692
  };
666
- s([K({ reflect: !0 })], $.prototype, "variant", void 0), s([K()], $.prototype, "heading", void 0), s([K({
693
+ s([K({ reflect: !0 })], $.prototype, "variant", void 0), s([K({
694
+ type: Boolean,
695
+ reflect: !0
696
+ })], $.prototype, "frameless", void 0), s([K()], $.prototype, "heading", void 0), s([K({
667
697
  type: Boolean,
668
698
  reflect: !0
669
699
  })], $.prototype, "active", void 0), s([K({
@@ -33,9 +33,9 @@ export declare class VfTextControlBase extends VfShadowRoleControl {
33
33
  /**
34
34
  * Opens with the whole text selected, so typing replaces it. Implies
35
35
  * `autofocus`: the first control carrying either takes the opening focus of
36
- * its `vf-dialog`, or of a window the shell's window manager opens. A dialog
37
- * selects the text on every open, a window on its first open only. A click
38
- * still places the caret.
36
+ * its `vf-dialog`, or of a window system-online-sdk's window manager opens.
37
+ * A dialog selects the text on every open, a window on its first open only.
38
+ * A click still places the caret.
39
39
  */
40
40
  autoselect: boolean;
41
41
  /** Form field name used when submitting the associated form. */