vintage-frames 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +262 -0
  3. package/custom-elements.json +19807 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js +9 -0
  5. package/dist/chrome.d.ts +73 -0
  6. package/dist/chrome.js +94 -0
  7. package/dist/components/vf-button-group.d.ts +50 -0
  8. package/dist/components/vf-button-group.js +68 -0
  9. package/dist/components/vf-button.d.ts +169 -0
  10. package/dist/components/vf-button.js +234 -0
  11. package/dist/components/vf-checkbox.d.ts +60 -0
  12. package/dist/components/vf-checkbox.js +135 -0
  13. package/dist/components/vf-container.d.ts +95 -0
  14. package/dist/components/vf-container.js +86 -0
  15. package/dist/components/vf-desktop.d.ts +243 -0
  16. package/dist/components/vf-desktop.js +310 -0
  17. package/dist/components/vf-dialog.d.ts +105 -0
  18. package/dist/components/vf-dialog.js +280 -0
  19. package/dist/components/vf-fieldset.d.ts +34 -0
  20. package/dist/components/vf-fieldset.js +76 -0
  21. package/dist/components/vf-grid.d.ts +124 -0
  22. package/dist/components/vf-grid.js +133 -0
  23. package/dist/components/vf-icon.d.ts +356 -0
  24. package/dist/components/vf-icon.js +507 -0
  25. package/dist/components/vf-img.d.ts +63 -0
  26. package/dist/components/vf-img.js +65 -0
  27. package/dist/components/vf-label.d.ts +117 -0
  28. package/dist/components/vf-label.js +151 -0
  29. package/dist/components/vf-list-item.d.ts +48 -0
  30. package/dist/components/vf-list-item.js +98 -0
  31. package/dist/components/vf-list.d.ts +77 -0
  32. package/dist/components/vf-list.js +256 -0
  33. package/dist/components/vf-menu-bar.d.ts +64 -0
  34. package/dist/components/vf-menu-bar.js +236 -0
  35. package/dist/components/vf-menu-item.d.ts +91 -0
  36. package/dist/components/vf-menu-item.js +252 -0
  37. package/dist/components/vf-menu.d.ts +95 -0
  38. package/dist/components/vf-menu.js +346 -0
  39. package/dist/components/vf-number-field.d.ts +60 -0
  40. package/dist/components/vf-number-field.js +248 -0
  41. package/dist/components/vf-option.d.ts +49 -0
  42. package/dist/components/vf-option.js +119 -0
  43. package/dist/components/vf-paragraph.d.ts +73 -0
  44. package/dist/components/vf-paragraph.js +66 -0
  45. package/dist/components/vf-progress-bar.d.ts +69 -0
  46. package/dist/components/vf-progress-bar.js +272 -0
  47. package/dist/components/vf-radio-group.d.ts +109 -0
  48. package/dist/components/vf-radio-group.js +105 -0
  49. package/dist/components/vf-radio.d.ts +59 -0
  50. package/dist/components/vf-radio.js +135 -0
  51. package/dist/components/vf-scroll-area.d.ts +75 -0
  52. package/dist/components/vf-scroll-area.js +124 -0
  53. package/dist/components/vf-select.d.ts +334 -0
  54. package/dist/components/vf-select.js +658 -0
  55. package/dist/components/vf-separator.d.ts +38 -0
  56. package/dist/components/vf-separator.js +55 -0
  57. package/dist/components/vf-slider.d.ts +80 -0
  58. package/dist/components/vf-slider.js +255 -0
  59. package/dist/components/vf-stack.d.ts +188 -0
  60. package/dist/components/vf-stack.js +168 -0
  61. package/dist/components/vf-swatch.d.ts +98 -0
  62. package/dist/components/vf-swatch.js +201 -0
  63. package/dist/components/vf-text-area.d.ts +77 -0
  64. package/dist/components/vf-text-area.js +121 -0
  65. package/dist/components/vf-text-field.d.ts +53 -0
  66. package/dist/components/vf-text-field.js +79 -0
  67. package/dist/components/vf-window.d.ts +157 -0
  68. package/dist/components/vf-window.js +377 -0
  69. package/dist/cursor-art.d.ts +37 -0
  70. package/dist/cursor-art.js +41 -0
  71. package/dist/cursor.d.ts +49 -0
  72. package/dist/cursor.js +171 -0
  73. package/dist/define.d.ts +45 -0
  74. package/dist/define.js +15 -0
  75. package/dist/document-listeners.d.ts +62 -0
  76. package/dist/document-listeners.js +29 -0
  77. package/dist/drag.d.ts +49 -0
  78. package/dist/drag.js +30 -0
  79. package/dist/events.d.ts +79 -0
  80. package/dist/events.js +25 -0
  81. package/dist/focus-modality.d.ts +94 -0
  82. package/dist/focus-modality.js +56 -0
  83. package/dist/form-control.d.ts +247 -0
  84. package/dist/form-control.js +127 -0
  85. package/dist/glyphs.d.ts +117 -0
  86. package/dist/glyphs.js +100 -0
  87. package/dist/grid-snap.d.ts +73 -0
  88. package/dist/grid-snap.js +135 -0
  89. package/dist/index.d.ts +145 -0
  90. package/dist/index.js +71 -0
  91. package/dist/menu-press.d.ts +60 -0
  92. package/dist/menu-press.js +97 -0
  93. package/dist/modal-dialog.d.ts +148 -0
  94. package/dist/modal-dialog.js +155 -0
  95. package/dist/motion.d.ts +72 -0
  96. package/dist/motion.js +22 -0
  97. package/dist/number.d.ts +24 -0
  98. package/dist/number.js +12 -0
  99. package/dist/open-art.d.ts +40 -0
  100. package/dist/open-art.js +35 -0
  101. package/dist/pixel-frame.d.ts +102 -0
  102. package/dist/pixel-frame.js +77 -0
  103. package/dist/popup-overflow.d.ts +157 -0
  104. package/dist/popup-overflow.js +45 -0
  105. package/dist/position.d.ts +187 -0
  106. package/dist/position.js +74 -0
  107. package/dist/scale.d.ts +259 -0
  108. package/dist/scale.js +133 -0
  109. package/dist/scroll-rail.d.ts +112 -0
  110. package/dist/scroll-rail.js +194 -0
  111. package/dist/scroll-state.d.ts +113 -0
  112. package/dist/scroll-state.js +55 -0
  113. package/dist/size.d.ts +47 -0
  114. package/dist/size.js +30 -0
  115. package/dist/styles/base.d.ts +38 -0
  116. package/dist/styles/body-font.d.ts +7 -0
  117. package/dist/styles/body-font.js +9 -0
  118. package/dist/styles/display-font.d.ts +7 -0
  119. package/dist/styles/display-font.js +9 -0
  120. package/dist/styles/recipes/body-face.d.ts +14 -0
  121. package/dist/styles/recipes/body-face.js +6 -0
  122. package/dist/styles/recipes/display-face.d.ts +23 -0
  123. package/dist/styles/recipes/display-face.js +10 -0
  124. package/dist/styles/recipes/field.d.ts +20 -0
  125. package/dist/styles/recipes/field.js +68 -0
  126. package/dist/styles/recipes/focus.d.ts +76 -0
  127. package/dist/styles/recipes/focus.js +39 -0
  128. package/dist/styles/recipes/host.d.ts +5 -0
  129. package/dist/styles/recipes/host.js +62 -0
  130. package/dist/styles/recipes/pattern.d.ts +80 -0
  131. package/dist/styles/recipes/pattern.js +82 -0
  132. package/dist/styles/recipes/scroll-rail.d.ts +69 -0
  133. package/dist/styles/recipes/scroll-rail.js +222 -0
  134. package/dist/styles/recipes/shadow.d.ts +13 -0
  135. package/dist/styles/recipes/shadow.js +5 -0
  136. package/dist/styles/recipes/static-text.d.ts +24 -0
  137. package/dist/styles/recipes/static-text.js +17 -0
  138. package/dist/styles/recipes/surface.d.ts +28 -0
  139. package/dist/styles/recipes/surface.js +27 -0
  140. package/dist/styles/recipes/tile.d.ts +122 -0
  141. package/dist/styles/recipes/tile.js +40 -0
  142. package/dist/styles/recipes/title-bar.d.ts +49 -0
  143. package/dist/styles/recipes/title-bar.js +134 -0
  144. package/dist/styles/recipes/toggle.d.ts +10 -0
  145. package/dist/styles/recipes/toggle.js +20 -0
  146. package/dist/styles/register-embedded-font.d.ts +64 -0
  147. package/dist/styles/register-embedded-font.js +30 -0
  148. package/dist/text-control.d.ts +131 -0
  149. package/dist/text-control.js +83 -0
  150. package/dist/tile-grid.d.ts +111 -0
  151. package/dist/tile-grid.js +53 -0
  152. package/dist/toggle-control.d.ts +60 -0
  153. package/dist/toggle-control.js +41 -0
  154. package/dist/track-width.d.ts +42 -0
  155. package/dist/track-width.js +30 -0
  156. package/dist/type-ahead.d.ts +35 -0
  157. package/dist/type-ahead.js +20 -0
  158. package/dist/zoom.d.ts +204 -0
  159. package/dist/zoom.js +105 -0
  160. package/docs/SPEC.md +2471 -0
  161. package/editor/vscode.html-custom-data.json +1320 -0
  162. package/editor/web-types.json +3237 -0
  163. package/package.json +118 -0
