@primer/primitives 11.4.0-rc.daff2d10 → 11.4.0-rc.e472be0d
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/build/formats/markdownLlmGuidelines.d.ts +3 -1
- package/dist/build/formats/markdownLlmGuidelines.js +53 -10
- package/dist/build/platforms/llmGuidelines.js +1 -0
- package/dist/build/preprocessors/inheritGroupProperties.d.ts +7 -0
- package/dist/build/preprocessors/inheritGroupProperties.js +70 -0
- package/dist/build/primerStyleDictionary.js +2 -0
- package/dist/build/schemas/designToken.d.ts +1 -1
- package/dist/build/schemas/designToken.js +113 -21
- package/dist/build/schemas/dimensionToken.d.ts +2 -2
- package/dist/build/schemas/dimensionToken.js +4 -2
- package/dist/build/schemas/validTokenType.d.ts +5 -1
- package/dist/build/schemas/validTokenType.js +71 -17
- package/dist/css/functional/size/size-coarse.css +3 -3
- package/dist/css/functional/size/size-fine.css +3 -3
- package/dist/css/functional/themes/dark-colorblind-high-contrast.css +4 -4
- package/dist/css/functional/themes/dark-colorblind.css +4 -4
- package/dist/css/functional/themes/dark-dimmed-high-contrast.css +4 -4
- package/dist/css/functional/themes/dark-dimmed.css +4 -4
- package/dist/css/functional/themes/dark-high-contrast.css +4 -4
- package/dist/css/functional/themes/dark-tritanopia-high-contrast.css +4 -4
- package/dist/css/functional/themes/dark-tritanopia.css +4 -4
- package/dist/css/functional/themes/dark.css +4 -4
- package/dist/css/functional/themes/light-colorblind-high-contrast.css +4 -4
- package/dist/css/functional/themes/light-colorblind.css +4 -4
- package/dist/css/functional/themes/light-high-contrast.css +4 -4
- package/dist/css/functional/themes/light-tritanopia-high-contrast.css +4 -4
- package/dist/css/functional/themes/light-tritanopia.css +4 -4
- package/dist/css/functional/themes/light.css +4 -4
- package/dist/docs/functional/size/size-coarse.json +45 -3
- package/dist/docs/functional/size/size-fine.json +45 -3
- package/dist/docs/functional/themes/dark-colorblind-high-contrast.json +22 -2
- package/dist/docs/functional/themes/dark-colorblind.json +22 -2
- package/dist/docs/functional/themes/dark-dimmed-high-contrast.json +22 -2
- package/dist/docs/functional/themes/dark-dimmed.json +22 -2
- package/dist/docs/functional/themes/dark-high-contrast.json +22 -2
- package/dist/docs/functional/themes/dark-tritanopia-high-contrast.json +22 -2
- package/dist/docs/functional/themes/dark-tritanopia.json +22 -2
- package/dist/docs/functional/themes/dark.json +22 -2
- package/dist/docs/functional/themes/light-colorblind-high-contrast.json +22 -2
- package/dist/docs/functional/themes/light-colorblind.json +22 -2
- package/dist/docs/functional/themes/light-high-contrast.json +22 -2
- package/dist/docs/functional/themes/light-tritanopia-high-contrast.json +22 -2
- package/dist/docs/functional/themes/light-tritanopia.json +22 -2
- package/dist/docs/functional/themes/light.json +22 -2
- package/dist/figma/themes/dark-colorblind.json +2 -0
- package/dist/figma/themes/dark-dimmed.json +2 -0
- package/dist/figma/themes/dark-high-contrast.json +2 -0
- package/dist/figma/themes/dark-tritanopia.json +2 -0
- package/dist/figma/themes/dark.json +2 -0
- package/dist/figma/themes/light-colorblind.json +2 -0
- package/dist/figma/themes/light-high-contrast.json +2 -0
- package/dist/figma/themes/light-tritanopia.json +2 -0
- package/dist/figma/themes/light.json +2 -0
- package/dist/internalCss/dark-colorblind-high-contrast.css +4 -4
- package/dist/internalCss/dark-colorblind.css +4 -4
- package/dist/internalCss/dark-dimmed-high-contrast.css +4 -4
- package/dist/internalCss/dark-dimmed.css +4 -4
- package/dist/internalCss/dark-high-contrast.css +4 -4
- package/dist/internalCss/dark-tritanopia-high-contrast.css +4 -4
- package/dist/internalCss/dark-tritanopia.css +4 -4
- package/dist/internalCss/dark.css +4 -4
- package/dist/internalCss/light-colorblind-high-contrast.css +4 -4
- package/dist/internalCss/light-colorblind.css +4 -4
- package/dist/internalCss/light-high-contrast.css +4 -4
- package/dist/internalCss/light-tritanopia-high-contrast.css +4 -4
- package/dist/internalCss/light-tritanopia.css +4 -4
- package/dist/internalCss/light.css +4 -4
- package/dist/styleLint/functional/size/size-coarse.json +42 -0
- package/dist/styleLint/functional/size/size-fine.json +42 -0
- package/dist/styleLint/functional/themes/dark-colorblind-high-contrast.json +20 -0
- package/dist/styleLint/functional/themes/dark-colorblind.json +20 -0
- package/dist/styleLint/functional/themes/dark-dimmed-high-contrast.json +20 -0
- package/dist/styleLint/functional/themes/dark-dimmed.json +20 -0
- package/dist/styleLint/functional/themes/dark-high-contrast.json +20 -0
- package/dist/styleLint/functional/themes/dark-tritanopia-high-contrast.json +20 -0
- package/dist/styleLint/functional/themes/dark-tritanopia.json +20 -0
- package/dist/styleLint/functional/themes/dark.json +20 -0
- package/dist/styleLint/functional/themes/light-colorblind-high-contrast.json +20 -0
- package/dist/styleLint/functional/themes/light-colorblind.json +20 -0
- package/dist/styleLint/functional/themes/light-high-contrast.json +20 -0
- package/dist/styleLint/functional/themes/light-tritanopia-high-contrast.json +20 -0
- package/dist/styleLint/functional/themes/light-tritanopia.json +20 -0
- package/dist/styleLint/functional/themes/light.json +20 -0
- package/package.json +1 -1
- package/src/tokens/functional/color/data-vis.json5 +7 -0
- package/src/tokens/functional/color/focus.json5 +5 -0
- package/src/tokens/functional/color/selection.json5 +5 -0
- package/src/tokens/functional/size/size-coarse.json5 +24 -3
- package/src/tokens/functional/size/size-fine.json5 +45 -24
- package/token-guidelines.llm.md +109 -86
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { FormatFn } from 'style-dictionary/types';
|
|
2
2
|
/**
|
|
3
3
|
* @description Outputs a markdown file with LLM token guidelines, extracting
|
|
4
|
-
* description from $description and usage/rules from $extensions['org.primer.llm']
|
|
4
|
+
* description from $description and usage/rules from $extensions['org.primer.llm'].
|
|
5
|
+
* Tokens with identical guidelines (from group-level inheritance) are consolidated
|
|
6
|
+
* into a single entry listing all token names.
|
|
5
7
|
* @param FormatFnArguments
|
|
6
8
|
* @returns formatted markdown `string`
|
|
7
9
|
*/
|
|
@@ -8,6 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { sortByName } from 'style-dictionary/utils';
|
|
11
|
+
/**
|
|
12
|
+
* Creates a unique key for grouping tokens with identical guidelines
|
|
13
|
+
*/
|
|
14
|
+
function createGuidelineKey(guideline) {
|
|
15
|
+
var _a;
|
|
16
|
+
return JSON.stringify({
|
|
17
|
+
description: guideline.description || '',
|
|
18
|
+
usage: ((_a = guideline.usage) === null || _a === void 0 ? void 0 : _a.sort()) || [],
|
|
19
|
+
rules: guideline.rules || '',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
11
22
|
/**
|
|
12
23
|
* Extracts category from token name
|
|
13
24
|
* - For "base-*" tokens, uses second word (e.g., "base-easing-ease" -> "easing")
|
|
@@ -36,7 +47,9 @@ function formatCategoryName(category) {
|
|
|
36
47
|
}
|
|
37
48
|
/**
|
|
38
49
|
* @description Outputs a markdown file with LLM token guidelines, extracting
|
|
39
|
-
* description from $description and usage/rules from $extensions['org.primer.llm']
|
|
50
|
+
* description from $description and usage/rules from $extensions['org.primer.llm'].
|
|
51
|
+
* Tokens with identical guidelines (from group-level inheritance) are consolidated
|
|
52
|
+
* into a single entry listing all token names.
|
|
40
53
|
* @param FormatFnArguments
|
|
41
54
|
* @returns formatted markdown `string`
|
|
42
55
|
*/
|
|
@@ -75,18 +88,48 @@ export const markdownLlmGuidelines = (_a) => __awaiter(void 0, [_a], void 0, fun
|
|
|
75
88
|
const lines = ['# Token Guidelines', ''];
|
|
76
89
|
for (const category of Object.keys(grouped).sort()) {
|
|
77
90
|
lines.push(`## ${formatCategoryName(category)}`, '');
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
const categoryGuidelines = grouped[category];
|
|
92
|
+
// Group tokens with identical guidelines
|
|
93
|
+
const consolidatedGroups = new Map();
|
|
94
|
+
for (const guideline of categoryGuidelines) {
|
|
95
|
+
const key = createGuidelineKey(guideline);
|
|
96
|
+
if (!consolidatedGroups.has(key)) {
|
|
97
|
+
consolidatedGroups.set(key, []);
|
|
82
98
|
}
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
consolidatedGroups.get(key).push(guideline);
|
|
100
|
+
}
|
|
101
|
+
for (const [, guidelinesGroup] of consolidatedGroups) {
|
|
102
|
+
const first = guidelinesGroup[0];
|
|
103
|
+
if (guidelinesGroup.length > 1) {
|
|
104
|
+
// Multiple tokens share the same guidelines - consolidate
|
|
105
|
+
if (first.description) {
|
|
106
|
+
lines.push(first.description);
|
|
107
|
+
lines.push('');
|
|
108
|
+
}
|
|
109
|
+
if (first.usage && first.usage.length > 0) {
|
|
110
|
+
lines.push(`**Usage:** ${first.usage.join(', ')}`);
|
|
111
|
+
}
|
|
112
|
+
if (first.rules) {
|
|
113
|
+
lines.push(`**Rules:** ${first.rules}`);
|
|
114
|
+
}
|
|
115
|
+
lines.push('');
|
|
116
|
+
lines.push(`**Tokens:** ${guidelinesGroup.map(g => g.name).join(', ')}`);
|
|
117
|
+
lines.push('');
|
|
85
118
|
}
|
|
86
|
-
|
|
87
|
-
|
|
119
|
+
else {
|
|
120
|
+
// Single token - output individually
|
|
121
|
+
lines.push(`### ${first.name}`);
|
|
122
|
+
if (first.description) {
|
|
123
|
+
lines.push(first.description);
|
|
124
|
+
}
|
|
125
|
+
if (first.usage && first.usage.length > 0) {
|
|
126
|
+
lines.push(`**Usage:** ${first.usage.join(', ')}`);
|
|
127
|
+
}
|
|
128
|
+
if (first.rules) {
|
|
129
|
+
lines.push(`**Rules:** ${first.rules}`);
|
|
130
|
+
}
|
|
131
|
+
lines.push('');
|
|
88
132
|
}
|
|
89
|
-
lines.push('');
|
|
90
133
|
}
|
|
91
134
|
}
|
|
92
135
|
return lines.join('\n');
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Preprocessor } from 'style-dictionary/types';
|
|
2
|
+
/**
|
|
3
|
+
* Preprocessor that inherits group-level $description and $extensions to child tokens.
|
|
4
|
+
* This enables W3C Design Tokens group properties to be available on individual tokens
|
|
5
|
+
* during formatting.
|
|
6
|
+
*/
|
|
7
|
+
export declare const inheritGroupProperties: Preprocessor;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively walks tokens and inherits group-level properties to child tokens.
|
|
3
|
+
* Group properties ($description, $extensions at group level) are merged into child tokens
|
|
4
|
+
* that don't have their own values for those properties.
|
|
5
|
+
*
|
|
6
|
+
* Per W3C Design Tokens spec: https://www.designtokens.org/tr/drafts/format/#group-properties
|
|
7
|
+
*/
|
|
8
|
+
function inheritProperties(tokens, inheritedProps = {}) {
|
|
9
|
+
var _a;
|
|
10
|
+
const result = {};
|
|
11
|
+
// Extract group-level properties from current level
|
|
12
|
+
const currentGroupProps = {};
|
|
13
|
+
if (typeof tokens.$description === 'string') {
|
|
14
|
+
currentGroupProps.$description = tokens.$description;
|
|
15
|
+
}
|
|
16
|
+
if (tokens.$extensions && typeof tokens.$extensions === 'object') {
|
|
17
|
+
currentGroupProps.$extensions = tokens.$extensions;
|
|
18
|
+
}
|
|
19
|
+
// Merge inherited with current (current takes precedence)
|
|
20
|
+
const mergedProps = Object.assign(Object.assign({}, inheritedProps), currentGroupProps);
|
|
21
|
+
// Merge $extensions deeply
|
|
22
|
+
if (inheritedProps.$extensions || currentGroupProps.$extensions) {
|
|
23
|
+
mergedProps.$extensions = Object.assign(Object.assign({}, inheritedProps.$extensions), currentGroupProps.$extensions);
|
|
24
|
+
}
|
|
25
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
26
|
+
// Skip group-level properties (they're inherited, not copied)
|
|
27
|
+
if (key === '$description' || key === '$extensions') {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (typeof value !== 'object' || value === null) {
|
|
31
|
+
result[key] = value;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const tokenValue = value;
|
|
35
|
+
// Check if this is a design token (has $value or value)
|
|
36
|
+
if ('$value' in tokenValue || 'value' in tokenValue) {
|
|
37
|
+
// It's a token - merge inherited properties
|
|
38
|
+
const token = tokenValue;
|
|
39
|
+
// Only inherit $description if token doesn't have its own
|
|
40
|
+
const inheritedDescription = !token.$description && mergedProps.$description ? mergedProps.$description : undefined;
|
|
41
|
+
// Merge $extensions (token-level takes precedence over inherited)
|
|
42
|
+
let mergedExtensions = token.$extensions;
|
|
43
|
+
if (mergedProps.$extensions) {
|
|
44
|
+
const inheritedLlm = mergedProps.$extensions['org.primer.llm'];
|
|
45
|
+
const tokenLlm = (_a = token.$extensions) === null || _a === void 0 ? void 0 : _a['org.primer.llm'];
|
|
46
|
+
if (inheritedLlm && !tokenLlm) {
|
|
47
|
+
// Token has no LLM extension, inherit from group
|
|
48
|
+
mergedExtensions = Object.assign(Object.assign({}, token.$extensions), { 'org.primer.llm': inheritedLlm });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
result[key] = Object.assign(Object.assign(Object.assign({}, token), (inheritedDescription ? { $description: inheritedDescription } : {})), (mergedExtensions ? { $extensions: mergedExtensions } : {}));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// It's a nested group - recurse with merged properties
|
|
55
|
+
result[key] = inheritProperties(tokenValue, mergedProps);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Preprocessor that inherits group-level $description and $extensions to child tokens.
|
|
62
|
+
* This enables W3C Design Tokens group properties to be available on individual tokens
|
|
63
|
+
* during formatting.
|
|
64
|
+
*/
|
|
65
|
+
export const inheritGroupProperties = {
|
|
66
|
+
name: 'inheritGroupProperties',
|
|
67
|
+
preprocessor: (dictionary) => {
|
|
68
|
+
return inheritProperties(dictionary);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -2,6 +2,7 @@ import StyleDictionary from 'style-dictionary';
|
|
|
2
2
|
import { borderToCss, colorToRgbAlpha, colorToHex, colorToRgbaFloat, cubicBezierToCss, dimensionToRem, dimensionToPixelUnitless, durationToCss, figmaAttributes, fontFamilyToCss, fontFamilyToFigma, fontWeightToNumber, gradientToCss, jsonDeprecated, namePathToDotNotation, namePathToCamelCase, namePathToPascalCase, namePathToKebabCase, namePathToSlashNotation, namePathToFigma, shadowToCss, typographyToCss, dimensionToRemPxArray, floatToPixel, floatToPixelUnitless, transitionToCss, } from './transformers/index.js';
|
|
3
3
|
import { javascriptCommonJs, javascriptEsm, typescriptExportDefinition, jsonNestedPrefixed, cssCustomMedia, jsonOneDimensional, jsonPostCssFallback, cssAdvanced, jsonFigma, markdownLlmGuidelines, } from './formats/index.js';
|
|
4
4
|
import { themeOverrides } from './preprocessors/themeOverrides.js';
|
|
5
|
+
import { inheritGroupProperties } from './preprocessors/inheritGroupProperties.js';
|
|
5
6
|
import { colorAlphaToCss } from './transformers/colorAlphaToCss.js';
|
|
6
7
|
/**
|
|
7
8
|
* @name {@link PrimerStyleDictionary}
|
|
@@ -92,3 +93,4 @@ PrimerStyleDictionary.registerTransform(fontFamilyToCss);
|
|
|
92
93
|
PrimerStyleDictionary.registerTransform(fontFamilyToFigma);
|
|
93
94
|
PrimerStyleDictionary.registerTransform(gradientToCss);
|
|
94
95
|
PrimerStyleDictionary.registerPreprocessor(themeOverrides);
|
|
96
|
+
PrimerStyleDictionary.registerPreprocessor(inheritGroupProperties);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export declare const designToken: z.
|
|
2
|
+
export declare const designToken: z.ZodType<unknown>;
|
|
@@ -14,26 +14,118 @@ import { durationToken } from './durationToken.js';
|
|
|
14
14
|
import { cubicBezierToken } from './cubicBezierToken.js';
|
|
15
15
|
import { gradientToken } from './gradientToken.js';
|
|
16
16
|
import { transitionToken } from './transitionToken.js';
|
|
17
|
+
import { llmExtension } from './llmExtension.js';
|
|
18
|
+
/**
|
|
19
|
+
* Group-level extensions schema (W3C Design Tokens spec)
|
|
20
|
+
* https://www.designtokens.org/tr/drafts/format/#group-properties
|
|
21
|
+
*/
|
|
22
|
+
const groupExtensions = z
|
|
23
|
+
.object({
|
|
24
|
+
'org.primer.llm': llmExtension,
|
|
25
|
+
})
|
|
26
|
+
.passthrough();
|
|
27
|
+
/**
|
|
28
|
+
* All valid token types with $type discriminator
|
|
29
|
+
*/
|
|
30
|
+
const tokenTypes = z.discriminatedUnion('$type', [
|
|
31
|
+
colorToken,
|
|
32
|
+
cubicBezierToken,
|
|
33
|
+
dimensionToken,
|
|
34
|
+
shadowToken,
|
|
35
|
+
borderToken,
|
|
36
|
+
fontFamilyToken,
|
|
37
|
+
fontWeightToken,
|
|
38
|
+
gradientToken,
|
|
39
|
+
typographyToken,
|
|
40
|
+
viewportRangeToken,
|
|
41
|
+
numberToken,
|
|
42
|
+
durationToken,
|
|
43
|
+
stringToken,
|
|
44
|
+
transitionToken,
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* Validates a record allowing both token names and group properties ($description, $extensions)
|
|
48
|
+
* Recursively validates nested groups
|
|
49
|
+
*/
|
|
50
|
+
const createDesignTokenSchema = () => {
|
|
51
|
+
return z.record(z.string(), z.unknown()).superRefine((obj, ctx) => {
|
|
52
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
53
|
+
if (key === '$description') {
|
|
54
|
+
// Group-level $description must be a string
|
|
55
|
+
if (typeof value !== 'string') {
|
|
56
|
+
ctx.addIssue({
|
|
57
|
+
code: z.ZodIssueCode.custom,
|
|
58
|
+
message: `$description must be a string, got ${typeof value}`,
|
|
59
|
+
path: [key],
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (key === '$extensions') {
|
|
64
|
+
// Group-level $extensions must be an object
|
|
65
|
+
if (typeof value !== 'object' || value === null) {
|
|
66
|
+
ctx.addIssue({
|
|
67
|
+
code: z.ZodIssueCode.custom,
|
|
68
|
+
message: `$extensions must be an object`,
|
|
69
|
+
path: [key],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const result = groupExtensions.safeParse(value);
|
|
74
|
+
if (!result.success) {
|
|
75
|
+
for (const issue of result.error.issues) {
|
|
76
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (key.startsWith('$')) {
|
|
82
|
+
// Unknown $-prefixed keys at group level are not allowed
|
|
83
|
+
ctx.addIssue({
|
|
84
|
+
code: z.ZodIssueCode.custom,
|
|
85
|
+
message: `Unknown group property: ${key}. Only $description and $extensions are allowed.`,
|
|
86
|
+
path: [key],
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Validate token name
|
|
91
|
+
const nameResult = tokenName.safeParse(key);
|
|
92
|
+
if (!nameResult.success) {
|
|
93
|
+
for (const issue of nameResult.error.issues) {
|
|
94
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key] }));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Validate value as either a token or nested group
|
|
98
|
+
if (typeof value === 'object' && value !== null) {
|
|
99
|
+
// Check if it's a token (has $type) or a nested group
|
|
100
|
+
if ('$type' in value) {
|
|
101
|
+
const tokenResult = tokenTypes.safeParse(value);
|
|
102
|
+
if (!tokenResult.success) {
|
|
103
|
+
for (const issue of tokenResult.error.issues) {
|
|
104
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Recursively validate nested group
|
|
110
|
+
const nestedResult = designToken.safeParse(value);
|
|
111
|
+
if (!nestedResult.success) {
|
|
112
|
+
for (const issue of nestedResult.error.issues) {
|
|
113
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
ctx.addIssue({
|
|
120
|
+
code: z.ZodIssueCode.custom,
|
|
121
|
+
message: `Expected token or group object, got ${typeof value}`,
|
|
122
|
+
path: [key],
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
};
|
|
17
129
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
18
130
|
// @ts-ignore: TODO: fix this
|
|
19
|
-
export const designToken =
|
|
20
|
-
return z.union([
|
|
21
|
-
z.discriminatedUnion('$type', [
|
|
22
|
-
colorToken,
|
|
23
|
-
cubicBezierToken,
|
|
24
|
-
dimensionToken,
|
|
25
|
-
shadowToken,
|
|
26
|
-
borderToken,
|
|
27
|
-
fontFamilyToken,
|
|
28
|
-
fontWeightToken,
|
|
29
|
-
gradientToken,
|
|
30
|
-
typographyToken,
|
|
31
|
-
viewportRangeToken,
|
|
32
|
-
numberToken,
|
|
33
|
-
durationToken,
|
|
34
|
-
stringToken,
|
|
35
|
-
transitionToken,
|
|
36
|
-
]),
|
|
37
|
-
designToken,
|
|
38
|
-
]);
|
|
39
|
-
}));
|
|
131
|
+
export const designToken = createDesignTokenSchema();
|
|
@@ -5,11 +5,11 @@ export declare const dimensionToken: z.ZodObject<{
|
|
|
5
5
|
$value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"0">, z.ZodLiteral<0>]>, z.ZodString]>;
|
|
6
6
|
$type: z.ZodLiteral<"string" | "number" | "border" | "color" | "fontFamily" | "fontWeight" | "transition" | "dimension" | "duration" | "gradient" | "shadow" | "typography" | "cubicBezier" | "custom-viewportRange">;
|
|
7
7
|
$extensions: z.ZodOptional<z.ZodObject<{
|
|
8
|
-
'org.primer.figma': z.ZodObject<{
|
|
8
|
+
'org.primer.figma': z.ZodOptional<z.ZodObject<{
|
|
9
9
|
collection: z.ZodString;
|
|
10
10
|
scopes: z.ZodArray<z.ZodString>;
|
|
11
11
|
group: z.ZodOptional<z.ZodString>;
|
|
12
|
-
}, z.core.$strip
|
|
12
|
+
}, z.core.$strip>>;
|
|
13
13
|
'org.primer.llm': z.ZodOptional<z.ZodObject<{
|
|
14
14
|
usage: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
15
15
|
rules: z.ZodOptional<z.ZodString>;
|
|
@@ -12,7 +12,8 @@ export const dimensionToken = baseToken
|
|
|
12
12
|
$type: tokenType('dimension'),
|
|
13
13
|
$extensions: z
|
|
14
14
|
.object({
|
|
15
|
-
'org.primer.figma': z
|
|
15
|
+
'org.primer.figma': z
|
|
16
|
+
.object({
|
|
16
17
|
collection: collection(['base/size', 'base/typography', 'functional/size', 'pattern/size', 'typography']),
|
|
17
18
|
scopes: scopes([
|
|
18
19
|
'all',
|
|
@@ -29,7 +30,8 @@ export const dimensionToken = baseToken
|
|
|
29
30
|
'paragraphIndent',
|
|
30
31
|
]),
|
|
31
32
|
group: z.string().optional(),
|
|
32
|
-
})
|
|
33
|
+
})
|
|
34
|
+
.optional(),
|
|
33
35
|
'org.primer.llm': llmExtension,
|
|
34
36
|
})
|
|
35
37
|
.optional(),
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
declare const validTypes: readonly ["color", "cubicBezier", "typography", "dimension", "duration", "border", "shadow", "fontFamily", "fontWeight", "gradient", "number", "string", "transition", "custom-viewportRange"];
|
|
3
3
|
export type TokenType = (typeof validTypes)[number];
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Recursively validates $type properties in token structure
|
|
6
|
+
* Allows group-level properties ($description, $extensions) per W3C Design Tokens spec
|
|
7
|
+
*/
|
|
8
|
+
export declare const validateType: z.ZodType<unknown>;
|
|
5
9
|
export {};
|
|
@@ -16,23 +16,77 @@ const validTypes = [
|
|
|
16
16
|
'transition',
|
|
17
17
|
'custom-viewportRange',
|
|
18
18
|
];
|
|
19
|
+
/**
|
|
20
|
+
* Token schema that validates $type property
|
|
21
|
+
*/
|
|
22
|
+
const tokenWithType = z
|
|
23
|
+
.object({
|
|
24
|
+
$value: z.any(),
|
|
25
|
+
$type: z.string().superRefine((value, ctx) => {
|
|
26
|
+
if (!validTypes.includes(value)) {
|
|
27
|
+
ctx.addIssue({
|
|
28
|
+
code: 'custom',
|
|
29
|
+
message: schemaErrorMessage(`Invalid token $type: "${value}"`, `Must be one of the following: ${joinFriendly([...validTypes], 'or')}`),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}),
|
|
33
|
+
})
|
|
34
|
+
.required();
|
|
35
|
+
/**
|
|
36
|
+
* Recursively validates $type properties in token structure
|
|
37
|
+
* Allows group-level properties ($description, $extensions) per W3C Design Tokens spec
|
|
38
|
+
*/
|
|
19
39
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
20
40
|
// @ts-ignore: TODO: fix this
|
|
21
|
-
export const validateType = z.record(z.string(), z.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
export const validateType = z.record(z.string(), z.unknown()).superRefine((obj, ctx) => {
|
|
42
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
43
|
+
if (key === '$description') {
|
|
44
|
+
// Group-level $description must be a string
|
|
45
|
+
if (typeof value !== 'string') {
|
|
46
|
+
ctx.addIssue({
|
|
47
|
+
code: z.ZodIssueCode.custom,
|
|
48
|
+
message: `$description must be a string`,
|
|
49
|
+
path: [key],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (key === '$extensions') {
|
|
54
|
+
// Group-level $extensions must be an object
|
|
55
|
+
if (typeof value !== 'object' || value === null) {
|
|
56
|
+
ctx.addIssue({
|
|
57
|
+
code: z.ZodIssueCode.custom,
|
|
58
|
+
message: `$extensions must be an object`,
|
|
59
|
+
path: [key],
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (key.startsWith('$')) {
|
|
64
|
+
// Unknown $-prefixed keys are not allowed
|
|
65
|
+
ctx.addIssue({
|
|
66
|
+
code: z.ZodIssueCode.custom,
|
|
67
|
+
message: `Unknown group property: ${key}`,
|
|
68
|
+
path: [key],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
else if (typeof value === 'object' && value !== null) {
|
|
72
|
+
// Check if it's a token (has $type) or a nested group
|
|
73
|
+
if ('$type' in value) {
|
|
74
|
+
const result = tokenWithType.safeParse(value);
|
|
75
|
+
if (!result.success) {
|
|
76
|
+
for (const issue of result.error.issues) {
|
|
77
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
78
|
+
}
|
|
32
79
|
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Recursively validate nested group
|
|
83
|
+
const result = validateType.safeParse(value);
|
|
84
|
+
if (!result.success) {
|
|
85
|
+
for (const issue of result.error.issues) {
|
|
86
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@media (pointer: coarse) {
|
|
2
2
|
:root {
|
|
3
|
-
--control-minTarget-auto: 2.75rem;
|
|
4
|
-
--controlStack-medium-gap-auto: 0.75rem;
|
|
5
|
-
--controlStack-small-gap-auto: 1rem;
|
|
3
|
+
--control-minTarget-auto: 2.75rem; /** Minimum touch target size for coarse pointer devices (touch screens) */
|
|
4
|
+
--controlStack-medium-gap-auto: 0.75rem; /** Gap between stacked controls in medium density layouts for touch devices */
|
|
5
|
+
--controlStack-small-gap-auto: 1rem; /** Gap between stacked controls in small density layouts for touch devices */
|
|
6
6
|
}
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@media (pointer: fine) {
|
|
2
2
|
:root {
|
|
3
|
-
--control-minTarget-auto: 1rem;
|
|
4
|
-
--controlStack-medium-gap-auto: 0.5rem;
|
|
5
|
-
--controlStack-small-gap-auto: 0.5rem;
|
|
3
|
+
--control-minTarget-auto: 1rem; /** Minimum target size for fine pointer devices (mouse) */
|
|
4
|
+
--controlStack-medium-gap-auto: 0.5rem; /** Gap between stacked controls in medium density layouts for mouse interfaces */
|
|
5
|
+
--controlStack-small-gap-auto: 0.5rem; /** Gap between stacked controls in small density layouts for mouse interfaces */
|
|
6
6
|
}
|
|
7
7
|
}
|
|
@@ -759,7 +759,7 @@
|
|
|
759
759
|
--fgColor-onEmphasis: #ffffff; /** Text color for use on emphasis backgrounds */
|
|
760
760
|
--fgColor-onInverse: #010409; /** Text color for use on inverse backgrounds */
|
|
761
761
|
--fgColor-white: #ffffff; /** Pure white text */
|
|
762
|
-
--focus-outlineColor: var(--borderColor-accent-emphasis);
|
|
762
|
+
--focus-outlineColor: var(--borderColor-accent-emphasis); /** Outline color for focus states on interactive elements */
|
|
763
763
|
--header-fgColor-default: #ffffffb3;
|
|
764
764
|
--label-auburn-borderColor: var(--label-auburn-fgColor-rest);
|
|
765
765
|
--label-blue-borderColor: var(--label-blue-fgColor-rest);
|
|
@@ -791,7 +791,7 @@
|
|
|
791
791
|
--progressBar-bgColor-success: var(--bgColor-success-emphasis);
|
|
792
792
|
--reactionButton-selected-fgColor-rest: var(--fgColor-link);
|
|
793
793
|
--selectMenu-borderColor: var(--borderColor-default);
|
|
794
|
-
--selection-bgColor: #194fb1b3;
|
|
794
|
+
--selection-bgColor: #194fb1b3; /** Background color for text selection highlights */
|
|
795
795
|
--shadow-floating-legacy: 0px 6px 12px -3px #01040966, 0px 6px 18px 0px #01040966;
|
|
796
796
|
--shadow-inset: inset 0px 1px 0px 0px #0104093d;
|
|
797
797
|
--shadow-resting-medium: 0px 1px 1px 0px #01040966, 0px 3px 6px 0px #010409cc;
|
|
@@ -1656,7 +1656,7 @@
|
|
|
1656
1656
|
--fgColor-onEmphasis: #ffffff; /** Text color for use on emphasis backgrounds */
|
|
1657
1657
|
--fgColor-onInverse: #010409; /** Text color for use on inverse backgrounds */
|
|
1658
1658
|
--fgColor-white: #ffffff; /** Pure white text */
|
|
1659
|
-
--focus-outlineColor: var(--borderColor-accent-emphasis);
|
|
1659
|
+
--focus-outlineColor: var(--borderColor-accent-emphasis); /** Outline color for focus states on interactive elements */
|
|
1660
1660
|
--header-fgColor-default: #ffffffb3;
|
|
1661
1661
|
--label-auburn-borderColor: var(--label-auburn-fgColor-rest);
|
|
1662
1662
|
--label-blue-borderColor: var(--label-blue-fgColor-rest);
|
|
@@ -1688,7 +1688,7 @@
|
|
|
1688
1688
|
--progressBar-bgColor-success: var(--bgColor-success-emphasis);
|
|
1689
1689
|
--reactionButton-selected-fgColor-rest: var(--fgColor-link);
|
|
1690
1690
|
--selectMenu-borderColor: var(--borderColor-default);
|
|
1691
|
-
--selection-bgColor: #194fb1b3;
|
|
1691
|
+
--selection-bgColor: #194fb1b3; /** Background color for text selection highlights */
|
|
1692
1692
|
--shadow-floating-legacy: 0px 6px 12px -3px #01040966, 0px 6px 18px 0px #01040966;
|
|
1693
1693
|
--shadow-inset: inset 0px 1px 0px 0px #0104093d;
|
|
1694
1694
|
--shadow-resting-medium: 0px 1px 1px 0px #01040966, 0px 3px 6px 0px #010409cc;
|
|
@@ -799,7 +799,7 @@
|
|
|
799
799
|
--fgColor-onInverse: #010409; /** Text color for use on inverse backgrounds */
|
|
800
800
|
--fgColor-upsell: var(--fgColor-done); /** Text color for upsell and promotional content */
|
|
801
801
|
--fgColor-white: #ffffff; /** Pure white text */
|
|
802
|
-
--focus-outlineColor: var(--borderColor-accent-emphasis);
|
|
802
|
+
--focus-outlineColor: var(--borderColor-accent-emphasis); /** Outline color for focus states on interactive elements */
|
|
803
803
|
--header-fgColor-default: #ffffffb3;
|
|
804
804
|
--overlay-bgColor: #010409;
|
|
805
805
|
--page-header-bgColor: var(--bgColor-default);
|
|
@@ -814,7 +814,7 @@
|
|
|
814
814
|
--progressBar-track-bgColor: var(--borderColor-default);
|
|
815
815
|
--reactionButton-selected-fgColor-rest: var(--fgColor-link);
|
|
816
816
|
--selectMenu-borderColor: var(--borderColor-default);
|
|
817
|
-
--selection-bgColor: #1f6febb3;
|
|
817
|
+
--selection-bgColor: #1f6febb3; /** Background color for text selection highlights */
|
|
818
818
|
--shadow-floating-legacy: 0px 6px 12px -3px #01040966, 0px 6px 18px 0px #01040966;
|
|
819
819
|
--shadow-inset: inset 0px 1px 0px 0px #0104093d;
|
|
820
820
|
--shadow-resting-medium: 0px 1px 1px 0px #01040966, 0px 3px 6px 0px #010409cc;
|
|
@@ -1696,7 +1696,7 @@
|
|
|
1696
1696
|
--fgColor-onInverse: #010409; /** Text color for use on inverse backgrounds */
|
|
1697
1697
|
--fgColor-upsell: var(--fgColor-done); /** Text color for upsell and promotional content */
|
|
1698
1698
|
--fgColor-white: #ffffff; /** Pure white text */
|
|
1699
|
-
--focus-outlineColor: var(--borderColor-accent-emphasis);
|
|
1699
|
+
--focus-outlineColor: var(--borderColor-accent-emphasis); /** Outline color for focus states on interactive elements */
|
|
1700
1700
|
--header-fgColor-default: #ffffffb3;
|
|
1701
1701
|
--overlay-bgColor: #010409;
|
|
1702
1702
|
--page-header-bgColor: var(--bgColor-default);
|
|
@@ -1711,7 +1711,7 @@
|
|
|
1711
1711
|
--progressBar-track-bgColor: var(--borderColor-default);
|
|
1712
1712
|
--reactionButton-selected-fgColor-rest: var(--fgColor-link);
|
|
1713
1713
|
--selectMenu-borderColor: var(--borderColor-default);
|
|
1714
|
-
--selection-bgColor: #1f6febb3;
|
|
1714
|
+
--selection-bgColor: #1f6febb3; /** Background color for text selection highlights */
|
|
1715
1715
|
--shadow-floating-legacy: 0px 6px 12px -3px #01040966, 0px 6px 18px 0px #01040966;
|
|
1716
1716
|
--shadow-inset: inset 0px 1px 0px 0px #0104093d;
|
|
1717
1717
|
--shadow-resting-medium: 0px 1px 1px 0px #01040966, 0px 3px 6px 0px #010409cc;
|
|
@@ -791,7 +791,7 @@
|
|
|
791
791
|
--fgColor-open: var(--fgColor-success); /** Text color for open state indicators (issues, PRs) */
|
|
792
792
|
--fgColor-upsell: var(--fgColor-done); /** Text color for upsell and promotional content */
|
|
793
793
|
--fgColor-white: #cdd9e5; /** Pure white text */
|
|
794
|
-
--focus-outlineColor: var(--borderColor-accent-emphasis);
|
|
794
|
+
--focus-outlineColor: var(--borderColor-accent-emphasis); /** Outline color for focus states on interactive elements */
|
|
795
795
|
--header-fgColor-default: #cdd9e5b3;
|
|
796
796
|
--label-auburn-borderColor: var(--label-auburn-fgColor-rest);
|
|
797
797
|
--label-blue-borderColor: var(--label-blue-fgColor-rest);
|
|
@@ -822,7 +822,7 @@
|
|
|
822
822
|
--progressBar-bgColor-sponsors: var(--bgColor-sponsors-emphasis);
|
|
823
823
|
--progressBar-bgColor-success: var(--bgColor-success-emphasis);
|
|
824
824
|
--selectMenu-borderColor: var(--borderColor-default);
|
|
825
|
-
--selection-bgColor: #1b4b91b3;
|
|
825
|
+
--selection-bgColor: #1b4b91b3; /** Background color for text selection highlights */
|
|
826
826
|
--shadow-floating-legacy: 0px 6px 12px -3px #01040966, 0px 6px 18px 0px #01040966;
|
|
827
827
|
--shadow-inset: inset 0px 1px 0px 0px #0104093d;
|
|
828
828
|
--shadow-resting-medium: 0px 1px 1px 0px #01040966, 0px 3px 6px 0px #010409cc;
|
|
@@ -1688,7 +1688,7 @@
|
|
|
1688
1688
|
--fgColor-open: var(--fgColor-success); /** Text color for open state indicators (issues, PRs) */
|
|
1689
1689
|
--fgColor-upsell: var(--fgColor-done); /** Text color for upsell and promotional content */
|
|
1690
1690
|
--fgColor-white: #cdd9e5; /** Pure white text */
|
|
1691
|
-
--focus-outlineColor: var(--borderColor-accent-emphasis);
|
|
1691
|
+
--focus-outlineColor: var(--borderColor-accent-emphasis); /** Outline color for focus states on interactive elements */
|
|
1692
1692
|
--header-fgColor-default: #cdd9e5b3;
|
|
1693
1693
|
--label-auburn-borderColor: var(--label-auburn-fgColor-rest);
|
|
1694
1694
|
--label-blue-borderColor: var(--label-blue-fgColor-rest);
|
|
@@ -1719,7 +1719,7 @@
|
|
|
1719
1719
|
--progressBar-bgColor-sponsors: var(--bgColor-sponsors-emphasis);
|
|
1720
1720
|
--progressBar-bgColor-success: var(--bgColor-success-emphasis);
|
|
1721
1721
|
--selectMenu-borderColor: var(--borderColor-default);
|
|
1722
|
-
--selection-bgColor: #1b4b91b3;
|
|
1722
|
+
--selection-bgColor: #1b4b91b3; /** Background color for text selection highlights */
|
|
1723
1723
|
--shadow-floating-legacy: 0px 6px 12px -3px #01040966, 0px 6px 18px 0px #01040966;
|
|
1724
1724
|
--shadow-inset: inset 0px 1px 0px 0px #0104093d;
|
|
1725
1725
|
--shadow-resting-medium: 0px 1px 1px 0px #01040966, 0px 3px 6px 0px #010409cc;
|