vintage-frames 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +16 -0
  2. package/custom-elements.json +184 -20
  3. package/dist/components/vf-checkbox.d.ts +6 -5
  4. package/dist/components/vf-checkbox.js +41 -37
  5. package/dist/components/vf-container.d.ts +14 -14
  6. package/dist/components/vf-container.js +58 -28
  7. package/dist/components/vf-desktop.d.ts +114 -12
  8. package/dist/components/vf-desktop.js +119 -58
  9. package/dist/components/vf-fieldset.js +30 -22
  10. package/dist/components/vf-icon-field.d.ts +1 -1
  11. package/dist/components/vf-icon.js +111 -104
  12. package/dist/components/vf-list.js +30 -29
  13. package/dist/components/vf-menu-bar.d.ts +5 -0
  14. package/dist/components/vf-menu-bar.js +67 -43
  15. package/dist/components/vf-menu.js +24 -22
  16. package/dist/components/vf-number-field.js +32 -30
  17. package/dist/components/vf-progress-bar.js +28 -29
  18. package/dist/components/vf-radio.js +3 -4
  19. package/dist/components/vf-scroll-area.js +27 -26
  20. package/dist/components/vf-select.js +108 -90
  21. package/dist/components/vf-separator.d.ts +5 -5
  22. package/dist/components/vf-separator.js +36 -10
  23. package/dist/components/vf-swatch.js +47 -45
  24. package/dist/components/vf-text-area.js +37 -35
  25. package/dist/components/vf-text-field.js +20 -18
  26. package/dist/components/vf-window.d.ts +13 -0
  27. package/dist/components/vf-window.js +101 -72
  28. package/dist/index.d.ts +12 -1
  29. package/dist/index.js +61 -59
  30. package/dist/pattern-fill.d.ts +11 -8
  31. package/dist/pattern-fill.js +2 -4
  32. package/dist/position.d.ts +25 -7
  33. package/dist/position.js +6 -3
  34. package/dist/shell/alert.d.ts +32 -0
  35. package/dist/shell/alert.js +44 -0
  36. package/dist/shell/catalog.d.ts +168 -0
  37. package/dist/shell/catalog.js +278 -0
  38. package/dist/shell/clock.d.ts +16 -0
  39. package/dist/shell/clock.js +36 -0
  40. package/dist/shell/filing.d.ts +39 -0
  41. package/dist/shell/filing.js +68 -0
  42. package/dist/shell/finder.d.ts +116 -0
  43. package/dist/shell/finder.js +564 -0
  44. package/dist/shell/geometry.d.ts +196 -0
  45. package/dist/shell/geometry.js +241 -0
  46. package/dist/shell/index.d.ts +29 -0
  47. package/dist/shell/index.js +11 -0
  48. package/dist/shell/shell.d.ts +150 -0
  49. package/dist/shell/shell.js +213 -0
  50. package/dist/shell/state.d.ts +88 -0
  51. package/dist/shell/state.js +103 -0
  52. package/dist/shell/storage.d.ts +14 -0
  53. package/dist/shell/storage.js +41 -0
  54. package/dist/shell/windows.d.ts +215 -0
  55. package/dist/shell/windows.js +343 -0
  56. package/dist/styles/base.d.ts +3 -1
  57. package/dist/styles/recipes/field.d.ts +10 -6
  58. package/dist/styles/recipes/field.js +8 -7
  59. package/dist/styles/recipes/focus.d.ts +7 -3
  60. package/dist/styles/recipes/rule.d.ts +11 -8
  61. package/dist/styles/recipes/rule.js +31 -13
  62. package/dist/styles/recipes/scroll-rail.d.ts +7 -6
  63. package/dist/styles/recipes/scroll-rail.js +18 -18
  64. package/dist/styles/recipes/shadow.d.ts +10 -6
  65. package/dist/styles/recipes/shadow.js +4 -2
  66. package/dist/styles/recipes/stroke.d.ts +85 -0
  67. package/dist/styles/recipes/stroke.js +53 -0
  68. package/dist/styles/recipes/surface.d.ts +8 -4
  69. package/dist/styles/recipes/surface.js +23 -17
  70. package/dist/styles/recipes/title-bar.d.ts +7 -0
  71. package/dist/styles/recipes/title-bar.js +25 -22
  72. package/dist/styles/recipes/toggle.js +3 -3
  73. package/dist/window-chrome.d.ts +43 -0
  74. package/dist/window-chrome.js +13 -0
  75. package/dist/zoom.d.ts +9 -9
  76. package/docs/SPEC.md +34 -32
  77. package/editor/vscode.html-custom-data.json +12 -7
  78. package/editor/web-types.json +50 -14
  79. package/package.json +10 -2
