vintage-frames 0.11.0 → 0.12.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.
@@ -10834,7 +10834,7 @@
10834
10834
  "declarations": [
10835
10835
  {
10836
10836
  "kind": "class",
10837
- "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected` and the transient\n`active` highlight, and slots this element into its popup panel.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.",
10837
+ "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected`, the transient\n`active` highlight and `size`, and slots this element into its popup panel.\nUnder `size=\"small\"` the row is the small pill's 10px content height, in the\nbody face, and clips its own box.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.",
10838
10838
  "name": "VfOption",
10839
10839
  "cssProperties": [
10840
10840
  {
@@ -10905,6 +10905,17 @@
10905
10905
  "attribute": "active",
10906
10906
  "reflects": true
10907
10907
  },
10908
+ {
10909
+ "kind": "field",
10910
+ "name": "size",
10911
+ "type": {
10912
+ "text": "VfSelectSize"
10913
+ },
10914
+ "default": "'regular'",
10915
+ "description": "The parent select's `size`. Managed by the parent.",
10916
+ "attribute": "size",
10917
+ "reflects": true
10918
+ },
10908
10919
  {
10909
10920
  "kind": "field",
10910
10921
  "name": "#internals",
@@ -11013,6 +11024,15 @@
11013
11024
  "description": "Transient highlight (hover / keyboard cursor) — full-row inversion.\nManaged by the parent `<vf-select>`; not part of the authoring API.",
11014
11025
  "fieldName": "active"
11015
11026
  },
11027
+ {
11028
+ "name": "size",
11029
+ "type": {
11030
+ "text": "VfSelectSize"
11031
+ },
11032
+ "default": "'regular'",
11033
+ "description": "The parent select's `size`. Managed by the parent.",
11034
+ "fieldName": "size"
11035
+ },
11016
11036
  {
11017
11037
  "name": "top",
11018
11038
  "type": {
@@ -13364,7 +13384,7 @@
13364
13384
  "declarations": [
13365
13385
  {
13366
13386
  "kind": "class",
13367
- "description": "`<vf-select>` — the classic System 7 popup menu control (\"Macintosh HD ▼\").\n\nChildren are `<vf-option>` elements in the default slot. The closed control\nis a white box with a 1px black border, the small 1px hard shadow, the\nselected option's label on the left and a solid black ▼ triangle on the\nright. The open panel uses the shared `.vf-panel` recipe and is positioned\n`position: fixed` (computed from `getBoundingClientRect()`) so it escapes\nclipping containers; when possible the currently-selected item opens\ndirectly over the control, like the real popup menu.\n\nPointer — two interaction styles are supported and disambiguated by the\ngesture itself, resolved at the first pointer release:\n - System 7 press-drag-release: press the pill (the list appears under the\n pointer), drag onto an item, release over it to pick — one continuous\n press. Releasing over the current item or off the list closes with no\n change.\n - Modern click-to-open: a quick in-place click (no drag, released within\n PRESS_HOLD_MS) leaves the list open; a second, independent click\n then picks an item.\nThe two share one opening trigger (pointerdown) and diverge only on how the\npress ends — whether the pointer travelled to another item, and (for an\nin-place release) whether it was a quick tap or a held press. The pull-down\nmenus drive themselves the same way, on the same threshold; that half lives\nin src/menu-press.ts, because one menu press may travel across a whole bar.\n\nA list too tall for the screen is **clipped**, never scrolled: the edge slot\nwith items beyond it shows a solid arrow instead of a row, which rolls the\nlist one row at a time while the pointer rests on it. The clamp is quantized\nto the pill lattice, so a clipped popup still opens with its selected row\nover the closed pill — and the panel keeps every slot the list asked for, so\na box that had to slide to fit the screen opens with *blank rows* at whichever\nend the list no longer reaches: the exact travel it will roll through, in\neither direction. See src/popup-overflow.ts.\n\nKeyboard: Space/Enter/ArrowDown open; while open ArrowUp/ArrowDown move the\nhighlight, Home/End jump, Enter/Space select, Escape cancels. Selecting an\nitem plays the classic inversion blink (~250 ms) before closing. Keyboard\nfocus is marked with the kit's 1px dashed rule under the closed pill\n(`vfFocusUnderline`) rather than a ring around it — keyboard only, which\nhere means the page's input modality rather than `:focus-visible` (the pill\ndrives its own focus, and Blink reads that as visible either way).\n\nForm-associated: submits `value` under `name`.",
13387
+ "description": "`<vf-select>` — the classic System 7 popup menu control (\"Macintosh HD ▼\").\n\nChildren are `<vf-option>` elements in the default slot. The closed control\nis a white box with a 1px black border, the small 1px hard shadow, the\nselected option's label on the left and a solid black ▼ triangle on the\nright. The open panel uses the shared `.vf-panel` recipe and is positioned\n`position: fixed` (computed from `getBoundingClientRect()`) so it escapes\nclipping containers; when possible the currently-selected item opens\ndirectly over the control, like the real popup menu.\n\nPointer — two interaction styles are supported and disambiguated by the\ngesture itself, resolved at the first pointer release:\n - System 7 press-drag-release: press the pill (the list appears under the\n pointer), drag onto an item, release over it to pick — one continuous\n press. Releasing over the current item or off the list closes with no\n change.\n - Modern click-to-open: a quick in-place click (no drag, released within\n PRESS_HOLD_MS) leaves the list open; a second, independent click\n then picks an item.\nThe two share one opening trigger (pointerdown) and diverge only on how the\npress ends — whether the pointer travelled to another item, and (for an\nin-place release) whether it was a quick tap or a held press. The pull-down\nmenus drive themselves the same way, on the same threshold; that half lives\nin src/menu-press.ts, because one menu press may travel across a whole bar.\n\nA list too tall for the screen is **clipped**, never scrolled: the edge slot\nwith items beyond it shows a solid arrow instead of a row, which rolls the\nlist one row at a time while the pointer rests on it. The clamp is quantized\nto the pill lattice, so a clipped popup still opens with its selected row\nover the closed pill — and the panel keeps every slot the list asked for, so\na box that had to slide to fit the screen opens with *blank rows* at whichever\nend the list no longer reaches: the exact travel it will roll through, in\neither direction. See src/popup-overflow.ts.\n\n`size=\"small\"` sets the pill and its rows in the body face: a 12px pill\n(`--vf-popup-height-small`) over 10px rows, the baseline 8 rows down so the\nface's 2-row descenders end on the last content row. Its ▼ and scroll\narrows are the 9×5 `CARET_DOWN_SMALL` / `CARET_UP_SMALL`; the ✓ and the\nhorizontal insets are the regular pill's. Marks above a capital (É, Å, Ñ)\nreach past the 8 rows above the baseline and are clipped.\n\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`.",
13368
13388
  "name": "VfSelect",
13369
13389
  "cssProperties": [
13370
13390
  {
@@ -13372,6 +13392,11 @@
13372
13392
  "name": "--vf-popup-height",
13373
13393
  "default": "18px"
13374
13394
  },
13395
+ {
13396
+ "description": "`vf-select[size=\"small\"]` pill (border box; its rows are this less the two borders)",
13397
+ "name": "--vf-popup-height-small",
13398
+ "default": "12px"
13399
+ },
13375
13400
  {
13376
13401
  "description": "room a clipped popup panel keeps clear at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4",
13377
13402
  "name": "--vf-popup-inset-top",
@@ -13417,18 +13442,6 @@
13417
13442
  }
13418
13443
  ],
13419
13444
  "members": [
13420
- {
13421
- "kind": "field",
13422
- "name": "ITEM_HEIGHT",
13423
- "type": {
13424
- "text": "number"
13425
- },
13426
- "privacy": "private",
13427
- "static": true,
13428
- "readonly": true,
13429
- "default": "16",
13430
- "description": "Fallback height of one option row — the pill's *content* height\n(`--vf-popup-height` 18px minus its two 1px borders). Used to overlay the\nselected row's white cell exactly on the closed pill. `positionPanel`\nprefers the row's *rendered* height so a re-themed `--vf-popup-height`\nkeeps the overlay aligned; this is the no-options fallback and must match\n`vf-option`'s default row height."
13431
- },
13432
13445
  {
13433
13446
  "kind": "field",
13434
13447
  "name": "value",
@@ -13450,6 +13463,28 @@
13450
13463
  "attribute": "name",
13451
13464
  "reflects": true
13452
13465
  },
13466
+ {
13467
+ "kind": "field",
13468
+ "name": "size",
13469
+ "type": {
13470
+ "text": "VfSelectSize"
13471
+ },
13472
+ "default": "'regular'",
13473
+ "description": "`regular` (the 18px pill in the display face) or `small` (12px, in the\nbody face). Any other value renders as `regular`. The select passes it to\nits options.",
13474
+ "attribute": "size",
13475
+ "reflects": true
13476
+ },
13477
+ {
13478
+ "kind": "field",
13479
+ "name": "noShadow",
13480
+ "type": {
13481
+ "text": "boolean"
13482
+ },
13483
+ "default": "false",
13484
+ "description": "Draws the closed pill without its 1px hard shadow. The open list keeps\nits shadow.",
13485
+ "attribute": "no-shadow",
13486
+ "reflects": true
13487
+ },
13453
13488
  {
13454
13489
  "kind": "field",
13455
13490
  "name": "label",
@@ -13869,6 +13904,17 @@
13869
13904
  },
13870
13905
  "description": "Marks the option matching `value` as selected."
13871
13906
  },
13907
+ {
13908
+ "kind": "method",
13909
+ "name": "applySize",
13910
+ "privacy": "private",
13911
+ "return": {
13912
+ "type": {
13913
+ "text": "void"
13914
+ }
13915
+ },
13916
+ "description": "Passes the pill size to every option; anything but `small` is regular."
13917
+ },
13872
13918
  {
13873
13919
  "kind": "field",
13874
13920
  "name": "handleSlotChange",
@@ -14932,6 +14978,24 @@
14932
14978
  "description": "Form field name used when submitting the associated form.",
14933
14979
  "fieldName": "name"
14934
14980
  },
14981
+ {
14982
+ "name": "size",
14983
+ "type": {
14984
+ "text": "VfSelectSize"
14985
+ },
14986
+ "default": "'regular'",
14987
+ "description": "`regular` (the 18px pill in the display face) or `small` (12px, in the\nbody face). Any other value renders as `regular`. The select passes it to\nits options.",
14988
+ "fieldName": "size"
14989
+ },
14990
+ {
14991
+ "name": "no-shadow",
14992
+ "type": {
14993
+ "text": "boolean"
14994
+ },
14995
+ "default": "false",
14996
+ "description": "Draws the closed pill without its 1px hard shadow. The open list keeps\nits shadow.",
14997
+ "fieldName": "noShadow"
14998
+ },
14935
14999
  {
14936
15000
  "name": "label",
14937
15001
  "type": {
@@ -1,5 +1,6 @@
1
1
  import { LitElement } from 'lit';
2
2
  import type { PropertyValues } from 'lit';
3
+ import type { VfSelectSize } from './vf-select.js';
3
4
  declare const VfOption_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
4
5
  /**
5
6
  * `<vf-option>` — a single choice inside a `<vf-select>` popup menu.
@@ -8,8 +9,10 @@ declare const VfOption_base: (new (...args: any[]) => import("../position.js").V
8
9
  * its slotted label at menu-item metrics (16px row — the pill's content height,
9
10
  * so a selected option overlays the closed pill exactly; the left checkmark gutter is
10
11
  * `--vf-select-gutter`, shared with the closed control's left inset so the value
11
- * doesn't shift on open). The parent select manages `selected` and the transient
12
- * `active` highlight, and slots this element into its popup panel.
12
+ * doesn't shift on open). The parent select manages `selected`, the transient
13
+ * `active` highlight and `size`, and slots this element into its popup panel.
14
+ * Under `size="small"` the row is the small pill's 10px content height, in the
15
+ * body face, and clips its own box.
13
16
  *
14
17
  * The host carries `role="option"` with `aria-selected`/`aria-disabled`.
15
18
  *
@@ -46,6 +49,8 @@ export declare class VfOption extends VfOption_base {
46
49
  * Managed by the parent `<vf-select>`; not part of the authoring API.
47
50
  */
48
51
  active: boolean;
52
+ /** The parent select's `size`. Managed by the parent. */
53
+ size: VfSelectSize;
49
54
  constructor();
50
55
  connectedCallback(): void;
51
56
  protected updated(changed: PropertyValues<this>): void;
@@ -2,18 +2,19 @@ import { vfElement as e } from "../define.js";
2
2
  import { ScaleController as t } from "../scale.js";
3
3
  import n from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
4
4
  import { VfPositioned as r } from "../position.js";
5
- import { vfDisplay as i } from "../styles/recipes/display-face.js";
6
- import { vfBase as a } from "../styles/recipes/host.js";
7
- import { CHECKMARK as o, glyphSvg as s } from "../glyphs.js";
8
- import { LitElement as c, css as l, html as u } from "lit";
9
- import { property as d } from "lit/decorators.js";
5
+ import { vfBodyDecls as i } from "../styles/recipes/body-face.js";
6
+ import { vfDisplay as a } from "../styles/recipes/display-face.js";
7
+ import { vfBase as o } from "../styles/recipes/host.js";
8
+ import { CHECKMARK as s, glyphSvg as c } from "../glyphs.js";
9
+ import { LitElement as l, css as u, html as d } from "lit";
10
+ import { property as f } from "lit/decorators.js";
10
11
  //#region src/components/vf-option.ts
11
- var f = class extends r(c) {
12
+ var p = class extends r(l) {
12
13
  static {
13
14
  this.styles = [
15
+ o,
14
16
  a,
15
- i,
16
- l`
17
+ u`
17
18
  :host {
18
19
  position: relative;
19
20
  display: flex;
@@ -43,6 +44,18 @@ var f = class extends r(c) {
43
44
  cursor: var(--vf-cursor, default);
44
45
  outline: none;
45
46
  }
47
+ /* The small row: the select restates --vf-popup-height on itself, so the
48
+ height above already follows it. The line box and padding match the
49
+ small pill's label (see vf-select's .value): 8 rows above the baseline,
50
+ 2 below it for the descenders. The row clips its own box, so a mark
51
+ above a capital doesn't draw into the row above, and the list clips
52
+ what the closed pill clips. */
53
+ :host([size='small']) {
54
+ ${i}
55
+ line-height: calc(var(--vf-scale, 1) * (var(--vf-popup-height, 12px) - 4px));
56
+ padding-bottom: calc(var(--vf-scale, 1) * 2px);
57
+ overflow: clip;
58
+ }
46
59
  /* Hover/keyboard highlight — classic full-row inversion. The parent
47
60
  vf-select drives [active] for both pointer and keyboard so only one
48
61
  row is ever highlighted at a time. */
@@ -81,6 +94,11 @@ var f = class extends r(c) {
81
94
  width: calc(var(--vf-scale, 1) * 9px);
82
95
  height: calc(var(--vf-scale, 1) * 9px);
83
96
  }
97
+ /* The ✓'s 8 ink rows centered in the 10px row, 1 above and 1 below. Its
98
+ top is level with the capitals' top, as at row 3 above. */
99
+ :host([size='small']) .check {
100
+ top: calc(var(--vf-scale, 1) * 1px);
101
+ }
84
102
  :host([selected]) .check {
85
103
  visibility: visible;
86
104
  }
@@ -89,7 +107,7 @@ var f = class extends r(c) {
89
107
  }
90
108
  #e;
91
109
  constructor() {
92
- super(), this.scale = new t(this), this.value = "", this.disabled = !1, this.selected = !1, this.active = !1, this.#e = this.attachInternals(), this.#e.role = "option";
110
+ super(), this.scale = new t(this), this.value = "", this.disabled = !1, this.selected = !1, this.active = !1, this.size = "regular", this.#e = this.attachInternals(), this.#e.role = "option";
93
111
  }
94
112
  connectedCallback() {
95
113
  super.connectedCallback(), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "-1");
@@ -98,23 +116,23 @@ var f = class extends r(c) {
98
116
  e.has("selected") && (this.#e.ariaSelected = this.selected ? "true" : "false"), e.has("disabled") && (this.#e.ariaDisabled = this.disabled ? "true" : null);
99
117
  }
100
118
  render() {
101
- return u`
119
+ return d`
102
120
  <span class="check" part="check" aria-hidden="true"
103
- >${s(o, "checkmark")}</span
121
+ >${c(s, "checkmark")}</span
104
122
  >
105
123
  <slot></slot>
106
124
  `;
107
125
  }
108
126
  };
109
- n([d()], f.prototype, "value", void 0), n([d({
127
+ n([f()], p.prototype, "value", void 0), n([f({
110
128
  type: Boolean,
111
129
  reflect: !0
112
- })], f.prototype, "disabled", void 0), n([d({
130
+ })], p.prototype, "disabled", void 0), n([f({
113
131
  type: Boolean,
114
132
  reflect: !0
115
- })], f.prototype, "selected", void 0), n([d({
133
+ })], p.prototype, "selected", void 0), n([f({
116
134
  type: Boolean,
117
135
  reflect: !0
118
- })], f.prototype, "active", void 0), f = n([e("vf-option")], f);
136
+ })], p.prototype, "active", void 0), n([f({ reflect: !0 })], p.prototype, "size", void 0), p = n([e("vf-option")], p);
119
137
  //#endregion
120
- export { f as VfOption };
138
+ export { p as VfOption };
@@ -1,5 +1,7 @@
1
1
  import type { PropertyValues } from 'lit';
2
2
  import { VfShadowRoleControl } from '../form-control.js';
3
+ /** The two pill sizes: the display face at 18px, or the body face at 12px. */
4
+ export type VfSelectSize = 'regular' | 'small';
3
5
  declare const VfSelect_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof VfShadowRoleControl;
4
6
  /**
5
7
  * `<vf-select>` — the classic System 7 popup menu control ("Macintosh HD ▼").
@@ -36,6 +38,16 @@ declare const VfSelect_base: (new (...args: any[]) => import("../position.js").V
36
38
  * end the list no longer reaches: the exact travel it will roll through, in
37
39
  * either direction. See src/popup-overflow.ts.
38
40
  *
41
+ * `size="small"` sets the pill and its rows in the body face: a 12px pill
42
+ * (`--vf-popup-height-small`) over 10px rows, the baseline 8 rows down so the
43
+ * face's 2-row descenders end on the last content row. Its ▼ and scroll
44
+ * arrows are the 9×5 `CARET_DOWN_SMALL` / `CARET_UP_SMALL`; the ✓ and the
45
+ * horizontal insets are the regular pill's. Marks above a capital (É, Å, Ñ)
46
+ * reach past the 8 rows above the baseline and are clipped.
47
+ *
48
+ * `no-shadow` draws the closed pill without its 1px hard shadow, and the focus
49
+ * rule moves up the row the shadow took. The open list keeps its shadow.
50
+ *
39
51
  * Keyboard: Space/Enter/ArrowDown open; while open ArrowUp/ArrowDown move the
40
52
  * highlight, Home/End jump, Enter/Space select, Escape cancels. Selecting an
41
53
  * item plays the classic inversion blink (~250 ms) before closing. Keyboard
@@ -63,6 +75,8 @@ declare const VfSelect_base: (new (...args: any[]) => import("../position.js").V
63
75
  * in its edge row slots.
64
76
  * @cssprop [--vf-popup-height=18px] - `vf-select` pill (border box; its 1px
65
77
  * hard shadow makes the sheet's 157×19 ink box)
78
+ * @cssprop [--vf-popup-height-small=12px] - `vf-select[size="small"]` pill
79
+ * (border box; its rows are this less the two borders)
66
80
  * @cssprop [--vf-popup-inset-top=4px] - room a clipped popup panel keeps clear
67
81
  * at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to
68
82
  * clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4
@@ -73,20 +87,22 @@ declare const VfSelect_base: (new (...args: any[]) => import("../position.js").V
73
87
  * on open)
74
88
  */
75
89
  export declare class VfSelect extends VfSelect_base {
76
- /**
77
- * Fallback height of one option row — the pill's *content* height
78
- * (`--vf-popup-height` 18px minus its two 1px borders). Used to overlay the
79
- * selected row's white cell exactly on the closed pill. `positionPanel`
80
- * prefers the row's *rendered* height so a re-themed `--vf-popup-height`
81
- * keeps the overlay aligned; this is the no-options fallback and must match
82
- * `vf-option`'s default row height.
83
- */
84
- private static readonly ITEM_HEIGHT;
85
90
  static styles: import("lit").CSSResult[];
86
91
  /** Value of the selected option. Adopts the first enabled option if unset. */
87
92
  value: string;
88
93
  /** Form field name used when submitting the associated form. */
89
94
  name: string;
95
+ /**
96
+ * `regular` (the 18px pill in the display face) or `small` (12px, in the
97
+ * body face). Any other value renders as `regular`. The select passes it to
98
+ * its options.
99
+ */
100
+ size: VfSelectSize;
101
+ /**
102
+ * Draws the closed pill without its 1px hard shadow. The open list keeps
103
+ * its shadow.
104
+ */
105
+ noShadow: boolean;
90
106
  /**
91
107
  * Accessible name for the combobox control (`aria-label`). Left empty, the
92
108
  * name falls back to whatever the host carries — `aria-labelledby`,
@@ -202,6 +218,8 @@ export declare class VfSelect extends VfSelect_base {
202
218
  private optionValue;
203
219
  /** Marks the option matching `value` as selected. */
204
220
  private applySelection;
221
+ /** Passes the pill size to every option; anything but `small` is regular. */
222
+ private applySize;
205
223
  private handleSlotChange;
206
224
  private openPanel;
207
225
  /**
@@ -3,36 +3,31 @@ import { vfElement as n } from "../define.js";
3
3
  import { ScaleController as r, sys as i } from "../scale.js";
4
4
  import a from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
5
5
  import { VfPositioned as o } from "../position.js";
6
- import { vfDisplay as s } from "../styles/recipes/display-face.js";
7
- import { vfBase as c } from "../styles/recipes/host.js";
8
- import { vfPanel as l } from "../styles/recipes/surface.js";
9
- import { vfFocusUnderline as u } from "../styles/recipes/focus.js";
10
- import { GridSnapController as d } from "../grid-snap.js";
11
- import { DocumentListenersController as f } from "../document-listeners.js";
12
- import { runSelectionBlink as p } from "../motion.js";
13
- import { CARET_DOWN as m, CARET_UP as h, glyphSvg as g } from "../glyphs.js";
14
- import { VfShadowRoleControl as _ } from "../form-control.js";
15
- import { FocusRuleController as v } from "../focus-modality.js";
16
- import { VfOption as y } from "./vf-option.js";
17
- import { clampScroll as b, ensureVisibleScroll as x, firstPickableRow as S, lastPickableRow as C, layoutClampedPopup as w } from "../popup-overflow.js";
18
- import { TypeAheadBuffer as T } from "../type-ahead.js";
19
- import { css as E, html as D, nothing as O } from "lit";
20
- import { property as k, query as A, queryAssignedElements as j, state as M } from "lit/decorators.js";
21
- import { classMap as N } from "lit/directives/class-map.js";
6
+ import { vfBodyDecls as s } from "../styles/recipes/body-face.js";
7
+ import { vfDisplay as c } from "../styles/recipes/display-face.js";
8
+ import { vfBase as l } from "../styles/recipes/host.js";
9
+ import { vfPanel as u } from "../styles/recipes/surface.js";
10
+ import { vfFocusUnderline as d } from "../styles/recipes/focus.js";
11
+ import { GridSnapController as f } from "../grid-snap.js";
12
+ import { DocumentListenersController as p } from "../document-listeners.js";
13
+ import { runSelectionBlink as m } from "../motion.js";
14
+ import { CARET_DOWN as h, CARET_DOWN_SMALL as g, CARET_UP as _, CARET_UP_SMALL as v, glyphSvg as y } from "../glyphs.js";
15
+ import { VfShadowRoleControl as b } from "../form-control.js";
16
+ import { FocusRuleController as x } from "../focus-modality.js";
17
+ import { VfOption as S } from "./vf-option.js";
18
+ import { clampScroll as C, ensureVisibleScroll as w, firstPickableRow as T, lastPickableRow as E, layoutClampedPopup as D } from "../popup-overflow.js";
19
+ import { TypeAheadBuffer as O } from "../type-ahead.js";
20
+ import { css as k, html as A, nothing as j } from "lit";
21
+ import { property as M, query as N, queryAssignedElements as P, state as F } from "lit/decorators.js";
22
+ import { classMap as I } from "lit/directives/class-map.js";
22
23
  //#region src/components/vf-select.ts
23
- var P, F = class extends o(_) {
24
- static {
25
- P = this;
26
- }
27
- static {
28
- this.ITEM_HEIGHT = 16;
29
- }
24
+ var L = class extends o(b) {
30
25
  static {
31
26
  this.styles = [
32
- c,
33
- s,
34
27
  l,
35
- E`
28
+ c,
29
+ u,
30
+ k`
36
31
  :host {
37
32
  /* A popup menu is sized to its widest option — never stretched to fill
38
33
  its container. fit-content holds that intrinsic width even inside a
@@ -41,6 +36,21 @@ var P, F = class extends o(_) {
41
36
  too narrow. Authors opt into filling via flex:1 / width / align-self. */
42
37
  display: inline-block;
43
38
  width: fit-content;
39
+ /* How deep a shadow the closed pill casts, resolved once so the shadow
40
+ and the focus rule below it read the same depth. The panel's shadow
41
+ is its own (--vf-shadow-offset). */
42
+ --_shadow-depth: 1px;
43
+ }
44
+ :host([no-shadow]) {
45
+ --_shadow-depth: 0px;
46
+ }
47
+ /* The small pill restates the height token on the host, so the pill, the
48
+ arrow slots and the slotted options (which inherit it) all derive from
49
+ the one small height. A --vf-popup-height set on the element itself
50
+ still wins over :host. */
51
+ :host([size='small']) {
52
+ --vf-popup-height: var(--vf-popup-height-small, 12px);
53
+ ${s}
44
54
  }
45
55
  .control {
46
56
  /* Also the anchor the focus rule below hangs from. */
@@ -63,8 +73,9 @@ var P, F = class extends o(_) {
63
73
  background: var(--vf-white, #fff);
64
74
  border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
65
75
  border-radius: 0;
66
- box-shadow: calc(var(--vf-scale, 1) * 1px) calc(var(--vf-scale, 1) * 1px)
67
- 0 0 var(--vf-black, #000);
76
+ /* At depth 0 the shadow is the border box itself, which paints nothing. */
77
+ box-shadow: calc(var(--vf-scale, 1) * var(--_shadow-depth))
78
+ calc(var(--vf-scale, 1) * var(--_shadow-depth)) 0 0 var(--vf-black, #000);
68
79
  /* The press-drag gesture owns pointer moves while the button is held;
69
80
  suppress the browser's own touch panning/scrolling so a touch drag
70
81
  tracks the list instead of scrolling the page. */
@@ -78,7 +89,8 @@ var P, F = class extends o(_) {
78
89
 
79
90
  The offset counts every row of ink below the pseudo-element's padding
80
91
  box before the blank row and the rule itself — the 1px border, then
81
- the 1px hard shadow: −(1 + 1 + 1 + 1). The ±1px sides widen it from
92
+ the hard shadow (1px, or none under no-shadow): −(1 + 1 + depth + 1).
93
+ The ±1px sides widen it from
82
94
  that same padding box to the border box, which is the shape the pill
83
95
  reads as (the shadow is a depth cue, not part of the silhouette).
84
96
 
@@ -95,8 +107,8 @@ var P, F = class extends o(_) {
95
107
  outline: none;
96
108
  }
97
109
  .control.vf-focus-rule::after {
98
- --vf-focus-underline-offset: -4px;
99
- ${u}
110
+ --vf-focus-underline-offset: calc(-3px - var(--_shadow-depth));
111
+ ${d}
100
112
  left: calc(var(--vf-scale, 1) * -1px);
101
113
  right: calc(var(--vf-scale, 1) * -1px);
102
114
  }
@@ -121,6 +133,23 @@ var P, F = class extends o(_) {
121
133
  overflow: hidden;
122
134
  text-overflow: ellipsis;
123
135
  }
136
+ /* A line box as tall as the small pill's content (10 rows) centers the
137
+ body face's 16px em with 9 rows above the baseline and 1 below, which
138
+ puts the second descender row on the border. An 8px line box leaves 8
139
+ above and 2 below for the descenders.
140
+
141
+ The em's 4px descent reaches 2 rows past those 2, and this box is a
142
+ scroll container (overflow: hidden, for the ellipsis): with the clip
143
+ ending at the content's last row, that inkless spill is 2px of
144
+ scrollable overflow a find-in-page could scroll. So the padding covers
145
+ all 4 rows below the baseline, and the negative margin hands the extra
146
+ 2 back to layout. The clip now ends 2 rows below the content, on the
147
+ border and the shadow, where the face draws nothing. */
148
+ :host([size='small']) .value {
149
+ line-height: calc(var(--vf-scale, 1) * (var(--vf-popup-height, 12px) - 4px));
150
+ padding-bottom: calc(var(--vf-scale, 1) * 4px);
151
+ margin-bottom: calc(var(--vf-scale, 1) * -2px);
152
+ }
124
153
  /* Sizer contributes width only: collapsed to zero height and clipped so it
125
154
  never adds a row, but its widest line still drives the grid cell width. */
126
155
  .sizer {
@@ -143,6 +172,17 @@ var P, F = class extends o(_) {
143
172
  width: calc(var(--vf-scale, 1) * 11px);
144
173
  height: calc(var(--vf-scale, 1) * 6px);
145
174
  }
175
+ /* The small ▼ is 5 rows tall, which centers on a half row, so it is
176
+ pinned 3 rows down the 10-row content: 3 blank rows above it, 2 below,
177
+ its middle row on the middle row of the x-height (rows 3–7). */
178
+ :host([size='small']) .arrow {
179
+ align-self: flex-start;
180
+ padding-top: calc(var(--vf-scale, 1) * 3px);
181
+ }
182
+ :host([size='small']) .arrow svg {
183
+ width: calc(var(--vf-scale, 1) * 9px);
184
+ height: calc(var(--vf-scale, 1) * 5px);
185
+ }
146
186
  /* Disabled: only the value label dims; the box, hard shadow and ▼ arrow
147
187
  stay solid black (System 7 dims the label, not the control). */
148
188
  :host([disabled]) .label,
@@ -226,6 +266,14 @@ var P, F = class extends o(_) {
226
266
  width: calc(var(--vf-scale, 1) * 11px);
227
267
  height: calc(var(--vf-scale, 1) * 6px);
228
268
  }
269
+ /* The small caret in a 10px slot: 2 rows above it, 3 below (5 rows can't
270
+ center), and 14 in, which keeps the regular caret's center column. */
271
+ :host([size='small']) .arrow-slot svg {
272
+ left: calc(var(--vf-scale, 1) * 14px);
273
+ top: calc(var(--vf-scale, 1) * 2px);
274
+ width: calc(var(--vf-scale, 1) * 9px);
275
+ height: calc(var(--vf-scale, 1) * 5px);
276
+ }
229
277
  `
230
278
  ];
231
279
  }
@@ -242,7 +290,7 @@ var P, F = class extends o(_) {
242
290
  return this.rowScroll < this.optionItems.length - this.visibleSlots;
243
291
  }
244
292
  constructor() {
245
- super(), this.value = "", this.name = "", this.label = "", this.open = !1, this.cachedOptions = [], this.scale = new r(this), this.gridSnap = new d(this), this.focusRule = new v(this), this.panelListeners = new f(this, () => [
293
+ super(), this.value = "", this.name = "", this.size = "regular", this.noShadow = !1, this.label = "", this.open = !1, this.cachedOptions = [], this.scale = new r(this), this.gridSnap = new f(this), this.focusRule = new x(this), this.panelListeners = new p(this, () => [
246
294
  [
247
295
  document,
248
296
  "pointerdown",
@@ -260,7 +308,7 @@ var P, F = class extends o(_) {
260
308
  "resize",
261
309
  this.handleWindowResize
262
310
  ]
263
- ]), this.pressListeners = new f(this, () => [
311
+ ]), this.pressListeners = new p(this, () => [
264
312
  [
265
313
  document,
266
314
  "pointermove",
@@ -279,8 +327,8 @@ var P, F = class extends o(_) {
279
327
  this.handlePressCancel,
280
328
  !0
281
329
  ]
282
- ]), this.activeIndex = -1, this.rowScroll = 0, this.visibleSlots = 0, this.rowHeight = 0, this.arrowScroll = null, this.pressStartArrow = null, this.pressing = !1, this.pressOpenedPanel = !1, this.pressMoved = !1, this.pressStartOption = null, this.pressDownTime = 0, this.pressDownX = 0, this.pressDownY = 0, this.swallowClick = !1, this.blinking = !1, this.typeAhead = new T(), this.handleSlotChange = () => {
283
- if (this.cachedOptions = this.assignedOptions ?? [], this.value === "") {
330
+ ]), this.activeIndex = -1, this.rowScroll = 0, this.visibleSlots = 0, this.rowHeight = 0, this.arrowScroll = null, this.pressStartArrow = null, this.pressing = !1, this.pressOpenedPanel = !1, this.pressMoved = !1, this.pressStartOption = null, this.pressDownTime = 0, this.pressDownX = 0, this.pressDownY = 0, this.swallowClick = !1, this.blinking = !1, this.typeAhead = new O(), this.handleSlotChange = () => {
331
+ if (this.cachedOptions = this.assignedOptions ?? [], this.applySize(), this.value === "") {
284
332
  let e = this.optionItems.find((e) => !e.disabled);
285
333
  e && (this.value = this.optionValue(e));
286
334
  }
@@ -407,7 +455,7 @@ var P, F = class extends o(_) {
407
455
  this.controlEl?.focus(e);
408
456
  }
409
457
  updated(e) {
410
- e.has("value") && this.applySelection(), (e.has("value") || e.has("disabled")) && this.syncFormValue(this.value), e.has("disabled") && this.disabled && this.open && this.closePanel(!1);
458
+ e.has("value") && this.applySelection(), (e.has("value") || e.has("disabled")) && this.syncFormValue(this.value), e.has("disabled") && this.disabled && this.open && this.closePanel(!1), e.has("size") && (this.applySize(), this.open && this.closePanel(!1));
411
459
  }
412
460
  formDisabledCallback(e) {
413
461
  super.formDisabledCallback(e), this.syncFormValue(this.value), e && this.open && this.closePanel(!1);
@@ -424,6 +472,10 @@ var P, F = class extends o(_) {
424
472
  applySelection() {
425
473
  for (let e of this.optionItems) e.selected = this.optionValue(e) === this.value;
426
474
  }
475
+ applySize() {
476
+ let e = this.size === "small" ? "small" : "regular";
477
+ for (let t of this.optionItems) t.size = e;
478
+ }
427
479
  async openPanel() {
428
480
  if (this.open || this.isDisabled) return;
429
481
  this.open = !0, this.panelListeners.attach(), await this.updateComplete;
@@ -433,15 +485,15 @@ var P, F = class extends o(_) {
433
485
  positionPanel(e) {
434
486
  let t = this.controlEl, n = this.panelEl;
435
487
  if (!t || !n) return;
436
- let r = t.getBoundingClientRect(), a = this.optionItems[0]?.getBoundingClientRect()?.height || i(P.ITEM_HEIGHT, this), o = getComputedStyle(n), s = parseFloat(o.borderTopWidth) || 0, c = (e) => i(parseFloat(o.getPropertyValue(e)) || 0, this), l = w({
437
- idealTop: r.top - e * a,
438
- rowHeight: a,
439
- border: s,
488
+ let r = t.getBoundingClientRect(), a = getComputedStyle(n), o = parseFloat(a.borderTopWidth) || 0, s = this.optionItems[0]?.getBoundingClientRect()?.height || r.height - 2 * o, c = (e) => i(parseFloat(a.getPropertyValue(e)) || 0, this), l = D({
489
+ idealTop: r.top - e * s,
490
+ rowHeight: s,
491
+ border: o,
440
492
  rowCount: this.optionItems.length,
441
493
  viewTop: c("--vf-popup-clamp-top"),
442
494
  viewBottom: window.innerHeight - c("--vf-popup-clamp-bottom")
443
495
  }), u = r.left;
444
- n.style.minWidth = `${r.width}px`, n.style.top = `${l.panelTop}px`, n.style.left = `${u}px`, n.style.height = `${l.panelHeight}px`, this.rowHeight = a, this.visibleSlots = l.visibleSlots, this.rowScroll = l.initialScroll, this.applyScroll();
496
+ n.style.minWidth = `${r.width}px`, n.style.top = `${l.panelTop}px`, n.style.left = `${u}px`, n.style.height = `${l.panelHeight}px`, this.rowHeight = s, this.visibleSlots = l.visibleSlots, this.rowScroll = l.initialScroll, this.applyScroll();
445
497
  }
446
498
  closePanel(e) {
447
499
  this.open && (this.open = !1, this.cancelBlink(), this.stopArrowScroll(), this.endPress(), this.clearActive(), this.typeAhead.reset(), this.panelListeners.detach(), e && this.controlEl?.focus());
@@ -451,11 +503,11 @@ var P, F = class extends o(_) {
451
503
  this.rowsEl && (this.rowsEl.style.transform = e ? `translateY(${-e}px)` : ""), this.upArrowEl?.classList.toggle("shown", this.showUpArrow), this.downArrowEl?.classList.toggle("shown", this.showDownArrow);
452
504
  }
453
505
  revealRow(e) {
454
- let t = x(e, this.rowScroll, this.optionItems.length, this.visibleSlots);
506
+ let t = w(e, this.rowScroll, this.optionItems.length, this.visibleSlots);
455
507
  t !== this.rowScroll && (this.rowScroll = t, this.applyScroll());
456
508
  }
457
509
  stepArrowScroll(e) {
458
- let t = b(this.rowScroll + e, this.rowScroll, this.optionItems.length, this.visibleSlots);
510
+ let t = C(this.rowScroll + e, this.rowScroll, this.optionItems.length, this.visibleSlots);
459
511
  return t !== this.rowScroll && (this.rowScroll = t, this.applyScroll(), !0);
460
512
  }
461
513
  startArrowScroll(e) {
@@ -531,7 +583,7 @@ var P, F = class extends o(_) {
531
583
  if (e.disabled || this.blinking) return;
532
584
  let t = this.optionItems.indexOf(e);
533
585
  this.setActive(t, !1), this.blinking = !0;
534
- let n = p((t) => {
586
+ let n = m((t) => {
535
587
  e.active = t;
536
588
  }, () => {
537
589
  this.commit(e);
@@ -547,7 +599,7 @@ var P, F = class extends o(_) {
547
599
  this.value = r, e(this, "vf-change", { value: r }), t(this, "input"), t(this, "change");
548
600
  }
549
601
  optionFromEvent(e) {
550
- return e.composedPath().find((e) => e instanceof y);
602
+ return e.composedPath().find((e) => e instanceof S);
551
603
  }
552
604
  endPress() {
553
605
  this.pressing && (this.pressing = !1, this.pressStartOption = null, this.pressStartArrow = null, this.pressListeners.detach());
@@ -557,7 +609,7 @@ var P, F = class extends o(_) {
557
609
  if (!this.open || !n) return null;
558
610
  let r = n.getBoundingClientRect();
559
611
  if (e < r.left || e >= r.right || t < r.top || t >= r.bottom) return null;
560
- let i = S(this.rowScroll), a = C(this.rowScroll, this.optionItems.length, this.visibleSlots);
612
+ let i = T(this.rowScroll), a = E(this.rowScroll, this.optionItems.length, this.visibleSlots);
561
613
  for (let n = i; n <= a; n += 1) {
562
614
  let r = this.optionItems[n];
563
615
  if (!r) continue;
@@ -580,10 +632,10 @@ var P, F = class extends o(_) {
580
632
  this.selectOption(e);
581
633
  }
582
634
  render() {
583
- let e = this.optionItems.find((e) => this.optionValue(e) === this.value), t = e ? (e.textContent ?? "").trim() : "", n = this.isDisabled;
584
- return D`
635
+ let e = this.optionItems.find((e) => this.optionValue(e) === this.value), t = e ? (e.textContent ?? "").trim() : "", n = this.isDisabled, r = this.size === "small", i = r ? g : h, a = r ? v : _;
636
+ return A`
585
637
  <div
586
- class=${N({
638
+ class=${I({
587
639
  control: !0,
588
640
  "vf-snap": !0,
589
641
  "vf-focus-rule": this.focusRule.marked && !this.open,
@@ -595,20 +647,20 @@ var P, F = class extends o(_) {
595
647
  aria-expanded=${this.open ? "true" : "false"}
596
648
  aria-disabled=${n ? "true" : "false"}
597
649
  aria-controls="listbox"
598
- aria-label=${this.label || this.hostLabel || O}
650
+ aria-label=${this.label || this.hostLabel || j}
599
651
  aria-describedby=${this.describedBy}
600
- aria-required=${this.required ? "true" : O}
601
- aria-invalid=${this.validity.valid ? O : "true"}
652
+ aria-required=${this.required ? "true" : j}
653
+ aria-invalid=${this.validity.valid ? j : "true"}
602
654
  tabindex=${n ? "-1" : "0"}
603
655
  >
604
656
  <span class="label" part="label">
605
657
  <span class="value">${t}</span>
606
658
  <span class="sizer" aria-hidden="true">
607
- ${this.optionItems.map((e) => D`<span>${(e.textContent ?? "").trim()}</span>`)}
659
+ ${this.optionItems.map((e) => A`<span>${(e.textContent ?? "").trim()}</span>`)}
608
660
  </span>
609
661
  </span>
610
662
  <span class="arrow" part="arrow" aria-hidden="true"
611
- >${g(m, "caret")}</span
663
+ >${y(i, "caret")}</span
612
664
  >
613
665
  </div>
614
666
  <div
@@ -616,7 +668,7 @@ var P, F = class extends o(_) {
616
668
  class="panel vf-panel ${this.open ? "open" : ""}"
617
669
  part="panel"
618
670
  role="listbox"
619
- aria-label=${this.label || this.hostLabel || O}
671
+ aria-label=${this.label || this.hostLabel || j}
620
672
  aria-hidden=${this.open ? "false" : "true"}
621
673
  >
622
674
  <!-- role="presentation" so the strip that carries the roll doesn't
@@ -636,7 +688,7 @@ var P, F = class extends o(_) {
636
688
  @pointermove=${this.handleArrowEnter}
637
689
  @pointerleave=${this.handleArrowLeave}
638
690
  >
639
- ${g(h, "caret")}
691
+ ${y(a, "caret")}
640
692
  </div>
641
693
  <div
642
694
  class="arrow-slot down"
@@ -646,13 +698,17 @@ var P, F = class extends o(_) {
646
698
  @pointermove=${this.handleArrowEnter}
647
699
  @pointerleave=${this.handleArrowLeave}
648
700
  >
649
- ${g(m, "caret")}
701
+ ${y(i, "caret")}
650
702
  </div>
651
703
  </div>
652
704
  ${this.renderDescription()}
653
705
  `;
654
706
  }
655
707
  };
656
- a([k()], F.prototype, "value", void 0), a([k({ reflect: !0 })], F.prototype, "name", void 0), a([k()], F.prototype, "label", void 0), a([M()], F.prototype, "open", void 0), a([A(".control")], F.prototype, "controlEl", void 0), a([A(".panel")], F.prototype, "panelEl", void 0), a([A(".rows")], F.prototype, "rowsEl", void 0), a([A(".arrow-slot.up")], F.prototype, "upArrowEl", void 0), a([A(".arrow-slot.down")], F.prototype, "downArrowEl", void 0), a([j({ selector: "vf-option" })], F.prototype, "assignedOptions", void 0), a([M()], F.prototype, "cachedOptions", void 0), F = P = a([n("vf-select")], F);
708
+ a([M()], L.prototype, "value", void 0), a([M({ reflect: !0 })], L.prototype, "name", void 0), a([M({ reflect: !0 })], L.prototype, "size", void 0), a([M({
709
+ type: Boolean,
710
+ reflect: !0,
711
+ attribute: "no-shadow"
712
+ })], L.prototype, "noShadow", void 0), a([M()], L.prototype, "label", void 0), a([F()], L.prototype, "open", void 0), a([N(".control")], L.prototype, "controlEl", void 0), a([N(".panel")], L.prototype, "panelEl", void 0), a([N(".rows")], L.prototype, "rowsEl", void 0), a([N(".arrow-slot.up")], L.prototype, "upArrowEl", void 0), a([N(".arrow-slot.down")], L.prototype, "downArrowEl", void 0), a([P({ selector: "vf-option" })], L.prototype, "assignedOptions", void 0), a([F()], L.prototype, "cachedOptions", void 0), L = a([n("vf-select")], L);
657
713
  //#endregion
658
- export { F as VfSelect };
714
+ export { L as VfSelect };
package/dist/glyphs.d.ts CHANGED
@@ -54,6 +54,14 @@ export declare const CARET_DOWN: Glyph;
54
54
  * retrace both. Same synthesis convention as {@link STEPPER_UP_FILL}.
55
55
  */
56
56
  export declare const CARET_UP: Glyph;
57
+ /**
58
+ * The small popup's ▼ (`vf-select size="small"`) — {@link CARET_DOWN} without
59
+ * its widest row: the same staircase, 9×5. Also the small panel's bottom
60
+ * scroll arrow, as the regular caret is the regular panel's.
61
+ */
62
+ export declare const CARET_DOWN_SMALL: Glyph;
63
+ /** {@link CARET_DOWN_SMALL} mirrored vertically: the small panel's top scroll arrow. */
64
+ export declare const CARET_UP_SMALL: Glyph;
57
65
  /**
58
66
  * The "little arrows" stepper at rest — a rounded 1-bit frame enclosing hollow
59
67
  * up/down arrows (`Little arrows.png`), used by `vf-number-field`.
package/dist/glyphs.js CHANGED
@@ -33,59 +33,67 @@ var t = {
33
33
  h: 6,
34
34
  d: "M5 0h1v1h-1zM4 1h3v1h-3zM3 2h5v1h-5zM2 3h7v1h-7zM1 4h9v1h-9zM0 5h11v1h-11z"
35
35
  }, l = {
36
+ w: 9,
37
+ h: 5,
38
+ d: "M0 0h9v1h-9zM1 1h7v1h-7zM2 2h5v1h-5zM3 3h3v1h-3zM4 4h1v1h-1z"
39
+ }, u = {
40
+ w: 9,
41
+ h: 5,
42
+ d: "M4 0h1v1h-1zM3 1h3v1h-3zM2 2h5v1h-5zM1 3h7v1h-7zM0 4h9v1h-9z"
43
+ }, d = {
36
44
  w: 15,
37
45
  h: 25,
38
46
  d: "M2 0h11v1h-11zM1 1h1v1h-1zM13 1h1v1h-1zM0 2h1v1h-1zM14 2h1v1h-1zM0 3h1v1h-1zM7 3h1v1h-1zM14 3h1v1h-1zM0 4h1v1h-1zM6 4h1v1h-1zM8 4h1v1h-1zM14 4h1v1h-1zM0 5h1v1h-1zM5 5h1v1h-1zM9 5h1v1h-1zM14 5h1v1h-1zM0 6h1v1h-1zM4 6h1v1h-1zM10 6h1v1h-1zM14 6h1v1h-1zM0 7h1v1h-1zM3 7h3v1h-3zM9 7h3v1h-3zM14 7h1v1h-1zM0 8h1v1h-1zM5 8h1v1h-1zM9 8h1v1h-1zM14 8h1v1h-1zM0 9h1v1h-1zM5 9h1v1h-1zM9 9h1v1h-1zM14 9h1v1h-1zM0 10h1v1h-1zM5 10h5v1h-5zM14 10h1v1h-1zM0 11h1v1h-1zM14 11h1v1h-1zM0 12h1v1h-1zM14 12h1v1h-1zM0 13h1v1h-1zM14 13h1v1h-1zM0 14h1v1h-1zM5 14h5v1h-5zM14 14h1v1h-1zM0 15h1v1h-1zM5 15h1v1h-1zM9 15h1v1h-1zM14 15h1v1h-1zM0 16h1v1h-1zM5 16h1v1h-1zM9 16h1v1h-1zM14 16h1v1h-1zM0 17h1v1h-1zM3 17h3v1h-3zM9 17h3v1h-3zM14 17h1v1h-1zM0 18h1v1h-1zM4 18h1v1h-1zM10 18h1v1h-1zM14 18h1v1h-1zM0 19h1v1h-1zM5 19h1v1h-1zM9 19h1v1h-1zM14 19h1v1h-1zM0 20h1v1h-1zM6 20h1v1h-1zM8 20h1v1h-1zM14 20h1v1h-1zM0 21h1v1h-1zM7 21h1v1h-1zM14 21h1v1h-1zM0 22h1v1h-1zM14 22h1v1h-1zM1 23h1v1h-1zM13 23h1v1h-1zM2 24h11v1h-11z"
39
- }, u = {
47
+ }, f = {
40
48
  w: 11,
41
49
  h: 12,
42
50
  d: "M1 0h9v1h-9zM0 1h1v1h-1zM10 1h1v1h-1zM0 2h1v1h-1zM10 2h1v1h-1zM0 3h1v1h-1zM3 3h1v1h-1zM5 3h1v1h-1zM7 3h1v1h-1zM10 3h1v1h-1zM0 4h1v1h-1zM3 4h1v1h-1zM5 4h1v1h-1zM7 4h1v1h-1zM10 4h1v1h-1zM0 5h1v1h-1zM3 5h1v1h-1zM5 5h1v1h-1zM7 5h1v1h-1zM10 5h1v1h-1zM0 6h1v1h-1zM3 6h1v1h-1zM5 6h1v1h-1zM7 6h1v1h-1zM10 6h1v1h-1zM0 7h1v1h-1zM3 7h1v1h-1zM5 7h1v1h-1zM7 7h1v1h-1zM10 7h1v1h-1zM1 8h1v1h-1zM9 8h1v1h-1zM2 9h1v1h-1zM8 9h1v1h-1zM3 10h1v1h-1zM7 10h1v1h-1zM4 11h3v1h-3z"
43
- }, d = {
51
+ }, p = {
44
52
  w: 11,
45
53
  h: 12,
46
54
  d: "M1 0h9v1h-9zM0 1h11v1h-11zM0 2h11v1h-11zM0 3h11v1h-11zM0 4h11v1h-11zM0 5h11v1h-11zM0 6h11v1h-11zM0 7h11v1h-11zM1 8h9v1h-9zM2 9h7v1h-7zM3 10h5v1h-5zM4 11h3v1h-3z"
47
- }, f = {
55
+ }, m = {
48
56
  w: 15,
49
57
  h: 25,
50
58
  d: "M7 3h1v1h-1zM6 4h3v1h-3zM5 5h5v1h-5zM4 6h7v1h-7zM3 7h9v1h-9zM5 8h5v1h-5zM5 9h5v1h-5zM5 10h5v1h-5z"
51
- }, p = {
59
+ }, h = {
52
60
  w: 15,
53
61
  h: 25,
54
62
  d: "M5 14h5v1h-5zM5 15h5v1h-5zM5 16h5v1h-5zM3 17h9v1h-9zM4 18h7v1h-7zM5 19h5v1h-5zM6 20h3v1h-3zM7 21h1v1h-1z"
55
- }, m = {
63
+ }, g = {
56
64
  w: 16,
57
65
  h: 16,
58
66
  d: "M7 3h2v1h-2zM6 4h1v1h-1zM9 4h1v1h-1zM5 5h1v1h-1zM10 5h1v1h-1zM4 6h1v1h-1zM11 6h1v1h-1zM3 7h1v1h-1zM12 7h1v1h-1zM2 8h4v1h-4zM10 8h4v1h-4zM5 9h1v1h-1zM10 9h1v1h-1zM5 10h1v1h-1zM10 10h1v1h-1zM5 11h1v1h-1zM10 11h1v1h-1zM5 12h6v1h-6z"
59
- }, h = {
67
+ }, _ = {
60
68
  w: 16,
61
69
  h: 16,
62
70
  d: "M7 3h2v1h-2zM6 4h4v1h-4zM5 5h6v1h-6zM4 6h8v1h-8zM3 7h10v1h-10zM2 8h12v1h-12zM5 9h6v1h-6zM5 10h6v1h-6zM5 11h6v1h-6zM5 12h6v1h-6z"
63
- }, g = {
71
+ }, v = {
64
72
  w: 16,
65
73
  h: 16,
66
74
  d: "M5 3h6v1h-6zM5 4h1v1h-1zM10 4h1v1h-1zM5 5h1v1h-1zM10 5h1v1h-1zM5 6h1v1h-1zM10 6h1v1h-1zM2 7h4v1h-4zM10 7h4v1h-4zM3 8h1v1h-1zM12 8h1v1h-1zM4 9h1v1h-1zM11 9h1v1h-1zM5 10h1v1h-1zM10 10h1v1h-1zM6 11h1v1h-1zM9 11h1v1h-1zM7 12h2v1h-2z"
67
- }, _ = {
75
+ }, y = {
68
76
  w: 16,
69
77
  h: 16,
70
78
  d: "M5 3h6v1h-6zM5 4h6v1h-6zM5 5h6v1h-6zM5 6h6v1h-6zM2 7h12v1h-12zM3 8h10v1h-10zM4 9h8v1h-8zM5 10h6v1h-6zM6 11h4v1h-4zM7 12h2v1h-2z"
71
- }, v = {
79
+ }, b = {
72
80
  w: 16,
73
81
  h: 16,
74
82
  d: "M8 2h1v1h-1zM7 3h2v1h-2zM6 4h1v1h-1zM8 4h1v1h-1zM5 5h1v1h-1zM8 5h5v1h-5zM4 6h1v1h-1zM12 6h1v1h-1zM3 7h1v1h-1zM12 7h1v1h-1zM3 8h1v1h-1zM12 8h1v1h-1zM4 9h1v1h-1zM12 9h1v1h-1zM5 10h1v1h-1zM8 10h5v1h-5zM6 11h1v1h-1zM8 11h1v1h-1zM7 12h2v1h-2zM8 13h1v1h-1z"
75
- }, y = {
83
+ }, x = {
76
84
  w: 16,
77
85
  h: 16,
78
86
  d: "M8 2h1v1h-1zM7 3h2v1h-2zM6 4h3v1h-3zM5 5h8v1h-8zM4 6h9v1h-9zM3 7h10v1h-10zM3 8h10v1h-10zM4 9h9v1h-9zM5 10h8v1h-8zM6 11h3v1h-3zM7 12h2v1h-2zM8 13h1v1h-1z"
79
- }, b = {
87
+ }, S = {
80
88
  w: 16,
81
89
  h: 16,
82
90
  d: "M7 2h1v1h-1zM7 3h2v1h-2zM7 4h1v1h-1zM9 4h1v1h-1zM3 5h5v1h-5zM10 5h1v1h-1zM3 6h1v1h-1zM11 6h1v1h-1zM3 7h1v1h-1zM12 7h1v1h-1zM3 8h1v1h-1zM12 8h1v1h-1zM3 9h1v1h-1zM11 9h1v1h-1zM3 10h5v1h-5zM10 10h1v1h-1zM7 11h1v1h-1zM9 11h1v1h-1zM7 12h2v1h-2zM7 13h1v1h-1z"
83
- }, x = {
91
+ }, C = {
84
92
  w: 16,
85
93
  h: 16,
86
94
  d: "M7 2h1v1h-1zM7 3h2v1h-2zM7 4h3v1h-3zM3 5h8v1h-8zM3 6h9v1h-9zM3 7h10v1h-10zM3 8h10v1h-10zM3 9h9v1h-9zM3 10h8v1h-8zM7 11h3v1h-3zM7 12h2v1h-2zM7 13h1v1h-1z"
87
95
  };
88
- function S(t, n) {
96
+ function w(t, n) {
89
97
  return e`<svg
90
98
  class=${n}
91
99
  viewBox="0 0 ${t.w} ${t.h}"
@@ -97,4 +105,4 @@ function S(t, n) {
97
105
  </svg>`;
98
106
  }
99
107
  //#endregion
100
- export { s as CARET_DOWN, c as CARET_UP, t as CHECKBOX_X, o as CHECKMARK, a as RADIO_DOT, n as RADIO_FACE, r as RADIO_RING, i as RADIO_RING_PRESSED, g as SCROLL_ARROW_DOWN, _ as SCROLL_ARROW_DOWN_FILL, v as SCROLL_ARROW_LEFT, y as SCROLL_ARROW_LEFT_FILL, b as SCROLL_ARROW_RIGHT, x as SCROLL_ARROW_RIGHT_FILL, m as SCROLL_ARROW_UP, h as SCROLL_ARROW_UP_FILL, u as SLIDER_THUMB, d as SLIDER_THUMB_FACE, l as STEPPER, p as STEPPER_DOWN_FILL, f as STEPPER_UP_FILL, S as glyphSvg };
108
+ export { s as CARET_DOWN, l as CARET_DOWN_SMALL, c as CARET_UP, u as CARET_UP_SMALL, t as CHECKBOX_X, o as CHECKMARK, a as RADIO_DOT, n as RADIO_FACE, r as RADIO_RING, i as RADIO_RING_PRESSED, v as SCROLL_ARROW_DOWN, y as SCROLL_ARROW_DOWN_FILL, b as SCROLL_ARROW_LEFT, x as SCROLL_ARROW_LEFT_FILL, S as SCROLL_ARROW_RIGHT, C as SCROLL_ARROW_RIGHT_FILL, g as SCROLL_ARROW_UP, _ as SCROLL_ARROW_UP_FILL, f as SLIDER_THUMB, p as SLIDER_THUMB_FACE, d as STEPPER, h as STEPPER_DOWN_FILL, m as STEPPER_UP_FILL, w as glyphSvg };
package/dist/index.d.ts CHANGED
@@ -24,6 +24,7 @@ export { VfTextField } from './components/vf-text-field.js';
24
24
  export { VfTextArea } from './components/vf-text-area.js';
25
25
  export { VfNumberField } from './components/vf-number-field.js';
26
26
  export { VfSelect } from './components/vf-select.js';
27
+ export type { VfSelectSize } from './components/vf-select.js';
27
28
  export { VfOption } from './components/vf-option.js';
28
29
  export { VfProgressBar } from './components/vf-progress-bar.js';
29
30
  export { VfSlider } from './components/vf-slider.js';
@@ -125,7 +126,7 @@ export type { Pattern, PatternMotif, PatternName } from './patterns.js';
125
126
  export { PatternFillController, vfPatternFill } from './pattern-fill.js';
126
127
  export type { PatternFillOptions } from './pattern-fill.js';
127
128
  /** Glyph sprites (`glyphSvg(CHECKMARK, 'check')`) and their pixel geometry. */
128
- export { glyphSvg, CHECKBOX_X, RADIO_FACE, RADIO_RING, RADIO_RING_PRESSED, RADIO_DOT, CHECKMARK, CARET_DOWN, STEPPER, STEPPER_UP_FILL, STEPPER_DOWN_FILL, SLIDER_THUMB, SLIDER_THUMB_FACE, } from './glyphs.js';
129
+ export { glyphSvg, CHECKBOX_X, RADIO_FACE, RADIO_RING, RADIO_RING_PRESSED, RADIO_DOT, CHECKMARK, CARET_DOWN, CARET_DOWN_SMALL, STEPPER, STEPPER_UP_FILL, STEPPER_DOWN_FILL, SLIDER_THUMB, SLIDER_THUMB_FACE, } from './glyphs.js';
129
130
  export type { Glyph } from './glyphs.js';
130
131
  /** Pixel-stepped corner profiles and the clip-paths traced from them. */
131
132
  export { steppedRectClip, steppedRingClip, steppedCornerClip, BUTTON_FRAME, BUTTON_FACE, RING_FRAME, RING_HOLE, RING_INSET, SCREEN_CORNER, } from './pixel-frame.js';
package/dist/index.js CHANGED
@@ -32,44 +32,44 @@ import { VfSized as Ie } from "./size.js";
32
32
  import { DragController as Le } from "./drag.js";
33
33
  import { ScrollStateController as Re } from "./scroll-state.js";
34
34
  import { BLINK_FLIPS as ze, BLINK_INTERVAL_MS as Be, PRESS_HOLD_MS as Ve, RENAME_DELAY_MS as He, WALK_BEAT_MS as Ue, WALK_STEP_MS as We, WALK_STEP_PX as Ge, prefersReducedMotion as Ke, runOutlineTravel as qe, runSelectionBlink as Je } from "./motion.js";
35
- import { CARET_DOWN as Ye, CHECKBOX_X as Xe, CHECKMARK as Ze, RADIO_DOT as Qe, RADIO_FACE as $e, RADIO_RING as et, RADIO_RING_PRESSED as tt, SLIDER_THUMB as nt, SLIDER_THUMB_FACE as rt, STEPPER as it, STEPPER_DOWN_FILL as at, STEPPER_UP_FILL as ot, glyphSvg as st } from "./glyphs.js";
36
- import { ScrollRailController as ct, renderScrollRail as lt } from "./scroll-rail.js";
37
- import { VfScrollArea as ut } from "./components/vf-scroll-area.js";
38
- import { VfWindow as dt } from "./components/vf-window.js";
39
- import { VfModalDialog as ft, modalDialogStyles as pt } from "./modal-dialog.js";
40
- import { VfDialog as mt } from "./components/vf-dialog.js";
41
- import { VfSeparator as ht } from "./components/vf-separator.js";
42
- import { VfFormControl as gt } from "./form-control.js";
43
- import { VfButton as _t } from "./components/vf-button.js";
44
- import { VfButtonGroup as vt } from "./components/vf-button-group.js";
45
- import { VfSwatch as yt } from "./components/vf-swatch.js";
46
- import { VfToggleControl as bt } from "./toggle-control.js";
47
- import { VfCheckbox as xt } from "./components/vf-checkbox.js";
48
- import { VfRadio as St } from "./components/vf-radio.js";
49
- import { VfRadioGroup as Ct } from "./components/vf-radio-group.js";
50
- import { FocusRuleController as wt, focusModality as Tt, trackFocusModality as Et } from "./focus-modality.js";
51
- import { VfTextControlBase as Dt } from "./text-control.js";
52
- import { VfTextField as Ot } from "./components/vf-text-field.js";
53
- import { VfTextArea as kt } from "./components/vf-text-area.js";
54
- import { VfNumberField as At } from "./components/vf-number-field.js";
55
- import { VfOption as jt } from "./components/vf-option.js";
56
- import { VfSelect as Mt } from "./components/vf-select.js";
57
- import { VfProgressBar as Nt } from "./components/vf-progress-bar.js";
58
- import { VfSlider as Pt } from "./components/vf-slider.js";
59
- import { VfLabel as Ft } from "./components/vf-label.js";
60
- import { VfParagraph as It } from "./components/vf-paragraph.js";
61
- import { VfImg as Lt } from "./components/vf-img.js";
62
- import { VfIcon as Rt } from "./components/vf-icon.js";
63
- import { VfIconField as zt } from "./components/vf-icon-field.js";
64
- import { VfMenuBar as Bt } from "./components/vf-menu-bar.js";
65
- import { VfMenu as Vt } from "./components/vf-menu.js";
66
- import { VfMenuItem as Ht } from "./components/vf-menu-item.js";
67
- import { VfList as Ut } from "./components/vf-list.js";
68
- import { VfListItem as Wt } from "./components/vf-list-item.js";
69
- import { VfFieldset as Gt } from "./components/vf-fieldset.js";
70
- import { VfGrid as Kt } from "./components/vf-grid.js";
71
- import { VfStack as qt } from "./components/vf-stack.js";
72
- import { VfContainer as Jt } from "./components/vf-container.js";
73
- import { CURSOR_ARROW as Yt, CURSOR_CROSSHAIR as Xt, CURSOR_I_BEAM as Zt, CURSOR_WAIT as Qt } from "./cursor-art.js";
74
- import { applyCursor as $t } from "./cursor.js";
75
- export { ze as BLINK_FLIPS, Be as BLINK_INTERVAL_MS, Ee as BUTTON_FACE, De as BUTTON_FRAME, Ye as CARET_DOWN, Xe as CHECKBOX_X, Ze as CHECKMARK, r as CLASSIC_DPI, i as CSS_REFERENCE_DPI, Yt as CURSOR_ARROW, Xt as CURSOR_CROSSHAIR, Zt as CURSOR_I_BEAM, Qt as CURSOR_WAIT, Te as DocumentListenersController, Le as DragController, wt as FocusRuleController, Ce as GridSnapController, G as PATTERNS, K as PATTERN_NAMES, q as PATTERN_SIZE, D as PIXEL_GRID_METRICS, Ve as PRESS_HOLD_MS, xe as PatternFillController, T as PlacementController, Qe as RADIO_DOT, $e as RADIO_FACE, et as RADIO_RING, tt as RADIO_RING_PRESSED, He as RENAME_DELAY_MS, Oe as RING_FRAME, ke as RING_HOLE, Ae as RING_INSET, ie as RULE_EDGES, je as SCREEN_CORNER, nt as SLIDER_THUMB, rt as SLIDER_THUMB_FACE, it as STEPPER, at as STEPPER_DOWN_FILL, ot as STEPPER_UP_FILL, a as SYSTEM_PX_IN_CSS_PX, d as ScaleController, ct as ScrollRailController, Re as ScrollStateController, R as TILE_LATTICE, ge as TileRasterCache, be as TrackWidthController, k as VF_BODY_FAMILY, M as VF_DISPLAY_FAMILY, _t as VfButton, vt as VfButtonGroup, xt as VfCheckbox, Jt as VfContainer, Fe as VfDesktop, mt as VfDialog, Gt as VfFieldset, gt as VfFormControl, Kt as VfGrid, Rt as VfIcon, zt as VfIconField, Lt as VfImg, Ft as VfLabel, Ut as VfList, Wt as VfListItem, Vt as VfMenu, Bt as VfMenuBar, Ht as VfMenuItem, ft as VfModalDialog, At as VfNumberField, jt as VfOption, It as VfParagraph, E as VfPositioned, Nt as VfProgressBar, St as VfRadio, Ct as VfRadioGroup, ut as VfScrollArea, Mt as VfSelect, ht as VfSeparator, Ie as VfSized, Pt as VfSlider, qt as VfStack, yt as VfSwatch, kt as VfTextArea, Dt as VfTextControlBase, Ot as VfTextField, bt as VfToggleControl, dt as VfWindow, Ue as WALK_BEAT_MS, We as WALK_STEP_MS, Ge as WALK_STEP_PX, $t as applyCursor, f as applyScale, t as defineElement, o as devicePxPerSystemPx, p as effectiveScale, e as emit, Tt as focusModality, m as getScale, s as getZoom, st as glyphSvg, pt as modalDialogStyles, h as onScaleChange, c as onZoomChange, J as parsePattern, ae as parseRule, Y as patternHex, X as patternMotif, _e as patternOverride, Z as patternRects, Ke as prefersReducedMotion, A as registerBodyFace, N as registerDisplayFace, O as registerEmbeddedFont, lt as renderScrollRail, we as requestGridSnap, l as resetZoomBaseline, oe as ruleClasses, qe as runOutlineTravel, Je as runSelectionBlink, g as snapSys, _ as snapToDevicePx, v as snapToSystemPx, Me as steppedCornerClip, Ne as steppedRectClip, Pe as steppedRingClip, y as sys, b as sysLength, x as sysLengths, S as systemPxQuantum, ve as tileGrid, z as tileImage, B as tileRaster, V as tileRects, H as tileSpan, C as toSys, w as toSysExact, Et as trackFocusModality, u as truePixelRatio, I as vfBase, j as vfBodyDecls, te as vfChromeFrame, P as vfDisplay, F as vfDisplayDecls, Q as vfDots, n as vfElement, me as vfField, ue as vfFocus, de as vfFocusRing, fe as vfFocusUnderline, ee as vfHardShadowDecls, ne as vfModalFrame, re as vfPanel, Se as vfPatternFill, se as vfRule, he as vfScrollRail, L as vfStaticText, $ as vfStripes, ye as vfTileGrid, U as vfTileMaskSize, W as vfTileSize, ce as vfTitleBar, pe as vfToggle, le as vfWindowWidgets };
35
+ import { CARET_DOWN as Ye, CARET_DOWN_SMALL as Xe, CHECKBOX_X as Ze, CHECKMARK as Qe, RADIO_DOT as $e, RADIO_FACE as et, RADIO_RING as tt, RADIO_RING_PRESSED as nt, SLIDER_THUMB as rt, SLIDER_THUMB_FACE as it, STEPPER as at, STEPPER_DOWN_FILL as ot, STEPPER_UP_FILL as st, glyphSvg as ct } from "./glyphs.js";
36
+ import { ScrollRailController as lt, renderScrollRail as ut } from "./scroll-rail.js";
37
+ import { VfScrollArea as dt } from "./components/vf-scroll-area.js";
38
+ import { VfWindow as ft } from "./components/vf-window.js";
39
+ import { VfModalDialog as pt, modalDialogStyles as mt } from "./modal-dialog.js";
40
+ import { VfDialog as ht } from "./components/vf-dialog.js";
41
+ import { VfSeparator as gt } from "./components/vf-separator.js";
42
+ import { VfFormControl as _t } from "./form-control.js";
43
+ import { VfButton as vt } from "./components/vf-button.js";
44
+ import { VfButtonGroup as yt } from "./components/vf-button-group.js";
45
+ import { VfSwatch as bt } from "./components/vf-swatch.js";
46
+ import { VfToggleControl as xt } from "./toggle-control.js";
47
+ import { VfCheckbox as St } from "./components/vf-checkbox.js";
48
+ import { VfRadio as Ct } from "./components/vf-radio.js";
49
+ import { VfRadioGroup as wt } from "./components/vf-radio-group.js";
50
+ import { FocusRuleController as Tt, focusModality as Et, trackFocusModality as Dt } from "./focus-modality.js";
51
+ import { VfTextControlBase as Ot } from "./text-control.js";
52
+ import { VfTextField as kt } from "./components/vf-text-field.js";
53
+ import { VfTextArea as At } from "./components/vf-text-area.js";
54
+ import { VfNumberField as jt } from "./components/vf-number-field.js";
55
+ import { VfOption as Mt } from "./components/vf-option.js";
56
+ import { VfSelect as Nt } from "./components/vf-select.js";
57
+ import { VfProgressBar as Pt } from "./components/vf-progress-bar.js";
58
+ import { VfSlider as Ft } from "./components/vf-slider.js";
59
+ import { VfLabel as It } from "./components/vf-label.js";
60
+ import { VfParagraph as Lt } from "./components/vf-paragraph.js";
61
+ import { VfImg as Rt } from "./components/vf-img.js";
62
+ import { VfIcon as zt } from "./components/vf-icon.js";
63
+ import { VfIconField as Bt } from "./components/vf-icon-field.js";
64
+ import { VfMenuBar as Vt } from "./components/vf-menu-bar.js";
65
+ import { VfMenu as Ht } from "./components/vf-menu.js";
66
+ import { VfMenuItem as Ut } from "./components/vf-menu-item.js";
67
+ import { VfList as Wt } from "./components/vf-list.js";
68
+ import { VfListItem as Gt } from "./components/vf-list-item.js";
69
+ import { VfFieldset as Kt } from "./components/vf-fieldset.js";
70
+ import { VfGrid as qt } from "./components/vf-grid.js";
71
+ import { VfStack as Jt } from "./components/vf-stack.js";
72
+ import { VfContainer as Yt } from "./components/vf-container.js";
73
+ import { CURSOR_ARROW as Xt, CURSOR_CROSSHAIR as Zt, CURSOR_I_BEAM as Qt, CURSOR_WAIT as $t } from "./cursor-art.js";
74
+ import { applyCursor as en } from "./cursor.js";
75
+ export { ze as BLINK_FLIPS, Be as BLINK_INTERVAL_MS, Ee as BUTTON_FACE, De as BUTTON_FRAME, Ye as CARET_DOWN, Xe as CARET_DOWN_SMALL, Ze as CHECKBOX_X, Qe as CHECKMARK, r as CLASSIC_DPI, i as CSS_REFERENCE_DPI, Xt as CURSOR_ARROW, Zt as CURSOR_CROSSHAIR, Qt as CURSOR_I_BEAM, $t as CURSOR_WAIT, Te as DocumentListenersController, Le as DragController, Tt as FocusRuleController, Ce as GridSnapController, G as PATTERNS, K as PATTERN_NAMES, q as PATTERN_SIZE, D as PIXEL_GRID_METRICS, Ve as PRESS_HOLD_MS, xe as PatternFillController, T as PlacementController, $e as RADIO_DOT, et as RADIO_FACE, tt as RADIO_RING, nt as RADIO_RING_PRESSED, He as RENAME_DELAY_MS, Oe as RING_FRAME, ke as RING_HOLE, Ae as RING_INSET, ie as RULE_EDGES, je as SCREEN_CORNER, rt as SLIDER_THUMB, it as SLIDER_THUMB_FACE, at as STEPPER, ot as STEPPER_DOWN_FILL, st as STEPPER_UP_FILL, a as SYSTEM_PX_IN_CSS_PX, d as ScaleController, lt as ScrollRailController, Re as ScrollStateController, R as TILE_LATTICE, ge as TileRasterCache, be as TrackWidthController, k as VF_BODY_FAMILY, M as VF_DISPLAY_FAMILY, vt as VfButton, yt as VfButtonGroup, St as VfCheckbox, Yt as VfContainer, Fe as VfDesktop, ht as VfDialog, Kt as VfFieldset, _t as VfFormControl, qt as VfGrid, zt as VfIcon, Bt as VfIconField, Rt as VfImg, It as VfLabel, Wt as VfList, Gt as VfListItem, Ht as VfMenu, Vt as VfMenuBar, Ut as VfMenuItem, pt as VfModalDialog, jt as VfNumberField, Mt as VfOption, Lt as VfParagraph, E as VfPositioned, Pt as VfProgressBar, Ct as VfRadio, wt as VfRadioGroup, dt as VfScrollArea, Nt as VfSelect, gt as VfSeparator, Ie as VfSized, Ft as VfSlider, Jt as VfStack, bt as VfSwatch, At as VfTextArea, Ot as VfTextControlBase, kt as VfTextField, xt as VfToggleControl, ft as VfWindow, Ue as WALK_BEAT_MS, We as WALK_STEP_MS, Ge as WALK_STEP_PX, en as applyCursor, f as applyScale, t as defineElement, o as devicePxPerSystemPx, p as effectiveScale, e as emit, Et as focusModality, m as getScale, s as getZoom, ct as glyphSvg, mt as modalDialogStyles, h as onScaleChange, c as onZoomChange, J as parsePattern, ae as parseRule, Y as patternHex, X as patternMotif, _e as patternOverride, Z as patternRects, Ke as prefersReducedMotion, A as registerBodyFace, N as registerDisplayFace, O as registerEmbeddedFont, ut as renderScrollRail, we as requestGridSnap, l as resetZoomBaseline, oe as ruleClasses, qe as runOutlineTravel, Je as runSelectionBlink, g as snapSys, _ as snapToDevicePx, v as snapToSystemPx, Me as steppedCornerClip, Ne as steppedRectClip, Pe as steppedRingClip, y as sys, b as sysLength, x as sysLengths, S as systemPxQuantum, ve as tileGrid, z as tileImage, B as tileRaster, V as tileRects, H as tileSpan, C as toSys, w as toSysExact, Dt as trackFocusModality, u as truePixelRatio, I as vfBase, j as vfBodyDecls, te as vfChromeFrame, P as vfDisplay, F as vfDisplayDecls, Q as vfDots, n as vfElement, me as vfField, ue as vfFocus, de as vfFocusRing, fe as vfFocusUnderline, ee as vfHardShadowDecls, ne as vfModalFrame, re as vfPanel, Se as vfPatternFill, se as vfRule, he as vfScrollRail, L as vfStaticText, $ as vfStripes, ye as vfTileGrid, U as vfTileMaskSize, W as vfTileSize, ce as vfTitleBar, pe as vfToggle, le as vfWindowWidgets };
package/docs/SPEC.md CHANGED
@@ -83,6 +83,7 @@ Every length in this doc is a **system pixel** value; components multiply it by
83
83
  | `--vf-button-height` | `20px` | `vf-button` face (the default ring's inner box is 80×20) |
84
84
  | `--vf-button-group-gap` | `12px` | gap between buttons in a `vf-button-group` — the default clears the default ring's 4px reach on both sides, so rings never collide; retheming it below **8px** is the one value that puts two adjacent `variant="default"` rings into each other |
85
85
  | `--vf-popup-height` | `18px` | `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) |
86
+ | `--vf-popup-height-small` | `12px` | `vf-select[size="small"]` pill (border box). The small select restates it as `--vf-popup-height` on its host, so its rows (10px) and arrow slots derive from it the same way; a `--vf-popup-height` set on the small element itself still wins |
86
87
  | `--vf-popup-inset-top` | `4px` | room a clipped popup panel keeps clear at the **top** screen edge. Environmental rather than per-instance — a page has one menu bar and every popup on it should respect the same reserve — so it is declared once on `:root` or the `vf-desktop`: `24px` clears a `vf-menu-bar` (the 20px bar plus the default 4). Authored (unscaled) system px, like `--vf-popup-height`; `positionPanel` reads it back off the panel and converts with `sys()` |
87
88
  | `--vf-popup-inset-bottom` | `4px` | the same reserve at the **bottom** screen edge |
88
89
  | `--vf-menu-row-height` | `16px` | `vf-menu-item` row pitch (`Menus.png`; kept separate from `--vf-popup-height` so re-theming the popup pill doesn't move pulldown rows); `vf-menu` also spends one full row on every slotted `vf-separator` — the MDEF's divider-as-item, rule 8px in (H/2 above, H/2−1 below) |
@@ -120,7 +121,7 @@ Every length in this doc is a **system pixel** value; components multiply it by
120
121
 
121
122
  **Line boxes are lengths too.** Every line-height in the kit is stated in whole system px (`--vf-menu-row-height`, `--vf-label-line-height`, `--vf-paragraph-line-height`, …), never as a ratio. A ratio resolves to whatever it resolves to — `1.65 × 17px` is `28.05px` — and each line pushes everything after it further off the device-pixel grid, which is the single most common way a page fringes an otherwise-correct component (see the layout contract in README). Re-theme these tokens with whole numbers.
122
123
 
123
- **One size.** Both embedded faces are single 16-design-px masters and render at exactly that size — one design px = one system px, always. "Smaller" is a *family* switch: System 7's fine print was Geneva 9 — the collection's smallest strike, which **is** the body face — so a dialog's disk-space caption is `face="body"` (usually `dim`), the way `vf-icon size="small"` swaps to the 16×16 art. A genuinely different size is a different strike, registered like the embedded ones and themed in through the font family/size tokens with its own whole-pixel metrics.
124
+ **One size.** Both embedded faces are single 16-design-px masters and render at exactly that size — one design px = one system px, always. "Smaller" is a *family* switch: System 7's fine print was Geneva 9 — the collection's smallest strike, which **is** the body face — so a dialog's disk-space caption is `face="body"` (usually `dim`) and a small popup menu is `vf-select size="small"`, the way `vf-icon size="small"` swaps to the 16×16 art. A genuinely different size is a different strike, registered like the embedded ones and themed in through the font family/size tokens with its own whole-pixel metrics.
124
125
 
125
126
  **Grid snapping.** Whole system pixels only put an edge on the device grid *relative to the component's own origin*; a page that lands that origin on a fractional device pixel smears the whole 1-bit interior. Every component measures its own paint and cancels the fractional remainder, always (`src/grid-snap.ts`), so the origin is the component's responsibility rather than the page's. The correction is a `left`/`top` offset on the component's own paint root — the shadow element carrying the `.vf-snap` class (`vfBase`), relatively positioned, driven by two reserved custom properties (`--vf-snap-dx`/`-dy`) the controller writes on the host. A *layout*-stage shift, because a compositing-stage `transform` leaves the subtree rastered at its old position and only removes ~80% of the fringe. Nothing outside the shadow root is written but those two properties, so the correction cannot collide with a consumer's positioning or with `vf-window`'s drag coordinates. Absolutely positioned satellites that anchor to the host (`vf-menu`'s panel, the default button's ring) compose the same properties into their insets; rows and options inside a corrected container (`vf-list-item`, `vf-menu-item`, `vf-option`) and layout-only hosts (`vf-button-group`, `vf-radio-group`) carry no target and ride their surroundings. The two properties are reset to `0` per host (`vfBase`): custom properties inherit, and without the reset a host needing no correction of its own would resolve an ancestor component's values in its shadow root and paint off the grid by exactly that amount. It corrects the origin only: a fractional *size*, and a `--vf-scale × trueDpr` that isn't whole, are still the page's to get right.
126
127
 
@@ -327,15 +328,16 @@ A numeric text field paired with the classic "little arrows" stepper.
327
328
 
328
329
  #### `vf-select` (`VfSelect`, vf-option.ts children) (vf-select.ts)
329
330
  The classic popup menu control ("Macintosh HD ▼").
330
- - **Attributes/props:** `value: string`, `disabled`, `name`.
331
- - **Children:** `<vf-option value="...">Label</vf-option>` elements (default slot). `vf-option` (`VfOption`, vf-option.ts): props `value`, `disabled`, `selected` (managed by parent); renders its slot; `role="option"`.
332
- - **Visual (closed control):** height `var(--vf-popup-height, 18px)`, white bg, `1px solid black`, NO radius, `box-shadow: 1px 1px 0 0 var(--vf-black, #000)` (the small hard shadow visible in the screenshot), `padding: 0 8px 0 var(--vf-select-gutter, 16px)` — the left inset equals the option checkmark gutter so the selected label sits at the same x closed or open. *One documented 1px deviation:* the reference sheets put a closed pill's label ink 16px from its border box but an open menu's at 17 (three pill instances and four menu panels, all consistent, in the reference art). System 7 reconciled that by drawing the open panel 1px left of the pill; the kit instead uses one shared gutter with no panel offset, which keeps the closed↔open alignment exact and puts the closed pill's ink at 17. Bold label left, the black `CARET_DOWN` ▼ pixel glyph (inline SVG) right with 8px gap. The ▼ stays black even when the control is disabled (only the label dims). **Width:** the control hugs the *widest* option — no intrinsic min-width — via an invisible, height-collapsed stack of every option's text sharing the label's grid cell; so the closed pill and the open panel are always exactly the same width and the value never shifts as the selection changes. Authors wanting a floor set `min-width` on the host (or grow it in their layout, e.g. `flex: 1`). **Keyboard focus: no ring** — `vfFocusUnderline` (§4) at `--vf-focus-underline-offset: -4px`, a dashed rule under the *whole* pill (border + hard shadow + blank row), not inside the face the way vf-button underlines its label: the pill's one line already holds the label and the ▼. Spans the border box (±1px off the padding box the pseudo-element sizes to). **Closed only**, as `vf-menu`'s is: the open list already shows where focus is, and a panel short enough not to cover the rule — a one-option menu overlays the pill exactly — would leave a stray dashed line below it. Gated on a `.vf-focus-rule` class from the page's input modality, not `:focus-visible` — see §4 for why this control can't use the selector either. `npm run verify:focus`.
331
+ - **Attributes/props:** `value: string`, `disabled`, `name`, `size: 'regular' | 'small'` (reflected; any other value renders as `regular`), `no-shadow` (`noShadow: boolean`, reflected).
332
+ - **Children:** `<vf-option value="...">Label</vf-option>` elements (default slot). `vf-option` (`VfOption`, vf-option.ts): props `value`, `disabled`, `selected` and `size` (both managed by parent — the select stamps its `size` on every option, including ones added later); renders its slot; `role="option"`.
333
+ - **Visual (closed control):** height `var(--vf-popup-height, 18px)`, white bg, `1px solid black`, NO radius, `box-shadow: 1px 1px 0 0 var(--vf-black, #000)` (the small hard shadow visible in the screenshot; `no-shadow` removes it from the pill, and the open panel keeps its own), `padding: 0 8px 0 var(--vf-select-gutter, 16px)` — the left inset equals the option checkmark gutter so the selected label sits at the same x closed or open. *One documented 1px deviation:* the reference sheets put a closed pill's label ink 16px from its border box but an open menu's at 17 (three pill instances and four menu panels, all consistent, in the reference art). System 7 reconciled that by drawing the open panel 1px left of the pill; the kit instead uses one shared gutter with no panel offset, which keeps the closed↔open alignment exact and puts the closed pill's ink at 17. Bold label left, the black `CARET_DOWN` ▼ pixel glyph (inline SVG) right with 8px gap. The ▼ stays black even when the control is disabled (only the label dims). **Width:** the control hugs the *widest* option — no intrinsic min-width — via an invisible, height-collapsed stack of every option's text sharing the label's grid cell; so the closed pill and the open panel are always exactly the same width and the value never shifts as the selection changes. Authors wanting a floor set `min-width` on the host (or grow it in their layout, e.g. `flex: 1`). **Keyboard focus: no ring** — `vfFocusUnderline` (§4) at `--vf-focus-underline-offset: calc(-3px - depth)`, where depth is the pill's shadow (1px, 0 under `no-shadow`): a dashed rule under the *whole* pill (border + hard shadow + blank row), not inside the face the way vf-button underlines its label: the pill's one line already holds the label and the ▼. Spans the border box (±1px off the padding box the pseudo-element sizes to). **Closed only**, as `vf-menu`'s is: the open list already shows where focus is, and a panel short enough not to cover the rule — a one-option menu overlays the pill exactly — would leave a stray dashed line below it. Gated on a `.vf-focus-rule` class from the page's input modality, not `:focus-visible` — see §4 for why this control can't use the selector either. `npm run verify:focus`.
333
334
  - **Visual (open):** panel uses the `.vf-panel` recipe but overrides `--vf-shadow-offset: 1px` so its hard shadow matches the pill's (not the 2px menu shadow). Positioned `position: fixed` to the control's exact width and left (unsnapped, so the panel's left/right edges and shadow coincide with the pill's). Item rows are height 16px — the pill's *content* height, derived as `calc(var(--vf-popup-height, 18px) - 2px)` so a re-themed pill moves its rows with it — `padding: 0 20px 0 var(--vf-select-gutter, 16px)`; the panel opens with the selected row's cell laid directly over the closed pill (its top border on the pill's top border, extending downward), so the selected label's position and surrounding whitespace are identical closed and open. The currently-selected item shows a ✓ checkmark in the left `--vf-select-gutter` column; hovered/active item inverts (black bg, white text); disabled options gray.
334
335
  - **Visual (open, clipped):** a list taller than the screen is **clipped, never scrolled** — System 7 put no scrollbar on a menu. The panel is `overflow: hidden` and drawn once at a whole number of row slots; the rows ride a `.rows` strip rolled by `transform`, and the edge slot with items beyond it is covered by an opaque white **arrow slot** (`part="scroll-arrow"`, `aria-hidden`) carrying `CARET_UP` / `CARET_DOWN`. Traced from a real System 7 popup clipped at the screen edge (Find File's criteria menu under Infinite Mac, 2×): the 11×6 triangle sits 13px in from the panel's content edge and 5px down its 16px row, and the arrow occupies a **full** row slot. The pointer resting on an arrow rolls the list one row per `MENU_SCROLL_INTERVAL_MS` (66ms, motion.ts — the interaction itself, so *not* reduced-motion gated); the arrow retires when its direction runs out. Both can show at once. Four invariants, all in `src/popup-overflow.ts`:
335
336
  - **The clamp is quantized to the pill lattice.** Rows are clipped a whole row at a time off `pillTop − selectedIndex × rowHeight`, so a clipped popup still opens with its selected row exactly over the closed pill — what an un-quantized pixel clamp loses. One deliberate exception: when the selected row would land *under* an arrow (the pill within one row of a screen edge with items beyond it), the scroll shifts by one and the overlay gives way by exactly one row. Rare, and purely geometric.
336
337
  - **The panel is as tall as the *list* asked for, not as tall as the rows it can currently show** — capped only by the screen band. A list that fits the band but not where the pill would put it keeps every slot and slides whole rows, while the item strip stays welded to the pill; the slots the strip no longer reaches are drawn as **empty white**. The blank is the exact travel the list rolls through: scrolling to that end lands the strip flush with the panel, precisely full, both arrows retired. This is what System 7 drew — 5 empty rows above `name` in Find File's criteria popup, 2 above `Athens` in Character Set's font menu. **The two directions are one rule:** a panel pushed up (the pill is low) reserves its blank at the top and rolls down into it; a panel pushed down (the pill is high with a late item selected) reserves it at the bottom and rolls up into it. Only the sign of the scroll integer distinguishes them — it is free to leave the `[0, rowCount − visibleSlots]` range that would fill every slot, and that departure *is* the blank. It follows that the blank is a one-way starting position: an arrow means "rows are really hidden this way", so whichever end the blank is on, the arrow pointing back at it is off.
337
338
  - **The panel box never moves or resizes while open:** scrolling rolls the items inside it.
338
339
  - **Three slots minimum** when overflowing, even if that intrudes on the insets below — with both arrows shown, fewer leaves nothing to pick. The screen-edge band comes from `--vf-popup-inset-top` / `--vf-popup-inset-bottom` (§3), whose 4px defaults reproduce the old viewport margins exactly, so a list that fits is untouched by any of this. `npm run verify:select-overflow`.
340
+ - **Visual (small):** `size="small"` sets the pill and its rows in the body face (`vfBodyDecls`): a `var(--vf-popup-height-small, 12px)` pill over 10px rows. Content rows: 1 blank, 7 for the capitals, 2 for the descenders, which end on the last content row. The label's line box is 8px (`--vf-popup-height − 4px`) with the descender rows below it as padding — a 10px line box centers the 16px em one row lower and puts the second descender row on the border. The pill label pads the em's full 4px descent and takes 2px back with a negative margin, so its clip never leaves scrollable overflow; each option clips its own row (`overflow: clip`). The ▼ is `CARET_DOWN_SMALL` — `CARET_DOWN` without its widest row, 9×5 — pinned 3 rows down the content (3 blank rows above, 2 below), its middle row level with the x-height's middle row; the panel's scroll arrows are `CARET_UP_SMALL` / `CARET_DOWN_SMALL` at (14, 2) in their 10px slots, 14 keeping the regular caret's center column. The ✓ sits at (3, 1), centered in the row. The ✓ glyph, the gutter, the insets, the hard shadow and the focus rule are the regular pill's. Glyphs reaching more than 8 rows above the baseline are clipped at the top: the accented capitals (É, Å, Ñ …), `å ƒ ∫ ⌘ ⇧ ▶ ◀`, and the Apple logo. Centered in a row beside a `vf-label` of either face, the small pill's baseline sits 1px above the label's; placed, a body-face label lines up at the pill's `top` − 1 and a display-face label at `top` − 3. A live `size` change closes an open panel. `npm run verify:control-heights`, `npm run verify:baseline`.
339
341
  - **Behavior:** form-associated. Opens on pointerdown (mouse/touch), Space/Enter/ArrowDown, or a synthesised click (assistive tech). Two pointer styles coexist, disambiguated by the gesture and resolved at the first release: **System 7 press-drag-release** (press the pill, drag onto an item, release to pick — releasing on the current item or off the list cancels) and **modern click-to-open** (a quick in-place click leaves the list open for a second click). The only timed distinction is an in-place release — a tap (<200ms) keeps the list open, a held press closes it; any press that travels to another item is a drag-pick regardless of duration. Highlight tracking during a press hit-tests by coordinates (so it works under touch's implicit pointer capture) and never moves DOM focus off the control. Panel is positioned `position: fixed` from `getBoundingClientRect()` so it escapes clipping containers; closes on outside pointerdown, Escape, blur, scroll. Keyboard while open: arrows move active item, Enter/Space select, Escape cancels, Home/End jump, and printable keys run the shared Finder first-letter type-ahead (`src/type-ahead.ts` — the same buffer `vf-list` and the menus use), moving the highlight to the match. On select: classic blink (invert toggles ~3 times in ~250ms) then close + `vf-change`. A press that *begins* on an arrow is neither a pick nor a dismissal (so a click on one leaves the list up); a press-drag *released* on one closes with no change, like any release on a non-item — and while a drag is in an arrow's zone the highlight is dropped, because the arrow row is not an item. That zone reaches past the panel edge in its own direction, the classic ergonomics of slamming the pointer to the screen edge.
340
342
  - **Parts:** `control`, `label`, `arrow`, `panel`, `scroll-arrow`.
341
343
  - **Events:** `vf-change` detail `{ value }`, plus the native `input`/`change` pair per committed pick (§2).
@@ -959,7 +959,7 @@
959
959
  },
960
960
  {
961
961
  "name": "vf-option",
962
- "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected` and the transient\n`active` highlight, and slots this element into its popup panel.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.\n---\n\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **check** - The ✓ checkmark shown in the left gutter when selected.",
962
+ "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected`, the transient\n`active` highlight and `size`, and slots this element into its popup panel.\nUnder `size=\"small\"` the row is the small pill's 10px content height, in the\nbody face, and clips its own box.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.\n---\n\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **check** - The ✓ checkmark shown in the left gutter when selected.",
963
963
  "attributes": [
964
964
  {
965
965
  "name": "value",
@@ -981,6 +981,11 @@
981
981
  "description": "Transient highlight (hover / keyboard cursor) — full-row inversion.\nManaged by the parent `<vf-select>`; not part of the authoring API.",
982
982
  "values": []
983
983
  },
984
+ {
985
+ "name": "size",
986
+ "description": "The parent select's `size`. Managed by the parent.",
987
+ "values": [{ "name": "VfSelectSize" }]
988
+ },
984
989
  {
985
990
  "name": "top",
986
991
  "description": "Offset from the top of the positioning parent, in whole system px.\nSetting this (or `left`) absolutely positions the element within its\nparent; the coordinate left unset is 0. Remove both to return the\nelement to normal flow.",
@@ -1240,7 +1245,7 @@
1240
1245
  },
1241
1246
  {
1242
1247
  "name": "vf-select",
1243
- "description": "`<vf-select>` — the classic System 7 popup menu control (\"Macintosh HD ▼\").\n\nChildren are `<vf-option>` elements in the default slot. The closed control\nis a white box with a 1px black border, the small 1px hard shadow, the\nselected option's label on the left and a solid black ▼ triangle on the\nright. The open panel uses the shared `.vf-panel` recipe and is positioned\n`position: fixed` (computed from `getBoundingClientRect()`) so it escapes\nclipping containers; when possible the currently-selected item opens\ndirectly over the control, like the real popup menu.\n\nPointer — two interaction styles are supported and disambiguated by the\ngesture itself, resolved at the first pointer release:\n - System 7 press-drag-release: press the pill (the list appears under the\n pointer), drag onto an item, release over it to pick — one continuous\n press. Releasing over the current item or off the list closes with no\n change.\n - Modern click-to-open: a quick in-place click (no drag, released within\n PRESS_HOLD_MS) leaves the list open; a second, independent click\n then picks an item.\nThe two share one opening trigger (pointerdown) and diverge only on how the\npress ends — whether the pointer travelled to another item, and (for an\nin-place release) whether it was a quick tap or a held press. The pull-down\nmenus drive themselves the same way, on the same threshold; that half lives\nin src/menu-press.ts, because one menu press may travel across a whole bar.\n\nA list too tall for the screen is **clipped**, never scrolled: the edge slot\nwith items beyond it shows a solid arrow instead of a row, which rolls the\nlist one row at a time while the pointer rests on it. The clamp is quantized\nto the pill lattice, so a clipped popup still opens with its selected row\nover the closed pill — and the panel keeps every slot the list asked for, so\na box that had to slide to fit the screen opens with *blank rows* at whichever\nend the list no longer reaches: the exact travel it will roll through, in\neither direction. See src/popup-overflow.ts.\n\nKeyboard: Space/Enter/ArrowDown open; while open ArrowUp/ArrowDown move the\nhighlight, Home/End jump, Enter/Space select, Escape cancels. Selecting an\nitem plays the classic inversion blink (~250 ms) before closing. Keyboard\nfocus is marked with the kit's 1px dashed rule under the closed pill\n(`vfFocusUnderline`) rather than a ring around it — keyboard only, which\nhere means the page's input modality rather than `:focus-visible` (the pill\ndrives its own focus, and Blink reads that as visible either way).\n\nForm-associated: submits `value` under `name`.\n---\n\n\n### **Events:**\n - **vf-change** - After a selection commits. `detail: { value: string }`.\n- **input** - Native event, dispatched from the host per committed pick (with `change`, the pair a native `<select>` fires). A programmatic `value` set fires nothing.\n- **change** - Native event, dispatched from the host per committed pick so form delegation and framework bindings hear it.\n\n### **Slots:**\n - _default_ - `<vf-option>` elements.\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-popup-inset-top** - room a clipped popup panel keeps clear at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4 _(default: 4px)_\n- **--vf-popup-inset-bottom** - room a clipped popup panel keeps clear at the BOTTOM screen edge _(default: 4px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **control** - The closed popup control box.\n- **label** - The selected-option label inside the control.\n- **arrow** - The black ▼ triangle.\n- **panel** - The popup panel (listbox).\n- **scroll-arrow** - Either of the two scroll arrows a clipped panel shows in its edge row slots.",
1248
+ "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`.\n---\n\n\n### **Events:**\n - **vf-change** - After a selection commits. `detail: { value: string }`.\n- **input** - Native event, dispatched from the host per committed pick (with `change`, the pair a native `<select>` fires). A programmatic `value` set fires nothing.\n- **change** - Native event, dispatched from the host per committed pick so form delegation and framework bindings hear it.\n\n### **Slots:**\n - _default_ - `<vf-option>` elements.\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-popup-height-small** - `vf-select[size=\"small\"]` pill (border box; its rows are this less the two borders) _(default: 12px)_\n- **--vf-popup-inset-top** - room a clipped popup panel keeps clear at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4 _(default: 4px)_\n- **--vf-popup-inset-bottom** - room a clipped popup panel keeps clear at the BOTTOM screen edge _(default: 4px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **control** - The closed popup control box.\n- **label** - The selected-option label inside the control.\n- **arrow** - The black ▼ triangle.\n- **panel** - The popup panel (listbox).\n- **scroll-arrow** - Either of the two scroll arrows a clipped panel shows in its edge row slots.",
1244
1249
  "attributes": [
1245
1250
  {
1246
1251
  "name": "value",
@@ -1252,6 +1257,16 @@
1252
1257
  "description": "Form field name used when submitting the associated form.",
1253
1258
  "values": []
1254
1259
  },
1260
+ {
1261
+ "name": "size",
1262
+ "description": "`regular` (the 18px pill in the display face) or `small` (12px, in the\nbody face). Any other value renders as `regular`. The select passes it to\nits options.",
1263
+ "values": [{ "name": "VfSelectSize" }]
1264
+ },
1265
+ {
1266
+ "name": "no-shadow",
1267
+ "description": "Draws the closed pill without its 1px hard shadow. The open list keeps\nits shadow.",
1268
+ "values": []
1269
+ },
1255
1270
  {
1256
1271
  "name": "label",
1257
1272
  "description": "Accessible name for the combobox control (`aria-label`). Left empty, the\nname falls back to whatever the host carries — `aria-labelledby`,\n`aria-label` or an associated `<label for>` — via\nVfShadowRoleControl.hostLabel; with neither, the control is announced by\nits contents, i.e. the selected value.",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
3
3
  "name": "vintage-frames",
4
- "version": "0.11.0",
4
+ "version": "0.12.1",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -2249,7 +2249,7 @@
2249
2249
  },
2250
2250
  {
2251
2251
  "name": "vf-option",
2252
- "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected` and the transient\n`active` highlight, and slots this element into its popup panel.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.\n---\n\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **check** - The ✓ checkmark shown in the left gutter when selected.",
2252
+ "description": "`<vf-option>` — a single choice inside a `<vf-select>` popup menu.\n\nA light-DOM child of `<vf-select>` (slotted into the popup panel). Renders\nits slotted label at menu-item metrics (16px row — the pill's content height,\nso a selected option overlays the closed pill exactly; the left checkmark gutter is\n`--vf-select-gutter`, shared with the closed control's left inset so the value\ndoesn't shift on open). The parent select manages `selected`, the transient\n`active` highlight and `size`, and slots this element into its popup panel.\nUnder `size=\"small\"` the row is the small pill's 10px content height, in the\nbody face, and clips its own box.\n\nThe host carries `role=\"option\"` with `aria-selected`/`aria-disabled`.\n\nTakes `top`/`left` like every other element (VfPositioned), for the\nconsumer who wants one somewhere other than a popup row. Inside its parent\n`<vf-select>` it is a row the panel measures and scrolls in flow, so stating\nan origin there takes it out of that measurement: the panel stops counting it\ntoward its own width and its scroll clamp, and the rows below close the gap.\nThat is the placement doing exactly what it says — not a bug — but it is not\nhow a popup is laid out.\n---\n\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **check** - The ✓ checkmark shown in the left gutter when selected.",
2253
2253
  "doc-url": "",
2254
2254
  "attributes": [
2255
2255
  {
@@ -2272,6 +2272,11 @@
2272
2272
  "description": "Transient highlight (hover / keyboard cursor) — full-row inversion.\nManaged by the parent `<vf-select>`; not part of the authoring API.",
2273
2273
  "value": { "type": "boolean", "default": "false" }
2274
2274
  },
2275
+ {
2276
+ "name": "size",
2277
+ "description": "The parent select's `size`. Managed by the parent.",
2278
+ "value": { "type": "VfSelectSize", "default": "'regular'" }
2279
+ },
2275
2280
  {
2276
2281
  "name": "top",
2277
2282
  "description": "Offset from the top of the positioning parent, in whole system px.\nSetting this (or `left`) absolutely positions the element within its\nparent; the coordinate left unset is 0. Remove both to return the\nelement to normal flow.",
@@ -2316,6 +2321,11 @@
2316
2321
  "description": "Transient highlight (hover / keyboard cursor) — full-row inversion.\nManaged by the parent `<vf-select>`; not part of the authoring API.",
2317
2322
  "type": "boolean"
2318
2323
  },
2324
+ {
2325
+ "name": "size",
2326
+ "description": "The parent select's `size`. Managed by the parent.",
2327
+ "type": "VfSelectSize"
2328
+ },
2319
2329
  { "name": "role", "type": "string" },
2320
2330
  {
2321
2331
  "name": "top",
@@ -2880,7 +2890,7 @@
2880
2890
  },
2881
2891
  {
2882
2892
  "name": "vf-select",
2883
- "description": "`<vf-select>` — the classic System 7 popup menu control (\"Macintosh HD ▼\").\n\nChildren are `<vf-option>` elements in the default slot. The closed control\nis a white box with a 1px black border, the small 1px hard shadow, the\nselected option's label on the left and a solid black ▼ triangle on the\nright. The open panel uses the shared `.vf-panel` recipe and is positioned\n`position: fixed` (computed from `getBoundingClientRect()`) so it escapes\nclipping containers; when possible the currently-selected item opens\ndirectly over the control, like the real popup menu.\n\nPointer — two interaction styles are supported and disambiguated by the\ngesture itself, resolved at the first pointer release:\n - System 7 press-drag-release: press the pill (the list appears under the\n pointer), drag onto an item, release over it to pick — one continuous\n press. Releasing over the current item or off the list closes with no\n change.\n - Modern click-to-open: a quick in-place click (no drag, released within\n PRESS_HOLD_MS) leaves the list open; a second, independent click\n then picks an item.\nThe two share one opening trigger (pointerdown) and diverge only on how the\npress ends — whether the pointer travelled to another item, and (for an\nin-place release) whether it was a quick tap or a held press. The pull-down\nmenus drive themselves the same way, on the same threshold; that half lives\nin src/menu-press.ts, because one menu press may travel across a whole bar.\n\nA list too tall for the screen is **clipped**, never scrolled: the edge slot\nwith items beyond it shows a solid arrow instead of a row, which rolls the\nlist one row at a time while the pointer rests on it. The clamp is quantized\nto the pill lattice, so a clipped popup still opens with its selected row\nover the closed pill — and the panel keeps every slot the list asked for, so\na box that had to slide to fit the screen opens with *blank rows* at whichever\nend the list no longer reaches: the exact travel it will roll through, in\neither direction. See src/popup-overflow.ts.\n\nKeyboard: Space/Enter/ArrowDown open; while open ArrowUp/ArrowDown move the\nhighlight, Home/End jump, Enter/Space select, Escape cancels. Selecting an\nitem plays the classic inversion blink (~250 ms) before closing. Keyboard\nfocus is marked with the kit's 1px dashed rule under the closed pill\n(`vfFocusUnderline`) rather than a ring around it — keyboard only, which\nhere means the page's input modality rather than `:focus-visible` (the pill\ndrives its own focus, and Blink reads that as visible either way).\n\nForm-associated: submits `value` under `name`.\n---\n\n\n### **Events:**\n - **vf-change** - After a selection commits. `detail: { value: string }`.\n- **input** - Native event, dispatched from the host per committed pick (with `change`, the pair a native `<select>` fires). A programmatic `value` set fires nothing.\n- **change** - Native event, dispatched from the host per committed pick so form delegation and framework bindings hear it.\n\n### **Slots:**\n - _default_ - `<vf-option>` elements.\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-popup-inset-top** - room a clipped popup panel keeps clear at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4 _(default: 4px)_\n- **--vf-popup-inset-bottom** - room a clipped popup panel keeps clear at the BOTTOM screen edge _(default: 4px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **control** - The closed popup control box.\n- **label** - The selected-option label inside the control.\n- **arrow** - The black ▼ triangle.\n- **panel** - The popup panel (listbox).\n- **scroll-arrow** - Either of the two scroll arrows a clipped panel shows in its edge row slots.",
2893
+ "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`.\n---\n\n\n### **Events:**\n - **vf-change** - After a selection commits. `detail: { value: string }`.\n- **input** - Native event, dispatched from the host per committed pick (with `change`, the pair a native `<select>` fires). A programmatic `value` set fires nothing.\n- **change** - Native event, dispatched from the host per committed pick so form delegation and framework bindings hear it.\n\n### **Slots:**\n - _default_ - `<vf-option>` elements.\n\n### **CSS Properties:**\n - **--vf-popup-height** - `vf-select` pill (border box; its 1px hard shadow makes the sheet's 157×19 ink box) _(default: 18px)_\n- **--vf-popup-height-small** - `vf-select[size=\"small\"]` pill (border box; its rows are this less the two borders) _(default: 12px)_\n- **--vf-popup-inset-top** - room a clipped popup panel keeps clear at the TOP screen edge — set it once on `:root` (or the `vf-desktop`) to clear a `vf-menu-bar`: `24px` is the 20px bar plus the default 4 _(default: 4px)_\n- **--vf-popup-inset-bottom** - room a clipped popup panel keeps clear at the BOTTOM screen edge _(default: 4px)_\n- **--vf-select-gutter** - checkmark column: `vf-select` left inset / `vf-option` + `vf-menu-item` ✓ column (shared so the value doesn't shift on open) _(default: 16px)_\n\n### **CSS Parts:**\n - **control** - The closed popup control box.\n- **label** - The selected-option label inside the control.\n- **arrow** - The black ▼ triangle.\n- **panel** - The popup panel (listbox).\n- **scroll-arrow** - Either of the two scroll arrows a clipped panel shows in its edge row slots.",
2884
2894
  "doc-url": "",
2885
2895
  "attributes": [
2886
2896
  {
@@ -2893,6 +2903,16 @@
2893
2903
  "description": "Form field name used when submitting the associated form.",
2894
2904
  "value": { "type": "string", "default": "''" }
2895
2905
  },
2906
+ {
2907
+ "name": "size",
2908
+ "description": "`regular` (the 18px pill in the display face) or `small` (12px, in the\nbody face). Any other value renders as `regular`. The select passes it to\nits options.",
2909
+ "value": { "type": "VfSelectSize", "default": "'regular'" }
2910
+ },
2911
+ {
2912
+ "name": "no-shadow",
2913
+ "description": "Draws the closed pill without its 1px hard shadow. The open list keeps\nits shadow.",
2914
+ "value": { "type": "boolean", "default": "false" }
2915
+ },
2896
2916
  {
2897
2917
  "name": "label",
2898
2918
  "description": "Accessible name for the combobox control (`aria-label`). Left empty, the\nname falls back to whatever the host carries — `aria-labelledby`,\n`aria-label` or an associated `<label for>` — via\nVfShadowRoleControl.hostLabel; with neither, the control is announced by\nits contents, i.e. the selected value.",
@@ -2961,6 +2981,16 @@
2961
2981
  "description": "Form field name used when submitting the associated form.",
2962
2982
  "type": "string"
2963
2983
  },
2984
+ {
2985
+ "name": "size",
2986
+ "description": "`regular` (the 18px pill in the display face) or `small` (12px, in the\nbody face). Any other value renders as `regular`. The select passes it to\nits options.",
2987
+ "type": "VfSelectSize"
2988
+ },
2989
+ {
2990
+ "name": "noShadow",
2991
+ "description": "Draws the closed pill without its 1px hard shadow. The open list keeps\nits shadow.",
2992
+ "type": "boolean"
2993
+ },
2964
2994
  {
2965
2995
  "name": "label",
2966
2996
  "description": "Accessible name for the combobox control (`aria-label`). Left empty, the\nname falls back to whatever the host carries — `aria-labelledby`,\n`aria-label` or an associated `<label for>` — via\nVfShadowRoleControl.hostLabel; with neither, the control is announced by\nits contents, i.e. the selected value.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vintage-frames",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "Lit web components that emulate the look and feel of classic Mac OS System 7",
5
5
  "type": "module",
6
6
  "license": "MIT",