Fix dialog focus
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
* Dialog components for modals, confirmations, and input dialogs.
|
||||
*/
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Box, Text, useInput, measureElement } from 'ink';
|
||||
import React, { useId, useRef, useState } from 'react';
|
||||
import { Box, Text, measureElement } from 'ink';
|
||||
import TextInput from './TextInput.js';
|
||||
import { colors } from '../theme.js';
|
||||
import { useInputLayer, useLayeredInput } from '../hooks/useInputLayer.js';
|
||||
|
||||
/**
|
||||
* Base dialog wrapper props.
|
||||
@@ -118,15 +119,17 @@ export function InputDialog({
|
||||
onCancel,
|
||||
isActive = true,
|
||||
}: InputDialogProps): React.ReactElement {
|
||||
const layerId = useId();
|
||||
const [value, setValue] = useState(initialValue);
|
||||
|
||||
useInput((input, key) => {
|
||||
if (!isActive) return;
|
||||
|
||||
// Auto-capture input when this dialog is mounted.
|
||||
useInputLayer(layerId);
|
||||
|
||||
useLayeredInput(layerId, (_input, key) => {
|
||||
if (key.escape) {
|
||||
onCancel();
|
||||
}
|
||||
}, { isActive });
|
||||
});
|
||||
|
||||
const handleSubmit = (val: string) => {
|
||||
onSubmit(val);
|
||||
@@ -183,11 +186,13 @@ export function ConfirmDialog({
|
||||
confirmLabel = 'Yes',
|
||||
cancelLabel = 'No',
|
||||
}: ConfirmDialogProps): React.ReactElement {
|
||||
const layerId = useId();
|
||||
const [selected, setSelected] = useState<'confirm' | 'cancel'>('confirm');
|
||||
|
||||
useInput((input, key) => {
|
||||
if (!isActive) return;
|
||||
// Auto-capture input when this dialog is mounted.
|
||||
useInputLayer(layerId);
|
||||
|
||||
useLayeredInput(layerId, (input, key) => {
|
||||
if (key.leftArrow || key.rightArrow || key.tab) {
|
||||
setSelected(prev => prev === 'confirm' ? 'cancel' : 'confirm');
|
||||
} else if (key.return) {
|
||||
@@ -201,7 +206,7 @@ export function ConfirmDialog({
|
||||
} else if (input === 'y' || input === 'Y') {
|
||||
onConfirm();
|
||||
}
|
||||
}, { isActive });
|
||||
});
|
||||
|
||||
return (
|
||||
<DialogWrapper title={title} borderColor={colors.warning}>
|
||||
@@ -255,13 +260,16 @@ export function MessageDialog({
|
||||
type = 'info',
|
||||
isActive = true,
|
||||
}: MessageDialogProps): React.ReactElement {
|
||||
useInput((input, key) => {
|
||||
if (!isActive) return;
|
||||
|
||||
const layerId = useId();
|
||||
|
||||
// Auto-capture input when this dialog is mounted.
|
||||
useInputLayer(layerId);
|
||||
|
||||
useLayeredInput(layerId, (_input, key) => {
|
||||
if (key.return || key.escape) {
|
||||
onClose();
|
||||
}
|
||||
}, { isActive });
|
||||
});
|
||||
|
||||
const borderColor = type === 'error' ? colors.error :
|
||||
type === 'success' ? colors.success :
|
||||
|
||||
Reference in New Issue
Block a user