wealth-alpha-chat-widget 1.0.3 → 1.0.5

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.
package/dist/index.mjs CHANGED
@@ -677,6 +677,9 @@ function useSession(opts = {}) {
677
677
  // src/styles/chat.module.css
678
678
  var chat_default = {
679
679
  root: "chat_root",
680
+ headerTitle: "chat_headerTitle",
681
+ menuItemTitle: "chat_menuItemTitle",
682
+ markdown: "chat_markdown",
680
683
  floatingButton: "chat_floatingButton",
681
684
  positionRight: "chat_positionRight",
682
685
  positionLeft: "chat_positionLeft",
@@ -684,15 +687,14 @@ var chat_default = {
684
687
  popupBubbleLeft: "chat_popupBubbleLeft",
685
688
  popupBubbleRight: "chat_popupBubbleRight",
686
689
  header: "chat_header",
687
- headerTitle: "chat_headerTitle",
688
690
  headerMeta: "chat_headerMeta",
689
691
  headerActions: "chat_headerActions",
690
692
  iconButton: "chat_iconButton",
691
693
  body: "chat_body",
692
694
  bubble: "chat_bubble",
693
- markdown: "chat_markdown",
694
695
  bubbleBot: "chat_bubbleBot",
695
696
  bubbleUser: "chat_bubbleUser",
697
+ bubbleCard: "chat_bubbleCard",
696
698
  bubbleMeta: "chat_bubbleMeta",
697
699
  chipRow: "chat_chipRow",
698
700
  chip: "chat_chip",
@@ -720,7 +722,7 @@ var chat_default = {
720
722
  menuGrid: "chat_menuGrid",
721
723
  menuItem: "chat_menuItem",
722
724
  menuItemIcon: "chat_menuItemIcon",
723
- menuItemTitle: "chat_menuItemTitle",
725
+ menuItemSvg: "chat_menuItemSvg",
724
726
  menuItemSub: "chat_menuItemSub",
725
727
  menuIconGreen: "chat_menuIconGreen",
726
728
  menuIconBlue: "chat_menuIconBlue",
@@ -729,7 +731,8 @@ var chat_default = {
729
731
  menuIconOrange: "chat_menuIconOrange",
730
732
  menuIconGold: "chat_menuIconGold",
731
733
  menuIconTeal: "chat_menuIconTeal",
732
- menuIconPurple: "chat_menuIconPurple"
734
+ menuIconPurple: "chat_menuIconPurple",
735
+ chat_bubbleBot: "chat_chat_bubbleBot"
733
736
  };
734
737
  function AuthGate({ brandName, loginUrl, onLoginClick }) {
735
738
  const handleClick = () => {
@@ -815,15 +818,21 @@ var SANITIZE_CFG = {
815
818
  function inlineMarkdownToHtml(text) {
816
819
  return text.replace(/^[ \t]*#{1,6}[ \t]+(.+?)[ \t]*$/gm, "<b>$1</b>").replace(/\*\*([^\n<>]+?)\*\*/g, "<b>$1</b>").replace(/__([^\n<>]+?)__/g, "<b>$1</b>").replace(/(?<!\*)\*([^\n*<>]+?)\*(?!\*)/g, "<b>$1</b>").replace(/(?<![_a-zA-Z0-9])_([^\n_<>]+?)_(?![_a-zA-Z0-9])/g, "<i>$1</i>");
817
820
  }
821
+ function stripCardDateTime(html) {
822
+ return html.replace(
823
+ /(<span class="wa-card-date">)([^<]*)(<\/span>)/g,
824
+ (_m, open, content, close) => open + content.replace(/,\s*\d{1,2}:\d{2}.*$/, "").trim() + close
825
+ );
826
+ }
818
827
  function renderMarkdown(text) {
819
828
  if (!text) return "";
820
829
  const inlined = inlineMarkdownToHtml(text);
821
830
  if (/<div[\s>]/i.test(inlined)) {
822
- return DOMPurify.sanitize(inlined, SANITIZE_CFG);
831
+ return DOMPurify.sanitize(stripCardDateTime(inlined), SANITIZE_CFG);
823
832
  }
824
833
  const paragraphs = inlined.split(/\n{2,}/).map((para) => para.replace(/\n/g, "<br>")).filter((p) => p.length > 0);
825
834
  const html = paragraphs.length > 1 ? paragraphs.map((p) => `<p>${p}</p>`).join("") : paragraphs[0] ?? "";
826
- return DOMPurify.sanitize(html, SANITIZE_CFG);
835
+ return DOMPurify.sanitize(stripCardDateTime(html), SANITIZE_CFG);
827
836
  }
828
837
  var ROOT_MENU_CHIP_IDS = /* @__PURE__ */ new Set([
829
838
  "stock_analysis",
@@ -855,12 +864,23 @@ var MENU_ICON_KEY = {
855
864
  tradable_picks: "menuIconTeal",
856
865
  peer_compare: "menuIconPurple"
857
866
  };
867
+ var MENU_ICON_SVG = {
868
+ stock_analysis: ' <path d="M4 16L9 11L13 15L20 8" /> <path d="M20 8V13" /> <path d="M20 8H15" />',
869
+ stock_discovery: '<circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/>',
870
+ new_listings: '<rect x="5" y="5" width="14" height="14" rx="3"/><path d="M12 8v8"/> <path d="M8 12h8"/>',
871
+ portfolio_risk: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"/>',
872
+ market_forecast: '<path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z"/>',
873
+ crypto: '<path d="M4 20V10M10 20V4M16 20v-7M22 20v-4"/>',
874
+ tradable_picks: '<circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1.5"/>',
875
+ peer_compare: '<path d="M12 3v18"/><path d="M5 8l-3 6h6z"/><path d="M19 8l-3 6h6z"/>'
876
+ };
858
877
  function isRootMenuChips(chips) {
859
- return chips.some((c) => ROOT_MENU_CHIP_IDS.has(c.id));
878
+ return chips.length > 0 && chips.every((c) => ROOT_MENU_CHIP_IDS.has(c.id));
860
879
  }
861
880
  function MessageBubble({ message, onChipClick }) {
862
881
  const isBot = message.role === "bot";
863
- const bubbleClass = isBot ? `${chat_default.bubble} ${chat_default.bubbleBot}` : `${chat_default.bubble} ${chat_default.bubbleUser}`;
882
+ const isCard = isBot && message.content.includes("<div");
883
+ const bubbleClass = isBot ? `${chat_default.bubble} ${isCard ? chat_default.bubbleCard : chat_default.bubbleBot}` : `${chat_default.bubble} ${chat_default.bubbleUser}`;
864
884
  const handleMarkdownClick = (e) => {
865
885
  const anchor = e.target.closest("a");
866
886
  if (!anchor?.href) return;
@@ -881,6 +901,7 @@ function MessageBubble({ message, onChipClick }) {
881
901
  showMenuGrid ? /* @__PURE__ */ jsx("div", { className: chat_default.menuGrid, children: chips.map((chip) => {
882
902
  const iconKey = MENU_ICON_KEY[chip.id];
883
903
  const iconClass = iconKey && chat_default[iconKey] || "";
904
+ const svgIcon = MENU_ICON_SVG[chip.id];
884
905
  return /* @__PURE__ */ jsxs(
885
906
  "button",
886
907
  {
@@ -888,7 +909,15 @@ function MessageBubble({ message, onChipClick }) {
888
909
  className: chat_default.menuItem,
889
910
  onClick: () => onChipClick(chip),
890
911
  children: [
891
- /* @__PURE__ */ jsx("div", { className: `${chat_default.menuItemIcon} ${iconClass}`, children: chip.icon }),
912
+ /* @__PURE__ */ jsx("div", { className: `${chat_default.menuItemIcon} ${iconClass}`, children: svgIcon ? /* @__PURE__ */ jsx(
913
+ "svg",
914
+ {
915
+ className: chat_default.menuItemSvg,
916
+ viewBox: "0 0 24 24",
917
+ "aria-hidden": "true",
918
+ dangerouslySetInnerHTML: { __html: svgIcon }
919
+ }
920
+ ) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: chip.icon }) }),
892
921
  /* @__PURE__ */ jsx("div", { className: chat_default.menuItemTitle, children: chip.label }),
893
922
  /* @__PURE__ */ jsx("div", { className: chat_default.menuItemSub, children: MENU_SUBTITLES[chip.id] ?? "" })
894
923
  ]
@@ -947,18 +976,6 @@ function ChatBody({
947
976
  /* @__PURE__ */ jsx("div", { ref: endRef })
948
977
  ] });
949
978
  }
950
-
951
- // src/utils/time.ts
952
- function formatCountdown(remainingMs) {
953
- if (remainingMs <= 0) return "expired";
954
- const totalSeconds = Math.floor(remainingMs / 1e3);
955
- const hours = Math.floor(totalSeconds / 3600);
956
- const minutes = Math.floor(totalSeconds % 3600 / 60);
957
- const seconds = totalSeconds % 60;
958
- if (hours > 0) return `${hours}h ${minutes}m left`;
959
- if (minutes > 0) return `${minutes}m ${seconds}s left`;
960
- return `${seconds}s left`;
961
- }
962
979
  function ChatHeader({
963
980
  brandName,
964
981
  remainingMs,
@@ -967,13 +984,7 @@ function ChatHeader({
967
984
  onClear
968
985
  }) {
969
986
  return /* @__PURE__ */ jsxs("div", { className: chat_default.header, children: [
970
- /* @__PURE__ */ jsxs("div", { children: [
971
- /* @__PURE__ */ jsx("div", { className: chat_default.headerTitle, children: brandName }),
972
- showCountdown && remainingMs > 0 ? /* @__PURE__ */ jsxs("div", { className: chat_default.headerMeta, children: [
973
- "Session: ",
974
- formatCountdown(remainingMs)
975
- ] }) : null
976
- ] }),
987
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("div", { className: chat_default.headerTitle, children: brandName }) }),
977
988
  /* @__PURE__ */ jsxs("div", { className: chat_default.headerActions, children: [
978
989
  onClear ? /* @__PURE__ */ jsx(
979
990
  "button",
@@ -1130,6 +1141,16 @@ function WealthChat(props) {
1130
1141
  useEffect(() => {
1131
1142
  setMounted(true);
1132
1143
  }, []);
1144
+ useEffect(() => {
1145
+ if (typeof document === "undefined") return;
1146
+ const id = "wac-google-fonts";
1147
+ if (document.getElementById(id)) return;
1148
+ const link = document.createElement("link");
1149
+ link.id = id;
1150
+ link.rel = "stylesheet";
1151
+ link.href = "https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Sora:wght@600;700;800&display=swap";
1152
+ document.head.appendChild(link);
1153
+ }, []);
1133
1154
  useEffect(() => {
1134
1155
  if (!mounted || open || popupShownRef.current) return;
1135
1156
  const timer = setTimeout(() => {