@seamly/web-ui 20.4.0 → 20.5.0

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 (38) hide show
  1. package/build/dist/lib/index.debug.js +35 -68
  2. package/build/dist/lib/index.debug.min.js +1 -1
  3. package/build/dist/lib/index.debug.min.js.LICENSE.txt +4 -16
  4. package/build/dist/lib/index.js +374 -3850
  5. package/build/dist/lib/index.min.js +1 -1
  6. package/build/dist/lib/index.min.js.LICENSE.txt +0 -5
  7. package/build/dist/lib/standalone.js +394 -3862
  8. package/build/dist/lib/standalone.min.js +1 -1
  9. package/build/dist/lib/style-guide.js +200 -113
  10. package/build/dist/lib/style-guide.min.js +1 -1
  11. package/package.json +2 -4
  12. package/src/javascripts/api/index.js +17 -1
  13. package/src/javascripts/domains/config/reducer.js +2 -0
  14. package/src/javascripts/domains/forms/provider.js +14 -6
  15. package/src/javascripts/domains/visibility/actions.js +2 -0
  16. package/src/javascripts/domains/visibility/hooks.js +60 -1
  17. package/src/javascripts/domains/visibility/reducer.js +5 -0
  18. package/src/javascripts/domains/visibility/selectors.js +5 -0
  19. package/src/javascripts/domains/visibility/utils.js +5 -1
  20. package/src/javascripts/style-guide/components/app.js +2 -0
  21. package/src/javascripts/style-guide/states.js +30 -50
  22. package/src/javascripts/ui/components/conversation/event/card-component.js +1 -2
  23. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +19 -9
  24. package/src/javascripts/ui/components/conversation/event/cta.js +1 -2
  25. package/src/javascripts/ui/components/conversation/event/participant.js +2 -11
  26. package/src/javascripts/ui/components/conversation/event/splash.js +1 -3
  27. package/src/javascripts/ui/components/conversation/event/text.js +9 -9
  28. package/src/javascripts/ui/components/layout/chat.js +52 -48
  29. package/src/javascripts/ui/components/suggestions/suggestions-list.js +12 -14
  30. package/src/javascripts/ui/components/view/deprecated-view.js +16 -11
  31. package/src/javascripts/ui/components/view/inline-view.js +13 -8
  32. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +3 -2
  33. package/src/javascripts/ui/hooks/seamly-state-hooks.js +4 -3
  34. package/src/javascripts/ui/hooks/use-seamly-chat.js +41 -29
  35. package/src/javascripts/ui/hooks/use-seamly-commands.js +16 -4
  36. package/src/javascripts/ui/utils/seamly-utils.js +16 -6
  37. package/src/javascripts/lib/parse-body.js +0 -10
  38. package/src/javascripts/ui/components/conversation/event/hooks/use-text-rendering.js +0 -35
