@claude-collective/cli 0.8.0 → 0.13.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/CHANGELOG.md +127 -0
- package/README.md +26 -9
- package/dist/{chunk-TOPAIL5W.js → chunk-3U3R4NCG.js} +2 -2
- package/dist/chunk-3U3R4NCG.js.map +1 -0
- package/dist/{chunk-YKXBGCFD.js → chunk-57Y5RALO.js} +10 -10
- package/dist/chunk-57Y5RALO.js.map +1 -0
- package/dist/{chunk-ED73HCW2.js → chunk-6DCSSORF.js} +37 -88
- package/dist/chunk-6DCSSORF.js.map +1 -0
- package/dist/{chunk-6LS7XO3H.js → chunk-6Q3Y7KVB.js} +2 -2
- package/dist/chunk-6Q3Y7KVB.js.map +1 -0
- package/dist/{chunk-A3J6IAXK.js → chunk-76DWXGQE.js} +4 -2
- package/dist/chunk-76DWXGQE.js.map +1 -0
- package/dist/{chunk-Q6DR5QUH.js → chunk-7Q44DMSP.js} +62 -27
- package/dist/chunk-7Q44DMSP.js.map +1 -0
- package/dist/chunk-ACNBKXXJ.js +321 -0
- package/dist/chunk-ACNBKXXJ.js.map +1 -0
- package/dist/{chunk-QGGSLMO3.js → chunk-B7CCVP6Q.js} +41 -9
- package/dist/chunk-B7CCVP6Q.js.map +1 -0
- package/dist/{chunk-LVKRVFYR.js → chunk-BDLUZVKU.js} +2 -2
- package/dist/chunk-BDLUZVKU.js.map +1 -0
- package/dist/{chunk-HNDT5QRB.js → chunk-CDX4W4DM.js} +3 -3
- package/dist/chunk-CDX4W4DM.js.map +1 -0
- package/dist/{chunk-MYAVQ23U.js → chunk-CJEHB4TB.js} +23 -9
- package/dist/chunk-CJEHB4TB.js.map +1 -0
- package/dist/{chunk-DKGL77IY.js → chunk-CPZOTVCI.js} +15 -14
- package/dist/chunk-CPZOTVCI.js.map +1 -0
- package/dist/{chunk-K7PTOVX4.js → chunk-D237EVNB.js} +32 -3
- package/dist/chunk-D237EVNB.js.map +1 -0
- package/dist/{chunk-Q2LH2DAB.js → chunk-DRXPNNPB.js} +19 -18
- package/dist/chunk-DRXPNNPB.js.map +1 -0
- package/dist/{chunk-Y3V43XCU.js → chunk-E3FJH4TF.js} +12 -8
- package/dist/chunk-E3FJH4TF.js.map +1 -0
- package/dist/{chunk-3HBTELJN.js → chunk-ED4E6Q2T.js} +10 -10
- package/dist/chunk-ED4E6Q2T.js.map +1 -0
- package/dist/{chunk-SYQ7R2JO.js → chunk-EHS3TWWP.js} +3 -3
- package/dist/chunk-EHS3TWWP.js.map +1 -0
- package/dist/{chunk-LQTST4WY.js → chunk-GDH553MV.js} +6 -6
- package/dist/chunk-GDH553MV.js.map +1 -0
- package/dist/{chunk-A65SBAAJ.js → chunk-HLJX2FTL.js} +31 -5
- package/dist/chunk-HLJX2FTL.js.map +1 -0
- package/dist/chunk-I2DSLOXZ.js +75 -0
- package/dist/chunk-I2DSLOXZ.js.map +1 -0
- package/dist/{chunk-SEBPPFUW.js → chunk-I4TPKIYX.js} +33 -18
- package/dist/chunk-I4TPKIYX.js.map +1 -0
- package/dist/{chunk-NGBFJJ7Q.js → chunk-IMDW5ZUP.js} +19 -11
- package/dist/chunk-IMDW5ZUP.js.map +1 -0
- package/dist/{chunk-U4VYHKPM.js → chunk-JIPWV2FX.js} +6 -6
- package/dist/chunk-JIPWV2FX.js.map +1 -0
- package/dist/{chunk-G2FBJOZG.js → chunk-K7EVM5LY.js} +4 -4
- package/dist/chunk-K7EVM5LY.js.map +1 -0
- package/dist/{chunk-MJSFR562.js → chunk-KAAEN2PO.js} +3 -3
- package/dist/chunk-KAAEN2PO.js.map +1 -0
- package/dist/{chunk-FNOYEXUE.js → chunk-LE6IY6IT.js} +22 -17
- package/dist/chunk-LE6IY6IT.js.map +1 -0
- package/dist/{chunk-CIY5UBRB.js → chunk-NDY25DTL.js} +6 -6
- package/dist/chunk-NDY25DTL.js.map +1 -0
- package/dist/{chunk-OLBOTK3O.js → chunk-P26A2K5N.js} +7 -7
- package/dist/chunk-P26A2K5N.js.map +1 -0
- package/dist/{chunk-DHFFRMF6.js → chunk-RTE64SJA.js} +2 -2
- package/dist/chunk-RTE64SJA.js.map +1 -0
- package/dist/{chunk-3ZCB5K33.js → chunk-SGJ23HIP.js} +14 -11
- package/dist/chunk-SGJ23HIP.js.map +1 -0
- package/dist/{chunk-C4ZTIYFR.js → chunk-SVYPSDWY.js} +10 -10
- package/dist/chunk-SVYPSDWY.js.map +1 -0
- package/dist/{chunk-MMDXNZPF.js → chunk-TKFPKEV3.js} +2 -2
- package/dist/chunk-TKFPKEV3.js.map +1 -0
- package/dist/{chunk-M7YCPFIX.js → chunk-UQTEPWU7.js} +2 -2
- package/dist/chunk-UQTEPWU7.js.map +1 -0
- package/dist/{chunk-QESUUPOE.js → chunk-V46GGCCI.js} +80 -27
- package/dist/chunk-V46GGCCI.js.map +1 -0
- package/dist/{chunk-UOWHJ6BE.js → chunk-X6QONICW.js} +6 -3
- package/dist/chunk-X6QONICW.js.map +1 -0
- package/dist/chunk-Y2LW7R3Y.js +23 -0
- package/dist/chunk-Y2LW7R3Y.js.map +1 -0
- package/dist/chunk-Z2CWURZ6.js +78 -0
- package/dist/chunk-Z2CWURZ6.js.map +1 -0
- package/dist/chunk-Z7G4B5HJ.js +377 -0
- package/dist/chunk-Z7G4B5HJ.js.map +1 -0
- package/dist/{chunk-XKEG3SCV.js → chunk-ZENYS6KW.js} +13 -9
- package/dist/chunk-ZENYS6KW.js.map +1 -0
- package/dist/{cli-v2 → cli}/defaults/agent-mappings.yaml +5 -5
- package/dist/commands/build/marketplace.js +9 -9
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +12 -12
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/build/stack.js +15 -15
- package/dist/commands/build/stack.js.map +1 -1
- package/dist/commands/compile.js +21 -21
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +9 -8
- package/dist/commands/config/get.js.map +1 -1
- package/dist/commands/config/index.js +7 -6
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/config/path.js +8 -7
- package/dist/commands/config/path.js.map +1 -1
- package/dist/commands/config/set-project.js +9 -8
- package/dist/commands/config/set-project.js.map +1 -1
- package/dist/commands/config/set.js +9 -8
- package/dist/commands/config/set.js.map +1 -1
- package/dist/commands/config/show.js +6 -5
- package/dist/commands/config/unset-project.js +9 -8
- package/dist/commands/config/unset-project.js.map +1 -1
- package/dist/commands/config/unset.js +9 -8
- package/dist/commands/config/unset.js.map +1 -1
- package/dist/commands/diff.js +12 -12
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +10 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +52 -49
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +180 -97
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +339 -0
- package/dist/commands/import/skill.js.map +1 -0
- package/dist/commands/info.js +9 -9
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +205 -78
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +9 -9
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/agent.js +19 -21
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/skill.js +11 -12
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +12 -12
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +205 -17
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/test-imports.js +18 -18
- package/dist/commands/test-imports.js.map +1 -1
- package/dist/commands/uninstall.js +58 -78
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +21 -21
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +9 -9
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/version/bump.js +8 -8
- package/dist/commands/version/bump.js.map +1 -1
- package/dist/commands/version/index.js +8 -8
- package/dist/commands/version/index.js.map +1 -1
- package/dist/commands/version/set.js +7 -7
- package/dist/commands/version/set.js.map +1 -1
- package/dist/commands/version/show.js +8 -8
- package/dist/commands/version/show.js.map +1 -1
- package/dist/components/common/confirm.js +1 -1
- package/dist/components/common/message.js +1 -1
- package/dist/components/common/message.js.map +1 -1
- package/dist/components/common/spinner.js +1 -1
- package/dist/components/common/spinner.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +10 -0
- package/dist/components/skill-search/skill-search.js.map +1 -0
- package/dist/components/wizard/category-grid.js +1 -1
- package/dist/components/wizard/category-grid.test.js +213 -80
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/section-progress.js +1 -1
- package/dist/components/wizard/section-progress.test.js +2 -2
- package/dist/components/wizard/section-progress.test.js.map +1 -1
- package/dist/components/wizard/step-approach.js +4 -3
- package/dist/components/wizard/step-build.js +4 -3
- package/dist/components/wizard/step-build.test.js +29 -17
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +2 -1
- package/dist/components/wizard/step-refine.js +2 -1
- package/dist/components/wizard/step-refine.test.js +4 -3
- package/dist/components/wizard/step-refine.test.js.map +1 -1
- package/dist/components/wizard/step-stack-options.js +3 -3
- package/dist/components/wizard/step-stack.js +3 -3
- package/dist/components/wizard/wizard-footer.js +9 -0
- package/dist/components/wizard/wizard-footer.js.map +1 -0
- package/dist/components/wizard/wizard-tabs.js +1 -1
- package/dist/components/wizard/wizard.js +14 -12
- package/dist/hooks/init.js +5 -4
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/stores/wizard-store.js +2 -2
- package/dist/stores/wizard-store.test.js +3 -3
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-3HBTELJN.js.map +0 -1
- package/dist/chunk-3ZCB5K33.js.map +0 -1
- package/dist/chunk-6LS7XO3H.js.map +0 -1
- package/dist/chunk-A3J6IAXK.js.map +0 -1
- package/dist/chunk-A65SBAAJ.js.map +0 -1
- package/dist/chunk-ALEPJ6YN.js +0 -80
- package/dist/chunk-ALEPJ6YN.js.map +0 -1
- package/dist/chunk-C4ZTIYFR.js.map +0 -1
- package/dist/chunk-CIY5UBRB.js.map +0 -1
- package/dist/chunk-DHFFRMF6.js.map +0 -1
- package/dist/chunk-DKGL77IY.js.map +0 -1
- package/dist/chunk-ED73HCW2.js.map +0 -1
- package/dist/chunk-FNOYEXUE.js.map +0 -1
- package/dist/chunk-G2FBJOZG.js.map +0 -1
- package/dist/chunk-HNDT5QRB.js.map +0 -1
- package/dist/chunk-K7PTOVX4.js.map +0 -1
- package/dist/chunk-LQTST4WY.js.map +0 -1
- package/dist/chunk-LVKRVFYR.js.map +0 -1
- package/dist/chunk-M7YCPFIX.js.map +0 -1
- package/dist/chunk-MJSFR562.js.map +0 -1
- package/dist/chunk-MMDXNZPF.js.map +0 -1
- package/dist/chunk-MYAVQ23U.js.map +0 -1
- package/dist/chunk-NGBFJJ7Q.js.map +0 -1
- package/dist/chunk-OLBOTK3O.js.map +0 -1
- package/dist/chunk-PPNTD5LO.js +0 -330
- package/dist/chunk-PPNTD5LO.js.map +0 -1
- package/dist/chunk-Q2LH2DAB.js.map +0 -1
- package/dist/chunk-Q6DR5QUH.js.map +0 -1
- package/dist/chunk-QESUUPOE.js.map +0 -1
- package/dist/chunk-QGGSLMO3.js.map +0 -1
- package/dist/chunk-SEBPPFUW.js.map +0 -1
- package/dist/chunk-SYQ7R2JO.js.map +0 -1
- package/dist/chunk-TOPAIL5W.js.map +0 -1
- package/dist/chunk-U4VYHKPM.js.map +0 -1
- package/dist/chunk-UOWHJ6BE.js.map +0 -1
- package/dist/chunk-XKEG3SCV.js.map +0 -1
- package/dist/chunk-Y3V43XCU.js.map +0 -1
- package/dist/chunk-YKXBGCFD.js.map +0 -1
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
RENDER_DELAY_MS,
|
|
9
9
|
TAB,
|
|
10
10
|
delay
|
|
11
|
-
} from "../../chunk-
|
|
11
|
+
} from "../../chunk-6Q3Y7KVB.js";
|
|
12
12
|
import {
|
|
13
13
|
render
|
|
14
14
|
} from "../../chunk-66UDJBF6.js";
|
|
@@ -21,12 +21,12 @@ import {
|
|
|
21
21
|
} from "../../chunk-XY3XDVMI.js";
|
|
22
22
|
import {
|
|
23
23
|
CategoryGrid
|
|
24
|
-
} from "../../chunk-
|
|
24
|
+
} from "../../chunk-Z7G4B5HJ.js";
|
|
25
25
|
import {
|
|
26
26
|
init_esm_shims
|
|
27
27
|
} from "../../chunk-DHET7RCE.js";
|
|
28
28
|
|
|
29
|
-
// src/cli
|
|
29
|
+
// src/cli/components/wizard/category-grid.test.tsx
|
|
30
30
|
init_esm_shims();
|
|
31
31
|
import { jsx } from "react/jsx-runtime";
|
|
32
32
|
var createOption = (id, label, overrides = {}) => ({
|
|
@@ -49,13 +49,13 @@ var defaultCategories = [
|
|
|
49
49
|
"framework",
|
|
50
50
|
"Framework",
|
|
51
51
|
[
|
|
52
|
-
createOption("react", "
|
|
52
|
+
createOption("react", "React", {
|
|
53
53
|
state: "recommended",
|
|
54
54
|
stateReason: "Popular choice"
|
|
55
55
|
}),
|
|
56
|
-
createOption("vue", "
|
|
57
|
-
createOption("angular", "
|
|
58
|
-
createOption("svelte", "
|
|
56
|
+
createOption("vue", "Vue"),
|
|
57
|
+
createOption("angular", "Angular"),
|
|
58
|
+
createOption("svelte", "Svelte")
|
|
59
59
|
],
|
|
60
60
|
{ required: true }
|
|
61
61
|
),
|
|
@@ -63,29 +63,64 @@ var defaultCategories = [
|
|
|
63
63
|
"styling",
|
|
64
64
|
"Styling",
|
|
65
65
|
[
|
|
66
|
-
createOption("scss-mod", "
|
|
67
|
-
createOption("tailwind", "
|
|
68
|
-
createOption("styled", "
|
|
69
|
-
createOption("vanilla", "
|
|
66
|
+
createOption("scss-mod", "SCSS Modules", { selected: true }),
|
|
67
|
+
createOption("tailwind", "Tailwind", { state: "recommended" }),
|
|
68
|
+
createOption("styled", "Styled Components"),
|
|
69
|
+
createOption("vanilla", "Vanilla CSS")
|
|
70
70
|
],
|
|
71
71
|
{ required: true }
|
|
72
72
|
),
|
|
73
73
|
createCategory("client-state", "Client State", [
|
|
74
|
-
createOption("zustand", "
|
|
75
|
-
createOption("jotai", "
|
|
76
|
-
createOption("redux", "
|
|
74
|
+
createOption("zustand", "Zustand", { state: "recommended" }),
|
|
75
|
+
createOption("jotai", "Jotai"),
|
|
76
|
+
createOption("redux", "Redux", {
|
|
77
77
|
state: "discouraged",
|
|
78
78
|
stateReason: "Complex for most apps"
|
|
79
79
|
}),
|
|
80
|
-
createOption("mobx", "
|
|
80
|
+
createOption("mobx", "MobX")
|
|
81
81
|
]),
|
|
82
82
|
createCategory("server-state", "Server State", [
|
|
83
|
-
createOption("react-query", "
|
|
84
|
-
createOption("swr", "
|
|
85
|
-
createOption("apollo", "
|
|
83
|
+
createOption("react-query", "React Query", { selected: true }),
|
|
84
|
+
createOption("swr", "SWR"),
|
|
85
|
+
createOption("apollo", "Apollo")
|
|
86
86
|
]),
|
|
87
87
|
createCategory("analytics", "Analytics", [
|
|
88
|
-
createOption("posthog", "
|
|
88
|
+
createOption("posthog", "PostHog")
|
|
89
|
+
])
|
|
90
|
+
];
|
|
91
|
+
var categoriesWithFramework = [
|
|
92
|
+
createCategory(
|
|
93
|
+
"framework",
|
|
94
|
+
"Framework",
|
|
95
|
+
[
|
|
96
|
+
createOption("react", "React", {
|
|
97
|
+
state: "recommended",
|
|
98
|
+
stateReason: "Popular choice",
|
|
99
|
+
selected: true
|
|
100
|
+
// Framework selected
|
|
101
|
+
}),
|
|
102
|
+
createOption("vue", "Vue"),
|
|
103
|
+
createOption("angular", "Angular"),
|
|
104
|
+
createOption("svelte", "Svelte")
|
|
105
|
+
],
|
|
106
|
+
{ required: true }
|
|
107
|
+
),
|
|
108
|
+
createCategory(
|
|
109
|
+
"styling",
|
|
110
|
+
"Styling",
|
|
111
|
+
[
|
|
112
|
+
createOption("scss-mod", "SCSS Modules"),
|
|
113
|
+
createOption("tailwind", "Tailwind", { state: "recommended" }),
|
|
114
|
+
createOption("styled", "Styled Components"),
|
|
115
|
+
createOption("vanilla", "Vanilla CSS")
|
|
116
|
+
],
|
|
117
|
+
{ required: true }
|
|
118
|
+
),
|
|
119
|
+
createCategory("client-state", "Client State", [
|
|
120
|
+
createOption("zustand", "Zustand", { state: "recommended" }),
|
|
121
|
+
createOption("jotai", "Jotai"),
|
|
122
|
+
createOption("redux", "Redux", { state: "discouraged" }),
|
|
123
|
+
createOption("mobx", "MobX")
|
|
89
124
|
])
|
|
90
125
|
];
|
|
91
126
|
var defaultProps = {
|
|
@@ -110,7 +145,7 @@ describe("CategoryGrid component", () => {
|
|
|
110
145
|
vi.clearAllMocks();
|
|
111
146
|
});
|
|
112
147
|
describe("rendering", () => {
|
|
113
|
-
it("should render all categories", () => {
|
|
148
|
+
it("should render all categories as sections", () => {
|
|
114
149
|
const { lastFrame, unmount } = renderGrid();
|
|
115
150
|
cleanup = unmount;
|
|
116
151
|
const output = lastFrame();
|
|
@@ -124,12 +159,12 @@ describe("CategoryGrid component", () => {
|
|
|
124
159
|
const { lastFrame, unmount } = renderGrid();
|
|
125
160
|
cleanup = unmount;
|
|
126
161
|
const output = lastFrame();
|
|
127
|
-
globalExpect(output).toContain("
|
|
128
|
-
globalExpect(output).toContain("
|
|
129
|
-
globalExpect(output).toContain("
|
|
130
|
-
globalExpect(output).toContain("
|
|
131
|
-
globalExpect(output).toContain("
|
|
132
|
-
globalExpect(output).toContain("
|
|
162
|
+
globalExpect(output).toContain("React");
|
|
163
|
+
globalExpect(output).toContain("Vue");
|
|
164
|
+
globalExpect(output).toContain("Angular");
|
|
165
|
+
globalExpect(output).toContain("Svelte");
|
|
166
|
+
globalExpect(output).toContain("SCSS Modules");
|
|
167
|
+
globalExpect(output).toContain("Tailwind");
|
|
133
168
|
});
|
|
134
169
|
it("should show required indicator (*) for required categories", () => {
|
|
135
170
|
const { lastFrame, unmount } = renderGrid();
|
|
@@ -137,13 +172,13 @@ describe("CategoryGrid component", () => {
|
|
|
137
172
|
const output = lastFrame();
|
|
138
173
|
globalExpect(output).toContain("*");
|
|
139
174
|
});
|
|
140
|
-
it("should show (optional) for non-required categories", () => {
|
|
175
|
+
it("should NOT show (optional) for non-required categories", () => {
|
|
141
176
|
const { lastFrame, unmount } = renderGrid();
|
|
142
177
|
cleanup = unmount;
|
|
143
178
|
const output = lastFrame();
|
|
144
|
-
globalExpect(output).toContain("(optional)");
|
|
179
|
+
globalExpect(output).not.toContain("(optional)");
|
|
145
180
|
});
|
|
146
|
-
it("should render legend row", () => {
|
|
181
|
+
it("should render legend row with visual states", () => {
|
|
147
182
|
const { lastFrame, unmount } = renderGrid();
|
|
148
183
|
cleanup = unmount;
|
|
149
184
|
const output = lastFrame();
|
|
@@ -157,7 +192,7 @@ describe("CategoryGrid component", () => {
|
|
|
157
192
|
const { lastFrame, unmount } = renderGrid();
|
|
158
193
|
cleanup = unmount;
|
|
159
194
|
const output = lastFrame();
|
|
160
|
-
globalExpect(output).toContain("[
|
|
195
|
+
globalExpect(output).toContain("[d] Descriptions");
|
|
161
196
|
globalExpect(output).toContain("[e] Expert Mode");
|
|
162
197
|
});
|
|
163
198
|
it("should handle empty categories array", () => {
|
|
@@ -166,33 +201,41 @@ describe("CategoryGrid component", () => {
|
|
|
166
201
|
const output = lastFrame();
|
|
167
202
|
globalExpect(output).toContain("No categories to display");
|
|
168
203
|
});
|
|
204
|
+
it("should render section underlines", () => {
|
|
205
|
+
const { lastFrame, unmount } = renderGrid();
|
|
206
|
+
cleanup = unmount;
|
|
207
|
+
const output = lastFrame();
|
|
208
|
+
globalExpect(output).toContain("\u2500");
|
|
209
|
+
});
|
|
169
210
|
});
|
|
170
211
|
describe("visual states", () => {
|
|
171
|
-
it("should show selected
|
|
212
|
+
it("should show selected options with label text", () => {
|
|
172
213
|
const { lastFrame, unmount } = renderGrid();
|
|
173
214
|
cleanup = unmount;
|
|
174
215
|
const output = lastFrame();
|
|
175
|
-
globalExpect(output).toContain("
|
|
216
|
+
globalExpect(output).toContain("SCSS Modules");
|
|
217
|
+
globalExpect(output).toContain("React Query");
|
|
176
218
|
});
|
|
177
|
-
it("should show unselected
|
|
219
|
+
it("should show unselected options with label text", () => {
|
|
178
220
|
const { lastFrame, unmount } = renderGrid();
|
|
179
221
|
cleanup = unmount;
|
|
180
222
|
const output = lastFrame();
|
|
181
|
-
globalExpect(output).toContain("
|
|
223
|
+
globalExpect(output).toContain("Vue");
|
|
224
|
+
globalExpect(output).toContain("Angular");
|
|
182
225
|
});
|
|
183
|
-
it("should show
|
|
226
|
+
it("should NOT show star indicator for recommended options (uses background instead)", () => {
|
|
184
227
|
const { lastFrame, unmount } = renderGrid();
|
|
185
228
|
cleanup = unmount;
|
|
186
229
|
const output = lastFrame();
|
|
187
|
-
globalExpect(output).toContain("\u2B50");
|
|
230
|
+
globalExpect(output).not.toContain("\u2B50");
|
|
188
231
|
});
|
|
189
|
-
it("should show
|
|
232
|
+
it("should NOT show warning indicator for discouraged options (uses color instead)", () => {
|
|
190
233
|
const { lastFrame, unmount } = renderGrid();
|
|
191
234
|
cleanup = unmount;
|
|
192
235
|
const output = lastFrame();
|
|
193
|
-
globalExpect(output).toContain("\u26A0");
|
|
236
|
+
globalExpect(output).not.toContain("\u26A0");
|
|
194
237
|
});
|
|
195
|
-
it("should show disabled
|
|
238
|
+
it("should show disabled options with dimmed styling", () => {
|
|
196
239
|
const categories = [
|
|
197
240
|
createCategory("test", "Test", [
|
|
198
241
|
createOption("opt1", "Option 1"),
|
|
@@ -202,37 +245,76 @@ describe("CategoryGrid component", () => {
|
|
|
202
245
|
const { lastFrame, unmount } = renderGrid({ categories });
|
|
203
246
|
cleanup = unmount;
|
|
204
247
|
const output = lastFrame();
|
|
205
|
-
globalExpect(output).toContain("
|
|
248
|
+
globalExpect(output).toContain("Option 2");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
describe("locked sections", () => {
|
|
252
|
+
it("should show all categories including locked ones", () => {
|
|
253
|
+
const { lastFrame, unmount } = renderGrid();
|
|
254
|
+
cleanup = unmount;
|
|
255
|
+
const output = lastFrame();
|
|
256
|
+
globalExpect(output).toContain("Framework");
|
|
257
|
+
globalExpect(output).toContain("Styling");
|
|
258
|
+
globalExpect(output).toContain("Client State");
|
|
259
|
+
});
|
|
260
|
+
it("should unlock sections when framework is selected", () => {
|
|
261
|
+
const { lastFrame, unmount } = renderGrid({
|
|
262
|
+
categories: categoriesWithFramework
|
|
263
|
+
});
|
|
264
|
+
cleanup = unmount;
|
|
265
|
+
const output = lastFrame();
|
|
266
|
+
globalExpect(output).toContain("Framework");
|
|
267
|
+
globalExpect(output).toContain("Styling");
|
|
268
|
+
globalExpect(output).toContain("Client State");
|
|
269
|
+
});
|
|
270
|
+
it("should not lock any sections when no framework category exists", () => {
|
|
271
|
+
const categoriesNoFramework = [
|
|
272
|
+
createCategory("styling", "Styling", [
|
|
273
|
+
createOption("scss", "SCSS"),
|
|
274
|
+
createOption("tailwind", "Tailwind")
|
|
275
|
+
]),
|
|
276
|
+
createCategory("state", "State", [createOption("zustand", "Zustand")])
|
|
277
|
+
];
|
|
278
|
+
const { lastFrame, unmount } = renderGrid({
|
|
279
|
+
categories: categoriesNoFramework
|
|
280
|
+
});
|
|
281
|
+
cleanup = unmount;
|
|
282
|
+
const output = lastFrame();
|
|
283
|
+
globalExpect(output).toContain("Styling");
|
|
284
|
+
globalExpect(output).toContain("State");
|
|
206
285
|
});
|
|
207
286
|
});
|
|
208
287
|
describe("focus indicator", () => {
|
|
209
|
-
it("should
|
|
288
|
+
it("should render focused option with label text", () => {
|
|
210
289
|
const { lastFrame, unmount } = renderGrid({
|
|
211
290
|
focusedRow: 0,
|
|
212
291
|
focusedCol: 0
|
|
213
292
|
});
|
|
214
293
|
cleanup = unmount;
|
|
215
294
|
const output = lastFrame();
|
|
216
|
-
globalExpect(output).toContain("
|
|
295
|
+
globalExpect(output).toContain("React");
|
|
217
296
|
});
|
|
218
|
-
it("should
|
|
297
|
+
it("should render correctly when focusedRow changes", () => {
|
|
219
298
|
const { lastFrame: frame1, unmount: unmount1 } = renderGrid({
|
|
299
|
+
categories: categoriesWithFramework,
|
|
220
300
|
focusedRow: 0,
|
|
221
301
|
focusedCol: 0
|
|
222
302
|
});
|
|
223
303
|
const output1 = frame1();
|
|
224
304
|
unmount1();
|
|
225
305
|
const { lastFrame: frame2, unmount: unmount2 } = renderGrid({
|
|
306
|
+
categories: categoriesWithFramework,
|
|
226
307
|
focusedRow: 1,
|
|
227
308
|
focusedCol: 0
|
|
228
309
|
});
|
|
229
310
|
cleanup = unmount2;
|
|
230
311
|
const output2 = frame2();
|
|
231
|
-
globalExpect(output1).toContain("
|
|
232
|
-
globalExpect(output2).toContain("
|
|
312
|
+
globalExpect(output1).toContain("Framework");
|
|
313
|
+
globalExpect(output2).toContain("Styling");
|
|
233
314
|
});
|
|
234
315
|
it("should highlight focused category name", () => {
|
|
235
316
|
const { lastFrame, unmount } = renderGrid({
|
|
317
|
+
categories: categoriesWithFramework,
|
|
236
318
|
focusedRow: 1,
|
|
237
319
|
focusedCol: 0
|
|
238
320
|
});
|
|
@@ -268,10 +350,10 @@ describe("CategoryGrid component", () => {
|
|
|
268
350
|
await delay(INPUT_DELAY_MS);
|
|
269
351
|
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 1);
|
|
270
352
|
});
|
|
271
|
-
it("should call onFocusChange when pressing up arrow", async () => {
|
|
353
|
+
it("should call onFocusChange when pressing up arrow (wraps to framework when locked)", async () => {
|
|
272
354
|
const onFocusChange = vi.fn();
|
|
273
355
|
const { stdin, unmount } = renderGrid({
|
|
274
|
-
focusedRow:
|
|
356
|
+
focusedRow: 0,
|
|
275
357
|
focusedCol: 0,
|
|
276
358
|
onFocusChange
|
|
277
359
|
});
|
|
@@ -281,9 +363,10 @@ describe("CategoryGrid component", () => {
|
|
|
281
363
|
await delay(INPUT_DELAY_MS);
|
|
282
364
|
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
283
365
|
});
|
|
284
|
-
it("should
|
|
366
|
+
it("should navigate between sections when unlocked", async () => {
|
|
285
367
|
const onFocusChange = vi.fn();
|
|
286
368
|
const { stdin, unmount } = renderGrid({
|
|
369
|
+
categories: categoriesWithFramework,
|
|
287
370
|
focusedRow: 0,
|
|
288
371
|
focusedCol: 0,
|
|
289
372
|
onFocusChange
|
|
@@ -321,9 +404,10 @@ describe("CategoryGrid component", () => {
|
|
|
321
404
|
await delay(INPUT_DELAY_MS);
|
|
322
405
|
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
323
406
|
});
|
|
324
|
-
it("should wrap vertically when
|
|
407
|
+
it("should wrap vertically when all sections are unlocked", async () => {
|
|
325
408
|
const onFocusChange = vi.fn();
|
|
326
409
|
const { stdin, unmount } = renderGrid({
|
|
410
|
+
categories: categoriesWithFramework,
|
|
327
411
|
focusedRow: 0,
|
|
328
412
|
focusedCol: 0,
|
|
329
413
|
onFocusChange
|
|
@@ -332,21 +416,7 @@ describe("CategoryGrid component", () => {
|
|
|
332
416
|
await delay(RENDER_DELAY_MS);
|
|
333
417
|
await stdin.write(ARROW_UP);
|
|
334
418
|
await delay(INPUT_DELAY_MS);
|
|
335
|
-
globalExpect(onFocusChange).toHaveBeenCalledWith(
|
|
336
|
-
});
|
|
337
|
-
it("should wrap vertically when pressing down at last row", async () => {
|
|
338
|
-
const onFocusChange = vi.fn();
|
|
339
|
-
const { stdin, unmount } = renderGrid({
|
|
340
|
-
focusedRow: 4,
|
|
341
|
-
// Last category (analytics)
|
|
342
|
-
focusedCol: 0,
|
|
343
|
-
onFocusChange
|
|
344
|
-
});
|
|
345
|
-
cleanup = unmount;
|
|
346
|
-
await delay(RENDER_DELAY_MS);
|
|
347
|
-
await stdin.write(ARROW_DOWN);
|
|
348
|
-
await delay(INPUT_DELAY_MS);
|
|
349
|
-
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
419
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(2, 0);
|
|
350
420
|
});
|
|
351
421
|
});
|
|
352
422
|
describe("keyboard navigation - vim keys", () => {
|
|
@@ -379,6 +449,7 @@ describe("CategoryGrid component", () => {
|
|
|
379
449
|
it("should move up with k key", async () => {
|
|
380
450
|
const onFocusChange = vi.fn();
|
|
381
451
|
const { stdin, unmount } = renderGrid({
|
|
452
|
+
categories: categoriesWithFramework,
|
|
382
453
|
focusedRow: 1,
|
|
383
454
|
focusedCol: 0,
|
|
384
455
|
onFocusChange
|
|
@@ -392,6 +463,7 @@ describe("CategoryGrid component", () => {
|
|
|
392
463
|
it("should move down with j key", async () => {
|
|
393
464
|
const onFocusChange = vi.fn();
|
|
394
465
|
const { stdin, unmount } = renderGrid({
|
|
466
|
+
categories: categoriesWithFramework,
|
|
395
467
|
focusedRow: 0,
|
|
396
468
|
focusedCol: 0,
|
|
397
469
|
onFocusChange
|
|
@@ -420,10 +492,22 @@ describe("CategoryGrid component", () => {
|
|
|
420
492
|
});
|
|
421
493
|
it("should call onToggle when pressing space on a selected option", async () => {
|
|
422
494
|
const onToggle = vi.fn();
|
|
495
|
+
const categories = [
|
|
496
|
+
createCategory(
|
|
497
|
+
"framework",
|
|
498
|
+
"Framework",
|
|
499
|
+
[
|
|
500
|
+
createOption("react", "React", { selected: true }),
|
|
501
|
+
createOption("vue", "Vue")
|
|
502
|
+
],
|
|
503
|
+
{ required: true }
|
|
504
|
+
)
|
|
505
|
+
];
|
|
423
506
|
const { stdin, unmount } = renderGrid({
|
|
424
|
-
|
|
507
|
+
categories,
|
|
508
|
+
focusedRow: 0,
|
|
425
509
|
focusedCol: 0,
|
|
426
|
-
//
|
|
510
|
+
// react (selected)
|
|
427
511
|
expertMode: true,
|
|
428
512
|
onToggle
|
|
429
513
|
});
|
|
@@ -431,7 +515,7 @@ describe("CategoryGrid component", () => {
|
|
|
431
515
|
await delay(RENDER_DELAY_MS);
|
|
432
516
|
await stdin.write(" ");
|
|
433
517
|
await delay(INPUT_DELAY_MS);
|
|
434
|
-
globalExpect(onToggle).toHaveBeenCalledWith("
|
|
518
|
+
globalExpect(onToggle).toHaveBeenCalledWith("framework", "react");
|
|
435
519
|
});
|
|
436
520
|
it("should NOT call onToggle when pressing space on a disabled option", async () => {
|
|
437
521
|
const onToggle = vi.fn();
|
|
@@ -455,6 +539,20 @@ describe("CategoryGrid component", () => {
|
|
|
455
539
|
await delay(INPUT_DELAY_MS);
|
|
456
540
|
globalExpect(onToggle).not.toHaveBeenCalled();
|
|
457
541
|
});
|
|
542
|
+
it("should NOT call onToggle when section is locked", async () => {
|
|
543
|
+
const onToggle = vi.fn();
|
|
544
|
+
const { stdin, unmount } = renderGrid({
|
|
545
|
+
focusedRow: 1,
|
|
546
|
+
// Styling (locked)
|
|
547
|
+
focusedCol: 0,
|
|
548
|
+
onToggle
|
|
549
|
+
});
|
|
550
|
+
cleanup = unmount;
|
|
551
|
+
await delay(RENDER_DELAY_MS);
|
|
552
|
+
await stdin.write(" ");
|
|
553
|
+
await delay(INPUT_DELAY_MS);
|
|
554
|
+
globalExpect(onToggle).not.toHaveBeenCalled();
|
|
555
|
+
});
|
|
458
556
|
});
|
|
459
557
|
describe("disabled options navigation", () => {
|
|
460
558
|
it("should skip disabled options when navigating right", async () => {
|
|
@@ -532,15 +630,44 @@ describe("CategoryGrid component", () => {
|
|
|
532
630
|
globalExpect(output).toContain("Framework");
|
|
533
631
|
});
|
|
534
632
|
});
|
|
633
|
+
describe("tab navigation", () => {
|
|
634
|
+
it("should jump to next section when pressing Tab", async () => {
|
|
635
|
+
const onFocusChange = vi.fn();
|
|
636
|
+
const { stdin, unmount } = renderGrid({
|
|
637
|
+
categories: categoriesWithFramework,
|
|
638
|
+
focusedRow: 0,
|
|
639
|
+
focusedCol: 0,
|
|
640
|
+
onFocusChange
|
|
641
|
+
});
|
|
642
|
+
cleanup = unmount;
|
|
643
|
+
await delay(RENDER_DELAY_MS);
|
|
644
|
+
await stdin.write(TAB);
|
|
645
|
+
await delay(INPUT_DELAY_MS);
|
|
646
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(1, 0);
|
|
647
|
+
});
|
|
648
|
+
it("should only jump to unlocked sections", async () => {
|
|
649
|
+
const onFocusChange = vi.fn();
|
|
650
|
+
const { stdin, unmount } = renderGrid({
|
|
651
|
+
focusedRow: 0,
|
|
652
|
+
focusedCol: 0,
|
|
653
|
+
onFocusChange
|
|
654
|
+
});
|
|
655
|
+
cleanup = unmount;
|
|
656
|
+
await delay(RENDER_DELAY_MS);
|
|
657
|
+
await stdin.write(TAB);
|
|
658
|
+
await delay(INPUT_DELAY_MS);
|
|
659
|
+
globalExpect(onFocusChange).not.toHaveBeenCalled();
|
|
660
|
+
});
|
|
661
|
+
});
|
|
535
662
|
describe("show descriptions toggle", () => {
|
|
536
|
-
it("should call onToggleDescriptions when pressing
|
|
663
|
+
it("should call onToggleDescriptions when pressing d key", async () => {
|
|
537
664
|
const onToggleDescriptions = vi.fn();
|
|
538
665
|
const { stdin, unmount } = renderGrid({
|
|
539
666
|
onToggleDescriptions
|
|
540
667
|
});
|
|
541
668
|
cleanup = unmount;
|
|
542
669
|
await delay(RENDER_DELAY_MS);
|
|
543
|
-
await stdin.write(
|
|
670
|
+
await stdin.write("d");
|
|
544
671
|
await delay(INPUT_DELAY_MS);
|
|
545
672
|
globalExpect(onToggleDescriptions).toHaveBeenCalled();
|
|
546
673
|
});
|
|
@@ -567,8 +694,8 @@ describe("CategoryGrid component", () => {
|
|
|
567
694
|
});
|
|
568
695
|
cleanup = unmount2;
|
|
569
696
|
const output2 = frame2();
|
|
570
|
-
globalExpect(output1).toContain("
|
|
571
|
-
globalExpect(output2).toContain("
|
|
697
|
+
globalExpect(output1).toContain("Descriptions: OFF");
|
|
698
|
+
globalExpect(output2).toContain("Descriptions: ON");
|
|
572
699
|
});
|
|
573
700
|
});
|
|
574
701
|
describe("expert mode toggle", () => {
|
|
@@ -647,7 +774,7 @@ describe("CategoryGrid component", () => {
|
|
|
647
774
|
const output = lastFrame();
|
|
648
775
|
globalExpect(output).toContain("Only Option");
|
|
649
776
|
});
|
|
650
|
-
it("should handle category with many options", () => {
|
|
777
|
+
it("should handle category with many options (flows naturally)", () => {
|
|
651
778
|
const options = Array.from(
|
|
652
779
|
{ length: 10 },
|
|
653
780
|
(_, i) => createOption(`opt${i}`, `Option ${i}`)
|
|
@@ -665,14 +792,14 @@ describe("CategoryGrid component", () => {
|
|
|
665
792
|
it("should handle long option labels", () => {
|
|
666
793
|
const categories = [
|
|
667
794
|
createCategory("long", "Long Labels", [
|
|
668
|
-
createOption("long1", "
|
|
669
|
-
createOption("long2", "
|
|
795
|
+
createOption("long1", "Very Long Option Name"),
|
|
796
|
+
createOption("long2", "Another Long Name")
|
|
670
797
|
])
|
|
671
798
|
];
|
|
672
799
|
const { lastFrame, unmount } = renderGrid({ categories });
|
|
673
800
|
cleanup = unmount;
|
|
674
801
|
const output = lastFrame();
|
|
675
|
-
globalExpect(output).toContain("
|
|
802
|
+
globalExpect(output).toContain("Very Long Option Name");
|
|
676
803
|
});
|
|
677
804
|
it("should handle categories with different option counts", () => {
|
|
678
805
|
const categories = [
|
|
@@ -701,11 +828,17 @@ describe("CategoryGrid component", () => {
|
|
|
701
828
|
it("should adjust focusedCol when changing to row with fewer options", async () => {
|
|
702
829
|
const onFocusChange = vi.fn();
|
|
703
830
|
const categories = [
|
|
704
|
-
createCategory(
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
831
|
+
createCategory(
|
|
832
|
+
"framework",
|
|
833
|
+
"Framework",
|
|
834
|
+
[
|
|
835
|
+
createOption("opt1", "Option 1", { selected: true }),
|
|
836
|
+
// Framework selected
|
|
837
|
+
createOption("opt2", "Option 2"),
|
|
838
|
+
createOption("opt3", "Option 3")
|
|
839
|
+
],
|
|
840
|
+
{ required: true }
|
|
841
|
+
),
|
|
709
842
|
createCategory("cat2", "Category 2", [
|
|
710
843
|
createOption("opt4", "Option 4")
|
|
711
844
|
])
|