@seamly/web-ui 20.7.0 → 20.8.0-alpha.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 (222) hide show
  1. package/CHANGELOG.md +212 -16
  2. package/build/dist/lib/hooks.js +1 -1
  3. package/build/dist/lib/hooks.min.js +1 -1
  4. package/build/dist/lib/index.debug.js +939 -784
  5. package/build/dist/lib/index.debug.min.js +1 -1
  6. package/build/dist/lib/index.debug.min.js.LICENSE.txt +186 -130
  7. package/build/dist/lib/index.js +24806 -19703
  8. package/build/dist/lib/index.min.js +1 -1
  9. package/build/dist/lib/index.min.js.LICENSE.txt +38 -4
  10. package/build/dist/lib/standalone.js +32726 -26838
  11. package/build/dist/lib/standalone.min.js +1 -1
  12. package/build/dist/lib/standalone.min.js.LICENSE.txt +39 -0
  13. package/build/dist/lib/storage.js +2 -2
  14. package/build/dist/lib/storage.min.js +1 -1
  15. package/build/dist/lib/style-guide.js +8649 -7863
  16. package/build/dist/lib/style-guide.min.js +2 -1
  17. package/build/dist/lib/style-guide.min.js.LICENSE.txt +38 -0
  18. package/build/dist/lib/utils.js +1 -2
  19. package/build/dist/lib/utils.min.js +1 -1
  20. package/package.json +19 -9
  21. package/src/icons/avatar_agent-32.svg +7 -0
  22. package/src/icons/avatar_bot-32.svg +6 -1
  23. package/src/javascripts/api/index.js +1 -1
  24. package/src/javascripts/{config.js → config.ts} +3 -1
  25. package/src/javascripts/config.types.ts +95 -0
  26. package/src/javascripts/domains/app/actions.ts +83 -0
  27. package/src/javascripts/domains/app/app.types.ts +3 -0
  28. package/src/javascripts/domains/app/hooks.js +3 -5
  29. package/src/javascripts/domains/app/selectors.ts +6 -0
  30. package/src/javascripts/domains/app/slice.ts +30 -0
  31. package/src/javascripts/domains/config/actions.ts +45 -0
  32. package/src/javascripts/domains/config/hooks.ts +19 -0
  33. package/src/javascripts/domains/config/selectors.ts +24 -0
  34. package/src/javascripts/domains/config/slice.ts +111 -0
  35. package/src/javascripts/domains/errors/index.js +13 -9
  36. package/src/javascripts/domains/forms/context.ts +14 -0
  37. package/src/javascripts/domains/forms/forms.types.ts +24 -0
  38. package/src/javascripts/domains/forms/{hooks.js → hooks.ts} +23 -26
  39. package/src/javascripts/domains/forms/{provider.js → provider.tsx} +20 -14
  40. package/src/javascripts/domains/forms/{selectors.js → selectors.ts} +7 -8
  41. package/src/javascripts/domains/forms/slice.ts +84 -0
  42. package/src/javascripts/domains/forms/utils.ts +15 -0
  43. package/src/javascripts/domains/i18n/actions.ts +24 -0
  44. package/src/javascripts/domains/i18n/{hooks.js → hooks.ts} +2 -2
  45. package/src/javascripts/domains/i18n/i18n.types.ts +6 -0
  46. package/src/javascripts/domains/i18n/selectors.ts +16 -0
  47. package/src/javascripts/domains/i18n/{reducer.js → slice.ts} +43 -37
  48. package/src/javascripts/domains/interrupt/{hooks.js → hooks.ts} +2 -2
  49. package/src/javascripts/domains/interrupt/{middleware.js → middleware.ts} +11 -8
  50. package/src/javascripts/domains/interrupt/selectors.ts +6 -0
  51. package/src/javascripts/domains/interrupt/slice.ts +40 -0
  52. package/src/javascripts/domains/options/middleware.js +9 -6
  53. package/src/javascripts/domains/redux/redux.types.ts +11 -0
  54. package/src/javascripts/domains/store/index.ts +53 -0
  55. package/src/javascripts/domains/store/slice.ts +639 -0
  56. package/src/javascripts/domains/store/store.types.ts +135 -0
  57. package/src/javascripts/domains/translations/components/chat-status.js +2 -2
  58. package/src/javascripts/domains/translations/components/options-button.js +1 -1
  59. package/src/javascripts/domains/translations/components/options-dialog/form.js +5 -5
  60. package/src/javascripts/domains/translations/components/options-dialog/index.js +2 -2
  61. package/src/javascripts/domains/translations/{hooks.js → hooks.ts} +28 -23
  62. package/src/javascripts/domains/translations/middleware.js +29 -27
  63. package/src/javascripts/domains/translations/selectors.js +4 -9
  64. package/src/javascripts/domains/translations/slice.ts +67 -0
  65. package/src/javascripts/domains/translations/translations.types.ts +12 -0
  66. package/src/javascripts/domains/visibility/{actions.js → actions.ts} +25 -19
  67. package/src/javascripts/domains/visibility/{hooks.js → hooks.ts} +13 -10
  68. package/src/javascripts/domains/visibility/{selectors.js → selectors.ts} +3 -6
  69. package/src/javascripts/domains/visibility/slice.ts +38 -0
  70. package/src/javascripts/domains/visibility/utils.js +0 -9
  71. package/src/javascripts/domains/visibility/visibility.types.ts +6 -0
  72. package/src/javascripts/index.ts +92 -0
  73. package/src/javascripts/lib/engine/index.js +15 -11
  74. package/src/javascripts/lib/external-api/initialize-api.js +1 -1
  75. package/src/javascripts/lib/id.js +5 -8
  76. package/src/javascripts/lib/mutex.js +3 -1
  77. package/src/javascripts/lib/store/providers/cookie-storage.js +1 -1
  78. package/src/javascripts/lib/store/providers/session-storage.js +1 -1
  79. package/src/javascripts/package/hooks.js +2 -2
  80. package/src/javascripts/package/utils.js +0 -1
  81. package/src/javascripts/schema.ts +1455 -0
  82. package/src/javascripts/style-guide/components/app.js +4 -4
  83. package/src/javascripts/style-guide/components/static-core.js +87 -65
  84. package/src/javascripts/style-guide/components/view.js +4 -4
  85. package/src/javascripts/style-guide/state-helpers/index.js +5 -5
  86. package/src/javascripts/style-guide/states.js +6 -4
  87. package/src/javascripts/style-guide.ts +5 -0
  88. package/src/javascripts/ui/components/app-options/index.js +2 -4
  89. package/src/javascripts/ui/components/conversation/component-filter.js +1 -1
  90. package/src/javascripts/ui/components/conversation/conversation.js +5 -5
  91. package/src/javascripts/ui/components/conversation/event/card-message.js +1 -1
  92. package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js +1 -1
  93. package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +1 -1
  94. package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +1 -1
  95. package/src/javascripts/ui/components/conversation/event/choice-prompt.js +2 -2
  96. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +11 -14
  97. package/src/javascripts/ui/components/conversation/event/cta.js +1 -1
  98. package/src/javascripts/ui/components/conversation/event/divider/variants/default.js +1 -1
  99. package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +5 -2
  100. package/src/javascripts/ui/components/conversation/event/event-participant.js +2 -2
  101. package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +2 -2
  102. package/src/javascripts/ui/components/conversation/event/image-lightbox.js +1 -1
  103. package/src/javascripts/ui/components/conversation/event/image.js +5 -7
  104. package/src/javascripts/ui/components/conversation/event/participant.js +1 -1
  105. package/src/javascripts/ui/components/conversation/event/splash.js +3 -3
  106. package/src/javascripts/ui/components/conversation/event/text.js +1 -1
  107. package/src/javascripts/ui/components/conversation/event/translation.js +2 -2
  108. package/src/javascripts/ui/components/conversation/event/upload.js +2 -2
  109. package/src/javascripts/ui/components/conversation/event/video.js +1 -1
  110. package/src/javascripts/ui/components/conversation/message-container.js +4 -4
  111. package/src/javascripts/ui/components/core/seamly-api-context.js +1 -1
  112. package/src/javascripts/ui/components/core/seamly-core.js +15 -14
  113. package/src/javascripts/ui/components/core/seamly-event-subscriber.js +96 -91
  114. package/src/javascripts/ui/components/core/seamly-file-upload.js +20 -24
  115. package/src/javascripts/ui/components/core/seamly-initializer.js +1 -1
  116. package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +5 -4
  117. package/src/javascripts/ui/components/core/seamly-new-notifications.js +2 -2
  118. package/src/javascripts/ui/components/core/seamly-read-state.js +10 -17
  119. package/src/javascripts/ui/components/entry/deprecated-toggle-button.js +3 -3
  120. package/src/javascripts/ui/components/entry/entry-container.js +4 -6
  121. package/src/javascripts/ui/components/entry/text-entry/hooks.js +3 -3
  122. package/src/javascripts/ui/components/entry/text-entry/index.js +3 -2
  123. package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +6 -10
  124. package/src/javascripts/ui/components/entry/upload/file-upload-form.js +2 -2
  125. package/src/javascripts/ui/components/entry/upload/index.js +10 -9
  126. package/src/javascripts/ui/components/entry/upload-toggle.js +2 -2
  127. package/src/javascripts/ui/components/faq/faq.js +6 -6
  128. package/src/javascripts/ui/components/form-controls/file-input.js +1 -1
  129. package/src/javascripts/ui/components/form-controls/form.js +1 -1
  130. package/src/javascripts/ui/components/form-controls/input.js +1 -1
  131. package/src/javascripts/ui/components/form-controls/select.js +1 -1
  132. package/src/javascripts/ui/components/layout/agent-info.js +4 -4
  133. package/src/javascripts/ui/components/layout/chat-frame.js +3 -3
  134. package/src/javascripts/ui/components/layout/chat.js +11 -12
  135. package/src/javascripts/ui/components/layout/deprecated-app-frame.js +10 -9
  136. package/src/javascripts/ui/components/layout/header.js +1 -1
  137. package/src/javascripts/ui/components/layout/interrupt.js +23 -24
  138. package/src/javascripts/ui/components/layout/pre-chat-messages.js +11 -11
  139. package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
  140. package/src/javascripts/ui/components/options/options-button.js +12 -10
  141. package/src/javascripts/ui/components/options/transcript/index.js +2 -2
  142. package/src/javascripts/ui/components/options/transcript/transcript-form.js +1 -1
  143. package/src/javascripts/ui/components/suggestions/index.js +9 -8
  144. package/src/javascripts/ui/components/view/deprecated-view.js +19 -16
  145. package/src/javascripts/ui/components/view/index.js +12 -12
  146. package/src/javascripts/ui/components/view/inline-view.js +2 -2
  147. package/src/javascripts/ui/components/view/window-view/collapse-button.js +3 -3
  148. package/src/javascripts/ui/components/view/window-view/index.js +13 -13
  149. package/src/javascripts/ui/components/view/window-view/window-open-button.js +13 -13
  150. package/src/javascripts/ui/components/warnings/idle-detach-warning.js +1 -1
  151. package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +1 -1
  152. package/src/javascripts/ui/components/widgets/lightbox.js +2 -2
  153. package/src/javascripts/ui/components/widgets/upload-progress.js +1 -1
  154. package/src/javascripts/ui/hooks/component-helper-hooks.js +1 -1
  155. package/src/javascripts/ui/hooks/file-upload-hooks.js +4 -6
  156. package/src/javascripts/ui/hooks/focus-helper-hooks.js +14 -12
  157. package/src/javascripts/ui/hooks/live-region-hooks.js +2 -0
  158. package/src/javascripts/ui/hooks/seamly-api-hooks.js +8 -3
  159. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +28 -25
  160. package/src/javascripts/ui/hooks/seamly-hooks.js +25 -25
  161. package/src/javascripts/ui/hooks/seamly-option-hooks.js +17 -19
  162. package/src/javascripts/ui/hooks/seamly-state-hooks.js +14 -13
  163. package/src/javascripts/ui/hooks/use-seamly-chat.js +15 -25
  164. package/src/javascripts/ui/hooks/use-seamly-commands.js +46 -46
  165. package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +22 -24
  166. package/src/javascripts/ui/hooks/use-seamly-resume-conversation-prompt.js +8 -9
  167. package/src/javascripts/ui/hooks/use-single-file-upload.js +4 -6
  168. package/src/javascripts/ui/hooks/utility-hooks.js +4 -4
  169. package/src/javascripts/ui/utils/form-utils.js +0 -145
  170. package/src/javascripts/ui/utils/general-utils.js +3 -4
  171. package/src/javascripts/ui/utils/seamly-utils.ts +73 -0
  172. package/webpack/config.common.js +16 -0
  173. package/webpack/config.dev.js +1 -0
  174. package/webpack/config.package.js +26 -5
  175. package/webpack/defaults.js +7 -2
  176. package/webpack/parts/babel-loader-browser-plugins.js +1 -0
  177. package/webpack/parts/dev-server.js +4 -3
  178. package/src/javascripts/domains/app/actions.js +0 -112
  179. package/src/javascripts/domains/app/index.js +0 -7
  180. package/src/javascripts/domains/app/reducer.js +0 -16
  181. package/src/javascripts/domains/app/selectors.js +0 -8
  182. package/src/javascripts/domains/app/utils.js +0 -4
  183. package/src/javascripts/domains/config/actions.js +0 -7
  184. package/src/javascripts/domains/config/hooks.js +0 -23
  185. package/src/javascripts/domains/config/index.js +0 -7
  186. package/src/javascripts/domains/config/reducer.js +0 -79
  187. package/src/javascripts/domains/config/selectors.js +0 -23
  188. package/src/javascripts/domains/config/utils.js +0 -4
  189. package/src/javascripts/domains/forms/actions.js +0 -21
  190. package/src/javascripts/domains/forms/context.js +0 -6
  191. package/src/javascripts/domains/forms/index.js +0 -8
  192. package/src/javascripts/domains/forms/reducer.js +0 -84
  193. package/src/javascripts/domains/forms/utils.js +0 -20
  194. package/src/javascripts/domains/i18n/actions.js +0 -20
  195. package/src/javascripts/domains/i18n/index.js +0 -7
  196. package/src/javascripts/domains/i18n/selectors.js +0 -15
  197. package/src/javascripts/domains/i18n/utils.js +0 -4
  198. package/src/javascripts/domains/interrupt/actions.js +0 -4
  199. package/src/javascripts/domains/interrupt/index.js +0 -9
  200. package/src/javascripts/domains/interrupt/reducer.js +0 -22
  201. package/src/javascripts/domains/interrupt/selectors.js +0 -6
  202. package/src/javascripts/domains/interrupt/utils.js +0 -4
  203. package/src/javascripts/domains/options/index.js +0 -1
  204. package/src/javascripts/domains/redux/context.js +0 -6
  205. package/src/javascripts/domains/redux/create-redux-store.js +0 -21
  206. package/src/javascripts/domains/redux/hooks.js +0 -80
  207. package/src/javascripts/domains/redux/index.js +0 -19
  208. package/src/javascripts/domains/redux/provider.js +0 -5
  209. package/src/javascripts/domains/redux/utils.js +0 -12
  210. package/src/javascripts/domains/store/index.js +0 -46
  211. package/src/javascripts/domains/store/state-reducer.js +0 -56
  212. package/src/javascripts/domains/translations/actions.js +0 -11
  213. package/src/javascripts/domains/translations/index.js +0 -10
  214. package/src/javascripts/domains/translations/reducer.js +0 -69
  215. package/src/javascripts/domains/translations/utils.js +0 -4
  216. package/src/javascripts/domains/visibility/index.js +0 -8
  217. package/src/javascripts/domains/visibility/reducer.js +0 -24
  218. package/src/javascripts/index.js +0 -153
  219. package/src/javascripts/lib/redux-helpers/index.js +0 -99
  220. package/src/javascripts/style-guide.js +0 -5
  221. package/src/javascripts/ui/hooks/use-seamly-dispatch.js +0 -3
  222. package/src/javascripts/ui/utils/seamly-utils.js +0 -832
