pager-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.
Files changed (71) hide show
  1. package/dist/index.css +1 -1
  2. package/dist/index.js +4 -4
  3. package/dist/react-parcel.9f367d21.css +2 -18
  4. package/dist/react-parcel.9f367d21.css.map +1 -1
  5. package/dist/react-parcel.js +119 -214
  6. package/dist/react-parcel.js.map +1 -1
  7. package/out/AgentFeedbackButtonWrapper.js +15 -0
  8. package/out/App.js +28 -0
  9. package/out/BotMain.js +91 -0
  10. package/out/ButtonsWrapper.js +29 -0
  11. package/out/ChatPage.js +9 -0
  12. package/out/ChatPageContent.js +131 -0
  13. package/out/ChatPageHeader.js +267 -0
  14. package/out/ChatPageInput.js +29 -0
  15. package/out/ChatWidget.js +17 -0
  16. package/out/Consent.js +66 -0
  17. package/out/CountryDropdown.js +31 -0
  18. package/out/Form.js +238 -0
  19. package/out/HomePage.js +11 -0
  20. package/out/HomePageContent.js +32 -0
  21. package/out/HomePageFooter.js +87 -0
  22. package/out/HomePageHeader.js +66 -0
  23. package/out/InputField.js +80 -0
  24. package/out/Markdown.js +126 -0
  25. package/out/Message.js +197 -0
  26. package/out/MessagesT.js +2 -0
  27. package/out/NewRecentMessagePage.js +525 -0
  28. package/out/NewRecentMessageTab.js +23 -0
  29. package/out/ReceivedMessage.js +211 -0
  30. package/out/RecentMessageDetail.js +178 -0
  31. package/out/RecentMessageList.js +112 -0
  32. package/out/RecentMessageListCard.js +20 -0
  33. package/out/RecentMessageListHeader.js +156 -0
  34. package/out/RecentMessagePage.js +183 -0
  35. package/out/RecentMessageTab.js +35 -0
  36. package/out/WidgetMessage.js +14 -0
  37. package/out/WidgetToggleButton.js +191 -0
  38. package/out/WidgetType.js +2 -0
  39. package/out/assets/icons/pikaicons-react.js +17475 -0
  40. package/out/components/ConsentForm.js +7 -0
  41. package/out/components/CustomTooltip.js +34 -0
  42. package/out/hooks/useChatHistoryExists.js +32 -0
  43. package/out/hooks/useChatHistoryListExist.js +81 -0
  44. package/out/hooks/useChatScroll.js +14 -0
  45. package/out/hooks/useCurrentConversationExists.js +88 -0
  46. package/out/hooks/useInitialMessage.js +33 -0
  47. package/out/hooks/useMessage.js +230 -0
  48. package/out/hooks/useMessageReceiver.js +183 -0
  49. package/out/hooks/usePopupAnimation.js +20 -0
  50. package/out/hooks/useSocket.js +19 -0
  51. package/out/hooks/useSocketContext.js +81 -0
  52. package/out/hooks/useWidgetDimension.js +41 -0
  53. package/out/hooks/useWidgetToggle.js +22 -0
  54. package/out/index.js +31 -0
  55. package/out/markdown/CodeCopy.js +22 -0
  56. package/out/markdown/CodeHighlight.js +58 -0
  57. package/out/markdown/PagerMarkdown.js +36 -0
  58. package/out/markdown/pager_md.js +152 -0
  59. package/out/onscreenNotificationPopup.js +23 -0
  60. package/out/socket.js +11 -0
  61. package/out/utils/checkConversationExit.js +24 -0
  62. package/out/utils/convertTime.js +43 -0
  63. package/out/utils/sendInitialMessage.js +82 -0
  64. package/out/widget.js +21 -0
  65. package/out/widgetConfigStore.js +205 -0
  66. package/out/widgetConfigStore2.js +569 -0
  67. package/out/widgetControlstore.js +23 -0
  68. package/out/widgetStateHandler.js +106 -0
  69. package/out/widgetStore.js +171 -0
  70. package/out/widgetUserStore.js +47 -0
  71. package/package.json +1 -1
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChatPageInput = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const widgetConfigStore2_1 = require("./widgetConfigStore2");
7
+ const pikaicons_react_1 = require("./assets/icons/pikaicons-react");
8
+ const ChatPageInput = ({ sendMessage }) => {
9
+ const [typedMessage, setTypedMessage] = (0, react_1.useState)('');
10
+ const widget = (0, widgetConfigStore2_1.useWidgetData)();
11
+ const [isSendHover, setIsSendHover] = (0, react_1.useState)(false);
12
+ const send = () => {
13
+ if (typedMessage.trim()) {
14
+ sendMessage(typedMessage);
15
+ }
16
+ setTypedMessage('');
17
+ };
18
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: widget.status === 'ALLOW_MESSAGE' && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col items-start p-5 gap-2.5", children: (0, jsx_runtime_1.jsx)("div", { className: "w-full border border-zinc-300 rounded-lg overflow-hidden bg-white", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 px-4 py-2.5", children: [(0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Enter message", className: "flex-1 text-sm text-[#1d293d] placeholder-[#62748e] outline-none", value: typedMessage, onChange: (e) => setTypedMessage(e.target.value), onKeyDown: (e) => {
19
+ if (e.key === 'Enter') {
20
+ e.preventDefault();
21
+ send();
22
+ }
23
+ } }), (0, jsx_runtime_1.jsx)("button", { className: "p-1.5 rounded-full transition-colors cursor-pointer flex items-center justify-center", onClick: () => send(), onMouseEnter: () => setIsSendHover(true), onMouseLeave: () => setIsSendHover(false), style: {
24
+ color: isSendHover
25
+ ? widget.data?.brand_color || '#4B2FFF'
26
+ : '#62748e',
27
+ }, children: isSendHover ? ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiSendPlaneSlantSolid, { className: "w-5 h-5" })) : ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiSendPlaneSlantStroke, { className: "w-5 h-5" })) })] }) }) })) }));
28
+ };
29
+ exports.ChatPageInput = ChatPageInput;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ChatWidget = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const widgetConfigStore2_1 = require("./widgetConfigStore2");
9
+ const BotMain_1 = __importDefault(require("./BotMain"));
10
+ const useSocketContext_1 = require("./hooks/useSocketContext");
11
+ const ChatWidget = ({ widgetToggleState, toggleWidget, widgetConfig, }) => {
12
+ const widget = (0, widgetConfigStore2_1.useWidgetData)();
13
+ console.log('DEBUG:: widget', widget);
14
+ const isWidgetOpen = widgetToggleState === 'OPEN' && widget.status !== 'INVALID_STATE';
15
+ return ((0, jsx_runtime_1.jsx)(useSocketContext_1.SocketProvider, { endpoint: widgetConfig.endpoint, children: isWidgetOpen && ((0, jsx_runtime_1.jsx)(BotMain_1.default, { toggleWidget: toggleWidget, widgetToggleState: widgetToggleState, widgetConfig: widgetConfig })) }));
16
+ };
17
+ exports.ChatWidget = ChatWidget;
package/out/Consent.js ADDED
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Consent = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const widgetConfigStore2_1 = require("./widgetConfigStore2");
9
+ const react_device_detect_1 = require("react-device-detect");
10
+ const uuid_1 = require("uuid");
11
+ const pager_md_1 = __importDefault(require("./markdown/pager_md"));
12
+ const widgetStore_1 = require("./widgetStore");
13
+ const Consent = () => {
14
+ const widget = (0, widgetConfigStore2_1.useWidgetData)();
15
+ // const current_conversation_id = useGetCurrentConversationId()
16
+ if (widget.status === 'CONSENT_NEEDED') {
17
+ let systemDetails;
18
+ let submissionPayload;
19
+ if (widget.status === 'CONSENT_NEEDED') {
20
+ const language = navigator.language;
21
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
22
+ systemDetails = [
23
+ { field_id: 'SYS_browser', value: react_device_detect_1.browserName },
24
+ { field_id: 'SYS_browser_os', value: react_device_detect_1.osName },
25
+ { field_id: 'SYS_browser_language', value: language },
26
+ {
27
+ field_id: 'SYS_screen_resolution',
28
+ value: `${window.screen.width} x ${window.screen.height}`,
29
+ },
30
+ { field_id: 'SYS_time_zone', value: timeZone },
31
+ { field_id: 'SYS_device_type', value: react_device_detect_1.deviceType },
32
+ { field_id: 'SYS_From_Page', value: window.location.origin },
33
+ ];
34
+ submissionPayload = {
35
+ form_id: widget?.form_data?.form_id ?? '',
36
+ conversation_id: (0, uuid_1.v4)(),
37
+ lead_data: {
38
+ name: widget?.form_data?.name,
39
+ fields: systemDetails,
40
+ ws: widget?.data?.workspace,
41
+ user_consent: widget?.data.user_consent,
42
+ },
43
+ type: 'browser',
44
+ };
45
+ }
46
+ const ConsentGiven = () => {
47
+ widgetConfigStore2_1.widgetFetchStore2.trigger.processConsent({
48
+ consentState: 'GIVEN',
49
+ submissionPayload,
50
+ });
51
+ };
52
+ const ConsentDenied = () => {
53
+ // widgetFetchStore2.trigger.processConsent({
54
+ // consentState: 'DENIED',
55
+ // submissionPayload,
56
+ // })
57
+ widgetStore_1.widgetStore.trigger.selectTab({ tab: widgetStore_1.TabType.HOME });
58
+ };
59
+ console.log('hereconsent', widget.consent);
60
+ return ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col items-start gap-1.5 w-full px-5 animate-slide-in-left", children: (0, jsx_runtime_1.jsx)("div", { className: "flex items-start w-full flex-col gap-2.5", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2 items-start w-full rounded-lg overflow-hidden", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsx)("div", { className: "flex items-start gap-[5px]", children: (0, jsx_runtime_1.jsx)("div", { className: "flex w-[24px] h-[24px] items-center justify-center rounded-full", children: (0, jsx_runtime_1.jsx)("img", { src: widget?.data?.logo_url, className: "w-6 h-6 text-white" }) }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-2 w-[90%]", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-2 w-full", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex gap-2 items-baseline pt-0.5", children: (0, jsx_runtime_1.jsx)("div", { className: "font-inter text-sm font-medium text-[#020618]", children: widget?.data?.name }) }), (0, jsx_runtime_1.jsx)("div", { className: "relative mt-[-1.00px] text-sm text-[#020618] w-full", children: (0, jsx_runtime_1.jsx)(pager_md_1.default, { mdText: widget?.consent
61
+ .consent_display_data // TODO: fix this any
62
+ }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap items-start gap-2 relative self-stretch pt-1", children: [(0, jsx_runtime_1.jsx)("button", { onClick: ConsentGiven, className: "flex cursor-pointer !h-7 w-max border border-slate-300 leading-5 px-3.5 py-1.5 font-medium text-slate-700 items-center text-sm justify-center bg-white rounded-lg hover:border-[#4b2fff]", children: "Yes, I agree" }), (0, jsx_runtime_1.jsx)("button", { onClick: ConsentDenied, className: "flex cursor-pointer !h-7 w-max border border-slate-300 leading-5 px-3.5 py-1.5 font-medium text-slate-700 items-center text-sm justify-center bg-white rounded-lg hover:border-[#4b2fff]", children: "No, I do not agree" })] })] })] }) }) }));
63
+ }
64
+ return null;
65
+ };
66
+ exports.Consent = Consent;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CountryDropdown = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const CountryDropdown = ({ countries, value, onChange, disabled, error, placeholder = 'Select a country', label = 'Country', }) => {
7
+ const [isOpen, setIsOpen] = (0, react_1.useState)(false);
8
+ const [search, setSearch] = (0, react_1.useState)('');
9
+ const dropdownRef = (0, react_1.useRef)(null);
10
+ const filteredCountries = countries.filter((c) => c.name.toLowerCase().includes(search.toLowerCase()));
11
+ (0, react_1.useEffect)(() => {
12
+ const handleClickOutside = (event) => {
13
+ if (dropdownRef.current &&
14
+ !dropdownRef.current.contains(event.target)) {
15
+ setIsOpen(false);
16
+ }
17
+ };
18
+ document.addEventListener('mousedown', handleClickOutside);
19
+ return () => document.removeEventListener('mousedown', handleClickOutside);
20
+ }, []);
21
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "w-full", ref: dropdownRef, children: [(0, jsx_runtime_1.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: label }), (0, jsx_runtime_1.jsxs)("div", { onClick: () => {
22
+ if (!disabled)
23
+ setIsOpen((prev) => !prev);
24
+ }, className: `w-full flex justify-between items-center px-4 py-2 h-9 text-sm rounded-lg border ${disabled ? 'text-slate-400 border-zinc-200 bg-zinc-50' : 'bg-white'} ${error
25
+ ? 'border-red-500 focus:ring-red-500'
26
+ : 'border-gray-300 focus:ring-blue-500'} focus:outline-none focus:ring-2 focus:border-transparent`, children: [(0, jsx_runtime_1.jsx)("span", { className: "truncate", children: value || placeholder }), (0, jsx_runtime_1.jsx)("svg", { className: "w-4 h-4 ml-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), isOpen && ((0, jsx_runtime_1.jsxs)("div", { className: "z-50 mt-1 w-[100%] bg-white border border-gray-300 rounded-md shadow-lg", onMouseDown: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsx)("div", { className: "p-2 border-b border-gray-200 bg-white sticky top-0 z-10 rounded-tl-md rounded-tr-md", children: (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Search", value: search, onChange: (e) => setSearch(e.target.value), onMouseDown: (e) => e.stopPropagation(), className: "w-full px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "max-h-48 overflow-y-auto", children: [filteredCountries.map((c) => ((0, jsx_runtime_1.jsx)("div", { onClick: () => {
27
+ onChange(c.name);
28
+ setIsOpen(false);
29
+ }, className: "px-4 py-2 hover:bg-gray-100 cursor-pointer text-sm", children: c.name }, c.code))), filteredCountries.length === 0 && ((0, jsx_runtime_1.jsx)("li", { className: "px-4 py-2 text-sm text-gray-500", children: "No results found" }))] })] })), error && (0, jsx_runtime_1.jsx)("p", { className: "text-red-500 text-xs mt-1", children: error })] }));
30
+ };
31
+ exports.CountryDropdown = CountryDropdown;
package/out/Form.js ADDED
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Form = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const widgetConfigStore2_1 = require("./widgetConfigStore2");
7
+ const uuid_1 = require("uuid");
8
+ const InputField_1 = require("./InputField");
9
+ const pikaicons_react_1 = require("./assets/icons/pikaicons-react");
10
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11
+ const Form = ({ conversationId }) => {
12
+ const widget = (0, widgetConfigStore2_1.useWidgetData)();
13
+ const widgetData = (0, widgetConfigStore2_1.widgetHasData)(widget) ? widget.data : null;
14
+ const [formValues, setFormValues] = (0, react_1.useState)({});
15
+ const [formErrors, setFormErrors] = (0, react_1.useState)({});
16
+ const [isSubmittedFormOpen, setIsSubmittedFormOpen] = (0, react_1.useState)(false);
17
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
18
+ const isUuid = typeof widgetData?.source_id === 'string' &&
19
+ uuidRegex.test(widgetData.source_id);
20
+ console.log('widget status from form', widget);
21
+ (0, react_1.useEffect)(() => {
22
+ if (widget.status === 'FORM_INPUT_NEEDED' && isUuid) {
23
+ console.log('Trigger here');
24
+ widgetConfigStore2_1.widgetFetchStore2.trigger.processMessage();
25
+ }
26
+ if (widget.status === 'FORM_INPUT_NEEDED' && widget.form_data) {
27
+ const localKey = `CONVERSATION::${widget.data.id}`;
28
+ try {
29
+ const existingRaw = localStorage.getItem(localKey);
30
+ const existingData = existingRaw
31
+ ? JSON.parse(existingRaw)
32
+ : {
33
+ widget_id: widget.data.id,
34
+ conversation_id: null,
35
+ user_state: 'FORM_INPUT_NEEDED',
36
+ events: [],
37
+ };
38
+ // ✅ Check if already added to prevent duplicates
39
+ const alreadyExists = existingData.events.some((e) => e.type === 'FORM_INPUT_NEEDED' &&
40
+ e.form_data?.form_id === widget.form_data.form_id);
41
+ if (!alreadyExists) {
42
+ const newEvent = {
43
+ type: 'FORM_INPUT_NEEDED',
44
+ form_data: widget.form_data,
45
+ };
46
+ existingData.events.push(newEvent);
47
+ localStorage.setItem(localKey, JSON.stringify(existingData));
48
+ console.log('✅ FORM_INPUT_NEEDED appended successfully');
49
+ }
50
+ else {
51
+ console.log('ℹ️ FORM_INPUT_NEEDED already present, skipping append.');
52
+ }
53
+ }
54
+ catch (error) {
55
+ console.error('❌ Failed to append FORM_INPUT_NEEDED event:', error);
56
+ }
57
+ }
58
+ }, [widget.status, widget?.form_data, widget.data.id]);
59
+ (0, react_1.useEffect)(() => {
60
+ switch (widget.status) {
61
+ case 'WIDGET_LOADING':
62
+ widgetConfigStore2_1.widgetFetchStore2.trigger.setFetchConfig(widget.config);
63
+ break;
64
+ case 'CONSENT_GIVEN':
65
+ widgetConfigStore2_1.widgetFetchStore2.trigger.shouldShowForm({
66
+ browser_data: widget.browser_data ?? null,
67
+ });
68
+ break;
69
+ case 'WIDGET_LOADED':
70
+ widgetConfigStore2_1.widgetFetchStore2.trigger.shouldShowForm({ browser_data: null });
71
+ break;
72
+ case 'FORM_SUBMITTED':
73
+ widgetConfigStore2_1.widgetFetchStore2.trigger.processMessage();
74
+ break;
75
+ }
76
+ }, [widget.status]);
77
+ if (widget.status !== 'ALLOW_MESSAGE' &&
78
+ widget.status !== 'FORM_INPUT_NEEDED' &&
79
+ widget.status !== 'WIDGET_LOADED' &&
80
+ widget.status !== 'CONSENT_NEEDED' &&
81
+ widget.status !== 'CONSENT_GIVEN' &&
82
+ widget.status !== 'FORM_SUBMITTED') {
83
+ return null;
84
+ }
85
+ // const getFormTemplateFromLocalStorage = () => {
86
+ // const raw = localStorage.getItem(`CONVERSATION_LIST::${widget.data.id}`);
87
+ // if (!raw) {
88
+ // console.warn('No data found in localStorage');
89
+ // return null;
90
+ // }
91
+ // try {
92
+ // const parsed: any = JSON.parse(raw);
93
+ // console.log("parsed event", parsed);
94
+ // const eventsArray = Array.isArray(parsed)
95
+ // ? parsed.reduce<any[]>((acc, item) => {
96
+ // if (item.events && Array.isArray(item.events)) acc.push(...item.events);
97
+ // return acc;
98
+ // }, [])
99
+ // : parsed.events || [];
100
+ // const formInputNeededEvent = eventsArray.find(
101
+ // (e: any) => e.type === "FORM_INPUT_NEEDED"
102
+ // );
103
+ // console.log("form input needed event", formInputNeededEvent);
104
+ // return formInputNeededEvent?.form_data || null;
105
+ // } catch (error) {
106
+ // console.error("Failed to parse localStorage data:", error);
107
+ // return null;
108
+ // }
109
+ // };
110
+ const getFormTemplateFromLocalStorage = () => {
111
+ const raw = localStorage.getItem(`CONVERSATION::${widget.data.id}`);
112
+ if (!raw) {
113
+ console.warn('No data found in localStorage under key "DUMMY"');
114
+ return null;
115
+ }
116
+ try {
117
+ const parsed = JSON.parse(raw);
118
+ console.log('parsed event', parsed);
119
+ const formInputNeededEvent = parsed.events.find((e) => e.type === 'FORM_INPUT_NEEDED');
120
+ console.log('form input needed event', formInputNeededEvent);
121
+ return formInputNeededEvent?.form_data || null;
122
+ }
123
+ catch (error) {
124
+ console.error('Failed to parse localStorage DUMMY data:', error);
125
+ return null;
126
+ }
127
+ };
128
+ const formData = getFormTemplateFromLocalStorage();
129
+ const formTemplate = formData?.form_template ?? []; // ✅ Safely fallback to empty array
130
+ console.log('form template', formTemplate);
131
+ const submittedValueMap = (() => {
132
+ try {
133
+ const raw = localStorage.getItem(`CONVERSATION::${widget.data.id}`);
134
+ if (!raw)
135
+ return {};
136
+ const parsed = JSON.parse(raw);
137
+ const formSubmittedEvent = parsed.events.find((e) => e.type === 'FORM_SUBMITTED');
138
+ const submittedArray = formSubmittedEvent?.submissionPayload?.lead_data?.fields ?? [];
139
+ return submittedArray.reduce((acc, { field_id, value }) => {
140
+ acc[field_id] = value;
141
+ return acc;
142
+ }, {});
143
+ }
144
+ catch (error) {
145
+ console.error('Error parsing submitted data:', error);
146
+ return {};
147
+ }
148
+ })();
149
+ const isFormSubmitted = (() => {
150
+ try {
151
+ const raw = localStorage.getItem(`CONVERSATION::${widget.data.id}`);
152
+ if (!raw)
153
+ return false;
154
+ const parsed = JSON.parse(raw);
155
+ return parsed.events.some((e) => e.type === 'FORM_SUBMITTED');
156
+ }
157
+ catch (error) {
158
+ console.error('Error checking form submission:', error);
159
+ return false;
160
+ }
161
+ })();
162
+ const handleChange = (e) => {
163
+ const { name, value } = e.target;
164
+ setFormValues((prev) => ({ ...prev, [name]: value }));
165
+ setFormErrors((prev) => ({ ...prev, [name]: '' }));
166
+ };
167
+ const validateForm = () => {
168
+ const errors = {};
169
+ formTemplate.forEach((field) => {
170
+ const value = formValues[field.field_id]?.trim() || '';
171
+ if (field.is_mandatory && !value) {
172
+ errors[field.field_id] =
173
+ `${field.dispaly_name || field.name} is required`;
174
+ }
175
+ if (field.field_type === 'email' &&
176
+ value &&
177
+ !emailRegex.test(value)) {
178
+ errors[field.field_id] = 'Please enter a valid email address';
179
+ }
180
+ });
181
+ setFormErrors(errors);
182
+ return Object.keys(errors).length === 0;
183
+ };
184
+ const handleFormSubmission = (e) => {
185
+ e.preventDefault();
186
+ if (!validateForm())
187
+ return;
188
+ const fieldsArray = Object.entries(formValues).map(([field_id, value]) => ({ field_id, value }));
189
+ const submissionPayload = {
190
+ form_id: formData?.form_id ?? '',
191
+ conversation_id: conversationId ?? (0, uuid_1.v4)(),
192
+ lead_data: {
193
+ name: formData?.name ?? '',
194
+ fields: fieldsArray,
195
+ ws: formData?.ws ?? '',
196
+ user_consent: widget.data.user_consent,
197
+ },
198
+ type: 'lead',
199
+ };
200
+ widgetConfigStore2_1.widgetFetchStore2.trigger.processFormSubmission({ submissionPayload });
201
+ const localKey = `form::${widget?.data?.id}::${conversationId}`;
202
+ let existingData = {};
203
+ try {
204
+ const stored = localStorage.getItem(localKey);
205
+ existingData = stored ? JSON.parse(stored) : {};
206
+ }
207
+ catch (err) {
208
+ console.error(`Failed to parse localStorage for ${localKey}`, err);
209
+ }
210
+ existingData[formData?.form_id] = fieldsArray;
211
+ try {
212
+ localStorage.setItem(localKey, JSON.stringify(existingData));
213
+ localStorage.setItem('current_conversation', conversationId);
214
+ }
215
+ catch (err) {
216
+ console.error(`Failed to save form data to ${localKey}`, err);
217
+ }
218
+ };
219
+ const shouldShowForm = (widget.status === 'FORM_INPUT_NEEDED' && !isUuid) ||
220
+ widget.status === 'WIDGET_LOADED' ||
221
+ (widget.status === 'ALLOW_MESSAGE' &&
222
+ conversationId === localStorage.getItem('current_conversation'));
223
+ if (!shouldShowForm)
224
+ return null;
225
+ console.log('should show form ', shouldShowForm, formTemplate, conversationId);
226
+ return ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col items-start gap-1.5 w-full px-5 animate-slide-in-left", children: (0, jsx_runtime_1.jsx)("div", { className: "flex items-start w-full", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-1.5 items-start w-full rounded-lg overflow-hidden", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsx)("div", { className: "flex items-start gap-[5px]", children: (0, jsx_runtime_1.jsx)("div", { className: "flex w-[24px] h-[24px] items-center justify-center rounded-full", children: (0, jsx_runtime_1.jsx)("img", { src: widget?.data?.logo_url, className: "w-6 h-6 text-white" }) }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-2 w-[90%]", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex gap-2 items-baseline pt-0.5", children: (0, jsx_runtime_1.jsx)("div", { className: "font-inter text-sm font-medium text-[#020618]", children: widget?.data?.name }) }), (0, jsx_runtime_1.jsx)("div", { className: "relative mt-[-1.00px] text-sm text-[#020618] w-full", children: isFormSubmitted ? ((0, jsx_runtime_1.jsxs)("div", { className: "py-2.5 px-3.5 flex w-full flex-col items-start gap-4 rounded-lg border border-zinc-200", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 rounded-sm w-full justify-between", children: [(0, jsx_runtime_1.jsxs)("span", { className: "flex gap-1 items-center text-slate-950 text-sm font-regular leading-5", children: ["Form submitted", ' ', (0, jsx_runtime_1.jsx)(pikaicons_react_1.PiCheckTickCircleSolid, { className: "h-[18px] w-[18px] text-green-500" })] }), (0, jsx_runtime_1.jsx)("span", { onClick: () => setIsSubmittedFormOpen(!isSubmittedFormOpen), className: "cursor-pointer text-slate-500 hover:text-slate-700 transition-colors hover:bg-slate-100 rounded-full", children: !isSubmittedFormOpen ? ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiChevronDownStroke, {})) : ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiChevronUpStroke, {})) })] }), isSubmittedFormOpen && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col items-start gap-4", children: formTemplate.map((input, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-slate-700 text-sm font-medium leading-5", children: input.dispaly_name ||
227
+ input.name }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-950 text-sm font-regular leading-5", children: formValues[input.field_id] ??
228
+ submittedValueMap[input
229
+ .field_id] ??
230
+ '' })] }, index))) }))] })) : ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col bg-white w-full gap-2.5 px-3.5 py-2.5 rounded-lg border border-zinc-200", children: (0, jsx_runtime_1.jsxs)("form", { onSubmit: handleFormSubmission, className: "space-y-4 w-full", children: [formTemplate.map((input) => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(InputField_1.InputField, { input: input, handleChange: handleChange, value: formValues[input.field_id] ??
231
+ submittedValueMap[input.field_id] ??
232
+ '', error: formErrors[input.field_id], disabled: isFormSubmitted }, input.field_id) }))), (0, jsx_runtime_1.jsx)("button", { type: "submit", className: `${!isFormSubmitted
233
+ ? 'hover:bg-[#4b2fff]/90'
234
+ : 'opacity-50'} w-full text-sm bg-[#4b2fff] text-white cursor-pointer font-medium py-2 px-4 rounded-lg transition-colors`, disabled: isFormSubmitted, children: isFormSubmitted
235
+ ? 'Submitted'
236
+ : 'Submit' })] }) })) })] })] }) }) }));
237
+ };
238
+ exports.Form = Form;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HomePage = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const HomePageContent_1 = require("./HomePageContent");
6
+ const HomePageFooter_1 = require("./HomePageFooter");
7
+ const HomePageHeader_1 = require("./HomePageHeader");
8
+ const HomePage = ({ toggleWidget, switchTab, isExpanded, }) => {
9
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(HomePageHeader_1.HomePageHeader, { toggleWidget: toggleWidget }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-1 flex-col justify-between", children: [(0, jsx_runtime_1.jsx)(HomePageContent_1.HomePageContent, {}), (0, jsx_runtime_1.jsx)(HomePageFooter_1.HomePageFooter, { switchTab: switchTab, isExpanded: isExpanded })] })] }));
10
+ };
11
+ exports.HomePage = HomePage;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HomePageContent = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const widgetConfigStore2_1 = require("./widgetConfigStore2");
7
+ const RecentMessageTab_1 = require("./RecentMessageTab");
8
+ const BotMain_1 = require("./BotMain");
9
+ const widgetStore_1 = require("./widgetStore");
10
+ // import { NewRecentMessageTab } from './NewRecentMessageTab'
11
+ // import { setWidgetLocalState } from './widgetStateHandler'
12
+ const HomePageContent = () => {
13
+ const widget = (0, widgetConfigStore2_1.useWidgetData)();
14
+ const [isHovered, setIsHovered] = (0, react_1.useState)(false);
15
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)("div", { className: "p-5 ", children: [(0, jsx_runtime_1.jsx)(RecentMessageTab_1.RecentMessageTab, {}), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col gap-2 mt-2", children: (0, jsx_runtime_1.jsxs)("button", { className: `flex w-full items-center justify-between rounded-xl pl-5 pr-4 py-[13px] text-sm font-medium text-slate-950 cursor-pointer`, onClick: () => {
16
+ localStorage.setItem('Tab', 'Chat');
17
+ widgetStore_1.widgetStore.trigger.selectTab({ tab: BotMain_1.TabType.CHAT });
18
+ widgetStore_1.widgetStore.send({
19
+ type: 'handleExitChatState',
20
+ value: false,
21
+ });
22
+ }, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), style: {
23
+ border: `1px solid ${isHovered
24
+ ? widget?.data?.brand_color
25
+ : '#e4e4e7'}`,
26
+ }, children: [(0, jsx_runtime_1.jsx)("span", { className: "self-stretch mt-[-1.00px] text-sm text-[#020618]", children: widget?.data?.send_message_description }), (0, jsx_runtime_1.jsx)("svg", { style: {
27
+ color: isHovered
28
+ ? widget?.data?.brand_color
29
+ : '#b8b8b8',
30
+ }, width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: (0, jsx_runtime_1.jsx)("path", { d: "M9 18l6-6-6-6" }) })] }) })] }) }));
31
+ };
32
+ exports.HomePageContent = HomePageContent;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HomePageFooter = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = __importDefault(require("react"));
9
+ const pikaicons_react_1 = require("./assets/icons/pikaicons-react");
10
+ const BotMain_1 = require("./BotMain");
11
+ const widgetStore_1 = require("./widgetStore");
12
+ const widgetConfigStore2_1 = require("./widgetConfigStore2");
13
+ const CustomTooltip_1 = require("./components/CustomTooltip");
14
+ const HomePageFooter = ({ switchTab, isExpanded, }) => {
15
+ const widget = (0, widgetConfigStore2_1.useWidgetData)();
16
+ const [isHomeHovered, setIsHomeHovered] = react_1.default.useState(false);
17
+ const [isRecentHovered, setIsRecentHovered] = react_1.default.useState(false);
18
+ // if (
19
+ // !(
20
+ // status !== 'NOT_STARTED' &&
21
+ // status !== 'WIDGET_LOADING' &&
22
+ // status !== 'INVALID_STATE' &&
23
+ // status !== 'ALLOW_MESSAGE'
24
+ // )
25
+ // ) {
26
+ // return null
27
+ // }
28
+ function hexToRGB(hex) {
29
+ hex = hex.replace(/^#/, '');
30
+ if (hex.length === 3) {
31
+ hex = hex
32
+ .split('')
33
+ .map((c) => c + c)
34
+ .join('');
35
+ }
36
+ const bigint = parseInt(hex, 16);
37
+ const r = (bigint >> 16) & 255;
38
+ const g = (bigint >> 8) & 255;
39
+ const b = bigint & 255;
40
+ return `rgb(${r}, ${g}, ${b}, 0.1)`;
41
+ }
42
+ const handleHomeButtonClick = () => {
43
+ if (isExpanded !== widgetStore_1.WidgetExpandType.DEFAULT) {
44
+ widgetStore_1.widgetStore.trigger.expandWidget({
45
+ expanded_size: widgetStore_1.WidgetExpandType.DEFAULT,
46
+ });
47
+ setTimeout(() => {
48
+ widgetStore_1.widgetStore.trigger.selectTab({ tab: BotMain_1.TabType.HOME });
49
+ }, 300);
50
+ }
51
+ else {
52
+ widgetStore_1.widgetStore.trigger.selectTab({ tab: BotMain_1.TabType.HOME });
53
+ }
54
+ };
55
+ const widgetData = (0, widgetConfigStore2_1.widgetHasData)(widget) ? widget.data : null;
56
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-10 border-t border-zinc-200 bg-white px-8 py-3 z-50", children: [(0, jsx_runtime_1.jsx)(CustomTooltip_1.CustomTooltip, { content: "Home", children: (0, jsx_runtime_1.jsx)("button", { className: "rounded-lg cursor-pointer p-1.5", onMouseEnter: () => setIsHomeHovered(true), onMouseLeave: () => setIsHomeHovered(false), onClick: () => handleHomeButtonClick(), style: {
57
+ background: switchTab == 'home'
58
+ ? widgetData?.brand_color
59
+ ? hexToRGB(widgetData?.brand_color)
60
+ : '#EBEFFF'
61
+ : '',
62
+ color: switchTab == 'home' || isHomeHovered
63
+ ? widgetData?.brand_color
64
+ ? widgetData?.brand_color
65
+ : '#45556c'
66
+ : '#62748e',
67
+ }, children: switchTab == 'home' ? ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiHomeAltSolid, { style: {
68
+ color: widgetData?.brand_color ?? '#564CFF',
69
+ } })) : ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiHomeAltStroke, {})) }) }), (0, jsx_runtime_1.jsx)(CustomTooltip_1.CustomTooltip, { content: "Recent chats", children: (0, jsx_runtime_1.jsx)("button", { className: "rounded-lg cursor-pointer p-1.5", onMouseEnter: () => setIsRecentHovered(true), onMouseLeave: () => setIsRecentHovered(false), onClick: () => widgetStore_1.widgetStore.trigger.selectTab({
70
+ tab: BotMain_1.TabType.RECENT_MESSAGE_LIST,
71
+ }), style: {
72
+ background: switchTab == 'recentMessageList'
73
+ ? widgetData?.brand_color
74
+ ? hexToRGB(widgetData?.brand_color)
75
+ : '#EBEFFF'
76
+ : '',
77
+ color: switchTab == 'recentMessageList' ||
78
+ isRecentHovered
79
+ ? widgetData?.brand_color
80
+ ? widgetData?.brand_color
81
+ : '#45556c'
82
+ : '#62748e',
83
+ }, children: switchTab == 'recentMessageList' ? ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiChatDefaultSolid, { style: {
84
+ color: widgetData?.brand_color ?? '#564CFF',
85
+ } })) : ((0, jsx_runtime_1.jsx)(pikaicons_react_1.PiChatDefaultStroke, {})) }) })] }) }));
86
+ };
87
+ exports.HomePageFooter = HomePageFooter;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HomePageHeader = exports.isDarkColor = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const widgetConfigStore2_1 = require("./widgetConfigStore2");
6
+ /**
7
+ * Determines if a color is "dark" or "light" based on its perceived brightness.
8
+ * @param color The color string in hex (e.g., #RRGGBB, #RGB) or RGB (e.g., rgb(r, g, b)) format.
9
+ * @returns 'dark' or 'light'. Returns 'light' for null or unsupported formats.
10
+ */
11
+ // TODO : Needs to be Verified
12
+ const isDarkColor = (color) => {
13
+ let r;
14
+ let g;
15
+ let b;
16
+ if (color?.startsWith('#')) {
17
+ let hex = color.slice(1);
18
+ if (hex.length === 3) {
19
+ hex = hex
20
+ .split('')
21
+ .map((c) => c + c)
22
+ .join('');
23
+ }
24
+ if (hex.length === 6) {
25
+ const bigint = parseInt(hex, 16);
26
+ r = (bigint >> 16) & 255;
27
+ g = (bigint >> 8) & 255;
28
+ b = bigint & 255;
29
+ }
30
+ }
31
+ else if (color?.startsWith('rgb')) {
32
+ const rgbValues = color.match(/\d+/g);
33
+ if (rgbValues && rgbValues.length >= 3) {
34
+ ;
35
+ [r, g, b] = rgbValues.map(Number);
36
+ }
37
+ }
38
+ if (r === undefined || g === undefined || b === undefined) {
39
+ return 'light';
40
+ }
41
+ // --- Improved brightness formula (HSP model) ---
42
+ const brightness = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b));
43
+ // --- Increased threshold for detecting “light” colors ---
44
+ return brightness < 170 ? 'dark' : 'light';
45
+ };
46
+ exports.isDarkColor = isDarkColor;
47
+ const HomePageHeader = ({ toggleWidget, }) => {
48
+ const widget = (0, widgetConfigStore2_1.useWidgetData)();
49
+ const { status } = widget;
50
+ if (!(status !== 'NOT_STARTED' &&
51
+ status !== 'WIDGET_LOADING' &&
52
+ status !== 'INVALID_STATE')) {
53
+ return null;
54
+ }
55
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `relative h-[40%] w-full rounded-[22px] ${widget?.data?.welcome_text_color && (0, exports.isDarkColor)(widget?.data?.welcome_text_color) == 'light' ? 'bg-widget-home-light-top' : 'bg-widget-home-dark-top'}`, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute top-0 left-0 w-full h-full rounded-[22px]", style: { backgroundColor: widget.data?.home_background_color }, children: (0, jsx_runtime_1.jsx)("div", { className: "absolute top-0 left-0 w-full h-full z-[0] rounded-[22px] opacity-90", style: {
56
+ backgroundImage: `url(${widget.data?.home_cover_image})`,
57
+ backgroundSize: 'cover',
58
+ backgroundPosition: 'center',
59
+ backgroundRepeat: 'no-repeat',
60
+ }, children: (0, jsx_runtime_1.jsx)("button", { className: "absolute top-6 right-6 hover:bg-white/10 rounded-lg p-1.5 cursor-pointer flex items-start h-max", style: { mixBlendMode: 'difference' }, onClick: toggleWidget, children: (0, jsx_runtime_1.jsx)("svg", { style: {
61
+ mixBlendMode: 'difference',
62
+ }, width: "20", height: "20", viewBox: "0 0 24 24", stroke: "white", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: (0, jsx_runtime_1.jsx)("path", { d: "M18 6L6 18M6 6l12 12" }) }) }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex justify-start p-6 z-10 absolute w-2/3", children: (0, jsx_runtime_1.jsx)("img", { className: "h-[32] w-auto cursor-pointer", src: widget?.data?.home_header_logo }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col absolute bottom-[1.2rem] left-[1.5rem]", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-2xl font-semibold leading-8 ", style: { color: widget?.data?.welcome_text_color }, children: widget?.data?.home_header_title }), (0, jsx_runtime_1.jsx)("span", { className: "text-base font-medium leading-6", style: {
63
+ color: widget?.data?.welcome_text_color,
64
+ }, children: widget?.data?.home_header_description })] })] }));
65
+ };
66
+ exports.HomePageHeader = HomePageHeader;