@seamly/web-ui 18.2.0 → 19.0.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 (194) hide show
  1. package/build/dist/lib/index.debug.js +598 -136
  2. package/build/dist/lib/index.debug.min.js +1 -1
  3. package/build/dist/lib/index.debug.min.js.LICENSE.txt +190 -22
  4. package/build/dist/lib/index.js +4745 -4468
  5. package/build/dist/lib/index.min.js +1 -1
  6. package/build/dist/lib/index.min.js.LICENSE.txt +1 -1
  7. package/build/dist/lib/standalone.js +4839 -4465
  8. package/build/dist/lib/standalone.min.js +1 -1
  9. package/build/dist/lib/standalone.min.js.LICENSE.txt +1 -1
  10. package/build/dist/lib/style-guide.js +1770 -980
  11. package/build/dist/lib/style-guide.min.js +1 -1
  12. package/build/dist/lib/styles.css +1 -1
  13. package/build/dist/lib/utils.js +0 -1
  14. package/build/dist/lib/utils.min.js +1 -1
  15. package/package.json +29 -29
  16. package/src/javascripts/api/index.js +33 -48
  17. package/src/javascripts/api/producer.js +9 -12
  18. package/src/javascripts/config.js +9 -11
  19. package/src/javascripts/domains/app/actions.js +43 -0
  20. package/src/javascripts/domains/app/hooks.js +6 -0
  21. package/src/javascripts/domains/app/index.js +6 -0
  22. package/src/javascripts/domains/app/reducer.js +16 -0
  23. package/src/javascripts/domains/app/selectors.js +8 -0
  24. package/src/javascripts/domains/app/utils.js +4 -0
  25. package/src/javascripts/domains/config/actions.js +4 -0
  26. package/src/javascripts/domains/config/hooks.js +6 -0
  27. package/src/javascripts/domains/config/index.js +8 -0
  28. package/src/javascripts/domains/config/middleware.js +22 -0
  29. package/src/javascripts/domains/config/reducer.js +63 -0
  30. package/src/javascripts/domains/config/selectors.js +23 -0
  31. package/src/javascripts/domains/config/utils.js +4 -0
  32. package/src/javascripts/domains/forms/actions.js +2 -4
  33. package/src/javascripts/domains/forms/hooks.js +10 -14
  34. package/src/javascripts/domains/forms/provider.js +4 -6
  35. package/src/javascripts/domains/forms/reducer.js +1 -2
  36. package/src/javascripts/domains/forms/selectors.js +4 -4
  37. package/src/javascripts/domains/forms/utils.js +5 -0
  38. package/src/javascripts/domains/i18n/actions.js +35 -0
  39. package/src/javascripts/domains/i18n/hooks.js +38 -0
  40. package/src/javascripts/domains/i18n/index.js +5 -80
  41. package/src/javascripts/domains/i18n/reducer.js +58 -0
  42. package/src/javascripts/domains/i18n/selectors.js +15 -0
  43. package/src/javascripts/domains/i18n/utils.js +9 -0
  44. package/src/javascripts/domains/interrupt/actions.js +4 -0
  45. package/src/javascripts/domains/interrupt/hooks.js +29 -0
  46. package/src/javascripts/domains/interrupt/index.js +9 -0
  47. package/src/javascripts/domains/interrupt/middleware.js +30 -0
  48. package/src/javascripts/domains/interrupt/reducer.js +21 -0
  49. package/src/javascripts/domains/interrupt/selectors.js +6 -0
  50. package/src/javascripts/domains/interrupt/utils.js +4 -0
  51. package/src/javascripts/domains/options/index.js +1 -0
  52. package/src/javascripts/domains/options/middleware.js +35 -0
  53. package/src/javascripts/domains/redux/create-redux-store.js +14 -6
  54. package/src/javascripts/domains/redux/hooks.js +3 -2
  55. package/src/javascripts/domains/redux/index.js +2 -1
  56. package/src/javascripts/domains/redux/provider.js +5 -0
  57. package/src/javascripts/domains/store/index.js +44 -0
  58. package/src/javascripts/{ui → domains}/store/state-reducer.js +4 -7
  59. package/src/javascripts/domains/translations/actions.js +4 -6
  60. package/src/javascripts/domains/translations/components/chat-status.js +7 -13
  61. package/src/javascripts/domains/translations/components/options-button.js +3 -3
  62. package/src/javascripts/domains/translations/components/options-dialog/form.js +12 -7
  63. package/src/javascripts/domains/translations/components/options-dialog/index.js +2 -5
  64. package/src/javascripts/domains/translations/hooks.js +1 -1
  65. package/src/javascripts/domains/translations/index.js +1 -0
  66. package/src/javascripts/domains/translations/middleware.js +43 -0
  67. package/src/javascripts/domains/translations/reducer.js +4 -11
  68. package/src/javascripts/domains/translations/selectors.js +3 -3
  69. package/src/javascripts/domains/translations/utils.js +4 -0
  70. package/src/javascripts/index.js +20 -5
  71. package/src/javascripts/lib/css.js +5 -5
  72. package/src/javascripts/lib/engine/index.js +39 -11
  73. package/src/javascripts/lib/external-api/index.js +6 -6
  74. package/src/javascripts/lib/mutex.js +30 -0
  75. package/src/javascripts/lib/parse-body.js +1 -1
  76. package/src/javascripts/lib/redux-helpers/index.js +25 -8
  77. package/src/javascripts/lib/split-url-params.js +2 -2
  78. package/src/javascripts/lib/store/providers/app-storage.js +1 -1
  79. package/src/javascripts/lib/store/providers/cookie-storage.js +1 -1
  80. package/src/javascripts/package/utils.js +0 -1
  81. package/src/javascripts/style-guide/components/app.js +12 -14
  82. package/src/javascripts/style-guide/components/links.js +6 -6
  83. package/src/javascripts/style-guide/components/static-core.js +32 -10
  84. package/src/javascripts/style-guide/state-helpers/index.js +1 -1
  85. package/src/javascripts/style-guide/states.js +29 -71
  86. package/src/javascripts/style-guide/style-guide-engine.js +13 -12
  87. package/src/javascripts/ui/components/chat-app.js +2 -2
  88. package/src/javascripts/ui/components/conversation/component-filter.js +2 -2
  89. package/src/javascripts/ui/components/conversation/conversation.js +2 -2
  90. package/src/javascripts/ui/components/conversation/event/card-component.js +24 -3
  91. package/src/javascripts/ui/components/conversation/event/carousel-component/components/pagination.js +2 -2
  92. package/src/javascripts/ui/components/conversation/event/carousel-component/index.js +4 -3
  93. package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +2 -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 +5 -5
  96. package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +2 -2
  97. package/src/javascripts/ui/components/conversation/event/event-participant.js +3 -5
  98. package/src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js +2 -2
  99. package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +3 -3
  100. package/src/javascripts/ui/components/conversation/event/hooks/use-text-rendering.js +3 -3
  101. package/src/javascripts/ui/components/conversation/event/participant.js +2 -2
  102. package/src/javascripts/ui/components/conversation/event/upload.js +12 -27
  103. package/src/javascripts/ui/components/conversation/message-container.js +4 -6
  104. package/src/javascripts/ui/components/core/seamly-activity-monitor.js +4 -5
  105. package/src/javascripts/ui/components/core/seamly-core.js +6 -7
  106. package/src/javascripts/ui/components/core/seamly-event-subscriber.js +18 -17
  107. package/src/javascripts/ui/components/core/seamly-file-upload.js +5 -6
  108. package/src/javascripts/ui/components/core/seamly-idle-detach-counter.js +2 -6
  109. package/src/javascripts/ui/components/core/seamly-initializer.js +7 -60
  110. package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +10 -16
  111. package/src/javascripts/ui/components/core/seamly-live-region.js +1 -1
  112. package/src/javascripts/ui/components/core/seamly-new-notifications.js +5 -6
  113. package/src/javascripts/ui/components/core/seamly-read-state.js +8 -6
  114. package/src/javascripts/ui/components/entry/entry-container.js +7 -10
  115. package/src/javascripts/ui/components/entry/text-entry/hooks.js +6 -4
  116. package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +10 -3
  117. package/src/javascripts/ui/components/entry/toggle-button.js +24 -10
  118. package/src/javascripts/ui/components/entry/upload/file-upload-form.js +6 -3
  119. package/src/javascripts/ui/components/entry/upload/index.js +11 -13
  120. package/src/javascripts/ui/components/faq/faq.js +6 -6
  121. package/src/javascripts/ui/components/form-controls/error.js +22 -0
  122. package/src/javascripts/ui/components/form-controls/file-input.js +3 -9
  123. package/src/javascripts/ui/components/form-controls/select.js +1 -1
  124. package/src/javascripts/ui/components/form-controls/wrapper.js +2 -9
  125. package/src/javascripts/ui/components/layout/agent-info.js +4 -4
  126. package/src/javascripts/ui/components/layout/app-frame.js +15 -12
  127. package/src/javascripts/ui/components/layout/chat-frame.js +3 -5
  128. package/src/javascripts/ui/components/layout/header.js +4 -18
  129. package/src/javascripts/ui/components/layout/interrupt.js +6 -2
  130. package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
  131. package/src/javascripts/ui/components/options/cobrowsing.js +3 -7
  132. package/src/javascripts/ui/components/options/options-button.js +9 -13
  133. package/src/javascripts/ui/components/options/options-frame.js +1 -1
  134. package/src/javascripts/ui/components/options/transcript/index.js +2 -2
  135. package/src/javascripts/ui/components/options/transcript/transcript-form.js +1 -1
  136. package/src/javascripts/ui/components/warnings/cobrowsing-active-frame.js +3 -6
  137. package/src/javascripts/ui/components/warnings/idle-detach-warning.js +2 -6
  138. package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +1 -1
  139. package/src/javascripts/ui/components/widgets/in-out-transition.js +2 -2
  140. package/src/javascripts/ui/components/widgets/lightbox.js +4 -4
  141. package/src/javascripts/ui/components/widgets/modal.js +3 -3
  142. package/src/javascripts/ui/components/widgets/upload-progress.js +3 -14
  143. package/src/javascripts/ui/hooks/component-helper-hooks.js +4 -15
  144. package/src/javascripts/ui/hooks/file-upload-hooks.js +3 -3
  145. package/src/javascripts/ui/hooks/focus-helper-hooks.js +4 -4
  146. package/src/javascripts/ui/hooks/live-region-hooks.js +2 -2
  147. package/src/javascripts/ui/hooks/seamly-api-hooks.js +0 -6
  148. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +22 -25
  149. package/src/javascripts/ui/hooks/seamly-hooks.js +3 -10
  150. package/src/javascripts/ui/hooks/seamly-option-hooks.js +4 -4
  151. package/src/javascripts/ui/hooks/seamly-state-hooks.js +8 -16
  152. package/src/javascripts/ui/hooks/use-event-component-mapping.js +1 -1
  153. package/src/javascripts/ui/hooks/use-seamly-chat.js +1 -0
  154. package/src/javascripts/ui/hooks/use-seamly-commands.js +31 -54
  155. package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +3 -3
  156. package/src/javascripts/ui/hooks/use-seamly-stored-visibility.js +3 -3
  157. package/src/javascripts/ui/hooks/use-seamly-visibility.js +6 -8
  158. package/src/javascripts/ui/hooks/use-single-file-upload.js +4 -1
  159. package/src/javascripts/ui/hooks/utility-hooks.js +2 -2
  160. package/src/javascripts/ui/utils/form-utils.js +3 -3
  161. package/src/javascripts/ui/utils/general-utils.js +21 -22
  162. package/src/javascripts/ui/utils/seamly-utils.js +15 -83
  163. package/src/javascripts/ui/utils/validations.js +10 -7
  164. package/src/stylesheets/1-settings/_config.scss +2 -1
  165. package/src/stylesheets/3-app/_app.scss +3 -4
  166. package/src/stylesheets/5-components/_card.scss +0 -1
  167. package/src/stylesheets/5-components/_faq.scss +3 -8
  168. package/src/stylesheets/5-components/_message.scss +10 -0
  169. package/src/stylesheets/5-components/_modal.scss +3 -3
  170. package/src/stylesheets/5-components/_options.scss +3 -2
  171. package/webpack/config.common.js +3 -3
  172. package/webpack/config.package.js +4 -22
  173. package/webpack/config.site.js +8 -6
  174. package/webpack/defaults.js +0 -3
  175. package/CHANGELOG.md +0 -561
  176. package/build/dist/translations/de-informal.js +0 -275
  177. package/build/dist/translations/de-informal.min.js +0 -1
  178. package/build/dist/translations/en.js +0 -275
  179. package/build/dist/translations/en.min.js +0 -1
  180. package/build/dist/translations/es-informal.js +0 -281
  181. package/build/dist/translations/es-informal.min.js +0 -1
  182. package/build/dist/translations/nl-formal.js +0 -275
  183. package/build/dist/translations/nl-formal.min.js +0 -1
  184. package/build/dist/translations/nl-informal.js +0 -275
  185. package/build/dist/translations/nl-informal.min.js +0 -1
  186. package/src/javascripts/lib/i18n.js +0 -46
  187. package/src/javascripts/ui/components/core/seamly-api.js +0 -44
  188. package/src/javascripts/ui/hooks/use-seamly-interrupt.js +0 -62
  189. package/src/javascripts/ui/store/index.js +0 -37
  190. package/translations/de-informal.js +0 -237
  191. package/translations/en.js +0 -234
  192. package/translations/es-informal.js +0 -243
  193. package/translations/nl-formal.js +0 -230
  194. package/translations/nl-informal.js +0 -230
