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,168 @@
1
+ import { vfElement as e } from "../define.js";
2
+ import { ScaleController as t, sysLength as n, sysLengths 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 { GridSnapController as s } from "../grid-snap.js";
7
+ import { VfSized as c } from "../size.js";
8
+ import { LitElement as l, css as u, html as d } from "lit";
9
+ import { property as f, query as p } from "lit/decorators.js";
10
+ //#region src/components/vf-stack.ts
11
+ var m = class extends c(a(l)) {
12
+ constructor(...e) {
13
+ super(...e), this.direction = "column", this.gap = 0, this.scale = new t(this), this.gridSnap = new s(this);
14
+ }
15
+ static {
16
+ this.styles = [o, u`
17
+ :host {
18
+ /* Shrink to the content, but stay BLOCK-level while doing it: the stack
19
+ is exactly as big as what it holds, so it can't hand a size it never
20
+ declared to the things inside it — and it takes no part in its
21
+ parent's inline formatting while doing it.
22
+
23
+ fit-content, not inline-level, and the difference is 2 system px. An
24
+ inline-level box sits on a line box, and a line box can never be
25
+ shorter than the parent's strut: a stack shorter than the line-height
26
+ around it silently gains the difference as leading (the showcase's
27
+ swatch panel, an 18px row inside a 20px line box, grew by exactly
28
+ that). vertical-align: top removes the descender half of it; nothing
29
+ inside a component can shrink its parent's strut. So the box stays
30
+ block-level and shrink-wraps instead — same geometry, no line box, no
31
+ whitespace between two adjacent stacks, and the typographic
32
+ transparency below stops having an exception.
33
+
34
+ The flex machinery itself lives one element down, on .box — the host
35
+ is a plain block shell, so the grid-snap correction has an interior
36
+ element to land on while the host's own layout stays untouched. */
37
+ display: block;
38
+ width: fit-content;
39
+ /* Typographic transparency — see the class doc. vfBase dresses a host
40
+ as chrome (body face, 1.25 line box, black, unselectable); a stack
41
+ holds no text of its own, so imposing any of that on what it wraps
42
+ would make a layout box change how content reads. In particular a
43
+ ratio line-height landing on slotted prose is the exact rule-2 fault
44
+ the kit warns pages about. */
45
+ /* font is a shorthand, so it carries the line box back to inherit with
46
+ the family, size and weight; smoothing and color are their own
47
+ inherited properties and need saying. */
48
+ font: inherit;
49
+ -webkit-font-smoothing: inherit;
50
+ color: inherit;
51
+ /* inherit, not auto: a stack inside a window has to keep the window's
52
+ chrome rule (SPEC §1 — chrome text isn't selectable), and one on an
53
+ ordinary page has to keep the page's. auto would be a third answer
54
+ of its own. */
55
+ user-select: inherit;
56
+ -webkit-user-select: inherit;
57
+ /* text-align is on that list because of a trap this component walked
58
+ into: align is a LEGACY HTML PRESENTATION ATTRIBUTE. Blink maps the
59
+ align content attribute on any HTML element to text-align — "left" /
60
+ "right" / "center" by name, anything else verbatim — so the cross-axis
61
+ attribute, back when it was spelled align, silently right-aligned
62
+ every run of copy inside an action row. It is spelled place now, but
63
+ the reset stays: it costs nothing, it keeps old markup harmless, and
64
+ a layout box changing how content reads is the one thing this
65
+ component promises not to do. */
66
+ text-align: inherit;
67
+ }
68
+
69
+ /* The flex container, the positioning anchor for children placed with
70
+ top/left (src/position.ts), and the grid-snap target — one shadow box
71
+ coinciding with the host box, the vf-container arrangement. vf-snap
72
+ (vfBase) gives it position: relative plus the controller's
73
+ --vf-snap-dx/-dy offset, so one element owns the coordinate system
74
+ and its correction: corrected, it takes every child with it, kit or
75
+ not. It carries no padding of its own until pad writes some, so its
76
+ padding box IS the host box and the placed-child anchor ignores pad
77
+ exactly as before (pad, like any padding, is flow-only).
78
+
79
+ height: 100% hands a declared (or filled) host height to the flex
80
+ layout — against an undeclared height it computes to auto and the
81
+ content governs, as always. Width needs no saying: a block-level box
82
+ fills the host, and the host shrink-wraps from its content. */
83
+ .box {
84
+ display: flex;
85
+ height: 100%;
86
+ flex-direction: column;
87
+ align-items: flex-start;
88
+ }
89
+
90
+ /* The same two words a child uses, read by the stack about itself — for
91
+ the parents that aren't stacks and have no ::slotted rule to give: a
92
+ window body, a fieldset, a scroll well, a grid cell, a plain div. A
93
+ percentage is the one fill a page can always express, needing no
94
+ system px, so this is the boundary where the chain would otherwise
95
+ break. Inside a stack both rules apply and agree: 100% of a column's
96
+ content box is what stretch resolves to anyway, and along a row the
97
+ zeroed flex basis outranks a width. A declared width/height lands on
98
+ the host's inline style and beats both, which is the resolution of
99
+ "don't declare a size and ask to fill it". */
100
+ :host([fill-width]) {
101
+ width: 100%;
102
+ }
103
+ :host([fill-height]) {
104
+ height: 100%;
105
+ }
106
+
107
+ /* --- Cross axis --------------------------------------------------- */
108
+ /* The two directions want opposite things and always did: a column of
109
+ fields starts at the panel's left edge, while a row of a caption beside
110
+ a control centers on it. Both are stated as the direction's default
111
+ rather than as an "auto" value, so an unrecognized place (a stale
112
+ place="stretch", say) lands on the sane one instead of on flexbox's
113
+ own "normal", which stretches. The named values come after, and win at
114
+ equal specificity on source order. */
115
+ :host([direction='row']) .box {
116
+ flex-direction: row;
117
+ align-items: center;
118
+ }
119
+ :host([place='start']) .box {
120
+ align-items: flex-start;
121
+ }
122
+ :host([place='center']) .box {
123
+ align-items: center;
124
+ }
125
+ :host([place='end']) .box {
126
+ align-items: flex-end;
127
+ }
128
+
129
+ /* --- Children ----------------------------------------------------- */
130
+ /* Neither grow nor shrink: the content governs the box, not the other way
131
+ round (see the class doc). A light-DOM declaration beats a ::slotted
132
+ one, so a page can still override any of this on its own children —
133
+ align-self: stretch is the escape hatch for the cross-axis fill a
134
+ direction doesn't offer, and needs no system px to write. */
135
+ ::slotted(*) {
136
+ flex: 0 0 auto;
137
+ }
138
+ /* fill-width / fill-height name the outcome, so each one compiles to the
139
+ main axis or the cross axis depending on which way the stack runs. The
140
+ min-* that rides the main-axis form is what lets a filled child shrink
141
+ below its content: the flex-item min-width: auto default is what
142
+ otherwise pins a text field to its value's width. */
143
+ :host(:not([direction='row'])) ::slotted([fill-width]) {
144
+ align-self: stretch;
145
+ }
146
+ :host(:not([direction='row'])) ::slotted([fill-height]) {
147
+ flex: 1 1 0;
148
+ min-height: 0;
149
+ }
150
+ :host([direction='row']) ::slotted([fill-width]) {
151
+ flex: 1 1 0;
152
+ min-width: 0;
153
+ }
154
+ :host([direction='row']) ::slotted([fill-height]) {
155
+ align-self: stretch;
156
+ }
157
+ `];
158
+ }
159
+ updated(e) {
160
+ e.has("gap") && (this.box.style.gap = n(this.gap)), e.has("pad") && (this.box.style.padding = r(this.pad));
161
+ }
162
+ render() {
163
+ return d`<div class="vf-snap box"><slot></slot></div>`;
164
+ }
165
+ };
166
+ i([f({ reflect: !0 })], m.prototype, "direction", void 0), i([f({ type: Number })], m.prototype, "gap", void 0), i([f()], m.prototype, "pad", void 0), i([f({ reflect: !0 })], m.prototype, "place", void 0), i([p(".box")], m.prototype, "box", void 0), m = i([e("vf-stack")], m);
167
+ //#endregion
168
+ export { m as VfStack };
@@ -0,0 +1,98 @@
1
+ import { type PropertyValues } from 'lit';
2
+ import { VfShadowRoleControl } from '../form-control.js';
3
+ declare const VfSwatch_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof VfShadowRoleControl;
4
+ /**
5
+ * `<vf-swatch>` — a color-swatch button: the color well of a palette cell.
6
+ *
7
+ * A solid rectangle with a 1px black border and a 1px white inset ring, filled
8
+ * edge-to-edge with a solid color. Given no `color` at all it shows the
9
+ * transparency checker instead — the "this cell holds nothing" grid every
10
+ * paint program draws behind an empty fill.
11
+ *
12
+ * `width`/`height` state the border box in whole system pixels (the fill is
13
+ * what remains inside the border and inset), multiplied by `--vf-scale` like
14
+ * every other metric, so the swatch holds the device-pixel grid wherever a
15
+ * palette puts it.
16
+ *
17
+ * `shadow` opts into the kit's hard drop shadow — the shared
18
+ * `--vf-shadow-offset` token, the same depth cue as windows, menus and alerts,
19
+ * painted outside the box like theirs. It is off by default because the
20
+ * swatch's usual home is a table of them (a `vf-grid`, a picker row), where
21
+ * every cell shadowing its neighbour reads as noise rather than depth; a lone
22
+ * well standing in for a current color — the one a dialog asks you to click —
23
+ * is the case that wants it.
24
+ *
25
+ * It is "basically a button": a native `<button>` inside, so `click` retargets
26
+ * to the host, Enter/Space activate it, and pressing inverts the white inset
27
+ * to black — the inset counterpart of vf-button's face inversion. Keyboard
28
+ * focus is marked with the kit's 1px dashed rule under the box
29
+ * (`vfFocusUnderline`) rather than a ring around it. It is form-associated
30
+ * for the *disabled* contract alone — an ancestor `<fieldset disabled>` must
31
+ * reach a palette the way it reaches every other control, and only the
32
+ * form-associated lifecycle delivers that across the shadow boundary — but it
33
+ * submits nothing (a palette cell picks, it doesn't submit; no `name`, no
34
+ * value, no `FormData` entry). `disabled` only stops interaction, dimming
35
+ * nothing — the kit dims *labels* when disabled, and a swatch's only label is
36
+ * its fill, which must keep reading as its color.
37
+ *
38
+ * @csspart button - The inner native `<button>` (border, inset and, with
39
+ * `shadow`, the drop shadow).
40
+ * @csspart fill - The color area inside the inset.
41
+ * @cssprop --vf-swatch-checker - `vf-swatch`'s no-color transparency checker —
42
+ * a 4×4 motif of 2×2 white/`#c0c0c0` checks, on a 60-system-px tile
43
+ * (override the whole tile like `--vf-desktop-pattern` — consumer art
44
+ * renders as a placed tile grid at that same geometry)
45
+ */
46
+ export declare class VfSwatch extends VfSwatch_base {
47
+ #private;
48
+ static shadowRootOptions: ShadowRootInit;
49
+ static styles: import("lit").CSSResult[];
50
+ /**
51
+ * The fill — a CSS color, typically the hex the palette calls for. Unset,
52
+ * the swatch shows the transparency checker; a translucent value (an
53
+ * 8-digit hex) layers over that same checker, so partial opacity reads as
54
+ * partial. An unparseable value falls back to the checker too.
55
+ */
56
+ color?: string;
57
+ /** The swatch's border box width in whole system px. */
58
+ width: number;
59
+ /** The swatch's border box height in whole system px. */
60
+ height: number;
61
+ /**
62
+ * Cast the kit's hard drop shadow (`--vf-shadow-offset`). Off by default:
63
+ * the plain black-bordered well is what a table of swatches wants, and the
64
+ * depth cue is for the lone well that stands in for a current color.
65
+ */
66
+ shadow: boolean;
67
+ /**
68
+ * Accessible name for the inner button — a swatch has no text of its own.
69
+ * Left empty, the name falls back to whatever the host carries
70
+ * (`aria-labelledby`, `aria-label`, an associated `<label for>` — see
71
+ * {@link VfShadowRoleControl.hostLabel}), then to the `color` value (or
72
+ * "transparent") as a last resort, so a palette is never nameless — but a
73
+ * hex literal announced as "number f f six six zero zero" is a fallback to
74
+ * name past, not a name. `vf-label`'s `for` wiring writes this property,
75
+ * like every `vf-*` control's.
76
+ */
77
+ label: string;
78
+ /** Disables the control: it stops responding. Nothing dims (see class doc). */
79
+ disabled: boolean;
80
+ /** Default-on display scaling (true 72dpi size); see src/scale.ts. */
81
+ private readonly scale;
82
+ /** Device-pixel grid snapping (opt in with applyGridSnap()); see src/grid-snap.ts. */
83
+ private readonly gridSnap;
84
+ /**
85
+ * The consumer's `--vf-swatch-checker` override, or `''` for the kit
86
+ * checker — which exact-fill path render() takes (src/tile-grid.ts).
87
+ * Re-read every update; a runtime token swap wants a `requestUpdate()`.
88
+ */
89
+ private _pattern;
90
+ protected willUpdate(changed: PropertyValues<this>): void;
91
+ protected render(): import("lit-html").TemplateResult<1>;
92
+ }
93
+ declare global {
94
+ interface HTMLElementTagNameMap {
95
+ 'vf-swatch': VfSwatch;
96
+ }
97
+ }
98
+ export {};
@@ -0,0 +1,201 @@
1
+ import { vfElement as e } from "../define.js";
2
+ import { ScaleController as t, sysLength as n } from "../scale.js";
3
+ import r from "../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
4
+ import { VfPositioned as i } from "../position.js";
5
+ import { vfBase as a } from "../styles/recipes/host.js";
6
+ import { tileImage as o, tileRects as s, tileSpan as c, vfTileSize as l } from "../styles/recipes/tile.js";
7
+ import { vfHardShadowDecls as u } from "../styles/recipes/shadow.js";
8
+ import { vfFocusUnderline as d } from "../styles/recipes/focus.js";
9
+ import { TileRasterCache as f, patternOverride as p, tileGrid as m, vfTileGrid as h } from "../tile-grid.js";
10
+ import { GridSnapController as g } from "../grid-snap.js";
11
+ import { VfShadowRoleControl as _ } from "../form-control.js";
12
+ import { css as v, html as y, unsafeCSS as b } from "lit";
13
+ import { property as x } from "lit/decorators.js";
14
+ import { styleMap as S } from "lit/directives/style-map.js";
15
+ //#region src/components/vf-swatch.ts
16
+ var C = 4, w = [
17
+ [
18
+ 0,
19
+ 0,
20
+ 4,
21
+ 4,
22
+ "#ffffff"
23
+ ],
24
+ [
25
+ 0,
26
+ 0,
27
+ 2,
28
+ 2,
29
+ "#c0c0c0"
30
+ ],
31
+ [
32
+ 2,
33
+ 2,
34
+ 2,
35
+ 2,
36
+ "#c0c0c0"
37
+ ]
38
+ ], T = o(C, C, s(w)), E = c(C), D = class extends i(_) {
39
+ constructor(...e) {
40
+ super(...e), this.width = 24, this.height = 18, this.shadow = !1, this.label = "", this.disabled = !1, this.scale = new t(this), this.gridSnap = new g(this), this._pattern = "", this.#e = new f();
41
+ }
42
+ static {
43
+ this.shadowRootOptions = {
44
+ ..._.shadowRootOptions,
45
+ delegatesFocus: !0
46
+ };
47
+ }
48
+ static {
49
+ this.styles = [
50
+ a,
51
+ h,
52
+ v`
53
+ :host {
54
+ display: inline-flex;
55
+ cursor: var(--vf-cursor, default);
56
+ /* The transparency checker: 2×2-system-px white/#c0c0c0 checks on a
57
+ 4×4 motif. Resolved into a private property once so the underlay
58
+ rule and the tile grid's art channel below share one definition;
59
+ override the public token to retheme the whole tile. What actually
60
+ shows is the exact fill rendered into .fill (see src/tile-grid.ts):
61
+ the whole-surface raster for the kit checker, or the placed tile
62
+ grid at the token's documented 60-px tile geometry for a consumer
63
+ override. */
64
+ --_checker: var(--vf-swatch-checker, ${b(T)});
65
+ /* How deep a shadow this swatch actually casts — nothing unless the
66
+ shadow attribute is set. Resolved here once so the focus rule below
67
+ can compose the real depth rather than assume one, and so a consumer
68
+ retheming --vf-shadow-offset still moves both together. */
69
+ --_shadow-depth: 0px;
70
+ }
71
+ :host([shadow]) {
72
+ --_shadow-depth: var(--vf-shadow-offset, 2px);
73
+ }
74
+ /* The 1px black frame, and — as the button's own background showing
75
+ through its 1px padding — the white inset ring around the fill. */
76
+ button {
77
+ display: block;
78
+ /* Also the anchor the focus rule below hangs from. */
79
+ position: relative;
80
+ padding: calc(var(--vf-scale, 1) * 1px);
81
+ margin: 0;
82
+ background: var(--vf-white, #fff);
83
+ border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
84
+ cursor: inherit;
85
+ -webkit-appearance: none;
86
+ appearance: none;
87
+ }
88
+ /* Opt-in depth: the kit's one hard shadow, painted outside the border
89
+ box like every raised surface's. */
90
+ :host([shadow]) button {
91
+ ${u}
92
+ }
93
+ /* Pressed: the white inset inverts to black — instant 1-bit feedback. */
94
+ button:active:not(:disabled) {
95
+ background: var(--vf-black, #000);
96
+ }
97
+ /* Keyboard focus is the kit's dashed rule under the swatch, not a ring
98
+ around it (see vfFocusUnderline). It goes BELOW the whole box rather
99
+ than inside it the way vf-button underlines its label: a swatch has no
100
+ interior to lend — every pixel inside the inset is the color it exists
101
+ to show, and a rule drawn over the fill would read as part of it.
102
+
103
+ The offset counts every row of ink below the pseudo-element's padding
104
+ box before the blank row and the rule itself — the 1px border, then
105
+ whatever shadow this swatch is casting — none by default, a rethemeable
106
+ token under the shadow attribute — so it composes --_shadow-depth
107
+ rather than assuming a depth. The ±1px sides widen the rule from that
108
+ same padding box to the border box, the shape the swatch reads as (the
109
+ shadow is a depth cue, not part of the silhouette). */
110
+ button:focus-visible {
111
+ outline: none;
112
+ }
113
+ button:focus-visible::after {
114
+ --vf-focus-underline-offset: calc(-3px - var(--_shadow-depth));
115
+ ${d}
116
+ left: calc(var(--vf-scale, 1) * -1px);
117
+ right: calc(var(--vf-scale, 1) * -1px);
118
+ }
119
+ .fill {
120
+ display: block;
121
+ /* The containing block for the exact fill and the tint. */
122
+ position: relative;
123
+ width: 100%;
124
+ height: 100%;
125
+ /* The CSS-repeated underlay, occluded by the (opaque) kit raster —
126
+ belt-and-braces paint only, like vf-desktop's. */
127
+ background-image: var(--_checker);
128
+ ${l(C)}
129
+ /* Forced colors would delete the color layer and keep the checker,
130
+ showing "transparent" for every color. The fill is CONTENT, not
131
+ chrome — the color is the one thing the control exists to show,
132
+ the case forced-color-adjust's own spec exempts (its example is a
133
+ color picker). It inherits to the raster, tiles and tint. Frame,
134
+ inset and press feedback stay on the forced palette like every
135
+ other control's. */
136
+ @media (forced-colors: active) {
137
+ forced-color-adjust: none;
138
+ }
139
+ }
140
+ /* A consumer checker token switches the fill to the placed tile grid;
141
+ the underlay must not paint beneath it — a translucent consumer tile
142
+ would show the underlay's drifting copy of itself. The grid's tiles
143
+ resolve the token through the shared private property. */
144
+ .fill.patterned {
145
+ background-image: none;
146
+ --_vf-tile-image: var(--_checker);
147
+ }
148
+ /* The color, painted over the checker so a translucent value reads as
149
+ partial — the same compositing the two-layer background used to do. */
150
+ .tint {
151
+ position: absolute;
152
+ inset: 0;
153
+ }
154
+ `
155
+ ];
156
+ }
157
+ #e;
158
+ willUpdate(e) {
159
+ super.willUpdate(e), this._pattern = p(this, "--vf-swatch-checker");
160
+ }
161
+ render() {
162
+ let e = Math.max(1, (this.width ?? 24) - 4), t = Math.max(1, (this.height ?? 18) - 4), r = (e) => Math.ceil((e + C) / C) * C, i = this._pattern ? m({
163
+ cols: Math.ceil(e / E),
164
+ rows: Math.ceil(t / E),
165
+ tile: E
166
+ }) : y`<span
167
+ class="vf-tile-raster"
168
+ style="width:${n(r(e))};height:${n(r(t))};background-image:${this.#e.for(C, C, w, r(e), r(t))}"
169
+ ></span>`, a = this.color ? y`<span
170
+ class="tint"
171
+ style=${S({ "background-color": this.color })}
172
+ ></span>` : null;
173
+ return y`
174
+ <button
175
+ part="button"
176
+ class="vf-snap"
177
+ type="button"
178
+ style="width: ${n(this.width)}; height: ${n(this.height)}"
179
+ aria-label=${this.label || this.hostLabel || this.color || "transparent"}
180
+ aria-describedby=${this.describedBy}
181
+ ?disabled=${this.isDisabled}
182
+ >
183
+ <span
184
+ class="fill vf-tile-grid${this._pattern ? " patterned" : ""}"
185
+ part="fill"
186
+ >${i}${a}</span
187
+ >
188
+ </button>
189
+ ${this.renderDescription()}
190
+ `;
191
+ }
192
+ };
193
+ r([x()], D.prototype, "color", void 0), r([x({ type: Number })], D.prototype, "width", void 0), r([x({ type: Number })], D.prototype, "height", void 0), r([x({
194
+ type: Boolean,
195
+ reflect: !0
196
+ })], D.prototype, "shadow", void 0), r([x()], D.prototype, "label", void 0), r([x({
197
+ type: Boolean,
198
+ reflect: !0
199
+ })], D.prototype, "disabled", void 0), D = r([e("vf-swatch")], D);
200
+ //#endregion
201
+ export { D as VfSwatch };
@@ -0,0 +1,77 @@
1
+ import { VfTextControlBase } from '../text-control.js';
2
+ declare const VfTextArea_base: (new (...args: any[]) => import("../position.js").VfPositionedInterface) & typeof VfTextControlBase;
3
+ /**
4
+ * `<vf-text-area>` — a System 7 multi-line text entry field.
5
+ *
6
+ * Identical styling to `<vf-text-field>` but wrapping a native `<textarea>`.
7
+ * No resize grip (`resize: none`) — System 7 fields don't resize. Wrapped
8
+ * text sits on Chicago 12's native 16px line (the single-line well keeps its
9
+ * 20px box — that is control geometry, not typesetting). The shared field
10
+ * skin lives in `vfField`; the value/form scaffolding in
11
+ * {@link VfTextControlBase}.
12
+ *
13
+ * The `.vf-field-well` wrapper is the one `vfField` hangs the focus rule from,
14
+ * doing double duty here: it is the field's framed box — it carries the 1px
15
+ * frame the single-line field draws on the well itself, and lays the drawn
16
+ * scroll rail beside the borderless inner `<textarea>` — and the `vf-snap`
17
+ * element whose grid-snap offset the field, the frame and the rule ride as
18
+ * one.
19
+ *
20
+ * The vertical scroll rail is a permanent System 7 placeholder: arrows on an
21
+ * empty white channel sit in the field even when the text fits, the dither
22
+ * and thumb filling in only once the content overflows (driven by
23
+ * {@link ScrollStateController}). The rail is the shared `vfScrollRail`
24
+ * subtree — the kit-drawn rail every scroll surface wears — synced to the
25
+ * textarea's own native scrolling by {@link ScrollRailController}; the native
26
+ * bar itself is hidden.
27
+ *
28
+ * @fires vf-input - On every keystroke. `detail: { value: string }`.
29
+ * @fires vf-change - On commit (native `change`). `detail: { value: string }`.
30
+ * @fires input - The native keystroke event: the inner textarea's own,
31
+ * composed, so it crosses the shadow boundary and retargets to the host.
32
+ * @fires change - The native commit event, re-dispatched from the host (the
33
+ * inner one is `composed: false` and never leaves the shadow root).
34
+ *
35
+ * The input-behavior attributes — `autocomplete`, `inputmode`, `enterkeyhint`,
36
+ * `maxlength`, `spellcheck`, `autocapitalize` — are forwarded from the host
37
+ * onto the inner textarea, where the platform actually honors them
38
+ * (`pattern` is not: only an `<input>` takes it).
39
+ *
40
+ * @csspart textarea - The inner native `<textarea>` element.
41
+ * @cssprop --vf-line-height-display - The display face's native line (default
42
+ * `16px`, Chicago 12's) — the pitch wrapped entry text sits on, shared with
43
+ * the static-text components so a display retheme moves them together.
44
+ * @cssprop [--vf-field-width=180px] - default width of `vf-text-field` /
45
+ * `vf-text-area`
46
+ * @cssprop [--vf-field-placeholder=#767676] - placeholder text in the editable
47
+ * fields — kept off `--vf-disabled`: a placeholder sits in an *enabled* well
48
+ * and holds AA contrast, where the disabled gray is exempt
49
+ * @cssprop --vf-scrollbar-thumb - scrollbar thumb/elevator (white)
50
+ * @cssprop --vf-scrollbar-track - the scroll trough's base color under the
51
+ * dot-dither (white)
52
+ */
53
+ export declare class VfTextArea extends VfTextArea_base {
54
+ static styles: import("lit").CSSResult[];
55
+ /** Number of visible text rows (native `rows`). Default 4. */
56
+ rows: number;
57
+ private textarea;
58
+ /** Reserves the vertical rail and toggles it active on overflow. */
59
+ private readonly scrollState;
60
+ /** Syncs the drawn rail to the textarea and drives its interactions. */
61
+ private readonly rail;
62
+ protected render(): import("lit-html").TemplateResult<1>;
63
+ /**
64
+ * Re-measure overflow on each keystroke. A `<textarea>`'s scrollHeight grows
65
+ * as the text wraps without resizing the element's box, so the controllers'
66
+ * ResizeObservers never fire — this is the imperative path both document
67
+ * (the state controller keeps the rail's active state honest, the rail
68
+ * controller its thumb).
69
+ */
70
+ protected handleInput(event: Event): void;
71
+ }
72
+ declare global {
73
+ interface HTMLElementTagNameMap {
74
+ 'vf-text-area': VfTextArea;
75
+ }
76
+ }
77
+ export {};
@@ -0,0 +1,121 @@
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 { vfBase as r } from "../styles/recipes/host.js";
5
+ import { vfField as i } from "../styles/recipes/field.js";
6
+ import { vfScrollRail as a } from "../styles/recipes/scroll-rail.js";
7
+ import { ScrollStateController as o } from "../scroll-state.js";
8
+ import { ScrollRailController as s, renderScrollRail as c } from "../scroll-rail.js";
9
+ import { VfTextControlBase as l } from "../text-control.js";
10
+ import { css as u, html as d, nothing as f } from "lit";
11
+ import { property as p, query as m } from "lit/decorators.js";
12
+ import { live as h } from "lit/directives/live.js";
13
+ //#region src/components/vf-text-area.ts
14
+ var g = class extends n(l) {
15
+ constructor(...e) {
16
+ super(...e), this.rows = 4, this.scrollState = new o(this, () => this.textarea), this.rail = new s(this, { getScroll: () => this.textarea });
17
+ }
18
+ static {
19
+ this.styles = [
20
+ r,
21
+ i,
22
+ a,
23
+ u`
24
+ :host {
25
+ display: inline-block;
26
+ /* A sensible default width (authored system px, scaled) so a bare field
27
+ doesn't collapse; the inner control fills it. Override with a width
28
+ on the host or the --vf-field-width token. */
29
+ width: calc(var(--vf-scale, 1) * var(--vf-field-width, 180px));
30
+ }
31
+ /* The well is the field's framed box: it carries the 1px frame (the
32
+ single-line field draws it on the input itself, but here the drawn
33
+ scroll rail has to sit inside the frame beside the text), and lays
34
+ out [textarea | rail] — the rail sizes itself to the 15px inside the
35
+ frame. */
36
+ .vf-field-well {
37
+ border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
38
+ background: var(--vf-white, #fff);
39
+ display: grid;
40
+ grid-template-columns: 1fr auto;
41
+ }
42
+ /* The focus rule anchors to the well's PADDING box, and this well —
43
+ unlike the single-line field's borderless wrapper — carries the 1px
44
+ frame: −3 is the documented bordered-carrier offset (see
45
+ vfFocusUnderline), keeping the rule one blank row under the frame,
46
+ and the −1px insets span it across the border box edge to edge. */
47
+ .vf-field-well.vf-focus-rule::after {
48
+ --vf-focus-underline-offset: -3px;
49
+ left: calc(var(--vf-scale, 1) * -1px);
50
+ right: calc(var(--vf-scale, 1) * -1px);
51
+ }
52
+ /* textarea.vf-field so the border override out-ranks the vf-field skin's
53
+ own border (a bare element selector would lose to the class). */
54
+ textarea.vf-field {
55
+ display: block;
56
+ width: 100%;
57
+ min-width: 0;
58
+ /* Borderless — the frame is the well's (above). vf-text-field's own
59
+ 3px/6px padding plus that border holds the text exactly where the
60
+ bordered field puts it; the mod() term is border-floor
61
+ compensation (engines floor the fractional border to whole CSS px;
62
+ this is exactly what they floored away), keeping the text on the
63
+ 4px/7px system-px inset from the frame box at every scale. */
64
+ border: 0;
65
+ padding: calc(
66
+ var(--vf-scale, 1) * 3px + mod(var(--vf-scale, 1) * 1px, 1px)
67
+ )
68
+ calc(var(--vf-scale, 1) * 6px + mod(var(--vf-scale, 1) * 1px, 1px));
69
+ /* Wrapped entry copy on the display face's native line (editable
70
+ text is display type) — the same face token the static-text
71
+ components read, so a display retheme moves this well too. The
72
+ vfField skin inherits the host's 1.25 ratio (a 20px box — what
73
+ vf-text-field's 22px well is built on and keeps); a multi-line
74
+ well is typesetting, and takes the strike's own pitch: rows buys
75
+ one line each. */
76
+ line-height: calc(var(--vf-scale, 1) * var(--vf-line-height-display, 16px));
77
+ resize: none;
78
+ /* Native scrolling; the bar itself is hidden by the recipe
79
+ (.vf-scroll) and the reservation is the rail element beside the
80
+ text. */
81
+ overflow-y: auto;
82
+ }
83
+ `
84
+ ];
85
+ }
86
+ render() {
87
+ return d`
88
+ <div class=${this.wellClass}>
89
+ <textarea
90
+ part="textarea"
91
+ class="vf-field vf-scroll"
92
+ rows=${this.rows}
93
+ aria-label=${this.label || this.hostLabel || f}
94
+ aria-describedby=${this.describedBy}
95
+ aria-required=${this.required ? "true" : f}
96
+ aria-invalid=${this.validity.valid ? f : "true"}
97
+ autocomplete=${this.forwardedAttr("autocomplete")}
98
+ inputmode=${this.forwardedAttr("inputmode")}
99
+ enterkeyhint=${this.forwardedAttr("enterkeyhint")}
100
+ maxlength=${this.forwardedAttr("maxlength")}
101
+ spellcheck=${this.forwardedAttr("spellcheck")}
102
+ autocapitalize=${this.forwardedAttr("autocapitalize")}
103
+ .value=${h(this.value)}
104
+ placeholder=${this.placeholder}
105
+ ?disabled=${this.isDisabled}
106
+ ?readonly=${this.readonly}
107
+ @input=${this.handleInput}
108
+ @change=${this.handleChange}
109
+ ></textarea>
110
+ ${c(this.rail, "vertical")}
111
+ </div>
112
+ ${this.renderDescription()}
113
+ `;
114
+ }
115
+ handleInput(e) {
116
+ super.handleInput(e), this.scrollState.measure(), this.rail.sync();
117
+ }
118
+ };
119
+ t([p({ type: Number })], g.prototype, "rows", void 0), t([m("textarea")], g.prototype, "textarea", void 0), g = t([e("vf-text-area")], g);
120
+ //#endregion
121
+ export { g as VfTextArea };