@tduniec/plugin-template-designer 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.esm.js","sources":["../../../src/components/DesignerFlow/handlers.ts"],"sourcesContent":["import type { Dispatch, SetStateAction } from \"react\";\nimport type { Edge, Node } from \"@xyflow/react\";\nimport type { TaskStep } from \"@backstage/plugin-scaffolder-common\";\n\n// Stateful handlers that mutate nodes/edges in response to user interactions.\nimport type {\n ActionNodeData,\n AddNodeConfig,\n DesignerNodeType,\n OutputNodeData,\n ParametersNodeData,\n ParameterSectionDisplay,\n TemplateParametersValue,\n} from \"../Nodes/types\";\nimport { createSequentialEdges } from \"../../utils/createSequentialEdges\";\nimport {\n normalizeParametersToSections,\n sanitizeSections,\n sectionsToParametersValue,\n} from \"./parameterTransforms\";\nimport { alignNodes } from \"./nodeLayout\";\n\ntype SetNodes = Dispatch<SetStateAction<Node[]>>;\ntype SetEdges = Dispatch<SetStateAction<Edge[]>>;\n\ninterface CreateHandleAddNodeOptions {\n fixedXPosition: number;\n verticalSpacing: number;\n nodeDefaults: Partial<Node>;\n scaffolderActionIds: string[];\n scaffolderActionInputsById: Record<string, Record<string, unknown>>;\n scaffolderActionOutputsById: Record<string, Record<string, unknown>>;\n}\n\nconst orderNodes = (\n parameterNodes: Node[],\n actionNodes: Node[],\n outputNodes: Node[]\n) => [...parameterNodes, ...actionNodes, ...outputNodes];\n\nexport const createHandleAddNode = (\n setNodes: SetNodes,\n setEdges: SetEdges,\n options: CreateHandleAddNodeOptions\n) => {\n const {\n fixedXPosition,\n verticalSpacing,\n nodeDefaults,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n } = options;\n\n return (config: AddNodeConfig) => {\n const {\n afterRfId,\n type = \"actionNode\",\n stepTemplate,\n outputTemplate,\n parametersTemplate,\n } = config;\n const nodeType: DesignerNodeType = type;\n\n setNodes((nodes) => {\n const parameterNodes = nodes.filter((n) => n.type === \"parametersNode\");\n const actionNodes = nodes.filter((n) => n.type === \"actionNode\");\n const outputNodes = nodes.filter((n) => n.type === \"outputNode\");\n\n const composeAndAlign = (\n nextParameters: Node[],\n nextActions: Node[],\n nextOutputs: Node[]\n ) => {\n const ordered = orderNodes(nextParameters, nextActions, nextOutputs);\n const aligned = alignNodes(ordered, fixedXPosition, verticalSpacing);\n setEdges(createSequentialEdges(aligned));\n return aligned;\n };\n\n if (nodeType === \"parametersNode\") {\n if (parameterNodes.length > 0) {\n return composeAndAlign(parameterNodes, actionNodes, outputNodes);\n }\n\n const rfParametersId = \"rf-parameters\";\n const initialParameters =\n parametersTemplate !== undefined\n ? (JSON.parse(\n JSON.stringify(parametersTemplate)\n ) as TemplateParametersValue)\n : undefined;\n\n const parameterNode: Node = {\n id: rfParametersId,\n type: \"parametersNode\",\n position: { x: fixedXPosition, y: 0 },\n data: {\n rfId: rfParametersId,\n parameters: initialParameters,\n sections: [],\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n } satisfies ParametersNodeData,\n ...nodeDefaults,\n };\n\n return composeAndAlign([parameterNode], actionNodes, outputNodes);\n }\n\n if (nodeType === \"outputNode\") {\n if (outputNodes.length > 0) {\n return composeAndAlign(parameterNodes, actionNodes, outputNodes);\n }\n\n const rfOutputId = \"rf-output\";\n const initialOutput =\n outputTemplate !== undefined && outputTemplate !== null\n ? (JSON.parse(JSON.stringify(outputTemplate)) as Record<\n string,\n unknown\n >)\n : {};\n\n const outputNode: Node = {\n id: rfOutputId,\n type: \"outputNode\",\n position: { x: fixedXPosition, y: 0 },\n data: {\n rfId: rfOutputId,\n output: initialOutput,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n };\n\n return composeAndAlign(parameterNodes, actionNodes, [\n ...outputNodes,\n outputNode,\n ]);\n }\n\n const parametersPlaceholder = nodes.find(\n (n) => n.type === \"parametersNode\"\n );\n const parametersNodeId = parametersPlaceholder?.id ?? null;\n const parentIndex = actionNodes.findIndex((n) => n.id === afterRfId);\n let insertIndex: number;\n if (parentIndex >= 0) {\n insertIndex = parentIndex + 1;\n } else if (afterRfId === parametersNodeId) {\n insertIndex = 0;\n } else {\n insertIndex = actionNodes.length;\n }\n\n const rfId = `rf-${Date.now()}`;\n const stepDefaults: TaskStep = {\n id: `step-${rfId}`,\n name: \"New Step\",\n action: \"\",\n input: {},\n };\n\n const newStep: TaskStep = {\n ...stepDefaults,\n ...(stepTemplate ?? {}),\n };\n\n const newNode: Node = {\n id: rfId,\n type: \"actionNode\",\n position: { x: fixedXPosition, y: 0 },\n data: {\n rfId,\n step: newStep,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n };\n\n const nextActionNodes = [\n ...actionNodes.slice(0, insertIndex),\n newNode,\n ...actionNodes.slice(insertIndex),\n ];\n\n return composeAndAlign(parameterNodes, nextActionNodes, outputNodes);\n });\n };\n};\n\nexport const createHandleRemoveInputKey = (setNodes: SetNodes) => {\n return (rfId: string, key: string) => {\n setNodes((nds) =>\n nds.map((n) => {\n if (n.id !== rfId) {\n return n;\n }\n\n const data = n.data as Partial<ActionNodeData>;\n if (!data.step) {\n return n;\n }\n const nextInput = { ...(data.step.input ?? {}) };\n delete nextInput[key];\n const step = { ...data.step, input: nextInput };\n\n return { ...n, data: { ...data, step } };\n })\n );\n };\n};\n\nexport const createHandleReorderAndAlignNodes = (\n setNodes: SetNodes,\n setEdges: SetEdges,\n options: { fixedXPosition: number; verticalSpacing: number }\n) => {\n const { fixedXPosition, verticalSpacing } = options;\n\n return (updatedNode: Node) => {\n setNodes((prevNodes) => {\n const updatedNodes = prevNodes.map((node) =>\n node.id === updatedNode.id ? updatedNode : node\n );\n\n const parameterNodes = updatedNodes\n .filter((node) => node.type === \"parametersNode\")\n .sort((a, b) => a.position.y - b.position.y);\n const actionNodes = updatedNodes\n .filter((node) => node.type === \"actionNode\")\n .sort((a, b) => a.position.y - b.position.y);\n const outputNodes = updatedNodes\n .filter((node) => node.type === \"outputNode\")\n .sort((a, b) => a.position.y - b.position.y);\n\n const ordered = orderNodes(parameterNodes, actionNodes, outputNodes);\n const aligned = alignNodes(ordered, fixedXPosition, verticalSpacing);\n\n setEdges(createSequentialEdges(aligned));\n return aligned;\n });\n };\n};\n\nexport const createHandleUpdateField = (setNodes: SetNodes) => {\n return (rfId: string, field: keyof TaskStep, value: string) => {\n setNodes((nds) =>\n nds.map((n) => {\n if (n.id !== rfId) {\n return n;\n }\n\n const data = n.data as Partial<ActionNodeData>;\n if (!data.step) {\n return n;\n }\n const step = { ...data.step, [field]: value };\n\n return { ...n, data: { ...data, step } };\n })\n );\n };\n};\n\nexport const createHandleUpdateInput = (setNodes: SetNodes) => {\n return (rfId: string, key: string, value: unknown) => {\n setNodes((nds) =>\n nds.map((n) => {\n if (n.id !== rfId) {\n return n;\n }\n\n const data = n.data as Partial<ActionNodeData>;\n if (!data.step) {\n return n;\n }\n const nextInput = { ...(data.step.input ?? {}), [key]: value };\n const step = { ...data.step, input: nextInput };\n\n return { ...n, data: { ...data, step } };\n })\n );\n };\n};\n\nexport const collectStepOutputReferences = (\n nodes: Node[],\n parameterReferences: string[]\n): Record<string, string[]> => {\n const referencesByNode: Record<string, string[]> = {};\n const sortedNodes = [...nodes].sort((a, b) => a.position.y - b.position.y);\n const accumulatedReferences: string[] = [...parameterReferences];\n const accumulatedSet = new Set<string>(parameterReferences);\n\n sortedNodes.forEach((node) => {\n referencesByNode[node.id] = [...accumulatedReferences];\n\n const data = node.data as Partial<ActionNodeData> | undefined;\n if (!data || !data.step) {\n return;\n }\n\n const { step, scaffolderActionOutputsById } = data;\n const stepId =\n step && typeof step.id === \"string\" && step.id.trim().length > 0\n ? step.id\n : null;\n const actionId =\n step && typeof step.action === \"string\" && step.action.trim().length > 0\n ? step.action\n : null;\n\n if (!stepId || !actionId) {\n return;\n }\n\n const outputKeys = new Set<string>();\n const schemaOutputs = scaffolderActionOutputsById?.[actionId];\n if (schemaOutputs && typeof schemaOutputs === \"object\") {\n Object.keys(schemaOutputs).forEach((key) => {\n if (key) {\n outputKeys.add(key);\n }\n });\n }\n\n const stepOutput = (step as { output?: Record<string, unknown> }).output;\n if (stepOutput && typeof stepOutput === \"object\") {\n Object.keys(stepOutput).forEach((key) => {\n if (key) {\n outputKeys.add(key);\n }\n });\n }\n\n outputKeys.forEach((outputKey) => {\n const reference = `\\${{ steps['${stepId}'].output.${outputKey} }}`;\n if (!accumulatedSet.has(reference)) {\n accumulatedSet.add(reference);\n accumulatedReferences.push(reference);\n }\n });\n });\n\n return referencesByNode;\n};\n\nexport const createHandleUpdateOutput = (setNodes: SetNodes) => {\n return (\n rfId: string,\n updater: (prev: OutputNodeData[\"output\"]) => OutputNodeData[\"output\"]\n ) => {\n setNodes((nodes) =>\n nodes.map((node) => {\n if (node.id !== rfId || node.type !== \"outputNode\") {\n return node;\n }\n const data = node.data as OutputNodeData;\n const nextOutput = updater(data.output ?? {});\n return {\n ...node,\n data: {\n ...data,\n output: nextOutput,\n },\n };\n })\n );\n };\n};\n\nexport const createHandleUpdateSections = (setNodes: SetNodes) => {\n return (\n rfId: string,\n updater: (prev: ParameterSectionDisplay[]) => ParameterSectionDisplay[]\n ) => {\n setNodes((nodes) =>\n nodes.map((node) => {\n if (node.id !== rfId || node.type !== \"parametersNode\") {\n return node;\n }\n const data = node.data as ParametersNodeData;\n const previousSections =\n data.sections ?? normalizeParametersToSections(data.parameters);\n const nextSections = sanitizeSections(updater(previousSections));\n const nextParameters = sectionsToParametersValue(nextSections);\n return {\n ...node,\n data: {\n ...data,\n sections: nextSections,\n parameters: nextParameters,\n },\n };\n })\n );\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handlers.esm.js","sources":["../../../src/components/DesignerFlow/handlers.ts"],"sourcesContent":["import type { Dispatch, SetStateAction } from \"react\";\nimport type { Edge, Node } from \"@xyflow/react\";\nimport type { TaskStep } from \"@backstage/plugin-scaffolder-common\";\n\n// Stateful handlers that mutate nodes/edges in response to user interactions.\nimport type {\n ActionNodeData,\n AddNodeConfig,\n DesignerNodeType,\n OutputNodeData,\n ParametersNodeData,\n ParameterSectionDisplay,\n TemplateParametersValue,\n} from \"../Nodes/types\";\nimport { createSequentialEdges } from \"../../utils/createSequentialEdges\";\nimport {\n normalizeParametersToSections,\n sanitizeSections,\n sectionsToParametersValue,\n} from \"./parameterTransforms\";\nimport { alignNodes } from \"./nodeLayout\";\n\ntype SetNodes = Dispatch<SetStateAction<Node[]>>;\ntype SetEdges = Dispatch<SetStateAction<Edge[]>>;\n\ninterface CreateHandleAddNodeOptions {\n fixedXPosition: number;\n verticalSpacing: number;\n nodeDefaults: Partial<Node>;\n scaffolderActionIds: string[];\n scaffolderActionInputsById: Record<string, Record<string, unknown>>;\n scaffolderActionInputRequiredById: Record<string, string[]>;\n scaffolderActionOutputsById: Record<string, Record<string, unknown>>;\n}\n\ninterface CreateHandleRemoveNodeOptions {\n fixedXPosition: number;\n verticalSpacing: number;\n}\n\nconst orderNodes = (\n parameterNodes: Node[],\n actionNodes: Node[],\n outputNodes: Node[]\n) => [...parameterNodes, ...actionNodes, ...outputNodes];\n\nexport const createHandleAddNode = (\n setNodes: SetNodes,\n setEdges: SetEdges,\n options: CreateHandleAddNodeOptions\n) => {\n const {\n fixedXPosition,\n verticalSpacing,\n nodeDefaults,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionInputRequiredById,\n scaffolderActionOutputsById,\n } = options;\n\n return (config: AddNodeConfig) => {\n const {\n afterRfId,\n type = \"actionNode\",\n stepTemplate,\n outputTemplate,\n parametersTemplate,\n } = config;\n const nodeType: DesignerNodeType = type;\n\n setNodes((nodes) => {\n const parameterNodes = nodes.filter((n) => n.type === \"parametersNode\");\n const actionNodes = nodes.filter((n) => n.type === \"actionNode\");\n const outputNodes = nodes.filter((n) => n.type === \"outputNode\");\n\n const composeAndAlign = (\n nextParameters: Node[],\n nextActions: Node[],\n nextOutputs: Node[]\n ) => {\n const ordered = orderNodes(nextParameters, nextActions, nextOutputs);\n const aligned = alignNodes(ordered, fixedXPosition, verticalSpacing);\n setEdges(createSequentialEdges(aligned));\n return aligned;\n };\n\n if (nodeType === \"parametersNode\") {\n if (parameterNodes.length > 0) {\n return composeAndAlign(parameterNodes, actionNodes, outputNodes);\n }\n\n const rfParametersId = \"rf-parameters\";\n const initialParameters =\n parametersTemplate !== undefined\n ? (JSON.parse(\n JSON.stringify(parametersTemplate)\n ) as TemplateParametersValue)\n : undefined;\n\n const parameterNode: Node = {\n id: rfParametersId,\n type: \"parametersNode\",\n position: { x: fixedXPosition, y: 0 },\n data: {\n rfId: rfParametersId,\n parameters: initialParameters,\n sections: [],\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionInputRequiredById,\n scaffolderActionOutputsById,\n } satisfies ParametersNodeData,\n ...nodeDefaults,\n };\n\n return composeAndAlign([parameterNode], actionNodes, outputNodes);\n }\n\n if (nodeType === \"outputNode\") {\n if (outputNodes.length > 0) {\n return composeAndAlign(parameterNodes, actionNodes, outputNodes);\n }\n\n const rfOutputId = \"rf-output\";\n const initialOutput =\n outputTemplate !== undefined && outputTemplate !== null\n ? (JSON.parse(JSON.stringify(outputTemplate)) as Record<\n string,\n unknown\n >)\n : {};\n\n const outputNode: Node = {\n id: rfOutputId,\n type: \"outputNode\",\n position: { x: fixedXPosition, y: 0 },\n data: {\n rfId: rfOutputId,\n output: initialOutput,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionInputRequiredById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n };\n\n return composeAndAlign(parameterNodes, actionNodes, [\n ...outputNodes,\n outputNode,\n ]);\n }\n\n const parametersPlaceholder = nodes.find(\n (n) => n.type === \"parametersNode\"\n );\n const parametersNodeId = parametersPlaceholder?.id ?? null;\n const parentIndex = actionNodes.findIndex((n) => n.id === afterRfId);\n let insertIndex: number;\n if (parentIndex >= 0) {\n insertIndex = parentIndex + 1;\n } else if (afterRfId === parametersNodeId) {\n insertIndex = 0;\n } else {\n insertIndex = actionNodes.length;\n }\n\n const rfId = `rf-${Date.now()}`;\n const stepDefaults: TaskStep = {\n id: `step-${rfId}`,\n name: \"New Step\",\n action: \"\",\n input: {},\n };\n\n const newStep: TaskStep = {\n ...stepDefaults,\n ...(stepTemplate ?? {}),\n };\n\n const newNode: Node = {\n id: rfId,\n type: \"actionNode\",\n position: { x: fixedXPosition, y: 0 },\n data: {\n rfId,\n step: newStep,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionInputRequiredById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n };\n\n const nextActionNodes = [\n ...actionNodes.slice(0, insertIndex),\n newNode,\n ...actionNodes.slice(insertIndex),\n ];\n\n return composeAndAlign(parameterNodes, nextActionNodes, outputNodes);\n });\n };\n};\n\nexport const createHandleRemoveNode = (\n setNodes: SetNodes,\n setEdges: SetEdges,\n options: CreateHandleRemoveNodeOptions\n) => {\n const { fixedXPosition, verticalSpacing } = options;\n\n return (rfId: string) => {\n setNodes((nodes) => {\n const targetNode = nodes.find((node) => node.id === rfId);\n if (!targetNode || targetNode.type !== \"actionNode\") {\n return nodes;\n }\n\n const remainingNodes = nodes.filter((node) => node.id !== rfId);\n const alignedNodes = alignNodes(\n remainingNodes,\n fixedXPosition,\n verticalSpacing\n );\n setEdges(createSequentialEdges(alignedNodes));\n return alignedNodes;\n });\n };\n};\n\nexport const createHandleRemoveInputKey = (setNodes: SetNodes) => {\n return (rfId: string, key: string) => {\n setNodes((nds) =>\n nds.map((n) => {\n if (n.id !== rfId) {\n return n;\n }\n\n const data = n.data as Partial<ActionNodeData>;\n if (!data.step) {\n return n;\n }\n const nextInput = { ...(data.step.input ?? {}) };\n delete nextInput[key];\n const step = { ...data.step, input: nextInput };\n\n return { ...n, data: { ...data, step } };\n })\n );\n };\n};\n\nexport const createHandleReorderAndAlignNodes = (\n setNodes: SetNodes,\n setEdges: SetEdges,\n options: { fixedXPosition: number; verticalSpacing: number }\n) => {\n const { fixedXPosition, verticalSpacing } = options;\n\n return (updatedNode: Node) => {\n setNodes((prevNodes) => {\n const updatedNodes = prevNodes.map((node) =>\n node.id === updatedNode.id ? updatedNode : node\n );\n\n const parameterNodes = updatedNodes\n .filter((node) => node.type === \"parametersNode\")\n .sort((a, b) => a.position.y - b.position.y);\n const actionNodes = updatedNodes\n .filter((node) => node.type === \"actionNode\")\n .sort((a, b) => a.position.y - b.position.y);\n const outputNodes = updatedNodes\n .filter((node) => node.type === \"outputNode\")\n .sort((a, b) => a.position.y - b.position.y);\n\n const ordered = orderNodes(parameterNodes, actionNodes, outputNodes);\n const aligned = alignNodes(ordered, fixedXPosition, verticalSpacing);\n\n setEdges(createSequentialEdges(aligned));\n return aligned;\n });\n };\n};\n\nexport const createHandleUpdateField = (setNodes: SetNodes) => {\n return (rfId: string, field: keyof TaskStep, value: string) => {\n setNodes((nds) =>\n nds.map((n) => {\n if (n.id !== rfId) {\n return n;\n }\n\n const data = n.data as Partial<ActionNodeData>;\n if (!data.step) {\n return n;\n }\n const step = { ...data.step, [field]: value };\n\n return { ...n, data: { ...data, step } };\n })\n );\n };\n};\n\nexport const createHandleUpdateInput = (setNodes: SetNodes) => {\n return (rfId: string, key: string, value: unknown) => {\n setNodes((nds) =>\n nds.map((n) => {\n if (n.id !== rfId) {\n return n;\n }\n\n const data = n.data as Partial<ActionNodeData>;\n if (!data.step) {\n return n;\n }\n const nextInput = { ...(data.step.input ?? {}), [key]: value };\n const step = { ...data.step, input: nextInput };\n\n return { ...n, data: { ...data, step } };\n })\n );\n };\n};\n\nexport const collectStepOutputReferences = (\n nodes: Node[],\n parameterReferences: string[]\n): Record<string, string[]> => {\n const referencesByNode: Record<string, string[]> = {};\n const sortedNodes = [...nodes].sort((a, b) => a.position.y - b.position.y);\n const accumulatedReferences: string[] = [...parameterReferences];\n const accumulatedSet = new Set<string>(parameterReferences);\n\n sortedNodes.forEach((node) => {\n referencesByNode[node.id] = [...accumulatedReferences];\n\n const data = node.data as Partial<ActionNodeData> | undefined;\n if (!data || !data.step) {\n return;\n }\n\n const { step, scaffolderActionOutputsById } = data;\n const stepId =\n step && typeof step.id === \"string\" && step.id.trim().length > 0\n ? step.id\n : null;\n const actionId =\n step && typeof step.action === \"string\" && step.action.trim().length > 0\n ? step.action\n : null;\n\n if (!stepId || !actionId) {\n return;\n }\n\n const outputKeys = new Set<string>();\n const schemaOutputs = scaffolderActionOutputsById?.[actionId];\n if (schemaOutputs && typeof schemaOutputs === \"object\") {\n Object.keys(schemaOutputs).forEach((key) => {\n if (key) {\n outputKeys.add(key);\n }\n });\n }\n\n const stepOutput = (step as { output?: Record<string, unknown> }).output;\n if (stepOutput && typeof stepOutput === \"object\") {\n Object.keys(stepOutput).forEach((key) => {\n if (key) {\n outputKeys.add(key);\n }\n });\n }\n\n outputKeys.forEach((outputKey) => {\n const reference = `\\${{ steps['${stepId}'].output.${outputKey} }}`;\n if (!accumulatedSet.has(reference)) {\n accumulatedSet.add(reference);\n accumulatedReferences.push(reference);\n }\n });\n });\n\n return referencesByNode;\n};\n\nexport const createHandleUpdateOutput = (setNodes: SetNodes) => {\n return (\n rfId: string,\n updater: (prev: OutputNodeData[\"output\"]) => OutputNodeData[\"output\"]\n ) => {\n setNodes((nodes) =>\n nodes.map((node) => {\n if (node.id !== rfId || node.type !== \"outputNode\") {\n return node;\n }\n const data = node.data as OutputNodeData;\n const nextOutput = updater(data.output ?? {});\n return {\n ...node,\n data: {\n ...data,\n output: nextOutput,\n },\n };\n })\n );\n };\n};\n\nexport const createHandleUpdateSections = (setNodes: SetNodes) => {\n return (\n rfId: string,\n updater: (prev: ParameterSectionDisplay[]) => ParameterSectionDisplay[]\n ) => {\n setNodes((nodes) =>\n nodes.map((node) => {\n if (node.id !== rfId || node.type !== \"parametersNode\") {\n return node;\n }\n const data = node.data as ParametersNodeData;\n const previousSections =\n data.sections ?? normalizeParametersToSections(data.parameters);\n const nextSections = sanitizeSections(updater(previousSections));\n const nextParameters = sectionsToParametersValue(nextSections);\n return {\n ...node,\n data: {\n ...data,\n sections: nextSections,\n parameters: nextParameters,\n },\n };\n })\n );\n };\n};\n"],"names":[],"mappings":"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"}
@@ -16,7 +16,8 @@ const buildNodesFromModel = (steps, parameters, output, options) => {
16
16
  const {
17
17
  scaffolderActionIds,
18
18
  scaffolderActionInputsById,
19
- scaffolderActionOutputsById
19
+ scaffolderActionOutputsById,
20
+ scaffolderActionInputRequiredById
20
21
  } = options;
21
22
  const parameterSections = normalizeParametersToSections(parameters);
22
23
  const nodes = [];
@@ -31,6 +32,7 @@ const buildNodesFromModel = (steps, parameters, output, options) => {
31
32
  sections: parameterSections,
32
33
  scaffolderActionIds,
33
34
  scaffolderActionInputsById,
35
+ scaffolderActionInputRequiredById,
34
36
  scaffolderActionOutputsById
35
37
  },
36
38
  ...nodeDefaults
@@ -46,6 +48,7 @@ const buildNodesFromModel = (steps, parameters, output, options) => {
46
48
  step: cloneStep(step),
47
49
  scaffolderActionIds,
48
50
  scaffolderActionInputsById,
51
+ scaffolderActionInputRequiredById,
49
52
  scaffolderActionOutputsById
50
53
  },
51
54
  ...nodeDefaults
@@ -63,6 +66,7 @@ const buildNodesFromModel = (steps, parameters, output, options) => {
63
66
  output: cloneOutput(output),
64
67
  scaffolderActionIds,
65
68
  scaffolderActionInputsById,
69
+ scaffolderActionInputRequiredById,
66
70
  scaffolderActionOutputsById
67
71
  },
68
72
  ...nodeDefaults
@@ -1 +1 @@
1
- {"version":3,"file":"model.esm.js","sources":["../../../src/components/DesignerFlow/model.ts"],"sourcesContent":["import type { Node } from \"@xyflow/react\";\n\n// Pure helpers for serializing/deserializing flow nodes and template models.\nimport type {\n TaskStep,\n ScaffolderTaskOutput,\n} from \"@backstage/plugin-scaffolder-common\";\nimport type {\n ActionNodeData,\n OutputNodeData,\n ParametersNodeData,\n TemplateParametersValue,\n} from \"../Nodes/types\";\nimport { alignNodes } from \"./nodeLayout\";\nimport { normalizeParametersToSections } from \"./parameterTransforms\";\nimport { FLOW_LAYOUT, nodeDefaults } from \"./flowConfig\";\n\nconst sanitizeForRfId = (value: string) =>\n value.replace(/[^a-zA-Z0-9-_.:]/g, \"_\");\n\nconst buildRfId = (step: TaskStep | undefined, index: number) => {\n if (step && typeof step.id === \"string\" && step.id.trim().length > 0) {\n return `rf-${sanitizeForRfId(step.id)}-${index}`;\n }\n return `rf-${index + 1}`;\n};\n\nexport const cloneStep = (step: TaskStep): TaskStep =>\n JSON.parse(JSON.stringify(step ?? {})) as TaskStep;\n\nexport const cloneOutput = (\n output: ScaffolderTaskOutput | undefined | null\n): ScaffolderTaskOutput =>\n JSON.parse(JSON.stringify(output ?? {})) as ScaffolderTaskOutput;\n\nexport const cloneParameters = (\n parameters: TemplateParametersValue\n): TemplateParametersValue =>\n parameters === undefined\n ? undefined\n : (JSON.parse(JSON.stringify(parameters)) as TemplateParametersValue);\n\nexport type BuildNodesFromModelOptions = {\n scaffolderActionIds: string[];\n scaffolderActionInputsById: Record<string, Record<string, unknown>>;\n scaffolderActionOutputsById: Record<string, Record<string, unknown>>;\n};\n\nexport const buildNodesFromModel = (\n steps: TaskStep[],\n parameters: TemplateParametersValue,\n output: ScaffolderTaskOutput | undefined | null,\n options: BuildNodesFromModelOptions\n) => {\n const {\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n } = options;\n\n const parameterSections = normalizeParametersToSections(parameters);\n const nodes: Node[] = [];\n\n const rfParametersId = \"rf-parameters\";\n nodes.push({\n id: rfParametersId,\n type: \"parametersNode\",\n position: { x: FLOW_LAYOUT.fixedXPosition, y: 0 },\n data: {\n rfId: rfParametersId,\n parameters: cloneParameters(parameters),\n sections: parameterSections,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n });\n\n const actionNodes = steps.map((step, index) => {\n const rfId = buildRfId(step, index);\n return {\n id: rfId,\n type: \"actionNode\",\n position: { x: FLOW_LAYOUT.fixedXPosition, y: 0 },\n data: {\n rfId,\n step: cloneStep(step),\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n } as Node;\n });\n\n nodes.push(...actionNodes);\n\n if (output !== undefined && output !== null) {\n const rfOutputId = \"rf-output\";\n nodes.push({\n id: rfOutputId,\n type: \"outputNode\",\n position: { x: FLOW_LAYOUT.fixedXPosition, y: 0 },\n data: {\n rfId: rfOutputId,\n output: cloneOutput(output),\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n });\n }\n\n return alignNodes(\n nodes,\n FLOW_LAYOUT.fixedXPosition,\n FLOW_LAYOUT.verticalSpacing\n );\n};\n\nexport const collectParameterReferences = (\n parameters: TemplateParametersValue\n): string[] => {\n const refs = new Set<string>();\n\n const extractProperties = (schema: unknown) => {\n if (!schema || typeof schema !== \"object\") {\n return;\n }\n\n const record = schema as Record<string, unknown>;\n if (record.properties && typeof record.properties === \"object\") {\n Object.keys(record.properties as Record<string, unknown>).forEach(\n (key) => {\n if (key) {\n refs.add(`\\${{ parameters.${key} }}`);\n }\n }\n );\n }\n\n if (Array.isArray(record.steps)) {\n record.steps.forEach((stepSchema) => {\n if (!stepSchema || typeof stepSchema !== \"object\") {\n return;\n }\n extractProperties((stepSchema as Record<string, unknown>).schema);\n });\n }\n };\n\n if (Array.isArray(parameters)) {\n parameters.forEach((item) => extractProperties(item));\n } else {\n extractProperties(parameters);\n }\n\n return Array.from(refs).sort();\n};\n\nconst normalizeValueForStableStringify = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map(normalizeValueForStableStringify);\n }\n if (value && typeof value === \"object\") {\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([key]) => key !== undefined)\n .sort(([a], [b]) => {\n if (a > b) {\n return 1;\n }\n if (a < b) {\n return -1;\n }\n return 0;\n });\n return entries.reduce<Record<string, unknown>>((acc, [key, val]) => {\n acc[key] = normalizeValueForStableStringify(val);\n return acc;\n }, {});\n }\n return value;\n};\n\nexport const stableStringify = (value: unknown): string =>\n JSON.stringify(normalizeValueForStableStringify(value));\n\nexport const resolveNodeHeightForTracking = (\n node: Node\n): number | undefined => {\n const measuredHeight = node.measured?.height;\n if (typeof measuredHeight === \"number\" && measuredHeight > 0) {\n return measuredHeight;\n }\n\n const explicitHeight = node.height;\n if (typeof explicitHeight === \"number\" && explicitHeight > 0) {\n return explicitHeight;\n }\n\n return undefined;\n};\n\nconst sortNodesByY = (nodes: Node[]) =>\n [...nodes].sort((a, b) => a.position.y - b.position.y);\n\nexport const extractStepsFromNodes = (nodes: Node[]): TaskStep[] => {\n const sorted = sortNodesByY(nodes);\n return sorted\n .map((node) => {\n const data = node.data as ActionNodeData | undefined;\n if (!data || !data.step) {\n return undefined;\n }\n return cloneStep(data.step as TaskStep);\n })\n .filter((step): step is TaskStep => !!step);\n};\n\nexport const extractParametersFromNodes = (\n nodes: Node[]\n): TemplateParametersValue | undefined => {\n const parametersNode = sortNodesByY(nodes).find(\n (node) => node.type === \"parametersNode\"\n );\n if (!parametersNode) {\n return undefined;\n }\n const data = parametersNode.data as ParametersNodeData | undefined;\n if (!data) {\n return undefined;\n }\n return cloneParameters(data.parameters);\n};\n\nexport const extractOutputFromNodes = (\n nodes: Node[]\n): ScaffolderTaskOutput | undefined => {\n const outputNode = sortNodesByY(nodes).find(\n (node) => node.type === \"outputNode\"\n );\n if (!outputNode) {\n return undefined;\n }\n const data = outputNode.data as OutputNodeData | undefined;\n if (!data) {\n return undefined;\n }\n return cloneOutput(data.output);\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.esm.js","sources":["../../../src/components/DesignerFlow/model.ts"],"sourcesContent":["import type { Node } from \"@xyflow/react\";\n\n// Pure helpers for serializing/deserializing flow nodes and template models.\nimport type {\n TaskStep,\n ScaffolderTaskOutput,\n} from \"@backstage/plugin-scaffolder-common\";\nimport type {\n ActionNodeData,\n OutputNodeData,\n ParametersNodeData,\n TemplateParametersValue,\n} from \"../Nodes/types\";\nimport { alignNodes } from \"./nodeLayout\";\nimport { normalizeParametersToSections } from \"./parameterTransforms\";\nimport { FLOW_LAYOUT, nodeDefaults } from \"./flowConfig\";\n\nconst sanitizeForRfId = (value: string) =>\n value.replace(/[^a-zA-Z0-9-_.:]/g, \"_\");\n\nconst buildRfId = (step: TaskStep | undefined, index: number) => {\n if (step && typeof step.id === \"string\" && step.id.trim().length > 0) {\n return `rf-${sanitizeForRfId(step.id)}-${index}`;\n }\n return `rf-${index + 1}`;\n};\n\nexport const cloneStep = (step: TaskStep): TaskStep =>\n JSON.parse(JSON.stringify(step ?? {})) as TaskStep;\n\nexport const cloneOutput = (\n output: ScaffolderTaskOutput | undefined | null\n): ScaffolderTaskOutput =>\n JSON.parse(JSON.stringify(output ?? {})) as ScaffolderTaskOutput;\n\nexport const cloneParameters = (\n parameters: TemplateParametersValue\n): TemplateParametersValue =>\n parameters === undefined\n ? undefined\n : (JSON.parse(JSON.stringify(parameters)) as TemplateParametersValue);\n\nexport type BuildNodesFromModelOptions = {\n scaffolderActionIds: string[];\n scaffolderActionInputsById: Record<string, Record<string, unknown>>;\n scaffolderActionOutputsById: Record<string, Record<string, unknown>>;\n scaffolderActionInputRequiredById: Record<string, string[]>;\n};\n\nexport const buildNodesFromModel = (\n steps: TaskStep[],\n parameters: TemplateParametersValue,\n output: ScaffolderTaskOutput | undefined | null,\n options: BuildNodesFromModelOptions\n) => {\n const {\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n scaffolderActionInputRequiredById,\n } = options;\n\n const parameterSections = normalizeParametersToSections(parameters);\n const nodes: Node[] = [];\n\n const rfParametersId = \"rf-parameters\";\n nodes.push({\n id: rfParametersId,\n type: \"parametersNode\",\n position: { x: FLOW_LAYOUT.fixedXPosition, y: 0 },\n data: {\n rfId: rfParametersId,\n parameters: cloneParameters(parameters),\n sections: parameterSections,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionInputRequiredById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n });\n\n const actionNodes = steps.map((step, index) => {\n const rfId = buildRfId(step, index);\n return {\n id: rfId,\n type: \"actionNode\",\n position: { x: FLOW_LAYOUT.fixedXPosition, y: 0 },\n data: {\n rfId,\n step: cloneStep(step),\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionInputRequiredById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n } as Node;\n });\n\n nodes.push(...actionNodes);\n\n if (output !== undefined && output !== null) {\n const rfOutputId = \"rf-output\";\n nodes.push({\n id: rfOutputId,\n type: \"outputNode\",\n position: { x: FLOW_LAYOUT.fixedXPosition, y: 0 },\n data: {\n rfId: rfOutputId,\n output: cloneOutput(output),\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionInputRequiredById,\n scaffolderActionOutputsById,\n },\n ...nodeDefaults,\n });\n }\n\n return alignNodes(\n nodes,\n FLOW_LAYOUT.fixedXPosition,\n FLOW_LAYOUT.verticalSpacing\n );\n};\n\nexport const collectParameterReferences = (\n parameters: TemplateParametersValue\n): string[] => {\n const refs = new Set<string>();\n\n const extractProperties = (schema: unknown) => {\n if (!schema || typeof schema !== \"object\") {\n return;\n }\n\n const record = schema as Record<string, unknown>;\n if (record.properties && typeof record.properties === \"object\") {\n Object.keys(record.properties as Record<string, unknown>).forEach(\n (key) => {\n if (key) {\n refs.add(`\\${{ parameters.${key} }}`);\n }\n }\n );\n }\n\n if (Array.isArray(record.steps)) {\n record.steps.forEach((stepSchema) => {\n if (!stepSchema || typeof stepSchema !== \"object\") {\n return;\n }\n extractProperties((stepSchema as Record<string, unknown>).schema);\n });\n }\n };\n\n if (Array.isArray(parameters)) {\n parameters.forEach((item) => extractProperties(item));\n } else {\n extractProperties(parameters);\n }\n\n return Array.from(refs).sort();\n};\n\nconst normalizeValueForStableStringify = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map(normalizeValueForStableStringify);\n }\n if (value && typeof value === \"object\") {\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([key]) => key !== undefined)\n .sort(([a], [b]) => {\n if (a > b) {\n return 1;\n }\n if (a < b) {\n return -1;\n }\n return 0;\n });\n return entries.reduce<Record<string, unknown>>((acc, [key, val]) => {\n acc[key] = normalizeValueForStableStringify(val);\n return acc;\n }, {});\n }\n return value;\n};\n\nexport const stableStringify = (value: unknown): string =>\n JSON.stringify(normalizeValueForStableStringify(value));\n\nexport const resolveNodeHeightForTracking = (\n node: Node\n): number | undefined => {\n const measuredHeight = node.measured?.height;\n if (typeof measuredHeight === \"number\" && measuredHeight > 0) {\n return measuredHeight;\n }\n\n const explicitHeight = node.height;\n if (typeof explicitHeight === \"number\" && explicitHeight > 0) {\n return explicitHeight;\n }\n\n return undefined;\n};\n\nconst sortNodesByY = (nodes: Node[]) =>\n [...nodes].sort((a, b) => a.position.y - b.position.y);\n\nexport const extractStepsFromNodes = (nodes: Node[]): TaskStep[] => {\n const sorted = sortNodesByY(nodes);\n return sorted\n .map((node) => {\n const data = node.data as ActionNodeData | undefined;\n if (!data || !data.step) {\n return undefined;\n }\n return cloneStep(data.step as TaskStep);\n })\n .filter((step): step is TaskStep => !!step);\n};\n\nexport const extractParametersFromNodes = (\n nodes: Node[]\n): TemplateParametersValue | undefined => {\n const parametersNode = sortNodesByY(nodes).find(\n (node) => node.type === \"parametersNode\"\n );\n if (!parametersNode) {\n return undefined;\n }\n const data = parametersNode.data as ParametersNodeData | undefined;\n if (!data) {\n return undefined;\n }\n return cloneParameters(data.parameters);\n};\n\nexport const extractOutputFromNodes = (\n nodes: Node[]\n): ScaffolderTaskOutput | undefined => {\n const outputNode = sortNodesByY(nodes).find(\n (node) => node.type === \"outputNode\"\n );\n if (!outputNode) {\n return undefined;\n }\n const data = outputNode.data as OutputNodeData | undefined;\n if (!data) {\n return undefined;\n }\n return cloneOutput(data.output);\n};\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { useState } from 'react';
2
+ import { useState, useRef, useEffect } from 'react';
3
3
  import { NodeToolbar, Position, Handle } from '@xyflow/react';
4
4
  import { useTheme, styled } from '@material-ui/core/styles';
5
- import { Typography, TextField, Button, Divider, Box, Chip, IconButton } from '@material-ui/core';
5
+ import { Box, Typography, IconButton, TextField, Button, Divider, Chip } from '@material-ui/core';
6
6
  import DeleteOutlineIcon from '@material-ui/icons/DeleteOutline';
7
7
  import AddIcon from '@material-ui/icons/Add';
8
8
  import Autocomplete from '@material-ui/lab/Autocomplete';
@@ -48,14 +48,21 @@ const ActionNode = ({ data }) => {
48
48
  const [newKey, setNewKey] = useState("");
49
49
  const [newVal, setNewVal] = useState("");
50
50
  const stepOutputReferences = data.stepOutputReferences ?? [];
51
+ const [isConfirmingDelete, setIsConfirmingDelete] = useState(false);
52
+ const deleteConfirmationTimeoutRef = useRef(null);
51
53
  const theme = useTheme();
52
54
  const actionOptions = (data.scaffolderActionIds?.length ?? 0) > 0 ? data.scaffolderActionIds ?? [] : DEFAULT_ACTION_OPTIONS;
53
55
  const handleTop = (field) => (e) => data.onUpdateField?.(rfId, field, e.target.value);
54
56
  const actionId = typeof step?.action === "string" ? step.action : "";
57
+ const [actionInputValue, setActionInputValue] = useState(actionId);
58
+ useEffect(() => {
59
+ setActionInputValue(actionId);
60
+ }, [actionId]);
55
61
  const {
56
62
  actionInputSchema,
57
63
  inputEntries,
58
64
  usedInputKeys,
65
+ missingRequiredInputKeys,
59
66
  availableInputOptions,
60
67
  trimmedNewKey,
61
68
  selectedNewKeyOption,
@@ -63,6 +70,7 @@ const ActionNode = ({ data }) => {
63
70
  newKeyTypeLabel,
64
71
  newKeyEnumOptions
65
72
  } = useActionInputs({ data, step, actionId, newKey });
73
+ const hasMissingRequiredInputs = missingRequiredInputKeys.length > 0;
66
74
  const isAddDisabled = !trimmedNewKey || usedInputKeys.has(trimmedNewKey);
67
75
  const newValueOptions = Array.from(
68
76
  /* @__PURE__ */ new Set([
@@ -71,6 +79,8 @@ const ActionNode = ({ data }) => {
71
79
  ...stepOutputReferences
72
80
  ])
73
81
  );
82
+ const paletteMode = theme.palette.mode ?? theme.palette.type ?? "light";
83
+ const requiredInputsBackground = paletteMode === "dark" ? "rgba(244, 67, 54, 0.2)" : "rgba(244, 67, 54, 0.08)";
74
84
  const addPair = () => {
75
85
  const k = trimmedNewKey;
76
86
  if (!k || usedInputKeys.has(k)) return;
@@ -82,9 +92,78 @@ const ActionNode = ({ data }) => {
82
92
  setNewVal("");
83
93
  };
84
94
  const stopAll = createStopNodeInteraction();
95
+ useEffect(() => {
96
+ if (!isConfirmingDelete) {
97
+ if (deleteConfirmationTimeoutRef.current) {
98
+ clearTimeout(deleteConfirmationTimeoutRef.current);
99
+ deleteConfirmationTimeoutRef.current = null;
100
+ }
101
+ return void 0;
102
+ }
103
+ deleteConfirmationTimeoutRef.current = setTimeout(() => {
104
+ setIsConfirmingDelete(false);
105
+ deleteConfirmationTimeoutRef.current = null;
106
+ }, 3500);
107
+ return () => {
108
+ if (deleteConfirmationTimeoutRef.current) {
109
+ clearTimeout(deleteConfirmationTimeoutRef.current);
110
+ deleteConfirmationTimeoutRef.current = null;
111
+ }
112
+ };
113
+ }, [isConfirmingDelete]);
114
+ const handleDeleteNode = () => {
115
+ if (!data.onRemoveNode) {
116
+ return;
117
+ }
118
+ if (!isConfirmingDelete) {
119
+ setIsConfirmingDelete(true);
120
+ return;
121
+ }
122
+ data.onRemoveNode(rfId);
123
+ setIsConfirmingDelete(false);
124
+ };
85
125
  return /* @__PURE__ */ jsxs(Card, { children: [
86
126
  /* @__PURE__ */ jsxs(Header, { title: step?.name || "Unnamed Step", children: [
87
- /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", noWrap: true, children: step?.name || "Unnamed Step" }),
127
+ /* @__PURE__ */ jsxs(
128
+ Box,
129
+ {
130
+ style: {
131
+ display: "flex",
132
+ alignItems: "center",
133
+ justifyContent: "space-between",
134
+ gap: theme.spacing(1)
135
+ },
136
+ children: [
137
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", noWrap: true, children: step?.name || "Unnamed Step" }),
138
+ data.onRemoveNode && /* @__PURE__ */ jsxs(
139
+ Box,
140
+ {
141
+ style: {
142
+ display: "flex",
143
+ alignItems: "center",
144
+ gap: theme.spacing(0.5),
145
+ color: theme.palette.text.secondary
146
+ },
147
+ children: [
148
+ isConfirmingDelete && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", children: "Click again to delete" }),
149
+ /* @__PURE__ */ jsx(
150
+ IconButton,
151
+ {
152
+ size: "small",
153
+ onClick: handleDeleteNode,
154
+ onPointerDown: (e) => e.stopPropagation(),
155
+ "aria-label": "Remove action",
156
+ color: isConfirmingDelete ? "secondary" : "default",
157
+ className: "nodrag nowheel",
158
+ children: /* @__PURE__ */ jsx(DeleteOutlineIcon, { fontSize: "small" })
159
+ }
160
+ )
161
+ ]
162
+ }
163
+ )
164
+ ]
165
+ }
166
+ ),
88
167
  /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: "Action" }),
89
168
  /* @__PURE__ */ jsx(
90
169
  Autocomplete,
@@ -93,10 +172,29 @@ const ActionNode = ({ data }) => {
93
172
  options: actionOptions,
94
173
  PopperComponent: AutoWidthPopper,
95
174
  freeSolo: true,
96
- value: typeof step?.action === "string" ? step.action : "",
97
- inputValue: typeof step?.action === "string" ? step.action : "",
98
- onChange: (_, newValue) => data.onUpdateField?.(rfId, "action", newValue ?? ""),
99
- onInputChange: (_, newInputValue) => data.onUpdateField?.(rfId, "action", newInputValue ?? ""),
175
+ autoHighlight: true,
176
+ value: actionId,
177
+ inputValue: actionInputValue,
178
+ filterOptions: (options) => {
179
+ const needle = actionInputValue.trim().toLowerCase();
180
+ if (!needle) {
181
+ return options;
182
+ }
183
+ return options.filter((opt) => opt.toLowerCase().includes(needle));
184
+ },
185
+ onChange: (_, newValue) => {
186
+ const nextValue = newValue ?? "";
187
+ setActionInputValue(nextValue);
188
+ data.onUpdateField?.(rfId, "action", nextValue);
189
+ },
190
+ onInputChange: (_, newInputValue, reason) => {
191
+ if (reason === "reset") {
192
+ return;
193
+ }
194
+ const nextValue = newInputValue ?? "";
195
+ setActionInputValue(nextValue);
196
+ data.onUpdateField?.(rfId, "action", nextValue);
197
+ },
100
198
  onPointerDown: stopAll.onPointerDown,
101
199
  onKeyDown: stopAll.onKeyDown,
102
200
  className: stopAll.className,
@@ -308,6 +406,15 @@ const ActionNode = ({ data }) => {
308
406
  PopperComponent: AutoWidthPopper,
309
407
  value: selectedNewKeyOption,
310
408
  inputValue: newKey,
409
+ filterOptions: (options) => {
410
+ const needle = newKey.trim().toLowerCase();
411
+ if (!needle) {
412
+ return options;
413
+ }
414
+ return options.filter(
415
+ (option) => (typeof option === "string" ? option : option.label).toLowerCase().includes(needle)
416
+ );
417
+ },
311
418
  onChange: (_, value) => {
312
419
  if (!value) {
313
420
  setNewKey("");
@@ -390,6 +497,23 @@ const ActionNode = ({ data }) => {
390
497
  value: newVal,
391
498
  inputValue: newVal,
392
499
  fullWidth: true,
500
+ filterOptions: (options) => {
501
+ const needle = newVal.trim().toLowerCase();
502
+ if (!needle) {
503
+ return options;
504
+ }
505
+ return options.filter((option) => {
506
+ const raw = String(option);
507
+ const normalized = raw.replace(/^\s*\$\{\{\s*/, "").replace(/\s*\}\}\s*$/, "");
508
+ const haystacks = [
509
+ raw.toLowerCase(),
510
+ normalized.toLowerCase()
511
+ ];
512
+ return haystacks.some(
513
+ (haystack) => haystack.includes(needle)
514
+ );
515
+ });
516
+ },
393
517
  onChange: (_, value) => setNewVal(value ?? ""),
394
518
  onInputChange: (_, value, reason) => {
395
519
  if (reason === "reset") {
@@ -428,6 +552,45 @@ const ActionNode = ({ data }) => {
428
552
  )
429
553
  ] })
430
554
  ] }),
555
+ hasMissingRequiredInputs && /* @__PURE__ */ jsxs(
556
+ Box,
557
+ {
558
+ sx: {
559
+ mt: 1.5,
560
+ p: 1,
561
+ borderRadius: 1,
562
+ border: `1px solid ${theme.palette.error.main}`
563
+ },
564
+ style: { backgroundColor: requiredInputsBackground },
565
+ children: [
566
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", children: "Missing required inputs" }),
567
+ /* @__PURE__ */ jsx(
568
+ Box,
569
+ {
570
+ sx: {
571
+ display: "flex",
572
+ flexWrap: "wrap",
573
+ mt: 0.75
574
+ },
575
+ style: { gap: theme.spacing(0.5) },
576
+ children: missingRequiredInputKeys.map((key) => /* @__PURE__ */ jsx(
577
+ Chip,
578
+ {
579
+ size: "small",
580
+ variant: "outlined",
581
+ label: key,
582
+ style: {
583
+ borderColor: theme.palette.error.main,
584
+ color: theme.palette.error.main
585
+ }
586
+ },
587
+ key
588
+ ))
589
+ }
590
+ )
591
+ ]
592
+ }
593
+ ),
431
594
  /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top }),
432
595
  /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom })
433
596
  ] });