@@ -1,19 +1,19 @@
1
+ import { useStartChatIcon } from 'domains/config/hooks'
2
+ import { useI18n } from 'domains/i18n/hooks'
3
+ import { useInterrupt } from 'domains/interrupt/hooks'
4
+ import { useVisibility } from 'domains/visibility/hooks'
5
+ import { className } from 'lib/css'
6
+ import Icon from 'ui/components/layout/icon'
1
7
  import { useCallback } from 'preact/hooks'
2
- import { className } from '../../../../lib/css'
8
+ import InOutTransition, {
9
+ transitionStartStates,
10
+ } from 'ui/components/widgets/in-out-transition'
11
+ import { useSkiplinkTargetFocusing } from 'ui/hooks/focus-helper-hooks'
12
+ import { useSeamlyHasConversation } from 'ui/hooks/seamly-api-hooks'
3
13
  import {
4
14
  useSeamlyCurrentAgent,
5
15
  useSeamlyUnreadCount,
6
- useSkiplinkTargetFocusing,
7
- } from '../../../hooks/seamly-hooks'
8
- import { useI18n } from '../../../../domains/i18n'
9
- import { useStartChatIcon } from '../../../../domains/config'
10
- import { useVisibility } from '../../../../domains/visibility'
11
- import Icon from '../../layout/icon'
12
- import { useInterrupt } from '../../../../domains/interrupt'
13
- import InOutTransition, {
14
- transitionStartStates,
15
- } from '../../widgets/in-out-transition'
16
- import { useSeamlyHasConversation } from '../../../hooks/seamly-api-hooks'
16
+ } from 'ui/hooks/seamly-state-hooks'
17
17
 
