@nyaruka/temba-components 0.129.1 → 0.129.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (583) hide show
  1. package/.github/workflows/build.yml +6 -5
  2. package/.github/workflows/coverage.yml +80 -0
  3. package/CHANGELOG.md +32 -0
  4. package/README.md +6 -0
  5. package/check-coverage.js +133 -0
  6. package/demo/components/alert/example.html +71 -0
  7. package/demo/components/button/example.html +167 -0
  8. package/demo/{chart → components/chart}/example.html +3 -3
  9. package/demo/components/chart/horizontal-demo.html +160 -0
  10. package/demo/components/checkbox/example.html +68 -0
  11. package/demo/components/compose/example.html +69 -0
  12. package/demo/components/datepicker/example.html +3 -3
  13. package/demo/components/datepicker/range-picker-demo.html +2 -2
  14. package/demo/{dialog → components/dialog}/example.html +3 -3
  15. package/demo/components/dropdown/example.html +95 -0
  16. package/demo/{flow → components/flow}/example.html +1 -1
  17. package/demo/{misc → components/misc}/example.html +3 -3
  18. package/demo/components/progress/example.html +62 -0
  19. package/demo/components/select/drag-and-drop.html +162 -0
  20. package/demo/components/select/example.html +76 -0
  21. package/demo/components/select/multi.html +72 -0
  22. package/demo/components/slider/example.html +55 -0
  23. package/demo/{sortable-list → components/sortable-list}/example.html +3 -3
  24. package/demo/components/tabs/example.html +91 -0
  25. package/demo/{textinput → components/textinput}/completion.html +3 -3
  26. package/demo/components/textinput/example.html +141 -0
  27. package/demo/{webchat → components/webchat}/example.html +3 -3
  28. package/demo/data/flows/sample-flow.json +107 -100
  29. package/demo/index.html +21 -21
  30. package/demo/static/css/styles.css +253 -0
  31. package/demo/sticky-note-demo.html +88 -85
  32. package/demo/styles.css +24 -0
  33. package/dist/locales/es.js +5 -5
  34. package/dist/locales/es.js.map +1 -1
  35. package/dist/locales/fr.js +5 -5
  36. package/dist/locales/fr.js.map +1 -1
  37. package/dist/locales/locale-codes.js +2 -11
  38. package/dist/locales/locale-codes.js.map +1 -1
  39. package/dist/locales/pt.js +5 -5
  40. package/dist/locales/pt.js.map +1 -1
  41. package/dist/temba-components.js +893 -476
  42. package/dist/temba-components.js.map +1 -1
  43. package/generate-coverage-badge.sh +69 -0
  44. package/out-tsc/src/{vectoricon/index.js → Icons.js} +1 -1
  45. package/out-tsc/src/Icons.js.map +1 -0
  46. package/out-tsc/src/display/Alert.js.map +1 -0
  47. package/out-tsc/src/display/Anchor.js.map +1 -0
  48. package/out-tsc/src/display/Button.js.map +1 -0
  49. package/out-tsc/src/{charcount → display}/CharCount.js +159 -2
  50. package/out-tsc/src/display/CharCount.js.map +1 -0
  51. package/out-tsc/src/display/Chat.js.map +1 -0
  52. package/out-tsc/src/display/ContactName.js.map +1 -0
  53. package/out-tsc/src/display/ContactUrn.js.map +1 -0
  54. package/out-tsc/src/display/Dropdown.js.map +1 -0
  55. package/out-tsc/src/{vectoricon/VectorIcon.js → display/Icon.js} +2 -2
  56. package/out-tsc/src/display/Icon.js.map +1 -0
  57. package/out-tsc/src/display/Label.js.map +1 -0
  58. package/out-tsc/src/{leafletmap → display}/LeafletMap.js +16 -1
  59. package/out-tsc/src/display/LeafletMap.js.map +1 -0
  60. package/out-tsc/src/display/Lightbox.js.map +1 -0
  61. package/out-tsc/src/{loading → display}/Loading.js.map +1 -1
  62. package/out-tsc/src/{options → display}/Options.js.map +1 -1
  63. package/out-tsc/src/display/ProgressBar.js.map +1 -0
  64. package/out-tsc/src/display/TembaDate.js.map +1 -0
  65. package/out-tsc/src/display/TembaUser.js.map +1 -0
  66. package/out-tsc/src/display/Thumbnail.js.map +1 -0
  67. package/out-tsc/src/{tip → display}/Tip.js +1 -2
  68. package/out-tsc/src/display/Tip.js.map +1 -0
  69. package/out-tsc/src/display/Toast.js.map +1 -0
  70. package/out-tsc/src/display/sms/gsmsplitter.js.map +1 -0
  71. package/out-tsc/src/display/sms/gsmvalidator.js.map +1 -0
  72. package/out-tsc/src/display/sms/index.js.map +1 -0
  73. package/out-tsc/src/display/sms/unicodesplitter.js.map +1 -0
  74. package/out-tsc/src/events.js +2 -0
  75. package/out-tsc/src/events.js.map +1 -0
  76. package/out-tsc/src/excellent/ExcellentParser.js.map +1 -0
  77. package/out-tsc/src/excellent/helpers.js.map +1 -0
  78. package/out-tsc/src/flow/Editor.js +533 -140
  79. package/out-tsc/src/flow/Editor.js.map +1 -1
  80. package/out-tsc/src/flow/EditorNode.js +287 -20
  81. package/out-tsc/src/flow/EditorNode.js.map +1 -1
  82. package/out-tsc/src/flow/Plumber.js +154 -74
  83. package/out-tsc/src/flow/Plumber.js.map +1 -1
  84. package/out-tsc/src/flow/StickyNote.js +153 -9
  85. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  86. package/out-tsc/src/flow/config.js +88 -18
  87. package/out-tsc/src/flow/config.js.map +1 -1
  88. package/out-tsc/src/flow/render.js +327 -10
  89. package/out-tsc/src/flow/render.js.map +1 -1
  90. package/out-tsc/src/{checkbox → form}/Checkbox.js +2 -2
  91. package/out-tsc/src/form/Checkbox.js.map +1 -0
  92. package/out-tsc/src/{colorpicker → form}/ColorPicker.js +1 -1
  93. package/out-tsc/src/form/ColorPicker.js.map +1 -0
  94. package/out-tsc/src/{completion → form}/Completion.js +2 -2
  95. package/out-tsc/src/form/Completion.js.map +1 -0
  96. package/out-tsc/src/{compose → form}/Compose.js +1 -1
  97. package/out-tsc/src/form/Compose.js.map +1 -0
  98. package/out-tsc/src/{contactsearch → form}/ContactSearch.js +2 -2
  99. package/out-tsc/src/form/ContactSearch.js.map +1 -0
  100. package/out-tsc/src/form/CroppieCSS.js.map +1 -0
  101. package/out-tsc/src/{datepicker → form}/DatePicker.js +1 -1
  102. package/out-tsc/src/form/DatePicker.js.map +1 -0
  103. package/out-tsc/src/{FormElement.js → form/FormElement.js} +1 -1
  104. package/out-tsc/src/form/FormElement.js.map +1 -0
  105. package/out-tsc/src/form/FormField.js.map +1 -0
  106. package/out-tsc/src/{imagepicker → form}/ImagePicker.js +2 -2
  107. package/out-tsc/src/form/ImagePicker.js.map +1 -0
  108. package/out-tsc/src/{mediapicker → form}/MediaPicker.js +1 -1
  109. package/out-tsc/src/form/MediaPicker.js.map +1 -0
  110. package/out-tsc/src/{datepicker → form}/RangePicker.js +3 -2
  111. package/out-tsc/src/form/RangePicker.js.map +1 -0
  112. package/out-tsc/src/{slider → form}/TembaSlider.js +1 -1
  113. package/out-tsc/src/form/TembaSlider.js.map +1 -0
  114. package/out-tsc/src/{templates → form}/TemplateEditor.js +1 -1
  115. package/out-tsc/src/form/TemplateEditor.js.map +1 -0
  116. package/out-tsc/src/{textinput → form}/TextInput.js +3 -3
  117. package/out-tsc/src/form/TextInput.js.map +1 -0
  118. package/out-tsc/src/{omnibox → form/select}/Omnibox.js +2 -2
  119. package/out-tsc/src/form/select/Omnibox.js.map +1 -0
  120. package/out-tsc/src/{select → form/select}/PopupSelect.js +1 -1
  121. package/out-tsc/src/form/select/PopupSelect.js.map +1 -0
  122. package/out-tsc/src/{select → form/select}/Select.js +86 -87
  123. package/out-tsc/src/form/select/Select.js.map +1 -0
  124. package/out-tsc/src/{select → form/select}/UserSelect.js +1 -1
  125. package/out-tsc/src/form/select/UserSelect.js.map +1 -0
  126. package/out-tsc/src/{select → form/select}/WorkspaceSelect.js +1 -1
  127. package/out-tsc/src/form/select/WorkspaceSelect.js.map +1 -0
  128. package/out-tsc/src/interfaces.js +1 -0
  129. package/out-tsc/src/interfaces.js.map +1 -1
  130. package/out-tsc/src/layout/Dialog.js.map +1 -0
  131. package/out-tsc/src/layout/Mask.js.map +1 -0
  132. package/out-tsc/src/{dialog → layout}/Modax.js.map +1 -1
  133. package/out-tsc/src/layout/Resizer.js.map +1 -0
  134. package/out-tsc/src/layout/Tab.js.map +1 -0
  135. package/out-tsc/src/layout/TabPane.js.map +1 -0
  136. package/out-tsc/src/list/NotificationList.js +1 -1
  137. package/out-tsc/src/list/NotificationList.js.map +1 -1
  138. package/out-tsc/src/list/RunList.js +1 -1
  139. package/out-tsc/src/list/RunList.js.map +1 -1
  140. package/out-tsc/src/list/ShortcutList.js.map +1 -1
  141. package/out-tsc/src/list/TembaMenu.js +1 -1
  142. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  143. package/out-tsc/src/list/TicketList.js +1 -1
  144. package/out-tsc/src/list/TicketList.js.map +1 -1
  145. package/out-tsc/src/{aliaseditor → live}/AliasEditor.js +1 -1
  146. package/out-tsc/src/live/AliasEditor.js.map +1 -0
  147. package/out-tsc/src/{contacts → live}/ContactBadges.js +1 -1
  148. package/out-tsc/src/live/ContactBadges.js.map +1 -0
  149. package/out-tsc/src/{contacts → live}/ContactChat.js +79 -3
  150. package/out-tsc/src/live/ContactChat.js.map +1 -0
  151. package/out-tsc/src/{contacts → live}/ContactDetails.js +1 -1
  152. package/out-tsc/src/live/ContactDetails.js.map +1 -0
  153. package/out-tsc/src/{contacts → live}/ContactFieldEditor.js +2 -2
  154. package/out-tsc/src/live/ContactFieldEditor.js.map +1 -0
  155. package/out-tsc/src/live/ContactFields.js.map +1 -0
  156. package/out-tsc/src/live/ContactNameFetch.js.map +1 -0
  157. package/out-tsc/src/{contacts → live}/ContactNotepad.js +1 -1
  158. package/out-tsc/src/{contacts → live}/ContactNotepad.js.map +1 -1
  159. package/out-tsc/src/{contacts → live}/ContactPending.js +1 -1
  160. package/out-tsc/src/live/ContactPending.js.map +1 -0
  161. package/out-tsc/src/live/ContactStoreElement.js.map +1 -0
  162. package/out-tsc/src/live/FieldManager.js.map +1 -0
  163. package/out-tsc/src/live/StartProgress.js.map +1 -0
  164. package/out-tsc/src/{chart → live}/TembaChart.js +5 -1
  165. package/out-tsc/src/live/TembaChart.js.map +1 -0
  166. package/out-tsc/src/locales/es.js +5 -5
  167. package/out-tsc/src/locales/es.js.map +1 -1
  168. package/out-tsc/src/locales/fr.js +5 -5
  169. package/out-tsc/src/locales/fr.js.map +1 -1
  170. package/out-tsc/src/locales/locale-codes.js +2 -11
  171. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  172. package/out-tsc/src/locales/pt.js +5 -5
  173. package/out-tsc/src/locales/pt.js.map +1 -1
  174. package/out-tsc/src/store/AppState.js +54 -24
  175. package/out-tsc/src/store/AppState.js.map +1 -1
  176. package/out-tsc/src/store/Store.js +1 -1
  177. package/out-tsc/src/store/Store.js.map +1 -1
  178. package/out-tsc/src/{utils/index.js → utils.js} +22 -1
  179. package/out-tsc/src/utils.js.map +1 -0
  180. package/out-tsc/src/webchat/WebChat.js +1 -1
  181. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  182. package/out-tsc/temba-components.js +2 -2
  183. package/out-tsc/temba-components.js.map +1 -1
  184. package/out-tsc/temba-modules.js +54 -54
  185. package/out-tsc/temba-modules.js.map +1 -1
  186. package/out-tsc/temba-webchat.js +2 -2
  187. package/out-tsc/temba-webchat.js.map +1 -1
  188. package/out-tsc/test/temba-alert.test.js +1 -1
  189. package/out-tsc/test/temba-alert.test.js.map +1 -1
  190. package/out-tsc/test/temba-appstate-language.test.js +90 -0
  191. package/out-tsc/test/temba-appstate-language.test.js.map +1 -1
  192. package/out-tsc/test/temba-charcount.test.js.map +1 -1
  193. package/out-tsc/test/temba-chart.test.js +1 -1
  194. package/out-tsc/test/temba-chart.test.js.map +1 -1
  195. package/out-tsc/test/temba-checkbox.test.js.map +1 -1
  196. package/out-tsc/test/temba-color-picker.test.js +1 -1
  197. package/out-tsc/test/temba-color-picker.test.js.map +1 -1
  198. package/out-tsc/test/temba-completion.test.js +1 -1
  199. package/out-tsc/test/temba-completion.test.js.map +1 -1
  200. package/out-tsc/test/temba-compose.test.js +1 -1
  201. package/out-tsc/test/temba-compose.test.js.map +1 -1
  202. package/out-tsc/test/temba-contact-badges.test.js +1 -1
  203. package/out-tsc/test/temba-contact-badges.test.js.map +1 -1
  204. package/out-tsc/test/temba-contact-chat.test.js +3 -1
  205. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  206. package/out-tsc/test/temba-contact-details.test.js +1 -1
  207. package/out-tsc/test/temba-contact-details.test.js.map +1 -1
  208. package/out-tsc/test/temba-contact-fields.test.js +1 -1
  209. package/out-tsc/test/temba-contact-fields.test.js.map +1 -1
  210. package/out-tsc/test/temba-contact-search.test.js +1 -1
  211. package/out-tsc/test/temba-contact-search.test.js.map +1 -1
  212. package/out-tsc/test/temba-date.test.js +5 -1
  213. package/out-tsc/test/temba-date.test.js.map +1 -1
  214. package/out-tsc/test/temba-datepicker.test.js +1 -1
  215. package/out-tsc/test/temba-datepicker.test.js.map +1 -1
  216. package/out-tsc/test/temba-dialog.test.js +1 -1
  217. package/out-tsc/test/temba-dialog.test.js.map +1 -1
  218. package/out-tsc/test/temba-dropdown.test.js +1 -1
  219. package/out-tsc/test/temba-dropdown.test.js.map +1 -1
  220. package/out-tsc/test/temba-excellent-helpers.test.js +316 -0
  221. package/out-tsc/test/temba-excellent-helpers.test.js.map +1 -0
  222. package/out-tsc/test/temba-field-manager.test.js.map +1 -1
  223. package/out-tsc/test/temba-flow-editor-node.test.js +414 -1
  224. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  225. package/out-tsc/test/temba-flow-editor.test.js +185 -0
  226. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  227. package/out-tsc/test/temba-flow-plumber-connections.test.js +113 -0
  228. package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -0
  229. package/out-tsc/test/temba-flow-plumber.test.js +73 -93
  230. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  231. package/out-tsc/test/temba-flow-render.test.js +624 -1
  232. package/out-tsc/test/temba-flow-render.test.js.map +1 -1
  233. package/out-tsc/test/temba-flow-self-routing.test.js +172 -0
  234. package/out-tsc/test/temba-flow-self-routing.test.js.map +1 -0
  235. package/out-tsc/test/temba-formfield.test.js.map +1 -1
  236. package/out-tsc/test/temba-icon.test.js +1 -1
  237. package/out-tsc/test/temba-icon.test.js.map +1 -1
  238. package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
  239. package/out-tsc/test/temba-label.test.js +1 -1
  240. package/out-tsc/test/temba-label.test.js.map +1 -1
  241. package/out-tsc/test/temba-lightbox.test.js +1 -1
  242. package/out-tsc/test/temba-lightbox.test.js.map +1 -1
  243. package/out-tsc/test/temba-markdown.test.js +127 -0
  244. package/out-tsc/test/temba-markdown.test.js.map +1 -0
  245. package/out-tsc/test/temba-menu.test.js +1 -1
  246. package/out-tsc/test/temba-menu.test.js.map +1 -1
  247. package/out-tsc/test/temba-modax.test.js +1 -1
  248. package/out-tsc/test/temba-modax.test.js.map +1 -1
  249. package/out-tsc/test/temba-modules.test.js +47 -0
  250. package/out-tsc/test/temba-modules.test.js.map +1 -0
  251. package/out-tsc/test/temba-omnibox.test.js +1 -1
  252. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  253. package/out-tsc/test/temba-options.test.js.map +1 -1
  254. package/out-tsc/test/temba-range-picker.test.js +9 -2
  255. package/out-tsc/test/temba-range-picker.test.js.map +1 -1
  256. package/out-tsc/test/temba-rapid-element.test.js +273 -0
  257. package/out-tsc/test/temba-rapid-element.test.js.map +1 -0
  258. package/out-tsc/test/temba-resize-element.test.js +85 -0
  259. package/out-tsc/test/temba-resize-element.test.js.map +1 -0
  260. package/out-tsc/test/temba-select.test.js +2 -2
  261. package/out-tsc/test/temba-select.test.js.map +1 -1
  262. package/out-tsc/test/temba-slider.test.js.map +1 -1
  263. package/out-tsc/test/temba-sticky-note.test.js +194 -0
  264. package/out-tsc/test/temba-sticky-note.test.js.map +1 -0
  265. package/out-tsc/test/temba-template-editor.test.js.map +1 -1
  266. package/out-tsc/test/temba-textinput.test.js +1 -1
  267. package/out-tsc/test/temba-textinput.test.js.map +1 -1
  268. package/out-tsc/test/temba-tip.test.js +1 -1
  269. package/out-tsc/test/temba-tip.test.js.map +1 -1
  270. package/out-tsc/test/temba-toast.test.js +1 -1
  271. package/out-tsc/test/temba-toast.test.js.map +1 -1
  272. package/out-tsc/test/temba-utils-index.test.js +1 -1
  273. package/out-tsc/test/temba-utils-index.test.js.map +1 -1
  274. package/out-tsc/test/temba-utils-uuid.test.js +38 -0
  275. package/out-tsc/test/temba-utils-uuid.test.js.map +1 -0
  276. package/out-tsc/test/temba-webchat.test.js +28 -12
  277. package/out-tsc/test/temba-webchat.test.js.map +1 -1
  278. package/out-tsc/test/utils.test.js +2 -6
  279. package/out-tsc/test/utils.test.js.map +1 -1
  280. package/package.json +18 -9
  281. package/rollup.components.mjs +1 -1
  282. package/screenshots/truth/datepicker/range-picker-all.png +0 -0
  283. package/screenshots/truth/datepicker/range-picker-button-states.png +0 -0
  284. package/screenshots/truth/datepicker/range-picker-default.png +0 -0
  285. package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
  286. package/screenshots/truth/datepicker/range-picker-initial-values.png +0 -0
  287. package/screenshots/truth/datepicker/range-picker-week.png +0 -0
  288. package/screenshots/truth/datepicker/range-picker-year.png +0 -0
  289. package/screenshots/truth/sticky-note/blue-color.png +0 -0
  290. package/screenshots/truth/sticky-note/blue.png +0 -0
  291. package/screenshots/truth/sticky-note/color-picker-expanded.png +0 -0
  292. package/screenshots/truth/sticky-note/default.png +0 -0
  293. package/screenshots/truth/sticky-note/gray-color.png +0 -0
  294. package/screenshots/truth/sticky-note/gray.png +0 -0
  295. package/screenshots/truth/sticky-note/green-color.png +0 -0
  296. package/screenshots/truth/sticky-note/green.png +0 -0
  297. package/screenshots/truth/sticky-note/pink-color.png +0 -0
  298. package/screenshots/truth/sticky-note/pink.png +0 -0
  299. package/screenshots/truth/sticky-note/yellow-color.png +0 -0
  300. package/screenshots/truth/sticky-note/yellow.png +0 -0
  301. package/src/{charcount → display}/CharCount.ts +164 -2
  302. package/src/{vectoricon/VectorIcon.ts → display/Icon.ts} +1 -1
  303. package/src/{leafletmap → display}/LeafletMap.ts +19 -1
  304. package/src/{thumbnail → display}/Thumbnail.ts +1 -1
  305. package/src/{tip → display}/Tip.ts +1 -2
  306. package/src/{contacts/events.ts → events.ts} +1 -64
  307. package/src/flow/Editor.ts +655 -165
  308. package/src/flow/EditorNode.ts +337 -22
  309. package/src/flow/Plumber.ts +186 -79
  310. package/src/flow/StickyNote.ts +165 -9
  311. package/src/flow/config.ts +114 -18
  312. package/src/flow/render.ts +398 -11
  313. package/src/{checkbox → form}/Checkbox.ts +2 -2
  314. package/src/{colorpicker → form}/ColorPicker.ts +2 -2
  315. package/src/{completion → form}/Completion.ts +3 -3
  316. package/src/{compose → form}/Compose.ts +7 -7
  317. package/src/{contactsearch → form}/ContactSearch.ts +6 -6
  318. package/src/{datepicker → form}/DatePicker.ts +1 -1
  319. package/src/{FormElement.ts → form/FormElement.ts} +1 -1
  320. package/src/{imagepicker → form}/ImagePicker.ts +2 -2
  321. package/src/{mediapicker → form}/MediaPicker.ts +1 -1
  322. package/src/{datepicker → form}/RangePicker.ts +3 -2
  323. package/src/{slider → form}/TembaSlider.ts +1 -1
  324. package/src/{templates → form}/TemplateEditor.ts +2 -2
  325. package/src/{textinput → form}/TextInput.ts +5 -5
  326. package/src/{omnibox → form/select}/Omnibox.ts +2 -2
  327. package/src/{select → form/select}/PopupSelect.ts +1 -1
  328. package/src/{select → form/select}/Select.ts +124 -126
  329. package/src/{select → form/select}/UserSelect.ts +1 -1
  330. package/src/{select → form/select}/WorkspaceSelect.ts +1 -1
  331. package/src/interfaces.ts +2 -1
  332. package/src/{dialog → layout}/Dialog.ts +1 -1
  333. package/src/list/NotificationList.ts +2 -2
  334. package/src/list/RunList.ts +3 -3
  335. package/src/list/ShortcutList.ts +1 -1
  336. package/src/list/TembaMenu.ts +2 -2
  337. package/src/list/TicketList.ts +1 -1
  338. package/src/{aliaseditor → live}/AliasEditor.ts +3 -3
  339. package/src/{contacts → live}/ContactBadges.ts +1 -1
  340. package/src/{contacts → live}/ContactChat.ts +118 -8
  341. package/src/{contacts → live}/ContactDetails.ts +1 -1
  342. package/src/{contacts → live}/ContactFieldEditor.ts +4 -4
  343. package/src/{contacts → live}/ContactFields.ts +1 -1
  344. package/src/{contacts → live}/ContactNotepad.ts +1 -1
  345. package/src/{contacts → live}/ContactPending.ts +1 -1
  346. package/src/{chart → live}/TembaChart.ts +5 -2
  347. package/src/locales/es.ts +13 -18
  348. package/src/locales/fr.ts +13 -18
  349. package/src/locales/locale-codes.ts +2 -11
  350. package/src/locales/pt.ts +13 -18
  351. package/src/store/AppState.ts +75 -29
  352. package/src/store/Store.ts +1 -1
  353. package/src/store/flow-definition.d.ts +125 -0
  354. package/src/{utils/index.ts → utils.ts} +26 -10
  355. package/src/webchat/WebChat.ts +1 -1
  356. package/static/css/temba-components.css +1 -0
  357. package/svg.js +1 -4
  358. package/temba-components.ts +2 -2
  359. package/temba-modules.ts +54 -54
  360. package/temba-webchat.ts +2 -2
  361. package/test/temba-alert.test.ts +1 -1
  362. package/test/temba-appstate-language.test.ts +108 -0
  363. package/test/temba-charcount.test.ts +1 -1
  364. package/test/temba-chart.test.ts +1 -1
  365. package/test/temba-checkbox.test.ts +1 -1
  366. package/test/temba-color-picker.test.ts +1 -1
  367. package/test/temba-completion.test.ts +1 -1
  368. package/test/temba-compose.test.ts +1 -1
  369. package/test/temba-contact-badges.test.ts +1 -1
  370. package/test/temba-contact-chat.test.ts +6 -4
  371. package/test/temba-contact-details.test.ts +1 -1
  372. package/test/temba-contact-fields.test.ts +1 -1
  373. package/test/temba-contact-search.test.ts +2 -2
  374. package/test/temba-date.test.ts +8 -3
  375. package/test/temba-datepicker.test.ts +1 -1
  376. package/test/temba-dialog.test.ts +1 -1
  377. package/test/temba-dropdown.test.ts +1 -1
  378. package/test/temba-excellent-helpers.test.ts +417 -0
  379. package/test/temba-field-manager.test.ts +2 -2
  380. package/test/temba-flow-editor-node.test.ts +536 -1
  381. package/test/temba-flow-editor.test.ts +224 -0
  382. package/test/temba-flow-editor.test.ts.backup +563 -0
  383. package/test/temba-flow-plumber-connections.test.ts +142 -0
  384. package/test/temba-flow-plumber.test.ts +83 -120
  385. package/test/temba-flow-render.test.ts +787 -4
  386. package/test/temba-flow-self-routing.test.ts +215 -0
  387. package/test/temba-formfield.test.ts +1 -1
  388. package/test/temba-icon.test.ts +1 -1
  389. package/test/temba-integration-markdown.test.ts +1 -1
  390. package/test/temba-label.test.ts +1 -1
  391. package/test/temba-lightbox.test.ts +1 -1
  392. package/test/temba-markdown.test.ts +162 -0
  393. package/test/temba-menu.test.ts +1 -1
  394. package/test/temba-modax.test.ts +2 -2
  395. package/test/temba-modules.test.ts +56 -0
  396. package/test/temba-omnibox.test.ts +1 -1
  397. package/test/temba-options.test.ts +1 -1
  398. package/test/temba-range-picker.test.ts +17 -2
  399. package/test/temba-rapid-element.test.ts +341 -0
  400. package/test/temba-resize-element.test.ts +104 -0
  401. package/test/temba-select.test.ts +2 -2
  402. package/test/temba-slider.test.ts +1 -1
  403. package/test/temba-sticky-note.test.ts +281 -0
  404. package/test/temba-template-editor.test.ts +1 -1
  405. package/test/temba-textinput.test.ts +1 -1
  406. package/test/temba-tip.test.ts +1 -1
  407. package/test/temba-toast.test.ts +1 -1
  408. package/test/temba-utils-index.test.ts +1 -1
  409. package/test/temba-utils-index.test.ts.backup +1737 -0
  410. package/test/temba-utils-uuid.test.ts +48 -0
  411. package/test/temba-webchat.test.ts +30 -12
  412. package/test/utils.test.ts +5 -9
  413. package/web-dev-server.config.mjs +1 -1
  414. package/demo/alert/example.html +0 -65
  415. package/demo/button/example.html +0 -71
  416. package/demo/chart/horizontal-demo.html +0 -81
  417. package/demo/checkbox/example.html +0 -72
  418. package/demo/compose/example.html +0 -72
  419. package/demo/dropdown/example.html +0 -99
  420. package/demo/progress/example.html +0 -59
  421. package/demo/select/drag-and-drop.html +0 -142
  422. package/demo/select/example.html +0 -82
  423. package/demo/select/multi.html +0 -73
  424. package/demo/slider/example.html +0 -59
  425. package/demo/tabs/example.html +0 -91
  426. package/demo/textinput/example.html +0 -61
  427. package/out-tsc/src/FormElement.js.map +0 -1
  428. package/out-tsc/src/alert/Alert.js.map +0 -1
  429. package/out-tsc/src/aliaseditor/AliasEditor.js.map +0 -1
  430. package/out-tsc/src/anchor/Anchor.js.map +0 -1
  431. package/out-tsc/src/button/Button.js.map +0 -1
  432. package/out-tsc/src/charcount/CharCount.js.map +0 -1
  433. package/out-tsc/src/charcount/helpers.js +0 -159
  434. package/out-tsc/src/charcount/helpers.js.map +0 -1
  435. package/out-tsc/src/chart/TembaChart.js.map +0 -1
  436. package/out-tsc/src/chat/Chat.js.map +0 -1
  437. package/out-tsc/src/checkbox/Checkbox.js.map +0 -1
  438. package/out-tsc/src/colorpicker/ColorPicker.js.map +0 -1
  439. package/out-tsc/src/completion/Completion.js.map +0 -1
  440. package/out-tsc/src/completion/ExcellentParser.js.map +0 -1
  441. package/out-tsc/src/completion/helpers.js.map +0 -1
  442. package/out-tsc/src/compose/Compose.js.map +0 -1
  443. package/out-tsc/src/contacts/ContactBadges.js.map +0 -1
  444. package/out-tsc/src/contacts/ContactChat.js.map +0 -1
  445. package/out-tsc/src/contacts/ContactDetails.js.map +0 -1
  446. package/out-tsc/src/contacts/ContactFieldEditor.js.map +0 -1
  447. package/out-tsc/src/contacts/ContactFields.js.map +0 -1
  448. package/out-tsc/src/contacts/ContactName.js.map +0 -1
  449. package/out-tsc/src/contacts/ContactNameFetch.js.map +0 -1
  450. package/out-tsc/src/contacts/ContactPending.js.map +0 -1
  451. package/out-tsc/src/contacts/ContactStoreElement.js.map +0 -1
  452. package/out-tsc/src/contacts/ContactUrn.js.map +0 -1
  453. package/out-tsc/src/contacts/events.js +0 -65
  454. package/out-tsc/src/contacts/events.js.map +0 -1
  455. package/out-tsc/src/contacts/helpers.js +0 -77
  456. package/out-tsc/src/contacts/helpers.js.map +0 -1
  457. package/out-tsc/src/contactsearch/ContactSearch.js.map +0 -1
  458. package/out-tsc/src/date/TembaDate.js.map +0 -1
  459. package/out-tsc/src/datepicker/DatePicker.js.map +0 -1
  460. package/out-tsc/src/datepicker/RangePicker.js.map +0 -1
  461. package/out-tsc/src/dialog/Dialog.js.map +0 -1
  462. package/out-tsc/src/dropdown/Dropdown.js.map +0 -1
  463. package/out-tsc/src/fields/FieldManager.js.map +0 -1
  464. package/out-tsc/src/formfield/FormField.js.map +0 -1
  465. package/out-tsc/src/imagepicker/CroppieCSS.js.map +0 -1
  466. package/out-tsc/src/imagepicker/ImagePicker.js.map +0 -1
  467. package/out-tsc/src/label/Label.js.map +0 -1
  468. package/out-tsc/src/leafletmap/LeafletMap.js.map +0 -1
  469. package/out-tsc/src/leafletmap/helpers.js +0 -17
  470. package/out-tsc/src/leafletmap/helpers.js.map +0 -1
  471. package/out-tsc/src/lightbox/Lightbox.js.map +0 -1
  472. package/out-tsc/src/mask/Mask.js.map +0 -1
  473. package/out-tsc/src/mediapicker/MediaPicker.js.map +0 -1
  474. package/out-tsc/src/omnibox/Omnibox.js.map +0 -1
  475. package/out-tsc/src/options/helpers.js +0 -28
  476. package/out-tsc/src/options/helpers.js.map +0 -1
  477. package/out-tsc/src/progress/ProgressBar.js.map +0 -1
  478. package/out-tsc/src/progress/StartProgress.js.map +0 -1
  479. package/out-tsc/src/resizer/Resizer.js.map +0 -1
  480. package/out-tsc/src/select/PopupSelect.js.map +0 -1
  481. package/out-tsc/src/select/Select.js.map +0 -1
  482. package/out-tsc/src/select/UserSelect.js.map +0 -1
  483. package/out-tsc/src/select/WorkspaceSelect.js.map +0 -1
  484. package/out-tsc/src/select/helpers.js +0 -1
  485. package/out-tsc/src/select/helpers.js.map +0 -1
  486. package/out-tsc/src/shadowless/Shadowless.js +0 -33
  487. package/out-tsc/src/shadowless/Shadowless.js.map +0 -1
  488. package/out-tsc/src/slider/TembaSlider.js.map +0 -1
  489. package/out-tsc/src/sms/gsmsplitter.js.map +0 -1
  490. package/out-tsc/src/sms/gsmvalidator.js.map +0 -1
  491. package/out-tsc/src/sms/index.js.map +0 -1
  492. package/out-tsc/src/sms/unicodesplitter.js.map +0 -1
  493. package/out-tsc/src/tabpane/Tab.js.map +0 -1
  494. package/out-tsc/src/tabpane/TabPane.js.map +0 -1
  495. package/out-tsc/src/templates/TemplateEditor.js.map +0 -1
  496. package/out-tsc/src/textinput/TextInput.js.map +0 -1
  497. package/out-tsc/src/textinput/helpers.js +0 -12
  498. package/out-tsc/src/textinput/helpers.js.map +0 -1
  499. package/out-tsc/src/thumbnail/Thumbnail.js.map +0 -1
  500. package/out-tsc/src/tip/Tip.js.map +0 -1
  501. package/out-tsc/src/tip/helpers.js +0 -7
  502. package/out-tsc/src/tip/helpers.js.map +0 -1
  503. package/out-tsc/src/toast/Toast.js.map +0 -1
  504. package/out-tsc/src/user/TembaUser.js.map +0 -1
  505. package/out-tsc/src/utils/index.js.map +0 -1
  506. package/out-tsc/src/vectoricon/VectorIcon.js.map +0 -1
  507. package/out-tsc/src/vectoricon/index.js.map +0 -1
  508. package/src/charcount/helpers.ts +0 -162
  509. package/src/contacts/helpers.ts +0 -103
  510. package/src/leafletmap/helpers.ts +0 -18
  511. package/src/options/helpers.ts +0 -37
  512. package/src/select/helpers.ts +0 -0
  513. package/src/shadowless/Shadowless.ts +0 -32
  514. package/src/textinput/helpers.ts +0 -11
  515. package/src/tip/helpers.ts +0 -7
  516. /package/out-tsc/src/{alert → display}/Alert.js +0 -0
  517. /package/out-tsc/src/{anchor → display}/Anchor.js +0 -0
  518. /package/out-tsc/src/{button → display}/Button.js +0 -0
  519. /package/out-tsc/src/{chat → display}/Chat.js +0 -0
  520. /package/out-tsc/src/{contacts → display}/ContactName.js +0 -0
  521. /package/out-tsc/src/{contacts → display}/ContactUrn.js +0 -0
  522. /package/out-tsc/src/{dropdown → display}/Dropdown.js +0 -0
  523. /package/out-tsc/src/{label → display}/Label.js +0 -0
  524. /package/out-tsc/src/{lightbox → display}/Lightbox.js +0 -0
  525. /package/out-tsc/src/{loading → display}/Loading.js +0 -0
  526. /package/out-tsc/src/{options → display}/Options.js +0 -0
  527. /package/out-tsc/src/{progress → display}/ProgressBar.js +0 -0
  528. /package/out-tsc/src/{date → display}/TembaDate.js +0 -0
  529. /package/out-tsc/src/{user → display}/TembaUser.js +0 -0
  530. /package/out-tsc/src/{thumbnail → display}/Thumbnail.js +0 -0
  531. /package/out-tsc/src/{toast → display}/Toast.js +0 -0
  532. /package/out-tsc/src/{sms → display/sms}/gsmsplitter.js +0 -0
  533. /package/out-tsc/src/{sms → display/sms}/gsmvalidator.js +0 -0
  534. /package/out-tsc/src/{sms → display/sms}/index.js +0 -0
  535. /package/out-tsc/src/{sms → display/sms}/unicodesplitter.js +0 -0
  536. /package/out-tsc/src/{completion → excellent}/ExcellentParser.js +0 -0
  537. /package/out-tsc/src/{completion → excellent}/helpers.js +0 -0
  538. /package/out-tsc/src/{imagepicker → form}/CroppieCSS.js +0 -0
  539. /package/out-tsc/src/{formfield → form}/FormField.js +0 -0
  540. /package/out-tsc/src/{dialog → layout}/Dialog.js +0 -0
  541. /package/out-tsc/src/{mask → layout}/Mask.js +0 -0
  542. /package/out-tsc/src/{dialog → layout}/Modax.js +0 -0
  543. /package/out-tsc/src/{resizer → layout}/Resizer.js +0 -0
  544. /package/out-tsc/src/{tabpane → layout}/Tab.js +0 -0
  545. /package/out-tsc/src/{tabpane → layout}/TabPane.js +0 -0
  546. /package/out-tsc/src/{contacts → live}/ContactFields.js +0 -0
  547. /package/out-tsc/src/{contacts → live}/ContactNameFetch.js +0 -0
  548. /package/out-tsc/src/{contacts → live}/ContactStoreElement.js +0 -0
  549. /package/out-tsc/src/{fields → live}/FieldManager.js +0 -0
  550. /package/out-tsc/src/{progress → live}/StartProgress.js +0 -0
  551. /package/src/{vectoricon/index.ts → Icons.ts} +0 -0
  552. /package/src/{alert → display}/Alert.ts +0 -0
  553. /package/src/{anchor → display}/Anchor.ts +0 -0
  554. /package/src/{button → display}/Button.ts +0 -0
  555. /package/src/{chat → display}/Chat.ts +0 -0
  556. /package/src/{contacts → display}/ContactName.ts +0 -0
  557. /package/src/{contacts → display}/ContactUrn.ts +0 -0
  558. /package/src/{dropdown → display}/Dropdown.ts +0 -0
  559. /package/src/{label → display}/Label.ts +0 -0
  560. /package/src/{lightbox → display}/Lightbox.ts +0 -0
  561. /package/src/{loading → display}/Loading.ts +0 -0
  562. /package/src/{options → display}/Options.ts +0 -0
  563. /package/src/{progress → display}/ProgressBar.ts +0 -0
  564. /package/src/{date → display}/TembaDate.ts +0 -0
  565. /package/src/{user → display}/TembaUser.ts +0 -0
  566. /package/src/{toast → display}/Toast.ts +0 -0
  567. /package/src/{sms → display/sms}/gsmsplitter.ts +0 -0
  568. /package/src/{sms → display/sms}/gsmvalidator.ts +0 -0
  569. /package/src/{sms → display/sms}/index.ts +0 -0
  570. /package/src/{sms → display/sms}/unicodesplitter.ts +0 -0
  571. /package/src/{completion → excellent}/ExcellentParser.ts +0 -0
  572. /package/src/{completion → excellent}/helpers.ts +0 -0
  573. /package/src/{imagepicker → form}/CroppieCSS.ts +0 -0
  574. /package/src/{formfield → form}/FormField.ts +0 -0
  575. /package/src/{mask → layout}/Mask.ts +0 -0
  576. /package/src/{dialog → layout}/Modax.ts +0 -0
  577. /package/src/{resizer → layout}/Resizer.ts +0 -0
  578. /package/src/{tabpane → layout}/Tab.ts +0 -0
  579. /package/src/{tabpane → layout}/TabPane.ts +0 -0
  580. /package/src/{contacts → live}/ContactNameFetch.ts +0 -0
  581. /package/src/{contacts → live}/ContactStoreElement.ts +0 -0
  582. /package/src/{fields → live}/FieldManager.ts +0 -0
  583. /package/src/{progress → live}/StartProgress.ts +0 -0
