@seamly/web-ui 20.8.1 → 21.0.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/build/dist/lib/components.js +14855 -20
  2. package/build/dist/lib/components.min.js +2 -1
  3. package/build/dist/lib/components.min.js.LICENSE.txt +48 -0
  4. package/build/dist/lib/config.js +9 -3
  5. package/build/dist/lib/config.min.js +1 -1
  6. package/build/dist/lib/contexts.js +14 -5
  7. package/build/dist/lib/contexts.min.js +1 -1
  8. package/build/dist/lib/deprecated-view.js +1 -1
  9. package/build/dist/lib/hooks.js +8446 -20
  10. package/build/dist/lib/hooks.min.js +2 -1
  11. package/build/dist/lib/hooks.min.js.LICENSE.txt +38 -0
  12. package/build/dist/lib/index.debug.js +585 -584
  13. package/build/dist/lib/index.debug.min.js +1 -1
  14. package/build/dist/lib/index.debug.min.js.LICENSE.txt +110 -110
  15. package/build/dist/lib/index.js +20279 -26454
  16. package/build/dist/lib/index.min.js +1 -1
  17. package/build/dist/lib/index.min.js.LICENSE.txt +6 -1
  18. package/build/dist/lib/standalone.js +27823 -34681
  19. package/build/dist/lib/standalone.min.js +1 -1
  20. package/build/dist/lib/standalone.min.js.LICENSE.txt +1 -1
  21. package/build/dist/lib/storage.js +6 -15
  22. package/build/dist/lib/style-guide.js +23181 -7921
  23. package/build/dist/lib/style-guide.min.js +1 -1
  24. package/build/dist/lib/style-guide.min.js.LICENSE.txt +10 -0
  25. package/build/dist/lib/styles-default-implementation.js +1 -1
  26. package/build/dist/lib/styles.js +1 -1
  27. package/build/dist/lib/utils.js +22149 -17
  28. package/build/dist/lib/utils.min.js +2 -1
  29. package/build/dist/lib/utils.min.js.LICENSE.txt +48 -0
  30. package/package.json +54 -52
  31. package/src/icons/icon_check-16.svg +14 -0
  32. package/src/icons/icon_check-32.svg +14 -0
  33. package/src/javascripts/api/conversation-connector.ts +149 -0
  34. package/src/javascripts/api/errors/seamly-base-error.js +19 -0
  35. package/src/javascripts/api/errors/seamly-unavailable-error.js +5 -7
  36. package/src/javascripts/api/{index.js → index.ts} +163 -116
  37. package/src/javascripts/config.types.ts +5 -4
  38. package/src/javascripts/domains/app/actions.ts +47 -46
  39. package/src/javascripts/domains/app/hooks.js +1 -1
  40. package/src/javascripts/domains/config/actions.ts +2 -8
  41. package/src/javascripts/domains/config/hooks.ts +1 -1
  42. package/src/javascripts/domains/config/selectors.ts +6 -6
  43. package/src/javascripts/domains/config/slice.ts +3 -3
  44. package/src/javascripts/domains/errors/index.ts +66 -0
  45. package/src/javascripts/domains/forms/context.ts +1 -1
  46. package/src/javascripts/domains/forms/forms.types.ts +3 -3
  47. package/src/javascripts/domains/forms/hooks.ts +10 -10
  48. package/src/javascripts/domains/forms/provider.tsx +9 -9
  49. package/src/javascripts/domains/i18n/actions.ts +11 -5
  50. package/src/javascripts/domains/i18n/hooks.ts +11 -8
  51. package/src/javascripts/domains/i18n/selectors.ts +10 -4
  52. package/src/javascripts/domains/i18n/slice.ts +0 -1
  53. package/src/javascripts/domains/interrupt/hooks.ts +1 -1
  54. package/src/javascripts/domains/interrupt/middleware.ts +1 -1
  55. package/src/javascripts/domains/store/index.ts +1 -1
  56. package/src/javascripts/domains/store/selectors.ts +16 -0
  57. package/src/javascripts/domains/store/slice.ts +47 -41
  58. package/src/javascripts/domains/store/store.types.ts +38 -10
  59. package/src/javascripts/domains/translations/components/{options-button.js → options-button.tsx} +30 -20
  60. package/src/javascripts/domains/translations/components/options-dialog/index.tsx +33 -0
  61. package/src/javascripts/domains/translations/components/options-dialog/translation-option.tsx +42 -0
  62. package/src/javascripts/domains/translations/components/options-dialog/translation-options.tsx +81 -0
  63. package/src/javascripts/domains/translations/components/translation-status.tsx +15 -0
  64. package/src/javascripts/domains/translations/hooks.ts +77 -11
  65. package/src/javascripts/domains/translations/slice.ts +20 -9
  66. package/src/javascripts/domains/translations/translations.types.ts +4 -2
  67. package/src/javascripts/domains/visibility/actions.ts +6 -10
  68. package/src/javascripts/domains/visibility/hooks.ts +33 -14
  69. package/src/javascripts/domains/visibility/selectors.ts +3 -2
  70. package/src/javascripts/domains/visibility/slice.ts +2 -6
  71. package/src/javascripts/index.ts +18 -22
  72. package/src/javascripts/lib/engine/{index.js → index.tsx} +25 -7
  73. package/src/javascripts/lib/url-helpers.ts +112 -0
  74. package/src/javascripts/package/components.js +15 -1
  75. package/src/javascripts/package/config.js +1 -1
  76. package/src/javascripts/package/contexts.js +5 -3
  77. package/src/javascripts/package/hooks.js +19 -1
  78. package/src/javascripts/package/utils.js +13 -3
  79. package/src/javascripts/schema.ts +28 -0
  80. package/src/javascripts/style-guide/components/app.js +16 -12
  81. package/src/javascripts/style-guide/components/links.js +6 -6
  82. package/src/javascripts/style-guide/components/static-core.js +14 -9
  83. package/src/javascripts/style-guide/components/view.js +2 -2
  84. package/src/javascripts/style-guide/states.js +132 -36
  85. package/src/javascripts/style-guide/style-guide-engine.js +2 -1
  86. package/src/javascripts/style-guide/style-guide-external-api.js +1 -1
  87. package/src/javascripts/ui/components/app-options/index.js +25 -6
  88. package/src/javascripts/ui/components/chat-app.js +1 -1
  89. package/src/javascripts/ui/components/chat-status/chat-status-action.tsx +30 -0
  90. package/src/javascripts/ui/components/chat-status/index.tsx +61 -0
  91. package/src/javascripts/ui/components/conversation/component-filter.js +9 -9
  92. package/src/javascripts/ui/components/conversation/{conversation.js → conversation.tsx} +32 -41
  93. package/src/javascripts/ui/components/conversation/event/card-component.js +2 -2
  94. package/src/javascripts/ui/components/conversation/event/card-message.js +1 -1
  95. package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js +2 -2
  96. package/src/javascripts/ui/components/conversation/event/carousel-component/index.js +4 -4
  97. package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +2 -2
  98. package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +1 -1
  99. package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-context.ts +12 -0
  100. package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-provider.tsx +46 -0
  101. package/src/javascripts/ui/components/conversation/event/chat-scroll/unread-messages-button.tsx +30 -0
  102. package/src/javascripts/ui/components/conversation/event/choice-prompt.js +12 -8
  103. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +6 -6
  104. package/src/javascripts/ui/components/conversation/event/cta.js +2 -2
  105. package/src/javascripts/ui/components/conversation/event/divider/index.js +0 -1
  106. package/src/javascripts/ui/components/conversation/event/divider/variants/default.js +1 -1
  107. package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +17 -22
  108. package/src/javascripts/ui/components/conversation/event/divider/variants/time-indicator.js +2 -2
  109. package/src/javascripts/ui/components/conversation/event/event-participant.js +1 -1
  110. package/src/javascripts/ui/components/conversation/event/event.tsx +66 -0
  111. package/src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js +1 -1
  112. package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +1 -1
  113. package/src/javascripts/ui/components/conversation/event/image-lightbox.js +1 -1
  114. package/src/javascripts/ui/components/conversation/event/image.js +2 -2
  115. package/src/javascripts/ui/components/conversation/event/splash.js +1 -1
  116. package/src/javascripts/ui/components/conversation/event/translation.js +1 -1
  117. package/src/javascripts/ui/components/conversation/event/upload.js +2 -2
  118. package/src/javascripts/ui/components/conversation/event/video.js +2 -2
  119. package/src/javascripts/ui/components/conversation/event-divider.js +1 -1
  120. package/src/javascripts/ui/components/conversation/message-container.js +1 -1
  121. package/src/javascripts/ui/components/conversation/use-chat-scroll.ts +108 -0
  122. package/src/javascripts/ui/components/core/{seamly-activity-monitor.js → seamly-activity-monitor.tsx} +12 -5
  123. package/src/javascripts/ui/components/core/seamly-api-context.ts +7 -0
  124. package/src/javascripts/ui/components/core/seamly-chat.tsx +8 -0
  125. package/src/javascripts/ui/components/core/{seamly-core.js → seamly-core.tsx} +27 -14
  126. package/src/javascripts/ui/components/core/seamly-event-subscriber.ts +340 -0
  127. package/src/javascripts/ui/components/core/seamly-file-upload.js +2 -2
  128. package/src/javascripts/ui/components/core/seamly-idle-detach-counter.js +1 -1
  129. package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +24 -11
  130. package/src/javascripts/ui/components/core/seamly-live-region.js +4 -4
  131. package/src/javascripts/ui/components/core/seamly-new-notifications.js +3 -3
  132. package/src/javascripts/ui/components/core/seamly-read-state.js +2 -33
  133. package/src/javascripts/ui/components/entry/deprecated-toggle-button.js +4 -4
  134. package/src/javascripts/ui/components/entry/entry-container.js +8 -8
  135. package/src/javascripts/ui/components/entry/text-entry/hooks.js +3 -3
  136. package/src/javascripts/ui/components/entry/text-entry/index.js +3 -3
  137. package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +4 -4
  138. package/src/javascripts/ui/components/entry/upload/file-upload-form.js +3 -3
  139. package/src/javascripts/ui/components/entry/upload/index.js +5 -5
  140. package/src/javascripts/ui/components/entry/upload-toggle.js +6 -6
  141. package/src/javascripts/ui/components/faq/faq.js +14 -14
  142. package/src/javascripts/ui/components/form-controls/error.js +2 -2
  143. package/src/javascripts/ui/components/form-controls/file-input.js +3 -3
  144. package/src/javascripts/ui/components/layout/agent-info.js +3 -3
  145. package/src/javascripts/ui/components/layout/chat-frame.js +20 -12
  146. package/src/javascripts/ui/components/layout/chat.js +5 -5
  147. package/src/javascripts/ui/components/layout/deprecated-app-frame.js +6 -6
  148. package/src/javascripts/ui/components/layout/deprecated-chat-frame.js +34 -0
  149. package/src/javascripts/ui/components/layout/header.js +2 -2
  150. package/src/javascripts/ui/components/layout/icon.js +11 -9
  151. package/src/javascripts/ui/components/layout/interrupt.js +7 -5
  152. package/src/javascripts/ui/components/layout/pre-chat-messages.js +1 -1
  153. package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
  154. package/src/javascripts/ui/components/options/options-button.js +5 -5
  155. package/src/javascripts/ui/components/options/{options-frame.js → options-frame.tsx} +52 -18
  156. package/src/javascripts/ui/components/options/transcript/index.js +9 -10
  157. package/src/javascripts/ui/components/options/transcript/transcript-form.js +2 -2
  158. package/src/javascripts/ui/components/suggestions/index.js +8 -8
  159. package/src/javascripts/ui/components/suggestions/suggestions-item.js +1 -1
  160. package/src/javascripts/{domains/translations/components/chat-status.js → ui/components/translation-chat-status/index.tsx} +13 -14
  161. package/src/javascripts/ui/components/translation-proposal/index.tsx +36 -0
  162. package/src/javascripts/ui/components/view/app-view.js +2 -7
  163. package/src/javascripts/ui/components/view/deprecated-view.js +8 -10
  164. package/src/javascripts/ui/components/view/index.js +6 -6
  165. package/src/javascripts/ui/components/view/inline-view.js +4 -8
  166. package/src/javascripts/ui/components/view/window-view/collapse-button.js +2 -2
  167. package/src/javascripts/ui/components/view/window-view/index.js +11 -17
  168. package/src/javascripts/ui/components/view/window-view/window-open-button.js +6 -6
  169. package/src/javascripts/ui/components/warnings/idle-detach-warning.js +3 -3
  170. package/src/javascripts/ui/components/warnings/prompt.js +1 -1
  171. package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +4 -4
  172. package/src/javascripts/ui/components/widgets/in-out-transition.js +20 -18
  173. package/src/javascripts/ui/components/widgets/lightbox.js +3 -3
  174. package/src/javascripts/ui/components/widgets/modal.js +2 -2
  175. package/src/javascripts/ui/components/widgets/upload-progress.js +2 -2
  176. package/src/javascripts/ui/hooks/file-upload-hooks.js +1 -1
  177. package/src/javascripts/ui/hooks/focus-helper-hooks.js +1 -1
  178. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +6 -6
  179. package/src/javascripts/ui/hooks/seamly-hooks.js +11 -10
  180. package/src/javascripts/ui/hooks/seamly-option-hooks.js +6 -6
  181. package/src/javascripts/ui/hooks/{seamly-state-hooks.js → seamly-state-hooks.ts} +9 -6
  182. package/src/javascripts/ui/hooks/use-click-outside.ts +29 -0
  183. package/src/javascripts/ui/hooks/use-event-component-mapping.js +11 -10
  184. package/src/javascripts/ui/hooks/use-interval.js +1 -1
  185. package/src/javascripts/ui/hooks/use-seamly-actions.ts +29 -29
  186. package/src/javascripts/ui/hooks/use-seamly-chat.js +14 -24
  187. package/src/javascripts/ui/hooks/use-seamly-commands.js +20 -15
  188. package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +8 -8
  189. package/src/javascripts/ui/hooks/use-seamly-resume-conversation-prompt.js +2 -2
  190. package/src/javascripts/ui/hooks/use-single-file-upload.js +1 -1
  191. package/src/javascripts/ui/hooks/utility-hooks.js +1 -1
  192. package/src/javascripts/ui/utils/general-utils.js +0 -23
  193. package/src/javascripts/ui/utils/seamly-utils.ts +10 -1
  194. package/src/javascripts/ui/utils/seamly-utils.types.ts +9 -0
  195. package/src/stylesheets/1-settings/_config.scss +1 -1
  196. package/src/stylesheets/3-chat/_chat.scss +24 -9
  197. package/src/stylesheets/5-components/_chat-status.scss +72 -16
  198. package/src/stylesheets/5-components/_conversation.scss +35 -1
  199. package/src/stylesheets/5-components/_disclaimer.scss +0 -5
  200. package/src/stylesheets/5-components/_options.scss +16 -6
  201. package/src/stylesheets/5-components/_translation-options.scss +51 -0
  202. package/src/stylesheets/6-default-implementation/_scrollbar.scss +1 -1
  203. package/src/stylesheets/7-deprecated/3-app/_app.scss +19 -4
  204. package/src/stylesheets/7-deprecated/5-components/_chat-status.scss +5 -0
  205. package/src/stylesheets/7-deprecated/5-components/_options.scss +1 -4
  206. package/src/stylesheets/7-deprecated/5-components/_translation-options.scss +49 -0
  207. package/src/stylesheets/deprecated-view.scss +1 -0
  208. package/src/stylesheets/styles.scss +1 -0
  209. package/webpack/config.common.js +4 -4
  210. package/webpack/config.package.js +10 -16
  211. package/webpack/config.site.js +4 -1
  212. package/webpack/config.test.js +2 -1
  213. package/build/dist/lib/deprecated-view.css +0 -1
  214. package/build/dist/lib/styles-default-implementation.css +0 -1
  215. package/build/dist/lib/styles.css +0 -1
  216. package/src/.DS_Store +0 -0
  217. package/src/javascripts/api/event-producer.js +0 -20
  218. package/src/javascripts/api/producer.js +0 -136
  219. package/src/javascripts/domains/errors/index.js +0 -37
  220. package/src/javascripts/domains/translations/components/options-dialog/form.js +0 -70
  221. package/src/javascripts/domains/translations/components/options-dialog/index.js +0 -87
  222. package/src/javascripts/ui/components/chat-status/index.js +0 -38
  223. package/src/javascripts/ui/components/conversation/event/event.js +0 -36
  224. package/src/javascripts/ui/components/core/seamly-api-context.js +0 -5
  225. package/src/javascripts/ui/components/core/seamly-event-subscriber.js +0 -279
