@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,48 +1,48 @@
1
+ import { useDispatch } from 'react-redux'
1
2
  import {
3
+ ackEvent,
2
4
  addEvent,
5
+ clearAllUploads,
3
6
  clearEvents,
4
- setHistory,
5
- setEventsRead,
6
- setLoadedImageEventIds,
7
- ackEvent,
8
- setIsLoading,
9
- setParticipant,
10
- setHeaderTitle,
11
- setHeaderSubTitle,
12
- resetHistoryLoadedFlag,
13
- setActiveService,
14
- initIdleDetachCountdown,
15
- decrementIdleDetachCountdownCounter,
16
- stopIdleDetachCountdownCounter,
7
+ clearFeatures,
17
8
  clearIdleDetachCountdown,
18
- initResumeConversationPrompt,
19
9
  clearResumeConversationPrompt,
20
- setServiceDataItem,
21
- setFeatures,
10
+ decrementIdleDetachCountdownCounter,
11
+ hideOption,
12
+ initIdleDetachCountdown,
13
+ initResumeConversationPrompt,
14
+ registerUpload,
15
+ resetHistoryLoadedFlag,
16
+ setActiveEntryType,
17
+ setActiveService,
18
+ setBlockAutoEntrySwitch,
19
+ setEventsRead,
22
20
  setFeatureEnabledState,
23
- clearFeatures,
21
+ setFeatures,
22
+ setHeaderSubTitle,
23
+ setHeaderTitle,
24
+ setHistory,
24
25
  setInitialState,
25
- setUserSelectedOptions,
26
- setUserSelectedOption,
27
- showOption,
28
- hideOption,
26
+ setIsLoading,
27
+ setLoadedImageEventIds,
28
+ setParticipant,
29
+ setSeamlyContainerElement,
30
+ setServiceDataItem,
29
31
  setServiceEntryMetadata,
30
- setBlockAutoEntrySwitch,
31
- setActiveEntryType,
32
- setUserEntryType,
33
- registerUpload,
34
- setUploadProgress,
35
32
  setUploadComplete,
36
33
  setUploadError,
37
- clearAllUploads,
38
- setSeamlyContainerElement,
34
+ setUploadProgress,
35
+ setUserEntryType,
36
+ setUserSelectedOption,
37
+ setUserSelectedOptions,
38
+ showOption,
39
+ stopIdleDetachCountdownCounter,
39
40
  } from 'domains/store/slice'
40
41
  import {
41
42
  ChannelEvent,
42
43
  HistoryResponse,
43
44
  ParticipantEvent,
44
45
  } from 'domains/store/store.types'
45
- import { useDispatch } from 'react-redux'
46
46
 
