vintage-frames 0.10.1 → 0.12.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.
@@ -2453,7 +2453,7 @@
2453
2453
  "declarations": [
2454
2454
  {
2455
2455
  "kind": "class",
2456
- "description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its top corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, one whole-surface raster at one image px per system px, 1-bit at\nevery density and zoom (src/pattern-fill.ts).\n\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. Not the top 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`).",
2456
+ "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. Not the top 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`).",
2457
2457
  "name": "VfDesktop",
2458
2458
  "cssProperties": [
2459
2459
  {
@@ -2506,7 +2506,7 @@
2506
2506
  "text": "number"
2507
2507
  },
2508
2508
  "default": "0",
2509
- "description": "Width of the black screen bezel, in system px (`0` = none), added onto\nthe declared screen on every side — a `width=\"502\" bezel=\"5\"` desktop\nrenders a 512-system-px host box. The compact Mac's CRT showed an\nunlit black margin between the desktop's raster and the case; `bezel`\ndraws it around the screen and puts the classic screen-corner mask on\nthe screen's two *top* corners — only the top pair was rounded in the\nframebuffer. Flow, window coordinates and the drag clip all belong to\nthe screen, so windows crop at its edge. Inside a bezeled desktop a\nmenu bar needs no `rounded` of its own — the desktop's mask lands on\nthe same pixels.",
2509
+ "description": "Width of the black screen bezel, in system px (`0` = none), added onto\nthe declared screen on every side — a `width=\"502\" bezel=\"5\"` desktop\nrenders a 512-system-px host box. The compact Mac's CRT showed an\nunlit black margin between the desktop's raster and the case; `bezel`\ndraws it around the screen and puts the classic screen-corner mask on\nall four of the screen's corners. Flow, window coordinates and the drag\nclip all belong to the screen, so windows crop at its edge. Inside a\nbezeled desktop a menu bar needs no `rounded` of its own — the desktop's\ntop pair lands on the same pixels.",
2510
2510
  "attribute": "bezel"
2511
2511
  },
2512
2512
  {
@@ -3071,7 +3071,7 @@
3071
3071
  "text": "number"
3072
3072
  },
3073
3073
  "default": "0",
3074
- "description": "Width of the black screen bezel, in system px (`0` = none), added onto\nthe declared screen on every side — a `width=\"502\" bezel=\"5\"` desktop\nrenders a 512-system-px host box. The compact Mac's CRT showed an\nunlit black margin between the desktop's raster and the case; `bezel`\ndraws it around the screen and puts the classic screen-corner mask on\nthe screen's two *top* corners — only the top pair was rounded in the\nframebuffer. Flow, window coordinates and the drag clip all belong to\nthe screen, so windows crop at its edge. Inside a bezeled desktop a\nmenu bar needs no `rounded` of its own — the desktop's mask lands on\nthe same pixels.",
3074
+ "description": "Width of the black screen bezel, in system px (`0` = none), added onto\nthe declared screen on every side — a `width=\"502\" bezel=\"5\"` desktop\nrenders a 512-system-px host box. The compact Mac's CRT showed an\nunlit black margin between the desktop's raster and the case; `bezel`\ndraws it around the screen and puts the classic screen-corner mask on\nall four of the screen's corners. Flow, window coordinates and the drag\nclip all belong to the screen, so windows crop at its edge. Inside a\nbezeled desktop a menu bar needs no `rounded` of its own — the desktop's\ntop pair lands on the same pixels.",
3075
3075
  "fieldName": "bezel"
3076
3076
  },
3077
3077
  {
@@ -10834,7 +10834,7 @@
10834
10834
  "declarations": [
10835
10835
  {
10836
10836
  "kind": "class",
10837
- "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected` and the transient\n`active` highlight, and slots this element into its popup panel.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.",
10837
+ "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected`, the transient\n`active` highlight and `size`, and slots this element into its popup panel.\nUnder `size=\"small\"` the row is the small pill's 10px content height, in the\nbody face, and clips its own box.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.",
10838
10838
  "name": "VfOption",
10839
10839
  "cssProperties": [
10840
10840
  {
@@ -10905,6 +10905,17 @@
10905
10905
  "attribute": "active",
10906
10906
  "reflects": true
10907
10907
  },
10908
+ {
10909
+ "kind": "field",
10910
+ "name": "size",
10911
+ "type": {
10912
+ "text": "VfSelectSize"
10913
+ },
10914
+ "default": "'regular'",
10915
+ "description": "The parent select's `size`. Managed by the parent.",
10916
+ "attribute": "size",
10917
+ "reflects": true
10918
+ },
10908
10919
  {
10909
10920
  "kind": "field",
10910
10921
  "name": "#internals",
@@ -11013,6 +11024,15 @@
11013
11024
  "description": "Transient highlight (hover / keyboard cursor) — full-row inversion.\nManaged by the parent `<vf-select>`; not part of the authoring API.",
11014
11025
  "fieldName": "active"
11015
11026
  },
11027
+ {
11028
+ "name": "size",
11029
+ "type": {
11030
+ "text": "VfSelectSize"
11031
+ },
11032
+ "default": "'regular'",
11033
+ "description": "The parent select's `size`. Managed by the parent.",
11034
+ "fieldName": "size"
11035
+ },
11016
11036
  {
11017
11037
  "name": "top",
11018
11038
  "type": {
@@ -13364,7 +13384,7 @@
13364
13384
  "declarations": [
13365
13385
  {
13366
13386
  "kind": "class",
13367
- "description": "`<vf-select>` — the classic System 7 popup menu control (\"Macintosh HD ▼\").\n\nChildren are `<vf-option>` elements in the default slot. The closed control\nis a white box with a 1px black border, the small 1px hard shadow, the\nselected option's label on the left and a solid black ▼ triangle on the\nright. The open panel uses the shared `.vf-panel` recipe and is positioned\n`position: fixed` (computed from `getBoundingClientRect()`) so it escapes\nclipping containers; when possible the currently-selected item opens\ndirectly over the control, like the real popup menu.\n\nPointer — two interaction styles are supported and disambiguated by the\ngesture itself, resolved at the first pointer release:\n - System 7 press-drag-release: press the pill (the list appears under the\n pointer), drag onto an item, release over it to pick — one continuous\n press. Releasing over the current item or off the list closes with no\n change.\n - Modern click-to-open: a quick in-place click (no drag, released within\n PRESS_HOLD_MS) leaves the list open; a second, independent click\n then picks an item.\nThe two share one opening trigger (pointerdown) and diverge only on how the\npress ends — whether the pointer travelled to another item, and (for an\nin-place release) whether it was a quick tap or a held press. The pull-down\nmenus drive themselves the same way, on the same threshold; that half lives\nin src/menu-press.ts, because one menu press may travel across a whole bar.\n\nA list too tall for the screen is **clipped**, never scrolled: the edge slot\nwith items beyond it shows a solid arrow instead of a row, which rolls the\nlist one row at a time while the pointer rests on it. The clamp is quantized\nto the pill lattice, so a clipped popup still opens with its selected row\nover the closed pill — and the panel keeps every slot the list asked for, so\na box that had to slide to fit the screen opens with *blank rows* at whichever\nend the list no longer reaches: the exact travel it will roll through, in\neither direction. See src/popup-overflow.ts.\n\nKeyboard: Space/Enter/ArrowDown open; while open ArrowUp/ArrowDown move the\nhighlight, Home/End jump, Enter/Space select, Escape cancels. Selecting an\nitem plays the classic inversion blink (~250 ms) before closing. Keyboard\nfocus is marked with the kit's 1px dashed rule under the closed pill\n(`vfFocusUnderline`) rather than a ring around it — keyboard only, which\nhere means the page's input modality rather than `:focus-visible` (the pill\ndrives its own focus, and Blink reads that as visible either way).\n\nForm-associated: submits `value` under `name`.",
13387
+ "description": "`<vf-select>` — the classic System 7 popup menu control (\"Macintosh HD ▼\").\n\nChildren are `<vf-option>` elements in the default slot. The closed control\nis a white box with a 1px black border, the small 1px hard shadow, the\nselected option's label on the left and a solid black ▼ triangle on the\nright. The open panel uses the shared `.vf-panel` recipe and is positioned\n`position: fixed` (computed from `getBoundingClientRect()`) so it escapes\nclipping containers; when possible the currently-selected item opens\ndirectly over the control, like the real popup menu.\n\nPointer — two interaction styles are supported and disambiguated by the\ngesture itself, resolved at the first pointer release:\n - System 7 press-drag-release: press the pill (the list appears under the\n pointer), drag onto an item, release over it to pick — one continuous\n press. Releasing over the current item or off the list closes with no\n change.\n - Modern click-to-open: a quick in-place click (no drag, released within\n PRESS_HOLD_MS) leaves the list open; a second, independent click\n then picks an item.\nThe two share one opening trigger (pointerdown) and diverge only on how the\npress ends — whether the pointer travelled to another item, and (for an\nin-place release) whether it was a quick tap or a held press. The pull-down\nmenus drive themselves the same way, on the same threshold; that half lives\nin src/menu-press.ts, because one menu press may travel across a whole bar.\n\nA list too tall for the screen is **clipped**, never scrolled: the edge slot\nwith items beyond it shows a solid arrow instead of a row, which rolls the\nlist one row at a time while the pointer rests on it. The clamp is quantized\nto the pill lattice, so a clipped popup still opens with its selected row\nover the closed pill — and the panel keeps every slot the list asked for, so\na box that had to slide to fit the screen opens with *blank rows* at whichever\nend the list no longer reaches: the exact travel it will roll through, in\neither direction. See src/popup-overflow.ts.\n\n`size=\"small\"` sets the pill and its rows in the body face: a 12px pill\n(`--vf-popup-height-small`) over 10px rows, the baseline 8 rows down so the\nface's 2-row descenders end on the last content row. Its ▼ and scroll\narrows are the 9×5 `CARET_DOWN_SMALL` / `CARET_UP_SMALL`; the ✓ and the\nhorizontal insets are the regular pill's. Marks above a capital (É, Å, Ñ)\nreach past the 8 rows above the baseline and are clipped.\n\nKeyboard: Space/Enter/ArrowDown open; while open ArrowUp/ArrowDown move the\nhighlight, Home/End jump, Enter/Space select, Escape cancels. Selecting an\nitem plays the classic inversion blink (~250 ms) before closing. Keyboard\nfocus is marked with the kit's 1px dashed rule under the closed pill\n(`vfFocusUnderline`) rather than a ring around it — keyboard only, which\nhere means the page's input modality rather than `:focus-visible` (the pill\ndrives its own focus, and Blink reads that as visible either way).\n\nForm-associated: submits `value` under `name`.",
13368
13388
  "name": "VfSelect",
13369
13389
  "cssProperties": [
13370
13390
  {
@@ -13372,6 +13392,11 @@
13372
13392
  "name": "--vf-popup-height",
13373
13393
  "default": "18px"
13374
13394
  },
13395
+ {
13396
+ "description": "`vf-select[size=\"small\"]` pill (border box; its rows are this less the two borders)",
13397
+ "name": "--vf-popup-height-small",
13398
+ "default": "12px"
13399
+ },
13375
13400
  {
13376
13401
  "description": "room a clipped popup panel keeps clear at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4",
13377
13402
  "name": "--vf-popup-inset-top",
@@ -13417,18 +13442,6 @@
13417
13442
  }
13418
13443
  ],
13419
13444
  "members": [
13420
- {
13421
- "kind": "field",
13422
- "name": "ITEM_HEIGHT",
13423
- "type": {
13424
- "text": "number"
13425
- },
13426
- "privacy": "private",
13427
- "static": true,
13428
- "readonly": true,
13429
- "default": "16",
13430
- "description": "Fallback height of one option row — the pill's *content* height\n(`--vf-popup-height` 18px minus its two 1px borders). Used to overlay the\nselected row's white cell exactly on the closed pill. `positionPanel`\nprefers the row's *rendered* height so a re-themed `--vf-popup-height`\nkeeps the overlay aligned; this is the no-options fallback and must match\n`vf-option`'s default row height."
13431
- },
13432
13445
  {
13433
13446
  "kind": "field",
13434
13447
  "name": "value",
@@ -13450,6 +13463,17 @@
13450
13463
  "attribute": "name",
13451
13464
  "reflects": true
13452
13465
  },
13466
+ {
13467
+ "kind": "field",
13468
+ "name": "size",
13469
+ "type": {
13470
+ "text": "VfSelectSize"
13471
+ },
13472
+ "default": "'regular'",
13473
+ "description": "`regular` (the 18px pill in the display face) or `small` (12px, in the\nbody face). Any other value renders as `regular`. The select passes it to\nits options.",
13474
+ "attribute": "size",
13475
+ "reflects": true
13476
+ },
13453
13477
  {
13454
13478
  "kind": "field",
13455
13479
  "name": "label",
@@ -13869,6 +13893,17 @@
13869
13893
  },
13870
13894
  "description": "Marks the option matching `value` as selected."
13871
13895
  },
13896
+ {
13897
+ "kind": "method",
13898
+ "name": "applySize",
13899
+ "privacy": "private",
13900
+ "return": {
13901
+ "type": {
13902
+ "text": "void"
13903
+ }
13904
+ },
13905
+ "description": "Passes the pill size to every option; anything but `small` is regular."
13906
+ },
13872
13907
  {
13873
13908
  "kind": "field",
13874
13909
  "name": "handleSlotChange",
@@ -14932,6 +14967,15 @@
14932
14967
  "description": "Form field name used when submitting the associated form.",
14933
14968
  "fieldName": "name"
14934
14969
  },
14970
+ {
14971
+ "name": "size",
14972
+ "type": {
14973
+ "text": "VfSelectSize"
14974
+ },
14975
+ "default": "'regular'",
14976
+ "description": "`regular` (the 18px pill in the display face) or `small` (12px, in the\nbody face). Any other value renders as `regular`. The select passes it to\nits options.",
14977
+ "fieldName": "size"
14978
+ },
14935
14979
  {
14936
14980
  "name": "label",
14937
14981
  "type": {
@@ -45,7 +45,7 @@ declare const VfDesktop_base: (new (...args: any[]) => import("../position.js").
45
45
  * `resize`/`onScaleChange` for a viewport-filling desktop — and positions
46
46
  * the sized box with its own stylesheet, keeping any sub-system-pixel
47
47
  * slack on its side. `bezel` (system px) draws the black screen surround —
48
- * the CRT's unlit margin — around the screen, rounding its top corners
48
+ * the CRT's unlit margin — around the screen, rounding its four corners
49
49
  * with the classic corner mask.
50
50
  *
51
51
  * **`pattern`** names the desktop pattern — `gray-50` (the dither) by
@@ -119,11 +119,10 @@ export declare class VfDesktop extends VfDesktop_base {
119
119
  * renders a 512-system-px host box. The compact Mac's CRT showed an
120
120
  * unlit black margin between the desktop's raster and the case; `bezel`
121
121
  * draws it around the screen and puts the classic screen-corner mask on
122
- * the screen's two *top* corners — only the top pair was rounded in the
123
- * framebuffer. Flow, window coordinates and the drag clip all belong to
124
- * the screen, so windows crop at its edge. Inside a bezeled desktop a
125
- * menu bar needs no `rounded` of its own — the desktop's mask lands on
126
- * the same pixels.
122
+ * all four of the screen's corners. Flow, window coordinates and the drag
123
+ * clip all belong to the screen, so windows crop at its edge. Inside a
124
+ * bezeled desktop a menu bar needs no `rounded` of its own — the desktop's
125
+ * top pair lands on the same pixels.
127
126
  */
128
127
  bezel: number;
129
128
  /**
@@ -165,16 +165,15 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I]
165
165
  .drag-surface > * {
166
166
  z-index: ${N};
167
167
  }
168
- /* With a bezel, the screen's top corners wear the SCREEN_CORNER mask,
169
- rounding into the surrounding black — the top pair only, because the
170
- classic framebuffer masked only those; the raster's bottom corners
171
- ran square. Children of .screen, so they anchor to the raster's own
172
- corners (over a slotted menu bar's, which sit in the same place). The
173
- hardware mask was in front of every pixel — a window dragged into a
174
- corner slides under it — hence the maximal z-index. */
168
+ /* With a bezel, the screen's four corners wear the SCREEN_CORNER mask,
169
+ rounding into the surrounding black; the bottom pair is the same
170
+ staircase mirrored vertically. Children of .screen, so they anchor to
171
+ the raster's own corners (the top pair over a slotted menu bar's,
172
+ which sit in the same place). The hardware mask was in front of every
173
+ pixel — a window dragged into a corner slides under it — hence the
174
+ maximal z-index. */
175
175
  .corner {
176
176
  position: absolute;
177
- top: 0;
178
177
  width: calc(var(--vf-scale, 1) * ${S[0]}px);
179
178
  height: calc(var(--vf-scale, 1) * ${S.length}px);
180
179
  background: var(--vf-black, #000);
@@ -182,13 +181,25 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I]
182
181
  z-index: 2147483647;
183
182
  }
184
183
  .corner.tl {
184
+ top: 0;
185
185
  left: 0;
186
186
  clip-path: ${D(C(S, "left"))};
187
187
  }
188
188
  .corner.tr {
189
+ top: 0;
189
190
  right: 0;
190
191
  clip-path: ${D(C(S, "right"))};
191
192
  }
193
+ .corner.bl {
194
+ bottom: 0;
195
+ left: 0;
196
+ clip-path: ${D(C(S, "left", "bottom"))};
197
+ }
198
+ .corner.br {
199
+ bottom: 0;
200
+ right: 0;
201
+ clip-path: ${D(C(S, "right", "bottom"))};
202
+ }
192
203
  `
193
204
  ];
194
205
  }
@@ -316,7 +327,9 @@ var j = 1e6, M = 2 * j, N = 2000001, P = 512, F = 342, I = "gray-50", L = m(f[I]
316
327
  <slot @slotchange=${this._onSlotChange}></slot>
317
328
  <div class="drag-surface"></div>
318
329
  ${this.bezel > 0 ? E`<div class="corner tl"></div>
319
- <div class="corner tr"></div>` : null}
330
+ <div class="corner tr"></div>
331
+ <div class="corner bl"></div>
332
+ <div class="corner br"></div>` : null}
320
333
  </div>
321
334
  </div>
322
335
  `;
@@ -1,5 +1,6 @@
1
1
  import { LitElement } from 'lit';
2
2
  import type { PropertyValues } from 'lit';
3
+ import type { VfSelectSize } from './vf-select.js';
3
4
  declare const VfOption_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
4
5
  /**
5
6
  * `<vf-option>` — a single choice inside a `<vf-select>` popup menu.
@@ -8,8 +9,10 @@ declare const VfOption_base: (new (...args: any[]) => import("../position.js").V
8
9
  * its slotted label at menu-item metrics (16px row — the pill's content height,
9
10
  * so a selected option overlays the closed pill exactly; the left checkmark gutter is
10
11
  * `--vf-select-gutter`, shared with the closed control's left inset so the value
11
- * doesn't shift on open). The parent select manages `selected` and the transient
12
- * `active` highlight, and slots this element into its popup panel.
12
+ * doesn't shift on open). The parent select manages `selected`, the transient
13
+ * `active` highlight and `size`, and slots this element into its popup panel.
14
+ * Under `size="small"` the row is the small pill's 10px content height, in the
15
+ * body face, and clips its own box.
13
16
  *
14
17
  * The host carries `role="option"` with `aria-selected`/`aria-disabled`.
15
18
  *
@@ -46,6 +49,8 @@ export declare class VfOption extends VfOption_base {
46
49
  * Managed by the parent `<vf-select>`; not part of the authoring API.
47
50
  */
48
51
  active: boolean;
52
+ /** The parent select's `size`. Managed by the parent. */
53
+ size: VfSelectSize;
49
54
  constructor();
50
55
  connectedCallback(): void;
51
56
  protected updated(changed: PropertyValues<this>): void;
@@ -2,18 +2,19 @@ import { vfElement as e } from "../define.js";
2
2
  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
- import { vfDisplay as i } from "../styles/recipes/display-face.js";
6
- import { vfBase as a } from "../styles/recipes/host.js";
7
- import { CHECKMARK as o, glyphSvg as s } from "../glyphs.js";
8
- import { LitElement as c, css as l, html as u } from "lit";
9
- import { property as d } from "lit/decorators.js";
5
+ import { vfBodyDecls as i } from "../styles/recipes/body-face.js";
6
+ import { vfDisplay as a } from "../styles/recipes/display-face.js";
7
+ import { vfBase as o } from "../styles/recipes/host.js";
8
+ import { CHECKMARK as s, glyphSvg as c } from "../glyphs.js";
9
+ import { LitElement as l, css as u, html as d } from "lit";
10
+ import { property as f } from "lit/decorators.js";
10
11
  //#region src/components/vf-option.ts
11
- var f = class extends r(c) {
12
+ var p = class extends r(l) {
12
13
  static {
13
14
  this.styles = [
15
+ o,
14
16
  a,
15
- i,
16
- l`
17
+ u`
17
18
  :host {
18
19
  position: relative;
19
20
  display: flex;
@@ -43,6 +44,18 @@ var f = class extends r(c) {
43
44
  cursor: var(--vf-cursor, default);
44
45
  outline: none;
45
46
  }
47
+ /* The small row: the select restates --vf-popup-height on itself, so the
48
+ height above already follows it. The line box and padding match the
49
+ small pill's label (see vf-select's .value): 8 rows above the baseline,
50
+ 2 below it for the descenders. The row clips its own box, so a mark
51
+ above a capital doesn't draw into the row above, and the list clips
52
+ what the closed pill clips. */
53
+ :host([size='small']) {
54
+ ${i}
55
+ line-height: calc(var(--vf-scale, 1) * (var(--vf-popup-height, 12px) - 4px));
56
+ padding-bottom: calc(var(--vf-scale, 1) * 2px);
57
+ overflow: clip;
58
+ }
46
59
  /* Hover/keyboard highlight — classic full-row inversion. The parent
47
60
  vf-select drives [active] for both pointer and keyboard so only one
48
61
  row is ever highlighted at a time. */
@@ -81,6 +94,11 @@ var f = class extends r(c) {
81
94
  width: calc(var(--vf-scale, 1) * 9px);
82
95
  height: calc(var(--vf-scale, 1) * 9px);
83
96
  }
97
+ /* The ✓'s 8 ink rows centered in the 10px row, 1 above and 1 below. Its
98
+ top is level with the capitals' top, as at row 3 above. */
99
+ :host([size='small']) .check {
100
+ top: calc(var(--vf-scale, 1) * 1px);
101
+ }
84
102
  :host([selected]) .check {
85
103
  visibility: visible;
86
104
  }
@@ -89,7 +107,7 @@ var f = class extends r(c) {
89
107
  }
90
108
  #e;
91
109
  constructor() {
92
- super(), this.scale = new t(this), this.value = "", this.disabled = !1, this.selected = !1, this.active = !1, this.#e = this.attachInternals(), this.#e.role = "option";
110
+ super(), this.scale = new t(this), this.value = "", this.disabled = !1, this.selected = !1, this.active = !1, this.size = "regular", this.#e = this.attachInternals(), this.#e.role = "option";
93
111
  }
94
112
  connectedCallback() {
95
113
  super.connectedCallback(), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "-1");
@@ -98,23 +116,23 @@ var f = class extends r(c) {
98
116
  e.has("selected") && (this.#e.ariaSelected = this.selected ? "true" : "false"), e.has("disabled") && (this.#e.ariaDisabled = this.disabled ? "true" : null);
99
117
  }
100
118
  render() {
101
- return u`
119
+ return d`
102
120
  <span class="check" part="check" aria-hidden="true"
103
- >${s(o, "checkmark")}</span
121
+ >${c(s, "checkmark")}</span
104
122
  >
105
123
  <slot></slot>
106
124
  `;
107
125
  }
108
126
  };
109
- n([d()], f.prototype, "value", void 0), n([d({
127
+ n([f()], p.prototype, "value", void 0), n([f({
110
128
  type: Boolean,
111
129
  reflect: !0
112
- })], f.prototype, "disabled", void 0), n([d({
130
+ })], p.prototype, "disabled", void 0), n([f({
113
131
  type: Boolean,
114
132
  reflect: !0
115
- })], f.prototype, "selected", void 0), n([d({
133
+ })], p.prototype, "selected", void 0), n([f({
116
134
  type: Boolean,
117
135
  reflect: !0
118
- })], f.prototype, "active", void 0), f = n([e("vf-option")], f);
136
+ })], p.prototype, "active", void 0), n([f({ reflect: !0 })], p.prototype, "size", void 0), p = n([e("vf-option")], p);
119
137
  //#endregion
120
- export { f as VfOption };
138
+ export { p as VfOption };
@@ -1,5 +1,7 @@
1
1
  import type { PropertyValues } from 'lit';
2
2
  import { VfShadowRoleControl } from '../form-control.js';
3
+ /** The two pill sizes: the display face at 18px, or the body face at 12px. */
4
+ export type VfSelectSize = 'regular' | 'small';
3
5
  declare const VfSelect_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof VfShadowRoleControl;
4
6
  /**
5
7
  * `<vf-select>` — the classic System 7 popup menu control ("Macintosh HD ▼").
@@ -36,6 +38,13 @@ declare const VfSelect_base: (new (...args: any[]) => import("../position.js").V
36
38
  * end the list no longer reaches: the exact travel it will roll through, in
37
39
  * either direction. See src/popup-overflow.ts.
38
40
  *
41
+ * `size="small"` sets the pill and its rows in the body face: a 12px pill
42
+ * (`--vf-popup-height-small`) over 10px rows, the baseline 8 rows down so the
43
+ * face's 2-row descenders end on the last content row. Its ▼ and scroll
44
+ * arrows are the 9×5 `CARET_DOWN_SMALL` / `CARET_UP_SMALL`; the ✓ and the
45
+ * horizontal insets are the regular pill's. Marks above a capital (É, Å, Ñ)
46
+ * reach past the 8 rows above the baseline and are clipped.
47
+ *
39
48
  * Keyboard: Space/Enter/ArrowDown open; while open ArrowUp/ArrowDown move the
40
49
  * highlight, Home/End jump, Enter/Space select, Escape cancels. Selecting an
41
50
  * item plays the classic inversion blink (~250 ms) before closing. Keyboard
@@ -63,6 +72,8 @@ declare const VfSelect_base: (new (...args: any[]) => import("../position.js").V
63
72
  * in its edge row slots.
64
73
  * @cssprop [--vf-popup-height=18px] - `vf-select` pill (border box; its 1px
65
74
  * hard shadow makes the sheet's 157×19 ink box)
75
+ * @cssprop [--vf-popup-height-small=12px] - `vf-select[size="small"]` pill
76
+ * (border box; its rows are this less the two borders)
66
77
  * @cssprop [--vf-popup-inset-top=4px] - room a clipped popup panel keeps clear
67
78
  * at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to
68
79
  * clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4
@@ -73,20 +84,17 @@ declare const VfSelect_base: (new (...args: any[]) => import("../position.js").V
73
84
  * on open)
74
85
  */
75
86
  export declare class VfSelect extends VfSelect_base {
76
- /**
77
- * Fallback height of one option row — the pill's *content* height
78
- * (`--vf-popup-height` 18px minus its two 1px borders). Used to overlay the
79
- * selected row's white cell exactly on the closed pill. `positionPanel`
80
- * prefers the row's *rendered* height so a re-themed `--vf-popup-height`
81
- * keeps the overlay aligned; this is the no-options fallback and must match
82
- * `vf-option`'s default row height.
83
- */
84
- private static readonly ITEM_HEIGHT;
85
87
  static styles: import("lit").CSSResult[];
86
88
  /** Value of the selected option. Adopts the first enabled option if unset. */
87
89
  value: string;
88
90
  /** Form field name used when submitting the associated form. */
89
91
  name: string;
92
+ /**
93
+ * `regular` (the 18px pill in the display face) or `small` (12px, in the
94
+ * body face). Any other value renders as `regular`. The select passes it to
95
+ * its options.
96
+ */
97
+ size: VfSelectSize;
90
98
  /**
91
99
  * Accessible name for the combobox control (`aria-label`). Left empty, the
92
100
  * name falls back to whatever the host carries — `aria-labelledby`,
@@ -202,6 +210,8 @@ export declare class VfSelect extends VfSelect_base {
202
210
  private optionValue;
203
211
  /** Marks the option matching `value` as selected. */
204
212
  private applySelection;
213
+ /** Passes the pill size to every option; anything but `small` is regular. */
214
+ private applySize;
205
215
  private handleSlotChange;
206
216
  private openPanel;
207
217
  /**