@grampro/kit 2.6.3 → 2.7.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/.gbs/skills/gbs-components/SKILL.md +5 -4
- package/.gbs/skills/gbs-components/references/install.md +17 -14
- package/CHANGELOG.md +164 -0
- package/README.md +19 -6
- package/index.cjs +59 -59
- package/package.json +2 -2
- package/schema/passport-overlay-v1.schema.json +67 -0
- package/source/components/accordion/passport.json +45 -8
- package/source/components/accordion/passport.manual.json +46 -0
- package/source/components/alert/passport.json +41 -8
- package/source/components/alert/passport.manual.json +42 -0
- package/source/components/avatar/passport.json +40 -7
- package/source/components/avatar/passport.manual.json +43 -0
- package/source/components/badge/passport.json +43 -7
- package/source/components/badge/passport.manual.json +46 -0
- package/source/components/breadcrumb/passport.json +36 -7
- package/source/components/breadcrumb/passport.manual.json +39 -0
- package/source/components/button/passport.json +1 -1
- package/source/components/button/passport.manual.json +1 -1
- package/source/components/card/passport.json +45 -8
- package/source/components/card/passport.manual.json +47 -0
- package/source/components/checkbox/core/agent.ts +33 -0
- package/source/components/checkbox/core/index.ts +2 -0
- package/source/components/checkbox/passport.json +83 -10
- package/source/components/checkbox/passport.manual.json +82 -0
- package/source/components/combobox/core/agent.ts +38 -0
- package/source/components/combobox/core/index.ts +2 -0
- package/source/components/combobox/passport.json +103 -11
- package/source/components/combobox/passport.manual.json +101 -0
- package/source/components/combobox/react/props.ts +14 -0
- package/source/components/combobox/react/useCombobox.ts +7 -1
- package/source/components/data-grid/export/xlsx.ts +9 -2
- package/source/components/data-grid/passport.json +2 -2
- package/source/components/data-grid/passport.manual.json +1 -1
- package/source/components/date-picker/core/agent.ts +42 -0
- package/source/components/date-picker/core/index.ts +2 -0
- package/source/components/date-picker/passport.json +102 -11
- package/source/components/date-picker/passport.manual.json +100 -0
- package/source/components/date-picker/react/DatePicker.tsx +6 -0
- package/source/components/date-picker/react/DateRangePicker.tsx +4 -0
- package/source/components/date-picker/react/props.ts +17 -0
- package/source/components/dialog/passport.json +54 -9
- package/source/components/dialog/passport.manual.json +54 -0
- package/source/components/file-uploader/passport.json +65 -10
- package/source/components/file-uploader/passport.manual.json +64 -0
- package/source/components/input/core/agent.ts +36 -0
- package/source/components/input/core/index.ts +2 -0
- package/source/components/input/passport.json +89 -12
- package/source/components/input/passport.manual.json +86 -0
- package/source/components/menu/passport.json +64 -9
- package/source/components/menu/passport.manual.json +64 -0
- package/source/components/modal/passport.json +52 -9
- package/source/components/modal/passport.manual.json +52 -0
- package/source/components/number-input/core/agent.ts +38 -0
- package/source/components/number-input/core/index.ts +2 -0
- package/source/components/number-input/passport.json +92 -11
- package/source/components/number-input/passport.manual.json +90 -0
- package/source/components/popover/passport.json +47 -8
- package/source/components/popover/passport.manual.json +48 -0
- package/source/components/progress/passport.json +37 -8
- package/source/components/progress/passport.manual.json +39 -0
- package/source/components/radio-group/core/agent.ts +34 -0
- package/source/components/radio-group/core/index.ts +2 -0
- package/source/components/radio-group/passport.json +77 -10
- package/source/components/radio-group/passport.manual.json +76 -0
- package/source/components/shared/core/agent/field-agent.ts +101 -0
- package/source/components/shared/core/agent/field-executors.ts +137 -0
- package/source/components/shared/core/agent/field.ts +649 -0
- package/source/components/shared/core/agent/index.ts +30 -0
- package/source/components/shared/core/agent/write.ts +58 -0
- package/source/components/shared/react/useFieldAgent.ts +88 -0
- package/source/components/skeleton/passport.json +37 -6
- package/source/components/skeleton/passport.manual.json +39 -0
- package/source/components/spinner/passport.json +34 -7
- package/source/components/spinner/passport.manual.json +37 -0
- package/source/components/switch/core/agent.ts +31 -0
- package/source/components/switch/core/index.ts +2 -0
- package/source/components/switch/passport.json +68 -10
- package/source/components/switch/passport.manual.json +67 -0
- package/source/components/tabs/passport.json +50 -9
- package/source/components/tabs/passport.manual.json +50 -0
- package/source/components/textarea/core/agent.ts +34 -0
- package/source/components/textarea/core/index.ts +2 -0
- package/source/components/textarea/passport.json +83 -10
- package/source/components/textarea/passport.manual.json +82 -0
- package/source/components/toaster/passport.json +41 -8
- package/source/components/toaster/passport.manual.json +42 -0
- package/source/components/tooltip/passport.json +39 -6
- package/source/components/tooltip/passport.manual.json +41 -0
- package/tools/mcp/design.cjs +6 -1
- package/tools/mcp/figma.cjs +49 -9
- package/tools/mcp/install.cjs +6 -1
- package/tools/mcp/server.cjs +14 -2
package/index.cjs
CHANGED
|
@@ -28,7 +28,7 @@ const readline = require("readline");
|
|
|
28
28
|
|
|
29
29
|
// Configuration
|
|
30
30
|
const CONFIG = {
|
|
31
|
-
|
|
31
|
+
legacyComponents: [
|
|
32
32
|
"Card",
|
|
33
33
|
"Select",
|
|
34
34
|
"SideBar",
|
|
@@ -55,7 +55,7 @@ const CONFIG = {
|
|
|
55
55
|
"UsePaginatedData",
|
|
56
56
|
"UseUploader",
|
|
57
57
|
],
|
|
58
|
-
|
|
58
|
+
components: [
|
|
59
59
|
"DataGrid",
|
|
60
60
|
"Combobox",
|
|
61
61
|
"DatePicker",
|
|
@@ -84,8 +84,8 @@ const CONFIG = {
|
|
|
84
84
|
"Badge",
|
|
85
85
|
"Progress",
|
|
86
86
|
],
|
|
87
|
-
//
|
|
88
|
-
|
|
87
|
+
// Folder names that are not simply the lowercased component name.
|
|
88
|
+
folders: {
|
|
89
89
|
DataGrid: "data-grid",
|
|
90
90
|
DatePicker: "date-picker",
|
|
91
91
|
FileUploader: "file-uploader",
|
|
@@ -198,7 +198,7 @@ const NL = String.fromCharCode(10);
|
|
|
198
198
|
const CLI_NAME = "@grampro/kit";
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
|
-
* Every
|
|
201
|
+
* Every component imports its shared helpers from `../../shared`, so this
|
|
202
202
|
* folder is installed alongside whatever the user picked. It is not a component
|
|
203
203
|
* and never appears in the component list.
|
|
204
204
|
*/
|
|
@@ -220,14 +220,14 @@ const normalizeComponent = (component, availableComponents) =>
|
|
|
220
220
|
(available) => available.toLowerCase() === component.toLowerCase(),
|
|
221
221
|
);
|
|
222
222
|
|
|
223
|
-
const getAvailableComponents = (
|
|
224
|
-
|
|
223
|
+
const getAvailableComponents = (current = false) =>
|
|
224
|
+
current ? CONFIG.components : CONFIG.legacyComponents;
|
|
225
225
|
|
|
226
|
-
const getSourcePath = (
|
|
226
|
+
const getSourcePath = (current = false) => (current ? SOURCE_PATH : LEGACY_SOURCE_PATH);
|
|
227
227
|
|
|
228
228
|
/** The folder a component lives in, which is not always its lowercased name. */
|
|
229
|
-
const folderFor = (component,
|
|
230
|
-
(
|
|
229
|
+
const folderFor = (component, current = false) =>
|
|
230
|
+
(current && CONFIG.folders[component]) || component.toLowerCase();
|
|
231
231
|
|
|
232
232
|
|
|
233
233
|
/*
|
|
@@ -271,8 +271,8 @@ const relativeFrom = (file, dir) => {
|
|
|
271
271
|
return rel.startsWith(".") ? rel : "./" + rel;
|
|
272
272
|
};
|
|
273
273
|
|
|
274
|
-
const writeStyleBarrel = async (destPath,
|
|
275
|
-
if (!
|
|
274
|
+
const writeStyleBarrel = async (destPath, current) => {
|
|
275
|
+
if (!current) return null;
|
|
276
276
|
|
|
277
277
|
// Whatever is on disk now, not whatever this run happened to install: the
|
|
278
278
|
// barrel has to stay correct across repeated and partial installs.
|
|
@@ -452,7 +452,7 @@ const installShared = async (destPath, { force = false } = {}) => {
|
|
|
452
452
|
|
|
453
453
|
if (!fs.existsSync(src)) {
|
|
454
454
|
throw new Error(
|
|
455
|
-
`The shared folder is missing from ${SOURCE_PATH}.
|
|
455
|
+
`The shared folder is missing from ${SOURCE_PATH}. Components cannot be installed without it.`,
|
|
456
456
|
);
|
|
457
457
|
}
|
|
458
458
|
|
|
@@ -914,12 +914,12 @@ const isSkillWord = (value) =>
|
|
|
914
914
|
typeof value === "string" && value.trim().toLowerCase() === "skill";
|
|
915
915
|
|
|
916
916
|
/** The files a component needs beside it, which differ between the two sets. */
|
|
917
|
-
const copySupportFiles = async (destPath,
|
|
918
|
-
if (
|
|
917
|
+
const copySupportFiles = async (destPath, current, options) => {
|
|
918
|
+
if (current) {
|
|
919
919
|
await installShared(destPath, options);
|
|
920
920
|
return;
|
|
921
921
|
}
|
|
922
|
-
// The legacy components' common files.
|
|
922
|
+
// The legacy components' common files. The current set uses none of them.
|
|
923
923
|
if (!fs.existsSync(path.join(destPath, "utils.ts"))) {
|
|
924
924
|
await copyCommonFiles(destPath);
|
|
925
925
|
}
|
|
@@ -927,22 +927,22 @@ const copySupportFiles = async (destPath, beta, options) => {
|
|
|
927
927
|
|
|
928
928
|
/* -------------------------------------------------------------- components */
|
|
929
929
|
|
|
930
|
-
const checkComponentExists = (component, destPath,
|
|
931
|
-
const componentPath = path.join(destPath, folderFor(component,
|
|
930
|
+
const checkComponentExists = (component, destPath, current = false) => {
|
|
931
|
+
const componentPath = path.join(destPath, folderFor(component, current));
|
|
932
932
|
return fs.existsSync(componentPath);
|
|
933
933
|
};
|
|
934
934
|
|
|
935
|
-
const copyComponent = async (component, destPath,
|
|
935
|
+
const copyComponent = async (component, destPath, current = false) => {
|
|
936
936
|
try {
|
|
937
937
|
const componentSrc = path.join(
|
|
938
|
-
getSourcePath(
|
|
939
|
-
folderFor(component,
|
|
938
|
+
getSourcePath(current),
|
|
939
|
+
folderFor(component, current),
|
|
940
940
|
);
|
|
941
|
-
const componentDest = path.join(destPath, folderFor(component,
|
|
941
|
+
const componentDest = path.join(destPath, folderFor(component, current));
|
|
942
942
|
|
|
943
943
|
if (!fs.existsSync(componentSrc)) {
|
|
944
944
|
throw new Error(
|
|
945
|
-
`Component ${component} not found in ${
|
|
945
|
+
`Component ${component} not found in ${current ? "" : "1.x "}source directory.`,
|
|
946
946
|
);
|
|
947
947
|
}
|
|
948
948
|
|
|
@@ -969,17 +969,17 @@ const copyComponent = async (component, destPath, beta = false) => {
|
|
|
969
969
|
const installComponentWithDependencies = async (
|
|
970
970
|
component,
|
|
971
971
|
destPath,
|
|
972
|
-
|
|
972
|
+
current = false,
|
|
973
973
|
) => {
|
|
974
974
|
// Get dependencies for the component
|
|
975
975
|
const dependencies = CONFIG.dependencies[component] || [];
|
|
976
976
|
const componentsToInstall = new Set([component, ...dependencies]);
|
|
977
977
|
|
|
978
978
|
// Check which components need to be installed
|
|
979
|
-
const pendingInstalls =
|
|
979
|
+
const pendingInstalls = current
|
|
980
980
|
? Array.from(componentsToInstall)
|
|
981
981
|
: Array.from(componentsToInstall).filter(
|
|
982
|
-
(comp) => !checkComponentExists(comp, destPath,
|
|
982
|
+
(comp) => !checkComponentExists(comp, destPath, current),
|
|
983
983
|
);
|
|
984
984
|
|
|
985
985
|
if (pendingInstalls.length === 0) {
|
|
@@ -991,7 +991,7 @@ const installComponentWithDependencies = async (
|
|
|
991
991
|
|
|
992
992
|
// Install all pending components
|
|
993
993
|
for (const comp of pendingInstalls) {
|
|
994
|
-
await copyComponent(comp, destPath,
|
|
994
|
+
await copyComponent(comp, destPath, current);
|
|
995
995
|
}
|
|
996
996
|
|
|
997
997
|
if (dependencies.length > 0) {
|
|
@@ -1001,7 +1001,7 @@ const installComponentWithDependencies = async (
|
|
|
1001
1001
|
});
|
|
1002
1002
|
}
|
|
1003
1003
|
|
|
1004
|
-
reportStyleBarrel(await writeStyleBarrel(destPath,
|
|
1004
|
+
reportStyleBarrel(await writeStyleBarrel(destPath, current));
|
|
1005
1005
|
|
|
1006
1006
|
console.log(`\nFor documentation visit: ${CONFIG.docs}`);
|
|
1007
1007
|
};
|
|
@@ -1009,7 +1009,7 @@ const installComponentWithDependencies = async (
|
|
|
1009
1009
|
const installMultipleComponents = async (
|
|
1010
1010
|
components,
|
|
1011
1011
|
destPath,
|
|
1012
|
-
|
|
1012
|
+
current = false,
|
|
1013
1013
|
) => {
|
|
1014
1014
|
const allComponentsToInstall = new Set();
|
|
1015
1015
|
|
|
@@ -1021,10 +1021,10 @@ const installMultipleComponents = async (
|
|
|
1021
1021
|
});
|
|
1022
1022
|
|
|
1023
1023
|
// Filter out already installed components
|
|
1024
|
-
const pendingInstalls =
|
|
1024
|
+
const pendingInstalls = current
|
|
1025
1025
|
? Array.from(allComponentsToInstall)
|
|
1026
1026
|
: Array.from(allComponentsToInstall).filter(
|
|
1027
|
-
(comp) => !checkComponentExists(comp, destPath,
|
|
1027
|
+
(comp) => !checkComponentExists(comp, destPath, current),
|
|
1028
1028
|
);
|
|
1029
1029
|
|
|
1030
1030
|
if (pendingInstalls.length === 0) {
|
|
@@ -1038,7 +1038,7 @@ const installMultipleComponents = async (
|
|
|
1038
1038
|
|
|
1039
1039
|
// Install all pending components
|
|
1040
1040
|
for (const comp of pendingInstalls) {
|
|
1041
|
-
await copyComponent(comp, destPath,
|
|
1041
|
+
await copyComponent(comp, destPath, current);
|
|
1042
1042
|
}
|
|
1043
1043
|
|
|
1044
1044
|
// Show dependency information
|
|
@@ -1055,12 +1055,12 @@ const installMultipleComponents = async (
|
|
|
1055
1055
|
});
|
|
1056
1056
|
}
|
|
1057
1057
|
|
|
1058
|
-
reportStyleBarrel(await writeStyleBarrel(destPath,
|
|
1058
|
+
reportStyleBarrel(await writeStyleBarrel(destPath, current));
|
|
1059
1059
|
|
|
1060
1060
|
console.log(`\nFor documentation visit: ${CONFIG.docs}`);
|
|
1061
1061
|
};
|
|
1062
1062
|
|
|
1063
|
-
const interactiveComponentSelector = async (
|
|
1063
|
+
const interactiveComponentSelector = async (current = false) => {
|
|
1064
1064
|
return new Promise((resolve) => {
|
|
1065
1065
|
const rl = readline.createInterface({
|
|
1066
1066
|
input: process.stdin,
|
|
@@ -1077,7 +1077,7 @@ const interactiveComponentSelector = async (beta = false) => {
|
|
|
1077
1077
|
"Use ↑/↓ arrow keys to navigate, SPACE to select/deselect, ENTER to install\n",
|
|
1078
1078
|
);
|
|
1079
1079
|
|
|
1080
|
-
const availableComponents = getAvailableComponents(
|
|
1080
|
+
const availableComponents = getAvailableComponents(current);
|
|
1081
1081
|
|
|
1082
1082
|
availableComponents.forEach((component, index) => {
|
|
1083
1083
|
const isSelected = selectedComponents.has(component);
|
|
@@ -1109,13 +1109,13 @@ const interactiveComponentSelector = async (beta = false) => {
|
|
|
1109
1109
|
break;
|
|
1110
1110
|
case "[B": // Down arrow
|
|
1111
1111
|
currentIndex = Math.min(
|
|
1112
|
-
getAvailableComponents(
|
|
1112
|
+
getAvailableComponents(current).length - 1,
|
|
1113
1113
|
currentIndex + 1,
|
|
1114
1114
|
);
|
|
1115
1115
|
renderMenu();
|
|
1116
1116
|
break;
|
|
1117
1117
|
case " ": // Space bar
|
|
1118
|
-
const component = getAvailableComponents(
|
|
1118
|
+
const component = getAvailableComponents(current)[currentIndex];
|
|
1119
1119
|
if (selectedComponents.has(component)) {
|
|
1120
1120
|
selectedComponents.delete(component);
|
|
1121
1121
|
} else {
|
|
@@ -1158,23 +1158,23 @@ const parseMultipleComponents = (componentString) => {
|
|
|
1158
1158
|
.filter((comp) => comp.length > 0);
|
|
1159
1159
|
};
|
|
1160
1160
|
|
|
1161
|
-
const validateComponents = (components,
|
|
1162
|
-
const availableComponents = getAvailableComponents(
|
|
1161
|
+
const validateComponents = (components, current = false) => {
|
|
1162
|
+
const availableComponents = getAvailableComponents(current);
|
|
1163
1163
|
const invalidComponents = components.filter(
|
|
1164
1164
|
(comp) => !availableComponents.includes(comp),
|
|
1165
1165
|
);
|
|
1166
1166
|
if (invalidComponents.length > 0) {
|
|
1167
1167
|
if (invalidComponents.some((comp) => comp.toLowerCase() === SHARED_DIR)) {
|
|
1168
1168
|
console.error(
|
|
1169
|
-
"`shared` is not a component: it is installed automatically with any
|
|
1169
|
+
"`shared` is not a component: it is installed automatically with any component.",
|
|
1170
1170
|
);
|
|
1171
1171
|
}
|
|
1172
1172
|
console.error(`Invalid components: ${invalidComponents.join(", ")}`);
|
|
1173
|
-
console.log(`\nAvailable ${
|
|
1173
|
+
console.log(`\nAvailable ${current ? "" : "1.x "}components:`);
|
|
1174
1174
|
availableComponents.forEach((comp) => console.log(`- ${comp}`));
|
|
1175
|
-
if (!
|
|
1176
|
-
console.log("\
|
|
1177
|
-
CONFIG.
|
|
1175
|
+
if (!current) {
|
|
1176
|
+
console.log("\nThe 2.x components, which are the default (drop --legacy):");
|
|
1177
|
+
CONFIG.components.forEach((comp) => console.log(`- ${comp}`));
|
|
1178
1178
|
}
|
|
1179
1179
|
return false;
|
|
1180
1180
|
}
|
|
@@ -1306,7 +1306,7 @@ const main = async () => {
|
|
|
1306
1306
|
* which is where the old `--beta` flag's meaning went: it used to opt *in* to
|
|
1307
1307
|
* these, and now there is nothing to opt into.
|
|
1308
1308
|
*/
|
|
1309
|
-
const
|
|
1309
|
+
const current = !argv.legacy;
|
|
1310
1310
|
|
|
1311
1311
|
if (argv["beta"] === true) {
|
|
1312
1312
|
console.log(
|
|
@@ -1381,24 +1381,24 @@ const main = async () => {
|
|
|
1381
1381
|
|
|
1382
1382
|
// List components if requested
|
|
1383
1383
|
if (argv.list) {
|
|
1384
|
-
const availableComponents = getAvailableComponents(
|
|
1385
|
-
console.log(`\nAvailable ${
|
|
1384
|
+
const availableComponents = getAvailableComponents(current);
|
|
1385
|
+
console.log(`\nAvailable ${current ? "" : "1.x "}components:`);
|
|
1386
1386
|
availableComponents.forEach((comp) => {
|
|
1387
1387
|
const deps = CONFIG.dependencies[comp]
|
|
1388
1388
|
? ` (requires: ${CONFIG.dependencies[comp].join(", ")})`
|
|
1389
1389
|
: "";
|
|
1390
1390
|
console.log(`- ${comp}${deps}`);
|
|
1391
1391
|
});
|
|
1392
|
-
if (
|
|
1392
|
+
if (current) {
|
|
1393
1393
|
console.log(
|
|
1394
|
-
`\nEvery
|
|
1394
|
+
`\nEvery component also installs component-lib/${SHARED_DIR}, which they all import.`,
|
|
1395
1395
|
);
|
|
1396
1396
|
console.log(
|
|
1397
1397
|
`${NL}The agent skill installs separately, at the project root, for ${SKILL_TARGETS.join(", ")} and the GBS agent:${NL} npx @grampro/kit skill`,
|
|
1398
1398
|
);
|
|
1399
1399
|
} else {
|
|
1400
|
-
console.log("\
|
|
1401
|
-
CONFIG.
|
|
1400
|
+
console.log("\nThe 2.x components, which are the default (drop --legacy):");
|
|
1401
|
+
CONFIG.components.forEach((comp) => console.log(`- ${comp}`));
|
|
1402
1402
|
}
|
|
1403
1403
|
return;
|
|
1404
1404
|
}
|
|
@@ -1406,7 +1406,7 @@ const main = async () => {
|
|
|
1406
1406
|
// Interactive mode
|
|
1407
1407
|
if (argv.interactive) {
|
|
1408
1408
|
console.log("Starting interactive component selector...\n");
|
|
1409
|
-
const selectedComponents = await interactiveComponentSelector(
|
|
1409
|
+
const selectedComponents = await interactiveComponentSelector(current);
|
|
1410
1410
|
|
|
1411
1411
|
if (selectedComponents.length === 0) {
|
|
1412
1412
|
console.log("No components selected. Exiting...");
|
|
@@ -1416,10 +1416,10 @@ const main = async () => {
|
|
|
1416
1416
|
const destPath = resolveDestPath(argv.dest);
|
|
1417
1417
|
await fs.ensureDir(destPath);
|
|
1418
1418
|
|
|
1419
|
-
await copySupportFiles(destPath,
|
|
1419
|
+
await copySupportFiles(destPath, current, { force: argv.force });
|
|
1420
1420
|
|
|
1421
1421
|
// Install selected components
|
|
1422
|
-
await installMultipleComponents(selectedComponents, destPath,
|
|
1422
|
+
await installMultipleComponents(selectedComponents, destPath, current);
|
|
1423
1423
|
return;
|
|
1424
1424
|
}
|
|
1425
1425
|
|
|
@@ -1453,27 +1453,27 @@ const main = async () => {
|
|
|
1453
1453
|
const componentInput = argv.add;
|
|
1454
1454
|
const components = parseMultipleComponents(componentInput).map(
|
|
1455
1455
|
(component) =>
|
|
1456
|
-
normalizeComponent(component, getAvailableComponents(
|
|
1456
|
+
normalizeComponent(component, getAvailableComponents(current)) ||
|
|
1457
1457
|
component,
|
|
1458
1458
|
);
|
|
1459
1459
|
|
|
1460
1460
|
// Validate all components
|
|
1461
|
-
if (!validateComponents(components,
|
|
1461
|
+
if (!validateComponents(components, current)) {
|
|
1462
1462
|
process.exit(1);
|
|
1463
1463
|
}
|
|
1464
1464
|
|
|
1465
1465
|
const destPath = resolveDestPath(argv.dest);
|
|
1466
1466
|
await fs.ensureDir(destPath);
|
|
1467
1467
|
|
|
1468
|
-
await copySupportFiles(destPath,
|
|
1468
|
+
await copySupportFiles(destPath, current, { force: argv.force });
|
|
1469
1469
|
|
|
1470
1470
|
// Install components
|
|
1471
1471
|
if (components.length === 1) {
|
|
1472
1472
|
// Single component installation (existing behavior)
|
|
1473
|
-
await installComponentWithDependencies(components[0], destPath,
|
|
1473
|
+
await installComponentWithDependencies(components[0], destPath, current);
|
|
1474
1474
|
} else {
|
|
1475
1475
|
// Multiple components installation
|
|
1476
|
-
await installMultipleComponents(components, destPath,
|
|
1476
|
+
await installMultipleComponents(components, destPath, current);
|
|
1477
1477
|
}
|
|
1478
1478
|
};
|
|
1479
1479
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grampro/kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "GramproKit \u2014 an agent-native UI runtime for React. Copy-in components you own, each publishing a contract that software can read.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"author": "Anandhu Remanan",
|
|
46
46
|
"license": "ISC",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@grampro/headless-helpers": "^1.0.
|
|
48
|
+
"@grampro/headless-helpers": "^1.0.22",
|
|
49
49
|
"fs-extra": "^11.0.4",
|
|
50
50
|
"tailwind-merge": "^3.6.0",
|
|
51
51
|
"yargs": "^17.7.2"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://kit.gramproindia.com/schema/passport-overlay-v1.schema.json",
|
|
4
|
+
"title": "GramproKit Passport Overlay v1",
|
|
5
|
+
"description": "The authored half of a component passport: passport.manual.json, written by the library, and passport.local.json, owned by the consuming developer. An overlay is a partial — the generator supplies passportVersion, identity, source, props, events, slots, states and coverage from the TypeScript, and merging the two produces passport.json, which passport-v1.schema.json describes. Validating an overlay against that schema reports all eight generated fields as missing and rejects the keys only an overlay has, which is why this file exists.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["component"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
"component": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Which component this annotates. Checked against the folder it sits in."
|
|
16
|
+
},
|
|
17
|
+
"purpose": {
|
|
18
|
+
"$ref": "./passport-v1.schema.json#/properties/purpose"
|
|
19
|
+
},
|
|
20
|
+
"accessibility": {
|
|
21
|
+
"$ref": "./passport-v1.schema.json#/properties/accessibility"
|
|
22
|
+
},
|
|
23
|
+
"composition": {
|
|
24
|
+
"$ref": "./passport-v1.schema.json#/properties/composition"
|
|
25
|
+
},
|
|
26
|
+
"operations": {
|
|
27
|
+
"$ref": "./passport-v1.schema.json#/properties/operations"
|
|
28
|
+
},
|
|
29
|
+
"intentDomains": {
|
|
30
|
+
"$ref": "./passport-v1.schema.json#/properties/intentDomains"
|
|
31
|
+
},
|
|
32
|
+
"safeMutations": {
|
|
33
|
+
"$ref": "./passport-v1.schema.json#/properties/safeMutations"
|
|
34
|
+
},
|
|
35
|
+
"examples": {
|
|
36
|
+
"$ref": "./passport-v1.schema.json#/properties/examples"
|
|
37
|
+
},
|
|
38
|
+
"props": {
|
|
39
|
+
"type": "array",
|
|
40
|
+
"description": "Annotations for derived props, by name: a description, a note or a deprecation. Only passport.local.json may introduce a prop that is not in the source.",
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"required": ["name"],
|
|
44
|
+
"properties": {
|
|
45
|
+
"name": { "type": "string" },
|
|
46
|
+
"description": { "type": "string" },
|
|
47
|
+
"note": { "type": "string" },
|
|
48
|
+
"deprecated": { "type": ["string", "boolean"] }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"propNotes": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"description": "Shorthand for annotating derived props: a map of prop name to note. Every key must name a prop the source actually has.",
|
|
55
|
+
"additionalProperties": { "type": "string" }
|
|
56
|
+
},
|
|
57
|
+
"notImplemented": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"description": "Capabilities a reader might reasonably expect and this component does not have. Saying so is cheaper than an agent discovering it by writing code that cannot work.",
|
|
60
|
+
"items": { "type": "string" }
|
|
61
|
+
},
|
|
62
|
+
"$operationsNote": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"description": "Where the operations block is mirrored from, and what fails if the two drift."
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
12
|
"source": {
|
|
13
|
-
"libraryVersion": "2.
|
|
13
|
+
"libraryVersion": "2.7.0",
|
|
14
14
|
"files": [
|
|
15
15
|
"core/index.ts",
|
|
16
16
|
"core/open.ts",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"sourceHash": "sha256:c04b9c09e8661f463e2a808ecd45a7c080c236bc7b398efc1b3505a45e245f00"
|
|
25
25
|
},
|
|
26
|
+
"purpose": "Sections that open and close, built on native <details> and <summary>, with single or multiple expansion.",
|
|
26
27
|
"props": [
|
|
27
28
|
{
|
|
28
29
|
"name": "children",
|
|
@@ -53,7 +54,8 @@
|
|
|
53
54
|
"default": true,
|
|
54
55
|
"origin": "derived",
|
|
55
56
|
"description": "Allow the open panel to be closed again. Default true.",
|
|
56
|
-
"descriptionOrigin": "jsdoc"
|
|
57
|
+
"descriptionOrigin": "jsdoc",
|
|
58
|
+
"note": "Whether the last open section can be closed, leaving none open."
|
|
57
59
|
},
|
|
58
60
|
{
|
|
59
61
|
"name": "defaultValue",
|
|
@@ -244,20 +246,55 @@
|
|
|
244
246
|
}
|
|
245
247
|
],
|
|
246
248
|
"accessibility": {
|
|
247
|
-
"supplied": [
|
|
248
|
-
|
|
249
|
+
"supplied": [
|
|
250
|
+
"native <details>/<summary> semantics, so it works before JavaScript loads and is findable by in-page search",
|
|
251
|
+
"Enter and Space toggle the summary, which is focusable by default",
|
|
252
|
+
"the open state is a real DOM attribute rather than a class"
|
|
253
|
+
],
|
|
254
|
+
"required": [
|
|
255
|
+
"summary text that says what is inside, since a collapsed section is judged entirely by its heading",
|
|
256
|
+
"`multiple` where sections are independent — forcing one open at a time hides content a user was reading"
|
|
257
|
+
]
|
|
258
|
+
},
|
|
259
|
+
"composition": {
|
|
260
|
+
"allowedChildren": [
|
|
261
|
+
"AccordionItem"
|
|
262
|
+
],
|
|
263
|
+
"notes": "Items come from children or the `items` array, not both."
|
|
249
264
|
},
|
|
250
|
-
"composition": {},
|
|
251
265
|
"operations": {},
|
|
252
|
-
"intentDomains": [
|
|
253
|
-
|
|
266
|
+
"intentDomains": [
|
|
267
|
+
"ActionIntent"
|
|
268
|
+
],
|
|
269
|
+
"safeMutations": {
|
|
270
|
+
"allowed": [
|
|
271
|
+
"variant",
|
|
272
|
+
"size",
|
|
273
|
+
"icon",
|
|
274
|
+
"iconPosition",
|
|
275
|
+
"collapsible",
|
|
276
|
+
"multiple"
|
|
277
|
+
],
|
|
278
|
+
"forbidden": [
|
|
279
|
+
"value",
|
|
280
|
+
"defaultValue",
|
|
281
|
+
"onValueChange",
|
|
282
|
+
"items",
|
|
283
|
+
"disabled"
|
|
284
|
+
],
|
|
285
|
+
"rationale": "Appearance is safe; which section is open is state, and `items` is the content."
|
|
286
|
+
},
|
|
254
287
|
"examples": [],
|
|
255
288
|
"coverage": {
|
|
256
289
|
"propsTotal": 15,
|
|
257
290
|
"propsDescribed": 12,
|
|
258
291
|
"describedPct": 80,
|
|
259
292
|
"authoredSections": [
|
|
260
|
-
"accessibility"
|
|
293
|
+
"accessibility",
|
|
294
|
+
"composition",
|
|
295
|
+
"intentDomains",
|
|
296
|
+
"purpose",
|
|
297
|
+
"safeMutations"
|
|
261
298
|
]
|
|
262
299
|
}
|
|
263
300
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../../schema/passport-overlay-v1.schema.json",
|
|
3
|
+
"component": "Accordion",
|
|
4
|
+
"purpose": "Sections that open and close, built on native <details> and <summary>, with single or multiple expansion.",
|
|
5
|
+
"intentDomains": [
|
|
6
|
+
"ActionIntent"
|
|
7
|
+
],
|
|
8
|
+
"accessibility": {
|
|
9
|
+
"supplied": [
|
|
10
|
+
"native <details>/<summary> semantics, so it works before JavaScript loads and is findable by in-page search",
|
|
11
|
+
"Enter and Space toggle the summary, which is focusable by default",
|
|
12
|
+
"the open state is a real DOM attribute rather than a class"
|
|
13
|
+
],
|
|
14
|
+
"required": [
|
|
15
|
+
"summary text that says what is inside, since a collapsed section is judged entirely by its heading",
|
|
16
|
+
"`multiple` where sections are independent — forcing one open at a time hides content a user was reading"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
"composition": {
|
|
20
|
+
"allowedChildren": [
|
|
21
|
+
"AccordionItem"
|
|
22
|
+
],
|
|
23
|
+
"notes": "Items come from children or the `items` array, not both."
|
|
24
|
+
},
|
|
25
|
+
"safeMutations": {
|
|
26
|
+
"allowed": [
|
|
27
|
+
"variant",
|
|
28
|
+
"size",
|
|
29
|
+
"icon",
|
|
30
|
+
"iconPosition",
|
|
31
|
+
"collapsible",
|
|
32
|
+
"multiple"
|
|
33
|
+
],
|
|
34
|
+
"forbidden": [
|
|
35
|
+
"value",
|
|
36
|
+
"defaultValue",
|
|
37
|
+
"onValueChange",
|
|
38
|
+
"items",
|
|
39
|
+
"disabled"
|
|
40
|
+
],
|
|
41
|
+
"rationale": "Appearance is safe; which section is open is state, and `items` is the content."
|
|
42
|
+
},
|
|
43
|
+
"propNotes": {
|
|
44
|
+
"collapsible": "Whether the last open section can be closed, leaving none open."
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
]
|
|
9
9
|
},
|
|
10
10
|
"source": {
|
|
11
|
-
"libraryVersion": "2.
|
|
11
|
+
"libraryVersion": "2.7.0",
|
|
12
12
|
"files": [
|
|
13
13
|
"core/index.ts",
|
|
14
14
|
"core/live.ts",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
],
|
|
22
22
|
"sourceHash": "sha256:1d3329cee22213d4fb81062f401b481902600b2a2b3a81edf12c6738934f6923"
|
|
23
23
|
},
|
|
24
|
+
"purpose": "A message that stays in the page — neither interrupting like a dialog nor leaving like a toast. For conditions the user needs to keep seeing.",
|
|
24
25
|
"props": [
|
|
25
26
|
{
|
|
26
27
|
"name": "actions",
|
|
@@ -178,7 +179,8 @@
|
|
|
178
179
|
"default": "info",
|
|
179
180
|
"origin": "derived",
|
|
180
181
|
"description": "Default `info`.",
|
|
181
|
-
"descriptionOrigin": "jsdoc"
|
|
182
|
+
"descriptionOrigin": "jsdoc",
|
|
183
|
+
"note": "Decides the role: error and warning are announced, info and success are not."
|
|
182
184
|
}
|
|
183
185
|
],
|
|
184
186
|
"inherits": [
|
|
@@ -231,20 +233,51 @@
|
|
|
231
233
|
}
|
|
232
234
|
],
|
|
233
235
|
"accessibility": {
|
|
234
|
-
"supplied": [
|
|
235
|
-
|
|
236
|
+
"supplied": [
|
|
237
|
+
"role=alert on the error and warning variants, so they are announced when they appear",
|
|
238
|
+
"the variant is carried in text and icon, not by colour alone",
|
|
239
|
+
"the dismiss control is a real button with an accessible name"
|
|
240
|
+
],
|
|
241
|
+
"required": [
|
|
242
|
+
"a message that says what to do, not only what went wrong",
|
|
243
|
+
"do not use `onDismiss` for something the user must act on — a dismissible error can be dismissed unread"
|
|
244
|
+
]
|
|
245
|
+
},
|
|
246
|
+
"composition": {
|
|
247
|
+
"mustNotContain": [
|
|
248
|
+
"Alert"
|
|
249
|
+
],
|
|
250
|
+
"notes": "Actions belong in `actions`, which keeps them in the alert's landmark rather than loose in the body."
|
|
236
251
|
},
|
|
237
|
-
"composition": {},
|
|
238
252
|
"operations": {},
|
|
239
|
-
"intentDomains": [
|
|
240
|
-
|
|
253
|
+
"intentDomains": [
|
|
254
|
+
"Summarization"
|
|
255
|
+
],
|
|
256
|
+
"safeMutations": {
|
|
257
|
+
"allowed": [
|
|
258
|
+
"size",
|
|
259
|
+
"icon",
|
|
260
|
+
"description"
|
|
261
|
+
],
|
|
262
|
+
"forbidden": [
|
|
263
|
+
"variant",
|
|
264
|
+
"children",
|
|
265
|
+
"actions",
|
|
266
|
+
"onDismiss"
|
|
267
|
+
],
|
|
268
|
+
"rationale": "`variant` is the severity. Downgrading an error to info changes what the page is telling the user, and it changes whether it is announced at all."
|
|
269
|
+
},
|
|
241
270
|
"examples": [],
|
|
242
271
|
"coverage": {
|
|
243
272
|
"propsTotal": 8,
|
|
244
273
|
"propsDescribed": 6,
|
|
245
274
|
"describedPct": 75,
|
|
246
275
|
"authoredSections": [
|
|
247
|
-
"accessibility"
|
|
276
|
+
"accessibility",
|
|
277
|
+
"composition",
|
|
278
|
+
"intentDomains",
|
|
279
|
+
"purpose",
|
|
280
|
+
"safeMutations"
|
|
248
281
|
]
|
|
249
282
|
}
|
|
250
283
|
}
|