ccmanager 3.5.0 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/components/App.d.ts +1 -0
- package/dist/components/App.js +17 -39
- package/dist/components/App.test.js +12 -44
- package/dist/components/Configuration.js +10 -15
- package/dist/components/ConfigureCommand.js +18 -106
- package/dist/components/ConfigureCustomCommand.js +2 -17
- package/dist/components/ConfigureOther.js +5 -23
- package/dist/components/ConfigureOther.test.js +7 -31
- package/dist/components/ConfigureShortcuts.js +4 -31
- package/dist/components/ConfigureStatusHooks.js +5 -44
- package/dist/components/ConfigureStatusHooks.test.js +7 -31
- package/dist/components/ConfigureTimeout.js +2 -14
- package/dist/components/ConfigureWorktree.js +4 -47
- package/dist/components/ConfigureWorktreeHooks.js +5 -37
- package/dist/components/ConfigureWorktreeHooks.test.js +8 -33
- package/dist/components/Confirmation.js +9 -21
- package/dist/components/CustomCommandSummary.js +2 -5
- package/dist/components/DeleteConfirmation.js +10 -47
- package/dist/components/DeleteWorktree.js +14 -42
- package/dist/components/DeleteWorktree.test.js +6 -6
- package/dist/components/LoadingSpinner.js +3 -6
- package/dist/components/LoadingSpinner.test.js +22 -22
- package/dist/components/Menu.d.ts +1 -0
- package/dist/components/Menu.js +10 -42
- package/dist/components/Menu.recent-projects.test.js +8 -8
- package/dist/components/Menu.test.js +10 -10
- package/dist/components/MergeWorktree.js +16 -88
- package/dist/components/MergeWorktree.test.js +5 -5
- package/dist/components/NewWorktree.js +25 -105
- package/dist/components/NewWorktree.test.js +8 -8
- package/dist/components/PresetSelector.js +3 -9
- package/dist/components/ProjectList.js +9 -38
- package/dist/components/ProjectList.recent-projects.test.js +7 -7
- package/dist/components/ProjectList.test.js +37 -37
- package/dist/components/RemoteBranchSelector.js +2 -21
- package/dist/components/RemoteBranchSelector.test.js +8 -8
- package/dist/components/TextInputWrapper.d.ts +5 -0
- package/dist/components/TextInputWrapper.js +138 -11
- package/dist/constants/statusIcons.d.ts +2 -1
- package/dist/constants/statusIcons.js +13 -4
- package/dist/constants/statusIcons.test.js +41 -11
- package/dist/contexts/ConfigEditorContext.d.ts +1 -1
- package/dist/contexts/ConfigEditorContext.js +3 -2
- package/dist/services/autoApprovalVerifier.js +1 -8
- package/dist/services/bunTerminal.js +41 -136
- package/dist/services/config/configEditor.js +2 -12
- package/dist/services/config/globalConfigManager.js +4 -24
- package/dist/services/config/projectConfigManager.js +3 -18
- package/dist/services/globalSessionOrchestrator.js +3 -12
- package/dist/services/globalSessionOrchestrator.test.js +1 -8
- package/dist/services/projectManager.js +13 -68
- package/dist/services/sessionManager.d.ts +1 -1
- package/dist/services/sessionManager.effect.test.js +9 -37
- package/dist/services/sessionManager.js +12 -28
- package/dist/services/sessionManager.test.js +48 -40
- package/dist/services/shortcutManager.js +7 -13
- package/dist/services/stateDetector/base.d.ts +1 -1
- package/dist/services/stateDetector/claude.d.ts +1 -1
- package/dist/services/stateDetector/claude.js +11 -4
- package/dist/services/stateDetector/claude.test.js +47 -24
- package/dist/services/stateDetector/cline.d.ts +1 -1
- package/dist/services/stateDetector/cline.js +1 -1
- package/dist/services/stateDetector/codex.d.ts +1 -1
- package/dist/services/stateDetector/codex.js +1 -1
- package/dist/services/stateDetector/cursor.d.ts +1 -1
- package/dist/services/stateDetector/cursor.js +1 -1
- package/dist/services/stateDetector/gemini.d.ts +1 -1
- package/dist/services/stateDetector/gemini.js +1 -1
- package/dist/services/stateDetector/github-copilot.d.ts +1 -1
- package/dist/services/stateDetector/github-copilot.js +1 -1
- package/dist/services/stateDetector/opencode.d.ts +1 -1
- package/dist/services/stateDetector/opencode.js +1 -1
- package/dist/services/stateDetector/types.d.ts +1 -1
- package/dist/services/worktreeConfigManager.js +3 -8
- package/dist/services/worktreeService.js +2 -12
- package/dist/types/index.js +4 -12
- package/dist/utils/logger.js +12 -33
- package/dist/utils/mutex.d.ts +1 -1
- package/dist/utils/mutex.js +4 -19
- package/dist/utils/worktreeUtils.js +4 -4
- package/package.json +12 -12
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
2
3
|
import { Box, Text, useInput } from 'ink';
|
|
3
4
|
import SelectInput from 'ink-select-input';
|
|
4
5
|
import { Effect } from 'effect';
|
|
@@ -99,116 +100,43 @@ const MergeWorktree = ({ onComplete, onCancel, }) => {
|
|
|
99
100
|
performMerge();
|
|
100
101
|
}, [step, sourceBranch, targetBranch, useRebase, worktreeService]);
|
|
101
102
|
if (isLoading) {
|
|
102
|
-
return (
|
|
103
|
-
React.createElement(Text, { color: "cyan" }, "Loading worktrees...")));
|
|
103
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { color: "cyan", children: "Loading worktrees..." }) }));
|
|
104
104
|
}
|
|
105
105
|
if (loadError) {
|
|
106
|
-
return (
|
|
107
|
-
React.createElement(Text, { color: "red" }, "Error loading worktrees:"),
|
|
108
|
-
React.createElement(Text, { color: "red" }, loadError),
|
|
109
|
-
React.createElement(Box, { marginTop: 1 },
|
|
110
|
-
React.createElement(Text, { dimColor: true },
|
|
111
|
-
"Press ",
|
|
112
|
-
shortcutManager.getShortcutDisplay('cancel'),
|
|
113
|
-
" to return to menu"))));
|
|
106
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", children: "Error loading worktrees:" }), _jsx(Text, { color: "red", children: loadError }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to return to menu"] }) })] }));
|
|
114
107
|
}
|
|
115
108
|
if (step === 'select-source') {
|
|
116
|
-
return (
|
|
117
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
118
|
-
React.createElement(Text, { bold: true, color: "green" }, "Merge Worktree")),
|
|
119
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
120
|
-
React.createElement(Text, null, "Select the source branch to merge:")),
|
|
121
|
-
React.createElement(SelectInput, { items: branchItems, onSelect: handleSelectSource, isFocused: true, limit: 10 }),
|
|
122
|
-
React.createElement(Box, { marginTop: 1 },
|
|
123
|
-
React.createElement(Text, { dimColor: true },
|
|
124
|
-
"Press ",
|
|
125
|
-
shortcutManager.getShortcutDisplay('cancel'),
|
|
126
|
-
" to cancel"))));
|
|
109
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Merge Worktree" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Select the source branch to merge:" }) }), _jsx(SelectInput, { items: branchItems, onSelect: handleSelectSource, isFocused: true, limit: 10 }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
|
|
127
110
|
}
|
|
128
111
|
if (step === 'select-target') {
|
|
129
|
-
return (
|
|
130
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
131
|
-
React.createElement(Text, { bold: true, color: "green" }, "Merge Worktree")),
|
|
132
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
133
|
-
React.createElement(Text, null,
|
|
134
|
-
"Merging from: ",
|
|
135
|
-
React.createElement(Text, { color: "yellow" }, sourceBranch))),
|
|
136
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
137
|
-
React.createElement(Text, null, "Select the target branch to merge into:")),
|
|
138
|
-
React.createElement(SelectInput, { items: branchItems, onSelect: handleSelectTarget, isFocused: true, limit: 10 }),
|
|
139
|
-
React.createElement(Box, { marginTop: 1 },
|
|
140
|
-
React.createElement(Text, { dimColor: true },
|
|
141
|
-
"Press ",
|
|
142
|
-
shortcutManager.getShortcutDisplay('cancel'),
|
|
143
|
-
" to cancel"))));
|
|
112
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Merge Worktree" }) }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Merging from: ", _jsx(Text, { color: "yellow", children: sourceBranch })] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Select the target branch to merge into:" }) }), _jsx(SelectInput, { items: branchItems, onSelect: handleSelectTarget, isFocused: true, limit: 10 }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
|
|
144
113
|
}
|
|
145
114
|
if (step === 'select-operation') {
|
|
146
|
-
const title = (
|
|
147
|
-
const message = (
|
|
148
|
-
|
|
149
|
-
React.createElement(Text, { color: "yellow" }, sourceBranch),
|
|
150
|
-
" into",
|
|
151
|
-
' ',
|
|
152
|
-
React.createElement(Text, { color: "yellow" }, targetBranch),
|
|
153
|
-
":"));
|
|
154
|
-
const hint = (React.createElement(Text, { dimColor: true },
|
|
155
|
-
"Use \u2191\u2193/j/k to navigate, Enter to select,",
|
|
156
|
-
' ',
|
|
157
|
-
shortcutManager.getShortcutDisplay('cancel'),
|
|
158
|
-
" to cancel"));
|
|
115
|
+
const title = (_jsx(Text, { bold: true, color: "green", children: "Select Operation" }));
|
|
116
|
+
const message = (_jsxs(Text, { children: ["Choose how to integrate ", _jsx(Text, { color: "yellow", children: sourceBranch }), " into", ' ', _jsx(Text, { color: "yellow", children: targetBranch }), ":"] }));
|
|
117
|
+
const hint = (_jsxs(Text, { dimColor: true, children: ["Use \u2191\u2193/j/k to navigate, Enter to select,", ' ', shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }));
|
|
159
118
|
const handleOperationSelect = (value) => {
|
|
160
119
|
setUseRebase(value === 'rebase');
|
|
161
120
|
setStep('confirm-merge');
|
|
162
121
|
};
|
|
163
|
-
return (
|
|
122
|
+
return (_jsx(Confirmation, { title: title, message: message, options: [
|
|
164
123
|
{ label: 'Merge', value: 'merge', color: 'green' },
|
|
165
124
|
{ label: 'Rebase', value: 'rebase', color: 'blue' },
|
|
166
125
|
], onSelect: handleOperationSelect, initialIndex: 0, hint: hint }));
|
|
167
126
|
}
|
|
168
127
|
if (step === 'confirm-merge') {
|
|
169
|
-
const confirmMessage = (
|
|
170
|
-
|
|
171
|
-
React.createElement(Text, { bold: true, color: "green" },
|
|
172
|
-
"Confirm ",
|
|
173
|
-
useRebase ? 'Rebase' : 'Merge')),
|
|
174
|
-
React.createElement(Text, null,
|
|
175
|
-
useRebase ? 'Rebase' : 'Merge',
|
|
176
|
-
' ',
|
|
177
|
-
React.createElement(Text, { color: "yellow" }, sourceBranch),
|
|
178
|
-
' ',
|
|
179
|
-
useRebase ? 'onto' : 'into',
|
|
180
|
-
' ',
|
|
181
|
-
React.createElement(Text, { color: "yellow" }, targetBranch),
|
|
182
|
-
"?")));
|
|
183
|
-
return (React.createElement(SimpleConfirmation, { message: confirmMessage, onConfirm: () => setStep('executing-merge'), onCancel: onCancel }));
|
|
128
|
+
const confirmMessage = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "green", children: ["Confirm ", useRebase ? 'Rebase' : 'Merge'] }) }), _jsxs(Text, { children: [useRebase ? 'Rebase' : 'Merge', ' ', _jsx(Text, { color: "yellow", children: sourceBranch }), ' ', useRebase ? 'onto' : 'into', ' ', _jsx(Text, { color: "yellow", children: targetBranch }), "?"] })] }));
|
|
129
|
+
return (_jsx(SimpleConfirmation, { message: confirmMessage, onConfirm: () => setStep('executing-merge'), onCancel: onCancel }));
|
|
184
130
|
}
|
|
185
131
|
if (step === 'executing-merge') {
|
|
186
|
-
return (
|
|
187
|
-
React.createElement(Text, { color: "green" },
|
|
188
|
-
useRebase ? 'Rebasing' : 'Merging',
|
|
189
|
-
" branches...")));
|
|
132
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { color: "green", children: [useRebase ? 'Rebasing' : 'Merging', " branches..."] }) }));
|
|
190
133
|
}
|
|
191
134
|
if (step === 'merge-error') {
|
|
192
|
-
return (
|
|
193
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
194
|
-
React.createElement(Text, { bold: true, color: "red" },
|
|
195
|
-
useRebase ? 'Rebase' : 'Merge',
|
|
196
|
-
" Failed")),
|
|
197
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
198
|
-
React.createElement(Text, { color: "red" }, mergeError)),
|
|
199
|
-
React.createElement(Box, { marginTop: 1 },
|
|
200
|
-
React.createElement(Text, { dimColor: true }, "Press any key to return to menu"))));
|
|
135
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "red", children: [useRebase ? 'Rebase' : 'Merge', " Failed"] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: mergeError }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press any key to return to menu" }) })] }));
|
|
201
136
|
}
|
|
202
137
|
if (step === 'delete-confirm') {
|
|
203
|
-
const deleteMessage = (
|
|
204
|
-
|
|
205
|
-
React.createElement(Text, { bold: true, color: "green" }, "Delete Source Branch?")),
|
|
206
|
-
React.createElement(Text, null,
|
|
207
|
-
"Delete the merged branch ",
|
|
208
|
-
React.createElement(Text, { color: "yellow" }, sourceBranch),
|
|
209
|
-
' ',
|
|
210
|
-
"and its worktree?")));
|
|
211
|
-
return (React.createElement(SimpleConfirmation, { message: deleteMessage, onConfirm: async () => {
|
|
138
|
+
const deleteMessage = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Delete Source Branch?" }) }), _jsxs(Text, { children: ["Delete the merged branch ", _jsx(Text, { color: "yellow", children: sourceBranch }), ' ', "and its worktree?"] })] }));
|
|
139
|
+
return (_jsx(SimpleConfirmation, { message: deleteMessage, onConfirm: async () => {
|
|
212
140
|
try {
|
|
213
141
|
// Find the worktree path for the source branch
|
|
214
142
|
const worktrees = await Effect.runPromise(worktreeService.getWorktreesEffect());
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { render } from 'ink-testing-library';
|
|
3
3
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
4
4
|
import { Effect } from 'effect';
|
|
@@ -66,7 +66,7 @@ describe('MergeWorktree - Effect Integration', () => {
|
|
|
66
66
|
const onComplete = vi.fn();
|
|
67
67
|
const onCancel = vi.fn();
|
|
68
68
|
// WHEN: Component is rendered
|
|
69
|
-
const { lastFrame } = render(
|
|
69
|
+
const { lastFrame } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
70
70
|
// Wait for Effect to execute
|
|
71
71
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
72
72
|
// THEN: Effect method should be called
|
|
@@ -105,7 +105,7 @@ describe('MergeWorktree - Effect Integration', () => {
|
|
|
105
105
|
const onComplete = vi.fn();
|
|
106
106
|
const onCancel = vi.fn();
|
|
107
107
|
// WHEN: Component renders and user selects branches
|
|
108
|
-
const { stdin } = render(
|
|
108
|
+
const { stdin } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
109
109
|
// Wait for initial load
|
|
110
110
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
111
111
|
// Simulate selecting source branch (Enter key)
|
|
@@ -162,7 +162,7 @@ describe('MergeWorktree - Effect Integration', () => {
|
|
|
162
162
|
const onComplete = vi.fn();
|
|
163
163
|
const onCancel = vi.fn();
|
|
164
164
|
// WHEN: Component renders and attempts merge
|
|
165
|
-
const { stdin, lastFrame } = render(
|
|
165
|
+
const { stdin, lastFrame } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
166
166
|
// Wait for initial load
|
|
167
167
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
168
168
|
// Go through merge flow
|
|
@@ -216,7 +216,7 @@ describe('MergeWorktree - Effect Integration', () => {
|
|
|
216
216
|
const onComplete = vi.fn();
|
|
217
217
|
const onCancel = vi.fn();
|
|
218
218
|
// WHEN: Component renders and completes merge with delete
|
|
219
|
-
const { stdin } = render(
|
|
219
|
+
const { stdin } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
220
220
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
221
221
|
stdin.write('\r'); // Select source
|
|
222
222
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useMemo, useEffect } from 'react';
|
|
2
3
|
import { Box, Text, useInput } from 'ink';
|
|
3
4
|
import TextInputWrapper from './TextInputWrapper.js';
|
|
4
5
|
import SelectInput from 'ink-select-input';
|
|
@@ -164,113 +165,32 @@ const NewWorktree = ({ projectPath, onComplete, onCancel, }) => {
|
|
|
164
165
|
};
|
|
165
166
|
// Show loading indicator while branches load
|
|
166
167
|
if (isLoadingBranches) {
|
|
167
|
-
return (
|
|
168
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
169
|
-
React.createElement(Text, { bold: true, color: "green" }, "Create New Worktree")),
|
|
170
|
-
React.createElement(Box, null,
|
|
171
|
-
React.createElement(Text, null, "Loading branches...")),
|
|
172
|
-
React.createElement(Box, { marginTop: 1 },
|
|
173
|
-
React.createElement(Text, { dimColor: true },
|
|
174
|
-
"Press ",
|
|
175
|
-
shortcutManager.getShortcutDisplay('cancel'),
|
|
176
|
-
" to cancel"))));
|
|
168
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Create New Worktree" }) }), _jsx(Box, { children: _jsx(Text, { children: "Loading branches..." }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
|
|
177
169
|
}
|
|
178
170
|
// Show error message if branch loading failed
|
|
179
171
|
if (branchLoadError) {
|
|
180
|
-
return (
|
|
181
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
182
|
-
React.createElement(Text, { bold: true, color: "green" }, "Create New Worktree")),
|
|
183
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
184
|
-
React.createElement(Text, { color: "red" }, "Error loading branches:")),
|
|
185
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
186
|
-
React.createElement(Text, { color: "red" }, branchLoadError)),
|
|
187
|
-
React.createElement(Box, { marginTop: 1 },
|
|
188
|
-
React.createElement(Text, { dimColor: true },
|
|
189
|
-
"Press ",
|
|
190
|
-
shortcutManager.getShortcutDisplay('cancel'),
|
|
191
|
-
" to go back"))));
|
|
172
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Create New Worktree" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: "Error loading branches:" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: branchLoadError }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to go back"] }) })] }));
|
|
192
173
|
}
|
|
193
|
-
return (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
!isSearchMode && (React.createElement(Box, { marginTop: 1 },
|
|
215
|
-
React.createElement(Text, { dimColor: true }, "Press / to search"))))),
|
|
216
|
-
step === 'branch-strategy' && (React.createElement(Box, { flexDirection: "column" },
|
|
217
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
218
|
-
React.createElement(Text, null,
|
|
219
|
-
"Base branch: ",
|
|
220
|
-
React.createElement(Text, { color: "cyan" }, baseBranch))),
|
|
221
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
222
|
-
React.createElement(Text, null, "Choose branch creation strategy:")),
|
|
223
|
-
React.createElement(SelectInput, { items: [
|
|
224
|
-
{
|
|
225
|
-
label: 'Create new branch from base branch',
|
|
226
|
-
value: 'new',
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
label: 'Use existing base branch',
|
|
230
|
-
value: 'existing',
|
|
231
|
-
},
|
|
232
|
-
], onSelect: handleBranchStrategySelect, initialIndex: 0 }))),
|
|
233
|
-
step === 'branch' && (React.createElement(Box, { flexDirection: "column" },
|
|
234
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
235
|
-
React.createElement(Text, null,
|
|
236
|
-
"Enter new branch name (will be created from",
|
|
237
|
-
' ',
|
|
238
|
-
React.createElement(Text, { color: "cyan" }, baseBranch),
|
|
239
|
-
"):")),
|
|
240
|
-
React.createElement(Box, null,
|
|
241
|
-
React.createElement(Text, { color: "cyan" }, '> '),
|
|
242
|
-
React.createElement(TextInputWrapper, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })),
|
|
243
|
-
isAutoDirectory && generatedPath && (React.createElement(Box, { marginTop: 1 },
|
|
244
|
-
React.createElement(Text, { dimColor: true },
|
|
245
|
-
"Worktree will be created at:",
|
|
246
|
-
' ',
|
|
247
|
-
React.createElement(Text, { color: "green" }, generatedPath)))))),
|
|
248
|
-
step === 'copy-settings' && (React.createElement(Box, { flexDirection: "column" },
|
|
249
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
250
|
-
React.createElement(Text, null,
|
|
251
|
-
"Copy .claude directory from base branch (",
|
|
252
|
-
React.createElement(Text, { color: "cyan" }, baseBranch),
|
|
253
|
-
")?")),
|
|
254
|
-
React.createElement(SelectInput, { items: [
|
|
255
|
-
{
|
|
256
|
-
label: 'Yes - Copy .claude directory from base branch',
|
|
257
|
-
value: true,
|
|
258
|
-
},
|
|
259
|
-
{ label: 'No - Start without .claude directory', value: false },
|
|
260
|
-
], onSelect: handleCopySettingsSelect, initialIndex: 0 }))),
|
|
261
|
-
step === 'copy-session' && (React.createElement(Box, { flexDirection: "column" },
|
|
262
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
263
|
-
React.createElement(Text, null, "Copy Claude Code session data to the new worktree?")),
|
|
264
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
265
|
-
React.createElement(Text, { dimColor: true }, "This will copy conversation history and context from the current worktree")),
|
|
266
|
-
React.createElement(SelectInput, { items: [
|
|
267
|
-
{ label: '✅ Yes, copy session data', value: 'yes' },
|
|
268
|
-
{ label: '❌ No, start fresh', value: 'no' },
|
|
269
|
-
], onSelect: handleCopySessionSelect, initialIndex: copySessionData ? 0 : 1 }))),
|
|
270
|
-
React.createElement(Box, { marginTop: 1 },
|
|
271
|
-
React.createElement(Text, { dimColor: true },
|
|
272
|
-
"Press ",
|
|
273
|
-
shortcutManager.getShortcutDisplay('cancel'),
|
|
274
|
-
" to cancel"))));
|
|
174
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Create New Worktree" }) }), step === 'path' && !isAutoDirectory ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Enter worktree path (relative to repository root):" }) }), _jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '> ' }), _jsx(TextInputWrapper, { value: path, onChange: setPath, onSubmit: handlePathSubmit, placeholder: "e.g., ../myproject-feature" })] })] })) : null, step === 'base-branch' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Select base branch for the worktree:" }) }), isSearchMode && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { children: "Search: " }), _jsx(TextInputWrapper, { value: searchQuery, onChange: setSearchQuery, focus: true, placeholder: "Type to filter branches..." })] })), isSearchMode && branchItems.length === 0 ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "No branches match your search" }) })) : isSearchMode ? (
|
|
175
|
+
// In search mode, show the items as a list without SelectInput
|
|
176
|
+
_jsx(Box, { flexDirection: "column", children: branchItems.slice(0, limit).map((item, index) => (_jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', item.label] }, item.value))) })) : (_jsx(SelectInput, { items: branchItems, onSelect: handleBaseBranchSelect, initialIndex: selectedIndex, limit: limit, isFocused: !isSearchMode })), !isSearchMode && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press / to search" }) }))] })), step === 'branch-strategy' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Base branch: ", _jsx(Text, { color: "cyan", children: baseBranch })] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Choose branch creation strategy:" }) }), _jsx(SelectInput, { items: [
|
|
177
|
+
{
|
|
178
|
+
label: 'Create new branch from base branch',
|
|
179
|
+
value: 'new',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
label: 'Use existing base branch',
|
|
183
|
+
value: 'existing',
|
|
184
|
+
},
|
|
185
|
+
], onSelect: handleBranchStrategySelect, initialIndex: 0 })] })), step === 'branch' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Enter new branch name (will be created from", ' ', _jsx(Text, { color: "cyan", children: baseBranch }), "):"] }) }), _jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '> ' }), _jsx(TextInputWrapper, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })] }), isAutoDirectory && generatedPath && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Worktree will be created at:", ' ', _jsx(Text, { color: "green", children: generatedPath })] }) }))] })), step === 'copy-settings' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Copy .claude directory from base branch (", _jsx(Text, { color: "cyan", children: baseBranch }), ")?"] }) }), _jsx(SelectInput, { items: [
|
|
186
|
+
{
|
|
187
|
+
label: 'Yes - Copy .claude directory from base branch',
|
|
188
|
+
value: true,
|
|
189
|
+
},
|
|
190
|
+
{ label: 'No - Start without .claude directory', value: false },
|
|
191
|
+
], onSelect: handleCopySettingsSelect, initialIndex: 0 })] })), step === 'copy-session' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Copy Claude Code session data to the new worktree?" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "This will copy conversation history and context from the current worktree" }) }), _jsx(SelectInput, { items: [
|
|
192
|
+
{ label: '✅ Yes, copy session data', value: 'yes' },
|
|
193
|
+
{ label: '❌ No, start fresh', value: 'no' },
|
|
194
|
+
], onSelect: handleCopySessionSelect, initialIndex: copySessionData ? 0 : 1 })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
|
|
275
195
|
};
|
|
276
196
|
export default NewWorktree;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { render } from 'ink-testing-library';
|
|
3
3
|
import NewWorktree from './NewWorktree.js';
|
|
4
4
|
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
@@ -89,7 +89,7 @@ describe('NewWorktree component Effect integration', () => {
|
|
|
89
89
|
});
|
|
90
90
|
const onComplete = vi.fn();
|
|
91
91
|
const onCancel = vi.fn();
|
|
92
|
-
const { lastFrame } = render(
|
|
92
|
+
const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
93
93
|
// Should immediately show loading state
|
|
94
94
|
const output = lastFrame();
|
|
95
95
|
expect(output).toContain('Loading branches...');
|
|
@@ -114,7 +114,7 @@ describe('NewWorktree component Effect integration', () => {
|
|
|
114
114
|
});
|
|
115
115
|
const onComplete = vi.fn();
|
|
116
116
|
const onCancel = vi.fn();
|
|
117
|
-
const { lastFrame } = render(
|
|
117
|
+
const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
118
118
|
// Wait for Effect to execute
|
|
119
119
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
120
120
|
const output = lastFrame();
|
|
@@ -138,7 +138,7 @@ describe('NewWorktree component Effect integration', () => {
|
|
|
138
138
|
});
|
|
139
139
|
const onComplete = vi.fn();
|
|
140
140
|
const onCancel = vi.fn();
|
|
141
|
-
render(
|
|
141
|
+
render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
142
142
|
// Wait for Effect to execute
|
|
143
143
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
144
144
|
// Verify both Effect-based methods were called (parallel execution via Effect.all)
|
|
@@ -164,7 +164,7 @@ describe('NewWorktree component Effect integration', () => {
|
|
|
164
164
|
});
|
|
165
165
|
const onComplete = vi.fn();
|
|
166
166
|
const onCancel = vi.fn();
|
|
167
|
-
const { lastFrame } = render(
|
|
167
|
+
const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
168
168
|
// Wait for Effect to execute
|
|
169
169
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
170
170
|
const output = lastFrame();
|
|
@@ -191,7 +191,7 @@ describe('NewWorktree component Effect integration', () => {
|
|
|
191
191
|
});
|
|
192
192
|
const onComplete = vi.fn();
|
|
193
193
|
const onCancel = vi.fn();
|
|
194
|
-
const { lastFrame } = render(
|
|
194
|
+
const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
195
195
|
// Wait for Effect to execute
|
|
196
196
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
197
197
|
const output = lastFrame();
|
|
@@ -221,7 +221,7 @@ describe('NewWorktree component Effect integration', () => {
|
|
|
221
221
|
});
|
|
222
222
|
const onComplete = vi.fn();
|
|
223
223
|
const onCancel = vi.fn();
|
|
224
|
-
const { lastFrame } = render(
|
|
224
|
+
const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
225
225
|
// Wait for Effect to execute
|
|
226
226
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
227
227
|
const output = lastFrame();
|
|
@@ -253,7 +253,7 @@ describe('NewWorktree component Effect integration', () => {
|
|
|
253
253
|
});
|
|
254
254
|
const onComplete = vi.fn();
|
|
255
255
|
const onCancel = vi.fn();
|
|
256
|
-
render(
|
|
256
|
+
render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
|
|
257
257
|
// Wait for Effect to execute
|
|
258
258
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
259
259
|
// Verify Effect was executed (Effect.match pattern)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
import { Box, Text, useInput } from 'ink';
|
|
3
4
|
import SelectInput from 'ink-select-input';
|
|
4
5
|
import { configReader } from '../services/config/configReader.js';
|
|
@@ -40,13 +41,6 @@ const PresetSelector = ({ onSelect, onCancel, }) => {
|
|
|
40
41
|
onCancel();
|
|
41
42
|
}
|
|
42
43
|
});
|
|
43
|
-
return (
|
|
44
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
45
|
-
React.createElement(Text, { bold: true, color: "green" }, "Select Command Preset")),
|
|
46
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
47
|
-
React.createElement(Text, { dimColor: true }, "Choose a preset to start the session with")),
|
|
48
|
-
React.createElement(SelectInput, { items: selectItems, onSelect: handleSelectItem, initialIndex: initialIndex >= 0 ? initialIndex : 0 }),
|
|
49
|
-
React.createElement(Box, { marginTop: 1 },
|
|
50
|
-
React.createElement(Text, { dimColor: true }, "Press \u2191\u2193 to navigate, Enter to select, ESC to cancel"))));
|
|
44
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Select Command Preset" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a preset to start the session with" }) }), _jsx(SelectInput, { items: selectItems, onSelect: handleSelectItem, initialIndex: initialIndex >= 0 ? initialIndex : 0 }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press \u2191\u2193 to navigate, Enter to select, ESC to cancel" }) })] }));
|
|
51
45
|
};
|
|
52
46
|
export default PresetSelector;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
2
3
|
import { Box, Text, useInput } from 'ink';
|
|
3
4
|
import { Effect } from 'effect';
|
|
4
5
|
import SelectInput from 'ink-select-input';
|
|
@@ -221,42 +222,12 @@ const ProjectList = ({ projectsDir, onSelectProject, error, onDismissError, }) =
|
|
|
221
222
|
onSelectProject(item.project);
|
|
222
223
|
}
|
|
223
224
|
};
|
|
224
|
-
return (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
React.createElement(TextInputWrapper, { value: searchQuery, onChange: setSearchQuery, focus: true, placeholder: "Type to filter projects..." }))),
|
|
232
|
-
loading ? (React.createElement(Box, null,
|
|
233
|
-
React.createElement(Text, { color: "yellow" }, "Loading projects..."))) : projects.length === 0 && !displayError ? (React.createElement(Box, null,
|
|
234
|
-
React.createElement(Text, { color: "yellow" },
|
|
235
|
-
"No git repositories found in ",
|
|
236
|
-
projectsDir))) : isSearchMode && items.length === 0 ? (React.createElement(Box, null,
|
|
237
|
-
React.createElement(Text, { color: "yellow" }, "No projects match your search"))) : isSearchMode ? (
|
|
238
|
-
// In search mode, show the items as a list without SelectInput
|
|
239
|
-
React.createElement(Box, { flexDirection: "column" }, items.slice(0, limit).map((item, index) => (React.createElement(Text, { key: item.value, color: index === selectedIndex ? 'green' : undefined },
|
|
240
|
-
index === selectedIndex ? '❯ ' : ' ',
|
|
241
|
-
item.label))))) : (React.createElement(SelectInput, { items: items, onSelect: handleSelect, isFocused: !displayError, limit: limit, initialIndex: selectedIndex })),
|
|
242
|
-
displayError && (React.createElement(Box, { marginTop: 1, paddingX: 1, borderStyle: "round", borderColor: "red" },
|
|
243
|
-
React.createElement(Box, { flexDirection: "column" },
|
|
244
|
-
React.createElement(Text, { color: "red", bold: true },
|
|
245
|
-
"Error: ",
|
|
246
|
-
displayError),
|
|
247
|
-
React.createElement(Text, { color: "gray", dimColor: true }, "Press any key to dismiss")))),
|
|
248
|
-
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
249
|
-
(isSearchMode || searchQuery) && (React.createElement(Text, { dimColor: true },
|
|
250
|
-
"Projects: ",
|
|
251
|
-
items.filter(item => item.project).length,
|
|
252
|
-
" of",
|
|
253
|
-
' ',
|
|
254
|
-
projects.length,
|
|
255
|
-
" shown")),
|
|
256
|
-
React.createElement(Text, { dimColor: true }, isSearchMode
|
|
257
|
-
? 'Search Mode: Type to filter, Enter to exit search, ESC to exit search'
|
|
258
|
-
: searchQuery
|
|
259
|
-
? `Filtered: "${searchQuery}" | ↑↓ Navigate Enter Select | /-Search ESC-Clear 0-9 Quick Select R-Refresh Q-Quit`
|
|
260
|
-
: 'Controls: ↑↓ Navigate Enter Select | Hotkeys: 0-9 Quick Select /-Search R-Refresh Q-Quit'))));
|
|
225
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "CCManager - Multi-Project Mode" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Select a project:" }) }), isSearchMode && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { children: "Search: " }), _jsx(TextInputWrapper, { value: searchQuery, onChange: setSearchQuery, focus: true, placeholder: "Type to filter projects..." })] })), loading ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "Loading projects..." }) })) : projects.length === 0 && !displayError ? (_jsx(Box, { children: _jsxs(Text, { color: "yellow", children: ["No git repositories found in ", projectsDir] }) })) : isSearchMode && items.length === 0 ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "No projects match your search" }) })) : isSearchMode ? (
|
|
226
|
+
// In search mode, show the items as a list without SelectInput
|
|
227
|
+
_jsx(Box, { flexDirection: "column", children: items.slice(0, limit).map((item, index) => (_jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', item.label] }, item.value))) })) : (_jsx(SelectInput, { items: items, onSelect: handleSelect, isFocused: !displayError, limit: limit, initialIndex: selectedIndex })), displayError && (_jsx(Box, { marginTop: 1, paddingX: 1, borderStyle: "round", borderColor: "red", children: _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "red", bold: true, children: ["Error: ", displayError] }), _jsx(Text, { color: "gray", dimColor: true, children: "Press any key to dismiss" })] }) })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [(isSearchMode || searchQuery) && (_jsxs(Text, { dimColor: true, children: ["Projects: ", items.filter(item => item.project).length, " of", ' ', projects.length, " shown"] })), _jsx(Text, { dimColor: true, children: isSearchMode
|
|
228
|
+
? 'Search Mode: Type to filter, Enter to exit search, ESC to exit search'
|
|
229
|
+
: searchQuery
|
|
230
|
+
? `Filtered: "${searchQuery}" | ↑↓ Navigate Enter Select | /-Search ESC-Clear 0-9 Quick Select R-Refresh Q-Quit`
|
|
231
|
+
: 'Controls: ↑↓ Navigate Enter Select | Hotkeys: 0-9 Quick Select /-Search R-Refresh Q-Quit' })] })] }));
|
|
261
232
|
};
|
|
262
233
|
export default ProjectList;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { render } from 'ink-testing-library';
|
|
3
3
|
import { expect, describe, it, vi, beforeEach, afterEach } from 'vitest';
|
|
4
4
|
import ProjectList from './ProjectList.js';
|
|
@@ -24,7 +24,7 @@ vi.mock('ink-select-input', async () => {
|
|
|
24
24
|
const { Text, Box } = await vi.importActual('ink');
|
|
25
25
|
return {
|
|
26
26
|
default: ({ items }) => {
|
|
27
|
-
return (
|
|
27
|
+
return (_jsx(Box, { flexDirection: "column", children: items.map(item => (_jsx(Text, { children: item.label }, item.value))) }));
|
|
28
28
|
},
|
|
29
29
|
};
|
|
30
30
|
});
|
|
@@ -79,7 +79,7 @@ describe('ProjectList - Recent Projects', () => {
|
|
|
79
79
|
lastAccessed: Date.now() - 2000,
|
|
80
80
|
},
|
|
81
81
|
]);
|
|
82
|
-
const { lastFrame } = render(
|
|
82
|
+
const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
|
|
83
83
|
// Wait for projects to load
|
|
84
84
|
await vi.waitFor(() => {
|
|
85
85
|
expect(lastFrame()).toContain('project-c');
|
|
@@ -97,7 +97,7 @@ describe('ProjectList - Recent Projects', () => {
|
|
|
97
97
|
});
|
|
98
98
|
it('should not show recent projects section when there are none', async () => {
|
|
99
99
|
vi.mocked(projectManager.getRecentProjects).mockReturnValue([]);
|
|
100
|
-
const { lastFrame } = render(
|
|
100
|
+
const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
|
|
101
101
|
// Wait for projects to load
|
|
102
102
|
await vi.waitFor(() => {
|
|
103
103
|
expect(lastFrame()).toContain('project-a');
|
|
@@ -127,7 +127,7 @@ describe('ProjectList - Recent Projects', () => {
|
|
|
127
127
|
lastAccessed: Date.now() - 2000,
|
|
128
128
|
},
|
|
129
129
|
]);
|
|
130
|
-
const { lastFrame } = render(
|
|
130
|
+
const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
|
|
131
131
|
// Wait for projects to load
|
|
132
132
|
await vi.waitFor(() => {
|
|
133
133
|
expect(lastFrame()).toContain('project-c');
|
|
@@ -151,7 +151,7 @@ describe('ProjectList - Recent Projects', () => {
|
|
|
151
151
|
lastAccessed: Date.now() - i * 1000,
|
|
152
152
|
}));
|
|
153
153
|
vi.mocked(projectManager.getRecentProjects).mockReturnValue(manyRecentProjects);
|
|
154
|
-
const { lastFrame } = render(
|
|
154
|
+
const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
|
|
155
155
|
// Wait for projects to load
|
|
156
156
|
await vi.waitFor(() => {
|
|
157
157
|
expect(lastFrame()).toContain('project-0');
|
|
@@ -177,7 +177,7 @@ describe('ProjectList - Recent Projects', () => {
|
|
|
177
177
|
mockUseInput.mockImplementation(handler => {
|
|
178
178
|
inputHandler = handler;
|
|
179
179
|
});
|
|
180
|
-
const { lastFrame } = render(
|
|
180
|
+
const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
|
|
181
181
|
// Wait for projects to load
|
|
182
182
|
await vi.waitFor(() => {
|
|
183
183
|
expect(lastFrame()).toContain('project-c');
|