praxis-kit 2.0.2 → 3.0.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.
@@ -332,11 +332,13 @@ function processVariableStatement(node, calleeNames, out) {
332
332
  }
333
333
  }
334
334
  if (rules.length === 0 && !hasAriaRules && !defaultTag) continue;
335
- const totalMin = rules.reduce((s, r) => s + cardinalityMin(r.cardinality), 0);
336
- const totalMax = rules.reduce(
337
- (s, r) => s === Infinity ? Infinity : s + cardinalityMax(r.cardinality),
338
- 0
339
- );
335
+ let totalMin = 0;
336
+ let totalMax = 0;
337
+ for (const rule of rules) {
338
+ totalMin += cardinalityMin(rule.cardinality);
339
+ const max = cardinalityMax(rule.cardinality);
340
+ totalMax = totalMax === Infinity || max === Infinity ? Infinity : totalMax + max;
341
+ }
340
342
  const componentName = ts3.isIdentifier(decl.name) ? decl.name.text : void 0;
341
343
  if (!componentName) continue;
342
344
  out.push({
@@ -367,7 +369,13 @@ function collectFileDeclarations(source, calleeNames) {
367
369
  if (!ts3.isStringLiteral(spec)) return;
368
370
  const namedBindings = node.importClause?.namedBindings;
369
371
  if (!namedBindings || !ts3.isNamedImports(namedBindings)) return;
370
- for (const el of namedBindings.elements) importSpecifiers.set(el.name.text, spec.text);
372
+ const specifier = spec.text;
373
+ for (const el of namedBindings.elements) {
374
+ if (el.isTypeOnly) continue;
375
+ const localName = el.name.text;
376
+ const importedName = el.propertyName?.text ?? localName;
377
+ importSpecifiers.set(localName, { importedName, specifier });
378
+ }
371
379
  }
372
380
  });
373
381
  return { constraints, importSpecifiers };
@@ -512,23 +520,24 @@ function analyzeJsxSites(source, constraints, severity) {
512
520
  const opening = node.openingElement;
513
521
  tagName = ts5.isIdentifier(opening.tagName) ? opening.tagName.text : void 0;
514
522
  attributes = opening.attributes;
515
- count = countStaticChildren(node);
523
+ count = countJsxChildren(node.children);
516
524
  } else if (ts5.isJsxSelfClosingElement(node)) {
517
525
  tagName = ts5.isIdentifier(node.tagName) ? node.tagName.text : void 0;
518
526
  attributes = node.attributes;
519
- count = 0;
527
+ count = ZERO;
520
528
  }
521
529
  if (!tagName) return;
522
530
  let pos;
523
531
  const getPos = () => pos ??= source.getLineAndCharacterOfPosition(node.getStart(source));
