@allternit/gizzi-code 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/gizzi +4 -0
- package/bin/gizzi-ink +5 -0
- package/package.json +137 -31
- package/src/Tool.ts +26 -0
- package/src/bootstrap/state.ts +165 -322
- package/src/commands.ts +209 -0
- package/src/context/QueuedMessageContext.tsx +63 -0
- package/src/context/fpsMetrics.tsx +30 -0
- package/src/context/mailbox.tsx +38 -0
- package/src/context/modalContext.tsx +58 -0
- package/src/context/notifications.tsx +240 -0
- package/src/context/overlayContext.tsx +151 -0
- package/src/context/promptOverlayContext.tsx +125 -0
- package/src/context/stats.tsx +220 -0
- package/src/context/voice.tsx +88 -0
- package/src/hooks/useCanUseTool.ts +11 -0
- package/src/hooks/useExitOnCtrlCD.ts +40 -187
- package/src/hooks/useExitOnCtrlCDWithKeybindings.ts +68 -0
- package/src/hooks/useKeybinding.ts +68 -209
- package/src/hooks/useTerminalSize.ts +31 -99
- package/src/hooks.ts +37 -0
- package/src/ink.ts +204 -0
- package/src/main.ts +7 -0
- package/src/types/command.ts +216 -0
- package/src/types/connectorText.ts +39 -0
- package/src/types/fileSuggestion.ts +15 -0
- package/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +865 -0
- package/src/types/generated/events_mono/common/v1/auth.ts +100 -0
- package/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +223 -0
- package/src/types/generated/google/protobuf/timestamp.ts +187 -0
- package/src/types/hooks.ts +319 -0
- package/src/types/ids.ts +44 -0
- package/src/types/logs.ts +331 -0
- package/src/types/merged/index.ts +5 -0
- package/src/types/merged/message.ts +552 -0
- package/src/types/message.ts +927 -186
- package/src/types/messageQueueTypes.ts +21 -0
- package/src/types/notebook.ts +72 -0
- package/src/types/permissions.ts +447 -0
- package/src/types/plugin.ts +363 -0
- package/src/types/statusLine.ts +15 -0
- package/src/types/textInputTypes.ts +387 -0
- package/src/types/tools.ts +149 -0
- package/src/types/utils.ts +20 -0
- package/src/utils/advisor.ts +12 -0
- package/src/utils/api.ts +29 -0
- package/src/utils/array.ts +7 -0
- package/src/utils/attachments.ts +60 -0
- package/src/utils/auth.ts +3 -0
- package/src/utils/claudeInChrome/chromeNativeHost.ts +15 -0
- package/src/utils/claudeInChrome/common.ts +12 -0
- package/src/utils/claudeInChrome/mcpServer.ts +15 -0
- package/src/utils/computerUse/common.ts +19 -0
- package/src/utils/computerUse/mcpServer.ts +15 -0
- package/src/utils/config.ts +35 -0
- package/src/utils/context.ts +19 -0
- package/src/utils/cwd.ts +3 -0
- package/src/utils/debug.ts +3 -0
- package/src/utils/earlyInput.ts +7 -0
- package/src/utils/effort.ts +13 -0
- package/src/utils/embeddedTools.ts +12 -0
- package/src/utils/envUtils.ts +3 -0
- package/src/utils/errors.ts +3 -0
- package/src/utils/execFileNoThrow.ts +24 -0
- package/src/utils/feature-flags.ts +112 -0
- package/src/utils/file.ts +3 -0
- package/src/utils/fileHistory.ts +17 -0
- package/src/utils/fingerprint.ts +7 -0
- package/src/utils/format.ts +75 -305
- package/src/utils/frontmatterParser.ts +33 -0
- package/src/utils/fsOperations.ts +31 -0
- package/src/utils/fullscreen.ts +40 -350
- package/src/utils/git.ts +15 -0
- package/src/utils/imageResizer.ts +30 -0
- package/src/utils/lazySchema.ts +9 -0
- package/src/utils/log.ts +3 -0
- package/src/utils/markdownConfigLoader.ts +12 -0
- package/src/utils/messages.ts +13 -0
- package/src/utils/migration.ts +137 -0
- package/src/utils/model/providers.ts +15 -0
- package/src/utils/path.ts +3 -0
- package/src/utils/permissions/PermissionResult.ts +14 -0
- package/src/utils/permissions/autoModeState.ts +12 -0
- package/src/utils/permissions/filesystem.ts +12 -0
- package/src/utils/plugins/loadPluginOutputStyles.ts +12 -0
- package/src/utils/plugins/schemas.ts +25 -0
- package/src/utils/process.ts +16 -0
- package/src/utils/sandbox/sandbox-adapter.ts +19 -0
- package/src/utils/sessionStorage.ts +238 -472
- package/src/utils/settings/constants.ts +10 -0
- package/src/utils/settings/settings.ts +19 -0
- package/src/utils/settings/types.ts +18 -0
- package/src/utils/shell/shellToolUtils.ts +9 -0
- package/src/utils/sinks.ts +11 -0
- package/src/utils/sleep.ts +7 -0
- package/src/utils/sliceAnsi.ts +7 -0
- package/src/utils/slowOperations.ts +3 -0
- package/src/utils/startupProfiler.ts +11 -0
- package/src/utils/stringUtils.ts +106 -0
- package/src/utils/systemPromptType.ts +9 -0
- package/src/utils/teleport/api.ts +15 -0
- package/src/utils/textHighlighting.ts +16 -0
- package/src/utils/theme.ts +17 -0
- package/src/utils/thinking.ts +58 -0
- package/src/utils/tokens.ts +11 -0
- package/src/utils/toolResultStorage.ts +17 -0
- package/src/utils/worktreeModeEnabled.ts +7 -0
- package/WORKSPACE_INTEGRATION.md +0 -290
- package/chat-sessions/sessions-index.json +0 -98
- package/package.json.original +0 -31
- package/package.json.publish +0 -47
- package/src/bootstrap/state.d.ts +0 -169
- package/src/bootstrap/state.js +0 -261
- package/src/context/pack-builder.d.ts +0 -24
- package/src/context/pack-builder.js +0 -281
- package/src/hooks/useExitOnCtrlCD.d.ts +0 -86
- package/src/hooks/useExitOnCtrlCD.js +0 -130
- package/src/hooks/useKeybinding.d.ts +0 -89
- package/src/hooks/useKeybinding.js +0 -163
- package/src/hooks/useTerminalSize.d.ts +0 -41
- package/src/hooks/useTerminalSize.js +0 -90
- package/src/index.d.ts +0 -23
- package/src/index.js +0 -24
- package/src/runtime/brand/brand.d.ts +0 -488
- package/src/runtime/brand/brand.js +0 -464
- package/src/runtime/brand/brand.ts +0 -667
- package/src/runtime/services/tokenEstimation.d.ts +0 -187
- package/src/runtime/services/tokenEstimation.js +0 -423
- package/src/runtime/services/tokenEstimation.ts +0 -547
- package/src/runtime/tools/Tool.d.ts +0 -239
- package/src/runtime/tools/Tool.js +0 -285
- package/src/runtime/tools/Tool.ts +0 -524
- package/src/scheduler/TaskScheduler.d.ts +0 -98
- package/src/scheduler/TaskScheduler.js +0 -201
- package/src/scheduler/TaskScheduler.ts +0 -259
- package/src/state/AppStateStore.d.ts +0 -347
- package/src/state/AppStateStore.js +0 -439
- package/src/state/AppStateStore.ts +0 -658
- package/src/state/WorkspaceStateStore.d.ts +0 -43
- package/src/state/WorkspaceStateStore.js +0 -224
- package/src/state/WorkspaceStateStore.ts +0 -297
- package/src/types/message.d.ts +0 -190
- package/src/types/message.js +0 -77
- package/src/utils/format.d.ts +0 -126
- package/src/utils/format.js +0 -230
- package/src/utils/fullscreen.d.ts +0 -161
- package/src/utils/fullscreen.js +0 -277
- package/src/utils/sessionStorage.d.ts +0 -210
- package/src/utils/sessionStorage.js +0 -435
- package/src/watcher/WorkspaceWatcher.d.ts +0 -70
- package/src/watcher/WorkspaceWatcher.js +0 -191
- package/src/watcher/WorkspaceWatcher.ts +0 -251
- package/src/workspace/loader.d.ts +0 -30
- package/src/workspace/loader.js +0 -117
- package/src/workspace/types.d.ts +0 -91
- package/src/workspace/types.js +0 -7
- package/threads/thread_1775361175022.json +0 -9
- package/tsconfig.json +0 -14
|
@@ -1,226 +1,85 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Provides a React hook for registering keyboard shortcuts and key combinations.
|
|
6
|
-
* Supports modifier keys (Ctrl, Alt, Shift, Meta) and automatic cleanup on unmount.
|
|
2
|
+
* useKeybinding hook
|
|
3
|
+
* Registers keyboard shortcuts
|
|
7
4
|
*/
|
|
8
5
|
|
|
9
|
-
import { useEffect, useCallback
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
readonly stopPropagation?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Mutable version for internal parsing
|
|
34
|
-
* @interface MutableKeybindingConfig
|
|
35
|
-
*/
|
|
36
|
-
interface MutableKeybindingConfig {
|
|
37
|
-
key: string;
|
|
38
|
-
ctrl?: boolean;
|
|
39
|
-
alt?: boolean;
|
|
40
|
-
shift?: boolean;
|
|
41
|
-
meta?: boolean;
|
|
42
|
-
preventDefault?: boolean;
|
|
43
|
-
stopPropagation?: boolean;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Normalized key combination string for comparison
|
|
48
|
-
* @param {KeybindingConfig} config - Keybinding configuration
|
|
49
|
-
* @returns {string} Normalized key combination string
|
|
50
|
-
*/
|
|
51
|
-
function normalizeKeyCombo(config: KeybindingConfig): string {
|
|
52
|
-
const parts: string[] = [];
|
|
53
|
-
if (config.ctrl) parts.push('ctrl');
|
|
54
|
-
if (config.alt) parts.push('alt');
|
|
55
|
-
if (config.shift) parts.push('shift');
|
|
56
|
-
if (config.meta) parts.push('meta');
|
|
57
|
-
parts.push(config.key.toLowerCase());
|
|
58
|
-
return parts.join('+');
|
|
6
|
+
import { useEffect, useCallback } from 'react'
|
|
7
|
+
import { useInput } from 'ink'
|
|
8
|
+
|
|
9
|
+
export type KeyHandler = (input: string, key: Key) => void
|
|
10
|
+
|
|
11
|
+
export interface Key {
|
|
12
|
+
upArrow: boolean
|
|
13
|
+
downArrow: boolean
|
|
14
|
+
leftArrow: boolean
|
|
15
|
+
rightArrow: boolean
|
|
16
|
+
pageDown: boolean
|
|
17
|
+
pageUp: boolean
|
|
18
|
+
return: boolean
|
|
19
|
+
escape: boolean
|
|
20
|
+
ctrl: boolean
|
|
21
|
+
shift: boolean
|
|
22
|
+
tab: boolean
|
|
23
|
+
backspace: boolean
|
|
24
|
+
delete: boolean
|
|
25
|
+
meta: boolean
|
|
59
26
|
}
|
|
60
27
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
break;
|
|
90
|
-
case 'alt':
|
|
91
|
-
case 'option':
|
|
92
|
-
config.alt = true;
|
|
93
|
-
break;
|
|
94
|
-
case 'shift':
|
|
95
|
-
config.shift = true;
|
|
96
|
-
break;
|
|
97
|
-
case 'meta':
|
|
98
|
-
case 'cmd':
|
|
99
|
-
case 'command':
|
|
100
|
-
case 'win':
|
|
101
|
-
case 'windows':
|
|
102
|
-
config.meta = true;
|
|
103
|
-
break;
|
|
104
|
-
default:
|
|
105
|
-
config.key = part;
|
|
106
|
-
break;
|
|
28
|
+
export function useKeybinding(key: string, handler: () => void, deps: React.DependencyList = []): void {
|
|
29
|
+
const memoizedHandler = useCallback(handler, deps)
|
|
30
|
+
|
|
31
|
+
useInput((input, keyEvent) => {
|
|
32
|
+
const keyMatch = key.toLowerCase()
|
|
33
|
+
|
|
34
|
+
if (keyMatch === 'ctrl+c' && keyEvent.ctrl && input === 'c') {
|
|
35
|
+
memoizedHandler()
|
|
36
|
+
} else if (keyMatch === 'ctrl+d' && keyEvent.ctrl && input === 'd') {
|
|
37
|
+
memoizedHandler()
|
|
38
|
+
} else if (keyMatch === 'ctrl+z' && keyEvent.ctrl && input === 'z') {
|
|
39
|
+
memoizedHandler()
|
|
40
|
+
} else if (keyMatch === 'escape' && keyEvent.escape) {
|
|
41
|
+
memoizedHandler()
|
|
42
|
+
} else if (keyMatch === 'return' && keyEvent.return) {
|
|
43
|
+
memoizedHandler()
|
|
44
|
+
} else if (keyMatch === 'tab' && keyEvent.tab) {
|
|
45
|
+
memoizedHandler()
|
|
46
|
+
} else if (keyMatch === 'up' && keyEvent.upArrow) {
|
|
47
|
+
memoizedHandler()
|
|
48
|
+
} else if (keyMatch === 'down' && keyEvent.downArrow) {
|
|
49
|
+
memoizedHandler()
|
|
50
|
+
} else if (keyMatch === 'left' && keyEvent.leftArrow) {
|
|
51
|
+
memoizedHandler()
|
|
52
|
+
} else if (keyMatch === 'right' && keyEvent.rightArrow) {
|
|
53
|
+
memoizedHandler()
|
|
54
|
+
} else if (keyMatch === input.toLowerCase()) {
|
|
55
|
+
memoizedHandler()
|
|
107
56
|
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return config;
|
|
57
|
+
})
|
|
111
58
|
}
|
|
112
59
|
|
|
113
|
-
|
|
114
|
-
* Key event handler type
|
|
115
|
-
* @typedef {Function} KeyHandler
|
|
116
|
-
*/
|
|
117
|
-
export type KeyHandler = (event: KeyboardEvent) => void | boolean;
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* React hook for registering keyboard shortcuts
|
|
121
|
-
*
|
|
122
|
-
* Registers a keyboard shortcut that triggers the provided handler when pressed.
|
|
123
|
-
* Automatically cleans up the event listener when the component unmounts or
|
|
124
|
-
* when the keybinding changes.
|
|
125
|
-
*
|
|
126
|
-
* @param {string | KeybindingConfig} key - Key combination (e.g., "Ctrl+C") or config object
|
|
127
|
-
* @param {KeyHandler} handler - Function to call when keybinding is triggered
|
|
128
|
-
* @param {boolean} [enabled=true] - Whether the keybinding is active
|
|
129
|
-
* @example
|
|
130
|
-
* ```typescript
|
|
131
|
-
* // Using string keybinding
|
|
132
|
-
* useKeybinding('Ctrl+C', () => {
|
|
133
|
-
* console.log('Copy!');
|
|
134
|
-
* });
|
|
135
|
-
*
|
|
136
|
-
* // Using config object
|
|
137
|
-
* useKeybinding({ key: 'k', ctrl: true }, (e) => {
|
|
138
|
-
* e.preventDefault();
|
|
139
|
-
* console.log('Ctrl+K pressed');
|
|
140
|
-
* });
|
|
141
|
-
*
|
|
142
|
-
* // With conditional enabling
|
|
143
|
-
* useKeybinding('Escape', handleClose, isModalOpen);
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
|
-
export function useKeybinding(
|
|
147
|
-
key: string | KeybindingConfig,
|
|
148
|
-
handler: KeyHandler,
|
|
149
|
-
enabled: boolean = true
|
|
150
|
-
): void {
|
|
151
|
-
const config = typeof key === 'string' ? parseKeybinding(key) : key;
|
|
152
|
-
const expectedCombo = normalizeKeyCombo(config);
|
|
153
|
-
const handlerRef = useRef<KeyHandler>(handler);
|
|
154
|
-
|
|
155
|
-
// Keep handler reference up to date without re-registering
|
|
60
|
+
export function useGlobalKeybinding(key: string, handler: () => void): void {
|
|
156
61
|
useEffect(() => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
alt: event.altKey,
|
|
167
|
-
shift: event.shiftKey,
|
|
168
|
-
meta: event.metaKey,
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
if (actualCombo === expectedCombo) {
|
|
172
|
-
if (config.preventDefault) {
|
|
173
|
-
event.preventDefault();
|
|
174
|
-
}
|
|
175
|
-
if (config.stopPropagation) {
|
|
176
|
-
event.stopPropagation();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const result = handlerRef.current(event);
|
|
180
|
-
// Allow handler to prevent default by returning false
|
|
181
|
-
if (result === false) {
|
|
182
|
-
event.preventDefault();
|
|
183
|
-
}
|
|
62
|
+
const keyHandler = (str: string, keyEvent: { ctrl: boolean; name: string }) => {
|
|
63
|
+
const keyMatch = key.toLowerCase()
|
|
64
|
+
|
|
65
|
+
if (keyMatch === 'ctrl+c' && keyEvent.ctrl && keyEvent.name === 'c') {
|
|
66
|
+
handler()
|
|
67
|
+
} else if (keyMatch === 'escape' && keyEvent.name === 'escape') {
|
|
68
|
+
handler()
|
|
69
|
+
} else if (keyMatch === keyEvent.name) {
|
|
70
|
+
handler()
|
|
184
71
|
}
|
|
185
|
-
},
|
|
186
|
-
[config, expectedCombo]
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
useEffect(() => {
|
|
190
|
-
if (!enabled || typeof window === 'undefined') {
|
|
191
|
-
return;
|
|
192
72
|
}
|
|
193
73
|
|
|
194
|
-
|
|
74
|
+
process.stdin.on('keypress', keyHandler)
|
|
195
75
|
|
|
196
76
|
return () => {
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
}, [
|
|
77
|
+
process.stdin.off('keypress', keyHandler)
|
|
78
|
+
}
|
|
79
|
+
}, [key, handler])
|
|
200
80
|
}
|
|
201
81
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
* @param {Array<[string | KeybindingConfig, KeyHandler]>} bindings - Array of [keybinding, handler] tuples
|
|
206
|
-
* @param {boolean} [enabled=true] - Whether all keybindings are active
|
|
207
|
-
* @example
|
|
208
|
-
* ```typescript
|
|
209
|
-
* useKeybindings([
|
|
210
|
-
* ['Ctrl+C', handleCopy],
|
|
211
|
-
* ['Ctrl+V', handlePaste],
|
|
212
|
-
* ['Escape', handleClose],
|
|
213
|
-
* ]);
|
|
214
|
-
* ```
|
|
215
|
-
*/
|
|
216
|
-
export function useKeybindings(
|
|
217
|
-
bindings: Array<[string | KeybindingConfig, KeyHandler]>,
|
|
218
|
-
enabled: boolean = true
|
|
219
|
-
): void {
|
|
220
|
-
bindings.forEach(([key, handler]) => {
|
|
221
|
-
useKeybinding(key, handler, enabled);
|
|
222
|
-
});
|
|
82
|
+
export default {
|
|
83
|
+
useKeybinding,
|
|
84
|
+
useGlobalKeybinding,
|
|
223
85
|
}
|
|
224
|
-
|
|
225
|
-
// Default export
|
|
226
|
-
export default useKeybinding;
|
|
@@ -1,117 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Provides a React hook to track terminal dimensions with resize event handling.
|
|
6
|
-
* Returns the current terminal width and height, defaulting to standard terminal
|
|
7
|
-
* dimensions when not in a browser environment.
|
|
2
|
+
* useTerminalSize hook
|
|
3
|
+
* Tracks terminal dimensions
|
|
8
4
|
*/
|
|
9
5
|
|
|
10
|
-
import { useState, useEffect
|
|
6
|
+
import { useState, useEffect } from 'react'
|
|
11
7
|
|
|
12
|
-
/**
|
|
13
|
-
* Terminal size state interface
|
|
14
|
-
* @interface TerminalSize
|
|
15
|
-
*/
|
|
16
8
|
export interface TerminalSize {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/** Current terminal height in rows */
|
|
20
|
-
readonly height: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Default terminal dimensions (80x24 is standard terminal size)
|
|
25
|
-
* @constant {TerminalSize}
|
|
26
|
-
*/
|
|
27
|
-
const DEFAULT_TERMINAL_SIZE: TerminalSize = {
|
|
28
|
-
width: 80,
|
|
29
|
-
height: 24,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Gets the current terminal size from the window object
|
|
34
|
-
* Falls back to default dimensions if window is not available
|
|
35
|
-
*
|
|
36
|
-
* @returns {TerminalSize} Current terminal dimensions
|
|
37
|
-
*/
|
|
38
|
-
function getTerminalSize(): TerminalSize {
|
|
39
|
-
if (typeof window === 'undefined') {
|
|
40
|
-
return DEFAULT_TERMINAL_SIZE;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Estimate columns/rows based on window size and average character dimensions
|
|
44
|
-
// This is an approximation - actual terminal emulators may vary
|
|
45
|
-
const avgCharWidth = 8; // pixels per character (approximate)
|
|
46
|
-
const avgLineHeight = 16; // pixels per line (approximate)
|
|
47
|
-
|
|
48
|
-
const width = Math.max(20, Math.floor(window.innerWidth / avgCharWidth));
|
|
49
|
-
const height = Math.max(5, Math.floor(window.innerHeight / avgLineHeight));
|
|
50
|
-
|
|
51
|
-
return { width, height };
|
|
9
|
+
width: number
|
|
10
|
+
height: number
|
|
52
11
|
}
|
|
53
12
|
|
|
54
|
-
/**
|
|
55
|
-
* React hook for tracking terminal size
|
|
56
|
-
*
|
|
57
|
-
* Returns the current terminal dimensions and automatically updates
|
|
58
|
-
* when the window is resized. Uses debouncing to prevent excessive
|
|
59
|
-
* re-renders during resize operations.
|
|
60
|
-
*
|
|
61
|
-
* @returns {TerminalSize} Current terminal width and height
|
|
62
|
-
* @example
|
|
63
|
-
* ```typescript
|
|
64
|
-
* function MyComponent() {
|
|
65
|
-
* const { width, height } = useTerminalSize();
|
|
66
|
-
*
|
|
67
|
-
* return (
|
|
68
|
-
* <div>
|
|
69
|
-
* Terminal: {width}×{height}
|
|
70
|
-
* </div>
|
|
71
|
-
* );
|
|
72
|
-
* }
|
|
73
|
-
* ```
|
|
74
|
-
*/
|
|
75
13
|
export function useTerminalSize(): TerminalSize {
|
|
76
|
-
const [size, setSize] = useState<TerminalSize>(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}, []);
|
|
14
|
+
const [size, setSize] = useState<TerminalSize>({
|
|
15
|
+
width: process.stdout.columns || 80,
|
|
16
|
+
height: process.stdout.rows || 24,
|
|
17
|
+
})
|
|
81
18
|
|
|
82
19
|
useEffect(() => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
20
|
+
const handleResize = () => {
|
|
21
|
+
setSize({
|
|
22
|
+
width: process.stdout.columns || 80,
|
|
23
|
+
height: process.stdout.rows || 24,
|
|
24
|
+
})
|
|
86
25
|
}
|
|
87
26
|
|
|
88
|
-
|
|
89
|
-
let resizeTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
90
|
-
|
|
91
|
-
const debouncedHandleResize = (): void => {
|
|
92
|
-
if (resizeTimeout) {
|
|
93
|
-
clearTimeout(resizeTimeout);
|
|
94
|
-
}
|
|
95
|
-
resizeTimeout = setTimeout(handleResize, 100);
|
|
96
|
-
};
|
|
27
|
+
process.stdout.on('resize', handleResize)
|
|
97
28
|
|
|
98
|
-
|
|
99
|
-
|
|
29
|
+
return () => {
|
|
30
|
+
process.stdout.off('resize', handleResize)
|
|
31
|
+
}
|
|
32
|
+
}, [])
|
|
100
33
|
|
|
101
|
-
|
|
102
|
-
|
|
34
|
+
return size
|
|
35
|
+
}
|
|
103
36
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (resizeTimeout) {
|
|
108
|
-
clearTimeout(resizeTimeout);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
}, [handleResize]);
|
|
37
|
+
export function useTerminalWidth(): number {
|
|
38
|
+
return useTerminalSize().width
|
|
39
|
+
}
|
|
112
40
|
|
|
113
|
-
|
|
41
|
+
export function useTerminalHeight(): number {
|
|
42
|
+
return useTerminalSize().height
|
|
114
43
|
}
|
|
115
44
|
|
|
116
|
-
|
|
117
|
-
|
|
45
|
+
export default {
|
|
46
|
+
useTerminalSize,
|
|
47
|
+
useTerminalWidth,
|
|
48
|
+
useTerminalHeight,
|
|
49
|
+
}
|
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hooks System
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface HookContext {
|
|
6
|
+
event: string
|
|
7
|
+
data: unknown
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type HookCallback = (ctx: HookContext) => void | Promise<void>
|
|
11
|
+
|
|
12
|
+
const hooks: Map<string, HookCallback[]> = new Map()
|
|
13
|
+
|
|
14
|
+
export function registerHook(event: string, callback: HookCallback): () => void {
|
|
15
|
+
if (!hooks.has(event)) {
|
|
16
|
+
hooks.set(event, [])
|
|
17
|
+
}
|
|
18
|
+
hooks.get(event)!.push(callback)
|
|
19
|
+
return () => {
|
|
20
|
+
const callbacks = hooks.get(event)
|
|
21
|
+
if (callbacks) {
|
|
22
|
+
const index = callbacks.indexOf(callback)
|
|
23
|
+
if (index >= 0) callbacks.splice(index, 1)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function executeHooks(event: string, data: unknown): Promise<void> {
|
|
29
|
+
const callbacks = hooks.get(event) || []
|
|
30
|
+
for (const callback of callbacks) {
|
|
31
|
+
await callback({ event, data })
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function hasWorktreeCreateHook(): boolean {
|
|
36
|
+
return hooks.has('worktree:create')
|
|
37
|
+
}
|
package/src/ink.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ink CLI rendering utilities
|
|
3
|
+
* React-based CLI UI components
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ReactNode } from 'react'
|
|
7
|
+
|
|
8
|
+
// Re-export from ink
|
|
9
|
+
export {
|
|
10
|
+
render,
|
|
11
|
+
Box,
|
|
12
|
+
Text,
|
|
13
|
+
useInput,
|
|
14
|
+
useApp,
|
|
15
|
+
useStdout,
|
|
16
|
+
useStdin,
|
|
17
|
+
Spacer,
|
|
18
|
+
Newline,
|
|
19
|
+
Static,
|
|
20
|
+
Transform,
|
|
21
|
+
measureElement,
|
|
22
|
+
useFocus,
|
|
23
|
+
useFocusManager,
|
|
24
|
+
} from 'ink'
|
|
25
|
+
|
|
26
|
+
export type { BoxProps, TextProps, RenderOptions } from 'ink'
|
|
27
|
+
|
|
28
|
+
// Key handling types
|
|
29
|
+
export interface Key {
|
|
30
|
+
name?: string
|
|
31
|
+
ctrl?: boolean
|
|
32
|
+
shift?: boolean
|
|
33
|
+
meta?: boolean
|
|
34
|
+
sequence?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// String width calculation (for text wrapping)
|
|
38
|
+
export function stringWidth(str: string): number {
|
|
39
|
+
// Strip ANSI codes and count visible characters
|
|
40
|
+
const withoutAnsi = str.replace(/\u001b\[[0-9;]*m/g, '')
|
|
41
|
+
// Approximate width (for proper implementation, use string-width package)
|
|
42
|
+
return [...withoutAnsi].length
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Terminal size hook
|
|
46
|
+
export interface TerminalSize {
|
|
47
|
+
width: number
|
|
48
|
+
height: number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function useTerminalSize(): TerminalSize {
|
|
52
|
+
// Default fallback
|
|
53
|
+
return {
|
|
54
|
+
width: process.stdout.columns || 80,
|
|
55
|
+
height: process.stdout.rows || 24,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Color utilities
|
|
60
|
+
export type InkColor =
|
|
61
|
+
| 'black'
|
|
62
|
+
| 'red'
|
|
63
|
+
| 'green'
|
|
64
|
+
| 'yellow'
|
|
65
|
+
| 'blue'
|
|
66
|
+
| 'magenta'
|
|
67
|
+
| 'cyan'
|
|
68
|
+
| 'white'
|
|
69
|
+
| 'gray'
|
|
70
|
+
| 'grey'
|
|
71
|
+
| 'redBright'
|
|
72
|
+
| 'greenBright'
|
|
73
|
+
| 'yellowBright'
|
|
74
|
+
| 'blueBright'
|
|
75
|
+
| 'magentaBright'
|
|
76
|
+
| 'cyanBright'
|
|
77
|
+
| 'whiteBright'
|
|
78
|
+
| string
|
|
79
|
+
| number
|
|
80
|
+
| undefined
|
|
81
|
+
|
|
82
|
+
// Common key codes
|
|
83
|
+
export const KeyCodes = {
|
|
84
|
+
RETURN: '\r',
|
|
85
|
+
ENTER: '\n',
|
|
86
|
+
TAB: '\t',
|
|
87
|
+
ESC: '\u001b',
|
|
88
|
+
BACKSPACE: '\u007f',
|
|
89
|
+
CTRL_C: '\u0003',
|
|
90
|
+
CTRL_D: '\u0004',
|
|
91
|
+
CTRL_Z: '\u001a',
|
|
92
|
+
UP: '\u001b[A',
|
|
93
|
+
DOWN: '\u001b[B',
|
|
94
|
+
RIGHT: '\u001b[C',
|
|
95
|
+
LEFT: '\u001b[D',
|
|
96
|
+
} as const
|
|
97
|
+
|
|
98
|
+
// Spinner states
|
|
99
|
+
export type SpinnerType =
|
|
100
|
+
| 'dots'
|
|
101
|
+
| 'dots2'
|
|
102
|
+
| 'dots3'
|
|
103
|
+
| 'dots4'
|
|
104
|
+
| 'dots5'
|
|
105
|
+
| 'dots6'
|
|
106
|
+
| 'dots7'
|
|
107
|
+
| 'dots8'
|
|
108
|
+
| 'dots9'
|
|
109
|
+
| 'dots10'
|
|
110
|
+
| 'dots11'
|
|
111
|
+
| 'dots12'
|
|
112
|
+
| 'line'
|
|
113
|
+
| 'line2'
|
|
114
|
+
| 'pipe'
|
|
115
|
+
| 'star'
|
|
116
|
+
| 'star2'
|
|
117
|
+
| 'flip'
|
|
118
|
+
| 'hamburger'
|
|
119
|
+
| 'growVertical'
|
|
120
|
+
| 'growHorizontal'
|
|
121
|
+
| 'balloon'
|
|
122
|
+
| 'balloon2'
|
|
123
|
+
| 'noise'
|
|
124
|
+
| 'bounce'
|
|
125
|
+
| 'boxBounce'
|
|
126
|
+
| 'boxBounce2'
|
|
127
|
+
| 'triangle'
|
|
128
|
+
| 'arc'
|
|
129
|
+
| 'circle'
|
|
130
|
+
| 'squareCorners'
|
|
131
|
+
| 'circleQuarters'
|
|
132
|
+
| 'circleHalves'
|
|
133
|
+
| 'squish'
|
|
134
|
+
| 'toggle'
|
|
135
|
+
| 'toggle2'
|
|
136
|
+
| 'toggle3'
|
|
137
|
+
| 'toggle4'
|
|
138
|
+
| 'toggle5'
|
|
139
|
+
| 'toggle6'
|
|
140
|
+
| 'toggle7'
|
|
141
|
+
| 'toggle8'
|
|
142
|
+
| 'toggle9'
|
|
143
|
+
| 'toggle10'
|
|
144
|
+
| 'toggle11'
|
|
145
|
+
| 'toggle12'
|
|
146
|
+
| 'toggle13'
|
|
147
|
+
|
|
148
|
+
export const SPINNER_FRAMES: Record<SpinnerType, string[]> = {
|
|
149
|
+
dots: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
|
|
150
|
+
dots2: ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'],
|
|
151
|
+
dots3: ['⠋', '⠙', '⠚', '⠞', '⠖', '⠦', '⠴', '⠲', '⠳', '⠓'],
|
|
152
|
+
dots4: ['⠄', '⠆', '⠇', '⠋', '⠙', '⠸', '⠰', '⠠', '⠰', '⠸', '⠙', '⠋', '⠇', '⠆'],
|
|
153
|
+
dots5: ['⠋', '⠙', '⠚', '⠒', '⠂', '⠂', '⠒', '⠲', '⠴', '⠦', '⠖', '⠒', '⠐', '⠐', '⠒', '⠓', '⠋'],
|
|
154
|
+
dots6: ['⠁', '⠉', '⠙', '⠚', '⠒', '⠂', '⠂', '⠒', '⠲', '⠴', '⠤', '⠄', '⠄', '⠤', '⠴', '⠲', '⠒', '⠂', '⠂', '⠒', '⠚', '⠙', '⠉', '⠁'],
|
|
155
|
+
dots7: ['⠈', '⠉', '⠋', '⠓', '⠒', '⠐', '⠐', '⠒', '⠖', '⠦', '⠤', '⠠', '⠠', '⠤', '⠦', '⠖', '⠒', '⠐', '⠐', '⠒', '⠓', '⠋', '⠉', '⠈'],
|
|
156
|
+
dots8: ['⠁', '⠁', '⠉', '⠙', '⠚', '⠒', '⠂', '⠂', '⠒', '⠲', '⠴', '⠤', '⠄', '⠄', '⠤', '⠠', '⠠', '⠤', '⠦', '⠖', '⠒', '⠐', '⠐', '⠒', '⠓', '⠋', '⠉', '⠈', '⠈'],
|
|
157
|
+
dots9: ['⢹', '⢺', '⢼', '⣸', '⣇', '⡧', '⡗', '⡏'],
|
|
158
|
+
dots10: ['⢄', '⢂', '⢁', '⡁', '⡈', '⡐', '⡠'],
|
|
159
|
+
dots11: ['⠁', '⠂', '⠄', '⡀', '⢀', '⠠', '⠐', '⠈'],
|
|
160
|
+
dots12: ['⢀⠀', '⡀⠀', '⠄⠀', '⢂⠀', '⡂⠀', '⠅⠀', '⢃⠀', '⡃⠀', '⠍⠀', '⢋⠀', '⡋⠀', '⠍⠁', '⢋⠁', '⡋⠁', '⠍⠉', '⢋⠉', '⡋⠉', '⠍⠙', '⢋⠙', '⡋⠙', '⠍⠚', '⢋⠚', '⡋⠚', '⠍⠒', '⢋⠒', '⡋⠒', '⠍⠂', '⢋⠂', '⡋⠂', '⠍⡀', '⢋⡀', '⡋⡀', '⠍⡄', '⢋⡄', '⡋⡄', '⠍⡆', '⢋⡆', '⡋⡆', '⠍⡇', '⢋⡇', '⡋⡇', '⠍⡏', '⢋⡏', '⡋⡏', '⠍⡹', '⢋⡹', '⡋⡹', '⠍⢹', '⢋⢹', '⡋⢹', '⠍⣸', '⢋⣸', '⡋⣸', '⠍⣴', '⢋⣴', '⡋⣴', '⠍⣦', '⢋⣦', '⡋⣦', '⠍⣇', '⢋⣇', '⡋⣇', '⠍⡧', '⢋⡧', '⡋⡧', '⠍⡗', '⢋⡗', '⡋⡗', '⠍⡏'],
|
|
161
|
+
line: ['-', '\\', '|', '/'],
|
|
162
|
+
line2: ['⠂', '-', '–', '—', '–', '-'],
|
|
163
|
+
pipe: ['┤', '┘', '┴', '└', '├', '┌', '┬', '┐'],
|
|
164
|
+
star: ['✶', '✸', '✹', '✺', '✹', '✷'],
|
|
165
|
+
star2: ['+', 'x', '*'],
|
|
166
|
+
flip: ['_', '_', '_', '-', '`', '`', "'", '´', '-', '_', '_', '_'],
|
|
167
|
+
hamburger: ['☱', '☲', '☴'],
|
|
168
|
+
growVertical: ['▁', '▃', '▄', '▅', '▆', '▇', '▆', '▅', '▄', '▃'],
|
|
169
|
+
growHorizontal: ['▏', '▎', '▍', '▌', '▋', '▊', '▉', '▊', '▋', '▌', '▍', '▎'],
|
|
170
|
+
balloon: ['.', 'o', 'O', '@', '*'],
|
|
171
|
+
balloon2: ['.', 'o', 'O', '°', 'O', 'o', '.'],
|
|
172
|
+
noise: ['▓', '▒', '░'],
|
|
173
|
+
bounce: ['⠁', '⠂', '⠄', '⠂'],
|
|
174
|
+
boxBounce: ['▖', '▘', '▝', '▗'],
|
|
175
|
+
boxBounce2: ['▌', '▀', '▐', '▄'],
|
|
176
|
+
triangle: ['◢', '◣', '◤', '◥'],
|
|
177
|
+
arc: ['◜', '◠', '◝', '◞', '◡', '◟'],
|
|
178
|
+
circle: ['◡', '⊙', '◠'],
|
|
179
|
+
squareCorners: ['◰', '◳', '◲', '◱'],
|
|
180
|
+
circleQuarters: ['◴', '◷', '◶', '◵'],
|
|
181
|
+
circleHalves: ['◐', '◓', '◑', '◒'],
|
|
182
|
+
squish: ['╫', '╪'],
|
|
183
|
+
toggle: ['⊶', '⊷'],
|
|
184
|
+
toggle2: ['▫', '▪'],
|
|
185
|
+
toggle3: ['□', '■'],
|
|
186
|
+
toggle4: ['■', '□', '▪', '▫'],
|
|
187
|
+
toggle5: ['▮', '▯'],
|
|
188
|
+
toggle6: ['ဝ', '၀'],
|
|
189
|
+
toggle7: ['⦾', '⦿'],
|
|
190
|
+
toggle8: ['◍', '◌'],
|
|
191
|
+
toggle9: ['◉', '◎'],
|
|
192
|
+
toggle10: ['㊂', '㊀', '㊁'],
|
|
193
|
+
toggle11: ['⬇', '⬆'],
|
|
194
|
+
toggle12: ['▹', '▿', '◃'],
|
|
195
|
+
toggle13: ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█', '▉', '▊', '▋', '▌', '▍', '▎', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█', '▇', '▆', '▅', '▄', '▃', '▂', '▁'],
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Default export
|
|
199
|
+
export default {
|
|
200
|
+
stringWidth,
|
|
201
|
+
useTerminalSize,
|
|
202
|
+
KeyCodes,
|
|
203
|
+
SPINNER_FRAMES,
|
|
204
|
+
}
|