@@ -273,8 +273,7 @@ const infoMessage = {
273
273
  payload: {
274
274
  body: {
275
275
  text: 'This is a system generated info message',
276
- type: 'text',
277
- variables: {}
276
+ type: 'text'
278
277
  },
279
278
  fromClient: false,
280
279
  id: (0,web_ui_namespaceObject.randomId)(),
@@ -327,7 +326,7 @@ const participantMessage = {
327
326
  participant: {
328
327
  avatar,
329
328
  id: 'agent',
330
- introduction: "You're now talking to {{name}} gimme a minit",
329
+ introduction: "You're now talking to Mrs. Bot gimme a minit",
331
330
  name: 'Mrs. Bot',
332
331
  service: {
333
332
  expose: {
@@ -353,7 +352,7 @@ const participantMessageDefaultIcon = {
353
352
  messageStatus: 'received',
354
353
  participant: {
355
354
  id: 'user',
356
- introduction: "You're now talking to {{name}} gimme a minit",
355
+ introduction: "You're now talking to Mrs. Bot gimme a minit",
357
356
  name: 'Mrs. Bot',
358
357
  service: {
359
358
  expose: {
@@ -381,8 +380,7 @@ const getCustomMessage = ({
381
380
  body: {
382
381
  type,
383
382
  text,
384
- data,
385
- variables: {}
383
+ data
386
384
  },
387
385
  participant: 'agent',
388
386
  service: {
@@ -407,8 +405,7 @@ const shortTextMessage = {
407
405
  payload: {
408
406
  body: {
409
407
  text: 'What do you want to do?',
410
- type: 'text',
411
- variables: {}
408
+ type: 'text'
412
409
  },
413
410
  fromClient: false,
414
411
  fromHistory: true,
@@ -443,7 +440,7 @@ const ctaMessage = {
443
440
  type: 'message',
444
441
  payload: {
445
442
  body: {
446
- description: 'Thanks for chatting!\n\nMore info about our **products**?',
443
+ description: 'Thanks for chatting!\n\nMore info about our <strong>products</strong>?',
447
444
  buttonLink: 'https://seamly.ai',
448
445
  buttonText: 'View website',
449
446
  buttonNewTab: true
@@ -472,8 +469,7 @@ const longTextMessage = {
472
469
  payload: {
473
470
  body: {
474
471
  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.',
475
- type: 'text',
476
- variables: {}
472
+ type: 'text'
477
473
  },
478
474
  fromClient: false,
479
475
  fromHistory: true,
@@ -496,9 +492,8 @@ const textMessageBoldItalicUnderline = {
496
492
  type: 'message',
497
493
  payload: {
498
494
  body: {
499
- text: 'Bubble with **bold** *italic* <u>underline</u>',
500
- type: 'text',
501
- variables: {}
495
+ text: 'Bubble with <strong>bold</strong> <em>italic</em> <u>underline</u>',
496
+ type: 'text'
502
497
  },
503
498
  fromClient: false,
504
499
  fromHistory: true,
@@ -523,24 +518,8 @@ const textMessageWithLinks = {
523
518
  type: 'message',
524
519
  payload: {
525
520
  body: {
526
- text: '{{link_1}} and {{link_2}} embedded in text',
527
- type: 'text',
528
- variables: {
529
- link_1: {
530
- id: '1',
531
- name: 'Link in same window',
532
- newTab: false,
533
- type: 'link',
534
- url: 'https://google.com'
535
- },
536
- link_2: {
537
- id: '2',
538
- name: 'link in new window',
539
- newTab: true,
540
- type: 'link',
541
- url: 'https://google.com'
542
- }
543
- }
521
+ text: '<a href="https://google.com" data-link-id="1">Link in same window</a> and <a href="https://google.com" data-link-id="2" target="_blank">link in new window</a> embedded in text',
522
+ type: 'text'
544
523
  },
545
524
  fromClient: false,
546
525
  fromHistory: true,
@@ -565,17 +544,8 @@ const textMessageWithLongLink = {
565
544
  type: 'message',
566
545
  payload: {
567
546
  body: {
568
- text: 'Here is a long link {{link_1}} embedded in text',
569
- type: 'text',
570
- variables: {
571
- link_1: {
572
- id: '1',
573
- 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',
574
- newTab: false,
575
- type: 'link',
576
- url: 'https://google.com'
577
- }
578
- }
547
+ text: 'Here is a long link <a href="https://google.com" data-link-id="1">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</a> embedded in text',
548
+ type: 'text'
579
549
  },
580
550
  fromClient: false,
581
551
  fromHistory: true,
@@ -601,8 +571,7 @@ const textMesageWithBullets = {
601
571
  payload: {
602
572
  body: {
603
573
  text: '<ul>\n<li>Bullets</li>\n<li>bullets</li>\n<li>bullets</li>\n</ul>\n',
604
- type: 'text',
605
- variables: {}
574
+ type: 'text'
606
575
  },
607
576
  fromClient: false,
608
577
  fromHistory: true,
@@ -763,8 +732,7 @@ const userMessage = {
763
732
  payload: {
764
733
  body: {
765
734
  text: 'This is what the user typed',
766
- type: 'text',
767
- variables: {}
735
+ type: 'text'
768
736
  },
769
737
  fromClient: true,
770
738
  fromHistory: true,
@@ -781,8 +749,24 @@ const userMessageLong = {
781
749
  payload: {
782
750
  body: {
783
751
  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!!',
784
- type: 'text',
785
- variables: {}
752
+ type: 'text'
753
+ },
754
+ fromClient: true,
755
+ fromHistory: true,
756
+ id: (0,web_ui_namespaceObject.randomId)(),
757
+ messageStatus: 'read',
758
+ participant: 'user',
759
+ transactionId: '1cdefea9-7437-4672-bcf8-2c75dc99244c',
760
+ transactionLast: null,
761
+ type: 'text'
762
+ }
763
+ };
764
+ const userMessageWithLinks = {
765
+ type: 'message',
766
+ payload: {
767
+ body: {
768
+ text: '<a href="https://google.com" data-link-id="1">Link in same window</a> and <a href="https://google.com" data-link-id="2" target="_blank">link in new window</a> embedded in text',
769
+ type: 'text'
786
770
  },
787
771
  fromClient: true,
788
772
  fromHistory: true,
@@ -968,7 +952,7 @@ const cardAskText = {
968
952
  type: 'ask'
969
953
  },
970
954
  buttonText: 'Ask about pizzas!',
971
- description: '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.',
955
+ description: 'Pizza Margherita is a <strong>typical Neapolitan pizza</strong>.\n\nIt is made with San Marzano tomatoes, mozzarella cheese, fresh basil, salt, and extra-virgin olive oil.',
972
956
  image: 'https://developers.seamly.ai/clients/web-ui/static/photos/card-square.jpg',
973
957
  title: 'Pizza Margherita'
974
958
  }
@@ -986,7 +970,7 @@ const cardNavigate = {
986
970
  type: 'navigate'
987
971
  },
988
972
  buttonText: 'Order now!',
989
- description: 'Pizza Margherita is a **typical Neapolitan pizza**.',
973
+ description: 'Pizza Margherita is a <strong>typical Neapolitan pizza</strong>.',
990
974
  image: 'https://developers.seamly.ai/clients/web-ui/static/photos/card-landscape.jpg',
991
975
  title: 'Pizza Margherita'
992
976
  }
@@ -1164,7 +1148,7 @@ const standardState = {
1164
1148
  payload: states_objectSpread(states_objectSpread({}, choicePromptMessage.payload), {}, {
1165
1149
  id: `${choicePromptMessage.payload.id}XXX`
1166
1150
  })
1167
- }), longTextMessage, userMessage, textMessageBoldItalicUnderline, newTopicDivider, imageMessage, fileDownloadAgentMessage, deletedFileDownloadAgentMessage, userMessageLong, videoMessage, textMessageWithLinks, textMessageWithLongLink, imageMessageWithLightbox, fileDownloadUserMessage, emptyUrlFileDownloadUserMessage, textMesageWithBullets, choicePromptMessage, ctaMessage]
1151
+ }), longTextMessage, userMessage, textMessageBoldItalicUnderline, userMessageWithLinks, newTopicDivider, imageMessage, fileDownloadAgentMessage, deletedFileDownloadAgentMessage, userMessageLong, videoMessage, textMessageWithLinks, textMessageWithLongLink, imageMessageWithLightbox, fileDownloadUserMessage, emptyUrlFileDownloadUserMessage, textMesageWithBullets, choicePromptMessage, ctaMessage]
1168
1152
  }),
1169
1153
  userMessages: states_objectSpread(states_objectSpread({
1170
1154
  category: categoryKeys.messages,
@@ -1172,7 +1156,7 @@ const standardState = {
1172
1156
  description: ''
1173
1157
  }, baseState), {}, {
1174
1158
  participantInfo,
1175
- events: [userMessage, userMessageLong, fileDownloadUserMessage, emptyUrlFileDownloadUserMessage]
1159
+ events: [userMessage, userMessageLong, fileDownloadUserMessage, emptyUrlFileDownloadUserMessage, userMessageWithLinks]
1176
1160
  }),
1177
1161
  withParticipants: states_objectSpread(states_objectSpread({
1178
1162
  category: categoryKeys.messages,
@@ -1239,8 +1223,7 @@ const standardState = {
1239
1223
  id: (0,web_ui_namespaceObject.randomId)(),
1240
1224
  body: {
1241
1225
  text: 'Long ago when a dialog started',
1242
- type: 'text',
1243
- variables: {}
1226
+ type: 'text'
1244
1227
  }
1245
1228
  })
1246
1229
  }, participantMessage, participantMessageDefaultIcon, newTopicDivider, transcriptInfoMessage, ...[newTranslationDividerStart, newTranslationDividerStop].map(addTranslationData), infoMessage]
@@ -1284,8 +1267,7 @@ const standardState = {
1284
1267
  id: (0,web_ui_namespaceObject.randomId)(),
1285
1268
  body: {
1286
1269
  text: 'Long ago when a dialog started',
1287
- type: 'text',
1288
- variables: {}
1270
+ type: 'text'
1289
1271
  }
1290
1272
  })
1291
1273
  }, {
@@ -1295,8 +1277,7 @@ const standardState = {
1295
1277
  id: (0,web_ui_namespaceObject.randomId)(),
1296
1278
  body: {
1297
1279
  text: 'Above me should be a time indicator showing the full date',
1298
- type: 'text',
1299
- variables: {}
1280
+ type: 'text'
1300
1281
  }
1301
1282
  })
1302
1283
  }, {
@@ -1306,8 +1287,7 @@ const standardState = {
1306
1287
  id: (0,web_ui_namespaceObject.randomId)(),
1307
1288
  body: {
1308
1289
  text: 'Another message',
1309
- type: 'text',
1310
- variables: {}
1290
+ type: 'text'
1311
1291
  }
1312
1292
  })
1313
1293
  }, {
@@ -1317,8 +1297,7 @@ const standardState = {
1317
1297
  id: (0,web_ui_namespaceObject.randomId)(),
1318
1298
  body: {
1319
1299
  text: 'And another message',
1320
- type: 'text',
1321
- variables: {}
1300
+ type: 'text'
1322
1301
  }
1323
1302
  })
1324
1303
  }, {
@@ -1328,8 +1307,7 @@ const standardState = {
1328
1307
  id: (0,web_ui_namespaceObject.randomId)(),
1329
1308
  body: {
1330
1309
  text: 'Above me should be a time indicator showing "yesterday"',
1331
- type: 'text',
1332
- variables: {}
1310
+ type: 'text'
1333
1311
  }
1334
1312
  })
1335
1313
  }, {
@@ -1339,8 +1317,7 @@ const standardState = {
1339
1317
  id: (0,web_ui_namespaceObject.randomId)(),
1340
1318
  body: {
1341
1319
  text: 'Another message',
1342
- type: 'text',
1343
- variables: {}
1320
+ type: 'text'
1344
1321
  }
1345
1322
  })
1346
1323
  }, {
@@ -1350,8 +1327,7 @@ const standardState = {
1350
1327
  id: (0,web_ui_namespaceObject.randomId)(),
1351
1328
  body: {
1352
1329
  text: 'And another message',
1353
- type: 'text',
1354
- variables: {}
1330
+ type: 'text'
1355
1331
  }
1356
1332
  })
1357
1333
  }, {
@@ -1361,8 +1337,7 @@ const standardState = {
1361
1337
  id: (0,web_ui_namespaceObject.randomId)(),
1362
1338
  body: {
1363
1339
  text: 'Above me should be a time indicator showing me the dialog continues today',
1364
- type: 'text',
1365
- variables: {}
1340
+ type: 'text'
1366
1341
  }
1367
1342
  })
1368
1343
  }]
@@ -1940,7 +1915,7 @@ const newInterface = {
1940
1915
  headingText: 'Suggestions message',
1941
1916
  description: ''
1942
1917
  }, baseState), {}, {
1943
- events: [{
1918
+ events: [getCustomMessage(shortTextMessage.payload.body), {
1944
1919
  type: 'service_data',
1945
1920
  payload: {
1946
1921
  type: 'suggestion',
@@ -2413,14 +2388,16 @@ const orderHistory = events => {
2413
2388
  };
2414
2389
 
2415
2390
  const mergeHistory = (stateEvents, historyEvents) => {
2416
- const newHistoryEvents = historyEvents.filter(historyEvent => // Deduplicate the event streams
2417
- !stateEvents.find(stateEvent => stateEvent.payload.id === historyEvent.payload.id) && // Remove all non displayable participant messages
2391
+ const newStateEvents = stateEvents.filter(stateEvent => // Deduplicate the event streams, giving events in historyEvents
2392
+ // precedence so the server is able to push changes to events.
2393
+ !historyEvents.some(historyEvent => historyEvent.payload.id === stateEvent.payload.id));
2394
+ const newHistoryEvents = historyEvents.filter(historyEvent => // Remove all non displayable participant messages
2418
2395
  !(historyEvent.type === 'participant' && !historyEvent.payload.participant.introduction)) // Reverse is done here because the server sends the history in the order
2419
2396
  // newest to oldest. In the case of exactly the same occurredAt timestamps
2420
2397
  // these messages will be shown in the wrong order if not reversed. For
2421
2398
  // the normal merging logic there is no added effect.
2422
2399
  .reverse();
2423
- return orderHistory([...newHistoryEvents, ...stateEvents]);
2400
+ return orderHistory([...newHistoryEvents, ...newStateEvents]);
2424
2401
  };
2425
2402
 
2426
2403
  const participantReducer = (state, action) => {
@@ -2801,8 +2778,12 @@ const seamlyStateReducer = (state, action) => {
2801
2778
  });
2802
2779
 
2803
2780
  case SET_INITIAL_STATE:
2781
+ const {
2782
+ initialState
2783
+ } = action;
2804
2784
  return seamly_utils_objectSpread(seamly_utils_objectSpread({}, state), {}, {
2805
- initialState: action.initialState
2785
+ initialState,
2786
+ unreadEvents: initialState.unreadMessageCount
2806
2787
  });
2807
2788
 
2808
2789
  case SET_SERVICE_DATA_ITEM:
@@ -3765,18 +3746,23 @@ const useEntryTextLimit = () => {
3765
3746
  entryMeta: {
3766
3747
  options: {
3767
3748
  text
3749
+ },
3750
+ optionsOverride: {
3751
+ text: overrideText
3768
3752
  }
3769
3753
  }
3770
3754
  } = seamly_state_hooks_useSeamlyStateContext();
3771
3755
  const {
3772
3756
  limit
3773
- } = text || {};
3757
+ } = overrideText || text || {
3758
+ limit: null
3759
+ };
3774
3760
  return {
3775
- hasLimit: limit != null,
3776
- limit: limit != null ? limit : null
3761
+ hasLimit: limit !== null,
3762
+ limit: limit !== null ? limit : null
3777
3763
  };
3778
3764
  };
3779
- const useSeamlyLayoutMode = () => {
3765
+ const seamly_state_hooks_useSeamlyLayoutMode = () => {
3780
3766
  const {
3781
3767
  layoutMode
3782
3768
  } = useConfig();
@@ -3809,7 +3795,12 @@ const calculateVisibility = ({
3809
3795
  } = config;
3810
3796
  const {
3811
3797
  visible: defaultVisibility
3812
- } = defaults || {}; // Requesting open should override the responded check.
3798
+ } = defaults || {}; // The app layout should always be open by default.
3799
+
3800
+ if (layoutMode === 'app' && !previousVisibility) {
3801
+ return constants_visibilityStates.open;
3802
+ } // Requesting open should override the responded check.
3803
+
3813
3804
 
3814
3805
  if (layoutMode === 'window' && hideOnNoUserResponse && requestedVisibility !== constants_visibilityStates.open) {
3815
3806
  return hasResponded ? requestedVisibility || previousVisibility || constants_visibilityStates.open : constants_visibilityStates.hidden;
@@ -3828,6 +3819,7 @@ const calculateVisibility = ({
3828
3819
 
3829
3820
 
3830
3821
  const selectVisibility = createSelector(visibility_utils_selectState, state => state.visibility);
3822
+ const selectors_selectShowInlineView = createSelector(visibility_utils_selectState, state => state.showInlineView);
3831
3823
 
3832
3824
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/actions.js
3833
3825
  function actions_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
@@ -3845,6 +3837,7 @@ function actions_defineProperty(obj, key, value) { if (key in obj) { Object.defi
3845
3837
  const setFromStorage = visibility_utils_createAction('setFromStorage', visibility => ({
3846
3838
  visibility
3847
3839
  }));
3840
+ const setShowInlineView = visibility_utils_createAction('setShowInlineView');
3848
3841
  const validVisibilityStates = [constants_visibilityStates.open, constants_visibilityStates.minimized, constants_visibilityStates.hidden];
3849
3842
  const setVisibility = visibility_utils_createThunk('set', (requestedVisibility, {
3850
3843
  getState,
@@ -3992,7 +3985,7 @@ const clear = interrupt_utils_createAction('clear');
3992
3985
 
3993
3986
 
3994
3987
 
3995
- const setHasResponded = app_utils_createAction('setHasResponded', hasResponded => ({
3988
+ const actions_setHasResponded = app_utils_createAction('setHasResponded', hasResponded => ({
3996
3989
  hasResponded
3997
3990
  }));
3998
3991
  const app_actions_initialize = app_utils_createThunk('initialize', async (_, {
@@ -4050,7 +4043,7 @@ const app_actions_initialize = app_utils_createThunk('initialize', async (_, {
4050
4043
  locale = initialState.translation?.locale || locale;
4051
4044
 
4052
4045
  if ('userResponded' in initialState) {
4053
- dispatch(setHasResponded(initialState.userResponded));
4046
+ dispatch(actions_setHasResponded(initialState.userResponded));
4054
4047
  }
4055
4048
  } else {
4056
4049
  if (config?.context?.topic) {
@@ -4356,6 +4349,7 @@ function provider_objectWithoutPropertiesLoose(source, excluded) { if (source ==
4356
4349
 
4357
4350
 
4358
4351
 
4352
+
4359
4353
  function provider_FormProvider(_ref) {
4360
4354
  let {
4361
4355
  children,
@@ -4411,13 +4405,13 @@ function provider_FormProvider(_ref) {
4411
4405
  setIsSubmitted(!ariaDisabled);
4412
4406
 
4413
4407
  if (!ariaDisabled && validationIsValid) {
4408
+ dispatch(setHasResponded(true));
4414
4409
  onSubmit(values, {
4415
4410
  updateControlValue,
4416
4411
  setError
4417
4412
  });
4418
4413
  }
4419
- }, [validationIsValid, onSubmit, values, updateControlValue, setError]); //
4420
-
4414
+ }, [validationIsValid, dispatch, onSubmit, values, updateControlValue, setError]);
4421
4415
  useEffect(() => {
4422
4416
  if (onError) {
4423
4417
  onError({
@@ -4662,6 +4656,7 @@ function config_reducer_defineProperty(obj, key, value) { if (key in obj) { Obje
4662
4656
 
4663
4657
  const config_reducer_initialState = config_reducer_objectSpread(config_reducer_objectSpread({}, defaultConfig), {}, {
4664
4658
  hideOnNoUserResponse: false,
4659
+ connectWhenInView: true,
4665
4660
  showDisclaimer: false,
4666
4661
  showFaq: false,
4667
4662
  customComponents: {},
@@ -4669,7 +4664,7 @@ const config_reducer_initialState = config_reducer_objectSpread(config_reducer_o
4669
4664
  preChatEvents: []
4670
4665
  });
4671
4666
 
4672
- const configKeys = ['hideOnNoUserResponse', 'showDisclaimer', 'showFaq', 'namespace', 'customComponents', 'defaults', 'layoutMode', 'api', 'zIndex', 'context', 'appContainerClassNames', 'messages', 'visible', 'visibilityCallback', 'errorCallback', 'agentParticipant', 'userParticipant', 'startChatIcon'];
4667
+ const configKeys = ['hideOnNoUserResponse', 'connectWhenInView', 'showDisclaimer', 'showFaq', 'namespace', 'customComponents', 'defaults', 'layoutMode', 'api', 'zIndex', 'context', 'appContainerClassNames', 'messages', 'visible', 'visibilityCallback', 'errorCallback', 'agentParticipant', 'userParticipant', 'startChatIcon'];
4673
4668
 
4674
4669
  const updateState = (state, {
4675
4670
  config
@@ -5938,6 +5933,7 @@ function hooks_useUserHasResponded() {
5938
5933
 
5939
5934
 
5940
5935
 
5936
+
5941
5937
  const hooks_useVisibility = () => {
5942
5938
  const dispatch = useStoreDispatch();
5943
5939
  const visible = useSelector(Selectors.selectVisibility);
@@ -5953,6 +5949,69 @@ const hooks_useVisibility = () => {
5953
5949
  setVisibility
5954
5950
  };
5955
5951
  };
5952
+ /**
5953
+ * Custom hook which enables initializing of IntersectionObserver on any node ref.
5954
+ * @param {object} options Hook options.
5955
+ * @param {boolean=} options.freezeOnceVisible Stops observing when the root element is visible.
5956
+ * @param {boolean=} options.enabled Determines if useIntersect is enabled.
5957
+ */
5958
+
5959
+ const useIntersect = ({
5960
+ freezeOnceVisible = false,
5961
+ enabled = true
5962
+ }) => {
5963
+ const [entry, setEntry] = useState(null);
5964
+ const containerRef = useRef(null);
5965
+ const isVisible = !!entry?.isIntersecting || !enabled;
5966
+ const frozen = isVisible && freezeOnceVisible;
5967
+
5968
+ const observerCallback = ([updatedEntry]) => setEntry(updatedEntry);
5969
+
5970
+ useEffect(() => {
5971
+ const node = containerRef?.current;
5972
+ const hasIOSupport = !!window.IntersectionObserver;
5973
+
5974
+ if (!node && "production" === 'development') {} // Return an arrow function to have a consistent return value
5975
+
5976
+
5977
+ if (!hasIOSupport || frozen || !node || !enabled) return () => undefined;
5978
+ const observerOptions = {
5979
+ threshold: 0,
5980
+ root: null,
5981
+ rootMargin: '0%'
5982
+ };
5983
+ const observer = new IntersectionObserver(observerCallback, observerOptions);
5984
+ observer.observe(node);
5985
+ return () => observer.disconnect();
5986
+ }, [enabled, frozen]);
5987
+ return {
5988
+ isVisible,
5989
+ containerRef
5990
+ };
5991
+ };
5992
+
5993
+ const useShowInlineView = () => {
5994
+ const dispatch = useStoreDispatch();
5995
+ const {
5996
+ connectWhenInView
5997
+ } = useConfig();
5998
+ const showInlineView = useSelector(Selectors.selectShowInlineView);
5999
+ const {
6000
+ containerRef,
6001
+ isVisible
6002
+ } = useIntersect({
6003
+ enabled: connectWhenInView,
6004
+ freezeOnceVisible: true
6005
+ });
6006
+ useEffect(() => {
6007
+ if (!isVisible) return;
6008
+ dispatch(Actions.setShowInlineView());
6009
+ }, [dispatch, isVisible]);
6010
+ return {
6011
+ containerRef,
6012
+ showInlineView
6013
+ };
6014
+ };
5956
6015
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/reducer.js
5957
6016
  function visibility_reducer_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
5958
6017
 
@@ -5964,7 +6023,8 @@ function visibility_reducer_defineProperty(obj, key, value) { if (key in obj) {
5964
6023
 
5965
6024
 
5966
6025
  const visibility_reducer_initialState = {
5967
- visibility: constants_visibilityStates.initialize
6026
+ visibility: constants_visibilityStates.initialize,
6027
+ showInlineView: false
5968
6028
  };
5969
6029
  /* harmony default export */ const visibility_reducer = (visibility_utils_createReducer({
5970
6030
  [setFromStorage]: (state, {
@@ -5976,7 +6036,10 @@ const visibility_reducer_initialState = {
5976
6036
  payload: visibility
5977
6037
  }) => visibility ? visibility_reducer_objectSpread(visibility_reducer_objectSpread({}, state), {}, {
5978
6038
  visibility
5979
- }) : state
6039
+ }) : state,
6040
+ [setShowInlineView]: state => visibility_reducer_objectSpread(visibility_reducer_objectSpread({}, state), {}, {
6041
+ showInlineView: true
6042
+ })
5980
6043
  }, visibility_reducer_initialState));
5981
6044
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/index.js
5982
6045
 
@@ -6047,7 +6110,8 @@ const use_seamly_commands_useSeamlyCommands = () => {
6047
6110
  const hasResponded = useUserHasResponded();
6048
6111
  const hasConversation = useSeamlyHasConversation();
6049
6112
  const {
6050
- visible: visibility
6113
+ visible: visibility,
6114
+ setVisibility
6051
6115
  } = useVisibility();
6052
6116
  const unreadMessageCount = useSeamlyUnreadCount();
6053
6117
  const emitEvent = useCallback((...args) => {
@@ -6105,7 +6169,9 @@ const use_seamly_commands_useSeamlyCommands = () => {
6105
6169
  type: use_seamly_commands_ADD_EVENT,
6106
6170
  event: {
6107
6171
  type: 'message',
6108
- payload: message
6172
+ payload: use_seamly_commands_objectSpread(use_seamly_commands_objectSpread({}, message), {}, {
6173
+ optimisticallyInjected: true
6174
+ })
6109
6175
  }
6110
6176
  });
6111
6177
  }, [api, dispatch, emitEvent, getTextMessageBase]);
@@ -6203,11 +6269,16 @@ const use_seamly_commands_useSeamlyCommands = () => {
6203
6269
  type: use_seamly_commands_SET_INITIAL_STATE,
6204
6270
  initialState
6205
6271
  });
6272
+
6273
+ if (initialState.userResponded) {
6274
+ dispatch(AppActions.setHasResponded(initialState.userResponded));
6275
+ setVisibility(visibilityStates.open);
6276
+ }
6206
6277
  }
6207
6278
  }).catch(error => {
6208
6279
  dispatch(InterruptActions.set(error));
6209
6280
  });
6210
- }, [api, dispatch]);
6281
+ }, [api, dispatch, setVisibility]);
6211
6282
  return {
6212
6283
  connect,
6213
6284
  start,
@@ -6220,6 +6291,7 @@ const use_seamly_commands_useSeamlyCommands = () => {
6220
6291
  addMessageBubble,
6221
6292
  addUploadBubble,
6222
6293
  addDivider,
6294
+ apiConnected: api.connected,
6223
6295
  apiConfigReady: api.configReady
6224
6296
  };
6225
6297
  };
@@ -6349,11 +6421,12 @@ const useSeamlyEntry = () => {
6349
6421
  default: defaultEntry,
6350
6422
  active,
6351
6423
  userSelected,
6352
- options: entryOptions
6424
+ options: entryOptions,
6425
+ optionsOverride: entryOptionsOverride
6353
6426
  } = useSeamlyStateContext().entryMeta;
6354
6427
  const dispatch = useSeamlyDispatchContext();
6355
6428
  const activeEntry = userSelected || active || defaultEntry;
6356
- const activeEntryOptions = entryOptions[activeEntry] || {};
6429
+ const activeEntryOptions = entryOptionsOverride[activeEntry] || entryOptions[activeEntry] || {};
6357
6430
  const setBlockAutoEntrySwitch = useCallback(value => {
6358
6431
  dispatch({
6359
6432
  type: seamly_entry_hooks_SET_BLOCK_AUTO_ENTRY_SWITCH,
@@ -6399,6 +6472,7 @@ const useSeamlyEntry = () => {
6399
6472
 
6400
6473
 
6401
6474
 
6475
+
6402
6476
  const {
6403
6477
  SET_IS_LOADING: use_seamly_chat_SET_IS_LOADING
6404
6478
  } = seamly_utils_seamlyActions;
@@ -6408,28 +6482,31 @@ const useSeamlyChat = () => {
6408
6482
  t
6409
6483
  } = useI18n();
6410
6484
  const {
6411
- layoutMode
6412
- } = useConfig();
6485
+ isInline,
6486
+ isWindow
6487
+ } = useSeamlyLayoutMode();
6413
6488
  const {
6414
6489
  isOpen,
6415
6490
  isVisible,
6416
6491
  setVisibility
6417
6492
  } = useVisibility();
6493
+ const showInlineView = useSelector(selectShowInlineView);
6418
6494
  const dispatch = useSeamlyDispatchContext();
6419
6495
  const events = useEvents();
6420
6496
  const spinnerTimeout = useRef(null);
6421
6497
  const {
6422
6498
  start,
6423
6499
  connect,
6424
- apiConfigReady
6500
+ apiConfigReady,
6501
+ apiConnected
6425
6502
  } = useSeamlyCommands();
6426
6503
  const hasConversation = useSeamlyHasConversation();
6427
6504
  const prevIsOpen = useRef(null);
6428
6505
  const prevIsVisible = useRef(null);
6506
+ const startCalled = useRef(false);
6429
6507
  const {
6430
6508
  sendAssertive
6431
6509
  } = useLiveRegion();
6432
- const connectCalled = useRef(false);
6433
6510
  const hasEvents = events.length > 0;
6434
6511
  useEffect(() => {
6435
6512
  if (isVisible) {
@@ -6478,22 +6555,34 @@ const useSeamlyChat = () => {
6478
6555
  }
6479
6556
  }, [hasEvents, dispatch]);
6480
6557
  useEffect(() => {
6481
- // This is needed to reset the ref to allow connect to happen again.
6558
+ // This is needed to reset the ref to allow connect and start to happen again.
6482
6559
  // Mostly due to Interrupt situations and a reset being called.
6483
- if (!hasConversation || !apiConfigReady) {
6484
- connectCalled.current = false;
6560
+ if (!apiConfigReady || !apiConnected) {
6561
+ startCalled.current = false;
6485
6562
  }
6486
- }, [hasConversation, apiConfigReady]);
6563
+ }, [apiConfigReady, apiConnected]);
6564
+ const connectAndStart = useCallback(async () => {
6565
+ // We don't connect if we are already connected to the api to avoid multiple in-flight connection processes.
6566
+ if (!apiConnected) {
6567
+ await connect();
6568
+ } // We only start a conversation when the chat interface is either 'open' or if using the inline view if it's 'open' or 'minimized'.
6569
+
6570
+
6571
+ if (isOpen || isVisible && isInline) {
6572
+ start();
6573
+ startCalled.current = true;
6574
+ }
6575
+ }, [apiConnected, connect, isInline, isOpen, isVisible, start]);
6487
6576
  useEffect(() => {
6488
- // We don't connect minimised or hidden window interfaces unless
6489
- // they had been connected before.
6490
- // We also keep track of whether connect was called before to avoid
6491
- // multiple in-flight connection processes.
6492
- if (layoutMode === 'window' && !isOpen && !hasConversation || connectCalled.current || !apiConfigReady) {
6577
+ // We dont't connect or start when the apiConfig is not ready yet.
6578
+ // We also keep track of whether start has been called to avoid multiple in-flight connection processes.
6579
+ // We check if the window view is not open and no conversation is started yet.
6580
+ // Lastly we check if the inline view is not scrolled in to view.
6581
+ if (!apiConfigReady || startCalled.current || isWindow && !isOpen && !hasConversation || isInline && !showInlineView) {
6493
6582
  return;
6494
6583
  }
6495
6584
 
6496
- if (hasConversation) {
6585
+ if (hasConversation && isOpen) {
6497
6586
  // We deactivate the extra startup loading spinner when a conversation is available
6498
6587
  // We also stop setting the loading indicator in the first place to avoid a flash.
6499
6588
  clearTimeout(spinnerTimeout.current);
@@ -6503,11 +6592,8 @@ const useSeamlyChat = () => {
6503
6592
  });
6504
6593
  }
6505
6594
 
6506
- connect().then(() => {
6507
- start();
6508
- });
6509
- connectCalled.current = true;
6510
- }, [isOpen, hasConversation, apiConfigReady, start, connect, dispatch, layoutMode]);
6595
+ connectAndStart();
6596
+ }, [apiConfigReady, connectAndStart, dispatch, hasConversation, isInline, isOpen, isWindow, showInlineView]);
6511
6597
 
6512
6598
  const openChat = () => {
6513
6599
  setVisibility(visibilityStates.open);
@@ -7981,7 +8067,7 @@ const app_reducer_initialState = {
7981
8067
  userHasResponded: false
7982
8068
  };
7983
8069
  /* harmony default export */ const app_reducer = (app_utils_createReducer({
7984
- [setHasResponded]: (state, {
8070
+ [actions_setHasResponded]: (state, {
7985
8071
  hasResponded
7986
8072
  }) => app_reducer_objectSpread(app_reducer_objectSpread({}, state), {}, {
7987
8073
  userHasResponded: hasResponded
@@ -8329,6 +8415,7 @@ const StyleGuideApp = ({
8329
8415
 
8330
8416
  const updatedState = app_objectSpread(app_objectSpread({}, bareState), {}, {
8331
8417
  config: app_objectSpread(app_objectSpread(app_objectSpread(app_objectSpread({}, bareState.config), config), {}, {
8418
+ showDisclaimer: bareState.config.showDisclaimer || config.showDisclaimer,
8332
8419
  layoutMode: bareState.config.layoutMode
8333
8420
  }, overrideMessages ? {
8334
8421
  messages: overrideMessages