vintage-frames 0.15.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/custom-elements.json +907 -99
  2. package/dist/chrome.d.ts +10 -1
  3. package/dist/chrome.js +8 -3
  4. package/dist/components/vf-desktop.d.ts +5 -2
  5. package/dist/components/vf-desktop.js +5 -5
  6. package/dist/components/vf-dialog.d.ts +14 -8
  7. package/dist/components/vf-dialog.js +27 -27
  8. package/dist/components/vf-menu-bar.js +9 -10
  9. package/dist/components/vf-menu-item.js +18 -13
  10. package/dist/components/vf-menu.d.ts +8 -3
  11. package/dist/components/vf-menu.js +85 -61
  12. package/dist/components/vf-number-field.d.ts +4 -0
  13. package/dist/components/vf-number-field.js +28 -25
  14. package/dist/components/vf-paragraph.d.ts +3 -1
  15. package/dist/components/vf-paragraph.js +7 -0
  16. package/dist/components/vf-scroll-area.d.ts +16 -1
  17. package/dist/components/vf-scroll-area.js +39 -29
  18. package/dist/components/vf-select.d.ts +5 -4
  19. package/dist/components/vf-select.js +26 -17
  20. package/dist/components/vf-text-field.d.ts +5 -5
  21. package/dist/components/vf-text-field.js +1 -1
  22. package/dist/components/vf-window.d.ts +22 -5
  23. package/dist/components/vf-window.js +113 -98
  24. package/dist/cursor.d.ts +8 -0
  25. package/dist/cursor.js +70 -73
  26. package/dist/index.d.ts +2 -1
  27. package/dist/modal-dialog.d.ts +27 -5
  28. package/dist/modal-dialog.js +63 -51
  29. package/dist/shell/catalog.d.ts +1 -1
  30. package/dist/shell/catalog.js +32 -18
  31. package/dist/shell/finder.d.ts +6 -1
  32. package/dist/shell/finder.js +182 -176
  33. package/dist/shell/index.d.ts +1 -1
  34. package/dist/shell/pure.d.ts +10 -0
  35. package/dist/shell/pure.js +4 -0
  36. package/dist/shell/shell.d.ts +16 -3
  37. package/dist/shell/shell.js +141 -126
  38. package/dist/shell/windows.d.ts +57 -13
  39. package/dist/shell/windows.js +214 -154
  40. package/dist/text-control.d.ts +46 -3
  41. package/dist/text-control.js +33 -5
  42. package/dist/top-layer.d.ts +13 -0
  43. package/dist/top-layer.js +16 -0
  44. package/docs/SPEC.md +25 -24
  45. package/editor/vscode.html-custom-data.json +36 -11
  46. package/editor/web-types.json +81 -23
  47. package/package.json +5 -1
@@ -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\n**Hidden windows.** A window with `hidden` — closed by a page that hides\nits windows rather than removing them, through `vf-window.hide()` or the\nattribute itself — never holds the active state. One slotted hidden waits\nto be shown; `bringToFront()` on one gives it its place in the stack and\nactivates nothing; the holder hiding hands the state to the topmost shown\ndocument window, or to none. A window shown into a tier where none is\nactive, unless the tier was deliberately deactivated, takes it.\nstackingOrder lists the windows as they stand, bottom-most first.\n\n**The work area.** A slotted `vf-menu-bar` along the top takes its band\noff the screen: workArea is what is left, and the gestures on the\nscreen stay in it — a window dragged up stops with its title bar under the\nbar, where it can still be grabbed, and an icon dropped, nudged or walked\non the desktop lands below the bar. `window-top` deepens the area for\nwindows alone (windowArea), for a page with a strip of its own\nunder the bar. A gesture asks for the box it is clamped into with\n`vf-placement-bounds-request` (bubbles, non-composed), the drag surface's\nhandshake, and the desktop answers for the hosts placed on its screen.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its four corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, a repeating tile drawn at the display's resolution, 1-bit at every\ndensity and zoom (src/pattern-fill.ts).\n\n**The drag surface.** The Finder dragged an icon as a dotted outline drawn\non the *screen*, clipped at its edge and phase-locked to its raster, so\nthe screen hosts the layer that outline draws on: a full-bleed child of\nthe screen, `pointer-events: none` (never a hit for the page's\n`elementsFromPoint`), whose children paint one tier above the menu bar\nand under the corner mask — the layer itself is deliberately no stacking\ncontext, since a blend inside one would composite against nothing. An\nicon reaches it without an import, the menu-handshake idiom: on a drag's\nfirst step it dispatches `vf-drag-surface-request` (bubbles, non-composed,\n`detail.surface` null), and the nearest desktop on its light-DOM path\nfills the detail with the layer. A window asks the same way and draws\nthere with the same pen: its zoom rects when it opens from a rect\n(`vf-window.show({ from })`), its outline under an `outline-drag`. Not the\ntop layer: stable Safari cannot\nblend an element there against the page (src/cursor.ts), and a second\nkit entry in the top layer would need a re-promotion handshake.\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).",
2566
+ "description": "`<vf-desktop>` — the full-bleed classic desktop container.\n\nRenders the desktop pattern — the classic 50% dither by default, or any of\nthe standard patterns by name (`pattern`, System 7's General Controls\nsetting) — and manages the stacking order and `active` state of slotted\n`vf-window` children: a `pointerdown` or\n`focusin` (keyboard focus) anywhere inside a window brings it to the front\nand makes it the single active window. A press on a title bar with ⌘ held\nraises nothing, so a background window is dragged where it stands in the\nstack. The windows' light-DOM order is kept\nin step with the stacking order (bottom-most first, synced in a task once\nany pointer gesture has ended), so tabbing walks the stack the way the eye\ndoes and Shift+Tab is its exact mirror.\n\nUtility windows (`vf-window[variant=\"utility\"]`) stack in a floating tier\nabove every document-tier window, restack only among themselves, and stand\noutside the single-active invariant entirely — clicking a palette neither\ndeactivates the active document window nor greys the palette, exactly as\nSystem 7's floating windoids behaved while their application was frontmost.\nA slotted `vf-menu-bar` (or a free-standing `vf-menu`) sits on a tier\nabove both, so its dropped menus cover palettes and document windows\nalike; only the screen-corner mask is in front of it.\n\n**Deactivation.** On a real System 7 machine clicking the desktop clicked\nthe *Finder* — the frontmost application's windows lost their stripes.\nclearActive is that gesture's handler: it clears `active` from\nthe whole document tier, and **zero active windows is a legal state**,\nheld until a press or keyboard focus re-enters a document window (or a\nnew one is slotted, which activates it — opening a window brings its\napplication forward). The desktop never takes this decision itself: its\nfurniture is slotted light DOM (an icon layer, say), so only the page\nknows which of its children — or which presses on the bare dither — mean\n\"the Finder\", and it routes those through `clearActive()`. Left alone,\nthe classic always-one-active behavior is unchanged. activeWindow\nreads the current holder, and every change of holder — including to and\nfrom none — fires `vf-activate`.\n\n**Hidden windows.** A window with `hidden` — closed by a page that hides\nits windows rather than removing them, through `vf-window.hide()` or the\nattribute itself — never holds the active state. One slotted hidden waits\nto be shown; `bringToFront()` on one gives it its place in the stack and\nactivates nothing; the holder hiding hands the state to the topmost shown\ndocument window, or to none. A window shown into a tier where none is\nactive, unless the tier was deliberately deactivated, takes it.\nstackingOrder lists the windows as they stand, bottom-most first.\n\n**The work area.** A slotted `vf-menu-bar` along the top takes its band\noff the screen: workArea is what is left, and the gestures on the\nscreen stay in it — a window dragged up stops with its title bar under the\nbar, where it can still be grabbed, and an icon dropped, nudged or walked\non the desktop lands below the bar. `window-top` deepens the area for\nwindows alone (windowArea), for a page with a strip of its own\nunder the bar. A gesture asks for the box it is clamped into with\n`vf-placement-bounds-request` (bubbles, non-composed), the drag surface's\nhandshake, and the desktop answers for the hosts placed on its screen.\n\nThe desktop is a raster with an explicit size, always: **`width` and\n`height`**, in system px, the way a WIND resource declared a window's —\nthe host box renders at the declared screen plus `2 × bezel` per axis, a\nwhole number of system pixels by construction (default 512×342, the\ncompact Mac's screen). Pure CSS sizing is not supported; the page sets\nthe numbers — directly, or via VfDesktop.fitWithin on\n`resize`/`onScaleChange` for a viewport-filling desktop — and positions\nthe sized box with its own stylesheet, keeping any sub-system-pixel\nslack on its side. `bezel` (system px) draws the black screen surround —\nthe CRT's unlit margin — around the screen, rounding its four corners\nwith the classic corner mask.\n\n**`pattern`** names the desktop pattern — `gray-50` (the dither) by\ndefault, any of the 38 standard patterns (docs/PATTERNS.md), or sixteen\nhex digits stating a custom 8×8 pattern, as on `vf-container`. It is\npainted as the screen's own background: black ink on an opaque white\npaper, a repeating tile drawn at the display's resolution, 1-bit at every\ndensity and zoom (src/pattern-fill.ts).\n\n**The drag surface.** The Finder dragged an icon as a dotted outline drawn\non the *screen*, clipped at its edge and phase-locked to its raster, so\nthe screen hosts the layer that outline draws on: a full-bleed child of\nthe screen, `pointer-events: none` (never a hit for the page's\n`elementsFromPoint`), whose children paint one tier above the menu bar\nand under the corner mask — the layer itself is deliberately no stacking\ncontext, since a blend inside one would composite against nothing. An\nicon reaches it without an import, the menu-handshake idiom: on a drag's\nfirst step it dispatches `vf-drag-surface-request` (bubbles, non-composed,\n`detail.surface` null), and the nearest desktop on its light-DOM path\nfills the detail with the layer. A window asks the same way and draws\nthere with the same pen: its zoom rects when it opens from a rect\n(`vf-window.show({ from })`), its outline under an `outline-drag`. Not the\ntop layer: stable Safari cannot\nblend an element there against the page (src/cursor.ts), and a second\nkit entry in the top layer would need a re-promotion handshake.\n\nCustom properties:\n- `--vf-desktop-pattern` — a consumer's own tile art in place of the\n pattern (the kit's default is a 1-bit 50% checker, opaque\n black-on-white on a 30-system-px tile). Set, it wins over `pattern` and\n renders as a placed tile grid at that same 30-px geometry\n (src/tile-grid.ts); a token swapped at runtime without touching the\n component wants a `requestUpdate()`.\n- `--vf-desktop` — base color painted *under* the pattern (default\n `#808080`). The pattern's paper is opaque, so this only becomes visible\n when `--vf-desktop-pattern` is overridden with a tile that has\n transparent cells (or with `none`).",
2567
2567
  "name": "VfDesktop",
2568
2568
  "cssProperties": [
2569
2569
  {
@@ -2626,8 +2626,9 @@
2626
2626
  "text": "string | null | undefined"
2627
2627
  },
2628
2628
  "default": "'gray-50'",
2629
- "description": "The desktop pattern — System 7's General Controls setting. A library\npattern by name (`gray-50`, the classic dither, by default; `gray-75`,\n`bricks`, … — docs/PATTERNS.md) or sixteen hex digits stating a custom\n8×8 pattern, as on `vf-container`. Painted black on opaque white over\nthe whole screen, 1-bit at every density and zoom. A\n`--vf-desktop-pattern` token override still wins and renders the\nconsumer's tile as a placed grid; an unrecognized value warns once and\nkeeps the dither.",
2630
- "attribute": "pattern"
2629
+ "description": "The desktop pattern — System 7's General Controls setting. A library\npattern by name (`gray-50`, the classic dither, by default; `gray-75`,\n`bricks`, … — docs/PATTERNS.md) or sixteen hex digits stating a custom\n8×8 pattern, as on `vf-container`. Painted black on opaque white over\nthe whole screen, 1-bit at every density and zoom. A\n`--vf-desktop-pattern` token override still wins and renders the\nconsumer's tile as a placed grid; an unrecognized value warns once and\nkeeps the dither. Reflects, so a change can be observed on the\nattribute.",
2630
+ "attribute": "pattern",
2631
+ "reflects": true
2631
2632
  },
2632
2633
  {
2633
2634
  "kind": "field",
@@ -3298,7 +3299,7 @@
3298
3299
  "text": "string | null | undefined"
3299
3300
  },
3300
3301
  "default": "DEFAULT_PATTERN",
