chaincss 2.0.7 → 2.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.
Files changed (159) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/CODE_OF_CONDUCT.md +21 -0
  3. package/CONTRIBUTING.md +28 -0
  4. package/README.md +455 -226
  5. package/demo/demo/node_modules/caniuse-db/fulldata-json/data-2.0.json +1 -0
  6. package/demo/index.html +16 -0
  7. package/demo/package.json +20 -0
  8. package/demo/src/App.tsx +117 -0
  9. package/demo/src/chaincss-barrel.ts +9 -0
  10. package/demo/src/main.tsx +8 -0
  11. package/demo/src/styles.chain.ts +300 -0
  12. package/demo/vite.config.ts +46 -0
  13. package/dist/cli/commands/build.d.ts +0 -1
  14. package/dist/cli/commands/cache.d.ts +1 -0
  15. package/dist/cli/commands/init.d.ts +6 -3
  16. package/dist/cli/commands/timeline.d.ts +0 -1
  17. package/dist/cli/commands/watch.d.ts +0 -1
  18. package/dist/cli/index.d.ts +0 -1
  19. package/dist/cli/index.js +3213 -5296
  20. package/dist/cli/types.d.ts +51 -20
  21. package/dist/cli/utils/config-loader.d.ts +0 -1
  22. package/dist/cli/utils/file-utils.d.ts +27 -3
  23. package/dist/cli/utils/logger.d.ts +0 -1
  24. package/dist/compiler/Chain.d.ts +215 -0
  25. package/dist/compiler/animations.d.ts +76 -0
  26. package/dist/compiler/atomic-optimizer.d.ts +47 -12
  27. package/dist/compiler/breakpoints.d.ts +46 -0
  28. package/dist/compiler/btt.d.ts +36 -60
  29. package/dist/compiler/cache-manager.d.ts +58 -4
  30. package/dist/compiler/commonProps.d.ts +0 -1
  31. package/dist/compiler/content-addressable-cache.d.ts +78 -0
  32. package/dist/compiler/helpers.d.ts +54 -0
  33. package/dist/compiler/index.d.ts +16 -9
  34. package/dist/compiler/index.js +4450 -4316
  35. package/dist/compiler/prefixer.d.ts +17 -1
  36. package/dist/compiler/shorthands.d.ts +28 -0
  37. package/dist/compiler/suggestions.d.ts +43 -0
  38. package/dist/compiler/theme-contract.d.ts +16 -27
  39. package/dist/compiler/token-resolver.d.ts +69 -0
  40. package/dist/compiler/tokens.d.ts +33 -8
  41. package/dist/core/auto-detector.d.ts +34 -0
  42. package/dist/core/common-utils.d.ts +97 -0
  43. package/dist/core/compiler.d.ts +63 -23
  44. package/dist/core/constants.d.ts +137 -36
  45. package/dist/core/smart-chain.d.ts +3 -0
  46. package/dist/core/types.d.ts +122 -15
  47. package/dist/core/utils.d.ts +134 -17
  48. package/dist/index.d.ts +52 -8
  49. package/dist/index.js +7090 -5578
  50. package/dist/plugins/vite.d.ts +7 -5
  51. package/dist/plugins/vite.js +2964 -25641
  52. package/dist/plugins/webpack.d.ts +24 -1
  53. package/dist/plugins/webpack.js +209 -72
  54. package/dist/runtime/Chain.d.ts +32 -0
  55. package/dist/runtime/auto-hooks.d.ts +11 -0
  56. package/dist/runtime/hmr.d.ts +22 -2
  57. package/dist/runtime/index.d.ts +3 -2
  58. package/dist/runtime/index.js +3648 -301
  59. package/dist/runtime/injector.d.ts +39 -72
  60. package/dist/runtime/react.d.ts +17 -12
  61. package/dist/runtime/svelte.d.ts +15 -0
  62. package/dist/runtime/types.d.ts +126 -4
  63. package/dist/runtime/utils.d.ts +0 -1
  64. package/dist/runtime/vue.d.ts +34 -14
  65. package/package.json +59 -66
  66. package/src/cli/commands/build.ts +133 -0
  67. package/src/cli/commands/cache.ts +371 -0
  68. package/src/cli/commands/init.ts +230 -0
  69. package/src/cli/commands/timeline.ts +435 -0
  70. package/src/cli/commands/watch.ts +211 -0
  71. package/src/cli/index.ts +226 -0
  72. package/src/cli/types.ts +100 -0
  73. package/src/cli/utils/config-loader.ts +174 -0
  74. package/src/cli/utils/file-utils.ts +139 -0
  75. package/src/cli/utils/logger.ts +74 -0
  76. package/src/compiler/Chain.ts +831 -0
  77. package/src/compiler/animations.ts +517 -0
  78. package/src/compiler/atomic-optimizer.ts +786 -0
  79. package/src/compiler/breakpoints.ts +347 -0
  80. package/src/compiler/btt.ts +1147 -0
  81. package/src/compiler/cache-manager.ts +446 -0
  82. package/src/compiler/commonProps.ts +18 -0
  83. package/src/compiler/content-addressable-cache.ts +478 -0
  84. package/src/compiler/helpers.ts +407 -0
  85. package/src/compiler/index.ts +72 -0
  86. package/src/compiler/prefixer.ts +724 -0
  87. package/src/compiler/shorthands.ts +558 -0
  88. package/src/compiler/suggestions.ts +436 -0
  89. package/src/compiler/theme-contract.ts +197 -0
  90. package/src/compiler/token-resolver.ts +241 -0
  91. package/src/compiler/tokens.ts +612 -0
  92. package/src/core/auto-detector.ts +187 -0
  93. package/src/core/common-utils.ts +423 -0
  94. package/src/core/compiler.ts +835 -0
  95. package/src/core/constants.ts +424 -0
  96. package/src/core/index.ts +107 -0
  97. package/src/core/smart-chain.ts +163 -0
  98. package/src/core/types.ts +257 -0
  99. package/src/core/utils.ts +598 -0
  100. package/src/index.ts +208 -0
  101. package/src/plugins/vite.d.ts +316 -0
  102. package/src/plugins/vite.ts +424 -0
  103. package/src/plugins/webpack.d.ts +289 -0
  104. package/src/plugins/webpack.ts +416 -0
  105. package/src/runtime/Chain.ts +242 -0
  106. package/src/runtime/auto-hooks.tsx +127 -0
  107. package/src/runtime/auto-vue.ts +72 -0
  108. package/src/runtime/hmr.ts +212 -0
  109. package/src/runtime/index.ts +82 -0
  110. package/src/runtime/injector.ts +273 -0
  111. package/src/runtime/react.tsx +269 -0
  112. package/src/runtime/svelte.ts +15 -0
  113. package/src/runtime/types.ts +256 -0
  114. package/src/runtime/utils.ts +128 -0
  115. package/src/runtime/vite-env.d.ts +120 -0
  116. package/src/runtime/vue.ts +231 -0
  117. package/tsconfig.build.json +41 -0
  118. package/tsconfig.json +25 -0
  119. package/tsconfig.runtimes.json +18 -0
  120. package/dist/cli/cli.cjs +0 -7
  121. package/dist/cli/commands/build.d.ts.map +0 -1
  122. package/dist/cli/commands/compile.d.ts +0 -3
  123. package/dist/cli/commands/compile.d.ts.map +0 -1
  124. package/dist/cli/commands/init.d.ts.map +0 -1
  125. package/dist/cli/commands/timeline.d.ts.map +0 -1
  126. package/dist/cli/commands/watch.d.ts.map +0 -1
  127. package/dist/cli/index.d.ts.map +0 -1
  128. package/dist/cli/types.d.ts.map +0 -1
  129. package/dist/cli/utils/config-loader.d.ts.map +0 -1
  130. package/dist/cli/utils/file-utils.d.ts.map +0 -1
  131. package/dist/cli/utils/logger.d.ts.map +0 -1
  132. package/dist/compiler/atomic-optimizer.d.ts.map +0 -1
  133. package/dist/compiler/btt.d.ts.map +0 -1
  134. package/dist/compiler/cache-manager.d.ts.map +0 -1
  135. package/dist/compiler/commonProps.d.ts.map +0 -1
  136. package/dist/compiler/index.d.ts.map +0 -1
  137. package/dist/compiler/prefixer.d.ts.map +0 -1
  138. package/dist/compiler/theme-contract.d.ts.map +0 -1
  139. package/dist/compiler/tokens.d.ts.map +0 -1
  140. package/dist/compiler/types.d.ts +0 -57
  141. package/dist/compiler/types.d.ts.map +0 -1
  142. package/dist/core/compiler.d.ts.map +0 -1
  143. package/dist/core/constants.d.ts.map +0 -1
  144. package/dist/core/index.d.ts +0 -4
  145. package/dist/core/index.d.ts.map +0 -1
  146. package/dist/core/types.d.ts.map +0 -1
  147. package/dist/core/utils.d.ts.map +0 -1
  148. package/dist/index.d.ts.map +0 -1
  149. package/dist/plugins/vite.d.ts.map +0 -1
  150. package/dist/plugins/webpack.d.ts.map +0 -1
  151. package/dist/runtime/hmr.d.ts.map +0 -1
  152. package/dist/runtime/index.d.ts.map +0 -1
  153. package/dist/runtime/injector.d.ts.map +0 -1
  154. package/dist/runtime/react.d.ts.map +0 -1
  155. package/dist/runtime/react.js +0 -324
  156. package/dist/runtime/types.d.ts.map +0 -1
  157. package/dist/runtime/utils.d.ts.map +0 -1
  158. package/dist/runtime/vue.d.ts.map +0 -1
  159. package/dist/runtime/vue.js +0 -286
