@seamly/web-ui 20.7.0 → 20.8.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/CHANGELOG.md +212 -16
  2. package/build/dist/lib/hooks.js +1 -1
  3. package/build/dist/lib/hooks.min.js +1 -1
  4. package/build/dist/lib/index.debug.js +939 -784
  5. package/build/dist/lib/index.debug.min.js +1 -1
  6. package/build/dist/lib/index.debug.min.js.LICENSE.txt +186 -130
  7. package/build/dist/lib/index.js +24806 -19703
  8. package/build/dist/lib/index.min.js +1 -1
  9. package/build/dist/lib/index.min.js.LICENSE.txt +38 -4
  10. package/build/dist/lib/standalone.js +32726 -26838
  11. package/build/dist/lib/standalone.min.js +1 -1
  12. package/build/dist/lib/standalone.min.js.LICENSE.txt +39 -0
  13. package/build/dist/lib/storage.js +2 -2
  14. package/build/dist/lib/storage.min.js +1 -1
  15. package/build/dist/lib/style-guide.js +8649 -7863
  16. package/build/dist/lib/style-guide.min.js +2 -1
  17. package/build/dist/lib/style-guide.min.js.LICENSE.txt +38 -0
  18. package/build/dist/lib/utils.js +1 -2
  19. package/build/dist/lib/utils.min.js +1 -1
  20. package/package.json +19 -9
  21. package/src/icons/avatar_agent-32.svg +7 -0
  22. package/src/icons/avatar_bot-32.svg +6 -1
  23. package/src/javascripts/api/index.js +1 -1
  24. package/src/javascripts/{config.js → config.ts} +3 -1
  25. package/src/javascripts/config.types.ts +95 -0
  26. package/src/javascripts/domains/app/actions.ts +83 -0
  27. package/src/javascripts/domains/app/app.types.ts +3 -0
  28. package/src/javascripts/domains/app/hooks.js +3 -5
  29. package/src/javascripts/domains/app/selectors.ts +6 -0
  30. package/src/javascripts/domains/app/slice.ts +30 -0
  31. package/src/javascripts/domains/config/actions.ts +45 -0
  32. package/src/javascripts/domains/config/hooks.ts +19 -0
  33. package/src/javascripts/domains/config/selectors.ts +24 -0
  34. package/src/javascripts/domains/config/slice.ts +111 -0
  35. package/src/javascripts/domains/errors/index.js +13 -9
  36. package/src/javascripts/domains/forms/context.ts +14 -0
  37. package/src/javascripts/domains/forms/forms.types.ts +24 -0
  38. package/src/javascripts/domains/forms/{hooks.js → hooks.ts} +23 -26
  39. package/src/javascripts/domains/forms/{provider.js → provider.tsx} +20 -14
  40. package/src/javascripts/domains/forms/{selectors.js → selectors.ts} +7 -8
  41. package/src/javascripts/domains/forms/slice.ts +84 -0
  42. package/src/javascripts/domains/forms/utils.ts +15 -0
  43. package/src/javascripts/domains/i18n/actions.ts +24 -0
  44. package/src/javascripts/domains/i18n/{hooks.js → hooks.ts} +2 -2
  45. package/src/javascripts/domains/i18n/i18n.types.ts +6 -0
  46. package/src/javascripts/domains/i18n/selectors.ts +16 -0
  47. package/src/javascripts/domains/i18n/{reducer.js → slice.ts} +43 -37
  48. package/src/javascripts/domains/interrupt/{hooks.js → hooks.ts} +2 -2
  49. package/src/javascripts/domains/interrupt/{middleware.js → middleware.ts} +11 -8
  50. package/src/javascripts/domains/interrupt/selectors.ts +6 -0
  51. package/src/javascripts/domains/interrupt/slice.ts +40 -0
  52. package/src/javascripts/domains/options/middleware.js +9 -6
  53. package/src/javascripts/domains/redux/redux.types.ts +11 -0
  54. package/src/javascripts/domains/store/index.ts +53 -0
  55. package/src/javascripts/domains/store/slice.ts +639 -0
  56. package/src/javascripts/domains/store/store.types.ts +135 -0
  57. package/src/javascripts/domains/translations/components/chat-status.js +2 -2
  58. package/src/javascripts/domains/translations/components/options-button.js +1 -1
  59. package/src/javascripts/domains/translations/components/options-dialog/form.js +5 -5
  60. package/src/javascripts/domains/translations/components/options-dialog/index.js +2 -2
  61. package/src/javascripts/domains/translations/{hooks.js → hooks.ts} +28 -23
  62. package/src/javascripts/domains/translations/middleware.js +29 -27
  63. package/src/javascripts/domains/translations/selectors.js +4 -9
  64. package/src/javascripts/domains/translations/slice.ts +67 -0
  65. package/src/javascripts/domains/translations/translations.types.ts +12 -0
  66. package/src/javascripts/domains/visibility/{actions.js → actions.ts} +25 -19
  67. package/src/javascripts/domains/visibility/{hooks.js → hooks.ts} +13 -10
  68. package/src/javascripts/domains/visibility/{selectors.js → selectors.ts} +3 -6
  69. package/src/javascripts/domains/visibility/slice.ts +38 -0
  70. package/src/javascripts/domains/visibility/utils.js +0 -9
  71. package/src/javascripts/domains/visibility/visibility.types.ts +6 -0
  72. package/src/javascripts/index.ts +92 -0
  73. package/src/javascripts/lib/engine/index.js +15 -11
  74. package/src/javascripts/lib/external-api/initialize-api.js +1 -1
  75. package/src/javascripts/lib/id.js +5 -8
  76. package/src/javascripts/lib/mutex.js +3 -1
  77. package/src/javascripts/lib/store/providers/cookie-storage.js +1 -1
  78. package/src/javascripts/lib/store/providers/session-storage.js +1 -1
  79. package/src/javascripts/package/hooks.js +2 -2
  80. package/src/javascripts/package/utils.js +0 -1
  81. package/src/javascripts/schema.ts +1455 -0
  82. package/src/javascripts/style-guide/components/app.js +4 -4
  83. package/src/javascripts/style-guide/components/static-core.js +87 -65
  84. package/src/javascripts/style-guide/components/view.js +4 -4
  85. package/src/javascripts/style-guide/state-helpers/index.js +5 -5
  86. package/src/javascripts/style-guide/states.js +6 -4
  87. package/src/javascripts/style-guide.ts +5 -0
  88. package/src/javascripts/ui/components/app-options/index.js +2 -4
  89. package/src/javascripts/ui/components/conversation/component-filter.js +1 -1
  90. package/src/javascripts/ui/components/conversation/conversation.js +5 -5
  91. package/src/javascripts/ui/components/conversation/event/card-message.js +1 -1
  92. package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js +1 -1
  93. package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +1 -1
  94. package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +1 -1
  95. package/src/javascripts/ui/components/conversation/event/choice-prompt.js +2 -2
  96. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +11 -14
  97. package/src/javascripts/ui/components/conversation/event/cta.js +1 -1
  98. package/src/javascripts/ui/components/conversation/event/divider/variants/default.js +1 -1
  99. package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +5 -2
  100. package/src/javascripts/ui/components/conversation/event/event-participant.js +2 -2
  101. package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +2 -2
  102. package/src/javascripts/ui/components/conversation/event/image-lightbox.js +1 -1
  103. package/src/javascripts/ui/components/conversation/event/image.js +5 -7
  104. package/src/javascripts/ui/components/conversation/event/participant.js +1 -1
  105. package/src/javascripts/ui/components/conversation/event/splash.js +3 -3
  106. package/src/javascripts/ui/components/conversation/event/text.js +1 -1
  107. package/src/javascripts/ui/components/conversation/event/translation.js +2 -2
  108. package/src/javascripts/ui/components/conversation/event/upload.js +2 -2
  109. package/src/javascripts/ui/components/conversation/event/video.js +1 -1
  110. package/src/javascripts/ui/components/conversation/message-container.js +4 -4
  111. package/src/javascripts/ui/components/core/seamly-api-context.js +1 -1
  112. package/src/javascripts/ui/components/core/seamly-core.js +15 -14
  113. package/src/javascripts/ui/components/core/seamly-event-subscriber.js +96 -91
  114. package/src/javascripts/ui/components/core/seamly-file-upload.js +20 -24
  115. package/src/javascripts/ui/components/core/seamly-initializer.js +1 -1
  116. package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +5 -4
  117. package/src/javascripts/ui/components/core/seamly-new-notifications.js +2 -2
  118. package/src/javascripts/ui/components/core/seamly-read-state.js +10 -17
  119. package/src/javascripts/ui/components/entry/deprecated-toggle-button.js +3 -3
  120. package/src/javascripts/ui/components/entry/entry-container.js +4 -6
  121. package/src/javascripts/ui/components/entry/text-entry/hooks.js +3 -3
  122. package/src/javascripts/ui/components/entry/text-entry/index.js +3 -2
  123. package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +6 -10
  124. package/src/javascripts/ui/components/entry/upload/file-upload-form.js +2 -2
  125. package/src/javascripts/ui/components/entry/upload/index.js +10 -9
  126. package/src/javascripts/ui/components/entry/upload-toggle.js +2 -2
  127. package/src/javascripts/ui/components/faq/faq.js +6 -6
  128. package/src/javascripts/ui/components/form-controls/file-input.js +1 -1
  129. package/src/javascripts/ui/components/form-controls/form.js +1 -1
  130. package/src/javascripts/ui/components/form-controls/input.js +1 -1
  131. package/src/javascripts/ui/components/form-controls/select.js +1 -1
  132. package/src/javascripts/ui/components/layout/agent-info.js +4 -4
  133. package/src/javascripts/ui/components/layout/chat-frame.js +3 -3
  134. package/src/javascripts/ui/components/layout/chat.js +11 -12
  135. package/src/javascripts/ui/components/layout/deprecated-app-frame.js +10 -9
  136. package/src/javascripts/ui/components/layout/header.js +1 -1
  137. package/src/javascripts/ui/components/layout/interrupt.js +23 -24
  138. package/src/javascripts/ui/components/layout/pre-chat-messages.js +11 -11
  139. package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
  140. package/src/javascripts/ui/components/options/options-button.js +12 -10
  141. package/src/javascripts/ui/components/options/transcript/index.js +2 -2
  142. package/src/javascripts/ui/components/options/transcript/transcript-form.js +1 -1
  143. package/src/javascripts/ui/components/suggestions/index.js +9 -8
  144. package/src/javascripts/ui/components/view/deprecated-view.js +19 -16
  145. package/src/javascripts/ui/components/view/index.js +12 -12
  146. package/src/javascripts/ui/components/view/inline-view.js +2 -2
  147. package/src/javascripts/ui/components/view/window-view/collapse-button.js +3 -3
  148. package/src/javascripts/ui/components/view/window-view/index.js +13 -13
  149. package/src/javascripts/ui/components/view/window-view/window-open-button.js +13 -13
  150. package/src/javascripts/ui/components/warnings/idle-detach-warning.js +1 -1
  151. package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +1 -1
  152. package/src/javascripts/ui/components/widgets/lightbox.js +2 -2
  153. package/src/javascripts/ui/components/widgets/upload-progress.js +1 -1
  154. package/src/javascripts/ui/hooks/component-helper-hooks.js +1 -1
  155. package/src/javascripts/ui/hooks/file-upload-hooks.js +4 -6
  156. package/src/javascripts/ui/hooks/focus-helper-hooks.js +14 -12
  157. package/src/javascripts/ui/hooks/live-region-hooks.js +2 -0
  158. package/src/javascripts/ui/hooks/seamly-api-hooks.js +8 -3
  159. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +28 -25
  160. package/src/javascripts/ui/hooks/seamly-hooks.js +25 -25
  161. package/src/javascripts/ui/hooks/seamly-option-hooks.js +17 -19
  162. package/src/javascripts/ui/hooks/seamly-state-hooks.js +14 -13
  163. package/src/javascripts/ui/hooks/use-seamly-chat.js +15 -25
  164. package/src/javascripts/ui/hooks/use-seamly-commands.js +46 -46
  165. package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +22 -24
  166. package/src/javascripts/ui/hooks/use-seamly-resume-conversation-prompt.js +8 -9
  167. package/src/javascripts/ui/hooks/use-single-file-upload.js +4 -6
  168. package/src/javascripts/ui/hooks/utility-hooks.js +4 -4
  169. package/src/javascripts/ui/utils/form-utils.js +0 -145
  170. package/src/javascripts/ui/utils/general-utils.js +3 -4
  171. package/src/javascripts/ui/utils/seamly-utils.ts +73 -0
  172. package/webpack/config.common.js +16 -0
  173. package/webpack/config.dev.js +1 -0
  174. package/webpack/config.package.js +26 -5
  175. package/webpack/defaults.js +7 -2
  176. package/webpack/parts/babel-loader-browser-plugins.js +1 -0
  177. package/webpack/parts/dev-server.js +4 -3
  178. package/src/javascripts/domains/app/actions.js +0 -112
  179. package/src/javascripts/domains/app/index.js +0 -7
  180. package/src/javascripts/domains/app/reducer.js +0 -16
  181. package/src/javascripts/domains/app/selectors.js +0 -8
  182. package/src/javascripts/domains/app/utils.js +0 -4
  183. package/src/javascripts/domains/config/actions.js +0 -7
  184. package/src/javascripts/domains/config/hooks.js +0 -23
  185. package/src/javascripts/domains/config/index.js +0 -7
  186. package/src/javascripts/domains/config/reducer.js +0 -79
  187. package/src/javascripts/domains/config/selectors.js +0 -23
  188. package/src/javascripts/domains/config/utils.js +0 -4
  189. package/src/javascripts/domains/forms/actions.js +0 -21
  190. package/src/javascripts/domains/forms/context.js +0 -6
  191. package/src/javascripts/domains/forms/index.js +0 -8
  192. package/src/javascripts/domains/forms/reducer.js +0 -84
  193. package/src/javascripts/domains/forms/utils.js +0 -20
  194. package/src/javascripts/domains/i18n/actions.js +0 -20
  195. package/src/javascripts/domains/i18n/index.js +0 -7
  196. package/src/javascripts/domains/i18n/selectors.js +0 -15
  197. package/src/javascripts/domains/i18n/utils.js +0 -4
  198. package/src/javascripts/domains/interrupt/actions.js +0 -4
  199. package/src/javascripts/domains/interrupt/index.js +0 -9
  200. package/src/javascripts/domains/interrupt/reducer.js +0 -22
  201. package/src/javascripts/domains/interrupt/selectors.js +0 -6
  202. package/src/javascripts/domains/interrupt/utils.js +0 -4
  203. package/src/javascripts/domains/options/index.js +0 -1
  204. package/src/javascripts/domains/redux/context.js +0 -6
  205. package/src/javascripts/domains/redux/create-redux-store.js +0 -21
  206. package/src/javascripts/domains/redux/hooks.js +0 -80
  207. package/src/javascripts/domains/redux/index.js +0 -19
  208. package/src/javascripts/domains/redux/provider.js +0 -5
  209. package/src/javascripts/domains/redux/utils.js +0 -12
  210. package/src/javascripts/domains/store/index.js +0 -46
  211. package/src/javascripts/domains/store/state-reducer.js +0 -56
  212. package/src/javascripts/domains/translations/actions.js +0 -11
  213. package/src/javascripts/domains/translations/index.js +0 -10
  214. package/src/javascripts/domains/translations/reducer.js +0 -69
  215. package/src/javascripts/domains/translations/utils.js +0 -4
  216. package/src/javascripts/domains/visibility/index.js +0 -8
  217. package/src/javascripts/domains/visibility/reducer.js +0 -24
  218. package/src/javascripts/index.js +0 -153
  219. package/src/javascripts/lib/redux-helpers/index.js +0 -99
  220. package/src/javascripts/style-guide.js +0 -5
  221. package/src/javascripts/ui/hooks/use-seamly-dispatch.js +0 -3
  222. package/src/javascripts/ui/utils/seamly-utils.js +0 -832
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @license React
3
+ * react-is.production.min.js
4
+ *
5
+ * Copyright (c) Facebook, Inc. and its affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+
11
+ /**
12
+ * @license React
13
+ * use-sync-external-store-shim.production.min.js
14
+ *
15
+ * Copyright (c) Facebook, Inc. and its affiliates.
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ */
20
+
21
+ /**
22
+ * @license React
23
+ * use-sync-external-store-shim/with-selector.production.min.js
24
+ *
25
+ * Copyright (c) Facebook, Inc. and its affiliates.
26
+ *
27
+ * This source code is licensed under the MIT license found in the
28
+ * LICENSE file in the root directory of this source tree.
29
+ */
30
+
31
+ /** @license React v16.13.1
32
+ * react-is.production.min.js
33
+ *
34
+ * Copyright (c) Facebook, Inc. and its affiliates.
35
+ *
36
+ * This source code is licensed under the MIT license found in the
37
+ * LICENSE file in the root directory of this source tree.
38
+ */
@@ -46,8 +46,7 @@ __webpack_require__.d(__webpack_exports__, {
46
46
  "eventTypes": () => (/* reexport */ web_ui_namespaceObject.eventTypes),
47
47
  "getUrlParams": () => (/* reexport */ web_ui_namespaceObject.getUrlParams),
48
48
  "getUrlSearchString": () => (/* reexport */ web_ui_namespaceObject.getUrlSearchString),
49
- "randomId": () => (/* reexport */ web_ui_namespaceObject.randomId),
50
- "seamlyActions": () => (/* reexport */ web_ui_namespaceObject.seamlyActions)
49
+ "randomId": () => (/* reexport */ web_ui_namespaceObject.randomId)
51
50
  });
