node-registries.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /**
  2. * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  3. * SPDX-License-Identifier: MIT
  4. */
  5. import {
  6. WorkflowNodeRegistry,
  7. Field,
  8. DataEvent,
  9. EffectFuncProps,
  10. WorkflowPorts,
  11. } from '@flowgram.ai/free-layout-editor';
  12. const CONDITION_ITEM_HEIGHT = 30;
  13. /**
  14. * You can customize your own node registry
  15. * 你可以自定义节点的注册器
  16. */
  17. export const nodeRegistries: WorkflowNodeRegistry[] = [
  18. {
  19. type: 'start',
  20. meta: {
  21. isStart: true, // Mark as start
  22. deleteDisable: true, // The start node cannot be deleted
  23. copyDisable: true, // The start node cannot be copied
  24. defaultPorts: [{ type: 'output' }], // Used to define the input and output ports, the start node only has the output port
  25. },
  26. },
  27. {
  28. type: 'condition',
  29. meta: {
  30. defaultPorts: [{ type: 'input' }],
  31. },
  32. formMeta: {
  33. /**
  34. * Initialize the form values
  35. * @param value
  36. */
  37. formatOnInit: (value) => ({
  38. portKeys: ['if', 'else'],
  39. ...value,
  40. }),
  41. effect: {
  42. /**
  43. * Listen for "portsKeys" changes and update ports
  44. */
  45. portKeys: [
  46. {
  47. event: DataEvent.onValueInitOrChange,
  48. effect: ({ value, context }: EffectFuncProps<Array<string>, FormData>) => {
  49. const { node } = context;
  50. const defaultPorts: WorkflowPorts = [{ type: 'input' }];
  51. const newPorts: WorkflowPorts = value.map((portID: string, i: number) => ({
  52. type: 'output',
  53. portID,
  54. location: 'right',
  55. locationConfig: {
  56. right: 0,
  57. top: (i + 1) * CONDITION_ITEM_HEIGHT,
  58. },
  59. }));
  60. node.ports.updateAllPorts([...defaultPorts, ...newPorts]);
  61. },
  62. },
  63. ],
  64. },
  65. render: () => (
  66. <>
  67. <Field<string> name="title">
  68. {({ field }) => <div className="demo-free-node-title">{field.value}</div>}
  69. </Field>
  70. <Field<Array<string>> name="portKeys">
  71. {({ field: { value, onChange } }) => (
  72. <div
  73. className="demo-free-node-content"
  74. style={{
  75. width: 160,
  76. height: value.length * CONDITION_ITEM_HEIGHT,
  77. minHeight: 2 * CONDITION_ITEM_HEIGHT,
  78. }}
  79. >
  80. <div>
  81. <button onClick={() => onChange(value.concat(`if_${value.length}`))}>
  82. Add Port
  83. </button>
  84. </div>
  85. <div style={{ marginTop: 8 }}>
  86. <button
  87. onClick={() => onChange(value.filter((v, i, arr) => i !== arr.length - 1))}
  88. >
  89. Delete Port
  90. </button>
  91. </div>
  92. </div>
  93. )}
  94. </Field>
  95. </>
  96. ),
  97. },
  98. },
  99. {
  100. type: 'chain',
  101. meta: {
  102. defaultPorts: [
  103. { type: 'input' },
  104. { type: 'output' },
  105. {
  106. portID: 'p4',
  107. location: 'bottom',
  108. locationConfig: { left: '33%', bottom: 0 },
  109. type: 'output',
  110. },
  111. {
  112. portID: 'p5',
  113. location: 'bottom',
  114. locationConfig: { left: '66%', bottom: 0 },
  115. type: 'output',
  116. },
  117. ],
  118. },
  119. },
  120. {
  121. type: 'tool',
  122. meta: {
  123. defaultPorts: [{ location: 'top', type: 'input' }],
  124. },
  125. },
  126. {
  127. // 支持双向连接, Support two-way connection
  128. type: 'twoway',
  129. meta: {
  130. defaultPorts: [
  131. { type: 'input', portID: 'input-left', location: 'left' },
  132. { type: 'output', portID: 'output-left', location: 'left' },
  133. { type: 'input', portID: 'input-right', location: 'right' },
  134. { type: 'output', portID: 'output-right', location: 'right' },
  135. ],
  136. },
  137. },
  138. {
  139. type: 'end',
  140. meta: {
  141. deleteDisable: true,
  142. copyDisable: true,
  143. defaultPorts: [{ type: 'input' }],
  144. },
  145. },
  146. {
  147. type: 'custom',
  148. meta: {},
  149. defaultPorts: [{ type: 'output' }, { type: 'input' }], // A normal node has two ports
  150. },
  151. ];