3301
- "description": "The desktop pattern — System 7's General Controls setting. A library\npattern by name (`gray-50`, the classic dither, by default; `gray-75`,\n`bricks`, … — docs/PATTERNS.md) or sixteen hex digits stating a custom\n8×8 pattern, as on `vf-container`. Painted black on opaque white over\nthe whole screen, 1-bit at every density and zoom. A\n`--vf-desktop-pattern` token override still wins and renders the\nconsumer's tile as a placed grid; an unrecognized value warns once and\nkeeps the dither.",
3302
+ "description": "The desktop pattern — System 7's General Controls setting. A library\npattern by name (`gray-50`, the classic dither, by default; `gray-75`,\n`bricks`, … — docs/PATTERNS.md) or sixteen hex digits stating a custom\n8×8 pattern, as on `vf-container`. Painted black on opaque white over\nthe whole screen, 1-bit at every density and zoom. A\n`--vf-desktop-pattern` token override still wins and renders the\nconsumer's tile as a placed grid; an unrecognized value warns once and\nkeeps the dither. Reflects, so a change can be observed on the\nattribute.",
3302
3303
  "fieldName": "pattern"
3303
3304
  },
3304
3305
  {
@@ -3398,7 +3399,7 @@
3398
3399
  "declarations": [
3399
3400
  {
3400
3401
  "kind": "class",
3401
- "description": "`<vf-dialog>` — the System 7 modal dialog shell.\n\nTwo chromes, one modal lifecycle (native `<dialog>` for top-layer rendering\nand focus trapping, with a fully transparent backdrop — no dimming). Both\nare the same dBoxProc double frame — 1px outer rule, 2px gap, 2px inner\nband, no shadow (vfModalFrame):\n\n- **Default:** the movable modal (movableDBoxProc) — the striped title bar\n set into the top of that frame, with a centered title over a white body.\n Drag the title bar to move it. `closable` adds the standard close box\n (left of the bar) — the HIG's own figures disagree on whether a movable\n modal carries one (Figure 5-1 says yes, Figure 6-1 and the Chapter 6 text\n say no), so the component enables either reading rather than enforcing\n one.\n- **`frame=\"plain\"`:** the modal dialog box — the bare frame, no title bar —\n and immovable, like the original. With no bar, `heading` only names the\n dialog and `closable` is ignored.\n\nOpen it with `show()` (or set the `open` attribute/property); close with\n`close()`. Escape closes it and fires `vf-close` with\n`{ reason: 'escape' }`; the close box and programmatic closing fire\n`{ reason: 'close' }`. With `light-dismiss`, a click outside the frame\ncloses it too, with `{ reason: 'outside' }` — for the About box; off by\ndefault, since the classic modal ignored an outside click.\n\nAnswers: a `<form method=\"dialog\">` inside it closes it with the\nsubmitting button's `value` as `returnValue`, and `close(value)` does the\nsame. `vf-close` carries it as `detail.returnValue`, null when the close\ncarried none (Escape, a click outside, the close box).\n\nKeyboard, the classic Dialog Manager's two rules (VfModalDialog):\non open, focus goes to the first text-entry control — a slotted control\nwith `autofocus` first — or, with none, to the default button\n(`vf-button variant=\"default\"`). Return or Enter activates the default\nbutton from anywhere in the dialog, a focused Cancel included; Space\npresses the focused control. A link keeps its own Enter, and in a\nmulti-line editor Return inserts the newline while the keypad's Enter\nactivates the button.\n\nSlotted children placed with `top`/`left` measure from the content region's\ncorner — the frame's inner edge, below the title bar — and flow content\nstarts at the same corner.",
3402
+ "description": "`<vf-dialog>` — the System 7 modal dialog shell.\n\nTwo chromes, one modal lifecycle (native `<dialog>` for top-layer rendering\nand focus trapping, with a fully transparent backdrop — no dimming). Both\nare the same dBoxProc double frame — 1px outer rule, 2px gap, 2px inner\nband, no shadow (vfModalFrame):\n\n- **Default:** the movable modal (movableDBoxProc) — the striped title bar\n set into the top of that frame, with a centered title over a white body.\n Drag the title bar to move it. `closable` adds the standard close box\n (left of the bar) — the HIG's own figures disagree on whether a movable\n modal carries one (Figure 5-1 says yes, Figure 6-1 and the Chapter 6 text\n say no), so the component enables either reading rather than enforcing\n one.\n- **`frame=\"plain\"`:** the modal dialog box — the bare frame, no title bar —\n and immovable, like the original. With no bar, `heading` only names the\n dialog and `closable` is ignored.\n\nOpen it with `show()` (or set the `open` attribute/property); close with\n`close()`. Escape closes it and fires `vf-close` with\n`{ reason: 'escape' }`; the close box and programmatic closing fire\n`{ reason: 'close' }`. With `light-dismiss`, a click outside the frame\ncloses it too, with `{ reason: 'outside' }` — for the About box; off by\ndefault, since the classic modal ignored an outside click.\n\nAnswers: a `<form method=\"dialog\">` inside it closes it with the\nsubmitting button's `value` as `returnValue`, and `close(value)` does the\nsame. `vf-close` carries it as `detail.returnValue`, null when the close\ncarried none (Escape, a click outside, the close box).\n\nKeyboard, the classic Dialog Manager's two rules (VfModalDialog):\non open, focus goes to the first text-entry control — a slotted control\nwith `autofocus` or `autoselect` first — or, with none, to the default\nbutton (`vf-button variant=\"default\"`). A field marked `autoselect` opens\nwith its whole text selected, on every open. Return or Enter activates\nthe default button from anywhere in the dialog, a focused Cancel\nincluded; Space presses the focused control. A link keeps its own Enter,\nand in a multi-line editor Return inserts the newline while the keypad's\nEnter activates the button.\n\nSlotted children placed with `top`/`left` measure from the content region's\ncorner — the frame's inner edge, below the title bar — and flow content\nstarts at the same corner.",
3402
3403
  "name": "VfDialog",
3403
3404
  "cssProperties": [
3404
3405
  {
@@ -3494,7 +3495,7 @@
3494
3495
  "text": "boolean"
3495
3496
  },
3496
3497
  "default": "false",
3497
- "description": "Show the close box (left side of the title bar). Off by default — the\nbare movable-modal bar. Ignored with `frame=\"plain\"` (no bar). Clicking\nit closes the dialog and fires `vf-close` with `{ reason: 'close' }`.",
3498
+ "description": "Show the close box (left side of the title bar). Off by default — the\nbare movable-modal bar. Ignored with `frame=\"plain\"` (no bar). Clicking\nit closes the dialog and fires `vf-close` with `{ reason: 'close' }` and\nthe modifier keys held on the click, as `vf-window`'s close box does.",
3498
3499
  "attribute": "closable",
3499
3500
  "reflects": true
3500
3501
  },
@@ -3561,7 +3562,15 @@
3561
3562
  "type": {
3562
3563
  "text": "void"
3563
3564
  }
3564
- }
3565
+ },
3566
+ "parameters": [
3567
+ {
3568
+ "name": "event",
3569
+ "type": {
3570
+ "text": "MouseEvent"
3571
+ }
3572
+ }
3573
+ ]
3565
3574
  },
3566
3575
  {
3567
3576
  "kind": "field",
@@ -3753,6 +3762,20 @@
3753
3762
  "module": "src/modal-dialog.ts"
3754
3763
  }
3755
3764
  },
3765
+ {
3766
+ "kind": "field",
3767
+ "name": "#closeKeys",
3768
+ "privacy": "private",
3769
+ "type": {
3770
+ "text": "VfCloseKeys | null"
3771
+ },
3772
+ "default": "null",
3773
+ "description": "The modifier keys a close box's click held, pending for the next native `close` event.",
3774
+ "inheritedFrom": {
3775
+ "name": "VfModalDialog",
3776
+ "module": "src/modal-dialog.ts"
3777
+ }
3778
+ },
3756
3779
  {
3757
3780
  "kind": "field",
3758
3781
  "name": "#onSubmit",
@@ -3810,7 +3833,7 @@
3810
3833
  "text": "HTMLElement | null"
3811
3834
  },
3812
3835
  "privacy": "protected",
3813
- "description": "Where focus lands on open. The classic Dialog Manager put the insertion\npoint in the first editable text item and gave nothing else focus at all;\nthe web needs a focused control for the keyboard to have anywhere to be,\nso with no text field the default button takes it (which is also what\nmakes Return and Space work there without a Tab). In order:\n\n1. a slotted control carrying `autofocus` — the author's say;\n2. the first enabled text-entry control (`vf-text-field`,\n `vf-number-field`, `vf-text-area`, or a native text input/textarea);\n3. the defaultButton;\n4. null — leave the browser's own choice alone.\n\nLeft to itself, `showModal()` focuses the first focusable thing in flat\ntree order, which for a Cancel/OK row is Cancel, and for a body with a\nlink in it is the link — so Return did the one thing a classic dialog's\nReturn never did. Override to choose differently.",
3836
+ "description": "Where focus lands on open. The classic Dialog Manager put the insertion\npoint in the first editable text item and gave nothing else focus at all;\nthe web needs a focused control for the keyboard to have anywhere to be,\nso with no text field the default button takes it (which is also what\nmakes Return and Space work there without a Tab). In order:\n\n1. the first slotted control carrying `autofocus` or `autoselect` — the\n author's say;\n2. the first enabled text-entry control (`vf-text-field`,\n `vf-number-field`, `vf-text-area`, or a native text input/textarea);\n3. the defaultButton;\n4. null — leave the browser's own choice alone.\n\nLeft to itself, `showModal()` focuses the first focusable thing in flat\ntree order, which for a Cancel/OK row is Cancel, and for a body with a\nlink in it is the link — so Return did the one thing a classic dialog's\nReturn never did. Override to choose differently. A target marked\n`autoselect` has its text selected once `vf-show` has fired.",
3814
3837
  "readonly": true,
3815
3838
  "inheritedFrom": {
3816
3839
  "name": "VfModalDialog",
@@ -3823,10 +3846,10 @@
3823
3846
  "privacy": "private",
3824
3847
  "return": {
3825
3848
  "type": {
3826
- "text": "void"
3849
+ "text": "HTMLElement | null"
3827
3850
  }
3828
3851
  },
3829
- "description": "Hand focus to initialFocusTarget, right after `showModal()`'s own\nfocusing steps have run (so this is the last word, not a race).",
3852
+ "description": "Hand focus to initialFocusTarget, right after `showModal()`'s own\nfocusing steps have run (so this is the last word, not a race). Returns\nthe element focused, for `vf-show`.",
3830
3853
  "inheritedFrom": {
3831
3854
  "name": "VfModalDialog",
3832
3855
  "module": "src/modal-dialog.ts"
@@ -3922,6 +3945,29 @@
3922
3945
  "module": "src/modal-dialog.ts"
3923
3946
  }
3924
3947
  },
3948
+ {
3949
+ "kind": "method",
3950
+ "name": "closeFromBox",
3951
+ "privacy": "protected",
3952
+ "return": {
3953
+ "type": {
3954
+ "text": "void"
3955
+ }
3956
+ },
3957
+ "parameters": [
3958
+ {
3959
+ "name": "keys",
3960
+ "type": {
3961
+ "text": "VfCloseKeys"
3962
+ }
3963
+ }
3964
+ ],
3965
+ "description": "Close from a close box, its `vf-close` carrying the modifier keys held on the click.",
3966
+ "inheritedFrom": {
3967
+ "name": "VfModalDialog",
3968
+ "module": "src/modal-dialog.ts"
3969
+ }
3970
+ },
3925
3971
  {
3926
3972
  "kind": "method",
3927
3973
  "name": "#viewport",
@@ -4159,7 +4205,15 @@
4159
4205
  ],