18
18
  const ButtonIcon = () => {
19
19
  const startChatIcon = useStartChatIcon()
@@ -35,7 +35,7 @@ const ButtonIcon = () => {
35
35
  const WindowOpenButton = ({ onClick }) => {
36
36
  const hasConversation = useSeamlyHasConversation()
37
37
  const { t } = useI18n()
38
- const ariaLabel = hasConversation
38
+ const ariaLabel = hasConversation()
39
39
  ? t('window.openButton.srContinue')
40
40
  : t('window.openButton.srStart')
41
41
  const focusSkiplinkTarget = useSkiplinkTargetFocusing()
@@ -1,5 +1,5 @@
1
1
  import { className } from 'lib/css'
2
- import { useI18n } from 'domains/i18n'
2
+ import { useI18n } from 'domains/i18n/hooks'
3
3
  import useSeamlyIdleDetachCountdown from 'ui/hooks/use-seamly-idle-detach-countdown'
4
4
  import { useSkiplinkTargetFocusing } from 'ui/hooks/focus-helper-hooks'
5
5
  import useSeamlyActivityEventHandler from 'ui/hooks/use-seamly-activity-event-handler'
@@ -1,5 +1,5 @@
1
1
  import { className } from 'lib/css'
2
- import { useI18n } from 'domains/i18n'
2
+ import { useI18n } from 'domains/i18n/hooks'
3
3
  import useSeamlyResumeConversationPrompt from 'ui/hooks/use-seamly-resume-conversation-prompt'
4
4
  import useSeamlyActivityEventHandler from 'ui/hooks/use-seamly-activity-event-handler'
5
5
  import { useSeamlyCurrentAgent } from 'ui/hooks/seamly-state-hooks'
@@ -1,12 +1,12 @@
1
1
  import { useRef } from 'preact/hooks'
2
- import { useI18n } from 'domains/i18n'
2
+ import { useI18n } from 'domains/i18n/hooks'
3
3
  import {
4
4
  useSeamlyActivityEventHandler,
5
5
  useSeamlyAppContainerClassNames,
6
6
  } from 'ui/hooks/seamly-hooks'
7
7
  import { className } from 'lib/css'
8
8
  import Icon from 'ui/components/layout/icon'
9
- import { useConfig } from 'domains/config'
9
+ import { useConfig } from 'domains/config/hooks'
10
10
  import Modal from './modal'
11
11
 
12
12
  const Lightbox = ({ url, description, onClose: onCloseHandler }) => {
@@ -1,6 +1,6 @@
1
1
  import { className } from 'lib/css'
2
2
  import { useFileUploads } from 'ui/hooks/seamly-hooks'
3
- import { useI18n } from 'domains/i18n'
3
+ import { useI18n } from 'domains/i18n/hooks'
4
4
  import Error from 'ui/components/form-controls/error'
5
5
 
6
6
  const UploadProgress = () => {
@@ -1,4 +1,4 @@
1
- import { useConfig } from 'domains/config'
1
+ import { useConfig } from 'domains/config/hooks'
2
2
 
3
3
  export const useSeamlyAppContainerClassNames = () => {
4
4
  return useConfig().appContainerClassNames
@@ -1,10 +1,8 @@
1
+ import { clearAllUploads } from 'domains/store/slice'
1
2
  import { useCallback, useContext } from 'preact/hooks'
3
+ import { useDispatch } from 'react-redux'
2
4
  import SeamlyFileUploadContext from 'ui/components/core/seamly-file-upload-context'
3
- import { seamlyActions } from 'ui/utils/seamly-utils'
4
5
  import { useSeamlyStateContext } from './seamly-state-hooks'
5
- import useSeamlyDispatchContext from './use-seamly-dispatch'
6
-
7
- const { CLEAR_ALL_UPLOADS } = seamlyActions
8
6
 
9
7
  const useSeamlyFileUploadContext = () => useContext(SeamlyFileUploadContext)
10
8
 
@@ -47,7 +45,7 @@ export const useFileUploadMeta = () => {
47
45
 
48
46
  export const useFileUploads = () => {
49
47
  const { currentUploads } = useSeamlyStateContext()
50
- const dispatch = useSeamlyDispatchContext()
48
+ const dispatch = useDispatch()
51
49
  const upload = useSeamlyFileUploadContext()
52
50
 
53
51
  const uploadFile = useCallback(
@@ -58,7 +56,7 @@ export const useFileUploads = () => {
58
56
  )
59
57
 
60
58
  const clearUploads = useCallback(() => {
61
- dispatch({ type: CLEAR_ALL_UPLOADS })
59
+ dispatch(clearAllUploads())
62
60
  }, [dispatch])
63
61
 
64
62
  return {
@@ -1,36 +1,38 @@
1
+ import { setSeamlyContainerElement } from 'domains/store/slice'
1
2
  import { useCallback, useRef } from 'preact/hooks'
3
+ import { useDispatch } from 'react-redux'
2
4
  import {
3
5
  focusElement,
4
6
  runIfElementContainsOrHasFocus,
5
7
  } from 'ui/utils/general-utils'
6
- import { seamlyActions } from 'ui/utils/seamly-utils'
7
8
  import { useSeamlyStateContext, useSkiplink } from './seamly-state-hooks'
8
- import useSeamlyDispatchContext from './use-seamly-dispatch'
9
9
 
10
- const { SET_SEAMLY_CONTAINER_ELEMENT } = seamlyActions
10
+ export const timeout = (ms = 0) =>
11
+ new Promise((resolve) => {
12
+ setTimeout(resolve, ms)
13
+ })
11
14
 
12
15
  const focusWithRaf = (el) => {
13
- requestAnimationFrame(() => {
14
- requestAnimationFrame(() => {
15
- const focusEl = typeof el === 'string' ? document.getElementById(el) : el
16
- focusElement(focusEl)
17
- })
16
+ requestAnimationFrame(async () => {
17
+ await timeout(180) // wait for next 3 ticks
18
+ const focusEl = typeof el === 'string' ? document.getElementById(el) : el
19
+ focusElement(focusEl)
18
20
  })
19
21
  }
20
22
 
21
23
  export const useSeamlyContainerElement = () => {
22
24
  const { seamlyContainerElement } = useSeamlyStateContext()
23
25
 
24
- const dispatch = useSeamlyDispatchContext()
26
+ const dispatch = useDispatch()
25
27
 
26
- const setSeamlyContainerElement = useCallback(
28
+ const dispatchSeamlyContainerElement = useCallback(
27
29
  (element) => {
28
- dispatch({ type: SET_SEAMLY_CONTAINER_ELEMENT, element })
30
+ dispatch(setSeamlyContainerElement(element))
29
31
  },
30
32
  [dispatch],
31
33
  )
32
34
 
33
- return [seamlyContainerElement, setSeamlyContainerElement]
35
+ return [seamlyContainerElement, dispatchSeamlyContainerElement]
34
36
  }
35
37
 
36
38
  export const useElementFocusingById = (elementId) =>
@@ -9,6 +9,7 @@ export const useLiveRegion = () => {
9
9
  const sendMessage = useSeamlyLiveRegionContext()
10
10
  const sendPolite = useCallback(
11
11
  (messageText) => {
12
+ if (!messageText) return
12
13
  sendMessage({
13
14
  ariaLive: ariaLiveLevels.polite,
14
15
  messageText,
@@ -18,6 +19,7 @@ export const useLiveRegion = () => {
18
19
  )
19
20
  const sendAssertive = useCallback(
20
21
  (messageText) => {
22
+ if (!messageText) return
21
23
  sendMessage({
22
24
  ariaLive: ariaLiveLevels.assertive,
23
25
  messageText,
@@ -1,4 +1,4 @@
1
- import { useContext } from 'preact/hooks'
1
+ import { useCallback, useContext } from 'preact/hooks'
2
2
  import { SeamlyApiContext } from 'ui/components/core/seamly-api-context'
3
3
 
4
4
  export const useSeamlyApiContext = () => useContext(SeamlyApiContext)
@@ -19,6 +19,11 @@ export const useSeamlyConversationUrl = () => {
19
19
  }
20
20
 
21
21
  export const useSeamlyHasConversation = () => {
22
- const url = useSeamlyConversationUrl()
23
- return !!url
22
+ const api = useSeamlyApiContext()
23
+
24
+ const hasConversation = useCallback(() => {
25
+ return api.hasConversation()
26
+ }, [api])
27
+
28
+ return hasConversation
24
29
  }
@@ -1,16 +1,14 @@
1
- import { useRef, useCallback, useEffect } from 'preact/hooks'
2
- import { seamlyActions, actionTypes } from 'ui/utils/seamly-utils'
3
1
  import { typingTimeout } from 'config'
4
- import { useSeamlyStateContext } from './seamly-state-hooks'
5
- import useSeamlyDispatchContext from './use-seamly-dispatch'
6
- import { useSeamlyOptions } from './seamly-option-hooks'
7
- import useSeamlyCommands from './use-seamly-commands'
8
-
9
- const {
10
- SET_BLOCK_AUTO_ENTRY_SWITCH,
11
- SET_ACTIVE_ENTRY_TYPE,
12
- SET_USER_ENTRY_TYPE,
13
- } = seamlyActions
2
+ import {
3
+ setBlockAutoEntrySwitch,
4
+ setActiveEntryType,
5
+ setUserEntryType,
6
+ } from 'domains/store/slice'
7
+ import { useSeamlyCommands, useSeamlyOptions } from 'ui/hooks/seamly-hooks'
8
+ import { useRef, useEffect, useCallback } from 'preact/hooks'
9
+ import { useSeamlyStateContext } from 'ui/hooks/seamly-state-hooks'
10
+ import { useDispatch } from 'react-redux'
11
+ import { actionTypes } from 'ui/utils/seamly-utils'
14
12
 
15
13
  export const useSeamlyTyping = () => {
16
14
  const { sendAction } = useSeamlyCommands()
@@ -82,47 +80,52 @@ export const useSeamlyEntry = () => {
82
80
  options: entryOptions,
83
81
  optionsOverride: entryOptionsOverride,
84
82
  } = useSeamlyStateContext().entryMeta
85
- const dispatch = useSeamlyDispatchContext()
83
+ const dispatch = useDispatch()
86
84
 
87
85
  const activeEntry = userSelected || active || defaultEntry
88
86
  const activeEntryOptions =
89
87
  entryOptionsOverride[activeEntry] || entryOptions[activeEntry] || {}
90
88
 
91
- const setBlockAutoEntrySwitch = useCallback(
89
+ const dispatchBlockAutoEntrySwitch = useCallback(
92
90
  (value) => {
93
- dispatch({ type: SET_BLOCK_AUTO_ENTRY_SWITCH, value })
91
+ dispatch(setBlockAutoEntrySwitch(value))
94
92
  },
95
93
  [dispatch],
96
94
  )
97
95
 
98
- const setActiveEntryType = useCallback(
96
+ const dispatchActiveEntryType = useCallback(
99
97
  (entryType) => {
100
- dispatch({ type: SET_ACTIVE_ENTRY_TYPE, entryType })
98
+ dispatch(setActiveEntryType(entryType))
101
99
  },
102
100
  [dispatch],
103
101
  )
104
102
 
105
- const setUserEntryType = useCallback(
103
+ const dispatchUserEntryType = useCallback(
106
104
  (entryType) => {
107
- dispatch({ type: SET_USER_ENTRY_TYPE, entryType })
105
+ dispatch(setUserEntryType(entryType))
108
106
  },
109
107
  [dispatch],
110
108
  )
111
109
 
112
110
  const cancelEntrySelection = useCallback(() => {
113
111
  if (userSelected) {
114
- setUserEntryType(null)
112
+ dispatchUserEntryType(null)
115
113
  } else {
116
- setActiveEntryType(defaultEntry)
114
+ dispatchActiveEntryType(defaultEntry)
117
115
  }
118
- }, [userSelected, defaultEntry, setUserEntryType, setActiveEntryType])
116
+ }, [
117
+ userSelected,
118
+ defaultEntry,
119
+ dispatchUserEntryType,
120
+ dispatchActiveEntryType,
121
+ ])
119
122
 
120
123
  return {
121
124
  activeEntry,
122
125
  activeEntryOptions,
123
- setActiveEntryType,
124
- setUserEntryType,
126
+ setActiveEntryType: dispatchActiveEntryType,
127
+ setUserEntryType: dispatchUserEntryType,
125
128
  cancelEntrySelection,
126
- setBlockAutoEntrySwitch,
129
+ setBlockAutoEntrySwitch: dispatchBlockAutoEntrySwitch,
127
130
  }
128
131
  }
@@ -1,4 +1,5 @@
1
1
  import { useEffect } from 'preact/hooks'
2
+ import { useDispatch } from 'react-redux'
2
3
 
3
4
  // Import extracted hooks here for use inside this file
4
5
  import { useSeamlyApiContext } from './seamly-api-hooks'
@@ -6,10 +7,27 @@ import { useSeamlyApiContext } from './seamly-api-hooks'
6
7
  // although this is a redundant, it prevents a bazillion code changes for now.
7
8
  // TODO: Remove exports and import them from the correct files
8
9
  export {
9
- useLastMessageEventId,
10
+ useElementFocusingById,
11
+ useFocusIfSeamlyContainedFocus,
12
+ useSeamlyContainerElement,
13
+ useSkiplinkTargetFocusing,
14
+ } from 'ui/hooks/focus-helper-hooks'
15
+ export {
16
+ useSeamlyAppContainerClassNames,
17
+ useSeamlyMessageContainerClassNames,
18
+ } from './component-helper-hooks'
19
+ export { useFileUploadMeta, useFileUploads } from './file-upload-hooks'
20
+ export { useLiveRegion, useSeamlyLiveRegionContext } from './live-region-hooks'
21
+ export {
22
+ useSeamlyApiContext,
23
+ useSeamlyConversationUrl,
24
+ } from './seamly-api-hooks'
25
+ export { useOptionButton, useSeamlyOptions } from './seamly-option-hooks'
26
+ export {
10
27
  useEntryTextLimit,
11
- useSeamlyCurrentAgent,
12
28
  useEvents,
29
+ useLastMessageEventId,
30
+ useSeamlyCurrentAgent,
13
31
  useSeamlyHeaderData,
14
32
  useSeamlyIsHistoryLoaded,
15
33
  useSeamlyIsLoading,
@@ -21,35 +39,17 @@ export {
21
39
  useSeamlyUnreadCount,
22
40
  useSkiplink,
23
41
  } from './seamly-state-hooks'
24
- export {
25
- useSeamlyApiContext,
26
- useSeamlyConversationUrl,
27
- } from './seamly-api-hooks'
28
- export { default as useSeamlyDispatchContext } from './use-seamly-dispatch'
29
- export {
30
- useSeamlyAppContainerClassNames,
31
- useSeamlyMessageContainerClassNames,
32
- } from './component-helper-hooks'
33
- export { useSeamlyOptions, useOptionButton } from './seamly-option-hooks'
34
- export { useFileUploadMeta, useFileUploads } from './file-upload-hooks'
35
- export { default as useSeamlyCommands } from './use-seamly-commands'
36
- export { useLiveRegion, useSeamlyLiveRegionContext } from './live-region-hooks'
37
42
  export { default as useSeamlyActivityEventHandler } from './use-seamly-activity-event-handler'
38
- export { useSeamlyTyping, useSeamlyEntry } from './seamly-entry-hooks'
43
+ export { default as useSeamlyChat } from './use-seamly-chat'
44
+ export { default as useSeamlyCommands } from './use-seamly-commands'
45
+ export { default as useSeamlyIdleDetachCountdown } from './use-seamly-idle-detach-countdown'
46
+ export { default as useSeamlyResumeConversationPrompt } from './use-seamly-resume-conversation-prompt'
39
47
  export {
40
48
  useForceUpdate,
41
49
  useGeneratedId,
42
50
  useStableCallback,
43
51
  } from './utility-hooks'
44
- export {
45
- useElementFocusingById,
46
- useSkiplinkTargetFocusing,
47
- useFocusIfSeamlyContainedFocus,
48
- useSeamlyContainerElement,
49
- } from './focus-helper-hooks'
50
- export { default as useSeamlyChat } from './use-seamly-chat'
51
- export { default as useSeamlyIdleDetachCountdown } from './use-seamly-idle-detach-countdown'
52
- export { default as useSeamlyResumeConversationPrompt } from './use-seamly-resume-conversation-prompt'
52
+ export { useDispatch as useSeamlyDispatchContext }
53
53
 
54
54
  // This hook isn't used within the core
55
55
  // But it is used in implementations
@@ -1,17 +1,15 @@
1
+ import { useI18n } from 'domains/i18n/hooks'
2
+ import {
3
+ hideOption as dispatchHideOption,
4
+ setUserSelectedOption as dispatchUserSelectedOption,
5
+ setUserSelectedOptions as dispatchUserSelectedOptions,
6
+ showOption as dispatchShowOption,
7
+ } from 'domains/store/slice'
1
8
  import { useCallback } from 'preact/hooks'
2
- import { useI18n } from 'domains/i18n'
3
- import { seamlyActions } from 'ui/utils/seamly-utils'
4
- import { useSeamlyStateContext } from './seamly-state-hooks'
5
- import useSeamlyDispatchContext from './use-seamly-dispatch'
6
- import { useSeamlyObjectStore } from './seamly-api-hooks'
7
- import { useElementFocusingById } from './focus-helper-hooks'
8
-
9
- const {
10
- SET_USER_SELECTED_OPTION,
11
- SET_USER_SELECTED_OPTIONS,
12
- SHOW_OPTION,
13
- HIDE_OPTION,
14
- } = seamlyActions
9
+ import { useDispatch } from 'react-redux'
10
+ import { useElementFocusingById } from 'ui/hooks/focus-helper-hooks'
11
+ import { useSeamlyObjectStore } from 'ui/hooks/seamly-api-hooks'
12
+ import { useSeamlyStateContext } from 'ui/hooks/seamly-state-hooks'
15
13
 
16
14
  export const useSeamlyOptions = () => {
17
15
  const { t } = useI18n()
@@ -35,17 +33,17 @@ export const useSeamlyOptions = () => {
35
33
 
36
34
  const allowOptionSelection = cobrowsing || sendTranscript
37
35
 
38
- const dispatch = useSeamlyDispatchContext()
36
+ const dispatch = useDispatch()
39
37
  const { get, set } = useSeamlyObjectStore()
40
38
 
41
39
  const initUserSelectedOptions = useCallback(() => {
42
40
  const storedOptions = get('options') || {}
43
- dispatch({ type: SET_USER_SELECTED_OPTIONS, options: storedOptions })
41
+ dispatch(dispatchUserSelectedOptions(storedOptions))
44
42
  }, [get, dispatch])
45
43
 
46
44
  const setUserSelectedOptions = useCallback(
47
45
  (optionValues) => {
48
- dispatch({ type: SET_USER_SELECTED_OPTIONS, options: optionValues })
46
+ dispatch(dispatchUserSelectedOptions(optionValues))
49
47
  set('options', optionValues)
50
48
  },
51
49
  [set, dispatch],
@@ -58,17 +56,17 @@ export const useSeamlyOptions = () => {
58
56
  ...storedOptions,
59
57
  [option]: value,
60
58
  })
61
- dispatch({ type: SET_USER_SELECTED_OPTION, option, value })
59
+ dispatch(dispatchUserSelectedOption({ option, value }))
62
60
  },
63
61
  [dispatch, get, set],
64
62
  )
65
63
 
66
64
  const showOption = (optionName) => {
67
- dispatch({ type: SHOW_OPTION, optionName })
65
+ dispatch(dispatchShowOption(optionName))
68
66
  }
69
67
 
70
68
  const hideOption = () => {
71
- dispatch({ type: HIDE_OPTION })
69
+ dispatch(dispatchHideOption())
72
70
  }
73
71
 
74
72
  return {
@@ -1,23 +1,23 @@
1
- import { createSelector } from 'reselect'
2
- import { useSelector } from 'domains/redux'
3
- import { microsecondsToMilliseconds } from 'ui/utils/general-utils'
4
1
  import * as ConfigSelectors from 'domains/config/selectors'
5
- import * as AppSelectors from 'domains/app/selectors'
2
+ import { microsecondsToMilliseconds } from 'ui/utils/general-utils'
3
+ import { createSelector } from '@reduxjs/toolkit'
4
+ import { selectUserHasResponded } from 'domains/app/selectors'
6
5
  import { useConfig } from 'domains/config/hooks'
6
+ import { useSelector } from 'react-redux'
7
7
 
8
- export const selectState = (state) => state.state
8
+ export const selectState = ({ state }) => state
9
9
  export const useSeamlyStateContext = () => useSelector(selectState)
10
10
 
11
11
  export const selectEventsWithSuggestion = createSelector(
12
12
  selectState,
13
13
  ConfigSelectors.selectConfig,
14
- AppSelectors.selectUserHasResponded,
15
- ({ events, serviceData }, config, userHasResponded) => {
14
+ selectUserHasResponded,
15
+ ({ events, serviceData }, config, hasUserResponded) => {
16
16
  if (
17
- userHasResponded ||
17
+ hasUserResponded ||
18
18
  config.layoutMode === 'inline' ||
19
- !serviceData.suggestion ||
20
- !serviceData.suggestion?.body.length
19
+ !serviceData?.suggestion ||
20
+ !serviceData?.suggestion?.body.length
21
21
  ) {
22
22
  return events
23
23
  }
@@ -63,7 +63,7 @@ export const selectEvents = createSelector(
63
63
  return mappedEvents
64
64
  },
65
65
  )
66
- export const useEvents = () => useSelector(selectEvents, [])
66
+ export const useEvents = () => useSelector(selectEvents)
67
67
 
68
68
  export const useSeamlyIsLoading = () => useSeamlyStateContext().isLoading
69
69
 
@@ -96,8 +96,9 @@ export const useSeamlyCurrentAgent = () => {
96
96
  return currentAgent ? participants[currentAgent] : null
97
97
  }
98
98
 
99
- export const useSeamlyServiceData = (key) =>
100
- useSeamlyStateContext().serviceData[key]
99
+ export const useSeamlyServiceData = (key) => {
100
+ return useSeamlyStateContext().serviceData[key]
101
+ }
101
102
 
102
103
  export const useEntryTextLimit = () => {
103
104
  const {
@@ -1,23 +1,21 @@
1
+ import { useI18n } from 'domains/i18n/hooks'
2
+ import { setIsLoading } from 'domains/store/slice'
3
+ import { visibilityStates } from 'domains/visibility/constants'
4
+ import { useVisibility } from 'domains/visibility/hooks'
1
5
  import { useCallback, useEffect, useRef } from 'preact/hooks'
2
- import { useI18n } from 'domains/i18n'
3
- import { seamlyActions } from 'ui/utils/seamly-utils'
4
- import { useVisibility, visibilityStates } from 'domains/visibility'
5
- import useSeamlyDispatchContext from './use-seamly-dispatch'
6
+ import { useDispatch, useSelector } from 'react-redux'
7
+ import { selectShowInlineView } from '../../domains/visibility/selectors'
8
+ import { useLiveRegion } from './live-region-hooks'
9
+ import { useSeamlyHasConversation } from './seamly-api-hooks'
6
10
  import { useEvents, useSeamlyLayoutMode } from './seamly-state-hooks'
7
11
  import useSeamlyCommands from './use-seamly-commands'
8
- import { useSeamlyHasConversation } from './seamly-api-hooks'
9
- import { useLiveRegion } from './live-region-hooks'
10
- import { useSelector } from '../../domains/redux/hooks'
11
- import { selectShowInlineView } from '../../domains/visibility/selectors'
12
-
13
- const { SET_IS_LOADING } = seamlyActions
14
12
 
15
13
  const useSeamlyChat = () => {
16
14
  const { t } = useI18n()
17
15
  const { isInline, isWindow } = useSeamlyLayoutMode()
18
16
  const { isOpen, isVisible, setVisibility } = useVisibility()
19
17
  const showInlineView = useSelector(selectShowInlineView)
20
- const dispatch = useSeamlyDispatchContext()
18
+ const dispatch = useDispatch()
21
19
  const events = useEvents()
22
20
  const spinnerTimeout = useRef(null)
23
21
  const { start, connect, apiConfigReady, apiConnected } = useSeamlyCommands()
@@ -60,20 +58,14 @@ const useSeamlyChat = () => {
60
58
  // This delays the start of the loading inidicator we set when we initialise
61
59
  // the application. This is done to only avoid BSOD on initial load if DCX is slow.
62
60
  spinnerTimeout.current = setTimeout(() => {
63
- dispatch({
64
- type: SET_IS_LOADING,
65
- isLoading: true,
66
- })
61
+ dispatch(setIsLoading(true))
67
62
  }, 500)
68
63
  }, [dispatch])
69
64
 
70
65
  useEffect(() => {
71
66
  if (hasEvents) {
72
67
  clearTimeout(spinnerTimeout.current)
73
- dispatch({
74
- type: SET_IS_LOADING,
75
- isLoading: false,
76
- })
68
+ dispatch(setIsLoading(false))
77
69
  }
78
70
  }, [hasEvents, dispatch])
79
71
 
@@ -106,21 +98,19 @@ const useSeamlyChat = () => {
106
98
  if (
107
99
  !apiConfigReady ||
108
100
  startCalled.current ||
109
- (isWindow && !isOpen && !hasConversation) ||
101
+ (isWindow && !isOpen && !hasConversation()) ||
110
102
  (isInline && !showInlineView)
111
103
  ) {
112
104
  return
113
105
  }
114
106
 
115
- if (hasConversation && isOpen) {
107
+ if (hasConversation() && isOpen) {
116
108
  // We deactivate the extra startup loading spinner when a conversation is available
117
109
  // We also stop setting the loading indicator in the first place to avoid a flash.
118
110
  clearTimeout(spinnerTimeout.current)
119
- dispatch({
120
- type: SET_IS_LOADING,
121
- isLoading: false,
122
- })
111
+ dispatch(setIsLoading(false))
123
112
  }
113
+
124
114
  connectAndStart()
125
115
  }, [
126
116
  apiConfigReady,