@seamly/web-ui 20.7.0 → 20.8.0-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 (226) hide show
  1. package/build/dist/lib/hooks.js +1 -1
  2. package/build/dist/lib/hooks.min.js +1 -1
  3. package/build/dist/lib/index.debug.js +945 -790
  4. package/build/dist/lib/index.debug.min.js +1 -1
  5. package/build/dist/lib/index.debug.min.js.LICENSE.txt +187 -131
  6. package/build/dist/lib/index.js +24800 -19606
  7. package/build/dist/lib/index.min.js +1 -1
  8. package/build/dist/lib/index.min.js.LICENSE.txt +38 -4
  9. package/build/dist/lib/standalone.js +32920 -26742
  10. package/build/dist/lib/standalone.min.js +1 -1
  11. package/build/dist/lib/standalone.min.js.LICENSE.txt +39 -0
  12. package/build/dist/lib/storage.js +2 -2
  13. package/build/dist/lib/storage.min.js +1 -1
  14. package/build/dist/lib/style-guide.js +8780 -7907
  15. package/build/dist/lib/style-guide.min.js +2 -1
  16. package/build/dist/lib/style-guide.min.js.LICENSE.txt +38 -0
  17. package/build/dist/lib/styles.css +1 -1
  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 +96 -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 +113 -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} +40 -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 +642 -0
  56. package/src/javascripts/domains/store/store.types.ts +146 -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.ts +114 -0
  62. package/src/javascripts/domains/translations/middleware.js +29 -27
  63. package/src/javascripts/domains/translations/selectors.ts +12 -0
  64. package/src/javascripts/domains/translations/slice.ts +120 -0
  65. package/src/javascripts/domains/translations/translations.types.ts +19 -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 +1448 -0
  82. package/src/javascripts/style-guide/components/app.js +6 -6
  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 +67 -7
  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 +11 -7
  91. package/src/javascripts/ui/components/conversation/event/card-message.js +2 -2
  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 +2 -2
  95. package/src/javascripts/ui/components/conversation/event/choice-prompt.js +3 -3
  96. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +19 -15
  97. package/src/javascripts/ui/components/conversation/event/cta.js +2 -2
  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 +44 -5
  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 +6 -8
  104. package/src/javascripts/ui/components/conversation/event/participant.js +2 -2
  105. package/src/javascripts/ui/components/conversation/event/splash.js +4 -4
  106. package/src/javascripts/ui/components/conversation/event/text.js +2 -2
  107. package/src/javascripts/ui/components/conversation/event/translation.js +3 -3
  108. package/src/javascripts/ui/components/conversation/event/upload.js +3 -3
  109. package/src/javascripts/ui/components/conversation/event/video.js +2 -2
  110. package/src/javascripts/ui/components/conversation/message-container.js +4 -26
  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 +98 -92
  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 +9 -7
  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 +14 -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 +14 -10
  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 +20 -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/src/stylesheets/5-components/_message-carousel.scss +10 -8
  173. package/webpack/config.common.js +16 -0
  174. package/webpack/config.dev.js +1 -0
  175. package/webpack/config.package.js +26 -5
  176. package/webpack/defaults.js +7 -2
  177. package/webpack/parts/babel-loader-browser-plugins.js +1 -0
  178. package/webpack/parts/dev-server.js +4 -3
  179. package/CHANGELOG.md +0 -791
  180. package/src/javascripts/domains/app/actions.js +0 -112
  181. package/src/javascripts/domains/app/index.js +0 -7
  182. package/src/javascripts/domains/app/reducer.js +0 -16
  183. package/src/javascripts/domains/app/selectors.js +0 -8
  184. package/src/javascripts/domains/app/utils.js +0 -4
  185. package/src/javascripts/domains/config/actions.js +0 -7
  186. package/src/javascripts/domains/config/hooks.js +0 -23
  187. package/src/javascripts/domains/config/index.js +0 -7
  188. package/src/javascripts/domains/config/reducer.js +0 -79
  189. package/src/javascripts/domains/config/selectors.js +0 -23
  190. package/src/javascripts/domains/config/utils.js +0 -4
  191. package/src/javascripts/domains/forms/actions.js +0 -21
  192. package/src/javascripts/domains/forms/context.js +0 -6
  193. package/src/javascripts/domains/forms/index.js +0 -8
  194. package/src/javascripts/domains/forms/reducer.js +0 -84
  195. package/src/javascripts/domains/forms/utils.js +0 -20
  196. package/src/javascripts/domains/i18n/actions.js +0 -20
  197. package/src/javascripts/domains/i18n/index.js +0 -7
  198. package/src/javascripts/domains/i18n/selectors.js +0 -15
  199. package/src/javascripts/domains/i18n/utils.js +0 -4
  200. package/src/javascripts/domains/interrupt/actions.js +0 -4
  201. package/src/javascripts/domains/interrupt/index.js +0 -9
  202. package/src/javascripts/domains/interrupt/reducer.js +0 -22
  203. package/src/javascripts/domains/interrupt/selectors.js +0 -6
  204. package/src/javascripts/domains/interrupt/utils.js +0 -4
  205. package/src/javascripts/domains/options/index.js +0 -1
  206. package/src/javascripts/domains/redux/context.js +0 -6
  207. package/src/javascripts/domains/redux/create-redux-store.js +0 -21
  208. package/src/javascripts/domains/redux/hooks.js +0 -80
  209. package/src/javascripts/domains/redux/index.js +0 -19
  210. package/src/javascripts/domains/redux/provider.js +0 -5
  211. package/src/javascripts/domains/redux/utils.js +0 -12
  212. package/src/javascripts/domains/store/index.js +0 -46
  213. package/src/javascripts/domains/store/state-reducer.js +0 -56
  214. package/src/javascripts/domains/translations/actions.js +0 -11
  215. package/src/javascripts/domains/translations/hooks.js +0 -103
  216. package/src/javascripts/domains/translations/index.js +0 -10
  217. package/src/javascripts/domains/translations/reducer.js +0 -69
  218. package/src/javascripts/domains/translations/selectors.js +0 -16
  219. package/src/javascripts/domains/translations/utils.js +0 -4
  220. package/src/javascripts/domains/visibility/index.js +0 -8
  221. package/src/javascripts/domains/visibility/reducer.js +0 -24
  222. package/src/javascripts/index.js +0 -153
  223. package/src/javascripts/lib/redux-helpers/index.js +0 -99
  224. package/src/javascripts/style-guide.js +0 -5
  225. package/src/javascripts/ui/hooks/use-seamly-dispatch.js +0 -3
  226. package/src/javascripts/ui/utils/seamly-utils.js +0 -832
