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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/build/dist/lib/components.js +14855 -20
  2. package/build/dist/lib/components.min.js +2 -1
  3. package/build/dist/lib/components.min.js.LICENSE.txt +48 -0
  4. package/build/dist/lib/config.js +9 -3
  5. package/build/dist/lib/config.min.js +1 -1
  6. package/build/dist/lib/contexts.js +14 -5
  7. package/build/dist/lib/contexts.min.js +1 -1
  8. package/build/dist/lib/deprecated-view.js +1 -1
  9. package/build/dist/lib/hooks.js +8446 -20
  10. package/build/dist/lib/hooks.min.js +2 -1
  11. package/build/dist/lib/hooks.min.js.LICENSE.txt +38 -0
  12. package/build/dist/lib/index.debug.js +585 -584
  13. package/build/dist/lib/index.debug.min.js +1 -1
  14. package/build/dist/lib/index.debug.min.js.LICENSE.txt +110 -110
  15. package/build/dist/lib/index.js +20279 -26454
  16. package/build/dist/lib/index.min.js +1 -1
  17. package/build/dist/lib/index.min.js.LICENSE.txt +6 -1
  18. package/build/dist/lib/standalone.js +27823 -34681
  19. package/build/dist/lib/standalone.min.js +1 -1
  20. package/build/dist/lib/standalone.min.js.LICENSE.txt +1 -1
  21. package/build/dist/lib/storage.js +6 -15
  22. package/build/dist/lib/style-guide.js +23181 -7921
  23. package/build/dist/lib/style-guide.min.js +1 -1
  24. package/build/dist/lib/style-guide.min.js.LICENSE.txt +10 -0
  25. package/build/dist/lib/styles-default-implementation.js +1 -1
  26. package/build/dist/lib/styles.js +1 -1
  27. package/build/dist/lib/utils.js +22149 -17
  28. package/build/dist/lib/utils.min.js +2 -1
  29. package/build/dist/lib/utils.min.js.LICENSE.txt +48 -0
  30. package/package.json +54 -52
  31. package/src/icons/icon_check-16.svg +14 -0
  32. package/src/icons/icon_check-32.svg +14 -0
  33. package/src/javascripts/api/conversation-connector.ts +149 -0
  34. package/src/javascripts/api/errors/seamly-base-error.js +19 -0
  35. package/src/javascripts/api/errors/seamly-unavailable-error.js +5 -7
  36. package/src/javascripts/api/{index.js → index.ts} +163 -116
  37. package/src/javascripts/config.types.ts +5 -4
  38. package/src/javascripts/domains/app/actions.ts +47 -46
  39. package/src/javascripts/domains/app/hooks.js +1 -1
  40. package/src/javascripts/domains/config/actions.ts +2 -8
  41. package/src/javascripts/domains/config/hooks.ts +1 -1
  42. package/src/javascripts/domains/config/selectors.ts +6 -6
  43. package/src/javascripts/domains/config/slice.ts +3 -3
  44. package/src/javascripts/domains/errors/index.ts +66 -0
  45. package/src/javascripts/domains/forms/context.ts +1 -1
  46. package/src/javascripts/domains/forms/forms.types.ts +3 -3
  47. package/src/javascripts/domains/forms/hooks.ts +10 -10
  48. package/src/javascripts/domains/forms/provider.tsx +9 -9
  49. package/src/javascripts/domains/i18n/actions.ts +11 -5
  50. package/src/javascripts/domains/i18n/hooks.ts +11 -8
  51. package/src/javascripts/domains/i18n/selectors.ts +10 -4
  52. package/src/javascripts/domains/i18n/slice.ts +0 -1
  53. package/src/javascripts/domains/interrupt/hooks.ts +1 -1
  54. package/src/javascripts/domains/interrupt/middleware.ts +1 -1
  55. package/src/javascripts/domains/store/index.ts +1 -1
  56. package/src/javascripts/domains/store/selectors.ts +16 -0
  57. package/src/javascripts/domains/store/slice.ts +47 -41
  58. package/src/javascripts/domains/store/store.types.ts +38 -10
  59. package/src/javascripts/domains/translations/components/{options-button.js → options-button.tsx} +30 -20
  60. package/src/javascripts/domains/translations/components/options-dialog/index.tsx +33 -0
  61. package/src/javascripts/domains/translations/components/options-dialog/translation-option.tsx +42 -0
  62. package/src/javascripts/domains/translations/components/options-dialog/translation-options.tsx +81 -0
  63. package/src/javascripts/domains/translations/components/translation-status.tsx +15 -0
  64. package/src/javascripts/domains/translations/hooks.ts +77 -11
  65. package/src/javascripts/domains/translations/slice.ts +20 -9
  66. package/src/javascripts/domains/translations/translations.types.ts +4 -2
  67. package/src/javascripts/domains/visibility/actions.ts +6 -10
  68. package/src/javascripts/domains/visibility/hooks.ts +33 -14
  69. package/src/javascripts/domains/visibility/selectors.ts +3 -2
  70. package/src/javascripts/domains/visibility/slice.ts +2 -6
  71. package/src/javascripts/index.ts +18 -22
  72. package/src/javascripts/lib/engine/{index.js → index.tsx} +25 -7
  73. package/src/javascripts/lib/url-helpers.ts +112 -0
  74. package/src/javascripts/package/components.js +15 -1
  75. package/src/javascripts/package/config.js +1 -1
  76. package/src/javascripts/package/contexts.js +5 -3
  77. package/src/javascripts/package/hooks.js +19 -1
  78. package/src/javascripts/package/utils.js +13 -3
  79. package/src/javascripts/schema.ts +28 -0
  80. package/src/javascripts/style-guide/components/app.js +16 -12
  81. package/src/javascripts/style-guide/components/links.js +6 -6
  82. package/src/javascripts/style-guide/components/static-core.js +14 -9
  83. package/src/javascripts/style-guide/components/view.js +2 -2
  84. package/src/javascripts/style-guide/states.js +132 -36
  85. package/src/javascripts/style-guide/style-guide-engine.js +2 -1
  86. package/src/javascripts/style-guide/style-guide-external-api.js +1 -1
  87. package/src/javascripts/ui/components/app-options/index.js +25 -6
  88. package/src/javascripts/ui/components/chat-app.js +1 -1
  89. package/src/javascripts/ui/components/chat-status/chat-status-action.tsx +30 -0
  90. package/src/javascripts/ui/components/chat-status/index.tsx +61 -0
  91. package/src/javascripts/ui/components/conversation/component-filter.js +9 -9
  92. package/src/javascripts/ui/components/conversation/{conversation.js → conversation.tsx} +32 -41
  93. package/src/javascripts/ui/components/conversation/event/card-component.js +2 -2
  94. package/src/javascripts/ui/components/conversation/event/card-message.js +1 -1
  95. package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js +2 -2
  96. package/src/javascripts/ui/components/conversation/event/carousel-component/index.js +4 -4
  97. package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +2 -2
  98. package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +1 -1
  99. package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-context.ts +12 -0
  100. package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-provider.tsx +46 -0
  101. package/src/javascripts/ui/components/conversation/event/chat-scroll/unread-messages-button.tsx +30 -0
  102. package/src/javascripts/ui/components/conversation/event/choice-prompt.js +12 -8
  103. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +6 -6
  104. package/src/javascripts/ui/components/conversation/event/cta.js +2 -2
  105. package/src/javascripts/ui/components/conversation/event/divider/index.js +0 -1
  106. package/src/javascripts/ui/components/conversation/event/divider/variants/default.js +1 -1
  107. package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +17 -22
  108. package/src/javascripts/ui/components/conversation/event/divider/variants/time-indicator.js +2 -2
  109. package/src/javascripts/ui/components/conversation/event/event-participant.js +1 -1
  110. package/src/javascripts/ui/components/conversation/event/event.tsx +66 -0
  111. package/src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js +1 -1
  112. package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +1 -1
  113. package/src/javascripts/ui/components/conversation/event/image-lightbox.js +1 -1
  114. package/src/javascripts/ui/components/conversation/event/image.js +2 -2
  115. package/src/javascripts/ui/components/conversation/event/splash.js +1 -1
  116. package/src/javascripts/ui/components/conversation/event/translation.js +1 -1
  117. package/src/javascripts/ui/components/conversation/event/upload.js +2 -2
  118. package/src/javascripts/ui/components/conversation/event/video.js +2 -2
  119. package/src/javascripts/ui/components/conversation/event-divider.js +1 -1
  120. package/src/javascripts/ui/components/conversation/message-container.js +1 -1
  121. package/src/javascripts/ui/components/conversation/use-chat-scroll.ts +108 -0
  122. package/src/javascripts/ui/components/core/{seamly-activity-monitor.js → seamly-activity-monitor.tsx} +12 -5
  123. package/src/javascripts/ui/components/core/seamly-api-context.ts +7 -0
  124. package/src/javascripts/ui/components/core/seamly-chat.tsx +8 -0
  125. package/src/javascripts/ui/components/core/{seamly-core.js → seamly-core.tsx} +27 -14
  126. package/src/javascripts/ui/components/core/seamly-event-subscriber.ts +340 -0
  127. package/src/javascripts/ui/components/core/seamly-file-upload.js +2 -2
  128. package/src/javascripts/ui/components/core/seamly-idle-detach-counter.js +1 -1
  129. package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +24 -11
  130. package/src/javascripts/ui/components/core/seamly-live-region.js +4 -4
  131. package/src/javascripts/ui/components/core/seamly-new-notifications.js +3 -3
  132. package/src/javascripts/ui/components/core/seamly-read-state.js +2 -33
  133. package/src/javascripts/ui/components/entry/deprecated-toggle-button.js +4 -4
  134. package/src/javascripts/ui/components/entry/entry-container.js +8 -8
  135. package/src/javascripts/ui/components/entry/text-entry/hooks.js +3 -3
  136. package/src/javascripts/ui/components/entry/text-entry/index.js +3 -3
  137. package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +4 -4
  138. package/src/javascripts/ui/components/entry/upload/file-upload-form.js +3 -3
  139. package/src/javascripts/ui/components/entry/upload/index.js +5 -5
  140. package/src/javascripts/ui/components/entry/upload-toggle.js +6 -6
  141. package/src/javascripts/ui/components/faq/faq.js +14 -14
  142. package/src/javascripts/ui/components/form-controls/error.js +2 -2
  143. package/src/javascripts/ui/components/form-controls/file-input.js +3 -3
  144. package/src/javascripts/ui/components/layout/agent-info.js +3 -3
  145. package/src/javascripts/ui/components/layout/chat-frame.js +20 -12
  146. package/src/javascripts/ui/components/layout/chat.js +5 -5
  147. package/src/javascripts/ui/components/layout/deprecated-app-frame.js +6 -6
  148. package/src/javascripts/ui/components/layout/deprecated-chat-frame.js +34 -0
  149. package/src/javascripts/ui/components/layout/header.js +2 -2
  150. package/src/javascripts/ui/components/layout/icon.js +11 -9
  151. package/src/javascripts/ui/components/layout/interrupt.js +7 -5
  152. package/src/javascripts/ui/components/layout/pre-chat-messages.js +1 -1
  153. package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
  154. package/src/javascripts/ui/components/options/options-button.js +5 -5
  155. package/src/javascripts/ui/components/options/{options-frame.js → options-frame.tsx} +52 -18
  156. package/src/javascripts/ui/components/options/transcript/index.js +9 -10
  157. package/src/javascripts/ui/components/options/transcript/transcript-form.js +2 -2
  158. package/src/javascripts/ui/components/suggestions/index.js +8 -8
  159. package/src/javascripts/ui/components/suggestions/suggestions-item.js +1 -1
  160. package/src/javascripts/{domains/translations/components/chat-status.js → ui/components/translation-chat-status/index.tsx} +13 -14
  161. package/src/javascripts/ui/components/translation-proposal/index.tsx +36 -0
  162. package/src/javascripts/ui/components/view/app-view.js +2 -7
  163. package/src/javascripts/ui/components/view/deprecated-view.js +8 -10
  164. package/src/javascripts/ui/components/view/index.js +6 -6
  165. package/src/javascripts/ui/components/view/inline-view.js +4 -8
  166. package/src/javascripts/ui/components/view/window-view/collapse-button.js +2 -2
  167. package/src/javascripts/ui/components/view/window-view/index.js +11 -17
  168. package/src/javascripts/ui/components/view/window-view/window-open-button.js +6 -6
  169. package/src/javascripts/ui/components/warnings/idle-detach-warning.js +3 -3
  170. package/src/javascripts/ui/components/warnings/prompt.js +1 -1
  171. package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +4 -4
  172. package/src/javascripts/ui/components/widgets/in-out-transition.js +20 -18
  173. package/src/javascripts/ui/components/widgets/lightbox.js +3 -3
  174. package/src/javascripts/ui/components/widgets/modal.js +2 -2
  175. package/src/javascripts/ui/components/widgets/upload-progress.js +2 -2
  176. package/src/javascripts/ui/hooks/file-upload-hooks.js +1 -1
  177. package/src/javascripts/ui/hooks/focus-helper-hooks.js +1 -1
  178. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +6 -6
  179. package/src/javascripts/ui/hooks/seamly-hooks.js +11 -10
  180. package/src/javascripts/ui/hooks/seamly-option-hooks.js +6 -6
  181. package/src/javascripts/ui/hooks/{seamly-state-hooks.js → seamly-state-hooks.ts} +9 -6
  182. package/src/javascripts/ui/hooks/use-click-outside.ts +29 -0
  183. package/src/javascripts/ui/hooks/use-event-component-mapping.js +11 -10
  184. package/src/javascripts/ui/hooks/use-interval.js +1 -1
  185. package/src/javascripts/ui/hooks/use-seamly-actions.ts +29 -29
  186. package/src/javascripts/ui/hooks/use-seamly-chat.js +14 -24
  187. package/src/javascripts/ui/hooks/use-seamly-commands.js +20 -15
  188. package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +8 -8
  189. package/src/javascripts/ui/hooks/use-seamly-resume-conversation-prompt.js +2 -2
  190. package/src/javascripts/ui/hooks/use-single-file-upload.js +1 -1
  191. package/src/javascripts/ui/hooks/utility-hooks.js +1 -1
  192. package/src/javascripts/ui/utils/general-utils.js +0 -23
  193. package/src/javascripts/ui/utils/seamly-utils.ts +10 -1
  194. package/src/javascripts/ui/utils/seamly-utils.types.ts +9 -0
  195. package/src/stylesheets/1-settings/_config.scss +1 -1
  196. package/src/stylesheets/3-chat/_chat.scss +24 -9
  197. package/src/stylesheets/5-components/_chat-status.scss +72 -16
  198. package/src/stylesheets/5-components/_conversation.scss +35 -1
  199. package/src/stylesheets/5-components/_disclaimer.scss +0 -5
  200. package/src/stylesheets/5-components/_options.scss +16 -6
  201. package/src/stylesheets/5-components/_translation-options.scss +51 -0
  202. package/src/stylesheets/6-default-implementation/_scrollbar.scss +1 -1
  203. package/src/stylesheets/7-deprecated/3-app/_app.scss +19 -4
  204. package/src/stylesheets/7-deprecated/5-components/_chat-status.scss +5 -0
  205. package/src/stylesheets/7-deprecated/5-components/_options.scss +1 -4
  206. package/src/stylesheets/7-deprecated/5-components/_translation-options.scss +49 -0
  207. package/src/stylesheets/deprecated-view.scss +1 -0
  208. package/src/stylesheets/styles.scss +1 -0
  209. package/webpack/config.common.js +4 -4
  210. package/webpack/config.package.js +10 -16
  211. package/webpack/config.site.js +4 -1
  212. package/webpack/config.test.js +2 -1
  213. package/build/dist/lib/deprecated-view.css +0 -1
  214. package/build/dist/lib/styles-default-implementation.css +0 -1
  215. package/build/dist/lib/styles.css +0 -1
  216. package/src/.DS_Store +0 -0
  217. package/src/javascripts/api/event-producer.js +0 -20
  218. package/src/javascripts/api/producer.js +0 -136
  219. package/src/javascripts/domains/errors/index.js +0 -37
  220. package/src/javascripts/domains/translations/components/options-dialog/form.js +0 -70
  221. package/src/javascripts/domains/translations/components/options-dialog/index.js +0 -87
  222. package/src/javascripts/ui/components/chat-status/index.js +0 -38
  223. package/src/javascripts/ui/components/conversation/event/event.js +0 -36
  224. package/src/javascripts/ui/components/core/seamly-api-context.js +0 -5
  225. package/src/javascripts/ui/components/core/seamly-event-subscriber.js +0 -279
