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.cjs +49 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +83 -37
- package/dist/index.css.map +1 -1
- package/dist/index.mjs +49 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
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
|
-
|
|
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.
|
|
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
|
|
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:
|
|
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.
|
|
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(() => {
|