Files
xo-cli/src/tui/components/Input.tsx
2026-03-16 06:48:29 +00:00

110 lines
2.3 KiB
TypeScript

/**
* Text input component with focus styling.
*/
import React from 'react';
import { Box, Text } from 'ink';
import TextInput from './TextInput.js';
import { colors } from '../theme.js';
/**
* Props for the Input component.
*/
interface InputProps {
/** Current value */
value: string;
/** Change handler */
onChange: (value: string) => void;
/** Submit handler (Enter key) */
onSubmit?: (value: string) => void;
/** Placeholder text */
placeholder?: string;
/** Label shown above input */
label?: string;
/** Whether input is focused */
focus?: boolean;
/** Whether to mask input (for passwords) */
mask?: string;
/** Whether input is disabled */
disabled?: boolean;
}
/**
* Text input component with label and focus styling.
*/
export function Input({
value,
onChange,
onSubmit,
placeholder,
label,
focus = true,
mask,
disabled = false,
}: InputProps): React.ReactElement {
const borderColor = focus ? colors.focus : colors.border;
return (
<Box flexDirection="column">
{label && (
<Text color={colors.text} bold>{label}</Text>
)}
<Box
borderStyle="single"
borderColor={borderColor}
paddingX={1}
>
{disabled ? (
<Text color={colors.textMuted}>{value || placeholder || ''}</Text>
) : (
<TextInput
value={value}
onChange={onChange}
onSubmit={onSubmit}
placeholder={placeholder}
focus={focus}
mask={mask}
/>
)}
</Box>
</Box>
);
}
/**
* Multi-line text display (read-only, styled like input).
*/
interface TextDisplayProps {
/** Text content */
content: string;
/** Label shown above */
label?: string;
/** Whether to show border */
border?: boolean;
}
export function TextDisplay({
content,
label,
border = true
}: TextDisplayProps): React.ReactElement {
return (
<Box flexDirection="column">
{label && (
<Text color={colors.text} bold>{label}</Text>
)}
{border ? (
<Box
borderStyle="single"
borderColor={colors.border}
paddingX={1}
>
<Text>{content}</Text>
</Box>
) : (
<Text>{content}</Text>
)}
</Box>
);
}