Fix dialog focus

This commit is contained in:
2026-03-23 03:51:51 +00:00
parent a28d43a68b
commit 7fd89c5663
18 changed files with 403 additions and 177 deletions

View File

@@ -7,8 +7,9 @@
*/
import React from 'react';
import { Box, Text, useInput } from 'ink';
import { Box, Text } from 'ink';
import { colors, formatSatoshis } from '../../../../theme.js';
import { useLayeredInput } from '../../../../hooks/useInputLayer.js';
import {
getInvitationState,
getStateColorName,
@@ -40,8 +41,7 @@ export function PreviewInvitationStep({
onCancel,
isActive,
}: PreviewStepProps): React.ReactElement {
useInput((_input, key) => {
if (!isActive) return;
useLayeredInput('import-flow', (_input, key) => {
if (key.return) onComplete();
if (key.escape) onCancel();
}, { isActive });
@@ -62,87 +62,129 @@ export function PreviewInvitationStep({
return (
<Box flexDirection="column">
{/* Template & action info */}
{/* Template info */}
<Box flexDirection="column" marginBottom={1}>
<Text color={colors.primary} bold>Template: </Text>
<Text color={colors.text}>{template?.name ?? invitation.data.templateIdentifier}</Text>
<Box>
<Text color={colors.primary} bold>Template:</Text>
</Box>
<Box>
<Text color={colors.text}>{template?.name ?? invitation.data.templateIdentifier}</Text>
</Box>
{template?.description && (
<Text color={colors.textMuted} dimColor>{template.description}</Text>
<Box>
<Text color={colors.textMuted} dimColor>{template.description}</Text>
</Box>
)}
</Box>
<Box flexDirection="row" marginBottom={1}>
<Box width="50%" flexDirection="column">
<Text color={colors.primary} bold>Action: </Text>
<Text color={colors.text}>{action?.name ?? invitation.data.actionIdentifier}</Text>
{action?.description && (
<Text color={colors.textMuted} dimColor>{action.description}</Text>
)}
{/* Action info */}
<Box flexDirection="column" marginBottom={1}>
<Box>
<Text color={colors.primary} bold>Action:</Text>
</Box>
<Box width="50%" flexDirection="column">
<Text color={colors.primary} bold>Status: </Text>
<Box>
<Text color={colors.text}>{action?.name ?? invitation.data.actionIdentifier}</Text>
</Box>
{action?.description && (
<Box>
<Text color={colors.textMuted} dimColor>{action.description}</Text>
</Box>
)}
</Box>
{/* Status */}
<Box flexDirection="column" marginBottom={1}>
<Box>
<Text color={colors.primary} bold>Status:</Text>
</Box>
<Box>
<Text color={stateColor(state)}>{state}</Text>
</Box>
</Box>
{/* Roles already filled */}
<Box flexDirection="column" marginBottom={1}>
<Text color={colors.primary} bold>Roles Filled ({filledRoles.size}):</Text>
<Box>
<Text color={colors.primary} bold>Roles Filled ({filledRoles.size}):</Text>
</Box>
{filledRoles.size === 0 ? (
<Text color={colors.textMuted}> None yet</Text>
<Box>
<Text color={colors.textMuted}> None yet</Text>
</Box>
) : (
Array.from(filledRoles).map(role => {
const roleInfoRaw = template?.roles?.[role];
const roleInfo = roleInfoRaw && typeof roleInfoRaw === 'object' ? roleInfoRaw : null;
return (
<Text key={role} color={colors.text}> {roleInfo?.name ?? role}</Text>
<Box key={role}>
<Text color={colors.text}> {roleInfo?.name ?? role}</Text>
</Box>
);
})
)}
</Box>
{/* Inputs & Outputs side by side */}
<Box flexDirection="row" marginBottom={1}>
<Box width="50%" flexDirection="column">
{/* Inputs */}
<Box flexDirection="column" marginBottom={1}>
<Box>
<Text color={colors.primary} bold>Inputs ({inputs.length}):</Text>
{inputs.length === 0 ? (
</Box>
{inputs.length === 0 ? (
<Box>
<Text color={colors.textMuted}> None yet</Text>
) : (
inputs.map((input, idx) => {
const inputTemplate = template?.inputs?.[input.inputIdentifier ?? ''];
return (
<Text key={`input-${idx}`} color={colors.text}>
</Box>
) : (
inputs.map((input, idx) => {
const inputTemplate = template?.inputs?.[input.inputIdentifier ?? ''];
return (
<Box key={`input-${idx}`}>
<Text color={colors.text}>
{' '} {inputTemplate?.name ?? input.inputIdentifier ?? `Input ${idx}`}
{input.roleIdentifier && ` (${input.roleIdentifier})`}
</Text>
);
})
)}
</Box>
);
})
)}
</Box>
{/* Outputs */}
<Box flexDirection="column" marginBottom={1}>
<Box>
<Text color={colors.primary} bold>Outputs ({outputs.length}):</Text>
</Box>
<Box width="50%" flexDirection="column">
<Text color={colors.primary} bold>Outputs ({outputs.length}):</Text>
{outputs.length === 0 ? (
{outputs.length === 0 ? (
<Box>
<Text color={colors.textMuted}> None yet</Text>
) : (
outputs.map((output, idx) => {
const outputTemplate = template?.outputs?.[output.outputIdentifier ?? ''];
return (
<Text key={`output-${idx}`} color={colors.text}>
</Box>
) : (
outputs.map((output, idx) => {
const outputTemplate = template?.outputs?.[output.outputIdentifier ?? ''];
return (
<Box key={`output-${idx}`}>
<Text color={colors.text}>
{' '} {outputTemplate?.name ?? output.outputIdentifier ?? `Output ${idx}`}
{output.valueSatoshis !== undefined && ` (${formatSatoshis(output.valueSatoshis)})`}
</Text>
);
})
)}
</Box>
</Box>
);
})
)}
</Box>
{/* Variables */}
<Box flexDirection="column" marginBottom={1}>
<Text color={colors.primary} bold>Variables ({variables.length}):</Text>
<Box>
<Text color={colors.primary} bold>Variables ({variables.length}):</Text>
</Box>
{variables.length === 0 ? (
<Text color={colors.textMuted}> None set</Text>
<Box>
<Text color={colors.textMuted}> None set</Text>
</Box>
) : (
variables.map((variable, idx) => {
const varTemplate = template?.variables?.[variable.variableIdentifier];
@@ -150,9 +192,11 @@ export function PreviewInvitationStep({
? variable.value.toString()
: String(variable.value);
return (
<Text key={`var-${idx}`} color={colors.text}>
{' '} {varTemplate?.name ?? variable.variableIdentifier}: {displayValue}
</Text>
<Box key={`var-${idx}`}>
<Text color={colors.text}>
{' '} {varTemplate?.name ?? variable.variableIdentifier}: {displayValue}
</Text>
</Box>
);
})
)}