@@ -4,33 +4,34 @@ import r from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js
4
4
  import { VfPositioned as i } from "../position.js";
5
5
  import { vfDisplay as a } from "../styles/recipes/display-face.js";
6
6
  import { vfBase as o } from "../styles/recipes/host.js";
7
- import { vfFocusUnderline as s } from "../styles/recipes/focus.js";
8
- import { vfToggle as c } from "../styles/recipes/toggle.js";
9
- import { CHECKBOX_X as l, glyphSvg as u } from "../glyphs.js";
10
- import { VfFormControl as d } from "../form-control.js";
11
- import { VfToggleControl as f } from "../toggle-control.js";
12
- import { css as p, html as m } from "lit";
13
- import { property as h, state as g } from "lit/decorators.js";
14
- import { classMap as _ } from "lit/directives/class-map.js";
7
+ import { vfStrokeDecls as s, vfStrokeInset as c, vfStrokeShadow as l } from "../styles/recipes/stroke.js";
8
+ import { vfFocusUnderline as u } from "../styles/recipes/focus.js";
9
+ import { vfToggle as d } from "../styles/recipes/toggle.js";
10
+ import { CHECKBOX_X as f, glyphSvg as p } from "../glyphs.js";
11
+ import { VfFormControl as m } from "../form-control.js";
12
+ import { VfToggleControl as h } from "../toggle-control.js";
13
+ import { css as g, html as _ } from "lit";
14
+ import { property as v, state as y } from "lit/decorators.js";
15
+ import { classMap as b } from "lit/directives/class-map.js";
15
16
  //#region src/components/vf-checkbox.ts