@@ -1,44 +1,63 @@
1
+ import type { VisibilityOptions } from 'config.types'
2
+ import { RefObject, createRef } from 'preact'
3
+ import { useCallback, useEffect, useState } from 'preact/hooks'
4
+ import { useDispatch, useSelector } from 'react-redux'
1
5
  import { useConfig } from 'domains/config/hooks'
2
6
  import { useAppDispatch } from 'domains/store'
3
7
  import { setVisibility } from 'domains/visibility/actions'
4
8
  import { setShowInlineView } from 'domains/visibility/slice'
5
- import { VisibilityState } from 'domains/visibility/visibility.types'
6
- import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
7
- import { useDispatch, useSelector } from 'react-redux'
8
9
  import { visibilityStates } from './constants'
9
- import * as Selectors from './selectors'
10
+ import { selectShowInlineView, selectVisibility } from './selectors'
10
11
 
11
12
  export const useVisibility = () => {
12
13
  const dispatch = useAppDispatch()
13
- const visible = useSelector(Selectors.selectVisibility)
14
+ const visible = useSelector(selectVisibility)
14
15
  const isVisible = visible ? visible !== visibilityStates.hidden : false
15
16
  const isOpen = visible === visibilityStates.open
16
17
  const isMinimized = visible === visibilityStates.minimized
17
18
 
18
19
  const dispatchVisibility = useCallback(
19
- (visibility: VisibilityState) => dispatch(setVisibility(visibility)),
20
+ (visibility: VisibilityOptions) => dispatch(setVisibility(visibility)),
20
21
  [dispatch],
21
22
  )
22
23
 
24
+ const openChat = () => {
25
+ dispatchVisibility(visibilityStates.open as VisibilityOptions)
26
+ }
27
+
28
+ const closeChat = () => {
29
+ dispatchVisibility(visibilityStates.minimized as VisibilityOptions)
30
+ }
31
+
23
32
  return {
24
33
  isVisible,
25
34
  isOpen,
26
35
  isMinimized,
27
36
  visible,
28
37
  setVisibility: dispatchVisibility,
38
+ openChat,
39
+ closeChat,
29
40
  }
30
41
  }