47
47
  export const useSeamlyActions = () => {
48
48
  const dispatch = useDispatch()
@@ -1,20 +1,19 @@
1
+ import { useCallback, useEffect, useRef } from 'preact/hooks'
2
+ import { useDispatch, useSelector } from 'react-redux'
3
+ import useSeamlyCommands from 'ui/hooks/use-seamly-commands'
1
4
  import { useI18n } from 'domains/i18n/hooks'
2
5
  import { setIsLoading } from 'domains/store/slice'
3
- import { visibilityStates } from 'domains/visibility/constants'
4
6
  import { useVisibility } from 'domains/visibility/hooks'
5
- import { useCallback, useEffect, useRef } from 'preact/hooks'
6
- import { useDispatch, useSelector } from 'react-redux'
7
7
  import { selectShowInlineView } from '../../domains/visibility/selectors'
8
8
  import { useLiveRegion } from './live-region-hooks'
9
9
  import { useSeamlyHasConversation } from './seamly-api-hooks'
10
10
  import { useEvents, useSeamlyLayoutMode } from './seamly-state-hooks'
11
- import useSeamlyCommands from './use-seamly-commands'
12
11
 
13
12
  const useSeamlyChat = () => {
14
13
  const events = useEvents()
15
14
  const { t } = useI18n()
16
- const { isInline, isWindow } = useSeamlyLayoutMode()
17
- const { isOpen, isVisible, setVisibility } = useVisibility()
15
+ const { isInline, isWindow, isApp } = useSeamlyLayoutMode()
16
+ const { isOpen, isVisible } = useVisibility()
18
17
  const showInlineView = useSelector(selectShowInlineView)
19
18
  const dispatch = useDispatch()
20
19
  const spinnerTimeout = useRef(null)
@@ -22,7 +21,7 @@ const useSeamlyChat = () => {
22
21
  const hasConversation = useSeamlyHasConversation()
23
22
  const prevIsOpen = useRef(null)
24
23
  const prevIsVisible = useRef(null)
25
- const startCalled = useRef(false)
24
+ const connectCalled = useRef(false)
26
25
  const { sendAssertive } = useLiveRegion()
27
26
 
28
27
  useEffect(() => {
@@ -80,22 +79,22 @@ const useSeamlyChat = () => {
80
79
  // This is needed to reset the ref to allow connect and start to happen again.
81
80
  // Mostly due to Interrupt situations and a reset being called.
82
81
  if (!apiConfigReady || !apiConnected) {
83
- startCalled.current = false
82
+ connectCalled.current = false
84
83
  }
85
84
  }, [apiConfigReady, apiConnected])
86
85
 
87
86
  const connectAndStart = useCallback(async () => {
88
87
  // We don't connect if we are already connected to the api to avoid multiple in-flight connection processes.
89
88
  if (!apiConnected) {
89
+ connectCalled.current = true
90
90
  await connect()
91
91
  }
92
92
 
93
- // We only start a conversation when the chat interface is either 'open' or if using the inline view if it's 'open' or 'minimized'.
94
- if (isOpen || (isVisible && isInline)) {
93
+ // We only start a conversation when the chat interface is either app, 'open' or if using the inline view if it's 'open' or 'minimized'.
94
+ if (isApp || isOpen || (isVisible && isInline)) {
95
95
  start()
96
- startCalled.current = true
97
96
  }
98
- }, [apiConnected, connect, isInline, isOpen, isVisible, start])
97
+ }, [apiConnected, connect, isApp, isInline, isOpen, isVisible, start])
99
98
 
100
99
  useEffect(() => {
101
100
  // We dont't connect or start when the apiConfig is not ready yet.
@@ -104,9 +103,9 @@ const useSeamlyChat = () => {
104
103
  // Lastly we check if the inline view is not scrolled in to view.
105
104
  if (
106
105
  !apiConfigReady ||
107
- startCalled.current ||
106
+ connectCalled.current ||
108
107
  (isWindow && !isOpen && !hasConversation()) ||
109
- (isInline && !showInlineView)
108
+ (isInline && (!isVisible || !showInlineView))
110
109
  ) {
111
110
  return
112
111
  }
@@ -127,18 +126,9 @@ const useSeamlyChat = () => {
127
126
  isInline,
128
127
  isOpen,
129
128
  isWindow,
129
+ isVisible,
130
130
  showInlineView,
131
131
  ])
132
-
133
- const openChat = () => {
134
- setVisibility(visibilityStates.open)
135
- }
136
-
137
- const closeChat = () => {
138
- setVisibility(visibilityStates.minimized)
139
- }
140
-
141
- return { openChat, closeChat }
142
132
  }
143
133
 
144
134
  export default useSeamlyChat
@@ -1,18 +1,17 @@
1
+ import { useCallback, useContext } from 'preact/hooks'
2
+ import { useDispatch } from 'react-redux'
1
3
  import { userParticipantId } from 'config'
2
- import { useUserHasResponded } from 'domains/app/hooks'
4
+ import { SeamlyEventBusContext } from 'ui/components/core/seamly-api-context'
5
+ import { actionTypes } from 'ui/utils/seamly-utils'
3
6
  import * as AppActions from 'domains/app/actions'
7
+ import { useUserHasResponded } from 'domains/app/hooks'
4
8
  import { setHasResponded } from 'domains/app/slice'
5
9
  import { useConfig } from 'domains/config/hooks'
6
10
  import { setInterrupt } from 'domains/interrupt/slice'
7
11
  import { addEvent, setInitialState } from 'domains/store/slice'
8
12
  import { visibilityStates } from 'domains/visibility/constants'
9
13
  import { useVisibility } from 'domains/visibility/hooks'
10
-
11
14
  import { randomId } from 'lib/id'
12
- import { useCallback, useContext } from 'preact/hooks'
13
- import { useDispatch } from 'react-redux'
14
- import { SeamlyEventBusContext } from 'ui/components/core/seamly-api-context'
15
- import { actionTypes } from 'ui/utils/seamly-utils'
16
15
  import {
17
16
  useSeamlyApiContext,
18
17
  useSeamlyHasConversation,
@@ -120,8 +119,13 @@ const useSeamlyCommands = () => {
120
119
  )
121
120
 
122
121
  const addMessageBubble = useCallback(
123
- (text) => {
124
- dispatch(addEvent({ type: 'message', payload: getTextMessageBase(text) }))
122
+ (text, transactionId = randomId()) => {
123
+ dispatch(
124
+ addEvent({
125
+ type: 'message',
126
+ payload: { ...getTextMessageBase(text), transactionId },
127
+ }),
128
+ )
125
129
  },
126
130
  [dispatch, getTextMessageBase],
127
131
  )
@@ -148,13 +152,13 @@ const useSeamlyCommands = () => {
148
152
  )
149
153
 
150
154
  const addDivider = useCallback(
151
- (subtype) => {
155
+ (subtype, transactionId = randomId()) => {
152
156
  const payload = {
153
157
  body: { subtype, type: 'divider' },
154
158
  fromClient: false,
155
159
  fromHistory: true,
156
160
  id: randomId(),
157
- transactionId: randomId(),
161
+ transactionId,
158
162
  type: 'divider',
159
163
  }
160
164
 
@@ -205,11 +209,12 @@ const useSeamlyCommands = () => {
205
209
  .catch((error) => {
206
210
  dispatch(
207
211
  setInterrupt({
208
- name: error.name,
209
- message: error.message,
210
- langKey: error.langKey,
211
- originalEvent: error.originalEvent,
212
- originalError: error.originalError,
212
+ name: error?.name,
213
+ message: error?.message,
214
+ langKey: error?.langKey,
215
+ action: error?.action,
216
+ originalEvent: error?.originalEvent,
217
+ originalError: error?.originalError,
213
218
  }),
214
219
  )
215
220
  })
@@ -1,19 +1,19 @@
1
+ import { useCallback, useRef } from 'preact/hooks'
2
+ import { useDispatch } from 'react-redux'
1
3
  import { screenReaderDebounceDelaySeconds } from 'config'
4
+ import {
5
+ getTimeFromSeconds,
6
+ millisecondsToSeconds,
7
+ } from 'ui/utils/general-utils'
8
+ import { actionTypes } from 'ui/utils/seamly-utils'
2
9
  import { useI18n } from 'domains/i18n/hooks'
3
- import { useVisibility } from 'domains/visibility/hooks'
4
10
  import {
5
11
  clearIdleDetachCountdown,
6
12
  decrementIdleDetachCountdownCounter,
7
13
  initIdleDetachCountdown,
8
14
  stopIdleDetachCountdownCounter,
9
15
  } from 'domains/store/slice'
10
- import { useCallback, useRef } from 'preact/hooks'
11
- import { useDispatch } from 'react-redux'
12
- import {
13
- getTimeFromSeconds,
14
- millisecondsToSeconds,
15
- } from 'ui/utils/general-utils'
16
- import { actionTypes } from 'ui/utils/seamly-utils'
16
+ import { useVisibility } from 'domains/visibility/hooks'
17
17
  import { useLiveRegion } from './live-region-hooks'
18
18
  import { useSeamlyStateContext } from './seamly-state-hooks'
19
19
  import useSeamlyCommands from './use-seamly-commands'
@@ -1,7 +1,7 @@
1
- import { useI18n } from 'domains/i18n/hooks'
2
- import { clearResumeConversationPrompt } from 'domains/store/slice'
3
1
  import { useDispatch } from 'react-redux'
4
2
  import { actionTypes, dismissTypes } from 'ui/utils/seamly-utils'
3
+ import { useI18n } from 'domains/i18n/hooks'
4
+ import { clearResumeConversationPrompt } from 'domains/store/slice'
5
5
  import { useLiveRegion } from './live-region-hooks'
6
6
  import { useSeamlyStateContext } from './seamly-state-hooks'
7
7
  import useSeamlyCommands from './use-seamly-commands'
@@ -1,5 +1,5 @@
1
- import { getControlValueByName } from 'domains/forms/selectors'
2
1
  import { useSelector } from 'react-redux'
2
+ import { getControlValueByName } from 'domains/forms/selectors'
3
3
  import { useFileUploads } from './seamly-hooks'
4
4
 
5
5
  const useSingleFileUpload = (formId, name) => {
@@ -1,4 +1,3 @@
1
- import { randomId } from 'lib/id'
2
1
  import {
3
2
  useCallback,
4
3
  useMemo,
@@ -6,6 +5,7 @@ import {
6
5
  useRef,
7
6
  useState,
8
7
  } from 'preact/hooks'
8
+ import { randomId } from 'lib/id'
9
9
 
10
10
  export const useForceUpdate = () => {
11
11
  // This is an escape hatch mentioned in the React docs:
@@ -105,29 +105,6 @@ export const formatBytes = (bytes, decimals = 2) => {
105
105
  return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`
106
106
  }
107
107
 
108
- export const getUrlParams = () => {
109
- const { search } = window.location
110
-
111
- if (!search) {
112
- return {}
113
- }
114
-
115
- const hashes = search.slice(search.indexOf('?') + 1).split('&')
116
-
117
- return hashes.reduce((acc, hash) => {
118
- const [key, val] = hash.split('=')
119
- return { ...acc, [key]: decodeURIComponent(val) }
120
- }, {})
121
- }
122
-
123
- export const getUrlSearchString = (params) => {
124
- return Object.keys(params).reduce(
125
- (search, key) =>
126
- `${search}${search ? '&' : ''}${key}=${encodeURIComponent(params[key])}`,
127
- '',
128
- )
129
- }
130
-
131
108
  export const keyCodes = {
132
109
  27: 'Escape',
133
110
  35: 'End',
@@ -46,9 +46,18 @@ export const actionTypes = {
46
46
  clickCard: 'click_card',
47
47
  }
48
48
 
49
+ export const TRANSLATION_PROPOSAL = 'translation_proposal'
50
+
49
51
  export const dismissTypes = {
50
52
  resumeConversationPrompt: 'resume_conversation_prompt',
51
- }
53
+ translationProposal: TRANSLATION_PROPOSAL,
54
+ } as const
55
+
56
+ export const sourceTypes = {
57
+ translationProposal: TRANSLATION_PROPOSAL,
58
+ translationChoice: 'translation_choice',
59
+ windowApi: 'window_api',
60
+ } as const
52
61
 
53
62
  export const ariaLiveLevels = {
54
63
  assertive: 'assertive',
@@ -0,0 +1,9 @@
1
+ // Generic ValueOf type to force value of objects
2
+ // example:
3
+ // export const objectType = {
4
+ // infoKey: 'info_key',
5
+ // messageKey: 'message_key',
6
+ // } as const <- important for Typescript
7
+ // const forceValueOf = ValueOf<typeof objectType> = objectType.infoKey GOOD
8
+ // const forceValueOf = ValueOf<typeof objectType> = "anything else" ERR
9
+ export type ValueOf<T> = T[keyof T]
@@ -81,7 +81,7 @@ $chat-window-width: $spacer * 18 !default;
81
81
  $chat-window-height: $spacer * 36 !default;
82
82
 
83
83
  // CHAT INLINE
84
- $chat-inline-height: $spacer * 32 !default;
84
+ $chat-inline-height: $spacer * 36 !default;
85
85
  $chat-inline-maxheight: 90vh !default;
86
86
 
87
87
  // CHAT SUGGESTION
@@ -71,6 +71,8 @@
71
71
  width: 100%;
72
72
  height: 100%;
73
73
  overflow: hidden;
74
+ transform: translate3d(0, 0, 0);
75
+ backface-visibility: hidden;
74
76
  transition: flex $transition, width $transition, height $transition,
75
77
  border-radius $transition;
76
78
  border: $thin-border solid set-border-color($chat-bg);
@@ -106,21 +108,34 @@
106
108
  .#{$n}-chat__container {
107
109
  display: flex;
108
110
  position: relative;
109
- flex-direction: column;
110
- width: 100%;
111
- height: 100%;
111
+ flex-grow: 1;
112
+ justify-content: center;
113
+
114
+ &__scroll-area {
115
+ overscroll-behavior: contain;
116
+ display: flex;
117
+ position: relative;
118
+ flex-direction: column;
119
+ justify-content: space-between;
120
+ width: 100%;
121
+ height: 100%;
122
+ overflow-y: auto;
123
+ will-change: scroll-position;
124
+ }
125
+
126
+ &__header {
127
+ display: flex;
128
+ position: sticky;
129
+ z-index: 1;
130
+ top: 0;
131
+ }
112
132
  }
113
133
 
114
134
  .#{$n}-chat__body {
115
135
  display: flex;
116
136
  position: relative;
117
- flex-grow: 4;
137
+ flex-grow: 1;
118
138
  padding: 0;
119
- overflow-y: auto;
120
- }
121
-
122
- .#{$n}-chat--layout-window .#{$n}-chat__body {
123
- overscroll-behavior: contain;
124
139
  }
125
140
 
126
141
  .#{$n}-chat__entry {
@@ -1,39 +1,95 @@
1
1
  .#{$n}-chat-status {
2
2
  display: flex;
3
- position: absolute;
4
3
  z-index: 1;
5
4
  top: $spacer;
6
- left: $spacer;
5
+ right: 0;
6
+ left: 0;
7
7
  align-items: center;
8
- justify-content: space-between;
9
- width: calc(100% - #{$spacer * 2});
10
- height: $buttonsize;
8
+ width: 100%;
11
9
  min-height: $buttonsize;
12
- padding: $spacer * 0.25 $spacer;
13
- border-radius: $borderradius-large;
10
+ margin: $spacer;
11
+ padding: $spacer * 0.5;
12
+ border-radius: $borderradius;
14
13
  background-color: $white;
15
14
  box-shadow: $boxshadow;
15
+
16
+ &--condensed {
17
+ padding: $spacer * 0.25;
18
+
19
+ .#{$n}-chat-status__title {
20
+ padding-left: $spacer * 0.25;
21
+ }
22
+
23
+ .#{$n}-chat-status__close {
24
+ min-height: $buttonsize-small;
25
+ padding-right: $spacer * 0.25;
26
+ }
27
+ }
16
28
  }
17
29
 
18
- &.#{$n}-app--collapsed .#{$n}-chat-status {
19
- display: none;
30
+ .#{$n}-chat--layout-window {
31
+ .#{$n}-chat-status {
32
+ margin-right: $buttonsize + $spacer * 2;
33
+ }
20
34
  }
21
35
 
22
- .#{$n}-chat--layout-window .#{$n}-chat-status {
23
- width: calc(100% - #{$spacer * 2.5 + $buttonsize});
36
+ .#{$n}-chat-status__body {
37
+ display: flex;
38
+ flex-direction: column;
39
+ flex-grow: 1;
40
+ align-items: flex-start;
41
+ justify-content: flex-start;
24
42
  }
25
43
 
26
44
  .#{$n}-chat-status__title {
27
45
  display: flex;
28
- flex: 1;
29
- align-items: center;
30
46
  margin: 0 $spacer * 0.5 0 0;
31
47
  color: $grey-e;
32
- font-size: $fontsize-small;
48
+ font-size: $fontsize-medium;
33
49
  font-weight: $fontweight-bold;
34
50
  line-height: 1.25;
51
+
52
+ + .#{$n}-chat-status__button {
53
+ margin-top: $spacer * 0.5;
54
+ }
55
+ }
56
+
57
+ .#{$n}-chat-status .#{$n}-icon {
58
+ flex: 0 0 $iconsize-small;
59
+ width: $iconsize-small;
60
+ height: $iconsize-small;
35
61
  }
36
62
 
37
- .#{$n}-chat-status .#{$n}-button--tertiary {
38
- color: $interaction;
63
+ .#{$n}-chat-status__button {
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: flex-end;
67
+ min-height: $buttonsize-small;
68
+ padding: $spacer * 0.25 $spacer * 0.5;
69
+ color: $white;
70
+
71
+ .#{$n}-icon {
72
+ margin-right: $spacer * 0.25;
73
+
74
+ svg {
75
+ width: 100%;
76
+ height: 100%;
77
+
78
+ path {
79
+ fill: $white;
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ .#{$n}-chat-status__close {
86
+ display: inline-flex;
87
+ align-self: flex-start;
88
+ justify-content: center;
89
+ min-height: $buttonsize-small - $spacer * 0.5;
90
+ color: $brand3;
91
+
92
+ .#{$n}-icon {
93
+ align-self: center;
94
+ }
39
95
  }
@@ -34,7 +34,7 @@
34
34
  }
35
35
 
36
36
  .#{$n}-chat-status
37
- ~ .#{$n}-chat__container
37
+ ~ .#{$n}-chat__container__scroll-area
38
38
  .#{$n}-disclaimer
39
39
  + .#{$n}-conversation {
40
40
  padding-top: 0;
@@ -66,3 +66,37 @@
66
66
  margin-bottom: 0;
67
67
  }
68
68
  }
69
+
70
+ .#{$n}-unread-messages {
71
+ display: none;
72
+ position: absolute;
73
+ bottom: 0;
74
+ align-items: center;
75
+ justify-content: center;
76
+ margin: $spacer;
77
+ opacity: 0;
78
+
79
+ > .#{$n}-button {
80
+ display: flex;
81
+ align-items: center;
82
+
83
+ > .#{$n}-icon {
84
+ width: $spacer;
85
+ height: $spacer;
86
+ margin-left: calc($spacer / 2);
87
+
88
+ svg path {
89
+ fill: $white;
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ .#{$n}-unread-messages.#{$n}-transition--visible {
96
+ display: flex;
97
+ }
98
+
99
+ .#{$n}-unread-messages.#{$n}-transition--in {
100
+ transition: opacity $transition 1000ms;
101
+ opacity: 1;
102
+ }
@@ -11,11 +11,6 @@
11
11
  padding-right: $buttonsize + $spacer * 2;
12
12
  }
13
13
 
14
- .#{$n}-chat-status ~ .#{$n}-chat__container .#{$n}-disclaimer {
15
- margin-top: $buttonsize + $spacer * 2;
16
- padding: $spacer * 0.5 $spacer;
17
- }
18
-
19
14
  .#{$n}-disclaimer__title {
20
15
  margin: 0 0 $spacer * 0.25;
21
16
  padding-right: $spacer;
@@ -94,6 +94,7 @@
94
94
  .#{$n}-options {
95
95
  display: none;
96
96
  position: absolute;
97
+ z-index: 10;
97
98
  right: $spacer * 0.5;
98
99
  bottom: calc(100% + (#{$spacer} * 0.5));
99
100
  flex-direction: column;
@@ -101,8 +102,6 @@
101
102
  max-width: $spacer * 15;
102
103
  margin: 0;
103
104
  padding: 0;
104
- transform: scaleY(0) translateY($spacer * 5);
105
- transform-origin: 100% 100%;
106
105
  transition: transform 0.2s ease-in-out, opacity 0.2s ease;
107
106
  border: $thin-border solid $grey-b;
108
107
  border-radius: $borderradius-small;
@@ -121,6 +120,20 @@
121
120
  right: $spacer * 0.5;
122
121
  }
123
122
 
123
+ .#{$n}-options--top {
124
+ top: initial;
125
+ bottom: calc(100% + $spacer * 0.5);
126
+ transform: scaleY(0) translateY($spacer * 5);
127
+ transform-origin: 100% 100%;
128
+ }
129
+
130
+ .#{$n}-options--bottom {
131
+ top: calc(100% + $spacer * 0.5);
132
+ bottom: initial;
133
+ transform: scaleY(0) translateY(-$spacer * 5);
134
+ transform-origin: 0 0;
135
+ }
136
+
124
137
  .#{$n}-options__dialog.#{$n}-transition--visible .#{$n}-options {
125
138
  display: flex;
126
139
  }
@@ -201,10 +214,6 @@
201
214
  }
202
215
  }
203
216
 
204
- .#{$n}-options__body div {
205
- width: 100%;
206
- }
207
-
208
217
  .#{$n}-options__wrapper h3 {
209
218
  margin: 0;
210
219
  color: $brand2;
@@ -216,6 +225,7 @@
216
225
  display: block;
217
226
  width: 100%;
218
227
  margin-bottom: $spacer * 0.5;
228
+ padding: 0 $spacer;
219
229
  font-size: $fontsize-medium;
220
230
  }
221
231