@claude-collective/cli 0.13.4 → 0.25.1

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.
Files changed (314) hide show
  1. package/CHANGELOG.md +357 -0
  2. package/README.md +41 -27
  3. package/config/skills-matrix.yaml +202 -134
  4. package/config/stacks.yaml +14 -20
  5. package/dist/chunk-3X5D7RM5.js +69 -0
  6. package/dist/chunk-3X5D7RM5.js.map +1 -0
  7. package/dist/chunk-4S4FCAA2.js +100 -0
  8. package/dist/chunk-4S4FCAA2.js.map +1 -0
  9. package/dist/chunk-4WGN6SUE.js +197 -0
  10. package/dist/chunk-4WGN6SUE.js.map +1 -0
  11. package/dist/{chunk-DHET7RCE.js → chunk-AWKZ5BDL.js} +9 -2
  12. package/dist/{chunk-DHET7RCE.js.map → chunk-AWKZ5BDL.js.map} +1 -1
  13. package/dist/{chunk-6Q3Y7KVB.js → chunk-DBRUQQUF.js} +8 -2
  14. package/dist/chunk-DBRUQQUF.js.map +1 -0
  15. package/dist/{chunk-Z7G4B5HJ.js → chunk-ETCVEV3S.js} +73 -150
  16. package/dist/chunk-ETCVEV3S.js.map +1 -0
  17. package/dist/chunk-F4RD5FYM.js +45 -0
  18. package/dist/chunk-F4RD5FYM.js.map +1 -0
  19. package/dist/{chunk-ACNBKXXJ.js → chunk-GGFOD5PK.js} +13 -44
  20. package/dist/chunk-GGFOD5PK.js.map +1 -0
  21. package/dist/chunk-H7SSBSPR.js +29 -0
  22. package/dist/chunk-H7SSBSPR.js.map +1 -0
  23. package/dist/chunk-HWD32NP7.js +19 -0
  24. package/dist/chunk-HWD32NP7.js.map +1 -0
  25. package/dist/{chunk-JIPWV2FX.js → chunk-IAYAE6MG.js} +12 -34
  26. package/dist/chunk-IAYAE6MG.js.map +1 -0
  27. package/dist/{chunk-RTE64SJA.js → chunk-IXBCRT3F.js} +2 -2
  28. package/dist/chunk-IXBCRT3F.js.map +1 -0
  29. package/dist/chunk-KWYO3M5Q.js +67 -0
  30. package/dist/chunk-KWYO3M5Q.js.map +1 -0
  31. package/dist/{chunk-E3FJH4TF.js → chunk-MCTSHLAF.js} +18 -18
  32. package/dist/chunk-MCTSHLAF.js.map +1 -0
  33. package/dist/chunk-MH66WDFV.js +251 -0
  34. package/dist/chunk-MH66WDFV.js.map +1 -0
  35. package/dist/{chunk-K3NB6DSG.js → chunk-MTPM7BX5.js} +108 -110
  36. package/dist/chunk-MTPM7BX5.js.map +1 -0
  37. package/dist/chunk-NQJ47R4N.js +1092 -0
  38. package/dist/chunk-NQJ47R4N.js.map +1 -0
  39. package/dist/chunk-NRC7XYCI.js +211 -0
  40. package/dist/chunk-NRC7XYCI.js.map +1 -0
  41. package/dist/{chunk-76DWXGQE.js → chunk-O6ZTD7ZI.js} +14 -3
  42. package/dist/chunk-O6ZTD7ZI.js.map +1 -0
  43. package/dist/chunk-OBXAY23Y.js +56 -0
  44. package/dist/chunk-OBXAY23Y.js.map +1 -0
  45. package/dist/{chunk-XY3XDVMI.js → chunk-QR2EBWL2.js} +3 -3
  46. package/dist/{chunk-66UDJBF6.js → chunk-REJGRCVQ.js} +2 -2
  47. package/dist/{chunk-D237EVNB.js → chunk-TMED5DQ2.js} +71 -48
  48. package/dist/chunk-TMED5DQ2.js.map +1 -0
  49. package/dist/chunk-U7HFKR74.js +21 -0
  50. package/dist/chunk-U7HFKR74.js.map +1 -0
  51. package/dist/chunk-UEMRJI2K.js +146 -0
  52. package/dist/chunk-UEMRJI2K.js.map +1 -0
  53. package/dist/{chunk-Z2CWURZ6.js → chunk-UNN7523L.js} +2 -2
  54. package/dist/chunk-V2ZIH7HV.js +29 -0
  55. package/dist/chunk-V2ZIH7HV.js.map +1 -0
  56. package/dist/{chunk-X6QONICW.js → chunk-VVYNZZUX.js} +7 -19
  57. package/dist/chunk-VVYNZZUX.js.map +1 -0
  58. package/dist/chunk-WXS4S3MA.js +220 -0
  59. package/dist/chunk-WXS4S3MA.js.map +1 -0
  60. package/dist/{chunk-CDX4W4DM.js → chunk-XENOESJZ.js} +53 -33
  61. package/dist/chunk-XENOESJZ.js.map +1 -0
  62. package/dist/chunk-YDBSSAJ6.js +4207 -0
  63. package/dist/chunk-YDBSSAJ6.js.map +1 -0
  64. package/dist/chunk-ZDREFYD2.js +696 -0
  65. package/dist/chunk-ZDREFYD2.js.map +1 -0
  66. package/dist/chunk-ZW2PELOH.js +197 -0
  67. package/dist/chunk-ZW2PELOH.js.map +1 -0
  68. package/dist/cli/defaults/agent-mappings.yaml +13 -14
  69. package/dist/commands/build/marketplace.js +19 -23
  70. package/dist/commands/build/marketplace.js.map +1 -1
  71. package/dist/commands/build/plugins.js +13 -240
  72. package/dist/commands/build/plugins.js.map +1 -1
  73. package/dist/commands/build/stack.js +13 -25
  74. package/dist/commands/build/stack.js.map +1 -1
  75. package/dist/commands/compile.js +45 -82
  76. package/dist/commands/compile.js.map +1 -1
  77. package/dist/commands/config/get.js +9 -9
  78. package/dist/commands/config/get.js.map +1 -1
  79. package/dist/commands/config/index.js +8 -8
  80. package/dist/commands/config/index.js.map +1 -1
  81. package/dist/commands/config/path.js +7 -9
  82. package/dist/commands/config/path.js.map +1 -1
  83. package/dist/commands/config/set-project.js +12 -13
  84. package/dist/commands/config/set-project.js.map +1 -1
  85. package/dist/commands/config/show.js +7 -7
  86. package/dist/commands/config/unset-project.js +12 -13
  87. package/dist/commands/config/unset-project.js.map +1 -1
  88. package/dist/commands/diff.js +15 -44
  89. package/dist/commands/diff.js.map +1 -1
  90. package/dist/commands/doctor.js +23 -67
  91. package/dist/commands/doctor.js.map +1 -1
  92. package/dist/commands/edit.js +98 -81
  93. package/dist/commands/edit.js.map +1 -1
  94. package/dist/commands/eject.js +27 -79
  95. package/dist/commands/eject.js.map +1 -1
  96. package/dist/commands/import/skill.js +38 -58
  97. package/dist/commands/import/skill.js.map +1 -1
  98. package/dist/commands/info.js +17 -24
  99. package/dist/commands/info.js.map +1 -1
  100. package/dist/commands/init.js +103 -779
  101. package/dist/commands/init.js.map +1 -1
  102. package/dist/commands/list.js +8 -11
  103. package/dist/commands/list.js.map +1 -1
  104. package/dist/commands/new/agent.js +11 -16
  105. package/dist/commands/new/agent.js.map +1 -1
  106. package/dist/commands/new/skill.js +14 -18
  107. package/dist/commands/new/skill.js.map +1 -1
  108. package/dist/commands/outdated.js +16 -97
  109. package/dist/commands/outdated.js.map +1 -1
  110. package/dist/commands/search.js +24 -43
  111. package/dist/commands/search.js.map +1 -1
  112. package/dist/commands/uninstall.js +22 -30
  113. package/dist/commands/uninstall.js.map +1 -1
  114. package/dist/commands/update.js +23 -154
  115. package/dist/commands/update.js.map +1 -1
  116. package/dist/commands/validate.js +38 -89
  117. package/dist/commands/validate.js.map +1 -1
  118. package/dist/commands/version/bump.js +12 -28
  119. package/dist/commands/version/bump.js.map +1 -1
  120. package/dist/commands/version/index.js +8 -24
  121. package/dist/commands/version/index.js.map +1 -1
  122. package/dist/commands/version/set.js +11 -26
  123. package/dist/commands/version/set.js.map +1 -1
  124. package/dist/commands/version/show.js +8 -24
  125. package/dist/commands/version/show.js.map +1 -1
  126. package/dist/components/common/confirm.js +2 -2
  127. package/dist/components/common/confirm.test.js +203 -0
  128. package/dist/components/common/confirm.test.js.map +1 -0
  129. package/dist/components/common/message.js +3 -7
  130. package/dist/components/common/message.js.map +1 -1
  131. package/dist/components/common/spinner.js +1 -1
  132. package/dist/components/common/spinner.js.map +1 -1
  133. package/dist/components/skill-search/skill-search.js +3 -3
  134. package/dist/components/wizard/category-grid.js +2 -2
  135. package/dist/components/wizard/category-grid.test.js +138 -156
  136. package/dist/components/wizard/category-grid.test.js.map +1 -1
  137. package/dist/components/wizard/menu-item.js +9 -0
  138. package/dist/components/wizard/search-modal.js +9 -0
  139. package/dist/components/wizard/search-modal.test.js +216 -0
  140. package/dist/components/wizard/search-modal.test.js.map +1 -0
  141. package/dist/components/wizard/section-progress.js +2 -2
  142. package/dist/components/wizard/section-progress.test.js +16 -106
  143. package/dist/components/wizard/section-progress.test.js.map +1 -1
  144. package/dist/components/wizard/source-grid.js +10 -0
  145. package/dist/components/wizard/source-grid.js.map +1 -0
  146. package/dist/components/wizard/source-grid.test.js +500 -0
  147. package/dist/components/wizard/source-grid.test.js.map +1 -0
  148. package/dist/components/wizard/step-approach.js +7 -5
  149. package/dist/components/wizard/step-approach.test.js +115 -0
  150. package/dist/components/wizard/step-approach.test.js.map +1 -0
  151. package/dist/components/wizard/step-build.js +9 -5
  152. package/dist/components/wizard/step-build.test.js +160 -284
  153. package/dist/components/wizard/step-build.test.js.map +1 -1
  154. package/dist/components/wizard/step-confirm.js +3 -3
  155. package/dist/components/wizard/step-confirm.test.js +364 -0
  156. package/dist/components/wizard/step-confirm.test.js.map +1 -0
  157. package/dist/components/wizard/step-refine.js +2 -3
  158. package/dist/components/wizard/step-refine.test.js +24 -26
  159. package/dist/components/wizard/step-refine.test.js.map +1 -1
  160. package/dist/components/wizard/step-settings.js +14 -0
  161. package/dist/components/wizard/step-settings.js.map +1 -0
  162. package/dist/components/wizard/step-settings.test.js +240 -0
  163. package/dist/components/wizard/step-settings.test.js.map +1 -0
  164. package/dist/components/wizard/step-sources.js +17 -0
  165. package/dist/components/wizard/step-sources.js.map +1 -0
  166. package/dist/components/wizard/step-sources.test.js +290 -0
  167. package/dist/components/wizard/step-sources.test.js.map +1 -0
  168. package/dist/components/wizard/step-stack.js +7 -4
  169. package/dist/components/wizard/step-stack.test.js +344 -0
  170. package/dist/components/wizard/step-stack.test.js.map +1 -0
  171. package/dist/components/wizard/view-title.js +9 -0
  172. package/dist/components/wizard/view-title.js.map +1 -0
  173. package/dist/components/wizard/wizard-layout.js +17 -0
  174. package/dist/components/wizard/wizard-layout.js.map +1 -0
  175. package/dist/components/wizard/wizard-tabs.js +2 -2
  176. package/dist/components/wizard/wizard-tabs.test.js +292 -0
  177. package/dist/components/wizard/wizard-tabs.test.js.map +1 -0
  178. package/dist/components/wizard/wizard.js +22 -15
  179. package/dist/config/skills-matrix.yaml +202 -134
  180. package/dist/config/stacks.yaml +14 -20
  181. package/dist/hooks/init.js +6 -8
  182. package/dist/hooks/init.js.map +1 -1
  183. package/dist/index.js +1 -1
  184. package/dist/index.js.map +1 -1
  185. package/dist/{magic-string.es-RGXYGAW3.js → magic-string.es-PAH2SOTR.js} +2 -2
  186. package/dist/source-manager-DSYZEVGZ.js +16 -0
  187. package/dist/source-manager-DSYZEVGZ.js.map +1 -0
  188. package/dist/src/agents/developer/api-developer/agent.yaml +1 -1
  189. package/dist/src/agents/developer/cli-developer/agent.yaml +1 -1
  190. package/dist/src/agents/developer/web-architecture/agent.yaml +1 -1
  191. package/dist/src/agents/developer/web-developer/agent.yaml +1 -1
  192. package/dist/src/agents/developer/web-developer/examples.md +1 -6
  193. package/dist/src/agents/meta/agent-summoner/agent.yaml +1 -1
  194. package/dist/src/agents/meta/documentor/agent.yaml +1 -1
  195. package/dist/src/agents/meta/documentor/workflow.md +1 -5
  196. package/dist/src/agents/meta/skill-summoner/agent.yaml +1 -1
  197. package/dist/src/agents/migration/cli-migrator/agent.yaml +1 -1
  198. package/dist/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
  199. package/dist/src/agents/pattern/pattern-scout/agent.yaml +1 -1
  200. package/dist/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
  201. package/dist/src/agents/planning/web-pm/agent.yaml +1 -1
  202. package/dist/src/agents/researcher/api-researcher/agent.yaml +1 -1
  203. package/dist/src/agents/researcher/web-researcher/agent.yaml +1 -1
  204. package/dist/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
  205. package/dist/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
  206. package/dist/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
  207. package/dist/src/agents/tester/cli-tester/agent.yaml +1 -1
  208. package/dist/src/agents/tester/web-tester/agent.yaml +1 -1
  209. package/dist/src/agents/tester/web-tester/output-format.md +1 -3
  210. package/dist/stores/wizard-store.js +4 -3
  211. package/dist/stores/wizard-store.test.js +94 -88
  212. package/dist/stores/wizard-store.test.js.map +1 -1
  213. package/package.json +5 -3
  214. package/src/agents/developer/api-developer/agent.yaml +1 -1
  215. package/src/agents/developer/cli-developer/agent.yaml +1 -1
  216. package/src/agents/developer/web-architecture/agent.yaml +1 -1
  217. package/src/agents/developer/web-developer/agent.yaml +1 -1
  218. package/src/agents/developer/web-developer/examples.md +1 -6
  219. package/src/agents/meta/agent-summoner/agent.yaml +1 -1
  220. package/src/agents/meta/documentor/agent.yaml +1 -1
  221. package/src/agents/meta/documentor/workflow.md +1 -5
  222. package/src/agents/meta/skill-summoner/agent.yaml +1 -1
  223. package/src/agents/migration/cli-migrator/agent.yaml +1 -1
  224. package/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
  225. package/src/agents/pattern/pattern-scout/agent.yaml +1 -1
  226. package/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
  227. package/src/agents/planning/web-pm/agent.yaml +1 -1
  228. package/src/agents/researcher/api-researcher/agent.yaml +1 -1
  229. package/src/agents/researcher/web-researcher/agent.yaml +1 -1
  230. package/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
  231. package/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
  232. package/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
  233. package/src/agents/tester/cli-tester/agent.yaml +1 -1
  234. package/src/agents/tester/web-tester/agent.yaml +1 -1
  235. package/src/agents/tester/web-tester/output-format.md +1 -3
  236. package/dist/chunk-3U3R4NCG.js +0 -22
  237. package/dist/chunk-3U3R4NCG.js.map +0 -1
  238. package/dist/chunk-4K4ZXQRM.js +0 -317
  239. package/dist/chunk-4K4ZXQRM.js.map +0 -1
  240. package/dist/chunk-6Q3Y7KVB.js.map +0 -1
  241. package/dist/chunk-76DWXGQE.js.map +0 -1
  242. package/dist/chunk-7Q44DMSP.js +0 -582
  243. package/dist/chunk-7Q44DMSP.js.map +0 -1
  244. package/dist/chunk-ACNBKXXJ.js.map +0 -1
  245. package/dist/chunk-B7CCVP6Q.js +0 -639
  246. package/dist/chunk-B7CCVP6Q.js.map +0 -1
  247. package/dist/chunk-BDLUZVKU.js +0 -54
  248. package/dist/chunk-BDLUZVKU.js.map +0 -1
  249. package/dist/chunk-CDX4W4DM.js.map +0 -1
  250. package/dist/chunk-D237EVNB.js.map +0 -1
  251. package/dist/chunk-DRXPNNPB.js +0 -393
  252. package/dist/chunk-DRXPNNPB.js.map +0 -1
  253. package/dist/chunk-E3FJH4TF.js.map +0 -1
  254. package/dist/chunk-ED4E6Q2T.js +0 -114
  255. package/dist/chunk-ED4E6Q2T.js.map +0 -1
  256. package/dist/chunk-EHS3TWWP.js +0 -95
  257. package/dist/chunk-EHS3TWWP.js.map +0 -1
  258. package/dist/chunk-GDH553MV.js +0 -91
  259. package/dist/chunk-GDH553MV.js.map +0 -1
  260. package/dist/chunk-HLJX2FTL.js +0 -95
  261. package/dist/chunk-HLJX2FTL.js.map +0 -1
  262. package/dist/chunk-I2DSLOXZ.js +0 -75
  263. package/dist/chunk-I2DSLOXZ.js.map +0 -1
  264. package/dist/chunk-I4TPKIYX.js +0 -493
  265. package/dist/chunk-I4TPKIYX.js.map +0 -1
  266. package/dist/chunk-IAUAQJQ2.js +0 -57
  267. package/dist/chunk-IAUAQJQ2.js.map +0 -1
  268. package/dist/chunk-IBE7JIAG.js +0 -129
  269. package/dist/chunk-IBE7JIAG.js.map +0 -1
  270. package/dist/chunk-IMDW5ZUP.js +0 -132
  271. package/dist/chunk-IMDW5ZUP.js.map +0 -1
  272. package/dist/chunk-JIPWV2FX.js.map +0 -1
  273. package/dist/chunk-K3NB6DSG.js.map +0 -1
  274. package/dist/chunk-K7EVM5LY.js +0 -141
  275. package/dist/chunk-K7EVM5LY.js.map +0 -1
  276. package/dist/chunk-KAAEN2PO.js +0 -57
  277. package/dist/chunk-KAAEN2PO.js.map +0 -1
  278. package/dist/chunk-NDY25DTL.js +0 -453
  279. package/dist/chunk-NDY25DTL.js.map +0 -1
  280. package/dist/chunk-P26A2K5N.js +0 -64
  281. package/dist/chunk-P26A2K5N.js.map +0 -1
  282. package/dist/chunk-RFTSZDHV.js +0 -313
  283. package/dist/chunk-RFTSZDHV.js.map +0 -1
  284. package/dist/chunk-RTE64SJA.js.map +0 -1
  285. package/dist/chunk-SVYPSDWY.js +0 -84
  286. package/dist/chunk-SVYPSDWY.js.map +0 -1
  287. package/dist/chunk-TKFPKEV3.js +0 -69
  288. package/dist/chunk-TKFPKEV3.js.map +0 -1
  289. package/dist/chunk-UQTEPWU7.js +0 -108
  290. package/dist/chunk-UQTEPWU7.js.map +0 -1
  291. package/dist/chunk-V46GGCCI.js +0 -294
  292. package/dist/chunk-V46GGCCI.js.map +0 -1
  293. package/dist/chunk-X6QONICW.js.map +0 -1
  294. package/dist/chunk-Y2LW7R3Y.js +0 -23
  295. package/dist/chunk-Y2LW7R3Y.js.map +0 -1
  296. package/dist/chunk-Z7G4B5HJ.js.map +0 -1
  297. package/dist/chunk-ZENYS6KW.js +0 -90
  298. package/dist/chunk-ZENYS6KW.js.map +0 -1
  299. package/dist/chunk-ZFPSUQOU.js +0 -396
  300. package/dist/chunk-ZFPSUQOU.js.map +0 -1
  301. package/dist/commands/config/set.js +0 -61
  302. package/dist/commands/config/set.js.map +0 -1
  303. package/dist/commands/config/unset.js +0 -57
  304. package/dist/commands/config/unset.js.map +0 -1
  305. package/dist/commands/test-imports.js +0 -92
  306. package/dist/commands/test-imports.js.map +0 -1
  307. package/dist/components/wizard/step-stack-options.js +0 -11
  308. package/dist/components/wizard/wizard-footer.js +0 -9
  309. /package/dist/{chunk-XY3XDVMI.js.map → chunk-QR2EBWL2.js.map} +0 -0
  310. /package/dist/{chunk-66UDJBF6.js.map → chunk-REJGRCVQ.js.map} +0 -0
  311. /package/dist/{chunk-Z2CWURZ6.js.map → chunk-UNN7523L.js.map} +0 -0
  312. /package/dist/components/wizard/{step-stack-options.js.map → menu-item.js.map} +0 -0
  313. /package/dist/components/wizard/{wizard-footer.js.map → search-modal.js.map} +0 -0
  314. /package/dist/{magic-string.es-RGXYGAW3.js.map → magic-string.es-PAH2SOTR.js.map} +0 -0
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getDomainDisplayName
4
+ } from "./chunk-V2ZIH7HV.js";
5
+ import {
6
+ ViewTitle
7
+ } from "./chunk-U7HFKR74.js";
8
+ import {
9
+ CategoryGrid
10
+ } from "./chunk-ETCVEV3S.js";
11
+ import {
12
+ getAvailableSkills,
13
+ resolveAlias
14
+ } from "./chunk-YDBSSAJ6.js";
15
+ import {
16
+ init_esm_shims
17
+ } from "./chunk-AWKZ5BDL.js";
18
+
19
+ // src/cli/components/wizard/step-build.tsx
20
+ init_esm_shims();
21
+ import { useState } from "react";
22
+ import { Box, Text, useInput } from "ink";
23
+ import { sortBy } from "remeda";
24
+ import { jsx, jsxs } from "react/jsx-runtime";
25
+ var FRAMEWORK_SUBCATEGORY_ID = "framework";
26
+ var WEB_DOMAIN_ID = "web";
27
+ function validateBuildStep(categories, selections) {
28
+ for (const category of categories) {
29
+ if (category.required) {
30
+ const categorySelections = selections[category.id] || [];
31
+ if (categorySelections.length === 0) {
32
+ return {
33
+ valid: false,
34
+ message: `Please select a ${category.displayName}`
35
+ };
36
+ }
37
+ }
38
+ }
39
+ return { valid: true };
40
+ }
41
+ function computeOptionState(skill) {
42
+ if (skill.disabled) {
43
+ return "disabled";
44
+ }
45
+ if (skill.discouraged) {
46
+ return "discouraged";
47
+ }
48
+ if (skill.recommended) {
49
+ return "recommended";
50
+ }
51
+ return "normal";
52
+ }
53
+ function getDisplayLabel(skill) {
54
+ return skill.displayName || skill.id;
55
+ }
56
+ function getStateReason(skill) {
57
+ if (skill.disabled && skill.disabledReason) {
58
+ return skill.disabledReason;
59
+ }
60
+ if (skill.discouraged && skill.discouragedReason) {
61
+ return skill.discouragedReason;
62
+ }
63
+ if (skill.recommended && skill.recommendedReason) {
64
+ return skill.recommendedReason;
65
+ }
66
+ return void 0;
67
+ }
68
+ function isFrameworkSelected(selections) {
69
+ const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];
70
+ return frameworkSelections.length > 0;
71
+ }
72
+ function getSelectedFrameworks(selections, matrix) {
73
+ const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];
74
+ return frameworkSelections.map((alias) => resolveAlias(alias, matrix));
75
+ }
76
+ function isCompatibleWithSelectedFrameworks(skillId, selectedFrameworkIds, matrix) {
77
+ const skill = matrix.skills[skillId];
78
+ if (!skill) return false;
79
+ if (skill.compatibleWith.length === 0) {
80
+ return true;
81
+ }
82
+ return selectedFrameworkIds.some((frameworkId) => skill.compatibleWith.includes(frameworkId));
83
+ }
84
+ function buildCategoriesForDomain(domain, allSelections, matrix, expertMode, selections, parentDomainSelections, installedSkillIds) {
85
+ const frameworkSource = parentDomainSelections ?? selections;
86
+ const frameworkSelected = isFrameworkSelected(frameworkSource);
87
+ const selectedFrameworkIds = frameworkSelected ? getSelectedFrameworks(frameworkSource, matrix) : [];
88
+ const subcategories = sortBy(
89
+ Object.values(matrix.categories).filter((cat) => cat.domain === domain),
90
+ (cat) => cat.order ?? 0
91
+ );
92
+ const categoryRows = subcategories.map((cat) => {
93
+ const skillOptions = getAvailableSkills(cat.id, allSelections, matrix, {
94
+ expertMode
95
+ });
96
+ const useFrameworkFilter = (domain === WEB_DOMAIN_ID || parentDomainSelections !== void 0) && cat.id !== FRAMEWORK_SUBCATEGORY_ID && frameworkSelected;
97
+ const filteredSkillOptions = useFrameworkFilter ? skillOptions.filter(
98
+ (skill) => isCompatibleWithSelectedFrameworks(skill.id, selectedFrameworkIds, matrix)
99
+ ) : skillOptions;
100
+ const options = filteredSkillOptions.map((skill) => ({
101
+ id: skill.id,
102
+ label: getDisplayLabel(skill),
103
+ state: computeOptionState(skill),
104
+ stateReason: getStateReason(skill),
105
+ selected: skill.selected,
106
+ local: matrix.skills[skill.id]?.local,
107
+ installed: installedSkillIds?.includes(skill.id) || false
108
+ }));
109
+ return {
110
+ id: cat.id,
111
+ displayName: cat.displayName,
112
+ required: cat.required ?? false,
113
+ exclusive: cat.exclusive ?? true,
114
+ options
115
+ };
116
+ });
117
+ return categoryRows.filter((row) => row.options.length > 0);
118
+ }
119
+ var Footer = ({ validationError }) => {
120
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: validationError && /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: validationError }) }) });
121
+ };
122
+ var LegendRow = () => {
123
+ return /* @__PURE__ */ jsxs(Box, { paddingLeft: 1, columnGap: 2, children: [
124
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "active" }),
125
+ /* @__PURE__ */ jsx(Text, { color: "#fff", children: "recommended" }),
126
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: "discouraged" }),
127
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "disabled" })
128
+ ] });
129
+ };
130
+ var StepBuild = ({
131
+ matrix,
132
+ domain: activeDomain,
133
+ selectedDomains,
134
+ selections,
135
+ allSelections,
136
+ focusedRow,
137
+ focusedCol,
138
+ showDescriptions,
139
+ expertMode,
140
+ parentDomainSelections,
141
+ installedSkillIds,
142
+ onToggle,
143
+ onFocusChange,
144
+ onToggleDescriptions,
145
+ onContinue,
146
+ onBack
147
+ }) => {
148
+ const [validationError, setValidationError] = useState(void 0);
149
+ const categories = buildCategoriesForDomain(
150
+ activeDomain,
151
+ allSelections,
152
+ matrix,
153
+ expertMode,
154
+ selections,
155
+ parentDomainSelections,
156
+ installedSkillIds
157
+ );
158
+ useInput((_input, key) => {
159
+ if (key.return) {
160
+ const validation = validateBuildStep(categories, selections);
161
+ if (validation.valid) {
162
+ setValidationError(void 0);
163
+ onContinue();
164
+ } else {
165
+ setValidationError(validation.message);
166
+ }
167
+ } else if (key.escape) {
168
+ setValidationError(void 0);
169
+ onBack();
170
+ }
171
+ });
172
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "100%", children: [
173
+ /* @__PURE__ */ jsxs(
174
+ Box,
175
+ {
176
+ columnGap: 2,
177
+ flexDirection: "row",
178
+ justifyContent: "space-between",
179
+ marginBottom: 1,
180
+ paddingRight: 1,
181
+ marginTop: -1,
182
+ borderTop: false,
183
+ borderRight: false,
184
+ borderLeft: false,
185
+ borderColor: "gray",
186
+ borderStyle: "single",
187
+ children: [
188
+ /* @__PURE__ */ jsx(Box, { columnGap: 2, flexDirection: "row", children: selectedDomains.map((domain) => /* @__PURE__ */ jsx(Text, { color: domain === activeDomain ? "cyan" : void 0, children: getDomainDisplayName(domain) }, domain)) }),
189
+ /* @__PURE__ */ jsx(LegendRow, {})
190
+ ]
191
+ }
192
+ ),
193
+ /* @__PURE__ */ jsxs(ViewTitle, { children: [
194
+ "Customise your ",
195
+ getDomainDisplayName(activeDomain),
196
+ " stack"
197
+ ] }),
198
+ /* @__PURE__ */ jsx(
199
+ CategoryGrid,
200
+ {
201
+ categories,
202
+ focusedRow,
203
+ focusedCol,
204
+ expertMode,
205
+ showDescriptions,
206
+ onToggle,
207
+ onFocusChange,
208
+ onToggleDescriptions
209
+ }
210
+ ),
211
+ /* @__PURE__ */ jsx(Footer, { validationError })
212
+ ] });
213
+ };
214
+
215
+ export {
216
+ validateBuildStep,
217
+ getDisplayLabel,
218
+ StepBuild
219
+ };
220
+ //# sourceMappingURL=chunk-WXS4S3MA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/step-build.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { sortBy } from \"remeda\";\nimport type {\n Domain,\n MergedSkillsMatrix,\n SkillId,\n Subcategory,\n SubcategorySelections,\n} from \"../../types/index.js\";\nimport { getAvailableSkills, resolveAlias } from \"../../lib/matrix/index.js\";\nimport {\n CategoryGrid,\n type CategoryRow,\n type CategoryOption,\n type OptionState,\n} from \"./category-grid.js\";\nimport { ViewTitle } from \"./view-title.js\";\nimport { getDomainDisplayName } from \"./utils.js\";\n\nexport type StepBuildProps = {\n matrix: MergedSkillsMatrix;\n domain: Domain;\n selectedDomains: Domain[];\n selections: SubcategorySelections;\n allSelections: SkillId[];\n focusedRow: number;\n focusedCol: number;\n showDescriptions: boolean;\n expertMode: boolean;\n /** For framework-first filtering on sub-domains (e.g., web-extras inherits from web) */\n parentDomainSelections?: SubcategorySelections;\n /** Skill IDs already installed on disk, shown with a dimmed checkmark */\n installedSkillIds?: SkillId[];\n onToggle: (subcategoryId: Subcategory, technologyId: SkillId) => void;\n onFocusChange: (row: number, col: number) => void;\n onToggleDescriptions: () => void;\n onContinue: () => void;\n onBack: () => void;\n};\n\nconst FRAMEWORK_SUBCATEGORY_ID = \"framework\";\nconst WEB_DOMAIN_ID = \"web\";\n\nexport type BuildStepValidation = {\n valid: boolean;\n message?: string;\n};\n\nexport function validateBuildStep(\n categories: CategoryRow[],\n selections: SubcategorySelections,\n): BuildStepValidation {\n for (const category of categories) {\n if (category.required) {\n const categorySelections = selections[category.id] || [];\n if (categorySelections.length === 0) {\n return {\n valid: false,\n message: `Please select a ${category.displayName}`,\n };\n }\n }\n }\n return { valid: true };\n}\n\nfunction computeOptionState(skill: {\n disabled: boolean;\n discouraged: boolean;\n recommended: boolean;\n}): OptionState {\n if (skill.disabled) {\n return \"disabled\";\n }\n if (skill.discouraged) {\n return \"discouraged\";\n }\n if (skill.recommended) {\n return \"recommended\";\n }\n return \"normal\";\n}\n\nexport function getDisplayLabel(skill: { displayName?: string; id: string }): string {\n return skill.displayName || skill.id;\n}\n\nfunction getStateReason(skill: {\n disabled: boolean;\n disabledReason?: string;\n discouraged: boolean;\n discouragedReason?: string;\n recommended: boolean;\n recommendedReason?: string;\n}): string | undefined {\n if (skill.disabled && skill.disabledReason) {\n return skill.disabledReason;\n }\n if (skill.discouraged && skill.discouragedReason) {\n return skill.discouragedReason;\n }\n if (skill.recommended && skill.recommendedReason) {\n return skill.recommendedReason;\n }\n return undefined;\n}\n\nfunction isFrameworkSelected(selections: SubcategorySelections): boolean {\n const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];\n return frameworkSelections.length > 0;\n}\n\nfunction getSelectedFrameworks(\n selections: SubcategorySelections,\n matrix: MergedSkillsMatrix,\n): SkillId[] {\n const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];\n // Resolve aliases to full skill IDs\n return frameworkSelections.map((alias) => resolveAlias(alias, matrix));\n}\n\nfunction isCompatibleWithSelectedFrameworks(\n skillId: SkillId,\n selectedFrameworkIds: SkillId[],\n matrix: MergedSkillsMatrix,\n): boolean {\n const skill = matrix.skills[skillId];\n if (!skill) return false;\n\n // No compatibleWith = compatible with all (allows legacy skills to appear)\n if (skill.compatibleWith.length === 0) {\n return true;\n }\n\n return selectedFrameworkIds.some((frameworkId) => skill.compatibleWith.includes(frameworkId));\n}\n\n// Build CategoryRow[] from matrix for a domain, with framework-first filtering for web\nfunction buildCategoriesForDomain(\n domain: Domain,\n allSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n expertMode: boolean,\n selections: SubcategorySelections,\n parentDomainSelections?: SubcategorySelections,\n installedSkillIds?: SkillId[],\n): CategoryRow[] {\n // For sub-domains (e.g., web-extras), use parent domain selections for framework checks\n const frameworkSource = parentDomainSelections ?? selections;\n const frameworkSelected = isFrameworkSelected(frameworkSource);\n const selectedFrameworkIds = frameworkSelected\n ? getSelectedFrameworks(frameworkSource, matrix)\n : [];\n\n const subcategories = sortBy(\n Object.values(matrix.categories).filter((cat) => cat.domain === domain),\n (cat) => cat.order ?? 0,\n );\n\n // All sections always visible; locking is handled by CategoryGrid\n const categoryRows: CategoryRow[] = subcategories.map((cat) => {\n const skillOptions = getAvailableSkills(cat.id, allSelections, matrix, {\n expertMode,\n });\n\n // Filter by framework compatibility (skip framework category itself)\n const useFrameworkFilter =\n (domain === WEB_DOMAIN_ID || parentDomainSelections !== undefined) &&\n cat.id !== FRAMEWORK_SUBCATEGORY_ID &&\n frameworkSelected;\n const filteredSkillOptions = useFrameworkFilter\n ? skillOptions.filter((skill) =>\n isCompatibleWithSelectedFrameworks(skill.id, selectedFrameworkIds, matrix),\n )\n : skillOptions;\n\n const options: CategoryOption[] = filteredSkillOptions.map((skill) => ({\n id: skill.id,\n label: getDisplayLabel(skill),\n state: computeOptionState(skill),\n stateReason: getStateReason(skill),\n selected: skill.selected,\n local: matrix.skills[skill.id]?.local,\n installed: installedSkillIds?.includes(skill.id) || false,\n }));\n\n return {\n id: cat.id,\n displayName: cat.displayName,\n required: cat.required ?? false,\n exclusive: cat.exclusive ?? true,\n options,\n };\n });\n\n return categoryRows.filter((row) => row.options.length > 0);\n}\n\ntype FooterProps = {\n validationError?: string;\n};\n\nconst Footer: React.FC<FooterProps> = ({ validationError }) => {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {validationError && (\n <Box marginBottom={1}>\n <Text color=\"yellow\">{validationError}</Text>\n </Box>\n )}\n </Box>\n );\n};\n\nconst LegendRow: React.FC = () => {\n return (\n <Box paddingLeft={1} columnGap={2}>\n <Text color=\"cyan\">active</Text>\n <Text color=\"#fff\">recommended</Text>\n <Text color=\"yellow\">discouraged</Text>\n <Text color=\"gray\">disabled</Text>\n </Box>\n );\n};\n\nexport const StepBuild: React.FC<StepBuildProps> = ({\n matrix,\n domain: activeDomain,\n selectedDomains,\n selections,\n allSelections,\n focusedRow,\n focusedCol,\n showDescriptions,\n expertMode,\n parentDomainSelections,\n installedSkillIds,\n onToggle,\n onFocusChange,\n onToggleDescriptions,\n onContinue,\n onBack,\n}) => {\n const [validationError, setValidationError] = useState<string | undefined>(undefined);\n\n const categories = buildCategoriesForDomain(\n activeDomain,\n allSelections,\n matrix,\n expertMode,\n selections,\n parentDomainSelections,\n installedSkillIds,\n );\n\n useInput((_input, key) => {\n if (key.return) {\n const validation = validateBuildStep(categories, selections);\n if (validation.valid) {\n setValidationError(undefined);\n onContinue();\n } else {\n setValidationError(validation.message);\n }\n } else if (key.escape) {\n setValidationError(undefined);\n onBack();\n }\n });\n\n return (\n <Box flexDirection=\"column\" width=\"100%\">\n <Box\n columnGap={2}\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n marginBottom={1}\n paddingRight={1}\n marginTop={-1}\n borderTop={false}\n borderRight={false}\n borderLeft={false}\n borderColor=\"gray\"\n borderStyle=\"single\"\n >\n <Box columnGap={2} flexDirection=\"row\">\n {selectedDomains.map((domain) => (\n <Text key={domain} color={domain === activeDomain ? \"cyan\" : undefined}>\n {getDomainDisplayName(domain)}\n </Text>\n ))}\n </Box>\n <LegendRow />\n </Box>\n <ViewTitle>Customise your {getDomainDisplayName(activeDomain)} stack</ViewTitle>\n\n <CategoryGrid\n categories={categories}\n focusedRow={focusedRow}\n focusedCol={focusedCol}\n expertMode={expertMode}\n showDescriptions={showDescriptions}\n onToggle={onToggle}\n onFocusChange={onFocusChange}\n onToggleDescriptions={onToggleDescriptions}\n />\n\n <Footer validationError={validationError} />\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAgB,gBAAgB;AAChC,SAAS,KAAK,MAAM,gBAAgB;AACpC,SAAS,cAAc;AA8Mb,cASN,YATM;AAvKV,IAAM,2BAA2B;AACjC,IAAM,gBAAgB;AAOf,SAAS,kBACd,YACA,YACqB;AACrB,aAAW,YAAY,YAAY;AACjC,QAAI,SAAS,UAAU;AACrB,YAAM,qBAAqB,WAAW,SAAS,EAAE,KAAK,CAAC;AACvD,UAAI,mBAAmB,WAAW,GAAG;AACnC,eAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS,mBAAmB,SAAS,WAAW;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,OAAO,KAAK;AACvB;AAEA,SAAS,mBAAmB,OAIZ;AACd,MAAI,MAAM,UAAU;AAClB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,aAAa;AACrB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,aAAa;AACrB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAqD;AACnF,SAAO,MAAM,eAAe,MAAM;AACpC;AAEA,SAAS,eAAe,OAOD;AACrB,MAAI,MAAM,YAAY,MAAM,gBAAgB;AAC1C,WAAO,MAAM;AAAA,EACf;AACA,MAAI,MAAM,eAAe,MAAM,mBAAmB;AAChD,WAAO,MAAM;AAAA,EACf;AACA,MAAI,MAAM,eAAe,MAAM,mBAAmB;AAChD,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,YAA4C;AACvE,QAAM,sBAAsB,WAAW,wBAAwB,KAAK,CAAC;AACrE,SAAO,oBAAoB,SAAS;AACtC;AAEA,SAAS,sBACP,YACA,QACW;AACX,QAAM,sBAAsB,WAAW,wBAAwB,KAAK,CAAC;AAErE,SAAO,oBAAoB,IAAI,CAAC,UAAU,aAAa,OAAO,MAAM,CAAC;AACvE;AAEA,SAAS,mCACP,SACA,sBACA,QACS;AACT,QAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,MAAI,CAAC,MAAO,QAAO;AAGnB,MAAI,MAAM,eAAe,WAAW,GAAG;AACrC,WAAO;AAAA,EACT;AAEA,SAAO,qBAAqB,KAAK,CAAC,gBAAgB,MAAM,eAAe,SAAS,WAAW,CAAC;AAC9F;AAGA,SAAS,yBACP,QACA,eACA,QACA,YACA,YACA,wBACA,mBACe;AAEf,QAAM,kBAAkB,0BAA0B;AAClD,QAAM,oBAAoB,oBAAoB,eAAe;AAC7D,QAAM,uBAAuB,oBACzB,sBAAsB,iBAAiB,MAAM,IAC7C,CAAC;AAEL,QAAM,gBAAgB;AAAA,IACpB,OAAO,OAAO,OAAO,UAAU,EAAE,OAAO,CAAC,QAAQ,IAAI,WAAW,MAAM;AAAA,IACtE,CAAC,QAAQ,IAAI,SAAS;AAAA,EACxB;AAGA,QAAM,eAA8B,cAAc,IAAI,CAAC,QAAQ;AAC7D,UAAM,eAAe,mBAAmB,IAAI,IAAI,eAAe,QAAQ;AAAA,MACrE;AAAA,IACF,CAAC;AAGD,UAAM,sBACH,WAAW,iBAAiB,2BAA2B,WACxD,IAAI,OAAO,4BACX;AACF,UAAM,uBAAuB,qBACzB,aAAa;AAAA,MAAO,CAAC,UACnB,mCAAmC,MAAM,IAAI,sBAAsB,MAAM;AAAA,IAC3E,IACA;AAEJ,UAAM,UAA4B,qBAAqB,IAAI,CAAC,WAAW;AAAA,MACrE,IAAI,MAAM;AAAA,MACV,OAAO,gBAAgB,KAAK;AAAA,MAC5B,OAAO,mBAAmB,KAAK;AAAA,MAC/B,aAAa,eAAe,KAAK;AAAA,MACjC,UAAU,MAAM;AAAA,MAChB,OAAO,OAAO,OAAO,MAAM,EAAE,GAAG;AAAA,MAChC,WAAW,mBAAmB,SAAS,MAAM,EAAE,KAAK;AAAA,IACtD,EAAE;AAEF,WAAO;AAAA,MACL,IAAI,IAAI;AAAA,MACR,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI,YAAY;AAAA,MAC1B,WAAW,IAAI,aAAa;AAAA,MAC5B;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,aAAa,OAAO,CAAC,QAAQ,IAAI,QAAQ,SAAS,CAAC;AAC5D;AAMA,IAAM,SAAgC,CAAC,EAAE,gBAAgB,MAAM;AAC7D,SACE,oBAAC,OAAI,eAAc,UAAS,WAAW,GACpC,6BACC,oBAAC,OAAI,cAAc,GACjB,8BAAC,QAAK,OAAM,UAAU,2BAAgB,GACxC,GAEJ;AAEJ;AAEA,IAAM,YAAsB,MAAM;AAChC,SACE,qBAAC,OAAI,aAAa,GAAG,WAAW,GAC9B;AAAA,wBAAC,QAAK,OAAM,QAAO,oBAAM;AAAA,IACzB,oBAAC,QAAK,OAAM,QAAO,yBAAW;AAAA,IAC9B,oBAAC,QAAK,OAAM,UAAS,yBAAW;AAAA,IAChC,oBAAC,QAAK,OAAM,QAAO,sBAAQ;AAAA,KAC7B;AAEJ;AAEO,IAAM,YAAsC,CAAC;AAAA,EAClD;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAA6B,MAAS;AAEpF,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,WAAS,CAAC,QAAQ,QAAQ;AACxB,QAAI,IAAI,QAAQ;AACd,YAAM,aAAa,kBAAkB,YAAY,UAAU;AAC3D,UAAI,WAAW,OAAO;AACpB,2BAAmB,MAAS;AAC5B,mBAAW;AAAA,MACb,OAAO;AACL,2BAAmB,WAAW,OAAO;AAAA,MACvC;AAAA,IACF,WAAW,IAAI,QAAQ;AACrB,yBAAmB,MAAS;AAC5B,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,SACE,qBAAC,OAAI,eAAc,UAAS,OAAM,QAChC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX,eAAc;AAAA,QACd,gBAAe;AAAA,QACf,cAAc;AAAA,QACd,cAAc;AAAA,QACd,WAAW;AAAA,QACX,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,aAAY;AAAA,QACZ,aAAY;AAAA,QAEZ;AAAA,8BAAC,OAAI,WAAW,GAAG,eAAc,OAC9B,0BAAgB,IAAI,CAAC,WACpB,oBAAC,QAAkB,OAAO,WAAW,eAAe,SAAS,QAC1D,+BAAqB,MAAM,KADnB,MAEX,CACD,GACH;AAAA,UACA,oBAAC,aAAU;AAAA;AAAA;AAAA,IACb;AAAA,IACA,qBAAC,aAAU;AAAA;AAAA,MAAgB,qBAAqB,YAAY;AAAA,MAAE;AAAA,OAAM;AAAA,IAEpE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IAEA,oBAAC,UAAO,iBAAkC;AAAA,KAC5C;AAEJ;","names":[]}
@@ -1,60 +1,80 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ ViewTitle
4
+ } from "./chunk-U7HFKR74.js";
5
+ import {
6
+ MenuItem
7
+ } from "./chunk-H7SSBSPR.js";
2
8
  import {
3
9
  useWizardStore
4
- } from "./chunk-D237EVNB.js";
10
+ } from "./chunk-TMED5DQ2.js";
5
11
  import {
6
12
  init_esm_shims
7
- } from "./chunk-DHET7RCE.js";
13
+ } from "./chunk-AWKZ5BDL.js";
8
14
 
