ccmanager 3.5.2 → 3.5.3

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.
@@ -9,10 +9,5 @@ interface TextInputWrapperProps {
9
9
  showCursor?: boolean;
10
10
  highlightPastedText?: boolean;
11
11
  }
12
- /**
13
- * Custom text input component that handles rapid input correctly.
14
- * This is a replacement for ink-text-input that uses refs for immediate
15
- * state updates, which is necessary for text expansion tools like Espanso.
16
- */
17
12
  declare const TextInputWrapper: React.FC<TextInputWrapperProps>;
18
13
  export default TextInputWrapper;
@@ -1,142 +1,15 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect, useRef } from 'react';
3
- import { Text, useInput } from 'ink';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import TextInput from 'ink-text-input';
4
3
  import stripAnsi from 'strip-ansi';
5
- /**
6
- * Custom text input component that handles rapid input correctly.
7
- * This is a replacement for ink-text-input that uses refs for immediate
8
- * state updates, which is necessary for text expansion tools like Espanso.
9
- */
10
- const TextInputWrapper = ({ value, onChange, onSubmit, placeholder = '', focus = true, mask, showCursor = true, }) => {
11
- // Use ref to track the actual current value for immediate updates
12
- // This is critical for handling rapid input from tools like Espanso
13
- const valueRef = useRef(value);
14
- const cursorRef = useRef(value.length);
15
- // State for triggering re-renders
16
- const [, forceUpdate] = useState({});
17
- // Sync refs when value prop changes from parent
18
- useEffect(() => {
19
- valueRef.current = value;
20
- // Adjust cursor if it's beyond the new value length
21
- if (cursorRef.current > value.length) {
22
- cursorRef.current = value.length;
23
- }
24
- }, [value]);
25
- const cleanValue = (val) => {
26
- let cleaned = stripAnsi(val);
27
- cleaned = cleaned.replace(/\[200~/g, '').replace(/\[201~/g, '');
28
- return cleaned;
4
+ const TextInputWrapper = ({ value, onChange, ...props }) => {
5
+ const handleChange = (newValue) => {
6
+ // First strip all ANSI escape sequences
7
+ let cleanedValue = stripAnsi(newValue);
8
+ // Then specifically remove bracketed paste mode markers that might remain
9
+ // These sometimes appear as literal text after ANSI stripping
10
+ cleanedValue = cleanedValue.replace(/\[200~/g, '').replace(/\[201~/g, '');
11
+ onChange(cleanedValue);
29
12
  };
30
- // Process backspace characters that might be embedded in input string
31
- // This handles cases where text expansion tools send backspaces as characters
32
- const processBackspaces = (input, currentValue, cursor) => {
33
- let newValue = currentValue;
34
- let newCursor = cursor;
35
- let remaining = '';
36
- for (let i = 0; i < input.length; i++) {
37
- const char = input[i];
38
- const charCode = char?.charCodeAt(0);
39
- // Check for backspace characters (ASCII 8 or 127)
40
- if (charCode === 8 || charCode === 127) {
41
- if (newCursor > 0) {
42
- newValue =
43
- newValue.slice(0, newCursor - 1) + newValue.slice(newCursor);
44
- newCursor--;
45
- }
46
- }
47
- else {
48
- // Regular character - add to remaining
49
- remaining += char;
50
- }
51
- }
52
- return { value: newValue, cursor: newCursor, remainingInput: remaining };
53
- };
54
- useInput((input, key) => {
55
- // Ignore certain keys
56
- if (key.upArrow ||
57
- key.downArrow ||
58
- (key.ctrl && input === 'c') ||
59
- key.tab ||
60
- (key.shift && key.tab)) {
61
- return;
62
- }
63
- // Handle Enter/Return
64
- if (key.return) {
65
- if (onSubmit) {
66
- onSubmit(valueRef.current);
67
- }
68
- return;
69
- }
70
- let currentValue = valueRef.current;
71
- let cursor = cursorRef.current;
72
- if (key.leftArrow) {
73
- if (showCursor && cursor > 0) {
74
- cursorRef.current = cursor - 1;
75
- forceUpdate({});
76
- }
77
- return;
78
- }
79
- if (key.rightArrow) {
80
- if (showCursor && cursor < currentValue.length) {
81
- cursorRef.current = cursor + 1;
82
- forceUpdate({});
83
- }
84
- return;
85
- }
86
- if (key.backspace || key.delete) {
87
- if (cursor > 0) {
88
- const nextValue = currentValue.slice(0, cursor - 1) + currentValue.slice(cursor);
89
- valueRef.current = nextValue;
90
- cursorRef.current = cursor - 1;
91
- onChange(nextValue);
92
- forceUpdate({});
93
- }
94
- return;
95
- }
96
- // Process input that might contain embedded backspace characters
97
- // (some text expansion tools send backspaces as part of the input string)
98
- const { value: processedValue, cursor: processedCursor, remainingInput, } = processBackspaces(input, currentValue, cursor);
99
- currentValue = processedValue;
100
- cursor = processedCursor;
101
- // Add remaining characters (non-backspace)
102
- if (remainingInput) {
103
- const cleanedInput = cleanValue(remainingInput);
104
- if (cleanedInput) {
105
- currentValue =
106
- currentValue.slice(0, cursor) +
107
- cleanedInput +
108
- currentValue.slice(cursor);
109
- cursor = cursor + cleanedInput.length;
110
- }
111
- }
112
- // Update refs immediately (synchronously)
113
- valueRef.current = currentValue;
114
- cursorRef.current = cursor;
115
- // Notify parent of value change
116
- onChange(currentValue);
117
- // Force re-render to update display
118
- forceUpdate({});
119
- }, { isActive: focus });
120
- // Render the text with cursor
121
- const displayValue = mask
122
- ? mask.repeat(valueRef.current.length)
123
- : valueRef.current;
124
- const cursor = cursorRef.current;
125
- if (!showCursor || !focus) {
126
- return (_jsx(Text, { children: displayValue.length > 0 ? (displayValue) : placeholder ? (_jsx(Text, { dimColor: true, children: placeholder })) : null }));
127
- }
128
- // Show cursor
129
- if (displayValue.length === 0) {
130
- // Show placeholder with cursor on first char
131
- if (placeholder) {
132
- return (_jsxs(Text, { children: [_jsx(Text, { inverse: true, children: placeholder[0] || ' ' }), _jsx(Text, { dimColor: true, children: placeholder.slice(1) })] }));
133
- }
134
- return _jsx(Text, { inverse: true, children: " " });
135
- }
136
- // Render value with cursor
137
- const beforeCursor = displayValue.slice(0, cursor);
138
- const atCursor = displayValue[cursor] || ' ';
139
- const afterCursor = displayValue.slice(cursor + 1);
140
- return (_jsxs(Text, { children: [beforeCursor, _jsx(Text, { inverse: true, children: atCursor }), afterCursor] }));
13
+ return _jsx(TextInput, { value: value, onChange: handleChange, ...props });
141
14
  };
142
15
  export default TextInputWrapper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccmanager",
3
- "version": "3.5.2",
3
+ "version": "3.5.3",
4
4
  "description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
5
5
  "license": "MIT",
6
6
  "author": "Kodai Kabasawa",
@@ -26,7 +26,7 @@
26
26
  "build:binary:native": "bun run scripts/build-binaries.ts --target=native",
27
27
  "build:binary:all": "bun run scripts/build-binaries.ts --target=all",
28
28
  "dev": "bun run tsc --watch",
29
- "start": "bun dist/cli.js",
29
+ "start": "bun --no-env-file dist/cli.js",
30
30
  "test": "vitest --run",
31
31
  "lint": "bun run eslint src",
32
32
  "lint:fix": "bun run eslint src --fix",
@@ -41,11 +41,11 @@
41
41
  "bin"
42
42
  ],
43
43
  "optionalDependencies": {
44
- "@kodaikabasawa/ccmanager-darwin-arm64": "3.5.2",
45
- "@kodaikabasawa/ccmanager-darwin-x64": "3.5.2",
46
- "@kodaikabasawa/ccmanager-linux-arm64": "3.5.2",
47
- "@kodaikabasawa/ccmanager-linux-x64": "3.5.2",
48
- "@kodaikabasawa/ccmanager-win32-x64": "3.5.2"
44
+ "@kodaikabasawa/ccmanager-darwin-arm64": "3.5.3",
45
+ "@kodaikabasawa/ccmanager-darwin-x64": "3.5.3",
46
+ "@kodaikabasawa/ccmanager-linux-arm64": "3.5.3",
47
+ "@kodaikabasawa/ccmanager-linux-x64": "3.5.3",
48
+ "@kodaikabasawa/ccmanager-win32-x64": "3.5.3"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@eslint/js": "^9.28.0",