@telia-ace/widget-conversation 1.0.17 → 1.0.20

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 (37) hide show
  1. package/dist/{ui → components}/conversation/conversation.d.ts +0 -0
  2. package/dist/{ui/conversation/conversation-component.d.ts → components/conversation/plugin.d.ts} +8 -2
  3. package/dist/components/conversation/ui/content.d.ts +2 -0
  4. package/dist/{ui/conversation/conversation-input.d.ts → components/conversation/ui/input.d.ts} +0 -0
  5. package/dist/{ui/conversation/conversation-loader.d.ts → components/conversation/ui/loader.d.ts} +1 -1
  6. package/dist/{ui/conversation → components/conversation/ui}/message-list-items/button-list.d.ts +1 -1
  7. package/dist/{ui/conversation → components/conversation/ui}/message-list-items/custom.d.ts +0 -0
  8. package/dist/{ui/conversation → components/conversation/ui}/message-list-items/html.d.ts +1 -1
  9. package/dist/{ui/conversation → components/conversation/ui}/message-list-items/link-list.d.ts +1 -1
  10. package/dist/{ui/conversation → components/conversation/ui}/message-list-items/separator.d.ts +0 -0
  11. package/dist/{ui/conversation → components/conversation/ui}/message-list-items/text.d.ts +0 -0
  12. package/dist/components/conversation/ui/message-list-items/video-request.d.ts +8 -0
  13. package/dist/{ui/conversation → components/conversation/ui}/message-types/agent.d.ts +1 -1
  14. package/dist/{ui/conversation → components/conversation/ui}/message-types/index.d.ts +0 -0
  15. package/dist/{ui/conversation → components/conversation/ui}/message-types/message-list.d.ts +1 -1
  16. package/dist/{ui/conversation → components/conversation/ui}/message-types/system.d.ts +0 -0
  17. package/dist/{ui/conversation → components/conversation/ui}/message-types/timestamp.d.ts +0 -0
  18. package/dist/{ui/conversation → components/conversation/ui}/message-types/user.d.ts +0 -0
  19. package/dist/components/conversation/ui/message.d.ts +7 -0
  20. package/dist/components/conversation/ui/overlay-outlets.d.ts +13 -0
  21. package/dist/components/conversation/ui/styles.d.ts +27 -0
  22. package/dist/{ui/return-button/return-button-component.d.ts → components/return-button/plugin.d.ts} +1 -2
  23. package/dist/{ui → components}/return-button/return-button.d.ts +0 -0
  24. package/dist/conversation.js +548 -329
  25. package/dist/conversation.js.map +1 -1
  26. package/dist/index.d.ts +2 -1
  27. package/dist/index.js +31 -8
  28. package/dist/index.js.map +1 -1
  29. package/dist/return-button.js.map +1 -1
  30. package/dist/types.d.ts +9 -2
  31. package/package.json +4 -4
  32. package/dist/ui/conversation/conversation-content.d.ts +0 -11
  33. package/dist/ui/conversation/conversation-message.d.ts +0 -7
  34. package/dist/ui/conversation/conversation-styles.d.ts +0 -12
  35. package/dist/ui/conversation/index.d.ts +0 -2
  36. package/dist/ui/index.d.ts +0 -2
  37. package/dist/ui/return-button/index.d.ts +0 -2
@@ -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, Html as Html$1, genericHtml, Lightbox, ItemList, itemList, buttonCss, useComponent, List, list, invertedHoverButton, usePrevious, useTransitionEnd, headingElement } from "@telia-ace/widget-ui";
32
+ import { Input, Button, borderTabStyle, SymbolBadge, useDispatch, useProperties, useScroll, Typography, invertedHoverButton, List, buttonCss, Html as Html$1, genericHtml, Lightbox, ItemList, itemList, useComponent, list, headingElement, usePrevious, useTransitionEnd, WidgetOverlayOutlet } from "@telia-ace/widget-ui";
33
33
  import { appendClassNames, uuid } from "@telia-ace/widget-utilities";
34
- import React, { useState, useEffect, Suspense, useRef, useCallback } from "react";
34
+ import React, { useState, useEffect, Suspense, useMemo, useCallback, useRef } from "react";
35
35
  import styled, { css, keyframes } from "styled-components";
36
- import { ConversationMessageListItemType, ConversationMessageType } from "./index.js";
37
36
  import { FormComponent } from "@telia-ace/widget-forms";
37
+ import { ConversationMessageListItemType, ConversationMessageType } from "./index.js";
38
38
  import "@telia-ace/widget-core";
39
39
  import "@telia-ace/widget-services";
40
40
  import "@telia-ace/widget-plugins";
@@ -82,7 +82,9 @@ const ConversationInput = ({ className }) => {
82
82
  return;
83
83
  }
84
84
  e.preventDefault();
85
- dispatch("action", secondaryAction);
85
+ dispatch("action", __spreadValues({
86
+ actionKey: secondaryAction.action
87
+ }, secondaryAction));
86
88
  };