@@ -1,9 +1,7 @@
1
- import {
2
- randomId,
3
- SeamlyGeneralError,
4
- SeamlyOfflineError,
5
- visibilityStates,
6
- } from '@seamly/web-ui'
1
+ import SeamlyGeneralError from 'api/errors/seamly-general-error'
2
+ import SeamlyOfflineError from 'api/errors/seamly-offline-error'
3
+ import { visibilityStates } from 'domains/visibility/constants'
4
+ import { randomId } from 'lib/id'
7
5
  import { addTranslationData } from './state-helpers'
8
6
 
9
7
  const baseState = {
@@ -107,8 +105,10 @@ const newTranslationDividerStart = {
107
105
  payload: {
108
106
  body: {
109
107
  language: 'Nederlands',
108
+ restartButtonText: null,
110
109
  subtype: 'new_translation',
111
110
  text: '[NL] Automatic translation to Dutch started. Please note that automatic translations may contain errors.',
111
+ title: '[NL] Translating to Dutch',
112
112
  translationEnabled: true,
113
113
  translationLocale: 'nl',
114
114
  },
@@ -158,8 +158,10 @@ const newTranslationDividerStop = {
158
158
  payload: {
159
159
  body: {
160
160
  language: 'Nederlands',
161
+ restartButtonText: '[NL] Start again',
161
162
  subtype: 'new_translation',
162
- text: '[NL] Automatic translation to Dutch ended.',
163
+ text: null,
164
+ title: '[NL] Automatic translation to Dutch ended',
163
165
  translationEnabled: false,
164
166
  translationLocale: 'nl',
165
167
  },
@@ -762,6 +764,7 @@ const translationsSlice = {
762
764
  isActive: false,
763
765
  currentLocale: undefined,
764
766
  isAvailable: false,
767
+ showTranslationProposal: false,
765
768
  languages: [],
766
769
  translatedEventGroups: {},
767
770
  containerId: randomId(),
@@ -1720,6 +1723,30 @@ const standardState = {
1720
1723
  languages: [
1721
1724
  { locale: 'nl', nativeName: 'Dutch' },
1722
1725
  { locale: 'en', nativeName: 'English' },
1726
+ { locale: 'ar', nativeName: 'Arabic' },
1727
+ { locale: 'bg', nativeName: 'Bulgarian' },
1728
+ { locale: 'zh', nativeName: 'Chinese' },
1729
+ { locale: 'cs', nativeName: 'Czech' },
1730
+ { locale: 'da', nativeName: 'Danish' },
1731
+ { locale: 'et', nativeName: 'Estonian' },
1732
+ { locale: 'fi', nativeName: 'Finnish' },
1733
+ { locale: 'fr', nativeName: 'French' },
1734
+ { locale: 'de-informal', nativeName: 'German' },
1735
+ { locale: 'el', nativeName: 'Greek' },
1736
+ { locale: 'hu', nativeName: 'Hungarian' },
1737
+ { locale: 'it', nativeName: 'Italian' },
1738
+ { locale: 'ja', nativeName: 'Japanese' },
1739
+ { locale: 'lv', nativeName: 'Latvian' },
1740
+ { locale: 'pl', nativeName: 'Polish' },
1741
+ { locale: 'ro', nativeName: 'Romanian' },
1742
+ { locale: 'ru', nativeName: 'Russian' },
1743
+ { locale: 'sk', nativeName: 'Slovak' },
1744
+ { locale: 'sl', nativeName: 'Slovenian' },
1745
+ { locale: 'es-informal', nativeName: 'Spanish' },
1746
+ { locale: 'sv', nativeName: 'Swedish' },
1747
+ { locale: 'ti', nativeName: 'Tigrinya' },
1748
+ { locale: 'tr', nativeName: 'Turkish' },
1749
+ { locale: 'uk', nativeName: 'Ukrainian' },
1723
1750
  ],
1724
1751
  },
1725
1752
  },
@@ -1823,6 +1850,63 @@ const standardState = {
1823
1850
  ],
1824
1851
  },
1825
1852
  },
1853
+ translationProposal: {
1854
+ category: categoryKeys.translations,
1855
+ headingText: 'Show translation proposal',
1856
+ description: '',
1857
+ ...baseState,
1858
+ events: [shortTextMessage, userMessage, userMessageLong],
1859
+ config: {
1860
+ ...baseState.config,
1861
+ showDisclaimer: true,
1862
+ context: {
1863
+ locale: 'nl-informal',
1864
+ },
1865
+ },
1866
+ translations: {
1867
+ ...translationsSlice,
1868
+ translationProposal: {
1869
+ buttonLabel: 'Activate',
1870
+ proposedLocale: 'en-GB',
1871
+ srDismissButtonText: 'Dismiss translation proposal',
1872
+ titleLabel: 'Do you want to chat in English?',
1873
+ },
1874
+ isAvailable: true,
1875
+ isActive: false,
1876
+ languages: [
1877
+ { locale: 'nl-informal', nativeName: 'Dutch' },
1878
+ { locale: 'en-GB', nativeName: 'English' },
1879
+ ],
1880
+ },
1881
+ },
1882
+ translationProposalWithoutTitle: {
1883
+ category: categoryKeys.translations,
1884
+ headingText: 'Show translation proposal without title',
1885
+ description: '',
1886
+ ...baseState,
1887
+ events: [shortTextMessage, userMessage, userMessageLong],
1888
+ config: {
1889
+ ...baseState.config,
1890
+ showDisclaimer: true,
1891
+ context: {
1892
+ locale: 'nl-informal',
1893
+ },
1894
+ },
1895
+ translations: {
1896
+ ...translationsSlice,
1897
+ translationProposal: {
1898
+ buttonLabel: 'Activate',
1899
+ proposedLocale: 'en-GB',
1900
+ srDismissButtonText: 'Dismiss translation proposal',
1901
+ },
1902
+ isAvailable: true,
1903
+ isActive: false,
1904
+ languages: [
1905
+ { locale: 'nl-informal', nativeName: 'Dutch' },
1906
+ { locale: 'en-GB', nativeName: 'English' },
1907
+ ],
1908
+ },
1909
+ },
1826
1910
  }
1827
1911
 
1828
1912
  const inlineInterface = {
@@ -1955,7 +2039,10 @@ const standardWindowStates = {
1955
2039
  description: '',
1956
2040
  window: {
1957
2041
  ...baseState,
1958
- config: { ...baseState.config, layoutMode: 'window' },
2042
+ config: {
2043
+ ...baseState.config,
2044
+ layoutMode: 'window',
2045
+ },
1959
2046
  visibility: {
1960
2047
  ...baseState.visibility,
1961
2048
  visibility: visibilityStates.minimized,
@@ -1968,7 +2055,10 @@ const standardWindowStates = {
1968
2055
  description: '',
1969
2056
  window: {
1970
2057
  ...baseState,
1971
- config: { ...baseState.config, layoutMode: 'window' },
2058
+ config: {
2059
+ ...baseState.config,
2060
+ layoutMode: 'window',
2061
+ },
1972
2062
  visibility: {
1973
2063
  ...baseState.visibility,
1974
2064
  visibility: visibilityStates.minimized,
@@ -2048,6 +2138,7 @@ const buildStandardState = (
2048
2138
  return Object.keys(intermediateState).reduce((acc, key) => {
2049
2139
  const { headingText, category, description, ...rest } =
2050
2140
  intermediateState[key]
2141
+
2051
2142
  return {
2052
2143
  ...acc,
2053
2144
  [key]: {
@@ -2057,7 +2148,10 @@ const buildStandardState = (
2057
2148
  ...layoutModes.reduce(
2058
2149
  (comb, layoutMode) => ({
2059
2150
  ...comb,
2060
- [layoutMode]: { ...rest, config: { ...rest.config, layoutMode } },
2151
+ [layoutMode]: {
2152
+ ...rest,
2153
+ config: { ...rest.config, layoutMode },
2154
+ },
2061
2155
  }),
2062
2156
  {},
2063
2157
  ),
@@ -2074,31 +2168,33 @@ export const getDeprecatedStateObj = (
2074
2168
  ...(layoutModes.indexOf('window') !== -1 ? standardWindowStates : {}),
2075
2169
  })
2076
2170
 
2077
- export const getStateObj = (layoutModes, customComponentEventBodies) => ({
2078
- ...buildStandardState(layoutModes, customComponentEventBodies, true),
2079
- ...(layoutModes.indexOf('window') !== -1
2080
- ? {
2081
- ...standardWindowStates,
2082
- minimizedWindowPrechat: {
2083
- category: categoryKeys.minimizedWindow,
2084
- headingText: 'Minimized with pre-chat messages',
2085
- description: '',
2086
- window: {
2087
- ...baseState,
2088
- config: {
2089
- ...baseState.config,
2090
- layoutMode: 'window',
2091
- preChatEvents: [splashMessage],
2092
- },
2093
- visibility: {
2094
- ...baseState.visibility,
2095
- visibility: visibilityStates.minimized,
2171
+ export const getStateObj = (layoutModes, customComponentEventBodies) => {
2172
+ return {
2173
+ ...buildStandardState(layoutModes, customComponentEventBodies, true),
2174
+ ...(layoutModes.indexOf('window') !== -1
2175
+ ? {
2176
+ ...standardWindowStates,
2177
+ minimizedWindowPrechat: {
2178
+ category: categoryKeys.minimizedWindow,
2179
+ headingText: 'Minimized with pre-chat messages',
2180
+ description: '',
2181
+ window: {
2182
+ ...baseState,
2183
+ config: {
2184
+ ...baseState.config,
2185
+ layoutMode: 'window',
2186
+ preChatEvents: [splashMessage],
2187
+ },
2188
+ visibility: {
2189
+ ...baseState.visibility,
2190
+ visibility: visibilityStates.minimized,
2191
+ },
2192
+ participantInfo,
2193
+ headerTitles,
2096
2194
  },
2097
- participantInfo,
2098
- headerTitles,
2099
2195
  },
2100
- },
2101
- }
2102
- : {}),
2103
- ...inlineInterface,
2104
- })
2196
+ }
2197
+ : {}),
2198
+ ...inlineInterface,
2199
+ }
2200
+ }
@@ -1,5 +1,6 @@
1
+ import { API } from 'api'
1
2
  import { render } from 'preact'
2
- import { API, Engine } from '@seamly/web-ui'
3
+ import Engine from 'lib/engine'
3
4
  import StyleGuideApp from './components/app'
4
5
 
5
6
  class SeamlyStyleGuideInstance extends Engine {
@@ -1,4 +1,4 @@
1
- import { ExternalApi } from '@seamly/web-ui'
1
+ import ExternalApi from 'lib/external-api'
2
2
  import StyleGuideEngine from './style-guide-engine'
3
3
 
4
4
  class StyleGuideExternalApi extends ExternalApi {
@@ -1,19 +1,35 @@
1
- import { useSeamlyOptions } from 'ui/hooks/seamly-hooks'
2
- import { className } from 'lib/css'
1
+ import Icon from 'ui/components/layout/icon'
3
2
  import OptionsButton from 'ui/components/options/options-button'
4
- import { useTranslations } from 'domains/translations/hooks'
3
+ import { useSeamlyOptions } from 'ui/hooks/seamly-hooks'
4
+ import { useI18n } from 'domains/i18n/hooks'
5
+ import { useInterrupt } from 'domains/interrupt/hooks'
5
6
  import TranslationsOptionsButton from 'domains/translations/components/options-button'
7
+ import {
8
+ useLocaleNativeName,
9
+ useTranslations,
10
+ } from 'domains/translations/hooks'
11
+ import { className } from 'lib/css'
6
12
 
7
13
  export default function AppOptions() {
8
14
  const { menuOptions, allowOptionSelection } = useSeamlyOptions()
9
15
  const { isAvailable: isTranslationsAvailable } = useTranslations()
16
+ const { hasInterrupt } = useInterrupt()
17
+ const { t, locale } = useI18n()
18
+ const localeNativeName = useLocaleNativeName(locale)
19
+
10
20
  if (
11
- !isTranslationsAvailable &&
12
- (!allowOptionSelection || !menuOptions.length)
21
+ (!isTranslationsAvailable &&
22
+ (!allowOptionSelection || !menuOptions.length)) ||
23
+ hasInterrupt
13
24
  ) {
14
25
  return null
15
26
  }
16
27
 
28
+ const openButtonText = t('translations.settings.openButtonText', {
29
+ hasLanguage: !!localeNativeName,
30
+ language: localeNativeName,
31
+ })
32
+
17
33
  return (
18
34
  <div className={className('chat__options')}>
19
35
  {isTranslationsAvailable && (
@@ -23,7 +39,10 @@ export default function AppOptions() {
23
39
  'chat__options-item--left',
24
40
  )}
25
41
  >
26
- <TranslationsOptionsButton />
42
+ <TranslationsOptionsButton classNames={['button--secondary']}>
43
+ <Icon alt={openButtonText} name="newTranslation" size="16" />
44
+ <span className={className('button__text')}>{openButtonText}</span>
45
+ </TranslationsOptionsButton>
27
46
  </div>
28
47
  )}
29
48
  {allowOptionSelection && (
@@ -1,5 +1,5 @@
1
- import View from './view'
2
1
  import SeamlyCore from './core/seamly-core'
2
+ import View from './view'
3
3
 
4
4
  const ChatApp = (props) => {
5
5
  return (
@@ -0,0 +1,30 @@
1
+ import Icon from 'ui/components/layout/icon'
2
+ import { className } from 'lib/css'
3
+
4
+ type ChatStatusActionProps = {
5
+ handleClick: () => void
6
+ icon: string
7
+ title: string
8
+ srButtonText?: string
9
+ }
10
+
11
+ const ChatStatusAction = ({
12
+ handleClick,
13
+ icon,
14
+ title,
15
+ srButtonText,
16
+ }: ChatStatusActionProps) => (
17
+ <button
18
+ type="button"
19
+ onClick={handleClick}
20
+ className={className('button', 'button--primary', 'chat-status__button')}
21
+ >
22
+ <Icon name={icon} size="16" alt="" />
23
+ {title}
24
+ {srButtonText && (
25
+ <span className={className('visually-hidden')}>{srButtonText}</span>
26
+ )}
27
+ </button>
28
+ )
29
+
30
+ export default ChatStatusAction
@@ -0,0 +1,61 @@
1
+ import { FC } from 'preact/compat'
2
+ import Icon from 'ui/components/layout/icon'
3
+ import { useGeneratedId } from 'ui/hooks/utility-hooks'
4
+ import { className } from 'lib/css'
5
+
6
+ type ChatStatusProps = {
7
+ handleClose: () => void
8
+ title: string
9
+ closeButtonText?: string
10
+ srCloseButtonText?: string
11
+ id: string
12
+ }
13
+
14
+ const ChatStatus: FC<ChatStatusProps> = ({
15
+ children,
16
+ handleClose,
17
+ title,
18
+ closeButtonText,
19
+ srCloseButtonText,
20
+ id,
21
+ }) => {
22
+ const headingId = useGeneratedId()
23
+
24
+ return (
25
+ <section
26
+ tabIndex={-1}
27
+ id={id}
28
+ aria-labelledby={title ? headingId : undefined}
29
+ className={className('chat-status', !title && 'chat-status--condensed')}
30
+ >
31
+ <div className={className('chat-status__body')}>
32
+ {title ? (
33
+ <h2 className={className('chat-status__title')} id={headingId}>
34
+ {title}
35
+ </h2>
36
+ ) : null}
37
+ {children}
38
+ </div>
39
+ {typeof handleClose === 'function' && (
40
+ <button
41
+ type="button"
42
+ onClick={handleClose}
43
+ className={className(
44
+ 'button',
45
+ 'button--tertiary',
46
+ 'chat-status__close',
47
+ )}
48
+ >
49
+ {closeButtonText || <Icon name="close" size="16" alt="" />}
50
+ {srCloseButtonText && (
51
+ <span className={className('visually-hidden')}>
52
+ {srCloseButtonText}
53
+ </span>
54
+ )}
55
+ </button>
56
+ )}
57
+ </section>
58
+ )
59
+ }
60
+
61
+ export default ChatStatus
@@ -1,20 +1,20 @@
1
1
  import { useMemo } from 'preact/hooks'
2
2
  import { useConfig } from 'domains/config/hooks'
3
3
  import ComponentContext from './component-context'
4
+ import CardMessage from './event/card-message'
5
+ import CarouselMessage from './event/carousel-message'
4
6
  import ChoicePrompt from './event/choice-prompt'
5
- import Text from './event/text'
6
- import Image from './event/image'
7
- import Video from './event/video'
7
+ import ConversationSuggestions from './event/conversation-suggestions'
8
+ import Cta from './event/cta'
8
9
  import Divider from './event/divider'
9
- import Translation from './event/translation'
10
+ import TimeIndicator from './event/divider/variants/time-indicator'
11
+ import Image from './event/image'
10
12
  import Participant from './event/participant'
11
13
  import Splash from './event/splash'
14
+ import Text from './event/text'
15
+ import Translation from './event/translation'
12
16
  import Upload from './event/upload'
13
- import Cta from './event/cta'
14
- import TimeIndicator from './event/divider/variants/time-indicator'
15
- import CarouselMessage from './event/carousel-message'
16
- import CardMessage from './event/card-message'
17
- import ConversationSuggestions from './event/conversation-suggestions'
17
+ import Video from './event/video'
18
18
 
19
19
  const eventTypeMapping = {
20
20
  message: {
@@ -1,15 +1,13 @@
1
- import { useI18n } from 'domains/i18n/hooks'
2
- import { useVisibility } from 'domains/visibility/hooks'
3
- import { className } from 'lib/css'
4
- import { useLayoutEffect, useRef } from 'preact/hooks'
5
1
  import PrivacyDisclaimer from 'ui/components/layout/privacy-disclaimer'
6
- import { timeout } from 'ui/hooks/focus-helper-hooks'
7
2
  import {
8
3
  useSeamlyIsLoading,
9
4
  useSkiplink,
10
5
  useSkiplinkTargetFocusing,
11
6
  } from 'ui/hooks/seamly-hooks'
12
- import { useEvents, useLoadedImageEventIds } from 'ui/hooks/seamly-state-hooks'
7
+ import { useEvents } from 'ui/hooks/seamly-state-hooks'
8
+ import { useI18n } from 'domains/i18n/hooks'
9
+ import { useVisibility } from 'domains/visibility/hooks'
10
+ import { className } from 'lib/css'
13
11
  import ComponentFilter from './component-filter'
14
12
  import Event from './event/event'
15
13
  import Loader from './loader'
@@ -18,49 +16,41 @@ const Events = () => {
18
16
  const events = useEvents()
19
17
 
20
18
  let prevParticipant = null
21
- return events.map((event) => {
22
- const { type, payload } = event
23
- const { participant, fromClient } = payload
24
- let participantChanged = false
25
- if (type !== 'participant') {
26
- const currentParticipant = fromClient
27
- ? 'seamly-client-participant'
28
- : participant
29
- if (event.type !== 'info' && prevParticipant !== currentParticipant) {
30
- participantChanged = true
31
- }
32
- prevParticipant = currentParticipant
33
- }
19
+ return (
20
+ <>
21
+ {events.map((event) => {
22
+ const { type, payload } = event
23
+
24
+ let participantChanged = false
25
+ if (type !== 'participant' && type !== 'service_data') {
26
+ const { participant, fromClient } = payload
27
+ const currentParticipant = fromClient
28
+ ? 'seamly-client-participant'
29
+ : participant
30
+ if (event.type !== 'info' && prevParticipant !== currentParticipant) {
31
+ participantChanged = true
32
+ }
33
+ prevParticipant = currentParticipant
34
+ }
34
35
 
35
- return (
36
- <Event
37
- key={event.payload.key || event.payload.id}
38
- event={event}
39
- newParticipant={participantChanged}
40
- />
41
- )
42
- })
36
+ return (
37
+ <Event
38
+ key={event.payload.key || event.payload.id}
39
+ event={event}
40
+ newParticipant={participantChanged}
41
+ />
42
+ )
43
+ })}
44
+ </>
45
+ )
43
46
  }
44
47
 
45
48
  const Conversation = () => {
46
49
  const { t } = useI18n()
47
- const chatBodyContainer = useRef(null)
48
- const events = useEvents()
49
50
  const isLoading = useSeamlyIsLoading()
50
51
  const { isOpen } = useVisibility()
51
52
  const skiplinkTargetId = useSkiplink()
52
53
  const focusSkiplinkTarget = useSkiplinkTargetFocusing()
53
- const loadedImageEventIds = useLoadedImageEventIds()
54
-
55
- useLayoutEffect(() => {
56
- const containerElement = chatBodyContainer.current
57
- if (containerElement) {
58
- requestAnimationFrame(async () => {
59
- await timeout(30) // Wait for next frame tick
60
- containerElement.scrollTop = containerElement.scrollHeight
61
- })
62
- }
63
- }, [events, isLoading, isOpen, loadedImageEventIds])
64
54
 
65
55
  const onClickHandler = (e) => {
66
56
  e.preventDefault()
@@ -78,7 +68,8 @@ const Conversation = () => {
78
68
  {t('skiplinkText')}
79
69
  </a>
80
70
  )}
81
- <div className={className('chat__body')} ref={chatBodyContainer}>
71
+
72
+ <div className={className('chat__body')}>
82
73
  <div className={className('conversation__container')}>
83
74
  <PrivacyDisclaimer />
84
75
  <ol className={className('conversation')}>
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
2
- import { className } from 'lib/css'
3
2
  import { useGeneratedId, useSeamlyCommands } from 'ui/hooks/seamly-hooks'
4
- import { cardTypes, actionTypes } from 'ui/utils/seamly-utils'
3
+ import { actionTypes, cardTypes } from 'ui/utils/seamly-utils'
4
+ import { className } from 'lib/css'
5
5
 
6
6
  const CardComponent = ({
7
7
  id,
@@ -1,5 +1,5 @@
1
- import { useGeneratedId } from 'ui/hooks/seamly-hooks'
2
1
  import MessageContainer from 'ui/components/conversation/message-container'
2
+ import { useGeneratedId } from 'ui/hooks/seamly-hooks'
3
3
  import { useTranslatedEventData } from 'domains/translations/hooks'
4
4
  import CardComponent from './card-component'
5
5
 
@@ -1,6 +1,6 @@
1
- import { className } from 'lib/css'
2
- import { useI18n } from 'domains/i18n/hooks'
3
1
  import Icon from 'ui/components/layout/icon'
2
+ import { useI18n } from 'domains/i18n/hooks'
3
+ import { className } from 'lib/css'
4
4
 
5
5
  export default function CarouselControls({
6
6
  items,
@@ -1,10 +1,10 @@
1
1
  import { createRef } from 'preact'
2
- import { useState, useEffect, useRef, useMemo } from 'preact/hooks'
3
- import { className } from 'lib/css'
4
- import { useGeneratedId } from 'ui/hooks/utility-hooks'
2
+ import { useEffect, useMemo, useRef, useState } from 'preact/hooks'
5
3
  import CarouselMessageSlide from 'ui/components/conversation/event/carousel-message/components/slide'
6
- import CarouselPagination from './components/pagination'
4
+ import { useGeneratedId } from 'ui/hooks/utility-hooks'
5
+ import { className } from 'lib/css'
7
6
  import CarouselControls from './components/controls'
7
+ import CarouselPagination from './components/pagination'
8
8
 
9
9
  const defaultGetItemKey = (item, idx, prefix) => `${prefix}${idx}`
10
10
  const defaultGetItemLabel = (item) => item.label
@@ -1,6 +1,6 @@
1
- import { className } from 'lib/css'
2
- import { useI18n } from 'domains/i18n/hooks'
3
1
  import CardComponent from 'ui/components/conversation/event/card-component'
2
+ import { useI18n } from 'domains/i18n/hooks'
3
+ import { className } from 'lib/css'
4
4
 
5
5
  export default function CarouselMessageSlide({
6
6
  item: slide,
@@ -1,5 +1,5 @@
1
- import MessageContainer from 'ui/components/conversation/message-container'
2
1
  import CarouselComponent from 'ui/components/conversation/event/carousel-component'
2
+ import MessageContainer from 'ui/components/conversation/message-container'
3
3
  import { useTranslatedEventData } from 'domains/translations/hooks'
4
4
  import CarouselMessageSlide from './components/slide'
5
5
 
@@ -0,0 +1,12 @@
1
+ import { RefObject, createContext } from 'preact'
2
+ import { MutableRef } from 'preact/hooks'
3
+
4
+ const ChatScrollContext = createContext<{
5
+ eventRefs: Record<string, RefObject<HTMLElement>>
6
+ unreadIds: string[]
7
+ scrollToRef: () => void
8
+ scrollToBottom: () => void
9
+ containerRef: MutableRef<HTMLDivElement>
10
+ }>(null)
11
+
12
+ export default ChatScrollContext
@@ -0,0 +1,46 @@
1
+ import { RefObject, createRef } from 'preact'
2
+ import { useMemo } from 'preact/hooks'
3
+ import ChatScrollContext from 'ui/components/conversation/event/chat-scroll/chat-scroll-context'
4
+ import UnreadMessagesButton from 'ui/components/conversation/event/chat-scroll/unread-messages-button'
5
+ import useChatScroll from 'ui/components/conversation/use-chat-scroll'
6
+ import { useEvents } from 'ui/hooks/seamly-hooks'
7
+ import { className } from 'lib/css'
8
+
9
+ const ChatScrollProvider = ({ children }) => {
10
+ const events = useEvents()
11
+ const eventRefs = useMemo(
12
+ () =>
13
+ events.reduce<Record<string, RefObject<HTMLElement>>>((acc, value) => {
14
+ acc[value.payload.id] = createRef()
15
+ return acc
16
+ }, {}),
17
+ [events],
18
+ )
19
+
20
+ const { scrollToRef, scrollToBottom, containerRef, unreadIds } =
21
+ useChatScroll(eventRefs)
22
+
23
+ return (
24
+ <ChatScrollContext.Provider
25
+ value={{
26
+ eventRefs,
27
+ unreadIds,
28
+ scrollToRef,
29
+ scrollToBottom,
30
+ containerRef,
31
+ }}
32
+ >
33
+ <div className={className('chat__container')}>
34
+ <div
35
+ className={className('chat__container__scroll-area')}
36
+ ref={containerRef}
37
+ >
38
+ {children}
39
+ </div>
40
+ <UnreadMessagesButton />
41
+ </div>
42
+ </ChatScrollContext.Provider>
43
+ )
44
+ }
45
+
46
+ export default ChatScrollProvider