@@ -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,13 @@ 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
+
68
+ export const selectEventIds = createSelector(selectEvents, (events) => {
69
+ return events.map((event) => event.payload.id)
70
+ })
71
+
72
+ export const useEventsIds = () => useSelector(selectEventIds)
67
73
 
68
74
  export const useSeamlyIsLoading = () => useSeamlyStateContext().isLoading
69
75
 
@@ -96,8 +102,9 @@ export const useSeamlyCurrentAgent = () => {
96
102
  return currentAgent ? participants[currentAgent] : null
97
103
  }
98
104
 
99
- export const useSeamlyServiceData = (key) =>
100
- useSeamlyStateContext().serviceData[key]
105
+ export const useSeamlyServiceData = (key) => {
106
+ return useSeamlyStateContext().serviceData[key]
107
+ }
101
108
 
102
109
  export const useEntryTextLimit = () => {
103
110
  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,
@@ -1,30 +1,30 @@
1
- import { useCallback, useContext } from 'preact/hooks'
2
- import { SeamlyEventBusContext } from 'ui/components/core/seamly-api-context'
3
- import { randomId } from 'lib/id'
4
1
  import { userParticipantId } from 'config'
5
- import { actionTypes, seamlyActions } from 'ui/utils/seamly-utils'
6
- import { Actions as InterruptActions } from 'domains/interrupt'
7
- import { useConfig } from 'domains/config'
8
- import * as AppActions from 'domains/app/actions'
9
2
  import { useUserHasResponded } from 'domains/app/hooks'
10
- import { useVisibility, visibilityStates } from 'domains/visibility'
11
- import { useStableCallback } from './utility-hooks'
12
- import useSeamlyDispatchContext from './use-seamly-dispatch'
13
- import { useSeamlyUnreadCount } from './seamly-state-hooks'
3
+ import * as AppActions from 'domains/app/actions'
4
+ import { setHasResponded } from 'domains/app/slice'
5
+ import { useConfig } from 'domains/config/hooks'
6
+ import { setInterrupt } from 'domains/interrupt/slice'
7
+ import { addEvent, setInitialState } from 'domains/store/slice'
8
+ import { visibilityStates } from 'domains/visibility/constants'
9
+ import { useVisibility } from 'domains/visibility/hooks'
10
+
11
+ 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'
14
16
  import {
15
17
  useSeamlyApiContext,
16
18
  useSeamlyHasConversation,
17
19
  } from './seamly-api-hooks'
18
-
19
- const { ADD_EVENT, SET_INITIAL_STATE } = seamlyActions
20
+ import { useSeamlyUnreadCount } from './seamly-state-hooks'
20
21
 
21
22
  const useSeamlyCommands = () => {
22
23
  const api = useSeamlyApiContext()
23
24
  const appConfig = useConfig()
24
- const dispatch = useSeamlyDispatchContext()
25
+ const dispatch = useDispatch()
25
26
  const eventBus = useContext(SeamlyEventBusContext)
26
-
27
- const hasResponded = useUserHasResponded()
27
+ const userHasResponded = useUserHasResponded()
28
28
  const hasConversation = useSeamlyHasConversation()
29
29
  const { visible: visibility, setVisibility } = useVisibility()
30
30
  const unreadMessageCount = useSeamlyUnreadCount()
@@ -36,34 +36,34 @@ const useSeamlyCommands = () => {
36
36
  [eventBus],
37
37
  )
38
38
 
39
- const start = useStableCallback(() => {
39
+ const start = useCallback(() => {
40
40
  api.sendContext(appConfig.context || {})
41
41
  emitEvent('ui.beforeStart', {
42
42
  visibility,
43
- hasConversation,
44
- hasResponded,
43
+ hasConversation: hasConversation(),
44
+ hasResponded: userHasResponded,
45
45
  unreadMessageCount,
46
46
  })
47
47
 
48
48
  api.send('start')
49
49
  emitEvent('ui.start', {
50
50
  visibility,
51
- hasConversation,
52
- hasResponded,
51
+ hasConversation: hasConversation(),
52
+ hasResponded: userHasResponded,
53
53
  unreadMessageCount,
54
54
  })
55
55
  }, [
56
56
  api,
57
- appConfig,
57
+ appConfig.context,
58
58
  emitEvent,
59
- hasResponded,
60
59
  hasConversation,
61
- visibility,
60
+ userHasResponded,
62
61
  unreadMessageCount,
62
+ visibility,
63
63
  ])
64
64
 
65
65
  const reset = useCallback(async () => {
66
- dispatch(AppActions.reset())
66
+ dispatch(AppActions.resetApp())
67
67
  }, [dispatch])
68
68
 
69
69
  const getMessageBase = useCallback(
@@ -106,35 +106,30 @@ const useSeamlyCommands = () => {
106
106
 
107
107
  api.send('message', message)
108
108
  emitEvent('message', message)
109
- dispatch({
110
- type: ADD_EVENT,
111
- event: {
109
+ dispatch(
110
+ addEvent({
112
111
  type: 'message',
113
112
  payload: {
114
113
  ...message,
115
114
  optimisticallyInjected: true,
116
115
  },
117
- },
118
- })
116
+ }),
117
+ )
119
118
  },
120
119
  [api, dispatch, emitEvent, getTextMessageBase],
121
120
  )
122
121
 
123
122
  const addMessageBubble = useCallback(
124
123
  (text) => {
125
- dispatch({
126
- type: ADD_EVENT,
127
- event: { type: 'message', payload: getTextMessageBase(text) },
128
- })
124
+ dispatch(addEvent({ type: 'message', payload: getTextMessageBase(text) }))
129
125
  },
130
126
  [dispatch, getTextMessageBase],
131
127
  )
132
128
 
133
129
  const addUploadBubble = useCallback(
134
130
  (id, transactionId, occurredAt, contentType, filename, filesize, url) => {
135
- dispatch({
136
- type: ADD_EVENT,
137
- event: {
131
+ dispatch(
132
+ addEvent({
138
133
  type: 'message',
139
134
  payload: {
140
135
  type: 'upload',
@@ -146,8 +141,8 @@ const useSeamlyCommands = () => {
146
141
  meta: {},
147
142
  body: { contentType, filename, filesize, url },
148
143
  },
149
- },
150
- })
144
+ }),
145
+ )
151
146
  },
152
147
  [dispatch],
153
148
  )
@@ -163,10 +158,7 @@ const useSeamlyCommands = () => {
163
158
  type: 'divider',
164
159
  }
165
160
 
166
- dispatch({
167
- type: ADD_EVENT,
168
- event: { type: 'info', payload },
169
- })
161
+ dispatch(addEvent({ type: 'info', payload }))
170
162
  },
171
163
  [dispatch],
172
164
  )
@@ -203,15 +195,23 @@ const useSeamlyCommands = () => {
203
195
  .connect()
204
196
  .then((initialState) => {
205
197
  if (initialState) {
206
- dispatch({ type: SET_INITIAL_STATE, initialState })
198
+ dispatch(setInitialState(initialState))
207
199
  if (initialState.userResponded) {
208
- dispatch(AppActions.setHasResponded(initialState.userResponded))
200
+ dispatch(setHasResponded(initialState.userResponded))
209
201
  setVisibility(visibilityStates.open)
210
202
  }
211
203
  }
212
204
  })
213
205
  .catch((error) => {
214
- dispatch(InterruptActions.set(error))
206
+ dispatch(
207
+ setInterrupt({
208
+ name: error.name,
209
+ message: error.message,
210
+ langKey: error.langKey,
211
+ originalEvent: error.originalEvent,
212
+ originalError: error.originalError,
213
+ }),
214
+ )
215
215
  })
216
216
  }, [api, dispatch, setVisibility])
217
217
 
@@ -1,26 +1,25 @@
1
+ import { screenReaderDebounceDelaySeconds } from 'config'
2
+ import { useI18n } from 'domains/i18n/hooks'
3
+ import { useVisibility } from 'domains/visibility/hooks'
4
+ import {
5
+ clearIdleDetachCountdown,
6
+ decrementIdleDetachCountdownCounter,
7
+ initIdleDetachCountdown,
8
+ stopIdleDetachCountdownCounter,
9
+ } from 'domains/store/slice'
1
10
  import { useCallback, useRef } from 'preact/hooks'
2
- import { useI18n } from 'domains/i18n'
11
+ import { useDispatch } from 'react-redux'
3
12
  import {
4
13
  getTimeFromSeconds,
5
14
  millisecondsToSeconds,
6
15
  } from 'ui/utils/general-utils'
7
- import { actionTypes, seamlyActions } from 'ui/utils/seamly-utils'
8
- import { screenReaderDebounceDelaySeconds } from 'config'
9
- import { useVisibility } from 'domains/visibility'
16
+ import { actionTypes } from 'ui/utils/seamly-utils'
10
17
  import { useLiveRegion } from './live-region-hooks'
11
- import useSeamlyCommands from './use-seamly-commands'
12
18
  import { useSeamlyStateContext } from './seamly-state-hooks'
13
- import useSeamlyDispatchContext from './use-seamly-dispatch'
14
-
15
- const {
16
- CLEAR_IDLE_DETACH_COUNTDOWN,
17
- INIT_IDLE_DETACH_COUNTDOWN,
18
- DECREMENT_IDLE_DETACH_COUNTDOWN_COUNTER,
19
- STOP_IDLE_DETACH_COUNTDOWN_COUNTER,
20
- } = seamlyActions
19
+ import useSeamlyCommands from './use-seamly-commands'
21
20
 
22
21
  const useSeamlyIdleDetachCountdown = () => {
23
- const dispatch = useSeamlyDispatchContext()
22
+ const dispatch = useDispatch()
24
23
 
25
24
  const { idleDetachCountdown } = useSeamlyStateContext()
26
25
 
@@ -65,11 +64,12 @@ const useSeamlyIdleDetachCountdown = () => {
65
64
  const delaySeconds = millisecondsToSeconds(milliseconds)
66
65
  const delayTime = getTimeFromSeconds(delaySeconds)
67
66
 
68
- dispatch({
69
- type: INIT_IDLE_DETACH_COUNTDOWN,
70
- delaySeconds,
71
- delayTime,
72
- })
67
+ dispatch(
68
+ initIdleDetachCountdown({
69
+ delaySeconds,
70
+ delayTime,
71
+ }),
72
+ )
73
73
  emitEvent('idleTimer.start')
74
74
  sendAssertiveIfOpen(
75
75
  `${t('idleDetachWarning.countdownTitle')} ${t(
@@ -98,7 +98,7 @@ const useSeamlyIdleDetachCountdown = () => {
98
98
  emitEvent('idleTimer.stop')
99
99
  }
100
100
 
101
- dispatch({ type: CLEAR_IDLE_DETACH_COUNTDOWN })
101
+ dispatch(clearIdleDetachCountdown())
102
102
  },
103
103
  [dispatch, sendAction, emitEvent, sendAssertiveIfOpen, t],
104
104
  )
@@ -120,9 +120,7 @@ const useSeamlyIdleDetachCountdown = () => {
120
120
  )
121
121
  }
122
122
 
123
- dispatch({
124
- type: DECREMENT_IDLE_DETACH_COUNTDOWN_COUNTER,
125
- })
123
+ dispatch(decrementIdleDetachCountdownCounter())
126
124
  }, [dispatch, sendAssertiveIfOpen, t])
127
125
 
128
126
  const stopCountdown = useCallback(() => {
@@ -131,7 +129,7 @@ const useSeamlyIdleDetachCountdown = () => {
131
129
  return
132
130
  }
133
131
 
134
- dispatch({ type: STOP_IDLE_DETACH_COUNTDOWN_COUNTER })
132
+ dispatch(stopIdleDetachCountdownCounter())
135
133
 
136
134
  if (remaining) {
137
135
  emitEvent('idleTimer.stop')
@@ -1,14 +1,13 @@
1
- import { useI18n } from 'domains/i18n'
2
- import { actionTypes, dismissTypes, seamlyActions } from 'ui/utils/seamly-utils'
3
- import useSeamlyDispatchContext from './use-seamly-dispatch'
1
+ import { useI18n } from 'domains/i18n/hooks'
2
+ import { clearResumeConversationPrompt } from 'domains/store/slice'
3
+ import { useDispatch } from 'react-redux'
4
+ import { actionTypes, dismissTypes } from 'ui/utils/seamly-utils'
5
+ import { useLiveRegion } from './live-region-hooks'
4
6
  import { useSeamlyStateContext } from './seamly-state-hooks'
5
7
  import useSeamlyCommands from './use-seamly-commands'
6
- import { useLiveRegion } from './live-region-hooks'
7
-
8
- const { CLEAR_RESUME_CONVERSATION_PROMPT } = seamlyActions
9
8
 
10
9
  const useSeamlyResumeConversationPrompt = () => {
11
- const dispatch = useSeamlyDispatchContext()
10
+ const dispatch = useDispatch()
12
11
  const hasPrompt = useSeamlyStateContext().resumeConversationPrompt
13
12
  const { sendAction } = useSeamlyCommands()
14
13
  const { t } = useI18n()
@@ -19,13 +18,13 @@ const useSeamlyResumeConversationPrompt = () => {
19
18
  type: actionTypes.dismiss,
20
19
  body: { type: dismissTypes.resumeConversationPrompt },
21
20
  })
22
- dispatch({ type: CLEAR_RESUME_CONVERSATION_PROMPT })
21
+ dispatch(clearResumeConversationPrompt())
23
22
  }
24
23
 
25
24
  const restartChat = () => {
26
25
  sendAssertive(t('resumeConversationPrompt.srNotifyRestartText'))
27
26
  sendAction({ type: actionTypes.detachService })
28
- dispatch({ type: CLEAR_RESUME_CONVERSATION_PROMPT })
27
+ dispatch(clearResumeConversationPrompt())
29
28
  }
30
29
 
31
30
  return { continueChat, hasPrompt, restartChat }
@@ -1,12 +1,10 @@
1
- import { Selectors } from 'domains/forms'
2
- import { useSelectorWithProps } from 'domains/redux'
1
+ import { getControlValueByName } from 'domains/forms/selectors'
2
+ import { useSelector } from 'react-redux'
3
3
  import { useFileUploads } from './seamly-hooks'
4
4
 
5
5
  const useSingleFileUpload = (formId, name) => {
6
- const fileList = useSelectorWithProps(
7
- Selectors.getControlValueByName,
8
- { formId, name },
9
- [formId, name],
6
+ const fileList = useSelector((store) =>
7
+ getControlValueByName(store, { formId, name }),
10
8
  )
11
9
  // This hook acts as a helper as the data model is built to handle multiple
12
10
  // file uploads but currently Seamly only supports single file uploads.
@@ -1,17 +1,17 @@
1
+ import { randomId } from 'lib/id'
1
2
  import {
2
3
  useCallback,
4
+ useMemo,
3
5
  useReducer,
4
6
  useRef,
5
7
  useState,
6
- useMemo,
7
8
  } 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:
12
12
  // https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate
13
13
  /* eslint-disable-next-line no-unused-vars */
14
- const [ignored, forceUpdate] = useReducer((x) => x + 1, 0)
14
+ const [_, forceUpdate] = useReducer((x) => x + 1, 0)
15
15
 
16
16
  return useCallback(() => {
17
17
  setTimeout(() => {
@@ -26,7 +26,7 @@ export const useGeneratedId = () => {
26
26
  }
27
27
 
28
28
  export const useStableCallback = (callback) => {
29
- const callbackRef = useRef()
29
+ const callbackRef = useRef(null)
30
30
  callbackRef.current = callback
31
31
  const isFunction = typeof callback === 'function'
32
32
  return useMemo(() => {