@nyaruka/temba-components 0.112.0 → 0.114.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 (130) hide show
  1. package/CHANGELOG.md +27 -2
  2. package/demo/index.html +1 -1
  3. package/dist/temba-components.js +794 -968
  4. package/dist/temba-components.js.map +1 -1
  5. package/out-tsc/src/aliaseditor/AliasEditor.js.map +1 -1
  6. package/out-tsc/src/button/Button.js +6 -2
  7. package/out-tsc/src/button/Button.js.map +1 -1
  8. package/out-tsc/src/chat/Chat.js +29 -7
  9. package/out-tsc/src/chat/Chat.js.map +1 -1
  10. package/out-tsc/src/compose/Compose.js +16 -20
  11. package/out-tsc/src/compose/Compose.js.map +1 -1
  12. package/out-tsc/src/contacts/ContactChat.js +240 -114
  13. package/out-tsc/src/contacts/ContactChat.js.map +1 -1
  14. package/out-tsc/src/contacts/ContactFieldEditor.js.map +1 -1
  15. package/out-tsc/src/contacts/events.js.map +1 -1
  16. package/out-tsc/src/contacts/helpers.js +5 -1
  17. package/out-tsc/src/contacts/helpers.js.map +1 -1
  18. package/out-tsc/src/contactsearch/ContactSearch.js +1 -1
  19. package/out-tsc/src/contactsearch/ContactSearch.js.map +1 -1
  20. package/out-tsc/src/dropdown/Dropdown.js +121 -108
  21. package/out-tsc/src/dropdown/Dropdown.js.map +1 -1
  22. package/out-tsc/src/interfaces.js +2 -0
  23. package/out-tsc/src/interfaces.js.map +1 -1
  24. package/out-tsc/src/list/ContentMenu.js +11 -8
  25. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  26. package/out-tsc/src/list/RunList.js.map +1 -1
  27. package/out-tsc/src/list/TembaList.js +21 -14
  28. package/out-tsc/src/list/TembaList.js.map +1 -1
  29. package/out-tsc/src/list/TembaMenu.js +11 -12
  30. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  31. package/out-tsc/src/list/TicketList.js +10 -0
  32. package/out-tsc/src/list/TicketList.js.map +1 -1
  33. package/out-tsc/src/omnibox/Omnibox.js +33 -90
  34. package/out-tsc/src/omnibox/Omnibox.js.map +1 -1
  35. package/out-tsc/src/options/Options.js +49 -47
  36. package/out-tsc/src/options/Options.js.map +1 -1
  37. package/out-tsc/src/select/PopupSelect.js +57 -0
  38. package/out-tsc/src/select/PopupSelect.js.map +1 -0
  39. package/out-tsc/src/select/Select.js +194 -144
  40. package/out-tsc/src/select/Select.js.map +1 -1
  41. package/out-tsc/src/select/UserSelect.js +67 -0
  42. package/out-tsc/src/select/UserSelect.js.map +1 -0
  43. package/out-tsc/src/store/Store.js +65 -14
  44. package/out-tsc/src/store/Store.js.map +1 -1
  45. package/out-tsc/src/tabpane/TabPane.js +82 -115
  46. package/out-tsc/src/tabpane/TabPane.js.map +1 -1
  47. package/out-tsc/src/textinput/TextInput.js +1 -0
  48. package/out-tsc/src/textinput/TextInput.js.map +1 -1
  49. package/out-tsc/src/user/TembaUser.js +24 -37
  50. package/out-tsc/src/user/TembaUser.js.map +1 -1
  51. package/out-tsc/src/utils/index.js +13 -6
  52. package/out-tsc/src/utils/index.js.map +1 -1
  53. package/out-tsc/temba-modules.js +4 -2
  54. package/out-tsc/temba-modules.js.map +1 -1
  55. package/out-tsc/test/temba-omnibox.test.js +43 -4
  56. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  57. package/out-tsc/test/temba-select.test.js +121 -65
  58. package/out-tsc/test/temba-select.test.js.map +1 -1
  59. package/out-tsc/test/utils.test.js +4 -0
  60. package/out-tsc/test/utils.test.js.map +1 -1
  61. package/package.json +1 -1
  62. package/screenshots/truth/compose/attachments-tab.png +0 -0
  63. package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
  64. package/screenshots/truth/compose/attachments-with-files.png +0 -0
  65. package/screenshots/truth/compose/intial-text.png +0 -0
  66. package/screenshots/truth/compose/no-counter.png +0 -0
  67. package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
  68. package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
  69. package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
  70. package/screenshots/truth/contacts/chat-failure.png +0 -0
  71. package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
  72. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  73. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  74. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  75. package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
  76. package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
  77. package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
  78. package/screenshots/truth/content-menu/item-no-buttons.png +0 -0
  79. package/screenshots/truth/content-menu/items-and-buttons.png +0 -0
  80. package/screenshots/truth/omnibox/selected.png +0 -0
  81. package/screenshots/truth/select/enabled-multi-selection.png +0 -0
  82. package/screenshots/truth/select/endpoint-initial-value-updated.png +0 -0
  83. package/screenshots/truth/select/endpoint-initial-value.png +0 -0
  84. package/screenshots/truth/select/expressions.png +0 -0
  85. package/screenshots/truth/select/functions.png +0 -0
  86. package/screenshots/truth/select/initial-value.png +0 -0
  87. package/screenshots/truth/select/multi-with-endpoint.png +0 -0
  88. package/screenshots/truth/select/multiple-initial-values.png +0 -0
  89. package/screenshots/truth/select/selected-multi-test.png +0 -0
  90. package/screenshots/truth/select/static-initial-value.png +0 -0
  91. package/screenshots/truth/select/static-initial-via-selected.png +0 -0
  92. package/screenshots/truth/select/value-initial.png +0 -0
  93. package/src/aliaseditor/AliasEditor.ts +1 -1
  94. package/src/button/Button.ts +6 -2
  95. package/src/chat/Chat.ts +28 -6
  96. package/src/compose/Compose.ts +17 -22
  97. package/src/contacts/ContactChat.ts +260 -118
  98. package/src/contacts/ContactFieldEditor.ts +1 -1
  99. package/src/contacts/events.ts +1 -0
  100. package/src/contacts/helpers.ts +8 -1
  101. package/src/contactsearch/ContactSearch.ts +3 -3
  102. package/src/dropdown/Dropdown.ts +142 -103
  103. package/src/interfaces.ts +4 -1
  104. package/src/list/ContentMenu.ts +11 -9
  105. package/src/list/RunList.ts +3 -1
  106. package/src/list/TembaList.ts +24 -14
  107. package/src/list/TembaMenu.ts +14 -15
  108. package/src/list/TicketList.ts +11 -0
  109. package/src/omnibox/Omnibox.ts +34 -95
  110. package/src/options/Options.ts +57 -60
  111. package/src/select/PopupSelect.ts +53 -0
  112. package/src/select/Select.ts +182 -112
  113. package/src/select/UserSelect.ts +71 -0
  114. package/src/store/Store.ts +70 -21
  115. package/src/tabpane/TabPane.ts +91 -113
  116. package/src/textinput/TextInput.ts +1 -0
  117. package/src/user/TembaUser.ts +30 -41
  118. package/src/utils/index.ts +12 -8
  119. package/temba-modules.ts +4 -2
  120. package/test/temba-omnibox.test.ts +56 -4
  121. package/test/temba-select.test.ts +170 -56
  122. package/test/utils.test.ts +5 -0
  123. package/test-assets/select/omnibox.json +55 -0
  124. package/web-test-runner.config.mjs +16 -4
  125. package/out-tsc/src/contacts/ContactTickets.js +0 -462
  126. package/out-tsc/src/contacts/ContactTickets.js.map +0 -1
  127. package/out-tsc/test/temba-contact-tickets.test.js +0 -36
  128. package/out-tsc/test/temba-contact-tickets.test.js.map +0 -1
  129. package/src/contacts/ContactTickets.ts +0 -490
  130. package/test/temba-contact-tickets.test.ts +0 -52