9
15
  // src/cli/components/wizard/step-stack.tsx
10
16
  init_esm_shims();
11
- import { Box, Text } from "ink";
17
+ import { useState } from "react";
18
+ import { Box, Text, useInput } from "ink";
12
19
  import { Select } from "@inkjs/ui";
13
20
  import { jsx, jsxs } from "react/jsx-runtime";
14
21
  var BACK_VALUE = "_back";
15
22
  var CONTINUE_VALUE = "_continue";
23
+ var INITIAL_FOCUSED_INDEX = 0;
16
24
  var AVAILABLE_DOMAINS = [
17
25
  { id: "web", label: "Web", description: "Frontend web applications" },
26
+ {
27
+ id: "web-extras",
28
+ label: "Web Extras",
29
+ description: "Animation, files, realtime, PWA, accessibility"
30
+ },
18
31
  { id: "api", label: "API", description: "Backend APIs and services" },
19
32
  { id: "cli", label: "CLI", description: "Command-line tools" },
20
33
  { id: "mobile", label: "Mobile", description: "Mobile applications" }
21
34
  ];
22
35
  var StackSelection = ({ matrix }) => {
23
- const { selectStack, setStep, goBack } = useWizardStore();
24
- const options = [
25
- { value: BACK_VALUE, label: "\u2190 Back" },
26
- ...matrix.suggestedStacks.map((stack) => ({
27
- value: stack.id,
28
- label: `${stack.name} - ${stack.description}`
29
- }))
30
- ];
31
- const handleSelect = (value) => {
32
- if (value === BACK_VALUE) {
36
+ const { selectStack, setStep, setStackAction, populateFromSkillIds, goBack } = useWizardStore();
37
+ const [focusedIndex, setFocusedIndex] = useState(INITIAL_FOCUSED_INDEX);
38
+ const stacks = matrix.suggestedStacks;
39
+ const stackCount = stacks.length;
40
+ useInput((input, key) => {
41
+ if (key.escape) {
33
42
  goBack();
34
43
  return;
35
44
  }
36
- const stack = matrix.suggestedStacks.find((s) => s.id === value);
37
- if (stack) {
38
- selectStack(stack.id);
39
- setStep("stack-options");
45
+ if (key.return && stackCount > 0) {
46
+ const focusedStack = stacks[focusedIndex];
47
+ if (focusedStack) {
48
+ selectStack(focusedStack.id);
49
+ setStackAction("customize");
50
+ const resolvedStack = matrix.suggestedStacks.find((s) => s.id === focusedStack.id);
51
+ if (resolvedStack) {
52
+ populateFromSkillIds(resolvedStack.allSkillIds, matrix.skills, matrix.categories);
53
+ }
54
+ setStep("build");
55
+ }
56
+ return;
40
57
  }
41
- };
58
+ if (key.upArrow || input === "k") {
59
+ setFocusedIndex((prev) => Math.max(0, prev - 1));
60
+ return;
61
+ }
62
+ if (key.downArrow || input === "j") {
63
+ setFocusedIndex((prev) => Math.min(stackCount - 1, prev + 1));
64
+ return;
65
+ }
66
+ });
42
67
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
43
- /* @__PURE__ */ jsx(Text, { bold: true, children: "Select a pre-built template:" }),
44
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
45
- Select,
68
+ /* @__PURE__ */ jsx(ViewTitle, { children: "Select a pre-built template" }),
69
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: stacks.map((stack, index) => /* @__PURE__ */ jsx(
70
+ MenuItem,
46
71
  {
47
- options,
48
- onChange: handleSelect,
49
- visibleOptionCount: options.length
50
- }
51
- ) }),
52
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
53
- "\u2191",
54
- "/",
55
- "\u2193",
56
- " navigate ENTER select ESC back"
57
- ] }) })
72
+ label: stack.name,
73
+ description: stack.description,
74
+ isFocused: index === focusedIndex
75
+ },
76
+ stack.id
77
+ )) })
58
78
  ] });
