@tduniec/plugin-template-designer 0.1.7

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.
Files changed (69) hide show
  1. package/README.md +120 -0
  2. package/dist/api/scaffolderActions.esm.js +42 -0
  3. package/dist/api/scaffolderActions.esm.js.map +1 -0
  4. package/dist/components/DesignerFlow/DesignerFlow.esm.js +370 -0
  5. package/dist/components/DesignerFlow/DesignerFlow.esm.js.map +1 -0
  6. package/dist/components/DesignerFlow/flowConfig.esm.js +21 -0
  7. package/dist/components/DesignerFlow/flowConfig.esm.js.map +1 -0
  8. package/dist/components/DesignerFlow/handlers.esm.js +288 -0
  9. package/dist/components/DesignerFlow/handlers.esm.js.map +1 -0
  10. package/dist/components/DesignerFlow/model.esm.js +181 -0
  11. package/dist/components/DesignerFlow/model.esm.js.map +1 -0
  12. package/dist/components/DesignerFlow/nodeLayout.esm.js +138 -0
  13. package/dist/components/DesignerFlow/nodeLayout.esm.js.map +1 -0
  14. package/dist/components/DesignerFlow/parameterTransforms.esm.js +184 -0
  15. package/dist/components/DesignerFlow/parameterTransforms.esm.js.map +1 -0
  16. package/dist/components/Nodes/ActionNode.esm.js +437 -0
  17. package/dist/components/Nodes/ActionNode.esm.js.map +1 -0
  18. package/dist/components/Nodes/OutputNode.esm.js +368 -0
  19. package/dist/components/Nodes/OutputNode.esm.js.map +1 -0
  20. package/dist/components/Nodes/ParameterInputNode.esm.js +310 -0
  21. package/dist/components/Nodes/ParameterInputNode.esm.js.map +1 -0
  22. package/dist/components/Nodes/ParameterTitlesNode.esm.js +251 -0
  23. package/dist/components/Nodes/ParameterTitlesNode.esm.js.map +1 -0
  24. package/dist/components/Nodes/ParametersNode.esm.js +142 -0
  25. package/dist/components/Nodes/ParametersNode.esm.js.map +1 -0
  26. package/dist/components/Nodes/action/schema.esm.js +117 -0
  27. package/dist/components/Nodes/action/schema.esm.js.map +1 -0
  28. package/dist/components/Nodes/action/useActionInputs.esm.js +66 -0
  29. package/dist/components/Nodes/action/useActionInputs.esm.js.map +1 -0
  30. package/dist/components/Nodes/common/AutoWidthPopper.esm.js +22 -0
  31. package/dist/components/Nodes/common/AutoWidthPopper.esm.js.map +1 -0
  32. package/dist/components/Nodes/common/nodeInteraction.esm.js +9 -0
  33. package/dist/components/Nodes/common/nodeInteraction.esm.js.map +1 -0
  34. package/dist/components/Nodes/output/useOutputController.esm.js +191 -0
  35. package/dist/components/Nodes/output/useOutputController.esm.js.map +1 -0
  36. package/dist/components/Nodes/parameters/useParameterSections.esm.js +162 -0
  37. package/dist/components/Nodes/parameters/useParameterSections.esm.js.map +1 -0
  38. package/dist/components/Nodes/types.esm.js +8 -0
  39. package/dist/components/Nodes/types.esm.js.map +1 -0
  40. package/dist/components/TemplateDesigner/TemplateDesigner.esm.js +115 -0
  41. package/dist/components/TemplateDesigner/TemplateDesigner.esm.js.map +1 -0
  42. package/dist/components/TemplateDesigner/components/FieldEditorDialog.esm.js +32 -0
  43. package/dist/components/TemplateDesigner/components/FieldEditorDialog.esm.js.map +1 -0
  44. package/dist/components/TemplateDesigner/components/TemplateLanding.esm.js +102 -0
  45. package/dist/components/TemplateDesigner/components/TemplateLanding.esm.js.map +1 -0
  46. package/dist/components/TemplateDesigner/components/TemplateWorkspace.esm.js +200 -0
  47. package/dist/components/TemplateDesigner/components/TemplateWorkspace.esm.js.map +1 -0
  48. package/dist/components/TemplateDesigner/index.esm.js +2 -0
  49. package/dist/components/TemplateDesigner/index.esm.js.map +1 -0
  50. package/dist/components/TemplateDesigner/useFieldEditor.esm.js +96 -0
  51. package/dist/components/TemplateDesigner/useFieldEditor.esm.js.map +1 -0
  52. package/dist/components/TemplateDesigner/useTemplateState.esm.js +391 -0
  53. package/dist/components/TemplateDesigner/useTemplateState.esm.js.map +1 -0
  54. package/dist/components/TemplateDesigner/utils.esm.js +46 -0
  55. package/dist/components/TemplateDesigner/utils.esm.js.map +1 -0
  56. package/dist/index.d.ts +9 -0
  57. package/dist/index.esm.js +2 -0
  58. package/dist/index.esm.js.map +1 -0
  59. package/dist/plugin.esm.js +19 -0
  60. package/dist/plugin.esm.js.map +1 -0
  61. package/dist/routes.esm.js +8 -0
  62. package/dist/routes.esm.js.map +1 -0
  63. package/dist/utils/createSequentialEdges.esm.js +15 -0
  64. package/dist/utils/createSequentialEdges.esm.js.map +1 -0
  65. package/dist/utils/sampleTemplate.esm.js +40 -0
  66. package/dist/utils/sampleTemplate.esm.js.map +1 -0
  67. package/dist/utils/yamlJsonConversion.esm.js +47 -0
  68. package/dist/utils/yamlJsonConversion.esm.js.map +1 -0
  69. package/package.json +116 -0
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # Backstage Template Designer Plugin
2
+
3
+ **From YAML to Canvas — simplifying Backstage scaffolding**
4
+
5
+ Empowering the **Democratization of Templates** in Backstage 🚀
6
+ Visually **design, connect, and manage** your Backstage scaffolder templates through an **intuitive drag-and-drop interface** — all inside your Backstage instance.
7
+ No YAML complexity. No coding required. Just creativity. **We are breaking the glass!** templating in Backstage made easy! 🚀
8
+
9
+ ---
10
+
11
+ ## 🌟 Why “Democratization of Templates”?
12
+
13
+ Backstage templates shouldn’t be just for developers.
14
+ The Template Designer makes **template creation accessible to everyone** — from DevOps engineers to product teams — enabling true **collaboration and transparency** in how your software templates are built and evolve.
15
+
16
+ ---
17
+
18
+ ## 🚀 Features
19
+
20
+ - ⚡ **Drag & Drop Editing** — visually compose your Backstage scaffolder workflows.
21
+ - 🧩 **Three Node Types**
22
+ - **Action Node** – represents a single scaffolder action.
23
+ - **Template Node** – groups multiple actions into a reusable unit.
24
+ - **Output Node** – defines exported values or pipeline results.
25
+ - 💾 **Work with Files** — open existing template definitions or save your flow as a JSON file directly from the UI.
26
+ - 🔄 **Live Flow Connections** — connect nodes with arrows to define execution order.
27
+ - 💡 **Frontend-Only Plugin** — zero backend setup required.
28
+
29
+ ---
30
+
31
+ ## 🖼️ Preview
32
+
33
+ Checkout the video!
34
+
35
+ [▶ Watch the PREVIEW on YouTube](https://youtu.be/Pwzlzvig4-c)
36
+
37
+ ## ⚙️ Installation
38
+
39
+ From your Backstage root directory
40
+
41
+ ```bash
42
+ yarn add --cwd packages/app @your-org/plugin-template-designer
43
+ ```
44
+
45
+ In packages/app/src/App.tsx:
46
+
47
+ ```tsx
48
+ import { TemplateDesignerPage } from "@your-org/plugin-template-designer";
49
+
50
+ const routes = (
51
+ <FlatRoutes>
52
+ {/* other routes */}
53
+ <Route path="/template-designer" element={<TemplateDesignerPage />} />
54
+ </FlatRoutes>
55
+ );
56
+ ```
57
+
58
+ In `packages/app/src/components/Root/Root.tsx`:
59
+
60
+ ```tsx
61
+ import DesignServicesIcon from "@mui/icons-material/DesignServices";
62
+ import { SidebarItem } from "@backstage/core-components";
63
+
64
+ <SidebarItem
65
+ icon={DesignServicesIcon}
66
+ to="template-designer"
67
+ text="Template Designer"
68
+ />;
69
+ ```
70
+
71
+ ## ⚙️ Usage
72
+
73
+ Visit your local Backstage instance:
74
+
75
+ http://localhost:7007/template-designer
76
+
77
+ Create and connect nodes, adjust properties, and export your flow as a JSON file.
78
+ You can also open an existing template file, modify it visually, and save your changes.
79
+
80
+ ## 💾 File Management
81
+
82
+ Template Designer allows you to easily work with your Backstage scaffolder definitions:
83
+ Open a template file (.json) – load an existing flow directly into the canvas.
84
+ Edit visually – move nodes, adjust connections, rename actions.
85
+ Save – export your template back to a .json file ready for scaffolder integration.
86
+
87
+ _Template Designer can read your registered actions!_
88
+
89
+ ## 🧠 Tech Stack
90
+
91
+ - React + TypeScript
92
+ - React Flow
93
+ - Backstage Core Components
94
+
95
+ ## 🛠️ Development
96
+
97
+ To run locally during development:
98
+
99
+ ```bash
100
+ yarn start
101
+ ```
102
+
103
+ This runs a local Backstage app with hot reload support for your plugin.
104
+
105
+ ## ❤️ Contributing
106
+
107
+ Template Designer is still fresh out of the oven, so rough edges and open questions are expected—and that’s part of the fun.
108
+ If you spot a bug, have an idea, or simply want to riff on better tooling for templates, please open an issue or PR.
109
+
110
+ Help us push forward the Democratization of Templates in Backstage!
111
+ Ideas, feedback, and PRs are all welcome.
112
+
113
+ ## 📄 License
114
+
115
+ Apache-2.0 © 2025 — Created by [tduniec](https://github.com/tduniec)
116
+
117
+ ## 🌐 Roadmap
118
+
119
+ TODO -> please help me gather your **[feedback](https://forms.gle/wqBtpNA3SrDoofgM8)** first!
120
+ Take 2 minutes to fill up the **[survey](https://forms.gle/wqBtpNA3SrDoofgM8)**!
@@ -0,0 +1,42 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { useApi } from '@backstage/core-plugin-api';
3
+ import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';
4
+
5
+ const buildCache = (list) => {
6
+ const { inputsById, outputsById } = list.reduce(
7
+ (acc, action) => {
8
+ acc.inputsById[action.id] = action.schema?.input?.properties ?? {};
9
+ acc.outputsById[action.id] = action.schema?.output?.properties ?? {};
10
+ return acc;
11
+ },
12
+ { inputsById: {}, outputsById: {} }
13
+ );
14
+ return {
15
+ ids: list.map((action) => action.id),
16
+ inputsById,
17
+ outputsById
18
+ };
19
+ };
20
+ const useScaffolderActions = () => {
21
+ const scaffolderApi = useApi(scaffolderApiRef);
22
+ const [cache, setCache] = useState(
23
+ () => buildCache([])
24
+ );
25
+ useEffect(() => {
26
+ let cancelled = false;
27
+ scaffolderApi.listActions().then((remoteActions) => {
28
+ if (cancelled) {
29
+ return;
30
+ }
31
+ setCache(buildCache(remoteActions));
32
+ }).catch(() => {
33
+ });
34
+ return () => {
35
+ cancelled = true;
36
+ };
37
+ }, [scaffolderApi]);
38
+ return cache;
39
+ };
40
+
41
+ export { useScaffolderActions };
42
+ //# sourceMappingURL=scaffolderActions.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffolderActions.esm.js","sources":["../../src/api/scaffolderActions.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { useApi } from \"@backstage/core-plugin-api\";\nimport { scaffolderApiRef } from \"@backstage/plugin-scaffolder-react\";\n\n// Encapsulated hook for loading/caching scaffolder action metadata.\n\ntype ScaffolderAction = {\n id: string;\n schema?: {\n input?: {\n properties?: Record<string, unknown>;\n };\n output?: {\n properties?: Record<string, unknown>;\n };\n };\n};\n\nexport type ScaffolderActionsCache = {\n ids: string[];\n inputsById: Record<string, Record<string, unknown>>;\n outputsById: Record<string, Record<string, unknown>>;\n};\n\nconst buildCache = (list: ScaffolderAction[]): ScaffolderActionsCache => {\n const { inputsById, outputsById } = list.reduce<{\n inputsById: Record<string, Record<string, unknown>>;\n outputsById: Record<string, Record<string, unknown>>;\n }>(\n (acc, action) => {\n acc.inputsById[action.id] = action.schema?.input?.properties ?? {};\n acc.outputsById[action.id] = action.schema?.output?.properties ?? {};\n return acc;\n },\n { inputsById: {}, outputsById: {} }\n );\n\n return {\n ids: list.map((action) => action.id),\n inputsById,\n outputsById,\n };\n};\n\nexport const useScaffolderActions = () => {\n const scaffolderApi = useApi(scaffolderApiRef);\n const [cache, setCache] = useState<ScaffolderActionsCache>(() =>\n buildCache([])\n );\n\n useEffect(() => {\n let cancelled = false;\n\n scaffolderApi\n .listActions()\n .then((remoteActions) => {\n if (cancelled) {\n return;\n }\n setCache(buildCache(remoteActions));\n })\n .catch(() => {});\n\n return () => {\n cancelled = true;\n };\n }, [scaffolderApi]);\n\n return cache;\n};\n"],"names":[],"mappings":";;;;AAwBA,MAAM,UAAA,GAAa,CAAC,IAAA,KAAqD;AACvE,EAAA,MAAM,EAAE,UAAA,EAAY,WAAA,EAAY,GAAI,IAAA,CAAK,MAAA;AAAA,IAIvC,CAAC,KAAK,MAAA,KAAW;AACf,MAAA,GAAA,CAAI,UAAA,CAAW,OAAO,EAAE,CAAA,GAAI,OAAO,MAAA,EAAQ,KAAA,EAAO,cAAc,EAAC;AACjE,MAAA,GAAA,CAAI,WAAA,CAAY,OAAO,EAAE,CAAA,GAAI,OAAO,MAAA,EAAQ,MAAA,EAAQ,cAAc,EAAC;AACnE,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IACA,EAAE,UAAA,EAAY,EAAC,EAAG,WAAA,EAAa,EAAC;AAAE,GACpC;AAEA,EAAA,OAAO;AAAA,IACL,KAAK,IAAA,CAAK,GAAA,CAAI,CAAC,MAAA,KAAW,OAAO,EAAE,CAAA;AAAA,IACnC,UAAA;AAAA,IACA;AAAA,GACF;AACF,CAAA;AAEO,MAAM,uBAAuB,MAAM;AACxC,EAAA,MAAM,aAAA,GAAgB,OAAO,gBAAgB,CAAA;AAC7C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA;AAAA,IAAiC,MACzD,UAAA,CAAW,EAAE;AAAA,GACf;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,IAAA,aAAA,CACG,WAAA,EAAY,CACZ,IAAA,CAAK,CAAC,aAAA,KAAkB;AACvB,MAAA,IAAI,SAAA,EAAW;AACb,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,UAAA,CAAW,aAAa,CAAC,CAAA;AAAA,IACpC,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAEjB,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAA,OAAO,KAAA;AACT;;;;"}
@@ -0,0 +1,370 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useMemo, useState, useRef, useEffect, useCallback } from 'react';
3
+ import { useNodesState, applyNodeChanges, applyEdgeChanges, addEdge, ReactFlow } from '@xyflow/react';
4
+ import '@xyflow/react/dist/style.css';
5
+ import { createSequentialEdges } from '../../utils/createSequentialEdges.esm.js';
6
+ import { collectStepOutputReferences, createHandleReorderAndAlignNodes, createHandleUpdateField, createHandleUpdateInput, createHandleRemoveInputKey, createHandleUpdateOutput, createHandleUpdateSections, createHandleAddNode } from './handlers.esm.js';
7
+ import { buildNodesFromModel, stableStringify, resolveNodeHeightForTracking, collectParameterReferences, extractStepsFromNodes, extractParametersFromNodes, extractOutputFromNodes } from './model.esm.js';
8
+ import { alignNodes } from './nodeLayout.esm.js';
9
+ import { nodeTypes, FLOW_LAYOUT, nodeDefaults } from './flowConfig.esm.js';
10
+ import { useScaffolderActions } from '../../api/scaffolderActions.esm.js';
11
+
12
+ const FIXED_X_POSITION = FLOW_LAYOUT.fixedXPosition;
13
+ const VERTICAL_SPACING = FLOW_LAYOUT.verticalSpacing;
14
+ function App({
15
+ steps = [],
16
+ parameters,
17
+ output,
18
+ onStepsChange,
19
+ onParametersChange,
20
+ onOutputChange
21
+ }) {
22
+ const scaffolderActionsCache = useScaffolderActions();
23
+ const {
24
+ ids: scaffolderActionIds,
25
+ inputsById: scaffolderActionInputsById,
26
+ outputsById: scaffolderActionOutputsById
27
+ } = scaffolderActionsCache;
28
+ const normalizedParametersProp = parameters ?? void 0;
29
+ const normalizedOutputProp = output ?? null;
30
+ const initialNodes = useMemo(
31
+ () => buildNodesFromModel(
32
+ steps,
33
+ normalizedParametersProp,
34
+ normalizedOutputProp,
35
+ {
36
+ scaffolderActionIds,
37
+ scaffolderActionInputsById,
38
+ scaffolderActionOutputsById
39
+ }
40
+ ),
41
+ [
42
+ steps,
43
+ normalizedParametersProp,
44
+ normalizedOutputProp,
45
+ scaffolderActionIds,
46
+ scaffolderActionInputsById,
47
+ scaffolderActionOutputsById
48
+ ]
49
+ );
50
+ const [nodes, setNodes] = useNodesState(initialNodes);
51
+ const [edges, setEdges] = useState(
52
+ () => createSequentialEdges(initialNodes)
53
+ );
54
+ const modelHash = useMemo(
55
+ () => stableStringify({
56
+ steps,
57
+ parameters: normalizedParametersProp,
58
+ output: normalizedOutputProp
59
+ }),
60
+ [steps, normalizedParametersProp, normalizedOutputProp]
61
+ );
62
+ const cacheFingerprint = useMemo(
63
+ () => stableStringify({
64
+ ids: scaffolderActionIds,
65
+ inputs: scaffolderActionInputsById,
66
+ outputs: scaffolderActionOutputsById
67
+ }),
68
+ [
69
+ scaffolderActionIds,
70
+ scaffolderActionInputsById,
71
+ scaffolderActionOutputsById
72
+ ]
73
+ );
74
+ const lastAppliedModelHashRef = useRef(null);
75
+ const lastEmittedModelHashRef = useRef(null);
76
+ const skipNextModelHashRef = useRef(null);
77
+ const lastCacheFingerprintRef = useRef(null);
78
+ const nodeHeightsRef = useRef({});
79
+ const shouldAutoFitViewRef = useRef(true);
80
+ useEffect(() => {
81
+ const isCacheChanged = cacheFingerprint !== lastCacheFingerprintRef.current;
82
+ const shouldSkip = modelHash === skipNextModelHashRef.current && !isCacheChanged;
83
+ if (shouldSkip) {
84
+ skipNextModelHashRef.current = null;
85
+ lastAppliedModelHashRef.current = modelHash;
86
+ lastCacheFingerprintRef.current = cacheFingerprint;
87
+ return;
88
+ }
89
+ if (modelHash === lastAppliedModelHashRef.current && !isCacheChanged) {
90
+ return;
91
+ }
92
+ const nextNodes = buildNodesFromModel(
93
+ steps,
94
+ normalizedParametersProp,
95
+ normalizedOutputProp,
96
+ {
97
+ scaffolderActionIds,
98
+ scaffolderActionInputsById,
99
+ scaffolderActionOutputsById
100
+ }
101
+ );
102
+ lastAppliedModelHashRef.current = modelHash;
103
+ lastCacheFingerprintRef.current = cacheFingerprint;
104
+ lastEmittedModelHashRef.current = modelHash;
105
+ setNodes(nextNodes);
106
+ setEdges(createSequentialEdges(nextNodes));
107
+ shouldAutoFitViewRef.current = true;
108
+ }, [
109
+ steps,
110
+ normalizedParametersProp,
111
+ normalizedOutputProp,
112
+ modelHash,
113
+ cacheFingerprint,
114
+ scaffolderActionIds,
115
+ scaffolderActionInputsById,
116
+ scaffolderActionOutputsById,
117
+ setNodes,
118
+ setEdges
119
+ ]);
120
+ useEffect(() => {
121
+ if (!nodes.length) {
122
+ return;
123
+ }
124
+ if (nodes.some((node) => node.dragging)) {
125
+ return;
126
+ }
127
+ const activeNodeIds = /* @__PURE__ */ new Set();
128
+ let hasMeasuredChange = false;
129
+ nodes.forEach((node) => {
130
+ activeNodeIds.add(node.id);
131
+ const measuredHeight = resolveNodeHeightForTracking(node);
132
+ if (typeof measuredHeight !== "number") {
133
+ return;
134
+ }
135
+ const previousHeight = nodeHeightsRef.current[node.id];
136
+ if (previousHeight !== measuredHeight) {
137
+ nodeHeightsRef.current[node.id] = measuredHeight;
138
+ hasMeasuredChange = true;
139
+ }
140
+ });
141
+ Object.keys(nodeHeightsRef.current).forEach((id) => {
142
+ if (!activeNodeIds.has(id)) {
143
+ delete nodeHeightsRef.current[id];
144
+ }
145
+ });
146
+ if (!hasMeasuredChange) {
147
+ return;
148
+ }
149
+ setNodes((currentNodes) => {
150
+ const alignedNodes = alignNodes(
151
+ currentNodes,
152
+ FIXED_X_POSITION,
153
+ VERTICAL_SPACING
154
+ );
155
+ const positionsChanged = alignedNodes.some((node, index) => {
156
+ const previousNode = currentNodes[index];
157
+ if (!previousNode) {
158
+ return true;
159
+ }
160
+ return node.position.x !== previousNode.position.x || node.position.y !== previousNode.position.y;
161
+ });
162
+ return positionsChanged ? alignedNodes : currentNodes;
163
+ });
164
+ }, [nodes, setNodes]);
165
+ const parameterReferences = useMemo(
166
+ () => collectParameterReferences(normalizedParametersProp),
167
+ [normalizedParametersProp]
168
+ );
169
+ const stepOutputReferencesByNode = useMemo(
170
+ () => collectStepOutputReferences(nodes, parameterReferences),
171
+ [nodes, parameterReferences]
172
+ );
173
+ const onNodesChange = useCallback(
174
+ (changes) => setNodes((ns) => applyNodeChanges(changes, ns)),
175
+ [setNodes]
176
+ );
177
+ const onEdgesChange = useCallback(
178
+ (changes) => setEdges((es) => applyEdgeChanges(changes, es)),
179
+ [setEdges]
180
+ );
181
+ const onConnect = useCallback(
182
+ (params) => setEdges((es) => addEdge(params, es)),
183
+ [setEdges]
184
+ );
185
+ const reorderAndAlignNodes = useMemo(
186
+ () => createHandleReorderAndAlignNodes(setNodes, setEdges, {
187
+ fixedXPosition: FIXED_X_POSITION,
188
+ verticalSpacing: VERTICAL_SPACING
189
+ }),
190
+ [setNodes, setEdges]
191
+ );
192
+ const onNodeDragStop = useCallback(
193
+ (_, node) => {
194
+ reorderAndAlignNodes(node);
195
+ },
196
+ [reorderAndAlignNodes]
197
+ );
198
+ const onUpdateField = useMemo(
199
+ () => createHandleUpdateField(setNodes),
200
+ [setNodes]
201
+ );
202
+ const onUpdateInput = useMemo(
203
+ () => createHandleUpdateInput(setNodes),
204
+ [setNodes]
205
+ );
206
+ const onRemoveInputKey = useMemo(
207
+ () => createHandleRemoveInputKey(setNodes),
208
+ [setNodes]
209
+ );
210
+ const onUpdateOutput = useMemo(
211
+ () => createHandleUpdateOutput(setNodes),
212
+ [setNodes]
213
+ );
214
+ const onUpdateSections = useMemo(
215
+ () => createHandleUpdateSections(setNodes),
216
+ [setNodes]
217
+ );
218
+ const handleAddNode = useMemo(
219
+ () => createHandleAddNode(setNodes, setEdges, {
220
+ fixedXPosition: FIXED_X_POSITION,
221
+ verticalSpacing: VERTICAL_SPACING,
222
+ nodeDefaults,
223
+ scaffolderActionIds,
224
+ scaffolderActionInputsById,
225
+ scaffolderActionOutputsById
226
+ }),
227
+ [
228
+ scaffolderActionIds,
229
+ scaffolderActionInputsById,
230
+ scaffolderActionOutputsById,
231
+ setNodes,
232
+ setEdges
233
+ ]
234
+ );
235
+ const nodesWithHandlers = useMemo(
236
+ () => nodes.map((node) => {
237
+ const stepOutputReferences = stepOutputReferencesByNode[node.id] ?? [];
238
+ if (node.type === "parametersNode") {
239
+ const data2 = node.data;
240
+ return {
241
+ ...node,
242
+ data: {
243
+ ...data2,
244
+ onAddNode: handleAddNode,
245
+ onUpdateSections,
246
+ stepOutputReferences
247
+ }
248
+ };
249
+ }
250
+ if (node.type === "outputNode") {
251
+ const data2 = node.data;
252
+ return {
253
+ ...node,
254
+ data: {
255
+ ...data2,
256
+ onAddNode: handleAddNode,
257
+ onUpdateOutput,
258
+ stepOutputReferences
259
+ }
260
+ };
261
+ }
262
+ const data = node.data;
263
+ return {
264
+ ...node,
265
+ data: {
266
+ ...data,
267
+ onAddNode: handleAddNode,
268
+ onUpdateField,
269
+ onUpdateInput,
270
+ onRemoveInputKey,
271
+ stepOutputReferences
272
+ }
273
+ };
274
+ }),
275
+ [
276
+ nodes,
277
+ handleAddNode,
278
+ onUpdateField,
279
+ onUpdateInput,
280
+ onRemoveInputKey,
281
+ onUpdateOutput,
282
+ onUpdateSections,
283
+ stepOutputReferencesByNode
284
+ ]
285
+ );
286
+ const stepsFromNodes = useMemo(() => extractStepsFromNodes(nodes), [nodes]);
287
+ const parametersFromNodes = useMemo(
288
+ () => extractParametersFromNodes(nodes),
289
+ [nodes]
290
+ );
291
+ const outputFromNodes = useMemo(() => extractOutputFromNodes(nodes), [nodes]);
292
+ const normalizedOutputFromNodes = outputFromNodes ?? null;
293
+ useEffect(() => {
294
+ if (!onStepsChange && !onParametersChange && !onOutputChange) {
295
+ return;
296
+ }
297
+ const serialized = stableStringify({
298
+ steps: stepsFromNodes,
299
+ parameters: parametersFromNodes ?? null,
300
+ output: normalizedOutputFromNodes
301
+ });
302
+ if (serialized === lastEmittedModelHashRef.current) {
303
+ return;
304
+ }
305
+ lastEmittedModelHashRef.current = serialized;
306
+ skipNextModelHashRef.current = serialized;
307
+ if (onStepsChange) {
308
+ onStepsChange(stepsFromNodes);
309
+ }
310
+ if (onParametersChange) {
311
+ onParametersChange(parametersFromNodes ?? void 0);
312
+ }
313
+ if (onOutputChange) {
314
+ onOutputChange(outputFromNodes);
315
+ }
316
+ }, [
317
+ stepsFromNodes,
318
+ parametersFromNodes,
319
+ normalizedOutputFromNodes,
320
+ outputFromNodes,
321
+ onStepsChange,
322
+ onParametersChange,
323
+ onOutputChange
324
+ ]);
325
+ const fitViewOptions = useMemo(() => ({ padding: 0.2, duration: 300 }), []);
326
+ const [reactFlowInstance, setReactFlowInstance] = useState(null);
327
+ const fitFlowToView = useCallback(() => {
328
+ if (!reactFlowInstance) {
329
+ return;
330
+ }
331
+ reactFlowInstance.fitView(fitViewOptions);
332
+ }, [fitViewOptions, reactFlowInstance]);
333
+ useEffect(() => {
334
+ if (!reactFlowInstance) {
335
+ return;
336
+ }
337
+ if (!shouldAutoFitViewRef.current) {
338
+ return;
339
+ }
340
+ shouldAutoFitViewRef.current = false;
341
+ fitFlowToView();
342
+ }, [fitFlowToView, nodes, edges, reactFlowInstance]);
343
+ useEffect(() => {
344
+ if (!reactFlowInstance) {
345
+ return void 0;
346
+ }
347
+ window.addEventListener("resize", fitFlowToView);
348
+ return () => {
349
+ window.removeEventListener("resize", fitFlowToView);
350
+ };
351
+ }, [fitFlowToView, reactFlowInstance]);
352
+ return /* @__PURE__ */ jsx("div", { style: { width: "100%", height: "100%", minHeight: "70vh" }, children: /* @__PURE__ */ jsx(
353
+ ReactFlow,
354
+ {
355
+ nodes: nodesWithHandlers,
356
+ edges,
357
+ nodeTypes,
358
+ onNodesChange,
359
+ onEdgesChange,
360
+ onNodeDragStop,
361
+ onConnect,
362
+ fitView: true,
363
+ onInit: setReactFlowInstance,
364
+ fitViewOptions
365
+ }
366
+ ) });
367
+ }
368
+
369
+ export { App as default };
370
+ //# sourceMappingURL=DesignerFlow.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DesignerFlow.esm.js","sources":["../../../src/components/DesignerFlow/DesignerFlow.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { MouseEvent as ReactMouseEvent } from \"react\";\nimport {\n ReactFlow,\n applyNodeChanges,\n applyEdgeChanges,\n addEdge,\n Node,\n Edge,\n NodeChange,\n EdgeChange,\n useNodesState,\n ReactFlowInstance,\n} from \"@xyflow/react\";\nimport \"@xyflow/react/dist/style.css\";\nimport type {\n ScaffolderTaskOutput,\n TaskStep,\n} from \"@backstage/plugin-scaffolder-common\";\nimport type {\n ActionNodeData,\n OutputNodeData,\n ParametersNodeData,\n TemplateParametersValue,\n} from \"../Nodes/types\";\nimport { createSequentialEdges } from \"../../utils/createSequentialEdges\";\nimport {\n collectStepOutputReferences,\n createHandleAddNode,\n createHandleRemoveInputKey,\n createHandleReorderAndAlignNodes,\n createHandleUpdateField,\n createHandleUpdateInput,\n createHandleUpdateOutput,\n createHandleUpdateSections,\n} from \"./handlers\";\nimport {\n buildNodesFromModel,\n collectParameterReferences,\n stableStringify,\n resolveNodeHeightForTracking,\n extractStepsFromNodes,\n extractParametersFromNodes,\n extractOutputFromNodes,\n} from \"./model\";\nimport { alignNodes } from \"./nodeLayout\";\nimport { FLOW_LAYOUT, nodeDefaults, nodeTypes } from \"./flowConfig\";\nimport { useScaffolderActions } from \"../../api/scaffolderActions\";\n\n// Main orchestration component that renders and synchronizes the Designer flow.\n\nconst FIXED_X_POSITION = FLOW_LAYOUT.fixedXPosition;\nconst VERTICAL_SPACING = FLOW_LAYOUT.verticalSpacing;\n\ntype DesignerFlowProps = {\n steps?: TaskStep[];\n parameters?: TemplateParametersValue;\n output?: ScaffolderTaskOutput | null;\n onStepsChange?: (steps: TaskStep[]) => void;\n onParametersChange?: (parameters: TemplateParametersValue) => void;\n onOutputChange?: (output: ScaffolderTaskOutput | undefined) => void;\n};\n\nexport default function App({\n steps = [],\n parameters,\n output,\n onStepsChange,\n onParametersChange,\n onOutputChange,\n}: DesignerFlowProps) {\n const scaffolderActionsCache = useScaffolderActions();\n\n const {\n ids: scaffolderActionIds,\n inputsById: scaffolderActionInputsById,\n outputsById: scaffolderActionOutputsById,\n } = scaffolderActionsCache;\n\n const normalizedParametersProp = parameters ?? undefined;\n const normalizedOutputProp = output ?? null;\n\n const initialNodes = useMemo(\n () =>\n buildNodesFromModel(\n steps,\n normalizedParametersProp,\n normalizedOutputProp,\n {\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n }\n ),\n [\n steps,\n normalizedParametersProp,\n normalizedOutputProp,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n ]\n );\n\n const [nodes, setNodes] = useNodesState(initialNodes);\n const [edges, setEdges] = useState<Edge[]>(() =>\n createSequentialEdges(initialNodes)\n );\n\n const modelHash = useMemo(\n () =>\n stableStringify({\n steps,\n parameters: normalizedParametersProp,\n output: normalizedOutputProp,\n }),\n [steps, normalizedParametersProp, normalizedOutputProp]\n );\n\n const cacheFingerprint = useMemo(\n () =>\n stableStringify({\n ids: scaffolderActionIds,\n inputs: scaffolderActionInputsById,\n outputs: scaffolderActionOutputsById,\n }),\n [\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n ]\n );\n\n const lastAppliedModelHashRef = useRef<string | null>(null);\n const lastEmittedModelHashRef = useRef<string | null>(null);\n const skipNextModelHashRef = useRef<string | null>(null);\n const lastCacheFingerprintRef = useRef<string | null>(null);\n const nodeHeightsRef = useRef<Record<string, number>>({});\n const shouldAutoFitViewRef = useRef(true);\n\n useEffect(() => {\n const isCacheChanged = cacheFingerprint !== lastCacheFingerprintRef.current;\n const shouldSkip =\n modelHash === skipNextModelHashRef.current && !isCacheChanged;\n\n if (shouldSkip) {\n skipNextModelHashRef.current = null;\n lastAppliedModelHashRef.current = modelHash;\n lastCacheFingerprintRef.current = cacheFingerprint;\n return;\n }\n\n if (modelHash === lastAppliedModelHashRef.current && !isCacheChanged) {\n return;\n }\n\n const nextNodes = buildNodesFromModel(\n steps,\n normalizedParametersProp,\n normalizedOutputProp,\n {\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n }\n );\n\n lastAppliedModelHashRef.current = modelHash;\n lastCacheFingerprintRef.current = cacheFingerprint;\n lastEmittedModelHashRef.current = modelHash;\n\n setNodes(nextNodes);\n setEdges(createSequentialEdges(nextNodes));\n shouldAutoFitViewRef.current = true;\n }, [\n steps,\n normalizedParametersProp,\n normalizedOutputProp,\n modelHash,\n cacheFingerprint,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n setNodes,\n setEdges,\n ]);\n\n useEffect(() => {\n if (!nodes.length) {\n return;\n }\n\n if (nodes.some((node) => node.dragging)) {\n return;\n }\n\n const activeNodeIds = new Set<string>();\n let hasMeasuredChange = false;\n\n nodes.forEach((node) => {\n activeNodeIds.add(node.id);\n const measuredHeight = resolveNodeHeightForTracking(node);\n if (typeof measuredHeight !== \"number\") {\n return;\n }\n const previousHeight = nodeHeightsRef.current[node.id];\n if (previousHeight !== measuredHeight) {\n nodeHeightsRef.current[node.id] = measuredHeight;\n hasMeasuredChange = true;\n }\n });\n\n Object.keys(nodeHeightsRef.current).forEach((id) => {\n if (!activeNodeIds.has(id)) {\n delete nodeHeightsRef.current[id];\n }\n });\n\n if (!hasMeasuredChange) {\n return;\n }\n\n setNodes((currentNodes) => {\n const alignedNodes = alignNodes(\n currentNodes,\n FIXED_X_POSITION,\n VERTICAL_SPACING\n );\n const positionsChanged = alignedNodes.some((node, index) => {\n const previousNode = currentNodes[index];\n if (!previousNode) {\n return true;\n }\n return (\n node.position.x !== previousNode.position.x ||\n node.position.y !== previousNode.position.y\n );\n });\n\n return positionsChanged ? alignedNodes : currentNodes;\n });\n }, [nodes, setNodes]);\n\n const parameterReferences = useMemo(\n () => collectParameterReferences(normalizedParametersProp),\n [normalizedParametersProp]\n );\n\n const stepOutputReferencesByNode = useMemo(\n () => collectStepOutputReferences(nodes, parameterReferences),\n [nodes, parameterReferences]\n );\n\n const onNodesChange = useCallback(\n (changes: NodeChange<Node>[]) =>\n setNodes((ns) => applyNodeChanges(changes, ns)),\n [setNodes]\n );\n\n const onEdgesChange = useCallback(\n (changes: EdgeChange<Edge>[]) =>\n setEdges((es) => applyEdgeChanges(changes, es)),\n [setEdges]\n );\n\n const onConnect = useCallback(\n (params: any) => setEdges((es) => addEdge(params, es)),\n [setEdges]\n );\n\n const reorderAndAlignNodes = useMemo(\n () =>\n createHandleReorderAndAlignNodes(setNodes, setEdges, {\n fixedXPosition: FIXED_X_POSITION,\n verticalSpacing: VERTICAL_SPACING,\n }),\n [setNodes, setEdges]\n );\n\n const onNodeDragStop = useCallback(\n (_: ReactMouseEvent, node: Node) => {\n reorderAndAlignNodes(node);\n },\n [reorderAndAlignNodes]\n );\n\n const onUpdateField = useMemo(\n () => createHandleUpdateField(setNodes),\n [setNodes]\n );\n\n const onUpdateInput = useMemo(\n () => createHandleUpdateInput(setNodes),\n [setNodes]\n );\n\n const onRemoveInputKey = useMemo(\n () => createHandleRemoveInputKey(setNodes),\n [setNodes]\n );\n\n const onUpdateOutput = useMemo(\n () => createHandleUpdateOutput(setNodes),\n [setNodes]\n );\n\n const onUpdateSections = useMemo(\n () => createHandleUpdateSections(setNodes),\n [setNodes]\n );\n\n const handleAddNode = useMemo(\n () =>\n createHandleAddNode(setNodes, setEdges, {\n fixedXPosition: FIXED_X_POSITION,\n verticalSpacing: VERTICAL_SPACING,\n nodeDefaults,\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n }),\n [\n scaffolderActionIds,\n scaffolderActionInputsById,\n scaffolderActionOutputsById,\n setNodes,\n setEdges,\n ]\n );\n\n const nodesWithHandlers = useMemo(\n () =>\n nodes.map((node) => {\n const stepOutputReferences = stepOutputReferencesByNode[node.id] ?? [];\n if (node.type === \"parametersNode\") {\n const data = node.data as ParametersNodeData;\n return {\n ...node,\n data: {\n ...data,\n onAddNode: handleAddNode,\n onUpdateSections,\n stepOutputReferences,\n },\n };\n }\n if (node.type === \"outputNode\") {\n const data = node.data as OutputNodeData;\n return {\n ...node,\n data: {\n ...data,\n onAddNode: handleAddNode,\n onUpdateOutput,\n stepOutputReferences,\n },\n };\n }\n\n const data = node.data as ActionNodeData;\n return {\n ...node,\n data: {\n ...data,\n onAddNode: handleAddNode,\n onUpdateField,\n onUpdateInput,\n onRemoveInputKey,\n stepOutputReferences,\n },\n };\n }),\n [\n nodes,\n handleAddNode,\n onUpdateField,\n onUpdateInput,\n onRemoveInputKey,\n onUpdateOutput,\n onUpdateSections,\n stepOutputReferencesByNode,\n ]\n );\n\n const stepsFromNodes = useMemo(() => extractStepsFromNodes(nodes), [nodes]);\n\n const parametersFromNodes = useMemo(\n () => extractParametersFromNodes(nodes),\n [nodes]\n );\n\n const outputFromNodes = useMemo(() => extractOutputFromNodes(nodes), [nodes]);\n\n const normalizedOutputFromNodes = outputFromNodes ?? null;\n\n useEffect(() => {\n if (!onStepsChange && !onParametersChange && !onOutputChange) {\n return;\n }\n const serialized = stableStringify({\n steps: stepsFromNodes,\n parameters: parametersFromNodes ?? null,\n output: normalizedOutputFromNodes,\n });\n if (serialized === lastEmittedModelHashRef.current) {\n return;\n }\n lastEmittedModelHashRef.current = serialized;\n skipNextModelHashRef.current = serialized;\n if (onStepsChange) {\n onStepsChange(stepsFromNodes);\n }\n if (onParametersChange) {\n onParametersChange(parametersFromNodes ?? undefined);\n }\n if (onOutputChange) {\n onOutputChange(outputFromNodes);\n }\n }, [\n stepsFromNodes,\n parametersFromNodes,\n normalizedOutputFromNodes,\n outputFromNodes,\n onStepsChange,\n onParametersChange,\n onOutputChange,\n ]);\n\n const fitViewOptions = useMemo(() => ({ padding: 0.2, duration: 300 }), []);\n const [reactFlowInstance, setReactFlowInstance] =\n useState<ReactFlowInstance | null>(null);\n\n const fitFlowToView = useCallback(() => {\n if (!reactFlowInstance) {\n return;\n }\n reactFlowInstance.fitView(fitViewOptions);\n }, [fitViewOptions, reactFlowInstance]);\n\n useEffect(() => {\n if (!reactFlowInstance) {\n return;\n }\n if (!shouldAutoFitViewRef.current) {\n return;\n }\n shouldAutoFitViewRef.current = false;\n fitFlowToView();\n }, [fitFlowToView, nodes, edges, reactFlowInstance]);\n\n useEffect(() => {\n if (!reactFlowInstance) {\n return undefined;\n }\n window.addEventListener(\"resize\", fitFlowToView);\n return () => {\n window.removeEventListener(\"resize\", fitFlowToView);\n };\n }, [fitFlowToView, reactFlowInstance]);\n\n return (\n <div style={{ width: \"100%\", height: \"100%\", minHeight: \"70vh\" }}>\n <ReactFlow\n nodes={nodesWithHandlers}\n edges={edges}\n nodeTypes={nodeTypes}\n onNodesChange={onNodesChange}\n onEdgesChange={onEdgesChange}\n onNodeDragStop={onNodeDragStop}\n onConnect={onConnect}\n fitView\n onInit={setReactFlowInstance}\n fitViewOptions={fitViewOptions}\n />\n </div>\n );\n}\n"],"names":["data"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { Position } from '@xyflow/react';
2
+ import { ActionNode } from '../Nodes/ActionNode.esm.js';
3
+ import { ParametersNode } from '../Nodes/ParametersNode.esm.js';
4
+ import { OutputNode } from '../Nodes/OutputNode.esm.js';
5
+
6
+ const FLOW_LAYOUT = {
7
+ verticalSpacing: 400,
8
+ fixedXPosition: 100
9
+ };
10
+ const nodeTypes = {
11
+ parametersNode: ParametersNode,
12
+ actionNode: ActionNode,
13
+ outputNode: OutputNode
14
+ };
15
+ const nodeDefaults = {
16
+ sourcePosition: Position.Bottom,
17
+ targetPosition: Position.Top
18
+ };
19
+
20
+ export { FLOW_LAYOUT, nodeDefaults, nodeTypes };
21
+ //# sourceMappingURL=flowConfig.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowConfig.esm.js","sources":["../../../src/components/DesignerFlow/flowConfig.ts"],"sourcesContent":["import { Position } from \"@xyflow/react\";\nimport { ActionNode } from \"../Nodes/ActionNode\";\nimport { ParametersNode } from \"../Nodes/ParametersNode\";\nimport { OutputNode } from \"../Nodes/OutputNode\";\n\n// Centralized flow layout + node type definitions consumed across DesignerFlow.\n\nexport const FLOW_LAYOUT = {\n verticalSpacing: 400,\n fixedXPosition: 100,\n} as const;\n\nexport const nodeTypes = {\n parametersNode: ParametersNode,\n actionNode: ActionNode,\n outputNode: OutputNode,\n};\n\nexport const nodeDefaults = {\n sourcePosition: Position.Bottom,\n targetPosition: Position.Top,\n};\n"],"names":[],"mappings":";;;;;AAOO,MAAM,WAAA,GAAc;AAAA,EACzB,eAAA,EAAiB,GAAA;AAAA,EACjB,cAAA,EAAgB;AAClB;AAEO,MAAM,SAAA,GAAY;AAAA,EACvB,cAAA,EAAgB,cAAA;AAAA,EAChB,UAAA,EAAY,UAAA;AAAA,EACZ,UAAA,EAAY;AACd;AAEO,MAAM,YAAA,GAAe;AAAA,EAC1B,gBAAgB,QAAA,CAAS,MAAA;AAAA,EACzB,gBAAgB,QAAA,CAAS;AAC3B;;;;"}