@nyaruka/temba-components 0.140.0 → 0.141.1

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 (297) hide show
  1. package/.lintstagedrc.js +10 -0
  2. package/CHANGELOG.md +22 -0
  3. package/dist/locales/es.js +5 -5
  4. package/dist/locales/es.js.map +1 -1
  5. package/dist/locales/fr.js +5 -5
  6. package/dist/locales/fr.js.map +1 -1
  7. package/dist/locales/locale-codes.js +11 -2
  8. package/dist/locales/locale-codes.js.map +1 -1
  9. package/dist/locales/pt.js +5 -5
  10. package/dist/locales/pt.js.map +1 -1
  11. package/dist/temba-components.js +263 -156
  12. package/dist/temba-components.js.map +1 -1
  13. package/out-tsc/src/display/FloatingTab.js +1 -1
  14. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  15. package/out-tsc/src/flow/CanvasNode.js +1 -1
  16. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  17. package/out-tsc/src/flow/Editor.js +239 -43
  18. package/out-tsc/src/flow/Editor.js.map +1 -1
  19. package/out-tsc/src/flow/Plumber.js +61 -14
  20. package/out-tsc/src/flow/Plumber.js.map +1 -1
  21. package/out-tsc/src/flow/actions/add_contact_groups.js +4 -1
  22. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  23. package/out-tsc/src/flow/actions/add_input_labels.js +4 -1
  24. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  25. package/out-tsc/src/flow/actions/remove_contact_groups.js +6 -1
  26. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  27. package/out-tsc/src/flow/actions/send_broadcast.js +6 -2
  28. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  29. package/out-tsc/src/flow/actions/set_contact_channel.js +13 -0
  30. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  31. package/out-tsc/src/flow/actions/set_contact_status.js +7 -5
  32. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  33. package/out-tsc/src/flow/actions/start_session.js +10 -3
  34. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  35. package/out-tsc/src/flow/nodes/split_by_contact_field.js +18 -5
  36. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  37. package/out-tsc/src/flow/nodes/split_by_expression.js +1 -1
  38. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  39. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +0 -1
  40. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  41. package/out-tsc/src/flow/nodes/split_by_random.js +0 -1
  42. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  43. package/out-tsc/src/flow/nodes/split_by_run_result.js +10 -4
  44. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  45. package/out-tsc/src/flow/nodes/wait_for_digits.js +1 -1
  46. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  47. package/out-tsc/src/flow/nodes/wait_for_response.js +1 -1
  48. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  49. package/out-tsc/src/form/FieldRenderer.js +7 -0
  50. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  51. package/out-tsc/src/layout/Dialog.js +0 -1
  52. package/out-tsc/src/layout/Dialog.js.map +1 -1
  53. package/out-tsc/src/layout/Modax.js +20 -2
  54. package/out-tsc/src/layout/Modax.js.map +1 -1
  55. package/out-tsc/src/list/ContentMenu.js +14 -1
  56. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  57. package/out-tsc/src/live/ContactChat.js +10 -1
  58. package/out-tsc/src/live/ContactChat.js.map +1 -1
  59. package/out-tsc/src/live/TembaChart.js.map +1 -1
  60. package/out-tsc/src/locales/es.js +5 -5
  61. package/out-tsc/src/locales/es.js.map +1 -1
  62. package/out-tsc/src/locales/fr.js +5 -5
  63. package/out-tsc/src/locales/fr.js.map +1 -1
  64. package/out-tsc/src/locales/locale-codes.js +11 -2
  65. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  66. package/out-tsc/src/locales/pt.js +5 -5
  67. package/out-tsc/src/locales/pt.js.map +1 -1
  68. package/out-tsc/src/simulator/Simulator.js +11 -0
  69. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  70. package/out-tsc/src/store/AppState.js +13 -0
  71. package/out-tsc/src/store/AppState.js.map +1 -1
  72. package/out-tsc/src/version.js +9 -0
  73. package/out-tsc/src/version.js.map +1 -0
  74. package/out-tsc/test/actions/add_contact_groups.test.js +35 -0
  75. package/out-tsc/test/actions/add_contact_groups.test.js.map +1 -1
  76. package/out-tsc/test/actions/add_input_labels.test.js +53 -0
  77. package/out-tsc/test/actions/add_input_labels.test.js.map +1 -0
  78. package/out-tsc/test/actions/enter_flow.test.js +71 -0
  79. package/out-tsc/test/actions/enter_flow.test.js.map +1 -0
  80. package/out-tsc/test/actions/remove_contact_groups.test.js +24 -0
  81. package/out-tsc/test/actions/remove_contact_groups.test.js.map +1 -1
  82. package/out-tsc/test/actions/send_broadcast.test.js +41 -0
  83. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
  84. package/out-tsc/test/actions/set_contact_channel.test.js +67 -0
  85. package/out-tsc/test/actions/set_contact_channel.test.js.map +1 -0
  86. package/out-tsc/test/actions/set_contact_field.test.js +52 -0
  87. package/out-tsc/test/actions/set_contact_field.test.js.map +1 -0
  88. package/out-tsc/test/actions/set_contact_language.test.js +39 -0
  89. package/out-tsc/test/actions/set_contact_language.test.js.map +1 -0
  90. package/out-tsc/test/actions/set_contact_name.test.js +28 -0
  91. package/out-tsc/test/actions/set_contact_name.test.js.map +1 -0
  92. package/out-tsc/test/actions/set_contact_status.test.js +44 -0
  93. package/out-tsc/test/actions/set_contact_status.test.js.map +1 -0
  94. package/out-tsc/test/actions/set_run_result.test.js +47 -0
  95. package/out-tsc/test/actions/set_run_result.test.js.map +1 -0
  96. package/out-tsc/test/actions/start_session.test.js +76 -0
  97. package/out-tsc/test/actions/start_session.test.js.map +1 -1
  98. package/out-tsc/test/nodes/split_by_contact_field.test.js +50 -0
  99. package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -1
  100. package/out-tsc/test/nodes/split_by_run_result.test.js +82 -0
  101. package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -1
  102. package/out-tsc/test/nodes/split_by_ticket.test.js +139 -0
  103. package/out-tsc/test/nodes/split_by_ticket.test.js.map +1 -0
  104. package/out-tsc/test/nodes/split_by_webhook.test.js +111 -0
  105. package/out-tsc/test/nodes/split_by_webhook.test.js.map +1 -0
  106. package/out-tsc/test/temba-contact-chat.test.js +12 -0
  107. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  108. package/out-tsc/test/temba-flow-editor.test.js +206 -0
  109. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  110. package/out-tsc/test/temba-flow-plumber.test.js +19 -0
  111. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  112. package/out-tsc/test/temba-select.test.js +4 -1
  113. package/out-tsc/test/temba-select.test.js.map +1 -1
  114. package/out-tsc/test/utils.test.js +4 -2
  115. package/out-tsc/test/utils.test.js.map +1 -1
  116. package/package.json +3 -9
  117. package/rollup.components.mjs +7 -1
  118. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  119. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  120. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  121. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  122. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  123. package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
  124. package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
  125. package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
  126. package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
  127. package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
  128. package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
  129. package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
  130. package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
  131. package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
  132. package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
  133. package/screenshots/truth/actions/add_input_labels/editor/multiple-labels.png +0 -0
  134. package/screenshots/truth/actions/add_input_labels/editor/single-label.png +0 -0
  135. package/screenshots/truth/actions/add_input_labels/render/multiple-labels.png +0 -0
  136. package/screenshots/truth/actions/add_input_labels/render/single-label.png +0 -0
  137. package/screenshots/truth/actions/enter_flow/editor/basic-flow.png +0 -0
  138. package/screenshots/truth/actions/enter_flow/editor/long-flow-name.png +0 -0
  139. package/screenshots/truth/actions/enter_flow/render/basic-flow.png +0 -0
  140. package/screenshots/truth/actions/enter_flow/render/long-flow-name.png +0 -0
  141. package/screenshots/truth/actions/play_audio/render/expression-url.png +0 -0
  142. package/screenshots/truth/actions/play_audio/render/static-url.png +0 -0
  143. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  144. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  145. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  146. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  147. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  148. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  149. package/screenshots/truth/actions/say_msg/render/multiline-text.png +0 -0
  150. package/screenshots/truth/actions/say_msg/render/simple-text.png +0 -0
  151. package/screenshots/truth/actions/say_msg/render/text-with-audio-url.png +0 -0
  152. package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
  153. package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
  154. package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
  155. package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
  156. package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
  157. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  158. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  159. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  160. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  161. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  162. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  163. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  164. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  165. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  166. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  167. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  168. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  169. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  170. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  171. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  172. package/screenshots/truth/actions/set_contact_channel/editor/sms-channel.png +0 -0
  173. package/screenshots/truth/actions/set_contact_channel/editor/whatsapp-channel.png +0 -0
  174. package/screenshots/truth/actions/set_contact_channel/render/sms-channel.png +0 -0
  175. package/screenshots/truth/actions/set_contact_channel/render/whatsapp-channel.png +0 -0
  176. package/screenshots/truth/actions/set_contact_field/editor/clear-value.png +0 -0
  177. package/screenshots/truth/actions/set_contact_field/editor/set-value.png +0 -0
  178. package/screenshots/truth/actions/set_contact_field/render/clear-value.png +0 -0
  179. package/screenshots/truth/actions/set_contact_field/render/set-value.png +0 -0
  180. package/screenshots/truth/actions/set_contact_language/editor/english.png +0 -0
  181. package/screenshots/truth/actions/set_contact_language/editor/french.png +0 -0
  182. package/screenshots/truth/actions/set_contact_language/render/english.png +0 -0
  183. package/screenshots/truth/actions/set_contact_language/render/french.png +0 -0
  184. package/screenshots/truth/actions/set_contact_name/editor/expression-name.png +0 -0
  185. package/screenshots/truth/actions/set_contact_name/editor/static-name.png +0 -0
  186. package/screenshots/truth/actions/set_contact_name/render/expression-name.png +0 -0
  187. package/screenshots/truth/actions/set_contact_name/render/static-name.png +0 -0
  188. package/screenshots/truth/actions/set_contact_status/editor/active.png +0 -0
  189. package/screenshots/truth/actions/set_contact_status/editor/archived.png +0 -0
  190. package/screenshots/truth/actions/set_contact_status/editor/blocked.png +0 -0
  191. package/screenshots/truth/actions/set_contact_status/render/active.png +0 -0
  192. package/screenshots/truth/actions/set_contact_status/render/archived.png +0 -0
  193. package/screenshots/truth/actions/set_contact_status/render/blocked.png +0 -0
  194. package/screenshots/truth/actions/set_run_result/editor/expression-value.png +0 -0
  195. package/screenshots/truth/actions/set_run_result/editor/with-category.png +0 -0
  196. package/screenshots/truth/actions/set_run_result/render/expression-value.png +0 -0
  197. package/screenshots/truth/actions/set_run_result/render/with-category.png +0 -0
  198. package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
  199. package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
  200. package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
  201. package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
  202. package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
  203. package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
  204. package/screenshots/truth/editor/wait.png +0 -0
  205. package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
  206. package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
  207. package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
  208. package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
  209. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  210. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  211. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  212. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  213. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  214. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  215. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  216. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  217. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  218. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  219. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  220. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  221. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  222. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  223. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  224. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  225. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  226. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  227. package/screenshots/truth/nodes/wait_for_audio/render/basic-audio-wait.png +0 -0
  228. package/screenshots/truth/nodes/wait_for_dial/render/basic-dial.png +0 -0
  229. package/screenshots/truth/nodes/wait_for_dial/render/dial-with-limits.png +0 -0
  230. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  231. package/screenshots/truth/nodes/wait_for_digits/editor/digits-with-rules.png +0 -0
  232. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  233. package/screenshots/truth/nodes/wait_for_digits/render/digits-with-rules.png +0 -0
  234. package/screenshots/truth/nodes/wait_for_menu/render/menu-with-digits.png +0 -0
  235. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  236. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  237. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  238. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  239. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  240. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  241. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  242. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  243. package/src/display/FloatingTab.ts +1 -1
  244. package/src/flow/CanvasNode.ts +1 -1
  245. package/src/flow/Editor.ts +299 -88
  246. package/src/flow/Plumber.ts +89 -14
  247. package/src/flow/actions/add_contact_groups.ts +4 -1
  248. package/src/flow/actions/add_input_labels.ts +4 -1
  249. package/src/flow/actions/remove_contact_groups.ts +6 -1
  250. package/src/flow/actions/send_broadcast.ts +6 -2
  251. package/src/flow/actions/set_contact_channel.ts +13 -1
  252. package/src/flow/actions/set_contact_status.ts +7 -5
  253. package/src/flow/actions/start_session.ts +10 -3
  254. package/src/flow/nodes/split_by_contact_field.ts +16 -5
  255. package/src/flow/nodes/split_by_expression.ts +1 -1
  256. package/src/flow/nodes/split_by_llm_categorize.ts +0 -1
  257. package/src/flow/nodes/split_by_random.ts +0 -1
  258. package/src/flow/nodes/split_by_run_result.ts +10 -4
  259. package/src/flow/nodes/wait_for_digits.ts +2 -1
  260. package/src/flow/nodes/wait_for_response.ts +1 -1
  261. package/src/form/FieldRenderer.ts +7 -0
  262. package/src/layout/Dialog.ts +0 -1
  263. package/src/layout/Modax.ts +19 -2
  264. package/src/list/ContentMenu.ts +15 -1
  265. package/src/live/ContactChat.ts +10 -1
  266. package/src/live/TembaChart.ts +1 -1
  267. package/src/locales/es.ts +18 -13
  268. package/src/locales/fr.ts +18 -13
  269. package/src/locales/locale-codes.ts +11 -2
  270. package/src/locales/pt.ts +18 -13
  271. package/src/simulator/Simulator.ts +12 -0
  272. package/src/store/AppState.ts +15 -0
  273. package/src/store/flow-definition.d.ts +1 -0
  274. package/src/version.ts +10 -0
  275. package/test/actions/add_contact_groups.test.ts +38 -0
  276. package/test/actions/add_input_labels.test.ts +67 -0
  277. package/test/actions/enter_flow.test.ts +88 -0
  278. package/test/actions/remove_contact_groups.test.ts +29 -0
  279. package/test/actions/send_broadcast.test.ts +44 -0
  280. package/test/actions/set_contact_channel.test.ts +88 -0
  281. package/test/actions/set_contact_field.test.ts +68 -0
  282. package/test/actions/set_contact_language.test.ts +55 -0
  283. package/test/actions/set_contact_name.test.ts +39 -0
  284. package/test/actions/set_contact_status.test.ts +64 -0
  285. package/test/actions/set_run_result.test.ts +61 -0
  286. package/test/actions/start_session.test.ts +82 -0
  287. package/test/nodes/split_by_contact_field.test.ts +59 -0
  288. package/test/nodes/split_by_run_result.test.ts +100 -0
  289. package/test/nodes/split_by_ticket.test.ts +157 -0
  290. package/test/nodes/split_by_webhook.test.ts +131 -0
  291. package/test/temba-contact-chat.test.ts +17 -0
  292. package/test/temba-flow-editor.test.ts +264 -0
  293. package/test/temba-flow-plumber.test.ts +62 -0
  294. package/test/temba-select.test.ts +6 -1
  295. package/test/utils.test.ts +4 -2
  296. package/web-dev-server.config.mjs +5 -1
  297. package/web-test-runner.config.mjs +4 -1
