vintage-frames 0.5.0 → 0.5.2

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.
@@ -1974,7 +1974,7 @@
1974
1974
  "declarations": [
1975
1975
  {
1976
1976
  "kind": "class",
1977
- "description": "`<vf-container>` — a box that is nothing but its declared size.\n\nThe kit's positioned-placement story (src/position.ts) ends with one line of\nCSS it can't write for you: children placed with `top`/`left` need a\npositioned ancestor, and while every kit container is one — a window body, a\nstack, a fieldset — a region of *your own* needs `position: relative` in a\nstylesheet. This component is that region as an element: declare `width` and\n`height` in whole system px, slot anything into it, place children against\nits origin. A DITL's enclosing rectangle, with nothing drawn in it.\n\n```html\n<vf-container width=\"200\" height=\"120\">\n <vf-icon label=\"System\" width=\"64\" top=\"8\" left=\"12\">…</vf-icon>\n <vf-icon label=\"Finder\" width=\"64\" top=\"8\" left=\"104\">…</vf-icon>\n</vf-container>\n```\n\nThe rectangle is the whole API — `width`/`height` here, plus the `top`/`left`\npair nearly every component takes (VfPositioned), so a container is\nitself placeable: inside a window, a desktop, or another container, at whole\nsystem px that keep its box on the device-pixel grid by construction.\n\n**It is not a `vf-stack`.** The stack is a flexbox with opinions — it\ndistributes children along an axis, compiles `fill-width`/`fill-height` into\nflex, defaults a cross-axis alignment. This box has no layout opinion at\nall: in-flow children get normal flow, placed children get a coordinate\nsystem, and that is the whole API. Reach for it when the stack's opinions\nare the thing in the way — a field of placed icons, a fixed stage for\nabsolutely-positioned art, a consumer's own composition that brings its\nlayout with it.\n\n**The declared size is the layout.** `width`/`height` land on the host as a\nlive `calc(var(--vf-scale, 1) * Npx)` (VfSized), so the box scales\nwith the display and sits on the device-pixel grid by construction. Content\nthat outgrows the box overflows it rather than growing it — the number is\nthe layout, and content that doesn't fit is a number to raise. Leave a\ndimension off and that axis shrink-wraps: `fit-content`, not the parent's\nwidth, because a layout box that silently claimed a size nobody declared\nwould be inventing one (the `vf-stack` rule, held here too).\n\n**It paints nothing and means nothing** — unless `pattern` says what to\npaint. No border, role, keyboard behavior or selection; what it holds\ndecides what it is.\n\n**`pattern` fills the box with a 1-bit pattern**: one of the 38 standard\nMacPaint patterns by name (`pattern=\"bricks\"`, `pattern=\"gray-50\"` —\ndocs/PATTERNS.md has the table), or sixteen hex digits stating a custom\n8×8 pattern row by row, the way a PAT resource did. It is painted as the\nbox's own background — black ink on a `--vf-white` ground, anchored at\nthe box's top-left corner, under the content — by the same whole-surface\nraster mechanism as the desktop dither, so it is 1-bit at every density\nand zoom (src/pattern-fill.ts). A declared `width`/`height` sizes the\nraster exactly; an undeclared axis (`fill-width`, a shrink-wrapped\nheight) is measured. Under forced colors the pattern goes flat Canvas.\n\n**It holds its box on the device-pixel grid** — with a `GridSnapController`.\nA container's box is itself the consumer's coordinate system, including for\nnon-`vf` content that cannot correct itself, so the box is the thing to\nhold on the grid. The shadow box below owns the `position: relative` anchor\nand the `vf-snap` class together, so the correction\nmoves the whole coordinate system — everything placed against it rides\nalong instead of being re-corrected child by child. (`vf-stack` shipped\nwithout a controller on the theory that slotted `vf-*` children correct\ntheir own origins; this component is where that theory's gap — consumer\ncontent — became visible, and the stack has since adopted the same\narrangement.)\n\nLike the stack it is **typographically transparent**: `vfBase`'s chrome\ndress is returned to `inherit` on the host, so wrapping content in a sized\nbox changes nothing about how that content reads.\n\n`fill-width` / `fill-height` work here the way they do everywhere: read\nabout the host (be as big as *its* parent allows), and compiled for slotted\nchildren — `width: 100%` in normal flow, so a child filling the cross of a\ndeclared box needs no stylesheet. A height fill needs a declared `height`\nto resolve against; with none it is inert, not an error.",
1977
+ "description": "`<vf-container>` — a box that is nothing but its declared size.\n\nThe kit's positioned-placement story (src/position.ts) ends with one line of\nCSS it can't write for you: children placed with `top`/`left` need a\npositioned ancestor, and while every kit container is one — a window body, a\nstack, a fieldset — a region of *your own* needs `position: relative` in a\nstylesheet. This component is that region as an element: declare `width` and\n`height` in whole system px, slot anything into it, place children against\nits origin. A DITL's enclosing rectangle, with nothing drawn in it.\n\n```html\n<vf-container width=\"200\" height=\"120\">\n <vf-icon label=\"System\" width=\"64\" top=\"8\" left=\"12\">…</vf-icon>\n <vf-icon label=\"Finder\" width=\"64\" top=\"8\" left=\"104\">…</vf-icon>\n</vf-container>\n```\n\nThe rectangle is the whole API — `width`/`height` here, plus the `top`/`left`\npair nearly every component takes (VfPositioned), so a container is\nitself placeable: inside a window, a desktop, or another container, at whole\nsystem px that keep its box on the device-pixel grid by construction.\n\n**It is not a `vf-stack`.** The stack is a flexbox with opinions — it\ndistributes children along an axis, compiles `fill-width`/`fill-height` into\nflex, defaults a cross-axis alignment. This box has no layout opinion at\nall: in-flow children get normal flow, placed children get a coordinate\nsystem, and that is the whole API. Reach for it when the stack's opinions\nare the thing in the way — a field of placed icons, a fixed stage for\nabsolutely-positioned art, a consumer's own composition that brings its\nlayout with it.\n\n**The declared size is the layout.** `width`/`height` land on the host as a\nlive `calc(var(--vf-scale, 1) * Npx)` (VfSized), so the box scales\nwith the display and sits on the device-pixel grid by construction. Content\nthat outgrows the box overflows it rather than growing it — the number is\nthe layout, and content that doesn't fit is a number to raise. Leave a\ndimension off and that axis shrink-wraps: `fit-content`, not the parent's\nwidth, because a layout box that silently claimed a size nobody declared\nwould be inventing one (the `vf-stack` rule, held here too).\n\n**It paints nothing and means nothing** — unless `pattern` or `rule` say\nwhat to paint. No role, keyboard behavior or selection; what it holds\ndecides what it is.\n\n**`rule` draws the 1px rule on the edges it names** — `rule=\"bottom\"` is\nthe menu bar's anatomy (the box's rows over one row of ink), `rule=\"top\"`\na status strip's, all four a framed box. The rule is the box's own border\n(vfRule), inside the declared size, so a 24px `rule=\"bottom\"`\nstrip is 23 rows of box over the line; content, `fill-width` children and\nplaced children begin inside it, as a rectangle's interior begins inside\nFrameRect's line.\n\n**`pattern` fills the box with a 1-bit pattern**: one of the 38 standard\nMacPaint patterns by name (`pattern=\"bricks\"`, `pattern=\"gray-50\"` —\ndocs/PATTERNS.md has the table), or sixteen hex digits stating a custom\n8×8 pattern row by row, the way a PAT resource did. It is painted as the\nbox's own background — black ink on a `--vf-white` ground, anchored at\nthe box's top-left corner, under the content — by the same whole-surface\nraster mechanism as the desktop dither, so it is 1-bit at every density\nand zoom (src/pattern-fill.ts). A declared `width`/`height` sizes the\nraster exactly; an undeclared axis (`fill-width`, a shrink-wrapped\nheight) is measured. Under forced colors the pattern goes flat Canvas.\n\n**It holds its box on the device-pixel grid** — with a `GridSnapController`.\nA container's box is itself the consumer's coordinate system, including for\nnon-`vf` content that cannot correct itself, so the box is the thing to\nhold on the grid. The shadow box below owns the `position: relative` anchor\nand the `vf-snap` class together, so the correction\nmoves the whole coordinate system — everything placed against it rides\nalong instead of being re-corrected child by child. (`vf-stack` shipped\nwithout a controller on the theory that slotted `vf-*` children correct\ntheir own origins; this component is where that theory's gap — consumer\ncontent — became visible, and the stack has since adopted the same\narrangement.)\n\nLike the stack it is **typographically transparent**: `vfBase`'s chrome\ndress is returned to `inherit` on the host, so wrapping content in a sized\nbox changes nothing about how that content reads.\n\n`fill-width` / `fill-height` work here the way they do everywhere: read\nabout the host (be as big as *its* parent allows), and compiled for slotted\nchildren — `width: 100%` in normal flow, so a child filling the cross of a\ndeclared box needs no stylesheet. A height fill needs a declared `height`\nto resolve against; with none it is inert, not an error.",
1978
1978
  "name": "VfContainer",
1979
1979
  "slots": [
1980
1980
  {
@@ -2012,6 +2012,35 @@
2012
2012
  "default": "false",
2013
2013
  "description": "One warning per element for an unrecognized `pattern`, not per render."
2014
2014
  },
2015
+ {
2016
+ "kind": "field",
2017
+ "name": "rule",
2018
+ "type": {
2019
+ "text": "string | null | undefined"
2020
+ },
2021
+ "description": "The 1px rule on the box's edges: edge names separated by spaces —\n`\"bottom\"`, `\"top bottom\"`, up to all four in any order. Drawn as the\nbox's own border inside the declared size, in `--vf-black`, scaled with\nthe display like every kit frame's border; content and placed children\nbegin inside it.\nUnset, no rule; a value naming anything but an edge draws none and\nwarns once.",
2022
+ "attribute": "rule"
2023
+ },
2024
+ {
2025
+ "kind": "field",
2026
+ "name": "_rule",
2027
+ "type": {
2028
+ "text": "RuleEdge[]"
2029
+ },
2030
+ "privacy": "private",
2031
+ "default": "[]",
2032
+ "description": "`rule`, resolved — the edges drawn; empty draws nothing."
2033
+ },
2034
+ {
2035
+ "kind": "field",
2036
+ "name": "#warnedRule",
2037
+ "privacy": "private",
2038
+ "type": {
2039
+ "text": "boolean"
2040
+ },
2041
+ "default": "false",
2042
+ "description": "One warning per element for an unrecognized `rule`, not per render."
2043
+ },
2015
2044
  {
2016
2045
  "kind": "field",
2017
2046
  "name": "box",
@@ -2108,6 +2137,14 @@
2108
2137
  "description": "A 1-bit fill for the box: a library pattern by name (`bricks`,\n`gray-50`, … — the 38 standard MacPaint patterns, docs/PATTERNS.md) or\nsixteen hex digits stating a custom 8×8 pattern row by row, bit 7 the\nleftmost pixel, 1 = ink (`\"DD 77 DD 77 DD 77 DD 77\"`). Painted in black\non a `--vf-white` ground under the content, anchored at the box's\ntop-left. Unset, the container paints nothing; an unrecognized value\npaints nothing and warns once.",
2109
2138
  "fieldName": "pattern"
2110
2139
  },
2140
+ {
2141
+ "name": "rule",
2142
+ "type": {
2143
+ "text": "string | null | undefined"
2144
+ },
2145
+ "description": "The 1px rule on the box's edges: edge names separated by spaces —\n`\"bottom\"`, `\"top bottom\"`, up to all four in any order. Drawn as the\nbox's own border inside the declared size, in `--vf-black`, scaled with\nthe display like every kit frame's border; content and placed children\nbegin inside it.\nUnset, no rule; a value naming anything but an edge draws none and\nwarns once.",
2146
+ "fieldName": "rule"
2147
+ },
2111
2148
  {
2112
2149
  "name": "width",
2113
2150
  "type": {
@@ -2200,7 +2237,7 @@
2200
2237
  "declarations": [
2201
2238
  {
2202
2239
  "kind": "class",
2203
- "description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, at pointer-gesture\nends), so tabbing walks the stack the way the eye does and Shift+Tab is\nits 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.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its top corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).",
2240
+ "description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, at pointer-gesture\nends), so tabbing walks the stack the way the eye does and Shift+Tab is\nits exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its top corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).",
2204
2241
  "name": "VfDesktop",
2205
2242
  "cssProperties": [
2206
2243
  {
@@ -6906,7 +6943,7 @@
6906
6943
  "declarations": [
6907
6944
  {
6908
6945
  "kind": "class",
6909
- "description": "`<vf-menu>` — a pull-down menu: a bar label plus a dropped panel of\n`<vf-menu-item>` / `<vf-separator>` children.\n\nInside a `<vf-menu-bar>` the bar coordinates open state (only one menu open,\nhover-switching, outside-click/Escape dismissal) and owns the pointer\ngesture, which may travel between its menus. Used standalone, the menu\ntoggles itself on label click and manages its own dismissal, its own press\ngesture and item keyboard navigation (ArrowUp/ArrowDown, Home/End, and the\nshared first-letter type-ahead — src/type-ahead.ts) while open.\n\nPointer — the two styles `vf-select` supports, on the same terms (see\nsrc/menu-press.ts): the System 7 press-drag-release (press the title, slide\nonto a command, release over it) and a modern quick tap that leaves the menu\ndropped for a second click.\n\nTakes `top`/`left` like every other element (VfPositioned) — the\nnatural fit being a standalone menu, which is a free-standing menu button and\nplaces like any other control. The panel is anchored to the host's own box\n(`top: 100%`), so it follows a placed menu down without any further work.\nInside a `<vf-menu-bar>`, the bar lays its titles out in flow — placing one\nlifts it off the bar and the titles beside it close the gap.",
6946
+ "description": "`<vf-menu>` — a pull-down menu: a bar label plus a dropped panel of\n`<vf-menu-item>` / `<vf-separator>` children.\n\nInside a `<vf-menu-bar>` the bar coordinates open state (only one menu open,\nhover-switching, outside-click/Escape dismissal) and owns the pointer\ngesture, which may travel between its menus. Used standalone, the menu\ntoggles itself on label click and manages its own dismissal, its own press\ngesture and item keyboard navigation (ArrowUp/ArrowDown, Home/End, and the\nshared first-letter type-ahead — src/type-ahead.ts) while open.\n\nPointer — the two styles `vf-select` supports, on the same terms (see\nsrc/menu-press.ts): the System 7 press-drag-release (press the title, slide\nonto a command, release over it) and a modern quick tap that leaves the menu\ndropped for a second click.\n\nTakes `top`/`left` like every other element (VfPositioned) — the\nnatural fit being a standalone menu, which is a free-standing menu button and\nplaces like any other control. The panel is anchored to the host's own box\n(`top: 100%`), so it follows a placed menu down without any further work.\nInside a `<vf-menu-bar>`, the bar lays its titles out in flow — placing one\nlifts it off the bar and the titles beside it close the gap. Slotted straight\ninto a `<vf-desktop>`, a free-standing menu sits on the desktop's menu tier\nabove every window, palettes included, as a bar does.",
6910
6947
  "name": "VfMenu",
6911
6948
  "cssProperties": [
6912
6949
  {
@@ -41,10 +41,18 @@ declare const VfContainer_base: (new (...args: any[]) => import("../size.js").Vf
41
41
  * width, because a layout box that silently claimed a size nobody declared
42
42
  * would be inventing one (the `vf-stack` rule, held here too).
43
43
  *
44
- * **It paints nothing and means nothing** — unless `pattern` says what to
45
- * paint. No border, role, keyboard behavior or selection; what it holds
44
+ * **It paints nothing and means nothing** — unless `pattern` or `rule` say
45
+ * what to paint. No role, keyboard behavior or selection; what it holds
46
46
  * decides what it is.
47
47
  *
48
+ * **`rule` draws the 1px rule on the edges it names** — `rule="bottom"` is
49
+ * 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.
55
+ *
48
56
  * **`pattern` fills the box with a 1-bit pattern**: one of the 38 standard
49
57
  * MacPaint patterns by name (`pattern="bricks"`, `pattern="gray-50"` —
50
58
  * docs/PATTERNS.md has the table), or sixteen hex digits stating a custom
@@ -97,6 +105,18 @@ export declare class VfContainer extends VfContainer_base {
97
105
  pattern?: string | null;
98
106
  /** `pattern`, resolved — what the fill paints; null paints nothing. */
99
107
  private _pattern;
108
+ /**
109
+ * The 1px rule on the box's edges: edge names separated by spaces —
110
+ * `"bottom"`, `"top bottom"`, up to all four in any order. Drawn as the
111
+ * box's own border inside the declared size, in `--vf-black`, scaled with
112
+ * the display like every kit frame's border; content and placed children
113
+ * begin inside it.
114
+ * Unset, no rule; a value naming anything but an edge draws none and
115
+ * warns once.
116
+ */
117
+ rule?: string | null;
118
+ /** `rule`, resolved — the edges drawn; empty draws nothing. */
119
+ private _rule;
100
120
  /** The shadow box the fill paints on; exists from the first render. */
101
121
  private readonly box;
102
122
  /**
@@ -4,15 +4,16 @@ 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 { PatternFillController as o, vfPatternFill as s } from "../pattern-fill.js";
8
- import { GridSnapController as c } from "../grid-snap.js";
9
- import { VfSized as l } from "../size.js";
10
- import { LitElement as u, css as d, html as f } from "lit";
11
- import { property as p, query as m } from "lit/decorators.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";
12
13
  //#region src/components/vf-container.ts
13
- var h = class extends l(r(u)) {
14
+ var v = class extends f(r(p)) {
14
15
  constructor(...e) {
15
- super(...e), this._pattern = null, this.#e = !1, this.scale = new t(this), this.gridSnap = new c(this), this.patternFill = new o(this, {
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, {
16
17
  getBox: () => this.box,
17
18
  getPattern: () => this._pattern,
18
19
  getSize: () => ({
@@ -24,8 +25,9 @@ var h = class extends l(r(u)) {
24
25
  static {
25
26
  this.styles = [
26
27
  i,
27
- s,
28
- d`
28
+ u,
29
+ c,
30
+ m`
29
31
  :host {
30
32
  display: block;
31
33
  /* Shrink-wrap an undeclared axis rather than claim the parent's
@@ -92,17 +94,22 @@ var h = class extends l(r(u)) {
92
94
  ];
93
95
  }
94
96
  #e;
97
+ #t;
95
98
  willUpdate(e) {
96
- 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.`)));
99
+ 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")) {
100
+ let e = o(this.rule);
101
+ 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.`));
102
+ }
97
103
  }
98
104
  render() {
99
- return f`<div
100
- class="vf-snap box vf-pattern-fill${this._pattern ? " vf-patterned" : ""}"
105
+ let e = s(this._rule);
106
+ return h`<div
107
+ class="vf-snap box vf-pattern-fill${this._pattern ? " vf-patterned" : ""}${e ? ` ${e}` : ""}"
101
108
  >
102
109
  <slot></slot>
103
110
  </div>`;
104
111
  }
105
112
  };
106
- n([p()], h.prototype, "pattern", void 0), n([m(".box")], h.prototype, "box", void 0), h = n([e("vf-container")], h);
113
+ 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);
107
114
  //#endregion
108
- export { h as VfContainer };
115
+ export { v as VfContainer };
@@ -18,6 +18,9 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
18
18
  * outside the single-active invariant entirely — clicking a palette neither
19
19
  * deactivates the active document window nor greys the palette, exactly as
20
20
  * System 7's floating windoids behaved while their application was frontmost.
21
+ * A slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier
22
+ * above both, so its dropped menus cover palettes and document windows
23
+ * alike; only the screen-corner mask is in front of it.
21
24
  *
22
25
  * **Deactivation.** On a real System 7 machine clicking the desktop clicked
23
26
  * the *Finder* — the frontmost application's windows lost their stripes.
@@ -14,14 +14,14 @@ import { SCREEN_CORNER as x, steppedCornerClip as S } from "../pixel-frame.js";
14
14
  import { LitElement as C, css as w, html as T, unsafeCSS as E } from "lit";
15
15
  import { property as D, query as O, queryAssignedElements as k } from "lit/decorators.js";
16
16
  //#region src/components/vf-desktop.ts
17
- var A = 1e6, j = 512, M = 342, N = "gray-50", P = p(d[N], "#000000", "#ffffff"), F = c(P.width, P.height, l(P.rects)), I = u(P.width), L = class extends o(C) {
17
+ var A = 1e6, j = 2 * A, M = 512, N = 342, P = "gray-50", F = p(d[P], "#000000", "#ffffff"), I = c(F.width, F.height, l(F.rects)), L = u(F.width), R = class extends o(C) {
18
18
  constructor(...e) {
19
- super(...e), this.width = j, this.height = M, this.bezel = 0, this.pattern = N, this.scale = new n(this), this.gridSnap = new y(this), this._token = "", this._desktopPattern = d[N], this.#e = !1, this.patternFill = new _(this, {
19
+ super(...e), this.width = M, this.height = N, this.bezel = 0, this.pattern = P, this.scale = new n(this), this.gridSnap = new y(this), this._token = "", this._desktopPattern = d[P], this.#e = !1, this.patternFill = new _(this, {
20
20
  getBox: () => this.screen,
21
21
  getPattern: () => this._token ? null : this._desktopPattern,
22
22
  getSize: () => ({
23
- width: this.width ?? j,
24
- height: this.height ?? M
23
+ width: this.width ?? M,
24
+ height: this.height ?? N
25
25
  })
26
26
  }), this._zCounter = 0, this._activeWindow = null, this._deactivated = !1, this._awaitingUpgrade = !1, this._pointerGesture = !1, this._restoringFocus = !1, this._gestureEnd = new b(this, () => [[
27
27
  document,
@@ -112,7 +112,7 @@ var A = 1e6, j = 512, M = 342, N = "gray-50", P = p(d[N], "#000000", "#ffffff"),
112
112
  position: absolute;
113
113
  inset: 0;
114
114
  z-index: -1;
115
- --_vf-tile-image: var(--vf-desktop-pattern, ${E(F)});
115
+ --_vf-tile-image: var(--vf-desktop-pattern, ${E(I)});
116
116
  /* Forced colors: hidden with the pattern, same posture. */
117
117
  @media (forced-colors: active) {
118
118
  display: none;
@@ -133,6 +133,19 @@ var A = 1e6, j = 512, M = 342, N = "gray-50", P = p(d[N], "#000000", "#ffffff"),
133
133
  ::slotted(vf-window) {
134
134
  position: relative;
135
135
  }
136
+ /* The menu tier: a slotted bar, or a free-standing menu placed on the
137
+ desktop, sits above both window tiers (MENU_BAR_Z), so a dropped
138
+ menu paints over a floating palette exactly as it does over a
139
+ document window. Stated here rather than left to the bar's own
140
+ :host z-index (1000, which the utility band outranks): an outer
141
+ tree's ::slotted declaration beats the inner tree's :host one, so the
142
+ desktop that hands out the window bands owns this band too. Under
143
+ the corner mask, like everything. */
144
+ ::slotted(vf-menu-bar),
145
+ ::slotted(vf-menu) {
146
+ position: relative;
147
+ z-index: ${j};
148
+ }
136
149
  /* With a bezel, the screen's top corners wear the SCREEN_CORNER mask,
137
150
  rounding into the surrounding black — the top pair only, because the
138
151
  classic framebuffer masked only those; the raster's bottom corners
@@ -252,21 +265,21 @@ var A = 1e6, j = 512, M = 342, N = "gray-50", P = p(d[N], "#000000", "#ffffff"),
252
265
  willUpdate(e) {
253
266
  if (super.willUpdate(e), this._token = m(this, "--vf-desktop-pattern"), e.has("pattern")) {
254
267
  let e = f(this.pattern);
255
- 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 ${N}.`)), this._desktopPattern = e ?? d[N];
268
+ 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 ${P}.`)), this._desktopPattern = e ?? d[P];
256
269
  }
257
270
  }
258
271
  updated(e) {
259
272
  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")) {
260
- let e = this.width ?? j, t = this.height ?? M;
273
+ let e = this.width ?? M, t = this.height ?? N;
261
274
  this.style.width = i(e + 2 * this.bezel), this.style.height = i(t + 2 * this.bezel);
262
275
  }
263
276
  }
264
277
  render() {
265
- let e = this.width ?? j, t = this.height ?? M, n = this._token ? T`<div class="vf-tile-grid">
278
+ let e = this.width ?? M, t = this.height ?? N, n = this._token ? T`<div class="vf-tile-grid">
266
279
  ${h({
267
- cols: Math.ceil(e / I),
268
- rows: Math.ceil(t / I),
269
- tile: I
280
+ cols: Math.ceil(e / L),
281
+ rows: Math.ceil(t / L),
282
+ tile: L
270
283
  })}
271
284
  </div>` : null;
272
285
  return T`
@@ -284,6 +297,6 @@ var A = 1e6, j = 512, M = 342, N = "gray-50", P = p(d[N], "#000000", "#ffffff"),
284
297
  `;
285
298
  }
286
299
  };
287
- a([D({ type: Number })], L.prototype, "width", void 0), a([D({ type: Number })], L.prototype, "height", void 0), a([D({ type: Number })], L.prototype, "bezel", void 0), a([D()], L.prototype, "pattern", void 0), a([k({ selector: "vf-window" })], L.prototype, "_windows", void 0), a([O(".screen")], L.prototype, "screen", void 0), L = a([t("vf-desktop")], L);
300
+ a([D({ type: Number })], R.prototype, "width", void 0), a([D({ type: Number })], R.prototype, "height", void 0), a([D({ type: Number })], R.prototype, "bezel", void 0), a([D()], R.prototype, "pattern", void 0), a([k({ selector: "vf-window" })], R.prototype, "_windows", void 0), a([O(".screen")], R.prototype, "screen", void 0), R = a([t("vf-desktop")], R);
288
301
  //#endregion
289
- export { L as VfDesktop };
302
+ export { R as VfDesktop };
@@ -3,17 +3,18 @@ import { ScaleController as t } from "../scale.js";
3
3
  import n from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
4
4
  import { VfPositioned as r } from "../position.js";
5
5
  import { vfBase as i } from "../styles/recipes/host.js";
6
- import { GridSnapController as a } from "../grid-snap.js";
7
- import { DocumentListenersController as o } from "../document-listeners.js";
8
- import { SCREEN_CORNER as s, steppedCornerClip as c } from "../pixel-frame.js";
9
- import { TypeAheadBuffer as l } from "../type-ahead.js";
10
- import { MenuPressController as u } from "../menu-press.js";
11
- import { LitElement as d, css as f, html as p, unsafeCSS as m } from "lit";
12
- import { property as h, queryAssignedElements as g } from "lit/decorators.js";
6
+ import { vfRule as a } from "../styles/recipes/rule.js";
7
+ import { GridSnapController as o } from "../grid-snap.js";
8
+ import { DocumentListenersController as s } from "../document-listeners.js";
9
+ import { SCREEN_CORNER as c, steppedCornerClip as l } from "../pixel-frame.js";
10
+ import { TypeAheadBuffer as u } from "../type-ahead.js";
11
+ import { MenuPressController as d } from "../menu-press.js";
12
+ import { LitElement as f, css as p, html as m, unsafeCSS as h } from "lit";
13
+ import { property as g, queryAssignedElements as _ } from "lit/decorators.js";
13
14
  //#region src/components/vf-menu-bar.ts
14
- var _ = class extends r(d) {
15
+ var v = class extends r(f) {
15
16
  constructor(...e) {
16
- super(...e), this.scale = new t(this), this.gridSnap = new a(this), this.label = "", this.rounded = !1, this.shortcuts = !1, this.#e = null, this.#t = this.attachInternals(), this.#n = new l(), this.#r = null, this.#i = new o(this, () => [[
17
+ super(...e), this.scale = new t(this), this.gridSnap = new o(this), this.label = "", this.rounded = !1, this.shortcuts = !1, this.#e = null, this.#t = this.attachInternals(), this.#n = new u(), this.#r = null, this.#i = new s(this, () => [[
17
18
  document,
18
19
  "pointerdown",
19
20
  this.#h,
@@ -23,7 +24,7 @@ var _ = class extends r(d) {
23
24
  "keydown",
24
25
  this.#g,
25
26
  !0
26
- ]]), this.#a = new u(this, {
27
+ ]]), this.#a = new d(this, {
27
28
  menus: () => this._menus,
28
29
  open: (e) => this.#p(e),
29
30
  close: () => this.#m()
@@ -101,20 +102,28 @@ var _ = class extends r(d) {
101
102
  };
102
103
  }
103
104
  static {
104
- this.styles = [i, f`
105
+ this.styles = [
106
+ i,
107
+ a,
108
+ p`
105
109
  :host {
106
110
  display: block;
107
111
  /* 19 white system px over the 1px black rule — Menus.png's bar strip
108
112
  exactly (white rows y 69..87 of the sheet). */
109
113
  height: calc(var(--vf-scale, 1) * var(--vf-menubar-height, 20px));
110
114
  position: relative;
115
+ /* Above the page content a bar stands among: its dropped panels are
116
+ z-index 1000 inside this stacking context, so this is the level
117
+ they paint at. Inside a vf-desktop the desktop restates the level
118
+ through ::slotted(vf-menu-bar) — its utility-window band is
119
+ higher than this, and the desktop owns the tiers. */
111
120
  z-index: 1000;
112
121
  }
113
122
  .bar {
114
123
  /* Paint lives here rather than on the host so it rides the snap offset
115
- (see .vf-snap in base.ts); border-box sizing keeps the geometry. */
124
+ (see .vf-snap in base.ts); border-box sizing keeps the geometry. The
125
+ rule is vfRule's vf-rule-bottom on the element. */
116
126
  background: var(--vf-white, #fff);
117
- border-bottom: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
118
127
  display: flex;
119
128
  align-items: stretch;
120
129
  height: 100%;
@@ -146,20 +155,21 @@ var _ = class extends r(d) {
146
155
  content: '';
147
156
  position: absolute;
148
157
  top: 0;
149
- width: calc(var(--vf-scale, 1) * ${s[0]}px);
150
- height: calc(var(--vf-scale, 1) * ${s.length}px);
158
+ width: calc(var(--vf-scale, 1) * ${c[0]}px);
159
+ height: calc(var(--vf-scale, 1) * ${c.length}px);
151
160
  background: var(--vf-black, #000);
152
161
  pointer-events: none;
153
162
  }
154
163
  :host([rounded]) .bar::before {
155
164
  left: 0;
156
- clip-path: ${m(c(s, "left"))};
165
+ clip-path: ${h(l(c, "left"))};
157
166
  }
158
167
  :host([rounded]) .bar::after {
159
168
  right: 0;
160
- clip-path: ${m(c(s, "right"))};
169
+ clip-path: ${h(l(c, "right"))};
161
170
  }
162
- `];
171
+ `
172
+ ];
163
173
  }
164
174
  #e;
165
175
  #t;
@@ -181,8 +191,8 @@ var _ = class extends r(d) {
181
191
  e.has("label") && (this.#t.ariaLabel = this.label || null);
182
192
  }
183
193
  render() {
184
- return p`
185
- <div class="bar vf-snap" part="bar" role="presentation">
194
+ return m`
195
+ <div class="bar vf-snap vf-rule-bottom" part="bar" role="presentation">
186
196
  <slot @slotchange=${this.#s}></slot>
187
197
  </div>
188
198
  `;
@@ -225,15 +235,15 @@ var _ = class extends r(d) {
225
235
  r = n < 0 ? e === 1 ? 0 : t.length - 1 : (n + e + t.length) % t.length, t[r]?.focus();
226
236
  }
227
237
  };
228
- n([h()], _.prototype, "label", void 0), n([h({
238
+ n([g()], v.prototype, "label", void 0), n([g({
229
239
  type: Boolean,
230
240
  reflect: !0
231
- })], _.prototype, "rounded", void 0), n([h({
241
+ })], v.prototype, "rounded", void 0), n([g({
232
242
  type: Boolean,
233
243
  reflect: !0
234
- })], _.prototype, "shortcuts", void 0), n([g({
244
+ })], v.prototype, "shortcuts", void 0), n([_({
235
245
  selector: "vf-menu",
236
246
  flatten: !0
237
- })], _.prototype, "_menus", void 0), _ = n([e("vf-menu-bar")], _);
247
+ })], v.prototype, "_menus", void 0), v = n([e("vf-menu-bar")], v);
238
248
  //#endregion
239
- export { _ as VfMenuBar };
249
+ export { v as VfMenuBar };
@@ -22,7 +22,9 @@ declare const VfMenu_base: (new (...args: any[]) => import("../position.js").VfP
22
22
  * places like any other control. The panel is anchored to the host's own box
23
23
  * (`top: 100%`), so it follows a placed menu down without any further work.
24
24
  * Inside a `<vf-menu-bar>`, the bar lays its titles out in flow — placing one
25
- * lifts it off the bar and the titles beside it close the gap.
25
+ * lifts it off the bar and the titles beside it close the gap. Slotted straight
26
+ * into a `<vf-desktop>`, a free-standing menu sits on the desktop's menu tier
27
+ * above every window, palettes included, as a bar does.
26
28
  *
27
29
  * @slot - Menu contents: `vf-menu-item` and `vf-separator` elements.
28
30
  * @slot label - Replaces the `label` text in the bar — e.g. a `vf-img` apple