@nyaruka/temba-components 0.129.1 → 0.129.3

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 (583) hide show
  1. package/.github/workflows/build.yml +6 -5
  2. package/.github/workflows/coverage.yml +80 -0
  3. package/CHANGELOG.md +32 -0
  4. package/README.md +6 -0
  5. package/check-coverage.js +133 -0
  6. package/demo/components/alert/example.html +71 -0
  7. package/demo/components/button/example.html +167 -0
  8. package/demo/{chart → components/chart}/example.html +3 -3
  9. package/demo/components/chart/horizontal-demo.html +160 -0
  10. package/demo/components/checkbox/example.html +68 -0
  11. package/demo/components/compose/example.html +69 -0
  12. package/demo/components/datepicker/example.html +3 -3
  13. package/demo/components/datepicker/range-picker-demo.html +2 -2
  14. package/demo/{dialog → components/dialog}/example.html +3 -3
  15. package/demo/components/dropdown/example.html +95 -0
  16. package/demo/{flow → components/flow}/example.html +1 -1
  17. package/demo/{misc → components/misc}/example.html +3 -3
  18. package/demo/components/progress/example.html +62 -0
  19. package/demo/components/select/drag-and-drop.html +162 -0
  20. package/demo/components/select/example.html +76 -0
  21. package/demo/components/select/multi.html +72 -0
  22. package/demo/components/slider/example.html +55 -0
  23. package/demo/{sortable-list → components/sortable-list}/example.html +3 -3
  24. package/demo/components/tabs/example.html +91 -0
  25. package/demo/{textinput → components/textinput}/completion.html +3 -3
  26. package/demo/components/textinput/example.html +141 -0
  27. package/demo/{webchat → components/webchat}/example.html +3 -3
  28. package/demo/data/flows/sample-flow.json +107 -100
  29. package/demo/index.html +21 -21
  30. package/demo/static/css/styles.css +253 -0
  31. package/demo/sticky-note-demo.html +88 -85
  32. package/demo/styles.css +24 -0
  33. package/dist/locales/es.js +5 -5
  34. package/dist/locales/es.js.map +1 -1
  35. package/dist/locales/fr.js +5 -5
  36. package/dist/locales/fr.js.map +1 -1
  37. package/dist/locales/locale-codes.js +2 -11
  38. package/dist/locales/locale-codes.js.map +1 -1
  39. package/dist/locales/pt.js +5 -5
  40. package/dist/locales/pt.js.map +1 -1
  41. package/dist/temba-components.js +893 -476
  42. package/dist/temba-components.js.map +1 -1
  43. package/generate-coverage-badge.sh +69 -0
  44. package/out-tsc/src/{vectoricon/index.js → Icons.js} +1 -1
  45. package/out-tsc/src/Icons.js.map +1 -0
  46. package/out-tsc/src/display/Alert.js.map +1 -0
  47. package/out-tsc/src/display/Anchor.js.map +1 -0
  48. package/out-tsc/src/display/Button.js.map +1 -0
  49. package/out-tsc/src/{charcount → display}/CharCount.js +159 -2
  50. package/out-tsc/src/display/CharCount.js.map +1 -0
  51. package/out-tsc/src/display/Chat.js.map +1 -0
  52. package/out-tsc/src/display/ContactName.js.map +1 -0
  53. package/out-tsc/src/display/ContactUrn.js.map +1 -0
  54. package/out-tsc/src/display/Dropdown.js.map +1 -0
  55. package/out-tsc/src/{vectoricon/VectorIcon.js → display/Icon.js} +2 -2
  56. package/out-tsc/src/display/Icon.js.map +1 -0
  57. package/out-tsc/src/display/Label.js.map +1 -0
  58. package/out-tsc/src/{leafletmap → display}/LeafletMap.js +16 -1
  59. package/out-tsc/src/display/LeafletMap.js.map +1 -0
  60. package/out-tsc/src/display/Lightbox.js.map +1 -0
  61. package/out-tsc/src/{loading → display}/Loading.js.map +1 -1
  62. package/out-tsc/src/{options → display}/Options.js.map +1 -1
  63. package/out-tsc/src/display/ProgressBar.js.map +1 -0
  64. package/out-tsc/src/display/TembaDate.js.map +1 -0
  65. package/out-tsc/src/display/TembaUser.js.map +1 -0
  66. package/out-tsc/src/display/Thumbnail.js.map +1 -0
  67. package/out-tsc/src/{tip → display}/Tip.js +1 -2
  68. package/out-tsc/src/display/Tip.js.map +1 -0
  69. package/out-tsc/src/display/Toast.js.map +1 -0
  70. package/out-tsc/src/display/sms/gsmsplitter.js.map +1 -0
  71. package/out-tsc/src/display/sms/gsmvalidator.js.map +1 -0
  72. package/out-tsc/src/display/sms/index.js.map +1 -0
  73. package/out-tsc/src/display/sms/unicodesplitter.js.map +1 -0
  74. package/out-tsc/src/events.js +2 -0
  75. package/out-tsc/src/events.js.map +1 -0
  76. package/out-tsc/src/excellent/ExcellentParser.js.map +1 -0
  77. package/out-tsc/src/excellent/helpers.js.map +1 -0
  78. package/out-tsc/src/flow/Editor.js +533 -140
  79. package/out-tsc/src/flow/Editor.js.map +1 -1
  80. package/out-tsc/src/flow/EditorNode.js +287 -20
  81. package/out-tsc/src/flow/EditorNode.js.map +1 -1
  82. package/out-tsc/src/flow/Plumber.js +154 -74
  83. package/out-tsc/src/flow/Plumber.js.map +1 -1
  84. package/out-tsc/src/flow/StickyNote.js +153 -9
  85. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  86. package/out-tsc/src/flow/config.js +88 -18
  87. package/out-tsc/src/flow/config.js.map +1 -1
  88. package/out-tsc/src/flow/render.js +327 -10
  89. package/out-tsc/src/flow/render.js.map +1 -1
  90. package/out-tsc/src/{checkbox → form}/Checkbox.js +2 -2
  91. package/out-tsc/src/form/Checkbox.js.map +1 -0
  92. package/out-tsc/src/{colorpicker → form}/ColorPicker.js +1 -1
  93. package/out-tsc/src/form/ColorPicker.js.map +1 -0
  94. package/out-tsc/src/{completion → form}/Completion.js +2 -2
  95. package/out-tsc/src/form/Completion.js.map +1 -0
  96. package/out-tsc/src/{compose → form}/Compose.js +1 -1
  97. package/out-tsc/src/form/Compose.js.map +1 -0
  98. package/out-tsc/src/{contactsearch → form}/ContactSearch.js +2 -2
  99. package/out-tsc/src/form/ContactSearch.js.map +1 -0
  100. package/out-tsc/src/form/CroppieCSS.js.map +1 -0
  101. package/out-tsc/src/{datepicker → form}/DatePicker.js +1 -1
  102. package/out-tsc/src/form/DatePicker.js.map +1 -0
  103. package/out-tsc/src/{FormElement.js → form/FormElement.js} +1 -1
  104. package/out-tsc/src/form/FormElement.js.map +1 -0
  105. package/out-tsc/src/form/FormField.js.map +1 -0
  106. package/out-tsc/src/{imagepicker → form}/ImagePicker.js +2 -2
  107. package/out-tsc/src/form/ImagePicker.js.map +1 -0
  108. package/out-tsc/src/{mediapicker → form}/MediaPicker.js +1 -1
  109. package/out-tsc/src/form/MediaPicker.js.map +1 -0
  110. package/out-tsc/src/{datepicker → form}/RangePicker.js +3 -2
  111. package/out-tsc/src/form/RangePicker.js.map +1 -0
  112. package/out-tsc/src/{slider → form}/TembaSlider.js +1 -1
  113. package/out-tsc/src/form/TembaSlider.js.map +1 -0
  114. package/out-tsc/src/{templates → form}/TemplateEditor.js +1 -1
  115. package/out-tsc/src/form/TemplateEditor.js.map +1 -0
  116. package/out-tsc/src/{textinput → form}/TextInput.js +3 -3
  117. package/out-tsc/src/form/TextInput.js.map +1 -0
  118. package/out-tsc/src/{omnibox → form/select}/Omnibox.js +2 -2
  119. package/out-tsc/src/form/select/Omnibox.js.map +1 -0
  120. package/out-tsc/src/{select → form/select}/PopupSelect.js +1 -1
  121. package/out-tsc/src/form/select/PopupSelect.js.map +1 -0
  122. package/out-tsc/src/{select → form/select}/Select.js +86 -87
  123. package/out-tsc/src/form/select/Select.js.map +1 -0
  124. package/out-tsc/src/{select → form/select}/UserSelect.js +1 -1
  125. package/out-tsc/src/form/select/UserSelect.js.map +1 -0
  126. package/out-tsc/src/{select → form/select}/WorkspaceSelect.js +1 -1
  127. package/out-tsc/src/form/select/WorkspaceSelect.js.map +1 -0
  128. package/out-tsc/src/interfaces.js +1 -0
  129. package/out-tsc/src/interfaces.js.map +1 -1
  130. package/out-tsc/src/layout/Dialog.js.map +1 -0
  131. package/out-tsc/src/layout/Mask.js.map +1 -0
  132. package/out-tsc/src/{dialog → layout}/Modax.js.map +1 -1
  133. package/out-tsc/src/layout/Resizer.js.map +1 -0
  134. package/out-tsc/src/layout/Tab.js.map +1 -0
  135. package/out-tsc/src/layout/TabPane.js.map +1 -0
  136. package/out-tsc/src/list/NotificationList.js +1 -1
  137. package/out-tsc/src/list/NotificationList.js.map +1 -1
  138. package/out-tsc/src/list/RunList.js +1 -1
  139. package/out-tsc/src/list/RunList.js.map +1 -1
  140. package/out-tsc/src/list/ShortcutList.js.map +1 -1
  141. package/out-tsc/src/list/TembaMenu.js +1 -1
  142. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  143. package/out-tsc/src/list/TicketList.js +1 -1
  144. package/out-tsc/src/list/TicketList.js.map +1 -1
  145. package/out-tsc/src/{aliaseditor → live}/AliasEditor.js +1 -1
  146. package/out-tsc/src/live/AliasEditor.js.map +1 -0
  147. package/out-tsc/src/{contacts → live}/ContactBadges.js +1 -1
  148. package/out-tsc/src/live/ContactBadges.js.map +1 -0
  149. package/out-tsc/src/{contacts → live}/ContactChat.js +79 -3
  150. package/out-tsc/src/live/ContactChat.js.map +1 -0
  151. package/out-tsc/src/{contacts → live}/ContactDetails.js +1 -1
  152. package/out-tsc/src/live/ContactDetails.js.map +1 -0
  153. package/out-tsc/src/{contacts → live}/ContactFieldEditor.js +2 -2
  154. package/out-tsc/src/live/ContactFieldEditor.js.map +1 -0
  155. package/out-tsc/src/live/ContactFields.js.map +1 -0
  156. package/out-tsc/src/live/ContactNameFetch.js.map +1 -0
  157. package/out-tsc/src/{contacts → live}/ContactNotepad.js +1 -1
  158. package/out-tsc/src/{contacts → live}/ContactNotepad.js.map +1 -1
  159. package/out-tsc/src/{contacts → live}/ContactPending.js +1 -1
  160. package/out-tsc/src/live/ContactPending.js.map +1 -0
  161. package/out-tsc/src/live/ContactStoreElement.js.map +1 -0
  162. package/out-tsc/src/live/FieldManager.js.map +1 -0
  163. package/out-tsc/src/live/StartProgress.js.map +1 -0
  164. package/out-tsc/src/{chart → live}/TembaChart.js +5 -1
  165. package/out-tsc/src/live/TembaChart.js.map +1 -0
  166. package/out-tsc/src/locales/es.js +5 -5
  167. package/out-tsc/src/locales/es.js.map +1 -1
  168. package/out-tsc/src/locales/fr.js +5 -5
  169. package/out-tsc/src/locales/fr.js.map +1 -1
  170. package/out-tsc/src/locales/locale-codes.js +2 -11
  171. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  172. package/out-tsc/src/locales/pt.js +5 -5
  173. package/out-tsc/src/locales/pt.js.map +1 -1
  174. package/out-tsc/src/store/AppState.js +54 -24
  175. package/out-tsc/src/store/AppState.js.map +1 -1
  176. package/out-tsc/src/store/Store.js +1 -1
  177. package/out-tsc/src/store/Store.js.map +1 -1
  178. package/out-tsc/src/{utils/index.js → utils.js} +22 -1
  179. package/out-tsc/src/utils.js.map +1 -0
  180. package/out-tsc/src/webchat/WebChat.js +1 -1
  181. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  182. package/out-tsc/temba-components.js +2 -2
  183. package/out-tsc/temba-components.js.map +1 -1
  184. package/out-tsc/temba-modules.js +54 -54
  185. package/out-tsc/temba-modules.js.map +1 -1
  186. package/out-tsc/temba-webchat.js +2 -2
  187. package/out-tsc/temba-webchat.js.map +1 -1
  188. package/out-tsc/test/temba-alert.test.js +1 -1
  189. package/out-tsc/test/temba-alert.test.js.map +1 -1
  190. package/out-tsc/test/temba-appstate-language.test.js +90 -0
  191. package/out-tsc/test/temba-appstate-language.test.js.map +1 -1
  192. package/out-tsc/test/temba-charcount.test.js.map +1 -1
  193. package/out-tsc/test/temba-chart.test.js +1 -1
  194. package/out-tsc/test/temba-chart.test.js.map +1 -1
  195. package/out-tsc/test/temba-checkbox.test.js.map +1 -1
  196. package/out-tsc/test/temba-color-picker.test.js +1 -1
  197. package/out-tsc/test/temba-color-picker.test.js.map +1 -1
  198. package/out-tsc/test/temba-completion.test.js +1 -1
  199. package/out-tsc/test/temba-completion.test.js.map +1 -1
  200. package/out-tsc/test/temba-compose.test.js +1 -1
  201. package/out-tsc/test/temba-compose.test.js.map +1 -1
  202. package/out-tsc/test/temba-contact-badges.test.js +1 -1
  203. package/out-tsc/test/temba-contact-badges.test.js.map +1 -1
  204. package/out-tsc/test/temba-contact-chat.test.js +3 -1
  205. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  206. package/out-tsc/test/temba-contact-details.test.js +1 -1
  207. package/out-tsc/test/temba-contact-details.test.js.map +1 -1
  208. package/out-tsc/test/temba-contact-fields.test.js +1 -1
  209. package/out-tsc/test/temba-contact-fields.test.js.map +1 -1
  210. package/out-tsc/test/temba-contact-search.test.js +1 -1
  211. package/out-tsc/test/temba-contact-search.test.js.map +1 -1
  212. package/out-tsc/test/temba-date.test.js +5 -1
  213. package/out-tsc/test/temba-date.test.js.map +1 -1
  214. package/out-tsc/test/temba-datepicker.test.js +1 -1
  215. package/out-tsc/test/temba-datepicker.test.js.map +1 -1
  216. package/out-tsc/test/temba-dialog.test.js +1 -1
  217. package/out-tsc/test/temba-dialog.test.js.map +1 -1
  218. package/out-tsc/test/temba-dropdown.test.js +1 -1
  219. package/out-tsc/test/temba-dropdown.test.js.map +1 -1
  220. package/out-tsc/test/temba-excellent-helpers.test.js +316 -0
  221. package/out-tsc/test/temba-excellent-helpers.test.js.map +1 -0
  222. package/out-tsc/test/temba-field-manager.test.js.map +1 -1
  223. package/out-tsc/test/temba-flow-editor-node.test.js +414 -1
  224. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  225. package/out-tsc/test/temba-flow-editor.test.js +185 -0
  226. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  227. package/out-tsc/test/temba-flow-plumber-connections.test.js +113 -0
  228. package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -0
  229. package/out-tsc/test/temba-flow-plumber.test.js +73 -93
  230. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  231. package/out-tsc/test/temba-flow-render.test.js +624 -1
  232. package/out-tsc/test/temba-flow-render.test.js.map +1 -1
  233. package/out-tsc/test/temba-flow-self-routing.test.js +172 -0
  234. package/out-tsc/test/temba-flow-self-routing.test.js.map +1 -0
  235. package/out-tsc/test/temba-formfield.test.js.map +1 -1
  236. package/out-tsc/test/temba-icon.test.js +1 -1
  237. package/out-tsc/test/temba-icon.test.js.map +1 -1
  238. package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
  239. package/out-tsc/test/temba-label.test.js +1 -1
  240. package/out-tsc/test/temba-label.test.js.map +1 -1
  241. package/out-tsc/test/temba-lightbox.test.js +1 -1
  242. package/out-tsc/test/temba-lightbox.test.js.map +1 -1
  243. package/out-tsc/test/temba-markdown.test.js +127 -0
  244. package/out-tsc/test/temba-markdown.test.js.map +1 -0
  245. package/out-tsc/test/temba-menu.test.js +1 -1
  246. package/out-tsc/test/temba-menu.test.js.map +1 -1
  247. package/out-tsc/test/temba-modax.test.js +1 -1
  248. package/out-tsc/test/temba-modax.test.js.map +1 -1
  249. package/out-tsc/test/temba-modules.test.js +47 -0
  250. package/out-tsc/test/temba-modules.test.js.map +1 -0
  251. package/out-tsc/test/temba-omnibox.test.js +1 -1
  252. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  253. package/out-tsc/test/temba-options.test.js.map +1 -1
  254. package/out-tsc/test/temba-range-picker.test.js +9 -2
  255. package/out-tsc/test/temba-range-picker.test.js.map +1 -1
  256. package/out-tsc/test/temba-rapid-element.test.js +273 -0
  257. package/out-tsc/test/temba-rapid-element.test.js.map +1 -0
  258. package/out-tsc/test/temba-resize-element.test.js +85 -0
  259. package/out-tsc/test/temba-resize-element.test.js.map +1 -0
  260. package/out-tsc/test/temba-select.test.js +2 -2
  261. package/out-tsc/test/temba-select.test.js.map +1 -1
  262. package/out-tsc/test/temba-slider.test.js.map +1 -1
  263. package/out-tsc/test/temba-sticky-note.test.js +194 -0
  264. package/out-tsc/test/temba-sticky-note.test.js.map +1 -0
  265. package/out-tsc/test/temba-template-editor.test.js.map +1 -1
  266. package/out-tsc/test/temba-textinput.test.js +1 -1
  267. package/out-tsc/test/temba-textinput.test.js.map +1 -1
  268. package/out-tsc/test/temba-tip.test.js +1 -1
  269. package/out-tsc/test/temba-tip.test.js.map +1 -1
  270. package/out-tsc/test/temba-toast.test.js +1 -1
  271. package/out-tsc/test/temba-toast.test.js.map +1 -1
  272. package/out-tsc/test/temba-utils-index.test.js +1 -1
  273. package/out-tsc/test/temba-utils-index.test.js.map +1 -1
  274. package/out-tsc/test/temba-utils-uuid.test.js +38 -0
  275. package/out-tsc/test/temba-utils-uuid.test.js.map +1 -0
  276. package/out-tsc/test/temba-webchat.test.js +28 -12
  277. package/out-tsc/test/temba-webchat.test.js.map +1 -1
  278. package/out-tsc/test/utils.test.js +2 -6
  279. package/out-tsc/test/utils.test.js.map +1 -1
  280. package/package.json +18 -9
  281. package/rollup.components.mjs +1 -1
  282. package/screenshots/truth/datepicker/range-picker-all.png +0 -0
  283. package/screenshots/truth/datepicker/range-picker-button-states.png +0 -0
  284. package/screenshots/truth/datepicker/range-picker-default.png +0 -0
  285. package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
  286. package/screenshots/truth/datepicker/range-picker-initial-values.png +0 -0
  287. package/screenshots/truth/datepicker/range-picker-week.png +0 -0
  288. package/screenshots/truth/datepicker/range-picker-year.png +0 -0
  289. package/screenshots/truth/sticky-note/blue-color.png +0 -0
  290. package/screenshots/truth/sticky-note/blue.png +0 -0
  291. package/screenshots/truth/sticky-note/color-picker-expanded.png +0 -0
  292. package/screenshots/truth/sticky-note/default.png +0 -0
  293. package/screenshots/truth/sticky-note/gray-color.png +0 -0
  294. package/screenshots/truth/sticky-note/gray.png +0 -0
  295. package/screenshots/truth/sticky-note/green-color.png +0 -0
  296. package/screenshots/truth/sticky-note/green.png +0 -0
  297. package/screenshots/truth/sticky-note/pink-color.png +0 -0
  298. package/screenshots/truth/sticky-note/pink.png +0 -0
  299. package/screenshots/truth/sticky-note/yellow-color.png +0 -0
  300. package/screenshots/truth/sticky-note/yellow.png +0 -0
  301. package/src/{charcount → display}/CharCount.ts +164 -2
  302. package/src/{vectoricon/VectorIcon.ts → display/Icon.ts} +1 -1
  303. package/src/{leafletmap → display}/LeafletMap.ts +19 -1
  304. package/src/{thumbnail → display}/Thumbnail.ts +1 -1
  305. package/src/{tip → display}/Tip.ts +1 -2
  306. package/src/{contacts/events.ts → events.ts} +1 -64
  307. package/src/flow/Editor.ts +655 -165
  308. package/src/flow/EditorNode.ts +337 -22
  309. package/src/flow/Plumber.ts +186 -79
  310. package/src/flow/StickyNote.ts +165 -9
  311. package/src/flow/config.ts +114 -18
  312. package/src/flow/render.ts +398 -11
  313. package/src/{checkbox → form}/Checkbox.ts +2 -2
  314. package/src/{colorpicker → form}/ColorPicker.ts +2 -2
  315. package/src/{completion → form}/Completion.ts +3 -3
  316. package/src/{compose → form}/Compose.ts +7 -7
  317. package/src/{contactsearch → form}/ContactSearch.ts +6 -6
  318. package/src/{datepicker → form}/DatePicker.ts +1 -1
  319. package/src/{FormElement.ts → form/FormElement.ts} +1 -1
  320. package/src/{imagepicker → form}/ImagePicker.ts +2 -2
  321. package/src/{mediapicker → form}/MediaPicker.ts +1 -1
  322. package/src/{datepicker → form}/RangePicker.ts +3 -2
  323. package/src/{slider → form}/TembaSlider.ts +1 -1
  324. package/src/{templates → form}/TemplateEditor.ts +2 -2
  325. package/src/{textinput → form}/TextInput.ts +5 -5
  326. package/src/{omnibox → form/select}/Omnibox.ts +2 -2
  327. package/src/{select → form/select}/PopupSelect.ts +1 -1
  328. package/src/{select → form/select}/Select.ts +124 -126
  329. package/src/{select → form/select}/UserSelect.ts +1 -1
  330. package/src/{select → form/select}/WorkspaceSelect.ts +1 -1
  331. package/src/interfaces.ts +2 -1
  332. package/src/{dialog → layout}/Dialog.ts +1 -1
  333. package/src/list/NotificationList.ts +2 -2
  334. package/src/list/RunList.ts +3 -3
  335. package/src/list/ShortcutList.ts +1 -1
  336. package/src/list/TembaMenu.ts +2 -2
  337. package/src/list/TicketList.ts +1 -1
  338. package/src/{aliaseditor → live}/AliasEditor.ts +3 -3
  339. package/src/{contacts → live}/ContactBadges.ts +1 -1
  340. package/src/{contacts → live}/ContactChat.ts +118 -8
  341. package/src/{contacts → live}/ContactDetails.ts +1 -1
  342. package/src/{contacts → live}/ContactFieldEditor.ts +4 -4
  343. package/src/{contacts → live}/ContactFields.ts +1 -1
  344. package/src/{contacts → live}/ContactNotepad.ts +1 -1
  345. package/src/{contacts → live}/ContactPending.ts +1 -1
  346. package/src/{chart → live}/TembaChart.ts +5 -2
  347. package/src/locales/es.ts +13 -18
  348. package/src/locales/fr.ts +13 -18
  349. package/src/locales/locale-codes.ts +2 -11
  350. package/src/locales/pt.ts +13 -18
  351. package/src/store/AppState.ts +75 -29
  352. package/src/store/Store.ts +1 -1
  353. package/src/store/flow-definition.d.ts +125 -0
  354. package/src/{utils/index.ts → utils.ts} +26 -10
  355. package/src/webchat/WebChat.ts +1 -1
  356. package/static/css/temba-components.css +1 -0
  357. package/svg.js +1 -4
  358. package/temba-components.ts +2 -2
  359. package/temba-modules.ts +54 -54
  360. package/temba-webchat.ts +2 -2
  361. package/test/temba-alert.test.ts +1 -1
  362. package/test/temba-appstate-language.test.ts +108 -0
  363. package/test/temba-charcount.test.ts +1 -1
  364. package/test/temba-chart.test.ts +1 -1
  365. package/test/temba-checkbox.test.ts +1 -1
  366. package/test/temba-color-picker.test.ts +1 -1
  367. package/test/temba-completion.test.ts +1 -1
  368. package/test/temba-compose.test.ts +1 -1
  369. package/test/temba-contact-badges.test.ts +1 -1
  370. package/test/temba-contact-chat.test.ts +6 -4
  371. package/test/temba-contact-details.test.ts +1 -1
  372. package/test/temba-contact-fields.test.ts +1 -1
  373. package/test/temba-contact-search.test.ts +2 -2
  374. package/test/temba-date.test.ts +8 -3
  375. package/test/temba-datepicker.test.ts +1 -1
  376. package/test/temba-dialog.test.ts +1 -1
  377. package/test/temba-dropdown.test.ts +1 -1
  378. package/test/temba-excellent-helpers.test.ts +417 -0
  379. package/test/temba-field-manager.test.ts +2 -2
  380. package/test/temba-flow-editor-node.test.ts +536 -1
  381. package/test/temba-flow-editor.test.ts +224 -0
  382. package/test/temba-flow-editor.test.ts.backup +563 -0
  383. package/test/temba-flow-plumber-connections.test.ts +142 -0
  384. package/test/temba-flow-plumber.test.ts +83 -120
  385. package/test/temba-flow-render.test.ts +787 -4
  386. package/test/temba-flow-self-routing.test.ts +215 -0
  387. package/test/temba-formfield.test.ts +1 -1
  388. package/test/temba-icon.test.ts +1 -1
  389. package/test/temba-integration-markdown.test.ts +1 -1
  390. package/test/temba-label.test.ts +1 -1
  391. package/test/temba-lightbox.test.ts +1 -1
  392. package/test/temba-markdown.test.ts +162 -0
  393. package/test/temba-menu.test.ts +1 -1
  394. package/test/temba-modax.test.ts +2 -2
  395. package/test/temba-modules.test.ts +56 -0
  396. package/test/temba-omnibox.test.ts +1 -1
  397. package/test/temba-options.test.ts +1 -1
  398. package/test/temba-range-picker.test.ts +17 -2
  399. package/test/temba-rapid-element.test.ts +341 -0
  400. package/test/temba-resize-element.test.ts +104 -0
  401. package/test/temba-select.test.ts +2 -2
  402. package/test/temba-slider.test.ts +1 -1
  403. package/test/temba-sticky-note.test.ts +281 -0
  404. package/test/temba-template-editor.test.ts +1 -1
  405. package/test/temba-textinput.test.ts +1 -1
  406. package/test/temba-tip.test.ts +1 -1
  407. package/test/temba-toast.test.ts +1 -1
  408. package/test/temba-utils-index.test.ts +1 -1
  409. package/test/temba-utils-index.test.ts.backup +1737 -0
  410. package/test/temba-utils-uuid.test.ts +48 -0
  411. package/test/temba-webchat.test.ts +30 -12
  412. package/test/utils.test.ts +5 -9
  413. package/web-dev-server.config.mjs +1 -1
  414. package/demo/alert/example.html +0 -65
  415. package/demo/button/example.html +0 -71
  416. package/demo/chart/horizontal-demo.html +0 -81
  417. package/demo/checkbox/example.html +0 -72
  418. package/demo/compose/example.html +0 -72
  419. package/demo/dropdown/example.html +0 -99
  420. package/demo/progress/example.html +0 -59
  421. package/demo/select/drag-and-drop.html +0 -142
  422. package/demo/select/example.html +0 -82
  423. package/demo/select/multi.html +0 -73
  424. package/demo/slider/example.html +0 -59
  425. package/demo/tabs/example.html +0 -91
  426. package/demo/textinput/example.html +0 -61
  427. package/out-tsc/src/FormElement.js.map +0 -1
  428. package/out-tsc/src/alert/Alert.js.map +0 -1
  429. package/out-tsc/src/aliaseditor/AliasEditor.js.map +0 -1
  430. package/out-tsc/src/anchor/Anchor.js.map +0 -1
  431. package/out-tsc/src/button/Button.js.map +0 -1
  432. package/out-tsc/src/charcount/CharCount.js.map +0 -1
  433. package/out-tsc/src/charcount/helpers.js +0 -159
  434. package/out-tsc/src/charcount/helpers.js.map +0 -1
  435. package/out-tsc/src/chart/TembaChart.js.map +0 -1
  436. package/out-tsc/src/chat/Chat.js.map +0 -1
  437. package/out-tsc/src/checkbox/Checkbox.js.map +0 -1
  438. package/out-tsc/src/colorpicker/ColorPicker.js.map +0 -1
  439. package/out-tsc/src/completion/Completion.js.map +0 -1
  440. package/out-tsc/src/completion/ExcellentParser.js.map +0 -1
  441. package/out-tsc/src/completion/helpers.js.map +0 -1
  442. package/out-tsc/src/compose/Compose.js.map +0 -1
  443. package/out-tsc/src/contacts/ContactBadges.js.map +0 -1
  444. package/out-tsc/src/contacts/ContactChat.js.map +0 -1
  445. package/out-tsc/src/contacts/ContactDetails.js.map +0 -1
  446. package/out-tsc/src/contacts/ContactFieldEditor.js.map +0 -1
  447. package/out-tsc/src/contacts/ContactFields.js.map +0 -1
  448. package/out-tsc/src/contacts/ContactName.js.map +0 -1
  449. package/out-tsc/src/contacts/ContactNameFetch.js.map +0 -1
  450. package/out-tsc/src/contacts/ContactPending.js.map +0 -1
  451. package/out-tsc/src/contacts/ContactStoreElement.js.map +0 -1
  452. package/out-tsc/src/contacts/ContactUrn.js.map +0 -1
  453. package/out-tsc/src/contacts/events.js +0 -65
  454. package/out-tsc/src/contacts/events.js.map +0 -1
  455. package/out-tsc/src/contacts/helpers.js +0 -77
  456. package/out-tsc/src/contacts/helpers.js.map +0 -1
  457. package/out-tsc/src/contactsearch/ContactSearch.js.map +0 -1
  458. package/out-tsc/src/date/TembaDate.js.map +0 -1
  459. package/out-tsc/src/datepicker/DatePicker.js.map +0 -1
  460. package/out-tsc/src/datepicker/RangePicker.js.map +0 -1
  461. package/out-tsc/src/dialog/Dialog.js.map +0 -1
  462. package/out-tsc/src/dropdown/Dropdown.js.map +0 -1
  463. package/out-tsc/src/fields/FieldManager.js.map +0 -1
  464. package/out-tsc/src/formfield/FormField.js.map +0 -1
  465. package/out-tsc/src/imagepicker/CroppieCSS.js.map +0 -1
  466. package/out-tsc/src/imagepicker/ImagePicker.js.map +0 -1
  467. package/out-tsc/src/label/Label.js.map +0 -1
  468. package/out-tsc/src/leafletmap/LeafletMap.js.map +0 -1
  469. package/out-tsc/src/leafletmap/helpers.js +0 -17
  470. package/out-tsc/src/leafletmap/helpers.js.map +0 -1
  471. package/out-tsc/src/lightbox/Lightbox.js.map +0 -1
  472. package/out-tsc/src/mask/Mask.js.map +0 -1
  473. package/out-tsc/src/mediapicker/MediaPicker.js.map +0 -1
  474. package/out-tsc/src/omnibox/Omnibox.js.map +0 -1
  475. package/out-tsc/src/options/helpers.js +0 -28
  476. package/out-tsc/src/options/helpers.js.map +0 -1
  477. package/out-tsc/src/progress/ProgressBar.js.map +0 -1
  478. package/out-tsc/src/progress/StartProgress.js.map +0 -1
  479. package/out-tsc/src/resizer/Resizer.js.map +0 -1
  480. package/out-tsc/src/select/PopupSelect.js.map +0 -1
  481. package/out-tsc/src/select/Select.js.map +0 -1
  482. package/out-tsc/src/select/UserSelect.js.map +0 -1
  483. package/out-tsc/src/select/WorkspaceSelect.js.map +0 -1
  484. package/out-tsc/src/select/helpers.js +0 -1
  485. package/out-tsc/src/select/helpers.js.map +0 -1
  486. package/out-tsc/src/shadowless/Shadowless.js +0 -33
  487. package/out-tsc/src/shadowless/Shadowless.js.map +0 -1
  488. package/out-tsc/src/slider/TembaSlider.js.map +0 -1
  489. package/out-tsc/src/sms/gsmsplitter.js.map +0 -1
  490. package/out-tsc/src/sms/gsmvalidator.js.map +0 -1
  491. package/out-tsc/src/sms/index.js.map +0 -1
  492. package/out-tsc/src/sms/unicodesplitter.js.map +0 -1
  493. package/out-tsc/src/tabpane/Tab.js.map +0 -1
  494. package/out-tsc/src/tabpane/TabPane.js.map +0 -1
  495. package/out-tsc/src/templates/TemplateEditor.js.map +0 -1
  496. package/out-tsc/src/textinput/TextInput.js.map +0 -1
  497. package/out-tsc/src/textinput/helpers.js +0 -12
  498. package/out-tsc/src/textinput/helpers.js.map +0 -1
  499. package/out-tsc/src/thumbnail/Thumbnail.js.map +0 -1
  500. package/out-tsc/src/tip/Tip.js.map +0 -1
  501. package/out-tsc/src/tip/helpers.js +0 -7
  502. package/out-tsc/src/tip/helpers.js.map +0 -1
  503. package/out-tsc/src/toast/Toast.js.map +0 -1
  504. package/out-tsc/src/user/TembaUser.js.map +0 -1
  505. package/out-tsc/src/utils/index.js.map +0 -1
  506. package/out-tsc/src/vectoricon/VectorIcon.js.map +0 -1
  507. package/out-tsc/src/vectoricon/index.js.map +0 -1
  508. package/src/charcount/helpers.ts +0 -162
  509. package/src/contacts/helpers.ts +0 -103
  510. package/src/leafletmap/helpers.ts +0 -18
  511. package/src/options/helpers.ts +0 -37
  512. package/src/select/helpers.ts +0 -0
  513. package/src/shadowless/Shadowless.ts +0 -32
  514. package/src/textinput/helpers.ts +0 -11
  515. package/src/tip/helpers.ts +0 -7
  516. /package/out-tsc/src/{alert → display}/Alert.js +0 -0
  517. /package/out-tsc/src/{anchor → display}/Anchor.js +0 -0
  518. /package/out-tsc/src/{button → display}/Button.js +0 -0
  519. /package/out-tsc/src/{chat → display}/Chat.js +0 -0
  520. /package/out-tsc/src/{contacts → display}/ContactName.js +0 -0
  521. /package/out-tsc/src/{contacts → display}/ContactUrn.js +0 -0
  522. /package/out-tsc/src/{dropdown → display}/Dropdown.js +0 -0
  523. /package/out-tsc/src/{label → display}/Label.js +0 -0
  524. /package/out-tsc/src/{lightbox → display}/Lightbox.js +0 -0
  525. /package/out-tsc/src/{loading → display}/Loading.js +0 -0
  526. /package/out-tsc/src/{options → display}/Options.js +0 -0
  527. /package/out-tsc/src/{progress → display}/ProgressBar.js +0 -0
  528. /package/out-tsc/src/{date → display}/TembaDate.js +0 -0
  529. /package/out-tsc/src/{user → display}/TembaUser.js +0 -0
  530. /package/out-tsc/src/{thumbnail → display}/Thumbnail.js +0 -0
  531. /package/out-tsc/src/{toast → display}/Toast.js +0 -0
  532. /package/out-tsc/src/{sms → display/sms}/gsmsplitter.js +0 -0
  533. /package/out-tsc/src/{sms → display/sms}/gsmvalidator.js +0 -0
  534. /package/out-tsc/src/{sms → display/sms}/index.js +0 -0
  535. /package/out-tsc/src/{sms → display/sms}/unicodesplitter.js +0 -0
  536. /package/out-tsc/src/{completion → excellent}/ExcellentParser.js +0 -0
  537. /package/out-tsc/src/{completion → excellent}/helpers.js +0 -0
  538. /package/out-tsc/src/{imagepicker → form}/CroppieCSS.js +0 -0
  539. /package/out-tsc/src/{formfield → form}/FormField.js +0 -0
  540. /package/out-tsc/src/{dialog → layout}/Dialog.js +0 -0
  541. /package/out-tsc/src/{mask → layout}/Mask.js +0 -0
  542. /package/out-tsc/src/{dialog → layout}/Modax.js +0 -0
  543. /package/out-tsc/src/{resizer → layout}/Resizer.js +0 -0
  544. /package/out-tsc/src/{tabpane → layout}/Tab.js +0 -0
  545. /package/out-tsc/src/{tabpane → layout}/TabPane.js +0 -0
  546. /package/out-tsc/src/{contacts → live}/ContactFields.js +0 -0
  547. /package/out-tsc/src/{contacts → live}/ContactNameFetch.js +0 -0
  548. /package/out-tsc/src/{contacts → live}/ContactStoreElement.js +0 -0
  549. /package/out-tsc/src/{fields → live}/FieldManager.js +0 -0
  550. /package/out-tsc/src/{progress → live}/StartProgress.js +0 -0
  551. /package/src/{vectoricon/index.ts → Icons.ts} +0 -0
  552. /package/src/{alert → display}/Alert.ts +0 -0
  553. /package/src/{anchor → display}/Anchor.ts +0 -0
  554. /package/src/{button → display}/Button.ts +0 -0
  555. /package/src/{chat → display}/Chat.ts +0 -0
  556. /package/src/{contacts → display}/ContactName.ts +0 -0
  557. /package/src/{contacts → display}/ContactUrn.ts +0 -0
  558. /package/src/{dropdown → display}/Dropdown.ts +0 -0
  559. /package/src/{label → display}/Label.ts +0 -0
  560. /package/src/{lightbox → display}/Lightbox.ts +0 -0
  561. /package/src/{loading → display}/Loading.ts +0 -0
  562. /package/src/{options → display}/Options.ts +0 -0
  563. /package/src/{progress → display}/ProgressBar.ts +0 -0
  564. /package/src/{date → display}/TembaDate.ts +0 -0
  565. /package/src/{user → display}/TembaUser.ts +0 -0
  566. /package/src/{toast → display}/Toast.ts +0 -0
  567. /package/src/{sms → display/sms}/gsmsplitter.ts +0 -0
  568. /package/src/{sms → display/sms}/gsmvalidator.ts +0 -0
  569. /package/src/{sms → display/sms}/index.ts +0 -0
  570. /package/src/{sms → display/sms}/unicodesplitter.ts +0 -0
  571. /package/src/{completion → excellent}/ExcellentParser.ts +0 -0
  572. /package/src/{completion → excellent}/helpers.ts +0 -0
  573. /package/src/{imagepicker → form}/CroppieCSS.ts +0 -0
  574. /package/src/{formfield → form}/FormField.ts +0 -0
  575. /package/src/{mask → layout}/Mask.ts +0 -0
  576. /package/src/{dialog → layout}/Modax.ts +0 -0
  577. /package/src/{resizer → layout}/Resizer.ts +0 -0
  578. /package/src/{tabpane → layout}/Tab.ts +0 -0
  579. /package/src/{tabpane → layout}/TabPane.ts +0 -0
  580. /package/src/{contacts → live}/ContactNameFetch.ts +0 -0
  581. /package/src/{contacts → live}/ContactStoreElement.ts +0 -0
  582. /package/src/{fields → live}/FieldManager.ts +0 -0
  583. /package/src/{progress → live}/StartProgress.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Editor.js","sourceRoot":"","sources":["../../../src/flow/Editor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,GAAG,EAAoB,SAAS,EAAE,MAAM,KAAK,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAY,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,eAAe,GAAG,GAAG,CAAC;AAS5B,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,MAAM,OAAO,MAAO,SAAQ,YAAY;IACtC,0DAA0D;IAC1D,gBAAgB;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAqCD,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6IT,CAAC;IACJ,CAAC;IAED;QACE,KAAK,EAAE,CAAC;QAlLV,6BAA6B;QACrB,cAAS,GAAkB,IAAI,CAAC;QAiBxC,aAAa;QAEL,eAAU,GAAG,KAAK,CAAC;QACnB,gBAAW,GAAG,KAAK,CAAC;QACpB,iBAAY,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAG9B,oBAAe,GAAyB,IAAI,CAAC;QAC7C,aAAQ,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAEvC,yDAAyD;QACjD,mBAAc,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,iBAAY,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAqJrD,CAAC;IAES,YAAY,CACpB,OAA0D;QAE1D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,yBAAyB,EAAE,CAAC;QACjC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,mBAAmB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAES,OAAO,CACf,OAA0D;QAE1D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,uDAAuD;QACzD,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,2BAA2B;QAC3B,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC5B,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,mBAAmB,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YAErE,IAAI,mBAAmB,IAAI,eAAe,EAAE,CAAC;gBAC3C,IAAI,CAAC,WAAW,EAAE,CAAC;gBACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,CAAC;QACH,CAAC,EAAE,eAAe,CAAC,CAAC;IACtB,CAAC;IAEO,WAAW;QACjB,yCAAyC;QACzC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACrE,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC5B,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC/D,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7D,CAAC;IAEO,yBAAyB;QAC/B,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC5D,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1D,CAAC;IAEO,WAAW,CAAC,IAAY,EAAE,IAAuB;;QACvD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,OAAO,MAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0CAAE,QAAQ,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,OAAO,MAAA,MAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,0CAAG,IAAI,CAAC,0CAAE,QAAQ,CAAC;QACxD,CAAC;IACH,CAAC;IAEO,cAAc,CACpB,IAAY,EACZ,IAAuB,EACvB,QAAsB;;QAEtB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,MAAM,aAAa,GAAG,MAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,0CAAG,IAAI,CAAC,CAAC;YAC3D,IAAI,aAAa,EAAE,CAAC;gBAClB,QAAQ,EAAE;qBACP,QAAQ,EAAE;qBACV,gBAAgB,CAAC,IAAI,EAAE;oBACtB,GAAG,aAAa;oBAChB,QAAQ;iBACT,CAAC,CAAC;YACP,CAAC;QACH,CAAC;IACH,CAAC;IAEO,eAAe,CAAC,KAAiB;QACvC,MAAM,OAAO,GAAG,KAAK,CAAC,aAA4B,CAAC;QACnD,oGAAoG;QACpG,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB,CAAC;QAC3C,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACjE,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,KAAK,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEvE,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,4DAA4D;QAC5D,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC3D,IAAI,CAAC,QAAQ,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC;QAC3D,IAAI,CAAC,eAAe,GAAG;YACrB,IAAI;YACJ,QAAQ;YACR,OAAO;YACP,IAAI;SACL,CAAC;QAEF,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;IAC1B,CAAC;IAEO,eAAe,CAAC,KAAiB;QACvC,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,eAAe;YAAE,OAAO;QAEvD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC;QAE9D,0DAA0D;QAC1D,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,QAAQ,GAAG,cAAc,EAAE,CAAC;YAClD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YAEvB,yCAAyC;YACzC,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACzD,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,+CAA+C;QAC/C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC;YAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,MAAM,CAAC;YAE1C,yCAAyC;YACzC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,OAAO,IAAI,CAAC;YACzD,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,MAAM,IAAI,CAAC;YAEvD,wCAAwC;YACxC,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACzD,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,KAAiB;QACrC,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,eAAe;YAAE,OAAO;QAEvD,oDAAoD;QACpD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,8CAA8C;YAC9C,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACzD,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YACnD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YAEnD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC;YAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,MAAM,CAAC;YAE1C,uCAAuC;YACvC,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;YAEtC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;YAE3D,iDAAiD;YACjD,IAAI,CAAC,cAAc,CACjB,IAAI,CAAC,eAAe,CAAC,IAAI,EACzB,IAAI,CAAC,eAAe,CAAC,IAAI,EACzB,WAAW,CACZ,CAAC;YAEF,oCAAoC;YACpC,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACzC,QAAQ,EAAE;qBACP,QAAQ,EAAE;qBACV,qBAAqB,CAAC;oBACrB,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,WAAW;iBACzC,CAAC,CAAC;YACP,CAAC;YAED,wCAAwC;YACxC,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACzD,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;YACnC,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;IAC9B,CAAC;IAEO,gBAAgB;;QACtB,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,uDAAuD;QACvD,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,uBAAuB;QACvB,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrC,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;gBACtB,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;gBAC9D,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,IAAI,GAAG,WAAW,CAAC,qBAAqB,EAAE,CAAC;oBACjD,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC7D,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,CAAA,MAAA,IAAI,CAAC,UAAU,CAAC,GAAG,0CAAE,QAAQ,KAAI,EAAE,CAAC;QACrD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YACzC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,oBAAoB;gBAC/E,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,qBAAqB;YACnF,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,8BAA8B;QAC9B,KAAK,CAAC,QAAQ,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC;IAEM,MAAM;;QACX,2DAA2D;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAA;QACd,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAChC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;aAC/B,CAAC;QAEV,MAAM,QAAQ,GAAG,CAAA,MAAA,MAAA,IAAI,CAAC,UAAU,0CAAE,GAAG,0CAAE,QAAQ,KAAI,EAAE,CAAC;QAEtD,OAAO,IAAI,CAAA,GAAG,KAAK;;;;wCAIiB,IAAI,CAAC,UAAU,CAAC,KAAK,cAAc,IAAI;aAClE,UAAU,CAAC,MAAM;;;cAGhB,IAAI,CAAC,UAAU;YACf,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;;gBACjC,MAAM,QAAQ,GACZ,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;gBAEhD,MAAM,QAAQ,GACZ,IAAI,CAAC,UAAU,IAAI,CAAA,MAAA,IAAI,CAAC,eAAe,0CAAE,IAAI,MAAK,IAAI,CAAC,IAAI,CAAC;gBAE9D,OAAO,IAAI,CAAA;uCACU,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;iCAChC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;2BACrC,IAAI,CAAC,IAAI;kCACF,QAAQ,CAAC,IAAI,WAAW,QAAQ,CAAC,GAAG;+BACvC,IAAI,CAAC,OAAO;4BACf,IAAI;0BACN,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;sCACxB,CAAC;YACvB,CAAC,CAAC;YACJ,CAAC,CAAC,IAAI,CAAA,iCAAiC;cACvC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;;YAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;YACxD,MAAM,QAAQ,GACZ,IAAI,CAAC,UAAU,IAAI,CAAA,MAAA,IAAI,CAAC,eAAe,0CAAE,IAAI,MAAK,IAAI,CAAC;YACzD,OAAO,IAAI,CAAA;mCACU,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;6BAChC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;8BAC9B,QAAQ,CAAC,IAAI,WAAW,QAAQ,CAAC,GAAG,gBAAgB,IAAI;gBACtE,QAAQ,CAAC,GAAG;uBACL,IAAI;wBACH,MAAM;4BACF,QAAQ;oCACA,CAAC;QACzB,CAAC,CAAC;;;aAGD,CAAC;IACZ,CAAC;CACF;AA7dQ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oCACP;AAGb;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;uCACJ;AAGf;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;0CAC1B;AAG5B;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;0CACH;AAG/C;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;yCAChC;AAIjB;IADP,KAAK,EAAE;0CACmB;AAKnB;IADP,KAAK,EAAE;+CAC6C","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { css, PropertyValueMap, unsafeCSS } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { FlowDefinition, FlowPosition } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\nimport { RapidElement } from '../RapidElement';\n\nimport { Plumber } from './Plumber';\nimport { EditorNode } from './EditorNode';\n\nexport function snapToGrid(value: number): number {\n return Math.round(value / 20) * 20;\n}\n\nconst SAVE_QUIET_TIME = 500;\n\nexport interface DraggableItem {\n uuid: string;\n position: FlowPosition;\n element: HTMLElement;\n type: 'node' | 'sticky';\n}\n\nconst DRAG_THRESHOLD = 10;\n\nexport class Editor extends RapidElement {\n // unfortunately, jsplumb requires that we be in light DOM\n createRenderRoot() {\n return this;\n }\n\n // this is the master plumber\n private plumber: Plumber;\n\n // timer for debounced saving\n private saveTimer: number | null = null;\n\n @property({ type: String })\n public flow: string;\n\n @property({ type: String })\n public version: string;\n\n @fromStore(zustand, (state: AppState) => state.flowDefinition)\n private definition!: FlowDefinition;\n\n @fromStore(zustand, (state: AppState) => state.canvasSize)\n private canvasSize!: { width: number; height: number };\n\n @fromStore(zustand, (state: AppState) => state.dirtyDate)\n private dirtyDate!: Date;\n\n // Drag state\n @state()\n private isDragging = false;\n private isMouseDown = false;\n private dragStartPos = { x: 0, y: 0 };\n\n @state()\n private currentDragItem: DraggableItem | null = null;\n private startPos = { left: 0, top: 0 };\n\n // Bound event handlers to maintain proper 'this' context\n private boundMouseMove = this.handleMouseMove.bind(this);\n private boundMouseUp = this.handleMouseUp.bind(this);\n\n static get styles() {\n return css`\n #editor {\n overflow: scroll;\n flex: 1;\n }\n\n #grid {\n position: relative;\n background-color: #f9f9f9;\n background-position: 10px 10px;\n background-image: linear-gradient(\n 0deg,\n transparent 24%,\n rgba(61, 177, 255, 0.15) 25%,\n rgba(61, 177, 255, 0.15) 26%,\n transparent 27%,\n transparent 74%,\n rgba(61, 177, 255, 0.15) 75%,\n rgba(61, 177, 255, 0.15) 76%,\n transparent 77%,\n transparent\n ),\n linear-gradient(\n 90deg,\n transparent 24%,\n rgba(61, 177, 255, 0.15) 25%,\n rgba(61, 177, 255, 0.15) 26%,\n transparent 27%,\n transparent 74%,\n rgba(61, 177, 255, 0.15) 75%,\n rgba(61, 177, 255, 0.15) 76%,\n transparent 77%,\n transparent\n );\n background-size: 40px 40px;\n box-shadow: inset -5px 0 10px rgba(0, 0, 0, 0.05);\n border-top: 1px solid #e0e0e0;\n display: inline-block;\n width: 100%;\n }\n\n #canvas {\n position: relative;\n padding: 20px;\n margin: 20px;\n }\n\n #canvas > .draggable {\n position: absolute;\n z-index: 100;\n }\n\n #canvas > .dragging {\n z-index: 10000 !important;\n }\n\n body .jtk-endpoint {\n width: initial;\n height: initial;\n }\n\n .jtk-endpoint {\n z-index: 600;\n }\n\n .plumb-source {\n z-index: 600;\n border: 0px solid var(--color-connectors);\n }\n\n .plumb-source.connected {\n box-shadow: 0 3px 3px 0px rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n }\n\n .plumb-source circle {\n fill: tomato;\n }\n\n .plumb-source.connected circle {\n fill: #fff;\n }\n\n .plumb-source svg {\n fill: var(--color-connectors) !important;\n stroke: var(--color-connectors);\n }\n\n .plumb-target {\n margin-top: -6px;\n z-index: 600;\n opacity: 0;\n cursor: pointer;\n }\n\n body .plumb-connector path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n z-index: 10;\n }\n\n body .plumb-connector {\n z-index: 10;\n }\n\n body .plumb-connector.elevated {\n z-index: 550;\n }\n\n body .plumb-connector.elevated path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n z-index: 550;\n }\n\n body .plumb-connector.elevated .plumb-arrow {\n fill: var(--color-connectors);\n stroke: var(--color-connectors);\n stroke-width: 0px;\n margin-top: 6px;\n z-index: 550;\n }\n\n body .plumb-connector .plumb-arrow {\n fill: var(--color-connectors);\n stroke: var(--color-connectors);\n stroke-width: 0px;\n margin-top: 6px;\n z-index: 10;\n }\n\n body svg.jtk-connector.jtk-hover path {\n stroke: var(--color-success) !important;\n stroke-width: 3px;\n }\n\n body .plumb-connector.jtk-hover .plumb-arrow {\n fill: var(--color-success) !important;\n stroke-width: 0px;\n z-index: 10;\n }\n `;\n }\n\n constructor() {\n super();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n this.plumber = new Plumber(this.querySelector('#canvas'));\n this.setupGlobalEventListeners();\n if (changes.has('flow')) {\n getStore().getState().fetchRevision(`/flow/revisions/${this.flow}`);\n }\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('canvasSize')) {\n // console.log('Setting canvas size', this.canvasSize);\n }\n\n if (changes.has('definition')) {\n this.updateCanvasSize();\n }\n\n if (changes.has('dirtyDate')) {\n if (this.dirtyDate) {\n this.debouncedSave();\n }\n }\n }\n\n private debouncedSave(): void {\n // Clear any existing timer\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n }\n\n this.saveTimer = window.setTimeout(() => {\n const now = new Date();\n const timeSinceLastChange = now.getTime() - this.dirtyDate.getTime();\n\n if (timeSinceLastChange >= SAVE_QUIET_TIME) {\n this.saveChanges();\n this.saveTimer = null;\n } else {\n this.debouncedSave();\n }\n }, SAVE_QUIET_TIME);\n }\n\n private saveChanges(): void {\n // post the flow definition to the server\n getStore().postJSON(`/flow/revisions/${this.flow}`, this.definition);\n getStore().getState().setDirtyDate(null);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n document.removeEventListener('mousemove', this.boundMouseMove);\n document.removeEventListener('mouseup', this.boundMouseUp);\n }\n\n private setupGlobalEventListeners(): void {\n document.addEventListener('mousemove', this.boundMouseMove);\n document.addEventListener('mouseup', this.boundMouseUp);\n }\n\n private getPosition(uuid: string, type: 'node' | 'sticky'): FlowPosition {\n if (type === 'node') {\n return this.definition._ui.nodes[uuid]?.position;\n } else {\n return this.definition._ui.stickies?.[uuid]?.position;\n }\n }\n\n private updatePosition(\n uuid: string,\n type: 'node' | 'sticky',\n position: FlowPosition\n ): void {\n if (type === 'node') {\n getStore().getState().updateNodePosition(uuid, position);\n } else {\n const currentSticky = this.definition._ui.stickies?.[uuid];\n if (currentSticky) {\n getStore()\n .getState()\n .updateStickyNote(uuid, {\n ...currentSticky,\n position\n });\n }\n }\n }\n\n private handleMouseDown(event: MouseEvent): void {\n const element = event.currentTarget as HTMLElement;\n // Only start dragging if clicking on the element itself, not on exits or other interactive elements\n const target = event.target as HTMLElement;\n if (target.classList.contains('exit') || target.closest('.exit')) {\n return;\n }\n\n const uuid = element.getAttribute('uuid');\n const type = element.tagName === 'TEMBA-FLOW-NODE' ? 'node' : 'sticky';\n\n const position = this.getPosition(uuid, type);\n if (!position) return;\n\n // Set up potential drag state, but don't start dragging yet\n this.isMouseDown = true;\n this.dragStartPos = { x: event.clientX, y: event.clientY };\n this.startPos = { left: position.left, top: position.top };\n this.currentDragItem = {\n uuid,\n position,\n element,\n type\n };\n\n event.preventDefault();\n event.stopPropagation();\n }\n\n private handleMouseMove(event: MouseEvent): void {\n if (!this.isMouseDown || !this.currentDragItem) return;\n\n const deltaX = event.clientX - this.dragStartPos.x;\n const deltaY = event.clientY - this.dragStartPos.y;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n // Only start dragging if we've moved beyond the threshold\n if (!this.isDragging && distance > DRAG_THRESHOLD) {\n this.isDragging = true;\n\n // If this is a node, elevate connections\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.elevateNodeConnections(this.currentDragItem.uuid);\n }\n }\n\n // If we're actually dragging, update positions\n if (this.isDragging) {\n const newLeft = this.startPos.left + deltaX;\n const newTop = this.startPos.top + deltaY;\n\n // Update the visual position during drag\n this.currentDragItem.element.style.left = `${newLeft}px`;\n this.currentDragItem.element.style.top = `${newTop}px`;\n\n // Repaint connections if this is a node\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.repaintEverything();\n }\n }\n }\n\n private handleMouseUp(event: MouseEvent): void {\n if (!this.isMouseDown || !this.currentDragItem) return;\n\n // If we were actually dragging, handle the drag end\n if (this.isDragging) {\n // Restore normal z-index for node connections\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.restoreNodeConnections(this.currentDragItem.uuid);\n }\n\n const deltaX = event.clientX - this.dragStartPos.x;\n const deltaY = event.clientY - this.dragStartPos.y;\n\n const newLeft = this.startPos.left + deltaX;\n const newTop = this.startPos.top + deltaY;\n\n // Snap to 20px grid for final position\n const snappedLeft = snapToGrid(newLeft);\n const snappedTop = snapToGrid(newTop);\n\n const newPosition = { left: snappedLeft, top: snappedTop };\n\n // Update the store with the new snapped position\n this.updatePosition(\n this.currentDragItem.uuid,\n this.currentDragItem.type,\n newPosition\n );\n\n // Update canvas positions for nodes\n if (this.currentDragItem.type === 'node') {\n getStore()\n .getState()\n .updateCanvasPositions({\n [this.currentDragItem.uuid]: newPosition\n });\n }\n\n // Repaint connections if this is a node\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.repaintEverything();\n }\n }\n\n // Reset all drag state\n this.isDragging = false;\n this.isMouseDown = false;\n this.currentDragItem = null;\n }\n\n private updateCanvasSize(): void {\n if (!this.definition) return;\n\n const store = getStore();\n if (!store) return;\n\n // Calculate required canvas size based on all elements\n let maxWidth = 0;\n let maxHeight = 0;\n\n // Check node positions\n this.definition.nodes.forEach((node) => {\n const ui = this.definition._ui.nodes[node.uuid];\n if (ui && ui.position) {\n const nodeElement = this.querySelector(`[id=\"${node.uuid}\"]`);\n if (nodeElement) {\n const rect = nodeElement.getBoundingClientRect();\n maxWidth = Math.max(maxWidth, ui.position.left + rect.width);\n maxHeight = Math.max(maxHeight, ui.position.top + rect.height);\n }\n }\n });\n\n // Check sticky note positions\n const stickies = this.definition._ui?.stickies || {};\n Object.values(stickies).forEach((sticky) => {\n if (sticky.position) {\n maxWidth = Math.max(maxWidth, sticky.position.left + 200); // Sticky note width\n maxHeight = Math.max(maxHeight, sticky.position.top + 100); // Sticky note height\n }\n });\n\n // Update canvas size in store\n store.getState().expandCanvas(maxWidth, maxHeight);\n }\n\n public render(): TemplateResult {\n // we have to embed our own style since we are in light DOM\n const style = html`<style>\n ${unsafeCSS(Editor.styles.cssText)}\n ${unsafeCSS(EditorNode.styles.cssText)}\n </style>`;\n\n const stickies = this.definition?._ui?.stickies || {};\n\n return html`${style}\n <div id=\"editor\">\n <div\n id=\"grid\"\n style=\"min-width:100%;width:${this.canvasSize.width}px; height:${this\n .canvasSize.height}px\"\n >\n <div id=\"canvas\">\n ${this.definition\n ? this.definition.nodes.map((node) => {\n const position =\n this.definition._ui.nodes[node.uuid].position;\n\n const dragging =\n this.isDragging && this.currentDragItem?.uuid === node.uuid;\n\n return html`<temba-flow-node\n class=\"draggable ${dragging ? 'dragging' : ''}\"\n @mousedown=${this.handleMouseDown.bind(this)}\n uuid=${node.uuid}\n style=\"left:${position.left}px; top:${position.top}px\"\n .plumber=${this.plumber}\n .node=${node}\n .ui=${this.definition._ui.nodes[node.uuid]}\n ></temba-flow-node>`;\n })\n : html`<temba-loading></temba-loading>`}\n ${Object.entries(stickies).map(([uuid, sticky]) => {\n const position = sticky.position || { left: 0, top: 0 };\n const dragging =\n this.isDragging && this.currentDragItem?.uuid === uuid;\n return html`<temba-sticky-note\n class=\"draggable ${dragging ? 'dragging' : ''}\"\n @mousedown=${this.handleMouseDown.bind(this)}\n style=\"left:${position.left}px; top:${position.top}px; z-index: ${1000 +\n position.top}\"\n uuid=${uuid}\n .data=${sticky}\n .dragging=${dragging}\n ></temba-sticky-note>`;\n })}\n </div>\n </div>\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"Editor.js","sourceRoot":"","sources":["../../../src/flow/Editor.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { css, PropertyValueMap, unsafeCSS } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { FlowDefinition, FlowPosition } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\nimport { RapidElement } from '../RapidElement';\nimport { repeat } from 'lit-html/directives/repeat.js';\n\nimport { Plumber } from './Plumber';\nimport { EditorNode } from './EditorNode';\nimport { Dialog } from '../layout/Dialog';\nimport { Connection } from '@jsplumb/browser-ui';\n\nexport function snapToGrid(value: number): number {\n const snapped = Math.round(value / 20) * 20;\n return Math.max(snapped, 0);\n}\n\nexport function findNodeForExit(\n definition: FlowDefinition,\n exitUuid: string\n): string | null {\n for (const node of definition.nodes) {\n const exit = node.exits.find((e) => e.uuid === exitUuid);\n if (exit) {\n return node.uuid;\n }\n }\n return null;\n}\n\nconst SAVE_QUIET_TIME = 500;\n\nexport interface DraggableItem {\n uuid: string;\n position: FlowPosition;\n element: HTMLElement;\n type: 'node' | 'sticky';\n}\n\nexport interface SelectionBox {\n startX: number;\n startY: number;\n endX: number;\n endY: number;\n}\n\nconst DRAG_THRESHOLD = 5;\n\nexport class Editor extends RapidElement {\n // unfortunately, jsplumb requires that we be in light DOM\n createRenderRoot() {\n return this;\n }\n\n // this is the master plumber\n private plumber: Plumber;\n\n // timer for debounced saving\n private saveTimer: number | null = null;\n\n @property({ type: String })\n public flow: string;\n\n @property({ type: String })\n public version: string;\n\n @fromStore(zustand, (state: AppState) => state.flowDefinition)\n private definition!: FlowDefinition;\n\n @fromStore(zustand, (state: AppState) => state.canvasSize)\n private canvasSize!: { width: number; height: number };\n\n @fromStore(zustand, (state: AppState) => state.dirtyDate)\n private dirtyDate!: Date;\n\n // Drag state\n @state()\n private isDragging = false;\n private isMouseDown = false;\n private dragStartPos = { x: 0, y: 0 };\n\n @state()\n private currentDragItem: DraggableItem | null = null;\n private startPos = { left: 0, top: 0 };\n\n // Selection state\n @state()\n private selectedItems: Set<string> = new Set();\n\n @state()\n private isSelecting = false;\n\n @state()\n private selectionBox: SelectionBox | null = null;\n\n @state()\n private targetId: string | null = null;\n\n @state()\n private sourceId: string | null = null;\n\n @state()\n private dragFromNodeId: string | null = null;\n\n @state()\n private isValidTarget = true;\n\n private canvasMouseDown = false;\n\n // Bound event handlers to maintain proper 'this' context\n private boundMouseMove = this.handleMouseMove.bind(this);\n private boundMouseUp = this.handleMouseUp.bind(this);\n private boundGlobalMouseDown = this.handleGlobalMouseDown.bind(this);\n private boundKeyDown = this.handleKeyDown.bind(this);\n private boundCanvasDoubleClick = this.handleCanvasDoubleClick.bind(this);\n\n static get styles() {\n return css`\n #editor {\n overflow: scroll;\n flex: 1;\n }\n\n #grid {\n position: relative;\n background-color: #f9f9f9;\n background-image: radial-gradient(\n circle,\n rgba(61, 177, 255, 0.3) 1px,\n transparent 1px\n );\n background-size: 20px 20px;\n background-position: 10px 10px;\n box-shadow: inset -5px 0 10px rgba(0, 0, 0, 0.05);\n border-top: 1px solid #e0e0e0;\n width: 100%;\n display: flex;\n }\n\n #canvas {\n position: relative;\n padding: 0px;\n flex-grow: 1;\n margin: 20px;\n }\n\n #canvas > .draggable {\n position: absolute;\n z-index: 100;\n }\n\n #canvas > .dragging {\n z-index: 99999 !important;\n }\n\n body .jtk-endpoint {\n width: initial;\n height: initial;\n }\n\n .jtk-endpoint {\n z-index: 600;\n opacity: 0;\n }\n\n .plumb-source {\n z-index: 600;\n cursor: pointer;\n opacity: 0;\n }\n\n .plumb-source.connected {\n border-radius: 50%;\n pointer-events: none;\n }\n\n .plumb-source circle {\n fill: purple;\n }\n\n .plumb-target {\n z-index: 600;\n opacity: 0;\n cursor: pointer;\n fill: transparent;\n }\n\n body svg.jtk-connector.plumb-connector path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n }\n\n body .plumb-connector {\n z-index: 10 !important;\n }\n\n body .plumb-connector .plumb-arrow {\n fill: var(--color-connectors);\n stroke: var(--color-connectors);\n stroke-width: 0px !important;\n margin-top: 6px;\n z-index: 10;\n }\n\n body svg.jtk-connector.jtk-hover path {\n stroke: var(--color-success) !important;\n stroke-width: 3px;\n }\n\n body .plumb-connector.jtk-hover .plumb-arrow {\n fill: var(--color-success) !important;\n stroke-width: 0px;\n z-index: 10;\n }\n\n /* Connection dragging feedback */\n body svg.jtk-connector.jtk-dragging {\n z-index: 99999 !important;\n }\n\n .katavorio-drag-no-select svg.jtk-connector path,\n .katavorio-drag-no-select svg.jtk-endpoint path {\n pointer-events: none !important;\n border: 1px solid purple;\n }\n\n /* Connection target feedback */\n temba-flow-node.connection-target-valid {\n outline: 3px solid var(--color-success, #22c55e) !important;\n outline-offset: 2px;\n border-radius: var(--curvature);\n }\n\n temba-flow-node.connection-target-invalid {\n outline: 3px solid var(--color-error, #ef4444) !important;\n outline-offset: 2px;\n border-radius: var(--curvature);\n }\n\n /* Selection box styles */\n .selection-box {\n position: absolute;\n border: 2px dashed #6298f0ff;\n background-color: rgba(59, 130, 246, 0.1);\n z-index: 9999;\n pointer-events: none;\n }\n\n /* Selected item styles */\n .draggable.selected {\n outline: 3px solid #6298f0ff;\n outline-offset: 0px;\n border-radius: var(--curvature);\n }\n\n .jtk-floating-endpoint {\n pointer-events: none;\n }\n `;\n }\n\n constructor() {\n super();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n this.plumber = new Plumber(this.querySelector('#canvas'));\n this.setupGlobalEventListeners();\n if (changes.has('flow')) {\n getStore().getState().fetchRevision(`/flow/revisions/${this.flow}`);\n }\n\n this.plumber.on('connection:drag', (info: Connection) => {\n this.dragFromNodeId = document\n .getElementById(info.sourceId)\n .closest('.node').id;\n this.sourceId = info.sourceId;\n });\n\n this.plumber.on('connection:abort', () => {\n this.makeConnection();\n });\n\n this.plumber.on('connection:detach', () => {\n this.makeConnection();\n });\n }\n\n private makeConnection() {\n if (this.sourceId && this.targetId && this.isValidTarget) {\n this.plumber.connectIds(\n this.dragFromNodeId,\n this.sourceId,\n this.targetId\n );\n getStore()\n .getState()\n .updateConnection(this.dragFromNodeId, this.sourceId, this.targetId);\n\n setTimeout(() => {\n this.plumber.repaintEverything();\n }, 100);\n }\n\n // Clean up visual feedback\n document.querySelectorAll('temba-flow-node').forEach((node) => {\n node.classList.remove(\n 'connection-target-valid',\n 'connection-target-invalid'\n );\n });\n\n this.sourceId = null;\n this.targetId = null;\n this.dragFromNodeId = null;\n this.isValidTarget = true;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('canvasSize')) {\n // console.log('Setting canvas size', this.canvasSize);\n }\n\n if (changes.has('definition')) {\n this.updateCanvasSize();\n }\n\n if (changes.has('dirtyDate')) {\n if (this.dirtyDate) {\n this.debouncedSave();\n }\n }\n }\n\n private debouncedSave(): void {\n // Clear any existing timer\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n }\n\n this.saveTimer = window.setTimeout(() => {\n const now = new Date();\n const timeSinceLastChange = now.getTime() - this.dirtyDate.getTime();\n\n if (timeSinceLastChange >= SAVE_QUIET_TIME) {\n this.saveChanges();\n this.saveTimer = null;\n } else {\n this.debouncedSave();\n }\n }, SAVE_QUIET_TIME);\n }\n\n private saveChanges(): void {\n // post the flow definition to the server\n getStore().postJSON(`/flow/revisions/${this.flow}`, this.definition);\n getStore().getState().setDirtyDate(null);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n document.removeEventListener('mousemove', this.boundMouseMove);\n document.removeEventListener('mouseup', this.boundMouseUp);\n document.removeEventListener('mousedown', this.boundGlobalMouseDown);\n document.removeEventListener('keydown', this.boundKeyDown);\n\n const canvas = this.querySelector('#canvas');\n if (canvas) {\n canvas.removeEventListener('dblclick', this.boundCanvasDoubleClick);\n }\n }\n\n private setupGlobalEventListeners(): void {\n document.addEventListener('mousemove', this.boundMouseMove);\n document.addEventListener('mouseup', this.boundMouseUp);\n document.addEventListener('mousedown', this.boundGlobalMouseDown);\n document.addEventListener('keydown', this.boundKeyDown);\n\n const canvas = this.querySelector('#canvas');\n if (canvas) {\n canvas.addEventListener('dblclick', this.boundCanvasDoubleClick);\n }\n }\n\n private getPosition(uuid: string, type: 'node' | 'sticky'): FlowPosition {\n if (type === 'node') {\n return this.definition._ui.nodes[uuid]?.position;\n } else {\n return this.definition._ui.stickies?.[uuid]?.position;\n }\n }\n\n private handleMouseDown(event: MouseEvent): void {\n // ignore right clicks\n if (event.button !== 0) return;\n\n const element = event.currentTarget as HTMLElement;\n // Only start dragging if clicking on the element itself, not on exits or other interactive elements\n const target = event.target as HTMLElement;\n if (target.classList.contains('exit') || target.closest('.exit')) {\n return;\n }\n\n const uuid = element.getAttribute('uuid');\n const type = element.tagName === 'TEMBA-FLOW-NODE' ? 'node' : 'sticky';\n\n const position = this.getPosition(uuid, type);\n if (!position) return;\n\n // If clicking on a non-selected item, clear selection unless Ctrl/Cmd is held\n if (!this.selectedItems.has(uuid) && !event.ctrlKey && !event.metaKey) {\n this.selectedItems.clear();\n // Don't add single items to selection - single clicks just clear existing selection\n } else if (!this.selectedItems.has(uuid)) {\n // Add this item to selection only if Ctrl/Cmd is held\n this.selectedItems.add(uuid);\n }\n\n // Always set up drag state regardless of selection status\n // This allows single nodes to be dragged without being selected\n this.isMouseDown = true;\n this.dragStartPos = { x: event.clientX, y: event.clientY };\n this.startPos = { left: position.left, top: position.top };\n this.currentDragItem = {\n uuid,\n position,\n element,\n type\n };\n\n event.preventDefault();\n event.stopPropagation();\n }\n\n private handleGlobalMouseDown(event: MouseEvent): void {\n // ignore right clicks\n if (event.button !== 0) return;\n\n // Check if the click is within our canvas\n const canvasRect = this.querySelector('#grid')?.getBoundingClientRect();\n\n if (!canvasRect) return;\n\n const isWithinCanvas =\n event.clientX >= canvasRect.left &&\n event.clientX <= canvasRect.right &&\n event.clientY >= canvasRect.top &&\n event.clientY <= canvasRect.bottom;\n\n if (!isWithinCanvas) return;\n\n // Check if we clicked on a draggable item (node or sticky)\n const target = event.target as HTMLElement;\n const clickedOnDraggable = target.closest('.draggable');\n\n if (clickedOnDraggable) {\n // This is handled by the individual item mousedown handlers\n return;\n }\n\n // We clicked on empty canvas space, start selection\n this.handleCanvasMouseDown(event);\n }\n\n private handleCanvasMouseDown(event: MouseEvent): void {\n const target = event.target as HTMLElement;\n if (target.id === 'canvas' || target.id === 'grid') {\n // Ignore clicks on exits\n\n // Start selection box\n this.canvasMouseDown = true;\n this.dragStartPos = { x: event.clientX, y: event.clientY };\n\n const canvasRect = this.querySelector('#canvas')?.getBoundingClientRect();\n if (canvasRect) {\n // Clear current selection\n this.selectedItems.clear();\n\n const relativeX = event.clientX - canvasRect.left;\n const relativeY = event.clientY - canvasRect.top;\n\n this.selectionBox = {\n startX: relativeX,\n startY: relativeY,\n endX: relativeX,\n endY: relativeY\n };\n }\n\n event.preventDefault();\n }\n }\n\n private handleKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Delete' || event.key === 'Backspace') {\n if (this.selectedItems.size > 0) {\n this.showDeleteConfirmation();\n }\n }\n if (event.key === 'Escape') {\n this.selectedItems.clear();\n this.requestUpdate();\n }\n }\n\n private showDeleteConfirmation(): void {\n const itemCount = this.selectedItems.size;\n const itemType = itemCount === 1 ? 'item' : 'items';\n\n // Create and show confirmation dialog\n const dialog = document.createElement('temba-dialog') as Dialog;\n dialog.header = 'Delete Items';\n dialog.primaryButtonName = 'Delete';\n dialog.cancelButtonName = 'Cancel';\n dialog.destructive = true;\n dialog.innerHTML = `<div style=\"padding: 20px;\">Are you sure you want to delete ${itemCount} ${itemType}?</div>`;\n\n dialog.addEventListener('temba-button-clicked', (event: any) => {\n if (event.detail.button.name === 'Delete') {\n this.deleteSelectedItems();\n dialog.open = false;\n }\n });\n\n // Add to document and show\n document.body.appendChild(dialog);\n dialog.open = true;\n\n // Clean up dialog when closed\n dialog.addEventListener('temba-dialog-hidden', () => {\n document.body.removeChild(dialog);\n });\n }\n\n private deleteNodes(uuids: string[]): void {\n // Clean up jsPlumb connections for nodes before removing them\n uuids.forEach((uuid) => {\n this.plumber.removeNodeConnections(uuid);\n });\n\n // Now remove them from the definition\n if (uuids.length > 0 && this.plumber) {\n getStore().getState().removeNodes(uuids);\n }\n }\n\n private deleteSelectedItems(): void {\n const nodes = Array.from(this.selectedItems).filter((uuid) =>\n this.definition.nodes.some((node) => node.uuid === uuid)\n );\n this.deleteNodes(Array.from(nodes));\n\n const stickies = Array.from(this.selectedItems).filter(\n (uuid) => this.definition._ui?.stickies?.[uuid]\n );\n\n getStore().getState().removeStickyNotes(stickies);\n\n // Clear selection\n this.selectedItems.clear();\n }\n\n private updateSelectionBox(event: MouseEvent): void {\n if (!this.selectionBox || !this.canvasMouseDown) return;\n\n const canvasRect = this.querySelector('#canvas')?.getBoundingClientRect();\n if (!canvasRect) return;\n\n const relativeX = event.clientX - canvasRect.left;\n const relativeY = event.clientY - canvasRect.top;\n\n this.selectionBox = {\n ...this.selectionBox,\n endX: relativeX,\n endY: relativeY\n };\n\n // Update selected items based on selection box\n this.updateSelectedItemsFromBox();\n }\n\n private updateSelectedItemsFromBox(): void {\n if (!this.selectionBox) return;\n\n const newSelection = new Set<string>();\n\n const boxLeft = Math.min(this.selectionBox.startX, this.selectionBox.endX);\n const boxTop = Math.min(this.selectionBox.startY, this.selectionBox.endY);\n const boxRight = Math.max(this.selectionBox.startX, this.selectionBox.endX);\n const boxBottom = Math.max(\n this.selectionBox.startY,\n this.selectionBox.endY\n );\n\n // Check nodes\n this.definition?.nodes.forEach((node) => {\n const nodeElement = this.querySelector(`[id=\"${node.uuid}\"]`);\n if (nodeElement) {\n const position = this.definition._ui.nodes[node.uuid]?.position;\n if (position) {\n const rect = nodeElement.getBoundingClientRect();\n const canvasRect =\n this.querySelector('#canvas')?.getBoundingClientRect();\n\n if (canvasRect) {\n const nodeLeft = position.left;\n const nodeTop = position.top;\n const nodeRight = nodeLeft + rect.width;\n const nodeBottom = nodeTop + rect.height;\n\n // Check if selection box intersects with node\n if (\n boxLeft < nodeRight &&\n boxRight > nodeLeft &&\n boxTop < nodeBottom &&\n boxBottom > nodeTop\n ) {\n newSelection.add(node.uuid);\n }\n }\n }\n }\n });\n\n // Check sticky notes\n const stickies = this.definition?._ui?.stickies || {};\n Object.entries(stickies).forEach(([uuid, sticky]) => {\n if (sticky.position) {\n const stickyElement = this.querySelector(\n `temba-sticky-note[uuid=\"${uuid}\"]`\n ) as HTMLElement;\n\n if (stickyElement) {\n // Use clientWidth/clientHeight instead of getBoundingClientRect() to get element dimensions\n // This avoids the coordinate system mismatch between viewport and canvas coordinates\n const width = stickyElement.clientWidth;\n const height = stickyElement.clientHeight;\n\n // Use the canvas coordinates from the sticky's position\n const stickyLeft = sticky.position.left;\n const stickyTop = sticky.position.top;\n const stickyRight = stickyLeft + width;\n const stickyBottom = stickyTop + height;\n\n // Check if selection box intersects with sticky\n if (\n boxLeft < stickyRight &&\n boxRight > stickyLeft &&\n boxTop < stickyBottom &&\n boxBottom > stickyTop\n ) {\n newSelection.add(uuid);\n }\n }\n }\n });\n\n this.selectedItems = newSelection;\n }\n\n private renderSelectionBox(): TemplateResult | string {\n if (!this.selectionBox || !this.isSelecting) return '';\n\n const left = Math.min(this.selectionBox.startX, this.selectionBox.endX);\n const top = Math.min(this.selectionBox.startY, this.selectionBox.endY);\n const width = Math.abs(this.selectionBox.endX - this.selectionBox.startX);\n const height = Math.abs(this.selectionBox.endY - this.selectionBox.startY);\n\n return html`<div\n class=\"selection-box\"\n style=\"left: ${left}px; top: ${top}px; width: ${width}px; height: ${height}px;\"\n ></div>`;\n }\n\n private handleMouseMove(event: MouseEvent): void {\n // Handle selection box drawing\n if (this.canvasMouseDown && !this.isMouseDown) {\n this.isSelecting = true;\n this.updateSelectionBox(event);\n this.requestUpdate(); // Force re-render\n return;\n }\n\n if (this.plumber.connectionDragging) {\n const targetNode = document.querySelector('temba-flow-node:hover');\n\n // Clear previous target styles\n document.querySelectorAll('temba-flow-node').forEach((node) => {\n node.classList.remove(\n 'connection-target-valid',\n 'connection-target-invalid'\n );\n });\n\n if (targetNode) {\n this.targetId = targetNode.getAttribute('uuid');\n // Check if target is different from source node (prevent self-targeting)\n this.isValidTarget = this.targetId !== this.dragFromNodeId;\n\n // Apply visual feedback based on validity\n if (this.isValidTarget) {\n targetNode.classList.add('connection-target-valid');\n } else {\n targetNode.classList.add('connection-target-invalid');\n }\n } else {\n this.targetId = null;\n this.isValidTarget = true;\n }\n }\n\n // Handle item dragging\n if (!this.isMouseDown || !this.currentDragItem) return;\n\n const deltaX = event.clientX - this.dragStartPos.x;\n const deltaY = event.clientY - this.dragStartPos.y;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n // Only start dragging if we've moved beyond the threshold\n if (!this.isDragging && distance > DRAG_THRESHOLD) {\n this.isDragging = true;\n }\n\n // If we're actually dragging, update positions\n if (this.isDragging) {\n // Determine what items to move\n const itemsToMove =\n this.selectedItems.has(this.currentDragItem.uuid) &&\n this.selectedItems.size > 1\n ? Array.from(this.selectedItems)\n : [this.currentDragItem.uuid];\n\n itemsToMove.forEach((uuid) => {\n const element = this.querySelector(`[uuid=\"${uuid}\"]`) as HTMLElement;\n if (element) {\n const type =\n element.tagName === 'TEMBA-FLOW-NODE' ? 'node' : 'sticky';\n const position = this.getPosition(uuid, type);\n\n if (position) {\n const newLeft = position.left + deltaX;\n const newTop = position.top + deltaY;\n\n // Update the visual position during drag\n element.style.left = `${newLeft}px`;\n element.style.top = `${newTop}px`;\n\n // Add dragging class to ensure highest z-index\n element.classList.add('dragging');\n }\n }\n });\n\n this.plumber.revalidate(itemsToMove);\n }\n }\n\n private handleMouseUp(event: MouseEvent): void {\n // Handle selection box completion\n if (this.canvasMouseDown && this.isSelecting) {\n this.isSelecting = false;\n this.selectionBox = null;\n this.canvasMouseDown = false;\n this.requestUpdate();\n return;\n }\n\n // Handle canvas click (clear selection)\n if (this.canvasMouseDown && !this.isSelecting) {\n this.canvasMouseDown = false;\n return;\n }\n\n // Handle item drag completion\n if (!this.isMouseDown || !this.currentDragItem) return;\n\n // If we were actually dragging, handle the drag end\n if (this.isDragging) {\n const deltaX = event.clientX - this.dragStartPos.x;\n const deltaY = event.clientY - this.dragStartPos.y;\n\n // Determine what items were moved\n const itemsToMove =\n this.selectedItems.has(this.currentDragItem.uuid) &&\n this.selectedItems.size > 1\n ? Array.from(this.selectedItems)\n : [this.currentDragItem.uuid];\n\n // Update positions for all moved items\n const newPositions: { [uuid: string]: FlowPosition } = {};\n\n itemsToMove.forEach((uuid) => {\n const type = this.definition.nodes.find((node) => node.uuid === uuid)\n ? 'node'\n : 'sticky';\n const position = this.getPosition(uuid, type);\n\n if (position) {\n const newLeft = position.left + deltaX;\n const newTop = position.top + deltaY;\n\n // Snap to 20px grid for final position\n const snappedLeft = snapToGrid(newLeft);\n const snappedTop = snapToGrid(newTop);\n\n const newPosition = { left: snappedLeft, top: snappedTop };\n newPositions[uuid] = newPosition;\n\n // Remove dragging class\n const element = this.querySelector(`[uuid=\"${uuid}\"]`) as HTMLElement;\n if (element) {\n element.classList.remove('dragging');\n element.style.left = `${snappedLeft}px`;\n element.style.top = `${snappedTop}px`;\n }\n }\n });\n\n if (Object.keys(newPositions).length > 0) {\n getStore().getState().updateCanvasPositions(newPositions);\n\n setTimeout(() => {\n this.plumber.repaintEverything();\n }, 0);\n }\n\n this.selectedItems.clear();\n }\n\n // Reset all drag state\n this.isDragging = false;\n this.isMouseDown = false;\n this.currentDragItem = null;\n this.canvasMouseDown = false;\n }\n\n private updateCanvasSize(): void {\n if (!this.definition) return;\n\n const store = getStore();\n if (!store) return;\n\n // Calculate required canvas size based on all elements\n let maxWidth = 0;\n let maxHeight = 0;\n\n // Check node positions\n this.definition.nodes.forEach((node) => {\n const ui = this.definition._ui.nodes[node.uuid];\n if (ui && ui.position) {\n const nodeElement = this.querySelector(`[id=\"${node.uuid}\"]`);\n if (nodeElement) {\n const rect = nodeElement.getBoundingClientRect();\n maxWidth = Math.max(maxWidth, ui.position.left + rect.width);\n maxHeight = Math.max(maxHeight, ui.position.top + rect.height);\n }\n }\n });\n\n // Check sticky note positions\n const stickies = this.definition._ui?.stickies || {};\n Object.entries(stickies).forEach(([uuid, sticky]) => {\n if (sticky.position) {\n const stickyElement = this.querySelector(\n `temba-sticky-note[uuid=\"${uuid}\"]`\n ) as HTMLElement;\n if (stickyElement) {\n // Use clientWidth/clientHeight instead of getBoundingClientRect() to get element dimensions\n // This avoids the coordinate system mismatch between viewport and canvas coordinates\n const width = stickyElement.clientWidth;\n const height = stickyElement.clientHeight;\n\n // Both sticky.position and width/height are now in the same coordinate system\n maxWidth = Math.max(maxWidth, sticky.position.left + width);\n maxHeight = Math.max(maxHeight, sticky.position.top + height);\n } else {\n // Fallback to default sizes if element not found\n maxWidth = Math.max(maxWidth, sticky.position.left + 200);\n maxHeight = Math.max(maxHeight, sticky.position.top + 100);\n }\n }\n });\n\n // Update canvas size in store\n store.getState().expandCanvas(maxWidth, maxHeight);\n }\n\n private handleCanvasDoubleClick(event: MouseEvent): void {\n // Check if we double-clicked on empty canvas space\n const target = event.target as HTMLElement;\n if (target.id !== 'canvas') {\n return;\n }\n\n // Get canvas position\n const canvas = this.querySelector('#canvas');\n if (!canvas) {\n return;\n }\n\n const canvasRect = canvas.getBoundingClientRect();\n const relativeX = event.clientX - canvasRect.left - 10;\n const relativeY = event.clientY - canvasRect.top - 10;\n\n // Snap position to grid\n const snappedLeft = snapToGrid(relativeX);\n const snappedTop = snapToGrid(relativeY);\n\n // Create new sticky note\n const store = getStore();\n store.getState().createStickyNote({\n left: snappedLeft,\n top: snappedTop\n });\n\n event.preventDefault();\n event.stopPropagation();\n }\n\n public render(): TemplateResult {\n // we have to embed our own style since we are in light DOM\n const style = html`<style>\n ${unsafeCSS(Editor.styles.cssText)}\n ${unsafeCSS(EditorNode.styles.cssText)}\n </style>`;\n\n const stickies = this.definition?._ui?.stickies || {};\n\n return html`${style}\n <div id=\"editor\">\n <div\n id=\"grid\"\n style=\"min-width:100%;width:${this.canvasSize.width}px; height:${this\n .canvasSize.height}px\"\n >\n <div id=\"canvas\">\n ${this.definition\n ? repeat(\n this.definition.nodes,\n (node) => node.uuid,\n (node) => {\n const position =\n this.definition._ui.nodes[node.uuid].position;\n\n const dragging =\n this.isDragging &&\n this.currentDragItem?.uuid === node.uuid;\n\n const selected = this.selectedItems.has(node.uuid);\n\n return html`<temba-flow-node\n class=\"draggable ${dragging ? 'dragging' : ''} ${selected\n ? 'selected'\n : ''}\"\n @mousedown=${this.handleMouseDown.bind(this)}\n uuid=${node.uuid}\n style=\"left:${position.left}px; top:${position.top}px\"\n .plumber=${this.plumber}\n .node=${node}\n .ui=${this.definition._ui.nodes[node.uuid]}\n @temba-node-deleted=${(event) => {\n this.deleteNodes([event.detail.uuid]);\n }}\n ></temba-flow-node>`;\n }\n )\n : html`<temba-loading></temba-loading>`}\n ${repeat(\n Object.entries(stickies),\n ([uuid]) => uuid,\n ([uuid, sticky]) => {\n const position = sticky.position || { left: 0, top: 0 };\n const dragging =\n this.isDragging && this.currentDragItem?.uuid === uuid;\n const selected = this.selectedItems.has(uuid);\n return html`<temba-sticky-note\n class=\"draggable ${dragging ? 'dragging' : ''} ${selected\n ? 'selected'\n : ''}\"\n @mousedown=${this.handleMouseDown.bind(this)}\n style=\"left:${position.left}px; top:${position.top}px; z-index: ${1000 +\n position.top}\"\n uuid=${uuid}\n .data=${sticky}\n .dragging=${dragging}\n .selected=${selected}\n ></temba-sticky-note>`;\n }\n )}\n ${this.renderSelectionBox()}\n </div>\n </div>\n </div>`;\n }\n}\n"]}
@@ -5,6 +5,7 @@ import { property } from 'lit/decorators.js';
5
5
  import { RapidElement } from '../RapidElement';
6
6
  import { getClasses } from '../utils';
7
7
  import { getStore } from '../store/Store';
8
+ import { CustomEventType } from '../interfaces';
8
9
  export class EditorNode extends RapidElement {
9
10
  createRenderRoot() {
10
11
  return this;
@@ -16,8 +17,8 @@ export class EditorNode extends RapidElement {
16
17
  background-color: #fff;
17
18
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
18
19
  min-width: 200px;
19
- border-radius: calc(var(--curvature) * 1.5);
20
- overflow: hidden;
20
+ border-radius: var(--curvature);
21
+
21
22
  color: #333;
22
23
  cursor: move;
23
24
  user-select: none;
@@ -33,12 +34,43 @@ export class EditorNode extends RapidElement {
33
34
  transform: scale(1.02);
34
35
  z-index: 1000;
35
36
  }
36
-
37
+
37
38
  .action {
38
39
  max-width: 200px;
39
40
  position: relative;
40
41
  }
41
42
 
43
+ .action .remove-button {
44
+ position: absolute;
45
+ top: 5px;
46
+ right: 5px;
47
+ width: 16px;
48
+ height: 16px;
49
+ border-radius: 50%;
50
+ background: var(--color-error, #dc3545);
51
+ color: white;
52
+ border: none;
53
+ cursor: pointer;
54
+ display: none;
55
+ align-items: center;
56
+ justify-content: center;
57
+ font-size: 10px;
58
+ line-height: 1;
59
+ z-index: 10;
60
+ }
61
+
62
+ .action:hover .remove-button {
63
+ display: flex;
64
+ }
65
+
66
+ .action.removing .title {
67
+ background-color: var(--color-error, #dc3545) !important;
68
+ }
69
+
70
+ .action.removing .title .name {
71
+ color: white;
72
+ }
73
+
42
74
  .action.sortable {
43
75
  display: flex;
44
76
  align-items: stretch;
@@ -115,11 +147,13 @@ export class EditorNode extends RapidElement {
115
147
  padding: 0.75em;
116
148
  flex-grow:1;
117
149
  text-align: center;
150
+ display: flex;
151
+ flex-direction: column;
118
152
  }
119
153
 
120
154
  .action-exits {
121
- padding-bottom: 0.75em;
122
- margin-top: -0.75em;
155
+ padding-bottom: 0.6em;
156
+ margin-top: -0.8em;
123
157
  }
124
158
 
125
159
  .category .title {
@@ -136,14 +170,103 @@ export class EditorNode extends RapidElement {
136
170
  display: inline-block;
137
171
  }
138
172
 
173
+ .exit-wrapper {
174
+ display: flex;
175
+ justify-content: center;
176
+ align-items: center;
177
+ position: relative;
178
+ margin-bottom: -1.2em;
179
+ padding-top:0.2em;
180
+ }
181
+
139
182
  .exit {
140
- padding-top: 10px;
141
- margin-bottom: -10px;
183
+ width: 12px;
184
+ height: 12px;
185
+ border-radius: 50%;
186
+ background-color: tomato;
187
+ position: relative;
188
+ box-shadow: 0 2px 2px rgba(0, 0, 0, .1);
189
+ cursor: pointer;
190
+ pointer-events: none;
191
+ }
192
+
193
+ .exit.jtk-connected {
194
+ background: var(--color-connectors, #e6e6e6);
195
+ }
196
+
197
+ .exit.connected {
198
+ background-color: #fff;
199
+ pointer-events: all;
200
+ }
201
+
202
+ .exit.connected:hover {
203
+ background-color: var(--color-connectors, #e6e6e6);
204
+ }
205
+
206
+ .exit.removing, .exit.removing:hover {
207
+ background-color: var(--color-error);
208
+ pointer-events: all;
209
+ }
210
+
211
+ .exit.removing::before {
212
+ content: '✕';
213
+ position: absolute;
214
+ top: 50%;
215
+ left: 50%;
216
+ transform: translate(-50%, -50%);
217
+ font-size: 8px;
218
+ color: white;
219
+ line-height: 1;
220
+ }
221
+
222
+ /* Connector in removing state */
223
+ :host {
224
+ --color-connector-removing: var(--color-error);
225
+ }
226
+
227
+ body svg.plumb-connector.removing path {
228
+ stroke: var(--color-connector-removing, tomato) !important;
229
+ stroke-width: 3px;
230
+ }
231
+
232
+ body .plumb-connector.removing .plumb-arrow {
233
+ fill: var(--color-connector-removing, tomato) !important;
234
+ stroke: var(--color-connector-removing, transparent) !important;
235
+ }
236
+
237
+ .category:first-child {
238
+ border-bottom-left-radius: var(--curvature);
239
+ }
240
+
241
+ .category:last-child {
242
+ border-bottom-right-radius: var(--curvature);
243
+ }
244
+
245
+ .router .title {
246
+ border-top-left-radius: var(--curvature);
247
+ border-top-right-radius: var(--curvature);
248
+ }
249
+
250
+ .action{
251
+ overflow: hidden;
252
+ }
253
+
254
+ .action:first-child .title {
255
+ border-top-left-radius: var(--curvature);
256
+ border-top-right-radius: var(--curvature);
142
257
  }
143
258
  }`;
144
259
  }
145
260
  constructor() {
146
261
  super();
262
+ // Track exits that are in "removing" state
263
+ this.exitRemovalTimeouts = new Map();
264
+ // Set of exit UUIDs that are in the removing state
265
+ this.exitRemovingState = new Set();
266
+ // Track actions that are in "removing" state
267
+ this.actionRemovalTimeouts = new Map();
268
+ // Set of action UUIDs that are in the removing state
269
+ this.actionRemovingState = new Set();
147
270
  this.handleActionOrderChanged = this.handleActionOrderChanged.bind(this);
148
271
  }
149
272
  updated(changes) {
@@ -152,13 +275,12 @@ export class EditorNode extends RapidElement {
152
275
  if (changes.has('node')) {
153
276
  // make our initial connections
154
277
  if (changes.get('node') === undefined) {
155
- // this.plumber.makeTarget(this.node.uuid);
156
278
  for (const exit of this.node.exits) {
157
279
  if (!exit.destination_uuid) {
158
280
  this.plumber.makeSource(exit.uuid);
159
281
  }
160
282
  else {
161
- this.plumber.connectIds(exit.uuid, exit.destination_uuid);
283
+ this.plumber.connectIds(this.node.uuid, exit.uuid, exit.destination_uuid);
162
284
  }
163
285
  }
164
286
  }
@@ -167,6 +289,129 @@ export class EditorNode extends RapidElement {
167
289
  (_a = getStore()) === null || _a === void 0 ? void 0 : _a.getState().expandCanvas(this.ui.position.left + rect.width, this.ui.position.top + rect.height);
168
290
  }
169
291
  }
292
+ disconnectedCallback() {
293
+ // Remove the event listener when the component is removed
294
+ super.disconnectedCallback();
295
+ // Clear any pending exit removal timeouts
296
+ this.exitRemovalTimeouts.forEach((timeoutId) => {
297
+ clearTimeout(timeoutId);
298
+ });
299
+ this.exitRemovalTimeouts.clear();
300
+ // Clear any pending action removal timeouts
301
+ this.actionRemovalTimeouts.forEach((timeoutId) => {
302
+ clearTimeout(timeoutId);
303
+ });
304
+ this.actionRemovalTimeouts.clear();
305
+ // Clear the removing state
306
+ this.exitRemovingState.clear();
307
+ this.actionRemovingState.clear();
308
+ }
309
+ handleExitClick(event, exit) {
310
+ event.preventDefault();
311
+ event.stopPropagation();
312
+ const exitId = exit.uuid;
313
+ // If exit is not connected, do nothing
314
+ if (!exit.destination_uuid)
315
+ return;
316
+ // If the exit is already in removing state, perform the disconnect
317
+ if (this.exitRemovingState.has(exitId)) {
318
+ this.disconnectExit(exit);
319
+ return;
320
+ }
321
+ // Start removal UI state
322
+ this.exitRemovingState.add(exitId);
323
+ this.requestUpdate();
324
+ // Set the connection to removing state
325
+ this.plumber.setConnectionRemovingState(exitId, true);
326
+ // Clear any existing timeout for this exit
327
+ if (this.exitRemovalTimeouts.has(exitId)) {
328
+ clearTimeout(this.exitRemovalTimeouts.get(exitId));
329
+ }
330
+ // Set timeout to reset UI if user doesn't click
331
+ const timeoutId = window.setTimeout(() => {
332
+ this.exitRemovingState.delete(exitId);
333
+ this.exitRemovalTimeouts.delete(exitId);
334
+ // Reset the connection to normal state
335
+ this.plumber.setConnectionRemovingState(exitId, false);
336
+ this.requestUpdate();
337
+ }, 1500);
338
+ this.exitRemovalTimeouts.set(exitId, timeoutId);
339
+ }
340
+ disconnectExit(exit) {
341
+ var _a;
342
+ const exitId = exit.uuid;
343
+ // Clear the UI state
344
+ this.exitRemovingState.delete(exitId);
345
+ // Reset the connection to normal state (this will be redundant as we're about to remove it,
346
+ // but it's safer to do this in case there's any timing issue)
347
+ this.plumber.setConnectionRemovingState(exitId, false);
348
+ // Clear any timeout
349
+ if (this.exitRemovalTimeouts.has(exitId)) {
350
+ clearTimeout(this.exitRemovalTimeouts.get(exitId));
351
+ this.exitRemovalTimeouts.delete(exitId);
352
+ }
353
+ // Remove the JSPlumb connection
354
+ this.plumber.removeExitConnection(exitId);
355
+ // Update the flow definition
356
+ const updatedExit = { ...exit, destination_uuid: null };
357
+ const updatedExits = this.node.exits.map((e) => e.uuid === exitId ? updatedExit : e);
358
+ // Update the node
359
+ const updatedNode = { ...this.node, exits: updatedExits };
360
+ (_a = getStore()) === null || _a === void 0 ? void 0 : _a.getState().updateNode(this.node.uuid, updatedNode);
361
+ // Request update to reflect changes
362
+ this.requestUpdate();
363
+ }
364
+ handleActionRemoveClick(event, action, index) {
365
+ event.preventDefault();
366
+ event.stopPropagation();
367
+ const actionId = action.uuid;
368
+ // If the action is already in removing state, perform the removal
369
+ if (this.actionRemovingState.has(actionId)) {
370
+ this.removeAction(action, index);
371
+ return;
372
+ }
373
+ // Start removal UI state
374
+ this.actionRemovingState.add(actionId);
375
+ this.requestUpdate();
376
+ // Clear any existing timeout for this action
377
+ if (this.actionRemovalTimeouts.has(actionId)) {
378
+ clearTimeout(this.actionRemovalTimeouts.get(actionId));
379
+ }
380
+ // Set timeout to reset UI if user doesn't click
381
+ const timeoutId = window.setTimeout(() => {
382
+ this.actionRemovingState.delete(actionId);
383
+ this.actionRemovalTimeouts.delete(actionId);
384
+ this.requestUpdate();
385
+ }, 1000); // 1 second as per requirements
386
+ this.actionRemovalTimeouts.set(actionId, timeoutId);
387
+ }
388
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
389
+ removeAction(action, _index) {
390
+ var _a;
391
+ const actionId = action.uuid;
392
+ // Clear the UI state
393
+ this.actionRemovingState.delete(actionId);
394
+ // Clear any timeout
395
+ if (this.actionRemovalTimeouts.has(actionId)) {
396
+ clearTimeout(this.actionRemovalTimeouts.get(actionId));
397
+ this.actionRemovalTimeouts.delete(actionId);
398
+ }
399
+ // Remove the action from the node
400
+ const updatedActions = this.node.actions.filter((a) => a.uuid !== actionId);
401
+ // If no actions remain, remove the entire node
402
+ if (updatedActions.length === 0) {
403
+ this.fireCustomEvent(CustomEventType.NodeDeleted, {
404
+ uuid: this.node.uuid
405
+ });
406
+ }
407
+ else {
408
+ // Update the node with remaining actions
409
+ const updatedNode = { ...this.node, actions: updatedActions };
410
+ (_a = getStore()) === null || _a === void 0 ? void 0 : _a.getState().updateNode(this.node.uuid, updatedNode);
411
+ // Request update to reflect changes
412
+ this.requestUpdate();
413
+ }
414
+ }
170
415
  handleActionOrderChanged(event) {
171
416
  var _a;
172
417
  const [fromIdx, toIdx] = event.detail.swap;
@@ -180,25 +425,33 @@ export class EditorNode extends RapidElement {
180
425
  this.node = { ...this.node, actions: newActions };
181
426
  (_a = getStore()) === null || _a === void 0 ? void 0 : _a.getState().updateNode(this.node.uuid, { ...this.node, actions: newActions });
182
427
  }
183
- renderTitle(config) {
428
+ renderTitle(config, isRemoving = false) {
184
429
  var _a, _b;
185
430
  return html `<div class="title" style="background:${config.color}">
186
431
  ${((_b = (_a = this.node) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.length) > 1
187
432
  ? html `<temba-icon class="drag-handle" name="sort"></temba-icon>`
188
433
  : null}
189
434
 
190
- <div class="name">${config.name}</div>
435
+ <div class="name">${isRemoving ? 'Remove?' : config.name}</div>
191
436
  </div>`;
192
437
  }
193
438
  renderAction(node, action, index) {
194
439
  const config = EDITOR_CONFIG[action.type];
440
+ const isRemoving = this.actionRemovingState.has(action.uuid);
195
441
  if (config) {
196
442
  return html `<div
197
- class="action sortable ${action.type}"
443
+ class="action sortable ${action.type} ${isRemoving ? 'removing' : ''}"
198
444
  id="action-${index}"
199
445
  >
446
+ <button
447
+ class="remove-button"
448
+ @click=${(e) => this.handleActionRemoveClick(e, action, index)}
449
+ title="Remove action"
450
+ >
451
+
452
+ </button>
200
453
  <div class="action-content">
201
- ${this.renderTitle(config)}
454
+ ${this.renderTitle(config, isRemoving)}
202
455
  <div class="body">
203
456
  ${config.render
204
457
  ? config.render(node, action)
@@ -207,7 +460,17 @@ export class EditorNode extends RapidElement {
207
460
  </div>
208
461
  </div>`;
209
462
  }
210
- return html `<div class="action sortable" id="action-${index}">
463
+ return html `<div
464
+ class="action sortable ${isRemoving ? 'removing' : ''}"
465
+ id="action-${index}"
466
+ >
467
+ <button
468
+ class="remove-button"
469
+ @click=${(e) => this.handleActionRemoveClick(e, action, index)}
470
+ title="Remove action"
471
+ >
472
+
473
+ </button>
211
474
  ${action.type}
212
475
  </div>`;
213
476
  }
@@ -215,7 +478,7 @@ export class EditorNode extends RapidElement {
215
478
  const config = EDITOR_CONFIG[ui.type];
216
479
  if (config) {
217
480
  return html `<div class="router">
218
- ${this.renderTitle(config)}
481
+ ${this.renderTitle(config, false)}
219
482
  ${router.result_name
220
483
  ? html `<div class="body">
221
484
  Save as
@@ -239,13 +502,17 @@ export class EditorNode extends RapidElement {
239
502
  return html `<div class="categories">${categories}</div>`;
240
503
  }
241
504
  renderExit(exit) {
242
- return html `<div
243
- id="${exit.uuid}"
244
- class=${getClasses({
505
+ return html `<div class="exit-wrapper">
506
+ <div
507
+ id="${exit.uuid}"
508
+ class=${getClasses({
245
509
  exit: true,
246
- connected: !!exit.destination_uuid
510
+ connected: !!exit.destination_uuid,
511
+ removing: this.exitRemovingState.has(exit.uuid)
247
512
  })}
248
- ></div>`;
513
+ @click=${(e) => this.handleExitClick(e, exit)}
514
+ ></div>
515
+ </div>`;
249
516
  }
250
517
  render() {
251
518
  if (!this.node || !this.ui) {