4160
4206
  "events": [
4161
4207
  {
4162
- "description": "Dialog closed. Detail `{ reason: 'escape' | 'close' | 'outside', returnValue: string | null }` — `'outside'` only under `light-dismiss`.",
4208
+ "description": "Dialog opened, placed and given its initial focus. Detail `{ focus }`, the element focused: the moment to measure copy that varies. A field marked `autoselect` has its text selected after it.",
4209
+ "name": "vf-show",
4210
+ "inheritedFrom": {
4211
+ "name": "VfModalDialog",
4212
+ "module": "src/modal-dialog.ts"
4213
+ }
4214
+ },
4215
+ {
4216
+ "description": "Dialog closed. Detail `{ reason: 'escape' | 'close' | 'outside', returnValue: string | null }` — `'outside'` only under `light-dismiss` — plus `altKey`, `shiftKey`, `metaKey` and `ctrlKey` when the close box closed it.",
4163
4217
  "name": "vf-close",
4164
4218
  "inheritedFrom": {
4165
4219
  "name": "VfModalDialog",
@@ -4192,7 +4246,7 @@
4192
4246
  "text": "boolean"
4193
4247
  },
4194
4248
  "default": "false",
4195
- "description": "Show the close box (left side of the title bar). Off by default — the\nbare movable-modal bar. Ignored with `frame=\"plain\"` (no bar). Clicking\nit closes the dialog and fires `vf-close` with `{ reason: 'close' }`.",
4249
+ "description": "Show the close box (left side of the title bar). Off by default — the\nbare movable-modal bar. Ignored with `frame=\"plain\"` (no bar). Clicking\nit closes the dialog and fires `vf-close` with `{ reason: 'close' }` and\nthe modifier keys held on the click, as `vf-window`'s close box does.",
4196
4250
  "fieldName": "closable"
4197
4251
  },
4198
4252
  {
@@ -9309,7 +9363,7 @@
9309
9363
  "name": ""
9310
9364
  },
9311
9365
  {
9312
- "description": "Replaces the `label` text in the bar — e.g. a `vf-img` apple icon for the Apple menu. Keep the `label` attribute set too: it stays the menu's accessible name (the bar item's `aria-label` and the panel's) when the visible title is an image.",
9366
+ "description": "Replaces the `label` text in the bar — e.g. a `vf-img` apple icon for the Apple menu. An icon (`vf-img`, `img`, `svg`, `picture` or `canvas`) is drawn in a 16×16 cell and placed for one: 6 system px into its plate, 6 short of the plate's end, on the plate's top row. Text keeps the text title's place. Keep the `label` attribute set too: it stays the menu's accessible name (the bar item's `aria-label` and the panel's) when the visible title is an image.",
9313
9367
  "name": "label"
9314
9368
  }
9315
9369
  ],
@@ -9386,6 +9440,21 @@
9386
9440
  },
9387
9441
  "privacy": "private"
9388
9442
  },
9443
+ {
9444
+ "kind": "field",
9445
+ "name": "_artTitle",
9446
+ "type": {
9447
+ "text": "boolean"
9448
+ },
9449
+ "privacy": "private",
9450
+ "default": "false",
9451
+ "description": "Whether the title is art — only images in the `label` slot — rather than text."
9452
+ },
9453
+ {
9454
+ "kind": "field",
9455
+ "name": "#onLabelSlotChange",
9456
+ "privacy": "private"
9457
+ },
9389
9458
  {
9390
9459
  "kind": "field",
9391
9460
  "name": "_assignedItems",
@@ -9966,6 +10035,48 @@
9966
10035
  }
9967
10036
  ]
9968
10037
  },
10038
+ {
10039
+ "kind": "method",
10040
+ "name": "#fit",
10041
+ "privacy": "private",
10042
+ "return": {
10043
+ "type": {
10044
+ "text": "string"
10045
+ }
10046
+ },
10047
+ "parameters": [
10048
+ {
10049
+ "name": "n",
10050
+ "type": {
10051
+ "text": "number"
10052
+ }
10053
+ }
10054
+ ],
10055
+ "description": "`n` clamped and rounded to the step's precision, as text."
10056
+ },
10057
+ {
10058
+ "kind": "method",
10059
+ "name": "committedText",
10060
+ "privacy": "protected",
10061
+ "return": {
10062
+ "type": {
10063
+ "text": "string"
10064
+ }
10065
+ },
10066
+ "parameters": [
10067
+ {
10068
+ "name": "raw",
10069
+ "type": {
10070
+ "text": "string"
10071
+ }
10072
+ }
10073
+ ],
10074
+ "description": "Typed text clamps and rounds when it is a number; otherwise it stays as typed.",
10075
+ "inheritedFrom": {
10076
+ "name": "VfTextControlBase",
10077
+ "module": "src/text-control.ts"
10078
+ }
10079
+ },
9969
10080
  {
9970
10081
  "kind": "method",
9971
10082
  "name": "#commit",
@@ -9983,7 +10094,7 @@
9983
10094
  }
9984
10095
  }
9985
10096
  ],
9986
- "description": "Clamp + round to the step's precision, store, and announce a change — but\nonly when the value actually changes, so autorepeat held against a bound\n(or a keyboard step already at min/max) doesn't fire a redundant\n`vf-change` on every 60ms tick."
10097
+ "description": "Step to `n`, clamped and rounded, and announce a change — but\nonly when the value actually changes, so autorepeat held against a bound\n(or a keyboard step already at min/max) doesn't fire a redundant\n`vf-change` on every 60ms tick."
9987
10098
  },
9988
10099
  {
9989
10100
  "kind": "method",
@@ -10005,8 +10116,8 @@
10005
10116
  },
10006
10117
  {
10007
10118
  "kind": "method",
10008
- "name": "#emit",
10009
- "privacy": "private",
10119
+ "name": "emitValue",
10120
+ "privacy": "protected",
10010
10121
  "return": {
10011
10122
  "type": {
10012
10123
  "text": "void"
@@ -10018,8 +10129,20 @@
10018
10129
  "type": {
10019
10130
  "text": "'vf-input' | 'vf-change'"
10020
10131
  }
10132
+ },
10133
+ {
10134
+ "name": "detail",
10135
+ "default": "{ value: this.value, valueAsNumber: this.#parse() }",
10136
+ "type": {
10137
+ "text": "Record<string, unknown>"
10138
+ }
10021
10139
  }
10022
- ]
10140
+ ],
10141
+ "description": "Every value event carries `valueAsNumber` too.",
10142
+ "inheritedFrom": {
10143
+ "name": "VfTextControlBase",
10144
+ "module": "src/text-control.ts"
10145
+ }
10023
10146
  },
10024
10147
  {
10025
10148
  "kind": "method",
@@ -10069,11 +10192,6 @@
10069
10192
  "name": "#onInput",
10070
10193
  "privacy": "private"
10071
10194
  },
10072
- {
10073
- "kind": "field",
10074
- "name": "#onChange",
10075
- "privacy": "private"
10076
- },
10077
10195
  {
10078
10196
  "kind": "field",
10079
10197
  "name": "top",
@@ -10186,6 +10304,21 @@
10186
10304
  "module": "src/text-control.ts"
10187
10305
  }
10188
10306
  },
10307
+ {
10308
+ "kind": "field",
10309
+ "name": "autoselect",
10310
+ "type": {
10311
+ "text": "boolean"
10312
+ },
10313
+ "default": "false",
10314
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
10315
+ "attribute": "autoselect",
10316
+ "reflects": true,
10317
+ "inheritedFrom": {
10318
+ "name": "VfTextControlBase",
10319
+ "module": "src/text-control.ts"
10320
+ }
10321
+ },
10189
10322
  {
10190
10323
  "kind": "field",
10191
10324
  "name": "name",
@@ -10318,6 +10451,71 @@
10318
10451
  "module": "src/text-control.ts"
10319
10452
  }
10320
10453
  },
10454
+ {
10455
+ "kind": "field",
10456
+ "name": "committed",
10457
+ "type": {
10458
+ "text": "string | null"
10459
+ },
10460
+ "privacy": "protected",
10461
+ "default": "null",
10462
+ "description": "The text as last committed: taken when the field gains focus, then at\neach commit. A commit that brings nothing new isn't announced, so the\nnative `change` that follows a Return commit, or a step, is not a second\none.",
10463
+ "inheritedFrom": {
10464
+ "name": "VfTextControlBase",
10465
+ "module": "src/text-control.ts"
10466
+ }
10467
+ },
10468
+ {
10469
+ "kind": "field",
10470
+ "name": "control",
10471
+ "type": {
10472
+ "text": "HTMLInputElement | HTMLTextAreaElement | null"
10473
+ },
10474
+ "privacy": "protected",
10475
+ "description": "The inner native control every field renders, tagged `vf-field`.",
10476
+ "readonly": true,
10477
+ "inheritedFrom": {
10478
+ "name": "VfTextControlBase",
10479
+ "module": "src/text-control.ts"
10480
+ }
10481
+ },
10482
+ {
10483
+ "kind": "method",
10484
+ "name": "focus",
10485
+ "return": {
10486
+ "type": {
10487
+ "text": "void"
10488
+ }
10489
+ },
10490
+ "parameters": [
10491
+ {
10492
+ "name": "options",
10493
+ "optional": true,
10494
+ "type": {
10495
+ "text": "FocusOptions"
10496
+ }
10497
+ }
10498
+ ],
10499
+ "description": "Focuses the inner control, keeping its caret where it was. Chromium\nselects all of an input's text when the host hands the focus on, as a Tab\ndoes; `select()` and autoselect are how a field opens selected.",
10500
+ "inheritedFrom": {
10501
+ "name": "VfTextControlBase",
10502
+ "module": "src/text-control.ts"
10503
+ }
10504
+ },
10505
+ {
10506
+ "kind": "method",
10507
+ "name": "select",
10508
+ "return": {
10509
+ "type": {
10510
+ "text": "void"
10511
+ }
10512
+ },
10513
+ "description": "Select all of the field's text, as a native field's `select()` does. With\na new value not yet rendered, once it has: writing the value into the\ninput drops its selection, so `field.value = x; field.select()` selects\n`x`, as on a native field.",
10514
+ "inheritedFrom": {
10515
+ "name": "VfTextControlBase",
10516
+ "module": "src/text-control.ts"
10517
+ }
10518
+ },
10321
10519
  {
10322
10520
  "kind": "method",
10323
10521
  "name": "formResetCallback",
@@ -10372,7 +10570,7 @@
10372
10570
  },
