@designid/tokens 0.4.6 → 1.0.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.
@@ -0,0 +1,1083 @@
1
+ /**
2
+ * W3C Design Tokens Format Module - TypeScript Types
3
+ * Based on the Design Tokens Community Group Draft (September 2025)
4
+ * https://deploy-preview-298--designtokensorg.netlify.app/tr/drafts/format/
5
+ *
6
+ * This file provides complete TypeScript type definitions for the W3C Design Tokens specification,
7
+ * including all basic types, composite types, references, aliases, and group structures.
8
+ */
9
+
10
+ // ============================================================================
11
+ // CORE DESIGN TOKEN INTERFACES
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Base properties available on all design tokens
16
+ */
17
+ export interface DesignTokenBase {
18
+ /** The token's type - required if not inherited from parent groups */
19
+ $type?: string;
20
+
21
+ /** Human-readable description of the token's purpose */
22
+ $description?: string;
23
+
24
+ /** Enhanced vendor-specific extensions with mode and generators support */
25
+ $extensions?: EnhancedExtensionData;
26
+
27
+ /** Deprecation status and optional explanation */
28
+ $deprecated?: boolean | string;
29
+ }
30
+
31
+ /**
32
+ * A design token with an explicit value
33
+ */
34
+ export interface DesignToken<T = unknown> extends DesignTokenBase {
35
+ /** The token's value */
36
+ $value: T;
37
+ }
38
+
39
+ /**
40
+ * Reference to another token using curly brace syntax
41
+ */
42
+ export type TokenReference = `{${string}}`;
43
+
44
+ /**
45
+ * JSON Pointer reference using $ref property
46
+ */
47
+ export interface JsonPointerReference {
48
+ $ref: string;
49
+ }
50
+
51
+ /**
52
+ * Composite string value that can contain multiple references and literal values
53
+ * Examples:
54
+ * - "{a.b.c}, 16px" (token reference + literal)
55
+ * - "{a.b} {a.c}" (multiple token references)
56
+ * - "16px {#/ref}" (literal + JSON pointer)
57
+ * - "{token.ref} solid {#/colors/primary}" (mixed reference types)
58
+ */
59
+ export type CompositeStringValue = string & {
60
+ readonly __brand: 'CompositeStringValue';
61
+ };
62
+
63
+ /**
64
+ * Union type for values that can be explicit, references, or composite strings
65
+ */
66
+ export type ValueOrReference<T> = T | TokenReference | JsonPointerReference | CompositeStringValue;
67
+
68
+ // ============================================================================
69
+ // BASIC TYPES
70
+ // ============================================================================
71
+
72
+ /**
73
+ * Color value in sRGB color space
74
+ * @see https://deploy-preview-298--designtokensorg.netlify.app/tr/drafts/color
75
+ */
76
+ export interface ColorValue {
77
+ /** Color space identifier */
78
+ colorSpace: 'srgb';
79
+ /** RGB components as numbers between 0 and 1 */
80
+ components: [number, number, number];
81
+ /** Optional alpha channel (0-1) */
82
+ alpha?: number;
83
+ /** Hex representation (optional, for convenience) */
84
+ hex?: string;
85
+ }
86
+
87
+ /**
88
+ * Extended color value supporting additional color spaces and string formats
89
+ * Supports OKLCH, CSS color functions, and hex strings commonly used in design systems
90
+ */
91
+ export type ExtendedColorValue =
92
+ | ColorValue
93
+ | string; // OKLCH string like "oklch(100% 0 236.74)" or hex like "#ff0000"
94
+
95
+ /**
96
+ * Color design token with extended color space support
97
+ */
98
+ export interface ColorToken extends DesignToken<ValueOrReference<ExtendedColorValue>> {
99
+ $type: 'color';
100
+ }
101
+
102
+ /**
103
+ * Dimension value with numeric value and unit
104
+ */
105
+ export interface DimensionValue {
106
+ /** Numeric value (integer or floating-point) */
107
+ value: number;
108
+ /** Unit of measurement */
109
+ unit: 'px' | 'rem';
110
+ }
111
+
112
+ /**
113
+ * Dimension design token
114
+ */
115
+ export interface DimensionToken extends DesignToken<ValueOrReference<DimensionValue>> {
116
+ $type: 'dimension';
117
+ }
118
+
119
+ /**
120
+ * Font family value - string or array of strings
121
+ */
122
+ export type FontFamilyValue = string | string[];
123
+
124
+ /**
125
+ * Font family design token
126
+ */
127
+ export interface FontFamilyToken extends DesignToken<ValueOrReference<FontFamilyValue>> {
128
+ $type: 'fontFamily';
129
+ }
130
+
131
+ /**
132
+ * Font weight numeric values
133
+ */
134
+ export type FontWeightNumeric = number; // Range [1, 1000]
135
+
136
+ /**
137
+ * Font weight string aliases
138
+ */
139
+ export type FontWeightString =
140
+ | 'thin' | 'hairline' // 100
141
+ | 'extra-light' | 'ultra-light' // 200
142
+ | 'light' // 300
143
+ | 'normal' | 'regular' | 'book' // 400
144
+ | 'medium' // 500
145
+ | 'semi-bold' | 'demi-bold' // 600
146
+ | 'bold' // 700
147
+ | 'extra-bold' | 'ultra-bold' // 800
148
+ | 'black' | 'heavy' // 900
149
+ | 'extra-black' | 'ultra-black'; // 950
150
+
151
+ /**
152
+ * Font weight value
153
+ */
154
+ export type FontWeightValue = FontWeightNumeric | FontWeightString;
155
+
156
+ /**
157
+ * Font weight design token
158
+ */
159
+ export interface FontWeightToken extends DesignToken<ValueOrReference<FontWeightValue>> {
160
+ $type: 'fontWeight';
161
+ }
162
+
163
+ /**
164
+ * Font face style values (CSS font-style property)
165
+ */
166
+ export type FontFaceStyleValue = 'normal' | 'italic' | 'oblique';
167
+
168
+ /**
169
+ * Font face format values
170
+ */
171
+ export type FontFaceFormatValue = 'woff2' | 'woff' | 'ttf' | 'otf' | 'eot' | 'svg';
172
+
173
+ /**
174
+ * Base font face properties
175
+ */
176
+ interface BaseFontFace {
177
+ /** Font family name */
178
+ family: string;
179
+ /** Font style description */
180
+ style: string;
181
+ /** CSS font-style property value */
182
+ faceStyle: FontFaceStyleValue;
183
+ /** Font weight numeric value */
184
+ weight: FontWeightNumeric;
185
+ /** Font file format */
186
+ format: FontFaceFormatValue;
187
+ }
188
+
189
+ /**
190
+ * Font face value with conditional directory field
191
+ * - If src is a URL (starts with http:// or https://), directory is optional
192
+ * - If src is a file path, directory is required
193
+ */
194
+ export type FontFaceValue = BaseFontFace & (
195
+ | {
196
+ /** HTTP or HTTPS URL to font file */
197
+ src: `http://${string}` | `https://${string}`;
198
+ /** Directory is optional for URLs */
199
+ directory?: string;
200
+ }
201
+ | {
202
+ /** File path or filename */
203
+ src: string;
204
+ /** Directory is required for file paths */
205
+ directory: string;
206
+ }
207
+ );
208
+
209
+ /**
210
+ * Font face design token for web font definitions
211
+ */
212
+ export interface FontFaceToken extends DesignToken<ValueOrReference<FontFaceValue>> {
213
+ $type: 'fontFace';
214
+ }
215
+
216
+ /**
217
+ * Font face collection value - array of font face definitions
218
+ */
219
+ export type FontFaceCollectionValue = FontFaceValue[];
220
+
221
+ /**
222
+ * Font face collection design token for multiple web font definitions
223
+ */
224
+ export interface FontFaceCollectionToken extends DesignToken<ValueOrReference<FontFaceCollectionValue>> {
225
+ $type: 'fontFaceCollection';
226
+ }
227
+
228
+ /**
229
+ * Duration value with numeric value and unit
230
+ */
231
+ export interface DurationValue {
232
+ /** Numeric value (integer or floating-point) */
233
+ value: number;
234
+ /** Unit of time */
235
+ unit: 'ms' | 's';
236
+ }
237
+
238
+ /**
239
+ * Duration design token
240
+ */
241
+ export interface DurationToken extends DesignToken<ValueOrReference<DurationValue>> {
242
+ $type: 'duration';
243
+ }
244
+
245
+ /**
246
+ * Cubic Bézier value as array of four control points
247
+ */
248
+ export type CubicBezierValue = [number, number, number, number];
249
+
250
+ /**
251
+ * Cubic Bézier design token
252
+ */
253
+ export interface CubicBezierToken extends DesignToken<ValueOrReference<CubicBezierValue>> {
254
+ $type: 'cubicBezier';
255
+ }
256
+
257
+ /**
258
+ * Number value
259
+ */
260
+ export type NumberValue = number;
261
+
262
+ /**
263
+ * Number design token
264
+ */
265
+ export interface NumberToken extends DesignToken<ValueOrReference<NumberValue>> {
266
+ $type: 'number';
267
+ }
268
+
269
+ /**
270
+ * String value that can be literal or composite with references
271
+ */
272
+ export type StringValue = string;
273
+
274
+ /**
275
+ * String design token - supports literal strings and composite strings with references
276
+ * @example
277
+ * // Literal string
278
+ * { $type: 'string', $value: 'bold' }
279
+ *
280
+ * // Composite string with token reference
281
+ * { $type: 'string', $value: '{font.weight.bold}, 16px' }
282
+ *
283
+ * // Composite string with multiple token references
284
+ * { $type: 'string', $value: '{font.weight} {font.size}px' }
285
+ *
286
+ * // Composite string with JSON pointer
287
+ * { $type: 'string', $value: '16px {#/colors/primary}' }
288
+ *
289
+ * // Mixed reference types in one string
290
+ * { $type: 'string', $value: '{font.weight} solid {#/colors/border}' }
291
+ */
292
+ export interface StringToken extends DesignToken<ValueOrReference<StringValue>> {
293
+ $type: 'string';
294
+ }
295
+
296
+ // ============================================================================
297
+ // COMPOSITE TYPES
298
+ // ============================================================================
299
+
300
+ /**
301
+ * Stroke style string values
302
+ */
303
+ export type StrokeStyleString =
304
+ | 'solid'
305
+ | 'dashed'
306
+ | 'dotted'
307
+ | 'double'
308
+ | 'groove'
309
+ | 'ridge'
310
+ | 'outset'
311
+ | 'inset';
312
+
313
+ /**
314
+ * Line cap values for stroke style
315
+ */
316
+ export type LineCap = 'round' | 'butt' | 'square';
317
+
318
+ /**
319
+ * Stroke style object value
320
+ */
321
+ export interface StrokeStyleObject {
322
+ /** Array of dash lengths alternating between dashes and gaps */
323
+ dashArray: ValueOrReference<DimensionValue>[];
324
+ /** Line cap style */
325
+ lineCap: LineCap;
326
+ }
327
+
328
+ /**
329
+ * Stroke style value - string or object
330
+ */
331
+ export type StrokeStyleValue = StrokeStyleString | StrokeStyleObject;
332
+
333
+ /**
334
+ * Stroke style design token
335
+ */
336
+ export interface StrokeStyleToken extends DesignToken<ValueOrReference<StrokeStyleValue>> {
337
+ $type: 'strokeStyle';
338
+ }
339
+
340
+ /**
341
+ * Border value object
342
+ */
343
+ export interface BorderValue {
344
+ /** Border color */
345
+ color: ValueOrReference<ExtendedColorValue>;
346
+ /** Border width */
347
+ width: ValueOrReference<DimensionValue>;
348
+ /** Border style */
349
+ style: ValueOrReference<StrokeStyleValue>;
350
+ }
351
+
352
+ /**
353
+ * Border design token
354
+ */
355
+ export interface BorderToken extends DesignToken<ValueOrReference<BorderValue>> {
356
+ $type: 'border';
357
+ }
358
+
359
+ /**
360
+ * Transition value object
361
+ */
362
+ export interface TransitionValue {
363
+ /** Duration of the transition */
364
+ duration: ValueOrReference<DurationValue>;
365
+ /** Delay before transition begins */
366
+ delay: ValueOrReference<DurationValue>;
367
+ /** Timing function for the transition */
368
+ timingFunction: ValueOrReference<CubicBezierValue>;
369
+ }
370
+
371
+ /**
372
+ * Transition design token
373
+ */
374
+ export interface TransitionToken extends DesignToken<ValueOrReference<TransitionValue>> {
375
+ $type: 'transition';
376
+ }
377
+
378
+ /**
379
+ * Shadow value object
380
+ */
381
+ export interface ShadowValue {
382
+ /** Shadow color */
383
+ color: ValueOrReference<ExtendedColorValue>;
384
+ /** Horizontal offset */
385
+ offsetX: ValueOrReference<DimensionValue>;
386
+ /** Vertical offset */
387
+ offsetY: ValueOrReference<DimensionValue>;
388
+ /** Blur radius */
389
+ blur: ValueOrReference<DimensionValue>;
390
+ /** Spread radius */
391
+ spread: ValueOrReference<DimensionValue>;
392
+ /** Whether this is an inner shadow */
393
+ inset?: boolean;
394
+ }
395
+
396
+ /**
397
+ * Shadow design token - supports single shadow or array of shadows
398
+ */
399
+ export interface ShadowToken extends DesignToken<ValueOrReference<ShadowValue | ShadowValue[]>> {
400
+ $type: 'shadow';
401
+ }
402
+
403
+ /**
404
+ * Gradient stop object
405
+ */
406
+ export interface GradientStop {
407
+ /** Color at this stop */
408
+ color: ValueOrReference<ExtendedColorValue>;
409
+ /** Position along gradient axis (0-1) */
410
+ position: ValueOrReference<NumberValue>;
411
+ }
412
+
413
+ /**
414
+ * Gradient value as array of stops
415
+ */
416
+ export type GradientValue = GradientStop[];
417
+
418
+ /**
419
+ * Gradient design token
420
+ */
421
+ export interface GradientToken extends DesignToken<ValueOrReference<GradientValue>> {
422
+ $type: 'gradient';
423
+ }
424
+
425
+ /**
426
+ * Typography value object
427
+ */
428
+ export interface TypographyValue {
429
+ /** Font family */
430
+ fontFamily: ValueOrReference<FontFamilyValue>;
431
+ /** Font size */
432
+ fontSize: ValueOrReference<DimensionValue>;
433
+ /** Font weight */
434
+ fontWeight: ValueOrReference<FontWeightValue>;
435
+ /** Letter spacing */
436
+ letterSpacing: ValueOrReference<DimensionValue>;
437
+ /** Line height as multiplier */
438
+ lineHeight: ValueOrReference<NumberValue>;
439
+ }
440
+
441
+ /**
442
+ * Typography design token
443
+ */
444
+ export interface TypographyToken extends DesignToken<ValueOrReference<TypographyValue>> {
445
+ $type: 'typography';
446
+ }
447
+
448
+ // ============================================================================
449
+ // TOKEN UNION TYPES
450
+ // ============================================================================
451
+
452
+ /**
453
+ * Union of all basic token types
454
+ */
455
+ export type BasicTokenType =
456
+ | ColorToken
457
+ | DimensionToken
458
+ | FontFamilyToken
459
+ | FontWeightToken
460
+ | FontFaceToken
461
+ | FontFaceCollectionToken
462
+ | DurationToken
463
+ | CubicBezierToken
464
+ | NumberToken
465
+ | StringToken;
466
+
467
+ /**
468
+ * Union of all composite token types
469
+ */
470
+ export type CompositeTokenType =
471
+ | StrokeStyleToken
472
+ | BorderToken
473
+ | TransitionToken
474
+ | ShadowToken
475
+ | GradientToken
476
+ | TypographyToken;
477
+
478
+ /**
479
+ * Token type string literals
480
+ */
481
+ export type TokenType =
482
+ | 'color'
483
+ | 'dimension'
484
+ | 'fontFamily'
485
+ | 'fontWeight'
486
+ | 'fontFace'
487
+ | 'fontFaceCollection'
488
+ | 'duration'
489
+ | 'cubicBezier'
490
+ | 'number'
491
+ | 'string'
492
+ | 'strokeStyle'
493
+ | 'border'
494
+ | 'transition'
495
+ | 'shadow'
496
+ | 'gradient'
497
+ | 'typography'
498
+ | 'composition';
499
+
500
+ /**
501
+ * Union of all token types
502
+ */
503
+ export type AnyToken = BasicTokenType | CompositeTokenType;
504
+
505
+ // ============================================================================
506
+ // GROUP DEFINITIONS
507
+ // ============================================================================
508
+
509
+ /**
510
+ * Base properties available on groups
511
+ */
512
+ export interface GroupBase {
513
+ /** Group type for type inheritance */
514
+ $type?: TokenType;
515
+
516
+ /** Group description */
517
+ $description?: string;
518
+
519
+ /** Group extension reference */
520
+ $extends?: TokenReference | JsonPointerReference;
521
+
522
+ /** Group deprecation status */
523
+ $deprecated?: boolean | string;
524
+
525
+ /** Enhanced vendor-specific extensions with mode and generators support */
526
+ $extensions?: EnhancedExtensionData;
527
+ }
528
+
529
+ /**
530
+ * Root token within a group using reserved $root name
531
+ * Can be any token type, identified by the $root key in groups
532
+ */
533
+ export type RootToken = AnyToken;
534
+
535
+ /**
536
+ * Group containing tokens and nested groups
537
+ */
538
+ export interface TokenGroup extends GroupBase {
539
+ /** Root token for the group */
540
+ $root?: RootToken;
541
+
542
+ /** Nested tokens and groups */
543
+ [key: string]: AnyToken | TokenGroup | unknown;
544
+ }
545
+
546
+ // ============================================================================
547
+ // FILE FORMAT DEFINITIONS
548
+ // ============================================================================
549
+
550
+ /**
551
+ * Design tokens file structure
552
+ */
553
+ export interface DesignTokensFile extends GroupBase {
554
+ /** Tokens and groups at the root level */
555
+ [tokenOrGroupName: string]: AnyToken | TokenGroup | unknown;
556
+ }
557
+
558
+ /**
559
+ * Media type for design token files
560
+ */
561
+ export const DESIGN_TOKENS_MEDIA_TYPE = 'application/design-tokens+json';
562
+
563
+ /**
564
+ * Recommended file extensions
565
+ */
566
+ export const DESIGN_TOKENS_EXTENSIONS = ['.tokens', '.tokens.json'] as const;
567
+
568
+ // ============================================================================
569
+ // UTILITY TYPES
570
+ // ============================================================================
571
+
572
+ /**
573
+ * Extract the value type from a token
574
+ */
575
+ export type ExtractTokenValue<T> = T extends DesignToken<infer V> ? V : never;
576
+
577
+ /**
578
+ * Check if a value is a token reference
579
+ */
580
+ export type IsTokenReference<T> = T extends TokenReference ? true : false;
581
+
582
+ /**
583
+ * Check if a value is a JSON Pointer reference
584
+ */
585
+ export type IsJsonPointerReference<T> = T extends JsonPointerReference ? true : false;
586
+
587
+ /**
588
+ * Resolve a value or reference to its actual type
589
+ */
590
+ export type ResolveValue<T> = T extends ValueOrReference<infer V> ? V : T;
591
+
592
+ /**
593
+ * Type guard for token references
594
+ */
595
+ export function isTokenReference(value: unknown): value is TokenReference {
596
+ if (typeof value !== 'string' || !value.startsWith('{') || !value.endsWith('}')) {
597
+ return false;
598
+ }
599
+
600
+ // Exclude composite strings (contain multiple references or non-reference text)
601
+ // A single token reference should only contain one set of braces
602
+ const innerContent = value.slice(1, -1);
603
+ return !innerContent.includes('{') && !innerContent.includes('}') && innerContent.trim() !== '';
604
+ }
605
+
606
+ /**
607
+ * Type guard for JSON Pointer references
608
+ */
609
+ export function isJsonPointerReference(value: unknown): value is JsonPointerReference {
610
+ return typeof value === 'object' && value !== null && '$ref' in value;
611
+ }
612
+
613
+ /**
614
+ * Type guard for composite string values
615
+ */
616
+ export function isCompositeStringValue(value: unknown): value is CompositeStringValue {
617
+ if (typeof value !== 'string') return false;
618
+
619
+ // Check for token references {a.b.c} or JSON pointer references {#/path}
620
+ const tokenRefPattern = /\{[^}]+\}/g;
621
+ const matches = value.match(tokenRefPattern);
622
+
623
+ // Must contain at least one reference and have additional content
624
+ return !!(matches && matches.length > 0 && value.length > matches.join('').length);
625
+ }
626
+
627
+ /**
628
+ * Extract all references from a composite string value
629
+ */
630
+ export function extractReferencesFromCompositeString(value: CompositeStringValue): (TokenReference | JsonPointerReference)[] {
631
+ const tokenRefPattern = /\{[^}]+\}/g;
632
+ const matches = value.match(tokenRefPattern) || [];
633
+
634
+ return matches.map(match => {
635
+ if (match.startsWith('{#/')) {
636
+ // JSON Pointer reference
637
+ return { $ref: match.slice(2, -1) } as JsonPointerReference;
638
+ } else {
639
+ // Token reference
640
+ return match as TokenReference;
641
+ }
642
+ });
643
+ }
644
+
645
+ /**
646
+ * Parse a composite string into parts (references and literals)
647
+ */
648
+ export function parseCompositeString(value: CompositeStringValue): Array<{ type: 'reference' | 'literal'; value: string; ref?: TokenReference | JsonPointerReference }> {
649
+ const parts: Array<{ type: 'reference' | 'literal'; value: string; ref?: TokenReference | JsonPointerReference }> = [];
650
+ const tokenRefPattern = /\{[^}]+\}/g;
651
+ let lastIndex = 0;
652
+ let match;
653
+
654
+ while ((match = tokenRefPattern.exec(value)) !== null) {
655
+ // Add literal part before the reference
656
+ if (match.index > lastIndex) {
657
+ const literalValue = value.slice(lastIndex, match.index);
658
+ if (literalValue) {
659
+ parts.push({ type: 'literal', value: literalValue });
660
+ }
661
+ }
662
+
663
+ // Add the reference part
664
+ const refValue = match[0];
665
+ if (refValue.startsWith('{#/')) {
666
+ // JSON Pointer reference - ref contains the JsonPointerReference object
667
+ parts.push({
668
+ type: 'reference',
669
+ value: refValue,
670
+ ref: { $ref: refValue.slice(2, -1) } as JsonPointerReference
671
+ });
672
+ } else {
673
+ // Token reference - ref contains the TokenReference (same as value for token refs)
674
+ parts.push({
675
+ type: 'reference',
676
+ value: refValue,
677
+ ref: refValue as TokenReference
678
+ });
679
+ }
680
+
681
+ lastIndex = match.index + match[0].length;
682
+ }
683
+
684
+ // Add any remaining literal part
685
+ if (lastIndex < value.length) {
686
+ const literalValue = value.slice(lastIndex);
687
+ if (literalValue) {
688
+ parts.push({ type: 'literal', value: literalValue });
689
+ }
690
+ }
691
+
692
+ return parts;
693
+ }
694
+
695
+ /**
696
+ * Type guard for mode extensions
697
+ */
698
+ export function hasModeExtension(token: AnyToken): token is AnyToken & { $extensions: { $mode: ModeExtension } } {
699
+ return !!(token.$extensions?.$mode);
700
+ }
701
+
702
+ /**
703
+ * Type guard for generator extensions
704
+ */
705
+ export function hasGeneratorExtension(token: AnyToken): token is AnyToken & { $extensions: { $generators: GeneratorsExtension } } {
706
+ return !!(token.$extensions?.$generators && Array.isArray(token.$extensions.$generators));
707
+ }
708
+
709
+ /**
710
+ * Type guard for breakpoint extensions
711
+ */
712
+ export function hasBreakpointExtension(token: AnyToken): token is AnyToken & { $extensions: { $breakpoints: BreakpointsExtension } } {
713
+ return !!(token.$extensions?.$breakpoints && typeof token.$extensions.$breakpoints === 'object');
714
+ }
715
+
716
+ /**
717
+ * Extract mode value for a specific mode
718
+ */
719
+ export function getModeValue<T>(token: AnyToken, mode: keyof ModeExtension): ValueOrReference<T> | undefined {
720
+ if (!hasModeExtension(token)) return undefined;
721
+ return token.$extensions.$mode[mode] as ValueOrReference<T> | undefined;
722
+ }
723
+
724
+ /**
725
+ * Get all generator suffixes for a token
726
+ */
727
+ export function getGeneratorSuffixes(token: AnyToken): string[] {
728
+ if (!hasGeneratorExtension(token)) return [];
729
+
730
+ return token.$extensions.$generators.flatMap(generator =>
731
+ Object.keys(generator.value)
732
+ );
733
+ }
734
+
735
+ /**
736
+ * Get all breakpoint media queries for a token
737
+ */
738
+ export function getBreakpointQueries(token: AnyToken): string[] {
739
+ if (!hasBreakpointExtension(token)) return [];
740
+
741
+ return Object.keys(token.$extensions.$breakpoints);
742
+ }
743
+
744
+ /**
745
+ * Get breakpoint value for a specific media query
746
+ */
747
+ export function getBreakpointValue<T>(token: AnyToken, mediaQuery: string): ValueOrReference<T> | undefined {
748
+ if (!hasBreakpointExtension(token)) return undefined;
749
+
750
+ const breakpointConfig = token.$extensions.$breakpoints[mediaQuery];
751
+ return breakpointConfig?.$value as ValueOrReference<T> | undefined;
752
+ }
753
+
754
+ /**
755
+ * Get breakpoint configuration for a specific media query
756
+ */
757
+ export function getBreakpointConfig(token: AnyToken, mediaQuery: string) {
758
+ if (!hasBreakpointExtension(token)) return undefined;
759
+
760
+ return token.$extensions.$breakpoints[mediaQuery];
761
+ }
762
+
763
+ /**
764
+ * Extract token references from media query strings
765
+ */
766
+ export function extractTokenReferencesFromMediaQuery(mediaQuery: string): (TokenReference | JsonPointerReference)[] {
767
+ // Treat media query as a composite string to extract references
768
+ const compositeValue = mediaQuery as CompositeStringValue;
769
+ return extractReferencesFromCompositeString(compositeValue);
770
+ }
771
+
772
+ /**
773
+ * Generate derived token name with suffix
774
+ * @example generateDerivedTokenName("gray.n0", "@alpha1") => "gray.n0@alpha1"
775
+ */
776
+ export function generateDerivedTokenName(baseName: string, suffix: string): string {
777
+ return `${baseName}${suffix}`;
778
+ }
779
+
780
+ /**
781
+ * Type guard for design tokens
782
+ */
783
+ export function isDesignToken(value: unknown): value is AnyToken {
784
+ return typeof value === 'object' && value !== null && '$value' in value;
785
+ }
786
+
787
+ /**
788
+ * Type guard for groups
789
+ */
790
+ export function isTokenGroup(value: unknown): value is TokenGroup {
791
+ return typeof value === 'object' && value !== null && !('$value' in value);
792
+ }
793
+
794
+ // ============================================================================
795
+ // VALIDATION TYPES
796
+ // ============================================================================
797
+
798
+ /**
799
+ * Validation error for design tokens
800
+ */
801
+ export interface ValidationError {
802
+ /** Path to the invalid token or property */
803
+ path: string;
804
+ /** Error message */
805
+ message: string;
806
+ /** Error code for programmatic handling */
807
+ code: string;
808
+ /** Severity level */
809
+ severity: 'error' | 'warning';
810
+ }
811
+
812
+ /**
813
+ * Validation result for design token files
814
+ */
815
+ export interface ValidationResult {
816
+ /** Whether the file is valid */
817
+ valid: boolean;
818
+ /** List of validation errors and warnings */
819
+ errors: ValidationError[];
820
+ /** Successfully parsed tokens */
821
+ tokens: Record<string, AnyToken>;
822
+ /** Successfully parsed groups */
823
+ groups: Record<string, TokenGroup>;
824
+ }
825
+
826
+ /**
827
+ * Character restrictions for token and group names
828
+ * Names MUST NOT:
829
+ * - Begin with '$' (reserved for spec properties)
830
+ * - Contain '{', '}', or '.' (conflicts with reference syntax)
831
+ */
832
+ export type ValidTokenName = string & {
833
+ readonly __brand: 'ValidTokenName';
834
+ };
835
+
836
+ /**
837
+ * Path to a token within a group structure
838
+ */
839
+ export type TokenPath = string & {
840
+ readonly __brand: 'TokenPath';
841
+ };
842
+
843
+ // ============================================================================
844
+ // REFERENCE RESOLUTION TYPES
845
+ // ============================================================================
846
+
847
+ /**
848
+ * Reference resolution context
849
+ */
850
+ export interface ResolutionContext {
851
+ /** The current file being processed */
852
+ file: DesignTokensFile;
853
+ /** Stack of references being resolved (for circular detection) */
854
+ resolutionStack: string[];
855
+ /** Root path for relative references */
856
+ rootPath?: string;
857
+ }
858
+
859
+ /**
860
+ * Reference resolution result
861
+ */
862
+ export interface ResolutionResult<T = unknown> {
863
+ /** Whether resolution was successful */
864
+ success: boolean;
865
+ /** Resolved value (if successful) */
866
+ value?: T;
867
+ /** Error message (if unsuccessful) */
868
+ error?: string;
869
+ /** Path of the resolved token */
870
+ resolvedPath?: string;
871
+ }
872
+
873
+ // ============================================================================
874
+ // ADVANCED GROUP FEATURES
875
+ // ============================================================================
876
+
877
+ /**
878
+ * Group inheritance semantics for $extends
879
+ */
880
+ export interface InheritanceRules {
881
+ /** Local properties override inherited properties at same path */
882
+ overrideAtSamePath: true;
883
+ /** Properties at different paths are merged */
884
+ mergeAtDifferentPaths: true;
885
+ /** Complete property replacement (not property-by-property merge) */
886
+ completeReplacement: true;
887
+ }
888
+
889
+ /**
890
+ * Processing order for group resolution
891
+ */
892
+ export type ProcessingOrder = [
893
+ 'localTokens', // Direct children with $value
894
+ 'rootTokens', // Tokens with $root names
895
+ 'extendedTokens', // Inherited via $extends
896
+ 'nestedGroups' // Process recursively
897
+ ];
898
+
899
+ /**
900
+ * Type inheritance precedence order
901
+ */
902
+ export type TypeInheritancePrecedence = [
903
+ 'tokenExplicitType', // Token's explicit $type property
904
+ 'resolvedGroupType', // Resolved group's $type (after extension)
905
+ 'parentGroupType', // Parent group's $type (walking up hierarchy)
906
+ 'invalid' // Token is invalid if no type determined
907
+ ];
908
+
909
+ // ============================================================================
910
+ // EXTENSION AND PLUGIN TYPES
911
+ // ============================================================================
912
+
913
+ /**
914
+ * Extension data structure for vendor-specific data
915
+ */
916
+ export interface ExtensionData {
917
+ /** Vendor identifier (reverse domain notation recommended) */
918
+ [vendorKey: string]: unknown;
919
+ }
920
+
921
+ /**
922
+ * Tool-specific extension interface
923
+ */
924
+ export interface ToolExtension {
925
+ /** Tool identifier */
926
+ toolId: string;
927
+ /** Tool version */
928
+ version?: string;
929
+ /** Extension data */
930
+ data: unknown;
931
+ }
932
+
933
+ /**
934
+ * Mode-specific token values for theming (e.g., light/dark mode)
935
+ * Values can be explicit values or token references
936
+ * When referencing tokens, the referenced token's mode value is used if available
937
+ * Used as $extensions.$mode in design tokens
938
+ */
939
+ export interface ModeExtension {
940
+ /** Dark mode value - can be explicit value or token reference */
941
+ dark?: ValueOrReference<unknown>;
942
+ /** Light mode value - can be explicit value or token reference */
943
+ light?: ValueOrReference<unknown>;
944
+ /** High contrast mode value */
945
+ 'high-contrast'?: ValueOrReference<unknown>;
946
+ /** Custom mode values */
947
+ [modeName: string]: ValueOrReference<unknown> | undefined;
948
+ }
949
+
950
+ /**
951
+ * Generator types for creating derived tokens
952
+ */
953
+ export type GeneratorType =
954
+ | 'alpha' // Alpha/opacity variations
955
+ | 'hue' // Hue variations
956
+ | 'saturation' // Saturation variations
957
+ | 'lightness' // Lightness variations
958
+ | 'scale' // Scale variations for dimensions
959
+ | string; // Custom generator types
960
+
961
+ /**
962
+ * Generator configuration for creating derived tokens
963
+ * The key (e.g., "@alpha1", "@scale2x") becomes a suffix for the generated token name
964
+ * Original token "gray.n0" with "@alpha1": 1 generates "gray.n0@alpha1"
965
+ */
966
+ export interface GeneratorConfig {
967
+ /** Generator type */
968
+ type: GeneratorType;
969
+ /**
970
+ * Generator values where key becomes token suffix and value is the generator parameter
971
+ * @example { "@alpha1": 1, "@alpha50": 50, "@alpha90": 90 }
972
+ * @example { "@scale2x": 2, "@scale05": 0.5 }
973
+ */
974
+ value: Record<string, number | string>;
975
+ }
976
+
977
+ /**
978
+ * Generators extension for creating derived tokens
979
+ * Used as $extensions.$generators in design tokens
980
+ */
981
+ export type GeneratorsExtension = GeneratorConfig[];
982
+
983
+ /**
984
+ * Breakpoint-specific token values for responsive design
985
+ * Keys are CSS media queries (can contain token references)
986
+ * Values follow the same structure as regular design tokens
987
+ * Used as $extensions.$breakpoints in design tokens
988
+ */
989
+ export interface BreakpointsExtension {
990
+ /**
991
+ * CSS media query as key (supports token references in composite strings)
992
+ * @example "(min-width: {foundation.breakpoint.lg})"
993
+ * @example "(prefers-color-scheme: dark)"
994
+ * @example "(min-width: 768px) and (orientation: landscape)"
995
+ * @example "@container (min-width: {container.sizes.md})"
996
+ */
997
+ [mediaQuery: string]: {
998
+ /** Token type (can override base type) */
999
+ $type?: TokenType;
1000
+ /** Token value for this breakpoint */
1001
+ $value: ValueOrReference<unknown>;
1002
+ /** Token description */
1003
+ $description?: string;
1004
+ /** Nested extensions (like mode) for this breakpoint */
1005
+ $extensions?: EnhancedExtensionData;
1006
+ };
1007
+ }
1008
+
1009
+ /**
1010
+ * Enhanced extension data with mode, generators, and breakpoints support
1011
+ * Uses $ prefix for reserved/standardized extensions
1012
+ */
1013
+ export interface EnhancedExtensionData extends ExtensionData {
1014
+ /** Mode-specific values for theming */
1015
+ $mode?: ModeExtension;
1016
+ /** Generator configurations for derived tokens */
1017
+ $generators?: GeneratorsExtension;
1018
+ /** Breakpoint-specific values for responsive design */
1019
+ $breakpoints?: BreakpointsExtension;
1020
+ }
1021
+
1022
+ /**
1023
+ * Common extension patterns
1024
+ */
1025
+ export interface CommonExtensions {
1026
+ /** Mode-specific token values */
1027
+ $mode?: ModeExtension;
1028
+
1029
+ /** Generator configurations for derived tokens */
1030
+ $generators?: GeneratorsExtension;
1031
+
1032
+ /** Breakpoint-specific values for responsive design */
1033
+ $breakpoints?: BreakpointsExtension;
1034
+
1035
+ /** Figma-specific data */
1036
+ 'com.figma'?: {
1037
+ node?: {
1038
+ nodeId?: string;
1039
+ styleId?: string;
1040
+ [key: string]: unknown;
1041
+ };
1042
+ } | {
1043
+ /** SVG-specific data to be loaded into Figma */
1044
+ svg?: {
1045
+ id: string;
1046
+ [svgName: string]: string;
1047
+ };
1048
+ };
1049
+ }
1050
+
1051
+ // ============================================================================
1052
+ // EXPORT ALL TYPES
1053
+ // ============================================================================
1054
+
1055
+ /**
1056
+ * Default export containing all types and utilities
1057
+ */
1058
+ export default {
1059
+ // Constants
1060
+ DESIGN_TOKENS_MEDIA_TYPE,
1061
+ DESIGN_TOKENS_EXTENSIONS,
1062
+
1063
+ // Type guards
1064
+ isTokenReference,
1065
+ isJsonPointerReference,
1066
+ isCompositeStringValue,
1067
+ isDesignToken,
1068
+ isTokenGroup,
1069
+ hasModeExtension,
1070
+ hasGeneratorExtension,
1071
+ hasBreakpointExtension,
1072
+
1073
+ // Utilities
1074
+ getModeValue,
1075
+ getGeneratorSuffixes,
1076
+ getBreakpointQueries,
1077
+ getBreakpointValue,
1078
+ getBreakpointConfig,
1079
+ generateDerivedTokenName,
1080
+ extractReferencesFromCompositeString,
1081
+ extractTokenReferencesFromMediaQuery,
1082
+ parseCompositeString,
1083
+ };