@tenphi/tasty 0.0.0-snapshot.0c0ba7f

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 (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +484 -0
  3. package/dist/_virtual/_rolldown/runtime.js +8 -0
  4. package/dist/chunks/cacheKey.js +70 -0
  5. package/dist/chunks/cacheKey.js.map +1 -0
  6. package/dist/chunks/definitions.d.ts +37 -0
  7. package/dist/chunks/definitions.js +260 -0
  8. package/dist/chunks/definitions.js.map +1 -0
  9. package/dist/chunks/renderChunk.js +61 -0
  10. package/dist/chunks/renderChunk.js.map +1 -0
  11. package/dist/config.d.ts +280 -0
  12. package/dist/config.js +403 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/core/index.d.ts +33 -0
  15. package/dist/core/index.js +26 -0
  16. package/dist/debug.d.ts +204 -0
  17. package/dist/debug.js +733 -0
  18. package/dist/debug.js.map +1 -0
  19. package/dist/hooks/useGlobalStyles.d.ts +27 -0
  20. package/dist/hooks/useGlobalStyles.js +56 -0
  21. package/dist/hooks/useGlobalStyles.js.map +1 -0
  22. package/dist/hooks/useKeyframes.d.ts +56 -0
  23. package/dist/hooks/useKeyframes.js +54 -0
  24. package/dist/hooks/useKeyframes.js.map +1 -0
  25. package/dist/hooks/useProperty.d.ts +79 -0
  26. package/dist/hooks/useProperty.js +91 -0
  27. package/dist/hooks/useProperty.js.map +1 -0
  28. package/dist/hooks/useRawCSS.d.ts +53 -0
  29. package/dist/hooks/useRawCSS.js +28 -0
  30. package/dist/hooks/useRawCSS.js.map +1 -0
  31. package/dist/hooks/useStyles.d.ts +40 -0
  32. package/dist/hooks/useStyles.js +169 -0
  33. package/dist/hooks/useStyles.js.map +1 -0
  34. package/dist/index.d.ts +48 -0
  35. package/dist/index.js +33 -0
  36. package/dist/injector/index.d.ts +157 -0
  37. package/dist/injector/index.js +154 -0
  38. package/dist/injector/index.js.map +1 -0
  39. package/dist/injector/injector.d.ts +139 -0
  40. package/dist/injector/injector.js +404 -0
  41. package/dist/injector/injector.js.map +1 -0
  42. package/dist/injector/sheet-manager.d.ts +127 -0
  43. package/dist/injector/sheet-manager.js +714 -0
  44. package/dist/injector/sheet-manager.js.map +1 -0
  45. package/dist/injector/types.d.ts +135 -0
  46. package/dist/keyframes/index.js +206 -0
  47. package/dist/keyframes/index.js.map +1 -0
  48. package/dist/parser/classify.js +319 -0
  49. package/dist/parser/classify.js.map +1 -0
  50. package/dist/parser/const.js +33 -0
  51. package/dist/parser/const.js.map +1 -0
  52. package/dist/parser/lru.js +109 -0
  53. package/dist/parser/lru.js.map +1 -0
  54. package/dist/parser/parser.d.ts +25 -0
  55. package/dist/parser/parser.js +116 -0
  56. package/dist/parser/parser.js.map +1 -0
  57. package/dist/parser/tokenizer.js +69 -0
  58. package/dist/parser/tokenizer.js.map +1 -0
  59. package/dist/parser/types.d.ts +51 -0
  60. package/dist/parser/types.js +46 -0
  61. package/dist/parser/types.js.map +1 -0
  62. package/dist/pipeline/conditions.d.ts +134 -0
  63. package/dist/pipeline/conditions.js +400 -0
  64. package/dist/pipeline/conditions.js.map +1 -0
  65. package/dist/pipeline/exclusive.js +231 -0
  66. package/dist/pipeline/exclusive.js.map +1 -0
  67. package/dist/pipeline/index.d.ts +53 -0
  68. package/dist/pipeline/index.js +645 -0
  69. package/dist/pipeline/index.js.map +1 -0
  70. package/dist/pipeline/materialize.js +864 -0
  71. package/dist/pipeline/materialize.js.map +1 -0
  72. package/dist/pipeline/parseStateKey.d.ts +15 -0
  73. package/dist/pipeline/parseStateKey.js +440 -0
  74. package/dist/pipeline/parseStateKey.js.map +1 -0
  75. package/dist/pipeline/simplify.js +542 -0
  76. package/dist/pipeline/simplify.js.map +1 -0
  77. package/dist/pipeline/warnings.js +18 -0
  78. package/dist/pipeline/warnings.js.map +1 -0
  79. package/dist/plugins/okhsl-plugin.d.ts +35 -0
  80. package/dist/plugins/okhsl-plugin.js +371 -0
  81. package/dist/plugins/okhsl-plugin.js.map +1 -0
  82. package/dist/plugins/types.d.ts +69 -0
  83. package/dist/properties/index.js +158 -0
  84. package/dist/properties/index.js.map +1 -0
  85. package/dist/states/index.d.ts +49 -0
  86. package/dist/states/index.js +416 -0
  87. package/dist/states/index.js.map +1 -0
  88. package/dist/static/index.d.ts +5 -0
  89. package/dist/static/index.js +5 -0
  90. package/dist/static/tastyStatic.d.ts +46 -0
  91. package/dist/static/tastyStatic.js +31 -0
  92. package/dist/static/tastyStatic.js.map +1 -0
  93. package/dist/static/types.d.ts +49 -0
  94. package/dist/static/types.js +24 -0
  95. package/dist/static/types.js.map +1 -0
  96. package/dist/styles/align.d.ts +15 -0
  97. package/dist/styles/align.js +14 -0
  98. package/dist/styles/align.js.map +1 -0
  99. package/dist/styles/border.d.ts +25 -0
  100. package/dist/styles/border.js +114 -0
  101. package/dist/styles/border.js.map +1 -0
  102. package/dist/styles/color.d.ts +14 -0
  103. package/dist/styles/color.js +23 -0
  104. package/dist/styles/color.js.map +1 -0
  105. package/dist/styles/createStyle.js +77 -0
  106. package/dist/styles/createStyle.js.map +1 -0
  107. package/dist/styles/dimension.js +97 -0
  108. package/dist/styles/dimension.js.map +1 -0
  109. package/dist/styles/display.d.ts +37 -0
  110. package/dist/styles/display.js +67 -0
  111. package/dist/styles/display.js.map +1 -0
  112. package/dist/styles/fade.d.ts +15 -0
  113. package/dist/styles/fade.js +58 -0
  114. package/dist/styles/fade.js.map +1 -0
  115. package/dist/styles/fill.d.ts +42 -0
  116. package/dist/styles/fill.js +51 -0
  117. package/dist/styles/fill.js.map +1 -0
  118. package/dist/styles/flow.d.ts +16 -0
  119. package/dist/styles/flow.js +12 -0
  120. package/dist/styles/flow.js.map +1 -0
  121. package/dist/styles/gap.d.ts +31 -0
  122. package/dist/styles/gap.js +37 -0
  123. package/dist/styles/gap.js.map +1 -0
  124. package/dist/styles/height.d.ts +17 -0
  125. package/dist/styles/height.js +20 -0
  126. package/dist/styles/height.js.map +1 -0
  127. package/dist/styles/index.d.ts +2 -0
  128. package/dist/styles/index.js +9 -0
  129. package/dist/styles/index.js.map +1 -0
  130. package/dist/styles/inset.d.ts +52 -0
  131. package/dist/styles/inset.js +150 -0
  132. package/dist/styles/inset.js.map +1 -0
  133. package/dist/styles/justify.d.ts +15 -0
  134. package/dist/styles/justify.js +14 -0
  135. package/dist/styles/justify.js.map +1 -0
  136. package/dist/styles/list.d.ts +16 -0
  137. package/dist/styles/list.js +98 -0
  138. package/dist/styles/list.js.map +1 -0
  139. package/dist/styles/margin.d.ts +24 -0
  140. package/dist/styles/margin.js +104 -0
  141. package/dist/styles/margin.js.map +1 -0
  142. package/dist/styles/outline.d.ts +29 -0
  143. package/dist/styles/outline.js +65 -0
  144. package/dist/styles/outline.js.map +1 -0
  145. package/dist/styles/padding.d.ts +24 -0
  146. package/dist/styles/padding.js +104 -0
  147. package/dist/styles/padding.js.map +1 -0
  148. package/dist/styles/predefined.d.ts +73 -0
  149. package/dist/styles/predefined.js +241 -0
  150. package/dist/styles/predefined.js.map +1 -0
  151. package/dist/styles/preset.d.ts +47 -0
  152. package/dist/styles/preset.js +126 -0
  153. package/dist/styles/preset.js.map +1 -0
  154. package/dist/styles/radius.d.ts +14 -0
  155. package/dist/styles/radius.js +51 -0
  156. package/dist/styles/radius.js.map +1 -0
  157. package/dist/styles/scrollbar.d.ts +21 -0
  158. package/dist/styles/scrollbar.js +112 -0
  159. package/dist/styles/scrollbar.js.map +1 -0
  160. package/dist/styles/shadow.d.ts +14 -0
  161. package/dist/styles/shadow.js +24 -0
  162. package/dist/styles/shadow.js.map +1 -0
  163. package/dist/styles/styledScrollbar.d.ts +47 -0
  164. package/dist/styles/styledScrollbar.js +38 -0
  165. package/dist/styles/styledScrollbar.js.map +1 -0
  166. package/dist/styles/transition.d.ts +14 -0
  167. package/dist/styles/transition.js +158 -0
  168. package/dist/styles/transition.js.map +1 -0
  169. package/dist/styles/types.d.ts +498 -0
  170. package/dist/styles/width.d.ts +17 -0
  171. package/dist/styles/width.js +20 -0
  172. package/dist/styles/width.js.map +1 -0
  173. package/dist/tasty.d.ts +982 -0
  174. package/dist/tasty.js +191 -0
  175. package/dist/tasty.js.map +1 -0
  176. package/dist/tokens/typography.d.ts +19 -0
  177. package/dist/tokens/typography.js +237 -0
  178. package/dist/tokens/typography.js.map +1 -0
  179. package/dist/types.d.ts +184 -0
  180. package/dist/utils/cache-wrapper.js +26 -0
  181. package/dist/utils/cache-wrapper.js.map +1 -0
  182. package/dist/utils/case-converter.js +8 -0
  183. package/dist/utils/case-converter.js.map +1 -0
  184. package/dist/utils/colors.d.ts +5 -0
  185. package/dist/utils/colors.js +9 -0
  186. package/dist/utils/colors.js.map +1 -0
  187. package/dist/utils/css-types.d.ts +7 -0
  188. package/dist/utils/dotize.d.ts +26 -0
  189. package/dist/utils/dotize.js +122 -0
  190. package/dist/utils/dotize.js.map +1 -0
  191. package/dist/utils/filter-base-props.d.ts +15 -0
  192. package/dist/utils/filter-base-props.js +45 -0
  193. package/dist/utils/filter-base-props.js.map +1 -0
  194. package/dist/utils/get-display-name.d.ts +7 -0
  195. package/dist/utils/get-display-name.js +10 -0
  196. package/dist/utils/get-display-name.js.map +1 -0
  197. package/dist/utils/hsl-to-rgb.js +38 -0
  198. package/dist/utils/hsl-to-rgb.js.map +1 -0
  199. package/dist/utils/is-dev-env.js +19 -0
  200. package/dist/utils/is-dev-env.js.map +1 -0
  201. package/dist/utils/is-valid-element-type.js +15 -0
  202. package/dist/utils/is-valid-element-type.js.map +1 -0
  203. package/dist/utils/merge-styles.d.ts +7 -0
  204. package/dist/utils/merge-styles.js +146 -0
  205. package/dist/utils/merge-styles.js.map +1 -0
  206. package/dist/utils/mod-attrs.d.ts +8 -0
  207. package/dist/utils/mod-attrs.js +21 -0
  208. package/dist/utils/mod-attrs.js.map +1 -0
  209. package/dist/utils/okhsl-to-rgb.js +296 -0
  210. package/dist/utils/okhsl-to-rgb.js.map +1 -0
  211. package/dist/utils/process-tokens.d.ts +31 -0
  212. package/dist/utils/process-tokens.js +171 -0
  213. package/dist/utils/process-tokens.js.map +1 -0
  214. package/dist/utils/resolve-recipes.d.ts +17 -0
  215. package/dist/utils/resolve-recipes.js +147 -0
  216. package/dist/utils/resolve-recipes.js.map +1 -0
  217. package/dist/utils/string.js +8 -0
  218. package/dist/utils/string.js.map +1 -0
  219. package/dist/utils/styles.d.ts +178 -0
  220. package/dist/utils/styles.js +590 -0
  221. package/dist/utils/styles.js.map +1 -0
  222. package/dist/utils/typography.d.ts +36 -0
  223. package/dist/utils/typography.js +53 -0
  224. package/dist/utils/typography.js.map +1 -0
  225. package/dist/utils/warnings.d.ts +16 -0
  226. package/dist/utils/warnings.js +16 -0
  227. package/dist/utils/warnings.js.map +1 -0
  228. package/dist/zero/babel.d.ts +108 -0
  229. package/dist/zero/babel.js +282 -0
  230. package/dist/zero/babel.js.map +1 -0
  231. package/dist/zero/css-writer.d.ts +45 -0
  232. package/dist/zero/css-writer.js +74 -0
  233. package/dist/zero/css-writer.js.map +1 -0
  234. package/dist/zero/extractor.d.ts +24 -0
  235. package/dist/zero/extractor.js +150 -0
  236. package/dist/zero/extractor.js.map +1 -0
  237. package/dist/zero/index.d.ts +3 -0
  238. package/dist/zero/index.js +4 -0
  239. package/dist/zero/next.d.ts +60 -0
  240. package/dist/zero/next.js +78 -0
  241. package/dist/zero/next.js.map +1 -0
  242. package/package.json +189 -0
  243. package/tasty.config.ts +14 -0
@@ -0,0 +1,864 @@
1
+ import { Lru } from "../parser/lru.js";
2
+ import { not } from "./conditions.js";
3
+
4
+ //#region src/pipeline/materialize.ts
5
+ /**
6
+ * CSS Materialization
7
+ *
8
+ * Converts condition trees into CSS selectors and at-rules.
9
+ * This is the final stage that produces actual CSS output.
10
+ */
11
+ const conditionCache = new Lru(3e3);
12
+ /**
13
+ * Convert a condition tree to CSS components
14
+ */
15
+ function conditionToCSS(node) {
16
+ const key = getConditionKey(node);
17
+ const cached = conditionCache.get(key);
18
+ if (cached) return cached;
19
+ const result = conditionToCSSInner(node);
20
+ conditionCache.set(key, result);
21
+ return result;
22
+ }
23
+ /**
24
+ * Create an empty selector variant
25
+ */
26
+ function emptyVariant() {
27
+ return {
28
+ modifierConditions: [],
29
+ pseudoConditions: [],
30
+ ownConditions: [],
31
+ mediaConditions: [],
32
+ containerConditions: [],
33
+ supportsConditions: [],
34
+ rootConditions: [],
35
+ parentGroups: [],
36
+ startingStyle: false
37
+ };
38
+ }
39
+ function conditionToCSSInner(node) {
40
+ if (node.kind === "true") return {
41
+ variants: [emptyVariant()],
42
+ isImpossible: false
43
+ };
44
+ if (node.kind === "false") return {
45
+ variants: [],
46
+ isImpossible: true
47
+ };
48
+ if (node.kind === "state") return stateToCSS(node);
49
+ if (node.kind === "compound") if (node.operator === "AND") return andToCSS(node.children);
50
+ else return orToCSS(node.children);
51
+ return {
52
+ variants: [emptyVariant()],
53
+ isImpossible: false
54
+ };
55
+ }
56
+ /**
57
+ * Convert a state condition to CSS
58
+ */
59
+ function stateToCSS(state) {
60
+ switch (state.type) {
61
+ case "media": return {
62
+ variants: mediaToParsed(state).map((mediaCond) => {
63
+ const v = emptyVariant();
64
+ v.mediaConditions.push(mediaCond);
65
+ return v;
66
+ }),
67
+ isImpossible: false
68
+ };
69
+ case "root": return innerConditionToVariants(state.innerCondition, state.negated ?? false, "rootConditions");
70
+ case "parent": return parentConditionToVariants(state.innerCondition, state.negated ?? false, state.direct);
71
+ case "own": return innerConditionToVariants(state.innerCondition, state.negated ?? false, "ownConditions");
72
+ case "modifier": {
73
+ const v = emptyVariant();
74
+ v.modifierConditions.push(modifierToParsed(state));
75
+ return {
76
+ variants: [v],
77
+ isImpossible: false
78
+ };
79
+ }
80
+ case "pseudo": {
81
+ const v = emptyVariant();
82
+ v.pseudoConditions.push(pseudoToParsed(state));
83
+ return {
84
+ variants: [v],
85
+ isImpossible: false
86
+ };
87
+ }
88
+ case "container": {
89
+ const v = emptyVariant();
90
+ v.containerConditions.push(containerToParsed(state));
91
+ return {
92
+ variants: [v],
93
+ isImpossible: false
94
+ };
95
+ }
96
+ case "supports": {
97
+ const v = emptyVariant();
98
+ v.supportsConditions.push(supportsToParsed(state));
99
+ return {
100
+ variants: [v],
101
+ isImpossible: false
102
+ };
103
+ }
104
+ case "starting": {
105
+ const v = emptyVariant();
106
+ v.startingStyle = !state.negated;
107
+ return {
108
+ variants: [v],
109
+ isImpossible: false
110
+ };
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Convert modifier condition to parsed structure
116
+ */
117
+ function modifierToParsed(state) {
118
+ return {
119
+ attribute: state.attribute,
120
+ value: state.value,
121
+ operator: state.operator,
122
+ negated: state.negated ?? false
123
+ };
124
+ }
125
+ /**
126
+ * Convert parsed modifier to CSS selector string (for final output)
127
+ */
128
+ function modifierToCSS(mod) {
129
+ let selector;
130
+ if (mod.value !== void 0) {
131
+ const op = mod.operator || "=";
132
+ selector = `[${mod.attribute}${op}"${mod.value}"]`;
133
+ } else selector = `[${mod.attribute}]`;
134
+ if (mod.negated) return `:not(${selector})`;
135
+ return selector;
136
+ }
137
+ /**
138
+ * Convert pseudo condition to parsed structure
139
+ */
140
+ function pseudoToParsed(state) {
141
+ return {
142
+ pseudo: state.pseudo,
143
+ negated: state.negated ?? false
144
+ };
145
+ }
146
+ /**
147
+ * Convert parsed pseudo to CSS selector string (for final output)
148
+ */
149
+ function pseudoToCSS(pseudo) {
150
+ if (pseudo.negated) {
151
+ if (pseudo.pseudo.startsWith(":not(")) return pseudo.pseudo.slice(5, -1);
152
+ return `:not(${pseudo.pseudo})`;
153
+ }
154
+ return pseudo.pseudo;
155
+ }
156
+ /**
157
+ * Convert media condition to parsed structure(s)
158
+ * Returns an array because negated ranges produce OR branches (two separate conditions)
159
+ */
160
+ function mediaToParsed(state) {
161
+ if (state.subtype === "type") {
162
+ const mediaType = state.mediaType || "all";
163
+ return [{
164
+ subtype: "type",
165
+ negated: state.negated ?? false,
166
+ condition: mediaType,
167
+ mediaType: state.mediaType
168
+ }];
169
+ } else if (state.subtype === "feature") {
170
+ let condition;
171
+ if (state.featureValue) condition = `(${state.feature}: ${state.featureValue})`;
172
+ else condition = `(${state.feature})`;
173
+ return [{
174
+ subtype: "feature",
175
+ negated: state.negated ?? false,
176
+ condition,
177
+ feature: state.feature,
178
+ featureValue: state.featureValue
179
+ }];
180
+ } else return dimensionToMediaParsed(state.dimension || "width", state.lowerBound, state.upperBound, state.negated ?? false);
181
+ }
182
+ /**
183
+ * Convert dimension bounds to parsed media condition(s)
184
+ * Uses CSS Media Queries Level 4 `not (condition)` syntax for negation.
185
+ */
186
+ function dimensionToMediaParsed(dimension, lowerBound, upperBound, negated) {
187
+ let condition;
188
+ if (lowerBound && upperBound) {
189
+ const lowerOp = lowerBound.inclusive ? "<=" : "<";
190
+ const upperOp = upperBound.inclusive ? "<=" : "<";
191
+ condition = `(${lowerBound.value} ${lowerOp} ${dimension} ${upperOp} ${upperBound.value})`;
192
+ } else if (upperBound) condition = `(${dimension} ${upperBound.inclusive ? "<=" : "<"} ${upperBound.value})`;
193
+ else if (lowerBound) condition = `(${dimension} ${lowerBound.inclusive ? ">=" : ">"} ${lowerBound.value})`;
194
+ else condition = `(${dimension})`;
195
+ return [{
196
+ subtype: "dimension",
197
+ negated: negated ?? false,
198
+ condition,
199
+ dimension,
200
+ lowerBound,
201
+ upperBound
202
+ }];
203
+ }
204
+ /**
205
+ * Convert container condition to parsed structure
206
+ * This enables structured analysis for contradiction detection and condition combining
207
+ */
208
+ function containerToParsed(state) {
209
+ let condition;
210
+ if (state.subtype === "style") if (state.propertyValue) condition = `style(--${state.property}: ${state.propertyValue})`;
211
+ else condition = `style(--${state.property})`;
212
+ else if (state.subtype === "raw") condition = state.rawCondition;
213
+ else condition = dimensionToContainerCondition(state.dimension || "width", state.lowerBound, state.upperBound);
214
+ return {
215
+ name: state.containerName,
216
+ condition,
217
+ negated: state.negated ?? false,
218
+ subtype: state.subtype,
219
+ property: state.property,
220
+ propertyValue: state.propertyValue
221
+ };
222
+ }
223
+ /**
224
+ * Convert dimension bounds to container query condition (single string)
225
+ * Container queries support "not (condition)", so no need to invert manually
226
+ */
227
+ function dimensionToContainerCondition(dimension, lowerBound, upperBound) {
228
+ if (lowerBound && upperBound) {
229
+ const lowerOp = lowerBound.inclusive ? "<=" : "<";
230
+ const upperOp = upperBound.inclusive ? "<=" : "<";
231
+ return `(${lowerBound.value} ${lowerOp} ${dimension} ${upperOp} ${upperBound.value})`;
232
+ } else if (upperBound) return `(${dimension} ${upperBound.inclusive ? "<=" : "<"} ${upperBound.value})`;
233
+ else if (lowerBound) return `(${dimension} ${lowerBound.inclusive ? ">=" : ">"} ${lowerBound.value})`;
234
+ return "(width)";
235
+ }
236
+ /**
237
+ * Convert supports condition to parsed structure
238
+ */
239
+ function supportsToParsed(state) {
240
+ return {
241
+ subtype: state.subtype,
242
+ condition: state.condition,
243
+ negated: state.negated ?? false
244
+ };
245
+ }
246
+ /**
247
+ * Collect all modifier and pseudo conditions from a variant as a flat array.
248
+ */
249
+ function collectSelectorConditions(variant) {
250
+ return [...variant.modifierConditions, ...variant.pseudoConditions];
251
+ }
252
+ /**
253
+ * Convert an inner condition tree into SelectorVariants.
254
+ * Each inner OR branch becomes a separate variant, preserving disjunction.
255
+ * Shared by @root() and @own().
256
+ */
257
+ function innerConditionToVariants(innerCondition, negated, target) {
258
+ const innerCSS = conditionToCSS(negated ? not(innerCondition) : innerCondition);
259
+ if (innerCSS.isImpossible || innerCSS.variants.length === 0) return {
260
+ variants: [],
261
+ isImpossible: true
262
+ };
263
+ const variants = [];
264
+ for (const innerVariant of innerCSS.variants) {
265
+ const conditions = collectSelectorConditions(innerVariant);
266
+ if (conditions.length > 0) {
267
+ const v = emptyVariant();
268
+ v[target].push(...conditions);
269
+ variants.push(v);
270
+ }
271
+ }
272
+ if (variants.length === 0) return {
273
+ variants: [emptyVariant()],
274
+ isImpossible: false
275
+ };
276
+ return {
277
+ variants,
278
+ isImpossible: false
279
+ };
280
+ }
281
+ /**
282
+ * Convert a @parent() inner condition into SelectorVariants with ParentGroups.
283
+ *
284
+ * Positive: each inner OR branch becomes a separate variant with one :is() group.
285
+ * Negated: !(A | B) = !A & !B — all branches become :not() groups collected
286
+ * into a single variant so they produce :not([a] *):not([b] *) on one element.
287
+ */
288
+ function parentConditionToVariants(innerCondition, negated, direct) {
289
+ const innerCSS = conditionToCSS(innerCondition);
290
+ if (innerCSS.isImpossible || innerCSS.variants.length === 0) return {
291
+ variants: [],
292
+ isImpossible: true
293
+ };
294
+ if (negated) {
295
+ const v = emptyVariant();
296
+ for (const innerVariant of innerCSS.variants) {
297
+ const conditions = collectSelectorConditions(innerVariant);
298
+ if (conditions.length > 0) v.parentGroups.push({
299
+ conditions,
300
+ direct,
301
+ negated: true
302
+ });
303
+ }
304
+ if (v.parentGroups.length === 0) return {
305
+ variants: [emptyVariant()],
306
+ isImpossible: false
307
+ };
308
+ return {
309
+ variants: [v],
310
+ isImpossible: false
311
+ };
312
+ }
313
+ const variants = [];
314
+ for (const innerVariant of innerCSS.variants) {
315
+ const conditions = collectSelectorConditions(innerVariant);
316
+ if (conditions.length > 0) {
317
+ const v = emptyVariant();
318
+ v.parentGroups.push({
319
+ conditions,
320
+ direct,
321
+ negated: false
322
+ });
323
+ variants.push(v);
324
+ }
325
+ }
326
+ if (variants.length === 0) return {
327
+ variants: [emptyVariant()],
328
+ isImpossible: false
329
+ };
330
+ return {
331
+ variants,
332
+ isImpossible: false
333
+ };
334
+ }
335
+ /**
336
+ * Convert parsed root conditions to CSS selector prefix (for final output)
337
+ */
338
+ function rootConditionsToCSS(roots) {
339
+ if (roots.length === 0) return void 0;
340
+ let prefix = ":root";
341
+ for (const cond of roots) prefix += selectorConditionToCSS(cond);
342
+ return prefix;
343
+ }
344
+ /**
345
+ * Convert parent groups to CSS selector fragments (for final output).
346
+ * Each group produces its own :is() wrapper.
347
+ */
348
+ function parentGroupsToCSS(groups) {
349
+ let result = "";
350
+ for (const group of groups) {
351
+ const combinator = group.direct ? " > *" : " *";
352
+ let parts = "";
353
+ for (const cond of group.conditions) parts += selectorConditionToCSS(cond);
354
+ const wrapper = group.negated ? ":not" : ":is";
355
+ result += `${wrapper}(${parts}${combinator})`;
356
+ }
357
+ return result;
358
+ }
359
+ /**
360
+ * Convert a modifier or pseudo condition to a CSS selector fragment
361
+ */
362
+ function selectorConditionToCSS(cond) {
363
+ if ("attribute" in cond) return modifierToCSS(cond);
364
+ return pseudoToCSS(cond);
365
+ }
366
+ /**
367
+ * Get unique key for a modifier condition
368
+ */
369
+ function getModifierKey(mod) {
370
+ const base = mod.value ? `${mod.attribute}${mod.operator || "="}${mod.value}` : mod.attribute;
371
+ return mod.negated ? `!${base}` : base;
372
+ }
373
+ /**
374
+ * Get unique key for a pseudo condition
375
+ */
376
+ function getPseudoKey(pseudo) {
377
+ return pseudo.negated ? `!${pseudo.pseudo}` : pseudo.pseudo;
378
+ }
379
+ /**
380
+ * Get unique key for any selector condition (modifier or pseudo)
381
+ */
382
+ function getSelectorConditionKey(cond) {
383
+ return "attribute" in cond ? `mod:${getModifierKey(cond)}` : `pseudo:${getPseudoKey(cond)}`;
384
+ }
385
+ /**
386
+ * Deduplicate selector conditions (modifiers or pseudos).
387
+ * Shared by root, parent, and own conditions.
388
+ */
389
+ function dedupeSelectorConditions(conditions) {
390
+ const seen = /* @__PURE__ */ new Set();
391
+ let result = [];
392
+ for (const c of conditions) {
393
+ const key = getSelectorConditionKey(c);
394
+ if (!seen.has(key)) {
395
+ seen.add(key);
396
+ result.push(c);
397
+ }
398
+ }
399
+ const negatedBooleanAttrs = /* @__PURE__ */ new Set();
400
+ const positiveExactValuesByAttr = /* @__PURE__ */ new Map();
401
+ for (const c of result) {
402
+ if (!("attribute" in c)) continue;
403
+ if (c.negated && c.value === void 0) negatedBooleanAttrs.add(c.attribute);
404
+ const op = c.operator ?? "=";
405
+ if (!c.negated && c.value !== void 0 && op === "=") {
406
+ let values = positiveExactValuesByAttr.get(c.attribute);
407
+ if (!values) {
408
+ values = /* @__PURE__ */ new Set();
409
+ positiveExactValuesByAttr.set(c.attribute, values);
410
+ }
411
+ values.add(c.value);
412
+ }
413
+ }
414
+ result = result.filter((c) => {
415
+ if (!("attribute" in c) || !c.negated || c.value === void 0) return true;
416
+ if (negatedBooleanAttrs.has(c.attribute)) return false;
417
+ if ((c.operator ?? "=") !== "=") return true;
418
+ const positiveValues = positiveExactValuesByAttr.get(c.attribute);
419
+ if (positiveValues !== void 0 && positiveValues.size === 1 && !positiveValues.has(c.value)) return false;
420
+ return true;
421
+ });
422
+ return result;
423
+ }
424
+ /**
425
+ * Check for modifier contradiction: same attribute with opposite negation
426
+ */
427
+ function hasModifierContradiction(conditions) {
428
+ const byKey = /* @__PURE__ */ new Map();
429
+ for (const mod of conditions) {
430
+ const baseKey = mod.value ? `${mod.attribute}${mod.operator || "="}${mod.value}` : mod.attribute;
431
+ const existing = byKey.get(baseKey);
432
+ if (existing !== void 0 && existing !== !mod.negated) return true;
433
+ byKey.set(baseKey, !mod.negated);
434
+ }
435
+ return false;
436
+ }
437
+ /**
438
+ * Check for pseudo contradiction: same pseudo with opposite negation
439
+ */
440
+ function hasPseudoContradiction(conditions) {
441
+ const byKey = /* @__PURE__ */ new Map();
442
+ for (const pseudo of conditions) {
443
+ const existing = byKey.get(pseudo.pseudo);
444
+ if (existing !== void 0 && existing !== !pseudo.negated) return true;
445
+ byKey.set(pseudo.pseudo, !pseudo.negated);
446
+ }
447
+ return false;
448
+ }
449
+ /**
450
+ * Check for selector condition contradiction (modifier or pseudo with opposite negation).
451
+ * Shared by root, parent, and own conditions.
452
+ */
453
+ function hasSelectorConditionContradiction(conditions) {
454
+ const modifiers = [];
455
+ const pseudos = [];
456
+ for (const c of conditions) if ("attribute" in c) modifiers.push(c);
457
+ else pseudos.push(c);
458
+ return hasModifierContradiction(modifiers) || hasPseudoContradiction(pseudos);
459
+ }
460
+ /**
461
+ * Check for parent group contradiction: same target (direct + conditions)
462
+ * with opposite negation. E.g. :not([data-hovered] *) and :is([data-hovered] *)
463
+ * in the same variant is impossible.
464
+ */
465
+ function hasParentGroupContradiction(groups) {
466
+ const byBaseKey = /* @__PURE__ */ new Map();
467
+ for (const g of groups) {
468
+ const baseKey = `${g.direct ? ">" : ""}(${g.conditions.map(getSelectorConditionKey).sort().join(",")})`;
469
+ const existing = byBaseKey.get(baseKey);
470
+ if (existing !== void 0 && existing !== !g.negated) return true;
471
+ byBaseKey.set(baseKey, !g.negated);
472
+ }
473
+ return false;
474
+ }
475
+ /**
476
+ * Merge two selector variants (AND operation)
477
+ * Deduplicates conditions and checks for contradictions
478
+ */
479
+ function mergeVariants(a, b) {
480
+ const mergedMedia = dedupeMediaConditions([...a.mediaConditions, ...b.mediaConditions]);
481
+ if (hasMediaContradiction(mergedMedia)) return null;
482
+ const mergedRoots = dedupeSelectorConditions([...a.rootConditions, ...b.rootConditions]);
483
+ if (hasSelectorConditionContradiction(mergedRoots)) return null;
484
+ const mergedModifiers = dedupeSelectorConditions([...a.modifierConditions, ...b.modifierConditions]);
485
+ const mergedPseudos = dedupeSelectorConditions([...a.pseudoConditions, ...b.pseudoConditions]);
486
+ if (hasSelectorConditionContradiction([...mergedModifiers, ...mergedPseudos])) return null;
487
+ const mergedParentGroups = [...a.parentGroups, ...b.parentGroups];
488
+ if (hasParentGroupContradiction(mergedParentGroups)) return null;
489
+ const mergedOwn = dedupeSelectorConditions([...a.ownConditions, ...b.ownConditions]);
490
+ if (hasSelectorConditionContradiction(mergedOwn)) return null;
491
+ const mergedContainers = dedupeContainerConditions([...a.containerConditions, ...b.containerConditions]);
492
+ if (hasContainerStyleContradiction(mergedContainers)) return null;
493
+ const mergedSupports = dedupeSupportsConditions([...a.supportsConditions, ...b.supportsConditions]);
494
+ if (hasSupportsContradiction(mergedSupports)) return null;
495
+ return {
496
+ modifierConditions: mergedModifiers,
497
+ pseudoConditions: mergedPseudos,
498
+ ownConditions: mergedOwn,
499
+ mediaConditions: mergedMedia,
500
+ containerConditions: mergedContainers,
501
+ supportsConditions: mergedSupports,
502
+ rootConditions: mergedRoots,
503
+ parentGroups: mergedParentGroups,
504
+ startingStyle: a.startingStyle || b.startingStyle
505
+ };
506
+ }
507
+ /**
508
+ * Generic deduplication by a key extraction function.
509
+ * Preserves insertion order, keeping the first occurrence of each key.
510
+ */
511
+ function dedupeByKey(items, getKey) {
512
+ const seen = /* @__PURE__ */ new Set();
513
+ const result = [];
514
+ for (const item of items) {
515
+ const key = getKey(item);
516
+ if (!seen.has(key)) {
517
+ seen.add(key);
518
+ result.push(item);
519
+ }
520
+ }
521
+ return result;
522
+ }
523
+ function dedupeMediaConditions(conditions) {
524
+ return dedupeByKey(conditions, (c) => `${c.subtype}|${c.condition}|${c.negated}`);
525
+ }
526
+ function dedupeContainerConditions(conditions) {
527
+ return dedupeByKey(conditions, (c) => `${c.name ?? ""}|${c.condition}|${c.negated}`);
528
+ }
529
+ function dedupeSupportsConditions(conditions) {
530
+ return dedupeByKey(conditions, (c) => `${c.subtype}|${c.condition}|${c.negated}`);
531
+ }
532
+ /**
533
+ * Check if supports conditions contain contradictions
534
+ * e.g., @supports(display: grid) AND NOT @supports(display: grid)
535
+ */
536
+ function hasSupportsContradiction(conditions) {
537
+ const conditionMap = /* @__PURE__ */ new Map();
538
+ for (const cond of conditions) {
539
+ const key = `${cond.subtype}|${cond.condition}`;
540
+ const existing = conditionMap.get(key);
541
+ if (existing !== void 0 && existing !== !cond.negated) return true;
542
+ conditionMap.set(key, !cond.negated);
543
+ }
544
+ return false;
545
+ }
546
+ /**
547
+ * Check if a set of media conditions contains contradictions
548
+ * e.g., (prefers-color-scheme: light) AND NOT (prefers-color-scheme: light)
549
+ * or (width >= 900px) AND (width < 600px)
550
+ *
551
+ * Uses parsed media conditions for efficient analysis without regex parsing.
552
+ */
553
+ function hasMediaContradiction(conditions) {
554
+ const featureConditions = /* @__PURE__ */ new Map();
555
+ const typeConditions = /* @__PURE__ */ new Map();
556
+ const dimensionConditions = /* @__PURE__ */ new Map();
557
+ const dimensionsByDim = /* @__PURE__ */ new Map();
558
+ for (const cond of conditions) if (cond.subtype === "type") {
559
+ const key = cond.mediaType || "all";
560
+ const existing = typeConditions.get(key);
561
+ if (existing !== void 0 && existing !== !cond.negated) return true;
562
+ typeConditions.set(key, !cond.negated);
563
+ } else if (cond.subtype === "feature") {
564
+ const key = cond.condition;
565
+ const existing = featureConditions.get(key);
566
+ if (existing !== void 0 && existing !== !cond.negated) return true;
567
+ featureConditions.set(key, !cond.negated);
568
+ } else if (cond.subtype === "dimension") {
569
+ const condKey = cond.condition;
570
+ const existing = dimensionConditions.get(condKey);
571
+ if (existing !== void 0 && existing !== !cond.negated) return true;
572
+ dimensionConditions.set(condKey, !cond.negated);
573
+ if (!cond.negated) {
574
+ const dim = cond.dimension || "width";
575
+ let bounds = dimensionsByDim.get(dim);
576
+ if (!bounds) {
577
+ bounds = {
578
+ lowerBound: null,
579
+ upperBound: null
580
+ };
581
+ dimensionsByDim.set(dim, bounds);
582
+ }
583
+ if (cond.lowerBound?.valueNumeric != null) {
584
+ const value = cond.lowerBound.valueNumeric;
585
+ if (bounds.lowerBound === null || value > bounds.lowerBound) bounds.lowerBound = value;
586
+ }
587
+ if (cond.upperBound?.valueNumeric != null) {
588
+ const value = cond.upperBound.valueNumeric;
589
+ if (bounds.upperBound === null || value < bounds.upperBound) bounds.upperBound = value;
590
+ }
591
+ if (bounds.lowerBound !== null && bounds.upperBound !== null && bounds.lowerBound >= bounds.upperBound) return true;
592
+ }
593
+ }
594
+ return false;
595
+ }
596
+ /**
597
+ * Check if container conditions contain contradictions in style queries
598
+ * e.g., style(--variant: danger) and style(--variant: success) together
599
+ * Same property with different values = always false
600
+ *
601
+ * Uses parsed container conditions for efficient analysis without regex parsing.
602
+ */
603
+ function hasContainerStyleContradiction(conditions) {
604
+ const styleQueries = /* @__PURE__ */ new Map();
605
+ for (const cond of conditions) {
606
+ if (cond.subtype !== "style" || !cond.property) continue;
607
+ const property = cond.property;
608
+ const value = cond.propertyValue;
609
+ if (!styleQueries.has(property)) styleQueries.set(property, {
610
+ hasExistence: false,
611
+ values: /* @__PURE__ */ new Set(),
612
+ hasNegatedExistence: false
613
+ });
614
+ const entry = styleQueries.get(property);
615
+ if (cond.negated) {
616
+ if (value === void 0) entry.hasNegatedExistence = true;
617
+ } else if (value === void 0) entry.hasExistence = true;
618
+ else entry.values.add(value);
619
+ }
620
+ for (const [, entry] of styleQueries) {
621
+ if (entry.hasExistence && entry.hasNegatedExistence) return true;
622
+ if (entry.values.size > 1) return true;
623
+ if (entry.hasNegatedExistence && entry.values.size > 0) return true;
624
+ }
625
+ return false;
626
+ }
627
+ const variantKeyCache = /* @__PURE__ */ new WeakMap();
628
+ /**
629
+ * Get a unique key for a variant (for deduplication).
630
+ * Cached via WeakMap since variants are compared multiple times during
631
+ * deduplication and sorting.
632
+ */
633
+ function getVariantKey(v) {
634
+ const cached = variantKeyCache.get(v);
635
+ if (cached !== void 0) return cached;
636
+ const modifierKey = v.modifierConditions.map(getModifierKey).sort().join("|");
637
+ const pseudoKey = v.pseudoConditions.map(getPseudoKey).sort().join("|");
638
+ const ownKey = v.ownConditions.map(getSelectorConditionKey).sort().join("|");
639
+ const containerKey = v.containerConditions.map((c) => `${c.name ?? ""}:${c.negated ? "!" : ""}${c.condition}`).sort().join("|");
640
+ const key = [
641
+ modifierKey,
642
+ pseudoKey,
643
+ ownKey,
644
+ v.mediaConditions.map((c) => `${c.subtype}:${c.negated ? "!" : ""}${c.condition}`).sort().join("|"),
645
+ containerKey,
646
+ v.supportsConditions.map((c) => `${c.subtype}:${c.negated ? "!" : ""}${c.condition}`).sort().join("|"),
647
+ v.rootConditions.map(getSelectorConditionKey).sort().join("|"),
648
+ v.parentGroups.map(getParentGroupKey).sort().join("|"),
649
+ v.startingStyle ? "1" : "0"
650
+ ].join("###");
651
+ variantKeyCache.set(v, key);
652
+ return key;
653
+ }
654
+ /**
655
+ * Check if variant A is a superset of variant B (A is more restrictive)
656
+ *
657
+ * If A has all of B's conditions plus more, then A is redundant
658
+ * because B already covers the same cases (and more).
659
+ *
660
+ * Example:
661
+ * A: :not([size=large]):not([size=medium]):not([size=small])
662
+ * B: :not([size=large])
663
+ * A is a superset of B, so A is redundant when B exists.
664
+ */
665
+ function isVariantSuperset(a, b) {
666
+ if (a.startingStyle !== b.startingStyle) return false;
667
+ if (!isSelectorConditionsSuperset(a.rootConditions, b.rootConditions)) return false;
668
+ if (!isMediaConditionsSuperset(a.mediaConditions, b.mediaConditions)) return false;
669
+ if (!isContainerConditionsSuperset(a.containerConditions, b.containerConditions)) return false;
670
+ if (!isSupportsConditionsSuperset(a.supportsConditions, b.supportsConditions)) return false;
671
+ if (!isModifierConditionsSuperset(a.modifierConditions, b.modifierConditions)) return false;
672
+ if (!isPseudoConditionsSuperset(a.pseudoConditions, b.pseudoConditions)) return false;
673
+ if (!isSelectorConditionsSuperset(a.ownConditions, b.ownConditions)) return false;
674
+ if (!isParentGroupsSuperset(a.parentGroups, b.parentGroups)) return false;
675
+ const parentConditionCount = (groups) => groups.reduce((sum, g) => sum + g.conditions.length, 0);
676
+ return a.mediaConditions.length + a.containerConditions.length + a.supportsConditions.length + a.modifierConditions.length + a.pseudoConditions.length + a.rootConditions.length + parentConditionCount(a.parentGroups) + a.ownConditions.length > b.mediaConditions.length + b.containerConditions.length + b.supportsConditions.length + b.modifierConditions.length + b.pseudoConditions.length + b.rootConditions.length + parentConditionCount(b.parentGroups) + b.ownConditions.length;
677
+ }
678
+ /**
679
+ * Generic superset check: true if every item in B has a matching key in A.
680
+ */
681
+ function isConditionsSuperset(a, b, getKey) {
682
+ const aKeys = new Set(a.map(getKey));
683
+ return b.every((c) => aKeys.has(getKey(c)));
684
+ }
685
+ function isMediaConditionsSuperset(a, b) {
686
+ return isConditionsSuperset(a, b, (c) => `${c.subtype}|${c.condition}|${c.negated}`);
687
+ }
688
+ function isContainerConditionsSuperset(a, b) {
689
+ return isConditionsSuperset(a, b, (c) => `${c.name ?? ""}|${c.condition}|${c.negated}`);
690
+ }
691
+ function isSupportsConditionsSuperset(a, b) {
692
+ return isConditionsSuperset(a, b, (c) => `${c.subtype}|${c.condition}|${c.negated}`);
693
+ }
694
+ function isModifierConditionsSuperset(a, b) {
695
+ return isConditionsSuperset(a, b, getModifierKey);
696
+ }
697
+ function isPseudoConditionsSuperset(a, b) {
698
+ return isConditionsSuperset(a, b, getPseudoKey);
699
+ }
700
+ function isSelectorConditionsSuperset(a, b) {
701
+ return isConditionsSuperset(a, b, getSelectorConditionKey);
702
+ }
703
+ /**
704
+ * Check if parent groups A is a superset of B.
705
+ * Each group in B must have a matching group in A.
706
+ */
707
+ function isParentGroupsSuperset(a, b) {
708
+ if (a.length < b.length) return false;
709
+ return isConditionsSuperset(a, b, getParentGroupKey);
710
+ }
711
+ function getParentGroupKey(g) {
712
+ return `${g.negated ? "!" : ""}${g.direct ? ">" : ""}(${g.conditions.map(getSelectorConditionKey).sort().join(",")})`;
713
+ }
714
+ /**
715
+ * Deduplicate variants
716
+ *
717
+ * Removes:
718
+ * 1. Exact duplicates (same key)
719
+ * 2. Superset variants (more restrictive selectors that are redundant)
720
+ */
721
+ function dedupeVariants(variants) {
722
+ const seen = /* @__PURE__ */ new Set();
723
+ const result = [];
724
+ for (const v of variants) {
725
+ const key = getVariantKey(v);
726
+ if (!seen.has(key)) {
727
+ seen.add(key);
728
+ result.push(v);
729
+ }
730
+ }
731
+ const variantConditionCount = (v) => v.modifierConditions.length + v.pseudoConditions.length + v.ownConditions.length + v.mediaConditions.length + v.containerConditions.length + v.supportsConditions.length + v.rootConditions.length + v.parentGroups.reduce((sum, g) => sum + g.conditions.length, 0);
732
+ result.sort((a, b) => {
733
+ const countDiff = variantConditionCount(a) - variantConditionCount(b);
734
+ if (countDiff !== 0) return countDiff;
735
+ return getVariantKey(a).localeCompare(getVariantKey(b));
736
+ });
737
+ const filtered = [];
738
+ for (const candidate of result) {
739
+ let isRedundant = false;
740
+ for (const kept of filtered) if (isVariantSuperset(candidate, kept)) {
741
+ isRedundant = true;
742
+ break;
743
+ }
744
+ if (!isRedundant) filtered.push(candidate);
745
+ }
746
+ return filtered;
747
+ }
748
+ /**
749
+ * Combine AND conditions into CSS
750
+ *
751
+ * AND of conditions means cartesian product of variants:
752
+ * (A1 | A2) & (B1 | B2) = A1&B1 | A1&B2 | A2&B1 | A2&B2
753
+ *
754
+ * Variants that result in contradictions (e.g., conflicting media rules)
755
+ * are filtered out.
756
+ */
757
+ function andToCSS(children) {
758
+ let currentVariants = [emptyVariant()];
759
+ for (const child of children) {
760
+ const childCSS = conditionToCSSInner(child);
761
+ if (childCSS.isImpossible || childCSS.variants.length === 0) return {
762
+ variants: [],
763
+ isImpossible: true
764
+ };
765
+ const newVariants = [];
766
+ for (const current of currentVariants) for (const childVariant of childCSS.variants) {
767
+ const merged = mergeVariants(current, childVariant);
768
+ if (merged !== null) newVariants.push(merged);
769
+ }
770
+ if (newVariants.length === 0) return {
771
+ variants: [],
772
+ isImpossible: true
773
+ };
774
+ currentVariants = dedupeVariants(newVariants);
775
+ }
776
+ return {
777
+ variants: currentVariants,
778
+ isImpossible: false
779
+ };
780
+ }
781
+ /**
782
+ * Combine OR conditions into CSS
783
+ *
784
+ * OR in CSS means multiple selector variants (DNF).
785
+ * Each variant becomes a separate selector in the comma-separated list,
786
+ * or multiple CSS rules if they have different at-rules.
787
+ *
788
+ * Note: OR exclusivity is handled at the pipeline level (expandOrConditions),
789
+ * so here we just collect all variants. Any remaining ORs in the condition
790
+ * tree (e.g., from De Morgan expansion) are handled as simple alternatives.
791
+ */
792
+ function orToCSS(children) {
793
+ const allVariants = [];
794
+ for (const child of children) {
795
+ const childCSS = conditionToCSSInner(child);
796
+ if (childCSS.isImpossible) continue;
797
+ allVariants.push(...childCSS.variants);
798
+ }
799
+ if (allVariants.length === 0) return {
800
+ variants: [],
801
+ isImpossible: true
802
+ };
803
+ return {
804
+ variants: dedupeVariants(allVariants),
805
+ isImpossible: false
806
+ };
807
+ }
808
+ /**
809
+ * Get a cache key for a condition
810
+ */
811
+ function getConditionKey(node) {
812
+ if (node.kind === "true") return "TRUE";
813
+ if (node.kind === "false") return "FALSE";
814
+ if (node.kind === "state") return node.uniqueId;
815
+ if (node.kind === "compound") {
816
+ const childKeys = node.children.map(getConditionKey).sort();
817
+ return `${node.operator}(${childKeys.join(",")})`;
818
+ }
819
+ return "UNKNOWN";
820
+ }
821
+ /**
822
+ * Build at-rules array from a variant
823
+ */
824
+ function buildAtRulesFromVariant(variant) {
825
+ const atRules = [];
826
+ if (variant.mediaConditions.length > 0) {
827
+ const conditionParts = variant.mediaConditions.map((c) => {
828
+ if (c.subtype === "type") return c.negated ? `not ${c.condition}` : c.condition;
829
+ else return c.negated ? `(not ${c.condition})` : c.condition;
830
+ });
831
+ atRules.push(`@media ${conditionParts.join(" and ")}`);
832
+ }
833
+ if (variant.containerConditions.length > 0) {
834
+ const byName = /* @__PURE__ */ new Map();
835
+ for (const cond of variant.containerConditions) {
836
+ const group = byName.get(cond.name) || [];
837
+ group.push(cond);
838
+ byName.set(cond.name, group);
839
+ }
840
+ for (const [name, conditions] of byName) {
841
+ const conditionParts = conditions.map((c) => c.negated ? `(not ${c.condition})` : c.condition);
842
+ const namePrefix = name ? `${name} ` : "";
843
+ atRules.push(`@container ${namePrefix}${conditionParts.join(" and ")}`);
844
+ }
845
+ }
846
+ if (variant.supportsConditions.length > 0) {
847
+ const conditionParts = variant.supportsConditions.map((c) => {
848
+ if (c.subtype === "selector") {
849
+ const selectorCond = `selector(${c.condition})`;
850
+ return c.negated ? `(not ${selectorCond})` : selectorCond;
851
+ } else {
852
+ const featureCond = `(${c.condition})`;
853
+ return c.negated ? `(not ${featureCond})` : featureCond;
854
+ }
855
+ });
856
+ atRules.push(`@supports ${conditionParts.join(" and ")}`);
857
+ }
858
+ if (variant.startingStyle) atRules.push("@starting-style");
859
+ return atRules;
860
+ }
861
+
862
+ //#endregion
863
+ export { buildAtRulesFromVariant, conditionToCSS, modifierToCSS, parentGroupsToCSS, pseudoToCSS, rootConditionsToCSS, selectorConditionToCSS };
864
+ //# sourceMappingURL=materialize.js.map