@stealthscale/plugin-theming 0.0.0-stage → 0.2.1
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 +135 -2
- package/dist/accessibility-Dg5Dh35o.js +409 -0
- package/dist/attributes-vx1W0PiK.js +26 -0
- package/dist/breakpoints-CJjhy79u.js +83 -0
- package/dist/code-DcoH6hCX.js +69 -0
- package/dist/conditions-CjjQwqro.js +338 -0
- package/dist/corners-CH5jyCks.js +92 -0
- package/dist/cursors-hl00ix41.js +54 -0
- package/dist/cyclonedx/bom.json +1 -0
- package/dist/density-DEW_j0I5.js +207 -0
- package/dist/depth-DCn3mAAJ.js +143 -0
- package/dist/doc-page-BQXdbP_h.js +439 -0
- package/dist/extending-CY7ry7Y4.js +31 -0
- package/dist/faces-D76c_Ryh.js +65 -0
- package/dist/gate-CoX2Yr9x.js +199 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +39 -0
- package/dist/layers-BxdWdfPg.js +53 -0
- package/dist/looks-BrROho5Y.js +107 -0
- package/dist/measure-uwF7Fmpy.js +137 -0
- package/dist/mode-colors-Cf_ZPo3g.js +260 -0
- package/dist/mode-panels-Bmh0ec0U.js +54 -0
- package/dist/motion-DRbsuZZo.js +202 -0
- package/dist/overview-BbE82N2c.js +192 -0
- package/dist/palettes-CZo2HrNT.js +49 -0
- package/dist/parts-BVmqVMgo.js +25 -0
- package/dist/recipes-C88xVIGB.js +32 -0
- package/dist/rows-Dv8c7jye.js +18 -0
- package/dist/sampler-Ue67PX2n.js +27 -0
- package/dist/series-AvSZjk2b.js +63 -0
- package/dist/setting-BsgJKTlh.js +12 -0
- package/dist/sizes-B7LgvyBS.js +98 -0
- package/dist/spacing-DMyyV6vX.js +75 -0
- package/dist/surfaces-Db0HjMwB.js +76 -0
- package/dist/text-styles-BZnXaigP.js +233 -0
- package/dist/theme.d.ts +12 -0
- package/dist/theme.js +23 -0
- package/dist/themes-yClyRA9e.js +305 -0
- package/dist/theming-text.recipe-Dvcza4j1.js +308 -0
- package/dist/token-table-yrZh5kLy.js +182 -0
- package/dist/tokens-7Pm-eLiZ.js +138 -0
- package/dist/use-readings-D56mNtEc.js +77 -0
- package/dist/variables-ymFs3Bzn.js +43 -0
- package/dist/worn-D4HEJsJ2.js +15 -0
- package/dist/writing-b05oSPB2.js +31 -0
- package/package.json +124 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//#region src/manifest.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Maps the theming plugin's contract to its code: one page module per route, each behind a lazy
|
|
4
|
+
* importer.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The theming plugin's manifest, which a product installs.
|
|
8
|
+
*/
|
|
9
|
+
export declare const manifest: import("@stealthscale/sdk-core").PluginManifest<import("@stealthscale/sdk-core").Contract<"theming", {
|
|
10
|
+
readonly menus: {
|
|
11
|
+
basics: import("@stealthscale/sdk-core").MenuMarker;
|
|
12
|
+
building: import("@stealthscale/sdk-core").MenuMarker;
|
|
13
|
+
color: import("@stealthscale/sdk-core").MenuMarker;
|
|
14
|
+
motion: import("@stealthscale/sdk-core").MenuMarker;
|
|
15
|
+
shape: import("@stealthscale/sdk-core").MenuMarker;
|
|
16
|
+
space: import("@stealthscale/sdk-core").MenuMarker;
|
|
17
|
+
type: import("@stealthscale/sdk-core").MenuMarker;
|
|
18
|
+
};
|
|
19
|
+
readonly routes: {
|
|
20
|
+
accessibility: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
21
|
+
breakpoints: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
22
|
+
code: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
23
|
+
conditions: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
24
|
+
corners: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
25
|
+
cursors: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
26
|
+
density: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
27
|
+
depth: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
28
|
+
extending: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
29
|
+
faces: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
30
|
+
gate: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
31
|
+
layers: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
32
|
+
looks: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
33
|
+
motion: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
34
|
+
overview: NoInfer<import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>>;
|
|
35
|
+
palettes: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
36
|
+
recipes: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
37
|
+
series: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
38
|
+
sizes: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
39
|
+
spacing: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
40
|
+
surfaces: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
41
|
+
textStyles: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
42
|
+
themes: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
43
|
+
tokens: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
44
|
+
writing: import("@stealthscale/sdk-core").RouteMarker<Readonly<Record<never, string>>, unknown>;
|
|
45
|
+
};
|
|
46
|
+
readonly version: string;
|
|
47
|
+
}>>;
|
|
48
|
+
//#endregion
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { themingContract } from "@stealthscale/plugin-theming-contract";
|
|
2
|
+
import { definePlugin } from "@stealthscale/sdk-core";
|
|
3
|
+
//#region src/manifest.ts
|
|
4
|
+
/**
|
|
5
|
+
* Maps the theming plugin's contract to its code: one page module per route, each behind a lazy
|
|
6
|
+
* importer.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The theming plugin's manifest, which a product installs.
|
|
10
|
+
*/
|
|
11
|
+
const manifest = definePlugin(themingContract, { routes: {
|
|
12
|
+
accessibility: () => import("./accessibility-Dg5Dh35o.js"),
|
|
13
|
+
breakpoints: () => import("./breakpoints-CJjhy79u.js"),
|
|
14
|
+
code: () => import("./code-DcoH6hCX.js"),
|
|
15
|
+
conditions: () => import("./conditions-CjjQwqro.js"),
|
|
16
|
+
corners: () => import("./corners-CH5jyCks.js"),
|
|
17
|
+
cursors: () => import("./cursors-hl00ix41.js"),
|
|
18
|
+
density: () => import("./density-DEW_j0I5.js"),
|
|
19
|
+
depth: () => import("./depth-DCn3mAAJ.js"),
|
|
20
|
+
extending: () => import("./extending-CY7ry7Y4.js"),
|
|
21
|
+
faces: () => import("./faces-D76c_Ryh.js"),
|
|
22
|
+
gate: () => import("./gate-CoX2Yr9x.js"),
|
|
23
|
+
layers: () => import("./layers-BxdWdfPg.js"),
|
|
24
|
+
looks: () => import("./looks-BrROho5Y.js"),
|
|
25
|
+
motion: () => import("./motion-DRbsuZZo.js"),
|
|
26
|
+
overview: () => import("./overview-BbE82N2c.js"),
|
|
27
|
+
palettes: () => import("./palettes-CZo2HrNT.js"),
|
|
28
|
+
recipes: () => import("./recipes-C88xVIGB.js"),
|
|
29
|
+
series: () => import("./series-AvSZjk2b.js"),
|
|
30
|
+
sizes: () => import("./sizes-B7LgvyBS.js"),
|
|
31
|
+
spacing: () => import("./spacing-DMyyV6vX.js"),
|
|
32
|
+
surfaces: () => import("./surfaces-Db0HjMwB.js"),
|
|
33
|
+
textStyles: () => import("./text-styles-BZnXaigP.js"),
|
|
34
|
+
themes: () => import("./themes-yClyRA9e.js"),
|
|
35
|
+
tokens: () => import("./tokens-7Pm-eLiZ.js"),
|
|
36
|
+
writing: () => import("./writing-b05oSPB2.js")
|
|
37
|
+
} });
|
|
38
|
+
//#endregion
|
|
39
|
+
export { manifest };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { n as useWords, t as DocPage } from "./doc-page-BQXdbP_h.js";
|
|
2
|
+
import { t as tokenRows } from "./rows-Dv8c7jye.js";
|
|
3
|
+
import { t as TokenTable } from "./token-table-yrZh5kLy.js";
|
|
4
|
+
import { LAYERS } from "@stealthscale/theme/contract";
|
|
5
|
+
import { c } from "react/compiler-runtime";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
//#region src/pages/layers.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Lists the layers, lowest first.
|
|
10
|
+
*/
|
|
11
|
+
const ROWS = tokenRows("zIndex", LAYERS);
|
|
12
|
+
/**
|
|
13
|
+
* Renders the layers page.
|
|
14
|
+
*/
|
|
15
|
+
function LayersPage() {
|
|
16
|
+
const $ = c(7);
|
|
17
|
+
const { t } = useWords();
|
|
18
|
+
let t0;
|
|
19
|
+
if ($[0] !== t) {
|
|
20
|
+
t0 = t("layers.sections.stack.title");
|
|
21
|
+
$[0] = t;
|
|
22
|
+
$[1] = t0;
|
|
23
|
+
} else t0 = $[1];
|
|
24
|
+
let t1;
|
|
25
|
+
if ($[2] !== t0) {
|
|
26
|
+
t1 = {
|
|
27
|
+
block: /* @__PURE__ */ jsx(TokenTable, {
|
|
28
|
+
caption: t0,
|
|
29
|
+
rows: ROWS
|
|
30
|
+
}),
|
|
31
|
+
id: "stack"
|
|
32
|
+
};
|
|
33
|
+
$[2] = t0;
|
|
34
|
+
$[3] = t1;
|
|
35
|
+
} else t1 = $[3];
|
|
36
|
+
let t2;
|
|
37
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
38
|
+
t2 = { id: "using" };
|
|
39
|
+
$[4] = t2;
|
|
40
|
+
} else t2 = $[4];
|
|
41
|
+
let t3;
|
|
42
|
+
if ($[5] !== t1) {
|
|
43
|
+
t3 = /* @__PURE__ */ jsx(DocPage, {
|
|
44
|
+
page: "layers",
|
|
45
|
+
sections: [t1, t2]
|
|
46
|
+
});
|
|
47
|
+
$[5] = t1;
|
|
48
|
+
$[6] = t3;
|
|
49
|
+
} else t3 = $[6];
|
|
50
|
+
return t3;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { LayersPage };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { s as keyOf } from "./theming-text.recipe-Dvcza4j1.js";
|
|
2
|
+
import { n as useWords, t as DocPage } from "./doc-page-BQXdbP_h.js";
|
|
3
|
+
import { t as ThemingLook } from "./parts-BVmqVMgo.js";
|
|
4
|
+
import { LAYER_STYLES } from "@stealthscale/theme/contract";
|
|
5
|
+
import { c } from "react/compiler-runtime";
|
|
6
|
+
import { Grid, Stack } from "@stealthscale/component-layout";
|
|
7
|
+
import { Code } from "@stealthscale/component-typography";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
//#region src/blocks/look-grid.tsx
|
|
10
|
+
/**
|
|
11
|
+
* The layer style of an inactive control.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* Its sample is marked disabled, because the look fades the words below the contrast minimum and
|
|
15
|
+
* WCAG exempts the text of an inactive component from that minimum.
|
|
16
|
+
*/
|
|
17
|
+
const INACTIVE = "disabled";
|
|
18
|
+
/**
|
|
19
|
+
* Renders a box per layer style, in the primary palette, under the style's name.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* The name is above the box and not inside it, because a blur or a mask also changes the words
|
|
23
|
+
* inside the box. A look that responds to the pointer, such as a fill's hover or the ripple's
|
|
24
|
+
* press, responds here too, so a reader can try each one.
|
|
25
|
+
*/
|
|
26
|
+
function LookGrid(t0) {
|
|
27
|
+
const $ = c(7);
|
|
28
|
+
const { names } = t0;
|
|
29
|
+
const { t } = useWords();
|
|
30
|
+
let t1;
|
|
31
|
+
if ($[0] !== names || $[1] !== t) {
|
|
32
|
+
let t2;
|
|
33
|
+
if ($[3] !== t) {
|
|
34
|
+
t2 = (name) => /* @__PURE__ */ jsxs(Stack, {
|
|
35
|
+
gap: "xs",
|
|
36
|
+
children: [/* @__PURE__ */ jsx(Code, { children: name }), /* @__PURE__ */ jsx(ThemingLook, {
|
|
37
|
+
"aria-disabled": name === INACTIVE ? true : void 0,
|
|
38
|
+
look: keyOf(name),
|
|
39
|
+
children: t("blocks.specimen")
|
|
40
|
+
})]
|
|
41
|
+
}, name);
|
|
42
|
+
$[3] = t;
|
|
43
|
+
$[4] = t2;
|
|
44
|
+
} else t2 = $[4];
|
|
45
|
+
t1 = names.map(t2);
|
|
46
|
+
$[0] = names;
|
|
47
|
+
$[1] = t;
|
|
48
|
+
$[2] = t1;
|
|
49
|
+
} else t1 = $[2];
|
|
50
|
+
let t2;
|
|
51
|
+
if ($[5] !== t1) {
|
|
52
|
+
t2 = /* @__PURE__ */ jsx(Grid.Root, {
|
|
53
|
+
columns: "fill-xs",
|
|
54
|
+
gap: "lg",
|
|
55
|
+
children: t1
|
|
56
|
+
});
|
|
57
|
+
$[5] = t1;
|
|
58
|
+
$[6] = t2;
|
|
59
|
+
} else t2 = $[6];
|
|
60
|
+
return t2;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/pages/looks.tsx
|
|
64
|
+
/**
|
|
65
|
+
* The page's sections: a grid of samples per group.
|
|
66
|
+
*/
|
|
67
|
+
const SECTIONS = [
|
|
68
|
+
["fills", ["fill."]],
|
|
69
|
+
["flats", ["flat."]],
|
|
70
|
+
["outlines", ["outline."]],
|
|
71
|
+
["fields", ["field."]],
|
|
72
|
+
["indicators", ["indicator."]],
|
|
73
|
+
["states", [
|
|
74
|
+
"disabled",
|
|
75
|
+
"glass",
|
|
76
|
+
"ripple"
|
|
77
|
+
]],
|
|
78
|
+
["effects", [
|
|
79
|
+
"glow.",
|
|
80
|
+
"blur.",
|
|
81
|
+
"border.",
|
|
82
|
+
"dim.",
|
|
83
|
+
"text.",
|
|
84
|
+
"mask."
|
|
85
|
+
]],
|
|
86
|
+
["backdrops", ["backdrop."]]
|
|
87
|
+
].map(([id, prefixes]) => ({
|
|
88
|
+
block: /* @__PURE__ */ jsx(LookGrid, { names: LAYER_STYLES.filter((name) => prefixes.some((prefix) => name.startsWith(prefix))) }),
|
|
89
|
+
id
|
|
90
|
+
}));
|
|
91
|
+
/**
|
|
92
|
+
* Renders the looks page.
|
|
93
|
+
*/
|
|
94
|
+
function LooksPage() {
|
|
95
|
+
const $ = c(1);
|
|
96
|
+
let t0;
|
|
97
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
98
|
+
t0 = /* @__PURE__ */ jsx(DocPage, {
|
|
99
|
+
page: "looks",
|
|
100
|
+
sections: SECTIONS
|
|
101
|
+
});
|
|
102
|
+
$[0] = t0;
|
|
103
|
+
} else t0 = $[0];
|
|
104
|
+
return t0;
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
export { LooksPage };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { contrast, linear } from "@stealthscale/theme/contract";
|
|
2
|
+
//#region src/reading/format.ts
|
|
3
|
+
/**
|
|
4
|
+
* Turns readings into what a page writes: a color as hex, the contrast ratio of two colors, and a
|
|
5
|
+
* length in pixels.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Encodes a linear channel with the sRGB transfer curve, clipped to the display's range, and writes
|
|
9
|
+
* it as two hex digits.
|
|
10
|
+
*/
|
|
11
|
+
function byteOf(channel) {
|
|
12
|
+
const clipped = Math.min(Math.max(channel, 0), 1);
|
|
13
|
+
const encoded = clipped <= .0031308 ? clipped * 12.92 : 1.055 * clipped ** (1 / 2.4) - .055;
|
|
14
|
+
return Math.round(encoded * 255).toString(16).padStart(2, "0");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Returns a color as the six hex digits a display shows for it.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* A color outside sRGB is clipped, as a display clips it. A color with transparency has no hex of
|
|
21
|
+
* its own, because what shows depends on what is under it.
|
|
22
|
+
* @param color - The color as a browser serialises it: OKLCH, hex or `rgb()`.
|
|
23
|
+
* @returns The hex color, or undefined where the color cannot be read or is translucent.
|
|
24
|
+
*/
|
|
25
|
+
function hexOf(color) {
|
|
26
|
+
const read = linear(color);
|
|
27
|
+
return read === void 0 ? void 0 : `#${byteOf(read.red)}${byteOf(read.green)}${byteOf(read.blue)}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns the color a reading resolved to.
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* A browser resolves the color, and a document without a color engine leaves it empty, where the
|
|
34
|
+
* substituted value is the color as the stylesheet writes it.
|
|
35
|
+
* @param reading - A token's reading, or undefined before the token is read.
|
|
36
|
+
* @returns The color, or undefined where the stylesheet declares no such token.
|
|
37
|
+
*/
|
|
38
|
+
function colorOf(reading) {
|
|
39
|
+
if (reading === void 0 || reading.value === "") return void 0;
|
|
40
|
+
return reading.color === "" ? reading.value : reading.color;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns the contrast ratio of two colors.
|
|
44
|
+
*
|
|
45
|
+
* @param front - The color in front, or undefined where it was not read.
|
|
46
|
+
* @param back - The color behind, or undefined where it was not read.
|
|
47
|
+
* @returns The ratio, from 1 to 21, or undefined where either color cannot be measured.
|
|
48
|
+
*/
|
|
49
|
+
function ratioOf(front, back) {
|
|
50
|
+
if (front === void 0 || back === void 0) return void 0;
|
|
51
|
+
const ratio = contrast(front, back);
|
|
52
|
+
return Number.isNaN(ratio) ? void 0 : ratio;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns a value with the zeros after each number's last significant digit dropped, and a zero
|
|
56
|
+
* before a number that starts at its decimal point: `0.5000rem` as `0.5rem`, `1.0000rem` as `1rem`
|
|
57
|
+
* and `.125rem` as `0.125rem`.
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* A built stylesheet writes a number below one without its leading zero, and a development
|
|
61
|
+
* stylesheet writes it with four decimals, so both read alike on a page.
|
|
62
|
+
* @param value - A value as a stylesheet writes it.
|
|
63
|
+
*/
|
|
64
|
+
function tidyNumbers(value) {
|
|
65
|
+
return value.replaceAll(/(\.\d*?)0+(?!\d)/gu, "$1").replaceAll(/\.(?!\d)/gu, "").replaceAll(/(?<before>^|[^\d.\\])\.(?=\d)/gu, "$<before>0.");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns a computed value with every length in pixels rounded to two decimals: `83.2256px` as
|
|
69
|
+
* `83.23px` and `-1.66451px` as `-1.66px`.
|
|
70
|
+
*
|
|
71
|
+
* @remarks
|
|
72
|
+
* A browser computes a length from a size in rem through the density and the type scale, so a
|
|
73
|
+
* length in pixels can have four decimals or more, which no reader compares.
|
|
74
|
+
* @param value - A value as a browser computes it, such as `16px` or `normal`.
|
|
75
|
+
*/
|
|
76
|
+
function roundedPixels(value) {
|
|
77
|
+
return value.replaceAll(/-?\d+\.\d+(?=px)/gu, (number) => String(Number(Number(number).toFixed(2))));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns the pixels a reading's length resolved to.
|
|
81
|
+
*
|
|
82
|
+
* @param reading - A token's reading, or undefined before the token is read.
|
|
83
|
+
* @returns The length in pixels, or undefined where the token is not a length a browser computed.
|
|
84
|
+
*/
|
|
85
|
+
function pixelsOf(reading) {
|
|
86
|
+
return reading?.length.endsWith("px") === true ? roundedPixels(reading.length) : void 0;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Returns the multiplier a density reading resolved to.
|
|
90
|
+
*
|
|
91
|
+
* @param reading - The reading of the density property, or undefined before it is read.
|
|
92
|
+
* @returns The multiplier, or `1` where nothing sets the property.
|
|
93
|
+
*/
|
|
94
|
+
function multiplierOf(reading) {
|
|
95
|
+
return reading === void 0 || reading.value === "" ? "1" : reading.value;
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/reading/measure.ts
|
|
99
|
+
/**
|
|
100
|
+
* Fixes the custom property the probe states each token under.
|
|
101
|
+
*/
|
|
102
|
+
const PROBE = "--theming-probe";
|
|
103
|
+
/**
|
|
104
|
+
* Collapses each run of whitespace to one space and trims the ends.
|
|
105
|
+
*/
|
|
106
|
+
function tidied(value) {
|
|
107
|
+
return value.replaceAll(/\s+/gu, " ").trim();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Reads every token inside an element.
|
|
111
|
+
*
|
|
112
|
+
* @param box - The element the tokens resolve in.
|
|
113
|
+
* @param variables - The custom properties to read, such as `--colors-bg`.
|
|
114
|
+
* @returns Each custom property's reading, keyed by the property.
|
|
115
|
+
*/
|
|
116
|
+
function measured(box, variables) {
|
|
117
|
+
const probe = box.ownerDocument.createElement("span");
|
|
118
|
+
const readings = /* @__PURE__ */ new Map();
|
|
119
|
+
probe.hidden = true;
|
|
120
|
+
box.append(probe);
|
|
121
|
+
for (const variable of variables) {
|
|
122
|
+
const reference = `var(${variable})`;
|
|
123
|
+
probe.style.setProperty(PROBE, reference);
|
|
124
|
+
probe.style.setProperty("color", reference);
|
|
125
|
+
probe.style.setProperty("inline-size", reference);
|
|
126
|
+
const computed = getComputedStyle(probe);
|
|
127
|
+
readings.set(variable, {
|
|
128
|
+
color: tidied(computed.color),
|
|
129
|
+
length: tidied(computed.inlineSize),
|
|
130
|
+
value: tidied(computed.getPropertyValue(PROBE))
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
probe.remove();
|
|
134
|
+
return readings;
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
export { pixelsOf as a, tidyNumbers as c, multiplierOf as i, colorOf as n, ratioOf as o, hexOf as r, roundedPixels as s, measured as t };
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { n as colorOf, o as ratioOf, r as hexOf } from "./measure-uwF7Fmpy.js";
|
|
2
|
+
import { n as useWords } from "./doc-page-BQXdbP_h.js";
|
|
3
|
+
import { t as useReadings } from "./use-readings-D56mNtEc.js";
|
|
4
|
+
import { t as ModePanels } from "./mode-panels-Bmh0ec0U.js";
|
|
5
|
+
import { c } from "react/compiler-runtime";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { Stack } from "@stealthscale/component-layout";
|
|
8
|
+
import { Table } from "@stealthscale/component-collections";
|
|
9
|
+
import { ColorSwatch, Format } from "@stealthscale/component-data";
|
|
10
|
+
import { Code } from "@stealthscale/component-typography";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
//#region src/blocks/color-table.tsx
|
|
13
|
+
/**
|
|
14
|
+
* Renders a table of colors in one mode: each color's swatch and name, the hex a display shows for
|
|
15
|
+
* it, and its contrast ratio against the color it is read on.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The page, which a color is read on where its row names nothing else.
|
|
19
|
+
*/
|
|
20
|
+
const PAGE = {
|
|
21
|
+
name: "bg",
|
|
22
|
+
variable: "--colors-bg"
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The digits a ratio is written with.
|
|
26
|
+
*/
|
|
27
|
+
const DIGITS = {
|
|
28
|
+
maximumFractionDigits: 2,
|
|
29
|
+
minimumFractionDigits: 2
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Returns the words a value cell writes: nothing before the color is read, its hex, the color as
|
|
33
|
+
* the browser writes it where it has no hex, or the word for a color the stylesheet does not
|
|
34
|
+
* declare.
|
|
35
|
+
*/
|
|
36
|
+
function written(reading, missing) {
|
|
37
|
+
if (reading === void 0) return "";
|
|
38
|
+
const color = colorOf(reading);
|
|
39
|
+
return color === void 0 ? missing : hexOf(color) ?? color;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Returns a row's name cell: the swatch, painted in the mode the table is read in, and the name.
|
|
43
|
+
*/
|
|
44
|
+
function named({ name, variable }) {
|
|
45
|
+
return /* @__PURE__ */ jsxs(Stack, {
|
|
46
|
+
direction: "row",
|
|
47
|
+
gap: "sm",
|
|
48
|
+
children: [/* @__PURE__ */ jsx(ColorSwatch, {
|
|
49
|
+
size: "sm",
|
|
50
|
+
value: `var(${variable})`
|
|
51
|
+
}), /* @__PURE__ */ jsx(Code, {
|
|
52
|
+
size: "sm",
|
|
53
|
+
children: name
|
|
54
|
+
})]
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns a row's cell of the color behind it.
|
|
59
|
+
*/
|
|
60
|
+
function behind({ against = PAGE }) {
|
|
61
|
+
return /* @__PURE__ */ jsx(Code, {
|
|
62
|
+
size: "sm",
|
|
63
|
+
children: against.name
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns a row's ratio cell: the ratio with two digits, or nothing where either color cannot be
|
|
68
|
+
* measured.
|
|
69
|
+
*/
|
|
70
|
+
function measuredRatio({ against = PAGE, variable }, readings) {
|
|
71
|
+
const ratio = ratioOf(colorOf(readings.get(variable)), colorOf(readings.get(against.variable)));
|
|
72
|
+
return ratio === void 0 ? null : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Format.Number, {
|
|
73
|
+
options: DIGITS,
|
|
74
|
+
value: ratio
|
|
75
|
+
}), ":1"] });
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Renders the table, reading every color and every color behind it inside the table's viewport.
|
|
79
|
+
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* A table inside a mode panel reads that panel's mode, and its swatches paint in it. The ratio is
|
|
82
|
+
* WCAG's, measured on the colors the display shows. The table is set at the `sm` size, so its
|
|
83
|
+
* four columns fit one panel beside the contents rail in a window 1100px wide or more.
|
|
84
|
+
*/
|
|
85
|
+
function ColorTable(t0) {
|
|
86
|
+
const $ = c(40);
|
|
87
|
+
const { caption, rows } = t0;
|
|
88
|
+
const { t } = useWords();
|
|
89
|
+
const [box, setBox] = useState(null);
|
|
90
|
+
let t1;
|
|
91
|
+
if ($[0] !== rows) {
|
|
92
|
+
t1 = new Set(rows.flatMap(_temp));
|
|
93
|
+
$[0] = rows;
|
|
94
|
+
$[1] = t1;
|
|
95
|
+
} else t1 = $[1];
|
|
96
|
+
let t2;
|
|
97
|
+
if ($[2] !== t1) {
|
|
98
|
+
t2 = [...t1];
|
|
99
|
+
$[2] = t1;
|
|
100
|
+
$[3] = t2;
|
|
101
|
+
} else t2 = $[3];
|
|
102
|
+
const readings = useReadings(box, t2);
|
|
103
|
+
let t3;
|
|
104
|
+
if ($[4] !== caption || $[5] !== t) {
|
|
105
|
+
t3 = t("blocks.tableOf", { name: caption });
|
|
106
|
+
$[4] = caption;
|
|
107
|
+
$[5] = t;
|
|
108
|
+
$[6] = t3;
|
|
109
|
+
} else t3 = $[6];
|
|
110
|
+
let t4;
|
|
111
|
+
if ($[7] !== t) {
|
|
112
|
+
t4 = t("blocks.name");
|
|
113
|
+
$[7] = t;
|
|
114
|
+
$[8] = t4;
|
|
115
|
+
} else t4 = $[8];
|
|
116
|
+
let t5;
|
|
117
|
+
if ($[9] !== t4) {
|
|
118
|
+
t5 = {
|
|
119
|
+
cell: named,
|
|
120
|
+
key: "name",
|
|
121
|
+
label: t4,
|
|
122
|
+
rowHeader: true
|
|
123
|
+
};
|
|
124
|
+
$[9] = t4;
|
|
125
|
+
$[10] = t5;
|
|
126
|
+
} else t5 = $[10];
|
|
127
|
+
let t6;
|
|
128
|
+
if ($[11] !== readings || $[12] !== t) {
|
|
129
|
+
t6 = (t7) => {
|
|
130
|
+
const { variable } = t7;
|
|
131
|
+
return written(readings.get(variable), t("blocks.missing"));
|
|
132
|
+
};
|
|
133
|
+
$[11] = readings;
|
|
134
|
+
$[12] = t;
|
|
135
|
+
$[13] = t6;
|
|
136
|
+
} else t6 = $[13];
|
|
137
|
+
let t7;
|
|
138
|
+
if ($[14] !== t) {
|
|
139
|
+
t7 = t("blocks.value");
|
|
140
|
+
$[14] = t;
|
|
141
|
+
$[15] = t7;
|
|
142
|
+
} else t7 = $[15];
|
|
143
|
+
let t8;
|
|
144
|
+
if ($[16] !== t6 || $[17] !== t7) {
|
|
145
|
+
t8 = {
|
|
146
|
+
cell: t6,
|
|
147
|
+
key: "value",
|
|
148
|
+
label: t7
|
|
149
|
+
};
|
|
150
|
+
$[16] = t6;
|
|
151
|
+
$[17] = t7;
|
|
152
|
+
$[18] = t8;
|
|
153
|
+
} else t8 = $[18];
|
|
154
|
+
let t9;
|
|
155
|
+
if ($[19] !== t) {
|
|
156
|
+
t9 = t("blocks.against");
|
|
157
|
+
$[19] = t;
|
|
158
|
+
$[20] = t9;
|
|
159
|
+
} else t9 = $[20];
|
|
160
|
+
let t10;
|
|
161
|
+
if ($[21] !== t9) {
|
|
162
|
+
t10 = {
|
|
163
|
+
cell: behind,
|
|
164
|
+
key: "against",
|
|
165
|
+
label: t9
|
|
166
|
+
};
|
|
167
|
+
$[21] = t9;
|
|
168
|
+
$[22] = t10;
|
|
169
|
+
} else t10 = $[22];
|
|
170
|
+
let t11;
|
|
171
|
+
if ($[23] !== readings) {
|
|
172
|
+
t11 = (row_0) => measuredRatio(row_0, readings);
|
|
173
|
+
$[23] = readings;
|
|
174
|
+
$[24] = t11;
|
|
175
|
+
} else t11 = $[24];
|
|
176
|
+
let t12;
|
|
177
|
+
if ($[25] !== t) {
|
|
178
|
+
t12 = t("blocks.ratio");
|
|
179
|
+
$[25] = t;
|
|
180
|
+
$[26] = t12;
|
|
181
|
+
} else t12 = $[26];
|
|
182
|
+
let t13;
|
|
183
|
+
if ($[27] !== t11 || $[28] !== t12) {
|
|
184
|
+
t13 = {
|
|
185
|
+
cell: t11,
|
|
186
|
+
key: "ratio",
|
|
187
|
+
label: t12,
|
|
188
|
+
numeric: true
|
|
189
|
+
};
|
|
190
|
+
$[27] = t11;
|
|
191
|
+
$[28] = t12;
|
|
192
|
+
$[29] = t13;
|
|
193
|
+
} else t13 = $[29];
|
|
194
|
+
let t14;
|
|
195
|
+
if ($[30] !== t10 || $[31] !== t13 || $[32] !== t5 || $[33] !== t8) {
|
|
196
|
+
t14 = [
|
|
197
|
+
t5,
|
|
198
|
+
t8,
|
|
199
|
+
t10,
|
|
200
|
+
t13
|
|
201
|
+
];
|
|
202
|
+
$[30] = t10;
|
|
203
|
+
$[31] = t13;
|
|
204
|
+
$[32] = t5;
|
|
205
|
+
$[33] = t8;
|
|
206
|
+
$[34] = t14;
|
|
207
|
+
} else t14 = $[34];
|
|
208
|
+
let t15;
|
|
209
|
+
if ($[35] !== caption || $[36] !== rows || $[37] !== t14 || $[38] !== t3) {
|
|
210
|
+
t15 = /* @__PURE__ */ jsx(Table.Simple, {
|
|
211
|
+
"aria-label": t3,
|
|
212
|
+
caption,
|
|
213
|
+
columns: t14,
|
|
214
|
+
rows,
|
|
215
|
+
rowToKey: _temp2,
|
|
216
|
+
size: "sm",
|
|
217
|
+
viewportRef: setBox
|
|
218
|
+
});
|
|
219
|
+
$[35] = caption;
|
|
220
|
+
$[36] = rows;
|
|
221
|
+
$[37] = t14;
|
|
222
|
+
$[38] = t3;
|
|
223
|
+
$[39] = t15;
|
|
224
|
+
} else t15 = $[39];
|
|
225
|
+
return t15;
|
|
226
|
+
}
|
|
227
|
+
function _temp2(t0) {
|
|
228
|
+
const { variable: variable_0 } = t0;
|
|
229
|
+
return variable_0;
|
|
230
|
+
}
|
|
231
|
+
function _temp(row) {
|
|
232
|
+
return [row.variable, (row.against ?? PAGE).variable];
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/blocks/mode-colors.tsx
|
|
236
|
+
/**
|
|
237
|
+
* Renders a color table in each mode's panel.
|
|
238
|
+
*/
|
|
239
|
+
function ModeColors(t0) {
|
|
240
|
+
const $ = c(4);
|
|
241
|
+
const { name, rows } = t0;
|
|
242
|
+
const { t } = useWords();
|
|
243
|
+
let t1;
|
|
244
|
+
if ($[0] !== name || $[1] !== rows || $[2] !== t) {
|
|
245
|
+
t1 = /* @__PURE__ */ jsx(ModePanels, { children: (mode) => /* @__PURE__ */ jsx(ColorTable, {
|
|
246
|
+
caption: t("blocks.inMode", {
|
|
247
|
+
mode: t(`blocks.${mode}Mode`),
|
|
248
|
+
name
|
|
249
|
+
}),
|
|
250
|
+
rows
|
|
251
|
+
}) });
|
|
252
|
+
$[0] = name;
|
|
253
|
+
$[1] = rows;
|
|
254
|
+
$[2] = t;
|
|
255
|
+
$[3] = t1;
|
|
256
|
+
} else t1 = $[3];
|
|
257
|
+
return t1;
|
|
258
|
+
}
|
|
259
|
+
//#endregion
|
|
260
|
+
export { ModeColors as t };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { n as useWords } from "./doc-page-BQXdbP_h.js";
|
|
2
|
+
import { n as attributesOf, t as MODES } from "./attributes-vx1W0PiK.js";
|
|
3
|
+
import { t as useWornTheme } from "./worn-D4HEJsJ2.js";
|
|
4
|
+
import { r as ThemingPanel } from "./parts-BVmqVMgo.js";
|
|
5
|
+
import { c } from "react/compiler-runtime";
|
|
6
|
+
import { Grid } from "@stealthscale/component-layout";
|
|
7
|
+
import { Heading } from "@stealthscale/component-typography";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
//#region src/reading/mode-panels.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Renders a panel per mode, each with the theme and the mode attributes, its mode's name as a
|
|
12
|
+
* heading, and the block.
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* The panels are keyed by the theme, so a block inside mounts again and reads its tokens again
|
|
16
|
+
* when a person wears another theme. Each panel is at least `sizes.xl` wide, the room a table of
|
|
17
|
+
* colors needs, so the panels stack unless the page has room for two at that width.
|
|
18
|
+
* @returns The grid of the two panels.
|
|
19
|
+
*/
|
|
20
|
+
function ModePanels(t0) {
|
|
21
|
+
const $ = c(7);
|
|
22
|
+
const { children } = t0;
|
|
23
|
+
const worn = useWornTheme();
|
|
24
|
+
const { t } = useWords();
|
|
25
|
+
let t1;
|
|
26
|
+
if ($[0] !== children || $[1] !== t || $[2] !== worn) {
|
|
27
|
+
t1 = MODES.map((mode) => /* @__PURE__ */ jsxs(ThemingPanel, {
|
|
28
|
+
...attributesOf(worn, mode),
|
|
29
|
+
children: [/* @__PURE__ */ jsx(Heading, {
|
|
30
|
+
as: "h3",
|
|
31
|
+
size: "xs",
|
|
32
|
+
children: t(`blocks.${mode}`)
|
|
33
|
+
}), children(mode)]
|
|
34
|
+
}, mode));
|
|
35
|
+
$[0] = children;
|
|
36
|
+
$[1] = t;
|
|
37
|
+
$[2] = worn;
|
|
38
|
+
$[3] = t1;
|
|
39
|
+
} else t1 = $[3];
|
|
40
|
+
let t2;
|
|
41
|
+
if ($[4] !== t1 || $[5] !== worn) {
|
|
42
|
+
t2 = /* @__PURE__ */ jsx(Grid.Root, {
|
|
43
|
+
columns: "fit-xl",
|
|
44
|
+
gap: "md",
|
|
45
|
+
children: t1
|
|
46
|
+
}, worn);
|
|
47
|
+
$[4] = t1;
|
|
48
|
+
$[5] = worn;
|
|
49
|
+
$[6] = t2;
|
|
50
|
+
} else t2 = $[6];
|
|
51
|
+
return t2;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { ModePanels as t };
|