@stealthscale/plugin-theming 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -2
  3. package/dist/accessibility-Dg5Dh35o.js +409 -0
  4. package/dist/attributes-vx1W0PiK.js +26 -0
  5. package/dist/breakpoints-CJjhy79u.js +83 -0
  6. package/dist/code-DcoH6hCX.js +69 -0
  7. package/dist/conditions-CjjQwqro.js +338 -0
  8. package/dist/corners-CH5jyCks.js +92 -0
  9. package/dist/cursors-hl00ix41.js +54 -0
  10. package/dist/cyclonedx/bom.json +1 -0
  11. package/dist/density-DEW_j0I5.js +207 -0
  12. package/dist/depth-DCn3mAAJ.js +143 -0
  13. package/dist/doc-page-BQXdbP_h.js +439 -0
  14. package/dist/extending-CY7ry7Y4.js +31 -0
  15. package/dist/faces-D76c_Ryh.js +65 -0
  16. package/dist/gate-CoX2Yr9x.js +199 -0
  17. package/dist/index.d.ts +48 -0
  18. package/dist/index.js +39 -0
  19. package/dist/layers-BxdWdfPg.js +53 -0
  20. package/dist/looks-BrROho5Y.js +107 -0
  21. package/dist/measure-uwF7Fmpy.js +137 -0
  22. package/dist/mode-colors-Cf_ZPo3g.js +260 -0
  23. package/dist/mode-panels-Bmh0ec0U.js +54 -0
  24. package/dist/motion-DRbsuZZo.js +202 -0
  25. package/dist/overview-BbE82N2c.js +192 -0
  26. package/dist/palettes-CZo2HrNT.js +49 -0
  27. package/dist/parts-BVmqVMgo.js +25 -0
  28. package/dist/recipes-C88xVIGB.js +32 -0
  29. package/dist/rows-Dv8c7jye.js +18 -0
  30. package/dist/sampler-Ue67PX2n.js +27 -0
  31. package/dist/series-AvSZjk2b.js +63 -0
  32. package/dist/setting-BsgJKTlh.js +12 -0
  33. package/dist/sizes-B7LgvyBS.js +98 -0
  34. package/dist/spacing-DMyyV6vX.js +75 -0
  35. package/dist/surfaces-Db0HjMwB.js +76 -0
  36. package/dist/text-styles-BZnXaigP.js +233 -0
  37. package/dist/theme.d.ts +12 -0
  38. package/dist/theme.js +23 -0
  39. package/dist/themes-yClyRA9e.js +305 -0
  40. package/dist/theming-text.recipe-Dvcza4j1.js +308 -0
  41. package/dist/token-table-yrZh5kLy.js +182 -0
  42. package/dist/tokens-7Pm-eLiZ.js +138 -0
  43. package/dist/use-readings-D56mNtEc.js +77 -0
  44. package/dist/variables-ymFs3Bzn.js +43 -0
  45. package/dist/worn-D4HEJsJ2.js +15 -0
  46. package/dist/writing-b05oSPB2.js +31 -0
  47. package/package.json +124 -3
@@ -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 };