31
42
 
43
+ type UseIntersectOptions = {
44
+ /** Stops observing when the root element is visible. */
45
+ freezeOnceVisible?: boolean
46
+ /** Determines if useIntersect is enabled. */
47
+ enabled?: boolean
48
+ /** The node ref to apply the intersection to */
49
+ containerRef?: RefObject<any>
50
+ }
51
+
32
52
  /**
33
53
  * Custom hook which enables initializing of IntersectionObserver on any node ref.
34
- * @param {object} options Hook options.
35
- * @param {boolean=} options.freezeOnceVisible Stops observing when the root element is visible.
36
- * @param {boolean=} options.enabled Determines if useIntersect is enabled.
37
54
  */
38
- const useIntersect = ({ freezeOnceVisible = false, enabled = true }) => {
55
+ export const useIntersect = ({
56
+ freezeOnceVisible = false,
57
+ enabled = true,
58
+ containerRef = createRef(),
59
+ }: UseIntersectOptions) => {
39
60
  const [entry, setEntry] = useState(null)
40
- const containerRef = useRef(null)
41
-
42
61
  const isVisible = !!entry?.isIntersecting || !enabled
43
62
  const frozen = isVisible && freezeOnceVisible
44
63
 
@@ -63,7 +82,7 @@ const useIntersect = ({ freezeOnceVisible = false, enabled = true }) => {
63
82
  observer.observe(node)
64
83
 
65
84
  return () => observer.disconnect()
66
- }, [enabled, frozen])
85
+ }, [containerRef, enabled, frozen])
67
86
 