@@ -12,6 +12,7 @@ interface ConnectionEndpoints {
12
12
  targetX: number;
13
13
  targetY: number;
14
14
  targetFace: TargetFace;
15
+ jogYOffset: number;
15
16
  }
16
17
 
17
18
  interface ConnectionInfo {
@@ -47,7 +48,8 @@ export function calculateFlowchartPath(
47
48
  stubStart = 20,
48
49
  stubEnd = 10,
49
50
  cornerRadius = 5,
50
- targetFace: TargetFace = 'top'
51
+ targetFace: TargetFace = 'top',
52
+ jogYOffset = 0
51
53
  ): string {
52
54
  const r = cornerRadius;
53
55
 
@@ -66,7 +68,11 @@ export function calculateFlowchartPath(
66
68
  // jogY is the horizontal level — must be above entryY so the
67
69
  // final approach into the node is always downward (no backtracking).
68
70
  const dirX = targetX > sourceX ? 1 : -1;
69
- const jogY = Math.max(sourceY + r, Math.min(exitY, entryY - r));
71
+ const baseJogY = Math.max(sourceY + r, Math.min(exitY, entryY - r));
72
+ const jogY = Math.max(
73
+ sourceY + r,
74
+ Math.min(baseJogY + jogYOffset, entryY - r - 3)
75
+ );
70
76
 
71
77
  // Corner 1: vertical→horizontal at jogY
72
78
  const r1 = Math.min(r, jogY - sourceY);
@@ -321,11 +327,17 @@ export class Plumber {
321
327
  });
322
328
  this.pendingConnections = [];
323
329
 
324
- // Repaint all connections that share a target with newly created ones
325
- // so anchor distribution is correct after the full batch is processed
330
+ // Repaint all connections that share a target or source with newly
331
+ // created ones so anchor distribution and jogY offsets are correct
326
332
  if (createdTargets.size > 0) {
327
- this.connections.forEach((conn, exitId) => {
333
+ const createdScopes = new Set<string>();
334
+ this.connections.forEach((conn) => {
328
335
  if (createdTargets.has(conn.toId)) {
336
+ createdScopes.add(conn.scope);
337
+ }
338
+ });
339
+ this.connections.forEach((conn, exitId) => {
340
+ if (createdTargets.has(conn.toId) || createdScopes.has(conn.scope)) {
329
341
  this.updateConnectionSVG(exitId);
330
342
  }
331
343
  });
@@ -371,7 +383,8 @@ export class Plumber {
371
383
 
372
384
  private getConnectionEndpoints(
373
385
  fromId: string,
374
- toId: string
386
+ toId: string,
387
+ scope?: string
375
388
  ): ConnectionEndpoints | null {
376
389
  const fromEl = document.getElementById(fromId);
377
390
  const toEl = document.getElementById(toId);
@@ -476,7 +489,57 @@ export class Plumber {
476
489
  : targetTop + margin + (span * (index + 0.5)) / count;
477
490
  }
478
491
 
479
- return { sourceX, sourceY, targetX, targetY, targetFace };
492
+ // Compute jogYOffset: stagger horizontal segments for sibling exits
493
+ // from the same source node so paths don't overlap
494
+ let jogYOffset = 0;
495
+ if (targetFace === 'top' && scope) {
496
+ const SIBLING_SPACING = 8;
497
+ const MAX_SPREAD = 50;
498
+
499
+ const siblings: { fromId: string; targetX: number }[] = [];
500
+ this.connections.forEach((conn) => {
501
+ if (conn.scope === scope && conn.toId !== toId) {
502
+ const connFromEl = document.getElementById(conn.fromId);
503
+ const connToEl = document.getElementById(conn.toId);
504
+ if (connFromEl && connToEl) {
505
+ const connFromRect = connFromEl.getBoundingClientRect();
506
+ const connToRect = connToEl.getBoundingClientRect();
507
+ const connSourceX =
508
+ connFromRect.left + connFromRect.width / 2 - canvasRect.left;
509
+ const connSourceY = connFromRect.bottom - canvasRect.top;
510
+ const connFace = this.determineTargetFace(
511
+ connSourceX,
512
+ connSourceY,
513
+ connToRect,
514
+ canvasRect
515
+ );
516
+ if (connFace === 'top') {
517
+ const connTargetLeft = connToRect.left - canvasRect.left;
518
+ const connTargetW = connToRect.width;
519
+ siblings.push({
520
+ fromId: conn.fromId,
521
+ targetX: connTargetLeft + connTargetW / 2
522
+ });
523
+ }
524
+ }
525
+ }
526
+ });
527
+
528
+ if (siblings.length > 0) {
529
+ siblings.push({ fromId, targetX });
530
+ siblings.sort((a, b) => a.targetX - b.targetX);
531
+ const idx = siblings.findIndex((s) => s.fromId === fromId);
532
+ const sibCount = siblings.length;
533
+ const rawSpread = (sibCount - 1) * SIBLING_SPACING;
534
+ const spacing =
535
+ rawSpread > MAX_SPREAD
536
+ ? MAX_SPREAD / (sibCount - 1)
537
+ : SIBLING_SPACING;
538
+ jogYOffset = (idx - (sibCount - 1) / 2) * spacing;
539
+ }
540
+ }
541
+
542
+ return { sourceX, sourceY, targetX, targetY, targetFace, jogYOffset };
480
543
  }
481
544
 
482
545
  // --- SVG creation and management ---
@@ -535,7 +598,8 @@ export class Plumber {
535
598
  sourceY: number,
536
599
  targetX: number,
537
600
  targetY: number,
538
- targetFace: TargetFace = 'top'
601
+ targetFace: TargetFace = 'top',
602
+ jogYOffset = 0
539
603
  ) {
540
604
  const aw = ARROW_HALF_WIDTH;
541
605
  const al = ARROW_LENGTH;
@@ -562,7 +626,8 @@ export class Plumber {
562
626
  EXIT_STUB,
563
627
  effectiveStub,
564
628
  5,
565
- targetFace
629
+ targetFace,
630
+ jogYOffset
566
631
  );
567
632
  pathEl.setAttribute('d', d);
568
633
 
@@ -596,7 +661,7 @@ export class Plumber {
596
661
  scope: string,
597
662
  toId: string
598
663
  ): boolean {
599
- const endpoints = this.getConnectionEndpoints(exitId, toId);
664
+ const endpoints = this.getConnectionEndpoints(exitId, toId, scope);
600
665
  if (!endpoints) return false;
601
666
 
602
667
  const { svgEl, pathEl, arrowEl } = this.createSVGElement();
@@ -607,7 +672,8 @@ export class Plumber {
607
672
  endpoints.sourceY,
608
673
  endpoints.targetX,
609
674
  endpoints.targetY,
610
- endpoints.targetFace
675
+ endpoints.targetFace,
676
+ endpoints.jogYOffset
611
677
  );
612
678
  this.canvas.appendChild(svgEl);
613
679
 
@@ -674,7 +740,11 @@ export class Plumber {
674
740
  const conn = this.connections.get(exitId);
675
741
  if (!conn) return;
676
742
 
677
- const endpoints = this.getConnectionEndpoints(conn.fromId, conn.toId);
743
+ const endpoints = this.getConnectionEndpoints(
744
+ conn.fromId,
745
+ conn.toId,
746
+ conn.scope
747
+ );
678
748
  if (!endpoints) return;
679
749
 
680
750
  this.updateSVGPath(
@@ -684,7 +754,8 @@ export class Plumber {
684
754
  endpoints.sourceY,
685
755
  endpoints.targetX,
686
756
  endpoints.targetY,
687
- endpoints.targetFace
757
+ endpoints.targetFace,
758
+ endpoints.jogYOffset
688
759
  );
689
760
  this.updateOverlayPosition(exitId);
690
761
  }
@@ -901,7 +972,11 @@ export class Plumber {
901
972
  const conn = this.connections.get(exitId);
902
973
  if (!overlayEl || !conn) return;
903
974
 
904
- const endpoints = this.getConnectionEndpoints(conn.fromId, conn.toId);
975
+ const endpoints = this.getConnectionEndpoints(
976
+ conn.fromId,
977
+ conn.toId,
978
+ conn.scope
979
+ );
905
980
  if (!endpoints) return;
906
981
 
907
982
  overlayEl.style.position = 'absolute';
@@ -52,7 +52,10 @@ export const add_contact_groups: ActionConfig = {
52
52
  return {
53
53
  uuid: formData.uuid,
54
54
  type: 'add_contact_groups',
55
- groups: formData.groups || []
55
+ groups: (formData.groups || []).map((g: any) => ({
56
+ uuid: g.uuid,
57
+ name: g.name
58
+ }))
56
59
  };
57
60
  }
58
61
  };
@@ -53,7 +53,10 @@ export const add_input_labels: ActionConfig = {
53
53
  return {
54
54
  uuid: formData.uuid,
55
55
  type: 'add_input_labels',
56
- labels: formData.labels || []
56
+ labels: (formData.labels || []).map((l: any) => ({
57
+ uuid: l.uuid,
58
+ name: l.name
59
+ }))
57
60
  };
58
61
  }
59
62
  };
@@ -69,7 +69,12 @@ export const remove_contact_groups: ActionConfig = {
69
69
  return {
70
70
  uuid: formData.uuid,
71
71
  type: 'remove_contact_groups',
72
- groups: formData.all_groups ? [] : formData.groups || [],
72
+ groups: formData.all_groups
73
+ ? []
74
+ : (formData.groups || []).map((g: any) => ({
75
+ uuid: g.uuid,
76
+ name: g.name
77
+ })),
73
78
  all_groups: formData.all_groups || false
74
79
  };
75
80
  }
@@ -70,8 +70,12 @@ export const send_broadcast: ActionConfig = {
70
70
 
71
71
  fromFormData: (formData: FormData): SendBroadcast => {
72
72
  const recipients = formData.recipients || [];
73
- const contacts = recipients.filter((r: any) => !r.group);
74
- const groups = recipients.filter((r: any) => r.group);
73
+ const contacts = recipients
74
+ .filter((r: any) => !r.group)
75
+ .map((c: any) => ({ uuid: c.uuid, name: c.name }));
76
+ const groups = recipients
77
+ .filter((r: any) => r.group)
78
+ .map((g: any) => ({ uuid: g.uuid, name: g.name }));
75
79
 
76
80
  const result: SendBroadcast = {
77
81
  uuid: formData.uuid,
@@ -1,5 +1,5 @@
1
1
  import { html } from 'lit-html';
2
- import { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';
2
+ import { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';
3
3
  import { Node, SetContactChannel } from '../../store/flow-definition';
4
4
 
5
5
  export const set_contact_channel: ActionConfig = {
@@ -19,6 +19,7 @@ export const set_contact_channel: ActionConfig = {
19
19
  endpoint: '/api/v2/channels.json',
20
20
  valueKey: 'uuid',
21
21
  nameKey: 'name',
22
+ placeholder: 'Select channel',
22
23
  helpText: 'Select the channel to set for the contact'
23
24
  }
24
25
  },
@@ -27,5 +28,16 @@ export const set_contact_channel: ActionConfig = {
27
28
  uuid: action.uuid,
28
29
  channel: action.channel ? [action.channel] : null
29
30
  };
31
+ },
32
+ fromFormData: (formData: FormData): SetContactChannel => {
33
+ const channel = formData.channel?.[0];
34
+ return {
35
+ uuid: formData.uuid,
36
+ type: 'set_contact_channel',
37
+ channel: {
38
+ uuid: channel.uuid || channel.value,
39
+ name: channel.name
40
+ }
41
+ };
30
42
  }
31
43
  };
@@ -12,11 +12,13 @@ export const set_contact_status: ActionConfig = {
12
12
  },
13
13
  toFormData: (action: SetContactStatus) => {
14
14
  return {
15
- ...action,
16
- status: {
17
- name: titleCase(action.status || 'active'),
18
- value: action.status || 'active'
19
- }
15
+ uuid: action.uuid,
16
+ status: [
17
+ {
18
+ name: titleCase(action.status || 'active'),
19
+ value: action.status || 'active'
20
+ }
21
+ ]
20
22
  };
21
23
  },
22
24
  fromFormData: (formData: FormData): SetContactStatus => {
@@ -186,7 +186,10 @@ export const start_session: ActionConfig = {
186
186
  } = {
187
187
  uuid: formData.uuid,
188
188
  type: 'start_session',
189
- flow: formData.flow[0],
189
+ flow: {
190
+ uuid: formData.flow[0].uuid || formData.flow[0].value,
191
+ name: formData.flow[0].name
192
+ },
190
193
  groups: [],
191
194
  contacts: []
192
195
  };
@@ -202,8 +205,12 @@ export const start_session: ActionConfig = {
202
205
  } else {
203
206
  // Manual selection - separate contacts and groups
204
207
  const recipients = formData.recipients || [];
205
- action.contacts = recipients.filter((r: any) => !r.group);
206
- action.groups = recipients.filter((r: any) => r.group);
208
+ action.contacts = recipients
209
+ .filter((r: any) => !r.group)
210
+ .map((c: any) => ({ uuid: c.uuid, name: c.name }));
211
+ action.groups = recipients
212
+ .filter((r: any) => r.group)
213
+ .map((g: any) => ({ uuid: g.uuid, name: g.name }));
207
214
  }
208
215
 
209
216
  // Add exclusions if set
@@ -38,10 +38,10 @@ const getOperandForField = (field: any): string => {
38
38
  }
39
39
  // For system properties, use the id
40
40
  if (field.type === 'property') {
41
- return `@contact.${field.id}`;
41
+ return `@contact.${field.id || field.value}`;
42
42
  }
43
- // Fallback to key
44
- return `@fields.${field.key}`;
43
+ // For custom fields, use key with fallbacks
44
+ return `@fields.${field.key || field.id || field.value}`;
45
45
  };
46
46
 
47
47
  export const split_by_contact_field: NodeConfig = {
@@ -79,7 +79,7 @@ export const split_by_contact_field: NodeConfig = {
79
79
  },
80
80
  rules: createRulesArrayConfig(
81
81
  operatorsToSelectOptions(getWaitForResponseOperators()),
82
- 'Define rules to split the contact field into categories'
82
+ ''
83
83
  ),
84
84
  result_name: resultNameField
85
85
  },
@@ -98,7 +98,18 @@ export const split_by_contact_field: NodeConfig = {
98
98
  },
99
99
  toFormData: (node: Node, nodeUI?: any) => {
100
100
  // Get the field from the UI config operand (source of truth)
101
- const field = nodeUI?.config?.operand || CONTACT_PROPERTIES.name;
101
+ const operand = nodeUI?.config?.operand || CONTACT_PROPERTIES.name;
102
+
103
+ // Normalize the field object to include properties expected by
104
+ // the Select component (valueKey: 'key') and getOperandForField.
105
+ // toUIConfig saves only { id, name, type }, so we need to add
106
+ // 'key' for custom fields and 'value' for static option matching.
107
+ const field = { ...operand };
108
+ if (field.type === 'field') {
109
+ if (!field.key) field.key = field.id;
110
+ } else {
111
+ if (!field.value) field.value = field.id;
112
+ }
102
113
 
103
114
  // Extract rules from router cases using shared function
104
115
  const rules = casesToFormRules(node);
@@ -34,7 +34,7 @@ export const split_by_expression: NodeConfig = {
34
34
  },
35
35
  rules: createRulesArrayConfig(
36
36
  operatorsToSelectOptions(getWaitForResponseOperators()),
37
- 'Define rules to categorize the expression result'
37
+ ''
38
38
  ),
39
39
  result_name: resultNameField
40
40
  },
@@ -34,7 +34,6 @@ export const split_by_llm_categorize: NodeConfig = {
34
34
  },
35
35
  categories: {
36
36
  type: 'array',
37
- label: 'Categories',
38
37
  helpText: 'Define the categories for classification',
39
38
  required: true,
40
39
  sortable: true,
@@ -57,7 +57,6 @@ export const split_by_random: NodeConfig = {
57
57
  form: {
58
58
  categories: {
59
59
  type: 'array',
60
- label: 'Buckets',
61
60
  helpText: 'Define the buckets to randomly split contacts into',
62
61
  required: true,
63
62
  itemLabel: 'Bucket',
@@ -105,7 +105,7 @@ export const split_by_run_result: NodeConfig = {
105
105
  },
106
106
  rules: createRulesArrayConfig(
107
107
  operatorsToSelectOptions(getWaitForResponseOperators()),
108
- 'Define rules to categorize the result'
108
+ ''
109
109
  ),
110
110
  result_name: resultNameField
111
111
  },
@@ -135,7 +135,12 @@ export const split_by_run_result: NodeConfig = {
135
135
  },
136
136
  toFormData: (node: Node, nodeUI?: any) => {
137
137
  // Get the result from the UI config operand (source of truth)
138
- const result = nodeUI?.config?.operand;
138
+ // Normalize: toUIConfig saves { id, name, type } but the Select component
139
+ // (valueKey: 'value') and fromFormData expect a 'value' property.
140
+ const savedOperand = nodeUI?.config?.operand;
141
+ const result = savedOperand
142
+ ? { ...savedOperand, value: savedOperand.value || savedOperand.id }
143
+ : null;
139
144
 
140
145
  // Extract rules from router cases using shared function
141
146
  const rules = casesToFormRules(node);
@@ -180,6 +185,7 @@ export const split_by_run_result: NodeConfig = {
180
185
 
181
186
  // Build operand based on whether delimiter is selected
182
187
  let operand: string;
188
+ const resultKey = selectedResult.value || selectedResult.id;
183
189
  const delimitBy = formData.delimit_by?.[0]?.value;
184
190
  const hasDelimiter = delimitBy !== undefined && delimitBy !== '';
185
191
 
@@ -188,10 +194,10 @@ export const split_by_run_result: NodeConfig = {
188
194
  const delimitIndex = formData.delimit_index?.[0]?.value ?? '0';
189
195
 
190
196
  // Build operand with field() function
191
- operand = `@(field(results.${selectedResult.value}, ${delimitIndex}, "${delimitBy}"))`;
197
+ operand = `@(field(results.${resultKey}, ${delimitIndex}, "${delimitBy}"))`;
192
198
  } else {
193
199
  // Standard operand without delimiter
194
- operand = `@results.${selectedResult.value}`;
200
+ operand = `@results.${resultKey}`;
195
201
  }
196
202
 
197
203
  // Get user rules using shared extraction function
@@ -25,7 +25,8 @@ export const wait_for_digits: NodeConfig = {
25
25
  dialogSize: 'large',
26
26
  form: {
27
27
  rules: createRulesArrayConfig(
28
- operatorsToSelectOptions(getDigitOperators())
28
+ operatorsToSelectOptions(getDigitOperators()),
29
+ ''
29
30
  ),
30
31
  result_name: resultNameField
31
32
  },
@@ -86,7 +86,7 @@ export const wait_for_response: NodeConfig = {
86
86
  form: {
87
87
  rules: createRulesArrayConfig(
88
88
  operatorsToSelectOptions(getWaitForResponseOperators()),
89
- 'Define rules to categorize responses'
89
+ 'If the message from the contact...'
90
90
  ),
91
91
  timeout_enabled: {
92
92
  type: 'checkbox',
@@ -356,6 +356,13 @@ export class FieldRenderer {
356
356
  } = context;
357
357
 
358
358
  return html`<div class="form-field">
359
+ ${config.helpText
360
+ ? html`<div
361
+ style="color: #666; font-size: 13px; margin-bottom: 14px;"
362
+ >
363
+ ${config.helpText}
364
+ </div>`
365
+ : ''}
359
366
  <temba-array-editor
360
367
  name="${fieldName}"
361
368
  .label="${showLabel ? config.label : ''}"
@@ -95,7 +95,6 @@ export class Dialog extends ResizeElement {
95
95
  }
96
96
 
97
97
  .dialog-mask .dialog-container {
98
-
99
98
  position: relative;
100
99
  transition: transform var(--transition-speed) ease-in-out,
101
100
  opacity ease-in-out calc(var(--transition-speed) - 50ms);
@@ -148,9 +148,22 @@ export class Modax extends RapidElement {
148
148
 
149
149
  @property({ type: Boolean })
150
150
  suspendSubmit = false;
151
+
152
+ @property({ type: Number })
153
+ originX: number | null = null;
154
+
155
+ @property({ type: Number })
156
+ originY: number | null = null;
157
+
151
158
  // private cancelToken: CancelTokenSource;
152
159
 
153
- private handleSlotClicked(): void {
160
+ private handleSlotClicked(event: MouseEvent): void {
161
+ const el = event.currentTarget as Element;
162
+ if (el) {
163
+ const rect = el.getBoundingClientRect();
164
+ this.originX = rect.left + rect.width / 2;
165
+ this.originY = rect.top;
166
+ }
154
167
  this.open = true;
155
168
  }
156
169
 
@@ -173,6 +186,8 @@ export class Modax extends RapidElement {
173
186
  // clear the modal body out when closed, note that js functions declared on the
174
187
  // window will hang around
175
188
  this.setBody('');
189
+ this.originX = null;
190
+ this.originY = null;
176
191
  }
177
192
  }
178
193
  }
@@ -441,11 +456,13 @@ export class Modax extends RapidElement {
441
456
  .header=${this.header}
442
457
  .buttons=${this.buttons}
443
458
  ?open=${this.open}
444
- ?loading=${this.fetching}
459
+ ?loading=${this.fetching && this.originX == null}
445
460
  ?submitting=${this.submitting}
446
461
  ?destructive=${this.isDestructive()}
447
462
  ?noFocus=${true}
448
463
  ?disabled=${this.disabled}
464
+ .originX=${this.originX}
465
+ .originY=${this.originY}
449
466
  @temba-button-clicked=${this.handleDialogClick.bind(this)}
450
467
  @temba-dialog-hidden=${this.handleDialogHidden.bind(this)}
451
468
  >
@@ -159,8 +159,22 @@ export class ContentMenu extends RapidElement {
159
159
  }
160
160
  }
161
161
 
162
+ private getTopCenter(el: Element): { x: number; y: number } {
163
+ const rect = el.getBoundingClientRect();
164
+ return { x: rect.left + rect.width / 2, y: rect.top };
165
+ }
166
+
162
167
  private handleItemClicked(item: ContentMenuItem, event: MouseEvent) {
163
- this.fireCustomEvent(CustomEventType.Selection, { item, event });
168
+ const el = event.currentTarget as Element;
169
+ const origin = el
170
+ ? this.getTopCenter(el)
171
+ : { x: event.clientX, y: event.clientY };
172
+ this.fireCustomEvent(CustomEventType.Selection, {
173
+ item,
174
+ event,
175
+ originX: origin.x,
176
+ originY: origin.y
177
+ });
164
178
  }
165
179
 
166
180
  public render(): TemplateResult {
@@ -162,6 +162,15 @@ export class ContactChat extends ContactStoreElement {
162
162
  opacity: 0.9;
163
163
  }
164
164
 
165
+ .flow-footer {
166
+ text-align: center;
167
+ pointer-events: none;
168
+ }
169
+
170
+ .flow-footer .in-flow {
171
+ pointer-events: auto;
172
+ }
173
+
165
174
  .in-flow:hover {
166
175
  opacity: 1;
167
176
  }
@@ -780,7 +789,7 @@ export class ContactChat extends ContactStoreElement {
780
789
  >
781
790
  ${inFlow
782
791
  ? html`
783
- <div slot="footer" style="text-align:center;">
792
+ <div slot="footer" class="flow-footer">
784
793
  <div class="in-flow">
785
794
  <div class="flow-name">
786
795
  <temba-icon name="flow" size="1.2"></temba-icon>
@@ -759,7 +759,7 @@ export class TembaChart extends RapidElement {
759
759
  private getValueAxisConfig() {
760
760
  return {
761
761
  min: 0,
762
- ...(this.showPercent && { max:this.getInflatedMax() }),
762
+ ...(this.showPercent && { max: this.getInflatedMax() }),
763
763
  stacked: true,
764
764
  grid: {
765
765
  color: 'rgba(0,0,0,0.04)',
package/src/locales/es.ts CHANGED
@@ -1,13 +1,18 @@
1
- // Do not modify this file by hand!
2
- // Re-generate this file by running lit-localize
3
-
4
- /* eslint-disable no-irregular-whitespace */
5
- /* eslint-disable @typescript-eslint/no-explicit-any */
6
-
7
- export const templates = {
8
- scf1453991c986b25: `Tab para completar, enter para seleccionar`,
9
- s73b4d70c02f4b4e0: `No options`,
10
- s8f02e3a18ffc083a: `Are not currently in a flow`,
11
- s638236250662c6b3: `Have sent a message in the last`,
12
- s4788ee206c4570c7: `Have not started this flow in the last 90 days`
13
- };
1
+
2
+ // Do not modify this file by hand!
3
+ // Re-generate this file by running lit-localize
4
+
5
+
6
+
7
+
8
+ /* eslint-disable no-irregular-whitespace */
9
+ /* eslint-disable @typescript-eslint/no-explicit-any */
10
+
11
+ export const templates = {
12
+ 'scf1453991c986b25': `Tab para completar, enter para seleccionar`,
13
+ 's73b4d70c02f4b4e0': `No options`,
14
+ 's8f02e3a18ffc083a': `Are not currently in a flow`,
15
+ 's638236250662c6b3': `Have sent a message in the last`,
16
+ 's4788ee206c4570c7': `Have not started this flow in the last 90 days`,
17
+ };
18
+
package/src/locales/fr.ts CHANGED
@@ -1,13 +1,18 @@
1
- // Do not modify this file by hand!
2
- // Re-generate this file by running lit-localize
3
-
4
- /* eslint-disable no-irregular-whitespace */
5
- /* eslint-disable @typescript-eslint/no-explicit-any */
6
-
7
- export const templates = {
8
- s73b4d70c02f4b4e0: `No options`,
9
- scf1453991c986b25: `Tab to complete, enter to select`,
10
- s8f02e3a18ffc083a: `Are not currently in a flow`,
11
- s638236250662c6b3: `Have sent a message in the last`,
12
- s4788ee206c4570c7: `Have not started this flow in the last 90 days`
13
- };
1
+
2
+ // Do not modify this file by hand!
3
+ // Re-generate this file by running lit-localize
4
+
5
+
6
+
7
+
8
+ /* eslint-disable no-irregular-whitespace */
9
+ /* eslint-disable @typescript-eslint/no-explicit-any */
10
+
11
+ export const templates = {
12
+ 's73b4d70c02f4b4e0': `No options`,
13
+ 'scf1453991c986b25': `Tab to complete, enter to select`,
14
+ 's8f02e3a18ffc083a': `Are not currently in a flow`,
15
+ 's638236250662c6b3': `Have sent a message in the last`,
16
+ 's4788ee206c4570c7': `Have not started this flow in the last 90 days`,
17
+ };
18
+