vintage-frames 0.13.0 → 0.14.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/custom-elements.json +8 -8
- package/dist/components/vf-checkbox.d.ts +6 -5
- package/dist/components/vf-checkbox.js +41 -37
- package/dist/components/vf-container.d.ts +11 -13
- package/dist/components/vf-container.js +24 -12
- package/dist/components/vf-fieldset.js +30 -22
- package/dist/components/vf-icon.js +55 -55
- package/dist/components/vf-list.js +30 -29
- package/dist/components/vf-menu.js +24 -22
- package/dist/components/vf-number-field.js +32 -30
- package/dist/components/vf-progress-bar.js +28 -29
- package/dist/components/vf-radio.js +3 -4
- package/dist/components/vf-scroll-area.js +27 -26
- package/dist/components/vf-select.js +108 -90
- package/dist/components/vf-separator.d.ts +5 -5
- package/dist/components/vf-separator.js +36 -10
- package/dist/components/vf-swatch.js +47 -45
- package/dist/components/vf-text-area.js +37 -35
- package/dist/components/vf-text-field.js +20 -18
- package/dist/components/vf-window.js +92 -72
- package/dist/index.d.ts +10 -1
- package/dist/index.js +60 -59
- package/dist/styles/base.d.ts +3 -1
- package/dist/styles/recipes/field.d.ts +10 -6
- package/dist/styles/recipes/field.js +8 -7
- package/dist/styles/recipes/focus.d.ts +7 -3
- package/dist/styles/recipes/rule.d.ts +11 -8
- package/dist/styles/recipes/rule.js +31 -13
- package/dist/styles/recipes/scroll-rail.d.ts +7 -6
- package/dist/styles/recipes/scroll-rail.js +18 -18
- package/dist/styles/recipes/shadow.d.ts +10 -6
- package/dist/styles/recipes/shadow.js +4 -2
- package/dist/styles/recipes/stroke.d.ts +85 -0
- package/dist/styles/recipes/stroke.js +53 -0
- package/dist/styles/recipes/surface.d.ts +8 -4
- package/dist/styles/recipes/surface.js +23 -17
- package/dist/styles/recipes/title-bar.d.ts +7 -0
- package/dist/styles/recipes/title-bar.js +25 -22
- package/dist/styles/recipes/toggle.js +3 -3
- package/dist/zoom.d.ts +9 -9
- package/docs/SPEC.md +23 -22
- package/editor/vscode.html-custom-data.json +4 -4
- package/editor/web-types.json +7 -7
- package/package.json +1 -1
|
@@ -64,13 +64,17 @@ export declare const vfFocus: import("lit").CSSResult;
|
|
|
64
64
|
* the box continues 6px past it (2px half-leading from vfBase's 1.25 line box
|
|
65
65
|
* over the 16px em, plus the face's 4px descent): 6 − 2 = 4.
|
|
66
66
|
* - `-2px` is a well whose ink runs to its own bottom edge — the radio's circle,
|
|
67
|
-
* a field's wrapper
|
|
68
|
-
*
|
|
67
|
+
* a field's wrapper, a box framed by a stroke (vf-checkbox), whose line is
|
|
68
|
+
* inside the padding box — putting the rule in the second row below it.
|
|
69
69
|
* - past that, the rule also clears a hard shadow, which is ink no box the
|
|
70
|
-
* pseudo-element can size to contains: `-
|
|
70
|
+
* pseudo-element can size to contains: `-3px` for vf-select's 1px one, and
|
|
71
71
|
* for vf-swatch an offset that composes `--vf-shadow-offset` rather than
|
|
72
72
|
* hard-coding a depth its consumer can retheme.
|
|
73
73
|
*
|
|
74
|
+
* Under forced colors a stroke is a border again and the padding box sits
|
|
75
|
+
* inside it, so a stroked carrier states its offset and sides with
|
|
76
|
+
* `vfStrokeInset`, which adds the stroke back there.
|
|
77
|
+
*
|
|
74
78
|
* Drawn in `currentColor`, so it inverts with the label on a pressed face.
|
|
75
79
|
*/
|
|
76
80
|
export declare const vfFocusUnderline: import("lit").CSSResult;
|
|
@@ -9,15 +9,18 @@ export type RuleEdge = (typeof RULE_EDGES)[number];
|
|
|
9
9
|
* floor is `.vf-rule-bottom`, a window's status strip's ceiling is
|
|
10
10
|
* `.vf-rule-top`, and `vf-container rule="…"` takes the edges by name.
|
|
11
11
|
*
|
|
12
|
-
* A
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* A stroke (see {@link vfStrokeDecls}), inside the box's own `border-box`
|
|
13
|
+
* size (vfBase): the rule's row is padding and an inset shadow paints it
|
|
14
|
+
* black, so it is one system px at every density and zoom, and in-flow
|
|
15
|
+
* content begins inside it. Children placed against the box, and percentage
|
|
16
|
+
* fills, measure from the box's outer edge; a component whose contract puts
|
|
17
|
+
* them inside the rule gives them an inner box to lay out in (vf-container
|
|
18
|
+
* uses its slot). Paints in `--vf-black`, and under forced colors turns back
|
|
19
|
+
* into a border, so it remaps with the rest of the ink.
|
|
18
20
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
+
* The classes compose on one element: each edge's shadow goes through its
|
|
22
|
+
* own private property and one rule paints all four, so the classes own the
|
|
23
|
+
* element's `box-shadow`, and its padding on their edges.
|
|
21
24
|
*
|
|
22
25
|
* `npm run verify:rule` asserts a container's rule against the menu bar's.
|
|
23
26
|
*/
|
|
@@ -1,32 +1,50 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { STROKE_FORCED_COLORS as e, strokeBorder as t, strokeEdgeShadow as n, strokePadding as r } from "./stroke.js";
|
|
2
|
+
import { css as i, unsafeCSS as a } from "lit";
|
|
2
3
|
//#region src/styles/recipes/rule.ts
|
|
3
|
-
var
|
|
4
|
+
var o = [
|
|
4
5
|
"top",
|
|
5
6
|
"right",
|
|
6
7
|
"bottom",
|
|
7
8
|
"left"
|
|
8
|
-
],
|
|
9
|
+
], s = (e) => a(`
|
|
10
|
+
--_vf-rule-${e}: ${n(e, 1)};
|
|
11
|
+
padding-${e}: ${r(0, 1)};
|
|
12
|
+
border-${e}: ${t(1)};
|
|
13
|
+
`), c = i`
|
|
14
|
+
.vf-rule-top,
|
|
15
|
+
.vf-rule-right,
|
|
16
|
+
.vf-rule-bottom,
|
|
17
|
+
.vf-rule-left {
|
|
18
|
+
--_vf-stroke-ink: var(--vf-black, #000);
|
|
19
|
+
--_vf-rule-top: 0 0 transparent;
|
|
20
|
+
--_vf-rule-right: 0 0 transparent;
|
|
21
|
+
--_vf-rule-bottom: 0 0 transparent;
|
|
22
|
+
--_vf-rule-left: 0 0 transparent;
|
|
23
|
+
box-shadow: var(--_vf-rule-top), var(--_vf-rule-right), var(--_vf-rule-bottom),
|
|
24
|
+
var(--_vf-rule-left);
|
|
25
|
+
${a(e)}
|
|
26
|
+
}
|
|
9
27
|
.vf-rule-top {
|
|
10
|
-
|
|
28
|
+
${s("top")}
|
|
11
29
|
}
|
|
12
30
|
.vf-rule-right {
|
|
13
|
-
|
|
31
|
+
${s("right")}
|
|
14
32
|
}
|
|
15
33
|
.vf-rule-bottom {
|
|
16
|
-
|
|
34
|
+
${s("bottom")}
|
|
17
35
|
}
|
|
18
36
|
.vf-rule-left {
|
|
19
|
-
|
|
37
|
+
${s("left")}
|
|
20
38
|
}
|
|
21
39
|
`;
|
|
22
|
-
function
|
|
40
|
+
function l(e) {
|
|
23
41
|
if (e == null) return [];
|
|
24
|
-
let t = e.trim().split(/\s+/).filter(Boolean),
|
|
25
|
-
for (let e of
|
|
26
|
-
return
|
|
42
|
+
let t = e.trim().split(/\s+/).filter(Boolean), n = new Set(t);
|
|
43
|
+
for (let e of n) if (!o.includes(e)) return null;
|
|
44
|
+
return o.filter((e) => n.has(e));
|
|
27
45
|
}
|
|
28
|
-
function
|
|
46
|
+
function u(e) {
|
|
29
47
|
return e.map((e) => `vf-rule-${e}`).join(" ");
|
|
30
48
|
}
|
|
31
49
|
//#endregion
|
|
32
|
-
export {
|
|
50
|
+
export { o as RULE_EDGES, l as parseRule, u as ruleClasses, c as vfRule };
|
|
@@ -28,16 +28,17 @@ export declare const TROUGH: import("../../patterns.js").PatternMotif;
|
|
|
28
28
|
*
|
|
29
29
|
* Geometry (system px) — the classic 16px cell, of which the outermost line
|
|
30
30
|
* is the component's own 1px frame: the rail element is the 15 inside it —
|
|
31
|
-
* a 1px divider on the content side (the rail's own
|
|
31
|
+
* a 1px divider on the content side (the rail's own stroke) plus the 14px
|
|
32
32
|
* channel. Arrow cells are 15 long (14 interior + the 1px divider facing the
|
|
33
33
|
* track); their glyphs are the 16-unit sprites windowed to the 14×14
|
|
34
34
|
* interior (`viewBox="1 1 14 14"`), since the sprite's outer ring is exactly
|
|
35
|
-
* the frame/divider lines the
|
|
36
|
-
* box spanning the channel, its
|
|
35
|
+
* the frame/divider lines the strokes draw. The thumb is a fixed 16px white
|
|
36
|
+
* box spanning the channel, its stroke reading as inset 1px from each
|
|
37
37
|
* channel rail over its extent. The component supplies the outer frame as a
|
|
38
|
-
*
|
|
39
|
-
* so the state selectors below can reach the rail from the
|
|
40
|
-
* attributes.
|
|
38
|
+
* stroke of its own and lays the rail out as a sibling of the scroller —
|
|
39
|
+
* AFTER it, so the state selectors below can reach the rail from the
|
|
40
|
+
* scroller's attributes. Every line here is a stroke (vfStrokeDecls):
|
|
41
|
+
* padding holds it and an inset shadow paints it.
|
|
41
42
|
*
|
|
42
43
|
* States, keyed off the attributes `ScrollStateController` writes on the
|
|
43
44
|
* scroller (now styling real elements, so there is no scrollbar-pseudo
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { tileImage as e, tileRects as t, vfTileMaskSize as n } from "./tile.js";
|
|
2
2
|
import { vfRepeatTileSize as r } from "../../tile-grid.js";
|
|
3
3
|
import { PATTERNS as i, patternMotif as a } from "../../patterns.js";
|
|
4
|
-
import {
|
|
4
|
+
import { vfStrokeDecls as o } from "./stroke.js";
|
|
5
|
+
import { css as s, unsafeCSS as c } from "lit";
|
|
5
6
|
//#region src/styles/recipes/scroll-rail.ts
|
|
6
|
-
var
|
|
7
|
+
var l = a(i["gray-25"]), u = e(l.width, l.height, t(l.rects)), d = s`
|
|
7
8
|
/* Hide the native bar, keep the native scrolling. Both lines ship:
|
|
8
9
|
scrollbar-width reaches Chromium 121+/Firefox/Safari 18.2+, the pseudo
|
|
9
10
|
covers older WebKit — the last scrollbar pseudo left in the kit.
|
|
@@ -37,7 +38,7 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
37
38
|
calc(var(--vf-scale, 1) * 15px)
|
|
38
39
|
1fr
|
|
39
40
|
calc(var(--vf-scale, 1) * 15px);
|
|
40
|
-
|
|
41
|
+
${o({ edges: ["left"] })}
|
|
41
42
|
}
|
|
42
43
|
.vf-rail--horizontal {
|
|
43
44
|
height: calc(var(--vf-scale, 1) * 15px);
|
|
@@ -45,7 +46,7 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
45
46
|
calc(var(--vf-scale, 1) * 15px)
|
|
46
47
|
1fr
|
|
47
48
|
calc(var(--vf-scale, 1) * 15px);
|
|
48
|
-
|
|
49
|
+
${o({ edges: ["top"] })}
|
|
49
50
|
}
|
|
50
51
|
/* Explicit placement, so hiding the arrows (inactive-window/degenerate
|
|
51
52
|
states) never reflows the track into an arrow cell — its box holds still
|
|
@@ -70,11 +71,11 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
/* Arrow cells: white boxes carrying only the 1px divider that faces the
|
|
73
|
-
track — the frame edges are the component's
|
|
74
|
-
rail's own divider — so no line ever doubles to 2px. Each cell's
|
|
74
|
+
track — the frame edges are the component's stroke, the content edge the
|
|
75
|
+
rail's own divider — so no line ever doubles to 2px. Each cell's content
|
|
75
76
|
box is by construction the sprite's 14×14 interior, wherever the cell
|
|
76
77
|
sits (flush to the frame, or against the corner cell), so the glyph
|
|
77
|
-
lands at the
|
|
78
|
+
lands at the content origin with no per-variant offsets. */
|
|
78
79
|
.vf-rail-button {
|
|
79
80
|
display: grid;
|
|
80
81
|
place-items: start;
|
|
@@ -82,16 +83,16 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
82
83
|
overflow: hidden;
|
|
83
84
|
}
|
|
84
85
|
.vf-rail--vertical .vf-rail-button--decrement {
|
|
85
|
-
|
|
86
|
+
${o({ edges: ["bottom"] })}
|
|
86
87
|
}
|
|
87
88
|
.vf-rail--vertical .vf-rail-button--increment {
|
|
88
|
-
|
|
89
|
+
${o({ edges: ["top"] })}
|
|
89
90
|
}
|
|
90
91
|
.vf-rail--horizontal .vf-rail-button--decrement {
|
|
91
|
-
|
|
92
|
+
${o({ edges: ["right"] })}
|
|
92
93
|
}
|
|
93
94
|
.vf-rail--horizontal .vf-rail-button--increment {
|
|
94
|
-
|
|
95
|
+
${o({ edges: ["left"] })}
|
|
95
96
|
}
|
|
96
97
|
.vf-rail-arrow {
|
|
97
98
|
display: block;
|
|
@@ -130,7 +131,7 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
130
131
|
pointer-events: none;
|
|
131
132
|
}
|
|
132
133
|
/* The fixed System 7 thumb (never proportional): a white 16px box spanning
|
|
133
|
-
the channel. Its
|
|
134
|
+
the channel. Its stroke reads as inset 1px from each channel rail — the
|
|
134
135
|
divider and the frame — over its extent; the controller writes its
|
|
135
136
|
travel as a whole-system-px translate. */
|
|
136
137
|
.vf-rail-thumb {
|
|
@@ -138,7 +139,7 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
138
139
|
top: 0;
|
|
139
140
|
left: 0;
|
|
140
141
|
background: var(--vf-scrollbar-thumb, #ffffff);
|
|
141
|
-
|
|
142
|
+
${o()}
|
|
142
143
|
}
|
|
143
144
|
.vf-rail--vertical .vf-rail-thumb {
|
|
144
145
|
width: 100%;
|
|
@@ -161,8 +162,7 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
161
162
|
width: calc(var(--vf-scale, 1) * 15px);
|
|
162
163
|
height: calc(var(--vf-scale, 1) * 15px);
|
|
163
164
|
background: var(--vf-white, #fff);
|
|
164
|
-
|
|
165
|
-
border-left: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
|
|
165
|
+
${o({ edges: ["top", "left"] })}
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
/* ── Always-a-rail (driven by ScrollStateController) ─────────────────────
|
|
@@ -208,10 +208,10 @@ var c = a(i["gray-25"]), l = e(c.width, c.height, t(c.rects)), u = o`
|
|
|
208
208
|
.vf-rail-trough {
|
|
209
209
|
background-image: none;
|
|
210
210
|
background-color: var(--vf-black, #000);
|
|
211
|
-
mask-image: ${
|
|
212
|
-
${n(
|
|
211
|
+
mask-image: ${c(u)};
|
|
212
|
+
${n(l.width, l.height)}
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
`;
|
|
216
216
|
//#endregion
|
|
217
|
-
export {
|
|
217
|
+
export { l as TROUGH, d as vfScrollRail };
|
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
* with no blur and no spread, System 7's only depth cue. The offset is
|
|
4
4
|
* tokenized via `--vf-shadow-offset` and scales with `--vf-scale`.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* {
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
6
|
+
* The shadow value, for a list: a stroked surface passes it to
|
|
7
|
+
* `vfStrokeDecls({ shadows: vfHardShadow })`, which paints it after the
|
|
8
|
+
* stroke. Every raised surface in the kit does — {@link vfPanel} (menus,
|
|
9
|
+
* popups) and {@link vfChromeFrame} (window frames). One value, so the kit
|
|
10
|
+
* can't grow two shadows.
|
|
11
|
+
*/
|
|
12
|
+
export declare const vfHardShadow: import("lit").CSSResult;
|
|
13
|
+
/**
|
|
14
|
+
* {@link vfHardShadow} as the whole `box-shadow` declaration, for a box that
|
|
15
|
+
* casts the shadow and draws no stroke.
|
|
12
16
|
*/
|
|
13
17
|
export declare const vfHardShadowDecls: import("lit").CSSResult;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { unsafeCSS as e } from "lit";
|
|
2
2
|
//#region src/styles/recipes/shadow.ts
|
|
3
|
-
var t = e("
|
|
3
|
+
var t = e("calc(var(--vf-scale, 1) * var(--vf-shadow-offset, 2px))\n calc(var(--vf-scale, 1) * var(--vf-shadow-offset, 2px)) 0 0\n var(--vf-black, #000)"), n = e(`
|
|
4
|
+
box-shadow: ${t};
|
|
5
|
+
`);
|
|
4
6
|
//#endregion
|
|
5
|
-
export { t as vfHardShadowDecls };
|
|
7
|
+
export { t as vfHardShadow, n as vfHardShadowDecls };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type CSSResult } from 'lit';
|
|
2
|
+
import type { RuleEdge } from './rule.js';
|
|
3
|
+
/** One to four values in shorthand order, as top/right/bottom/left. */
|
|
4
|
+
type Sides<T> = T | readonly T[];
|
|
5
|
+
/** The padding under a stroked edge: the element's own plus the stroke's. */
|
|
6
|
+
export declare function strokePadding(own: number | string, width: number): string;
|
|
7
|
+
/** The border a stroked edge becomes under forced colors; 0 wide otherwise. */
|
|
8
|
+
export declare function strokeBorder(width: number): string;
|
|
9
|
+
/** The inset shadow that paints one edge's stroke. */
|
|
10
|
+
export declare function strokeEdgeShadow(edge: RuleEdge, width: number): string;
|
|
11
|
+
/** The forced-colors switch every stroked element carries. */
|
|
12
|
+
export declare const STROKE_FORCED_COLORS = "@media (forced-colors: active) {\n --_vf-stroke-pad: 0;\n }";
|
|
13
|
+
/**
|
|
14
|
+
* The inset shadow of a stroke `width` system px wide on all four edges — the
|
|
15
|
+
* value to restate when only the painted width changes, as vf-checkbox's
|
|
16
|
+
* press does. Reads the ink and forced-colors switch the element's
|
|
17
|
+
* {@link vfStrokeDecls} declares.
|
|
18
|
+
*/
|
|
19
|
+
export declare function vfStrokeShadow(width?: number): CSSResult;
|
|
20
|
+
/** The options of {@link vfStrokeDecls}. */
|
|
21
|
+
export interface VfStrokeOptions {
|
|
22
|
+
/** The stroked edges. Default all four. */
|
|
23
|
+
edges?: readonly RuleEdge[];
|
|
24
|
+
/**
|
|
25
|
+
* The stroke's width in whole system px, one to four values in shorthand
|
|
26
|
+
* order. Default 1.
|
|
27
|
+
*/
|
|
28
|
+
width?: Sides<number>;
|
|
29
|
+
/**
|
|
30
|
+
* The element's own padding, in system px, one to four values in shorthand
|
|
31
|
+
* order; each stroked edge adds its stroke. A value is a number or a
|
|
32
|
+
* system-px CSS length (`'var(--vf-select-gutter, 16px)'`). Omitted, the
|
|
33
|
+
* declarations set padding on the stroked edges alone, to the stroke.
|
|
34
|
+
*/
|
|
35
|
+
padding?: Sides<number | string>;
|
|
36
|
+
/**
|
|
37
|
+
* More shadows, painted with the stroke: the hard drop shadow
|
|
38
|
+
* ({@link vfHardShadow}), a white ring. The stroke comes first in the list.
|
|
39
|
+
*/
|
|
40
|
+
shadows?: string | CSSResult;
|
|
41
|
+
/** The stroke's color. Default `var(--vf-black, #000)`. */
|
|
42
|
+
ink?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A 1-bit stroke that isn't a line width. The declarations for a box whose
|
|
46
|
+
* edges carry a black line of whole system px — every frame, well, rule and
|
|
47
|
+
* box in the kit — for interpolating into the box's rule:
|
|
48
|
+
* `.card { ${vfStrokeDecls({ padding: [4, 8] })} }`.
|
|
49
|
+
*
|
|
50
|
+
* Safari rounds a border width to device px before it applies page zoom, so a
|
|
51
|
+
* `border` of `calc(var(--vf-scale, 1) * 1px)` draws thinner than the art
|
|
52
|
+
* around it at most zoom levels, and moves everything inside the box off the
|
|
53
|
+
* device grid. Padding and box-shadow lengths are not rounded that way. So the
|
|
54
|
+
* stroke's space is padding on each stroked edge, added to the element's own,
|
|
55
|
+
* and the black is an inset `box-shadow`, with `shadows` after it in the same
|
|
56
|
+
* list. Both land on whole device px at every zoom.
|
|
57
|
+
*
|
|
58
|
+
* What changes from a border:
|
|
59
|
+
* - The declarations own `padding` on the stroked edges (on all four, when
|
|
60
|
+
* `padding` is passed) and `box-shadow`. Pass the element's own padding and
|
|
61
|
+
* shadows here; a later `padding` or `box-shadow` on the element replaces
|
|
62
|
+
* the stroke's.
|
|
63
|
+
* - A child placed against the box measures from its outer edge. Offset it by
|
|
64
|
+
* the stroke with {@link vfStrokeInset}.
|
|
65
|
+
* - An `overflow: hidden` box clips at its outer edge, so its content can
|
|
66
|
+
* paint over the stroke. Clip on an inner element instead.
|
|
67
|
+
* - Forced colors paints no `box-shadow`, so there each stroke is a border
|
|
68
|
+
* again and the padding is the element's own: the same box a border draws.
|
|
69
|
+
*
|
|
70
|
+
* The color goes through a private property the declarations set, so pass a
|
|
71
|
+
* `var()` as `ink` to change it from a state rule without restating the
|
|
72
|
+
* shadow list.
|
|
73
|
+
*/
|
|
74
|
+
export declare function vfStrokeDecls(options?: VfStrokeOptions): CSSResult;
|
|
75
|
+
/**
|
|
76
|
+
* A length `base` system px in from a stroke's inner edge, measured from the
|
|
77
|
+
* box's outer edge, on an edge carrying `stroke` system px of it (see
|
|
78
|
+
* {@link vfStrokeDecls}): the inset for a child placed against a stroked box
|
|
79
|
+
* (`right: ${vfStrokeInset(0)}` is flush inside a 1px frame), or a padding
|
|
80
|
+
* that restates the stroke's (`padding: ${vfStrokeInset(0)} ${vfStrokeInset(6)}`).
|
|
81
|
+
* `base` is a number or a system-px CSS length. Under forced colors, where
|
|
82
|
+
* the stroke is a border, it is `base`.
|
|
83
|
+
*/
|
|
84
|
+
export declare function vfStrokeInset(base: number | string, stroke?: number): CSSResult;
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { unsafeCSS as e } from "lit";
|
|
2
|
+
//#region src/styles/recipes/stroke.ts
|
|
3
|
+
var t = [
|
|
4
|
+
"top",
|
|
5
|
+
"right",
|
|
6
|
+
"bottom",
|
|
7
|
+
"left"
|
|
8
|
+
], n = "var(--_vf-stroke-pad, 1)", r = "var(--_vf-stroke-ink)";
|
|
9
|
+
function i(e) {
|
|
10
|
+
let t = Array.isArray(e) ? e : [e], n = t[0], r = t[1] ?? n;
|
|
11
|
+
return [
|
|
12
|
+
n,
|
|
13
|
+
r,
|
|
14
|
+
t[2] ?? n,
|
|
15
|
+
t[3] ?? r
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
var a = (e) => typeof e == "number" ? `${e}px` : e, o = (e) => `calc(var(--vf-scale, 1) * ${e}px * ${n})`;
|
|
19
|
+
function s(e, t) {
|
|
20
|
+
return e === 0 ? o(t) : `calc(var(--vf-scale, 1) * (${a(e)} + ${t}px * ${n}))`;
|
|
21
|
+
}
|
|
22
|
+
function c(e) {
|
|
23
|
+
return `calc(var(--vf-scale, 1) * ${e}px * (1 - ${n})) solid ${r}`;
|
|
24
|
+
}
|
|
25
|
+
function l(e, t) {
|
|
26
|
+
let i = (e) => `calc(var(--vf-scale, 1) * ${e * t}px * ${n})`;
|
|
27
|
+
switch (e) {
|
|
28
|
+
case "top": return `inset 0 ${i(1)} 0 0 ${r}`;
|
|
29
|
+
case "right": return `inset ${i(-1)} 0 0 0 ${r}`;
|
|
30
|
+
case "bottom": return `inset 0 ${i(-1)} 0 0 ${r}`;
|
|
31
|
+
case "left": return `inset ${i(1)} 0 0 0 ${r}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
var u = "@media (forced-colors: active) {\n --_vf-stroke-pad: 0;\n }";
|
|
35
|
+
function d(t = 1) {
|
|
36
|
+
return e(`inset 0 0 0 ${o(t)} ${r}`);
|
|
37
|
+
}
|
|
38
|
+
function f(n = {}) {
|
|
39
|
+
let r = new Set(n.edges ?? t), o = i(n.width ?? 1), f = i(n.padding ?? 0), p = t.map((e, t) => r.has(e) ? o[t] : 0), m = p.every((e) => e > 0 && e === p[0]), h = [`--_vf-stroke-ink: ${n.ink ?? "var(--vf-black, #000)"};`], g = [];
|
|
40
|
+
return t.forEach((e, t) => {
|
|
41
|
+
let r = p[t];
|
|
42
|
+
if (!r) {
|
|
43
|
+
n.padding !== void 0 && h.push(`padding-${e}: calc(var(--vf-scale, 1) * ${a(f[t])});`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
h.push(`padding-${e}: ${s(f[t], r)};`), h.push(`border-${e}: ${c(r)};`), m || g.push(l(e, r));
|
|
47
|
+
}), m && g.push(String(d(p[0]))), n.shadows && g.push(String(n.shadows)), h.push(`box-shadow: ${g.length ? g.join(", ") : "none"};`), h.push(u), e(h.join("\n "));
|
|
48
|
+
}
|
|
49
|
+
function p(t, n = 1) {
|
|
50
|
+
return e(s(t, n));
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { u as STROKE_FORCED_COLORS, c as strokeBorder, l as strokeEdgeShadow, s as strokePadding, f as vfStrokeDecls, p as vfStrokeInset, d as vfStrokeShadow };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Panel recipe for menus and popups: white face, 1px black
|
|
2
|
+
* Panel recipe for menus and popups: white face, 1px black frame, hard
|
|
3
3
|
* offset shadow.
|
|
4
4
|
*/
|
|
5
5
|
export declare const vfPanel: import("lit").CSSResult;
|
|
6
6
|
/**
|
|
7
7
|
* Chrome-frame recipe for the desktop window (vf-window): the same white
|
|
8
|
-
* face, 1px black
|
|
8
|
+
* face, 1px black frame and hard offset shadow as {@link vfPanel}. Apply
|
|
9
9
|
* `.vf-frame` to the outer frame element.
|
|
10
10
|
*
|
|
11
11
|
* Skin only — the component adds its own layout (a full-size flex column: the
|
|
@@ -14,7 +14,7 @@ export declare const vfPanel: import("lit").CSSResult;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare const vfChromeFrame: import("lit").CSSResult;
|
|
16
16
|
/**
|
|
17
|
-
* The classic modal-dialog (dBoxProc) frame: 1px outer
|
|
17
|
+
* The classic modal-dialog (dBoxProc) frame: 1px outer rule, 2px white gap,
|
|
18
18
|
* 2px inner band — and NO drop shadow, per the `Windows/modal dialog.png`
|
|
19
19
|
* reference. System 7's alert box drew the
|
|
20
20
|
* *mirror* trace (2px outer, 2px gap, 1px inner rule, with the hard shadow) —
|
|
@@ -30,10 +30,14 @@ export declare const vfChromeFrame: import("lit").CSSResult;
|
|
|
30
30
|
* six stripes / 3 white rows, the title patch's 7px margins) sits directly
|
|
31
31
|
* under the outer rule, inset 2px at either end so its stripes keep the same
|
|
32
32
|
* 2px of white from the outer rule that the inner band keeps; the bar's own
|
|
33
|
-
* 1px rule plus the inner box's 1px top
|
|
33
|
+
* 1px rule plus the inner box's 1px top stroke make the 2px band its floor,
|
|
34
34
|
* which then continues down both sides and along the bottom as the band
|
|
35
35
|
* around the body. No shadow anywhere. Put the `.vf-title-bar` between the
|
|
36
36
|
* two elements, as the first child of `.vf-modal-frame`, and the three rules
|
|
37
37
|
* below do the rest.
|
|
38
|
+
*
|
|
39
|
+
* Both lines are strokes ({@link vfStrokeDecls}): padding holds their space
|
|
40
|
+
* and an inset shadow paints them, so the recipe owns both elements' padding
|
|
41
|
+
* and box-shadow.
|
|
38
42
|
*/
|
|
39
43
|
export declare const vfModalFrame: import("lit").CSSResult;
|
|
@@ -1,42 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { vfHardShadow as e } from "./shadow.js";
|
|
2
|
+
import { vfStrokeDecls as t, vfStrokeInset as n } from "./stroke.js";
|
|
3
|
+
import { css as r, unsafeCSS as i } from "lit";
|
|
3
4
|
//#region src/styles/recipes/surface.ts
|
|
4
|
-
var
|
|
5
|
+
var a = i(`
|
|
5
6
|
background: var(--vf-white, #fff);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`), i = t`
|
|
7
|
+
${t({ shadows: e })}
|
|
8
|
+
`), o = r`
|
|
9
9
|
.vf-panel {
|
|
10
|
-
${
|
|
10
|
+
${a}
|
|
11
11
|
}
|
|
12
|
-
`,
|
|
12
|
+
`, s = r`
|
|
13
13
|
.vf-frame {
|
|
14
|
-
${
|
|
14
|
+
${a}
|
|
15
15
|
}
|
|
16
|
-
`,
|
|
16
|
+
`, c = r`
|
|
17
17
|
.vf-modal-frame {
|
|
18
18
|
background: var(--vf-white, #fff);
|
|
19
|
-
|
|
19
|
+
${t()}
|
|
20
20
|
}
|
|
21
21
|
.vf-modal-frame-inner {
|
|
22
22
|
margin: calc(var(--vf-scale, 1) * 2px);
|
|
23
|
-
|
|
23
|
+
${t({ width: 2 })}
|
|
24
24
|
}
|
|
25
25
|
/* The bar set into the frame: 2px in from the outer rule at either end, its
|
|
26
26
|
stripes flush to the bar's own edge (vfStripes' 1px side inset is the
|
|
27
|
-
window frame's buffer — here the frame's gap is that buffer).
|
|
27
|
+
window frame's buffer — here the frame's gap is that buffer). The bottom
|
|
28
|
+
inset counts the bar's rule, which is padding (vfTitleBar). */
|
|
28
29
|
.vf-modal-frame > .vf-title-bar {
|
|
29
30
|
margin: 0 calc(var(--vf-scale, 1) * 2px);
|
|
30
31
|
}
|
|
31
32
|
.vf-modal-frame > .vf-title-bar .vf-stripes {
|
|
32
|
-
inset: calc(var(--vf-scale, 1) * 3px) 0;
|
|
33
|
+
inset: calc(var(--vf-scale, 1) * 3px) 0 ${n(3)};
|
|
33
34
|
}
|
|
34
|
-
/* Under a bar, the inner box's top
|
|
35
|
+
/* Under a bar, the inner box's top stroke is the second row of the band —
|
|
35
36
|
the bar's 1px rule is the first — and there is no gap row between. */
|
|
36
37
|
.vf-modal-frame > .vf-title-bar + .vf-modal-frame-inner {
|
|
37
38
|
margin-top: 0;
|
|
38
|
-
|
|
39
|
+
${t({ width: [
|
|
40
|
+
1,
|
|
41
|
+
2,
|
|
42
|
+
2,
|
|
43
|
+
2
|
|
44
|
+
] })}
|
|
39
45
|
}
|
|
40
46
|
`;
|
|
41
47
|
//#endregion
|
|
42
|
-
export {
|
|
48
|
+
export { s as vfChromeFrame, c as vfModalFrame, o as vfPanel };
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
* drag handle, vf-window's only when `[movable]` — suppressing touch scrolling
|
|
33
33
|
* on a bar that can't be dragged would be a real behavior change, so each
|
|
34
34
|
* component keeps that one declaration under its own selector.
|
|
35
|
+
*
|
|
36
|
+
* The rule is a stroke ({@link vfStrokeDecls}): the bottom row is padding, so
|
|
37
|
+
* the texture layers placed inside the bar count it in their bottom insets.
|
|
35
38
|
*/
|
|
36
39
|
export declare const vfTitleBar: import("lit").CSSResult;
|
|
37
40
|
/**
|
|
@@ -45,5 +48,9 @@ export declare const vfTitleBar: import("lit").CSSResult;
|
|
|
45
48
|
* Geometry is the standard 18px bar's; vf-window's utility variant overrides
|
|
46
49
|
* the sizes under its own selector. Host-state rules (hiding widgets on an
|
|
47
50
|
* inactive window) stay with the component — a dialog has no inactive state.
|
|
51
|
+
*
|
|
52
|
+
* Each box's line is a stroke ({@link vfStrokeDecls}), its white patch ring
|
|
53
|
+
* the next shadow in the same list. State rules recolor the line through
|
|
54
|
+
* `--_vf-stroke-ink`.
|
|
48
55
|
*/
|
|
49
56
|
export declare const vfWindowWidgets: import("lit").CSSResult;
|