wealth-alpha-chat-widget 1.0.3 → 1.0.4

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.cjs CHANGED
@@ -683,6 +683,9 @@ function useSession(opts = {}) {
683
683
  // src/styles/chat.module.css
684
684
  var chat_default = {
685
685
  root: "chat_root",
686
+ headerTitle: "chat_headerTitle",
687
+ menuItemTitle: "chat_menuItemTitle",
688
+ markdown: "chat_markdown",
686
689
  floatingButton: "chat_floatingButton",
687
690
  positionRight: "chat_positionRight",
688
691
  positionLeft: "chat_positionLeft",
@@ -690,15 +693,14 @@ var chat_default = {
690
693
  popupBubbleLeft: "chat_popupBubbleLeft",
691
694
  popupBubbleRight: "chat_popupBubbleRight",
692
695
  header: "chat_header",
693
- headerTitle: "chat_headerTitle",
694
696
  headerMeta: "chat_headerMeta",
695
697
  headerActions: "chat_headerActions",
696
698
  iconButton: "chat_iconButton",
697
699
  body: "chat_body",
698
700
  bubble: "chat_bubble",
699
- markdown: "chat_markdown",
700
701
  bubbleBot: "chat_bubbleBot",
701
702
  bubbleUser: "chat_bubbleUser",
703
+ bubbleCard: "chat_bubbleCard",
702
704
  bubbleMeta: "chat_bubbleMeta",
703
705
  chipRow: "chat_chipRow",
704
706
  chip: "chat_chip",
@@ -726,7 +728,7 @@ var chat_default = {
726
728
  menuGrid: "chat_menuGrid",
727
729
  menuItem: "chat_menuItem",
728
730
  menuItemIcon: "chat_menuItemIcon",
729
- menuItemTitle: "chat_menuItemTitle",
731
+ menuItemSvg: "chat_menuItemSvg",
730
732
  menuItemSub: "chat_menuItemSub",
731
733
  menuIconGreen: "chat_menuIconGreen",
732
734
  menuIconBlue: "chat_menuIconBlue",
@@ -735,7 +737,8 @@ var chat_default = {
735
737
  menuIconOrange: "chat_menuIconOrange",
736
738
  menuIconGold: "chat_menuIconGold",
737
739
  menuIconTeal: "chat_menuIconTeal",
738
- menuIconPurple: "chat_menuIconPurple"
740
+ menuIconPurple: "chat_menuIconPurple",
741
+ chat_bubbleBot: "chat_chat_bubbleBot"
739
742
  };
740
743
  function AuthGate({ brandName, loginUrl, onLoginClick }) {
741
744
  const handleClick = () => {
@@ -821,15 +824,21 @@ var SANITIZE_CFG = {
821
824
  function inlineMarkdownToHtml(text) {
822
825
  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>");
823
826
  }
827
+ function stripCardDateTime(html) {
828
+ return html.replace(
829
+ /(<span class="wa-card-date">)([^<]*)(<\/span>)/g,
830
+ (_m, open, content, close) => open + content.replace(/,\s*\d{1,2}:\d{2}.*$/, "").trim() + close
831
+ );
832
+ }
824
833
  function renderMarkdown(text) {
825
834
  if (!text) return "";
826
835
  const inlined = inlineMarkdownToHtml(text);
827
836
  if (/<div[\s>]/i.test(inlined)) {
828
- return DOMPurify__default.default.sanitize(inlined, SANITIZE_CFG);
837
+ return DOMPurify__default.default.sanitize(stripCardDateTime(inlined), SANITIZE_CFG);
829
838
  }
830
839
  const paragraphs = inlined.split(/\n{2,}/).map((para) => para.replace(/\n/g, "<br>")).filter((p) => p.length > 0);
831
840
  const html = paragraphs.length > 1 ? paragraphs.map((p) => `<p>${p}</p>`).join("") : paragraphs[0] ?? "";
832
- return DOMPurify__default.default.sanitize(html, SANITIZE_CFG);
841
+ return DOMPurify__default.default.sanitize(stripCardDateTime(html), SANITIZE_CFG);
833
842
  }
834
843
  var ROOT_MENU_CHIP_IDS = /* @__PURE__ */ new Set([
835
844
  "stock_analysis",
@@ -861,12 +870,23 @@ var MENU_ICON_KEY = {
861
870
  tradable_picks: "menuIconTeal",
862
871
  peer_compare: "menuIconPurple"
863
872
  };
873
+ var MENU_ICON_SVG = {
874
+ stock_analysis: ' <path d="M4 16L9 11L13 15L20 8" /> <path d="M20 8V13" /> <path d="M20 8H15" />',
875
+ stock_discovery: '<circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/>',
876
+ new_listings: '<rect x="5" y="5" width="14" height="14" rx="3"/><path d="M12 8v8"/> <path d="M8 12h8"/>',
877
+ portfolio_risk: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"/>',
878
+ market_forecast: '<path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z"/>',
879
+ crypto: '<path d="M4 20V10M10 20V4M16 20v-7M22 20v-4"/>',
880
+ tradable_picks: '<circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1.5"/>',
881
+ peer_compare: '<path d="M12 3v18"/><path d="M5 8l-3 6h6z"/><path d="M19 8l-3 6h6z"/>'
882
+ };
864
883
  function isRootMenuChips(chips) {
865
- return chips.some((c) => ROOT_MENU_CHIP_IDS.has(c.id));
884
+ return chips.length > 0 && chips.every((c) => ROOT_MENU_CHIP_IDS.has(c.id));
866
885
  }
867
886
  function MessageBubble({ message, onChipClick }) {
868
887
  const isBot = message.role === "bot";
869
- const bubbleClass = isBot ? `${chat_default.bubble} ${chat_default.bubbleBot}` : `${chat_default.bubble} ${chat_default.bubbleUser}`;
888
+ const isCard = isBot && message.content.includes("<div");
889
+ const bubbleClass = isBot ? `${chat_default.bubble} ${isCard ? chat_default.bubbleCard : chat_default.bubbleBot}` : `${chat_default.bubble} ${chat_default.bubbleUser}`;
870
890
  const handleMarkdownClick = (e) => {
871
891
  const anchor = e.target.closest("a");
872
892
  if (!anchor?.href) return;
@@ -887,6 +907,7 @@ function MessageBubble({ message, onChipClick }) {
887
907
  showMenuGrid ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: chat_default.menuGrid, children: chips.map((chip) => {
888
908
  const iconKey = MENU_ICON_KEY[chip.id];
889
909
  const iconClass = iconKey && chat_default[iconKey] || "";
910
+ const svgIcon = MENU_ICON_SVG[chip.id];
890
911
  return /* @__PURE__ */ jsxRuntime.jsxs(
891
912
  "button",
892
913
  {
@@ -894,7 +915,15 @@ function MessageBubble({ message, onChipClick }) {
894
915
  className: chat_default.menuItem,
895
916
  onClick: () => onChipClick(chip),
896
917
  children: [
897
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${chat_default.menuItemIcon} ${iconClass}`, children: chip.icon }),
918
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${chat_default.menuItemIcon} ${iconClass}`, children: svgIcon ? /* @__PURE__ */ jsxRuntime.jsx(
919
+ "svg",
920
+ {
921
+ className: chat_default.menuItemSvg,
922
+ viewBox: "0 0 24 24",
923
+ "aria-hidden": "true",
924
+ dangerouslySetInnerHTML: { __html: svgIcon }
925
+ }
926
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: chip.icon }) }),
898
927
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: chat_default.menuItemTitle, children: chip.label }),
899
928
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: chat_default.menuItemSub, children: MENU_SUBTITLES[chip.id] ?? "" })
900
929
  ]
@@ -953,18 +982,6 @@ function ChatBody({
953
982
  /* @__PURE__ */ jsxRuntime.jsx("div", { ref: endRef })
954
983
  ] });
955
984
  }
956
-
957
- // src/utils/time.ts
958
- function formatCountdown(remainingMs) {
959
- if (remainingMs <= 0) return "expired";
960
- const totalSeconds = Math.floor(remainingMs / 1e3);
961
- const hours = Math.floor(totalSeconds / 3600);
962
- const minutes = Math.floor(totalSeconds % 3600 / 60);
963
- const seconds = totalSeconds % 60;
964
- if (hours > 0) return `${hours}h ${minutes}m left`;
965
- if (minutes > 0) return `${minutes}m ${seconds}s left`;
966
- return `${seconds}s left`;
967
- }
968
985
  function ChatHeader({
969
986
  brandName,
970
987
  remainingMs,
@@ -973,13 +990,7 @@ function ChatHeader({
973
990
  onClear
974
991
  }) {
975
992
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chat_default.header, children: [
976
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
977
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: chat_default.headerTitle, children: brandName }),
978
- showCountdown && remainingMs > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chat_default.headerMeta, children: [
979
- "Session: ",
980
- formatCountdown(remainingMs)
981
- ] }) : null
982
- ] }),
993
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: chat_default.headerTitle, children: brandName }) }),
983
994
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chat_default.headerActions, children: [
984
995
  onClear ? /* @__PURE__ */ jsxRuntime.jsx(
985
996
  "button",
@@ -1136,6 +1147,16 @@ function WealthChat(props) {
1136
1147
  react.useEffect(() => {
1137
1148
  setMounted(true);
1138
1149
  }, []);
1150
+ react.useEffect(() => {
1151
+ if (typeof document === "undefined") return;
1152
+ const id = "wac-google-fonts";
1153
+ if (document.getElementById(id)) return;
1154
+ const link = document.createElement("link");
1155
+ link.id = id;
1156
+ link.rel = "stylesheet";
1157
+ link.href = "https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Sora:wght@600;700;800&display=swap";
1158
+ document.head.appendChild(link);
1159
+ }, []);
1139
1160
  react.useEffect(() => {
1140
1161
  if (!mounted || open || popupShownRef.current) return;
1141
1162
  const timer = setTimeout(() => {