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.
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/custom-elements.json +19807 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js +9 -0
- package/dist/chrome.d.ts +73 -0
- package/dist/chrome.js +94 -0
- package/dist/components/vf-button-group.d.ts +50 -0
- package/dist/components/vf-button-group.js +68 -0
- package/dist/components/vf-button.d.ts +169 -0
- package/dist/components/vf-button.js +234 -0
- package/dist/components/vf-checkbox.d.ts +60 -0
- package/dist/components/vf-checkbox.js +135 -0
- package/dist/components/vf-container.d.ts +95 -0
- package/dist/components/vf-container.js +86 -0
- package/dist/components/vf-desktop.d.ts +243 -0
- package/dist/components/vf-desktop.js +310 -0
- package/dist/components/vf-dialog.d.ts +105 -0
- package/dist/components/vf-dialog.js +280 -0
- package/dist/components/vf-fieldset.d.ts +34 -0
- package/dist/components/vf-fieldset.js +76 -0
- package/dist/components/vf-grid.d.ts +124 -0
- package/dist/components/vf-grid.js +133 -0
- package/dist/components/vf-icon.d.ts +356 -0
- package/dist/components/vf-icon.js +507 -0
- package/dist/components/vf-img.d.ts +63 -0
- package/dist/components/vf-img.js +65 -0
- package/dist/components/vf-label.d.ts +117 -0
- package/dist/components/vf-label.js +151 -0
- package/dist/components/vf-list-item.d.ts +48 -0
- package/dist/components/vf-list-item.js +98 -0
- package/dist/components/vf-list.d.ts +77 -0
- package/dist/components/vf-list.js +256 -0
- package/dist/components/vf-menu-bar.d.ts +64 -0
- package/dist/components/vf-menu-bar.js +236 -0
- package/dist/components/vf-menu-item.d.ts +91 -0
- package/dist/components/vf-menu-item.js +252 -0
- package/dist/components/vf-menu.d.ts +95 -0
- package/dist/components/vf-menu.js +346 -0
- package/dist/components/vf-number-field.d.ts +60 -0
- package/dist/components/vf-number-field.js +248 -0
- package/dist/components/vf-option.d.ts +49 -0
- package/dist/components/vf-option.js +119 -0
- package/dist/components/vf-paragraph.d.ts +73 -0
- package/dist/components/vf-paragraph.js +66 -0
- package/dist/components/vf-progress-bar.d.ts +69 -0
- package/dist/components/vf-progress-bar.js +272 -0
- package/dist/components/vf-radio-group.d.ts +109 -0
- package/dist/components/vf-radio-group.js +105 -0
- package/dist/components/vf-radio.d.ts +59 -0
- package/dist/components/vf-radio.js +135 -0
- package/dist/components/vf-scroll-area.d.ts +75 -0
- package/dist/components/vf-scroll-area.js +124 -0
- package/dist/components/vf-select.d.ts +334 -0
- package/dist/components/vf-select.js +658 -0
- package/dist/components/vf-separator.d.ts +38 -0
- package/dist/components/vf-separator.js +55 -0
- package/dist/components/vf-slider.d.ts +80 -0
- package/dist/components/vf-slider.js +255 -0
- package/dist/components/vf-stack.d.ts +188 -0
- package/dist/components/vf-stack.js +168 -0
- package/dist/components/vf-swatch.d.ts +98 -0
- package/dist/components/vf-swatch.js +201 -0
- package/dist/components/vf-text-area.d.ts +77 -0
- package/dist/components/vf-text-area.js +121 -0
- package/dist/components/vf-text-field.d.ts +53 -0
- package/dist/components/vf-text-field.js +79 -0
- package/dist/components/vf-window.d.ts +157 -0
- package/dist/components/vf-window.js +377 -0
- package/dist/cursor-art.d.ts +37 -0
- package/dist/cursor-art.js +41 -0
- package/dist/cursor.d.ts +49 -0
- package/dist/cursor.js +171 -0
- package/dist/define.d.ts +45 -0
- package/dist/define.js +15 -0
- package/dist/document-listeners.d.ts +62 -0
- package/dist/document-listeners.js +29 -0
- package/dist/drag.d.ts +49 -0
- package/dist/drag.js +30 -0
- package/dist/events.d.ts +79 -0
- package/dist/events.js +25 -0
- package/dist/focus-modality.d.ts +94 -0
- package/dist/focus-modality.js +56 -0
- package/dist/form-control.d.ts +247 -0
- package/dist/form-control.js +127 -0
- package/dist/glyphs.d.ts +117 -0
- package/dist/glyphs.js +100 -0
- package/dist/grid-snap.d.ts +73 -0
- package/dist/grid-snap.js +135 -0
- package/dist/index.d.ts +145 -0
- package/dist/index.js +71 -0
- package/dist/menu-press.d.ts +60 -0
- package/dist/menu-press.js +97 -0
- package/dist/modal-dialog.d.ts +148 -0
- package/dist/modal-dialog.js +155 -0
- package/dist/motion.d.ts +72 -0
- package/dist/motion.js +22 -0
- package/dist/number.d.ts +24 -0
- package/dist/number.js +12 -0
- package/dist/open-art.d.ts +40 -0
- package/dist/open-art.js +35 -0
- package/dist/pixel-frame.d.ts +102 -0
- package/dist/pixel-frame.js +77 -0
- package/dist/popup-overflow.d.ts +157 -0
- package/dist/popup-overflow.js +45 -0
- package/dist/position.d.ts +187 -0
- package/dist/position.js +74 -0
- package/dist/scale.d.ts +259 -0
- package/dist/scale.js +133 -0
- package/dist/scroll-rail.d.ts +112 -0
- package/dist/scroll-rail.js +194 -0
- package/dist/scroll-state.d.ts +113 -0
- package/dist/scroll-state.js +55 -0
- package/dist/size.d.ts +47 -0
- package/dist/size.js +30 -0
- package/dist/styles/base.d.ts +38 -0
- package/dist/styles/body-font.d.ts +7 -0
- package/dist/styles/body-font.js +9 -0
- package/dist/styles/display-font.d.ts +7 -0
- package/dist/styles/display-font.js +9 -0
- package/dist/styles/recipes/body-face.d.ts +14 -0
- package/dist/styles/recipes/body-face.js +6 -0
- package/dist/styles/recipes/display-face.d.ts +23 -0
- package/dist/styles/recipes/display-face.js +10 -0
- package/dist/styles/recipes/field.d.ts +20 -0
- package/dist/styles/recipes/field.js +68 -0
- package/dist/styles/recipes/focus.d.ts +76 -0
- package/dist/styles/recipes/focus.js +39 -0
- package/dist/styles/recipes/host.d.ts +5 -0
- package/dist/styles/recipes/host.js +62 -0
- package/dist/styles/recipes/pattern.d.ts +80 -0
- package/dist/styles/recipes/pattern.js +82 -0
- package/dist/styles/recipes/scroll-rail.d.ts +69 -0
- package/dist/styles/recipes/scroll-rail.js +222 -0
- package/dist/styles/recipes/shadow.d.ts +13 -0
- package/dist/styles/recipes/shadow.js +5 -0
- package/dist/styles/recipes/static-text.d.ts +24 -0
- package/dist/styles/recipes/static-text.js +17 -0
- package/dist/styles/recipes/surface.d.ts +28 -0
- package/dist/styles/recipes/surface.js +27 -0
- package/dist/styles/recipes/tile.d.ts +122 -0
- package/dist/styles/recipes/tile.js +40 -0
- package/dist/styles/recipes/title-bar.d.ts +49 -0
- package/dist/styles/recipes/title-bar.js +134 -0
- package/dist/styles/recipes/toggle.d.ts +10 -0
- package/dist/styles/recipes/toggle.js +20 -0
- package/dist/styles/register-embedded-font.d.ts +64 -0
- package/dist/styles/register-embedded-font.js +30 -0
- package/dist/text-control.d.ts +131 -0
- package/dist/text-control.js +83 -0
- package/dist/tile-grid.d.ts +111 -0
- package/dist/tile-grid.js +53 -0
- package/dist/toggle-control.d.ts +60 -0
- package/dist/toggle-control.js +41 -0
- package/dist/track-width.d.ts +42 -0
- package/dist/track-width.js +30 -0
- package/dist/type-ahead.d.ts +35 -0
- package/dist/type-ahead.js +20 -0
- package/dist/zoom.d.ts +204 -0
- package/dist/zoom.js +105 -0
- package/docs/SPEC.md +2471 -0
- package/editor/vscode.html-custom-data.json +1320 -0
- package/editor/web-types.json +3237 -0
- package/package.json +118 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { effectiveScale as e, sysLength as t } from "./scale.js";
|
|
2
|
+
import { TROUGH_RECTS as n } from "./styles/recipes/scroll-rail.js";
|
|
3
|
+
import { TileRasterCache as r } from "./tile-grid.js";
|
|
4
|
+
import "./motion.js";
|
|
5
|
+
import { SCROLL_ARROW_DOWN as i, SCROLL_ARROW_DOWN_FILL as a, SCROLL_ARROW_LEFT as o, SCROLL_ARROW_LEFT_FILL as s, SCROLL_ARROW_RIGHT as c, SCROLL_ARROW_RIGHT_FILL as l, SCROLL_ARROW_UP as u, SCROLL_ARROW_UP_FILL as d } from "./glyphs.js";
|
|
6
|
+
import { html as f } from "lit";
|
|
7
|
+
//#region src/scroll-rail.ts
|
|
8
|
+
var p = 16, m = 16, h = 14, g = 66, _ = class {
|
|
9
|
+
constructor(t, n) {
|
|
10
|
+
this.host = t, this.opts = n, this.scroller = null, this.press = null, this.troughCache = {
|
|
11
|
+
vertical: new r(),
|
|
12
|
+
horizontal: new r()
|
|
13
|
+
}, this.onScroll = () => this.sync(), this.onPointerDown = (t) => {
|
|
14
|
+
if (t.button !== 0 || this.press !== null) return;
|
|
15
|
+
let n = t.currentTarget, r = this.opts.getScroll();
|
|
16
|
+
if (!r) return;
|
|
17
|
+
let i = v(n), a = i === "vertical" ? "data-overflow-y" : "data-overflow-x";
|
|
18
|
+
if (r.getAttribute(a) === "false" || r.hasAttribute("data-window-inactive") || n.getAttribute("data-degenerate") === "rail") return;
|
|
19
|
+
let o = t.target, s = i === "vertical" ? t.clientY : t.clientX, c = e(this.host) || 1, l = o.closest(".vf-rail-thumb"), u = o.closest(".vf-rail-button--decrement"), d = o.closest(".vf-rail-button--increment");
|
|
20
|
+
if (l) {
|
|
21
|
+
let e = n.querySelector(".vf-rail-track");
|
|
22
|
+
if (!e) return;
|
|
23
|
+
let a = e.getBoundingClientRect(), o = i === "vertical" ? a.height : a.width;
|
|
24
|
+
this.press = {
|
|
25
|
+
pointerId: t.pointerId,
|
|
26
|
+
kind: "thumb",
|
|
27
|
+
axis: i,
|
|
28
|
+
rail: n,
|
|
29
|
+
dir: 1,
|
|
30
|
+
button: null,
|
|
31
|
+
startCoord: s,
|
|
32
|
+
startScroll: i === "vertical" ? r.scrollTop : r.scrollLeft,
|
|
33
|
+
travelCss: o - m * c,
|
|
34
|
+
lastCoord: s
|
|
35
|
+
};
|
|
36
|
+
} else if (u || d) {
|
|
37
|
+
let e = u ?? d, r = u ? -1 : 1;
|
|
38
|
+
e.setAttribute("data-pressed", ""), this.press = {
|
|
39
|
+
pointerId: t.pointerId,
|
|
40
|
+
kind: "step",
|
|
41
|
+
axis: i,
|
|
42
|
+
rail: n,
|
|
43
|
+
dir: r,
|
|
44
|
+
button: e,
|
|
45
|
+
startCoord: s,
|
|
46
|
+
startScroll: 0,
|
|
47
|
+
travelCss: 0,
|
|
48
|
+
lastCoord: s
|
|
49
|
+
}, this.stepBy(r, i), this.armRepeat(() => this.stepBy(r, i));
|
|
50
|
+
} else if (o.closest(".vf-rail-track")) {
|
|
51
|
+
let e = n.querySelector(".vf-rail-thumb")?.getBoundingClientRect(), r = s < ((e && (i === "vertical" ? e.top : e.left)) ?? s) ? -1 : 1;
|
|
52
|
+
this.press = {
|
|
53
|
+
pointerId: t.pointerId,
|
|
54
|
+
kind: "page",
|
|
55
|
+
axis: i,
|
|
56
|
+
rail: n,
|
|
57
|
+
dir: r,
|
|
58
|
+
button: null,
|
|
59
|
+
startCoord: s,
|
|
60
|
+
startScroll: 0,
|
|
61
|
+
travelCss: 0,
|
|
62
|
+
lastCoord: s
|
|
63
|
+
}, this.pageBy(r, i), this.armRepeat(() => this.pageTowardPointer());
|
|
64
|
+
} else return;
|
|
65
|
+
n.setPointerCapture(t.pointerId), t.preventDefault();
|
|
66
|
+
}, this.onPointerMove = (e) => {
|
|
67
|
+
let t = this.press;
|
|
68
|
+
if (!t || e.pointerId !== t.pointerId || (t.lastCoord = t.axis === "vertical" ? e.clientY : e.clientX, t.kind !== "thumb")) return;
|
|
69
|
+
let n = this.opts.getScroll();
|
|
70
|
+
if (!n || t.travelCss <= 0) return;
|
|
71
|
+
let r = this.scrollRange(n, t.axis);
|
|
72
|
+
if (r <= 0) return;
|
|
73
|
+
let i = t.startScroll + (t.lastCoord - t.startCoord) / t.travelCss * r;
|
|
74
|
+
t.axis === "vertical" ? n.scrollTop = i : n.scrollLeft = i;
|
|
75
|
+
}, this.onPointerUp = (e) => {
|
|
76
|
+
let t = this.press;
|
|
77
|
+
!t || e.pointerId !== t.pointerId || (this.press = null, this.clearRepeat(), t.button?.removeAttribute("data-pressed"), t.rail.hasPointerCapture(e.pointerId) && t.rail.releasePointerCapture(e.pointerId));
|
|
78
|
+
}, t.addController(this);
|
|
79
|
+
}
|
|
80
|
+
hostUpdated() {
|
|
81
|
+
this.wire(), this.sync();
|
|
82
|
+
}
|
|
83
|
+
hostDisconnected() {
|
|
84
|
+
this.clearRepeat(), this.press = null, this.unwire();
|
|
85
|
+
}
|
|
86
|
+
wire() {
|
|
87
|
+
let e = this.opts.getScroll() ?? null;
|
|
88
|
+
if (e !== this.scroller && (this.unwire(), this.scroller = e, e && (e.addEventListener("scroll", this.onScroll, { passive: !0 }), typeof ResizeObserver < "u"))) {
|
|
89
|
+
this.resizeObserver = new ResizeObserver(() => this.sync()), this.resizeObserver.observe(e);
|
|
90
|
+
let t = this.opts.getContent?.();
|
|
91
|
+
t && this.resizeObserver.observe(t);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
unwire() {
|
|
95
|
+
this.scroller?.removeEventListener("scroll", this.onScroll), this.scroller = null, this.resizeObserver?.disconnect(), this.resizeObserver = void 0;
|
|
96
|
+
}
|
|
97
|
+
sync() {
|
|
98
|
+
let e = this.scroller ?? this.opts.getScroll(), t = this.host.renderRoot;
|
|
99
|
+
if (!(!e || !t)) for (let n of t.querySelectorAll(".vf-rail")) this.syncRail(n, e);
|
|
100
|
+
}
|
|
101
|
+
syncRail(r, i) {
|
|
102
|
+
let a = v(r), o = r.querySelector(".vf-rail-track"), s = r.querySelector(".vf-rail-thumb");
|
|
103
|
+
if (!o || !s) return;
|
|
104
|
+
let c = e(this.host) || 1, l = o.getBoundingClientRect(), u = (a === "vertical" ? l.height : l.width) / c, d = u < 1 ? "rail" : u < m ? "thumb" : null;
|
|
105
|
+
if (d ? r.setAttribute("data-degenerate", d) : r.removeAttribute("data-degenerate"), d === "rail") return;
|
|
106
|
+
let f = this.scrollRange(i, a), p = a === "vertical" ? i.scrollTop : i.scrollLeft, g = u - m, _ = f > 0 && g > 0 ? Math.max(0, Math.min(Math.floor(g), Math.round(p / f * g))) : 0;
|
|
107
|
+
s.style.translate = a === "vertical" ? `0 ${t(_)}` : `${t(_)} 0`;
|
|
108
|
+
let y = r.querySelector(".vf-rail-trough-art");
|
|
109
|
+
if (y) {
|
|
110
|
+
let e = Math.ceil((u + (a === "vertical" ? 2 : 4)) / (a === "vertical" ? 2 : 4)) * (a === "vertical" ? 2 : 4), r = a === "vertical" ? h : e, i = a === "vertical" ? e : h;
|
|
111
|
+
y.style.width = t(r), y.style.height = t(i), y.style.backgroundImage = this.troughCache[a].for(4, 2, n, r, i);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
scrollRange(e, t) {
|
|
115
|
+
return t === "vertical" ? e.scrollHeight - e.clientHeight : e.scrollWidth - e.clientWidth;
|
|
116
|
+
}
|
|
117
|
+
stepBy(t, n) {
|
|
118
|
+
let r = this.opts.getScroll();
|
|
119
|
+
if (!r) return;
|
|
120
|
+
let i = t * p * (e(this.host) || 1);
|
|
121
|
+
n === "vertical" ? r.scrollTop += i : r.scrollLeft += i;
|
|
122
|
+
}
|
|
123
|
+
pageBy(t, n) {
|
|
124
|
+
let r = this.opts.getScroll();
|
|
125
|
+
if (!r) return;
|
|
126
|
+
let i = p * (e(this.host) || 1), a = n === "vertical" ? r.clientHeight : r.clientWidth, o = Math.max(i, a - i);
|
|
127
|
+
n === "vertical" ? r.scrollTop += t * o : r.scrollLeft += t * o;
|
|
128
|
+
}
|
|
129
|
+
pageTowardPointer() {
|
|
130
|
+
let e = this.press;
|
|
131
|
+
if (!e || e.kind !== "page") return;
|
|
132
|
+
let t = e.rail.querySelector(".vf-rail-thumb");
|
|
133
|
+
if (t) {
|
|
134
|
+
let n = t.getBoundingClientRect(), r = e.axis === "vertical" ? n.top : n.left, i = e.axis === "vertical" ? n.bottom : n.right;
|
|
135
|
+
if (e.dir > 0 ? i > e.lastCoord : r < e.lastCoord) return;
|
|
136
|
+
}
|
|
137
|
+
this.pageBy(e.dir, e.axis);
|
|
138
|
+
}
|
|
139
|
+
armRepeat(e) {
|
|
140
|
+
this.clearRepeat(), this.holdTimer = window.setTimeout(() => {
|
|
141
|
+
this.repeatTimer = window.setInterval(e, g);
|
|
142
|
+
}, 200);
|
|
143
|
+
}
|
|
144
|
+
clearRepeat() {
|
|
145
|
+
this.holdTimer !== void 0 && window.clearTimeout(this.holdTimer), this.repeatTimer !== void 0 && window.clearInterval(this.repeatTimer), this.holdTimer = void 0, this.repeatTimer = void 0;
|
|
146
|
+
}
|
|
147
|
+
}, v = (e) => e.classList.contains("vf-rail--horizontal") ? "horizontal" : "vertical", y = (e, t) => f`<svg
|
|
148
|
+
class="vf-rail-arrow vf-rail-arrow--${t}"
|
|
149
|
+
viewBox="1 1 14 14"
|
|
150
|
+
fill="currentColor"
|
|
151
|
+
shape-rendering="crispEdges"
|
|
152
|
+
aria-hidden="true"
|
|
153
|
+
>
|
|
154
|
+
<path d=${e.d}></path>
|
|
155
|
+
</svg>`;
|
|
156
|
+
function b(e, t) {
|
|
157
|
+
let [n, r, p, m] = t === "vertical" ? [
|
|
158
|
+
u,
|
|
159
|
+
d,
|
|
160
|
+
i,
|
|
161
|
+
a
|
|
162
|
+
] : [
|
|
163
|
+
o,
|
|
164
|
+
s,
|
|
165
|
+
c,
|
|
166
|
+
l
|
|
167
|
+
];
|
|
168
|
+
return f`
|
|
169
|
+
<div
|
|
170
|
+
class="vf-rail vf-rail--${t}"
|
|
171
|
+
aria-hidden="true"
|
|
172
|
+
@pointerdown=${e.onPointerDown}
|
|
173
|
+
@pointermove=${e.onPointerMove}
|
|
174
|
+
@pointerup=${e.onPointerUp}
|
|
175
|
+
@pointercancel=${e.onPointerUp}
|
|
176
|
+
@lostpointercapture=${e.onPointerUp}
|
|
177
|
+
>
|
|
178
|
+
<div class="vf-rail-button vf-rail-button--decrement">
|
|
179
|
+
${y(n, "rest")}${y(r, "fill")}
|
|
180
|
+
</div>
|
|
181
|
+
<div class="vf-rail-track">
|
|
182
|
+
<div class="vf-rail-trough">
|
|
183
|
+
<div class="vf-rail-trough-art"></div>
|
|
184
|
+
</div>
|
|
185
|
+
<div class="vf-rail-thumb"></div>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="vf-rail-button vf-rail-button--increment">
|
|
188
|
+
${y(p, "rest")}${y(m, "fill")}
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
`;
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
export { _ as ScrollRailController, b as renderScrollRail };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Rail-state tracking for System 7 "always-a-rail" scrollbars.
|
|
4
|
+
*
|
|
5
|
+
* System 7 draws a scrollable frame's scroll bar as a permanent part of its
|
|
6
|
+
* chrome: an empty white rail sits in the reserved channel even when there is
|
|
7
|
+
* nothing to scroll, and it only fills in — dither track, draggable thumb,
|
|
8
|
+
* arrow buttons — once the content actually overflows. Native `overflow` can't
|
|
9
|
+
* express that: `auto` is all-or-nothing (no rail when it fits) and `scroll`
|
|
10
|
+
* shows the whole bar always (arrows + a full-height thumb even when it fits),
|
|
11
|
+
* and there is no CSS selector for "is this element overflowing".
|
|
12
|
+
*
|
|
13
|
+
* This controller supplies the missing signal. It measures scroll vs. client
|
|
14
|
+
* size on both axes and writes `data-overflow-x` / `data-overflow-y`
|
|
15
|
+
* (`"true"` | `"false"`) onto the scroll element. The shared `vfScrollRail`
|
|
16
|
+
* recipe keys the drawn rail's dither, thumb and arrows off those attributes,
|
|
17
|
+
* so a rail is a bare white channel at `"false"` and the full System 7
|
|
18
|
+
* scrollbar at `"true"`.
|
|
19
|
+
*
|
|
20
|
+
* It also supplies the HIG's inactive-window treatment: a window that isn't
|
|
21
|
+
* frontmost must not display interactive scroll UX, so System 7 blanked a
|
|
22
|
+
* deactivated window's scrollbars back to the empty rail (and its List
|
|
23
|
+
* Manager/TextEdit did the same for scrollbars *inside* the window). The
|
|
24
|
+
* controller finds the nearest `vf-window` up the composed tree, watches its
|
|
25
|
+
* reflected `active` attribute, and toggles `data-window-inactive`
|
|
26
|
+
* (presence-only) on the scroll element; the recipe empties the
|
|
27
|
+
* dither/thumb/arrows while it is present, regardless of overflow. A scroller
|
|
28
|
+
* with no `vf-window` ancestor never carries the attribute — `vf-dialog` has
|
|
29
|
+
* no inactive state, and a bare scroll component on a page always draws live.
|
|
30
|
+
*
|
|
31
|
+
* The controller reports BOTH axes always; each component decides which rails
|
|
32
|
+
* it *reserves* by which rail elements it renders (`renderScrollRail`,
|
|
33
|
+
* src/scroll-rail.ts). An unreserved axis still scrolls natively but draws no
|
|
34
|
+
* rail, so the idle rules never touch it. The attributes exist only on
|
|
35
|
+
* managed elements, so a plain `.vf-scroll` used without a controller is
|
|
36
|
+
* untouched.
|
|
37
|
+
*
|
|
38
|
+
* Re-measures on every signal that can change overflow: the viewport resizing
|
|
39
|
+
* (host size, `--vf-scale`), the content resizing (a passed content element —
|
|
40
|
+
* slotted rows growing, media or late bitmap-font load), the host re-rendering,
|
|
41
|
+
* and an imperative {@link measure} (a `<textarea>`'s own scrollHeight changes
|
|
42
|
+
* on input without any box resizing).
|
|
43
|
+
*
|
|
44
|
+
* FUTURE: once `@container scroll-state(scrollable)` container queries reach
|
|
45
|
+
* baseline support, slotted-content components could drop this JS and gate the
|
|
46
|
+
* same recipe rules with a pure-CSS `@container` query instead (a native
|
|
47
|
+
* `<textarea>` changing scrollHeight on input would still need the imperative
|
|
48
|
+
* path). The window-activity half has the same trajectory via `@container
|
|
49
|
+
* style()` queries: vf-window cascades a custom property under
|
|
50
|
+
* `:host(:not([active]))` and the recipe gates on
|
|
51
|
+
* `style(--vf-window-active: false)`, retiring {@link observeWindow}'s
|
|
52
|
+
* MutationObserver and composed-tree walk. The rails being ordinary DOM,
|
|
53
|
+
* either migration is a plain selector swap — the old scrollbar-pseudo
|
|
54
|
+
* re-resolution caveat retired with `::-webkit-scrollbar`.
|
|
55
|
+
*/
|
|
56
|
+
export declare class ScrollStateController implements ReactiveController {
|
|
57
|
+
private readonly host;
|
|
58
|
+
private readonly getScroll;
|
|
59
|
+
private readonly getContent?;
|
|
60
|
+
/**
|
|
61
|
+
* Invoked whenever the measured overflow state changes (including the
|
|
62
|
+
* first measurement), with the per-axis result. Components that gate
|
|
63
|
+
* *rendered* state on scrollability — vf-scroll-area's conditional tab
|
|
64
|
+
* stop — hang a reactive property off this; the data attributes alone
|
|
65
|
+
* are written outside Lit's render and would never re-render the host.
|
|
66
|
+
*/
|
|
67
|
+
private readonly onOverflowChange?;
|
|
68
|
+
private resizeObserver?;
|
|
69
|
+
private windowObserver?;
|
|
70
|
+
private vfWindow;
|
|
71
|
+
private wired;
|
|
72
|
+
constructor(host: ReactiveControllerHost & HTMLElement, getScroll: () => HTMLElement | null | undefined, getContent?: (() => Element | null | undefined) | undefined,
|
|
73
|
+
/**
|
|
74
|
+
* Invoked whenever the measured overflow state changes (including the
|
|
75
|
+
* first measurement), with the per-axis result. Components that gate
|
|
76
|
+
* *rendered* state on scrollability — vf-scroll-area's conditional tab
|
|
77
|
+
* stop — hang a reactive property off this; the data attributes alone
|
|
78
|
+
* are written outside Lit's render and would never re-render the host.
|
|
79
|
+
*/
|
|
80
|
+
onOverflowChange?: ((overflow: {
|
|
81
|
+
x: boolean;
|
|
82
|
+
y: boolean;
|
|
83
|
+
}) => void) | undefined);
|
|
84
|
+
hostConnected(): void;
|
|
85
|
+
hostUpdated(): void;
|
|
86
|
+
hostDisconnected(): void;
|
|
87
|
+
/** (Re-)attach the ResizeObserver to the viewport and content boxes. */
|
|
88
|
+
private wire;
|
|
89
|
+
/**
|
|
90
|
+
* Find the containing `vf-window` (checked by tag name, not instanceof — an
|
|
91
|
+
* import here would pull the whole window component into every scroller's
|
|
92
|
+
* graph) and watch its `active` attribute. The walk crosses shadow
|
|
93
|
+
* boundaries, so it reaches the window whether the scroller is slotted into
|
|
94
|
+
* its body (light-DOM ancestor) or is the window's own edge scroll area
|
|
95
|
+
* (shadow-DOM ancestor). Reconnect re-runs it, so a reparented scroller
|
|
96
|
+
* re-resolves its window.
|
|
97
|
+
*/
|
|
98
|
+
private observeWindow;
|
|
99
|
+
/**
|
|
100
|
+
* Reflect the containing window's `active` state as a presence-only
|
|
101
|
+
* `data-window-inactive` on the scroll element. A window that hasn't
|
|
102
|
+
* upgraded yet has no `active` attribute (its default reflects on first
|
|
103
|
+
* update, which precedes any scroller rendering inside it); the observer
|
|
104
|
+
* catches the reflection either way.
|
|
105
|
+
*/
|
|
106
|
+
private reflectWindowState;
|
|
107
|
+
/**
|
|
108
|
+
* Measure overflow and reflect it as `data-overflow-{x,y}` on the scroll
|
|
109
|
+
* element. Safe to call any time; components hit it imperatively when content
|
|
110
|
+
* changes without a box resize (e.g. a `<textarea>` on input).
|
|
111
|
+
*/
|
|
112
|
+
measure(): void;
|
|
113
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { sys as e } from "./scale.js";
|
|
2
|
+
//#region src/scroll-state.ts
|
|
3
|
+
var t = 1, n = 2, r = class {
|
|
4
|
+
constructor(e, t, n, r) {
|
|
5
|
+
this.host = e, this.getScroll = t, this.getContent = n, this.onOverflowChange = r, this.vfWindow = null, this.wired = !1, e.addController(this);
|
|
6
|
+
}
|
|
7
|
+
hostConnected() {
|
|
8
|
+
this.wired = !1, this.wire(), this.observeWindow(), typeof document < "u" && document.fonts && document.fonts.ready.then(() => this.measure());
|
|
9
|
+
}
|
|
10
|
+
hostUpdated() {
|
|
11
|
+
this.wire(), this.measure(), this.reflectWindowState();
|
|
12
|
+
}
|
|
13
|
+
hostDisconnected() {
|
|
14
|
+
this.resizeObserver?.disconnect(), this.resizeObserver = void 0, this.windowObserver?.disconnect(), this.windowObserver = void 0, this.vfWindow = null, this.wired = !1;
|
|
15
|
+
}
|
|
16
|
+
wire() {
|
|
17
|
+
if (this.wired || typeof ResizeObserver > "u") return;
|
|
18
|
+
let e = this.getScroll();
|
|
19
|
+
if (!e) return;
|
|
20
|
+
this.resizeObserver ||= new ResizeObserver(() => this.measure()), this.resizeObserver.observe(e);
|
|
21
|
+
let t = this.getContent?.();
|
|
22
|
+
t && this.resizeObserver.observe(t), this.wired = !0;
|
|
23
|
+
}
|
|
24
|
+
observeWindow() {
|
|
25
|
+
let e = this.host;
|
|
26
|
+
for (this.vfWindow = null; e;) {
|
|
27
|
+
if (e instanceof HTMLElement && e.localName === "vf-window") {
|
|
28
|
+
this.vfWindow = e;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
e = e.parentNode ?? (e instanceof ShadowRoot ? e.host : null);
|
|
32
|
+
}
|
|
33
|
+
!this.vfWindow || typeof MutationObserver > "u" || (this.windowObserver ??= new MutationObserver(() => this.reflectWindowState()), this.windowObserver.observe(this.vfWindow, {
|
|
34
|
+
attributes: !0,
|
|
35
|
+
attributeFilter: ["active"]
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
reflectWindowState() {
|
|
39
|
+
let e = this.getScroll();
|
|
40
|
+
if (!e) return;
|
|
41
|
+
let t = this.vfWindow !== null && !this.vfWindow.hasAttribute("active");
|
|
42
|
+
e.hasAttribute("data-window-inactive") !== t && e.toggleAttribute("data-window-inactive", t);
|
|
43
|
+
}
|
|
44
|
+
measure() {
|
|
45
|
+
let r = this.getScroll();
|
|
46
|
+
if (!r) return;
|
|
47
|
+
let i = r.scrollHeight - r.clientHeight > e(n, r) + t, a = r.scrollWidth - r.clientWidth > t, o = r.getAttribute("data-overflow-y") !== String(i) || r.getAttribute("data-overflow-x") !== String(a);
|
|
48
|
+
r.setAttribute("data-overflow-y", String(i)), r.setAttribute("data-overflow-x", String(a)), o && this.onOverflowChange?.({
|
|
49
|
+
x: a,
|
|
50
|
+
y: i
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
//#endregion
|
|
55
|
+
export { r as ScrollStateController };
|
package/dist/size.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { LitElement } from 'lit';
|
|
2
|
+
type Constructor<T = object> = new (...args: any[]) => T;
|
|
3
|
+
/**
|
|
4
|
+
* The mixin's surface, as a `declare class` for the same TS4094 reason
|
|
5
|
+
* {@link VfPositionedInterface} states: TypeScript cannot name the
|
|
6
|
+
* anonymous class a mixin returns when emitting declarations. Keep it in sync
|
|
7
|
+
* with the implementation below.
|
|
8
|
+
*/
|
|
9
|
+
export declare abstract class VfSizedInterface extends LitElement {
|
|
10
|
+
width?: number | null;
|
|
11
|
+
height?: number | null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A declared box — `width`/`height` in whole system px, the size half of
|
|
15
|
+
* {@link VfPositioned}'s DITL story: a resource stated each item's rectangle,
|
|
16
|
+
* position *and* extent, in the window's own coordinates.
|
|
17
|
+
*
|
|
18
|
+
* It goes only on the components whose box is *stated* rather than governed
|
|
19
|
+
* by content: the two static-text elements (`vf-paragraph`, where width is
|
|
20
|
+
* the measure the copy wraps to; `vf-label`, a caption column's shared
|
|
21
|
+
* width), `vf-stack` (a panel's declared box) and `vf-window` (the WIND
|
|
22
|
+
* rect). The rest of the kit is content-governed on purpose — a push button
|
|
23
|
+
* is as wide as its label, a popup hugs its widest option (docs/LAYOUT.md, "the
|
|
24
|
+
* content governs the box") — and the components that *transform* a declared
|
|
25
|
+
* size keep their own properties: `vf-desktop` adds the bezel around it,
|
|
26
|
+
* `vf-dialog` sizes the top-layer box, `vf-img` negotiates with the art's
|
|
27
|
+
* natural size.
|
|
28
|
+
*
|
|
29
|
+
* Mechanics, mirroring the position mixin: each declared dimension goes on
|
|
30
|
+
* the host's own inline style as `calc(var(--vf-scale, 1) * Npx)` — live
|
|
31
|
+
* against the display, resolved at paint time — and a whole number keeps the
|
|
32
|
+
* box on the device-pixel grid by construction (the size half of layout
|
|
33
|
+
* contract rule 3, the one grid snapping deliberately doesn't cover).
|
|
34
|
+
* Unsetting a dimension removes the declaration and that axis returns to
|
|
35
|
+
* layout.
|
|
36
|
+
*
|
|
37
|
+
* The writing rides a {@link ReactiveController} for the lifecycle reason
|
|
38
|
+
* position.ts records (components override `updated()` without calling
|
|
39
|
+
* `super.updated()`, which would shadow a mixin-level override), and it
|
|
40
|
+
* re-applies **only when the property values changed** — the `vf-window`
|
|
41
|
+
* grow-box rule: a resize writes resolved px into the same inline
|
|
42
|
+
* `width`/`height` without touching these properties, and re-asserting the
|
|
43
|
+
* authored size on an unrelated render would snap a resized window back.
|
|
44
|
+
* Setting the property again is the deliberate way to re-size it.
|
|
45
|
+
*/
|
|
46
|
+
export declare const VfSized: <T extends Constructor<LitElement>>(Base: T) => Constructor<VfSizedInterface> & T;
|
|
47
|
+
export {};
|
package/dist/size.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { sysLength as e } from "./scale.js";
|
|
2
|
+
import t from "./_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
|
|
3
|
+
import { property as n } from "lit/decorators.js";
|
|
4
|
+
//#region src/size.ts
|
|
5
|
+
var r = (e) => {
|
|
6
|
+
class r extends e {
|
|
7
|
+
constructor(...e) {
|
|
8
|
+
super(...e), new i(this);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return t([n({ type: Number })], r.prototype, "width", void 0), t([n({ type: Number })], r.prototype, "height", void 0), r;
|
|
12
|
+
}, i = class {
|
|
13
|
+
#e;
|
|
14
|
+
#t = {
|
|
15
|
+
width: null,
|
|
16
|
+
height: null
|
|
17
|
+
};
|
|
18
|
+
constructor(e) {
|
|
19
|
+
this.#e = e, e.addController(this);
|
|
20
|
+
}
|
|
21
|
+
hostUpdated() {
|
|
22
|
+
this.#n("width"), this.#n("height");
|
|
23
|
+
}
|
|
24
|
+
#n(t) {
|
|
25
|
+
let n = this.#e[t] ?? null;
|
|
26
|
+
n !== this.#t[t] && (this.#t[t] = n, n === null ? this.#e.style.removeProperty(t) : this.#e.style[t] = e(n));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
//#endregion
|
|
30
|
+
export { r as VfSized };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 1-bit style recipes — the barrel every component and the package root
|
|
3
|
+
* import from. Each recipe lives in its own module under `./recipes/`; this
|
|
4
|
+
* file re-exports them so `import { vfBase, vfField } from '../styles/base.js'`
|
|
5
|
+
* keeps working and the public API is one name list.
|
|
6
|
+
*
|
|
7
|
+
* Why the recipes are split across modules rather than declared here: a bundler
|
|
8
|
+
* cannot drop an unused `export const x = css\`…\`` from within a module. The
|
|
9
|
+
* `/* @__PURE__ *\/` annotation that would let it is honored on *call*
|
|
10
|
+
* expressions only — Lit's `css` is a *tagged template*, and esbuild (like
|
|
11
|
+
* Rollup) ignores the annotation there. Whole-module elimination is the one
|
|
12
|
+
* granularity every bundler handles, so a module boundary is the only place a
|
|
13
|
+
* recipe can be dropped at. Before the split, importing a single recipe pulled
|
|
14
|
+
* all 24 KB of them plus both font files; a `vf-button` now carries the four it
|
|
15
|
+
* composes.
|
|
16
|
+
*
|
|
17
|
+
* That is also why the two `@font-face` registrations sit beside the two face
|
|
18
|
+
* recipes (`./recipes/body-face.ts`, `./recipes/display-face.ts`) instead of at
|
|
19
|
+
* the top of this file — a component that sets no chrome type should not ship
|
|
20
|
+
* the Chicago face.
|
|
21
|
+
*
|
|
22
|
+
* Adding a recipe: give it a module here (or add it to the one whose recipes it
|
|
23
|
+
* is always composed with), then re-export it below and from `src/index.ts`.
|
|
24
|
+
*/
|
|
25
|
+
export { vfBodyDecls } from './recipes/body-face.js';
|
|
26
|
+
export { vfDisplay, vfDisplayDecls } from './recipes/display-face.js';
|
|
27
|
+
export { vfBase } from './recipes/host.js';
|
|
28
|
+
export { vfStaticText } from './recipes/static-text.js';
|
|
29
|
+
export { vfDots, vfStripes } from './recipes/pattern.js';
|
|
30
|
+
export { vfHardShadowDecls } from './recipes/shadow.js';
|
|
31
|
+
export { vfChromeFrame, vfModalFrame, vfPanel } from './recipes/surface.js';
|
|
32
|
+
export { vfTitleBar, vfWindowWidgets } from './recipes/title-bar.js';
|
|
33
|
+
export { vfFocus, vfFocusRing, vfFocusUnderline } from './recipes/focus.js';
|
|
34
|
+
export { vfToggle } from './recipes/toggle.js';
|
|
35
|
+
export { vfField } from './recipes/field.js';
|
|
36
|
+
export { vfScrollRail } from './recipes/scroll-rail.js';
|
|
37
|
+
export { TILE_LATTICE, tileImage, tileRaster, tileRects, tileSpan, vfTileMaskSize, vfTileSize, } from './recipes/tile.js';
|
|
38
|
+
export type { TileRect } from './recipes/tile.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CSS `font-family` name the face is registered under — the default of
|
|
3
|
+
* `--vf-font-family`, and the `familyName` inside the woff2 itself.
|
|
4
|
+
*/
|
|
5
|
+
export declare const VF_BODY_FAMILY = "VF Body";
|
|
6
|
+
/** Register the body face on the document once (idempotent). */
|
|
7
|
+
export declare function registerBodyFace(): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PIXEL_GRID_METRICS as e, registerEmbeddedFont as t } from "./register-embedded-font.js";
|
|
2
|
+
//#region src/styles/body-font.ts
|
|
3
|
+
var n = "VF Body", r = "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";
|
|
4
|
+
function i() {
|
|
5
|
+
t(n, r, e);
|
|
6
|
+
}
|
|
7
|
+
i();
|
|
8
|
+
//#endregion
|
|
9
|
+
export { n as VF_BODY_FAMILY, i as registerBodyFace };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CSS `font-family` name the face is registered under — the default of
|
|
3
|
+
* `--vf-font-family-display`, and the `familyName` inside the woff2 itself.
|
|
4
|
+
*/
|
|
5
|
+
export declare const VF_DISPLAY_FAMILY = "VF Display";
|
|
6
|
+
/** Register the display face on the document once (idempotent). */
|
|
7
|
+
export declare function registerDisplayFace(): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PIXEL_GRID_METRICS as e, registerEmbeddedFont as t } from "./register-embedded-font.js";
|
|
2
|
+
//#region src/styles/display-font.ts
|
|
3
|
+
var n = "VF Display", r = "d09GMgABAAAAABIAAAoAAAAAnDwAABGvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmAAhUQKgpkcgd9zATYCJAOIDAuECAAEIAWCXAeHYxvbfEUHctg4AFB8NUVRLlbJyECwcQAV4BXj/3tyS0bgLlBtVf2TnMhqd3t09h7swdW7hULVvqlQVTPo7Dbn5ax78Nz1xE2zqsM0Xi2n+BMkiIQUi2XyguMLJZhEEnuHJmNgmH6bMit+o73wnP9ocAY63hGaHHk3Iaq17Jl5pkShI4VyjYrQMSq1FQWogDWiYuNYxRGq879f22PTV+Xsfbg3selMxyMkSjKPTCcRI6X8P7Aunw7p4g9MYLq0BMUDUQcmIqkuSZFNdRdj89GSOXIWEZuIJzHI87TBW258b8U3SaHaIripiKhYgUCcgOdp5/vVlYb5TAY0gREkMprpUGfQzcYEwRADm5jIXPrrOirgWmpqnJ/JWOsUGHthqEnlfzhAloyEgGlXhk+ubBvbju0DKIGBANxgbH4DIwfmmfNAp2j8ifb/26+JXjTiiTxpE9bZrQnemz/I+4PZsA3zJjaoJUInNYskUuJ0T3RqoHYLseP3P+0Vv+do05HdWQgIb99OwR3Bv5Jmji1LqY3VTjW6mnnSW0nrUjelNMBLwzwQLtzQEJSpNnN2a0aG7VD8KFk4AkQhqMUMOO+3/2vnS06TUv0zSsyd9qDCy+t+DzgIBsEgCIIgGARBMBgEg4d/KoTyK1NghFjVPZic8P4idB3jd4vcwP1qBMAI664GPkCBgVL4/7wkVHYARmhgJQw4VNTQMnbo3L13/4IYNaOrtmrnDSEECQkGHBCiyKOEJrr4hPeuVVt6HznUaNAigxxK0ZDGtGBBtlmEpdj2s0huYGRizUakjYyRLXJF3mgQu2JyTP0P/jQQNHgrKmvqmDpy6cmnIMwKHClCgwWUFtHAKW9RM6PnsbKsNc/PkEdkda4CAFIIXnt2DKub/9/jzz8+M7UA4HFzj+sWPN6MPxMWPJxW5KFgG6c4suD+wRrmIWIaE+bfVObRtCYxgBopkBQOqf6Prck/i5tDcfInavEmGDbhe48rDjLwAXY2R5FbekbAHgC7A03wjliHDaFvXODF4jzZxyIQPdjFJXt14Aif6sMNIZ3BZPki4/j24JGC55bKn2cv1E6UnaqoOlNzrq5py6uFN0sfXg1sW/MNkAqgHZIb6Fg+X+fwAUALHwAQE5GRVcELcpeiMJUCOBAmRhAMwWEGTqFBHBDMZRooE8MEiTEGzCOq0Ego0v1kwaWKoFTQXKIIBHOiY3iTMccIIl13jnsnEqFYykIk4H2Xg5cQnGyNxsl0N+pb7n7j40TI63DLNTHxjYC7wAjNgJqLLEAikorIOUzQjh0Y25QEYwAUgo5KOyUyezFVtIhTWtRMY6PNFdp0qWQimLIi9acafzlpp9iKGWgvE7kr08T1hsjsZseJwKgp9cc6ChEUMJD5+foZACjWVduksAVgY0XpJSAzI99mHJhHIsxEk5xbuscKdeqa70dbGBNtjKbfZB9MaNVjW/BBHZhRqTukeuJq62sep+g2hAaXsuQSV4tP+DaWrOQdIyBtWT5kaoS0BU8YkP1IUXPNmJRjxfcvcoJwN2KHCItJDGtxG10mJJlJuGGaBkMU3LqWSOJYVAO707RG1/2KHIzID5FTlkQWEpLMOof+pK4Z3BhlK6rlyAlzUl0i6UXVuz1bQsUlSdzB0B6n1krerfb+0RPMuiqDENdmZ0hjZAOqjm6xnOX+u6evtK5rP+Ywx4DXgMLyBAQdbhj5DuaBs61p0kxo9tIcX8PBwMfiqnYqfnydf/ZqOJRgsQt/1g6+q0kIj9XSOhqyL/bxqppJHCyrZIwwCHO+6CnLntjDSbTZIslWTkTjOkq2e0eUDJYTKoLfvF2N5wv1KSOxZJuSPo7BlbGsnyyWstoUtbsHMkXwkCeNMeu1poy3YbwgAo1tTMooKEi4Yltvva3zbjr3Y12yPXVyzS1UoGVeXGZgNVx9zoZpxzTMHZKDuRXwJSGibntHVGrQN0onPKQHJuEcQDF62W0FgAHIewOfSDQMbIygVETbJ8fBVzSal7wbUkqHvNVamksldt8A5lkgUSpk1U3FBK0brKUBtBJGLcotwWmRAnBe6l3k8g1PDk/ExoPS39kUpG2s/WN5QYjtTPbY+1ZoXmZd6rWZE/p6DE8UWgi05jBBiBnJ2N9+Jtocq1nFUEqs59MuLo32FPsXZ9OKViRmkPDy9KFxXvW5AxHr4vW2LLgpr+lki2f9OI+5jqDTKHCSUExsGvtnWlmqldSRhSBMvvg0BiLZv2Xm7m/ypFacjSBfqZCUZS1S8Cdo2bU+HmS7HXmeLyKBYtWlTxYSpslPMsMRmspTMUZXQK/OuCApAPaz94la3zJzq/TCW7OnTCk/81gWfmKr3Fp5H2TTim+g7TeZjqUE9MVTlBEeXEb5jIPK01eQ7zycmc1BbqIyvc3XlNjSLpDDGrSua2ocYA4IyrY9lQFpulP5CAt5gdAyMXvU9VbGYoO2cK1T4ZOLpk9OFNLoS4gjjHxLYveckzcpKjx6Dxecd5JKlmTD26TtB96FvIcp6O05GgkkgZudlETVBE3wlTUVx0BP65WWJv7Ymk62Ehv0b4kwo/8HyezqVJkBphESiui0IdfVEv62mcpXB3H1U8MZLh99AYUuIZ7azPRVE75y7E94aCouifBlEV43PDlJpa3JDbjHV47w9S42sqUj+OVdpUMC/9DQ8ZY7SXs4jwnOQANpgukNScTfPfgb12avZbIsBJyouFr9xSWNsXzp4hMBzO7pRu8TEAcR7d+Q0ovo7pUE94yxDJVJol65pTAHDBIN9RQz2TmKqVVslt4PzWZwtHUa9cbz6lPHo5tBnRH2H59gZuacn6WGyS7d6Xlu4jofEl/0If5o/qqCeyxVz3MuN2I1ra+n6CCn9pff9W9dmVn3UmjIkGJRgq9n3Z+JEsqRc0JRYYkhaff+WOT14LrfCM0ktpEf1+KbRaIAvqoJgR5yRka08YujFNxPJLfKDJoTsqMI8FzKnaNaeqa5eSL9iGQTc4yRApxpjT7XhAB+Yivr5SPvUnPymvQUGYXYH4XUqbVJzDLX4icLbXFXSTz00CVVDwOkUc2GvjeqjXzizBsDhVKNoJFbn+y7xG/cjhwsSwH0O4zjd/Z3kIWjdzB/ASGRmOC5774JnalVj1bSy3Ix9JhHrz7QlPTJb5IOp5MkhVaQDTvVpPJkWlcj+u1Rbh5S5xPIO70EkW2nlPpvZDOGREJ7qBigIhd/CbXRPlfzjuN+a4FwSDvsyOIYgQPAtuVqln0ri6H6dpKpoGzhasYpB9Aiw9C2mcFd3S4kFf9A/VX59dBdYQ+ooYJdk/XFJtMEuR6mLL2FzqCa1aT6+OfQgVi9irXxHNXEjMig4LYPj327F/q6xjRpgnrmY/1oiN3ykCEHUuLAkI6c/7A53GU6DlbvCX/W3JT+PCIGzHxkDniHR4oRHjjqVrFdwbL7N+aQIKu/i66N6HrIvKAoPvBWLI+FnwzxyDv5mRXtPtTemjih2yfGuONvrFZ1Iy1XRcLRkP+vnJYNoMUOpaixbbKTXy4EDi1aVnZJm/LTlHZim+pvBCTTLhVK76+fNK4ey7oVaDNvlVnObS1CTejGMPjWGL7B6EImziDgZxLAhNHTuz5P5I7oW7HdLRTse8Hv0Ttw4aQtgsd1qT8H+xdE+j7enPGza81V8A3EbO/oWiU6U6W/xBZW67/R9ThlM24mJ8+5/WEOCrfEc1vbzHYMwXKXimfBPG/9Lv8m2xLd4ooeG15watrAADU3M+HUd+7yEnEi4E5bOYGR+6AAxcyKy/3YJfRYrC3tAyJW06AFQPgVQmrqqatdlN5s+y56xe2Mu4Pirs56dGFOPL/crIkettFGnPKT34/Ijaj5qgnfPMS6NdWzw9b5Lte2maA3N/K6E/ahoz/mARC8q841AElRf+2mWGU/iCwlTN6c30Jou3h/B9s7nNUDN9Fkeu6svpJJ//vjbvJ02jPjJDOhZjzkcmIMbjKURLYT6p00i4w5f9Y33v6VE3UZETFgdCoX3rcZotH1ZrrPwkQBj7n9eZwktmx/ZqLoeZ9+IgNjeUn3tEERVAU6oh7WKUKBtp8Mzu4QuMvMuE5wdy4683ObBLunFqgpb0vApXfyGRI34GV93P+ACSY+vxtE0TsOLaLK4raFUaOew/pOQV6kFsCcJ1VvXweZQAWkUfQZFf3TQklpO6ef+KJ8mYyzCta7MOWfjXXS8pn/hQS/VVMiQNe/kg85CJzHVpOw46si102dDiKPm6Pn/O+YmSR5h/8I83+ODIEstB0f1TvfT80Ljk3rgpf/B+fXJk7rowhFbHYV6XEdWbBPOAhl8by1bVKptTCzBR+HHHBwR0z58h+yPZtMMvHOr29kdOYylHILFVnLi2j+15x+39JBE2mrIDt2UURfh/7IW98frDaS7G5J8Pa0cIT+fb9y3f9/+iFKztscYkyfebVmNUmGAgWkR3uG204pLJlber0tBXNSlICOjWXBTQIbnklBAr9WVk1MEvCQfzJAhjbzFIuX/H7SsUdg+N9bqfjMwyILVcICsaNRPB6fX3GbrZdls6Fi3gSIrirx+E2+6WdlWL5vXrJ28E8qL2De8eULDEhZ6aBLu3PSoIQt2ctc5Zy/m/fbeptx/UfTmzRpkl5e9IMM9KnPsc2v7o1Vsmkh08zTYZK1M289+n4ytIJ/hyD8CJoTX8ilGDEwnEU26esRG5mgpnyOZN16UiznEXlt/0nYXbia/MeNrs5Fnnuoh1O67S9q9ecb73IuKmD/m0v5ATsVsXqqlOMDD69YAgKUHuzT6skEpSreq/T/W/vE3f8Si3dvLM4F22gmo7zWsQrMLReURpRPlNNFckzUZCJffFXRCSxAgUc+B+3uO4J0ZhpZE4+cTNcI68IiXhls5XLnAcMk87IyNToHdMpFScVmmOcX5T29opRSOPe5Xry6MoEpq9b1Eta7PEM8K0l0rVZ13miyWtXdSTaOB0ccFfIf2V/ByZ7vN7IQAE+ztEj5xcA0AEMx8v/GLLzAKoeMcIfd6w89L+dWPSelxvcrL8c5ikkjAKfbj/NbdjP5wEKfjNun0cNDLroLdRcbQyTsWUQNJaU7lN+D+GY+N6kAGDQlka273eITV3gBp6DRKqWguzxnZzFoRVhuxncKmIA15Cp5dw7h0qoDPLQma0vI3rB/5AAJJE3KZgQ1I9+2xKuD8GPtqGFl7noBaHAzAR4grtHwfTJ9h6zVMweWb76E78NeE6zvuW7mzr5FvBPM+BOABxwgIEY/9QCKdVeKaQQAIQFQKVESyqifG783FK3C0lrvjkjoFSQtjihpI6Uy+pTpNN8bQiqs3qsxEhH/XuDdU4MHDyzRKV6FCKxFJPmS0gP/4NoDvYVsnqgVyGl5UGQCCNBFUYhYEMsIDEFzLJTpKDwVlidgWizJ4K5W9EAxTFwvU1AEPEBBVp5wYoyWTTZ+s3M7bkJ8pIi5hKSmKU3/ejyBSCJTqDQ6g8lic7jAQ5iwiKiYuISklLSMrJy8ggMIEwqMC6m0sc4DgCAwBAqDI5AoNAaLwxOIJDKFSqMzmCw2h8vjC6IOJVIbmU5t5+WqEpu1tgp7b2c/f6HI0EYEGNwFshUUM2goDA6Lt4dNIpIpNCrfbp/NUr9DHtelLDVfSGumo2uuJC2up29kbGBIx6xuzYpVDhEVMVFFPgllbgHBmIQ4TVgivDnzbtunD5++fPtJVGJc27Vlz4ZNh/YdO3Dk3IlTZ65duHTnxm1iSUhSUpKWjGQlBx4CREiQoUCFBh0GTFiw4cAF4IHAEEYEUcQQR4I2PNWeb+VBWWepUC+udKpFtUJpAuzq95P07GFekJvhvCwky4Lx4CZWWXxb0kqnJvqSEPcBZXHxDjPL000M5pLl6yYsSX7zMEU7btOi32HqF7I0Qzl1DAt855qBfDCjQnD7ukEKnCmSgsDMTvItg2fjSV4LIEdoHvIUD5lXj9r0v8061awJivOtblt54ivX3l91U939ZecFmhhMm7G/WGxfIddwdbXm6c/PkNZH6DblBO/1aJjnQ2f2c8ne3lbLxFyfDAAA";
|
|
4
|
+
function i() {
|
|
5
|
+
t(n, r, e);
|
|
6
|
+
}
|
|
7
|
+
i();
|
|
8
|
+
//#endregion
|
|
9
|
+
export { n as VF_DISPLAY_FAMILY, i as registerDisplayFace };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import '../body-font.js';
|
|
2
|
+
/**
|
|
3
|
+
* The three declarations that put text on the *body* face — the family via
|
|
4
|
+
* --vf-font-family, 16px so its 1024-upm pixel grid lands exactly, and the
|
|
5
|
+
* body smoothing token. The mirror image of {@link vfDisplayDecls}, and the
|
|
6
|
+
* body face's single definition: {@link vfBase} applies it to every host, and
|
|
7
|
+
* the places that switch *back* to it from the display face
|
|
8
|
+
* (vf-label/vf-paragraph's `face="body"`) compose this rather than repeating
|
|
9
|
+
* the family stack.
|
|
10
|
+
*
|
|
11
|
+
* 'VF Body' is the embedded face (../body-font.ts); 'Geneva' after it is the
|
|
12
|
+
* installed one a real Mac already has. See {@link vfDisplayDecls}.
|
|
13
|
+
*/
|
|
14
|
+
export declare const vfBodyDecls: import("lit").CSSResult;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import "../body-font.js";
|
|
2
|
+
import { unsafeCSS as e } from "lit";
|
|
3
|
+
//#region src/styles/recipes/body-face.ts
|
|
4
|
+
var t = e("\n font-family: var(\n --vf-font-family,\n 'VF Body',\n 'Geneva',\n 'Helvetica Neue',\n Helvetica,\n Arial,\n sans-serif\n );\n font-size: calc(var(--vf-scale, 1) * var(--vf-font-size, 16px));\n -webkit-font-smoothing: var(--vf-font-smoothing, antialiased);\n");
|
|
5
|
+
//#endregion
|
|
6
|
+
export { t as vfBodyDecls };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import '../display-font.js';
|
|
2
|
+
/**
|
|
3
|
+
* The three declarations that switch text to the display face — the family via
|
|
4
|
+
* --vf-font-family-display, 16px so the 1024-upm pixel grid lands exactly, and
|
|
5
|
+
* grayscale smoothing off for crisp 1-bit edges. Each is tokenized for
|
|
6
|
+
* retheming. Compose onto a rule for one chrome element, or use
|
|
7
|
+
* {@link vfDisplay} to apply to the whole host.
|
|
8
|
+
*
|
|
9
|
+
* 'VF Display' is the embedded face (../display-font.ts). Everything after it
|
|
10
|
+
* is an *installed* face the reader might have — a real Mac has Chicago and
|
|
11
|
+
* Charcoal — so the stack degrades toward the same shapes on a machine that
|
|
12
|
+
* already owns them, and toward the platform sans on one that doesn't.
|
|
13
|
+
*/
|
|
14
|
+
export declare const vfDisplayDecls: import("lit").CSSResult;
|
|
15
|
+
/**
|
|
16
|
+
* Display type applied to the whole host. Compose into any
|
|
17
|
+
* component whose text is entirely "chrome": buttons, menus, menu items,
|
|
18
|
+
* checkbox/radio labels, popup menus. Components that mix a chrome title with
|
|
19
|
+
* body content (windows, dialogs, fieldsets) instead apply {@link vfDisplayDecls}
|
|
20
|
+
* to just their title/legend element, leaving slotted body copy on the vfBase
|
|
21
|
+
* body face.
|
|
22
|
+
*/
|
|
23
|
+
export declare const vfDisplay: import("lit").CSSResult;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "../display-font.js";
|
|
2
|
+
import { css as e, unsafeCSS as t } from "lit";
|
|
3
|
+
//#region src/styles/recipes/display-face.ts
|
|
4
|
+
var n = t("\n font-family: var(\n --vf-font-family-display,\n 'VF Display',\n 'Chicago',\n 'ChicagoFLF',\n 'Charcoal',\n 'Geneva',\n 'Helvetica Neue',\n Helvetica,\n Arial,\n sans-serif\n );\n font-size: calc(var(--vf-scale, 1) * var(--vf-font-size-display, 16px));\n -webkit-font-smoothing: var(--vf-font-smoothing-display, none);\n"), r = e`
|
|
5
|
+
:host {
|
|
6
|
+
${n}
|
|
7
|
+
}
|
|
8
|
+
`;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { r as vfDisplay, n as vfDisplayDecls };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The System 7 editable-field skin (SPEC §1/§5): a white well with a 1px black
|
|
3
|
+
* border, no corner radius, Chicago-style display type, and the kit's dashed
|
|
4
|
+
* keyboard-focus rule under the well (no dotted ring). Add the `vf-field`
|
|
5
|
+
* class to the inner native `<input>`/`<textarea>` and wrap it in a
|
|
6
|
+
* `.vf-field-well` element; the host supplies layout (width, height, padding)
|
|
7
|
+
* around it, and `VfTextControlBase` supplies the `.vf-focus-rule` class that
|
|
8
|
+
* turns the rule on. Shared by vf-text-field, vf-text-area and
|
|
9
|
+
* vf-number-field so the well, focus and disabled treatment stay identical
|
|
10
|
+
* across all three.
|
|
11
|
+
*
|
|
12
|
+
* Why the wrapper: the rule is a pseudo-element, and a replaced element
|
|
13
|
+
* generates none — neither `<input>` nor `<textarea>` can draw its own
|
|
14
|
+
* `::after`. Hanging it off the host instead would leave it behind when grid
|
|
15
|
+
* snapping moves the field, since the correction lands on `.vf-snap` inside the
|
|
16
|
+
* shadow root and never on the host. The wrapper is both anchors at once: it
|
|
17
|
+
* carries `vf-snap`, and it boxes the well exactly, so the rule spans the well
|
|
18
|
+
* and measures its offset from the well's own bottom edge.
|
|
19
|
+
*/
|
|
20
|
+
export declare const vfField: import("lit").CSSResult;
|