@rakeyshgidwani/roger-ui-bank-theme-harvey 0.2.52 → 0.3.1

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 (131) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/components/ui/button.d.ts +3 -1
  3. package/dist/components/ui/button.d.ts.map +1 -1
  4. package/dist/components/ui/button.esm.js +3 -2
  5. package/dist/components/ui/button.js +3 -2
  6. package/dist/components/ui/layout/container.d.ts +57 -0
  7. package/dist/components/ui/layout/container.d.ts.map +1 -0
  8. package/dist/components/ui/layout/container.esm.js +173 -0
  9. package/dist/components/ui/layout/container.js +173 -0
  10. package/dist/components/ui/layout/index.d.ts +9 -0
  11. package/dist/components/ui/layout/index.d.ts.map +1 -0
  12. package/dist/components/ui/layout/index.esm.js +6 -0
  13. package/dist/components/ui/layout/index.js +6 -0
  14. package/dist/components/ui/layout/responsive-grid.d.ts +93 -0
  15. package/dist/components/ui/layout/responsive-grid.d.ts.map +1 -0
  16. package/dist/components/ui/layout/responsive-grid.esm.js +124 -0
  17. package/dist/components/ui/layout/responsive-grid.js +124 -0
  18. package/dist/components/ui/layouts/adaptive-layout.d.ts +1 -0
  19. package/dist/components/ui/layouts/adaptive-layout.d.ts.map +1 -1
  20. package/dist/components/ui/layouts/adaptive-layout.esm.js +2 -2
  21. package/dist/components/ui/layouts/adaptive-layout.js +2 -2
  22. package/dist/components/ui/navigation/index.d.ts +2 -1
  23. package/dist/components/ui/navigation/index.d.ts.map +1 -1
  24. package/dist/components/ui/navigation/index.esm.js +1 -0
  25. package/dist/components/ui/navigation/index.js +1 -0
  26. package/dist/components/ui/navigation/progressive-navigation.d.ts +37 -0
  27. package/dist/components/ui/navigation/progressive-navigation.d.ts.map +1 -0
  28. package/dist/components/ui/navigation/progressive-navigation.esm.js +145 -0
  29. package/dist/components/ui/navigation/progressive-navigation.js +145 -0
  30. package/dist/components/ui/navigation/types.d.ts +21 -0
  31. package/dist/components/ui/navigation/types.d.ts.map +1 -1
  32. package/dist/hooks/use-adaptive-layout.d.ts +2 -1
  33. package/dist/hooks/use-adaptive-layout.d.ts.map +1 -1
  34. package/dist/hooks/use-adaptive-layout.esm.js +13 -8
  35. package/dist/hooks/use-adaptive-layout.js +13 -8
  36. package/dist/hooks/use-device.d.ts +3 -1
  37. package/dist/hooks/use-device.d.ts.map +1 -1
  38. package/dist/hooks/use-device.esm.js +14 -7
  39. package/dist/hooks/use-device.js +14 -7
  40. package/dist/index.d.ts +19 -4
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.esm.js +9 -4
  43. package/dist/index.js +9 -4
  44. package/dist/plugins/css-purge-optimizer.d.ts +25 -0
  45. package/dist/plugins/css-purge-optimizer.d.ts.map +1 -0
  46. package/dist/plugins/css-purge-optimizer.esm.js +414 -0
  47. package/dist/plugins/css-purge-optimizer.js +414 -0
  48. package/dist/plugins/performance-monitor.d.ts +29 -0
  49. package/dist/plugins/performance-monitor.d.ts.map +1 -0
  50. package/dist/plugins/performance-monitor.esm.js +221 -0
  51. package/dist/plugins/performance-monitor.js +221 -0
  52. package/dist/plugins/progressive-css-loader.d.ts +21 -0
  53. package/dist/plugins/progressive-css-loader.d.ts.map +1 -0
  54. package/dist/plugins/progressive-css-loader.esm.js +227 -0
  55. package/dist/plugins/progressive-css-loader.js +227 -0
  56. package/dist/plugins/theme-css-generator.d.ts.map +1 -1
  57. package/dist/plugins/theme-css-generator.esm.js +19 -6
  58. package/dist/plugins/theme-css-generator.js +19 -6
  59. package/dist/styles.css +1027 -112
  60. package/dist/theme.d.ts.map +1 -1
  61. package/dist/theme.esm.js +4 -1
  62. package/dist/theme.js +4 -1
  63. package/dist/themes/phase1-constants.d.ts +23 -0
  64. package/dist/themes/phase1-constants.d.ts.map +1 -0
  65. package/dist/themes/phase1-constants.esm.js +180 -0
  66. package/dist/themes/phase1-constants.js +180 -0
  67. package/dist/themes/themes/default.d.ts.map +1 -1
  68. package/dist/themes/themes/default.esm.js +4 -1
  69. package/dist/themes/themes/default.js +4 -1
  70. package/dist/themes/themes/harvey.d.ts.map +1 -1
  71. package/dist/themes/themes/harvey.esm.js +4 -1
  72. package/dist/themes/themes/harvey.js +4 -1
  73. package/dist/themes/types.d.ts +62 -0
  74. package/dist/themes/types.d.ts.map +1 -1
  75. package/dist/themes/validation.d.ts +17 -0
  76. package/dist/themes/validation.d.ts.map +1 -1
  77. package/dist/themes/validation.esm.js +218 -0
  78. package/dist/themes/validation.js +218 -0
  79. package/dist/types.d.ts +62 -0
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/utils/progressive-css-injector.d.ts +80 -0
  82. package/dist/utils/progressive-css-injector.d.ts.map +1 -0
  83. package/dist/utils/progressive-css-injector.esm.js +217 -0
  84. package/dist/utils/progressive-css-injector.js +217 -0
  85. package/package.json +1 -1
  86. package/src/components/ui/button.tsx +9 -6
  87. package/src/components/ui/layout/container.tsx +312 -0
  88. package/src/components/ui/layout/index.ts +10 -0
  89. package/src/components/ui/layout/responsive-grid.tsx +286 -0
  90. package/src/components/ui/layouts/adaptive-layout.tsx +3 -1
  91. package/src/components/ui/navigation/index.ts +2 -0
  92. package/src/components/ui/navigation/progressive-navigation.tsx +453 -0
  93. package/src/components/ui/navigation/types.ts +41 -0
  94. package/src/hooks/use-adaptive-layout.ts +13 -9
  95. package/src/hooks/use-device.tsx +17 -10
  96. package/src/index.ts +19 -4
  97. package/src/plugins/css-purge-optimizer.ts +491 -0
  98. package/src/plugins/performance-monitor.ts +292 -0
  99. package/src/plugins/progressive-css-loader.ts +269 -0
  100. package/src/plugins/theme-css-generator.ts +22 -6
  101. package/src/styles/components/base/badge.css +2 -2
  102. package/src/styles/components/base/button.css +238 -35
  103. package/src/styles/components/base/card.css +2 -2
  104. package/src/styles/components/base/checkbox.css +3 -3
  105. package/src/styles/components/base/label.css +3 -3
  106. package/src/styles/components/feedback/skeleton.css +1 -1
  107. package/src/styles/components/feedback/toast.css +1 -1
  108. package/src/styles/components/index.css +3 -0
  109. package/src/styles/components/layout/container.css +466 -0
  110. package/src/styles/components/layout/index.css +5 -0
  111. package/src/styles/components/layout/responsive-grid.css +422 -0
  112. package/src/styles/components/navigation/breadcrumb.css +1 -1
  113. package/src/styles/components/navigation/index.css +1 -0
  114. package/src/styles/components/navigation/menu.css +2 -2
  115. package/src/styles/components/navigation/pagination.css +4 -4
  116. package/src/styles/components/navigation/progressive-navigation.css +633 -0
  117. package/src/styles/components/navigation/sidebar.css +4 -4
  118. package/src/styles/components/navigation/stepper.css +2 -2
  119. package/src/styles/components/navigation/tabs.css +1 -1
  120. package/src/styles/components/ui/theme-toggle.css +2 -2
  121. package/src/styles/progressive.css +17 -0
  122. package/src/styles/themes/harvey.css +103 -19
  123. package/src/styles/utilities/semantic-input-system.css +7 -13
  124. package/src/theme.ts +5 -1
  125. package/src/themes/phase1-constants.ts +189 -0
  126. package/src/themes/themes/default.ts +5 -1
  127. package/src/themes/themes/harvey.ts +5 -1
  128. package/src/themes/types.ts +77 -1
  129. package/src/themes/validation.ts +249 -0
  130. package/src/types.ts +77 -1
  131. package/src/utils/progressive-css-injector.ts +254 -0
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Progressive CSS Loader Plugin
3
+ * Implements Phase 3 Performance Optimization: Progressive Enhancement Loading
4
+ *
5
+ * Separates CSS into:
6
+ * - Critical: xs-md breakpoints (mobile-tablet) - loaded immediately
7
+ * - Progressive: lg-3xl breakpoints (desktop+) - loaded on demand
8
+ */
9
+ import postcss from 'postcss';
10
+ const DEFAULT_CONFIG = {
11
+ critical: ['xs', 'sm', 'md'],
12
+ progressive: ['lg', 'xl', '2xl', '3xl'],
13
+ progressivePath: 'progressive.css'
14
+ };
15
+ export default function progressiveCSSLoader(config = {}) {
16
+ const finalConfig = { ...DEFAULT_CONFIG, ...config };
17
+ return {
18
+ name: 'progressive-css-loader',
19
+ apply: 'build',
20
+ generateBundle(_options, bundle) {
21
+ // Find CSS assets in bundle
22
+ const cssAssets = Object.keys(bundle).filter(key => key.endsWith('.css'));
23
+ cssAssets.forEach((assetKey, index) => {
24
+ const asset = bundle[assetKey];
25
+ if (asset.type === 'asset' && typeof asset.source === 'string') {
26
+ const originalSource = asset.source;
27
+ // Safely separate CSS into critical and progressive parts
28
+ const { critical, progressive } = separateCSS(originalSource, finalConfig);
29
+ const originalSize = Math.round(originalSource.length / 1024);
30
+ const criticalSize = Math.round(critical.length / 1024);
31
+ const progressiveSize = Math.round(progressive.length / 1024);
32
+ console.log(` Split ${assetKey}: ${originalSize}KB -> ${criticalSize}KB critical + ${progressiveSize}KB progressive`);
33
+ // Update the main CSS asset to contain only critical CSS
34
+ asset.source = critical;
35
+ // Create separate progressive CSS file with unique naming for desktop enhancement
36
+ if (progressive.trim()) {
37
+ const progressiveFileName = index === 0
38
+ ? finalConfig.progressivePath
39
+ : finalConfig.progressivePath.replace('.css', `-${index}.css`);
40
+ this.emitFile({
41
+ type: 'asset',
42
+ fileName: progressiveFileName,
43
+ source: progressive
44
+ });
45
+ console.log(` Created ${progressiveFileName} for desktop enhancement (${progressiveSize}KB)`);
46
+ }
47
+ // Skip creating explicit critical CSS file since main bundle already contains critical styles
48
+ }
49
+ });
50
+ }
51
+ };
52
+ }
53
+ /**
54
+ * CSS Variable to pixel value mapping based on design system
55
+ * This provides the authoritative mapping for breakpoint classification
56
+ */
57
+ const BREAKPOINT_VALUES = {
58
+ 'xs': 475,
59
+ 'sm': 640,
60
+ 'mobile': 640,
61
+ 'md': 768,
62
+ 'tablet': 768,
63
+ 'lg': 1024,
64
+ 'desktop': 1024,
65
+ 'xl': 1280,
66
+ 'wide': 1280,
67
+ '2xl': 1536,
68
+ 'ultra': 1536,
69
+ '3xl': 1920
70
+ };
71
+ /**
72
+ * Desktop breakpoint threshold - anything >= 1024px is considered desktop
73
+ */
74
+ const DESKTOP_THRESHOLD = 1024;
75
+ /**
76
+ * Determines if a media query represents a desktop breakpoint
77
+ * Uses CSS variable resolution to properly classify breakpoints
78
+ */
79
+ function isDesktopMediaQuery(mediaQuery) {
80
+ // Skip max-width queries - they should always stay in critical CSS
81
+ if (mediaQuery.includes('max-width')) {
82
+ return false;
83
+ }
84
+ // Check for CSS variable-based breakpoints
85
+ const variableMatch = mediaQuery.match(/var\(--cs-breakpoints-([^)]+)\)/);
86
+ if (variableMatch) {
87
+ const breakpointName = variableMatch[1];
88
+ const pixelValue = BREAKPOINT_VALUES[breakpointName];
89
+ if (pixelValue !== undefined) {
90
+ return pixelValue >= DESKTOP_THRESHOLD;
91
+ }
92
+ // If we don't recognize the variable, log it and assume it's critical for safety
93
+ console.warn(`Unknown breakpoint variable: --cs-breakpoints-${breakpointName}`);
94
+ return false;
95
+ }
96
+ // Check for direct pixel values
97
+ const pixelMatch = mediaQuery.match(/min-width:\s*(\d+)px/);
98
+ if (pixelMatch) {
99
+ const pixelValue = parseInt(pixelMatch[1], 10);
100
+ return pixelValue >= DESKTOP_THRESHOLD;
101
+ }
102
+ // If we can't classify it, keep it in critical CSS for safety
103
+ return false;
104
+ }
105
+ /**
106
+ * Safely separates CSS content into critical and progressive sections
107
+ * Critical: < 1024px breakpoints (mobile/tablet) + base styles
108
+ * Progressive: >= 1024px breakpoints (desktop+) only
109
+ */
110
+ function separateCSS(cssContent, _config) {
111
+ try {
112
+ const desktopRules = [];
113
+ // Parse CSS using PostCSS
114
+ const root = postcss.parse(cssContent);
115
+ // Walk through all rules and find desktop media queries
116
+ root.walkAtRules('media', (rule) => {
117
+ const mediaQuery = rule.params;
118
+ const shouldExtract = isDesktopMediaQuery(mediaQuery);
119
+ if (shouldExtract) {
120
+ // Convert the rule back to CSS string and collect it
121
+ desktopRules.push(rule.toString());
122
+ // Remove the rule from the original AST
123
+ rule.remove();
124
+ }
125
+ });
126
+ // Generate the critical CSS (without desktop rules)
127
+ const criticalCSS = root.toString();
128
+ const progressiveCSS = desktopRules.join('\n');
129
+ // Validate CSS syntax by checking for balanced braces
130
+ const criticalOpenBraces = (criticalCSS.match(/\{/g) || []).length;
131
+ const criticalCloseBraces = (criticalCSS.match(/\}/g) || []).length;
132
+ const progressiveOpenBraces = (progressiveCSS.match(/\{/g) || []).length;
133
+ const progressiveCloseBraces = (progressiveCSS.match(/\}/g) || []).length;
134
+ if (criticalOpenBraces !== criticalCloseBraces) {
135
+ console.error(`PostCSS extraction created malformed critical CSS: ${criticalOpenBraces} open braces vs ${criticalCloseBraces} close braces`);
136
+ console.log('Falling back to original CSS to avoid syntax errors');
137
+ return {
138
+ critical: cssContent,
139
+ progressive: ''
140
+ };
141
+ }
142
+ if (progressiveOpenBraces !== progressiveCloseBraces) {
143
+ console.error(`PostCSS extraction created malformed progressive CSS: ${progressiveOpenBraces} open braces vs ${progressiveCloseBraces} close braces`);
144
+ console.log('Falling back to original CSS to avoid syntax errors');
145
+ return {
146
+ critical: cssContent,
147
+ progressive: ''
148
+ };
149
+ }
150
+ console.log(`CSS separation: Extracted ${desktopRules.length} desktop-only media queries using PostCSS`);
151
+ // Note: Any remaining CSS syntax warnings are from pre-existing CSS generation issues,
152
+ // not from the progressive CSS extraction process
153
+ return {
154
+ critical: criticalCSS,
155
+ progressive: progressiveCSS
156
+ };
157
+ }
158
+ catch (error) {
159
+ console.error('PostCSS separation failed, falling back to original CSS:', error);
160
+ return {
161
+ critical: cssContent,
162
+ progressive: ''
163
+ };
164
+ }
165
+ }
166
+ /**
167
+ * Creates progressive CSS loading script for runtime
168
+ */
169
+ export function createProgressiveLoader() {
170
+ return `
171
+ // Progressive CSS Loader - Phase 3 Performance Optimization
172
+ (function() {
173
+ 'use strict';
174
+
175
+ const DESKTOP_BREAKPOINT = 1024; // lg breakpoint
176
+ const PROGRESSIVE_CSS_PATH = '/assets/progressive.css';
177
+
178
+ let progressiveCSSLoaded = false;
179
+
180
+ function loadProgressiveCSS() {
181
+ if (progressiveCSSLoaded) return;
182
+
183
+ const link = document.createElement('link');
184
+ link.rel = 'stylesheet';
185
+ link.href = PROGRESSIVE_CSS_PATH;
186
+ link.media = 'screen and (min-width: ' + DESKTOP_BREAKPOINT + 'px)';
187
+
188
+ // Load asynchronously for non-blocking
189
+ link.onload = function() {
190
+ console.log('Progressive CSS loaded for desktop');
191
+ progressiveCSSLoaded = true;
192
+ };
193
+
194
+ document.head.appendChild(link);
195
+ }
196
+
197
+ function checkViewport() {
198
+ if (window.innerWidth >= DESKTOP_BREAKPOINT) {
199
+ loadProgressiveCSS();
200
+ }
201
+ }
202
+
203
+ // Load on resize to desktop
204
+ let resizeTimeout;
205
+ window.addEventListener('resize', function() {
206
+ clearTimeout(resizeTimeout);
207
+ resizeTimeout = setTimeout(checkViewport, 150);
208
+ });
209
+
210
+ // Check initial viewport
211
+ if (document.readyState === 'loading') {
212
+ document.addEventListener('DOMContentLoaded', checkViewport);
213
+ } else {
214
+ checkViewport();
215
+ }
216
+
217
+ // Preload for fast desktop switches
218
+ if (window.innerWidth >= 768) { // tablet+
219
+ const preload = document.createElement('link');
220
+ preload.rel = 'preload';
221
+ preload.href = PROGRESSIVE_CSS_PATH;
222
+ preload.as = 'style';
223
+ document.head.appendChild(preload);
224
+ }
225
+ })();
226
+ `;
227
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"theme-css-generator.d.ts","sourceRoot":"","sources":["../../src/plugins/theme-css-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAIlC,MAAM,CAAC,OAAO,UAAU,iBAAiB,IAAI,MAAM,CAuTlD"}
1
+ {"version":3,"file":"theme-css-generator.d.ts","sourceRoot":"","sources":["../../src/plugins/theme-css-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAIlC,MAAM,CAAC,OAAO,UAAU,iBAAiB,IAAI,MAAM,CAuUlD"}
@@ -89,7 +89,7 @@ export default function themeCSSGenerator() {
89
89
  return fonts?.[fontKey]?.source?.type === 'google';
90
90
  };
91
91
  // Recursively generate CSS variables from theme object
92
- const generateCSSVariables = (obj, path = [], rootTheme) => {
92
+ const generateCSSVariables = (obj, path = [], rootTheme, localVars = new Set()) => {
93
93
  let css = '';
94
94
  if (typeof obj !== 'object' || obj === null) {
95
95
  return css;
@@ -104,19 +104,31 @@ export default function themeCSSGenerator() {
104
104
  return;
105
105
  }
106
106
  }
107
+ // Skip breakpoints as they're handled by generateBreakpointVariables
108
+ if (key === 'breakpoints') {
109
+ return;
110
+ }
107
111
  if (typeof value === 'string' || typeof value === 'number') {
108
112
  // Generate CSS variable for primitive values
109
113
  const cssVarName = createCSSVarName(currentPath);
110
- css += ` ${cssVarName}: ${value};\n`;
114
+ // Only prevent duplicates within the same traversal (same CSS rule block)
115
+ if (!localVars.has(cssVarName)) {
116
+ css += ` ${cssVarName}: ${value};\n`;
117
+ localVars.add(cssVarName);
118
+ }
111
119
  }
112
120
  else if (Array.isArray(value)) {
113
121
  // Handle arrays (like font weights, tags)
114
122
  const cssVarName = createCSSVarName(currentPath);
115
- css += ` ${cssVarName}: ${valueToString(value)};\n`;
123
+ // Only prevent duplicates within the same traversal (same CSS rule block)
124
+ if (!localVars.has(cssVarName)) {
125
+ css += ` ${cssVarName}: ${valueToString(value)};\n`;
126
+ localVars.add(cssVarName);
127
+ }
116
128
  }
117
129
  else if (typeof value === 'object' && value !== null) {
118
130
  // Recursively process nested objects
119
- css += generateCSSVariables(value, currentPath, rootTheme);
131
+ css += generateCSSVariables(value, currentPath, rootTheme, localVars);
120
132
  }
121
133
  });
122
134
  return css;
@@ -138,8 +150,9 @@ export default function themeCSSGenerator() {
138
150
  css += ` /* Light Mode Variables */\n`;
139
151
  // NEW: Generate breakpoint variables first
140
152
  css += generateBreakpointVariables(breakpoints);
141
- // Generate all other CSS variables
142
- css += generateCSSVariables(themeObj, [], themeObj);
153
+ // Generate all other CSS variables (each CSS block has its own scope)
154
+ const localVars = new Set();
155
+ css += generateCSSVariables(themeObj, [], themeObj, localVars);
143
156
  css += '}\n\n';
144
157
  // Generate dark mode variables
145
158
  css += `.dark {\n`;
@@ -89,7 +89,7 @@ export default function themeCSSGenerator() {
89
89
  return fonts?.[fontKey]?.source?.type === 'google';
90
90
  };
91
91
  // Recursively generate CSS variables from theme object
92
- const generateCSSVariables = (obj, path = [], rootTheme) => {
92
+ const generateCSSVariables = (obj, path = [], rootTheme, localVars = new Set()) => {
93
93
  let css = '';
94
94
  if (typeof obj !== 'object' || obj === null) {
95
95
  return css;
@@ -104,19 +104,31 @@ export default function themeCSSGenerator() {
104
104
  return;
105
105
  }
106
106
  }
107
+ // Skip breakpoints as they're handled by generateBreakpointVariables
108
+ if (key === 'breakpoints') {
109
+ return;
110
+ }
107
111
  if (typeof value === 'string' || typeof value === 'number') {
108
112
  // Generate CSS variable for primitive values
109
113
  const cssVarName = createCSSVarName(currentPath);
110
- css += ` ${cssVarName}: ${value};\n`;
114
+ // Only prevent duplicates within the same traversal (same CSS rule block)
115
+ if (!localVars.has(cssVarName)) {
116
+ css += ` ${cssVarName}: ${value};\n`;
117
+ localVars.add(cssVarName);
118
+ }
111
119
  }
112
120
  else if (Array.isArray(value)) {
113
121
  // Handle arrays (like font weights, tags)
114
122
  const cssVarName = createCSSVarName(currentPath);
115
- css += ` ${cssVarName}: ${valueToString(value)};\n`;
123
+ // Only prevent duplicates within the same traversal (same CSS rule block)
124
+ if (!localVars.has(cssVarName)) {
125
+ css += ` ${cssVarName}: ${valueToString(value)};\n`;
126
+ localVars.add(cssVarName);
127
+ }
116
128
  }
117
129
  else if (typeof value === 'object' && value !== null) {
118
130
  // Recursively process nested objects
119
- css += generateCSSVariables(value, currentPath, rootTheme);
131
+ css += generateCSSVariables(value, currentPath, rootTheme, localVars);
120
132
  }
121
133
  });
122
134
  return css;
@@ -138,8 +150,9 @@ export default function themeCSSGenerator() {
138
150
  css += ` /* Light Mode Variables */\n`;
139
151
  // NEW: Generate breakpoint variables first
140
152
  css += generateBreakpointVariables(breakpoints);
141
- // Generate all other CSS variables
142
- css += generateCSSVariables(themeObj, [], themeObj);
153
+ // Generate all other CSS variables (each CSS block has its own scope)
154
+ const localVars = new Set();
155
+ css += generateCSSVariables(themeObj, [], themeObj, localVars);
143
156
  css += '}\n\n';
144
157
  // Generate dark mode variables
145
158
  css += `.dark {\n`;