@nyaruka/temba-components 0.138.4 → 0.139.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 (69) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/locales/es.js +5 -5
  3. package/dist/locales/es.js.map +1 -1
  4. package/dist/locales/fr.js +5 -5
  5. package/dist/locales/fr.js.map +1 -1
  6. package/dist/locales/locale-codes.js +2 -11
  7. package/dist/locales/locale-codes.js.map +1 -1
  8. package/dist/locales/pt.js +5 -5
  9. package/dist/locales/pt.js.map +1 -1
  10. package/dist/temba-components.js +816 -852
  11. package/dist/temba-components.js.map +1 -1
  12. package/out-tsc/src/display/FloatingTab.js +23 -30
  13. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  14. package/out-tsc/src/flow/CanvasMenu.js +5 -3
  15. package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
  16. package/out-tsc/src/flow/CanvasNode.js +6 -7
  17. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  18. package/out-tsc/src/flow/Editor.js +152 -235
  19. package/out-tsc/src/flow/Editor.js.map +1 -1
  20. package/out-tsc/src/flow/Plumber.js +757 -403
  21. package/out-tsc/src/flow/Plumber.js.map +1 -1
  22. package/out-tsc/src/flow/utils.js +138 -66
  23. package/out-tsc/src/flow/utils.js.map +1 -1
  24. package/out-tsc/src/interfaces.js +1 -0
  25. package/out-tsc/src/interfaces.js.map +1 -1
  26. package/out-tsc/src/list/TicketList.js +4 -1
  27. package/out-tsc/src/list/TicketList.js.map +1 -1
  28. package/out-tsc/src/live/ContactChat.js +18 -1
  29. package/out-tsc/src/live/ContactChat.js.map +1 -1
  30. package/out-tsc/src/locales/es.js +5 -5
  31. package/out-tsc/src/locales/es.js.map +1 -1
  32. package/out-tsc/src/locales/fr.js +5 -5
  33. package/out-tsc/src/locales/fr.js.map +1 -1
  34. package/out-tsc/src/locales/locale-codes.js +2 -11
  35. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  36. package/out-tsc/src/locales/pt.js +5 -5
  37. package/out-tsc/src/locales/pt.js.map +1 -1
  38. package/out-tsc/src/simulator/Simulator.js +1 -0
  39. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  40. package/out-tsc/test/temba-floating-tab.test.js +4 -6
  41. package/out-tsc/test/temba-floating-tab.test.js.map +1 -1
  42. package/out-tsc/test/temba-flow-collision.test.js +221 -223
  43. package/out-tsc/test/temba-flow-collision.test.js.map +1 -1
  44. package/out-tsc/test/temba-flow-editor.test.js +0 -2
  45. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  46. package/out-tsc/test/temba-flow-plumber-connections.test.js +83 -84
  47. package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
  48. package/out-tsc/test/temba-flow-plumber.test.js +102 -93
  49. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  50. package/package.json +1 -1
  51. package/src/display/FloatingTab.ts +22 -31
  52. package/src/flow/CanvasMenu.ts +8 -3
  53. package/src/flow/CanvasNode.ts +6 -7
  54. package/src/flow/Editor.ts +184 -279
  55. package/src/flow/Plumber.ts +1011 -457
  56. package/src/flow/utils.ts +162 -84
  57. package/src/interfaces.ts +2 -1
  58. package/src/list/TicketList.ts +4 -1
  59. package/src/live/ContactChat.ts +19 -1
  60. package/src/locales/es.ts +13 -18
  61. package/src/locales/fr.ts +13 -18
  62. package/src/locales/locale-codes.ts +2 -11
  63. package/src/locales/pt.ts +13 -18
  64. package/src/simulator/Simulator.ts +1 -0
  65. package/test/temba-floating-tab.test.ts +4 -6
  66. package/test/temba-flow-collision.test.ts +225 -303
  67. package/test/temba-flow-editor.test.ts +0 -2
  68. package/test/temba-flow-plumber-connections.test.ts +97 -97
  69. package/test/temba-flow-plumber.test.ts +116 -103
@@ -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"]}
@@ -1,4 +1,9 @@
1
1
  import { html } from 'lit-html';
2
+ const GRID_SIZE = 20;
3
+ export function snapToGrid(value) {
4
+ const snapped = Math.round(value / GRID_SIZE) * GRID_SIZE;
5
+ return Math.max(snapped, 0);
6
+ }
2
7
  /**
3
8
  * Renders a single line item with optional icon
4
9
  */
