@tekton-ui/core 0.2.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 (254) hide show
  1. package/README.md +758 -0
  2. package/dist/blueprint.d.ts +44 -0
  3. package/dist/blueprint.d.ts.map +1 -0
  4. package/dist/blueprint.js +163 -0
  5. package/dist/blueprint.js.map +1 -0
  6. package/dist/component-schemas.d.ts +78 -0
  7. package/dist/component-schemas.d.ts.map +1 -0
  8. package/dist/component-schemas.js +1037 -0
  9. package/dist/component-schemas.js.map +1 -0
  10. package/dist/css-generator.d.ts +42 -0
  11. package/dist/css-generator.d.ts.map +1 -0
  12. package/dist/css-generator.js +339 -0
  13. package/dist/css-generator.js.map +1 -0
  14. package/dist/icon-library.d.ts +109 -0
  15. package/dist/icon-library.d.ts.map +1 -0
  16. package/dist/icon-library.js +204 -0
  17. package/dist/icon-library.js.map +1 -0
  18. package/dist/index.d.ts +36 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +51 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/layout-css-generator.d.ts +158 -0
  23. package/dist/layout-css-generator.d.ts.map +1 -0
  24. package/dist/layout-css-generator.js +901 -0
  25. package/dist/layout-css-generator.js.map +1 -0
  26. package/dist/layout-resolver.d.ts +92 -0
  27. package/dist/layout-resolver.d.ts.map +1 -0
  28. package/dist/layout-resolver.js +275 -0
  29. package/dist/layout-resolver.js.map +1 -0
  30. package/dist/layout-tokens/index.d.ts +16 -0
  31. package/dist/layout-tokens/index.d.ts.map +1 -0
  32. package/dist/layout-tokens/index.js +16 -0
  33. package/dist/layout-tokens/index.js.map +1 -0
  34. package/dist/layout-tokens/keyboard.d.ts +254 -0
  35. package/dist/layout-tokens/keyboard.d.ts.map +1 -0
  36. package/dist/layout-tokens/keyboard.js +407 -0
  37. package/dist/layout-tokens/keyboard.js.map +1 -0
  38. package/dist/layout-tokens/mobile-shells.d.ts +78 -0
  39. package/dist/layout-tokens/mobile-shells.d.ts.map +1 -0
  40. package/dist/layout-tokens/mobile-shells.js +635 -0
  41. package/dist/layout-tokens/mobile-shells.js.map +1 -0
  42. package/dist/layout-tokens/pages.d.ts +100 -0
  43. package/dist/layout-tokens/pages.d.ts.map +1 -0
  44. package/dist/layout-tokens/pages.js +576 -0
  45. package/dist/layout-tokens/pages.js.map +1 -0
  46. package/dist/layout-tokens/responsive.d.ts +109 -0
  47. package/dist/layout-tokens/responsive.d.ts.map +1 -0
  48. package/dist/layout-tokens/responsive.js +167 -0
  49. package/dist/layout-tokens/responsive.js.map +1 -0
  50. package/dist/layout-tokens/safe-area.d.ts +156 -0
  51. package/dist/layout-tokens/safe-area.d.ts.map +1 -0
  52. package/dist/layout-tokens/safe-area.js +316 -0
  53. package/dist/layout-tokens/safe-area.js.map +1 -0
  54. package/dist/layout-tokens/sections-advanced.d.ts +277 -0
  55. package/dist/layout-tokens/sections-advanced.d.ts.map +1 -0
  56. package/dist/layout-tokens/sections-advanced.js +593 -0
  57. package/dist/layout-tokens/sections-advanced.js.map +1 -0
  58. package/dist/layout-tokens/sections.d.ts +137 -0
  59. package/dist/layout-tokens/sections.d.ts.map +1 -0
  60. package/dist/layout-tokens/sections.js +694 -0
  61. package/dist/layout-tokens/sections.js.map +1 -0
  62. package/dist/layout-tokens/shells.d.ts +77 -0
  63. package/dist/layout-tokens/shells.d.ts.map +1 -0
  64. package/dist/layout-tokens/shells.js +408 -0
  65. package/dist/layout-tokens/shells.js.map +1 -0
  66. package/dist/layout-tokens/touch-target.d.ts +119 -0
  67. package/dist/layout-tokens/touch-target.d.ts.map +1 -0
  68. package/dist/layout-tokens/touch-target.js +156 -0
  69. package/dist/layout-tokens/touch-target.js.map +1 -0
  70. package/dist/layout-tokens/types.d.ts +632 -0
  71. package/dist/layout-tokens/types.d.ts.map +1 -0
  72. package/dist/layout-tokens/types.js +49 -0
  73. package/dist/layout-tokens/types.js.map +1 -0
  74. package/dist/layout-validation.d.ts +1547 -0
  75. package/dist/layout-validation.d.ts.map +1 -0
  76. package/dist/layout-validation.js +628 -0
  77. package/dist/layout-validation.js.map +1 -0
  78. package/dist/render.d.ts +23 -0
  79. package/dist/render.d.ts.map +1 -0
  80. package/dist/render.js +244 -0
  81. package/dist/render.js.map +1 -0
  82. package/dist/schema-validation.d.ts +208 -0
  83. package/dist/schema-validation.d.ts.map +1 -0
  84. package/dist/schema-validation.js +205 -0
  85. package/dist/schema-validation.js.map +1 -0
  86. package/dist/screen-generation/generators/css-in-js-generator.d.ts +82 -0
  87. package/dist/screen-generation/generators/css-in-js-generator.d.ts.map +1 -0
  88. package/dist/screen-generation/generators/css-in-js-generator.js +335 -0
  89. package/dist/screen-generation/generators/css-in-js-generator.js.map +1 -0
  90. package/dist/screen-generation/generators/index.d.ts +13 -0
  91. package/dist/screen-generation/generators/index.d.ts.map +1 -0
  92. package/dist/screen-generation/generators/index.js +32 -0
  93. package/dist/screen-generation/generators/index.js.map +1 -0
  94. package/dist/screen-generation/generators/react-generator.d.ts +100 -0
  95. package/dist/screen-generation/generators/react-generator.d.ts.map +1 -0
  96. package/dist/screen-generation/generators/react-generator.js +379 -0
  97. package/dist/screen-generation/generators/react-generator.js.map +1 -0
  98. package/dist/screen-generation/generators/tailwind-generator.d.ts +105 -0
  99. package/dist/screen-generation/generators/tailwind-generator.d.ts.map +1 -0
  100. package/dist/screen-generation/generators/tailwind-generator.js +355 -0
  101. package/dist/screen-generation/generators/tailwind-generator.js.map +1 -0
  102. package/dist/screen-generation/generators/types.d.ts +136 -0
  103. package/dist/screen-generation/generators/types.d.ts.map +1 -0
  104. package/dist/screen-generation/generators/types.js +18 -0
  105. package/dist/screen-generation/generators/types.js.map +1 -0
  106. package/dist/screen-generation/generators/utils.d.ts +187 -0
  107. package/dist/screen-generation/generators/utils.d.ts.map +1 -0
  108. package/dist/screen-generation/generators/utils.js +312 -0
  109. package/dist/screen-generation/generators/utils.js.map +1 -0
  110. package/dist/screen-generation/index.d.ts +14 -0
  111. package/dist/screen-generation/index.d.ts.map +1 -0
  112. package/dist/screen-generation/index.js +33 -0
  113. package/dist/screen-generation/index.js.map +1 -0
  114. package/dist/screen-generation/resolver/component-resolver.d.ts +157 -0
  115. package/dist/screen-generation/resolver/component-resolver.d.ts.map +1 -0
  116. package/dist/screen-generation/resolver/component-resolver.js +295 -0
  117. package/dist/screen-generation/resolver/component-resolver.js.map +1 -0
  118. package/dist/screen-generation/resolver/index.d.ts +10 -0
  119. package/dist/screen-generation/resolver/index.d.ts.map +1 -0
  120. package/dist/screen-generation/resolver/index.js +46 -0
  121. package/dist/screen-generation/resolver/index.js.map +1 -0
  122. package/dist/screen-generation/resolver/layout-resolver.d.ts +155 -0
  123. package/dist/screen-generation/resolver/layout-resolver.d.ts.map +1 -0
  124. package/dist/screen-generation/resolver/layout-resolver.js +193 -0
  125. package/dist/screen-generation/resolver/layout-resolver.js.map +1 -0
  126. package/dist/screen-generation/resolver/screen-resolver.d.ts +174 -0
  127. package/dist/screen-generation/resolver/screen-resolver.d.ts.map +1 -0
  128. package/dist/screen-generation/resolver/screen-resolver.js +373 -0
  129. package/dist/screen-generation/resolver/screen-resolver.js.map +1 -0
  130. package/dist/screen-generation/resolver/token-resolver.d.ts +170 -0
  131. package/dist/screen-generation/resolver/token-resolver.d.ts.map +1 -0
  132. package/dist/screen-generation/resolver/token-resolver.js +260 -0
  133. package/dist/screen-generation/resolver/token-resolver.js.map +1 -0
  134. package/dist/screen-generation/types.d.ts +116 -0
  135. package/dist/screen-generation/types.d.ts.map +1 -0
  136. package/dist/screen-generation/types.js +33 -0
  137. package/dist/screen-generation/types.js.map +1 -0
  138. package/dist/screen-generation/validators.d.ts +286 -0
  139. package/dist/screen-generation/validators.d.ts.map +1 -0
  140. package/dist/screen-generation/validators.js +323 -0
  141. package/dist/screen-generation/validators.js.map +1 -0
  142. package/dist/screen-templates/__tests__/registry.test.d.ts +6 -0
  143. package/dist/screen-templates/__tests__/registry.test.d.ts.map +1 -0
  144. package/dist/screen-templates/__tests__/registry.test.js +247 -0
  145. package/dist/screen-templates/__tests__/registry.test.js.map +1 -0
  146. package/dist/screen-templates/__tests__/templates.test.d.ts +6 -0
  147. package/dist/screen-templates/__tests__/templates.test.d.ts.map +1 -0
  148. package/dist/screen-templates/__tests__/templates.test.js +179 -0
  149. package/dist/screen-templates/__tests__/templates.test.js.map +1 -0
  150. package/dist/screen-templates/index.d.ts +39 -0
  151. package/dist/screen-templates/index.d.ts.map +1 -0
  152. package/dist/screen-templates/index.js +79 -0
  153. package/dist/screen-templates/index.js.map +1 -0
  154. package/dist/screen-templates/registry.d.ts +177 -0
  155. package/dist/screen-templates/registry.d.ts.map +1 -0
  156. package/dist/screen-templates/registry.js +274 -0
  157. package/dist/screen-templates/registry.js.map +1 -0
  158. package/dist/screen-templates/templates/account/index.d.ts +6 -0
  159. package/dist/screen-templates/templates/account/index.d.ts.map +1 -0
  160. package/dist/screen-templates/templates/account/index.js +6 -0
  161. package/dist/screen-templates/templates/account/index.js.map +1 -0
  162. package/dist/screen-templates/templates/account/profile.d.ts +23 -0
  163. package/dist/screen-templates/templates/account/profile.d.ts.map +1 -0
  164. package/dist/screen-templates/templates/account/profile.js +249 -0
  165. package/dist/screen-templates/templates/account/profile.js.map +1 -0
  166. package/dist/screen-templates/templates/auth/forgot-password.d.ts +23 -0
  167. package/dist/screen-templates/templates/auth/forgot-password.d.ts.map +1 -0
  168. package/dist/screen-templates/templates/auth/forgot-password.js +203 -0
  169. package/dist/screen-templates/templates/auth/forgot-password.js.map +1 -0
  170. package/dist/screen-templates/templates/auth/index.d.ts +9 -0
  171. package/dist/screen-templates/templates/auth/index.d.ts.map +1 -0
  172. package/dist/screen-templates/templates/auth/index.js +9 -0
  173. package/dist/screen-templates/templates/auth/index.js.map +1 -0
  174. package/dist/screen-templates/templates/auth/login.d.ts +24 -0
  175. package/dist/screen-templates/templates/auth/login.d.ts.map +1 -0
  176. package/dist/screen-templates/templates/auth/login.js +254 -0
  177. package/dist/screen-templates/templates/auth/login.js.map +1 -0
  178. package/dist/screen-templates/templates/auth/signup.d.ts +24 -0
  179. package/dist/screen-templates/templates/auth/signup.d.ts.map +1 -0
  180. package/dist/screen-templates/templates/auth/signup.js +315 -0
  181. package/dist/screen-templates/templates/auth/signup.js.map +1 -0
  182. package/dist/screen-templates/templates/auth/verification.d.ts +23 -0
  183. package/dist/screen-templates/templates/auth/verification.d.ts.map +1 -0
  184. package/dist/screen-templates/templates/auth/verification.js +239 -0
  185. package/dist/screen-templates/templates/auth/verification.js.map +1 -0
  186. package/dist/screen-templates/templates/feedback/confirmation.d.ts +9 -0
  187. package/dist/screen-templates/templates/feedback/confirmation.d.ts.map +1 -0
  188. package/dist/screen-templates/templates/feedback/confirmation.js +107 -0
  189. package/dist/screen-templates/templates/feedback/confirmation.js.map +1 -0
  190. package/dist/screen-templates/templates/feedback/empty.d.ts +9 -0
  191. package/dist/screen-templates/templates/feedback/empty.d.ts.map +1 -0
  192. package/dist/screen-templates/templates/feedback/empty.js +90 -0
  193. package/dist/screen-templates/templates/feedback/empty.js.map +1 -0
  194. package/dist/screen-templates/templates/feedback/error.d.ts +9 -0
  195. package/dist/screen-templates/templates/feedback/error.d.ts.map +1 -0
  196. package/dist/screen-templates/templates/feedback/error.js +99 -0
  197. package/dist/screen-templates/templates/feedback/error.js.map +1 -0
  198. package/dist/screen-templates/templates/feedback/index.d.ts +10 -0
  199. package/dist/screen-templates/templates/feedback/index.d.ts.map +1 -0
  200. package/dist/screen-templates/templates/feedback/index.js +10 -0
  201. package/dist/screen-templates/templates/feedback/index.js.map +1 -0
  202. package/dist/screen-templates/templates/feedback/loading.d.ts +9 -0
  203. package/dist/screen-templates/templates/feedback/loading.d.ts.map +1 -0
  204. package/dist/screen-templates/templates/feedback/loading.js +77 -0
  205. package/dist/screen-templates/templates/feedback/loading.js.map +1 -0
  206. package/dist/screen-templates/templates/feedback/success.d.ts +9 -0
  207. package/dist/screen-templates/templates/feedback/success.d.ts.map +1 -0
  208. package/dist/screen-templates/templates/feedback/success.js +99 -0
  209. package/dist/screen-templates/templates/feedback/success.js.map +1 -0
  210. package/dist/screen-templates/templates/home/index.d.ts +6 -0
  211. package/dist/screen-templates/templates/home/index.d.ts.map +1 -0
  212. package/dist/screen-templates/templates/home/index.js +6 -0
  213. package/dist/screen-templates/templates/home/index.js.map +1 -0
  214. package/dist/screen-templates/templates/home/landing.d.ts +24 -0
  215. package/dist/screen-templates/templates/home/landing.d.ts.map +1 -0
  216. package/dist/screen-templates/templates/home/landing.js +197 -0
  217. package/dist/screen-templates/templates/home/landing.js.map +1 -0
  218. package/dist/screen-templates/templates/settings/index.d.ts +6 -0
  219. package/dist/screen-templates/templates/settings/index.d.ts.map +1 -0
  220. package/dist/screen-templates/templates/settings/index.js +6 -0
  221. package/dist/screen-templates/templates/settings/index.js.map +1 -0
  222. package/dist/screen-templates/templates/settings/preferences.d.ts +24 -0
  223. package/dist/screen-templates/templates/settings/preferences.d.ts.map +1 -0
  224. package/dist/screen-templates/templates/settings/preferences.js +265 -0
  225. package/dist/screen-templates/templates/settings/preferences.js.map +1 -0
  226. package/dist/screen-templates/types.d.ts +229 -0
  227. package/dist/screen-templates/types.d.ts.map +1 -0
  228. package/dist/screen-templates/types.js +7 -0
  229. package/dist/screen-templates/types.js.map +1 -0
  230. package/dist/theme-v2.d.ts +228 -0
  231. package/dist/theme-v2.d.ts.map +1 -0
  232. package/dist/theme-v2.js +158 -0
  233. package/dist/theme-v2.js.map +1 -0
  234. package/dist/theme.d.ts +60 -0
  235. package/dist/theme.d.ts.map +1 -0
  236. package/dist/theme.js +76 -0
  237. package/dist/theme.js.map +1 -0
  238. package/dist/token-resolver.d.ts +69 -0
  239. package/dist/token-resolver.d.ts.map +1 -0
  240. package/dist/token-resolver.js +122 -0
  241. package/dist/token-resolver.js.map +1 -0
  242. package/dist/token-validation.d.ts +432 -0
  243. package/dist/token-validation.d.ts.map +1 -0
  244. package/dist/token-validation.js +140 -0
  245. package/dist/token-validation.js.map +1 -0
  246. package/dist/tokens.d.ts +158 -0
  247. package/dist/tokens.d.ts.map +1 -0
  248. package/dist/tokens.js +10 -0
  249. package/dist/tokens.js.map +1 -0
  250. package/dist/types.d.ts +77 -0
  251. package/dist/types.d.ts.map +1 -0
  252. package/dist/types.js +7 -0
  253. package/dist/types.js.map +1 -0
  254. package/package.json +53 -0
