@seamly/web-ui 20.3.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 (48) hide show
  1. package/build/dist/lib/index.debug.js +61 -94
  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 +467 -3965
  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 +432 -3865
  8. package/build/dist/lib/standalone.min.js +1 -1
  9. package/build/dist/lib/style-guide.js +267 -191
  10. package/build/dist/lib/style-guide.min.js +1 -1
  11. package/build/dist/lib/styles.css +1 -1
  12. package/package.json +2 -4
  13. package/src/.DS_Store +0 -0
  14. package/src/javascripts/api/index.js +17 -1
  15. package/src/javascripts/domains/config/reducer.js +2 -0
  16. package/src/javascripts/domains/forms/provider.js +14 -6
  17. package/src/javascripts/domains/store/state-reducer.js +1 -0
  18. package/src/javascripts/domains/visibility/actions.js +2 -0
  19. package/src/javascripts/domains/visibility/hooks.js +60 -1
  20. package/src/javascripts/domains/visibility/reducer.js +5 -0
  21. package/src/javascripts/domains/visibility/selectors.js +5 -0
  22. package/src/javascripts/domains/visibility/utils.js +5 -1
  23. package/src/javascripts/index.js +1 -0
  24. package/src/javascripts/style-guide/components/app.js +2 -0
  25. package/src/javascripts/style-guide/states.js +55 -50
  26. package/src/javascripts/ui/components/conversation/conversation.js +9 -10
  27. package/src/javascripts/ui/components/conversation/event/card-component.js +1 -2
  28. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +19 -9
  29. package/src/javascripts/ui/components/conversation/event/cta.js +1 -2
  30. package/src/javascripts/ui/components/conversation/event/image.js +11 -3
  31. package/src/javascripts/ui/components/conversation/event/participant.js +2 -11
  32. package/src/javascripts/ui/components/conversation/event/splash.js +1 -3
  33. package/src/javascripts/ui/components/conversation/event/text.js +9 -9
  34. package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +6 -0
  35. package/src/javascripts/ui/components/layout/chat.js +52 -48
  36. package/src/javascripts/ui/components/suggestions/suggestions-list.js +12 -14
  37. package/src/javascripts/ui/components/view/deprecated-view.js +16 -11
  38. package/src/javascripts/ui/components/view/index.js +2 -2
  39. package/src/javascripts/ui/components/view/inline-view.js +13 -8
  40. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +3 -2
  41. package/src/javascripts/ui/hooks/seamly-state-hooks.js +7 -3
  42. package/src/javascripts/ui/hooks/use-seamly-chat.js +41 -29
  43. package/src/javascripts/ui/hooks/use-seamly-commands.js +16 -4
  44. package/src/javascripts/ui/utils/seamly-utils.js +24 -7
  45. package/src/stylesheets/5-components/_message-count.scss +5 -2
  46. package/CHANGELOG.md +0 -729
  47. package/src/javascripts/lib/parse-body.js +0 -10
  48. package/src/javascripts/ui/components/conversation/event/hooks/use-text-rendering.js +0 -35
@@ -129,6 +129,7 @@ const baseState = {
129
129
  },
130
130
  initialState: {},
131
131
  unreadEvents: 0,
132
+ loadedImageEventIds: [],
132
133
  isLoading: false,