@@ -0,0 +1,55 @@
1
+ import { vfElement as e } from "../define.js";
2
+ import { ScaleController as t } from "../scale.js";
3
+ import n from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
4
+ import { VfPositioned as r } from "../position.js";
5
+ import { vfBase as i } from "../styles/recipes/host.js";
6
+ import { GridSnapController as a } from "../grid-snap.js";
7
+ import { LitElement as o, css as s, html as c } from "lit";
8
+ import { property as l } from "lit/decorators.js";
9
+ //#region src/components/vf-separator.ts
10
+ var u = class extends r(o) {
11
+ static {
12
+ this.styles = [i, s`
13
+ :host {
14
+ display: block;
15
+ height: calc(var(--vf-scale, 1) * 1px);
16
+ }
17
+ :host([vertical]) {
18
+ width: calc(var(--vf-scale, 1) * 1px);
19
+ height: auto;
20
+ align-self: stretch;
21
+ }
22
+ /* The rule ink lives on an inner element rather than a host border so it
23
+ can ride the snap offset (see .vf-snap in base.ts). */
24
+ .rule {
25
+ width: 100%;
26
+ height: 100%;
27
+ border-top: calc(var(--vf-scale, 1) * 1px)
28
+ var(--vf-separator-style, solid)
29
+ var(--vf-separator-color, var(--vf-black, #000));
30
+ }
31
+ :host([vertical]) .rule {
32
+ border-top: none;
33
+ border-left: calc(var(--vf-scale, 1) * 1px)
34
+ var(--vf-separator-style, solid)
35
+ var(--vf-separator-color, var(--vf-black, #000));
36
+ }
37
+ `];
38
+ }
39
+ #e;
40
+ constructor() {
41
+ super(), this.scale = new t(this), this.gridSnap = new a(this), this.vertical = !1, this.#e = this.attachInternals(), this.#e.role = "separator";
42
+ }
43
+ updated(e) {
44
+ e.has("vertical") && (this.#e.ariaOrientation = this.vertical ? "vertical" : null);
45
+ }
46
+ render() {
47
+ return c`<div class="rule vf-snap"></div>`;
48
+ }
49
+ };
50
+ n([l({
51
+ type: Boolean,
52
+ reflect: !0
53
+ })], u.prototype, "vertical", void 0), u = n([e("vf-separator")], u);
54
+ //#endregion
55
+ export { u as VfSeparator };
@@ -0,0 +1,80 @@
1
+ import type { PropertyValues } from 'lit';
2
+ import { VfFormControl } from '../form-control.js';
3
+ declare const VfSlider_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof VfFormControl;
4
+ /**
5
+ * `<vf-slider>` — a horizontal 1-bit slider.
6
+ *
7
+ * Not a historically shipped System 7 control: it reverse-adapts the later
8
+ * Mac OS slider into the library's solid-black, pixel-crisp 1-bit style. A
9
+ * rounded capsule rail fills solid black from the left up to a shield-shaped
10
+ * drag handle (the {@link SLIDER_THUMB} sprite) and runs hollow after it. The
11
+ * rail is regenerated as a whole-pixel SVG on every resize so it stays crisp at
12
+ * any width, and the thumb snaps to integer pixels so the sprite never blurs.
13
+ *
14
+ * Form-associated: submits `value` under `name` and restores it on form reset.
15
+ * Drag or click the track to set the value; focus it and use the arrow keys
16
+ * (Home/End jump to min/max, PageUp/PageDown move in bigger steps).
17
+ *
18
+ * @fires vf-input - On every drag move or key change. `detail: { value: number }`.
19
+ * @fires vf-change - On commit (pointer release, or key change). `detail: { value: number }`.
20
+ * @fires input - Native event, dispatched from the host on every user value
21
+ * move — a native range input's cadence. A programmatic `value` set fires
22
+ * nothing.
23
+ * @fires change - Native event, dispatched from the host on commit (release,
24
+ * or a key change) so form delegation and framework bindings hear it.
25
+ *
26
+ * @csspart track - The full-width rail row (the pointer target).
27
+ * @csspart rail - The `<svg>` capsule (fill + hollow).
28
+ * @csspart thumb - The shield-shaped drag handle.
29
+ */
30
+ export declare class VfSlider extends VfSlider_base {
31
+ #private;
32
+ static styles: import("lit").CSSResult[];
33
+ /** Current value, clamped to `[min, max]` and snapped to `step`. */
34
+ value: number;
35
+ /** Minimum value (inclusive). */
36
+ min: number;
37
+ /** Maximum value (inclusive). */
38
+ max: number;
39
+ /** Increment the value snaps to (also sets its display precision). */
40
+ step: number;
41
+ /** Form field name used when submitting the associated form. */
42
+ name: string;
43
+ /** Accessible name, exposed as the control's `aria-label`. */
44
+ label: string;
45
+ private track;
46
+ /** Measured content width of the rail, in px — the rail SVG is regenerated
47
+ * from it so every edge stays on the device grid. */
48
+ private readonly trackSize;
49
+ /** Default-on display scaling (true 72dpi size); see src/scale.ts. */
50
+ private readonly scale;
51
+ /** Device-pixel grid snapping (opt in with applyGridSnap()); see src/grid-snap.ts. */
52
+ private readonly gridSnap;
53
+ /** True when this component owns the host `tabindex`. */
54
+ private selfManagedTabIndex;
55
+ constructor();
56
+ connectedCallback(): void;
57
+ disconnectedCallback(): void;
58
+ /** Restores the initial value when the associated form resets. */
59
+ formResetCallback(): void;
60
+ /**
61
+ * Restored form state parses back to the numeric `value` (the stored state
62
+ * is `String(clampedValue)`; the base default would assign the string).
63
+ */
64
+ protected applyFormState(state: string): void;
65
+ /**
66
+ * Mirror state into the form value, ARIA and the tab stop — each write gated
67
+ * on the properties it derives from, so the re-renders driven by unrelated
68
+ * state (the focus ring, a rail resize tick) don't re-run all of it. On the
69
+ * first update every reactive property is in `changed` (class-field defaults,
70
+ * with `undefined` as the old value), so the initial writes all still happen.
71
+ */
72
+ protected updated(changed: PropertyValues<this>): void;
73
+ protected render(): import("lit-html").TemplateResult<1>;
74
+ }
75
+ declare global {
76
+ interface HTMLElementTagNameMap {
77
+ 'vf-slider': VfSlider;
78
+ }
79
+ }
80
+ export {};
@@ -0,0 +1,255 @@
1
+ import { vfElement as e } from "../define.js";
2
+ import { ScaleController as t, sys as n, toSys as r } from "../scale.js";
3
+ import i from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
4
+ import { VfPositioned as a } from "../position.js";
5
+ import { vfBase as o } from "../styles/recipes/host.js";
6
+ import { vfFocusUnderline as s } from "../styles/recipes/focus.js";
7
+ import { GridSnapController as c } from "../grid-snap.js";
8
+ import { emit as l, emitNative as u } from "../events.js";
9
+ import { SLIDER_THUMB as d, SLIDER_THUMB_FACE as f } from "../glyphs.js";
10
+ import { VfFormControl as p } from "../form-control.js";
11
+ import { FocusRuleController as m } from "../focus-modality.js";
12
+ import { decimalsOf as h } from "../number.js";
13
+ import { TrackWidthController as g } from "../track-width.js";
14
+ import { css as _, html as v } from "lit";
15
+ import { property as y, query as b } from "lit/decorators.js";
16
+ //#region src/components/vf-slider.ts
17
+ var x = 11, S = 12, C = 5, w = x / 2, T = 4, E = 3;
18
+ function D(e, t) {
19
+ let n = [], r = (e, t, r, i) => {
20
+ r > 0 && i > 0 && n.push(`M${e} ${t}h${r}v${i}h-${r}z`);
21
+ };
22
+ return r(1, 0, e - 2, 1), r(1, 3, e - 2, 1), r(0, 1, 1, 2), r(e - 1, 1, 1, 2), r(1, 1, Math.min(Math.max(t, 0), e - 1) - 1, 2), n.join("");
23
+ }
24
+ var O = class extends a(p) {
25
+ static {
26
+ this.styles = [o, _`
27
+ :host {
28
+ /* Padding just leaves room for the thumb's focus ring; the thumb itself
29
+ stays within the rail (its travel is inset by half its width). */
30
+ display: block;
31
+ padding: calc(var(--vf-scale, 1) * 3px) calc(var(--vf-scale, 1) * 4px);
32
+ color: var(--vf-black, #000);
33
+ cursor: var(--vf-cursor, default);
34
+ -webkit-tap-highlight-color: transparent;
35
+ }
36
+ .track {
37
+ position: relative;
38
+ width: 100%;
39
+ height: calc(var(--vf-scale, 1) * ${S}px);
40
+ touch-action: none;
41
+ }
42
+ /* A slider has no separate label — the fill *is* the value, so the whole
43
+ control dims to gray when disabled (like the number field's value).
44
+ Keyed off the resolved state (covers both the attribute and an ancestor
45
+ <fieldset disabled>), which .rail/.thumb inherit via currentColor. */
46
+ .track.disabled {
47
+ color: var(--vf-disabled, #c0c0c0);
48
+ pointer-events: none;
49
+ }
50
+ .rail {
51
+ position: absolute;
52
+ left: 0;
53
+ top: calc(var(--vf-scale, 1) * ${E}px);
54
+ height: calc(var(--vf-scale, 1) * ${T}px);
55
+ color: inherit;
56
+ pointer-events: none;
57
+ }
58
+ .rail path {
59
+ fill: currentColor;
60
+ }
61
+ .thumb {
62
+ position: absolute;
63
+ top: 0;
64
+ /* Above the rail so the opaque handle occludes it. */
65
+ z-index: 1;
66
+ width: calc(var(--vf-scale, 1) * ${x}px);
67
+ height: calc(var(--vf-scale, 1) * ${S}px);
68
+ color: inherit;
69
+ pointer-events: none;
70
+ }
71
+ .thumb-glyph {
72
+ display: block;
73
+ width: calc(var(--vf-scale, 1) * ${x}px);
74
+ height: calc(var(--vf-scale, 1) * ${S}px);
75
+ }
76
+ /* Solid white fill behind the black outline so the rail passes *behind*
77
+ the handle, not through its interior. */
78
+ .thumb-face {
79
+ fill: var(--vf-white, #fff);
80
+ }
81
+ .thumb-outline {
82
+ fill: currentColor;
83
+ }
84
+ /* Never draw the UA outline on the host: keyboard focus is the kit's
85
+ dashed rule under the RAIL, not a ring around the handle. Marking the
86
+ handle marked the value rather than the control, and moved as the value
87
+ did; the rail is the slider's whole extent, so the rule reads as one
88
+ underline for the control however far along the thumb has travelled.
89
+ One blank system px row under the rail's bottom edge, which sits
90
+ RAIL_TOP + RAIL_H from the track's top: the offset counts back up from
91
+ the track's own bottom, 12 − (3 + 4) − 1 − 1 = 3.
92
+
93
+ The thumb is z-index 1 and the rule is not, so the handle occludes the
94
+ dashes it passes over — the same way it occludes the rail behind it.
95
+
96
+ Gated on a class, not :focus-visible, as vf-select and vf-menu are: a
97
+ press on the track preventDefaults (to suppress text selection), which
98
+ cancels the native focus, so #onPointerDown calls focus() itself — and
99
+ Blink reads a scripted focus as a visible one. */
100
+ :host(:focus) {
101
+ outline: none;
102
+ }
103
+ .track.vf-focus-rule::after {
104
+ --vf-focus-underline-offset: ${3}px;
105
+ ${s}
106
+ }
107
+ `];
108
+ }
109
+ #e;
110
+ #t;
111
+ #n;
112
+ constructor() {
113
+ super(), this.value = 0, this.min = 0, this.max = 100, this.step = 1, this.name = "", this.label = "", this.trackSize = new g(this, () => this.track), this.scale = new t(this), this.gridSnap = new c(this), this.selfManagedTabIndex = !1, this.#e = new m(this), this.#t = 0, this.#n = !1, this.#f = (e) => {
114
+ if (!(this.isDisabled || e.button !== 0)) {
115
+ e.preventDefault(), this.#e.suppress(), this.focus(), this.#n = !0, this.#t = this.value;
116
+ try {
117
+ this.track?.setPointerCapture(e.pointerId);
118
+ } catch {}
119
+ this.#l(this.#d(e.clientX));
120
+ }
121
+ }, this.#p = (e) => {
122
+ this.#n && this.#l(this.#d(e.clientX));
123
+ }, this.#m = (e) => {
124
+ if (this.#n) {
125
+ this.#n = !1;
126
+ try {
127
+ this.track?.hasPointerCapture(e.pointerId) && this.track.releasePointerCapture(e.pointerId);
128
+ } catch {}
129
+ this.value !== this.#t && this.#u("vf-change");
130
+ }
131
+ }, this.#h = (e) => {
132
+ if (this.isDisabled) return;
133
+ let t = this.#i, n = Math.max(t, this.#r / 10), r = this.value;
134
+ switch (e.key) {
135
+ case "ArrowRight":
136
+ case "ArrowUp":
137
+ r = this.#o(this.#s + t);
138
+ break;
139
+ case "ArrowLeft":
140
+ case "ArrowDown":
141
+ r = this.#o(this.#s - t);
142
+ break;
143
+ case "PageUp":
144
+ r = this.#o(this.#s + n);
145
+ break;
146
+ case "PageDown":
147
+ r = this.#o(this.#s - n);
148
+ break;
149
+ case "Home":
150
+ r = this.min;
151
+ break;
152
+ case "End":
153
+ r = this.max;
154
+ break;
155
+ default: return;
156
+ }
157
+ e.preventDefault(), this.#e.reveal(), r !== this.value && (this.#l(r), this.#u("vf-change"));
158
+ }, this.internals.role = "slider", this.internals.ariaOrientation = "horizontal";
159
+ }
160
+ connectedCallback() {
161
+ super.connectedCallback(), this.latchFormDefault(this.value), this.hasAttribute("tabindex") || (this.selfManagedTabIndex = !0, this.tabIndex = this.isDisabled ? -1 : 0), this.addEventListener("keydown", this.#h);
162
+ }
163
+ disconnectedCallback() {
164
+ super.disconnectedCallback(), this.removeEventListener("keydown", this.#h);
165
+ }
166
+ formResetCallback() {
167
+ this.value = this.formDefault(0);
168
+ }
169
+ applyFormState(e) {
170
+ let t = Number(e);
171
+ Number.isNaN(t) || (this.value = t);
172
+ }
173
+ get #r() {
174
+ return this.max - this.min || 1;
175
+ }
176
+ get #i() {
177
+ return this.step > 0 ? this.step : 1;
178
+ }
179
+ #a(e) {
180
+ return Math.min(Math.max(e, this.min), this.max);
181
+ }
182
+ #o(e) {
183
+ let t = this.#i, n = Math.round((e - this.min) / t), r = this.#a(this.min + n * t);
184
+ return Number(r.toFixed(h(t)));
185
+ }
186
+ get #s() {
187
+ let e = Number.isFinite(this.value) ? this.value : this.min;
188
+ return this.#a(e);
189
+ }
190
+ get #c() {
191
+ return Math.min(Math.max((this.#s - this.min) / this.#r, 0), 1);
192
+ }
193
+ #l(e) {
194
+ e !== this.value && (this.value = e, this.#u("vf-input"));
195
+ }
196
+ #u(e) {
197
+ l(this, e, { value: this.value }), u(this, e === "vf-input" ? "input" : "change");
198
+ }
199
+ #d(e) {
200
+ let t = this.track?.getBoundingClientRect();
201
+ if (!t) return this.value;
202
+ let r = t.width - n(x, this);
203
+ if (r <= 0) return this.value;
204
+ let i = Math.min(Math.max((e - t.left - n(w, this)) / r, 0), 1);
205
+ return this.#o(this.min + i * this.#r);
206
+ }
207
+ #f;
208
+ #p;
209
+ #m;
210
+ #h;
211
+ updated(e) {
212
+ let t = this.disabledChanged(e), n = e.has("value") || e.has("min") || e.has("max");
213
+ (n || t) && this.syncFormValue(String(this.#s)), e.has("min") && (this.internals.ariaValueMin = String(this.min)), e.has("max") && (this.internals.ariaValueMax = String(this.max)), n && (this.internals.ariaValueNow = String(this.#s)), e.has("label") && (this.internals.ariaLabel = this.label || null), t && (this.internals.ariaDisabled = this.isDisabled ? "true" : "false", this.selfManagedTabIndex && (this.tabIndex = this.isDisabled ? -1 : 0));
214
+ }
215
+ render() {
216
+ let e = r(this.trackSize.width, this), t = Math.round(this.#c * Math.max(0, e - x)), i = n(t, this), a = t + C;
217
+ return v`
218
+ <div
219
+ class="track vf-snap ${this.#e.marked ? "vf-focus-rule" : ""} ${this.isDisabled ? "disabled" : ""}"
220
+ part="track"
221
+ @pointerdown=${this.#f}
222
+ @pointermove=${this.#p}
223
+ @pointerup=${this.#m}
224
+ @pointercancel=${this.#m}
225
+ @lostpointercapture=${this.#m}
226
+ >
227
+ ${e >= 2 ? v`<svg
228
+ class="rail"
229
+ part="rail"
230
+ width=${n(e, this)}
231
+ height=${n(T, this)}
232
+ viewBox="0 0 ${e} ${T}"
233
+ shape-rendering="crispEdges"
234
+ aria-hidden="true"
235
+ >
236
+ <path d=${D(e, a)}></path>
237
+ </svg>` : null}
238
+ <span class="thumb" part="thumb" style="left: ${i}px">
239
+ <svg
240
+ class="thumb-glyph"
241
+ viewBox="0 0 ${x} ${S}"
242
+ shape-rendering="crispEdges"
243
+ aria-hidden="true"
244
+ >
245
+ <path class="thumb-face" d=${f.d}></path>
246
+ <path class="thumb-outline" d=${d.d}></path>
247
+ </svg>
248
+ </span>
249
+ </div>
250
+ `;
251
+ }
252
+ };
253
+ i([y({ type: Number })], O.prototype, "value", void 0), i([y({ type: Number })], O.prototype, "min", void 0), i([y({ type: Number })], O.prototype, "max", void 0), i([y({ type: Number })], O.prototype, "step", void 0), i([y({ reflect: !0 })], O.prototype, "name", void 0), i([y()], O.prototype, "label", void 0), i([b(".track")], O.prototype, "track", void 0), O = i([e("vf-slider")], O);
254
+ //#endregion
255
+ export { O as VfSlider };
@@ -0,0 +1,188 @@
1
+ import { LitElement } from 'lit';
2
+ import type { PropertyValues } from 'lit';
3
+ /** Which axis the children run along. */
4
+ export type VfStackDirection = 'column' | 'row';
5
+ /**
6
+ * Where the children sit across the stack. Defaults per direction — `start`
7
+ * down a column, `center` across a row.
8
+ */
9
+ export type VfStackPlace = 'start' | 'center' | 'end';
10
+ declare const VfStack_base: (new (...args: any[]) => import("../size.js").VfSizedInterface) & (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
11
+ /**
12
+ * `<vf-stack>` — arrange things inside a window, in system pixels.
13
+ *
14
+ * A window body is the one place the kit stopped short: every control inside it
15
+ * is authored in system px, but the *spaces between* them were the consumer's
16
+ * problem, written by hand as `calc(var(--vf-scale, 1) * 12px)`. This is that
17
+ * calculation, as a component — a flexbox whose `gap`, `pad`, `width` and
18
+ * `height` are declared in whole system px and converted internally:
19
+ *
20
+ * ```html
21
+ * <vf-stack gap="12"> <!-- a column -->
22
+ * <vf-stack fill-width direction="row" gap="8"> <!-- a labeled field -->
23
+ * <vf-label width="80" for="name">Name:</vf-label>
24
+ * <vf-text-field id="name" fill-width></vf-text-field>
25
+ * </vf-stack>
26
+ * <vf-stack fill-width place="end"> <!-- an action row -->
27
+ * <vf-button-group>
28
+ * <vf-button>Cancel</vf-button>
29
+ * <vf-button variant="default">Save</vf-button>
30
+ * </vf-button-group>
31
+ * </vf-stack>
32
+ * </vf-stack>
33
+ * ```
34
+ *
35
+ * **Why this can't just be page CSS.** Scaling is default-on and *per
36
+ * component*: `ScaleController` sets `--vf-scale` on the component's own host,
37
+ * not on the document. So `var(--vf-scale, 1)` in a consumer's stylesheet
38
+ * resolves only where the rule's element happens to sit inside a `vf-*`
39
+ * ancestor and inherit it — true inside a window body, false for a plain
40
+ * `<div>` holding two buttons on an ordinary page, where the fallback `1` wins
41
+ * and the gap renders at 8px around 3×-sized buttons with no warning. A page
42
+ * that hasn't called `applyScale()` has no way to write "8 system px" at all.
43
+ * A component always can, because it *is* the scope — which is also why this
44
+ * one carries a {@link ScaleController} of its own: without it a lone stack
45
+ * would resolve its own gap against that same fallback while its children each
46
+ * self-scaled around it.
47
+ *
48
+ * **Whole system px is the only expressible value**, so the gap half of the
49
+ * layout contract (docs/SIZING.md rule 2) stops being a rule to remember. Declaring
50
+ * `width`/`height` covers the size half of rule 3 as well.
51
+ *
52
+ * **The geometry is governed by the content.** A column is as wide as its
53
+ * widest child and a row as tall as its tallest; children keep the size they
54
+ * drew themselves at (`flex: 0 0 auto` — no growing, no shrinking). System 7
55
+ * boxes are the size they are: a push button is as wide as its label, a popup
56
+ * menu hugs its widest option, and a window is a fixed box whose overflow is
57
+ * clipped at the frame, not a layout that squeezes its controls to fit. The
58
+ * stack distributes; it does not resize. That is why the box shrink-wraps
59
+ * (`fit-content`) rather than claiming its parent's whole width — a layout box
60
+ * that did would be inventing a size nobody declared.
61
+ *
62
+ * **`fill-width` / `fill-height` are how a child asks for more**, as bare
63
+ * attributes on consumer DOM the way `nosnap` opts an element out of snapping:
64
+ *
65
+ * ```html
66
+ * <vf-text-field fill-width></vf-text-field>
67
+ * ```
68
+ *
69
+ * Each names the *outcome*, not the axis, so the markup means the same thing
70
+ * wherever it lands; the stack does the flexbox translation, which is the whole
71
+ * reason to have a component. One rule to learn, about geometry rather than
72
+ * vocabulary: **the cross axis always has a size, the main axis only has slack
73
+ * if you declared one.** So `fill-width` always works in a column (the width is
74
+ * the widest child's) and needs a declared `width` in a row; `fill-height` is
75
+ * exactly the other way round. A fill with nothing to take is inert, not an
76
+ * error. Two children filling along the main axis end up *equal* — the zeroed
77
+ * flex basis is what lets them divide the slack rather than keep their natural
78
+ * sizes — and a child that declares its own size shouldn't also ask to fill it.
79
+ *
80
+ * A stack reads the same two attributes about *itself*, for the parents that
81
+ * aren't stacks: a window body, a fieldset, a scroll well, a grid cell. That is
82
+ * where a panel's width enters the tree, and from there `fill-width` hands it
83
+ * down a level at a time.
84
+ *
85
+ * **It paints nothing and means nothing.** No border, no background, no role,
86
+ * no keyboard behavior — what it holds decides what it is, as with
87
+ * {@link VfGrid}.
88
+ *
89
+ * **It holds its box on the device-pixel grid** — the `vf-container`
90
+ * arrangement, adopted here after first shipping without it. The original
91
+ * reasoning ("no ink of its own, and slotted `vf-*` children correct their own
92
+ * origins") accounted only for kit children: a stack is a positioned ancestor
93
+ * and a layout box for *anything*, and consumer content inside it — a div, an
94
+ * `<img>`, a run of text — has no controller of its own. So the flex
95
+ * container, the placed-child anchor and the `vf-snap` class live on one
96
+ * shadow box, and under `applyGridSnap()` the correction moves the stack's
97
+ * whole coordinate system; children (kit or not) ride it, and the sweep's
98
+ * outermost-first order means the kit children then find nothing left to
99
+ * correct. What this deliberately does not fix: a text-governed child width
100
+ * mid-row still shifts later siblings fractionally (their own controllers
101
+ * cover that), and centering still can't land on a whole pixel by itself.
102
+ *
103
+ * It is also the kit's one **typographically transparent** component: `vfBase`'s
104
+ * chrome face, ratio line box, color and non-selectability are all reset to
105
+ * `inherit` on the host. Wrapping content in a layout box must not change how
106
+ * that content reads — inside a window it goes on inheriting the window's face
107
+ * exactly as before, and on a plain page it leaves the page's typography (and
108
+ * its whole-pixel line boxes) alone.
109
+ *
110
+ * What it deliberately does **not** do: equalize its children's widths. A row of
111
+ * buttons still belongs in a `vf-button-group`, which sizes them all to the
112
+ * widest and aligns their *faces* rather than the `variant="default"` ring
113
+ * boxes a plain flex row would line up.
114
+ *
115
+ * @slot - The children to arrange. `fill-width` / `fill-height` on any of them.
116
+ */
117
+ export declare class VfStack extends VfStack_base {
118
+ static styles: import("lit").CSSResult[];
119
+ /**
120
+ * Which axis the children run along — `column` (the default) or `row`.
121
+ *
122
+ * A stack is vertical unless it says otherwise, the way the word is used
123
+ * everywhere else; a row is the one that reads as a deliberate choice in the
124
+ * markup.
125
+ */
126
+ direction: VfStackDirection;
127
+ /**
128
+ * The space between children, in whole system px. `0` by default: a layout
129
+ * box that spaced things out on its own would be exactly the kind of
130
+ * surprise SPEC §2 rules out when it says a component renders nothing
131
+ * unexpected outside its box.
132
+ */
133
+ gap: number;
134
+ /**
135
+ * Padding inside the stack, in whole system px — one to four values in the
136
+ * usual CSS shorthand order (`pad="12"`, `pad="10 12"`, `pad="14 12 10"`).
137
+ *
138
+ * Leave it off inside a `vf-window` body, which already carries its own 12px
139
+ * inset; a stack that means to own that inset goes inside `<vf-window flush>`.
140
+ */
141
+ pad?: string | number;
142
+ /**
143
+ * Where the children sit across the stack — `start`, `center` or `end`.
144
+ * Unset resolves per direction: `start` down a column, `center` across a row.
145
+ *
146
+ * Named `place` rather than `align` for a reason worth keeping in the source:
147
+ * `align` is a legacy HTML presentation attribute, and Blink maps it to
148
+ * `text-align` on any element, so the cross-axis switch used to re-align every
149
+ * run of copy inside the stack (see the `text-align` reset above).
150
+ *
151
+ * Note the one thing centering cannot do: land on a whole pixel by itself. A
152
+ * 16px caption centered in a row set by the 25-system-px `vf-number-field`
153
+ * sits at 4.5 system px, and no container can round that — it would have to
154
+ * read each child's height. `applyGridSnap()` keeps the caption's own ink
155
+ * crisp regardless (it corrects the origin inside the child's shadow root);
156
+ * `place="start"` is the deterministic escape.
157
+ */
158
+ place?: VfStackPlace;
159
+ /** Default-on display scaling (true 72dpi size); see src/scale.ts. */
160
+ private readonly scale;
161
+ /**
162
+ * Hold the box on the device-pixel grid under `applyGridSnap()` — see the
163
+ * class doc for why the original no-controller decision was reversed. The
164
+ * host is what gets measured; `.box` (vf-snap) is where the correction
165
+ * lands, taking the whole coordinate system with it.
166
+ */
167
+ private readonly gridSnap;
168
+ /** The shadow flex box `gap`/`pad` write to; exists from the first render. */
169
+ private readonly box;
170
+ /**
171
+ * `gap` and `pad` go on the shadow box's inline style as
172
+ * `calc(var(--vf-scale, 1) * Npx)`, the way VfSized writes the declared
173
+ * size. Emitting the calc rather than a resolved number keeps each one live
174
+ * against the display: the scale is read at paint time (the var resolves
175
+ * against the host's own --vf-scale by inheritance), so a stack follows a
176
+ * monitor change exactly as the metrics in a component's stylesheet do.
177
+ * A real property on a real element, not a custom property — a token would
178
+ * inherit, and a nested stack would silently pick up its parent's spacing.
179
+ */
180
+ protected updated(changed: PropertyValues<this>): void;
181
+ protected render(): import("lit-html").TemplateResult<1>;
182
+ }
183
+ declare global {
184
+ interface HTMLElementTagNameMap {
185
+ 'vf-stack': VfStack;
186
+ }
187
+ }
188
+ export {};