import { configurableValue, ConfigurableEditorComp, ConfigurableEditorConfigStructured, evaluateCondition, ConfigurableValue, PartialEditorPorts, } from "@flyde/core"; import { ConfigurableFieldEditor } from "../../ui"; import { usePorts } from "../../flow-editor/ports"; import { useState } from "react"; // Define the GroupFieldDefinition type interface GroupFieldDefinition { type: "group"; configKey: string; label: string; description?: string; condition?: string; fields: any[]; // Using any[] to avoid typing issues typeData?: { collapsible?: boolean; defaultCollapsed?: boolean; }; } // Type guard to check if a field is a group function isGroupField(field: any): field is GroupFieldDefinition { return field && field.type === "group" && Array.isArray(field.fields); } // Helper function to evaluate field visibility based on its condition function evaluateFieldVisibility(field: any, value: any): boolean { if (field.condition) { return evaluateCondition(field.condition, value); } return true; } // Component to render a group of fields function GroupFields({ group, value, onChange, ports, nodeId, insId }: { group: GroupFieldDefinition; value: any; onChange: (value: any) => void; ports: PartialEditorPorts; nodeId: string; insId?: string; }) { const [isCollapsed, setIsCollapsed] = useState( group.typeData?.defaultCollapsed ?? false ); if (!evaluateFieldVisibility(group, value)) { return null; } return (
{ if (group.typeData?.collapsible) { setIsCollapsed(!isCollapsed); } }} >
{group.label}
{group.typeData?.collapsible && (
{isCollapsed ? "▼ Show" : "▲ Hide"}
)}
{group.description && (
{group.description}
)} {!isCollapsed && (
{group.fields.map((field: any) => { // Check if the field is a group if (isGroupField(field)) { return ( ); } // Check if the field should be visible if (!evaluateFieldVisibility(field, value)) { return null; } // Use ConfigurableFieldEditor for all fields return ( onChange({ ...value, [field.configKey]: newValue, }) } ports={ports} config={field} nodeId={nodeId} insId={insId} /> ); })}
)}
); } export function StructuredConfigurableEditorComp( editorConfig: ConfigurableEditorConfigStructured ): ConfigurableEditorComp { return (props) => { // eslint-disable-next-line react-hooks/rules-of-hooks const ports = usePorts(); return (
{editorConfig.fields.map((field: any) => { // Check if the field is a group if (isGroupField(field)) { return ( ); } // Check if the field has a condition and evaluate it if (!evaluateFieldVisibility(field, props.value)) { return null; } const configValue: Record = props.value && typeof props.value === "object" ? props.value : {}; const value = configValue[field.configKey] ?? configurableValue("dynamic", ""); // Use ConfigurableFieldEditor for all fields return ( props.onChange({ ...props.value, [field.configKey]: newValue, }) } config={field} ports={ports} nodeId={props.nodeId} insId={props.insId} /> ); })}
); }; }