@nyaruka/temba-components 0.141.0 → 0.142.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 (206) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/static/svg/index.svg +1 -1
  3. package/dist/temba-components.js +859 -656
  4. package/dist/temba-components.js.map +1 -1
  5. package/out-tsc/src/Icons.js +3 -1
  6. package/out-tsc/src/Icons.js.map +1 -1
  7. package/out-tsc/src/display/Button.js +2 -2
  8. package/out-tsc/src/display/Button.js.map +1 -1
  9. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  10. package/out-tsc/src/flow/CanvasMenu.js +24 -1
  11. package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
  12. package/out-tsc/src/flow/CanvasNode.js +7 -2
  13. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  14. package/out-tsc/src/flow/Editor.js +665 -67
  15. package/out-tsc/src/flow/Editor.js.map +1 -1
  16. package/out-tsc/src/flow/NodeEditor.js +8 -5
  17. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  18. package/out-tsc/src/flow/Plumber.js +40 -28
  19. package/out-tsc/src/flow/Plumber.js.map +1 -1
  20. package/out-tsc/src/flow/actions/send_msg.js +2 -1
  21. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  22. package/out-tsc/src/flow/nodes/wait_for_response.js +1 -1
  23. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  24. package/out-tsc/src/flow/reflow.js +393 -0
  25. package/out-tsc/src/flow/reflow.js.map +1 -0
  26. package/out-tsc/src/flow/types.js.map +1 -1
  27. package/out-tsc/src/flow/utils.js +18 -3
  28. package/out-tsc/src/flow/utils.js.map +1 -1
  29. package/out-tsc/src/form/Compose.js +5 -0
  30. package/out-tsc/src/form/Compose.js.map +1 -1
  31. package/out-tsc/src/form/FieldRenderer.js +1 -3
  32. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  33. package/out-tsc/src/layout/Dialog.js +2 -0
  34. package/out-tsc/src/layout/Dialog.js.map +1 -1
  35. package/out-tsc/src/list/SortableList.js +39 -19
  36. package/out-tsc/src/list/SortableList.js.map +1 -1
  37. package/out-tsc/src/live/ContactChat.js +10 -1
  38. package/out-tsc/src/live/ContactChat.js.map +1 -1
  39. package/out-tsc/src/version.js +9 -0
  40. package/out-tsc/src/version.js.map +1 -0
  41. package/out-tsc/test/temba-canvas-menu.test.js +44 -0
  42. package/out-tsc/test/temba-canvas-menu.test.js.map +1 -1
  43. package/out-tsc/test/temba-contact-chat.test.js +12 -0
  44. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  45. package/out-tsc/test/temba-flow-collision.test.js +25 -0
  46. package/out-tsc/test/temba-flow-collision.test.js.map +1 -1
  47. package/out-tsc/test/temba-flow-editor-zoom.test.js +491 -0
  48. package/out-tsc/test/temba-flow-editor-zoom.test.js.map +1 -0
  49. package/out-tsc/test/temba-flow-editor.test.js +164 -1
  50. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  51. package/out-tsc/test/temba-flow-node-drag.test.js +123 -0
  52. package/out-tsc/test/temba-flow-node-drag.test.js.map +1 -1
  53. package/out-tsc/test/temba-flow-plumber.test.js +31 -0
  54. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  55. package/out-tsc/test/temba-flow-reflow.test.js +472 -0
  56. package/out-tsc/test/temba-flow-reflow.test.js.map +1 -0
  57. package/out-tsc/test/temba-sortable-list.test.js +93 -0
  58. package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
  59. package/package.json +1 -1
  60. package/rollup.components.mjs +7 -1
  61. package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
  62. package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
  63. package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
  64. package/screenshots/truth/actions/add_contact_urn/editor/expression-facebook.png +0 -0
  65. package/screenshots/truth/actions/add_contact_urn/editor/expression-phone.png +0 -0
  66. package/screenshots/truth/actions/add_contact_urn/editor/facebook-id.png +0 -0
  67. package/screenshots/truth/actions/add_contact_urn/editor/instagram-handle.png +0 -0
  68. package/screenshots/truth/actions/add_contact_urn/editor/line-id.png +0 -0
  69. package/screenshots/truth/actions/add_contact_urn/editor/phone-number.png +0 -0
  70. package/screenshots/truth/actions/add_contact_urn/editor/telegram-id.png +0 -0
  71. package/screenshots/truth/actions/add_contact_urn/editor/viber-id.png +0 -0
  72. package/screenshots/truth/actions/add_contact_urn/editor/wechat-id.png +0 -0
  73. package/screenshots/truth/actions/add_contact_urn/editor/whatsapp.png +0 -0
  74. package/screenshots/truth/actions/enter_flow/editor/basic-flow.png +0 -0
  75. package/screenshots/truth/actions/enter_flow/editor/long-flow-name.png +0 -0
  76. package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
  77. package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
  78. package/screenshots/truth/actions/say_msg/editor/multiline-text.png +0 -0
  79. package/screenshots/truth/actions/say_msg/editor/simple-text.png +0 -0
  80. package/screenshots/truth/actions/say_msg/editor/text-with-audio-url.png +0 -0
  81. package/screenshots/truth/actions/send_broadcast/editor/contacts-only.png +0 -0
  82. package/screenshots/truth/actions/send_broadcast/editor/groups-and-contacts.png +0 -0
  83. package/screenshots/truth/actions/send_broadcast/editor/groups-only.png +0 -0
  84. package/screenshots/truth/actions/send_broadcast/editor/many-groups.png +0 -0
  85. package/screenshots/truth/actions/send_broadcast/editor/multiline-text.png +0 -0
  86. package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
  87. package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
  88. package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
  89. package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
  90. package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
  91. package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
  92. package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
  93. package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
  94. package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
  95. package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
  96. package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
  97. package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
  98. package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
  99. package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
  100. package/screenshots/truth/actions/set_contact_channel/editor/sms-channel.png +0 -0
  101. package/screenshots/truth/actions/set_contact_channel/editor/whatsapp-channel.png +0 -0
  102. package/screenshots/truth/actions/set_contact_field/editor/clear-value.png +0 -0
  103. package/screenshots/truth/actions/set_contact_field/editor/set-value.png +0 -0
  104. package/screenshots/truth/actions/set_contact_language/editor/english.png +0 -0
  105. package/screenshots/truth/actions/set_contact_language/editor/french.png +0 -0
  106. package/screenshots/truth/actions/set_contact_status/editor/active.png +0 -0
  107. package/screenshots/truth/actions/set_contact_status/editor/archived.png +0 -0
  108. package/screenshots/truth/actions/set_contact_status/editor/blocked.png +0 -0
  109. package/screenshots/truth/actions/set_run_result/editor/expression-value.png +0 -0
  110. package/screenshots/truth/actions/set_run_result/editor/with-category.png +0 -0
  111. package/screenshots/truth/actions/start_session/editor/contact-query.png +0 -0
  112. package/screenshots/truth/actions/start_session/editor/contacts-only.png +0 -0
  113. package/screenshots/truth/actions/start_session/editor/create-contact.png +0 -0
  114. package/screenshots/truth/actions/start_session/editor/groups-and-contacts.png +0 -0
  115. package/screenshots/truth/actions/start_session/editor/groups-only.png +0 -0
  116. package/screenshots/truth/actions/start_session/editor/many-recipients.png +0 -0
  117. package/screenshots/truth/list/fields-dragging.png +0 -0
  118. package/screenshots/truth/list/sortable-dragging.png +0 -0
  119. package/screenshots/truth/modax/simple.png +0 -0
  120. package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
  121. package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
  122. package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
  123. package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
  124. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  125. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  126. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  127. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  128. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  129. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  130. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  131. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  132. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  133. package/screenshots/truth/nodes/wait_for_dial/editor/dial-with-limits.png +0 -0
  134. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  135. package/screenshots/truth/nodes/wait_for_digits/editor/digits-with-rules.png +0 -0
  136. package/screenshots/truth/nodes/wait_for_menu/editor/menu-with-digits.png +0 -0
  137. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  138. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  139. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  140. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  141. package/src/Icons.ts +3 -1
  142. package/src/display/Button.ts +2 -2
  143. package/src/display/FloatingTab.ts +1 -1
  144. package/src/flow/CanvasMenu.ts +28 -3
  145. package/src/flow/CanvasNode.ts +7 -2
  146. package/src/flow/Editor.ts +769 -76
  147. package/src/flow/NodeEditor.ts +8 -4
  148. package/src/flow/Plumber.ts +65 -35
  149. package/src/flow/actions/send_msg.ts +2 -1
  150. package/src/flow/nodes/wait_for_response.ts +1 -1
  151. package/src/flow/reflow.ts +534 -0
  152. package/src/flow/types.ts +1 -0
  153. package/src/flow/utils.ts +19 -3
  154. package/src/form/Compose.ts +5 -0
  155. package/src/form/FieldRenderer.ts +1 -3
  156. package/src/layout/Dialog.ts +2 -0
  157. package/src/list/SortableList.ts +40 -19
  158. package/src/live/ContactChat.ts +10 -1
  159. package/src/store/flow-definition.d.ts +1 -0
  160. package/src/version.ts +10 -0
  161. package/static/svg/index.svg +1 -1
  162. package/static/svg/work/traced/expand-06.svg +1 -0
  163. package/static/svg/work/used/expand-06.svg +3 -0
  164. package/test/temba-canvas-menu.test.ts +55 -0
  165. package/test/temba-contact-chat.test.ts +17 -0
  166. package/test/temba-flow-collision.test.ts +31 -0
  167. package/test/temba-flow-editor-zoom.test.ts +583 -0
  168. package/test/temba-flow-editor.test.ts +211 -1
  169. package/test/temba-flow-node-drag.test.ts +171 -0
  170. package/test/temba-flow-plumber.test.ts +38 -0
  171. package/test/temba-flow-reflow.test.ts +703 -0
  172. package/test/temba-sortable-list.test.ts +120 -0
  173. package/web-dev-server.config.mjs +5 -1
  174. package/web-test-runner.config.mjs +4 -1
  175. package/screenshots/truth/actions/call_llm/editor/information-extraction.png +0 -0
  176. package/screenshots/truth/actions/call_llm/editor/sentiment-analysis.png +0 -0
  177. package/screenshots/truth/actions/call_llm/editor/summarization.png +0 -0
  178. package/screenshots/truth/actions/call_llm/editor/translation-task.png +0 -0
  179. package/screenshots/truth/actions/call_llm/render/information-extraction.png +0 -0
  180. package/screenshots/truth/actions/call_llm/render/sentiment-analysis.png +0 -0
  181. package/screenshots/truth/actions/call_llm/render/summarization.png +0 -0
  182. package/screenshots/truth/actions/call_llm/render/translation-task.png +0 -0
  183. package/screenshots/truth/actions/send_broadcast/editor/with-attachments.png +0 -0
  184. package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
  185. package/screenshots/truth/compose/attachments-with-failures.png +0 -0
  186. package/screenshots/truth/compose/attachments-with-files-and-failures.png +0 -0
  187. package/screenshots/truth/contacts/tickets-assignment.png +0 -0
  188. package/screenshots/truth/contacts/tickets.png +0 -0
  189. package/screenshots/truth/flow/editor-basic.png +0 -0
  190. package/screenshots/truth/formfield/markdown-errors.png +0 -0
  191. package/screenshots/truth/formfield/no-errors.png +0 -0
  192. package/screenshots/truth/formfield/plain-text-errors.png +0 -0
  193. package/screenshots/truth/formfield/widget-only-markdown-errors.png +0 -0
  194. package/screenshots/truth/omnibox/selected.png +0 -0
  195. package/screenshots/truth/select/enabled-multi-selection.png +0 -0
  196. package/screenshots/truth/select/endpoint-initial-value-updated.png +0 -0
  197. package/screenshots/truth/select/endpoint-initial-value.png +0 -0
  198. package/screenshots/truth/select/initial-value.png +0 -0
  199. package/screenshots/truth/select/multi-reorder-final.png +0 -0
  200. package/screenshots/truth/select/multi-reorder-initial.png +0 -0
  201. package/screenshots/truth/select/selected-multi-test.png +0 -0
  202. package/screenshots/truth/select/value-initial.png +0 -0
  203. package/screenshots/truth/wait-for-response/rules-editor.png +0 -0
  204. package/screenshots/truth/wait-for-response/timeout-editor-unchecked.png +0 -0
  205. package/screenshots/truth/wait-for-response/timeout-editor.png +0 -0
  206. package/screenshots/truth/webchat/connecting-state.png +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"send_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_msg.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, SendMsg } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\n\nexport const send_msg: ActionConfig = {\n name: 'Send Message',\n group: ACTION_GROUPS.send,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendMsg) => {\n const text = action.text.replace(/\\n/g, '<br>');\n return html`\n ${unsafeHTML(text)}\n ${(action.quick_replies || [])?.length > 0\n ? html`<div class=\"quick-replies\">\n ${(action.quick_replies || []).map((reply) => {\n return html`<div class=\"quick-reply\">${reply}</div>`;\n })}\n ${action.template\n ? html`<div\n style=\"border: 1px solid var(--color-widget-border);padding: 0.5em;margin-top: 1em;border-radius: var(--curvature); display:flex;background: rgba(0,0,0,.03);\"\n >\n <temba-icon name=\"channel_wac\"></temba-icon>\n <div style=\"margin-left:0.5em\">${action.template.name}</div>\n </div>`\n : null}\n </div>`\n : null}\n `;\n },\n form: {\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n },\n quick_replies: {\n type: 'select',\n options: [],\n multi: true,\n tags: true,\n searchable: true,\n placeholder: 'Add quick replies...',\n maxItems: 10,\n evaluated: true\n },\n runtime_attachments: {\n type: 'array',\n helpText: 'Add dynamic attachments using expressions',\n itemLabel: 'Attachment',\n sortable: true,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.expression || item.expression.trim() === '';\n },\n itemConfig: {\n type: {\n type: 'select',\n options: [\n { value: 'image', name: 'Image' },\n { value: 'audio', name: 'Audio' },\n { value: 'video', name: 'Video' },\n { value: 'document', name: 'Document' }\n ],\n required: true,\n searchable: false\n },\n expression: {\n type: 'text',\n placeholder: 'Expression (e.g. @contact.photo)',\n required: true,\n evaluated: true\n }\n }\n }\n },\n layout: [\n 'text',\n {\n type: 'group',\n label: 'Quick Replies',\n items: ['quick_replies'],\n collapsible: true,\n collapsed: (formData: FormData) => {\n // Collapse only if there are no quick replies\n return !formData.quick_replies || formData.quick_replies.length === 0;\n },\n getGroupValueCount: (formData: FormData) => {\n return formData.quick_replies?.length || 0;\n }\n },\n {\n type: 'group',\n label: 'Runtime Attachments',\n items: ['runtime_attachments'],\n collapsible: true,\n collapsed: true,\n helpText: 'Add dynamic attachments that are evaluated at runtime',\n getGroupValueCount: (formData: FormData) => {\n return (\n formData.runtime_attachments?.filter(\n (item: any) =>\n item && item.expression && item.expression.trim() !== ''\n ).length || 0\n );\n }\n }\n ],\n toFormData: (action: SendMsg) => {\n // Extract runtime attachments from the text field attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (action.attachments && Array.isArray(action.attachments)) {\n action.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n return {\n uuid: action.uuid,\n text: action.text || '',\n attachments: staticAttachments,\n runtime_attachments: runtimeAttachments,\n quick_replies: (action.quick_replies || []).map((reply) => ({\n name: reply,\n value: reply\n }))\n };\n },\n fromFormData: (data: FormData) => {\n const result = {\n uuid: data.uuid,\n type: 'send_msg',\n text: data.text || '',\n attachments: [],\n quick_replies: (data.quick_replies || []).map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n };\n\n // Combine static attachments from text field with runtime attachments\n const staticAttachments = data.attachments || [];\n const runtimeAttachments = (data.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => item && item.type && item.expression\n ) // Filter out invalid items\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n result.attachments = [...staticAttachments, ...runtimeAttachments];\n\n // Remove quick_replies if empty to match original format\n if (result.quick_replies.length === 0) {\n delete (result as any).quick_replies;\n }\n\n return result as SendMsg;\n },\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n // Check total attachment count (static + runtime should not exceed 10)\n const staticAttachments = formData.attachments || [];\n const runtimeAttachments = (formData.runtime_attachments || []).filter(\n (item: any) => item && item.expression && item.expression.trim() !== ''\n );\n\n const totalAttachments =\n staticAttachments.length + runtimeAttachments.length;\n if (totalAttachments > 10) {\n if (runtimeAttachments.length > 0) {\n errors.runtime_attachments =\n 'Each message can only have up to 10 attachments';\n }\n if (staticAttachments.length > 0) {\n errors.text = 'Each message can only have up to 10 total attachments';\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n localizable: ['text', 'quick_replies', 'attachments'],\n toLocalizationFormData: (\n action: SendMsg,\n localization: Record<string, any>\n ) => {\n // Convert localized values to form data format\n // Localized values are stored as arrays even for single values\n const formData: FormData = {\n uuid: action.uuid\n };\n\n // Handle text (single value, but stored as array in localization)\n if (localization.text && Array.isArray(localization.text)) {\n formData.text = localization.text[0] || '';\n } else {\n // Fall back to empty string if no localization\n formData.text = '';\n }\n\n // Handle attachments (already an array)\n if (localization.attachments && Array.isArray(localization.attachments)) {\n formData.attachments = localization.attachments;\n }\n\n // Handle quick_replies (already an array)\n if (\n localization.quick_replies &&\n Array.isArray(localization.quick_replies)\n ) {\n formData.quick_replies = localization.quick_replies.map((reply) => ({\n name: reply,\n value: reply\n }));\n }\n\n // Extract runtime attachments from localized attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (formData.attachments && Array.isArray(formData.attachments)) {\n formData.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n formData.attachments = staticAttachments;\n formData.runtime_attachments = runtimeAttachments;\n\n return formData;\n },\n fromLocalizationFormData: (formData: FormData, action: SendMsg) => {\n // Convert form data to localization format\n // All values must be stored as arrays\n const localization: Record<string, any> = {};\n\n // Handle text (store as single-element array)\n // Only save if not empty and different from base action\n if (formData.text && formData.text.trim() !== '') {\n if (formData.text !== action.text) {\n localization.text = [formData.text];\n }\n }\n\n // Handle quick_replies (store as array)\n const quickReplies = (formData.quick_replies || [])\n .map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n .filter((reply: string) => reply && reply.trim() !== '');\n\n // Only save if there are quick replies and different from base action\n if (quickReplies.length > 0) {\n if (\n JSON.stringify(quickReplies) !==\n JSON.stringify(action.quick_replies || [])\n ) {\n localization.quick_replies = quickReplies;\n }\n }\n\n // Handle attachments (combine static and runtime attachments)\n const staticAttachments = (formData.attachments || []).filter(\n (att: string) => att && att.trim() !== ''\n );\n const runtimeAttachments = (formData.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) =>\n item && item.type && item.expression && item.expression.trim() !== ''\n )\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n const allAttachments = [...staticAttachments, ...runtimeAttachments];\n\n // Only save if there are attachments and different from base action\n if (allAttachments.length > 0) {\n if (\n JSON.stringify(allAttachments) !==\n JSON.stringify(action.attachments || [])\n ) {\n localization.attachments = allAttachments;\n }\n }\n\n return localization;\n }\n};\n"]}
