@bamboocss/core 1.11.1 → 1.11.2

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.
package/dist/index.cjs ADDED
@@ -0,0 +1,4055 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __exportAll = (all, no_symbols) => {
10
+ let target = {};
11
+ for (var name in all) __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
16
+ return target;
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
20
+ key = keys[i];
21
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
22
+ get: ((k) => from[k]).bind(null, key),
23
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
24
+ });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
29
+ value: mod,
30
+ enumerable: true
31
+ }) : target, mod));
32
+ //#endregion
33
+ let _bamboocss_logger = require("@bamboocss/logger");
34
+ let outdent = require("outdent");
35
+ let _bamboocss_shared = require("@bamboocss/shared");
36
+ let postcss = require("postcss");
37
+ postcss = __toESM(postcss);
38
+ let _bamboocss_is_valid_prop = require("@bamboocss/is-valid-prop");
39
+ let _bamboocss_token_dictionary = require("@bamboocss/token-dictionary");
40
+ let lodash_merge = require("lodash.merge");
41
+ lodash_merge = __toESM(lodash_merge);
42
+ let _csstools_postcss_cascade_layers = require("@csstools/postcss-cascade-layers");
43
+ _csstools_postcss_cascade_layers = __toESM(_csstools_postcss_cascade_layers);
44
+ let postcss_nested = require("postcss-nested");
45
+ postcss_nested = __toESM(postcss_nested);
46
+ let postcss_discard_duplicates = require("postcss-discard-duplicates");
47
+ postcss_discard_duplicates = __toESM(postcss_discard_duplicates);
48
+ let postcss_discard_empty = require("postcss-discard-empty");
49
+ postcss_discard_empty = __toESM(postcss_discard_empty);
50
+ let postcss_minify_selectors = require("postcss-minify-selectors");
51
+ postcss_minify_selectors = __toESM(postcss_minify_selectors);
52
+ let postcss_normalize_whitespace = require("postcss-normalize-whitespace");
53
+ postcss_normalize_whitespace = __toESM(postcss_normalize_whitespace);
54
+ let ts_pattern = require("ts-pattern");
55
+ let postcss_selector_parser = require("postcss-selector-parser");
56
+ postcss_selector_parser = __toESM(postcss_selector_parser);
57
+ //#region src/messages.ts
58
+ var messages_exports = /* @__PURE__ */ __exportAll({
59
+ artifactsGenerated: () => artifactsGenerated,
60
+ buildComplete: () => buildComplete,
61
+ codegenComplete: () => codegenComplete,
62
+ configExists: () => configExists,
63
+ configWatch: () => configWatch,
64
+ cssArtifactComplete: () => cssArtifactComplete,
65
+ exclamation: () => exclamation,
66
+ getMessages: () => getMessages,
67
+ noExtract: () => noExtract,
68
+ thankYou: () => thankYou,
69
+ watch: () => watch
70
+ });
71
+ const tick = _bamboocss_logger.colors.green().bold("✔️");
72
+ const artifactsGenerated = (ctx) => {
73
+ const { config: { outdir, themes }, recipes, patterns, tokens, jsx } = ctx;
74
+ return () => [
75
+ outdent.outdent`
76
+ ${tick} ${(0, _bamboocss_logger.quote)(outdir, "/css")}: the css function to author styles
77
+ `,
78
+ !tokens.isEmpty && outdent.outdent`
79
+ ${tick} ${(0, _bamboocss_logger.quote)(outdir, "/tokens")}: the css variables and js function to query your tokens
80
+ `,
81
+ !patterns.isEmpty() && !ctx.isTemplateLiteralSyntax && outdent.outdent`
82
+ ${tick} ${(0, _bamboocss_logger.quote)(outdir, "/patterns")}: functions to implement and apply common layout patterns
83
+ `,
84
+ !recipes.isEmpty() && outdent.outdent`
85
+ ${tick} ${(0, _bamboocss_logger.quote)(outdir, "/recipes")}: functions to create multi-variant styles
86
+ `,
87
+ jsx.framework && outdent.outdent`
88
+ ${tick} ${(0, _bamboocss_logger.quote)(outdir, "/jsx")}: styled jsx elements for ${jsx.framework}
89
+ `,
90
+ themes && outdent.outdent`
91
+ ${tick} ${(0, _bamboocss_logger.quote)(outdir, "/themes")}: theme variants for your design system
92
+ `,
93
+ "\n"
94
+ ].filter(Boolean).join("\n");
95
+ };
96
+ const configExists = (cmd) => outdent.outdent`
97
+ \n
98
+ It looks like you already have bamboo created\`.
99
+
100
+ You can now run ${(0, _bamboocss_logger.quote)(cmd, " bamboo --watch")}.
101
+
102
+ `;
103
+ const thankYou = () => outdent.outdent`
104
+
105
+ 🚀 Thanks for choosing ${_bamboocss_logger.colors.cyan("Bamboo")})} to write your css.
106
+
107
+ You are set up to start using Bamboo!
108
+
109
+ `;
110
+ const codegenComplete = () => outdent.outdent`
111
+
112
+ ${_bamboocss_logger.colors.bold().cyan("Next steps:")}
113
+
114
+ [1] Create a ${(0, _bamboocss_logger.quote)("index.css")} file in your project that contains:
115
+
116
+ @layer reset, base, tokens, recipes, utilities;
117
+
118
+
119
+ [2] Import the ${(0, _bamboocss_logger.quote)("index.css")} file at the root of your project.
120
+
121
+ `;
122
+ const noExtract = () => outdent.outdent`
123
+ No style object or props were detected in your source files.
124
+ If this is unexpected, double-check the \`include\` options in your Bamboo config\n
125
+ `;
126
+ const watch = () => outdent.outdent`
127
+ Watching for file changes...
128
+ `;
129
+ const configWatch = () => outdent.outdent`
130
+ Watching for config file changes...
131
+ `;
132
+ const buildComplete = (count) => outdent.outdent`
133
+ Successfully extracted css from ${count} file(s) ✨
134
+ `;
135
+ const randomWords = [
136
+ "Sweet",
137
+ "Divine",
138
+ "Bamboolicious",
139
+ "Super"
140
+ ];
141
+ const pickRandom = (arr) => arr[Math.floor(Math.random() * arr.length)];
142
+ const exclamation = () => `🎋 ${pickRandom(randomWords)}! ✨`;
143
+ const cssArtifactComplete = (type) => `Successfully generated ${type} css artifact ✨`;
144
+ const getMessages = (ctx) => ({
145
+ artifactsGenerated: artifactsGenerated(ctx),
146
+ configExists,
147
+ thankYou,
148
+ codegenComplete,
149
+ noExtract,
150
+ watch,
151
+ buildComplete,
152
+ configWatch,
153
+ cssArtifactComplete,
154
+ exclamation
155
+ });
156
+ //#endregion
157
+ //#region src/breakpoints.ts
158
+ var Breakpoints = class {
159
+ breakpoints;
160
+ sorted;
161
+ values;
162
+ keys;
163
+ ranges;
164
+ conditions;
165
+ constructor(breakpoints) {
166
+ this.breakpoints = breakpoints;
167
+ this.sorted = sortBreakpoints(breakpoints);
168
+ this.values = Object.fromEntries(this.sorted);
169
+ this.keys = ["base", ...Object.keys(this.values)];
170
+ this.ranges = this.getRanges();
171
+ this.conditions = this.getConditions();
172
+ }
173
+ get = (name) => {
174
+ return this.values[name];
175
+ };
176
+ build = ({ min, max }) => {
177
+ if (min == null && max == null) return "";
178
+ return [
179
+ "screen",
180
+ min && `(min-width: ${min})`,
181
+ max && `(max-width: ${max})`
182
+ ].filter(Boolean).join(" and ");
183
+ };
184
+ only = (name) => {
185
+ const { min, max } = this.get(name);
186
+ return this.build({
187
+ min,
188
+ max
189
+ });
190
+ };
191
+ getRanges = () => {
192
+ const breakpoints = Object.keys(this.values);
193
+ const permuations = getPermutations(breakpoints);
194
+ const values = breakpoints.flatMap((name) => {
195
+ const value = this.get(name);
196
+ const down = [`${name}Down`, this.build({ max: adjust(value.min) })];
197
+ return [
198
+ [name, this.build({ min: value.min })],
199
+ [`${name}Only`, this.only(name)],
200
+ down
201
+ ];
202
+ }).filter(([_, value]) => value !== "").concat(permuations.map(([min, max]) => {
203
+ const minValue = this.get(min);
204
+ const maxValue = this.get(max);
205
+ return [`${min}To${(0, _bamboocss_shared.capitalize)(max)}`, this.build({
206
+ min: minValue.min,
207
+ max: adjust(maxValue.min)
208
+ })];
209
+ }));
210
+ return Object.fromEntries(values);
211
+ };
212
+ getConditions = () => {
213
+ const values = Object.entries(this.ranges).map(([key, value]) => {
214
+ return [key, toCondition(key, value)];
215
+ });
216
+ return Object.fromEntries(values);
217
+ };
218
+ getCondition = (key) => {
219
+ return this.conditions[key];
220
+ };
221
+ expandScreenAtRule = (root) => {
222
+ root.walkAtRules("breakpoint", (rule) => {
223
+ const value = this.getCondition(rule.params);
224
+ if (!value) throw rule.error(`No \`${rule.params}\` screen found.`);
225
+ if (value.type !== "at-rule") throw rule.error(`\`${rule.params}\` is not a valid screen.`);
226
+ rule.name = "media";
227
+ rule.params = value.params;
228
+ });
229
+ };
230
+ };
231
+ function adjust(value) {
232
+ return (0, _bamboocss_shared.toRem)(`${parseFloat((0, _bamboocss_shared.toPx)(value) ?? "") - .04}px`);
233
+ }
234
+ function sortBreakpoints(breakpoints) {
235
+ return Object.entries(breakpoints).sort(([, minA], [, minB]) => {
236
+ return parseInt(minA, 10) < parseInt(minB, 10) ? -1 : 1;
237
+ }).map(([name, min], index, entries) => {
238
+ let max = null;
239
+ if (index <= entries.length - 1) max = entries[index + 1]?.[1];
240
+ if (max != null) max = adjust(max);
241
+ return [name, {
242
+ name,
243
+ min: (0, _bamboocss_shared.toRem)(min),
244
+ max
245
+ }];
246
+ });
247
+ }
248
+ const toCondition = (key, value) => ({
249
+ type: "at-rule",
250
+ name: "breakpoint",
251
+ value: key,
252
+ raw: `@media ${value}`,
253
+ params: value
254
+ });
255
+ function getPermutations(values) {
256
+ const result = [];
257
+ values.forEach((current, index) => {
258
+ let idx = index;
259
+ idx++;
260
+ let next = values[idx];
261
+ while (next) {
262
+ result.push([current, next]);
263
+ idx++;
264
+ next = values[idx];
265
+ }
266
+ });
267
+ return result;
268
+ }
269
+ //#endregion
270
+ //#region src/safe-parse.ts
271
+ function safeParse(str) {
272
+ try {
273
+ return postcss.default.parse(str);
274
+ } catch {
275
+ return postcss.default.root();
276
+ }
277
+ }
278
+ //#endregion
279
+ //#region src/parse-condition.ts
280
+ function parseAtRule(value) {
281
+ const rule = safeParse(value).nodes[0];
282
+ return {
283
+ type: "at-rule",
284
+ name: rule.name,
285
+ value: rule.params,
286
+ raw: value,
287
+ params: rule.params
288
+ };
289
+ }
290
+ /**
291
+ * Parses an object condition with `@slot` markers into condition blocks.
292
+ * Each path from root to `@slot` becomes an independent condition block.
293
+ *
294
+ * @example
295
+ * ```ts
296
+ * parseObjectCondition({
297
+ * "@media (hover: hover)": { "&:is(:hover, [data-hover])": "@slot" },
298
+ * "@media (hover: none)": { "&:is(:active, [data-active])": "@slot" },
299
+ * })
300
+ * ```
301
+ */
302
+ function parseObjectCondition(obj) {
303
+ const blocks = [];
304
+ function traverse(node, path) {
305
+ for (const [key, value] of Object.entries(node)) if (value === "@slot") {
306
+ const parsed = parseCondition([...path, key]);
307
+ if (parsed && parsed.type === "mixed" && parsed.value.length > 0) blocks.push(parsed);
308
+ } else if (typeof value === "object" && value !== null) traverse(value, [...path, key]);
309
+ }
310
+ traverse(obj, []);
311
+ if (blocks.length === 0) return void 0;
312
+ if (blocks.length === 1) return blocks[0];
313
+ return {
314
+ type: "multi-block",
315
+ value: blocks,
316
+ raw: obj
317
+ };
318
+ }
319
+ function parseCondition(condition) {
320
+ if (Array.isArray(condition)) return {
321
+ type: "mixed",
322
+ raw: condition,
323
+ value: condition.map(parseCondition).filter(Boolean)
324
+ };
325
+ if (typeof condition === "object" && condition !== null) return parseObjectCondition(condition);
326
+ if (condition.startsWith("@")) return parseAtRule(condition);
327
+ let type;
328
+ if (condition.startsWith("&")) type = "self-nesting";
329
+ else if (condition.endsWith(" &")) type = "parent-nesting";
330
+ else if (condition.includes("&")) type = "combinator-nesting";
331
+ if (type) return {
332
+ type,
333
+ value: condition,
334
+ raw: condition
335
+ };
336
+ }
337
+ //#endregion
338
+ //#region src/sort-at-rules.ts
339
+ const minMaxWidth = /(!?\(\s*min(-device-)?-width)(.|\n)+\(\s*max(-device)?-width/i;
340
+ const minWidth = /\(\s*min(-device)?-width/i;
341
+ const maxMinWidth = /(!?\(\s*max(-device)?-width)(.|\n)+\(\s*min(-device)?-width/i;
342
+ const maxWidth = /\(\s*max(-device)?-width/i;
343
+ const isMinWidth = _testQuery(minMaxWidth, maxMinWidth, minWidth);
344
+ const isMaxWidth = _testQuery(maxMinWidth, minMaxWidth, maxWidth);
345
+ const minMaxHeight = /(!?\(\s*min(-device)?-height)(.|\n)+\(\s*max(-device)?-height/i;
346
+ const minHeight = /\(\s*min(-device)?-height/i;
347
+ const maxMinHeight = /(!?\(\s*max(-device)?-height)(.|\n)+\(\s*min(-device)?-height/i;
348
+ const maxHeight = /\(\s*max(-device)?-height/i;
349
+ const isMinHeight = _testQuery(minMaxHeight, maxMinHeight, minHeight);
350
+ const isMaxHeight = _testQuery(maxMinHeight, minMaxHeight, maxHeight);
351
+ const isPrint = /print/i;
352
+ const isPrintOnly = /^print$/i;
353
+ const maxValue = Number.MAX_VALUE;
354
+ /**
355
+ * Obtain the length of the media request in pixels.
356
+ * Copy from original source `function inspectLength (length)`
357
+ */
358
+ function getQueryLength(query) {
359
+ let length = /(-?\d*\.?\d+)(ch|em|ex|px|rem)/.exec(query);
360
+ if (length === null && (isMinWidth(query) || isMinHeight(query))) length = /(\d)/.exec(query);
361
+ if (length === "0") return 0;
362
+ if (length === null) return maxValue;
363
+ let number = length[1];
364
+ switch (length[2]) {
365
+ case "ch":
366
+ number = parseFloat(number) * 8.8984375;
367
+ break;
368
+ case "em":
369
+ case "rem":
370
+ number = parseFloat(number) * 16;
371
+ break;
372
+ case "ex":
373
+ number = parseFloat(number) * 8.296875;
374
+ break;
375
+ case "px":
376
+ number = parseFloat(number);
377
+ break;
378
+ }
379
+ return +number;
380
+ }
381
+ /**
382
+ * Wrapper for creating test functions
383
+ * @private
384
+ * @param {RegExp} doubleTestTrue
385
+ * @param {RegExp} doubleTestFalse
386
+ * @param {RegExp} singleTest
387
+ * @return {Function}
388
+ */
389
+ function _testQuery(doubleTestTrue, doubleTestFalse, singleTest) {
390
+ /**
391
+ * @param {string} query
392
+ * @return {boolean}
393
+ */
394
+ return function(query) {
395
+ if (doubleTestTrue.test(query)) return true;
396
+ else if (doubleTestFalse.test(query)) return false;
397
+ return singleTest.test(query);
398
+ };
399
+ }
400
+ /**
401
+ * @private
402
+ * @param {string} a
403
+ * @param {string} b
404
+ * @return {number|null}
405
+ */
406
+ function _testIsPrint(a, b) {
407
+ const isPrintA = isPrint.test(a);
408
+ const isPrintOnlyA = isPrintOnly.test(a);
409
+ const isPrintB = isPrint.test(b);
410
+ const isPrintOnlyB = isPrintOnly.test(b);
411
+ if (isPrintA && isPrintB) {
412
+ if (!isPrintOnlyA && isPrintOnlyB) return 1;
413
+ if (isPrintOnlyA && !isPrintOnlyB) return -1;
414
+ return a.localeCompare(b);
415
+ }
416
+ if (isPrintA) return 1;
417
+ if (isPrintB) return -1;
418
+ return null;
419
+ }
420
+ function createSort(config = {}) {
421
+ const { unitlessMqAlwaysFirst } = config;
422
+ return function sortCSSmq(a, b) {
423
+ const testIsPrint = _testIsPrint(a, b);
424
+ if (testIsPrint !== null) return testIsPrint;
425
+ const minA = isMinWidth(a) || isMinHeight(a);
426
+ const maxA = isMaxWidth(a) || isMaxHeight(a);
427
+ const minB = isMinWidth(b) || isMinHeight(b);
428
+ const maxB = isMaxWidth(b) || isMaxHeight(b);
429
+ if (unitlessMqAlwaysFirst && (!minA && !maxA || !minB && !maxB)) {
430
+ if (!minA && !maxA && !minB && !maxB) return a.localeCompare(b);
431
+ return !minB && !maxB ? 1 : -1;
432
+ } else {
433
+ if (minA && maxB) return -1;
434
+ if (maxA && minB) return 1;
435
+ const lengthA = getQueryLength(a);
436
+ const lengthB = getQueryLength(b);
437
+ if (lengthA === maxValue && lengthB === maxValue) return a.localeCompare(b);
438
+ else if (lengthA === maxValue) return 1;
439
+ else if (lengthB === maxValue) return -1;
440
+ if (lengthA > lengthB) {
441
+ if (maxA) return -1;
442
+ return 1;
443
+ }
444
+ if (lengthA < lengthB) {
445
+ if (maxA) return 1;
446
+ return -1;
447
+ }
448
+ return a.localeCompare(b);
449
+ }
450
+ };
451
+ }
452
+ const sortAtRules = createSort();
453
+ //#endregion
454
+ //#region src/sort-style-rules.ts
455
+ const hasAtRule = (conditions) => conditions.some((details) => details.type === "at-rule" || details.type === "mixed" || details.type === "multi-block");
456
+ const styleOrder = [
457
+ ":link",
458
+ ":visited",
459
+ ":focus-within",
460
+ ":focus",
461
+ ":focus-visible",
462
+ ":hover",
463
+ ":active"
464
+ ];
465
+ const pseudoSelectorScore = (selector) => {
466
+ return styleOrder.findIndex((pseudoClass) => selector.includes(pseudoClass)) + 1;
467
+ };
468
+ const compareSelectors = (a, b) => {
469
+ const aConds = a.conditions;
470
+ const bConds = b.conditions;
471
+ if (aConds.length === bConds.length) {
472
+ const selector1 = aConds[0].value;
473
+ const selector2 = bConds[0].value;
474
+ return pseudoSelectorScore(selector1) - pseudoSelectorScore(selector2);
475
+ }
476
+ return aConds.length - bConds.length;
477
+ };
478
+ /**
479
+ * Flatten mixed conditions to Array<AtRuleCondition | SelectorCondition>
480
+ */
481
+ const flatten$1 = (conds) => conds.flatMap((cond) => {
482
+ if (cond.type === "mixed") return cond.value;
483
+ if (cond.type === "multi-block") return cond.value.flatMap((block) => block.value);
484
+ return cond;
485
+ });
486
+ /**
487
+ * Compare 2 Array<AtRuleCondition | SelectorCondition>
488
+ * - sort by condition length (shorter first)
489
+ * - sort at-rules by predefined order (sort-mq postcss plugin order)
490
+ * - sort selectors by predefined pseudo selector order
491
+ * - return 0 if equal
492
+ *
493
+ * do this for item in the array against the same index in the other array
494
+ * -> exit early if not equal
495
+ * -> if all comparisons result in a score of 0, return 0
496
+ */
497
+ const compareAtRuleOrMixed = (a, b) => {
498
+ const aConds = flatten$1(a.conditions);
499
+ const bConds = flatten$1(b.conditions);
500
+ let aCond, bCond;
501
+ const max = Math.max(aConds.length, bConds.length);
502
+ for (let i = 0; i < max; i++) {
503
+ aCond = aConds[i];
504
+ bCond = bConds[i];
505
+ if (!aCond) return -1;
506
+ if (!bCond) return 1;
507
+ if (aCond.type === "at-rule" && bCond.type.includes("nesting")) return 1;
508
+ if (aCond.type.includes("nesting") && bCond.type === "at-rule") return -1;
509
+ if (aCond.type === "at-rule" && bCond.type === "at-rule") {
510
+ const atRule1 = aCond.params ?? aCond.raw;
511
+ const atRule2 = bCond.params ?? bCond.raw;
512
+ if (!atRule1) return -1;
513
+ if (!atRule2) return 1;
514
+ const score = sortAtRules(atRule1, atRule2);
515
+ if (score !== 0) return score;
516
+ continue;
517
+ }
518
+ if (aCond.type.includes("nesting") && bCond.type.includes("nesting")) {
519
+ const nextACond = aConds[i + 1];
520
+ const nextBCond = bConds[i + 1];
521
+ if (Boolean(nextACond) === Boolean(nextBCond)) {
522
+ const score = pseudoSelectorScore(aCond.value) - pseudoSelectorScore(bCond.value);
523
+ if (score !== 0) return score;
524
+ }
525
+ }
526
+ }
527
+ return 0;
528
+ };
529
+ const sortByPropertyPriority = (a, b) => {
530
+ if (a.entry.prop === b.entry.prop) return 0;
531
+ return (0, _bamboocss_shared.getPropertyPriority)(a.entry.prop) - (0, _bamboocss_shared.getPropertyPriority)(b.entry.prop);
532
+ };
533
+ /**
534
+ * Sort style rules by conditions
535
+ * - with no conditions first
536
+ * - with selectors only next
537
+ * - with at-rules last
538
+ *
539
+ * for each of them:
540
+ * - sort by condition length (shorter first, the more you nest the more specific it is)
541
+ * - sort selectors by predefined pseudo selector order
542
+ * - sort at-rules by predefined order (sort-mq postcss plugin order)
543
+ * - sort by property priority (longhands first)
544
+ */
545
+ const sortStyleRules = (styleRules) => {
546
+ const declarations = [];
547
+ const withSelectorsOnly = [];
548
+ const withAtRules = [];
549
+ for (const styleRule of styleRules) if (!styleRule.conditions?.length) declarations.push(styleRule);
550
+ else if (!hasAtRule(styleRule.conditions)) withSelectorsOnly.push(styleRule);
551
+ else withAtRules.push(styleRule);
552
+ withSelectorsOnly.sort((a, b) => {
553
+ const selectorDiff = compareSelectors(a, b);
554
+ if (selectorDiff !== 0) return selectorDiff;
555
+ return sortByPropertyPriority(a, b);
556
+ });
557
+ withAtRules.sort((a, b) => {
558
+ const conditionDiff = compareAtRuleOrMixed(a, b);
559
+ if (conditionDiff !== 0) return conditionDiff;
560
+ return sortByPropertyPriority(a, b);
561
+ });
562
+ const sorted = declarations.sort(sortByPropertyPriority);
563
+ sorted.push(...withSelectorsOnly, ...withAtRules);
564
+ return sorted;
565
+ };
566
+ //#endregion
567
+ //#region src/conditions.ts
568
+ /**
569
+ * Checks if a condition is an at-rule type
570
+ */
571
+ const isAtRule = (cond) => cond.type === "at-rule";
572
+ /**
573
+ * Matches pseudo-element selectors (::before, ::after, ::placeholder, etc.)
574
+ * Pseudo-elements must appear at the end of CSS selector chains per the CSS spec.
575
+ */
576
+ const pseudoElementRegex$1 = /::[\w-]/;
577
+ const isPseudoElement = (cond) => typeof cond.raw === "string" && pseudoElementRegex$1.test(cond.raw);
578
+ /**
579
+ * Flattens a condition, extracting parts from mixed conditions.
580
+ * Returns an array of { condition, originalIndex } to track source order.
581
+ */
582
+ const flattenCondition = (cond, originalIndex) => {
583
+ if (cond.type === "mixed") return cond.value.map((part) => ({
584
+ cond: part,
585
+ originalIndex
586
+ }));
587
+ return [{
588
+ cond,
589
+ originalIndex
590
+ }];
591
+ };
592
+ const underscoreRegex = /^_/;
593
+ const selectorRegex = /&|@/;
594
+ var Conditions = class {
595
+ options;
596
+ values;
597
+ breakpoints;
598
+ constructor(options) {
599
+ this.options = options;
600
+ const { breakpoints: breakpointValues = {}, conditions = {} } = options;
601
+ const breakpoints = new Breakpoints(breakpointValues);
602
+ this.breakpoints = breakpoints;
603
+ const entries = Object.entries(conditions).map(([key, value]) => [`_${key}`, parseCondition(value)]);
604
+ const containers = this.setupContainers();
605
+ const themes = this.setupThemes();
606
+ this.values = {
607
+ ...Object.fromEntries(entries),
608
+ ...breakpoints.conditions,
609
+ ...containers,
610
+ ...themes
611
+ };
612
+ }
613
+ setupContainers = () => {
614
+ const { containerNames = [], containerSizes = {} } = this.options;
615
+ const containers = {};
616
+ containerNames.unshift("");
617
+ containerNames.forEach((name) => {
618
+ Object.entries(containerSizes).forEach(([size, value]) => {
619
+ const _value = (0, _bamboocss_shared.toRem)(value) ?? value;
620
+ containers[`@${name}/${size}`] = {
621
+ type: "at-rule",
622
+ name: "container",
623
+ value: _value,
624
+ raw: `@container ${name} (min-width: ${_value})`,
625
+ params: `${name} ${value}`
626
+ };
627
+ });
628
+ });
629
+ return containers;
630
+ };
631
+ setupThemes = () => {
632
+ const { themes = {} } = this.options;
633
+ const themeVariants = {};
634
+ Object.entries(themes).forEach(([theme, _themeVariant]) => {
635
+ const condName = this.getThemeName(theme);
636
+ const cond = parseCondition(this.getThemeSelector(theme) + " &");
637
+ if (!cond) return;
638
+ themeVariants[condName] = cond;
639
+ });
640
+ return themeVariants;
641
+ };
642
+ getThemeSelector = (name) => {
643
+ return `[data-bamboo-theme=${name}]`;
644
+ };
645
+ getThemeName = (theme) => {
646
+ return "_theme" + (0, _bamboocss_shared.capitalize)(theme);
647
+ };
648
+ finalize = (paths) => {
649
+ return paths.map((path) => {
650
+ if (this.has(path)) return path.replace(underscoreRegex, "");
651
+ if (selectorRegex.test(path)) return `[${(0, _bamboocss_shared.withoutSpace)(path.trim())}]`;
652
+ return path;
653
+ });
654
+ };
655
+ shift = (paths) => {
656
+ return paths.map((path) => path.trim()).sort((a, b) => {
657
+ const aIsCondition = this.isCondition(a);
658
+ const bIsCondition = this.isCondition(b);
659
+ if (aIsCondition && !bIsCondition) return 1;
660
+ if (!aIsCondition && bIsCondition) return -1;
661
+ if (!aIsCondition && !bIsCondition) return -1;
662
+ return 0;
663
+ });
664
+ };
665
+ segment = (paths) => {
666
+ const condition = [];
667
+ const selector = [];
668
+ for (const path of paths) if (this.isCondition(path)) condition.push(path);
669
+ else selector.push(path);
670
+ return {
671
+ condition,
672
+ selector
673
+ };
674
+ };
675
+ has = (key) => {
676
+ return Object.prototype.hasOwnProperty.call(this.values, key);
677
+ };
678
+ isCondition = (key) => {
679
+ return this.has(key) || !!this.getRaw(key) || (0, _bamboocss_shared.isBaseCondition)(key);
680
+ };
681
+ isEmpty = () => {
682
+ return Object.keys(this.values).length === 0;
683
+ };
684
+ get = (key) => {
685
+ return this.values[key]?.raw;
686
+ };
687
+ getRaw = (condNameOrQuery) => {
688
+ if (typeof condNameOrQuery === "string" && this.values[condNameOrQuery]) return this.values[condNameOrQuery];
689
+ try {
690
+ return parseCondition(condNameOrQuery);
691
+ } catch (error) {
692
+ const query = typeof condNameOrQuery === "string" ? condNameOrQuery : JSON.stringify(condNameOrQuery);
693
+ const message = error instanceof Error ? error.message : String(error);
694
+ _bamboocss_logger.logger.warn("core:condition", `Failed to parse condition "${query}": ${message}`);
695
+ }
696
+ };
697
+ sort = (conditions) => {
698
+ const flattened = conditions.map(this.getRaw).filter(Boolean).flatMap((cond, index) => flattenCondition(cond, index));
699
+ flattened.sort((a, b) => {
700
+ const aIsAtRule = isAtRule(a.cond);
701
+ const bIsAtRule = isAtRule(b.cond);
702
+ if (aIsAtRule && !bIsAtRule) return -1;
703
+ if (!aIsAtRule && bIsAtRule) return 1;
704
+ const aIsPseudo = isPseudoElement(a.cond);
705
+ if (aIsPseudo !== isPseudoElement(b.cond)) return aIsPseudo ? 1 : -1;
706
+ return a.originalIndex - b.originalIndex;
707
+ });
708
+ return flattened.map((item) => item.cond);
709
+ };
710
+ normalize = (condition) => {
711
+ return (0, _bamboocss_shared.isObject)(condition) ? condition : this.getRaw(condition);
712
+ };
713
+ keys = () => {
714
+ return Object.keys(this.values);
715
+ };
716
+ saveOne = (key, value) => {
717
+ const parsed = parseCondition(value);
718
+ if (!parsed) return;
719
+ this.values[`_${key}`] = parsed;
720
+ };
721
+ remove(key) {
722
+ delete this.values[`_${key}`];
723
+ }
724
+ getSortedKeys = () => {
725
+ return Object.keys(this.values).sort((a, b) => {
726
+ const aCondition = this.values[a];
727
+ const bCondition = this.values[b];
728
+ return compareAtRuleOrMixed({
729
+ entry: {},
730
+ conditions: [aCondition]
731
+ }, {
732
+ entry: {},
733
+ conditions: [bCondition]
734
+ });
735
+ });
736
+ };
737
+ };
738
+ //#endregion
739
+ //#region src/file.ts
740
+ var FileEngine = class {
741
+ context;
742
+ constructor(context) {
743
+ this.context = context;
744
+ }
745
+ get forceConsistentTypeExtension() {
746
+ return this.context.config.forceConsistentTypeExtension || false;
747
+ }
748
+ get outExtension() {
749
+ return this.context.config.outExtension;
750
+ }
751
+ ext(file) {
752
+ return `${file}.${this.outExtension}`;
753
+ }
754
+ extDts(file) {
755
+ return `${file}.${this.outExtension === "mjs" && this.forceConsistentTypeExtension ? "d.mts" : "d.ts"}`;
756
+ }
757
+ __extDts(file) {
758
+ return this.forceConsistentTypeExtension ? this.extDts(file) : file;
759
+ }
760
+ import(mod, file) {
761
+ return `import { ${mod} } from '${this.ext(file)}';`;
762
+ }
763
+ importType(mod, file) {
764
+ return `import type { ${mod} } from '${this.__extDts(file)}';`;
765
+ }
766
+ exportType(mod, file) {
767
+ return `export type { ${mod} } from '${this.__extDts(file)}';`;
768
+ }
769
+ exportStar(file) {
770
+ return `export * from '${this.ext(file)}';`;
771
+ }
772
+ exportTypeStar(file) {
773
+ return `export * from '${this.__extDts(file)}';`;
774
+ }
775
+ isTypeFile(file) {
776
+ return file.endsWith(".d.ts") || file.endsWith(".d.mts");
777
+ }
778
+ jsDocComment(comment, options) {
779
+ const { deprecated, default: defaultValue } = options ?? {};
780
+ if (!comment && !deprecated && !defaultValue) return "";
781
+ const comments = ["/**"];
782
+ if (comment) comments.push(` * ${comment}`, "\n");
783
+ if (deprecated) {
784
+ const suffix = (0, _bamboocss_shared.isString)(deprecated) ? ` ${deprecated}` : "";
785
+ comments.push(` * @deprecated${suffix}`);
786
+ }
787
+ if (defaultValue) comments.push(` * @default ${defaultValue}`);
788
+ comments.push(" */");
789
+ return comments.filter((c) => c.trim().length).join("\n");
790
+ }
791
+ /**
792
+ * convert import type { CompositionStyleObject } from './system-types'
793
+ * to import type { CompositionStyleObject } from './system-types.d.ts'
794
+ */
795
+ rewriteTypeImport(code) {
796
+ return code.replace(/import\s+type\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/g, this.importType("$1", "$2"));
797
+ }
798
+ };
799
+ //#endregion
800
+ //#region src/unitless.ts
801
+ const keys = {
802
+ animationIterationCount: true,
803
+ aspectRatio: true,
804
+ borderImageOutset: true,
805
+ borderImageSlice: true,
806
+ borderImageWidth: true,
807
+ boxFlex: true,
808
+ boxFlexGroup: true,
809
+ boxOrdinalGroup: true,
810
+ columnCount: true,
811
+ columns: true,
812
+ flex: true,
813
+ flexGrow: true,
814
+ flexPositive: true,
815
+ flexShrink: true,
816
+ flexNegative: true,
817
+ flexOrder: true,
818
+ gridRow: true,
819
+ gridRowEnd: true,
820
+ gridRowSpan: true,
821
+ gridRowStart: true,
822
+ gridColumn: true,
823
+ gridColumnEnd: true,
824
+ gridColumnSpan: true,
825
+ gridColumnStart: true,
826
+ msGridRow: true,
827
+ msGridRowSpan: true,
828
+ msGridColumn: true,
829
+ msGridColumnSpan: true,
830
+ fontWeight: true,
831
+ lineClamp: true,
832
+ lineHeight: true,
833
+ opacity: true,
834
+ order: true,
835
+ orphans: true,
836
+ scale: true,
837
+ tabSize: true,
838
+ widows: true,
839
+ zIndex: true,
840
+ zoom: true,
841
+ WebkitLineClamp: true,
842
+ fillOpacity: true,
843
+ floodOpacity: true,
844
+ stopOpacity: true,
845
+ strokeDasharray: true,
846
+ strokeDashoffset: true,
847
+ strokeMiterlimit: true,
848
+ strokeOpacity: true,
849
+ strokeWidth: true
850
+ };
851
+ const unitlessProperties = /* @__PURE__ */ new Set();
852
+ Object.keys(keys).forEach((key) => {
853
+ unitlessProperties.add(key);
854
+ unitlessProperties.add((0, _bamboocss_shared.hypenateProperty)(key));
855
+ });
856
+ //#endregion
857
+ //#region src/stringify.ts
858
+ const toString = Object.prototype.toString;
859
+ /** Returns a string of CSS from an object of CSS. */
860
+ function stringify(value) {
861
+ /** Set used to manage the opened and closed state of rules. */
862
+ const used = /* @__PURE__ */ new WeakSet();
863
+ const write = (cssText, selectors, conditions, name, data, isAtRuleLike, isVariableLike) => {
864
+ if (data === false) return "";
865
+ for (let i = 0; i < conditions.length; ++i) if (!used.has(conditions[i])) {
866
+ used.add(conditions[i]);
867
+ cssText += `${conditions[i]} {`;
868
+ }
869
+ if (selectors.length && !used.has(selectors)) {
870
+ used.add(selectors);
871
+ cssText += `${selectors.map((s) => s.replace("& ", ""))} {`;
872
+ }
873
+ let value = data;
874
+ if (typeof value === "number") {
875
+ if (!(value === 0 || unitlessProperties.has(name) || isVariableLike)) value = `${value}px`;
876
+ }
877
+ if (isAtRuleLike) name = `${name} `;
878
+ else if (isVariableLike) name = `${name}: `;
879
+ else name = `${(0, _bamboocss_shared.hypenateProperty)(name)}: `;
880
+ cssText += `${name + String(value)};\n`;
881
+ return cssText;
882
+ };
883
+ const parse = (style, selectors, conditions) => {
884
+ let cssText = "";
885
+ for (const name in style) {
886
+ const isAtRuleLike = name[0] === "@";
887
+ const isVariableLike = !isAtRuleLike && name.startsWith("--");
888
+ const rules = isAtRuleLike && Array.isArray(style[name]) ? style[name] : [style[name]];
889
+ for (const data of rules) {
890
+ if (!(typeof data === "object" && data && data.toString === toString)) {
891
+ cssText = write(cssText, selectors, conditions, name, data, isAtRuleLike, isVariableLike);
892
+ continue;
893
+ }
894
+ if (used.has(selectors)) {
895
+ used.delete(selectors);
896
+ cssText += "}";
897
+ }
898
+ let usedName = Object(name);
899
+ let nextSelectors;
900
+ if (isAtRuleLike) {
901
+ if (selectors.length && name.includes("@scope") && name.includes("&")) {
902
+ const resolvedSelectors = getResolvedSelectors(selectors, parseSelectors(name));
903
+ usedName = Object(resolvedSelectors[0]);
904
+ }
905
+ nextSelectors = selectors;
906
+ cssText += parse(data, nextSelectors, conditions.concat(usedName));
907
+ } else {
908
+ const nestedSelectors = parseSelectors(name);
909
+ nextSelectors = selectors.length ? getResolvedSelectors(selectors, nestedSelectors) : nestedSelectors;
910
+ cssText += parse(data, nextSelectors, conditions);
911
+ }
912
+ if (used.has(usedName)) {
913
+ used.delete(usedName);
914
+ cssText += "}\n";
915
+ }
916
+ if (used.has(nextSelectors)) {
917
+ used.delete(nextSelectors);
918
+ cssText += "}\n";
919
+ }
920
+ }
921
+ }
922
+ return cssText;
923
+ };
924
+ return parse(value, [], []);
925
+ }
926
+ /**
927
+ * Returns a list of separated selectors from a selector string.
928
+ * @example
929
+ * parseSelectors('a, button') // ['a', 'button']
930
+ * parseSelectors('.switch:is(:checked, [data-checked]).dark, .dark .switch:is(:checked, [data-checked])') // ['.switch:is(:checked, [data-checked]).dark', '.dark .switch:is(:checked, [data-checked])']
931
+ * parseSelectors('&:is(:disabled, [disabled], [data-disabled]), .another') // [':is(:disabled, [disabled], [data-disabled])', '.another']
932
+ */
933
+ function parseSelectors(selector) {
934
+ const result = [];
935
+ let parenCount = 0;
936
+ let currentSelector = "";
937
+ let inEscape = false;
938
+ for (let i = 0; i < selector.length; i++) {
939
+ const char = selector[i];
940
+ if (char === "\\" && !inEscape) {
941
+ inEscape = true;
942
+ currentSelector += char;
943
+ continue;
944
+ }
945
+ if (inEscape) {
946
+ inEscape = false;
947
+ currentSelector += char;
948
+ continue;
949
+ }
950
+ if (char === "(") parenCount++;
951
+ else if (char === ")") parenCount--;
952
+ if (char === "," && parenCount === 0) {
953
+ result.push(currentSelector.trim());
954
+ currentSelector = "";
955
+ } else currentSelector += char;
956
+ }
957
+ if (currentSelector) result.push(currentSelector.trim());
958
+ return result;
959
+ }
960
+ const parentSelectorRegex = /&/g;
961
+ const descendantSelectorRegex = /[ +>|~]/g;
962
+ const surroundedRegex = /&.*&/g;
963
+ /**
964
+ * Returns selectors resolved from parent selectors and nested selectors.
965
+ * @example
966
+ * getResolvedSelectors(['a', 'button'], ['&:hover', '&:focus']) // ['a:hover', 'a:focus', 'button:hover', 'button:focus']
967
+ * getResolvedSelectors(['.switch:is(:checked, [data-checked]).dark, .dark .switch:is(:checked, [data-checked])'], ['&:hover', '&:focus']) // ['.switch:is(:checked, [data-checked]).dark:hover', '.switch:is(:checked, [data-checked]).dark:focus', '.dark .switch:is(:checked, [data-checked]):hover', '.dark .switch:is(:checked, [data-checked]):focus']
968
+ *
969
+ */
970
+ const getResolvedSelectors = (parentSelectors, nestedSelectors) => {
971
+ const resolved = [];
972
+ parentSelectors.forEach((parentSelector) => {
973
+ resolved.push(...nestedSelectors.map((selector) => {
974
+ if (!selector.includes("&")) return parentSelector + " " + selector;
975
+ return selector.replace(parentSelectorRegex, descendantSelectorRegex.test(parentSelector) && surroundedRegex.test(selector) ? `:is(${parentSelector})` : parentSelector);
976
+ }));
977
+ });
978
+ return resolved;
979
+ };
980
+ //#endregion
981
+ //#region src/global-fontface.ts
982
+ var GlobalFontface = class {
983
+ options;
984
+ names;
985
+ constructor(options) {
986
+ this.options = options;
987
+ const { globalFontface = {} } = options;
988
+ this.names = Object.keys(globalFontface);
989
+ }
990
+ isEmpty() {
991
+ return this.names.length === 0;
992
+ }
993
+ toString() {
994
+ const { globalFontface = {} } = this.options;
995
+ return stringifyGlobalFontface(globalFontface);
996
+ }
997
+ };
998
+ const stringifyGlobalFontface = (globalFontface) => {
999
+ if (!globalFontface) return "";
1000
+ const lines = [];
1001
+ Object.entries(globalFontface).forEach(([key, value]) => {
1002
+ (Array.isArray(value) ? value : [value]).forEach((v) => {
1003
+ lines.push(stringifyFontface(key, v));
1004
+ });
1005
+ });
1006
+ return lines.join("\n\n");
1007
+ };
1008
+ function stringifyFontface(fontFamily, config) {
1009
+ return `@font-face {
1010
+ font-family: ${fontFamily};
1011
+ ${stringify(config)}
1012
+ }`;
1013
+ }
1014
+ //#endregion
1015
+ //#region src/global-position-try.ts
1016
+ var GlobalPositionTry = class {
1017
+ opts;
1018
+ names;
1019
+ constructor(opts) {
1020
+ this.opts = opts;
1021
+ this.names = Object.keys(opts.globalPositionTry ?? {});
1022
+ }
1023
+ isEmpty() {
1024
+ return this.names.length === 0;
1025
+ }
1026
+ toString() {
1027
+ return stringifyGlobalPositionTry(this.opts.globalPositionTry ?? {});
1028
+ }
1029
+ };
1030
+ const stringifyGlobalPositionTry = (dfns) => {
1031
+ if (!dfns) return "";
1032
+ const lines = [];
1033
+ Object.entries(dfns).forEach(([key, value]) => {
1034
+ (Array.isArray(value) ? value : [value]).forEach((v) => {
1035
+ lines.push(stringifyPositionTry(key, v));
1036
+ });
1037
+ });
1038
+ return lines.join("\n\n");
1039
+ };
1040
+ const ident = (key) => key.startsWith("--") ? key : `--${key}`;
1041
+ function stringifyPositionTry(key, config) {
1042
+ return `@position-try ${ident(key)} {
1043
+ ${stringify(config)}
1044
+ }`;
1045
+ }
1046
+ //#endregion
1047
+ //#region src/global-vars.ts
1048
+ var GlobalVars = class {
1049
+ options;
1050
+ keys;
1051
+ vars;
1052
+ names;
1053
+ constructor(options) {
1054
+ this.options = options;
1055
+ const { globalVars = {} } = options;
1056
+ this.keys = new Set(Object.keys(globalVars));
1057
+ const arr = Array.from(this.keys);
1058
+ this.names = arr.map((v) => `${v.slice(2)}`);
1059
+ this.vars = arr.map((v) => `var(${v})`);
1060
+ }
1061
+ isEmpty() {
1062
+ return this.keys.size === 0;
1063
+ }
1064
+ toString() {
1065
+ const { globalVars = {}, cssVarRoot } = this.options;
1066
+ return stringifyGlobalVars(globalVars, cssVarRoot);
1067
+ }
1068
+ };
1069
+ const stringifyGlobalVars = (globalVars, cssVarRoot) => {
1070
+ if (!globalVars) return "";
1071
+ const decls = [];
1072
+ const vars = { [cssVarRoot]: {} };
1073
+ const base = vars[cssVarRoot];
1074
+ Object.entries(globalVars).forEach(([key, value]) => {
1075
+ if (typeof value === "string") {
1076
+ base[key] = value;
1077
+ return;
1078
+ }
1079
+ const css = stringifyProperty(key, value);
1080
+ decls.push(css);
1081
+ });
1082
+ const lines = [];
1083
+ lines.push(stringify(vars));
1084
+ lines.push(...decls);
1085
+ return lines.join("\n\n");
1086
+ };
1087
+ function stringifyProperty(key, config) {
1088
+ return outdent.outdent`@property ${key} {
1089
+ syntax: '${config.syntax}';
1090
+ inherits: ${config.inherits};
1091
+ initial-value: ${config.initialValue ?? "initial"};
1092
+ }`;
1093
+ }
1094
+ //#endregion
1095
+ //#region src/rule-processor.ts
1096
+ var RuleProcessor = class {
1097
+ context;
1098
+ encoder;
1099
+ decoder;
1100
+ sheet;
1101
+ constructor(context) {
1102
+ this.context = context;
1103
+ this.encoder = context.encoder;
1104
+ this.decoder = context.decoder;
1105
+ this.sheet = context.createSheet();
1106
+ }
1107
+ getParamsOrThrow() {
1108
+ if (!Boolean(this.encoder && this.decoder && this.sheet)) throw new _bamboocss_shared.BambooError("MISSING_PARAMS", "RuleProcessor is missing params, please call `clone` first");
1109
+ return {
1110
+ encoder: this.encoder,
1111
+ decoder: this.decoder,
1112
+ sheet: this.sheet
1113
+ };
1114
+ }
1115
+ clone() {
1116
+ this.encoder = this.context.encoder.clone();
1117
+ this.decoder = this.context.decoder.clone();
1118
+ this.sheet = this.context.createSheet();
1119
+ return this;
1120
+ }
1121
+ toCss(options) {
1122
+ const { decoder, sheet } = this.getParamsOrThrow();
1123
+ sheet.processDecoder(decoder);
1124
+ return sheet.toCss(options);
1125
+ }
1126
+ css(styles) {
1127
+ const { encoder, decoder } = this.getParamsOrThrow();
1128
+ encoder.processAtomic(styles);
1129
+ decoder.collect(encoder);
1130
+ return {
1131
+ styles,
1132
+ getClassNames: () => Array.from(decoder.classNames.keys()),
1133
+ toCss: this.toCss.bind(this)
1134
+ };
1135
+ }
1136
+ grouped(styles) {
1137
+ const { encoder, decoder } = this.getParamsOrThrow();
1138
+ encoder.processGrouped(styles);
1139
+ decoder.collect(encoder);
1140
+ const groupedResults = Array.from(decoder.grouped);
1141
+ return {
1142
+ styles,
1143
+ getClassNames: () => groupedResults.map((r) => r.className),
1144
+ toCss: this.toCss.bind(this)
1145
+ };
1146
+ }
1147
+ cva(recipeConfig) {
1148
+ const { encoder, decoder } = this.getParamsOrThrow();
1149
+ encoder.processAtomicRecipe(recipeConfig);
1150
+ decoder.collect(encoder);
1151
+ return {
1152
+ config: recipeConfig,
1153
+ getClassNames: () => Array.from(decoder.classNames.keys()),
1154
+ toCss: this.toCss.bind(this)
1155
+ };
1156
+ }
1157
+ sva(recipeConfig) {
1158
+ const { encoder, decoder } = this;
1159
+ this.getParamsOrThrow();
1160
+ encoder.processAtomicSlotRecipe(recipeConfig);
1161
+ decoder.collect(encoder);
1162
+ return {
1163
+ config: recipeConfig,
1164
+ getClassNames: () => Array.from(decoder.classNames.keys()),
1165
+ toCss: this.toCss.bind(this)
1166
+ };
1167
+ }
1168
+ recipe(name, variants = {}) {
1169
+ const { encoder, decoder } = this;
1170
+ this.getParamsOrThrow();
1171
+ encoder.processRecipe(name, variants);
1172
+ decoder.collect(encoder);
1173
+ return {
1174
+ variants,
1175
+ getClassNames: () => Array.from(decoder.classNames.keys()),
1176
+ toCss: this.toCss.bind(this)
1177
+ };
1178
+ }
1179
+ };
1180
+ //#endregion
1181
+ //#region src/hooks-api.ts
1182
+ var HooksApi = class {
1183
+ ctx;
1184
+ processor;
1185
+ constructor(ctx) {
1186
+ this.ctx = ctx;
1187
+ this.processor = new RuleProcessor(ctx);
1188
+ }
1189
+ get config() {
1190
+ return this.ctx.conf.config;
1191
+ }
1192
+ get configPath() {
1193
+ return this.ctx.conf.path;
1194
+ }
1195
+ get configDependencies() {
1196
+ return this.ctx.conf.dependencies;
1197
+ }
1198
+ get classNames() {
1199
+ return this.ctx.utility.classNames;
1200
+ }
1201
+ get generatedClassNames() {
1202
+ return this.ctx.decoder.classNames;
1203
+ }
1204
+ };
1205
+ //#endregion
1206
+ //#region src/file-matcher.ts
1207
+ const cssEntrypointFns = new Set([
1208
+ "css",
1209
+ "cva",
1210
+ "sva"
1211
+ ]);
1212
+ var FileMatcher = class {
1213
+ context;
1214
+ imports;
1215
+ namespaces = /* @__PURE__ */ new Map();
1216
+ importMap;
1217
+ cssAliases = /* @__PURE__ */ new Set();
1218
+ cvaAliases = /* @__PURE__ */ new Set();
1219
+ svaAliases = /* @__PURE__ */ new Set();
1220
+ tokenAliases = /* @__PURE__ */ new Set();
1221
+ jsxFactoryAliases = /* @__PURE__ */ new Set();
1222
+ recipeAliases = /* @__PURE__ */ new Set();
1223
+ patternAliases = /* @__PURE__ */ new Set();
1224
+ propertiesMap = /* @__PURE__ */ new Map();
1225
+ functions = /* @__PURE__ */ new Map();
1226
+ components = /* @__PURE__ */ new Map();
1227
+ constructor(context, opts) {
1228
+ this.context = context;
1229
+ const { value, importMap } = opts;
1230
+ this.importMap = importMap;
1231
+ this.imports = value;
1232
+ this.imports.forEach((result) => {
1233
+ if (result.kind === "namespace") this.namespaces.set(result.name, result);
1234
+ });
1235
+ this.assignAliases();
1236
+ this.assignProperties();
1237
+ }
1238
+ assignAliases() {
1239
+ const isCssEntrypoint = this.createMatch(this.importMap.css, Array.from(cssEntrypointFns));
1240
+ const isTokensEntrypoint = this.createMatch(this.importMap.tokens, ["token"]);
1241
+ this.imports.forEach((result) => {
1242
+ if (this.isValidRecipe(result.alias)) this.recipeAliases.add(result.alias);
1243
+ if (this.isValidPattern(result.alias)) this.patternAliases.add(result.alias);
1244
+ if (isCssEntrypoint(result.alias)) {
1245
+ if (result.name === "css") this.cssAliases.add(result.alias);
1246
+ if (result.name === "cva") this.cvaAliases.add(result.alias);
1247
+ if (result.name === "sva") this.svaAliases.add(result.alias);
1248
+ }
1249
+ if (isTokensEntrypoint(result.alias)) {
1250
+ if (result.name === "token") this.tokenAliases.add(result.alias);
1251
+ }
1252
+ if (result.name === this.context.jsx.factoryName) this.jsxFactoryAliases.add(result.alias);
1253
+ if (result.kind === "namespace") {
1254
+ if (this.importMap.pattern.some((m) => result.mod.includes(m))) this.context.patterns.keys.forEach((pattern) => {
1255
+ this.patternAliases.add(pattern);
1256
+ });
1257
+ if (this.importMap.recipe.some((m) => result.mod.includes(m))) this.context.recipes.keys.forEach((recipe) => {
1258
+ this.recipeAliases.add(recipe);
1259
+ });
1260
+ }
1261
+ });
1262
+ }
1263
+ assignProperties() {
1264
+ this.context.jsx.nodes.forEach((node) => {
1265
+ this.getAliases(node.jsxName).forEach((alias) => {
1266
+ node.props?.forEach((prop) => this.propertiesMap.set(prop, true));
1267
+ this.functions.set(node.baseName, this.propertiesMap);
1268
+ this.functions.set(alias, this.propertiesMap);
1269
+ this.components.set(alias, this.propertiesMap);
1270
+ });
1271
+ });
1272
+ }
1273
+ isEmpty = () => {
1274
+ return this.imports.length === 0;
1275
+ };
1276
+ toString = () => {
1277
+ return this.imports.map((item) => item.alias).join(", ");
1278
+ };
1279
+ find = (id) => {
1280
+ return this.imports.find((o) => o.alias === id);
1281
+ };
1282
+ createMatch = (mods, keys) => {
1283
+ const matchingImports = this.imports.filter((o) => {
1284
+ const isFromMod = mods.some((m) => o.mod.includes(m) || o.importMapValue?.includes(m));
1285
+ const isOneOfKeys = o.kind === "namespace" ? true : keys.includes(o.name);
1286
+ return isFromMod && isOneOfKeys;
1287
+ });
1288
+ return (0, _bamboocss_shared.memo)((id) => {
1289
+ return !!matchingImports.find((mod) => {
1290
+ if (mod.kind === "namespace") return keys.includes(id.replace(`${mod.alias}.`, ""));
1291
+ return mod.alias === id || mod.name === id;
1292
+ });
1293
+ });
1294
+ };
1295
+ match = (id) => {
1296
+ return !!this.find(id);
1297
+ };
1298
+ getName = (id) => {
1299
+ return this.find(id)?.name || id;
1300
+ };
1301
+ getAliases = (id) => {
1302
+ return this.imports.filter((o) => o.name === id).map((o) => o.alias || id);
1303
+ };
1304
+ _patternsMatcher;
1305
+ isValidPattern = (id) => {
1306
+ this._patternsMatcher ||= this.createMatch(this.importMap.pattern, this.context.patterns.keys);
1307
+ return this._patternsMatcher(id);
1308
+ };
1309
+ _recipesMatcher;
1310
+ isValidRecipe = (id) => {
1311
+ this._recipesMatcher ||= this.createMatch(this.importMap.recipe, this.context.recipes.keys);
1312
+ return this._recipesMatcher(id);
1313
+ };
1314
+ isRawFn = (fnName) => {
1315
+ const name = fnName.split(".raw")[0] ?? "";
1316
+ return name === "css" || this.cssAliases.has(name) || this.cvaAliases.has(name) || this.svaAliases.has(name) || this.isValidPattern(name) || this.isValidRecipe(name);
1317
+ };
1318
+ isNamespaced = (fnName) => {
1319
+ return this.namespaces.has(fnName.split(".")[0]);
1320
+ };
1321
+ normalizeFnName = (fnName) => {
1322
+ let name = fnName;
1323
+ if (this.isNamespaced(fnName)) name = name.split(".").slice(1).join(".");
1324
+ if (this.isRawFn(name)) return name.replace(".raw", "");
1325
+ return name;
1326
+ };
1327
+ isAliasFnName = (0, _bamboocss_shared.memo)((fnName) => {
1328
+ return this.cvaAliases.has(fnName) || this.cssAliases.has(fnName) || this.svaAliases.has(fnName) || this.tokenAliases.has(fnName) || this.isJsxFactory(fnName);
1329
+ });
1330
+ isTokenAlias = (fnName) => {
1331
+ return this.tokenAliases.has(fnName);
1332
+ };
1333
+ matchFn = (0, _bamboocss_shared.memo)((fnName) => {
1334
+ if (this.recipeAliases.has(fnName) || this.patternAliases.has(fnName)) return true;
1335
+ if (this.isAliasFnName(fnName) || this.isRawFn(fnName)) return true;
1336
+ if (this.functions.has(fnName)) return true;
1337
+ const [namespace, identifier] = fnName.split(".");
1338
+ const ns = this.namespaces.get(namespace);
1339
+ if (ns) {
1340
+ if (this.importMap.css.some((m) => ns.mod.includes(m)) && cssEntrypointFns.has(identifier)) return true;
1341
+ if (this.importMap.tokens.some((m) => ns.mod.includes(m)) && identifier === "token") return true;
1342
+ if (this.importMap.recipe.some((m) => ns.mod.includes(m)) && this.recipeAliases.has(identifier)) return true;
1343
+ if (this.importMap.pattern.some((m) => ns.mod.includes(m)) && this.patternAliases.has(identifier)) return true;
1344
+ return this.functions.has(identifier);
1345
+ }
1346
+ return false;
1347
+ });
1348
+ isJsxFactory = (0, _bamboocss_shared.memo)((tagName) => {
1349
+ const { jsx } = this.context;
1350
+ if (!jsx.isEnabled) return false;
1351
+ for (const alias of this.jsxFactoryAliases) if (tagName.startsWith(alias)) return true;
1352
+ const [namespace, identifier] = tagName.split(".");
1353
+ const ns = this.namespaces.get(namespace);
1354
+ if (ns && this.importMap.jsx.some((m) => ns.mod.includes(m)) && identifier === this.context.jsx.factoryName) return true;
1355
+ });
1356
+ isBambooComponent = (0, _bamboocss_shared.memo)((tagName) => {
1357
+ if (!tagName) return false;
1358
+ const { jsx } = this.context;
1359
+ return this.components.has(tagName) || this.isJsxFactory(tagName) || jsx.isJsxTagRecipe(tagName) || jsx.isJsxTagPattern(tagName);
1360
+ });
1361
+ matchTag = (0, _bamboocss_shared.memo)((tagName) => {
1362
+ return this.isBambooComponent(tagName) || isUpperCase(tagName);
1363
+ });
1364
+ matchTagProp = (0, _bamboocss_shared.memo)((tagName, propName) => {
1365
+ const { jsx, isValidProperty } = this.context;
1366
+ switch (jsx.styleProps) {
1367
+ case "all": return Boolean(this.components.get(tagName)?.has(propName)) || isValidProperty(propName) || this.propertiesMap.has(propName) || jsx.isRecipeOrPatternProp(tagName, propName) || propName.endsWith("Css");
1368
+ case "minimal": return propName === "css" || propName.endsWith("Css") || jsx.isRecipeOrPatternProp(tagName, propName);
1369
+ case "none": return jsx.isRecipeOrPatternProp(tagName, propName);
1370
+ default: return false;
1371
+ }
1372
+ });
1373
+ };
1374
+ const isUpperCase = (value) => value[0] === value[0]?.toUpperCase();
1375
+ //#endregion
1376
+ //#region src/import-map.ts
1377
+ var ImportMap = class {
1378
+ context;
1379
+ value;
1380
+ matchers = {};
1381
+ outdir;
1382
+ constructor(context) {
1383
+ this.context = context;
1384
+ const { jsx } = this.context;
1385
+ this.outdir = this.getOutdir();
1386
+ const importMap = this.buildImportMap(context.config.importMap);
1387
+ this.matchers.css = this.createMatcher(importMap.css, [
1388
+ "css",
1389
+ "cva",
1390
+ "sva"
1391
+ ]);
1392
+ this.matchers.tokens = this.createMatcher(importMap.tokens, ["token"]);
1393
+ this.matchers.recipe = this.createMatcher(importMap.recipe);
1394
+ this.matchers.pattern = this.createMatcher(importMap.pattern);
1395
+ if (jsx.isEnabled) this.matchers.jsx = this.createMatcher(importMap.jsx, jsx.names);
1396
+ this.value = importMap;
1397
+ }
1398
+ /**
1399
+ * Normalize one/many import map inputs to a single import map output with absolute paths.
1400
+ * @example
1401
+ * ```ts
1402
+ * importMap: '@acme/org'
1403
+ * ```
1404
+ *
1405
+ * will be normalized to
1406
+ * ```ts
1407
+ * {
1408
+ * css: ['@acme/org/css'],
1409
+ * recipe: ['@acme/org/recipes'],
1410
+ * pattern: ['@acme/org/patterns'],
1411
+ * jsx: ['@acme/org/jsx'],
1412
+ * tokens: ['@acme/org/tokens'],
1413
+ * }
1414
+ * ```
1415
+ *
1416
+ * @exammple
1417
+ * importMap: ['@acme/org', '@foo/org', '@bar/org']
1418
+ * ```
1419
+ *
1420
+ * will be normalized to
1421
+ * ```ts
1422
+ * {
1423
+ * css: ['@acme/org/css', '@foo/org/css', '@bar/org/css'],
1424
+ * recipe: ['@acme/org/recipes', '@foo/org/recipes', '@bar/org/recipes'],
1425
+ * pattern: ['@acme/org/patterns', '@foo/org/patterns', '@bar/org/patterns'],
1426
+ * jsx: ['@acme/org/jsx', '@foo/org/jsx', '@bar/org/jsx'],
1427
+ * tokens: ['@acme/org/tokens', '@foo/org/tokens', '@bar/org/tokens'],
1428
+ * }
1429
+ * ```
1430
+ */
1431
+ buildImportMap = (option) => {
1432
+ const output = {
1433
+ css: [],
1434
+ recipe: [],
1435
+ pattern: [],
1436
+ jsx: [],
1437
+ tokens: []
1438
+ };
1439
+ asArray(option).forEach((input) => {
1440
+ const normalized = this.normalize(input);
1441
+ output.css.push(...normalized.css);
1442
+ output.recipe.push(...normalized.recipe);
1443
+ output.pattern.push(...normalized.pattern);
1444
+ output.tokens.push(...normalized.tokens);
1445
+ if (normalized.jsx) output.jsx.push(...normalized.jsx);
1446
+ });
1447
+ return output;
1448
+ };
1449
+ fromString = (map) => {
1450
+ return {
1451
+ css: [[map, "css"].join("/")],
1452
+ recipe: [[map, "recipes"].join("/")],
1453
+ pattern: [[map, "patterns"].join("/")],
1454
+ jsx: [[map, "jsx"].join("/")],
1455
+ tokens: [[map, "tokens"].join("/")]
1456
+ };
1457
+ };
1458
+ fromInput = (map) => {
1459
+ const { css, recipes, patterns, jsx, tokens } = map ?? {};
1460
+ return {
1461
+ css: css ? asArray(css) : [[this.outdir, "css"].join("/")],
1462
+ recipe: recipes ? asArray(recipes) : [[this.outdir, "recipes"].join("/")],
1463
+ pattern: patterns ? asArray(patterns) : [[this.outdir, "patterns"].join("/")],
1464
+ jsx: jsx ? asArray(jsx) : [[this.outdir, "jsx"].join("/")],
1465
+ tokens: tokens ? asArray(tokens) : [[this.outdir, "tokens"].join("/")]
1466
+ };
1467
+ };
1468
+ getOutdir = () => {
1469
+ const { outdir } = this.context.config;
1470
+ const split = outdir.split("/");
1471
+ return split[split.length - 1];
1472
+ };
1473
+ normalize = (map) => {
1474
+ if ((0, _bamboocss_shared.isString)(map)) return this.fromString(map);
1475
+ return this.fromInput(map);
1476
+ };
1477
+ createMatcher = (mods, values) => {
1478
+ const regex = values ? new RegExp(`^(${values.join("|")})$`) : /.*/;
1479
+ const match = (value) => regex.test(value);
1480
+ return {
1481
+ mods,
1482
+ regex,
1483
+ match
1484
+ };
1485
+ };
1486
+ match = (result, resolveTsPath) => {
1487
+ if (!result) return false;
1488
+ for (const { regex, mods } of Object.values(this.matchers)) {
1489
+ if (result.kind !== "namespace" && !regex.test(result.name)) continue;
1490
+ if (mods.some((m) => result.mod.includes(m))) return true;
1491
+ const resolvedMod = resolveTsPath?.(result.mod);
1492
+ for (const mod of mods) {
1493
+ const absMod = [this.context.config.cwd, mod].join("/").replaceAll("\\", "/");
1494
+ if (resolvedMod?.includes(absMod) || resolvedMod === mod) {
1495
+ result.importMapValue = resolvedMod;
1496
+ return true;
1497
+ }
1498
+ }
1499
+ }
1500
+ return false;
1501
+ };
1502
+ file = (results) => {
1503
+ return new FileMatcher(this.context, {
1504
+ importMap: this.value,
1505
+ value: results
1506
+ });
1507
+ };
1508
+ };
1509
+ const asArray = (value) => Array.isArray(value) ? value : [value];
1510
+ //#endregion
1511
+ //#region src/jsx.ts
1512
+ var JsxEngine = class {
1513
+ context;
1514
+ nodes = [];
1515
+ names = [];
1516
+ recipeMatcher = {
1517
+ string: /* @__PURE__ */ new Set(),
1518
+ regex: []
1519
+ };
1520
+ recipePropertiesByJsxName = /* @__PURE__ */ new Map();
1521
+ patternMatcher = {
1522
+ string: /* @__PURE__ */ new Set(),
1523
+ regex: []
1524
+ };
1525
+ patternPropertiesByJsxName = /* @__PURE__ */ new Map();
1526
+ constructor(context) {
1527
+ this.context = context;
1528
+ this.nodes = [...context.patterns.details, ...context.recipes.details];
1529
+ this.names = [this.factoryName, ...this.nodes.map((node) => node.jsxName)];
1530
+ this.assignRecipeMatcher();
1531
+ this.assignPatternMatcher();
1532
+ }
1533
+ assignRecipeMatcher() {
1534
+ if (!this.isEnabled) return;
1535
+ for (const recipe of this.context.recipes.details) {
1536
+ this.recipePropertiesByJsxName.set(recipe.jsxName, new Set(recipe.props ?? []));
1537
+ recipe.jsx.forEach((jsx) => {
1538
+ if (typeof jsx === "string") this.recipeMatcher.string.add(jsx);
1539
+ else this.recipeMatcher.regex.push(jsx);
1540
+ });
1541
+ }
1542
+ }
1543
+ assignPatternMatcher() {
1544
+ if (!this.isEnabled) return;
1545
+ for (const pattern of this.context.patterns.details) {
1546
+ this.patternPropertiesByJsxName.set(pattern.jsxName, new Set(pattern.props ?? []));
1547
+ pattern.jsx.forEach((jsx) => {
1548
+ if (typeof jsx === "string") this.patternMatcher.string.add(jsx);
1549
+ else this.patternMatcher.regex.push(jsx);
1550
+ });
1551
+ }
1552
+ }
1553
+ get jsxFactory() {
1554
+ return this.context.config.jsxFactory ?? "styled";
1555
+ }
1556
+ get styleProps() {
1557
+ return this.context.config.jsxStyleProps ?? "all";
1558
+ }
1559
+ get framework() {
1560
+ return this.context.config.jsxFramework;
1561
+ }
1562
+ get isEnabled() {
1563
+ return this.framework != null;
1564
+ }
1565
+ get factoryName() {
1566
+ return this.jsxFactory;
1567
+ }
1568
+ get upperName() {
1569
+ return (0, _bamboocss_shared.capitalize)(this.jsxFactory);
1570
+ }
1571
+ get typeName() {
1572
+ return `HTML${(0, _bamboocss_shared.capitalize)(this.jsxFactory)}Props`;
1573
+ }
1574
+ get variantName() {
1575
+ return `${(0, _bamboocss_shared.capitalize)(this.jsxFactory)}VariantProps`;
1576
+ }
1577
+ get componentName() {
1578
+ return `${(0, _bamboocss_shared.capitalize)(this.jsxFactory)}Component`;
1579
+ }
1580
+ isJsxFactory = (name) => {
1581
+ if (name === this.factoryName) return true;
1582
+ const [_namespace, identifier] = name.split(".");
1583
+ return identifier === this.factoryName;
1584
+ };
1585
+ isJsxTagRecipe = (0, _bamboocss_shared.memo)((tagName) => {
1586
+ return this.recipeMatcher.string.has(tagName) || this.recipeMatcher.regex.some((regex) => regex.test(tagName));
1587
+ });
1588
+ isJsxTagPattern = (0, _bamboocss_shared.memo)((tagName) => {
1589
+ return this.patternMatcher.string.has(tagName) || this.patternMatcher.regex.some((regex) => regex.test(tagName));
1590
+ });
1591
+ isRecipeOrPatternProp = (0, _bamboocss_shared.memo)((tagName, propName) => {
1592
+ if (this.isJsxTagRecipe(tagName)) return this.context.recipes.filter(tagName).some((recipe) => this.recipePropertiesByJsxName.get(recipe.jsxName)?.has(propName));
1593
+ if (this.isJsxTagPattern(tagName)) return this.context.patterns.filter(tagName).some((pattern) => this.patternPropertiesByJsxName.get(pattern.jsxName)?.has(propName));
1594
+ return false;
1595
+ });
1596
+ };
1597
+ //#endregion
1598
+ //#region src/layers.ts
1599
+ var Layers = class {
1600
+ names;
1601
+ root;
1602
+ reset;
1603
+ base;
1604
+ tokens;
1605
+ recipes;
1606
+ recipes_base;
1607
+ recipes_slots;
1608
+ recipes_slots_base;
1609
+ utilities;
1610
+ compositions;
1611
+ utilityRuleMap = /* @__PURE__ */ new Map();
1612
+ constructor(names) {
1613
+ this.names = names;
1614
+ this.root = postcss.default.root();
1615
+ this.reset = postcss.default.atRule({
1616
+ name: "layer",
1617
+ params: names.reset,
1618
+ nodes: []
1619
+ });
1620
+ this.base = postcss.default.atRule({
1621
+ name: "layer",
1622
+ params: names.base,
1623
+ nodes: []
1624
+ });
1625
+ this.tokens = postcss.default.atRule({
1626
+ name: "layer",
1627
+ params: names.tokens,
1628
+ nodes: []
1629
+ });
1630
+ this.recipes = postcss.default.atRule({
1631
+ name: "layer",
1632
+ params: names.recipes,
1633
+ nodes: []
1634
+ });
1635
+ this.recipes_base = postcss.default.atRule({
1636
+ name: "layer",
1637
+ params: "_base",
1638
+ nodes: []
1639
+ });
1640
+ this.recipes_slots = postcss.default.atRule({
1641
+ name: "layer",
1642
+ params: names.recipes + ".slots",
1643
+ nodes: []
1644
+ });
1645
+ this.recipes_slots_base = postcss.default.atRule({
1646
+ name: "layer",
1647
+ params: "_base",
1648
+ nodes: []
1649
+ });
1650
+ this.utilities = postcss.default.atRule({
1651
+ name: "layer",
1652
+ params: names.utilities,
1653
+ nodes: []
1654
+ });
1655
+ this.compositions = postcss.default.atRule({
1656
+ name: "layer",
1657
+ params: "compositions",
1658
+ nodes: []
1659
+ });
1660
+ }
1661
+ getLayerRoot(layer) {
1662
+ const { reset, base, tokens, recipes, recipes_base, recipes_slots, recipes_slots_base, utilities, compositions } = this;
1663
+ switch (layer) {
1664
+ case "base": return base;
1665
+ case "reset": return reset;
1666
+ case "tokens": return tokens;
1667
+ case "recipes": {
1668
+ const recipeRoot = postcss.default.root();
1669
+ if (recipes_base.nodes?.length) recipes.prepend(recipes_base);
1670
+ if (recipes_slots_base.nodes?.length) recipes_slots.prepend(recipes_slots_base);
1671
+ if (recipes.nodes?.length) recipeRoot.append(recipes);
1672
+ if (recipes_slots.nodes?.length) recipeRoot.append(recipes_slots);
1673
+ return recipeRoot;
1674
+ }
1675
+ case "utilities":
1676
+ if (compositions.nodes?.length) utilities.prepend(compositions);
1677
+ this.utilityRuleMap.forEach((rules) => {
1678
+ if (rules.nodes?.length) utilities.append(rules);
1679
+ });
1680
+ return utilities;
1681
+ default: throw new _bamboocss_shared.BambooError("INVALID_LAYER", `Unknown layer: ${layer}`);
1682
+ }
1683
+ }
1684
+ insert() {
1685
+ const { root } = this;
1686
+ const reset = this.getLayerRoot("reset");
1687
+ if (reset.nodes?.length) root.append(reset);
1688
+ const base = this.getLayerRoot("base");
1689
+ if (base.nodes?.length) root.append(base);
1690
+ const tokens = this.getLayerRoot("tokens");
1691
+ if (tokens.nodes?.length) root.append(tokens);
1692
+ const recipes = this.getLayerRoot("recipes");
1693
+ if (recipes.nodes?.length) root.append(recipes);
1694
+ const utilities = this.getLayerRoot("utilities");
1695
+ if (utilities.nodes?.length) root.append(utilities);
1696
+ return root;
1697
+ }
1698
+ get layerNames() {
1699
+ return Object.values(this.names);
1700
+ }
1701
+ get params() {
1702
+ return `@layer ${this.layerNames.join(", ")};`;
1703
+ }
1704
+ };
1705
+ //#endregion
1706
+ //#region src/path.ts
1707
+ var PathEngine = class {
1708
+ context;
1709
+ constructor(context) {
1710
+ this.context = context;
1711
+ }
1712
+ get cwd() {
1713
+ return this.context.config.cwd;
1714
+ }
1715
+ get outdir() {
1716
+ return this.context.config.outdir;
1717
+ }
1718
+ getFilePath(file) {
1719
+ return [
1720
+ this.cwd,
1721
+ this.outdir,
1722
+ file
1723
+ ].filter(Boolean);
1724
+ }
1725
+ get root() {
1726
+ return this.getFilePath();
1727
+ }
1728
+ get css() {
1729
+ return this.getFilePath("css");
1730
+ }
1731
+ get token() {
1732
+ return this.getFilePath("tokens");
1733
+ }
1734
+ get types() {
1735
+ return this.getFilePath("types");
1736
+ }
1737
+ get recipe() {
1738
+ return this.getFilePath("recipes");
1739
+ }
1740
+ get pattern() {
1741
+ return this.getFilePath("patterns");
1742
+ }
1743
+ get outCss() {
1744
+ return this.getFilePath("styles.css");
1745
+ }
1746
+ get jsx() {
1747
+ return this.getFilePath("jsx");
1748
+ }
1749
+ get themes() {
1750
+ return this.getFilePath("themes");
1751
+ }
1752
+ get specs() {
1753
+ return this.getFilePath("specs");
1754
+ }
1755
+ };
1756
+ //#endregion
1757
+ //#region src/patterns.ts
1758
+ var Patterns = class {
1759
+ options;
1760
+ patterns;
1761
+ details;
1762
+ keys;
1763
+ utility;
1764
+ tokens;
1765
+ deprecated = /* @__PURE__ */ new Set();
1766
+ constructor(options) {
1767
+ this.options = options;
1768
+ this.patterns = options.config.patterns ?? {};
1769
+ this.details = Object.entries(this.patterns).map(([name, pattern]) => this.createDetail(name, pattern));
1770
+ this.keys = Object.keys(this.patterns);
1771
+ this.utility = options.utility;
1772
+ this.tokens = options.tokens;
1773
+ }
1774
+ createDetail(name, pattern) {
1775
+ const names = this.getNames(name);
1776
+ const jsx = (pattern.jsx ?? []).concat([names.jsxName]);
1777
+ if (pattern.deprecated) this.deprecated.add(name);
1778
+ return {
1779
+ ...names,
1780
+ props: Object.keys(pattern?.properties ?? {}),
1781
+ blocklistType: pattern?.blocklist ? `| '${pattern.blocklist.join("' | '")}'` : "",
1782
+ config: pattern,
1783
+ type: "pattern",
1784
+ match: (0, _bamboocss_shared.createRegex)(jsx),
1785
+ jsx
1786
+ };
1787
+ }
1788
+ getConfig(name) {
1789
+ return this.patterns[name];
1790
+ }
1791
+ transform(name, styles) {
1792
+ const pattern = this.patterns[name];
1793
+ const _styles = (0, _bamboocss_shared.getPatternStyles)(pattern, styles);
1794
+ return pattern?.transform?.(_styles, this.options.helpers) ?? {};
1795
+ }
1796
+ getNames(name) {
1797
+ const upperName = (0, _bamboocss_shared.capitalize)(name);
1798
+ return {
1799
+ upperName,
1800
+ baseName: name,
1801
+ dashName: (0, _bamboocss_shared.dashCase)(name),
1802
+ styleFnName: `get${upperName}Style`,
1803
+ jsxName: this.patterns[name]?.jsxName ?? upperName
1804
+ };
1805
+ }
1806
+ find = (0, _bamboocss_shared.memo)((jsxName) => {
1807
+ return this.details.find((node) => node.match.test(jsxName))?.baseName ?? (0, _bamboocss_shared.uncapitalize)(jsxName);
1808
+ });
1809
+ filter = (0, _bamboocss_shared.memo)((jsxName) => {
1810
+ return this.details.filter((node) => node.match.test(jsxName));
1811
+ });
1812
+ isEmpty() {
1813
+ return this.keys.length === 0;
1814
+ }
1815
+ isDeprecated(name) {
1816
+ return this.deprecated.has(name);
1817
+ }
1818
+ saveOne(name, pattern) {
1819
+ this.patterns[name] = pattern;
1820
+ const detailIndex = this.details.findIndex((detail) => detail.baseName === name);
1821
+ const updated = this.createDetail(name, pattern);
1822
+ if (detailIndex > -1) this.details[detailIndex] = updated;
1823
+ else this.details.push(updated);
1824
+ }
1825
+ remove(name) {
1826
+ delete this.patterns[name];
1827
+ const detailIndex = this.details.findIndex((detail) => detail.baseName === name);
1828
+ if (detailIndex > -1) this.details.splice(detailIndex, 1);
1829
+ }
1830
+ filterDetails(filters) {
1831
+ const patternDiffs = filters?.affecteds?.patterns;
1832
+ return patternDiffs ? this.details.filter((pattern) => patternDiffs.includes(pattern.dashName)) : this.details;
1833
+ }
1834
+ getPropertyValues = (patternName, property) => {
1835
+ const patternConfig = this.getConfig(patternName);
1836
+ if (!patternConfig) return [];
1837
+ const propType = patternConfig.properties?.[property];
1838
+ if (!propType) return;
1839
+ if (propType.type === "enum") return propType.value;
1840
+ if (propType.type === "boolean") return ["true", "false"];
1841
+ if (propType.type === "property") return this.utility.getPropertyKeys(propType.value || property);
1842
+ if (propType.type === "token") {
1843
+ const values = this.tokens.view.getCategoryValues(propType.value);
1844
+ return Object.keys(values ?? {});
1845
+ }
1846
+ };
1847
+ getPropertyType = (prop) => {
1848
+ switch (prop.type) {
1849
+ case "enum": return `ConditionalValue<${(0, _bamboocss_shared.unionType)(prop.value)}>`;
1850
+ case "token": {
1851
+ const tokenType = `Tokens["${prop.value}"]`;
1852
+ if (prop.property) return `ConditionalValue<${tokenType} | Properties["${prop.property}"]>`;
1853
+ return `ConditionalValue<${tokenType}>`;
1854
+ }
1855
+ case "property": return `SystemProperties["${prop.value}"]`;
1856
+ case "string":
1857
+ case "number":
1858
+ case "boolean": return `ConditionalValue<${prop.type}>`;
1859
+ default: return `ConditionalValue<${prop.type || "unknown"}>`;
1860
+ }
1861
+ };
1862
+ static isValidNode = (node) => {
1863
+ return (0, _bamboocss_shared.isObject)(node) && "type" in node && node.type === "recipe";
1864
+ };
1865
+ };
1866
+ //#endregion
1867
+ //#region src/serialize.ts
1868
+ /**
1869
+ * Transform the style object (with conditions, shorthands, tokens) into a valid CSS (in JS) object
1870
+ */
1871
+ function transformStyles(context, styleObj, key) {
1872
+ const encoder = context.encoder.clone();
1873
+ const decoder = context.decoder.clone();
1874
+ const hashSet = /* @__PURE__ */ new Set();
1875
+ encoder.hashStyleObject(hashSet, styleObj);
1876
+ return decoder.getGroup(hashSet, key).result;
1877
+ }
1878
+ /**
1879
+ * Serialize the style object (with conditions, shorthands, tokens) into a valid CSS string
1880
+ */
1881
+ function serializeStyles(context, groupedObject) {
1882
+ const result = {};
1883
+ for (const [scope, styles] of Object.entries(groupedObject)) {
1884
+ result[scope] ||= {};
1885
+ const styleObject = (0, _bamboocss_shared.walkObject)(styles, (value) => value, { getKey: (prop, value) => {
1886
+ if ((0, _bamboocss_shared.isObject)(value) && !context.conditions.isCondition(prop) && !context.isValidProperty(prop)) return parseSelectors(prop).map((s) => "& " + s).join(", ");
1887
+ return prop;
1888
+ } });
1889
+ (0, lodash_merge.default)(result[scope], transformStyles(context, styleObject, scope));
1890
+ }
1891
+ return result;
1892
+ }
1893
+ //#endregion
1894
+ //#region src/recipes.ts
1895
+ const sharedState = {
1896
+ /**
1897
+ * The map of recipe names to their resolved class names
1898
+ */
1899
+ classNames: /* @__PURE__ */ new Map(),
1900
+ /**
1901
+ * The map of the property to their resolved styles
1902
+ */
1903
+ styles: /* @__PURE__ */ new Map(),
1904
+ /**
1905
+ * The map of the recipes with their resolved styles
1906
+ */
1907
+ nodes: /* @__PURE__ */ new Map(),
1908
+ /**
1909
+ * The map of recipe key to slot key + slot recipe
1910
+ */
1911
+ slots: /* @__PURE__ */ new Map()
1912
+ };
1913
+ var Recipes = class Recipes {
1914
+ recipes;
1915
+ slotSeparator = "__";
1916
+ keys = [];
1917
+ deprecated = /* @__PURE__ */ new Set();
1918
+ context;
1919
+ get config() {
1920
+ return this.recipes;
1921
+ }
1922
+ constructor(recipes = {}) {
1923
+ this.recipes = recipes;
1924
+ this.prune();
1925
+ }
1926
+ getPropKey = (recipe, variant, value) => {
1927
+ return `${recipe} (${variant} = ${value})`;
1928
+ };
1929
+ get separator() {
1930
+ return this.context.utility.separator ?? "_";
1931
+ }
1932
+ getClassName = (className, variant, value) => {
1933
+ return `${className}--${variant}${this.separator}${value}`;
1934
+ };
1935
+ prune = () => {
1936
+ const recipeNames = Object.keys(this.recipes);
1937
+ Array.from(sharedState.nodes.keys()).filter((name) => !recipeNames.includes(name)).forEach((name) => {
1938
+ this.remove(name);
1939
+ });
1940
+ };
1941
+ save = (context) => {
1942
+ this.context = context;
1943
+ for (const [name, recipe] of Object.entries(this.recipes)) this.saveOne(name, recipe);
1944
+ this.keys = Object.keys(this.recipes);
1945
+ };
1946
+ saveOne = (name, recipe) => {
1947
+ if (Recipes.isSlotRecipeConfig(recipe)) {
1948
+ const slots = (0, _bamboocss_shared.getSlotRecipes)(recipe);
1949
+ const slotsMap = /* @__PURE__ */ new Map();
1950
+ Object.entries(slots).forEach(([slot, slotRecipe]) => {
1951
+ const slotName = this.getSlotKey(name, slot);
1952
+ this.normalize(slotName, slotRecipe);
1953
+ slotsMap.set(slotName, slotRecipe);
1954
+ });
1955
+ this.assignRecipe(name, recipe);
1956
+ sharedState.slots.set(name, slotsMap);
1957
+ } else this.assignRecipe(name, this.normalize(name, recipe));
1958
+ };
1959
+ remove(name) {
1960
+ sharedState.nodes.delete(name);
1961
+ sharedState.classNames.delete(name);
1962
+ sharedState.styles.delete(name);
1963
+ }
1964
+ inferJsxSlots = (name, recipe) => {
1965
+ const capitalized = (0, _bamboocss_shared.capitalize)(name);
1966
+ const jsx = Array.from(recipe.jsx ?? [capitalized]);
1967
+ const ROOT_SLOT = "root";
1968
+ if (Recipes.isSlotRecipeConfig(recipe)) {
1969
+ const jsxRootName = (0, _bamboocss_shared.capitalize)(ROOT_SLOT);
1970
+ const rootNames = [`${capitalized}.${jsxRootName}`, `${capitalized}${jsxRootName}`];
1971
+ jsx.push(...rootNames);
1972
+ }
1973
+ return jsx;
1974
+ };
1975
+ assignRecipe = (name, recipe) => {
1976
+ if (recipe.deprecated) this.deprecated.add(name);
1977
+ const variantKeys = Object.keys(recipe.variants ?? {});
1978
+ const jsx = this.inferJsxSlots(name, recipe);
1979
+ sharedState.nodes.set(name, {
1980
+ ...this.getNames(name),
1981
+ className: recipe.className ?? name,
1982
+ jsx,
1983
+ type: "recipe",
1984
+ variantKeys,
1985
+ variantKeyMap: Object.fromEntries(Object.entries(recipe.variants ?? {}).map(([key, value]) => {
1986
+ return [key, Object.keys(value)];
1987
+ })),
1988
+ match: (0, _bamboocss_shared.createRegex)(jsx),
1989
+ config: recipe,
1990
+ splitProps: (props) => {
1991
+ return (0, _bamboocss_shared.splitProps)(props, variantKeys);
1992
+ },
1993
+ props: variantKeys
1994
+ });
1995
+ };
1996
+ getSlotKey = (name, slot) => {
1997
+ return `${name}${this.slotSeparator}${slot}`;
1998
+ };
1999
+ isEmpty = () => {
2000
+ return sharedState.nodes.size === 0;
2001
+ };
2002
+ isDeprecated = (name) => {
2003
+ return this.deprecated.has(name);
2004
+ };
2005
+ getNames = (0, _bamboocss_shared.memo)((name) => {
2006
+ return {
2007
+ baseName: name,
2008
+ upperName: (0, _bamboocss_shared.capitalize)(name),
2009
+ dashName: (0, _bamboocss_shared.dashCase)(name),
2010
+ jsxName: (0, _bamboocss_shared.capitalize)(name)
2011
+ };
2012
+ });
2013
+ getRecipe = (0, _bamboocss_shared.memo)((name) => {
2014
+ return sharedState.nodes.get(name);
2015
+ });
2016
+ getConfig = (0, _bamboocss_shared.memo)((name) => {
2017
+ return this.recipes[name];
2018
+ });
2019
+ getConfigOrThrow = (0, _bamboocss_shared.memo)((name) => {
2020
+ const config = this.getConfig(name);
2021
+ if (!config) throw new _bamboocss_shared.BambooError("UNKNOWN_RECIPE", `Recipe "${name}" not found`);
2022
+ return config;
2023
+ });
2024
+ find = (0, _bamboocss_shared.memo)((jsxName) => {
2025
+ return this.details.find((node) => node.match.test(jsxName));
2026
+ });
2027
+ filter = (0, _bamboocss_shared.memo)((jsxName) => {
2028
+ return this.details.filter((node) => node.match.test(jsxName));
2029
+ });
2030
+ get details() {
2031
+ return Array.from(sharedState.nodes.values());
2032
+ }
2033
+ splitProps = (recipeName, props) => {
2034
+ const recipe = this.details.find((node) => node.baseName === recipeName);
2035
+ if (!recipe) return [{}, props];
2036
+ return recipe.splitProps(props);
2037
+ };
2038
+ isSlotRecipe = (name) => {
2039
+ return sharedState.slots.has(name);
2040
+ };
2041
+ static isSlotRecipeConfig = (config) => {
2042
+ return "slots" in config && Array.isArray(config.slots) && config.slots.length > 0;
2043
+ };
2044
+ normalize = (name, config) => {
2045
+ const { jsx = [(0, _bamboocss_shared.capitalize)(name)], base = {}, variants = {}, defaultVariants = {}, description = "", compoundVariants = [], staticCss = [] } = config;
2046
+ const className = config.className ?? name;
2047
+ const recipe = {
2048
+ ...config,
2049
+ deprecated: config.deprecated == null ? false : config.deprecated,
2050
+ jsx,
2051
+ className,
2052
+ description,
2053
+ base: {},
2054
+ variants: {},
2055
+ defaultVariants,
2056
+ compoundVariants,
2057
+ staticCss
2058
+ };
2059
+ recipe.base = transformStyles(this.context, base, name);
2060
+ sharedState.styles.set(name, recipe.base);
2061
+ sharedState.classNames.set(name, recipe.className);
2062
+ for (const [key, variant] of Object.entries(variants)) for (const [variantKey, styles] of Object.entries(variant)) {
2063
+ const propKey = this.getPropKey(name, key, variantKey);
2064
+ const className = this.getClassName(recipe.className, key, variantKey);
2065
+ const styleObject = transformStyles(this.context, styles, className);
2066
+ sharedState.styles.set(propKey, styleObject);
2067
+ sharedState.classNames.set(propKey, className);
2068
+ (0, lodash_merge.default)(recipe.variants, { [key]: { [variantKey]: styleObject } });
2069
+ }
2070
+ return recipe;
2071
+ };
2072
+ getTransform = (name, slot) => {
2073
+ return (variant, value) => {
2074
+ if (value === "__ignore__") return {
2075
+ layer: slot ? "recipes_slots_base" : "recipes_base",
2076
+ className: sharedState.classNames.get(name),
2077
+ styles: sharedState.styles.get(name) ?? {}
2078
+ };
2079
+ const propKey = this.getPropKey(name, variant, value);
2080
+ return {
2081
+ className: sharedState.classNames.get(propKey),
2082
+ styles: sharedState.styles.get(propKey) ?? {}
2083
+ };
2084
+ };
2085
+ };
2086
+ filterDetails = (filters) => {
2087
+ const recipeDiffs = filters?.affecteds?.recipes;
2088
+ return recipeDiffs ? this.details.filter((recipe) => recipeDiffs.includes(recipe.dashName)) : this.details;
2089
+ };
2090
+ static inferSlots = (recipe) => {
2091
+ const slots = /* @__PURE__ */ new Set();
2092
+ Object.keys(recipe.base ?? {}).forEach((name) => {
2093
+ slots.add(name);
2094
+ });
2095
+ Object.values(recipe.variants ?? {}).forEach((variants) => {
2096
+ Object.keys(variants).forEach((name) => {
2097
+ slots.add(name);
2098
+ });
2099
+ });
2100
+ recipe.compoundVariants?.forEach((compoundVariant) => {
2101
+ if (!compoundVariant) return;
2102
+ Object.keys(compoundVariant.css ?? {}).forEach((name) => {
2103
+ slots.add(name);
2104
+ });
2105
+ });
2106
+ return Array.from(slots);
2107
+ };
2108
+ static isValidNode = (node) => {
2109
+ return (0, _bamboocss_shared.isObject)(node) && "type" in node && node.type === "recipe";
2110
+ };
2111
+ };
2112
+ //#endregion
2113
+ //#region package.json
2114
+ var version = "1.11.2";
2115
+ //#endregion
2116
+ //#region src/style-encoder.ts
2117
+ const urlRegex = /^https?:\/\//;
2118
+ var StyleEncoder = class StyleEncoder {
2119
+ context;
2120
+ static separator = "]___[";
2121
+ static conditionSeparator = "<___>";
2122
+ atomic = /* @__PURE__ */ new Set();
2123
+ compound_variants = /* @__PURE__ */ new Set();
2124
+ recipes = /* @__PURE__ */ new Map();
2125
+ recipes_base = /* @__PURE__ */ new Map();
2126
+ grouped = /* @__PURE__ */ new Map();
2127
+ constructor(context) {
2128
+ this.context = context;
2129
+ }
2130
+ filterStyleProps = (props) => {
2131
+ if (this.context.isTemplateLiteralSyntax) return props;
2132
+ return filterProps(this.context.isValidProperty, props);
2133
+ };
2134
+ clone = () => {
2135
+ return new StyleEncoder(this.context);
2136
+ };
2137
+ isEmpty = () => {
2138
+ return !this.atomic.size && !this.recipes.size && !this.compound_variants.size && !this.recipes_base.size && !this.grouped.size;
2139
+ };
2140
+ get results() {
2141
+ return {
2142
+ atomic: this.atomic,
2143
+ recipes: this.recipes,
2144
+ recipes_base: this.recipes_base,
2145
+ grouped: this.grouped
2146
+ };
2147
+ }
2148
+ /**
2149
+ * Hashes a style object and adds the resulting hashes to a set.
2150
+ * @param set - The set to add the resulting hashes to.
2151
+ * @param obj - The style object to hash.
2152
+ * @param baseEntry - An optional base style entry to use when hashing the style object.
2153
+ */
2154
+ hashStyleObject = (set, obj, baseEntry) => {
2155
+ const isCondition = this.context.conditions.isCondition;
2156
+ const traverseOptions = { separator: StyleEncoder.conditionSeparator };
2157
+ let prop = "";
2158
+ let prevProp = "";
2159
+ const isRecipe = !!baseEntry?.variants;
2160
+ (0, _bamboocss_shared.traverse)((0, _bamboocss_shared.normalizeStyleObject)(obj, this.context, !isRecipe), ({ key, value: rawValue, path }) => {
2161
+ if (rawValue === void 0) return;
2162
+ if (urlRegex.test(rawValue)) return;
2163
+ const value = Array.isArray(rawValue) ? (0, _bamboocss_shared.toResponsiveObject)(rawValue, this.context.conditions.breakpoints.keys) : rawValue;
2164
+ prop = key;
2165
+ if (isCondition(key)) {
2166
+ if ((0, _bamboocss_shared.isObjectOrArray)(value)) return;
2167
+ prop = prevProp;
2168
+ } else if ((0, _bamboocss_shared.isObjectOrArray)(value)) {
2169
+ prevProp = prop;
2170
+ return;
2171
+ }
2172
+ const resolvedCondition = getResolvedCondition(path, isCondition);
2173
+ const hashed = hashStyleEntry(Object.assign(baseEntry ?? {}, {
2174
+ prop,
2175
+ value,
2176
+ cond: resolvedCondition
2177
+ }));
2178
+ set.add(hashed);
2179
+ prevProp = prop;
2180
+ }, traverseOptions);
2181
+ };
2182
+ processAtomic = (styles) => {
2183
+ this.hashStyleObject(this.atomic, styles);
2184
+ };
2185
+ processGrouped = (styles) => {
2186
+ const groupSet = /* @__PURE__ */ new Set();
2187
+ this.hashStyleObject(groupSet, styles);
2188
+ if (groupSet.size === 0) return;
2189
+ const groupId = Array.from(groupSet).sort().join("|");
2190
+ if (this.grouped.get(groupId)) return;
2191
+ this.grouped.set(groupId, groupSet);
2192
+ };
2193
+ processStyleProps = (styleProps, grouped = false) => {
2194
+ const processFn = grouped ? this.processGrouped : this.processAtomic;
2195
+ const styles = this.filterStyleProps(styleProps);
2196
+ const rest = {};
2197
+ for (const [key, value] of Object.entries(styles)) if (key === "css" || key.endsWith("Css")) {
2198
+ if (Array.isArray(value)) value.forEach((style) => processFn(style));
2199
+ else if (value) processFn(value);
2200
+ } else rest[key] = value;
2201
+ processFn(rest);
2202
+ };
2203
+ processConfigSlotRecipeBase = (recipeName, config) => {
2204
+ config.slots.forEach((slot) => {
2205
+ const recipeKey = this.context.recipes.getSlotKey(recipeName, slot);
2206
+ const slotBase = config.base?.[slot];
2207
+ if (!slotBase || this.recipes_base.has(recipeKey)) return;
2208
+ const base_set = (0, _bamboocss_shared.getOrCreateSet)(this.recipes_base, recipeKey);
2209
+ this.hashStyleObject(base_set, slotBase, {
2210
+ recipe: recipeName,
2211
+ slot
2212
+ });
2213
+ });
2214
+ };
2215
+ processConfigSlotRecipe = (recipeName, variants) => {
2216
+ const config = this.context.recipes.getConfig(recipeName);
2217
+ if (!Recipes.isSlotRecipeConfig(config)) return;
2218
+ this.processConfigSlotRecipeBase(recipeName, config);
2219
+ const set = (0, _bamboocss_shared.getOrCreateSet)(this.recipes, recipeName);
2220
+ const computedVariants = Object.assign({}, config.defaultVariants, variants);
2221
+ this.hashStyleObject(set, computedVariants, {
2222
+ recipe: recipeName,
2223
+ variants: true
2224
+ });
2225
+ if (!config.compoundVariants || this.compound_variants.has(recipeName)) return;
2226
+ this.compound_variants.add(recipeName);
2227
+ config.compoundVariants.forEach((compoundVariant) => {
2228
+ if (!compoundVariant) return;
2229
+ Object.values(compoundVariant.css).forEach((values) => {
2230
+ if (!values) return;
2231
+ this.processAtomic(values);
2232
+ });
2233
+ });
2234
+ };
2235
+ processConfigRecipeBase = (recipeName, config) => {
2236
+ if (!config.base || this.recipes_base.has(recipeName)) return;
2237
+ const base_set = (0, _bamboocss_shared.getOrCreateSet)(this.recipes_base, recipeName);
2238
+ this.hashStyleObject(base_set, config.base, { recipe: recipeName });
2239
+ };
2240
+ processConfigRecipe = (recipeName, variants) => {
2241
+ const config = this.context.recipes.getConfig(recipeName);
2242
+ if (!config) return;
2243
+ this.processConfigRecipeBase(recipeName, config);
2244
+ const set = (0, _bamboocss_shared.getOrCreateSet)(this.recipes, recipeName);
2245
+ const computedVariants = Object.assign({}, config.defaultVariants, variants);
2246
+ this.hashStyleObject(set, computedVariants, {
2247
+ recipe: recipeName,
2248
+ variants: true
2249
+ });
2250
+ if (!config.compoundVariants || this.compound_variants.has(recipeName)) return;
2251
+ this.compound_variants.add(recipeName);
2252
+ config.compoundVariants.forEach((compoundVariant) => {
2253
+ if (!compoundVariant) return;
2254
+ this.processAtomic(compoundVariant.css);
2255
+ });
2256
+ };
2257
+ processRecipe = (recipeName, variants) => {
2258
+ if (this.context.recipes.isSlotRecipe(recipeName)) this.processConfigSlotRecipe(recipeName, variants);
2259
+ else this.processConfigRecipe(recipeName, variants);
2260
+ };
2261
+ processRecipeBase(recipeName) {
2262
+ const config = this.context.recipes.getConfig(recipeName);
2263
+ if (!config) return;
2264
+ if (this.context.recipes.isSlotRecipe(recipeName)) this.processConfigSlotRecipeBase(recipeName, config);
2265
+ else this.processConfigRecipeBase(recipeName, config);
2266
+ }
2267
+ processPattern = (name, patternProps, type, jsxName) => {
2268
+ let fnName = name;
2269
+ if (type === "jsx-pattern" && jsxName) fnName = this.context.patterns.find(jsxName);
2270
+ const styleProps = this.context.patterns.transform(fnName, patternProps);
2271
+ this.processStyleProps(styleProps);
2272
+ };
2273
+ processAtomicRecipe = (recipe) => {
2274
+ const { base = {}, variants = {}, compoundVariants = [] } = recipe;
2275
+ this.processAtomic(base);
2276
+ for (const variant of Object.values(variants)) for (const styles of Object.values(variant)) this.processAtomic(styles);
2277
+ compoundVariants.forEach((compoundVariant) => {
2278
+ if (!compoundVariant) return;
2279
+ this.processAtomic(compoundVariant.css);
2280
+ });
2281
+ };
2282
+ processAtomicSlotRecipe = (recipe) => {
2283
+ const inferredSlots = Recipes.inferSlots(recipe);
2284
+ recipe.slots = (0, _bamboocss_shared.uniq)([...recipe.slots ?? [], ...inferredSlots].filter(Boolean));
2285
+ const slots = (0, _bamboocss_shared.getSlotRecipes)(recipe);
2286
+ for (const slotRecipe of Object.values(slots)) this.processAtomicRecipe(slotRecipe);
2287
+ };
2288
+ getConfigRecipeHash = (recipeName) => {
2289
+ return {
2290
+ atomic: this.atomic,
2291
+ base: this.recipes_base.get(recipeName),
2292
+ variants: this.recipes.get(recipeName)
2293
+ };
2294
+ };
2295
+ getConfigSlotRecipeHash = (recipeName) => {
2296
+ const recipeConfig = this.context.recipes.getConfigOrThrow(recipeName);
2297
+ if (!Recipes.isSlotRecipeConfig(recipeConfig)) throw new _bamboocss_shared.BambooError("INVALID_RECIPE", `Recipe "${recipeName}" is not a slot recipe`);
2298
+ const base = {};
2299
+ recipeConfig.slots.map((slot) => {
2300
+ const recipeKey = this.context.recipes.getSlotKey(recipeName, slot);
2301
+ base[slot] = this.recipes_base.get(recipeKey);
2302
+ });
2303
+ return {
2304
+ atomic: this.atomic,
2305
+ base,
2306
+ variants: this.recipes.get(recipeName)
2307
+ };
2308
+ };
2309
+ getRecipeHash = (recipeName) => {
2310
+ if (this.context.recipes.isSlotRecipe(recipeName)) return this.getConfigSlotRecipeHash(recipeName);
2311
+ return this.getConfigRecipeHash(recipeName);
2312
+ };
2313
+ toJSON = () => {
2314
+ const styles = {
2315
+ atomic: Array.from(this.atomic),
2316
+ recipes: Object.fromEntries(Array.from(this.recipes.entries()).map(([name, set]) => [name, Array.from(set)]))
2317
+ };
2318
+ if (this.grouped.size) styles.grouped = Object.fromEntries(Array.from(this.grouped.entries()).map(([id, set]) => [id, Array.from(set)]));
2319
+ return {
2320
+ schemaVersion: version,
2321
+ styles
2322
+ };
2323
+ };
2324
+ fromJSON = (json) => {
2325
+ const { styles } = json;
2326
+ styles.atomic?.forEach((hash) => this.atomic.add(hash));
2327
+ Object.entries(styles.recipes ?? {}).forEach(([recipeName, hashes]) => {
2328
+ this.processRecipeBase(recipeName);
2329
+ const set = (0, _bamboocss_shared.getOrCreateSet)(this.recipes, recipeName);
2330
+ hashes.forEach((hash) => set.add(hash));
2331
+ });
2332
+ Object.entries(styles.grouped ?? {}).forEach(([groupId, hashes]) => {
2333
+ const set = (0, _bamboocss_shared.getOrCreateSet)(this.grouped, groupId);
2334
+ hashes.forEach((hash) => set.add(hash));
2335
+ });
2336
+ return this;
2337
+ };
2338
+ };
2339
+ const filterProps = (isValidProperty, props) => {
2340
+ const clone = {};
2341
+ for (const [key, value] of Object.entries(props)) if ((isValidProperty(key) || key === "css" || key.endsWith("Css")) && value !== void 0) clone[key] = value;
2342
+ return clone;
2343
+ };
2344
+ const hashStyleEntry = (entry) => {
2345
+ const parts = [`${entry.prop}${StyleEncoder.separator}value:${entry.value}`];
2346
+ if (entry.cond) parts.push(`cond:${entry.cond}`);
2347
+ if (entry.recipe) parts.push(`recipe:${entry.recipe}`);
2348
+ if (entry.layer) parts.push(`layer:${entry.layer}`);
2349
+ if (entry.slot) parts.push(`slot:${entry.slot}`);
2350
+ return parts.join(StyleEncoder.separator);
2351
+ };
2352
+ /**
2353
+ * Returns the final condition string after filtering out irrelevant parts. ('base' and props)
2354
+ * @example
2355
+ * 'marginTop<___>md' => 'md'
2356
+ * 'marginTop<___>md<___>lg' => 'md<___>lg'
2357
+ * '_hover' => '_hover'
2358
+ * '& > p<___>base', => '& > p'
2359
+ * '@media base' => '@media base'
2360
+ * '_hover<___>base<___>_dark' => '_hover<___>_dark'
2361
+ *
2362
+ */
2363
+ const getResolvedCondition = (cond, isCondition) => {
2364
+ if (!cond) return "";
2365
+ const parts = cond.split(StyleEncoder.conditionSeparator);
2366
+ const relevantParts = parts.filter((part) => part !== "base" && isCondition(part));
2367
+ if (parts.length !== relevantParts.length) return relevantParts.join(StyleEncoder.conditionSeparator);
2368
+ return cond;
2369
+ };
2370
+ //#endregion
2371
+ //#region src/style-decoder.ts
2372
+ var StyleDecoder = class StyleDecoder {
2373
+ context;
2374
+ constructor(context) {
2375
+ this.context = context;
2376
+ }
2377
+ classNames = /* @__PURE__ */ new Map();
2378
+ atomic_cache = /* @__PURE__ */ new Map();
2379
+ group_cache = /* @__PURE__ */ new Map();
2380
+ recipe_base_cache = /* @__PURE__ */ new Map();
2381
+ atomic = /* @__PURE__ */ new Set();
2382
+ grouped = /* @__PURE__ */ new Set();
2383
+ recipes = /* @__PURE__ */ new Map();
2384
+ recipes_base = /* @__PURE__ */ new Map();
2385
+ clone = () => {
2386
+ return new StyleDecoder(this.context);
2387
+ };
2388
+ isEmpty = () => {
2389
+ return !this.atomic.size && !this.grouped.size && !this.recipes.size && !this.recipes_base.size;
2390
+ };
2391
+ get results() {
2392
+ return {
2393
+ atomic: this.atomic,
2394
+ grouped: this.grouped,
2395
+ recipes: this.recipes,
2396
+ recipes_base: this.recipes_base
2397
+ };
2398
+ }
2399
+ formatSelector = (conditions, className) => {
2400
+ const { conditions: cond, hash, utility } = this.context;
2401
+ const conds = cond.finalize(conditions);
2402
+ let result;
2403
+ if (hash.className) {
2404
+ conds.push(className);
2405
+ result = utility.formatClassName(utility.toHash(conds, utility.defaultHashFn));
2406
+ } else {
2407
+ conds.push(utility.formatClassName(className));
2408
+ result = conds.join(":");
2409
+ }
2410
+ return (0, _bamboocss_shared.esc)(result);
2411
+ };
2412
+ getRecipeName = (hash) => {
2413
+ const entry = getEntryFromHash(hash);
2414
+ if (!entry.recipe) return;
2415
+ return entry.slot ? this.context.recipes.getSlotKey(entry.recipe, entry.slot) : entry.recipe;
2416
+ };
2417
+ getTransformResult = (hash) => {
2418
+ const entry = getEntryFromHash(hash);
2419
+ const recipeName = this.getRecipeName(hash);
2420
+ const transformed = (recipeName ? this.context.recipes.getTransform(recipeName) : this.context.utility.transform)(entry.prop, (0, _bamboocss_shared.withoutImportant)(entry.value));
2421
+ if (!transformed.className) return;
2422
+ const important = (0, _bamboocss_shared.isImportant)(entry.value);
2423
+ const styles = important ? (0, _bamboocss_shared.markImportant)(transformed.styles) : transformed.styles;
2424
+ const parts = entry.cond ? entry.cond.split(StyleEncoder.conditionSeparator) : [];
2425
+ const className = this.formatSelector(parts, transformed.className);
2426
+ return {
2427
+ className,
2428
+ classSelector: important ? `.${className}\\!` : `.${className}`,
2429
+ styles,
2430
+ transformed,
2431
+ parts
2432
+ };
2433
+ };
2434
+ resolveCondition = (condition) => {
2435
+ if (condition.type === "multi-block") return [];
2436
+ if (Array.isArray(condition.raw)) return condition.raw.map((c) => this.context.utility.tokens.resolveReference(c));
2437
+ return this.context.utility.tokens.resolveReference(condition.raw);
2438
+ };
2439
+ /**
2440
+ * Expands multi-block conditions into separate sets of conditions.
2441
+ * Each block becomes an independent condition set that produces its own CSS block.
2442
+ * When multiple multi-block conditions are stacked (e.g. two custom multi-block
2443
+ * conditions used together), the cartesian product of all blocks is produced.
2444
+ * Returns null if no multi-block condition is found.
2445
+ */
2446
+ expandMultiBlock(conditions) {
2447
+ if (!conditions.some((c) => c.type === "multi-block")) return null;
2448
+ const alternatives = conditions.map((c) => {
2449
+ if (c.type === "multi-block") return c.value.map((block) => block.value.filter(Boolean));
2450
+ return [[c]];
2451
+ });
2452
+ let combos = [[]];
2453
+ for (const slot of alternatives) {
2454
+ const next = [];
2455
+ for (const partial of combos) for (const choice of slot) next.push([...partial, ...choice]);
2456
+ combos = next;
2457
+ }
2458
+ return combos.map((combo) => sortConditionDetails(combo));
2459
+ }
2460
+ getAtomic = (hash) => {
2461
+ const cached = this.atomic_cache.get(hash);
2462
+ if (cached) return cached;
2463
+ const entry = getEntryFromHash(hash);
2464
+ const transformResult = this.getTransformResult(hash);
2465
+ if (!transformResult) return;
2466
+ const { className, classSelector, styles, transformed, parts } = transformResult;
2467
+ const basePath = [classSelector];
2468
+ const obj = {};
2469
+ let conditions;
2470
+ if (entry.cond) {
2471
+ conditions = this.context.conditions.sort(parts);
2472
+ const expanded = this.expandMultiBlock(conditions);
2473
+ if (expanded) for (const blockConditions of expanded) (0, _bamboocss_shared.deepSet)(obj, basePath.concat(blockConditions.flatMap((c) => this.resolveCondition(c))), styles);
2474
+ else (0, _bamboocss_shared.deepSet)(obj, basePath.concat(conditions.flatMap((c) => this.resolveCondition(c))), styles);
2475
+ } else (0, _bamboocss_shared.deepSet)(obj, basePath, styles);
2476
+ const styleResult = {
2477
+ result: obj,
2478
+ entry,
2479
+ hash,
2480
+ conditions,
2481
+ className,
2482
+ layer: transformed.layer
2483
+ };
2484
+ this.atomic_cache.set(hash, styleResult);
2485
+ return styleResult;
2486
+ };
2487
+ getGroup = (hashSet, key) => {
2488
+ const cached = this.group_cache.get(key);
2489
+ if (cached) return cached;
2490
+ let obj = {};
2491
+ const basePath = [];
2492
+ const details = [];
2493
+ const transform = this.context.utility.transform.bind(this.context.utility);
2494
+ hashSet.forEach((hash) => {
2495
+ const entry = getEntryFromHash(hash);
2496
+ const transformed = transform(entry.prop, (0, _bamboocss_shared.withoutImportant)(entry.value));
2497
+ if (!transformed.className) return;
2498
+ const result = (0, _bamboocss_shared.isImportant)(entry.value) ? (0, _bamboocss_shared.markImportant)(transformed.styles) : transformed.styles;
2499
+ const parts = entry.cond ? entry.cond.split(StyleEncoder.conditionSeparator) : [];
2500
+ let conditions;
2501
+ if (entry.cond) conditions = this.context.conditions.sort(parts);
2502
+ details.push({
2503
+ hash,
2504
+ entry,
2505
+ conditions,
2506
+ result
2507
+ });
2508
+ });
2509
+ sortStyleRules(details).forEach((value) => {
2510
+ if (value.conditions) {
2511
+ const expanded = this.expandMultiBlock(value.conditions);
2512
+ if (expanded) for (const blockConditions of expanded) {
2513
+ const path = basePath.concat(blockConditions.flatMap((c) => this.resolveCondition(c)));
2514
+ obj = (0, _bamboocss_shared.deepSet)(obj, path, value.result);
2515
+ }
2516
+ else {
2517
+ const path = basePath.concat(value.conditions.flatMap((c) => this.resolveCondition(c)));
2518
+ obj = (0, _bamboocss_shared.deepSet)(obj, path, value.result);
2519
+ }
2520
+ } else obj = (0, _bamboocss_shared.deepSet)(obj, basePath, value.result);
2521
+ });
2522
+ const result = {
2523
+ result: obj,
2524
+ hashSet,
2525
+ details,
2526
+ className: key
2527
+ };
2528
+ this.group_cache.set(key, result);
2529
+ return result;
2530
+ };
2531
+ getRecipeBase = (hashSet, recipeName, slot) => {
2532
+ const recipeConfig = this.context.recipes.getConfig(recipeName);
2533
+ if (!recipeConfig) return;
2534
+ const recipeNode = this.context.recipes.getRecipe(recipeName);
2535
+ if (!recipeNode) return;
2536
+ const className = "slots" in recipeConfig && slot ? this.context.recipes.getSlotKey(recipeNode.className, slot) : recipeNode.className;
2537
+ const cached = this.recipe_base_cache.get(className);
2538
+ if (cached) return cached;
2539
+ const selector = this.formatSelector([], className);
2540
+ const style = this.getGroup(hashSet, className);
2541
+ const result = Object.assign({}, style, {
2542
+ result: { ["." + selector]: style.result },
2543
+ recipe: recipeName,
2544
+ className,
2545
+ slot
2546
+ });
2547
+ this.recipe_base_cache.set(className, result);
2548
+ return result;
2549
+ };
2550
+ collectAtomic = (encoder) => {
2551
+ const atomic = [];
2552
+ encoder.atomic.forEach((item) => {
2553
+ const result = this.getAtomic(item);
2554
+ if (!result) return;
2555
+ atomic.push(result);
2556
+ });
2557
+ sortStyleRules(atomic).forEach((styleResult) => {
2558
+ this.atomic.add(styleResult);
2559
+ this.classNames.set(styleResult.className, styleResult);
2560
+ });
2561
+ return this;
2562
+ };
2563
+ processClassName = (recipeName, hash) => {
2564
+ const result = this.getAtomic(hash);
2565
+ if (!result) return;
2566
+ (0, _bamboocss_shared.getOrCreateSet)(this.recipes, recipeName).add(result);
2567
+ this.classNames.set(result.className, result);
2568
+ };
2569
+ collectRecipe = (encoder) => {
2570
+ encoder.recipes.forEach((hashSet, recipeName) => {
2571
+ const recipeConfig = this.context.recipes.getConfig(recipeName);
2572
+ if (!recipeConfig) return;
2573
+ hashSet.forEach((hash) => {
2574
+ if ("slots" in recipeConfig) recipeConfig.slots.forEach((slot) => {
2575
+ const slotHash = hash + StyleEncoder.separator + "slot:" + slot;
2576
+ this.processClassName(recipeName, slotHash);
2577
+ });
2578
+ else this.processClassName(recipeName, hash);
2579
+ });
2580
+ });
2581
+ };
2582
+ collectRecipeBase = (encoder) => {
2583
+ encoder.recipes_base.forEach((hashSet, recipeKey) => {
2584
+ const [recipeName, slot] = recipeKey.split(this.context.recipes.slotSeparator);
2585
+ if (!this.context.recipes.getConfig(recipeName)) return;
2586
+ const result = this.getRecipeBase(hashSet, recipeName, slot);
2587
+ if (!result) return;
2588
+ (0, _bamboocss_shared.getOrCreateSet)(this.recipes_base, recipeKey).add(result);
2589
+ this.classNames.set(result.className, result);
2590
+ });
2591
+ };
2592
+ collectGrouped = (encoder) => {
2593
+ encoder.grouped.forEach((hashSet, groupId) => {
2594
+ const groupKey = "grouped:" + groupId;
2595
+ const style = this.getGroup(hashSet, groupKey);
2596
+ const shortHash = this.context.utility.toHash(["grouped", groupId], this.context.utility.defaultHashFn);
2597
+ const className = this.formatSelector([], shortHash);
2598
+ const result = {
2599
+ ...style,
2600
+ className,
2601
+ result: { ["." + className]: style.result }
2602
+ };
2603
+ this.grouped.add(result);
2604
+ this.classNames.set(className, result);
2605
+ });
2606
+ };
2607
+ /**
2608
+ * Collect and re-create all styles and recipes objects from the style encoder
2609
+ * So that we can just iterate over them and transform resulting CSS objects into CSS strings
2610
+ */
2611
+ collect = (encoder) => {
2612
+ this.collectAtomic(encoder);
2613
+ this.collectGrouped(encoder);
2614
+ this.collectRecipe(encoder);
2615
+ this.collectRecipeBase(encoder);
2616
+ return this;
2617
+ };
2618
+ getConfigRecipeResult = (recipeName) => {
2619
+ return {
2620
+ atomic: this.atomic,
2621
+ base: this.recipes_base.get(recipeName),
2622
+ variants: this.recipes.get(recipeName)
2623
+ };
2624
+ };
2625
+ getConfigSlotRecipeResult = (recipeName) => {
2626
+ const recipeConfig = this.context.recipes.getConfigOrThrow(recipeName);
2627
+ if (!Recipes.isSlotRecipeConfig(recipeConfig)) throw new _bamboocss_shared.BambooError("UNKNOWN_RECIPE", `Recipe "${recipeName}" is not a slot recipe`);
2628
+ const base = {};
2629
+ recipeConfig.slots.map((slot) => {
2630
+ const recipeKey = this.context.recipes.getSlotKey(recipeName, slot);
2631
+ base[slot] = this.recipes_base.get(recipeKey);
2632
+ });
2633
+ return {
2634
+ atomic: this.atomic,
2635
+ base,
2636
+ variants: this.recipes.get(recipeName)
2637
+ };
2638
+ };
2639
+ getRecipeResult = (recipeName) => {
2640
+ if (this.context.recipes.isSlotRecipe(recipeName)) return this.getConfigSlotRecipeResult(recipeName);
2641
+ return this.getConfigRecipeResult(recipeName);
2642
+ };
2643
+ };
2644
+ const entryKeys = [
2645
+ "cond",
2646
+ "recipe",
2647
+ "layer",
2648
+ "slot"
2649
+ ];
2650
+ const getEntryFromHash = (hash) => {
2651
+ const parts = hash.split(StyleEncoder.separator);
2652
+ const entry = {
2653
+ prop: parts[0],
2654
+ value: parseValue(parts[1].replace("value:", ""))
2655
+ };
2656
+ parts.forEach((part) => {
2657
+ const key = entryKeys.find((k) => part.startsWith(k));
2658
+ if (key) entry[key] = part.slice(key.length + 1);
2659
+ });
2660
+ return entry;
2661
+ };
2662
+ const startsWithZero = /^0\d+$/;
2663
+ const parseValue = (value) => {
2664
+ if (startsWithZero.test(value)) return value;
2665
+ const asNumber = Number(value);
2666
+ if (!Number.isNaN(asNumber)) return asNumber;
2667
+ return castBoolean(value);
2668
+ };
2669
+ const castBoolean = (value) => {
2670
+ if (value === "true") return true;
2671
+ if (value === "false") return false;
2672
+ return value;
2673
+ };
2674
+ const pseudoElementRegex = /::[\w-]/;
2675
+ /**
2676
+ * Sort flattened condition details (at-rules and selectors only):
2677
+ * at-rules first, pseudo-elements last, preserve relative order.
2678
+ *
2679
+ * Note: This only operates on individual at-rule and selector conditions
2680
+ * (not mixed or multi-block), so checking `raw` as string is sufficient
2681
+ * for pseudo-element detection.
2682
+ */
2683
+ const sortConditionDetails = (conditions) => {
2684
+ const indexed = conditions.map((cond, i) => ({
2685
+ cond,
2686
+ i
2687
+ }));
2688
+ indexed.sort((a, b) => {
2689
+ const aIsAtRule = a.cond.type === "at-rule";
2690
+ const bIsAtRule = b.cond.type === "at-rule";
2691
+ if (aIsAtRule && !bIsAtRule) return -1;
2692
+ if (!aIsAtRule && bIsAtRule) return 1;
2693
+ const aIsPseudo = typeof a.cond.raw === "string" && pseudoElementRegex.test(a.cond.raw);
2694
+ if (aIsPseudo !== (typeof b.cond.raw === "string" && pseudoElementRegex.test(b.cond.raw))) return aIsPseudo ? 1 : -1;
2695
+ return a.i - b.i;
2696
+ });
2697
+ return indexed.map((item) => item.cond);
2698
+ };
2699
+ //#endregion
2700
+ //#region src/static-css.ts
2701
+ var StaticCss = class {
2702
+ context;
2703
+ encoder;
2704
+ decoder;
2705
+ breakpointKeys;
2706
+ conditionKeys;
2707
+ wildcardCache = /* @__PURE__ */ new Map();
2708
+ constructor(context) {
2709
+ this.context = context;
2710
+ this.encoder = context.encoder;
2711
+ this.decoder = context.decoder;
2712
+ this.breakpointKeys = Object.keys(context.config.theme?.breakpoints ?? {});
2713
+ this.conditionKeys = Object.keys(context.config.conditions ?? {});
2714
+ }
2715
+ clone() {
2716
+ this.encoder = this.encoder.clone();
2717
+ this.decoder = this.decoder.clone();
2718
+ return this;
2719
+ }
2720
+ formatCondition = (condition) => {
2721
+ return this.conditionKeys.includes(condition) ? `_${condition}` : condition;
2722
+ };
2723
+ getConditionalValues = (conditions, value) => {
2724
+ return conditions.reduce((acc, key) => {
2725
+ const cond = this.formatCondition(key);
2726
+ return {
2727
+ ...acc,
2728
+ [cond]: value
2729
+ };
2730
+ }, { base: value });
2731
+ };
2732
+ createRegex = () => {
2733
+ const pattern = `(${Array.from(this.decoder.classNames.keys()).map((name) => (0, _bamboocss_shared.esc)(name)).join("|")})`;
2734
+ return new RegExp(`\\b${pattern}\\b`, "g");
2735
+ };
2736
+ parse = (text) => {
2737
+ const regex = this.createRegex();
2738
+ const matches = text.match(regex);
2739
+ if (!matches) return [];
2740
+ return matches.map((match) => match.replace(".", ""));
2741
+ };
2742
+ /**
2743
+ * Get property keys with memoization for wildcard expansion
2744
+ * This is the main performance optimization - avoids redundant token lookups
2745
+ */
2746
+ getCachedPropertyKeys = (property) => {
2747
+ if (!this.wildcardCache.has(property)) {
2748
+ const keys = this.context.utility.getPropertyKeys(property);
2749
+ this.wildcardCache.set(property, keys);
2750
+ _bamboocss_logger.logger.debug("static_css:wildcard", `${property} -> ${keys.length} values (memoized)`);
2751
+ } else _bamboocss_logger.logger.debug("static_css:wildcard", `${property} (cache hit)`);
2752
+ return this.wildcardCache.get(property);
2753
+ };
2754
+ /**
2755
+ * Get pattern property values with memoization
2756
+ */
2757
+ getCachedPatternPropertyValues = (patternName, property) => {
2758
+ const cacheKey = `${patternName}:${property}`;
2759
+ if (!this.wildcardCache.has(cacheKey)) {
2760
+ const values = this.context.patterns.getPropertyValues(patternName, property) ?? [];
2761
+ this.wildcardCache.set(cacheKey, values);
2762
+ _bamboocss_logger.logger.debug("static_css:wildcard", `Pattern ${patternName}.${property} -> ${values.length} values (memoized)`);
2763
+ } else _bamboocss_logger.logger.debug("static_css:wildcard", `Pattern ${patternName}.${property} (cache hit)`);
2764
+ return this.wildcardCache.get(cacheKey);
2765
+ };
2766
+ getCssObjects = (entry, conditions) => {
2767
+ const [property, values] = entry;
2768
+ const propKeys = this.getCachedPropertyKeys(property);
2769
+ return values.flatMap((value) => value === "*" ? propKeys : value).map((value) => ({ [property]: conditions.length ? this.getConditionalValues(conditions, value) : value }));
2770
+ };
2771
+ getCssRuleObjects = (rule) => {
2772
+ const conditions = rule.conditions || [];
2773
+ if (rule.responsive) conditions.push(...this.breakpointKeys);
2774
+ return Object.entries(rule.properties).flatMap((entry) => this.getCssObjects(entry, conditions));
2775
+ };
2776
+ getPatternObjects = (name, entry, conditions) => {
2777
+ const [property, values] = entry;
2778
+ const propValues = this.getCachedPatternPropertyValues(name, property);
2779
+ return values.flatMap((value) => value === "*" ? propValues : value).map((patternValue) => {
2780
+ const value = this.context.patterns.transform(name, { [property]: patternValue });
2781
+ const conditionalValues = this.getConditionalValues(conditions, value);
2782
+ return conditions.length ? conditionalValues : value;
2783
+ });
2784
+ };
2785
+ getPatternRuleObjects = (name, pattern) => {
2786
+ const details = this.context.patterns.details.find((d) => d.baseName === name);
2787
+ if (!details) return [];
2788
+ const useAllKeys = pattern === "*";
2789
+ let props = {};
2790
+ if (useAllKeys) props = Object.fromEntries((details.props ?? []).map((key) => [key, ["*"]]));
2791
+ const { conditions = [], responsive = false, properties = props } = useAllKeys ? {} : pattern;
2792
+ if (responsive) conditions.push(...this.breakpointKeys);
2793
+ return Object.entries(properties).flatMap((entry) => this.getPatternObjects(name, entry, conditions));
2794
+ };
2795
+ getRecipeNode = (name) => {
2796
+ return this.context.recipes.details.find((detail) => detail.baseName === name);
2797
+ };
2798
+ getRecipeRuleObjects = (name, recipe, recipeNode) => {
2799
+ const recipeKeys = recipeNode.variantKeyMap;
2800
+ if (!recipeKeys) return [];
2801
+ const { conditions = [], responsive, ...variants } = recipe === "*" ? recipeKeys : recipe;
2802
+ if (responsive) conditions.push(...this.breakpointKeys);
2803
+ return Object.entries(variants).flatMap(([variant, values]) => {
2804
+ if (!Array.isArray(values)) return [];
2805
+ return values.flatMap((value) => value === "*" ? recipeKeys[variant] : value).map((value) => {
2806
+ const conditionalValues = this.getConditionalValues(conditions, value);
2807
+ return { [name]: { [variant]: conditions.length ? conditionalValues : value } };
2808
+ });
2809
+ });
2810
+ };
2811
+ getRecipeCompoundVariantCssObjects = (recipeNode) => {
2812
+ const cssRules = [];
2813
+ const { compoundVariants } = recipeNode.config;
2814
+ if (!compoundVariants) return cssRules;
2815
+ compoundVariants.forEach((compoundVariant) => {
2816
+ const css = compoundVariant.css;
2817
+ if ("slots" in recipeNode.config && recipeNode.config.slots.length) Object.values(css).forEach((styles) => {
2818
+ Object.entries(styles).forEach(([prop, value]) => {
2819
+ cssRules.push({ [prop]: value });
2820
+ });
2821
+ });
2822
+ else Object.entries(css).forEach(([prop, value]) => {
2823
+ cssRules.push({ [prop]: value });
2824
+ });
2825
+ });
2826
+ return cssRules;
2827
+ };
2828
+ /**
2829
+ * This transforms a static css config into the same format as in the ParserResult,
2830
+ * so that it can be processed by the same logic as styles found in app code.
2831
+ *
2832
+ * e.g.
2833
+ * @example { css: [{ color: ['red', 'blue'] }] } => { css: [{ color: 'red }, { color: 'blue }] }
2834
+ * @example { css: [{ color: ['red'], conditions: ['md'] }] } => { css: [{ color: { base: 'red', md: 'red' } }] }
2835
+ *
2836
+ */
2837
+ getStyleObjects(options) {
2838
+ const { css = [], patterns = {} } = options;
2839
+ const results = {
2840
+ css: [],
2841
+ recipes: [],
2842
+ patterns: []
2843
+ };
2844
+ css.forEach((rule) => {
2845
+ const cssObjects = this.getCssRuleObjects(rule);
2846
+ results.css.push(...cssObjects);
2847
+ });
2848
+ const recipes = options.recipes ?? {};
2849
+ Object.entries(recipes).forEach(([recipe, rules]) => {
2850
+ const recipeNode = this.getRecipeNode(recipe);
2851
+ if (!recipeNode) return;
2852
+ results.recipes.push({ [recipe]: {} });
2853
+ if (recipeNode.config.compoundVariants) results.css.push(...this.getRecipeCompoundVariantCssObjects(recipeNode));
2854
+ rules.forEach((rule) => {
2855
+ results.recipes.push(...this.getRecipeRuleObjects(recipe, rule, recipeNode));
2856
+ });
2857
+ });
2858
+ Object.entries(patterns).forEach(([pattern, rules]) => {
2859
+ rules.forEach((rule) => {
2860
+ results.patterns.push(...this.getPatternRuleObjects(pattern, rule));
2861
+ });
2862
+ });
2863
+ return results;
2864
+ }
2865
+ process = (options, stylesheet) => {
2866
+ const { context } = this;
2867
+ const sheet = stylesheet ?? context.createSheet();
2868
+ const isClonedInstance = this.encoder !== context.encoder;
2869
+ const encoder = isClonedInstance ? context.encoder.clone() : this.encoder;
2870
+ const decoder = isClonedInstance ? context.decoder.clone() : this.decoder;
2871
+ const staticCss = {
2872
+ ...options,
2873
+ recipes: { ...typeof options.recipes === "string" ? {} : options.recipes }
2874
+ };
2875
+ const { theme = {} } = context.config;
2876
+ const recipeConfigs = Object.assign({}, theme.recipes, theme.slotRecipes);
2877
+ const useAllRecipes = options.recipes === "*";
2878
+ Object.entries(recipeConfigs).forEach(([name, recipe]) => {
2879
+ if (useAllRecipes) staticCss.recipes[name] = ["*"];
2880
+ else if (recipe.staticCss) staticCss.recipes[name] = recipe.staticCss;
2881
+ });
2882
+ _bamboocss_logger.logger.debug("static_css:process", `Processing staticCss`);
2883
+ const results = this.getStyleObjects(staticCss);
2884
+ _bamboocss_logger.logger.debug("static_css:process", `Generated style objects: ${results.css.length} css, ${results.recipes.length} recipes, ${results.patterns.length} patterns`);
2885
+ results.css.forEach((css) => {
2886
+ encoder.hashStyleObject(encoder.atomic, css);
2887
+ });
2888
+ results.recipes.forEach((result) => {
2889
+ Object.entries(result).forEach(([name, value]) => {
2890
+ encoder.processRecipe(name, value);
2891
+ });
2892
+ });
2893
+ results.patterns.forEach((result) => {
2894
+ encoder.hashStyleObject(encoder.atomic, result);
2895
+ });
2896
+ sheet.processDecoder(decoder.collect(encoder));
2897
+ return {
2898
+ results,
2899
+ sheet
2900
+ };
2901
+ };
2902
+ };
2903
+ //#endregion
2904
+ //#region src/plugins/merge-rules.ts
2905
+ const vendorPrefix = /-(ah|apple|atsc|epub|hp|khtml|moz|ms|o|rim|ro|tc|wap|webkit|xv)-/;
2906
+ const findMsInputPlaceholder = (selector) => ~selector.search(/-ms-input-placeholder/i);
2907
+ function filterPrefixes(selector) {
2908
+ return selector.match(vendorPrefix);
2909
+ }
2910
+ function sameVendor(selectorsA, selectorsB) {
2911
+ const same = (selectors) => selectors.map((s) => filterPrefixes(s)?.join() ?? "").join(",");
2912
+ const findMsVendor = (selectors) => selectors.find((s) => findMsInputPlaceholder(s));
2913
+ return same(selectorsA) === same(selectorsB) && !(findMsVendor(selectorsA) && findMsVendor(selectorsB));
2914
+ }
2915
+ function noVendor(selector) {
2916
+ return !vendorPrefix.test(selector);
2917
+ }
2918
+ function checkMatch(nodeA, nodeB) {
2919
+ if (nodeA.type === "atrule" && nodeB.type === "atrule") return nodeA.params === nodeB.params && nodeA.name?.toLowerCase() === nodeB.name?.toLowerCase();
2920
+ return nodeA.type === nodeB.type;
2921
+ }
2922
+ function sameParent(nodeA, nodeB) {
2923
+ if (!nodeA.parent) return !nodeB.parent;
2924
+ if (!nodeB.parent) return false;
2925
+ if (!checkMatch(nodeA.parent, nodeB.parent)) return false;
2926
+ return sameParent(nodeA.parent, nodeB.parent);
2927
+ }
2928
+ function declarationIsEqual(a, b) {
2929
+ return a.important === b.important && a.prop === b.prop && a.value === b.value;
2930
+ }
2931
+ function indexOfDeclaration(array, decl) {
2932
+ return array.findIndex((d) => declarationIsEqual(d, decl));
2933
+ }
2934
+ function intersect(a, b, not = false) {
2935
+ return a.filter((c) => {
2936
+ const index = indexOfDeclaration(b, c) !== -1;
2937
+ return not ? !index : index;
2938
+ });
2939
+ }
2940
+ function sameDeclarationsAndOrder(a, b) {
2941
+ if (a.length !== b.length) return false;
2942
+ return a.every((d, index) => declarationIsEqual(d, b[index]));
2943
+ }
2944
+ function isRuleOrAtRule(node) {
2945
+ return node.type === "rule" || node.type === "atrule";
2946
+ }
2947
+ function isDeclaration(node) {
2948
+ return node.type === "decl";
2949
+ }
2950
+ function getDecls(rule) {
2951
+ return rule.nodes.filter(isDeclaration);
2952
+ }
2953
+ const joinSelectors = (...rules) => rules.map((s) => s.selector).join(",");
2954
+ function ruleLength(...rules) {
2955
+ return rules.map((r) => r.nodes.length ? String(r) : "").join("").length;
2956
+ }
2957
+ function splitProp(prop) {
2958
+ const parts = prop.split("-");
2959
+ if (prop[0] !== "-") return {
2960
+ prefix: "",
2961
+ base: parts[0],
2962
+ rest: parts.slice(1)
2963
+ };
2964
+ if (prop[1] === "-") return {
2965
+ prefix: null,
2966
+ base: null,
2967
+ rest: [prop]
2968
+ };
2969
+ return {
2970
+ prefix: parts[1],
2971
+ base: parts[2],
2972
+ rest: parts.slice(3)
2973
+ };
2974
+ }
2975
+ function isConflictingProp(propA, propB) {
2976
+ if (propA === propB) return true;
2977
+ const a = splitProp(propA);
2978
+ const b = splitProp(propB);
2979
+ if (!a.base && !b.base) return true;
2980
+ if (a.base !== b.base && a.base !== "place" && b.base !== "place") return false;
2981
+ if (a.rest.length !== b.rest.length) return true;
2982
+ if (a.base === "border") {
2983
+ const allRestProps = new Set([...a.rest, ...b.rest]);
2984
+ if (allRestProps.has("image") || allRestProps.has("width") || allRestProps.has("color") || allRestProps.has("style")) return true;
2985
+ }
2986
+ return a.rest.every((s, index) => b.rest[index] === s);
2987
+ }
2988
+ function mergeParents(first, second) {
2989
+ if (!first.parent || !second.parent) return false;
2990
+ if (first.parent === second.parent) return false;
2991
+ second.remove();
2992
+ first.parent.append(second);
2993
+ return true;
2994
+ }
2995
+ function canMerge(ruleA, ruleB) {
2996
+ const a = ruleA.selectors;
2997
+ const b = ruleB.selectors;
2998
+ const selectors = a.concat(b);
2999
+ const parent = sameParent(ruleA, ruleB);
3000
+ if (parent && ruleA.parent && ruleA.parent.type === "atrule" && ruleA.parent.name?.includes("keyframes")) return false;
3001
+ if (ruleA.some(isRuleOrAtRule) || ruleB.some(isRuleOrAtRule)) return false;
3002
+ return parent && (selectors.every(noVendor) || sameVendor(a, b));
3003
+ }
3004
+ function partialMerge(first, second) {
3005
+ let intersection = intersect(getDecls(first), getDecls(second));
3006
+ if (intersection.length === 0) return second;
3007
+ let nextRule = second.next();
3008
+ if (!nextRule) nextRule = (second.parent?.next())?.nodes?.[0];
3009
+ if (nextRule && nextRule.type === "rule" && canMerge(second, nextRule)) {
3010
+ const nextIntersection = intersect(getDecls(second), getDecls(nextRule));
3011
+ if (nextIntersection.length > intersection.length) {
3012
+ mergeParents(second, nextRule);
3013
+ first = second;
3014
+ second = nextRule;
3015
+ intersection = nextIntersection;
3016
+ }
3017
+ }
3018
+ const firstDecls = getDecls(first);
3019
+ intersection = intersection.filter((decl, intersectIndex) => {
3020
+ const indexOfDecl = indexOfDeclaration(firstDecls, decl);
3021
+ const nextConflictInFirst = firstDecls.slice(indexOfDecl + 1).filter((d) => isConflictingProp(d.prop, decl.prop));
3022
+ if (nextConflictInFirst.length === 0) return true;
3023
+ const nextConflictInIntersection = intersection.slice(intersectIndex + 1).filter((d) => isConflictingProp(d.prop, decl.prop));
3024
+ if (nextConflictInFirst.length !== nextConflictInIntersection.length) return false;
3025
+ return nextConflictInFirst.every((d, index) => declarationIsEqual(d, nextConflictInIntersection[index]));
3026
+ });
3027
+ const secondDecls = getDecls(second);
3028
+ intersection = intersection.filter((decl) => {
3029
+ const nextConflictIndex = secondDecls.findIndex((d) => isConflictingProp(d.prop, decl.prop));
3030
+ if (nextConflictIndex === -1) return false;
3031
+ if (!declarationIsEqual(secondDecls[nextConflictIndex], decl)) return false;
3032
+ if (decl.prop.toLowerCase() !== "direction" && decl.prop.toLowerCase() !== "unicode-bidi" && secondDecls.some((d) => d.prop.toLowerCase() === "all")) return false;
3033
+ secondDecls.splice(nextConflictIndex, 1);
3034
+ return true;
3035
+ });
3036
+ if (intersection.length === 0) return second;
3037
+ const receivingBlock = second.clone();
3038
+ receivingBlock.selector = joinSelectors(first, second);
3039
+ receivingBlock.nodes = [];
3040
+ second.parent.insertBefore(second, receivingBlock);
3041
+ const firstClone = first.clone();
3042
+ const secondClone = second.clone();
3043
+ function moveDecl(callback) {
3044
+ return (decl) => {
3045
+ if (indexOfDeclaration(intersection, decl) !== -1) callback(decl);
3046
+ };
3047
+ }
3048
+ firstClone.walkDecls(moveDecl((decl) => {
3049
+ decl.remove();
3050
+ receivingBlock.append(decl);
3051
+ }));
3052
+ secondClone.walkDecls(moveDecl((decl) => decl.remove()));
3053
+ if (ruleLength(firstClone, receivingBlock, secondClone) < ruleLength(first, second)) {
3054
+ first.replaceWith(firstClone);
3055
+ second.replaceWith(secondClone);
3056
+ [
3057
+ firstClone,
3058
+ receivingBlock,
3059
+ secondClone
3060
+ ].forEach((r) => {
3061
+ if (r.nodes.length === 0) r.remove();
3062
+ });
3063
+ if (!secondClone.parent) return receivingBlock;
3064
+ return secondClone;
3065
+ } else {
3066
+ receivingBlock.remove();
3067
+ return second;
3068
+ }
3069
+ }
3070
+ function selectorMerger() {
3071
+ let cache = null;
3072
+ return function(rule) {
3073
+ if (!cache || !canMerge(rule, cache)) {
3074
+ cache = rule;
3075
+ return;
3076
+ }
3077
+ if (cache === rule) {
3078
+ cache = rule;
3079
+ return;
3080
+ }
3081
+ mergeParents(cache, rule);
3082
+ if (sameDeclarationsAndOrder(getDecls(rule), getDecls(cache))) {
3083
+ rule.selector = joinSelectors(cache, rule);
3084
+ cache.remove();
3085
+ cache = rule;
3086
+ return;
3087
+ }
3088
+ if (cache.selector === rule.selector) {
3089
+ const cached = getDecls(cache);
3090
+ rule.walk((node) => {
3091
+ if (node.type === "decl" && indexOfDeclaration(cached, node) !== -1) {
3092
+ node.remove();
3093
+ return;
3094
+ }
3095
+ cache.append(node);
3096
+ });
3097
+ rule.remove();
3098
+ return;
3099
+ }
3100
+ cache = partialMerge(cache, rule);
3101
+ };
3102
+ }
3103
+ function mergeRules() {
3104
+ return {
3105
+ postcssPlugin: "postcss-merge-rules",
3106
+ OnceExit(css) {
3107
+ css.walkRules(selectorMerger());
3108
+ }
3109
+ };
3110
+ }
3111
+ mergeRules.postcss = true;
3112
+ //#endregion
3113
+ //#region src/plugins/prettify.ts
3114
+ function prettifyNode(node, indent = 0) {
3115
+ node.each && node.each((child, i) => {
3116
+ if (!child.raws.before || !child.raws.before.trim() || child.raws.before.includes("\n")) child.raws.before = `\n${node.type !== "rule" && i > 0 ? "\n" : ""}${" ".repeat(indent)}`;
3117
+ prettifyNode(child, indent + 1);
3118
+ });
3119
+ }
3120
+ function prettify() {
3121
+ return (root) => {
3122
+ prettifyNode(root);
3123
+ if (root.first) root.first.raws.before = "";
3124
+ };
3125
+ }
3126
+ prettify.postcssPlugin = "bamboo-prettify";
3127
+ //#endregion
3128
+ //#region src/plugins/optimize-postcss.ts
3129
+ function optimizePostCss(code, options = {}) {
3130
+ const { minify = false } = options;
3131
+ const plugins = [
3132
+ (0, postcss_nested.default)(),
3133
+ (0, postcss_discard_duplicates.default)(),
3134
+ mergeRules(),
3135
+ (0, postcss_discard_empty.default)()
3136
+ ];
3137
+ if (minify) plugins.push((0, postcss_normalize_whitespace.default)(), (0, postcss_minify_selectors.default)());
3138
+ else plugins.push(prettify());
3139
+ const { css } = (0, postcss.default)(plugins).process(code);
3140
+ return css;
3141
+ }
3142
+ //#endregion
3143
+ //#region src/optimize.ts
3144
+ function optimizeCss(code, options = {}) {
3145
+ const { hooks } = options;
3146
+ const css = typeof code === "string" ? code : code.toString();
3147
+ if (hooks?.["css:optimize"]) {
3148
+ const result = hooks["css:optimize"]({
3149
+ css,
3150
+ minify: options.minify,
3151
+ browserslist: options.browserslist
3152
+ });
3153
+ if (result !== void 0) return result;
3154
+ }
3155
+ return optimizePostCss(code, options);
3156
+ }
3157
+ function expandNestedCss(code) {
3158
+ const { css } = (0, postcss.default)([(0, postcss_nested.default)(), prettify()]).process(code);
3159
+ return css;
3160
+ }
3161
+ //#endregion
3162
+ //#region src/plugins/sort-mq.ts
3163
+ const atRuleName = ts_pattern.P.union("media", "container");
3164
+ function sortMediaQueries() {
3165
+ const inner = (root) => {
3166
+ root.nodes?.sort((a, b) => {
3167
+ return (0, ts_pattern.match)({
3168
+ a,
3169
+ b
3170
+ }).with({
3171
+ a: {
3172
+ type: "atrule",
3173
+ name: atRuleName
3174
+ },
3175
+ b: {
3176
+ type: "atrule",
3177
+ name: atRuleName
3178
+ }
3179
+ }, ({ a, b }) => {
3180
+ return sortAtRules(a.params, b.params);
3181
+ }).with({
3182
+ a: {
3183
+ type: "atrule",
3184
+ name: atRuleName
3185
+ },
3186
+ b: ts_pattern.P.any
3187
+ }, () => {
3188
+ return 1;
3189
+ }).with({
3190
+ a: ts_pattern.P.any,
3191
+ b: {
3192
+ type: "atrule",
3193
+ name: atRuleName
3194
+ }
3195
+ }, () => {
3196
+ return -1;
3197
+ }).otherwise(() => {
3198
+ return 0;
3199
+ });
3200
+ });
3201
+ root.nodes?.forEach((node) => {
3202
+ if ("nodes" in node) inner(node);
3203
+ });
3204
+ };
3205
+ return inner;
3206
+ }
3207
+ sortMediaQueries.postcssPlugin = "bamboo-sort-mq";
3208
+ //#endregion
3209
+ //#region src/stylesheet.ts
3210
+ var Stylesheet = class {
3211
+ context;
3212
+ constructor(context) {
3213
+ this.context = context;
3214
+ }
3215
+ get layers() {
3216
+ return this.context.layers;
3217
+ }
3218
+ getLayer(layer) {
3219
+ return this.context.layers[layer];
3220
+ }
3221
+ process(options) {
3222
+ const layer = this.getLayer(options.layer);
3223
+ if (!layer) return;
3224
+ const { styles } = options;
3225
+ if (typeof styles !== "object") return;
3226
+ try {
3227
+ layer.append(stringify(styles));
3228
+ } catch (error) {
3229
+ if (error instanceof postcss.CssSyntaxError) _bamboocss_logger.logger.error("sheet:process", error.showSourceCode(true));
3230
+ else _bamboocss_logger.logger.caughtError("sheet:process", "Failed to process styles", error);
3231
+ }
3232
+ }
3233
+ serialize = (styles) => {
3234
+ return serializeStyles(this.context, styles);
3235
+ };
3236
+ processResetCss = (styles) => {
3237
+ let css = stringify(this.serialize(styles));
3238
+ if (this.context.hooks["cssgen:done"]) css = this.context.hooks["cssgen:done"]({
3239
+ artifact: "reset",
3240
+ content: css
3241
+ }) ?? css;
3242
+ this.context.layers.reset.append(css);
3243
+ };
3244
+ processGlobalCss = (styles) => {
3245
+ let css = stringify(this.serialize(styles));
3246
+ css += this.context.globalVars.toString();
3247
+ css += this.context.globalFontface.toString();
3248
+ css += this.context.globalPositionTry.toString();
3249
+ if (this.context.hooks["cssgen:done"]) css = this.context.hooks["cssgen:done"]({
3250
+ artifact: "global",
3251
+ content: css
3252
+ }) ?? css;
3253
+ this.context.layers.base.append(css);
3254
+ };
3255
+ processCss = (styles, layer) => {
3256
+ if (!styles) return;
3257
+ this.process({
3258
+ styles,
3259
+ layer
3260
+ });
3261
+ };
3262
+ processDecoder = (decoder) => {
3263
+ sortStyleRules([...decoder.atomic]).forEach((css) => {
3264
+ this.processCss(css.result, css.layer ?? "utilities");
3265
+ });
3266
+ decoder.grouped.forEach((grouped) => {
3267
+ this.processCss(grouped.result, "utilities");
3268
+ });
3269
+ decoder.recipes.forEach((recipeSet) => {
3270
+ recipeSet.forEach((recipe) => {
3271
+ this.processCss(recipe.result, recipe.entry.slot ? "recipes_slots" : "recipes");
3272
+ });
3273
+ });
3274
+ decoder.recipes_base.forEach((recipeSet) => {
3275
+ recipeSet.forEach((recipe) => {
3276
+ this.processCss(recipe.result, recipe.slot ? "recipes_slots_base" : "recipes_base");
3277
+ });
3278
+ });
3279
+ };
3280
+ /**
3281
+ * Process only the styles for a specific recipe from the decoder
3282
+ */
3283
+ processDecoderForRecipe = (decoder, recipeName) => {
3284
+ const recipeSet = decoder.recipes.get(recipeName);
3285
+ if (recipeSet) recipeSet.forEach((recipe) => {
3286
+ this.processCss(recipe.result, recipe.entry.slot ? "recipes_slots" : "recipes");
3287
+ });
3288
+ decoder.recipes_base.forEach((baseSet, recipeKey) => {
3289
+ const [baseRecipeName] = recipeKey.split("__");
3290
+ if (baseRecipeName === recipeName) baseSet.forEach((recipe) => {
3291
+ this.processCss(recipe.result, recipe.slot ? "recipes_slots_base" : "recipes_base");
3292
+ });
3293
+ });
3294
+ };
3295
+ getLayerCss = (...layers) => {
3296
+ const breakpoints = this.context.conditions.breakpoints;
3297
+ return optimizeCss(layers.map((layer) => {
3298
+ const root = this.context.layers.getLayerRoot(layer);
3299
+ breakpoints.expandScreenAtRule(root);
3300
+ return root.toString();
3301
+ }).join("\n"), {
3302
+ minify: false,
3303
+ browserslist: this.context.browserslist,
3304
+ hooks: this.context.hooks
3305
+ });
3306
+ };
3307
+ toCss = ({ minify } = {}) => {
3308
+ try {
3309
+ const breakpoints = this.context.conditions.breakpoints;
3310
+ const root = this.context.layers.insert();
3311
+ breakpoints.expandScreenAtRule(root);
3312
+ const plugins = [sortMediaQueries()];
3313
+ if (this.context.polyfill) plugins.push((0, _csstools_postcss_cascade_layers.default)());
3314
+ return optimizeCss((0, postcss.default)(plugins).process(root).toString(), {
3315
+ minify,
3316
+ browserslist: this.context.browserslist,
3317
+ hooks: this.context.hooks
3318
+ });
3319
+ } catch (error) {
3320
+ if (error instanceof postcss.CssSyntaxError) _bamboocss_logger.logger.error("sheet:toCss", error.showSourceCode(true));
3321
+ throw error;
3322
+ }
3323
+ };
3324
+ };
3325
+ //#endregion
3326
+ //#region src/color-mix.ts
3327
+ const colorMix = (value, token) => {
3328
+ if (!value || typeof value !== "string") return {
3329
+ invalid: true,
3330
+ value
3331
+ };
3332
+ const [rawColor, rawOpacity] = value.split("/");
3333
+ if (!rawColor || !rawOpacity) return {
3334
+ invalid: true,
3335
+ value: rawColor
3336
+ };
3337
+ const colorToken = token(`colors.${rawColor}`);
3338
+ const opacityToken = token.raw(`opacity.${rawOpacity}`)?.value;
3339
+ if (!opacityToken && isNaN(Number(rawOpacity))) return {
3340
+ invalid: true,
3341
+ value: rawColor
3342
+ };
3343
+ const percent = opacityToken ? Number(opacityToken) * 100 + "%" : `${rawOpacity}%`;
3344
+ const color = colorToken ?? rawColor;
3345
+ return {
3346
+ invalid: false,
3347
+ color,
3348
+ value: `color-mix(in srgb, ${color} ${percent}, transparent)`
3349
+ };
3350
+ };
3351
+ //#endregion
3352
+ //#region src/utility.ts
3353
+ var Utility = class {
3354
+ options;
3355
+ /**
3356
+ * The token map or dictionary of tokens
3357
+ */
3358
+ tokens;
3359
+ /**
3360
+ * [cache] The map of property names to their resolved class names
3361
+ */
3362
+ classNames = /* @__PURE__ */ new Map();
3363
+ /**
3364
+ * [cache] The map of the property to their resolved styless
3365
+ */
3366
+ styles = /* @__PURE__ */ new Map();
3367
+ /**
3368
+ * Map of shorthand properties to their longhand properties
3369
+ */
3370
+ shorthands = /* @__PURE__ */ new Map();
3371
+ /**
3372
+ * The map of possible values for each property
3373
+ */
3374
+ types = /* @__PURE__ */ new Map();
3375
+ /**
3376
+ * The map of the property keys
3377
+ */
3378
+ propertyTypeKeys = /* @__PURE__ */ new Map();
3379
+ /**
3380
+ * The utility config
3381
+ */
3382
+ config = {};
3383
+ /**
3384
+ * The map of property names to their transform functions
3385
+ */
3386
+ transforms = /* @__PURE__ */ new Map();
3387
+ /**
3388
+ * The map of property names to their config
3389
+ */
3390
+ configs = /* @__PURE__ */ new Map();
3391
+ /**
3392
+ * The map of deprecated properties
3393
+ */
3394
+ deprecated = /* @__PURE__ */ new Set();
3395
+ separator = "_";
3396
+ prefix = "";
3397
+ strictTokens = false;
3398
+ constructor(options) {
3399
+ this.options = options;
3400
+ const { tokens, config = {}, separator, prefix, shorthands, strictTokens } = options;
3401
+ this.tokens = tokens;
3402
+ this.config = this.normalizeConfig(config);
3403
+ if (separator) this.separator = separator;
3404
+ if (prefix) this.prefix = prefix;
3405
+ if (strictTokens) this.strictTokens = strictTokens;
3406
+ if (shorthands) this.assignShorthands();
3407
+ this.assignColorPaletteProperty();
3408
+ this.assignProperties();
3409
+ this.assignPropertyTypes();
3410
+ }
3411
+ defaultHashFn = _bamboocss_shared.toHash;
3412
+ toHash = (path, hashFn) => hashFn(path.join(":"));
3413
+ normalizeConfig(config) {
3414
+ return Object.fromEntries(Object.entries(config).map(([property, propertyConfig]) => {
3415
+ return [property, this.normalize(propertyConfig)];
3416
+ }));
3417
+ }
3418
+ assignDeprecated = (property, config) => {
3419
+ if (!config.deprecated) return;
3420
+ this.deprecated.add(property);
3421
+ if ((0, _bamboocss_shared.isString)(config.shorthand)) this.deprecated.add(config.shorthand);
3422
+ if (Array.isArray(config.shorthand)) config.shorthand.forEach((shorthand) => this.deprecated.add(shorthand));
3423
+ };
3424
+ register = (property, config) => {
3425
+ this.config[property] = this.normalize(config);
3426
+ this.assignProperty(property, config);
3427
+ this.assignPropertyType(property, config);
3428
+ };
3429
+ assignShorthands = () => {
3430
+ for (const [property, config] of Object.entries(this.config)) {
3431
+ const { shorthand } = config ?? {};
3432
+ if (!shorthand) continue;
3433
+ (Array.isArray(shorthand) ? shorthand : [shorthand]).forEach((shorthandName) => {
3434
+ this.shorthands.set(shorthandName, property);
3435
+ });
3436
+ }
3437
+ };
3438
+ assignColorPaletteProperty = () => {
3439
+ if (!this.tokens.view.colorPalettes.size) return;
3440
+ const values = (0, _bamboocss_shared.mapToJson)(this.tokens.view.colorPalettes);
3441
+ this.config.colorPalette = {
3442
+ values: Object.keys(values),
3443
+ transform(value) {
3444
+ return values[value];
3445
+ }
3446
+ };
3447
+ };
3448
+ resolveShorthand = (prop) => {
3449
+ return this.shorthands.get(prop) ?? prop;
3450
+ };
3451
+ get hasShorthand() {
3452
+ return this.shorthands.size > 0;
3453
+ }
3454
+ get isEmpty() {
3455
+ return Object.keys(this.config).length === 0;
3456
+ }
3457
+ entries = () => {
3458
+ return Object.entries(this.config).filter(([, value]) => !!value?.className).map(([key, value]) => [key, value.className]);
3459
+ };
3460
+ getPropKey = (prop, value) => {
3461
+ return `(${prop} = ${value})`;
3462
+ };
3463
+ hash = (prop, value) => {
3464
+ return `${prop}${this.separator}${value}`;
3465
+ };
3466
+ /**
3467
+ * Get all the possible values for the defined property
3468
+ */
3469
+ getPropertyValues = (config, resolveFn) => {
3470
+ const { values } = config;
3471
+ const fn = (key) => {
3472
+ const categoryValues = this.getTokenCategoryValues(key);
3473
+ if (!categoryValues) return;
3474
+ const prop = resolveFn?.(key);
3475
+ if (!prop) return;
3476
+ return { [prop]: categoryValues };
3477
+ };
3478
+ if ((0, _bamboocss_shared.isString)(values)) return fn?.(values) ?? this.tokens.view.getCategoryValues(values) ?? {};
3479
+ if (Array.isArray(values)) return values.reduce((result, value) => {
3480
+ result[value] = value;
3481
+ return result;
3482
+ }, {});
3483
+ if ((0, _bamboocss_shared.isFunction)(values)) return values(resolveFn ? fn : this.getTokenCategoryValues.bind(this));
3484
+ return values;
3485
+ };
3486
+ getPropertyRawValue(config, value) {
3487
+ const { values } = config;
3488
+ if (!values) return value;
3489
+ if ((0, _bamboocss_shared.isString)(values)) return this.tokens.view.valuesByCategory.get(values)?.get(String(value)) || value;
3490
+ if (Array.isArray(values)) return value;
3491
+ if ((0, _bamboocss_shared.isFunction)(values)) return values(this.getTokenCategoryValues.bind(this))[value] || value;
3492
+ if (values.type) return value;
3493
+ return values[value] || value;
3494
+ }
3495
+ getToken = (path) => {
3496
+ return this.tokens.view.getVar(path);
3497
+ };
3498
+ getTokenCategoryValues = (category) => {
3499
+ return this.tokens.view.getCategoryValues(category);
3500
+ };
3501
+ /**
3502
+ * Normalize the property config
3503
+ */
3504
+ normalize = (propertyConfig) => {
3505
+ const config = { ...propertyConfig };
3506
+ if (config.values === "keyframes") config.values = Object.keys(this.options.keyframes ?? {});
3507
+ if (config.shorthand && !config.className) config.className = Array.isArray(config.shorthand) ? config.shorthand[0] : config.shorthand;
3508
+ return config;
3509
+ };
3510
+ assignProperty = (property, config) => {
3511
+ this.setTransform(property, config?.transform);
3512
+ this.assignDeprecated(property, config);
3513
+ if (!config) return;
3514
+ this.configs.set(property, config);
3515
+ };
3516
+ assignProperties = () => {
3517
+ for (const [property, propertyConfig] of Object.entries(this.config)) {
3518
+ if (!propertyConfig) continue;
3519
+ this.assignProperty(property, propertyConfig);
3520
+ }
3521
+ };
3522
+ assignPropertiesValues = () => {
3523
+ for (const [property, propertyConfig] of Object.entries(this.config)) {
3524
+ if (!propertyConfig) continue;
3525
+ this.assignPropertyValues(property, propertyConfig);
3526
+ }
3527
+ return this;
3528
+ };
3529
+ assignPropertyValues = (property, config) => {
3530
+ const values = this.getPropertyValues(config);
3531
+ if (!values) return;
3532
+ for (const [alias, raw] of Object.entries(values)) {
3533
+ const propKey = this.getPropKey(property, alias);
3534
+ this.setStyles(property, raw, alias, propKey);
3535
+ this.getOrCreateClassName(property, alias);
3536
+ }
3537
+ };
3538
+ getPropertyKeys = (prop) => {
3539
+ const propConfig = this.config[prop];
3540
+ if (!propConfig) return [];
3541
+ const values = this.getPropertyValues(propConfig);
3542
+ if (!values) return [];
3543
+ return Object.keys(values);
3544
+ };
3545
+ getPropertyTypeKeys = (property) => {
3546
+ const keys = this.propertyTypeKeys.get(property);
3547
+ return keys ? Array.from(keys) : [];
3548
+ };
3549
+ assignPropertyType = (property, config) => {
3550
+ if (!config) return;
3551
+ const values = this.getPropertyValues(config, (key) => `type:Tokens["${key}"]`);
3552
+ if (typeof values === "object" && values.type) {
3553
+ this.types.set(property, new Set([`type:${values.type}`]));
3554
+ return;
3555
+ }
3556
+ if (values) {
3557
+ const keys = new Set(Object.keys(values));
3558
+ this.types.set(property, keys);
3559
+ this.propertyTypeKeys.set(property, keys);
3560
+ }
3561
+ const set = this.types.get(property) ?? /* @__PURE__ */ new Set();
3562
+ if (!this.strictTokens && config.property) this.types.set(property, set.add(`CssProperties["${config.property}"]`));
3563
+ };
3564
+ assignPropertyTypes = () => {
3565
+ for (const [property, propertyConfig] of Object.entries(this.config)) {
3566
+ if (!propertyConfig) continue;
3567
+ this.assignPropertyType(property, propertyConfig);
3568
+ }
3569
+ };
3570
+ addPropertyType = (property, type) => {
3571
+ const set = this.types.get(property) ?? /* @__PURE__ */ new Set();
3572
+ this.types.set(property, new Set([...set, ...type]));
3573
+ };
3574
+ /**
3575
+ * Returns the Typescript type for the define properties
3576
+ */
3577
+ getTypes = () => {
3578
+ const map = /* @__PURE__ */ new Map();
3579
+ for (const [prop, tokens] of this.types.entries()) {
3580
+ if (tokens.size === 0) continue;
3581
+ const typeValues = Array.from(tokens).map((key) => {
3582
+ if (key.startsWith("CssProperties")) return key;
3583
+ if (key.startsWith("type:")) return key.replace("type:", "");
3584
+ return JSON.stringify(key);
3585
+ });
3586
+ map.set(prop, typeValues);
3587
+ }
3588
+ return map;
3589
+ };
3590
+ defaultTransform = (0, _bamboocss_shared.memo)((value, prop) => {
3591
+ if (prop.startsWith("--")) {
3592
+ const tokenValue = this.tokens.view.getVar(value);
3593
+ value = typeof tokenValue === "string" ? tokenValue : value;
3594
+ }
3595
+ return { [prop]: value };
3596
+ });
3597
+ setTransform = (property, transform) => {
3598
+ const defaultTransform = (value) => this.defaultTransform(value, property);
3599
+ const transformFn = transform ?? defaultTransform;
3600
+ this.transforms.set(property, transformFn);
3601
+ return this;
3602
+ };
3603
+ getTokenFn = () => {
3604
+ return Object.assign(this.getToken.bind(this), { raw: (path) => this.tokens.getByName(path) });
3605
+ };
3606
+ resolveColorMix = (value) => {
3607
+ return colorMix(value, this.getTokenFn());
3608
+ };
3609
+ getTransformArgs = (raw) => {
3610
+ return {
3611
+ token: this.getTokenFn(),
3612
+ raw,
3613
+ utils: { colorMix: this.resolveColorMix.bind(this) }
3614
+ };
3615
+ };
3616
+ setStyles = (property, raw, alias, propKey) => {
3617
+ propKey = propKey ?? this.getPropKey(property, raw);
3618
+ const defaultTransform = (value) => this.defaultTransform(value, property);
3619
+ const styles = (this.transforms.get(property) ?? defaultTransform)(raw, this.getTransformArgs(alias));
3620
+ this.styles.set(propKey, styles ?? {});
3621
+ return this;
3622
+ };
3623
+ formatClassName = (className) => {
3624
+ return [this.prefix, className].filter(Boolean).join("-");
3625
+ };
3626
+ /**
3627
+ * Returns the resolved className for a given property and value
3628
+ */
3629
+ getClassName = (property, raw) => {
3630
+ const config = this.configs.get(property);
3631
+ if (!config || !config.className) return this.hash((0, _bamboocss_shared.hypenateProperty)(property), raw);
3632
+ return this.hash(config.className, raw);
3633
+ };
3634
+ getOrCreateClassName = (property, raw) => {
3635
+ const propKey = this.getPropKey(property, raw);
3636
+ let className = this.classNames.get(propKey);
3637
+ if (!className) {
3638
+ className = this.getClassName(property, raw);
3639
+ this.classNames.set(propKey, className);
3640
+ }
3641
+ return className;
3642
+ };
3643
+ /**
3644
+ * Whether a given property exists in the config
3645
+ */
3646
+ has = (prop) => {
3647
+ return this.configs.has(prop);
3648
+ };
3649
+ /**
3650
+ * Get or create the resolved styles for a given property and value
3651
+ */
3652
+ getOrCreateStyle = (prop, value) => {
3653
+ const propKey = this.getPropKey(prop, value);
3654
+ const styles = this.styles.get(propKey);
3655
+ if (styles) return styles;
3656
+ const config = this.configs.get(prop);
3657
+ const raw = config ? this.getPropertyRawValue(config, value) : value;
3658
+ this.setStyles(prop, raw, value, propKey);
3659
+ return this.styles.get(propKey);
3660
+ };
3661
+ /**
3662
+ * Returns the resolved className and styles for a given property and value
3663
+ */
3664
+ transform = (prop, value) => {
3665
+ if (value == null) return {
3666
+ className: "",
3667
+ styles: {}
3668
+ };
3669
+ const key = this.resolveShorthand(prop);
3670
+ let styleValue = (0, _bamboocss_shared.getArbitraryValue)(value);
3671
+ if ((0, _bamboocss_shared.isString)(styleValue)) styleValue = this.tokens.expandReferenceInValue(styleValue);
3672
+ return (0, _bamboocss_shared.compact)({
3673
+ layer: this.configs.get(key)?.layer,
3674
+ className: this.getOrCreateClassName(key, (0, _bamboocss_shared.withoutSpace)(value)),
3675
+ styles: this.getOrCreateStyle(key, styleValue)
3676
+ });
3677
+ };
3678
+ /**
3679
+ * All keys including shorthand keys
3680
+ */
3681
+ keys = () => {
3682
+ const shorthands = Array.from(this.shorthands.keys());
3683
+ const properties = Object.keys(this.config);
3684
+ return [...shorthands, ...properties];
3685
+ };
3686
+ /**
3687
+ * Returns a map of the property keys and their shorthands
3688
+ */
3689
+ getPropShorthandsMap = () => {
3690
+ const shorthandsByProp = /* @__PURE__ */ new Map();
3691
+ this.shorthands.forEach((prop, shorthand) => {
3692
+ const list = shorthandsByProp.get(prop) ?? [];
3693
+ list.push(shorthand);
3694
+ shorthandsByProp.set(prop, list);
3695
+ });
3696
+ return shorthandsByProp;
3697
+ };
3698
+ /**
3699
+ * Returns the shorthands for a given property
3700
+ */
3701
+ getPropShorthands = (prop) => {
3702
+ return this.getPropShorthandsMap().get(prop) ?? [];
3703
+ };
3704
+ /**
3705
+ * Whether a given property is deprecated
3706
+ */
3707
+ isDeprecated = (prop) => {
3708
+ return this.deprecated.has(prop);
3709
+ };
3710
+ /**
3711
+ * Returns the token type for a given property
3712
+ */
3713
+ getTokenType = (prop) => {
3714
+ const set = this.types.get(prop);
3715
+ if (!set) return;
3716
+ for (const type of set) {
3717
+ const match = type.match(TOKEN_TYPE_PATTERN);
3718
+ if (match) return match[1];
3719
+ }
3720
+ };
3721
+ };
3722
+ const TOKEN_TYPE_PATTERN = /type:Tokens\["([^"]+)"\]/;
3723
+ //#endregion
3724
+ //#region src/context.ts
3725
+ const defaults = (config) => ({
3726
+ cssVarRoot: ":where(:root, :host)",
3727
+ jsxFactory: "styled",
3728
+ jsxStyleProps: "all",
3729
+ outExtension: "mjs",
3730
+ shorthands: true,
3731
+ syntax: "object-literal",
3732
+ ...config,
3733
+ layers: {
3734
+ reset: "reset",
3735
+ base: "base",
3736
+ tokens: "tokens",
3737
+ recipes: "recipes",
3738
+ utilities: "utilities",
3739
+ ...config.layers
3740
+ }
3741
+ });
3742
+ var Context = class {
3743
+ conf;
3744
+ studio;
3745
+ tokens;
3746
+ utility;
3747
+ recipes;
3748
+ conditions;
3749
+ patterns;
3750
+ staticCss;
3751
+ jsx;
3752
+ imports;
3753
+ paths;
3754
+ file;
3755
+ globalVars;
3756
+ globalFontface;
3757
+ globalPositionTry;
3758
+ encoder;
3759
+ decoder;
3760
+ hooksApi;
3761
+ properties;
3762
+ isValidProperty;
3763
+ messages;
3764
+ parserOptions;
3765
+ constructor(conf) {
3766
+ this.conf = conf;
3767
+ const config = defaults(conf.config);
3768
+ const theme = config.theme ?? {};
3769
+ conf.config = config;
3770
+ this.tokens = this.createTokenDictionary(theme, config.themes);
3771
+ this.hooks["tokens:created"]?.({ configure: (opts) => {
3772
+ if (opts.formatTokenName) this.tokens.formatTokenName = opts.formatTokenName;
3773
+ if (opts.formatCssVar) this.tokens.formatCssVar = opts.formatCssVar;
3774
+ } });
3775
+ this.tokens.init();
3776
+ this.utility = this.createUtility(config);
3777
+ this.hooks["utility:created"]?.({ configure: (opts) => {
3778
+ if (opts.toHash) this.utility.toHash = opts.toHash;
3779
+ } });
3780
+ this.conditions = this.createConditions(config);
3781
+ this.patterns = new Patterns({
3782
+ config,
3783
+ tokens: this.tokens,
3784
+ utility: this.utility,
3785
+ helpers: _bamboocss_shared.patternFns
3786
+ });
3787
+ this.studio = {
3788
+ outdir: `${config.outdir}-studio`,
3789
+ ...conf.config.studio
3790
+ };
3791
+ this.setupProperties();
3792
+ this.recipes = this.createRecipes(theme);
3793
+ this.encoder = new StyleEncoder({
3794
+ utility: this.utility,
3795
+ recipes: this.recipes,
3796
+ conditions: this.conditions,
3797
+ patterns: this.patterns,
3798
+ isTemplateLiteralSyntax: this.isTemplateLiteralSyntax,
3799
+ isValidProperty: this.isValidProperty
3800
+ });
3801
+ this.decoder = new StyleDecoder({
3802
+ conditions: this.conditions,
3803
+ utility: this.utility,
3804
+ recipes: this.recipes,
3805
+ hash: this.hash
3806
+ });
3807
+ this.setupCompositions(theme);
3808
+ this.registerAnimationName(theme);
3809
+ this.registerFontFamily(config.globalFontface);
3810
+ this.recipes.save(this.baseSheetContext);
3811
+ this.staticCss = new StaticCss({
3812
+ config,
3813
+ utility: this.utility,
3814
+ patterns: this.patterns,
3815
+ recipes: this.recipes,
3816
+ createSheet: this.createSheet,
3817
+ encoder: this.encoder,
3818
+ decoder: this.decoder
3819
+ });
3820
+ this.jsx = new JsxEngine({
3821
+ patterns: this.patterns,
3822
+ recipes: this.recipes,
3823
+ config
3824
+ });
3825
+ this.imports = new ImportMap({
3826
+ jsx: this.jsx,
3827
+ conf: this.conf,
3828
+ config: this.config,
3829
+ patterns: this.patterns,
3830
+ recipes: this.recipes,
3831
+ isValidProperty: this.isValidProperty
3832
+ });
3833
+ this.paths = new PathEngine({ config: this.config });
3834
+ this.file = new FileEngine({ config: this.config });
3835
+ this.globalVars = new GlobalVars({
3836
+ globalVars: this.config.globalVars,
3837
+ cssVarRoot: this.config.cssVarRoot
3838
+ });
3839
+ this.globalFontface = new GlobalFontface({ globalFontface: this.config.globalFontface });
3840
+ this.globalPositionTry = new GlobalPositionTry({ globalPositionTry: this.config.globalPositionTry });
3841
+ this.messages = getMessages({
3842
+ jsx: this.jsx,
3843
+ config: this.config,
3844
+ tokens: this.tokens,
3845
+ recipes: this.recipes,
3846
+ patterns: this.patterns,
3847
+ isTemplateLiteralSyntax: this.isTemplateLiteralSyntax
3848
+ });
3849
+ this.parserOptions = {
3850
+ hash: this.hash,
3851
+ compilerOptions: this.conf.tsconfig?.compilerOptions ?? {},
3852
+ recipes: this.recipes,
3853
+ patterns: this.patterns,
3854
+ jsx: this.jsx,
3855
+ config: this.config,
3856
+ tokens: this.tokens,
3857
+ conditions: this.conditions,
3858
+ utility: this.utility,
3859
+ encoder: this.encoder,
3860
+ tsOptions: this.conf.tsOptions,
3861
+ join: (...paths) => paths.join("/"),
3862
+ imports: this.imports
3863
+ };
3864
+ this.hooksApi = new HooksApi(this);
3865
+ this.hooks["context:created"]?.({
3866
+ ctx: this.hooksApi,
3867
+ logger: _bamboocss_logger.logger
3868
+ });
3869
+ }
3870
+ get config() {
3871
+ return this.conf.config;
3872
+ }
3873
+ get hooks() {
3874
+ return this.conf.hooks ?? {};
3875
+ }
3876
+ get isTemplateLiteralSyntax() {
3877
+ return this.config.syntax === "template-literal";
3878
+ }
3879
+ get hash() {
3880
+ return {
3881
+ tokens: (0, _bamboocss_shared.isBoolean)(this.config.hash) ? this.config.hash : this.config.hash?.cssVar,
3882
+ className: (0, _bamboocss_shared.isBoolean)(this.config.hash) ? this.config.hash : this.config.hash?.className
3883
+ };
3884
+ }
3885
+ get prefix() {
3886
+ return {
3887
+ tokens: (0, _bamboocss_shared.isString)(this.config.prefix) ? this.config.prefix : this.config.prefix?.cssVar,
3888
+ className: (0, _bamboocss_shared.isString)(this.config.prefix) ? this.config.prefix : this.config.prefix?.className
3889
+ };
3890
+ }
3891
+ createTokenDictionary = (theme, themeVariants) => {
3892
+ return new _bamboocss_token_dictionary.TokenDictionary({
3893
+ breakpoints: theme.breakpoints,
3894
+ tokens: theme.tokens,
3895
+ semanticTokens: theme.semanticTokens,
3896
+ themes: themeVariants,
3897
+ prefix: this.prefix.tokens,
3898
+ hash: this.hash.tokens,
3899
+ colorPalette: theme.colorPalette
3900
+ });
3901
+ };
3902
+ createUtility = (config) => {
3903
+ return new Utility({
3904
+ prefix: this.prefix.className,
3905
+ tokens: this.tokens,
3906
+ config: this.isTemplateLiteralSyntax ? {} : Object.assign({}, config.utilities),
3907
+ separator: config.separator,
3908
+ shorthands: config.shorthands,
3909
+ strictTokens: config.strictTokens,
3910
+ keyframes: config.theme?.keyframes
3911
+ });
3912
+ };
3913
+ createConditions = (config) => {
3914
+ return new Conditions({
3915
+ conditions: config.conditions,
3916
+ containerNames: config.theme?.containerNames,
3917
+ containerSizes: config.theme?.containerSizes,
3918
+ breakpoints: config.theme?.breakpoints,
3919
+ themes: config.themes
3920
+ });
3921
+ };
3922
+ createLayers = (layers) => {
3923
+ return new Layers(layers);
3924
+ };
3925
+ setupCompositions = (theme) => {
3926
+ const { textStyles, layerStyles, animationStyles } = theme;
3927
+ const compositions = (0, _bamboocss_shared.compact)({
3928
+ textStyle: textStyles,
3929
+ layerStyle: layerStyles,
3930
+ animationStyle: animationStyles
3931
+ });
3932
+ const stylesheetCtx = {
3933
+ ...this.baseSheetContext,
3934
+ layers: this.createLayers(this.config.layers)
3935
+ };
3936
+ for (const [key, values] of Object.entries(compositions)) {
3937
+ this.properties.add(key);
3938
+ const flatValues = (0, _bamboocss_shared.flatten)(values ?? {});
3939
+ const config = {
3940
+ layer: "compositions",
3941
+ className: key,
3942
+ values: Object.keys(flatValues),
3943
+ transform: (value) => {
3944
+ return transformStyles(stylesheetCtx, flatValues[value], key + "." + value);
3945
+ }
3946
+ };
3947
+ this.utility.register(key, config);
3948
+ }
3949
+ };
3950
+ registerAnimationName = (theme) => {
3951
+ this.utility.addPropertyType("animationName", Object.keys(theme.keyframes ?? {}));
3952
+ };
3953
+ registerFontFamily = (fontFaces) => {
3954
+ this.utility.addPropertyType("fontFamily", Object.keys(fontFaces ?? {}));
3955
+ };
3956
+ setupProperties = () => {
3957
+ this.properties = new Set([
3958
+ "css",
3959
+ ...this.utility.keys(),
3960
+ ...this.conditions.keys()
3961
+ ]);
3962
+ this.isValidProperty = (0, _bamboocss_shared.memo)((key) => this.properties.has(key) || (0, _bamboocss_is_valid_prop.isCssProperty)(key));
3963
+ };
3964
+ get baseSheetContext() {
3965
+ return {
3966
+ conditions: this.conditions,
3967
+ utility: this.utility,
3968
+ hash: this.hash.className,
3969
+ encoder: this.encoder,
3970
+ decoder: this.decoder,
3971
+ hooks: this.hooks,
3972
+ isValidProperty: this.isValidProperty,
3973
+ browserslist: this.config.browserslist,
3974
+ polyfill: this.config.polyfill,
3975
+ cssVarRoot: this.config.cssVarRoot,
3976
+ helpers: _bamboocss_shared.patternFns,
3977
+ globalVars: this.globalVars,
3978
+ globalFontface: this.globalFontface,
3979
+ globalPositionTry: this.globalPositionTry
3980
+ };
3981
+ }
3982
+ createSheet = () => {
3983
+ return new Stylesheet({
3984
+ ...this.baseSheetContext,
3985
+ layers: this.createLayers(this.config.layers)
3986
+ });
3987
+ };
3988
+ createRecipes = (theme) => {
3989
+ return new Recipes(Object.assign({}, theme.recipes ?? {}, theme.slotRecipes ?? {}));
3990
+ };
3991
+ isValidLayerParams = (params) => {
3992
+ const names = new Set(params.split(",").map((name) => name.trim()));
3993
+ return names.size >= 5 && Object.values(this.config.layers).every((name) => names.has(name));
3994
+ };
3995
+ };
3996
+ //#endregion
3997
+ //#region src/selector.ts
3998
+ const parentNestingRegex = /\s&/g;
3999
+ function extractParentSelectors(selector) {
4000
+ const result = /* @__PURE__ */ new Set();
4001
+ (0, postcss_selector_parser.default)((selectors) => {
4002
+ selectors.each((selector) => {
4003
+ (0, ts_pattern.match)(parseCondition(selector.toString())).with({ type: "parent-nesting" }, () => {
4004
+ result.add(selector.toString().replace(parentNestingRegex, "").trim());
4005
+ }).otherwise(() => {});
4006
+ });
4007
+ }).processSync(selector);
4008
+ const finalized = Array.from(result).join(", ").trim();
4009
+ return result.size > 1 ? `:where(${finalized})` : finalized;
4010
+ }
4011
+ function extractTrailingPseudos(selector) {
4012
+ const ast = (0, postcss_selector_parser.default)((selectors) => selectors).astSync(selector);
4013
+ const matrix = [];
4014
+ for (const [i, sel] of ast.nodes.entries()) for (const [j, child] of [...sel.nodes].reverse().entries()) {
4015
+ if (child.type !== "pseudo" || !child.value.startsWith("::")) break;
4016
+ matrix[j] = matrix[j] || [];
4017
+ matrix[j][i] = child;
4018
+ }
4019
+ const trailingPseudos = postcss_selector_parser.default.selector({ value: "" });
4020
+ for (const pseudos of matrix) {
4021
+ if (!pseudos) continue;
4022
+ if (new Set(pseudos.map((p) => p.value)).size > 1) break;
4023
+ pseudos.forEach((pseudo) => pseudo.remove());
4024
+ trailingPseudos.prepend(pseudos[0]);
4025
+ }
4026
+ if (trailingPseudos.nodes.length) return [trailingPseudos.toString(), ast.toString()];
4027
+ return [null, selector];
4028
+ }
4029
+ //#endregion
4030
+ exports.Breakpoints = Breakpoints;
4031
+ exports.Conditions = Conditions;
4032
+ exports.Context = Context;
4033
+ exports.FileMatcher = FileMatcher;
4034
+ exports.ImportMap = ImportMap;
4035
+ exports.JsxEngine = JsxEngine;
4036
+ exports.Layers = Layers;
4037
+ exports.Patterns = Patterns;
4038
+ exports.Recipes = Recipes;
4039
+ exports.RuleProcessor = RuleProcessor;
4040
+ exports.StaticCss = StaticCss;
4041
+ exports.StyleDecoder = StyleDecoder;
4042
+ exports.StyleEncoder = StyleEncoder;
4043
+ exports.Stylesheet = Stylesheet;
4044
+ exports.Utility = Utility;
4045
+ exports.expandNestedCss = expandNestedCss;
4046
+ exports.extractParentSelectors = extractParentSelectors;
4047
+ exports.extractTrailingPseudos = extractTrailingPseudos;
4048
+ Object.defineProperty(exports, "messages", {
4049
+ enumerable: true,
4050
+ get: function() {
4051
+ return messages_exports;
4052
+ }
4053
+ });
4054
+ exports.optimizeCss = optimizeCss;
4055
+ exports.stringify = stringify;