@motion-proto/live-tokens 0.91.2 → 0.92.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-create-page/SKILL.md +10 -3
- package/.claude/skills/live-tokens-set-type/SKILL.md +3 -3
- package/CHANGELOG.md +140 -0
- package/bin/lib/tokenVocabulary.mjs +2 -2
- package/bin/rules/testRuns.mjs +1 -1
- package/bin/rules/tokens.mjs +3 -3
- package/dist-plugin/chunk-JOSSYGR2.js +1634 -0
- package/dist-plugin/index.cjs +932 -15
- package/dist-plugin/index.js +1 -1
- package/dist-plugin/setType/index.cjs +23 -2
- package/dist-plugin/setType/index.js +23 -2
- package/dist-plugin/tokensCssMigrations/index.cjs +936 -15
- package/dist-plugin/tokensCssMigrations/index.d.cts +23 -3
- package/dist-plugin/tokensCssMigrations/index.d.ts +23 -3
- package/dist-plugin/tokensCssMigrations/index.js +5 -1
- package/package.json +1 -1
- package/src/app/site.css +243 -9
- package/src/demo/TestingLoops.svelte +9 -9
- package/src/editor/core/fonts/weightCoverage.ts +31 -2
- package/src/editor/core/palettes/tokenRegistry.ts +36 -37
- package/src/editor/core/themes/parsers/mediaBlocks.ts +46 -0
- package/src/editor/core/typeScale/typeScale.ts +341 -0
- package/src/editor/skill-atlas/SourcePane.svelte +3 -3
- package/src/editor/skill-atlas/skillSources.generated.ts +2 -2
- package/src/editor/skill-atlas/trees/create-page.ts +14 -14
- package/src/editor/skill-atlas/trees/set-type.ts +2 -2
- package/src/editor/ui/UIFontFamilySelector.svelte +5 -1
- package/src/editor/ui/UIFontWeightSelector.svelte +4 -0
- package/src/editor/ui/UILetterSpacingSelector.svelte +4 -0
- package/src/editor/ui/UILineHeightSelector.svelte +4 -0
- package/src/editor/ui/UITextTransformSelector.svelte +4 -0
- package/src/editor/ui/UIVariantSelector.svelte +6 -8
- package/src/editor/ui/VariablesTab.svelte +4 -4
- package/src/editor/ui/sections/textStyles.ts +44 -92
- package/src/editor/ui/text-styles/ControlBody.svelte +100 -0
- package/src/editor/ui/text-styles/ResetIcon.svelte +60 -0
- package/src/editor/ui/text-styles/StepRow.svelte +330 -0
- package/src/editor/ui/text-styles/StyleControl.svelte +128 -0
- package/src/editor/ui/text-styles/TextStylesSection.svelte +551 -0
- package/src/editor/ui/text-styles/textStyleEdits.ts +308 -0
- package/src/editor/ui/variantScales.ts +16 -0
- package/src/system/styles/tokens.css +412 -48
- package/src/testing-js/page-compliance.contract.js +233 -80
- package/src/testing-js/page-compliance.contract.js.map +1 -1
- package/dist-plugin/chunk-GWMEYBZ2.js +0 -715
- package/src/editor/ui/TextStylesSection.svelte +0 -171
|
@@ -47,12 +47,16 @@ interface TokensCssMigration {
|
|
|
47
47
|
* sectioning, and formatting survive untouched. They are idempotent **by
|
|
48
48
|
* presence**: `ensure` skips a token that already exists, `rename` only fires
|
|
49
49
|
* when the old name is present and the new one is absent, `remove` is a no-op
|
|
50
|
-
* when the name is gone
|
|
50
|
+
* when the name is gone, `set` writes nothing when the value already matches,
|
|
51
|
+
* and `appendMediaBlock` skips a name the block declares. Re-running a migration therefore never double-applies,
|
|
51
52
|
* which is what lets the CLI run safely without a schema-version stamp.
|
|
52
53
|
*/
|
|
53
54
|
/** Names declared as custom properties (`--x: …;`) anywhere in the source. */
|
|
54
55
|
declare function collectDefinedTokens(css: string): Set<string>;
|
|
55
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Declared name → top-level value, last declaration winning. Declarations
|
|
58
|
+
* inside `@media` are breakpoint re-points and never count.
|
|
59
|
+
*/
|
|
56
60
|
declare function collectTokenValues(css: string): Map<string, string>;
|
|
57
61
|
/** Names referenced via `var(--x)` anywhere in the source. */
|
|
58
62
|
declare function collectReferencedTokens(css: string): Set<string>;
|
|
@@ -96,6 +100,22 @@ declare function removeToken(css: string, name: string): string;
|
|
|
96
100
|
* No-op when nothing matches. Use for retiring a whole retired namespace.
|
|
97
101
|
*/
|
|
98
102
|
declare function removeTokensMatching(css: string, predicate: (name: string) => boolean): string;
|
|
103
|
+
interface SetTokenValueOptions {
|
|
104
|
+
/** Rewrite only when the current value equals this one, so a consumer's edit stays. */
|
|
105
|
+
from?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Rewrite the value of `name` where the top-level `:root` declares it. A
|
|
109
|
+
* re-declaration inside `@media` keeps its value. No-op when the top-level
|
|
110
|
+
* `:root` does not declare `name`.
|
|
111
|
+
*/
|
|
112
|
+
declare function setTokenValue(css: string, name: string, value: string, opts?: SetTokenValueOptions): string;
|
|
113
|
+
/**
|
|
114
|
+
* Append each entry that no top-level `@media <query>` block declares yet to
|
|
115
|
+
* that block's `:root`. The query must match exactly. With no such block, a new
|
|
116
|
+
* one goes at the end of the file.
|
|
117
|
+
*/
|
|
118
|
+
declare function appendMediaBlock(css: string, query: string, entries: ScaleEntry[]): string;
|
|
99
119
|
|
|
100
120
|
/**
|
|
101
121
|
* Registered tokens-css migrations, applied in array order. Unlike the
|
|
@@ -194,4 +214,4 @@ interface ValidateInput {
|
|
|
194
214
|
*/
|
|
195
215
|
declare function validateTokensCss(input: ValidateInput): MissingToken[];
|
|
196
216
|
|
|
197
|
-
export { type BreakingGateResult, type ComponentSource, type ContractViolation, type MissingToken, type RunResult, type SemverBump, TOKENS_CSS_MIGRATIONS, type TokensCssMigration, type ValidateInput, collectDefinedTokens, collectReferencedTokens, collectTokenValues, enforceBreakingRequiresMajor, ensureScale, findContractViolations, removeToken, removeTokensMatching, renameToken, runAdditiveTokensCssMigrations, runTokensCssMigrations, semverBumpType, validateTokensCss };
|
|
217
|
+
export { type BreakingGateResult, type ComponentSource, type ContractViolation, type MissingToken, type RunResult, type SemverBump, TOKENS_CSS_MIGRATIONS, type TokensCssMigration, type ValidateInput, appendMediaBlock, collectDefinedTokens, collectReferencedTokens, collectTokenValues, enforceBreakingRequiresMajor, ensureScale, findContractViolations, removeToken, removeTokensMatching, renameToken, runAdditiveTokensCssMigrations, runTokensCssMigrations, semverBumpType, setTokenValue, validateTokensCss };
|
|
@@ -47,12 +47,16 @@ interface TokensCssMigration {
|
|
|
47
47
|
* sectioning, and formatting survive untouched. They are idempotent **by
|
|
48
48
|
* presence**: `ensure` skips a token that already exists, `rename` only fires
|
|
49
49
|
* when the old name is present and the new one is absent, `remove` is a no-op
|
|
50
|
-
* when the name is gone
|
|
50
|
+
* when the name is gone, `set` writes nothing when the value already matches,
|
|
51
|
+
* and `appendMediaBlock` skips a name the block declares. Re-running a migration therefore never double-applies,
|
|
51
52
|
* which is what lets the CLI run safely without a schema-version stamp.
|
|
52
53
|
*/
|
|
53
54
|
/** Names declared as custom properties (`--x: …;`) anywhere in the source. */
|
|
54
55
|
declare function collectDefinedTokens(css: string): Set<string>;
|
|
55
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Declared name → top-level value, last declaration winning. Declarations
|
|
58
|
+
* inside `@media` are breakpoint re-points and never count.
|
|
59
|
+
*/
|
|
56
60
|
declare function collectTokenValues(css: string): Map<string, string>;
|
|
57
61
|
/** Names referenced via `var(--x)` anywhere in the source. */
|
|
58
62
|
declare function collectReferencedTokens(css: string): Set<string>;
|
|
@@ -96,6 +100,22 @@ declare function removeToken(css: string, name: string): string;
|
|
|
96
100
|
* No-op when nothing matches. Use for retiring a whole retired namespace.
|
|
97
101
|
*/
|
|
98
102
|
declare function removeTokensMatching(css: string, predicate: (name: string) => boolean): string;
|
|
103
|
+
interface SetTokenValueOptions {
|
|
104
|
+
/** Rewrite only when the current value equals this one, so a consumer's edit stays. */
|
|
105
|
+
from?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Rewrite the value of `name` where the top-level `:root` declares it. A
|
|
109
|
+
* re-declaration inside `@media` keeps its value. No-op when the top-level
|
|
110
|
+
* `:root` does not declare `name`.
|
|
111
|
+
*/
|
|
112
|
+
declare function setTokenValue(css: string, name: string, value: string, opts?: SetTokenValueOptions): string;
|
|
113
|
+
/**
|
|
114
|
+
* Append each entry that no top-level `@media <query>` block declares yet to
|
|
115
|
+
* that block's `:root`. The query must match exactly. With no such block, a new
|
|
116
|
+
* one goes at the end of the file.
|
|
117
|
+
*/
|
|
118
|
+
declare function appendMediaBlock(css: string, query: string, entries: ScaleEntry[]): string;
|
|
99
119
|
|
|
100
120
|
/**
|
|
101
121
|
* Registered tokens-css migrations, applied in array order. Unlike the
|
|
@@ -194,4 +214,4 @@ interface ValidateInput {
|
|
|
194
214
|
*/
|
|
195
215
|
declare function validateTokensCss(input: ValidateInput): MissingToken[];
|
|
196
216
|
|
|
197
|
-
export { type BreakingGateResult, type ComponentSource, type ContractViolation, type MissingToken, type RunResult, type SemverBump, TOKENS_CSS_MIGRATIONS, type TokensCssMigration, type ValidateInput, collectDefinedTokens, collectReferencedTokens, collectTokenValues, enforceBreakingRequiresMajor, ensureScale, findContractViolations, removeToken, removeTokensMatching, renameToken, runAdditiveTokensCssMigrations, runTokensCssMigrations, semverBumpType, validateTokensCss };
|
|
217
|
+
export { type BreakingGateResult, type ComponentSource, type ContractViolation, type MissingToken, type RunResult, type SemverBump, TOKENS_CSS_MIGRATIONS, type TokensCssMigration, type ValidateInput, appendMediaBlock, collectDefinedTokens, collectReferencedTokens, collectTokenValues, enforceBreakingRequiresMajor, ensureScale, findContractViolations, removeToken, removeTokensMatching, renameToken, runAdditiveTokensCssMigrations, runTokensCssMigrations, semverBumpType, setTokenValue, validateTokensCss };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TOKENS_CSS_MIGRATIONS,
|
|
3
|
+
appendMediaBlock,
|
|
3
4
|
collectDefinedTokens,
|
|
4
5
|
collectReferencedTokens,
|
|
5
6
|
collectTokenValues,
|
|
@@ -12,14 +13,16 @@ import {
|
|
|
12
13
|
runAdditiveTokensCssMigrations,
|
|
13
14
|
runTokensCssMigrations,
|
|
14
15
|
semverBumpType,
|
|
16
|
+
setTokenValue,
|
|
15
17
|
validateTokensCss
|
|
16
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-JOSSYGR2.js";
|
|
17
19
|
import "../chunk-7TQQTHI6.js";
|
|
18
20
|
import {
|
|
19
21
|
readLiveTokensConfig
|
|
20
22
|
} from "../chunk-6WGFOJXO.js";
|
|
21
23
|
export {
|
|
22
24
|
TOKENS_CSS_MIGRATIONS,
|
|
25
|
+
appendMediaBlock,
|
|
23
26
|
collectDefinedTokens,
|
|
24
27
|
collectReferencedTokens,
|
|
25
28
|
collectTokenValues,
|
|
@@ -33,5 +36,6 @@ export {
|
|
|
33
36
|
runAdditiveTokensCssMigrations,
|
|
34
37
|
runTokensCssMigrations,
|
|
35
38
|
semverBumpType,
|
|
39
|
+
setTokenValue,
|
|
36
40
|
validateTokensCss
|
|
37
41
|
};
|
package/package.json
CHANGED
package/src/app/site.css
CHANGED
|
@@ -52,6 +52,28 @@ h4 {
|
|
|
52
52
|
margin: var(--space-16) 0 var(--space-4);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
h5 {
|
|
56
|
+
font-family: var(--heading-xs-font-family);
|
|
57
|
+
font-size: var(--heading-xs-font-size);
|
|
58
|
+
font-weight: var(--heading-xs-font-weight);
|
|
59
|
+
line-height: var(--heading-xs-line-height);
|
|
60
|
+
letter-spacing: var(--heading-xs-letter-spacing);
|
|
61
|
+
color: var(--text-primary);
|
|
62
|
+
margin: var(--space-16) 0 var(--space-4);
|
|
63
|
+
overflow-wrap: break-word;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
h6 {
|
|
67
|
+
font-family: var(--heading-2xs-font-family);
|
|
68
|
+
font-size: var(--heading-2xs-font-size);
|
|
69
|
+
font-weight: var(--heading-2xs-font-weight);
|
|
70
|
+
line-height: var(--heading-2xs-line-height);
|
|
71
|
+
letter-spacing: var(--heading-2xs-letter-spacing);
|
|
72
|
+
color: var(--text-primary);
|
|
73
|
+
margin: var(--space-16) 0 var(--space-4);
|
|
74
|
+
overflow-wrap: break-word;
|
|
75
|
+
}
|
|
76
|
+
|
|
55
77
|
@media (max-width: 768px) {
|
|
56
78
|
h1 {
|
|
57
79
|
margin-bottom: var(--space-8);
|
|
@@ -80,19 +102,31 @@ p:last-child {
|
|
|
80
102
|
margin-bottom: 0;
|
|
81
103
|
}
|
|
82
104
|
|
|
105
|
+
small {
|
|
106
|
+
font-family: var(--body-sm-font-family);
|
|
107
|
+
font-size: var(--body-sm-font-size);
|
|
108
|
+
font-weight: var(--body-sm-font-weight);
|
|
109
|
+
line-height: var(--body-sm-line-height);
|
|
110
|
+
letter-spacing: var(--body-sm-letter-spacing);
|
|
111
|
+
}
|
|
112
|
+
|
|
83
113
|
code {
|
|
84
|
-
font-family: var(--code-font-family);
|
|
85
|
-
font-size:
|
|
86
|
-
font-weight: var(--code-font-weight);
|
|
87
|
-
letter-spacing: var(--code-letter-spacing);
|
|
114
|
+
font-family: var(--code-md-font-family);
|
|
115
|
+
font-size: 0.875em;
|
|
116
|
+
font-weight: var(--code-md-font-weight);
|
|
117
|
+
letter-spacing: var(--code-md-letter-spacing);
|
|
88
118
|
}
|
|
89
119
|
|
|
90
120
|
pre {
|
|
91
|
-
font-family: var(--code-font-family);
|
|
92
|
-
font-size: var(--code-font-size);
|
|
93
|
-
font-weight: var(--code-font-weight);
|
|
94
|
-
line-height: var(--code-line-height);
|
|
95
|
-
letter-spacing: var(--code-letter-spacing);
|
|
121
|
+
font-family: var(--code-md-font-family);
|
|
122
|
+
font-size: var(--code-md-font-size);
|
|
123
|
+
font-weight: var(--code-md-font-weight);
|
|
124
|
+
line-height: var(--code-md-line-height);
|
|
125
|
+
letter-spacing: var(--code-md-letter-spacing);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
pre code {
|
|
129
|
+
font-size: inherit;
|
|
96
130
|
}
|
|
97
131
|
|
|
98
132
|
a {
|
|
@@ -255,3 +289,203 @@ blockquote {
|
|
|
255
289
|
letter-spacing: var(--eyebrow-letter-spacing);
|
|
256
290
|
text-transform: var(--eyebrow-text-transform);
|
|
257
291
|
}
|
|
292
|
+
|
|
293
|
+
.display-2xl {
|
|
294
|
+
font-family: var(--display-2xl-font-family);
|
|
295
|
+
font-size: var(--display-2xl-font-size);
|
|
296
|
+
font-weight: var(--display-2xl-font-weight);
|
|
297
|
+
line-height: var(--display-2xl-line-height);
|
|
298
|
+
letter-spacing: var(--display-2xl-letter-spacing);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.display-xl {
|
|
302
|
+
font-family: var(--display-xl-font-family);
|
|
303
|
+
font-size: var(--display-xl-font-size);
|
|
304
|
+
font-weight: var(--display-xl-font-weight);
|
|
305
|
+
line-height: var(--display-xl-line-height);
|
|
306
|
+
letter-spacing: var(--display-xl-letter-spacing);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.display-lg {
|
|
310
|
+
font-family: var(--display-lg-font-family);
|
|
311
|
+
font-size: var(--display-lg-font-size);
|
|
312
|
+
font-weight: var(--display-lg-font-weight);
|
|
313
|
+
line-height: var(--display-lg-line-height);
|
|
314
|
+
letter-spacing: var(--display-lg-letter-spacing);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.display-md {
|
|
318
|
+
font-family: var(--display-md-font-family);
|
|
319
|
+
font-size: var(--display-md-font-size);
|
|
320
|
+
font-weight: var(--display-md-font-weight);
|
|
321
|
+
line-height: var(--display-md-line-height);
|
|
322
|
+
letter-spacing: var(--display-md-letter-spacing);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.display-sm {
|
|
326
|
+
font-family: var(--display-sm-font-family);
|
|
327
|
+
font-size: var(--display-sm-font-size);
|
|
328
|
+
font-weight: var(--display-sm-font-weight);
|
|
329
|
+
line-height: var(--display-sm-line-height);
|
|
330
|
+
letter-spacing: var(--display-sm-letter-spacing);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.display-xs {
|
|
334
|
+
font-family: var(--display-xs-font-family);
|
|
335
|
+
font-size: var(--display-xs-font-size);
|
|
336
|
+
font-weight: var(--display-xs-font-weight);
|
|
337
|
+
line-height: var(--display-xs-line-height);
|
|
338
|
+
letter-spacing: var(--display-xs-letter-spacing);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.display-2xs {
|
|
342
|
+
font-family: var(--display-2xs-font-family);
|
|
343
|
+
font-size: var(--display-2xs-font-size);
|
|
344
|
+
font-weight: var(--display-2xs-font-weight);
|
|
345
|
+
line-height: var(--display-2xs-line-height);
|
|
346
|
+
letter-spacing: var(--display-2xs-letter-spacing);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.heading-2xl {
|
|
350
|
+
font-family: var(--heading-2xl-font-family);
|
|
351
|
+
font-size: var(--heading-2xl-font-size);
|
|
352
|
+
font-weight: var(--heading-2xl-font-weight);
|
|
353
|
+
line-height: var(--heading-2xl-line-height);
|
|
354
|
+
letter-spacing: var(--heading-2xl-letter-spacing);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.heading-xs {
|
|
358
|
+
font-family: var(--heading-xs-font-family);
|
|
359
|
+
font-size: var(--heading-xs-font-size);
|
|
360
|
+
font-weight: var(--heading-xs-font-weight);
|
|
361
|
+
line-height: var(--heading-xs-line-height);
|
|
362
|
+
letter-spacing: var(--heading-xs-letter-spacing);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.heading-2xs {
|
|
366
|
+
font-family: var(--heading-2xs-font-family);
|
|
367
|
+
font-size: var(--heading-2xs-font-size);
|
|
368
|
+
font-weight: var(--heading-2xs-font-weight);
|
|
369
|
+
line-height: var(--heading-2xs-line-height);
|
|
370
|
+
letter-spacing: var(--heading-2xs-letter-spacing);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.body-2xl {
|
|
374
|
+
font-family: var(--body-2xl-font-family);
|
|
375
|
+
font-size: var(--body-2xl-font-size);
|
|
376
|
+
font-weight: var(--body-2xl-font-weight);
|
|
377
|
+
line-height: var(--body-2xl-line-height);
|
|
378
|
+
letter-spacing: var(--body-2xl-letter-spacing);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.body-xl {
|
|
382
|
+
font-family: var(--body-xl-font-family);
|
|
383
|
+
font-size: var(--body-xl-font-size);
|
|
384
|
+
font-weight: var(--body-xl-font-weight);
|
|
385
|
+
line-height: var(--body-xl-line-height);
|
|
386
|
+
letter-spacing: var(--body-xl-letter-spacing);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.body-lg {
|
|
390
|
+
font-family: var(--body-lg-font-family);
|
|
391
|
+
font-size: var(--body-lg-font-size);
|
|
392
|
+
font-weight: var(--body-lg-font-weight);
|
|
393
|
+
line-height: var(--body-lg-line-height);
|
|
394
|
+
letter-spacing: var(--body-lg-letter-spacing);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.body-xs {
|
|
398
|
+
font-family: var(--body-xs-font-family);
|
|
399
|
+
font-size: var(--body-xs-font-size);
|
|
400
|
+
font-weight: var(--body-xs-font-weight);
|
|
401
|
+
line-height: var(--body-xs-line-height);
|
|
402
|
+
letter-spacing: var(--body-xs-letter-spacing);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.body-2xs {
|
|
406
|
+
font-family: var(--body-2xs-font-family);
|
|
407
|
+
font-size: var(--body-2xs-font-size);
|
|
408
|
+
font-weight: var(--body-2xs-font-weight);
|
|
409
|
+
line-height: var(--body-2xs-line-height);
|
|
410
|
+
letter-spacing: var(--body-2xs-letter-spacing);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.editorial-2xl {
|
|
414
|
+
font-family: var(--editorial-2xl-font-family);
|
|
415
|
+
font-size: var(--editorial-2xl-font-size);
|
|
416
|
+
font-weight: var(--editorial-2xl-font-weight);
|
|
417
|
+
line-height: var(--editorial-2xl-line-height);
|
|
418
|
+
letter-spacing: var(--editorial-2xl-letter-spacing);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.editorial-xs {
|
|
422
|
+
font-family: var(--editorial-xs-font-family);
|
|
423
|
+
font-size: var(--editorial-xs-font-size);
|
|
424
|
+
font-weight: var(--editorial-xs-font-weight);
|
|
425
|
+
line-height: var(--editorial-xs-line-height);
|
|
426
|
+
letter-spacing: var(--editorial-xs-letter-spacing);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.editorial-2xs {
|
|
430
|
+
font-family: var(--editorial-2xs-font-family);
|
|
431
|
+
font-size: var(--editorial-2xs-font-size);
|
|
432
|
+
font-weight: var(--editorial-2xs-font-weight);
|
|
433
|
+
line-height: var(--editorial-2xs-line-height);
|
|
434
|
+
letter-spacing: var(--editorial-2xs-letter-spacing);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.code-2xl {
|
|
438
|
+
font-family: var(--code-2xl-font-family);
|
|
439
|
+
font-size: var(--code-2xl-font-size);
|
|
440
|
+
font-weight: var(--code-2xl-font-weight);
|
|
441
|
+
line-height: var(--code-2xl-line-height);
|
|
442
|
+
letter-spacing: var(--code-2xl-letter-spacing);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.code-xl {
|
|
446
|
+
font-family: var(--code-xl-font-family);
|
|
447
|
+
font-size: var(--code-xl-font-size);
|
|
448
|
+
font-weight: var(--code-xl-font-weight);
|
|
449
|
+
line-height: var(--code-xl-line-height);
|
|
450
|
+
letter-spacing: var(--code-xl-letter-spacing);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.code-lg {
|
|
454
|
+
font-family: var(--code-lg-font-family);
|
|
455
|
+
font-size: var(--code-lg-font-size);
|
|
456
|
+
font-weight: var(--code-lg-font-weight);
|
|
457
|
+
line-height: var(--code-lg-line-height);
|
|
458
|
+
letter-spacing: var(--code-lg-letter-spacing);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.code-md {
|
|
462
|
+
font-family: var(--code-md-font-family);
|
|
463
|
+
font-size: var(--code-md-font-size);
|
|
464
|
+
font-weight: var(--code-md-font-weight);
|
|
465
|
+
line-height: var(--code-md-line-height);
|
|
466
|
+
letter-spacing: var(--code-md-letter-spacing);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.code-sm {
|
|
470
|
+
font-family: var(--code-sm-font-family);
|
|
471
|
+
font-size: var(--code-sm-font-size);
|
|
472
|
+
font-weight: var(--code-sm-font-weight);
|
|
473
|
+
line-height: var(--code-sm-line-height);
|
|
474
|
+
letter-spacing: var(--code-sm-letter-spacing);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.code-xs {
|
|
478
|
+
font-family: var(--code-xs-font-family);
|
|
479
|
+
font-size: var(--code-xs-font-size);
|
|
480
|
+
font-weight: var(--code-xs-font-weight);
|
|
481
|
+
line-height: var(--code-xs-line-height);
|
|
482
|
+
letter-spacing: var(--code-xs-letter-spacing);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.code-2xs {
|
|
486
|
+
font-family: var(--code-2xs-font-family);
|
|
487
|
+
font-size: var(--code-2xs-font-size);
|
|
488
|
+
font-weight: var(--code-2xs-font-weight);
|
|
489
|
+
line-height: var(--code-2xs-line-height);
|
|
490
|
+
letter-spacing: var(--code-2xs-letter-spacing);
|
|
491
|
+
}
|
|
@@ -607,10 +607,10 @@
|
|
|
607
607
|
|
|
608
608
|
code {
|
|
609
609
|
font-family: var(--code-font-family);
|
|
610
|
-
font-size: var(--code-font-size);
|
|
610
|
+
font-size: var(--code-md-font-size);
|
|
611
611
|
font-weight: var(--code-font-weight);
|
|
612
|
-
line-height: var(--code-line-height);
|
|
613
|
-
letter-spacing: var(--code-letter-spacing);
|
|
612
|
+
line-height: var(--code-md-line-height);
|
|
613
|
+
letter-spacing: var(--code-md-letter-spacing);
|
|
614
614
|
background: var(--tint-low);
|
|
615
615
|
padding-inline: var(--space-4);
|
|
616
616
|
border-radius: var(--radius-sm);
|
|
@@ -863,10 +863,10 @@
|
|
|
863
863
|
|
|
864
864
|
.dg :global(.rule) {
|
|
865
865
|
font-family: var(--code-font-family);
|
|
866
|
-
font-size: var(--code-font-size);
|
|
866
|
+
font-size: var(--code-md-font-size);
|
|
867
867
|
font-weight: var(--code-font-weight);
|
|
868
|
-
line-height: var(--code-line-height);
|
|
869
|
-
letter-spacing: var(--code-letter-spacing);
|
|
868
|
+
line-height: var(--code-md-line-height);
|
|
869
|
+
letter-spacing: var(--code-md-letter-spacing);
|
|
870
870
|
fill: var(--text-accent);
|
|
871
871
|
}
|
|
872
872
|
|
|
@@ -901,10 +901,10 @@
|
|
|
901
901
|
padding-top: var(--space-24);
|
|
902
902
|
border-top: var(--border-width-1) solid var(--border-neutral-subtle);
|
|
903
903
|
font-family: var(--code-font-family);
|
|
904
|
-
font-size: var(--code-font-size);
|
|
904
|
+
font-size: var(--code-md-font-size);
|
|
905
905
|
font-weight: var(--code-font-weight);
|
|
906
|
-
line-height: var(--code-line-height);
|
|
907
|
-
letter-spacing: var(--code-letter-spacing);
|
|
906
|
+
line-height: var(--code-md-line-height);
|
|
907
|
+
letter-spacing: var(--code-md-letter-spacing);
|
|
908
908
|
color: var(--text-secondary);
|
|
909
909
|
}
|
|
910
910
|
|
|
@@ -18,6 +18,7 @@ export interface FaceCoverage {
|
|
|
18
18
|
|
|
19
19
|
const STACK_REF = /var\(\s*(--font-(?:display|sans|serif|mono))\s*\)/;
|
|
20
20
|
const VAR_REF = /var\(\s*(--[a-z0-9-]+)/i;
|
|
21
|
+
const ALIAS = /^var\(\s*(--[a-z0-9-]+)\s*\)$/i;
|
|
21
22
|
|
|
22
23
|
function declarations(css: string): Map<string, string> {
|
|
23
24
|
const decls = new Map<string, string>();
|
|
@@ -27,6 +28,28 @@ function declarations(css: string): Map<string, string> {
|
|
|
27
28
|
return decls;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Follows whole-value aliases, such as a text style's `var(--heading-font-weight)`,
|
|
33
|
+
* until `read` accepts a value. A `--font-*` stack or weight token ends the walk,
|
|
34
|
+
* so an alias between stacks, such as `--font-editorial`, counts for no stack.
|
|
35
|
+
*/
|
|
36
|
+
function follow<T>(
|
|
37
|
+
decls: Map<string, string>,
|
|
38
|
+
value: string | undefined,
|
|
39
|
+
read: (v: string) => T | undefined,
|
|
40
|
+
): T | undefined {
|
|
41
|
+
const seen = new Set<string>();
|
|
42
|
+
while (value !== undefined) {
|
|
43
|
+
const hit = read(value);
|
|
44
|
+
if (hit !== undefined) return hit;
|
|
45
|
+
const next = value.match(ALIAS)?.[1];
|
|
46
|
+
if (!next || next.startsWith('--font-') || seen.has(next)) return undefined;
|
|
47
|
+
seen.add(next);
|
|
48
|
+
value = decls.get(next);
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
30
53
|
/**
|
|
31
54
|
* Every weight the token contract asks of each font stack, read off the
|
|
32
55
|
* `-font-family` / `-font-weight` pairing that typography tokens follow.
|
|
@@ -50,10 +73,16 @@ export function requiredWeights(
|
|
|
50
73
|
for (const [name, value] of decls) {
|
|
51
74
|
const familyVariable = inferFontFamilyVariable(name);
|
|
52
75
|
if (!familyVariable) continue;
|
|
53
|
-
const stack =
|
|
76
|
+
const stack = follow(
|
|
77
|
+
decls,
|
|
78
|
+
decls.get(familyVariable),
|
|
79
|
+
(v) => v.match(STACK_REF)?.[1] as FontStackVariable | undefined,
|
|
80
|
+
);
|
|
54
81
|
if (!stack) continue;
|
|
55
82
|
|
|
56
|
-
const weight =
|
|
83
|
+
const weight = follow(decls, value, (v) =>
|
|
84
|
+
/^\d+$/.test(v) ? Number(v) : scale.get(v.match(VAR_REF)?.[1] ?? ''),
|
|
85
|
+
);
|
|
57
86
|
if (weight === undefined) continue;
|
|
58
87
|
|
|
59
88
|
const key = `${stack}:${weight}`;
|
|
@@ -23,6 +23,8 @@ import tokensCss from '../../../system/styles/tokens.css?raw';
|
|
|
23
23
|
import { editorState } from '../store/editorStore';
|
|
24
24
|
import type { EditorState } from '../store/editorTypes';
|
|
25
25
|
import { extractGlobalRootBody } from '../themes/parsers/globalRootBlock';
|
|
26
|
+
import { stripMediaBlocks } from '../themes/parsers/mediaBlocks';
|
|
27
|
+
import { parseColorOpacity } from '../themes/parsers/colorOpacity';
|
|
26
28
|
import { refToCss } from '../store/cssVarRef';
|
|
27
29
|
|
|
28
30
|
// Re-exported for tests and downstream consumers that previously imported it
|
|
@@ -43,39 +45,51 @@ export interface TokenRegistry {
|
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
47
|
* Pure constructor: parses a CSS source string (possibly concatenated from
|
|
46
|
-
* multiple files) and returns a registry bound to that snapshot.
|
|
48
|
+
* multiple files) and returns a registry bound to that snapshot. A declaration
|
|
49
|
+
* inside `@media` is a breakpoint re-point and never counts as declared.
|
|
47
50
|
*/
|
|
48
51
|
export function buildTokenRegistry(cssText: string): TokenRegistry {
|
|
49
52
|
const declarations = new Map<string, string>();
|
|
50
53
|
const re = /(--[a-z0-9-]+)\s*:\s*([^;]+);/gi;
|
|
51
54
|
let m: RegExpExecArray | null;
|
|
52
|
-
|
|
55
|
+
const topLevel = stripMediaBlocks(cssText);
|
|
56
|
+
while ((m = re.exec(topLevel)) !== null) {
|
|
53
57
|
declarations.set(m[1], m[2].trim());
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
const chain = [varName];
|
|
58
|
-
const visited = new Set<string>([varName]);
|
|
59
|
-
let current = varName;
|
|
60
|
-
while (true) {
|
|
61
|
-
const decl = declarations.get(current);
|
|
62
|
-
if (!decl) return chain;
|
|
63
|
-
const aliasMatch = decl.match(/var\((--[a-z0-9-]+)\)/i);
|
|
64
|
-
if (!aliasMatch) return chain;
|
|
65
|
-
const next = aliasMatch[1];
|
|
66
|
-
if (visited.has(next)) return chain;
|
|
67
|
-
visited.add(next);
|
|
68
|
-
chain.push(next);
|
|
69
|
-
current = next;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
60
|
+
const getDeclaredValue = (v: string): string | null => declarations.get(v) ?? null;
|
|
73
61
|
return {
|
|
74
|
-
getDeclaredValue
|
|
75
|
-
resolveAliasChain,
|
|
62
|
+
getDeclaredValue,
|
|
63
|
+
resolveAliasChain: (varName) => walkAliasChain(varName, getDeclaredValue),
|
|
76
64
|
};
|
|
77
65
|
}
|
|
78
66
|
|
|
67
|
+
const ALIAS_RE = /^var\(\s*(--[a-z0-9-]+)\s*\)$/i;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The token a declaration aliases: the whole value is `var(--x)`, or `--x` at
|
|
71
|
+
* reduced opacity. A `var()` inside any other expression is arithmetic on the
|
|
72
|
+
* token, so `calc(var(--x) * 2)` aliases nothing.
|
|
73
|
+
*/
|
|
74
|
+
function aliasTarget(decl: string): string | null {
|
|
75
|
+
return decl.match(ALIAS_RE)?.[1] ?? parseColorOpacity(decl)?.name ?? null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function walkAliasChain(varName: string, getDeclared: (v: string) => string | null): string[] {
|
|
79
|
+
const chain = [varName];
|
|
80
|
+
const visited = new Set<string>([varName]);
|
|
81
|
+
let current = varName;
|
|
82
|
+
while (true) {
|
|
83
|
+
const decl = getDeclared(current);
|
|
84
|
+
if (!decl) return chain;
|
|
85
|
+
const next = aliasTarget(decl);
|
|
86
|
+
if (!next || visited.has(next)) return chain;
|
|
87
|
+
visited.add(next);
|
|
88
|
+
chain.push(next);
|
|
89
|
+
current = next;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
const componentTokenCss = Object.values(componentSources)
|
|
80
94
|
.map(extractGlobalRootBody)
|
|
81
95
|
.join('\n');
|
|
@@ -119,22 +133,7 @@ function buildOverlayRegistry(
|
|
|
119
133
|
overrides.has(v) ? overrides.get(v)! : base.getDeclaredValue(v);
|
|
120
134
|
return {
|
|
121
135
|
getDeclaredValue: getDeclared,
|
|
122
|
-
resolveAliasChain(varName
|
|
123
|
-
const chain = [varName];
|
|
124
|
-
const visited = new Set<string>([varName]);
|
|
125
|
-
let current = varName;
|
|
126
|
-
while (true) {
|
|
127
|
-
const decl = getDeclared(current);
|
|
128
|
-
if (!decl) return chain;
|
|
129
|
-
const aliasMatch = decl.match(/var\((--[a-z0-9-]+)\)/i);
|
|
130
|
-
if (!aliasMatch) return chain;
|
|
131
|
-
const next = aliasMatch[1];
|
|
132
|
-
if (visited.has(next)) return chain;
|
|
133
|
-
visited.add(next);
|
|
134
|
-
chain.push(next);
|
|
135
|
-
current = next;
|
|
136
|
-
}
|
|
137
|
-
},
|
|
136
|
+
resolveAliasChain: (varName) => walkAliasChain(varName, getDeclared),
|
|
138
137
|
};
|
|
139
138
|
}
|
|
140
139
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `css` with every `@media` block removed. Readers that want a token's declared
|
|
3
|
+
* default go through it, so a breakpoint re-point never stands in for the
|
|
4
|
+
* top-level value.
|
|
5
|
+
*
|
|
6
|
+
* Dependency-free so the vite plugin build can import it, as it does
|
|
7
|
+
* `globalRootBlock`.
|
|
8
|
+
*/
|
|
9
|
+
export function stripMediaBlocks(css: string): string {
|
|
10
|
+
const kept: string[] = [];
|
|
11
|
+
let from = 0;
|
|
12
|
+
let i = 0;
|
|
13
|
+
while (i < css.length) {
|
|
14
|
+
if (css.startsWith('/*', i)) {
|
|
15
|
+
i = commentEnd(css, i);
|
|
16
|
+
} else if (css[i] === '@' && /^@media\b/i.test(css.slice(i, i + 7))) {
|
|
17
|
+
kept.push(css.slice(from, i));
|
|
18
|
+
i = from = blockEnd(css, i);
|
|
19
|
+
} else {
|
|
20
|
+
i++;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
kept.push(css.slice(from));
|
|
24
|
+
return kept.join('');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function commentEnd(css: string, start: number): number {
|
|
28
|
+
const end = css.indexOf('*/', start + 2);
|
|
29
|
+
return end === -1 ? css.length : end + 2;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Index just past the brace that closes the first block opened at or after `start`. */
|
|
33
|
+
function blockEnd(css: string, start: number): number {
|
|
34
|
+
let depth = 0;
|
|
35
|
+
let i = start;
|
|
36
|
+
while (i < css.length) {
|
|
37
|
+
if (css.startsWith('/*', i)) {
|
|
38
|
+
i = commentEnd(css, i);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const c = css[i++];
|
|
42
|
+
if (c === '{') depth++;
|
|
43
|
+
else if (c === '}' && --depth === 0) return i;
|
|
44
|
+
}
|
|
45
|
+
return css.length;
|
|
46
|
+
}
|