10373
10571
  {
10374
10572
  "kind": "method",
10375
- "name": "emitValue",
10573
+ "name": "handleInput",
10376
10574
  "privacy": "protected",
10377
10575
  "return": {
10378
10576
  "type": {
@@ -10381,20 +10579,36 @@
10381
10579
  },
10382
10580
  "parameters": [
10383
10581
  {
10384
- "name": "type",
10582
+ "name": "event",
10385
10583
  "type": {
10386
- "text": "'vf-input' | 'vf-change'"
10584
+ "text": "Event"
10387
10585
  }
10388
- },
10586
+ }
10587
+ ],
10588
+ "description": "Mirror the native control's value into `value` and announce a keystroke.",
10589
+ "inheritedFrom": {
10590
+ "name": "VfTextControlBase",
10591
+ "module": "src/text-control.ts"
10592
+ }
10593
+ },
10594
+ {
10595
+ "kind": "method",
10596
+ "name": "commit",
10597
+ "privacy": "protected",
10598
+ "return": {
10599
+ "type": {
10600
+ "text": "void"
10601
+ }
10602
+ },
10603
+ "parameters": [
10389
10604
  {
10390
- "name": "detail",
10391
- "default": "{ value: this.value }",
10605
+ "name": "raw",
10392
10606
  "type": {
10393
- "text": "Record<string, unknown>"
10607
+ "text": "string"
10394
10608
  }
10395
10609
  }
10396
10610
  ],
10397
- "description": "Dispatch a bubbling, composed value event (SPEC §4). Text fields use the\ndefault `{ value }` detail; `vf-number-field` passes an enriched detail that\nalso carries `valueAsNumber`.",
10611
+ "description": "Commit typed text: its committed form into `value`, announced unless it is what was last committed.",
10398
10612
  "inheritedFrom": {
10399
10613
  "name": "VfTextControlBase",
10400
10614
  "module": "src/text-control.ts"
@@ -10402,7 +10616,7 @@
10402
10616
  },
10403
10617
  {
10404
10618
  "kind": "method",
10405
- "name": "handleInput",
10619
+ "name": "handleChange",
10406
10620
  "privacy": "protected",
10407
10621
  "return": {
10408
10622
  "type": {
@@ -10417,7 +10631,7 @@
10417
10631
  }
10418
10632
  }
10419
10633
  ],
10420
- "description": "Mirror the native control's value into `value` and announce a keystroke.",
10634
+ "description": "The native control's commit.",
10421
10635
  "inheritedFrom": {
10422
10636
  "name": "VfTextControlBase",
10423
10637
  "module": "src/text-control.ts"
@@ -10425,7 +10639,7 @@
10425
10639
  },
10426
10640
  {
10427
10641
  "kind": "method",
10428
- "name": "handleChange",
10642
+ "name": "submitOnEnter",
10429
10643
  "privacy": "protected",
10430
10644
  "return": {
10431
10645
  "type": {
@@ -10436,11 +10650,11 @@
10436
10650
  {
10437
10651
  "name": "event",
10438
10652
  "type": {
10439
- "text": "Event"
10653
+ "text": "KeyboardEvent"
10440
10654
  }
10441
10655
  }
10442
10656
  ],
10443
- "description": "Mirror the native control's value into `value` and announce a commit.",
10657
+ "description": "A plain Return in a single-line field with a form: commit, then the\nform's implicit submission, the order a native input keeps (its `change`\ncomes before the submission). The keydown is cancelled, so an enclosing\nmodal does not route the same press to its default button as well.",
10444
10658
  "inheritedFrom": {
10445
10659
  "name": "VfTextControlBase",
10446
10660
  "module": "src/text-control.ts"
@@ -11105,6 +11319,19 @@
11105
11319
  "module": "src/text-control.ts"
11106
11320
  }
11107
11321
  },
11322
+ {
11323
+ "name": "autoselect",
11324
+ "type": {
11325
+ "text": "boolean"
11326
+ },
11327
+ "default": "false",
11328
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
11329
+ "fieldName": "autoselect",
11330
+ "inheritedFrom": {
11331
+ "name": "VfTextControlBase",
11332
+ "module": "src/text-control.ts"
11333
+ }
11334
+ },
11108
11335
  {
11109
11336
  "name": "name",
11110
11337
  "type": {
@@ -11498,7 +11725,7 @@
11498
11725
  "declarations": [
11499
11726
  {
11500
11727
  "kind": "class",
11501
- "description": "`<vf-paragraph>` — a paragraph of copy on the kit's body face and grid.\n\nThe installer's welcome text, a dialog's explanation, an article's prose:\nanything a page would otherwise set with a `<p>` and hope the leading landed\nsomewhere sensible. What it adds over that `<p>`:\n\n- the **Geneva body face** by default (`face=\"display\"` switches to\n the Chicago-style chrome face);\n- a **whole-system-pixel line box at the face's native pitch** —\n `--vf-paragraph-line-height`: 12px for the body face (Geneva 9's own\n strike line) and 16px under `face=\"display\"` (Chicago 12's — ascent 12 +\n descent 3 + leading 1, the pitch a real dialog wrapped its copy on).\n Whole pixels are the point of the component: line boxes are the single\n biggest source of off-grid layout, because a ratio resolves to whatever\n it resolves to (`1.65 × 17px = 28.05px`) and every line of prose nudges\n everything after it further off the device-pixel grid, smearing 1-bit\n borders and bitmap glyph stems (docs/SIZING.md rule 2). A\n whole-pixel line box accumulates whole offsets;\n- its own GridSnapController, so it holds its own origin\n wherever the page puts it;\n- a **declared box** when the layout wants one — `width`/`height` in whole\n system px (VfSized). In flow a paragraph takes its container's\n width, which is usually right; a *placed* one (`top`/`left`) shrink-wraps\n its longest line instead — a fractional glyph-run width, wrapped wherever\n the parent's edge happens to fall — so a DITL-style layout states the\n measure the copy wraps to, whole and on the grid.\n\nThe shadow root renders a real `<p>`, so the copy keeps paragraph semantics\nfor assistive tech, and — unlike the kit's chrome — the text is selectable.\nThere is no margin: per SPEC §2 a component adds nothing outside its own box,\nso paragraph spacing is the page's (a `gap` on the column, or a margin on the\nhost — kept a whole number of pixels, like everything else in the contract).",
11728
+ "description": "`<vf-paragraph>` — a paragraph of copy on the kit's body face and grid.\n\nThe installer's welcome text, a dialog's explanation, an article's prose:\nanything a page would otherwise set with a `<p>` and hope the leading landed\nsomewhere sensible. What it adds over that `<p>`:\n\n- the **Geneva body face** by default (`face=\"display\"` switches to\n the Chicago-style chrome face);\n- a **whole-system-pixel line box at the face's native pitch** —\n `--vf-paragraph-line-height`: 12px for the body face (Geneva 9's own\n strike line) and 16px under `face=\"display\"` (Chicago 12's — ascent 12 +\n descent 3 + leading 1, the pitch a real dialog wrapped its copy on).\n Whole pixels are the point of the component: line boxes are the single\n biggest source of off-grid layout, because a ratio resolves to whatever\n it resolves to (`1.65 × 17px = 28.05px`) and every line of prose nudges\n everything after it further off the device-pixel grid, smearing 1-bit\n borders and bitmap glyph stems (docs/SIZING.md rule 2). A\n whole-pixel line box accumulates whole offsets;\n- its own GridSnapController, so it holds its own origin\n wherever the page puts it;\n- a **declared box** when the layout wants one — `width`/`height` in whole\n system px (VfSized). In flow a paragraph takes its container's\n width, which is usually right; a *placed* one (`top`/`left`) shrink-wraps\n its longest line instead — a fractional glyph-run width, wrapped wherever\n the parent's edge happens to fall — so a DITL-style layout states the\n measure the copy wraps to, whole and on the grid.\n\nThe shadow root renders a real `<p>`, so the copy keeps paragraph semantics\nfor assistive tech, and — unlike the kit's chrome — the text is selectable,\nselected text inverting to the 1-bit highlight (`--vf-highlight` /\n`--vf-highlight-text`) as a field's does.\nThere is no margin: per SPEC §2 a component adds nothing outside its own box,\nso paragraph spacing is the page's (a `gap` on the column, or a margin on the\nhost — kept a whole number of pixels, like everything else in the contract).",
11502
11729
  "name": "VfParagraph",
11503
11730
  "cssProperties": [
11504
11731
  {
@@ -13397,7 +13624,7 @@
13397
13624
  "declarations": [
13398
13625
  {
13399
13626
  "kind": "class",
13400
- "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them,\nand corner reserves that cell on a single-axis rail too — the\nrail stops 15px short of the frame, for a grow box to land in.\n\nSize the host (width/height) from the outside; the viewport fills it.\nContent runs to the frame and the rails — the area adds no inset of its\nown; an inset is the content's (a `vf-stack pad`).\n\nThe scrolled plane sizes to its content — never narrower than the\nviewport, as wide as content that cannot wrap — so the rails follow a row\nthat grows sideways the way they follow copy that grows down, and a\n`slotchange` re-measures. A placed child moved through `top`/`left` is\nheard too: every such write is announced as `vf-placement-change`\n(src/position.ts), and the area re-measures on it — a drop, an arrow\nnudge, a page's own `icon.left = …`, with no code on the page. * measure covers a scroll range that changes with no box and no placement\nchanging (a transform).\n\nplacementAt converts a viewport point into the plane's own\nplacement coordinates, for a drop that lands in this area from elsewhere.",
13627
+ "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them,\nand corner reserves that cell on a single-axis rail too — the\nrail stops 15px short of the frame, for a grow box to land in.\n\nSize the host (width/height) from the outside; the viewport fills it.\nContent runs to the frame and the rails — the area adds no inset of its\nown; an inset is the content's (a `vf-stack pad`). `pattern` fills the\nscrolled plane with a 1-bit pattern, as on `vf-container`.\n\nThe scrolled plane sizes to its content — never narrower than the\nviewport, as wide as content that cannot wrap — so the rails follow a row\nthat grows sideways the way they follow copy that grows down, and a\n`slotchange` re-measures. A placed child moved through `top`/`left` is\nheard too: every such write is announced as `vf-placement-change`\n(src/position.ts), and the area re-measures on it — a drop, an arrow\nnudge, a page's own `icon.left = …`, with no code on the page. * measure covers a scroll range that changes with no box and no placement\nchanging (a transform).\n\nplacementAt converts a viewport point into the plane's own\nplacement coordinates, for a drop that lands in this area from elsewhere.",
13401
13628
  "name": "VfScrollArea",
13402
13629
  "cssProperties": [
13403
13630
  {
@@ -13471,27 +13698,64 @@
13471
13698
  },
13472
13699
  {
13473
13700
  "kind": "field",
13474
- "name": "viewport",
13701
+ "name": "pattern",
13475
13702
  "type": {
13476
- "text": "HTMLElement | null"
13703
+ "text": "string | null | undefined"
13477
13704
  },
13478
- "privacy": "private"
13705
+ "description": "A 1-bit fill for the scrolled plane, as on `vf-container`: a library\npattern by name (docs/PATTERNS.md) or sixteen hex digits. It fills the\nvisible area, runs on past the content, and scrolls with it, its phase\nanchored at the content's top-left. Unset, the plane stays white; an\nunrecognized value paints nothing and warns once.",
13706
+ "attribute": "pattern"
13479
13707
  },
13480
13708
  {
13481
13709
  "kind": "field",
13482
- "name": "content",
13710
+ "name": "_pattern",
13483
13711
  "type": {
13484
- "text": "HTMLElement | null"
13712
+ "text": "Pattern | null"
13485
13713
  },
13486
- "privacy": "private"
13487
- },
13488
- {
13489
- "kind": "field",
13490
- "name": "scrollState",
13491
13714
  "privacy": "private",
13492
- "readonly": true,
13493
- "default": "new ScrollStateController( this, () => this.viewport, () => this.content, (overflow) => { this._scrollable = overflow.x || overflow.y } )",
13494
- "description": "Reports overflow per axis so the reserved rail(s) activate on overflow."
13715
+ "default": "null",
13716
+ "description": "`pattern`, resolved — what the fill paints; null paints nothing."
13717
+ },
13718
+ {
13719
+ "kind": "field",
13720
+ "name": "#warnedPattern",
13721
+ "privacy": "private",
13722
+ "type": {
13723
+ "text": "boolean"
13724
+ },
13725
+ "default": "false",
13726
+ "description": "One warning per element for an unrecognized `pattern`, not per render."
13727
+ },
13728
+ {
13729
+ "kind": "field",
13730
+ "name": "viewport",
13731
+ "type": {
13732
+ "text": "HTMLElement | null"
13733
+ },
13734
+ "privacy": "private"
13735
+ },
13736
+ {
13737
+ "kind": "field",
13738
+ "name": "content",
13739
+ "type": {
13740
+ "text": "HTMLElement | null"
13741
+ },
13742
+ "privacy": "private"
13743
+ },
13744
+ {
13745
+ "kind": "field",
13746
+ "name": "patternFill",
13747
+ "privacy": "private",
13748
+ "readonly": true,
13749
+ "default": "new PatternFillController(this, { getBox: () => this.content, getPattern: () => this._pattern, })",
13750
+ "description": "The pattern fill, painted on the scrolled plane (src/pattern-fill.ts)."
13751
+ },
13752
+ {
13753
+ "kind": "field",
13754
+ "name": "scrollState",
13755
+ "privacy": "private",
13756
+ "readonly": true,
13757
+ "default": "new ScrollStateController( this, () => this.viewport, () => this.content, (overflow) => { this._scrollable = overflow.x || overflow.y } )",
13758
+ "description": "Reports overflow per axis so the reserved rail(s) activate on overflow."
13495
13759
  },
13496
13760
  {
13497
13761
  "kind": "field",
@@ -13671,6 +13935,14 @@
13671
13935
  "description": "Accessible name for the scrolling viewport, applied as its `aria-label`\n(an `aria-label` on the host would not reach into the shadow DOM). The\nviewport is keyboard-focusable while its content overflows, so without a\nname it is announced only as an anonymous scrollable group; setting\n`label` also promotes it to a named `role=\"region\"` landmark. While\n`label` is empty the viewport is a plain `group` when scrollable (an\nunnamed region is inert) and role-less when not.",
13672
13936
  "fieldName": "label"
13673
13937
  },
13938
+ {
13939
+ "name": "pattern",
13940
+ "type": {
13941
+ "text": "string | null | undefined"
13942
+ },
13943
+ "description": "A 1-bit fill for the scrolled plane, as on `vf-container`: a library\npattern by name (docs/PATTERNS.md) or sixteen hex digits. It fills the\nvisible area, runs on past the content, and scrolls with it, its phase\nanchored at the content's top-left. Unset, the plane stays white; an\nunrecognized value paints nothing and warns once.",
13944
+ "fieldName": "pattern"
13945
+ },
13674
13946
  {
13675
13947
  "name": "top",
13676
13948
  "type": {
@@ -13760,7 +14032,7 @@
13760
14032
  "declarations": [
13761
14033
  {
13762
14034
  "kind": "class",
13763
- "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\n`no-shadow` draws the closed pill without its 1px hard shadow, and the focus\nrule moves up the row the shadow took. The open list keeps its shadow.\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`.",
14035
+ "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 a manual\npopover in the top layer, positioned `position: fixed` (computed from\n`getBoundingClientRect()`), so it escapes clipping containers and paints\nover every window, palettes included; when possible the currently-selected\nitem opens directly 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\n`no-shadow` draws the closed pill without its 1px hard shadow, and the focus\nrule moves up the row the shadow took. The open list keeps its shadow.\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`.",
13764
14036
  "name": "VfSelect",
13765
14037
  "cssProperties": [
13766
14038
  {
@@ -18132,6 +18404,21 @@
18132
18404
  "module": "src/text-control.ts"
18133
18405
  }
18134
18406
  },
18407
+ {
18408
+ "kind": "field",
18409
+ "name": "autoselect",
18410
+ "type": {
18411
+ "text": "boolean"
18412
+ },
18413
+ "default": "false",
18414
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
18415
+ "attribute": "autoselect",
18416
+ "reflects": true,
18417
+ "inheritedFrom": {
18418
+ "name": "VfTextControlBase",
18419
+ "module": "src/text-control.ts"
18420
+ }
18421
+ },
18135
18422
  {
18136
18423
  "kind": "field",
18137
18424
  "name": "name",
@@ -18264,6 +18551,71 @@
18264
18551
  "module": "src/text-control.ts"
18265
18552
  }
18266
18553
  },
18554
+ {
18555
+ "kind": "field",
18556
+ "name": "committed",
18557
+ "type": {
18558
+ "text": "string | null"
18559
+ },
18560
+ "privacy": "protected",
18561
+ "default": "null",
18562
+ "description": "The text as last committed: taken when the field gains focus, then at\neach commit. A commit that brings nothing new isn't announced, so the\nnative `change` that follows a Return commit, or a step, is not a second\none.",
18563
+ "inheritedFrom": {
18564
+ "name": "VfTextControlBase",
18565
+ "module": "src/text-control.ts"
18566
+ }
18567
+ },
18568
+ {
18569
+ "kind": "field",
18570
+ "name": "control",
18571
+ "type": {
18572
+ "text": "HTMLInputElement | HTMLTextAreaElement | null"
18573
+ },
18574
+ "privacy": "protected",
18575
+ "description": "The inner native control every field renders, tagged `vf-field`.",
18576
+ "readonly": true,
18577
+ "inheritedFrom": {
18578
+ "name": "VfTextControlBase",
18579
+ "module": "src/text-control.ts"
18580
+ }
18581
+ },
18582
+ {
18583
+ "kind": "method",
18584
+ "name": "focus",
18585
+ "return": {
18586
+ "type": {
18587
+ "text": "void"
18588
+ }
18589
+ },
18590
+ "parameters": [
18591
+ {
18592
+ "name": "options",
18593
+ "optional": true,
18594
+ "type": {
18595
+ "text": "FocusOptions"
18596
+ }
18597
+ }
18598
+ ],
18599
+ "description": "Focuses the inner control, keeping its caret where it was. Chromium\nselects all of an input's text when the host hands the focus on, as a Tab\ndoes; `select()` and autoselect are how a field opens selected.",
18600
+ "inheritedFrom": {
18601
+ "name": "VfTextControlBase",
18602
+ "module": "src/text-control.ts"
18603
+ }
18604
+ },
18605
+ {
18606
+ "kind": "method",
18607
+ "name": "select",
18608
+ "return": {
18609
+ "type": {
18610
+ "text": "void"
18611
+ }
18612
+ },
18613
+ "description": "Select all of the field's text, as a native field's `select()` does. With\na new value not yet rendered, once it has: writing the value into the\ninput drops its selection, so `field.value = x; field.select()` selects\n`x`, as on a native field.",
18614
+ "inheritedFrom": {
18615
+ "name": "VfTextControlBase",
18616
+ "module": "src/text-control.ts"
18617
+ }
18618
+ },
18267
18619
  {
18268
18620
  "kind": "method",
18269
18621
  "name": "formResetCallback",
@@ -18346,6 +18698,52 @@
18346
18698
  "module": "src/text-control.ts"
18347
18699
  }
18348
18700
  },
18701
+ {
18702
+ "kind": "method",
18703
+ "name": "committedText",
18704
+ "privacy": "protected",
18705
+ "return": {
18706
+ "type": {
18707
+ "text": "string"
18708
+ }
18709
+ },
18710
+ "parameters": [
18711
+ {
18712
+ "name": "raw",
18713
+ "type": {
18714
+ "text": "string"
18715
+ }
18716
+ }
18717
+ ],
18718
+ "description": "The committed form of typed text: as typed here; `vf-number-field` clamps and rounds it.",
18719
+ "inheritedFrom": {
18720
+ "name": "VfTextControlBase",
18721
+ "module": "src/text-control.ts"
18722
+ }
18723
+ },
18724
+ {
18725
+ "kind": "method",
18726
+ "name": "commit",
18727
+ "privacy": "protected",
18728
+ "return": {
18729
+ "type": {
18730
+ "text": "void"
18731
+ }
18732
+ },
18733
+ "parameters": [
18734
+ {
18735
+ "name": "raw",
18736
+ "type": {
18737
+ "text": "string"
18738
+ }
18739
+ }
18740
+ ],
18741
+ "description": "Commit typed text: its committed form into `value`, announced unless it is what was last committed.",
18742
+ "inheritedFrom": {
18743
+ "name": "VfTextControlBase",
18744
+ "module": "src/text-control.ts"
18745
+ }
18746
+ },
18349
18747
  {
18350
18748
  "kind": "method",
18351
18749
  "name": "handleChange",
@@ -18363,7 +18761,30 @@
18363
18761
  }
18364
18762
  }
18365
18763
  ],
18366
- "description": "Mirror the native control's value into `value` and announce a commit.",
18764
+ "description": "The native control's commit.",
18765
+ "inheritedFrom": {
18766
+ "name": "VfTextControlBase",
18767
+ "module": "src/text-control.ts"
18768
+ }
18769
+ },
18770
+ {
18771
+ "kind": "method",
18772
+ "name": "submitOnEnter",
18773
+ "privacy": "protected",
18774
+ "return": {
18775
+ "type": {
18776
+ "text": "void"
18777
+ }
18778
+ },
18779
+ "parameters": [
18780
+ {
18781
+ "name": "event",
18782
+ "type": {
18783
+ "text": "KeyboardEvent"
18784
+ }
18785
+ }
18786
+ ],
18787
+ "description": "A plain Return in a single-line field with a form: commit, then the\nform's implicit submission, the order a native input keeps (its `change`\ncomes before the submission). The keydown is cancelled, so an enclosing\nmodal does not route the same press to its default button as well.",
18367
18788
  "inheritedFrom": {
18368
18789
  "name": "VfTextControlBase",
18369
18790
  "module": "src/text-control.ts"
@@ -19012,6 +19433,19 @@
19012
19433
  "module": "src/text-control.ts"
19013
19434
  }
19014
19435
  },
19436
+ {
19437
+ "name": "autoselect",
19438
+ "type": {
19439
+ "text": "boolean"
19440
+ },
19441
+ "default": "false",
19442
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
19443
+ "fieldName": "autoselect",
19444
+ "inheritedFrom": {
19445
+ "name": "VfTextControlBase",
19446
+ "module": "src/text-control.ts"
19447
+ }
19448
+ },
19015
19449
  {
19016
19450
  "name": "name",
19017
19451
  "type": {
@@ -19186,7 +19620,7 @@
19186
19620
  }
19187
19621
  }
19188
19622
  ],
19189
- "description": "Enter in a single-line field triggers the associated form's implicit\nsubmission. The native `<input>` is shadow-encapsulated, so its form owner\nis null and the browser won't do this itself. A press the form took is\ncancelled, so an enclosing modal does not route it again."
19623
+ "description": "Enter in a single-line field commits, then triggers the associated\nform's implicit submission. The native `<input>` is shadow-encapsulated,\nso its form owner is null and the browser won't do this itself."
19190
19624
  },
19191
19625
  {
19192
19626
  "kind": "field",
@@ -19300,6 +19734,21 @@
19300
19734
  "module": "src/text-control.ts"
19301
19735
  }
19302
19736
  },
19737
+ {
19738
+ "kind": "field",
19739
+ "name": "autoselect",
19740
+ "type": {
19741
+ "text": "boolean"
19742
+ },
19743
+ "default": "false",
19744
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
19745
+ "attribute": "autoselect",
19746
+ "reflects": true,
19747
+ "inheritedFrom": {
19748
+ "name": "VfTextControlBase",
19749
+ "module": "src/text-control.ts"
19750
+ }
19751
+ },
19303
19752
  {
19304
19753
  "kind": "field",
19305
19754
  "name": "name",
@@ -19417,37 +19866,51 @@
19417
19866
  }
19418
19867
  },
19419
19868
  {
19420
- "kind": "method",
19421
- "name": "formResetCallback",
19422
- "return": {
19423
- "type": {
19424
- "text": "void"
19425
- }
19869
+ "kind": "field",
19870
+ "name": "committed",
19871
+ "type": {
19872
+ "text": "string | null"
19426
19873
  },
19427
- "description": "Restores the initial value when the associated form resets.",
19874
+ "privacy": "protected",
19875
+ "default": "null",
19876
+ "description": "The text as last committed: taken when the field gains focus, then at\neach commit. A commit that brings nothing new isn't announced, so the\nnative `change` that follows a Return commit, or a step, is not a second\none.",
19428
19877
  "inheritedFrom": {
19429
19878
  "name": "VfTextControlBase",
19430
19879
  "module": "src/text-control.ts"
19431
19880
  }
19432
19881
  },
19433
19882
  {
19434
- "kind": "method",
19435
- "name": "isSubmitEnter",
19883
+ "kind": "field",
19884
+ "name": "control",
19885
+ "type": {
19886
+ "text": "HTMLInputElement | HTMLTextAreaElement | null"
19887
+ },
19436
19888
  "privacy": "protected",
19889
+ "description": "The inner native control every field renders, tagged `vf-field`.",
19890
+ "readonly": true,
19891
+ "inheritedFrom": {
19892
+ "name": "VfTextControlBase",
19893
+ "module": "src/text-control.ts"
19894
+ }
19895
+ },
19896
+ {
19897
+ "kind": "method",
19898
+ "name": "focus",
19437
19899
  "return": {
19438
19900
  "type": {
19439
- "text": "boolean"
19901
+ "text": "void"
19440
19902
  }
19441
19903
  },
19442
19904
  "parameters": [
19443
19905
  {
19444
- "name": "event",
19906
+ "name": "options",
19907
+ "optional": true,
19445
19908
  "type": {
19446
- "text": "KeyboardEvent"
19909
+ "text": "FocusOptions"
19447
19910
  }
19448
19911
  }
19449
19912
  ],
19450
- "description": "True for a plain Enter press (no modifiers, not IME-composing) — the key\nthat triggers a form's implicit submission. The native control is\nshadow-encapsulated (null form owner), so single-line fields call\n`internals.form?.requestSubmit()` themselves; this centralises the guard.",
19913
+ "description": "Focuses the inner control, keeping its caret where it was. Chromium\nselects all of an input's text when the host hands the focus on, as a Tab\ndoes; `select()` and autoselect are how a field opens selected.",
19451
19914
  "inheritedFrom": {
19452
19915
  "name": "VfTextControlBase",
19453
19916
  "module": "src/text-control.ts"
@@ -19455,14 +19918,13 @@
19455
19918
  },
19456
19919
  {
19457
19920
  "kind": "method",
19458
- "name": "requestImplicitSubmit",
19459
- "privacy": "protected",
19921
+ "name": "select",
19460
19922
  "return": {
19461
19923
  "type": {
19462
- "text": "boolean"
19924
+ "text": "void"
19463
19925
  }
19464
19926
  },
19465
- "description": "Emulates the form's implicit submission for a plain Enter press. HTML\ndefines it as *activating the form's default button* — the first submit\nbutton in tree order — so the submission carries that button's submitter\nidentity and name/value. A bare `requestSubmit()` carries neither\n(`event.submitter === null`), which made Enter and a click on the same\nform produce different payloads. `click()` is the activation: a native\nbutton becomes the real submitter, and a `vf-button` forwards it to its\ninner button, which runs the same transient-proxy path a pointer does. A\ndisabled default button means no submission at all, as in HTML; a form\nwith no submit button falls back to the bare call, also as in HTML.\n\nOne departure: a submit `vf-button variant=\"default\"`, the button with\nthe ring, is the default button when the form has one, ahead of the\nfirst in tree order. A Cancel/OK row puts Cancel first, and Return\nshould press the button the ring marks — the one a modal's own Return\nrule presses (`VfModalDialog`).\n\nReturns whether a form owner took the press — true even when a disabled\ndefault button meant no submission, since HTML gave the press to the form\neither way. The callers cancel the keydown on true, so a modal shell\n(`VfModalDialog`) sees the press as spoken for and does not also route it\nto the dialog's default button; with no form the press goes on to the\ndialog untouched.",
19927
+ "description": "Select all of the field's text, as a native field's `select()` does. With\na new value not yet rendered, once it has: writing the value into the\ninput drops its selection, so `field.value = x; field.select()` selects\n`x`, as on a native field.",
19466
19928
  "inheritedFrom": {
19467
19929
  "name": "VfTextControlBase",
19468
19930
  "module": "src/text-control.ts"
@@ -19470,25 +19932,77 @@
19470
19932
  },
19471
19933
  {
19472
19934
  "kind": "method",
19473
- "name": "emitValue",
19474
- "privacy": "protected",
19935
+ "name": "formResetCallback",
19475
19936
  "return": {
19476
19937
  "type": {
19477
19938
  "text": "void"
19478
19939
  }
19479
19940
  },
19480
- "parameters": [
19481
- {
19482
- "name": "type",
19483
- "type": {
19484
- "text": "'vf-input' | 'vf-change'"
19485
- }
19486
- },
19487
- {
19488
- "name": "detail",
19489
- "default": "{ value: this.value }",
19490
- "type": {
19491
- "text": "Record<string, unknown>"
19941
+ "description": "Restores the initial value when the associated form resets.",
19942
+ "inheritedFrom": {
19943
+ "name": "VfTextControlBase",
19944
+ "module": "src/text-control.ts"
19945
+ }
19946
+ },
19947
+ {
19948
+ "kind": "method",
19949
+ "name": "isSubmitEnter",
19950
+ "privacy": "protected",
19951
+ "return": {
19952
+ "type": {
19953
+ "text": "boolean"
19954
+ }
19955
+ },
19956
+ "parameters": [
19957
+ {
19958
+ "name": "event",
19959
+ "type": {
19960
+ "text": "KeyboardEvent"
19961
+ }
19962
+ }
19963
+ ],
19964
+ "description": "True for a plain Enter press (no modifiers, not IME-composing) — the key\nthat triggers a form's implicit submission. The native control is\nshadow-encapsulated (null form owner), so single-line fields call\n`internals.form?.requestSubmit()` themselves; this centralises the guard.",
19965
+ "inheritedFrom": {
19966
+ "name": "VfTextControlBase",
19967
+ "module": "src/text-control.ts"
19968
+ }
19969
+ },
19970
+ {
19971
+ "kind": "method",
19972
+ "name": "requestImplicitSubmit",
19973
+ "privacy": "protected",
19974
+ "return": {
19975
+ "type": {
19976
+ "text": "boolean"
19977
+ }
19978
+ },
19979
+ "description": "Emulates the form's implicit submission for a plain Enter press. HTML\ndefines it as *activating the form's default button* — the first submit\nbutton in tree order — so the submission carries that button's submitter\nidentity and name/value. A bare `requestSubmit()` carries neither\n(`event.submitter === null`), which made Enter and a click on the same\nform produce different payloads. `click()` is the activation: a native\nbutton becomes the real submitter, and a `vf-button` forwards it to its\ninner button, which runs the same transient-proxy path a pointer does. A\ndisabled default button means no submission at all, as in HTML; a form\nwith no submit button falls back to the bare call, also as in HTML.\n\nOne departure: a submit `vf-button variant=\"default\"`, the button with\nthe ring, is the default button when the form has one, ahead of the\nfirst in tree order. A Cancel/OK row puts Cancel first, and Return\nshould press the button the ring marks — the one a modal's own Return\nrule presses (`VfModalDialog`).\n\nReturns whether a form owner took the press — true even when a disabled\ndefault button meant no submission, since HTML gave the press to the form\neither way. The callers cancel the keydown on true, so a modal shell\n(`VfModalDialog`) sees the press as spoken for and does not also route it\nto the dialog's default button; with no form the press goes on to the\ndialog untouched.",
19980
+ "inheritedFrom": {
19981
+ "name": "VfTextControlBase",
19982
+ "module": "src/text-control.ts"
19983
+ }
19984
+ },
19985
+ {
19986
+ "kind": "method",
19987
+ "name": "emitValue",
19988
+ "privacy": "protected",
19989
+ "return": {
19990
+ "type": {
19991
+ "text": "void"
19992
+ }
19993
+ },
19994
+ "parameters": [
19995
+ {
19996
+ "name": "type",
19997
+ "type": {
19998
+ "text": "'vf-input' | 'vf-change'"
19999
+ }
20000
+ },
20001
+ {
20002
+ "name": "detail",
20003
+ "default": "{ value: this.value }",
20004
+ "type": {
20005
+ "text": "Record<string, unknown>"
19492
20006
  }
19493
20007
  }
19494
20008
  ],
@@ -19521,6 +20035,52 @@
19521
20035
  "module": "src/text-control.ts"
19522
20036
  }
19523
20037
  },
20038
+ {
20039
+ "kind": "method",
20040
+ "name": "committedText",
20041
+ "privacy": "protected",
20042
+ "return": {
20043
+ "type": {
20044
+ "text": "string"
20045
+ }
20046
+ },
20047
+ "parameters": [
20048
+ {
20049
+ "name": "raw",
20050
+ "type": {
20051
+ "text": "string"
20052
+ }
20053
+ }
20054
+ ],
20055
+ "description": "The committed form of typed text: as typed here; `vf-number-field` clamps and rounds it.",
20056
+ "inheritedFrom": {
20057
+ "name": "VfTextControlBase",
20058
+ "module": "src/text-control.ts"
20059
+ }
20060
+ },
20061
+ {
20062
+ "kind": "method",
20063
+ "name": "commit",
20064
+ "privacy": "protected",
20065
+ "return": {
20066
+ "type": {
20067
+ "text": "void"
20068
+ }
20069
+ },
20070
+ "parameters": [
20071
+ {
20072
+ "name": "raw",
20073
+ "type": {
20074
+ "text": "string"
20075
+ }
20076
+ }
20077
+ ],
20078
+ "description": "Commit typed text: its committed form into `value`, announced unless it is what was last committed.",
20079
+ "inheritedFrom": {
20080
+ "name": "VfTextControlBase",
20081
+ "module": "src/text-control.ts"
20082
+ }
20083
+ },
19524
20084
  {
19525
20085
  "kind": "method",
19526
20086
  "name": "handleChange",
@@ -19538,7 +20098,30 @@
19538
20098
  }
19539
20099
  }
19540
20100
  ],
19541
- "description": "Mirror the native control's value into `value` and announce a commit.",
20101
+ "description": "The native control's commit.",
20102
+ "inheritedFrom": {
20103
+ "name": "VfTextControlBase",
20104
+ "module": "src/text-control.ts"
20105
+ }
20106
+ },
20107
+ {
20108
+ "kind": "method",
20109
+ "name": "submitOnEnter",
20110
+ "privacy": "protected",
20111
+ "return": {
20112
+ "type": {
20113
+ "text": "void"
20114
+ }
20115
+ },
20116
+ "parameters": [
20117
+ {
20118
+ "name": "event",
20119
+ "type": {
20120
+ "text": "KeyboardEvent"
20121
+ }
20122
+ }
20123
+ ],
20124
+ "description": "A plain Return in a single-line field with a form: commit, then the\nform's implicit submission, the order a native input keeps (its `change`\ncomes before the submission). The keydown is cancelled, so an enclosing\nmodal does not route the same press to its default button as well.",
19542
20125
  "inheritedFrom": {
19543
20126
  "name": "VfTextControlBase",
19544
20127
  "module": "src/text-control.ts"
@@ -20077,7 +20660,7 @@
20077
20660
  "name": "vf-input"
20078
20661
  },
20079
20662
  {
20080
- "description": "On commit (native `change`). `detail: { value: string }`.",
20663
+ "description": "On commit: the native `change`, leaving the field, or Return in a form, before its submission. `detail: { value: string }`.",
20081
20664
  "name": "vf-change"
20082
20665
  },
20083
20666
  {
@@ -20187,6 +20770,19 @@
20187
20770
  "module": "src/text-control.ts"
20188
20771
  }
20189
20772
  },
20773
+ {
20774
+ "name": "autoselect",
20775
+ "type": {
20776
+ "text": "boolean"
20777
+ },
20778
+ "default": "false",
20779
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
20780
+ "fieldName": "autoselect",
20781
+ "inheritedFrom": {
20782
+ "name": "VfTextControlBase",
20783
+ "module": "src/text-control.ts"
20784
+ }
20785
+ },
20190
20786
  {
20191
20787
  "name": "name",
20192
20788
  "type": {
@@ -20292,7 +20888,7 @@
20292
20888
  "declarations": [
20293
20889
  {
20294
20890
  "kind": "class",
20295
- "description": "`<vf-window>` — the System 7 desktop-window shell.\n\nStriped title bar with optional close box (left) and zoom box (right), a\nsolid-white frame with a hard offset shadow, an optional grow box for\nresizing, optional edge scroll rails (`scrollbars`), and the slim windoid\nchrome (`variant=\"utility\"`). The HIG's window archetypes are parameter\nrecipes over this shell rather than fixed anatomies — the component enables\nHIG compliance, it doesn't enforce it (see docs/LAYOUT.md \"Window archetypes\"):\nthe full document window is `closable zoomable movable resizable\nscrollbars=\"both\"`, a modeless dialog box is `closable movable`, a utility\nwindow is `variant=\"utility\" movable`. Place inside `<vf-desktop>` to get\nclick-to-front stacking and automatic `active` management (utility windows\nfloat above the document tier).\n\nEvery recipe also declares `width` AND `height` (VfSized), in whole\nsystem px — the art's own unit, so the window keeps its proportions to the\nchrome inside it at every display density (a CSS-px size stays put while\nthe components in it triple). A window is a fixed box in both axes, the way\nthe WIND resource carried it: left to layout it takes whatever its\ncontainer or content hands it, which is how a title bar ends up wider than\nthe screen or a dialog reflows as it moves — and a window that grows with\nits body is one the user can neither predict nor (via the grow box) own.\nContent taller than the declared box is clipped at the frame the way the\nclassic content region was; `scrollbars` lets the user reach the rest.\nUnset, the window still renders — normal block layout, as before — and\nsays so once in the console.\n\n**Opening from a rect.** show clears `hidden`, and given `from` — a\nbox in viewport CSS px, an icon's `cellRect()` or a button's rect — opens\nthe window from it: dotted rectangles grow from that box toward the\nwindow's frame, four on screen at a time, bunched at the box and opening\nout toward the window, drawn with the icon drag outline's XOR pen on the\ndesktop's drag surface; the window draws once they have drained, eighteen\nsteps later. Until then it matches `:state(opening)` and paints nothing —\nstill laid out, focusable and a hit target, so a page can place it, raise\nit and focus into it at once, and a press finishes the rects and lands on\nthe window. Under `prefers-reduced-motion`, with no `vf-desktop` on its\npath, or without `from`, the window shows at once.\n\n**Closing to a rect.** hide sets `hidden`, and given `to` closes\nthe window to it: the same rectangles run the other way, from where the\nframe was in toward the box, the window gone from the first step. A press\nfinishes them, and removing the window leaves them running. Under\n`prefers-reduced-motion`, with no `vf-desktop` on its path, or without\n`to`, the window hides at once. The window knows nothing about icons:\n`from` and `to` are any rect.\n\n**Dragging as an outline.** A `movable` window moves live under the\npointer. With `outline-drag` a press on the title bar draws a dotted\noutline around the window on the desktop's drag surface instead, with the\nsame pen; the drag moves the outline, held where the window can land, and\nthe window moves there on the release. Escape cancels.",
20891
+ "description": "`<vf-window>` — the System 7 desktop-window shell.\n\nStriped title bar with optional close box (left) and zoom box (right), a\nsolid-white frame with a hard offset shadow, an optional grow box for\nresizing, optional edge scroll rails (`scrollbars`), and the slim windoid\nchrome (`variant=\"utility\"`). The HIG's window archetypes are parameter\nrecipes over this shell rather than fixed anatomies — the component enables\nHIG compliance, it doesn't enforce it (see docs/LAYOUT.md \"Window archetypes\"):\nthe full document window is `closable zoomable movable resizable\nscrollbars=\"both\"`, a modeless dialog box is `closable movable`, a utility\nwindow is `variant=\"utility\" closable movable`. Place inside `<vf-desktop>` to get\nclick-to-front stacking and automatic `active` management (utility windows\nfloat above the document tier).\n\nEvery recipe also declares `width` AND `height` (VfSized), in whole\nsystem px — the art's own unit, so the window keeps its proportions to the\nchrome inside it at every display density (a CSS-px size stays put while\nthe components in it triple). A window is a fixed box in both axes, the way\nthe WIND resource carried it: left to layout it takes whatever its\ncontainer or content hands it, which is how a title bar ends up wider than\nthe screen or a dialog reflows as it moves — and a window that grows with\nits body is one the user can neither predict nor (via the grow box) own.\nContent taller than the declared box is clipped at the frame the way the\nclassic content region was; `scrollbars` lets the user reach the rest.\nUnset, the window still renders — normal block layout, as before — and\nsays so once in the console.\n\n**Opening from a rect.** show clears `hidden`, and given `from` — a\nbox in viewport CSS px, an icon's `cellRect()` or a button's rect — opens\nthe window from it: dotted rectangles grow from that box toward the\nwindow's frame, four on screen at a time, bunched at the box and opening\nout toward the window, drawn with the icon drag outline's XOR pen on the\ndesktop's drag surface; the window draws once they have drained, eighteen\nsteps later. Until then it matches `:state(opening)` and paints nothing —\nstill laid out, focusable and a hit target, so a page can place it, raise\nit and focus into it at once, and a press finishes the rects and lands on\nthe window. Under `prefers-reduced-motion`, with no `vf-desktop` on its\npath, or without `from`, the window shows at once.\n\n**Closing to a rect.** hide sets `hidden`, and given `to` closes\nthe window to it: the same rectangles run the other way, from where the\nframe was in toward the box, the window gone from the first step. A press\nfinishes them, and removing the window leaves them running. Under\n`prefers-reduced-motion`, with no `vf-desktop` on its path, or without\n`to`, the window hides at once. The window knows nothing about icons:\n`from` and `to` are any rect.\n\n**Dragging as an outline.** A `movable` window moves live under the\npointer. With `outline-drag` a press on the title bar draws a dotted\noutline around the window on the desktop's drag surface instead, with the\nsame pen; the drag moves the outline, held where the window can land, and\nthe window moves there on the release. Escape cancels.",
20296
20892
  "name": "VfWindow",
20297
20893
  "cssProperties": [
20298
20894
  {
@@ -20413,8 +21009,8 @@
20413
21009
  "type": {
20414
21010
  "text": "boolean"
20415
21011
  },
20416
- "default": "true",
20417
- "description": "Show the close box (left side of the title bar).",
21012
+ "default": "false",
21013
+ "description": "Show the close box (left side of the title bar). Off by default, like\nevery other boolean attribute, so markup can leave it out; the document\nwindow and the modeless dialog box recipes say `closable`.",
20418
21014
  "attribute": "closable",
20419
21015
  "reflects": true
20420
21016
  },
@@ -20526,6 +21122,35 @@
20526
21122
  "description": "The header's height in whole system px, rule included — the way every\nkit bar counts its rule (an 18px title bar is 17 + 1). Unset, the header\nis as tall as what is slotted into it, plus the rule. Only matters while\nthe `header` slot is populated.",
20527
21123
  "attribute": "header-height"
20528
21124
  },
21125
+ {
21126
+ "kind": "field",
21127
+ "name": "pattern",
21128
+ "type": {
21129
+ "text": "string | null | undefined"
21130
+ },
21131
+ "description": "A 1-bit fill for the body, as on `vf-container`: a library pattern by\nname (docs/PATTERNS.md) or sixteen hex digits, under the content and\nanchored at the content region's corner. Under `scrollbars` it fills the\nscrolled plane and scrolls with it (`vf-scroll-area`'s `pattern`). Unset,\nthe body stays white; an unrecognized value paints nothing and warns\nonce.",
21132
+ "attribute": "pattern"
21133
+ },
21134
+ {
21135
+ "kind": "field",
21136
+ "name": "_pattern",
21137
+ "type": {
21138
+ "text": "Pattern | null"
21139
+ },
21140
+ "privacy": "private",
21141
+ "default": "null",
21142
+ "description": "`pattern`, resolved — what the body's fill paints; null paints nothing."
21143
+ },
21144
+ {
21145
+ "kind": "field",
21146
+ "name": "#warnedPattern",
21147
+ "privacy": "private",
21148
+ "type": {
21149
+ "text": "boolean"
21150
+ },
21151
+ "default": "false",
21152
+ "description": "One warning per element for an unrecognized `pattern`, not per render."
21153
+ },
20529
21154
  {
20530
21155
  "kind": "field",
20531
21156
  "name": "_hasHeader",
@@ -20608,6 +21233,14 @@
20608
21233
  "default": "new RepeatTileController(this, { getBox: () => this.renderRoot?.querySelector<HTMLElement>('.vf-dots'), getArt: () => (this.variant === 'utility' && !this._dotsPattern ? DOTS : null), property: '--_vf-dots-tile', })",
20609
21234
  "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."
20610
21235
  },
21236
+ {
21237
+ "kind": "field",
21238
+ "name": "#bodyFill",
21239
+ "privacy": "private",
21240
+ "readonly": true,
21241
+ "default": "new PatternFillController(this, { getBox: () => this.body, getPattern: () => (this.scrollbars ? null : this._pattern), })",
21242
+ "description": "The body's pattern fill (src/pattern-fill.ts). Under `scrollbars` the\nbuilt-in scroll area paints it on its scrolled plane instead."
21243
+ },
20611
21244
  {
20612
21245
  "kind": "method",
20613
21246
  "name": "_dotsTexture",
@@ -21085,7 +21718,15 @@
21085
21718
  "type": {
21086
21719
  "text": "void"
21087
21720
  }
21088
- }
21721
+ },
21722
+ "parameters": [
21723
+ {
21724
+ "name": "event",
21725
+ "type": {
21726
+ "text": "MouseEvent"
21727
+ }
21728
+ }
21729
+ ]
21089
21730
  },
21090
21731
  {
21091
21732
  "kind": "method",
@@ -21236,7 +21877,7 @@
21236
21877
  ],
21237
21878
  "events": [
21238
21879
  {
21239
- "description": "Close box clicked. Detail `{ reason: 'close' }` (shape- compatible with vf-dialog's `vf-close`). The window does NOT remove itself; the consumer decides what closing means.",
21880
+ "description": "Close box clicked. Detail `{ reason: 'close', altKey, shiftKey, metaKey, ctrlKey }`, the modifier keys held on the click (shape-compatible with vf-dialog's `vf-close`), so an Option-click can mean more than a click. The window does NOT remove itself; the consumer decides what closing means.",
21240
21881
  "name": "vf-close"
21241
21882
  },
21242
21883
  {
@@ -21280,8 +21921,8 @@
21280
21921
  "type": {
21281
21922
  "text": "boolean"
21282
21923
  },
21283
- "default": "true",
21284
- "description": "Show the close box (left side of the title bar).",
21924
+ "default": "false",
21925
+ "description": "Show the close box (left side of the title bar). Off by default, like\nevery other boolean attribute, so markup can leave it out; the document\nwindow and the modeless dialog box recipes say `closable`.",
21285
21926
  "fieldName": "closable"
21286
21927
  },
21287
21928
  {
@@ -21368,6 +22009,14 @@
21368
22009
  "description": "The header's height in whole system px, rule included — the way every\nkit bar counts its rule (an 18px title bar is 17 + 1). Unset, the header\nis as tall as what is slotted into it, plus the rule. Only matters while\nthe `header` slot is populated.",
21369
22010
  "fieldName": "headerHeight"
21370
22011
  },
22012
+ {
22013
+ "name": "pattern",
22014
+ "type": {
22015
+ "text": "string | null | undefined"
22016
+ },
22017
+ "description": "A 1-bit fill for the body, as on `vf-container`: a library pattern by\nname (docs/PATTERNS.md) or sixteen hex digits, under the content and\nanchored at the content region's corner. Under `scrollbars` it fills the\nscrolled plane and scrolls with it (`vf-scroll-area`'s `pattern`). Unset,\nthe body stays white; an unrecognized value paints nothing and warns\nonce.",
22018
+ "fieldName": "pattern"
22019
+ },
21371
22020
  {
21372
22021
  "name": "width",
21373
22022
  "type": {
@@ -22419,7 +23068,7 @@
22419
23068
  "declarations": [
22420
23069
  {
22421
23070
  "kind": "class",
22422
- "description": "Shared base for the kit's editable text fields — `vf-text-field`,\n`vf-text-area` and `vf-number-field`. Builds on\nVfShadowRoleControl (form association, the disabled-value guard and\nthe name/description bridge every field needs, its role sitting on the inner\nnative control) and adds the value/label scaffolding\nevery field repeated: the reflected `name`, the `value`/`placeholder`/\n`readonly`/`label` props, the captured default restored on form reset, the\n`updated()` → VfShadowRoleControl.syncFormValue funnel, and the display-\nscaling controller. Pairs with the `vfField` css fragment (the white-well\nskin) in styles/base.ts.\n\nSubclasses render their own native control (`<input>`/`<textarea>` plus any\nadornments), tag it `class=\"vf-field\"`, and may enrich the emitted event\ndetail via emitValue.",
23071
+ "description": "Shared base for the kit's editable text fields — `vf-text-field`,\n`vf-text-area` and `vf-number-field`. Builds on\nVfShadowRoleControl (form association, the disabled-value guard and\nthe name/description bridge every field needs, its role sitting on the inner\nnative control) and adds the value/label scaffolding\nevery field repeated: the reflected `name`, the `value`/`placeholder`/\n`readonly`/`autoselect`/`label` props, the captured default restored on\nform reset, the `updated()` → VfShadowRoleControl.syncFormValue\nfunnel, `select()` and `focus()` on the inner control, and the display-\nscaling controller. Pairs with the `vfField` css fragment (the white-well\nskin) in styles/base.ts.\n\nSubclasses render their own native control (`<input>`/`<textarea>` plus any\nadornments), tag it `class=\"vf-field\"`, and may enrich the emitted event\ndetail via emitValue.",
22423
23072
  "name": "VfTextControlBase",
22424
23073
  "members": [
22425
23074
  {
@@ -22463,6 +23112,17 @@
22463
23112
  "attribute": "readonly",
22464
23113
  "reflects": true
22465
23114
  },
23115
+ {
23116
+ "kind": "field",
23117
+ "name": "autoselect",
23118
+ "type": {
23119
+ "text": "boolean"
23120
+ },
23121
+ "default": "false",
23122
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
23123
+ "attribute": "autoselect",
23124
+ "reflects": true
23125
+ },
22466
23126
  {
22467
23127
  "kind": "field",
22468
23128
  "name": "name",
@@ -22563,6 +23223,55 @@
22563
23223
  "description": "Classes for the `.vf-field-well` wrapper every field renders around its\nnative control: the shared skin hook (`vfField`), the grid-snap target, and\nthe focus rule's own gate. Assembled here so the three fields state the\nwrapper once and can't drift on what turns the rule on.",
22564
23224
  "readonly": true
22565
23225
  },
23226
+ {
23227
+ "kind": "field",
23228
+ "name": "committed",
23229
+ "type": {
23230
+ "text": "string | null"
23231
+ },
23232
+ "privacy": "protected",
23233
+ "default": "null",
23234
+ "description": "The text as last committed: taken when the field gains focus, then at\neach commit. A commit that brings nothing new isn't announced, so the\nnative `change` that follows a Return commit, or a step, is not a second\none."
23235
+ },
23236
+ {
23237
+ "kind": "field",
23238
+ "name": "control",
23239
+ "type": {
23240
+ "text": "HTMLInputElement | HTMLTextAreaElement | null"
23241
+ },
23242
+ "privacy": "protected",
23243
+ "description": "The inner native control every field renders, tagged `vf-field`.",
23244
+ "readonly": true
23245
+ },
23246
+ {
23247
+ "kind": "method",
23248
+ "name": "focus",
23249
+ "return": {
23250
+ "type": {
23251
+ "text": "void"
23252
+ }
23253
+ },
23254
+ "parameters": [
23255
+ {
23256
+ "name": "options",
23257
+ "optional": true,
23258
+ "type": {
23259
+ "text": "FocusOptions"
23260
+ }
23261
+ }
23262
+ ],
23263
+ "description": "Focuses the inner control, keeping its caret where it was. Chromium\nselects all of an input's text when the host hands the focus on, as a Tab\ndoes; `select()` and autoselect are how a field opens selected."
23264
+ },
23265
+ {
23266
+ "kind": "method",
23267
+ "name": "select",
23268
+ "return": {
23269
+ "type": {
23270
+ "text": "void"
23271
+ }
23272
+ },
23273
+ "description": "Select all of the field's text, as a native field's `select()` does. With\na new value not yet rendered, once it has: writing the value into the\ninput drops its selection, so `field.value = x; field.select()` selects\n`x`, as on a native field."
23274
+ },
22566
23275
  {
22567
23276
  "kind": "method",
22568
23277
  "name": "formResetCallback",
@@ -22648,6 +23357,44 @@
22648
23357
  ],
22649
23358
  "description": "Mirror the native control's value into `value` and announce a keystroke."
22650
23359
  },
23360
+ {
23361
+ "kind": "method",
23362
+ "name": "committedText",
23363
+ "privacy": "protected",
23364
+ "return": {
23365
+ "type": {
23366
+ "text": "string"
23367
+ }
23368
+ },
23369
+ "parameters": [
23370
+ {
23371
+ "name": "raw",
23372
+ "type": {
23373
+ "text": "string"
23374
+ }
23375
+ }
23376
+ ],
23377
+ "description": "The committed form of typed text: as typed here; `vf-number-field` clamps and rounds it."
23378
+ },
23379
+ {
23380
+ "kind": "method",
23381
+ "name": "commit",
23382
+ "privacy": "protected",
23383
+ "return": {
23384
+ "type": {
23385
+ "text": "void"
23386
+ }
23387
+ },
23388
+ "parameters": [
23389
+ {
23390
+ "name": "raw",
23391
+ "type": {
23392
+ "text": "string"
23393
+ }
23394
+ }
23395
+ ],
23396
+ "description": "Commit typed text: its committed form into `value`, announced unless it is what was last committed."
23397
+ },
22651
23398
  {
22652
23399
  "kind": "method",
22653
23400
  "name": "handleChange",
@@ -22665,7 +23412,26 @@
22665
23412
  }
22666
23413
  }
22667
23414
  ],
22668
- "description": "Mirror the native control's value into `value` and announce a commit."
23415
+ "description": "The native control's commit."
23416
+ },
23417
+ {
23418
+ "kind": "method",
23419
+ "name": "submitOnEnter",
23420
+ "privacy": "protected",
23421
+ "return": {
23422
+ "type": {
23423
+ "text": "void"
23424
+ }
23425
+ },
23426
+ "parameters": [
23427
+ {
23428
+ "name": "event",
23429
+ "type": {
23430
+ "text": "KeyboardEvent"
23431
+ }
23432
+ }
23433
+ ],
23434
+ "description": "A plain Return in a single-line field with a form: commit, then the\nform's implicit submission, the order a native input keeps (its `change`\ncomes before the submission). The keydown is cancelled, so an enclosing\nmodal does not route the same press to its default button as well."
22669
23435
  },
22670
23436
  {
22671
23437
  "kind": "field",
@@ -23222,6 +23988,15 @@
23222
23988
  "description": "Makes the field read-only (focusable, not editable).",
23223
23989
  "fieldName": "readonly"
23224
23990
  },
23991
+ {
23992
+ "name": "autoselect",
23993
+ "type": {
23994
+ "text": "boolean"
23995
+ },
23996
+ "default": "false",
23997
+ "description": "Opens with the whole text selected, so typing replaces it. Implies\n`autofocus`: the first control carrying either takes the opening focus of\nits `vf-dialog`, or of a window the shell's window manager opens. A dialog\nselects the text on every open, a window on its first open only. A click\nstill places the caret.",
23998
+ "fieldName": "autoselect"
23999
+ },
23225
24000
  {
23226
24001
  "name": "name",
23227
24002
  "type": {
@@ -23541,7 +24316,7 @@
23541
24316
  },
23542
24317
  {
23543
24318
  "kind": "class",
23544
- "description": "Base class for the modal shell `vf-dialog` — and for a consumer's own\nmodal (an alert box, say) authored against the kit.\n\nOwns the native `<dialog>` lifecycle every modal shares: `open` sync, `show()` /\n`close()`, the top/left placement (stated or centered) and the\nsingle `close` funnel that drops the written origin and fires `vf-close` with\nthe reason. Because every close path — Escape, `close()`, the opt-in\nlightDismiss click outside — routes through the native `close`\nevent, an Escape-close no longer leaves a stale origin behind, so the next\nopen re-derives it.\n\nIt also owns the two keyboard rules every classic dialog followed (see\ndefaultButton and initialFocusTarget): Return or Enter\nactivates the default button from anywhere in the dialog, and the box opens\nwith the insertion point in its first text field — or, with none, focus on\nthe default button.\n\nRemoving an open modal from the DOM is a close path too. HTML's dialog\n*removing steps* take the element out of the top layer **without** running\nthe close algorithm — no `close` event, no focus restoration — which is\nexactly what the standard framework pattern of unmounting a dialog instead\nof calling `close()` does. `disconnectedCallback` routes that path through\nthe same funnel: the removed element still fires `vf-close` (heard by\nlisteners on the element itself — it has left the tree, so nothing\nbubbles), `open` and the pinned margins reconcile so a re-append mounts it\nclosed and re-centered, and focus returns to the element that was focused\nwhen the modal opened.\n\nA `<form method=\"dialog\">` inside the modal closes it with the submitting\nbutton's `value` as returnValue, as a form inside a native\n`<dialog>` does. The platform's own rule looks for a `<dialog>` around the\nform, and this one is in the shadow root, so the modal listens for the\nsubmit itself.\n\nSubclasses supply only the frame chrome: a `render()` returning\n`<dialog",
24319
+ "description": "Base class for the modal shell `vf-dialog` — and for a consumer's own\nmodal (an alert box, say) authored against the kit.\n\nOwns the native `<dialog>` lifecycle every modal shares: `open` sync, `show()` /\n`close()`, the top/left placement (stated or centered) and the\nsingle `close` funnel that drops the written origin and fires `vf-close` with\nthe reason. Because every close path — Escape, `close()`, the opt-in\nlightDismiss click outside — routes through the native `close`\nevent, an Escape-close no longer leaves a stale origin behind, so the next\nopen re-derives it.\n\nIt also owns the two keyboard rules every classic dialog followed (see\ndefaultButton and initialFocusTarget): Return or Enter\nactivates the default button from anywhere in the dialog, and the box opens\nwith the insertion point in its first text field — or, with none, focus on\nthe default button. A field marked `autoselect` takes the focus with its\ntext selected, on every open.\n\nRemoving an open modal from the DOM is a close path too. HTML's dialog\n*removing steps* take the element out of the top layer **without** running\nthe close algorithm — no `close` event, no focus restoration — which is\nexactly what the standard framework pattern of unmounting a dialog instead\nof calling `close()` does. `disconnectedCallback` routes that path through\nthe same funnel: the removed element still fires `vf-close` (heard by\nlisteners on the element itself — it has left the tree, so nothing\nbubbles), `open` and the pinned margins reconcile so a re-append mounts it\nclosed and re-centered, and focus returns to the element that was focused\nwhen the modal opened.\n\nA `<form method=\"dialog\">` inside the modal closes it with the submitting\nbutton's `value` as returnValue, as a form inside a native\n`<dialog>` does. The platform's own rule looks for a `<dialog>` around the\nform, and this one is in the shadow root, so the modal listens for the\nsubmit itself.\n\nSubclasses supply only the frame chrome: a `render()` returning\n`<dialog",
23545
24320
  "name": "VfModalDialog",
23546
24321
  "members": [
23547
24322
  {
@@ -23678,6 +24453,16 @@
23678
24453
  "default": "null",
23679
24454
  "description": "The value `close(value)` gave, pending for the next native `close` event."
23680
24455
  },
24456
+ {
24457
+ "kind": "field",
24458
+ "name": "#closeKeys",
24459
+ "privacy": "private",
24460
+ "type": {
24461
+ "text": "VfCloseKeys | null"
24462
+ },
24463
+ "default": "null",
24464
+ "description": "The modifier keys a close box's click held, pending for the next native `close` event."
24465
+ },
23681
24466
  {
23682
24467
  "kind": "field",
23683
24468
  "name": "#onSubmit",
@@ -23719,7 +24504,7 @@
23719
24504
  "text": "HTMLElement | null"
23720
24505
  },
23721
24506
  "privacy": "protected",
23722
- "description": "Where focus lands on open. The classic Dialog Manager put the insertion\npoint in the first editable text item and gave nothing else focus at all;\nthe web needs a focused control for the keyboard to have anywhere to be,\nso with no text field the default button takes it (which is also what\nmakes Return and Space work there without a Tab). In order:\n\n1. a slotted control carrying `autofocus` — the author's say;\n2. the first enabled text-entry control (`vf-text-field`,\n `vf-number-field`, `vf-text-area`, or a native text input/textarea);\n3. the defaultButton;\n4. null — leave the browser's own choice alone.\n\nLeft to itself, `showModal()` focuses the first focusable thing in flat\ntree order, which for a Cancel/OK row is Cancel, and for a body with a\nlink in it is the link — so Return did the one thing a classic dialog's\nReturn never did. Override to choose differently.",
24507
+ "description": "Where focus lands on open. The classic Dialog Manager put the insertion\npoint in the first editable text item and gave nothing else focus at all;\nthe web needs a focused control for the keyboard to have anywhere to be,\nso with no text field the default button takes it (which is also what\nmakes Return and Space work there without a Tab). In order:\n\n1. the first slotted control carrying `autofocus` or `autoselect` — the\n author's say;\n2. the first enabled text-entry control (`vf-text-field`,\n `vf-number-field`, `vf-text-area`, or a native text input/textarea);\n3. the defaultButton;\n4. null — leave the browser's own choice alone.\n\nLeft to itself, `showModal()` focuses the first focusable thing in flat\ntree order, which for a Cancel/OK row is Cancel, and for a body with a\nlink in it is the link — so Return did the one thing a classic dialog's\nReturn never did. Override to choose differently. A target marked\n`autoselect` has its text selected once `vf-show` has fired.",
23723
24508
  "readonly": true
23724
24509
  },
23725
24510
  {
@@ -23728,10 +24513,10 @@
23728
24513
  "privacy": "private",
23729
24514
  "return": {
23730
24515
  "type": {
23731
- "text": "void"
24516
+ "text": "HTMLElement | null"
23732
24517
  }
23733
24518
  },
23734
- "description": "Hand focus to initialFocusTarget, right after `showModal()`'s own\nfocusing steps have run (so this is the last word, not a race)."
24519
+ "description": "Hand focus to initialFocusTarget, right after `showModal()`'s own\nfocusing steps have run (so this is the last word, not a race). Returns\nthe element focused, for `vf-show`."
23735
24520
  },
23736
24521
  {
23737
24522
  "kind": "field",
@@ -23795,6 +24580,25 @@
23795
24580
  ],
23796
24581
  "description": "Close the modal, with `returnValue` as its answer when one is given.\nFires `vf-close` with `{ reason: 'close', returnValue }`."
23797
24582
  },
24583
+ {
24584
+ "kind": "method",
24585
+ "name": "closeFromBox",
24586
+ "privacy": "protected",
24587
+ "return": {
24588
+ "type": {
24589
+ "text": "void"
24590
+ }
24591
+ },
24592
+ "parameters": [
24593
+ {
24594
+ "name": "keys",
24595
+ "type": {
24596
+ "text": "VfCloseKeys"
24597
+ }
24598
+ }
24599
+ ],
24600
+ "description": "Close from a close box, its `vf-close` carrying the modifier keys held on the click."
24601
+ },
23798
24602
  {
23799
24603
  "kind": "method",
23800
24604
  "name": "#viewport",
@@ -23975,6 +24779,10 @@
23975
24779
  }
23976
24780
  ],
23977
24781
  "events": [
24782
+ {
24783
+ "description": "The modal opened: it is in the top layer, placed, and its initial focus is set. `detail: { focus }`, the element focused. The page's moment to finish composing it, such as measuring copy that varies. A field marked `autoselect` has its text selected after the event, so a value set in a handler is the one selected. Fired inside `show()` once the modal has rendered, else at its first render.",
24784
+ "name": "vf-show"
24785
+ },
23978
24786
  {
23979
24787
  "description": "The modal closed. `detail: { reason: 'escape' | 'close' | 'outside', returnValue: string | null }`.",
23980
24788
  "name": "vf-close"