@@ -206,85 +211,152 @@ export const nodesOverlap = (bounds1, bounds2) => {
206
211
  export const detectCollisions = (targetBounds, allBounds) => {
207
212
  return allBounds.filter((bounds) => bounds.uuid !== targetBounds.uuid && nodesOverlap(targetBounds, bounds));
208
213
  };
214
+ const DIRECTIONS = ['down', 'up', 'right', 'left'];
209
215
  /**
210
- * Calculates the new positions needed to resolve all collisions
211
- * Nodes are only moved downward, never up, left, or right
212
- * Returns a map of node UUIDs to their new positions
216
+ * Creates a new NodeBounds at a different position
213
217
  */
214
- export const calculateReflowPositions = (movedNodeUuid, movedNodeBounds, allBounds, droppedBelowMidpoint = false) => {
218
+ const makeBoundsAt = (original, left, top) => ({
219
+ ...original,
220
+ left,
221
+ top,
222
+ right: left + original.width,
223
+ bottom: top + original.height
224
+ });
225
+ /**
226
+ * Computes the minimum position needed to clear all fixed nodes in a given direction.
227
+ * Returns null if the direction is not viable (e.g., would require negative coordinates
228
+ * and still overlap).
229
+ */
230
+ const computeDirectionalClearance = (collider, fixedNodes, direction) => {
231
+ switch (direction) {
232
+ case 'down': {
233
+ const maxBottom = Math.max(...fixedNodes.map((f) => f.bottom));
234
+ const newTop = snapToGrid(maxBottom + MIN_NODE_SPACING);
235
+ return { left: collider.left, top: newTop };
236
+ }
237
+ case 'up': {
238
+ const minTop = Math.min(...fixedNodes.map((f) => f.top));
239
+ const newTop = snapToGrid(minTop - collider.height - MIN_NODE_SPACING);
240
+ if (newTop < 0)
241
+ return { left: collider.left, top: 0 };
242
+ return { left: collider.left, top: newTop };
243
+ }
244
+ case 'right': {
245
+ const maxRight = Math.max(...fixedNodes.map((f) => f.right));
246
+ const newLeft = snapToGrid(maxRight + MIN_NODE_SPACING);
247
+ return { left: newLeft, top: collider.top };
248
+ }
249
+ case 'left': {
250
+ const minLeft = Math.min(...fixedNodes.map((f) => f.left));
251
+ const newLeft = snapToGrid(minLeft - collider.width - MIN_NODE_SPACING);
252
+ if (newLeft < 0)
253
+ return { left: 0, top: collider.top };
254
+ return { left: newLeft, top: collider.top };
255
+ }
256
+ }
257
+ };
258
+ /**
259
+ * Calculates new positions to resolve all collisions using multi-directional reflow.
260
+ *
261
+ * Sacred nodes (the ones just dropped/created) keep their positions. All other
262
+ * colliding nodes are moved in whichever direction requires the least displacement
263
+ * and causes the fewest cascading collisions.
264
+ */
265
+ export const calculateReflowPositions = (sacredNodeUuids, allBounds) => {
215
266
  const newPositions = new Map();
216
- // If dropped below midpoint, the moved node should move down instead
217
- if (droppedBelowMidpoint) {
218
- // Find all nodes that collide with the moved node
219
- const collisions = detectCollisions(movedNodeBounds, allBounds);
220
- if (collisions.length > 0) {
221
- // Find the highest bottom position of all colliding nodes
222
- const maxBottom = Math.max(...collisions.map((b) => b.bottom));
223
- // Move the dropped node below all colliding nodes
224
- const newTop = maxBottom + MIN_NODE_SPACING;
225
- newPositions.set(movedNodeUuid, {
226
- left: movedNodeBounds.left,
227
- top: newTop
228
- });
229
- // Update the moved node bounds for further collision checks
230
- movedNodeBounds = {
231
- ...movedNodeBounds,
232
- top: newTop,
233
- bottom: newTop + movedNodeBounds.height
234
- };
267
+ const sacredSet = new Set(sacredNodeUuids);
268
+ // Mutable map of current bounds, updated as collisions are resolved
269
+ const currentBounds = new Map();
270
+ for (const b of allBounds) {
271
+ currentBounds.set(b.uuid, { ...b });
272
+ }
273
+ // Seed the queue with non-sacred nodes that overlap any sacred node
274
+ const queue = [];
275
+ const inQueue = new Set();
276
+ for (const sacredUuid of sacredSet) {
277
+ const sacred = currentBounds.get(sacredUuid);
278
+ if (!sacred)
279
+ continue;
280
+ for (const [uuid, bounds] of currentBounds) {
281
+ if (sacredSet.has(uuid) || inQueue.has(uuid))
282
+ continue;
283
+ if (nodesOverlap(sacred, bounds)) {
284
+ queue.push(uuid);
285
+ inQueue.add(uuid);
286
+ }
235
287
  }
236
288
  }
237
- // Now check for any remaining collisions and move other nodes down
238
- const processedNodes = new Set();
239
- processedNodes.add(movedNodeUuid);
240
- // Keep checking for collisions until none remain
241
- let hasCollisions = true;
289
+ const resolved = new Set();
242
290
  let iterations = 0;
243
- const maxIterations = 100; // Prevent infinite loops
244
- while (hasCollisions && iterations < maxIterations) {
245
- hasCollisions = false;
291
+ const maxIterations = 200;
292
+ while (queue.length > 0 && iterations < maxIterations) {
246
293
  iterations++;
247
- // Check all nodes for collisions
248
- for (const bounds of allBounds) {
249
- if (processedNodes.has(bounds.uuid)) {
294
+ const uuid = queue.shift();
295
+ if (resolved.has(uuid))
296
+ continue;
297
+ const collider = currentBounds.get(uuid);
298
+ // Find all fixed nodes (sacred + already-resolved) that overlap this node
299
+ const fixedOverlaps = [];
300
+ for (const [otherUuid, otherBounds] of currentBounds) {
301
+ if (otherUuid === uuid)
250
302
  continue;
303
+ if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) {
304
+ if (nodesOverlap(collider, otherBounds)) {
305
+ fixedOverlaps.push(otherBounds);
306
+ }
251
307
  }
252
- // Use original bounds since we skip already processed nodes
253
- const currentBounds = bounds;
254
- // Check if this node collides with the moved node or any already repositioned nodes
255
- let collisionFound = false;
256
- let maxCollisionBottom = 0;
257
- // Check against moved node
258
- if (nodesOverlap(currentBounds, movedNodeBounds)) {
259
- collisionFound = true;
260
- maxCollisionBottom = Math.max(maxCollisionBottom, movedNodeBounds.bottom);
261
- }
262
- // Check against other repositioned nodes
263
- for (const [otherUuid, otherPosition] of newPositions.entries()) {
264
- if (otherUuid === bounds.uuid)
308
+ }
309
+ if (fixedOverlaps.length === 0)
310
+ continue;
311
+ // Try each direction, pick the one with least disruption
312
+ let bestPos = null;
313
+ let bestScore = Infinity;
314
+ for (const dir of DIRECTIONS) {
315
+ const candidate = computeDirectionalClearance(collider, fixedOverlaps, dir);
316
+ if (!candidate)
317
+ continue;
318
+ const candidateBounds = makeBoundsAt(collider, candidate.left, candidate.top);
319
+ // Verify no overlap with any sacred or resolved node
320
+ let stillOverlaps = false;
321
+ let cascadeCount = 0;
322
+ for (const [otherUuid, otherBounds] of currentBounds) {
323
+ if (otherUuid === uuid)
265
324
  continue;
266
- const otherBounds = allBounds.find((b) => b.uuid === otherUuid);
267
- if (!otherBounds)
325
+ if (!nodesOverlap(candidateBounds, otherBounds))
268
326
  continue;
269
- const otherUpdatedBounds = {
270
- ...otherBounds,
271
- top: otherPosition.top,
272
- bottom: otherPosition.top + otherBounds.height
273
- };
274
- if (nodesOverlap(currentBounds, otherUpdatedBounds)) {
275
- collisionFound = true;
276
- maxCollisionBottom = Math.max(maxCollisionBottom, otherUpdatedBounds.bottom);
327
+ if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) {
328
+ stillOverlaps = true;
329
+ break;
277
330
  }
331
+ cascadeCount++;
332
+ }
333
+ if (stillOverlaps)
334
+ continue;
335
+ const distance = Math.abs(candidate.left - collider.left) +
336
+ Math.abs(candidate.top - collider.top);
337
+ const score = cascadeCount * 10000 + distance;
338
+ if (score < bestScore) {
339
+ bestScore = score;
340
+ bestPos = candidate;
278
341
  }
279
- if (collisionFound) {
280
- // Move this node down below the collision
281
- const newTop = maxCollisionBottom + MIN_NODE_SPACING;
282
- newPositions.set(bounds.uuid, {
283
- left: bounds.left,
284
- top: newTop
285
- });
286
- hasCollisions = true;
287
- processedNodes.add(bounds.uuid);
342
+ }
343
+ if (bestPos) {
344
+ newPositions.set(uuid, { left: bestPos.left, top: bestPos.top });
345
+ const newBounds = makeBoundsAt(collider, bestPos.left, bestPos.top);
346
+ currentBounds.set(uuid, newBounds);
347
+ resolved.add(uuid);
348
+ // Enqueue any new cascading collisions
349
+ for (const [otherUuid, otherBounds] of currentBounds) {
350
+ if (otherUuid === uuid)
351
+ continue;
352
+ if (sacredSet.has(otherUuid) || resolved.has(otherUuid))
353
+ continue;
354
+ if (inQueue.has(otherUuid))
355
+ continue;
356
+ if (nodesOverlap(newBounds, otherBounds)) {
357
+ queue.push(otherUuid);
358
+ inQueue.add(otherUuid);
359
+ }
288
360
  }
289
361
  }
290
362
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/flow/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGhC;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,IAAa,EAAE,EAAE;IAC5D,OAAO,IAAI,CAAA;MACP,IAAI;QACJ,CAAC,CAAC,IAAI,CAAA,oBAAoB,IAAI,2CAA2C;QACzE,CAAC,CAAC,IAAI;;;;QAIJ,IAAI;;SAEH,CAAC;AACV,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAqB,EAAE,IAAa,EAAE,EAAE;IACzE,OAAO,gBAAgB,CACrB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EACjC,IAAI,CACL,CAAC;AACJ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAe,EAAE,IAAa,EAAE,EAAE;IACjE,MAAM,YAAY,GAAG,EAAE,CAAC;IACxB,MAAM,UAAU,GAAG,CAAC,CAAC;IAErB,kDAAkD;IAClD,MAAM,YAAY,GAChB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,mEAAmE;IACnE,IAAI,KAAK,CAAC,MAAM,GAAG,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC;QACjD,YAAY,CAAC,IAAI,CAAC,IAAI,CAAA;;;QAGlB,IAAI;YACJ,CAAC,CAAC,IAAI,CAAA,qDAAqD,CAAC,sBAAsB;YAClF,CAAC,CAAC,IAAI;sCACwB,cAAc;WACzC,CAAC,CAAC;IACX,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC;AASF,MAAM,CAAC,MAAM,OAAO,GAAa;IAC/B;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,cAAc;KACrB;IACD;QACE,MAAM,EAAE,UAAU;QAClB,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,iBAAiB;KACxB;IACD;QACE,MAAM,EAAE,UAAU;QAClB,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,aAAa;KACpB;IACD;QACE,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,cAAc;KACrB;IACD;QACE,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,YAAY;QAClB,gBAAgB,EAAE,IAAI;KACvB;IACD;QACE,MAAM,EAAE,UAAU;QAClB,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,aAAa;KACpB;IACD;QACE,MAAM,EAAE,OAAO;QACf,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,UAAU;KACjB;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,SAAS;KAChB;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,WAAW;KAClB;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,aAAa;KACpB;IACD;QACE,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,YAAY;KACnB;IACD;QACE,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,cAAc;KACrB;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,eAAe;QACrB,gBAAgB,EAAE,IAAI;KACvB;IACD;QACE,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,gBAAgB;QACtB,gBAAgB,EAAE,IAAI;KACvB;IACD;QACE,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,OAAO;KACd;IACD;QACE,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,YAAY;KACnB;IACD;QACE,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,YAAY;QAClB,gBAAgB,EAAE,IAAI;KACvB;IACD;QACE,MAAM,EAAE,YAAY;QACpB,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,eAAe;KACtB;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,aAAa;KACpB;CACF,CAAC;AAeF;;GAEG;AACH,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B;;;;GAIG;AACH,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,QAAgB,EAChB,QAAsB,EACtB,OAAqB,EACF,EAAE;IACrB,kEAAkE;IAClE,MAAM,WAAW,GACf,OAAO,IAAK,QAAQ,CAAC,aAAa,CAAC,QAAQ,QAAQ,IAAI,CAAiB,CAAC;IAE3E,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,qBAAqB,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAE3B,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,GAAG,EAAE,QAAQ,CAAC,GAAG;QACjB,KAAK,EAAE,QAAQ,CAAC,IAAI,GAAG,KAAK;QAC5B,MAAM,EAAE,QAAQ,CAAC,GAAG,GAAG,MAAM;QAC7B,KAAK;QACL,MAAM;KACP,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAmB,EACnB,OAAmB,EACV,EAAE;IACX,8DAA8D;IAC9D,MAAM,MAAM,GAAG,cAAc,CAAC;IAE9B,OAAO,CAAC,CACN,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,GAAG,MAAM;QACtC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK,GAAG,MAAM;QACtC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,GAAG,MAAM;QACtC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CACvC,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,YAAwB,EACxB,SAAuB,EACT,EAAE;IAChB,OAAO,SAAS,CAAC,MAAM,CACrB,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI,IAAI,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAC1E,CAAC;AACJ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,aAAqB,EACrB,eAA2B,EAC3B,SAAuB,EACvB,uBAAgC,KAAK,EACV,EAAE;IAC7B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAwB,CAAC;IAErD,qEAAqE;IACrE,IAAI,oBAAoB,EAAE,CAAC;QACzB,kDAAkD;QAClD,MAAM,UAAU,GAAG,gBAAgB,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;QAEhE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,0DAA0D;YAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAE/D,kDAAkD;YAClD,MAAM,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAAC;YAC5C,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE;gBAC9B,IAAI,EAAE,eAAe,CAAC,IAAI;gBAC1B,GAAG,EAAE,MAAM;aACZ,CAAC,CAAC;YAEH,4DAA4D;YAC5D,eAAe,GAAG;gBAChB,GAAG,eAAe;gBAClB,GAAG,EAAE,MAAM;gBACX,MAAM,EAAE,MAAM,GAAG,eAAe,CAAC,MAAM;aACxC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IACzC,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAElC,iDAAiD;IACjD,IAAI,aAAa,GAAG,IAAI,CAAC;IACzB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,aAAa,GAAG,GAAG,CAAC,CAAC,yBAAyB;IAEpD,OAAO,aAAa,IAAI,UAAU,GAAG,aAAa,EAAE,CAAC;QACnD,aAAa,GAAG,KAAK,CAAC;QACtB,UAAU,EAAE,CAAC;QAEb,iCAAiC;QACjC,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;YAC/B,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,SAAS;YACX,CAAC;YAED,4DAA4D;YAC5D,MAAM,aAAa,GAAG,MAAM,CAAC;YAE7B,oFAAoF;YACpF,IAAI,cAAc,GAAG,KAAK,CAAC;YAC3B,IAAI,kBAAkB,GAAG,CAAC,CAAC;YAE3B,2BAA2B;YAC3B,IAAI,YAAY,CAAC,aAAa,EAAE,eAAe,CAAC,EAAE,CAAC;gBACjD,cAAc,GAAG,IAAI,CAAC;gBACtB,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAC3B,kBAAkB,EAClB,eAAe,CAAC,MAAM,CACvB,CAAC;YACJ,CAAC;YAED,yCAAyC;YACzC,KAAK,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;gBAChE,IAAI,SAAS,KAAK,MAAM,CAAC,IAAI;oBAAE,SAAS;gBAExC,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;gBAChE,IAAI,CAAC,WAAW;oBAAE,SAAS;gBAE3B,MAAM,kBAAkB,GAAG;oBACzB,GAAG,WAAW;oBACd,GAAG,EAAE,aAAa,CAAC,GAAG;oBACtB,MAAM,EAAE,aAAa,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM;iBAC/C,CAAC;gBAEF,IAAI,YAAY,CAAC,aAAa,EAAE,kBAAkB,CAAC,EAAE,CAAC;oBACpD,cAAc,GAAG,IAAI,CAAC;oBACtB,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAC3B,kBAAkB,EAClB,kBAAkB,CAAC,MAAM,CAC1B,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,IAAI,cAAc,EAAE,CAAC;gBACnB,0CAA0C;gBAC1C,MAAM,MAAM,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;gBACrD,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE;oBAC5B,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,GAAG,EAAE,MAAM;iBACZ,CAAC,CAAC;gBACH,aAAa,GAAG,IAAI,CAAC;gBACrB,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { NamedObject, FlowPosition } from '../store/flow-definition';\n\n/**\n * Renders a single line item with optional icon\n */\nexport const renderLineItem = (name: string, icon?: string) => {\n return html`<div style=\"display:flex;items-align:center;\">\n ${icon\n ? html`<temba-icon name=${icon} style=\"margin-right:0.5em\"></temba-icon>`\n : null}\n <div\n style=\"white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 250px;\"\n >\n ${name}\n </div>\n </div>`;\n};\n\n/**\n * Renders a list of named objects with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderNamedObjects = (assets: NamedObject[], icon?: string) => {\n return renderStringList(\n assets.map((asset) => asset.name),\n icon\n );\n};\n\n/**\n * Renders a list of strings with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderStringList = (items: string[], icon?: string) => {\n const itemElements = [];\n const maxDisplay = 3;\n\n // Show up to 3 items, or all 4 if exactly 4 items\n const displayCount =\n items.length === 4 ? 4 : Math.min(maxDisplay, items.length);\n\n for (let i = 0; i < displayCount; i++) {\n const item = items[i];\n itemElements.push(renderLineItem(item, icon));\n }\n\n // Add \"+X more\" if there are more than 3 items (and not exactly 4)\n if (items.length > maxDisplay && items.length !== 4) {\n const remainingCount = items.length - maxDisplay;\n itemElements.push(html`<div\n style=\"display:flex;items-align:center;margin-top:0.2em;\"\n >\n ${icon\n ? html`<div style=\"margin-right:0.4em; width: 1em;\"></div>` // spacing placeholder\n : null}\n <div style=\"font-size:0.8em\">+${remainingCount} more</div>\n </div>`);\n }\n return itemElements;\n};\n\nexport interface Scheme {\n scheme: string;\n name: string;\n path: string;\n excludeFromSplit?: boolean;\n}\n\nexport const SCHEMES: Scheme[] = [\n {\n scheme: 'tel',\n name: 'SMS',\n path: 'Phone Number'\n },\n {\n scheme: 'whatsapp',\n name: 'WhatsApp',\n path: 'WhatsApp Number'\n },\n {\n scheme: 'facebook',\n name: 'Facebook',\n path: 'Facebook ID'\n },\n {\n scheme: 'instagram',\n name: 'Instagram',\n path: 'Instagram ID'\n },\n {\n scheme: 'twitterid',\n name: 'Twitter',\n path: 'Twitter ID',\n excludeFromSplit: true\n },\n {\n scheme: 'telegram',\n name: 'Telegram',\n path: 'Telegram ID'\n },\n {\n scheme: 'viber',\n name: 'Viber',\n path: 'Viber ID'\n },\n {\n scheme: 'line',\n name: 'Line',\n path: 'Line ID'\n },\n {\n scheme: 'wechat',\n name: 'WeChat',\n path: 'WeChat ID'\n },\n {\n scheme: 'fcm',\n name: 'Firebase',\n path: 'Firebase ID'\n },\n {\n scheme: 'jiochat',\n name: 'JioChat',\n path: 'JioChat ID'\n },\n {\n scheme: 'freshchat',\n name: 'Freshchat',\n path: 'Freshchat ID'\n },\n {\n scheme: 'mailto',\n name: 'Email',\n path: 'Email Address',\n excludeFromSplit: true\n },\n {\n scheme: 'twitter',\n name: 'Twitter',\n path: 'Twitter Handle',\n excludeFromSplit: true\n },\n {\n scheme: 'vk',\n name: 'VK',\n path: 'VK ID'\n },\n {\n scheme: 'discord',\n name: 'Discord',\n path: 'Discord ID'\n },\n {\n scheme: 'webchat',\n name: 'Webchat',\n path: 'Webchat ID',\n excludeFromSplit: true\n },\n {\n scheme: 'rocketchat',\n name: 'RocketChat',\n path: 'RocketChat ID'\n },\n {\n scheme: 'ext',\n name: 'External',\n path: 'External ID'\n }\n];\n\n/**\n * Represents the bounding box of a node on the canvas\n */\nexport interface NodeBounds {\n uuid: string;\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n}\n\n/**\n * Minimum vertical spacing between nodes (in pixels)\n */\nconst MIN_NODE_SPACING = 30;\n\n/**\n * Small buffer to avoid floating point precision issues in overlap detection (in pixels)\n * This prevents false positives when nodes are exactly adjacent (e.g., bottom of one node\n * at exactly the same position as top of another)\n */\nconst OVERLAP_BUFFER = 10;\n\n/**\n * Gets the bounding box for a node from the DOM\n *\n * @param nodeUuid - The UUID of the node\n * @param position - The current position of the node\n * @param element - Optional pre-fetched DOM element (recommended for performance when checking multiple nodes)\n * @returns NodeBounds object or null if element not found\n *\n * Note: When element is not provided, performs a DOM query which may impact performance\n * during bulk collision detection. Consider fetching elements beforehand when possible.\n */\nexport const getNodeBounds = (\n nodeUuid: string,\n position: FlowPosition,\n element?: HTMLElement\n): NodeBounds | null => {\n // If element is provided, use it; otherwise try to find it in DOM\n const nodeElement =\n element || (document.querySelector(`[id=\"${nodeUuid}\"]`) as HTMLElement);\n\n if (!nodeElement) {\n return null;\n }\n\n const rect = nodeElement.getBoundingClientRect();\n const width = rect.width;\n const height = rect.height;\n\n return {\n uuid: nodeUuid,\n left: position.left,\n top: position.top,\n right: position.left + width,\n bottom: position.top + height,\n width,\n height\n };\n};\n\n/**\n * Checks if two node bounding boxes overlap\n */\nexport const nodesOverlap = (\n bounds1: NodeBounds,\n bounds2: NodeBounds\n): boolean => {\n // Use a small buffer to avoid floating point precision issues\n const buffer = OVERLAP_BUFFER;\n\n return !(\n bounds1.right <= bounds2.left - buffer ||\n bounds1.left >= bounds2.right + buffer ||\n bounds1.bottom <= bounds2.top - buffer ||\n bounds1.top >= bounds2.bottom + buffer\n );\n};\n\n/**\n * Detects all collisions between a node and other nodes\n */\nexport const detectCollisions = (\n targetBounds: NodeBounds,\n allBounds: NodeBounds[]\n): NodeBounds[] => {\n return allBounds.filter(\n (bounds) =>\n bounds.uuid !== targetBounds.uuid && nodesOverlap(targetBounds, bounds)\n );\n};\n\n/**\n * Calculates the new positions needed to resolve all collisions\n * Nodes are only moved downward, never up, left, or right\n * Returns a map of node UUIDs to their new positions\n */\nexport const calculateReflowPositions = (\n movedNodeUuid: string,\n movedNodeBounds: NodeBounds,\n allBounds: NodeBounds[],\n droppedBelowMidpoint: boolean = false\n): Map<string, FlowPosition> => {\n const newPositions = new Map<string, FlowPosition>();\n\n // If dropped below midpoint, the moved node should move down instead\n if (droppedBelowMidpoint) {\n // Find all nodes that collide with the moved node\n const collisions = detectCollisions(movedNodeBounds, allBounds);\n\n if (collisions.length > 0) {\n // Find the highest bottom position of all colliding nodes\n const maxBottom = Math.max(...collisions.map((b) => b.bottom));\n\n // Move the dropped node below all colliding nodes\n const newTop = maxBottom + MIN_NODE_SPACING;\n newPositions.set(movedNodeUuid, {\n left: movedNodeBounds.left,\n top: newTop\n });\n\n // Update the moved node bounds for further collision checks\n movedNodeBounds = {\n ...movedNodeBounds,\n top: newTop,\n bottom: newTop + movedNodeBounds.height\n };\n }\n }\n\n // Now check for any remaining collisions and move other nodes down\n const processedNodes = new Set<string>();\n processedNodes.add(movedNodeUuid);\n\n // Keep checking for collisions until none remain\n let hasCollisions = true;\n let iterations = 0;\n const maxIterations = 100; // Prevent infinite loops\n\n while (hasCollisions && iterations < maxIterations) {\n hasCollisions = false;\n iterations++;\n\n // Check all nodes for collisions\n for (const bounds of allBounds) {\n if (processedNodes.has(bounds.uuid)) {\n continue;\n }\n\n // Use original bounds since we skip already processed nodes\n const currentBounds = bounds;\n\n // Check if this node collides with the moved node or any already repositioned nodes\n let collisionFound = false;\n let maxCollisionBottom = 0;\n\n // Check against moved node\n if (nodesOverlap(currentBounds, movedNodeBounds)) {\n collisionFound = true;\n maxCollisionBottom = Math.max(\n maxCollisionBottom,\n movedNodeBounds.bottom\n );\n }\n\n // Check against other repositioned nodes\n for (const [otherUuid, otherPosition] of newPositions.entries()) {\n if (otherUuid === bounds.uuid) continue;\n\n const otherBounds = allBounds.find((b) => b.uuid === otherUuid);\n if (!otherBounds) continue;\n\n const otherUpdatedBounds = {\n ...otherBounds,\n top: otherPosition.top,\n bottom: otherPosition.top + otherBounds.height\n };\n\n if (nodesOverlap(currentBounds, otherUpdatedBounds)) {\n collisionFound = true;\n maxCollisionBottom = Math.max(\n maxCollisionBottom,\n otherUpdatedBounds.bottom\n );\n }\n }\n\n if (collisionFound) {\n // Move this node down below the collision\n const newTop = maxCollisionBottom + MIN_NODE_SPACING;\n newPositions.set(bounds.uuid, {\n left: bounds.left,\n top: newTop\n });\n hasCollisions = true;\n processedNodes.add(bounds.uuid);\n }\n }\n }\n\n return newPositions;\n};\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/flow/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { NamedObject, FlowPosition } from '../store/flow-definition';\n\nconst GRID_SIZE = 20;\n\nexport function snapToGrid(value: number): number {\n const snapped = Math.round(value / GRID_SIZE) * GRID_SIZE;\n return Math.max(snapped, 0);\n}\n\n/**\n * Renders a single line item with optional icon\n */\nexport const renderLineItem = (name: string, icon?: string) => {\n return html`<div style=\"display:flex;items-align:center;\">\n ${icon\n ? html`<temba-icon name=${icon} style=\"margin-right:0.5em\"></temba-icon>`\n : null}\n <div\n style=\"white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 250px;\"\n >\n ${name}\n </div>\n </div>`;\n};\n\n/**\n * Renders a list of named objects with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderNamedObjects = (assets: NamedObject[], icon?: string) => {\n return renderStringList(\n assets.map((asset) => asset.name),\n icon\n );\n};\n\n/**\n * Renders a list of strings with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderStringList = (items: string[], icon?: string) => {\n const itemElements = [];\n const maxDisplay = 3;\n\n // Show up to 3 items, or all 4 if exactly 4 items\n const displayCount =\n items.length === 4 ? 4 : Math.min(maxDisplay, items.length);\n\n for (let i = 0; i < displayCount; i++) {\n const item = items[i];\n itemElements.push(renderLineItem(item, icon));\n }\n\n // Add \"+X more\" if there are more than 3 items (and not exactly 4)\n if (items.length > maxDisplay && items.length !== 4) {\n const remainingCount = items.length - maxDisplay;\n itemElements.push(html`<div\n style=\"display:flex;items-align:center;margin-top:0.2em;\"\n >\n ${icon\n ? html`<div style=\"margin-right:0.4em; width: 1em;\"></div>` // spacing placeholder\n : null}\n <div style=\"font-size:0.8em\">+${remainingCount} more</div>\n </div>`);\n }\n return itemElements;\n};\n\nexport interface Scheme {\n scheme: string;\n name: string;\n path: string;\n excludeFromSplit?: boolean;\n}\n\nexport const SCHEMES: Scheme[] = [\n {\n scheme: 'tel',\n name: 'SMS',\n path: 'Phone Number'\n },\n {\n scheme: 'whatsapp',\n name: 'WhatsApp',\n path: 'WhatsApp Number'\n },\n {\n scheme: 'facebook',\n name: 'Facebook',\n path: 'Facebook ID'\n },\n {\n scheme: 'instagram',\n name: 'Instagram',\n path: 'Instagram ID'\n },\n {\n scheme: 'twitterid',\n name: 'Twitter',\n path: 'Twitter ID',\n excludeFromSplit: true\n },\n {\n scheme: 'telegram',\n name: 'Telegram',\n path: 'Telegram ID'\n },\n {\n scheme: 'viber',\n name: 'Viber',\n path: 'Viber ID'\n },\n {\n scheme: 'line',\n name: 'Line',\n path: 'Line ID'\n },\n {\n scheme: 'wechat',\n name: 'WeChat',\n path: 'WeChat ID'\n },\n {\n scheme: 'fcm',\n name: 'Firebase',\n path: 'Firebase ID'\n },\n {\n scheme: 'jiochat',\n name: 'JioChat',\n path: 'JioChat ID'\n },\n {\n scheme: 'freshchat',\n name: 'Freshchat',\n path: 'Freshchat ID'\n },\n {\n scheme: 'mailto',\n name: 'Email',\n path: 'Email Address',\n excludeFromSplit: true\n },\n {\n scheme: 'twitter',\n name: 'Twitter',\n path: 'Twitter Handle',\n excludeFromSplit: true\n },\n {\n scheme: 'vk',\n name: 'VK',\n path: 'VK ID'\n },\n {\n scheme: 'discord',\n name: 'Discord',\n path: 'Discord ID'\n },\n {\n scheme: 'webchat',\n name: 'Webchat',\n path: 'Webchat ID',\n excludeFromSplit: true\n },\n {\n scheme: 'rocketchat',\n name: 'RocketChat',\n path: 'RocketChat ID'\n },\n {\n scheme: 'ext',\n name: 'External',\n path: 'External ID'\n }\n];\n\n/**\n * Represents the bounding box of a node on the canvas\n */\nexport interface NodeBounds {\n uuid: string;\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n}\n\n/**\n * Minimum vertical spacing between nodes (in pixels)\n */\nconst MIN_NODE_SPACING = 30;\n\n/**\n * Small buffer to avoid floating point precision issues in overlap detection (in pixels)\n * This prevents false positives when nodes are exactly adjacent (e.g., bottom of one node\n * at exactly the same position as top of another)\n */\nconst OVERLAP_BUFFER = 10;\n\n/**\n * Gets the bounding box for a node from the DOM\n *\n * @param nodeUuid - The UUID of the node\n * @param position - The current position of the node\n * @param element - Optional pre-fetched DOM element (recommended for performance when checking multiple nodes)\n * @returns NodeBounds object or null if element not found\n *\n * Note: When element is not provided, performs a DOM query which may impact performance\n * during bulk collision detection. Consider fetching elements beforehand when possible.\n */\nexport const getNodeBounds = (\n nodeUuid: string,\n position: FlowPosition,\n element?: HTMLElement\n): NodeBounds | null => {\n // If element is provided, use it; otherwise try to find it in DOM\n const nodeElement =\n element || (document.querySelector(`[id=\"${nodeUuid}\"]`) as HTMLElement);\n\n if (!nodeElement) {\n return null;\n }\n\n const rect = nodeElement.getBoundingClientRect();\n const width = rect.width;\n const height = rect.height;\n\n return {\n uuid: nodeUuid,\n left: position.left,\n top: position.top,\n right: position.left + width,\n bottom: position.top + height,\n width,\n height\n };\n};\n\n/**\n * Checks if two node bounding boxes overlap\n */\nexport const nodesOverlap = (\n bounds1: NodeBounds,\n bounds2: NodeBounds\n): boolean => {\n // Use a small buffer to avoid floating point precision issues\n const buffer = OVERLAP_BUFFER;\n\n return !(\n bounds1.right <= bounds2.left - buffer ||\n bounds1.left >= bounds2.right + buffer ||\n bounds1.bottom <= bounds2.top - buffer ||\n bounds1.top >= bounds2.bottom + buffer\n );\n};\n\n/**\n * Detects all collisions between a node and other nodes\n */\nexport const detectCollisions = (\n targetBounds: NodeBounds,\n allBounds: NodeBounds[]\n): NodeBounds[] => {\n return allBounds.filter(\n (bounds) =>\n bounds.uuid !== targetBounds.uuid && nodesOverlap(targetBounds, bounds)\n );\n};\n\ntype Direction = 'down' | 'up' | 'right' | 'left';\n\nconst DIRECTIONS: Direction[] = ['down', 'up', 'right', 'left'];\n\n/**\n * Creates a new NodeBounds at a different position\n */\nconst makeBoundsAt = (\n original: NodeBounds,\n left: number,\n top: number\n): NodeBounds => ({\n ...original,\n left,\n top,\n right: left + original.width,\n bottom: top + original.height\n});\n\n/**\n * Computes the minimum position needed to clear all fixed nodes in a given direction.\n * Returns null if the direction is not viable (e.g., would require negative coordinates\n * and still overlap).\n */\nconst computeDirectionalClearance = (\n collider: NodeBounds,\n fixedNodes: NodeBounds[],\n direction: Direction\n): { left: number; top: number } | null => {\n switch (direction) {\n case 'down': {\n const maxBottom = Math.max(...fixedNodes.map((f) => f.bottom));\n const newTop = snapToGrid(maxBottom + MIN_NODE_SPACING);\n return { left: collider.left, top: newTop };\n }\n case 'up': {\n const minTop = Math.min(...fixedNodes.map((f) => f.top));\n const newTop = snapToGrid(minTop - collider.height - MIN_NODE_SPACING);\n if (newTop < 0) return { left: collider.left, top: 0 };\n return { left: collider.left, top: newTop };\n }\n case 'right': {\n const maxRight = Math.max(...fixedNodes.map((f) => f.right));\n const newLeft = snapToGrid(maxRight + MIN_NODE_SPACING);\n return { left: newLeft, top: collider.top };\n }\n case 'left': {\n const minLeft = Math.min(...fixedNodes.map((f) => f.left));\n const newLeft = snapToGrid(minLeft - collider.width - MIN_NODE_SPACING);\n if (newLeft < 0) return { left: 0, top: collider.top };\n return { left: newLeft, top: collider.top };\n }\n }\n};\n\n/**\n * Calculates new positions to resolve all collisions using multi-directional reflow.\n *\n * Sacred nodes (the ones just dropped/created) keep their positions. All other\n * colliding nodes are moved in whichever direction requires the least displacement\n * and causes the fewest cascading collisions.\n */\nexport const calculateReflowPositions = (\n sacredNodeUuids: string[],\n allBounds: NodeBounds[]\n): Map<string, FlowPosition> => {\n const newPositions = new Map<string, FlowPosition>();\n const sacredSet = new Set(sacredNodeUuids);\n\n // Mutable map of current bounds, updated as collisions are resolved\n const currentBounds = new Map<string, NodeBounds>();\n for (const b of allBounds) {\n currentBounds.set(b.uuid, { ...b });\n }\n\n // Seed the queue with non-sacred nodes that overlap any sacred node\n const queue: string[] = [];\n const inQueue = new Set<string>();\n\n for (const sacredUuid of sacredSet) {\n const sacred = currentBounds.get(sacredUuid);\n if (!sacred) continue;\n for (const [uuid, bounds] of currentBounds) {\n if (sacredSet.has(uuid) || inQueue.has(uuid)) continue;\n if (nodesOverlap(sacred, bounds)) {\n queue.push(uuid);\n inQueue.add(uuid);\n }\n }\n }\n\n const resolved = new Set<string>();\n let iterations = 0;\n const maxIterations = 200;\n\n while (queue.length > 0 && iterations < maxIterations) {\n iterations++;\n const uuid = queue.shift()!;\n\n if (resolved.has(uuid)) continue;\n\n const collider = currentBounds.get(uuid)!;\n\n // Find all fixed nodes (sacred + already-resolved) that overlap this node\n const fixedOverlaps: NodeBounds[] = [];\n for (const [otherUuid, otherBounds] of currentBounds) {\n if (otherUuid === uuid) continue;\n if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) {\n if (nodesOverlap(collider, otherBounds)) {\n fixedOverlaps.push(otherBounds);\n }\n }\n }\n\n if (fixedOverlaps.length === 0) continue;\n\n // Try each direction, pick the one with least disruption\n let bestPos: { left: number; top: number } | null = null;\n let bestScore = Infinity;\n\n for (const dir of DIRECTIONS) {\n const candidate = computeDirectionalClearance(\n collider,\n fixedOverlaps,\n dir\n );\n if (!candidate) continue;\n\n const candidateBounds = makeBoundsAt(\n collider,\n candidate.left,\n candidate.top\n );\n\n // Verify no overlap with any sacred or resolved node\n let stillOverlaps = false;\n let cascadeCount = 0;\n for (const [otherUuid, otherBounds] of currentBounds) {\n if (otherUuid === uuid) continue;\n if (!nodesOverlap(candidateBounds, otherBounds)) continue;\n\n if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) {\n stillOverlaps = true;\n break;\n }\n cascadeCount++;\n }\n if (stillOverlaps) continue;\n\n const distance =\n Math.abs(candidate.left - collider.left) +\n Math.abs(candidate.top - collider.top);\n const score = cascadeCount * 10000 + distance;\n\n if (score < bestScore) {\n bestScore = score;\n bestPos = candidate;\n }\n }\n\n if (bestPos) {\n newPositions.set(uuid, { left: bestPos.left, top: bestPos.top });\n const newBounds = makeBoundsAt(collider, bestPos.left, bestPos.top);\n currentBounds.set(uuid, newBounds);\n resolved.add(uuid);\n\n // Enqueue any new cascading collisions\n for (const [otherUuid, otherBounds] of currentBounds) {\n if (otherUuid === uuid) continue;\n if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) continue;\n if (inQueue.has(otherUuid)) continue;\n if (nodesOverlap(newBounds, otherBounds)) {\n queue.push(otherUuid);\n inQueue.add(otherUuid);\n }\n }\n }\n }\n\n return newPositions;\n};\n"]}