@telia-ace/widget-conversation 1.0.14 → 1.0.17

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.
@@ -29,12 +29,12 @@ var __objRest = (source, exclude) => {
29
29
  }
30
30
  return target;
31
31
  };
32
- import { Input, Button, borderTabStyle, SymbolBadge, useDispatch, useProperties, useScroll, Typography, useComponent, invertedHoverButton, Html, List, buttonCss, Icon, Lightbox, useTransitionEnd, headingElement } from "@telia-ace/widget-ui";
32
+ import { Input, Button, borderTabStyle, SymbolBadge, useDispatch, useProperties, useScroll, Typography, Html as Html$1, genericHtml, Lightbox, ItemList, itemList, buttonCss, useComponent, List, list, invertedHoverButton, usePrevious, useTransitionEnd, headingElement } from "@telia-ace/widget-ui";
33
33
  import { appendClassNames, uuid } from "@telia-ace/widget-utilities";
34
- import React, { useState, useEffect, Suspense, Fragment, useRef, useCallback } from "react";
34
+ import React, { useState, useEffect, Suspense, useRef, useCallback } from "react";
35
35
  import styled, { css, keyframes } from "styled-components";
36
- import { FormComponent } from "@telia-ace/widget-forms";
37
36
  import { ConversationMessageListItemType, ConversationMessageType } from "./index.js";
37
+ import { FormComponent } from "@telia-ace/widget-forms";
38
38
  import "@telia-ace/widget-core";
39
39
  import "@telia-ace/widget-services";
40
40
  import "@telia-ace/widget-plugins";
@@ -82,7 +82,7 @@ const ConversationInput = ({ className }) => {
82
82
  return;
83
83
  }
84
84
  e.preventDefault();
85
- dispatch("action", secondaryAction.action);
85
+ dispatch("action", secondaryAction);
86
86
  };