@@ -0,0 +1,901 @@
1
+ /**
2
+ * @tekton-ui/core - Layout CSS Generator
3
+ * Generates CSS from layout tokens (shells, pages, sections)
4
+ * [SPEC-LAYOUT-001] [PHASE-8]
5
+ */
6
+ import { resolveTokenReference } from './layout-resolver.js';
7
+ import { getAllShellTokens } from './layout-tokens/shells.js';
8
+ import { getAllPageLayoutTokens } from './layout-tokens/pages.js';
9
+ import { getAllSectionPatternTokens } from './layout-tokens/sections.js';
10
+ import { getAllAdvancedSectionPatternTokens } from './layout-tokens/sections-advanced.js';
11
+ import { BREAKPOINT_VALUES } from './layout-tokens/responsive.js';
12
+ // ============================================================================
13
+ // Utility Functions
14
+ // ============================================================================
15
+ /**
16
+ * Extract CSS variable references from token references in an object
17
+ *
18
+ * @param obj - Object to extract token references from
19
+ * @returns Set of unique CSS variable names
20
+ */
21
+ function extractCSSVariables(obj) {
22
+ const vars = new Set();
23
+ function traverse(value) {
24
+ if (typeof value === 'string' && /^[a-z]+\.[a-z-]+(\.[a-z0-9-]+)*$/.test(value)) {
25
+ // This is a token reference - convert to CSS variable
26
+ vars.add(resolveTokenReference(value));
27
+ }
28
+ else if (typeof value === 'object' && value !== null) {
29
+ for (const prop of Object.values(value)) {
30
+ traverse(prop);
31
+ }
32
+ }
33
+ }
34
+ traverse(obj);
35
+ return vars;
36
+ }
37
+ /**
38
+ * Convert token reference to CSS var() function call
39
+ *
40
+ * @param ref - Token reference (e.g., "atomic.spacing.16")
41
+ * @returns CSS var() function (e.g., "var(--atomic-spacing-16)")
42
+ */
43
+ function tokenRefToVar(ref) {
44
+ return `var(${resolveTokenReference(ref)})`;
45
+ }
46
+ /**
47
+ * Validate CSS syntax (balanced braces)
48
+ *
49
+ * @param css - CSS string to validate
50
+ * @returns true if valid, false otherwise
51
+ */
52
+ export function validateCSS(css) {
53
+ const openBraces = (css.match(/{/g) || []).length;
54
+ const closeBraces = (css.match(/}/g) || []).length;
55
+ return openBraces === closeBraces;
56
+ }
57
+ /**
58
+ * Format CSS with proper indentation
59
+ *
60
+ * @param css - CSS string to format
61
+ * @param indent - Indentation string (default: 2 spaces)
62
+ * @returns Formatted CSS
63
+ */
64
+ export function formatCSS(css, indent = ' ') {
65
+ let formatted = '';
66
+ let indentLevel = 0;
67
+ let inMediaQuery = false;
68
+ // Split by lines and process each
69
+ const lines = css
70
+ .split('\n')
71
+ .map(line => line.trim())
72
+ .filter(line => line.length > 0);
73
+ for (const line of lines) {
74
+ // Decrease indent for closing braces
75
+ if (line === '}') {
76
+ indentLevel--;
77
+ if (inMediaQuery && indentLevel === 0) {
78
+ inMediaQuery = false;
79
+ }
80
+ }
81
+ // Add indented line
82
+ formatted += indent.repeat(indentLevel) + line + '\n';
83
+ // Increase indent for opening braces
84
+ if (line.endsWith('{')) {
85
+ indentLevel++;
86
+ if (line.startsWith('@media')) {
87
+ inMediaQuery = true;
88
+ }
89
+ }
90
+ }
91
+ return formatted;
92
+ }
93
+ // ============================================================================
94
+ // CSS Generation Functions
95
+ // ============================================================================
96
+ /**
97
+ * Generate CSS custom properties in :root from layout tokens
98
+ *
99
+ * @param tokens - Array of layout tokens
100
+ * @returns CSS :root block with custom properties
101
+ */
102
+ export function generateCSSVariables(tokens) {
103
+ const vars = new Set();
104
+ // Extract all CSS variables from all tokens
105
+ for (const token of tokens) {
106
+ const tokenVars = extractCSSVariables(token);
107
+ tokenVars.forEach(v => vars.add(v));
108
+ }
109
+ if (vars.size === 0) {
110
+ return '';
111
+ }
112
+ // Generate :root block
113
+ let css = ':root {\n';
114
+ // Sort variables for consistent output
115
+ const sortedVars = Array.from(vars).sort();
116
+ for (const cssVar of sortedVars) {
117
+ // Extract original token reference from CSS variable name
118
+ // --atomic-spacing-16 → atomic.spacing.16
119
+ const tokenRef = cssVar.replace(/^--/, '').replace(/-/g, '.');
120
+ css += ` ${cssVar}: ${tokenRef};\n`;
121
+ }
122
+ css += '}\n';
123
+ return css;
124
+ }
125
+ /**
126
+ * Generate utility classes for shell tokens
127
+ *
128
+ * @param shells - Array of shell tokens
129
+ * @returns CSS classes for shells
130
+ */
131
+ export function generateShellClasses(shells) {
132
+ let css = '';
133
+ for (const shell of shells) {
134
+ // Generate class name: .shell-{platform}-{name}
135
+ // shell.web.dashboard → .shell-web-dashboard
136
+ const className = shell.id.replace(/\./g, '-');
137
+ css += `.${className} {\n`;
138
+ css += ` display: grid;\n`;
139
+ // Generate grid template areas based on regions
140
+ const areas = [];
141
+ const positions = new Map();
142
+ // Group regions by position
143
+ for (const region of shell.regions) {
144
+ const pos = region.position;
145
+ if (!positions.has(pos)) {
146
+ positions.set(pos, []);
147
+ }
148
+ positions.get(pos).push(region.name);
149
+ }
150
+ // Build grid template areas
151
+ // Example: "header header" "sidebar main"
152
+ if (positions.has('top')) {
153
+ const topRegions = positions.get('top');
154
+ areas.push(`"${topRegions.join(' ')}"`);
155
+ }
156
+ // Middle row with left, center, right
157
+ const middleRow = [];
158
+ if (positions.has('left')) {
159
+ middleRow.push(...positions.get('left'));
160
+ }
161
+ if (positions.has('center')) {
162
+ middleRow.push(...positions.get('center'));
163
+ }
164
+ if (positions.has('right')) {
165
+ middleRow.push(...positions.get('right'));
166
+ }
167
+ if (middleRow.length > 0) {
168
+ areas.push(`"${middleRow.join(' ')}"`);
169
+ }
170
+ if (positions.has('bottom')) {
171
+ const bottomRegions = positions.get('bottom');
172
+ areas.push(`"${bottomRegions.join(' ')}"`);
173
+ }
174
+ if (areas.length > 0) {
175
+ css += ` grid-template-areas:\n`;
176
+ for (const area of areas) {
177
+ css += ` ${area}\n`;
178
+ }
179
+ }
180
+ css += `}\n\n`;
181
+ }
182
+ return css;
183
+ }
184
+ /**
185
+ * Generate utility classes for page tokens
186
+ *
187
+ * @param pages - Array of page layout tokens
188
+ * @returns CSS classes for pages
189
+ */
190
+ export function generatePageClasses(pages) {
191
+ let css = '';
192
+ for (const page of pages) {
193
+ // Generate class name: .page-{name}
194
+ // page.dashboard → .page-dashboard
195
+ const className = page.id.replace(/\./g, '-');
196
+ css += `.${className} {\n`;
197
+ css += ` display: flex;\n`;
198
+ css += ` flex-direction: column;\n`;
199
+ // Add gap if specified in tokenBindings
200
+ if (page.tokenBindings.sectionSpacing) {
201
+ const gapVar = tokenRefToVar(page.tokenBindings.sectionSpacing);
202
+ css += ` gap: ${gapVar};\n`;
203
+ }
204
+ css += `}\n\n`;
205
+ }
206
+ return css;
207
+ }
208
+ /**
209
+ * Generate utility classes for section pattern tokens
210
+ *
211
+ * @param sections - Array of section pattern tokens
212
+ * @returns CSS classes for sections
213
+ */
214
+ export function generateSectionClasses(sections) {
215
+ let css = '';
216
+ for (const section of sections) {
217
+ // Generate class name: .section-{pattern}
218
+ // section.grid-3 → .section-grid-3
219
+ const className = section.id.replace(/\./g, '-');
220
+ css += `.${className} {\n`;
221
+ // Add CSS properties from section.css
222
+ const sectionCSS = section.css;
223
+ if (sectionCSS.display) {
224
+ css += ` display: ${sectionCSS.display};\n`;
225
+ }
226
+ if (sectionCSS.gridTemplateColumns) {
227
+ css += ` grid-template-columns: ${sectionCSS.gridTemplateColumns};\n`;
228
+ }
229
+ if (sectionCSS.gridTemplateRows) {
230
+ css += ` grid-template-rows: ${sectionCSS.gridTemplateRows};\n`;
231
+ }
232
+ if (sectionCSS.gap) {
233
+ const gapValue = tokenRefToVar(sectionCSS.gap);
234
+ css += ` gap: ${gapValue};\n`;
235
+ }
236
+ if (sectionCSS.flexDirection) {
237
+ css += ` flex-direction: ${sectionCSS.flexDirection};\n`;
238
+ }
239
+ if (sectionCSS.alignItems) {
240
+ css += ` align-items: ${sectionCSS.alignItems};\n`;
241
+ }
242
+ if (sectionCSS.justifyContent) {
243
+ css += ` justify-content: ${sectionCSS.justifyContent};\n`;
244
+ }
245
+ if (sectionCSS.maxWidth) {
246
+ const maxWidthValue = tokenRefToVar(sectionCSS.maxWidth);
247
+ css += ` max-width: ${maxWidthValue};\n`;
248
+ }
249
+ if (sectionCSS.padding) {
250
+ const paddingValue = tokenRefToVar(sectionCSS.padding);
251
+ css += ` padding: ${paddingValue};\n`;
252
+ }
253
+ css += `}\n\n`;
254
+ }
255
+ return css;
256
+ }
257
+ /**
258
+ * Check if a token is an advanced section pattern
259
+ *
260
+ * @param token - Token to check
261
+ * @returns true if the token is an advanced section pattern (masonry, sticky, collapsible)
262
+ */
263
+ function isAdvancedSectionToken(token) {
264
+ if (!('type' in token)) {
265
+ return false;
266
+ }
267
+ const advancedTypes = ['masonry', 'sticky', 'collapsible'];
268
+ return advancedTypes.includes(token.type);
269
+ }
270
+ /**
271
+ * Generate utility classes for advanced section pattern tokens
272
+ * Handles masonry, sticky, and collapsible patterns
273
+ *
274
+ * @param sections - Array of advanced section pattern tokens
275
+ * @returns CSS classes for advanced sections
276
+ */
277
+ export function generateAdvancedSectionClasses(sections) {
278
+ let css = '';
279
+ for (const section of sections) {
280
+ // Generate class name: .section-{pattern}
281
+ // section.masonry → .section-masonry
282
+ const className = section.id.replace(/\./g, '-');
283
+ css += `.${className} {\n`;
284
+ const sectionCSS = section.css;
285
+ // Handle based on section type
286
+ if (section.type === 'masonry') {
287
+ const masonryCSS = sectionCSS;
288
+ // Masonry-specific properties
289
+ if (masonryCSS.columnCount) {
290
+ css += ` column-count: ${masonryCSS.columnCount};\n`;
291
+ }
292
+ if (masonryCSS.columnGap) {
293
+ const columnGapValue = tokenRefToVar(masonryCSS.columnGap);
294
+ css += ` column-gap: ${columnGapValue};\n`;
295
+ }
296
+ if (masonryCSS.breakInside) {
297
+ css += ` break-inside: ${masonryCSS.breakInside};\n`;
298
+ }
299
+ if (masonryCSS.columnFill) {
300
+ css += ` column-fill: ${masonryCSS.columnFill};\n`;
301
+ }
302
+ }
303
+ else if (section.type === 'sticky') {
304
+ const stickyCSS = sectionCSS;
305
+ // Common flex properties first
306
+ if (stickyCSS.display) {
307
+ css += ` display: ${stickyCSS.display};\n`;
308
+ }
309
+ if (stickyCSS.flexDirection) {
310
+ css += ` flex-direction: ${stickyCSS.flexDirection};\n`;
311
+ }
312
+ if (stickyCSS.alignItems) {
313
+ css += ` align-items: ${stickyCSS.alignItems};\n`;
314
+ }
315
+ if (stickyCSS.justifyContent) {
316
+ css += ` justify-content: ${stickyCSS.justifyContent};\n`;
317
+ }
318
+ if (stickyCSS.gap) {
319
+ const gapValue = tokenRefToVar(stickyCSS.gap);
320
+ css += ` gap: ${gapValue};\n`;
321
+ }
322
+ // Sticky-specific properties
323
+ if (stickyCSS.position) {
324
+ css += ` position: ${stickyCSS.position};\n`;
325
+ }
326
+ if (stickyCSS.top) {
327
+ const topValue = tokenRefToVar(stickyCSS.top);
328
+ css += ` top: ${topValue};\n`;
329
+ }
330
+ if (stickyCSS.bottom) {
331
+ const bottomValue = tokenRefToVar(stickyCSS.bottom);
332
+ css += ` bottom: ${bottomValue};\n`;
333
+ }
334
+ if (stickyCSS.zIndex !== undefined) {
335
+ css += ` z-index: ${stickyCSS.zIndex};\n`;
336
+ }
337
+ if (stickyCSS.padding) {
338
+ const paddingValue = tokenRefToVar(stickyCSS.padding);
339
+ css += ` padding: ${paddingValue};\n`;
340
+ }
341
+ if (stickyCSS.backgroundColor) {
342
+ const bgValue = tokenRefToVar(stickyCSS.backgroundColor);
343
+ css += ` background-color: ${bgValue};\n`;
344
+ }
345
+ if (stickyCSS.boxShadow) {
346
+ const shadowValue = tokenRefToVar(stickyCSS.boxShadow);
347
+ css += ` box-shadow: ${shadowValue};\n`;
348
+ }
349
+ }
350
+ else if (section.type === 'collapsible') {
351
+ const collapsibleCSS = sectionCSS;
352
+ // Common flex properties first
353
+ if (collapsibleCSS.display) {
354
+ css += ` display: ${collapsibleCSS.display};\n`;
355
+ }
356
+ if (collapsibleCSS.flexDirection) {
357
+ css += ` flex-direction: ${collapsibleCSS.flexDirection};\n`;
358
+ }
359
+ // Collapsible-specific properties
360
+ if (collapsibleCSS.width) {
361
+ const widthValue = tokenRefToVar(collapsibleCSS.width);
362
+ css += ` width: ${widthValue};\n`;
363
+ }
364
+ if (collapsibleCSS.minWidth) {
365
+ const minWidthValue = tokenRefToVar(collapsibleCSS.minWidth);
366
+ css += ` min-width: ${minWidthValue};\n`;
367
+ }
368
+ if (collapsibleCSS.transition) {
369
+ css += ` transition: ${collapsibleCSS.transition};\n`;
370
+ }
371
+ if (collapsibleCSS.overflow) {
372
+ css += ` overflow: ${collapsibleCSS.overflow};\n`;
373
+ }
374
+ if (collapsibleCSS.willChange) {
375
+ css += ` will-change: ${collapsibleCSS.willChange};\n`;
376
+ }
377
+ if (collapsibleCSS.padding) {
378
+ const paddingValue = tokenRefToVar(collapsibleCSS.padding);
379
+ css += ` padding: ${paddingValue};\n`;
380
+ }
381
+ if (collapsibleCSS.gap) {
382
+ const gapValue = tokenRefToVar(collapsibleCSS.gap);
383
+ css += ` gap: ${gapValue};\n`;
384
+ }
385
+ }
386
+ css += `}\n\n`;
387
+ }
388
+ return css;
389
+ }
390
+ /**
391
+ * Generate state classes for interactive advanced section patterns
392
+ * Handles stuck states for sticky patterns and collapsed states for collapsible patterns
393
+ *
394
+ * @param sections - Array of advanced section pattern tokens
395
+ * @returns CSS state classes for advanced sections
396
+ */
397
+ export function generateAdvancedSectionStateClasses(sections) {
398
+ let css = '';
399
+ for (const section of sections) {
400
+ if (!section.states) {
401
+ continue;
402
+ }
403
+ const className = section.id.replace(/\./g, '-');
404
+ // Generate stuck state for sticky patterns
405
+ if (section.states.stuck) {
406
+ css += `.${className}.is-stuck {\n`;
407
+ const stuckCSS = section.states.stuck;
408
+ if (stuckCSS.boxShadow) {
409
+ const shadowValue = tokenRefToVar(stuckCSS.boxShadow);
410
+ css += ` box-shadow: ${shadowValue};\n`;
411
+ }
412
+ if (stuckCSS.backgroundColor) {
413
+ const bgValue = tokenRefToVar(stuckCSS.backgroundColor);
414
+ css += ` background-color: ${bgValue};\n`;
415
+ }
416
+ if (stuckCSS.zIndex !== undefined) {
417
+ css += ` z-index: ${stuckCSS.zIndex};\n`;
418
+ }
419
+ css += `}\n\n`;
420
+ }
421
+ // Generate collapsed state for collapsible patterns
422
+ if (section.states.collapsed) {
423
+ css += `.${className}.is-collapsed {\n`;
424
+ const collapsedCSS = section.states.collapsed;
425
+ if (collapsedCSS.width) {
426
+ const widthValue = tokenRefToVar(collapsedCSS.width);
427
+ css += ` width: ${widthValue};\n`;
428
+ }
429
+ if (collapsedCSS.minWidth) {
430
+ const minWidthValue = tokenRefToVar(collapsedCSS.minWidth);
431
+ css += ` min-width: ${minWidthValue};\n`;
432
+ }
433
+ if (collapsedCSS.overflow) {
434
+ css += ` overflow: ${collapsedCSS.overflow};\n`;
435
+ }
436
+ if (collapsedCSS.padding) {
437
+ const paddingValue = tokenRefToVar(collapsedCSS.padding);
438
+ css += ` padding: ${paddingValue};\n`;
439
+ }
440
+ css += `}\n\n`;
441
+ }
442
+ }
443
+ return css;
444
+ }
445
+ /**
446
+ * Generate media query CSS for advanced section patterns
447
+ * Internal helper function for generateMediaQueries
448
+ *
449
+ * @param className - CSS class name for the section
450
+ * @param type - Section type ('masonry', 'sticky', 'collapsible')
451
+ * @param responsiveConfig - Responsive configuration for this breakpoint
452
+ * @returns CSS string for the media query content
453
+ */
454
+ function generateAdvancedSectionMediaQueryCSS(className, type, responsiveConfig) {
455
+ let css = '';
456
+ if (!responsiveConfig || Object.keys(responsiveConfig).length === 0) {
457
+ return css;
458
+ }
459
+ css += ` .${className} {\n`;
460
+ if (type === 'masonry') {
461
+ const masonryConfig = responsiveConfig;
462
+ if (masonryConfig.columnCount) {
463
+ css += ` column-count: ${masonryConfig.columnCount};\n`;
464
+ }
465
+ if (masonryConfig.columnGap) {
466
+ const columnGapValue = tokenRefToVar(masonryConfig.columnGap);
467
+ css += ` column-gap: ${columnGapValue};\n`;
468
+ }
469
+ if (masonryConfig.breakInside) {
470
+ css += ` break-inside: ${masonryConfig.breakInside};\n`;
471
+ }
472
+ if (masonryConfig.columnFill) {
473
+ css += ` column-fill: ${masonryConfig.columnFill};\n`;
474
+ }
475
+ // Common section properties
476
+ if (masonryConfig.display) {
477
+ css += ` display: ${masonryConfig.display};\n`;
478
+ }
479
+ if (masonryConfig.gap) {
480
+ const gapValue = tokenRefToVar(masonryConfig.gap);
481
+ css += ` gap: ${gapValue};\n`;
482
+ }
483
+ }
484
+ else if (type === 'sticky') {
485
+ const stickyConfig = responsiveConfig;
486
+ if (stickyConfig.display) {
487
+ css += ` display: ${stickyConfig.display};\n`;
488
+ }
489
+ if (stickyConfig.flexDirection) {
490
+ css += ` flex-direction: ${stickyConfig.flexDirection};\n`;
491
+ }
492
+ if (stickyConfig.alignItems) {
493
+ css += ` align-items: ${stickyConfig.alignItems};\n`;
494
+ }
495
+ if (stickyConfig.justifyContent) {
496
+ css += ` justify-content: ${stickyConfig.justifyContent};\n`;
497
+ }
498
+ if (stickyConfig.gap) {
499
+ const gapValue = tokenRefToVar(stickyConfig.gap);
500
+ css += ` gap: ${gapValue};\n`;
501
+ }
502
+ if (stickyConfig.position) {
503
+ css += ` position: ${stickyConfig.position};\n`;
504
+ }
505
+ if (stickyConfig.top) {
506
+ const topValue = tokenRefToVar(stickyConfig.top);
507
+ css += ` top: ${topValue};\n`;
508
+ }
509
+ if (stickyConfig.bottom) {
510
+ const bottomValue = tokenRefToVar(stickyConfig.bottom);
511
+ css += ` bottom: ${bottomValue};\n`;
512
+ }
513
+ if (stickyConfig.zIndex !== undefined) {
514
+ css += ` z-index: ${stickyConfig.zIndex};\n`;
515
+ }
516
+ if (stickyConfig.padding) {
517
+ const paddingValue = tokenRefToVar(stickyConfig.padding);
518
+ css += ` padding: ${paddingValue};\n`;
519
+ }
520
+ if (stickyConfig.backgroundColor) {
521
+ const bgValue = tokenRefToVar(stickyConfig.backgroundColor);
522
+ css += ` background-color: ${bgValue};\n`;
523
+ }
524
+ if (stickyConfig.boxShadow) {
525
+ const shadowValue = tokenRefToVar(stickyConfig.boxShadow);
526
+ css += ` box-shadow: ${shadowValue};\n`;
527
+ }
528
+ }
529
+ else if (type === 'collapsible') {
530
+ const collapsibleConfig = responsiveConfig;
531
+ if (collapsibleConfig.display) {
532
+ css += ` display: ${collapsibleConfig.display};\n`;
533
+ }
534
+ if (collapsibleConfig.flexDirection) {
535
+ css += ` flex-direction: ${collapsibleConfig.flexDirection};\n`;
536
+ }
537
+ if (collapsibleConfig.width) {
538
+ const widthValue = tokenRefToVar(collapsibleConfig.width);
539
+ css += ` width: ${widthValue};\n`;
540
+ }
541
+ if (collapsibleConfig.minWidth) {
542
+ const minWidthValue = tokenRefToVar(collapsibleConfig.minWidth);
543
+ css += ` min-width: ${minWidthValue};\n`;
544
+ }
545
+ if (collapsibleConfig.transition) {
546
+ css += ` transition: ${collapsibleConfig.transition};\n`;
547
+ }
548
+ if (collapsibleConfig.overflow) {
549
+ css += ` overflow: ${collapsibleConfig.overflow};\n`;
550
+ }
551
+ if (collapsibleConfig.willChange) {
552
+ css += ` will-change: ${collapsibleConfig.willChange};\n`;
553
+ }
554
+ if (collapsibleConfig.padding) {
555
+ const paddingValue = tokenRefToVar(collapsibleConfig.padding);
556
+ css += ` padding: ${paddingValue};\n`;
557
+ }
558
+ if (collapsibleConfig.gap) {
559
+ const gapValue = tokenRefToVar(collapsibleConfig.gap);
560
+ css += ` gap: ${gapValue};\n`;
561
+ }
562
+ }
563
+ css += ` }\n\n`;
564
+ return css;
565
+ }
566
+ /**
567
+ * Generate responsive media queries for all breakpoints
568
+ *
569
+ * @param tokens - Array of layout tokens
570
+ * @returns CSS media queries
571
+ */
572
+ export function generateMediaQueries(tokens) {
573
+ let css = '';
574
+ // Breakpoint names in order
575
+ const breakpoints = ['sm', 'md', 'lg', 'xl', '2xl'];
576
+ for (const bp of breakpoints) {
577
+ const minWidth = BREAKPOINT_VALUES[bp];
578
+ let mediaQueryContent = '';
579
+ // Process each token
580
+ for (const token of tokens) {
581
+ // Get responsive config for this breakpoint
582
+ const responsiveConfig = token.responsive[bp];
583
+ if (!responsiveConfig || Object.keys(responsiveConfig).length === 0) {
584
+ continue;
585
+ }
586
+ // Generate class name based on token type
587
+ let className = '';
588
+ if ('platform' in token) {
589
+ // ShellToken
590
+ className = token.id.replace(/\./g, '-');
591
+ }
592
+ else if ('purpose' in token) {
593
+ // PageLayoutToken
594
+ className = token.id.replace(/\./g, '-');
595
+ }
596
+ else if ('type' in token) {
597
+ // SectionPatternToken or AdvancedSectionPatternToken
598
+ const sectionToken = token;
599
+ className = sectionToken.id.replace(/\./g, '-');
600
+ // Check if this is an advanced section pattern
601
+ if (isAdvancedSectionToken(token)) {
602
+ const advancedToken = token;
603
+ mediaQueryContent += generateAdvancedSectionMediaQueryCSS(className, advancedToken.type, responsiveConfig);
604
+ }
605
+ else {
606
+ // Generate standard section CSS for this breakpoint
607
+ const responsiveCss = responsiveConfig;
608
+ if (Object.keys(responsiveCss).length > 0) {
609
+ mediaQueryContent += ` .${className} {\n`;
610
+ if (responsiveCss.display) {
611
+ mediaQueryContent += ` display: ${responsiveCss.display};\n`;
612
+ }
613
+ if (responsiveCss.gridTemplateColumns) {
614
+ mediaQueryContent += ` grid-template-columns: ${responsiveCss.gridTemplateColumns};\n`;
615
+ }
616
+ if (responsiveCss.gridTemplateRows) {
617
+ mediaQueryContent += ` grid-template-rows: ${responsiveCss.gridTemplateRows};\n`;
618
+ }
619
+ if (responsiveCss.gap) {
620
+ const gapValue = tokenRefToVar(responsiveCss.gap);
621
+ mediaQueryContent += ` gap: ${gapValue};\n`;
622
+ }
623
+ if (responsiveCss.flexDirection) {
624
+ mediaQueryContent += ` flex-direction: ${responsiveCss.flexDirection};\n`;
625
+ }
626
+ if (responsiveCss.alignItems) {
627
+ mediaQueryContent += ` align-items: ${responsiveCss.alignItems};\n`;
628
+ }
629
+ if (responsiveCss.justifyContent) {
630
+ mediaQueryContent += ` justify-content: ${responsiveCss.justifyContent};\n`;
631
+ }
632
+ if (responsiveCss.maxWidth) {
633
+ const maxWidthValue = tokenRefToVar(responsiveCss.maxWidth);
634
+ mediaQueryContent += ` max-width: ${maxWidthValue};\n`;
635
+ }
636
+ if (responsiveCss.padding) {
637
+ const paddingValue = tokenRefToVar(responsiveCss.padding);
638
+ mediaQueryContent += ` padding: ${paddingValue};\n`;
639
+ }
640
+ mediaQueryContent += ` }\n\n`;
641
+ }
642
+ }
643
+ }
644
+ }
645
+ // Only add media query if there's content
646
+ if (mediaQueryContent.trim().length > 0) {
647
+ css += `@media (min-width: ${minWidth}px) {\n`;
648
+ css += mediaQueryContent;
649
+ css += `}\n\n`;
650
+ }
651
+ }
652
+ return css;
653
+ }
654
+ /**
655
+ * Generate complete CSS from layout tokens
656
+ *
657
+ * @param tokens - Array of layout tokens (shells, pages, sections)
658
+ * @param options - CSS generation options
659
+ * @returns Complete CSS string with variables, utilities, and media queries
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * import { getAllShellTokens, getAllPageLayoutTokens, getAllSectionPatternTokens } from './layout-tokens/index.js';
664
+ *
665
+ * const shells = getAllShellTokens();
666
+ * const pages = getAllPageLayoutTokens();
667
+ * const sections = getAllSectionPatternTokens();
668
+ *
669
+ * const css = generateLayoutCSS([...shells, ...pages, ...sections]);
670
+ * console.log(css);
671
+ * ```
672
+ */
673
+ export function generateLayoutCSS(tokens, options = {}) {
674
+ const { includeVariables = true, includeClasses = true, includeMediaQueries = true, indent = ' ', } = options;
675
+ let css = '';
676
+ // Separate tokens by type
677
+ const shells = tokens.filter(t => 'platform' in t);
678
+ const pages = tokens.filter(t => 'purpose' in t);
679
+ // Separate standard sections from advanced sections
680
+ const allSections = tokens.filter(t => 'type' in t);
681
+ const advancedTypes = ['masonry', 'sticky', 'collapsible'];
682
+ const standardSections = allSections.filter(t => !advancedTypes.includes(t.type));
683
+ const advancedSections = allSections.filter(t => advancedTypes.includes(t.type));
684
+ // 1. Generate CSS variables
685
+ if (includeVariables) {
686
+ const variablesCSS = generateCSSVariables(tokens);
687
+ if (variablesCSS) {
688
+ css += variablesCSS + '\n';
689
+ }
690
+ }
691
+ // 2. Generate utility classes
692
+ if (includeClasses) {
693
+ // Shell classes
694
+ if (shells.length > 0) {
695
+ const shellCSS = generateShellClasses(shells);
696
+ if (shellCSS) {
697
+ css += shellCSS;
698
+ }
699
+ }
700
+ // Page classes
701
+ if (pages.length > 0) {
702
+ const pageCSS = generatePageClasses(pages);
703
+ if (pageCSS) {
704
+ css += pageCSS;
705
+ }
706
+ }
707
+ // Standard section classes
708
+ if (standardSections.length > 0) {
709
+ const sectionCSS = generateSectionClasses(standardSections);
710
+ if (sectionCSS) {
711
+ css += sectionCSS;
712
+ }
713
+ }
714
+ // Advanced section classes (masonry, sticky, collapsible)
715
+ if (advancedSections.length > 0) {
716
+ const advancedCSS = generateAdvancedSectionClasses(advancedSections);
717
+ if (advancedCSS) {
718
+ css += advancedCSS;
719
+ }
720
+ // Generate state classes for interactive patterns
721
+ const stateCSS = generateAdvancedSectionStateClasses(advancedSections);
722
+ if (stateCSS) {
723
+ css += stateCSS;
724
+ }
725
+ }
726
+ }
727
+ // 3. Generate responsive media queries (only if includeClasses is true)
728
+ if (includeMediaQueries && includeClasses) {
729
+ const mediaCSS = generateMediaQueries(tokens);
730
+ if (mediaCSS) {
731
+ css += mediaCSS;
732
+ }
733
+ }
734
+ // 4. Format CSS with proper indentation
735
+ const formatted = formatCSS(css, indent);
736
+ // 5. Validate CSS syntax
737
+ if (!validateCSS(formatted)) {
738
+ throw new Error('Generated CSS has unbalanced braces');
739
+ }
740
+ return formatted;
741
+ }
742
+ /**
743
+ * Generate CSS for all layout tokens in the system
744
+ *
745
+ * @param options - CSS generation options
746
+ * @returns Complete CSS for all shells, pages, and sections
747
+ *
748
+ * @example
749
+ * ```typescript
750
+ * const css = generateAllLayoutCSS();
751
+ * // Write to file or use in application
752
+ * ```
753
+ */
754
+ export function generateAllLayoutCSS(options = {}) {
755
+ const shells = getAllShellTokens();
756
+ const pages = getAllPageLayoutTokens();
757
+ const sections = getAllSectionPatternTokens();
758
+ const advancedSections = getAllAdvancedSectionPatternTokens();
759
+ return generateLayoutCSS([...shells, ...pages, ...sections, ...advancedSections], options);
760
+ }
761
+ // ============================================================================
762
+ // Container Query CSS Generation (SPEC-LAYOUT-003 Phase 3)
763
+ // ============================================================================
764
+ /**
765
+ * Generate CSS container queries with browser fallback
766
+ * Uses @supports for progressive enhancement
767
+ *
768
+ * @param config - Container query configuration
769
+ * @returns CSS string with container queries and fallback
770
+ */
771
+ export function generateContainerQueryCSS(config) {
772
+ const rules = [];
773
+ // Container definition
774
+ rules.push(` container-type: ${config.type};`);
775
+ rules.push(` container-name: ${config.name};`);
776
+ // Container query rules with @supports progressive enhancement
777
+ const queryRules = [];
778
+ for (const [_bp, bpConfig] of Object.entries(config.breakpoints)) {
779
+ if (bpConfig) {
780
+ const cssProps = Object.entries(bpConfig.css)
781
+ .map(([prop, value]) => ` ${prop}: ${value};`)
782
+ .join('\n');
783
+ queryRules.push(`
784
+ @container ${config.name} (min-width: ${bpConfig.minWidth}px) {
785
+ ${cssProps}
786
+ }`);
787
+ }
788
+ }
789
+ // Wrap in @supports for browser compatibility
790
+ if (queryRules.length > 0) {
791
+ rules.push(`
792
+ @supports (container-type: inline-size) {
793
+ ${queryRules.join('\n')}
794
+ }`);
795
+ }
796
+ return rules.join('\n');
797
+ }
798
+ /**
799
+ * Generate fallback CSS for browsers without container query support
800
+ * Uses viewport-based media queries as fallback
801
+ *
802
+ * @param config - Container query configuration
803
+ * @returns CSS string with media query fallbacks
804
+ */
805
+ export function generateContainerQueryFallback(config) {
806
+ const fallbackRules = [];
807
+ // Map container breakpoints to approximate viewport breakpoints
808
+ const breakpointMapping = {
809
+ sm: 640,
810
+ md: 768,
811
+ lg: 1024,
812
+ xl: 1280,
813
+ };
814
+ for (const [bp, bpConfig] of Object.entries(config.breakpoints)) {
815
+ if (bpConfig) {
816
+ const viewportWidth = breakpointMapping[bp] || bpConfig.minWidth * 2;
817
+ const cssProps = Object.entries(bpConfig.css)
818
+ .map(([prop, value]) => ` ${prop}: ${value};`)
819
+ .join('\n');
820
+ fallbackRules.push(`
821
+ @supports not (container-type: inline-size) {
822
+ @media (min-width: ${viewportWidth}px) {
823
+ ${cssProps}
824
+ }
825
+ }`);
826
+ }
827
+ }
828
+ return fallbackRules.join('\n');
829
+ }
830
+ // ============================================================================
831
+ // Orientation CSS Generation (SPEC-LAYOUT-003 Phase 3)
832
+ // ============================================================================
833
+ /**
834
+ * Generate orientation-specific CSS media queries
835
+ * Supports portrait (height >= width) and landscape (width > height)
836
+ *
837
+ * @param config - Orientation configuration
838
+ * @param cssGenerator - Function to convert config to CSS properties
839
+ * @returns CSS string with orientation media queries
840
+ */
841
+ export function generateOrientationCSS(config, cssGenerator) {
842
+ const rules = [];
843
+ if (config.portrait) {
844
+ const portraitCSS = cssGenerator(config.portrait);
845
+ if (portraitCSS) {
846
+ rules.push(`
847
+ @media (orientation: portrait) {
848
+ ${portraitCSS}
849
+ }`);
850
+ }
851
+ }
852
+ if (config.landscape) {
853
+ const landscapeCSS = cssGenerator(config.landscape);
854
+ if (landscapeCSS) {
855
+ rules.push(`
856
+ @media (orientation: landscape) {
857
+ ${landscapeCSS}
858
+ }`);
859
+ }
860
+ }
861
+ return rules.join('\n');
862
+ }
863
+ /**
864
+ * Generate complete responsive CSS with orientation support
865
+ * Combines viewport breakpoints, container queries, and orientation
866
+ *
867
+ * @param config - Full responsive configuration
868
+ * @param cssGenerator - Function to convert config to CSS properties
869
+ * @param containerConfig - Optional container query configuration
870
+ * @returns Complete CSS string
871
+ */
872
+ export function generateAdvancedResponsiveCSS(config, cssGenerator, containerConfig) {
873
+ const sections = [];
874
+ // Base responsive CSS (viewport breakpoints)
875
+ sections.push(cssGenerator(config.default));
876
+ // Breakpoint overrides
877
+ const breakpoints = ['sm', 'md', 'lg', 'xl', '2xl'];
878
+ for (const bp of breakpoints) {
879
+ const override = config[bp];
880
+ if (override) {
881
+ const css = cssGenerator(override);
882
+ if (css) {
883
+ sections.push(`
884
+ @media (min-width: ${BREAKPOINT_VALUES[bp]}px) {
885
+ ${css}
886
+ }`);
887
+ }
888
+ }
889
+ }
890
+ // Container queries (if provided)
891
+ if (containerConfig) {
892
+ sections.push(generateContainerQueryCSS(containerConfig));
893
+ sections.push(generateContainerQueryFallback(containerConfig));
894
+ }
895
+ // Orientation overrides
896
+ if (config.orientation) {
897
+ sections.push(generateOrientationCSS(config.orientation, cssGenerator));
898
+ }
899
+ return sections.join('\n');
900
+ }
901
+ //# sourceMappingURL=layout-css-generator.js.map