@nyaruka/temba-components 0.129.2 → 0.129.4

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 (773) hide show
  1. package/.eslintrc.js +1 -0
  2. package/.github/workflows/build.yml +141 -8
  3. package/CHANGELOG.md +40 -0
  4. package/README.md +6 -0
  5. package/check-coverage.js +133 -0
  6. package/demo/data/flows/sample-flow.json +158 -128
  7. package/demo/field-config-demo.html +135 -0
  8. package/dist/temba-components.js +1750 -751
  9. package/dist/temba-components.js.map +1 -1
  10. package/docs/ActionEditor-Migration.md +118 -0
  11. package/generate-coverage-badge.sh +69 -0
  12. package/out-tsc/src/{vectoricon/index.js → Icons.js} +1 -1
  13. package/out-tsc/src/Icons.js.map +1 -0
  14. package/out-tsc/src/display/Alert.js.map +1 -0
  15. package/out-tsc/src/display/Anchor.js.map +1 -0
  16. package/out-tsc/src/display/Button.js.map +1 -0
  17. package/out-tsc/src/{charcount → display}/CharCount.js +159 -2
  18. package/out-tsc/src/display/CharCount.js.map +1 -0
  19. package/out-tsc/src/display/Chat.js.map +1 -0
  20. package/out-tsc/src/display/ContactName.js.map +1 -0
  21. package/out-tsc/src/display/ContactUrn.js.map +1 -0
  22. package/out-tsc/src/display/Dropdown.js.map +1 -0
  23. package/out-tsc/src/{vectoricon/VectorIcon.js → display/Icon.js} +2 -2
  24. package/out-tsc/src/display/Icon.js.map +1 -0
  25. package/out-tsc/src/display/Label.js.map +1 -0
  26. package/out-tsc/src/{leafletmap → display}/LeafletMap.js +16 -1
  27. package/out-tsc/src/display/LeafletMap.js.map +1 -0
  28. package/out-tsc/src/display/Lightbox.js.map +1 -0
  29. package/out-tsc/src/{loading → display}/Loading.js.map +1 -1
  30. package/out-tsc/src/{options → display}/Options.js.map +1 -1
  31. package/out-tsc/src/display/ProgressBar.js.map +1 -0
  32. package/out-tsc/src/display/TembaDate.js.map +1 -0
  33. package/out-tsc/src/display/TembaUser.js.map +1 -0
  34. package/out-tsc/src/display/Thumbnail.js.map +1 -0
  35. package/out-tsc/src/{tip → display}/Tip.js +1 -2
  36. package/out-tsc/src/display/Tip.js.map +1 -0
  37. package/out-tsc/src/display/Toast.js.map +1 -0
  38. package/out-tsc/src/display/sms/gsmsplitter.js.map +1 -0
  39. package/out-tsc/src/display/sms/gsmvalidator.js.map +1 -0
  40. package/out-tsc/src/display/sms/index.js.map +1 -0
  41. package/out-tsc/src/display/sms/unicodesplitter.js.map +1 -0
  42. package/out-tsc/src/events.js +2 -0
  43. package/out-tsc/src/events.js.map +1 -0
  44. package/out-tsc/src/excellent/ExcellentParser.js.map +1 -0
  45. package/out-tsc/src/excellent/helpers.js.map +1 -0
  46. package/out-tsc/src/flow/CanvasNode.js +861 -0
  47. package/out-tsc/src/flow/CanvasNode.js.map +1 -0
  48. package/out-tsc/src/flow/Editor.js +640 -143
  49. package/out-tsc/src/flow/Editor.js.map +1 -1
  50. package/out-tsc/src/flow/NodeEditor.js +1200 -0
  51. package/out-tsc/src/flow/NodeEditor.js.map +1 -0
  52. package/out-tsc/src/flow/Plumber.js +148 -74
  53. package/out-tsc/src/flow/Plumber.js.map +1 -1
  54. package/out-tsc/src/flow/StickyNote.js +153 -9
  55. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  56. package/out-tsc/src/flow/actions/add_contact_groups.js +40 -0
  57. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -0
  58. package/out-tsc/src/flow/actions/add_contact_urn.js +16 -0
  59. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -0
  60. package/out-tsc/src/flow/actions/add_input_labels.js +11 -0
  61. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -0
  62. package/out-tsc/src/flow/actions/call_classifier.js +11 -0
  63. package/out-tsc/src/flow/actions/call_classifier.js.map +1 -0
  64. package/out-tsc/src/flow/actions/call_llm.js +11 -0
  65. package/out-tsc/src/flow/actions/call_llm.js.map +1 -0
  66. package/out-tsc/src/flow/actions/call_resthook.js +11 -0
  67. package/out-tsc/src/flow/actions/call_resthook.js.map +1 -0
  68. package/out-tsc/src/flow/actions/call_webhook.js +122 -0
  69. package/out-tsc/src/flow/actions/call_webhook.js.map +1 -0
  70. package/out-tsc/src/flow/actions/enter_flow.js +14 -0
  71. package/out-tsc/src/flow/actions/enter_flow.js.map +1 -0
  72. package/out-tsc/src/flow/actions/open_ticket.js +11 -0
  73. package/out-tsc/src/flow/actions/open_ticket.js.map +1 -0
  74. package/out-tsc/src/flow/actions/play_audio.js +11 -0
  75. package/out-tsc/src/flow/actions/play_audio.js.map +1 -0
  76. package/out-tsc/src/flow/actions/remove_contact_groups.js +62 -0
  77. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -0
  78. package/out-tsc/src/flow/actions/request_optin.js +11 -0
  79. package/out-tsc/src/flow/actions/request_optin.js.map +1 -0
  80. package/out-tsc/src/flow/actions/say_msg.js +11 -0
  81. package/out-tsc/src/flow/actions/say_msg.js.map +1 -0
  82. package/out-tsc/src/flow/actions/send_broadcast.js +33 -0
  83. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -0
  84. package/out-tsc/src/flow/actions/send_email.js +56 -0
  85. package/out-tsc/src/flow/actions/send_email.js.map +1 -0
  86. package/out-tsc/src/flow/actions/send_msg.js +55 -0
  87. package/out-tsc/src/flow/actions/send_msg.js.map +1 -0
  88. package/out-tsc/src/flow/actions/set_contact_channel.js +12 -0
  89. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -0
  90. package/out-tsc/src/flow/actions/set_contact_field.js +12 -0
  91. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -0
  92. package/out-tsc/src/flow/actions/set_contact_language.js +10 -0
  93. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -0
  94. package/out-tsc/src/flow/actions/set_contact_name.js +10 -0
  95. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -0
  96. package/out-tsc/src/flow/actions/set_contact_status.js +10 -0
  97. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -0
  98. package/out-tsc/src/flow/actions/set_run_result.js +10 -0
  99. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -0
  100. package/out-tsc/src/flow/actions/split_by_expression_example.js +77 -0
  101. package/out-tsc/src/flow/actions/split_by_expression_example.js.map +1 -0
  102. package/out-tsc/src/flow/actions/start_session.js +11 -0
  103. package/out-tsc/src/flow/actions/start_session.js.map +1 -0
  104. package/out-tsc/src/flow/actions/transfer_airtime.js +11 -0
  105. package/out-tsc/src/flow/actions/transfer_airtime.js.map +1 -0
  106. package/out-tsc/src/flow/config.js +88 -123
  107. package/out-tsc/src/flow/config.js.map +1 -1
  108. package/out-tsc/src/flow/nodes/execute_actions.js +4 -0
  109. package/out-tsc/src/flow/nodes/execute_actions.js.map +1 -0
  110. package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -0
  111. package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -0
  112. package/out-tsc/src/flow/nodes/split_by_contact_field.js +7 -0
  113. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -0
  114. package/out-tsc/src/flow/nodes/split_by_expression.js +7 -0
  115. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -0
  116. package/out-tsc/src/flow/nodes/split_by_groups.js +7 -0
  117. package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -0
  118. package/out-tsc/src/flow/nodes/split_by_random.js +10 -0
  119. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -0
  120. package/out-tsc/src/flow/nodes/split_by_run_result.js +7 -0
  121. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -0
  122. package/out-tsc/src/flow/nodes/split_by_scheme.js +7 -0
  123. package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -0
  124. package/out-tsc/src/flow/nodes/split_by_subflow.js +9 -0
  125. package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -0
  126. package/out-tsc/src/flow/nodes/split_by_webhook.js +18 -0
  127. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -0
  128. package/out-tsc/src/flow/nodes/wait_for_audio.js +7 -0
  129. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -0
  130. package/out-tsc/src/flow/nodes/wait_for_digits.js +7 -0
  131. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -0
  132. package/out-tsc/src/flow/nodes/wait_for_image.js +7 -0
  133. package/out-tsc/src/flow/nodes/wait_for_image.js.map +1 -0
  134. package/out-tsc/src/flow/nodes/wait_for_location.js +7 -0
  135. package/out-tsc/src/flow/nodes/wait_for_location.js.map +1 -0
  136. package/out-tsc/src/flow/nodes/wait_for_menu.js +7 -0
  137. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -0
  138. package/out-tsc/src/flow/nodes/wait_for_response.js +7 -0
  139. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -0
  140. package/out-tsc/src/flow/nodes/wait_for_video.js +7 -0
  141. package/out-tsc/src/flow/nodes/wait_for_video.js.map +1 -0
  142. package/out-tsc/src/flow/types.js +79 -0
  143. package/out-tsc/src/flow/types.js.map +1 -0
  144. package/out-tsc/src/flow/utils.js +65 -0
  145. package/out-tsc/src/flow/utils.js.map +1 -0
  146. package/out-tsc/src/form/ArrayEditor.js +199 -0
  147. package/out-tsc/src/form/ArrayEditor.js.map +1 -0
  148. package/out-tsc/src/form/BaseListEditor.js +128 -0
  149. package/out-tsc/src/form/BaseListEditor.js.map +1 -0
  150. package/out-tsc/src/{checkbox → form}/Checkbox.js +19 -4
  151. package/out-tsc/src/form/Checkbox.js.map +1 -0
  152. package/out-tsc/src/{colorpicker → form}/ColorPicker.js +1 -1
  153. package/out-tsc/src/form/ColorPicker.js.map +1 -0
  154. package/out-tsc/src/{completion → form}/Completion.js +8 -2
  155. package/out-tsc/src/form/Completion.js.map +1 -0
  156. package/out-tsc/src/{compose → form}/Compose.js +1 -1
  157. package/out-tsc/src/form/Compose.js.map +1 -0
  158. package/out-tsc/src/{contactsearch → form}/ContactSearch.js +2 -2
  159. package/out-tsc/src/form/ContactSearch.js.map +1 -0
  160. package/out-tsc/src/form/CroppieCSS.js.map +1 -0
  161. package/out-tsc/src/{datepicker → form}/DatePicker.js +1 -1
  162. package/out-tsc/src/form/DatePicker.js.map +1 -0
  163. package/out-tsc/src/{FormElement.js → form/FormElement.js} +1 -1
  164. package/out-tsc/src/form/FormElement.js.map +1 -0
  165. package/out-tsc/src/form/FormField.js +243 -0
  166. package/out-tsc/src/form/FormField.js.map +1 -0
  167. package/out-tsc/src/{imagepicker → form}/ImagePicker.js +2 -2
  168. package/out-tsc/src/form/ImagePicker.js.map +1 -0
  169. package/out-tsc/src/form/KeyValueEditor.js +223 -0
  170. package/out-tsc/src/form/KeyValueEditor.js.map +1 -0
  171. package/out-tsc/src/{mediapicker → form}/MediaPicker.js +1 -1
  172. package/out-tsc/src/form/MediaPicker.js.map +1 -0
  173. package/out-tsc/src/form/RangePicker.js.map +1 -0
  174. package/out-tsc/src/{slider → form}/TembaSlider.js +1 -1
  175. package/out-tsc/src/form/TembaSlider.js.map +1 -0
  176. package/out-tsc/src/{templates → form}/TemplateEditor.js +1 -1
  177. package/out-tsc/src/form/TemplateEditor.js.map +1 -0
  178. package/out-tsc/src/{textinput → form}/TextInput.js +3 -3
  179. package/out-tsc/src/form/TextInput.js.map +1 -0
  180. package/out-tsc/src/{omnibox → form/select}/Omnibox.js +2 -2
  181. package/out-tsc/src/form/select/Omnibox.js.map +1 -0
  182. package/out-tsc/src/{select → form/select}/PopupSelect.js +1 -1
  183. package/out-tsc/src/form/select/PopupSelect.js.map +1 -0
  184. package/out-tsc/src/{select → form/select}/Select.js +157 -113
  185. package/out-tsc/src/form/select/Select.js.map +1 -0
  186. package/out-tsc/src/{select → form/select}/UserSelect.js +1 -1
  187. package/out-tsc/src/form/select/UserSelect.js.map +1 -0
  188. package/out-tsc/src/{select → form/select}/WorkspaceSelect.js +1 -1
  189. package/out-tsc/src/form/select/WorkspaceSelect.js.map +1 -0
  190. package/out-tsc/src/interfaces.js +7 -0
  191. package/out-tsc/src/interfaces.js.map +1 -1
  192. package/out-tsc/src/layout/Dialog.js.map +1 -0
  193. package/out-tsc/src/layout/Mask.js.map +1 -0
  194. package/out-tsc/src/{dialog → layout}/Modax.js.map +1 -1
  195. package/out-tsc/src/layout/Resizer.js.map +1 -0
  196. package/out-tsc/src/layout/Tab.js.map +1 -0
  197. package/out-tsc/src/layout/TabPane.js.map +1 -0
  198. package/out-tsc/src/list/NotificationList.js +1 -1
  199. package/out-tsc/src/list/NotificationList.js.map +1 -1
  200. package/out-tsc/src/list/RunList.js +1 -1
  201. package/out-tsc/src/list/RunList.js.map +1 -1
  202. package/out-tsc/src/list/ShortcutList.js.map +1 -1
  203. package/out-tsc/src/list/TembaMenu.js +1 -1
  204. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  205. package/out-tsc/src/list/TicketList.js +1 -1
  206. package/out-tsc/src/list/TicketList.js.map +1 -1
  207. package/out-tsc/src/{aliaseditor → live}/AliasEditor.js +1 -1
  208. package/out-tsc/src/live/AliasEditor.js.map +1 -0
  209. package/out-tsc/src/{contacts → live}/ContactBadges.js +1 -1
  210. package/out-tsc/src/live/ContactBadges.js.map +1 -0
  211. package/out-tsc/src/{contacts → live}/ContactChat.js +80 -78
  212. package/out-tsc/src/live/ContactChat.js.map +1 -0
  213. package/out-tsc/src/{contacts → live}/ContactDetails.js +1 -1
  214. package/out-tsc/src/live/ContactDetails.js.map +1 -0
  215. package/out-tsc/src/{contacts → live}/ContactFieldEditor.js +2 -2
  216. package/out-tsc/src/live/ContactFieldEditor.js.map +1 -0
  217. package/out-tsc/src/live/ContactFields.js.map +1 -0
  218. package/out-tsc/src/live/ContactNameFetch.js.map +1 -0
  219. package/out-tsc/src/{contacts → live}/ContactNotepad.js +1 -1
  220. package/out-tsc/src/{contacts → live}/ContactNotepad.js.map +1 -1
  221. package/out-tsc/src/{contacts → live}/ContactPending.js +1 -1
  222. package/out-tsc/src/live/ContactPending.js.map +1 -0
  223. package/out-tsc/src/live/ContactStoreElement.js.map +1 -0
  224. package/out-tsc/src/live/FieldManager.js.map +1 -0
  225. package/out-tsc/src/live/StartProgress.js.map +1 -0
  226. package/out-tsc/src/live/TembaChart.js.map +1 -0
  227. package/out-tsc/src/store/AppState.js +54 -24
  228. package/out-tsc/src/store/AppState.js.map +1 -1
  229. package/out-tsc/src/store/Store.js +1 -1
  230. package/out-tsc/src/store/Store.js.map +1 -1
  231. package/out-tsc/src/{utils/index.js → utils.js} +22 -1
  232. package/out-tsc/src/utils.js.map +1 -0
  233. package/out-tsc/src/webchat/WebChat.js +1 -1
  234. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  235. package/out-tsc/temba-components.js +2 -2
  236. package/out-tsc/temba-components.js.map +1 -1
  237. package/out-tsc/temba-modules.js +63 -56
  238. package/out-tsc/temba-modules.js.map +1 -1
  239. package/out-tsc/temba-webchat.js +2 -2
  240. package/out-tsc/temba-webchat.js.map +1 -1
  241. package/out-tsc/test/ActionHelper.js +116 -0
  242. package/out-tsc/test/ActionHelper.js.map +1 -0
  243. package/out-tsc/test/actions/add_contact_groups.test.js +66 -0
  244. package/out-tsc/test/actions/add_contact_groups.test.js.map +1 -0
  245. package/out-tsc/test/actions/remove_contact_groups.test.js +226 -0
  246. package/out-tsc/test/actions/remove_contact_groups.test.js.map +1 -0
  247. package/out-tsc/test/actions/send_email.test.js +160 -0
  248. package/out-tsc/test/actions/send_email.test.js.map +1 -0
  249. package/out-tsc/test/actions/send_msg.test.js +95 -0
  250. package/out-tsc/test/actions/send_msg.test.js.map +1 -0
  251. package/out-tsc/test/temba-action-editing-integration.test.js +183 -0
  252. package/out-tsc/test/temba-action-editing-integration.test.js.map +1 -0
  253. package/out-tsc/test/temba-alert.test.js +1 -1
  254. package/out-tsc/test/temba-alert.test.js.map +1 -1
  255. package/out-tsc/test/temba-appstate-language.test.js +90 -0
  256. package/out-tsc/test/temba-appstate-language.test.js.map +1 -1
  257. package/out-tsc/test/temba-charcount.test.js.map +1 -1
  258. package/out-tsc/test/temba-chart.test.js +1 -1
  259. package/out-tsc/test/temba-chart.test.js.map +1 -1
  260. package/out-tsc/test/temba-checkbox.test.js +1 -1
  261. package/out-tsc/test/temba-checkbox.test.js.map +1 -1
  262. package/out-tsc/test/temba-color-picker.test.js +1 -1
  263. package/out-tsc/test/temba-color-picker.test.js.map +1 -1
  264. package/out-tsc/test/temba-completion.test.js +1 -1
  265. package/out-tsc/test/temba-completion.test.js.map +1 -1
  266. package/out-tsc/test/temba-compose.test.js +1 -1
  267. package/out-tsc/test/temba-compose.test.js.map +1 -1
  268. package/out-tsc/test/temba-contact-badges.test.js +1 -1
  269. package/out-tsc/test/temba-contact-badges.test.js.map +1 -1
  270. package/out-tsc/test/temba-contact-chat.test.js +3 -1
  271. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  272. package/out-tsc/test/temba-contact-details.test.js +1 -1
  273. package/out-tsc/test/temba-contact-details.test.js.map +1 -1
  274. package/out-tsc/test/temba-contact-fields.test.js +1 -1
  275. package/out-tsc/test/temba-contact-fields.test.js.map +1 -1
  276. package/out-tsc/test/temba-contact-search.test.js +1 -1
  277. package/out-tsc/test/temba-contact-search.test.js.map +1 -1
  278. package/out-tsc/test/temba-date.test.js +5 -1
  279. package/out-tsc/test/temba-date.test.js.map +1 -1
  280. package/out-tsc/test/temba-datepicker.test.js +1 -1
  281. package/out-tsc/test/temba-datepicker.test.js.map +1 -1
  282. package/out-tsc/test/temba-dialog.test.js +1 -1
  283. package/out-tsc/test/temba-dialog.test.js.map +1 -1
  284. package/out-tsc/test/temba-dropdown.test.js +1 -1
  285. package/out-tsc/test/temba-dropdown.test.js.map +1 -1
  286. package/out-tsc/test/temba-excellent-helpers.test.js +316 -0
  287. package/out-tsc/test/temba-excellent-helpers.test.js.map +1 -0
  288. package/out-tsc/test/temba-field-config.test.js +133 -0
  289. package/out-tsc/test/temba-field-config.test.js.map +1 -0
  290. package/out-tsc/test/temba-field-manager.test.js.map +1 -1
  291. package/out-tsc/test/temba-flow-editor-node.test.js +426 -13
  292. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  293. package/out-tsc/test/temba-flow-editor.test.js +185 -0
  294. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  295. package/out-tsc/test/temba-flow-plumber-connections.test.js +113 -0
  296. package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -0
  297. package/out-tsc/test/temba-flow-plumber.test.js +73 -93
  298. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  299. package/out-tsc/test/temba-flow-self-routing.test.js +172 -0
  300. package/out-tsc/test/temba-flow-self-routing.test.js.map +1 -0
  301. package/out-tsc/test/temba-formfield.test.js.map +1 -1
  302. package/out-tsc/test/temba-icon.test.js +1 -1
  303. package/out-tsc/test/temba-icon.test.js.map +1 -1
  304. package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
  305. package/out-tsc/test/temba-label.test.js +1 -1
  306. package/out-tsc/test/temba-label.test.js.map +1 -1
  307. package/out-tsc/test/temba-lightbox.test.js +1 -1
  308. package/out-tsc/test/temba-lightbox.test.js.map +1 -1
  309. package/out-tsc/test/temba-markdown.test.js +127 -0
  310. package/out-tsc/test/temba-markdown.test.js.map +1 -0
  311. package/out-tsc/test/temba-menu.test.js +1 -1
  312. package/out-tsc/test/temba-menu.test.js.map +1 -1
  313. package/out-tsc/test/temba-modax.test.js +1 -1
  314. package/out-tsc/test/temba-modax.test.js.map +1 -1
  315. package/out-tsc/test/temba-modules.test.js +47 -0
  316. package/out-tsc/test/temba-modules.test.js.map +1 -0
  317. package/out-tsc/test/temba-node-editor.test.js +283 -0
  318. package/out-tsc/test/temba-node-editor.test.js.map +1 -0
  319. package/out-tsc/test/temba-omnibox.test.js +1 -1
  320. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  321. package/out-tsc/test/temba-options.test.js.map +1 -1
  322. package/out-tsc/test/temba-range-picker.test.js +9 -2
  323. package/out-tsc/test/temba-range-picker.test.js.map +1 -1
  324. package/out-tsc/test/temba-rapid-element.test.js +273 -0
  325. package/out-tsc/test/temba-rapid-element.test.js.map +1 -0
  326. package/out-tsc/test/temba-resize-element.test.js +85 -0
  327. package/out-tsc/test/temba-resize-element.test.js.map +1 -0
  328. package/out-tsc/test/temba-select.test.js +87 -2
  329. package/out-tsc/test/temba-select.test.js.map +1 -1
  330. package/out-tsc/test/temba-slider.test.js.map +1 -1
  331. package/out-tsc/test/temba-sticky-note.test.js +194 -0
  332. package/out-tsc/test/temba-sticky-note.test.js.map +1 -0
  333. package/out-tsc/test/temba-template-editor.test.js.map +1 -1
  334. package/out-tsc/test/temba-textinput.test.js +1 -1
  335. package/out-tsc/test/temba-textinput.test.js.map +1 -1
  336. package/out-tsc/test/temba-tip.test.js +1 -1
  337. package/out-tsc/test/temba-tip.test.js.map +1 -1
  338. package/out-tsc/test/temba-toast.test.js +1 -1
  339. package/out-tsc/test/temba-toast.test.js.map +1 -1
  340. package/out-tsc/test/temba-utils-index.test.js +1 -1
  341. package/out-tsc/test/temba-utils-index.test.js.map +1 -1
  342. package/out-tsc/test/temba-utils-uuid.test.js +38 -0
  343. package/out-tsc/test/temba-utils-uuid.test.js.map +1 -0
  344. package/out-tsc/test/temba-webchat.test.js +28 -12
  345. package/out-tsc/test/temba-webchat.test.js.map +1 -1
  346. package/out-tsc/test/utils.test.js +2 -6
  347. package/out-tsc/test/utils.test.js.map +1 -1
  348. package/package.json +18 -9
  349. package/rollup.components.mjs +1 -1
  350. package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
  351. package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
  352. package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
  353. package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
  354. package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
  355. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  356. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  357. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  358. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  359. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  360. package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
  361. package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
  362. package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
  363. package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
  364. package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
  365. package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
  366. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  367. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  368. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  369. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  370. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  371. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  372. package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
  373. package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
  374. package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
  375. package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
  376. package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
  377. package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
  378. package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
  379. package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
  380. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  381. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  382. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  383. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  384. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  385. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  386. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  387. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  388. package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
  389. package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
  390. package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
  391. package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
  392. package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
  393. package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
  394. package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
  395. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  396. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  397. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  398. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  399. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  400. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  401. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  402. package/screenshots/truth/datepicker/range-picker-all.png +0 -0
  403. package/screenshots/truth/datepicker/range-picker-button-states.png +0 -0
  404. package/screenshots/truth/datepicker/range-picker-default.png +0 -0
  405. package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
  406. package/screenshots/truth/datepicker/range-picker-initial-values.png +0 -0
  407. package/screenshots/truth/datepicker/range-picker-week.png +0 -0
  408. package/screenshots/truth/datepicker/range-picker-year.png +0 -0
  409. package/screenshots/truth/editor/router.png +0 -0
  410. package/screenshots/truth/editor/send_msg.png +0 -0
  411. package/screenshots/truth/editor/set_contact_language.png +0 -0
  412. package/screenshots/truth/editor/set_contact_name.png +0 -0
  413. package/screenshots/truth/editor/set_run_result.png +0 -0
  414. package/screenshots/truth/editor/wait.png +0 -0
  415. package/screenshots/truth/formfield/markdown-errors.png +0 -0
  416. package/screenshots/truth/formfield/plain-text-errors.png +0 -0
  417. package/screenshots/truth/formfield/widget-only-markdown-errors.png +0 -0
  418. package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
  419. package/screenshots/truth/sticky-note/blue-color.png +0 -0
  420. package/screenshots/truth/sticky-note/blue.png +0 -0
  421. package/screenshots/truth/sticky-note/color-picker-expanded.png +0 -0
  422. package/screenshots/truth/sticky-note/default.png +0 -0
  423. package/screenshots/truth/sticky-note/gray-color.png +0 -0
  424. package/screenshots/truth/sticky-note/gray.png +0 -0
  425. package/screenshots/truth/sticky-note/green-color.png +0 -0
  426. package/screenshots/truth/sticky-note/green.png +0 -0
  427. package/screenshots/truth/sticky-note/pink-color.png +0 -0
  428. package/screenshots/truth/sticky-note/pink.png +0 -0
  429. package/screenshots/truth/sticky-note/yellow-color.png +0 -0
  430. package/screenshots/truth/sticky-note/yellow.png +0 -0
  431. package/src/{charcount → display}/CharCount.ts +164 -2
  432. package/src/{vectoricon/VectorIcon.ts → display/Icon.ts} +1 -1
  433. package/src/{leafletmap → display}/LeafletMap.ts +19 -1
  434. package/src/{thumbnail → display}/Thumbnail.ts +1 -1
  435. package/src/{tip → display}/Tip.ts +1 -2
  436. package/src/events.ts +108 -0
  437. package/src/flow/CanvasNode.ts +1009 -0
  438. package/src/flow/Editor.ts +795 -169
  439. package/src/flow/NodeEditor.ts +1443 -0
  440. package/src/flow/Plumber.ts +177 -79
  441. package/src/flow/StickyNote.ts +165 -9
  442. package/src/flow/actions/add_contact_groups.ts +42 -0
  443. package/src/flow/actions/add_contact_urn.ts +17 -0
  444. package/src/flow/actions/add_input_labels.ts +12 -0
  445. package/src/flow/actions/call_classifier.ts +12 -0
  446. package/src/flow/actions/call_llm.ts +12 -0
  447. package/src/flow/actions/call_resthook.ts +12 -0
  448. package/src/flow/actions/call_webhook.ts +133 -0
  449. package/src/flow/actions/enter_flow.ts +15 -0
  450. package/src/flow/actions/open_ticket.ts +12 -0
  451. package/src/flow/actions/play_audio.ts +12 -0
  452. package/src/flow/actions/remove_contact_groups.ts +66 -0
  453. package/src/flow/actions/request_optin.ts +12 -0
  454. package/src/flow/actions/say_msg.ts +12 -0
  455. package/src/flow/actions/send_broadcast.ts +35 -0
  456. package/src/flow/actions/send_email.ts +60 -0
  457. package/src/flow/actions/send_msg.ts +58 -0
  458. package/src/flow/actions/set_contact_channel.ts +13 -0
  459. package/src/flow/actions/set_contact_field.ts +13 -0
  460. package/src/flow/actions/set_contact_language.ts +11 -0
  461. package/src/flow/actions/set_contact_name.ts +11 -0
  462. package/src/flow/actions/set_contact_status.ts +11 -0
  463. package/src/flow/actions/set_run_result.ts +11 -0
  464. package/src/flow/actions/split_by_expression_example.ts +88 -0
  465. package/src/flow/actions/start_session.ts +12 -0
  466. package/src/flow/actions/transfer_airtime.ts +12 -0
  467. package/src/flow/config.ts +93 -136
  468. package/src/flow/nodes/execute_actions.ts +5 -0
  469. package/src/flow/nodes/split_by_airtime.ts +9 -0
  470. package/src/flow/nodes/split_by_contact_field.ts +7 -0
  471. package/src/flow/nodes/split_by_expression.ts +7 -0
  472. package/src/flow/nodes/split_by_groups.ts +7 -0
  473. package/src/flow/nodes/split_by_random.ts +10 -0
  474. package/src/flow/nodes/split_by_run_result.ts +7 -0
  475. package/src/flow/nodes/split_by_scheme.ts +7 -0
  476. package/src/flow/nodes/split_by_subflow.ts +9 -0
  477. package/src/flow/nodes/split_by_webhook.ts +19 -0
  478. package/src/flow/nodes/wait_for_audio.ts +7 -0
  479. package/src/flow/nodes/wait_for_digits.ts +7 -0
  480. package/src/flow/nodes/wait_for_image.ts +7 -0
  481. package/src/flow/nodes/wait_for_location.ts +7 -0
  482. package/src/flow/nodes/wait_for_menu.ts +7 -0
  483. package/src/flow/nodes/wait_for_response.ts +7 -0
  484. package/src/flow/nodes/wait_for_video.ts +7 -0
  485. package/src/flow/types.ts +352 -0
  486. package/src/flow/utils.ts +76 -0
  487. package/src/form/ArrayEditor.ts +240 -0
  488. package/src/form/BaseListEditor.ts +177 -0
  489. package/src/{checkbox → form}/Checkbox.ts +24 -5
  490. package/src/{colorpicker → form}/ColorPicker.ts +2 -2
  491. package/src/{completion → form}/Completion.ts +9 -3
  492. package/src/{compose → form}/Compose.ts +7 -7
  493. package/src/{contactsearch → form}/ContactSearch.ts +6 -6
  494. package/src/{datepicker → form}/DatePicker.ts +1 -1
  495. package/src/{FormElement.ts → form/FormElement.ts} +1 -1
  496. package/src/form/FormField.ts +238 -0
  497. package/src/{imagepicker → form}/ImagePicker.ts +2 -2
  498. package/src/form/KeyValueEditor.ts +251 -0
  499. package/src/{mediapicker → form}/MediaPicker.ts +1 -1
  500. package/src/{slider → form}/TembaSlider.ts +1 -1
  501. package/src/{templates → form}/TemplateEditor.ts +2 -2
  502. package/src/{textinput → form}/TextInput.ts +5 -5
  503. package/src/{omnibox → form/select}/Omnibox.ts +2 -2
  504. package/src/{select → form/select}/PopupSelect.ts +1 -1
  505. package/src/{select → form/select}/Select.ts +207 -152
  506. package/src/{select → form/select}/UserSelect.ts +1 -1
  507. package/src/{select → form/select}/WorkspaceSelect.ts +1 -1
  508. package/src/interfaces.ts +8 -2
  509. package/src/{dialog → layout}/Dialog.ts +1 -1
  510. package/src/list/NotificationList.ts +2 -2
  511. package/src/list/RunList.ts +3 -3
  512. package/src/list/ShortcutList.ts +1 -1
  513. package/src/list/TembaMenu.ts +2 -2
  514. package/src/list/TicketList.ts +1 -1
  515. package/src/{aliaseditor → live}/AliasEditor.ts +3 -3
  516. package/src/{contacts → live}/ContactBadges.ts +1 -1
  517. package/src/{contacts → live}/ContactChat.ts +120 -104
  518. package/src/{contacts → live}/ContactDetails.ts +1 -1
  519. package/src/{contacts → live}/ContactFieldEditor.ts +4 -4
  520. package/src/{contacts → live}/ContactFields.ts +1 -1
  521. package/src/{contacts → live}/ContactNotepad.ts +1 -1
  522. package/src/{contacts → live}/ContactPending.ts +1 -1
  523. package/src/{chart → live}/TembaChart.ts +1 -1
  524. package/src/store/AppState.ts +75 -29
  525. package/src/store/Store.ts +1 -1
  526. package/src/store/flow-definition.d.ts +131 -1
  527. package/src/{utils/index.ts → utils.ts} +26 -10
  528. package/src/webchat/WebChat.ts +1 -1
  529. package/static/api/contacts.json +30 -0
  530. package/static/api/groups.json +4 -426
  531. package/static/api/locations.json +24 -0
  532. package/static/api/media.json +5 -0
  533. package/static/api/optins.json +16 -0
  534. package/static/api/orgs.json +13 -0
  535. package/static/api/topics.json +21 -0
  536. package/static/api/users.json +26 -0
  537. package/static/css/temba-components.css +4 -6
  538. package/svg.js +1 -4
  539. package/temba-components.ts +2 -2
  540. package/temba-modules.ts +63 -56
  541. package/temba-webchat.ts +2 -2
  542. package/test/ActionHelper.ts +142 -0
  543. package/test/actions/add_contact_groups.test.ts +89 -0
  544. package/test/actions/remove_contact_groups.test.ts +265 -0
  545. package/test/actions/send_email.test.ts +214 -0
  546. package/test/actions/send_msg.test.ts +130 -0
  547. package/test/temba-action-editing-integration.test.ts +240 -0
  548. package/test/temba-alert.test.ts +1 -1
  549. package/test/temba-appstate-language.test.ts +108 -0
  550. package/test/temba-charcount.test.ts +1 -1
  551. package/test/temba-chart.test.ts +1 -1
  552. package/test/temba-checkbox.test.ts +2 -2
  553. package/test/temba-color-picker.test.ts +1 -1
  554. package/test/temba-completion.test.ts +1 -1
  555. package/test/temba-compose.test.ts +1 -1
  556. package/test/temba-contact-badges.test.ts +1 -1
  557. package/test/temba-contact-chat.test.ts +6 -4
  558. package/test/temba-contact-details.test.ts +1 -1
  559. package/test/temba-contact-fields.test.ts +1 -1
  560. package/test/temba-contact-search.test.ts +2 -2
  561. package/test/temba-date.test.ts +8 -3
  562. package/test/temba-datepicker.test.ts +1 -1
  563. package/test/temba-dialog.test.ts +1 -1
  564. package/test/temba-dropdown.test.ts +1 -1
  565. package/test/temba-excellent-helpers.test.ts +417 -0
  566. package/test/temba-field-config.test.ts +152 -0
  567. package/test/temba-field-manager.test.ts +2 -2
  568. package/test/temba-flow-editor-node.test.ts +551 -16
  569. package/test/temba-flow-editor.test.ts +224 -0
  570. package/test/temba-flow-editor.test.ts.backup +563 -0
  571. package/test/temba-flow-plumber-connections.test.ts +142 -0
  572. package/test/temba-flow-plumber.test.ts +83 -120
  573. package/test/temba-flow-self-routing.test.ts +215 -0
  574. package/test/temba-formfield.test.ts +1 -1
  575. package/test/temba-icon.test.ts +1 -1
  576. package/test/temba-integration-markdown.test.ts +1 -1
  577. package/test/temba-label.test.ts +1 -1
  578. package/test/temba-lightbox.test.ts +1 -1
  579. package/test/temba-markdown.test.ts +162 -0
  580. package/test/temba-menu.test.ts +1 -1
  581. package/test/temba-modax.test.ts +2 -2
  582. package/test/temba-modules.test.ts +56 -0
  583. package/test/temba-node-editor.test.ts +353 -0
  584. package/test/temba-omnibox.test.ts +1 -1
  585. package/test/temba-options.test.ts +1 -1
  586. package/test/temba-range-picker.test.ts +17 -2
  587. package/test/temba-rapid-element.test.ts +341 -0
  588. package/test/temba-resize-element.test.ts +104 -0
  589. package/test/temba-select.test.ts +129 -2
  590. package/test/temba-slider.test.ts +1 -1
  591. package/test/temba-sticky-note.test.ts +281 -0
  592. package/test/temba-template-editor.test.ts +1 -1
  593. package/test/temba-textinput.test.ts +1 -1
  594. package/test/temba-tip.test.ts +1 -1
  595. package/test/temba-toast.test.ts +1 -1
  596. package/test/temba-utils-index.test.ts +1 -1
  597. package/test/temba-utils-index.test.ts.backup +1737 -0
  598. package/test/temba-utils-uuid.test.ts +48 -0
  599. package/test/temba-webchat.test.ts +30 -12
  600. package/test/utils.test.ts +5 -9
  601. package/test-assets/contacts/history.json +11 -33
  602. package/web-dev-server.config.mjs +35 -1
  603. package/demo/sticky-note-demo.html +0 -155
  604. package/out-tsc/src/FormElement.js.map +0 -1
  605. package/out-tsc/src/alert/Alert.js.map +0 -1
  606. package/out-tsc/src/aliaseditor/AliasEditor.js.map +0 -1
  607. package/out-tsc/src/anchor/Anchor.js.map +0 -1
  608. package/out-tsc/src/button/Button.js.map +0 -1
  609. package/out-tsc/src/charcount/CharCount.js.map +0 -1
  610. package/out-tsc/src/charcount/helpers.js +0 -159
  611. package/out-tsc/src/charcount/helpers.js.map +0 -1
  612. package/out-tsc/src/chart/TembaChart.js.map +0 -1
  613. package/out-tsc/src/chat/Chat.js.map +0 -1
  614. package/out-tsc/src/checkbox/Checkbox.js.map +0 -1
  615. package/out-tsc/src/colorpicker/ColorPicker.js.map +0 -1
  616. package/out-tsc/src/completion/Completion.js.map +0 -1
  617. package/out-tsc/src/completion/ExcellentParser.js.map +0 -1
  618. package/out-tsc/src/completion/helpers.js.map +0 -1
  619. package/out-tsc/src/compose/Compose.js.map +0 -1
  620. package/out-tsc/src/contacts/ContactBadges.js.map +0 -1
  621. package/out-tsc/src/contacts/ContactChat.js.map +0 -1
  622. package/out-tsc/src/contacts/ContactDetails.js.map +0 -1
  623. package/out-tsc/src/contacts/ContactFieldEditor.js.map +0 -1
  624. package/out-tsc/src/contacts/ContactFields.js.map +0 -1
  625. package/out-tsc/src/contacts/ContactName.js.map +0 -1
  626. package/out-tsc/src/contacts/ContactNameFetch.js.map +0 -1
  627. package/out-tsc/src/contacts/ContactPending.js.map +0 -1
  628. package/out-tsc/src/contacts/ContactStoreElement.js.map +0 -1
  629. package/out-tsc/src/contacts/ContactUrn.js.map +0 -1
  630. package/out-tsc/src/contacts/events.js +0 -65
  631. package/out-tsc/src/contacts/events.js.map +0 -1
  632. package/out-tsc/src/contacts/helpers.js +0 -77
  633. package/out-tsc/src/contacts/helpers.js.map +0 -1
  634. package/out-tsc/src/contactsearch/ContactSearch.js.map +0 -1
  635. package/out-tsc/src/date/TembaDate.js.map +0 -1
  636. package/out-tsc/src/datepicker/DatePicker.js.map +0 -1
  637. package/out-tsc/src/datepicker/RangePicker.js.map +0 -1
  638. package/out-tsc/src/dialog/Dialog.js.map +0 -1
  639. package/out-tsc/src/dropdown/Dropdown.js.map +0 -1
  640. package/out-tsc/src/fields/FieldManager.js.map +0 -1
  641. package/out-tsc/src/flow/EditorNode.js +0 -291
  642. package/out-tsc/src/flow/EditorNode.js.map +0 -1
  643. package/out-tsc/src/flow/render.js +0 -41
  644. package/out-tsc/src/flow/render.js.map +0 -1
  645. package/out-tsc/src/formfield/FormField.js +0 -144
  646. package/out-tsc/src/formfield/FormField.js.map +0 -1
  647. package/out-tsc/src/imagepicker/CroppieCSS.js.map +0 -1
  648. package/out-tsc/src/imagepicker/ImagePicker.js.map +0 -1
  649. package/out-tsc/src/label/Label.js.map +0 -1
  650. package/out-tsc/src/leafletmap/LeafletMap.js.map +0 -1
  651. package/out-tsc/src/leafletmap/helpers.js +0 -17
  652. package/out-tsc/src/leafletmap/helpers.js.map +0 -1
  653. package/out-tsc/src/lightbox/Lightbox.js.map +0 -1
  654. package/out-tsc/src/mask/Mask.js.map +0 -1
  655. package/out-tsc/src/mediapicker/MediaPicker.js.map +0 -1
  656. package/out-tsc/src/omnibox/Omnibox.js.map +0 -1
  657. package/out-tsc/src/options/helpers.js +0 -28
  658. package/out-tsc/src/options/helpers.js.map +0 -1
  659. package/out-tsc/src/progress/ProgressBar.js.map +0 -1
  660. package/out-tsc/src/progress/StartProgress.js.map +0 -1
  661. package/out-tsc/src/resizer/Resizer.js.map +0 -1
  662. package/out-tsc/src/select/PopupSelect.js.map +0 -1
  663. package/out-tsc/src/select/Select.js.map +0 -1
  664. package/out-tsc/src/select/UserSelect.js.map +0 -1
  665. package/out-tsc/src/select/WorkspaceSelect.js.map +0 -1
  666. package/out-tsc/src/select/helpers.js +0 -1
  667. package/out-tsc/src/select/helpers.js.map +0 -1
  668. package/out-tsc/src/shadowless/Shadowless.js +0 -33
  669. package/out-tsc/src/shadowless/Shadowless.js.map +0 -1
  670. package/out-tsc/src/slider/TembaSlider.js.map +0 -1
  671. package/out-tsc/src/sms/gsmsplitter.js.map +0 -1
  672. package/out-tsc/src/sms/gsmvalidator.js.map +0 -1
  673. package/out-tsc/src/sms/index.js.map +0 -1
  674. package/out-tsc/src/sms/unicodesplitter.js.map +0 -1
  675. package/out-tsc/src/tabpane/Tab.js.map +0 -1
  676. package/out-tsc/src/tabpane/TabPane.js.map +0 -1
  677. package/out-tsc/src/templates/TemplateEditor.js.map +0 -1
  678. package/out-tsc/src/textinput/TextInput.js.map +0 -1
  679. package/out-tsc/src/textinput/helpers.js +0 -12
  680. package/out-tsc/src/textinput/helpers.js.map +0 -1
  681. package/out-tsc/src/thumbnail/Thumbnail.js.map +0 -1
  682. package/out-tsc/src/tip/Tip.js.map +0 -1
  683. package/out-tsc/src/tip/helpers.js +0 -7
  684. package/out-tsc/src/tip/helpers.js.map +0 -1
  685. package/out-tsc/src/toast/Toast.js.map +0 -1
  686. package/out-tsc/src/user/TembaUser.js.map +0 -1
  687. package/out-tsc/src/utils/index.js.map +0 -1
  688. package/out-tsc/src/vectoricon/VectorIcon.js.map +0 -1
  689. package/out-tsc/src/vectoricon/index.js.map +0 -1
  690. package/out-tsc/test/temba-flow-render.test.js +0 -171
  691. package/out-tsc/test/temba-flow-render.test.js.map +0 -1
  692. package/src/charcount/helpers.ts +0 -162
  693. package/src/contacts/events.ts +0 -210
  694. package/src/contacts/helpers.ts +0 -103
  695. package/src/flow/EditorNode.ts +0 -318
  696. package/src/flow/render.ts +0 -56
  697. package/src/formfield/FormField.ts +0 -134
  698. package/src/leafletmap/helpers.ts +0 -18
  699. package/src/options/helpers.ts +0 -37
  700. package/src/select/helpers.ts +0 -0
  701. package/src/shadowless/Shadowless.ts +0 -32
  702. package/src/textinput/helpers.ts +0 -11
  703. package/src/tip/helpers.ts +0 -7
  704. package/test/temba-flow-render.test.ts +0 -220
  705. /package/out-tsc/src/{alert → display}/Alert.js +0 -0
  706. /package/out-tsc/src/{anchor → display}/Anchor.js +0 -0
  707. /package/out-tsc/src/{button → display}/Button.js +0 -0
  708. /package/out-tsc/src/{chat → display}/Chat.js +0 -0
  709. /package/out-tsc/src/{contacts → display}/ContactName.js +0 -0
  710. /package/out-tsc/src/{contacts → display}/ContactUrn.js +0 -0
  711. /package/out-tsc/src/{dropdown → display}/Dropdown.js +0 -0
  712. /package/out-tsc/src/{label → display}/Label.js +0 -0
  713. /package/out-tsc/src/{lightbox → display}/Lightbox.js +0 -0
  714. /package/out-tsc/src/{loading → display}/Loading.js +0 -0
  715. /package/out-tsc/src/{options → display}/Options.js +0 -0
  716. /package/out-tsc/src/{progress → display}/ProgressBar.js +0 -0
  717. /package/out-tsc/src/{date → display}/TembaDate.js +0 -0
  718. /package/out-tsc/src/{user → display}/TembaUser.js +0 -0
  719. /package/out-tsc/src/{thumbnail → display}/Thumbnail.js +0 -0
  720. /package/out-tsc/src/{toast → display}/Toast.js +0 -0
  721. /package/out-tsc/src/{sms → display/sms}/gsmsplitter.js +0 -0
  722. /package/out-tsc/src/{sms → display/sms}/gsmvalidator.js +0 -0
  723. /package/out-tsc/src/{sms → display/sms}/index.js +0 -0
  724. /package/out-tsc/src/{sms → display/sms}/unicodesplitter.js +0 -0
  725. /package/out-tsc/src/{completion → excellent}/ExcellentParser.js +0 -0
  726. /package/out-tsc/src/{completion → excellent}/helpers.js +0 -0
  727. /package/out-tsc/src/{imagepicker → form}/CroppieCSS.js +0 -0
  728. /package/out-tsc/src/{datepicker → form}/RangePicker.js +0 -0
  729. /package/out-tsc/src/{dialog → layout}/Dialog.js +0 -0
  730. /package/out-tsc/src/{mask → layout}/Mask.js +0 -0
  731. /package/out-tsc/src/{dialog → layout}/Modax.js +0 -0
  732. /package/out-tsc/src/{resizer → layout}/Resizer.js +0 -0
  733. /package/out-tsc/src/{tabpane → layout}/Tab.js +0 -0
  734. /package/out-tsc/src/{tabpane → layout}/TabPane.js +0 -0
  735. /package/out-tsc/src/{contacts → live}/ContactFields.js +0 -0
  736. /package/out-tsc/src/{contacts → live}/ContactNameFetch.js +0 -0
  737. /package/out-tsc/src/{contacts → live}/ContactStoreElement.js +0 -0
  738. /package/out-tsc/src/{fields → live}/FieldManager.js +0 -0
  739. /package/out-tsc/src/{progress → live}/StartProgress.js +0 -0
  740. /package/out-tsc/src/{chart → live}/TembaChart.js +0 -0
  741. /package/src/{vectoricon/index.ts → Icons.ts} +0 -0
  742. /package/src/{alert → display}/Alert.ts +0 -0
  743. /package/src/{anchor → display}/Anchor.ts +0 -0
  744. /package/src/{button → display}/Button.ts +0 -0
  745. /package/src/{chat → display}/Chat.ts +0 -0
  746. /package/src/{contacts → display}/ContactName.ts +0 -0
  747. /package/src/{contacts → display}/ContactUrn.ts +0 -0
  748. /package/src/{dropdown → display}/Dropdown.ts +0 -0
  749. /package/src/{label → display}/Label.ts +0 -0
  750. /package/src/{lightbox → display}/Lightbox.ts +0 -0
  751. /package/src/{loading → display}/Loading.ts +0 -0
  752. /package/src/{options → display}/Options.ts +0 -0
  753. /package/src/{progress → display}/ProgressBar.ts +0 -0
  754. /package/src/{date → display}/TembaDate.ts +0 -0
  755. /package/src/{user → display}/TembaUser.ts +0 -0
  756. /package/src/{toast → display}/Toast.ts +0 -0
  757. /package/src/{sms → display/sms}/gsmsplitter.ts +0 -0
  758. /package/src/{sms → display/sms}/gsmvalidator.ts +0 -0
  759. /package/src/{sms → display/sms}/index.ts +0 -0
  760. /package/src/{sms → display/sms}/unicodesplitter.ts +0 -0
  761. /package/src/{completion → excellent}/ExcellentParser.ts +0 -0
  762. /package/src/{completion → excellent}/helpers.ts +0 -0
  763. /package/src/{imagepicker → form}/CroppieCSS.ts +0 -0
  764. /package/src/{datepicker → form}/RangePicker.ts +0 -0
  765. /package/src/{mask → layout}/Mask.ts +0 -0
  766. /package/src/{dialog → layout}/Modax.ts +0 -0
  767. /package/src/{resizer → layout}/Resizer.ts +0 -0
  768. /package/src/{tabpane → layout}/Tab.ts +0 -0
  769. /package/src/{tabpane → layout}/TabPane.ts +0 -0
  770. /package/src/{contacts → live}/ContactNameFetch.ts +0 -0
  771. /package/src/{contacts → live}/ContactStoreElement.ts +0 -0
  772. /package/src/{fields → live}/FieldManager.ts +0 -0
  773. /package/src/{progress → live}/StartProgress.ts +0 -0