87
87
  const calculateHeight = (value) => {
88
88
  if (multiline && inputRef.current) {
@@ -117,13 +117,13 @@ const ConversationInput = ({ className }) => {
117
117
  className: appendClassNames("humany-conversation-input", className),
118
118
  "data-has-focus": inputFocus,
119
119
  scrollableCss
120
- }, secondaryAction && /* @__PURE__ */ React.createElement(StyledButton, {
120
+ }, secondaryAction && /* @__PURE__ */ React.createElement(SecondaryActionButton, {
121
121
  disabled: inputDisabled,
122
122
  onClick: onSecondaryActionButtonClick,
123
123
  title: secondaryAction.label,
124
124
  "aria-label": secondaryAction.label
125
125
  }, /* @__PURE__ */ React.createElement(SymbolBadge, {
126
- size: 22,
126
+ size: 24,
127
127
  symbol: { type: "Svg", content: secondaryAction.icon || "browse" }
128
128
  })), multiline ? /* @__PURE__ */ React.createElement(StyledTextArea, {
129
129
  value: inputText,
@@ -164,13 +164,10 @@ const StyledTextArea = styled(Input)`
164
164
  line-height: 1.2em;
165
165
  height: 1.2em;
166
166
  padding: 0;
167
- margin: ${(p) => {
167
+ margin: calc(${(p) => {
168
168
  var _a;
169
169
  return (_a = p.theme.sizes) == null ? void 0 : _a.small;
170
- }} ${(p) => {
171
- var _a;
172
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
173
- }};
170
+ }} * 2);
174
171
  font-size: ${(p) => {
175
172
  var _a;
176
173
  return (_a = p.theme.fonts) == null ? void 0 : _a.normal;
@@ -222,6 +219,13 @@ const StyledButton = styled(Button)`
222
219
  }};
223
220
  }
224
221
  `;
222
+ const SecondaryActionButton = styled(StyledButton)`
223
+ border-right: ${(p) => p.theme.border};
224
+ margin: ${(p) => {
225
+ var _a;
226
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
227
+ }} 0;
228
+ `;
225
229
  const Wrapper$1 = styled.div`
226
230
  ${(p) => p.grow ? css`
227
231
  min-height: 50px;
@@ -349,7 +353,6 @@ const Loader = styled.div`
349
353
  const ContentBundle = styled.div`
350
354
  grid-area: content;
351
355
  max-width: 100%;
352
- overflow: hidden;
353
356
  `;
354
357
  const MessageTitle = styled(Typography)`
355
358
  font-size: ${(p) => {
@@ -363,35 +366,14 @@ const MessageContainer = styled.div`
363
366
  display: flex;
364
367
  `;
365
368
  const MessageContent = styled.div`
366
- background-color: ${(p) => {
367
- var _a, _b;
368
- return p.user ? (_a = p.theme.colors) == null ? void 0 : _a.primary : (_b = p.theme.colors) == null ? void 0 : _b.accent;
369
- }};
370
- color: ${(p) => {
371
- var _a, _b;
372
- return p.user ? (_a = p.theme.colors) == null ? void 0 : _a.accent : (_b = p.theme.colors) == null ? void 0 : _b.text;
373
- }};
374
- border-radius: 5px; // TODO: prop?
375
- border: 1px solid rgb(231, 231, 231);
376
- padding-top: calc(${(p) => {
377
- var _a;
378
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
379
- }} - ${(p) => {
380
- var _a;
381
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
382
- }});
383
- padding-bottom: calc(${(p) => {
384
- var _a;
385
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
386
- }} - ${(p) => {
387
- var _a;
388
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
389
- }});
369
+ ${(p) => !p.user && nonUserMessageStyling(p.stacked, p.theme)}
370
+ ${(p) => p.user && userMessageStyling(p.stacked, p.theme)}
371
+
372
+ display: inline-block;
390
373
  margin-top: ${(p) => {
391
374
  var _a;
392
375
  return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
393
376
  }};
394
- display: inline-block;
395
377
  && > * {
396
378
  overflow-wrap: break-word;
397
379
  word-wrap: break-word;
@@ -401,39 +383,56 @@ const MessageContent = styled.div`
401
383
  }
402
384
  max-width: 100%;
403
385
  ${(p) => p.fullWidth && "width: 100%;"}
386
+ `;
387
+ const nonUserMessageStyling = (stacked, theme) => {
388
+ var _a, _b;
389
+ const colors = css`
390
+ background-color: ${(_a = theme.colors) == null ? void 0 : _a.accent};
391
+ color: ${(_b = theme.colors) == null ? void 0 : _b.text};
392
+ ${theme.border && `border: ${theme.border};`};
393
+ `;
394
+ if (!theme.borderRadius) {
395
+ return colors;
396
+ }
397
+ return css`
398
+ ${colors}
404
399
 
405
- ${(p) => !p.user && css`
406
- border: ${p.theme.border};
407
- `}
408
- ${(p) => p.user && "margin-left: auto"};
400
+ border-top-right-radius: ${theme.borderRadius};
401
+ border-bottom-right-radius: ${theme.borderRadius};
409
402
 
410
- ${(p) => p.stacked === "first" && p.user && css`
411
- border-bottom-right-radius: 1px; // TODO: Prop?
412
- `}
413
- ${(p) => p.stacked === "middle" && p.user && css`
414
- border-bottom-right-radius: 1px;
415
- border-top-right-radius: 1px;
416
- `}
417
- ${(p) => p.stacked === "last" && p.user && css`
418
- border-top-right-radius: 1px;
403
+ ${stacked === "first" && `
404
+ border-top-left-radius: ${theme.borderRadius};
419
405
  `}
420
- ${(p) => p.stacked === "first" && !p.user && css`
421
- border-bottom-left-radius: 1px;
422
- `}
423
- ${(p) => p.stacked === "middle" && !p.user && css`
424
- border-bottom-left-radius: 1px;
425
- border-top-left-radius: 1px;
406
+
407
+ ${stacked === "last" && `
408
+ border-bottom-left-radius: ${theme.borderRadius};
426
409
  `}
427
- ${(p) => p.stacked === "last" && !p.user && css`
428
- border-top-left-radius: 1px;
429
- `};
410
+ `;
411
+ };
412
+ const userMessageStyling = (stacked, theme) => {
413
+ var _a, _b;
414
+ const colors = css`
415
+ background-color: ${(_a = theme.colors) == null ? void 0 : _a.primary};
416
+ color: ${(_b = theme.colors) == null ? void 0 : _b.accent};
417
+ `;
418
+ if (!theme.borderRadius) {
419
+ return colors;
420
+ }
421
+ return css`
422
+ ${colors}
430
423
 
431
- ${(p) => !p.stacked && css`
432
- ${p.user ? "border-bottom-right-radius: 1px;" : "border-bottom-left-radius: 1px;"}
433
- `};
424
+ border-top-left-radius: ${theme.borderRadius};
425
+ border-bottom-left-radius: ${theme.borderRadius};
434
426
 
435
- transition: border-radius 500ms linear;
436
- `;
427
+ ${stacked === "first" && `
428
+ border-top-right-radius: ${theme.borderRadius};
429
+ `}
430
+
431
+ ${stacked === "last" && `
432
+ border-bottom-right-radius: ${theme.borderRadius};
433
+ `}
434
+ `;
435
+ };
437
436
  const MessageContentPart = styled.div`
438
437
  padding: ${(p) => {
439
438
  var _a;
@@ -455,190 +454,276 @@ const MessageContentPart = styled.div`
455
454
  margin-bottom: 0;
456
455
  }
457
456
  `;
457
+ const messageContentPadding = css`
458
+ margin: ${(p) => {
459
+ var _a;
460
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
461
+ }} 0;
462
+ padding: 0 ${(p) => {
463
+ var _a;
464
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
465
+ }};
466
+ `;
458
467
  const ConversationLoader = ({ className, agentData }) => {
459
468
  return /* @__PURE__ */ React.createElement(ContentBundle, null, /* @__PURE__ */ React.createElement(MessageContainer, null, /* @__PURE__ */ React.createElement(MessageContent, null, /* @__PURE__ */ React.createElement(Loader, null, /* @__PURE__ */ React.createElement("div", null), /* @__PURE__ */ React.createElement("div", null), /* @__PURE__ */ React.createElement("div", null)))));
460
469
  };
461
- const StyledTimestamp = styled.p`
462
- && {
463
- font-size: ${(p) => {
470
+ const imageLightboxRenderer$1 = (attrs) => /* @__PURE__ */ React.createElement(Lightbox, {
471
+ attrs
472
+ });
473
+ const htmlParseInstructions$1 = {
474
+ transform: {
475
+ img: imageLightboxRenderer$1
476
+ }
477
+ };
478
+ const Html = ({ body }) => {
479
+ return /* @__PURE__ */ React.createElement(StyledHtml, {
480
+ html: body,
481
+ htmlParseInstruction: htmlParseInstructions$1
482
+ });
483
+ };
484
+ const StyledHtml = styled(Html$1)`
485
+ ${genericHtml}
486
+ color: inherit;
487
+ white-space: pre-wrap;
488
+ ${messageContentPadding}
489
+ a {
490
+ color: ${(p) => p.theme.colors.link};
491
+ &:focus {
492
+ ${(p) => {
464
493
  var _a;
465
- return (_a = p.theme.fonts) == null ? void 0 : _a.small;
494
+ return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && borderTabStyle;
466
495
  }};
467
- font-weight: 300;
496
+ }
468
497
  }
469
- padding-top: ${(p) => {
498
+ `;
499
+ const mapActions = (actions) => Array.isArray(actions) ? actions : Object.keys(actions).map((i) => {
500
+ return {
501
+ label: actions[i],
502
+ actionKey: i
503
+ };
504
+ });
505
+ const ButtonList = ({ header, actions, dispatch }) => {
506
+ return /* @__PURE__ */ React.createElement(StyledButtonList, {
507
+ header,
508
+ items: mapActions(actions),
509
+ renderItem: (item) => {
510
+ return /* @__PURE__ */ React.createElement("li", {
511
+ key: item.actionKey
512
+ }, /* @__PURE__ */ React.createElement(StyledButtonListButton, {
513
+ onClick: () => {
514
+ dispatch("action", item);
515
+ },
516
+ "aria-label": item.label,
517
+ title: item.label
518
+ }, /* @__PURE__ */ React.createElement(SymbolBadge, {
519
+ symbol: item.symbol
520
+ }), item.label));
521
+ }
522
+ });
523
+ };
524
+ const StyledButtonList = styled(ItemList)`
525
+ ${itemList}
526
+ > ul {
527
+ display: flex;
528
+ flex-wrap: wrap;
529
+ gap: ${(p) => {
470
530
  var _a;
471
- return (_a = p.theme.sizes) == null ? void 0 : _a.small;
531
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
472
532
  }};
473
- margin: 0;
474
- line-height: 1.5em;
475
- grid-area: info;
476
- color: ${(p) => {
533
+ > li {
534
+ margin: 0;
535
+ }
536
+ }
537
+ ${messageContentPadding}
538
+ `;
539
+ const StyledButtonListButton = styled(Button)`
540
+ ${buttonCss};
541
+
542
+ display: block;
543
+ padding: ${(p) => {
477
544
  var _a;
478
- return (_a = p.theme.colors) == null ? void 0 : _a.text;
545
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
546
+ }};
547
+ background-color: ${(p) => {
548
+ var _a;
549
+ return (_a = p.theme.colors) == null ? void 0 : _a.primary;
550
+ }};
551
+ width: 100%;
552
+ color: #ffffff;
553
+ &:focus {
554
+ ${(p) => {
555
+ var _a;
556
+ return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && css`
557
+ ${borderTabStyle}
558
+ background-color: transparent;
559
+ `;
560
+ }}
561
+ }
562
+
563
+ i,
564
+ svg {
565
+ margin-right: ${(p) => {
566
+ var _a;
567
+ return (_a = p.theme.sizes) == null ? void 0 : _a.small;
479
568
  }};
480
- `;
481
- const getTimestamp = (raw) => {
482
- return new Date(raw).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
483
- };
484
- const Timestamp = ({ className, name, timestamp }) => {
485
- if (!name && !timestamp) {
486
- return null;
487
- }
488
- let output = "";
489
- if (name) {
490
- if (timestamp) {
491
- output = `${name}: ${getTimestamp(timestamp)}`;
492
- } else {
493
- output = name;
494
569
  }
495
- } else if (timestamp) {
496
- output = getTimestamp(timestamp);
497
- }
498
- return /* @__PURE__ */ React.createElement(StyledTimestamp, null, output);
499
- };
500
- const AgentMessage = ({ className, children, sender, timestamp }) => {
501
- const { avatar, name } = sender;
502
- const { avatarSize } = useProperties();
503
- return /* @__PURE__ */ React.createElement(StyledAgentMessage, {
504
- hasAvatar: !!avatar,
505
- className: appendClassNames(className, "humany-conversation-agent-message")
506
- }, avatar && /* @__PURE__ */ React.createElement(Avatar, {
507
- avatarSize
508
- }, typeof avatar === "string" ? /* @__PURE__ */ React.createElement("img", {
509
- src: avatar
510
- }) : /* @__PURE__ */ React.createElement(SymbolBadge, {
511
- symbol: avatar
512
- })), children, /* @__PURE__ */ React.createElement(Timestamp, {
513
- name,
514
- timestamp
515
- }));
516
- };
517
- const StyledAgentMessage = styled.div`
518
- display: grid;
519
- margin-right: 10%;
520
- width: 90%;
521
- ${(p) => p.hasAvatar ? css`
522
- grid-template-columns: auto 1fr;
523
- grid-template-rows: 1fr auto;
524
- grid-template-areas:
525
- 'avatar content'
526
- '. info';
527
- ` : css`
528
- grid-template-columns: 1fr;
529
- grid-template-rows: 1fr auto;
530
- grid-template-areas:
531
- 'content'
532
- 'info';
533
- `};
534
570
  `;
535
- const CustomMessage = (props) => {
536
- const CustomComponent = useComponent(props.type);
537
- if (!CustomComponent) {
571
+ const Custom = ({ type, content = {} }) => {
572
+ const Component = useComponent(type);
573
+ if (!Component || !type) {
538
574
  return null;
539
575
  }
540
576
  return /* @__PURE__ */ React.createElement(Suspense, {
541
577
  fallback: null
542
- }, /* @__PURE__ */ React.createElement(MessageContent, {
543
- user: props.isUser,
544
- stacked: !!props.stacked && props.stacked,
545
- fullWidth: !!props.content.form || !!props.content.actions
546
- }, /* @__PURE__ */ React.createElement(MessageContentPart, {
547
- noPadding: !!props.content.noPadding && props.content.noPadding
548
- }, /* @__PURE__ */ React.createElement(CustomComponent, __spreadValues({}, props.content)))));
578
+ }, /* @__PURE__ */ React.createElement(Component, __spreadValues({}, content)));
549
579
  };
550
- const SystemMessage = ({
551
- className,
552
- children,
553
- timestamp,
554
- discrete,
555
- fullWidth
556
- }) => {
557
- return /* @__PURE__ */ React.createElement(StyledSystemMessage, {
558
- className: appendClassNames(className, "humany-conversation-system-message"),
559
- fullWidth
560
- }, discrete ? /* @__PURE__ */ React.createElement(Discrete, {
561
- className: "humany-conversation-discrete-message"
562
- }, children, /* @__PURE__ */ React.createElement(Timestamp, {
563
- timestamp
564
- })) : /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement(Timestamp, {
565
- timestamp
566
- })));
580
+ const LinkList = ({ header, actions, dispatch }) => {
581
+ return /* @__PURE__ */ React.createElement(StyledLinkList, {
582
+ header,
583
+ items: mapActions(actions),
584
+ renderItem: (item) => {
585
+ return /* @__PURE__ */ React.createElement("li", {
586
+ key: item.actionKey
587
+ }, /* @__PURE__ */ React.createElement(StyledLinkButton, {
588
+ help: item.actionKey === "help",
589
+ onClick: () => {
590
+ dispatch("action", item);
591
+ },
592
+ "aria-label": item.label,
593
+ title: item.label
594
+ }, item.label, item.actionKey === "help" && /* @__PURE__ */ React.createElement(SymbolBadge, {
595
+ size: 14,
596
+ symbol: {
597
+ type: "Svg",
598
+ content: "caret-down"
599
+ }
600
+ })));
601
+ }
602
+ });
567
603
  };
568
- const StyledSystemMessage = styled.div`
569
- ${(p) => p.fullWidth && "width: 100%"};
570
- padding: 0 ${(p) => {
604
+ const StyledLinkList = styled(ItemList)`
605
+ ${itemList}
606
+ ${messageContentPadding}
607
+ > ul {
608
+ display: flex;
609
+ flex-direction: column;
610
+ gap: ${(p) => {
571
611
  var _a;
572
- return (_a = p.theme.sizes) == null ? void 0 : _a.large;
612
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
573
613
  }};
574
- overflow: auto;
614
+ > li {
615
+ margin: 0;
616
+ }
617
+ }
575
618
  `;
576
- const Discrete = styled.div`
577
- text-align: center;
578
- word-wrap: break-word;
579
- font-size: ${(p) => {
580
- var _a;
581
- return (_a = p.theme.fonts) == null ? void 0 : _a.normal;
582
- }};
619
+ const StyledLinkButton = styled(Button)`
620
+ display: block;
621
+ text-align: left;
622
+ font-weight: 300;
583
623
  color: ${(p) => {
584
624
  var _a;
585
- return (_a = p.theme.colors) == null ? void 0 : _a.text;
625
+ return (_a = p.theme.colors) == null ? void 0 : _a.primary;
626
+ }};
627
+
628
+ ${(p) => {
629
+ var _a, _b;
630
+ return p.help && css`
631
+ color: ${(_a = p.theme.colors) == null ? void 0 : _a.text};
632
+ text-decoration: underline;
633
+
634
+ i,
635
+ svg {
636
+ margin-left: ${(_b = p.theme.sizes) == null ? void 0 : _b.small};
637
+ }
638
+ `;
639
+ }}
640
+
641
+ &:focus {
642
+ ${(p) => {
643
+ var _a, _b;
644
+ return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && css`
645
+ ${borderTabStyle}
646
+ span {
647
+ color: ${(_b = p.theme.colors) == null ? void 0 : _b.primary};
648
+ text-decoration: underline;
649
+ }
650
+ `;
586
651
  }};
587
- > p {
588
- margin: 0;
589
652
  }
590
653
  `;
591
- const UserMessage = ({ className, children, timestamp }) => {
592
- const { userLabel = "" } = useProperties();
593
- return /* @__PURE__ */ React.createElement(StyledUserMessage, {
594
- className: appendClassNames(className, "humany-conversation-user-message")
595
- }, children, /* @__PURE__ */ React.createElement(Timestamp, {
596
- name: userLabel,
597
- timestamp
598
- }));
654
+ const Separator = () => {
655
+ return /* @__PURE__ */ React.createElement(StyledSeparator, null);
599
656
  };
600
- const StyledUserMessage = styled.div`
601
- margin-left: 10%;
602
- width: 90%;
603
- display: flex;
604
- flex-direction: column;
605
- align-items: flex-end;
657
+ const StyledSeparator = styled.div`
658
+ ${(p) => p.theme.border && `border-bottom: ${p.theme.border};`}
659
+ width: 100%;
606
660
  `;
607
- const CustomMessageListItem = ({ type, content = {} }) => {
608
- const Component = useComponent(type);
609
- if (!Component || !type) {
610
- return null;
611
- }
612
- return /* @__PURE__ */ React.createElement(Component, __spreadValues({}, content));
661
+ const Text = ({ text }) => {
662
+ return /* @__PURE__ */ React.createElement(StyledTypography, {
663
+ variant: "span"
664
+ }, text);
613
665
  };
614
- const imageLightboxRenderer$1 = (attrs) => /* @__PURE__ */ React.createElement(Lightbox, {
615
- attrs
616
- });
617
- const htmlParseInstructions$1 = {
618
- transform: {
619
- img: imageLightboxRenderer$1
620
- }
666
+ const StyledTypography = styled(Typography)`
667
+ ${messageContentPadding}
668
+ `;
669
+ const mapItem = ([type, content]) => {
670
+ return { type, content, id: uuid() };
621
671
  };
672
+ const MessageList = ({ items, dispatch }) => {
673
+ return /* @__PURE__ */ React.createElement(StyledList, {
674
+ items: items.map(mapItem),
675
+ renderLi: true,
676
+ renderItem: (item) => {
677
+ switch (item.type) {
678
+ case ConversationMessageListItemType.Text: {
679
+ return /* @__PURE__ */ React.createElement(Text, {
680
+ text: item.content
681
+ });
682
+ }
683
+ case ConversationMessageListItemType.HTML: {
684
+ return /* @__PURE__ */ React.createElement(Html, __spreadValues({}, item.content));
685
+ }
686
+ case ConversationMessageListItemType.Separator: {
687
+ return /* @__PURE__ */ React.createElement(Separator, __spreadValues({}, item.content));
688
+ }
689
+ case ConversationMessageListItemType.LinkList: {
690
+ return /* @__PURE__ */ React.createElement(LinkList, __spreadProps(__spreadValues({}, item.content), {
691
+ dispatch
692
+ }));
693
+ }
694
+ case ConversationMessageListItemType.ButtonList: {
695
+ return /* @__PURE__ */ React.createElement(ButtonList, __spreadProps(__spreadValues({}, item.content), {
696
+ dispatch
697
+ }));
698
+ }
699
+ default: {
700
+ return /* @__PURE__ */ React.createElement(Custom, {
701
+ type: item.type,
702
+ content: item.content
703
+ });
704
+ }
705
+ }
706
+ }
707
+ });
708
+ };
709
+ const StyledList = styled(List)`
710
+ ${list}
711
+
712
+ > li {
713
+ margin: 0;
714
+ }
715
+ `;
622
716
  const ConversationContent = ({ content, isUser, stacked }) => {
623
717
  const dispatch = useDispatch();
624
- const { title, body, actions, form, type, items } = content;
625
- if (type)
626
- return /* @__PURE__ */ React.createElement(CustomMessage, {
627
- type,
628
- content,
629
- isUser,
630
- stacked
631
- });
718
+ const { title, body, actions, form, items } = content;
632
719
  return /* @__PURE__ */ React.createElement(MessageContent, {
633
- noPadding: true,
634
720
  user: isUser,
635
721
  stacked: !!stacked && stacked,
636
722
  fullWidth: !!form || !!actions
637
723
  }, title && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(MessageTitle, {
638
724
  variant: "h2"
639
- }, title)), body && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(StyledHtml, {
640
- html: body,
641
- htmlParseInstruction: htmlParseInstructions$1
725
+ }, title)), body && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(Html, {
726
+ body
642
727
  })), form && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(StyledForm, __spreadProps(__spreadValues({}, form), {
643
728
  onChange: (key, data) => {
644
729
  dispatch("form", {
@@ -660,146 +745,21 @@ const ConversationContent = ({ content, isUser, stacked }) => {
660
745
  }
661
746
  }, item.label));
662
747
  }
663
- })), items && /* @__PURE__ */ React.createElement(Fragment, null, /* @__PURE__ */ React.createElement(MessageContentPart, {
748
+ })), items && /* @__PURE__ */ React.createElement(MessageList, {
664
749
  key: uuid(),
665
- noPadding: true
666
- }, /* @__PURE__ */ React.createElement(StyledActionList, {
667
- items: items.map(([type2, content2]) => {
668
- return { type: type2, content: content2 };
669
- }),
670
- renderItem: (item) => {
671
- const itemKey = uuid();
672
- switch (item.type) {
673
- case ConversationMessageListItemType.Header: {
674
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
675
- key: itemKey
676
- }, /* @__PURE__ */ React.createElement(HeaderText, null, item.content));
677
- }
678
- case ConversationMessageListItemType.Text: {
679
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
680
- key: itemKey
681
- }, /* @__PURE__ */ React.createElement("span", null, item.content));
682
- }
683
- case ConversationMessageListItemType.HTML: {
684
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
685
- key: itemKey
686
- }, /* @__PURE__ */ React.createElement(StyledHtml, {
687
- html: item.content.body,
688
- htmlParseInstruction: htmlParseInstructions$1
689
- }));
690
- }
691
- case ConversationMessageListItemType.Separator: {
692
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
693
- key: itemKey,
694
- noPadding: true
695
- }, /* @__PURE__ */ React.createElement(SeparatorPadding, null, /* @__PURE__ */ React.createElement(Separator, null)));
696
- }
697
- case ConversationMessageListItemType.LinkList: {
698
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
699
- key: itemKey
700
- }, /* @__PURE__ */ React.createElement(StyledLinkList, {
701
- items: Object.keys(item.content.actions).map((i) => {
702
- return {
703
- label: item.content.actions[i],
704
- actionKey: i
705
- };
706
- }),
707
- renderItem: (item2) => {
708
- return /* @__PURE__ */ React.createElement("li", {
709
- key: item2.actionKey
710
- }, /* @__PURE__ */ React.createElement(StyledLinkButton, {
711
- help: item2.actionKey === "help",
712
- onClick: () => {
713
- dispatch("action", item2.actionKey);
714
- }
715
- }, item2.label, item2.actionKey === "help" && /* @__PURE__ */ React.createElement(SymbolBadge, {
716
- size: 14,
717
- symbol: {
718
- type: "Svg",
719
- content: "caret-down"
720
- }
721
- })));
722
- }
723
- }));
724
- }
725
- case ConversationMessageListItemType.ButtonList: {
726
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
727
- key: itemKey
728
- }, /* @__PURE__ */ React.createElement(StyledButtonList, {
729
- items: Object.keys(item.content.actions).map((i) => {
730
- return {
731
- label: item.content.actions[i],
732
- actionKey: i
733
- };
734
- }),
735
- renderItem: (item2) => {
736
- return /* @__PURE__ */ React.createElement("li", {
737
- key: item2.actionKey
738
- }, /* @__PURE__ */ React.createElement(StyledButtonListButton, {
739
- onClick: () => {
740
- dispatch("action", item2.actionKey);
741
- }
742
- }, item2.label));
743
- }
744
- }));
745
- }
746
- case ConversationMessageListItemType.NoGoodAlternative: {
747
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
748
- key: itemKey
749
- }, /* @__PURE__ */ React.createElement(NoGoodAlternativeWrapper, {
750
- onClick: () => {
751
- dispatch("action", "help");
752
- }
753
- }, /* @__PURE__ */ React.createElement(SymbolBadge, {
754
- size: 14,
755
- symbol: {
756
- type: "FontAwesome",
757
- content: "meh-o"
758
- }
759
- }), /* @__PURE__ */ React.createElement("span", null, item.content.body)));
760
- }
761
- case ConversationMessageListItemType.FeedbackList: {
762
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
763
- key: itemKey
764
- }, /* @__PURE__ */ React.createElement(StyledButtonList, {
765
- items: Object.keys(item.content.actions).map((i) => {
766
- return {
767
- label: item.content.actions[i],
768
- actionKey: i
769
- };
770
- }),
771
- renderItem: (item2) => {
772
- return /* @__PURE__ */ React.createElement(FeedbackItem, {
773
- key: item2.actionKey
774
- }, /* @__PURE__ */ React.createElement(FeedbackButton, {
775
- className: "humany-feedback-button",
776
- disabled: false,
777
- "aria-pressed": true,
778
- "data-selected": true,
779
- "data-direction": "vertical",
780
- onClick: () => {
781
- dispatch("action", item2.actionKey);
782
- }
783
- }, /* @__PURE__ */ React.createElement(Icon, {
784
- faIcon: item2.actionKey == "yes" ? "smile-o" : "frown-o"
785
- }), /* @__PURE__ */ React.createElement("span", null, item2.label)));
786
- }
787
- }));
788
- }
789
- default: {
790
- return /* @__PURE__ */ React.createElement(ConversationListItem, {
791
- key: itemKey,
792
- noPadding: true
793
- }, /* @__PURE__ */ React.createElement(CustomMessageListItem, {
794
- type: item.type,
795
- content: item.content
796
- }));
797
- }
798
- }
799
- }
800
- }))));
750
+ items,
751
+ dispatch
752
+ }));
801
753
  };
