@nyaruka/temba-components 0.86.1 → 0.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/.eslintrc.js +3 -3
  2. package/.prettierrc +6 -0
  3. package/.storybook/main.js +3 -3
  4. package/.storybook/preview.js +2 -2
  5. package/CHANGELOG.md +24 -24
  6. package/CreateIncludesPlugin.js +2 -2
  7. package/demo/index.html +1 -0
  8. package/dist/locales/es.js +1 -1
  9. package/dist/locales/es.js.map +1 -1
  10. package/dist/locales/fr.js +1 -1
  11. package/dist/locales/fr.js.map +1 -1
  12. package/dist/locales/pt.js +1 -1
  13. package/dist/locales/pt.js.map +1 -1
  14. package/dist/temba-components.js +647 -535
  15. package/dist/temba-components.js.map +1 -1
  16. package/out-tsc/src/RapidElement.js +3 -3
  17. package/out-tsc/src/RapidElement.js.map +1 -1
  18. package/out-tsc/src/ResizeElement.js +2 -2
  19. package/out-tsc/src/ResizeElement.js.map +1 -1
  20. package/out-tsc/src/aliaseditor/AliasEditor.js +1 -1
  21. package/out-tsc/src/aliaseditor/AliasEditor.js.map +1 -1
  22. package/out-tsc/src/button/Button.js +1 -1
  23. package/out-tsc/src/button/Button.js.map +1 -1
  24. package/out-tsc/src/charcount/helpers.js +1 -1
  25. package/out-tsc/src/charcount/helpers.js.map +1 -1
  26. package/out-tsc/src/colorpicker/ColorPicker.js +4 -4
  27. package/out-tsc/src/colorpicker/ColorPicker.js.map +1 -1
  28. package/out-tsc/src/completion/Completion.js +2 -2
  29. package/out-tsc/src/completion/Completion.js.map +1 -1
  30. package/out-tsc/src/completion/ExcellentParser.js +1 -1
  31. package/out-tsc/src/completion/ExcellentParser.js.map +1 -1
  32. package/out-tsc/src/completion/helpers.js +8 -8
  33. package/out-tsc/src/completion/helpers.js.map +1 -1
  34. package/out-tsc/src/compose/Compose.js +14 -14
  35. package/out-tsc/src/compose/Compose.js.map +1 -1
  36. package/out-tsc/src/contacts/ContactBadges.js +2 -2
  37. package/out-tsc/src/contacts/ContactBadges.js.map +1 -1
  38. package/out-tsc/src/contacts/ContactChat.js +4 -4
  39. package/out-tsc/src/contacts/ContactChat.js.map +1 -1
  40. package/out-tsc/src/contacts/ContactDetails.js +4 -4
  41. package/out-tsc/src/contacts/ContactDetails.js.map +1 -1
  42. package/out-tsc/src/contacts/ContactFieldEditor.js +3 -3
  43. package/out-tsc/src/contacts/ContactFieldEditor.js.map +1 -1
  44. package/out-tsc/src/contacts/ContactFields.js +2 -2
  45. package/out-tsc/src/contacts/ContactFields.js.map +1 -1
  46. package/out-tsc/src/contacts/ContactHistory.js +21 -19
  47. package/out-tsc/src/contacts/ContactHistory.js.map +1 -1
  48. package/out-tsc/src/contacts/ContactPending.js +4 -4
  49. package/out-tsc/src/contacts/ContactPending.js.map +1 -1
  50. package/out-tsc/src/contacts/ContactTickets.js +8 -8
  51. package/out-tsc/src/contacts/ContactTickets.js.map +1 -1
  52. package/out-tsc/src/contacts/events.js +2 -2
  53. package/out-tsc/src/contacts/events.js.map +1 -1
  54. package/out-tsc/src/contacts/helpers.js +2 -2
  55. package/out-tsc/src/contacts/helpers.js.map +1 -1
  56. package/out-tsc/src/contactsearch/ContactSearch.js +7 -7
  57. package/out-tsc/src/contactsearch/ContactSearch.js.map +1 -1
  58. package/out-tsc/src/date/TembaDate.js +1 -1
  59. package/out-tsc/src/date/TembaDate.js.map +1 -1
  60. package/out-tsc/src/datepicker/DatePicker.js +1 -1
  61. package/out-tsc/src/datepicker/DatePicker.js.map +1 -1
  62. package/out-tsc/src/dialog/Dialog.js +5 -5
  63. package/out-tsc/src/dialog/Dialog.js.map +1 -1
  64. package/out-tsc/src/dialog/Modax.js +8 -8
  65. package/out-tsc/src/dialog/Modax.js.map +1 -1
  66. package/out-tsc/src/dropdown/Dropdown.js +1 -1
  67. package/out-tsc/src/dropdown/Dropdown.js.map +1 -1
  68. package/out-tsc/src/fields/FieldManager.js +6 -6
  69. package/out-tsc/src/fields/FieldManager.js.map +1 -1
  70. package/out-tsc/src/imagepicker/ImagePicker.js +4 -4
  71. package/out-tsc/src/imagepicker/ImagePicker.js.map +1 -1
  72. package/out-tsc/src/interfaces.js.map +1 -1
  73. package/out-tsc/src/label/Label.js +1 -1
  74. package/out-tsc/src/label/Label.js.map +1 -1
  75. package/out-tsc/src/leafletmap/LeafletMap.js +6 -6
  76. package/out-tsc/src/leafletmap/LeafletMap.js.map +1 -1
  77. package/out-tsc/src/leafletmap/helpers.js +2 -2
  78. package/out-tsc/src/leafletmap/helpers.js.map +1 -1
  79. package/out-tsc/src/lightbox/Lightbox.js +2 -2
  80. package/out-tsc/src/lightbox/Lightbox.js.map +1 -1
  81. package/out-tsc/src/list/ContentMenu.js +8 -8
  82. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  83. package/out-tsc/src/list/RunList.js +1 -1
  84. package/out-tsc/src/list/RunList.js.map +1 -1
  85. package/out-tsc/src/list/SortableList.js +6 -6
  86. package/out-tsc/src/list/SortableList.js.map +1 -1
  87. package/out-tsc/src/list/TembaList.js +9 -7
  88. package/out-tsc/src/list/TembaList.js.map +1 -1
  89. package/out-tsc/src/list/TembaMenu.js +22 -22
  90. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  91. package/out-tsc/src/loading/Loading.js +1 -1
  92. package/out-tsc/src/loading/Loading.js.map +1 -1
  93. package/out-tsc/src/locales/es.js +1 -1
  94. package/out-tsc/src/locales/es.js.map +1 -1
  95. package/out-tsc/src/locales/fr.js +1 -1
  96. package/out-tsc/src/locales/fr.js.map +1 -1
  97. package/out-tsc/src/locales/pt.js +1 -1
  98. package/out-tsc/src/locales/pt.js.map +1 -1
  99. package/out-tsc/src/omnibox/Omnibox.js +1 -1
  100. package/out-tsc/src/omnibox/Omnibox.js.map +1 -1
  101. package/out-tsc/src/options/Options.js +9 -9
  102. package/out-tsc/src/options/Options.js.map +1 -1
  103. package/out-tsc/src/remote/Remote.js +1 -1
  104. package/out-tsc/src/remote/Remote.js.map +1 -1
  105. package/out-tsc/src/select/Select.js +18 -18
  106. package/out-tsc/src/select/Select.js.map +1 -1
  107. package/out-tsc/src/sms/gsmsplitter.js +8 -8
  108. package/out-tsc/src/sms/gsmsplitter.js.map +1 -1
  109. package/out-tsc/src/sms/gsmvalidator.js +1 -1
  110. package/out-tsc/src/sms/gsmvalidator.js.map +1 -1
  111. package/out-tsc/src/sms/index.js +2 -2
  112. package/out-tsc/src/sms/index.js.map +1 -1
  113. package/out-tsc/src/sms/unicodesplitter.js +8 -8
  114. package/out-tsc/src/sms/unicodesplitter.js.map +1 -1
  115. package/out-tsc/src/store/Store.js +10 -10
  116. package/out-tsc/src/store/Store.js.map +1 -1
  117. package/out-tsc/src/store/StoreElement.js +2 -2
  118. package/out-tsc/src/store/StoreElement.js.map +1 -1
  119. package/out-tsc/src/tabpane/TabPane.js +4 -4
  120. package/out-tsc/src/tabpane/TabPane.js.map +1 -1
  121. package/out-tsc/src/templates/TemplateEditor.js +9 -9
  122. package/out-tsc/src/templates/TemplateEditor.js.map +1 -1
  123. package/out-tsc/src/textinput/TextInput.js +1 -1
  124. package/out-tsc/src/textinput/TextInput.js.map +1 -1
  125. package/out-tsc/src/thumbnail/Thumbnail.js +5 -5
  126. package/out-tsc/src/thumbnail/Thumbnail.js.map +1 -1
  127. package/out-tsc/src/tip/Tip.js +3 -3
  128. package/out-tsc/src/tip/Tip.js.map +1 -1
  129. package/out-tsc/src/toast/Toast.js +199 -0
  130. package/out-tsc/src/toast/Toast.js.map +1 -0
  131. package/out-tsc/src/utils/index.js +28 -21
  132. package/out-tsc/src/utils/index.js.map +1 -1
  133. package/out-tsc/src/vectoricon/VectorIcon.js +2 -2
  134. package/out-tsc/src/vectoricon/VectorIcon.js.map +1 -1
  135. package/out-tsc/src/vectoricon/index.js +1 -0
  136. package/out-tsc/src/vectoricon/index.js.map +1 -1
  137. package/out-tsc/src/webchat/WebChat.js +234 -81
  138. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  139. package/out-tsc/src/webchat/assets.js +2 -0
  140. package/out-tsc/src/webchat/assets.js.map +1 -0
  141. package/out-tsc/src/webchat/index.js.map +1 -1
  142. package/out-tsc/temba-modules.js +2 -0
  143. package/out-tsc/temba-modules.js.map +1 -1
  144. package/out-tsc/test/temba-alert.test.js +1 -1
  145. package/out-tsc/test/temba-alert.test.js.map +1 -1
  146. package/out-tsc/test/temba-checkbox.test.js.map +1 -1
  147. package/out-tsc/test/temba-color-picker.test.js +4 -4
  148. package/out-tsc/test/temba-color-picker.test.js.map +1 -1
  149. package/out-tsc/test/temba-compose.test.js +50 -54
  150. package/out-tsc/test/temba-compose.test.js.map +1 -1
  151. package/out-tsc/test/temba-contact-badges.test.js +2 -2
  152. package/out-tsc/test/temba-contact-badges.test.js.map +1 -1
  153. package/out-tsc/test/temba-contact-chat.test.js +25 -38
  154. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  155. package/out-tsc/test/temba-contact-details.test.js +2 -2
  156. package/out-tsc/test/temba-contact-details.test.js.map +1 -1
  157. package/out-tsc/test/temba-contact-fields.test.js +4 -4
  158. package/out-tsc/test/temba-contact-fields.test.js.map +1 -1
  159. package/out-tsc/test/temba-contact-history.test.js +3 -3
  160. package/out-tsc/test/temba-contact-history.test.js.map +1 -1
  161. package/out-tsc/test/temba-contact-search.test.js +7 -7
  162. package/out-tsc/test/temba-contact-search.test.js.map +1 -1
  163. package/out-tsc/test/temba-contact-tickets.test.js +3 -3
  164. package/out-tsc/test/temba-contact-tickets.test.js.map +1 -1
  165. package/out-tsc/test/temba-content-menu.test.js +7 -7
  166. package/out-tsc/test/temba-content-menu.test.js.map +1 -1
  167. package/out-tsc/test/temba-date.test.js +3 -3
  168. package/out-tsc/test/temba-date.test.js.map +1 -1
  169. package/out-tsc/test/temba-datepicker.test.js +1 -1
  170. package/out-tsc/test/temba-datepicker.test.js.map +1 -1
  171. package/out-tsc/test/temba-field-manager.test.js +1 -3
  172. package/out-tsc/test/temba-field-manager.test.js.map +1 -1
  173. package/out-tsc/test/temba-label.test.js +6 -6
  174. package/out-tsc/test/temba-label.test.js.map +1 -1
  175. package/out-tsc/test/temba-lightbox.test.js +2 -2
  176. package/out-tsc/test/temba-lightbox.test.js.map +1 -1
  177. package/out-tsc/test/temba-list.test.js +6 -6
  178. package/out-tsc/test/temba-list.test.js.map +1 -1
  179. package/out-tsc/test/temba-menu.test.js +4 -5
  180. package/out-tsc/test/temba-menu.test.js.map +1 -1
  181. package/out-tsc/test/temba-modax.test.js +3 -3
  182. package/out-tsc/test/temba-modax.test.js.map +1 -1
  183. package/out-tsc/test/temba-options.test.js +1 -1
  184. package/out-tsc/test/temba-options.test.js.map +1 -1
  185. package/out-tsc/test/temba-select.test.js +17 -17
  186. package/out-tsc/test/temba-select.test.js.map +1 -1
  187. package/out-tsc/test/temba-sortable-list.test.js +1 -1
  188. package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
  189. package/out-tsc/test/temba-textinput.test.js +2 -2
  190. package/out-tsc/test/temba-textinput.test.js.map +1 -1
  191. package/out-tsc/test/temba-tip.test.js +4 -4
  192. package/out-tsc/test/temba-tip.test.js.map +1 -1
  193. package/out-tsc/test/utils.test.js +8 -8
  194. package/out-tsc/test/utils.test.js.map +1 -1
  195. package/package.json +6 -15
  196. package/src/RapidElement.ts +3 -3
  197. package/src/ResizeElement.ts +2 -2
  198. package/src/aliaseditor/AliasEditor.ts +1 -2
  199. package/src/button/Button.ts +1 -1
  200. package/src/charcount/helpers.ts +1 -1
  201. package/src/colorpicker/ColorPicker.ts +4 -4
  202. package/src/completion/Completion.ts +2 -2
  203. package/src/completion/ExcellentParser.ts +1 -1
  204. package/src/completion/helpers.ts +9 -9
  205. package/src/compose/Compose.ts +18 -16
  206. package/src/contacts/ContactBadges.ts +2 -2
  207. package/src/contacts/ContactChat.ts +4 -4
  208. package/src/contacts/ContactDetails.ts +4 -4
  209. package/src/contacts/ContactFieldEditor.ts +4 -4
  210. package/src/contacts/ContactFields.ts +2 -2
  211. package/src/contacts/ContactHistory.ts +25 -22
  212. package/src/contacts/ContactPending.ts +4 -4
  213. package/src/contacts/ContactTickets.ts +9 -9
  214. package/src/contacts/events.ts +3 -3
  215. package/src/contacts/helpers.ts +2 -2
  216. package/src/contactsearch/ContactSearch.ts +9 -9
  217. package/src/date/TembaDate.ts +1 -1
  218. package/src/datepicker/DatePicker.ts +1 -1
  219. package/src/dialog/Dialog.ts +6 -6
  220. package/src/dialog/Modax.ts +8 -8
  221. package/src/dropdown/Dropdown.ts +1 -2
  222. package/src/emojis.json +1882 -1
  223. package/src/fields/FieldManager.ts +6 -7
  224. package/src/imagepicker/ImagePicker.ts +4 -4
  225. package/src/interfaces.ts +4 -4
  226. package/src/label/Label.ts +1 -1
  227. package/src/leafletmap/LeafletMap.ts +6 -6
  228. package/src/leafletmap/helpers.ts +2 -2
  229. package/src/lightbox/Lightbox.ts +2 -2
  230. package/src/list/ContentMenu.ts +9 -9
  231. package/src/list/RunList.ts +1 -1
  232. package/src/list/SortableList.ts +6 -6
  233. package/src/list/TembaList.ts +9 -7
  234. package/src/list/TembaMenu.ts +23 -23
  235. package/src/loading/Loading.ts +1 -1
  236. package/src/locales/es.ts +1 -1
  237. package/src/locales/fr.ts +1 -1
  238. package/src/locales/pt.ts +1 -1
  239. package/src/omnibox/Omnibox.ts +2 -2
  240. package/src/options/Options.ts +9 -9
  241. package/src/remote/Remote.ts +1 -1
  242. package/src/select/Select.ts +19 -19
  243. package/src/sms/gsmsplitter.ts +8 -8
  244. package/src/sms/gsmvalidator.ts +1 -1
  245. package/src/sms/index.ts +2 -2
  246. package/src/sms/unicodesplitter.ts +8 -8
  247. package/src/store/Store.ts +10 -10
  248. package/src/store/StoreElement.ts +2 -2
  249. package/src/tabpane/TabPane.ts +4 -4
  250. package/src/templates/TemplateEditor.ts +9 -9
  251. package/src/textinput/TextInput.ts +2 -2
  252. package/src/thumbnail/Thumbnail.ts +5 -5
  253. package/src/tip/Tip.ts +3 -3
  254. package/src/toast/Toast.ts +224 -0
  255. package/src/utils/index.ts +33 -24
  256. package/src/vectoricon/VectorIcon.ts +2 -2
  257. package/src/vectoricon/index.ts +2 -1
  258. package/src/webchat/WebChat.ts +272 -87
  259. package/src/webchat/assets.ts +2 -0
  260. package/src/webchat/index.ts +1 -1
  261. package/svg.js +28 -29
  262. package/temba-modules.ts +2 -0
  263. package/test/temba-alert.test.ts +1 -1
  264. package/test/temba-checkbox.test.ts +1 -1
  265. package/test/temba-color-picker.test.ts +4 -4
  266. package/test/temba-compose.test.ts +50 -55
  267. package/test/temba-contact-badges.test.ts +2 -2
  268. package/test/temba-contact-chat.test.ts +26 -46
  269. package/test/temba-contact-details.test.ts +2 -8
  270. package/test/temba-contact-fields.test.ts +4 -11
  271. package/test/temba-contact-history.test.ts +3 -3
  272. package/test/temba-contact-search.test.ts +7 -13
  273. package/test/temba-contact-tickets.test.ts +3 -3
  274. package/test/temba-content-menu.test.ts +7 -7
  275. package/test/temba-date.test.ts +3 -3
  276. package/test/temba-datepicker.test.ts +1 -1
  277. package/test/temba-field-manager.test.ts +1 -4
  278. package/test/temba-label.test.ts +6 -6
  279. package/test/temba-lightbox.test.ts +2 -2
  280. package/test/temba-list.test.ts +6 -6
  281. package/test/temba-menu.test.ts +4 -5
  282. package/test/temba-modax.test.ts +3 -3
  283. package/test/temba-options.test.ts +1 -1
  284. package/test/temba-select.test.ts +17 -17
  285. package/test/temba-sortable-list.test.ts +1 -1
  286. package/test/temba-textinput.test.ts +2 -2
  287. package/test/temba-tip.test.ts +5 -5
  288. package/test/utils.test.ts +8 -9
