import type { RefObject } from "react"; import { t } from "../../../i18n"; import { useRemoteUiNode } from "../../../remote/semantic-tree"; import { Box, Text, TextAttributes, Textarea, type InputRenderable, type TextareaRenderable, } from "../../../ui"; import { NumberField, TextField } from "../../ui"; import { SelectField, type SelectFieldHandle } from "../../ui/select-field"; import { coerceFieldString, getWorkflowFieldDescription, isWorkflowTextField, summarizeWorkflowFieldValue, } from "../helpers"; import { useCommandBarPalette } from "../panel/palette"; import { truncateText } from "../view-model"; import type { CommandBarFieldValue, CommandBarWorkflowField, CommandBarWorkflowRoute, } from "./types"; interface CommandBarWorkflowFieldRowProps { route: CommandBarWorkflowRoute; field: CommandBarWorkflowField; isLastField: boolean; nativePaneChrome: boolean; queryDisplayWidth: number; getWorkflowInputRef: (fieldId: string) => RefObject; onActiveTextareaSync: (route: CommandBarWorkflowRoute) => void; onFieldFocus: (fieldId: string) => void; onFieldPickerOpen: (route: CommandBarWorkflowRoute, field: CommandBarWorkflowField) => void; onFieldValueChange: (fieldId: string, value: CommandBarFieldValue) => void; onMoveFieldFocus: (delta: number) => void; onSelectFieldRef: (fieldId: string, element: SelectFieldHandle | null) => void; onSubmit: (route: CommandBarWorkflowRoute) => void | Promise; } export function CommandBarWorkflowFieldRow({ route, field, isLastField, nativePaneChrome, queryDisplayWidth, getWorkflowInputRef, onActiveTextareaSync, onFieldFocus, onFieldPickerOpen, onFieldValueChange, onMoveFieldFocus, onSelectFieldRef, onSubmit, }: CommandBarWorkflowFieldRowProps) { const palette = useCommandBarPalette(nativePaneChrome); const active = field.id === route.activeFieldId; const value = route.values[field.id]; const borderColor = active ? palette.selectedBg : palette.bg; const fieldBg = nativePaneChrome ? "transparent" : active ? palette.inputBg : palette.panelBg; const useSelectField = nativePaneChrome && field.type === "select"; const fieldDescription = getWorkflowFieldDescription(field); const fieldLabel = t(field.label); const translatedFieldDescription = fieldDescription ? t(fieldDescription) : null; const submitOrMoveNext = () => { if (isLastField) { void onSubmit(route); } else { onMoveFieldFocus(1); } }; const focusOrOpenField = () => { onActiveTextareaSync(route); onFieldFocus(field.id); if (!isWorkflowTextField(field) && !useSelectField) { onFieldPickerOpen(route, field); } }; useRemoteUiNode({ role: "command-bar-field", label: fieldLabel, disabled: route.pending, actions: { focus: focusOrOpenField, open: !isWorkflowTextField(field) && !useSelectField ? focusOrOpenField : undefined, submit: () => void onSubmit(route), }, metadata: { scope: "command-bar", surface: "workflow", routeTitle: t(route.title), fieldId: field.id, fieldType: field.type, active, value: summarizeWorkflowFieldValue(field, value), description: translatedFieldDescription, }, }); return ( { event.stopPropagation?.(); focusOrOpenField(); }} style={nativePaneChrome ? { marginBottom: isLastField ? 8 : 10, paddingBlock: 3, } : undefined} > {fieldLabel} {isWorkflowTextField(field) ? ( field.type === "number" ? ( } value={coerceFieldString(value)} placeholder={field.placeholder ? t(field.placeholder) : undefined} focused={active && !route.pending} variant="default" backgroundColor={nativePaneChrome ? palette.inputBg : fieldBg} onChange={(nextValue) => onFieldValueChange(field.id, nextValue)} onSubmit={submitOrMoveNext} /> ) : field.type === "textarea" ? ( {active ? (