802
754
  const StyledForm = styled(FormComponent)`
755
+ margin: ${(p) => {
756
+ var _a;
757
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
758
+ }} 0;
759
+ padding: 0 ${(p) => {
760
+ var _a;
761
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
762
+ }};
803
763
  & button.humany-form-component-button {
804
764
  ${(p) => {
805
765
  var _a, _b;
@@ -827,123 +787,43 @@ const StyledForm = styled(FormComponent)`
827
787
  }
828
788
  }
829
789
  `;
830
- const StyledHtml = styled(Html)`
831
- white-space: pre-wrap;
832
- a {
833
- color: ${(p) => p.theme.colors.link};
834
- &:focus {
835
- ${(p) => {
836
- var _a;
837
- return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && borderTabStyle;
838
- }};
839
- }
840
- }
841
- `;
842
790
  const StyledActionList = styled(List)`
843
791
  padding: 0;
844
792
  list-style: none;
845
- margin: 0 -${(p) => {
793
+ button {
794
+ font-size: inherit;
795
+ }
796
+ margin: ${(p) => {
846
797
  var _a;
847
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
848
- }};
849
- > li {
850
- margin: ${(p) => {
798
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
799
+ }} 0;
800
+ padding: 0 ${(p) => {
851
801
  var _a;
852
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
802
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
853
803
  }};
854
- }
855
- `;
856
- const StyledButtonList = styled(List)`
857
- padding: 0;
858
- list-style: none;
859
- > li {
860
- margin: ${(p) => {
861
- var _a;
862
- return (_a = p.theme.sizes) == null ? void 0 : _a.small;
863
- }} ${(p) => {
804
+ display: flex;
805
+ gap: ${(p) => {
864
806
  var _a;
865
807
  return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
866
808
  }};
867
- margin-left: 0;
868
- display: inline-block;
869
- }
870
809
  `;
871
- const StyledButtonListButton = styled.button`
810
+ const StyledActionButton = styled.button`
872
811
  ${buttonCss};
873
812
  display: block;
874
- text-align: left;
875
813
  background-color: ${(p) => {
876
814
  var _a;
877
815
  return (_a = p.theme.colors) == null ? void 0 : _a.primary;
878
816
  }};
879
817
  width: 100%;
880
818
  color: #fff;
881
- &:focus {
882
- ${(p) => {
883
- var _a;
884
- return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && css`
885
- ${borderTabStyle}
886
- background-color: transparent;
887
- `;
888
- }}
889
- }
890
- `;
891
- const StyledLinkList = styled(List)`
892
- padding: 0;
893
- list-style: none;
894
- > li {
895
- margin-bottom: ${(p) => {
896
- var _a;
897
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
898
- }};
899
-
900
- &:last-child {
901
- margin-bottom: 0;
902
- }
903
- }
904
- `;
905
- const HeaderText = styled.strong`
906
- font-size: ${(p) => {
907
- var _a;
908
- return (_a = p.theme.fonts) == null ? void 0 : _a.huge;
909
- }};
910
- `;
911
- const StyledLinkButton = styled.button`
912
- display: block;
913
- background-color: transparent;
914
- text-align: left;
915
- border: none;
916
- padding: 0;
917
- font-weight: 300;
918
- font-family: inherit;
919
- cursor: pointer;
920
- color: ${(p) => {
819
+ margin: ${(p) => {
921
820
  var _a;
922
- return (_a = p.theme.colors) == null ? void 0 : _a.primary;
923
- }};
924
-
925
- ${(p) => {
926
- var _a, _b;
927
- return p.help && css`
928
- color: ${(_a = p.theme.colors) == null ? void 0 : _a.text};
929
- text-decoration: underline;
930
-
931
- i,
932
- svg {
933
- margin-left: ${(_b = p.theme.sizes) == null ? void 0 : _b.small};
934
- }
935
- `;
936
- }}
937
- `;
938
- const StyledActionButton = styled.button`
939
- ${buttonCss};
940
- display: block;
941
- background-color: ${(p) => {
821
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
822
+ }} 0;
823
+ padding: 0 ${(p) => {
942
824
  var _a;
943
- return (_a = p.theme.colors) == null ? void 0 : _a.primary;
825
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
944
826
  }};
945
- width: 100%;
946
- color: #fff;
947
827
  font-family: Lato;
948
828
  font-size: ${(p) => {
949
829
  var _a;
@@ -960,107 +840,136 @@ const StyledActionButton = styled.button`
960
840
  }}
961
841
  }
962
842
  `;
963
- const SeparatorPadding = styled.div`
964
- padding-top: calc(${(p) => {
965
- var _a;
966
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
967
- }} - ${(p) => {
968
- var _a;
969
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
970
- }});
971
- padding-bottom: calc(${(p) => {
972
- var _a;
973
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
974
- }} - ${(p) => {
975
- var _a;
976
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
977
- }});
978
- `;
979
- const Separator = styled.div`
980
- background-color: #efefef;
981
- height: 1px;
982
- width: 100%;
983
- `;
984
- const NoGoodAlternativeWrapper = styled.div`
985
- display: flex;
986
- align-items: center;
987
- justify-content: center;
988
- cursor: pointer;
989
-
990
- > i,
991
- svg {
992
- margin-right: ${(p) => {
843
+ const StyledTimestamp = styled.p`
844
+ && {
845
+ font-size: ${(p) => {
993
846
  var _a;
994
- return (_a = p.theme.sizes) == null ? void 0 : _a.small;
847
+ return (_a = p.theme.fonts) == null ? void 0 : _a.small;
995
848
  }};
849
+ font-weight: 300;
996
850
  }
997
- `;
998
- const ConversationListItem = styled.li`
999
- padding-left: ${(p) => {
851
+ padding-top: ${(p) => {
1000
852
  var _a;
1001
- return p.noPadding ? 0 : (_a = p.theme.sizes) == null ? void 0 : _a.medium;
853
+ return (_a = p.theme.sizes) == null ? void 0 : _a.small;
1002
854
  }};
1003
- padding-right: ${(p) => {
855
+ margin: 0;
856
+ line-height: 1.5em;
857
+ grid-area: info;
858
+ color: ${(p) => {
1004
859
  var _a;
1005
- return p.noPadding ? 0 : (_a = p.theme.sizes) == null ? void 0 : _a.medium;
860
+ return (_a = p.theme.colors) == null ? void 0 : _a.text;
1006
861
  }};
1007
862
  `;
1008
- const FeedbackItem = styled.li`
1009
- @media (min-width: 768px) {
1010
- display: list-item !important;
1011
- margin-right: 0 !important;
1012
- margin-top: ${(p) => {
1013
- var _a;
1014
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
1015
- }} !important;
863
+ const getTimestamp = (raw) => {
864
+ return new Date(raw).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
865
+ };
866
+ const Timestamp = ({ className, name, timestamp }) => {
867
+ if (!name && !timestamp) {
868
+ return null;
869
+ }
870
+ let output = "";
871
+ if (name) {
872
+ if (timestamp) {
873
+ output = `${name}: ${getTimestamp(timestamp)}`;
874
+ } else {
875
+ output = name;
1016
876
  }
877
+ } else if (timestamp) {
878
+ output = getTimestamp(timestamp);
879
+ }
880
+ return /* @__PURE__ */ React.createElement(StyledTimestamp, null, output);
881
+ };
882
+ const AgentMessage = ({ className, children, sender, timestamp }) => {
883
+ const { avatar, name } = sender;
884
+ const { avatarSize } = useProperties();
885
+ return /* @__PURE__ */ React.createElement(StyledAgentMessage, {
886
+ hasAvatar: !!avatar,
887
+ className: appendClassNames(className, "humany-conversation-agent-message")
888
+ }, avatar && /* @__PURE__ */ React.createElement(Avatar, {
889
+ avatarSize
890
+ }, typeof avatar === "string" ? /* @__PURE__ */ React.createElement("img", {
891
+ src: avatar
892
+ }) : /* @__PURE__ */ React.createElement(SymbolBadge, {
893
+ symbol: avatar
894
+ })), children, /* @__PURE__ */ React.createElement(Timestamp, {
895
+ name,
896
+ timestamp
897
+ }));
898
+ };
899
+ const StyledAgentMessage = styled.div`
900
+ display: grid;
901
+ margin-right: 10%;
902
+ width: 90%;
903
+ ${(p) => p.hasAvatar ? css`
904
+ grid-template-columns: auto 1fr;
905
+ grid-template-rows: 1fr auto;
906
+ grid-template-areas:
907
+ 'avatar content'
908
+ '. info';
909
+ ` : css`
910
+ grid-template-columns: 1fr;
911
+ grid-template-rows: 1fr auto;
912
+ grid-template-areas:
913
+ 'content'
914
+ 'info';
915
+ `};
1017
916
  `;
1018
- const FeedbackButton = styled.button`
1019
- @media (min-width: 768px) {
1020
- min-width: 100%;
1021
- margin-right: 0;
1022
- }
1023
- display: inline-block;
917
+ const SystemMessage = ({
918
+ className,
919
+ children,
920
+ timestamp,
921
+ discrete,
922
+ fullWidth
923
+ }) => {
924
+ return /* @__PURE__ */ React.createElement(StyledSystemMessage, {
925
+ className: appendClassNames(className, "humany-conversation-system-message"),
926
+ fullWidth
927
+ }, discrete ? /* @__PURE__ */ React.createElement(Discrete, {
928
+ className: "humany-conversation-discrete-message"
929
+ }, children, /* @__PURE__ */ React.createElement(Timestamp, {
930
+ timestamp
931
+ })) : /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement(Timestamp, {
932
+ timestamp
933
+ })));
934
+ };
935
+ const StyledSystemMessage = styled.div`
936
+ ${(p) => p.fullWidth && "width: 100%"};
937
+ padding: 0 ${(p) => {
938
+ var _a;
939
+ return (_a = p.theme.sizes) == null ? void 0 : _a.large;
940
+ }};
941
+ overflow: auto;
942
+ `;
943
+ const Discrete = styled.div`
944
+ text-align: center;
945
+ word-wrap: break-word;
1024
946
  font-size: ${(p) => {
1025
947
  var _a;
1026
948
  return (_a = p.theme.fonts) == null ? void 0 : _a.normal;
1027
949
  }};
1028
- border-color: ${(p) => {
1029
- var _a;
1030
- return (_a = p.theme.colors) == null ? void 0 : _a.primary;
1031
- }} !important;
1032
- font-weight: 300;
1033
- && {
1034
- margin-right: ${(p) => {
950
+ color: ${(p) => {
1035
951
  var _a;
1036
- return (_a = p.theme.sizes) == null ? void 0 : _a.small;
952
+ return (_a = p.theme.colors) == null ? void 0 : _a.text;
1037
953
  }};
954
+ > p {
955
+ margin: 0;
1038
956
  }
1039
- ${(p) => {
1040
- var _a, _b;
1041
- return p["data-direction"] === "horizontal" && css`
1042
- width: 225px;
1043
- max-width: calc(50% - ${(_a = p.theme.sizes) == null ? void 0 : _a.large} - ${(_b = p.theme.sizes) == null ? void 0 : _b.small});
1044
- `;
1045
- }}
1046
- ${(p) => p["data-direction"] === "vertical" && css`
1047
- min-width: 150px;
1048
- `}
1049
- ${(p) => {
1050
- var _a;
1051
- return invertedHoverButton({
1052
- primaryColor: `${(_a = p.theme.colors) == null ? void 0 : _a.primary}`,
1053
- secondaryColor: "#FFFFFF"
1054
- });
1055
- }}
1056
- i {
1057
- margin: 0 ${(p) => {
1058
- var _a;
1059
- return (_a = p.theme.sizes) == null ? void 0 : _a.small;
1060
- }} 0 0;
1061
- }
1062
- span {
1063
- }
957
+ `;
958
+ const UserMessage = ({ className, children, timestamp }) => {
959
+ const { userLabel = "" } = useProperties();
960
+ return /* @__PURE__ */ React.createElement(StyledUserMessage, {
961
+ className: appendClassNames(className, "humany-conversation-user-message")
962
+ }, children, /* @__PURE__ */ React.createElement(Timestamp, {
963
+ name: userLabel,
964
+ timestamp
965
+ }));
966
+ };
967
+ const StyledUserMessage = styled.div`
968
+ margin-left: 10%;
969
+ width: 90%;
970
+ display: flex;
971
+ flex-direction: column;
972
+ align-items: flex-end;
1064
973
  `;
1065
974
  const imageLightboxRenderer = (attrs) => /* @__PURE__ */ React.createElement(Lightbox, {
1066
975
  attrs
@@ -1077,9 +986,8 @@ const ConversationMessageComponent = ({
1077
986
  type,
1078
987
  content
1079
988
  }) => {
1080
- useDispatch();
1081
989
  const getMessageStackPosition = (index) => {
1082
- let messageOrder = void 0;
990
+ let messageOrder = "first";
1083
991
  if (content.length > 1) {
1084
992
  messageOrder = index === 0 ? "first" : index + 1 === content.length ? "last" : "middle";
1085
993
  }
@@ -1095,7 +1003,7 @@ const ConversationMessageComponent = ({
1095
1003
  discrete,
1096
1004
  timestamp,
1097
1005
  fullWidth: !!form || !!actions
1098
- }, discrete && body ? /* @__PURE__ */ React.createElement(Html, {
1006
+ }, discrete && body ? /* @__PURE__ */ React.createElement(Html$1, {
1099
1007
  html: body,
1100
1008
  htmlParseInstruction: htmlParseInstructions
1101
1009
  }) : /* @__PURE__ */ React.createElement(ConversationContent, {
@@ -1144,86 +1052,13 @@ const ConversationMessageComponent = ({
1144
1052
  return null;
1145
1053
  }
1146
1054
  };
1147
- styled(FormComponent)`
1148
- & button.humany-form-component-button {
1149
- ${(p) => {
1150
- var _a, _b;
1151
- return invertedHoverButton({
1152
- active: false,
1153
- primaryColor: (_a = p.theme.colors) == null ? void 0 : _a.primary,
1154
- secondaryColor: (_b = p.theme.colors) == null ? void 0 : _b.accent
1155
- });
1156
- }};
1157
- display: block;
1158
- width: 100%;
1159
- margin-bottom: ${(p) => {
1160
- var _a;
1161
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
1162
- }};
1163
- }
1164
-
1165
- & button.humany-form-component-submit {
1166
- width: 100%;
1167
- margin: 0;
1168
- :not(:last-child) {
1169
- margin-bottom: ${(p) => {
1170
- var _a;
1171
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
1172
- }};
1173
- }
1174
- }
1175
- `;
1176
- styled(Html)`
1177
- white-space: pre-wrap;
1178
-
1179
- a {
1180
- color: ${(p) => p.theme.colors.link};
1181
- &:focus {
1182
- ${(p) => {
1183
- var _a;
1184
- return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && borderTabStyle;
1185
- }};
1186
- }
1187
- }
1188
- `;
1189
- styled(List)`
1190
- padding: 0;
1191
- list-style: none;
1192
- margin: 0 -${(p) => {
1193
- var _a;
1194
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
1195
- }};
1196
- > li {
1197
- margin: ${(p) => {
1198
- var _a;
1199
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
1200
- }};
1201
- }
1202
- `;
1203
- styled.button`
1204
- ${buttonCss};
1205
- display: block;
1206
- background-color: ${(p) => {
1207
- var _a;
1208
- return (_a = p.theme.colors) == null ? void 0 : _a.primary;
1209
- }};
1210
- width: 100%;
1211
- color: #fff;
1212
- &:focus {
1213
- ${(p) => {
1214
- var _a;
1215
- return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && css`
1216
- ${borderTabStyle}
1217
- background-color: transparent;
1218
- `;
1219
- }}
1220
- }
1221
- `;
1222
1055
  const Conversation = ({ className }) => {
1223
1056
  const lastEntry = useRef(document.createElement("div"));
1224
1057
  const [scrollableCss, viewElem] = useScroll(true);
1225
1058
  const { messages, loading, typingActors } = useProperties();
1226
1059
  const [canSmooth, setCanSmooth] = useState(false);
1060
+ const previousMessages = usePrevious(messages);
1061
+ const previousTypingActors = usePrevious(typingActors);
1227
1062
  const scrollView = useCallback((lastEntry2, smooth = true) => {
1228
1063
  if (lastEntry2 !== null && lastEntry2.current !== null) {
1229
1064
  if (messages && messages.length === 1) {
@@ -1239,12 +1074,23 @@ const Conversation = ({ className }) => {
1239
1074
  behavior: smooth ? "smooth" : "auto"
1240
1075
  });
1241
1076
  }
1242
- }, 0);
1077
+ }, 150);
1243
1078
  }
1244
1079
  }, [lastEntry]);
1245
1080
  useEffect(() => {
1246
1081
  if (canSmooth) {
1247
- scrollView(lastEntry);
1082
+ const messageCountChanged = messages.length !== (previousMessages == null ? void 0 : previousMessages.length);
1083
+ const typingActorCountChanged = typingActors.length !== (previousTypingActors == null ? void 0 : previousTypingActors.length);
1084
+ const messageContentCountChanged = messages.reduce((changed, message, index) => {
1085
+ var _a;
1086
+ if (((_a = previousMessages == null ? void 0 : previousMessages[index]) == null ? void 0 : _a.content.length) !== message.content.length) {
1087
+ return true;
1088
+ }
1089
+ return changed;
1090
+ }, false);
1091
+ if (messageCountChanged || messageContentCountChanged || typingActorCountChanged) {
1092
+ scrollView(lastEntry);
1093
+ }
1248
1094
  }
1249
1095
  }, [messages, typingActors]);
1250
1096
  useTransitionEnd(() => {
@@ -1330,13 +1176,6 @@ const MessageEntry = styled.div`
1330
1176
  }};
1331
1177
  }
1332
1178
 
1333
- * {
1334
- font-size: ${(p) => {
1335
- var _a;
1336
- return (_a = p.theme.fonts) == null ? void 0 : _a.normal;
1337
- }};
1338
- }
1339
-
1340
1179
  & span,
1341
1180
  p,
1342
1181
  a,