@scattered-light/loomiere 0.5.2 → 0.5.3
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/build/build-tokens.mjs +32 -0
- package/package.json +1 -1
- package/tokens/README.md +1 -0
package/build/build-tokens.mjs
CHANGED
|
@@ -285,6 +285,34 @@ const inLook = (selectors, name) =>
|
|
|
285
285
|
.map((s) => `${s.trim()}[data-look='${name}']`)
|
|
286
286
|
.join(', ');
|
|
287
287
|
|
|
288
|
+
/** Pair class name → Map of variable → value, read from pairBlocks' text. */
|
|
289
|
+
const pairDeclarations = (text) =>
|
|
290
|
+
new Map([...(text ?? '').matchAll(/^\.[\w-]+-pair-([\w-]+) \{\n([\s\S]*?)\n\}/gm)].map(([, name, body]) => [name, declarationsIn(body)]));
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* What a look's pair classes need beyond the brand's. The pairs and their re-pointed parts are
|
|
294
|
+
* the brand's, but a look's `tokens` can change the tokens that lead to them: a token the look
|
|
295
|
+
* points elsewhere (or newly at a re-pointed one) gets the look's value inside each pair, under
|
|
296
|
+
* [data-look='<name>'] .<prefix>-pair-<pair>, which outranks the brand's pair class.
|
|
297
|
+
*/
|
|
298
|
+
function lookPairBlocks(name, parts, base) {
|
|
299
|
+
const own = pairDeclarations(parts.rules.pairs);
|
|
300
|
+
const brand = pairDeclarations(base.rules.pairs);
|
|
301
|
+
const names = (m) => [...m.keys()].sort().join(',');
|
|
302
|
+
if (names(own) !== names(brand)) throw new Error(`Look "${name}" changes the pairs rules, not only values. A look can change colors, fonts and sizes, but it has to keep the brand's palettes, pairs, statuses and emphasis levels.`);
|
|
303
|
+
const blocks = [];
|
|
304
|
+
for (const [pair, decls] of brand) {
|
|
305
|
+
const mine = own.get(pair);
|
|
306
|
+
const lines = [];
|
|
307
|
+
for (const [v, value] of mine) if (decls.get(v) !== value) lines.push(`${v}: ${value};`);
|
|
308
|
+
// No longer leads to a re-pointed token in this look: restate the look's own value so the
|
|
309
|
+
// brand's declaration in the pair class doesn't win.
|
|
310
|
+
for (const v of decls.keys()) if (!mine.has(v) && parts.root[v] !== undefined) lines.push(`${v}: ${parts.root[v]};`);
|
|
311
|
+
if (lines.length) blocks.push(`[data-look='${name}'] .${prefix}-pair-${pair} {\n${indent(lines.join('\n'), 2)}\n}`);
|
|
312
|
+
}
|
|
313
|
+
return blocks.join('\n\n');
|
|
314
|
+
}
|
|
315
|
+
|
|
288
316
|
/** [rootBlocks, modeBlocks] for every look against the brand's own parts. */
|
|
289
317
|
function lookBlocks(dictionary, base) {
|
|
290
318
|
const roots = [];
|
|
@@ -293,8 +321,12 @@ function lookBlocks(dictionary, base) {
|
|
|
293
321
|
for (const [rule, text] of Object.entries(parts.rules)) {
|
|
294
322
|
// Color vision blocks list the data colors by name, so a look with its own names has its own.
|
|
295
323
|
if (rule === 'vision') continue;
|
|
324
|
+
// A look's `tokens` can change what leads to a re-pointed token; lookPairBlocks restates those.
|
|
325
|
+
if (rule === 'pairs') continue;
|
|
296
326
|
if (text !== base.rules[rule]) throw new Error(`Look "${name}" changes the ${rule} rules, not only values. A look can change colors, fonts and sizes, but it has to keep the brand's palettes, pairs, statuses and emphasis levels.`);
|
|
297
327
|
}
|
|
328
|
+
const pairRules = lookPairBlocks(name, parts, base);
|
|
329
|
+
if (pairRules) modeRules.push(pairRules);
|
|
298
330
|
const changed = Object.entries(parts.root).filter(([v, value]) => base.root[v] !== value);
|
|
299
331
|
if (changed.length) roots.push(`/* Look: ${label} (data-look='${name}'). */\n[data-look='${name}'] {\n${indent(changed.map(([v, value]) => `${v}: ${value};`).join('\n'), 2)}\n}`);
|
|
300
332
|
if (parts.rules.vision !== base.rules.vision) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scattered-light/loomiere",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Turns a small brand file into a full design token theme: OKLCH color ramps, a type scale, light, dark and high-contrast modes, plus Tailwind, MUI, Chakra, AG Grid and Figma exports.",
|
|
5
5
|
"keywords": ["design-tokens", "theme", "style-dictionary", "dtcg", "oklch", "base-ui", "ag-grid", "tailwind"],
|
|
6
6
|
"repository": {
|
package/tokens/README.md
CHANGED
|
@@ -66,6 +66,7 @@ A look is another way the same brand can look: an old and a new brand, a quiet a
|
|
|
66
66
|
- It is merged over the brand: objects merge key by key and lists replace. A palette, a pair, a concept, an emphasis or status entry, or a font's metrics replaces the brand's whole entry, so a look's palette never keeps keys from the brand's.
|
|
67
67
|
- `tokens` picks a value for any semantic or component token, for what the brand inputs can't say (square buttons, a thicker focus ring). It works at the top of the brand file too.
|
|
68
68
|
- Every look has the same tokens; only their values change. Components, Figma bindings and code written against one look work in all of them. Pair names and role rules must match across looks; the build says so if they don't.
|
|
69
|
+
- A look's `tokens` can point a token at something else in that look only, such as Highlighter's selected table rows at the highlighter yellow: `"tokens": { "table.row-selected": "{scope.secondary.soft-hover}" }`. Point at a scope slot (`{scope.<palette>.<slot>}`) or a semantic token rather than a palette step, so the value still changes with light, dark and high contrast. Brand pair classes pick up the look's value too.
|
|
69
70
|
|
|
70
71
|
In CSS a look is `data-look="<name>"` on the root element, next to `data-theme`. With no `data-look` the brand's own look applies. `tokens.css` holds one `[data-look]` block with only the variables that change, plus that look's dark, high contrast and color vision blocks. The contrast check runs on every look, and `tokens.json` lists the looks under `looks` with what each one changes. In Figma each look is a mode of the Brand collection (see [figma/README.md](../figma/README.md)), and Storybook has a Look toolbar.
|
|
71
72
|
|