@bamboocss/generator 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -107,43 +107,13 @@ function generateConditions(ctx) {
107
107
  };
108
108
  }
109
109
  //#endregion
110
- //#region src/artifacts/js/conditions.string-literal.ts
111
- function generateStringLiteralConditions(ctx) {
112
- return {
113
- js: outdent.default`
114
- ${ctx.file.import("withoutSpace", "../helpers")}
115
-
116
- export const isCondition = (val) => condRegex.test(val)
117
-
118
- const condRegex = /^@|&|&$/
119
- const selectorRegex = /&|@/
120
-
121
- export const finalizeConditions = (paths) => {
122
- return paths.map((path) => (selectorRegex.test(path) ? \`[\${withoutSpace(path.trim())}]\` : path))
123
- }
124
-
125
- export function sortConditions(paths){
126
- return paths.sort((a, b) => {
127
- const aa = isCondition(a)
128
- const bb = isCondition(b)
129
- if (aa && !bb) return 1
130
- if (!aa && bb) return -1
131
- return 0
132
- })
133
- }
134
- `,
135
- dts: outdent.default`
136
- `
137
- };
138
- }
139
- //#endregion
140
110
  //#region src/artifacts/js/css-fn.ts
141
111
  function generateCssFn(ctx) {
142
112
  const { utility, hash, prefix, conditions } = ctx;
143
113
  const { separator, getPropShorthands } = utility;
144
114
  return {
145
115
  dts: outdent.outdent`
146
- ${ctx.file.importType("SystemStyleObject", "../types/index")}
116
+ ${ctx.file.importType("SystemStyleObject, ViewTransitionFn", "../types/index")}
147
117
 
148
118
  type Styles = SystemStyleObject | undefined | null | false
149
119
 
@@ -180,6 +150,24 @@ function generateCssFn(ctx) {
180
150
  */
181
151
  export declare function fallback(preferred: string | number, ...rest: Array<string | number>): \`fallback(\${string})\`;
182
152
 
153
+ /**
154
+ * Style the View Transitions API and get back one stable class for the bag.
155
+ *
156
+ * The class is applied through \`view-transition-class\`, so the same transition can be
157
+ * shared by any number of elements. You still set \`view-transition-name\` yourself —
158
+ * it has to be unique per element, so bamboo cannot share it for you.
159
+ *
160
+ * @example
161
+ * const slide = viewTransition({
162
+ * group: { animationDuration: '0.4s' },
163
+ * old: { animationName: 'slide-out' },
164
+ * new: { animationName: 'slide-in' },
165
+ * })
166
+ *
167
+ * @see https://bamboocss.com/docs/concepts/view-transitions
168
+ */
169
+ export declare const viewTransition: ViewTransitionFn;
170
+
183
171
  /**
184
172
  * Internal. Emitted for the source transform, which rewrites a single dynamic style
185
173
  * leaf into a call to this. Not part of the authoring API.
@@ -187,8 +175,8 @@ function generateCssFn(ctx) {
187
175
  export declare const cssLeaf: (prefix: string, prop: string, value: unknown) => string;
188
176
  `,
189
177
  js: outdent.outdent`
190
- ${ctx.file.import("cloneStyles, createCss, createMergeCss, hypenateProperty, leafClass, memo, withoutSpace", "../helpers")}
191
- ${ctx.file.import("sortConditions, finalizeConditions", "./conditions")}
178
+ ${ctx.file.import("cloneStyles, createCss, createMergeCss, hypenateProperty, leafClass, memo, viewTransitionClassName, withoutSpace", "../helpers")}
179
+ ${[ctx.file.import("sortConditions, finalizeConditions", "./conditions"), ctx.config.cssMode === "grouped" ? ctx.file.import("groups", "./groups") : ""].filter(Boolean).join("\n")}
192
180
 
193
181
  const utilities = "${utility.entries().map(([prop, className]) => {
194
182
  const shorthandList = getPropShorthands(prop);
@@ -218,7 +206,7 @@ function generateCssFn(ctx) {
218
206
  `}
219
207
 
220
208
  const context = {
221
- ${[hash.className && "hash: true,", ctx.config.cssMode === "grouped" && "grouped: true,"].filter(Boolean).join("\n ")}
209
+ ${[hash.className && "hash: true,", ctx.config.cssMode === "grouped" && "grouped: true,\n knownGroups: groups,"].filter(Boolean).join("\n ")}
222
210
  conditions: {
223
211
  shift: sortConditions,
224
212
  finalize: finalizeConditions,
@@ -243,6 +231,7 @@ function generateCssFn(ctx) {
243
231
  // condition object would otherwise poison it for everyone after them.
244
232
  css.raw = (...styles) => cloneStyles(mergeCss(...styles))
245
233
 
234
+
246
235
  // Emitted for the source transform, which rewrites a single dynamic style leaf into a
247
236
  // call to this rather than leaving a \`css()\` behind. \`prefix\` is the class up to the
248
237
  // value, resolved at build time; \`prop\` is only used for the shapes \`leafClass\`
@@ -257,82 +246,30 @@ function generateCssFn(ctx) {
257
246
  // value reaching \`css()\` is the same literal either way.
258
247
  export const fallback = (...values) => \`fallback($\{values.join(', ')})\`
259
248
 
260
- export const { mergeCss, assignCss } = createMergeCss(context)
261
- `
262
- };
263
- }
264
- //#endregion
265
- //#region src/artifacts/js/css-fn.string-literal.ts
266
- function generateStringLiteralCssFn(ctx) {
267
- const { utility, hash, prefix } = ctx;
268
- const { separator } = utility;
269
- return {
270
- dts: outdent.outdent`
271
- ${ctx.file.importType("SystemStyleObject", "../types/index")}
272
-
273
- type Styles =
274
- | { raw: readonly string[] | ArrayLike<string> }
275
- | SystemStyleObject
276
- | boolean
277
- | null
278
- | undefined
279
-
280
- interface CssRawFunction {
281
- (...styles: Styles[]): SystemStyleObject
282
- }
283
-
284
- interface CssFunction {
285
- (...styles: Styles[]): string
286
-
287
- raw: CssRawFunction
288
- }
289
-
290
- export declare const css: CssFunction;
291
- `,
292
- js: outdent.outdent`
293
- ${ctx.file.import("astish, cloneStyles, createCss, isObject, mergeProps, withoutSpace", "../helpers")}
294
- ${ctx.file.import("finalizeConditions, sortConditions", "./conditions")}
295
-
296
- function transform(prop, value) {
297
- const className = \`$\{prop}${separator}$\{withoutSpace(value)}\`
298
- return { className }
299
- }
300
-
301
- const context = {
302
- hash: ${hash.className ? "true" : "false"},
303
- conditions: {
304
- shift: sortConditions,
305
- finalize: finalizeConditions,
306
- breakpoints: { keys: [] },
307
- },
308
- utility: {
309
- prefix: ${prefix.className ? JSON.stringify(prefix.className) : void 0},
310
- transform,
311
- hasShorthand: false,
312
- toHash: ${utility.toHash},
313
- resolveShorthand(prop) {
314
- return prop
315
- },
316
- }
317
- }
318
-
319
- const cssFn = createCss(context)
249
+ // The class is the whole return value — the CSS behind it was emitted at build time
250
+ // from the same options, hashed by this same function. A call the extractor never saw
251
+ // still returns a class, exactly as \`css()\` does for a value it never saw.
252
+ export const viewTransition = (options) => viewTransitionClassName(options, ${JSON.stringify(prefix.className ?? "")})
320
253
 
321
- const fn = (style) => (isObject(style) ? style : astish(style[0]))
322
- export const css = (...styles) => cssFn(mergeProps(...styles.filter(Boolean).map(fn)))
323
- // Same independence guarantee as the object-syntax css.raw(), so the public
324
- // API behaves identically across both syntaxes.
325
- css.raw = (...styles) => cloneStyles(mergeProps(...styles.filter(Boolean).map(fn)))
254
+ export const { mergeCss, assignCss } = createMergeCss(context)
326
255
  `
327
256
  };
328
257
  }
329
258
  //#endregion
330
259
  //#region src/artifacts/js/cva.ts
331
260
  function generateCvaFn(ctx) {
261
+ const { utility, hash, prefix } = ctx;
262
+ const withPrefix = prefix.className ? `(className) => className ? ${JSON.stringify(prefix.className)} + '-' + className : ${JSON.stringify(prefix.className)}` : `(className) => className`;
332
263
  return {
333
264
  js: outdent.outdent`
334
- ${ctx.file.import("cloneStyles, compact, mergeProps, memo, splitProps, uniq", "../helpers")}
335
- ${ctx.file.import("css, mergeCss", "./css")}
265
+ ${ctx.file.import("cloneStyles, compact, getRecipeClassNames, getRecipeIdentity, mergeProps, memo, splitProps, toHash, uniq", "../helpers")}
266
+ ${ctx.file.import("mergeCss", "./css")}
267
+
268
+ // What \`createCss\` does to a class name, for the recipe path: prefix it, and hash it
269
+ // when \`hash.className\` is set. The build applies the same two steps to the rules it
270
+ // emits — see \`checkNamingAgreement\`, which compares the results.
271
+ const withPrefix = ${withPrefix}
272
+ const formatRecipeClass = ${hash.className ? `(className) => withPrefix((${utility.toHash})([className], toHash))` : `withPrefix`}
336
273
 
337
274
  const defaults = (conf) => ({
338
275
  base: {},
@@ -346,6 +283,11 @@ function generateCvaFn(ctx) {
346
283
  const { base, variants, defaultVariants, compoundVariants } = defaults(config)
347
284
  const getVariantProps = (variants) => ({ ...defaultVariants, ...compact(variants) })
348
285
 
286
+ // Derived from the config, because the build derives it from the same config while
287
+ // emitting the stylesheet and the two never meet. \`className\` when the author set
288
+ // one, a hash of the styles otherwise.
289
+ const name = getRecipeIdentity(config)
290
+
349
291
  function resolve(props = {}) {
350
292
  const computedVariants = getVariantProps(props)
351
293
  let variantCss = { ...base }
@@ -354,6 +296,13 @@ function generateCvaFn(ctx) {
354
296
  variantCss = mergeCss(variantCss, variants[key][value])
355
297
  }
356
298
  }
299
+ // A recipe with no compound variants has nothing left to merge, and the merge is
300
+ // not free just because its second operand is empty: \`mergeCss\` is memoized on its
301
+ // arguments, so the call hashes the whole accumulated style object before finding
302
+ // there is nothing to do. Most recipes declare no compound variants at all, so
303
+ // this is the common shape rather than a special case.
304
+ if (compoundVariants.length === 0) return variantCss
305
+
357
306
  const compoundVariantCss = getCompoundVariantCss(compoundVariants, computedVariants)
358
307
  return mergeCss(variantCss, compoundVariantCss)
359
308
  }
@@ -378,10 +327,25 @@ function generateCvaFn(ctx) {
378
327
  //
379
328
  // \`raw\` still clones what it returns. The memoized object is shared, so handing it to a
380
329
  // caller that mutated it would poison every later call.
330
+ //
331
+ // A recipe whose variants are all boolean could index an array instead of hashing, and
332
+ // that was built and measured: +25% to +35% on \`raw()\`. It is not here because the
333
+ // trade is bad. Correctness needs the selection read from own enumerable keys only, and
334
+ // every variant to carry a boolean default so the merge order is pinned — and once that
335
+ // gate is honest, no \`cva\`/\`sva\` call site in this repo passes it, because real recipes
336
+ // mix a string variant in. The cost is unconditional: +289 B gzipped on that module for
337
+ // every consumer, qualifying or not.
381
338
  const resolveVariants = memo(resolve)
382
339
 
340
+ // The class names the build emitted rules for: the recipe's own class, plus one per
341
+ // selected variant. Not \`css(resolve(props))\` — that would name classes by property,
342
+ // and the stylesheet names this recipe's rules semantically, in the \`recipes\` layer.
343
+ //
344
+ // Compound variants are absent on purpose. Their rule selects on the variant classes
345
+ // already in this list — \`.btn--size_sm.btn--tone_a\` — so it applies without anything
346
+ // being added here, and adding a class for it would name a rule that does not exist.
383
347
  function cvaFn(props) {
384
- return css(resolve(props))
348
+ return getRecipeClassNames(name, variants, getVariantProps(props), '${utility.separator}', formatRecipeClass)
385
349
  }
386
350
 
387
351
  const variantKeys = Object.keys(variants)
@@ -440,36 +404,55 @@ function generateCvaFn(ctx) {
440
404
  }
441
405
  //#endregion
442
406
  //#region src/artifacts/js/cx.ts
443
- const dts = outdent.default`
407
+ /**
408
+ * `cx` joins class names. It does not resolve conflicts between them, in any build.
409
+ *
410
+ * It used to, when the class names happened to carry a property to compare — atomic mode
411
+ * with `hash.className` off. That made it a correctness tool in development and a plain
412
+ * join in a hashed production build, from the same source, with no error either way. An
413
+ * override that worked locally silently stopped working when it shipped.
414
+ *
415
+ * The two could not be reconciled by teaching the matcher to read hashed names.
416
+ * `cssMode: 'grouped'` names a *whole call* with one class — `toHash(['grouped', groupId])`
417
+ * — so there is no single property behind it to compare, whatever the naming scheme. As
418
+ * long as grouped exists, some builds can never merge, and a `cx` that merges in the rest
419
+ * is a behavioural difference keyed on a config flag.
420
+ *
421
+ * So precedence is decided where it can be decided the same way everywhere: by
422
+ * {@link https://bamboocss.com/docs/concepts/cascade-layers cascade layers}. A component
423
+ * whose styles a consumer will override belongs in `recipes` — write it with `cva`/`sva`,
424
+ * not bare `css()` — and the consumer's `css()` in `utilities` wins by layer, in every
425
+ * build. Two `css()` outputs joined with `cx` are in the same layer and resolve by source
426
+ * order; when you own both, merge the style objects with `css(a, b)` instead.
427
+ */
428
+ const declaration = outdent.default`
444
429
  type Argument = string | boolean | null | undefined | Argument[]
445
430
 
446
431
  /**
447
- * Join classNames into a single string, with the last conflicting utility winning.
432
+ * Join classNames into a single string.
448
433
  *
449
- * \`cx('px_4', 'px_2')\` is \`'px_2'\`: two classes that set the same property under the
450
- * same conditions cannot both apply, and which one the browser picks would otherwise
451
- * depend on their order in the stylesheet rather than on the order you passed them.
452
- * Classes bamboo did not generate are left alone, duplicates included.
434
+ * This does **not** resolve conflicts between them: \`cx('px_4', 'px_2')\` keeps both, and
435
+ * the browser picks by their order in the stylesheet rather than by the order you passed
436
+ * them. That is true of every build — atomic, hashed and grouped alike.
437
+ *
438
+ * To override a style rather than append to it, let the cascade decide: styles from
439
+ * \`cva\`/\`sva\` sit in the \`recipes\` layer and \`css()\` in \`utilities\`, so a consumer's
440
+ * \`css()\` always wins. Between two \`css()\` calls you own, merge the objects instead —
441
+ * \`css(base, override)\` resolves per property before any class name exists.
453
442
  */
454
443
  export declare function cx(...args: Argument[]): string
455
444
  `;
456
- /**
457
- * The plain concatenating \`cx\`, for when the class names carry nothing to merge on.
458
- *
459
- * With \`hash.className\` every class is an opaque hash, so there is no property to compare
460
- * and no merge to do — emitting the matcher would only cost bytes on a path that runs in
461
- * the browser on every render.
462
- */
463
- function concatOnly() {
464
- return outdent.default`
445
+ function generateCx() {
446
+ return {
447
+ js: outdent.default`
465
448
  function cx(...args) {
466
449
  let str = ''
467
450
 
468
451
  for (let i = 0; i < args.length; i++) {
469
452
  const arg = args[i]
470
453
  if (!arg) continue
471
- // Arrays are part of the declared type, so this branch has to handle them even
472
- // though it does no merging — returning '' for \`cx(['a', 'b'])\` would be a lie.
454
+ // Arrays are part of the declared type, so this branch has to handle them.
455
+ // Returning '' for \`cx(['a', 'b'])\` would be a lie.
473
456
  const part = Array.isArray(arg) ? cx(...arg) : typeof arg === 'string' ? arg : ''
474
457
  if (!part) continue
475
458
  str && (str += ' ')
@@ -479,185 +462,18 @@ function concatOnly() {
479
462
  }
480
463
 
481
464
  export { cx }
482
- `;
483
- }
484
- function generateCx(ctx) {
485
- const { utility, hash, prefix } = ctx;
486
- const separatorChar = utility.separator;
487
- const utilityClassNames = [...new Set(utility.keys().map((key) => {
488
- const withEmptyValue = utility.getClassName(utility.resolveShorthand(key), "");
489
- return withEmptyValue.endsWith(separatorChar) ? withEmptyValue.slice(0, -separatorChar.length) : withEmptyValue;
490
- }))].sort();
491
- const recipeClassNames = [...new Set(ctx.recipes.details.map((node) => node.className))].filter(Boolean).sort();
492
- if (hash.className || utilityClassNames.length === 0) return {
493
- js: concatOnly(),
494
- dts
495
- };
496
- return {
497
- js: outdent.default`
498
- const cxSeparator = ${JSON.stringify(utility.separator)}
499
- const cxPrefix = ${prefix.className ? JSON.stringify(prefix.className + "-") : "''"}
500
- const cxUtilities = new Set(${JSON.stringify(utilityClassNames.join(","))}.split(','))
501
- const cxRecipes = ${recipeClassNames.length ? `new Set(${JSON.stringify(recipeClassNames.join(","))}.split(','))` : "null"}
502
-
503
- /**
504
- * The declaration a bamboo class sets: its condition path plus the property, without the
505
- * value. Two classes sharing one are alternatives, and only the last can apply.
506
- *
507
- * \`null\` for anything that is not a bamboo class, which is then never merged.
508
- */
509
- function mergeKey(className) {
510
- let end = className.length
511
-
512
- // \`c_red\` and \`c_red!\` are the same declaration. Argument order decides between them,
513
- // which is the point of this function — the cascade would always pick the important
514
- // one no matter which the caller asked for.
515
- if (end > 0 && className.charCodeAt(end - 1) === 33) end -= 1
516
- if (end === 0) return null
517
-
518
- // The last colon ends the condition path — but only one outside brackets, since an
519
- // arbitrary selector carries its own: \`[&[data-x="a:b"]]:px_4\`.
520
- let depth = 0
521
- let lastColon = -1
522
- for (let i = 0; i < end; i++) {
523
- const code = className.charCodeAt(i)
524
- if (code === 91) depth++
525
- else if (code === 93) depth--
526
- else if (code === 58 && depth === 0) lastColon = i
527
- }
528
-
529
- // Conditions come before the prefix — \`hover:bam-px_4\` — so the prefix is skipped
530
- // after the condition path, not before it. When a prefix is configured every class
531
- // bamboo emits carries it, so one that does not is by definition someone else's.
532
- let propStart = lastColon + 1
533
- if (cxPrefix) {
534
- if (!className.startsWith(cxPrefix, propStart)) return null
535
- propStart += cxPrefix.length
536
- }
537
-
538
- // A recipe owns its whole class, bare or with a \`--variant\` suffix, whatever it
539
- // looks like to the utility matcher below.
540
- if (cxRecipes !== null) {
541
- const variantIdx = className.indexOf('--', propStart)
542
- const base = variantIdx === -1 ? className.slice(propStart, end) : className.slice(propStart, variantIdx)
543
- if (cxRecipes.has(base)) return null
544
- }
545
-
546
- // The longest registered utility name wins, not the first separator. Utility names
547
- // contain the separator themselves under \`separator: '-'\` — \`bd-w\`, \`ov-x\`,
548
- // \`translate-x\` — and their leading segment is often a utility too, so stopping at the
549
- // first \`-\` would key \`bd-w-4px\` and \`bd-c-red\` both on \`bd\` and drop one of them.
550
- let property = null
551
- let sepIdx = className.indexOf(cxSeparator, propStart)
552
- while (sepIdx > propStart && sepIdx < end) {
553
- const candidate = className.slice(propStart, sepIdx)
554
- if (cxUtilities.has(candidate)) property = candidate
555
- sepIdx = className.indexOf(cxSeparator, sepIdx + 1)
556
- }
557
-
558
- // Only a class bamboo generated for a utility. A recipe class or a hand-written one
559
- // may well contain the separator, and merging on the text before it would drop a
560
- // class the caller meant to keep.
561
- if (property === null) return null
562
-
563
- return lastColon === -1 ? property : className.slice(0, lastColon) + ':' + property
564
- }
565
-
566
- function isClassWhitespace(code) {
567
- return code === 32 || code === 9 || code === 10 || code === 12 || code === 13
568
- }
569
-
570
- function flattenParts(parts, out) {
571
- for (let i = 0; i < parts.length; i++) {
572
- const part = parts[i]
573
- if (!part) continue
574
- if (Array.isArray(part)) flattenParts(part, out)
575
- else if (typeof part === 'string') out.push(part)
576
- }
577
- }
578
-
579
- function mergeClassStrings(classes) {
580
- const seen = new Map()
581
- const order = []
582
- let id = 0
583
-
584
- for (let c = 0; c < classes.length; c++) {
585
- const cls = classes[c]
586
- let tokenStart = 0
587
-
588
- for (let i = 0; i <= cls.length; i++) {
589
- // The class attribute splits on all ASCII whitespace, not just the space, and a
590
- // multi-line template literal is an ordinary way to write one.
591
- if (i !== cls.length && !isClassWhitespace(cls.charCodeAt(i))) continue
592
- if (i === tokenStart) {
593
- tokenStart = i + 1
594
- continue
595
- }
596
-
597
- const token = cls.slice(tokenStart, i)
598
- tokenStart = i + 1
599
-
600
- const key = mergeKey(token)
601
- if (key !== null) {
602
- // Keeps the first position and the last value, so a later override lands where
603
- // the class it replaces already sat.
604
- if (!seen.has(key)) order.push(key)
605
- seen.set(key, token)
606
- } else {
607
- // Not ours to reason about — kept as written, duplicates and all.
608
- const uniqueKey = '\\0' + id++
609
- order.push(uniqueKey)
610
- seen.set(uniqueKey, token)
611
- }
612
- }
613
- }
614
-
615
- if (order.length === 0) return ''
616
- let str = seen.get(order[0])
617
- for (let i = 1; i < order.length; i++) str += ' ' + seen.get(order[i])
618
- return str
619
- }
620
-
621
- function cx() {
622
- // Everything that produces a bamboo class string — \`css()\`, a recipe, a nested \`cx\` —
623
- // emits one that is already conflict-free, so a lone string has nothing to merge and
624
- // tokenizing it is pure cost. This is the hot path: \`cx(staticClasses, props.className)\`
625
- // with no \`className\` passed.
626
- if (arguments.length === 1) {
627
- const only = arguments[0]
628
- if (typeof only === 'string') return only
629
- if (!only) return ''
630
- }
631
-
632
- const flat = []
633
- flattenParts(arguments, flat)
634
- if (flat.length === 0) return ''
635
- if (flat.length === 1) return flat[0]
636
- return mergeClassStrings(flat)
637
- }
638
-
639
- export { cx }
640
- `,
641
- dts
465
+ `,
466
+ dts: declaration
642
467
  };
643
468
  }
644
469
  //#endregion
645
- //#region src/artifacts/generated/astish.mjs.json
646
- var content$11 = "//#region src/astish.ts\nconst newRule = /(?:([\\u0080-\\uFFFF\\w-%@]+) *:? *([^{;]+?);|([^;}{]*?) *{)|(}\\s*)/g;\nconst ruleClean = /\\/\\*[^]*?\\*\\/| +/g;\nconst ruleNewline = /\\n+/g;\nconst empty = \" \";\nconst astish = (val, tree = [{}]) => {\n if (!val) return tree[0];\n let block, left;\n while (block = newRule.exec(val.replace(ruleClean, \"\"))) if (block[4]) tree.shift();\n else if (block[3]) {\n left = block[3].replace(ruleNewline, empty).trim();\n if (!left.includes(\"&\") && !left.startsWith(\"@\")) left = \"& \" + left;\n tree.unshift(tree[0][left] = tree[0][left] || {});\n } else tree[0][block[1]] = block[2].replace(ruleNewline, empty).trim();\n return tree[0];\n};\n//#endregion\nexport { astish };\n";
647
- //#endregion
648
470
  //#region src/artifacts/generated/helpers.mjs.json
649
- var content$10 = "//#region src/assert.ts\nfunction isObject(value) {\n return typeof value === \"object\" && value != null && !Array.isArray(value);\n}\nconst isObjectOrArray = (obj) => typeof obj === \"object\" && obj !== null;\n//#endregion\n//#region src/condition.ts\nconst isBaseCondition = (v) => v === \"base\";\nfunction filterBaseConditions(c) {\n return c.slice().filter((v) => !isBaseCondition(v));\n}\n//#endregion\n//#region src/hash.ts\nfunction toChar(code) {\n return String.fromCharCode(code + (code > 25 ? 39 : 97));\n}\nfunction toName(code) {\n let name = \"\";\n let x;\n for (x = Math.abs(code); x > 52; x = x / 52 | 0) name = toChar(x % 52) + name;\n return toChar(x % 52) + name;\n}\nfunction toPhash(h, x) {\n let i = x.length;\n while (i) h = h * 33 ^ x.charCodeAt(--i);\n return h;\n}\nfunction toHash(value) {\n return toName(toPhash(5381, value) >>> 0);\n}\n//#endregion\n//#region src/important.ts\nconst importantRegex = /\\s*!(important)?/i;\nconst whitespaceRegex = /\\s/;\n/**\n* Collapse every run of whitespace to a single space, which is what the class name is\n* built from. Exported because `leafClass` has to reproduce this exact pipeline, and a\n* second copy of it would be free to drift from the one `createCss` runs.\n*/\nfunction sanitize(value) {\n if (typeof value !== \"string\") return value;\n const collapsed = whitespaceRegex.test(value) ? value.replaceAll(/[\\n\\s]+/g, \" \") : value;\n return collapsed.includes(\"\\0\") ? collapsed.replaceAll(\"\\0\", \"\") : collapsed;\n}\nfunction isImportant(value) {\n if (typeof value !== \"string\") return false;\n return value.includes(\"!\") && importantRegex.test(value);\n}\nfunction withoutImportant(value) {\n if (typeof value !== \"string\") return value;\n if (!value.includes(\"!\")) return value.trim();\n return value.replace(importantRegex, \"\").trim();\n}\nfunction withoutSpace(str) {\n if (typeof str !== \"string\") return str;\n return str.includes(\" \") ? str.replaceAll(\" \", \"_\") : str;\n}\n//#endregion\n//#region src/memo.ts\n/**\n* Bounded argument memo used by the generated runtime (`css`, patterns, `cva`, recipes).\n*\n* Two regimes, picked per call:\n*\n* - Arguments that are flat (objects of primitives) take a cheap structural hash\n* and are confirmed with an exact comparison, so a hash collision can never\n* serve the wrong result. This is the shape `css({ ... })` has.\n* - Anything nested falls back to `JSON.stringify`, which V8 does faster than a\n* JS walk.\n*\n* The second point is the counter-intuitive one, and it has been measured rather\n* than assumed. Extending the structural hash to recurse — so nested styles could\n* take the fast path too — is *slower*, because it trades one native serialization\n* for two JS walks (hash, then the deep equality that confirms it). Over 10k\n* iterations per shape:\n*\n* shape stringify recursive hash + deep equal\n* flat 1.06ms 2.09ms\n* _hover 1.00ms 2.16ms\n* responsive 1.23ms 2.15ms\n* realistic 2.32ms 5.84ms\n* nested 3 deep 1.22ms 2.35ms\n*\n* So a nested `css()` call costing several times a flat one is not a defect here.\n* It is the floor for a value-keyed memo in JS, and the way to avoid it is to not\n* make the call — see the build-time fold in `@bamboocss/vite`.\n*\n* Both regimes key on *values*, never on object identity: mutating a style object\n* between calls changes its hash, so the next call misses and recomputes rather\n* than serving a stale class. Keying nested arguments on the identity of the inner\n* objects would skip serialization entirely, but it cannot detect a mutation, and\n* \"same object, different contents\" is exactly what a style object built per render\n* looks like.\n*\n* Both caches are bounded. An unbounded memo is a leak in any long-lived process\n* (SSR), where the set of distinct style objects grows without limit.\n*/\n/**\n* Distinct hashes held per memoized function before the cache rotates.\n*\n* This bounds *buckets*, not entries: a bucket keeps up to `MAX_BUCKET` colliding\n* argument lists, so the ceiling is `MAX_ENTRIES * MAX_BUCKET` live entries, and\n* twice that across both generations, since the previous one is retained until the\n* next rotation. Collisions are rare in practice, so the realistic figure is close\n* to `MAX_ENTRIES` — but the worst case is what matters when sizing a long-lived\n* process, so state it plainly.\n*\n* Rotation beats evicting the oldest key: single-key eviction is worst-case for a\n* working set that cycles, because it drops exactly the entry about to be needed.\n* Measured on a cycling set of 20k styles, one-at-a-time eviction cost ~719ns/op\n* against ~189ns unbounded, while rotation holds ~274ns. On realistic skewed\n* access rotation is at or below the unbounded cost.\n*/\nconst MAX_ENTRIES = 1e3;\n/** Entries kept per hash bucket, to bound the cost of a collision scan. */\nconst MAX_BUCKET = 8;\n/**\n* DJB2 over the arguments' own keys and primitive values.\n* Returns `null` for anything nested, which routes the call to the string key.\n*/\nconst flatHashOrNull = (args) => {\n let h = 5381;\n for (let a = 0; a < args.length; a++) {\n const obj = args[a];\n if (obj === null || typeof obj !== \"object\") {\n const t = typeof obj;\n if (t === \"string\") for (let i = 0; i < obj.length; i++) h = h * 33 ^ obj.charCodeAt(i);\n else if (t === \"number\") h = h * 33 ^ (obj | 0);\n else if (t === \"boolean\") h = h * 33 ^ (obj ? 991 : 997);\n else h = h * 33 ^ 3;\n continue;\n }\n if (Array.isArray(obj)) h = h * 33 ^ 7;\n else {\n const proto = Object.getPrototypeOf(obj);\n if (proto !== Object.prototype && proto !== null) return null;\n }\n for (const k in obj) {\n const v = obj[k];\n const tv = typeof v;\n if (v !== null && tv === \"object\") return null;\n for (let i = 0; i < k.length; i++) h = h * 33 ^ k.charCodeAt(i);\n if (tv === \"string\") for (let i = 0; i < v.length; i++) h = h * 33 ^ v.charCodeAt(i);\n else if (tv === \"number\") h = h * 33 ^ (v | 0);\n else if (tv === \"boolean\") h = h * 33 ^ (v ? 991 : 997);\n else h = h * 33 ^ 2;\n }\n }\n return h >>> 0;\n};\n/**\n* Value snapshot of the arguments, taken once at insert.\n*\n* The cache must not hold the caller's objects: a style object can capture a much\n* larger graph, and keeping it alive until the cache rotates changes GC behaviour\n* for code that never asked to be cached. Only the flat path reaches here, so a\n* shallow copy contains primitives only and retains nothing.\n*\n* Comparing against a copy also removes the last way a mutation could be missed.\n* Were the caller's own object stored, `oa === ob` would short-circuit the value\n* comparison, and a mutation that happened to preserve the hash would return the\n* stale entry. Against a copy that check can only ever be true for equal\n* primitives.\n*/\nconst snapshotArgs = (args) => {\n const values = [];\n const counts = [];\n for (let i = 0; i < args.length; i++) {\n const o = args[i];\n if (o !== null && typeof o === \"object\") {\n const copy = Array.isArray(o) ? [] : {};\n let n = 0;\n for (const k in o) {\n copy[k] = o[k];\n n++;\n }\n values.push(copy);\n counts.push(n);\n } else {\n values.push(o);\n counts.push(0);\n }\n }\n return {\n values,\n counts\n };\n};\n/**\n* Exact match, so a `flatHashOrNull` collision is resolved rather than trusted.\n* `bCounts` is the cached side's key count; comparing against it avoids the\n* `Object.keys()` allocation this would otherwise make on every cache hit.\n*/\nconst flatArgsEqual = (a, b, bCounts) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n const oa = a[i];\n const ob = b[i];\n if (oa === ob) continue;\n if (oa === null || ob === null || typeof oa !== \"object\" || typeof ob !== \"object\") return false;\n if (Array.isArray(oa) !== Array.isArray(ob)) return false;\n let n = 0;\n for (const k in oa) {\n if (oa[k] !== ob[k]) return false;\n n++;\n }\n if (n !== bCounts[i]) return false;\n }\n return true;\n};\nconst memo = (fn) => {\n let buckets = /* @__PURE__ */ new Map();\n let priorBuckets = /* @__PURE__ */ new Map();\n let strings = /* @__PURE__ */ new Map();\n let priorStrings = /* @__PURE__ */ new Map();\n /**\n * One scalar argument, keyed directly.\n *\n * This is the shape of the hottest callers — `isCssProperty(prop)` runs per prop\n * per render — and a plain map lookup beats hashing, bucket scanning and\n * snapshotting for it. Distinct types stay distinct keys, so `1` and `'1'` do not\n * share an entry.\n */\n let scalars = /* @__PURE__ */ new Map();\n let priorScalars = /* @__PURE__ */ new Map();\n const scan = (bucket, args) => {\n if (bucket) for (let i = 0; i < bucket.length; i++) {\n const entry = bucket[i];\n if (flatArgsEqual(args, entry.values, entry.counts)) return entry;\n }\n };\n const get = (...args) => {\n if (args.length === 1) {\n const only = args[0];\n if (only === null || typeof only !== \"object\") {\n if (scalars.has(only)) return scalars.get(only);\n if (priorScalars.has(only)) {\n const promoted = priorScalars.get(only);\n scalars.set(only, promoted);\n return promoted;\n }\n const out = fn(only);\n scalars.set(only, out);\n if (scalars.size > MAX_ENTRIES) {\n priorScalars = scalars;\n scalars = /* @__PURE__ */ new Map();\n }\n return out;\n }\n }\n const hash = flatHashOrNull(args);\n if (hash !== null) {\n let bucket = buckets.get(hash);\n const hit = scan(bucket, args);\n if (hit) return hit.out;\n const priorHit = scan(priorBuckets.get(hash), args);\n if (priorHit) {\n if (!bucket) {\n bucket = [];\n buckets.set(hash, bucket);\n }\n bucket.push(priorHit);\n if (bucket.length > MAX_BUCKET) bucket.shift();\n return priorHit.out;\n }\n const snap = snapshotArgs(args);\n const out = fn(...args);\n if (!bucket) {\n bucket = [];\n buckets.set(hash, bucket);\n }\n bucket.push({\n values: snap.values,\n counts: snap.counts,\n out\n });\n if (bucket.length > MAX_BUCKET) bucket.shift();\n if (buckets.size > MAX_ENTRIES) {\n priorBuckets = buckets;\n buckets = /* @__PURE__ */ new Map();\n }\n return out;\n }\n const key = JSON.stringify(args);\n if (strings.has(key)) return strings.get(key);\n if (priorStrings.has(key)) {\n const promoted = priorStrings.get(key);\n strings.set(key, promoted);\n return promoted;\n }\n const out = fn(...args);\n strings.set(key, out);\n if (strings.size > MAX_ENTRIES) {\n priorStrings = strings;\n strings = /* @__PURE__ */ new Map();\n }\n return out;\n };\n return get;\n};\n//#endregion\n//#region src/merge-props.ts\nconst MERGE_OMIT = new Set([\n \"__proto__\",\n \"constructor\",\n \"prototype\"\n]);\nfunction mergeProps(...sources) {\n return sources.reduce((prev, obj) => {\n if (!obj) return prev;\n Object.keys(obj).forEach((key) => {\n if (MERGE_OMIT.has(key)) return;\n const prevValue = prev[key];\n const value = obj[key];\n if (isObject(prevValue) && isObject(value)) prev[key] = mergeProps(prevValue, value);\n else prev[key] = value;\n });\n return prev;\n }, {});\n}\n//#endregion\n//#region src/walk-object.ts\nconst isNotNullish = (element) => element != null;\nfunction walkObject(target, predicate, options = {}) {\n const { stop, getKey } = options;\n function inner(value, path = []) {\n if (isObjectOrArray(value)) {\n const result = {};\n for (const [prop, child] of Object.entries(value)) {\n const key = getKey?.(prop, child) ?? prop;\n const childPath = [...path, key];\n if (stop?.(value, childPath)) return predicate(value, path);\n const next = inner(child, childPath);\n if (isNotNullish(next)) result[key] = next;\n }\n return result;\n }\n return predicate(value, path);\n }\n return inner(target);\n}\nfunction mapObject(obj, fn) {\n if (Array.isArray(obj)) return obj.map((value) => fn(value));\n if (!isObject(obj)) return fn(obj);\n return walkObject(obj, (value) => fn(value));\n}\n//#endregion\n//#region src/normalize-style-object.ts\nfunction toResponsiveObject(values, breakpoints) {\n return values.reduce((acc, current, index) => {\n const key = breakpoints[index];\n if (current != null) acc[key] = current;\n return acc;\n }, {});\n}\n/**\n* Whether walking the object would only rebuild it.\n*\n* Normalizing does three things: it renames a shorthand to its longhand, expands a responsive\n* array into a breakpoint object, and drops nullish leaves. A flat object of plain values\n* written in longhand needs none of them, and that is most of what `css()` is handed — but it\n* still paid for a full rebuild plus a path array per key.\n*\n* Every clause has to be exact, since a false positive returns an object the walk would have\n* changed. Nullish is one of them: a leaf the walk removes must not survive, or a later merge\n* would see it override the value beneath it. The array check is another, and it is on the\n* container as well as the values — `stop` is handed the container, so an array arriving at\n* the top level becomes a breakpoint object rather than being walked into.\n*\n* `for...in` reads inherited keys the walk ignores, which is safe in the only direction it can\n* be wrong — an extra key can send this to the slow path, never past it.\n*\n* It does read every value, as `compactStyles` and the argument memo already do, so an\n* accessor prop is read once more than before. Style props are values by the time they get\n* here and reading one has no effect, but it is the reason this cannot be reordered to read\n* lazily.\n*/\nfunction needsNoNormalizing(styles, resolveShorthand) {\n if (Array.isArray(styles)) return false;\n for (const key in styles) {\n const value = styles[key];\n if (value == null || typeof value === \"object\") return false;\n if (resolveShorthand !== void 0 && resolveShorthand(key) !== key) return false;\n }\n return true;\n}\n/**\n* The result may be the argument itself rather than a fresh object, so callers have to treat\n* it as read-only. Every one of them does today: merging accumulates into its own object and\n* the two `raw()` helpers clone at the boundary.\n*/\nfunction normalizeStyleObject(styles, context, shorthand = true) {\n const { utility, conditions } = context;\n const { hasShorthand, resolveShorthand } = utility;\n if (needsNoNormalizing(styles, shorthand && hasShorthand ? resolveShorthand : void 0)) return styles;\n return walkObject(styles, (value) => {\n return Array.isArray(value) ? toResponsiveObject(value, conditions.breakpoints.keys) : value;\n }, {\n stop: (value) => Array.isArray(value),\n getKey: shorthand ? (prop) => hasShorthand ? resolveShorthand(prop) : prop : void 0\n });\n}\n//#endregion\n//#region src/classname.ts\nconst fallbackCondition = {\n shift: (v) => v,\n finalize: (v) => v,\n breakpoints: { keys: [] }\n};\nconst ENTRY_SEP = \"]___[\";\nconst COND_SEP = \"<___>\";\nfunction createCss(context) {\n const { utility, hash, grouped, conditions: conds = fallbackCondition } = context;\n const { prefix } = utility;\n const formatClassName = prefix ? (str) => str ? `${prefix}-${str}` : prefix : (str) => str || \"\";\n const hashFn = (conditions, className) => {\n if (hash) {\n const baseArray = [...conds.finalize(conditions), className];\n return formatClassName(utility.toHash(baseArray, toHash));\n }\n const finalized = conds.finalize(conditions);\n if (finalized.length === 0) return formatClassName(className);\n return [...finalized, formatClassName(className)].join(\":\");\n };\n if (grouped) return memo(({ base, ...styles } = {}) => {\n const normalizedObject = normalizeStyleObject(Object.assign(styles, base), context);\n const hashes = [];\n walkObject(normalizedObject, (value, paths) => {\n if (value == null) return;\n const [prop, ...allConditions] = conds.shift(paths);\n const conditions = filterBaseConditions(allConditions);\n const parts = [`${prop}${ENTRY_SEP}value:${value}`];\n if (conditions.length) parts.push(`cond:${conditions.join(COND_SEP)}`);\n hashes.push(parts.join(ENTRY_SEP));\n });\n if (hashes.length === 0) return \"\";\n hashes.sort();\n const groupId = hashes.join(\"|\");\n return formatClassName(utility.toHash([\"grouped\", groupId], toHash));\n });\n return memo(({ base, ...styles } = {}) => {\n const normalizedObject = normalizeStyleObject(Object.assign(styles, base), context);\n const classNames = /* @__PURE__ */ new Set();\n walkObject(normalizedObject, (value, paths) => {\n if (value == null) return;\n const important = isImportant(value);\n const [prop, ...allConditions] = conds.shift(paths);\n let className = hashFn(filterBaseConditions(allConditions), utility.transform(prop, withoutImportant(sanitize(value))).className);\n if (important) className = `${className}!`;\n classNames.add(className);\n });\n return Array.from(classNames).join(\" \");\n });\n}\n/**\n* Whether a style object carries anything `compact` would have kept.\n*\n* The question `compactStyles` asks is only ever \"is this empty once undefined values are\n* dropped\", but it used to answer it by building the compacted object and then a key array\n* for it, then throwing both away. `Object.keys` enumerates exactly what `compact`'s\n* `Object.entries` did — own, enumerable, string-keyed — so this is the same predicate\n* without the two allocations, and it stops at the first value that settles it.\n*/\nfunction hasDefinedValue(style) {\n const keys = Object.keys(style);\n for (let i = 0; i < keys.length; i++) if (style[keys[i]] !== void 0) return true;\n return false;\n}\nfunction compactStyles(...styles) {\n return styles.flat().filter((style) => isObject(style) && hasDefinedValue(style));\n}\nfunction createMergeCss(context) {\n function resolve(styles) {\n const allStyles = compactStyles(...styles);\n if (allStyles.length === 1) return allStyles;\n return allStyles.map((style) => normalizeStyleObject(style, context));\n }\n function mergeCss(...styles) {\n return mergeProps(...resolve(styles));\n }\n function assignCss(...styles) {\n return Object.assign({}, ...resolve(styles));\n }\n return {\n mergeCss: memo(mergeCss),\n assignCss\n };\n}\n//#endregion\n//#region src/clone-styles.ts\nconst OMIT = new Set([\n \"__proto__\",\n \"constructor\",\n \"prototype\"\n]);\n/**\n* Independent copy of a style object, nested condition blocks included.\n*\n* Merged style objects are cached, so anything handed to user code has to be\n* copied first: a caller mutating what it received would otherwise change what\n* every later caller reads back. `css.raw()` and `cva.raw()` are those boundaries.\n*\n* Kept separate from `mergeProps` deliberately. Merging is on the hot path — it\n* runs on every `css()` cache miss and on every render of a pattern component\n* under `jsxStyleProps: 'minimal'` — and copying there charges every caller for a\n* guarantee only the two `raw()` helpers need. Measured on a realistic style\n* object (5 base properties, 4 condition blocks) that was roughly twice the cost\n* of merging alone.\n*/\nfunction cloneStyles(styles) {\n if (Array.isArray(styles)) return styles.map((value) => cloneStyles(value));\n if (!isObject(styles)) return styles;\n const out = {};\n for (const key of Object.keys(styles)) {\n if (OMIT.has(key)) continue;\n out[key] = cloneStyles(styles[key]);\n }\n return out;\n}\n//#endregion\n//#region src/compact.ts\nfunction compact(value) {\n return Object.fromEntries(Object.entries(value ?? {}).filter(([_, value]) => value !== void 0));\n}\n//#endregion\n//#region src/leaf-class.ts\n/**\n* The class a single dynamic style leaf resolves to, given the prefix its property and\n* condition path produce.\n*\n* ## Why this can exist at all\n*\n* `css()` builds a class from the value alone — `utility.transform` is string\n* construction over a static map, and nothing consults which rules were actually emitted.\n* So `css({ color: tone })` already returns `c_<tone>` for a value the extractor never\n* saw, with no CSS behind it. Reproducing that string here cannot be less correct than\n* the call it replaces; it just skips the object literal, the merge and the memo.\n*\n* ## Why it is not a template literal\n*\n* Three shapes do not reduce to `prefix + value`, and all three return `undefined` so the\n* caller runs `css()` instead:\n*\n* - An array is expanded to a responsive object by `normalizeStyleObject`, so it produces\n* one class per breakpoint rather than one class.\n* - An object is a condition block, walked into for the same reason.\n* - `null` and `undefined` are skipped by the walk entirely, which is an empty string\n* rather than a class — that one is answered here, since it needs no `css()` call.\n*\n* ## Why the character scan\n*\n* The remaining work — collapsing whitespace, stripping `!important`, turning spaces into\n* underscores — is three regexes, and paying them per call makes this *slower* than a\n* memo hit. Almost no token value contains whitespace or `!`, so one scan for the\n* characters that make any of it necessary sends the common value straight to a\n* concatenation. A false positive only costs the slow path, so the scan errs wide.\n*/\nfunction leafClass(prefix, value) {\n if (value == null) return \"\";\n const type = typeof value;\n if (type === \"number\" || type === \"boolean\") return `${prefix}${value}`;\n if (type !== \"string\") return void 0;\n const str = value;\n for (let index = 0; index < str.length; index++) {\n const code = str.charCodeAt(index);\n if (code <= 33 || code === 160 || code === 5760 || code >= 8192) return slowLeaf(prefix, str);\n }\n return `${prefix}${str}`;\n}\n/** The full pipeline `createCss` runs, for a value that needs it. */\nfunction slowLeaf(prefix, value) {\n const important = isImportant(value);\n const className = `${prefix}${withoutSpace(withoutImportant(sanitize(value)))}`;\n return important ? `${className}!` : className;\n}\n//#endregion\n//#region src/hypenate-property.ts\nconst wordRegex = /([A-Z])/g;\nconst msRegex = /^ms-/;\nconst hypenateProperty = memo((property) => {\n if (property.startsWith(\"--\")) return property;\n return property.replace(wordRegex, \"-$1\").replace(msRegex, \"-ms-\").toLowerCase();\n});\n//#endregion\n//#region src/is-css-function.ts\nconst fnRegExp = new RegExp(`^(${[\n \"min\",\n \"max\",\n \"clamp\",\n \"calc\"\n].join(\"|\")})\\\\(.*\\\\)`);\nconst isCssFunction = (v) => typeof v === \"string\" && fnRegExp.test(v);\n//#endregion\n//#region src/is-css-unit.ts\nconst lengthUnitsPattern = `(?:${\"cm,mm,Q,in,pc,pt,px,em,ex,ch,rem,lh,rlh,vw,vh,vmin,vmax,vb,vi,svw,svh,lvw,lvh,dvw,dvh,cqw,cqh,cqi,cqb,cqmin,cqmax,%\".split(\",\").join(\"|\")})`;\nconst lengthRegExp = new RegExp(`^[+-]?[0-9]*.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`);\nconst isCssUnit = (v) => typeof v === \"string\" && lengthRegExp.test(v);\n//#endregion\n//#region src/is-css-var.ts\nconst isCssVar = (v) => typeof v === \"string\" && /^var\\(--.+\\)$/.test(v);\n//#endregion\n//#region src/pattern-fns.ts\nconst patternFns = {\n map: mapObject,\n isCssFunction,\n isCssVar,\n isCssUnit\n};\nconst getPatternStyles = (pattern, styles) => {\n if (!pattern?.defaultValues) return styles;\n const defaults = typeof pattern.defaultValues === \"function\" ? pattern.defaultValues(styles) : pattern.defaultValues;\n return Object.assign({}, defaults, compact(styles));\n};\n//#endregion\n//#region src/slot.ts\nconst getSlotRecipes = (recipe = {}) => {\n const init = (slot) => ({\n className: [recipe.className, slot].filter(Boolean).join(\"__\"),\n base: recipe.base?.[slot] ?? {},\n variants: {},\n defaultVariants: recipe.defaultVariants ?? {},\n compoundVariants: recipe.compoundVariants ? getSlotCompoundVariant(recipe.compoundVariants, slot) : []\n });\n const recipeParts = (recipe.slots ?? []).map((slot) => [slot, init(slot)]);\n for (const [variantsKey, variantsSpec] of Object.entries(recipe.variants ?? {})) for (const [variantKey, variantSpec] of Object.entries(variantsSpec)) recipeParts.forEach(([slot, slotRecipe]) => {\n slotRecipe.variants[variantsKey] ??= {};\n slotRecipe.variants[variantsKey][variantKey] = variantSpec[slot] ?? {};\n });\n return Object.fromEntries(recipeParts);\n};\nconst getSlotCompoundVariant = (compoundVariants, slotName) => compoundVariants.filter((compoundVariant) => compoundVariant.css[slotName]).map((compoundVariant) => ({\n ...compoundVariant,\n css: compoundVariant.css[slotName]\n}));\n//#endregion\n//#region src/split-props.ts\n/**\n* Deal a props object into one bucket per key group, plus a final bucket for the rest.\n* A key goes to the first group that claims it.\n*\n* ## Why the descriptor is read per key rather than in bulk\n*\n* This used to call `Object.getOwnPropertyDescriptors` for the whole object and\n* `defineProperty` for every key it moved. Copying plain values instead is 2.4–2.9x faster\n* on the shapes that allow it, but it is only correct where props are data — and they are\n* not always. Solid compiles props to accessors, so reading one eagerly runs whatever it\n* wraps: splitting a component's props would construct its children before the surrounding\n* provider exists.\n*\n* So the descriptor is fetched per key, and the value path is taken only when it changes\n* nothing observable. An accessor keeps its laziness, a non-enumerable key keeps its\n* invisibility, and `__proto__` is defined rather than assigned so it stays an own\n* property instead of reaching the prototype setter.\n*\n* The one thing the value path drops is `writable`/`configurable`, so a bucket key taken\n* from frozen props is writable where it used to be frozen. Nothing here relies on that,\n* and preserving it would mean `defineProperty` on the common path — the cost this exists\n* to avoid. Keys that take the descriptor path keep theirs, so a bucket can be\n* inconsistent in that one respect.\n*\n* Key order within a bucket is preserved exactly. It is not cosmetic: `cva` merges\n* variant props in iteration order, and the parser reads the rest bucket as the style\n* props it encodes, so order reaches the emitted CSS.\n*/\nfunction splitProps(props, ...keys) {\n const allKeys = Object.getOwnPropertyNames(props);\n const own = new Set(allKeys);\n const taken = /* @__PURE__ */ new Set();\n const split = (group) => {\n const clone = {};\n for (let i = 0; i < group.length; i++) {\n const key = group[i];\n if (taken.has(key) || !own.has(key)) continue;\n const descriptor = Object.getOwnPropertyDescriptor(props, key);\n if (!descriptor) continue;\n if (\"get\" in descriptor || \"set\" in descriptor || !descriptor.enumerable || key === \"__proto__\") Object.defineProperty(clone, key, descriptor);\n else clone[key] = descriptor.value;\n taken.add(key);\n }\n return clone;\n };\n /**\n * The predicate is called with the key alone.\n *\n * Handing it to `filter` passes `(key, index, allKeys)`. A one-parameter predicate cannot\n * see the extras, but a memoized one reads its whole argument list — and the predicates\n * that arrive here are memoized, `isCssProperty` among them. So the memo hashed the entire\n * key array once per prop, and keyed its cache on it: two elements with different prop sets\n * shared no entry even for the same prop name.\n *\n * Worth ~9.7x on that path, and nothing at all on a plain predicate — which is why the\n * bench below it needs a memoized case to see this at all.\n *\n * A loop rather than `filter((k) => key(k))` because the wrapper allocates a closure per\n * group. The two measure the same to within noise; the loop just does not need one.\n */\n const matching = (predicate) => {\n const group = [];\n for (let i = 0; i < allKeys.length; i++) {\n const key = allKeys[i];\n if (predicate(key)) group.push(key);\n }\n return group;\n };\n return keys.map((key) => split(Array.isArray(key) ? key : matching(key))).concat(split(allKeys));\n}\n//#endregion\n//#region src/uniq.ts\nconst uniq = (...items) => {\n const set = items.reduce((acc, currItems) => {\n if (currItems) currItems.forEach((item) => acc.add(item));\n return acc;\n }, /* @__PURE__ */ new Set([]));\n return Array.from(set);\n};\n//#endregion\nexport { cloneStyles, compact, createCss, createMergeCss, filterBaseConditions, getPatternStyles, getSlotCompoundVariant, getSlotRecipes, hypenateProperty, isBaseCondition, isObject, leafClass, mapObject, memo, mergeProps, patternFns, splitProps, toHash, uniq, walkObject, withoutSpace };\n";
650
- //#endregion
651
- //#region src/artifacts/generated/normalize-html.mjs.json
652
- var content$9 = "//#region src/normalize-html.ts\nconst htmlProps = [\n \"htmlSize\",\n \"htmlTranslate\",\n \"htmlWidth\",\n \"htmlHeight\"\n];\nfunction convert(key) {\n return htmlProps.includes(key) ? key.replace(\"html\", \"\").toLowerCase() : key;\n}\nfunction normalizeHTMLProps(props) {\n return Object.fromEntries(Object.entries(props).map(([key, value]) => [convert(key), value]));\n}\nnormalizeHTMLProps.keys = htmlProps;\n//#endregion\nexport { normalizeHTMLProps };\n";
471
+ var content$8 = "//#region src/assert.ts\nfunction isObject(value) {\n return typeof value === \"object\" && value != null && !Array.isArray(value);\n}\nconst isObjectOrArray = (obj) => typeof obj === \"object\" && obj !== null;\n//#endregion\n//#region src/condition.ts\nconst isBaseCondition = (v) => v === \"base\";\nfunction filterBaseConditions(c) {\n return c.slice().filter((v) => !isBaseCondition(v));\n}\n//#endregion\n//#region src/hash.ts\nfunction toChar(code) {\n return String.fromCharCode(code + (code > 25 ? 39 : 97));\n}\nfunction toName(code) {\n let name = \"\";\n let x;\n for (x = Math.abs(code); x > 52; x = x / 52 | 0) name = toChar(x % 52) + name;\n return toChar(x % 52) + name;\n}\nfunction toPhash(h, x) {\n let i = x.length;\n while (i) h = h * 33 ^ x.charCodeAt(--i);\n return h;\n}\nfunction toHash(value) {\n return toName(toPhash(5381, value) >>> 0);\n}\n//#endregion\n//#region src/important.ts\nconst importantRegex = /\\s*!(important)?/i;\nconst whitespaceRegex = /\\s/;\n/**\n* Collapse every run of whitespace to a single space, which is what the class name is\n* built from. Exported because `leafClass` has to reproduce this exact pipeline, and a\n* second copy of it would be free to drift from the one `createCss` runs.\n*/\nfunction sanitize(value) {\n if (typeof value !== \"string\") return value;\n const collapsed = whitespaceRegex.test(value) ? value.replaceAll(/[\\n\\s]+/g, \" \") : value;\n return collapsed.includes(\"\\0\") ? collapsed.replaceAll(\"\\0\", \"\") : collapsed;\n}\nfunction isImportant(value) {\n if (typeof value !== \"string\") return false;\n return value.includes(\"!\") && importantRegex.test(value);\n}\nfunction withoutImportant(value) {\n if (typeof value !== \"string\") return value;\n if (!value.includes(\"!\")) return value.trim();\n return value.replace(importantRegex, \"\").trim();\n}\nfunction withoutSpace(str) {\n if (typeof str !== \"string\") return str;\n return str.includes(\" \") ? str.replaceAll(\" \", \"_\") : str;\n}\n//#endregion\n//#region src/memo.ts\n/**\n* Bounded argument memo used by the generated runtime (`css`, patterns, `cva`, recipes).\n*\n* Two regimes, picked per call:\n*\n* - Arguments that are flat (objects of primitives) take a cheap structural hash\n* and are confirmed with an exact comparison, so a hash collision can never\n* serve the wrong result. This is the shape `css({ ... })` has.\n* - Anything nested falls back to `JSON.stringify`, which V8 does faster than a\n* JS walk.\n*\n* The second point is the counter-intuitive one, and it has been measured rather\n* than assumed. Extending the structural hash to recurse — so nested styles could\n* take the fast path too — is *slower*, because it trades one native serialization\n* for two JS walks (hash, then the deep equality that confirms it). Over 10k\n* iterations per shape:\n*\n* shape stringify recursive hash + deep equal\n* flat 1.06ms 2.09ms\n* _hover 1.00ms 2.16ms\n* responsive 1.23ms 2.15ms\n* realistic 2.32ms 5.84ms\n* nested 3 deep 1.22ms 2.35ms\n*\n* So a nested `css()` call costing several times a flat one is not a defect here.\n* It is the floor for a value-keyed memo in JS, and the way to avoid it is to not\n* make the call — see the build-time fold in `@bamboocss/vite`.\n*\n* Both regimes key on *values*, never on object identity: mutating a style object\n* between calls changes its hash, so the next call misses and recomputes rather\n* than serving a stale class. Keying nested arguments on the identity of the inner\n* objects would skip serialization entirely, but it cannot detect a mutation, and\n* \"same object, different contents\" is exactly what a style object built per render\n* looks like.\n*\n* Both caches are bounded. An unbounded memo is a leak in any long-lived process\n* (SSR), where the set of distinct style objects grows without limit.\n*/\n/**\n* Distinct hashes held per memoized function before the cache rotates.\n*\n* This bounds *buckets*, not entries: a bucket keeps up to `MAX_BUCKET` colliding\n* argument lists, so the ceiling is `MAX_ENTRIES * MAX_BUCKET` live entries, and\n* twice that across both generations, since the previous one is retained until the\n* next rotation. Collisions are rare in practice, so the realistic figure is close\n* to `MAX_ENTRIES` — but the worst case is what matters when sizing a long-lived\n* process, so state it plainly.\n*\n* Rotation beats evicting the oldest key: single-key eviction is worst-case for a\n* working set that cycles, because it drops exactly the entry about to be needed.\n* Measured on a cycling set of 20k styles, one-at-a-time eviction cost ~719ns/op\n* against ~189ns unbounded, while rotation holds ~274ns. On realistic skewed\n* access rotation is at or below the unbounded cost.\n*/\nconst MAX_ENTRIES = 1e3;\n/** Entries kept per hash bucket, to bound the cost of a collision scan. */\nconst MAX_BUCKET = 8;\n/**\n* DJB2 over the arguments' own keys and primitive values.\n* Returns `null` for anything nested, which routes the call to the string key.\n*/\nconst flatHashOrNull = (args) => {\n let h = 5381;\n for (let a = 0; a < args.length; a++) {\n const obj = args[a];\n if (obj === null || typeof obj !== \"object\") {\n const t = typeof obj;\n if (t === \"string\") for (let i = 0; i < obj.length; i++) h = h * 33 ^ obj.charCodeAt(i);\n else if (t === \"number\") h = h * 33 ^ (obj | 0);\n else if (t === \"boolean\") h = h * 33 ^ (obj ? 991 : 997);\n else h = h * 33 ^ 3;\n continue;\n }\n if (Array.isArray(obj)) h = h * 33 ^ 7;\n else {\n const proto = Object.getPrototypeOf(obj);\n if (proto !== Object.prototype && proto !== null) return null;\n }\n for (const k in obj) {\n const v = obj[k];\n const tv = typeof v;\n if (v !== null && tv === \"object\") return null;\n for (let i = 0; i < k.length; i++) h = h * 33 ^ k.charCodeAt(i);\n if (tv === \"string\") for (let i = 0; i < v.length; i++) h = h * 33 ^ v.charCodeAt(i);\n else if (tv === \"number\") h = h * 33 ^ (v | 0);\n else if (tv === \"boolean\") h = h * 33 ^ (v ? 991 : 997);\n else h = h * 33 ^ 2;\n }\n }\n return h >>> 0;\n};\n/**\n* Value snapshot of the arguments, taken once at insert.\n*\n* The cache must not hold the caller's objects: a style object can capture a much\n* larger graph, and keeping it alive until the cache rotates changes GC behaviour\n* for code that never asked to be cached. Only the flat path reaches here, so a\n* shallow copy contains primitives only and retains nothing.\n*\n* Comparing against a copy also removes the last way a mutation could be missed.\n* Were the caller's own object stored, `oa === ob` would short-circuit the value\n* comparison, and a mutation that happened to preserve the hash would return the\n* stale entry. Against a copy that check can only ever be true for equal\n* primitives.\n*/\nconst snapshotArgs = (args) => {\n const values = [];\n const counts = [];\n for (let i = 0; i < args.length; i++) {\n const o = args[i];\n if (o !== null && typeof o === \"object\") {\n const copy = Array.isArray(o) ? [] : {};\n let n = 0;\n for (const k in o) {\n copy[k] = o[k];\n n++;\n }\n values.push(copy);\n counts.push(n);\n } else {\n values.push(o);\n counts.push(0);\n }\n }\n return {\n values,\n counts\n };\n};\n/**\n* Exact match, so a `flatHashOrNull` collision is resolved rather than trusted.\n* `bCounts` is the cached side's key count; comparing against it avoids the\n* `Object.keys()` allocation this would otherwise make on every cache hit.\n*/\nconst flatArgsEqual = (a, b, bCounts) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n const oa = a[i];\n const ob = b[i];\n if (oa === ob) continue;\n if (oa === null || ob === null || typeof oa !== \"object\" || typeof ob !== \"object\") return false;\n if (Array.isArray(oa) !== Array.isArray(ob)) return false;\n let n = 0;\n for (const k in oa) {\n if (oa[k] !== ob[k]) return false;\n n++;\n }\n if (n !== bCounts[i]) return false;\n }\n return true;\n};\nconst memo = (fn) => {\n let buckets = /* @__PURE__ */ new Map();\n let priorBuckets = /* @__PURE__ */ new Map();\n let strings = /* @__PURE__ */ new Map();\n let priorStrings = /* @__PURE__ */ new Map();\n /**\n * One scalar argument, keyed directly.\n *\n * This is the shape of the hottest callers — `isCssProperty(prop)` runs per prop\n * per render — and a plain map lookup beats hashing, bucket scanning and\n * snapshotting for it. Distinct types stay distinct keys, so `1` and `'1'` do not\n * share an entry.\n */\n let scalars = /* @__PURE__ */ new Map();\n let priorScalars = /* @__PURE__ */ new Map();\n const scan = (bucket, args) => {\n if (bucket) for (let i = 0; i < bucket.length; i++) {\n const entry = bucket[i];\n if (flatArgsEqual(args, entry.values, entry.counts)) return entry;\n }\n };\n const get = (...args) => {\n if (args.length === 1) {\n const only = args[0];\n if (only === null || typeof only !== \"object\") {\n if (scalars.has(only)) return scalars.get(only);\n if (priorScalars.has(only)) {\n const promoted = priorScalars.get(only);\n scalars.set(only, promoted);\n return promoted;\n }\n const out = fn(only);\n scalars.set(only, out);\n if (scalars.size > MAX_ENTRIES) {\n priorScalars = scalars;\n scalars = /* @__PURE__ */ new Map();\n }\n return out;\n }\n }\n const hash = flatHashOrNull(args);\n if (hash !== null) {\n let bucket = buckets.get(hash);\n const hit = scan(bucket, args);\n if (hit) return hit.out;\n const priorHit = scan(priorBuckets.get(hash), args);\n if (priorHit) {\n if (!bucket) {\n bucket = [];\n buckets.set(hash, bucket);\n }\n bucket.push(priorHit);\n if (bucket.length > MAX_BUCKET) bucket.shift();\n return priorHit.out;\n }\n const snap = snapshotArgs(args);\n const out = fn(...args);\n if (!bucket) {\n bucket = [];\n buckets.set(hash, bucket);\n }\n bucket.push({\n values: snap.values,\n counts: snap.counts,\n out\n });\n if (bucket.length > MAX_BUCKET) bucket.shift();\n if (buckets.size > MAX_ENTRIES) {\n priorBuckets = buckets;\n buckets = /* @__PURE__ */ new Map();\n }\n return out;\n }\n const key = JSON.stringify(args);\n if (strings.has(key)) return strings.get(key);\n if (priorStrings.has(key)) {\n const promoted = priorStrings.get(key);\n strings.set(key, promoted);\n return promoted;\n }\n const out = fn(...args);\n strings.set(key, out);\n if (strings.size > MAX_ENTRIES) {\n priorStrings = strings;\n strings = /* @__PURE__ */ new Map();\n }\n return out;\n };\n return get;\n};\n//#endregion\n//#region src/merge-props.ts\nconst MERGE_OMIT = new Set([\n \"__proto__\",\n \"constructor\",\n \"prototype\"\n]);\nfunction mergeProps(...sources) {\n return sources.reduce((prev, obj) => {\n if (!obj) return prev;\n Object.keys(obj).forEach((key) => {\n if (MERGE_OMIT.has(key)) return;\n const prevValue = prev[key];\n const value = obj[key];\n if (isObject(prevValue) && isObject(value)) prev[key] = mergeProps(prevValue, value);\n else prev[key] = value;\n });\n return prev;\n }, {});\n}\n//#endregion\n//#region src/walk-object.ts\nconst isNotNullish = (element) => element != null;\nfunction walkObject(target, predicate, options = {}) {\n const { stop, getKey } = options;\n function inner(value, path = []) {\n if (isObjectOrArray(value)) {\n const result = {};\n for (const [prop, child] of Object.entries(value)) {\n const key = getKey?.(prop, child) ?? prop;\n const childPath = [...path, key];\n if (stop?.(value, childPath)) return predicate(value, path);\n const next = inner(child, childPath);\n if (isNotNullish(next)) result[key] = next;\n }\n return result;\n }\n return predicate(value, path);\n }\n return inner(target);\n}\nfunction mapObject(obj, fn) {\n if (Array.isArray(obj)) return obj.map((value) => fn(value));\n if (!isObject(obj)) return fn(obj);\n return walkObject(obj, (value) => fn(value));\n}\n//#endregion\n//#region src/normalize-style-object.ts\nfunction toResponsiveObject(values, breakpoints) {\n return values.reduce((acc, current, index) => {\n const key = breakpoints[index];\n if (current != null) acc[key] = current;\n return acc;\n }, {});\n}\n/**\n* Whether walking the object would only rebuild it.\n*\n* Normalizing does three things: it renames a shorthand to its longhand, expands a responsive\n* array into a breakpoint object, and drops nullish leaves. A flat object of plain values\n* written in longhand needs none of them, and that is most of what `css()` is handed — but it\n* still paid for a full rebuild plus a path array per key.\n*\n* Every clause has to be exact, since a false positive returns an object the walk would have\n* changed. Nullish is one of them: a leaf the walk removes must not survive, or a later merge\n* would see it override the value beneath it. The array check is another, and it is on the\n* container as well as the values — `stop` is handed the container, so an array arriving at\n* the top level becomes a breakpoint object rather than being walked into.\n*\n* `for...in` reads inherited keys the walk ignores, which is safe in the only direction it can\n* be wrong — an extra key can send this to the slow path, never past it.\n*\n* It does read every value, as `compactStyles` and the argument memo already do, so an\n* accessor prop is read once more than before. Style props are values by the time they get\n* here and reading one has no effect, but it is the reason this cannot be reordered to read\n* lazily.\n*/\nfunction needsNoNormalizing(styles, resolveShorthand) {\n if (Array.isArray(styles)) return false;\n for (const key in styles) {\n const value = styles[key];\n if (value == null || typeof value === \"object\") return false;\n if (resolveShorthand !== void 0 && resolveShorthand(key) !== key) return false;\n }\n return true;\n}\n/**\n* The result may be the argument itself rather than a fresh object, so callers have to treat\n* it as read-only. Every one of them does today: merging accumulates into its own object and\n* the two `raw()` helpers clone at the boundary.\n*/\nfunction normalizeStyleObject(styles, context, shorthand = true) {\n const { utility, conditions } = context;\n const { hasShorthand, resolveShorthand } = utility;\n if (needsNoNormalizing(styles, shorthand && hasShorthand ? resolveShorthand : void 0)) return styles;\n return walkObject(styles, (value) => {\n return Array.isArray(value) ? toResponsiveObject(value, conditions.breakpoints.keys) : value;\n }, {\n stop: (value) => Array.isArray(value),\n getKey: shorthand ? (prop) => hasShorthand ? resolveShorthand(prop) : prop : void 0\n });\n}\n//#endregion\n//#region src/classname.ts\nconst fallbackCondition = {\n shift: (v) => v,\n finalize: (v) => v,\n breakpoints: { keys: [] }\n};\nconst ENTRY_SEP = \"]___[\";\nconst COND_SEP = \"<___>\";\n/**\n* The class a whole grouped `css()` call resolves to, given its group id.\n*\n* Shared with `StyleDecoder.collectGrouped` on purpose: both sides name this class, and\n* deriving it twice is what let `hash.className` re-hash on the build side only, leaving\n* every grouped element carrying a class no rule was emitted for.\n*\n* A group id already digests every declaration in the call, so it is hashed exactly once\n* and `hash.className` is deliberately not consulted — that option shortens *utility*\n* class names, and a grouped class is not one. The build `esc()`s the result for a\n* selector; the runtime does not. That asymmetry belongs to the callers.\n*/\nfunction groupClassName(groupId, toHashFn, formatClassName) {\n return formatClassName(toHashFn([\"grouped\", groupId], toHash));\n}\nfunction createCss(context) {\n const { utility, hash, grouped, conditions: conds = fallbackCondition } = context;\n const { prefix } = utility;\n const formatClassName = prefix ? (str) => str ? `${prefix}-${str}` : prefix : (str) => str || \"\";\n const hashFn = (conditions, className) => {\n if (hash) {\n const baseArray = [...conds.finalize(conditions), className];\n return formatClassName(utility.toHash(baseArray, toHash));\n }\n const finalized = conds.finalize(conditions);\n if (finalized.length === 0) return formatClassName(className);\n return [...finalized, formatClassName(className)].join(\":\");\n };\n /** One declaration, kept only when there is a fallback that might need to name it. */\n const atomicName = (prop, value, conditions) => {\n const important = isImportant(value);\n const className = hashFn(conditions, utility.transform(prop, withoutImportant(sanitize(value))).className);\n return important ? `${className}!` : className;\n };\n if (grouped) {\n const { knownGroups } = context;\n return memo(({ base, ...styles } = {}) => {\n const normalizedObject = normalizeStyleObject(Object.assign(styles, base), context);\n const hashes = [];\n const leaves = knownGroups ? [] : void 0;\n walkObject(normalizedObject, (value, paths) => {\n if (value == null) return;\n const [prop, ...allConditions] = conds.shift(paths);\n const conditions = filterBaseConditions(allConditions);\n const parts = [`${prop}${ENTRY_SEP}value:${value}`];\n if (conditions.length) parts.push(`cond:${conditions.join(COND_SEP)}`);\n hashes.push(parts.join(ENTRY_SEP));\n leaves?.push([\n prop,\n value,\n conditions\n ]);\n });\n if (hashes.length === 0) return \"\";\n hashes.sort();\n const className = groupClassName(hashes.join(\"|\"), utility.toHash, formatClassName);\n if (!leaves || knownGroups.has(className)) return className;\n const classNames = new Set([className]);\n for (const [prop, value, conditions] of leaves) classNames.add(atomicName(prop, value, conditions));\n return Array.from(classNames).join(\" \");\n });\n }\n return memo(({ base, ...styles } = {}) => {\n const normalizedObject = normalizeStyleObject(Object.assign(styles, base), context);\n const classNames = /* @__PURE__ */ new Set();\n walkObject(normalizedObject, (value, paths) => {\n if (value == null) return;\n const [prop, ...allConditions] = conds.shift(paths);\n classNames.add(atomicName(prop, value, filterBaseConditions(allConditions)));\n });\n return Array.from(classNames).join(\" \");\n });\n}\n/**\n* Whether a style object carries anything `compact` would have kept.\n*\n* The question `compactStyles` asks is only ever \"is this empty once undefined values are\n* dropped\", but it used to answer it by building the compacted object and then a key array\n* for it, then throwing both away. `Object.keys` enumerates exactly what `compact`'s\n* `Object.entries` did — own, enumerable, string-keyed — so this is the same predicate\n* without the two allocations, and it stops at the first value that settles it.\n*/\nfunction hasDefinedValue(style) {\n const keys = Object.keys(style);\n for (let i = 0; i < keys.length; i++) if (style[keys[i]] !== void 0) return true;\n return false;\n}\nfunction compactStyles(...styles) {\n return styles.flat().filter((style) => isObject(style) && hasDefinedValue(style));\n}\nfunction createMergeCss(context) {\n function resolve(styles) {\n const allStyles = compactStyles(...styles);\n if (allStyles.length === 1) return allStyles;\n return allStyles.map((style) => normalizeStyleObject(style, context));\n }\n function mergeCss(...styles) {\n return mergeProps(...resolve(styles));\n }\n function assignCss(...styles) {\n return Object.assign({}, ...resolve(styles));\n }\n return {\n mergeCss: memo(mergeCss),\n assignCss\n };\n}\n//#endregion\n//#region src/clone-styles.ts\nconst OMIT = new Set([\n \"__proto__\",\n \"constructor\",\n \"prototype\"\n]);\n/**\n* Independent copy of a style object, nested condition blocks included.\n*\n* Merged style objects are cached, so anything handed to user code has to be\n* copied first: a caller mutating what it received would otherwise change what\n* every later caller reads back. `css.raw()` and `cva.raw()` are those boundaries.\n*\n* Kept separate from `mergeProps` deliberately. Merging is on the hot path — it\n* runs on every `css()` cache miss and on every render of a pattern component\n* under `jsxStyleProps: 'minimal'` — and copying there charges every caller for a\n* guarantee only the two `raw()` helpers need. Measured on a realistic style\n* object (5 base properties, 4 condition blocks) that was roughly twice the cost\n* of merging alone.\n*/\nfunction cloneStyles(styles) {\n if (Array.isArray(styles)) return styles.map((value) => cloneStyles(value));\n if (!isObject(styles)) return styles;\n const out = {};\n for (const key of Object.keys(styles)) {\n if (OMIT.has(key)) continue;\n out[key] = cloneStyles(styles[key]);\n }\n return out;\n}\n//#endregion\n//#region src/compact.ts\nfunction compact(value) {\n return Object.fromEntries(Object.entries(value ?? {}).filter(([_, value]) => value !== void 0));\n}\n//#endregion\n//#region src/leaf-class.ts\n/**\n* The class a single dynamic style leaf resolves to, given the prefix its property and\n* condition path produce.\n*\n* ## Why this can exist at all\n*\n* `css()` builds a class from the value alone — `utility.transform` is string\n* construction over a static map, and nothing consults which rules were actually emitted.\n* So `css({ color: tone })` already returns `c_<tone>` for a value the extractor never\n* saw, with no CSS behind it. Reproducing that string here cannot be less correct than\n* the call it replaces; it just skips the object literal, the merge and the memo.\n*\n* ## Why it is not a template literal\n*\n* Three shapes do not reduce to `prefix + value`, and all three return `undefined` so the\n* caller runs `css()` instead:\n*\n* - An array is expanded to a responsive object by `normalizeStyleObject`, so it produces\n* one class per breakpoint rather than one class.\n* - An object is a condition block, walked into for the same reason.\n* - `null` and `undefined` are skipped by the walk entirely, which is an empty string\n* rather than a class — that one is answered here, since it needs no `css()` call.\n*\n* ## Why the character scan\n*\n* The remaining work — collapsing whitespace, stripping `!important`, turning spaces into\n* underscores — is three regexes, and paying them per call makes this *slower* than a\n* memo hit. Almost no token value contains whitespace or `!`, so one scan for the\n* characters that make any of it necessary sends the common value straight to a\n* concatenation. A false positive only costs the slow path, so the scan errs wide.\n*/\nfunction leafClass(prefix, value) {\n if (value == null) return \"\";\n const type = typeof value;\n if (type === \"number\" || type === \"boolean\") return `${prefix}${value}`;\n if (type !== \"string\") return void 0;\n const str = value;\n for (let index = 0; index < str.length; index++) {\n const code = str.charCodeAt(index);\n if (code <= 33 || code === 160 || code === 5760 || code >= 8192) return slowLeaf(prefix, str);\n }\n return `${prefix}${str}`;\n}\n/** The full pipeline `createCss` runs, for a value that needs it. */\nfunction slowLeaf(prefix, value) {\n const important = isImportant(value);\n const className = `${prefix}${withoutSpace(withoutImportant(sanitize(value)))}`;\n return important ? `${className}!` : className;\n}\n//#endregion\n//#region src/hypenate-property.ts\nconst wordRegex = /([A-Z])/g;\nconst msRegex = /^ms-/;\nconst hypenateProperty = memo((property) => {\n if (property.startsWith(\"--\")) return property;\n return property.replace(wordRegex, \"-$1\").replace(msRegex, \"-ms-\").toLowerCase();\n});\n//#endregion\n//#region src/recipe-identity.ts\n/** The fields that decide what CSS a recipe produces. Anything else is metadata. */\nconst STYLE_FIELDS = [\n \"base\",\n \"variants\",\n \"compoundVariants\",\n \"defaultVariants\"\n];\n/**\n* A serialization that depends on the config's *content* and not on how it was written.\n*\n* Object keys are sorted, so reordering two variants in the source does not rename every\n* class the recipe emits. Arrays keep their order, because `compoundVariants` is precedence\n* ordered and two orderings are two different recipes.\n*\n* A function serializes to `null` rather than to its source. `JSON.stringify` already drops\n* them, and stringifying instead would key the name on whether the bundle was minified —\n* the same build-dependent divergence that `cx` was changed to avoid. Nothing that survives\n* static extraction is a function, so there is no real config this loses information about.\n*/\nconst stable = (value) => {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\";\n if (Array.isArray(value)) return `[${value.map(stable).join(\",\")}]`;\n const source = value;\n return `{${Object.keys(source).sort().map((key) => `${JSON.stringify(key)}:${stable(source[key])}`).join(\",\")}}`;\n};\n/**\n* The name an inline `cva`/`sva` emits its classes under — `button--size_sm`, where this\n* returns the `button`.\n*\n* A config recipe gets its name from the key it is declared under. An inline one has no\n* such key, and the two places that need the name never meet: the build derives it while\n* emitting the stylesheet, the runtime derives it again in the browser. So it has to come\n* from something both of them see, which leaves the config object itself.\n*\n* Deriving it from the *binding* — `const button = cva(...)` — was the obvious alternative\n* and does not work. Only the build can see that binding; handing it to the runtime means\n* rewriting the call, and then a pipeline without that transform names classes differently\n* from one with it. An optional `className` gets the same readable output with none of\n* that, because it travels inside the config to both sides.\n*\n* `className` is the field a config recipe already names itself with, and it means the same\n* thing here — the prefix every class the recipe emits is built from. An inline recipe that\n* declares one is indistinguishable in the stylesheet from a recipe declared in config.\n*/\nconst getRecipeIdentity = (config, prefix = \"cva\") => {\n const declared = config?.className;\n if (typeof declared === \"string\" && declared) return declared;\n const styles = {};\n for (const field of STYLE_FIELDS) {\n const value = config?.[field];\n if (value !== void 0) styles[field] = value;\n }\n return `${prefix}_${toHash(stable(styles))}`;\n};\n/**\n* The classes a recipe puts on an element: its own, plus one per selected variant.\n*\n* Lives here rather than in the generated `cva` because the build has to be able to check\n* it. `checkNamingAgreement` derives class names both ways and compares them, and it can\n* only do that against the code the browser actually runs — a second implementation written\n* to match would agree with itself and prove nothing.\n*\n* Compound variants are absent by design. Their rule selects on the variant classes already\n* in this list, so it applies without a class of its own.\n*/\nconst getRecipeClassNames = (name, variants, selection, separator = \"_\", format = (className) => className) => {\n let result = format(name);\n for (const variant of Object.keys(variants ?? {})) {\n const value = selection[variant];\n if (value == null) continue;\n if (variants?.[variant]?.[value] == null) continue;\n result += ` ${format(`${name}--${variant}${separator}${withoutSpace(value)}`)}`;\n }\n return result;\n};\n//#endregion\n//#region src/is-css-function.ts\nconst fnRegExp = new RegExp(`^(${[\n \"min\",\n \"max\",\n \"clamp\",\n \"calc\"\n].join(\"|\")})\\\\(.*\\\\)`);\nconst isCssFunction = (v) => typeof v === \"string\" && fnRegExp.test(v);\n//#endregion\n//#region src/is-css-unit.ts\nconst lengthUnitsPattern = `(?:${\"cm,mm,Q,in,pc,pt,px,em,ex,ch,rem,lh,rlh,vw,vh,vmin,vmax,vb,vi,svw,svh,lvw,lvh,dvw,dvh,cqw,cqh,cqi,cqb,cqmin,cqmax,%\".split(\",\").join(\"|\")})`;\nconst lengthRegExp = new RegExp(`^[+-]?[0-9]*.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`);\nconst isCssUnit = (v) => typeof v === \"string\" && lengthRegExp.test(v);\n//#endregion\n//#region src/is-css-var.ts\nconst isCssVar = (v) => typeof v === \"string\" && /^var\\(--.+\\)$/.test(v);\n//#endregion\n//#region src/pattern-fns.ts\nconst patternFns = {\n map: mapObject,\n isCssFunction,\n isCssVar,\n isCssUnit\n};\nconst getPatternStyles = (pattern, styles) => {\n if (!pattern?.defaultValues) return styles;\n const defaults = typeof pattern.defaultValues === \"function\" ? pattern.defaultValues(styles) : pattern.defaultValues;\n return Object.assign({}, defaults, compact(styles));\n};\n//#endregion\n//#region src/slot.ts\nconst getSlotRecipes = (recipe = {}) => {\n const init = (slot) => ({\n className: [recipe.className, slot].filter(Boolean).join(\"__\"),\n base: recipe.base?.[slot] ?? {},\n variants: {},\n defaultVariants: recipe.defaultVariants ?? {},\n compoundVariants: recipe.compoundVariants ? getSlotCompoundVariant(recipe.compoundVariants, slot) : []\n });\n const recipeParts = (recipe.slots ?? []).map((slot) => [slot, init(slot)]);\n for (const [variantsKey, variantsSpec] of Object.entries(recipe.variants ?? {})) for (const [variantKey, variantSpec] of Object.entries(variantsSpec)) recipeParts.forEach(([slot, slotRecipe]) => {\n slotRecipe.variants[variantsKey] ??= {};\n slotRecipe.variants[variantsKey][variantKey] = variantSpec[slot] ?? {};\n });\n return Object.fromEntries(recipeParts);\n};\nconst getSlotCompoundVariant = (compoundVariants, slotName) => compoundVariants.filter((compoundVariant) => compoundVariant.css[slotName]).map((compoundVariant) => ({\n ...compoundVariant,\n css: compoundVariant.css[slotName]\n}));\n//#endregion\n//#region src/split-props.ts\n/**\n* Deal a props object into one bucket per key group, plus a final bucket for the rest.\n* A key goes to the first group that claims it.\n*\n* ## Why the descriptor is read per key rather than in bulk\n*\n* This used to call `Object.getOwnPropertyDescriptors` for the whole object and\n* `defineProperty` for every key it moved. Copying plain values instead is 2.4–2.9x faster\n* on the shapes that allow it, but it is only correct where props are data — and they are\n* not always. Solid compiles props to accessors, so reading one eagerly runs whatever it\n* wraps: splitting a component's props would construct its children before the surrounding\n* provider exists.\n*\n* So the descriptor is fetched per key, and the value path is taken only when it changes\n* nothing observable. An accessor keeps its laziness, a non-enumerable key keeps its\n* invisibility, and `__proto__` is defined rather than assigned so it stays an own\n* property instead of reaching the prototype setter.\n*\n* The one thing the value path drops is `writable`/`configurable`, so a bucket key taken\n* from frozen props is writable where it used to be frozen. Nothing here relies on that,\n* and preserving it would mean `defineProperty` on the common path — the cost this exists\n* to avoid. Keys that take the descriptor path keep theirs, so a bucket can be\n* inconsistent in that one respect.\n*\n* Key order within a bucket is preserved exactly. It is not cosmetic: `cva` merges\n* variant props in iteration order, and the parser reads the rest bucket as the style\n* props it encodes, so order reaches the emitted CSS.\n*/\nfunction splitProps(props, ...keys) {\n const allKeys = Object.getOwnPropertyNames(props);\n const own = new Set(allKeys);\n const taken = /* @__PURE__ */ new Set();\n const split = (group) => {\n const clone = {};\n for (let i = 0; i < group.length; i++) {\n const key = group[i];\n if (taken.has(key) || !own.has(key)) continue;\n const descriptor = Object.getOwnPropertyDescriptor(props, key);\n if (!descriptor) continue;\n if (\"get\" in descriptor || \"set\" in descriptor || !descriptor.enumerable || key === \"__proto__\") Object.defineProperty(clone, key, descriptor);\n else clone[key] = descriptor.value;\n taken.add(key);\n }\n return clone;\n };\n /**\n * The predicate is called with the key alone.\n *\n * Handing it to `filter` passes `(key, index, allKeys)`. A one-parameter predicate cannot\n * see the extras, but a memoized one reads its whole argument list — and the predicates\n * that arrive here are memoized, `isCssProperty` among them. So the memo hashed the entire\n * key array once per prop, and keyed its cache on it: two elements with different prop sets\n * shared no entry even for the same prop name.\n *\n * Worth ~9.7x on that path, and nothing at all on a plain predicate — which is why the\n * bench below it needs a memoized case to see this at all.\n *\n * A loop rather than `filter((k) => key(k))` because the wrapper allocates a closure per\n * group. The two measure the same to within noise; the loop just does not need one.\n */\n const matching = (predicate) => {\n const group = [];\n for (let i = 0; i < allKeys.length; i++) {\n const key = allKeys[i];\n if (predicate(key)) group.push(key);\n }\n return group;\n };\n return keys.map((key) => split(Array.isArray(key) ? key : matching(key))).concat(split(allKeys));\n}\n//#endregion\n//#region src/uniq.ts\nconst uniq = (...items) => {\n const set = items.reduce((acc, currItems) => {\n if (currItems) currItems.forEach((item) => acc.add(item));\n return acc;\n }, /* @__PURE__ */ new Set([]));\n return Array.from(set);\n};\n//#endregion\n//#region src/view-transition.ts\n/**\n* The slots a `viewTransition()` bag accepts, in the order they are emitted.\n*\n* Anything else in the options object is ignored — including by the hash, so adding a\n* comment key or spreading an unrelated object does not fork the class name.\n*/\nconst viewTransitionSlots = [\n \"group\",\n \"imagePair\",\n \"old\",\n \"new\"\n];\n/**\n* Serialize a value with object keys sorted, so two style objects that differ only in\n* authoring order hash to the same class.\n*\n* Values JSON has no encoding for (`undefined`, functions, symbols) serialize as `null`\n* rather than being dropped. Nothing reaches here holding one — `filterSlots` removes\n* nullish slots, and the extractor drops nullish leaves — so this is only a floor: it\n* keeps a hole in an array from shifting the elements after it.\n*\n* Not exported. The name promises a general-purpose stable serializer, and this is not\n* one; `viewTransitionClassName` is the whole reason it exists.\n*/\nfunction stableStringify(value) {\n if (value === null) return \"null\";\n const type = typeof value;\n if (type === \"boolean\") return value ? \"true\" : \"false\";\n if (type === \"number\") return Number.isFinite(value) ? String(value) : \"null\";\n if (type === \"string\") return JSON.stringify(value);\n if (Array.isArray(value)) {\n let out = \"[\";\n for (let index = 0; index < value.length; index++) {\n if (index) out += \",\";\n out += stableStringify(value[index]);\n }\n return out + \"]\";\n }\n if (type === \"object\") {\n const keys = Object.keys(value).sort();\n let out = \"{\";\n for (let index = 0; index < keys.length; index++) {\n if (index) out += \",\";\n const key = keys[index];\n out += JSON.stringify(key) + \":\" + stableStringify(value[key]);\n }\n return out + \"}\";\n }\n return \"null\";\n}\n/**\n* Keep the four known slots, dropping any that is nullish.\n*\n* Both halves of the contract have to agree on what an empty slot is, and only one of\n* them gets a choice. The extractor evaluates the source, and a nullish property is gone\n* from what it hands over — `{ new: undefined }` and `{}` reach the build identically.\n* So absent, `undefined` and `null` collapse here too, and `new: enabled ? {…} : null`\n* hashes to the bag it actually styles.\n*/\nfunction filterSlots(options) {\n const filtered = {};\n if (!options || typeof options !== \"object\") return filtered;\n for (const slot of viewTransitionSlots) {\n const value = options[slot];\n if (value != null) filtered[slot] = value;\n }\n return filtered;\n}\n/**\n* The class a `viewTransition()` call resolves to.\n*\n* This is the whole contract between the build and the runtime: the extractor hashes the\n* options it found in the source, the generated `viewTransition()` hashes the options it\n* is called with, and the CSS only reaches the element if the two agree. They agree by\n* construction — both call this function — but only over what the extractor can see. A\n* value it cannot resolve statically is absent from its side and present on the runtime's,\n* which is why a bag has to be a static object literal to be styled at all.\n*\n* The class is used twice, as the `view-transition-class` value and as the argument to\n* `::view-transition-*(.cls)`, so the prefix applies to both.\n*/\nfunction viewTransitionClassName(options, prefix = \"\") {\n const base = \"vt_\" + toHash(stableStringify(filterSlots(options)));\n return prefix ? prefix + \"-\" + base : base;\n}\n//#endregion\nexport { cloneStyles, compact, createCss, createMergeCss, filterBaseConditions, getPatternStyles, getRecipeClassNames, getRecipeIdentity, getSlotCompoundVariant, getSlotRecipes, hypenateProperty, isBaseCondition, isObject, leafClass, mapObject, memo, mergeProps, patternFns, splitProps, toHash, uniq, viewTransitionClassName, walkObject, withoutSpace };\n";
653
472
  //#endregion
654
473
  //#region src/artifacts/js/helpers.ts
655
- function generateHelpers(ctx) {
474
+ function generateHelpers() {
656
475
  return { js: outdent.outdent`
657
- ${content$10}
658
- ${ctx.isTemplateLiteralSyntax ? content$11 : ""}
659
-
660
- ${ctx.jsx.framework ? `${content$9}` : ""}
476
+ ${content$8}
661
477
 
662
478
  export function __spreadValues(a, b) {
663
479
  return { ...a, ...b }
@@ -669,74 +485,6 @@ function generateHelpers(ctx) {
669
485
  ` };
670
486
  }
671
487
  //#endregion
672
- //#region src/artifacts/generated/is-valid-prop.mjs.json
673
- var content$8 = "//#region src/index.ts\nconst userGenerated = \"\".split(\",\");\nconst allCssProperties = \"WebkitAppearance,WebkitBorderBefore,WebkitBorderBeforeColor,WebkitBorderBeforeStyle,WebkitBorderBeforeWidth,WebkitBoxReflect,WebkitLineClamp,WebkitMask,WebkitMaskAttachment,WebkitMaskClip,WebkitMaskComposite,WebkitMaskImage,WebkitMaskOrigin,WebkitMaskPosition,WebkitMaskPositionX,WebkitMaskPositionY,WebkitMaskRepeat,WebkitMaskRepeatX,WebkitMaskRepeatY,WebkitMaskSize,WebkitOverflowScrolling,WebkitTapHighlightColor,WebkitTextFillColor,WebkitTextStroke,WebkitTextStrokeColor,WebkitTextStrokeWidth,WebkitTouchCallout,WebkitUserModify,WebkitUserSelect,accentColor,alignContent,alignItems,alignSelf,alignTracks,all,anchorName,anchorScope,animation,animationComposition,animationDelay,animationDirection,animationDuration,animationFillMode,animationIterationCount,animationName,animationPlayState,animationRange,animationRangeEnd,animationRangeStart,animationTimeline,animationTimingFunction,appearance,aspectRatio,backdropFilter,backfaceVisibility,background,backgroundAttachment,backgroundBlendMode,backgroundClip,backgroundColor,backgroundImage,backgroundOrigin,backgroundPosition,backgroundPositionX,backgroundPositionY,backgroundRepeat,backgroundSize,blockSize,border,borderBlock,borderBlockColor,borderBlockEnd,borderBlockEndColor,borderBlockEndStyle,borderBlockEndWidth,borderBlockStart,borderBlockStartColor,borderBlockStartStyle,borderBlockStartWidth,borderBlockStyle,borderBlockWidth,borderBottom,borderBottomColor,borderBottomLeftRadius,borderBottomRightRadius,borderBottomStyle,borderBottomWidth,borderCollapse,borderColor,borderEndEndRadius,borderEndStartRadius,borderImage,borderImageOutset,borderImageRepeat,borderImageSlice,borderImageSource,borderImageWidth,borderInline,borderInlineColor,borderInlineEnd,borderInlineEndColor,borderInlineEndStyle,borderInlineEndWidth,borderInlineStart,borderInlineStartColor,borderInlineStartStyle,borderInlineStartWidth,borderInlineStyle,borderInlineWidth,borderLeft,borderLeftColor,borderLeftStyle,borderLeftWidth,borderRadius,borderRight,borderRightColor,borderRightStyle,borderRightWidth,borderSpacing,borderStartEndRadius,borderStartStartRadius,borderStyle,borderTop,borderTopColor,borderTopLeftRadius,borderTopRightRadius,borderTopStyle,borderTopWidth,borderWidth,bottom,boxAlign,boxDecorationBreak,boxDirection,boxFlex,boxFlexGroup,boxLines,boxOrdinalGroup,boxOrient,boxPack,boxShadow,boxSizing,breakAfter,breakBefore,breakInside,captionSide,caret,caretColor,caretShape,clear,clip,clipPath,clipRule,color,colorInterpolationFilters,colorScheme,columnCount,columnFill,columnGap,columnRule,columnRuleColor,columnRuleStyle,columnRuleWidth,columnSpan,columnWidth,columns,contain,containIntrinsicBlockSize,containIntrinsicHeight,containIntrinsicInlineSize,containIntrinsicSize,containIntrinsicWidth,container,containerName,containerType,content,contentVisibility,cornerShape,counterIncrement,counterReset,counterSet,cursor,cx,cy,d,direction,display,dominantBaseline,emptyCells,fieldSizing,fill,fillOpacity,fillRule,filter,flex,flexBasis,flexDirection,flexFlow,flexGrow,flexShrink,flexWrap,float,floodColor,floodOpacity,font,fontFamily,fontFeatureSettings,fontKerning,fontLanguageOverride,fontOpticalSizing,fontPalette,fontSize,fontSizeAdjust,fontSmooth,fontStretch,fontStyle,fontSynthesis,fontSynthesisPosition,fontSynthesisSmallCaps,fontSynthesisStyle,fontSynthesisWeight,fontVariant,fontVariantAlternates,fontVariantCaps,fontVariantEastAsian,fontVariantEmoji,fontVariantLigatures,fontVariantNumeric,fontVariantPosition,fontVariationSettings,fontWeight,forcedColorAdjust,gap,grid,gridArea,gridAutoColumns,gridAutoFlow,gridAutoRows,gridColumn,gridColumnEnd,gridColumnGap,gridColumnStart,gridGap,gridRow,gridRowEnd,gridRowGap,gridRowStart,gridTemplate,gridTemplateAreas,gridTemplateColumns,gridTemplateRows,hangingPunctuation,height,hyphenateCharacter,hyphenateLimitChars,hyphens,imageOrientation,imageRendering,imageResolution,imeMode,initialLetter,initialLetterAlign,inlineSize,inset,insetBlock,insetBlockEnd,insetBlockStart,insetInline,insetInlineEnd,insetInlineStart,interpolateSize,isolation,justifyContent,justifyItems,justifySelf,justifyTracks,left,letterSpacing,lightingColor,lineBreak,lineClamp,lineHeight,lineHeightStep,listStyle,listStyleImage,listStylePosition,listStyleType,margin,marginBlock,marginBlockEnd,marginBlockStart,marginBottom,marginInline,marginInlineEnd,marginInlineStart,marginLeft,marginRight,marginTop,marginTrim,marker,markerEnd,markerMid,markerStart,mask,maskBorder,maskBorderMode,maskBorderOutset,maskBorderRepeat,maskBorderSlice,maskBorderSource,maskBorderWidth,maskClip,maskComposite,maskImage,maskMode,maskOrigin,maskPosition,maskRepeat,maskSize,maskType,masonryAutoFlow,mathDepth,mathShift,mathStyle,maxBlockSize,maxHeight,maxInlineSize,maxLines,maxWidth,minBlockSize,minHeight,minInlineSize,minWidth,mixBlendMode,objectFit,objectPosition,offset,offsetAnchor,offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline,outlineColor,outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowBlock,overflowClipBox,overflowClipMargin,overflowInline,overflowWrap,overflowX,overflowY,overlay,overscrollBehavior,overscrollBehaviorBlock,overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,padding,paddingBlock,paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline,paddingInlineEnd,paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter,pageBreakBefore,pageBreakInside,paintOrder,perspective,perspectiveOrigin,placeContent,placeItems,placeSelf,pointerEvents,position,positionAnchor,positionArea,positionTry,positionTryFallbacks,positionTryOrder,positionVisibility,printColorAdjust,quotes,r,resize,right,rotate,rowGap,rubyAlign,rubyMerge,rubyPosition,rx,ry,scale,scrollBehavior,scrollMargin,scrollMarginBlock,scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom,scrollMarginInline,scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft,scrollMarginRight,scrollMarginTop,scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd,scrollPaddingBlockStart,scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd,scrollPaddingInlineStart,scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign,scrollSnapCoordinate,scrollSnapDestination,scrollSnapPointsX,scrollSnapPointsY,scrollSnapStop,scrollSnapType,scrollSnapTypeX,scrollSnapTypeY,scrollTimeline,scrollTimelineAxis,scrollTimelineName,scrollbarColor,scrollbarGutter,scrollbarWidth,shapeImageThreshold,shapeMargin,shapeOutside,shapeRendering,stopColor,stopOpacity,stroke,strokeDasharray,strokeDashoffset,strokeLinecap,strokeLinejoin,strokeMiterlimit,strokeOpacity,strokeWidth,tabSize,tableLayout,textAlign,textAlignLast,textAnchor,textBox,textBoxEdge,textBoxTrim,textCombineUpright,textDecoration,textDecorationColor,textDecorationLine,textDecorationSkip,textDecorationSkipInk,textDecorationStyle,textDecorationThickness,textEmphasis,textEmphasisColor,textEmphasisPosition,textEmphasisStyle,textIndent,textJustify,textOrientation,textOverflow,textRendering,textShadow,textSizeAdjust,textSpacingTrim,textTransform,textUnderlineOffset,textUnderlinePosition,textWrap,textWrapMode,textWrapStyle,timelineScope,top,touchAction,transform,transformBox,transformOrigin,transformStyle,transition,transitionBehavior,transitionDelay,transitionDuration,transitionProperty,transitionTimingFunction,translate,unicodeBidi,userSelect,vectorEffect,verticalAlign,viewTimeline,viewTimelineAxis,viewTimelineInset,viewTimelineName,viewTransitionName,visibility,whiteSpace,whiteSpaceCollapse,widows,width,willChange,wordBreak,wordSpacing,wordWrap,writingMode,x,y,zIndex,zoom,alignmentBaseline,baselineShift,colorInterpolation,colorRendering,glyphOrientationVertical\".split(\",\").concat(userGenerated);\nconst properties = new Map(allCssProperties.map((prop) => [prop, true]));\nfunction memo(fn) {\n const cache = Object.create(null);\n return (arg) => {\n if (cache[arg] === void 0) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\nconst cssPropertySelectorRegex = /&|@/;\nconst isCssProperty = /* @__PURE__ */ memo((prop) => {\n return properties.has(prop) || prop.startsWith(\"--\") || cssPropertySelectorRegex.test(prop);\n});\n//#endregion\nexport { allCssProperties, isCssProperty };\n";
674
- //#endregion
675
- //#region src/artifacts/js/is-valid-prop.ts
676
- const cssPropListRegex = /const userGenerated = ".*?"\.split\(","\);\s*const allCssProperties = "(.*?)"\.split\(","\)\.concat\(userGenerated\);/;
677
- const memoFnDeclarationRegex = /function memo(?:.+?)\n((?:var|const|let) cssPropertySelectorRegex)/s;
678
- function generateIsValidProp(ctx) {
679
- if (ctx.isTemplateLiteralSyntax) return;
680
- let content = content$8;
681
- const propertyList = content.match(cssPropListRegex);
682
- if (!propertyList) throw new _bamboocss_shared.BambooError("NOT_FOUND", "Could not find the property list in the prebuilt is-valid-prop module. Its bundled shape has changed.");
683
- const userProperties = (0, ts_pattern.match)(ctx.jsx.styleProps).with("all", () => Array.from(ctx.properties)).with("minimal", () => ["css"]).with("none", () => ["css"]).exhaustive();
684
- const browserProperties = ctx.jsx.styleProps === "all" ? propertyList[1].split(",") : [];
685
- content = content.replace(cssPropListRegex, () => `const allCssProperties = "${(0, _bamboocss_shared.uniq)(browserProperties, userProperties).join(",")}".split(",");`);
686
- content = content.replace(memoFnDeclarationRegex, "$1");
687
- if (ctx.jsx.styleProps === "minimal" || ctx.jsx.styleProps === "none") content = content.replace("/* @__PURE__ */ memo(", "/* @__PURE__ */ (");
688
- else content = ctx.file.import("memo", "../helpers") + "\n" + content;
689
- content = ctx.file.import("splitProps", "../helpers") + "\n" + content;
690
- content += `export const splitCssProps = (props) => splitProps(props, isCssProperty)`;
691
- return {
692
- js: content,
693
- dts: outdent.outdent`
694
- import type { DistributiveOmit, HTMLBambooProps, JsxStyleProps, Pretty } from '../types';
695
-
696
- declare const isCssProperty: (value: string) => boolean;
697
-
698
- type CssPropKey = keyof JsxStyleProps
699
- type OmittedCssProps<T> = Pretty<DistributiveOmit<T, CssPropKey>>
700
-
701
- declare const splitCssProps: <T>(props: T) => [JsxStyleProps, OmittedCssProps<T>]
702
-
703
- export { isCssProperty, splitCssProps };
704
- `
705
- };
706
- }
707
- //#endregion
708
- //#region src/artifacts/js/jsx-helper.ts
709
- function generatedJsxHelpers(ctx) {
710
- return { js: (0, ts_pattern.match)(ctx.isTemplateLiteralSyntax).with(true, () => outdent.outdent`
711
- export const getDisplayName = (Component) => {
712
- if (typeof Component === 'string') return Component
713
- return Component?.displayName || Component?.name || 'Component'
714
- }`).otherwise(() => outdent.outdent`
715
- ${ctx.file.import("isCssProperty", "./is-valid-prop")}
716
-
717
- export const defaultShouldForwardProp = (prop, variantKeys) => !variantKeys.includes(prop) && !isCssProperty(prop)
718
-
719
- export const composeShouldForwardProps = (tag, shouldForwardProp) =>
720
- tag.__shouldForwardProps__ && shouldForwardProp
721
- ? (propName) => tag.__shouldForwardProps__(propName) && shouldForwardProp(propName)
722
- : shouldForwardProp
723
-
724
- export const composeCvaFn = (cvaA, cvaB) => {
725
- if (cvaA && !cvaB) return cvaA
726
- if (!cvaA && cvaB) return cvaB
727
- if ((cvaA.__cva__ && cvaB.__cva__) || (cvaA.__recipe__ && cvaB.__recipe__)) return cvaA.merge(cvaB)
728
- const error = new TypeError('Cannot merge cva with recipe. Please use either cva or recipe.')
729
- TypeError.captureStackTrace?.(error)
730
- throw error
731
- }
732
-
733
- export const getDisplayName = (Component) => {
734
- if (typeof Component === 'string') return Component
735
- return Component?.displayName || Component?.name || 'Component'
736
- }
737
- `) };
738
- }
739
- //#endregion
740
488
  //#region src/artifacts/js/package-json.ts
741
489
  /**
742
490
  * The generated output is a plain directory, not an installed package, so bundlers
@@ -860,22 +608,12 @@ function generatePattern(ctx, filters) {
860
608
  //#region src/shared.ts
861
609
  const isBooleanValue = (value) => value === "true" || value === "false";
862
610
  const formatFunctionValue = (value) => isBooleanValue(value) ? value : `'${value}'`;
863
- const formatJsxValue = (value) => isBooleanValue(value) ? `{${value}}` : `"${value}"`;
864
611
  const buildFunctionProps = (key, value) => `${key}: ${formatFunctionValue(value)}`;
865
- const buildJsxProps = (key, value) => `${key}=${formatJsxValue(value)}`;
866
612
  const formatProps = (props, options = {}) => {
867
613
  const { keyValueSeparator = ": ", propSeparator = ", ", quoteStyle = "single" } = options;
868
614
  const quote = quoteStyle === "single" ? "'" : quoteStyle === "double" ? "\"" : "";
869
615
  return Object.entries(props).filter(([_, value]) => value != null).map(([key, value]) => `${key}${keyValueSeparator}${quote}${value}${quote}`).join(propSeparator);
870
616
  };
871
- const formatJsxComponent = (component, props) => {
872
- const formattedProps = formatProps(props, {
873
- keyValueSeparator: "=",
874
- propSeparator: " ",
875
- quoteStyle: "double"
876
- });
877
- return `<${component}${formattedProps ? " " + formattedProps : ""} />`;
878
- };
879
617
  const collectCompositionStyles = (values) => {
880
618
  const result = [];
881
619
  (0, _bamboocss_shared.walkObject)(values, (token, paths) => {
@@ -889,27 +627,6 @@ const collectCompositionStyles = (values) => {
889
627
  }, { stop: (v) => (0, _bamboocss_shared.isObject)(v) && "value" in v });
890
628
  return result;
891
629
  };
892
- /**
893
- * Generates a single JSX example based on jsxStyleProps setting
894
- */
895
- const generateJsxExample = (props, jsxStyleProps = "all", component = "Box") => {
896
- if (jsxStyleProps === "all") return formatJsxComponent(component, props);
897
- if (jsxStyleProps === "minimal") return `<${component} css={{ ${formatProps(props)} }} />`;
898
- return null;
899
- };
900
- /**
901
- * Generates function and JSX examples for a style property
902
- */
903
- const generateJsxExamples = (props, jsxStyleProps = "all", component = "Box") => {
904
- const functionExamples = [`css({ ${formatProps(props)} })`];
905
- const jsxExamples = [];
906
- const jsxExample = generateJsxExample(props, jsxStyleProps, component);
907
- if (jsxExample) jsxExamples.push(jsxExample);
908
- return {
909
- functionExamples,
910
- jsxExamples
911
- };
912
- };
913
630
  const COMPOSITION_STYLE_CONFIG = {
914
631
  "text-styles": {
915
632
  prop: "textStyle",
@@ -924,14 +641,14 @@ const COMPOSITION_STYLE_CONFIG = {
924
641
  themeKey: "animationStyles"
925
642
  }
926
643
  };
927
- function generateCompositionStyleSpec(type, theme, jsxStyleProps) {
644
+ function generateCompositionStyleSpec(type, theme) {
928
645
  const { prop, themeKey } = COMPOSITION_STYLE_CONFIG[type];
929
646
  return {
930
647
  type,
931
648
  data: collectCompositionStyles(theme?.[themeKey] ?? {}).map((style) => ({
932
649
  name: style.name,
933
650
  description: style.description,
934
- ...generateJsxExamples({ [prop]: style.name }, jsxStyleProps)
651
+ functionExamples: [`css({ ${formatProps({ [prop]: style.name })} })`]
935
652
  }))
936
653
  };
937
654
  }
@@ -950,7 +667,6 @@ function generateCreateRecipe(ctx) {
950
667
  dts: "",
951
668
  js: outdent.outdent`
952
669
  ${ctx.file.import("finalizeConditions, sortConditions", "../css/conditions")}
953
- ${ctx.file.import("css", "../css/css")}
954
670
  ${ctx.file.import("assertCompoundVariant, getCompoundVariantCss", "../css/cva")}
955
671
  ${ctx.file.import("cx", "../css/cx")}
956
672
  ${ctx.file.import("compact, createCss, splitProps, uniq, withoutSpace", "../helpers")}
@@ -964,7 +680,7 @@ function generateCreateRecipe(ctx) {
964
680
  };
965
681
  };
966
682
 
967
- const recipeFn = (variants, withCompoundVariants = true) => {
683
+ const recipeFn = (variants) => {
968
684
  const transform = (prop, value) => {
969
685
  assertCompoundVariant(name, compoundVariants, variants, prop)
970
686
 
@@ -992,11 +708,10 @@ function generateCreateRecipe(ctx) {
992
708
 
993
709
  const recipeStyles = getVariantProps(variants)
994
710
 
995
- if (withCompoundVariants) {
996
- const compoundVariantStyles = getCompoundVariantCss(compoundVariants, recipeStyles)
997
- return cx(recipeCss(recipeStyles), css(compoundVariantStyles))
998
- }
999
-
711
+ // No class for the compound variants. Their rule selects on the variant classes
712
+ // \`recipeCss\` just named — \`.btn--size_sm.btn--tone_a\` — so it applies on its own,
713
+ // and it is in the same layer as the rest of the recipe rather than atomically in
714
+ // \`utilities\` above it.
1000
715
  return recipeCss(recipeStyles)
1001
716
  }
1002
717
 
@@ -1048,9 +763,22 @@ function generateRecipes(ctx, filters) {
1048
763
  else defaultValue = JSON.stringify(defaultValue);
1049
764
  return ctx.file.jsDocComment("", { default: defaultValue });
1050
765
  };
766
+ const slotNames = _bamboocss_core.Recipes.isSlotRecipeConfig(config) ? config.slots : [];
767
+ const anchorSlotNames = _bamboocss_core.Recipes.isSlotRecipeConfig(config) ? _bamboocss_core.Recipes.getScopeRoots(config) : [];
1051
768
  return {
1052
769
  name: dashName,
1053
- js: (0, ts_pattern.match)(config).when(_bamboocss_core.Recipes.isSlotRecipeConfig, (config) => outdent.outdent`
770
+ js: (0, ts_pattern.match)(config).when(_bamboocss_core.Recipes.isSlotRecipeConfig, (config) => {
771
+ const anchors = _bamboocss_core.Recipes.getScopeRoots(config);
772
+ /**
773
+ * Which slots each variant writes styles for.
774
+ *
775
+ * A scope reaches every slot inside an anchor's subtree. A slot under no anchor at
776
+ * all is not reached, and nothing here can detect that — reachability is a fact
777
+ * about the DOM. This is what says which slots a variant has to get to, so the
778
+ * component layer can thread the ones a scope cannot.
779
+ */
780
+ const slotsAffectedBy = Object.fromEntries(Object.entries(config.variants ?? {}).map(([variant, values]) => [variant, Array.from(new Set(Object.values(values ?? {}).flatMap((slotStyles) => Object.keys(slotStyles ?? {}))))]));
781
+ return outdent.outdent`
1054
782
  ${ctx.file.import("compact, getSlotCompoundVariant, memo, splitProps", "../helpers")}
1055
783
  ${ctx.file.import("createRecipe", "./create-recipe")}
1056
784
 
@@ -1058,11 +786,27 @@ function generateRecipes(ctx, filters) {
1058
786
  const ${baseName}CompoundVariants = ${stringify$2(compoundVariants ?? [])}
1059
787
 
1060
788
  const ${baseName}SlotNames = ${stringify$2(config.slots.map((slot) => [slot, `${config.className}__${slot}`]))}
789
+ ${anchors.length ? outdent.outdent`
790
+ /**
791
+ * Only the anchors take variants: ${anchors.map((slot) => `\`${baseName}.${slot}\``).join(", ")}.
792
+ * Every other slot's variant styles are emitted as rules scoped by a class an anchor
793
+ * carries, so that slot's class is a constant and nothing has to reach it at runtime.
794
+ */
795
+ const ${baseName}Anchors = ${JSON.stringify(anchors)}
796
+ const ${baseName}AnchorFns = /* @__PURE__ */ ${baseName}Anchors.map((slotName) => [slotName, createRecipe(\`${config.className}__\${slotName}\`, ${baseName}DefaultVariants, getSlotCompoundVariant(${baseName}CompoundVariants, slotName))])
797
+ const ${baseName}StaticSlots = /* @__PURE__ */ Object.fromEntries(
798
+ ${baseName}SlotNames.filter(([slotName]) => !${baseName}Anchors.includes(slotName)),
799
+ )
800
+
801
+ const ${baseName}Fn = memo((props = {}) => ({
802
+ ...${baseName}StaticSlots,
803
+ ...Object.fromEntries(${baseName}AnchorFns.map(([slotName, anchorFn]) => [slotName, anchorFn.recipeFn(props)])),
804
+ }))` : outdent.outdent`
1061
805
  const ${baseName}SlotFns = /* @__PURE__ */ ${baseName}SlotNames.map(([slotName, slotKey]) => [slotName, createRecipe(slotKey, ${baseName}DefaultVariants, getSlotCompoundVariant(${baseName}CompoundVariants, slotName))])
1062
806
 
1063
807
  const ${baseName}Fn = memo((props = {}) => {
1064
808
  return Object.fromEntries(${baseName}SlotFns.map(([slotName, slotFn]) => [slotName, slotFn.recipeFn(props)]))
1065
- })
809
+ })`}
1066
810
 
1067
811
  const ${baseName}VariantKeys = ${stringify$2(Object.keys(variantKeyMap))}
1068
812
  const getVariantProps = (variants) => ({ ...${baseName}DefaultVariants, ...compact(variants) })
@@ -1071,15 +815,25 @@ function generateRecipes(ctx, filters) {
1071
815
  __recipe__: false,
1072
816
  __name__: '${baseName}',
1073
817
  raw: (props) => props,
1074
- classNameMap: {},
818
+ /** Each slot's constant class, for targeting a slot in the DOM. */
819
+ classNameMap: /* @__PURE__ */ Object.fromEntries(${baseName}SlotNames),
820
+ /** The slots that enclose other slots, and so anchor their variant rules. */
821
+ scopeRoots: ${JSON.stringify(anchors)},
1075
822
  variantKeys: ${baseName}VariantKeys,
1076
823
  variantMap: ${stringify$2(variantKeyMap)},
824
+ /** Which slots each variant actually reaches, for a slot a scope cannot get to. */
825
+ slotsAffectedBy: ${stringify$2(slotsAffectedBy)},
1077
826
  splitVariantProps(props) {
1078
827
  return splitProps(props, ${baseName}VariantKeys)
1079
828
  },
1080
- getVariantProps
829
+ getVariantProps,
830
+ ${anchors.length ? outdent.outdent`
831
+ ...Object.fromEntries(${baseName}AnchorFns.map(([slotName, anchorFn]) => [slotName, anchorFn.recipeFn])),
832
+ ...${baseName}StaticSlots,
833
+ ` : ""}
1081
834
  })
1082
- `).otherwise((config) => outdent.outdent`
835
+ `;
836
+ }).otherwise((config) => outdent.outdent`
1083
837
  ${ctx.file.import("memo, splitProps", "../helpers")}
1084
838
  ${ctx.file.import("createRecipe, mergeRecipes", "./create-recipe")}
1085
839
 
@@ -1136,6 +890,13 @@ function generateRecipes(ctx, filters) {
1136
890
  variantKeys: Array<keyof ${upperName}Variant>
1137
891
  splitVariantProps<Props extends ${upperName}VariantProps>(props: Props): [${upperName}VariantProps, Pretty<DistributiveOmit<Props, keyof ${upperName}VariantProps>>]
1138
892
  getVariantProps: (props?: ${upperName}VariantProps) => ${upperName}VariantProps
893
+ ${_bamboocss_core.Recipes.isSlotRecipeConfig(config) ? outdent.outdent`
894
+ /** Which slots each variant writes styles for. */
895
+ slotsAffectedBy: Record<keyof ${upperName}Variant, ${upperName}Slot[]>` : ""}
896
+ ${anchorSlotNames.length ? outdent.outdent`
897
+ /** The slots that take variants — every other one is scoped by a class an anchor carries. */
898
+ ${anchorSlotNames.map((slot) => `${slot}: (props?: ${upperName}VariantProps) => string`).join("\n")}
899
+ ${slotNames.filter((slot) => !anchorSlotNames.includes(slot)).map((slot) => `${slot}: string`).join("\n")}` : ""}
1139
900
  }
1140
901
 
1141
902
  ${ctx.file.jsDocComment(description, { deprecated })}
@@ -1149,2819 +910,283 @@ function generateRecipes(ctx, filters) {
1149
910
  function generateSvaFn(ctx) {
1150
911
  return {
1151
912
  js: outdent.outdent`
1152
- ${ctx.file.import("compact, getSlotRecipes, memo, splitProps", "../helpers")}
913
+ ${ctx.file.import("compact, getRecipeIdentity, getSlotRecipes, memo, splitProps", "../helpers")}
1153
914
  ${ctx.file.import("cva", "./cva")}
1154
915
  ${ctx.file.import("cx", "./cx")}
1155
916
 
1156
917
  export function sva(config) {
1157
- const slots = Object.entries(getSlotRecipes(config)).map(([slot, slotCva]) => [slot, cva(slotCva)])
918
+ // Named before the split, so each slot's class is \`name__slot\`. Left to
919
+ // \`getSlotRecipes\`, a config with no \`className\` gives every slot the bare slot name
920
+ // — \`root\` — which every other anonymous recipe with a \`root\` slot would share. The
921
+ // build injects the identity at the same point, for the same reason.
922
+ const name = getRecipeIdentity(config, 'sva')
923
+ const withName = { ...config, className: config.className ?? name }
924
+
925
+ const slots = Object.entries(getSlotRecipes(withName)).map(([slot, slotCva]) => [slot, cva(slotCva)])
1158
926
  const defaultVariants = config.defaultVariants ?? {}
1159
927
 
928
+ // Populated whether or not the author set a \`className\`. Every slot recipe is given
929
+ // one before the split — the identity when the config declares none — so the guard
930
+ // that used to sit here left an anonymous \`sva\` reporting no slot classes despite
931
+ // emitting them.
1160
932
  const classNameMap = slots.reduce((acc, [slot, cvaFn]) => {
1161
- if (config.className) acc[slot] = cvaFn.config.className
933
+ acc[slot] = cvaFn.config.className
1162
934
  return acc
1163
935
  }, {})
1164
936
 
1165
- function svaFn(props) {
1166
- const result = slots.map(([slot, cvaFn]) => [slot, cx(cvaFn(props), classNameMap[slot])])
1167
- return Object.fromEntries(result)
1168
- }
1169
-
1170
- function raw(props) {
1171
- const result = slots.map(([slot, cvaFn]) => [slot, cvaFn.raw(props)])
1172
- return Object.fromEntries(result)
1173
- }
1174
-
1175
- const variants = config.variants ?? {};
1176
- const variantKeys = Object.keys(variants);
1177
-
1178
- function splitVariantProps(props) {
1179
- return splitProps(props, variantKeys);
1180
- }
1181
- const getVariantProps = (variants) => ({ ...defaultVariants, ...compact(variants) })
1182
-
1183
- const variantMap = Object.fromEntries(
1184
- Object.entries(variants).map(([key, value]) => [key, Object.keys(value)])
1185
- );
1186
-
1187
- return Object.assign(memo(svaFn), {
1188
- __cva__: false,
1189
- raw,
1190
- config,
1191
- variantMap,
1192
- variantKeys,
1193
- classNameMap,
1194
- splitVariantProps,
1195
- getVariantProps,
1196
- })
1197
- }
1198
- `,
1199
- dts: outdent.outdent`
1200
- ${ctx.file.importType("SlotRecipeCreatorFn", "../types/recipe")}
1201
-
1202
- export declare const sva: SlotRecipeCreatorFn
1203
- `
1204
- };
1205
- }
1206
- //#endregion
1207
- //#region src/artifacts/js/token.ts
1208
- function generateTokenJs(ctx) {
1209
- const { tokens } = ctx;
1210
- const map = /* @__PURE__ */ new Map();
1211
- tokens.allTokens.forEach((token) => {
1212
- const { varRef, isVirtual } = token.extensions;
1213
- const value = isVirtual || token.extensions.condition !== "base" ? varRef : token.value;
1214
- map.set(token.name, {
1215
- value,
1216
- variable: varRef
1217
- });
1218
- });
1219
- const obj = Object.fromEntries(map);
1220
- return {
1221
- js: outdent.default`
1222
- const tokens = ${JSON.stringify(obj, null, 2)}
1223
-
1224
- export function token(path, fallback) {
1225
- return tokens[path]?.value || fallback
1226
- }
1227
-
1228
- function tokenVar(path, fallback) {
1229
- return tokens[path]?.variable || fallback
1230
- }
1231
-
1232
- token.var = tokenVar
1233
- `,
1234
- dts: outdent.default`
1235
- ${ctx.file.importType("Token", "./tokens")}
1236
-
1237
- export declare const token: {
1238
- (path: Token, fallback?: string): string
1239
- var: (path: Token, fallback?: string) => string
1240
- }
1241
-
1242
- ${ctx.file.exportTypeStar("./tokens")}
1243
- `
1244
- };
1245
- }
1246
- //#endregion
1247
- //#region src/artifacts/preact-jsx/jsx.ts
1248
- function generatePreactJsxFactory(ctx) {
1249
- const { factoryName, componentName } = ctx.jsx;
1250
- return { js: outdent.outdent`
1251
- import { h } from 'preact'
1252
- import { forwardRef } from 'preact/compat'
1253
- ${ctx.file.import("defaultShouldForwardProp, composeShouldForwardProps, composeCvaFn, getDisplayName", "./factory-helper")}
1254
- ${ctx.file.import("isCssProperty", "./is-valid-prop")}
1255
- ${ctx.file.import("css, cx, cva", "../css/index")}
1256
- ${ctx.file.import("splitProps, normalizeHTMLProps", "../helpers")}
1257
-
1258
- function styledFn(Dynamic, configOrCva = {}, options = {}) {
1259
- const cvaFn = configOrCva.__cva__ || configOrCva.__recipe__ ? configOrCva : cva(configOrCva)
1260
-
1261
- const forwardFn = options.shouldForwardProp || defaultShouldForwardProp
1262
- const shouldForwardProp = (prop) => {
1263
- if (options.forwardProps?.includes(prop)) return true
1264
- return forwardFn(prop, cvaFn.variantKeys)
1265
- }
1266
-
1267
- const defaultProps = Object.assign(
1268
- options.dataAttr && configOrCva.__name__ ? { 'data-recipe': configOrCva.__name__ } : {},
1269
- options.defaultProps,
1270
- )
1271
-
1272
- const __cvaFn__ = composeCvaFn(Dynamic.__cva__, cvaFn)
1273
- const __shouldForwardProps__ = composeShouldForwardProps(Dynamic, shouldForwardProp)
1274
- const __base__ = Dynamic.__base__ || Dynamic
1275
-
1276
- const ${componentName} = /* @__PURE__ */ forwardRef(function ${componentName}(props, ref) {
1277
- const { as: Element = __base__, unstyled, children, ...restProps } = props
1278
-
1279
-
1280
- // Not memoized, deliberately. \`restProps\` is rest destructuring, so it is a fresh
1281
- // object on every render and a dependency on it can never match — a memo here is a
1282
- // guaranteed miss that still costs a hook slot, a deps array and a retained cell.
1283
- const combinedProps = Object.assign({}, defaultProps, restProps)
1284
-
1285
- const [htmlProps, forwardedProps, variantProps, styleProps, elementProps] =
1286
- splitProps(combinedProps, normalizeHTMLProps.keys, __shouldForwardProps__, __cvaFn__.variantKeys, isCssProperty)
1287
-
1288
- function recipeClass() {
1289
- const { css: cssStyles, ...propStyles } = styleProps
1290
- const compoundVariantStyles = __cvaFn__.__getCompoundVariantCss__?.(variantProps)
1291
- return cx(__cvaFn__(variantProps, false), css(compoundVariantStyles, propStyles, cssStyles), combinedProps.class, combinedProps.className)
1292
- }
1293
-
1294
- function cvaClass() {
1295
- const { css: cssStyles, ...propStyles } = styleProps
1296
- const cvaStyles = __cvaFn__.raw(variantProps)
1297
- return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.class, combinedProps.className)
1298
- }
1299
-
1300
- const classes = () => {
1301
- if (unstyled) {
1302
- const { css: cssStyles, ...propStyles } = styleProps
1303
- return cx(css(propStyles, cssStyles), combinedProps.class, combinedProps.className)
1304
- }
1305
- return configOrCva.__recipe__ ? recipeClass() : cvaClass()
1306
- }
1307
-
1308
- return h(Element, {
1309
- ...forwardedProps,
1310
- ...elementProps,
1311
- ...normalizeHTMLProps(htmlProps),
1312
- ref,
1313
- className: classes()
1314
- }, children ?? combinedProps.children)
1315
- })
1316
-
1317
- const name = getDisplayName(__base__)
1318
-
1319
- ${componentName}.displayName = \`${factoryName}.\${name}\`
1320
- ${componentName}.__cva__ = __cvaFn__
1321
- ${componentName}.__base__ = __base__
1322
- ${componentName}.__shouldForwardProps__ = shouldForwardProp
1323
-
1324
- return ${componentName}
1325
- }
1326
-
1327
- function createJsxFactory() {
1328
- const cache = new Map()
1329
-
1330
- return new Proxy(styledFn, {
1331
- apply(_, __, args) {
1332
- return styledFn(...args)
1333
- },
1334
- get(_, el) {
1335
- if (!cache.has(el)) {
1336
- cache.set(el, styledFn(el))
1337
- }
1338
- return cache.get(el)
1339
- },
1340
- })
1341
- }
1342
-
1343
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
1344
- ` };
1345
- }
1346
- //#endregion
1347
- //#region src/artifacts/preact-jsx/pattern.ts
1348
- function generatePreactJsxPattern(ctx, filters) {
1349
- const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx;
1350
- return ctx.patterns.filterDetails(filters).map((pattern) => {
1351
- const { upperName, styleFnName, dashName, jsxName, props, blocklistType } = pattern;
1352
- const { description, jsxElement = "div", deprecated } = pattern.config;
1353
- return {
1354
- name: dashName,
1355
- js: outdent.outdent`
1356
- import { h } from 'preact'
1357
- import { forwardRef } from 'preact/compat'
1358
- ${jsxStyleProps === "minimal" ? ctx.file.import("mergeCss", "../css/css") : ""}
1359
- ${ctx.file.import("splitProps", "../helpers")}
1360
- ${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
1361
- ${ctx.file.import(factoryName, "./factory")}
1362
-
1363
- export const ${jsxName} = /* @__PURE__ */ forwardRef(function ${jsxName}(props, ref) {
1364
- ${(0, ts_pattern.match)(jsxStyleProps).with("none", () => outdent.outdent`
1365
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
1366
-
1367
- const styleProps = ${styleFnName}(patternProps)
1368
- const mergedProps = { ref, ...restProps, css: styleProps }
1369
-
1370
- return h(${factoryName}.${jsxElement}, mergedProps)
1371
- `).with("minimal", () => outdent.outdent`
1372
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
1373
-
1374
- const styleProps = ${styleFnName}(patternProps)
1375
- const cssProps = { css: mergeCss(styleProps, props.css) }
1376
- const mergedProps = { ref, ...restProps, ...cssProps }
1377
-
1378
- return h(${factoryName}.${jsxElement}, mergedProps)
1379
- `).with("all", () => outdent.outdent`
1380
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
1381
-
1382
- const styleProps = ${styleFnName}(patternProps)
1383
- const mergedProps = { ref, ...styleProps, ...restProps }
1384
-
1385
- return h(${factoryName}.${jsxElement}, mergedProps)
1386
- `).exhaustive()}
1387
- })
1388
- `,
1389
- dts: outdent.outdent`
1390
- import type { FunctionComponent } from 'preact'
1391
- ${ctx.file.importType(`${upperName}Properties`, `../patterns/${dashName}`)}
1392
- ${ctx.file.importType("DistributiveOmit", "../types/system-types")}
1393
- ${ctx.file.importType(typeName, "../types/jsx")}
1394
-
1395
- export interface ${upperName}Props extends ${upperName}Properties, DistributiveOmit<${typeName}<'${jsxElement}'>, keyof ${upperName}Properties ${blocklistType}> {}
1396
-
1397
- ${ctx.file.jsDocComment(description, { deprecated })}
1398
- export declare const ${jsxName}: FunctionComponent<${upperName}Props>
1399
- `
1400
- };
1401
- });
1402
- }
1403
- //#endregion
1404
- //#region src/artifacts/preact-jsx/types.ts
1405
- function generatePreactJsxTypes(ctx) {
1406
- const { factoryName, componentName, upperName, typeName, variantName } = ctx.jsx;
1407
- return {
1408
- jsxFactory: outdent.outdent`
1409
- import type { ${upperName} } from '../types/jsx'
1410
- export declare const ${factoryName}: ${upperName}
1411
- `,
1412
- jsxType: outdent.outdent`
1413
- import type { ComponentProps, JSX } from 'preact'
1414
- ${ctx.file.importType("RecipeDefinition, RecipeSelection, RecipeVariantRecord", "./recipe")}
1415
- ${ctx.file.importType("Assign, DistributiveOmit, DistributiveUnion, JsxHTMLProps, JsxStyleProps, Pretty", "./system-types")}
1416
-
1417
- export type ElementType = JSX.ElementType
1418
-
1419
- interface Dict {
1420
- [k: string]: unknown
1421
- }
1422
-
1423
- export type DataAttrs = Record<\`data-\${string}\`, unknown>
1424
-
1425
- export interface UnstyledProps {
1426
- /**
1427
- * Whether to remove recipe styles
1428
- */
1429
- unstyled?: boolean | undefined
1430
- }
1431
-
1432
- export interface AsProps {
1433
- /**
1434
- * The element to render as
1435
- */
1436
- as?: ElementType | undefined
1437
- }
1438
-
1439
- export interface ${componentName}<T extends ElementType, P extends Dict = {}> {
1440
- (props: JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<JsxStyleProps, P>>): JSX.Element
1441
- displayName?: string | undefined
1442
- }
1443
-
1444
- interface RecipeFn {
1445
- __type: any
1446
- }
1447
-
1448
- export interface JsxFactoryOptions<TProps extends Dict> {
1449
- dataAttr?: boolean
1450
- defaultProps?: Partial<TProps> & DataAttrs
1451
- shouldForwardProp?: (prop: string, variantKeys: string[]) => boolean
1452
- forwardProps?: string[]
1453
- }
1454
-
1455
- export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, P>
1456
-
1457
- export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
1458
- ? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
1459
- : ${componentName}<T, P>
1460
-
1461
- export interface JsxFactory {
1462
- <T extends ElementType>(component: T): ${componentName}<T, {}>
1463
- <T extends ElementType, P extends RecipeVariantRecord>(component: T, recipe: RecipeDefinition<P>, options?: JsxFactoryOptions<JsxRecipeProps<T, RecipeSelection<P>>>): JsxElement<
1464
- T,
1465
- RecipeSelection<P>
1466
- >
1467
- <T extends ElementType, P extends RecipeFn>(component: T, recipeFn: P, options?: JsxFactoryOptions<JsxRecipeProps<T, P['__type']>>): JsxElement<T, P['__type']>
1468
- }
1469
-
1470
- export type JsxElements = {
1471
- [K in keyof JSX.IntrinsicElements]: ${componentName}<K, {}>
1472
- }
1473
-
1474
- export type ${upperName} = JsxFactory & JsxElements
1475
-
1476
- export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
1477
-
1478
- export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
1479
- `
1480
- };
1481
- }
1482
- //#endregion
1483
- //#region src/artifacts/preact-jsx/create-style-context.ts
1484
- function generatePreactCreateStyleContext(ctx) {
1485
- const { factoryName } = ctx.jsx;
1486
- return {
1487
- js: outdent.outdent`
1488
- ${ctx.file.import("cx, css, sva", "../css/index")}
1489
- ${ctx.file.import(factoryName, "./factory")}
1490
- ${ctx.file.import("getDisplayName", "./factory-helper")}
1491
- import { createContext } from 'preact'
1492
- import { useContext } from 'preact/hooks'
1493
- import { createElement, forwardRef } from 'preact/compat'
1494
-
1495
- function createSafeContext(contextName) {
1496
- const Context = createContext(undefined)
1497
- const useStyleContext = (componentName, slot) => {
1498
- const context = useContext(Context)
1499
- if (context === undefined) {
1500
- const componentInfo = componentName ? \`Component "\${componentName}"\` : 'A component'
1501
- const slotInfo = slot ? \` (slot: "\${slot}")\` : ''
1502
-
1503
- throw new Error(
1504
- \`\${componentInfo}\${slotInfo} cannot access \${contextName} because it's missing its Provider.\`
1505
- )
1506
- }
1507
- return context
1508
- }
1509
- return [Context, useStyleContext]
1510
- }
1511
-
1512
- export function createStyleContext(recipe) {
1513
- const isConfigRecipe = '__recipe__' in recipe
1514
- const recipeName = isConfigRecipe && recipe.__name__ ? recipe.__name__ : undefined
1515
- const contextName = recipeName ? \`createStyleContext("\${recipeName}")\` : 'createStyleContext'
1516
-
1517
- const [StyleContext, useStyleContext] = createSafeContext(contextName)
1518
- const svaFn = isConfigRecipe ? recipe : sva(recipe.config)
1519
-
1520
- const getResolvedProps = (props, slotStyles) => {
1521
- const { unstyled, ...restProps } = props
1522
- if (unstyled) return restProps
1523
- if (isConfigRecipe) {
1524
- return { ...restProps, className: cx(slotStyles, restProps.className) }
1525
- }
1526
- ${outdent.outdent.string((0, ts_pattern.match)(ctx.config.jsxStyleProps).with("all", () => `return { ...slotStyles, ...restProps }`).with("minimal", () => `return { ...restProps, css: css.raw(slotStyles, restProps.css) }`).with("none", () => `return { ...restProps, className: cx(css(slotStyles), restProps.className) }`).otherwise(() => `return restProps`))}
1527
- }
1528
-
1529
- const withRootProvider = (Component, options) => {
1530
- const WithRootProvider = (props) => {
1531
- const [variantProps, otherProps] = svaFn.splitVariantProps(props)
1532
-
1533
- const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
1534
- slotStyles._classNameMap = svaFn.classNameMap
1535
-
1536
- const mergedProps = options?.defaultProps
1537
- ? { ...options.defaultProps, ...otherProps }
1538
- : otherProps
1539
-
1540
- return createElement(StyleContext.Provider, {
1541
- value: slotStyles,
1542
- children: createElement(Component, mergedProps)
1543
- })
1544
- }
1545
-
1546
- const componentName = getDisplayName(Component)
1547
- WithRootProvider.displayName = \`withRootProvider(\${componentName})\`
1548
-
1549
- return WithRootProvider
1550
- }
1551
-
1552
- const withProvider = (Component, slot, options) => {
1553
- const StyledComponent = ${factoryName}(Component, {}, options)
1554
-
1555
- const WithProvider = forwardRef(function WithProvider(props, ref) {
1556
- const [variantProps, restProps] = svaFn.splitVariantProps(props)
1557
-
1558
- const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
1559
- slotStyles._classNameMap = svaFn.classNameMap
1560
-
1561
- const propsWithClass = { ...restProps, className: restProps.className ?? options?.defaultProps?.className }
1562
- const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
1563
- return createElement(StyleContext.Provider, {
1564
- value: slotStyles,
1565
- children: createElement(StyledComponent, {
1566
- ...resolvedProps,
1567
- className: cx(resolvedProps.className, slotStyles._classNameMap[slot]),
1568
- ref,
1569
- })
1570
- })
1571
- })
1572
-
1573
- const componentName = getDisplayName(Component)
1574
- WithProvider.displayName = \`withProvider(\${componentName})\`
1575
-
1576
- return WithProvider
1577
- }
1578
-
1579
- const withContext = (Component, slot, options) => {
1580
- const StyledComponent = ${factoryName}(Component, {}, options)
1581
- const componentName = getDisplayName(Component)
1582
-
1583
- const WithContext = forwardRef(function WithContext(props, ref) {
1584
- const slotStyles = useStyleContext(componentName, slot)
1585
-
1586
- const propsWithClass = { ...props, className: props.className ?? options?.defaultProps?.className }
1587
- const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
1588
- return createElement(StyledComponent, {
1589
- ...resolvedProps,
1590
- className: cx(resolvedProps.className, slotStyles._classNameMap[slot]),
1591
- ref,
1592
- })
1593
- })
1594
-
1595
- WithContext.displayName = \`withContext(\${componentName})\`
1596
-
1597
- return WithContext
1598
- }
1599
-
1600
- return {
1601
- withRootProvider,
1602
- withProvider,
1603
- withContext,
1604
- }
1605
- }
1606
- `,
1607
- dts: outdent.outdent`
1608
- ${ctx.file.importType("SlotRecipeRuntimeFn, RecipeVariantProps", "../types/recipe")}
1609
- ${ctx.file.importType("JsxHTMLProps, JsxStyleProps, Assign", "../types/system-types")}
1610
- ${ctx.file.importType("JsxFactoryOptions, DataAttrs, AsProps", "../types/jsx")}
1611
- import type { ComponentType, ComponentProps, JSX } from 'preact/compat'
1612
-
1613
- interface UnstyledProps {
1614
- unstyled?: boolean | undefined
1615
- }
1616
-
1617
- interface WithProviderOptions<P = {}> {
1618
- defaultProps?: (Partial<P> & DataAttrs) | undefined
1619
- }
1620
-
1621
- type ElementType = JSX.ElementType
1622
-
1623
- type SvaFn<S extends string = any> = SlotRecipeRuntimeFn<S, any>
1624
- interface SlotRecipeFn {
1625
- __type: any
1626
- __slot: string
1627
- (props?: any): any
1628
- }
1629
- type SlotRecipe = SvaFn | SlotRecipeFn
1630
-
1631
- type InferSlot<R extends SlotRecipe> = R extends SlotRecipeFn ? R['__slot'] : R extends SvaFn<infer S> ? S : never
1632
-
1633
- type StyleContextProvider<T extends ElementType, R extends SlotRecipe> = ComponentType<
1634
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<RecipeVariantProps<R>, JsxStyleProps>>
1635
- >
1636
-
1637
- type StyleContextRootProvider<T extends ElementType, R extends SlotRecipe> = ComponentType<
1638
- ComponentProps<T> & UnstyledProps & RecipeVariantProps<R>
1639
- >
1640
-
1641
- type StyleContextConsumer<T extends ElementType> = ComponentType<
1642
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
1643
- >
1644
-
1645
- export interface StyleContext<R extends SlotRecipe> {
1646
- withRootProvider: <T extends ElementType>(
1647
- Component: T,
1648
- options?: WithProviderOptions<ComponentProps<T>> | undefined
1649
- ) => StyleContextRootProvider<T, R>
1650
- withProvider: <T extends ElementType>(
1651
- Component: T,
1652
- slot: InferSlot<R>,
1653
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
1654
- ) => StyleContextProvider<T, R>
1655
- withContext: <T extends ElementType>(
1656
- Component: T,
1657
- slot: InferSlot<R>,
1658
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
1659
- ) => StyleContextConsumer<T>
1660
- }
1661
-
1662
- export declare function createStyleContext<R extends SlotRecipe>(recipe: R): StyleContext<R>
1663
- `
1664
- };
1665
- }
1666
- //#endregion
1667
- //#region src/artifacts/preact-jsx/jsx.string-literal.ts
1668
- function generatePreactJsxStringLiteralFactory(ctx) {
1669
- const { factoryName, componentName } = ctx.jsx;
1670
- return { js: outdent.outdent`
1671
- import { h } from 'preact'
1672
- import { forwardRef } from 'preact/compat'
1673
- ${ctx.file.import("getDisplayName", "./factory-helper")}
1674
- ${ctx.file.import("css, cx", "../css/index")}
1675
-
1676
- function createStyledFn(Dynamic) {
1677
- const __base__ = Dynamic.__base__ || Dynamic
1678
- return function styledFn(template) {
1679
- const styles = css.raw(Dynamic.__styles__, template)
1680
-
1681
- const ${componentName} = /* @__PURE__ */ forwardRef(function ${componentName}(props, ref) {
1682
- const { as: Element = __base__, ...elementProps } = props
1683
-
1684
- function classes() {
1685
- return cx(css(styles), elementProps.className)
1686
- }
1687
-
1688
- return h(Element, {
1689
- ref,
1690
- ...elementProps,
1691
- className: classes(),
1692
- })
1693
- })
1694
-
1695
- const name = getDisplayName(__base__)
1696
-
1697
- ${componentName}.displayName = \`${factoryName}.\${name}\`
1698
- ${componentName}.__styles__ = styles
1699
- ${componentName}.__base__ = __base__
1700
-
1701
- return ${componentName}
1702
- }
1703
- }
1704
-
1705
- function createJsxFactory() {
1706
- const cache = new Map()
1707
-
1708
- return new Proxy(createStyledFn, {
1709
- apply(_, __, args) {
1710
- return createStyledFn(...args)
1711
- },
1712
- get(_, el) {
1713
- if (!cache.has(el)) {
1714
- cache.set(el, createStyledFn(el))
1715
- }
1716
- return cache.get(el)
1717
- },
1718
- })
1719
- }
1720
-
1721
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
1722
- ` };
1723
- }
1724
- //#endregion
1725
- //#region src/artifacts/preact-jsx/types.string-literal.ts
1726
- function generatePreactJsxStringLiteralTypes(ctx) {
1727
- const { factoryName, componentName, upperName, typeName } = ctx.jsx;
1728
- return {
1729
- jsxFactory: outdent.outdent`
1730
- ${ctx.file.importType(upperName, "../types/jsx")}
1731
- export declare const ${factoryName}: ${upperName}
1732
- `,
1733
- jsxType: outdent.outdent`
1734
- import type { ComponentProps, JSX } from 'preact'
1735
-
1736
- export type ElementType = JSX.ElementType
1737
-
1738
- interface Dict {
1739
- [k: string]: unknown
1740
- }
1741
-
1742
- export interface AsProps {
1743
- /**
1744
- * The element to render as
1745
- */
1746
- as?: ElementType | undefined
1747
- }
1748
-
1749
- export type ${componentName}<T extends ElementType> = {
1750
- (args: { raw: readonly string[] | ArrayLike<string> }): (props: ComponentProps<T> & AsProps) => JSX.Element
1751
- displayName?: string | undefined
1752
- }
1753
-
1754
- export interface JsxFactory {
1755
- <T extends ElementType>(component: T): ${componentName}<T>
1756
- }
1757
-
1758
- export type JsxElements = {
1759
- [K in keyof JSX.IntrinsicElements]: ${componentName}<K>
1760
- }
1761
-
1762
- export type ${upperName} = JsxFactory & JsxElements
1763
-
1764
- export type ${typeName}<T extends ElementType> = ComponentProps<T>
1765
- `
1766
- };
1767
- }
1768
- //#endregion
1769
- //#region src/artifacts/qwik-jsx/jsx.ts
1770
- function generateQwikJsxFactory(ctx) {
1771
- const { factoryName, componentName } = ctx.jsx;
1772
- return { js: outdent.outdent`
1773
- import { h } from '@builder.io/qwik'
1774
- ${ctx.file.import("defaultShouldForwardProp, composeShouldForwardProps, composeCvaFn, getDisplayName", "./factory-helper")}
1775
- ${ctx.file.import("isCssProperty", "./is-valid-prop")}
1776
- ${ctx.file.import("css, cx, cva", "../css/index")}
1777
- ${ctx.file.import("splitProps, normalizeHTMLProps", "../helpers")}
1778
-
1779
- function styledFn(Dynamic, configOrCva = {}, options = {}) {
1780
- const cvaFn = configOrCva.__cva__ || configOrCva.__recipe__ ? configOrCva : cva(configOrCva)
1781
-
1782
- const forwardFn = options.shouldForwardProp || defaultShouldForwardProp
1783
- const shouldForwardProp = (prop) => {
1784
- if (options.forwardProps?.includes(prop)) return true
1785
- return forwardFn(prop, cvaFn.variantKeys)
1786
- }
1787
-
1788
- const defaultProps = Object.assign(
1789
- options.dataAttr && configOrCva.__name__ ? { 'data-recipe': configOrCva.__name__ } : {},
1790
- options.defaultProps,
1791
- )
1792
-
1793
- const __cvaFn__ = composeCvaFn(Dynamic.__cva__, cvaFn)
1794
- const __shouldForwardProps__ = composeShouldForwardProps(Dynamic, shouldForwardProp)
1795
- const __base__ = Dynamic.__base__ || Dynamic
1796
-
1797
- const ${componentName} = function ${componentName}(props) {
1798
- const { as: Element = __base__, unstyled, children, className, ...restProps } = props
1799
-
1800
- const combinedProps = Object.assign({}, defaultProps, restProps)
1801
-
1802
- const [htmlProps, forwardedProps, variantProps, styleProps, elementProps] =
1803
- splitProps(combinedProps, normalizeHTMLProps.keys, __shouldForwardProps__, __cvaFn__.variantKeys, isCssProperty)
1804
-
1805
- const { css: cssStyles, ...propStyles } = styleProps
1806
-
1807
- function recipeClass() {
1808
- const { css: cssStyles, ...propStyles } = styleProps
1809
- const compoundVariantStyles = __cvaFn__.__getCompoundVariantCss__?.(variantProps);
1810
- return cx(__cvaFn__(variantProps, false), css(compoundVariantStyles, propStyles, cssStyles), combinedProps.class, className)
1811
- }
1812
-
1813
- function cvaClass() {
1814
- const { css: cssStyles, ...propStyles } = styleProps
1815
- const cvaStyles = __cvaFn__.raw(variantProps)
1816
- return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.class, className)
1817
- }
1818
-
1819
- const classes = () => {
1820
- if (unstyled) {
1821
- const { css: cssStyles, ...propStyles } = styleProps
1822
- return cx(css(propStyles, cssStyles), combinedProps.class, className)
1823
- }
1824
- return configOrCva.__recipe__ ? recipeClass() : cvaClass()
1825
- }
1826
-
1827
- return h(Element, {
1828
- ...forwardedProps,
1829
- ...elementProps,
1830
- ...normalizeHTMLProps(htmlProps),
1831
- class: classes(),
1832
- }, children ?? combinedProps.children)
1833
- }
1834
-
1835
- const name = getDisplayName(__base__)
1836
-
1837
- ${componentName}.displayName = \`${factoryName}.\${name}\`
1838
- ${componentName}.__cva__ = __cvaFn__
1839
- ${componentName}.__base__ = __base__
1840
- ${componentName}.__shouldForwardProps__ = shouldForwardProp
1841
-
1842
- return ${componentName}
1843
- }
1844
-
1845
- function createJsxFactory() {
1846
- const cache = new Map()
1847
-
1848
- return new Proxy(styledFn, {
1849
- apply(_, __, args) {
1850
- return styledFn(...args)
1851
- },
1852
- get(_, el) {
1853
- if (!cache.has(el)) {
1854
- cache.set(el, styledFn(el))
1855
- }
1856
- return cache.get(el)
1857
- },
1858
- })
1859
- }
1860
-
1861
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
1862
-
1863
- ` };
1864
- }
1865
- //#endregion
1866
- //#region src/artifacts/qwik-jsx/pattern.ts
1867
- function generateQwikJsxPattern(ctx, filters) {
1868
- const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx;
1869
- return ctx.patterns.filterDetails(filters).map((pattern) => {
1870
- const { upperName, styleFnName, dashName, jsxName, props, blocklistType } = pattern;
1871
- const { description, jsxElement = "div", deprecated } = pattern.config;
1872
- return {
1873
- name: dashName,
1874
- js: outdent.outdent`
1875
- import { h } from '@builder.io/qwik'
1876
- ${jsxStyleProps === "minimal" ? ctx.file.import("mergeCss", "../css/css") : ""}
1877
- ${ctx.file.import("splitProps", "../helpers")}
1878
- ${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
1879
- ${ctx.file.import(factoryName, "./factory")}
1880
-
1881
- export const ${jsxName} = /* @__PURE__ */ function ${jsxName}(props) {
1882
- ${(0, ts_pattern.match)(jsxStyleProps).with("none", () => outdent.outdent`
1883
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
1884
-
1885
- const styleProps = ${styleFnName}(patternProps)
1886
- const mergedProps = { ref, ...restProps, css: styleProps }
1887
-
1888
- return h(${factoryName}.${jsxElement}, mergedProps)
1889
- `).with("minimal", () => outdent.outdent`
1890
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
1891
-
1892
- const styleProps = ${styleFnName}(patternProps)
1893
- const cssProps = { css: mergeCss(styleProps, props.css) }
1894
- const mergedProps = { ...restProps, ...cssProps }
1895
-
1896
- return h(${factoryName}.${jsxElement}, mergedProps)
1897
- `).with("all", () => outdent.outdent`
1898
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
1899
-
1900
- const styleProps = ${styleFnName}(patternProps)
1901
- const mergedProps = { ...styleProps, ...restProps }
1902
-
1903
- return h(${factoryName}.${jsxElement}, mergedProps)
1904
- `).exhaustive()}
1905
- }
1906
- `,
1907
- dts: outdent.outdent`
1908
- import type { Component } from '@builder.io/qwik'
1909
- ${ctx.file.importType(`${upperName}Properties`, `../patterns/${dashName}`)}
1910
- ${ctx.file.importType(typeName, "../types/jsx")}
1911
- ${ctx.file.importType("Assign, DistributiveOmit", "../types/system-types")}
1912
-
1913
- export interface ${upperName}Props extends Assign<${typeName}<'${jsxElement}'>, DistributiveOmit<${upperName}Properties, ${blocklistType || "\"\""}>> {}
1914
-
1915
- ${ctx.file.jsDocComment(description, { deprecated })}
1916
- export declare const ${jsxName}: Component<${upperName}Props>
1917
- `
1918
- };
1919
- });
1920
- }
1921
- //#endregion
1922
- //#region src/artifacts/qwik-jsx/types.ts
1923
- function generateQwikJsxTypes(ctx) {
1924
- const { factoryName, componentName, upperName, typeName, variantName } = ctx.jsx;
1925
- return {
1926
- jsxFactory: outdent.outdent`
1927
- ${ctx.file.importType(upperName, "../types/jsx")}
1928
- export declare const ${factoryName}: ${upperName}
1929
- `,
1930
- jsxType: outdent.outdent`
1931
- import type { Component, QwikIntrinsicElements } from '@builder.io/qwik'
1932
- ${ctx.file.importType("RecipeDefinition, RecipeSelection, RecipeVariantRecord", "./recipe")}
1933
- ${ctx.file.importType("Assign, DistributiveOmit, DistributiveUnion, JsxStyleProps, PatchedHTMLProps, Pretty", "./system-types")}
1934
-
1935
- export type ElementType = keyof QwikIntrinsicElements | Component<any>
1936
-
1937
- export type ComponentProps<T extends ElementType> = T extends keyof QwikIntrinsicElements
1938
- ? QwikIntrinsicElements[T]
1939
- : T extends Component<infer P>
1940
- ? P
1941
- : never
1942
-
1943
- interface Dict {
1944
- [k: string]: unknown
1945
- }
1946
-
1947
- export type DataAttrs = Record<\`data-\${string}\`, unknown>
1948
-
1949
- export interface UnstyledProps {
1950
- /**
1951
- * Whether to remove recipe styles
1952
- */
1953
- unstyled?: boolean | undefined
1954
- }
1955
-
1956
- export interface AsProps {
1957
- /**
1958
- * The element to render as
1959
- */
1960
- as?: ElementType | undefined
1961
- }
1962
-
1963
- export interface ${componentName}<T extends ElementType, P extends Dict = {}> extends Component<Assign<ComponentProps<T> & UnstyledProps & AsProps, Assign<PatchedHTMLProps, Assign<JsxStyleProps, P>>>> {}
1964
-
1965
- interface RecipeFn {
1966
- __type: any
1967
- }
1968
-
1969
- export interface JsxFactoryOptions<TProps extends Dict> {
1970
- dataAttr?: boolean
1971
- defaultProps?: Partial<TProps> & DataAttrs
1972
- shouldForwardProp?: (prop: string, variantKeys: string[]) => boolean
1973
- forwardProps?: string[]
1974
- }
1975
-
1976
- export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, P>;
1977
-
1978
- export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
1979
- ? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
1980
- : ${componentName}<T, P>
1981
-
1982
- export interface JsxFactory {
1983
- <T extends ElementType>(component: T): ${componentName}<T, {}>
1984
- <T extends ElementType, P extends RecipeVariantRecord>(component: T, recipe: RecipeDefinition<P>, options?: JsxFactoryOptions<JsxRecipeProps<T, RecipeSelection<P>>>): JsxElement<
1985
- T,
1986
- RecipeSelection<P>
1987
- >
1988
- <T extends ElementType, P extends RecipeFn>(component: T, recipeFn: P, options?: JsxFactoryOptions<JsxRecipeProps<T, P['__type']>>): JsxElement<T, P['__type']>
1989
- }
1990
-
1991
- export type JsxElements = {
1992
- [K in keyof QwikIntrinsicElements]: ${componentName}<K, {}>
1993
- }
1994
-
1995
- export type ${upperName} = JsxFactory & JsxElements
1996
-
1997
- export type ${typeName}<T extends ElementType> = Assign<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
1998
-
1999
- export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
2000
- `
2001
- };
2002
- }
2003
- //#endregion
2004
- //#region src/artifacts/qwik-jsx/jsx.string-literal.ts
2005
- function generateQwikJsxStringLiteralFactory(ctx) {
2006
- const { factoryName, componentName } = ctx.jsx;
2007
- return { js: outdent.outdent`
2008
- import { h } from '@builder.io/qwik'
2009
- ${ctx.file.import("getDisplayName", "./factory-helper")}
2010
- ${ctx.file.import("css, cx", "../css/index")}
2011
-
2012
- function createStyledFn(Dynamic) {
2013
- const __base__ = Dynamic.__base__ || Dynamic
2014
- return function styledFn(template) {
2015
- const styles = css.raw(Dynamic.__styles__, template)
2016
-
2017
- const ${componentName} = (props) => {
2018
- const { as: Element = __base__, ...elementProps } = props
2019
-
2020
- function classes() {
2021
- return cx(css(styles), elementProps.className)
2022
- }
2023
-
2024
- return h(Element, {
2025
- ...elementProps,
2026
- className: classes(),
2027
- })
2028
- }
2029
-
2030
- const name = getDisplayName(__base__)
2031
-
2032
- ${componentName}.displayName = \`${factoryName}.\${name}\`
2033
- ${componentName}.__styles__ = styles
2034
- ${componentName}.__base__ = __base__
2035
-
2036
- return ${componentName}
2037
- }
2038
- }
2039
-
2040
- function createJsxFactory() {
2041
- const cache = new Map()
2042
-
2043
- return new Proxy(createStyledFn, {
2044
- apply(_, __, args) {
2045
- return createStyledFn(...args)
2046
- },
2047
- get(_, el) {
2048
- if (!cache.has(el)) {
2049
- cache.set(el, createStyledFn(el))
2050
- }
2051
- return cache.get(el)
2052
- },
2053
- })
2054
- }
2055
-
2056
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
2057
-
2058
- ` };
2059
- }
2060
- //#endregion
2061
- //#region src/artifacts/qwik-jsx/types.string-literal.ts
2062
- function generateQwikJsxStringLiteralTypes(ctx) {
2063
- const { factoryName, componentName, upperName, typeName } = ctx.jsx;
2064
- return {
2065
- jsxFactory: outdent.outdent`
2066
- ${ctx.file.importType(upperName, "../types/jsx")}
2067
- export declare const ${factoryName}: ${upperName}
2068
- `,
2069
- jsxType: outdent.outdent`
2070
- import type { Component, QwikIntrinsicElements } from '@builder.io/qwik'
2071
-
2072
- export type ElementType = keyof QwikIntrinsicElements | Component<any>
2073
-
2074
- export type ComponentProps<T extends ElementType> = T extends keyof QwikIntrinsicElements
2075
- ? QwikIntrinsicElements[T]
2076
- : T extends Component<infer P>
2077
- ? P
2078
- : never
2079
-
2080
- interface Dict {
2081
- [k: string]: unknown
2082
- }
2083
-
2084
- export interface AsProps {
2085
- /**
2086
- * The element to render as
2087
- */
2088
- as?: ElementType | undefined
2089
- }
2090
-
2091
- export type ${componentName}<T extends ElementType> = {
2092
- (args: { raw: readonly string[] | ArrayLike<string> }): (props: ComponentProps<T> & AsProps) => JSX.Element
2093
- }
2094
-
2095
- export interface JsxFactory {
2096
- <T extends ElementType>(component: T): ${componentName}<T>
2097
- }
2098
-
2099
- export type JsxElements = {
2100
- [K in keyof QwikIntrinsicElements]: ${componentName}<K>
2101
- }
2102
-
2103
- export type ${upperName} = JsxFactory & JsxElements
2104
-
2105
- export type ${typeName}<T extends ElementType> = ComponentProps<T>
2106
- `
2107
- };
2108
- }
2109
- //#endregion
2110
- //#region src/artifacts/react-jsx/jsx.ts
2111
- function generateReactJsxFactory(ctx) {
2112
- const { factoryName, componentName } = ctx.jsx;
2113
- return { js: outdent.outdent`
2114
- import { createElement, forwardRef } from 'react'
2115
- ${ctx.file.import("css, cx, cva", "../css/index")}
2116
- ${ctx.file.import("defaultShouldForwardProp, composeShouldForwardProps, composeCvaFn, getDisplayName", "./factory-helper")}
2117
- ${ctx.file.import("splitProps, normalizeHTMLProps", "../helpers")}
2118
- ${ctx.file.import("isCssProperty", "./is-valid-prop")}
2119
-
2120
- function styledFn(Dynamic, configOrCva = {}, options = {}) {
2121
- const cvaFn = configOrCva.__cva__ || configOrCva.__recipe__ ? configOrCva : cva(configOrCva)
2122
-
2123
- const forwardFn = options.shouldForwardProp || defaultShouldForwardProp
2124
- const shouldForwardProp = (prop) => {
2125
- if (options.forwardProps?.includes(prop)) return true
2126
- return forwardFn(prop, cvaFn.variantKeys)
2127
- }
2128
-
2129
- const defaultProps = Object.assign(
2130
- options.dataAttr && configOrCva.__name__ ? { 'data-recipe': configOrCva.__name__ } : {},
2131
- options.defaultProps,
2132
- )
2133
-
2134
- const __cvaFn__ = composeCvaFn(Dynamic.__cva__, cvaFn)
2135
- const __shouldForwardProps__ = composeShouldForwardProps(Dynamic, shouldForwardProp)
2136
- const __base__ = Dynamic.__base__ || Dynamic
2137
-
2138
- const ${componentName} = /* @__PURE__ */ forwardRef(function ${componentName}(props, ref) {
2139
- const { as: Element = __base__, unstyled, children, ...restProps } = props
2140
-
2141
- // Not memoized, deliberately. \`restProps\` is rest destructuring, so it is a fresh
2142
- // object on every render and a dependency on it can never match — a memo here is a
2143
- // guaranteed miss that still costs a hook slot, a deps array and a retained cell.
2144
- const combinedProps = Object.assign({}, defaultProps, restProps)
2145
-
2146
- const [htmlProps, forwardedProps, variantProps, styleProps, elementProps] =
2147
- splitProps(combinedProps, normalizeHTMLProps.keys, __shouldForwardProps__, __cvaFn__.variantKeys, isCssProperty)
2148
-
2149
- function recipeClass() {
2150
- const { css: cssStyles, ...propStyles } = styleProps
2151
- const compoundVariantStyles = __cvaFn__.__getCompoundVariantCss__?.(variantProps)
2152
- return cx(__cvaFn__(variantProps, false), css(compoundVariantStyles, propStyles, cssStyles), combinedProps.className)
2153
- }
2154
-
2155
- function cvaClass() {
2156
- const { css: cssStyles, ...propStyles } = styleProps
2157
- const cvaStyles = __cvaFn__.raw(variantProps)
2158
- return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.className)
2159
- }
2160
-
2161
- const classes = () => {
2162
- if (unstyled) {
2163
- const { css: cssStyles, ...propStyles } = styleProps
2164
- return cx(css(propStyles, cssStyles), combinedProps.className)
2165
- }
2166
- return configOrCva.__recipe__ ? recipeClass() : cvaClass()
2167
- }
2168
-
2169
- return createElement(Element, {
2170
- ref,
2171
- ...forwardedProps,
2172
- ...elementProps,
2173
- ...normalizeHTMLProps(htmlProps),
2174
- className: classes(),
2175
- }, children ?? combinedProps.children)
2176
- })
2177
-
2178
- const name = getDisplayName(__base__)
2179
-
2180
- ${componentName}.displayName = \`${factoryName}.\${name}\`
2181
- ${componentName}.__cva__ = __cvaFn__
2182
- ${componentName}.__base__ = __base__
2183
- ${componentName}.__shouldForwardProps__ = shouldForwardProp
2184
-
2185
- return ${componentName}
2186
- }
2187
-
2188
- function createJsxFactory() {
2189
- const cache = new Map()
2190
-
2191
- return new Proxy(styledFn, {
2192
- apply(_, __, args) {
2193
- return styledFn(...args)
2194
- },
2195
- get(_, el) {
2196
- if (!cache.has(el)) {
2197
- cache.set(el, styledFn(el))
2198
- }
2199
- return cache.get(el)
2200
- },
2201
- })
2202
- }
2203
-
2204
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
2205
-
2206
- ` };
2207
- }
2208
- //#endregion
2209
- //#region src/artifacts/react-jsx/pattern.ts
2210
- function generateReactJsxPattern(ctx, filters) {
2211
- const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx;
2212
- return ctx.patterns.filterDetails(filters).map((pattern) => {
2213
- const { upperName, styleFnName, dashName, jsxName, props, blocklistType } = pattern;
2214
- const { description, jsxElement = "div", deprecated } = pattern.config;
2215
- return {
2216
- name: dashName,
2217
- js: outdent.outdent`
2218
- import { createElement, forwardRef } from 'react'
2219
- ${jsxStyleProps === "minimal" ? ctx.file.import("mergeCss", "../css/css") : ""}
2220
- ${ctx.file.import("splitProps", "../helpers")}
2221
- ${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
2222
- ${ctx.file.import(factoryName, "./factory")}
2223
-
2224
- export const ${jsxName} = /* @__PURE__ */ forwardRef(function ${jsxName}(props, ref) {
2225
- ${(0, ts_pattern.match)(jsxStyleProps).with("none", () => outdent.outdent`
2226
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
2227
-
2228
- const styleProps = ${styleFnName}(patternProps)
2229
- const mergedProps = { ref, ...restProps, css: styleProps }
2230
-
2231
- return createElement(${factoryName}.${jsxElement}, mergedProps)
2232
- `).with("minimal", () => outdent.outdent`
2233
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
2234
-
2235
- const styleProps = ${styleFnName}(patternProps)
2236
- const cssProps = { css: mergeCss(styleProps, props.css) }
2237
- const mergedProps = { ref, ...restProps, ...cssProps }
2238
-
2239
- return createElement(${factoryName}.${jsxElement}, mergedProps)
2240
- `).with("all", () => outdent.outdent`
2241
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
2242
-
2243
- const styleProps = ${styleFnName}(patternProps)
2244
- const mergedProps = { ref, ...styleProps, ...restProps }
2245
-
2246
- return createElement(${factoryName}.${jsxElement}, mergedProps)
2247
- `).exhaustive()}
2248
- })
2249
- `,
2250
- dts: outdent.outdent`
2251
- import type { FunctionComponent } from 'react'
2252
- ${ctx.file.importType(`${upperName}Properties`, `../patterns/${dashName}`)}
2253
- ${ctx.file.importType(typeName, "../types/jsx")}
2254
- ${ctx.file.importType("DistributiveOmit", "../types/system-types")}
2255
-
2256
- export interface ${upperName}Props extends ${upperName}Properties, DistributiveOmit<${typeName}<'${jsxElement}'>, keyof ${upperName}Properties ${blocklistType}> {}
2257
-
2258
- ${ctx.file.jsDocComment(description, { deprecated })}
2259
- export declare const ${jsxName}: FunctionComponent<${upperName}Props>
2260
- `
2261
- };
2262
- });
2263
- }
2264
- //#endregion
2265
- //#region src/artifacts/react-jsx/types.ts
2266
- function generateReactJsxTypes(ctx) {
2267
- const { factoryName, componentName, upperName, typeName, variantName } = ctx.jsx;
2268
- return {
2269
- jsxFactory: outdent.outdent`
2270
- ${ctx.file.importType(upperName, "../types/jsx")}
2271
- export declare const ${factoryName}: ${upperName}
2272
- `,
2273
- jsxType: outdent.outdent`
2274
- import type { ElementType, JSX, ComponentPropsWithRef, ComponentType, Component } from 'react'
2275
- ${ctx.file.importType("RecipeDefinition, RecipeSelection, RecipeVariantRecord", "./recipe")}
2276
- ${ctx.file.importType("Assign, DistributiveOmit, DistributiveUnion, JsxHTMLProps, JsxStyleProps, Pretty", "./system-types")}
2277
-
2278
- interface Dict {
2279
- [k: string]: unknown
2280
- }
2281
-
2282
- export type DataAttrs = Record<\`data-\${string}\`, unknown>
2283
-
2284
- export interface UnstyledProps {
2285
- /**
2286
- * Whether to remove recipe styles
2287
- */
2288
- unstyled?: boolean | undefined
2289
- }
2290
-
2291
- export interface AsProps {
2292
- /**
2293
- * The element to render as
2294
- */
2295
- as?: ElementType | undefined
2296
- }
2297
-
2298
- export type ComponentProps<T extends ElementType> = T extends ComponentType<infer P> | Component<infer P>
2299
- ? JSX.LibraryManagedAttributes<T, P>
2300
- : ComponentPropsWithRef<T>
2301
-
2302
- export interface ${componentName}<T extends ElementType, P extends Dict = {}> {
2303
- (props: JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<JsxStyleProps, P>>): JSX.Element
2304
- displayName?: string | undefined
2305
- }
2306
-
2307
- interface RecipeFn {
2308
- __type: any
2309
- }
2310
-
2311
- export interface JsxFactoryOptions<TProps extends Dict> {
2312
- dataAttr?: boolean
2313
- defaultProps?: Partial<TProps> & DataAttrs
2314
- shouldForwardProp?: (prop: string, variantKeys: string[]) => boolean
2315
- forwardProps?: string[]
2316
- }
2317
-
2318
- export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, P>;
2319
-
2320
- export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
2321
- ? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
2322
- : ${componentName}<T, P>
2323
-
2324
- export interface JsxFactory {
2325
- <T extends ElementType>(component: T): ${componentName}<T, {}>
2326
- <T extends ElementType, P extends RecipeVariantRecord>(component: T, recipe: RecipeDefinition<P>, options?: JsxFactoryOptions<JsxRecipeProps<T, RecipeSelection<P>>>): JsxElement<
2327
- T,
2328
- RecipeSelection<P>
2329
- >
2330
- <T extends ElementType, P extends RecipeFn>(component: T, recipeFn: P, options?: JsxFactoryOptions<JsxRecipeProps<T, P['__type']>>): JsxElement<T, P['__type']>
2331
- }
2332
-
2333
- export type JsxElements = {
2334
- [K in keyof JSX.IntrinsicElements]: ${componentName}<K, {}>
2335
- }
2336
-
2337
- export type ${upperName} = JsxFactory & JsxElements
2338
-
2339
- export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
2340
-
2341
- export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
2342
- `
2343
- };
2344
- }
2345
- //#endregion
2346
- //#region src/artifacts/react-jsx/create-style-context.ts
2347
- function generateReactCreateStyleContext(ctx) {
2348
- const { factoryName } = ctx.jsx;
2349
- return {
2350
- js: outdent.outdent`'use client'\n
2351
- ${ctx.file.import("cx, css, sva", "../css/index")}
2352
- ${ctx.file.import(factoryName, "./factory")}
2353
- ${ctx.file.import("getDisplayName", "./factory-helper")}
2354
- import { createContext, useContext, createElement, forwardRef } from 'react'
2355
-
2356
- function createSafeContext(contextName) {
2357
- const Context = createContext(undefined)
2358
- const useStyleContext = (componentName, slot) => {
2359
- const context = useContext(Context)
2360
- if (context === undefined) {
2361
- const componentInfo = componentName ? \`Component "\${componentName}"\` : 'A component'
2362
- const slotInfo = slot ? \` (slot: "\${slot}")\` : ''
2363
-
2364
- throw new Error(
2365
- \`\${componentInfo}\${slotInfo} cannot access \${contextName} because it's missing its Provider.\`
2366
- )
2367
- }
2368
- return context
2369
- }
2370
- return [Context, useStyleContext]
2371
- }
2372
-
2373
- export function createStyleContext(recipe) {
2374
- const isConfigRecipe = '__recipe__' in recipe
2375
- const recipeName = isConfigRecipe && recipe.__name__ ? recipe.__name__ : undefined
2376
- const contextName = recipeName ? \`createStyleContext("\${recipeName}")\` : 'createStyleContext'
2377
-
2378
- const [StyleContext, useStyleContext] = createSafeContext(contextName)
2379
- const svaFn = isConfigRecipe ? recipe : sva(recipe.config)
2380
-
2381
- const getResolvedProps = (props, slotStyles) => {
2382
- const { unstyled, ...restProps } = props
2383
- if (unstyled) return restProps
2384
- if (isConfigRecipe) {
2385
- return { ...restProps, className: cx(slotStyles, restProps.className) }
2386
- }
2387
- ${outdent.outdent.string((0, ts_pattern.match)(ctx.config.jsxStyleProps).with("all", () => `return { ...slotStyles, ...restProps }`).with("minimal", () => `return { ...restProps, css: css.raw(slotStyles, restProps.css) }`).with("none", () => `return { ...restProps, className: cx(css(slotStyles), restProps.className) }`).otherwise(() => `return restProps`))}
2388
- }
2389
-
2390
- const withRootProvider = (Component, options) => {
2391
- const WithRootProvider = (props) => {
2392
- const [variantProps, otherProps] = svaFn.splitVariantProps(props)
2393
-
2394
- const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
2395
- slotStyles._classNameMap = svaFn.classNameMap
2396
-
2397
- const mergedProps = options?.defaultProps
2398
- ? { ...options.defaultProps, ...otherProps }
2399
- : otherProps
2400
-
2401
- return createElement(StyleContext.Provider, {
2402
- value: slotStyles,
2403
- children: createElement(Component, mergedProps)
2404
- })
2405
- }
2406
-
2407
- const componentName = getDisplayName(Component)
2408
- WithRootProvider.displayName = \`withRootProvider(\${componentName})\`
2409
-
2410
- return WithRootProvider
2411
- }
2412
-
2413
- const withProvider = (Component, slot, options) => {
2414
- const StyledComponent = ${factoryName}(Component, {}, options)
2415
-
2416
- const WithProvider = forwardRef((props, ref) => {
2417
- const [variantProps, restProps] = svaFn.splitVariantProps(props)
2418
-
2419
- const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
2420
- slotStyles._classNameMap = svaFn.classNameMap
2421
-
2422
- const propsWithClass = { ...restProps, className: restProps.className ?? options?.defaultProps?.className }
2423
- const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
2424
- return createElement(StyleContext.Provider, {
2425
- value: slotStyles,
2426
- children: createElement(StyledComponent, {
2427
- ...resolvedProps,
2428
- className: cx(resolvedProps.className, slotStyles._classNameMap[slot]),
2429
- ref,
2430
- })
2431
- })
2432
- })
2433
-
2434
- const componentName = getDisplayName(Component)
2435
- WithProvider.displayName = \`withProvider(\${componentName})\`
2436
-
2437
- return WithProvider
2438
- }
2439
-
2440
- const withContext = (Component, slot, options) => {
2441
- const StyledComponent = ${factoryName}(Component, {}, options)
2442
- const componentName = getDisplayName(Component)
2443
-
2444
- const WithContext = forwardRef((props, ref) => {
2445
- const slotStyles = useStyleContext(componentName, slot)
2446
-
2447
- const propsWithClass = { ...props, className: props.className ?? options?.defaultProps?.className }
2448
- const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
2449
- return createElement(StyledComponent, {
2450
- ...resolvedProps,
2451
- className: cx(resolvedProps.className, slotStyles._classNameMap[slot]),
2452
- ref,
2453
- })
2454
- })
2455
-
2456
- WithContext.displayName = \`withContext(\${componentName})\`
2457
-
2458
- return WithContext
2459
- }
2460
-
2461
- return {
2462
- withRootProvider,
2463
- withProvider,
2464
- withContext,
2465
- }
2466
- }
2467
- `,
2468
- dts: outdent.outdent`
2469
- ${ctx.file.importType("SlotRecipeRuntimeFn, RecipeVariantProps", "../types/recipe")}
2470
- ${ctx.file.importType("JsxHTMLProps, JsxStyleProps, Assign", "../types/system-types")}
2471
- ${ctx.file.importType("JsxFactoryOptions, ComponentProps, DataAttrs, AsProps", "../types/jsx")}
2472
- import type { ComponentType, ElementType } from 'react'
2473
-
2474
- interface UnstyledProps {
2475
- unstyled?: boolean | undefined
2476
- }
2477
-
2478
- type SvaFn<S extends string = any> = SlotRecipeRuntimeFn<S, any>
2479
- interface SlotRecipeFn {
2480
- __type: any
2481
- __slot: string
2482
- (props?: any): any
2483
- }
2484
- type SlotRecipe = SvaFn | SlotRecipeFn
2485
-
2486
- type InferSlot<R extends SlotRecipe> = R extends SlotRecipeFn ? R['__slot'] : R extends SvaFn<infer S> ? S : never
2487
-
2488
- interface WithProviderOptions<P = {}> {
2489
- defaultProps?: (Partial<P> & DataAttrs) | undefined
2490
- }
2491
-
2492
- type StyleContextProvider<T extends ElementType, R extends SlotRecipe> = ComponentType<
2493
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<RecipeVariantProps<R>, JsxStyleProps>>
2494
- >
2495
-
2496
- type StyleContextRootProvider<T extends ElementType, R extends SlotRecipe> = ComponentType<
2497
- ComponentProps<T> & UnstyledProps & RecipeVariantProps<R>
2498
- >
2499
-
2500
- type StyleContextConsumer<T extends ElementType> = ComponentType<
2501
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
2502
- >
2503
-
2504
- export interface StyleContext<R extends SlotRecipe> {
2505
- withRootProvider: <T extends ElementType>(
2506
- Component: T,
2507
- options?: WithProviderOptions<ComponentProps<T>> | undefined
2508
- ) => StyleContextRootProvider<T, R>
2509
- withProvider: <T extends ElementType>(
2510
- Component: T,
2511
- slot: InferSlot<R>,
2512
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
2513
- ) => StyleContextProvider<T, R>
2514
- withContext: <T extends ElementType>(
2515
- Component: T,
2516
- slot: InferSlot<R>,
2517
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
2518
- ) => StyleContextConsumer<T>
2519
- }
2520
-
2521
- export declare function createStyleContext<R extends SlotRecipe>(recipe: R): StyleContext<R>
2522
- `
2523
- };
2524
- }
2525
- //#endregion
2526
- //#region src/artifacts/react-jsx/jsx.string-literal.ts
2527
- function generateReactJsxStringLiteralFactory(ctx) {
2528
- const { factoryName, componentName } = ctx.jsx;
2529
- return { js: outdent.outdent`
2530
- import { createElement, forwardRef } from 'react'
2531
- ${ctx.file.import("getDisplayName", "./factory-helper")}
2532
- ${ctx.file.import("css, cx", "../css/index")}
2533
-
2534
- function createStyledFn(Dynamic) {
2535
- const __base__ = Dynamic.__base__ || Dynamic
2536
- return function styledFn(template) {
2537
- const styles = css.raw(Dynamic.__styles__, template)
2538
-
2539
- const ${componentName} = /* @__PURE__ */ forwardRef(function ${componentName}(props, ref) {
2540
- const { as: Element = __base__, ...elementProps } = props
2541
-
2542
- function classes() {
2543
- return cx(css(styles), elementProps.className)
2544
- }
2545
-
2546
- return createElement(Element, {
2547
- ref,
2548
- ...elementProps,
2549
- className: classes(),
2550
- })
2551
- })
2552
-
2553
- const name = getDisplayName(__base__)
2554
-
2555
- ${componentName}.displayName = \`${factoryName}.\${name}\`
2556
- ${componentName}.__styles__ = styles
2557
- ${componentName}.__base__ = __base__
2558
-
2559
- return ${componentName}
2560
- }
2561
- }
2562
-
2563
- function createJsxFactory() {
2564
- const cache = new Map()
2565
-
2566
- return new Proxy(createStyledFn, {
2567
- apply(_, __, args) {
2568
- return createStyledFn(...args)
2569
- },
2570
- get(_, el) {
2571
- if (!cache.has(el)) {
2572
- cache.set(el, createStyledFn(el))
2573
- }
2574
- return cache.get(el)
2575
- },
2576
- })
2577
- }
2578
-
2579
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
2580
- ` };
2581
- }
2582
- //#endregion
2583
- //#region src/artifacts/react-jsx/types.string-literal.ts
2584
- function generateReactJsxStringLiteralTypes(ctx) {
2585
- const { factoryName, componentName, upperName, typeName } = ctx.jsx;
2586
- return {
2587
- jsxFactory: outdent.outdent`
2588
- ${ctx.file.importType(upperName, "../types/jsx")}
2589
- export declare const ${factoryName}: ${upperName}
2590
- `,
2591
- jsxType: outdent.outdent`
2592
- import type { ComponentPropsWithoutRef, ElementType, ElementRef, JSX, Ref } from 'react'
2593
- ${ctx.file.importType("DistributiveOmit", "../types/system-types")}
2594
-
2595
- interface Dict {
2596
- [k: string]: unknown
2597
- }
2598
-
2599
- export interface AsProps {
2600
- /**
2601
- * The element to render as
2602
- */
2603
- as?: ElementType | undefined
2604
- }
2605
-
2606
- export type ComponentProps<T extends ElementType> = DistributiveOmit<ComponentPropsWithoutRef<T>, 'ref'> & {
2607
- ref?: Ref<ElementRef<T>>
2608
- } & AsProps
2609
-
2610
- export type ${componentName}<T extends ElementType> = {
2611
- (args: { raw: readonly string[] | ArrayLike<string> }): (props: ComponentProps<T>) => JSX.Element
2612
- displayName?: string | undefined
2613
- }
2614
-
2615
- export interface JsxFactory {
2616
- <T extends ElementType>(component: T): ${componentName}<T>
2617
- }
2618
-
2619
- export type JsxElements = {
2620
- [K in keyof JSX.IntrinsicElements]: ${componentName}<K>
2621
- }
2622
-
2623
- export type ${upperName} = JsxFactory & JsxElements
2624
-
2625
- export type ${typeName}<T extends ElementType> = ComponentProps<T>
2626
- `
2627
- };
2628
- }
2629
- //#endregion
2630
- //#region src/artifacts/solid-jsx/jsx.ts
2631
- function generateSolidJsxFactory(ctx) {
2632
- const { componentName, factoryName } = ctx.jsx;
2633
- return { js: outdent.outdent`
2634
- import { createMemo, mergeProps, splitProps } from 'solid-js'
2635
- import { Dynamic, createComponent } from 'solid-js/web'
2636
- ${ctx.file.import("css, cx, cva", "../css/index")}
2637
- ${ctx.file.import("normalizeHTMLProps", "../helpers")}
2638
- ${ctx.file.import("composeCvaFn, composeShouldForwardProps, defaultShouldForwardProp, getDisplayName", "./factory-helper")}
2639
- ${ctx.file.import("isCssProperty", "./is-valid-prop")}
2640
-
2641
- function styledFn(element, configOrCva = {}, options = {}) {
2642
- const cvaFn =
2643
- configOrCva.__cva__ || configOrCva.__recipe__
2644
- ? configOrCva
2645
- : cva(configOrCva)
2646
-
2647
- const forwardFn = options.shouldForwardProp || defaultShouldForwardProp
2648
- const shouldForwardProp = (prop) => {
2649
- if (options.forwardProps?.includes(prop)) return true
2650
- return forwardFn(prop, cvaFn.variantKeys)
2651
- }
2652
-
2653
- const getDefaultProps = () => {
2654
- const baseDefaults = options.dataAttr && configOrCva.__name__
2655
- ? { 'data-recipe': configOrCva.__name__ }
2656
- : {}
2657
- const defaults = typeof options.defaultProps === 'function'
2658
- ? options.defaultProps()
2659
- : options.defaultProps
2660
- return Object.assign(baseDefaults, defaults)
2661
- }
2662
-
2663
- const __cvaFn__ = composeCvaFn(element.__cva__, cvaFn)
2664
- const __shouldForwardProps__ = composeShouldForwardProps(
2665
- element,
2666
- shouldForwardProp
2667
- )
2668
-
2669
- const ${componentName} = (props) => {
2670
- const mergedProps = mergeProps(
2671
- { as: element.__base__ || element },
2672
- getDefaultProps(),
2673
- props
2674
- )
2675
-
2676
- const [localProps, restProps] = splitProps(mergedProps, [
2677
- 'as',
2678
- 'unstyled',
2679
- 'class',
2680
- 'className',
2681
- ])
2682
-
2683
- const [htmlProps, aProps] = splitProps(restProps, normalizeHTMLProps.keys)
2684
-
2685
- const forwardedKeys = createMemo(() => {
2686
- const keys = Object.keys(aProps)
2687
- return keys.filter((prop) => __shouldForwardProps__(prop))
2688
- })
2689
-
2690
- const [forwardedProps, variantProps, bProps] = splitProps(aProps, forwardedKeys(), __cvaFn__.variantKeys)
2691
-
2692
- const cssPropKeys = createMemo(() => {
2693
- const keys = Object.keys(bProps)
2694
- return keys.filter((prop) => isCssProperty(prop))
2695
- })
2696
-
2697
- const [styleProps, elementProps] = splitProps(bProps, cssPropKeys())
2698
-
2699
- function recipeClass() {
2700
- const { css: cssStyles, ...propStyles } = styleProps
2701
- const compoundVariantStyles =
2702
- __cvaFn__.__getCompoundVariantCss__?.(variantProps)
2703
- return cx(
2704
- __cvaFn__(variantProps, false),
2705
- css(compoundVariantStyles, propStyles, cssStyles),
2706
- localProps.class,
2707
- localProps.className
2708
- )
2709
- }
2710
-
2711
- function cvaClass() {
2712
- const { css: cssStyles, ...propStyles } = styleProps
2713
- const cvaStyles = __cvaFn__.raw(variantProps)
2714
- return cx(
2715
- css(cvaStyles, propStyles, cssStyles),
2716
- localProps.class,
2717
- localProps.className
2718
- )
2719
- }
2720
-
2721
- const classes = () => {
2722
- if (localProps.unstyled) {
2723
- const { css: cssStyles, ...propStyles } = styleProps
2724
- return cx(css(propStyles, cssStyles), localProps.class, localProps.className)
2725
- }
2726
- return configOrCva.__recipe__ ? recipeClass() : cvaClass()
2727
- }
2728
-
2729
- if (forwardedProps.className) {
2730
- delete forwardedProps.className
2731
- }
2732
-
2733
- return createComponent(
2734
- Dynamic,
2735
- mergeProps(forwardedProps, elementProps, normalizeHTMLProps(htmlProps), {
2736
- get component() {
2737
- return localProps.as
2738
- },
2739
- get class() {
2740
- return classes()
2741
- },
2742
- })
2743
- )
2744
- }
2745
-
2746
- const name = getDisplayName(element)
2747
-
2748
- ${componentName}.displayName = \`${factoryName}.\${name}\`
2749
- ${componentName}.__cva__ = __cvaFn__
2750
- ${componentName}.__base__ = element
2751
- ${componentName}.__shouldForwardProps__ = shouldForwardProp
2752
-
2753
- return ${componentName}
2754
- }
2755
-
2756
- function createJsxFactory() {
2757
- const cache = new Map()
2758
-
2759
- return new Proxy(styledFn, {
2760
- apply(_, __, args) {
2761
- return styledFn(...args)
2762
- },
2763
- get(_, el) {
2764
- if (!cache.has(el)) {
2765
- cache.set(el, styledFn(el))
2766
- }
2767
- return cache.get(el)
2768
- },
2769
- })
2770
- }
2771
-
2772
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
2773
- ` };
2774
- }
2775
- //#endregion
2776
- //#region src/artifacts/solid-jsx/pattern.ts
2777
- function generateSolidJsxPattern(ctx, filters) {
2778
- const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx;
2779
- return ctx.patterns.filterDetails(filters).map((pattern) => {
2780
- const { upperName, styleFnName, dashName, jsxName, props, blocklistType } = pattern;
2781
- const { description, jsxElement = "div", deprecated } = pattern.config;
2782
- return {
2783
- name: dashName,
2784
- js: outdent.outdent`
2785
- import { createMemo, mergeProps, splitProps } from 'solid-js'
2786
- import { createComponent } from 'solid-js/web'
2787
- ${jsxStyleProps === "minimal" ? ctx.file.import("mergeCss", "../css/css") : ""}
2788
- ${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
2789
- ${ctx.file.import(factoryName, "./factory")}
2790
-
2791
- export const ${jsxName} = /* @__PURE__ */ function ${jsxName}(props) {
2792
- ${(0, ts_pattern.match)(jsxStyleProps).with("none", () => outdent.outdent`
2793
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
2794
-
2795
- const cssProps = createMemo(() => {
2796
- const styleProps = ${styleFnName}(patternProps)
2797
- return { css: styleProps }
2798
- })
2799
-
2800
- const mergedProps = mergeProps(restProps, cssProps)
2801
-
2802
- return createComponent(${factoryName}.${jsxElement}, mergedProps)
2803
- `).with("minimal", () => outdent.outdent`
2804
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
2805
-
2806
- const cssProps = createMemo(() => {
2807
- const styleProps = ${styleFnName}(patternProps)
2808
- return { css: mergeCss(styleProps, props.css) }
2809
- })
2810
-
2811
- const mergedProps = mergeProps(restProps, cssProps)
2812
-
2813
- return createComponent(${factoryName}.${jsxElement}, mergedProps)
2814
- `).with("all", () => outdent.outdent`
2815
- const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
2816
-
2817
- const styleProps = ${styleFnName}(patternProps)
2818
- const mergedProps = mergeProps(styleProps, restProps)
2819
-
2820
- return createComponent(${factoryName}.${jsxElement}, mergedProps)
2821
- `).exhaustive()}
2822
- }
2823
- `,
2824
- dts: outdent.outdent`
2825
- import type { Component } from 'solid-js'
2826
- ${ctx.file.importType(`${upperName}Properties`, `../patterns/${dashName}`)}
2827
- ${ctx.file.importType(typeName, "../types/jsx")}
2828
- ${ctx.file.importType("DistributiveOmit", "../types/system-types")}
2829
-
2830
- export interface ${upperName}Props extends ${upperName}Properties, DistributiveOmit<${typeName}<'${jsxElement}'>, keyof ${upperName}Properties ${blocklistType}> {}
2831
-
2832
- ${ctx.file.jsDocComment(description, { deprecated })}
2833
- export declare const ${jsxName}: Component<${upperName}Props>
2834
- `
2835
- };
2836
- });
2837
- }
2838
- //#endregion
2839
- //#region src/artifacts/solid-jsx/types.ts
2840
- function generateSolidJsxTypes(ctx) {
2841
- const { factoryName, componentName, upperName, typeName, variantName } = ctx.jsx;
2842
- return {
2843
- jsxFactory: outdent.outdent`
2844
- ${ctx.file.importType(upperName, "../types/jsx")}
2845
- export declare const ${factoryName}: ${upperName}
2846
- `,
2847
- jsxType: outdent.outdent`
2848
- import type { Accessor, ComponentProps, Component, JSX } from 'solid-js'
2849
- ${ctx.file.importType("RecipeDefinition, RecipeSelection, RecipeVariantRecord", "./recipe")}
2850
- ${ctx.file.importType("Assign, DistributiveUnion, JsxHTMLProps, JsxStyleProps, Pretty", "./system-types")}
2851
-
2852
- interface Dict {
2853
- [k: string]: unknown
2854
- }
2855
-
2856
- export type DataAttrs = Record<\`data-\${string}\`, unknown>
2857
-
2858
- export interface UnstyledProps {
2859
- /**
2860
- * Whether to remove recipe styles
2861
- */
2862
- unstyled?: boolean | undefined
2863
- }
2864
-
2865
- export interface AsProps {
2866
- /**
2867
- * The element to render as
2868
- */
2869
- as?: ElementType | undefined
2870
- }
2871
-
2872
- export type ElementType = keyof JSX.IntrinsicElements | Component<any>
2873
-
2874
- export interface ${componentName}<T extends ElementType, P extends Dict = {}> {
2875
- (props: JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<JsxStyleProps, P>>): JSX.Element
2876
- displayName?: string | undefined
2877
- }
2878
-
2879
- interface RecipeFn {
2880
- __type: any
2881
- }
2882
-
2883
- export type MaybeAccessor<T> = T | Accessor<T>
2884
-
2885
- export interface JsxFactoryOptions<TProps extends Dict> {
2886
- dataAttr?: boolean
2887
- defaultProps?: MaybeAccessor<Partial<TProps> & DataAttrs>
2888
- shouldForwardProp?: (prop: string, variantKeys: string[]) => boolean
2889
- forwardProps?: string[]
2890
- }
2891
-
2892
- export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, P>;
2893
-
2894
- export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
2895
- ? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
2896
- : ${componentName}<T, P>
2897
-
2898
- export interface JsxFactory {
2899
- <T extends ElementType>(component: T): ${componentName}<T, {}>
2900
- <T extends ElementType, P extends RecipeVariantRecord>(component: T, recipe: RecipeDefinition<P>, options?: JsxFactoryOptions<JsxRecipeProps<T, RecipeSelection<P>>>): JsxElement<
2901
- T,
2902
- RecipeSelection<P>
2903
- >
2904
- <T extends ElementType, P extends RecipeFn>(component: T, recipeFn: P, options?: JsxFactoryOptions<JsxRecipeProps<T, P['__type']>>): JsxElement<T, P['__type']>
2905
- }
2906
-
2907
- export type JsxElements = {
2908
- [K in keyof JSX.IntrinsicElements]: ${componentName}<K, {}>
2909
- }
2910
-
2911
- export type ${upperName} = JsxFactory & JsxElements
2912
-
2913
- export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
2914
-
2915
- export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
2916
- `
2917
- };
2918
- }
2919
- //#endregion
2920
- //#region src/artifacts/solid-jsx/create-style-context.ts
2921
- function generateSolidCreateStyleContext(ctx) {
2922
- const { factoryName } = ctx.jsx;
2923
- return {
2924
- js: outdent.outdent`
2925
- ${ctx.file.import("cx, css, sva", "../css/index")}
2926
- ${ctx.file.import(factoryName, "./factory")}
2927
- ${ctx.file.import("getDisplayName", "./factory-helper")}
2928
- import { createComponent, mergeProps } from 'solid-js/web'
2929
- import { createContext, createMemo, splitProps, useContext } from 'solid-js'
2930
-
2931
- function createSafeContext(contextName) {
2932
- const Context = createContext(undefined)
2933
- const useStyleContext = (componentName, slot) => {
2934
- const context = useContext(Context)
2935
- if (context === undefined) {
2936
- const componentInfo = componentName ? \`Component "\${componentName}"\` : 'A component'
2937
- const slotInfo = slot ? \` (slot: "\${slot}")\` : ''
2938
-
2939
- throw new Error(
2940
- \`\${componentInfo}\${slotInfo} cannot access \${contextName} because it's missing its Provider.\`
2941
- )
2942
- }
2943
- return context
2944
- }
2945
- return [Context, useStyleContext]
2946
- }
2947
-
2948
- export function createStyleContext(recipe) {
2949
- const isConfigRecipe = '__recipe__' in recipe
2950
- const recipeName = isConfigRecipe && recipe.__name__ ? recipe.__name__ : undefined
2951
- const contextName = recipeName ? \`createStyleContext("\${recipeName}")\` : 'createStyleContext'
2952
-
2953
- const [StyleContext, useStyleContext] = createSafeContext(contextName)
2954
- const svaFn = isConfigRecipe ? recipe : sva(recipe.config)
2955
-
2956
- const getResolvedProps = (props, slotStyles) => {
2957
- const { unstyled, ...restProps } = props
2958
- if (unstyled) return restProps
2959
- if (isConfigRecipe) {
2960
- return { ...restProps, class: cx(slotStyles, restProps.class) }
2961
- }
2962
- ${outdent.outdent.string((0, ts_pattern.match)(ctx.config.jsxStyleProps).with("all", () => `return { ...slotStyles, ...restProps }`).with("minimal", () => `return { ...restProps, css: css.raw(slotStyles, restProps.css) }`).with("none", () => `return { ...restProps, class: cx(css(slotStyles), restProps.class) }`).otherwise(() => `return restProps`))}
2963
- }
2964
-
2965
- const withRootProvider = (Component, options) => {
2966
- const WithRootProvider = (props) => {
2967
- const [variantProps, otherProps] = svaFn.splitVariantProps(props)
2968
- const [local, propsWithoutChildren] = splitProps(otherProps, ['children'])
2969
-
2970
- const slotStyles = createMemo(() => {
2971
- const styles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
2972
- styles._classNameMap = svaFn.classNameMap
2973
- return styles
2974
- })
2975
-
2976
- const mergedProps = createMemo(() => {
2977
- if (!options?.defaultProps) return propsWithoutChildren
2978
- const defaults = typeof options.defaultProps === 'function'
2979
- ? options.defaultProps()
2980
- : options.defaultProps
2981
- return { ...defaults, ...propsWithoutChildren }
2982
- })
2983
-
2984
- return createComponent(StyleContext.Provider, {
2985
- get value() {
2986
- return slotStyles()
2987
- },
2988
- get children() {
2989
- return createComponent(
2990
- Component,
2991
- mergeProps(mergedProps, {
2992
- get children() {
2993
- return local.children
2994
- },
2995
- }),
2996
- )
2997
- },
2998
- })
2999
- }
3000
-
3001
- const componentName = getDisplayName(Component)
3002
- WithRootProvider.displayName = \`withRootProvider(\${componentName})\`
3003
- return WithRootProvider
3004
- }
3005
-
3006
- const withProvider = (Component, slot, options) => {
3007
- const StyledComponent = ${factoryName}(Component, {}, options)
3008
-
3009
- const WithProvider = (props) => {
3010
- const [variantProps, restProps] = svaFn.splitVariantProps(props)
3011
- const [local, propsWithoutChildren] = splitProps(restProps, ["children"])
3012
-
3013
- const slotStyles = createMemo(() => {
3014
- const styles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
3015
- styles._classNameMap = svaFn.classNameMap
3016
- return styles
3017
- })
3018
-
3019
- const resolvedProps = createMemo(() => {
3020
- const propsWithClass = {
3021
- ...propsWithoutChildren,
3022
- class: propsWithoutChildren.class ?? options?.defaultProps?.class,
3023
- }
3024
- const resolved = getResolvedProps(propsWithClass, slotStyles()[slot])
3025
- resolved.class = cx(resolved.class, slotStyles()._classNameMap[slot])
3026
- return resolved
3027
- })
3028
-
3029
- return createComponent(StyleContext.Provider, {
3030
- get value() {
3031
- return slotStyles()
3032
- },
3033
- get children() {
3034
- return createComponent(
3035
- StyledComponent,
3036
- mergeProps(resolvedProps, {
3037
- get children() {
3038
- return local.children
3039
- },
3040
- })
3041
- )
3042
- },
3043
- })
3044
- }
3045
-
3046
- const componentName = getDisplayName(Component)
3047
- WithProvider.displayName = \`withProvider(\${componentName})\`
3048
- return WithProvider
3049
- }
3050
-
3051
- const withContext = (Component, slot, options) => {
3052
- const StyledComponent = ${factoryName}(Component, {}, options)
3053
- const componentName = getDisplayName(Component)
3054
-
3055
- const WithContext = (props) => {
3056
- const slotStyles = useStyleContext(componentName, slot)
3057
- const [local, propsWithoutChildren] = splitProps(props, ["children"])
3058
-
3059
- const resolvedProps = createMemo(() => {
3060
- const propsWithClass = {
3061
- ...propsWithoutChildren,
3062
- class: propsWithoutChildren.class ?? options?.defaultProps?.class,
3063
- }
3064
- const resolved = getResolvedProps(propsWithClass, slotStyles[slot])
3065
- resolved.class = cx(resolved.class, slotStyles._classNameMap?.[slot])
3066
- return resolved
3067
- })
3068
-
3069
- return createComponent(
3070
- StyledComponent,
3071
- mergeProps(resolvedProps, {
3072
- get children() {
3073
- return local.children
3074
- },
3075
- })
3076
- )
3077
- }
3078
-
3079
- WithContext.displayName = \`withContext(\${componentName})\`
3080
- return WithContext
3081
- }
3082
-
3083
- return {
3084
- withRootProvider,
3085
- withProvider,
3086
- withContext,
3087
- }
3088
- }
3089
- `,
3090
- dts: outdent.outdent`
3091
- ${ctx.file.importType("SlotRecipeRuntimeFn, RecipeVariantProps", "../types/recipe")}
3092
- ${ctx.file.importType("JsxHTMLProps, JsxStyleProps, Assign", "../types/system-types")}
3093
- ${ctx.file.importType("JsxFactoryOptions, DataAttrs, MaybeAccessor, AsProps", "../types/jsx")}
3094
- import type { Component, JSX, ComponentProps } from 'solid-js'
3095
-
3096
- interface UnstyledProps {
3097
- unstyled?: boolean | undefined
3098
- }
3099
-
3100
- interface WithProviderOptions<P> {
3101
- defaultProps?: MaybeAccessor<Partial<P> & DataAttrs> | undefined
3102
- }
3103
-
3104
- type ElementType = keyof JSX.IntrinsicElements | Component<any>
3105
-
3106
- type SvaFn<S extends string = any> = SlotRecipeRuntimeFn<S, any>
3107
- interface SlotRecipeFn {
3108
- __type: any
3109
- __slot: string
3110
- (props?: any): any
3111
- }
3112
- type SlotRecipe = SvaFn | SlotRecipeFn
3113
-
3114
- type InferSlot<R extends SlotRecipe> = R extends SlotRecipeFn
3115
- ? R['__slot']
3116
- : R extends SvaFn<infer S>
3117
- ? S
3118
- : never
3119
-
3120
- type StyleContextProvider<T extends ElementType, R extends SlotRecipe> = Component<
3121
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<RecipeVariantProps<R>, JsxStyleProps>>
3122
- >
3123
-
3124
- type StyleContextRootProvider<T extends ElementType, R extends SlotRecipe> = Component<
3125
- ComponentProps<T> & UnstyledProps & RecipeVariantProps<R>
3126
- >
3127
-
3128
- type StyleContextConsumer<T extends ElementType> = Component<
3129
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
3130
- >
3131
-
3132
- export interface StyleContext<R extends SlotRecipe> {
3133
- withRootProvider: <T extends ElementType>(
3134
- Component: T,
3135
- options?: WithProviderOptions<ComponentProps<T>> | undefined
3136
- ) => StyleContextRootProvider<T, R>
3137
- withProvider: <T extends ElementType>(
3138
- Component: T,
3139
- slot: InferSlot<R>,
3140
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
3141
- ) => StyleContextProvider<T, R>
3142
- withContext: <T extends ElementType>(
3143
- Component: T,
3144
- slot: InferSlot<R>,
3145
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
3146
- ) => StyleContextConsumer<T>
3147
- }
3148
-
3149
- export declare function createStyleContext<R extends SlotRecipe>(recipe: R): StyleContext<R>
3150
- `
3151
- };
3152
- }
3153
- //#endregion
3154
- //#region src/artifacts/solid-jsx/jsx.string-literal.ts
3155
- function generateSolidJsxStringLiteralFactory(ctx) {
3156
- const { componentName, factoryName } = ctx.jsx;
3157
- return { js: outdent.outdent`
3158
- import { mergeProps, splitProps } from 'solid-js'
3159
- import { Dynamic, createComponent } from 'solid-js/web'
3160
- ${ctx.file.import("getDisplayName", "./factory-helper")}
3161
- ${ctx.file.import("css, cx", "../css/index")}
3162
-
3163
- function createStyled(element) {
3164
- const __base__ = element.__base__ || element
3165
- return function styledFn(template) {
3166
- const styles = css.raw(element.__styles__, template)
3167
-
3168
- const ${componentName} = (props) => {
3169
- const mergedProps = mergeProps({ as: __base__ }, props)
3170
- const [localProps, elementProps] = splitProps(mergedProps, ['as', 'class'])
3171
-
3172
- return createComponent(
3173
- Dynamic,
3174
- mergeProps(
3175
- {
3176
- get component() {
3177
- return localProps.as
3178
- },
3179
- get class() {
3180
- return cx(css(styles), localProps.class)
3181
- },
3182
- },
3183
- elementProps,
3184
- ),
3185
- )
3186
- }
3187
-
3188
- const name = getDisplayName(__base__)
3189
-
3190
- ${componentName}.displayName = \`${factoryName}.\${name}\`
3191
- ${componentName}.__styles__ = styles
3192
- ${componentName}.__base__ = __base__
3193
-
3194
- return ${componentName}
3195
- }
3196
- }
3197
-
3198
- function createJsxFactory() {
3199
- const cache = new Map()
3200
-
3201
- return new Proxy(createStyled, {
3202
- apply(_, __, args) {
3203
- return createStyled(...args)
3204
- },
3205
- get(_, el) {
3206
- if (!cache.has(el)) {
3207
- cache.set(el, createStyled(el))
3208
- }
3209
- return cache.get(el)
3210
- },
3211
- })
3212
- }
3213
-
3214
- export const ${factoryName} = /* @__PURE__ */ createJsxFactory()
3215
- ` };
3216
- }
3217
- //#endregion
3218
- //#region src/artifacts/solid-jsx/types.string-literal.ts
3219
- function generateSolidJsxStringLiteralTypes(ctx) {
3220
- const { factoryName, componentName, upperName, typeName } = ctx.jsx;
3221
- return {
3222
- jsxFactory: outdent.outdent`
3223
- ${ctx.file.importType(upperName, "../types/jsx")}
3224
- export declare const ${factoryName}: ${upperName}
3225
- `,
3226
- jsxType: outdent.outdent`
3227
- import type { Component, ComponentProps, JSX } from 'solid-js'
3228
-
3229
- interface Dict {
3230
- [k: string]: unknown
3231
- }
3232
-
3233
- export interface AsProps {
3234
- /**
3235
- * The element to render as
3236
- */
3237
- as?: ElementType | undefined
3238
- }
3239
-
3240
- export type ElementType<P = any> = keyof JSX.IntrinsicElements | Component<P>
3241
-
3242
- export type ${componentName}<T extends ElementType> = {
3243
- (args: { raw: readonly string[] | ArrayLike<string> }): (props: ComponentProps<T> & AsProps) => JSX.Element
3244
- displayName?: string | undefined
3245
- }
3246
-
3247
- export interface JsxFactory {
3248
- <T extends ElementType>(component: T): ${componentName}<T>
3249
- }
3250
-
3251
- export type JsxElements = {
3252
- [K in keyof JSX.IntrinsicElements]: ${componentName}<K>
3253
- }
3254
-
3255
- export type ${upperName} = JsxFactory & JsxElements
3256
-
3257
- export type ${typeName}<T extends ElementType> = ComponentProps<T>
3258
- `
3259
- };
3260
- }
3261
- //#endregion
3262
- //#region src/artifacts/vue-jsx/jsx.ts
3263
- function generateVueJsxFactory(ctx) {
3264
- const { factoryName, componentName } = ctx.jsx;
3265
- return { js: outdent.outdent`
3266
- import { defineComponent, h, computed } from 'vue'
3267
- ${ctx.file.import("defaultShouldForwardProp, composeShouldForwardProps, composeCvaFn, getDisplayName", "./factory-helper")}
3268
- ${ctx.file.import("isCssProperty", "./is-valid-prop")}
3269
- ${ctx.file.import("css, cx, cva", "../css/index")}
3270
- ${ctx.file.import("splitProps, normalizeHTMLProps", "../helpers")}
3271
-
3272
- function styledFn(Dynamic, configOrCva = {}, options = {}) {
3273
- const cvaFn = configOrCva.__cva__ || configOrCva.__recipe__ ? configOrCva : cva(configOrCva)
3274
-
3275
- const forwardFn = options.shouldForwardProp || defaultShouldForwardProp
3276
- const shouldForwardProp = (prop) => {
3277
- if (options.forwardProps?.includes(prop)) return true
3278
- return forwardFn(prop, cvaFn.variantKeys)
3279
- }
3280
-
3281
- const defaultProps = Object.assign(
3282
- options.dataAttr && configOrCva.__name__ ? { 'data-recipe': configOrCva.__name__ } : {},
3283
- options.defaultProps,
3284
- )
3285
-
3286
- const __cvaFn__ = composeCvaFn(Dynamic.__cva__, cvaFn)
3287
- const __shouldForwardProps__ = composeShouldForwardProps(Dynamic, shouldForwardProp)
3288
-
3289
- const __base__ = Dynamic.__base__ || Dynamic
3290
- const name = getDisplayName(__base__)
3291
-
3292
- const ${componentName} = defineComponent({
3293
- name: \`${factoryName}.\${name}\`,
3294
- inheritAttrs: false,
3295
- props: {
3296
- modelValue: null,
3297
- unstyled: { type: Boolean, default: false },
3298
- as: { type: [String, Object], default: __base__ }
3299
- },
3300
- setup(props, { slots, attrs, emit }) {
3301
- const combinedProps = computed(() => Object.assign({}, defaultProps, attrs))
3302
-
3303
- const splittedProps = computed(() => {
3304
- return splitProps(combinedProps.value, normalizeHTMLProps.keys, __shouldForwardProps__, __cvaFn__.variantKeys, isCssProperty)
3305
- })
3306
-
3307
- const recipeClass = computed(() => {
3308
- const [_htmlProps, _forwardedProps, variantProps, styleProps, _elementProps] = splittedProps.value
3309
- const { css: cssStyles, ...propStyles } = styleProps
3310
- const compoundVariantStyles = __cvaFn__.__getCompoundVariantCss__?.(variantProps);
3311
- return cx(__cvaFn__(variantProps, false), css(compoundVariantStyles, propStyles, cssStyles), combinedProps.value.className, combinedProps.value.class)
3312
- })
3313
-
3314
- const cvaClass = computed(() => {
3315
- const [_htmlProps, _forwardedProps, variantProps, styleProps, _elementProps] = splittedProps.value
3316
- const { css: cssStyles, ...propStyles } = styleProps
3317
- const cvaStyles = __cvaFn__.raw(variantProps)
3318
- return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.value.className, combinedProps.value.class)
3319
- })
3320
-
3321
- const classes = computed(() => {
3322
- if (props.unstyled) {
3323
- const [_htmlProps, _forwardedProps, _variantProps, styleProps, _elementProps] = splittedProps.value
3324
- const { css: cssStyles, ...propStyles } = styleProps
3325
- return cx(css(propStyles, cssStyles), combinedProps.value.className, combinedProps.value.class)
3326
- }
3327
- return configOrCva.__recipe__ ? recipeClass.value : cvaClass.value
3328
- })
3329
-
3330
- const vModelProps = computed(() => {
3331
- const result = {};
3332
-
3333
- if (
3334
- props.as === 'input' &&
3335
- (props.type === 'checkbox' || props.type === 'radio')
3336
- ) {
3337
- result.checked = props.modelValue;
3338
- result.onChange = (event) => {
3339
- const checked = !event.currentTarget.checked;
3340
- emit('change', checked, event);
3341
- emit('update:modelValue', checked, event);
3342
- };
3343
- } else if (
3344
- props.as === 'input' ||
3345
- props.as === 'textarea' ||
3346
- props.as === 'select'
3347
- ) {
3348
- result.value = props.modelValue;
3349
- result.onInput = (event) => {
3350
- const value = event.currentTarget.value;
3351
- emit('input', value, event);
3352
- emit('update:modelValue', value, event);
3353
- };
3354
- }
3355
-
3356
- return result;
3357
- });
3358
-
3359
- return () => {
3360
- const [htmlProps, forwardedProps, _variantProps, _styleProps, elementProps] = splittedProps.value
3361
-
3362
- return h(
3363
- props.as,
3364
- {
3365
- ...forwardedProps,
3366
- ...elementProps,
3367
- ...normalizeHTMLProps(htmlProps),
3368
- ...vModelProps.value,
3369
- class: classes.value,
3370
- },
3371
- slots,
3372
- )
3373
- }
3374
- },
3375
- })
3376
-
3377
- ${componentName}.displayName = \`${factoryName}.\${name}\`
3378
- ${componentName}.__cva__ = __cvaFn__
3379
- ${componentName}.__base__ = __base__
3380
- ${componentName}.__shouldForwardProps__ = shouldForwardProp
3381
-
3382
- return ${componentName}
3383
- }
3384
-
3385
- const tags = 'a, abbr, address, area, article, aside, audio, b, base, bdi, bdo, big, blockquote, body, br, button, canvas, caption, cite, code, col, colgroup, data, datalist, dd, del, details, dfn, dialog, div, dl, dt, em, embed, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html, i, iframe, img, input, ins, kbd, keygen, label, legend, li, link, main, map, mark, marquee, menu, menuitem, meta, meter, nav, noscript, object, ol, optgroup, option, output, p, param, picture, pre, progress, q, rp, rt, ruby, s, samp, script, section, select, small, source, span, strong, style, sub, summary, sup, table, tbody, td, textarea, tfoot, th, thead, time, title, tr, track, u, ul, var, video, wbr, circle, clipPath, defs, ellipse, foreignObject, g, image, line, linearGradient, mask, path, pattern, polygon, polyline, radialGradient, rect, stop, svg, text, tspan';
3386
-
3387
- export const ${factoryName} = /* @__PURE__ */ styledFn.bind();
3388
-
3389
- tags.split(', ').forEach((tag) => {
3390
- ${factoryName}[tag] = ${factoryName}(tag);
3391
- });
3392
- ` };
3393
- }
3394
- //#endregion
3395
- //#region src/artifacts/vue-jsx/pattern.ts
3396
- function generateVueJsxPattern(ctx, filters) {
3397
- const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx;
3398
- return ctx.patterns.filterDetails(filters).map((pattern) => {
3399
- const { upperName, styleFnName, dashName, jsxName, props, blocklistType } = pattern;
3400
- const { description, jsxElement = "div", deprecated } = pattern.config;
3401
- return {
3402
- name: dashName,
3403
- js: outdent.outdent`
3404
- import { defineComponent, h, computed } from 'vue'
3405
- ${jsxStyleProps === "minimal" ? ctx.file.import("mergeCss", "../css/css") : ""}
3406
- ${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
3407
- ${ctx.file.import(factoryName, "./factory")}
3408
-
3409
- export const ${jsxName} = /* @__PURE__ */ defineComponent({
3410
- name: '${jsxName}',
3411
- inheritAttrs: false,
3412
- props: ${JSON.stringify(props)},
3413
- setup(props, { attrs, slots }) {
3414
- ${(0, ts_pattern.match)(jsxStyleProps).with("none", () => outdent.outdent`
3415
- const cssProps = computed(() => {
3416
- const styleProps = ${styleFnName}(props)
3417
- return { css: styleProps }
3418
- })
3419
-
3420
- return () => {
3421
- const mergedProps = { ...attrs, ...cssProps.value }
3422
- return h(${factoryName}.${jsxElement}, mergedProps, slots)
3423
- }
3424
- `).with("minimal", () => outdent.outdent`
3425
- const cssProps = computed(() => {
3426
- const styleProps = ${styleFnName}(props)
3427
- return { css: mergeCss(styleProps, attrs.css) }
3428
- })
3429
-
3430
- return () => {
3431
- const mergedProps = { ...attrs, ...cssProps.value }
3432
- return h(${factoryName}.${jsxElement}, mergedProps, slots)
3433
- }
3434
- `).with("all", () => outdent.outdent`
3435
- const styleProps = computed(() => ${styleFnName}(props))
3436
-
3437
- return () => {
3438
- const mergedProps = { ...styleProps.value, ...attrs }
3439
- return h(${factoryName}.${jsxElement}, mergedProps, slots)
3440
- }
3441
- `).exhaustive()}
3442
- }
3443
- })
3444
- `,
3445
- dts: outdent.outdent`
3446
- import type { FunctionalComponent } from 'vue'
3447
- ${ctx.file.importType(`${upperName}Properties`, `../patterns/${dashName}`)}
3448
- ${ctx.file.importType(typeName, "../types/jsx")}
3449
- ${ctx.file.importType("DistributiveOmit", "../types/system-types")}
3450
-
3451
- export interface ${upperName}Props extends ${upperName}Properties, DistributiveOmit<${typeName}<'${jsxElement}'>, keyof ${upperName}Properties ${blocklistType}> {}
3452
-
3453
- ${ctx.file.jsDocComment(description, { deprecated })}
3454
- export declare const ${jsxName}: FunctionalComponent<${upperName}Props>
3455
- `
3456
- };
3457
- });
3458
- }
3459
- //#endregion
3460
- //#region src/artifacts/vue-jsx/types.ts
3461
- function generateVueJsxTypes(ctx) {
3462
- const { factoryName, componentName, upperName, typeName, variantName } = ctx.jsx;
3463
- return {
3464
- jsxFactory: outdent.outdent`
3465
- ${ctx.file.importType(upperName, "../types/jsx")}
3466
-
3467
- export declare const ${factoryName}: ${upperName}
3468
- `,
3469
- jsxType: outdent.outdent`
3470
- import type { Component, FunctionalComponent, NativeElements } from 'vue'
3471
-
3472
- ${ctx.file.importType("RecipeDefinition, RecipeSelection, RecipeVariantRecord", "./recipe")}
3473
- ${ctx.file.importType("Assign, DistributiveOmit, DistributiveUnion, JsxHTMLProps, JsxStyleProps, Pretty", "./system-types")}
3474
-
3475
- export type IntrinsicElement = keyof NativeElements
3476
-
3477
- export type ElementType = IntrinsicElement | Component
3478
-
3479
- export type ComponentProps<T extends ElementType> = T extends IntrinsicElement
3480
- ? NativeElements[T]
3481
- : T extends Component<infer Props>
3482
- ? Props
3483
- : never
3484
-
3485
- interface Dict {
3486
- [k: string]: unknown
3487
- }
3488
-
3489
- export type DataAttrs = Record<\`data-\${string}\`, unknown>
937
+ // The slots that enclose other slots, matching \`Recipes.getScopeRoots\`. Their variant
938
+ // styles anchor \`@scope\` rules for every other slot, so only they take variants — a
939
+ // variant class on any other slot would name a rule that was never emitted.
940
+ //
941
+ // A list, because a component can span a portal and so occupy more than one subtree.
942
+ const declaredSlots = config.slots ?? []
943
+ const anchors = config.scopeRoots
944
+ ? config.scopeRoots.filter((slot) => declaredSlots.includes(slot))
945
+ : declaredSlots.includes('root') ? ['root'] : []
946
+
947
+ // \`classNameMap[slot]\` used to be joined on here, because the slot's classes were
948
+ // atomic and nothing else carried the name to target it in the DOM. The slot's cva is
949
+ // now named \`name__slot\` and returns that as its base class, so joining it again
950
+ // would just repeat it.
951
+ function svaFn(props) {
952
+ const result = slots.map(([slot, cvaFn]) => [
953
+ slot,
954
+ anchors.length && !anchors.includes(slot) ? cvaFn.config.className : cvaFn(props),
955
+ ])
956
+ return Object.fromEntries(result)
957
+ }
3490
958
 
3491
- export interface UnstyledProps {
3492
- /**
3493
- * Whether to remove recipe styles
3494
- */
3495
- unstyled?: boolean | undefined
3496
- }
959
+ function raw(props) {
960
+ const result = slots.map(([slot, cvaFn]) => [slot, cvaFn.raw(props)])
961
+ return Object.fromEntries(result)
962
+ }
3497
963
 
3498
- export interface AsProps {
3499
- /**
3500
- * The element to render as
3501
- */
3502
- as?: ElementType | undefined
3503
- }
964
+ const variants = config.variants ?? {};
965
+ const variantKeys = Object.keys(variants);
3504
966
 
3505
- export interface ${componentName}<T extends ElementType, P extends Dict = {}> extends FunctionalComponent<
3506
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<JsxStyleProps, P>>
3507
- > {}
967
+ function splitVariantProps(props) {
968
+ return splitProps(props, variantKeys);
969
+ }
970
+ const getVariantProps = (variants) => ({ ...defaultVariants, ...compact(variants) })
3508
971
 
3509
- interface RecipeFn {
3510
- __type: any
3511
- }
972
+ const variantMap = Object.fromEntries(
973
+ Object.entries(variants).map(([key, value]) => [key, Object.keys(value)])
974
+ );
3512
975
 
3513
- export interface JsxFactoryOptions<TProps extends Dict> {
3514
- dataAttr?: boolean
3515
- defaultProps?: Partial<TProps> & DataAttrs
3516
- shouldForwardProp?: (prop: string, variantKeys: string[]) => boolean
3517
- forwardProps?: string[]
3518
- }
976
+ // Which slots each variant writes styles for.
977
+ //
978
+ // A scope reaches every slot inside an anchor's subtree. A slot under no anchor is
979
+ // not reached, and nothing at build time can detect that — reachability is a fact
980
+ // about the DOM. This is what says which slots a variant has to get to, so the
981
+ // component layer can thread the ones a scope cannot. Config slot recipes have always
982
+ // exposed it; an inline \`sva\` had no way to answer the question at all.
983
+ const slotsAffectedBy = Object.fromEntries(
984
+ Object.entries(variants).map(([variant, values]) => [
985
+ variant,
986
+ [...new Set(Object.values(values ?? {}).flatMap((slotStyles) => Object.keys(slotStyles ?? {})))],
987
+ ])
988
+ );
3519
989
 
3520
- export type JsxRecipeProps<T extends ElementType, P extends RecipeFn> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<JsxStyleProps, P['__type']>>;
990
+ return Object.assign(memo(svaFn), {
991
+ __cva__: false,
992
+ raw,
993
+ config,
994
+ variantMap,
995
+ variantKeys,
996
+ classNameMap,
997
+ /** The slots that enclose other slots, and so anchor their variant rules. */
998
+ scopeRoots: anchors,
999
+ slotsAffectedBy,
1000
+ splitVariantProps,
1001
+ getVariantProps,
1002
+ })
1003
+ }
3521
1004
 
3522
- export type JsxElement<T extends ElementType, P> = T extends ${componentName}<infer A, infer B>
3523
- ? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
3524
- : ${componentName}<T, P>
1005
+ /**
1006
+ * Report slots whose variant styles can never reach them.
1007
+ *
1008
+ * A scoped slot is styled through an \`@scope\` rule opened at an anchor, so it has to be
1009
+ * rendered inside one. A slot moved out of every anchor's subtree — through a portal,
1010
+ * with no second anchor named in \`scopeRoots\` — keeps its base styles and silently
1011
+ * loses its variant styles. That renders *nearly* right, which is harder to notice than
1012
+ * a total failure, and no build step can catch it: whether one element is inside another
1013
+ * is a fact about the DOM.
1014
+ *
1015
+ * Checks for the anchor's *base* class rather than its variant class. An anchor always
1016
+ * carries the base one; the variant class is absent whenever no variant is selected, and
1017
+ * matching on it would report a slot that is correctly placed and simply unstyled.
1018
+ *
1019
+ * Development only — call it behind \`process.env.NODE_ENV !== 'production'\` so bundlers
1020
+ * drop it, along with this function, from your production build.
1021
+ *
1022
+ * \`\`\`js
1023
+ * import { auditSlotScopes, select } from '../styled-system/css'
1024
+ *
1025
+ * if (process.env.NODE_ENV !== 'production') auditSlotScopes([select], { observe: true })
1026
+ * \`\`\`
1027
+ */
1028
+ export function auditSlotScopes(recipes, options = {}) {
1029
+ const { root = typeof document === 'undefined' ? undefined : document, observe = false, onReport } = options
1030
+ if (!root) return () => {}
3525
1031
 
3526
- export interface JsxFactory {
3527
- <T extends ElementType>(component: T): ${componentName}<T, {}>
3528
- <T extends ElementType, P extends RecipeVariantRecord>(component: T, recipe: RecipeDefinition<P>, options?: JsxFactoryOptions<JsxRecipeProps<T, RecipeSelection<P>>>): JsxElement<
3529
- T,
3530
- RecipeSelection<P>
3531
- >
3532
- <T extends ElementType, P extends RecipeFn>(component: T, recipeFn: P, options?: JsxFactoryOptions<JsxRecipeProps<T, P['__type']>> ): JsxElement<T, P['__type']>
3533
- }
1032
+ const escape = (value) =>
1033
+ typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(value) : value.replace(/[^\\w-]/g, '\\\\$&')
3534
1034
 
3535
- export type JsxElements = {
3536
- [K in IntrinsicElement]: ${componentName}<K, {}>
3537
- }
1035
+ const audit = () => {
1036
+ const found = []
3538
1037
 
3539
- export type ${upperName} = JsxFactory & JsxElements
1038
+ for (const recipe of recipes) {
1039
+ const anchors = recipe?.scopeRoots ?? []
1040
+ // Nothing is scoped, so every slot carries its own variant class and none of them
1041
+ // depends on where it is rendered.
1042
+ if (!anchors.length) continue
3540
1043
 
3541
- export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, JsxStyleProps>
1044
+ const classNameMap = recipe.classNameMap ?? {}
1045
+ const anchorSelector = anchors
1046
+ .map((slot) => classNameMap[slot])
1047
+ .filter(Boolean)
1048
+ .map((className) => '.' + escape(className))
1049
+ .join(', ')
1050
+ if (!anchorSelector) continue
3542
1051
 
3543
- export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
3544
- `
3545
- };
3546
- }
3547
- //#endregion
3548
- //#region src/artifacts/vue-jsx/create-style-context.ts
3549
- function generateVueCreateStyleContext(ctx) {
3550
- const { factoryName } = ctx.jsx;
3551
- return {
3552
- js: outdent.outdent`
3553
- ${ctx.file.import("cx, css, sva", "../css/index")}
3554
- ${ctx.file.import(factoryName, "./factory")}
3555
- ${ctx.file.import("getDisplayName", "./factory-helper")}
3556
- import { defineComponent, provide, inject, computed, h } from 'vue'
3557
-
3558
- export function createStyleContext(recipe) {
3559
- const StyleContext = Symbol('StyleContext')
3560
- const isConfigRecipe = '__recipe__' in recipe
3561
- const recipeName = isConfigRecipe && recipe.__name__ ? recipe.__name__ : undefined
3562
- const contextName = recipeName ? \`createStyleContext("\${recipeName}")\` : 'createStyleContext'
3563
- const svaFn = isConfigRecipe ? recipe : sva(recipe.config)
3564
-
3565
- function useStyleContext(componentName, slot) {
3566
- const context = inject(StyleContext)
3567
- if (context === undefined) {
3568
- const componentInfo = componentName ? \`Component "\${componentName}"\` : 'A component'
3569
- const slotInfo = slot ? \` (slot: "\${slot}")\` : ''
3570
-
3571
- throw new Error(
3572
- \`\${componentInfo}\${slotInfo} cannot access \${contextName} because it's missing its Provider.\`
3573
- )
3574
- }
3575
- return context
3576
- }
3577
-
3578
- const getResolvedProps = (props, slotStyles) => {
3579
- const { unstyled, ...restProps } = props
3580
- if (unstyled) return restProps
3581
- if (isConfigRecipe) {
3582
- return { ...restProps, class: cx(slotStyles, restProps.class) }
3583
- }
3584
- ${outdent.outdent.string((0, ts_pattern.match)(ctx.config.jsxStyleProps).with("all", () => `return { ...slotStyles, ...restProps }`).with("minimal", () => `return { ...restProps, css: css.raw(slotStyles, restProps.css) }`).with("none", () => `return { ...restProps, class: cx(css(slotStyles), restProps.class) }`).otherwise(() => `return restProps`))}
3585
- }
1052
+ const scoped = new Set(Object.values(recipe.slotsAffectedBy ?? {}).flat())
3586
1053
 
3587
- const withRootProvider = (Component, options) => {
3588
- const WithRootProvider = defineComponent({
3589
- props: svaFn.variantKeys,
3590
- setup(props, { slots }) {
3591
- const [variantProps, otherProps] = svaFn.splitVariantProps(props)
1054
+ for (const slot of scoped) {
1055
+ if (anchors.includes(slot)) continue
3592
1056
 
3593
- const slotStyles = computed(() => {
3594
- const styles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
3595
- styles._classNameMap = svaFn.classNameMap
3596
- return styles
3597
- })
1057
+ const className = classNameMap[slot]
1058
+ if (!className) continue
3598
1059
 
3599
- provide(StyleContext, slotStyles)
1060
+ for (const element of root.querySelectorAll('.' + escape(className))) {
1061
+ if (element.closest(anchorSelector)) continue
1062
+ found.push({ recipe: recipe.__name__, slot, className, element, anchors })
1063
+ }
1064
+ }
1065
+ }
3600
1066
 
3601
- const mergedProps = computed(() => {
3602
- if (!options?.defaultProps) return otherProps
3603
- return { ...options.defaultProps, ...otherProps }
3604
- })
1067
+ if (!found.length) return found
1068
+
1069
+ if (onReport) {
1070
+ onReport(found)
1071
+ } else {
1072
+ for (const problem of found) {
1073
+ console.warn(
1074
+ \`[bamboo] \${problem.recipe ?? 'slot recipe'}: the \\\`\${problem.slot}\\\` slot is rendered outside every \` +
1075
+ \`anchor (\${problem.anchors.join(', ')}), so its variant styles cannot reach it. \` +
1076
+ \`Add the enclosing slot to \\\`scopeRoots\\\`, or deliver the variant to this slot by hand.\`,
1077
+ problem.element,
1078
+ )
1079
+ }
1080
+ }
3605
1081
 
3606
- return () => h(Component, mergedProps.value, slots)
3607
- },
3608
- })
3609
-
3610
- const componentName = getDisplayName(Component)
3611
- WithRootProvider.displayName = \`withRootProvider(\${componentName})\`
3612
-
3613
- return WithRootProvider
1082
+ return found
3614
1083
  }
3615
1084
 
3616
- const withProvider = (Component, slot, options) => {
3617
- const StyledComponent = ${factoryName}(Component, {}, options)
3618
-
3619
- const WithProvider = defineComponent({
3620
- props: ["unstyled", ...svaFn.variantKeys],
3621
- inheritAttrs: false,
3622
- setup(inProps, { slots, attrs }) {
3623
- const props = computed(() => {
3624
- const propsWithClass = { ...inProps, ...attrs }
3625
- propsWithClass.class = propsWithClass.class ?? options?.defaultProps?.class
3626
- return propsWithClass
3627
- })
3628
- const res = computed(() => {
3629
- const [variantProps, restProps] = svaFn.splitVariantProps(props.value)
3630
- return { variantProps, restProps }
3631
- })
3632
-
3633
- const slotStyles = computed(() => {
3634
- const styles = isConfigRecipe ? svaFn(res.value.variantProps) : svaFn.raw(res.value.variantProps)
3635
- styles._classNameMap = svaFn.classNameMap
3636
- return styles
3637
- })
3638
-
3639
- provide(StyleContext, slotStyles)
3640
-
3641
- return () => {
3642
- const resolvedProps = getResolvedProps(res.value.restProps, slotStyles.value[slot])
3643
- resolvedProps.class = cx(resolvedProps.class, slotStyles.value._classNameMap[slot], attrs.class)
3644
- return h(StyledComponent, resolvedProps, slots)
3645
- }
3646
- },
3647
- })
3648
-
3649
- const componentName = getDisplayName(Component)
3650
- WithProvider.displayName = \`withProvider(\${componentName})\`
3651
-
3652
- return WithProvider
3653
- }
1085
+ audit()
3654
1086
 
3655
- const withContext = (Component, slot, options) => {
3656
- const StyledComponent = ${factoryName}(Component, {}, options)
3657
- const componentName = getDisplayName(Component)
3658
-
3659
- const WithContext = defineComponent({
3660
- props: ["unstyled"],
3661
- inheritAttrs: false,
3662
- setup(inProps, { slots, attrs }) {
3663
- const props = computed(() => {
3664
- const propsWithClass = { ...inProps, ...attrs }
3665
- propsWithClass.class = propsWithClass.class ?? options?.defaultProps?.class
3666
- return propsWithClass
3667
- })
3668
- const slotStyles = useStyleContext(componentName, slot)
3669
-
3670
- return () => {
3671
- const resolvedProps = getResolvedProps(props.value, slotStyles.value[slot])
3672
- resolvedProps.class = cx(resolvedProps.class, slotStyles.value._classNameMap[slot], attrs.class)
3673
- return h(StyledComponent, resolvedProps, slots)
3674
- }
3675
- },
1087
+ if (!observe || typeof MutationObserver === 'undefined') return () => {}
1088
+
1089
+ // Portaled content mounts after the first sweep, which is exactly the case this
1090
+ // exists to catch, so a one-shot pass would miss it.
1091
+ let queued = false
1092
+ const observer = new MutationObserver(() => {
1093
+ if (queued) return
1094
+ queued = true
1095
+ queueMicrotask(() => {
1096
+ queued = false
1097
+ audit()
3676
1098
  })
3677
-
3678
- WithContext.displayName = \`withContext(\${componentName})\`
3679
-
3680
- return WithContext
3681
- }
1099
+ })
1100
+ observer.observe(root === document ? document.documentElement : root, { childList: true, subtree: true })
3682
1101
 
3683
- return {
3684
- withRootProvider,
3685
- withProvider,
3686
- withContext,
3687
- }
1102
+ return () => observer.disconnect()
3688
1103
  }
3689
1104
  `,
3690
1105
  dts: outdent.outdent`
3691
- ${ctx.file.importType("SlotRecipeRuntimeFn, RecipeVariantProps", "../types/recipe")}
3692
- ${ctx.file.importType("JsxHTMLProps, JsxStyleProps, Assign", "../types/system-types")}
3693
- ${ctx.file.importType("JsxFactoryOptions, DataAttrs, AsProps", "../types/jsx")}
3694
- import type { Component, FunctionalComponent, NativeElements } from 'vue'
3695
-
3696
- interface UnstyledProps {
3697
- unstyled?: boolean | undefined
3698
- }
1106
+ ${ctx.file.importType("SlotRecipeCreatorFn", "../types/recipe")}
3699
1107
 
3700
- interface WithProviderOptions<P = {}> {
3701
- defaultProps?: (Partial<P> & DataAttrs) | undefined
3702
- }
1108
+ export declare const sva: SlotRecipeCreatorFn
3703
1109
 
3704
- // Add v-model support types
3705
- interface VModelProps {
3706
- modelValue?: any
3707
- 'onUpdate:modelValue'?: (value: any) => void
1110
+ export interface SlotScopeProblem {
1111
+ /** The recipe the slot belongs to, when it has a name. */
1112
+ recipe?: string
1113
+ /** The slot whose variant styles cannot reach it. */
1114
+ slot: string
1115
+ /** The constant class that slot carries. */
1116
+ className: string
1117
+ /** The element found outside every anchor. */
1118
+ element: Element
1119
+ /** The anchors that were looked for. */
1120
+ anchors: string[]
3708
1121
  }
3709
1122
 
3710
- type SvaFn<S extends string = any> = SlotRecipeRuntimeFn<S, any>
3711
- interface SlotRecipeFn {
3712
- __type: any
3713
- __slot: string
3714
- (props?: any): any
3715
- }
3716
- type SlotRecipe = SvaFn | SlotRecipeFn
3717
-
3718
- type InferSlot<R extends SlotRecipe> = R extends SlotRecipeFn ? R['__slot'] : R extends SvaFn<infer S> ? S : never
3719
-
3720
- type IntrinsicElement = keyof NativeElements
3721
- type ElementType = IntrinsicElement | Component
3722
-
3723
- type ComponentProps<T extends ElementType> = T extends IntrinsicElement
3724
- ? NativeElements[T]
3725
- : T extends Component<infer Props>
3726
- ? Props
3727
- : never
3728
-
3729
- type StyleContextProvider<T extends ElementType, R extends SlotRecipe> = FunctionalComponent<
3730
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps & VModelProps, Assign<RecipeVariantProps<R>, JsxStyleProps>>
3731
- >
3732
-
3733
- type StyleContextRootProvider<T extends ElementType, R extends SlotRecipe> = FunctionalComponent<
3734
- ComponentProps<T> & UnstyledProps & VModelProps & RecipeVariantProps<R>
3735
- >
3736
-
3737
- type StyleContextConsumer<T extends ElementType> = FunctionalComponent<
3738
- JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps & VModelProps, JsxStyleProps>
3739
- >
3740
-
3741
- export interface StyleContext<R extends SlotRecipe> {
3742
- withRootProvider: <T extends ElementType>(
3743
- Component: T,
3744
- options?: WithProviderOptions<ComponentProps<T>> | undefined
3745
- ) => StyleContextRootProvider<T, R>
3746
- withProvider: <T extends ElementType>(
3747
- Component: T,
3748
- slot: InferSlot<R>,
3749
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
3750
- ) => StyleContextProvider<T, R>
3751
- withContext: <T extends ElementType>(
3752
- Component: T,
3753
- slot: InferSlot<R>,
3754
- options?: JsxFactoryOptions<ComponentProps<T>> | undefined
3755
- ) => StyleContextConsumer<T>
1123
+ export interface AuditSlotScopesOptions {
1124
+ /** Where to look. Defaults to \`document\`. */
1125
+ root?: ParentNode
1126
+ /** Re-check as the DOM changes, for content that mounts through a portal. */
1127
+ observe?: boolean
1128
+ /** Handle the findings yourself instead of warning to the console. */
1129
+ onReport?: (problems: SlotScopeProblem[]) => void
3756
1130
  }
3757
1131
 
3758
- export declare function createStyleContext<R extends SlotRecipe>(recipe: R): StyleContext<R>
1132
+ /**
1133
+ * Report slots whose variant styles can never reach them, in development.
1134
+ *
1135
+ * A scoped slot is styled through an \`@scope\` rule opened at an anchor, so it has to be
1136
+ * rendered inside one. A slot moved out of every anchor's subtree keeps its base styles
1137
+ * and silently loses its variant styles — which no build step can catch, because whether
1138
+ * one element is inside another is a fact about the DOM.
1139
+ *
1140
+ * Returns a function that stops observing.
1141
+ */
1142
+ export declare function auditSlotScopes(
1143
+ recipes: ReadonlyArray<unknown>,
1144
+ options?: AuditSlotScopesOptions,
1145
+ ): () => void
3759
1146
  `
3760
1147
  };
3761
1148
  }
3762
1149
  //#endregion
3763
- //#region src/artifacts/vue-jsx/jsx.string-literal.ts
3764
- function generateVueJsxStringLiteralFactory(ctx) {
3765
- const { componentName, factoryName } = ctx.jsx;
3766
- return { js: outdent.outdent`
3767
- import { defineComponent, h, computed } from 'vue'
3768
- ${ctx.file.import("getDisplayName", "./factory-helper")}
3769
- ${ctx.file.import("css, cx", "../css/index")}
3770
-
3771
- function createStyled(Dynamic) {
3772
- const name = getDisplayName(Dynamic)
3773
- const __base__ = Dynamic.__base__ || Dynamic
3774
-
3775
- function styledFn(template) {
3776
- const styles = css.raw(Dynamic.__styles__, template)
3777
-
3778
- const ${componentName} = defineComponent({
3779
- name: \`${factoryName}.\${name}\`,
3780
- inheritAttrs: false,
3781
- props: {
3782
- modelValue: null,
3783
- as: { type: [String, Object], default: __base__ }
3784
- },
3785
- setup(props, { slots, attrs, emit }) {
3786
- const classes = computed(() => {
3787
- return cx(css(styles), attrs.className)
3788
- })
3789
-
3790
- const vModelProps = computed(() => {
3791
- const result = {};
3792
-
3793
- if (
3794
- props.as === 'input' &&
3795
- (props.type === 'checkbox' || props.type === 'radio')
3796
- ) {
3797
- result.checked = props.modelValue;
3798
- result.onChange = (event) => {
3799
- const checked = !event.currentTarget.checked;
3800
- emit('change', checked, event);
3801
- emit('update:modelValue', checked, event);
3802
- };
3803
- } else if (
3804
- props.as === 'input' ||
3805
- props.as === 'textarea' ||
3806
- props.as === 'select'
3807
- ) {
3808
- result.value = props.modelValue;
3809
- result.onInput = (event) => {
3810
- const value = event.currentTarget.value;
3811
- emit('input', value, event);
3812
- emit('update:modelValue', value, event);
3813
- };
3814
- }
3815
-
3816
- return result;
3817
- });
3818
-
3819
- return () => {
3820
- return h(
3821
- props.as,
3822
- {
3823
- class: classes.value,
3824
- ...attrs,
3825
- ...vModelProps.value,
3826
- },
3827
- slots
3828
- )
3829
- }
3830
- },
3831
- })
3832
-
3833
- ${componentName}.__styles__ = styles
3834
- ${componentName}.__base__ = __base__
3835
-
3836
- return ${componentName}
3837
- }
3838
-
3839
- return styledFn
3840
- }
3841
-
3842
- const tags = 'a, abbr, address, area, article, aside, audio, b, base, bdi, bdo, big, blockquote, body, br, button, canvas, caption, cite, code, col, colgroup, data, datalist, dd, del, details, dfn, dialog, div, dl, dt, em, embed, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html, i, iframe, img, input, ins, kbd, keygen, label, legend, li, link, main, map, mark, marquee, menu, menuitem, meta, meter, nav, noscript, object, ol, optgroup, option, output, p, param, picture, pre, progress, q, rp, rt, ruby, s, samp, script, section, select, small, source, span, strong, style, sub, summary, sup, table, tbody, td, textarea, tfoot, th, thead, time, title, tr, track, u, ul, var, video, wbr, circle, clipPath, defs, ellipse, foreignObject, g, image, line, linearGradient, mask, path, pattern, polygon, polyline, radialGradient, rect, stop, svg, text, tspan';
3843
-
3844
- export const ${factoryName} = /* @__PURE__ */ createStyled.bind();
3845
-
3846
- tags.split(', ').forEach((tag) => {
3847
- ${factoryName}[tag] = createStyled(tag);
3848
- });
3849
- ` };
3850
- }
3851
- //#endregion
3852
- //#region src/artifacts/vue-jsx/types.string-literal.ts
3853
- function generateVueJsxStringLiteralTypes(ctx) {
3854
- const { factoryName, componentName, upperName, typeName } = ctx.jsx;
1150
+ //#region src/artifacts/js/token.ts
1151
+ function generateTokenJs(ctx) {
1152
+ const { tokens } = ctx;
1153
+ const map = /* @__PURE__ */ new Map();
1154
+ tokens.allTokens.forEach((token) => {
1155
+ const { varRef, isVirtual } = token.extensions;
1156
+ const value = isVirtual || token.extensions.condition !== "base" ? varRef : token.value;
1157
+ map.set(token.name, {
1158
+ value,
1159
+ variable: varRef
1160
+ });
1161
+ });
1162
+ const obj = Object.fromEntries(map);
3855
1163
  return {
3856
- jsxFactory: outdent.outdent`
3857
- ${ctx.file.importType(upperName, "../types/jsx")}
3858
-
3859
- export declare const ${factoryName}: ${upperName}
3860
- `,
3861
- jsxType: outdent.outdent`
3862
- import type { Component, FunctionalComponent, NativeElements } from 'vue'
3863
-
3864
- export type IntrinsicElement = keyof NativeElements
3865
-
3866
- export type ElementType = IntrinsicElement | Component
3867
-
3868
- export type ComponentProps<T extends ElementType> = T extends IntrinsicElement
3869
- ? NativeElements[T]
3870
- : T extends Component<infer Props>
3871
- ? Props
3872
- : never
3873
-
3874
- export interface AsProps {
3875
- /**
3876
- * The element to render as
3877
- */
3878
- as?: ElementType | undefined
3879
- }
1164
+ js: outdent.default`
1165
+ const tokens = ${JSON.stringify(obj, null, 2)}
3880
1166
 
3881
- export type ${componentName}<T extends ElementType> = {
3882
- (args: { raw: readonly string[] | ArrayLike<string> }): FunctionalComponent<ComponentProps<T> & AsProps>
3883
- }
1167
+ export function token(path, fallback) {
1168
+ return tokens[path]?.value || fallback
1169
+ }
3884
1170
 
3885
- export interface JsxFactory {
3886
- <T extends ElementType>(component: T): ${componentName}<T>
3887
- }
1171
+ function tokenVar(path, fallback) {
1172
+ return tokens[path]?.variable || fallback
1173
+ }
3888
1174
 
3889
- export type JsxElements = {
3890
- [K in IntrinsicElement]: ${componentName}<K>
3891
- }
1175
+ token.var = tokenVar
1176
+ `,
1177
+ dts: outdent.default`
1178
+ ${ctx.file.importType("Token", "./tokens")}
3892
1179
 
3893
- export type ${upperName} = JsxFactory & JsxElements
1180
+ export declare const token: {
1181
+ (path: Token, fallback?: string): string
1182
+ var: (path: Token, fallback?: string) => string
1183
+ }
3894
1184
 
3895
- export type ${typeName}<T extends ElementType> = ComponentProps<T>
1185
+ ${ctx.file.exportTypeStar("./tokens")}
3896
1186
  `
3897
1187
  };
3898
1188
  }
3899
1189
  //#endregion
3900
- //#region src/artifacts/jsx.ts
3901
- const typesMap = {
3902
- react: generateReactJsxTypes,
3903
- preact: generatePreactJsxTypes,
3904
- solid: generateSolidJsxTypes,
3905
- vue: generateVueJsxTypes,
3906
- qwik: generateQwikJsxTypes
3907
- };
3908
- const typesStringLiteralMap = {
3909
- react: generateReactJsxStringLiteralTypes,
3910
- solid: generateSolidJsxStringLiteralTypes,
3911
- qwik: generateQwikJsxStringLiteralTypes,
3912
- preact: generatePreactJsxStringLiteralTypes,
3913
- vue: generateVueJsxStringLiteralTypes
3914
- };
3915
- const isKnownFramework = (framework) => Boolean(typesMap[framework]);
3916
- function generateJsxTypes(ctx) {
3917
- if (!ctx.jsx.framework) return;
3918
- if (!isKnownFramework(ctx.jsx.framework)) return;
3919
- return (ctx.isTemplateLiteralSyntax ? typesStringLiteralMap[ctx.jsx.framework] : typesMap[ctx.jsx.framework])?.(ctx);
3920
- }
3921
- const factoryMap = {
3922
- react: generateReactJsxFactory,
3923
- solid: generateSolidJsxFactory,
3924
- preact: generatePreactJsxFactory,
3925
- vue: generateVueJsxFactory,
3926
- qwik: generateQwikJsxFactory
3927
- };
3928
- const factoryStringLiteralMap = {
3929
- react: generateReactJsxStringLiteralFactory,
3930
- solid: generateSolidJsxStringLiteralFactory,
3931
- qwik: generateQwikJsxStringLiteralFactory,
3932
- preact: generatePreactJsxStringLiteralFactory,
3933
- vue: generateVueJsxStringLiteralFactory
3934
- };
3935
- function generateJsxFactory(ctx) {
3936
- if (!ctx.jsx.framework) return;
3937
- if (!isKnownFramework(ctx.jsx.framework)) return;
3938
- return (ctx.isTemplateLiteralSyntax ? factoryStringLiteralMap[ctx.jsx.framework] : factoryMap[ctx.jsx.framework])?.(ctx);
3939
- }
3940
- const patternMap = {
3941
- react: generateReactJsxPattern,
3942
- solid: generateSolidJsxPattern,
3943
- preact: generatePreactJsxPattern,
3944
- vue: generateVueJsxPattern,
3945
- qwik: generateQwikJsxPattern
3946
- };
3947
- function generateJsxPatterns(ctx, filters) {
3948
- if (ctx.isTemplateLiteralSyntax || ctx.patterns.isEmpty() || !ctx.jsx.framework) return [];
3949
- if (!isKnownFramework(ctx.jsx.framework)) return;
3950
- return patternMap[ctx.jsx.framework](ctx, filters);
3951
- }
3952
- const createStyleContextMap = {
3953
- react: generateReactCreateStyleContext,
3954
- preact: generatePreactCreateStyleContext,
3955
- solid: generateSolidCreateStyleContext,
3956
- vue: generateVueCreateStyleContext
3957
- };
3958
- function generateJsxCreateStyleContext(ctx) {
3959
- if (ctx.isTemplateLiteralSyntax || !ctx.jsx.framework) return;
3960
- if (!isKnownFramework(ctx.jsx.framework)) return;
3961
- const generator = createStyleContextMap[ctx.jsx.framework];
3962
- return generator?.(ctx);
3963
- }
3964
- //#endregion
3965
1190
  //#region src/artifacts/generated/composition.d.ts.json
3966
1191
  var content$7 = "import type { CompositionStyleObject } from './system-types'\n\ninterface Token<T> {\n value: T\n description?: string\n}\n\ninterface Recursive<T> {\n [key: string]: Recursive<T> | T\n}\n\n/* -----------------------------------------------------------------------------\n * Text styles\n * -----------------------------------------------------------------------------*/\n\ntype TextStyleProperty =\n | 'color'\n | 'direction'\n | 'font'\n | 'fontFamily'\n | 'fontFeatureSettings'\n | 'fontKerning'\n | 'fontLanguageOverride'\n | 'fontOpticalSizing'\n | 'fontPalette'\n | 'fontSize'\n | 'fontSizeAdjust'\n | 'fontStretch'\n | 'fontStyle'\n | 'fontSynthesis'\n | 'fontVariant'\n | 'fontVariantAlternates'\n | 'fontVariantCaps'\n | 'fontVariantLigatures'\n | 'fontVariantNumeric'\n | 'fontVariantPosition'\n | 'fontVariationSettings'\n | 'fontWeight'\n | 'hangingPunctuation'\n | 'hypens'\n | 'hyphenateCharacter'\n | 'hyphenateLimitChars'\n | 'letterSpacing'\n | 'lineBreak'\n | 'lineHeight'\n | 'quotes'\n | 'overflowWrap'\n | 'tabSize'\n | 'textAlign'\n | 'textAlignLast'\n | 'textBox'\n | 'textBoxEdge'\n | 'textBoxTrim'\n | 'textCombineUpright'\n | 'textDecoration'\n | 'textDecorationColor'\n | 'textDecorationLine'\n | 'textDecorationSkip'\n | 'textDecorationSkipBox'\n | 'textDecorationSkipInk'\n | 'textDecorationSkipInset'\n | 'textDecorationStyle'\n | 'textDecorationThickness'\n | 'textEmphasis'\n | 'textEmphasisColor'\n | 'textEmphasisPosition'\n | 'textEmphasisStyle'\n | 'textIndent'\n | 'textJustify'\n | 'textOrientation'\n | 'textOverflow'\n | 'textRendering'\n | 'textShadow'\n | 'textStroke'\n | 'textStrokeColor'\n | 'textStrokeWidth'\n | 'textTransform'\n | 'textUnderlineOffset'\n | 'textUnderlinePosition'\n | 'textWrap'\n | 'textWrapMode'\n | 'textWrapStyle'\n | 'unicodeBidi'\n | 'verticalAlign'\n | 'whiteSpace'\n | 'wordBreak'\n | 'wordSpacing'\n | 'writingMode'\n\nexport type TextStyle = CompositionStyleObject<TextStyleProperty>\n\nexport type TextStyles = Recursive<Token<TextStyle>>\n\n/* -----------------------------------------------------------------------------\n * Layer styles\n * -----------------------------------------------------------------------------*/\n\ntype LogicalPlacement = 'Inline' | 'Block' | 'InlineStart' | 'InlineEnd' | 'BlockStart' | 'BlockEnd'\n\ntype PhysicalPlacement = 'Top' | 'Right' | 'Bottom' | 'Left'\n\ntype Placement = PhysicalPlacement | LogicalPlacement\n\ntype Radius =\n | `Top${'Right' | 'Left'}`\n | `Bottom${'Right' | 'Left'}`\n | `Start${'Start' | 'End'}`\n | `End${'Start' | 'End'}`\n\ntype LayerStyleProperty =\n | 'aspectRatio'\n | 'background'\n | 'backgroundColor'\n | 'backgroundImage'\n | 'border'\n | 'borderColor'\n | 'borderImage'\n | 'borderImageOutset'\n | 'borderImageRepeat'\n | 'borderImageSlice'\n | 'borderImageSource'\n | 'borderImageWidth'\n | 'borderRadius'\n | 'borderStyle'\n | 'borderWidth'\n | `border${Placement}`\n | `border${Placement}Color`\n | `border${Placement}Style`\n | `border${Placement}Width`\n | 'borderRadius'\n | `border${Radius}Radius`\n | 'boxShadow'\n | 'boxShadowColor'\n | 'clipPath'\n | 'color'\n | 'contain'\n | 'content'\n | 'contentVisibility'\n | 'cursor'\n | 'display'\n | 'filter'\n | 'backdropFilter'\n | 'height'\n | 'width'\n | 'minHeight'\n | 'minWidth'\n | 'maxHeight'\n | 'maxWidth'\n | `margin${Placement}`\n | 'inset'\n | `inset${LogicalPlacement}`\n | Lowercase<PhysicalPlacement>\n | 'isolation'\n | 'mask'\n | 'maskClip'\n | 'maskComposite'\n | 'maskImage'\n | 'maskMode'\n | 'maskOrigin'\n | 'maskPosition'\n | 'maskRepeat'\n | 'maskSize'\n | 'mixBlendMode'\n | 'objectFit'\n | 'objectPosition'\n | 'opacity'\n | 'outline'\n | 'outlineColor'\n | 'outlineOffset'\n | 'outlineStyle'\n | 'outlineWidth'\n | 'overflow'\n | 'overflowX'\n | 'overflowY'\n | 'padding'\n | `padding${Placement}`\n | 'pointerEvents'\n | 'position'\n | 'resize'\n | 'transform'\n | 'transition'\n | 'visibility'\n | 'willChange'\n | 'zIndex'\n | 'backgroundBlendMode'\n | 'backgroundAttachment'\n | 'backgroundClip'\n | 'backgroundOrigin'\n | 'backgroundPosition'\n | 'backgroundRepeat'\n | 'backgroundSize'\n\nexport type LayerStyle = CompositionStyleObject<LayerStyleProperty>\n\nexport type LayerStyles = Recursive<Token<LayerStyle>>\n\n/* -----------------------------------------------------------------------------\n * Motion styles\n * -----------------------------------------------------------------------------*/\n\ntype AnimationStyleProperty =\n | 'animation'\n | 'animationComposition'\n | 'animationDelay'\n | 'animationDirection'\n | 'animationDuration'\n | 'animationFillMode'\n | 'animationIterationCount'\n | 'animationName'\n | 'animationPlayState'\n | 'animationTimingFunction'\n | 'animationRange'\n | 'animationRangeStart'\n | 'animationRangeEnd'\n | 'animationTimeline'\n | 'transformOrigin'\n\nexport type AnimationStyle = CompositionStyleObject<AnimationStyleProperty>\n\nexport type AnimationStyles = Recursive<Token<AnimationStyle>>\n\nexport interface CompositionStyles {\n textStyles: TextStyles\n layerStyles: LayerStyles\n animationStyles: AnimationStyles\n}\n";
3967
1192
  //#endregion
@@ -4721,10 +1946,10 @@ var comments = {
4721
1946
  var content$5 = "export interface Part {\n selector: string\n}\n\nexport interface Parts {\n [key: string]: Part\n}\n";
4722
1947
  //#endregion
4723
1948
  //#region src/artifacts/generated/pattern.d.ts.json
4724
- var content$4 = "import type { CssProperty, SystemStyleObject } from './system-types'\nimport type { TokenCategory } from '../tokens'\n\ntype Primitive = string | number | boolean | null | undefined\ntype LiteralUnion<T, K extends Primitive = string> = T | (K & Record<never, never>)\n\nexport type PatternProperty =\n | { type: 'property'; value: CssProperty; description?: string }\n | { type: 'enum'; value: string[]; description?: string }\n | { type: 'token'; value: TokenCategory; property?: CssProperty; description?: string }\n | { type: 'string' | 'boolean' | 'number'; description?: string }\n\nexport interface PatternHelpers {\n map: (value: any, fn: (value: string) => string | undefined) => any\n isCssUnit: (value: any) => boolean\n isCssVar: (value: any) => boolean\n isCssFunction: (value: any) => boolean\n}\n\nexport interface PatternProperties {\n [key: string]: PatternProperty\n}\n\ntype InferProps<T> = Record<LiteralUnion<keyof T>, any>\n\nexport type PatternDefaultValue<T> = Partial<InferProps<T>>\n\nexport type PatternDefaultValueFn<T> = (props: InferProps<T>) => PatternDefaultValue<T>\n\nexport interface PatternConfig<T extends PatternProperties = PatternProperties> {\n /**\n * The description of the pattern. This will be used in the JSDoc comment.\n */\n description?: string\n /**\n * The JSX element rendered by the pattern\n * @default 'div'\n */\n jsxElement?: string\n /**\n * The properties of the pattern.\n */\n properties?: T\n /**\n * The default values of the pattern.\n */\n defaultValues?: PatternDefaultValue<T> | PatternDefaultValueFn<T>\n /**\n * The css object this pattern will generate.\n */\n transform?: (props: InferProps<T>, helpers: PatternHelpers) => SystemStyleObject\n /**\n * Whether the pattern is deprecated.\n */\n deprecated?: boolean | string\n /**\n * The jsx element name this pattern will generate.\n */\n jsxName?: string\n /**\n * The jsx elements to track for this pattern. Can be string or Regexp.\n *\n * @default capitalize(pattern.name)\n * @example ['Button', 'Link', /Button$/]\n */\n jsx?: Array<string | RegExp>\n /**\n * Whether to only generate types for the specified properties.\n * This will disallow css properties\n */\n strict?: boolean\n /**\n * @experimental\n * Disallow certain css properties for this pattern\n */\n blocklist?: LiteralUnion<CssProperty>[]\n}\n";
1949
+ var content$4 = "import type { CssProperty, SystemStyleObject } from './system-types'\nimport type { TokenCategory } from '../tokens'\n\ntype Primitive = string | number | boolean | null | undefined\ntype LiteralUnion<T, K extends Primitive = string> = T | (K & Record<never, never>)\n\nexport type PatternProperty =\n | { type: 'property'; value: CssProperty; description?: string }\n | { type: 'enum'; value: string[]; description?: string }\n | { type: 'token'; value: TokenCategory; property?: CssProperty; description?: string }\n | { type: 'string' | 'boolean' | 'number'; description?: string }\n\nexport interface PatternHelpers {\n map: (value: any, fn: (value: string) => string | undefined) => any\n isCssUnit: (value: any) => boolean\n isCssVar: (value: any) => boolean\n isCssFunction: (value: any) => boolean\n}\n\nexport interface PatternProperties {\n [key: string]: PatternProperty\n}\n\ntype InferProps<T> = Record<LiteralUnion<keyof T>, any>\n\nexport type PatternDefaultValue<T> = Partial<InferProps<T>>\n\nexport type PatternDefaultValueFn<T> = (props: InferProps<T>) => PatternDefaultValue<T>\n\nexport interface PatternConfig<T extends PatternProperties = PatternProperties> {\n /**\n * The description of the pattern. This will be used in the JSDoc comment.\n */\n description?: string\n /**\n * The properties of the pattern.\n */\n properties?: T\n /**\n * The default values of the pattern.\n */\n defaultValues?: PatternDefaultValue<T> | PatternDefaultValueFn<T>\n /**\n * The css object this pattern will generate.\n */\n transform?: (props: InferProps<T>, helpers: PatternHelpers) => SystemStyleObject\n /**\n * Whether the pattern is deprecated.\n */\n deprecated?: boolean | string\n /**\n * Whether to only generate types for the specified properties.\n * This will disallow css properties\n */\n strict?: boolean\n /**\n * @experimental\n * Disallow certain css properties for this pattern\n */\n blocklist?: LiteralUnion<CssProperty>[]\n}\n";
4725
1950
  //#endregion
4726
1951
  //#region src/artifacts/generated/recipe.d.ts.json
4727
- var content$3 = "import type { RecipeRule } from './static-css'\nimport type { SystemStyleObject, DistributiveOmit, Pretty } from './system-types'\n\ntype StringToBoolean<T> = T extends 'true' | 'false' ? boolean : T\n\nexport type RecipeVariantRecord = Record<any, Record<any, SystemStyleObject>>\n\nexport type RecipeSelection<T extends RecipeVariantRecord> = keyof any extends keyof T\n ? {}\n : {\n [K in keyof T]?: StringToBoolean<keyof T[K]> | undefined\n }\n\nexport type RecipeVariantFn<T extends RecipeVariantRecord> = (props?: RecipeSelection<T>) => string\n\n/**\n * Extract the variant as optional props from a `cva` function.\n * Intended to be used with a JSX component, prefer `RecipeVariant` for a more strict type.\n */\nexport type RecipeVariantProps<\n T extends RecipeVariantFn<RecipeVariantRecord> | SlotRecipeVariantFn<string, SlotRecipeVariantRecord<string>>,\n> = Pretty<Parameters<T>[0]>\n\n/**\n * Extract the variants from a `cva` function.\n */\nexport type RecipeVariant<\n T extends RecipeVariantFn<RecipeVariantRecord> | SlotRecipeVariantFn<string, SlotRecipeVariantRecord<string>>,\n> = Exclude<Pretty<Required<RecipeVariantProps<T>>>, undefined>\n\ntype RecipeVariantMap<T extends RecipeVariantRecord> = {\n [K in keyof T]: Array<keyof T[K]>\n}\n\n/* -----------------------------------------------------------------------------\n * Recipe / Standard\n * -----------------------------------------------------------------------------*/\n\nexport interface RecipeRuntimeFn<T extends RecipeVariantRecord> extends RecipeVariantFn<T> {\n __type: RecipeSelection<T>\n variantKeys: (keyof T)[]\n variantMap: RecipeVariantMap<T>\n raw: (props?: RecipeSelection<T>) => SystemStyleObject\n config: RecipeConfig<T>\n splitVariantProps<Props extends RecipeSelection<T>>(\n props: Props,\n ): [RecipeSelection<T>, Pretty<DistributiveOmit<Props, keyof T>>]\n getVariantProps: (props?: RecipeSelection<T>) => RecipeSelection<T>\n}\n\ntype OneOrMore<T> = T | Array<T>\n\nexport type RecipeCompoundSelection<T> = {\n [K in keyof T]?: OneOrMore<StringToBoolean<keyof T[K]>> | undefined\n}\n\nexport type RecipeCompoundVariant<T> = T & {\n css: SystemStyleObject\n}\n\nexport interface RecipeDefinition<T extends RecipeVariantRecord = RecipeVariantRecord> {\n /**\n * The base styles of the recipe.\n */\n base?: SystemStyleObject\n /**\n * Whether the recipe is deprecated.\n */\n deprecated?: boolean | string\n /**\n * The multi-variant styles of the recipe.\n */\n variants?: T\n /**\n * The default variants of the recipe.\n */\n defaultVariants?: RecipeSelection<T>\n /**\n * The styles to apply when a combination of variants is selected.\n */\n compoundVariants?: Pretty<RecipeCompoundVariant<RecipeCompoundSelection<T>>>[]\n}\n\nexport type RecipeCreatorFn = <T extends RecipeVariantRecord>(config: RecipeDefinition<T>) => RecipeRuntimeFn<T>\n\ninterface RecipeConfigMeta {\n /**\n * The class name of the recipe.\n */\n className: string\n /**\n * The description of the recipe. This will be used in the JSDoc comment.\n */\n description?: string\n /**\n * The jsx elements to track for this recipe. Can be string or Regexp.\n *\n * @default capitalize(recipe.name)\n * @example ['Button', 'Link', /Button$/]\n */\n jsx?: Array<string | RegExp>\n /**\n * Variants to pre-generate, will be include in the final `config.staticCss`\n */\n staticCss?: RecipeRule[]\n}\n\nexport interface RecipeConfig<T extends RecipeVariantRecord = RecipeVariantRecord>\n extends RecipeDefinition<T>, RecipeConfigMeta {}\n\n/* -----------------------------------------------------------------------------\n * Recipe / Slot\n * -----------------------------------------------------------------------------*/\n\ntype SlotRecord<S extends string, T> = Partial<Record<S, T>>\n\nexport type SlotRecipeVariantRecord<S extends string> = Record<any, Record<any, SlotRecord<S, SystemStyleObject>>>\n\nexport type SlotRecipeVariantFn<S extends string, T extends RecipeVariantRecord> = (\n props?: RecipeSelection<T>,\n) => SlotRecord<S, string>\n\nexport interface SlotRecipeRuntimeFn<\n S extends string,\n T extends SlotRecipeVariantRecord<S>,\n> extends SlotRecipeVariantFn<S, T> {\n raw: (props?: RecipeSelection<T>) => Record<S, SystemStyleObject>\n variantKeys: (keyof T)[]\n variantMap: RecipeVariantMap<T>\n splitVariantProps<Props extends RecipeSelection<T>>(\n props: Props,\n ): [RecipeSelection<T>, Pretty<DistributiveOmit<Props, keyof T>>]\n getVariantProps: (props?: RecipeSelection<T>) => RecipeSelection<T>\n}\n\nexport type SlotRecipeCompoundVariant<S extends string, T> = T & {\n css: SlotRecord<S, SystemStyleObject>\n}\n\nexport interface SlotRecipeDefinition<\n S extends string = string,\n T extends SlotRecipeVariantRecord<S> = SlotRecipeVariantRecord<S>,\n> {\n /**\n * An optional class name that can be used to target slots in the DOM.\n */\n className?: string\n /**\n * Whether the recipe is deprecated.\n */\n deprecated?: boolean | string\n /**\n * The parts/slots of the recipe.\n */\n slots: S[] | Readonly<S[]>\n /**\n * The base styles of the recipe.\n */\n base?: SlotRecord<S, SystemStyleObject>\n /**\n * The multi-variant styles of the recipe.\n */\n variants?: T\n /**\n * The default variants of the recipe.\n */\n defaultVariants?: RecipeSelection<T>\n /**\n * The styles to apply when a combination of variants is selected.\n */\n compoundVariants?: Pretty<SlotRecipeCompoundVariant<S, RecipeCompoundSelection<T>>>[]\n}\n\nexport type SlotRecipeCreatorFn = <S extends string, T extends SlotRecipeVariantRecord<S>>(\n config: SlotRecipeDefinition<S, T>,\n) => SlotRecipeRuntimeFn<S, T>\n\nexport type SlotRecipeConfig<\n S extends string = string,\n T extends SlotRecipeVariantRecord<S> = SlotRecipeVariantRecord<S>,\n> = SlotRecipeDefinition<S, T> & RecipeConfigMeta\n";
1952
+ var content$3 = "import type { RecipeRule } from './static-css'\nimport type { SystemStyleObject, DistributiveOmit, Pretty } from './system-types'\n\ntype StringToBoolean<T> = T extends 'true' | 'false' ? boolean : T\n\nexport type RecipeVariantRecord = Record<any, Record<any, SystemStyleObject>>\n\nexport type RecipeSelection<T extends RecipeVariantRecord> = keyof any extends keyof T\n ? {}\n : {\n [K in keyof T]?: StringToBoolean<keyof T[K]> | undefined\n }\n\nexport type RecipeVariantFn<T extends RecipeVariantRecord> = (props?: RecipeSelection<T>) => string\n\n/**\n * Extract the variant as optional props from a `cva` function.\n * Intended to be used with a JSX component, prefer `RecipeVariant` for a more strict type.\n */\nexport type RecipeVariantProps<\n T extends RecipeVariantFn<RecipeVariantRecord> | SlotRecipeVariantFn<string, SlotRecipeVariantRecord<string>>,\n> = Pretty<Parameters<T>[0]>\n\n/**\n * Extract the variants from a `cva` function.\n */\nexport type RecipeVariant<\n T extends RecipeVariantFn<RecipeVariantRecord> | SlotRecipeVariantFn<string, SlotRecipeVariantRecord<string>>,\n> = Exclude<Pretty<Required<RecipeVariantProps<T>>>, undefined>\n\ntype RecipeVariantMap<T extends RecipeVariantRecord> = {\n [K in keyof T]: Array<keyof T[K]>\n}\n\n/* -----------------------------------------------------------------------------\n * Recipe / Standard\n * -----------------------------------------------------------------------------*/\n\nexport interface RecipeRuntimeFn<T extends RecipeVariantRecord> extends RecipeVariantFn<T> {\n __type: RecipeSelection<T>\n variantKeys: (keyof T)[]\n variantMap: RecipeVariantMap<T>\n raw: (props?: RecipeSelection<T>) => SystemStyleObject\n config: RecipeConfig<T>\n splitVariantProps<Props extends RecipeSelection<T>>(\n props: Props,\n ): [RecipeSelection<T>, Pretty<DistributiveOmit<Props, keyof T>>]\n getVariantProps: (props?: RecipeSelection<T>) => RecipeSelection<T>\n}\n\ntype OneOrMore<T> = T | Array<T>\n\nexport type RecipeCompoundSelection<T> = {\n [K in keyof T]?: OneOrMore<StringToBoolean<keyof T[K]>> | undefined\n}\n\nexport type RecipeCompoundVariant<T> = T & {\n css: SystemStyleObject\n}\n\nexport interface RecipeDefinition<T extends RecipeVariantRecord = RecipeVariantRecord> {\n /**\n * The base styles of the recipe.\n */\n base?: SystemStyleObject\n /**\n * The prefix every class this recipe emits is built from — `button` gives `button` for\n * the base styles and `button--size_sm` for a variant.\n *\n * Required for a recipe declared in `theme.recipes`, where it is the key it is declared\n * under. Optional for an inline `cva`, which is otherwise named by hashing its own\n * config: `cva_a1b2c3--size_sm`. Setting it buys readable class names and nothing else —\n * the CSS is identical either way.\n *\n * It has to be unique across every recipe in the build. Two recipes sharing a name emit\n * rules under the same selectors, and the later one wins for any variant they both\n * declare.\n */\n className?: string\n /**\n * Whether the recipe is deprecated.\n */\n deprecated?: boolean | string\n /**\n * The multi-variant styles of the recipe.\n */\n variants?: T\n /**\n * The default variants of the recipe.\n */\n defaultVariants?: RecipeSelection<T>\n /**\n * The styles to apply when a combination of variants is selected.\n */\n compoundVariants?: Pretty<RecipeCompoundVariant<RecipeCompoundSelection<T>>>[]\n}\n\nexport type RecipeCreatorFn = <T extends RecipeVariantRecord>(config: RecipeDefinition<T>) => RecipeRuntimeFn<T>\n\ninterface RecipeConfigMeta {\n /**\n * The description of the recipe. This will be used in the JSDoc comment.\n */\n description?: string\n /**\n * The jsx elements to track for this recipe. Can be string or Regexp.\n *\n * @default capitalize(recipe.name)\n * @example ['Button', 'Link', /Button$/]\n */\n jsx?: Array<string | RegExp>\n /**\n * Variants to pre-generate, will be include in the final `config.staticCss`\n */\n staticCss?: RecipeRule[]\n}\n\nexport interface RecipeConfig<T extends RecipeVariantRecord = RecipeVariantRecord>\n extends RecipeDefinition<T>, RecipeConfigMeta {\n /** Optional on `RecipeDefinition`, where an inline `cva` falls back to hashing its config. A recipe declared in `theme.recipes` always has one — the key it is declared under. */\n className: string\n}\n\n/* -----------------------------------------------------------------------------\n * Recipe / Slot\n * -----------------------------------------------------------------------------*/\n\ntype SlotRecord<S extends string, T> = Partial<Record<S, T>>\n\nexport type SlotRecipeVariantRecord<S extends string> = Record<any, Record<any, SlotRecord<S, SystemStyleObject>>>\n\nexport type SlotRecipeVariantFn<S extends string, T extends RecipeVariantRecord> = (\n props?: RecipeSelection<T>,\n) => SlotRecord<S, string>\n\nexport interface SlotRecipeRuntimeFn<\n S extends string,\n T extends SlotRecipeVariantRecord<S>,\n> extends SlotRecipeVariantFn<S, T> {\n raw: (props?: RecipeSelection<T>) => Record<S, SystemStyleObject>\n variantKeys: (keyof T)[]\n variantMap: RecipeVariantMap<T>\n /** The config this recipe was created from. */\n config: SlotRecipeDefinition<S, T>\n /** Each slot's constant class, for targeting a slot in the DOM. */\n classNameMap: Partial<Record<S, string>>\n /**\n * Which slots each variant writes styles for.\n *\n * A variant's styles reach a slot through a scope opened at an anchor, which covers every\n * slot in that anchor's subtree. A slot under no anchor — moved out by a portal, with no\n * second anchor named in `scopeRoots` — is not reached, and nothing at build time can\n * detect that. This says which slots a variant has to get to, so whatever a scope cannot\n * reach can be threaded by hand.\n */\n slotsAffectedBy: Record<keyof T, S[]>\n splitVariantProps<Props extends RecipeSelection<T>>(\n props: Props,\n ): [RecipeSelection<T>, Pretty<DistributiveOmit<Props, keyof T>>]\n getVariantProps: (props?: RecipeSelection<T>) => RecipeSelection<T>\n}\n\nexport type SlotRecipeCompoundVariant<S extends string, T> = T & {\n css: SlotRecord<S, SystemStyleObject>\n}\n\nexport interface SlotRecipeDefinition<\n S extends string = string,\n T extends SlotRecipeVariantRecord<S> = SlotRecipeVariantRecord<S>,\n> {\n /**\n * The prefix every class this recipe emits is built from, and the name to target its\n * slots in the DOM by — `checkbox` gives `checkbox__control` for a slot and\n * `checkbox__control--size_md` for that slot under a variant.\n *\n * Required for a recipe declared in `theme.slotRecipes`, where it is the key it is\n * declared under. Optional for an inline `sva`, which is otherwise named by hashing its\n * own config. Setting it buys readable class names and nothing else — the CSS is\n * identical either way.\n *\n * It has to be unique across every recipe in the build.\n */\n className?: string\n /**\n * Whether the recipe is deprecated.\n */\n deprecated?: boolean | string\n /**\n * The parts/slots of the recipe.\n */\n slots: S[] | Readonly<S[]>\n /**\n * The slots that enclose other slots, used to scope their variant styles.\n *\n * A slot recipe's variants are chosen once, at the top, but the slots that react to them\n * are authored by the consumer somewhere below. Naming the enclosing slots lets the build\n * emit their variant styles as rules scoped by a class those slots already carry, so\n * nothing has to be delivered to a slot at runtime and every other slot's class is a\n * constant.\n *\n * A list, because a portal is a real discontinuity in the tree and no CSS mechanism\n * crosses one. A `<Select>` occupies two disjoint subtrees — the trigger side under\n * `root`, the listbox side under a portaled `positioner` — and a variant writes styles\n * into both. One anchor can only ever reach one of them.\n *\n * ```ts\n * scopeRoots: ['root', 'positioner']\n * ```\n *\n * Each named slot takes variant props; every other slot's class is a constant. The build\n * emits each non-anchor slot's variant rules under *every* anchor, and only the anchor\n * that is genuinely an ancestor matches — so the DOM shape never has to be declared.\n *\n * Defaults to `['root']` when a slot by that name exists. Set `[]` to turn scoping off\n * and give every slot a variant class of its own, which is what a recipe whose slots are\n * siblings wants.\n *\n * A slot under *no* anchor is still unreachable, and nothing at build time can detect\n * that — reachability is a fact about the DOM. `recipe.slotsAffectedBy` says which slots\n * a variant writes to, for whatever still needs threading by hand.\n */\n scopeRoots?: S[] | Readonly<S[]>\n /**\n * The base styles of the recipe.\n */\n base?: SlotRecord<S, SystemStyleObject>\n /**\n * The multi-variant styles of the recipe.\n */\n variants?: T\n /**\n * The default variants of the recipe.\n */\n defaultVariants?: RecipeSelection<T>\n /**\n * The styles to apply when a combination of variants is selected.\n */\n compoundVariants?: Pretty<SlotRecipeCompoundVariant<S, RecipeCompoundSelection<T>>>[]\n}\n\nexport type SlotRecipeCreatorFn = <S extends string, T extends SlotRecipeVariantRecord<S>>(\n config: SlotRecipeDefinition<S, T>,\n) => SlotRecipeRuntimeFn<S, T>\n\nexport type SlotRecipeConfig<\n S extends string = string,\n T extends SlotRecipeVariantRecord<S> = SlotRecipeVariantRecord<S>,\n> = SlotRecipeDefinition<S, T> &\n RecipeConfigMeta & {\n /** Optional on `SlotRecipeDefinition`, where an inline `sva` falls back to hashing its config. A recipe declared in `theme.slotRecipes` always has one — the key it is declared under. */\n className: string\n }\n";
4728
1953
  //#endregion
4729
1954
  //#region src/artifacts/generated/selectors.d.ts.json
4730
1955
  var content$2 = "import type { Pseudos } from './csstype'\n\ntype AriaAttributes =\n | '[aria-disabled]'\n | '[aria-hidden]'\n | '[aria-invalid]'\n | '[aria-readonly]'\n | '[aria-required]'\n | '[aria-selected]'\n | '[aria-checked]'\n | '[aria-expanded]'\n | '[aria-pressed]'\n | `[aria-current=${'page' | 'step' | 'location' | 'date' | 'time'}]`\n | '[aria-invalid]'\n | `[aria-sort=${'ascending' | 'descending'}]`\n\ntype DataAttributes =\n | '[data-selected]'\n | '[data-highlighted]'\n | '[data-hover]'\n | '[data-active]'\n | '[data-checked]'\n | '[data-disabled]'\n | '[data-readonly]'\n | '[data-focus]'\n | '[data-focus-visible]'\n | '[data-focus-visible-added]'\n | '[data-invalid]'\n | '[data-pressed]'\n | '[data-expanded]'\n | '[data-grabbed]'\n | '[data-dragged]'\n | '[data-orientation=horizontal]'\n | '[data-orientation=vertical]'\n | '[data-in-range]'\n | '[data-out-of-range]'\n | '[data-placeholder-shown]'\n | `[data-part=${string}]`\n | `[data-attr=${string}]`\n | `[data-placement=${string}]`\n | `[data-theme=${string}]`\n | `[data-size=${string}]`\n | `[data-state=${string}]`\n | '[data-empty]'\n | '[data-loading]'\n | '[data-loaded]'\n | '[data-enter]'\n | '[data-entering]'\n | '[data-exited]'\n | '[data-exiting]'\n\ntype AttributeSelector = `&${Pseudos | DataAttributes | AriaAttributes}`\ntype ParentSelector = `${DataAttributes | AriaAttributes} &`\n\ntype AtRuleType = 'media' | 'layer' | 'container' | 'supports' | 'page' | 'scope' | 'starting-style'\n\nexport type AnySelector = `${string}&` | `&${string}` | `@${AtRuleType}${string}`\nexport type Selectors = AttributeSelector | ParentSelector\n";
@@ -4733,7 +1958,7 @@ var content$2 = "import type { Pseudos } from './csstype'\n\ntype AriaAttributes
4733
1958
  var content$1 = "interface ConditionOptions {\n /**\n * The conditions to generate for the rule.\n * @example ['hover', 'focus']\n */\n conditions?: string[]\n /**\n * Whether to generate responsive styles for the rule.\n */\n responsive?: boolean\n}\n\nexport interface CssRule extends ConditionOptions {\n /**\n * The css properties to generate utilities for.\n * @example ['margin', 'padding']\n */\n properties: {\n [property: string]: Array<string | number>\n }\n}\n\ninterface RecipeRuleVariants {\n [variant: string]: boolean | string[]\n}\n\nexport type RecipeRuleObject = RecipeRuleVariants & ConditionOptions\nexport type RecipeRule = '*' | RecipeRuleObject\n\nexport type PatternRule = '*' | CssRule\n\nexport interface StaticCssOptions {\n /**\n * The css utility classes to generate.\n */\n css?: CssRule[]\n /**\n * The css recipes to generate.\n */\n recipes?:\n | '*'\n | {\n [recipe: string]: RecipeRule[]\n }\n /**\n * The css patterns to generate.\n */\n patterns?: {\n [pattern: string]: PatternRule[]\n }\n /**\n * The CSS themes to generate\n */\n themes?: string[]\n}\n";
4734
1959
  //#endregion
4735
1960
  //#region src/artifacts/generated/system-types.d.ts.json
4736
- var content = "import type { ConditionalValue, Nested } from './conditions'\nimport type { AtRule, Globals, PropertiesFallback } from './csstype'\nimport type { SystemProperties, CssVarProperties } from './style-props'\n\ntype String = string & {}\ntype Number = number & {}\n\nexport type Pretty<T> = { [K in keyof T]: T[K] } & {}\n\nexport type DistributiveOmit<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never\n\nexport type DistributiveUnion<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] | T[K] : T[K]\n} & DistributiveOmit<U, keyof T>\n\nexport type Assign<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] : T[K]\n} & U\n\n/* -----------------------------------------------------------------------------\n * Native css properties\n * -----------------------------------------------------------------------------*/\n\ntype CornerShapeValue = 'round' | 'square' | 'bevel' | 'scoop' | 'notch' | 'squircle' | `superellipse(${number})`\n\nexport interface ModernCssProperties {\n /**\n * Controls whether the entire element should be draggable instead of its contents.\n */\n WebkitUserDrag?: Globals | 'auto' | 'element' | 'none'\n\n /**\n * Specifies whether an element can be used to drag the entire app window (Electron).\n */\n WebkitAppRegion?: Globals | 'drag' | 'no-drag'\n\n /**\n * Sets the horizontal spacing between table borders.\n */\n WebkitBorderHorizontalSpacing?: Globals | String | Number\n\n /**\n * Sets the vertical spacing between table borders.\n */\n WebkitBorderVerticalSpacing?: Globals | String | Number\n\n /**\n * Controls the display of text content for security purposes (e.g., password fields).\n */\n WebkitTextSecurity?: Globals | 'none' | 'circle' | 'disc' | 'square'\n\n /**\n * Specifies the shape of a box's corners within the area defined by the border-radius property.\n * @experimental\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/corner-shape\n */\n cornerShape?:\n | Globals\n | CornerShapeValue\n | `${CornerShapeValue} ${CornerShapeValue}`\n | `${CornerShapeValue} ${CornerShapeValue} ${CornerShapeValue}`\n | `${CornerShapeValue} ${CornerShapeValue} ${CornerShapeValue} ${CornerShapeValue}`\n | String\n}\n\nexport type CssProperty = keyof PropertiesFallback\n\nexport interface CssProperties extends PropertiesFallback<String | Number>, CssVarProperties, ModernCssProperties {}\n\nexport interface CssKeyframes {\n [name: string]: {\n [time: string]: CssProperties\n }\n}\n\n/* -----------------------------------------------------------------------------\n * Conditional css properties\n * -----------------------------------------------------------------------------*/\n\ninterface GenericProperties {\n [key: string]: ConditionalValue<String | Number | boolean>\n}\n\n/* -----------------------------------------------------------------------------\n * Native css props\n * -----------------------------------------------------------------------------*/\n\nexport type NestedCssProperties = Nested<CssProperties>\n\nexport type SystemStyleObject = Omit<Nested<SystemProperties & CssVarProperties>, 'base'>\n\nexport interface GlobalStyleObject {\n [selector: string]: SystemStyleObject\n}\nexport interface ExtendableGlobalStyleObject {\n [selector: string]: SystemStyleObject | undefined\n extend?: GlobalStyleObject | undefined\n}\n\n/* -----------------------------------------------------------------------------\n * Composition (text styles, layer styles)\n * -----------------------------------------------------------------------------*/\n\ntype FilterStyleObject<P extends string> = {\n [K in P]?: K extends keyof SystemStyleObject ? SystemStyleObject[K] : unknown\n}\n\nexport type CompositionStyleObject<Property extends string> = Nested<FilterStyleObject<Property> & CssVarProperties>\n\n/* -----------------------------------------------------------------------------\n * Font face\n * -----------------------------------------------------------------------------*/\n\nexport type GlobalFontfaceRule = Omit<AtRule.FontFaceFallback, 'src'> & Required<Pick<AtRule.FontFaceFallback, 'src'>>\n\nexport type FontfaceRule = Omit<GlobalFontfaceRule, 'fontFamily'>\n\nexport interface GlobalFontface {\n [name: string]: FontfaceRule | FontfaceRule[]\n}\n\nexport interface ExtendableGlobalFontface {\n [name: string]: FontfaceRule | FontfaceRule[] | GlobalFontface | undefined\n extend?: GlobalFontface | undefined\n}\n\n/* -----------------------------------------------------------------------------\n * Jsx style props\n * -----------------------------------------------------------------------------*/\ninterface WithCss {\n css?: SystemStyleObject | SystemStyleObject[]\n}\n\nexport type JsxStyleProps = SystemStyleObject & WithCss\n\nexport interface PatchedHTMLProps {\n htmlWidth?: string | number\n htmlHeight?: string | number\n htmlTranslate?: 'yes' | 'no' | undefined\n htmlContent?: string\n}\n\nexport type OmittedHTMLProps = 'color' | 'translate' | 'transition' | 'width' | 'height' | 'content'\n\ntype WithHTMLProps<T> = DistributiveOmit<T, OmittedHTMLProps> & PatchedHTMLProps\n\nexport type JsxHTMLProps<T extends Record<string, any>, P extends Record<string, any> = {}> = Assign<\n WithHTMLProps<T>,\n P\n>\n";
1961
+ var content = "import type { ConditionalValue, Nested } from './conditions'\nimport type { AtRule, Globals, PropertiesFallback } from './csstype'\nimport type { SystemProperties, CssVarProperties } from './style-props'\n\ntype String = string & {}\ntype Number = number & {}\n\nexport type Pretty<T> = { [K in keyof T]: T[K] } & {}\n\nexport type DistributiveOmit<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never\n\nexport type DistributiveUnion<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] | T[K] : T[K]\n} & DistributiveOmit<U, keyof T>\n\nexport type Assign<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] : T[K]\n} & U\n\n/* -----------------------------------------------------------------------------\n * Native css properties\n * -----------------------------------------------------------------------------*/\n\ntype CornerShapeValue = 'round' | 'square' | 'bevel' | 'scoop' | 'notch' | 'squircle' | `superellipse(${number})`\n\nexport interface ModernCssProperties {\n /**\n * Controls whether the entire element should be draggable instead of its contents.\n */\n WebkitUserDrag?: Globals | 'auto' | 'element' | 'none'\n\n /**\n * Specifies whether an element can be used to drag the entire app window (Electron).\n */\n WebkitAppRegion?: Globals | 'drag' | 'no-drag'\n\n /**\n * Sets the horizontal spacing between table borders.\n */\n WebkitBorderHorizontalSpacing?: Globals | String | Number\n\n /**\n * Sets the vertical spacing between table borders.\n */\n WebkitBorderVerticalSpacing?: Globals | String | Number\n\n /**\n * Controls the display of text content for security purposes (e.g., password fields).\n */\n WebkitTextSecurity?: Globals | 'none' | 'circle' | 'disc' | 'square'\n\n /**\n * Specifies the shape of a box's corners within the area defined by the border-radius property.\n * @experimental\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/corner-shape\n */\n cornerShape?:\n | Globals\n | CornerShapeValue\n | `${CornerShapeValue} ${CornerShapeValue}`\n | `${CornerShapeValue} ${CornerShapeValue} ${CornerShapeValue}`\n | `${CornerShapeValue} ${CornerShapeValue} ${CornerShapeValue} ${CornerShapeValue}`\n | String\n}\n\nexport type CssProperty = keyof PropertiesFallback\n\nexport interface CssProperties extends PropertiesFallback<String | Number>, CssVarProperties, ModernCssProperties {}\n\nexport interface CssKeyframes {\n [name: string]: {\n [time: string]: CssProperties\n }\n}\n\n/* -----------------------------------------------------------------------------\n * Conditional css properties\n * -----------------------------------------------------------------------------*/\n\ninterface GenericProperties {\n [key: string]: ConditionalValue<String | Number | boolean>\n}\n\n/* -----------------------------------------------------------------------------\n * Native css props\n * -----------------------------------------------------------------------------*/\n\nexport type NestedCssProperties = Nested<CssProperties>\n\nexport type SystemStyleObject = Omit<Nested<SystemProperties & CssVarProperties>, 'base'>\n\n/**\n * The four `::view-transition-*` pseudo-elements a `viewTransition()` bag can style.\n *\n * `imagePair` is camelCase here and emitted as `::view-transition-image-pair`, matching\n * how every other property in a style object is authored.\n */\nexport interface ViewTransitionStyleObject {\n group?: SystemStyleObject\n imagePair?: SystemStyleObject\n old?: SystemStyleObject\n new?: SystemStyleObject\n}\n\nexport type ViewTransitionFn = (options: ViewTransitionStyleObject) => string\n\nexport interface GlobalStyleObject {\n [selector: string]: SystemStyleObject\n}\nexport interface ExtendableGlobalStyleObject {\n [selector: string]: SystemStyleObject | undefined\n extend?: GlobalStyleObject | undefined\n}\n\n/* -----------------------------------------------------------------------------\n * Composition (text styles, layer styles)\n * -----------------------------------------------------------------------------*/\n\ntype FilterStyleObject<P extends string> = {\n [K in P]?: K extends keyof SystemStyleObject ? SystemStyleObject[K] : unknown\n}\n\nexport type CompositionStyleObject<Property extends string> = Nested<FilterStyleObject<Property> & CssVarProperties>\n\n/* -----------------------------------------------------------------------------\n * Font face\n * -----------------------------------------------------------------------------*/\n\nexport type GlobalFontfaceRule = Omit<AtRule.FontFaceFallback, 'src'> & Required<Pick<AtRule.FontFaceFallback, 'src'>>\n\nexport type FontfaceRule = Omit<GlobalFontfaceRule, 'fontFamily'>\n\nexport interface GlobalFontface {\n [name: string]: FontfaceRule | FontfaceRule[]\n}\n\nexport interface ExtendableGlobalFontface {\n [name: string]: FontfaceRule | FontfaceRule[] | GlobalFontface | undefined\n extend?: GlobalFontface | undefined\n}\n\n/* -----------------------------------------------------------------------------\n * Jsx style props\n * -----------------------------------------------------------------------------*/\ninterface WithCss {\n css?: SystemStyleObject | SystemStyleObject[]\n}\n\nexport type JsxStyleProps = SystemStyleObject & WithCss\n\nexport interface PatchedHTMLProps {\n htmlWidth?: string | number\n htmlHeight?: string | number\n htmlTranslate?: 'yes' | 'no' | undefined\n htmlContent?: string\n}\n\nexport type OmittedHTMLProps = 'color' | 'translate' | 'transition' | 'width' | 'height' | 'content'\n\ntype WithHTMLProps<T> = DistributiveOmit<T, OmittedHTMLProps> & PatchedHTMLProps\n\nexport type JsxHTMLProps<T extends Record<string, any>, P extends Record<string, any> = {}> = Assign<\n WithHTMLProps<T>,\n P\n>\n";
4737
1962
  //#endregion
4738
1963
  //#region src/artifacts/types/generated.ts
4739
1964
  function getGeneratedTypes(ctx) {
@@ -4747,20 +1972,18 @@ function getGeneratedTypes(ctx) {
4747
1972
  selectors: ctx.file.rewriteTypeImport(content$2)
4748
1973
  };
4749
1974
  }
4750
- const jsxStyleProps = "export type JsxStyleProps = SystemStyleObject & WithCss";
4751
1975
  function getGeneratedSystemTypes(ctx) {
4752
- return { system: ctx.file.rewriteTypeImport((0, ts_pattern.match)(ctx.jsx.styleProps).with("all", () => content).with("minimal", () => content.replace("WithHTMLProps<T>,", "T,").replace(jsxStyleProps, "export type JsxStyleProps = WithCss")).with("none", () => content.replace("WithHTMLProps<T>,", "T,").replace(jsxStyleProps, "export type JsxStyleProps = {}")).exhaustive()) };
1976
+ return { system: ctx.file.rewriteTypeImport(content) };
4753
1977
  }
4754
1978
  //#endregion
4755
1979
  //#region src/artifacts/types/main.ts
4756
- const generateTypesEntry = (ctx, isJsxRequired) => {
1980
+ const generateTypesEntry = (ctx) => {
4757
1981
  const indexExports = [
4758
1982
  `import '${ctx.file.extDts("./global")}'`,
4759
1983
  ctx.file.exportTypeStar("./conditions"),
4760
1984
  ctx.file.exportTypeStar("./pattern"),
4761
1985
  ctx.file.exportTypeStar("./recipe"),
4762
1986
  ctx.file.exportTypeStar("./system-types"),
4763
- isJsxRequired && ctx.file.exportTypeStar("./jsx"),
4764
1987
  ctx.file.exportTypeStar("./style-props")
4765
1988
  ].filter(Boolean);
4766
1989
  return {
@@ -5265,7 +2488,7 @@ function generateThemesIndex(ctx, files) {
5265
2488
  //#endregion
5266
2489
  //#region src/artifacts/setup-artifacts.ts
5267
2490
  function setupHelpers(ctx) {
5268
- const code = generateHelpers(ctx);
2491
+ const code = generateHelpers();
5269
2492
  return {
5270
2493
  id: "helpers",
5271
2494
  files: [{
@@ -5304,21 +2527,8 @@ function setupDesignTokens(ctx) {
5304
2527
  ]
5305
2528
  };
5306
2529
  }
5307
- function setupJsxTypes(ctx) {
5308
- if (!ctx.jsx.framework) return;
5309
- const jsx = generateJsxTypes(ctx);
5310
- if (!jsx) return;
5311
- return {
5312
- id: "types-jsx",
5313
- dir: ctx.paths.types,
5314
- files: [{
5315
- file: ctx.file.extDts("jsx"),
5316
- code: jsx.jsxType
5317
- }]
5318
- };
5319
- }
5320
2530
  function setupEntryTypes(ctx) {
5321
- const entry = generateTypesEntry(ctx, Boolean(ctx.jsx.framework));
2531
+ const entry = generateTypesEntry(ctx);
5322
2532
  return {
5323
2533
  id: "types-entry",
5324
2534
  dir: ctx.paths.types,
@@ -5404,29 +2614,29 @@ function setupGeneratedSystemTypes(ctx) {
5404
2614
  };
5405
2615
  }
5406
2616
  function setupCss(ctx) {
5407
- const code = ctx.isTemplateLiteralSyntax ? generateStringLiteralCssFn(ctx) : generateCssFn(ctx);
5408
- const conditions = ctx.isTemplateLiteralSyntax ? generateStringLiteralConditions(ctx) : generateConditions(ctx);
2617
+ const code = generateCssFn(ctx);
2618
+ const conditions = generateConditions(ctx);
2619
+ const files = [
2620
+ {
2621
+ file: ctx.file.ext("conditions"),
2622
+ code: conditions.js
2623
+ },
2624
+ {
2625
+ file: ctx.file.ext("css"),
2626
+ code: code.js
2627
+ },
2628
+ {
2629
+ file: ctx.file.extDts("css"),
2630
+ code: code.dts
2631
+ }
2632
+ ];
5409
2633
  return {
5410
2634
  id: "css-fn",
5411
2635
  dir: ctx.paths.css,
5412
- files: [
5413
- {
5414
- file: ctx.file.ext("conditions"),
5415
- code: conditions.js
5416
- },
5417
- {
5418
- file: ctx.file.ext("css"),
5419
- code: code.js
5420
- },
5421
- {
5422
- file: ctx.file.extDts("css"),
5423
- code: code.dts
5424
- }
5425
- ]
2636
+ files
5426
2637
  };
5427
2638
  }
5428
2639
  function setupCva(ctx) {
5429
- if (ctx.isTemplateLiteralSyntax) return;
5430
2640
  const code = generateCvaFn(ctx);
5431
2641
  return {
5432
2642
  id: "cva",
@@ -5441,7 +2651,6 @@ function setupCva(ctx) {
5441
2651
  };
5442
2652
  }
5443
2653
  function setupSva(ctx) {
5444
- if (ctx.isTemplateLiteralSyntax) return;
5445
2654
  const code = generateSvaFn(ctx);
5446
2655
  return {
5447
2656
  id: "sva",
@@ -5456,7 +2665,7 @@ function setupSva(ctx) {
5456
2665
  };
5457
2666
  }
5458
2667
  function setupCx(ctx) {
5459
- const code = generateCx(ctx);
2668
+ const code = generateCx();
5460
2669
  return {
5461
2670
  id: "cx",
5462
2671
  dir: ctx.paths.css,
@@ -5521,7 +2730,6 @@ function setupRecipes(ctx, filters) {
5521
2730
  };
5522
2731
  }
5523
2732
  function setupPatternsIndex(ctx) {
5524
- if (ctx.isTemplateLiteralSyntax) return;
5525
2733
  const fileNames = ctx.patterns.details.map((pattern) => pattern.dashName);
5526
2734
  const index = {
5527
2735
  js: outdent.default.string(fileNames.map((file) => ctx.file.exportStar(`./${file}`)).join("\n")),
@@ -5540,7 +2748,6 @@ function setupPatternsIndex(ctx) {
5540
2748
  };
5541
2749
  }
5542
2750
  function setupPatterns(ctx, filters) {
5543
- if (ctx.isTemplateLiteralSyntax) return;
5544
2751
  const files = generatePattern(ctx, filters);
5545
2752
  if (!files) return;
5546
2753
  return {
@@ -5555,127 +2762,19 @@ function setupPatterns(ctx, filters) {
5555
2762
  }])
5556
2763
  };
5557
2764
  }
5558
- function setupJsxIsValidProp(ctx) {
5559
- if (!ctx.jsx.framework || ctx.isTemplateLiteralSyntax) return;
5560
- const isValidProp = generateIsValidProp(ctx);
5561
- return {
5562
- id: "jsx-is-valid-prop",
5563
- dir: ctx.paths.jsx,
5564
- files: [{
5565
- file: ctx.file.ext("is-valid-prop"),
5566
- code: isValidProp?.js
5567
- }, {
5568
- file: ctx.file.extDts("is-valid-prop"),
5569
- code: isValidProp?.dts
5570
- }]
5571
- };
5572
- }
5573
- function setupJsxFactory(ctx) {
5574
- if (!ctx.jsx.framework) return;
5575
- const types = generateJsxTypes(ctx);
5576
- if (!types) return;
5577
- const factory = generateJsxFactory(ctx);
5578
- if (!factory) return;
5579
- return {
5580
- id: "jsx-factory",
5581
- dir: ctx.paths.jsx,
5582
- files: [{
5583
- file: ctx.file.ext("factory"),
5584
- code: factory?.js
5585
- }, {
5586
- file: ctx.file.extDts("factory"),
5587
- code: types.jsxFactory
5588
- }]
5589
- };
5590
- }
5591
- function setupJsxHelpers(ctx) {
5592
- if (!ctx.jsx.framework) return;
5593
- const helpers = generatedJsxHelpers(ctx);
5594
- return {
5595
- id: "jsx-helpers",
5596
- dir: ctx.paths.jsx,
5597
- files: [{
5598
- file: ctx.file.ext("factory-helper"),
5599
- code: helpers.js
5600
- }]
5601
- };
5602
- }
5603
- function setupJsxPatterns(ctx, filters) {
5604
- if (!ctx.jsx.framework || ctx.isTemplateLiteralSyntax) return;
5605
- const patterns = generateJsxPatterns(ctx, filters);
5606
- if (!patterns) return;
5607
- return {
5608
- id: "jsx-patterns",
5609
- dir: ctx.paths.jsx,
5610
- files: [...patterns.flatMap((file) => [{
5611
- file: ctx.file.ext(file.name),
5612
- code: file.js
5613
- }, {
5614
- file: ctx.file.extDts(file.name),
5615
- code: file.dts
5616
- }])]
5617
- };
5618
- }
5619
- function setupJsxCreateStyleContext(ctx) {
5620
- if (!ctx.jsx.framework || ctx.isTemplateLiteralSyntax) return;
5621
- const createStyleContext = generateJsxCreateStyleContext(ctx);
5622
- if (!createStyleContext) return;
5623
- return {
5624
- id: "jsx-create-style-context",
5625
- dir: ctx.paths.jsx,
5626
- files: [{
5627
- file: ctx.file.ext("create-style-context"),
5628
- code: createStyleContext.js
5629
- }, {
5630
- file: ctx.file.extDts("create-style-context"),
5631
- code: createStyleContext.dts
5632
- }]
5633
- };
5634
- }
5635
- function setupJsxPatternsIndex(ctx) {
5636
- if (!ctx.jsx.framework) return;
5637
- const isStyleProp = !ctx.isTemplateLiteralSyntax;
5638
- const patternNames = ctx.patterns.details.map((pattern) => pattern.dashName);
5639
- const index = {
5640
- js: outdent.default`
5641
- ${ctx.file.exportStar("./factory")}
5642
- ${isStyleProp ? ctx.file.exportStar("./is-valid-prop") : ""}
5643
- ${isStyleProp && !["qwik", "svelte"].includes(ctx.jsx.framework) ? ctx.file.exportStar("./create-style-context") : ""}
5644
- ${isStyleProp ? outdent.default.string(patternNames.map((file) => ctx.file.exportStar(`./${file}`)).join("\n")) : ""}
5645
- `,
5646
- dts: outdent.default`
5647
- ${ctx.file.exportTypeStar("./factory")}
5648
- ${isStyleProp ? ctx.file.exportTypeStar("./is-valid-prop") : ""}
5649
- ${isStyleProp ? ctx.file.exportTypeStar("./create-style-context") : ""}
5650
- ${isStyleProp ? outdent.default.string(patternNames.map((file) => ctx.file.exportTypeStar(`./${file}`)).join("\n")) : ""}
5651
- ${ctx.file.exportType([ctx.jsx.typeName, ctx.jsx.componentName].join(", "), "../types/jsx")}
5652
- `
5653
- };
5654
- return {
5655
- id: "jsx-patterns-index",
5656
- dir: ctx.paths.jsx,
5657
- files: [{
5658
- file: ctx.file.ext("index"),
5659
- code: index.js
5660
- }, {
5661
- file: ctx.file.extDts("index"),
5662
- code: index.dts
5663
- }]
5664
- };
5665
- }
5666
2765
  function setupCssIndex(ctx) {
5667
2766
  const index = {
5668
2767
  js: outdent.default`
5669
2768
  ${ctx.file.exportStar("./css")}
5670
2769
  ${ctx.file.exportStar("./cx")}
5671
- ${ctx.isTemplateLiteralSyntax ? "" : ctx.file.exportStar("./cva")}
5672
- ${ctx.isTemplateLiteralSyntax ? "" : ctx.file.exportStar("./sva")}
2770
+ ${ctx.file.exportStar("./cva")}
2771
+ ${ctx.file.exportStar("./sva")}
5673
2772
  `,
5674
2773
  dts: outdent.default`
5675
2774
  ${ctx.file.exportTypeStar("./css")}
5676
2775
  ${ctx.file.exportTypeStar("./cx")}
5677
- ${ctx.isTemplateLiteralSyntax ? "" : ctx.file.exportTypeStar("./cva")}
5678
- ${ctx.isTemplateLiteralSyntax ? "" : ctx.file.exportTypeStar("./sva")}
2776
+ ${ctx.file.exportTypeStar("./cva")}
2777
+ ${ctx.file.exportTypeStar("./sva")}
5679
2778
  `
5680
2779
  };
5681
2780
  return {
@@ -5726,7 +2825,7 @@ const filterArtifactsFiles = (artifacts, filters) => {
5726
2825
  if (affected.recipes && !item.file.includes("index") && artifact?.dir?.includes("recipes")) {
5727
2826
  if (!affected.recipes.some((recipe) => item.file.includes(recipe))) return;
5728
2827
  }
5729
- if (affected.patterns && !item.file.includes("index") && (artifact?.dir?.includes("patterns") || artifact?.dir?.includes("jsx"))) {
2828
+ if (affected.patterns && !item.file.includes("index") && artifact?.dir?.includes("patterns")) {
5730
2829
  if (!affected.patterns.some((pattern) => item.file.includes(pattern))) return;
5731
2830
  }
5732
2831
  return true;
@@ -5741,7 +2840,6 @@ const entries = [
5741
2840
  ["package.json", setupPackageJson],
5742
2841
  ["helpers", setupHelpers],
5743
2842
  ["design-tokens", setupDesignTokens],
5744
- ["types-jsx", setupJsxTypes],
5745
2843
  ["types-entry", setupEntryTypes],
5746
2844
  ["types-styles", setupStyleTypes],
5747
2845
  ["types-conditions", setupConditionsTypes],
@@ -5756,12 +2854,6 @@ const entries = [
5756
2854
  ["recipes", setupRecipes],
5757
2855
  ["patterns-index", setupPatternsIndex],
5758
2856
  ["patterns", setupPatterns],
5759
- ["jsx-is-valid-prop", setupJsxIsValidProp],
5760
- ["jsx-factory", setupJsxFactory],
5761
- ["jsx-helpers", setupJsxHelpers],
5762
- ["jsx-patterns", setupJsxPatterns],
5763
- ["jsx-create-style-context", setupJsxCreateStyleContext],
5764
- ["jsx-patterns-index", setupJsxPatternsIndex],
5765
2857
  ["css-index", setupCssIndex],
5766
2858
  ["themes", setupThemes]
5767
2859
  ];
@@ -5811,6 +2903,61 @@ const generateGlobalCss = (ctx, sheet) => {
5811
2903
  sheet.processGlobalCss(globalCss);
5812
2904
  };
5813
2905
  //#endregion
2906
+ //#region src/artifacts/js/group-registry.ts
2907
+ /**
2908
+ * The grouped class names an encoder has accumulated.
2909
+ *
2910
+ * Derived through `groupClassName`, the same function the browser runtime calls — a
2911
+ * registry built any other way would be a third spelling of a name that already has two.
2912
+ * Unescaped, unlike `StyleDecoder`'s class names: this is compared against what `css()`
2913
+ * returns into a `class` attribute, not against a selector.
2914
+ *
2915
+ * Reads from the encoder rather than the decoder so it is available as soon as extraction
2916
+ * is, and so `codegen` can emit whatever is already known instead of blanking the file.
2917
+ */
2918
+ function collectGroupClassNames(ctx) {
2919
+ const names = [];
2920
+ ctx.encoder.grouped.forEach((_hashes, groupId) => {
2921
+ names.push((0, _bamboocss_shared.groupClassName)(groupId, ctx.utility.toHash, ctx.utility.formatClassName));
2922
+ });
2923
+ return names.sort();
2924
+ }
2925
+ /**
2926
+ * The grouped classes the build emitted a rule for.
2927
+ *
2928
+ * Under `cssMode: 'grouped'` a class names a whole `css()` call, so the build has to have
2929
+ * seen that exact call to emit its rule. This is how the runtime tells the difference: a
2930
+ * class in here has CSS behind it, and one that is not falls back to naming its
2931
+ * declarations atomically as well.
2932
+ *
2933
+ * Written by two passes. `codegen` emits whatever the encoder already holds — usually
2934
+ * nothing, since it runs on config change before anything is extracted, but not blank when
2935
+ * it runs after a build. The CSS build then rewrites it with the set it emitted.
2936
+ *
2937
+ * An empty or stale registry is safe by construction: the runtime *adds* to the group class
2938
+ * rather than replacing it, so the worst a miss can do is name a class that matches nothing.
2939
+ */
2940
+ function generateGroupRegistry(ctx, classNames) {
2941
+ const names = classNames ?? collectGroupClassNames(ctx);
2942
+ return {
2943
+ js: outdent.outdent`
2944
+ // Generated by bamboo. Rewritten on every CSS build — do not edit.
2945
+ const packed = ${JSON.stringify(names.slice().sort().join(","))}
2946
+
2947
+ export const groups = /* @__PURE__ */ new Set(packed ? packed.split(',') : [])
2948
+ `,
2949
+ dts: outdent.outdent`
2950
+ /**
2951
+ * The grouped classes this build emitted a rule for. Internal — the generated \`css\`
2952
+ * consults it to decide whether a grouped class has CSS behind it.
2953
+ */
2954
+ export declare const groups: Set<string>;
2955
+ `
2956
+ };
2957
+ }
2958
+ /** Where the registry lives, so the writer and the importer cannot disagree about it. */
2959
+ const GROUP_REGISTRY_FILE = "groups";
2960
+ //#endregion
5814
2961
  //#region src/artifacts/css/keyframe-css.ts
5815
2962
  function generateKeyframeCss(ctx, sheet) {
5816
2963
  const { keyframes = {} } = ctx.config.theme ?? {};
@@ -5975,7 +3122,7 @@ const generateStaticCss = (ctx, sheet) => {
5975
3122
  //#endregion
5976
3123
  //#region src/spec/animation-styles.ts
5977
3124
  const generateAnimationStylesSpec = (ctx) => {
5978
- return generateCompositionStyleSpec("animation-styles", ctx.config.theme, ctx.config.jsxStyleProps);
3125
+ return generateCompositionStyleSpec("animation-styles", ctx.config.theme);
5979
3126
  };
5980
3127
  //#endregion
5981
3128
  //#region src/spec/color-palette.ts
@@ -6000,16 +3147,12 @@ const getColorPaletteExampleValues = (ctx, paletteValues) => {
6000
3147
  };
6001
3148
  const generateColorPaletteSpec = (ctx) => {
6002
3149
  if ((ctx.config.theme?.colorPalette)?.enabled === false) return null;
6003
- const jsxStyleProps = ctx.config.jsxStyleProps;
6004
3150
  const values = Array.from(ctx.tokens.view.colorPalettes.keys()).sort();
6005
3151
  if (!values.length) return null;
6006
3152
  const { examplePalette, bgToken, colorToken } = getColorPaletteExampleValues(ctx, values);
6007
3153
  const functionExamples = [];
6008
- const jsxExamples = [];
6009
3154
  const basicProps = { colorPalette: examplePalette };
6010
3155
  functionExamples.push(`css({ ${formatProps(basicProps)} })`);
6011
- const basicJsx = generateJsxExample(basicProps, jsxStyleProps);
6012
- if (basicJsx) jsxExamples.push(basicJsx);
6013
3156
  if (bgToken || colorToken) {
6014
3157
  const extendedProps = {
6015
3158
  colorPalette: examplePalette,
@@ -6017,25 +3160,17 @@ const generateColorPaletteSpec = (ctx) => {
6017
3160
  color: colorToken
6018
3161
  };
6019
3162
  functionExamples.push(`css({ ${formatProps(extendedProps)} })`);
6020
- const extendedJsx = generateJsxExample(extendedProps, jsxStyleProps);
6021
- if (extendedJsx) jsxExamples.push(extendedJsx);
6022
3163
  }
6023
3164
  return {
6024
3165
  type: "color-palette",
6025
3166
  data: {
6026
3167
  values,
6027
- functionExamples,
6028
- jsxExamples
3168
+ functionExamples
6029
3169
  }
6030
3170
  };
6031
3171
  };
6032
3172
  //#endregion
6033
3173
  //#region src/spec/conditions.ts
6034
- const generateConditionJsxExamples = (conditionName, jsxStyleProps = "all") => {
6035
- if (jsxStyleProps === "all") return [`<Box margin={{ base: '2', ${conditionName}: '4' }} />`, `<Box margin="2" ${conditionName}={{ margin: '4' }} />`];
6036
- if (jsxStyleProps === "minimal") return [`<Box css={{ margin: { base: '2', ${conditionName}: '4' } }} />`, `<Box css={{ margin: '2', ${conditionName}: { margin: '4' } }} />`];
6037
- return [];
6038
- };
6039
3174
  /**
6040
3175
  * Walk an object condition collecting every path that ends in `@slot`.
6041
3176
  * Each path is joined with spaces; multiple paths are joined with `; ` so the
@@ -6051,7 +3186,6 @@ const formatObjectCondition = (raw) => {
6051
3186
  return blocks.join("; ");
6052
3187
  };
6053
3188
  const generateConditionsSpec = (ctx) => {
6054
- const jsxStyleProps = ctx.config.jsxStyleProps;
6055
3189
  const breakpointKeys = new Set(Object.keys(ctx.conditions.breakpoints.conditions));
6056
3190
  return {
6057
3191
  type: "conditions",
@@ -6062,37 +3196,26 @@ const generateConditionsSpec = (ctx) => {
6062
3196
  return {
6063
3197
  name: conditionName,
6064
3198
  value: value ?? "",
6065
- functionExamples: [`css({ margin: { base: '2', ${conditionName}: '4' } })`, `css({ margin: '2', ${conditionName}: { margin: '4' } })`],
6066
- jsxExamples: generateConditionJsxExamples(conditionName, jsxStyleProps)
3199
+ functionExamples: [`css({ margin: { base: '2', ${conditionName}: '4' } })`, `css({ margin: '2', ${conditionName}: { margin: '4' } })`]
6067
3200
  };
6068
3201
  })
6069
3202
  };
6070
3203
  };
6071
3204
  //#endregion
6072
3205
  //#region src/spec/keyframes.ts
6073
- const generateKeyframeJsxExamples = (name, jsxStyleProps = "all") => {
6074
- const jsxExamples = [];
6075
- const example1 = generateJsxExample({ animationName: name }, jsxStyleProps);
6076
- if (example1) jsxExamples.push(example1);
6077
- const example2 = generateJsxExample({ animation: `${name} 1s ease-in-out infinite` }, jsxStyleProps);
6078
- if (example2) jsxExamples.push(example2);
6079
- return jsxExamples;
6080
- };
6081
3206
  const generateKeyframesSpec = (ctx) => {
6082
- const jsxStyleProps = ctx.config.jsxStyleProps;
6083
3207
  return {
6084
3208
  type: "keyframes",
6085
3209
  data: Object.keys(ctx.config.theme?.keyframes ?? {}).map((name) => ({
6086
3210
  name,
6087
- functionExamples: [`css({ animationName: '${name}' })`, `css({ animation: '${name} 1s ease-in-out infinite' })`],
6088
- jsxExamples: generateKeyframeJsxExamples(name, jsxStyleProps)
3211
+ functionExamples: [`css({ animationName: '${name}' })`, `css({ animation: '${name} 1s ease-in-out infinite' })`]
6089
3212
  }))
6090
3213
  };
6091
3214
  };
6092
3215
  //#endregion
6093
3216
  //#region src/spec/layer-styles.ts
6094
3217
  const generateLayerStylesSpec = (ctx) => {
6095
- return generateCompositionStyleSpec("layer-styles", ctx.config.theme, ctx.config.jsxStyleProps);
3218
+ return generateCompositionStyleSpec("layer-styles", ctx.config.theme);
6096
3219
  };
6097
3220
  //#endregion
6098
3221
  //#region src/spec/patterns.ts
@@ -6104,22 +3227,16 @@ const getExampleValue = (prop) => {
6104
3227
  return "<value>";
6105
3228
  };
6106
3229
  const generatePatternsSpec = (ctx) => {
6107
- const jsxStyleProps = ctx.config.jsxStyleProps;
6108
3230
  return {
6109
3231
  type: "patterns",
6110
3232
  data: ctx.patterns.details.map((node) => {
6111
3233
  const patternName = node.baseName;
6112
- const jsxName = node.jsxName;
6113
3234
  const properties = Object.entries(node.config.properties ?? {});
6114
3235
  const functionExamples = [];
6115
- const jsxExamples = [];
6116
- if (properties.length === 0) {
6117
- functionExamples.push(`${patternName}()`);
6118
- if (jsxStyleProps !== "none") jsxExamples.push(`<${jsxName} />`);
6119
- } else properties.forEach(([propName, prop]) => {
3236
+ if (properties.length === 0) functionExamples.push(`${patternName}()`);
3237
+ else properties.forEach(([propName, prop]) => {
6120
3238
  const exampleValue = getExampleValue(prop);
6121
3239
  functionExamples.push(`${patternName}({ ${propName}: ${exampleValue} })`);
6122
- if (jsxStyleProps !== "none") jsxExamples.push(`<${jsxName} ${propName}={${exampleValue}} />`);
6123
3240
  });
6124
3241
  const defaultValues = typeof node.config.defaultValues === "object" ? node.config.defaultValues : {};
6125
3242
  return {
@@ -6131,9 +3248,7 @@ const generatePatternsSpec = (ctx) => {
6131
3248
  description: prop.description,
6132
3249
  defaultValue: defaultValues[name]
6133
3250
  })),
6134
- jsx: jsxName,
6135
- functionExamples,
6136
- jsxExamples
3251
+ functionExamples
6137
3252
  };
6138
3253
  })
6139
3254
  };
@@ -6155,28 +3270,17 @@ const generateRecipesSpec = (ctx) => {
6155
3270
  type: "recipes",
6156
3271
  data: ctx.recipes.details.map((node) => {
6157
3272
  const recipeName = node.baseName;
6158
- const jsxName = node.jsxName;
6159
3273
  const variantKeys = Object.keys(node.variantKeyMap);
6160
3274
  const functionExamples = [];
6161
- const jsxExamples = [];
6162
- if (variantKeys.length === 0) {
6163
- functionExamples.push(`${recipeName}()`);
6164
- jsxExamples.push(`<${jsxName} />`);
6165
- } else {
3275
+ if (variantKeys.length === 0) functionExamples.push(`${recipeName}()`);
3276
+ else {
6166
3277
  variantKeys.forEach((variantKey) => {
6167
3278
  const firstValue = getFirstVariantValue(node.variantKeyMap, variantKey);
6168
- if (firstValue) {
6169
- functionExamples.push(`${recipeName}({ ${variantKey}: ${formatFunctionValue(firstValue)} })`);
6170
- jsxExamples.push(`<${jsxName} ${variantKey}=${formatJsxValue(firstValue)} />`);
6171
- }
3279
+ if (firstValue) functionExamples.push(`${recipeName}({ ${variantKey}: ${formatFunctionValue(firstValue)} })`);
6172
3280
  });
6173
3281
  if (variantKeys.length > 1) {
6174
3282
  const props = buildVariantProps(variantKeys, node.variantKeyMap, buildFunctionProps, ", ");
6175
- const jsxProps = buildVariantProps(variantKeys, node.variantKeyMap, buildJsxProps, " ");
6176
- if (props && jsxProps) {
6177
- functionExamples.push(`${recipeName}({ ${props} })`);
6178
- jsxExamples.push(`<${jsxName} ${jsxProps} />`);
6179
- }
3283
+ if (props) functionExamples.push(`${recipeName}({ ${props} })`);
6180
3284
  }
6181
3285
  }
6182
3286
  return {
@@ -6184,8 +3288,7 @@ const generateRecipesSpec = (ctx) => {
6184
3288
  description: node.config.description,
6185
3289
  variants: node.variantKeyMap,
6186
3290
  defaultVariants: node.config.defaultVariants ?? {},
6187
- functionExamples,
6188
- jsxExamples
3291
+ functionExamples
6189
3292
  };
6190
3293
  })
6191
3294
  };
@@ -6193,7 +3296,7 @@ const generateRecipesSpec = (ctx) => {
6193
3296
  //#endregion
6194
3297
  //#region src/spec/text-styles.ts
6195
3298
  const generateTextStylesSpec = (ctx) => {
6196
- return generateCompositionStyleSpec("text-styles", ctx.config.theme, ctx.config.jsxStyleProps);
3299
+ return generateCompositionStyleSpec("text-styles", ctx.config.theme);
6197
3300
  };
6198
3301
  //#endregion
6199
3302
  //#region src/spec/token-examples.ts
@@ -6222,26 +3325,21 @@ const CATEGORY_PROPERTY_MAP = {
6222
3325
  const getCategoryProperty = (category) => {
6223
3326
  return category ? CATEGORY_PROPERTY_MAP[category] ?? "color" : "color";
6224
3327
  };
6225
- const generateTokenExamples = (token, jsxStyleProps = "all") => {
3328
+ const generateTokenExamples = (token) => {
6226
3329
  const prop = getCategoryProperty(token.extensions?.category);
6227
3330
  const tokenName = token.extensions.prop;
6228
3331
  const fullTokenName = token.name;
6229
3332
  const functionExamples = [`css({ ${prop}: '${tokenName}' })`];
6230
3333
  const tokenFunctionExamples = [`token('${fullTokenName}')`];
6231
- const jsxExamples = [];
6232
- const jsxExample = generateJsxExample({ [prop]: tokenName }, jsxStyleProps);
6233
- if (jsxExample) jsxExamples.push(jsxExample);
6234
3334
  if (token.extensions.varRef) tokenFunctionExamples.push(`token.var('${fullTokenName}')`);
6235
3335
  return {
6236
3336
  functionExamples,
6237
- tokenFunctionExamples,
6238
- jsxExamples
3337
+ tokenFunctionExamples
6239
3338
  };
6240
3339
  };
6241
3340
  //#endregion
6242
3341
  //#region src/spec/themes.ts
6243
3342
  const generateThemeTokenGroups = (ctx, themeName, filterFn) => {
6244
- const jsxStyleProps = ctx.config.jsxStyleProps;
6245
3343
  const condName = "_theme" + (0, _bamboocss_shared.capitalize)(themeName);
6246
3344
  const themeTokens = ctx.tokens.allTokens.filter((token) => token.extensions.isVirtual && token.extensions.theme === themeName && filterFn(token));
6247
3345
  const byCategory = /* @__PURE__ */ new Map();
@@ -6254,7 +3352,7 @@ const generateThemeTokenGroups = (ctx, themeName, filterFn) => {
6254
3352
  return Array.from(byCategory.entries()).map(([category, typeTokens]) => {
6255
3353
  if (!typeTokens.length) return null;
6256
3354
  const firstToken = typeTokens[0];
6257
- const { functionExamples, tokenFunctionExamples, jsxExamples } = generateTokenExamples(firstToken, jsxStyleProps);
3355
+ const { functionExamples, tokenFunctionExamples } = generateTokenExamples(firstToken);
6258
3356
  return {
6259
3357
  type: category,
6260
3358
  values: typeTokens.map((token) => {
@@ -6274,8 +3372,7 @@ const generateThemeTokenGroups = (ctx, themeName, filterFn) => {
6274
3372
  };
6275
3373
  }),
6276
3374
  tokenFunctionExamples,
6277
- functionExamples,
6278
- jsxExamples
3375
+ functionExamples
6279
3376
  };
6280
3377
  }).filter(Boolean);
6281
3378
  };
@@ -6296,14 +3393,13 @@ const generateThemesSpec = (ctx) => {
6296
3393
  //#endregion
6297
3394
  //#region src/spec/tokens.ts
6298
3395
  const generateTokensSpec = (ctx) => {
6299
- const jsxStyleProps = ctx.config.jsxStyleProps;
6300
3396
  return {
6301
3397
  type: "tokens",
6302
3398
  data: Array.from(ctx.tokens.view.categoryMap.entries()).map(([category, tokenMap]) => {
6303
3399
  const typeTokens = Array.from(tokenMap.values()).filter((token) => !token.extensions.isSemantic && !token.extensions.isVirtual && !token.extensions.conditions && !token.extensions.isNegative);
6304
3400
  if (!typeTokens.length) return null;
6305
3401
  const firstToken = typeTokens[0];
6306
- const { functionExamples, tokenFunctionExamples, jsxExamples } = generateTokenExamples(firstToken, jsxStyleProps);
3402
+ const { functionExamples, tokenFunctionExamples } = generateTokenExamples(firstToken);
6307
3403
  return {
6308
3404
  type: category,
6309
3405
  values: typeTokens.map((token) => ({
@@ -6314,21 +3410,19 @@ const generateTokensSpec = (ctx) => {
6314
3410
  cssVar: token.extensions.varRef
6315
3411
  })),
6316
3412
  tokenFunctionExamples,
6317
- functionExamples,
6318
- jsxExamples
3413
+ functionExamples
6319
3414
  };
6320
3415
  }).filter(Boolean)
6321
3416
  };
6322
3417
  };
6323
3418
  const generateSemanticTokensSpec = (ctx) => {
6324
- const jsxStyleProps = ctx.config.jsxStyleProps;
6325
3419
  return {
6326
3420
  type: "semantic-tokens",
6327
3421
  data: Array.from(ctx.tokens.view.categoryMap.entries()).map(([category, tokenMap]) => {
6328
3422
  const typeTokens = Array.from(tokenMap.values()).filter((token) => (token.extensions.isSemantic || token.extensions.conditions) && !token.extensions.isVirtual);
6329
3423
  if (!typeTokens.length) return null;
6330
3424
  const firstToken = typeTokens[0];
6331
- const { functionExamples, tokenFunctionExamples, jsxExamples } = generateTokenExamples(firstToken, jsxStyleProps);
3425
+ const { functionExamples, tokenFunctionExamples } = generateTokenExamples(firstToken);
6332
3426
  return {
6333
3427
  type: category,
6334
3428
  values: typeTokens.map((token) => {
@@ -6348,8 +3442,7 @@ const generateSemanticTokensSpec = (ctx) => {
6348
3442
  };
6349
3443
  }),
6350
3444
  tokenFunctionExamples,
6351
- functionExamples,
6352
- jsxExamples
3445
+ functionExamples
6353
3446
  };
6354
3447
  }).filter(Boolean)
6355
3448
  };
@@ -6515,6 +3608,20 @@ var Generator = class extends _bamboocss_core.Context {
6515
3608
  getParserCss = (decoder) => {
6516
3609
  return generateParserCss(this, decoder);
6517
3610
  };
3611
+ /**
3612
+ * The grouped class names this build emitted a rule for.
3613
+ *
3614
+ * Derived from the encoder rather than the decoder, so it is available as soon as
3615
+ * extraction finishes and before a stylesheet exists. Both sides go through
3616
+ * `groupClassName`, which is the same function the browser runtime calls — a registry
3617
+ * built any other way would be a third spelling of a name that already has two.
3618
+ *
3619
+ * Unescaped, unlike `StyleDecoder`'s class names: this is compared against what `css()`
3620
+ * returns into a `class` attribute, not against a selector. A grouped class is an opaque
3621
+ * hash, so the two only differ in principle, but the principle is the one that matters
3622
+ * here — the registry is only useful if it holds exactly what the runtime will ask about.
3623
+ */
3624
+ getGroupRegistry = () => collectGroupClassNames(this);
6518
3625
  getCss = (stylesheet) => {
6519
3626
  let css = (stylesheet ?? this.createSheet()).toCss({ minify: this.config.minify });
6520
3627
  if (this.hooks["cssgen:done"]) css = this.hooks["cssgen:done"]({
@@ -6658,5 +3765,7 @@ var Generator = class extends _bamboocss_core.Context {
6658
3765
  };
6659
3766
  };
6660
3767
  //#endregion
3768
+ exports.GROUP_REGISTRY_FILE = GROUP_REGISTRY_FILE;
6661
3769
  exports.Generator = Generator;
3770
+ exports.generateGroupRegistry = generateGroupRegistry;
6662
3771
  exports.getThemeCss = getThemeCss;