68
87
  return { isVisible, containerRef }
69
88
  }
@@ -71,7 +90,7 @@ const useIntersect = ({ freezeOnceVisible = false, enabled = true }) => {
71
90
  export const useShowInlineView = () => {
72
91
  const dispatch = useDispatch()
73
92
  const { connectWhenInView } = useConfig()
74
- const showInlineView = useSelector(Selectors.selectShowInlineView)
93
+ const showInlineView = useSelector(selectShowInlineView)
75
94
 
76
95
  const { containerRef, isVisible } = useIntersect({
77
96
  enabled: connectWhenInView,
@@ -1,11 +1,12 @@
1
1
  import { createSelector } from '@reduxjs/toolkit'
2
+ import type { RootState } from 'domains/store'
2
3
 
3
4
  export const selectVisibility = createSelector(
4
- ({ visibility }) => visibility,
5
+ ({ visibility }: RootState) => visibility,
5
6
  (state) => state.visibility,
6
7
  )
7
8
 
8
9
  export const selectShowInlineView = createSelector(
9
- ({ visibility }) => visibility,
10
+ ({ visibility }: RootState) => visibility,
10
11
  (state) => state.showInlineView,
11
12
  )
@@ -1,5 +1,5 @@
1
- import { createSlice, PayloadAction } from '@reduxjs/toolkit'
2
- import { VisibilityOptions } from 'config.types'
1
+ import { PayloadAction, createSlice } from '@reduxjs/toolkit'
2
+ import type { VisibilityOptions } from 'config.types'
3
3
  import { initializeConfig } from 'domains/config/actions'
4
4
  import { setVisibility } from 'domains/visibility/actions'
5
5
  import { visibilityStates } from 'domains/visibility/constants'
@@ -14,9 +14,6 @@ export const visibilitySlice = createSlice({
14
14
  name: 'visibility',
15
15
  initialState,
16
16
  reducers: {
17
- setFromStorage: (state, action) => {
18
- state.visibility = action.payload
19
- },
20
17
  setShowInlineView: (state) => {
21
18
  state.showInlineView = true
22
19
  },
@@ -40,7 +37,6 @@ export const visibilitySlice = createSlice({
40
37
  },
41
38
  })
42
39
 
43
- export const { setFromStorage } = visibilitySlice.actions
44
40
  export const { setShowInlineView } = visibilitySlice.actions
45
41
 
46
42
  export default visibilitySlice.reducer
@@ -5,14 +5,6 @@ import initializeExternalApi from './lib/external-api/initialize-api'
5
5
  export default initializeExternalApi
6
6
 
7
7
  // Used by: StyleGuide
8
- export { API } from './api'
9
-
10
- // Used by: StyleGuide
11
- export { Provider as SeamlyStoreProvider } from 'react-redux'
12
- // Used by: StyleGuide
13
- export { default as SeamlyGeneralError } from './api/errors/seamly-general-error'
14
- // Used by: StyleGuide
15
- export { default as SeamlyOfflineError } from './api/errors/seamly-offline-error'
16
8
  // Used by: Client
17
9
  export { useConfig as useSeamlyConfig } from 'domains/config/hooks'
18
10
  // Used by: Client
@@ -23,18 +15,10 @@ export {
23
15
  useTranslations,
24
16
  useTranslationsContainer,
25
17
  } from 'domains/translations/hooks'
18
+ export { visibilityStates } from 'domains/visibility/constants'
26
19
  // Used by: Client
27
20
  export { useVisibility as useSeamlyVisibility } from 'domains/visibility/hooks'
28
- export { visibilityStates } from 'domains/visibility/constants'
29
21
  export { calculateVisibility } from 'domains/visibility/utils'
30
- // Used by: Client
31
- export { className } from './lib/css'
32
- // Used by: StyleGuide
33
- export { default as Engine } from './lib/engine'
34
- // Used by: StyleGuide
35
- export { default as ExternalApi } from './lib/external-api'
36
- // Used by: StyleGuide
37
- export { randomId } from './lib/id'
38
22
  // Used by: StyleGuide
39
23
  export { default as ComponentFilter } from 'ui/components/conversation/component-filter'
40
24
  // Used by: Client
@@ -74,6 +58,23 @@ export { default as Interrupt } from 'ui/components/layout/interrupt'
74
58
  export { default as View } from 'ui/components/view'
75
59
  // Used by: Client
76
60
  export { default as DeprecatedView } from 'ui/components/view/deprecated-view'
61
+ export { useSeamlyActions } from 'ui/hooks/use-seamly-actions'
62
+ // Used by: StyleGuide
63
+ // Used by: Client
64
+ export { eventTypes } from 'ui/utils/seamly-utils'
65
+ export { API } from './api'
66
+ // Used by: StyleGuide
67
+ export { default as SeamlyGeneralError } from './api/errors/seamly-general-error'
68
+ // Used by: StyleGuide
69
+ export { default as SeamlyOfflineError } from './api/errors/seamly-offline-error'
70
+ // Used by: Client
71
+ export { className } from './lib/css'
72
+ // Used by: StyleGuide
73
+ export { default as Engine } from './lib/engine'
74
+ // Used by: StyleGuide
75
+ export { default as ExternalApi } from './lib/external-api'
76
+ // Used by: StyleGuide
77
+ export { randomId } from './lib/id'
77
78
  // Used by: Client
78
79
  export {
79
80
  useEvents,
@@ -85,8 +86,3 @@ export {
85
86
  useSeamlyMessageContainerClassNames,
86
87
  useSeamlyOptions,
87
88
  } from './ui/hooks/seamly-hooks'
88
- // Used by: StyleGuide
89
- export { getUrlParams, getUrlSearchString } from './ui/utils/general-utils'
90
- // Used by: Client
91
- export { eventTypes } from './ui/utils/seamly-utils'
92
- export { useSeamlyActions } from 'ui/hooks/use-seamly-actions'
@@ -1,19 +1,33 @@
1
1
  import { API } from 'api'
2
+ import type { Config } from 'config.types'
3
+ import Events, { Events as EventsType } from 'minivents'
4
+ import { render } from 'preact'
5
+ import ChatApp from 'ui/components/chat-app'
6
+ import SeamlyCore from 'ui/components/core/seamly-core'
2
7
  import { initializeApp } from 'domains/app/actions'
3
-
4
8
  import { initializeConfig } from 'domains/config/actions'
5
9
  import { setConfig } from 'domains/config/slice'
6
10
  import { setLocale } from 'domains/i18n/actions'
7
-
8
11
  import { createStore } from 'domains/store'
9
12
  import { initializeVisibility } from 'domains/visibility/actions'
10
- import Events from 'minivents'
11
- import { render } from 'preact'
12
- import ChatApp from 'ui/components/chat-app'
13
- import SeamlyCore from 'ui/components/core/seamly-core'
13
+ import type ExternalApi from 'lib/external-api'
14
14
 
15
15
  export default class Engine {
16
- constructor(config, externalApi) {
16
+ config: Config
17
+
18
+ namespace: string
19
+
20
+ parentElement: HTMLElement
21
+
22
+ externalApi: ExternalApi
23
+
24
+ functions: {}
25
+
26
+ eventBus: EventsType
27
+
28
+ api: API
29
+
30
+ constructor(config: Config, externalApi: ExternalApi) {
17
31
  const { namespace = '', parentElement, showFaq, ...restConfig } = config
18
32
 
19
33
  this.config = {
@@ -32,6 +46,8 @@ export default class Engine {
32
46
  context: config.context,
33
47
  })
34
48
 
49
+ // Following are ignored because the types of minivents do not match the docs.
50
+ // @ts-ignore
35
51
  this.eventBus = new Events()
36
52
  this.functions = {}
37
53
  this.registerFunctions({
@@ -39,9 +55,11 @@ export default class Engine {
39
55
  off: this.eventBus.off,
40
56
  })
41
57
 
58
+ // @ts-ignore
42
59
  this.eventBus.on('function.register', (functionName, fn) =>
43
60
  this.registerFunction(functionName, fn),
44
61
  )
62
+ // @ts-ignore
45
63
  this.eventBus.on('function.unregister', (functionName, fn) =>
46
64
  this.unregisterFunction(functionName, fn),
47
65
  )
@@ -0,0 +1,112 @@
1
+ export const getUrlSearchParams = () => {
2
+ const params = new URLSearchParams(window.location.search)
3
+
4
+ return Array.from(params.entries()).reduce(
5
+ (acc, [key, val]) => ({ ...acc, [key]: val }),
6
+ {},
7
+ )
8
+ }
9
+
10
+ // Return search parameters as a string
11
+ export const getUrlSearchString = (params: Record<string, string>) =>
12
+ new URLSearchParams(params).toString()
13
+
14
+ // Return search parameters found in URL or sessionStorage
15
+ export const getSearchParamsByKeys = <T extends string>(
16
+ ...keys: T[]
17
+ ): Record<T, string> => {
18
+ const url = new URL(window.location.href)
19
+
20
+ const values = keys.reduce((acc, key) => {
21
+ const searchParam = url.searchParams.get(key)
22
+ const param = searchParam || sessionStorage.getItem(key)
23
+ if (param) {
24
+ acc[key] = param
25
+ }
26
+ return acc
27
+ }, {} as Record<T, string>)
28
+
29
+ return values
30
+ }
31
+
32
+ // Adds a search parameter to the url
33
+ export const setSearchParam = (key: string, value: string): void => {
34
+ const url = new URL(window.location.href)
35
+ const { searchParams } = url
36
+
37
+ searchParams.set(key, value)
38
+
39
+ url.search = searchParams.toString()
40
+ window.location.href = url.toString()
41
+ }
42
+
43
+ // Replace search parameters with those found in URL search parameters or sessionStorage
44
+ export const replaceSearchParams = <T extends string>(
45
+ ...keys: T[]
46
+ ): Record<T, string> => {
47
+ const url = new URL(window.location.href)
48
+
49
+ const params = keys.reduce<URLSearchParams>((acc, key) => {
50
+ const paramValue = url.searchParams.get(key)
51
+
52
+ const value = paramValue || sessionStorage.getItem(key)
53
+
54
+ // If the query parameter is present, add it to the sessionStorage
55
+ if (paramValue) {
56
+ sessionStorage.setItem(key, paramValue)
57
+ }
58
+
59
+ // Bail if there is nothing to set
60
+ if (!value) return acc
61
+
62
+ acc.set(key, value)
63
+ return acc
64
+ }, new URLSearchParams())
65
+
66
+ // To keep other params in place, we merge them with the current URL parameters
67
+ const combinedParams = new URLSearchParams({
68
+ ...Object.fromEntries(url.searchParams),
69
+ ...Object.fromEntries(params),
70
+ })
71
+
72
+ if (combinedParams.toString()) {
73
+ window.history.replaceState(null, null, `?${combinedParams}`)
74
+ }
75
+
76
+ return getSearchParamsByKeys(...params.keys())
77
+ }
78
+
79
+ // Sets up click handlers for elements with data-attribute `data-reset-search-params`.
80
+ // Clicking these will remove all given keys from the sessionStorage and remove the search parameters from the url
81
+
82
+ // If you want to reset both 'apiKey' and 'locale' when the event is executed, you would use it as followed
83
+ // import { initResetSearchParams } from 'lib/url-helpers'
84
+
85
+ // Setup the event handlers for the search parameters you want to be reset after execution.
86
+ // initResetSearchParams('apiKey', 'locale')
87
+
88
+ // Somewhere in the HTML add an element with the 'data-reset-search-params' attribute.
89
+ // <a href="#" data-reset-search-params>Reset account and source locale</a>
90
+ export const initResetSearchParams = <T extends string>(...keys: T[]): void => {
91
+ const resetLink = document.querySelector('[data-reset-search-params]')
92
+
93
+ if (!resetLink) {
94
+ return
95
+ }
96
+
97
+ resetLink.addEventListener('click', (e) => {
98
+ e.preventDefault()
99
+ const url = new URL(window.location.href)
100
+
101
+ keys.forEach((key) => {
102
+ // Clear current session for each key
103
+ sessionStorage.removeItem(key)
104
+
105
+ // Delete key from url
106
+ url.searchParams.delete(key)
107
+ })
108
+
109
+ // Reload page
110
+ window.location.href = url.toString()
111
+ })
112
+ }
@@ -1,3 +1,17 @@
1
+ import Conversation from 'ui/components/conversation/conversation'
2
+ import EventParticipant from 'ui/components/conversation/event/event-participant'
3
+ import Text from 'ui/components/conversation/event/text'
4
+ import MessageContainer from 'ui/components/conversation/message-container'
5
+ import DeprecatedToggleButton from 'ui/components/entry/deprecated-toggle-button'
6
+ import EntryContainer from 'ui/components/entry/entry-container'
7
+ import AgentInfo from 'ui/components/layout/agent-info'
8
+ import Chat from 'ui/components/layout/chat'
9
+ import ChatFrame from 'ui/components/layout/chat-frame'
10
+ import Header from 'ui/components/layout/header'
11
+ import Icon from 'ui/components/layout/icon'
12
+ import View from 'ui/components/view'
13
+ import DeprecatedView from 'ui/components/view/deprecated-view'
14
+
1
15
  export {
2
16
  AgentInfo,
3
17
  Chat,
@@ -12,4 +26,4 @@ export {
12
26
  DeprecatedToggleButton,
13
27
  DeprecatedView,
14
28
  View,
15
- } from '@seamly/web-ui'
29
+ }
@@ -1 +1 @@
1
- export { visibilityStates } from '@seamly/web-ui'
1
+ export { visibilityStates } from 'domains/visibility/constants'
@@ -1,5 +1,7 @@
1
- export {
1
+ import {
2
2
  SeamlyApiContext,
3
3
  SeamlyEventBusContext,
4
- SeamlyLiveRegionContext,
5
- } from '@seamly/web-ui'
4
+ } from 'ui/components/core/seamly-api-context'
5
+ import { SeamlyLiveRegionContext } from 'ui/components/core/seamly-live-region-context'
6
+
7
+ export { SeamlyApiContext, SeamlyEventBusContext, SeamlyLiveRegionContext }
@@ -1,3 +1,21 @@
1
+ import { useChoicePrompt } from 'ui/components/conversation/event/choice-prompt'
2
+ import {
3
+ useSeamlyEventStream,
4
+ useSeamlyIdleDetachCountdown,
5
+ useSeamlyMessageContainerClassNames,
6
+ useSeamlyOptions,
7
+ } from 'ui/hooks/seamly-hooks'
8
+ import { useEvents } from 'ui/hooks/seamly-state-hooks'
9
+ import useSeamlyChat from 'ui/hooks/use-seamly-chat'
10
+ import useSeamlyCommands from 'ui/hooks/use-seamly-commands'
11
+ import { useGeneratedId } from 'ui/hooks/utility-hooks'
12
+ import { useI18n } from 'domains/i18n/hooks'
13
+ import {
14
+ useTranslatedEventData,
15
+ useTranslations,
16
+ useTranslationsContainer,
17
+ } from 'domains/translations/hooks'
18
+
1
19
  export {
2
20
  useChoicePrompt,
3
21
  useEvents,
@@ -12,4 +30,4 @@ export {
12
30
  useTranslatedEventData,
13
31
  useTranslations,
14
32
  useTranslationsContainer,
15
- } from '@seamly/web-ui'
33
+ }
@@ -1,10 +1,20 @@
1
+ import { eventTypes } from 'ui/utils/seamly-utils'
2
+ import { calculateVisibility } from 'domains/visibility/utils'
3
+ import { className } from 'lib/css'
4
+ import Engine from 'lib/engine'
5
+ import ExternalApi from 'lib/external-api'
6
+ import { randomId } from 'lib/id'
7
+
8
+ export {
9
+ getSearchParamsByKeys,
10
+ initResetSearchParams,
11
+ replaceSearchParams,
12
+ } from 'lib/url-helpers'
1
13
  export {
2
14
  calculateVisibility,
3
15
  className,
4
16
  Engine,
5
17
  eventTypes,
6
18
  ExternalApi,
7
- getUrlParams,
8
- getUrlSearchString,
9
19
  randomId,
10
- } from '@seamly/web-ui'
20
+ }
@@ -185,6 +185,29 @@ export interface components {
185
185
  * @example false
186
186
  */
187
187
  resumeConversationPrompt?: boolean
188
+ /** @description Additional information to be able to show a translation proposal element. */
189
+ translationProposal?: {
190
+ /**
191
+ * @description Title of the activate button
192
+ * @example Activate
193
+ */
194
+ buttonLabel?: string
195
+ /**
196
+ * @description Proposed locale for translation
197
+ * @example en-GB
198
+ */
199
+ proposedLocale?: string
200
+ /**
201
+ * @description Screen reader text for dismiss button
202
+ * @example Dismiss translation proposal
203
+ */
204
+ srDismissButtonText?: string
205
+ /**
206
+ * @description Title of the shown translation proposal element
207
+ * @example Do you want to chat in English?
208
+ */
209
+ titleLabel?: string
210
+ } | null
188
211
  }
189
212
  }
190
213
  _links?: {
@@ -1084,6 +1107,11 @@ export interface operations {
1084
1107
  * @example https://seamly.ai/en/contact-us/
1085
1108
  */
1086
1109
  currentUrl?: string
1110
+ /**
1111
+ * @description The preferred locale of the user, for example the language of the browser UI.
1112
+ * @example en-US
1113
+ */
1114
+ preferredLocale?: string
1087
1115
  /**
1088
1116
  * @description The screen resolution of the user.
1089
1117
  * @example 2560x1440
@@ -1,5 +1,6 @@
1
- import { getUrlParams, getUrlSearchString, randomId } from '@seamly/web-ui'
2
1
  import { useCallback, useEffect, useState } from 'preact/hooks'
2
+ import { randomId } from 'lib/id'
3
+ import { getSearchParamsByKeys, getUrlSearchParams } from 'lib/url-helpers'
3
4
  import StyleGuideLinks from 'style-guide/components/links'
4
5
  import StyleGuideView from 'style-guide/components/view'
5
6
  import { getDeprecatedStateObj, getStateObj } from 'style-guide/states'
@@ -22,6 +23,7 @@ const StyleGuideApp = ({
22
23
  styleGuideConfig.showLayoutModes || ['inline', 'window'],
23
24
  customMessageEventBodies,
24
25
  )
26
+
25
27
  return Object.keys(mainStateObj).reduce(
26
28
  (acc, key) => ({
27
29
  ...acc,
@@ -47,6 +49,13 @@ const StyleGuideApp = ({
47
49
 
48
50
  const getState = useCallback(
49
51
  (layoutMode, feature) => {
52
+ const keys = getSearchParamsByKeys('apiKey', 'locale')
53
+ const combinedParams = new URLSearchParams({
54
+ ...keys,
55
+ layoutMode,
56
+ feature,
57
+ })
58
+ window.history.replaceState(null, null, `?${combinedParams}`)
50
59
  const { headingText } = mainState[feature]
51
60
  setSelectedStateDescription(headingText)
52
61
  const bareState = mainState[feature][layoutMode]
@@ -62,6 +71,10 @@ const StyleGuideApp = ({
62
71
  ...config,
63
72
  showDisclaimer:
64
73
  bareState.config.showDisclaimer || config.showDisclaimer,
74
+ context: {
75
+ ...config.context,
76
+ ...bareState.config?.context,
77
+ },
65
78
  layoutMode: bareState.config.layoutMode,
66
79
  ...(overrideMessages ? { messages: overrideMessages } : {}),
67
80
  showFaq,
@@ -95,17 +108,8 @@ const StyleGuideApp = ({
95
108
  }, [staticState, setStaticState, showStyleGuide])
96
109
 
97
110
  const loadFromUrl = useCallback(() => {
98
- const params = getUrlParams()
99
- if (Object.keys(params).length !== 2) {
100
- window.history.pushState(
101
- null,
102
- null,
103
- `${window.location.pathname}?${getUrlSearchString({
104
- layoutMode: 'inline',
105
- feature: 'base',
106
- })}`,
107
- )
108
- }
111
+ const params = getUrlSearchParams()
112
+
109
113
  const { layoutMode = 'inline', feature = 'base' } = params
110
114
  updateState(getState(layoutMode, feature))
111
115
  window.title = `Style`
@@ -1,4 +1,4 @@
1
- import { getUrlSearchString, getUrlParams } from '@seamly/web-ui'
1
+ import { getUrlSearchParams, getUrlSearchString } from 'lib/url-helpers'
2
2
  import { categories } from 'style-guide/states'
3
3
 
4
4
  const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
@@ -13,7 +13,7 @@ const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
13
13
  setSelectedState(actionObj)
14
14
  }
15
15
 
16
- const currentSearch = getUrlParams(window.location.search)
16
+ const currentSearch = getUrlSearchParams()
17
17
 
18
18
  return (
19
19
  <nav aria-label="Style guide navigation" className="nav--styleguide">
@@ -54,8 +54,8 @@ const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
54
54
  <li
55
55
  key={layoutMode}
56
56
  className={
57
- layoutMode === currentSearch.layoutMode &&
58
- feature === currentSearch.feature
57
+ layoutMode === currentSearch?.layoutMode &&
58
+ feature === currentSearch?.feature
59
59
  ? 'state__selected'
60
60
  : null
61
61
  }
@@ -69,8 +69,8 @@ const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
69
69
  feature,
70
70
  })}`}
71
71
  aria-current={
72
- layoutMode === currentSearch.layoutMode &&
73
- feature === currentSearch.feature
72
+ layoutMode === currentSearch?.layoutMode &&
73
+ feature === currentSearch?.feature
74
74
  ? 'page'
75
75
  : null
76
76
  }
@@ -1,15 +1,17 @@
1
1
  import { configureStore } from '@reduxjs/toolkit'
2
+ import { useMemo, useRef } from 'preact/hooks'
3
+ import { Provider } from 'react-redux'
4
+ import ComponentFilter from 'ui/components/conversation/component-filter'
2
5
  import {
3
- ComponentFilter,
4
6
  SeamlyApiContext,
5
7
  SeamlyEventBusContext,
6
- SeamlyLiveRegionContext,
7
- SeamlyStoreProvider,
8
- } from '@seamly/web-ui'
8
+ } from 'ui/components/core/seamly-api-context'
9
+ import SeamlyChat from 'ui/components/core/seamly-chat'
10
+ import { SeamlyLiveRegionContext } from 'ui/components/core/seamly-live-region-context'
9
11
  import appReducer from 'domains/app/slice'
10
12
  import configReducer, {
11
- setPreChatEvents,
12
13
  setConfig,
14
+ setPreChatEvents,
13
15
  } from 'domains/config/slice'
14
16
  import formsReducer from 'domains/forms/slice'
15
17
  import i18nReducer, {
@@ -20,7 +22,6 @@ import interruptReducer from 'domains/interrupt/slice'
20
22
  import stateReducer, { setParticipant } from 'domains/store/slice'
21
23
  import translationReducer from 'domains/translations/slice'
22
24
  import visibilityReducer from 'domains/visibility/slice'
23
- import { useMemo, useRef } from 'preact/hooks'
24
25
 
25
26
  const bareApi = {
26
27
  send: () => {
@@ -38,6 +39,8 @@ const bareApi = {
38
39
  },
39
40
  },
40
41
  hasConversation: () => false,
42
+ connected: false,
43
+ ready: false,
41
44
  }
42
45
 
43
46
  const SeamlyStaticCore = ({
@@ -117,15 +120,17 @@ const SeamlyStaticCore = ({
117
120
 
118
121
  return (
119
122
  state && (
120
- <SeamlyStoreProvider store={store}>
123
+ <Provider store={store}>
121
124
  <SeamlyEventBusContext.Provider value={eventBusRef.current}>
122
125
  <SeamlyLiveRegionContext.Provider value={liveMsgRef.current}>
123
126
  <SeamlyApiContext.Provider value={bareApi}>
124
- <ComponentFilter>{children}</ComponentFilter>
127
+ <SeamlyChat>
128
+ <ComponentFilter>{children}</ComponentFilter>
129
+ </SeamlyChat>
125
130
  </SeamlyApiContext.Provider>
126
131
  </SeamlyLiveRegionContext.Provider>
127
132
  </SeamlyEventBusContext.Provider>
128
- </SeamlyStoreProvider>
133
+ </Provider>
129
134
  )
130
135
  )
131
136
  }
@@ -1,5 +1,5 @@
1
- import { useState, useEffect } from 'preact/hooks'
2
- import { View } from '@seamly/web-ui'
1
+ import { useEffect, useState } from 'preact/hooks'
2
+ import View from 'ui/components/view'
3
3
  import { timeout } from 'ui/hooks/focus-helper-hooks'
4
4
  import StyleGuideStaticCore from './static-core'
5
5