vintage-frames 0.12.8 → 0.14.0

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 (62) hide show
  1. package/custom-elements.json +26 -26
  2. package/dist/chrome.d.ts +1 -1
  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 +16 -20
  6. package/dist/components/vf-container.js +25 -17
  7. package/dist/components/vf-desktop.d.ts +4 -5
  8. package/dist/components/vf-desktop.js +13 -18
  9. package/dist/components/vf-fieldset.js +30 -22
  10. package/dist/components/vf-icon.js +55 -55
  11. package/dist/components/vf-list.js +30 -29
  12. package/dist/components/vf-menu.js +24 -22
  13. package/dist/components/vf-number-field.js +32 -30
  14. package/dist/components/vf-progress-bar.d.ts +2 -2
  15. package/dist/components/vf-progress-bar.js +65 -52
  16. package/dist/components/vf-radio.js +3 -4
  17. package/dist/components/vf-scroll-area.js +27 -26
  18. package/dist/components/vf-select.js +108 -90
  19. package/dist/components/vf-separator.d.ts +5 -5
  20. package/dist/components/vf-separator.js +36 -10
  21. package/dist/components/vf-slider.js +11 -11
  22. package/dist/components/vf-swatch.d.ts +2 -2
  23. package/dist/components/vf-swatch.js +73 -72
  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 +6 -9
  27. package/dist/components/vf-window.js +106 -87
  28. package/dist/index.d.ts +20 -10
  29. package/dist/index.js +63 -62
  30. package/dist/pattern-fill.d.ts +21 -50
  31. package/dist/pattern-fill.js +19 -54
  32. package/dist/scroll-rail.d.ts +6 -6
  33. package/dist/scroll-rail.js +24 -29
  34. package/dist/styles/base.d.ts +3 -1
  35. package/dist/styles/recipes/field.d.ts +10 -6
  36. package/dist/styles/recipes/field.js +8 -7
  37. package/dist/styles/recipes/focus.d.ts +7 -3
  38. package/dist/styles/recipes/pattern.d.ts +19 -10
  39. package/dist/styles/recipes/pattern.js +27 -18
  40. package/dist/styles/recipes/rule.d.ts +11 -8
  41. package/dist/styles/recipes/rule.js +31 -13
  42. package/dist/styles/recipes/scroll-rail.d.ts +21 -13
  43. package/dist/styles/recipes/scroll-rail.js +27 -37
  44. package/dist/styles/recipes/shadow.d.ts +10 -6
  45. package/dist/styles/recipes/shadow.js +4 -2
  46. package/dist/styles/recipes/stroke.d.ts +85 -0
  47. package/dist/styles/recipes/stroke.js +53 -0
  48. package/dist/styles/recipes/surface.d.ts +8 -4
  49. package/dist/styles/recipes/surface.js +23 -17
  50. package/dist/styles/recipes/tile.d.ts +11 -3
  51. package/dist/styles/recipes/tile.js +12 -12
  52. package/dist/styles/recipes/title-bar.d.ts +7 -0
  53. package/dist/styles/recipes/title-bar.js +25 -22
  54. package/dist/styles/recipes/toggle.js +3 -3
  55. package/dist/tile-grid.d.ts +98 -64
  56. package/dist/tile-grid.js +63 -30
  57. package/dist/track-width.d.ts +1 -2
  58. package/dist/zoom.d.ts +9 -9
  59. package/docs/SPEC.md +33 -32
  60. package/editor/vscode.html-custom-data.json +5 -5
  61. package/editor/web-types.json +8 -8
  62. package/package.json +1 -1