@@ -0,0 +1,612 @@
1
+ // src/compiler/tokens.ts
2
+ // Types
3
+ export interface TokenColors {
4
+ [key: string]: string | Record<string, string>;
5
+ }
6
+
7
+ export interface TokenSpacing {
8
+ [key: string]: string;
9
+ }
10
+
11
+ export interface TokenTypography {
12
+ fontFamily: Record<string, string>;
13
+ fontSize: Record<string, string>;
14
+ fontWeight: Record<string, string>;
15
+ lineHeight: Record<string, string>;
16
+ letterSpacing?: Record<string, string>; // Add this optional property
17
+ }
18
+
19
+ export interface TokenBreakpoints {
20
+ [key: string]: string;
21
+ }
22
+
23
+ export interface TokenZIndex {
24
+ [key: string]: string;
25
+ }
26
+
27
+ export interface TokenShadows {
28
+ [key: string]: string;
29
+ }
30
+
31
+ export interface TokenBorderRadius {
32
+ [key: string]: string;
33
+ }
34
+
35
+ export interface TokensStructure {
36
+ colors: TokenColors;
37
+ spacing: TokenSpacing;
38
+ typography: TokenTypography;
39
+ breakpoints: TokenBreakpoints;
40
+ zIndex: TokenZIndex;
41
+ shadows: TokenShadows;
42
+ borderRadius: TokenBorderRadius;
43
+ [key: string]: any;
44
+ }
45
+
46
+ export interface TokenValue {
47
+ value: any;
48
+ description?: string;
49
+ deprecated?: boolean;
50
+ aliases?: string[];
51
+ }
52
+
53
+ export type FlattenedTokens = Record<string, string>;
54
+
55
+ // Default tokens (kept as immutable constant)
56
+ export const defaultTokens: TokensStructure = {
57
+ colors: {
58
+ primary: '#667eea',
59
+ secondary: '#764ba2',
60
+ success: '#48bb78',
61
+ danger: '#f56565',
62
+ warning: '#ed8936',
63
+ info: '#4299e1',
64
+ light: '#f7fafc',
65
+ dark: '#1a202c',
66
+ white: '#ffffff',
67
+ black: '#000000',
68
+ gray: {
69
+ 50: '#f9fafb',
70
+ 100: '#f7fafc',
71
+ 200: '#edf2f7',
72
+ 300: '#e2e8f0',
73
+ 400: '#cbd5e0',
74
+ 500: '#a0aec0',
75
+ 600: '#718096',
76
+ 700: '#4a5568',
77
+ 800: '#2d3748',
78
+ 900: '#1a202c'
79
+ },
80
+ blue: {
81
+ 50: '#eff6ff',
82
+ 100: '#dbeafe',
83
+ 200: '#bfdbfe',
84
+ 300: '#93c5fd',
85
+ 400: '#60a5fa',
86
+ 500: '#3b82f6',
87
+ 600: '#2563eb',
88
+ 700: '#1d4ed8',
89
+ 800: '#1e40af',
90
+ 900: '#1e3a8a'
91
+ },
92
+ green: {
93
+ 50: '#f0fdf4',
94
+ 100: '#dcfce7',
95
+ 200: '#bbf7d0',
96
+ 300: '#86efac',
97
+ 400: '#4ade80',
98
+ 500: '#22c55e',
99
+ 600: '#16a34a',
100
+ 700: '#15803d',
101
+ 800: '#166534',
102
+ 900: '#14532d'
103
+ },
104
+ red: {
105
+ 50: '#fef2f2',
106
+ 100: '#fee2e2',
107
+ 200: '#fecaca',
108
+ 300: '#fca5a5',
109
+ 400: '#f87171',
110
+ 500: '#ef4444',
111
+ 600: '#dc2626',
112
+ 700: '#b91c1c',
113
+ 800: '#991b1b',
114
+ 900: '#7f1d1d'
115
+ },
116
+ yellow: {
117
+ 50: '#fefce8',
118
+ 100: '#fef9c3',
119
+ 200: '#fef08a',
120
+ 300: '#fde047',
121
+ 400: '#facc15',
122
+ 500: '#eab308',
123
+ 600: '#ca8a04',
124
+ 700: '#a16207',
125
+ 800: '#854d0e',
126
+ 900: '#713f12'
127
+ }
128
+ },
129
+
130
+ spacing: {
131
+ 0: '0',
132
+ 0.5: '0.125rem',
133
+ 1: '0.25rem',
134
+ 1.5: '0.375rem',
135
+ 2: '0.5rem',
136
+ 2.5: '0.625rem',
137
+ 3: '0.75rem',
138
+ 3.5: '0.875rem',
139
+ 4: '1rem',
140
+ 5: '1.25rem',
141
+ 6: '1.5rem',
142
+ 7: '1.75rem',
143
+ 8: '2rem',
144
+ 9: '2.25rem',
145
+ 10: '2.5rem',
146
+ 11: '2.75rem',
147
+ 12: '3rem',
148
+ 14: '3.5rem',
149
+ 16: '4rem',
150
+ 20: '5rem',
151
+ 24: '6rem',
152
+ 28: '7rem',
153
+ 32: '8rem',
154
+ 36: '9rem',
155
+ 40: '10rem',
156
+ 44: '11rem',
157
+ 48: '12rem',
158
+ 52: '13rem',
159
+ 56: '14rem',
160
+ 60: '15rem',
161
+ 64: '16rem',
162
+ 72: '18rem',
163
+ 80: '20rem',
164
+ 96: '24rem',
165
+ xs: '0.5rem',
166
+ sm: '1rem',
167
+ md: '1.5rem',
168
+ lg: '2rem',
169
+ xl: '3rem',
170
+ '2xl': '4rem',
171
+ '3xl': '6rem',
172
+ '4xl': '8rem',
173
+ '5xl': '10rem'
174
+ },
175
+
176
+ typography: {
177
+ fontFamily: {
178
+ sans: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
179
+ serif: 'Georgia, Cambria, "Times New Roman", Times, serif',
180
+ mono: 'SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
181
+ system: 'system-ui, -apple-system, sans-serif'
182
+ },
183
+ fontSize: {
184
+ xs: '0.75rem',
185
+ sm: '0.875rem',
186
+ base: '1rem',
187
+ lg: '1.125rem',
188
+ xl: '1.25rem',
189
+ '2xl': '1.5rem',
190
+ '3xl': '1.875rem',
191
+ '4xl': '2.25rem',
192
+ '5xl': '3rem',
193
+ '6xl': '3.75rem',
194
+ '7xl': '4.5rem',
195
+ '8xl': '6rem',
196
+ '9xl': '8rem'
197
+ },
198
+ fontWeight: {
199
+ hairline: '100',
200
+ thin: '200',
201
+ light: '300',
202
+ normal: '400',
203
+ medium: '500',
204
+ semibold: '600',
205
+ bold: '700',
206
+ extrabold: '800',
207
+ black: '900'
208
+ },
209
+ lineHeight: {
210
+ none: '1',
211
+ tight: '1.25',
212
+ snug: '1.375',
213
+ normal: '1.5',
214
+ relaxed: '1.625',
215
+ loose: '2',
216
+ 3: '.75rem',
217
+ 4: '1rem',
218
+ 5: '1.25rem',
219
+ 6: '1.5rem',
220
+ 7: '1.75rem',
221
+ 8: '2rem',
222
+ 9: '2.25rem',
223
+ 10: '2.5rem'
224
+ },
225
+ letterSpacing: {
226
+ tighter: '-0.05em',
227
+ tight: '-0.025em',
228
+ normal: '0',
229
+ wide: '0.025em',
230
+ wider: '0.05em',
231
+ widest: '0.1em'
232
+ }
233
+ },
234
+
235
+ breakpoints: {
236
+ sm: '640px',
237
+ md: '768px',
238
+ lg: '1024px',
239
+ xl: '1280px',
240
+ '2xl': '1536px',
241
+ '3xl': '1920px',
242
+ mobile: '640px',
243
+ tablet: '768px',
244
+ desktop: '1024px',
245
+ wide: '1280px'
246
+ },
247
+
248
+ zIndex: {
249
+ 0: '0',
250
+ 10: '10',
251
+ 20: '20',
252
+ 30: '30',
253
+ 40: '40',
254
+ 50: '50',
255
+ auto: 'auto',
256
+ dropdown: '1000',
257
+ sticky: '1020',
258
+ fixed: '1030',
259
+ modal: '1040',
260
+ popover: '1050',
261
+ tooltip: '1060',
262
+ toast: '1070',
263
+ overlay: '1080'
264
+ },
265
+
266
+ shadows: {
267
+ xs: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
268
+ sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
269
+ base: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
270
+ md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
271
+ lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
272
+ xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
273
+ '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
274
+ inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
275
+ none: 'none',
276
+ 'glow-sm': '0 0 10px rgba(102, 126, 234, 0.5)',
277
+ 'glow-md': '0 0 20px rgba(102, 126, 234, 0.5)',
278
+ 'glow-lg': '0 0 30px rgba(102, 126, 234, 0.5)'
279
+ },
280
+
281
+ borderRadius: {
282
+ none: '0',
283
+ sm: '0.125rem',
284
+ base: '0.25rem',
285
+ md: '0.375rem',
286
+ lg: '0.5rem',
287
+ xl: '0.75rem',
288
+ '2xl': '1rem',
289
+ '3xl': '1.5rem',
290
+ '4xl': '2rem',
291
+ full: '9999px'
292
+ },
293
+
294
+ // Additional animation presets
295
+ animations: {
296
+ fade: {
297
+ '0%': { opacity: 0 },
298
+ '100%': { opacity: 1 }
299
+ },
300
+ slideUp: {
301
+ '0%': { transform: 'translateY(20px)', opacity: 0 },
302
+ '100%': { transform: 'translateY(0)', opacity: 1 }
303
+ },
304
+ slideDown: {
305
+ '0%': { transform: 'translateY(-20px)', opacity: 0 },
306
+ '100%': { transform: 'translateY(0)', opacity: 1 }
307
+ },
308
+ slideLeft: {
309
+ '0%': { transform: 'translateX(20px)', opacity: 0 },
310
+ '100%': { transform: 'translateX(0)', opacity: 1 }
311
+ },
312
+ slideRight: {
313
+ '0%': { transform: 'translateX(-20px)', opacity: 0 },
314
+ '100%': { transform: 'translateX(0)', opacity: 1 }
315
+ },
316
+ scale: {
317
+ '0%': { transform: 'scale(0.95)', opacity: 0 },
318
+ '100%': { transform: 'scale(1)', opacity: 1 }
319
+ },
320
+ bounce: {
321
+ '0%, 100%': { transform: 'translateY(0)' },
322
+ '50%': { transform: 'translateY(-25%)' }
323
+ },
324
+ pulse: {
325
+ '0%, 100%': { opacity: 1 },
326
+ '50%': { opacity: 0.5 }
327
+ },
328
+ spin: {
329
+ '0%': { transform: 'rotate(0deg)' },
330
+ '100%': { transform: 'rotate(360deg)' }
331
+ },
332
+ shimmer: {
333
+ '0%': { backgroundPosition: '-200% 0' },
334
+ '100%': { backgroundPosition: '200% 0' }
335
+ }
336
+ }
337
+ };
338
+
339
+ export class DesignTokens {
340
+ private customTokens: TokensStructure;
341
+ private customFlattened: FlattenedTokens;
342
+ private defaultFlattened: FlattenedTokens;
343
+ private tokenCache: Map<string, string> = new Map();
344
+
345
+ constructor(customTokens: Partial<TokensStructure> = {}) {
346
+ // Deep clone custom tokens to prevent mutation
347
+ this.customTokens = this.deepClone(customTokens) as TokensStructure;
348
+
349
+ // Flatten both token sets
350
+ this.customFlattened = this.flattenTokens(this.customTokens);
351
+ this.defaultFlattened = this.flattenTokens(defaultTokens);
352
+
353
+ // Freeze to prevent modifications
354
+ Object.freeze(this.customTokens);
355
+ Object.freeze(this.customFlattened);
356
+ Object.freeze(this.defaultFlattened);
357
+ }
358
+
359
+ // Deep clone objects
360
+ private deepClone<T>(obj: T): T {
361
+ if (obj === null || typeof obj !== 'object') return obj;
362
+ if (Array.isArray(obj)) return obj.map(item => this.deepClone(item)) as any;
363
+
364
+ const cloned: any = {};
365
+ for (const key in obj) {
366
+ if (obj.hasOwnProperty(key)) {
367
+ cloned[key] = this.deepClone(obj[key]);
368
+ }
369
+ }
370
+ return cloned;
371
+ }
372
+
373
+ // Deep freeze to prevent accidental modifications
374
+ private deepFreeze<T extends object>(obj: T): T {
375
+ Object.keys(obj).forEach(key => {
376
+ const value = (obj as any)[key];
377
+ if (typeof value === 'object' && value !== null && !Object.isFrozen(value)) {
378
+ this.deepFreeze(value);
379
+ }
380
+ });
381
+ return Object.freeze(obj);
382
+ }
383
+
384
+ // Flatten nested tokens for easy access
385
+ flattenTokens(obj: Record<string, any>, prefix: string = ''): FlattenedTokens {
386
+ const result: FlattenedTokens = {};
387
+
388
+ for (const [key, value] of Object.entries(obj)) {
389
+ const prefixed = prefix ? `${prefix}.${key}` : key;
390
+
391
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
392
+ // Recursively flatten nested objects
393
+ Object.assign(result, this.flattenTokens(value, prefixed));
394
+ } else {
395
+ result[prefixed] = String(value);
396
+ }
397
+ }
398
+
399
+ return result;
400
+ }
401
+
402
+ // Get token value by path (e.g., 'colors.primary')
403
+ // Checks custom tokens first, then falls back to default tokens
404
+ get(path: string, defaultValue: string = ''): string {
405
+ // Check cache first
406
+ if (this.tokenCache.has(path)) {
407
+ return this.tokenCache.get(path)!;
408
+ }
409
+
410
+ let value: string | undefined;
411
+
412
+ // First try custom tokens
413
+ if (path in this.customFlattened) {
414
+ value = this.customFlattened[path];
415
+ }
416
+
417
+ // Then try default tokens
418
+ if (value === undefined && path in this.defaultFlattened) {
419
+ value = this.defaultFlattened[path];
420
+ }
421
+
422
+ // Handle token references (e.g., "$colors.primary")
423
+ if (value && value.startsWith('$')) {
424
+ const refPath = value.substring(1);
425
+ value = this.get(refPath, defaultValue);
426
+ }
427
+
428
+ const result = value !== undefined ? value : defaultValue;
429
+
430
+ // Cache the result
431
+ this.tokenCache.set(path, result);
432
+
433
+ return result;
434
+ }
435
+
436
+ // Get token with type safety
437
+ getColor(path: string, defaultValue: string = '#000000'): string {
438
+ return this.get(`colors.${path}`, defaultValue);
439
+ }
440
+
441
+ getSpacing(path: string, defaultValue: string = '0'): string {
442
+ return this.get(`spacing.${path}`, defaultValue);
443
+ }
444
+
445
+ getFontSize(path: string, defaultValue: string = '1rem'): string {
446
+ return this.get(`typography.fontSize.${path}`, defaultValue);
447
+ }
448
+
449
+ getFontWeight(path: string, defaultValue: string = '400'): string {
450
+ return this.get(`typography.fontWeight.${path}`, defaultValue);
451
+ }
452
+
453
+ getLineHeight(path: string, defaultValue: string = '1.5'): string {
454
+ return this.get(`typography.lineHeight.${path}`, defaultValue);
455
+ }
456
+
457
+ getBreakpoint(path: string, defaultValue: string = '768px'): string {
458
+ return this.get(`breakpoints.${path}`, defaultValue);
459
+ }
460
+
461
+ getZIndex(path: string, defaultValue: string = '0'): string {
462
+ return this.get(`zIndex.${path}`, defaultValue);
463
+ }
464
+
465
+ getShadow(path: string, defaultValue: string = 'none'): string {
466
+ return this.get(`shadows.${path}`, defaultValue);
467
+ }
468
+
469
+ getBorderRadius(path: string, defaultValue: string = '0'): string {
470
+ return this.get(`borderRadius.${path}`, defaultValue);
471
+ }
472
+
473
+ // Get all custom tokens (as flattened object)
474
+ getCustomTokens(): FlattenedTokens {
475
+ return { ...this.customFlattened };
476
+ }
477
+
478
+ // Get all default tokens (as flattened object)
479
+ getDefaultTokens(): FlattenedTokens {
480
+ return { ...this.defaultFlattened };
481
+ }
482
+
483
+ // Check if a token exists (in either custom or default)
484
+ has(path: string): boolean {
485
+ return path in this.customFlattened || path in this.defaultFlattened;
486
+ }
487
+
488
+ // Generate CSS variables from tokens (combines both custom and default)
489
+ toCSSVariables(prefix: string = 'chain'): string {
490
+ let css = ':root {\n';
491
+
492
+ // Combine both token sets (custom overrides default)
493
+ const allTokens = { ...this.defaultFlattened, ...this.customFlattened };
494
+
495
+ for (const [key, value] of Object.entries(allTokens)) {
496
+ const varName = `--${prefix}-${key.replace(/\./g, '-')}`;
497
+ css += ` ${varName}: ${value};\n`;
498
+ }
499
+
500
+ css += '}\n';
501
+ return css;
502
+ }
503
+
504
+ // Generate media queries from breakpoints
505
+ toMediaQueries(): Record<string, string> {
506
+ const queries: Record<string, string> = {};
507
+
508
+ for (const [name, value] of Object.entries(this.customFlattened)) {
509
+ if (name.startsWith('breakpoints.')) {
510
+ const breakpointName = name.replace('breakpoints.', '');
511
+ queries[breakpointName] = value;
512
+ }
513
+ }
514
+
515
+ return queries;
516
+ }
517
+
518
+ // Create a theme variant (overrides on top of defaults + custom)
519
+ createTheme(name: string, overrides: Record<string, string>): DesignTokens {
520
+ // Start with current custom tokens, then apply overrides
521
+ const newCustomTokens = this.deepClone(this.customTokens);
522
+
523
+ // Apply overrides to nested structure
524
+ for (const [path, value] of Object.entries(overrides)) {
525
+ const parts = path.split('.');
526
+ let current: any = newCustomTokens;
527
+
528
+ for (let i = 0; i < parts.length - 1; i++) {
529
+ if (!current[parts[i]]) {
530
+ current[parts[i]] = {};
531
+ }
532
+ current = current[parts[i]];
533
+ }
534
+
535
+ current[parts[parts.length - 1]] = value;
536
+ }
537
+
538
+ return new DesignTokens(newCustomTokens);
539
+ }
540
+
541
+ // Merge with another token set
542
+ merge(tokens: Partial<TokensStructure>): DesignTokens {
543
+ const merged = this.deepClone(this.customTokens);
544
+
545
+ const deepMerge = (target: any, source: any) => {
546
+ for (const key in source) {
547
+ if (source.hasOwnProperty(key)) {
548
+ if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
549
+ if (!target[key]) target[key] = {};
550
+ deepMerge(target[key], source[key]);
551
+ } else {
552
+ target[key] = source[key];
553
+ }
554
+ }
555
+ }
556
+ };
557
+
558
+ deepMerge(merged, tokens);
559
+ return new DesignTokens(merged);
560
+ }
561
+
562
+ // Clear cache
563
+ clearCache(): void {
564
+ this.tokenCache.clear();
565
+ }
566
+
567
+ // Get token path suggestions for autocomplete
568
+ getSuggestions(partialPath: string): string[] {
569
+ const allTokens = { ...this.defaultFlattened, ...this.customFlattened };
570
+ const suggestions: string[] = [];
571
+
572
+ for (const key of Object.keys(allTokens)) {
573
+ if (key.includes(partialPath)) {
574
+ suggestions.push(key);
575
+ }
576
+ }
577
+
578
+ return suggestions.sort();
579
+ }
580
+ }
581
+
582
+ // Singleton instance with default tokens
583
+ export const tokens = new DesignTokens(defaultTokens);
584
+
585
+ // Token utility functions
586
+ export function createTokens(customTokens: Partial<TokensStructure>): DesignTokens {
587
+ return new DesignTokens(customTokens);
588
+ }
589
+
590
+ // Helper to resolve token references in strings
591
+ export function resolveTokenReferences(
592
+ value: string,
593
+ tokens: DesignTokens,
594
+ prefix: string = '$'
595
+ ): string {
596
+ if (typeof value !== 'string') return String(value);
597
+
598
+ const tokenRegex = new RegExp(`${prefix}([a-zA-Z0-9.-]+)`, 'g');
599
+
600
+ return value.replace(tokenRegex, (match, tokenPath) => {
601
+ const resolved = tokens.get(tokenPath);
602
+ return resolved !== undefined ? resolved : match;
603
+ });
604
+ }
605
+
606
+ // Type guard to check if value is a token reference
607
+ export function isTokenReference(value: any, prefix: string = '$'): boolean {
608
+ return typeof value === 'string' && value.startsWith(prefix);
609
+ }
610
+
611
+ // ESM Export
612
+ export { DesignTokens as default };