@@ -0,0 +1,224 @@
1
+ import { TemplateResult, css, html } from 'lit';
2
+ import { RapidElement } from '../RapidElement';
3
+ import { property } from 'lit/decorators.js';
4
+ import { repeat } from 'lit/directives/repeat.js';
5
+
6
+ interface ToastMessage {
7
+ id: number;
8
+ text: string;
9
+ level: 'info' | 'warning' | 'error';
10
+ visible?: boolean;
11
+ time: Date;
12
+ removeTime?: Date;
13
+ }
14
+
15
+ export class Toast extends RapidElement {
16
+ @property({ type: Array })
17
+ messages: ToastMessage[] = [];
18
+
19
+ @property({ type: Number, attribute: 'duration' })
20
+ staleDuration = 5000;
21
+
22
+ @property({ type: Number, attribute: 'animation' })
23
+ animationDuration = 200;
24
+
25
+ @property({ type: Boolean, attribute: 'error-sticky' })
26
+ errorSticky = false;
27
+
28
+ @property({ type: Boolean, attribute: 'warning-sticky' })
29
+ warningSticky = false;
30
+
31
+ @property({ type: Boolean, attribute: 'info-sticky' })
32
+ infoSticky = false;
33
+
34
+ static styles = css`
35
+ :host {
36
+ position: fixed;
37
+ width: 400px;
38
+ z-index: 10000;
39
+ right: 0;
40
+ }
41
+
42
+ .message {
43
+ background-color: rgba(50, 50, 50, 0.85);
44
+ background-color: rgba(255, 255, 255, 0.97);
45
+ color: rgba(0, 0, 0, 0.85);
46
+ padding: 0.5em 1em;
47
+ margin: 0.75em;
48
+ border-radius: 0.5em;
49
+ display: flex;
50
+ transition-property: transform, opacity;
51
+ transition-timing-function: ease-in-out;
52
+ transform: translateY(-100%);
53
+ opacity: 0;
54
+ box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 3em 2px;
55
+ border: 2px solid rgba(0, 0, 0, 0.3);
56
+ }
57
+
58
+ .message.visible {
59
+ transform: translateY(0);
60
+ opacity: 1;
61
+ }
62
+
63
+ .message.info {
64
+ }
65
+
66
+ .message.warning {
67
+ color: rgba(255, 167, 0, 0.9);
68
+ }
69
+
70
+ .message.error {
71
+ border-color: var(--color-error);
72
+ color: var(--color-error);
73
+ }
74
+
75
+ .message.removing {
76
+ opacity: 0;
77
+ transform: translateY(-100%);
78
+ }
79
+
80
+ temba-icon {
81
+ cursor: pointer;
82
+ padding-left: 1em;
83
+ opacity: 0;
84
+ transition: all 200ms ease-in-out;
85
+ }
86
+
87
+ .message:hover temba-icon {
88
+ opacity: 1;
89
+ }
90
+
91
+ temba-icon:hover {
92
+ transform: scale(1.3) translateX(-0.1em);
93
+ }
94
+
95
+ .message .text {
96
+ flex-grow: 1;
97
+ }
98
+
99
+ .info {
100
+ }
101
+ `;
102
+
103
+ public checkForStaleMessages() {
104
+ const now = new Date();
105
+
106
+ // ignore sticky messages
107
+ const staleMessages = this.messages.filter((message) => {
108
+ if (message.level === 'error' && this.errorSticky) {
109
+ return false;
110
+ }
111
+ if (message.level === 'warning' && this.warningSticky) {
112
+ return false;
113
+ }
114
+ if (message.level === 'info' && this.infoSticky) {
115
+ return false;
116
+ }
117
+ return true;
118
+ });
119
+
120
+ staleMessages.forEach((message) => {
121
+ // error messages do not remove themselves
122
+ if (now.getTime() - message.time.getTime() > this.staleDuration) {
123
+ this.removeMessage(message);
124
+ }
125
+ });
126
+
127
+ if (this.messages.length === 0 && this.checker) {
128
+ window.clearInterval(this.checker);
129
+ this.checker = 0;
130
+ }
131
+ }
132
+
133
+ private checker: number;
134
+ private messageId: number = 0;
135
+
136
+ public addMessages(messages: ToastMessage[]) {
137
+ messages.forEach((message) => {
138
+ this.addMessage(message.text, message.level);
139
+ });
140
+ }
141
+
142
+ public addMessage(text: string, level: 'info' | 'warning' | 'error') {
143
+ const message: ToastMessage = {
144
+ id: ++this.messageId,
145
+ text,
146
+ level,
147
+ time: new Date()
148
+ };
149
+ this.messages.push(message);
150
+
151
+ window.setTimeout(() => {
152
+ message.visible = true;
153
+ this.requestUpdate('messages');
154
+ }, 100);
155
+
156
+ this.requestUpdate('messages');
157
+
158
+ if (this.checker) {
159
+ window.clearInterval(this.checker);
160
+ this.checker = 0;
161
+ }
162
+
163
+ this.checker = window.setInterval(
164
+ this.checkForStaleMessages.bind(this),
165
+ 1000
166
+ );
167
+ }
168
+
169
+ public info(message: string) {
170
+ this.addMessage(message, 'info');
171
+ }
172
+
173
+ public warning(message: string) {
174
+ this.addMessage(message, 'warning');
175
+ }
176
+
177
+ public error(message: string) {
178
+ this.addMessage(message, 'error');
179
+ }
180
+
181
+ public removeMessage(message: ToastMessage) {
182
+ message.removeTime = new Date();
183
+ window.setTimeout(() => {
184
+ this.messages = this.messages.filter((m) => m !== message);
185
+ this.requestUpdate('messages');
186
+ }, this.animationDuration);
187
+
188
+ this.requestUpdate('messages');
189
+ }
190
+
191
+ private handleMessageClicked(e: MouseEvent) {
192
+ const ele = e.target as HTMLElement;
193
+ const id = parseInt(ele.getAttribute('message_id'));
194
+ const message = this.messages.find((m) => m.id === id);
195
+ if (message) {
196
+ this.removeMessage(message);
197
+ }
198
+ }
199
+
200
+ public render(): TemplateResult {
201
+ return html`
202
+ ${repeat(
203
+ this.messages,
204
+ (message) => message.id,
205
+ (message) => html`
206
+ <div
207
+ style="transition-duration: ${this.animationDuration}ms"
208
+ class="message ${message.level} ${message.visible
209
+ ? 'visible'
210
+ : ''} ${message.removeTime ? 'removing' : ''}"
211
+ >
212
+ <div class="text">${message.text}</div>
213
+ <temba-icon
214
+ name="close"
215
+ size="1.3"
216
+ message_id="${message.id}"
217
+ @click=${this.handleMessageClicked}
218
+ ></temba-icon>
219
+ </div>
220
+ `
221
+ )}
222
+ `;
223
+ }
224
+ }
@@ -4,6 +4,7 @@ import { Button } from '../button/Button';
4
4
  import { Dialog } from '../dialog/Dialog';