524
532
  if (count !== void 0) {
525
533
  const c = byName.get(tagName);
526
- if (c && (count < c.totalMin || count > c.totalMax)) {
534
+ if (c && (count.max < c.totalMin || count.min > c.totalMax)) {
527
535
  const { line, character } = getPos();
528
536
  const { totalMin, totalMax, name } = c;
529
537
  const rangeText = totalMax === Infinity ? `at least ${totalMin}` : totalMin === totalMax ? `exactly ${totalMin}` : `${totalMin}\u2013${totalMax}`;
538
+ const receivedText = count.min === count.max ? `${count.min}` : `${count.min}\u2013${count.max}`;
530
539
  diagnostics.push({
531
- message: `<${name}> expects ${rangeText} ${totalMax === 1 && totalMin === 1 ? "child" : "children"} but received ${count}.`,
540
+ message: `<${name}> expects ${rangeText} ${totalMax === 1 && totalMin === 1 ? "child" : "children"} but received ${receivedText}.`,
532
541
  line: line + 1,
533
542
  col: character + 1,
534
543
  severity
@@ -567,17 +576,71 @@ function analyzeJsxSites(source, constraints, severity) {
567
576
  });
568
577
  return { diagnostics, usages };
569
578
  }
570
- function countStaticChildren(node) {
571
- let count = 0;
572
- for (const child of node.children) {
573
- if (ts5.isJsxExpression(child)) return void 0;
574
- if (ts5.isJsxText(child)) {
575
- if (child.text.trim().length > 0) count++;
579
+ var ZERO = { min: 0, max: 0 };
580
+ var ONE = { min: 1, max: 1 };
581
+ function countExpression(node) {
582
+ if (node.kind === ts5.SyntaxKind.NullKeyword) return ZERO;
583
+ if (node.kind === ts5.SyntaxKind.FalseKeyword) return ZERO;
584
+ if (ts5.isIdentifier(node) && node.text === "undefined") return ZERO;
585
+ if (ts5.isParenthesizedExpression(node)) return countExpression(node.expression);
586
+ if (ts5.isJsxElement(node) || ts5.isJsxSelfClosingElement(node)) return ONE;
587
+ if (ts5.isJsxFragment(node)) return countJsxChildren(node.children);
588
+ if (ts5.isArrayLiteralExpression(node)) {
589
+ let min = 0;
590
+ let max = 0;
591
+ for (const el of node.elements) {
592
+ if (ts5.isSpreadElement(el)) return void 0;
593
+ const c = countExpression(el);
594
+ if (!c) return void 0;
595
+ min += c.min;
596
+ max += c.max;
597
+ }
598
+ return { min, max };
599
+ }
600
+ if (ts5.isBinaryExpression(node)) {
601
+ const op = node.operatorToken.kind;
602
+ if (op === ts5.SyntaxKind.AmpersandAmpersandToken) {
603
+ const right = countExpression(node.right);
604
+ if (!right) return void 0;
605
+ return { min: 0, max: right.max };
606
+ }
607
+ if (op === ts5.SyntaxKind.BarBarToken || op === ts5.SyntaxKind.QuestionQuestionToken) {
608
+ const left = countExpression(node.left);
609
+ const right = countExpression(node.right);
610
+ if (!left || !right) return void 0;
611
+ return { min: Math.min(left.min, right.min), max: Math.max(left.max, right.max) };
612
+ }
613
+ }
614
+ if (ts5.isConditionalExpression(node)) {
615
+ const whenTrue = countExpression(node.whenTrue);
616
+ const whenFalse = countExpression(node.whenFalse);
617
+ if (!whenTrue || !whenFalse) return void 0;
618
+ return {
619
+ min: Math.min(whenTrue.min, whenFalse.min),
620
+ max: Math.max(whenTrue.max, whenFalse.max)
621
+ };
622
+ }
623
+ return void 0;
624
+ }
625
+ function countJsxChildren(children) {
626
+ let min = 0;
627
+ let max = 0;
628
+ for (const child of children) {
629
+ let c;
630
+ if (ts5.isJsxExpression(child)) {
631
+ c = child.expression === void 0 ? ZERO : countExpression(child.expression);
632
+ } else if (ts5.isJsxText(child)) {
633
+ c = child.text.trim().length > 0 ? ONE : ZERO;
634
+ } else if (ts5.isJsxFragment(child)) {
635
+ c = countJsxChildren(child.children);
576
636
  } else {
577
- count++;
637
+ c = ONE;
578
638
  }
639
+ if (!c) return void 0;
640
+ min += c.min;
641
+ max += c.max;
579
642
  }
580
- return count;
643
+ return { min, max };
581
644
  }
582
645
  function diagnoseUsages(source, constraints, severity) {
583
646
  if (constraints.length === 0) return [];
@@ -589,21 +652,22 @@ function diagnoseUsages(source, constraints, severity) {
589
652
  if (ts5.isJsxElement(node)) {
590
653
  const openTag = node.openingElement;
591
654
  tagName = ts5.isIdentifier(openTag.tagName) ? openTag.tagName.text : void 0;
592
- count = countStaticChildren(node);
655
+ count = countJsxChildren(node.children);
593
656
  } else if (ts5.isJsxSelfClosingElement(node)) {
594
657
  tagName = ts5.isIdentifier(node.tagName) ? node.tagName.text : void 0;
595
- count = 0;
658
+ count = ZERO;
596
659
  }
597
660
  if (!tagName) return;
598
661
  const constraint = byName.get(tagName);
599
662
  if (!constraint) return;
600
663
  if (count === void 0) return;
601
664
  const { totalMin, totalMax, name } = constraint;
602
- if (count < totalMin || count > totalMax) {
665
+ if (count.max < totalMin || count.min > totalMax) {
603
666
  const { line, character } = source.getLineAndCharacterOfPosition(node.getStart(source));
604
667
  const rangeText = totalMax === Infinity ? `at least ${totalMin}` : totalMin === totalMax ? `exactly ${totalMin}` : `${totalMin}\u2013${totalMax}`;
668
+ const receivedText = count.min === count.max ? `${count.min}` : `${count.min}\u2013${count.max}`;
605
669
  diagnostics.push({
606
- message: `<${name}> expects ${rangeText} ${totalMax === 1 && totalMin === 1 ? "child" : "children"} but received ${count}.`,
670
+ message: `<${name}> expects ${rangeText} ${totalMax === 1 && totalMin === 1 ? "child" : "children"} but received ${receivedText}.`,
607
671
  line: line + 1,
608
672
  col: character + 1,
609
673
  severity
@@ -650,12 +714,13 @@ var ConstraintRegistry = class {
650
714
  const constraint = this.resolveConstraint(fileId, usage.tagName);
651
715
  if (!constraint) continue;
652
716
  const { totalMin, totalMax, name } = constraint;
653
- if (usage.count >= totalMin && usage.count <= totalMax) continue;
717
+ if (usage.count.max >= totalMin && usage.count.min <= totalMax) continue;
654
718
  const rangeText = totalMax === Infinity ? `at least ${totalMin}` : totalMin === totalMax ? `exactly ${totalMin}` : `${totalMin}\u2013${totalMax}`;
655
719
  const childWord = totalMax === 1 && totalMin === 1 ? "child" : "children";
720
+ const receivedText = usage.count.min === usage.count.max ? `${usage.count.min}` : `${usage.count.min}\u2013${usage.count.max}`;
656
721
  result.push({
657
722
  fileId,
658
- message: `<${name}> expects ${rangeText} ${childWord} but received ${usage.count}.`,
723
+ message: `<${name}> expects ${rangeText} ${childWord} but received ${receivedText}.`,
659
724
  line: usage.line,
660
725
  col: usage.col,
661
726
  severity
@@ -1042,8 +1107,9 @@ function createStaticCompositionTransformer(factory, components, onInlined) {
1042
1107
  return (sourceFile) => ts7.visitEachChild(sourceFile, visit, context);
1043
1108
  };
1044
1109
  }
1045
- function composeStatically(source, calleeNames) {
1046
- const components = extractStaticComponents(source, calleeNames);
1110
+ function composeStatically(source, calleeNames, importedComponents = /* @__PURE__ */ new Map()) {
1111
+ const sameFile = extractStaticComponents(source, calleeNames);
1112
+ const components = importedComponents.size > 0 ? new Map([...importedComponents, ...sameFile]) : sameFile;
1047
1113
  if (components.size === 0) return null;
1048
1114
  const componentNames = new Set(components.keys());
1049
1115
  let hasEligibleTag = false;
@@ -1074,6 +1140,27 @@ function composeStatically(source, calleeNames) {
1074
1140
  return output;
1075
1141
  }
1076
1142
 
1143
+ // ../vite-plugin/src/imports.ts
1144
+ import ts8 from "typescript";
1145
+ function extractImportSpecifiers(source) {
1146
+ const result = /* @__PURE__ */ new Map();
1147
+ walk(source, (node) => {
1148
+ if (!ts8.isImportDeclaration(node)) return;
1149
+ const moduleSpecifier = node.moduleSpecifier;
1150
+ if (!ts8.isStringLiteral(moduleSpecifier)) return;
1151
+ const specifier = moduleSpecifier.text;
1152
+ const namedBindings = node.importClause?.namedBindings;
1153
+ if (!namedBindings || !ts8.isNamedImports(namedBindings)) return;
1154
+ for (const element of namedBindings.elements) {
1155
+ if (element.isTypeOnly) continue;
1156
+ const localName = element.name.text;
1157
+ const importedName = element.propertyName?.text ?? localName;
1158
+ result.set(localName, { importedName, specifier });
1159
+ }
1160
+ });
1161
+ return result;
1162
+ }
1163
+
1077
1164
  // ../vite-plugin/src/analyze.ts
1078
1165
  function analyze(code, filename, options) {
1079
1166
  const ext = filename.split(".").pop() ?? "";
@@ -1088,14 +1175,14 @@ function analyze(code, filename, options) {
1088
1175
  // ../vite-plugin/src/design-tokens.ts
1089
1176
  import { writeFileSync } from "fs";
1090
1177
  import { resolve } from "path";
1091
- import ts8 from "typescript";
1178
+ import ts9 from "typescript";
1092
1179
  function collectStringValues(node, out) {
1093
1180
  if (!node) return;
1094
- if (ts8.isStringLiteral(node)) {
1181
+ if (ts9.isStringLiteral(node)) {
1095
1182
  if (node.text.trim()) out.push(node.text);
1096
1183
  return;
1097
1184
  }
1098
- if (ts8.isArrayLiteralExpression(node)) {
1185
+ if (ts9.isArrayLiteralExpression(node)) {
1099
1186
  for (const elem of node.elements) collectStringValues(elem, out);
1100
1187
  }
1101
1188
  }
@@ -1108,11 +1195,11 @@ function extractStylingTokens(stylingObj) {
1108
1195
  const variantsObj = asObject(getProperty(stylingObj, "variants"));
1109
1196
  if (variantsObj) {
1110
1197
  for (const dimProp of variantsObj.properties) {
1111
- if (!ts8.isPropertyAssignment(dimProp)) continue;
1198
+ if (!ts9.isPropertyAssignment(dimProp)) continue;
1112
1199
  const valuesObj = asObject(dimProp.initializer);
1113
1200
  if (!valuesObj) continue;
1114
1201
  for (const vp of valuesObj.properties) {
1115
- if (!ts8.isPropertyAssignment(vp)) continue;
1202
+ if (!ts9.isPropertyAssignment(vp)) continue;
1116
1203
  collectStringValues(vp.initializer, variantClasses);
1117
1204
  }
1118
1205
  }
@@ -1128,7 +1215,7 @@ function extractStylingTokens(stylingObj) {
1128
1215
  const tagsObj = asObject(getProperty(stylingObj, "tags"));
1129
1216
  if (tagsObj) {
1130
1217
  for (const tp of tagsObj.properties) {
1131
- if (!ts8.isPropertyAssignment(tp)) continue;
1218
+ if (!ts9.isPropertyAssignment(tp)) continue;
1132
1219
  collectStringValues(tp.initializer, tagClasses);
1133
1220
  }
1134
1221
  }
@@ -1136,17 +1223,17 @@ function extractStylingTokens(stylingObj) {
1136
1223
  }
1137
1224
  function collectFileTokens(source, calleeNames) {
1138
1225
  const result = /* @__PURE__ */ new Map();
1139
- ts8.forEachChild(source, (stmt) => {
1140
- if (!ts8.isVariableStatement(stmt)) return;
1226
+ ts9.forEachChild(source, (stmt) => {
1227
+ if (!ts9.isVariableStatement(stmt)) return;
1141
1228
  for (const decl of stmt.declarationList.declarations) {
1142
- if (!decl.initializer || !ts8.isCallExpression(decl.initializer)) continue;
1229
+ if (!decl.initializer || !ts9.isCallExpression(decl.initializer)) continue;
1143
1230
  if (!isFactoryCall(decl.initializer, calleeNames)) continue;
1144
1231
  const arg = firstObjectArg(decl.initializer);
1145
1232
  if (!arg) continue;
1146
1233
  const stylingNode = getProperty(arg, "styling");
1147
1234
  const stylingObj = asObject(stylingNode);
1148
1235
  if (!stylingObj) continue;
1149
- const name = ts8.isIdentifier(decl.name) ? decl.name.text : void 0;
1236
+ const name = ts9.isIdentifier(decl.name) ? decl.name.text : void 0;
1150
1237
  if (!name) continue;
1151
1238
  result.set(name, extractStylingTokens(stylingObj));
1152
1239
  }
@@ -1235,10 +1322,10 @@ function contractPlugin(options) {
1235
1322
  );
1236
1323
  if (importedTagsInUse.size > 0) {
1237
1324
  const resolvedImports = /* @__PURE__ */ new Map();
1238
- for (const [name, specifier] of importSpecifiers) {
1239
- if (!importedTagsInUse.has(name)) continue;
1325
+ for (const [localName, { specifier }] of importSpecifiers) {
1326
+ if (!importedTagsInUse.has(localName)) continue;
1240
1327
  const resolved = await this.resolve(specifier, id);
1241
- if (resolved) resolvedImports.set(name, resolved.id);
1328
+ if (resolved) resolvedImports.set(localName, resolved.id);
1242
1329
  }
1243
1330
  registry.registerImports(id, resolvedImports);
1244
1331
  for (const usage of allUsages) {
@@ -1297,12 +1384,29 @@ function slotTransformPlugin() {
1297
1384
  }
1298
1385
  function staticCompositionPlugin(options) {
1299
1386
  const calleeNames = new Set(options?.calleeNames ?? DEFAULT_CALLEE_NAMES);
1387
+ const registry = /* @__PURE__ */ new Map();
1300
1388
  return {
1301
1389
  name: "praxis-kit:static-compose",
1302
- transform(code, id) {
1390
+ buildStart() {
1391
+ registry.clear();
1392
+ },
1393
+ async transform(code, id) {
1303
1394
  const ext = id.split(".").pop() ?? "";
1304
1395
  if (!JSX_EXTS.has(ext)) return null;
1305
- const result = composeStatically(parseSource(id, code), calleeNames);
1396
+ const source = parseSource(id, code);
1397
+ const sameFile = extractStaticComponents(source, calleeNames);
1398
+ if (sameFile.size > 0) registry.set(id, sameFile);
1399
+ const importedComponents = /* @__PURE__ */ new Map();
1400
+ const importSpecifiers = extractImportSpecifiers(source);
1401
+ for (const [localName, { importedName, specifier }] of importSpecifiers) {
1402
+ const resolved = await this.resolve(specifier, id);
1403
+ if (!resolved) continue;
1404
+ const entry = registry.get(resolved.id);
1405
+ if (!entry) continue;
1406
+ const component = entry.get(importedName);
1407
+ if (component) importedComponents.set(localName, component);
1408
+ }
1409
+ const result = composeStatically(source, calleeNames, importedComponents);
1306
1410
  return result !== null ? { code: result } : null;
1307
1411
  }
1308
1412
  };
@@ -1320,6 +1424,7 @@ export {
1320
1424
  compoundPrunePlugin,
1321
1425
  contractPlugin,
1322
1426
  designTokensPlugin,
1427
+ extractStaticComponents,
1323
1428
  injectPrecomputedClasses,
1324
1429
  pruneDeadCompounds,
1325
1430
  slotTransformPlugin,
@@ -117,9 +117,9 @@ type VariantSelection<V extends VariantMap> = {
117
117
  * Presets are named bundles of variant props that callers activate by key,
118
118
  * avoiding the need to repeat variant combinations at each call site.
119
119
  */
120
- type PresetMap<V extends VariantMap = VariantMap> = Readonly<Record<string, VariantSelection<V>>>;
120
+ type RecipeMap<V extends VariantMap = VariantMap> = Readonly<Record<string, VariantSelection<V>>>;
121
121
 
122
- interface PolymorphicGenerics<TDefault extends ElementType = ElementType, Props extends AnyRecord = AnyRecord, Variants extends Readonly<VariantMap> = Readonly<VariantMap>, TPreset extends PresetMap<Variants> = Readonly<EmptyRecord>, TAllowed extends ElementType = ElementType> {
122
+ interface PolymorphicGenerics<TDefault extends ElementType = ElementType, Props extends AnyRecord = AnyRecord, Variants extends Readonly<VariantMap> = Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TAllowed extends ElementType = ElementType> {
123
123
  default: TDefault;
124
124
  props: Props;
125
125
  variants: Variants;
@@ -127,25 +127,25 @@ interface PolymorphicGenerics<TDefault extends ElementType = ElementType, Props
127
127
  allowed: TAllowed;
128
128
  }
129
129
  type VariantsOf<T extends PolymorphicGenerics> = T['variants'];
130
- type PresetOf<T extends PolymorphicGenerics> = T['preset'];
130
+ type RecipeOf<T extends PolymorphicGenerics> = T['preset'];
131
131
 
132
- type PresetTarget<TVariants extends VariantMap = VariantMap> = VariantSelection<TVariants>;
132
+ type RecipeTarget<TVariants extends VariantMap = VariantMap> = VariantSelection<TVariants>;
133
133
 
134
134
  interface BaseClassOptions {
135
135
  baseClassName?: ClassName;
136
136
  }
137
137
 
138
- type ClassPipelineFn = (tag: unknown, props: AnyRecord, className?: ClassName, variantKey?: string) => string;
138
+ type ClassPipelineFn = (tag: unknown, props: AnyRecord, className?: ClassName, recipe?: string) => string;
139
139
 
140
- interface PresetOptions<TVariants extends VariantMap = VariantMap> {
141
- presetMap?: Record<string, PresetTarget<TVariants>>;
140
+ interface RecipeOptions<TVariants extends VariantMap = VariantMap> {
141
+ recipeMap?: Record<string, RecipeTarget<TVariants>>;
142
142
  }
143
143
 
144
144
  interface TagMapOptions {
145
145
  tagMap?: TagMap;
146
146
  }
147
147
 
148
- type CompositionOptions<TVariants extends VariantMap = VariantMap> = Simplify<TagMapOptions & PresetOptions<TVariants>>;
148
+ type CompositionOptions<TVariants extends VariantMap = VariantMap> = Simplify<TagMapOptions & RecipeOptions<TVariants>>;
149
149
 
150
150
  type CVASystemOptions<TVariants extends VariantMap = VariantMap> = Simplify<CVAVariants<TVariants> & CVADefaults<TVariants> & CVACompounds<TVariants>>;
151
151
 
@@ -220,7 +220,7 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
220
220
  readonly allowedAs?: readonly TAllowed[];
221
221
  };
222
222
 
223
- type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends PresetMap<V> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord> = {
223
+ type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord> = {
224
224
  readonly base?: ClassName;
225
225
  readonly variants?: V;
226
226
  readonly defaults?: Partial<DefaultVariants<V>>;
@@ -234,8 +234,8 @@ type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPre
234
234
  type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
235
235
  normalize(props: Readonly<Props & IntrinsicProps>): Props & IntrinsicProps;
236
236
  }['normalize'];
237
- type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, PresetMap<VariantMap>, AnyRecord>;
238
- type FactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends PresetMap<V> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord, TAllowed extends ElementType = ElementType> = {
237
+ type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyRecord>;
238
+ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord, TAllowed extends ElementType = ElementType> = {
239
239
  readonly tag?: TDefault;
240
240
  readonly name?: string;
241
241
  readonly defaults?: Partial<NoInfer<Props>>;
@@ -247,9 +247,11 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
247
247
  type DefaultOf<T extends PolymorphicGenerics> = T['default'];
248
248
  type PropsOf<T extends PolymorphicGenerics> = T['props'];
249
249
 
250
+ declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
251
+
250
252
  type UnknownProps = Record<string, unknown>;
251
253
 
252
- type VueFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends PresetMap<Variants> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord> = FactoryOptions<TDefault, Props, Variants, TPreset, TPluginProps> & {
254
+ type VueFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord> = FactoryOptions<TDefault, Props, Variants, TPreset, TPluginProps> & {
253
255
  /**
254
256
  * Return true for any prop key that should be consumed but not forwarded to
255
257
  * the DOM. Variant keys are always stripped automatically.
@@ -271,7 +273,7 @@ declare const Slottable: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNod
271
273
  type ControlProps<G extends PolymorphicGenerics, TAs extends ElementType> = PropsOf<G> & VariantProps<VariantsOf<G>> & {
272
274
  as?: TAs;
273
275
  class?: ClassName;
274
- variantKey?: keyof PresetOf<G>;
276
+ recipe?: keyof RecipeOf<G>;
275
277
  };
276
278
  /**
277
279
  * Props for the normal (non-slot) render path. `asChild` is absent or `false`.
@@ -306,8 +308,6 @@ type PolymorphicComponent<G extends PolymorphicGenerics> = {
306
308
  displayName?: string;
307
309
  };
308
310
 
309
- declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends PresetMap<Variants> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord>(options: VueFactoryOptions<TDefault, Props, Variants, TPreset, TPluginProps>): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & TPluginProps, Variants, TPreset>>;
310
-
311
- declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
311
+ declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPluginProps extends AnyRecord = EmptyRecord>(options: VueFactoryOptions<TDefault, Props, Variants, TPreset, TPluginProps>): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & TPluginProps, Variants, TPreset>>;
312
312
 
313
313
  export { type AnyFactoryOptions, type ElementType, type EmptyRecord, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type PolymorphicWithAsChild, Slottable, type SlottableProps, type VueFactoryOptions, createContractComponent, defineContractComponent };
package/dist/vue/index.js CHANGED
@@ -20,7 +20,12 @@ function applyFilter(props, filterProps, variantKeys) {
20
20
  return out;
21
21
  }
22
22
 
23
- // ../core/dist/chunk-XFCAUPVZ.js
23
+ // ../../lib/adapter-utils/src/define-component.ts
24
+ function defineContractComponent(options) {
25
+ return (factory) => factory(options);
26
+ }
27
+
28
+ // ../core/dist/chunk-KKSHJDE7.js
24
29
  function makeResolveTag(defaultTag) {
25
30
  return function tag(as) {
26
31
  return as ?? defaultTag;
@@ -89,7 +94,7 @@ function resolveFactoryOptions(options = {}) {
89
94
  ...whenDefined("defaultProps", options.defaults),
90
95
  ...whenDefined("baseClassName", styling?.base),
91
96
  ...whenDefined("tagMap", styling?.tags),
92
- ...whenDefined("presetMap", styling?.presets),
97
+ ...whenDefined("recipeMap", styling?.presets),
93
98
  ...whenDefined("variants", styling?.variants),
94
99
  ...whenDefined("defaultVariants", styling?.defaults),
95
100
  ...whenDefined("compoundVariants", styling?.compounds),
@@ -130,10 +135,10 @@ function validateFactoryOptions(resolved) {
130
135
  }
131
136
  }
132
137
  };
133
- const { presetMap } = resolved;
134
- if (presetMap) {
135
- for (const presetKey in presetMap) {
136
- checkSelection(`preset "${presetKey}"`, presetMap[presetKey]);
138
+ const { recipeMap } = resolved;
139
+ if (recipeMap) {
140
+ for (const recipeKey in recipeMap) {
141
+ checkSelection(`preset "${recipeKey}"`, recipeMap[recipeKey]);
137
142
  }
138
143
  }
139
144
  if (resolved.defaultVariants) checkSelection("defaults", resolved.defaultVariants);
@@ -169,12 +174,12 @@ function report2(strict, message) {
169
174
  function label(name) {
170
175
  return name ? `[${name}]` : "[createContractComponent]";
171
176
  }
172
- function validateRenderProps(options, props, presetKey) {
173
- const { strict, presetMap, variants, displayName } = options;
177
+ function validateRenderProps(options, props, recipeKey) {
178
+ const { strict, recipeMap, variants, displayName } = options;
174
179
  if (!strict) return;
175
180
  const tag = label(displayName);
176
- if (presetKey !== void 0 && (!presetMap || !Object.hasOwn(presetMap, presetKey))) {
177
- report2(strict, `${tag} Unknown presetKey "${presetKey}" \u2014 no preset with that name exists.`);
181
+ if (recipeKey !== void 0 && (!recipeMap || !Object.hasOwn(recipeMap, recipeKey))) {
182
+ report2(strict, `${tag} Unknown recipeKey "${recipeKey}" \u2014 no preset with that name exists.`);
178
183
  }
179
184
  if (variants) {
180
185
  for (const key in variants) {
@@ -212,8 +217,8 @@ function assertPluginShape(result) {
212
217
  }
213
218
  function guardPipeline(pipeline) {
214
219
  if (process.env.NODE_ENV === "production") return pipeline;
215
- return function guardedPipeline(tag, props, className, variantKey) {
216
- const result = pipeline(tag, props, className, variantKey);
220
+ return function guardedPipeline(tag, props, className, recipe) {
221
+ const result = pipeline(tag, props, className, recipe);
217
222
  if (typeof result !== "string")
218
223
  panic(`[praxis-kit] Plugin pipeline must return a string. Got: ${describe(result)}.`);
219
224
  return result;
@@ -238,11 +243,11 @@ function createRuntimeMethods(resolved, classPipeline, engine) {
238
243
  resolveProps(props) {
239
244
  return mergeProps(resolved.defaultProps, props);
240
245
  },
241
- resolveClasses(tag, props, className, variantKey) {
246
+ resolveClasses(tag, props, className, recipe) {
242
247
  if (process.env.NODE_ENV !== "production") {
243
- validateRenderProps(resolved, props, variantKey);
248
+ validateRenderProps(resolved, props, recipe);
244
249
  }
245
- return classPipeline(tag, props, className, variantKey);
250
+ return classPipeline(tag, props, className, recipe);
246
251
  },
247
252
  resolveAria(tag, props) {
248
253
  if (!engine) return { props };
@@ -591,7 +596,7 @@ function isKnownAriaRole(value) {
591
596
  return isString(value) && KNOWN_ARIA_ROLES_SET.has(value);
592
597
  }
593
598
 
594
- // ../core/dist/chunk-VU44HAB7.js
599
+ // ../core/dist/chunk-BNVYTMYV.js
595
600
  var IMPLICIT_ROLE_RECORD2 = {
596
601
  article: "article",
597
602
  aside: "complementary",
@@ -1526,7 +1531,7 @@ function getHtmlPropNormalizers(tag) {
1526
1531
  return typeof tag === "string" ? HTML_FORM_NORMALIZERS.get(tag) : void 0;
1527
1532
  }
1528
1533
 
1529
- // ../core/dist/chunk-EHCOMLJ4.js
1534
+ // ../core/dist/chunk-3T4EM5FG.js
1530
1535
  var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
1531
1536
  var cx = clsx;
1532
1537
  var cva = (base, config) => (props) => {
@@ -1603,18 +1608,18 @@ var StaticClassResolver = class {
1603
1608
  };
1604
1609
  var VariantClassResolver = class _VariantClassResolver {
1605
1610
  #cvaFn;
1606
- #presetMap;
1611
+ #recipeMap;
1607
1612
  #variantKeys;
1608
1613
  #precomputedClasses;
1609
1614
  #cache = /* @__PURE__ */ new Map();
1610
- constructor(cvaFn, presetMap, variantKeys, precomputedClasses) {
1615
+ constructor(cvaFn, recipeMap, variantKeys, precomputedClasses) {
1611
1616
  this.#cvaFn = cvaFn ?? null;
1612
- this.#presetMap = Object.freeze(presetMap ?? {});
1617
+ this.#recipeMap = Object.freeze(recipeMap ?? {});
1613
1618
  this.#variantKeys = variantKeys ?? null;
1614
1619
  this.#precomputedClasses = precomputedClasses ?? null;
1615
1620
  }
1616
- resolve({ props, variantKey }) {
1617
- const normalizedKey = variantKey ?? "__none__";
1621
+ resolve({ props, recipe }) {
1622
+ const normalizedKey = recipe ?? "__none__";
1618
1623
  const cacheKey = this.#createCacheKey(props, normalizedKey);
1619
1624
  if (this.#precomputedClasses !== null) {
1620
1625
  const precomputed = this.#precomputedClasses[cacheKey];
@@ -1626,7 +1631,7 @@ var VariantClassResolver = class _VariantClassResolver {
1626
1631
  this.#cache.set(cacheKey, cached);
1627
1632
  return cached;
1628
1633
  }
1629
- const result = this.#compute(props, variantKey);
1634
+ const result = this.#compute(props, recipe);
1630
1635
  this.#cache.set(cacheKey, result);
1631
1636
  if (this.#cache.size > 1e3) {
1632
1637
  const lru = this.#cache.keys().next().value;
@@ -1634,10 +1639,10 @@ var VariantClassResolver = class _VariantClassResolver {
1634
1639
  }
1635
1640
  return result;
1636
1641
  }
1637
- #compute(props, variantKey) {
1642
+ #compute(props, recipe) {
1638
1643
  if (!this.#cvaFn) return "";
1639
- if (!variantKey) return this.#cvaFn(props);
1640
- const preset = this.#presetMap[variantKey];
1644
+ if (!recipe) return this.#cvaFn(props);
1645
+ const preset = this.#recipeMap[recipe];
1641
1646
  if (!preset) return this.#cvaFn(props);
1642
1647
  return this.#cvaFn({ ...preset, ...props });
1643
1648
  }
@@ -1645,15 +1650,15 @@ var VariantClassResolver = class _VariantClassResolver {
1645
1650
  // props (className, id, etc.) produce identical CVA output and must not fragment the cache.
1646
1651
  // Iterating #variantKeys directly (fixed Set insertion order) avoids Object.keys + filter + sort.
1647
1652
  // String is built incrementally to avoid a parts[] array allocation on every render.
1648
- #createCacheKey(props, variantKey) {
1653
+ #createCacheKey(props, recipe) {
1649
1654
  if (this.#variantKeys !== null) {
1650
- let key2 = variantKey;
1655
+ let key2 = recipe;
1651
1656
  for (const k of this.#variantKeys) {
1652
1657
  if (k in props) key2 += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
1653
1658
  }
1654
1659
  return key2;
1655
1660
  }
1656
- let key = variantKey;
1661
+ let key = recipe;
1657
1662
  for (const k of Object.keys(props).sort()) {
1658
1663
  key += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
1659
1664
  }
@@ -1678,13 +1683,13 @@ function createClassPipeline(resolved) {
1678
1683
  const staticResolver = new StaticClassResolver(baseClass, resolved.tagMap);
1679
1684
  const variantResolver = new VariantClassResolver(
1680
1685
  cvaFn,
1681
- resolved.presetMap,
1686
+ resolved.recipeMap,
1682
1687
  variantKeys,
1683
1688
  resolved.precomputedClasses
1684
1689
  );
1685
- return function resolveClasses(tag, props, className, variantKey) {
1686
- const staticClasses = staticResolver.resolve(tag, variantKey !== void 0);
1687
- const variantClasses = variantResolver.resolve({ props, variantKey });
1690
+ return function resolveClasses(tag, props, className, recipe) {
1691
+ const staticClasses = staticResolver.resolve(tag, recipe !== void 0);
1692
+ const variantClasses = variantResolver.resolve({ props, recipe });
1688
1693
  if (!className)
1689
1694
  return staticClasses && variantClasses ? `${staticClasses} ${variantClasses}` : staticClasses || variantClasses;
1690
1695
  return cn(staticClasses, variantClasses, className);
@@ -1850,7 +1855,7 @@ function buildDirectives(as, asChild) {
1850
1855
  };
1851
1856
  }
1852
1857
  function resolveRenderState(runtime, attrs, filterProps) {
1853
- const { as, asChild, class: className, variantKey, ...rest } = attrs;
1858
+ const { as, asChild, class: className, recipe, ...rest } = attrs;
1854
1859
  const tag = runtime.resolveTag(as);
1855
1860
  const mergedProps = runtime.resolveProps(rest);
1856
1861
  const baseProps = runtime.options.normalizeFn ? runtime.options.normalizeFn(mergedProps) : mergedProps;
@@ -1860,7 +1865,7 @@ function resolveRenderState(runtime, attrs, filterProps) {
1860
1865
  tag,
1861
1866
  normalizedProps,
1862
1867
  typeof className === "string" ? className : void 0,
1863
- typeof variantKey === "string" ? variantKey : void 0
1868
+ typeof recipe === "string" ? recipe : void 0
1864
1869
  );
1865
1870
  const filteredProps = applyFilter(normalizedProps, filterProps, runtime.options.variantKeys);
1866
1871
  return {
@@ -1959,11 +1964,6 @@ function createContractComponent(options) {
1959
1964
  }
1960
1965
  return Component;
1961
1966
  }
1962
-
1963
- // ../../adapters/vue/src/define-contract-component.ts
1964
- function defineContractComponent(options) {
1965
- return (factory) => factory(options);
1966
- }
1967
1967
  export {
1968
1968
  Slottable,
1969
1969
  createContractComponent,