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.
- package/dist/{chunk-ACAKUHH5.js → chunk-PBBPAHMV.js} +170 -164
- package/dist/contract/index.d.ts +9 -9
- package/dist/contract/index.js +2 -2
- package/dist/lit/index.d.ts +14 -14
- package/dist/lit/index.js +45 -45
- package/dist/{merge-refs-tA18zYP6.d.ts → merge-refs-CfAbwCKz.d.ts} +16 -14
- package/dist/preact/index.d.ts +16 -16
- package/dist/preact/index.js +40 -40
- package/dist/react/index.d.ts +8 -10
- package/dist/react/index.js +2 -6
- package/dist/react/legacy.d.ts +7 -7
- package/dist/react/legacy.js +3 -1
- package/dist/solid/index.d.ts +17 -17
- package/dist/solid/index.js +40 -40
- package/dist/svelte/index.d.ts +20 -20
- package/dist/svelte/index.js +38 -38
- package/dist/tailwind/index.js +23 -23
- package/dist/vite-plugin/index.d.ts +76 -50
- package/dist/vite-plugin/index.js +146 -41
- package/dist/vue/index.d.ts +16 -16
- package/dist/vue/index.js +40 -40
- package/dist/web/index.d.ts +14 -14
- package/dist/web/index.js +43 -43
- package/package.json +3 -3
|
@@ -332,11 +332,13 @@ function processVariableStatement(node, calleeNames, out) {
|
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
334
|
if (rules.length === 0 && !hasAriaRules && !defaultTag) continue;
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 ${
|
|
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
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
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
|
-
|
|
637
|
+
c = ONE;
|
|
578
638
|
}
|
|
639
|
+
if (!c) return void 0;
|
|
640
|
+
min += c.min;
|
|
641
|
+
max += c.max;
|
|
579
642
|
}
|
|
580
|
-
return
|
|
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 =
|
|
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 =
|
|
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 ${
|
|
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 ${
|
|
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
|
|
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
|
|
1178
|
+
import ts9 from "typescript";
|
|
1092
1179
|
function collectStringValues(node, out) {
|
|
1093
1180
|
if (!node) return;
|
|
1094
|
-
if (
|
|
1181
|
+
if (ts9.isStringLiteral(node)) {
|
|
1095
1182
|
if (node.text.trim()) out.push(node.text);
|
|
1096
1183
|
return;
|
|
1097
1184
|
}
|
|
1098
|
-
if (
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
-
|
|
1140
|
-
if (!
|
|
1226
|
+
ts9.forEachChild(source, (stmt) => {
|
|
1227
|
+
if (!ts9.isVariableStatement(stmt)) return;
|
|
1141
1228
|
for (const decl of stmt.declarationList.declarations) {
|
|
1142
|
-
if (!decl.initializer || !
|
|
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 =
|
|
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 [
|
|
1239
|
-
if (!importedTagsInUse.has(
|
|
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(
|
|
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
|
-
|
|
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
|
|
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,
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
130
|
+
type RecipeOf<T extends PolymorphicGenerics> = T['preset'];
|
|
131
131
|
|
|
132
|
-
type
|
|
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,
|
|
138
|
+
type ClassPipelineFn = (tag: unknown, props: AnyRecord, className?: ClassName, recipe?: string) => string;
|
|
139
139
|
|
|
140
|
-
interface
|
|
141
|
-
|
|
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 &
|
|
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
|
|
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,
|
|
238
|
-
type FactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
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("
|
|
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 {
|
|
134
|
-
if (
|
|
135
|
-
for (const
|
|
136
|
-
checkSelection(`preset "${
|
|
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,
|
|
173
|
-
const { strict,
|
|
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 (
|
|
177
|
-
report2(strict, `${tag} Unknown
|
|
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,
|
|
216
|
-
const result = pipeline(tag, props, className,
|
|
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,
|
|
246
|
+
resolveClasses(tag, props, className, recipe) {
|
|
242
247
|
if (process.env.NODE_ENV !== "production") {
|
|
243
|
-
validateRenderProps(resolved, props,
|
|
248
|
+
validateRenderProps(resolved, props, recipe);
|
|
244
249
|
}
|
|
245
|
-
return classPipeline(tag, props, className,
|
|
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-
|
|
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-
|
|
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
|
-
#
|
|
1611
|
+
#recipeMap;
|
|
1607
1612
|
#variantKeys;
|
|
1608
1613
|
#precomputedClasses;
|
|
1609
1614
|
#cache = /* @__PURE__ */ new Map();
|
|
1610
|
-
constructor(cvaFn,
|
|
1615
|
+
constructor(cvaFn, recipeMap, variantKeys, precomputedClasses) {
|
|
1611
1616
|
this.#cvaFn = cvaFn ?? null;
|
|
1612
|
-
this.#
|
|
1617
|
+
this.#recipeMap = Object.freeze(recipeMap ?? {});
|
|
1613
1618
|
this.#variantKeys = variantKeys ?? null;
|
|
1614
1619
|
this.#precomputedClasses = precomputedClasses ?? null;
|
|
1615
1620
|
}
|
|
1616
|
-
resolve({ props,
|
|
1617
|
-
const normalizedKey =
|
|
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,
|
|
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,
|
|
1642
|
+
#compute(props, recipe) {
|
|
1638
1643
|
if (!this.#cvaFn) return "";
|
|
1639
|
-
if (!
|
|
1640
|
-
const preset = this.#
|
|
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,
|
|
1653
|
+
#createCacheKey(props, recipe) {
|
|
1649
1654
|
if (this.#variantKeys !== null) {
|
|
1650
|
-
let key2 =
|
|
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 =
|
|
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.
|
|
1686
|
+
resolved.recipeMap,
|
|
1682
1687
|
variantKeys,
|
|
1683
1688
|
resolved.precomputedClasses
|
|
1684
1689
|
);
|
|
1685
|
-
return function resolveClasses(tag, props, className,
|
|
1686
|
-
const staticClasses = staticResolver.resolve(tag,
|
|
1687
|
-
const variantClasses = variantResolver.resolve({ props,
|
|
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,
|
|
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
|
|
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,
|