87
89
  const calculateHeight = (value) => {
88
90
  if (multiline && inputRef.current) {
@@ -144,7 +146,7 @@ const ConversationInput = ({ className }) => {
144
146
  "aria-label": inputPlaceholder,
145
147
  placeholder: inputPlaceholder,
146
148
  onFocusChange: setInputFocus
147
- }), /* @__PURE__ */ React.createElement(StyledButton, {
149
+ }), /* @__PURE__ */ React.createElement(StyledButton$1, {
148
150
  disabled: inputDisabled,
149
151
  onClick: submit,
150
152
  title: sendButtonLabel,
@@ -203,7 +205,7 @@ const StyledInput = styled(Input)`
203
205
  font-style: italic;
204
206
  }
205
207
  `;
206
- const StyledButton = styled(Button)`
208
+ const StyledButton$1 = styled(Button)`
207
209
  flex: 0 0 50px;
208
210
  align-self: stretch;
209
211
  background-color: transparent;
@@ -219,7 +221,7 @@ const StyledButton = styled(Button)`
219
221
  }};
220
222
  }
221
223
  `;
222
- const SecondaryActionButton = styled(StyledButton)`
224
+ const SecondaryActionButton = styled(StyledButton$1)`
223
225
  border-right: ${(p) => p.theme.border};
224
226
  margin: ${(p) => {
225
227
  var _a;
@@ -364,10 +366,11 @@ const MessageTitle = styled(Typography)`
364
366
  `;
365
367
  const MessageContainer = styled.div`
366
368
  display: flex;
369
+ justify-content: ${(p) => p.user ? "end" : "start"};
367
370
  `;
368
371
  const MessageContent = styled.div`
369
- ${(p) => !p.user && nonUserMessageStyling(p.stacked, p.theme)}
370
- ${(p) => p.user && userMessageStyling(p.stacked, p.theme)}
372
+ ${(p) => !p.user && p.stacked && nonUserMessageStyling(p.stacked, p.theme)}
373
+ ${(p) => p.user && p.stacked && userMessageStyling(p.stacked, p.theme)}
371
374
 
372
375
  display: inline-block;
373
376
  margin-top: ${(p) => {
@@ -434,18 +437,6 @@ const userMessageStyling = (stacked, theme) => {
434
437
  `;
435
438
  };
436
439
  const MessageContentPart = styled.div`
437
- padding: ${(p) => {
438
- var _a;
439
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
440
- }} ${(p) => {
441
- var _a;
442
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
443
- }};
444
-
445
- ${(p) => p.noPadding && css`
446
- padding: 0;
447
- `}
448
-
449
440
  margin-bottom: ${(p) => {
450
441
  var _a;
451
442
  return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
@@ -464,21 +455,110 @@ const messageContentPadding = css`
464
455
  return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
465
456
  }};
466
457
  `;
458
+ const StyledForm = styled(FormComponent)`
459
+ margin: ${(p) => {
460
+ var _a;
461
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
462
+ }} 0;
463
+ padding: 0 ${(p) => {
464
+ var _a;
465
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
466
+ }};
467
+ & button.humany-form-component-button {
468
+ ${(p) => {
469
+ var _a, _b;
470
+ return invertedHoverButton({
471
+ active: false,
472
+ primaryColor: (_a = p.theme.colors) == null ? void 0 : _a.primary,
473
+ secondaryColor: (_b = p.theme.colors) == null ? void 0 : _b.accent
474
+ });
475
+ }};
476
+ display: block;
477
+ width: 100%;
478
+ margin-bottom: ${(p) => {
479
+ var _a;
480
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
481
+ }};
482
+ }
483
+ & button.humany-form-component-submit {
484
+ width: 100%;
485
+ margin: 0;
486
+ :not(:last-child) {
487
+ margin-bottom: ${(p) => {
488
+ var _a;
489
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
490
+ }};
491
+ }
492
+ }
493
+ `;
494
+ const StyledActionList = styled(List)`
495
+ padding: 0;
496
+ list-style: none;
497
+ button {
498
+ font-size: inherit;
499
+ }
500
+ margin: ${(p) => {
501
+ var _a;
502
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
503
+ }} 0;
504
+ padding: 0 ${(p) => {
505
+ var _a;
506
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
507
+ }};
508
+ display: flex;
509
+ gap: ${(p) => {
510
+ var _a;
511
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
512
+ }};
513
+ `;
514
+ const StyledActionButton = styled.button`
515
+ ${buttonCss};
516
+ display: block;
517
+ background-color: ${(p) => {
518
+ var _a;
519
+ return (_a = p.theme.colors) == null ? void 0 : _a.primary;
520
+ }};
521
+ width: 100%;
522
+ color: #fff;
523
+ margin: ${(p) => {
524
+ var _a;
525
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
526
+ }} 0;
527
+ padding: 0 ${(p) => {
528
+ var _a;
529
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
530
+ }};
531
+ font-family: Lato;
532
+ font-size: ${(p) => {
533
+ var _a;
534
+ return (_a = p.theme.fonts) == null ? void 0 : _a.huge;
535
+ }};
536
+ font-weight: 300;
537
+ &:focus {
538
+ ${(p) => {
539
+ var _a;
540
+ return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && css`
541
+ ${borderTabStyle}
542
+ background-color: transparent;
543
+ `;
544
+ }}
545
+ }
546
+ `;
467
547
  const ConversationLoader = ({ className, agentData }) => {
468
548
  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)))));
469
549
  };
470
- const imageLightboxRenderer$1 = (attrs) => /* @__PURE__ */ React.createElement(Lightbox, {
550
+ const imageLightboxRenderer = (attrs) => /* @__PURE__ */ React.createElement(Lightbox, {
471
551
  attrs
472
552
  });
473
- const htmlParseInstructions$1 = {
553
+ const htmlParseInstructions = {
474
554
  transform: {
475
- img: imageLightboxRenderer$1
555
+ img: imageLightboxRenderer
476
556
  }
477
557
  };
478
558
  const Html = ({ body }) => {
479
559
  return /* @__PURE__ */ React.createElement(StyledHtml, {
480
560
  html: body,
481
- htmlParseInstruction: htmlParseInstructions$1
561
+ htmlParseInstruction: htmlParseInstructions
482
562
  });
483
563
  };
484
564
  const StyledHtml = styled(Html$1)`
@@ -496,6 +576,137 @@ const StyledHtml = styled(Html$1)`
496
576
  }
497
577
  }
498
578
  `;
579
+ const StyledTimestamp = styled.p`
580
+ && {
581
+ font-size: ${(p) => {
582
+ var _a;
583
+ return (_a = p.theme.fonts) == null ? void 0 : _a.small;
584
+ }};
585
+ font-weight: 300;
586
+ }
587
+ padding-top: ${(p) => {
588
+ var _a;
589
+ return (_a = p.theme.sizes) == null ? void 0 : _a.small;
590
+ }};
591
+ margin: 0;
592
+ line-height: 1.5em;
593
+ grid-area: info;
594
+ color: ${(p) => {
595
+ var _a;
596
+ return (_a = p.theme.colors) == null ? void 0 : _a.text;
597
+ }};
598
+ `;
599
+ const getTimestamp = (raw) => {
600
+ return new Date(raw).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
601
+ };
602
+ const Timestamp = ({ className, name, timestamp }) => {
603
+ if (!name && !timestamp) {
604
+ return null;
605
+ }
606
+ let output = "";
607
+ if (name) {
608
+ if (timestamp) {
609
+ output = `${name}: ${getTimestamp(timestamp)}`;
610
+ } else {
611
+ output = name;
612
+ }
613
+ } else if (timestamp) {
614
+ output = getTimestamp(timestamp);
615
+ }
616
+ return /* @__PURE__ */ React.createElement(StyledTimestamp, null, output);
617
+ };
618
+ const AgentMessage = ({ className, children, sender, timestamp }) => {
619
+ const { avatar, name } = sender;
620
+ const { avatarSize } = useProperties();
621
+ return /* @__PURE__ */ React.createElement(StyledAgentMessage, {
622
+ hasAvatar: !!avatar,
623
+ className: appendClassNames(className, "humany-conversation-agent-message")
624
+ }, avatar && /* @__PURE__ */ React.createElement(Avatar, {
625
+ avatarSize
626
+ }, typeof avatar === "string" ? /* @__PURE__ */ React.createElement("img", {
627
+ src: avatar
628
+ }) : /* @__PURE__ */ React.createElement(SymbolBadge, {
629
+ symbol: avatar
630
+ })), children, /* @__PURE__ */ React.createElement(Timestamp, {
631
+ name,
632
+ timestamp
633
+ }));
634
+ };
635
+ const StyledAgentMessage = styled.div`
636
+ display: grid;
637
+ margin-right: 10%;
638
+ width: 90%;
639
+ ${(p) => p.hasAvatar ? css`
640
+ grid-template-columns: auto 1fr;
641
+ grid-template-rows: 1fr auto;
642
+ grid-template-areas:
643
+ 'avatar content'
644
+ '. info';
645
+ ` : css`
646
+ grid-template-columns: 1fr;
647
+ grid-template-rows: 1fr auto;
648
+ grid-template-areas:
649
+ 'content'
650
+ 'info';
651
+ `};
652
+ `;
653
+ const SystemMessage = ({
654
+ className,
655
+ children,
656
+ timestamp,
657
+ discrete,
658
+ fullWidth
659
+ }) => {
660
+ return /* @__PURE__ */ React.createElement(StyledSystemMessage, {
661
+ className: appendClassNames(className, "humany-conversation-system-message"),
662
+ fullWidth
663
+ }, discrete ? /* @__PURE__ */ React.createElement(Discrete, {
664
+ className: "humany-conversation-discrete-message"
665
+ }, children, /* @__PURE__ */ React.createElement(Timestamp, {
666
+ timestamp
667
+ })) : /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement(Timestamp, {
668
+ timestamp
669
+ })));
670
+ };
671
+ const StyledSystemMessage = styled.div`
672
+ ${(p) => p.fullWidth && "width: 100%"};
673
+ padding: 0 ${(p) => {
674
+ var _a;
675
+ return (_a = p.theme.sizes) == null ? void 0 : _a.large;
676
+ }};
677
+ overflow: auto;
678
+ `;
679
+ const Discrete = styled.div`
680
+ text-align: center;
681
+ word-wrap: break-word;
682
+ font-size: ${(p) => {
683
+ var _a;
684
+ return (_a = p.theme.fonts) == null ? void 0 : _a.normal;
685
+ }};
686
+ color: ${(p) => {
687
+ var _a;
688
+ return (_a = p.theme.colors) == null ? void 0 : _a.text;
689
+ }};
690
+ > p {
691
+ margin: 0;
692
+ }
693
+ `;
694
+ const UserMessage = ({ className, children, timestamp }) => {
695
+ const { userLabel = "" } = useProperties();
696
+ return /* @__PURE__ */ React.createElement(StyledUserMessage, {
697
+ className: appendClassNames(className, "humany-conversation-user-message")
698
+ }, children, /* @__PURE__ */ React.createElement(Timestamp, {
699
+ name: userLabel,
700
+ timestamp
701
+ }));
702
+ };
703
+ const StyledUserMessage = styled.div`
704
+ margin-left: 10%;
705
+ width: 90%;
706
+ display: flex;
707
+ flex-direction: column;
708
+ align-items: flex-end;
709
+ `;
499
710
  const mapActions = (actions) => Array.isArray(actions) ? actions : Object.keys(actions).map((i) => {
500
711
  return {
501
712
  label: actions[i],
@@ -666,333 +877,180 @@ const Text = ({ text }) => {
666
877
  const StyledTypography = styled(Typography)`
667
878
  ${messageContentPadding}
668
879
  `;
669
- const mapItem = ([type, content]) => {
670
- return { type, content, id: uuid() };
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
- });
880
+ const VideoRequest = ({
881
+ header = "Video call",
882
+ acceptLabel = "Accept",
883
+ declineLabel = "Decline",
884
+ dispatch
885
+ }) => {
886
+ const actions = useMemo(() => {
887
+ return [
888
+ {
889
+ label: acceptLabel,
890
+ actionKey: "accept-video-call",
891
+ symbol: {
892
+ type: "Svg",
893
+ content: "video"
682
894
  }
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
- });
895
+ },
896
+ {
897
+ label: declineLabel,
898
+ actionKey: "decline-video-call",
899
+ symbol: {
900
+ type: "Svg",
901
+ content: "close"
704
902
  }
705
903
  }
706
- }
707
- });
708
- };
709
- const StyledList = styled(List)`
710
- ${list}
711
-
712
- > li {
713
- margin: 0;
714
- }
715
- `;
716
- const ConversationContent = ({ content, isUser, stacked }) => {
717
- const dispatch = useDispatch();
718
- const { title, body, actions, form, items } = content;
719
- return /* @__PURE__ */ React.createElement(MessageContent, {
720
- user: isUser,
721
- stacked: !!stacked && stacked,
722
- fullWidth: !!form || !!actions
723
- }, title && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(MessageTitle, {
724
- variant: "h2"
725
- }, title)), body && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(Html, {
726
- body
727
- })), form && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(StyledForm, __spreadProps(__spreadValues({}, form), {
728
- onChange: (key, data) => {
729
- dispatch("form", {
730
- data,
731
- formKey: form.schema.id,
732
- actionKey: key
733
- });
734
- }
735
- }))), actions && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(StyledActionList, {
736
- items: Object.keys(actions).map((i) => {
737
- return { label: actions[i], actionKey: i };
738
- }),
904
+ ];
905
+ }, [acceptLabel, declineLabel]);
906
+ return /* @__PURE__ */ React.createElement(StyledItemList, {
907
+ header,
908
+ items: actions,
739
909
  renderItem: (item) => {
910
+ const bgColor = item.actionKey === "accept-video-call" ? "#70c48e" : "#da5c85";
740
911
  return /* @__PURE__ */ React.createElement("li", {
741
912
  key: item.actionKey
742
- }, /* @__PURE__ */ React.createElement(StyledActionButton, {
913
+ }, /* @__PURE__ */ React.createElement(StyledButton, {
743
914
  onClick: () => {
744
- dispatch("action", item.actionKey);
745
- }
746
- }, item.label));
915
+ dispatch("action", item);
916
+ },
917
+ "aria-label": item.label,
918
+ title: item.label,
919
+ bgColor
920
+ }, /* @__PURE__ */ React.createElement(SymbolBadge, {
921
+ symbol: item.symbol,
922
+ size: 25
923
+ })));
747
924
  }