@@ -1,41 +1,52 @@
1
- import { html, fixture, expect } from '@open-wc/testing';
1
+ import { expect } from '@open-wc/testing';
2
2
  import { Plumber, SOURCE_DEFAULTS, TARGET_DEFAULTS } from '../src/flow/Plumber';
3
- import { stub, restore } from 'sinon';
3
+ import { stub, useFakeTimers, SinonFakeTimers } from 'sinon';
4
4
 
5
5
  describe('Plumber', () => {
6
6
  let plumber: Plumber;
7
7
  let mockJsPlumb: any;
8
- let container: HTMLElement;
9
-
10
- beforeEach(async () => {
11
- // Create a container with mock elements
12
- container = await fixture(html`
13
- <div>
14
- <div id="test-canvas"></div>
15
- <div id="test-source">Source Element</div>
16
- <div id="test-target">Target Element</div>
17
- <div id="test-from">From Element</div>
18
- <div id="test-to">To Element</div>
19
- </div>
20
- `);
21
-
22
- const canvas = container.querySelector('#test-canvas') as HTMLElement;
23
-
24
- // Mock jsPlumb functionality
8
+ let mockCanvas: HTMLElement;
9
+ let clock: SinonFakeTimers;
10
+
11
+ beforeEach(() => {
12
+ // Use fake timers to control setTimeout
13
+ clock = useFakeTimers();
14
+
15
+ // Create mock canvas and make getElementById return a mock element
16
+ mockCanvas = document.createElement('div');
17
+ const mockElement = document.createElement('div');
18
+ stub(document, 'getElementById').returns(mockElement);
19
+
20
+ // Create a new plumber instance
21
+ plumber = new Plumber(mockCanvas);
22
+
23
+ // Replace the internal jsPlumb instance with mocks
25
24
  mockJsPlumb = {
26
- addEndpoint: stub().returns({ uuid: 'mock-endpoint' }),
25
+ getConnections: stub().returns([]),
26
+ addClass: stub(),
27
+ removeClass: stub(),
28
+ batch: stub().callsFake((fn) => fn()),
29
+ addEndpoint: stub().returns({}),
27
30
  connect: stub(),
28
- batch: stub().callsFake((fn: () => void) => fn())
31
+ selectEndpoints: stub().returns({
32
+ deleteAll: stub()
33
+ }),
34
+ deleteConnection: stub(),
35
+ removeAllEndpoints: stub(),
36
+ repaintEverything: stub(),
37
+ revalidate: stub(),
38
+ bind: stub()
29
39
  };
30
40
 
31
- // Create plumber instance and replace jsPlumb
32
- plumber = new Plumber(canvas);
33
- // Access private property for testing
34
41
  (plumber as any).jsPlumb = mockJsPlumb;
42
+ // Reset the connectionWait to avoid timing issues
43
+ (plumber as any).connectionWait = null;
35
44
  });
36
45
 
37
46
  afterEach(() => {
38
- restore();
47
+ // Restore the original document.getElementById
48
+ (document.getElementById as any).restore?.();
49
+ clock.restore();
39
50
  });
40
51
 
41
52
  describe('constructor', () => {
@@ -47,143 +58,95 @@ describe('Plumber', () => {
47
58
  describe('makeTarget', () => {
48
59
  it('creates a target endpoint for the specified element', () => {
49
60
  plumber.makeTarget('test-target');
50
-
51
- expect(mockJsPlumb.addEndpoint).to.have.been.calledWith(
52
- container.querySelector('#test-target'),
53
- TARGET_DEFAULTS
54
- );
55
- });
56
-
57
- it('handles non-existent elements gracefully', () => {
58
- plumber.makeTarget('non-existent');
59
-
60
- expect(mockJsPlumb.addEndpoint).to.have.been.calledWith(
61
- null,
62
- TARGET_DEFAULTS
63
- );
61
+ expect(mockJsPlumb.addEndpoint).to.have.been.called;
64
62
  });
65
63
  });
66
64
 
67
65
  describe('makeSource', () => {
68
66
  it('creates a source endpoint for the specified element', () => {
69
67
  plumber.makeSource('test-source');
70
-
71
- expect(mockJsPlumb.addEndpoint).to.have.been.calledWith(
72
- container.querySelector('#test-source'),
73
- SOURCE_DEFAULTS
74
- );
75
- });
76
-
77
- it('handles non-existent elements gracefully', () => {
78
- plumber.makeSource('non-existent');
79
-
80
- expect(mockJsPlumb.addEndpoint).to.have.been.calledWith(
81
- null,
82
- SOURCE_DEFAULTS
83
- );
68
+ expect(mockJsPlumb.addEndpoint).to.have.been.called;
84
69
  });
85
70
  });
86
71
 
87
72
  describe('connectIds', () => {
88
73
  it('adds connection to pending connections and processes them', () => {
89
- plumber.connectIds('test-from', 'test-to');
74
+ plumber.connectIds('test-node', 'test-from', 'test-to');
75
+
76
+ // Verify pendingConnections has the new connection
77
+ expect((plumber as any).pendingConnections.length).to.equal(1);
90
78
 
91
- // Verify that the method doesn't throw and plumber exists
92
- expect(plumber).to.exist;
79
+ // Advance timer to trigger the timeout
80
+ clock.tick(51); // Just past the 50ms timeout
81
+
82
+ // Now the batch should have been called
83
+ expect(mockJsPlumb.batch).to.have.been.called;
93
84
  });
94
85
  });
95
86
 
96
87
  describe('processPendingConnections', () => {
97
- it('processes pending connections with timeout', (done) => {
88
+ it('processes pending connections with timeout', () => {
98
89
  // Add a connection to pending connections
99
- plumber.connectIds('test-from', 'test-to');
90
+ plumber.connectIds('test-node', 'test-from', 'test-to');
91
+
92
+ // Fast-forward clock past the timeout
93
+ clock.tick(51); // Just past the 50ms timeout
100
94
 
101
- // Wait for the debounced timeout
102
- setTimeout(() => {
103
- expect(mockJsPlumb.batch).to.have.been.called;
104
- done();
105
- }, 60); // Wait longer than the 50ms timeout
95
+ expect(mockJsPlumb.batch).to.have.been.called;
106
96
  });
107
97
 
108
- it('creates endpoints and connections for pending connections', (done) => {
109
- plumber.connectIds('test-from', 'test-to');
98
+ it('creates endpoints and connections for pending connections', () => {
99
+ plumber.connectIds('test-node', 'test-from', 'test-to');
100
+
101
+ // Fast-forward clock past the timeout
102
+ clock.tick(51); // Just past the 50ms timeout
110
103
 
111
- setTimeout(() => {
112
- expect(mockJsPlumb.addEndpoint).to.have.been.called;
113
- expect(mockJsPlumb.connect).to.have.been.called;
114
- done();
115
- }, 60);
104
+ expect(mockJsPlumb.addEndpoint).to.have.been.called;
105
+ expect(mockJsPlumb.connect).to.have.been.called;
116
106
  });
117
107
 
118
108
  it('clears existing timeout when called multiple times', () => {
119
- // Call processPendingConnections directly
109
+ // Set up spies for window.setTimeout and window.clearTimeout
110
+ const clearTimeoutSpy = stub(window, 'clearTimeout');
111
+ const setTimeoutSpy = stub(window, 'setTimeout').returns(123 as any);
112
+
113
+ // Call twice
120
114
  plumber.processPendingConnections();
121
115
  plumber.processPendingConnections();
122
116
 
123
- // This mainly tests that no errors are thrown
124
- expect(plumber).to.exist;
117
+ // Should have called clearTimeout once and setTimeout twice
118
+ expect(clearTimeoutSpy).to.have.been.calledOnce;
119
+ expect(setTimeoutSpy).to.have.been.calledTwice;
120
+
121
+ // Clean up
122
+ clearTimeoutSpy.restore();
123
+ setTimeoutSpy.restore();
125
124
  });
126
125
 
127
- it('handles empty pending connections', (done) => {
126
+ it('handles empty pending connections', () => {
128
127
  // Call without adding any connections
129
128
  plumber.processPendingConnections();
130
129
 
131
- setTimeout(() => {
132
- expect(mockJsPlumb.batch).to.have.been.called;
133
- done();
134
- }, 60);
130
+ // Fast-forward clock past the timeout
131
+ clock.tick(51); // Just past the 50ms timeout
132
+
133
+ expect(mockJsPlumb.batch).to.have.been.called;
135
134
  });
136
135
  });
137
136
 
138
137
  describe('constants', () => {
139
- it('exports SOURCE_DEFAULTS with correct structure', () => {
138
+ it('has correct properties in SOURCE_DEFAULTS', () => {
140
139
  expect(SOURCE_DEFAULTS).to.have.property('endpoint');
141
- expect(SOURCE_DEFAULTS.endpoint).to.have.property('type');
142
- expect(SOURCE_DEFAULTS.endpoint).to.have.property('options');
143
140
  expect(SOURCE_DEFAULTS).to.have.property('anchors');
144
- expect(SOURCE_DEFAULTS).to.have.property('maxConnections', 1);
145
- expect(SOURCE_DEFAULTS).to.have.property('isSource', true);
146
- expect(SOURCE_DEFAULTS).to.have.property('dragAllowedWhenFull', false);
147
- expect(SOURCE_DEFAULTS).to.have.property('deleteEndpointsOnEmpty', true);
141
+ expect(SOURCE_DEFAULTS).to.have.property('maxConnections');
142
+ expect(SOURCE_DEFAULTS).to.have.property('source');
148
143
  });
149
144
 
150
- it('exports TARGET_DEFAULTS with correct structure', () => {
145
+ it('has correct properties in TARGET_DEFAULTS', () => {
151
146
  expect(TARGET_DEFAULTS).to.have.property('endpoint');
152
- expect(TARGET_DEFAULTS.endpoint).to.have.property('type');
153
- expect(TARGET_DEFAULTS.endpoint).to.have.property('options');
154
147
  expect(TARGET_DEFAULTS).to.have.property('anchor');
155
- expect(TARGET_DEFAULTS).to.have.property('isTarget', true);
156
- expect(TARGET_DEFAULTS).to.have.property('dragAllowedWhenFull', false);
157
- expect(TARGET_DEFAULTS).to.have.property('deleteEndpointsOnEmpty', true);
158
- });
159
-
160
- it('has correct SOURCE_DEFAULTS endpoint options', () => {
161
- const options = SOURCE_DEFAULTS.endpoint.options;
162
- expect(options).to.have.property('radius', 6);
163
- expect(options).to.have.property('cssClass', 'plumb-source');
164
- expect(options).to.have.property('hoverClass', 'plumb-source-hover');
165
- expect(options).to.have.property('connectedClass', 'plumb-connected');
166
- });
167
-
168
- it('has correct TARGET_DEFAULTS endpoint options', () => {
169
- const options = TARGET_DEFAULTS.endpoint.options;
170
- expect(options).to.have.property('width', 23);
171
- expect(options).to.have.property('height', 23);
172
- expect(options).to.have.property('cssClass', 'plumb-target');
173
- expect(options).to.have.property('hoverClass', 'plumb-target-hover');
174
- });
175
-
176
- it('has correct TARGET_DEFAULTS anchor options', () => {
177
- const anchor = TARGET_DEFAULTS.anchor;
178
- expect(anchor).to.have.property('type', 'Continuous');
179
- expect(anchor.options).to.have.property('faces');
180
- expect(anchor.options.faces).to.include('top');
181
- expect(anchor.options.faces).to.include('left');
182
- expect(anchor.options.faces).to.include('right');
183
- expect(anchor.options).to.have.property(
184
- 'cssClass',
185
- 'continuos plumb-target-anchor'
186
- );
148
+ expect(TARGET_DEFAULTS).to.have.property('maxConnections');
149
+ expect(TARGET_DEFAULTS).to.have.property('target');
187
150
  });
188
151
  });
189
152
  });
@@ -0,0 +1,215 @@
1
+ import { expect, fixture, html } from '@open-wc/testing';
2
+ import { stub, restore, useFakeTimers, SinonFakeTimers } from 'sinon';
3
+ import { Editor } from '../src/flow/Editor';
4
+ import { FlowDefinition } from '../src/store/flow-definition';
5
+
6
+ // Register the component
7
+ customElements.define('temba-flow-editor-test', Editor);
8
+
9
+ describe('Flow Editor Self-Routing Prevention', () => {
10
+ let editor: Editor;
11
+ let mockDefinition: FlowDefinition;
12
+ let clock: SinonFakeTimers;
13
+
14
+ beforeEach(() => {
15
+ restore();
16
+
17
+ // Use fake timers to control any async operations
18
+ clock = useFakeTimers({
19
+ shouldAdvanceTime: true,
20
+ advanceTimeDelta: 10
21
+ });
22
+
23
+ // Create a mock flow definition with test nodes and exits
24
+ mockDefinition = {
25
+ uuid: 'test-flow',
26
+ name: 'Test Flow',
27
+ nodes: [
28
+ {
29
+ uuid: 'node-1',
30
+ actions: [],
31
+ exits: [
32
+ { uuid: 'exit-1a', destination_uuid: undefined },
33
+ { uuid: 'exit-1b', destination_uuid: 'node-2' }
34
+ ]
35
+ },
36
+ {
37
+ uuid: 'node-2',
38
+ actions: [],
39
+ exits: [{ uuid: 'exit-2a', destination_uuid: undefined }]
40
+ }
41
+ ],
42
+ localization: {},
43
+ language: 'eng',
44
+ type: 'messaging',
45
+ revision: 1,
46
+ spec_version: '13.1.0',
47
+ _ui: {
48
+ nodes: {
49
+ 'node-1': { position: { left: 100, top: 100 } },
50
+ 'node-2': { position: { left: 300, top: 100 } }
51
+ },
52
+ languages: []
53
+ }
54
+ };
55
+ });
56
+
57
+ afterEach(() => {
58
+ restore();
59
+ if (clock) {
60
+ clock.restore();
61
+ }
62
+ });
63
+
64
+ describe('connection dragging behavior', () => {
65
+ let mockPlumber: any;
66
+
67
+ beforeEach(async () => {
68
+ editor = (await fixture(
69
+ html`<temba-flow-editor-test></temba-flow-editor-test>`
70
+ )) as Editor;
71
+
72
+ // Wait for element to be fully initialized
73
+ await editor.updateComplete;
74
+
75
+ // Mock the plumber
76
+ mockPlumber = {
77
+ connectionDragging: false,
78
+ on: stub(),
79
+ connectIds: stub(),
80
+ repaintEverything: stub()
81
+ };
82
+
83
+ // Set up editor state
84
+ (editor as any).plumber = mockPlumber;
85
+ (editor as any).definition = mockDefinition;
86
+ });
87
+
88
+ it('prevents connection when targeting same node', () => {
89
+ // Set up connection drag state
90
+ (editor as any).sourceId = 'exit-1a';
91
+ (editor as any).sourceNodeId = 'node-1';
92
+ (editor as any).targetId = 'node-1'; // Same node as source
93
+ (editor as any).isValidTarget = false;
94
+
95
+ // Test the validation logic directly without makeConnection
96
+ const shouldConnect =
97
+ (editor as any).sourceId &&
98
+ (editor as any).targetId &&
99
+ (editor as any).isValidTarget;
100
+
101
+ expect(shouldConnect).to.be.false;
102
+ });
103
+
104
+ it('allows connection when targeting different node', () => {
105
+ // Set up connection drag state
106
+ (editor as any).sourceId = 'exit-1a';
107
+ (editor as any).sourceNodeId = 'node-1';
108
+ (editor as any).targetId = 'node-2'; // Different node
109
+ (editor as any).isValidTarget = true;
110
+
111
+ // Test the validation logic directly without makeConnection
112
+ const shouldConnect =
113
+ (editor as any).sourceId &&
114
+ (editor as any).targetId &&
115
+ (editor as any).isValidTarget;
116
+
117
+ expect(shouldConnect).to.be.true;
118
+ });
119
+ });
120
+
121
+ describe('visual feedback during connection dragging', () => {
122
+ let mockTargetNode: HTMLElement;
123
+
124
+ beforeEach(async () => {
125
+ editor = (await fixture(
126
+ html`<temba-flow-editor-test></temba-flow-editor-test>`
127
+ )) as Editor;
128
+
129
+ // Wait for element to be fully initialized
130
+ await editor.updateComplete;
131
+
132
+ // Create mock target node
133
+ mockTargetNode = document.createElement('temba-flow-node');
134
+ mockTargetNode.setAttribute('uuid', 'node-2');
135
+ document.body.appendChild(mockTargetNode);
136
+
137
+ // Mock querySelector to return our mock node
138
+ stub(document, 'querySelector')
139
+ .withArgs('temba-flow-node:hover')
140
+ .returns(mockTargetNode);
141
+ stub(document, 'querySelectorAll')
142
+ .withArgs('temba-flow-node')
143
+ .returns({
144
+ forEach: (callback: (node: Element) => void) =>
145
+ callback(mockTargetNode)
146
+ } as any);
147
+
148
+ // Set up editor state
149
+ (editor as any).plumber = { connectionDragging: true };
150
+ (editor as any).definition = mockDefinition;
151
+ (editor as any).sourceId = 'exit-1a';
152
+ (editor as any).sourceNodeId = 'node-1';
153
+ (editor as any).dragFromNodeId = 'node-1'; // This is the key property used in validation
154
+ });
155
+
156
+ afterEach(() => {
157
+ if (document.body.contains(mockTargetNode)) {
158
+ document.body.removeChild(mockTargetNode);
159
+ }
160
+ });
161
+
162
+ it('adds valid target class when hovering over different node', async () => {
163
+ // Make sure other properties on the editor are correctly set up
164
+ (editor as any).targetId = 'node-2';
165
+ (editor as any).isValidTarget = true;
166
+
167
+ // Simulate mouse move over different node
168
+ (editor as any).handleMouseMove(new MouseEvent('mousemove'));
169
+ await editor.updateComplete;
170
+
171
+ // Allow time for DOM updates
172
+ clock.tick(50);
173
+
174
+ expect(mockTargetNode.classList.contains('connection-target-valid')).to.be
175
+ .true;
176
+ expect(mockTargetNode.classList.contains('connection-target-invalid')).to
177
+ .be.false;
178
+ });
179
+
180
+ it('adds invalid target class when hovering over same node', async () => {
181
+ // Change target to same node as source
182
+ mockTargetNode.setAttribute('uuid', 'node-1');
183
+
184
+ // Make sure other properties on the editor are correctly set up
185
+ (editor as any).targetId = 'node-1';
186
+ (editor as any).isValidTarget = false;
187
+
188
+ // Simulate mouse move over same node
189
+ (editor as any).handleMouseMove(new MouseEvent('mousemove'));
190
+ await editor.updateComplete;
191
+
192
+ // Allow time for DOM updates
193
+ clock.tick(50);
194
+
195
+ expect(mockTargetNode.classList.contains('connection-target-invalid')).to
196
+ .be.true;
197
+ expect(mockTargetNode.classList.contains('connection-target-valid')).to.be
198
+ .false;
199
+ });
200
+
201
+ it('cleans up visual feedback after connection attempt', async () => {
202
+ // Add classes to simulate active state
203
+ mockTargetNode.classList.add('connection-target-valid');
204
+
205
+ // Make connection (which should clean up)
206
+ (editor as any).makeConnection();
207
+ await editor.updateComplete;
208
+
209
+ expect(mockTargetNode.classList.contains('connection-target-valid')).to.be
210
+ .false;
211
+ expect(mockTargetNode.classList.contains('connection-target-invalid')).to
212
+ .be.false;
213
+ });
214
+ });
215
+ });
@@ -1,5 +1,5 @@
1
1
  import { html, fixture, expect } from '@open-wc/testing';
2
- import { FormField } from '../src/formfield/FormField';
2
+ import { FormField } from '../src/form/FormField';
3
3
  import { assertScreenshot, getClip } from './utils.test';
4
4
 
5
5
  describe('temba-field', () => {
@@ -1,5 +1,5 @@
1
1
  import { assert } from '@open-wc/testing';
2
- import { VectorIcon } from '../src/vectoricon/VectorIcon';
2
+ import { VectorIcon } from '../src/display/Icon';
3
3
  import { getComponent } from './utils.test';
4
4
 
5
5
  const TAG = 'temba-icon';
@@ -1,5 +1,5 @@
1
1
  import { html, fixture, expect } from '@open-wc/testing';
2
- import { Checkbox } from '../src/checkbox/Checkbox';
2
+ import { Checkbox } from '../src/form/Checkbox';
3
3
  import { assertScreenshot, getClip } from './utils.test';
4
4
 
5
5
  describe('FormElement markdown integration', () => {
@@ -1,5 +1,5 @@
1
1
  import { assert } from '@open-wc/testing';
2
- import Label from '../src/label/Label';
2
+ import Label from '../src/display/Label';
3
3
  import { assertScreenshot, getClip, getComponent } from './utils.test';
4
4
 
5
5
  const TAG = 'temba-label';
@@ -1,5 +1,5 @@
1
1
  import { fixture, assert } from '@open-wc/testing';
2
- import { Lightbox } from '../src/lightbox/Lightbox';
2
+ import { Lightbox } from '../src/display/Lightbox';
3
3
  import { assertScreenshot } from './utils.test';
4
4
 
5
5
  export const getHTML = () => {
@@ -0,0 +1,162 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { html, render } from 'lit';
3
+ import { markdown, renderMarkdown, RenderMarkdown } from '../src/markdown';
4
+ import { PartType } from 'lit/directive.js';
5
+
6
+ describe('markdown', () => {
7
+ describe('markdown instance', () => {
8
+ it('exports a Remarkable instance', () => {
9
+ expect(markdown).to.exist;
10
+ expect(typeof markdown.render).to.equal('function');
11
+ });
12
+
13
+ it('renders basic markdown', () => {
14
+ const result = markdown.render('# Hello World');
15
+ expect(result).to.include('<h1>Hello World</h1>');
16
+ });
17
+
18
+ it('renders markdown with emphasis', () => {
19
+ const result = markdown.render('**bold** and *italic*');
20
+ expect(result).to.include('<strong>bold</strong>');
21
+ expect(result).to.include('<em>italic</em>');
22
+ });
23
+
24
+ it('renders markdown lists', () => {
25
+ const result = markdown.render('- Item 1\n- Item 2');
26
+ expect(result).to.include('<ul>');
27
+ expect(result).to.include('<li>Item 1</li>');
28
+ expect(result).to.include('<li>Item 2</li>');
29
+ });
30
+
31
+ it('renders markdown links', () => {
32
+ const result = markdown.render('[Link](https://example.com)');
33
+ expect(result).to.include('<a href="https://example.com">Link</a>');
34
+ });
35
+ });
36
+
37
+ describe('RenderMarkdown directive', () => {
38
+ it('throws error for non-child part types', () => {
39
+ const invalidPartInfo = {
40
+ type: PartType.ATTRIBUTE
41
+ };
42
+
43
+ expect(() => new RenderMarkdown(invalidPartInfo as any)).to.throw(
44
+ 'renderMarkdown only supports child expressions'
45
+ );
46
+ });
47
+
48
+ it('creates directive for child part type', () => {
49
+ const validPartInfo = {
50
+ type: PartType.CHILD
51
+ };
52
+
53
+ expect(() => new RenderMarkdown(validPartInfo as any)).to.not.throw;
54
+ });
55
+
56
+ it('renders markdown content', () => {
57
+ const validPartInfo = {
58
+ type: PartType.CHILD
59
+ };
60
+
61
+ const directive = new RenderMarkdown(validPartInfo as any);
62
+ const result = directive.render('# Test Header');
63
+
64
+ // The result should be a TemplateResult
65
+ expect(result).to.exist;
66
+ expect(result.strings).to.exist;
67
+ });
68
+
69
+ it('updates correctly', () => {
70
+ const validPartInfo = {
71
+ type: PartType.CHILD
72
+ };
73
+
74
+ const directive = new RenderMarkdown(validPartInfo as any);
75
+ const mockPart = {} as any;
76
+
77
+ const result = directive.update(mockPart, ['# Updated Content']);
78
+
79
+ // Should return the same as render
80
+ expect(result).to.exist;
81
+ expect(result.strings).to.exist;
82
+ });
83
+ });
84
+
85
+ describe('renderMarkdown function', () => {
86
+ it('creates a directive that can be used in templates', () => {
87
+ const template = html`${renderMarkdown('# Test')}`;
88
+
89
+ // Should create a valid template
90
+ expect(template).to.exist;
91
+ expect(template.strings).to.exist;
92
+ });
93
+
94
+ it('renders markdown when used in a template', () => {
95
+ const container = document.createElement('div');
96
+ const template = html`${renderMarkdown('# Hello World')}`;
97
+
98
+ render(template, container);
99
+
100
+ // Check that the markdown was rendered to HTML
101
+ expect(container.innerHTML).to.include('<h1>Hello World</h1>');
102
+ });
103
+
104
+ it('handles empty markdown', () => {
105
+ const container = document.createElement('div');
106
+ const template = html`${renderMarkdown('')}`;
107
+
108
+ render(template, container);
109
+
110
+ // Should not throw - Lit may add HTML comments for template placeholders
111
+ expect(() => render(template, container)).to.not.throw;
112
+ });
113
+
114
+ it('handles markdown with special characters', () => {
115
+ const container = document.createElement('div');
116
+ const markdownWithSpecialChars =
117
+ '**Bold** text with <script>alert("xss")</script>';
118
+ const template = html`${renderMarkdown(markdownWithSpecialChars)}`;
119
+
120
+ render(template, container);
121
+
122
+ // Should render the markdown but the script tag should be escaped/handled
123
+ expect(container.innerHTML).to.include('<strong>Bold</strong>');
124
+ // The script tag should be rendered as text or escaped
125
+ expect(container.innerHTML).to.include('script');
126
+ });
127
+
128
+ it('renders complex markdown structures', () => {
129
+ const complexMarkdown = `
130
+ # Main Header
131
+
132
+ ## Sub Header
133
+
134
+ This is a paragraph with **bold** and *italic* text.
135
+
136
+ - List item 1
137
+ - List item 2
138
+ - Nested item
139
+
140
+ [A link](https://example.com)
141
+
142
+ \`\`\`
143
+ code block
144
+ \`\`\`
145
+ `;
146
+
147
+ const container = document.createElement('div');
148
+ const template = html`${renderMarkdown(complexMarkdown)}`;
149
+
150
+ render(template, container);
151
+
152
+ expect(container.innerHTML).to.include('<h1>Main Header</h1>');
153
+ expect(container.innerHTML).to.include('<h2>Sub Header</h2>');
154
+ expect(container.innerHTML).to.include('<strong>bold</strong>');
155
+ expect(container.innerHTML).to.include('<em>italic</em>');
156
+ expect(container.innerHTML).to.include('<ul>');
157
+ expect(container.innerHTML).to.include(
158
+ '<a href="https://example.com">A link</a>'
159
+ );
160
+ });
161
+ });
162
+ });