@@ -1 +1 @@
1
- {"version":3,"file":"AliasEditor.js","sourceRoot":"","sources":["../../../src/aliaseditor/AliasEditor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAkB,MAAM,KAAK,CAAC;AAE5D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAe,MAAM,UAAU,CAAC;AAEzD,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C,MAAM,OAAO,WAAY,SAAQ,UAAU;IACzC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuHT,CAAC;IACJ,CAAC;IAoBD;QACE,KAAK,EAAE,CAAC;QAlBV,SAAI,GAAwB,EAAE,CAAC;IAmB/B,CAAC;IAEM,OAAO,CAAC,iBAAmC;QAChD,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,4CAA4C;YAC5C,MAAM,OAAO,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACtB,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;oBAClC,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;oBACzB,IAAI,CAAC,eAAe,EAAE,CAAC;oBACvB,OAAO;gBACT,CAAC;YACH,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAEO,YAAY;QAClB,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,aAAa,GAAG,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,IAAI,CAChE,CAAC,QAAqB,EAAE,EAAE;YACxB,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAA2B,CAAC;YACjD,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC,CACF,CAAC;IACJ,CAAC;IAEO,gBAAgB,CAAC,OAA0B;QACjD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,CAAC;IACH,CAAC;IAEO,kBAAkB,CAAC,OAA0B;QACnD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,CAAC;IAEO,qBAAqB,CAAC,GAAgB;QAC5C,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,QAA6B,CAAC;QAC3D,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAW,CAAC;QACvE,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAEO,OAAO,CAAC,MAAW,EAAE,KAAa;QACxC,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,CAAC;IAEO,aAAa,CACnB,OAA0B,EAC1B,aAAkC;QAElC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,SAAS,GACb,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC;YAC7C,OAAO,KAAK,eAAe,CAAC;QAC9B,MAAM,eAAe,GAAG,IAAI,CAAA;;;uBAGT,GAAG,EAAE;YAChB,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACzB,CAAC;QACH,CAAC;sBACW,GAAG,EAAE;YACf,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;yBACc,OAAO,CAAC,KAAK;;;kCAGJ,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;qBACzC,GAAG,EAAE;YACZ,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;;cAEC,OAAO,CAAC,IAAI;;;;cAIZ,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAa,EAAE,EAAE,CAClD,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,IAAI,CAAA;;;+BAGS,GAAG,EAAE;gBACZ,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;;;yBAGE,KAAK;;mBAEX;YACH,CAAC,CAAC,IAAI,CACT;cACC,OAAO,CAAC,KAAK,GAAG,CAAC;YACjB,CAAC,CAAC,IAAI,CAAA;;;6BAGS,CAAC,GAAe,EAAE,EAAE;gBAC3B,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBAC9B,GAAG,CAAC,cAAc,EAAE,CAAC;gBACrB,GAAG,CAAC,eAAe,EAAE,CAAC;YACxB,CAAC;;wCAEmB,IAAI,CAAC,OAAO;;iBAEnC;YACH,CAAC,CAAC,EAAE;;;;KAIb,CAAC;QAEF,MAAM,gBAAgB,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CACnD,CAAC,KAAwB,EAAE,EAAE;YAC3B,IACE,aAAa,CAAC,MAAM,GAAG,CAAC;gBACxB,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EACxC,CAAC;gBACD,OAAO,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC;YAED,IACE,aAAa,CAAC,MAAM,KAAK,CAAC;gBAC1B,aAAa,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EACtC,CAAC;gBACD,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YAClD,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC,CACF,CAAC;QAEF,OAAO,IAAI,CAAA,IAAI,eAAe,IAAI,gBAAgB,GAAG,CAAC;IACxD,CAAC;IAEM,eAAe,CAAC,OAA0B;QAC/C,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;QAC1C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC;QAC3B,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QACnE,IAAI,WAAW,EAAE,CAAC;YAChB,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAEM,eAAe;QACpB,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QACnE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,WAAW,EAAE,CAAC;YAChB,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAEO,WAAW;QACjB,OAAO,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACnE,CAAC;IAEO,iBAAiB,CAAC,GAAgB;QACxC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;QACjC,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAC7C,IAAI,CAAC,WAAW,CAAC,MAAM,CACX,CAAC;YACf,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC;YAC5C,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC7D,QAAQ,CACN,IAAI,CAAC,WAAW,EAAE,GAAG,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,EAClE,OAAO,CACR,CAAC,IAAI,CAAC,GAAG,EAAE;gBACV,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,QAAqB;QACtC,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAW,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACjE,CAAC;IAEO,kBAAkB,CAAC,aAAkC;QAC3D,OAAO,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC;IACpC,CAAC;IAEO,kBAAkB,CAAC,MAAyB;QAClD,MAAM,WAAW,GAAG;YAClB,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,KAAK;SACnB,CAAC;QAEF,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,KAAa,EAAE,EAAE,CAC9C,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,IAAI,CAAA;iCACmB,QAAQ,CAAC,WAAW,CAAC;iBACrC,KAAK;;WAEX;YACH,CAAC,CAAC,IAAI,CACT,CAAC;QACF,OAAO,IAAI,CAAA;0BACW,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;6BAC5B,OAAO;KAC/B,CAAC;IACJ,CAAC;IAEM,MAAM;QACX,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAA,EAAE,CAAC;QAChB,CAAC;QAED,sDAAsD;QACtD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,UAAU,GACd,eAAe,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YACnC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YACjC,CAAC,CAAC,eAAe,CAAC;QAEtB,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACxE,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAExE,OAAO,IAAI,CAAA;;;;;wBAKS,IAAI,CAAC,WAAW,EAAE,cAAc,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM;kCACzC,IAAI,CAAC,kBAAkB;0BAC/B,IAAI,CAAC,UAAU;0BACf,IAAI,CAAC,kBAAkB;uBAC1B,IAAI,CAAC,OAAO;+BACJ,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;YAMxD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;;;;;;qBAM3C,IAAI,CAAC,WAAW,EAAE;qBAClB,UAAU;mBACZ,UAAU,CAAC,MAAM;qBACf,IAAI,CAAC,OAAO;8BACH,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;8BAOhC,eAAe;;gCAEb,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;;;;iDAIhB,eAAe;;iBAE/C,aAAa;qBACT,IAAI,CAAC,kBAAkB;;;;;KAKvC,CAAC;IACJ,CAAC;CACF;AA1SC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;yCACb;AAG/B;IADC,QAAQ,EAAE;6CACM;AAGjB;IADC,QAAQ,EAAE;0CACG;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;4CACA;AAG3B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDACI;AAG/B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;uDAClB","sourcesContent":["import { css, html, LitElement, TemplateResult } from 'lit';\nimport { FeatureProperties } from '../interfaces';\nimport { getUrl, postJSON, WebResponse } from '../utils';\nimport { TextInput } from '../textinput/TextInput';\nimport { styleMap } from 'lit-html/directives/style-map.js';\nimport { Icon } from '../vectoricon';\n\nimport { property } from 'lit/decorators.js';\nimport { Select } from '../select/Select';\n\nexport class AliasEditor extends LitElement {\n static get styles() {\n return css`\n :host {\n line-height: normal;\n }\n\n temba-textinput {\n height: 150px;\n }\n\n #left-column {\n display: inline-block;\n margin-left: 10px;\n width: 300px;\n z-index: 100;\n }\n\n .search {\n margin-bottom: 10px;\n }\n\n .feature {\n padding: 4px 14px;\n font-size: 16px;\n }\n\n .level-0 {\n margin-left: 0px;\n }\n\n .level-1 {\n margin-left: 5px;\n font-size: 95%;\n }\n\n .level-2 {\n margin-left: 10px;\n font-size: 90%;\n }\n\n .level-3 {\n margin-left: 15px;\n font-size: 85%;\n }\n\n .feature-name {\n display: inline-block;\n }\n\n .clickable {\n text-decoration: none;\n cursor: pointer;\n color: var(--color-link-primary);\n }\n\n .clickable.secondary {\n color: var(--color-link-secondary);\n }\n\n .clickable:hover {\n text-decoration: underline;\n color: var(--color-link-primary-hover);\n }\n\n .feature:hover .showonhover {\n visibility: visible;\n }\n\n .showonhover {\n visibility: hidden;\n }\n\n .aliases {\n color: #bbb;\n font-size: 80%;\n display: inline;\n margin-left: 5px;\n }\n\n temba-label {\n margin-right: 3px;\n margin-bottom: 3px;\n vertical-align: top;\n }\n\n .selected {\n display: flex;\n flex-direction: column;\n padding: 15px;\n padding-bottom: 40px;\n }\n\n .selected .name {\n font-size: 18px;\n padding: 5px;\n }\n\n .selected .help {\n padding: 5px 2px;\n font-size: 11px;\n color: var(--color-secondary-light);\n }\n\n #right-column {\n vertical-align: top;\n margin-left: 20px;\n display: inline-block;\n }\n\n leaflet-map {\n height: 600px;\n width: 800px;\n border: 0px solid #999;\n border-radius: var(--curvature);\n }\n\n .edit {\n display: inline-block;\n margin-right: 0px;\n }\n `;\n }\n\n @property({ type: Array, attribute: false })\n path: FeatureProperties[] = [];\n\n @property()\n endpoint: string;\n\n @property()\n osmId: string;\n\n @property({ type: Object })\n hovered: FeatureProperties;\n\n @property({ type: Object })\n editFeature: FeatureProperties;\n\n @property({ type: String, attribute: false })\n editFeatureAliases: string;\n\n public constructor() {\n super();\n }\n\n public updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('osmId')) {\n // going up the tree doesn't require a fetch\n const newPath = [];\n for (const feature of this.path) {\n newPath.push(feature);\n if (feature.osm_id === this.osmId) {\n this.path = [...newPath];\n this.hideAliasDialog();\n return;\n }\n }\n\n this.fetchFeature();\n }\n }\n\n private fetchFeature() {\n getUrl(this.getEndpoint() + 'boundaries/' + this.osmId + '/').then(\n (response: WebResponse) => {\n this.path = response.json as FeatureProperties[];\n this.hideAliasDialog();\n }\n );\n }\n\n private handleMapClicked(feature: FeatureProperties): void {\n this.hovered = null;\n if (!feature || feature.osm_id !== this.osmId) {\n this.osmId = feature.osm_id;\n }\n }\n\n private handlePlaceClicked(feature: FeatureProperties) {\n this.osmId = feature.osm_id;\n }\n\n private handleSearchSelection(evt: CustomEvent) {\n const selection = evt.detail.selected as FeatureProperties;\n this.showAliasDialog(selection);\n const select = this.shadowRoot.querySelector('temba-select') as Select;\n select.clear();\n }\n\n private isMatch(option: any, query: string) {\n return `${option.name} ${option.aliases}`.toLowerCase().indexOf(query) > -1;\n }\n\n private renderFeature(\n feature: FeatureProperties,\n remainingPath: FeatureProperties[]\n ): TemplateResult {\n const selectedFeature = this.path[this.path.length - 1];\n const clickable =\n (feature.has_children || feature.level === 0) &&\n feature !== selectedFeature;\n const renderedFeature = html`\n <div class=\"feature\">\n <div\n @mouseover=${() => {\n if (feature.level > 0) {\n this.hovered = feature;\n }\n }}\n @mouseout=${() => {\n this.hovered = null;\n }}\n class=\"level-${feature.level}\"\n >\n <div\n class=\"feature-name ${clickable ? 'clickable' : ''}\"\n @click=${() => {\n if (clickable) {\n this.handlePlaceClicked(feature);\n }\n }}\n >\n ${feature.name}\n </div>\n\n <div class=\"aliases\">\n ${feature.aliases.split('\\n').map((alias: string) =>\n alias.trim().length > 0\n ? html`\n <temba-label\n class=\"alias\"\n @click=${() => {\n this.showAliasDialog(feature);\n }}\n light\n clickable\n >${alias}</temba-label\n >\n `\n : null\n )}\n ${feature.level > 0\n ? html`\n <div\n class=\"edit clickable showonhover\"\n @click=${(evt: MouseEvent) => {\n this.showAliasDialog(feature);\n evt.preventDefault();\n evt.stopPropagation();\n }}\n >\n <temba-icon name=\"${Icon.updated}\" />\n </div>\n `\n : ''}\n </div>\n </div>\n </div>\n `;\n\n const renderedChildren = (feature.children || []).map(\n (child: FeatureProperties) => {\n if (\n remainingPath.length > 0 &&\n remainingPath[0].osm_id === child.osm_id\n ) {\n return this.renderFeature(remainingPath[0], remainingPath.slice(1));\n }\n\n if (\n remainingPath.length === 0 ||\n remainingPath[0].children.length === 0\n ) {\n return this.renderFeature(child, remainingPath);\n }\n\n return null;\n }\n );\n\n return html` ${renderedFeature} ${renderedChildren} `;\n }\n\n public showAliasDialog(feature: FeatureProperties) {\n this.editFeatureAliases = feature.aliases;\n this.editFeature = feature;\n const aliasDialog = this.shadowRoot.getElementById('alias-dialog');\n if (aliasDialog) {\n aliasDialog.setAttribute('open', '');\n }\n }\n\n public hideAliasDialog() {\n const aliasDialog = this.shadowRoot.getElementById('alias-dialog');\n this.editFeature = null;\n this.editFeatureAliases = null;\n if (aliasDialog) {\n aliasDialog.removeAttribute('open');\n }\n\n this.requestUpdate();\n }\n\n private getEndpoint(): string {\n return this.endpoint + (!this.endpoint.endsWith('/') ? '/' : '');\n }\n\n private handleDialogClick(evt: CustomEvent) {\n const button = evt.detail.button;\n if (button.name === 'Save') {\n const textarea = this.shadowRoot.getElementById(\n this.editFeature.osm_id\n ) as TextInput;\n const aliases = textarea.inputElement.value;\n const payload = { osm_id: this.editFeature.osm_id, aliases };\n postJSON(\n this.getEndpoint() + 'boundaries/' + this.editFeature.osm_id + '/',\n payload\n ).then(() => {\n this.fetchFeature();\n });\n }\n\n if (button.name === 'Cancel') {\n this.hideAliasDialog();\n }\n }\n\n private getOptions(response: WebResponse) {\n return response.json.filter((option: any) => option.level > 0);\n }\n\n private getOptionsComplete(newestOptions: FeatureProperties[]) {\n return newestOptions.length === 0;\n }\n\n private renderOptionDetail(option: FeatureProperties): TemplateResult {\n const labelStyles = {\n marginTop: '3px',\n marginRight: '3px'\n };\n\n const aliasList = option.aliases.split('\\n');\n const aliases = aliasList.map((alias: string) =>\n alias.trim().length > 0\n ? html`\n <temba-label style=${styleMap(labelStyles)} class=\"alias\" dark\n >${alias}</temba-label\n >\n `\n : null\n );\n return html`\n <div class=\"path\">${option.path.replace(/>/gi, '‣')}</div>\n <div class=\"aliases\">${aliases}</div>\n `;\n }\n\n public render(): TemplateResult {\n if (this.path.length === 0) {\n return html``;\n }\n\n // if we are a leaf, have our map show the level above\n const selectedFeature = this.path[this.path.length - 1];\n const mapFeature =\n selectedFeature.children.length === 0\n ? this.path[this.path.length - 2]\n : selectedFeature;\n\n const editFeatureId = this.editFeature ? this.editFeature.osm_id : null;\n const editFeatureName = this.editFeature ? this.editFeature.name : null;\n\n return html`\n <div id=\"left-column\">\n <div class=\"search\">\n <temba-select\n placeholder=\"Search\"\n endpoint=\"${this.getEndpoint()}boundaries/${this.path[0].osm_id}/?\"\n .renderOptionDetail=${this.renderOptionDetail}\n .getOptions=${this.getOptions}\n .isComplete=${this.getOptionsComplete}\n .isMatch=${this.isMatch}\n @temba-selection=${this.handleSearchSelection.bind(this)}\n queryParam=\"q\"\n searchable\n ></temba-select>\n </div>\n <div class=\"feature-tree\">\n ${this.renderFeature(this.path[0], this.path.slice(1))}\n </div>\n </div>\n\n <div id=\"right-column\">\n <leaflet-map\n endpoint=${this.getEndpoint()}\n .feature=${mapFeature}\n .osmId=${mapFeature.osm_id}\n .hovered=${this.hovered}\n .onFeatureClicked=${this.handleMapClicked.bind(this)}\n >\n </leaflet-map>\n </div>\n\n <temba-dialog\n id=\"alias-dialog\"\n header=\"Aliases for ${editFeatureName}\"\n primaryButtonName=\"Save\"\n @temba-button-clicked=${this.handleDialogClick.bind(this)}\n >\n <div class=\"selected\">\n <temba-textinput\n .helpText=\"Enter other aliases for ${editFeatureName}, one per line\"\n name=\"aliases\"\n id=${editFeatureId}\n .value=${this.editFeatureAliases}\n textarea\n ></temba-textinput>\n </div>\n </temba-dialog>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"AliasEditor.js","sourceRoot":"","sources":["../../../src/aliaseditor/AliasEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, TemplateResult } from 'lit';\nimport { FeatureProperties } from '../interfaces';\nimport { getUrl, postJSON, WebResponse } from '../utils';\nimport { TextInput } from '../textinput/TextInput';\nimport { styleMap } from 'lit-html/directives/style-map.js';\nimport { Icon } from '../vectoricon';\n\nimport { property } from 'lit/decorators.js';\nimport { Select } from '../select/Select';\n\nexport class AliasEditor extends LitElement {\n static get styles() {\n return css`\n :host {\n line-height: normal;\n }\n\n temba-textinput {\n height: 150px;\n }\n\n #left-column {\n display: inline-block;\n margin-left: 10px;\n width: 300px;\n z-index: 100;\n }\n\n .search {\n margin-bottom: 10px;\n }\n\n .feature {\n padding: 4px 14px;\n font-size: 16px;\n }\n\n .level-0 {\n margin-left: 0px;\n }\n\n .level-1 {\n margin-left: 5px;\n font-size: 95%;\n }\n\n .level-2 {\n margin-left: 10px;\n font-size: 90%;\n }\n\n .level-3 {\n margin-left: 15px;\n font-size: 85%;\n }\n\n .feature-name {\n display: inline-block;\n }\n\n .clickable {\n text-decoration: none;\n cursor: pointer;\n color: var(--color-link-primary);\n }\n\n .clickable.secondary {\n color: var(--color-link-secondary);\n }\n\n .clickable:hover {\n text-decoration: underline;\n color: var(--color-link-primary-hover);\n }\n\n .feature:hover .showonhover {\n visibility: visible;\n }\n\n .showonhover {\n visibility: hidden;\n }\n\n .aliases {\n color: #bbb;\n font-size: 80%;\n display: inline;\n margin-left: 5px;\n }\n\n temba-label {\n margin-right: 3px;\n margin-bottom: 3px;\n vertical-align: top;\n }\n\n .selected {\n display: flex;\n flex-direction: column;\n padding: 15px;\n padding-bottom: 40px;\n }\n\n .selected .name {\n font-size: 18px;\n padding: 5px;\n }\n\n .selected .help {\n padding: 5px 2px;\n font-size: 11px;\n color: var(--color-secondary-light);\n }\n\n #right-column {\n vertical-align: top;\n margin-left: 20px;\n display: inline-block;\n }\n\n leaflet-map {\n height: 600px;\n width: 800px;\n border: 0px solid #999;\n border-radius: var(--curvature);\n }\n\n .edit {\n display: inline-block;\n margin-right: 0px;\n }\n `;\n }\n\n @property({ type: Array, attribute: false })\n path: FeatureProperties[] = [];\n\n @property()\n endpoint: string;\n\n @property()\n osmId: string;\n\n @property({ type: Object })\n hovered: FeatureProperties;\n\n @property({ type: Object })\n editFeature: FeatureProperties;\n\n @property({ type: String, attribute: false })\n editFeatureAliases: string;\n\n public constructor() {\n super();\n }\n\n public updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('osmId')) {\n // going up the tree doesn't require a fetch\n const newPath = [];\n for (const feature of this.path) {\n newPath.push(feature);\n if (feature.osm_id === this.osmId) {\n this.path = [...newPath];\n this.hideAliasDialog();\n return;\n }\n }\n\n this.fetchFeature();\n }\n }\n\n private fetchFeature() {\n getUrl(this.getEndpoint() + 'boundaries/' + this.osmId + '/').then(\n (response: WebResponse) => {\n this.path = response.json as FeatureProperties[];\n this.hideAliasDialog();\n }\n );\n }\n\n private handleMapClicked(feature: FeatureProperties): void {\n this.hovered = null;\n if (!feature || feature.osm_id !== this.osmId) {\n this.osmId = feature.osm_id;\n }\n }\n\n private handlePlaceClicked(feature: FeatureProperties) {\n this.osmId = feature.osm_id;\n }\n\n private handleSearchSelection(evt: CustomEvent) {\n const selection = evt.detail.selected as FeatureProperties;\n this.showAliasDialog(selection);\n const select = this.shadowRoot.querySelector('temba-select') as Select<any>;\n select.clear();\n }\n\n private isMatch(option: any, query: string) {\n return `${option.name} ${option.aliases}`.toLowerCase().indexOf(query) > -1;\n }\n\n private renderFeature(\n feature: FeatureProperties,\n remainingPath: FeatureProperties[]\n ): TemplateResult {\n const selectedFeature = this.path[this.path.length - 1];\n const clickable =\n (feature.has_children || feature.level === 0) &&\n feature !== selectedFeature;\n const renderedFeature = html`\n <div class=\"feature\">\n <div\n @mouseover=${() => {\n if (feature.level > 0) {\n this.hovered = feature;\n }\n }}\n @mouseout=${() => {\n this.hovered = null;\n }}\n class=\"level-${feature.level}\"\n >\n <div\n class=\"feature-name ${clickable ? 'clickable' : ''}\"\n @click=${() => {\n if (clickable) {\n this.handlePlaceClicked(feature);\n }\n }}\n >\n ${feature.name}\n </div>\n\n <div class=\"aliases\">\n ${feature.aliases.split('\\n').map((alias: string) =>\n alias.trim().length > 0\n ? html`\n <temba-label\n class=\"alias\"\n @click=${() => {\n this.showAliasDialog(feature);\n }}\n light\n clickable\n >${alias}</temba-label\n >\n `\n : null\n )}\n ${feature.level > 0\n ? html`\n <div\n class=\"edit clickable showonhover\"\n @click=${(evt: MouseEvent) => {\n this.showAliasDialog(feature);\n evt.preventDefault();\n evt.stopPropagation();\n }}\n >\n <temba-icon name=\"${Icon.updated}\" />\n </div>\n `\n : ''}\n </div>\n </div>\n </div>\n `;\n\n const renderedChildren = (feature.children || []).map(\n (child: FeatureProperties) => {\n if (\n remainingPath.length > 0 &&\n remainingPath[0].osm_id === child.osm_id\n ) {\n return this.renderFeature(remainingPath[0], remainingPath.slice(1));\n }\n\n if (\n remainingPath.length === 0 ||\n remainingPath[0].children.length === 0\n ) {\n return this.renderFeature(child, remainingPath);\n }\n\n return null;\n }\n );\n\n return html` ${renderedFeature} ${renderedChildren} `;\n }\n\n public showAliasDialog(feature: FeatureProperties) {\n this.editFeatureAliases = feature.aliases;\n this.editFeature = feature;\n const aliasDialog = this.shadowRoot.getElementById('alias-dialog');\n if (aliasDialog) {\n aliasDialog.setAttribute('open', '');\n }\n }\n\n public hideAliasDialog() {\n const aliasDialog = this.shadowRoot.getElementById('alias-dialog');\n this.editFeature = null;\n this.editFeatureAliases = null;\n if (aliasDialog) {\n aliasDialog.removeAttribute('open');\n }\n\n this.requestUpdate();\n }\n\n private getEndpoint(): string {\n return this.endpoint + (!this.endpoint.endsWith('/') ? '/' : '');\n }\n\n private handleDialogClick(evt: CustomEvent) {\n const button = evt.detail.button;\n if (button.name === 'Save') {\n const textarea = this.shadowRoot.getElementById(\n this.editFeature.osm_id\n ) as TextInput;\n const aliases = textarea.inputElement.value;\n const payload = { osm_id: this.editFeature.osm_id, aliases };\n postJSON(\n this.getEndpoint() + 'boundaries/' + this.editFeature.osm_id + '/',\n payload\n ).then(() => {\n this.fetchFeature();\n });\n }\n\n if (button.name === 'Cancel') {\n this.hideAliasDialog();\n }\n }\n\n private getOptions(response: WebResponse) {\n return response.json.filter((option: any) => option.level > 0);\n }\n\n private getOptionsComplete(newestOptions: FeatureProperties[]) {\n return newestOptions.length === 0;\n }\n\n private renderOptionDetail(option: FeatureProperties): TemplateResult {\n const labelStyles = {\n marginTop: '3px',\n marginRight: '3px'\n };\n\n const aliasList = option.aliases.split('\\n');\n const aliases = aliasList.map((alias: string) =>\n alias.trim().length > 0\n ? html`\n <temba-label style=${styleMap(labelStyles)} class=\"alias\" dark\n >${alias}</temba-label\n >\n `\n : null\n );\n return html`\n <div class=\"path\">${option.path.replace(/>/gi, '‣')}</div>\n <div class=\"aliases\">${aliases}</div>\n `;\n }\n\n public render(): TemplateResult {\n if (this.path.length === 0) {\n return html``;\n }\n\n // if we are a leaf, have our map show the level above\n const selectedFeature = this.path[this.path.length - 1];\n const mapFeature =\n selectedFeature.children.length === 0\n ? this.path[this.path.length - 2]\n : selectedFeature;\n\n const editFeatureId = this.editFeature ? this.editFeature.osm_id : null;\n const editFeatureName = this.editFeature ? this.editFeature.name : null;\n\n return html`\n <div id=\"left-column\">\n <div class=\"search\">\n <temba-select\n placeholder=\"Search\"\n endpoint=\"${this.getEndpoint()}boundaries/${this.path[0].osm_id}/?\"\n .renderOptionDetail=${this.renderOptionDetail}\n .getOptions=${this.getOptions}\n .isComplete=${this.getOptionsComplete}\n .isMatch=${this.isMatch}\n @temba-selection=${this.handleSearchSelection.bind(this)}\n queryParam=\"q\"\n searchable\n ></temba-select>\n </div>\n <div class=\"feature-tree\">\n ${this.renderFeature(this.path[0], this.path.slice(1))}\n </div>\n </div>\n\n <div id=\"right-column\">\n <leaflet-map\n endpoint=${this.getEndpoint()}\n .feature=${mapFeature}\n .osmId=${mapFeature.osm_id}\n .hovered=${this.hovered}\n .onFeatureClicked=${this.handleMapClicked.bind(this)}\n >\n </leaflet-map>\n </div>\n\n <temba-dialog\n id=\"alias-dialog\"\n header=\"Aliases for ${editFeatureName}\"\n primaryButtonName=\"Save\"\n @temba-button-clicked=${this.handleDialogClick.bind(this)}\n >\n <div class=\"selected\">\n <temba-textinput\n .helpText=\"Enter other aliases for ${editFeatureName}, one per line\"\n name=\"aliases\"\n id=${editFeatureId}\n .value=${this.editFeatureAliases}\n textarea\n ></temba-textinput>\n </div>\n </temba-dialog>\n `;\n }\n}\n"]}
@@ -10,7 +10,8 @@ export class Button extends LitElement {
10
10
  static get styles() {
11
11
  return css `
12
12
  :host {
13
- display: inline-block;
13
+ display: flex;
14
+ align-self: stretch;
14
15
  font-family: var(--font-family);
15
16
  font-weight: 400;
16
17
  }
@@ -32,13 +33,15 @@ export class Button extends LitElement {
32
33
  .button-container {
33
34
  color: #fff;
34
35
  cursor: pointer;
35
- display: block;
36
+ display: flex;
37
+ flex-grow: 1;
36
38
  border-radius: var(--curvature);
37
39
  outline: none;
38
40
  transition: background ease-in var(--transition-speed);
39
41
  user-select: none;
40
42
  -webkit-user-select: none;
41
43
  text-align: center;
44
+ border: var(--button-border, none);
42
45
  }
43
46
 
44
47
  .button-name {
@@ -73,6 +76,7 @@ export class Button extends LitElement {
73
76
  transition: var(--transition-speed);
74
77
  background: var(--button-mask);
75
78
  display: flex;
79
+ align-items: center;
76
80
  }
77
81
 
78
82
  .button-container.disabled-button {
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/button/Button.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAkB,IAAI,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,MAAM,OAAO,MAAO,SAAQ,UAAU;IAAtC;;QAkLE,MAAC,GAAG,CAAC,CAAC;IA+GR,CAAC;IAhSC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmKT,CAAC;IACJ,CAAC;IA+CO,WAAW,CAAC,GAAe;QACjC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,cAAc,EAAE,CAAC;YACrB,GAAG,CAAC,eAAe,EAAE,CAAC;QACxB,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YAC7C,GAAG,CAAC,cAAc,EAAE,CAAC;YACrB,GAAG,CAAC,eAAe,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,KAAoB;QACtC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACvC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAEM,MAAM;QACX,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU;YAChC,CAAC,CAAC,IAAI,CAAA;;eAEG;YACT,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAEd,OAAO,IAAI,CAAA;;;cAGD,IAAI,CAAC,CAAC;YACR,UAAU,CAAC;YACb,gBAAgB,EACd,IAAI,CAAC,OAAO;gBACZ,CAAC,CAAC,IAAI,CAAC,OAAO;oBACZ,CAAC,IAAI,CAAC,SAAS;oBACf,CAAC,IAAI,CAAC,SAAS;oBACf,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YAChB,kBAAkB,EAAE,IAAI,CAAC,SAAS;YAClC,iBAAiB,EAAE,IAAI,CAAC,QAAQ;YAChC,eAAe,EAAE,IAAI,CAAC,MAAM;YAC5B,kBAAkB,EAAE,IAAI,CAAC,SAAS;YAClC,oBAAoB,EAAE,IAAI,CAAC,WAAW;YACtC,cAAc,EAAE,IAAI,CAAC,KAAK;YAC1B,cAAc,EAAE,IAAI,CAAC,KAAK;YAC1B,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;YAC1B,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC;;qBAEW,IAAI,CAAC,eAAe;mBACtB,IAAI,CAAC,aAAa;sBACf,IAAI,CAAC,aAAa;iBACvB,IAAI,CAAC,WAAW;iBAChB,IAAI,CAAC,WAAW;;;YAGrB,IAAI,CAAC,IAAI;YACT,CAAC,CAAC,IAAI,CAAA,qBAAqB,IAAI,CAAC,IAAI,iBAAiB;YACrD,CAAC,CAAC,IAAI;uDACqC,UAAU;;;KAG5D,CAAC;IACJ,CAAC;CACF;AAxHC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;uCACX;AAGjB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;yCACT;AAGnB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;yCACT;AAGnB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;iCACrB;AAGN;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;2CACP;AAGrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;qCACb;AAGf;IADC,QAAQ,EAAE;oCACE;AAGb;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;wCACV;AAGlB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;0CACR;AAGpB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;sCACZ;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;qCACb;AAGf;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;qCACb;AAGf;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oCACd;AAGb;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;qCACZ;AAGf;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oCACb","sourcesContent":["import { LitElement, TemplateResult, html, css } from 'lit';\nimport { getClasses } from '../utils';\n\nimport { property } from 'lit/decorators.js';\n\nexport class Button extends LitElement {\n static get styles() {\n return css`\n :host {\n display: inline-block;\n font-family: var(--font-family);\n font-weight: 400;\n }\n\n .small {\n font-size: 0.8em;\n --button-y: 0px;\n --button-x: 0.5em;\n }\n\n .v-2.button-container {\n background: var(--button-bg);\n background-image: var(--button-bg-img);\n color: var(--button-text);\n box-shadow: var(--button-shadow);\n transition: all calc(var(--transition-speed) / 2) ease-in;\n }\n\n .button-container {\n color: #fff;\n cursor: pointer;\n display: block;\n border-radius: var(--curvature);\n outline: none;\n transition: background ease-in var(--transition-speed);\n user-select: none;\n -webkit-user-select: none;\n text-align: center;\n }\n\n .button-name {\n white-space: nowrap;\n }\n\n .secondary-button:hover .button-mask {\n border: 1px solid var(--color-button-secondary);\n }\n\n .button-mask:hover {\n background: rgba(0, 0, 0, 0.05);\n }\n\n .button-container:focus {\n outline: none;\n margin: 0;\n }\n\n .button-container:focus {\n box-shadow: var(--widget-box-shadow-focused);\n }\n\n .button-container.secondary-button:focus .button-mask {\n background: transparent;\n }\n\n .button-mask {\n padding: var(--button-y) var(--button-x);\n border-radius: var(--curvature);\n border: 1px solid transparent;\n transition: var(--transition-speed);\n background: var(--button-mask);\n display: flex;\n }\n\n .button-container.disabled-button {\n background: rgba(0, 0, 0, 0.05);\n color: rgba(255, 255, 255, 0.45);\n cursor: default;\n }\n\n .button-container.disabled-button .button-mask {\n box-shadow: 0 0 0px 1px var(--color-button-disabled);\n }\n\n .button-container.disabled-button:hover .button-mask {\n box-shadow: 0 0 0px 1px var(--color-button-disabled);\n background: rgba(0, 0, 0, 0.05);\n }\n\n .button-container.active-button .button-mask {\n }\n\n .secondary-button.active-button {\n background: transparent;\n color: var(--color-text);\n }\n\n .secondary-button.active-button .button-mask {\n border: none;\n }\n\n .button-container.secondary-button.active-button:focus .button-mask {\n background: transparent;\n box-shadow: none;\n }\n\n .primary-button {\n background: var(--color-button-primary);\n color: var(--color-button-primary-text);\n }\n\n .affirmative {\n background: var(--color-button-attention);\n }\n\n .light-button {\n background: var(--color-button-light);\n color: var(--color-button-light-text);\n }\n\n .lined-button {\n border: 1px solid rgba(0, 0, 0, 0.1);\n color: rgba(0, 0, 0, 0.7);\n background: transparent;\n }\n\n .lined-button .button-mask:hover {\n background: rgba(0, 0, 0, 0.03);\n }\n\n .icon-button {\n --button-y: 0.2em;\n --button-x: 0em;\n }\n\n .icon-button temba-icon {\n padding: 0 0.5em;\n }\n\n .attention-button {\n background: var(--color-button-attention);\n color: var(--color-button-primary-text);\n }\n\n .secondary-button {\n background: transparent;\n color: var(--color-text);\n }\n\n .destructive-button {\n background: var(--color-button-destructive);\n color: var(--color-button-destructive-text);\n }\n\n .button-mask.disabled-button {\n background: rgba(0, 0, 0, 0.1);\n }\n\n .secondary-button .button-mask:hover {\n background: transparent;\n }\n\n .submit-animation {\n padding: 1px 4px;\n }\n\n .submit-animation temba-loading {\n margin-bottom: -3px;\n line-height: normal;\n }\n `;\n }\n\n @property({ type: Boolean })\n primary: boolean;\n\n @property({ type: Boolean })\n secondary: boolean;\n\n @property({ type: Boolean })\n attention: boolean;\n\n @property({ type: Number })\n v = 1;\n\n @property({ type: Boolean })\n destructive: boolean;\n\n @property({ type: Boolean })\n light: boolean;\n\n @property()\n name: string;\n\n @property({ type: Boolean })\n disabled: boolean;\n\n @property({ type: Boolean })\n submitting: boolean;\n\n @property({ type: Boolean })\n active: boolean;\n\n @property({ type: Boolean })\n small: boolean;\n\n @property({ type: Boolean })\n lined: boolean;\n\n @property({ type: String })\n href: string;\n\n @property({ type: Number })\n index?: number;\n\n @property({ type: String })\n icon?: string;\n\n private handleClick(evt: MouseEvent) {\n if (this.disabled) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n if (this.href && !this.disabled) {\n this.ownerDocument.location.href = this.href;\n evt.preventDefault();\n evt.stopPropagation();\n }\n }\n\n private handleKeyUp(event: KeyboardEvent): void {\n this.active = false;\n if (event.key === 'Enter') {\n this.click();\n }\n }\n\n private handleMouseDown(): void {\n if (!this.disabled && !this.submitting) {\n this.active = true;\n this.classList.add('active');\n }\n }\n\n private handleMouseUp(): void {\n this.active = false;\n this.classList.remove('active');\n }\n\n public render(): TemplateResult {\n const buttonName = this.submitting\n ? html`<div class=\"submit-animation\">\n <temba-loading units=\"3\" size=\"8\" color=\"#eee\"></temba-loading>\n </div>`\n : this.name;\n\n return html`\n <div\n class=\"button-container \n v-${this.v}\n ${getClasses({\n 'primary-button':\n this.primary ||\n (!this.primary &&\n !this.secondary &&\n !this.attention &&\n this.v == 1),\n 'secondary-button': this.secondary,\n 'disabled-button': this.disabled,\n 'active-button': this.active,\n 'attention-button': this.attention,\n 'destructive-button': this.destructive,\n 'light-button': this.light,\n 'lined-button': this.lined,\n 'icon-button': !!this.icon,\n small: this.small\n })}\"\n tabindex=\"0\"\n @mousedown=${this.handleMouseDown}\n @mouseup=${this.handleMouseUp}\n @mouseleave=${this.handleMouseUp}\n @keyup=${this.handleKeyUp}\n @click=${this.handleClick}\n >\n <div class=\"button-mask\">\n ${this.icon\n ? html`<temba-icon name=\"${this.icon}\"></temba-icon>`\n : null}\n <div class=\"button-name\"><slot name=\"name\">${buttonName}</slot></div>\n </div>\n </div>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/button/Button.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, TemplateResult, html, css } from 'lit';\nimport { getClasses } from '../utils';\n\nimport { property } from 'lit/decorators.js';\n\nexport class Button extends LitElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n align-self: stretch;\n font-family: var(--font-family);\n font-weight: 400;\n }\n\n .small {\n font-size: 0.8em;\n --button-y: 0px;\n --button-x: 0.5em;\n }\n\n .v-2.button-container {\n background: var(--button-bg);\n background-image: var(--button-bg-img);\n color: var(--button-text);\n box-shadow: var(--button-shadow);\n transition: all calc(var(--transition-speed) / 2) ease-in;\n }\n\n .button-container {\n color: #fff;\n cursor: pointer;\n display: flex;\n flex-grow: 1;\n border-radius: var(--curvature);\n outline: none;\n transition: background ease-in var(--transition-speed);\n user-select: none;\n -webkit-user-select: none;\n text-align: center;\n border: var(--button-border, none);\n }\n\n .button-name {\n white-space: nowrap;\n }\n\n .secondary-button:hover .button-mask {\n border: 1px solid var(--color-button-secondary);\n }\n\n .button-mask:hover {\n background: rgba(0, 0, 0, 0.05);\n }\n\n .button-container:focus {\n outline: none;\n margin: 0;\n }\n\n .button-container:focus {\n box-shadow: var(--widget-box-shadow-focused);\n }\n\n .button-container.secondary-button:focus .button-mask {\n background: transparent;\n }\n\n .button-mask {\n padding: var(--button-y) var(--button-x);\n border-radius: var(--curvature);\n border: 1px solid transparent;\n transition: var(--transition-speed);\n background: var(--button-mask);\n display: flex;\n align-items: center;\n }\n\n .button-container.disabled-button {\n background: rgba(0, 0, 0, 0.05);\n color: rgba(255, 255, 255, 0.45);\n cursor: default;\n }\n\n .button-container.disabled-button .button-mask {\n box-shadow: 0 0 0px 1px var(--color-button-disabled);\n }\n\n .button-container.disabled-button:hover .button-mask {\n box-shadow: 0 0 0px 1px var(--color-button-disabled);\n background: rgba(0, 0, 0, 0.05);\n }\n\n .button-container.active-button .button-mask {\n }\n\n .secondary-button.active-button {\n background: transparent;\n color: var(--color-text);\n }\n\n .secondary-button.active-button .button-mask {\n border: none;\n }\n\n .button-container.secondary-button.active-button:focus .button-mask {\n background: transparent;\n box-shadow: none;\n }\n\n .primary-button {\n background: var(--color-button-primary);\n color: var(--color-button-primary-text);\n }\n\n .affirmative {\n background: var(--color-button-attention);\n }\n\n .light-button {\n background: var(--color-button-light);\n color: var(--color-button-light-text);\n }\n\n .lined-button {\n border: 1px solid rgba(0, 0, 0, 0.1);\n color: rgba(0, 0, 0, 0.7);\n background: transparent;\n }\n\n .lined-button .button-mask:hover {\n background: rgba(0, 0, 0, 0.03);\n }\n\n .icon-button {\n --button-y: 0.2em;\n --button-x: 0em;\n }\n\n .icon-button temba-icon {\n padding: 0 0.5em;\n }\n\n .attention-button {\n background: var(--color-button-attention);\n color: var(--color-button-primary-text);\n }\n\n .secondary-button {\n background: transparent;\n color: var(--color-text);\n }\n\n .destructive-button {\n background: var(--color-button-destructive);\n color: var(--color-button-destructive-text);\n }\n\n .button-mask.disabled-button {\n background: rgba(0, 0, 0, 0.1);\n }\n\n .secondary-button .button-mask:hover {\n background: transparent;\n }\n\n .submit-animation {\n padding: 1px 4px;\n }\n\n .submit-animation temba-loading {\n margin-bottom: -3px;\n line-height: normal;\n }\n `;\n }\n\n @property({ type: Boolean })\n primary: boolean;\n\n @property({ type: Boolean })\n secondary: boolean;\n\n @property({ type: Boolean })\n attention: boolean;\n\n @property({ type: Number })\n v = 1;\n\n @property({ type: Boolean })\n destructive: boolean;\n\n @property({ type: Boolean })\n light: boolean;\n\n @property()\n name: string;\n\n @property({ type: Boolean })\n disabled: boolean;\n\n @property({ type: Boolean })\n submitting: boolean;\n\n @property({ type: Boolean })\n active: boolean;\n\n @property({ type: Boolean })\n small: boolean;\n\n @property({ type: Boolean })\n lined: boolean;\n\n @property({ type: String })\n href: string;\n\n @property({ type: Number })\n index?: number;\n\n @property({ type: String })\n icon?: string;\n\n private handleClick(evt: MouseEvent) {\n if (this.disabled) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n if (this.href && !this.disabled) {\n this.ownerDocument.location.href = this.href;\n evt.preventDefault();\n evt.stopPropagation();\n }\n }\n\n private handleKeyUp(event: KeyboardEvent): void {\n this.active = false;\n if (event.key === 'Enter') {\n this.click();\n }\n }\n\n private handleMouseDown(): void {\n if (!this.disabled && !this.submitting) {\n this.active = true;\n this.classList.add('active');\n }\n }\n\n private handleMouseUp(): void {\n this.active = false;\n this.classList.remove('active');\n }\n\n public render(): TemplateResult {\n const buttonName = this.submitting\n ? html`<div class=\"submit-animation\">\n <temba-loading units=\"3\" size=\"8\" color=\"#eee\"></temba-loading>\n </div>`\n : this.name;\n\n return html`\n <div\n class=\"button-container \n v-${this.v}\n ${getClasses({\n 'primary-button':\n this.primary ||\n (!this.primary &&\n !this.secondary &&\n !this.attention &&\n this.v == 1),\n 'secondary-button': this.secondary,\n 'disabled-button': this.disabled,\n 'active-button': this.active,\n 'attention-button': this.attention,\n 'destructive-button': this.destructive,\n 'light-button': this.light,\n 'lined-button': this.lined,\n 'icon-button': !!this.icon,\n small: this.small\n })}\"\n tabindex=\"0\"\n @mousedown=${this.handleMouseDown}\n @mouseup=${this.handleMouseUp}\n @mouseleave=${this.handleMouseUp}\n @keyup=${this.handleKeyUp}\n @click=${this.handleClick}\n >\n <div class=\"button-mask\">\n ${this.icon\n ? html`<temba-icon name=\"${this.icon}\"></temba-icon>`\n : null}\n <div class=\"button-name\"><slot name=\"name\">${buttonName}</slot></div>\n </div>\n </div>\n `;\n }\n}\n"]}
@@ -48,6 +48,22 @@ export class Chat extends RapidElement {
48
48
  z-index: 1;
49
49
  }
50
50
 
51
+ slot[name='header'] {
52
+ position: absolute;
53
+ top: 0;
54
+ left: 0;
55
+ right: 0;
56
+ display: block;
57
+ }
58
+
59
+ slot[name='footer'] {
60
+ position: absolute;
61
+ bottom: 0;
62
+ left: 0;
63
+ right: 0;
64
+ display: block;
65
+ }
66
+
51
67
  .block {
52
68
  margin-bottom: 1em;
53
69
  display: flex;
@@ -148,6 +164,7 @@ export class Chat extends RapidElement {
148
164
  padding-bottom: 0.25em;
149
165
  background: var(--color-chat-in, #f1f1f1);
150
166
  border-radius: var(--curvature);
167
+ border: var(--chat-border-in, none);
151
168
  }
152
169
 
153
170
  .bubble .name {
@@ -167,6 +184,7 @@ export class Chat extends RapidElement {
167
184
 
168
185
  .incoming .bubble {
169
186
  background: var(--color-chat-out, #3c92dd);
187
+ border: var(--chat-border-out, none);
170
188
  color: white;
171
189
  }
172
190
 
@@ -216,7 +234,6 @@ export class Chat extends RapidElement {
216
234
  }
217
235
 
218
236
  .messages {
219
- background: #fff;
220
237
  position: relative;
221
238
  flex-grow: 1;
222
239
  overflow: hidden;
@@ -233,6 +250,7 @@ export class Chat extends RapidElement {
233
250
  -webkit-overflow-scrolling: touch;
234
251
  overflow-scrolling: touch;
235
252
  padding: 1em 1em 1em 1em;
253
+ padding-bottom: 2.5em;
236
254
  display: flex;
237
255
  flex-direction: column-reverse;
238
256
  }
@@ -593,7 +611,7 @@ export class Chat extends RapidElement {
593
611
  }
594
612
  }
595
613
  renderMessageGroup(msgIds, idx, groups) {
596
- var _a, _b;
614
+ var _a, _b, _c;
597
615
  const today = new Date();
598
616
  const firstGroup = idx === groups.length - 1;
599
617
  let prevMsg;
@@ -648,11 +666,13 @@ export class Chat extends RapidElement {
648
666
  </div>
649
667
  ${showAvatar
650
668
  ? html `<div class="avatar" style="align-self:flex-end">
651
- ${email
652
- ? html `<temba-user email=${email}></temba-user>`
653
- : name
654
- ? html `<temba-user fullname=${name}></temba-user>`
655
- : html `<temba-user system></temba-user>`}
669
+ <temba-user
670
+ email=${email}
671
+ name=${name}
672
+ avatar=${(_c = currentMsg.user) === null || _c === void 0 ? void 0 : _c.avatar}
673
+ ?system=${!email && !name}
674
+ >
675
+ </temba-user>
656
676
  </div>`
657
677
  : null}
658
678
  </div>
@@ -717,6 +737,8 @@ export class Chat extends RapidElement {
717
737
  class="${!this.fetching ? 'hidden' : ''}"
718
738
  ></temba-loading>
719
739
  </div>
740
+ <slot class="header" name="header"></slot>
741
+ <slot class="footer" name="footer"></slot>
720
742
  </div>`;
721
743
  }
722
744
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/chat/Chat.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, html, PropertyValueMap, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { DEFAULT_AVATAR } from '../webchat/assets';\nimport { hashCode } from '../utils';\nimport { renderMarkdown } from '../markdown';\n\nconst BATCH_TIME_WINDOW = 60 * 60 * 1000;\nconst SCROLL_FETCH_BUFFER = 0.05;\nconst MIN_FETCH_TIME = 250;\n\nexport enum MessageType {\n Inline = 'inline',\n Error = 'error',\n Collapse = 'collapse',\n Note = 'note',\n MsgIn = 'msg_in',\n MsgOut = 'msg_out'\n}\n\ninterface User {\n avatar?: string;\n email: string;\n name: string;\n}\n\nexport interface ChatEvent {\n id?: string;\n type: MessageType;\n text: string;\n date: Date;\n user?: User;\n popup?: TemplateResult;\n}\n\nexport interface Message extends ChatEvent {\n sendError?: boolean;\n attachments?: string[];\n}\n\nconst TIME_FORMAT = { hour: 'numeric', minute: '2-digit' } as any;\nconst VERBOSE_FORMAT = {\n weekday: undefined,\n year: undefined,\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n} as any;\n\nexport class Chat extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n position: relative;\n z-index: 1;\n }\n\n .block {\n margin-bottom: 1em;\n display: flex;\n flex-direction: row;\n }\n\n .block.outgoing {\n flex-direction: row-reverse;\n }\n\n .block.collapse {\n margin: 0;\n align-items: center;\n display: flex;\n flex-direction: column;\n margin-bottom: 0.5em;\n }\n\n .block.collapse .messsage {\n transform: scaleY(0);\n margin: 0;\n padding: 0;\n line-height: 0;\n }\n\n .time {\n text-align: center;\n font-size: 0.8em;\n color: #999;\n margin-top: 2em;\n border-top: 1px solid #e9e9e9;\n padding: 1em;\n margin-left: 10%;\n margin-right: 10%;\n }\n\n .time.first {\n border-top: none;\n margin-top: 0;\n border-bottom: 1px solid #e9e9e9;\n margin-bottom: 2em;\n }\n\n .first .time {\n margin-top: 0;\n border-top: none;\n padding-top: 0;\n }\n\n .row {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n margin-bottom: 0.25em;\n }\n\n .input-panel {\n padding: 1em;\n background: #fff;\n }\n\n temba-user {\n margin-right: 0.6em;\n margin-left: 0.6em;\n width: 2em;\n align-self: flex-end;\n }\n\n .toggle {\n flex-shrink: 0;\n width: 4em;\n height: 4em;\n overflow: hidden;\n border-radius: 100%;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.1);\n cursor: pointer;\n transition: box-shadow var(--toggle-speed, 200ms) ease-out;\n position: absolute;\n bottom: 1em;\n right: 1em;\n }\n\n .toggle:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.4) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.2);\n }\n\n .incoming .row {\n flex-direction: row-reverse;\n margin-left: 1em;\n }\n\n .bubble {\n padding: 0.75em;\n padding-bottom: 0.25em;\n background: var(--color-chat-in, #f1f1f1);\n border-radius: var(--curvature);\n }\n\n .bubble .name {\n font-size: 0.95em;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.4);\n margin-bottom: 0.25em;\n }\n\n .outgoing .latest .bubble {\n border-bottom-left-radius: 0;\n }\n\n .incoming .bubble-wrap {\n align-items: flex-end;\n }\n\n .incoming .bubble {\n background: var(--color-chat-out, #3c92dd);\n color: white;\n }\n\n .incoming .latest .bubble {\n border-bottom-right-radius: 0;\n }\n\n .incoming .bubble .name {\n color: rgba(255, 255, 255, 0.7);\n }\n\n .note .bubble {\n background: #fffac3;\n color: rgba(0, 0, 0, 0.7);\n }\n\n .note .bubble .name {\n color: rgba(0, 0, 0, 0.5);\n }\n\n .message {\n margin-bottom: 0.5em;\n line-height: 1.2em;\n word-break: break-word;\n }\n\n .chat {\n width: 28rem;\n border-radius: var(--curvature);\n overflow: hidden;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, rgba(0, 0, 0, 0.1) 5em 5em 5em 5em;\n position: absolute;\n bottom: 3em;\n right: 1em;\n transition: all var(--toggle-speed, 200ms) ease-out;\n transform: scale(0.9);\n pointer-events: none;\n opacity: 0;\n }\n\n .chat.open {\n bottom: 6em;\n opacity: 1;\n transform: scale(1);\n pointer-events: initial;\n }\n\n .messages {\n background: #fff;\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n }\n\n .scroll {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overflow-scrolling: touch;\n padding: 1em 1em 1em 1em;\n display: flex;\n flex-direction: column-reverse;\n }\n\n .messages:before {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 0,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center top;\n height: 10px;\n display: block;\n position: absolute;\n width: 100%;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .messages:after {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 100%,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center bottom;\n height: 10px;\n display: block;\n position: absolute;\n bottom: 0;\n margin-top: -10px;\n width: 100%;\n margin-right: 5em;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .bubble-wrap {\n position: relative;\n max-width: 70%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-top: -1em;\n padding-top: 1em;\n }\n\n .scroll-at-top.messages:before {\n opacity: 0;\n }\n\n .scroll-at-bottom.messages:after {\n opacity: 0;\n }\n\n .input {\n border: none;\n flex-grow: 1;\n color: #333;\n font-size: 1em;\n }\n\n .input:focus {\n outline: none;\n }\n\n input::placeholder {\n opacity: 0.3;\n }\n\n .input.inactive {\n // pointer-events: none;\n // opacity: 0.3;\n }\n\n .active {\n }\n\n .send-icon {\n color: #eee;\n pointer-events: none;\n transform: rotate(-45deg);\n transition: transform 0.2s ease-out;\n }\n\n .pending .send-icon {\n color: var(--color-primary-dark);\n pointer-events: initial;\n transform: rotate(0deg);\n }\n\n .notice {\n padding: 1em;\n background: #f8f8f8;\n color: #666;\n text-align: center;\n cursor: pointer;\n }\n\n .connecting .notice {\n display: flex;\n justify-content: center;\n }\n\n .connecting .notice temba-icon {\n margin-left: 0.5em;\n }\n\n .reconnect {\n color: var(--color-primary-dark);\n text-decoration: underline;\n font-size: 0.9em;\n }\n\n .input:disabled {\n background: transparent !important;\n }\n\n temba-loading {\n justify-content: center;\n margin: 0.5em auto;\n margin-bottom: 2em;\n }\n\n temba-loading.hidden {\n display: none;\n }\n\n .inline {\n }\n\n .event {\n flex-grow: 1;\n align-self: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .event p {\n margin: 0;\n padding: 0;\n }\n\n .collapse {\n }\n\n a {\n color: var(--color-primary-dark);\n }\n\n .attachments {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n align-self: flex-start;\n }\n\n .incoming .attachments {\n align-self: flex-end;\n }\n\n temba-thumbnail {\n margin: 0.4em;\n border-radius: var(--curvature);\n }\n\n .error .bubble {\n border: 1px solid var(--color-error);\n background: white;\n color: #333;\n }\n\n .error .bubble .name {\n color: #999;\n }\n\n .error temba-thumbnail {\n --thumb-background: var(--color-error);\n --thumb-icon: white;\n }\n\n .outgoing .popup {\n justify-content: left;\n }\n\n .incoming .popup {\n justify-content: right;\n }\n\n .popup {\n display: flex;\n position: absolute;\n background: #fff;\n margin: 0;\n padding: 0.5em 1em;\n border-radius: var(--curvature);\n box-shadow: rgba(0, 0, 0, 0.05) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n border: 1px solid #f3f3f3;\n opacity: 0;\n transform: scale(0.7);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n z-index: 2;\n }\n\n .popup .arrow {\n z-index: 1;\n text-shadow: 0px 3px 3px rgba(0, 0, 0, 0.1);\n position: absolute;\n justify-content: center;\n text-align: center;\n font-size: 1.3em;\n transform: translateY(0.7em) scale(1);\n color: #fff;\n bottom: 0;\n }\n\n .bubble-wrap:hover .popup {\n transform: translateY(-120%);\n opacity: 1;\n transition-delay: 1s;\n }\n `;\n }\n\n @property({ type: Array })\n messageGroups: string[][] = [];\n\n @property({ type: Boolean })\n fetching = false;\n\n @property({ type: Boolean, attribute: false })\n hideTopScroll = true;\n\n @property({ type: Boolean, attribute: false })\n hideBottomScroll = true;\n\n @property({ type: String, attribute: 'avatar' })\n defaultAvatar = DEFAULT_AVATAR;\n\n @property({ type: Boolean })\n agent = false;\n\n private msgMap = new Map<string, ChatEvent>();\n\n public firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const scroll = this.shadowRoot.querySelector('.scroll');\n const hasScroll = scroll.scrollHeight > scroll.clientHeight;\n this.hideBottomScroll = true;\n this.hideTopScroll = !hasScroll;\n }\n\n public addMessages(\n messages: ChatEvent[],\n startTime: Date = null,\n append = false\n ) {\n // make sure our messages have ids\n messages.forEach((m) => {\n if (!m.id) {\n m.id = hashCode(m.text) + '_' + m.date.toISOString();\n }\n });\n\n if (!startTime) {\n startTime = new Date();\n }\n\n const elapsed = new Date().getTime() - startTime.getTime();\n window.setTimeout(\n () => {\n this.fetching = false;\n // first add messages to the map\n const newMessages = [];\n for (const m of messages) {\n if (this.addMessage(m)) {\n newMessages.push(m.id);\n }\n }\n\n if (newMessages.length === 0) {\n return;\n }\n\n const ele = this.shadowRoot.querySelector('.scroll');\n const prevTop = ele.scrollTop;\n\n const grouped = this.groupMessages(newMessages);\n this.insertGroups(grouped, append);\n\n window.setTimeout(() => {\n ele.scrollTop = prevTop;\n\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }, 100);\n },\n // if it's the first load don't wait, otherwise wait a minimum amount of time\n this.messageGroups.length === 0\n ? 0\n : Math.max(0, MIN_FETCH_TIME - elapsed)\n );\n }\n\n private addMessage(msg: ChatEvent): boolean {\n const isNew = !this.messageExists(msg);\n this.msgMap.set(msg.id, msg);\n return isNew;\n }\n\n public messageExists(msg: ChatEvent): boolean {\n return this.msgMap.has(msg.id);\n }\n\n private isSameGroup(msg1: ChatEvent, msg2: ChatEvent): boolean {\n if (msg1 && msg2) {\n return (\n msg1.type === msg2.type &&\n msg1.user?.name === msg2.user?.name &&\n Math.abs(msg1.date.getTime() - msg2.date.getTime()) < BATCH_TIME_WINDOW\n );\n }\n\n return false;\n }\n\n private insertGroups(newGroups: string[][], append = false) {\n if (!append) {\n newGroups.reverse();\n }\n\n for (const newGroup of newGroups) {\n // see if our new group belongs to the most recent group\n const group =\n this.messageGroups[append ? 0 : this.messageGroups.length - 1];\n\n if (group) {\n const lastMsgId = group[group.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup[0]);\n // if our message belongs to the previous group, in we go\n if (this.isSameGroup(lastMsg, newMsg)) {\n group.push(...newGroup);\n } else {\n // otherwise, just add our entire group as a new one\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n } else {\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n }\n\n this.requestUpdate('messageGroups');\n }\n\n private groupMessages(msgIds: string[]): string[][] {\n // group our messages by origin and user\n const groups = [];\n let lastGroup = [];\n let lastMsg = null;\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n if (!this.isSameGroup(msg, lastMsg)) {\n lastGroup = [];\n groups.push(lastGroup);\n }\n lastGroup.push(msgId);\n lastMsg = msg;\n }\n return groups;\n }\n\n private handleScroll(event: any) {\n const ele = event.target;\n const top = ele.scrollHeight - ele.clientHeight;\n const scroll = Math.round(top + ele.scrollTop);\n const scrollPct = scroll / top;\n\n this.hideTopScroll = scrollPct <= 0.01;\n this.hideBottomScroll = scrollPct >= 0.99;\n\n if (scrollPct < SCROLL_FETCH_BUFFER) {\n this.fireCustomEvent(CustomEventType.ScrollThreshold);\n }\n }\n\n private scrollToBottom() {\n const scroll = this.shadowRoot.querySelector('.scroll');\n if (scroll) {\n scroll.scrollTop = scroll.scrollHeight;\n this.hideBottomScroll = true;\n }\n }\n\n private renderMessageGroup(\n msgIds: string[],\n idx: number,\n groups: string[][]\n ): TemplateResult {\n const today = new Date();\n const firstGroup = idx === groups.length - 1;\n\n let prevMsg: ChatEvent;\n if (idx > 0) {\n const lastGroup = groups[idx - 1];\n if (lastGroup && lastGroup.length > 0) {\n prevMsg = this.msgMap.get(lastGroup[0]);\n }\n }\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\n let timeDisplay = null;\n if (\n prevMsg &&\n !this.isSameGroup(prevMsg, currentMsg) &&\n (Math.abs(currentMsg.date.getTime() - prevMsg.date.getTime()) >\n BATCH_TIME_WINDOW ||\n idx === groups.length - 1)\n ) {\n if (\n today.getDate() !== prevMsg.date.getDate() ||\n prevMsg.date.getDate() !== currentMsg.date.getDate()\n ) {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, VERBOSE_FORMAT)}\n </div>`;\n } else {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, TIME_FORMAT)}\n </div>`;\n }\n }\n\n const incoming = this.agent\n ? currentMsg.type !== 'msg_in'\n : currentMsg.type === 'msg_in';\n\n const name = currentMsg.user?.name;\n const email = currentMsg.user?.email;\n\n const showAvatar =\n ((currentMsg.type === 'note' ||\n currentMsg.type === 'msg_in' ||\n currentMsg.type === 'msg_out') &&\n this.agent) ||\n !incoming;\n\n return html`\n ${!firstGroup ? timeDisplay : null}\n <div\n class=\"block ${incoming ? 'incoming' : 'outgoing'} ${currentMsg.type}\"\n >\n <div class=\"group-messages\" style=\"flex-grow:1\">\n ${msgIds.map((msgId, index) => {\n const msg = this.msgMap.get(msgId);\n return html`<div class=\"row message\">\n ${this.renderMessage(msg, index == 0 ? name : null)}\n </div>`;\n })}\n </div>\n ${showAvatar\n ? html`<div class=\"avatar\" style=\"align-self:flex-end\">\n ${email\n ? html`<temba-user email=${email}></temba-user>`\n : name\n ? html`<temba-user fullname=${name}></temba-user>`\n : html`<temba-user system></temba-user>`}\n </div>`\n : null}\n </div>\n ${firstGroup ? timeDisplay : null}\n `;\n }\n\n private renderMessage(event: ChatEvent, name = null): TemplateResult {\n if (\n event.type === MessageType.Error ||\n event.type === MessageType.Collapse ||\n event.type === MessageType.Inline\n ) {\n return html`<div class=\"event\">${renderMarkdown(event.text)}</div>`;\n }\n\n const message = event as Message;\n return html`\n <div class=\"bubble-wrap ${message.sendError ? 'error' : ''}\">\n ${\n message.popup\n ? html`<div class=\"popup\">\n ${message.popup}\n <div class=\"arrow\">▼</div>\n </div>`\n : null\n }\n \n ${\n message.text\n ? html`\n <div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message\">${message.text}</div>\n\n <!--div>${message.date.toLocaleDateString(\n undefined,\n VERBOSE_FORMAT\n )}</div-->\n </div>\n `\n : null\n }\n\n <div class=\"attachments\">\n ${(message.attachments || []).map(\n (attachment) =>\n html`<temba-thumbnail\n attachment=\"${attachment}\"\n ></temba-thumbnail>`\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n public reset() {\n this.msgMap.clear();\n this.messageGroups = [];\n this.hideBottomScroll = true;\n this.hideTopScroll = true;\n }\n\n public render(): TemplateResult {\n return html` <div\n class=\"\n messages \n ${this.hideBottomScroll ? 'scroll-at-bottom' : ''}\n ${this.hideTopScroll ? 'scroll-at-top' : ''}\"\n >\n <div class=\"scroll\" @scroll=${this.handleScroll}>\n ${this.messageGroups\n ? this.messageGroups.map(\n (msgGroup, idx, groups) =>\n html`${this.renderMessageGroup(msgGroup, idx, groups)}`\n )\n : null}\n\n <temba-loading\n class=\"${!this.fetching ? 'hidden' : ''}\"\n ></temba-loading>\n </div>\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../../src/chat/Chat.ts"],"names":[],"mappings":";AAAA,OAAO,EAAkB,IAAI,EAAoB,GAAG,EAAE,MAAM,KAAK,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACzC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACjC,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B,MAAM,CAAN,IAAY,WAOX;AAPD,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,oCAAqB,CAAA;IACrB,4BAAa,CAAA;IACb,+BAAgB,CAAA;IAChB,iCAAkB,CAAA;AACpB,CAAC,EAPW,WAAW,KAAX,WAAW,QAOtB;AAsBD,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAS,CAAC;AAClE,MAAM,cAAc,GAAG;IACrB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;CACX,CAAC;AAET,MAAM,OAAO,IAAK,SAAQ,YAAY;IAAtC;;QA4bE,kBAAa,GAAe,EAAE,CAAC;QAG/B,aAAQ,GAAG,KAAK,CAAC;QAGjB,kBAAa,GAAG,IAAI,CAAC;QAGrB,qBAAgB,GAAG,IAAI,CAAC;QAGxB,kBAAa,GAAG,cAAc,CAAC;QAG/B,UAAK,GAAG,KAAK,CAAC;QAEN,WAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;IAoUhD,CAAC;IAhxBC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsbT,CAAC;IACJ,CAAC;IAsBM,YAAY,CACjB,OAA0D;QAE1D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QAC5D,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,CAAC,SAAS,CAAC;IAClC,CAAC;IAEM,WAAW,CAChB,QAAqB,EACrB,YAAkB,IAAI,EACtB,MAAM,GAAG,KAAK;QAEd,kCAAkC;QAClC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACrB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACV,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACvD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;QAC3D,MAAM,CAAC,UAAU,CACf,GAAG,EAAE;YACH,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,gCAAgC;YAChC,MAAM,WAAW,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YACrD,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC;YAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;YAChD,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAEnC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;gBACrB,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC;gBAExB,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;YACtD,CAAC,EAAE,GAAG,CAAC,CAAC;QACV,CAAC;QACD,6EAA6E;QAC7E,IAAI,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC;YAC7B,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAC1C,CAAC;IACJ,CAAC;IAEO,UAAU,CAAC,GAAc;QAC/B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,aAAa,CAAC,GAAc;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAEO,WAAW,CAAC,IAAe,EAAE,IAAe;;QAClD,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACjB,OAAO,CACL,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;gBACvB,CAAA,MAAA,IAAI,CAAC,IAAI,0CAAE,IAAI,OAAK,MAAA,IAAI,CAAC,IAAI,0CAAE,IAAI,CAAA;gBACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,iBAAiB,CACxE,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,YAAY,CAAC,SAAqB,EAAE,MAAM,GAAG,KAAK;QACxD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAS,CAAC,OAAO,EAAE,CAAC;QACtB,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,wDAAwD;YACxD,MAAM,KAAK,GACT,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAEjE,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,yDAAyD;gBACzD,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;oBACtC,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACN,oDAAoD;oBACpD,IAAI,MAAM,EAAE,CAAC;wBACX,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;oBAC5C,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACpC,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,MAAM,EAAE,CAAC;oBACX,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;gBAC5C,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;IACtC,CAAC;IAEO,aAAa,CAAC,MAAgB;QACpC,wCAAwC;QACxC,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;gBACpC,SAAS,GAAG,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzB,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,OAAO,GAAG,GAAG,CAAC;QAChB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,YAAY,CAAC,KAAU;QAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;QACzB,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,MAAM,GAAG,GAAG,CAAC;QAE/B,IAAI,CAAC,aAAa,GAAG,SAAS,IAAI,IAAI,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,SAAS,IAAI,IAAI,CAAC;QAE1C,IAAI,SAAS,GAAG,mBAAmB,EAAE,CAAC;YACpC,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACxD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC;YACvC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,kBAAkB,CACxB,MAAgB,EAChB,GAAW,EACX,MAAkB;;QAElB,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,GAAG,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAE7C,IAAI,OAAkB,CAAC;QACvB,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAClC,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,WAAW,GAAG,IAAI,CAAC;QACvB,IACE,OAAO;YACP,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC;YACtC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC3D,iBAAiB;gBACjB,GAAG,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EAC5B,CAAC;YACD,IACE,KAAK,CAAC,OAAO,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE;gBAC1C,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,EACpD,CAAC;gBACD,WAAW,GAAG,IAAI,CAAA,oBAAoB,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YAC3D,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,cAAc,CAAC;eACvD,CAAC;YACV,CAAC;iBAAM,CAAC;gBACN,WAAW,GAAG,IAAI,CAAA,oBAAoB,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YAC3D,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC;eACpD,CAAC;YACV,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK;YACzB,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,QAAQ;YAC9B,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,QAAQ,CAAC;QAEjC,MAAM,IAAI,GAAG,MAAA,UAAU,CAAC,IAAI,0CAAE,IAAI,CAAC;QACnC,MAAM,KAAK,GAAG,MAAA,UAAU,CAAC,IAAI,0CAAE,KAAK,CAAC;QAErC,MAAM,UAAU,GACd,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,MAAM;YAC1B,UAAU,CAAC,IAAI,KAAK,QAAQ;YAC5B,UAAU,CAAC,IAAI,KAAK,SAAS,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC;YACb,CAAC,QAAQ,CAAC;QAEZ,OAAO,IAAI,CAAA;QACP,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;;wBAEhB,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,IAAI;;;YAGjE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnC,OAAO,IAAI,CAAA;gBACP,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;mBAC9C,CAAC;QACV,CAAC,CAAC;;UAEF,UAAU;YACV,CAAC,CAAC,IAAI,CAAA;;wBAEQ,KAAK;uBACN,IAAI;yBACF,MAAA,UAAU,CAAC,IAAI,0CAAE,MAAM;0BACtB,CAAC,KAAK,IAAI,CAAC,IAAI;;;mBAGtB;YACT,CAAC,CAAC,IAAI;;QAER,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;KAClC,CAAC;IACJ,CAAC;IAEO,aAAa,CAAC,KAAgB,EAAE,IAAI,GAAG,IAAI;QACjD,IACE,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,KAAK;YAChC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,QAAQ;YACnC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,MAAM,EACjC,CAAC;YACD,OAAO,IAAI,CAAA,sBAAsB,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;QACtE,CAAC;QAED,MAAM,OAAO,GAAG,KAAgB,CAAC;QACjC,OAAO,IAAI,CAAA;kCACmB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;UAExD,OAAO,CAAC,KAAK;YACX,CAAC,CAAC,IAAI,CAAA;kBACA,OAAO,CAAC,KAAK;;qBAEV;YACT,CAAC,CAAC,IACN;;YAGI,OAAO,CAAC,IAAI;YACV,CAAC,CAAC,IAAI,CAAA;;sBAEE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,qBAAqB,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI;2CAC9B,OAAO,CAAC,IAAI;;8BAEzB,OAAO,CAAC,IAAI,CAAC,kBAAkB,CACvC,SAAS,EACT,cAAc,CACf;;iBAEJ;YACH,CAAC,CAAC,IACN;;;cAGI,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAC/B,CAAC,UAAU,EAAE,EAAE,CACb,IAAI,CAAA;gCACY,UAAU;oCACN,CACvB;;;;KAIR,CAAC;IACJ,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAA;;;UAGL,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE;UAC/C,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;;oCAEf,IAAI,CAAC,YAAY;UAC3C,IAAI,CAAC,aAAa;YAClB,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CACpB,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CACxB,IAAI,CAAA,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,CAC1D;YACH,CAAC,CAAC,IAAI;;;mBAGG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;;;;;WAKtC,CAAC;IACV,CAAC;CACF;AArVC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;2CACK;AAG/B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;sCACX;AAGjB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;2CACzB;AAGrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;8CACtB;AAGxB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;2CACjB;AAG/B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;mCACd","sourcesContent":["import { TemplateResult, html, PropertyValueMap, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { DEFAULT_AVATAR } from '../webchat/assets';\nimport { hashCode } from '../utils';\nimport { renderMarkdown } from '../markdown';\n\nconst BATCH_TIME_WINDOW = 60 * 60 * 1000;\nconst SCROLL_FETCH_BUFFER = 0.05;\nconst MIN_FETCH_TIME = 250;\n\nexport enum MessageType {\n Inline = 'inline',\n Error = 'error',\n Collapse = 'collapse',\n Note = 'note',\n MsgIn = 'msg_in',\n MsgOut = 'msg_out'\n}\n\ninterface User {\n avatar?: string;\n email: string;\n name: string;\n}\n\nexport interface ChatEvent {\n id?: string;\n type: MessageType;\n text: string;\n date: Date;\n user?: User;\n popup?: TemplateResult;\n}\n\nexport interface Message extends ChatEvent {\n sendError?: boolean;\n attachments?: string[];\n}\n\nconst TIME_FORMAT = { hour: 'numeric', minute: '2-digit' } as any;\nconst VERBOSE_FORMAT = {\n weekday: undefined,\n year: undefined,\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n} as any;\n\nexport class Chat extends RapidElement {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n position: relative;\n z-index: 1;\n }\n\n slot[name='header'] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n slot[name='footer'] {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: block;\n }\n\n .block {\n margin-bottom: 1em;\n display: flex;\n flex-direction: row;\n }\n\n .block.outgoing {\n flex-direction: row-reverse;\n }\n\n .block.collapse {\n margin: 0;\n align-items: center;\n display: flex;\n flex-direction: column;\n margin-bottom: 0.5em;\n }\n\n .block.collapse .messsage {\n transform: scaleY(0);\n margin: 0;\n padding: 0;\n line-height: 0;\n }\n\n .time {\n text-align: center;\n font-size: 0.8em;\n color: #999;\n margin-top: 2em;\n border-top: 1px solid #e9e9e9;\n padding: 1em;\n margin-left: 10%;\n margin-right: 10%;\n }\n\n .time.first {\n border-top: none;\n margin-top: 0;\n border-bottom: 1px solid #e9e9e9;\n margin-bottom: 2em;\n }\n\n .first .time {\n margin-top: 0;\n border-top: none;\n padding-top: 0;\n }\n\n .row {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n margin-bottom: 0.25em;\n }\n\n .input-panel {\n padding: 1em;\n background: #fff;\n }\n\n temba-user {\n margin-right: 0.6em;\n margin-left: 0.6em;\n width: 2em;\n align-self: flex-end;\n }\n\n .toggle {\n flex-shrink: 0;\n width: 4em;\n height: 4em;\n overflow: hidden;\n border-radius: 100%;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.1);\n cursor: pointer;\n transition: box-shadow var(--toggle-speed, 200ms) ease-out;\n position: absolute;\n bottom: 1em;\n right: 1em;\n }\n\n .toggle:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 1em 0.7em,\n rgba(0, 0, 0, 0.4) 0px 1px 2px 0px,\n inset 0 0 0 0.25em rgba(0, 0, 0, 0.2);\n }\n\n .incoming .row {\n flex-direction: row-reverse;\n margin-left: 1em;\n }\n\n .bubble {\n padding: 0.75em;\n padding-bottom: 0.25em;\n background: var(--color-chat-in, #f1f1f1);\n border-radius: var(--curvature);\n border: var(--chat-border-in, none);\n }\n\n .bubble .name {\n font-size: 0.95em;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.4);\n margin-bottom: 0.25em;\n }\n\n .outgoing .latest .bubble {\n border-bottom-left-radius: 0;\n }\n\n .incoming .bubble-wrap {\n align-items: flex-end;\n }\n\n .incoming .bubble {\n background: var(--color-chat-out, #3c92dd);\n border: var(--chat-border-out, none);\n color: white;\n }\n\n .incoming .latest .bubble {\n border-bottom-right-radius: 0;\n }\n\n .incoming .bubble .name {\n color: rgba(255, 255, 255, 0.7);\n }\n\n .note .bubble {\n background: #fffac3;\n color: rgba(0, 0, 0, 0.7);\n }\n\n .note .bubble .name {\n color: rgba(0, 0, 0, 0.5);\n }\n\n .message {\n margin-bottom: 0.5em;\n line-height: 1.2em;\n word-break: break-word;\n }\n\n .chat {\n width: 28rem;\n border-radius: var(--curvature);\n overflow: hidden;\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, rgba(0, 0, 0, 0.1) 5em 5em 5em 5em;\n position: absolute;\n bottom: 3em;\n right: 1em;\n transition: all var(--toggle-speed, 200ms) ease-out;\n transform: scale(0.9);\n pointer-events: none;\n opacity: 0;\n }\n\n .chat.open {\n bottom: 6em;\n opacity: 1;\n transform: scale(1);\n pointer-events: initial;\n }\n\n .messages {\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n }\n\n .scroll {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overflow-scrolling: touch;\n padding: 1em 1em 1em 1em;\n padding-bottom: 2.5em;\n display: flex;\n flex-direction: column-reverse;\n }\n\n .messages:before {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 0,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center top;\n height: 10px;\n display: block;\n position: absolute;\n width: 100%;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .messages:after {\n content: '';\n background: radial-gradient(\n farthest-side at 50% 100%,\n rgba(0, 0, 0, 0.2),\n rgba(0, 0, 0, 0)\n )\n center bottom;\n height: 10px;\n display: block;\n position: absolute;\n bottom: 0;\n margin-top: -10px;\n width: 100%;\n margin-right: 5em;\n transition: opacity var(--toggle-speed, 200ms) ease-out;\n z-index: 1;\n }\n\n .bubble-wrap {\n position: relative;\n max-width: 70%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-top: -1em;\n padding-top: 1em;\n }\n\n .scroll-at-top.messages:before {\n opacity: 0;\n }\n\n .scroll-at-bottom.messages:after {\n opacity: 0;\n }\n\n .input {\n border: none;\n flex-grow: 1;\n color: #333;\n font-size: 1em;\n }\n\n .input:focus {\n outline: none;\n }\n\n input::placeholder {\n opacity: 0.3;\n }\n\n .input.inactive {\n // pointer-events: none;\n // opacity: 0.3;\n }\n\n .active {\n }\n\n .send-icon {\n color: #eee;\n pointer-events: none;\n transform: rotate(-45deg);\n transition: transform 0.2s ease-out;\n }\n\n .pending .send-icon {\n color: var(--color-primary-dark);\n pointer-events: initial;\n transform: rotate(0deg);\n }\n\n .notice {\n padding: 1em;\n background: #f8f8f8;\n color: #666;\n text-align: center;\n cursor: pointer;\n }\n\n .connecting .notice {\n display: flex;\n justify-content: center;\n }\n\n .connecting .notice temba-icon {\n margin-left: 0.5em;\n }\n\n .reconnect {\n color: var(--color-primary-dark);\n text-decoration: underline;\n font-size: 0.9em;\n }\n\n .input:disabled {\n background: transparent !important;\n }\n\n temba-loading {\n justify-content: center;\n margin: 0.5em auto;\n margin-bottom: 2em;\n }\n\n temba-loading.hidden {\n display: none;\n }\n\n .inline {\n }\n\n .event {\n flex-grow: 1;\n align-self: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .event p {\n margin: 0;\n padding: 0;\n }\n\n .collapse {\n }\n\n a {\n color: var(--color-primary-dark);\n }\n\n .attachments {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n align-self: flex-start;\n }\n\n .incoming .attachments {\n align-self: flex-end;\n }\n\n temba-thumbnail {\n margin: 0.4em;\n border-radius: var(--curvature);\n }\n\n .error .bubble {\n border: 1px solid var(--color-error);\n background: white;\n color: #333;\n }\n\n .error .bubble .name {\n color: #999;\n }\n\n .error temba-thumbnail {\n --thumb-background: var(--color-error);\n --thumb-icon: white;\n }\n\n .outgoing .popup {\n justify-content: left;\n }\n\n .incoming .popup {\n justify-content: right;\n }\n\n .popup {\n display: flex;\n position: absolute;\n background: #fff;\n margin: 0;\n padding: 0.5em 1em;\n border-radius: var(--curvature);\n box-shadow: rgba(0, 0, 0, 0.05) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n border: 1px solid #f3f3f3;\n opacity: 0;\n transform: scale(0.7);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n z-index: 2;\n }\n\n .popup .arrow {\n z-index: 1;\n text-shadow: 0px 3px 3px rgba(0, 0, 0, 0.1);\n position: absolute;\n justify-content: center;\n text-align: center;\n font-size: 1.3em;\n transform: translateY(0.7em) scale(1);\n color: #fff;\n bottom: 0;\n }\n\n .bubble-wrap:hover .popup {\n transform: translateY(-120%);\n opacity: 1;\n transition-delay: 1s;\n }\n `;\n }\n\n @property({ type: Array })\n messageGroups: string[][] = [];\n\n @property({ type: Boolean })\n fetching = false;\n\n @property({ type: Boolean, attribute: false })\n hideTopScroll = true;\n\n @property({ type: Boolean, attribute: false })\n hideBottomScroll = true;\n\n @property({ type: String, attribute: 'avatar' })\n defaultAvatar = DEFAULT_AVATAR;\n\n @property({ type: Boolean })\n agent = false;\n\n private msgMap = new Map<string, ChatEvent>();\n\n public firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const scroll = this.shadowRoot.querySelector('.scroll');\n const hasScroll = scroll.scrollHeight > scroll.clientHeight;\n this.hideBottomScroll = true;\n this.hideTopScroll = !hasScroll;\n }\n\n public addMessages(\n messages: ChatEvent[],\n startTime: Date = null,\n append = false\n ) {\n // make sure our messages have ids\n messages.forEach((m) => {\n if (!m.id) {\n m.id = hashCode(m.text) + '_' + m.date.toISOString();\n }\n });\n\n if (!startTime) {\n startTime = new Date();\n }\n\n const elapsed = new Date().getTime() - startTime.getTime();\n window.setTimeout(\n () => {\n this.fetching = false;\n // first add messages to the map\n const newMessages = [];\n for (const m of messages) {\n if (this.addMessage(m)) {\n newMessages.push(m.id);\n }\n }\n\n if (newMessages.length === 0) {\n return;\n }\n\n const ele = this.shadowRoot.querySelector('.scroll');\n const prevTop = ele.scrollTop;\n\n const grouped = this.groupMessages(newMessages);\n this.insertGroups(grouped, append);\n\n window.setTimeout(() => {\n ele.scrollTop = prevTop;\n\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }, 100);\n },\n // if it's the first load don't wait, otherwise wait a minimum amount of time\n this.messageGroups.length === 0\n ? 0\n : Math.max(0, MIN_FETCH_TIME - elapsed)\n );\n }\n\n private addMessage(msg: ChatEvent): boolean {\n const isNew = !this.messageExists(msg);\n this.msgMap.set(msg.id, msg);\n return isNew;\n }\n\n public messageExists(msg: ChatEvent): boolean {\n return this.msgMap.has(msg.id);\n }\n\n private isSameGroup(msg1: ChatEvent, msg2: ChatEvent): boolean {\n if (msg1 && msg2) {\n return (\n msg1.type === msg2.type &&\n msg1.user?.name === msg2.user?.name &&\n Math.abs(msg1.date.getTime() - msg2.date.getTime()) < BATCH_TIME_WINDOW\n );\n }\n\n return false;\n }\n\n private insertGroups(newGroups: string[][], append = false) {\n if (!append) {\n newGroups.reverse();\n }\n\n for (const newGroup of newGroups) {\n // see if our new group belongs to the most recent group\n const group =\n this.messageGroups[append ? 0 : this.messageGroups.length - 1];\n\n if (group) {\n const lastMsgId = group[group.length - 1];\n const lastMsg = this.msgMap.get(lastMsgId);\n const newMsg = this.msgMap.get(newGroup[0]);\n // if our message belongs to the previous group, in we go\n if (this.isSameGroup(lastMsg, newMsg)) {\n group.push(...newGroup);\n } else {\n // otherwise, just add our entire group as a new one\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n } else {\n if (append) {\n this.messageGroups.splice(0, 0, newGroup);\n } else {\n this.messageGroups.push(newGroup);\n }\n }\n }\n\n this.requestUpdate('messageGroups');\n }\n\n private groupMessages(msgIds: string[]): string[][] {\n // group our messages by origin and user\n const groups = [];\n let lastGroup = [];\n let lastMsg = null;\n for (const msgId of msgIds) {\n const msg = this.msgMap.get(msgId);\n if (!this.isSameGroup(msg, lastMsg)) {\n lastGroup = [];\n groups.push(lastGroup);\n }\n lastGroup.push(msgId);\n lastMsg = msg;\n }\n return groups;\n }\n\n private handleScroll(event: any) {\n const ele = event.target;\n const top = ele.scrollHeight - ele.clientHeight;\n const scroll = Math.round(top + ele.scrollTop);\n const scrollPct = scroll / top;\n\n this.hideTopScroll = scrollPct <= 0.01;\n this.hideBottomScroll = scrollPct >= 0.99;\n\n if (scrollPct < SCROLL_FETCH_BUFFER) {\n this.fireCustomEvent(CustomEventType.ScrollThreshold);\n }\n }\n\n private scrollToBottom() {\n const scroll = this.shadowRoot.querySelector('.scroll');\n if (scroll) {\n scroll.scrollTop = scroll.scrollHeight;\n this.hideBottomScroll = true;\n }\n }\n\n private renderMessageGroup(\n msgIds: string[],\n idx: number,\n groups: string[][]\n ): TemplateResult {\n const today = new Date();\n const firstGroup = idx === groups.length - 1;\n\n let prevMsg: ChatEvent;\n if (idx > 0) {\n const lastGroup = groups[idx - 1];\n if (lastGroup && lastGroup.length > 0) {\n prevMsg = this.msgMap.get(lastGroup[0]);\n }\n }\n\n const mostRecentId = msgIds[msgIds.length - 1];\n const currentMsg = this.msgMap.get(mostRecentId);\n let timeDisplay = null;\n if (\n prevMsg &&\n !this.isSameGroup(prevMsg, currentMsg) &&\n (Math.abs(currentMsg.date.getTime() - prevMsg.date.getTime()) >\n BATCH_TIME_WINDOW ||\n idx === groups.length - 1)\n ) {\n if (\n today.getDate() !== prevMsg.date.getDate() ||\n prevMsg.date.getDate() !== currentMsg.date.getDate()\n ) {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, VERBOSE_FORMAT)}\n </div>`;\n } else {\n timeDisplay = html`<div class=\"time ${firstGroup ? 'first' : ''}\">\n ${prevMsg.date.toLocaleTimeString(undefined, TIME_FORMAT)}\n </div>`;\n }\n }\n\n const incoming = this.agent\n ? currentMsg.type !== 'msg_in'\n : currentMsg.type === 'msg_in';\n\n const name = currentMsg.user?.name;\n const email = currentMsg.user?.email;\n\n const showAvatar =\n ((currentMsg.type === 'note' ||\n currentMsg.type === 'msg_in' ||\n currentMsg.type === 'msg_out') &&\n this.agent) ||\n !incoming;\n\n return html`\n ${!firstGroup ? timeDisplay : null}\n <div\n class=\"block ${incoming ? 'incoming' : 'outgoing'} ${currentMsg.type}\"\n >\n <div class=\"group-messages\" style=\"flex-grow:1\">\n ${msgIds.map((msgId, index) => {\n const msg = this.msgMap.get(msgId);\n return html`<div class=\"row message\">\n ${this.renderMessage(msg, index == 0 ? name : null)}\n </div>`;\n })}\n </div>\n ${showAvatar\n ? html`<div class=\"avatar\" style=\"align-self:flex-end\">\n <temba-user\n email=${email}\n name=${name}\n avatar=${currentMsg.user?.avatar}\n ?system=${!email && !name}\n >\n </temba-user>\n </div>`\n : null}\n </div>\n ${firstGroup ? timeDisplay : null}\n `;\n }\n\n private renderMessage(event: ChatEvent, name = null): TemplateResult {\n if (\n event.type === MessageType.Error ||\n event.type === MessageType.Collapse ||\n event.type === MessageType.Inline\n ) {\n return html`<div class=\"event\">${renderMarkdown(event.text)}</div>`;\n }\n\n const message = event as Message;\n return html`\n <div class=\"bubble-wrap ${message.sendError ? 'error' : ''}\">\n ${\n message.popup\n ? html`<div class=\"popup\">\n ${message.popup}\n <div class=\"arrow\">▼</div>\n </div>`\n : null\n }\n \n ${\n message.text\n ? html`\n <div class=\"bubble\">\n ${name ? html`<div class=\"name\">${name}</div>` : null}\n <div class=\"message\">${message.text}</div>\n\n <!--div>${message.date.toLocaleDateString(\n undefined,\n VERBOSE_FORMAT\n )}</div-->\n </div>\n `\n : null\n }\n\n <div class=\"attachments\">\n ${(message.attachments || []).map(\n (attachment) =>\n html`<temba-thumbnail\n attachment=\"${attachment}\"\n ></temba-thumbnail>`\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n public reset() {\n this.msgMap.clear();\n this.messageGroups = [];\n this.hideBottomScroll = true;\n this.hideTopScroll = true;\n }\n\n public render(): TemplateResult {\n return html` <div\n class=\"\n messages \n ${this.hideBottomScroll ? 'scroll-at-bottom' : ''}\n ${this.hideTopScroll ? 'scroll-at-top' : ''}\"\n >\n <div class=\"scroll\" @scroll=${this.handleScroll}>\n ${this.messageGroups\n ? this.messageGroups.map(\n (msgGroup, idx, groups) =>\n html`${this.renderMessageGroup(msgGroup, idx, groups)}`\n )\n : null}\n\n <temba-loading\n class=\"${!this.fetching ? 'hidden' : ''}\"\n ></temba-loading>\n </div>\n <slot class=\"header\" name=\"header\"></slot>\n <slot class=\"footer\" name=\"footer\"></slot>\n </div>`;\n }\n}\n"]}
@@ -97,8 +97,14 @@ export class Compose extends FormElement {
97
97
  }
98
98
 
99
99
  temba-tabs {
100
- --focused-tab-color: #f4f4f4;
101
- min-height: var(--compose-min-height, 13.5em);
100
+ --temba-tabs-border-bottom: none;
101
+ --temba-tabs-border-left: none;
102
+ --temba-tabs-border-right: none;
103
+ --temba-tabs-options-padding: 0.25em 0 0 0.25em;
104
+ }
105
+
106
+ temba-completion {
107
+ --textarea-min-height: 8em;
102
108
  }
103
109
 
104
110
  .quick-replies {
@@ -299,8 +305,9 @@ export class Compose extends FormElement {
299
305
  const line = text.substring(lineStart, cursor);
300
306
  if (line.startsWith('/')) {
301
307
  // switch to the shortcuts tab
302
- const tabs = this.shadowRoot.querySelector('temba-tabs');
303
- tabs.focusTab('Shortcuts');
308
+ if (this.currentTab.name !== 'Shortcuts') {
309
+ this.getTabs().focusTab('Shortcuts');
310
+ }
304
311
  const shortcuts = this.shadowRoot.querySelector('temba-shortcuts');
305
312
  shortcuts.filter = line.substring(1);
306
313
  }
@@ -333,23 +340,14 @@ export class Compose extends FormElement {
333
340
  num > 0 &&
334
341
  evt.ctrlKey &&
335
342
  evt.metaKey &&
336
- num <= tabs.tabs.length) {
343
+ num <= tabs.options.length) {
337
344
  tabs.index = num - 1;
338
345
  }
339
- // if they type / as the first character in a line, switch to the shortcut
340
- if (evt.key === '/' && this.currentTab.name !== 'Shortcuts') {
341
- const line = this.getCurrentLine();
342
- const text = line.text.trim();
343
- if (text.trim().length === 1) {
344
- evt.preventDefault();
345
- tabs.index = tabs.tabs.findIndex((tab) => tab.name === 'Shortcuts');
346
- }
347
- }
348
- else if (evt.key === 'Backspace') {
346
+ if (evt.key === 'Backspace') {
349
347
  const line = this.getCurrentLine();
350
348
  const text = line.text;
351
349
  if (text === '/') {
352
- tabs.index = tabs.tabs.findIndex((tab) => tab.name === 'Reply');
350
+ tabs.focusTab('Reply');
353
351
  }
354
352
  }
355
353
  if (this.currentTab.name === 'Shortcuts') {
@@ -384,7 +382,7 @@ export class Compose extends FormElement {
384
382
  this.currentLanguage = select.values[0].iso;
385
383
  }
386
384
  resetTabs() {
387
- this.shadowRoot.querySelector('temba-tabs').index = 0;
385
+ this.getTabs().focusTab('Reply');
388
386
  }
389
387
  getTabs() {
390
388
  return this.shadowRoot.querySelector('temba-tabs');
@@ -456,16 +454,14 @@ export class Compose extends FormElement {
456
454
  chatbox.inputElement.setSelectionRange(newCursor, newCursor);
457
455
  }
458
456
  const tabs = this.shadowRoot.querySelector('temba-tabs');
459
- tabs.index = tabs.tabs.findIndex((tab) => tab.name === 'Reply');
457
+ tabs.index = tabs.options.findIndex((tab) => tab.name === 'Reply');
460
458
  }
461
459
  getActions() {
462
460
  const showOptins = this.optIns && this.isBaseLanguage();
463
461
  const showTemplates = this.templates && this.isBaseLanguage();
464
462
  return html `
465
463
  <temba-tabs
466
- embedded
467
464
  focusedname
468
- index="0"
469
465
  @temba-context-changed=${this.handleTabChanged}
470
466
  refresh="${(this.currentAttachments || []).length}|${this.index}|${this
471
467
  .currentQuickReplies.length}|${showOptins}|${this