import React, { type ReactNode } from 'react';
import { ActivityIndicator, Image, Pressable, Text, View } from 'react-native';
import { Check, type LucideIcon } from 'lucide-react-native';
import { conversationStyles } from '../../features/conversation/conversationStyles';
import { themedColor } from '../../theme';
import { ToolWidgetRow } from '../primitives/ToolWidgetRow';
import { WidgetCard } from '../primitives/WidgetCard';
import { toolWidgetStyles } from '../primitives/toolWidgetStyles';
import type { ToolWidgetStatus } from '../toolWidgetUtils';
/**
* Shared building blocks for the interactive widgets (clarifying questions,
* agent permissions, payments) — the option rows, buttons and fallback/status
* surfaces they all render.
*/
/** Radio/checkbox option row (clarifying options, provider picker, PSP selects). */
export function SelectableOptionRow({
centered = false,
children,
disabled,
imageUrl,
label,
multi = false,
onPress,
selected,
subtitle,
}: {
/** Centers the indicator against the whole row instead of the label's first line. */
centered?: boolean;
children?: ReactNode;
disabled: boolean;
imageUrl?: string | null;
/** Omit to let `children` (e.g. an inline input) stand in for the label instead. */
label?: string;
multi?: boolean;
onPress: () => void;
selected: boolean;
subtitle?: string | null;
}) {
return (
{multi ? (
// approvalCheckbox's marginTop is tuned for EntityApprovalBatchCard's rows;
// here the 20px box already lines up with the 18px label line, so drop it.
{selected ? : null}
) : (
{selected ? : null}
)}
{label ? {label} : null}
{subtitle ? {subtitle} : null}
{imageUrl ? : null}
{children}
);
}
export function WidgetActionButton({
disabled,
isSubmitting,
label,
onPress,
primary = false,
small = false,
}: {
disabled: boolean;
isSubmitting: boolean;
label: string;
onPress: () => void;
primary?: boolean;
/** DS Button size="sm" instead of the default taller approval-card button. */
small?: boolean;
}) {
return (
{isSubmitting ? : null}
{label}
);
}
/**
* Card with a message and a single action — the web's amber fallback panels
* (choices/fields failed to load) and the clarifying "couldn't generate
* questions" state.
*/
export function FallbackActionCard({
buttonLabel,
error,
isSubmitting,
message,
onPress,
}: {
buttonLabel: string;
error?: string | null;
isSubmitting: boolean;
message: string;
onPress?: () => void;
}) {
return (
{message}
{})}
/>
{error ? {error} : null}
);
}
/** Resolved-state row with the tool's error message underneath (PSP widgets). */
export function StatusRowWithError({
errorMessage,
icon,
status,
title,
}: {
errorMessage: string | null;
icon: LucideIcon;
status: ToolWidgetStatus;
title: string;
}) {
return (
{errorMessage ? {errorMessage} : null}
);
}
/** DS tiny ghost icon button (pager chevrons, the clarifying card's minimize toggle). */
export function TinyIconButton({
accessibilityLabel,
disabled,
icon: Icon,
onPress,
}: {
accessibilityLabel: string;
disabled: boolean;
icon: LucideIcon;
onPress: () => void;
}) {
return (
);
}