@@ -1348,11 +1348,11 @@
1348
1348
  "declarations": [
1349
1349
  {
1350
1350
  "kind": "class",
1351
- "description": "The classic System 7 checkbox: a 13×13 white square with a 1px black\nborder whose checked state is the corner-to-corner ✕ glyph — the pixel-exact\ncross traced from the Classic Macintosh UI Kit sprite. The border \"thickens\"\nwhile pressed, exactly like the original control.\n\nForm-associated: submits `value` under `name` when checked (like a native\ncheckbox) and restores its initial checked state on form reset. Toggles on\nclick and Space.",
1351
+ "description": "The classic System 7 checkbox: a 12×12 white square with a 1px black\nborder whose checked state is the corner-to-corner ✕ glyph — the pixel-exact\ncross traced from the Classic Macintosh UI Kit sprite, filling the 10×10\ninterior. The border \"thickens\" while pressed, exactly like the original\ncontrol.\n\nForm-associated: submits `value` under `name` when checked (like a native\ncheckbox) and restores its initial checked state on form reset. Toggles on\nclick and Space.",
1352
1352
  "name": "VfCheckbox",
1353
1353
  "cssParts": [
1354
1354
  {
1355
- "description": "The 13×13 checkbox square.",
1355
+ "description": "The 12×12 checkbox square.",
1356
1356
  "name": "box"
1357
1357
  },
1358
1358
  {
@@ -1362,7 +1362,7 @@
1362
1362
  ],
1363
1363
  "slots": [
1364
1364
  {
1365
- "description": "The label, rendered to the right of the box with a 6px gap. Left empty, the label and its gap collapse: the control is the bare 13×13 box.",
1365
+ "description": "The label, rendered to the right of the box with a 6px gap. Left empty, the label and its gap collapse: the control is the bare 12×12 box.",
1366
1366
  "name": ""
1367
1367
  }
1368
1368
  ],
@@ -2246,7 +2246,7 @@
2246
2246
  "declarations": [
2247
2247
  {
2248
2248
  "kind": "class",
2249
- "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.",
2249
+ "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 drawn inside the\ndeclared size (vfRule), so a 24px `rule=\"bottom\"` strip is 23 rows\nof box over the line; content, `fill-width` children and placed children\nbegin inside it, as a rectangle's interior begins inside FrameRect'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 repeating tile\nas the desktop dither, so it is 1-bit at every density and zoom and a box\nof any size, declared or not, costs nothing more (src/pattern-fill.ts).\nUnder 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 correction lands on the shadow box below, and the\ncoordinate system sits inside it, so the correction moves the whole\ncoordinate system — everything placed against it rides along instead of\nbeing 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.",
2250
2250
  "name": "VfContainer",
2251
2251
  "slots": [
2252
2252
  {
@@ -2290,7 +2290,7 @@
2290
2290
  "type": {
2291
2291
  "text": "string | null | undefined"
2292
2292
  },
2293
- "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.",
2293
+ "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 inside\nthe declared size, in `--vf-black`, scaled with the display like every\nkit frame; content and placed children begin inside it.\nUnset, no rule; a value naming anything but an edge draws none and\nwarns once.",
2294
2294
  "attribute": "rule"
2295
2295
  },
2296
2296
  {
@@ -2344,8 +2344,8 @@
2344
2344
  "name": "patternFill",
2345
2345
  "privacy": "private",
2346
2346
  "readonly": true,
2347
- "default": "new PatternFillController(this, { getBox: () => this.box, getPattern: () => this._pattern, getSize: () => ({ width: this.width, height: this.height }), })",
2348
- "description": "The pattern fill, painted on `.box` so it rides the snap correction with\nthe coordinate system. A declared axis sizes the raster exactly; an\nundeclared one is measured (src/pattern-fill.ts)."
2347
+ "default": "new PatternFillController(this, { getBox: () => this.box, getPattern: () => this._pattern, })",
2348
+ "description": "The pattern fill, painted on `.box` so it rides the snap correction with\nthe coordinate system (src/pattern-fill.ts)."
2349
2349
  },
2350
2350
  {
2351
2351
  "kind": "field",
@@ -2443,7 +2443,7 @@
2443
2443
  "type": {
2444
2444
  "text": "string | null | undefined"
2445
2445
  },
2446
- "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.",
2446
+ "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 inside\nthe declared size, in `--vf-black`, scaled with the display like every\nkit frame; content and placed children begin inside it.\nUnset, no rule; a value naming anything but an edge draws none and\nwarns once.",
2447
2447
  "fieldName": "rule"
2448
2448
  },
2449
2449
  {
@@ -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. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its 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, one whole-surface raster at one image px per system px, 1-bit at\nevery density 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. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its 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
  {
@@ -2764,8 +2764,8 @@
2764
2764
  "name": "patternFill",
2765
2765
  "privacy": "private",
2766
2766
  "readonly": true,
2767
- "default": "new PatternFillController(this, { getBox: () => this.screen, getPattern: () => (this._token ? null : this._desktopPattern), getSize: () => ({ width: this.width ?? DEFAULT_SCREEN_WIDTH, height: this.height ?? DEFAULT_SCREEN_HEIGHT, }), })",
2768
- "description": "The desktop pattern, painted as the screen's own background\n(src/pattern-fill.ts) from the declared raster — scale-independent, so\ndensity and zoom re-encode nothing — and silent while a consumer token\nowns the fill."
2767
+ "default": "new PatternFillController(this, { getBox: () => this.screen, getPattern: () => (this._token ? null : this._desktopPattern), })",
2768
+ "description": "The desktop pattern, painted as the screen's own background\n(src/pattern-fill.ts) — a repeating tile, so resizing the screen\nre-encodes nothing — and silent while a consumer token owns the fill."
2769
2769
  },
2770
2770
  {
2771
2771
  "kind": "field",
@@ -11689,15 +11689,15 @@
11689
11689
  },
11690
11690
  "privacy": "private",
11691
11691
  "default": "''",
11692
- "description": "The consumer's `--vf-progress-stripes` override, or `''` for the kit\nbarber — which exact-fill path the strip takes (src/tile-grid.ts).\nRe-read every update; a runtime token swap wants a `requestUpdate()`."
11692
+ "description": "The consumer's `--vf-progress-stripes` override, or `''` for the kit\nbarber — which path the strip takes (src/tile-grid.ts). Re-read every\nupdate; a runtime token swap wants a `requestUpdate()`."
11693
11693
  },
11694
11694
  {
11695
11695
  "kind": "field",
11696
- "name": "#raster",
11696
+ "name": "#barberTile",
11697
11697
  "privacy": "private",
11698
11698
  "readonly": true,
11699
- "default": "new TileRasterCache()",
11700
- "description": "The whole-strip barber raster, cached against its ceiled width."
11699
+ "default": "new RepeatTileController(this, { getBox: () => this.renderRoot?.querySelector<HTMLElement>('.vf-tile-strip'), getArt: () => (this.indeterminate && !this._pattern ? BARBER : null), property: '--_vf-barber-tile', })",
11700
+ "description": "The kit barber: the strip carries the repeating tile as\n`--_vf-barber-tile`."
11701
11701
  },
11702
11702
  {
11703
11703
  "kind": "field",
@@ -15308,7 +15308,7 @@
15308
15308
  "declarations": [
15309
15309
  {
15310
15310
  "kind": "class",
15311
- "description": "`<vf-separator>` — a 1px System 7 rule.\n\nHorizontal by default (1px tall, full width); set the `vertical` attribute\nfor a 1px-wide vertical rule (give it a height, or let a flex parent\nstretch it).\n\nContainers may restyle it via custom properties:\n- `--vf-separator-color` — line color (default `var(--vf-black, #000)`).\n- `--vf-separator-style` — line style, e.g. `dotted` (default `solid`).\n `vf-menu` sets these so slotted separators render as the classic dimmed\n dotted menu rule (see Menus.png).",
15311
+ "description": "`<vf-separator>` — a 1px System 7 rule.\n\nHorizontal by default (1px tall, full width); set the `vertical` attribute\nfor a 1px-wide vertical rule (give it a height, or let a flex parent\nstretch it).\n\nContainers may restyle it via custom properties:\n- `--vf-separator-color` — line color (default `var(--vf-black, #000)`).\n- `--vf-separator-style` — `solid` (the default) or `dotted`, one system px\n on and one off. `vf-menu` sets these so slotted separators render as the\n classic dimmed dotted menu rule (see Menus.png).",
15312
15312
  "name": "VfSeparator",
15313
15313
  "cssProperties": [
15314
15314
  {
@@ -15316,7 +15316,7 @@
15316
15316
  "name": "--vf-separator-color"
15317
15317
  },
15318
15318
  {
15319
- "description": "`vf-separator` rule style — `vf-menu` sets `dotted` (see `Menus.png`)",
15319
+ "description": "`vf-separator` rule style: `solid` or `dotted` — `vf-menu` sets `dotted` (see `Menus.png`)",
15320
15320
  "name": "--vf-separator-style",
15321
15321
  "default": "solid"
15322
15322
  }
@@ -16965,15 +16965,15 @@
16965
16965
  },
16966
16966
  "privacy": "private",
16967
16967
  "default": "''",
16968
- "description": "The consumer's `--vf-swatch-checker` override, or `''` for the kit\nchecker — which exact-fill path render() takes (src/tile-grid.ts).\nRe-read every update; a runtime token swap wants a `requestUpdate()`."
16968
+ "description": "The consumer's `--vf-swatch-checker` override, or `''` for the kit\nchecker — which path render() takes (src/tile-grid.ts). Re-read every\nupdate; a runtime token swap wants a `requestUpdate()`."
16969
16969
  },
16970
16970
  {
16971
16971
  "kind": "field",
16972
- "name": "#raster",
16972
+ "name": "#checkerTile",
16973
16973
  "privacy": "private",
16974
16974
  "readonly": true,
16975
- "default": "new TileRasterCache()",
16976
- "description": "The whole-surface checker raster, cached against the fill's size."
16975
+ "default": "new RepeatTileController(this, { getBox: () => this.renderRoot?.querySelector<HTMLElement>('.fill'), getArt: () => (this._pattern ? null : CHECKER), property: '--_vf-checker-tile', })",
16976
+ "description": "The kit checker: `.fill` carries the repeating tile as\n`--_vf-checker-tile`."
16977
16977
  },
16978
16978
  {
16979
16979
  "kind": "field",
@@ -20388,15 +20388,15 @@
20388
20388
  },
20389
20389
  "privacy": "private",
20390
20390
  "default": "''",
20391
- "description": "The consumer's `--vf-dots-pattern` override, or `''` for the kit dots —\nwhich exact-fill path the utility bar takes (src/tile-grid.ts). Re-read\nevery update; a runtime token swap wants a `requestUpdate()`."
20391
+ "description": "The consumer's `--vf-dots-pattern` override, or `''` for the kit dots —\nwhich path the utility bar takes (src/tile-grid.ts). Re-read every\nupdate; a runtime token swap wants a `requestUpdate()`."
20392
20392
  },
20393
20393
  {
20394
20394
  "kind": "field",
20395
- "name": "#dotsRaster",
20395
+ "name": "#dotsTile",
20396
20396
  "privacy": "private",
20397
20397
  "readonly": true,
20398
- "default": "new TileRasterCache()",
20399
- "description": "The whole-surface dots raster, cached against its ceiled size."
20398
+ "default": "new RepeatTileController(this, { getBox: () => this.renderRoot?.querySelector<HTMLElement>('.vf-dots'), getArt: () => (this.variant === 'utility' && !this._dotsPattern ? DOTS : null), property: '--_vf-dots-tile', })",
20399
+ "description": "The kit dots: the utility bar's `.vf-dots` layer carries the repeating\ntile as `--_vf-dots-tile` (`vfDots`), whatever the window's width."
20400
20400
  },
20401
20401
  {
20402
20402
  "kind": "method",
@@ -20407,7 +20407,7 @@
20407
20407
  "text": "unknown"
20408
20408
  }
20409
20409
  },
20410
- "description": "The exact dots fill rendered into the utility bar's `.vf-dots` layer\n(src/tile-grid.ts): the bar interior is the declared width minus the\nframe borders. The kit raster is ceiled to whole 30-px tiles so a\ngrow-box resize only re-encodes the image when it crosses a tile\nboundary — the layer's clip crops the overdraw; a consumer\n`--vf-dots-pattern` renders the placed tile grid at the token's\ndocumented 30-px geometry instead. A window with no declared width\nrenders neither and the layer keeps its CSS-repeated tile."
20410
+ "description": "A consumer `--vf-dots-pattern`'s placed tile grid, rendered into the\nutility bar's `.vf-dots` layer at the token's documented 30-px geometry\n(src/tile-grid.ts): the bar interior is the declared width minus the\nframe borders. A window with no declared width renders none, and the\nlayer repeats the token in CSS instead (`vf-dots-token`)."
20411
20411
  },
20412
20412
  {
20413
20413
  "kind": "field",
package/dist/chrome.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type TemplateResult } from 'lit';
2
2
  import type { ReactiveController, ReactiveControllerHost } from 'lit';
3
3
  import type { DragController } from './drag.js';
4
- export declare const chromeTitleBar: (drag: DragController, content: unknown, textureClass?: "vf-stripes" | "vf-dots", texture?: unknown) => TemplateResult;
4
+ export declare const chromeTitleBar: (drag: DragController, content: unknown, textureClass?: string, texture?: unknown) => TemplateResult;
5
5
  /**
6
6
  * Holds the flex-centered `.vf-title` patch on the placement lattice.
7
7
  *
@@ -2,10 +2,11 @@ import { type PropertyValues } from 'lit';
2
2
  import { VfFormControl } from '../form-control.js';
3
3
  declare const VfCheckbox_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & (abstract new (...args: any[]) => import("../toggle-control.js").VfToggleControlInterface) & typeof VfFormControl;
4
4
  /**
5
- * The classic System 7 checkbox: a 13×13 white square with a 1px black
5
+ * The classic System 7 checkbox: a 12×12 white square with a 1px black
6
6
  * border whose checked state is the corner-to-corner ✕ glyph — the pixel-exact
7
- * cross traced from the Classic Macintosh UI Kit sprite. The border "thickens"
8
- * while pressed, exactly like the original control.
7
+ * cross traced from the Classic Macintosh UI Kit sprite, filling the 10×10
8
+ * interior. The border "thickens" while pressed, exactly like the original
9
+ * control.
9
10
  *
10
11
  * Form-associated: submits `value` under `name` when checked (like a native
11
12
  * checkbox) and restores its initial checked state on form reset. Toggles on
@@ -13,8 +14,8 @@ declare const VfCheckbox_base: (new (...args: any[]) => import("../position.js")
13
14
  *
14
15
  * @slot - The label, rendered to the right of the box with a 6px gap.
15
16
  * Left empty, the label and its gap collapse: the control is the bare
16
- * 13×13 box.
17
- * @csspart box - The 13×13 checkbox square.
17
+ * 12×12 box.
18
+ * @csspart box - The 12×12 checkbox square.
18
19
  * @csspart label - The label wrapper around the slot.
19
20
  * @fires vf-change - When toggled by user interaction. `detail: { checked: boolean }`.
20
21
  * @fires input - Native event, dispatched from the host per user toggle (with
@@ -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 };
@@ -47,30 +47,28 @@ declare const VfContainer_base: (new (...args: any[]) => import("../size.js").Vf
47
47
  *
48
48
  * **`rule` draws the 1px rule on the edges it names** — `rule="bottom"` is
49
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.
50
+ * a status strip's, all four a framed box. The rule is drawn inside the
51
+ * declared size ({@link vfRule}), so a 24px `rule="bottom"` strip is 23 rows
52
+ * of box over the line; content, `fill-width` children and placed children
53
+ * begin inside it, as a rectangle's interior begins inside FrameRect's line.
55
54
  *
56
55
  * **`pattern` fills the box with a 1-bit pattern**: one of the 38 standard
57
56
  * MacPaint patterns by name (`pattern="bricks"`, `pattern="gray-50"` —
58
57
  * docs/PATTERNS.md has the table), or sixteen hex digits stating a custom
59
58
  * 8×8 pattern row by row, the way a PAT resource did. It is painted as the
60
59
  * box's own background — black ink on a `--vf-white` ground, anchored at
61
- * the box's top-left corner, under the content — by the same whole-surface
62
- * raster mechanism as the desktop dither, so it is 1-bit at every density
63
- * and zoom (src/pattern-fill.ts). A declared `width`/`height` sizes the
64
- * raster exactly; an undeclared axis (`fill-width`, a shrink-wrapped
65
- * height) is measured. Under forced colors the pattern goes flat Canvas.
60
+ * the box's top-left corner, under the content — by the same repeating tile
61
+ * as the desktop dither, so it is 1-bit at every density and zoom and a box
62
+ * of any size, declared or not, costs nothing more (src/pattern-fill.ts).
63
+ * Under forced colors the pattern goes flat Canvas.
66
64
  *
67
65
  * **It holds its box on the device-pixel grid** — with a `GridSnapController`.
68
66
  * A container's box is itself the consumer's coordinate system, including for
69
67
  * non-`vf` content that cannot correct itself, so the box is the thing to
70
- * hold on the grid. The shadow box below owns the `position: relative` anchor
71
- * and the `vf-snap` class together, so the correction
72
- * moves the whole coordinate system — everything placed against it rides
73
- * along instead of being re-corrected child by child. (`vf-stack` shipped
68
+ * hold on the grid. The correction lands on the shadow box below, and the
69
+ * coordinate system sits inside it, so the correction moves the whole
70
+ * coordinate system — everything placed against it rides along instead of
71
+ * being re-corrected child by child. (`vf-stack` shipped
74
72
  * without a controller on the theory that slotted `vf-*` children correct
75
73
  * their own origins; this component is where that theory's gap — consumer
76
74
  * content — became visible, and the stack has since adopted the same
@@ -107,10 +105,9 @@ export declare class VfContainer extends VfContainer_base {
107
105
  private _pattern;
108
106
  /**
109
107
  * 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.
108
+ * `"bottom"`, `"top bottom"`, up to all four in any order. Drawn inside
109
+ * the declared size, in `--vf-black`, scaled with the display like every
110
+ * kit frame; content and placed children begin inside it.
114
111
  * Unset, no rule; a value naming anything but an edge draws none and
115
112
  * warns once.
116
113
  */
@@ -134,8 +131,7 @@ export declare class VfContainer extends VfContainer_base {
134
131
  private readonly gridSnap;
135
132
  /**
136
133
  * The pattern fill, painted on `.box` so it rides the snap correction with
137
- * the coordinate system. A declared axis sizes the raster exactly; an
138
- * undeclared one is measured (src/pattern-fill.ts).
134
+ * the coordinate system (src/pattern-fill.ts).
139
135
  */
140
136
  private readonly patternFill;
141
137
  protected willUpdate(changed: PropertyValues<this>): void;
@@ -15,11 +15,7 @@ var v = class extends f(r(p)) {
15
15
  constructor(...e) {
16
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, {
17
17
  getBox: () => this.box,
18
- getPattern: () => this._pattern,
19
- getSize: () => ({
20
- width: this.width,
21
- height: this.height
22
- })
18
+ getPattern: () => this._pattern
23
19
  });
24
20
  }
25
21
  static {
@@ -48,21 +44,33 @@ var v = class extends f(r(p)) {
48
44
  text-align: inherit;
49
45
  }
50
46
 
51
- /* The coordinate system, as one shadow box coinciding with the host box.
52
- vf-snap (vfBase) gives it position: relative plus the controller's
53
- --vf-snap-dx/-dy offset — so it is BOTH the positioning anchor for
54
- children placed with top/left (src/position.ts) AND the element the
55
- grid-snap correction lands on. One element owning both is the point:
56
- corrected, it takes every placed child with it, kit or not. */
47
+ /* The painted box, coinciding with the host box: the pattern, the rule
48
+ and the grid-snap correction (vf-snap, vfBase — position: relative
49
+ plus the controller's --vf-snap-dx/-dy offset). The coordinate system
50
+ rides inside it (the slot, below), so the correction takes every
51
+ placed child with it, kit or not. */
57
52
  .box {
58
- /* flow-root: contain slotted margins, so the box's top edge — the
59
- origin placed children measure from — stays glued to the host's
60
- corner instead of being pushed down by a first child's margin
61
- collapsing through. */
62
- display: flow-root;
63
53
  /* Coincide with a declared height (100% of a definite host height;
64
54
  against an undeclared one it computes to auto and wraps content),
65
- so slotted percentage fills resolve against the stated box. */
55
+ so the slot inside can take the stated box. */
56
+ height: 100%;
57
+ /* The pattern starts inside the rule, as it did when the rule was a
58
+ border. */
59
+ background-origin: content-box;
60
+ }
61
+ /* The coordinate system: the slot, as a box inside the rule — the
62
+ rule's row is the painted box's padding (vfRule) — so content,
63
+ percentage fills and children placed with top/left (src/position.ts)
64
+ all begin inside it. */
65
+ .box > slot {
66
+ position: relative;
67
+ /* flow-root: contain slotted margins, so the top edge — the origin
68
+ placed children measure from — stays glued to the box's corner
69
+ instead of being pushed down by a first child's margin collapsing
70
+ through. */
71
+ display: flow-root;
72
+ /* The stated box less its rules, so slotted percentage fills resolve
73
+ against it; auto against an undeclared height. */
66
74
  height: 100%;
67
75
  }
68
76
 
@@ -52,8 +52,8 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
52
52
  * default, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen
53
53
  * hex digits stating a custom 8×8 pattern, as on `vf-container`. It is
54
54
  * painted as the screen's own background: black ink on an opaque white
55
- * paper, one whole-surface raster at one image px per system px, 1-bit at
56
- * every density and zoom (src/pattern-fill.ts).
55
+ * paper, a repeating tile drawn at the display's resolution, 1-bit at every
56
+ * density and zoom (src/pattern-fill.ts).
57
57
  *
58
58
  * **The drag surface.** The Finder dragged an icon as a dotted outline drawn
59
59
  * on the *screen*, clipped at its edge and phase-locked to its raster, so
@@ -187,9 +187,8 @@ export declare class VfDesktop extends VfDesktop_base {
187
187
  private readonly dragSurface;
188
188
  /**
189
189
  * The desktop pattern, painted as the screen's own background
190
- * (src/pattern-fill.ts) from the declared raster — scale-independent, so
191
- * density and zoom re-encode nothing — and silent while a consumer token
192
- * owns the fill.
190
+ * (src/pattern-fill.ts) — a repeating tile, so resizing the screen
191
+ * re-encodes nothing — and silent while a consumer token owns the fill.
193
192
  */
194
193
  private readonly patternFill;
195
194
  /** Monotonic z-index counter for window stacking. */
@@ -5,8 +5,8 @@ import a from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js
5
5
  import { VfPositioned as o, placementIn as s } from "../position.js";
6
6
  import { vfBase as c } from "../styles/recipes/host.js";
7
7
  import { tileImage as l, tileRects as u, tileSpan as d } from "../styles/recipes/tile.js";
8
- import { PATTERNS as f, parsePattern as p, patternMotif as m } from "../patterns.js";
9
- import { patternOverride as h, tileGrid as g, vfTileGrid as _ } from "../tile-grid.js";
8
+ import { patternOverride as f, tileGrid as p, vfTileGrid as m } from "../tile-grid.js";
9
+ import { PATTERNS as h, parsePattern as g, patternMotif as _ } from "../patterns.js";
10
10
  import { PatternFillController as v, vfPatternFill as y } from "../pattern-fill.js";
11
11
  import { GridSnapController as b } from "../grid-snap.js";
12
12
  import { DocumentListenersController as x } from "../document-listeners.js";
@@ -14,15 +14,11 @@ import { SCREEN_CORNER as S, steppedCornerClip as C } from "../pixel-frame.js";
14
14
  import { LitElement as w, css as T, html as E, unsafeCSS as D } from "lit";
15
15
  import { property as O, query as k, queryAssignedElements as A } from "lit/decorators.js";
16
16
  //#region src/components/vf-desktop.ts
17
- var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I], "#000000", "#ffffff"), R = l(L.width, L.height, u(L.rects)), z = d(L.width), B = class extends o(w) {
17
+ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = _(h[I], "#000000", "#ffffff"), R = l(L.width, L.height, u(L.rects)), z = d(L.width), B = class extends o(w) {
18
18
  constructor(...e) {
19
- super(...e), this.width = P, this.height = F, this.bezel = 0, this.pattern = I, this.scale = new n(this), this.gridSnap = new b(this), this._token = "", this._desktopPattern = f[I], this.#e = !1, this.patternFill = new v(this, {
19
+ super(...e), this.width = P, this.height = F, this.bezel = 0, this.pattern = I, this.scale = new n(this), this.gridSnap = new b(this), this._token = "", this._desktopPattern = h[I], this.#e = !1, this.patternFill = new v(this, {
20
20
  getBox: () => this.screen,
21
- getPattern: () => this._token ? null : this._desktopPattern,
22
- getSize: () => ({
23
- width: this.width ?? P,
24
- height: this.height ?? F
25
- })
21
+ getPattern: () => this._token ? null : this._desktopPattern
26
22
  }), this._zCounter = 0, this._activeWindow = null, this._deactivated = !1, this._awaitingUpgrade = !1, this._pointerGesture = !1, this._restoringFocus = !1, this._domSyncTimer = 0, this._gestureEnd = new x(this, () => [[
27
23
  document,
28
24
  "pointerup",
@@ -51,7 +47,7 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I]
51
47
  static {
52
48
  this.styles = [
53
49
  c,
54
- _,
50
+ m,
55
51
  y,
56
52
  T`
57
53
  :host {
@@ -89,10 +85,9 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I]
89
85
  dither — and shows only through a consumer token's translucent
90
86
  tile (see the --vf-desktop note in the class doc). The pattern
91
87
  itself is this element's own background, written by the
92
- PatternFillController: one whole-surface raster at one image px
93
- per system px, magnified nearest-neighbor, which is what keeps it
94
- 1-bit at the zoom-minted scales a repeating fill cannot hold
95
- (src/tile-grid.ts, src/pattern-fill.ts). */
88
+ PatternFillController: a 120-system-px tile drawn at the device
89
+ resolution it is shown at and repeated, so every engine copies it
90
+ 1:1 (src/pattern-fill.ts). */
96
91
  background-color: var(--vf-desktop, #808080);
97
92
  /* Forced colors: the pattern is literal black ink on white, which
98
93
  ignores a dark theme entirely. A backdrop is decoration, and
@@ -298,9 +293,9 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I]
298
293
  r && n instanceof HTMLElement && n.isConnected && this._deepActiveElement() !== n && (this._restoringFocus = !0, n.focus({ preventScroll: !0 }), this._restoringFocus = !1);
299
294
  }
300
295
  willUpdate(e) {
301
- if (super.willUpdate(e), this._token = h(this, "--vf-desktop-pattern"), e.has("pattern")) {
302
- let e = p(this.pattern);
303
- e === null && this.pattern?.trim() && !this.#e && (this.#e = !0, console.warn(`vf-desktop: unknown pattern "${this.pattern}" — a library name (docs/PATTERNS.md) or sixteen hex digits. Keeping ${I}.`)), this._desktopPattern = e ?? f[I];
296
+ if (super.willUpdate(e), this._token = f(this, "--vf-desktop-pattern"), e.has("pattern")) {
297
+ let e = g(this.pattern);
298
+ e === null && this.pattern?.trim() && !this.#e && (this.#e = !0, console.warn(`vf-desktop: unknown pattern "${this.pattern}" — a library name (docs/PATTERNS.md) or sixteen hex digits. Keeping ${I}.`)), this._desktopPattern = e ?? h[I];
304
299
  }
305
300
  }
306
301
  updated(e) {
@@ -311,7 +306,7 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I]
311
306
  }
312
307
  render() {
313
308
  let e = this.width ?? P, t = this.height ?? F, n = this._token ? E`<div class="vf-tile-grid">
314
- ${g({
309
+ ${p({
315
310
  cols: Math.ceil(e / z),
316
311
  rows: Math.ceil(t / z),
317
312
  tile: z