5
5
  import { Attachment, ContactField, Ticket, User } from '../interfaces';
6
6
  import ColorHash from 'color-hash';
7
+ import { Toast } from '../toast/Toast';
7
8
 
8
9
  export const DEFAULT_MEDIA_ENDPOINT = '/api/v2/media.json';
9
10
 
@@ -32,7 +33,7 @@ export enum Color {
32
33
  BLUE = 'color:#5078b5;',
33
34
  GREEN = 'color:#62bd6a;',
34
35
  RED = 'color:#e36049;',
35
- PURPLE = 'color:#a626a4;',
36
+ PURPLE = 'color:#a626a4;'
36
37
  }
37
38
 
38
39
  export const log = (message: string | object, styling = '', details = []) => {
@@ -73,7 +74,7 @@ export const getHeaders = (headers: any = {}) => {
73
74
  // mark us as ajax
74
75
  fetchHeaders['X-Requested-With'] = 'XMLHttpRequest';
75
76
 
76
- Object.keys(headers).forEach(key => {
77
+ Object.keys(headers).forEach((key) => {
77
78
  fetchHeaders[key] = headers[key];
78
79
  });
79
80
  return fetchHeaders;
@@ -87,7 +88,7 @@ export const getUrl = (
87
88
  return new Promise<WebResponse>((resolve, reject) => {
88
89
  const options = {
89
90
  method: 'GET',
90
- headers: getHeaders(headers),
91
+ headers: getHeaders(headers)
91
92
  };
92
93
 
93
94
  if (controller) {
@@ -95,7 +96,7 @@ export const getUrl = (
95
96
  }
96
97
 
97
98
  fetch(url, options)
98
- .then(response => {
99
+ .then((response) => {
99
100
  response.text().then((body: string) => {
100
101
  let json = {};
101
102
  try {
@@ -108,11 +109,11 @@ export const getUrl = (
108
109
  json,
109
110
  url: response.url,
110
111
  headers: response.headers,
111
- status: response.status,
112
+ status: response.status
112
113
  });
113
114
  });
114
115
  })
115
- .catch(error => {
116
+ .catch((error) => {
116
117
  reject(error);
117
118
  });
118
119
  });
@@ -146,16 +147,16 @@ export const fetchResultsPage = (
146
147
  .then((response: WebResponse) => {
147
148
  resolve({
148
149
  results: response.json.results,
149
- next: response.json.next,
150
+ next: response.json.next
150
151
  });
151
152
  })
152
- .catch(error => reject(error));
153
+ .catch((error) => reject(error));
153
154
  });
154
155
  };
155
156
 
156
157
  export const fetchResults = async (url: string): Promise<any[]> => {
157
158
  if (!url) {
158
- return new Promise<any[]>(resolve => resolve([]));
159
+ return new Promise<any[]>((resolve) => resolve([]));
159
160
  }
160
161
 
161
162
  let results: any[] = [];
@@ -177,19 +178,19 @@ export const getAssetPage = (url: string): Promise<AssetPage> => {
177
178
  if (response.status >= 200 && response.status < 300) {
178
179
  resolve({
179
180
  assets: response.json.results,
180
- next: response.json.next,
181
+ next: response.json.next
181
182
  });
182
183
  } else {
183
184
  reject(response);
184
185
  }
185
186
  })
186
- .catch(error => reject(error));
187
+ .catch((error) => reject(error));
187
188
  });
188
189
  };
189
190
 
190
191
  export const getAssets = async (url: string): Promise<Asset[]> => {
191
192
  if (!url) {
192
- return new Promise<Asset[]>(resolve => resolve([]));
193
+ return new Promise<Asset[]>((resolve) => resolve([]));
193
194
  }
194
195
 
195
196
  let assets: Asset[] = [];
@@ -231,17 +232,25 @@ export const postUrl = (
231
232
  const options = {
232
233
  method: 'POST',
233
234
  headers: fetchHeaders,
234
- body: payload,
235
+ body: payload
235
236
  };
236
237
 
237
238
  return new Promise<WebResponse>((resolve, reject) => {
238
239
  fetch(url, options)
239
- .then(async response => {
240
+ .then(async (response) => {
240
241
  if (response.status >= 500) {
241
242
  reject(response);
242
243
  return;
243
244
  }
244
245
 
246
+ const toasts = response.headers.get('x-temba-toasts');
247
+ if (toasts) {
248
+ const toastEle = document.querySelector('temba-toast') as Toast;
249
+ if (toastEle) {
250
+ toastEle.addMessages(JSON.parse(toasts));
251
+ }
252
+ }
253
+
245
254
  response.text().then((body: string) => {
246
255
  let json = {};
247
256
  try {
@@ -254,11 +263,11 @@ export const postUrl = (
254
263
  headers: response.headers,
255
264
  status: response.status,
256
265
  redirected: response.redirected,
257
- url: response.url,
266
+ url: response.url
258
267
  });
259
268
  });
260
269
  })
261
- .catch(error => {
270
+ .catch((error) => {
262
271
  reject(error);
263
272
  });
264
273
  });
@@ -275,7 +284,7 @@ export const postFormData = (
275
284
  ): Promise<WebResponse> => {
276
285
  return new Promise<WebResponse>((resolve, reject) => {
277
286
  postUrl(url, formData, headers)
278
- .then(response => {
287
+ .then((response) => {
279
288
  if (response.status >= 200 && response.status < 400) {
280
289
  resolve(response);
281
290
  } else {
@@ -286,7 +295,7 @@ export const postFormData = (
286
295
  }
287
296
  }
288
297
  })
289
- .catch(err => {
298
+ .catch((err) => {
290
299
  console.error(err);
291
300
  reject(err);
292
301
  });
@@ -319,7 +328,7 @@ export const hexToRgb = (hex: string): { r: number; g: number; b: number } => {
319
328
  ? {
320
329
  r: parseInt(result[1], 16),
321
330
  g: parseInt(result[2], 16),
322
- b: parseInt(result[3], 16),
331
+ b: parseInt(result[3], 16)
323
332
  }
324
333
  : null;
325
334
  };
@@ -343,7 +352,7 @@ export const getElementOffset = (
343
352
  bottom: rect.top + rect.height,
344
353
  right: rect.left + rect.width,
345
354
  width: rect.width,
346
- height: rect.height,
355
+ height: rect.height
347
356
  };
348
357
  };
349
358
 
@@ -474,7 +483,7 @@ export const stubbable = new Stubbable();
474
483
  export const timeSince = (
475
484
  date: Date,
476
485
  options: { compareDate?: Date; hideRecentText?: boolean; suffix?: string } = {
477
- suffix: '',
486
+ suffix: ''
478
487
  }
479
488
  ) => {
480
489
  const { compareDate, hideRecentText, suffix } = options;
@@ -653,7 +662,7 @@ export const getCookieBoolean = (name: string) => {
653
662
  export enum COOKIE_KEYS {
654
663
  SETTINGS = 'settings',
655
664
  MENU_COLLAPSED = 'menu-collapsed',
656
- TICKET_SHOW_DETAILS = 'tickets.show-details',
665
+ TICKET_SHOW_DETAILS = 'tickets.show-details'
657
666
  }
658
667
 
659
668
  export const capitalize = ([first, ...rest], locale = navigator.language) =>
@@ -717,7 +726,7 @@ export const extractInitials = (text: string) => {
717
726
  }
718
727
 
719
728
  // use initial letters of words with preference to first word and capital letters
720
- const firstLetters = words.map(w => w.substring(0, 1));
729
+ const firstLetters = words.map((w) => w.substring(0, 1));
721
730
  const firstCapitals = firstLetters.filter(
722
731
  (l, index) => l == l.toUpperCase() || index == 0
723
732
  );
@@ -731,7 +740,7 @@ export const extractInitials = (text: string) => {
731
740
  export const hslToHex = (h, s, l) => {
732
741
  l /= 100;
733
742
  const a = (s * Math.min(l, 1 - l)) / 100;
734
- const f = n => {
743
+ const f = (n) => {
735
744
  const k = (n + h / 30) % 12;
736
745
  const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
737
746
  return Math.round(255 * color)
@@ -228,7 +228,7 @@ export class VectorIcon extends LitElement {
228
228
  clickable: this.clickable,
229
229
  circled: this.circled,
230
230
  animate: !!this.animateChange || !!this.animateClick,
231
- 'spin-forever': this.spin,
231
+ 'spin-forever': this.spin
232
232
  })}"
233
233
  >
234
234
  <svg
@@ -243,7 +243,7 @@ export class VectorIcon extends LitElement {
243
243
  this.animationStep > 0,
244
244
  [this.animateClick]: !!this.animateClick,
245
245
  [this.animateClick + '-' + this.animationStep]:
246
- this.animationStep > 0,
246
+ this.animationStep > 0
247
247
  })}"
248
248
  >
249
249
  <use
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-duplicate-enum-values */
1
2
  // for cache busting we dynamically generate a fingerprint, use yarn svg to update
2
3
  export const SVG_FINGERPRINT = 'e5bcaf1a10896e9b870da4b40474d67b';
3
4
 
@@ -249,5 +250,5 @@ export enum Icon {
249
250
  datepicker = 'calendar',
250
251
  slider = 'sliders-02',
251
252
  select = 'browser',
252
- input = 'edit-05',
253
+ input = 'edit-05'
253
254
  }