@wix/web5-core 1.63.45 → 1.63.47
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/dist/cjs/client/applyThemeOverrides.js +47 -30
- package/dist/cjs/client/applyThemeOverrides.js.map +1 -1
- package/dist/cjs/index.js +11 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/styles/base-tokens.css +19 -0
- package/dist/cjs/styles/tailwind-theme.css +12 -0
- package/dist/cjs/theme/chromeTokens.js +60 -0
- package/dist/cjs/theme/chromeTokens.js.map +1 -0
- package/dist/cjs/theme/themeScheme.js +54 -55
- package/dist/cjs/theme/themeScheme.js.map +1 -1
- package/dist/esm/client/applyThemeOverrides.js +55 -30
- package/dist/esm/client/applyThemeOverrides.js.map +1 -1
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/styles/base-tokens.css +19 -0
- package/dist/esm/styles/tailwind-theme.css +12 -0
- package/dist/esm/theme/chromeTokens.js +53 -0
- package/dist/esm/theme/chromeTokens.js.map +1 -0
- package/dist/esm/theme/themeScheme.js +57 -56
- package/dist/esm/theme/themeScheme.js.map +1 -1
- package/dist/types/client/applyThemeOverrides.d.ts +11 -0
- package/dist/types/client/applyThemeOverrides.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/theme/chromeTokens.d.ts +46 -0
- package/dist/types/theme/chromeTokens.d.ts.map +1 -0
- package/dist/types/theme/themeScheme.d.ts +24 -11
- package/dist/types/theme/themeScheme.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/styles/base-tokens.css +19 -0
- package/src/styles/tailwind-theme.css +12 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.WEB5_CHROME_TOKENS = void 0;
|
|
5
|
+
exports.web5ChromeProperties = web5ChromeProperties;
|
|
6
|
+
exports.web5ChromeProperty = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* The owner panel's own chrome colours (`--web5-chrome-*`).
|
|
9
|
+
*
|
|
10
|
+
* The Customize panel edits and previews the store's colour tokens, so its
|
|
11
|
+
* chrome cannot be painted with them: a dark scheme would turn its labels
|
|
12
|
+
* dark-on-dark and a cream card colour would turn the whole panel cream. It
|
|
13
|
+
* takes these instead — light, neutral, and written by nothing the store or the
|
|
14
|
+
* merchant controls.
|
|
15
|
+
*
|
|
16
|
+
* WHY A CONSTANT AND NOT ONLY CSS. `base-tokens.css` declares the same values,
|
|
17
|
+
* but that stylesheet reaches a page through the CLIENT bundle, and every
|
|
18
|
+
* client bundle pins the core version it was built against. A storefront whose
|
|
19
|
+
* template predates these tokens would leave the panel's `hsl(var(...))`
|
|
20
|
+
* invalid — a transparent panel inheriting the scheme's text colour. The panel
|
|
21
|
+
* lives in web50-server-ui, which bundles its own core, so it writes each value
|
|
22
|
+
* as the `var()` fallback (`hsl(var(--web5-chrome-surface, 0 0% 100%))`, see
|
|
23
|
+
* `chrome()` in the TemplatePicker) and never depends on the client's CSS.
|
|
24
|
+
* `chromeTokens.spec.ts` keeps this map and `base-tokens.css` equal.
|
|
25
|
+
*
|
|
26
|
+
* Bare HSL triplets, like every colour token: callers wrap them in `hsl()`.
|
|
27
|
+
* A leaf module (no CSS imports), for the reason `tokenContract.ts` gives.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/** Token name (without the `--web5-chrome-` prefix) → bare HSL triplet. */
|
|
31
|
+
const WEB5_CHROME_TOKENS = exports.WEB5_CHROME_TOKENS = Object.freeze({
|
|
32
|
+
surface: '0 0% 100%',
|
|
33
|
+
foreground: '0 0% 18.8%',
|
|
34
|
+
'muted-foreground': '0 0% 38%',
|
|
35
|
+
'subtle-foreground': '210 4.5% 56.9%',
|
|
36
|
+
border: '0 0% 89%',
|
|
37
|
+
'border-strong': '0 0% 71%',
|
|
38
|
+
tint: '0 0% 98%',
|
|
39
|
+
accent: '0 0% 18.8%',
|
|
40
|
+
'accent-foreground': '0 0% 100%',
|
|
41
|
+
destructive: '9 72.2% 44.9%'
|
|
42
|
+
});
|
|
43
|
+
/** `surface` → `--web5-chrome-surface`. */
|
|
44
|
+
const web5ChromeProperty = token => `--web5-chrome-${token}`;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Every chrome token as custom properties, ready to spread into an element's
|
|
48
|
+
* inline style (`style={{ ...web5ChromeProperties(), ... }}`), so the element
|
|
49
|
+
* and everything inside it resolve `var(--web5-chrome-*)` without any
|
|
50
|
+
* stylesheet.
|
|
51
|
+
*/
|
|
52
|
+
exports.web5ChromeProperty = web5ChromeProperty;
|
|
53
|
+
function web5ChromeProperties() {
|
|
54
|
+
const out = {};
|
|
55
|
+
for (const [token, value] of Object.entries(WEB5_CHROME_TOKENS)) {
|
|
56
|
+
out[web5ChromeProperty(token)] = value;
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=chromeTokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["WEB5_CHROME_TOKENS","exports","Object","freeze","surface","foreground","border","tint","accent","destructive","web5ChromeProperty","token","web5ChromeProperties","out","value","entries"],"sources":["../../../src/theme/chromeTokens.ts"],"sourcesContent":["/**\n * The owner panel's own chrome colours (`--web5-chrome-*`).\n *\n * The Customize panel edits and previews the store's colour tokens, so its\n * chrome cannot be painted with them: a dark scheme would turn its labels\n * dark-on-dark and a cream card colour would turn the whole panel cream. It\n * takes these instead — light, neutral, and written by nothing the store or the\n * merchant controls.\n *\n * WHY A CONSTANT AND NOT ONLY CSS. `base-tokens.css` declares the same values,\n * but that stylesheet reaches a page through the CLIENT bundle, and every\n * client bundle pins the core version it was built against. A storefront whose\n * template predates these tokens would leave the panel's `hsl(var(...))`\n * invalid — a transparent panel inheriting the scheme's text colour. The panel\n * lives in web50-server-ui, which bundles its own core, so it writes each value\n * as the `var()` fallback (`hsl(var(--web5-chrome-surface, 0 0% 100%))`, see\n * `chrome()` in the TemplatePicker) and never depends on the client's CSS.\n * `chromeTokens.spec.ts` keeps this map and `base-tokens.css` equal.\n *\n * Bare HSL triplets, like every colour token: callers wrap them in `hsl()`.\n * A leaf module (no CSS imports), for the reason `tokenContract.ts` gives.\n */\n\n/** Token name (without the `--web5-chrome-` prefix) → bare HSL triplet. */\nexport const WEB5_CHROME_TOKENS = Object.freeze({\n surface: '0 0% 100%',\n foreground: '0 0% 18.8%',\n 'muted-foreground': '0 0% 38%',\n 'subtle-foreground': '210 4.5% 56.9%',\n border: '0 0% 89%',\n 'border-strong': '0 0% 71%',\n tint: '0 0% 98%',\n accent: '0 0% 18.8%',\n 'accent-foreground': '0 0% 100%',\n destructive: '9 72.2% 44.9%',\n} as const);\n\nexport type Web5ChromeToken = keyof typeof WEB5_CHROME_TOKENS;\n\n/** `surface` → `--web5-chrome-surface`. */\nexport const web5ChromeProperty = (token: Web5ChromeToken): `--web5-chrome-${string}` =>\n `--web5-chrome-${token}`;\n\n/**\n * Every chrome token as custom properties, ready to spread into an element's\n * inline style (`style={{ ...web5ChromeProperties(), ... }}`), so the element\n * and everything inside it resolve `var(--web5-chrome-*)` without any\n * stylesheet.\n */\nexport function web5ChromeProperties(): Record<`--web5-chrome-${string}`, string> {\n const out = {} as Record<`--web5-chrome-${string}`, string>;\n for (const [token, value] of Object.entries(WEB5_CHROME_TOKENS)) {\n out[web5ChromeProperty(token as Web5ChromeToken)] = value;\n }\n return out;\n}\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACO,MAAMA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAGE,MAAM,CAACC,MAAM,CAAC;EAC9CC,OAAO,EAAE,WAAW;EACpBC,UAAU,EAAE,YAAY;EACxB,kBAAkB,EAAE,UAAU;EAC9B,mBAAmB,EAAE,gBAAgB;EACrCC,MAAM,EAAE,UAAU;EAClB,eAAe,EAAE,UAAU;EAC3BC,IAAI,EAAE,UAAU;EAChBC,MAAM,EAAE,YAAY;EACpB,mBAAmB,EAAE,WAAW;EAChCC,WAAW,EAAE;AACf,CAAU,CAAC;AAIX;AACO,MAAMC,kBAAkB,GAAIC,KAAsB,IACvD,iBAAiBA,KAAK,EAAE;;AAE1B;AACA;AACA;AACA;AACA;AACA;AALAV,OAAA,CAAAS,kBAAA,GAAAA,kBAAA;AAMO,SAASE,oBAAoBA,CAAA,EAA8C;EAChF,MAAMC,GAAG,GAAG,CAAC,CAA8C;EAC3D,KAAK,MAAM,CAACF,KAAK,EAAEG,KAAK,CAAC,IAAIZ,MAAM,CAACa,OAAO,CAACf,kBAAkB,CAAC,EAAE;IAC/Da,GAAG,CAACH,kBAAkB,CAACC,KAAwB,CAAC,CAAC,GAAGG,KAAK;EAC3D;EACA,OAAOD,GAAG;AACZ","ignoreList":[]}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.SCHEME_COLOR_TOKENS = exports.SCHEME_ANCHOR_TOKENS = exports.MAX_THEME_SCHEMES = void 0;
|
|
4
|
+
exports.SCHEME_TOKENS = exports.SCHEME_COLOR_TOKENS = exports.SCHEME_ANCHOR_TOKENS = exports.MAX_THEME_SCHEMES = void 0;
|
|
5
5
|
exports.completeScheme = completeScheme;
|
|
6
6
|
exports.isSchemeTokenEntry = isSchemeTokenEntry;
|
|
7
7
|
exports.isThemeScheme = isThemeScheme;
|
|
8
8
|
exports.nextOwnerSchemeId = nextOwnerSchemeId;
|
|
9
9
|
exports.resolveActiveScheme = resolveActiveScheme;
|
|
10
10
|
exports.schemeDisplayName = schemeDisplayName;
|
|
11
|
+
exports.schemeTokensOf = schemeTokensOf;
|
|
11
12
|
var _colorFormat = require("./colorFormat");
|
|
12
13
|
var _tokenContract = require("./tokenContract");
|
|
13
14
|
/**
|
|
@@ -41,9 +42,22 @@ var _tokenContract = require("./tokenContract");
|
|
|
41
42
|
* but a deep import of a zero-CSS leaf works. It imports only its siblings
|
|
42
43
|
* `./tokenContract` and `./colorFormat`, both leaves themselves.
|
|
43
44
|
*
|
|
45
|
+
* ## What a scheme carries (ADR 0243)
|
|
46
|
+
*
|
|
47
|
+
* A theme scheme is a background and its text, plus the colours mechanically
|
|
48
|
+
* derived from those two: `SCHEME_TOKENS`. Card colours, button colours,
|
|
49
|
+
* radius and fonts are the store's global set (`themeOverrides`) and the
|
|
50
|
+
* owner's global edits (`userThemeOverrides`), applied under and over the
|
|
51
|
+
* scheme respectively — so they survive every scheme switch. Rows written
|
|
52
|
+
* before 0243 may still carry more; readers apply whatever a row holds, and
|
|
53
|
+
* the owner panel writes only `SCHEME_TOKENS` into the rows it creates.
|
|
54
|
+
*
|
|
55
|
+
* An edited THEME scheme is an OWNER row that names it in `baseSchemeId`, so
|
|
56
|
+
* the panel can show the edit on that scheme's tile and revert only that one.
|
|
57
|
+
*
|
|
44
58
|
* ## `completeScheme` — what the owner panel recomputes
|
|
45
59
|
*
|
|
46
|
-
* The owner edits the
|
|
60
|
+
* The owner edits the two anchors. The rest of the scheme has to move with
|
|
47
61
|
* them the way `web50-shopify-adapter/src/theme-tokens.ts` would have moved it
|
|
48
62
|
* had the theme stated those anchors, so the arithmetic below is a COPY of the
|
|
49
63
|
* adapter's (`composite`/`mix`/`toTriplet` and the token assignments at the end
|
|
@@ -54,30 +68,21 @@ var _tokenContract = require("./tokenContract");
|
|
|
54
68
|
* | ------------------------ | ------------------------------------------------------ |
|
|
55
69
|
* | `--background` | anchor (else inherited from base) |
|
|
56
70
|
* | `--foreground` | anchor (else inherited from base) |
|
|
57
|
-
* | `--card` | anchor; when not given, derived: foreground 4% over background |
|
|
58
|
-
* | `--card-foreground` | anchor; when not given, derived: = foreground |
|
|
59
71
|
* | `--popover` | derived: = background |
|
|
60
72
|
* | `--popover-foreground` | derived: = foreground |
|
|
61
73
|
* | `--muted` | derived: foreground 4% over background |
|
|
62
74
|
* | `--muted-foreground` | derived: foreground 60% over background |
|
|
63
|
-
* | `--secondary` | derived: primary 10% over background |
|
|
64
|
-
* | `--accent` | derived: primary 10% over background |
|
|
65
|
-
* | `--primary` | inherited from base (the theme's button colour) |
|
|
66
|
-
* | `--primary-foreground` | inherited from base (the theme's button label) |
|
|
67
|
-
* | `--secondary-foreground` | inherited from base (the theme's outline-button label) |
|
|
68
|
-
* | `--accent-foreground` | inherited from base; fallback = primary |
|
|
69
|
-
* | `--ring` | inherited from base; fallback = primary |
|
|
70
75
|
* | `--border` | inherited from base (no fallback — see below) |
|
|
71
76
|
* | `--input` | inherited from base (no fallback — see below) |
|
|
72
|
-
* | `--heading` | inherited from base (no adapter fills it) |
|
|
73
|
-
* | any non-colour key | `--radius`, fonts, unknown: copied from base when valid |
|
|
74
77
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* missing border from the theme's
|
|
80
|
-
* does not carry — so they are
|
|
78
|
+
* `--secondary`/`--accent` are NOT scheme tokens: the adapter mixes them from
|
|
79
|
+
* the button colour, so they belong to the store's global set
|
|
80
|
+
* (`themeOverrides`) with the buttons, and a scheme edit leaves them alone.
|
|
81
|
+
* `--border`/`--input` are read straight off the
|
|
82
|
+
* theme by the adapter, which reconstructs a missing border from the theme's
|
|
83
|
+
* `*_border_opacity` setting a token map does not carry — so they are
|
|
84
|
+
* inherited from base, and omitted when base lacks them, as the adapter omits
|
|
85
|
+
* them.
|
|
81
86
|
*
|
|
82
87
|
* ## Rounding: why an unchanged input keeps base's value
|
|
83
88
|
*
|
|
@@ -92,8 +97,8 @@ var _tokenContract = require("./tokenContract");
|
|
|
92
97
|
*
|
|
93
98
|
* When it is recomputed, triplets convert back to RGB WITHOUT rounding to
|
|
94
99
|
* 8-bit first — that would be a second quantisation the adapter never
|
|
95
|
-
* performs, and enough to move
|
|
96
|
-
* to `230 42% 94
|
|
100
|
+
* performs, and enough to move a mixed colour's saturation by several points
|
|
101
|
+
* (smallflower's button tint went from `230 38% 94%` to `230 42% 94%`). The mix result is rounded exactly where the adapter
|
|
97
102
|
* rounds it.
|
|
98
103
|
*/
|
|
99
104
|
|
|
@@ -128,8 +133,21 @@ const SCHEME_RADIUS_VALUE = /^\d{1,4}(?:\.\d+)?(?:px|rem|em)$/;
|
|
|
128
133
|
const SCHEME_LOOSE_VALUE = /^[^;{}\p{Cc}]+$/u;
|
|
129
134
|
const MAX_SCHEME_VALUE_LENGTH = 256;
|
|
130
135
|
|
|
131
|
-
/**
|
|
132
|
-
|
|
136
|
+
/**
|
|
137
|
+
* What a scheme is (ADR 0243): its background and text, and the colours
|
|
138
|
+
* derived from those two. The panel writes exactly these into the OWNER rows
|
|
139
|
+
* it creates, and mirrors exactly these of the active row into `themeOverrides`.
|
|
140
|
+
*/
|
|
141
|
+
const SCHEME_TOKENS = exports.SCHEME_TOKENS = ['--background', '--foreground', '--popover', '--popover-foreground', '--muted', '--muted-foreground', '--border', '--input'];
|
|
142
|
+
const SCHEME_TOKEN_SET = new Set(SCHEME_TOKENS);
|
|
143
|
+
|
|
144
|
+
/** Only the `SCHEME_TOKENS` entries of `map`. */
|
|
145
|
+
function schemeTokensOf(map) {
|
|
146
|
+
return Object.fromEntries(Object.entries(map ?? {}).filter(([token]) => SCHEME_TOKEN_SET.has(token)));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** The two the owner edits on a scheme, in panel order. */
|
|
150
|
+
const SCHEME_ANCHOR_TOKENS = exports.SCHEME_ANCHOR_TOKENS = ['--background', '--foreground'];
|
|
133
151
|
/** Upper bound on schemes per configuration. */
|
|
134
152
|
const MAX_THEME_SCHEMES = exports.MAX_THEME_SCHEMES = 16;
|
|
135
153
|
const SCHEME_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
@@ -152,11 +170,15 @@ function isThemeScheme(value) {
|
|
|
152
170
|
id,
|
|
153
171
|
name,
|
|
154
172
|
origin,
|
|
173
|
+
baseSchemeId,
|
|
155
174
|
tokens
|
|
156
175
|
} = value;
|
|
157
176
|
if (typeof id !== 'string' || !SCHEME_ID_PATTERN.test(id)) {
|
|
158
177
|
return false;
|
|
159
178
|
}
|
|
179
|
+
if (baseSchemeId !== undefined && typeof baseSchemeId !== 'string') {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
160
182
|
if (name !== undefined && (typeof name !== 'string' || name.length > MAX_SCHEME_NAME_LENGTH)) {
|
|
161
183
|
return false;
|
|
162
184
|
}
|
|
@@ -249,23 +271,18 @@ function toTriplet({
|
|
|
249
271
|
return `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
|
|
250
272
|
}
|
|
251
273
|
|
|
252
|
-
/** Tokens the adapter reads off the theme rather than computing from the anchors. */
|
|
253
|
-
const INHERITED_TOKENS = ['--primary', '--primary-foreground', '--secondary-foreground', '--accent-foreground', '--ring', '--border', '--input', '--heading'];
|
|
254
|
-
|
|
255
274
|
/**
|
|
256
|
-
*
|
|
275
|
+
* The `SCHEME_TOKENS` of a scheme whose anchors the owner just edited.
|
|
257
276
|
*
|
|
258
277
|
* `anchors` win; everything the adapter derives from them is recomputed when
|
|
259
278
|
* one of its inputs changed (and kept from `base` when none did — see "Rounding"
|
|
260
|
-
* in the module header);
|
|
261
|
-
*
|
|
262
|
-
*
|
|
279
|
+
* in the module header); `--border`/`--input` are taken from `base`. Invalid
|
|
280
|
+
* triplets in any input are ignored, and a derived token whose inputs are
|
|
281
|
+
* unavailable keeps `base`'s value, if any.
|
|
263
282
|
*
|
|
264
|
-
* Returns
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
* everything it states beyond colour. Every output entry passes
|
|
268
|
-
* `isSchemeTokenEntry`.
|
|
283
|
+
* Returns ONLY `SCHEME_TOKENS`: whatever else `base` carries (a pre-0243 row's
|
|
284
|
+
* card, button or secondary/accent colours, its radius) is the store's global set now, not the
|
|
285
|
+
* scheme's, and is dropped. Every output entry passes `isSchemeTokenEntry`.
|
|
269
286
|
*/
|
|
270
287
|
function completeScheme(base, anchors) {
|
|
271
288
|
// Both checks: `isHslTriplet` is what the arithmetic can convert, and the
|
|
@@ -295,30 +312,12 @@ function completeScheme(base, anchors) {
|
|
|
295
312
|
const mixOver = (over, ratio) => () => over !== null && bg !== null ? toTriplet(mix(over, ratio, bg)) : undefined;
|
|
296
313
|
put('--background', background);
|
|
297
314
|
put('--foreground', foreground);
|
|
298
|
-
put('--card', fromAnchor('--card') ?? derive('--card', bgChanged || fgChanged, mixOver(fg, 0.04)));
|
|
299
|
-
put('--card-foreground', fromAnchor('--card-foreground') ?? derive('--card-foreground', fgChanged, () => foreground));
|
|
300
315
|
put('--popover', derive('--popover', bgChanged, () => background));
|
|
301
316
|
put('--popover-foreground', derive('--popover-foreground', fgChanged, () => foreground));
|
|
302
317
|
put('--muted', derive('--muted', bgChanged || fgChanged, mixOver(fg, 0.04)));
|
|
303
318
|
put('--muted-foreground', derive('--muted-foreground', bgChanged || fgChanged, mixOver(fg, 0.6)));
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
// Primary is inherited, so of the button family's inputs only the page can change.
|
|
308
|
-
const primaryTriplet = out['--primary'];
|
|
309
|
-
const primary = primaryTriplet === undefined ? null : tripletToRgb(primaryTriplet);
|
|
310
|
-
put('--ring', out['--ring'] ?? primaryTriplet);
|
|
311
|
-
put('--accent-foreground', out['--accent-foreground'] ?? primaryTriplet);
|
|
312
|
-
put('--secondary', derive('--secondary', bgChanged, mixOver(primary, 0.1)));
|
|
313
|
-
put('--accent', derive('--accent', bgChanged, mixOver(primary, 0.1)));
|
|
314
|
-
|
|
315
|
-
// Not colours, so no arithmetic touches them: the palette keeps its shape,
|
|
316
|
-
// its type, and any token a writer added that this module has never heard of.
|
|
317
|
-
for (const [token, value] of Object.entries(base)) {
|
|
318
|
-
if (!SCHEME_COLOR_TOKENS.has(token) && isSchemeTokenEntry(token, value)) {
|
|
319
|
-
out[token] = value;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
319
|
+
put('--border', fromBase('--border'));
|
|
320
|
+
put('--input', fromBase('--input'));
|
|
322
321
|
return out;
|
|
323
322
|
}
|
|
324
323
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_colorFormat","require","_tokenContract","SCHEME_COLOR_TOKENS","exports","Object","freeze","Set","entries","THEME_TOKEN_CONTRACT","filter","entry","type","map","token","SCHEME_COLOR_VALUE","SCHEME_RADIUS_VALUE","SCHEME_LOOSE_VALUE","MAX_SCHEME_VALUE_LENGTH","SCHEME_ANCHOR_TOKENS","MAX_THEME_SCHEMES","SCHEME_ID_PATTERN","MAX_SCHEME_NAME_LENGTH","isPlainObject","value","Array","isArray","isThemeScheme","id","name","origin","tokens","test","undefined","length","values","every","v","resolveActiveScheme","cfg","themeSchemes","schemes","activeId","activeThemeSchemeId","active","find","scheme","TRIPLET","tripletToRgb","triplet","parts","exec","trim","isHslTriplet","h","Number","s","l","c","Math","abs","x","m","r","g","b","mix","fg","ratio","bg","round","toTriplet","rn","gn","bn","max","min","delta","INHERITED_TOKENS","completeScheme","base","anchors","valid","isSchemeColorValue","fromBase","fromAnchor","out","put","background","foreground","bgChanged","fgChanged","derive","inputsChanged","compute","kept","mixOver","over","primaryTriplet","primary","has","isSchemeTokenEntry","schemeDisplayName","index","nextOwnerSchemeId","taken","n","key","_THEME_TOKEN_CONTRACT","THEME_OVERRIDE_KEY_PATTERN"],"sources":["../../../src/theme/themeScheme.ts"],"sourcesContent":["/**\n * Named theme schemes on a site configuration, and the one that is active.\n *\n * A store's theme states a SET of palettes rather than one — Dawn and Horizon\n * ship `scheme-1`..`scheme-5` for the page, the cards, the hero band, the\n * footer. The configuration therefore carries a list of schemes plus the id of\n * the active one, beside the flat `themeOverrides` map it has always had:\n *\n * themeSchemes?: [{ id, name?, origin?, tokens: { '--background': '0 0% 100%', … } }]\n * activeThemeSchemeId?: 'scheme-1'\n *\n * A scheme's `tokens` are finished CSS tokens, spelled exactly as\n * `themeOverrides` spells them — and, like `themeOverrides`, the key set is\n * OPEN. Today's writers put the 18 colour roles (`SCHEME_COLOR_TOKENS`) there,\n * sometimes `--radius`; that a palette may carry shape as well as colour is why\n * this is a THEME scheme and not a colour scheme. A new token (a font stack,\n * something the contract has not catalogued yet) needs no release anywhere but\n * its writer. The server checks only the loose shape `themeOverrides` gets (key\n * `THEME_OVERRIDE_KEY_PATTERN`, a value free of `;`, `{`, `}` and control\n * characters, ≤ 256, at most 24 entries); the typed per-token grammar is the\n * CLIENT's contract, enforced by `isSchemeTokenEntry` before the panel writes.\n * Nothing is expanded at apply time: the reader resolves the active entry and\n * hands its map to `applyThemeOverrides`, which layers it between the store map\n * and the owner's overrides, filtered and bucketed exactly like the store map.\n * A configuration with no schemes renders exactly as it did before they existed.\n *\n * A leaf module beside `tokenContract.ts`, and for the same reason that file\n * documents: requiring core's ENTRY from plain Node fails on its CSS import,\n * but a deep import of a zero-CSS leaf works. It imports only its siblings\n * `./tokenContract` and `./colorFormat`, both leaves themselves.\n *\n * ## `completeScheme` — what the owner panel recomputes\n *\n * The owner edits the four anchors. The rest of the palette has to move with\n * them the way `web50-shopify-adapter/src/theme-tokens.ts` would have moved it\n * had the theme stated those anchors, so the arithmetic below is a COPY of the\n * adapter's (`composite`/`mix`/`toTriplet` and the token assignments at the end\n * of `extractThemeOverrides`), integer rounding included. It is copied rather\n * than shared on purpose: the adapter must not import core.\n *\n * | token | role |\n * | ------------------------ | ------------------------------------------------------ |\n * | `--background` | anchor (else inherited from base) |\n * | `--foreground` | anchor (else inherited from base) |\n * | `--card` | anchor; when not given, derived: foreground 4% over background |\n * | `--card-foreground` | anchor; when not given, derived: = foreground |\n * | `--popover` | derived: = background |\n * | `--popover-foreground` | derived: = foreground |\n * | `--muted` | derived: foreground 4% over background |\n * | `--muted-foreground` | derived: foreground 60% over background |\n * | `--secondary` | derived: primary 10% over background |\n * | `--accent` | derived: primary 10% over background |\n * | `--primary` | inherited from base (the theme's button colour) |\n * | `--primary-foreground` | inherited from base (the theme's button label) |\n * | `--secondary-foreground` | inherited from base (the theme's outline-button label) |\n * | `--accent-foreground` | inherited from base; fallback = primary |\n * | `--ring` | inherited from base; fallback = primary |\n * | `--border` | inherited from base (no fallback — see below) |\n * | `--input` | inherited from base (no fallback — see below) |\n * | `--heading` | inherited from base (no adapter fills it) |\n * | any non-colour key | `--radius`, fonts, unknown: copied from base when valid |\n *\n * \"Inherited\" tokens are ones the adapter reads straight off the theme, which\n * no arithmetic over the anchors can recover. Where base lacks one, the\n * adapter's own fallback applies: `--ring` and `--accent-foreground` are the\n * primary colour. `--border`/`--input` have none — the adapter reconstructs a\n * missing border from the theme's `*_border_opacity` setting, which a token map\n * does not carry — so they are omitted, as the adapter omits them.\n *\n * ## Rounding: why an unchanged input keeps base's value\n *\n * The adapter mixes 8-bit channels parsed from the theme's hex; a scheme only\n * has the integer-rounded triplet, and the hex cannot be recovered from it.\n * Re-deriving from triplets therefore lands a point off now and then — Horizon\n * `color_palette`'s `--muted-foreground` comes back `359 83% 68%` against the\n * adapter's `359 84% 68%`. So a derived token is recomputed only when one of\n * its INPUTS differs from base; otherwise base's value stands. A merchant who\n * edits nothing gets the adapter's map back exactly, and one who edits the\n * background gets the family recomputed.\n *\n * When it is recomputed, triplets convert back to RGB WITHOUT rounding to\n * 8-bit first — that would be a second quantisation the adapter never\n * performs, and enough to move smallflower's `--secondary` from `230 38% 94%`\n * to `230 42% 94%`. The mix result is rounded exactly where the adapter\n * rounds it.\n */\nimport { isHslTriplet } from './colorFormat';\nimport {\n THEME_OVERRIDE_KEY_PATTERN,\n THEME_TOKEN_CONTRACT,\n} from './tokenContract';\n\n/** Where a scheme came from. Any other value on the wire reads as unknown. */\nexport type SchemeOrigin = 'UNKNOWN_SCHEME_ORIGIN' | 'THEME' | 'OWNER';\n\n/** One named palette as the configuration carries it. */\nexport interface ThemeScheme {\n /** `^[a-z0-9][a-z0-9-]{0,31}$`, unique within the list. */\n id: string;\n /** Shown in the owner panel; at most 48 characters. */\n name?: string;\n origin?: SchemeOrigin | string;\n /**\n * Token → value, keys as open as `themeOverrides`': colours as bare HSL\n * triplets (`0 0% 100%`), `--radius` as a length (`0.5rem`), anything else\n * in the loose value shape. See `isSchemeTokenEntry`.\n */\n tokens: Record<string, string>;\n}\n\n/** Every colour role in the contract (`type: 'color-hsl'`, `--heading` included). */\nexport const SCHEME_COLOR_TOKENS: ReadonlySet<string> = Object.freeze(\n new Set(\n Object.entries(THEME_TOKEN_CONTRACT)\n .filter(([, entry]) => entry.type === 'color-hsl')\n .map(([token]) => token),\n ),\n) as ReadonlySet<string>;\n\n/**\n * A scheme colour (`type: 'color-hsl'`): `H S% L%`, single-spaced, no `hsl()`\n * wrapper. Saturation and lightness are additionally capped at 100\n * (`isSchemeColorValue`); hue is bounded only by its three digits.\n */\nconst SCHEME_COLOR_VALUE =\n /^(\\d{1,3}(?:\\.\\d+)?) (\\d{1,3}(?:\\.\\d+)?)% (\\d{1,3}(?:\\.\\d+)?)%$/;\n\n/**\n * A scheme length (`type: 'length'`, i.e. `--radius`): px/rem/em, unit REQUIRED\n * (`0px`, not `0`). A bare `0` would turn `calc(var(--radius) - 4px)` into\n * invalid CSS — see the `length` note in `tokenContract.ts`.\n */\nconst SCHEME_RADIUS_VALUE = /^\\d{1,4}(?:\\.\\d+)?(?:px|rem|em)$/;\n\n/**\n * Any other scheme value — a font stack, a key the contract has not catalogued:\n * no `;`, `{`, `}` or control character. The server's `themeOverrides` value\n * shape (`^[^;{}\\p{Cntrl}]{1,256}$`); the length is checked separately in\n * UTF-16 units, as the server counts, since a `u`-flag quantifier counts code\n * points.\n */\nconst SCHEME_LOOSE_VALUE = /^[^;{}\\p{Cc}]+$/u;\nconst MAX_SCHEME_VALUE_LENGTH = 256;\n\n/** The four the owner edits, in panel order. Equal to the contract's editable colour tokens. */\nexport const SCHEME_ANCHOR_TOKENS = [\n '--background',\n '--foreground',\n '--card',\n '--card-foreground',\n] as const;\n\nexport type SchemeAnchorToken = (typeof SCHEME_ANCHOR_TOKENS)[number];\n\n/** Upper bound on schemes per configuration. */\nexport const MAX_THEME_SCHEMES = 16;\n\nconst SCHEME_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;\nconst MAX_SCHEME_NAME_LENGTH = 48;\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/**\n * Whether an untrusted value has a scheme's SHAPE.\n *\n * Token content is deliberately not judged here: `applyThemeOverrides` drops a\n * malformed key one entry at a time, exactly as it does for the flat store map\n * (and says so), so one bad token costs that token rather than the whole\n * palette. The typed value grammar is `isSchemeTokenEntry`, checked by writers.\n */\nexport function isThemeScheme(value: unknown): value is ThemeScheme {\n if (!isPlainObject(value)) {\n return false;\n }\n const { id, name, origin, tokens } = value;\n if (typeof id !== 'string' || !SCHEME_ID_PATTERN.test(id)) {\n return false;\n }\n if (\n name !== undefined &&\n (typeof name !== 'string' || name.length > MAX_SCHEME_NAME_LENGTH)\n ) {\n return false;\n }\n if (origin !== undefined && typeof origin !== 'string') {\n return false;\n }\n return (\n isPlainObject(tokens) &&\n Object.values(tokens).every((v) => typeof v === 'string')\n );\n}\n\n/**\n * The active scheme: the entry whose id is `activeThemeSchemeId`, else the\n * first entry, else null. Entries failing `isThemeScheme` are skipped first, so\n * a dangling id or a malformed entry falls through to the first usable one.\n */\nexport function resolveActiveScheme(\n cfg:\n | { themeSchemes?: unknown; activeThemeSchemeId?: string | null }\n | null\n | undefined,\n): ThemeScheme | null {\n if (!cfg || !Array.isArray(cfg.themeSchemes)) {\n return null;\n }\n const schemes = cfg.themeSchemes.filter(isThemeScheme);\n if (schemes.length === 0) {\n return null;\n }\n const activeId = cfg.activeThemeSchemeId;\n const active =\n typeof activeId === 'string'\n ? schemes.find((scheme) => scheme.id === activeId)\n : undefined;\n return active ?? schemes[0];\n}\n\n// ── Arithmetic copied from web50-shopify-adapter/src/theme-tokens.ts ────────\n\ninterface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nconst TRIPLET = /^(\\d{1,3}(?:\\.\\d+)?)\\s+(\\d{1,3}(?:\\.\\d+)?)%\\s+(\\d{1,3}(?:\\.\\d+)?)%$/;\n\n/**\n * A triplet as RGB in 0–255, NOT rounded to 8-bit — see the module header for\n * why. Same conversion as `colorFormat.hslTripletToHex`, minus its rounding.\n */\nfunction tripletToRgb(triplet: string): Rgb | null {\n const parts = TRIPLET.exec(triplet.trim());\n if (!parts || !isHslTriplet(triplet)) {\n return null;\n }\n const h = Number(parts[1]);\n const s = Number(parts[2]) / 100;\n const l = Number(parts[3]) / 100;\n\n const c = (1 - Math.abs(2 * l - 1)) * s;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = l - c / 2;\n const [r, g, b] =\n h < 60\n ? [c, x, 0]\n : h < 120\n ? [x, c, 0]\n : h < 180\n ? [0, c, x]\n : h < 240\n ? [0, x, c]\n : h < 300\n ? [x, 0, c]\n : [c, 0, x];\n return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };\n}\n\n/** Adapter `composite` for an opaque-over-opaque mix, via its `mix`: channels rounded to 8-bit. */\nfunction mix(fg: Rgb, ratio: number, bg: Rgb): Rgb {\n return {\n r: Math.round(fg.r * ratio + bg.r * (1 - ratio)),\n g: Math.round(fg.g * ratio + bg.g * (1 - ratio)),\n b: Math.round(fg.b * ratio + bg.b * (1 - ratio)),\n };\n}\n\n/** Adapter `toTriplet`: `\"H S% L%\"`, integer-rounded. */\nfunction toTriplet({ r, g, b }: Rgb): string {\n const rn = r / 255;\n const gn = g / 255;\n const bn = b / 255;\n const max = Math.max(rn, gn, bn);\n const min = Math.min(rn, gn, bn);\n const l = (max + min) / 2;\n const delta = max - min;\n\n let h = 0;\n let s = 0;\n if (delta !== 0) {\n s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n if (max === rn) {\n h = (gn - bn) / delta + (gn < bn ? 6 : 0);\n } else if (max === gn) {\n h = (bn - rn) / delta + 2;\n } else {\n h = (rn - gn) / delta + 4;\n }\n h *= 60;\n }\n return `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;\n}\n\n/** Tokens the adapter reads off the theme rather than computing from the anchors. */\nconst INHERITED_TOKENS = [\n '--primary',\n '--primary-foreground',\n '--secondary-foreground',\n '--accent-foreground',\n '--ring',\n '--border',\n '--input',\n '--heading',\n] as const;\n\n/**\n * A full colour-token map for a palette whose anchors the owner just edited.\n *\n * `anchors` win; everything the adapter derives from them is recomputed when\n * one of its inputs changed (and kept from `base` when none did — see \"Rounding\"\n * in the module header); everything it reads directly is taken from `base`.\n * Invalid triplets in either input are ignored, and a derived token whose\n * inputs are unavailable keeps `base`'s value, if any.\n *\n * Returns the whole scheme map, not only its colours: every non-colour entry of\n * `base` that passes `isSchemeTokenEntry` — `--radius`, a font stack, a token\n * this module does not know — is copied as is, so customizing a palette keeps\n * everything it states beyond colour. Every output entry passes\n * `isSchemeTokenEntry`.\n */\nexport function completeScheme(\n base: Record<string, string>,\n anchors: Partial<Record<SchemeAnchorToken, string>>,\n): Record<string, string> {\n // Both checks: `isHslTriplet` is what the arithmetic can convert, and the\n // scheme grammar is what a write accepts — failing either would poison a\n // derivation or get the whole save refused.\n const valid = (value: unknown): string | undefined =>\n typeof value === 'string' &&\n isHslTriplet(value) &&\n isSchemeColorValue(value.trim())\n ? value.trim()\n : undefined;\n const fromBase = (token: string): string | undefined => valid(base[token]);\n const fromAnchor = (token: SchemeAnchorToken): string | undefined =>\n valid(anchors[token]);\n\n const out: Record<string, string> = {};\n const put = (token: string, value: string | undefined): void => {\n if (value !== undefined) {\n out[token] = value;\n }\n };\n\n const background = fromAnchor('--background') ?? fromBase('--background');\n const foreground = fromAnchor('--foreground') ?? fromBase('--foreground');\n const bgChanged = background !== fromBase('--background');\n const fgChanged = foreground !== fromBase('--foreground');\n const bg = background === undefined ? null : tripletToRgb(background);\n const fg = foreground === undefined ? null : tripletToRgb(foreground);\n\n /** base's value while the inputs are unchanged, else the recomputation (else base's). */\n const derive = (\n token: string,\n inputsChanged: boolean,\n compute: () => string | undefined,\n ): string | undefined => {\n const kept = fromBase(token);\n return !inputsChanged && kept !== undefined ? kept : compute() ?? kept;\n };\n const mixOver = (over: Rgb | null, ratio: number) => (): string | undefined =>\n over !== null && bg !== null ? toTriplet(mix(over, ratio, bg)) : undefined;\n\n put('--background', background);\n put('--foreground', foreground);\n put(\n '--card',\n fromAnchor('--card') ??\n derive('--card', bgChanged || fgChanged, mixOver(fg, 0.04)),\n );\n put(\n '--card-foreground',\n fromAnchor('--card-foreground') ??\n derive('--card-foreground', fgChanged, () => foreground),\n );\n put('--popover', derive('--popover', bgChanged, () => background));\n put(\n '--popover-foreground',\n derive('--popover-foreground', fgChanged, () => foreground),\n );\n put('--muted', derive('--muted', bgChanged || fgChanged, mixOver(fg, 0.04)));\n put(\n '--muted-foreground',\n derive('--muted-foreground', bgChanged || fgChanged, mixOver(fg, 0.6)),\n );\n\n for (const token of INHERITED_TOKENS) {\n put(token, fromBase(token));\n }\n // Primary is inherited, so of the button family's inputs only the page can change.\n const primaryTriplet = out['--primary'];\n const primary =\n primaryTriplet === undefined ? null : tripletToRgb(primaryTriplet);\n put('--ring', out['--ring'] ?? primaryTriplet);\n put('--accent-foreground', out['--accent-foreground'] ?? primaryTriplet);\n put('--secondary', derive('--secondary', bgChanged, mixOver(primary, 0.1)));\n put('--accent', derive('--accent', bgChanged, mixOver(primary, 0.1)));\n\n // Not colours, so no arithmetic touches them: the palette keeps its shape,\n // its type, and any token a writer added that this module has never heard of.\n for (const [token, value] of Object.entries(base)) {\n if (!SCHEME_COLOR_TOKENS.has(token) && isSchemeTokenEntry(token, value)) {\n out[token] = value;\n }\n }\n\n return out;\n}\n\n/** The label the panel shows: the trimmed name, else `Palette N` (1-based). */\nexport function schemeDisplayName(scheme: ThemeScheme, index: number): string {\n const name = typeof scheme.name === 'string' ? scheme.name.trim() : '';\n return name !== '' ? name : `Palette ${index + 1}`;\n}\n\n/** `owner-N` with the smallest N ≥ 1 not already taken. */\nexport function nextOwnerSchemeId(schemes: readonly { id: string }[]): string {\n const taken = new Set(schemes.map((scheme) => scheme.id));\n let n = 1;\n while (taken.has(`owner-${n}`)) {\n n += 1;\n }\n return `owner-${n}`;\n}\n\n/** A colour value a scheme may hold: `SCHEME_COLOR_VALUE`, with S and L ≤ 100. */\nfunction isSchemeColorValue(value: string): boolean {\n const parts = SCHEME_COLOR_VALUE.exec(value);\n return parts !== null && Number(parts[2]) <= 100 && Number(parts[3]) <= 100;\n}\n\n/**\n * Whether a key/value pair may be written as a scheme token — the CLIENT's\n * contract, checked before the panel writes and by `completeScheme`.\n *\n * There is no allow-list: any key of the `themeOverrides` shape\n * (`THEME_OVERRIDE_KEY_PATTERN`) is a candidate. The value grammar follows the\n * key's contract type: `color-hsl` → an HSL triplet with S and L ≤ 100;\n * `length` → a px/rem/em length with its unit; anything else (font stacks,\n * keys the contract does not know) → the loose `themeOverrides` value shape.\n *\n * The server enforces only that loose shape for every key, so a `0 101% 50%`\n * colour or a unitless radius would be ACCEPTED there — and render wrong. That\n * is why the panel refuses them here. The renderer does not re-check values.\n */\nexport function isSchemeTokenEntry(key: string, value: unknown): boolean {\n if (typeof value !== 'string' || !THEME_OVERRIDE_KEY_PATTERN.test(key)) {\n return false;\n }\n switch (THEME_TOKEN_CONTRACT[key]?.type) {\n case 'color-hsl':\n return isSchemeColorValue(value);\n case 'length':\n return SCHEME_RADIUS_VALUE.test(value);\n default:\n return (\n value.length <= MAX_SCHEME_VALUE_LENGTH &&\n SCHEME_LOOSE_VALUE.test(value)\n );\n }\n}\n"],"mappings":";;;;;;;;;;AAsFA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AAvFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;;AAGA;;AAeA;AACO,MAAME,mBAAwC,GAAAC,OAAA,CAAAD,mBAAA,GAAGE,MAAM,CAACC,MAAM,CACnE,IAAIC,GAAG,CACLF,MAAM,CAACG,OAAO,CAACC,mCAAoB,CAAC,CACjCC,MAAM,CAAC,CAAC,GAAGC,KAAK,CAAC,KAAKA,KAAK,CAACC,IAAI,KAAK,WAAW,CAAC,CACjDC,GAAG,CAAC,CAAC,CAACC,KAAK,CAAC,KAAKA,KAAK,CAC3B,CACF,CAAwB;;AAExB;AACA;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,GACtB,iEAAiE;;AAEnE;AACA;AACA;AACA;AACA;AACA,MAAMC,mBAAmB,GAAG,kCAAkC;;AAE9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,GAAG,kBAAkB;AAC7C,MAAMC,uBAAuB,GAAG,GAAG;;AAEnC;AACO,MAAMC,oBAAoB,GAAAf,OAAA,CAAAe,oBAAA,GAAG,CAClC,cAAc,EACd,cAAc,EACd,QAAQ,EACR,mBAAmB,CACX;AAIV;AACO,MAAMC,iBAAiB,GAAAhB,OAAA,CAAAgB,iBAAA,GAAG,EAAE;AAEnC,MAAMC,iBAAiB,GAAG,2BAA2B;AACrD,MAAMC,sBAAsB,GAAG,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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_colorFormat","require","_tokenContract","SCHEME_COLOR_TOKENS","exports","Object","freeze","Set","entries","THEME_TOKEN_CONTRACT","filter","entry","type","map","token","SCHEME_COLOR_VALUE","SCHEME_RADIUS_VALUE","SCHEME_LOOSE_VALUE","MAX_SCHEME_VALUE_LENGTH","SCHEME_TOKENS","SCHEME_TOKEN_SET","schemeTokensOf","fromEntries","has","SCHEME_ANCHOR_TOKENS","MAX_THEME_SCHEMES","SCHEME_ID_PATTERN","MAX_SCHEME_NAME_LENGTH","isPlainObject","value","Array","isArray","isThemeScheme","id","name","origin","baseSchemeId","tokens","test","undefined","length","values","every","v","resolveActiveScheme","cfg","themeSchemes","schemes","activeId","activeThemeSchemeId","active","find","scheme","TRIPLET","tripletToRgb","triplet","parts","exec","trim","isHslTriplet","h","Number","s","l","c","Math","abs","x","m","r","g","b","mix","fg","ratio","bg","round","toTriplet","rn","gn","bn","max","min","delta","completeScheme","base","anchors","valid","isSchemeColorValue","fromBase","fromAnchor","out","put","background","foreground","bgChanged","fgChanged","derive","inputsChanged","compute","kept","mixOver","over","schemeDisplayName","index","nextOwnerSchemeId","taken","n","isSchemeTokenEntry","key","_THEME_TOKEN_CONTRACT","THEME_OVERRIDE_KEY_PATTERN"],"sources":["../../../src/theme/themeScheme.ts"],"sourcesContent":["/**\n * Named theme schemes on a site configuration, and the one that is active.\n *\n * A store's theme states a SET of palettes rather than one — Dawn and Horizon\n * ship `scheme-1`..`scheme-5` for the page, the cards, the hero band, the\n * footer. The configuration therefore carries a list of schemes plus the id of\n * the active one, beside the flat `themeOverrides` map it has always had:\n *\n * themeSchemes?: [{ id, name?, origin?, tokens: { '--background': '0 0% 100%', … } }]\n * activeThemeSchemeId?: 'scheme-1'\n *\n * A scheme's `tokens` are finished CSS tokens, spelled exactly as\n * `themeOverrides` spells them — and, like `themeOverrides`, the key set is\n * OPEN. Today's writers put the 18 colour roles (`SCHEME_COLOR_TOKENS`) there,\n * sometimes `--radius`; that a palette may carry shape as well as colour is why\n * this is a THEME scheme and not a colour scheme. A new token (a font stack,\n * something the contract has not catalogued yet) needs no release anywhere but\n * its writer. The server checks only the loose shape `themeOverrides` gets (key\n * `THEME_OVERRIDE_KEY_PATTERN`, a value free of `;`, `{`, `}` and control\n * characters, ≤ 256, at most 24 entries); the typed per-token grammar is the\n * CLIENT's contract, enforced by `isSchemeTokenEntry` before the panel writes.\n * Nothing is expanded at apply time: the reader resolves the active entry and\n * hands its map to `applyThemeOverrides`, which layers it between the store map\n * and the owner's overrides, filtered and bucketed exactly like the store map.\n * A configuration with no schemes renders exactly as it did before they existed.\n *\n * A leaf module beside `tokenContract.ts`, and for the same reason that file\n * documents: requiring core's ENTRY from plain Node fails on its CSS import,\n * but a deep import of a zero-CSS leaf works. It imports only its siblings\n * `./tokenContract` and `./colorFormat`, both leaves themselves.\n *\n * ## What a scheme carries (ADR 0243)\n *\n * A theme scheme is a background and its text, plus the colours mechanically\n * derived from those two: `SCHEME_TOKENS`. Card colours, button colours,\n * radius and fonts are the store's global set (`themeOverrides`) and the\n * owner's global edits (`userThemeOverrides`), applied under and over the\n * scheme respectively — so they survive every scheme switch. Rows written\n * before 0243 may still carry more; readers apply whatever a row holds, and\n * the owner panel writes only `SCHEME_TOKENS` into the rows it creates.\n *\n * An edited THEME scheme is an OWNER row that names it in `baseSchemeId`, so\n * the panel can show the edit on that scheme's tile and revert only that one.\n *\n * ## `completeScheme` — what the owner panel recomputes\n *\n * The owner edits the two anchors. The rest of the scheme has to move with\n * them the way `web50-shopify-adapter/src/theme-tokens.ts` would have moved it\n * had the theme stated those anchors, so the arithmetic below is a COPY of the\n * adapter's (`composite`/`mix`/`toTriplet` and the token assignments at the end\n * of `extractThemeOverrides`), integer rounding included. It is copied rather\n * than shared on purpose: the adapter must not import core.\n *\n * | token | role |\n * | ------------------------ | ------------------------------------------------------ |\n * | `--background` | anchor (else inherited from base) |\n * | `--foreground` | anchor (else inherited from base) |\n * | `--popover` | derived: = background |\n * | `--popover-foreground` | derived: = foreground |\n * | `--muted` | derived: foreground 4% over background |\n * | `--muted-foreground` | derived: foreground 60% over background |\n * | `--border` | inherited from base (no fallback — see below) |\n * | `--input` | inherited from base (no fallback — see below) |\n *\n * `--secondary`/`--accent` are NOT scheme tokens: the adapter mixes them from\n * the button colour, so they belong to the store's global set\n * (`themeOverrides`) with the buttons, and a scheme edit leaves them alone.\n * `--border`/`--input` are read straight off the\n * theme by the adapter, which reconstructs a missing border from the theme's\n * `*_border_opacity` setting a token map does not carry — so they are\n * inherited from base, and omitted when base lacks them, as the adapter omits\n * them.\n *\n * ## Rounding: why an unchanged input keeps base's value\n *\n * The adapter mixes 8-bit channels parsed from the theme's hex; a scheme only\n * has the integer-rounded triplet, and the hex cannot be recovered from it.\n * Re-deriving from triplets therefore lands a point off now and then — Horizon\n * `color_palette`'s `--muted-foreground` comes back `359 83% 68%` against the\n * adapter's `359 84% 68%`. So a derived token is recomputed only when one of\n * its INPUTS differs from base; otherwise base's value stands. A merchant who\n * edits nothing gets the adapter's map back exactly, and one who edits the\n * background gets the family recomputed.\n *\n * When it is recomputed, triplets convert back to RGB WITHOUT rounding to\n * 8-bit first — that would be a second quantisation the adapter never\n * performs, and enough to move a mixed colour's saturation by several points\n * (smallflower's button tint went from `230 38% 94%` to `230 42% 94%`). The mix result is rounded exactly where the adapter\n * rounds it.\n */\nimport { isHslTriplet } from './colorFormat';\nimport {\n THEME_OVERRIDE_KEY_PATTERN,\n THEME_TOKEN_CONTRACT,\n} from './tokenContract';\n\n/** Where a scheme came from. Any other value on the wire reads as unknown. */\nexport type SchemeOrigin = 'UNKNOWN_SCHEME_ORIGIN' | 'THEME' | 'OWNER';\n\n/** One named palette as the configuration carries it. */\nexport interface ThemeScheme {\n /** `^[a-z0-9][a-z0-9-]{0,31}$`, unique within the list. */\n id: string;\n /** Shown in the owner panel; at most 48 characters. */\n name?: string;\n origin?: SchemeOrigin | string;\n /**\n * On an OWNER row: the id of the THEME scheme it is an edit of. Not the\n * row's own id, unique across rows (at most one edit per scheme), and it may\n * dangle — a theme publish can remove the base, and the edit survives it.\n */\n baseSchemeId?: string;\n /**\n * Token → value, keys as open as `themeOverrides`': colours as bare HSL\n * triplets (`0 0% 100%`), `--radius` as a length (`0.5rem`), anything else\n * in the loose value shape. See `isSchemeTokenEntry`.\n */\n tokens: Record<string, string>;\n}\n\n/** Every colour role in the contract (`type: 'color-hsl'`, `--heading` included). */\nexport const SCHEME_COLOR_TOKENS: ReadonlySet<string> = Object.freeze(\n new Set(\n Object.entries(THEME_TOKEN_CONTRACT)\n .filter(([, entry]) => entry.type === 'color-hsl')\n .map(([token]) => token),\n ),\n) as ReadonlySet<string>;\n\n/**\n * A scheme colour (`type: 'color-hsl'`): `H S% L%`, single-spaced, no `hsl()`\n * wrapper. Saturation and lightness are additionally capped at 100\n * (`isSchemeColorValue`); hue is bounded only by its three digits.\n */\nconst SCHEME_COLOR_VALUE =\n /^(\\d{1,3}(?:\\.\\d+)?) (\\d{1,3}(?:\\.\\d+)?)% (\\d{1,3}(?:\\.\\d+)?)%$/;\n\n/**\n * A scheme length (`type: 'length'`, i.e. `--radius`): px/rem/em, unit REQUIRED\n * (`0px`, not `0`). A bare `0` would turn `calc(var(--radius) - 4px)` into\n * invalid CSS — see the `length` note in `tokenContract.ts`.\n */\nconst SCHEME_RADIUS_VALUE = /^\\d{1,4}(?:\\.\\d+)?(?:px|rem|em)$/;\n\n/**\n * Any other scheme value — a font stack, a key the contract has not catalogued:\n * no `;`, `{`, `}` or control character. The server's `themeOverrides` value\n * shape (`^[^;{}\\p{Cntrl}]{1,256}$`); the length is checked separately in\n * UTF-16 units, as the server counts, since a `u`-flag quantifier counts code\n * points.\n */\nconst SCHEME_LOOSE_VALUE = /^[^;{}\\p{Cc}]+$/u;\nconst MAX_SCHEME_VALUE_LENGTH = 256;\n\n/**\n * What a scheme is (ADR 0243): its background and text, and the colours\n * derived from those two. The panel writes exactly these into the OWNER rows\n * it creates, and mirrors exactly these of the active row into `themeOverrides`.\n */\nexport const SCHEME_TOKENS = [\n '--background',\n '--foreground',\n '--popover',\n '--popover-foreground',\n '--muted',\n '--muted-foreground',\n '--border',\n '--input',\n] as const;\n\nexport type SchemeToken = (typeof SCHEME_TOKENS)[number];\n\nconst SCHEME_TOKEN_SET: ReadonlySet<string> = new Set(SCHEME_TOKENS);\n\n/** Only the `SCHEME_TOKENS` entries of `map`. */\nexport function schemeTokensOf(\n map: Record<string, string> | null | undefined,\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(map ?? {}).filter(([token]) => SCHEME_TOKEN_SET.has(token)),\n );\n}\n\n/** The two the owner edits on a scheme, in panel order. */\nexport const SCHEME_ANCHOR_TOKENS = ['--background', '--foreground'] as const;\n\nexport type SchemeAnchorToken = (typeof SCHEME_ANCHOR_TOKENS)[number];\n\n/** Upper bound on schemes per configuration. */\nexport const MAX_THEME_SCHEMES = 16;\n\nconst SCHEME_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;\nconst MAX_SCHEME_NAME_LENGTH = 48;\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/**\n * Whether an untrusted value has a scheme's SHAPE.\n *\n * Token content is deliberately not judged here: `applyThemeOverrides` drops a\n * malformed key one entry at a time, exactly as it does for the flat store map\n * (and says so), so one bad token costs that token rather than the whole\n * palette. The typed value grammar is `isSchemeTokenEntry`, checked by writers.\n */\nexport function isThemeScheme(value: unknown): value is ThemeScheme {\n if (!isPlainObject(value)) {\n return false;\n }\n const { id, name, origin, baseSchemeId, tokens } = value;\n if (typeof id !== 'string' || !SCHEME_ID_PATTERN.test(id)) {\n return false;\n }\n if (baseSchemeId !== undefined && typeof baseSchemeId !== 'string') {\n return false;\n }\n if (\n name !== undefined &&\n (typeof name !== 'string' || name.length > MAX_SCHEME_NAME_LENGTH)\n ) {\n return false;\n }\n if (origin !== undefined && typeof origin !== 'string') {\n return false;\n }\n return (\n isPlainObject(tokens) &&\n Object.values(tokens).every((v) => typeof v === 'string')\n );\n}\n\n/**\n * The active scheme: the entry whose id is `activeThemeSchemeId`, else the\n * first entry, else null. Entries failing `isThemeScheme` are skipped first, so\n * a dangling id or a malformed entry falls through to the first usable one.\n */\nexport function resolveActiveScheme(\n cfg:\n | { themeSchemes?: unknown; activeThemeSchemeId?: string | null }\n | null\n | undefined,\n): ThemeScheme | null {\n if (!cfg || !Array.isArray(cfg.themeSchemes)) {\n return null;\n }\n const schemes = cfg.themeSchemes.filter(isThemeScheme);\n if (schemes.length === 0) {\n return null;\n }\n const activeId = cfg.activeThemeSchemeId;\n const active =\n typeof activeId === 'string'\n ? schemes.find((scheme) => scheme.id === activeId)\n : undefined;\n return active ?? schemes[0];\n}\n\n// ── Arithmetic copied from web50-shopify-adapter/src/theme-tokens.ts ────────\n\ninterface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nconst TRIPLET =\n /^(\\d{1,3}(?:\\.\\d+)?)\\s+(\\d{1,3}(?:\\.\\d+)?)%\\s+(\\d{1,3}(?:\\.\\d+)?)%$/;\n\n/**\n * A triplet as RGB in 0–255, NOT rounded to 8-bit — see the module header for\n * why. Same conversion as `colorFormat.hslTripletToHex`, minus its rounding.\n */\nfunction tripletToRgb(triplet: string): Rgb | null {\n const parts = TRIPLET.exec(triplet.trim());\n if (!parts || !isHslTriplet(triplet)) {\n return null;\n }\n const h = Number(parts[1]);\n const s = Number(parts[2]) / 100;\n const l = Number(parts[3]) / 100;\n\n const c = (1 - Math.abs(2 * l - 1)) * s;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = l - c / 2;\n const [r, g, b] =\n h < 60\n ? [c, x, 0]\n : h < 120\n ? [x, c, 0]\n : h < 180\n ? [0, c, x]\n : h < 240\n ? [0, x, c]\n : h < 300\n ? [x, 0, c]\n : [c, 0, x];\n return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };\n}\n\n/** Adapter `composite` for an opaque-over-opaque mix, via its `mix`: channels rounded to 8-bit. */\nfunction mix(fg: Rgb, ratio: number, bg: Rgb): Rgb {\n return {\n r: Math.round(fg.r * ratio + bg.r * (1 - ratio)),\n g: Math.round(fg.g * ratio + bg.g * (1 - ratio)),\n b: Math.round(fg.b * ratio + bg.b * (1 - ratio)),\n };\n}\n\n/** Adapter `toTriplet`: `\"H S% L%\"`, integer-rounded. */\nfunction toTriplet({ r, g, b }: Rgb): string {\n const rn = r / 255;\n const gn = g / 255;\n const bn = b / 255;\n const max = Math.max(rn, gn, bn);\n const min = Math.min(rn, gn, bn);\n const l = (max + min) / 2;\n const delta = max - min;\n\n let h = 0;\n let s = 0;\n if (delta !== 0) {\n s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n if (max === rn) {\n h = (gn - bn) / delta + (gn < bn ? 6 : 0);\n } else if (max === gn) {\n h = (bn - rn) / delta + 2;\n } else {\n h = (rn - gn) / delta + 4;\n }\n h *= 60;\n }\n return `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;\n}\n\n/**\n * The `SCHEME_TOKENS` of a scheme whose anchors the owner just edited.\n *\n * `anchors` win; everything the adapter derives from them is recomputed when\n * one of its inputs changed (and kept from `base` when none did — see \"Rounding\"\n * in the module header); `--border`/`--input` are taken from `base`. Invalid\n * triplets in any input are ignored, and a derived token whose inputs are\n * unavailable keeps `base`'s value, if any.\n *\n * Returns ONLY `SCHEME_TOKENS`: whatever else `base` carries (a pre-0243 row's\n * card, button or secondary/accent colours, its radius) is the store's global set now, not the\n * scheme's, and is dropped. Every output entry passes `isSchemeTokenEntry`.\n */\nexport function completeScheme(\n base: Record<string, string>,\n anchors: Partial<Record<SchemeAnchorToken, string>>,\n): Record<string, string> {\n // Both checks: `isHslTriplet` is what the arithmetic can convert, and the\n // scheme grammar is what a write accepts — failing either would poison a\n // derivation or get the whole save refused.\n const valid = (value: unknown): string | undefined =>\n typeof value === 'string' &&\n isHslTriplet(value) &&\n isSchemeColorValue(value.trim())\n ? value.trim()\n : undefined;\n const fromBase = (token: string): string | undefined => valid(base[token]);\n const fromAnchor = (token: SchemeAnchorToken): string | undefined =>\n valid(anchors[token]);\n\n const out: Record<string, string> = {};\n const put = (token: string, value: string | undefined): void => {\n if (value !== undefined) {\n out[token] = value;\n }\n };\n\n const background = fromAnchor('--background') ?? fromBase('--background');\n const foreground = fromAnchor('--foreground') ?? fromBase('--foreground');\n const bgChanged = background !== fromBase('--background');\n const fgChanged = foreground !== fromBase('--foreground');\n const bg = background === undefined ? null : tripletToRgb(background);\n const fg = foreground === undefined ? null : tripletToRgb(foreground);\n\n /** base's value while the inputs are unchanged, else the recomputation (else base's). */\n const derive = (\n token: string,\n inputsChanged: boolean,\n compute: () => string | undefined,\n ): string | undefined => {\n const kept = fromBase(token);\n return !inputsChanged && kept !== undefined ? kept : compute() ?? kept;\n };\n const mixOver = (over: Rgb | null, ratio: number) => (): string | undefined =>\n over !== null && bg !== null ? toTriplet(mix(over, ratio, bg)) : undefined;\n\n put('--background', background);\n put('--foreground', foreground);\n put(\n '--popover',\n derive('--popover', bgChanged, () => background),\n );\n put(\n '--popover-foreground',\n derive('--popover-foreground', fgChanged, () => foreground),\n );\n put('--muted', derive('--muted', bgChanged || fgChanged, mixOver(fg, 0.04)));\n put(\n '--muted-foreground',\n derive('--muted-foreground', bgChanged || fgChanged, mixOver(fg, 0.6)),\n );\n\n put('--border', fromBase('--border'));\n put('--input', fromBase('--input'));\n\n return out;\n}\n\n/** The label the panel shows: the trimmed name, else `Palette N` (1-based). */\nexport function schemeDisplayName(scheme: ThemeScheme, index: number): string {\n const name = typeof scheme.name === 'string' ? scheme.name.trim() : '';\n return name !== '' ? name : `Palette ${index + 1}`;\n}\n\n/** `owner-N` with the smallest N ≥ 1 not already taken. */\nexport function nextOwnerSchemeId(schemes: readonly { id: string }[]): string {\n const taken = new Set(schemes.map((scheme) => scheme.id));\n let n = 1;\n while (taken.has(`owner-${n}`)) {\n n += 1;\n }\n return `owner-${n}`;\n}\n\n/** A colour value a scheme may hold: `SCHEME_COLOR_VALUE`, with S and L ≤ 100. */\nfunction isSchemeColorValue(value: string): boolean {\n const parts = SCHEME_COLOR_VALUE.exec(value);\n return parts !== null && Number(parts[2]) <= 100 && Number(parts[3]) <= 100;\n}\n\n/**\n * Whether a key/value pair may be written as a scheme token — the CLIENT's\n * contract, checked before the panel writes and by `completeScheme`.\n *\n * There is no allow-list: any key of the `themeOverrides` shape\n * (`THEME_OVERRIDE_KEY_PATTERN`) is a candidate. The value grammar follows the\n * key's contract type: `color-hsl` → an HSL triplet with S and L ≤ 100;\n * `length` → a px/rem/em length with its unit; anything else (font stacks,\n * keys the contract does not know) → the loose `themeOverrides` value shape.\n *\n * The server enforces only that loose shape for every key, so a `0 101% 50%`\n * colour or a unitless radius would be ACCEPTED there — and render wrong. That\n * is why the panel refuses them here. The renderer does not re-check values.\n */\nexport function isSchemeTokenEntry(key: string, value: unknown): boolean {\n if (typeof value !== 'string' || !THEME_OVERRIDE_KEY_PATTERN.test(key)) {\n return false;\n }\n switch (THEME_TOKEN_CONTRACT[key]?.type) {\n case 'color-hsl':\n return isSchemeColorValue(value);\n case 'length':\n return SCHEME_RADIUS_VALUE.test(value);\n default:\n return (\n value.length <= MAX_SCHEME_VALUE_LENGTH &&\n SCHEME_LOOSE_VALUE.test(value)\n );\n }\n}\n"],"mappings":";;;;;;;;;;;AA0FA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AA3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;;AAGA;;AAqBA;AACO,MAAME,mBAAwC,GAAAC,OAAA,CAAAD,mBAAA,GAAGE,MAAM,CAACC,MAAM,CACnE,IAAIC,GAAG,CACLF,MAAM,CAACG,OAAO,CAACC,mCAAoB,CAAC,CACjCC,MAAM,CAAC,CAAC,GAAGC,KAAK,CAAC,KAAKA,KAAK,CAACC,IAAI,KAAK,WAAW,CAAC,CACjDC,GAAG,CAAC,CAAC,CAACC,KAAK,CAAC,KAAKA,KAAK,CAC3B,CACF,CAAwB;;AAExB;AACA;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,GACtB,iEAAiE;;AAEnE;AACA;AACA;AACA;AACA;AACA,MAAMC,mBAAmB,GAAG,kCAAkC;;AAE9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,GAAG,kBAAkB;AAC7C,MAAMC,uBAAuB,GAAG,GAAG;;AAEnC;AACA;AACA;AACA;AACA;AACO,MAAMC,aAAa,GAAAf,OAAA,CAAAe,aAAA,GAAG,CAC3B,cAAc,EACd,cAAc,EACd,WAAW,EACX,sBAAsB,EACtB,SAAS,EACT,oBAAoB,EACpB,UAAU,EACV,SAAS,CACD;AAIV,MAAMC,gBAAqC,GAAG,IAAIb,G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","ignoreList":[]}
|
|
@@ -104,15 +104,63 @@ function wellFormedEntries(overrides) {
|
|
|
104
104
|
* which core consumes only as a fallback the template can beat.
|
|
105
105
|
*/
|
|
106
106
|
const bucketed = key => bucketOf(key) === 'brand' ? key : hostAliasFor(key);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The declarations the three layers resolve to, in the order they are written:
|
|
110
|
+
* the store map bucketed, then the active scheme bucketed the same way, then
|
|
111
|
+
* the owner's overrides as their real names. Later entries win.
|
|
112
|
+
*
|
|
113
|
+
* Pure apart from the malformed-key warning, so a second writer — the owner
|
|
114
|
+
* panel's live preview — paints exactly what a saved configuration will render
|
|
115
|
+
* rather than a reconstruction of it.
|
|
116
|
+
*/
|
|
117
|
+
export function themeOverrideDeclarations(overrides, userOverrides, schemeTokens) {
|
|
118
|
+
return [
|
|
119
|
+
// Brand wins over the template, so it is written as the token the
|
|
120
|
+
// stylesheets actually read. Everything else lands in the host namespace,
|
|
121
|
+
// where core consumes it only as a fallback the template can beat.
|
|
122
|
+
...wellFormedEntries(overrides).map(_ref2 => {
|
|
123
|
+
let [token, value] = _ref2;
|
|
124
|
+
return {
|
|
125
|
+
token,
|
|
126
|
+
value,
|
|
127
|
+
writtenAs: bucketed(token),
|
|
128
|
+
source: 'store'
|
|
129
|
+
};
|
|
130
|
+
}),
|
|
131
|
+
// The active scheme over the store map, bucketed the same way: a brand
|
|
132
|
+
// token as itself, `--radius` and unknown keys as their alias. Either way
|
|
133
|
+
// this is the later write of that property, so it beats the store's — and
|
|
134
|
+
// a template's `--radius` still beats the alias.
|
|
135
|
+
...wellFormedEntries(schemeTokens).map(_ref3 => {
|
|
136
|
+
let [token, value] = _ref3;
|
|
137
|
+
return {
|
|
138
|
+
token,
|
|
139
|
+
value,
|
|
140
|
+
writtenAs: bucketed(token),
|
|
141
|
+
source: 'scheme'
|
|
142
|
+
};
|
|
143
|
+
}),
|
|
144
|
+
// Owner choices last and never aliased: within one declaration block the
|
|
145
|
+
// last write of a property wins, so a token both maps carry ends up the
|
|
146
|
+
// owner's.
|
|
147
|
+
...wellFormedEntries(userOverrides).map(_ref4 => {
|
|
148
|
+
let [token, value] = _ref4;
|
|
149
|
+
return {
|
|
150
|
+
token,
|
|
151
|
+
value,
|
|
152
|
+
writtenAs: token,
|
|
153
|
+
source: 'user'
|
|
154
|
+
};
|
|
155
|
+
})];
|
|
156
|
+
}
|
|
107
157
|
export function applyThemeOverrides(overrides, userOverrides, schemeTokens) {
|
|
108
158
|
if (typeof document === 'undefined') {
|
|
109
159
|
return;
|
|
110
160
|
}
|
|
111
161
|
const existing = document.head.querySelector(`style[${MARKER_ATTR}]`);
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
const activeSchemeEntries = wellFormedEntries(schemeTokens);
|
|
115
|
-
if (entries.length === 0 && activeSchemeEntries.length === 0 && userEntries.length === 0) {
|
|
162
|
+
const declarations = themeOverrideDeclarations(overrides, userOverrides, schemeTokens);
|
|
163
|
+
if (declarations.length === 0) {
|
|
116
164
|
existing == null || existing.remove();
|
|
117
165
|
// Nothing to apply is itself a traceable answer: it means every token on
|
|
118
166
|
// the page is the template's, which is otherwise indistinguishable from
|
|
@@ -131,37 +179,14 @@ export function applyThemeOverrides(overrides, userOverrides, schemeTokens) {
|
|
|
131
179
|
sheet.insertRule(`${WEB5_SCOPE} {}`, 0);
|
|
132
180
|
const rule = sheet.cssRules[0];
|
|
133
181
|
const applied = [];
|
|
134
|
-
|
|
182
|
+
for (const declaration of declarations) {
|
|
135
183
|
try {
|
|
136
|
-
rule.style.setProperty(
|
|
137
|
-
applied.push(
|
|
138
|
-
token: key,
|
|
139
|
-
value,
|
|
140
|
-
writtenAs: target,
|
|
141
|
-
source
|
|
142
|
-
});
|
|
184
|
+
rule.style.setProperty(declaration.writtenAs, declaration.value);
|
|
185
|
+
applied.push(declaration);
|
|
143
186
|
} catch {
|
|
144
187
|
// An engine that rejects the value leaves the token at its baked
|
|
145
188
|
// default — degraded theming, never broken CSS.
|
|
146
189
|
}
|
|
147
|
-
};
|
|
148
|
-
for (const [key, value] of entries) {
|
|
149
|
-
// Brand wins over the template, so it is written as the token the
|
|
150
|
-
// stylesheets actually read. Everything else lands in the host namespace,
|
|
151
|
-
// where core consumes it only as a fallback the template can beat.
|
|
152
|
-
write(key, value, bucketed(key), 'store');
|
|
153
|
-
}
|
|
154
|
-
// The active scheme over the store map, bucketed the same way: a brand token
|
|
155
|
-
// as itself, `--radius` and unknown keys as their alias. Either way this is
|
|
156
|
-
// the later write of that property, so it beats the store's — and a
|
|
157
|
-
// template's `--radius` still beats the alias.
|
|
158
|
-
for (const [key, value] of activeSchemeEntries) {
|
|
159
|
-
write(key, value, bucketed(key), 'scheme');
|
|
160
|
-
}
|
|
161
|
-
// Owner choices last and never aliased: within one declaration block the last
|
|
162
|
-
// write of a property wins, so a token both maps carry ends up the owner's.
|
|
163
|
-
for (const [key, value] of userEntries) {
|
|
164
|
-
write(key, value, key, 'user');
|
|
165
190
|
}
|
|
166
191
|
// Replace-on-reapply: the fresh element is appended (so it stays last in
|
|
167
192
|
// document order) before the stale one is dropped.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["WEB5_SCOPE","traceThemeOverrides","THEME_OVERRIDE_KEY_PATTERN","THEME_TOKEN_CONTRACT","bucketOf","hostAliasFor","THEME_OVERRIDE_TOKENS","Set","Object","keys","MARKER_ATTR","wellFormedEntries","overrides","entries","filter","_ref","key","wellFormed","test","console","warn","bucketed","applyThemeOverrides","userOverrides","schemeTokens","document","existing","head","querySelector","userEntries","activeSchemeEntries","length","remove","style","createElement","setAttribute","appendChild","sheet","insertRule","rule","cssRules","applied","write","value","target","source","setProperty","push","token","writtenAs"],"sources":["../../../src/client/applyThemeOverrides.ts"],"sourcesContent":["/**\n * Runtime theme token injection (DL #131).\n *\n * `Configuration.themeOverrides` carries per-store CSS custom-property\n * overrides (`--primary`, `--radius`, `--heading`, ...) computed from the\n * store's own theme (e.g. the Shopify `settings_data.json` extractor). This\n * applies them to the page so they win over the bundle's baked `theme.css`:\n *\n * - **Scoped, not `:root`**: the rule targets `WEB5_SCOPE`, the same\n * `:is(#root, .w5-root, [data-web5-placement], .debug-view)` selector every\n * compiled bundle stylesheet uses — host-page styling is never touched, and\n * equal specificity + later document order makes the override win. Callers\n * must therefore apply AFTER the client bundle's CSS is in the document.\n * - **Bucketed, since DL #193**: a `brand` token (colour roles, font families)\n * is written as itself, so the store's identity beats the template's. Every\n * other key — `host` tokens and anything the contract has never heard of —\n * is written as its `--web5-host-*` alias, which core's stylesheets consume\n * as a `var()` fallback. A template stating the real token therefore wins on\n * shape, and an unknown key is inert rather than dangerous: a custom property\n * nothing references renders nothing, so an adapter that learns to read a new\n * token cannot silently override a template.\n * - **The token set stays open, but the destination changed.** Before DL #193\n * an unrecognised key was applied verbatim, so a template could consume\n * `var(--foo)` and grow a token with no release. It now arrives as\n * `--web5-host-foo`, so the template consumes `var(--web5-host-foo, <default>)`\n * instead. One line different, and the provenance is explicit — the wiring\n * line is what activates a host token, not the contract entry.\n * - The mandatory `--` prefix means an override can only define custom\n * properties — it can never set a real CSS property inside the scope. The\n * server enforces the same shape (plus value sanitation) at write time.\n * - **Values are inert**: entries are written with\n * `CSSStyleDeclaration.setProperty`, never string-concatenated into CSS, so\n * a hostile value cannot terminate the declaration or open a new rule.\n * - **The shop owner is the last word (DL #193)**: `userOverrides` carries the\n * choices a human made in the owner panel, and every one of them is written\n * as the real token whatever its bucket. Bucketing exists to arbitrate a\n * disagreement between a store and a template; an owner who opened a panel\n * and set a value has already settled that argument, so aliasing theirs would\n * let the template overrule the person who chose. They are written last, so a\n * token both maps carry resolves to the owner's value.\n * - **The active theme scheme sits between the two**: `schemeTokens` is the\n * resolved entry of `Configuration.themeSchemes` (see `theme/themeScheme`).\n * It is written after the store map and before the owner's overrides, under\n * the SAME bucket rule as the store map: a `brand` token (colours, fonts) as\n * the real token, anything else — `--radius`, a key the contract has never\n * heard of — as its `--web5-host-*` alias. Being the later write of either\n * property, the chosen palette beats the flat store map on colours and on\n * radius alike — yet a template that states `--radius` still wins on shape,\n * exactly as it does over an imported radius. A scheme is written like the\n * store map it stands in for, not like an owner override, so it gets no\n * exemption from aliasing; the owner's layer still wins over it. Its entries\n * are filtered exactly like the store map's too: the same key check, the same\n * warning, and no per-type value check — `setProperty` keeps any value inert,\n * and the typed grammar (`isSchemeTokenEntry`) is the panel's to enforce\n * before a write. So the scheme token set is as open as `themeOverrides`: a\n * new scheme token needs no release here. Absent → exactly the pre-scheme\n * behaviour.\n * - **Idempotent**: one marker element per document, replaced wholesale on\n * re-apply; empty/absent input (all three layers) removes it.\n */\nimport { WEB5_SCOPE } from '../hostScope';\nimport {\n traceThemeOverrides,\n type AppliedToken,\n type ThemeOverrideSource,\n} from './themeDebug';\nimport {\n THEME_OVERRIDE_KEY_PATTERN,\n THEME_TOKEN_CONTRACT,\n bucketOf,\n hostAliasFor,\n} from '../theme/tokenContract';\n\n/** A themeOverrides key: always a CSS custom property. */\nexport type ThemeOverrideKey = `--${string}`;\n\n/**\n * Writer-side shape for a theme override map. The catalog below documents\n * the tokens the seed consumes today; the type stays open so new tokens\n * flow end-to-end with no release anywhere but the seed.\n */\nexport type ThemeOverrides = Record<ThemeOverrideKey, string>;\n\n/**\n * The known token catalog. GUIDANCE, NOT A GATE — `applyThemeOverrides` still\n * applies any well-formed custom property, so the vocabulary can grow without a\n * release here.\n *\n * Derived from `@wix/web5-token-contract` rather than restated, because two\n * hand-maintained copies of one list is how they drift. The contract also\n * carries what this Set cannot: which bucket each token is in, and therefore\n * who wins when a store and a template disagree.\n */\nexport const THEME_OVERRIDE_TOKENS: ReadonlySet<string> = new Set(\n Object.keys(THEME_TOKEN_CONTRACT),\n);\n\nconst MARKER_ATTR = 'data-web5-theme-overrides';\n\n/**\n * Drops keys that are not well-formed custom properties, warning about each.\n * Used for all three layers — store, scheme and owner.\n */\nfunction wellFormedEntries(\n overrides?: Record<string, string> | null,\n): [string, string][] {\n return Object.entries(overrides ?? {}).filter(([key]) => {\n const wellFormed = THEME_OVERRIDE_KEY_PATTERN.test(key);\n if (!wellFormed) {\n console.warn(\n `[web5-theme] Skipping malformed theme override key: ${key}`,\n );\n }\n return wellFormed;\n });\n}\n\n/**\n * Where a store-side token lands: a `brand` token as itself, so the store's\n * identity beats the template's; everything else as its `--web5-host-*` alias,\n * which core consumes only as a fallback the template can beat.\n */\nconst bucketed = (key: string): string =>\n bucketOf(key) === 'brand' ? key : hostAliasFor(key);\n\nexport function applyThemeOverrides(\n overrides?: Record<string, string> | null,\n userOverrides?: Record<string, string> | null,\n schemeTokens?: Record<string, string> | null,\n): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n const existing = document.head.querySelector(`style[${MARKER_ATTR}]`);\n const entries = wellFormedEntries(overrides);\n const userEntries = wellFormedEntries(userOverrides);\n const activeSchemeEntries = wellFormedEntries(schemeTokens);\n\n if (\n entries.length === 0 &&\n activeSchemeEntries.length === 0 &&\n userEntries.length === 0\n ) {\n existing?.remove();\n // Nothing to apply is itself a traceable answer: it means every token on\n // the page is the template's, which is otherwise indistinguishable from\n // tracing having failed.\n traceThemeOverrides([]);\n return;\n }\n\n const style = document.createElement('style');\n style.setAttribute(MARKER_ATTR, '');\n document.head.appendChild(style);\n const sheet = style.sheet;\n if (!sheet) {\n style.remove();\n return;\n }\n sheet.insertRule(`${WEB5_SCOPE} {}`, 0);\n const rule = sheet.cssRules[0] as CSSStyleRule;\n const applied: AppliedToken[] = [];\n const write = (\n key: string,\n value: string,\n target: string,\n source: ThemeOverrideSource,\n ): void => {\n try {\n rule.style.setProperty(target, value);\n applied.push({ token: key, value, writtenAs: target, source });\n } catch {\n // An engine that rejects the value leaves the token at its baked\n // default — degraded theming, never broken CSS.\n }\n };\n\n for (const [key, value] of entries) {\n // Brand wins over the template, so it is written as the token the\n // stylesheets actually read. Everything else lands in the host namespace,\n // where core consumes it only as a fallback the template can beat.\n write(key, value, bucketed(key), 'store');\n }\n // The active scheme over the store map, bucketed the same way: a brand token\n // as itself, `--radius` and unknown keys as their alias. Either way this is\n // the later write of that property, so it beats the store's — and a\n // template's `--radius` still beats the alias.\n for (const [key, value] of activeSchemeEntries) {\n write(key, value, bucketed(key), 'scheme');\n }\n // Owner choices last and never aliased: within one declaration block the last\n // write of a property wins, so a token both maps carry ends up the owner's.\n for (const [key, value] of userEntries) {\n write(key, value, key, 'user');\n }\n // Replace-on-reapply: the fresh element is appended (so it stays last in\n // document order) before the stale one is dropped.\n existing?.remove();\n // AFTER the stale element is gone, so the resolved values traced below are\n // the ones the page will actually render. Off unless explicitly enabled.\n traceThemeOverrides(applied);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,UAAU,QAAQ,cAAc;AACzC,SACEC,mBAAmB,QAGd,cAAc;AACrB,SACEC,0BAA0B,EAC1BC,oBAAoB,EACpBC,QAAQ,EACRC,YAAY,QACP,wBAAwB;;AAE/B;;AAGA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,qBAA0C,GAAG,IAAIC,GAAG,CAC/DC,MAAM,CAACC,IAAI,CAACN,oBAAoB,CAClC,CAAC;AAED,MAAMO,WAAW,GAAG,2BAA2B;;AAE/C;AACA;AACA;AACA;AACA,SAASC,iBAAiBA,CACxBC,SAAyC,EACrB;EACpB,OAAOJ,MAAM,CAACK,OAAO,CAACD,SAAS,IAAI,CAAC,CAAC,CAAC,CAACE,MAAM,CAACC,IAAA,IAAW;IAAA,IAAV,CAACC,GAAG,CAAC,GAAAD,IAAA;IAClD,MAAME,UAAU,GAAGf,0BAA0B,CAACgB,IAAI,CAACF,GAAG,CAAC;IACvD,IAAI,CAACC,UAAU,EAAE;MACfE,OAAO,CAACC,IAAI,CACV,uDAAuDJ,GAAG,EAC5D,CAAC;IACH;IACA,OAAOC,UAAU;EACnB,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAMI,QAAQ,GAAIL,GAAW,IAC3BZ,QAAQ,CAACY,GAAG,CAAC,KAAK,OAAO,GAAGA,GAAG,GAAGX,YAAY,CAACW,GAAG,CAAC;AAErD,OAAO,SAASM,mBAAmBA,CACjCV,SAAyC,EACzCW,aAA6C,EAC7CC,YAA4C,EACtC;EACN,IAAI,OAAOC,QAAQ,KAAK,WAAW,EAAE;IACnC;EACF;EAEA,MAAMC,QAAQ,GAAGD,QAAQ,CAACE,IAAI,CAACC,aAAa,CAAC,SAASlB,WAAW,GAAG,CAAC;EACrE,MAAMG,OAAO,GAAGF,iBAAiB,CAACC,SAAS,CAAC;EAC5C,MAAMiB,WAAW,GAAGlB,iBAAiB,CAACY,aAAa,CAAC;EACpD,MAAMO,mBAAmB,GAAGnB,iBAAiB,CAACa,YAAY,CAAC;EAE3D,IACEX,OAAO,CAACkB,MAAM,KAAK,CAAC,IACpBD,mBAAmB,CAACC,MAAM,KAAK,CAAC,IAChCF,WAAW,CAACE,MAAM,KAAK,CAAC,EACxB;IACAL,QAAQ,YAARA,QAAQ,CAAEM,MAAM,CAAC,CAAC;IAClB;IACA;IACA;IACA/B,mBAAmB,CAAC,EAAE,CAAC;IACvB;EACF;EAEA,MAAMgC,KAAK,GAAGR,QAAQ,CAACS,aAAa,CAAC,OAAO,CAAC;EAC7CD,KAAK,CAACE,YAAY,CAACzB,WAAW,EAAE,EAAE,CAAC;EACnCe,QAAQ,CAACE,IAAI,CAACS,WAAW,CAACH,KAAK,CAAC;EAChC,MAAMI,KAAK,GAAGJ,KAAK,CAACI,KAAK;EACzB,IAAI,CAACA,KAAK,EAAE;IACVJ,KAAK,CAACD,MAAM,CAAC,CAAC;IACd;EACF;EACAK,KAAK,CAACC,UAAU,CAAC,GAAGtC,UAAU,KAAK,EAAE,CAAC,CAAC;EACvC,MAAMuC,IAAI,GAAGF,KAAK,CAACG,QAAQ,CAAC,CAAC,CAAiB;EAC9C,MAAMC,OAAuB,GAAG,EAAE;EAClC,MAAMC,KAAK,GAAGA,CACZ1B,GAAW,EACX2B,KAAa,EACbC,MAAc,EACdC,MAA2B,KAClB;IACT,IAAI;MACFN,IAAI,CAACN,KAAK,CAACa,WAAW,CAACF,MAAM,EAAED,KAAK,CAAC;MACrCF,OAAO,CAACM,IAAI,CAAC;QAAEC,KAAK,EAAEhC,GAAG;QAAE2B,KAAK;QAAEM,SAAS,EAAEL,MAAM;QAAEC;MAAO,CAAC,CAAC;IAChE,CAAC,CAAC,MAAM;MACN;MACA;IAAA;EAEJ,CAAC;EAED,KAAK,MAAM,CAAC7B,GAAG,EAAE2B,KAAK,CAAC,IAAI9B,OAAO,EAAE;IAClC;IACA;IACA;IACA6B,KAAK,CAAC1B,GAAG,EAAE2B,KAAK,EAAEtB,QAAQ,CAACL,GAAG,CAAC,EAAE,OAAO,CAAC;EAC3C;EACA;EACA;EACA;EACA;EACA,KAAK,MAAM,CAACA,GAAG,EAAE2B,KAAK,CAAC,IAAIb,mBAAmB,EAAE;IAC9CY,KAAK,CAAC1B,GAAG,EAAE2B,KAAK,EAAEtB,QAAQ,CAACL,GAAG,CAAC,EAAE,QAAQ,CAAC;EAC5C;EACA;EACA;EACA,KAAK,MAAM,CAACA,GAAG,EAAE2B,KAAK,CAAC,IAAId,WAAW,EAAE;IACtCa,KAAK,CAAC1B,GAAG,EAAE2B,KAAK,EAAE3B,GAAG,EAAE,MAAM,CAAC;EAChC;EACA;EACA;EACAU,QAAQ,YAARA,QAAQ,CAAEM,MAAM,CAAC,CAAC;EAClB;EACA;EACA/B,mBAAmB,CAACwC,OAAO,CAAC;AAC9B","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["WEB5_SCOPE","traceThemeOverrides","THEME_OVERRIDE_KEY_PATTERN","THEME_TOKEN_CONTRACT","bucketOf","hostAliasFor","THEME_OVERRIDE_TOKENS","Set","Object","keys","MARKER_ATTR","wellFormedEntries","overrides","entries","filter","_ref","key","wellFormed","test","console","warn","bucketed","themeOverrideDeclarations","userOverrides","schemeTokens","map","_ref2","token","value","writtenAs","source","_ref3","_ref4","applyThemeOverrides","document","existing","head","querySelector","declarations","length","remove","style","createElement","setAttribute","appendChild","sheet","insertRule","rule","cssRules","applied","declaration","setProperty","push"],"sources":["../../../src/client/applyThemeOverrides.ts"],"sourcesContent":["/**\n * Runtime theme token injection (DL #131).\n *\n * `Configuration.themeOverrides` carries per-store CSS custom-property\n * overrides (`--primary`, `--radius`, `--heading`, ...) computed from the\n * store's own theme (e.g. the Shopify `settings_data.json` extractor). This\n * applies them to the page so they win over the bundle's baked `theme.css`:\n *\n * - **Scoped, not `:root`**: the rule targets `WEB5_SCOPE`, the same\n * `:is(#root, .w5-root, [data-web5-placement], .debug-view)` selector every\n * compiled bundle stylesheet uses — host-page styling is never touched, and\n * equal specificity + later document order makes the override win. Callers\n * must therefore apply AFTER the client bundle's CSS is in the document.\n * - **Bucketed, since DL #193**: a `brand` token (colour roles, font families)\n * is written as itself, so the store's identity beats the template's. Every\n * other key — `host` tokens and anything the contract has never heard of —\n * is written as its `--web5-host-*` alias, which core's stylesheets consume\n * as a `var()` fallback. A template stating the real token therefore wins on\n * shape, and an unknown key is inert rather than dangerous: a custom property\n * nothing references renders nothing, so an adapter that learns to read a new\n * token cannot silently override a template.\n * - **The token set stays open, but the destination changed.** Before DL #193\n * an unrecognised key was applied verbatim, so a template could consume\n * `var(--foo)` and grow a token with no release. It now arrives as\n * `--web5-host-foo`, so the template consumes `var(--web5-host-foo, <default>)`\n * instead. One line different, and the provenance is explicit — the wiring\n * line is what activates a host token, not the contract entry.\n * - The mandatory `--` prefix means an override can only define custom\n * properties — it can never set a real CSS property inside the scope. The\n * server enforces the same shape (plus value sanitation) at write time.\n * - **Values are inert**: entries are written with\n * `CSSStyleDeclaration.setProperty`, never string-concatenated into CSS, so\n * a hostile value cannot terminate the declaration or open a new rule.\n * - **The shop owner is the last word (DL #193)**: `userOverrides` carries the\n * choices a human made in the owner panel, and every one of them is written\n * as the real token whatever its bucket. Bucketing exists to arbitrate a\n * disagreement between a store and a template; an owner who opened a panel\n * and set a value has already settled that argument, so aliasing theirs would\n * let the template overrule the person who chose. They are written last, so a\n * token both maps carry resolves to the owner's value.\n * - **The active theme scheme sits between the two**: `schemeTokens` is the\n * resolved entry of `Configuration.themeSchemes` (see `theme/themeScheme`).\n * It is written after the store map and before the owner's overrides, under\n * the SAME bucket rule as the store map: a `brand` token (colours, fonts) as\n * the real token, anything else — `--radius`, a key the contract has never\n * heard of — as its `--web5-host-*` alias. Being the later write of either\n * property, the chosen palette beats the flat store map on colours and on\n * radius alike — yet a template that states `--radius` still wins on shape,\n * exactly as it does over an imported radius. A scheme is written like the\n * store map it stands in for, not like an owner override, so it gets no\n * exemption from aliasing; the owner's layer still wins over it. Its entries\n * are filtered exactly like the store map's too: the same key check, the same\n * warning, and no per-type value check — `setProperty` keeps any value inert,\n * and the typed grammar (`isSchemeTokenEntry`) is the panel's to enforce\n * before a write. So the scheme token set is as open as `themeOverrides`: a\n * new scheme token needs no release here. Absent → exactly the pre-scheme\n * behaviour.\n * - **Idempotent**: one marker element per document, replaced wholesale on\n * re-apply; empty/absent input (all three layers) removes it.\n */\nimport { WEB5_SCOPE } from '../hostScope';\nimport { traceThemeOverrides, type AppliedToken } from './themeDebug';\nimport {\n THEME_OVERRIDE_KEY_PATTERN,\n THEME_TOKEN_CONTRACT,\n bucketOf,\n hostAliasFor,\n} from '../theme/tokenContract';\n\n/** A themeOverrides key: always a CSS custom property. */\nexport type ThemeOverrideKey = `--${string}`;\n\n/**\n * Writer-side shape for a theme override map. The catalog below documents\n * the tokens the seed consumes today; the type stays open so new tokens\n * flow end-to-end with no release anywhere but the seed.\n */\nexport type ThemeOverrides = Record<ThemeOverrideKey, string>;\n\n/**\n * The known token catalog. GUIDANCE, NOT A GATE — `applyThemeOverrides` still\n * applies any well-formed custom property, so the vocabulary can grow without a\n * release here.\n *\n * Derived from `@wix/web5-token-contract` rather than restated, because two\n * hand-maintained copies of one list is how they drift. The contract also\n * carries what this Set cannot: which bucket each token is in, and therefore\n * who wins when a store and a template disagree.\n */\nexport const THEME_OVERRIDE_TOKENS: ReadonlySet<string> = new Set(\n Object.keys(THEME_TOKEN_CONTRACT),\n);\n\nconst MARKER_ATTR = 'data-web5-theme-overrides';\n\n/**\n * Drops keys that are not well-formed custom properties, warning about each.\n * Used for all three layers — store, scheme and owner.\n */\nfunction wellFormedEntries(\n overrides?: Record<string, string> | null,\n): [string, string][] {\n return Object.entries(overrides ?? {}).filter(([key]) => {\n const wellFormed = THEME_OVERRIDE_KEY_PATTERN.test(key);\n if (!wellFormed) {\n console.warn(\n `[web5-theme] Skipping malformed theme override key: ${key}`,\n );\n }\n return wellFormed;\n });\n}\n\n/**\n * Where a store-side token lands: a `brand` token as itself, so the store's\n * identity beats the template's; everything else as its `--web5-host-*` alias,\n * which core consumes only as a fallback the template can beat.\n */\nconst bucketed = (key: string): string =>\n bucketOf(key) === 'brand' ? key : hostAliasFor(key);\n\n/**\n * The declarations the three layers resolve to, in the order they are written:\n * the store map bucketed, then the active scheme bucketed the same way, then\n * the owner's overrides as their real names. Later entries win.\n *\n * Pure apart from the malformed-key warning, so a second writer — the owner\n * panel's live preview — paints exactly what a saved configuration will render\n * rather than a reconstruction of it.\n */\nexport function themeOverrideDeclarations(\n overrides?: Record<string, string> | null,\n userOverrides?: Record<string, string> | null,\n schemeTokens?: Record<string, string> | null,\n): AppliedToken[] {\n return [\n // Brand wins over the template, so it is written as the token the\n // stylesheets actually read. Everything else lands in the host namespace,\n // where core consumes it only as a fallback the template can beat.\n ...wellFormedEntries(overrides).map(\n ([token, value]): AppliedToken => ({\n token,\n value,\n writtenAs: bucketed(token),\n source: 'store',\n }),\n ),\n // The active scheme over the store map, bucketed the same way: a brand\n // token as itself, `--radius` and unknown keys as their alias. Either way\n // this is the later write of that property, so it beats the store's — and\n // a template's `--radius` still beats the alias.\n ...wellFormedEntries(schemeTokens).map(\n ([token, value]): AppliedToken => ({\n token,\n value,\n writtenAs: bucketed(token),\n source: 'scheme',\n }),\n ),\n // Owner choices last and never aliased: within one declaration block the\n // last write of a property wins, so a token both maps carry ends up the\n // owner's.\n ...wellFormedEntries(userOverrides).map(\n ([token, value]): AppliedToken => ({\n token,\n value,\n writtenAs: token,\n source: 'user',\n }),\n ),\n ];\n}\n\nexport function applyThemeOverrides(\n overrides?: Record<string, string> | null,\n userOverrides?: Record<string, string> | null,\n schemeTokens?: Record<string, string> | null,\n): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n const existing = document.head.querySelector(`style[${MARKER_ATTR}]`);\n const declarations = themeOverrideDeclarations(\n overrides,\n userOverrides,\n schemeTokens,\n );\n\n if (declarations.length === 0) {\n existing?.remove();\n // Nothing to apply is itself a traceable answer: it means every token on\n // the page is the template's, which is otherwise indistinguishable from\n // tracing having failed.\n traceThemeOverrides([]);\n return;\n }\n\n const style = document.createElement('style');\n style.setAttribute(MARKER_ATTR, '');\n document.head.appendChild(style);\n const sheet = style.sheet;\n if (!sheet) {\n style.remove();\n return;\n }\n sheet.insertRule(`${WEB5_SCOPE} {}`, 0);\n const rule = sheet.cssRules[0] as CSSStyleRule;\n const applied: AppliedToken[] = [];\n for (const declaration of declarations) {\n try {\n rule.style.setProperty(declaration.writtenAs, declaration.value);\n applied.push(declaration);\n } catch {\n // An engine that rejects the value leaves the token at its baked\n // default — degraded theming, never broken CSS.\n }\n }\n // Replace-on-reapply: the fresh element is appended (so it stays last in\n // document order) before the stale one is dropped.\n existing?.remove();\n // AFTER the stale element is gone, so the resolved values traced below are\n // the ones the page will actually render. Off unless explicitly enabled.\n traceThemeOverrides(applied);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,UAAU,QAAQ,cAAc;AACzC,SAASC,mBAAmB,QAA2B,cAAc;AACrE,SACEC,0BAA0B,EAC1BC,oBAAoB,EACpBC,QAAQ,EACRC,YAAY,QACP,wBAAwB;;AAE/B;;AAGA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,qBAA0C,GAAG,IAAIC,GAAG,CAC/DC,MAAM,CAACC,IAAI,CAACN,oBAAoB,CAClC,CAAC;AAED,MAAMO,WAAW,GAAG,2BAA2B;;AAE/C;AACA;AACA;AACA;AACA,SAASC,iBAAiBA,CACxBC,SAAyC,EACrB;EACpB,OAAOJ,MAAM,CAACK,OAAO,CAACD,SAAS,IAAI,CAAC,CAAC,CAAC,CAACE,MAAM,CAACC,IAAA,IAAW;IAAA,IAAV,CAACC,GAAG,CAAC,GAAAD,IAAA;IAClD,MAAME,UAAU,GAAGf,0BAA0B,CAACgB,IAAI,CAACF,GAAG,CAAC;IACvD,IAAI,CAACC,UAAU,EAAE;MACfE,OAAO,CAACC,IAAI,CACV,uDAAuDJ,GAAG,EAC5D,CAAC;IACH;IACA,OAAOC,UAAU;EACnB,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAMI,QAAQ,GAAIL,GAAW,IAC3BZ,QAAQ,CAACY,GAAG,CAAC,KAAK,OAAO,GAAGA,GAAG,GAAGX,YAAY,CAACW,GAAG,CAAC;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,yBAAyBA,CACvCV,SAAyC,EACzCW,aAA6C,EAC7CC,YAA4C,EAC5B;EAChB,OAAO;EACL;EACA;EACA;EACA,GAAGb,iBAAiB,CAACC,SAAS,CAAC,CAACa,GAAG,CACjCC,KAAA;IAAA,IAAC,CAACC,KAAK,EAAEC,KAAK,CAAC,GAAAF,KAAA;IAAA,OAAoB;MACjCC,KAAK;MACLC,KAAK;MACLC,SAAS,EAAER,QAAQ,CAACM,KAAK,CAAC;MAC1BG,MAAM,EAAE;IACV,CAAC;EAAA,CACH,CAAC;EACD;EACA;EACA;EACA;EACA,GAAGnB,iBAAiB,CAACa,YAAY,CAAC,CAACC,GAAG,CACpCM,KAAA;IAAA,IAAC,CAACJ,KAAK,EAAEC,KAAK,CAAC,GAAAG,KAAA;IAAA,OAAoB;MACjCJ,KAAK;MACLC,KAAK;MACLC,SAAS,EAAER,QAAQ,CAACM,KAAK,CAAC;MAC1BG,MAAM,EAAE;IACV,CAAC;EAAA,CACH,CAAC;EACD;EACA;EACA;EACA,GAAGnB,iBAAiB,CAACY,aAAa,CAAC,CAACE,GAAG,CACrCO,KAAA;IAAA,IAAC,CAACL,KAAK,EAAEC,KAAK,CAAC,GAAAI,KAAA;IAAA,OAAoB;MACjCL,KAAK;MACLC,KAAK;MACLC,SAAS,EAAEF,KAAK;MAChBG,MAAM,EAAE;IACV,CAAC;EAAA,CACH,CAAC,CACF;AACH;AAEA,OAAO,SAASG,mBAAmBA,CACjCrB,SAAyC,EACzCW,aAA6C,EAC7CC,YAA4C,EACtC;EACN,IAAI,OAAOU,QAAQ,KAAK,WAAW,EAAE;IACnC;EACF;EAEA,MAAMC,QAAQ,GAAGD,QAAQ,CAACE,IAAI,CAACC,aAAa,CAAC,SAAS3B,WAAW,GAAG,CAAC;EACrE,MAAM4B,YAAY,GAAGhB,yBAAyB,CAC5CV,SAAS,EACTW,aAAa,EACbC,YACF,CAAC;EAED,IAAIc,YAAY,CAACC,MAAM,KAAK,CAAC,EAAE;IAC7BJ,QAAQ,YAARA,QAAQ,CAAEK,MAAM,CAAC,CAAC;IAClB;IACA;IACA;IACAvC,mBAAmB,CAAC,EAAE,CAAC;IACvB;EACF;EAEA,MAAMwC,KAAK,GAAGP,QAAQ,CAACQ,aAAa,CAAC,OAAO,CAAC;EAC7CD,KAAK,CAACE,YAAY,CAACjC,WAAW,EAAE,EAAE,CAAC;EACnCwB,QAAQ,CAACE,IAAI,CAACQ,WAAW,CAACH,KAAK,CAAC;EAChC,MAAMI,KAAK,GAAGJ,KAAK,CAACI,KAAK;EACzB,IAAI,CAACA,KAAK,EAAE;IACVJ,KAAK,CAACD,MAAM,CAAC,CAAC;IACd;EACF;EACAK,KAAK,CAACC,UAAU,CAAC,GAAG9C,UAAU,KAAK,EAAE,CAAC,CAAC;EACvC,MAAM+C,IAAI,GAAGF,KAAK,CAACG,QAAQ,CAAC,CAAC,CAAiB;EAC9C,MAAMC,OAAuB,GAAG,EAAE;EAClC,KAAK,MAAMC,WAAW,IAAIZ,YAAY,EAAE;IACtC,IAAI;MACFS,IAAI,CAACN,KAAK,CAACU,WAAW,CAACD,WAAW,CAACrB,SAAS,EAAEqB,WAAW,CAACtB,KAAK,CAAC;MAChEqB,OAAO,CAACG,IAAI,CAACF,WAAW,CAAC;IAC3B,CAAC,CAAC,MAAM;MACN;MACA;IAAA;EAEJ;EACA;EACA;EACAf,QAAQ,YAARA,QAAQ,CAAEK,MAAM,CAAC,CAAC;EAClB;EACA;EACAvC,mBAAmB,CAACgD,OAAO,CAAC;AAC9B","ignoreList":[]}
|
package/dist/esm/index.js
CHANGED
|
@@ -160,9 +160,10 @@ export { getClientBundleOverride, isTrustedBundleHost } from './client/clientBun
|
|
|
160
160
|
// `web50-server-ui` and `embed-placement`, the two client-bundle load sites.
|
|
161
161
|
export { TEMPLATES_CDN_BASE, TEMPLATES_MANIFEST_URL, getTemplateOverride, isTemplatePickerRequested, isValidTemplateId, resolveClientBundleUrl } from './client/clientBundleUrl.js';
|
|
162
162
|
export { mergeClientConfig } from './client/mergeClientConfig.js';
|
|
163
|
-
export { applyThemeOverrides, THEME_OVERRIDE_TOKENS } from './client/applyThemeOverrides.js';
|
|
163
|
+
export { applyThemeOverrides, themeOverrideDeclarations, THEME_OVERRIDE_TOKENS } from './client/applyThemeOverrides.js';
|
|
164
164
|
export { THEME_TOKEN_CONTRACT, BRAND_TOKENS, EDITABLE_TOKENS, TOKEN_NAME_PATTERN, THEME_OVERRIDE_KEY_PATTERN, bucketOf, hostAliasFor } from './theme/tokenContract.js';
|
|
165
|
-
export { SCHEME_COLOR_TOKENS, MAX_THEME_SCHEMES, SCHEME_ANCHOR_TOKENS, completeScheme, isThemeScheme, isSchemeTokenEntry, nextOwnerSchemeId, resolveActiveScheme, schemeDisplayName } from './theme/themeScheme.js';
|
|
165
|
+
export { SCHEME_COLOR_TOKENS, MAX_THEME_SCHEMES, SCHEME_ANCHOR_TOKENS, SCHEME_TOKENS, completeScheme, isThemeScheme, isSchemeTokenEntry, nextOwnerSchemeId, resolveActiveScheme, schemeDisplayName, schemeTokensOf } from './theme/themeScheme.js';
|
|
166
|
+
export { WEB5_CHROME_TOKENS, web5ChromeProperties, web5ChromeProperty } from './theme/chromeTokens.js';
|
|
166
167
|
export { isThemeDebugEnabled, THEME_DEBUG_KEY, THEME_DEBUG_QUERY_PARAM } from './client/themeDebug.js';
|
|
167
168
|
export { hexToHslTriplet, hslTripletToHex, isHslTriplet } from './theme/colorFormat.js';
|
|
168
169
|
|