59
79
  };
60
80
  var DomainSelection = () => {
@@ -117,4 +137,4 @@ var StepStack = ({ matrix }) => {
117
137
  export {
118
138
  StepStack
119
139
  };
120
- //# sourceMappingURL=chunk-CDX4W4DM.js.map
140
+ //# sourceMappingURL=chunk-XENOESJZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/step-stack.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { Select } from \"@inkjs/ui\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport type { Domain, MergedSkillsMatrix } from \"../../types/index.js\";\nimport { MenuItem } from \"./menu-item.js\";\nimport { ViewTitle } from \"./view-title.js\";\n\nconst BACK_VALUE = \"_back\";\nconst CONTINUE_VALUE = \"_continue\";\nconst INITIAL_FOCUSED_INDEX = 0;\n\nconst AVAILABLE_DOMAINS: Array<{ id: Domain; label: string; description: string }> = [\n { id: \"web\", label: \"Web\", description: \"Frontend web applications\" },\n {\n id: \"web-extras\",\n label: \"Web Extras\",\n description: \"Animation, files, realtime, PWA, accessibility\",\n },\n { id: \"api\", label: \"API\", description: \"Backend APIs and services\" },\n { id: \"cli\", label: \"CLI\", description: \"Command-line tools\" },\n { id: \"mobile\", label: \"Mobile\", description: \"Mobile applications\" },\n];\n\ntype StepStackProps = {\n matrix: MergedSkillsMatrix;\n};\n\ntype StackSelectionProps = {\n matrix: MergedSkillsMatrix;\n};\n\nconst StackSelection: React.FC<StackSelectionProps> = ({ matrix }) => {\n const { selectStack, setStep, setStackAction, populateFromSkillIds, goBack } = useWizardStore();\n const [focusedIndex, setFocusedIndex] = useState(INITIAL_FOCUSED_INDEX);\n\n const stacks = matrix.suggestedStacks;\n const stackCount = stacks.length;\n\n useInput((input, key) => {\n if (key.escape) {\n goBack();\n return;\n }\n\n if (key.return && stackCount > 0) {\n const focusedStack = stacks[focusedIndex];\n if (focusedStack) {\n selectStack(focusedStack.id);\n setStackAction(\"customize\");\n\n const resolvedStack = matrix.suggestedStacks.find((s) => s.id === focusedStack.id);\n if (resolvedStack) {\n populateFromSkillIds(resolvedStack.allSkillIds, matrix.skills, matrix.categories);\n }\n\n setStep(\"build\");\n }\n return;\n }\n\n if (key.upArrow || input === \"k\") {\n setFocusedIndex((prev) => Math.max(0, prev - 1));\n return;\n }\n if (key.downArrow || input === \"j\") {\n setFocusedIndex((prev) => Math.min(stackCount - 1, prev + 1));\n return;\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n <ViewTitle>Select a pre-built template</ViewTitle>\n <Box flexDirection=\"column\" marginTop={1}>\n {stacks.map((stack, index) => (\n <MenuItem\n key={stack.id}\n label={stack.name}\n description={stack.description}\n isFocused={index === focusedIndex}\n />\n ))}\n </Box>\n </Box>\n );\n};\n\nconst DomainSelection: React.FC = () => {\n const { selectedDomains, toggleDomain, setStep, goBack } = useWizardStore();\n\n const domainOptions = AVAILABLE_DOMAINS.map((domain) => {\n const isSelected = selectedDomains.includes(domain.id);\n const checkbox = isSelected ? \"[\\u2713]\" : \"[ ]\";\n return {\n value: domain.id,\n label: `${checkbox} ${domain.label} - ${domain.description}`,\n };\n });\n\n const options = [\n { value: BACK_VALUE, label: \"\\u2190 Back\" },\n ...domainOptions,\n ...(selectedDomains.length > 0\n ? [\n {\n value: CONTINUE_VALUE,\n label: `\\u2192 Continue with ${selectedDomains.length} domain(s)`,\n },\n ]\n : []),\n ];\n\n const handleSelect = (value: string) => {\n if (value === BACK_VALUE) {\n goBack();\n return;\n }\n\n if (value === CONTINUE_VALUE) {\n if (selectedDomains.length > 0) {\n setStep(\"build\");\n }\n return;\n }\n\n // Toggle domain selection (value comes from Select UI component - data boundary)\n toggleDomain(value as Domain);\n };\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>Select domains to configure:</Text>\n <Text dimColor>Select one or more domains, then continue</Text>\n <Box marginTop={1}>\n <Select options={options} onChange={handleSelect} />\n </Box>\n {selectedDomains.length > 0 ? (\n <Box marginTop={1}>\n <Text>\n Selected: <Text color=\"cyan\">{selectedDomains.join(\", \")}</Text>\n </Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <Text color=\"yellow\">Please select at least one domain</Text>\n </Box>\n )}\n <Box marginTop={1}>\n <Text dimColor>\n {\"\\u2191\"}/{\"\\u2193\"} navigate ENTER toggle/select ESC back\n </Text>\n </Box>\n </Box>\n );\n};\n\nexport const StepStack: React.FC<StepStackProps> = ({ matrix }) => {\n const { approach } = useWizardStore();\n\n if (approach === \"stack\") {\n return <StackSelection matrix={matrix} />;\n }\n\n // approach === \"scratch\"\n return <DomainSelection />;\n};\n"],"mappings":"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","names":[]}