1
+ {"version":3,"file":"send_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_msg.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, SendMsg } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\n\nexport const send_msg: ActionConfig = {\n name: 'Send Message',\n group: ACTION_GROUPS.send,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendMsg) => {\n const text = action.text.replace(/\\n/g, '<br>');\n return html`\n ${unsafeHTML(text)}\n ${(action.quick_replies || [])?.length > 0\n ? html`<div class=\"quick-replies\">\n ${(action.quick_replies || []).map((reply) => {\n return html`<div class=\"quick-reply\">${reply}</div>`;\n })}\n ${action.template\n ? html`<div\n style=\"border: 1px solid var(--color-widget-border);padding: 0.5em;margin-top: 1em;border-radius: var(--curvature); display:flex;background: rgba(0,0,0,.03);\"\n >\n <temba-icon name=\"channel_wac\"></temba-icon>\n <div style=\"margin-left:0.5em\">${action.template.name}</div>\n </div>`\n : null}\n </div>`\n : null}\n `;\n },\n form: {\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n },\n quick_replies: {\n type: 'select',\n options: [],\n multi: true,\n tags: true,\n searchable: true,\n placeholder: 'Add quick replies...',\n maxItems: 10,\n evaluated: true\n },\n runtime_attachments: {\n type: 'array',\n itemLabel: 'Attachment',\n sortable: true,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.expression || item.expression.trim() === '';\n },\n itemConfig: {\n type: {\n type: 'select',\n width: '140px',\n options: [\n { value: 'image', name: 'Image' },\n { value: 'audio', name: 'Audio' },\n { value: 'video', name: 'Video' },\n { value: 'document', name: 'Document' }\n ],\n required: true,\n searchable: false\n },\n expression: {\n type: 'text',\n placeholder: 'Expression (e.g. @contact.photo)',\n required: true,\n evaluated: true\n }\n }\n }\n },\n layout: [\n 'text',\n {\n type: 'group',\n label: 'Quick Replies',\n items: ['quick_replies'],\n collapsible: true,\n collapsed: (formData: FormData) => {\n // Collapse only if there are no quick replies\n return !formData.quick_replies || formData.quick_replies.length === 0;\n },\n getGroupValueCount: (formData: FormData) => {\n return formData.quick_replies?.length || 0;\n }\n },\n {\n type: 'group',\n label: 'Runtime Attachments',\n items: ['runtime_attachments'],\n collapsible: true,\n collapsed: true,\n helpText: 'Add dynamic attachments that are evaluated at runtime',\n contentPadding: '12px',\n getGroupValueCount: (formData: FormData) => {\n return (\n formData.runtime_attachments?.filter(\n (item: any) =>\n item && item.expression && item.expression.trim() !== ''\n ).length || 0\n );\n }\n }\n ],\n toFormData: (action: SendMsg) => {\n // Extract runtime attachments from the text field attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (action.attachments && Array.isArray(action.attachments)) {\n action.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n return {\n uuid: action.uuid,\n text: action.text || '',\n attachments: staticAttachments,\n runtime_attachments: runtimeAttachments,\n quick_replies: (action.quick_replies || []).map((reply) => ({\n name: reply,\n value: reply\n }))\n };\n },\n fromFormData: (data: FormData) => {\n const result = {\n uuid: data.uuid,\n type: 'send_msg',\n text: data.text || '',\n attachments: [],\n quick_replies: (data.quick_replies || []).map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n };\n\n // Combine static attachments from text field with runtime attachments\n const staticAttachments = data.attachments || [];\n const runtimeAttachments = (data.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => item && item.type && item.expression\n ) // Filter out invalid items\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n result.attachments = [...staticAttachments, ...runtimeAttachments];\n\n // Remove quick_replies if empty to match original format\n if (result.quick_replies.length === 0) {\n delete (result as any).quick_replies;\n }\n\n return result as SendMsg;\n },\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n // Check total attachment count (static + runtime should not exceed 10)\n const staticAttachments = formData.attachments || [];\n const runtimeAttachments = (formData.runtime_attachments || []).filter(\n (item: any) => item && item.expression && item.expression.trim() !== ''\n );\n\n const totalAttachments =\n staticAttachments.length + runtimeAttachments.length;\n if (totalAttachments > 10) {\n if (runtimeAttachments.length > 0) {\n errors.runtime_attachments =\n 'Each message can only have up to 10 attachments';\n }\n if (staticAttachments.length > 0) {\n errors.text = 'Each message can only have up to 10 total attachments';\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n localizable: ['text', 'quick_replies', 'attachments'],\n toLocalizationFormData: (\n action: SendMsg,\n localization: Record<string, any>\n ) => {\n // Convert localized values to form data format\n // Localized values are stored as arrays even for single values\n const formData: FormData = {\n uuid: action.uuid\n };\n\n // Handle text (single value, but stored as array in localization)\n if (localization.text && Array.isArray(localization.text)) {\n formData.text = localization.text[0] || '';\n } else {\n // Fall back to empty string if no localization\n formData.text = '';\n }\n\n // Handle attachments (already an array)\n if (localization.attachments && Array.isArray(localization.attachments)) {\n formData.attachments = localization.attachments;\n }\n\n // Handle quick_replies (already an array)\n if (\n localization.quick_replies &&\n Array.isArray(localization.quick_replies)\n ) {\n formData.quick_replies = localization.quick_replies.map((reply) => ({\n name: reply,\n value: reply\n }));\n }\n\n // Extract runtime attachments from localized attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (formData.attachments && Array.isArray(formData.attachments)) {\n formData.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n formData.attachments = staticAttachments;\n formData.runtime_attachments = runtimeAttachments;\n\n return formData;\n },\n fromLocalizationFormData: (formData: FormData, action: SendMsg) => {\n // Convert form data to localization format\n // All values must be stored as arrays\n const localization: Record<string, any> = {};\n\n // Handle text (store as single-element array)\n // Only save if not empty and different from base action\n if (formData.text && formData.text.trim() !== '') {\n if (formData.text !== action.text) {\n localization.text = [formData.text];\n }\n }\n\n // Handle quick_replies (store as array)\n const quickReplies = (formData.quick_replies || [])\n .map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n .filter((reply: string) => reply && reply.trim() !== '');\n\n // Only save if there are quick replies and different from base action\n if (quickReplies.length > 0) {\n if (\n JSON.stringify(quickReplies) !==\n JSON.stringify(action.quick_replies || [])\n ) {\n localization.quick_replies = quickReplies;\n }\n }\n\n // Handle attachments (combine static and runtime attachments)\n const staticAttachments = (formData.attachments || []).filter(\n (att: string) => att && att.trim() !== ''\n );\n const runtimeAttachments = (formData.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) =>\n item && item.type && item.expression && item.expression.trim() !== ''\n )\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n const allAttachments = [...staticAttachments, ...runtimeAttachments];\n\n // Only save if there are attachments and different from base action\n if (allAttachments.length > 0) {\n if (\n JSON.stringify(allAttachments) !==\n JSON.stringify(action.attachments || [])\n ) {\n localization.attachments = allAttachments;\n }\n }\n\n return localization;\n }\n};\n"]}
@@ -62,7 +62,7 @@ export const wait_for_response = {
62
62
  type: 'select',
63
63
  placeholder: '5 minutes',
64
64
  multi: false,
65
- maxWidth: '100px',
65
+ maxWidth: '130px',
66
66
  flavor: 'xsmall',
67
67
  options: TIMEOUT_OPTIONS,
68
68
  conditions: {
@@ -1 +1 @@
1
- {"version":3,"file":"wait_for_response.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_response.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node, Category, Exit, Case } from '../../store/flow-definition';\nimport { generateUUID, createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\n\nconst TIMEOUT_OPTIONS = [\n { value: '60', name: '1 minute' },\n { value: '120', name: '2 minutes' },\n { value: '180', name: '3 minutes' },\n { value: '240', name: '4 minutes' },\n { value: '300', name: '5 minutes' },\n { value: '600', name: '10 minutes' },\n { value: '900', name: '15 minutes' },\n { value: '1800', name: '30 minutes' },\n { value: '3600', name: '1 hour' },\n { value: '7200', name: '2 hours' },\n { value: '10800', name: '3 hours' },\n { value: '21600', name: '6 hours' },\n { value: '43200', name: '12 hours' },\n { value: '64800', name: '18 hours' },\n { value: '86400', name: '1 day' },\n { value: '172800', name: '2 days' },\n { value: '259200', name: '3 days' },\n { value: '604800', name: '1 week' }\n];\n\n// Helper function to create a wait_for_response router with user rules\n// This is a thin wrapper around createRulesRouter that adds the No Response category for timeouts\nconst createWaitForResponseRouter = (\n userRules: any[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = [],\n existingCases: Case[] = []\n) => {\n const { router, exits } = createRulesRouter(\n '@input.text',\n userRules,\n getOperatorConfig,\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Add \"No Response\" category last (if it exists in the original)\n const existingNoResponseCategory = existingCategories.find(\n (cat) => cat.name === 'No Response' || cat.name === 'Timeout'\n );\n\n if (existingNoResponseCategory) {\n const existingNoResponseExit = existingExits.find(\n (exit) => exit.uuid === existingNoResponseCategory.exit_uuid\n );\n\n if (existingNoResponseExit) {\n router.categories.push(existingNoResponseCategory);\n exits.push({\n uuid: existingNoResponseExit.uuid,\n destination_uuid: existingNoResponseExit.destination_uuid || null\n });\n }\n }\n\n return { router, exits };\n};\n\nexport const wait_for_response: NodeConfig = {\n type: 'wait_for_response',\n name: 'Wait for Response',\n group: SPLIT_GROUPS.wait,\n flowTypes: [FlowTypes.MESSAGE],\n dialogSize: 'large',\n form: {\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getWaitForResponseOperators()),\n 'If the message from the contact...'\n ),\n timeout_enabled: {\n type: 'checkbox',\n label: (formData: Record<string, any>) => {\n return formData.timeout_enabled\n ? 'Continue when there is no response for'\n : 'Continue when there is no response..';\n },\n labelPadding: '4px 8px'\n },\n timeout_duration: {\n type: 'select',\n placeholder: '5 minutes',\n multi: false,\n maxWidth: '100px',\n flavor: 'xsmall',\n options: TIMEOUT_OPTIONS,\n\n conditions: {\n visible: (formData: Record<string, any>) => {\n return formData.timeout_enabled === true;\n }\n }\n },\n result_name: resultNameField\n },\n layout: ['rules', 'result_name'],\n gutter: [\n {\n type: 'row',\n items: ['timeout_enabled', 'timeout_duration'],\n gap: '0.5rem'\n }\n ],\n validate: (_formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // No validation needed - allow multiple rules to use same category name\n // Rules with the same category name will be merged to use the same exit\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract rules from router cases using shared function\n const rules = casesToFormRules(node);\n\n // Extract timeout configuration\n const timeoutSeconds = node.router?.wait?.timeout?.seconds;\n let timeoutOption = TIMEOUT_OPTIONS.find(\n (opt) => opt.value === String(timeoutSeconds)\n );\n\n if (!timeoutOption) {\n timeoutOption = { value: '300', name: '5 minutes' };\n }\n\n return {\n uuid: node.uuid,\n rules: rules,\n timeout_enabled: !!timeoutSeconds,\n timeout_duration: timeoutOption,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user rules using shared extraction function\n const userRules = extractUserRules(formData);\n\n // If no user rules, clear cases but preserve other router config\n if (userRules.length === 0) {\n // Get existing router data for preservation\n let existingCategories = originalNode.router?.categories || [];\n const existingExits = [...(originalNode.exits || [])]; // Create a copy to avoid extensibility issues\n\n // Handle timeout: ensure \"No Response\" category exists if timeout is enabled,\n // or remove it if timeout is disabled\n if (formData.timeout_enabled) {\n let noResponseCategory = existingCategories.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n if (!noResponseCategory) {\n // Create new \"No Response\" category and exit\n const noResponseExitUuid = generateUUID();\n noResponseCategory = {\n uuid: generateUUID(),\n name: 'No Response',\n exit_uuid: noResponseExitUuid\n };\n\n // Add to existing categories for processing\n existingCategories = [...existingCategories, noResponseCategory];\n\n // Add corresponding exit if it doesn't exist\n if (!existingExits.find((exit) => exit.uuid === noResponseExitUuid)) {\n existingExits.push({\n uuid: noResponseExitUuid,\n destination_uuid: null\n });\n }\n }\n } else {\n // If timeout is disabled, remove \"No Response\" category from existing categories\n existingCategories = existingCategories.filter(\n (cat: any) => cat.name !== 'No Response'\n );\n }\n\n // Create router with \"All Responses\" as default category\n // This will now properly handle the \"No Response\" category if it exists\n const { router: noRulesRouter, exits: noRulesExits } =\n createWaitForResponseRouter(\n [], // No user rules\n existingCategories,\n existingExits,\n [] // No cases\n );\n\n const router: any = {\n ...noRulesRouter,\n cases: [] // Clear all cases when no rules\n };\n\n // Only set result_name if provided\n if (formData.result_name && formData.result_name.trim() !== '') {\n router.result_name = formData.result_name.trim();\n }\n\n // Build wait configuration based on form data\n const waitConfig: any = {\n type: 'msg'\n };\n\n // Add timeout if enabled\n if (formData.timeout_enabled) {\n // Extract timeout value (handle both string and object formats)\n let timeoutSeconds;\n\n if (formData.timeout_duration) {\n if (\n Array.isArray(formData.timeout_duration) &&\n formData.timeout_duration.length > 0\n ) {\n // Handle array of selected options (multi-select behavior)\n timeoutSeconds = parseInt(formData.timeout_duration[0].value, 10);\n } else if (typeof formData.timeout_duration === 'string') {\n timeoutSeconds = parseInt(formData.timeout_duration, 10);\n } else if (\n formData.timeout_duration &&\n typeof formData.timeout_duration === 'object' &&\n formData.timeout_duration.value\n ) {\n timeoutSeconds = parseInt(formData.timeout_duration.value, 10);\n } else {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n } else {\n // No duration selected, use default\n timeoutSeconds = 300; // Default to 5 minutes\n }\n\n // Validate that we got a valid number\n if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n\n // Find the \"No Response\" category (should exist now)\n const noResponseCategory = router.categories.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n if (noResponseCategory) {\n waitConfig.timeout = {\n seconds: timeoutSeconds,\n category_uuid: noResponseCategory.uuid\n };\n }\n }\n\n router.wait = waitConfig;\n\n return {\n ...originalNode,\n router,\n exits: noRulesExits\n };\n }\n\n // Get existing router data for preservation\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Create router and exits using existing data when possible\n const { router, exits } = createWaitForResponseRouter(\n userRules,\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Build final router with wait configuration and result_name\n const finalRouter: any = {\n ...router\n };\n\n // Only set result_name if provided\n if (formData.result_name && formData.result_name.trim() !== '') {\n finalRouter.result_name = formData.result_name.trim();\n }\n\n // Build wait configuration based on form data\n const waitConfig: any = {\n type: 'msg'\n };\n\n try {\n // Handle timeout configuration\n if (formData.timeout_enabled) {\n // Extract timeout value (handle both string and object formats)\n let timeoutSeconds;\n\n if (formData.timeout_duration) {\n try {\n timeoutSeconds = parseInt(formData.timeout_duration[0].value, 10);\n } catch (e) {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n }\n\n // Find or create the \"No Response\" category\n const existingNoResponseCategory =\n originalNode.router?.categories?.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n const noResponseCategory = existingNoResponseCategory || {\n uuid: generateUUID(),\n name: 'No Response',\n exit_uuid: generateUUID()\n };\n\n waitConfig.timeout = {\n seconds: timeoutSeconds,\n category_uuid: noResponseCategory.uuid\n };\n\n // Ensure No Response category and exit exist\n if (\n !router.categories?.some((cat: any) => cat.name === 'No Response')\n ) {\n router.categories = router.categories || [];\n router.categories.push(noResponseCategory);\n\n // Add corresponding exit if it doesn't exist\n if (\n !exits.some(\n (exit: any) => exit.uuid === noResponseCategory.exit_uuid\n )\n ) {\n const noResponseExit = {\n uuid: noResponseCategory.exit_uuid,\n destination_uuid: existingNoResponseCategory?.exit_uuid\n ? originalNode.exits?.find(\n (exit) => exit.uuid === existingNoResponseCategory.exit_uuid\n )?.destination_uuid || null\n : null\n };\n exits.push(noResponseExit);\n }\n }\n } else {\n // Remove \"No Response\" category if timeout is disabled\n if (router.categories) {\n const noResponseCategoryIndex = router.categories.findIndex(\n (cat: any) => cat.name === 'No Response'\n );\n if (noResponseCategoryIndex !== -1) {\n const noResponseCategory =\n router.categories[noResponseCategoryIndex];\n\n // Remove the category\n router.categories.splice(noResponseCategoryIndex, 1);\n\n // Remove corresponding exit\n const exitIndex = exits.findIndex(\n (exit: any) => exit.uuid === noResponseCategory.exit_uuid\n );\n if (exitIndex !== -1) {\n exits.splice(exitIndex, 1);\n }\n }\n }\n }\n } catch (error) {\n console.error('Error processing timeout configuration:', error);\n // Continue without timeout in case of error\n }\n\n finalRouter.wait = waitConfig;\n return {\n ...originalNode,\n router: finalRouter,\n exits: exits\n };\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
1
+ {"version":3,"file":"wait_for_response.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_response.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node, Category, Exit, Case } from '../../store/flow-definition';\nimport { generateUUID, createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\n\nconst TIMEOUT_OPTIONS = [\n { value: '60', name: '1 minute' },\n { value: '120', name: '2 minutes' },\n { value: '180', name: '3 minutes' },\n { value: '240', name: '4 minutes' },\n { value: '300', name: '5 minutes' },\n { value: '600', name: '10 minutes' },\n { value: '900', name: '15 minutes' },\n { value: '1800', name: '30 minutes' },\n { value: '3600', name: '1 hour' },\n { value: '7200', name: '2 hours' },\n { value: '10800', name: '3 hours' },\n { value: '21600', name: '6 hours' },\n { value: '43200', name: '12 hours' },\n { value: '64800', name: '18 hours' },\n { value: '86400', name: '1 day' },\n { value: '172800', name: '2 days' },\n { value: '259200', name: '3 days' },\n { value: '604800', name: '1 week' }\n];\n\n// Helper function to create a wait_for_response router with user rules\n// This is a thin wrapper around createRulesRouter that adds the No Response category for timeouts\nconst createWaitForResponseRouter = (\n userRules: any[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = [],\n existingCases: Case[] = []\n) => {\n const { router, exits } = createRulesRouter(\n '@input.text',\n userRules,\n getOperatorConfig,\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Add \"No Response\" category last (if it exists in the original)\n const existingNoResponseCategory = existingCategories.find(\n (cat) => cat.name === 'No Response' || cat.name === 'Timeout'\n );\n\n if (existingNoResponseCategory) {\n const existingNoResponseExit = existingExits.find(\n (exit) => exit.uuid === existingNoResponseCategory.exit_uuid\n );\n\n if (existingNoResponseExit) {\n router.categories.push(existingNoResponseCategory);\n exits.push({\n uuid: existingNoResponseExit.uuid,\n destination_uuid: existingNoResponseExit.destination_uuid || null\n });\n }\n }\n\n return { router, exits };\n};\n\nexport const wait_for_response: NodeConfig = {\n type: 'wait_for_response',\n name: 'Wait for Response',\n group: SPLIT_GROUPS.wait,\n flowTypes: [FlowTypes.MESSAGE],\n dialogSize: 'large',\n form: {\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getWaitForResponseOperators()),\n 'If the message from the contact...'\n ),\n timeout_enabled: {\n type: 'checkbox',\n label: (formData: Record<string, any>) => {\n return formData.timeout_enabled\n ? 'Continue when there is no response for'\n : 'Continue when there is no response..';\n },\n labelPadding: '4px 8px'\n },\n timeout_duration: {\n type: 'select',\n placeholder: '5 minutes',\n multi: false,\n maxWidth: '130px',\n flavor: 'xsmall',\n options: TIMEOUT_OPTIONS,\n\n conditions: {\n visible: (formData: Record<string, any>) => {\n return formData.timeout_enabled === true;\n }\n }\n },\n result_name: resultNameField\n },\n layout: ['rules', 'result_name'],\n gutter: [\n {\n type: 'row',\n items: ['timeout_enabled', 'timeout_duration'],\n gap: '0.5rem'\n }\n ],\n validate: (_formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // No validation needed - allow multiple rules to use same category name\n // Rules with the same category name will be merged to use the same exit\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract rules from router cases using shared function\n const rules = casesToFormRules(node);\n\n // Extract timeout configuration\n const timeoutSeconds = node.router?.wait?.timeout?.seconds;\n let timeoutOption = TIMEOUT_OPTIONS.find(\n (opt) => opt.value === String(timeoutSeconds)\n );\n\n if (!timeoutOption) {\n timeoutOption = { value: '300', name: '5 minutes' };\n }\n\n return {\n uuid: node.uuid,\n rules: rules,\n timeout_enabled: !!timeoutSeconds,\n timeout_duration: timeoutOption,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user rules using shared extraction function\n const userRules = extractUserRules(formData);\n\n // If no user rules, clear cases but preserve other router config\n if (userRules.length === 0) {\n // Get existing router data for preservation\n let existingCategories = originalNode.router?.categories || [];\n const existingExits = [...(originalNode.exits || [])]; // Create a copy to avoid extensibility issues\n\n // Handle timeout: ensure \"No Response\" category exists if timeout is enabled,\n // or remove it if timeout is disabled\n if (formData.timeout_enabled) {\n let noResponseCategory = existingCategories.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n if (!noResponseCategory) {\n // Create new \"No Response\" category and exit\n const noResponseExitUuid = generateUUID();\n noResponseCategory = {\n uuid: generateUUID(),\n name: 'No Response',\n exit_uuid: noResponseExitUuid\n };\n\n // Add to existing categories for processing\n existingCategories = [...existingCategories, noResponseCategory];\n\n // Add corresponding exit if it doesn't exist\n if (!existingExits.find((exit) => exit.uuid === noResponseExitUuid)) {\n existingExits.push({\n uuid: noResponseExitUuid,\n destination_uuid: null\n });\n }\n }\n } else {\n // If timeout is disabled, remove \"No Response\" category from existing categories\n existingCategories = existingCategories.filter(\n (cat: any) => cat.name !== 'No Response'\n );\n }\n\n // Create router with \"All Responses\" as default category\n // This will now properly handle the \"No Response\" category if it exists\n const { router: noRulesRouter, exits: noRulesExits } =\n createWaitForResponseRouter(\n [], // No user rules\n existingCategories,\n existingExits,\n [] // No cases\n );\n\n const router: any = {\n ...noRulesRouter,\n cases: [] // Clear all cases when no rules\n };\n\n // Only set result_name if provided\n if (formData.result_name && formData.result_name.trim() !== '') {\n router.result_name = formData.result_name.trim();\n }\n\n // Build wait configuration based on form data\n const waitConfig: any = {\n type: 'msg'\n };\n\n // Add timeout if enabled\n if (formData.timeout_enabled) {\n // Extract timeout value (handle both string and object formats)\n let timeoutSeconds;\n\n if (formData.timeout_duration) {\n if (\n Array.isArray(formData.timeout_duration) &&\n formData.timeout_duration.length > 0\n ) {\n // Handle array of selected options (multi-select behavior)\n timeoutSeconds = parseInt(formData.timeout_duration[0].value, 10);\n } else if (typeof formData.timeout_duration === 'string') {\n timeoutSeconds = parseInt(formData.timeout_duration, 10);\n } else if (\n formData.timeout_duration &&\n typeof formData.timeout_duration === 'object' &&\n formData.timeout_duration.value\n ) {\n timeoutSeconds = parseInt(formData.timeout_duration.value, 10);\n } else {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n } else {\n // No duration selected, use default\n timeoutSeconds = 300; // Default to 5 minutes\n }\n\n // Validate that we got a valid number\n if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n\n // Find the \"No Response\" category (should exist now)\n const noResponseCategory = router.categories.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n if (noResponseCategory) {\n waitConfig.timeout = {\n seconds: timeoutSeconds,\n category_uuid: noResponseCategory.uuid\n };\n }\n }\n\n router.wait = waitConfig;\n\n return {\n ...originalNode,\n router,\n exits: noRulesExits\n };\n }\n\n // Get existing router data for preservation\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Create router and exits using existing data when possible\n const { router, exits } = createWaitForResponseRouter(\n userRules,\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Build final router with wait configuration and result_name\n const finalRouter: any = {\n ...router\n };\n\n // Only set result_name if provided\n if (formData.result_name && formData.result_name.trim() !== '') {\n finalRouter.result_name = formData.result_name.trim();\n }\n\n // Build wait configuration based on form data\n const waitConfig: any = {\n type: 'msg'\n };\n\n try {\n // Handle timeout configuration\n if (formData.timeout_enabled) {\n // Extract timeout value (handle both string and object formats)\n let timeoutSeconds;\n\n if (formData.timeout_duration) {\n try {\n timeoutSeconds = parseInt(formData.timeout_duration[0].value, 10);\n } catch (e) {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n }\n\n // Find or create the \"No Response\" category\n const existingNoResponseCategory =\n originalNode.router?.categories?.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n const noResponseCategory = existingNoResponseCategory || {\n uuid: generateUUID(),\n name: 'No Response',\n exit_uuid: generateUUID()\n };\n\n waitConfig.timeout = {\n seconds: timeoutSeconds,\n category_uuid: noResponseCategory.uuid\n };\n\n // Ensure No Response category and exit exist\n if (\n !router.categories?.some((cat: any) => cat.name === 'No Response')\n ) {\n router.categories = router.categories || [];\n router.categories.push(noResponseCategory);\n\n // Add corresponding exit if it doesn't exist\n if (\n !exits.some(\n (exit: any) => exit.uuid === noResponseCategory.exit_uuid\n )\n ) {\n const noResponseExit = {\n uuid: noResponseCategory.exit_uuid,\n destination_uuid: existingNoResponseCategory?.exit_uuid\n ? originalNode.exits?.find(\n (exit) => exit.uuid === existingNoResponseCategory.exit_uuid\n )?.destination_uuid || null\n : null\n };\n exits.push(noResponseExit);\n }\n }\n } else {\n // Remove \"No Response\" category if timeout is disabled\n if (router.categories) {\n const noResponseCategoryIndex = router.categories.findIndex(\n (cat: any) => cat.name === 'No Response'\n );\n if (noResponseCategoryIndex !== -1) {\n const noResponseCategory =\n router.categories[noResponseCategoryIndex];\n\n // Remove the category\n router.categories.splice(noResponseCategoryIndex, 1);\n\n // Remove corresponding exit\n const exitIndex = exits.findIndex(\n (exit: any) => exit.uuid === noResponseCategory.exit_uuid\n );\n if (exitIndex !== -1) {\n exits.splice(exitIndex, 1);\n }\n }\n }\n }\n } catch (error) {\n console.error('Error processing timeout configuration:', error);\n // Continue without timeout in case of error\n }\n\n finalRouter.wait = waitConfig;\n return {\n ...originalNode,\n router: finalRouter,\n exits: exits\n };\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -0,0 +1,393 @@
1
+ import { snapToGrid } from './utils';
2
+ const VERTICAL_GAP = 80;
3
+ const HORIZONTAL_GAP = 60;
4
+ const STICKY_GAP = 20;
5
+ const MAX_WIDTH = 1200;
6
+ /**
7
+ * Calculates a layered layout for a flow, placing the start node at the
8
+ * upper-left and arranging the flow downward. Sibling nodes at splits
9
+ * share the same horizontal plane.
10
+ */
11
+ export function calculateLayeredLayout(nodes, nodeUIs, startNodeUuid, getNodeSize) {
12
+ if (nodes.length === 0)
13
+ return {};
14
+ const nodeSet = new Set(nodes.map((n) => n.uuid));
15
+ // Build deduplicated adjacency lists
16
+ const children = new Map();
17
+ const parents = new Map();
18
+ for (const node of nodes) {
19
+ const seen = new Set();
20
+ const childUuids = [];
21
+ for (const exit of node.exits) {
22
+ if (exit.destination_uuid &&
23
+ nodeSet.has(exit.destination_uuid) &&
24
+ !seen.has(exit.destination_uuid)) {
25
+ seen.add(exit.destination_uuid);
26
+ childUuids.push(exit.destination_uuid);
27
+ const p = parents.get(exit.destination_uuid) || [];
28
+ p.push(node.uuid);
29
+ parents.set(exit.destination_uuid, p);
30
+ }
31
+ }
32
+ children.set(node.uuid, childUuids);
33
+ }
34
+ // Find back-edges via DFS so we can ignore cycles during layering
35
+ const backEdges = findBackEdges(startNodeUuid, children);
36
+ // Assign layers using longest-path on the DAG (ignoring back-edges)
37
+ const layers = assignLayers(startNodeUuid, nodes, children, parents, backEdges);
38
+ // Group nodes by layer
39
+ const layerGroups = new Map();
40
+ for (const [uuid, layer] of layers) {
41
+ const group = layerGroups.get(layer) || [];
42
+ group.push(uuid);
43
+ layerGroups.set(layer, group);
44
+ }
45
+ // Order nodes within each layer using barycenter heuristic
46
+ const sortedLayers = Array.from(layerGroups.keys()).sort((a, b) => a - b);
47
+ orderNodesInLayers(sortedLayers, layerGroups, parents, layers);
48
+ // Gather sizes
49
+ const sizes = new Map();
50
+ for (const node of nodes) {
51
+ sizes.set(node.uuid, getNodeSize(node.uuid));
52
+ }
53
+ // Compute positions
54
+ return computePositions(sortedLayers, layerGroups, sizes, parents, layers, startNodeUuid);
55
+ }
56
+ /**
57
+ * Finds back-edges (cycle-forming edges) via DFS from the start node.
58
+ * Returns a set of "parentUuid->childUuid" strings representing edges to ignore.
59
+ */
60
+ function findBackEdges(startNodeUuid, children) {
61
+ const backEdges = new Set();
62
+ const visiting = new Set(); // currently on the DFS stack
63
+ const visited = new Set(); // fully processed
64
+ function dfs(node) {
65
+ visiting.add(node);
66
+ visited.add(node);
67
+ for (const child of children.get(node) || []) {
68
+ if (visiting.has(child)) {
69
+ backEdges.add(`${node}->${child}`);
70
+ }
71
+ else if (!visited.has(child)) {
72
+ dfs(child);
73
+ }
74
+ }
75
+ visiting.delete(node);
76
+ }
77
+ dfs(startNodeUuid);
78
+ return backEdges;
79
+ }
80
+ /**
81
+ * Assigns layers using topological processing order on the DAG
82
+ * (back-edges removed). Each node's layer = max(parent layers) + 1,
83
+ * giving the longest-path assignment so merge nodes sit below all parents.
84
+ */
85
+ function assignLayers(startNodeUuid, nodes, children, parents, backEdges) {
86
+ const layers = new Map();
87
+ layers.set(startNodeUuid, 0);
88
+ // Build forward in-degree (ignoring back-edges) for topological processing
89
+ const inDegree = new Map();
90
+ for (const node of nodes) {
91
+ inDegree.set(node.uuid, 0);
92
+ }
93
+ for (const [parent, childList] of children) {
94
+ for (const child of childList) {
95
+ if (!backEdges.has(`${parent}->${child}`)) {
96
+ inDegree.set(child, (inDegree.get(child) || 0) + 1);
97
+ }
98
+ }
99
+ }
100
+ // Process nodes in topological order (Kahn's algorithm)
101
+ // Start with nodes that have no forward in-edges
102
+ const queue = [];
103
+ for (const [uuid, deg] of inDegree) {
104
+ if (deg === 0) {
105
+ queue.push(uuid);
106
+ if (!layers.has(uuid)) {
107
+ layers.set(uuid, 0);
108
+ }
109
+ }
110
+ }
111
+ while (queue.length > 0) {
112
+ const current = queue.shift();
113
+ const currentLayer = layers.get(current);
114
+ for (const child of children.get(current) || []) {
115
+ if (backEdges.has(`${current}->${child}`))
116
+ continue;
117
+ // Longest path: child layer = max of all parent layers + 1
118
+ const newLayer = currentLayer + 1;
119
+ if (!layers.has(child) || newLayer > layers.get(child)) {
120
+ layers.set(child, newLayer);
121
+ }
122
+ // Decrement in-degree; enqueue when all forward parents processed
123
+ const remaining = inDegree.get(child) - 1;
124
+ inDegree.set(child, remaining);
125
+ if (remaining === 0) {
126
+ queue.push(child);
127
+ }
128
+ }
129
+ }
130
+ // Handle unreachable nodes (not reachable from start)
131
+ const unreachable = nodes.filter((n) => !layers.has(n.uuid));
132
+ if (unreachable.length > 0) {
133
+ const maxLayer = Math.max(...Array.from(layers.values()), -1);
134
+ let unreachableLayer = maxLayer + 2;
135
+ for (const node of unreachable) {
136
+ layers.set(node.uuid, unreachableLayer);
137
+ unreachableLayer++;
138
+ }
139
+ }
140
+ return layers;
141
+ }
142
+ /**
143
+ * Orders nodes within each layer using a barycenter heuristic:
144
+ * each node is positioned based on the average index of its parents
145
+ * in layers above.
146
+ */
147
+ function orderNodesInLayers(sortedLayers, layerGroups, parents, layers) {
148
+ const indexInLayer = new Map();
149
+ for (const layer of sortedLayers) {
150
+ const group = layerGroups.get(layer);
151
+ if (layer === sortedLayers[0]) {
152
+ group.forEach((uuid, idx) => indexInLayer.set(uuid, idx));
153
+ continue;
154
+ }
155
+ const barycenters = group.map((uuid) => {
156
+ // Only consider parents that are in layers above this one
157
+ const nodeParents = (parents.get(uuid) || []).filter((p) => {
158
+ const pl = layers.get(p);
159
+ return pl !== undefined && pl < layer;
160
+ });
161
+ if (nodeParents.length === 0) {
162
+ return { uuid, value: Infinity };
163
+ }
164
+ const sum = nodeParents.reduce((acc, p) => {
165
+ var _a;
166
+ return acc + ((_a = indexInLayer.get(p)) !== null && _a !== void 0 ? _a : 0);
167
+ }, 0);
168
+ return { uuid, value: sum / nodeParents.length };
169
+ });
170
+ barycenters.sort((a, b) => a.value - b.value);
171
+ const sorted = barycenters.map((b) => b.uuid);
172
+ layerGroups.set(layer, sorted);
173
+ sorted.forEach((uuid, idx) => indexInLayer.set(uuid, idx));
174
+ }
175
+ }
176
+ /**
177
+ * Splits a layer's nodes into sub-rows that each fit within MAX_WIDTH.
178
+ */
179
+ function splitIntoRows(group, sizes) {
180
+ var _a;
181
+ const rows = [];
182
+ let currentRow = [];
183
+ let currentWidth = 0;
184
+ for (const uuid of group) {
185
+ const nodeWidth = ((_a = sizes.get(uuid)) === null || _a === void 0 ? void 0 : _a.width) || 200;
186
+ const additionalWidth = currentRow.length > 0 ? HORIZONTAL_GAP + nodeWidth : nodeWidth;
187
+ if (currentRow.length > 0 && currentWidth + additionalWidth > MAX_WIDTH) {
188
+ rows.push(currentRow);
189
+ currentRow = [uuid];
190
+ currentWidth = nodeWidth;
191
+ }
192
+ else {
193
+ currentRow.push(uuid);
194
+ currentWidth += additionalWidth;
195
+ }
196
+ }
197
+ if (currentRow.length > 0) {
198
+ rows.push(currentRow);
199
+ }
200
+ return rows;
201
+ }
202
+ /**
203
+ * Computes pixel positions for each node. Each node's ideal X is centered
204
+ * under its parent(s), with overlap resolution to prevent collisions.
205
+ * Layers that exceed MAX_WIDTH are split into multiple rows.
206
+ */
207
+ function computePositions(sortedLayers, layerGroups, sizes, parents, layers, startNodeUuid) {
208
+ var _a, _b, _c, _d;
209
+ const positions = {};
210
+ let currentTop = 0;
211
+ for (const layer of sortedLayers) {
212
+ const group = layerGroups.get(layer);
213
+ const subRows = splitIntoRows(group, sizes);
214
+ for (const subRow of subRows) {
215
+ const top = snapToGrid(currentTop);
216
+ if (layer === sortedLayers[0]) {
217
+ // First layer: start node at top, others nudged down two grid squares
218
+ let x = 0;
219
+ for (const uuid of subRow) {
220
+ const nodeTop = uuid === startNodeUuid ? top : top + 40;
221
+ positions[uuid] = { left: snapToGrid(x), top: nodeTop };
222
+ x += (((_a = sizes.get(uuid)) === null || _a === void 0 ? void 0 : _a.width) || 200) + HORIZONTAL_GAP;
223
+ }
224
+ }
225
+ else {
226
+ // Compute total width of this sub-row
227
+ let totalWidth = 0;
228
+ for (const uuid of subRow) {
229
+ totalWidth += ((_b = sizes.get(uuid)) === null || _b === void 0 ? void 0 : _b.width) || 200;
230
+ }
231
+ totalWidth += HORIZONTAL_GAP * (subRow.length - 1);
232
+ // Find the center point to place this sub-row under: midpoint of
233
+ // the span of all parent centers for nodes in this sub-row
234
+ const parentCenters = [];
235
+ for (const uuid of subRow) {
236
+ const nodeParents = (parents.get(uuid) || []).filter((p) => {
237
+ const pl = layers.get(p);
238
+ return pl !== undefined && pl < layer;
239
+ });
240
+ for (const pUuid of nodeParents) {
241
+ const parentPos = positions[pUuid];
242
+ if (parentPos) {
243
+ const parentWidth = ((_c = sizes.get(pUuid)) === null || _c === void 0 ? void 0 : _c.width) || 200;
244
+ parentCenters.push(parentPos.left + parentWidth / 2);
245
+ }
246
+ }
247
+ }
248
+ // Center the sub-row under the parent span, anchored left if not enough room
249
+ let rowLeft;
250
+ if (parentCenters.length > 0) {
251
+ const spanCenter = (Math.min(...parentCenters) + Math.max(...parentCenters)) / 2;
252
+ rowLeft = Math.max(0, spanCenter - totalWidth / 2);
253
+ }
254
+ else {
255
+ rowLeft = 0;
256
+ }
257
+ // Place nodes left-to-right starting from rowLeft
258
+ let x = rowLeft;
259
+ for (const uuid of subRow) {
260
+ const nodeWidth = ((_d = sizes.get(uuid)) === null || _d === void 0 ? void 0 : _d.width) || 200;
261
+ positions[uuid] = { left: snapToGrid(x), top };
262
+ x = snapToGrid(x) + nodeWidth + HORIZONTAL_GAP;
263
+ }
264
+ }
265
+ // Advance past this sub-row
266
+ const maxHeight = Math.max(...subRow.map((uuid) => { var _a; return ((_a = sizes.get(uuid)) === null || _a === void 0 ? void 0 : _a.height) || 100; }));
267
+ currentTop = top + maxHeight + VERTICAL_GAP;
268
+ }
269
+ }
270
+ // Shift everything so the start node is at (0, 0)
271
+ const startPos = positions[startNodeUuid];
272
+ if (startPos) {
273
+ const offsetX = startPos.left;
274
+ const offsetY = startPos.top;
275
+ for (const uuid of Object.keys(positions)) {
276
+ positions[uuid] = {
277
+ left: snapToGrid(Math.max(0, positions[uuid].left - offsetX)),
278
+ top: snapToGrid(Math.max(0, positions[uuid].top - offsetY))
279
+ };
280
+ }
281
+ }
282
+ return positions;
283
+ }
284
+ /**
285
+ * Places sticky notes next to the node they were closest to before reflow.
286
+ * If a sticky was to the left of the start node, it is placed to the right instead.
287
+ */
288
+ export function placeStickyNotes(stickies, oldNodePositions, newNodePositions, nodeSizes, stickySizes, startNodeUuid) {
289
+ const stickyPositions = {};
290
+ const nodeUuids = Object.keys(newNodePositions);
291
+ if (nodeUuids.length === 0)
292
+ return stickyPositions;
293
+ // For each sticky, find the closest node based on pre-reflow positions
294
+ const stickyToNode = new Map();
295
+ const nodeStickies = new Map();
296
+ for (const [stickyUuid, sticky] of Object.entries(stickies)) {
297
+ if (!sticky.position)
298
+ continue;
299
+ const sx = sticky.position.left;
300
+ const sy = sticky.position.top;
301
+ let closestNode = nodeUuids[0];
302
+ let closestDist = Infinity;
303
+ for (const nodeUuid of nodeUuids) {
304
+ const np = oldNodePositions[nodeUuid];
305
+ if (!np)
306
+ continue;
307
+ const dx = sx - np.left;
308
+ const dy = sy - np.top;
309
+ const dist = dx * dx + dy * dy;
310
+ if (dist < closestDist) {
311
+ closestDist = dist;
312
+ closestNode = nodeUuid;
313
+ }
314
+ }
315
+ stickyToNode.set(stickyUuid, closestNode);
316
+ // Was the sticky to the left of the node?
317
+ const nodePos = oldNodePositions[closestNode];
318
+ const wasLeft = nodePos ? sx < nodePos.left : false;
319
+ const list = nodeStickies.get(closestNode) || [];
320
+ list.push({ uuid: stickyUuid, wasLeft });
321
+ nodeStickies.set(closestNode, list);
322
+ }
323
+ // Place stickies next to their associated nodes
324
+ // Collect all placed rectangles (nodes + stickies) for collision avoidance
325
+ const placed = [];
326
+ // Add all nodes to placed rectangles
327
+ for (const nodeUuid of nodeUuids) {
328
+ const pos = newNodePositions[nodeUuid];
329
+ const size = nodeSizes.get(nodeUuid) || { width: 200, height: 100 };
330
+ placed.push({
331
+ left: pos.left,
332
+ top: pos.top,
333
+ width: size.width,
334
+ height: size.height
335
+ });
336
+ }
337
+ for (const [nodeUuid, stickyList] of nodeStickies) {
338
+ const nodePos = newNodePositions[nodeUuid];
339
+ if (!nodePos)
340
+ continue;
341
+ const nodeSize = nodeSizes.get(nodeUuid) || { width: 200, height: 100 };
342
+ for (const { uuid: stickyUuid, wasLeft } of stickyList) {
343
+ const stickySize = stickySizes.get(stickyUuid) || {
344
+ width: 182,
345
+ height: 100
346
+ };
347
+ // Determine placement side: right of node if it's the start node and sticky
348
+ // was to the left, otherwise prefer the side it was on originally
349
+ const placeRight = (nodeUuid === startNodeUuid && wasLeft) || !wasLeft;
350
+ let candidateLeft;
351
+ if (placeRight) {
352
+ candidateLeft = nodePos.left + nodeSize.width + STICKY_GAP;
353
+ }
354
+ else {
355
+ candidateLeft = nodePos.left - stickySize.width - STICKY_GAP;
356
+ }
357
+ let candidateTop = nodePos.top;
358
+ // Snap and clamp
359
+ candidateLeft = snapToGrid(Math.max(0, candidateLeft));
360
+ candidateTop = snapToGrid(Math.max(0, candidateTop));
361
+ // Nudge down if colliding with any placed rectangle
362
+ let maxAttempts = 50;
363
+ while (maxAttempts-- > 0 &&
364
+ collidesWithAny(candidateLeft, candidateTop, stickySize.width, stickySize.height, placed)) {
365
+ candidateTop = snapToGrid(candidateTop + STICKY_GAP);
366
+ }
367
+ stickyPositions[stickyUuid] = {
368
+ left: candidateLeft,
369
+ top: candidateTop
370
+ };
371
+ // Add this sticky to placed rectangles
372
+ placed.push({
373
+ left: candidateLeft,
374
+ top: candidateTop,
375
+ width: stickySize.width,
376
+ height: stickySize.height
377
+ });
378
+ }
379
+ }
380
+ return stickyPositions;
381
+ }
382
+ function collidesWithAny(left, top, width, height, placed) {
383
+ for (const r of placed) {
384
+ if (left < r.left + r.width + STICKY_GAP &&
385
+ left + width + STICKY_GAP > r.left &&
386
+ top < r.top + r.height + STICKY_GAP &&
387
+ top + height + STICKY_GAP > r.top) {
388
+ return true;
389
+ }
390
+ }
391
+ return false;
392
+ }
393
+ //# sourceMappingURL=reflow.js.map