748
- })), items && /* @__PURE__ */ React.createElement(MessageList, {
749
- key: uuid(),
750
- items,
751
- dispatch
752
- }));
753
- };
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
- }};
763
- & button.humany-form-component-button {
764
- ${(p) => {
765
- var _a, _b;
766
- return invertedHoverButton({
767
- active: false,
768
- primaryColor: (_a = p.theme.colors) == null ? void 0 : _a.primary,
769
- secondaryColor: (_b = p.theme.colors) == null ? void 0 : _b.accent
770
925
  });
771
- }};
772
- display: block;
773
- width: 100%;
774
- margin-bottom: ${(p) => {
775
- var _a;
776
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
777
- }};
778
- }
779
- & button.humany-form-component-submit {
780
- width: 100%;
781
- margin: 0;
782
- :not(:last-child) {
783
- margin-bottom: ${(p) => {
926
+ };
927
+ const StyledItemList = styled(ItemList)`
928
+ ${itemList}
929
+ > ul {
930
+ display: flex;
931
+ flex-wrap: wrap;
932
+ gap: ${(p) => {
784
933
  var _a;
785
934
  return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
786
935
  }};
936
+ > li {
937
+ margin: 0;
787
938
  }
788
939
  }
940
+ ${messageContentPadding}
789
941
  `;
790
- const StyledActionList = styled(List)`
791
- padding: 0;
792
- list-style: none;
793
- button {
794
- font-size: inherit;
795
- }
796
- margin: ${(p) => {
797
- var _a;
798
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
799
- }} 0;
800
- padding: 0 ${(p) => {
801
- var _a;
802
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
803
- }};
804
- display: flex;
805
- gap: ${(p) => {
806
- var _a;
807
- return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
808
- }};
809
- `;
810
- const StyledActionButton = styled.button`
942
+ const StyledButton = styled(Button)`
811
943
  ${buttonCss};
812
- display: block;
813
- background-color: ${(p) => {
814
- var _a;
815
- return (_a = p.theme.colors) == null ? void 0 : _a.primary;
816
- }};
817
- width: 100%;
818
- color: #fff;
819
- margin: ${(p) => {
820
- var _a;
821
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
822
- }} 0;
823
- padding: 0 ${(p) => {
824
- var _a;
825
- return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
826
- }};
827
- font-family: Lato;
828
- font-size: ${(p) => {
829
- var _a;
830
- return (_a = p.theme.fonts) == null ? void 0 : _a.huge;
831
- }};
832
- font-weight: 300;
944
+
945
+ background-color: ${(p) => p.bgColor};
946
+ display: flex;
947
+ justify-content: center;
948
+ align-items: center;
949
+ color: #ffffff;
950
+ width: 46px;
951
+ height: 46px;
952
+ border-radius: 100%;
953
+
833
954
  &:focus {
834
955
  ${(p) => {
835
956
  var _a;
836
957
  return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && css`
837
958
  ${borderTabStyle}
838
959
  background-color: transparent;
960
+
961
+ i,
962
+ svg {
963
+ color: ${(p2) => {
964
+ var _a2;
965
+ return (_a2 = p2.theme.colors) == null ? void 0 : _a2.primary;
966
+ }};
967
+
968
+ path {
969
+ stroke: ${(p2) => {
970
+ var _a2;
971
+ return (_a2 = p2.theme.colors) == null ? void 0 : _a2.primary;
972
+ }};
973
+ }
974
+ }
839
975
  `;
840
976
  }}
841
977
  }
842
- `;
843
- const StyledTimestamp = styled.p`
844
- && {
845
- font-size: ${(p) => {
846
- var _a;
847
- return (_a = p.theme.fonts) == null ? void 0 : _a.small;
848
- }};
849
- font-weight: 300;
978
+
979
+ i,
980
+ svg {
981
+ color: #fff;
982
+
983
+ path {
984
+ stroke: #fff;
985
+ }
850
986
  }
851
- padding-top: ${(p) => {
852
- var _a;
853
- return (_a = p.theme.sizes) == null ? void 0 : _a.small;
854
- }};
855
- margin: 0;
856
- line-height: 1.5em;
857
- grid-area: info;
858
- color: ${(p) => {
859
- var _a;
860
- return (_a = p.theme.colors) == null ? void 0 : _a.text;
861
- }};
862
987
  `;
863
- const getTimestamp = (raw) => {
864
- return new Date(raw).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
988
+ const mapItem = ([type, content]) => {
989
+ return { type, content, id: uuid() };
865
990
  };
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;
991
+ const MessageList = ({ items, dispatch }) => {
992
+ return /* @__PURE__ */ React.createElement(StyledList, {
993
+ items: items.map(mapItem),
994
+ renderLi: true,
995
+ renderItem: (item) => {
996
+ switch (item.type) {
997
+ case ConversationMessageListItemType.Text: {
998
+ return /* @__PURE__ */ React.createElement(Text, {
999
+ text: item.content
1000
+ });
1001
+ }
1002
+ case ConversationMessageListItemType.HTML: {
1003
+ return /* @__PURE__ */ React.createElement(Html, __spreadValues({}, item.content));
1004
+ }
1005
+ case ConversationMessageListItemType.Separator: {
1006
+ return /* @__PURE__ */ React.createElement(Separator, __spreadValues({}, item.content));
1007
+ }
1008
+ case ConversationMessageListItemType.LinkList: {
1009
+ return /* @__PURE__ */ React.createElement(LinkList, __spreadProps(__spreadValues({}, item.content), {
1010
+ dispatch
1011
+ }));
1012
+ }
1013
+ case ConversationMessageListItemType.ButtonList: {
1014
+ return /* @__PURE__ */ React.createElement(ButtonList, __spreadProps(__spreadValues({}, item.content), {
1015
+ dispatch
1016
+ }));
1017
+ }
1018
+ case ConversationMessageListItemType.VideoRequest: {
1019
+ return /* @__PURE__ */ React.createElement(VideoRequest, __spreadProps(__spreadValues({}, item.content), {
1020
+ dispatch
1021
+ }));
1022
+ }
1023
+ default: {
1024
+ return /* @__PURE__ */ React.createElement(Custom, {
1025
+ type: item.type,
1026
+ content: item.content
1027
+ });
1028
+ }
1029
+ }
876
1030
  }
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
- `};
916
- `;
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
- })));
1031
+ });
934
1032
  };
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;
946
- font-size: ${(p) => {
947
- var _a;
948
- return (_a = p.theme.fonts) == null ? void 0 : _a.normal;
949
- }};
950
- color: ${(p) => {
951
- var _a;
952
- return (_a = p.theme.colors) == null ? void 0 : _a.text;
953
- }};
954
- > p {
1033
+ const StyledList = styled(List)`
1034
+ ${list}
1035
+
1036
+ > li {
955
1037
  margin: 0;
956
1038
  }
957
1039
  `;
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;
973
- `;
974
- const imageLightboxRenderer = (attrs) => /* @__PURE__ */ React.createElement(Lightbox, {
975
- attrs
976
- });
977
- const htmlParseInstructions = {
978
- transform: {
979
- img: imageLightboxRenderer
980
- }
981
- };
982
- const ConversationMessageComponent = ({
1040
+ const ConversationMessage = ({
983
1041
  className,
984
1042
  timestamp,
985
1043
  sender,
986
1044
  type,
987
1045
  content
988
1046
  }) => {
989
- const getMessageStackPosition = (index) => {
1047
+ const getMessageStackPosition = useCallback((index) => {
990
1048
  let messageOrder = "first";
991
1049
  if (content.length > 1) {
992
1050
  messageOrder = index === 0 ? "first" : index + 1 === content.length ? "last" : "middle";
993
1051
  }
994
1052
  return messageOrder;
995
- };
1053
+ }, [content]);
996
1054
  const createSystemMessage = () => {
997
1055
  return /* @__PURE__ */ React.createElement(React.Fragment, null, content.map((item) => {
998
1056
  const { key, body, title, form, actions } = item;
@@ -1003,10 +1061,9 @@ const ConversationMessageComponent = ({
1003
1061
  discrete,
1004
1062
  timestamp,
1005
1063
  fullWidth: !!form || !!actions
1006
- }, discrete && body ? /* @__PURE__ */ React.createElement(Html$1, {
1007
- html: body,
1008
- htmlParseInstruction: htmlParseInstructions
1009
- }) : /* @__PURE__ */ React.createElement(ConversationContent, {
1064
+ }, discrete && body ? /* @__PURE__ */ React.createElement(Html, {
1065
+ body
1066
+ }) : /* @__PURE__ */ React.createElement(Message, {
1010
1067
  content: item,
1011
1068
  isUser: false
1012
1069
  }));
@@ -1020,7 +1077,7 @@ const ConversationMessageComponent = ({
1020
1077
  }, /* @__PURE__ */ React.createElement(ContentBundle, null, content.map((item, index) => {
1021
1078
  return /* @__PURE__ */ React.createElement(MessageContainer, {
1022
1079
  key: item.key
1023
- }, /* @__PURE__ */ React.createElement(ConversationContent, {
1080
+ }, /* @__PURE__ */ React.createElement(Message, {
1024
1081
  content: item,
1025
1082
  isUser: false,
1026
1083
  stacked: getMessageStackPosition(index)
@@ -1033,8 +1090,9 @@ const ConversationMessageComponent = ({
1033
1090
  className
1034
1091
  }, /* @__PURE__ */ React.createElement(ContentBundle, null, content.map((item, index) => {
1035
1092
  return /* @__PURE__ */ React.createElement(MessageContainer, {
1093
+ user: true,
1036
1094
  key: item.key
1037
- }, /* @__PURE__ */ React.createElement(ConversationContent, {
1095
+ }, /* @__PURE__ */ React.createElement(Message, {
1038
1096
  content: item,
1039
1097
  isUser: true,
1040
1098
  stacked: getMessageStackPosition(index)
@@ -1052,7 +1110,45 @@ const ConversationMessageComponent = ({
1052
1110
  return null;
1053
1111
  }
1054
1112
  };
1055
- const Conversation = ({ className }) => {
1113
+ const Message = ({ content, isUser, stacked }) => {
1114
+ const dispatch = useDispatch();
1115
+ const { title, body, actions, form, items } = content;
1116
+ return /* @__PURE__ */ React.createElement(MessageContent, {
1117
+ user: isUser,
1118
+ stacked,
1119
+ fullWidth: !!form || !!actions
1120
+ }, title && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(MessageTitle, {
1121
+ variant: "h2"
1122
+ }, title)), body && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(Html, {
1123
+ body
1124
+ })), form && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(StyledForm, __spreadProps(__spreadValues({}, form), {
1125
+ onChange: (key, data) => {
1126
+ dispatch("form", {
1127
+ data,
1128
+ formKey: form.schema.id,
1129
+ actionKey: key
1130
+ });
1131
+ }
1132
+ }))), actions && /* @__PURE__ */ React.createElement(MessageContentPart, null, /* @__PURE__ */ React.createElement(StyledActionList, {
1133
+ items: Object.keys(actions).map((i) => {
1134
+ return { label: actions[i], actionKey: i };
1135
+ }),
1136
+ renderItem: (item) => {
1137
+ return /* @__PURE__ */ React.createElement("li", {
1138
+ key: item.actionKey
1139
+ }, /* @__PURE__ */ React.createElement(StyledActionButton, {
1140
+ onClick: () => {
1141
+ dispatch("action", item.actionKey);
1142
+ }
1143
+ }, item.label));
1144
+ }
1145
+ })), items && /* @__PURE__ */ React.createElement(MessageList, {
1146
+ key: uuid(),
1147
+ items,
1148
+ dispatch
1149
+ }));
1150
+ };
1151
+ const ConversationContent = () => {
1056
1152
  const lastEntry = useRef(document.createElement("div"));
1057
1153
  const [scrollableCss, viewElem] = useScroll(true);
1058
1154
  const { messages, loading, typingActors } = useProperties();
@@ -1112,9 +1208,7 @@ const Conversation = ({ className }) => {
1112
1208
  }
1113
1209
  return null;
1114
1210
  };
1115
- return /* @__PURE__ */ React.createElement(Wrapper, {
1116
- className: appendClassNames(className, "humany-conversation-component")
1117
- }, /* @__PURE__ */ React.createElement(Scrollable, {
1211
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Scrollable, {
1118
1212
  tabIndex: 0,
1119
1213
  scrollableCss,
1120
1214
  ref: viewElem
@@ -1125,19 +1219,9 @@ const Conversation = ({ className }) => {
1125
1219
  tabIndex: -1,
1126
1220
  key: `${type}_${sender == null ? void 0 : sender.name}_${timestamp}_${content[0].key}`,
1127
1221
  ref: index + 1 < messages.length ? null : typingActors.length ? null : lastEntry
1128
- }, /* @__PURE__ */ React.createElement(ConversationMessageComponent, __spreadValues({}, message)));
1222
+ }, /* @__PURE__ */ React.createElement(ConversationMessage, __spreadValues({}, message)));
1129
1223
  }) : null, renderTypingActors(), loading && /* @__PURE__ */ React.createElement(MessageEntry, null, /* @__PURE__ */ React.createElement(ConversationLoader, null))), /* @__PURE__ */ React.createElement(ConversationInput, null));
1130
1224
  };
1131
- const Wrapper = styled.div`
1132
- position: absolute;
1133
- right: 0;
1134
- left: 0;
1135
- bottom: 0;
1136
- top: 0;
1137
- overflow: hidden;
1138
- display: flex;
1139
- flex-direction: column;
1140
- `;
1141
1225
  const Scrollable = styled.div`
1142
1226
  display: flex;
1143
1227
  flex-direction: column;
@@ -1192,5 +1276,140 @@ const MessageEntry = styled.div`
1192
1276
  font-weight: normal;
1193
1277
  `)}
1194
1278
  `;
1279
+ const OverlayOutlet = ({ dispatch }) => {
1280
+ const wrapperRef = useRef(null);
1281
+ useEffect(() => {
1282
+ if (wrapperRef.current && wrapperRef.current.parentNode) {
1283
+ dispatch("overlay-mounted", wrapperRef.current);
1284
+ }
1285
+ }, [wrapperRef]);
1286
+ return /* @__PURE__ */ React.createElement(WidgetOverlayOutlet, {
1287
+ portalId: "humany-conversation-overlay-portal",
1288
+ className: "humany-conversation-overlay-outlet",
1289
+ ref: wrapperRef
1290
+ });
1291
+ };
1292
+ const ConversationOverlayOutlet = ({
1293
+ dispatch,
1294
+ header,
1295
+ buttonLabel
1296
+ }) => {
1297
+ return /* @__PURE__ */ React.createElement(StyledWidgetOverlayOutlet, {
1298
+ portalId: "humany-conversation-portal",
1299
+ className: "humany-conversation-outlet"
1300
+ }, /* @__PURE__ */ React.createElement(ConversationOverlayHead, {
1301
+ className: "humany-conversation-outlet-head"
1302
+ }, /* @__PURE__ */ React.createElement(ConversationOverlayHeadButton, {
1303
+ className: "humany-conversation-outlet-head-button",
1304
+ "aria-label": buttonLabel,
1305
+ title: buttonLabel,
1306
+ onClick: () => dispatch("hide-overlay-conversation")
1307
+ }, /* @__PURE__ */ React.createElement(SymbolBadge, {
1308
+ symbol: {
1309
+ type: "Svg",
1310
+ content: "caret-down"
1311
+ },
1312
+ size: 20
1313
+ })), header && /* @__PURE__ */ React.createElement(ConversationOverlayHeader, {
1314
+ className: "humany-conversation-outlet-header",
1315
+ variant: "h1"
1316
+ }, header)), /* @__PURE__ */ React.createElement(ConversationContent, null));
1317
+ };
1318
+ const StyledWidgetOverlayOutlet = styled(WidgetOverlayOutlet)`
1319
+ z-index: 11;
1320
+ top: auto;
1321
+ height: 65%;
1322
+ background-color: #ffffff;
1323
+ display: flex;
1324
+ flex-direction: column;
1325
+ border-top-right-radius: ${(p) => {
1326
+ var _a;
1327
+ return (_a = p.theme.sizes) == null ? void 0 : _a.large;
1328
+ }};
1329
+ border-top-left-radius: ${(p) => {
1330
+ var _a;
1331
+ return (_a = p.theme.sizes) == null ? void 0 : _a.large;
1332
+ }};
1333
+ `;
1334
+ const ConversationOverlayHead = styled.div`
1335
+ display: flex;
1336
+ flex-direction: column;
1337
+ justify-content: center;
1338
+ align-items: center;
1339
+ gap: ${(p) => {
1340
+ var _a;
1341
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
1342
+ }};
1343
+ padding: ${(p) => {
1344
+ var _a;
1345
+ return (_a = p.theme.sizes) == null ? void 0 : _a.normal;
1346
+ }};
1347
+ ${(p) => p.theme.border && `border-bottom: ${p.theme.border};`}
1348
+ `;
1349
+ const ConversationOverlayHeader = styled(Typography)`
1350
+ font-size: ${(p) => {
1351
+ var _a;
1352
+ return (_a = p.theme.fonts) == null ? void 0 : _a.medium;
1353
+ }};
1354
+ color: ${(p) => {
1355
+ var _a;
1356
+ return (_a = p.theme.colors) == null ? void 0 : _a.text;
1357
+ }};
1358
+ margin: 0;
1359
+ `;
1360
+ const ConversationOverlayHeadButton = styled(Button)`
1361
+ display: flex;
1362
+ align-items: center;
1363
+ justify-content: center;
1364
+ padding: ${(p) => {
1365
+ var _a;
1366
+ return (_a = p.theme.sizes) == null ? void 0 : _a.small;
1367
+ }} ${(p) => {
1368
+ var _a;
1369
+ return (_a = p.theme.sizes) == null ? void 0 : _a.medium;
1370
+ }};
1371
+ ${(p) => p.theme.borderRadius && `border-radius: ${p.theme.borderRadius};`}
1372
+
1373
+ &:focus {
1374
+ ${(p) => {
1375
+ var _a;
1376
+ return ((_a = p.theme.accessibility) == null ? void 0 : _a.isTabbing) && borderTabStyle;
1377
+ }};
1378
+ }
1379
+
1380
+ svg line {
1381
+ stroke: ${(p) => {
1382
+ var _a;
1383
+ return (_a = p.theme.colors) == null ? void 0 : _a.text;
1384
+ }};
1385
+ }
1386
+ `;
1387
+ const Conversation = ({ className }) => {
1388
+ const {
1389
+ overlay,
1390
+ overlayConversationHeader,
1391
+ overlayConversationCloseLabel
1392
+ } = useProperties();
1393
+ const dispatch = useDispatch();
1394
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Wrapper, {
1395
+ className: appendClassNames(className, "humany-conversation-component")
1396
+ }, /* @__PURE__ */ React.createElement(ConversationContent, null)), overlay && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(OverlayOutlet, {
1397
+ dispatch
1398
+ }), overlay.conversation && /* @__PURE__ */ React.createElement(ConversationOverlayOutlet, {
1399
+ dispatch,
1400
+ header: overlayConversationHeader,
1401
+ buttonLabel: overlayConversationCloseLabel
1402
+ })));
1403
+ };
1404
+ const Wrapper = styled.div`
1405
+ position: absolute;
1406
+ right: 0;
1407
+ left: 0;
1408
+ bottom: 0;
1409
+ top: 0;
1410
+ overflow: hidden;
1411
+ display: flex;
1412
+ flex-direction: column;
1413
+ `;
1195
1414
  export { Conversation as default };
1196
1415
  //# sourceMappingURL=conversation.js.map