@@ -3,24 +3,52 @@ import {
3
3
  FlowchartConnector,
4
4
  newInstance,
5
5
  ready,
6
- RectangleEndpoint
6
+ RectangleEndpoint,
7
+ EVENT_CONNECTION_DRAG,
8
+ EVENT_CONNECTION_ABORT,
9
+ INTERCEPT_BEFORE_DROP,
10
+ EVENT_CONNECTION,
11
+ EVENT_REVERT,
12
+ INTERCEPT_BEFORE_DETACH,
13
+ EVENT_CONNECTION_DETACHED
7
14
  } from '@jsplumb/browser-ui';
8
15
 
16
+ const CONNECTOR_DEFAULTS = {
17
+ type: FlowchartConnector.type,
18
+ options: {
19
+ stub: [20, 10],
20
+ midpoint: 0.5,
21
+ alwaysRespectStubs: true,
22
+ cornerRadius: 5,
23
+ cssClass: 'plumb-connector'
24
+ }
25
+ };
26
+
27
+ const OVERLAYS_DEFAULTS = [
28
+ {
29
+ type: 'PlainArrow',
30
+ options: {
31
+ width: 13,
32
+ length: 13,
33
+ location: 0.999,
34
+ cssClass: 'plumb-arrow'
35
+ }
36
+ }
37
+ ];
38
+
9
39
  export const SOURCE_DEFAULTS = {
10
40
  endpoint: {
11
41
  type: DotEndpoint.type,
12
42
  options: {
13
- radius: 6,
14
- connectedClass: 'plumb-connected',
43
+ radius: 12,
15
44
  cssClass: 'plumb-source',
16
45
  hoverClass: 'plumb-source-hover'
17
46
  }
18
47
  },
19
48
  anchors: ['Bottom', 'Continuous'],
20
49
  maxConnections: 1,
21
- dragAllowedWhenFull: false,
22
- deleteEndpointsOnEmpty: true,
23
- isSource: true
50
+ source: true,
51
+ dragAllowedWhenFull: false
24
52
  };
