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,68 @@
|
|
|
1
|
+
import { vfDisplayDecls as e } from "./display-face.js";
|
|
2
|
+
import { vfFocusUnderline as t } from "./focus.js";
|
|
3
|
+
import { css as n } from "lit";
|
|
4
|
+
//#region src/styles/recipes/field.ts
|
|
5
|
+
var r = n`
|
|
6
|
+
.vf-field {
|
|
7
|
+
background: var(--vf-white, #fff);
|
|
8
|
+
border: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
|
|
9
|
+
border-radius: 0;
|
|
10
|
+
/* Editable text is set in the Chicago-style display face. */
|
|
11
|
+
${e}
|
|
12
|
+
font-weight: var(--vf-font-weight, 700);
|
|
13
|
+
line-height: inherit;
|
|
14
|
+
color: var(--vf-black, #000);
|
|
15
|
+
user-select: text;
|
|
16
|
+
-webkit-user-select: text;
|
|
17
|
+
outline: none;
|
|
18
|
+
/* Stated, not inherited: Firefox's UA sheet puts \`cursor: text\` on
|
|
19
|
+
\`<input>\`, so the kit-wide cursor token (SPEC §3) has to be read here
|
|
20
|
+
to reach the well at all. The fallback is the I-beam it always was. */
|
|
21
|
+
cursor: var(--vf-cursor, text);
|
|
22
|
+
}
|
|
23
|
+
/* The wrapper boxing the well: the positioned anchor the focus rule hangs
|
|
24
|
+
from, and the element grid snapping moves (see the note above). */
|
|
25
|
+
.vf-field-well {
|
|
26
|
+
position: relative;
|
|
27
|
+
}
|
|
28
|
+
/* Keyboard focus is the kit's dashed rule one blank row under the well — not
|
|
29
|
+
a ring around it, and not a thickened border (see vfFocusUnderline). The
|
|
30
|
+
offset counts that blank row and the rule itself down from the well's
|
|
31
|
+
bottom edge: −(1 + 1).
|
|
32
|
+
|
|
33
|
+
Gated on a class rather than :focus-visible, which cannot express this for
|
|
34
|
+
a field: the selector matches any focus of an element that takes keyboard
|
|
35
|
+
input, so it is already true for a mouse click (see focus-modality.ts).
|
|
36
|
+
VfTextControlBase adds .vf-focus-rule for a keyboard focus only. */
|
|
37
|
+
.vf-field-well.vf-focus-rule::after {
|
|
38
|
+
--vf-focus-underline-offset: -2px;
|
|
39
|
+
${t}
|
|
40
|
+
}
|
|
41
|
+
/* Its own token, deliberately not --vf-disabled: the disabled rule below is
|
|
42
|
+
an inactive control and exempt from contrast requirements, but a
|
|
43
|
+
placeholder sits in an ENABLED, operable field and isn't — and the dim
|
|
44
|
+
gray is 1.82:1 on the white well. #767676 is 4.54:1 (AA). System 7 had no
|
|
45
|
+
placeholder text at all, so like the focus rule this is a modern
|
|
46
|
+
affordance the kit adds, and it gets a color the modern requirement can
|
|
47
|
+
accept rather than a traced gray it must match. */
|
|
48
|
+
.vf-field::placeholder {
|
|
49
|
+
color: var(--vf-field-placeholder, #767676);
|
|
50
|
+
font-weight: inherit;
|
|
51
|
+
opacity: 1;
|
|
52
|
+
}
|
|
53
|
+
/* Disabled: the text dims to gray; the solid black box border stays. The
|
|
54
|
+
cursor returns to the arrow — a well that can't take input isn't text. */
|
|
55
|
+
.vf-field:disabled {
|
|
56
|
+
color: var(--vf-disabled, #c0c0c0);
|
|
57
|
+
cursor: var(--vf-cursor, default);
|
|
58
|
+
}
|
|
59
|
+
/* Selected text inverts to solid black-on-white — the 1-bit System 7
|
|
60
|
+
selection, not the browser's translucent blue. Reuses the list's highlight
|
|
61
|
+
tokens so every selection in the kit shares one color. */
|
|
62
|
+
.vf-field::selection {
|
|
63
|
+
background-color: var(--vf-highlight, #000);
|
|
64
|
+
color: var(--vf-highlight-text, #fff);
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
67
|
+
//#endregion
|
|
68
|
+
export { r as vfField };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dotted focus outline's two declarations, for composing inside any focus
|
|
3
|
+
* selector whose shape (`:host(:focus-visible) .box`, `.viewport:focus-visible`,
|
|
4
|
+
* a JS-toggled `.focus-ring`, …) is too varied to share a whole rule. Interpolate
|
|
5
|
+
* it into the component's own selector: `.box { ${vfFocusRing} }`.
|
|
6
|
+
*
|
|
7
|
+
* The offset defaults to +2px (ring sits just outside the box); set
|
|
8
|
+
* `--vf-focus-offset` in the same rule to inset it (negative, to stay in-box) or
|
|
9
|
+
* widen it. Keeps the outline default (`--vf-focus-outline`) authoritative in one
|
|
10
|
+
* place so a ring-style change is a single edit.
|
|
11
|
+
*
|
|
12
|
+
* Drawn in `currentColor` — the same mechanism as {@link vfFocusUnderline} —
|
|
13
|
+
* so the ring inverts with the ink it sits on. This is load-bearing for
|
|
14
|
+
* `vf-list-item` in a `multiple` list: Ctrl+Arrow deliberately walks the
|
|
15
|
+
* cursor across already-selected rows, and a hard-coded black ring on the
|
|
16
|
+
* inverted black selection bar left that cursor genuinely invisible while
|
|
17
|
+
* Space still acted on it. On the highlight bar `currentColor` is
|
|
18
|
+
* `--vf-highlight-text`, so the ring reads white there and black everywhere
|
|
19
|
+
* else — no unselected artwork changes.
|
|
20
|
+
*/
|
|
21
|
+
export declare const vfFocusRing: import("lit").CSSResult;
|
|
22
|
+
/**
|
|
23
|
+
* Focus ring for non-text controls where focus and ring share one element.
|
|
24
|
+
* Apply to the focusable element:
|
|
25
|
+
* .control:focus-visible { ... }
|
|
26
|
+
* or compose this class name onto it.
|
|
27
|
+
*/
|
|
28
|
+
export declare const vfFocus: import("lit").CSSResult;
|
|
29
|
+
/**
|
|
30
|
+
* The kit's focus indicator for a control that can carry the mark on its own
|
|
31
|
+
* face: a 1px dashed rule beneath it — 1 system px on, 1 off — instead of a
|
|
32
|
+
* ring around it. It has two placements, both out of this one recipe:
|
|
33
|
+
*
|
|
34
|
+
* - *Inside* the control, under the ink it marks: the button underlines its
|
|
35
|
+
* label, the two toggles their box and circle.
|
|
36
|
+
* - *Below* the control, under its whole box and clear of its hard shadow, for
|
|
37
|
+
* a control with no interior to give: vf-select's one line is shared by the
|
|
38
|
+
* label and the ▼, and a vf-swatch is nothing but fill.
|
|
39
|
+
*
|
|
40
|
+
* It is why none of those compose {@link vfFocus}.
|
|
41
|
+
*
|
|
42
|
+
* Keyboard focus is one of the modern requirements the kit adds rather than
|
|
43
|
+
* emulates (SPEC §1): System 7 predates full keyboard access and drew no such
|
|
44
|
+
* indicator at all. So the job is to render an affordance it never had in a
|
|
45
|
+
* 1-bit vocabulary it would recognize — a hairline dashed rule on the pixel
|
|
46
|
+
* grid, which reads on a white face and inside a control's tight silhouette
|
|
47
|
+
* where an offset ring has nowhere to go.
|
|
48
|
+
*
|
|
49
|
+
* Interpolate into an `::after` rule on the element being underlined (which
|
|
50
|
+
* needs `position: relative`), gated on whatever focus selector the component
|
|
51
|
+
* uses — and suppress the UA outline in the same rule set:
|
|
52
|
+
*
|
|
53
|
+
* button:focus-visible { outline: none; }
|
|
54
|
+
* button:focus-visible .label::after { ${vfFocusUnderline} }
|
|
55
|
+
*
|
|
56
|
+
* The rule spans that element's own box and leaves ONE blank system px row
|
|
57
|
+
* between itself and the ink above, which is what `--vf-focus-underline-offset`
|
|
58
|
+
* places — measured from the element's bottom edge up to the rule's, so
|
|
59
|
+
* positive insets it and negative drops it below. A negative one counts every
|
|
60
|
+
* row of ink between the two, since an absolutely positioned pseudo-element
|
|
61
|
+
* sizes to the PADDING box and the ink can carry on past it:
|
|
62
|
+
*
|
|
63
|
+
* - `4px` (the default) is a text box, where the ink stops at the baseline and
|
|
64
|
+
* the box continues 6px past it (2px half-leading from vfBase's 1.25 line box
|
|
65
|
+
* over the 16px em, plus the face's 4px descent): 6 − 2 = 4.
|
|
66
|
+
* - `-2px` is a well whose ink runs to its own bottom edge — the radio's circle,
|
|
67
|
+
* a field's wrapper — putting the rule in the second row below it.
|
|
68
|
+
* - `-3px` adds a 1px border the pseudo-element sits inside of (vf-checkbox).
|
|
69
|
+
* - past that, the rule also clears a hard shadow, which is ink no box the
|
|
70
|
+
* pseudo-element can size to contains: `-4px` for vf-select's 1px one, and
|
|
71
|
+
* for vf-swatch an offset that composes `--vf-shadow-offset` rather than
|
|
72
|
+
* hard-coding a depth its consumer can retheme.
|
|
73
|
+
*
|
|
74
|
+
* Drawn in `currentColor`, so it inverts with the label on a pressed face.
|
|
75
|
+
*/
|
|
76
|
+
export declare const vfFocusUnderline: import("lit").CSSResult;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { css as e } from "lit";
|
|
2
|
+
//#region src/styles/recipes/focus.ts
|
|
3
|
+
var t = e`
|
|
4
|
+
outline: var(--vf-focus-outline, 1px dotted currentColor);
|
|
5
|
+
outline-offset: calc(var(--vf-scale, 1) * var(--vf-focus-offset, 2px));
|
|
6
|
+
`, n = e`
|
|
7
|
+
.vf-focus:focus-visible {
|
|
8
|
+
${t}
|
|
9
|
+
}
|
|
10
|
+
`, r = e`
|
|
11
|
+
content: '';
|
|
12
|
+
position: absolute;
|
|
13
|
+
left: 0;
|
|
14
|
+
right: 0;
|
|
15
|
+
bottom: calc(var(--vf-scale, 1) * var(--vf-focus-underline-offset, 4px));
|
|
16
|
+
height: calc(var(--vf-scale, 1) * 1px);
|
|
17
|
+
background: repeating-linear-gradient(
|
|
18
|
+
to right,
|
|
19
|
+
currentColor 0 calc(var(--vf-scale, 1) * 1px),
|
|
20
|
+
transparent calc(var(--vf-scale, 1) * 1px) calc(var(--vf-scale, 1) * 2px)
|
|
21
|
+
);
|
|
22
|
+
pointer-events: none;
|
|
23
|
+
/* Forced colors deletes every non-url() background-image, this gradient
|
|
24
|
+
included — and each carrier suppresses the UA outline in the same rule
|
|
25
|
+
set, so without this branch a keyboard user in high-contrast mode has no
|
|
26
|
+
focus mark anywhere the underline serves (ACCESSIBILITY-REVIEW §2.1).
|
|
27
|
+
forced-color-adjust: none turns the same 1-on/1-off gradient back on. It
|
|
28
|
+
stays currentColor, and the ::after's color inherits from an ancestor the
|
|
29
|
+
override DID reach — so the mark lands in the user's own palette
|
|
30
|
+
(CanvasText on a face, HighlightText on a highlight bar) and still
|
|
31
|
+
inverts with the ink it marks. Bare declarations in a nested @media apply
|
|
32
|
+
to the composing rule's own selector (CSSNestedDeclarations), which every
|
|
33
|
+
forced-colors engine supports. */
|
|
34
|
+
@media (forced-colors: active) {
|
|
35
|
+
forced-color-adjust: none;
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { n as vfFocus, t as vfFocusRing, r as vfFocusUnderline };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { vfBodyDecls as e } from "./body-face.js";
|
|
2
|
+
import { css as t } from "lit";
|
|
3
|
+
//#region src/styles/recipes/host.ts
|
|
4
|
+
var n = t`
|
|
5
|
+
:host {
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
${e}
|
|
8
|
+
font-weight: var(--vf-font-weight, 700);
|
|
9
|
+
line-height: 1.25;
|
|
10
|
+
color: var(--vf-black, #000);
|
|
11
|
+
user-select: none;
|
|
12
|
+
-webkit-user-select: none;
|
|
13
|
+
}
|
|
14
|
+
:host *,
|
|
15
|
+
:host *::before,
|
|
16
|
+
:host *::after {
|
|
17
|
+
box-sizing: inherit;
|
|
18
|
+
}
|
|
19
|
+
:host([hidden]) {
|
|
20
|
+
display: none !important;
|
|
21
|
+
}
|
|
22
|
+
/* Forced-colors mode (Windows High Contrast) — a modern adaptation the kit
|
|
23
|
+
ADDS, in what is arguably the most 1-bit-native form the platform offers:
|
|
24
|
+
the user chose their own two colors, and a two-color design honors them by
|
|
25
|
+
re-declaring its palette in the system pair rather than fighting the
|
|
26
|
+
override. The mechanism: forced colors rewrites color-valued properties at
|
|
27
|
+
used-value time, but a property whose computed value is a <system-color>
|
|
28
|
+
keyword is preserved — and var() substitution happens before the override
|
|
29
|
+
judges it. So remapping the tokens here repairs, in one place, every paint
|
|
30
|
+
site that routes through them: borders, faces, glyphs, the selection
|
|
31
|
+
inversion, the button's silhouette pseudos, vf-grid's masked rules.
|
|
32
|
+
What it cannot reach is filed per site: non-url()
|
|
33
|
+
background-images are deleted regardless of color (the focus underline and
|
|
34
|
+
title-bar stripe gradients — see vfFocusUnderline/vfStripes), url() tiles
|
|
35
|
+
are preserved with their literal ink (the dot/sprite tiles — masks over
|
|
36
|
+
these tokens instead), and box-shadows are never painted. */
|
|
37
|
+
@media (forced-colors: active) {
|
|
38
|
+
:host {
|
|
39
|
+
--vf-black: CanvasText;
|
|
40
|
+
--vf-white: Canvas;
|
|
41
|
+
--vf-surface: Canvas;
|
|
42
|
+
--vf-disabled: GrayText;
|
|
43
|
+
--vf-field-placeholder: GrayText;
|
|
44
|
+
--vf-highlight: Highlight;
|
|
45
|
+
--vf-highlight-text: HighlightText;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/* Device-pixel grid snapping (src/grid-snap.ts). The controller writes the
|
|
49
|
+
sub-half-pixel correction as two reserved custom properties on the host
|
|
50
|
+
(--vf-snap-dx/-dy); this class applies it to a component's top-level
|
|
51
|
+
painted element(s). Absolutely positioned satellites that anchor to the
|
|
52
|
+
host (vf-menu's panel, the default button's ring) compose the same
|
|
53
|
+
variables into their own insets instead. Controller-owned — never set the
|
|
54
|
+
variables by hand. */
|
|
55
|
+
.vf-snap {
|
|
56
|
+
position: relative;
|
|
57
|
+
left: var(--vf-snap-dx, 0px);
|
|
58
|
+
top: var(--vf-snap-dy, 0px);
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { n as vfBase };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type TileRect } from './tile.js';
|
|
2
|
+
/**
|
|
3
|
+
* The windoid bar's dither: a 2-system-px motif with a single black pixel at
|
|
4
|
+
* its origin, stated once as rect data. Transparent ground, because the layer
|
|
5
|
+
* floats over the bar and the same art doubles as the forced-colors mask,
|
|
6
|
+
* where the ground would be opacity rather than paint. The SVG tile below is
|
|
7
|
+
* the CSS-repeated form (the no-declared-width fallback and the forced-colors
|
|
8
|
+
* mask); `vf-window` renders the exact fill — the whole-surface raster or a
|
|
9
|
+
* consumer token's placed tile grid — from the same data (src/tile-grid.ts).
|
|
10
|
+
*/
|
|
11
|
+
export declare const DOT_MOTIF = 2;
|
|
12
|
+
export declare const DOT_RECTS: readonly TileRect[];
|
|
13
|
+
/** The dots' tile size in system px (30) — the consumer token's documented box. */
|
|
14
|
+
export declare const DOT_SPAN: number;
|
|
15
|
+
/**
|
|
16
|
+
* Racing stripes for title bars. Apply the class to an absolutely-positioned
|
|
17
|
+
* layer inset 3px (top/bottom) and 1px (left/right) within the title bar. At
|
|
18
|
+
* the 18px bar height this yields exactly six 1px stripes spanning the close
|
|
19
|
+
* box's top and bottom edges (title-bar interior 17px, band 11px tall); the
|
|
20
|
+
* side inset leaves the stripes one system px clear of the frame border,
|
|
21
|
+
* matching the widgets' 1px patch ring in the reference art.
|
|
22
|
+
*
|
|
23
|
+
* TWO renderings by engine, each the measured best (2026-08-09/10: all
|
|
24
|
+
* three engines at eight densities, then a four-geometry Blink
|
|
25
|
+
* registration sweep; the numbers live in scripts/verify-tile.mjs):
|
|
26
|
+
*
|
|
27
|
+
* - **Gecko and WebKit show the six placed solid rows** (`chromeTitleBar`
|
|
28
|
+
* renders the spans). Both engines device-snap solid boxes — the rows
|
|
29
|
+
* measured pixel-perfect at all eight densities in each — and each
|
|
30
|
+
* misrendered the gradient this layer once used: Gecko's GPU WebRender
|
|
31
|
+
* pipeline renders a gradient through a cached texture whose sampling
|
|
32
|
+
* softens a hard stop at default zoom (the originally reported bug), and
|
|
33
|
+
* WebKit landed the sixth stripe one device row thin at dpr 3 and the
|
|
34
|
+
* zoom-minted scales.
|
|
35
|
+
*
|
|
36
|
+
* - **Blink — and any engine failing both gate properties — shows the
|
|
37
|
+
* 12-unit SVG**: the band's 11 rows plus one empty pad row, viewBox
|
|
38
|
+
* stretched onto a 12px-tall box, crispEdges. Blink pixel-snaps a
|
|
39
|
+
* painted BOX to whole CSS px, which killed every mechanism whose
|
|
40
|
+
* geometry rides an 11-system-px box — no legal CSS height exists at
|
|
41
|
+
* scale 3/2 (16.5px), so placed rows fuse, rasters and an 11-tall SVG
|
|
42
|
+
* drop or wobble a row, and a clip-path comb (origin-anchored, so the
|
|
43
|
+
* even-height trick can't reach it) AAs at every fractional density.
|
|
44
|
+
* Twelve divides by 2 and 3, so 12·scale is a whole CSS length at every
|
|
45
|
+
* scale an integer display derives (18px at 3/2, 16px at 4/3): the box
|
|
46
|
+
* never rounds. Measured: registered Δ0 with the close box, whole-rhythm
|
|
47
|
+
* and zero-gray at dpr 1/1.5/2/3 across all four sweep geometries, and
|
|
48
|
+
* never worse than the retired gradient at the unholdable scales
|
|
49
|
+
* (1.25/1.7/2.3/2.5), where its residual is a hard one-row-thin first
|
|
50
|
+
* stripe with no gray — the gradient produced the same thin stripe PLUS
|
|
51
|
+
* a smeared row, so it is strictly dominated and gone.
|
|
52
|
+
*
|
|
53
|
+
* The gate is two engine-exclusive properties: `-moz-appearance` parses
|
|
54
|
+
* only in Gecko, `-webkit-backdrop-filter` only in WebKit (Blink's
|
|
55
|
+
* backdrop-filter is unprefixed, never aliased).
|
|
56
|
+
*
|
|
57
|
+
* Forced colors: every paint is token-routed — the rows' background-color
|
|
58
|
+
* and the rects' fill both resolve var(--vf-black), remapped to CanvasText
|
|
59
|
+
* — and the layer keeps forced-color-adjust: none (inherited, so it covers
|
|
60
|
+
* the SVG) so no forced palette repaints the active window's whole signal
|
|
61
|
+
* out from under it.
|
|
62
|
+
*/
|
|
63
|
+
export declare const vfStripes: import("lit").CSSResult;
|
|
64
|
+
/**
|
|
65
|
+
* Dot-grid dither for the utility ("windoid") title bar — the slim bar's
|
|
66
|
+
* counterpart to {@link vfStripes}. Apply the class to an absolutely-positioned
|
|
67
|
+
* layer inset 2px top/bottom and FLUSH left/right: the close-up reference art
|
|
68
|
+
* runs the dots all the way into the side borders (the Windows/ sheet hand-
|
|
69
|
+
* insets them 2px, which the close-up shows is not the bar's own geometry).
|
|
70
|
+
*
|
|
71
|
+
* The layer's own CSS-repeated tile (a crisp 1-bit SVG on the 30-system-px
|
|
72
|
+
* span, overridable via `--vf-dots-pattern`) is the fallback for a window
|
|
73
|
+
* with no declared width. A `vf-window` that knows its width renders the
|
|
74
|
+
* exact fill INTO the layer instead — the whole-surface raster, or a consumer
|
|
75
|
+
* token's placed tile grid (src/tile-grid.ts) — and marks the layer
|
|
76
|
+
* `vf-tile-grid`, which switches the repeat off: the dot art is transparent-
|
|
77
|
+
* grounded, so a drifting CSS-repeated copy underneath would show through
|
|
78
|
+
* between the exactly-placed dots.
|
|
79
|
+
*/
|
|
80
|
+
export declare const vfDots: import("lit").CSSResult;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { tileImage as e, tileRects as t, tileSpan as n, vfTileMaskSize as r, vfTileSize as i } from "./tile.js";
|
|
2
|
+
import { css as a, unsafeCSS as o } from "lit";
|
|
3
|
+
var s = [[
|
|
4
|
+
0,
|
|
5
|
+
0,
|
|
6
|
+
1,
|
|
7
|
+
1,
|
|
8
|
+
"#000000"
|
|
9
|
+
]], c = e(2, 2, t(s)), l = n(2), u = a`
|
|
10
|
+
.vf-stripes {
|
|
11
|
+
position: absolute;
|
|
12
|
+
inset: calc(var(--vf-scale, 1) * 3px) calc(var(--vf-scale, 1) * 1px);
|
|
13
|
+
pointer-events: none;
|
|
14
|
+
@media (forced-colors: active) {
|
|
15
|
+
forced-color-adjust: none;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
.vf-stripes svg {
|
|
19
|
+
display: block;
|
|
20
|
+
position: absolute;
|
|
21
|
+
top: 0;
|
|
22
|
+
left: 0;
|
|
23
|
+
width: 100%;
|
|
24
|
+
height: calc(var(--vf-scale, 1) * 12px);
|
|
25
|
+
}
|
|
26
|
+
.vf-stripes rect {
|
|
27
|
+
fill: var(--vf-black, #000000);
|
|
28
|
+
}
|
|
29
|
+
.vf-stripes span {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
/* Gecko (-moz-appearance) and WebKit (-webkit-backdrop-filter): each
|
|
33
|
+
parses nowhere else — Blink's backdrop-filter is unprefixed. */
|
|
34
|
+
@supports (-moz-appearance: none) or (-webkit-backdrop-filter: blur(1px)) {
|
|
35
|
+
.vf-stripes svg {
|
|
36
|
+
display: none;
|
|
37
|
+
}
|
|
38
|
+
.vf-stripes span {
|
|
39
|
+
display: block;
|
|
40
|
+
position: absolute;
|
|
41
|
+
left: 0;
|
|
42
|
+
right: 0;
|
|
43
|
+
height: calc(var(--vf-scale, 1) * 1px);
|
|
44
|
+
background: var(--vf-black, #000000);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`, d = a`
|
|
48
|
+
.vf-dots {
|
|
49
|
+
position: absolute;
|
|
50
|
+
inset: calc(var(--vf-scale, 1) * 2px) 0;
|
|
51
|
+
background-image: var(--vf-dots-pattern, ${o(c)});
|
|
52
|
+
${i(2)}
|
|
53
|
+
pointer-events: none;
|
|
54
|
+
/* The consumer-token art channel for the placed tile grid. */
|
|
55
|
+
--_vf-tile-image: var(--vf-dots-pattern, ${o(c)});
|
|
56
|
+
}
|
|
57
|
+
.vf-dots.vf-tile-grid {
|
|
58
|
+
background-image: none;
|
|
59
|
+
}
|
|
60
|
+
/* Forced colors preserves url() tiles verbatim, so the dots would stay
|
|
61
|
+
literal black — invisible on a dark high-contrast theme. Repainted as the
|
|
62
|
+
ink token through the same tile as a mask (the vf-grid rules idiom), so
|
|
63
|
+
the windoid bar's signature follows the user's palette. The exact-fill
|
|
64
|
+
children hide here and the span mask takes over — no mask pipeline
|
|
65
|
+
rasterizes exactly at a zoom-minted scale anyway (image-rendering does
|
|
66
|
+
not reach masks), so forced-colors keeps the span approach and its zoom
|
|
67
|
+
caveat, unchanged. */
|
|
68
|
+
@media (forced-colors: active) {
|
|
69
|
+
.vf-dots {
|
|
70
|
+
background-image: none;
|
|
71
|
+
background-color: var(--vf-black, #000);
|
|
72
|
+
mask-image: var(--vf-dots-pattern, ${o(c)});
|
|
73
|
+
${r(2)}
|
|
74
|
+
}
|
|
75
|
+
.vf-dots .vf-tile,
|
|
76
|
+
.vf-dots .vf-tile-raster {
|
|
77
|
+
display: none;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
//#endregion
|
|
82
|
+
export { s as DOT_RECTS, l as DOT_SPAN, d as vfDots, u as vfStripes };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type TileRect } from './tile.js';
|
|
2
|
+
/**
|
|
3
|
+
* The trough's 25% lattice — a 4×2-system-px motif with a dot at (0,0) and
|
|
4
|
+
* (2,1), traced from the UI kit's "Scroll bg" sprite — stated once as rect
|
|
5
|
+
* data. The DOM trough renders it as a whole-surface raster
|
|
6
|
+
* (`tileRaster`, written by `ScrollRailController` — 1-bit at every scale,
|
|
7
|
+
* zoom-minted ones included); the SVG span tile below is the forced-colors
|
|
8
|
+
* mask, which repaints the same art in the remapped ink token.
|
|
9
|
+
*/
|
|
10
|
+
export declare const TROUGH_MOTIF_X = 4;
|
|
11
|
+
export declare const TROUGH_MOTIF_Y = 2;
|
|
12
|
+
export declare const TROUGH_RECTS: readonly TileRect[];
|
|
13
|
+
/**
|
|
14
|
+
* System 7 scroll rails, drawn by the kit as ordinary shadow DOM — the skin
|
|
15
|
+
* for the subtree `renderScrollRail()` (src/scroll-rail.ts) produces. The
|
|
16
|
+
* native scrollbar is hidden, never the native scrolling: the scroller keeps
|
|
17
|
+
* real `overflow` scrolling (wheel, trackpad momentum, keyboard, touch and
|
|
18
|
+
* AT scrolling all stay the platform's), and the rail is synced to it by
|
|
19
|
+
* `ScrollRailController`.
|
|
20
|
+
*
|
|
21
|
+
* Why DOM and not the `::-webkit-scrollbar` skin this replaces: the engine
|
|
22
|
+
* owns themed-scrollbar geometry and quantizes it to whole CSS px — WebKit
|
|
23
|
+
* painted the rail one device pixel adrift (or a CSS px short) whenever the
|
|
24
|
+
* scroller's box edges or width left the whole-CSS-px lattice, which the
|
|
25
|
+
* kit's own odd-system-px insets produce constantly at scale 1.5. A DOM rail
|
|
26
|
+
* is kit art: subpixel layout device-snaps at paint like every other element,
|
|
27
|
+
* and the whole defect class is unrepresentable. It also renders identically
|
|
28
|
+
* in every engine (Firefox included), is assertable headless, and lets the
|
|
29
|
+
* trough adopt the exact tile raster the other dithers use.
|
|
30
|
+
*
|
|
31
|
+
* Geometry (system px) — the classic 16px cell, of which the outermost line
|
|
32
|
+
* is the component's own 1px frame: the rail element is the 15 inside it —
|
|
33
|
+
* a 1px divider on the content side (the rail's own border) plus the 14px
|
|
34
|
+
* channel. Arrow cells are 15 long (14 interior + the 1px divider facing the
|
|
35
|
+
* track); their glyphs are the 16-unit sprites windowed to the 14×14
|
|
36
|
+
* interior (`viewBox="1 1 14 14"`), since the sprite's outer ring is exactly
|
|
37
|
+
* the frame/divider lines the borders draw. The thumb is a fixed 16px white
|
|
38
|
+
* box spanning the channel, its border reading as inset 1px from each
|
|
39
|
+
* channel rail over its extent. The component supplies the outer frame as a
|
|
40
|
+
* real border and lays the rail out as a sibling of the scroller — AFTER it,
|
|
41
|
+
* so the state selectors below can reach the rail from the scroller's
|
|
42
|
+
* attributes.
|
|
43
|
+
*
|
|
44
|
+
* States, keyed off the attributes `ScrollStateController` writes on the
|
|
45
|
+
* scroller (now styling real elements, so there is no scrollbar-pseudo
|
|
46
|
+
* re-resolution caveat in any engine):
|
|
47
|
+
* - `data-overflow-{x,y}="false"` — idle rail: arrows stay drawn on a white
|
|
48
|
+
* channel, divider stays, no dither, no thumb — System 7 drew an active
|
|
49
|
+
* window's no-overflow bar as arrows on an empty channel, and a scroller
|
|
50
|
+
* outside a window always counts as active;
|
|
51
|
+
* - `data-window-inactive` — both axes blanked to the bare rail, arrows
|
|
52
|
+
* included, regardless of overflow (the HIG's inactive-window treatment);
|
|
53
|
+
* - `data-degenerate` (written by `ScrollRailController` when the track is
|
|
54
|
+
* too short) — `"thumb"` drops the thumb, `"rail"` drops the trough and
|
|
55
|
+
* arrows too, as the classic Control Manager did.
|
|
56
|
+
* A rail used without the controllers carries no such attributes, so none of
|
|
57
|
+
* these rules match and the full skin renders — the managed behavior stays
|
|
58
|
+
* strictly opt-in.
|
|
59
|
+
*
|
|
60
|
+
* FORCED COLORS: the rails, thumb, channel and frame land on the user's pair
|
|
61
|
+
* through the vfBase token remap like every other element. The arrows are
|
|
62
|
+
* inline `currentColor` SVG now, so they re-ink with the palette (the old
|
|
63
|
+
* `::-webkit-scrollbar` skin's one genuine residual — mask-image is ignored
|
|
64
|
+
* on scrollbar pseudos — dies here). The trough raster keeps literal ink, so
|
|
65
|
+
* it is hidden and the trough repaints as the ink token masked by the same
|
|
66
|
+
* art (the vfDots idiom; the span mask keeps the zoom caveat every masked
|
|
67
|
+
* surface has, an accepted residual).
|
|
68
|
+
*/
|
|
69
|
+
export declare const vfScrollRail: import("lit").CSSResult;
|