133
134
  idleDetachCountdown: {
134
135
  hasCountdown: false,
@@ -272,8 +273,7 @@ const infoMessage = {
272
273
  payload: {
273
274
  body: {
274
275
  text: 'This is a system generated info message',
275
- type: 'text',
276
- variables: {}
276
+ type: 'text'
277
277
  },
278
278
  fromClient: false,
279
279
  id: (0,web_ui_namespaceObject.randomId)(),
@@ -326,7 +326,7 @@ const participantMessage = {
326
326
  participant: {
327
327
  avatar,
328
328
  id: 'agent',
329
- introduction: "You're now talking to {{name}} gimme a minit",
329
+ introduction: "You're now talking to Mrs. Bot gimme a minit",
330
330
  name: 'Mrs. Bot',
331
331
  service: {
332
332
  expose: {
@@ -352,7 +352,7 @@ const participantMessageDefaultIcon = {
352
352
  messageStatus: 'received',
353
353
  participant: {
354
354
  id: 'user',
355
- introduction: "You're now talking to {{name}} gimme a minit",
355
+ introduction: "You're now talking to Mrs. Bot gimme a minit",
356
356
  name: 'Mrs. Bot',
357
357
  service: {
358
358
  expose: {
@@ -380,8 +380,7 @@ const getCustomMessage = ({
380
380
  body: {
381
381
  type,
382
382
  text,
383
- data,
384
- variables: {}
383
+ data
385
384
  },
386
385
  participant: 'agent',
387
386
  service: {
@@ -406,8 +405,7 @@ const shortTextMessage = {
406
405
  payload: {
407
406
  body: {
408
407
  text: 'What do you want to do?',
409
- type: 'text',
410
- variables: {}
408
+ type: 'text'
411
409
  },
412
410
  fromClient: false,
413
411
  fromHistory: true,
@@ -442,7 +440,7 @@ const ctaMessage = {
442
440
  type: 'message',
443
441
  payload: {
444
442
  body: {
445
- description: 'Thanks for chatting!\n\nMore info about our **products**?',
443
+ description: 'Thanks for chatting!\n\nMore info about our <strong>products</strong>?',
446
444
  buttonLink: 'https://seamly.ai',
447
445
  buttonText: 'View website',
448
446
  buttonNewTab: true
@@ -471,8 +469,7 @@ const longTextMessage = {
471
469
  payload: {
472
470
  body: {
473
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.',
474
- type: 'text',
475
- variables: {}
472
+ type: 'text'
476
473
  },
477
474
  fromClient: false,
478
475
  fromHistory: true,
@@ -495,9 +492,8 @@ const textMessageBoldItalicUnderline = {
495
492
  type: 'message',
496
493
  payload: {
497
494
  body: {
498
- text: 'Bubble with **bold** *italic* <u>underline</u>',
499
- type: 'text',
500
- variables: {}
495
+ text: 'Bubble with <strong>bold</strong> <em>italic</em> <u>underline</u>',
496
+ type: 'text'
501
497
  },
502
498
  fromClient: false,
503
499
  fromHistory: true,
@@ -522,24 +518,8 @@ const textMessageWithLinks = {
522
518
  type: 'message',
523
519
  payload: {
524
520
  body: {
525
- text: '{{link_1}} and {{link_2}} embedded in text',
526
- type: 'text',
527
- variables: {
528
- link_1: {
529
- id: '1',
530
- name: 'Link in same window',
531
- newTab: false,
532
- type: 'link',
533
- url: 'https://google.com'
534
- },
535
- link_2: {
536
- id: '2',
537
- name: 'link in new window',
538
- newTab: true,
539
- type: 'link',
540
- url: 'https://google.com'
541
- }
542
- }
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'
543
523
  },
544
524
  fromClient: false,
545
525
  fromHistory: true,
@@ -564,17 +544,8 @@ const textMessageWithLongLink = {
564
544
  type: 'message',
565
545
  payload: {
566
546
  body: {
567
- text: 'Here is a long link {{link_1}} embedded in text',
568
- type: 'text',
569
- variables: {
570
- link_1: {
571
- id: '1',
572
- 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',
573
- newTab: false,
574
- type: 'link',
575
- url: 'https://google.com'
576
- }
577
- }
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'
578
549
  },
579
550
  fromClient: false,
580
551
  fromHistory: true,
@@ -600,8 +571,7 @@ const textMesageWithBullets = {
600
571
  payload: {
601
572
  body: {
602
573
  text: '<ul>\n<li>Bullets</li>\n<li>bullets</li>\n<li>bullets</li>\n</ul>\n',
603
- type: 'text',
604
- variables: {}
574
+ type: 'text'
605
575
  },
606
576
  fromClient: false,
607
577
  fromHistory: true,
@@ -762,8 +732,7 @@ const userMessage = {
762
732
  payload: {
763
733
  body: {
764
734
  text: 'This is what the user typed',
765
- type: 'text',
766
- variables: {}
735
+ type: 'text'
767
736
  },
768
737
  fromClient: true,
769
738
  fromHistory: true,
@@ -780,8 +749,24 @@ const userMessageLong = {
780
749
  payload: {
781
750
  body: {
782
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!!',
783
- type: 'text',
784
- 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'
785
770
  },
786
771
  fromClient: true,
787
772
  fromHistory: true,
@@ -967,7 +952,7 @@ const cardAskText = {
967
952
  type: 'ask'
968
953
  },
969
954
  buttonText: 'Ask about pizzas!',
970
- 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.',
971
956
  image: 'https://developers.seamly.ai/clients/web-ui/static/photos/card-square.jpg',
972
957
  title: 'Pizza Margherita'
973
958
  }
@@ -985,7 +970,7 @@ const cardNavigate = {
985
970
  type: 'navigate'
986
971
  },
987
972
  buttonText: 'Order now!',
988
- description: 'Pizza Margherita is a **typical Neapolitan pizza**.',
973
+ description: 'Pizza Margherita is a <strong>typical Neapolitan pizza</strong>.',
989
974
  image: 'https://developers.seamly.ai/clients/web-ui/static/photos/card-landscape.jpg',
990
975
  title: 'Pizza Margherita'
991
976
  }
@@ -1163,7 +1148,7 @@ const standardState = {
1163
1148
  payload: states_objectSpread(states_objectSpread({}, choicePromptMessage.payload), {}, {
1164
1149
  id: `${choicePromptMessage.payload.id}XXX`
1165
1150
  })
1166
- }), 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]
1167
1152
  }),
1168
1153
  userMessages: states_objectSpread(states_objectSpread({
1169
1154
  category: categoryKeys.messages,
@@ -1171,7 +1156,7 @@ const standardState = {
1171
1156
  description: ''
1172
1157
  }, baseState), {}, {
1173
1158
  participantInfo,
1174
- events: [userMessage, userMessageLong, fileDownloadUserMessage, emptyUrlFileDownloadUserMessage]
1159
+ events: [userMessage, userMessageLong, fileDownloadUserMessage, emptyUrlFileDownloadUserMessage, userMessageWithLinks]
1175
1160
  }),
1176
1161
  withParticipants: states_objectSpread(states_objectSpread({
1177
1162
  category: categoryKeys.messages,
@@ -1238,8 +1223,7 @@ const standardState = {
1238
1223
  id: (0,web_ui_namespaceObject.randomId)(),
1239
1224
  body: {
1240
1225
  text: 'Long ago when a dialog started',
1241
- type: 'text',
1242
- variables: {}
1226
+ type: 'text'
1243
1227
  }
1244
1228
  })
1245
1229
  }, participantMessage, participantMessageDefaultIcon, newTopicDivider, transcriptInfoMessage, ...[newTranslationDividerStart, newTranslationDividerStop].map(addTranslationData), infoMessage]
@@ -1283,8 +1267,7 @@ const standardState = {
1283
1267
  id: (0,web_ui_namespaceObject.randomId)(),
1284
1268
  body: {
1285
1269
  text: 'Long ago when a dialog started',
1286
- type: 'text',
1287
- variables: {}
1270
+ type: 'text'
1288
1271
  }
1289
1272
  })
1290
1273
  }, {
@@ -1294,8 +1277,7 @@ const standardState = {
1294
1277
  id: (0,web_ui_namespaceObject.randomId)(),
1295
1278
  body: {
1296
1279
  text: 'Above me should be a time indicator showing the full date',
1297
- type: 'text',
1298
- variables: {}
1280
+ type: 'text'
1299
1281
  }
1300
1282
  })
1301
1283
  }, {
@@ -1305,8 +1287,7 @@ const standardState = {
1305
1287
  id: (0,web_ui_namespaceObject.randomId)(),
1306
1288
  body: {
1307
1289
  text: 'Another message',
1308
- type: 'text',
1309
- variables: {}
1290
+ type: 'text'
1310
1291
  }
1311
1292
  })
1312
1293
  }, {
@@ -1316,8 +1297,7 @@ const standardState = {
1316
1297
  id: (0,web_ui_namespaceObject.randomId)(),
1317
1298
  body: {
1318
1299
  text: 'And another message',
1319
- type: 'text',
1320
- variables: {}
1300
+ type: 'text'
1321
1301
  }
1322
1302
  })
1323
1303
  }, {
@@ -1327,8 +1307,7 @@ const standardState = {
1327
1307
  id: (0,web_ui_namespaceObject.randomId)(),
1328
1308
  body: {
1329
1309
  text: 'Above me should be a time indicator showing "yesterday"',
1330
- type: 'text',
1331
- variables: {}
1310
+ type: 'text'
1332
1311
  }
1333
1312
  })
1334
1313
  }, {
@@ -1338,8 +1317,7 @@ const standardState = {
1338
1317
  id: (0,web_ui_namespaceObject.randomId)(),
1339
1318
  body: {
1340
1319
  text: 'Another message',
1341
- type: 'text',
1342
- variables: {}
1320
+ type: 'text'
1343
1321
  }
1344
1322
  })
1345
1323
  }, {
@@ -1349,8 +1327,7 @@ const standardState = {
1349
1327
  id: (0,web_ui_namespaceObject.randomId)(),
1350
1328
  body: {
1351
1329
  text: 'And another message',
1352
- type: 'text',
1353
- variables: {}
1330
+ type: 'text'
1354
1331
  }
1355
1332
  })
1356
1333
  }, {
@@ -1360,8 +1337,7 @@ const standardState = {
1360
1337
  id: (0,web_ui_namespaceObject.randomId)(),
1361
1338
  body: {
1362
1339
  text: 'Above me should be a time indicator showing me the dialog continues today',
1363
- type: 'text',
1364
- variables: {}
1340
+ type: 'text'
1365
1341
  }
1366
1342
  })
1367
1343
  }]
@@ -1798,6 +1774,26 @@ const inlineInterface = {
1798
1774
  })
1799
1775
  })
1800
1776
  },
1777
+ minimizedInlineCharacterLimit: {
1778
+ category: categoryKeys.minimizedInline,
1779
+ headingText: 'Inline minimized with limited characters',
1780
+ description: '',
1781
+ inline: states_objectSpread(states_objectSpread({}, baseState), {}, {
1782
+ config: states_objectSpread(states_objectSpread({}, baseState.config), {}, {
1783
+ layoutMode: 'inline'
1784
+ }),
1785
+ visibility: states_objectSpread(states_objectSpread({}, baseState.visibility), {}, {
1786
+ visibility: web_ui_namespaceObject.visibilityStates.minimized
1787
+ }),
1788
+ entryMeta: states_objectSpread(states_objectSpread({}, baseState.entryMeta), {}, {
1789
+ options: {
1790
+ text: {
1791
+ limit: 120
1792
+ }
1793
+ }
1794
+ })
1795
+ })
1796
+ },
1801
1797
  minimizedInlinePrechat: {
1802
1798
  category: categoryKeys.minimizedInline,
1803
1799
  headingText: 'Inline minimized with pre-chat messages',
@@ -1919,7 +1915,7 @@ const newInterface = {
1919
1915
  headingText: 'Suggestions message',
1920
1916
  description: ''
1921
1917
  }, baseState), {}, {
1922
- events: [{
1918
+ events: [getCustomMessage(shortTextMessage.payload.body), {
1923
1919
  type: 'service_data',
1924
1920
  payload: {
1925
1921
  type: 'suggestion',
@@ -2292,6 +2288,7 @@ const seamly_utils_seamlyActions = {
2292
2288
  CLEAR_EVENTS: 'CLEAR_EVENTS',
2293
2289
  SET_HISTORY: 'SET_HISTORY',
2294
2290
  SET_EVENTS_READ: 'SET_EVENTS_READ',
2291
+ SET_LOADED_IMAGE_EVENT_IDS: 'SET_LOADED_IMAGE_EVENT_IDS',
2295
2292
  ACK_EVENT: 'ACK_EVENT',
2296
2293
  SET_IS_LOADING: 'SET_IS_LOADING',
2297
2294
  CLEAR_PARTICIPANTS: 'CLEAR_PARTICIPANTS',
@@ -2337,6 +2334,7 @@ const {
2337
2334
  CLEAR_EVENTS,
2338
2335
  SET_HISTORY,
2339
2336
  SET_EVENTS_READ,
2337
+ SET_LOADED_IMAGE_EVENT_IDS,
2340
2338
  ACK_EVENT,
2341
2339
  SET_IS_LOADING,
2342
2340
  CLEAR_PARTICIPANTS,
@@ -2390,14 +2388,16 @@ const orderHistory = events => {
2390
2388
  };
2391
2389
 
2392
2390
  const mergeHistory = (stateEvents, historyEvents) => {
2393
- const newHistoryEvents = historyEvents.filter(historyEvent => // Deduplicate the event streams
2394
- !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
2395
2395
  !(historyEvent.type === 'participant' && !historyEvent.payload.participant.introduction)) // Reverse is done here because the server sends the history in the order
2396
2396
  // newest to oldest. In the case of exactly the same occurredAt timestamps
2397
2397
  // these messages will be shown in the wrong order if not reversed. For
2398
2398
  // the normal merging logic there is no added effect.
2399
2399
  .reverse();
2400
- return orderHistory([...newHistoryEvents, ...stateEvents]);
2400
+ return orderHistory([...newHistoryEvents, ...newStateEvents]);
2401
2401
  };
2402
2402
 
2403
2403
  const participantReducer = (state, action) => {
@@ -2576,6 +2576,7 @@ const seamlyStateReducer = (state, action) => {
2576
2576
  case CLEAR_EVENTS:
2577
2577
  return seamly_utils_objectSpread(seamly_utils_objectSpread({}, state), {}, {
2578
2578
  unreadEvents: 0,
2579
+ loadedImageEventIds: [],
2579
2580
  events: []
2580
2581
  });
2581
2582
 
@@ -2595,6 +2596,11 @@ const seamlyStateReducer = (state, action) => {
2595
2596
  })
2596
2597
  });
2597
2598
 
2599
+ case SET_LOADED_IMAGE_EVENT_IDS:
2600
+ return seamly_utils_objectSpread(seamly_utils_objectSpread({}, state), {}, {
2601
+ loadedImageEventIds: [...state.loadedImageEventIds, action.eventId]
2602
+ });
2603
+
2598
2604
  case SET_HISTORY:
2599
2605
  const {
2600
2606
  events: history,
@@ -2772,8 +2778,12 @@ const seamlyStateReducer = (state, action) => {
2772
2778
  });
2773
2779
 
2774
2780
  case SET_INITIAL_STATE:
2781
+ const {
2782
+ initialState
2783
+ } = action;
2775
2784
  return seamly_utils_objectSpread(seamly_utils_objectSpread({}, state), {}, {
2776
- initialState: action.initialState
2785
+ initialState,
2786
+ unreadEvents: initialState.unreadMessageCount
2777
2787
  });
2778
2788
 
2779
2789
  case SET_SERVICE_DATA_ITEM:
@@ -2986,7 +2996,7 @@ function createAction(type, identityReducer = payload => ({
2986
2996
 
2987
2997
  action.toString = () => String(type);
2988
2998
 
2989
- action.match = obj => (obj === null || obj === void 0 ? void 0 : obj.type) === String(type);
2999
+ action.match = obj => obj?.type === String(type);
2990
3000
 
2991
3001
  return action;
2992
3002
  }
@@ -3076,7 +3086,7 @@ function createThunk(type, payloadCreator) {
3076
3086
  }
3077
3087
  function createReducer(domain, handlers = {}, defaultState) {
3078
3088
  const reducer = (state = defaultState, action) => {
3079
- const typeReducer = handlers === null || handlers === void 0 ? void 0 : handlers[action === null || action === void 0 ? void 0 : action.type];
3089
+ const typeReducer = handlers?.[action?.type];
3080
3090
  return typeReducer ? typeReducer(state, action) : state;
3081
3091
  };
3082
3092
 
@@ -3507,7 +3517,7 @@ function selectors_defineProperty(obj, key, value) { if (key in obj) { Object.de
3507
3517
 
3508
3518
  const selectConfig = createSelector(selectState, config => {
3509
3519
  let newConfig = selectors_objectSpread({
3510
- visible: (config === null || config === void 0 ? void 0 : config.layoutMode) === 'inline' ? constants_visibilityStates.open : constants_visibilityStates.minimized,
3520
+ visible: config?.layoutMode === 'inline' ? constants_visibilityStates.open : constants_visibilityStates.minimized,
3511
3521
  appContainerClassNames: config.appContainerClassNames || []
3512
3522
  }, config);
3513
3523
 
@@ -3599,8 +3609,6 @@ function hooks_useSelector(selector, deps = []) {
3599
3609
  useLayoutEffect(() => {
3600
3610
  // we subscribe to the store changes
3601
3611
  return store.subscribe(() => {
3602
- var _selectorRef$current;
3603
-
3604
3612
  const newState = store.getState(); // prevent recalculating if the state hasn't changed
3605
3613
  // if the selector changed, it was already handled synchronously
3606
3614
 
@@ -3609,7 +3617,7 @@ function hooks_useSelector(selector, deps = []) {
3609
3617
  } // calculate the new value based on selector+state
3610
3618
 
3611
3619
 
3612
- const newValue = (_selectorRef$current = selectorRef.current) === null || _selectorRef$current === void 0 ? void 0 : _selectorRef$current.call(selectorRef, store.getState()); // only if the value changed we update. this saves heaps of re-rendering
3620
+ const newValue = selectorRef.current?.(store.getState()); // only if the value changed we update. this saves heaps of re-rendering
3613
3621
 
3614
3622
  if (newValue !== valueRef.current) {
3615
3623
  valueRef.current = newValue;
@@ -3672,9 +3680,7 @@ const selectEventsWithSuggestion = createSelector(seamly_state_hooks_selectState
3672
3680
  events,
3673
3681
  serviceData
3674
3682
  }, config, userHasResponded) => {
3675
- var _serviceData$suggesti;
3676
-
3677
- if (userHasResponded || config.layoutMode === 'inline' || !serviceData.suggestion || !((_serviceData$suggesti = serviceData.suggestion) !== null && _serviceData$suggesti !== void 0 && _serviceData$suggesti.body.length)) {
3683
+ if (userHasResponded || config.layoutMode === 'inline' || !serviceData.suggestion || !serviceData.suggestion?.body.length) {
3678
3684
  return events;
3679
3685
  }
3680
3686
 
@@ -3685,12 +3691,10 @@ const selectEventsWithSuggestion = createSelector(seamly_state_hooks_selectState
3685
3691
  return [...events, suggestionsEvent];
3686
3692
  });
3687
3693
  const selectEvents = createSelector(selectEventsWithSuggestion, selectConfig, (events, config) => {
3688
- var _config$messages;
3689
-
3690
3694
  const {
3691
3695
  enabled,
3692
3696
  threshold
3693
- } = (config === null || config === void 0 ? void 0 : (_config$messages = config.messages) === null || _config$messages === void 0 ? void 0 : _config$messages.timeIndicator) ?? {};
3697
+ } = config?.messages?.timeIndicator ?? {};
3694
3698
 
3695
3699
  if (!enabled) {
3696
3700
  return events;
@@ -3719,14 +3723,13 @@ const seamly_state_hooks_useEvents = () => useSelector(selectEvents, []);
3719
3723
  const useSeamlyIsLoading = () => seamly_state_hooks_useSeamlyStateContext().isLoading;
3720
3724
  const useSeamlyHeaderData = () => seamly_state_hooks_useSeamlyStateContext().headerTitles;
3721
3725
  const seamly_state_hooks_useSeamlyUnreadCount = () => seamly_state_hooks_useSeamlyStateContext().unreadEvents;
3726
+ const useLoadedImageEventIds = () => seamly_state_hooks_useSeamlyStateContext().loadedImageEventIds;
3722
3727
  const seamly_state_hooks_useSkiplink = () => seamly_state_hooks_useSeamlyStateContext().skiplinkTargetId;
3723
3728
  const useSeamlyParticipant = participantId => seamly_state_hooks_useSeamlyStateContext().participantInfo.participants[participantId];
3724
3729
  const useSeamlyServiceInfo = () => seamly_state_hooks_useSeamlyStateContext().serviceInfo;
3725
3730
  const selectLastMessageEventId = createSelector(selectEvents, events => {
3726
- var _filteredEvents;
3727
-
3728
3731
  const filteredEvents = events.filter(event => event.type === 'message');
3729
- return (_filteredEvents = filteredEvents[filteredEvents.length - 1]) === null || _filteredEvents === void 0 ? void 0 : _filteredEvents.payload.id;
3732
+ return filteredEvents[filteredEvents.length - 1]?.payload.id;
3730
3733
  });
3731
3734
  const useLastMessageEventId = () => useSelector(selectLastMessageEventId);
3732
3735
  const useSeamlyIsHistoryLoaded = () => seamly_state_hooks_useSeamlyStateContext().historyLoaded;
@@ -3743,18 +3746,23 @@ const useEntryTextLimit = () => {
3743
3746
  entryMeta: {
3744
3747
  options: {
3745
3748
  text
3749
+ },
3750
+ optionsOverride: {
3751
+ text: overrideText
3746
3752
  }
3747
3753
  }
3748
3754
  } = seamly_state_hooks_useSeamlyStateContext();
3749
3755
  const {
3750
3756
  limit
3751
- } = text || {};
3757
+ } = overrideText || text || {
3758
+ limit: null
3759
+ };
3752
3760
  return {
3753
- hasLimit: limit != null,
3754
- limit: limit != null ? limit : null
3761
+ hasLimit: limit !== null,
3762
+ limit: limit !== null ? limit : null
3755
3763
  };
3756
3764
  };
3757
- const useSeamlyLayoutMode = () => {
3765
+ const seamly_state_hooks_useSeamlyLayoutMode = () => {
3758
3766
  const {
3759
3767
  layoutMode
3760
3768
  } = useConfig();
@@ -3787,7 +3795,12 @@ const calculateVisibility = ({
3787
3795
  } = config;
3788
3796
  const {
3789
3797
  visible: defaultVisibility
3790
- } = 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
+
3791
3804
 
3792
3805
  if (layoutMode === 'window' && hideOnNoUserResponse && requestedVisibility !== constants_visibilityStates.open) {
3793
3806
  return hasResponded ? requestedVisibility || previousVisibility || constants_visibilityStates.open : constants_visibilityStates.hidden;
@@ -3806,6 +3819,7 @@ const calculateVisibility = ({
3806
3819
 
3807
3820
 
3808
3821
  const selectVisibility = createSelector(visibility_utils_selectState, state => state.visibility);
3822
+ const selectors_selectShowInlineView = createSelector(visibility_utils_selectState, state => state.showInlineView);
3809
3823
 
3810
3824
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/actions.js
3811
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; }
@@ -3823,6 +3837,7 @@ function actions_defineProperty(obj, key, value) { if (key in obj) { Object.defi
3823
3837
  const setFromStorage = visibility_utils_createAction('setFromStorage', visibility => ({
3824
3838
  visibility
3825
3839
  }));
3840
+ const setShowInlineView = visibility_utils_createAction('setShowInlineView');
3826
3841
  const validVisibilityStates = [constants_visibilityStates.open, constants_visibilityStates.minimized, constants_visibilityStates.hidden];
3827
3842
  const setVisibility = visibility_utils_createThunk('set', (requestedVisibility, {
3828
3843
  getState,
@@ -3883,13 +3898,11 @@ const actions_initialize = visibility_utils_createThunk('initialize', async (loc
3883
3898
  api
3884
3899
  }
3885
3900
  }) => {
3886
- var _api$store$get;
3887
-
3888
3901
  // initialize stored visibility
3889
3902
  const {
3890
3903
  layoutMode
3891
3904
  } = selectConfig(getState());
3892
- const storedVisibility = (_api$store$get = api.store.get(StoreKey)) === null || _api$store$get === void 0 ? void 0 : _api$store$get[layoutMode];
3905
+ const storedVisibility = api.store.get(StoreKey)?.[layoutMode];
3893
3906
 
3894
3907
  if (storedVisibility) {
3895
3908
  dispatch(setFromStorage(storedVisibility));
@@ -3927,13 +3940,13 @@ class SeamlyBaseError extends Error {
3927
3940
 
3928
3941
  this.originalError = originalError;
3929
3942
 
3930
- if (originalError !== null && originalError !== void 0 && originalError.payload) {
3943
+ if (originalError?.payload) {
3931
3944
  this.originalEvent = originalError;
3932
3945
  this.originalError = originalError.payload.error;
3933
3946
  this.message = `Event of type ${originalError.payload.type} encountered`;
3934
3947
  }
3935
3948
 
3936
- if (originalError !== null && originalError !== void 0 && originalError.error) {
3949
+ if (originalError?.error) {
3937
3950
  this.originalError = originalError.error;
3938
3951
  }
3939
3952
  }
@@ -3972,7 +3985,7 @@ const clear = interrupt_utils_createAction('clear');
3972
3985
 
3973
3986
 
3974
3987
 
3975
- const setHasResponded = app_utils_createAction('setHasResponded', hasResponded => ({
3988
+ const actions_setHasResponded = app_utils_createAction('setHasResponded', hasResponded => ({
3976
3989
  hasResponded
3977
3990
  }));
3978
3991
  const app_actions_initialize = app_utils_createThunk('initialize', async (_, {
@@ -3982,10 +3995,8 @@ const app_actions_initialize = app_utils_createThunk('initialize', async (_, {
3982
3995
  config
3983
3996
  }
3984
3997
  }) => {
3985
- var _config$context;
3986
-
3987
3998
  dispatch(initialize(config));
3988
- let locale = config === null || config === void 0 ? void 0 : (_config$context = config.context) === null || _config$context === void 0 ? void 0 : _config$context.locale;
3999
+ let locale = config?.context?.locale;
3989
4000
 
3990
4001
  try {
3991
4002
  const {
@@ -4012,7 +4023,7 @@ const app_actions_initialize = app_utils_createThunk('initialize', async (_, {
4012
4023
  startChatIcon
4013
4024
  }));
4014
4025
 
4015
- if (agentParticipant !== null && agentParticipant !== void 0 && agentParticipant.name) {
4026
+ if (agentParticipant?.name) {
4016
4027
  dispatch({
4017
4028
  type: seamly_utils_seamlyActions.SET_HEADER_SUB_TITLE,
4018
4029
  title: agentParticipant.name
@@ -4024,22 +4035,18 @@ const app_actions_initialize = app_utils_createThunk('initialize', async (_, {
4024
4035
 
4025
4036
  try {
4026
4037
  if (api.hasConversation()) {
4027
- var _initialState$transla;
4028
-
4029
4038
  const initialState = await api.getConversationIntitialState();
4030
4039
  dispatch({
4031
4040
  type: seamly_utils_seamlyActions.SET_INITIAL_STATE,
4032
4041
  initialState
4033
4042
  });
4034
- locale = ((_initialState$transla = initialState.translation) === null || _initialState$transla === void 0 ? void 0 : _initialState$transla.locale) || locale;
4043
+ locale = initialState.translation?.locale || locale;
4035
4044
 
4036
4045
  if ('userResponded' in initialState) {
4037
- dispatch(setHasResponded(initialState.userResponded));
4046
+ dispatch(actions_setHasResponded(initialState.userResponded));
4038
4047
  }
4039
4048
  } else {
4040
- var _config$context2, _config$context3;
4041
-
4042
- if (config !== null && config !== void 0 && (_config$context2 = config.context) !== null && _config$context2 !== void 0 && _config$context2.topic) {
4049
+ if (config?.context?.topic) {
4043
4050
  api.send('action', {
4044
4051
  type: seamly_utils_actionTypes.setTopic,
4045
4052
  body: {
@@ -4051,7 +4058,7 @@ const app_actions_initialize = app_utils_createThunk('initialize', async (_, {
4051
4058
  });
4052
4059
  }
4053
4060
 
4054
- if (config !== null && config !== void 0 && (_config$context3 = config.context) !== null && _config$context3 !== void 0 && _config$context3.translationLocale) {
4061
+ if (config?.context?.translationLocale) {
4055
4062
  locale = config.context.translationLocale;
4056
4063
  api.send('action', {
4057
4064
  type: seamly_utils_actionTypes.setTranslation,
@@ -4097,6 +4104,7 @@ const initialState = {
4097
4104
  events: [],
4098
4105
  initialState: {},
4099
4106
  unreadEvents: 0,
4107
+ loadedImageEventIds: [],
4100
4108
  isLoading: false,
4101
4109
  idleDetachCountdown: {
4102
4110
  hasCountdown: false,
@@ -4158,9 +4166,7 @@ function utils_validate(values, schema = {}) {
4158
4166
  validations = [validations];
4159
4167
  }
4160
4168
 
4161
- for (let i = 0; i < ((_validations = validations) === null || _validations === void 0 ? void 0 : _validations.length) ?? 0; i++) {
4162
- var _validations;
4163
-
4169
+ for (let i = 0; i < validations?.length ?? 0; i++) {
4164
4170
  if (!validations[i].fn(values[key], validations[i].compareValue)) {
4165
4171
  errors[key] = validations[i].errorText;
4166
4172
  break;
@@ -4220,7 +4226,7 @@ const getPropSelector = (propName, orDefault) => (_, props) => props[propName] |
4220
4226
 
4221
4227
  const getState = forms_utils_selectState;
4222
4228
  const selectors_getFormById = createSelector(getState, getPropSelector('formId'), (forms, formId) => forms[formId]);
4223
- const getFormControlsByFormId = createSelector(selectors_getFormById, form => (form === null || form === void 0 ? void 0 : form.controls) || {});
4229
+ const getFormControlsByFormId = createSelector(selectors_getFormById, form => form?.controls || {});
4224
4230
  const selectors_getFormValuesByFormId = createSelector(getFormControlsByFormId, controls => {
4225
4231
  const valuesObj = {};
4226
4232
  Object.entries(controls).forEach(([key, {
@@ -4230,16 +4236,8 @@ const selectors_getFormValuesByFormId = createSelector(getFormControlsByFormId,
4230
4236
  });
4231
4237
  return valuesObj;
4232
4238
  });
4233
- const selectors_getControlValueByName = createSelector(getFormControlsByFormId, getPropSelector('name'), (controls, name) => {
4234
- var _controls$name;
4235
-
4236
- return (_controls$name = controls[name]) === null || _controls$name === void 0 ? void 0 : _controls$name.value;
4237
- });
4238
- const selectors_getControlTouchedByName = createSelector(getFormControlsByFormId, getPropSelector('name'), (controls, name) => {
4239
- var _controls$name2;
4240
-
4241
- return (_controls$name2 = controls[name]) === null || _controls$name2 === void 0 ? void 0 : _controls$name2.touched;
4242
- });
4239
+ const selectors_getControlValueByName = createSelector(getFormControlsByFormId, getPropSelector('name'), (controls, name) => controls[name]?.value);
4240
+ const selectors_getControlTouchedByName = createSelector(getFormControlsByFormId, getPropSelector('name'), (controls, name) => controls[name]?.touched);
4243
4241
  ;// CONCATENATED MODULE: ./src/javascripts/domains/forms/context.js
4244
4242
 
4245
4243
  const context_FormContext = (0,external_preact_namespaceObject.createContext)({});
@@ -4299,7 +4297,7 @@ function hooks_useFormControl(name) {
4299
4297
  formId,
4300
4298
  name
4301
4299
  }, [formId, name]);
4302
- const error = errors === null || errors === void 0 ? void 0 : errors[name];
4300
+ const error = errors?.[name];
4303
4301
  const isValid = !error;
4304
4302
  useEffect(() => {
4305
4303
  // Make sure the form is registered
@@ -4351,6 +4349,7 @@ function provider_objectWithoutPropertiesLoose(source, excluded) { if (source ==
4351
4349
 
4352
4350
 
4353
4351
 
4352
+
4354
4353
  function provider_FormProvider(_ref) {
4355
4354
  let {
4356
4355
  children,
@@ -4400,21 +4399,19 @@ function provider_FormProvider(_ref) {
4400
4399
  });
4401
4400
  }, [setExternalErrors]);
4402
4401
  const handleSubmit = useCallback(e => {
4403
- var _e$submitter;
4404
-
4405
4402
  e.preventDefault(); // If the submitter is set to being aria-disabled, block the submit action
4406
4403
 
4407
- const ariaDisabled = ((_e$submitter = e.submitter) === null || _e$submitter === void 0 ? void 0 : _e$submitter.ariaDisabled) === 'true';
4404
+ const ariaDisabled = e.submitter?.ariaDisabled === 'true';
4408
4405
  setIsSubmitted(!ariaDisabled);
4409
4406
 
4410
4407
  if (!ariaDisabled && validationIsValid) {
4408
+ dispatch(setHasResponded(true));
4411
4409
  onSubmit(values, {
4412
4410
  updateControlValue,
4413
4411
  setError
4414
4412
  });
4415
4413
  }
4416
- }, [validationIsValid, onSubmit, values, updateControlValue, setError]); //
4417
-
4414
+ }, [validationIsValid, dispatch, onSubmit, values, updateControlValue, setError]);
4418
4415
  useEffect(() => {
4419
4416
  if (onError) {
4420
4417
  onError({
@@ -4471,9 +4468,7 @@ const initialControlState = {
4471
4468
  };
4472
4469
 
4473
4470
  function updateFormControl(state, formId, name, controlState) {
4474
- var _state$formId;
4475
-
4476
- const currentControlState = ((_state$formId = state[formId]) === null || _state$formId === void 0 ? void 0 : _state$formId.controls[name]) || initialControlState;
4471
+ const currentControlState = state[formId]?.controls[name] || initialControlState;
4477
4472
  return reducer_objectSpread(reducer_objectSpread({}, state), {}, {
4478
4473
  [formId]: reducer_objectSpread(reducer_objectSpread({}, state[formId]), {}, {
4479
4474
  controls: reducer_objectSpread(reducer_objectSpread({}, state[formId].controls), {}, {
@@ -4501,11 +4496,9 @@ function updateFormControl(state, formId, name, controlState) {
4501
4496
  [deregisterForm]: (state, {
4502
4497
  formId
4503
4498
  }) => {
4504
- var _newState$formId;
4505
-
4506
4499
  const newState = reducer_objectSpread({}, state);
4507
4500
 
4508
- if (!((_newState$formId = newState[formId]) !== null && _newState$formId !== void 0 && _newState$formId.persistData)) {
4501
+ if (!newState[formId]?.persistData) {
4509
4502
  delete newState[formId];
4510
4503
  }
4511
4504
 
@@ -4663,6 +4656,7 @@ function config_reducer_defineProperty(obj, key, value) { if (key in obj) { Obje
4663
4656
 
4664
4657
  const config_reducer_initialState = config_reducer_objectSpread(config_reducer_objectSpread({}, defaultConfig), {}, {
4665
4658
  hideOnNoUserResponse: false,
4659
+ connectWhenInView: true,
4666
4660
  showDisclaimer: false,
4667
4661
  showFaq: false,
4668
4662
  customComponents: {},
@@ -4670,7 +4664,7 @@ const config_reducer_initialState = config_reducer_objectSpread(config_reducer_o
4670
4664
  preChatEvents: []
4671
4665
  });
4672
4666
 
4673
- 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'];
4674
4668
 
4675
4669
  const updateState = (state, {
4676
4670
  config
@@ -5939,6 +5933,7 @@ function hooks_useUserHasResponded() {
5939
5933
 
5940
5934
 
5941
5935
 
5936
+
5942
5937
  const hooks_useVisibility = () => {
5943
5938
  const dispatch = useStoreDispatch();
5944
5939
  const visible = useSelector(Selectors.selectVisibility);
@@ -5954,6 +5949,69 @@ const hooks_useVisibility = () => {
5954
5949
  setVisibility
5955
5950
  };
5956
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
+ };
5957
6015
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/reducer.js
5958
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; }
5959
6017
 
@@ -5965,7 +6023,8 @@ function visibility_reducer_defineProperty(obj, key, value) { if (key in obj) {
5965
6023
 
5966
6024
 
5967
6025
  const visibility_reducer_initialState = {
5968
- visibility: constants_visibilityStates.initialize
6026
+ visibility: constants_visibilityStates.initialize,
6027
+ showInlineView: false
5969
6028
  };
5970
6029
  /* harmony default export */ const visibility_reducer = (visibility_utils_createReducer({
5971
6030
  [setFromStorage]: (state, {
@@ -5977,7 +6036,10 @@ const visibility_reducer_initialState = {
5977
6036
  payload: visibility
5978
6037
  }) => visibility ? visibility_reducer_objectSpread(visibility_reducer_objectSpread({}, state), {}, {
5979
6038
  visibility
5980
- }) : state
6039
+ }) : state,
6040
+ [setShowInlineView]: state => visibility_reducer_objectSpread(visibility_reducer_objectSpread({}, state), {}, {
6041
+ showInlineView: true
6042
+ })
5981
6043
  }, visibility_reducer_initialState));
5982
6044
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/index.js
5983
6045
 
@@ -6048,7 +6110,8 @@ const use_seamly_commands_useSeamlyCommands = () => {
6048
6110
  const hasResponded = useUserHasResponded();
6049
6111
  const hasConversation = useSeamlyHasConversation();
6050
6112
  const {
6051
- visible: visibility
6113
+ visible: visibility,
6114
+ setVisibility
6052
6115
  } = useVisibility();
6053
6116
  const unreadMessageCount = useSeamlyUnreadCount();
6054
6117
  const emitEvent = useCallback((...args) => {
@@ -6106,7 +6169,9 @@ const use_seamly_commands_useSeamlyCommands = () => {
6106
6169
  type: use_seamly_commands_ADD_EVENT,
6107
6170
  event: {
6108
6171
  type: 'message',
6109
- payload: message
6172
+ payload: use_seamly_commands_objectSpread(use_seamly_commands_objectSpread({}, message), {}, {
6173
+ optimisticallyInjected: true
6174
+ })
6110
6175
  }
6111
6176
  });
6112
6177
  }, [api, dispatch, emitEvent, getTextMessageBase]);
@@ -6204,11 +6269,16 @@ const use_seamly_commands_useSeamlyCommands = () => {
6204
6269
  type: use_seamly_commands_SET_INITIAL_STATE,
6205
6270
  initialState
6206
6271
  });
6272
+
6273
+ if (initialState.userResponded) {
6274
+ dispatch(AppActions.setHasResponded(initialState.userResponded));
6275
+ setVisibility(visibilityStates.open);
6276
+ }
6207
6277
  }
6208
6278
  }).catch(error => {
6209
6279
  dispatch(InterruptActions.set(error));
6210
6280
  });
6211
- }, [api, dispatch]);
6281
+ }, [api, dispatch, setVisibility]);
6212
6282
  return {
6213
6283
  connect,
6214
6284
  start,
@@ -6221,6 +6291,7 @@ const use_seamly_commands_useSeamlyCommands = () => {
6221
6291
  addMessageBubble,
6222
6292
  addUploadBubble,
6223
6293
  addDivider,
6294
+ apiConnected: api.connected,
6224
6295
  apiConfigReady: api.configReady
6225
6296
  };
6226
6297
  };
@@ -6350,11 +6421,12 @@ const useSeamlyEntry = () => {
6350
6421
  default: defaultEntry,
6351
6422
  active,
6352
6423
  userSelected,
6353
- options: entryOptions
6424
+ options: entryOptions,
6425
+ optionsOverride: entryOptionsOverride
6354
6426
  } = useSeamlyStateContext().entryMeta;
6355
6427
  const dispatch = useSeamlyDispatchContext();
6356
6428
  const activeEntry = userSelected || active || defaultEntry;
6357
- const activeEntryOptions = entryOptions[activeEntry] || {};
6429
+ const activeEntryOptions = entryOptionsOverride[activeEntry] || entryOptions[activeEntry] || {};
6358
6430
  const setBlockAutoEntrySwitch = useCallback(value => {
6359
6431
  dispatch({
6360
6432
  type: seamly_entry_hooks_SET_BLOCK_AUTO_ENTRY_SWITCH,
@@ -6400,6 +6472,7 @@ const useSeamlyEntry = () => {
6400
6472
 
6401
6473
 
6402
6474
 
6475
+
6403
6476
  const {
6404
6477
  SET_IS_LOADING: use_seamly_chat_SET_IS_LOADING
6405
6478
  } = seamly_utils_seamlyActions;
@@ -6409,28 +6482,31 @@ const useSeamlyChat = () => {
6409
6482
  t
6410
6483
  } = useI18n();
6411
6484
  const {
6412
- layoutMode
6413
- } = useConfig();
6485
+ isInline,
6486
+ isWindow
6487
+ } = useSeamlyLayoutMode();
6414
6488
  const {
6415
6489
  isOpen,
6416
6490
  isVisible,
6417
6491
  setVisibility
6418
6492
  } = useVisibility();
6493
+ const showInlineView = useSelector(selectShowInlineView);
6419
6494
  const dispatch = useSeamlyDispatchContext();
6420
6495
  const events = useEvents();
6421
6496
  const spinnerTimeout = useRef(null);
6422
6497
  const {
6423
6498
  start,
6424
6499
  connect,
6425
- apiConfigReady
6500
+ apiConfigReady,
6501
+ apiConnected
6426
6502
  } = useSeamlyCommands();
6427
6503
  const hasConversation = useSeamlyHasConversation();
6428
6504
  const prevIsOpen = useRef(null);
6429
6505
  const prevIsVisible = useRef(null);
6506
+ const startCalled = useRef(false);
6430
6507
  const {
6431
6508
  sendAssertive
6432
6509
  } = useLiveRegion();
6433
- const connectCalled = useRef(false);
6434
6510
  const hasEvents = events.length > 0;
6435
6511
  useEffect(() => {
6436
6512
  if (isVisible) {
@@ -6479,22 +6555,34 @@ const useSeamlyChat = () => {
6479
6555
  }
6480
6556
  }, [hasEvents, dispatch]);
6481
6557
  useEffect(() => {
6482
- // 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.
6483
6559
  // Mostly due to Interrupt situations and a reset being called.
6484
- if (!hasConversation || !apiConfigReady) {
6485
- connectCalled.current = false;
6560
+ if (!apiConfigReady || !apiConnected) {
6561
+ startCalled.current = false;
6562
+ }
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;
6486
6574
  }
6487
- }, [hasConversation, apiConfigReady]);
6575
+ }, [apiConnected, connect, isInline, isOpen, isVisible, start]);
6488
6576
  useEffect(() => {
6489
- // We don't connect minimised or hidden window interfaces unless
6490
- // they had been connected before.
6491
- // We also keep track of whether connect was called before to avoid
6492
- // multiple in-flight connection processes.
6493
- 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) {
6494
6582
  return;
6495
6583
  }
6496
6584
 
6497
- if (hasConversation) {
6585
+ if (hasConversation && isOpen) {
6498
6586
  // We deactivate the extra startup loading spinner when a conversation is available
6499
6587
  // We also stop setting the loading indicator in the first place to avoid a flash.
6500
6588
  clearTimeout(spinnerTimeout.current);
@@ -6504,11 +6592,8 @@ const useSeamlyChat = () => {
6504
6592
  });
6505
6593
  }
6506
6594
 
6507
- connect().then(() => {
6508
- start();
6509
- });
6510
- connectCalled.current = true;
6511
- }, [isOpen, hasConversation, apiConfigReady, start, connect, dispatch, layoutMode]);
6595
+ connectAndStart();
6596
+ }, [apiConfigReady, connectAndStart, dispatch, hasConversation, isInline, isOpen, isWindow, showInlineView]);
6512
6597
 
6513
6598
  const openChat = () => {
6514
6599
  setVisibility(visibilityStates.open);
@@ -6825,21 +6910,19 @@ function hooks_useTranslations() {
6825
6910
  function useTranslatedEventData({
6826
6911
  payload
6827
6912
  } = {}) {
6828
- var _translatedBody, _translatedBody2, _translatedBody3;
6829
-
6830
- const payloadId = payload === null || payload === void 0 ? void 0 : payload.id;
6913
+ const payloadId = payload?.id;
6831
6914
  let body;
6832
6915
  let translatedBody;
6833
6916
 
6834
- switch (payload === null || payload === void 0 ? void 0 : payload.type) {
6917
+ switch (payload?.type) {
6835
6918
  case 'participant':
6836
6919
  body = payload.participant.introduction;
6837
6920
  translatedBody = payload.participant.translatedIntroduction;
6838
6921
  break;
6839
6922
 
6840
6923
  default:
6841
- body = payload === null || payload === void 0 ? void 0 : payload.body;
6842
- translatedBody = payload === null || payload === void 0 ? void 0 : payload.translatedBody;
6924
+ body = payload?.body;
6925
+ translatedBody = payload?.translatedBody;
6843
6926
  }
6844
6927
 
6845
6928
  const hasTranslation = !!translatedBody;
@@ -6854,12 +6937,12 @@ function useTranslatedEventData({
6854
6937
  dispatch(Actions.enableEvent(payloadId));
6855
6938
  }
6856
6939
  }, [isTranslated, payloadId, dispatch]);
6857
- return [hasTranslation && isTranslated ? (_translatedBody = translatedBody) === null || _translatedBody === void 0 ? void 0 : _translatedBody.data : body, {
6940
+ return [hasTranslation && isTranslated ? translatedBody?.data : body, {
6858
6941
  hasTranslation,
6859
6942
  isTranslated: isTranslated && hasTranslation,
6860
6943
  toggleTranslation,
6861
- translatedBy: (_translatedBody2 = translatedBody) === null || _translatedBody2 === void 0 ? void 0 : _translatedBody2.translatedBy,
6862
- locale: (_translatedBody3 = translatedBody) === null || _translatedBody3 === void 0 ? void 0 : _translatedBody3.locale
6944
+ translatedBy: translatedBody?.translatedBy,
6945
+ locale: translatedBody?.locale
6863
6946
  }];
6864
6947
  }
6865
6948
  function hooks_useTranslationsContainer() {
@@ -6874,11 +6957,7 @@ function hooks_useLocaleNativeName(locale) {
6874
6957
  const {
6875
6958
  languages
6876
6959
  } = hooks_useTranslations();
6877
- return useMemo(() => {
6878
- var _languages$find;
6879
-
6880
- return languages === null || languages === void 0 ? void 0 : (_languages$find = languages.find(lang => lang.locale === locale)) === null || _languages$find === void 0 ? void 0 : _languages$find.nativeName;
6881
- }, [locale, languages]);
6960
+ return useMemo(() => languages?.find(lang => lang.locale === locale)?.nativeName, [locale, languages]);
6882
6961
  }
6883
6962
  ;// CONCATENATED MODULE: ./src/javascripts/domains/translations/middleware.js
6884
6963
 
@@ -6889,20 +6968,18 @@ function middleware_createMiddleware() {
6889
6968
  dispatch,
6890
6969
  getState
6891
6970
  }) => next => action => {
6892
- var _action$history, _action$history$trans, _action$initialState, _action$initialState$, _action$event, _action$event$payload, _action$event$payload2;
6893
-
6894
6971
  const result = next(action);
6895
6972
 
6896
6973
  switch (action.type) {
6897
6974
  case String(seamlyActions.SET_HISTORY):
6898
- if ((_action$history = action.history) !== null && _action$history !== void 0 && (_action$history$trans = _action$history.translation) !== null && _action$history$trans !== void 0 && _action$history$trans.enabled) {
6975
+ if (action.history?.translation?.enabled) {
6899
6976
  dispatch(Actions.enable(action.history.translation.locale));
6900
6977
  }
6901
6978
 
6902
6979
  break;
6903
6980
 
6904
6981
  case String(seamlyActions.SET_INITIAL_STATE):
6905
- if ((_action$initialState = action.initialState) !== null && _action$initialState !== void 0 && (_action$initialState$ = _action$initialState.translation) !== null && _action$initialState$ !== void 0 && _action$initialState$.enabled) {
6982
+ if (action.initialState?.translation?.enabled) {
6906
6983
  dispatch(Actions.enable(action.initialState.translation.locale));
6907
6984
  dispatch(I18nActions.setLocale(action.locale));
6908
6985
  }
@@ -6910,7 +6987,7 @@ function middleware_createMiddleware() {
6910
6987
  break;
6911
6988
 
6912
6989
  case String(seamlyActions.ADD_EVENT):
6913
- if (action.event.type === 'info' && ((_action$event = action.event) === null || _action$event === void 0 ? void 0 : (_action$event$payload = _action$event.payload) === null || _action$event$payload === void 0 ? void 0 : (_action$event$payload2 = _action$event$payload.body) === null || _action$event$payload2 === void 0 ? void 0 : _action$event$payload2.subtype) === 'new_translation' && action.event.payload.body.translationEnabled) {
6990
+ if (action.event.type === 'info' && action.event?.payload?.body?.subtype === 'new_translation' && action.event.payload.body.translationEnabled) {
6914
6991
  dispatch(I18nActions.setLocale(action.event.payload.body.translationLocale));
6915
6992
  }
6916
6993
 
@@ -6947,9 +7024,7 @@ const translations_reducer_initialState = {
6947
7024
  };
6948
7025
  /* harmony default export */ const translations_reducer = (translations_utils_createReducer({
6949
7026
  [seamly_utils_seamlyActions.SET_FEATURES]: (state, action) => {
6950
- var _action$features;
6951
-
6952
- const feature = action === null || action === void 0 ? void 0 : (_action$features = action.features) === null || _action$features === void 0 ? void 0 : _action$features.translation;
7027
+ const feature = action?.features?.translation;
6953
7028
 
6954
7029
  if (!feature) {
6955
7030
  return state;
@@ -7992,7 +8067,7 @@ const app_reducer_initialState = {
7992
8067
  userHasResponded: false
7993
8068
  };
7994
8069
  /* harmony default export */ const app_reducer = (app_utils_createReducer({
7995
- [setHasResponded]: (state, {
8070
+ [actions_setHasResponded]: (state, {
7996
8071
  hasResponded
7997
8072
  }) => app_reducer_objectSpread(app_reducer_objectSpread({}, state), {}, {
7998
8073
  userHasResponded: hasResponded
@@ -8340,6 +8415,7 @@ const StyleGuideApp = ({
8340
8415
 
8341
8416
  const updatedState = app_objectSpread(app_objectSpread({}, bareState), {}, {
8342
8417
  config: app_objectSpread(app_objectSpread(app_objectSpread(app_objectSpread({}, bareState.config), config), {}, {
8418
+ showDisclaimer: bareState.config.showDisclaimer || config.showDisclaimer,
8343
8419
  layoutMode: bareState.config.layoutMode
8344
8420
  }, overrideMessages ? {
8345
8421
  messages: overrideMessages
@@ -8347,7 +8423,7 @@ const StyleGuideApp = ({
8347
8423
  showFaq
8348
8424
  }),
8349
8425
  headerTitles: app_objectSpread(app_objectSpread({}, bareState.headerTitles), {}, {
8350
- subTitle: (agent === null || agent === void 0 ? void 0 : agent.name) || bareState.headerTitles.subTitle
8426
+ subTitle: agent?.name || bareState.headerTitles.subTitle
8351
8427
  })
8352
8428
  });
8353
8429