16
- var v = class extends i(f(d)) {
17
+ var x = class extends i(h(m)) {
17
18
  static {
18
19
  this.styles = [
19
20
  o,
20
21
  a,
21
- c,
22
- p`
22
+ d,
23
+ g`
23
24
  /* Keyboard focus underlines the box itself — not the label, and not a
24
- ring around either (see vfFocusUnderline). Both adjustments below are
25
- the 1px border: an absolutely positioned pseudo sizes to the PADDING
26
- box, which the border sits outside of. So the rule grows 1px each side
27
- to span the whole well, and its offset counts the border before the
28
- blank row and the rule itself: −(1 + 1 + 1). */
25
+ ring around either (see vfFocusUnderline). An absolutely positioned
26
+ pseudo sizes to the padding box, which runs under the box's stroke,
27
+ so the rule spans the whole well and −2 puts it one blank row under
28
+ it. Under forced colors the stroke is a border and the padding box
29
+ sits inside it, so the insets grow by it there. */
29
30
  :host(:focus-visible) .box::after {
30
- --vf-focus-underline-offset: -3px;
31
- ${s}
32
- left: calc(var(--vf-scale, 1) * -1px);
33
- right: calc(var(--vf-scale, 1) * -1px);
31
+ ${u}
32
+ bottom: ${c(-3)};
33
+ left: ${c(-1)};
34
+ right: ${c(-1)};
34
35
  }
35
36
  .box {
36
37
  position: relative;
@@ -38,28 +39,31 @@ var v = class extends i(f(d)) {
38
39
  display: flex;
39
40
  align-items: center;
40
41
  justify-content: center;
41
- width: calc(var(--vf-scale, 1) * 13px);
42
- height: calc(var(--vf-scale, 1) * 13px);
42
+ width: calc(var(--vf-scale, 1) * 12px);
43
+ height: calc(var(--vf-scale, 1) * 12px);
43
44
  background: var(--vf-white, #fff);
44
- border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
45
45
  color: var(--vf-black, #000);
46
+ ${s()}
46
47
  }
47
- /* Pressed: border thickens to 2px (classic press feedback). */
48
+ /* Pressed: the line thickens to 2px (classic press feedback), inward,
49
+ over the padding the 1px stroke leaves the glyph. */
48
50
  :host(:active) .box:not(.dim) {
49
- box-shadow: inset 0 0 0 calc(var(--vf-scale, 1) * 1px) var(--vf-black, #000);
51
+ box-shadow: ${l(2)};
50
52
  }
51
53
  /* Forced colors never paints box-shadow, so the press feedback above
52
54
  goes silent. The same thickening as a real border-width change: with
53
- box-sizing: border-box the 13×13 box holds and the extra pixel grows
54
- inward, exactly where the inset shadow painted. */
55
+ box-sizing: border-box the 12×12 box holds and the extra pixel grows
56
+ inward, exactly where the inset shadow paints. */
55
57
  @media (forced-colors: active) {
56
58
  :host(:active) .box:not(.dim) {
57
59
  border-width: calc(var(--vf-scale, 1) * 2px);
58
60
  }
59
61
  }
60
- /* Native 12×12 sprite — centered in the 13×13 box; the glyph's own 1px
61
- transparent margin lets it overhang onto the border harmlessly. Scales
62
- with the box; crispEdges keeps it whole-device-pixel at any dpr. */
62
+ /* Native 12×12 sprite, the box's own size: centered on the 10×10
63
+ interior it covers the box exactly, its 1px transparent margin over
64
+ the frame, so the ✕ fills the interior corner to corner on whole
65
+ system px — the sprite's own registration. Scales with the box;
66
+ crispEdges keeps it whole-device-pixel at any dpr. */
63
67
  .check {
64
68
  flex: none;
65
69
  width: calc(var(--vf-scale, 1) * 12px);
@@ -93,9 +97,9 @@ var v = class extends i(f(d)) {
93
97
  }
94
98
  render() {
95
99
  let e = this.isDisabled;
96
- return m`
100
+ return _`
97
101
  <span
98
- class=${_({
102
+ class=${b({
99
103
  box: !0,
100
104
  dim: e,
101
105
  "vf-snap": !0
@@ -103,10 +107,10 @@ var v = class extends i(f(d)) {
103
107
  part="box"
104
108
  aria-hidden="true"
105
109
  >
106
- ${u(l, "check")}
110
+ ${p(f, "check")}
107
111
  </span>
108
112
  <span
109
- class=${_({
113
+ class=${b({
110
114
  label: !0,
111
115
  dim: e,
112
116
  empty: !this._hasLabel,
@@ -135,9 +139,9 @@ var v = class extends i(f(d)) {
135
139
  this.checked = !this.checked, this.focus(), e(this, "vf-change", { checked: this.checked }), t(this, "input"), t(this, "change");
136
140
  }
137
141
  };
138
- r([h({
142
+ r([v({
139
143
  type: Boolean,
140
144
  reflect: !0
141
- })], v.prototype, "checked", void 0), r([h({ reflect: !0 })], v.prototype, "name", void 0), r([h()], v.prototype, "value", void 0), r([g()], v.prototype, "_hasLabel", void 0), v = r([n("vf-checkbox")], v);
145
+ })], x.prototype, "checked", void 0), r([v({ reflect: !0 })], x.prototype, "name", void 0), r([v()], x.prototype, "value", void 0), r([y()], x.prototype, "_hasLabel", void 0), x = r([n("vf-checkbox")], x);
142
146
  //#endregion
143
- export { v as VfCheckbox };
147
+ export { x as VfCheckbox };
@@ -43,15 +43,16 @@ declare const VfContainer_base: (new (...args: any[]) => import("../size.js").Vf
43
43
  *
44
44
  * **It paints nothing and means nothing** — unless `pattern` or `rule` say
45
45
  * what to paint. No role, keyboard behavior or selection; what it holds
46
- * decides what it is.
46
+ * decides what it is. A page that gives it a role and a `tabindex` — a
47
+ * pattern chooser's cells as radios — gets the kit's keyboard focus mark
48
+ * rather than the browser's ring: the dashed rule below the box.
47
49
  *
48
50
  * **`rule` draws the 1px rule on the edges it names** — `rule="bottom"` is
49
51
  * the menu bar's anatomy (the box's rows over one row of ink), `rule="top"`
50
- * a status strip's, all four a framed box. The rule is the box's own border
51
- * ({@link vfRule}), inside the declared size, so a 24px `rule="bottom"`
52
- * strip is 23 rows of box over the line; content, `fill-width` children and
53
- * placed children begin inside it, as a rectangle's interior begins inside
54
- * FrameRect's line.
52
+ * a status strip's, all four a framed box. The rule is drawn inside the
53
+ * declared size ({@link vfRule}), so a 24px `rule="bottom"` strip is 23 rows
54
+ * of box over the line; content, `fill-width` children and placed children
55
+ * begin inside it, as a rectangle's interior begins inside FrameRect's line.
55
56
  *
56
57
  * **`pattern` fills the box with a 1-bit pattern**: one of the 38 standard
57
58
  * MacPaint patterns by name (`pattern="bricks"`, `pattern="gray-50"` —
@@ -66,10 +67,10 @@ declare const VfContainer_base: (new (...args: any[]) => import("../size.js").Vf
66
67
  * **It holds its box on the device-pixel grid** — with a `GridSnapController`.
67
68
  * A container's box is itself the consumer's coordinate system, including for
68
69
  * non-`vf` content that cannot correct itself, so the box is the thing to
69
- * hold on the grid. The shadow box below owns the `position: relative` anchor
70
- * and the `vf-snap` class together, so the correction
71
- * moves the whole coordinate system — everything placed against it rides
72
- * along instead of being re-corrected child by child. (`vf-stack` shipped
70
+ * hold on the grid. The correction lands on the shadow box below, and the
71
+ * coordinate system sits inside it, so the correction moves the whole
72
+ * coordinate system — everything placed against it rides along instead of
73
+ * being re-corrected child by child. (`vf-stack` shipped
73
74
  * without a controller on the theory that slotted `vf-*` children correct
74
75
  * their own origins; this component is where that theory's gap — consumer
75
76
  * content — became visible, and the stack has since adopted the same
@@ -106,10 +107,9 @@ export declare class VfContainer extends VfContainer_base {
106
107
  private _pattern;
107
108
  /**
108
109
  * The 1px rule on the box's edges: edge names separated by spaces —
109
- * `"bottom"`, `"top bottom"`, up to all four in any order. Drawn as the
110
- * box's own border inside the declared size, in `--vf-black`, scaled with
111
- * the display like every kit frame's border; content and placed children
112
- * begin inside it.
110
+ * `"bottom"`, `"top bottom"`, up to all four in any order. Drawn inside
111
+ * the declared size, in `--vf-black`, scaled with the display like every
112
+ * kit frame; content and placed children begin inside it.
113
113
  * Unset, no rule; a value naming anything but an edge draws none and
114
114
  * warns once.
115
115
  */
@@ -4,16 +4,18 @@ import n from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js
4
4
  import { VfPositioned as r } from "../position.js";
5
5
  import { vfBase as i } from "../styles/recipes/host.js";
6
6
  import { parsePattern as a } from "../patterns.js";
7
- import { parseRule as o, ruleClasses as s, vfRule as c } from "../styles/recipes/rule.js";
8
- import { PatternFillController as l, vfPatternFill as u } from "../pattern-fill.js";
9
- import { GridSnapController as d } from "../grid-snap.js";
10
- import { VfSized as f } from "../size.js";
11
- import { LitElement as p, css as m, html as h } from "lit";
12
- import { property as g, query as _ } from "lit/decorators.js";
7
+ import { vfStrokeInset as o } from "../styles/recipes/stroke.js";
8
+ import { parseRule as s, ruleClasses as c, vfRule as l } from "../styles/recipes/rule.js";
9
+ import { vfFocusUnderline as u } from "../styles/recipes/focus.js";
10
+ import { PatternFillController as d, vfPatternFill as f } from "../pattern-fill.js";
11
+ import { GridSnapController as p } from "../grid-snap.js";
12
+ import { VfSized as m } from "../size.js";
13
+ import { LitElement as h, css as g, html as _ } from "lit";
14
+ import { property as v, query as y } from "lit/decorators.js";
13
15
  //#region src/components/vf-container.ts
14
- var v = class extends f(r(p)) {
16
+ var b = class extends m(r(h)) {
15
17
  constructor(...e) {
16
- super(...e), this._pattern = null, this.#e = !1, this._rule = [], this.#t = !1, this.scale = new t(this), this.gridSnap = new d(this), this.patternFill = new l(this, {
18
+ super(...e), this._pattern = null, this.#e = !1, this._rule = [], this.#t = !1, this.scale = new t(this), this.gridSnap = new p(this), this.patternFill = new d(this, {
17
19
  getBox: () => this.box,
18
20
  getPattern: () => this._pattern
19
21
  });
@@ -21,9 +23,9 @@ var v = class extends f(r(p)) {
21
23
  static {
22
24
  this.styles = [
23
25
  i,
24
- u,
25
- c,
26
- m`
26
+ f,
27
+ l,
28
+ g`
27
29
  :host {
28
30
  display: block;
29
31
  /* Shrink-wrap an undeclared axis rather than claim the parent's
@@ -44,24 +46,52 @@ var v = class extends f(r(p)) {
44
46
  text-align: inherit;
45
47
  }
46
48
 
47
- /* The coordinate system, as one shadow box coinciding with the host box.
48
- vf-snap (vfBase) gives it position: relative plus the controller's
49
- --vf-snap-dx/-dy offset — so it is BOTH the positioning anchor for
50
- children placed with top/left (src/position.ts) AND the element the
51
- grid-snap correction lands on. One element owning both is the point:
52
- corrected, it takes every placed child with it, kit or not. */
49
+ /* The painted box, coinciding with the host box: the pattern, the rule
50
+ and the grid-snap correction (vf-snap, vfBase — position: relative
51
+ plus the controller's --vf-snap-dx/-dy offset). The coordinate system
52
+ rides inside it (the slot, below), so the correction takes every
53
+ placed child with it, kit or not. */
53
54
  .box {
54
- /* flow-root: contain slotted margins, so the box's top edge — the
55
- origin placed children measure from — stays glued to the host's
56
- corner instead of being pushed down by a first child's margin
57
- collapsing through. */
58
- display: flow-root;
59
55
  /* Coincide with a declared height (100% of a definite host height;
60
56
  against an undeclared one it computes to auto and wraps content),
61
- so slotted percentage fills resolve against the stated box. */
57
+ so the slot inside can take the stated box. */
58
+ height: 100%;
59
+ /* The pattern starts inside the rule, as it did when the rule was a
60
+ border. */
61
+ background-origin: content-box;
62
+ }
63
+ /* The coordinate system: the slot, as a box inside the rule — the
64
+ rule's row is the painted box's padding (vfRule) — so content,
65
+ percentage fills and children placed with top/left (src/position.ts)
66
+ all begin inside it. */
67
+ .box > slot {
68
+ position: relative;
69
+ /* flow-root: contain slotted margins, so the top edge — the origin
70
+ placed children measure from — stays glued to the box's corner
71
+ instead of being pushed down by a first child's margin collapsing
72
+ through. */
73
+ display: flow-root;
74
+ /* The stated box less its rules, so slotted percentage fills resolve
75
+ against it; auto against an undeclared height. */
62
76
  height: 100%;
63
77
  }
64
78
 
79
+ /* A box the page makes focusable — a pattern chooser's cells as
80
+ radios, say — wears the kit's focus mark, not the browser's ring: the
81
+ dashed rule below the box, one blank row under it, since a box like
82
+ that is nothing but fill (vf-swatch's placement). The rule spans the
83
+ box; under forced colors a ruled box's stroke is a border outside the
84
+ padding box the rule measures from, so the insets grow by it there. */
85
+ :host(:focus-visible) {
86
+ outline: none;
87
+ }
88
+ :host(:focus-visible) .box::after {
89
+ ${u}
90
+ bottom: ${o(-3)};
91
+ left: ${o(-1)};
92
+ right: ${o(-1)};
93
+ }
94
+
65
95
  /* The same two words a child uses, read about the host itself — for the
66
96
  parents that can give this box a size: a window body, a filled stack
67
97
  column, a grid cell. A percentage is the one fill a page can always
@@ -93,19 +123,19 @@ var v = class extends f(r(p)) {
93
123
  #t;
94
124
  willUpdate(e) {
95
125
  if (super.willUpdate(e), e.has("pattern") && (this._pattern = a(this.pattern), this._pattern === null && this.pattern?.trim() && !this.#e && (this.#e = !0, console.warn(`vf-container: unknown pattern "${this.pattern}" — a library name (docs/PATTERNS.md) or sixteen hex digits. Painting nothing.`))), e.has("rule")) {
96
- let e = o(this.rule);
126
+ let e = s(this.rule);
97
127
  this._rule = e ?? [], e === null && !this.#t && (this.#t = !0, console.warn(`vf-container: unknown rule "${this.rule}" — edge names (top, right, bottom, left) separated by spaces. Drawing none.`));
98
128
  }
99
129
  }
100
130
  render() {
101
- let e = s(this._rule);
102
- return h`<div
131
+ let e = c(this._rule);
132
+ return _`<div
103
133
  class="vf-snap box vf-pattern-fill${this._pattern ? " vf-patterned" : ""}${e ? ` ${e}` : ""}"
104
134
  >
105
135
  <slot></slot>
106
136
  </div>`;
107
137
  }
108
138
  };
109
- n([g()], v.prototype, "pattern", void 0), n([g()], v.prototype, "rule", void 0), n([_(".box")], v.prototype, "box", void 0), v = n([e("vf-container")], v);
139
+ n([v()], b.prototype, "pattern", void 0), n([v()], b.prototype, "rule", void 0), n([y(".box")], b.prototype, "box", void 0), b = n([e("vf-container")], b);
110
140
  //#endregion
111
- export { v as VfContainer };
141
+ export { b as VfContainer };
@@ -36,6 +36,25 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
36
36
  * reads the current holder, and every change of holder — including to and
37
37
  * from none — fires `vf-activate`.
38
38
  *
39
+ * **Hidden windows.** A window with `hidden` — closed by a page that hides
40
+ * its windows rather than removing them, through `vf-window.hide()` or the
41
+ * attribute itself — never holds the active state. One slotted hidden waits
42
+ * to be shown; `bringToFront()` on one gives it its place in the stack and
43
+ * activates nothing; the holder hiding hands the state to the topmost shown
44
+ * document window, or to none. A window shown into a tier where none is
45
+ * active, unless the tier was deliberately deactivated, takes it.
46
+ * {@link stackingOrder} lists the windows as they stand, bottom-most first.
47
+ *
48
+ * **The work area.** A slotted `vf-menu-bar` along the top takes its band
49
+ * off the screen: {@link workArea} is what is left, and the gestures on the
50
+ * screen stay in it — a window dragged up stops with its title bar under the
51
+ * bar, where it can still be grabbed, and an icon dropped, nudged or walked
52
+ * on the desktop lands below the bar. `window-top` deepens the area for
53
+ * windows alone ({@link windowArea}), for a page with a strip of its own
54
+ * under the bar. A gesture asks for the box it is clamped into with
55
+ * `vf-placement-bounds-request` (bubbles, non-composed), the drag surface's
56
+ * handshake, and the desktop answers for the hosts placed on its screen.
57
+ *
39
58
  * The desktop is a raster with an explicit size, always: **`width` and
40
59
  * `height`**, in system px, the way a WIND resource declared a window's —
41
60
  * the host box renders at the declared screen plus `2 × bezel` per axis, a
@@ -88,8 +107,8 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
88
107
  * @fires vf-activate - The active document-tier window changed. Detail
89
108
  * `{ window: HTMLElement | null }` — the new holder, or `null` when the
90
109
  * document tier deactivated (a {@link clearActive} call, or the active
91
- * window leaving the DOM with none behind it). Fired once per change of
92
- * holder, never for a re-assertion of the same one.
110
+ * window leaving the DOM or hiding with no shown window behind it). Fired
111
+ * once per change of holder, never for a re-assertion of the same one.
93
112
  * @csspart desktop - The patterned screen surface — the whole-system-px
94
113
  * raster (inset by `bezel` when one is set).
95
114
  * @cssprop [--vf-desktop=#808080] - base color under the desktop pattern —
@@ -139,6 +158,38 @@ export declare class VfDesktop extends VfDesktop_base {
139
158
  * keeps the dither.
140
159
  */
141
160
  pattern: string | null | undefined;
161
+ /**
162
+ * The least `top` a window may take, in system px from the screen's top —
163
+ * for a page that keeps a strip of its own under the menu bar, over the
164
+ * windows. A window dragged on this desktop stops there, and
165
+ * {@link windowArea} starts there; icons still stop at the menu bar. Below
166
+ * the bar's bottom it changes nothing. Unset, windows stop at the bar.
167
+ */
168
+ windowTop?: number | null;
169
+ /**
170
+ * The screen less a slotted `vf-menu-bar` along its top edge, in system
171
+ * px from the screen's corner (the bezel excluded, as for
172
+ * {@link placementAt}): `{ left, top, width, height }`. The desktop clamps
173
+ * the gestures on its screen into it — an icon dropped, nudged or walked
174
+ * on the desktop lands below the menu bar, where it can be grabbed again.
175
+ * Without a bar it is the whole screen. Measured at the call.
176
+ */
177
+ get workArea(): {
178
+ left: number;
179
+ top: number;
180
+ width: number;
181
+ height: number;
182
+ };
183
+ /**
184
+ * {@link workArea}, deepened to {@link windowTop} where that is lower: the
185
+ * area windows are dragged in. A window's title bar never goes above it.
186
+ */
187
+ get windowArea(): {
188
+ left: number;
189
+ top: number;
190
+ width: number;
191
+ height: number;
192
+ };
142
193
  /**
143
194
  * Size the screen to the largest whole-system-px raster whose host box —
144
195
  * bezel included — fits a CSS-px bound, and return what was set. The
@@ -223,10 +274,13 @@ export declare class VfDesktop extends VfDesktop_base {
223
274
  private readonly _gestureEnd;
224
275
  connectedCallback(): void;
225
276
  disconnectedCallback(): void;
226
- /** Whether a slotted window belongs to the floating (utility) tier. The
227
- * attribute is the source of truth here so a not-yet-upgraded element
228
- * still lands in the right tier (variant reflects, so an upgraded
229
- * property-set window agrees). */
277
+ /** Whether a slotted window belongs to the floating (utility) tier: the
278
+ * `variant` property where the window has one, else the attribute, so a
279
+ * not-yet-upgraded element still lands in the right tier. Not the
280
+ * attribute alone — it reflects in the window's next update, after a
281
+ * window made by script and appended in the same task has been slotted,
282
+ * and that palette would land in the document tier and lose its
283
+ * `active`. */
230
284
  private _isUtility;
231
285
  /**
232
286
  * Bring a slotted window to the front of its tier. A document-tier window
@@ -247,8 +301,17 @@ export declare class VfDesktop extends VfDesktop_base {
247
301
  */
248
302
  bringToFront(win: HTMLElement): void;
249
303
  /** The active document-tier window, or null while the tier is deactivated
250
- * (or has no windows). Utility windows are never the holder. */
304
+ * (or has no shown windows). Utility windows and hidden windows are never
305
+ * the holder. */
251
306
  get activeWindow(): HTMLElement | null;
307
+ /**
308
+ * The slotted windows in stacking order, bottom-most first: the document
309
+ * tier, then the floating tier above it, each in the order its windows
310
+ * were last raised. Hidden windows are included where they stand. This is
311
+ * the order the eye sees; the windows' light-DOM order catches up with it
312
+ * only once a gesture ends, and a raise by keyboard focus moves no node.
313
+ */
314
+ get stackingOrder(): HTMLElement[];
252
315
  /**
253
316
  * Deactivate the whole document tier — clear `active` from every document
254
317
  * window, leaving none the holder. Pages route "the user clicked the
@@ -258,7 +321,11 @@ export declare class VfDesktop extends VfDesktop_base {
258
321
  * slotted.
259
322
  */
260
323
  clearActive(): void;
261
- /** The z/active half of a raise, shared by every path. */
324
+ /**
325
+ * The z/active half of a raise, shared by every path. A hidden window
326
+ * takes its place in the stack and nothing else: it activates when it is
327
+ * shown and raised.
328
+ */
262
329
  private _restack;
263
330
  /**
264
331
  * Schedule the DOM-order sync: one task from now, coalesced, and never
@@ -316,6 +383,19 @@ export declare class VfDesktop extends VfDesktop_base {
316
383
  * detail alone.
317
384
  */
318
385
  private _onDragSurfaceRequest;
386
+ /**
387
+ * A gesture measuring the box it is clamped into (src/position.ts): for a
388
+ * host placed on this screen — a slotted window, an icon in an unplaced
389
+ * field — the screen, bezel excluded, and the work area's top as the
390
+ * floor: {@link windowArea}'s for a window, {@link workArea}'s for
391
+ * anything else. The floor is rounded up to the host's placement lattice,
392
+ * so a snapped landing never rounds above it. A host placed in a box of its
393
+ * own (a window body, a placed field) is that box's; an outer desktop
394
+ * leaves a filled detail alone.
395
+ */
396
+ private _onBoundsRequest;
397
+ /** The bottom of a slotted, shown menu bar along the screen's top edge, system px; else 0. */
398
+ private _menuBarFloor;
319
399
  /**
320
400
  * Delegated focusin: raise the window keyboard focus entered, so tabbing
321
401
  * into a background window brings it to front (and reveals its close/zoom
@@ -329,6 +409,19 @@ export declare class VfDesktop extends VfDesktop_base {
329
409
  private _windowFromEvent;
330
410
  /** Wire up newly slotted windows: seed z-indices, normalize `active`. */
331
411
  private _onSlotChange;
412
+ /**
413
+ * Resolve who should hold `active` after the window set or a window's
414
+ * visibility changed: a holder still slotted and shown keeps it, a
415
+ * deliberate deactivation is preserved (never promote a survivor over the
416
+ * user's "clicked the Finder"), and only then does the topmost shown
417
+ * window inherit — the active window left the DOM or was hidden, or a
418
+ * window was shown into a tier with none active. Applied even when null,
419
+ * so a stray `active` attribute on slotted markup, or on a hidden window,
420
+ * is normalized in the deactivated state too.
421
+ */
422
+ private _resolveActive;
423
+ /** Watch the `hidden` attribute of every slotted window, and no other. */
424
+ private _observeWindows;
332
425
  /**
333
426
  * Re-assert the single-active-window state after slotted `<vf-window>`
334
427
  * elements upgrade. One-shot: the flag collapses repeat slotchanges into a
@@ -365,15 +458,24 @@ export declare class VfDesktop extends VfDesktop_base {
365
458
  * Minimal-move: windows already in relative order are never touched (the
366
459
  * common case — after one raise, one window moves). Non-window siblings
367
460
  * (a menu bar, page content) keep their positions; only a window that must
368
- * cross the stack moves past them. Moving a node containing the focused
369
- * element drops focus to `<body>`, so it is restored afterwards — behind
370
- * `_restoringFocus`, because the restore re-fires focusin (see
371
- * {@link _onFocusIn}) on an element that may sit in a background window.
461
+ * cross the stack moves past them. `moveBefore()` keeps the focus inside a
462
+ * moved window where the browser has it ({@link _move}); re-inserting a
463
+ * node containing the focused element drops focus to `<body>`, so it is
464
+ * restored afterwards — behind `_restoringFocus`, because the restore
465
+ * re-fires focusin (see {@link _onFocusIn}) on an element that may sit in a
466
+ * background window.
372
467
  * Reached only through {@link _requestDomSync}'s task — after a pointer
373
468
  * gesture or a programmatic raise, never from a focus-driven one (see
374
469
  * {@link _raise} for why).
375
470
  */
376
471
  private _syncDomOrder;
472
+ /**
473
+ * Move a slotted window before `before`: with `Element.moveBefore()` where
474
+ * the browser has it, which keeps the focus inside the window — a rename
475
+ * field, a text field's caret — through the move; else by re-inserting it,
476
+ * and {@link _syncDomOrder} puts the focus back.
477
+ */
478
+ private _move;
377
479
  protected willUpdate(changed: PropertyValues<this>): void;
378
480
  protected updated(changed: Map<PropertyKey, unknown>): void;
379
481
  protected render(): unknown;