procedure-cli 0.1.12 → 0.1.13
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/.claude/settings.local.json +2 -1
- package/AGENTS.md +82 -61
- package/CODE-FIXED.md +55 -0
- package/CODE-REVIEW.md +127 -0
- package/README.md +15 -3
- package/dist/steps/build-test.js +32 -3
- package/dist/steps/build-test.js.map +1 -1
- package/dist/steps/powerline.js +11 -3
- package/dist/steps/powerline.js.map +1 -1
- package/dist/steps/product-context.js +54 -19
- package/dist/steps/product-context.js.map +1 -1
- package/dist/steps/project-info.js +30 -3
- package/dist/steps/project-info.js.map +1 -1
- package/docs/PRD.md +2 -1
- package/docs/USER-STORIES.md +66 -6
- package/package.json +1 -1
- package/src/steps/build-test.tsx +41 -6
- package/src/steps/powerline.tsx +17 -1
- package/src/steps/product-context.tsx +100 -39
- package/src/steps/project-info.tsx +57 -10
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { Text } from "ink";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { Text, useInput } from "ink";
|
|
4
4
|
import { TextInput } from "@inkjs/ui";
|
|
5
5
|
import { GutterLine } from "../components/gutter-line.js";
|
|
6
6
|
import { GutteredMultiSelect } from "../components/guttered-select.js";
|
|
@@ -46,6 +46,7 @@ export default function ProductContext({ initialValues, onComplete }) {
|
|
|
46
46
|
const [phaseIndex, setPhaseIndex] = useState(0);
|
|
47
47
|
const [answers, setAnswers] = useState({});
|
|
48
48
|
const [error, setError] = useState("");
|
|
49
|
+
const [liveInput, setLiveInput] = useState("");
|
|
49
50
|
// Prefill tech stack from Stack & Style selections (language + framework)
|
|
50
51
|
const prefillTechStack = [];
|
|
51
52
|
if (initialValues?.language) {
|
|
@@ -59,6 +60,54 @@ export default function ProductContext({ initialValues, onComplete }) {
|
|
|
59
60
|
prefillTechStack.push(match.value);
|
|
60
61
|
}
|
|
61
62
|
const currentPhase = PHASE_ORDER[phaseIndex];
|
|
63
|
+
const isFirst = phaseIndex === 0;
|
|
64
|
+
const isLast = phaseIndex === PHASE_ORDER.length - 1;
|
|
65
|
+
// Reset live input when navigating to a different field
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
setLiveInput("");
|
|
68
|
+
}, [phaseIndex]);
|
|
69
|
+
const isMultiSelectPhase = currentPhase === "techStack" || currentPhase === "coreFeatures";
|
|
70
|
+
useInput((input, key) => {
|
|
71
|
+
if (key.shift && key.tab && phaseIndex > 0) {
|
|
72
|
+
setPhaseIndex((i) => i - 1);
|
|
73
|
+
setError("");
|
|
74
|
+
}
|
|
75
|
+
else if (key.tab && !key.shift && !isMultiSelectPhase) {
|
|
76
|
+
// Tab only advances text phases — multi-select phases use Enter to confirm
|
|
77
|
+
const required = currentPhase === "problem" || currentPhase === "users";
|
|
78
|
+
const val = liveInput.trim() || answers[currentPhase] || "";
|
|
79
|
+
if (required && !val) {
|
|
80
|
+
setError("This field is required");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
setError("");
|
|
84
|
+
const next = { ...answers, [currentPhase]: val };
|
|
85
|
+
setAnswers(next);
|
|
86
|
+
if (phaseIndex < PHASE_ORDER.length - 1) {
|
|
87
|
+
setPhaseIndex((i) => i + 1);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
finalize(next);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
function finalize(data) {
|
|
95
|
+
onComplete({
|
|
96
|
+
problem: data.problem,
|
|
97
|
+
users: data.users,
|
|
98
|
+
techStack: data.techStack,
|
|
99
|
+
coreFeatures: (data.coreFeatures || "")
|
|
100
|
+
.split(",")
|
|
101
|
+
.map((s) => s.trim())
|
|
102
|
+
.filter(Boolean),
|
|
103
|
+
nonGoals: (data.nonGoals || "")
|
|
104
|
+
.split(",")
|
|
105
|
+
.map((s) => s.trim())
|
|
106
|
+
.filter(Boolean),
|
|
107
|
+
userStories: [],
|
|
108
|
+
envVars: [],
|
|
109
|
+
});
|
|
110
|
+
}
|
|
62
111
|
function advanceToNext(key, value) {
|
|
63
112
|
const next = { ...answers, [key]: value };
|
|
64
113
|
setAnswers(next);
|
|
@@ -67,28 +116,14 @@ export default function ProductContext({ initialValues, onComplete }) {
|
|
|
67
116
|
setPhaseIndex(phaseIndex + 1);
|
|
68
117
|
}
|
|
69
118
|
else {
|
|
70
|
-
|
|
71
|
-
problem: next.problem,
|
|
72
|
-
users: next.users,
|
|
73
|
-
techStack: next.techStack,
|
|
74
|
-
coreFeatures: (next.coreFeatures || "")
|
|
75
|
-
.split(",")
|
|
76
|
-
.map((s) => s.trim())
|
|
77
|
-
.filter(Boolean),
|
|
78
|
-
nonGoals: (next.nonGoals || "")
|
|
79
|
-
.split(",")
|
|
80
|
-
.map((s) => s.trim())
|
|
81
|
-
.filter(Boolean),
|
|
82
|
-
userStories: [],
|
|
83
|
-
envVars: [],
|
|
84
|
-
});
|
|
119
|
+
finalize(next);
|
|
85
120
|
}
|
|
86
121
|
}
|
|
87
122
|
function handleTextSubmit(key, required) {
|
|
88
123
|
return (value) => {
|
|
89
124
|
const val = value.trim();
|
|
90
125
|
if (required && !val) {
|
|
91
|
-
setError(
|
|
126
|
+
setError("This field is required");
|
|
92
127
|
return;
|
|
93
128
|
}
|
|
94
129
|
advanceToNext(key, val);
|
|
@@ -105,6 +140,6 @@ export default function ProductContext({ initialValues, onComplete }) {
|
|
|
105
140
|
const usersPlaceholder = answers["problem"]
|
|
106
141
|
? `People affected by: ${answers["problem"]}`
|
|
107
142
|
: "e.g. Developers, PMs, designers...";
|
|
108
|
-
return (_jsxs(_Fragment, { children: [completedFields, currentPhase === "problem" && (_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "What problem does this solve? " }), _jsx(TextInput, { placeholder: "Describe the core problem...", onSubmit: handleTextSubmit("problem", true) })] })), currentPhase === "users" && (_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "Who are the users? " }), _jsx(TextInput, { placeholder: usersPlaceholder, onSubmit: handleTextSubmit("users", true) })] })), currentPhase === "techStack" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Tech stack:" }) }), _jsx(GutteredMultiSelect, { options: TECH_STACK_OPTIONS, initialSelected: prefillTechStack, onSubmit: handleTechStackSubmit })] })), currentPhase === "coreFeatures" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Core features:" }) }), _jsx(GutteredMultiSelect, { options: CORE_FEATURE_OPTIONS, onSubmit: handleCoreFeaturesSubmit, allowCustom: true, customPlaceholder: "e.g. Export PDF, Onboarding flow..." })] })), currentPhase === "nonGoals" && (_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "Non-goals (comma-separated): " }), _jsx(TextInput, { placeholder: "e.g. Mobile app, Real-time sync...", onSubmit: handleTextSubmit("nonGoals", false) })] })), error && (_jsx(GutterLine, { children: _jsx(Text, { color: C.red, children: error }) }))] }));
|
|
143
|
+
return (_jsxs(_Fragment, { children: [completedFields, currentPhase === "problem" && (_jsxs(_Fragment, { children: [_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "What problem does this solve? " }), _jsx(TextInput, { placeholder: "Describe the core problem...", onChange: setLiveInput, onSubmit: handleTextSubmit("problem", true) })] }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Tab next Enter confirm" }) })] })), currentPhase === "users" && (_jsxs(_Fragment, { children: [_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "Who are the users? " }), _jsx(TextInput, { placeholder: usersPlaceholder, onChange: setLiveInput, onSubmit: handleTextSubmit("users", true) })] }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Shift+Tab prev Tab next Enter confirm" }) })] })), currentPhase === "techStack" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Tech stack:" }) }), _jsx(GutteredMultiSelect, { options: TECH_STACK_OPTIONS, initialSelected: prefillTechStack, onSubmit: handleTechStackSubmit }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Shift+Tab prev ↑↓ move Space toggle Enter confirm" }) })] })), currentPhase === "coreFeatures" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Core features:" }) }), _jsx(GutteredMultiSelect, { options: CORE_FEATURE_OPTIONS, onSubmit: handleCoreFeaturesSubmit, allowCustom: true, customPlaceholder: "e.g. Export PDF, Onboarding flow..." }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Shift+Tab prev ↑↓ move Space toggle Enter confirm" }) })] })), currentPhase === "nonGoals" && (_jsxs(_Fragment, { children: [_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "Non-goals (comma-separated): " }), _jsx(TextInput, { placeholder: "e.g. Mobile app, Real-time sync...", onChange: setLiveInput, onSubmit: handleTextSubmit("nonGoals", false) })] }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Shift+Tab prev Tab / Enter confirm" }) })] })), error && (_jsx(GutterLine, { children: _jsx(Text, { color: C.red, children: error }) }))] }));
|
|
109
144
|
}
|
|
110
145
|
//# sourceMappingURL=product-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-context.js","sourceRoot":"","sources":["../../src/steps/product-context.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"product-context.js","sourceRoot":"","sources":["../../src/steps/product-context.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { Text } from "ink";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { Text, useInput } from "ink";
|
|
4
4
|
import { TextInput } from "@inkjs/ui";
|
|
5
5
|
import { GutterLine } from "../components/gutter-line.js";
|
|
6
6
|
import { GutteredSelect } from "../components/guttered-select.js";
|
|
@@ -28,7 +28,34 @@ export default function ProjectInfo({ onComplete }) {
|
|
|
28
28
|
const [stepIndex, setStepIndex] = useState(0);
|
|
29
29
|
const [answers, setAnswers] = useState({});
|
|
30
30
|
const [error, setError] = useState("");
|
|
31
|
+
const [liveInput, setLiveInput] = useState("");
|
|
31
32
|
const currentStep = STEP_ORDER[stepIndex];
|
|
33
|
+
const isFirst = stepIndex === 0;
|
|
34
|
+
// Reset live input when navigating to a different field
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
setLiveInput("");
|
|
37
|
+
}, [stepIndex]);
|
|
38
|
+
const isSelectStep = currentStep === "packageManager" || currentStep === "license";
|
|
39
|
+
useInput((input, key) => {
|
|
40
|
+
if (key.shift && key.tab && stepIndex > 0) {
|
|
41
|
+
setStepIndex((i) => i - 1);
|
|
42
|
+
setError("");
|
|
43
|
+
}
|
|
44
|
+
else if (key.tab && !key.shift && !isSelectStep) {
|
|
45
|
+
// Tab only advances text steps — select steps require an explicit Enter selection
|
|
46
|
+
const val = liveInput.trim() || answers[currentStep] || "";
|
|
47
|
+
if (!val) {
|
|
48
|
+
setError(currentStep === "projectName"
|
|
49
|
+
? "Project name is required"
|
|
50
|
+
: "Description is required");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
setError("");
|
|
54
|
+
const next = { ...answers, [currentStep]: val };
|
|
55
|
+
setAnswers(next);
|
|
56
|
+
setStepIndex((i) => i + 1);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
32
59
|
function advance(key, value) {
|
|
33
60
|
const next = { ...answers, [key]: value };
|
|
34
61
|
setAnswers(next);
|
|
@@ -57,6 +84,6 @@ export default function ProjectInfo({ onComplete }) {
|
|
|
57
84
|
}
|
|
58
85
|
// Render completed fields
|
|
59
86
|
const completed = STEP_ORDER.slice(0, stepIndex).map((key) => (_jsx(GutterLine, { children: _jsxs(Text, { color: C.overlay1, children: [key === "projectName" && `Project name: ${answers[key]}`, key === "description" && `Description: ${answers[key]}`, key === "packageManager" && `Package manager: ${answers[key]}`, key === "license" && `License: ${answers[key]}`] }) }, key)));
|
|
60
|
-
return (_jsxs(_Fragment, { children: [completed, currentStep === "projectName" && (_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "Project name: " }), _jsx(TextInput, { placeholder: "...", onSubmit: handleTextSubmit })] })), currentStep === "description" && (_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "One-line description: " }), _jsx(TextInput, { placeholder: "...", onSubmit: handleTextSubmit })] })), currentStep === "packageManager" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Package manager:" }) }), _jsx(GutteredSelect, { options: PACKAGE_MANAGER_OPTIONS, onChange: handleSelectChange("packageManager") })] })), currentStep === "license" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "License:" }) }), _jsx(GutteredSelect, { options: LICENSE_OPTIONS, onChange: handleSelectChange("license") })] })), error && (_jsx(GutterLine, { children: _jsx(Text, { color: C.red, children: error }) }))] }));
|
|
87
|
+
return (_jsxs(_Fragment, { children: [completed, currentStep === "projectName" && (_jsxs(_Fragment, { children: [_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "Project name: " }), _jsx(TextInput, { placeholder: "...", onChange: setLiveInput, onSubmit: handleTextSubmit })] }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Tab next Enter confirm" }) })] })), currentStep === "description" && (_jsxs(_Fragment, { children: [_jsxs(GutterLine, { children: [_jsx(Text, { bold: true, children: "One-line description: " }), _jsx(TextInput, { placeholder: "...", onChange: setLiveInput, onSubmit: handleTextSubmit })] }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Shift+Tab prev Tab next Enter confirm" }) })] })), currentStep === "packageManager" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "Package manager:" }) }), _jsx(GutteredSelect, { options: PACKAGE_MANAGER_OPTIONS, onChange: handleSelectChange("packageManager") }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Shift+Tab prev ↑↓ move Enter select" }) })] })), currentStep === "license" && (_jsxs(_Fragment, { children: [_jsx(GutterLine, { children: _jsx(Text, { bold: true, children: "License:" }) }), _jsx(GutteredSelect, { options: LICENSE_OPTIONS, onChange: handleSelectChange("license") }), _jsx(GutterLine, { children: _jsx(Text, { color: C.overlay1, children: "Shift+Tab prev ↑↓ move Enter select" }) })] })), error && (_jsx(GutterLine, { children: _jsx(Text, { color: C.red, children: error }) }))] }));
|
|
61
88
|
}
|
|
62
89
|
//# sourceMappingURL=project-info.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-info.js","sourceRoot":"","sources":["../../src/steps/project-info.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"project-info.js","sourceRoot":"","sources":["../../src/steps/project-info.tsx"],"names":[],"mappings":"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"}
|
package/docs/PRD.md
CHANGED
|
@@ -26,8 +26,9 @@ Empower developers to start projects with production-ready documentation and arc
|
|
|
26
26
|
**F-001: Interactive Project Wizard**
|
|
27
27
|
- 7-step guided setup with Catppuccin Mocha timeline UI
|
|
28
28
|
- `┌`/`└` corners wrap the full flow; animated dot on active step
|
|
29
|
-
- Empty-directory guard:
|
|
29
|
+
- Empty-directory guard: warns when cwd has files and continues — Step 6 overwrite confirmation handles conflicts
|
|
30
30
|
- Validates required fields; ESC exits at any point; Enter exits on completion
|
|
31
|
+
- In-step field navigation: `Tab` = next field, `Shift+Tab` = previous field, `Enter` = confirm; `↑`/`↓` retain their option-navigation role inside selects
|
|
31
32
|
|
|
32
33
|
**F-002: CLAUDE.md Generation**
|
|
33
34
|
- Code style and import conventions (from preset or manual config)
|
package/docs/USER-STORIES.md
CHANGED
|
@@ -43,13 +43,13 @@ Scenario: User skips generation
|
|
|
43
43
|
### Feature: Pre-flight Directory Check
|
|
44
44
|
|
|
45
45
|
```gherkin
|
|
46
|
-
Scenario: CLI
|
|
46
|
+
Scenario: CLI warns when directory has existing files and continues
|
|
47
47
|
Given a developer runs `npx @b3awesome/procedure` in a directory with files
|
|
48
48
|
When the CLI starts
|
|
49
|
-
Then
|
|
50
|
-
And
|
|
51
|
-
And
|
|
52
|
-
And
|
|
49
|
+
Then a warning is printed listing up to 3 found files/directories
|
|
50
|
+
And a recommendation to use an empty directory is shown
|
|
51
|
+
And the wizard renders normally so the user can proceed
|
|
52
|
+
And Step 6 (Generation) will list any files that would be overwritten before confirmation
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
```gherkin
|
|
@@ -240,7 +240,67 @@ Scenario: Release script skipped when it already exists
|
|
|
240
240
|
And package.json release scripts are still applied if not already present
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
## US-010:
|
|
243
|
+
## US-010: In-Step Field Navigation
|
|
244
|
+
|
|
245
|
+
**As a** developer who made a typo in a previous field
|
|
246
|
+
**I want** to navigate back and forward between inputs within the current step
|
|
247
|
+
**So that** I can fix mistakes without restarting the step from scratch
|
|
248
|
+
|
|
249
|
+
### Feature: ↑/↓ Field Navigation
|
|
250
|
+
|
|
251
|
+
```gherkin
|
|
252
|
+
Scenario: User navigates back to a previous field within a step
|
|
253
|
+
Given the user is on Step 3 (Build & Test) with "Test command" active
|
|
254
|
+
When they press Shift+Tab
|
|
255
|
+
Then "Build command" becomes active again with its previously saved value restored
|
|
256
|
+
And "Test command" becomes invisible (not yet re-confirmed)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
```gherkin
|
|
260
|
+
Scenario: User navigates forward using Tab
|
|
261
|
+
Given the user has gone back to "Build command" in Step 3
|
|
262
|
+
When they press Tab
|
|
263
|
+
Then the current value (typed or previously saved) is kept
|
|
264
|
+
And "Test command" becomes active again
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
```gherkin
|
|
268
|
+
Scenario: Tab on a required empty field shows error
|
|
269
|
+
Given the user is on "Build command" in Step 3
|
|
270
|
+
And the field is empty with no saved value
|
|
271
|
+
When they press Tab
|
|
272
|
+
Then a validation error is shown
|
|
273
|
+
And the field index does not advance
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
```gherkin
|
|
277
|
+
Scenario: Navigation hint is shown below each input field
|
|
278
|
+
Given the user is on any input field within a step
|
|
279
|
+
When the field renders
|
|
280
|
+
Then a hint line shows the available navigation keys
|
|
281
|
+
And "Shift+Tab prev" is omitted when on the first field
|
|
282
|
+
And "Tab next" is replaced by "Tab / Enter confirm" on the last field
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
```gherkin
|
|
286
|
+
Scenario: Tab and Shift+Tab work on select fields too
|
|
287
|
+
Given the user is on "Package manager" select (Step 1)
|
|
288
|
+
When they press Shift+Tab
|
|
289
|
+
Then the "Description" text input becomes active again
|
|
290
|
+
When they press Tab
|
|
291
|
+
Then the "License" select becomes active
|
|
292
|
+
And ↑↓ continue to navigate options within the select as normal
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```gherkin
|
|
296
|
+
Scenario: Shift+Tab in Setup step navigates between confirm questions
|
|
297
|
+
Given the user is on the "Initialize git repo?" question in Step 7
|
|
298
|
+
When they press Shift+Tab
|
|
299
|
+
Then the "Set up Powerline?" question is shown again
|
|
300
|
+
And the user can re-answer it
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## US-011: Escape and Graceful Exit
|
|
244
304
|
|
|
245
305
|
**As a** developer who changed their mind
|
|
246
306
|
**I want** to exit the wizard at any point
|
package/package.json
CHANGED
package/src/steps/build-test.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { Text } from "ink";
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import { Text, useInput } from "ink";
|
|
3
3
|
import { TextInput } from "@inkjs/ui";
|
|
4
4
|
import { GutterLine } from "../components/gutter-line.js";
|
|
5
5
|
import type { WizardAnswers } from "../lib/types.js";
|
|
@@ -29,23 +29,47 @@ export default function BuildTest({ initialValues, onComplete }: Props) {
|
|
|
29
29
|
const [fieldIndex, setFieldIndex] = useState(0);
|
|
30
30
|
const [answers, setAnswers] = useState<Record<string, string>>({});
|
|
31
31
|
const [error, setError] = useState("");
|
|
32
|
+
const [liveInput, setLiveInput] = useState("");
|
|
32
33
|
|
|
33
34
|
const current = FIELDS[fieldIndex]!;
|
|
34
35
|
const preset = initialValues?.[current.key] as string | undefined;
|
|
35
36
|
const defaultVal = preset || current.fallback;
|
|
36
37
|
|
|
38
|
+
// Reset live input when navigating to a different field
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
setLiveInput("");
|
|
41
|
+
}, [fieldIndex]);
|
|
42
|
+
|
|
43
|
+
useInput((input, key) => {
|
|
44
|
+
if (key.shift && key.tab && fieldIndex > 0) {
|
|
45
|
+
setFieldIndex((f) => f - 1);
|
|
46
|
+
setError("");
|
|
47
|
+
} else if (key.tab && !key.shift) {
|
|
48
|
+
const val = liveInput.trim() || answers[current.key] || defaultVal;
|
|
49
|
+
if (current.required && !val.trim()) {
|
|
50
|
+
setError(`${current.label} is required`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
setError("");
|
|
54
|
+
const next = { ...answers, [current.key]: val };
|
|
55
|
+
setAnswers(next);
|
|
56
|
+
if (fieldIndex < FIELDS.length - 1) {
|
|
57
|
+
setFieldIndex((f) => f + 1);
|
|
58
|
+
} else {
|
|
59
|
+
onComplete(next as unknown as Partial<WizardAnswers>);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
37
64
|
function handleSubmit(value: string) {
|
|
38
65
|
const val = value.trim() || defaultVal;
|
|
39
|
-
|
|
40
66
|
if (current.required && !val) {
|
|
41
67
|
setError(`${current.label} is required`);
|
|
42
68
|
return;
|
|
43
69
|
}
|
|
44
|
-
|
|
45
70
|
setError("");
|
|
46
71
|
const next = { ...answers, [current.key]: val };
|
|
47
72
|
setAnswers(next);
|
|
48
|
-
|
|
49
73
|
if (fieldIndex < FIELDS.length - 1) {
|
|
50
74
|
setFieldIndex(fieldIndex + 1);
|
|
51
75
|
} else {
|
|
@@ -53,6 +77,9 @@ export default function BuildTest({ initialValues, onComplete }: Props) {
|
|
|
53
77
|
}
|
|
54
78
|
}
|
|
55
79
|
|
|
80
|
+
const isFirst = fieldIndex === 0;
|
|
81
|
+
const isLast = fieldIndex === FIELDS.length - 1;
|
|
82
|
+
|
|
56
83
|
return (
|
|
57
84
|
<>
|
|
58
85
|
{FIELDS.slice(0, fieldIndex).map((f) => (
|
|
@@ -67,13 +94,21 @@ export default function BuildTest({ initialValues, onComplete }: Props) {
|
|
|
67
94
|
<Text bold>{current.label}</Text>
|
|
68
95
|
<Text color={C.overlay1}> ({defaultVal})</Text>
|
|
69
96
|
<Text bold>: </Text>
|
|
70
|
-
<TextInput placeholder={defaultVal} onSubmit={handleSubmit} />
|
|
97
|
+
<TextInput placeholder={defaultVal} onChange={setLiveInput} onSubmit={handleSubmit} />
|
|
71
98
|
</GutterLine>
|
|
99
|
+
|
|
72
100
|
{error && (
|
|
73
101
|
<GutterLine>
|
|
74
102
|
<Text color={C.red}>{error}</Text>
|
|
75
103
|
</GutterLine>
|
|
76
104
|
)}
|
|
105
|
+
|
|
106
|
+
<GutterLine>
|
|
107
|
+
<Text color={C.overlay1}>
|
|
108
|
+
{!isFirst ? "Shift+Tab prev " : ""}
|
|
109
|
+
{isLast ? "Tab / Enter confirm" : "Tab next Enter confirm"}
|
|
110
|
+
</Text>
|
|
111
|
+
</GutterLine>
|
|
77
112
|
</>
|
|
78
113
|
);
|
|
79
114
|
}
|
package/src/steps/powerline.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
-
import { Text } from "ink";
|
|
2
|
+
import { Text, useInput } from "ink";
|
|
3
3
|
import { ConfirmInput, Spinner } from "@inkjs/ui";
|
|
4
4
|
import { GutterLine } from "../components/gutter-line.js";
|
|
5
5
|
import { setupPowerline } from "../lib/powerline.js";
|
|
@@ -38,6 +38,16 @@ export default function Powerline({ answers, onComplete }: Props) {
|
|
|
38
38
|
const [errorMsg, setErrorMsg] = useState("");
|
|
39
39
|
const [setupResult, setSetupResult] = useState<SetupResult>({});
|
|
40
40
|
|
|
41
|
+
useInput(
|
|
42
|
+
(input, key) => {
|
|
43
|
+
if (key.shift && key.tab) {
|
|
44
|
+
if (phase === "ask-git") setPhase("ask-powerline");
|
|
45
|
+
else if (phase === "ask-release") setPhase("ask-git");
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{ isActive: phase === "ask-git" || phase === "ask-release" }
|
|
49
|
+
);
|
|
50
|
+
|
|
41
51
|
function runSetup(powerline: boolean, git: boolean, release: boolean) {
|
|
42
52
|
setPhase("running");
|
|
43
53
|
try {
|
|
@@ -129,6 +139,9 @@ export default function Powerline({ answers, onComplete }: Props) {
|
|
|
129
139
|
onCancel={() => { setWantGit(false); setPhase("ask-release"); }}
|
|
130
140
|
/>
|
|
131
141
|
</GutterLine>
|
|
142
|
+
<GutterLine>
|
|
143
|
+
<Text color={C.overlay1}>{"Shift+Tab prev y/n answer"}</Text>
|
|
144
|
+
</GutterLine>
|
|
132
145
|
</>
|
|
133
146
|
);
|
|
134
147
|
}
|
|
@@ -173,6 +186,9 @@ export default function Powerline({ answers, onComplete }: Props) {
|
|
|
173
186
|
onCancel={() => { setWantRelease(false); runSetup(wantPowerline, wantGit, false); }}
|
|
174
187
|
/>
|
|
175
188
|
</GutterLine>
|
|
189
|
+
<GutterLine>
|
|
190
|
+
<Text color={C.overlay1}>{"Shift+Tab prev y/n answer"}</Text>
|
|
191
|
+
</GutterLine>
|
|
176
192
|
</>
|
|
177
193
|
);
|
|
178
194
|
}
|