All checks were successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
61 lines
1.3 KiB
TypeScript
61 lines
1.3 KiB
TypeScript
import React from 'react';
|
|
import { Box, Text, useInput } from 'ink';
|
|
import TextInput from 'ink-text-input';
|
|
|
|
export interface SearchBarProps {
|
|
query: string;
|
|
onQueryChange: (q: string) => void;
|
|
totalMatches: number;
|
|
currentMatch: number;
|
|
onNext: () => void;
|
|
onPrev: () => void;
|
|
onClose: () => void;
|
|
focused: boolean;
|
|
}
|
|
|
|
export function SearchBar({
|
|
query,
|
|
onQueryChange,
|
|
totalMatches,
|
|
currentMatch,
|
|
onNext,
|
|
onPrev,
|
|
onClose,
|
|
focused,
|
|
}: SearchBarProps) {
|
|
useInput(
|
|
(_input, key) => {
|
|
if (key.upArrow) {
|
|
onPrev();
|
|
}
|
|
if (key.downArrow) {
|
|
onNext();
|
|
}
|
|
if (key.escape) {
|
|
onClose();
|
|
}
|
|
},
|
|
{ isActive: focused },
|
|
);
|
|
|
|
const borderColor = focused ? 'yellow' : 'gray';
|
|
|
|
const matchDisplay =
|
|
query.length >= 2
|
|
? totalMatches > 0
|
|
? `${String(currentMatch + 1)}/${String(totalMatches)}`
|
|
: 'no matches'
|
|
: '';
|
|
|
|
return (
|
|
<Box borderStyle="round" borderColor={borderColor} paddingX={1} flexDirection="row" gap={1}>
|
|
<Text>🔍</Text>
|
|
<Box flexGrow={1}>
|
|
<TextInput value={query} onChange={onQueryChange} focus={focused} />
|
|
</Box>
|
|
{matchDisplay && <Text dimColor>{matchDisplay}</Text>}
|
|
<Text dimColor>↑↓ navigate · Esc close</Text>
|
|
</Box>
|
|
);
|
|
}
|