25
53
 
26
54
  export const TARGET_DEFAULTS = {
@@ -40,23 +68,85 @@ export const TARGET_DEFAULTS = {
40
68
  cssClass: 'continuos plumb-target-anchor'
41
69
  }
42
70
  },
43
- dragAllowedWhenFull: false,
44
- deleteEndpointsOnEmpty: true,
45
- isTarget: true
71
+ deleteOnEmpty: true,
72
+ maxConnections: 1,
73
+ target: true
46
74
  };
47
75
 
48
76
  export class Plumber {
49
77
  private jsPlumb = null;
50
78
  private pendingConnections = [];
79
+ private connectionListeners = new Map();
80
+ public connectionDragging = false;
81
+ private connectionWait = null;
51
82
 
52
83
  constructor(canvas: HTMLElement) {
53
84
  ready(() => {
54
85
  this.jsPlumb = newInstance({
55
- container: canvas
86
+ container: canvas,
87
+ connectionsDetachable: true,
88
+ endpointStyle: {
89
+ fill: 'green'
90
+ },
91
+ connector: CONNECTOR_DEFAULTS,
92
+ connectionOverlays: OVERLAYS_DEFAULTS
93
+ });
94
+
95
+ // Bind to connection events
96
+ this.jsPlumb.bind(EVENT_CONNECTION, (info) => {
97
+ this.connectionDragging = false;
98
+ this.notifyListeners(EVENT_CONNECTION, info);
99
+ });
100
+
101
+ // Bind to connection drag events
102
+ this.jsPlumb.bind(EVENT_CONNECTION_DRAG, (info) => {
103
+ this.connectionDragging = true;
104
+ this.notifyListeners(EVENT_CONNECTION_DRAG, info);
105
+ });
106
+
107
+ this.jsPlumb.bind(EVENT_CONNECTION_ABORT, (info) => {
108
+ this.connectionDragging = false;
109
+ this.notifyListeners(EVENT_CONNECTION_ABORT, info);
56
110
  });
111
+
112
+ this.jsPlumb.bind(EVENT_CONNECTION_DETACHED, (info) => {
113
+ this.connectionDragging = false;
114
+ this.notifyListeners(EVENT_CONNECTION_DETACHED, info);
115
+ });
116
+
117
+ this.jsPlumb.bind(EVENT_REVERT, (info) => {
118
+ this.notifyListeners(EVENT_REVERT, info);
119
+ });
120
+
121
+ this.jsPlumb.bind(INTERCEPT_BEFORE_DROP, () => {
122
+ // we always deny automatic connections
123
+ return false;
124
+ });
125
+ this.jsPlumb.bind(INTERCEPT_BEFORE_DETACH, () => {});
57
126
  });
58
127
  }
59
128
 
129
+ private notifyListeners(eventName: string, info: any) {
130
+ const listeners = this.connectionListeners.get(eventName) || [];
131
+ listeners.forEach((listener) => listener(info));
132
+ }
133
+
134
+ public on(eventName: string, callback: (info: any) => void) {
135
+ if (!this.connectionListeners.has(eventName)) {
136
+ this.connectionListeners.set(eventName, []);
137
+ }
138
+ this.connectionListeners.get(eventName).push(callback);
139
+ }
140
+
141
+ public off(eventName: string, callback: (info: any) => void) {
142
+ if (!this.connectionListeners.has(eventName)) return;
143
+ const listeners = this.connectionListeners.get(eventName);
144
+ const index = listeners.indexOf(callback);
145
+ if (index !== -1) {
146
+ listeners.splice(index, 1);
147
+ }
148
+ }
149
+
60
150
  public makeTarget(uuid: string) {
61
151
  const element = document.getElementById(uuid);
62
152
  this.jsPlumb.addEndpoint(element, TARGET_DEFAULTS);
@@ -67,8 +157,6 @@ export class Plumber {
67
157
  this.jsPlumb.addEndpoint(element, SOURCE_DEFAULTS);
68
158
  }
69
159
 
70
- private connectionWait = null;
71
-
72
160
  // we'll process our pending connections, but we want to debounce this
73
161
  public processPendingConnections() {
74
162
  // if we have a pending connection wait, clear it
@@ -81,10 +169,13 @@ export class Plumber {
81
169
  this.connectionWait = setTimeout(() => {
82
170
  this.jsPlumb.batch(() => {
83
171
  this.pendingConnections.forEach((connection) => {
84
- const { fromId, toId } = connection;
172
+ const { scope, fromId, toId } = connection;
85
173
  const fromElement = document.getElementById(fromId);
86
174
  const toElement = document.getElementById(toId);
87
175
 
176
+ // delete any existing endpoints
177
+ this.jsPlumb.selectEndpoints({ source: fromId }).deleteAll();
178
+
88
179
  const source = this.jsPlumb.addEndpoint(fromElement, {
89
180
  ...SOURCE_DEFAULTS,
90
181
  endpoint: {
@@ -95,32 +186,18 @@ export class Plumber {
95
186
  }
96
187
  }
97
188
  });
189
+
98
190
  const target = this.jsPlumb.addEndpoint(toElement, TARGET_DEFAULTS);
99
191
  this.jsPlumb.connect({
100
192
  source,
101
193
  target,
102
194
  connector: {
103
- type: FlowchartConnector.type,
104
- options: {
105
- stub: 12,
106
- midpoint: 0.75,
107
- alwaysRespectStubs: false,
108
- gap: [0, 5],
109
- cornerRadius: 3,
110
- cssClass: 'plumb-connector'
111
- }
195
+ ...CONNECTOR_DEFAULTS,
196
+ options: { ...CONNECTOR_DEFAULTS.options, gap: [0, 5] }
112
197
  },
113
- overlays: [
114
- {
115
- type: 'PlainArrow',
116
- options: {
117
- width: 13,
118
- length: 13,
119
- location: 0.999,
120
- cssClass: 'plumb-arrow'
121
- }
122
- }
123
- ]
198
+ data: {
199
+ nodeId: scope
200
+ }
124
201
  });
125
202
  });
126
203
  this.pendingConnections = [];
@@ -128,8 +205,8 @@ export class Plumber {
128
205
  }, 50);
129
206
  }
130
207
 
131
- public connectIds(fromId: string, toId: string) {
132
- this.pendingConnections.push({ fromId, toId });
208
+ public connectIds(scope: string, fromId: string, toId: string) {
209
+ this.pendingConnections.push({ scope, fromId, toId });
133
210
  this.processPendingConnections();
134
211
  }
135
212
 
@@ -138,63 +215,93 @@ export class Plumber {
138
215
  this.jsPlumb.repaintEverything();
139
216
  }
140
217
  }
141
- public elevateNodeConnections(nodeId: string) {
218
+
219
+ public revalidate(ids: string[]) {
142
220
  if (!this.jsPlumb) return;
221
+ this.jsPlumb.batch(() => {
222
+ ids.forEach((id) => {
223
+ const element = document.getElementById(id);
224
+ if (element) {
225
+ this.jsPlumb.revalidate(element);
226
+ }
227
+ });
228
+ });
229
+ }
143
230
 
144
- // Get all connections
145
- const connections = this.jsPlumb.getConnections();
231
+ public removeNodeConnections(nodeId: string) {
232
+ if (!this.jsPlumb) return;
146
233
 
147
- // Get the node element to find its exit elements
148
- const nodeElement = document.getElementById(nodeId);
149
- const exitElements = nodeElement
150
- ? nodeElement.querySelectorAll('.exit')
151
- : [];
152
- const exitIds = Array.from(exitElements).map((exit) => exit.id);
234
+ const inbound = this.jsPlumb.select({ target: nodeId });
153
235
 
154
- connections.forEach((connection) => {
155
- const sourceId = connection.source.id;
156
- const targetId = connection.target.id;
157
-
158
- // Check if this connection involves the dragged node:
159
- // - Incoming: target is the node itself
160
- // - Outgoing: source is one of the node's exits
161
- if (targetId === nodeId || exitIds.includes(sourceId)) {
162
- // Add elevated class to the connector element
163
- const connectorElement = connection.connector.canvas;
164
- if (connectorElement) {
165
- connectorElement.classList.add('elevated');
166
- }
167
- }
236
+ // keep track of our source ids that are connected, we'll need new endpoints
237
+ const sourceIds = inbound.map((connection) => connection.sourceId);
238
+
239
+ const exitIds =
240
+ Array.from(
241
+ document.getElementById(nodeId)?.querySelectorAll('.exit') || []
242
+ ).map((exit) => {
243
+ return exit.id;
244
+ }) || [];
245
+
246
+ inbound.deleteAll();
247
+ this.jsPlumb.select({ source: exitIds }).deleteAll();
248
+ this.jsPlumb.selectEndpoints({ source: exitIds }).deleteAll();
249
+
250
+ // Recreate source endpoints for each source
251
+ sourceIds.forEach((exitId) => {
252
+ this.makeSource(exitId);
168
253
  });
169
254
  }
170
255
 
171
- public restoreNodeConnections(nodeId: string) {
256
+ public removeExitConnection(exitId: string) {
172
257
  if (!this.jsPlumb) return;
173
258
 
174
- // Get all connections
175
- const connections = this.jsPlumb.getConnections();
259
+ const exitElement = document.getElementById(exitId);
260
+ if (!exitElement) return;
176
261
 
177
- // Get the node element to find its exit elements
178
- const nodeElement = document.getElementById(nodeId);
179
- const exitElements = nodeElement
180
- ? nodeElement.querySelectorAll('.exit')
181
- : [];
182
- const exitIds = Array.from(exitElements).map((exit) => exit.id);
262
+ // Get all connections from this exit
263
+ const connections = this.jsPlumb.getConnections({ source: exitElement });
183
264
 
265
+ // Remove the connections
184
266
  connections.forEach((connection) => {
185
- const sourceId = connection.source.id;
186
- const targetId = connection.target.id;
187
-
188
- // Check if this connection involves the node:
189
- // - Incoming: target is the node itself
190
- // - Outgoing: source is one of the node's exits
191
- if (targetId === nodeId || exitIds.includes(sourceId)) {
192
- // Remove elevated class from the connector element
193
- const connectorElement = connection.connector.canvas;
194
- if (connectorElement) {
195
- connectorElement.classList.remove('elevated');
196
- }
267
+ this.jsPlumb.deleteConnection(connection);
268
+ });
269
+
270
+ // Re-create the source endpoint (now without connection)
271
+ this.jsPlumb.removeAllEndpoints(exitElement);
272
+ this.makeSource(exitId);
273
+
274
+ return connections.length > 0;
275
+ }
276
+
277
+ /**
278
+ * Set the removing state for an exit's connection
279
+ * @param exitId The ID of the exit whose connections should be marked as removing
280
+ * @returns true if connections were found and updated, false otherwise
281
+ */
282
+ public setConnectionRemovingState(
283
+ exitId: string,
284
+ isRemoving: boolean
285
+ ): boolean {
286
+ if (!this.jsPlumb) return false;
287
+
288
+ const exitElement = document.getElementById(exitId);
289
+ if (!exitElement) return false;
290
+
291
+ // Get all connections from this exit
292
+ const connections = this.jsPlumb.getConnections({ source: exitElement });
293
+
294
+ if (connections.length === 0) return false;
295
+
296
+ // Update the connections' CSS classes
297
+ connections.forEach((connection) => {
298
+ if (isRemoving) {
299
+ connection.addClass('removing');
300
+ } else {
301
+ connection.removeClass('removing');
197
302
  }
198
303
  });
304
+
305
+ return true;
199
306
  }
200
307
  }
@@ -14,6 +14,12 @@ export class StickyNote extends RapidElement {
14
14
  @property({ type: Boolean })
15
15
  private dragging = false;
16
16
 
17
+ @property({ type: Boolean })
18
+ public selected = false;
19
+
20
+ @property({ type: Boolean })
21
+ private colorPickerExpanded = false;
22
+
17
23
  static get styles() {
18
24
  return css`
19
25
  :host {
@@ -35,10 +41,11 @@ export class StickyNote extends RapidElement {
35
41
  overflow: hidden;
36
42
  transition: transform 0.1s ease, box-shadow 0.2s ease;
37
43
  color: var(--sticky-text-color);
44
+ opacity: 0.85;
38
45
  }
39
46
 
40
47
  .sticky-note.dragging {
41
- opacity: 0.5;
48
+ opacity: 0.7;
42
49
  z-index: 1000;
43
50
  transform: rotate(0deg);
44
51
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
@@ -147,20 +154,16 @@ export class StickyNote extends RapidElement {
147
154
  .sticky-title-container > .drag-handle {
148
155
  --icon-color: var(--sticky-border-color);
149
156
  cursor: move;
150
- max-width: 0px;
157
+ max-width: 20px;
158
+ padding-left: 8px;
151
159
  overflow: hidden;
152
160
  transition: all 0.2s ease;
153
- padding-left: 0;
154
161
  }
155
162
 
156
163
  .sticky-note:hover .drag-handle {
157
- max-width: 20px;
158
- padding-left: 8px;
159
164
  }
160
165
 
161
166
  .sticky-note:focus-within .sticky-title-container > .drag-handle {
162
- max-width: 0px;
163
- padding-left: 0px;
164
167
  }
165
168
 
166
169
  /* Focus/active states */
@@ -171,6 +174,83 @@ export class StickyNote extends RapidElement {
171
174
 
172
175
  .sticky-note:focus-within .drag-handle {
173
176
  max-width: 0px;
177
+ padding-left: 0px;
178
+ }
179
+
180
+ /* Color picker */
181
+ .color-picker {
182
+ position: absolute;
183
+ bottom: 4px;
184
+ right: 4px;
185
+ width: 8px;
186
+ height: 8px;
187
+ border: 1px solid rgba(0, 0, 0, 0.2);
188
+
189
+ border-radius: 3px;
190
+ background-color: var(--sticky-color);
191
+ cursor: pointer;
192
+ transition: transform 0.2s ease;
193
+ }
194
+
195
+ .color-picker:hover {
196
+ transform: scale(1.1);
197
+ }
198
+
199
+ .color-options {
200
+ position: absolute;
201
+ bottom: 0;
202
+ right: 0;
203
+ display: flex;
204
+ gap: 4px;
205
+ background-color: rgba(255, 255, 255, 0.9);
206
+ border: 1px solid #ccc;
207
+ border-radius: 6px;
208
+ padding: 3px;
209
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
210
+ transform-origin: bottom right;
211
+ transform: scale(0);
212
+ opacity: 0;
213
+ transition: transform 0.2s ease, opacity 0.2s ease;
214
+ z-index: 1000;
215
+ }
216
+
217
+ .color-options.expanded {
218
+ transform: scale(1);
219
+ opacity: 1;
220
+ }
221
+
222
+ .color-option {
223
+ width: 12px;
224
+ height: 12px;
225
+ border: 1px solid rgba(0, 0, 0, 0.2);
226
+ border-radius: 3px;
227
+ cursor: pointer;
228
+ transition: transform 0.15s ease, border-color 0.15s ease;
229
+ }
230
+
231
+ .color-option:hover {
232
+ transform: scale(1.1);
233
+ border-color: rgba(0, 0, 0, 0.4);
234
+ }
235
+
236
+ .color-option.yellow {
237
+ background-color: #fef08a;
238
+ }
239
+
240
+ .color-option.blue {
241
+ background-color: #bfdbfe;
242
+ }
243
+
244
+ .color-option.pink {
245
+ background-color: #fce7f3;
246
+ }
247
+
248
+ .color-option.green {
249
+ background-color: #d1fae5;
250
+ }
251
+
252
+ .color-option.gray {
253
+ background-color: #f3f4f6;
174
254
  }
175
255
  `;
176
256
  }
@@ -231,6 +311,16 @@ export class StickyNote extends RapidElement {
231
311
  this.requestUpdate();
232
312
  }
233
313
 
314
+ private handleContentMouseDown(event: MouseEvent): void {
315
+ // If this sticky note is selected, don't stop propagation
316
+ // so that group dragging can work
317
+ if (this.selected) {
318
+ return;
319
+ }
320
+ // Otherwise, stop propagation to enable editing
321
+ event.stopPropagation();
322
+ }
323
+
234
324
  private handleKeyDown(event: KeyboardEvent): void {
235
325
  if (event.key === 'Enter' && !event.shiftKey) {
236
326
  event.preventDefault();
@@ -241,6 +331,33 @@ export class StickyNote extends RapidElement {
241
331
  }
242
332
  }
243
333
 
334
+ private handleColorPickerMouseEnter(): void {
335
+ this.colorPickerExpanded = true;
336
+ }
337
+
338
+ private handleColorPickerMouseLeave(): void {
339
+ this.colorPickerExpanded = false;
340
+ }
341
+
342
+ private handleColorOptionClick(
343
+ event: MouseEvent,
344
+ color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'
345
+ ): void {
346
+ event.stopPropagation();
347
+
348
+ if (this.data && color !== this.data.color) {
349
+ getStore()
350
+ .getState()
351
+ .updateStickyNote(this.uuid, {
352
+ ...this.data,
353
+ color: color
354
+ });
355
+ }
356
+
357
+ this.colorPickerExpanded = false;
358
+ this.requestUpdate();
359
+ }
360
+
244
361
  public render(): TemplateResult {
245
362
  if (!this.data) {
246
363
  return html`<div class="sticky-note" style="display: none;"></div>`;
@@ -263,7 +380,7 @@ export class StickyNote extends RapidElement {
263
380
  contenteditable="true"
264
381
  @blur="${this.handleTitleBlur}"
265
382
  @keydown="${this.handleKeyDown}"
266
- @mousedown="${(e: MouseEvent) => e.stopPropagation()}"
383
+ @mousedown="${this.handleContentMouseDown}"
267
384
  .textContent="${this.data.title}"
268
385
  ></div>
269
386
  </div>
@@ -273,10 +390,49 @@ export class StickyNote extends RapidElement {
273
390
  contenteditable="true"
274
391
  @blur="${this.handleBodyBlur}"
275
392
  @keydown="${this.handleKeyDown}"
276
- @mousedown="${(e: MouseEvent) => e.stopPropagation()}"
393
+ @mousedown="${this.handleContentMouseDown}"
277
394
  .textContent="${this.data.body}"
278
395
  ></div>
279
396
  <div class="edit-icon" title="Edit note"></div>
397
+
398
+ <!-- Color picker -->
399
+ <div
400
+ class="color-picker"
401
+ @mouseenter="${this.handleColorPickerMouseEnter}"
402
+ @mouseleave="${this.handleColorPickerMouseLeave}"
403
+ >
404
+ <div
405
+ class="color-options ${this.colorPickerExpanded
406
+ ? 'expanded'
407
+ : ''}"
408
+ >
409
+ <div
410
+ class="color-option yellow"
411
+ @click="${(e: MouseEvent) =>
412
+ this.handleColorOptionClick(e, 'yellow')}"
413
+ ></div>
414
+ <div
415
+ class="color-option blue"
416
+ @click="${(e: MouseEvent) =>
417
+ this.handleColorOptionClick(e, 'blue')}"
418
+ ></div>
419
+ <div
420
+ class="color-option pink"
421
+ @click="${(e: MouseEvent) =>
422
+ this.handleColorOptionClick(e, 'pink')}"
423
+ ></div>
424
+ <div
425
+ class="color-option green"
426
+ @click="${(e: MouseEvent) =>
427
+ this.handleColorOptionClick(e, 'green')}"
428
+ ></div>
429
+ <div
430
+ class="color-option gray"
431
+ @click="${(e: MouseEvent) =>
432
+ this.handleColorOptionClick(e, 'gray')}"
433
+ ></div>
434
+ </div>
435
+ </div>
280
436
  </div>
281
437
  </div>
282
438
  `;