@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,4 +1,10 @@
1
- import { visibilityStates, randomId } from '@seamly/web-ui'
1
+ import {
2
+ visibilityStates,
3
+ randomId,
4
+ SeamlyOfflineError,
5
+ SeamlyGeneralError,
6
+ SeamlyConfigurationError,
7
+ } from '@seamly/web-ui'
2
8
  import { addTranslationData } from './state-helpers'
3
9
 
4
10
  const baseState = {
@@ -8,6 +14,7 @@ const baseState = {
8
14
  accountConfig: {},
9
15
  hideOnNoUserResponse: false,
10
16
  showFaq: false,
17
+ showDisclaimer: false,
11
18
  },
12
19
  initialState: {},
13
20
  unreadEvents: 0,
@@ -27,14 +34,12 @@ const baseState = {
27
34
  subTitle: 'Test subtitle',
28
35
  },
29
36
  interrupt: {
30
- hasInterrupt: false,
31
- meta: {},
37
+ error: undefined,
32
38
  },
33
39
  historyLoaded: false,
34
40
  skiplinkTargetId: randomId(),
35
41
  optionsButtonId: randomId(),
36
42
  cobrowseContainerId: randomId(),
37
- showDisclaimer: false,
38
43
  serviceData: {},
39
44
  options: {
40
45
  features: {},
@@ -117,8 +122,7 @@ const newTranslationDividerStart = {
117
122
  body: {
118
123
  language: 'Nederlands',
119
124
  subtype: 'new_translation',
120
- text:
121
- '[NL] Automatic translation to Dutch started. Please note that automatic translations may contain errors.',
125
+ text: '[NL] Automatic translation to Dutch started. Please note that automatic translations may contain errors.',
122
126
  translationEnabled: true,
123
127
  translationLocale: 'nl',
124
128
  },
@@ -329,8 +333,7 @@ const longTextMessage = {
329
333
  type: 'message',
330
334
  payload: {
331
335
  body: {
332
- text:
333
- 'What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am.',
336
+ text: 'What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am.',
334
337
  type: 'text',
335
338
  variables: {},
336
339
  },
@@ -422,8 +425,7 @@ const textMessageWithLongLink = {
422
425
  variables: {
423
426
  link_1: {
424
427
  id: '1',
425
- name:
426
- 'click me click me please click me yoohoooo please please click me here I am click me now what are you waiting for click me now now now now now click meeeeeeeeeeeeee',
428
+ name: 'click me click me please click me yoohoooo please please click me here I am click me now what are you waiting for click me now now now now now click meeeeeeeeeeeeee',
427
429
  newTab: false,
428
430
  type: 'link',
429
431
  url: 'https://google.com',
@@ -450,8 +452,7 @@ const textMesageWithBullets = {
450
452
  type: 'message',
451
453
  payload: {
452
454
  body: {
453
- text:
454
- '<ul>\n<li>Bullets</li>\n<li>bullets</li>\n<li>bullets</li>\n</ul>\n',
455
+ text: '<ul>\n<li>Bullets</li>\n<li>bullets</li>\n<li>bullets</li>\n</ul>\n',
455
456
  type: 'text',
456
457
  variables: {},
457
458
  },
@@ -478,7 +479,7 @@ const imageMessage = {
478
479
  description: 'Plaatje',
479
480
  isZoomable: false,
480
481
  type: 'image',
481
- url: 'https://via.placeholder.com/150',
482
+ url: 'https://developers.seamly.ai/clients/web-ui/static/photos/image-square-small.jpg',
482
483
  },
483
484
  fromClient: false,
484
485
  fromHistory: true,
@@ -503,7 +504,7 @@ const imageMessageWithLightbox = {
503
504
  description: 'Plaatje',
504
505
  isZoomable: true,
505
506
  type: 'image',
506
- url: 'https://via.placeholder.com/150',
507
+ url: 'https://developers.seamly.ai/clients/web-ui/static/photos/image-portrait.jpg',
507
508
  },
508
509
  fromClient: false,
509
510
  fromHistory: true,
@@ -553,8 +554,7 @@ const choicePromptMessage = {
553
554
  choices: [
554
555
  {
555
556
  id: '703db9b3-2157-4d4a-9f9b-c382c6a10531',
556
- text:
557
- 'Dialog (this is intentionally made longer for testing purposes)',
557
+ text: 'Dialog (this is intentionally made longer for testing purposes)',
558
558
  type: 'choice',
559
559
  },
560
560
  {
@@ -631,8 +631,7 @@ const userMessageLong = {
631
631
  type: 'message',
632
632
  payload: {
633
633
  body: {
634
- text:
635
- 'This is what the user typed. And sometimes the user has quite a lot to say and then we get longer lines that need to wrap well and not break the styling so here goes with just such a line right here!!',
634
+ text: 'This is what the user typed. And sometimes the user has quite a lot to say and then we get longer lines that need to wrap well and not break the styling so here goes with just such a line right here!!',
636
635
  type: 'text',
637
636
  variables: {},
638
637
  },
@@ -653,10 +652,9 @@ const fileDownloadPayload = {
653
652
  meta: {},
654
653
  body: {
655
654
  contentType: 'image/jpg',
656
- deleteAt: 1000 * (Date.now() + 3600000),
657
655
  filename: 'placeholder.jpg',
658
656
  filesize: 991078,
659
- url: 'https://via.placeholder.com/150',
657
+ url: 'https://developers.seamly.ai/clients/web-ui/static/photos/image-square-small.jpg',
660
658
  },
661
659
  }
662
660
 
@@ -676,7 +674,6 @@ const deletedFileDownloadAgentMessage = {
676
674
  ...fileDownloadAgentMessage.payload,
677
675
  body: {
678
676
  ...fileDownloadAgentMessage.payload.body,
679
- deleteAt: 1000 * (Date.now() - 3600000),
680
677
  },
681
678
  id: randomId(),
682
679
  },
@@ -692,18 +689,6 @@ const fileDownloadUserMessage = {
692
689
  },
693
690
  }
694
691
 
695
- const deletedFileDownloadUserMessage = {
696
- ...fileDownloadUserMessage,
697
- payload: {
698
- id: randomId(),
699
- ...fileDownloadUserMessage.payload,
700
- body: {
701
- ...fileDownloadUserMessage.payload.body,
702
- deleteAt: 1000 * (Date.now() - 3600000),
703
- },
704
- },
705
- }
706
-
707
692
  const emptyUrlFileDownloadUserMessage = {
708
693
  ...fileDownloadUserMessage,
709
694
  payload: {
@@ -811,7 +796,7 @@ const cardAskText = {
811
796
  description:
812
797
  'Pizza Margherita is a **typical Neapolitan pizza**.\n\nIt is made with San Marzano tomatoes, mozzarella cheese, fresh basil, salt, and extra-virgin olive oil.',
813
798
  image:
814
- 'https://via.placeholder.com/400x200/dee3e5/6a7f8c?text=Margherita',
799
+ 'https://developers.seamly.ai/clients/web-ui/static/photos/card-square.jpg',
815
800
  title: 'Pizza Margherita',
816
801
  },
817
802
  },
@@ -830,7 +815,7 @@ const cardNavigate = {
830
815
  buttonText: 'Order now!',
831
816
  description: 'Pizza Margherita is a **typical Neapolitan pizza**.',
832
817
  image:
833
- 'https://via.placeholder.com/400x200/dee3e5/6a7f8c?text=Margherita',
818
+ 'https://developers.seamly.ai/clients/web-ui/static/photos/card-landscape.jpg',
834
819
  title: 'Pizza Margherita',
835
820
  },
836
821
  },
@@ -847,7 +832,7 @@ const cardTopic = {
847
832
  },
848
833
  buttonText: 'Set topic! (title & description optional)',
849
834
  image:
850
- 'https://via.placeholder.com/400x200/dee3e5/6a7f8c?text=Margherita',
835
+ 'https://developers.seamly.ai/clients/web-ui/static/photos/card-portrait.jpg',
851
836
  },
852
837
  },
853
838
  }
@@ -893,7 +878,6 @@ const standardState = {
893
878
  textMessageWithLongLink,
894
879
  imageMessageWithLightbox,
895
880
  fileDownloadUserMessage,
896
- deletedFileDownloadUserMessage,
897
881
  emptyUrlFileDownloadUserMessage,
898
882
  textMesageWithBullets,
899
883
  choicePromptMessage,
@@ -910,7 +894,6 @@ const standardState = {
910
894
  userMessage,
911
895
  userMessageLong,
912
896
  fileDownloadUserMessage,
913
- deletedFileDownloadUserMessage,
914
897
  emptyUrlFileDownloadUserMessage,
915
898
  ],
916
899
  },
@@ -1116,8 +1099,7 @@ const standardState = {
1116
1099
  occurredAt: Date.now() * 1000,
1117
1100
  id: randomId(),
1118
1101
  body: {
1119
- text:
1120
- 'Above me should be a time indicator showing me the dialog continues today',
1102
+ text: 'Above me should be a time indicator showing me the dialog continues today',
1121
1103
  type: 'text',
1122
1104
  variables: {},
1123
1105
  },
@@ -1167,14 +1149,7 @@ const standardState = {
1167
1149
  description: '',
1168
1150
  ...baseState,
1169
1151
  interrupt: {
1170
- hasInterrupt: true,
1171
- meta: {
1172
- title: 'Connection issues',
1173
- message:
1174
- 'There might be a problem with your or our network connection. The chat session should resume as soon the connection is available again.',
1175
- srText:
1176
- 'The chat has connection issues. There might be a problem with your or our network connection. The chat session should resume as soon as the connection is available again.',
1177
- },
1152
+ error: new SeamlyOfflineError(),
1178
1153
  },
1179
1154
  },
1180
1155
  generalErrorInterrupt: {
@@ -1184,15 +1159,7 @@ const standardState = {
1184
1159
  description: '',
1185
1160
  ...baseState,
1186
1161
  interrupt: {
1187
- hasInterrupt: true,
1188
- meta: {
1189
- title: 'Something went wrong',
1190
- message: 'Do you want to start a new chat session?',
1191
- buttonText: 'Restart chat',
1192
- action: 'reset',
1193
- srText:
1194
- 'Something went wrong with the chat session. You can restart the chat.',
1195
- },
1162
+ error: new SeamlyGeneralError(),
1196
1163
  },
1197
1164
  },
1198
1165
  configErrorInterrupt: {
@@ -1202,13 +1169,7 @@ const standardState = {
1202
1169
  description: '',
1203
1170
  ...baseState,
1204
1171
  interrupt: {
1205
- hasInterrupt: true,
1206
- meta: {
1207
- title: 'Chat configuration error.',
1208
- message: 'We are sorry this happened, please retry at a later time.',
1209
- srText:
1210
- 'A chat configuration error occurred. Our apologies, please retry at a later time.',
1211
- },
1172
+ error: new SeamlyConfigurationError(),
1212
1173
  },
1213
1174
  },
1214
1175
  privacyDisclaimer: {
@@ -1220,11 +1181,10 @@ const standardState = {
1220
1181
  ...baseState.config,
1221
1182
  showDisclaimer: true,
1222
1183
  },
1223
- showDisclaimer: true,
1224
1184
  },
1225
- cobrowserBar: {
1185
+ chatStatusBar: {
1226
1186
  category: categoryKeys.features,
1227
- headingText: `Cobrowse bar`,
1187
+ headingText: `Chat status bar`,
1228
1188
  description: '',
1229
1189
  ...baseState,
1230
1190
  options: {
@@ -1758,7 +1718,6 @@ const standardState = {
1758
1718
  textMessageWithLongLink,
1759
1719
  imageMessageWithLightbox,
1760
1720
  fileDownloadUserMessage,
1761
- deletedFileDownloadUserMessage,
1762
1721
  emptyUrlFileDownloadUserMessage,
1763
1722
  textMesageWithBullets,
1764
1723
  choicePromptMessage,
@@ -1796,9 +1755,8 @@ const buildStandardState = (layoutModes, customComponentEventBodies = []) => {
1796
1755
  }, {}),
1797
1756
  }
1798
1757
  return Object.keys(intermediateState).reduce((acc, key) => {
1799
- const { headingText, category, description, ...rest } = intermediateState[
1800
- key
1801
- ]
1758
+ const { headingText, category, description, ...rest } =
1759
+ intermediateState[key]
1802
1760
  return {
1803
1761
  ...acc,
1804
1762
  [key]: {
@@ -1,6 +1,5 @@
1
1
  import { render } from 'preact'
2
- import { Engine } from '@seamly/web-ui'
3
- import en from '@seamly/web-ui/translations/en'
2
+ import { API, Engine } from '@seamly/web-ui'
4
3
  import StyleGuideApp from './components/app'
5
4
 
6
5
  class SeamlyStyleGuideInstance extends Engine {
@@ -9,31 +8,33 @@ class SeamlyStyleGuideInstance extends Engine {
9
8
  this.styleGuideConfig = styleGuideConfig || {}
10
9
  }
11
10
 
12
- render() {
11
+ async render() {
13
12
  const restComponents = {
14
- ...(this.customComponents || {}),
13
+ ...(this.config.customComponents || {}),
15
14
  view: undefined,
16
15
  }
17
16
 
17
+ const api = new API({
18
+ namespace: this.config.namespace,
19
+ config: this.config.api,
20
+ })
21
+ api.URLS = {
22
+ translations: '/client/wilson/translations/{version}/{locale}.json',
23
+ }
24
+ const translations = await api.getTranslations('en-GB')
25
+
18
26
  const renderConfig = {
19
27
  ...this.config,
20
28
  customComponents: Object.keys(restComponents).length
21
29
  ? restComponents
22
30
  : undefined,
23
- translations: this.config.translations || {
24
- ...en,
25
- disclaimer: {
26
- ...en.disclaimer,
27
- content:
28
- 'This chat session will be saved to help us improve our service delivery. <a href="https://seamly.ai/">More information</a>',
29
- },
30
- },
31
31
  }
32
32
 
33
33
  render(
34
34
  <StyleGuideApp
35
35
  config={renderConfig}
36
36
  styleGuideConfig={this.styleGuideConfig}
37
+ translations={translations}
37
38
  />,
38
39
  this.parentElement,
39
40
  )
@@ -1,9 +1,9 @@
1
1
  import View from './layout/view'
2
2
  import SeamlyCore from './core/seamly-core'
3
3
 
4
- const ChatApp = ({ config, eventBus }) => {
4
+ const ChatApp = (props) => {
5
5
  return (
6
- <SeamlyCore config={config} eventBus={eventBus}>
6
+ <SeamlyCore {...props}>
7
7
  <View />
8
8
  </SeamlyCore>
9
9
  )
@@ -1,5 +1,5 @@
1
1
  import { useMemo } from 'preact/hooks'
2
- import { useSeamlyConfig } from '../../hooks/seamly-hooks'
2
+ import { useConfig } from '../../../domains/config'
3
3
  import ComponentContext from './component-context'
4
4
  import ChoicePrompt from './event/choice-prompt'
5
5
  import Text from './event/text'
@@ -37,7 +37,7 @@ const eventTypeMapping = {
37
37
  }
38
38
 
39
39
  const ComponentFilter = ({ children }) => {
40
- const { customComponents } = useSeamlyConfig()
40
+ const { customComponents } = useConfig()
41
41
 
42
42
  const resolvedComponents = useMemo(() => {
43
43
  // Calculates a combined component mapping object based on the defaults with
@@ -33,7 +33,7 @@ const Conversation = () => {
33
33
 
34
34
  const renderEvents = () => {
35
35
  let prevParticipant = null
36
- return events.map(event => {
36
+ return events.map((event) => {
37
37
  const { type, payload } = event
38
38
  const { participant, fromClient } = payload
39
39
  let participantChanged = false
@@ -56,7 +56,7 @@ const Conversation = () => {
56
56
  })
57
57
  }
58
58
 
59
- const onClickHandler = e => {
59
+ const onClickHandler = (e) => {
60
60
  e.preventDefault()
61
61
  focusSkiplinkTarget()
62
62
  }
@@ -1,4 +1,4 @@
1
- import { useCallback, useMemo } from 'preact/hooks'
1
+ import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
2
2
  import { className } from '../../../../lib/css'
3
3
  import parseBody from '../../../../lib/parse-body'
4
4
  import { useGeneratedId, useSeamlyCommands } from '../../../hooks/seamly-hooks'
@@ -9,11 +9,15 @@ const CardComponent = ({
9
9
  action,
10
10
  buttonText,
11
11
  description,
12
+ hasFocus,
12
13
  image,
13
14
  title,
15
+ isCarouselItem,
14
16
  }) => {
17
+ const cardRef = useRef(null)
15
18
  const { sendMessage, sendAction, emitEvent } = useSeamlyCommands()
16
19
  const descriptionId = useGeneratedId()
20
+ const isMounted = useRef()
17
21
 
18
22
  const CardActionComponent =
19
23
  action.type === cardTypes.navigate ? 'a' : 'button'
@@ -53,18 +57,35 @@ const CardComponent = ({
53
57
  [action, handleClick, emitCardEvent],
54
58
  )
55
59
 
60
+ useEffect(() => {
61
+ if (isCarouselItem) {
62
+ if (hasFocus && isMounted.current) {
63
+ window.requestAnimationFrame(() => cardRef.current.focus())
64
+ } else {
65
+ cardRef.current.blur()
66
+ }
67
+ }
68
+ isMounted.current = true
69
+ }, [hasFocus, isCarouselItem])
70
+
56
71
  return (
57
- <div className={className('card__wrapper')} id={id}>
72
+ <div
73
+ className={className('card__wrapper')}
74
+ id={id}
75
+ tabIndex="-1" // set tabIndex of -1 so card can be focussed
76
+ ref={cardRef}
77
+ >
58
78
  <img className={className('card__image')} src={image} alt="" />
59
79
  <div className={className('card__content')} id={id}>
60
80
  {title && <h2 className={className('card__title')}>{title}</h2>}
61
81
  {description && (
62
- <p
82
+ <div
63
83
  className={className('card__description')}
64
84
  dangerouslySetInnerHTML={{ __html: parseBody(description) }}
65
85
  />
66
86
  )}
67
87
  <CardActionComponent
88
+ tabIndex={isCarouselItem && !hasFocus ? '-1' : undefined} // disable to prevent tabbing through cards
68
89
  className={className('button', 'button--primary')}
69
90
  aria-describedby={descriptionId}
70
91
  {...actionProps}
@@ -10,7 +10,7 @@ export default function CarouselPagination({
10
10
  }) {
11
11
  const itemCount = items.length
12
12
  const handlePaginate = useCallback(
13
- event => {
13
+ (event) => {
14
14
  const slideIndex = Number(event.target.dataset.item || '0')
15
15
  const nextIndex = Math.min(itemCount - 1, Math.max(0, slideIndex))
16
16
  if (nextIndex !== currentIndex) {
@@ -27,7 +27,7 @@ export default function CarouselPagination({
27
27
  const isActive = currentIndex === idx
28
28
  return (
29
29
  <li
30
- key={getItemKey(item, idx)}
30
+ key={getItemKey(item, idx, 'pagination-item-')}
31
31
  className={className(
32
32
  'carousel-pagination__item',
33
33
  isActive ? 'is-active' : undefined,
@@ -6,8 +6,8 @@ import CarouselPagination from './components/pagination'
6
6
  import CarouselControls from './components/controls'
7
7
  import CarouselMessageSlide from '../carousel-message/components/slide'
8
8
 
9
- const defaultGetItemKey = (item, idx) => idx
10
- const defaultGetItemLabel = item => item.label
9
+ const defaultGetItemKey = (item, idx, prefix) => `${prefix}${idx}`
10
+ const defaultGetItemLabel = (item) => item.label
11
11
 
12
12
  export default function CarouselComponent({
13
13
  currentIndex: originalIndex,
@@ -66,7 +66,7 @@ export default function CarouselComponent({
66
66
  const isActive = currentIndex === idx
67
67
  return (
68
68
  <div
69
- key={idx}
69
+ key={getItemKey(item, idx, 'item-')}
70
70
  ref={slideRefs.current[idx]}
71
71
  className={className(
72
72
  'carousel__slide',
@@ -78,6 +78,7 @@ export default function CarouselComponent({
78
78
  item={item}
79
79
  items={items}
80
80
  currentIndex={currentIndex}
81
+ isActive={isActive}
81
82
  />
82
83
  </div>
83
84
  )
@@ -6,6 +6,7 @@ export default function CarouselMessageSlide({
6
6
  item: slide,
7
7
  items,
8
8
  currentIndex,
9
+ isActive,
9
10
  }) {
10
11
  const { t } = useI18n()
11
12
 
@@ -19,7 +20,7 @@ export default function CarouselMessageSlide({
19
20
  total: items.length,
20
21
  })}
21
22
  >
22
- <CardComponent {...slide} />
23
+ <CardComponent {...slide} isCarouselItem={true} hasFocus={isActive} />
23
24
  </div>
24
25
  )
25
26
  }
@@ -2,8 +2,8 @@ import MessageContainer from '../../message-container'
2
2
  import CarouselComponent from '../carousel-component'
3
3
  import CarouselMessageSlide from './components/slide'
4
4
 
5
- const getItemKey = item => item.title
6
- const getItemLabel = item => item.title
5
+ const getItemKey = (item, idx, prefix = '') => `${prefix}${item.title}:${idx}`
6
+ const getItemLabel = (item) => item.title
7
7
  const CarouselMessage = ({ event }) => {
8
8
  const slides = event.payload.body.cards
9
9
 
@@ -13,7 +13,7 @@ import { useI18n } from '../../../../domains/i18n'
13
13
  import { useTranslatedEventData } from '../../../../domains/translations'
14
14
  import MessageContainer from '../message-container'
15
15
 
16
- export const useChoicePrompt = event => {
16
+ export const useChoicePrompt = (event) => {
17
17
  const { payload } = event
18
18
  const [showOptions, setShowOptions] = useState(false)
19
19
  const { sendAction, addMessageBubble, addDivider } = useSeamlyCommands()
@@ -45,7 +45,7 @@ export const useChoicePrompt = event => {
45
45
  setShowOptions(payload.id === lastEventId)
46
46
  }, [payload, lastEventId])
47
47
 
48
- const onChoiceClickHandler = choice => {
48
+ const onChoiceClickHandler = (choice) => {
49
49
  if (chooseAgain) {
50
50
  addDivider('new_topic')
51
51
  }
@@ -63,7 +63,7 @@ export const useChoicePrompt = event => {
63
63
  }
64
64
 
65
65
  const onChooseAgainClickHandler = () => {
66
- setShowOptions(s => !s)
66
+ setShowOptions((s) => !s)
67
67
  }
68
68
 
69
69
  return {
@@ -91,7 +91,7 @@ const ChoicePrompt = ({ event, children, ...props }) => {
91
91
 
92
92
  return (
93
93
  <>
94
- {toChildArray(children).map(child => {
94
+ {toChildArray(children).map((child) => {
95
95
  child.props = {
96
96
  ...child.props,
97
97
  event: subEvent,
@@ -126,7 +126,7 @@ const ChoicePrompt = ({ event, children, ...props }) => {
126
126
  {...props}
127
127
  >
128
128
  <ul className={className('choice-prompt', 'choice-prompt--many')}>
129
- {body.choices.map(choice => (
129
+ {body.choices.map((choice) => (
130
130
  <li
131
131
  key={choice.id}
132
132
  className={className('choice-prompt__item', {
@@ -10,7 +10,7 @@ const NewTranslationDivider = ({ event }) => {
10
10
  const { enableTranslations, languages } = useTranslations()
11
11
 
12
12
  const languageName = useMemo(() => {
13
- return languages?.find(lang => lang.locale === translationLocale)
13
+ return languages?.find((lang) => lang.locale === translationLocale)
14
14
  ?.nativeName
15
15
  }, [languages, translationLocale])
16
16
 
@@ -25,7 +25,7 @@ const NewTranslationDivider = ({ event }) => {
25
25
  translationEnabled
26
26
  ? 'translations.divider.startText'
27
27
  : 'translations.divider.stopText',
28
- languageName,
28
+ { language: languageName },
29
29
  )}
30
30
  </p>
31
31
  {translationEnabled ? (
@@ -1,13 +1,11 @@
1
- import {
2
- useSeamlyConfig,
3
- useSeamlyParticipant,
4
- } from '../../../hooks/seamly-hooks'
1
+ import { useSeamlyParticipant } from '../../../hooks/seamly-hooks'
5
2
  import { className } from '../../../../lib/css'
3
+ import { useConfig } from '../../../../domains/config'
6
4
 
7
5
  const EventParticipant = ({ eventPayload }) => {
8
6
  const { fromClient, participant: participantId } = eventPayload
9
7
  const participant = useSeamlyParticipant(participantId) || {}
10
- const { messages, defaults } = useSeamlyConfig()
8
+ const { messages, defaults } = useConfig()
11
9
 
12
10
  const participantName = participant && participant.name
13
11
  const { showAvatar, showName } = messages[fromClient ? 'user' : 'agent'] || {}
@@ -1,10 +1,10 @@
1
1
  import { actionTypes } from '../../../../utils/seamly-utils'
2
2
  import { useSeamlyCommands } from '../../../../hooks/seamly-hooks'
3
3
 
4
- const useEventLinkClickHandler = eventId => {
4
+ const useEventLinkClickHandler = (eventId) => {
5
5
  const { sendAction } = useSeamlyCommands()
6
6
 
7
- const eventClick = e => {
7
+ const eventClick = (e) => {
8
8
  if (e.target && e.target.dataset.linkId) {
9
9
  sendAction({
10
10
  type: actionTypes.navigate,
@@ -1,13 +1,13 @@
1
1
  import { useI18n } from '../../../../../domains/i18n'
2
- import { useSeamlyConfig } from '../../../../hooks/seamly-hooks'
3
2
  import { getRelativeDate } from '../../../../utils/general-utils'
3
+ import { useConfig } from '../../../../../domains/config'
4
4
 
5
5
  const dateFormatOptions = { month: 'long', day: 'numeric', year: 'numeric' }
6
6
  const timeFormatOptions = { hour: 'numeric', minute: 'numeric' }
7
7
 
8
- export const useFormattedDate = date => {
8
+ export const useFormattedDate = (date) => {
9
9
  const { t } = useI18n()
10
- const config = useSeamlyConfig()
10
+ const config = useConfig()
11
11
  const locale = config?.context?.locale ?? []
12
12
  const eventDate = new Date(date)
13
13
  const currentDate = new Date()
@@ -1,11 +1,11 @@
1
1
  import { useMemo } from 'preact/hooks'
2
2
  import Mustache from 'mustache'
3
3
 
4
- Mustache.escape = function(escapeText) {
4
+ Mustache.escape = function (escapeText) {
5
5
  return escapeText
6
6
  }
7
7
 
8
- const parseLinkVariable = variable => {
8
+ const parseLinkVariable = (variable) => {
9
9
  return `<a href='${variable.url}' data-link-id='${variable.id}' ${
10
10
  variable.newTab ? 'target="_blank"' : ''
11
11
  }>${variable.name}</a>`
@@ -26,7 +26,7 @@ export function parseRichtText(text, variables = {}) {
26
26
 
27
27
  // Disable escaping as we'll be generating HTML
28
28
  const oldEscape = Mustache.escape
29
- Mustache.escape = function(escapeText) {
29
+ Mustache.escape = function (escapeText) {
30
30
  return escapeText
31
31
  }
32
32
  const output = Mustache.render(text, view)
@@ -2,11 +2,11 @@ import { useMemo } from 'preact/hooks'
2
2
  import Mustache from 'mustache'
3
3
  import parseBody from '../../../../lib/parse-body'
4
4
  import EventDivider from '../event-divider'
5
- import { useSeamlyConfig } from '../../../hooks/seamly-hooks'
6
5
  import { useTranslatedEventData } from '../../../../domains/translations'
6
+ import { useConfig } from '../../../../domains/config'
7
7
 
8
8
  const Participant = ({ event }) => {
9
- const { agentIcon } = useSeamlyConfig().defaults || {}
9
+ const { agentIcon } = useConfig().defaults || {}
10
10
 
11
11
  const { participant } = event.payload
12
12
  const [introduction] = useTranslatedEventData(event)