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,234 @@
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 { vfDisplay as i } from "../styles/recipes/display-face.js";
6
+ import { vfBase as a } from "../styles/recipes/host.js";
7
+ import { vfFocusUnderline as o } from "../styles/recipes/focus.js";
8
+ import { GridSnapController as s } from "../grid-snap.js";
9
+ import { BUTTON_FACE as c, BUTTON_FRAME as l, RING_FRAME as u, RING_HOLE as d, steppedRectClip as f, steppedRingClip as p } from "../pixel-frame.js";
10
+ import { deferActivation as m } from "../events.js";
11
+ import { VfShadowRoleControl as h } from "../form-control.js";
12
+ import { css as g, html as _, nothing as v, unsafeCSS as y } from "lit";
13
+ import { property as b, query as x } from "lit/decorators.js";
14
+ //#region src/components/vf-button.ts
15
+ var S = "vf-submitter", C = class extends r(h) {
16
+ constructor(...e) {
17
+ super(...e), this.type = "button", this.name = "", this.value = "", this.formAction = "", this.formEnctype = "", this.formMethod = "", this.formNoValidate = !1, this.formTarget = "", this.scale = new t(this), this.gridSnap = new s(this), this.#e = !1, this.handleClick = (e) => {
18
+ this.isDisabled || this.#e || this.resolvedType !== "button" && m(this, e, () => this.activate());
19
+ };
20
+ }
21
+ static {
22
+ this.shadowRootOptions = {
23
+ ...h.shadowRootOptions,
24
+ delegatesFocus: !0
25
+ };
26
+ }
27
+ static {
28
+ this.styles = [
29
+ a,
30
+ i,
31
+ g`
32
+ :host {
33
+ display: inline-flex;
34
+ position: relative;
35
+ cursor: var(--vf-cursor, default);
36
+ /* Display scaling: metrics are authored in *system pixels* and
37
+ multiplied by --vf-scale (default 1 = today's rendering). Opt a
38
+ subtree into true 72dpi size via applyScale()/--vf-scale — see
39
+ src/scale.ts. The chrome font scales with the control. */
40
+ font-size: calc(var(--vf-scale, 1) * var(--vf-font-size-display, 16px));
41
+ }
42
+ /* Breathing room for the default-button ring drawn at inset -4 system px.
43
+ A vf-button-group zeroes this (via --vf-button-ring-margin) and reserves
44
+ the ring space itself, so grouped button *faces* align instead of their
45
+ margin boxes — see src/components/vf-button-group.ts. */
46
+ :host([variant='default']) {
47
+ margin: calc(
48
+ var(--vf-scale, 1) * var(--vf-button-ring-margin, ${4}px)
49
+ );
50
+ }
51
+ /* The default ring: a 3px stepped band with a transparent 1px gap to the
52
+ button, clipped as an evenodd donut so the gap shows the surface
53
+ behind it (the reference's gap pixels are alpha-0). */
54
+ :host([variant='default'])::before {
55
+ content: '';
56
+ position: absolute;
57
+ /* The ring anchors to the host, not the corrected button, so each
58
+ inset composes the snap offset (see grid-snap.ts) to ride along. */
59
+ top: calc(var(--vf-scale, 1) * -${4}px + var(--vf-snap-dy, 0px));
60
+ left: calc(var(--vf-scale, 1) * -${4}px + var(--vf-snap-dx, 0px));
61
+ bottom: calc(var(--vf-scale, 1) * -${4}px - var(--vf-snap-dy, 0px));
62
+ right: calc(var(--vf-scale, 1) * -${4}px - var(--vf-snap-dx, 0px));
63
+ background: var(--vf-black, #000);
64
+ clip-path: ${y(p(u, d))};
65
+ pointer-events: none;
66
+ }
67
+ /* Disabled default: the fat outer ring dims to gray; the inner button
68
+ border stays solid black (see button:disabled) — the System 7 reading,
69
+ where the ring and the title dim together and the button's own frame
70
+ does not. (The original dimmed with a 50% stipple; gray standing in
71
+ for it is the kit's one liberty here — SPEC §1.)
72
+
73
+ Both disabled routes need a selector, because only one of them is an
74
+ attribute: an ancestor <fieldset disabled> disables the control
75
+ through formDisabledCallback, which sets the form-disabled custom
76
+ state and never touches the disabled attribute. Keyed on the
77
+ attribute alone, a default button inside a disabled fieldset greyed
78
+ its label — that comes from the inner <button>'s own :disabled —
79
+ while its ring stayed solid black. Separate rules rather than one
80
+ :is() list: an engine that doesn't parse :state() drops the whole
81
+ selector it appears in, and the attribute case should survive that
82
+ on its own. */
83
+ :host([variant='default'][disabled])::before {
84
+ background: var(--vf-disabled, #c0c0c0);
85
+ }
86
+ :host([variant='default']:state(form-disabled))::before {
87
+ background: var(--vf-disabled, #c0c0c0);
88
+ }
89
+ /* The native button paints no box of its own — its frame and face are
90
+ the stepped pseudo-element silhouettes below. Keeping the clip-paths
91
+ off the button itself leaves the hit area a plain rectangle, and
92
+ anything painted outside the silhouette (a ring a consumer restores
93
+ on ::part(button)) unclipped. */
94
+ button {
95
+ position: relative;
96
+ /* Own stacking context so the negative-z silhouettes stay inside the
97
+ button: above everything behind it, below the label. */
98
+ z-index: 0;
99
+ display: inline-flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ /* 20px, not the 22px fields: the reference sheets put the button face
103
+ at 80×20 (and the default ring's inner box at exactly that), so the
104
+ ring traces were authored against a 20px face. --vf-control-height
105
+ stays the *field* height — see SPEC §3. */
106
+ height: calc(var(--vf-scale, 1) * var(--vf-button-height, 20px));
107
+ min-width: calc(var(--vf-scale, 1) * 64px);
108
+ /* Fill the host so a vf-button-group can stretch this face to the
109
+ shared column width. Standalone (shrink-wrapped host) it's a no-op. */
110
+ flex: var(--vf-button-flex, 0 1 auto);
111
+ padding: 0 calc(var(--vf-scale, 1) * 14px);
112
+ background: none;
113
+ border: none;
114
+ color: var(--vf-black, #000);
115
+ font-family: inherit;
116
+ font-size: inherit;
117
+ font-weight: inherit;
118
+ line-height: inherit;
119
+ white-space: nowrap;
120
+ cursor: inherit;
121
+ }
122
+ /* Frame: the outer silhouette in solid black. The face below covers all
123
+ but the outline, leaving the reference's exact border pixels — the
124
+ QuickDraw difference-of-silhouettes, not a stroked border. */
125
+ button::before,
126
+ button::after {
127
+ content: '';
128
+ position: absolute;
129
+ inset: 0;
130
+ z-index: -1;
131
+ }
132
+ button::before {
133
+ background: var(--vf-black, #000);
134
+ clip-path: ${y(f(l))};
135
+ }
136
+ /* Face: white fill inset one pixel, with its own traced corner steps. */
137
+ button::after {
138
+ background: var(--vf-white, #fff);
139
+ clip-path: ${y(f(c))};
140
+ }
141
+ /* Pressed: instant white-on-black inversion. */
142
+ button:active:not(:disabled) {
143
+ color: var(--vf-white, #fff);
144
+ }
145
+ button:active:not(:disabled)::after {
146
+ background: var(--vf-black, #000);
147
+ }
148
+ /* The label rides in its own box so the focus underline can span the
149
+ text and not the button's padding: as the flex item it shrink-wraps
150
+ to the label, and its 20px line box puts the baseline a known
151
+ distance above its bottom edge (see vfFocusUnderline). */
152
+ .label {
153
+ position: relative;
154
+ }
155
+ /* Keyboard focus is the dashed rule under the label, not a ring around
156
+ the control — so the UA's own outline goes. */
157
+ button:focus-visible {
158
+ outline: none;
159
+ }
160
+ /* …and off the host too. Blink doesn't currently propagate
161
+ :focus-visible to a delegatesFocus host, so today this paints nothing
162
+ — but SPEC §vf-button claims the ring is off on both, and that claim
163
+ should hold because the component says so, not because one engine
164
+ happens to agree. Its own rule, not a selector list with the above:
165
+ one unparsed selector would drop the other with it. */
166
+ :host(:focus-visible) {
167
+ outline: none;
168
+ }
169
+ button:focus-visible .label::after {
170
+ ${o}
171
+ }
172
+ /* Disabled: only the label dims to gray; the solid black border stays. */
173
+ button:disabled {
174
+ color: var(--vf-disabled, #c0c0c0);
175
+ }
176
+ `
177
+ ];
178
+ }
179
+ #e;
180
+ get resolvedType() {
181
+ let e = String(this.type ?? "").toLowerCase();
182
+ return e === "submit" ? "submit" : e === "reset" ? "reset" : "button";
183
+ }
184
+ click() {
185
+ let e = this.buttonEl;
186
+ e ? e.click() : super.click();
187
+ }
188
+ render() {
189
+ return _`
190
+ <button
191
+ part="button"
192
+ class="vf-snap"
193
+ type="button"
194
+ aria-label=${this.hostAriaLabel || v}
195
+ aria-describedby=${this.describedBy}
196
+ ?disabled=${this.isDisabled}
197
+ @click=${this.handleClick}
198
+ >
199
+ <span class="label"><slot></slot></span>
200
+ </button>
201
+ ${this.renderDescription()}
202
+ `;
203
+ }
204
+ activate() {
205
+ let e = this.resolvedType;
206
+ if (!this.internals.form || e === "button" || this.isDisabled) return;
207
+ let t = document.createElement("button");
208
+ t.type = e, t.slot = S, t.addEventListener("click", (e) => e.stopPropagation()), e === "submit" && (this.name && (t.name = this.name, t.value = this.value), this.formAction && (t.formAction = this.formAction), this.formEnctype && (t.formEnctype = this.formEnctype), this.formMethod && (t.formMethod = this.formMethod), this.formTarget && (t.formTarget = this.formTarget), t.formNoValidate = this.formNoValidate), this.#e = !0;
209
+ try {
210
+ this.append(t), t.click();
211
+ } finally {
212
+ t.remove(), this.#e = !1;
213
+ }
214
+ }
215
+ };
216
+ n([b({ reflect: !0 })], C.prototype, "variant", void 0), n([b({ reflect: !0 })], C.prototype, "type", void 0), n([b({ reflect: !0 })], C.prototype, "name", void 0), n([b({ reflect: !0 })], C.prototype, "value", void 0), n([b({
217
+ attribute: "formaction",
218
+ reflect: !0
219
+ })], C.prototype, "formAction", void 0), n([b({
220
+ attribute: "formenctype",
221
+ reflect: !0
222
+ })], C.prototype, "formEnctype", void 0), n([b({
223
+ attribute: "formmethod",
224
+ reflect: !0
225
+ })], C.prototype, "formMethod", void 0), n([b({
226
+ type: Boolean,
227
+ attribute: "formnovalidate",
228
+ reflect: !0
229
+ })], C.prototype, "formNoValidate", void 0), n([b({
230
+ attribute: "formtarget",
231
+ reflect: !0
232
+ })], C.prototype, "formTarget", void 0), n([x("button")], C.prototype, "buttonEl", void 0), C = n([e("vf-button")], C);
233
+ //#endregion
234
+ export { C as VfButton };
@@ -0,0 +1,60 @@
1
+ import { type PropertyValues } from 'lit';
2
+ import { VfFormControl } from '../form-control.js';
3
+ declare const VfCheckbox_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & (abstract new (...args: any[]) => import("../toggle-control.js").VfToggleControlInterface) & typeof VfFormControl;
4
+ /**
5
+ * The classic System 7 checkbox: a 13×13 white square with a 1px black
6
+ * border whose checked state is the corner-to-corner ✕ glyph — the pixel-exact
7
+ * cross traced from the Classic Macintosh UI Kit sprite. The border "thickens"
8
+ * while pressed, exactly like the original control.
9
+ *
10
+ * Form-associated: submits `value` under `name` when checked (like a native
11
+ * checkbox) and restores its initial checked state on form reset. Toggles on
12
+ * click and Space.
13
+ *
14
+ * @slot - The label, rendered to the right of the box with a 6px gap.
15
+ * @csspart box - The 13×13 checkbox square.
16
+ * @csspart label - The label wrapper around the slot.
17
+ * @fires vf-change - When toggled by user interaction. `detail: { checked: boolean }`.
18
+ * @fires input - Native event, dispatched from the host per user toggle (with
19
+ * `change`, the pair a native checkbox fires). A programmatic `checked` set
20
+ * fires nothing, as on a native checkbox.
21
+ * @fires change - Native event, dispatched from the host per user toggle so
22
+ * form delegation and framework bindings hear it.
23
+ */
24
+ export declare class VfCheckbox extends VfCheckbox_base {
25
+ static styles: import("lit").CSSResult[];
26
+ /** Whether the checkbox is checked. */
27
+ checked: boolean;
28
+ /** Form field name used when submitting. */
29
+ name: string;
30
+ /** Value submitted with the form while checked. */
31
+ value: string;
32
+ /** `required` on a checkbox means it must be checked, as on a native one. */
33
+ protected get valueMissing(): boolean;
34
+ /** The message a native `<input type="checkbox" required>` reports. */
35
+ protected get valueMissingMessage(): string;
36
+ constructor();
37
+ connectedCallback(): void;
38
+ /** The handle {@link VfFormControl} already attached. */
39
+ protected get toggleInternals(): ElementInternals;
40
+ /** `disabled`, or an ancestor `<fieldset disabled>`. */
41
+ protected get toggleDisabled(): boolean;
42
+ render(): import("lit-html").TemplateResult<1>;
43
+ protected updated(changed: PropertyValues<this>): void;
44
+ /** Form-associated lifecycle: restores the initial checked state. */
45
+ formResetCallback(): void;
46
+ /**
47
+ * Restored form state means the flag, not `value`: a checkbox only ever
48
+ * stores its submission string while checked, so getting one back IS
49
+ * "checked" (the base default would have overwritten `value` instead).
50
+ */
51
+ protected applyFormState(): void;
52
+ /** Click/Space on an enabled checkbox flips it. */
53
+ protected activate(): void;
54
+ }
55
+ declare global {
56
+ interface HTMLElementTagNameMap {
57
+ 'vf-checkbox': VfCheckbox;
58
+ }
59
+ }
60
+ export {};
@@ -0,0 +1,135 @@
1
+ import { vfElement as e } from "../define.js";
2
+ import t from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
3
+ import { VfPositioned as n } from "../position.js";
4
+ import { vfDisplay as r } from "../styles/recipes/display-face.js";
5
+ import { vfBase as i } from "../styles/recipes/host.js";
6
+ import { vfFocusUnderline as a } from "../styles/recipes/focus.js";
7
+ import { vfToggle as o } from "../styles/recipes/toggle.js";
8
+ import { emit as s, emitNative as c } from "../events.js";
9
+ import { CHECKBOX_X as l, glyphSvg as u } from "../glyphs.js";
10
+ import { VfFormControl as d } from "../form-control.js";
11
+ import { VfToggleControl as f } from "../toggle-control.js";
12
+ import { css as p, html as m } from "lit";
13
+ import { property as h } from "lit/decorators.js";
14
+ import { classMap as g } from "lit/directives/class-map.js";
15
+ //#region src/components/vf-checkbox.ts
16
+ var _ = class extends n(f(d)) {
17
+ static {
18
+ this.styles = [
19
+ i,
20
+ r,
21
+ o,
22
+ p`
23
+ /* Keyboard focus underlines the box itself — not the label, and not a
24
+ ring around either (see vfFocusUnderline). Both adjustments below are
25
+ the 1px border: an absolutely positioned pseudo sizes to the PADDING
26
+ box, which the border sits outside of. So the rule grows 1px each side
27
+ to span the whole well, and its offset counts the border before the
28
+ blank row and the rule itself: −(1 + 1 + 1). */
29
+ :host(:focus-visible) .box::after {
30
+ --vf-focus-underline-offset: -3px;
31
+ ${a}
32
+ left: calc(var(--vf-scale, 1) * -1px);
33
+ right: calc(var(--vf-scale, 1) * -1px);
34
+ }
35
+ .box {
36
+ position: relative;
37
+ flex: none;
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ width: calc(var(--vf-scale, 1) * 13px);
42
+ height: calc(var(--vf-scale, 1) * 13px);
43
+ background: var(--vf-white, #fff);
44
+ border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
45
+ color: var(--vf-black, #000);
46
+ }
47
+ /* Pressed: border thickens to 2px (classic press feedback). */
48
+ :host(:active) .box:not(.dim) {
49
+ box-shadow: inset 0 0 0 calc(var(--vf-scale, 1) * 1px) var(--vf-black, #000);
50
+ }
51
+ /* Forced colors never paints box-shadow, so the press feedback above
52
+ goes silent. The same thickening as a real border-width change: with
53
+ box-sizing: border-box the 13×13 box holds and the extra pixel grows
54
+ inward, exactly where the inset shadow painted. */
55
+ @media (forced-colors: active) {
56
+ :host(:active) .box:not(.dim) {
57
+ border-width: calc(var(--vf-scale, 1) * 2px);
58
+ }
59
+ }
60
+ /* Native 12×12 sprite — centered in the 13×13 box; the glyph's own 1px
61
+ transparent margin lets it overhang onto the border harmlessly. Scales
62
+ with the box; crispEdges keeps it whole-device-pixel at any dpr. */
63
+ .check {
64
+ flex: none;
65
+ width: calc(var(--vf-scale, 1) * 12px);
66
+ height: calc(var(--vf-scale, 1) * 12px);
67
+ display: none;
68
+ color: inherit;
69
+ }
70
+ :host([checked]) .check {
71
+ display: block;
72
+ }
73
+ `
74
+ ];
75
+ }
76
+ get valueMissing() {
77
+ return !this.checked;
78
+ }
79
+ get valueMissingMessage() {
80
+ return "Please check this box if you want to proceed.";
81
+ }
82
+ constructor() {
83
+ super(), this.checked = !1, this.name = "", this.value = "on", this.internals.role = "checkbox";
84
+ }
85
+ connectedCallback() {
86
+ super.connectedCallback(), this.latchFormDefault(this.checked);
87
+ }
88
+ get toggleInternals() {
89
+ return this.internals;
90
+ }
91
+ get toggleDisabled() {
92
+ return this.isDisabled;
93
+ }
94
+ render() {
95
+ let e = this.isDisabled;
96
+ return m`
97
+ <span
98
+ class=${g({
99
+ box: !0,
100
+ dim: e,
101
+ "vf-snap": !0
102
+ })}
103
+ part="box"
104
+ aria-hidden="true"
105
+ >
106
+ ${u(l, "check")}
107
+ </span>
108
+ <span class=${g({
109
+ label: !0,
110
+ dim: e,
111
+ "vf-snap": !0
112
+ })} part="label">
113
+ <slot></slot>
114
+ </span>
115
+ `;
116
+ }
117
+ updated(e) {
118
+ super.updated(e), (e.has("checked") || e.has("value") || this.disabledChanged(e)) && this.syncFormValue(this.checked ? this.value : null);
119
+ }
120
+ formResetCallback() {
121
+ this.checked = this.formDefault(!1);
122
+ }
123
+ applyFormState() {
124
+ this.checked = !0;
125
+ }
126
+ activate() {
127
+ this.checked = !this.checked, this.focus(), s(this, "vf-change", { checked: this.checked }), c(this, "input"), c(this, "change");
128
+ }
129
+ };
130
+ t([h({
131
+ type: Boolean,
132
+ reflect: !0
133
+ })], _.prototype, "checked", void 0), t([h({ reflect: !0 })], _.prototype, "name", void 0), t([h()], _.prototype, "value", void 0), _ = t([e("vf-checkbox")], _);
134
+ //#endregion
135
+ export { _ as VfCheckbox };
@@ -0,0 +1,95 @@
1
+ import { LitElement } from 'lit';
2
+ declare const VfContainer_base: (new (...args: any[]) => import("../size.js").VfSizedInterface) & (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof LitElement;
3
+ /**
4
+ * `<vf-container>` — a box that is nothing but its declared size.
5
+ *
6
+ * The kit's positioned-placement story (src/position.ts) ends with one line of
7
+ * CSS it can't write for you: children placed with `top`/`left` need a
8
+ * positioned ancestor, and while every kit container is one — a window body, a
9
+ * stack, a fieldset — a region of *your own* needs `position: relative` in a
10
+ * stylesheet. This component is that region as an element: declare `width` and
11
+ * `height` in whole system px, slot anything into it, place children against
12
+ * its origin. A DITL's enclosing rectangle, with nothing drawn in it.
13
+ *
14
+ * ```html
15
+ * <vf-container width="200" height="120">
16
+ * <vf-icon label="System" width="64" top="8" left="12">…</vf-icon>
17
+ * <vf-icon label="Finder" width="64" top="8" left="104">…</vf-icon>
18
+ * </vf-container>
19
+ * ```
20
+ *
21
+ * The rectangle is the whole API — `width`/`height` here, plus the `top`/`left`
22
+ * pair nearly every component takes ({@link VfPositioned}), so a container is
23
+ * itself placeable: inside a window, a desktop, or another container, at whole
24
+ * system px that keep its box on the device-pixel grid by construction.
25
+ *
26
+ * **It is not a `vf-stack`.** The stack is a flexbox with opinions — it
27
+ * distributes children along an axis, compiles `fill-width`/`fill-height` into
28
+ * flex, defaults a cross-axis alignment. This box has no layout opinion at
29
+ * all: in-flow children get normal flow, placed children get a coordinate
30
+ * system, and that is the whole API. Reach for it when the stack's opinions
31
+ * are the thing in the way — a field of placed icons, a fixed stage for
32
+ * absolutely-positioned art, a consumer's own composition that brings its
33
+ * layout with it.
34
+ *
35
+ * **The declared size is the layout.** `width`/`height` land on the host as a
36
+ * live `calc(var(--vf-scale, 1) * Npx)` ({@link VfSized}), so the box scales
37
+ * with the display and sits on the device-pixel grid by construction. Content
38
+ * that outgrows the box overflows it rather than growing it — the number is
39
+ * the layout, and content that doesn't fit is a number to raise. Leave a
40
+ * dimension off and that axis shrink-wraps: `fit-content`, not the parent's
41
+ * width, because a layout box that silently claimed a size nobody declared
42
+ * would be inventing one (the `vf-stack` rule, held here too).
43
+ *
44
+ * **It paints nothing and means nothing.** No border, background, role,
45
+ * keyboard behavior or selection — what it holds decides what it is.
46
+ *
47
+ * **It holds its box on the device-pixel grid** — with a `GridSnapController`.
48
+ * A container's box is itself the consumer's coordinate system, including for
49
+ * non-`vf` content that cannot correct itself, so the box is the thing to
50
+ * hold on the grid. The shadow box below owns the `position: relative` anchor
51
+ * and the `vf-snap` class together, so under `applyGridSnap()` the correction
52
+ * moves the whole coordinate system — everything placed against it rides
53
+ * along instead of being re-corrected child by child. (`vf-stack` shipped
54
+ * without a controller on the theory that slotted `vf-*` children correct
55
+ * their own origins; this component is where that theory's gap — consumer
56
+ * content — became visible, and the stack has since adopted the same
57
+ * arrangement.)
58
+ *
59
+ * Like the stack it is **typographically transparent**: `vfBase`'s chrome
60
+ * dress is returned to `inherit` on the host, so wrapping content in a sized
61
+ * box changes nothing about how that content reads.
62
+ *
63
+ * `fill-width` / `fill-height` work here the way they do everywhere: read
64
+ * about the host (be as big as *its* parent allows), and compiled for slotted
65
+ * children — `width: 100%` in normal flow, so a child filling the cross of a
66
+ * declared box needs no stylesheet. A height fill needs a declared `height`
67
+ * to resolve against; with none it is inert, not an error.
68
+ *
69
+ * @slot - The content. In flow by default; `top`/`left` on a kit child places
70
+ * it against this box's origin. `fill-width` / `fill-height` on a child
71
+ * fills it to the declared box.
72
+ */
73
+ export declare class VfContainer extends VfContainer_base {
74
+ static styles: import("lit").CSSResult[];
75
+ /**
76
+ * Default-on display scaling (true 72dpi size); see src/scale.ts. Without
77
+ * one, a lone container on a plain page would resolve its declared size
78
+ * against the `var(--vf-scale, 1)` fallback while its slotted children each
79
+ * self-scaled around it — the vf-stack reasoning, inherited with the rest.
80
+ */
81
+ private readonly scale;
82
+ /**
83
+ * Hold the box on the device-pixel grid under `applyGridSnap()` — see the
84
+ * class doc. The host is what gets measured; `.box` (vf-snap) is where the
85
+ * correction lands.
86
+ */
87
+ private readonly gridSnap;
88
+ protected render(): import("lit-html").TemplateResult<1>;
89
+ }
90
+ declare global {
91
+ interface HTMLElementTagNameMap {
92
+ 'vf-container': VfContainer;
93
+ }
94
+ }
95
+ export {};
@@ -0,0 +1,86 @@
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 { VfSized as o } from "../size.js";
8
+ import { LitElement as s, css as c, html as l } from "lit";
9
+ //#region src/components/vf-container.ts
10
+ var u = class extends o(r(s)) {
11
+ constructor(...e) {
12
+ super(...e), this.scale = new t(this), this.gridSnap = new a(this);
13
+ }
14
+ static {
15
+ this.styles = [i, c`
16
+ :host {
17
+ display: block;
18
+ /* Shrink-wrap an undeclared axis rather than claim the parent's
19
+ width — the vf-stack rule: a layout box must not hand out a size
20
+ nobody declared. A declared width/height lands on the host's inline
21
+ style (VfSized) and beats this. */
22
+ width: fit-content;
23
+ /* Typographic transparency — the same reset vf-stack carries, for the
24
+ same reason: vfBase dresses a host as chrome (body face, ratio line
25
+ box, black, unselectable), and a box that holds no text of its own
26
+ must not change how slotted content reads. font is a shorthand, so
27
+ it carries the line box back with the family, size and weight. */
28
+ font: inherit;
29
+ -webkit-font-smoothing: inherit;
30
+ color: inherit;
31
+ user-select: inherit;
32
+ -webkit-user-select: inherit;
33
+ text-align: inherit;
34
+ }
35
+
36
+ /* The coordinate system, as one shadow box coinciding with the host box.
37
+ vf-snap (vfBase) gives it position: relative plus the controller's
38
+ --vf-snap-dx/-dy offset — so it is BOTH the positioning anchor for
39
+ children placed with top/left (src/position.ts) AND the element the
40
+ grid-snap correction lands on. One element owning both is the point:
41
+ corrected, it takes every placed child with it, kit or not. */
42
+ .box {
43
+ /* flow-root: contain slotted margins, so the box's top edge — the
44
+ origin placed children measure from — stays glued to the host's
45
+ corner instead of being pushed down by a first child's margin
46
+ collapsing through. */
47
+ display: flow-root;
48
+ /* Coincide with a declared height (100% of a definite host height;
49
+ against an undeclared one it computes to auto and wraps content),
50
+ so slotted percentage fills resolve against the stated box. */
51
+ height: 100%;
52
+ }
53
+
54
+ /* The same two words a child uses, read about the host itself — for the
55
+ parents that can give this box a size: a window body, a filled stack
56
+ column, a grid cell. A percentage is the one fill a page can always
57
+ express; a declared width/height on the inline style beats it. */
58
+ :host([fill-width]) {
59
+ width: 100%;
60
+ }
61
+ :host([fill-height]) {
62
+ height: 100%;
63
+ }
64
+
65
+ /* And compiled for slotted children. Normal flow has no flex axes to
66
+ translate onto, so both fills are the percentage form: width resolves
67
+ against the box always, height only against a declared height —
68
+ percentage-against-auto computes to auto, so a fill with nothing to
69
+ take is inert, not an error (the vf-stack wording, kept true here). A
70
+ light-DOM declaration beats a ::slotted one, so a page can still
71
+ override either on its own children. */
72
+ ::slotted([fill-width]) {
73
+ width: 100%;
74
+ }
75
+ ::slotted([fill-height]) {
76
+ height: 100%;
77
+ }
78
+ `];
79
+ }
80
+ render() {
81
+ return l`<div class="vf-snap box"><slot></slot></div>`;
82
+ }
83
+ };
84
+ u = n([e("vf-container")], u);
85
+ //#endregion
86
+ export { u as VfContainer };