@tduniec/plugin-template-designer-foundation 0.1.1

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 (78) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +13 -0
  3. package/dist/api/useScaffolderActions.esm.js +59 -0
  4. package/dist/api/useScaffolderActions.esm.js.map +1 -0
  5. package/dist/components/FieldEditorDialog.esm.js +55 -0
  6. package/dist/components/FieldEditorDialog.esm.js.map +1 -0
  7. package/dist/components/Nodes/ActionNode.esm.js +613 -0
  8. package/dist/components/Nodes/ActionNode.esm.js.map +1 -0
  9. package/dist/components/Nodes/OutputNode.esm.js +373 -0
  10. package/dist/components/Nodes/OutputNode.esm.js.map +1 -0
  11. package/dist/components/Nodes/ParameterInputNode.esm.js +320 -0
  12. package/dist/components/Nodes/ParameterInputNode.esm.js.map +1 -0
  13. package/dist/components/Nodes/ParameterTitlesNode.esm.js +251 -0
  14. package/dist/components/Nodes/ParameterTitlesNode.esm.js.map +1 -0
  15. package/dist/components/Nodes/ParametersNode.esm.js +147 -0
  16. package/dist/components/Nodes/ParametersNode.esm.js.map +1 -0
  17. package/dist/components/Nodes/action/schema.esm.js +68 -0
  18. package/dist/components/Nodes/action/schema.esm.js.map +1 -0
  19. package/dist/components/Nodes/action/useActionInputs.esm.js +71 -0
  20. package/dist/components/Nodes/action/useActionInputs.esm.js.map +1 -0
  21. package/dist/components/Nodes/common/AutoWidthPopper.esm.js +11 -0
  22. package/dist/components/Nodes/common/AutoWidthPopper.esm.js.map +1 -0
  23. package/dist/components/Nodes/common/nodeInteraction.esm.js +20 -0
  24. package/dist/components/Nodes/common/nodeInteraction.esm.js.map +1 -0
  25. package/dist/components/Nodes/output/useOutputController.esm.js +125 -0
  26. package/dist/components/Nodes/output/useOutputController.esm.js.map +1 -0
  27. package/dist/components/TemplateDesigner/TemplateLanding.esm.js +157 -0
  28. package/dist/components/TemplateDesigner/TemplateLanding.esm.js.map +1 -0
  29. package/dist/components/TemplateDesigner/TemplateWorkspace.esm.js +416 -0
  30. package/dist/components/TemplateDesigner/TemplateWorkspace.esm.js.map +1 -0
  31. package/dist/components/TemplateDesigner/codemirrorTheme.esm.js +30 -0
  32. package/dist/components/TemplateDesigner/codemirrorTheme.esm.js.map +1 -0
  33. package/dist/components/TemplateDesigner/useFieldEditor.esm.js +95 -0
  34. package/dist/components/TemplateDesigner/useFieldEditor.esm.js.map +1 -0
  35. package/dist/components/TemplateDesignerIcon.esm.js +33 -0
  36. package/dist/components/TemplateDesignerIcon.esm.js.map +1 -0
  37. package/dist/components/designerFlowConfig.esm.js +13 -0
  38. package/dist/components/designerFlowConfig.esm.js.map +1 -0
  39. package/dist/designerFlow/DesignerFlow.esm.js +828 -0
  40. package/dist/designerFlow/DesignerFlow.esm.js.map +1 -0
  41. package/dist/designerFlow/handlers.esm.js +317 -0
  42. package/dist/designerFlow/handlers.esm.js.map +1 -0
  43. package/dist/designerFlow/model.esm.js +166 -0
  44. package/dist/designerFlow/model.esm.js.map +1 -0
  45. package/dist/designerFlow/nodeLayout.esm.js +108 -0
  46. package/dist/designerFlow/nodeLayout.esm.js.map +1 -0
  47. package/dist/designerFlow/parameterTransforms.esm.js +124 -0
  48. package/dist/designerFlow/parameterTransforms.esm.js.map +1 -0
  49. package/dist/designerFlow/utils/stableComparators.esm.js +69 -0
  50. package/dist/designerFlow/utils/stableComparators.esm.js.map +1 -0
  51. package/dist/foundation/actionNodeCustomization.esm.js +20 -0
  52. package/dist/foundation/actionNodeCustomization.esm.js.map +1 -0
  53. package/dist/foundation/actionNodeRegistry.esm.js +30 -0
  54. package/dist/foundation/actionNodeRegistry.esm.js.map +1 -0
  55. package/dist/foundation/featureFlags.esm.js +6 -0
  56. package/dist/foundation/featureFlags.esm.js.map +1 -0
  57. package/dist/foundation/templateSources.esm.js +16 -0
  58. package/dist/foundation/templateSources.esm.js.map +1 -0
  59. package/dist/index.d.ts +382 -0
  60. package/dist/index.esm.js +25 -0
  61. package/dist/index.esm.js.map +1 -0
  62. package/dist/state/templateUtils.esm.js +46 -0
  63. package/dist/state/templateUtils.esm.js.map +1 -0
  64. package/dist/state/useParameterSections.esm.js +162 -0
  65. package/dist/state/useParameterSections.esm.js.map +1 -0
  66. package/dist/state/useTemplateState.esm.js +627 -0
  67. package/dist/state/useTemplateState.esm.js.map +1 -0
  68. package/dist/types/flowNodes.esm.js +8 -0
  69. package/dist/types/flowNodes.esm.js.map +1 -0
  70. package/dist/utils/createSequentialEdges.esm.js +15 -0
  71. package/dist/utils/createSequentialEdges.esm.js.map +1 -0
  72. package/dist/utils/mocks/mocks.esm.js +120 -0
  73. package/dist/utils/mocks/mocks.esm.js.map +1 -0
  74. package/dist/utils/sampleTemplate.esm.js +40 -0
  75. package/dist/utils/sampleTemplate.esm.js.map +1 -0
  76. package/dist/utils/yamlJsonConversion.esm.js +47 -0
  77. package/dist/utils/yamlJsonConversion.esm.js.map +1 -0
  78. package/package.json +103 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ ## [0.1.1](https://github.com/tduniec/template-designer-plugin/compare/template-designer-foundation-v0.1.0...template-designer-foundation-v0.1.1) (2025-12-20)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **template-designer-foundation:** initial release ([1ddc9d7](https://github.com/tduniec/template-designer-plugin/commit/1ddc9d72f343ab944e706919788e244b8efcdb39))