52
51
 
53
52
  ;// CONCATENATED MODULE: external "@seamly/web-ui"
@@ -1 +1 @@
1
- (()=>{"use strict";var e={d:(t,r)=>{for(var a in r)e.o(r,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:r[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{Engine:()=>r.Engine,ExternalApi:()=>r.ExternalApi,calculateVisibility:()=>r.calculateVisibility,className:()=>r.className,eventTypes:()=>r.eventTypes,getUrlParams:()=>r.getUrlParams,getUrlSearchString:()=>r.getUrlSearchString,randomId:()=>r.randomId,seamlyActions:()=>r.seamlyActions});const r=require("@seamly/web-ui");module.exports=t})();
1
+ (()=>{"use strict";var e={d:(r,t)=>{for(var a in t)e.o(t,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:t[a]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},r={};e.r(r),e.d(r,{Engine:()=>t.Engine,ExternalApi:()=>t.ExternalApi,calculateVisibility:()=>t.calculateVisibility,className:()=>t.className,eventTypes:()=>t.eventTypes,getUrlParams:()=>t.getUrlParams,getUrlSearchString:()=>t.getUrlSearchString,randomId:()=>t.randomId});const t=require("@seamly/web-ui");module.exports=r})();
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@seamly/web-ui",
3
- "version": "20.7.0",
3
+ "version": "20.8.0-alpha.1",
4
4
  "main": "build/dist/lib/index.js",
5
+ "types": "build/src/javascripts/index.d.ts",
5
6
  "module": "",
6
7
  "exports": {
7
8
  ".": "./build/dist/lib/index.js",
@@ -21,6 +22,7 @@
21
22
  "webpack/*"
22
23
  ],
23
24
  "dependencies": {
25
+ "@reduxjs/toolkit": "^1.8.5",
24
26
  "@ultraq/icu-message-formatter": "^0.12.0",
25
27
  "deep-keys": "^0.5.0",
26
28
  "focus-trap": "^6.7.1",
@@ -28,9 +30,7 @@
28
30
  "js-cookie": "^3.0.1",
29
31
  "minivents": "^2.2.0",
30
32
  "phoenix": "1.6.11",
31
- "redux": "^4.1.1",
32
- "redux-thunk": "^2.3.0",
33
- "reselect": "^4.0.0",
33
+ "react-redux": "^8.0.2",
34
34
  "superagent": "^7.1.2",
35
35
  "xstream": "^11.14.0"
36
36
  },
@@ -42,14 +42,18 @@
42
42
  "@babel/plugin-transform-react-jsx": "^7.14.9",
43
43
  "@babel/plugin-transform-runtime": "^7.15.8",
44
44
  "@babel/preset-env": "^7.15.8",
45
+ "@babel/preset-react": "^7.18.6",
46
+ "@babel/preset-typescript": "^7.18.6",
45
47
  "@babel/runtime-corejs3": "^7.18.3",
46
48
  "@seamly/doc-site": "^1.0",
47
49
  "@seamly/eslint-config": "^2.2.0",
48
50
  "@seamly/prettier-config": "^2.1.0",
49
51
  "@seamly/stylelint-config": "^2.0.0",
50
- "@testing-library/jest-dom": "^5.13.0",
52
+ "@testing-library/jest-dom": "^5.16.5",
51
53
  "@testing-library/preact": "^2.0.1",
52
- "babel-jest": "^27.3.1",
54
+ "@types/jest": "^27.1.7",
55
+ "@typescript-eslint/eslint-plugin": "^5.35.1",
56
+ "@typescript-eslint/parser": "^5.35.1",
53
57
  "babel-loader": "^8.2.2",
54
58
  "copy-webpack-plugin": "^10.2.4",
55
59
  "cypress": "^10.0.3",
@@ -58,22 +62,27 @@
58
62
  "debug": "^4.3.2",
59
63
  "eslint": "^8.17.0",
60
64
  "eslint-import-resolver-alias": "^1.1.2",
65
+ "eslint-import-resolver-typescript": "^3.5.0",
61
66
  "eslint-plugin-cypress": "^2.12.1",
67
+ "eslint-plugin-import": "^2.26.0",
62
68
  "eslint-plugin-jest": "^26.5.3",
63
69
  "file-loader": "^6.2.0",
64
70
  "glob": "^8.0.3",
65
71
  "husky": "^7.0.2",
72
+ "ignore-loader": "^0.1.2",
66
73
  "jest": "^27.5.1",
67
74
  "mini-css-extract-plugin": "^2.4.2",
68
75
  "postcss": "8",
69
- "preact": "10.7.3",
76
+ "preact": "^10.10.6",
70
77
  "prettier": "^2.4.1",
71
78
  "raw-loader": "^4.0.2",
72
79
  "rimraf": "^3.0.2",
73
80
  "sneakpeek-cli": "^0.2.1",
74
81
  "start-server-and-test": "^1.14.0",
75
82
  "style-loader": "^3.3.0",
76
- "stylelint": "^14.9.0",
83
+ "stylelint": "14.9.0",
84
+ "ts-loader": "^9.3.1",
85
+ "typescript": "^4.7.4",
77
86
  "url-loader": "^4.1.1",
78
87
  "webpack": "^5.58.2",
79
88
  "webpack-bundle-analyzer": "^4.5.0",
@@ -82,7 +91,7 @@
82
91
  "webpack-merge": "^5.8.0"
83
92
  },
84
93
  "peerDependencies": {
85
- "preact": "10.7.3"
94
+ "preact": "10.10.6"
86
95
  },
87
96
  "scripts": {
88
97
  "build:clean": "rimraf build; mkdir -p build",
@@ -105,6 +114,7 @@
105
114
  "check:webpack": "prettier --check \"webpack/**/*.{js,scss,html}\"",
106
115
  "check:prettier": "yarn run check:code && yarn run check:tests && yarn run check:public && yarn run check:webpack",
107
116
  "test": "jest",
117
+ "types:generate": "npx openapi-typescript schema.yaml --output src/javascripts/schema.ts",
108
118
  "test:coverage": "yarn run test --coverage",
109
119
  "cypress:open": "cypress open",
110
120
  "cypress:run": "cypress run",
@@ -0,0 +1,7 @@
1
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
2
+ viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
3
+ <path fill="#4A48C1" d="M10.1,14.9c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S11.2,14.9,10.1,14.9z M21.9,10.9c-1.1,0-2,0.9-2,2
4
+ s0.9,2,2,2s2-0.9,2-2S23,10.9,21.9,10.9z M21.4,18.2H10.8C11.8,24,20.3,24,21.4,18.2z M17.2,25.3h-2.4c-0.6,0-1.2,0.4-1.4,1
5
+ c-5.1-0.2-9.2-4.4-9.4-9.6c0.1,0,0.2,0.1,0.4,0.1h0.1c0.8,0,1.4-0.6,1.4-1.4v-4.7c0-0.8-0.6-1.4-1.4-1.4h0c-0.8,0-1.4,0.6-1.4,1.4
6
+ v2.7v2v1.1c0,5.9,4.7,10.6,10.5,10.8c0.2,0.5,0.7,0.8,1.2,0.8h2.4c0.8,0,1.4-0.6,1.4-1.4S18,25.3,17.2,25.3z"/>
7
+ </svg>
@@ -1 +1,6 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="32px" height="32px" x="0px" y="0px" viewBox="0 0 32 32"><defs/><path fill="#003A5D" d="M0,4.717C0,2.112,2.112,0,4.717,0h22.566C29.888,0,32,2.112,32,4.717v22.566C32,29.887,29.888,32,27.283,32 H4.717C2.113,32,0,29.887,0,27.283V4.717z"/><path fill="#FFF" d="M10.103,14.901c-1.107,0-2.004-0.897-2.004-2.004s0.897-2.005,2.004-2.005c1.107,0,2.005,0.897,2.005,2.005 C12.108,14.004,11.211,14.901,10.103,14.901z M16,14.901c1.107,0,2.005-0.897,2.005-2.004S17.108,10.892,16,10.892 c-1.108,0-2.005,0.897-2.005,2.005C13.995,14.004,14.892,14.901,16,14.901z M21.896,10.892c-1.106,0-2.004,0.897-2.004,2.005 c0,1.107,0.896,2.004,2.004,2.004c1.109,0,2.005-0.897,2.005-2.004C23.901,11.789,23.005,10.892,21.896,10.892z M21.408,18.207 H10.783C11.83,23.973,20.361,23.973,21.408,18.207z"/></svg>
1
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
2
+ viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
3
+ <path fill="#4A48C1" d="M10,14.8c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S11.1,14.8,10,14.8z M15.9,14.8c1.1,0,2-0.9,2-2s-0.9-2-2-2
4
+ s-2,0.9-2,2S14.8,14.8,15.9,14.8z M21.8,10.8c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S22.9,10.8,21.8,10.8z M21.3,18.1H10.7
5
+ C11.7,23.9,20.2,23.9,21.3,18.1z"/>
6
+ </svg>
@@ -88,7 +88,7 @@ export class API {
88
88
  */
89
89
  constructor({ layoutMode, namespace, config = {}, context = {} }) {
90
90
  this.store = objectStore(
91
- `${namespace}.connection${context.locale ? '.' + context.locale : ''}`,
91
+ `${namespace}.connection${context.locale ? `.${context.locale}` : ''}`,
92
92
  config.storageProvider || sessionStorageProvider,
93
93
  )
94
94
 
@@ -1,3 +1,5 @@
1
+ import type { Config } from 'config.types'
2
+
1
3
  export const CSS_NAME = 'cvco'
2
4
 
3
5
  export const apiVersion = '2'
@@ -23,7 +25,7 @@ export const defaultTransitionTimeMs = 300
23
25
  // How long to wait before we decide the user isn't typing
24
26
  export const typingTimeout = 2000
25
27
 
26
- export const defaultConfig = {
28
+ export const defaultConfig: Partial<Config> = {
27
29
  namespace: 'default',
28
30
  layoutMode: 'window', // "window", "inline" ("sidebar")
29
31
  messages: {
@@ -0,0 +1,95 @@
1
+ import type { ChannelEvent } from 'domains/store/store.types'
2
+ import { FunctionComponent } from 'preact'
3
+
4
+ export type ApiConfig = {
5
+ key: string
6
+ domain: string
7
+ secure: boolean
8
+ sendEnvironment?: boolean
9
+ storageProvider?: unknown
10
+ externalId?: string
11
+ }
12
+
13
+ export type LayoutMode = 'inline' | 'window' | 'app' | null
14
+
15
+ export type VisibilityOptions = 'open' | 'minimized' | 'hidden' | null
16
+
17
+ export type ErrorCallbackMeta = {
18
+ namespace: string
19
+ api: ApiConfig
20
+ layoutMode: LayoutMode
21
+ conversationUrl: string
22
+ }
23
+ export type ErrorCallback = (error: Error, meta: ErrorCallbackMeta) => void
24
+
25
+ export type Message = {
26
+ showName?: boolean
27
+ showAvatar?: boolean
28
+ }
29
+
30
+ export type Messages = {
31
+ agent?: Message
32
+ user?: Message
33
+ timeIndicator?: {
34
+ enabled: boolean
35
+ threshold: number
36
+ }
37
+ custom?: Record<string, unknown>
38
+ }
39
+
40
+ export type Context = {
41
+ channelName?: string
42
+ locale?: string
43
+ topic?: string
44
+ translationLocale?: string
45
+ variables?: Record<string, unknown>
46
+ }
47
+
48
+ export type AgentParticipant = {
49
+ name: string
50
+ avatar: string
51
+ }
52
+ export type UserParticipant = {
53
+ avatar: string
54
+ }
55
+
56
+ export type VisibilityCallbackOptions = {
57
+ hasConversation: boolean
58
+ hasResponded: boolean
59
+ previousVisibility: VisibilityOptions
60
+ requestedVisibility: VisibilityOptions
61
+ config: Config
62
+ }
63
+
64
+ export type VisibilityCallback = (
65
+ options: VisibilityCallbackOptions,
66
+ ) => VisibilityOptions
67
+
68
+ export type Config = {
69
+ parentElement?: HTMLElement
70
+ namespace?: string
71
+ customComponents?: {
72
+ view?: FunctionComponent
73
+ message?: Messages
74
+ }
75
+ showDisclaimer?: boolean
76
+ hideOnNoUserResponse?: boolean
77
+ layoutMode?: LayoutMode
78
+ connectWhenInView?: boolean
79
+ visibilityCallback?: VisibilityCallback
80
+ errorCallback?: ErrorCallback
81
+ api: ApiConfig
82
+ appContainerClassNames?: string[] | ((config: Config) => string[])
83
+ zIndex?: number
84
+ showFaq?: boolean
85
+ context?: Context
86
+ messages?: Messages
87
+ defaults?: {
88
+ visible: VisibilityOptions
89
+ }
90
+ preChatEvents?: ChannelEvent[]
91
+ agentParticipant?: AgentParticipant
92
+ userParticipant?: UserParticipant
93
+ startChatIcon?: string
94
+ visible?: VisibilityOptions
95
+ }
@@ -0,0 +1,83 @@
1
+ import { createAsyncThunk } from '@reduxjs/toolkit'
2
+ import SeamlySessionExpiredError from 'api/errors/seamly-session-expired-error'
3
+ import SeamlyUnavailableError from 'api/errors/seamly-unavailable-error'
4
+ import { Config } from 'config.types'
5
+ import { initializeConfig, resetConfig } from 'domains/config/actions'
6
+ import { ThunkAPI } from 'domains/redux/redux.types'
7
+ import type { RootState } from 'domains/store'
8
+ import { initializeVisibility } from 'domains/visibility/actions'
9
+ import { actionTypes } from 'ui/utils/seamly-utils'
10
+
11
+ export const initializeApp = createAsyncThunk<
12
+ {
13
+ initialState: RootState['state']['initialState']
14
+ locale: string
15
+ config: Config
16
+ },
17
+ void,
18
+ ThunkAPI
19
+ >('initializeApp', async (_, { extra: { api, config }, rejectWithValue }) => {
20
+ let locale = config?.context?.locale
21
+ try {
22
+ if (api.hasConversation()) {
23
+ const initialState = await api.getConversationIntitialState()
24
+
25
+ locale = initialState.translation?.locale || locale
26
+
27
+ return { initialState, locale, config }
28
+ } else {
29
+ if (config?.context?.topic) {
30
+ api.send('action', {
31
+ type: actionTypes.setTopic,
32
+ body: {
33
+ name: config.context.topic,
34
+ // Separate fallback message is not needed here. Only an attached service will use this, but none will
35
+ // be attached before the conversation has started (meaning the fallback message will never be shown).
36
+ fallbackMessage: config.context.topic,
37
+ },
38
+ })
39
+ }
40
+ if (config?.context?.translationLocale) {
41
+ locale = config.context.translationLocale
42
+ api.send('action', {
43
+ type: actionTypes.setTranslation,
44
+ body: { enabled: true, locale },
45
+ })
46
+ }
47
+
48
+ return { initialState: undefined, locale, config }
49
+ }
50
+ } catch (e) {
51
+ if (e instanceof SeamlySessionExpiredError) {
52
+ const err = new SeamlySessionExpiredError()
53
+
54
+ return rejectWithValue({
55
+ name: err.name,
56
+ message: err.message,
57
+ originalEvent: err.originalEvent,
58
+ originalError: err.originalError,
59
+ action: err.action,
60
+ })
61
+ }
62
+
63
+ const err = new SeamlyUnavailableError()
64
+ return rejectWithValue({
65
+ name: err.name,
66
+ message: err.message,
67
+ langKey: err.langKey,
68
+ })
69
+ }
70
+ })
71
+
72
+ export const resetApp = createAsyncThunk<unknown, void, ThunkAPI>(
73
+ 'resetApp',
74
+ async (_, { dispatch, extra: { api } }) => {
75
+ await api.disconnect()
76
+ await api.clearStore()
77
+
78
+ dispatch(resetConfig())
79
+ await dispatch(initializeConfig())
80
+ await dispatch(initializeApp())
81
+ dispatch(initializeVisibility())
82
+ },
83
+ )
@@ -0,0 +1,3 @@
1
+ export interface AppState {
2
+ userHasResponded: boolean
3
+ }
@@ -1,6 +1,4 @@
1
- import { useSelector } from 'domains/redux'
2
- import * as Selectors from './selectors'
1
+ import { selectUserHasResponded } from 'domains/app/selectors'
2
+ import { useSelector } from 'react-redux'
3
3
 
4
- export function useUserHasResponded() {
5
- return useSelector(Selectors.selectUserHasResponded)
6
- }
4
+ export const useUserHasResponded = () => useSelector(selectUserHasResponded)
@@ -0,0 +1,6 @@
1
+ import { createSelector } from '@reduxjs/toolkit'
2
+
3
+ export const selectUserHasResponded = createSelector(
4
+ ({ app }) => app,
5
+ ({ userHasResponded }) => userHasResponded,
6
+ )
@@ -0,0 +1,30 @@
1
+ import { createSlice } from '@reduxjs/toolkit'
2
+ import { initializeApp, resetApp } from 'domains/app/actions'
3
+ import { AppState } from 'domains/app/app.types'
4
+
5
+ const initialState: AppState = {
6
+ userHasResponded: false,
7
+ }
8
+
9
+ export const appSlice = createSlice({
10
+ name: 'app',
11
+ initialState,
12
+ reducers: {
13
+ setHasResponded: (state, { payload }) => {
14
+ state.userHasResponded = payload
15
+ },
16
+ },
17
+ extraReducers: (builder) => {
18
+ builder
19
+ .addCase(resetApp.pending, () => initialState)
20
+ .addCase(initializeApp.fulfilled, (state, { payload }) => {
21
+ if (payload.initialState && 'userResponded' in payload.initialState) {
22
+ state.userHasResponded = payload.initialState?.userResponded
23
+ }
24
+ })
25
+ },
26
+ })
27
+
28
+ export const { setHasResponded } = appSlice.actions
29
+
30
+ export default appSlice.reducer
@@ -0,0 +1,45 @@
1
+ import { createAsyncThunk } from '@reduxjs/toolkit'
2
+ import SeamlyUnavailableError from 'api/errors/seamly-unavailable-error'
3
+ import { ThunkAPI } from 'domains/redux/redux.types'
4
+
5
+ export const initializeConfig = createAsyncThunk<any, void, ThunkAPI>(
6
+ 'initializeConfig',
7
+ async (_, { extra: { api, config }, rejectWithValue }) => {
8
+ try {
9
+ const {
10
+ features,
11
+ defaultLocale,
12
+ preChat,
13
+ agentParticipant,
14
+ userParticipant,
15
+ startChatIcon,
16
+ } = await api.getConfig()
17
+
18
+ const locale = config?.context?.locale || defaultLocale
19
+
20
+ return {
21
+ features,
22
+ defaultLocale,
23
+ preChat,
24
+ agentParticipant,
25
+ userParticipant,
26
+ startChatIcon,
27
+ locale,
28
+ }
29
+ } catch (e) {
30
+ const err = new SeamlyUnavailableError()
31
+ return rejectWithValue({
32
+ name: err.name,
33
+ langKey: err.langKey,
34
+ message: err.message,
35
+ })
36
+ }
37
+ },
38
+ )
39
+
40
+ export const resetConfig = createAsyncThunk<unknown, void, ThunkAPI>(
41
+ 'resetConfig',
42
+ async (_, { extra: { config } }) => {
43
+ return config
44
+ },
45
+ )
@@ -0,0 +1,19 @@
1
+ import { selectConfig } from 'domains/config/selectors'
2
+ import { useSelector } from 'react-redux'
3
+
4
+ export const useConfig = () => useSelector(selectConfig)
5
+
6
+ export function useParticipants() {
7
+ const { agentParticipant, userParticipant } = useConfig()
8
+
9
+ return {
10
+ agent: agentParticipant,
11
+ user: userParticipant,
12
+ }
13
+ }
14
+
15
+ export function useStartChatIcon() {
16
+ const { startChatIcon } = useConfig()
17
+
18
+ return startChatIcon
19
+ }
@@ -0,0 +1,24 @@
1
+ import { createSelector } from '@reduxjs/toolkit'
2
+ import { Config } from 'config.types'
3
+ import { visibilityStates } from 'domains/visibility/constants'
4
+
5
+ export const selectConfig = createSelector(
6
+ ({ config }): Config => config,
7
+ (config) => {
8
+ let newConfig = {
9
+ visible:
10
+ config?.layoutMode === 'inline'
11
+ ? visibilityStates.open
12
+ : visibilityStates.minimized,
13
+ appContainerClassNames: config.appContainerClassNames || [],
14
+ ...config,
15
+ }
16
+ if (typeof newConfig.appContainerClassNames === 'function') {
17
+ newConfig = {
18
+ ...newConfig,
19
+ appContainerClassNames: newConfig.appContainerClassNames(newConfig),
20
+ }
21
+ }
22
+ return newConfig
23
+ },
24
+ )
@@ -0,0 +1,111 @@
1
+ import { createSlice, PayloadAction } from '@reduxjs/toolkit'
2
+ import { defaultConfig } from 'config'
3
+ import { Config } from 'config.types'
4
+ import { initializeConfig, resetConfig } from 'domains/config/actions'
5
+ import { pick } from 'ui/utils/general-utils'
6
+
7
+ export const initialConfigState: Config = {
8
+ ...defaultConfig,
9
+ api: {
10
+ domain: '',
11
+ key: '',
12
+ secure: true,
13
+ },
14
+ hideOnNoUserResponse: false,
15
+ connectWhenInView: true,
16
+ showDisclaimer: false,
17
+ showFaq: false,
18
+ customComponents: {},
19
+ defaults: {
20
+ visible: null,
21
+ },
22
+ preChatEvents: [],
23
+ }
24
+
25
+ const configKeys: (keyof Config)[] = [
26
+ 'hideOnNoUserResponse',
27
+ 'connectWhenInView',
28
+ 'showDisclaimer',
29
+ 'showFaq',
30
+ 'namespace',
31
+ 'customComponents',
32
+ 'defaults',
33
+ 'layoutMode',
34
+ 'api',
35
+ 'zIndex',
36
+ 'context',
37
+ 'appContainerClassNames',
38
+ 'messages',
39
+ 'visible',
40
+ 'visibilityCallback',
41
+ 'errorCallback',
42
+ 'agentParticipant',
43
+ 'userParticipant',
44
+ 'startChatIcon',
45
+ ]
46
+
47
+ const updateState = (state, config: Config): Config => {
48
+ const { messages, ...partialConfig } = pick(config, configKeys)
49
+ let newState = state
50
+ if (Object.keys(partialConfig).length > 0) {
51
+ newState = {
52
+ ...newState,
53
+ ...partialConfig,
54
+ }
55
+ }
56
+ if (messages) {
57
+ newState = {
58
+ ...newState,
59
+ messages: {
60
+ ...newState.messages,
61
+ ...messages,
62
+ },
63
+ }
64
+ }
65
+ return newState
66
+ }
67
+
68
+ export const configSlice = createSlice({
69
+ name: 'config',
70
+ initialState: initialConfigState,
71
+ reducers: {
72
+ setConfig: (state, { payload }: PayloadAction<Config>) =>
73
+ updateState(state, payload),
74
+ updateConfig: (state, { payload }: PayloadAction<Config>) =>
75
+ updateState(state, payload),
76
+ setPreChatEvents: (state, { payload: { events } }) => {
77
+ state.preChatEvents = events
78
+ },
79
+ },
80
+ extraReducers: (builder) => {
81
+ builder
82
+ .addCase(resetConfig.fulfilled, (config) => config)
83
+ .addCase(
84
+ initializeConfig.fulfilled,
85
+ (
86
+ state,
87
+ {
88
+ payload: {
89
+ preChat,
90
+ agentParticipant,
91
+ userParticipant,
92
+ startChatIcon,
93
+ },
94
+ },
95
+ ) => {
96
+ state.preChatEvents = preChat.map((payload) => ({
97
+ type: 'message',
98
+ payload,
99
+ }))
100
+
101
+ state.agentParticipant = agentParticipant
102
+ state.userParticipant = userParticipant
103
+ state.startChatIcon = startChatIcon
104
+ },
105
+ )
106
+ },
107
+ })
108
+
109
+ export const { setConfig, updateConfig, setPreChatEvents } = configSlice.actions
110
+
111
+ export default configSlice.reducer
@@ -1,15 +1,15 @@
1
- import { createDomain } from 'lib/redux-helpers'
2
- import { Selectors as ConfigSelectors } from 'domains/config'
3
-
4
- const { createAction } = createDomain('errors')
1
+ import { createAction } from '@reduxjs/toolkit'
2
+ import { selectConfig } from 'domains/config/selectors'
5
3
 
6
4
  export const catchError = createAction('catch-error', (error) => ({ error }))
7
5
 
8
- export function createMiddleware({ api: seamlyApi }) {
6
+ export function createErrorsMiddleware({ api: seamlyApi }) {
9
7
  return ({ getState }) => {
10
8
  const handleError = (action) => {
11
- const { errorCallback, namespace, api, layoutMode } =
12
- ConfigSelectors.selectConfig(getState())
9
+ const { errorCallback, namespace, api, layoutMode } = selectConfig(
10
+ getState(),
11
+ )
12
+
13
13
  errorCallback?.(action.error, {
14
14
  namespace,
15
15
  api,
@@ -18,10 +18,14 @@ export function createMiddleware({ api: seamlyApi }) {
18
18
  action: action.type ? action : undefined,
19
19
  })
20
20
  }
21
+
21
22
  return (next) => (action) => {
22
23
  try {
23
- if (action.error) {
24
- handleError(action)
24
+ if (action.payload?.originalEvent?.payload) {
25
+ handleError({
26
+ error: action.payload,
27
+ type: action.payload?.originalEvent?.payload?.type,
28
+ })
25
29
  }
26
30
  return next(action)
27
31
  } catch (error) {