MCPcopy
hub / github.com/codeaashu/claude-code / TextInput

Function TextInput

src/components/TextInput.tsx:37–123  ·  view source on GitHub ↗
(props: Props)

Source from the content-addressed store, hash-verified

35 highlights?: TextHighlight[];
36};
37export default function TextInput(props: Props): React.ReactNode {
38 const [theme] = useTheme();
39 const isTerminalFocused = useTerminalFocus();
40 // Hoisted to mount-time — this component re-renders on every keystroke.
41 const accessibilityEnabled = useMemo(() => isEnvTruthy(process.env.CLAUDE_CODE_ACCESSIBILITY), []);
42 const settings = useSettings();
43 const reducedMotion = settings.prefersReducedMotion ?? false;
44 const voiceState = feature('VOICE_MODE') ?
45 // biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
46 useVoiceState(s => s.voiceState) : 'idle' as const;
47 const isVoiceRecording = voiceState === 'recording';
48 const audioLevels = feature('VOICE_MODE') ?
49 // biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
50 useVoiceState(s_0 => s_0.voiceAudioLevels) : [];
51 const smoothedRef = useRef<number[]>(new Array(CURSOR_WAVEFORM_WIDTH).fill(0));
52 const needsAnimation = isVoiceRecording && !reducedMotion;
53 const [animRef, animTime] = feature('VOICE_MODE') ?
54 // biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
55 useAnimationFrame(needsAnimation ? 50 : null) : [() => {}, 0];
56
57 // Show hint when terminal regains focus and clipboard has an image
58 useClipboardImageHint(isTerminalFocused, !!props.onImagePaste);
59
60 // Cursor invert function: mini waveform during voice recording,
61 // standard chalk.inverse otherwise. No warmup pulse — the ~120ms
62 // warmup window is too short for a 1s-period pulse to register, and
63 // driving TextInput re-renders at 50ms during warmup (while spaces
64 // are simultaneously arriving every 30-80ms) causes visible stutter.
65 const canShowCursor = isTerminalFocused && !accessibilityEnabled;
66 let invert: (text: string) => string;
67 if (!canShowCursor) {
68 invert = (text: string) => text;
69 } else if (isVoiceRecording && !reducedMotion) {
70 // Single-bar waveform from the latest audio level
71 const smoothed = smoothedRef.current;
72 const raw = audioLevels.length > 0 ? audioLevels[audioLevels.length - 1] ?? 0 : 0;
73 const target = Math.min(raw * LEVEL_BOOST, 1);
74 smoothed[0] = (smoothed[0] ?? 0) * SMOOTH + target * (1 - SMOOTH);
75 const displayLevel = smoothed[0] ?? 0;
76 const barIndex = Math.max(1, Math.min(Math.round(displayLevel * (BARS.length - 1)), BARS.length - 1));
77 const isSilent = raw < SILENCE_THRESHOLD;
78 const hue = animTime / 1000 * 90 % 360;
79 const {
80 r,
81 g,
82 b
83 } = isSilent ? {
84 r: 128,
85 g: 128,
86 b: 128
87 } : hueToRgb(hue);
88 invert = () => chalk.rgb(r, g, b)(BARS[barIndex]!);
89 } else {
90 invert = chalk.inverse;
91 }
92 const textInputState = useTextInput({
93 value: props.value,
94 onChange: props.onChange,

Callers

nothing calls this directly

Calls 13

useTerminalFocusFunction · 0.85
isEnvTruthyFunction · 0.85
useSettingsFunction · 0.85
featureFunction · 0.85
useVoiceStateFunction · 0.85
useAnimationFrameFunction · 0.85
useClipboardImageHintFunction · 0.85
hueToRgbFunction · 0.85
useTextInputFunction · 0.85
colorFunction · 0.85
fillMethod · 0.80
maxMethod · 0.80

Tested by

no test coverage detected