@@ -1,7 +1,7 @@
1
+ import { useMemo } from 'preact/hooks'
1
2
  import { className } from '../../../../lib/css'
2
3
  import Icon from '../../layout/icon'
3
4
  import { useI18n } from '../../../../domains/i18n'
4
- import { microsecondsToMilliseconds } from '../../../utils/general-utils'
5
5
  import MessageContainer from '../message-container'
6
6
  import { useTranslatedEventData } from '../../../../domains/translations'
7
7
 
@@ -18,40 +18,25 @@ const Upload = ({ event, ...props }) => {
18
18
  const { t } = useI18n()
19
19
  const [body] = useTranslatedEventData(event)
20
20
  const { fromClient } = event.payload
21
- const { deleteAt, filename, url } = body
22
- const deleted =
23
- url && !!deleteAt && microsecondsToMilliseconds(deleteAt) < Date.now()
21
+ const { filename, url } = body
24
22
 
25
- const getSrText = () => {
26
- if (url) {
27
- if (deleted) {
28
- return t('fileUpload.srFileUnavailableText', filename)
29
- } else {
30
- return t('fileUpload.srFileDownloadText', filename)
31
- }
32
- } else {
33
- return t('fileUpload.srFileUploadedText', filename)
34
- }
35
- }
23
+ const srText = useMemo(
24
+ () =>
25
+ url
26
+ ? t('fileUpload.srFileDownloadText', { fileName: filename })
27
+ : t('fileUpload.srFileUploadedText', { fileName: filename }),
28
+ [url, filename, t],
29
+ )
36
30
 
37
31
  return (
38
- <MessageContainer
39
- event={event}
40
- type="upload"
41
- modifiers={deleted && 'deleted'}
42
- info={deleted ? t('fileUpload.fileUnavailableText') : undefined}
43
- {...props}
44
- >
32
+ <MessageContainer event={event} type="upload" {...props}>
45
33
  <div className={className('download')}>
46
34
  <Icon name="download" size="16" />
47
- <UploadContent
48
- url={!deleted && url}
49
- target={!fromClient ? '_blank' : undefined}
50
- >
35
+ <UploadContent url={url} target={!fromClient ? '_blank' : undefined}>
51
36
  <span aria-hidden="true" className={className('file-download')}>
52
37
  {filename}
53
38
  </span>
54
- <span className={className('visually-hidden')}>{getSrText()}</span>
39
+ <span className={className('visually-hidden')}>{srText}</span>
55
40
  </UploadContent>
56
41
  </div>
57
42
  </MessageContainer>
@@ -18,10 +18,8 @@ function MessageContainer({
18
18
  const classNames = useSeamlyMessageContainerClassNames(event)
19
19
  const { t } = useI18n()
20
20
 
21
- const [
22
- ,
23
- { hasTranslation, isTranslated, toggleTranslation, locale },
24
- ] = useTranslatedEventData(event)
21
+ const [, { hasTranslation, isTranslated, toggleTranslation, locale }] =
22
+ useTranslatedEventData(event)
25
23
 
26
24
  if (type) {
27
25
  classNames.push('message--type-' + type)
@@ -29,9 +27,9 @@ function MessageContainer({
29
27
  if (modifiers) {
30
28
  if (typeof modifiers === 'string') {
31
29
  // eslint-disable-next-line no-param-reassign
32
- modifiers = modifiers.split(' ').filter(v => v.length)
30
+ modifiers = modifiers.split(' ').filter((v) => v.length)
33
31
  }
34
- modifiers.forEach(modifier => {
32
+ modifiers.forEach((modifier) => {
35
33
  classNames.push('message--' + modifier)
36
34
  })
37
35
  }
@@ -5,15 +5,13 @@ import {
5
5
  useSeamlyIdleDetachCountdown,
6
6
  } from '../../hooks/seamly-hooks'
7
7
  import { activitySendDelay } from '../../../config'
8
+ import { className } from '../../../lib/css'
8
9
 
9
10
  const SeamlyActivityMonitor = ({ children }) => {
10
11
  const prevSendTimestamp = useRef(0)
11
12
  const { sendAction } = useSeamlyCommands()
12
- const {
13
- hasCountdown,
14
- isActive,
15
- stopCountdown,
16
- } = useSeamlyIdleDetachCountdown()
13
+ const { hasCountdown, isActive, stopCountdown } =
14
+ useSeamlyIdleDetachCountdown()
17
15
 
18
16
  const onActivityHandler = useCallback(() => {
19
17
  const timeStamp = new Date().getTime()
@@ -38,6 +36,7 @@ const SeamlyActivityMonitor = ({ children }) => {
38
36
  // be fired inside the container on the initial focus event.
39
37
  return (
40
38
  <div
39
+ className={className('activity-monitor')}
41
40
  tabIndex="-1"
42
41
  onMouseDown={onActivityHandler}
43
42
  onKeyUp={onActivityHandler}
@@ -1,4 +1,3 @@
1
- import SeamlyApi from './seamly-api'
2
1
  import SeamlyInstanceFunctionsLoader from './seamly-instance-functions-loader'
3
2
  import SeamlyReadState from './seamly-read-state'
4
3
  import SeamlyNewNotifications from './seamly-new-notifications'
@@ -8,14 +7,14 @@ import SeamlyActivityMonitor from './seamly-activity-monitor'
8
7
  import SeamlyInitializer from './seamly-initializer'
9
8
  import SeamlyEventSubscriber from './seamly-event-subscriber'
10
9
  import SeamlyFileUpload from './seamly-file-upload'
11
- import { SeamlyEventBusContext } from './seamly-api-context'
12
- import StoreProvider from '../../store'
10
+ import { SeamlyEventBusContext, SeamlyApiContext } from './seamly-api-context'
11
+ import { StoreProvider } from '../../../domains/redux'
13
12
 
14
- const SeamlyCore = ({ children, config, eventBus }) => {
13
+ const SeamlyCore = ({ store, children, config, eventBus, api }) => {
15
14
  return (
16
- <StoreProvider translations={config.translations}>
15
+ <StoreProvider store={store}>
17
16
  <SeamlyEventBusContext.Provider value={eventBus}>
18
- <SeamlyApi>
17
+ <SeamlyApiContext.Provider value={api}>
19
18
  <SeamlyLiveRegion>
20
19
  <SeamlyInitializer config={config} />
21
20
  <SeamlyEventSubscriber eventBus={eventBus} />
@@ -27,7 +26,7 @@ const SeamlyCore = ({ children, config, eventBus }) => {
27
26
  <SeamlyFileUpload>{children}</SeamlyFileUpload>
28
27
  </SeamlyActivityMonitor>
29
28
  </SeamlyLiveRegion>
30
- </SeamlyApi>
29
+ </SeamlyApiContext.Provider>
31
30
  </SeamlyEventBusContext.Provider>
32
31
  </StoreProvider>
33
32
  )
@@ -2,7 +2,6 @@ import { useEffect, useRef } from 'preact/hooks'
2
2
  import { seamlyActions, featureKeys } from '../../utils/seamly-utils'
3
3
  import { useI18n } from '../../../domains/i18n'
4
4
  import {
5
- useSeamlyInterrupt,
6
5
  useSeamlyOptions,
7
6
  useEvents,
8
7
  useSeamlyApiContext,
@@ -13,6 +12,8 @@ import {
13
12
  import SeamlyGeneralError from '../../../api/errors/seamly-general-error'
14
13
  import SeamlySessionExpiredError from '../../../api/errors/seamly-session-expired-error'
15
14
  import SeamlyOfflineError from '../../../api/errors/seamly-offline-error'
15
+ import { Actions as InterruptActions } from '../../../domains/interrupt'
16
+ import { Actions as AppActions } from '../../../domains/app'
16
17
 
17
18
  const {
18
19
  ADD_EVENT,
@@ -20,7 +21,6 @@ const {
20
21
  SET_IS_LOADING,
21
22
  SET_PARTICIPANT,
22
23
  SET_HEADER_SUB_TITLE,
23
- CLEAR_INTERRUPT,
24
24
  SET_ACTIVE_SERVICE,
25
25
  INIT_RESUME_CONVERSATION_PROMPT,
26
26
  CLEAR_EVENTS,
@@ -38,14 +38,13 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
38
38
  const dispatch = useSeamlyDispatchContext()
39
39
  const events = useEvents()
40
40
  const prevEmittedEventId = useRef(null)
41
- const { setInterrupt } = useSeamlyInterrupt()
42
41
  const { setUserSelectedOption } = useSeamlyOptions()
43
42
  const { initCountdown, endCountdown } = useSeamlyIdleDetachCountdown()
44
43
  const { emitEvent } = useSeamlyCommands()
45
44
 
46
45
  useEffect(() => {
47
46
  if (api.connectionInfo) {
48
- const updateParticipant = event => {
47
+ const updateParticipant = (event) => {
49
48
  const { payload } = event
50
49
 
51
50
  if (!payload || !payload.participant) {
@@ -73,7 +72,7 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
73
72
  }
74
73
 
75
74
  api.stream().subscribe({
76
- next: event => {
75
+ next: (event) => {
77
76
  const { type, payload } = event
78
77
  switch (type) {
79
78
  case 'ui':
@@ -94,6 +93,7 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
94
93
  dispatch({ type: INIT_RESUME_CONVERSATION_PROMPT })
95
94
  break
96
95
  case 'user_first_response':
96
+ dispatch(AppActions.setHasResponded(true))
97
97
  eventBus.emit('system.userFirstResponse', payload.body)
98
98
  break
99
99
  }
@@ -178,19 +178,21 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
178
178
  case 'error':
179
179
  switch (payload.type) {
180
180
  case 'find_conversation_erred':
181
- setInterrupt(new SeamlySessionExpiredError())
181
+ dispatch(
182
+ InterruptActions.set(new SeamlySessionExpiredError()),
183
+ )
182
184
  break
183
185
  case 'seamly_offline':
184
- setInterrupt(new SeamlyOfflineError())
186
+ dispatch(InterruptActions.set(new SeamlyOfflineError()))
185
187
  dispatch({ type: CLEAR_EVENTS })
186
188
  break
187
189
  default:
188
- setInterrupt(new SeamlyGeneralError())
190
+ dispatch(InterruptActions.set(new SeamlyGeneralError()))
189
191
  break
190
192
  }
191
193
  break
192
194
  case 'socket_opened':
193
- dispatch({ type: CLEAR_INTERRUPT })
195
+ dispatch(InterruptActions.clear())
194
196
  break
195
197
  }
196
198
  },
@@ -199,7 +201,7 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
199
201
  api
200
202
  .stream()
201
203
  .filter(
202
- e =>
204
+ (e) =>
203
205
  e.type === 'message' &&
204
206
  EMITTABLE_MESSAGE_TYPES.includes(e.payload.type),
205
207
  )
@@ -220,7 +222,6 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
220
222
  api,
221
223
  eventBus,
222
224
  t,
223
- setInterrupt,
224
225
  setUserSelectedOption,
225
226
  initCountdown,
226
227
  endCountdown,
@@ -231,9 +232,9 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
231
232
  const subscribe = () => {
232
233
  return api
233
234
  .stream()
234
- .filter(e => e.type === 'sync')
235
+ .filter((e) => e.type === 'sync')
235
236
  .subscribe({
236
- next: event => {
237
+ next: (event) => {
237
238
  const { payload } = event
238
239
 
239
240
  const lastEvent = events[events.length - 1]
@@ -245,7 +246,7 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
245
246
 
246
247
  api
247
248
  .getConversation()
248
- .then(history => {
249
+ .then((history) => {
249
250
  if (!history) {
250
251
  return
251
252
  }
@@ -255,8 +256,8 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
255
256
  history,
256
257
  })
257
258
  })
258
- .catch(error => {
259
- setInterrupt(error)
259
+ .catch((error) => {
260
+ dispatch(InterruptActions.set(error))
260
261
  })
261
262
  },
262
263
  })
@@ -270,7 +271,7 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
270
271
  }
271
272
 
272
273
  return () => {}
273
- }, [api, events, dispatch, setInterrupt])
274
+ }, [api, events, dispatch])
274
275
 
275
276
  return null
276
277
  }
@@ -21,20 +21,20 @@ const SeamlyFileUpload = ({ children }) => {
21
21
  const api = useSeamlyApiContext()
22
22
  const { addUploadBubble } = useSeamlyCommands()
23
23
 
24
- const onUploadFileHandler = file => {
24
+ const onUploadFileHandler = (file) => {
25
25
  const fileId = randomId()
26
26
 
27
27
  const uploadHandle = api.uploadFile(
28
28
  file,
29
- p => {
29
+ (p) => {
30
30
  dispatch({ type: SET_UPLOAD_PROGRESS, fileId, progress: Math.ceil(p) })
31
31
  },
32
- result => {
32
+ (result) => {
33
33
  const {
34
34
  id,
35
35
  transactionId,
36
36
  occurredAt,
37
- body: { contentType, deleteAt, filename, filesize, url },
37
+ body: { contentType, filename, filesize, url },
38
38
  } = result.body
39
39
  dispatch({ type: SET_UPLOAD_COMPLETE, fileId })
40
40
  addUploadBubble(
@@ -42,13 +42,12 @@ const SeamlyFileUpload = ({ children }) => {
42
42
  transactionId,
43
43
  occurredAt,
44
44
  contentType,
45
- deleteAt,
46
45
  filename,
47
46
  filesize,
48
47
  url,
49
48
  )
50
49
  },
51
- err => {
50
+ (err) => {
52
51
  const errorKey = err && err.body ? err.body.error : ''
53
52
  let errorText
54
53
 
@@ -2,12 +2,8 @@ import useSeamlyIdleDetachCountdown from '../../hooks/use-seamly-idle-detach-cou
2
2
  import useInterval from '../../hooks/use-interval'
3
3
 
4
4
  const SeamlyIdleDetachCounter = () => {
5
- const {
6
- hasCountdown,
7
- isActive,
8
- remaining,
9
- decrementCountdown,
10
- } = useSeamlyIdleDetachCountdown()
5
+ const { hasCountdown, isActive, remaining, decrementCountdown } =
6
+ useSeamlyIdleDetachCountdown()
11
7
 
12
8
  useInterval(
13
9
  () => {
@@ -1,75 +1,22 @@
1
1
  import { useEffect, useRef } from 'preact/hooks'
2
- import {
3
- getSeamlyConfig,
4
- seamlyActions,
5
- visibilityStates,
6
- } from '../../utils/seamly-utils'
7
- import { useI18n } from '../../../domains/i18n'
8
- import {
9
- useSeamlyInterrupt,
10
- useSeamlyOptions,
11
- useSeamlyVisibility,
12
- useSeamlyApiContext,
13
- useSeamlyDispatchContext,
14
- } from '../../hooks/seamly-hooks'
2
+ import { visibilityStates } from '../../utils/seamly-utils'
3
+ import { useSeamlyOptions, useSeamlyVisibility } from '../../hooks/seamly-hooks'
4
+ import { useConfig } from '../../../domains/config'
15
5
 
16
- const {
17
- UPDATE_CONFIG,
18
- SET_INITIAL_STATE,
19
- SET_SHOW_DISCLAIMER,
20
- SET_HEADER_SUB_TITLE,
21
- SET_FEATURES,
22
- } = seamlyActions
23
-
24
- const SeamlyInitializer = ({ config }) => {
25
- const { t } = useI18n()
26
- const dispatch = useSeamlyDispatchContext()
27
- const api = useSeamlyApiContext()
6
+ const SeamlyInitializer = () => {
28
7
  const { initUserSelectedOptions } = useSeamlyOptions()
29
- const { setInterrupt } = useSeamlyInterrupt()
30
8
  const seamlyInitialized = useRef(false)
31
9
  const { setVisibility } = useSeamlyVisibility()
10
+ const config = useConfig()
32
11
 
33
12
  useEffect(() => {
34
- const seamlyConfig = getSeamlyConfig(config)
35
- const { showDisclaimer } = config
36
- const { agentName } = config.defaults || {}
37
-
38
- dispatch({ type: UPDATE_CONFIG, config: seamlyConfig })
39
-
40
- dispatch({ type: SET_SHOW_DISCLAIMER, showDisclaimer })
41
-
42
- if (agentName) {
43
- dispatch({
44
- type: SET_HEADER_SUB_TITLE,
45
- title: agentName,
46
- })
47
- }
48
- }, [dispatch, config])
49
-
50
- useEffect(() => {
51
- const initSeamly = async () => {
13
+ if (config.api && !seamlyInitialized.current) {
52
14
  seamlyInitialized.current = true
53
15
  initUserSelectedOptions()
54
16
 
55
17
  setVisibility(visibilityStates.initialize)
56
-
57
- try {
58
- const { accountConfig = {}, initialState = {} } = await api.getConfig()
59
- const { features } = accountConfig || {}
60
-
61
- dispatch({ type: SET_FEATURES, features })
62
-
63
- dispatch({ type: SET_INITIAL_STATE, initialState })
64
- } catch (error) {
65
- setInterrupt(error)
66
- }
67
- }
68
-
69
- if (api.connectionInfo && !seamlyInitialized.current) {
70
- initSeamly()
71
18
  }
72
- }, [api, dispatch, t, setInterrupt, initUserSelectedOptions, setVisibility])
19
+ }, [initUserSelectedOptions, config, setVisibility])
73
20
 
74
21
  return null
75
22
  }
@@ -1,11 +1,9 @@
1
1
  import { useContext, useEffect, useRef } from 'preact/hooks'
2
2
  import {
3
- useSeamlyConfig,
4
3
  useSeamlyCommands,
5
4
  useSeamlyVisibility,
6
5
  useSeamlyUnreadCount,
7
6
  useSeamlyLayoutMode,
8
- useSeamlyInterrupt,
9
7
  useSeamlyConversationUrl,
10
8
  useSeamlyActivityEventHandler,
11
9
  useSeamlyApiContext,
@@ -13,6 +11,8 @@ import {
13
11
  import { visibilityStates } from '../../utils/seamly-utils'
14
12
  import { SeamlyEventBusContext } from './seamly-api-context'
15
13
  import { useTranslations } from '../../../domains/translations'
14
+ import { useInterrupt } from '../../../domains/interrupt'
15
+ import { useConfig } from '../../../domains/config'
16
16
 
17
17
  function useSeamlyInstanceFunction(functionName, fn, deps = []) {
18
18
  const eventBus = useContext(SeamlyEventBusContext)
@@ -32,7 +32,7 @@ function useSeamlyInstanceFunction(functionName, fn, deps = []) {
32
32
  }
33
33
 
34
34
  const SeamlyInstanceFunctionsLoader = () => {
35
- const config = useSeamlyConfig()
35
+ const config = useConfig()
36
36
  const { sendMessage, sendContext, sendAction } = useSeamlyCommands()
37
37
  const { setVisibility, visible } = useSeamlyVisibility()
38
38
  const currentVisibility = useRef(visible)
@@ -42,7 +42,7 @@ const SeamlyInstanceFunctionsLoader = () => {
42
42
  const previousUnreadCount = useRef(null)
43
43
  const previousVisibilityState = useRef(null)
44
44
  const { isInline, isResolving } = useSeamlyLayoutMode()
45
- const { hasInterrupt } = useSeamlyInterrupt()
45
+ const { hasInterrupt } = useInterrupt()
46
46
  const currentConversationUrl = useSeamlyConversationUrl()
47
47
  const prevConversationUrl = useRef(null)
48
48
  const onActivityHandler = useSeamlyActivityEventHandler()
@@ -54,26 +54,20 @@ const SeamlyInstanceFunctionsLoader = () => {
54
54
 
55
55
  useSeamlyInstanceFunction(
56
56
  'askText',
57
- text => {
57
+ (text) => {
58
58
  sendMessage({ body: text })
59
59
  },
60
60
  [api?.send],
61
61
  )
62
- useSeamlyInstanceFunction(
63
- 'setLocale',
64
- locale => {
65
- sendContext({ locale })
66
- },
67
- [api?.send],
68
- )
62
+
69
63
  useSeamlyInstanceFunction(
70
64
  'setVariables',
71
- variables => {
65
+ (variables) => {
72
66
  sendContext({ variables })
73
67
  },
74
68
  [api?.send],
75
69
  )
76
- useSeamlyInstanceFunction('getVisibility', callback => {
70
+ useSeamlyInstanceFunction('getVisibility', (callback) => {
77
71
  if (callback) {
78
72
  callback(currentVisibility.current)
79
73
  } else {
@@ -84,7 +78,7 @@ const SeamlyInstanceFunctionsLoader = () => {
84
78
  })
85
79
  useSeamlyInstanceFunction(
86
80
  'setVisibility',
87
- visibilityState => {
81
+ (visibilityState) => {
88
82
  if (!Object.values(visibilityStates).includes(visibilityState)) {
89
83
  console.error(
90
84
  'Requested visibility states should be "open", "minimized" ,"hidden" or null.',
@@ -102,7 +96,7 @@ const SeamlyInstanceFunctionsLoader = () => {
102
96
  setVisibility(visibilityState)
103
97
  }
104
98
  },
105
- [api?.send],
99
+ [config?.api],
106
100
  )
107
101
  useSeamlyInstanceFunction(
108
102
  'sendCustomAction',
@@ -16,7 +16,7 @@ const SeamlyLiveRegion = ({ children }) => {
16
16
  const isMounted = useRef(true)
17
17
 
18
18
  const messageSetter = useCallback(
19
- state => {
19
+ (state) => {
20
20
  if (isMounted.current) {
21
21
  setMessage(state)
22
22
  eventBus.emit('aria-live', state)
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useCallback } from 'preact/hooks'
1
+ import { useEffect, useRef, useMemo } from 'preact/hooks'
2
2
  import { useI18n } from '../../../domains/i18n'
3
3
  import {
4
4
  useEvents,
@@ -20,8 +20,8 @@ const SeamlyNewNotifications = () => {
20
20
  const prevIsOpen = useRef(null)
21
21
  const debounceFunc = useRef(null)
22
22
 
23
- const notifyUnread = useCallback(
24
- debounce(eventArray => {
23
+ const notifyUnread = useMemo(() => {
24
+ return debounce((eventArray) => {
25
25
  const serverEventCount = eventArray.filter(
26
26
  ({ payload }) => !payload.fromClient && !payload.fromHistory,
27
27
  ).length
@@ -33,9 +33,8 @@ const SeamlyNewNotifications = () => {
33
33
  )
34
34
  previousServerEventCount.current = serverEventCount
35
35
  }
36
- }, newMessageScreenReaderWait),
37
- [sendPolite],
38
- )
36
+ }, newMessageScreenReaderWait)
37
+ }, [sendPolite, t])
39
38
 
40
39
  useEffect(() => {
41
40
  if (events.length > previousEventCount.current) {
@@ -1,4 +1,4 @@
1
- import { useEffect, useCallback, useRef } from 'preact/hooks'
1
+ import { useEffect, useRef, useMemo } from 'preact/hooks'
2
2
 
3
3
  import {
4
4
  useEvents,
@@ -28,9 +28,11 @@ const SeamlyReadState = () => {
28
28
  const { sendAction } = useSeamlyCommands()
29
29
  const unreadCount = useSeamlyUnreadCount()
30
30
  const { sendPolite } = useLiveRegion()
31
- const sendLive = useCallback(debounce(sendPolite, unreadScreenReaderWait), [
32
- sendPolite,
33
- ])
31
+ const sendLive = useMemo(
32
+ () => debounce(sendPolite, unreadScreenReaderWait),
33
+
34
+ [sendPolite],
35
+ )
34
36
  const prevIsVisible = useRef(null)
35
37
  const cancelSend = useRef(null)
36
38
 
@@ -40,13 +42,13 @@ const SeamlyReadState = () => {
40
42
  }
41
43
 
42
44
  const unread = events
43
- .filter(event => {
45
+ .filter((event) => {
44
46
  return (
45
47
  isUnreadMessage(event) &&
46
48
  event.payload.messageStatus === readStates.received
47
49
  )
48
50
  })
49
- .map(event => event.payload.id)
51
+ .map((event) => event.payload.id)
50
52
 
51
53
  if (unread.length > 0) {
52
54
  dispatch({ type: SET_EVENTS_READ, ids: unread })
@@ -5,7 +5,6 @@ import {
5
5
  useSeamlyResumeConversationPrompt,
6
6
  useSkiplinkTargetFocusing,
7
7
  useSeamlyEntry,
8
- useSeamlyConfig,
9
8
  useFileUploadMeta,
10
9
  } from '../../hooks/seamly-hooks'
11
10
  import { entryTypes } from '../../utils/seamly-utils'
@@ -15,18 +14,16 @@ import ResumeConversationPrompt from '../warnings/resume-conversation-prompt'
15
14
  import TextEntry from './text-entry'
16
15
  import UploadToggle from './upload-toggle'
17
16
  import Upload from './upload'
17
+ import { useConfig } from '../../../domains/config'
18
18
 
19
19
  const EntryContainer = () => {
20
20
  const entryContainer = useRef(null)
21
21
  const { hasCountdown } = useSeamlyIdleDetachCountdown()
22
22
  const [showCountdown, setShowCountDown] = useState(hasCountdown)
23
- const {
24
- hasPrompt: hasResumeConversationPrompt,
25
- } = useSeamlyResumeConversationPrompt()
26
- const [
27
- showResumeConversationPrompt,
28
- setShowResumeConversationPrompt,
29
- ] = useState(hasResumeConversationPrompt)
23
+ const { hasPrompt: hasResumeConversationPrompt } =
24
+ useSeamlyResumeConversationPrompt()
25
+ const [showResumeConversationPrompt, setShowResumeConversationPrompt] =
26
+ useState(hasResumeConversationPrompt)
30
27
  const focusSkiplinkTarget = useSkiplinkTargetFocusing()
31
28
  const containedFocus = useRef(false)
32
29
  const { activeEntry } = useSeamlyEntry()
@@ -35,7 +32,7 @@ const EntryContainer = () => {
35
32
  upload: Upload,
36
33
  })
37
34
  const [renderEntry, setRenderEntry] = useState(() => activeEntry)
38
- const config = useSeamlyConfig()
35
+ const config = useConfig()
39
36
  const { accountAllowsUploads } = useFileUploadMeta()
40
37
 
41
38
  const focusFn = useCallback(() => {
@@ -49,7 +46,7 @@ const EntryContainer = () => {
49
46
  const { entry } = customComponents || {}
50
47
 
51
48
  if (entry) {
52
- setEntryComponents(c => ({
49
+ setEntryComponents((c) => ({
53
50
  ...c,
54
51
  ...entry,
55
52
  }))
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useMemo } from 'preact/hooks'
1
+ import { useEffect, useMemo } from 'preact/hooks'
2
2
  import { useI18n } from '../../../../domains/i18n'
3
3
  import { useLiveRegion } from '../../../hooks/live-region-hooks'
4
4
  import { useEntryTextLimit } from '../../../hooks/seamly-state-hooks'
@@ -14,14 +14,16 @@ export function useCharacterLimit(controlName) {
14
14
  const { sendAssertive } = useLiveRegion()
15
15
  const { hasLimit, limit } = useEntryTextLimit()
16
16
 
17
- const debouncedSendAssertive = useCallback(
18
- debounce(sendAssertive, maxCharacterSrDebounceDelay),
17
+ const debouncedSendAssertive = useMemo(
18
+ () => debounce(sendAssertive, maxCharacterSrDebounceDelay),
19
19
  [sendAssertive],
20
20
  )
21
21
  const validateLimit = useMemo(() => {
22
22
  return debounce((_reachedCharacterWarning, _remainingChars) => {
23
23
  if (_reachedCharacterWarning) {
24
- debouncedSendAssertive(t('input.srCharacterLimitText', _remainingChars))
24
+ debouncedSendAssertive(
25
+ t('input.srCharacterLimitText', { limit: _remainingChars }),
26
+ )
25
27
  }
26
28
  }, maxCharacterSrDebounceDelay)
27
29
  }, [debouncedSendAssertive, t])