@baukit/ui-tokens 0.1.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/dist/eslint.js ADDED
@@ -0,0 +1,233 @@
1
+ import { findRawColor, isCssColorKeyword } from './color-literals.js';
2
+ const DEFAULT_ALLOWED_VALUES = ['transparent', 'currentColor', 'inherit', 'none'];
3
+ /**
4
+ * Property and attribute names whose values are styling input. Keyword matching
5
+ * is limited to these so that a route name or a test id is never reported.
6
+ */
7
+ const STYLE_PROPERTY_NAMES = new Set([
8
+ 'backgroundColor',
9
+ 'background',
10
+ 'borderColor',
11
+ 'borderBottomColor',
12
+ 'borderLeftColor',
13
+ 'borderRightColor',
14
+ 'borderTopColor',
15
+ 'borderStartColor',
16
+ 'borderEndColor',
17
+ 'color',
18
+ 'fill',
19
+ 'stroke',
20
+ 'shadowColor',
21
+ 'textShadowColor',
22
+ 'textDecorationColor',
23
+ 'tintColor',
24
+ 'placeholderTextColor',
25
+ 'selectionColor',
26
+ 'underlayColor',
27
+ 'outlineColor',
28
+ 'caretColor',
29
+ 'colors',
30
+ 'style',
31
+ 'styles',
32
+ 'theme',
33
+ 'palette',
34
+ 'gradient',
35
+ 'boxShadow',
36
+ 'textShadow',
37
+ 'borderTop',
38
+ 'borderBottom',
39
+ 'borderLeft',
40
+ 'borderRight',
41
+ 'border',
42
+ 'outline',
43
+ ]);
44
+ /** Tagged-template tags whose contents are CSS. */
45
+ const CSS_TEMPLATE_TAGS = new Set([
46
+ 'css',
47
+ 'styled',
48
+ 'createGlobalStyle',
49
+ 'keyframes',
50
+ 'injectGlobal',
51
+ ]);
52
+ function globToRegExp(pattern) {
53
+ let source = '';
54
+ for (let index = 0; index < pattern.length; index += 1) {
55
+ const character = pattern[index];
56
+ if (character === '*') {
57
+ if (pattern[index + 1] === '*') {
58
+ source += '.*';
59
+ index += 1;
60
+ }
61
+ else {
62
+ source += '[^/]*';
63
+ }
64
+ continue;
65
+ }
66
+ if (character === '?') {
67
+ source += '[^/]';
68
+ continue;
69
+ }
70
+ source += character?.replace(/[.+^${}()|[\]\\]/g, '\\$&') ?? '';
71
+ }
72
+ return new RegExp(`(?:^|/)(?:${source})$`);
73
+ }
74
+ function isAllowedFile(filename, patterns) {
75
+ const normalized = filename.replaceAll('\\', '/');
76
+ return patterns.some((pattern) => globToRegExp(pattern).test(normalized));
77
+ }
78
+ function propertyKeyName(node) {
79
+ const parent = node.parent;
80
+ if (parent === undefined || parent === null)
81
+ return undefined;
82
+ if (parent.type === 'Property' && parent.value === node) {
83
+ const key = parent.key;
84
+ if (key.type === 'Identifier')
85
+ return key.name;
86
+ if (key.type === 'Literal' && typeof key.value === 'string')
87
+ return key.value;
88
+ }
89
+ return undefined;
90
+ }
91
+ /**
92
+ * Walks up from a literal to decide whether it lands in a styling position: a
93
+ * style-named property or JSX attribute, a CSS tagged template, or a nested
94
+ * object or array under one of those.
95
+ */
96
+ function isStyleContext(node, styleNames) {
97
+ let current = node;
98
+ let child;
99
+ while (current !== undefined && current !== null) {
100
+ if (current.type === 'TaggedTemplateExpression') {
101
+ const tag = current.tag;
102
+ if (tag.type === 'Identifier' && CSS_TEMPLATE_TAGS.has(tag.name))
103
+ return true;
104
+ if (tag.type === 'MemberExpression' &&
105
+ tag.object.type === 'Identifier' &&
106
+ CSS_TEMPLATE_TAGS.has(tag.object.name)) {
107
+ return true;
108
+ }
109
+ }
110
+ if (current.type === 'Property' && child !== undefined && current.value === child) {
111
+ const name = propertyKeyName(child);
112
+ if (name !== undefined && styleNames.has(name))
113
+ return true;
114
+ }
115
+ const jsxName = jsxAttributeName(current);
116
+ if (jsxName !== undefined && styleNames.has(jsxName))
117
+ return true;
118
+ if (current.type === 'VariableDeclarator') {
119
+ const id = current.id;
120
+ if (id.type === 'Identifier' && looksLikeStyleName(id.name))
121
+ return true;
122
+ }
123
+ if (isStyleSheetCall(current))
124
+ return true;
125
+ child = current;
126
+ current = current.parent;
127
+ }
128
+ return false;
129
+ }
130
+ function jsxAttributeName(current) {
131
+ const candidate = current;
132
+ return candidate.type === 'JSXAttribute' ? candidate.name?.name : undefined;
133
+ }
134
+ function looksLikeStyleName(name) {
135
+ return /(^|[a-z])(style|styles|theme|palette|colors?)$/i.test(name);
136
+ }
137
+ function isStyleSheetCall(node) {
138
+ if (node.type !== 'CallExpression')
139
+ return false;
140
+ const callee = node.callee;
141
+ return (callee.type === 'MemberExpression' &&
142
+ callee.object.type === 'Identifier' &&
143
+ callee.object.name === 'StyleSheet' &&
144
+ callee.property.type === 'Identifier' &&
145
+ callee.property.name === 'create');
146
+ }
147
+ const MESSAGE_IDS = {
148
+ hex: 'rawHex',
149
+ function: 'rawFunction',
150
+ keyword: 'rawKeyword',
151
+ };
152
+ /**
153
+ * Reports CSS colors written directly in application code. Colors belong in the
154
+ * token definition, which the `allowedFiles` option exempts.
155
+ */
156
+ export const noRawColor = {
157
+ meta: {
158
+ type: 'problem',
159
+ docs: {
160
+ description: 'Disallow raw CSS colors outside the design-token definition',
161
+ },
162
+ schema: [
163
+ {
164
+ type: 'object',
165
+ properties: {
166
+ allowedFiles: { type: 'array', items: { type: 'string' } },
167
+ allowedValues: { type: 'array', items: { type: 'string' } },
168
+ additionalStyleProperties: { type: 'array', items: { type: 'string' } },
169
+ reportKeywords: { type: 'boolean' },
170
+ },
171
+ additionalProperties: false,
172
+ },
173
+ ],
174
+ messages: {
175
+ rawHex: 'Raw hex color "{{value}}". Use a design token instead.',
176
+ rawFunction: 'Raw {{value}}() color. Use a design token instead.',
177
+ rawKeyword: 'Raw CSS color keyword "{{value}}". Use a design token instead.',
178
+ },
179
+ },
180
+ create(context) {
181
+ const options = (context.options[0] ?? {});
182
+ const allowedFiles = options.allowedFiles ?? [];
183
+ const allowedValues = new Set([...DEFAULT_ALLOWED_VALUES, ...(options.allowedValues ?? [])].map((value) => value.toLowerCase()));
184
+ const styleNames = new Set([
185
+ ...STYLE_PROPERTY_NAMES,
186
+ ...(options.additionalStyleProperties ?? []),
187
+ ]);
188
+ const reportKeywords = options.reportKeywords ?? true;
189
+ if (isAllowedFile(context.filename, allowedFiles))
190
+ return {};
191
+ const check = (node, value) => {
192
+ if (allowedValues.has(value.trim().toLowerCase()))
193
+ return;
194
+ const styled = isStyleContext(node, styleNames);
195
+ const keywordsHere = reportKeywords && styled;
196
+ const match = findRawColor(value, keywordsHere);
197
+ if (match === undefined)
198
+ return;
199
+ if (match.kind === 'keyword' && !isCssColorKeyword(value) && !styled)
200
+ return;
201
+ context.report({
202
+ node,
203
+ messageId: MESSAGE_IDS[match.kind],
204
+ data: { value: match.text },
205
+ });
206
+ };
207
+ return {
208
+ Literal(node) {
209
+ if (typeof node.value === 'string')
210
+ check(node, node.value);
211
+ },
212
+ TemplateLiteral(node) {
213
+ const raw = node.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join(' ');
214
+ check(node, raw);
215
+ },
216
+ };
217
+ },
218
+ };
219
+ /** Rules exported by this plugin, keyed by rule name. */
220
+ export const rules = { 'no-raw-color': noRawColor };
221
+ const plugin = { rules };
222
+ /**
223
+ * Ready-made flat config. Spread it into a product's `eslint.config.js` and pass
224
+ * `allowedFiles` so the token definition may keep its color literals.
225
+ */
226
+ export const configs = {
227
+ recommended: {
228
+ plugins: { '@baukit/ui-tokens': plugin },
229
+ rules: { '@baukit/ui-tokens/no-raw-color': 'error' },
230
+ },
231
+ };
232
+ export default plugin;
233
+ //# sourceMappingURL=eslint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.js","sourceRoot":"","sources":["../src/eslint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /** A deliberately small fixture that demonstrates the pipeline, not a design system. */
2
+ export declare const exampleTokens: {
3
+ readonly color: {
4
+ readonly background: {
5
+ readonly primary: {
6
+ readonly light: "#ffffff";
7
+ readonly dark: "#111111";
8
+ };
9
+ readonly accent: {
10
+ readonly light: "#005fcc";
11
+ readonly dark: "#66aaff";
12
+ };
13
+ };
14
+ readonly text: {
15
+ readonly primary: {
16
+ readonly light: "#111111";
17
+ readonly dark: "#ffffff";
18
+ };
19
+ readonly onAccent: {
20
+ readonly light: "#ffffff";
21
+ readonly dark: "#111111";
22
+ };
23
+ };
24
+ };
25
+ readonly typography: {
26
+ readonly family: {
27
+ readonly body: "Inter, sans-serif";
28
+ };
29
+ readonly size: {
30
+ readonly body: "1rem";
31
+ readonly title: "2rem";
32
+ };
33
+ readonly weight: {
34
+ readonly regular: 400;
35
+ readonly bold: 700;
36
+ };
37
+ readonly lineHeight: {
38
+ readonly body: 1.5;
39
+ readonly title: 1.2;
40
+ };
41
+ };
42
+ readonly space: {
43
+ readonly small: 8;
44
+ readonly medium: 16;
45
+ };
46
+ readonly radius: {
47
+ readonly small: 4;
48
+ readonly pill: 999;
49
+ };
50
+ readonly motion: {
51
+ readonly duration: {
52
+ readonly fast: "120ms";
53
+ readonly normal: "240ms";
54
+ };
55
+ readonly easing: {
56
+ readonly standard: "cubic-bezier(0.2, 0, 0, 1)";
57
+ };
58
+ };
59
+ readonly elevation: {
60
+ readonly raised: "0 2px 8px rgb(0 0 0 / 0.2)";
61
+ };
62
+ readonly contrastPairs: readonly [{
63
+ readonly foreground: "color.text.primary";
64
+ readonly background: "color.background.primary";
65
+ }, {
66
+ readonly foreground: "color.text.onAccent";
67
+ readonly background: "color.background.accent";
68
+ }];
69
+ };
70
+ //# sourceMappingURL=example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.d.ts","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BO,CAAC"}
@@ -0,0 +1,31 @@
1
+ /** A deliberately small fixture that demonstrates the pipeline, not a design system. */
2
+ export const exampleTokens = {
3
+ color: {
4
+ background: {
5
+ primary: { light: '#ffffff', dark: '#111111' },
6
+ accent: { light: '#005fcc', dark: '#66aaff' },
7
+ },
8
+ text: {
9
+ primary: { light: '#111111', dark: '#ffffff' },
10
+ onAccent: { light: '#ffffff', dark: '#111111' },
11
+ },
12
+ },
13
+ typography: {
14
+ family: { body: 'Inter, sans-serif' },
15
+ size: { body: '1rem', title: '2rem' },
16
+ weight: { regular: 400, bold: 700 },
17
+ lineHeight: { body: 1.5, title: 1.2 },
18
+ },
19
+ space: { small: 8, medium: 16 },
20
+ radius: { small: 4, pill: 999 },
21
+ motion: {
22
+ duration: { fast: '120ms', normal: '240ms' },
23
+ easing: { standard: 'cubic-bezier(0.2, 0, 0, 1)' },
24
+ },
25
+ elevation: { raised: '0 2px 8px rgb(0 0 0 / 0.2)' },
26
+ contrastPairs: [
27
+ { foreground: 'color.text.primary', background: 'color.background.primary' },
28
+ { foreground: 'color.text.onAccent', background: 'color.background.accent' },
29
+ ],
30
+ };
31
+ //# sourceMappingURL=example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.js","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,KAAK,EAAE;QACL,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;YAC9C,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;SAC9C;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;YAC9C,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;SAChD;KACF;IACD,UAAU,EAAE;QACV,MAAM,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE;QACrC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;QACrC,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE;QACnC,UAAU,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;KACtC;IACD,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IAC/B,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE;IAC/B,MAAM,EAAE;QACN,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;QAC5C,MAAM,EAAE,EAAE,QAAQ,EAAE,4BAA4B,EAAE;KACnD;IACD,SAAS,EAAE,EAAE,MAAM,EAAE,4BAA4B,EAAE;IACnD,aAAa,EAAE;QACb,EAAE,UAAU,EAAE,oBAAoB,EAAE,UAAU,EAAE,0BAA0B,EAAE;QAC5E,EAAE,UAAU,EAAE,qBAAqB,EAAE,UAAU,EAAE,yBAAyB,EAAE;KAC7E;CAC8B,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from './compiler.js';
2
+ export * from './contrast.js';
3
+ export * from './example.js';
4
+ export * from './layout.js';
5
+ export * from './schema.js';
6
+ export * from './validation.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from './compiler.js';
2
+ export * from './contrast.js';
3
+ export * from './example.js';
4
+ export * from './layout.js';
5
+ export * from './schema.js';
6
+ export * from './validation.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Layout mode arithmetic over a product's own breakpoint numbers. The rules are
3
+ * shared; the numbers are not, so every function takes them as an argument.
4
+ */
5
+ export type LayoutMode = 'compact' | 'medium' | 'expanded';
6
+ export interface LayoutBreakpoints {
7
+ /** Width at or above which the layout is `medium`. */
8
+ readonly medium: number;
9
+ /** Width at or above which the layout is `expanded`. */
10
+ readonly expanded: number;
11
+ }
12
+ export type ScreenMaxWidths = Readonly<Record<string, number>>;
13
+ export interface ScreenMaxWidthOptions<Widths extends ScreenMaxWidths> {
14
+ readonly maxWidths: Widths;
15
+ /** Key used when a wide screen is requested below the `expanded` mode. */
16
+ readonly narrowFallback: keyof Widths;
17
+ /** Keys that only reach their full width in the `expanded` mode. */
18
+ readonly expandedOnly: readonly (keyof Widths)[];
19
+ }
20
+ /** Classifies a viewport width. Ties go to the wider mode. */
21
+ export declare function getLayoutMode(width: number, breakpoints: LayoutBreakpoints): LayoutMode;
22
+ /** Resolves a named content width, narrowing expanded-only keys below that mode. */
23
+ export declare function getScreenMaxWidth<Widths extends ScreenMaxWidths>(screen: keyof Widths, layoutMode: LayoutMode, { maxWidths, narrowFallback, expandedOnly }: ScreenMaxWidthOptions<Widths>): number;
24
+ /** Bottom padding that keeps content clear of a mobile tab bar and the safe area. */
25
+ export declare function getTabContentInset(layoutMode: LayoutMode, safeAreaBottom: number, tabBarHeight: number): number;
26
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE3D,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE/D,MAAM,WAAW,qBAAqB,CAAC,MAAM,SAAS,eAAe;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,MAAM,CAAC;IACtC,oEAAoE;IACpE,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,MAAM,MAAM,CAAC,EAAE,CAAC;CAClD;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,GAAG,UAAU,CAIvF;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,MAAM,SAAS,eAAe,EAC9D,MAAM,EAAE,MAAM,MAAM,EACpB,UAAU,EAAE,UAAU,EACtB,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,qBAAqB,CAAC,MAAM,CAAC,GACzE,MAAM,CAOR;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,GACnB,MAAM,CAGR"}
package/dist/layout.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Layout mode arithmetic over a product's own breakpoint numbers. The rules are
3
+ * shared; the numbers are not, so every function takes them as an argument.
4
+ */
5
+ /** Classifies a viewport width. Ties go to the wider mode. */
6
+ export function getLayoutMode(width, breakpoints) {
7
+ if (width >= breakpoints.expanded)
8
+ return 'expanded';
9
+ if (width >= breakpoints.medium)
10
+ return 'medium';
11
+ return 'compact';
12
+ }
13
+ /** Resolves a named content width, narrowing expanded-only keys below that mode. */
14
+ export function getScreenMaxWidth(screen, layoutMode, { maxWidths, narrowFallback, expandedOnly }) {
15
+ const key = layoutMode !== 'expanded' && expandedOnly.includes(screen) ? narrowFallback : screen;
16
+ const width = maxWidths[key];
17
+ if (width === undefined) {
18
+ throw new Error(`unknown screen max width: ${String(key)}`);
19
+ }
20
+ return width;
21
+ }
22
+ /** Bottom padding that keeps content clear of a mobile tab bar and the safe area. */
23
+ export function getTabContentInset(layoutMode, safeAreaBottom, tabBarHeight) {
24
+ if (layoutMode === 'expanded')
25
+ return 0;
26
+ return tabBarHeight + Math.max(0, safeAreaBottom);
27
+ }
28
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqBH,8DAA8D;AAC9D,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,WAA8B;IACzE,IAAI,KAAK,IAAI,WAAW,CAAC,QAAQ;QAAE,OAAO,UAAU,CAAC;IACrD,IAAI,KAAK,IAAI,WAAW,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IACjD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,iBAAiB,CAC/B,MAAoB,EACpB,UAAsB,EACtB,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAiC;IAE1E,MAAM,GAAG,GAAG,UAAU,KAAK,UAAU,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC;IACjG,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,6BAA6B,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,kBAAkB,CAChC,UAAsB,EACtB,cAAsB,EACtB,YAAoB;IAEpB,IAAI,UAAU,KAAK,UAAU;QAAE,OAAO,CAAC,CAAC;IACxC,OAAO,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,40 @@
1
+ export interface ThemeColor {
2
+ /** A three- or six-digit hexadecimal sRGB color. */
3
+ readonly light: string;
4
+ /** A three- or six-digit hexadecimal sRGB color. */
5
+ readonly dark: string;
6
+ }
7
+ export interface ColorTokenGroup {
8
+ readonly [name: string]: ColorTokenGroup | ThemeColor;
9
+ }
10
+ export type TokenScale<T> = Readonly<Record<string, T>>;
11
+ export type DimensionValue = number | string;
12
+ export interface TypographyTokens {
13
+ readonly family: TokenScale<string>;
14
+ readonly size: TokenScale<DimensionValue>;
15
+ readonly weight: TokenScale<number>;
16
+ readonly lineHeight: TokenScale<DimensionValue>;
17
+ }
18
+ export interface MotionTokens {
19
+ readonly duration: TokenScale<DimensionValue>;
20
+ readonly easing: TokenScale<string>;
21
+ }
22
+ export interface ContrastPair {
23
+ /** A complete semantic path such as `color.text.primary`. */
24
+ readonly foreground: string;
25
+ /** A complete semantic path such as `color.background.primary`. */
26
+ readonly background: string;
27
+ /** Large text uses WCAG's 3:1 threshold instead of 4.5:1. */
28
+ readonly largeText?: boolean;
29
+ }
30
+ /** Cross-platform token source. It intentionally contains no component definitions. */
31
+ export interface DesignTokens {
32
+ readonly color: ColorTokenGroup;
33
+ readonly typography: TypographyTokens;
34
+ readonly space: TokenScale<DimensionValue>;
35
+ readonly radius: TokenScale<DimensionValue>;
36
+ readonly motion: MotionTokens;
37
+ readonly elevation: TokenScale<DimensionValue>;
38
+ readonly contrastPairs: readonly ContrastPair[];
39
+ }
40
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,UAAU,CAAC;CACvD;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,uFAAuF;AACvF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAC/C,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;CACjD"}
package/dist/schema.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { DesignTokens } from './schema.js';
2
+ export interface ValidationIssue {
3
+ readonly path: string;
4
+ readonly message: string;
5
+ }
6
+ /** Returns every structural problem with a path rooted at `$`. */
7
+ export declare function validateTokens(input: unknown): ValidationIssue[];
8
+ export declare class TokenValidationError extends Error {
9
+ readonly issues: readonly ValidationIssue[];
10
+ constructor(issues: readonly ValidationIssue[]);
11
+ }
12
+ /** Validates unknown input and returns it with the design-token type. */
13
+ export declare function parseTokens(input: unknown): DesignTokens;
14
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AA+LD,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,EAAE,CAoBhE;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAgB,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;gBAEhC,MAAM,EAAE,SAAS,eAAe,EAAE;CAKtD;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAMxD"}