7
+
8
+ # [0.1.0](https://github.com/tduniec/template-designer-plugin/compare/template-designer-foundation-v0.0.1...template-designer-foundation-v0.1.0) (2025-12-20)
9
+
10
+
11
+ ### Features
12
+
13
+ * bulk refactor to commons ([#55](https://github.com/tduniec/template-designer-plugin/issues/55)) optimized rendering - redesigned rendering logic ([99aa586](https://github.com/tduniec/template-designer-plugin/commit/99aa5862ffb3bac254f1bb0e69b0e94a5ed96c16))
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # template-designer-foundation
2
+
3
+ Welcome to the template-designer-foundation plugin!
4
+
5
+ _This plugin was created through the Backstage CLI_
6
+
7
+ ## Getting started
8
+
9
+ Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/template-designer-foundation](http://localhost:3000/template-designer-foundation).
10
+
11
+ You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
12
+ This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
13
+ It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory.
@@ -0,0 +1,59 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { useApiHolder } from '@backstage/core-plugin-api';
3
+ import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';
4
+ import { MOCK_SCAFFOLDER_ACTIONS } from '../utils/mocks/mocks.esm.js';
5
+
6
+ const buildCache = (list) => {
7
+ const { inputsById, outputsById, inputRequiredById } = list.reduce(
8
+ (acc, action) => {
9
+ acc.inputsById[action.id] = action.schema?.input?.properties ?? {};
10
+ acc.outputsById[action.id] = action.schema?.output?.properties ?? {};
11
+ const required = Array.isArray(action.schema?.input?.required) ? action.schema?.input?.required.filter(
12
+ (key) => typeof key === "string" && key.trim().length > 0
13
+ ) : [];
14
+ acc.inputRequiredById[action.id] = required;
15
+ return acc;
16
+ },
17
+ { inputsById: {}, outputsById: {}, inputRequiredById: {} }
18
+ );
19
+ return {
20
+ ids: list.map((action) => action.id),
21
+ inputsById,
22
+ outputsById,
23
+ inputRequiredById
24
+ };
25
+ };
26
+ const fallbackCache = buildCache(
27
+ MOCK_SCAFFOLDER_ACTIONS
28
+ );
29
+ const useScaffolderActions = () => {
30
+ const apiHolder = useApiHolder();
31
+ const scaffolderApi = apiHolder.get(scaffolderApiRef);
32
+ const [cache, setCache] = useState(fallbackCache);
33
+ useEffect(() => {
34
+ let cancelled = false;
35
+ if (!scaffolderApi) {
36
+ setCache(fallbackCache);
37
+ return () => {
38
+ cancelled = true;
39
+ };
40
+ }
41
+ scaffolderApi.listActions().then((remoteActions) => {
42
+ if (cancelled) {
43
+ return;
44
+ }
45
+ setCache(buildCache(remoteActions));
46
+ }).catch(() => {
47
+ if (!cancelled) {
48
+ setCache(fallbackCache);
49
+ }
50
+ });
51
+ return () => {
52
+ cancelled = true;
53
+ };
54
+ }, [scaffolderApi]);
55
+ return cache;
56
+ };
57
+
58
+ export { useScaffolderActions };
59
+ //# sourceMappingURL=useScaffolderActions.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScaffolderActions.esm.js","sources":["../../src/api/useScaffolderActions.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { useApiHolder } from \"@backstage/core-plugin-api\";\nimport { scaffolderApiRef } from \"@backstage/plugin-scaffolder-react\";\nimport type { ListActionsResponse } from \"@backstage/plugin-scaffolder-common\";\nimport { MOCK_SCAFFOLDER_ACTIONS } from \"../utils/mocks/mocks\";\n\ntype ScaffolderAction = {\n id: string;\n schema?: {\n input?: {\n properties?: Record<string, unknown>;\n required?: 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 inputRequiredById: Record<string, string[]>;\n};\n\nconst buildCache = (list: ScaffolderAction[]): ScaffolderActionsCache => {\n const { inputsById, outputsById, inputRequiredById } = list.reduce<{\n inputsById: Record<string, Record<string, unknown>>;\n outputsById: Record<string, Record<string, unknown>>;\n inputRequiredById: Record<string, string[]>;\n }>(\n (acc, action) => {\n acc.inputsById[action.id] = action.schema?.input?.properties ?? {};\n acc.outputsById[action.id] = action.schema?.output?.properties ?? {};\n const required = Array.isArray(action.schema?.input?.required)\n ? action.schema?.input?.required.filter(\n (key): key is string =>\n typeof key === \"string\" && key.trim().length > 0\n )\n : [];\n acc.inputRequiredById[action.id] = required;\n return acc;\n },\n { inputsById: {}, outputsById: {}, inputRequiredById: {} }\n );\n\n return {\n ids: list.map((action) => action.id),\n inputsById,\n outputsById,\n inputRequiredById,\n };\n};\n\nconst fallbackCache = buildCache(\n MOCK_SCAFFOLDER_ACTIONS as ListActionsResponse\n);\n\nexport const useScaffolderActions = () => {\n const apiHolder = useApiHolder();\n const scaffolderApi = apiHolder.get(scaffolderApiRef);\n const [cache, setCache] = useState<ScaffolderActionsCache>(fallbackCache);\n\n useEffect(() => {\n let cancelled = false;\n\n if (!scaffolderApi) {\n setCache(fallbackCache);\n return () => {\n cancelled = true;\n };\n }\n\n scaffolderApi\n .listActions()\n .then((remoteActions) => {\n if (cancelled) {\n return;\n }\n setCache(buildCache(remoteActions));\n })\n .catch(() => {\n if (!cancelled) {\n setCache(fallbackCache);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [scaffolderApi]);\n\n return cache;\n};\n"],"names":[],"mappings":";;;;;AA0BA,MAAM,UAAA,GAAa,CAAC,IAAA,KAAqD;AACvE,EAAA,MAAM,EAAE,UAAA,EAAY,WAAA,EAAa,iBAAA,KAAsB,IAAA,CAAK,MAAA;AAAA,IAK1D,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,MAAM,QAAA,GAAW,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,MAAA,EAAQ,KAAA,EAAO,QAAQ,CAAA,GACzD,MAAA,CAAO,MAAA,EAAQ,KAAA,EAAO,QAAA,CAAS,MAAA;AAAA,QAC7B,CAAC,QACC,OAAO,GAAA,KAAQ,YAAY,GAAA,CAAI,IAAA,GAAO,MAAA,GAAS;AAAA,UAEnD,EAAC;AACL,MAAA,GAAA,CAAI,iBAAA,CAAkB,MAAA,CAAO,EAAE,CAAA,GAAI,QAAA;AACnC,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IACA,EAAE,YAAY,EAAC,EAAG,aAAa,EAAC,EAAG,iBAAA,EAAmB,EAAC;AAAE,GAC3D;AAEA,EAAA,OAAO;AAAA,IACL,KAAK,IAAA,CAAK,GAAA,CAAI,CAAC,MAAA,KAAW,OAAO,EAAE,CAAA;AAAA,IACnC,UAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AACF,CAAA;AAEA,MAAM,aAAA,GAAgB,UAAA;AAAA,EACpB;AACF,CAAA;AAEO,MAAM,uBAAuB,MAAM;AACxC,EAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,EAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,GAAA,CAAI,gBAAgB,CAAA;AACpD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAiC,aAAa,CAAA;AAExE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,QAAA,CAAS,aAAa,CAAA;AACtB,MAAA,OAAO,MAAM;AACX,QAAA,SAAA,GAAY,IAAA;AAAA,MACd,CAAA;AAAA,IACF;AAEA,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;AACX,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,QAAA,CAAS,aAAa,CAAA;AAAA,MACxB;AAAA,IACF,CAAC,CAAA;AAEH,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,55 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Dialog, DialogTitle, DialogContent, TextField, DialogActions, Button } from '@material-ui/core';
3
+ import { useRef, useEffect } from 'react';
4
+
5
+ const FieldEditorDialog = ({
6
+ open,
7
+ label,
8
+ value,
9
+ onClose,
10
+ onApply
11
+ }) => {
12
+ const draftRef = useRef(value);
13
+ const inputRef = useRef(null);
14
+ useEffect(() => {
15
+ if (open) {
16
+ draftRef.current = value;
17
+ if (inputRef.current) {
18
+ inputRef.current.value = value;
19
+ }
20
+ }
21
+ }, [open, value]);
22
+ return /* @__PURE__ */ jsxs(Dialog, { open, onClose, fullWidth: true, maxWidth: "md", children: [
23
+ /* @__PURE__ */ jsx(DialogTitle, { children: label ? `Edit ${label}` : "Edit field" }),
24
+ /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsx(
25
+ TextField,
26
+ {
27
+ multiline: true,
28
+ minRows: 8,
29
+ variant: "outlined",
30
+ defaultValue: value,
31
+ inputRef,
32
+ onChange: (event) => {
33
+ draftRef.current = event.target.value;
34
+ },
35
+ fullWidth: true,
36
+ autoFocus: true
37
+ }
38
+ ) }),
39
+ /* @__PURE__ */ jsxs(DialogActions, { children: [
40
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, children: "Cancel" }),
41
+ /* @__PURE__ */ jsx(
42
+ Button,
43
+ {
44
+ color: "primary",
45
+ variant: "contained",
46
+ onClick: () => onApply(draftRef.current ?? value),
47
+ children: "Apply"
48
+ }
49
+ )
50
+ ] })
51
+ ] });
52
+ };
53
+
54
+ export { FieldEditorDialog };
55
+ //# sourceMappingURL=FieldEditorDialog.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FieldEditorDialog.esm.js","sources":["../../src/components/FieldEditorDialog.tsx"],"sourcesContent":["import {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n TextField,\n} from \"@material-ui/core\";\nimport { useEffect, useRef } from \"react\";\n\nexport type FieldEditorDialogProps = {\n open: boolean;\n label?: string;\n value: string;\n onClose: () => void;\n onApply: (value: string) => void;\n};\n\nexport const FieldEditorDialog = ({\n open,\n label,\n value,\n onClose,\n onApply,\n}: FieldEditorDialogProps) => {\n const draftRef = useRef(value);\n const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement | null>(null);\n\n useEffect(() => {\n if (open) {\n draftRef.current = value;\n if (inputRef.current) {\n inputRef.current.value = value;\n }\n }\n }, [open, value]);\n\n return (\n <Dialog open={open} onClose={onClose} fullWidth maxWidth=\"md\">\n <DialogTitle>{label ? `Edit ${label}` : \"Edit field\"}</DialogTitle>\n <DialogContent>\n <TextField\n multiline\n minRows={8}\n variant=\"outlined\"\n defaultValue={value}\n inputRef={inputRef}\n onChange={(event) => {\n draftRef.current = event.target.value;\n }}\n fullWidth\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}>Cancel</Button>\n <Button\n color=\"primary\"\n variant=\"contained\"\n onClick={() => onApply(draftRef.current ?? value)}\n >\n Apply\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":";;;;AAkBO,MAAM,oBAAoB,CAAC;AAAA,EAChC,IAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,KAA8B;AAC5B,EAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,OAAsD,IAAI,CAAA;AAE3E,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,MAAA,IAAI,SAAS,OAAA,EAAS;AACpB,QAAA,QAAA,CAAS,QAAQ,KAAA,GAAQ,KAAA;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,KAAK,CAAC,CAAA;AAEhB,EAAA,4BACG,MAAA,EAAA,EAAO,IAAA,EAAY,SAAkB,SAAA,EAAS,IAAA,EAAC,UAAS,IAAA,EACvD,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAA,EAAA,EAAa,QAAA,EAAA,KAAA,GAAQ,CAAA,KAAA,EAAQ,KAAK,KAAK,YAAA,EAAa,CAAA;AAAA,wBACpD,aAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAS,IAAA;AAAA,QACT,OAAA,EAAS,CAAA;AAAA,QACT,OAAA,EAAQ,UAAA;AAAA,QACR,YAAA,EAAc,KAAA;AAAA,QACd,QAAA;AAAA,QACA,QAAA,EAAU,CAAC,KAAA,KAAU;AACnB,UAAA,QAAA,CAAS,OAAA,GAAU,MAAM,MAAA,CAAO,KAAA;AAAA,QAClC,CAAA;AAAA,QACA,SAAA,EAAS,IAAA;AAAA,QAET,SAAA,EAAS;AAAA;AAAA,KACX,EACF,CAAA;AAAA,yBACC,aAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,OAAA,EAAS,QAAA,EAAA,QAAA,EAAM,CAAA;AAAA,sBAChC,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAM,SAAA;AAAA,UACN,OAAA,EAAQ,WAAA;AAAA,UACR,OAAA,EAAS,MAAM,OAAA,CAAQ,QAAA,CAAS,WAAW,KAAK,CAAA;AAAA,UACjD,QAAA,EAAA;AAAA;AAAA;AAED,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}