@nyaruka/temba-components 0.138.6 → 0.140.0

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 (196) hide show
  1. package/.github/workflows/cla.yml +1 -1
  2. package/.github/workflows/copilot-setup-steps.yml +6 -1
  3. package/CHANGELOG.md +26 -0
  4. package/demo/data/flows/sample-flow.json +24 -0
  5. package/dist/locales/es.js +5 -5
  6. package/dist/locales/es.js.map +1 -1
  7. package/dist/locales/fr.js +5 -5
  8. package/dist/locales/fr.js.map +1 -1
  9. package/dist/locales/locale-codes.js +2 -11
  10. package/dist/locales/locale-codes.js.map +1 -1
  11. package/dist/locales/pt.js +5 -5
  12. package/dist/locales/pt.js.map +1 -1
  13. package/dist/temba-components.js +1112 -882
  14. package/dist/temba-components.js.map +1 -1
  15. package/out-tsc/src/display/Chat.js +10 -7
  16. package/out-tsc/src/display/Chat.js.map +1 -1
  17. package/out-tsc/src/display/Dropdown.js +3 -1
  18. package/out-tsc/src/display/Dropdown.js.map +1 -1
  19. package/out-tsc/src/display/FloatingTab.js +25 -32
  20. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  21. package/out-tsc/src/display/Thumbnail.js +163 -5
  22. package/out-tsc/src/display/Thumbnail.js.map +1 -1
  23. package/out-tsc/src/flow/CanvasMenu.js +5 -3
  24. package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
  25. package/out-tsc/src/flow/CanvasNode.js +70 -29
  26. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  27. package/out-tsc/src/flow/Editor.js +290 -239
  28. package/out-tsc/src/flow/Editor.js.map +1 -1
  29. package/out-tsc/src/flow/NodeEditor.js +118 -10
  30. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  31. package/out-tsc/src/flow/Plumber.js +757 -403
  32. package/out-tsc/src/flow/Plumber.js.map +1 -1
  33. package/out-tsc/src/flow/StickyNote.js +13 -4
  34. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  35. package/out-tsc/src/flow/actions/audio-player.js +112 -0
  36. package/out-tsc/src/flow/actions/audio-player.js.map +1 -0
  37. package/out-tsc/src/flow/actions/enter_flow.js +43 -0
  38. package/out-tsc/src/flow/actions/enter_flow.js.map +1 -0
  39. package/out-tsc/src/flow/actions/play_audio.js +57 -4
  40. package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
  41. package/out-tsc/src/flow/actions/say_msg.js +86 -3
  42. package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
  43. package/out-tsc/src/flow/config.js +11 -3
  44. package/out-tsc/src/flow/config.js.map +1 -1
  45. package/out-tsc/src/flow/nodes/shared-rules.js +1 -1
  46. package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -1
  47. package/out-tsc/src/flow/nodes/terminal.js +7 -0
  48. package/out-tsc/src/flow/nodes/terminal.js.map +1 -0
  49. package/out-tsc/src/flow/nodes/wait_for_audio.js +77 -0
  50. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -0
  51. package/out-tsc/src/flow/nodes/wait_for_dial.js +151 -0
  52. package/out-tsc/src/flow/nodes/wait_for_dial.js.map +1 -0
  53. package/out-tsc/src/flow/nodes/wait_for_digits.js +61 -1
  54. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  55. package/out-tsc/src/flow/nodes/wait_for_menu.js +173 -2
  56. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
  57. package/out-tsc/src/flow/operators.js +21 -5
  58. package/out-tsc/src/flow/operators.js.map +1 -1
  59. package/out-tsc/src/flow/types.js.map +1 -1
  60. package/out-tsc/src/flow/utils.js +213 -65
  61. package/out-tsc/src/flow/utils.js.map +1 -1
  62. package/out-tsc/src/form/ArrayEditor.js +4 -2
  63. package/out-tsc/src/form/ArrayEditor.js.map +1 -1
  64. package/out-tsc/src/form/FieldRenderer.js +49 -0
  65. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  66. package/out-tsc/src/interfaces.js +2 -0
  67. package/out-tsc/src/interfaces.js.map +1 -1
  68. package/out-tsc/src/layout/Dialog.js +52 -7
  69. package/out-tsc/src/layout/Dialog.js.map +1 -1
  70. package/out-tsc/src/list/TicketList.js +4 -1
  71. package/out-tsc/src/list/TicketList.js.map +1 -1
  72. package/out-tsc/src/live/TembaChart.js.map +1 -1
  73. package/out-tsc/src/locales/es.js +5 -5
  74. package/out-tsc/src/locales/es.js.map +1 -1
  75. package/out-tsc/src/locales/fr.js +5 -5
  76. package/out-tsc/src/locales/fr.js.map +1 -1
  77. package/out-tsc/src/locales/locale-codes.js +2 -11
  78. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  79. package/out-tsc/src/locales/pt.js +5 -5
  80. package/out-tsc/src/locales/pt.js.map +1 -1
  81. package/out-tsc/src/simulator/Simulator.js +10 -3
  82. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  83. package/out-tsc/src/store/AppState.js +89 -3
  84. package/out-tsc/src/store/AppState.js.map +1 -1
  85. package/out-tsc/test/actions/play_audio.test.js +118 -0
  86. package/out-tsc/test/actions/play_audio.test.js.map +1 -0
  87. package/out-tsc/test/actions/say_msg.test.js +158 -0
  88. package/out-tsc/test/actions/say_msg.test.js.map +1 -0
  89. package/out-tsc/test/nodes/wait_for_audio.test.js +156 -0
  90. package/out-tsc/test/nodes/wait_for_audio.test.js.map +1 -0
  91. package/out-tsc/test/nodes/wait_for_dial.test.js +336 -0
  92. package/out-tsc/test/nodes/wait_for_dial.test.js.map +1 -0
  93. package/out-tsc/test/nodes/wait_for_digits.test.js +198 -84
  94. package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
  95. package/out-tsc/test/nodes/wait_for_menu.test.js +340 -0
  96. package/out-tsc/test/nodes/wait_for_menu.test.js.map +1 -0
  97. package/out-tsc/test/temba-floating-tab.test.js +4 -6
  98. package/out-tsc/test/temba-floating-tab.test.js.map +1 -1
  99. package/out-tsc/test/temba-flow-collision.test.js +473 -220
  100. package/out-tsc/test/temba-flow-collision.test.js.map +1 -1
  101. package/out-tsc/test/temba-flow-editor.test.js +0 -2
  102. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  103. package/out-tsc/test/temba-flow-plumber-connections.test.js +83 -84
  104. package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
  105. package/out-tsc/test/temba-flow-plumber.test.js +102 -93
  106. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  107. package/out-tsc/test/temba-node-type-selector.test.js +6 -6
  108. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
  109. package/package.json +1 -1
  110. package/screenshots/truth/actions/play_audio/editor/expression-url.png +0 -0
  111. package/screenshots/truth/actions/play_audio/editor/static-url.png +0 -0
  112. package/screenshots/truth/actions/play_audio/render/expression-url.png +0 -0
  113. package/screenshots/truth/actions/play_audio/render/static-url.png +0 -0
  114. package/screenshots/truth/actions/say_msg/editor/multiline-text.png +0 -0
  115. package/screenshots/truth/actions/say_msg/editor/simple-text.png +0 -0
  116. package/screenshots/truth/actions/say_msg/editor/text-with-audio-url.png +0 -0
  117. package/screenshots/truth/actions/say_msg/render/multiline-text.png +0 -0
  118. package/screenshots/truth/actions/say_msg/render/simple-text.png +0 -0
  119. package/screenshots/truth/actions/say_msg/render/text-with-audio-url.png +0 -0
  120. package/screenshots/truth/editor/router.png +0 -0
  121. package/screenshots/truth/editor/wait.png +0 -0
  122. package/screenshots/truth/nodes/wait_for_audio/editor/basic-audio-wait.png +0 -0
  123. package/screenshots/truth/nodes/wait_for_audio/render/basic-audio-wait.png +0 -0
  124. package/screenshots/truth/nodes/wait_for_dial/editor/basic-dial.png +0 -0
  125. package/screenshots/truth/nodes/wait_for_dial/editor/dial-with-limits.png +0 -0
  126. package/screenshots/truth/nodes/wait_for_dial/render/basic-dial.png +0 -0
  127. package/screenshots/truth/nodes/wait_for_dial/render/dial-with-limits.png +0 -0
  128. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  129. package/screenshots/truth/nodes/wait_for_digits/editor/digits-with-rules.png +0 -0
  130. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  131. package/screenshots/truth/nodes/wait_for_digits/render/digits-with-rules.png +0 -0
  132. package/screenshots/truth/nodes/wait_for_menu/editor/menu-with-digits.png +0 -0
  133. package/screenshots/truth/nodes/wait_for_menu/render/menu-with-digits.png +0 -0
  134. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  135. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  136. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  137. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  138. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  139. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  140. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  141. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  142. package/src/display/Chat.ts +13 -7
  143. package/src/display/Dropdown.ts +3 -1
  144. package/src/display/FloatingTab.ts +24 -33
  145. package/src/display/Thumbnail.ts +162 -2
  146. package/src/flow/CanvasMenu.ts +8 -3
  147. package/src/flow/CanvasNode.ts +75 -30
  148. package/src/flow/Editor.ts +336 -288
  149. package/src/flow/NodeEditor.ts +137 -9
  150. package/src/flow/Plumber.ts +1011 -457
  151. package/src/flow/StickyNote.ts +14 -4
  152. package/src/flow/actions/audio-player.ts +127 -0
  153. package/src/flow/actions/enter_flow.ts +44 -0
  154. package/src/flow/actions/play_audio.ts +64 -5
  155. package/src/flow/actions/say_msg.ts +94 -4
  156. package/src/flow/config.ts +11 -3
  157. package/src/flow/nodes/shared-rules.ts +1 -1
  158. package/src/flow/nodes/terminal.ts +9 -0
  159. package/src/flow/nodes/wait_for_audio.ts +88 -0
  160. package/src/flow/nodes/wait_for_dial.ts +176 -0
  161. package/src/flow/nodes/wait_for_digits.ts +86 -2
  162. package/src/flow/nodes/wait_for_menu.ts +209 -3
  163. package/src/flow/operators.ts +23 -5
  164. package/src/flow/types.ts +23 -1
  165. package/src/flow/utils.ts +238 -81
  166. package/src/form/ArrayEditor.ts +4 -2
  167. package/src/form/FieldRenderer.ts +64 -1
  168. package/src/interfaces.ts +3 -1
  169. package/src/layout/Dialog.ts +53 -7
  170. package/src/list/TicketList.ts +4 -1
  171. package/src/live/TembaChart.ts +1 -1
  172. package/src/locales/es.ts +13 -18
  173. package/src/locales/fr.ts +13 -18
  174. package/src/locales/locale-codes.ts +2 -11
  175. package/src/locales/pt.ts +13 -18
  176. package/src/simulator/Simulator.ts +13 -3
  177. package/src/store/AppState.ts +105 -1
  178. package/src/store/flow-definition.d.ts +2 -0
  179. package/test/actions/play_audio.test.ts +155 -0
  180. package/test/actions/say_msg.test.ts +196 -0
  181. package/test/nodes/wait_for_audio.test.ts +182 -0
  182. package/test/nodes/wait_for_dial.test.ts +382 -0
  183. package/test/nodes/wait_for_digits.test.ts +233 -109
  184. package/test/nodes/wait_for_menu.test.ts +383 -0
  185. package/test/temba-floating-tab.test.ts +4 -6
  186. package/test/temba-flow-collision.test.ts +495 -293
  187. package/test/temba-flow-editor.test.ts +0 -2
  188. package/test/temba-flow-plumber-connections.test.ts +97 -97
  189. package/test/temba-flow-plumber.test.ts +116 -103
  190. package/test/temba-node-type-selector.test.ts +6 -6
  191. package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
  192. package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
  193. package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
  194. package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
  195. package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
  196. package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Plumber.js","sourceRoot":"","sources":["../../../src/flow/Plumber.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DotEndpoint,\n FlowchartConnector,\n newInstance,\n ready,\n RectangleEndpoint,\n EVENT_CONNECTION_DRAG,\n EVENT_CONNECTION_ABORT,\n INTERCEPT_BEFORE_DROP,\n EVENT_CONNECTION,\n EVENT_REVERT,\n INTERCEPT_BEFORE_DETACH,\n EVENT_CONNECTION_DETACHED\n} from '@jsplumb/browser-ui';\nimport { getStore } from '../store/Store';\n\nconst CONNECTOR_DEFAULTS = {\n type: FlowchartConnector.type,\n options: {\n stub: [20, 10],\n midpoint: 0.5,\n alwaysRespectStubs: true,\n cornerRadius: 5,\n cssClass: 'plumb-connector'\n }\n};\n\nconst OVERLAYS_DEFAULTS = [\n {\n type: 'PlainArrow',\n options: {\n width: 13,\n length: 13,\n location: 0.999,\n cssClass: 'plumb-arrow'\n }\n }\n];\n\nexport const SOURCE_DEFAULTS = {\n endpoint: {\n type: DotEndpoint.type,\n options: {\n radius: 12,\n cssClass: 'plumb-source',\n hoverClass: 'plumb-source-hover'\n }\n },\n anchors: ['Bottom', 'Continuous'],\n maxConnections: 1,\n source: true,\n dragAllowedWhenFull: false\n};\n\nexport const TARGET_DEFAULTS = {\n endpoint: {\n type: RectangleEndpoint.type,\n options: {\n width: 23,\n height: 23,\n cssClass: 'plumb-target',\n hoverClass: 'plumb-target-hover'\n }\n },\n anchor: {\n type: 'Continuous',\n options: {\n faces: ['top', 'left', 'right'],\n cssClass: 'continuos plumb-target-anchor'\n }\n },\n deleteOnEmpty: true,\n maxConnections: 1,\n target: true\n};\n\nexport class Plumber {\n private jsPlumb = null;\n private pendingConnections = [];\n private connectionListeners = new Map();\n public connectionDragging = false;\n private connectionWait = null;\n private activityData: { segments: { [key: string]: number } } | null = null;\n private hoveredActivityKey: string | null = null;\n private recentContactsPopup: HTMLElement | null = null;\n private recentContactsCache: { [key: string]: any[] } = {};\n private pendingFetches: { [key: string]: AbortController } = {};\n private hideContactsTimeout: number | null = null;\n private showContactsTimeout: number | null = null;\n private editor: any;\n\n initializeJSPlumb(canvas: HTMLElement) {\n this.jsPlumb = newInstance({\n container: canvas,\n connectionsDetachable: true,\n endpointStyle: {\n fill: 'green'\n },\n connector: CONNECTOR_DEFAULTS,\n connectionOverlays: OVERLAYS_DEFAULTS\n });\n\n // Bind to connection events\n this.jsPlumb.bind(EVENT_CONNECTION, (info) => {\n this.connectionDragging = false;\n this.notifyListeners(EVENT_CONNECTION, info);\n });\n\n // Bind to connection drag events\n this.jsPlumb.bind(EVENT_CONNECTION_DRAG, (info) => {\n this.connectionDragging = true;\n this.notifyListeners(EVENT_CONNECTION_DRAG, info);\n });\n\n this.jsPlumb.bind(EVENT_CONNECTION_ABORT, (info) => {\n this.connectionDragging = false;\n this.notifyListeners(EVENT_CONNECTION_ABORT, info);\n });\n\n this.jsPlumb.bind(EVENT_CONNECTION_DETACHED, (info) => {\n this.connectionDragging = false;\n this.notifyListeners(EVENT_CONNECTION_DETACHED, info);\n });\n\n this.jsPlumb.bind(EVENT_REVERT, (info) => {\n this.notifyListeners(EVENT_REVERT, info);\n });\n\n this.jsPlumb.bind(INTERCEPT_BEFORE_DROP, () => {\n // we always deny automatic connections\n return false;\n });\n this.jsPlumb.bind(INTERCEPT_BEFORE_DETACH, () => {});\n }\n\n constructor(canvas: HTMLElement, editor: any) {\n this.editor = editor;\n ready(() => {\n this.initializeJSPlumb(canvas);\n });\n }\n\n private notifyListeners(eventName: string, info: any) {\n const listeners = this.connectionListeners.get(eventName) || [];\n listeners.forEach((listener) => listener(info));\n }\n\n public on(eventName: string, callback: (info: any) => void) {\n if (!this.connectionListeners.has(eventName)) {\n this.connectionListeners.set(eventName, []);\n }\n this.connectionListeners.get(eventName).push(callback);\n }\n\n public off(eventName: string, callback: (info: any) => void) {\n if (!this.connectionListeners.has(eventName)) return;\n const listeners = this.connectionListeners.get(eventName);\n const index = listeners.indexOf(callback);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n }\n\n public makeTarget(uuid: string) {\n const element = document.getElementById(uuid);\n if (!element) return;\n return this.jsPlumb.addEndpoint(element, TARGET_DEFAULTS);\n }\n\n public makeSource(uuid: string) {\n const element = document.getElementById(uuid);\n if (!element) return;\n return this.jsPlumb.addEndpoint(element, SOURCE_DEFAULTS);\n }\n\n // we'll process our pending connections, but we want to debounce this\n public processPendingConnections() {\n // if we have a pending connection wait, clear it\n if (this.connectionWait) {\n clearTimeout(this.connectionWait);\n this.connectionWait = null;\n }\n\n // debounce the connection processing\n this.connectionWait = setTimeout(() => {\n this.jsPlumb.batch(() => {\n this.pendingConnections.forEach((connection) => {\n const { scope, fromId, toId } = connection;\n\n // sources and targets must exist\n const source = document.getElementById(fromId);\n // const target = document.getElementById(toId);\n\n this.revalidate([fromId, toId]);\n\n // we need to find the source endpoint\n const sourceEndpoint = this.jsPlumb\n .getEndpoints(source)\n ?.find((endpoint) =>\n endpoint.elementId === fromId ? true : false\n );\n\n // update endpoint have connect css class\n if (sourceEndpoint) {\n sourceEndpoint.addClass('connected');\n }\n\n // each connection needs its own target endpoint\n const targetEndpoint = this.makeTarget(toId);\n\n if (!source || !targetEndpoint) {\n console.warn(\n `Plumber: Cannot connect ${fromId} to ${toId}. Element(s) missing.`\n );\n return;\n }\n\n // delete connections\n this.jsPlumb.select({ source, targetEndpoint }).deleteAll();\n this.jsPlumb.connect({\n source: source,\n target: targetEndpoint,\n connector: {\n ...CONNECTOR_DEFAULTS,\n options: { ...CONNECTOR_DEFAULTS.options, gap: [0, 5] }\n },\n data: {\n nodeId: scope\n }\n });\n });\n this.pendingConnections = [];\n });\n\n // Force a repaint to ensure connections are positioned correctly\n // especially after bulk updates or view switching\n window.requestAnimationFrame(() => {\n if (this.jsPlumb) {\n this.jsPlumb.repaintEverything();\n }\n });\n }, 0);\n }\n\n public connectIds(scope: string, fromId: string, toId: string) {\n this.pendingConnections.push({ scope, fromId, toId });\n this.processPendingConnections();\n }\n\n public setActivityData(\n activityData: { segments: { [key: string]: number } } | null\n ) {\n this.activityData = activityData;\n // Clear recent contacts cache when activity data changes\n this.clearRecentContactsCache();\n this.updateActivityOverlays();\n }\n\n private updateActivityOverlays() {\n if (!this.jsPlumb || !this.activityData) {\n return;\n }\n\n // Get all connections\n const connections = this.jsPlumb.getConnections();\n\n connections.forEach((connection: any) => {\n // Get the source exit element\n const sourceElement = connection.source;\n if (!sourceElement) {\n return;\n }\n\n // Get destination node\n const targetElement = connection.target;\n if (!targetElement) {\n return;\n }\n\n // Create activity key: exitUuid:destinationUuid\n const exitUuid = sourceElement.id;\n const destinationUuid = targetElement.id;\n const activityKey = `${exitUuid}:${destinationUuid}`;\n\n // Get activity count for this segment\n const count = this.activityData.segments[activityKey];\n\n // Remove existing activity overlays\n connection.removeOverlay('activity-label');\n\n // Add new overlay if there's activity\n if (count && count > 0) {\n const overlay = connection.addOverlay({\n type: 'Label',\n options: {\n label: count.toLocaleString(),\n id: 'activity-label',\n cssClass: 'activity-overlay',\n location: 20 // Fixed pixel distance from the start (exit point)\n }\n });\n\n // Add hover events for recent contacts popup\n // Use setTimeout to ensure the overlay is fully rendered\n setTimeout(() => {\n // Try multiple ways to get the overlay element\n let overlayElement =\n overlay.canvas || overlay.element || overlay.getElement?.();\n\n // If still not found, query the DOM directly\n if (!overlayElement) {\n const overlays = connection.getOverlays();\n if (Array.isArray(overlays)) {\n for (const ovl of overlays) {\n if (ovl.id === 'activity-label') {\n overlayElement =\n ovl.canvas || ovl.element || ovl.getElement?.();\n break;\n }\n }\n }\n }\n\n // Also try querying by CSS class\n if (!overlayElement && connection.canvas) {\n overlayElement =\n connection.canvas.querySelector('.activity-overlay');\n }\n\n if (overlayElement) {\n overlayElement.style.cursor = 'pointer';\n overlayElement.setAttribute('data-activity-key', activityKey);\n overlayElement.addEventListener('mouseenter', () => {\n // Don't show recent contacts when simulator is active\n const store = getStore();\n if (store?.getState().simulatorActive) {\n return;\n }\n\n // Get flow UUID from the editor element\n const editor = document.querySelector('temba-flow-editor') as any;\n const flowUuid = editor?.definition?.uuid;\n if (flowUuid) {\n // Start fetching immediately\n this.fetchRecentContacts(activityKey, flowUuid);\n\n // But delay showing the popup by half a second\n this.showContactsTimeout = window.setTimeout(() => {\n this.showRecentContacts(activityKey, flowUuid);\n }, 500);\n }\n });\n overlayElement.addEventListener('mouseleave', () => {\n // Cancel the show timeout if still pending\n if (this.showContactsTimeout) {\n clearTimeout(this.showContactsTimeout);\n this.showContactsTimeout = null;\n }\n this.hoveredActivityKey = null;\n this.hideRecentContacts();\n });\n }\n }, 50);\n }\n });\n\n // Force repaint to ensure overlays are positioned correctly\n this.repaintEverything();\n }\n\n private findOverlayElement(activityKey: string): HTMLElement | null {\n // Find overlay by data attribute\n const overlays = document.querySelectorAll('.activity-overlay');\n for (const overlay of overlays) {\n if (overlay.getAttribute('data-activity-key') === activityKey) {\n return overlay as HTMLElement;\n }\n }\n return null;\n }\n\n private async fetchRecentContacts(activityKey: string, flowUuid: string) {\n // Skip if already cached or currently fetching\n if (\n this.recentContactsCache[activityKey] ||\n this.pendingFetches[activityKey]\n ) {\n return;\n }\n\n // Cancel any pending fetch for this key\n if (this.pendingFetches[activityKey]) {\n this.pendingFetches[activityKey].abort();\n }\n\n // Fetch recent contacts from endpoint\n const controller = new AbortController();\n this.pendingFetches[activityKey] = controller;\n\n try {\n // Parse exit UUID and destination UUID from activity key\n const [exitUuid, destinationUuid] = activityKey.split(':');\n\n const endpoint = `/flow/recent_contacts/${flowUuid}/${exitUuid}/${destinationUuid}/`;\n\n const response = await fetch(endpoint, {\n signal: controller.signal\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n // API returns array directly, not wrapped in results\n const recentContacts = Array.isArray(data) ? data : data.results || [];\n\n // Cache the results\n this.recentContactsCache[activityKey] = recentContacts;\n } catch (error) {\n if ((error as Error).name !== 'AbortError') {\n console.error('Failed to fetch recent contacts:', error);\n }\n } finally {\n delete this.pendingFetches[activityKey];\n }\n }\n\n private async showRecentContacts(activityKey: string, flowUuid: string) {\n // Don't show recent contacts when simulator is active\n const store = getStore();\n if (store?.getState().simulatorActive) {\n return;\n }\n\n // Find the overlay element fresh to avoid stale references\n const overlayElement = this.findOverlayElement(activityKey);\n if (!overlayElement) {\n console.warn('Could not find overlay element for activity:', activityKey);\n return;\n }\n // Clear any pending hide timeout\n if (this.hideContactsTimeout) {\n clearTimeout(this.hideContactsTimeout);\n this.hideContactsTimeout = null;\n }\n\n this.hoveredActivityKey = activityKey;\n\n // Create popup if it doesn't exist\n if (!this.recentContactsPopup) {\n this.recentContactsPopup = document.createElement('div');\n this.recentContactsPopup.className = 'recent-contacts-popup';\n // Add inline styles to ensure visibility\n this.recentContactsPopup.style.position = 'absolute';\n this.recentContactsPopup.style.width = '200px';\n this.recentContactsPopup.style.background = '#f3f3f3';\n this.recentContactsPopup.style.borderRadius = '10px';\n this.recentContactsPopup.style.boxShadow =\n '0 1px 3px 1px rgba(130, 130, 130, 0.2)';\n this.recentContactsPopup.style.zIndex = '1015';\n this.recentContactsPopup.style.display = 'none';\n document.body.appendChild(this.recentContactsPopup);\n }\n\n // Add hover events to keep popup open (only needs to be done once)\n if (!this.recentContactsPopup.onmouseenter) {\n this.recentContactsPopup.onmouseenter = () => {\n if (this.hideContactsTimeout) {\n clearTimeout(this.hideContactsTimeout);\n this.hideContactsTimeout = null;\n }\n };\n this.recentContactsPopup.onmouseleave = () => {\n this.hoveredActivityKey = null;\n this.hideRecentContacts();\n };\n\n // Add click event listener for contact names\n this.recentContactsPopup.onclick = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n if (target.classList.contains('contact-name')) {\n this.hideRecentContacts(false);\n const contactUuid = target.getAttribute('data-uuid');\n if (contactUuid) {\n // Fire custom event through editor\n this.editor.fireCustomEvent('temba-contact-clicked', {\n uuid: contactUuid\n });\n }\n }\n };\n }\n\n // Check cache first\n if (this.recentContactsCache[activityKey]) {\n this.renderRecentContactsPopup(this.recentContactsCache[activityKey]);\n this.positionPopup(overlayElement);\n } else {\n // Show loading state if data isn't ready yet\n this.recentContactsPopup.innerHTML =\n '<div class=\"no-contacts-message\">Loading...</div>';\n this.positionPopup(overlayElement);\n\n // Wait for the fetch to complete\n await this.fetchRecentContacts(activityKey, flowUuid);\n\n // Render if still hovering over this activity\n if (this.hoveredActivityKey === activityKey) {\n const contacts = this.recentContactsCache[activityKey] || [];\n this.renderRecentContactsPopup(contacts);\n this.positionPopup(overlayElement);\n }\n }\n }\n\n private positionPopup(overlayElement: HTMLElement) {\n if (!this.recentContactsPopup) return;\n\n // Position popup near the overlay\n const rect = overlayElement.getBoundingClientRect();\n this.recentContactsPopup.style.left = `${rect.left + window.scrollX}px`;\n this.recentContactsPopup.style.top = `${\n rect.bottom + window.scrollY + 5\n }px`;\n\n // Remove inline display style so CSS class can work\n this.recentContactsPopup.style.display = '';\n\n // Trigger animation by adding class\n this.recentContactsPopup.classList.remove('show');\n // Force reflow to restart animation\n void this.recentContactsPopup.offsetWidth;\n this.recentContactsPopup.classList.add('show');\n }\n\n private renderRecentContactsPopup(recentContacts: any[]) {\n if (!this.recentContactsPopup) return;\n\n const hasContacts = recentContacts.length > 0;\n\n if (!hasContacts) {\n // Simple message when no contacts\n this.recentContactsPopup.innerHTML =\n '<div class=\"no-contacts-message\">No Recent Contacts</div>';\n return;\n }\n\n let html = `<div class=\"popup-title\">Recent Contacts</div>`;\n\n recentContacts.forEach((contact: any) => {\n html += `<div class=\"contact-row\">`;\n html += `<div class=\"contact-name\" data-uuid=\"${contact.contact.uuid}\">${contact.contact.name}</div>`;\n if (contact.operand) {\n html += `<div class=\"contact-operand\">${contact.operand}</div>`;\n }\n if (contact.time) {\n const time = new Date(contact.time);\n const now = new Date();\n const diffMs = now.getTime() - time.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n let timeStr = '';\n if (diffMins < 1) timeStr = 'just now';\n else if (diffMins < 60) timeStr = `${diffMins}m ago`;\n else if (diffHours < 24) timeStr = `${diffHours}h ago`;\n else timeStr = `${diffDays}d ago`;\n\n html += `<div class=\"contact-time\">${timeStr}</div>`;\n }\n html += `</div>`;\n });\n\n this.recentContactsPopup.innerHTML = html;\n }\n\n private hideRecentContacts(wait = true) {\n if (!wait) {\n if (this.recentContactsPopup) {\n this.recentContactsPopup.classList.remove('show');\n this.recentContactsPopup.style.display = 'none';\n this.hoveredActivityKey = null;\n }\n return;\n }\n\n this.hideContactsTimeout = window.setTimeout(() => {\n // Check if we're still hovering over an activity\n if (!this.hoveredActivityKey && this.recentContactsPopup) {\n this.recentContactsPopup.classList.remove('show');\n this.recentContactsPopup.style.display = 'none';\n this.hoveredActivityKey = null;\n }\n }, 200); // Small delay to allow moving between overlay and popup\n }\n\n public clearRecentContactsCache() {\n this.recentContactsCache = {};\n // Cancel any pending fetches\n Object.values(this.pendingFetches).forEach((controller) =>\n controller.abort()\n );\n this.pendingFetches = {};\n }\n\n public repaintEverything() {\n if (this.jsPlumb) {\n this.jsPlumb.repaintEverything();\n }\n }\n\n public revalidate(ids: string[]) {\n if (!this.jsPlumb) return;\n this.jsPlumb.batch(() => {\n ids.forEach((id) => {\n const element = document.getElementById(id);\n if (element) {\n this.jsPlumb.revalidate(element);\n }\n });\n });\n }\n\n public reset() {\n if (this.connectionWait) {\n clearTimeout(this.connectionWait);\n this.connectionWait = null;\n }\n this.pendingConnections = [];\n this.jsPlumb.select().deleteAll();\n this.jsPlumb._managedElements = {};\n }\n\n public forgetNode(nodeId: string) {\n if (!this.jsPlumb) return;\n const element = document.getElementById(nodeId);\n if (!element) return;\n\n this.jsPlumb.deleteConnectionsForElement(element);\n this.jsPlumb.removeAllEndpoints(element);\n this.jsPlumb.unmanage(element);\n }\n\n public removeNodeConnections(nodeId: string, exitIds?: string[]) {\n if (!this.jsPlumb) return;\n\n const inbound = this.jsPlumb.select({ target: nodeId });\n\n // Use provided exitIds or try to find them in DOM (fallback)\n const exits =\n exitIds ||\n Array.from(\n document.getElementById(nodeId)?.querySelectorAll('.exit') || []\n ).map((exit) => {\n return exit.id;\n }) ||\n [];\n\n inbound.deleteAll();\n this.jsPlumb.select({ source: exits }).deleteAll();\n this.jsPlumb.selectEndpoints({ source: exits }).deleteAll();\n }\n\n public removeExitConnection(exitId: string) {\n if (!this.jsPlumb) return;\n\n const exitElement = document.getElementById(exitId);\n if (!exitElement) return;\n\n // Get all connections from this exit\n const connections = this.jsPlumb.getConnections({ source: exitElement });\n\n // Remove the connections\n connections.forEach((connection) => {\n this.jsPlumb.deleteConnection(connection);\n });\n\n return connections.length > 0;\n }\n\n public removeAllEndpoints(nodeId: string) {\n if (!this.jsPlumb) return;\n const element = document.getElementById(nodeId);\n if (!element) return;\n this.jsPlumb.removeAllEndpoints(element, true);\n }\n\n /**\n * Set the removing state for an exit's connection\n * @param exitId The ID of the exit whose connections should be marked as removing\n * @returns true if connections were found and updated, false otherwise\n */\n public setConnectionRemovingState(\n exitId: string,\n isRemoving: boolean\n ): boolean {\n if (!this.jsPlumb) return false;\n\n const exitElement = document.getElementById(exitId);\n if (!exitElement) return false;\n\n // Get all connections from this exit\n const connections = this.jsPlumb.getConnections({ source: exitElement });\n\n if (connections.length === 0) return false;\n\n // Update the connections' CSS classes\n connections.forEach((connection) => {\n if (isRemoving) {\n connection.addClass('removing');\n } else {\n connection.removeClass('removing');\n }\n });\n\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"Plumber.js","sourceRoot":"","sources":["../../../src/flow/Plumber.ts"],"names":[],"mappings":"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","sourcesContent":["export type TargetFace = 'top' | 'left' | 'right';\n\n// Shared arrow/drag constants used by both Plumber and Editor\nexport const ARROW_LENGTH = 13;\nexport const ARROW_HALF_WIDTH = 6.5;\nexport const CURSOR_GAP = 1;\nexport const EXIT_STUB = 30;\n\ninterface ConnectionEndpoints {\n sourceX: number;\n sourceY: number;\n targetX: number;\n targetY: number;\n targetFace: TargetFace;\n}\n\ninterface ConnectionInfo {\n scope: string; // nodeId\n fromId: string; // exitId\n toId: string; // target nodeId\n svgEl: SVGSVGElement;\n pathEl: SVGPathElement;\n arrowEl: SVGPolygonElement;\n}\n\ninterface DragState {\n sourceId: string;\n scope: string;\n originalTargetId: string | null;\n svgEl: SVGSVGElement;\n pathEl: SVGPathElement;\n arrowEl: SVGPolygonElement;\n onMove: (e: MouseEvent) => void;\n onUp: (e: MouseEvent) => void;\n}\n\n/**\n * Calculate a flowchart-style SVG path between two points.\n * Routes with right-angle segments, stubs at each end, and rounded corners.\n * Supports entering the target from top, left, or right faces.\n */\nexport function calculateFlowchartPath(\n sourceX: number,\n sourceY: number,\n targetX: number,\n targetY: number,\n stubStart = 20,\n stubEnd = 10,\n cornerRadius = 5,\n targetFace: TargetFace = 'top'\n): string {\n const r = cornerRadius;\n\n if (targetFace === 'top') {\n // Target is below (or we treat it as such): exit down, horizontal jog, enter from top\n const exitY = sourceY + stubStart;\n const entryY = targetY - stubEnd;\n\n let d = `M ${sourceX} ${sourceY}`;\n\n if (sourceX === targetX) {\n // Straight vertical — no turns needed\n d += ` L ${targetX} ${entryY}`;\n } else {\n // L-shape: exit curves horizontal, then straight down to target.\n // jogY is the horizontal level — must be above entryY so the\n // final approach into the node is always downward (no backtracking).\n const dirX = targetX > sourceX ? 1 : -1;\n const jogY = Math.max(sourceY + r, Math.min(exitY, entryY - r));\n\n // Corner 1: vertical→horizontal at jogY\n const r1 = Math.min(r, jogY - sourceY);\n if (r1 >= 1) {\n d += ` L ${sourceX} ${jogY - r1}`;\n d += ` Q ${sourceX} ${jogY}, ${sourceX + dirX * r1} ${jogY}`;\n } else {\n d += ` L ${sourceX} ${jogY}`;\n }\n\n // Corner 2: horizontal→vertical at targetX — leave minSeg of\n // straight line after the curve before reaching entryY\n const minSeg = 3;\n const r2 = Math.min(r, Math.max(0, entryY - jogY - minSeg));\n if (r2 >= 1) {\n d += ` L ${targetX - dirX * r2} ${jogY}`;\n d += ` Q ${targetX} ${jogY}, ${targetX} ${jogY + r2}`;\n } else {\n d += ` L ${targetX} ${jogY}`;\n }\n d += ` L ${targetX} ${entryY}`;\n }\n\n d += ` L ${targetX} ${targetY}`;\n return d;\n }\n\n if (targetFace === 'left' || targetFace === 'right') {\n // Route: exit down from source, horizontal jog, vertical to target Y, stub into side\n // When target is above source, skip the exit stub so the path turns horizontal\n // as quickly as possible (only the corner radius creates downward travel)\n const goingUp = targetY < sourceY;\n const exitY = sourceY + (goingUp ? 0 : stubStart);\n const sideDir = targetFace === 'left' ? -1 : 1;\n // Entry point is OUTSIDE the node boundary (stub behind arrowhead)\n const entryX = targetX + sideDir * stubEnd;\n\n const dirX = entryX > sourceX ? 1 : -1;\n\n // Minimum straight segment after each curve\n const minSeg = 3;\n\n // When the horizontal approach would double-back over the stub\n // (dirX matches sideDir), keep midY at the natural exit level so\n // the path jogs horizontally ABOVE the target and descends into\n // the stub — never dipping past the target and curving back up.\n // For non-backtrack, midY goes to targetY for a direct entry.\n const midY =\n dirX === sideDir ? exitY + r * 2 : Math.max(exitY + r * 2, targetY);\n\n let d = `M ${sourceX} ${sourceY} L ${sourceX} ${exitY}`;\n\n // Corner 1: vertical→horizontal at (sourceX, midY)\n if (midY - exitY > r) {\n d += ` L ${sourceX} ${midY - r}`;\n d += ` Q ${sourceX} ${midY}, ${sourceX + dirX * r} ${midY}`;\n }\n\n const vertGap = Math.abs(midY - targetY);\n\n if (vertGap < 1) {\n // midY ≈ targetY — horizontal to entryX, then stub into face\n d += ` L ${entryX} ${targetY}`;\n d += ` L ${targetX} ${targetY}`;\n } else {\n // Corners 2 and 3 — turnR is limited so that at least minSeg of\n // straight line remains between the two corners and after corner 3\n const turnDir = targetY < midY ? -1 : 1;\n const turnR = Math.min(\n r,\n Math.max(0, Math.floor((vertGap - minSeg) / 2)),\n Math.max(0, stubEnd - minSeg)\n );\n\n if (turnR >= 1) {\n // Corner 2: horizontal→vertical at (entryX, midY)\n d += ` L ${entryX - dirX * turnR} ${midY}`;\n d += ` Q ${entryX} ${midY}, ${entryX} ${midY + turnDir * turnR}`;\n // Vertical toward targetY\n d += ` L ${entryX} ${targetY - turnDir * turnR}`;\n // Corner 3: vertical→horizontal into side face\n d += ` Q ${entryX} ${targetY}, ${entryX - sideDir * turnR} ${targetY}`;\n } else {\n d += ` L ${entryX} ${midY}`;\n d += ` L ${entryX} ${targetY}`;\n }\n // Horizontal stub into target face\n d += ` L ${targetX} ${targetY}`;\n }\n\n return d;\n }\n\n return `M ${sourceX} ${sourceY} L ${targetX} ${targetY}`;\n}\n\nexport class Plumber {\n private connections: Map<string, ConnectionInfo> = new Map();\n private sources: Map<string, () => void> = new Map(); // exitId → cleanup fn\n private canvas: HTMLElement;\n private pendingConnections: {\n scope: string;\n fromId: string;\n toId: string;\n }[] = [];\n private connectionWait: number | null = null;\n private connectionListeners: Map<string, ((info: any) => void)[]> = new Map();\n private dragState: DragState | null = null;\n private editor: any;\n private retryCount = 0;\n private maxRetries = 3;\n\n // Activity overlay state\n private activityData: { segments: { [key: string]: number } } | null = null;\n private overlays: Map<string, HTMLElement> = new Map();\n private hoveredActivityKey: string | null = null;\n private recentContactsPopup: HTMLElement | null = null;\n private recentContactsCache: { [key: string]: any[] } = {};\n private pendingFetches: { [key: string]: AbortController } = {};\n private hideContactsTimeout: number | null = null;\n private showContactsTimeout: number | null = null;\n\n public connectionDragging = false;\n\n constructor(canvas: HTMLElement, editor: any) {\n this.canvas = canvas;\n this.editor = editor;\n }\n\n // --- Event system ---\n\n private notifyListeners(eventName: string, info: any) {\n const listeners = this.connectionListeners.get(eventName) || [];\n listeners.forEach((listener) => listener(info));\n }\n\n public on(eventName: string, callback: (info: any) => void) {\n if (!this.connectionListeners.has(eventName)) {\n this.connectionListeners.set(eventName, []);\n }\n this.connectionListeners.get(eventName).push(callback);\n }\n\n public off(eventName: string, callback: (info: any) => void) {\n if (!this.connectionListeners.has(eventName)) return;\n const listeners = this.connectionListeners.get(eventName);\n const index = listeners.indexOf(callback);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n }\n\n // --- Source/Target registration ---\n\n public makeSource(exitId: string) {\n const element = document.getElementById(exitId);\n if (!element) return;\n\n // Clean up any existing listener for this exit\n if (this.sources.has(exitId)) {\n this.sources.get(exitId)();\n }\n\n let pendingDrag: {\n startX: number;\n startY: number;\n onMove: (e: MouseEvent) => void;\n onUp: (e: MouseEvent) => void;\n } | null = null;\n\n const DRAG_THRESHOLD = 5;\n\n const onMouseDown = (e: MouseEvent) => {\n if (e.button !== 0) return;\n\n // Don't start drag from exit if it already has a connection —\n // existing connections are picked up from the arrowhead instead\n if (this.connections.has(exitId)) return;\n\n const startX = e.clientX;\n const startY = e.clientY;\n\n const nodeEl = element.closest('temba-flow-node');\n const scope = nodeEl?.getAttribute('uuid') || '';\n const originalTargetId: string | null = null;\n\n const onMove = (me: MouseEvent) => {\n const dx = me.clientX - startX;\n const dy = me.clientY - startY;\n if (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD) {\n // Exceeded threshold — start actual drag\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n pendingDrag = null;\n this.startDrag(exitId, scope, originalTargetId, me);\n }\n };\n\n const onUp = () => {\n // Mouse released without dragging — let click handler fire\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n pendingDrag = null;\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n pendingDrag = { startX, startY, onMove, onUp };\n };\n\n element.addEventListener('mousedown', onMouseDown);\n this.sources.set(exitId, () => {\n element.removeEventListener('mousedown', onMouseDown);\n if (pendingDrag) {\n document.removeEventListener('mousemove', pendingDrag.onMove);\n document.removeEventListener('mouseup', pendingDrag.onUp);\n pendingDrag = null;\n }\n });\n }\n\n public makeTarget(_nodeId: string) {\n // No-op: target detection happens via DOM hover during drag\n }\n\n // --- Connection creation ---\n\n public connectIds(scope: string, fromId: string, toId: string) {\n this.pendingConnections.push({ scope, fromId, toId });\n this.processPendingConnections();\n }\n\n public processPendingConnections() {\n if (this.connectionWait) {\n cancelAnimationFrame(this.connectionWait);\n this.connectionWait = null;\n }\n\n this.connectionWait = requestAnimationFrame(() => {\n const failed: { scope: string; fromId: string; toId: string }[] = [];\n const createdTargets = new Set<string>();\n\n this.pendingConnections.forEach((conn) => {\n const { scope, fromId, toId } = conn;\n // Remove existing connection from this exit if any\n this.removeConnectionSVG(fromId);\n if (!this.createConnectionSVG(fromId, scope, toId)) {\n failed.push(conn);\n } else {\n createdTargets.add(toId);\n }\n });\n this.pendingConnections = [];\n\n // Repaint all connections that share a target with newly created ones\n // so anchor distribution is correct after the full batch is processed\n if (createdTargets.size > 0) {\n this.connections.forEach((conn, exitId) => {\n if (createdTargets.has(conn.toId)) {\n this.updateConnectionSVG(exitId);\n }\n });\n }\n\n // Retry failed connections (elements may not be laid out yet)\n if (failed.length > 0 && this.retryCount < this.maxRetries) {\n this.retryCount++;\n this.pendingConnections = failed;\n this.processPendingConnections();\n } else {\n this.retryCount = 0;\n }\n });\n }\n\n // --- Anchor point distribution ---\n\n private determineTargetFace(\n sourceX: number,\n sourceY: number,\n targetRect: DOMRect,\n canvasRect: DOMRect\n ): TargetFace {\n const targetCenterX =\n targetRect.left + targetRect.width / 2 - canvasRect.left;\n const targetTop = targetRect.top - canvasRect.top;\n const verticalGap = targetTop - sourceY;\n\n // Top face requires enough vertical room for the exit stub, entry stub,\n // arrow, and curved corners. Below this threshold the path components\n // overlap and the connection backtracks, so use a side face instead.\n if (verticalGap > 30) {\n return 'top';\n }\n\n // Source is level with, below, or too close to target — connect to a side face\n if (sourceX < targetCenterX) {\n return 'left';\n }\n return 'right';\n }\n\n private getConnectionEndpoints(\n fromId: string,\n toId: string\n ): ConnectionEndpoints | null {\n const fromEl = document.getElementById(fromId);\n const toEl = document.getElementById(toId);\n if (!fromEl || !toEl) return null;\n\n const canvasRect = this.canvas.getBoundingClientRect();\n const fromRect = fromEl.getBoundingClientRect();\n const toRect = toEl.getBoundingClientRect();\n\n if (fromRect.width === 0 || toRect.width === 0) return null;\n\n const sourceX = fromRect.left + fromRect.width / 2 - canvasRect.left;\n const sourceY = fromRect.bottom - canvasRect.top;\n\n const targetFace = this.determineTargetFace(\n sourceX,\n sourceY,\n toRect,\n canvasRect\n );\n\n // Find all connections targeting the same node, grouped by face\n // Track source position for spatial sorting\n const faceConnections: Map<\n TargetFace,\n { fromId: string; sortPos: number }[]\n > = new Map();\n this.connections.forEach((conn) => {\n if (conn.toId === toId) {\n const connFromEl = document.getElementById(conn.fromId);\n if (connFromEl) {\n const connFromRect = connFromEl.getBoundingClientRect();\n const connSourceX =\n connFromRect.left + connFromRect.width / 2 - canvasRect.left;\n const connSourceY = connFromRect.bottom - canvasRect.top;\n const face = this.determineTargetFace(\n connSourceX,\n connSourceY,\n toRect,\n canvasRect\n );\n if (!faceConnections.has(face)) {\n faceConnections.set(face, []);\n }\n // Sort position: X for top face, Y for side faces\n const sortPos = face === 'top' ? connSourceX : connSourceY;\n faceConnections.get(face).push({ fromId: conn.fromId, sortPos });\n }\n }\n });\n\n // Add current connection to its face group if not already tracked\n if (!faceConnections.has(targetFace)) {\n faceConnections.set(targetFace, []);\n }\n const faceGroup = faceConnections.get(targetFace);\n if (!faceGroup.find((e) => e.fromId === fromId)) {\n const sortPos = targetFace === 'top' ? sourceX : sourceY;\n faceGroup.push({ fromId, sortPos });\n }\n\n // Sort by spatial position so connections don't cross\n faceGroup.sort((a, b) => a.sortPos - b.sortPos);\n const index = faceGroup.findIndex((e) => e.fromId === fromId);\n const count = faceGroup.length;\n\n // Calculate anchor point on the chosen face\n const targetLeft = toRect.left - canvasRect.left;\n const targetTop = toRect.top - canvasRect.top;\n const targetW = toRect.width;\n const targetH = toRect.height;\n\n let targetX: number;\n let targetY: number;\n\n if (targetFace === 'top') {\n // Distribute across top face (middle 60% of width)\n const margin = targetW * 0.2;\n const span = targetW * 0.6;\n targetX =\n count === 1\n ? targetLeft + targetW / 2\n : targetLeft + margin + (span * (index + 0.5)) / count;\n targetY = targetTop;\n } else if (targetFace === 'left') {\n targetX = targetLeft;\n // Distribute along left face (middle 60% of height)\n const margin = targetH * 0.2;\n const span = targetH * 0.6;\n targetY =\n count === 1\n ? targetTop + targetH / 2\n : targetTop + margin + (span * (index + 0.5)) / count;\n } else {\n // right\n targetX = targetLeft + targetW;\n const margin = targetH * 0.2;\n const span = targetH * 0.6;\n targetY =\n count === 1\n ? targetTop + targetH / 2\n : targetTop + margin + (span * (index + 0.5)) / count;\n }\n\n return { sourceX, sourceY, targetX, targetY, targetFace };\n }\n\n // --- SVG creation and management ---\n\n private createSVGElement(): {\n svgEl: SVGSVGElement;\n pathEl: SVGPathElement;\n arrowEl: SVGPolygonElement;\n } {\n const svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svgEl.classList.add('plumb-connector');\n svgEl.style.position = 'absolute';\n svgEl.style.left = '0';\n svgEl.style.top = '0';\n svgEl.style.width = '100%';\n svgEl.style.height = '100%';\n svgEl.style.pointerEvents = 'none';\n svgEl.style.overflow = 'visible';\n\n const pathEl = document.createElementNS(\n 'http://www.w3.org/2000/svg',\n 'path'\n );\n pathEl.setAttribute('fill', 'none');\n pathEl.setAttribute('stroke', 'var(--color-connectors)');\n pathEl.setAttribute('stroke-width', '3');\n pathEl.style.pointerEvents = 'stroke';\n\n const arrowEl = document.createElementNS(\n 'http://www.w3.org/2000/svg',\n 'polygon'\n );\n arrowEl.setAttribute('fill', 'var(--color-connectors)');\n arrowEl.classList.add('plumb-arrow');\n arrowEl.style.pointerEvents = 'fill';\n arrowEl.style.cursor = 'pointer';\n\n svgEl.appendChild(pathEl);\n svgEl.appendChild(arrowEl);\n\n // Hover support\n const addHover = () => svgEl.classList.add('hover');\n const removeHover = () => svgEl.classList.remove('hover');\n pathEl.addEventListener('mouseenter', addHover);\n pathEl.addEventListener('mouseleave', removeHover);\n arrowEl.addEventListener('mouseenter', addHover);\n arrowEl.addEventListener('mouseleave', removeHover);\n\n return { svgEl, pathEl, arrowEl };\n }\n\n private updateSVGPath(\n pathEl: SVGPathElement,\n arrowEl: SVGPolygonElement,\n sourceX: number,\n sourceY: number,\n targetX: number,\n targetY: number,\n targetFace: TargetFace = 'top'\n ) {\n const aw = ARROW_HALF_WIDTH;\n const al = ARROW_LENGTH;\n const stubBehindArrow = 8;\n\n // Path ends at arrow BASE (not tip) so the line never pokes through the front.\n // The arrow polygon covers from base to the node edge (tip).\n let pathTargetX = targetX;\n let pathTargetY = targetY;\n if (targetFace === 'top') {\n pathTargetY = targetY - al;\n } else if (targetFace === 'left') {\n pathTargetX = targetX - al;\n } else if (targetFace === 'right') {\n pathTargetX = targetX + al;\n }\n\n const effectiveStub = stubBehindArrow;\n const d = calculateFlowchartPath(\n sourceX,\n sourceY,\n pathTargetX,\n pathTargetY,\n EXIT_STUB,\n effectiveStub,\n 5,\n targetFace\n );\n pathEl.setAttribute('d', d);\n\n // Arrow tip at node edge, base extends outward\n if (targetFace === 'top') {\n arrowEl.setAttribute(\n 'points',\n `${targetX},${targetY} ${targetX - aw},${targetY - al} ${\n targetX + aw\n },${targetY - al}`\n );\n } else if (targetFace === 'left') {\n arrowEl.setAttribute(\n 'points',\n `${targetX},${targetY} ${targetX - al},${targetY - aw} ${\n targetX - al\n },${targetY + aw}`\n );\n } else {\n arrowEl.setAttribute(\n 'points',\n `${targetX},${targetY} ${targetX + al},${targetY - aw} ${\n targetX + al\n },${targetY + aw}`\n );\n }\n }\n\n private createConnectionSVG(\n exitId: string,\n scope: string,\n toId: string\n ): boolean {\n const endpoints = this.getConnectionEndpoints(exitId, toId);\n if (!endpoints) return false;\n\n const { svgEl, pathEl, arrowEl } = this.createSVGElement();\n this.updateSVGPath(\n pathEl,\n arrowEl,\n endpoints.sourceX,\n endpoints.sourceY,\n endpoints.targetX,\n endpoints.targetY,\n endpoints.targetFace\n );\n this.canvas.appendChild(svgEl);\n\n this.connections.set(exitId, {\n scope,\n fromId: exitId,\n toId,\n svgEl,\n pathEl,\n arrowEl\n });\n\n // Make arrowhead draggable for picking up existing connections\n const DRAG_THRESHOLD = 5;\n const onArrowMouseDown = (e: MouseEvent) => {\n if (e.button !== 0) return;\n e.stopPropagation();\n\n const startX = e.clientX;\n const startY = e.clientY;\n\n const onMove = (me: MouseEvent) => {\n const dx = me.clientX - startX;\n const dy = me.clientY - startY;\n if (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD) {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this.startDrag(exitId, scope, toId, me);\n }\n };\n\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n };\n arrowEl.addEventListener('mousedown', onArrowMouseDown);\n\n // Mark the exit element as connected\n const exitEl = document.getElementById(exitId);\n if (exitEl) {\n exitEl.classList.add('connected');\n }\n\n // Create activity overlay if activity data exists for this segment\n if (this.activityData) {\n const activityKey = `${exitId}:${toId}`;\n const count = this.activityData.segments[activityKey];\n if (count && count > 0) {\n const overlayEl = this.createOverlayElement(count, activityKey);\n this.canvas.appendChild(overlayEl);\n this.overlays.set(exitId, overlayEl);\n this.updateOverlayPosition(exitId);\n }\n }\n\n return true;\n }\n\n private updateConnectionSVG(exitId: string) {\n const conn = this.connections.get(exitId);\n if (!conn) return;\n\n const endpoints = this.getConnectionEndpoints(conn.fromId, conn.toId);\n if (!endpoints) return;\n\n this.updateSVGPath(\n conn.pathEl,\n conn.arrowEl,\n endpoints.sourceX,\n endpoints.sourceY,\n endpoints.targetX,\n endpoints.targetY,\n endpoints.targetFace\n );\n this.updateOverlayPosition(exitId);\n }\n\n private removeConnectionSVG(exitId: string) {\n const conn = this.connections.get(exitId);\n if (!conn) return;\n\n const overlay = this.overlays.get(exitId);\n if (overlay) {\n overlay.remove();\n this.overlays.delete(exitId);\n }\n\n conn.svgEl.remove();\n this.connections.delete(exitId);\n }\n\n // --- Repaint ---\n\n public repaintEverything() {\n this.connections.forEach((_conn, exitId) => {\n this.updateConnectionSVG(exitId);\n });\n }\n\n public revalidate(ids: string[]) {\n // Find all connections directly involving the given IDs\n const directExits: string[] = [];\n const affectedTargets = new Set<string>();\n\n this.connections.forEach((conn, exitId) => {\n if (\n ids.includes(conn.fromId) ||\n ids.includes(conn.toId) ||\n ids.includes(conn.scope)\n ) {\n directExits.push(exitId);\n affectedTargets.add(conn.toId);\n }\n });\n\n // Also repaint sibling connections that share a target\n // (so anchor distribution stays correct during drag)\n const allExitsToRepaint = new Set(directExits);\n this.connections.forEach((conn, exitId) => {\n if (affectedTargets.has(conn.toId)) {\n allExitsToRepaint.add(exitId);\n }\n });\n\n allExitsToRepaint.forEach((exitId) => {\n this.updateConnectionSVG(exitId);\n });\n }\n\n // --- Connection removal ---\n\n public forgetNode(nodeId: string) {\n // Remove all connections where this node is source or target\n const toRemove: string[] = [];\n this.connections.forEach((conn, exitId) => {\n if (conn.scope === nodeId || conn.toId === nodeId) {\n toRemove.push(exitId);\n }\n });\n toRemove.forEach((exitId) => this.removeConnectionSVG(exitId));\n\n // Remove source listeners for exits of this node\n const exitEls = document.getElementById(nodeId)?.querySelectorAll('.exit');\n if (exitEls) {\n exitEls.forEach((el) => {\n const id = el.id;\n if (this.sources.has(id)) {\n this.sources.get(id)();\n this.sources.delete(id);\n }\n });\n }\n }\n\n public removeNodeConnections(nodeId: string, exitIds?: string[]) {\n // Only remove outbound connections from this node's exits.\n // Inbound connections are managed by their source nodes and\n // will repaint correctly on the next revalidate.\n const exits =\n exitIds ||\n Array.from(\n document.getElementById(nodeId)?.querySelectorAll('.exit') || []\n ).map((el) => el.id);\n\n exits.forEach((exitId) => this.removeConnectionSVG(exitId));\n }\n\n public removeExitConnection(exitId: string): boolean {\n if (!this.connections.has(exitId)) return false;\n this.removeConnectionSVG(exitId);\n return true;\n }\n\n public removeAllEndpoints(nodeId: string) {\n // Remove source listeners for this node's exits\n const exitEls = document.getElementById(nodeId)?.querySelectorAll('.exit');\n if (exitEls) {\n exitEls.forEach((el) => {\n const id = el.id;\n if (this.sources.has(id)) {\n this.sources.get(id)();\n this.sources.delete(id);\n }\n });\n }\n }\n\n // --- Connection state ---\n\n public setConnectionRemovingState(\n exitId: string,\n isRemoving: boolean\n ): boolean {\n const conn = this.connections.get(exitId);\n if (!conn) return false;\n\n if (isRemoving) {\n conn.svgEl.classList.add('removing');\n } else {\n conn.svgEl.classList.remove('removing');\n }\n return true;\n }\n\n // --- Activity overlays ---\n\n public setActivityData(\n activityData: { segments: { [key: string]: number } } | null\n ) {\n this.activityData = activityData;\n this.clearRecentContactsCache();\n this.updateActivityOverlays();\n }\n\n private updateActivityOverlays() {\n if (!this.activityData) {\n this.overlays.forEach((el) => el.remove());\n this.overlays.clear();\n return;\n }\n\n const activeExitIds = new Set<string>();\n\n this.connections.forEach((conn, exitId) => {\n const activityKey = `${conn.fromId}:${conn.toId}`;\n const count = this.activityData.segments[activityKey];\n\n if (count && count > 0) {\n activeExitIds.add(exitId);\n let overlayEl = this.overlays.get(exitId);\n\n if (!overlayEl) {\n overlayEl = this.createOverlayElement(count, activityKey);\n this.canvas.appendChild(overlayEl);\n this.overlays.set(exitId, overlayEl);\n } else {\n overlayEl.textContent = count.toLocaleString();\n overlayEl.setAttribute('data-activity-key', activityKey);\n }\n\n this.updateOverlayPosition(exitId);\n }\n });\n\n // Remove overlays for connections that no longer have activity\n this.overlays.forEach((el, exitId) => {\n if (!activeExitIds.has(exitId)) {\n el.remove();\n this.overlays.delete(exitId);\n }\n });\n }\n\n private createOverlayElement(\n count: number,\n activityKey: string\n ): HTMLElement {\n const el = document.createElement('div');\n el.className = 'activity-overlay';\n el.textContent = count.toLocaleString();\n el.setAttribute('data-activity-key', activityKey);\n\n el.addEventListener('mouseenter', () => {\n const flowUuid = this.getFlowUuid();\n if (flowUuid) {\n this.fetchRecentContacts(activityKey, flowUuid);\n this.showContactsTimeout = window.setTimeout(() => {\n this.showRecentContacts(activityKey, flowUuid);\n }, 500);\n }\n });\n\n el.addEventListener('mouseleave', () => {\n if (this.showContactsTimeout) {\n clearTimeout(this.showContactsTimeout);\n this.showContactsTimeout = null;\n }\n this.hoveredActivityKey = null;\n this.hideRecentContacts();\n });\n\n return el;\n }\n\n private updateOverlayPosition(exitId: string) {\n const overlayEl = this.overlays.get(exitId);\n const conn = this.connections.get(exitId);\n if (!overlayEl || !conn) return;\n\n const endpoints = this.getConnectionEndpoints(conn.fromId, conn.toId);\n if (!endpoints) return;\n\n overlayEl.style.position = 'absolute';\n overlayEl.style.left = `${endpoints.sourceX}px`;\n overlayEl.style.top = `${endpoints.sourceY + EXIT_STUB / 2}px`;\n overlayEl.style.transform = 'translate(-50%, -50%)';\n }\n\n private getFlowUuid(): string | null {\n return this.editor?.definition?.uuid || null;\n }\n\n // --- Recent contacts ---\n\n private async fetchRecentContacts(activityKey: string, flowUuid: string) {\n if (\n this.recentContactsCache[activityKey] ||\n this.pendingFetches[activityKey]\n ) {\n return;\n }\n\n const controller = new AbortController();\n this.pendingFetches[activityKey] = controller;\n\n try {\n const [exitUuid, destinationUuid] = activityKey.split(':');\n const endpoint = `/flow/recent_contacts/${flowUuid}/${exitUuid}/${destinationUuid}/`;\n const response = await fetch(endpoint, { signal: controller.signal });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n this.recentContactsCache[activityKey] = Array.isArray(data)\n ? data\n : data.results || [];\n } catch (error) {\n if ((error as Error).name !== 'AbortError') {\n console.error('Failed to fetch recent contacts:', error);\n }\n } finally {\n delete this.pendingFetches[activityKey];\n }\n }\n\n private async showRecentContacts(activityKey: string, flowUuid: string) {\n const overlayElement = this.findOverlayForActivityKey(activityKey);\n if (!overlayElement) return;\n\n if (this.hideContactsTimeout) {\n clearTimeout(this.hideContactsTimeout);\n this.hideContactsTimeout = null;\n }\n\n this.hoveredActivityKey = activityKey;\n\n if (!this.recentContactsPopup) {\n this.recentContactsPopup = document.createElement('div');\n this.recentContactsPopup.className = 'recent-contacts-popup';\n this.recentContactsPopup.style.position = 'absolute';\n this.recentContactsPopup.style.zIndex = '1015';\n this.recentContactsPopup.style.display = 'none';\n document.body.appendChild(this.recentContactsPopup);\n\n this.recentContactsPopup.onmouseenter = () => {\n if (this.hideContactsTimeout) {\n clearTimeout(this.hideContactsTimeout);\n this.hideContactsTimeout = null;\n }\n };\n this.recentContactsPopup.onmouseleave = () => {\n this.hoveredActivityKey = null;\n this.hideRecentContacts();\n };\n\n this.recentContactsPopup.onclick = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n if (target.classList.contains('contact-name')) {\n this.hideRecentContacts(false);\n const contactUuid = target.getAttribute('data-uuid');\n if (contactUuid) {\n this.editor.fireCustomEvent('temba-contact-clicked', {\n uuid: contactUuid\n });\n }\n }\n };\n }\n\n if (this.recentContactsCache[activityKey]) {\n this.renderRecentContactsPopup(this.recentContactsCache[activityKey]);\n this.positionPopup(overlayElement);\n } else {\n this.recentContactsPopup.innerHTML =\n '<div class=\"no-contacts-message\">Loading...</div>';\n this.positionPopup(overlayElement);\n await this.fetchRecentContacts(activityKey, flowUuid);\n if (this.hoveredActivityKey === activityKey) {\n this.renderRecentContactsPopup(\n this.recentContactsCache[activityKey] || []\n );\n this.positionPopup(overlayElement);\n }\n }\n }\n\n private findOverlayForActivityKey(activityKey: string): HTMLElement | null {\n for (const [, el] of this.overlays) {\n if (el.getAttribute('data-activity-key') === activityKey) {\n return el;\n }\n }\n return null;\n }\n\n private positionPopup(overlayElement: HTMLElement) {\n if (!this.recentContactsPopup) return;\n const rect = overlayElement.getBoundingClientRect();\n this.recentContactsPopup.style.left = `${rect.left + window.scrollX}px`;\n this.recentContactsPopup.style.top = `${\n rect.bottom + window.scrollY + 5\n }px`;\n this.recentContactsPopup.style.display = '';\n this.recentContactsPopup.classList.remove('show');\n void this.recentContactsPopup.offsetWidth;\n this.recentContactsPopup.classList.add('show');\n }\n\n private renderRecentContactsPopup(recentContacts: any[]) {\n if (!this.recentContactsPopup) return;\n\n if (recentContacts.length === 0) {\n this.recentContactsPopup.innerHTML =\n '<div class=\"no-contacts-message\">No Recent Contacts</div>';\n return;\n }\n\n let html = '<div class=\"popup-title\">Recent Contacts</div>';\n recentContacts.forEach((contact: any) => {\n html += '<div class=\"contact-row\">';\n html += `<div class=\"contact-name\" data-uuid=\"${contact.contact.uuid}\">${contact.contact.name}</div>`;\n if (contact.operand) {\n html += `<div class=\"contact-operand\">${contact.operand}</div>`;\n }\n if (contact.time) {\n const time = new Date(contact.time);\n const diffMs = Date.now() - time.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n let timeStr = '';\n if (diffMins < 1) timeStr = 'just now';\n else if (diffMins < 60) timeStr = `${diffMins}m ago`;\n else if (diffHours < 24) timeStr = `${diffHours}h ago`;\n else timeStr = `${diffDays}d ago`;\n html += `<div class=\"contact-time\">${timeStr}</div>`;\n }\n html += '</div>';\n });\n this.recentContactsPopup.innerHTML = html;\n }\n\n private hideRecentContacts(wait = true) {\n if (!wait) {\n if (this.recentContactsPopup) {\n this.recentContactsPopup.classList.remove('show');\n this.recentContactsPopup.style.display = 'none';\n this.hoveredActivityKey = null;\n }\n return;\n }\n\n this.hideContactsTimeout = window.setTimeout(() => {\n if (!this.hoveredActivityKey && this.recentContactsPopup) {\n this.recentContactsPopup.classList.remove('show');\n this.recentContactsPopup.style.display = 'none';\n this.hoveredActivityKey = null;\n }\n }, 200);\n }\n\n public clearRecentContactsCache() {\n this.recentContactsCache = {};\n Object.values(this.pendingFetches).forEach((controller) =>\n controller.abort()\n );\n this.pendingFetches = {};\n }\n\n // --- Drag-and-drop ---\n\n private startDrag(\n exitId: string,\n scope: string,\n originalTargetId: string | null,\n e: MouseEvent\n ) {\n // Remove existing connection SVG for this exit (the connection is being dragged away)\n this.removeConnectionSVG(exitId);\n\n const { svgEl, pathEl, arrowEl } = this.createSVGElement();\n svgEl.classList.add('dragging');\n // Ensure the drag SVG never intercepts mouse events (e.g. hover detection on nodes)\n pathEl.style.pointerEvents = 'none';\n arrowEl.style.pointerEvents = 'none';\n this.canvas.appendChild(svgEl);\n\n // Calculate source point\n const exitEl = document.getElementById(exitId);\n if (!exitEl) {\n svgEl.remove();\n return;\n }\n\n const canvasRect = this.canvas.getBoundingClientRect();\n const exitRect = exitEl.getBoundingClientRect();\n const sourceX = exitRect.left + exitRect.width / 2 - canvasRect.left;\n const sourceY = exitRect.bottom - canvasRect.top;\n\n const aw = ARROW_HALF_WIDTH;\n const al = ARROW_LENGTH;\n const stubBehindArrow = 8;\n\n // Update the drag path and arrow based on cursor position.\n // Arrow trails just before the cursor (between source and cursor).\n const cursorGap = CURSOR_GAP;\n const updateDragPath = (cx: number, cy: number) => {\n const goingUp = cy < sourceY;\n\n let routeFace: TargetFace = 'top';\n if (goingUp) {\n routeFace = cx < sourceX ? 'left' : 'right';\n }\n\n // Position the arrow so its top edge sits just before the cursor.\n // \"Top\" = smallest Y on screen, which is the base for a downward\n // arrow and the tip for an upward arrow.\n let arrowBaseY: number;\n if (goingUp) {\n // Arrow points up: tip just below cursor, base below that\n arrowBaseY = cy + cursorGap + al;\n } else {\n // Arrow points down: base just above cursor, tip below\n arrowBaseY = cy - cursorGap;\n }\n\n const d = calculateFlowchartPath(\n sourceX,\n sourceY,\n cx,\n arrowBaseY,\n EXIT_STUB,\n goingUp ? 0 : stubBehindArrow,\n 5,\n routeFace\n );\n pathEl.setAttribute('d', d);\n\n if (goingUp) {\n const tipY = cy + cursorGap;\n arrowEl.setAttribute(\n 'points',\n `${cx},${tipY} ${cx - aw},${arrowBaseY} ${cx + aw},${arrowBaseY}`\n );\n } else {\n const tipY = arrowBaseY + al;\n arrowEl.setAttribute(\n 'points',\n `${cx},${tipY} ${cx - aw},${arrowBaseY} ${cx + aw},${arrowBaseY}`\n );\n }\n };\n\n // Initial path to cursor\n const cursorX = e.clientX - canvasRect.left;\n const cursorY = e.clientY - canvasRect.top;\n updateDragPath(cursorX, cursorY);\n\n this.connectionDragging = true;\n\n const onMove = (me: MouseEvent) => {\n const cx = me.clientX - canvasRect.left;\n const cy = me.clientY - canvasRect.top;\n updateDragPath(cx, cy);\n };\n\n const onUp = (_me: MouseEvent) => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n\n // Remove the drag SVG\n svgEl.remove();\n this.connectionDragging = false;\n this.dragState = null;\n\n // Fire abort event so Editor can handle connection logic\n this.notifyListeners('connection:abort', {\n source: exitEl,\n sourceId: exitId,\n target: { id: originalTargetId },\n data: { nodeId: scope }\n });\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n\n this.dragState = {\n sourceId: exitId,\n scope,\n originalTargetId,\n svgEl,\n pathEl,\n arrowEl,\n onMove,\n onUp\n };\n\n // Fire drag event so Editor knows a drag has started\n this.notifyListeners('connection:drag', {\n sourceId: exitId,\n sourceX,\n sourceY,\n data: { nodeId: scope },\n target: { id: originalTargetId }\n });\n }\n\n // --- Reset ---\n\n public reset() {\n if (this.connectionWait) {\n cancelAnimationFrame(this.connectionWait);\n this.connectionWait = null;\n }\n this.pendingConnections = [];\n\n // Remove all connection SVGs\n this.connections.forEach((conn) => conn.svgEl.remove());\n this.connections.clear();\n\n // Remove all activity overlays\n this.overlays.forEach((el) => el.remove());\n this.overlays.clear();\n\n // Clean up recent contacts popup\n this.hideRecentContacts(false);\n if (this.recentContactsPopup) {\n this.recentContactsPopup.remove();\n this.recentContactsPopup = null;\n }\n this.recentContactsCache = {};\n Object.values(this.pendingFetches).forEach((c) => c.abort());\n this.pendingFetches = {};\n\n // Remove all source listeners\n this.sources.forEach((cleanup) => cleanup());\n this.sources.clear();\n\n // Clean up any active drag\n if (this.dragState) {\n document.removeEventListener('mousemove', this.dragState.onMove);\n document.removeEventListener('mouseup', this.dragState.onUp);\n this.dragState.svgEl.remove();\n this.dragState = null;\n this.connectionDragging = false;\n }\n }\n}\n"]}
@@ -281,7 +281,7 @@ export class StickyNote extends RapidElement {
281
281
  }
282
282
  handleBodyBlur(event) {
283
283
  const target = event.target;
284
- const newBody = target.textContent || '';
284
+ const newBody = target.innerText || '';
285
285
  if (this.data && newBody !== this.data.body) {
286
286
  getStore()
287
287
  .getState()
@@ -301,7 +301,16 @@ export class StickyNote extends RapidElement {
301
301
  // Otherwise, stop propagation to enable editing
302
302
  event.stopPropagation();
303
303
  }
304
- handleKeyDown(event) {
304
+ handleTitleKeyDown(event) {
305
+ if (event.key === 'Enter') {
306
+ event.preventDefault();
307
+ event.target.blur();
308
+ }
309
+ if (event.key === 'Escape') {
310
+ event.target.blur();
311
+ }
312
+ }
313
+ handleBodyKeyDown(event) {
305
314
  if (event.key === 'Enter' && !event.shiftKey) {
306
315
  event.preventDefault();
307
316
  event.target.blur();
@@ -348,7 +357,7 @@ export class StickyNote extends RapidElement {
348
357
  class="sticky-title"
349
358
  contenteditable="${!this.isTranslating}"
350
359
  @blur="${this.handleTitleBlur}"
351
- @keydown="${this.handleKeyDown}"
360
+ @keydown="${this.handleTitleKeyDown}"
352
361
  @mousedown="${this.handleContentMouseDown}"
353
362
  .textContent="${this.data.title}"
354
363
  ></div>
@@ -358,7 +367,7 @@ export class StickyNote extends RapidElement {
358
367
  class="sticky-body"
359
368
  contenteditable="${!this.isTranslating}"
360
369
  @blur="${this.handleBodyBlur}"
361
- @keydown="${this.handleKeyDown}"
370
+ @keydown="${this.handleBodyKeyDown}"
362
371
  @mousedown="${this.handleContentMouseDown}"
363
372
  .textContent="${this.data.body}"
364
373
  ></div>
@@ -1 +1 @@
1
- {"version":3,"file":"StickyNote.js","sourceRoot":"","sources":["../../../src/flow/StickyNote.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { StickyNote as StickyNoteData } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\n\nexport class StickyNote extends RapidElement {\n @property({ type: String })\n public uuid: string;\n\n @property({ type: Object })\n public data: StickyNoteData;\n\n @property({ type: Boolean })\n private dragging = false;\n\n @property({ type: Boolean })\n public selected = false;\n\n @property({ type: Boolean })\n private colorPickerExpanded = false;\n\n @fromStore(zustand, (state: AppState) => state.isTranslating)\n private isTranslating!: boolean;\n\n static get styles() {\n return css`\n :host {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n --curvature: 8px;\n }\n\n .sticky-note {\n width: 182px;\n background-color: var(--sticky-color);\n border: 1px solid var(--sticky-border-color);\n border-radius: var(--curvature);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n sans-serif;\n font-size: 12px;\n overflow: hidden;\n transition: transform 0.1s ease, box-shadow 0.2s ease;\n color: var(--sticky-text-color);\n opacity: 0.85;\n }\n\n .sticky-note.dragging {\n opacity: 0.7;\n z-index: 1000;\n transform: rotate(0deg);\n box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:hover {\n transform: translateY(0px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n }\n\n /* Color themes */\n .sticky-note.yellow {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n }\n .sticky-note.blue {\n --sticky-color: #bfdbfe;\n --sticky-border-color: #3b82f6;\n --sticky-text-color: #1e3a8a;\n }\n .sticky-note.pink {\n --sticky-color: #fce7f3;\n --sticky-border-color: #ec4899;\n --sticky-text-color: #831843;\n }\n .sticky-note.green {\n --sticky-color: #d1fae5;\n --sticky-border-color: #10b981;\n --sticky-text-color: #064e3b;\n }\n .sticky-note.gray {\n --sticky-color: #f3f4f6;\n --sticky-border-color: #6b7280;\n --sticky-text-color: #374151;\n }\n\n /* Title and body containers */\n .sticky-title-container {\n position: relative;\n border-bottom: 1px solid var(--sticky-border-color);\n background-color: rgba(255, 255, 255, 0.5);\n display: flex;\n align-items: center;\n }\n .sticky-body-container {\n position: relative;\n }\n\n /* Editable fields */\n [contenteditable='true'] {\n margin: 2px;\n padding: 4px 8px;\n outline: none;\n border-radius: var(--curvature);\n transition: background 0.2s;\n }\n [contenteditable='true']:focus {\n background-color: rgba(255, 255, 255, 0.8);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n outline-color: var(--sticky-border-color);\n }\n\n /* Title */\n .sticky-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--sticky-text-color);\n min-height: 20px;\n line-height: 20px;\n border-top-left-radius: var(--curvature);\n border-top-right-radius: var(--curvature);\n flex-grow: 1;\n padding: 4px 8px !important;\n margin: 2px;\n padding-left: 8px;\n }\n .sticky-title:empty::before {\n content: 'Click to add title';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-title:focus {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n /* Body */\n .sticky-body {\n padding: 8px 10px;\n color: var(--sticky-text-color);\n line-height: 1.4;\n min-height: 48px;\n word-wrap: break-word;\n white-space: pre-wrap;\n margin: 2px;\n }\n .sticky-body:empty::before {\n content: 'Click to add note';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-body:focus {\n border-top-left-radius: 0px;\n border-top-right-radius: 0px;\n }\n\n /* Drag icon */\n .sticky-title-container > .drag-handle {\n --icon-color: var(--sticky-border-color);\n cursor: move;\n max-width: 20px;\n padding-left: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .sticky-note:hover .drag-handle {\n }\n\n .sticky-note:focus-within .sticky-title-container > .drag-handle {\n }\n\n /* Focus/active states */\n .sticky-note:focus-within {\n box-shadow: 0 0 0 1px var(--sticky-border-color),\n 0 10px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:focus-within .drag-handle {\n max-width: 0px;\n padding-left: 0px;\n }\n\n /* Color picker */\n .color-picker {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 8px;\n height: 8px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n\n border-radius: 3px;\n background-color: var(--sticky-color);\n cursor: pointer;\n transition: transform 0.2s ease;\n }\n\n .color-picker:hover {\n transform: scale(1.1);\n }\n\n .color-options {\n position: absolute;\n bottom: 0;\n right: 0;\n display: flex;\n gap: 4px;\n background-color: rgba(255, 255, 255, 0.9);\n border: 1px solid #ccc;\n border-radius: 6px;\n padding: 3px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform-origin: bottom right;\n transform: scale(0);\n opacity: 0;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: 1000;\n }\n\n .color-options.expanded {\n transform: scale(1);\n opacity: 1;\n }\n\n .color-option {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n cursor: pointer;\n transition: transform 0.15s ease, border-color 0.15s ease;\n }\n\n .color-option:hover {\n transform: scale(1.1);\n border-color: rgba(0, 0, 0, 0.4);\n }\n\n .color-option.yellow {\n background-color: #fef08a;\n }\n\n .color-option.blue {\n background-color: #bfdbfe;\n }\n\n .color-option.pink {\n background-color: #fce7f3;\n }\n\n .color-option.green {\n background-color: #d1fae5;\n }\n\n .color-option.gray {\n background-color: #f3f4f6;\n }\n `;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('data') || changes.has('uuid')) {\n this.updateCanvasSize();\n }\n }\n\n private updateCanvasSize(): void {\n if (!this.data) {\n return;\n }\n\n const element = this.querySelector('.sticky-note');\n if (element) {\n const rect = element.getBoundingClientRect();\n getStore()\n .getState()\n .expandCanvas(\n this.data.position.left + rect.width,\n this.data.position.top + rect.height\n );\n }\n }\n\n private handleTitleBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newTitle = target.textContent || '';\n\n if (this.data && newTitle !== this.data.title) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n title: newTitle\n });\n }\n this.requestUpdate();\n }\n\n private handleBodyBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newBody = target.textContent || '';\n\n if (this.data && newBody !== this.data.body) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n body: newBody\n });\n }\n this.requestUpdate();\n }\n\n private handleContentMouseDown(event: MouseEvent): void {\n // If this sticky note is selected, don't stop propagation\n // so that group dragging can work\n if (this.selected) {\n return;\n }\n // Otherwise, stop propagation to enable editing\n event.stopPropagation();\n }\n\n private handleKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleColorPickerMouseEnter(): void {\n this.colorPickerExpanded = true;\n }\n\n private handleColorPickerMouseLeave(): void {\n this.colorPickerExpanded = false;\n }\n\n private handleColorOptionClick(\n event: MouseEvent,\n color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'\n ): void {\n event.stopPropagation();\n\n if (this.data && color !== this.data.color) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n color: color\n });\n }\n\n this.colorPickerExpanded = false;\n this.requestUpdate();\n }\n\n public render(): TemplateResult {\n if (!this.data) {\n return html`<div class=\"sticky-note\" style=\"display: none;\"></div>`;\n }\n\n const style = `left: ${this.data.position.left}px; top: ${this.data.position.top}px;`;\n\n return html`\n <div\n class=\"sticky-note ${this.data.color} ${this.dragging\n ? 'dragging'\n : ''}\"\n style=\"${style}\"\n data-uuid=\"${this.uuid}\"\n >\n <div class=\"sticky-title-container\">\n <temba-icon name=\"drag\" class=\"drag-handle\"></temba-icon>\n <div\n class=\"sticky-title\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleTitleBlur}\"\n @keydown=\"${this.handleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.title}\"\n ></div>\n </div>\n <div class=\"sticky-body-container\">\n <div\n class=\"sticky-body\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleBodyBlur}\"\n @keydown=\"${this.handleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.body}\"\n ></div>\n ${!this.isTranslating\n ? html`<div class=\"edit-icon\" title=\"Edit note\"></div>`\n : ''}\n\n <!-- Color picker -->\n <div\n class=\"color-picker\"\n @mouseenter=\"${this.handleColorPickerMouseEnter}\"\n @mouseleave=\"${this.handleColorPickerMouseLeave}\"\n >\n <div\n class=\"color-options ${this.colorPickerExpanded\n ? 'expanded'\n : ''}\"\n >\n <div\n class=\"color-option yellow\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'yellow')}\"\n ></div>\n <div\n class=\"color-option blue\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'blue')}\"\n ></div>\n <div\n class=\"color-option pink\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'pink')}\"\n ></div>\n <div\n class=\"color-option green\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'green')}\"\n ></div>\n <div\n class=\"color-option gray\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'gray')}\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"StickyNote.js","sourceRoot":"","sources":["../../../src/flow/StickyNote.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { StickyNote as StickyNoteData } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\n\nexport class StickyNote extends RapidElement {\n @property({ type: String })\n public uuid: string;\n\n @property({ type: Object })\n public data: StickyNoteData;\n\n @property({ type: Boolean })\n private dragging = false;\n\n @property({ type: Boolean })\n public selected = false;\n\n @property({ type: Boolean })\n private colorPickerExpanded = false;\n\n @fromStore(zustand, (state: AppState) => state.isTranslating)\n private isTranslating!: boolean;\n\n static get styles() {\n return css`\n :host {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n --curvature: 8px;\n }\n\n .sticky-note {\n width: 182px;\n background-color: var(--sticky-color);\n border: 1px solid var(--sticky-border-color);\n border-radius: var(--curvature);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n sans-serif;\n font-size: 12px;\n overflow: hidden;\n transition: transform 0.1s ease, box-shadow 0.2s ease;\n color: var(--sticky-text-color);\n opacity: 0.85;\n }\n\n .sticky-note.dragging {\n opacity: 0.7;\n z-index: 1000;\n transform: rotate(0deg);\n box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:hover {\n transform: translateY(0px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n }\n\n /* Color themes */\n .sticky-note.yellow {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n }\n .sticky-note.blue {\n --sticky-color: #bfdbfe;\n --sticky-border-color: #3b82f6;\n --sticky-text-color: #1e3a8a;\n }\n .sticky-note.pink {\n --sticky-color: #fce7f3;\n --sticky-border-color: #ec4899;\n --sticky-text-color: #831843;\n }\n .sticky-note.green {\n --sticky-color: #d1fae5;\n --sticky-border-color: #10b981;\n --sticky-text-color: #064e3b;\n }\n .sticky-note.gray {\n --sticky-color: #f3f4f6;\n --sticky-border-color: #6b7280;\n --sticky-text-color: #374151;\n }\n\n /* Title and body containers */\n .sticky-title-container {\n position: relative;\n border-bottom: 1px solid var(--sticky-border-color);\n background-color: rgba(255, 255, 255, 0.5);\n display: flex;\n align-items: center;\n }\n .sticky-body-container {\n position: relative;\n }\n\n /* Editable fields */\n [contenteditable='true'] {\n margin: 2px;\n padding: 4px 8px;\n outline: none;\n border-radius: var(--curvature);\n transition: background 0.2s;\n }\n [contenteditable='true']:focus {\n background-color: rgba(255, 255, 255, 0.8);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n outline-color: var(--sticky-border-color);\n }\n\n /* Title */\n .sticky-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--sticky-text-color);\n min-height: 20px;\n line-height: 20px;\n border-top-left-radius: var(--curvature);\n border-top-right-radius: var(--curvature);\n flex-grow: 1;\n padding: 4px 8px !important;\n margin: 2px;\n padding-left: 8px;\n }\n .sticky-title:empty::before {\n content: 'Click to add title';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-title:focus {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n /* Body */\n .sticky-body {\n padding: 8px 10px;\n color: var(--sticky-text-color);\n line-height: 1.4;\n min-height: 48px;\n word-wrap: break-word;\n white-space: pre-wrap;\n margin: 2px;\n }\n .sticky-body:empty::before {\n content: 'Click to add note';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-body:focus {\n border-top-left-radius: 0px;\n border-top-right-radius: 0px;\n }\n\n /* Drag icon */\n .sticky-title-container > .drag-handle {\n --icon-color: var(--sticky-border-color);\n cursor: move;\n max-width: 20px;\n padding-left: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .sticky-note:hover .drag-handle {\n }\n\n .sticky-note:focus-within .sticky-title-container > .drag-handle {\n }\n\n /* Focus/active states */\n .sticky-note:focus-within {\n box-shadow: 0 0 0 1px var(--sticky-border-color),\n 0 10px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:focus-within .drag-handle {\n max-width: 0px;\n padding-left: 0px;\n }\n\n /* Color picker */\n .color-picker {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 8px;\n height: 8px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n\n border-radius: 3px;\n background-color: var(--sticky-color);\n cursor: pointer;\n transition: transform 0.2s ease;\n }\n\n .color-picker:hover {\n transform: scale(1.1);\n }\n\n .color-options {\n position: absolute;\n bottom: 0;\n right: 0;\n display: flex;\n gap: 4px;\n background-color: rgba(255, 255, 255, 0.9);\n border: 1px solid #ccc;\n border-radius: 6px;\n padding: 3px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform-origin: bottom right;\n transform: scale(0);\n opacity: 0;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: 1000;\n }\n\n .color-options.expanded {\n transform: scale(1);\n opacity: 1;\n }\n\n .color-option {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n cursor: pointer;\n transition: transform 0.15s ease, border-color 0.15s ease;\n }\n\n .color-option:hover {\n transform: scale(1.1);\n border-color: rgba(0, 0, 0, 0.4);\n }\n\n .color-option.yellow {\n background-color: #fef08a;\n }\n\n .color-option.blue {\n background-color: #bfdbfe;\n }\n\n .color-option.pink {\n background-color: #fce7f3;\n }\n\n .color-option.green {\n background-color: #d1fae5;\n }\n\n .color-option.gray {\n background-color: #f3f4f6;\n }\n `;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('data') || changes.has('uuid')) {\n this.updateCanvasSize();\n }\n }\n\n private updateCanvasSize(): void {\n if (!this.data) {\n return;\n }\n\n const element = this.querySelector('.sticky-note');\n if (element) {\n const rect = element.getBoundingClientRect();\n getStore()\n .getState()\n .expandCanvas(\n this.data.position.left + rect.width,\n this.data.position.top + rect.height\n );\n }\n }\n\n private handleTitleBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newTitle = target.textContent || '';\n\n if (this.data && newTitle !== this.data.title) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n title: newTitle\n });\n }\n this.requestUpdate();\n }\n\n private handleBodyBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newBody = target.innerText || '';\n\n if (this.data && newBody !== this.data.body) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n body: newBody\n });\n }\n this.requestUpdate();\n }\n\n private handleContentMouseDown(event: MouseEvent): void {\n // If this sticky note is selected, don't stop propagation\n // so that group dragging can work\n if (this.selected) {\n return;\n }\n // Otherwise, stop propagation to enable editing\n event.stopPropagation();\n }\n\n private handleTitleKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleBodyKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleColorPickerMouseEnter(): void {\n this.colorPickerExpanded = true;\n }\n\n private handleColorPickerMouseLeave(): void {\n this.colorPickerExpanded = false;\n }\n\n private handleColorOptionClick(\n event: MouseEvent,\n color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'\n ): void {\n event.stopPropagation();\n\n if (this.data && color !== this.data.color) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n color: color\n });\n }\n\n this.colorPickerExpanded = false;\n this.requestUpdate();\n }\n\n public render(): TemplateResult {\n if (!this.data) {\n return html`<div class=\"sticky-note\" style=\"display: none;\"></div>`;\n }\n\n const style = `left: ${this.data.position.left}px; top: ${this.data.position.top}px;`;\n\n return html`\n <div\n class=\"sticky-note ${this.data.color} ${this.dragging\n ? 'dragging'\n : ''}\"\n style=\"${style}\"\n data-uuid=\"${this.uuid}\"\n >\n <div class=\"sticky-title-container\">\n <temba-icon name=\"drag\" class=\"drag-handle\"></temba-icon>\n <div\n class=\"sticky-title\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleTitleBlur}\"\n @keydown=\"${this.handleTitleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.title}\"\n ></div>\n </div>\n <div class=\"sticky-body-container\">\n <div\n class=\"sticky-body\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleBodyBlur}\"\n @keydown=\"${this.handleBodyKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.body}\"\n ></div>\n ${!this.isTranslating\n ? html`<div class=\"edit-icon\" title=\"Edit note\"></div>`\n : ''}\n\n <!-- Color picker -->\n <div\n class=\"color-picker\"\n @mouseenter=\"${this.handleColorPickerMouseEnter}\"\n @mouseleave=\"${this.handleColorPickerMouseLeave}\"\n >\n <div\n class=\"color-options ${this.colorPickerExpanded\n ? 'expanded'\n : ''}\"\n >\n <div\n class=\"color-option yellow\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'yellow')}\"\n ></div>\n <div\n class=\"color-option blue\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'blue')}\"\n ></div>\n <div\n class=\"color-option pink\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'pink')}\"\n ></div>\n <div\n class=\"color-option green\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'green')}\"\n ></div>\n <div\n class=\"color-option gray\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'gray')}\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n}\n"]}
@@ -0,0 +1,112 @@
1
+ import { html } from 'lit-html';
2
+ // SVG paths for play and pause icons
3
+ const PLAY_SVG = html `<svg
4
+ viewBox="0 0 24 24"
5
+ width="16"
6
+ height="16"
7
+ fill="currentColor"
8
+ >
9
+ <polygon points="6,3 20,12 6,21" />
10
+ </svg>`;
11
+ // Track active audio so only one plays at a time
12
+ let activeAudio = null;
13
+ let activeContainer = null;
14
+ function stopActive() {
15
+ if (activeAudio) {
16
+ activeAudio.pause();
17
+ activeAudio.currentTime = 0;
18
+ if (activeContainer) {
19
+ resetPlayer(activeContainer);
20
+ }
21
+ activeAudio = null;
22
+ activeContainer = null;
23
+ }
24
+ }
25
+ function resetPlayer(container) {
26
+ const btn = container.querySelector('.audio-play-btn');
27
+ const progress = container.querySelector('.audio-progress');
28
+ if (btn)
29
+ btn.innerHTML =
30
+ '<svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><polygon points="6,3 20,12 6,21"/></svg>';
31
+ if (progress)
32
+ progress.style.width = '0%';
33
+ }
34
+ function handlePlayClick(e) {
35
+ e.stopPropagation();
36
+ e.preventDefault();
37
+ const container = e.currentTarget.closest('.audio-player');
38
+ if (!container)
39
+ return;
40
+ const url = container.dataset.url;
41
+ if (!url)
42
+ return;
43
+ const btn = container.querySelector('.audio-play-btn');
44
+ const progress = container.querySelector('.audio-progress');
45
+ // If this is already playing, pause it
46
+ if (activeAudio && activeContainer === container && !activeAudio.paused) {
47
+ activeAudio.pause();
48
+ btn.innerHTML =
49
+ '<svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><polygon points="6,3 20,12 6,21"/></svg>';
50
+ return;
51
+ }
52
+ // Stop any other playing audio
53
+ stopActive();
54
+ const audio = new Audio(url);
55
+ activeAudio = audio;
56
+ activeContainer = container;
57
+ btn.innerHTML =
58
+ '<svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><rect x="5" y="3" width="4" height="18"/><rect x="15" y="3" width="4" height="18"/></svg>';
59
+ audio.addEventListener('timeupdate', () => {
60
+ if (audio.duration && progress) {
61
+ const pct = (audio.currentTime / audio.duration) * 100;
62
+ progress.style.width = `${pct}%`;
63
+ }
64
+ });
65
+ audio.addEventListener('ended', () => {
66
+ resetPlayer(container);
67
+ activeAudio = null;
68
+ activeContainer = null;
69
+ });
70
+ audio.addEventListener('error', () => {
71
+ resetPlayer(container);
72
+ activeAudio = null;
73
+ activeContainer = null;
74
+ });
75
+ audio.play().catch(() => {
76
+ resetPlayer(container);
77
+ activeAudio = null;
78
+ activeContainer = null;
79
+ });
80
+ }
81
+ /**
82
+ * Renders an inline audio player with play/pause button and progress bar.
83
+ * Used on canvas nodes for play_audio and say_msg actions.
84
+ */
85
+ export function renderAudioPlayer(audioUrl) {
86
+ return html `
87
+ <div
88
+ class="audio-player"
89
+ data-url="${audioUrl}"
90
+ style="display: flex; align-items: center; gap: 0.4em; cursor: default;"
91
+ @mousedown=${(e) => e.stopPropagation()}
92
+ @mouseup=${(e) => e.stopPropagation()}
93
+ >
94
+ <div
95
+ class="audio-play-btn"
96
+ @click=${handlePlayClick}
97
+ style="cursor: pointer; color: #666; display: flex; align-items: center; flex-shrink: 0;"
98
+ >
99
+ ${PLAY_SVG}
100
+ </div>
101
+ <div
102
+ style="flex: 1; height: 4px; background: #e0e0e0; border-radius: 2px; overflow: hidden; min-width: 40px;"
103
+ >
104
+ <div
105
+ class="audio-progress"
106
+ style="width: 0%; height: 100%; background: var(--color-primary, #2387ca); border-radius: 2px; transition: width 0.2s linear;"
107
+ ></div>
108
+ </div>
109
+ </div>
110
+ `;
111
+ }
112
+ //# sourceMappingURL=audio-player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player.js","sourceRoot":"","sources":["../../../../src/flow/actions/audio-player.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,UAAU,CAAC;AAEhD,qCAAqC;AACrC,MAAM,QAAQ,GAAG,IAAI,CAAA;;;;;;;OAOd,CAAC;AAER,iDAAiD;AACjD,IAAI,WAAW,GAA4B,IAAI,CAAC;AAChD,IAAI,eAAe,GAAuB,IAAI,CAAC;AAE/C,SAAS,UAAU;IACjB,IAAI,WAAW,EAAE,CAAC;QAChB,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,WAAW,CAAC,WAAW,GAAG,CAAC,CAAC;QAC5B,IAAI,eAAe,EAAE,CAAC;YACpB,WAAW,CAAC,eAAe,CAAC,CAAC;QAC/B,CAAC;QACD,WAAW,GAAG,IAAI,CAAC;QACnB,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,SAAsB;IACzC,MAAM,GAAG,GAAG,SAAS,CAAC,aAAa,CAAC,iBAAiB,CAAgB,CAAC;IACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,aAAa,CAAC,iBAAiB,CAAgB,CAAC;IAC3E,IAAI,GAAG;QACL,GAAG,CAAC,SAAS;YACX,8GAA8G,CAAC;IACnH,IAAI,QAAQ;QAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;AAC5C,CAAC;AAED,SAAS,eAAe,CAAC,CAAa;IACpC,CAAC,CAAC,eAAe,EAAE,CAAC;IACpB,CAAC,CAAC,cAAc,EAAE,CAAC;IAEnB,MAAM,SAAS,GAAI,CAAC,CAAC,aAA6B,CAAC,OAAO,CACxD,eAAe,CACD,CAAC;IACjB,IAAI,CAAC,SAAS;QAAE,OAAO;IAEvB,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,MAAM,GAAG,GAAG,SAAS,CAAC,aAAa,CAAC,iBAAiB,CAAgB,CAAC;IACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,aAAa,CAAC,iBAAiB,CAAgB,CAAC;IAE3E,uCAAuC;IACvC,IAAI,WAAW,IAAI,eAAe,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QACxE,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,GAAG,CAAC,SAAS;YACX,8GAA8G,CAAC;QACjH,OAAO;IACT,CAAC;IAED,+BAA+B;IAC/B,UAAU,EAAE,CAAC;IAEb,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,WAAW,GAAG,KAAK,CAAC;IACpB,eAAe,GAAG,SAAS,CAAC;IAE5B,GAAG,CAAC,SAAS;QACX,+JAA+J,CAAC;IAElK,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,GAAG,EAAE;QACxC,IAAI,KAAK,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;YACvD,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;QACnC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QACnC,WAAW,CAAC,SAAS,CAAC,CAAC;QACvB,WAAW,GAAG,IAAI,CAAC;QACnB,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QACnC,WAAW,CAAC,SAAS,CAAC,CAAC;QACvB,WAAW,GAAG,IAAI,CAAC;QACnB,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;QACtB,WAAW,CAAC,SAAS,CAAC,CAAC;QACvB,WAAW,GAAG,IAAI,CAAC;QACnB,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,IAAI,CAAA;;;kBAGK,QAAQ;;mBAEP,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE;iBACxC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE;;;;iBAItC,eAAe;;;UAGtB,QAAQ;;;;;;;;;;;GAWf,CAAC;AACJ,CAAC","sourcesContent":["import { html, TemplateResult } from 'lit-html';\n\n// SVG paths for play and pause icons\nconst PLAY_SVG = html`<svg\n viewBox=\"0 0 24 24\"\n width=\"16\"\n height=\"16\"\n fill=\"currentColor\"\n>\n <polygon points=\"6,3 20,12 6,21\" />\n</svg>`;\n\n// Track active audio so only one plays at a time\nlet activeAudio: HTMLAudioElement | null = null;\nlet activeContainer: HTMLElement | null = null;\n\nfunction stopActive() {\n if (activeAudio) {\n activeAudio.pause();\n activeAudio.currentTime = 0;\n if (activeContainer) {\n resetPlayer(activeContainer);\n }\n activeAudio = null;\n activeContainer = null;\n }\n}\n\nfunction resetPlayer(container: HTMLElement) {\n const btn = container.querySelector('.audio-play-btn') as HTMLElement;\n const progress = container.querySelector('.audio-progress') as HTMLElement;\n if (btn)\n btn.innerHTML =\n '<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"currentColor\"><polygon points=\"6,3 20,12 6,21\"/></svg>';\n if (progress) progress.style.width = '0%';\n}\n\nfunction handlePlayClick(e: MouseEvent) {\n e.stopPropagation();\n e.preventDefault();\n\n const container = (e.currentTarget as HTMLElement).closest(\n '.audio-player'\n ) as HTMLElement;\n if (!container) return;\n\n const url = container.dataset.url;\n if (!url) return;\n\n const btn = container.querySelector('.audio-play-btn') as HTMLElement;\n const progress = container.querySelector('.audio-progress') as HTMLElement;\n\n // If this is already playing, pause it\n if (activeAudio && activeContainer === container && !activeAudio.paused) {\n activeAudio.pause();\n btn.innerHTML =\n '<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"currentColor\"><polygon points=\"6,3 20,12 6,21\"/></svg>';\n return;\n }\n\n // Stop any other playing audio\n stopActive();\n\n const audio = new Audio(url);\n activeAudio = audio;\n activeContainer = container;\n\n btn.innerHTML =\n '<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"currentColor\"><rect x=\"5\" y=\"3\" width=\"4\" height=\"18\"/><rect x=\"15\" y=\"3\" width=\"4\" height=\"18\"/></svg>';\n\n audio.addEventListener('timeupdate', () => {\n if (audio.duration && progress) {\n const pct = (audio.currentTime / audio.duration) * 100;\n progress.style.width = `${pct}%`;\n }\n });\n\n audio.addEventListener('ended', () => {\n resetPlayer(container);\n activeAudio = null;\n activeContainer = null;\n });\n\n audio.addEventListener('error', () => {\n resetPlayer(container);\n activeAudio = null;\n activeContainer = null;\n });\n\n audio.play().catch(() => {\n resetPlayer(container);\n activeAudio = null;\n activeContainer = null;\n });\n}\n\n/**\n * Renders an inline audio player with play/pause button and progress bar.\n * Used on canvas nodes for play_audio and say_msg actions.\n */\nexport function renderAudioPlayer(audioUrl: string): TemplateResult {\n return html`\n <div\n class=\"audio-player\"\n data-url=\"${audioUrl}\"\n style=\"display: flex; align-items: center; gap: 0.4em; cursor: default;\"\n @mousedown=${(e: MouseEvent) => e.stopPropagation()}\n @mouseup=${(e: MouseEvent) => e.stopPropagation()}\n >\n <div\n class=\"audio-play-btn\"\n @click=${handlePlayClick}\n style=\"cursor: pointer; color: #666; display: flex; align-items: center; flex-shrink: 0;\"\n >\n ${PLAY_SVG}\n </div>\n <div\n style=\"flex: 1; height: 4px; background: #e0e0e0; border-radius: 2px; overflow: hidden; min-width: 40px;\"\n >\n <div\n class=\"audio-progress\"\n style=\"width: 0%; height: 100%; background: var(--color-primary, #2387ca); border-radius: 2px; transition: width 0.2s linear;\"\n ></div>\n </div>\n </div>\n `;\n}\n"]}
@@ -0,0 +1,43 @@
1
+ import { html } from 'lit-html';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
+ import { renderNamedObjects } from '../utils';
4
+ export const enter_flow = {
5
+ name: 'Enter a Flow',
6
+ group: ACTION_GROUPS.trigger,
7
+ hideFromActions: true,
8
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
9
+ render: (_node, action) => {
10
+ return html `${renderNamedObjects([action.flow], 'flow')}`;
11
+ },
12
+ toFormData: (action) => {
13
+ return {
14
+ uuid: action.uuid,
15
+ flow: action.flow ? [action.flow] : []
16
+ };
17
+ },
18
+ form: {
19
+ flow: {
20
+ type: 'select',
21
+ required: true,
22
+ placeholder: 'Select a flow...',
23
+ helpText: 'The contact will enter this flow and not return',
24
+ endpoint: '/api/v2/flows.json',
25
+ valueKey: 'uuid',
26
+ nameKey: 'name'
27
+ }
28
+ },
29
+ layout: ['flow'],
30
+ fromFormData: (formData) => {
31
+ const selected = formData.flow[0];
32
+ return {
33
+ uuid: formData.uuid,
34
+ type: 'enter_flow',
35
+ terminal: true,
36
+ flow: {
37
+ uuid: selected.uuid || selected.value,
38
+ name: selected.name
39
+ }
40
+ };
41
+ }
42
+ };
43
+ //# sourceMappingURL=enter_flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enter_flow.js","sourceRoot":"","sources":["../../../../src/flow/actions/enter_flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,aAAa,CAAC,OAAO;IAC5B,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAiB,EAAE,EAAE;QACzC,OAAO,IAAI,CAAA,GAAG,kBAAkB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;IAC5D,CAAC;IACD,UAAU,EAAE,CAAC,MAAiB,EAAE,EAAE;QAChC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;SACvC,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,kBAAkB;YAC/B,QAAQ,EAAE,iDAAiD;YAC3D,QAAQ,EAAE,oBAAoB;YAC9B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;SAChB;KACF;IACD,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,YAAY,EAAE,CAAC,QAAa,EAAa,EAAE;QACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK;gBACrC,IAAI,EAAE,QAAQ,CAAC,IAAI;aACpB;SACF,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';\nimport { Node, EnterFlow } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const enter_flow: ActionConfig = {\n name: 'Enter a Flow',\n group: ACTION_GROUPS.trigger,\n hideFromActions: true,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: EnterFlow) => {\n return html`${renderNamedObjects([action.flow], 'flow')}`;\n },\n toFormData: (action: EnterFlow) => {\n return {\n uuid: action.uuid,\n flow: action.flow ? [action.flow] : []\n };\n },\n form: {\n flow: {\n type: 'select',\n required: true,\n placeholder: 'Select a flow...',\n helpText: 'The contact will enter this flow and not return',\n endpoint: '/api/v2/flows.json',\n valueKey: 'uuid',\n nameKey: 'name'\n }\n },\n layout: ['flow'],\n fromFormData: (formData: any): EnterFlow => {\n const selected = formData.flow[0];\n return {\n uuid: formData.uuid,\n type: 'enter_flow',\n terminal: true,\n flow: {\n uuid: selected.uuid || selected.value,\n name: selected.name\n }\n };\n }\n};\n"]}