@motion-proto/live-tokens 0.67.1 → 0.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/live-tokens-build-page/SKILL.md +16 -5
- package/.claude/skills/live-tokens-create-component/SKILL.md +43 -8
- package/.claude/skills/live-tokens-create-component/references/token-naming.md +30 -1
- package/.claude/skills/live-tokens-fix-findings/SKILL.md +131 -0
- package/.claude/skills/live-tokens-pick-component/SKILL.md +2 -1
- package/CHANGELOG.md +239 -0
- package/README.md +11 -4
- package/bin/check-component.mjs +367 -63
- package/bin/check-page.mjs +409 -0
- package/bin/cli.mjs +57 -8
- package/bin/generate-theme.mjs +5 -4
- package/bin/lib/cssValues.mjs +50 -0
- package/bin/lib/findings.mjs +106 -0
- package/bin/lib/tokenVocabulary.mjs +213 -0
- package/dist-plugin/adjust/index.cjs +174 -23
- package/dist-plugin/adjust/index.d.cts +1 -1
- package/dist-plugin/adjust/index.d.ts +1 -1
- package/dist-plugin/adjust/index.js +68 -23
- package/dist-plugin/{chunk-J2JT4UEA.js → chunk-2YNERPXY.js} +26 -26
- package/dist-plugin/{chunk-NE6N66EE.js → chunk-GPIBU44G.js} +107 -1
- package/dist-plugin/{chunk-ZHPX7ZYQ.js → chunk-RFVYPNRO.js} +39 -1
- package/dist-plugin/{dataPaths-DZUzVv8H.d.ts → dataPaths-bJTCEO4H.d.cts} +1 -1
- package/dist-plugin/{dataPaths-DZUzVv8H.d.cts → dataPaths-bJTCEO4H.d.ts} +1 -1
- package/dist-plugin/fontPairing/index.d.cts +1 -1
- package/dist-plugin/fontPairing/index.d.ts +1 -1
- package/dist-plugin/generateColorsAndType/index.cjs +107 -1
- package/dist-plugin/generateColorsAndType/index.d.cts +1 -1
- package/dist-plugin/generateColorsAndType/index.d.ts +1 -1
- package/dist-plugin/generateColorsAndType/index.js +1 -1
- package/dist-plugin/index.cjs +173 -29
- package/dist-plugin/index.d.cts +1 -1
- package/dist-plugin/index.d.ts +1 -1
- package/dist-plugin/index.js +7 -7
- package/dist-plugin/migrateData/index.cjs +132 -26
- package/dist-plugin/migrateData/index.d.cts +1 -1
- package/dist-plugin/migrateData/index.d.ts +1 -1
- package/dist-plugin/migrateData/index.js +2 -2
- package/dist-plugin/tokensCssMigrations/index.cjs +39 -1
- package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
- package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
- package/dist-plugin/tokensCssMigrations/index.js +1 -1
- package/package.json +6 -5
- package/src/app/site.css +4 -4
- package/src/editor/bootstrap.ts +6 -6
- package/src/editor/component-editor/ButtonEditor.svelte +71 -4
- package/src/editor/component-editor/CardEditor.svelte +6 -6
- package/src/editor/component-editor/DialogEditor.svelte +3 -3
- package/src/editor/component-editor/IconButtonEditor.svelte +68 -3
- package/src/editor/component-editor/ImageEditor.svelte +8 -8
- package/src/editor/component-editor/ImageLightboxEditor.svelte +13 -2
- package/src/editor/component-editor/MenuSelectEditor.svelte +63 -3
- package/src/editor/component-editor/SegmentedControlEditor.svelte +63 -3
- package/src/editor/component-editor/SideNavigationEditor.svelte +67 -3
- package/src/editor/component-editor/SliderEditor.svelte +186 -0
- package/src/editor/component-editor/TabBarEditor.svelte +63 -3
- package/src/editor/component-editor/registry.ts +10 -0
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +4 -4
- package/src/editor/core/components/aliasKinds.ts +51 -28
- package/src/editor/core/fonts/fontLoader.ts +2 -2
- package/src/editor/core/preview/{lookPreview.ts → themePreview.ts} +27 -27
- package/src/editor/core/productionPulse.ts +3 -3
- package/src/editor/core/sketch/index.ts +52 -44
- package/src/editor/core/sketch/maskField.ts +9 -9
- package/src/editor/core/sketch/sketchLayer.ts +25 -9
- package/src/editor/core/sketch/sketchRegistry.ts +34 -34
- package/src/editor/core/sketch/sketchStore.ts +98 -83
- package/src/editor/core/sketch/sketchStyleService.ts +4 -4
- package/src/editor/core/sketch/sketchStyles.ts +28 -28
- package/src/editor/core/store/editorPersistence.ts +44 -1
- package/src/editor/core/store/editorRenderer.ts +2 -2
- package/src/editor/core/store/editorStore.ts +18 -18
- package/src/editor/core/store/editorTypes.ts +7 -6
- package/src/editor/core/themes/colorsAndTypeService.ts +1 -1
- package/src/editor/core/themes/loadRows.ts +8 -8
- package/src/editor/core/themes/migrations/2026-09-01-gate-suffix-enabled.ts +31 -0
- package/src/editor/core/themes/migrations/2026-09-01-scrim-rename.ts +52 -0
- package/src/editor/core/themes/migrations/2026-09-01-tabbar-active-tint.ts +27 -0
- package/src/editor/core/themes/migrations/2026-09-01-tint-rename.ts +42 -0
- package/src/editor/core/themes/migrations/index.ts +16 -0
- package/src/editor/core/themes/slices/domainVars.ts +2 -2
- package/src/editor/core/themes/slices/washes.ts +107 -0
- package/src/editor/core/themes/themeDocumentSync.ts +2 -2
- package/src/editor/core/themes/themeInit.ts +2 -2
- package/src/editor/core/themes/themeService.ts +17 -17
- package/src/editor/core/themes/{lookSummary.ts → themeSummary.ts} +9 -9
- package/src/editor/core/themes/themeTypes.ts +10 -6
- package/src/editor/docs/content/editing-tokens.md +5 -3
- package/src/editor/docs/content/getting-started.md +1 -1
- package/src/editor/docs/content/sketch-mode.md +22 -17
- package/src/editor/docs/content/themes-workflow.md +11 -11
- package/src/editor/docs/content/where-themes-live.md +6 -6
- package/src/editor/docs/content.generated.ts +5 -5
- package/src/editor/index.ts +2 -2
- package/src/editor/pages/EditorShell.svelte +1 -1
- package/src/editor/ui/SurfacesTab.svelte +3 -3
- package/src/editor/ui/ThemePanel.svelte +52 -52
- package/src/editor/ui/UITokenSelector.svelte +1 -0
- package/src/editor/ui/VariablesTab.svelte +2 -2
- package/src/editor/ui/sections/{OverlaysSection.svelte → WashesSection.svelte} +44 -43
- package/src/editor/ui/sketch/SketchPreview.svelte +2 -2
- package/src/editor/ui/sketch/SketchTab.svelte +64 -38
- package/src/live-tokens/data/colors-and-type/autumn.json +6 -6
- package/src/live-tokens/data/colors-and-type/default.json +6 -6
- package/src/live-tokens/data/colors-and-type/halloween.json +6 -6
- package/src/live-tokens/data/colors-and-type/midnight-study.json +6 -6
- package/src/live-tokens/data/colors-and-type/ocean.json +6 -6
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +6 -6
- package/src/live-tokens/data/colors-and-type/sketchy.json +6 -6
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +6 -6
- package/src/live-tokens/data/colors-and-type/sunset.json +6 -6
- package/src/live-tokens/data/sketch-styles/dry.json +5 -5
- package/src/live-tokens/data/sketch-styles/hatched.json +9 -9
- package/src/live-tokens/data/themes/autumn.json +82 -14
- package/src/live-tokens/data/themes/halloween.json +82 -14
- package/src/live-tokens/data/themes/midnight-study.json +82 -14
- package/src/live-tokens/data/themes/ocean.json +82 -14
- package/src/live-tokens/data/themes/royal-velvet.json +82 -14
- package/src/live-tokens/data/themes/sketchy.json +82 -14
- package/src/live-tokens/data/themes/spring-meadow.json +82 -14
- package/src/live-tokens/data/themes/sunset.json +82 -14
- package/src/live-tokens/data/tokens.generated.css +6 -6
- package/src/system/backdrop/backdrop.ts +1 -1
- package/src/system/components/Button.svelte +28 -10
- package/src/system/components/Card.svelte +6 -6
- package/src/system/components/Dialog.svelte +3 -3
- package/src/system/components/IconButton.svelte +23 -7
- package/src/system/components/Image.svelte +6 -6
- package/src/system/components/MenuSelect.svelte +17 -1
- package/src/system/components/SectionDivider.svelte +1 -1
- package/src/system/components/SegmentedControl.svelte +20 -2
- package/src/system/components/SideNavigation.svelte +22 -2
- package/src/system/components/Slider.svelte +348 -0
- package/src/system/components/TabBar.svelte +20 -2
- package/src/system/styles/CONVENTIONS.md +2 -2
- package/src/system/styles/tokens.css +12 -4
- package/template/package.json +3 -2
- package/template/src/pages/Home.svelte +1 -1
- package/src/editor/core/themes/slices/overlays.ts +0 -101
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Severity resolution and reporting shared by check-page and check-component.
|
|
2
|
+
//
|
|
3
|
+
// Every rule has a default severity. Three things can override it, last wins:
|
|
4
|
+
// `checks.rules` in live-tokens.config.json, then the CLI flags
|
|
5
|
+
// (--off/--warn/--error), then --strict, which promotes every warning.
|
|
6
|
+
//
|
|
7
|
+
// A checker returns findings; this module decides what they mean and how they
|
|
8
|
+
// print. `--json` output is the contract a skill iterates against, so the shape
|
|
9
|
+
// here is deliberately stable.
|
|
10
|
+
|
|
11
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
|
|
14
|
+
export const SEVERITIES = ['off', 'warn', 'error'];
|
|
15
|
+
|
|
16
|
+
/** Line number of `index` within `text`, 1-based. */
|
|
17
|
+
export function lineOf(text, index) {
|
|
18
|
+
let line = 1;
|
|
19
|
+
for (let i = 0; i < index && i < text.length; i++) if (text[i] === '\n') line++;
|
|
20
|
+
return line;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function readChecksConfig(root) {
|
|
24
|
+
const path = join(root, 'live-tokens.config.json');
|
|
25
|
+
if (!existsSync(path)) return {};
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(readFileSync(path, 'utf8')).checks ?? {};
|
|
28
|
+
} catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Parse `--off=a,b --warn=c --error=d --strict --json` out of argv.
|
|
35
|
+
* Unrecognised flags are returned in `rest` for the caller to handle.
|
|
36
|
+
*/
|
|
37
|
+
export function parseCheckFlags(argv) {
|
|
38
|
+
const opts = { off: [], warn: [], error: [], strict: false, json: false, rest: [] };
|
|
39
|
+
for (const arg of argv) {
|
|
40
|
+
const m = arg.match(/^--(off|warn|error)=(.+)$/);
|
|
41
|
+
if (m) {
|
|
42
|
+
opts[m[1]].push(...m[2].split(',').map((s) => s.trim()).filter(Boolean));
|
|
43
|
+
} else if (arg === '--strict') opts.strict = true;
|
|
44
|
+
else if (arg === '--json') opts.json = true;
|
|
45
|
+
else opts.rest.push(arg);
|
|
46
|
+
}
|
|
47
|
+
return opts;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolve each finding's severity and drop the ones turned off.
|
|
52
|
+
* `rules` maps rule id to its default severity.
|
|
53
|
+
*/
|
|
54
|
+
export function applySeverity(findings, rules, opts = {}, config = {}) {
|
|
55
|
+
const configured = config.rules ?? {};
|
|
56
|
+
const resolve = (id) => {
|
|
57
|
+
let severity = rules[id] ?? 'error';
|
|
58
|
+
if (SEVERITIES.includes(configured[id])) severity = configured[id];
|
|
59
|
+
if (opts.off?.includes(id)) severity = 'off';
|
|
60
|
+
if (opts.warn?.includes(id)) severity = 'warn';
|
|
61
|
+
if (opts.error?.includes(id)) severity = 'error';
|
|
62
|
+
if (opts.strict && severity === 'warn') severity = 'error';
|
|
63
|
+
return severity;
|
|
64
|
+
};
|
|
65
|
+
return findings
|
|
66
|
+
.map((f) => ({ ...f, severity: resolve(f.rule) }))
|
|
67
|
+
.filter((f) => f.severity !== 'off');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function countBySeverity(findings) {
|
|
71
|
+
return {
|
|
72
|
+
errors: findings.filter((f) => f.severity === 'error').length,
|
|
73
|
+
warnings: findings.filter((f) => f.severity === 'warn').length,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function formatFindings(findings, { label, checked = 0 } = {}) {
|
|
78
|
+
const { errors, warnings } = countBySeverity(findings);
|
|
79
|
+
if (findings.length === 0) {
|
|
80
|
+
return `✓ ${label}: ${checked} file(s) clean.`;
|
|
81
|
+
}
|
|
82
|
+
const lines = [];
|
|
83
|
+
const byFile = new Map();
|
|
84
|
+
for (const f of findings) {
|
|
85
|
+
if (!byFile.has(f.file)) byFile.set(f.file, []);
|
|
86
|
+
byFile.get(f.file).push(f);
|
|
87
|
+
}
|
|
88
|
+
for (const [file, group] of byFile) {
|
|
89
|
+
lines.push(file);
|
|
90
|
+
for (const f of group.sort((a, b) => a.line - b.line)) {
|
|
91
|
+
const mark = f.severity === 'error' ? '✗' : '!';
|
|
92
|
+
lines.push(` ${mark} ${f.line}: ${f.message} [${f.rule}]`);
|
|
93
|
+
}
|
|
94
|
+
lines.push('');
|
|
95
|
+
}
|
|
96
|
+
lines.push(`${label}: ${errors} error(s), ${warnings} warning(s) across ${checked} file(s).`);
|
|
97
|
+
if (warnings > 0 && errors === 0) {
|
|
98
|
+
lines.push('Warnings do not fail the check. Re-run with --strict to treat them as errors.');
|
|
99
|
+
}
|
|
100
|
+
return lines.join('\n');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function toJson(findings, { label, checked = 0 } = {}) {
|
|
104
|
+
const { errors, warnings } = countBySeverity(findings);
|
|
105
|
+
return JSON.stringify({ check: label, checked, errors, warnings, findings }, null, 2);
|
|
106
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// The token and component vocabulary both static checkers validate against.
|
|
2
|
+
//
|
|
3
|
+
// One module so `check-page` and `check-component` can never disagree about
|
|
4
|
+
// what counts as a real token. Two sources feed it:
|
|
5
|
+
//
|
|
6
|
+
// 1. tokens.css — the developer-authored file (the consumer's, or the
|
|
7
|
+
// package's when a consumer has none yet). A theme token *is* a name
|
|
8
|
+
// declared here; there is no second register of tokens to consult.
|
|
9
|
+
// 2. Component tokens — every `--<id>-*` a component declares in its
|
|
10
|
+
// `:global(:root)` block, shipped or consumer-authored.
|
|
11
|
+
//
|
|
12
|
+
// A state word is not a token. `hover` is a segment inside a semantic property
|
|
13
|
+
// name (`--button-outline-hover-surface`), so `var(--hover)` names nothing and
|
|
14
|
+
// the checkers say so.
|
|
15
|
+
//
|
|
16
|
+
// Reads files only. Nothing here may import dist-plugin at module top: CI runs
|
|
17
|
+
// the suite before the plugin is built (see bin/engineLoadsLazily.test.ts).
|
|
18
|
+
|
|
19
|
+
import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from 'node:fs';
|
|
20
|
+
import { dirname, join, resolve } from 'node:path';
|
|
21
|
+
import { fileURLToPath } from 'node:url';
|
|
22
|
+
import { resolveTokensCssPath } from '../migrate.mjs';
|
|
23
|
+
|
|
24
|
+
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
|
|
25
|
+
|
|
26
|
+
const SHIPPED_COMPONENTS_DIR = 'src/system/components';
|
|
27
|
+
|
|
28
|
+
/** Families whose names are governed by the token contract (see TOKENS.md). */
|
|
29
|
+
const CONTRACT_FAMILIES = [
|
|
30
|
+
'surface', 'text', 'border', 'color', 'space', 'radius', 'font', 'line-height',
|
|
31
|
+
'letter-spacing', 'shadow', 'blur', 'icon-size', 'scrim', 'tint', 'columns',
|
|
32
|
+
'heading', 'body', 'editorial', 'eyebrow', 'code', 'easing', 'duration', 'zoom',
|
|
33
|
+
'gradient', 'stroke',
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/** True when `name` belongs to a contract-governed family, so a miss is a typo. */
|
|
37
|
+
export function isContractToken(name) {
|
|
38
|
+
const stem = name.replace(/^--/, '');
|
|
39
|
+
return CONTRACT_FAMILIES.some((f) => stem === f || stem.startsWith(`${f}-`));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Every `--name:` declared anywhere in a stylesheet or style block. */
|
|
43
|
+
export function declaredCustomProperties(css) {
|
|
44
|
+
const out = new Set();
|
|
45
|
+
for (const m of css.matchAll(/(?:^|[;{])\s*(--[a-z0-9-]+)\s*:/gim)) out.add(m[1]);
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Every `var(--name)` referenced in a stylesheet or style block. */
|
|
50
|
+
export function referencedCustomProperties(css) {
|
|
51
|
+
const out = new Set();
|
|
52
|
+
for (const m of css.matchAll(/var\(\s*(--[a-z0-9-]+)/g)) out.add(m[1]);
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The body of every `:global(:root) { ... }` block, brace-balanced so a nested
|
|
58
|
+
* at-rule or an SCSS block inside it neither truncates the block nor leaks
|
|
59
|
+
* declarations from the rule after it.
|
|
60
|
+
*/
|
|
61
|
+
export function extractGlobalRootBlocks(source) {
|
|
62
|
+
const out = [];
|
|
63
|
+
const re = /:global\(:root\)\s*\{/g;
|
|
64
|
+
let m;
|
|
65
|
+
while ((m = re.exec(source)) !== null) {
|
|
66
|
+
const start = m.index + m[0].length;
|
|
67
|
+
let depth = 1;
|
|
68
|
+
let i = start;
|
|
69
|
+
for (; i < source.length && depth > 0; i++) {
|
|
70
|
+
if (source[i] === '{') depth++;
|
|
71
|
+
else if (source[i] === '}') depth--;
|
|
72
|
+
}
|
|
73
|
+
out.push(source.slice(start, depth === 0 ? i - 1 : i));
|
|
74
|
+
re.lastIndex = i;
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const STRING_UNION = /^(?:'[^']*'\s*\|?\s*)+$/;
|
|
80
|
+
|
|
81
|
+
function unionValues(text) {
|
|
82
|
+
return [...text.matchAll(/'([^']*)'/g)].map((m) => m[1]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The public props of a component: every name its `interface Props` declares,
|
|
87
|
+
* and for each prop typed as a union of string literals (inline, via a `type`
|
|
88
|
+
* alias, or via `typeof <const array>[number]`), the values it accepts.
|
|
89
|
+
*
|
|
90
|
+
* Shipped components declare their props this way and none spreads a rest
|
|
91
|
+
* object onto the element, so an attribute outside this set is silently
|
|
92
|
+
* dropped at runtime. Returns null when the file declares no `interface Props`.
|
|
93
|
+
*/
|
|
94
|
+
export function componentProps(source) {
|
|
95
|
+
const script = source.replace(/<style[^>]*>[\s\S]*?<\/style>/g, '');
|
|
96
|
+
const iface = script.match(/interface\s+Props\b[^{]*\{([\s\S]*?)\n\s*\}/);
|
|
97
|
+
if (!iface) return null;
|
|
98
|
+
const aliases = new Map();
|
|
99
|
+
for (const m of script.matchAll(/\btype\s+(\w+)\s*=\s*([^;]+);/g)) aliases.set(m[1], m[2].trim());
|
|
100
|
+
const arrays = new Map();
|
|
101
|
+
for (const m of script.matchAll(/\bconst\s+(\w+)\s*=\s*\[([\s\S]*?)\]\s*as\s+const/g)) arrays.set(m[1], unionValues(m[2]));
|
|
102
|
+
|
|
103
|
+
const resolveEnum = (type) => {
|
|
104
|
+
const t = type.replace(/\|\s*undefined\b/g, '').replace(/\bundefined\s*\|/g, '').trim();
|
|
105
|
+
if (STRING_UNION.test(t)) return unionValues(t);
|
|
106
|
+
const viaArray = t.match(/^typeof\s+(\w+)\[number\]$/);
|
|
107
|
+
if (viaArray) return arrays.get(viaArray[1]) ?? null;
|
|
108
|
+
if (/^\w+$/.test(t) && aliases.has(t)) return resolveEnum(aliases.get(t));
|
|
109
|
+
return null;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const props = new Set();
|
|
113
|
+
const enums = new Map();
|
|
114
|
+
const body = iface[1].replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
|
|
115
|
+
for (const m of body.matchAll(/^\s*(?:readonly\s+)?(\w+)\??\s*:\s*([^;\n]+)/gm)) {
|
|
116
|
+
props.add(m[1]);
|
|
117
|
+
const values = resolveEnum(m[2]);
|
|
118
|
+
if (values) enums.set(m[1], new Set(values));
|
|
119
|
+
}
|
|
120
|
+
return { props, enums };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function walk(dir, exts, out = []) {
|
|
124
|
+
if (!existsSync(dir)) return out;
|
|
125
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
126
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.') || entry.name.startsWith('__')) continue;
|
|
127
|
+
const full = join(dir, entry.name);
|
|
128
|
+
if (entry.isDirectory()) walk(full, exts, out);
|
|
129
|
+
else if (exts.some((e) => entry.name.endsWith(e))) out.push(full);
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function componentFiles(roots) {
|
|
135
|
+
const seen = new Set();
|
|
136
|
+
const files = [];
|
|
137
|
+
for (const dir of roots) {
|
|
138
|
+
for (const file of walk(dir, ['.svelte'])) {
|
|
139
|
+
if (file.endsWith('Editor.svelte')) continue;
|
|
140
|
+
let key = file;
|
|
141
|
+
try {
|
|
142
|
+
key = realpathSync(file);
|
|
143
|
+
} catch {
|
|
144
|
+
// unreadable link; fall back to the path itself
|
|
145
|
+
}
|
|
146
|
+
if (seen.has(key)) continue;
|
|
147
|
+
seen.add(key);
|
|
148
|
+
files.push(file);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return files;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function registeredIds(root) {
|
|
155
|
+
const ids = new Set();
|
|
156
|
+
for (const file of walk(join(root, 'src'), ['.ts', '.js', '.mjs', '.svelte'])) {
|
|
157
|
+
let src;
|
|
158
|
+
try {
|
|
159
|
+
src = readFileSync(file, 'utf8');
|
|
160
|
+
} catch {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (!/registerComponent|bootLiveTokens/.test(src)) continue;
|
|
164
|
+
for (const m of src.matchAll(/id\s*:\s*['"]([a-z][a-z0-9]*)['"]/g)) ids.add(m[1]);
|
|
165
|
+
}
|
|
166
|
+
return ids;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Build the vocabulary for `root` (a consumer project, or this repo).
|
|
171
|
+
*
|
|
172
|
+
* Returns sets of names plus the paths they came from, so a checker can say
|
|
173
|
+
* *which* tokens.css a finding was judged against.
|
|
174
|
+
*/
|
|
175
|
+
export function loadVocabulary({ root = process.cwd(), pkgRoot = PKG_ROOT } = {}) {
|
|
176
|
+
const tokensCssPath =
|
|
177
|
+
resolveTokensCssPath(null, null, root) ??
|
|
178
|
+
(existsSync(join(pkgRoot, 'src/system/styles/tokens.css'))
|
|
179
|
+
? join(pkgRoot, 'src/system/styles/tokens.css')
|
|
180
|
+
: null);
|
|
181
|
+
|
|
182
|
+
const themeTokens = new Set();
|
|
183
|
+
if (tokensCssPath && existsSync(tokensCssPath)) {
|
|
184
|
+
for (const n of declaredCustomProperties(readFileSync(tokensCssPath, 'utf8'))) themeTokens.add(n);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const componentTokens = new Set();
|
|
188
|
+
const components = new Map();
|
|
189
|
+
const dirs = [join(pkgRoot, SHIPPED_COMPONENTS_DIR), join(root, SHIPPED_COMPONENTS_DIR)];
|
|
190
|
+
for (const file of componentFiles(dirs)) {
|
|
191
|
+
const Id = file.slice(file.lastIndexOf('/') + 1).replace('.svelte', '');
|
|
192
|
+
const src = readFileSync(file, 'utf8');
|
|
193
|
+
components.set(Id.toLowerCase(), { id: Id.toLowerCase(), name: Id, file, props: componentProps(src) });
|
|
194
|
+
for (const block of extractGlobalRootBlocks(src)) {
|
|
195
|
+
for (const n of declaredCustomProperties(block)) componentTokens.add(n);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const registered = registeredIds(root);
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
themeTokens,
|
|
202
|
+
componentTokens,
|
|
203
|
+
components,
|
|
204
|
+
registered,
|
|
205
|
+
tokensCssPath,
|
|
206
|
+
/** True when `name` resolves to something real at runtime. */
|
|
207
|
+
knows(name) {
|
|
208
|
+
return themeTokens.has(name) || componentTokens.has(name);
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export { PKG_ROOT, walk };
|
|
@@ -39,29 +39,74 @@ __export(adjust_exports, {
|
|
|
39
39
|
module.exports = __toCommonJS(adjust_exports);
|
|
40
40
|
|
|
41
41
|
// src/editor/core/components/aliasKinds.ts
|
|
42
|
-
var
|
|
43
|
-
{ kind: "font-family",
|
|
44
|
-
{ kind: "font-weight",
|
|
45
|
-
{ kind: "font-size",
|
|
46
|
-
{ kind: "line-height",
|
|
47
|
-
{ kind: "letter-spacing",
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
42
|
+
var KIND_RULES = [
|
|
43
|
+
{ kind: "font-family", suffix: ["-font-family"] },
|
|
44
|
+
{ kind: "font-weight", suffix: ["-font-weight"] },
|
|
45
|
+
{ kind: "font-size", suffix: ["-font-size", "-icon-size", "-thumb-size"] },
|
|
46
|
+
{ kind: "line-height", suffix: ["-line-height"] },
|
|
47
|
+
{ kind: "letter-spacing", suffix: ["-letter-spacing"] },
|
|
48
|
+
// Element-named colour roles: the property *is* the element it paints.
|
|
49
|
+
{
|
|
50
|
+
kind: "text-color",
|
|
51
|
+
suffix: [
|
|
52
|
+
"-text",
|
|
53
|
+
"-label",
|
|
54
|
+
"-icon",
|
|
55
|
+
"-title",
|
|
56
|
+
"-body",
|
|
57
|
+
"-eyebrow",
|
|
58
|
+
"-description",
|
|
59
|
+
"-hint",
|
|
60
|
+
"-error",
|
|
61
|
+
"-placeholder",
|
|
62
|
+
"-value"
|
|
63
|
+
],
|
|
64
|
+
prefix: ["--text-"]
|
|
65
|
+
},
|
|
66
|
+
{ kind: "radius", suffix: ["-radius"], prefix: ["--radius-"] },
|
|
67
|
+
{ kind: "divider-width", suffix: ["-divider-width", "-divider-thickness"] },
|
|
68
|
+
{ kind: "divider-height", suffix: ["-divider-height", "-track-height"] },
|
|
69
|
+
{ kind: "divider-inset", suffix: ["-divider-inset", "-inset"] },
|
|
70
|
+
{ kind: "dot-size", suffix: ["-dot-size"] },
|
|
71
|
+
{ kind: "blur", suffix: ["-blur"], prefix: ["--blur-"] },
|
|
72
|
+
{ kind: "scale", suffix: ["-scale"], prefix: ["--scale-"] },
|
|
73
|
+
{ kind: "shadow", suffix: ["-shadow"], prefix: ["--shadow-"] },
|
|
74
|
+
{ kind: "padding", suffix: ["-padding", "-margin"] },
|
|
75
|
+
{ kind: "gap", suffix: ["-gap"] },
|
|
76
|
+
{ kind: "duration", suffix: ["-duration"], prefix: ["--duration-"] },
|
|
77
|
+
{ kind: "easing", suffix: ["-easing"], prefix: ["--ease-"] },
|
|
78
|
+
{
|
|
79
|
+
kind: "border-width",
|
|
80
|
+
suffix: ["-border-width", "-accent-width", "-hairline-thickness", "-thickness"],
|
|
81
|
+
prefix: ["--border-width-"]
|
|
82
|
+
},
|
|
83
|
+
{ kind: "border", suffix: ["-border"], prefix: ["--border-"] },
|
|
84
|
+
// Fills. A tint is a wash over a surface, so it takes the surface picker: the
|
|
85
|
+
// full palette with an alpha, not just the tint stops it defaults to.
|
|
86
|
+
{
|
|
87
|
+
kind: "surface",
|
|
88
|
+
suffix: [
|
|
89
|
+
"-surface",
|
|
90
|
+
"-fill",
|
|
91
|
+
"-divider",
|
|
92
|
+
"-background",
|
|
93
|
+
"-indicator",
|
|
94
|
+
"-thumb",
|
|
95
|
+
"-accent",
|
|
96
|
+
"-color",
|
|
97
|
+
"-tint",
|
|
98
|
+
"-opacity",
|
|
99
|
+
"-width",
|
|
100
|
+
"-height",
|
|
101
|
+
"-size"
|
|
102
|
+
],
|
|
103
|
+
prefix: ["--surface-", "--tint", "--color-"]
|
|
104
|
+
}
|
|
64
105
|
];
|
|
106
|
+
var KIND_PATTERNS = KIND_RULES.map(({ kind, suffix = [], prefix = [] }) => ({
|
|
107
|
+
kind,
|
|
108
|
+
matches: (v) => suffix.some((s) => v.endsWith(s)) || prefix.some((p) => v.startsWith(p))
|
|
109
|
+
}));
|
|
65
110
|
var MATCHER_BY_KIND = Object.fromEntries(
|
|
66
111
|
KIND_PATTERNS.map((p) => [p.kind, p.matches])
|
|
67
112
|
);
|
|
@@ -980,6 +1025,106 @@ var componentMigration_2026_08_15_lineHeightScaleRename = {
|
|
|
980
1025
|
apply: renameValues
|
|
981
1026
|
};
|
|
982
1027
|
|
|
1028
|
+
// src/editor/core/themes/migrations/2026-09-01-scrim-rename.ts
|
|
1029
|
+
var RENAMED2 = {
|
|
1030
|
+
"--overlay-low": "--scrim-low",
|
|
1031
|
+
"--overlay": "--scrim",
|
|
1032
|
+
"--overlay-high": "--scrim-high"
|
|
1033
|
+
};
|
|
1034
|
+
var RENAMED_COMPONENT_KEYS = {
|
|
1035
|
+
"--dialog-overlay-surface": "--dialog-scrim-surface"
|
|
1036
|
+
};
|
|
1037
|
+
var colorsAndTypeMigration_2026_09_01_scrimRename = {
|
|
1038
|
+
id: "2026-09-01-scrim-rename-theme",
|
|
1039
|
+
fromVersion: 5,
|
|
1040
|
+
toVersion: 6,
|
|
1041
|
+
appliesTo: "colors-and-type",
|
|
1042
|
+
apply(rawVars) {
|
|
1043
|
+
const out = {};
|
|
1044
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1045
|
+
out[RENAMED2[key] ?? key] = value;
|
|
1046
|
+
}
|
|
1047
|
+
return out;
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
var componentMigration_2026_09_01_scrimRename = {
|
|
1051
|
+
id: "2026-09-01-scrim-rename-component",
|
|
1052
|
+
fromVersion: 21,
|
|
1053
|
+
toVersion: 22,
|
|
1054
|
+
appliesTo: "component-config",
|
|
1055
|
+
apply(rawVars) {
|
|
1056
|
+
const out = {};
|
|
1057
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1058
|
+
out[RENAMED_COMPONENT_KEYS[key] ?? key] = RENAMED2[value] ?? value;
|
|
1059
|
+
}
|
|
1060
|
+
return out;
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
|
|
1064
|
+
// src/editor/core/themes/migrations/2026-09-01-tint-rename.ts
|
|
1065
|
+
var RENAMED3 = {
|
|
1066
|
+
"--hover-low": "--tint-low",
|
|
1067
|
+
"--hover": "--tint",
|
|
1068
|
+
"--hover-high": "--tint-high"
|
|
1069
|
+
};
|
|
1070
|
+
var colorsAndTypeMigration_2026_09_01_tintRename = {
|
|
1071
|
+
id: "2026-09-01-tint-rename-theme",
|
|
1072
|
+
fromVersion: 6,
|
|
1073
|
+
toVersion: 7,
|
|
1074
|
+
appliesTo: "colors-and-type",
|
|
1075
|
+
apply(rawVars) {
|
|
1076
|
+
const out = {};
|
|
1077
|
+
for (const [key, value] of Object.entries(rawVars)) out[RENAMED3[key] ?? key] = value;
|
|
1078
|
+
return out;
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
1081
|
+
var componentMigration_2026_09_01_tintRename = {
|
|
1082
|
+
id: "2026-09-01-tint-rename-component",
|
|
1083
|
+
fromVersion: 22,
|
|
1084
|
+
toVersion: 23,
|
|
1085
|
+
appliesTo: "component-config",
|
|
1086
|
+
apply(rawVars) {
|
|
1087
|
+
const out = {};
|
|
1088
|
+
for (const [key, value] of Object.entries(rawVars)) out[key] = RENAMED3[value] ?? value;
|
|
1089
|
+
return out;
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1093
|
+
// src/editor/core/themes/migrations/2026-09-01-tabbar-active-tint.ts
|
|
1094
|
+
var componentMigration_2026_09_01_tabbarActiveTint = {
|
|
1095
|
+
id: "2026-09-01-tabbar-active-tint",
|
|
1096
|
+
fromVersion: 23,
|
|
1097
|
+
toVersion: 24,
|
|
1098
|
+
appliesTo: "component-config",
|
|
1099
|
+
apply(rawVars, meta) {
|
|
1100
|
+
if (meta.component !== "tabbar") return { ...rawVars };
|
|
1101
|
+
const out = { ...rawVars };
|
|
1102
|
+
if (out["--tabbar-active-surface"] === "--scrim-low") {
|
|
1103
|
+
out["--tabbar-active-surface"] = "--tint-low";
|
|
1104
|
+
}
|
|
1105
|
+
return out;
|
|
1106
|
+
}
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1109
|
+
// src/editor/core/themes/migrations/2026-09-01-gate-suffix-enabled.ts
|
|
1110
|
+
var RENAMED4 = {
|
|
1111
|
+
"--card-hover-border-active": "--card-hover-border-enabled",
|
|
1112
|
+
"--card-hover-shadow-active": "--card-hover-shadow-enabled",
|
|
1113
|
+
"--image-zoom-hover": "--image-zoom-enabled",
|
|
1114
|
+
"--image-grow-hover": "--image-grow-enabled"
|
|
1115
|
+
};
|
|
1116
|
+
var componentMigration_2026_09_01_gateSuffixEnabled = {
|
|
1117
|
+
id: "2026-09-01-gate-suffix-enabled",
|
|
1118
|
+
fromVersion: 24,
|
|
1119
|
+
toVersion: 25,
|
|
1120
|
+
appliesTo: "component-config",
|
|
1121
|
+
apply(rawVars) {
|
|
1122
|
+
const out = {};
|
|
1123
|
+
for (const [key, value] of Object.entries(rawVars)) out[RENAMED4[key] ?? key] = value;
|
|
1124
|
+
return out;
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
|
|
983
1128
|
// src/editor/core/themes/migrations/index.ts
|
|
984
1129
|
var MIGRATIONS = [
|
|
985
1130
|
colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas,
|
|
@@ -1007,7 +1152,13 @@ var MIGRATIONS = [
|
|
|
1007
1152
|
componentMigration_2026_05_29_toggleDeriveTrackFromThumb,
|
|
1008
1153
|
colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys,
|
|
1009
1154
|
colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
|
|
1010
|
-
componentMigration_2026_08_15_lineHeightScaleRename
|
|
1155
|
+
componentMigration_2026_08_15_lineHeightScaleRename,
|
|
1156
|
+
colorsAndTypeMigration_2026_09_01_scrimRename,
|
|
1157
|
+
componentMigration_2026_09_01_scrimRename,
|
|
1158
|
+
colorsAndTypeMigration_2026_09_01_tintRename,
|
|
1159
|
+
componentMigration_2026_09_01_tintRename,
|
|
1160
|
+
componentMigration_2026_09_01_tabbarActiveTint,
|
|
1161
|
+
componentMigration_2026_09_01_gateSuffixEnabled
|
|
1011
1162
|
];
|
|
1012
1163
|
function countFor(kind) {
|
|
1013
1164
|
return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as AliasDiskValue, a as ComponentConfig } from '../themeTypes-DSV3Zisf.cjs';
|
|
2
|
-
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-
|
|
2
|
+
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-bJTCEO4H.cjs';
|
|
3
3
|
export { C as CURRENT_COMPONENT_SCHEMA_VERSION } from '../index-4N-Orzzi.cjs';
|
|
4
4
|
|
|
5
5
|
type AdjustKind = 'radius' | 'padding' | 'gap' | 'border-width';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as AliasDiskValue, a as ComponentConfig } from '../themeTypes-DSV3Zisf.js';
|
|
2
|
-
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-
|
|
2
|
+
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-bJTCEO4H.js';
|
|
3
3
|
export { C as CURRENT_COMPONENT_SCHEMA_VERSION } from '../index-4N-Orzzi.js';
|
|
4
4
|
|
|
5
5
|
type AdjustKind = 'radius' | 'padding' | 'gap' | 'border-width';
|
|
@@ -1,35 +1,80 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CURRENT_COMPONENT_SCHEMA_VERSION
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-GPIBU44G.js";
|
|
4
4
|
import {
|
|
5
5
|
readLiveTokensConfig,
|
|
6
6
|
resolveDataDirs
|
|
7
7
|
} from "../chunk-RVE3MNKM.js";
|
|
8
8
|
|
|
9
9
|
// src/editor/core/components/aliasKinds.ts
|
|
10
|
-
var
|
|
11
|
-
{ kind: "font-family",
|
|
12
|
-
{ kind: "font-weight",
|
|
13
|
-
{ kind: "font-size",
|
|
14
|
-
{ kind: "line-height",
|
|
15
|
-
{ kind: "letter-spacing",
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
var KIND_RULES = [
|
|
11
|
+
{ kind: "font-family", suffix: ["-font-family"] },
|
|
12
|
+
{ kind: "font-weight", suffix: ["-font-weight"] },
|
|
13
|
+
{ kind: "font-size", suffix: ["-font-size", "-icon-size", "-thumb-size"] },
|
|
14
|
+
{ kind: "line-height", suffix: ["-line-height"] },
|
|
15
|
+
{ kind: "letter-spacing", suffix: ["-letter-spacing"] },
|
|
16
|
+
// Element-named colour roles: the property *is* the element it paints.
|
|
17
|
+
{
|
|
18
|
+
kind: "text-color",
|
|
19
|
+
suffix: [
|
|
20
|
+
"-text",
|
|
21
|
+
"-label",
|
|
22
|
+
"-icon",
|
|
23
|
+
"-title",
|
|
24
|
+
"-body",
|
|
25
|
+
"-eyebrow",
|
|
26
|
+
"-description",
|
|
27
|
+
"-hint",
|
|
28
|
+
"-error",
|
|
29
|
+
"-placeholder",
|
|
30
|
+
"-value"
|
|
31
|
+
],
|
|
32
|
+
prefix: ["--text-"]
|
|
33
|
+
},
|
|
34
|
+
{ kind: "radius", suffix: ["-radius"], prefix: ["--radius-"] },
|
|
35
|
+
{ kind: "divider-width", suffix: ["-divider-width", "-divider-thickness"] },
|
|
36
|
+
{ kind: "divider-height", suffix: ["-divider-height", "-track-height"] },
|
|
37
|
+
{ kind: "divider-inset", suffix: ["-divider-inset", "-inset"] },
|
|
38
|
+
{ kind: "dot-size", suffix: ["-dot-size"] },
|
|
39
|
+
{ kind: "blur", suffix: ["-blur"], prefix: ["--blur-"] },
|
|
40
|
+
{ kind: "scale", suffix: ["-scale"], prefix: ["--scale-"] },
|
|
41
|
+
{ kind: "shadow", suffix: ["-shadow"], prefix: ["--shadow-"] },
|
|
42
|
+
{ kind: "padding", suffix: ["-padding", "-margin"] },
|
|
43
|
+
{ kind: "gap", suffix: ["-gap"] },
|
|
44
|
+
{ kind: "duration", suffix: ["-duration"], prefix: ["--duration-"] },
|
|
45
|
+
{ kind: "easing", suffix: ["-easing"], prefix: ["--ease-"] },
|
|
46
|
+
{
|
|
47
|
+
kind: "border-width",
|
|
48
|
+
suffix: ["-border-width", "-accent-width", "-hairline-thickness", "-thickness"],
|
|
49
|
+
prefix: ["--border-width-"]
|
|
50
|
+
},
|
|
51
|
+
{ kind: "border", suffix: ["-border"], prefix: ["--border-"] },
|
|
52
|
+
// Fills. A tint is a wash over a surface, so it takes the surface picker: the
|
|
53
|
+
// full palette with an alpha, not just the tint stops it defaults to.
|
|
54
|
+
{
|
|
55
|
+
kind: "surface",
|
|
56
|
+
suffix: [
|
|
57
|
+
"-surface",
|
|
58
|
+
"-fill",
|
|
59
|
+
"-divider",
|
|
60
|
+
"-background",
|
|
61
|
+
"-indicator",
|
|
62
|
+
"-thumb",
|
|
63
|
+
"-accent",
|
|
64
|
+
"-color",
|
|
65
|
+
"-tint",
|
|
66
|
+
"-opacity",
|
|
67
|
+
"-width",
|
|
68
|
+
"-height",
|
|
69
|
+
"-size"
|
|
70
|
+
],
|
|
71
|
+
prefix: ["--surface-", "--tint", "--color-"]
|
|
72
|
+
}
|
|
32
73
|
];
|
|
74
|
+
var KIND_PATTERNS = KIND_RULES.map(({ kind, suffix = [], prefix = [] }) => ({
|
|
75
|
+
kind,
|
|
76
|
+
matches: (v) => suffix.some((s) => v.endsWith(s)) || prefix.some((p) => v.startsWith(p))
|
|
77
|
+
}));
|
|
33
78
|
var MATCHER_BY_KIND = Object.fromEntries(
|
|
34
79
|
KIND_PATTERNS.map((p) => [p.kind, p.matches])
|
|
35
80
|
);
|