@getwidgets/live-chat-widget 1.0.1 → 1.0.2

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.
@@ -19580,6 +19580,7 @@
19580
19580
  const [inputMessage, setInputMessage] = reactExports.useState("");
19581
19581
  const [isLoading, setIsLoading] = reactExports.useState(false);
19582
19582
  const [isOpen, setIsOpen] = reactExports.useState(false);
19583
+ const [showNotificationPreview, setShowNotificationPreview] = reactExports.useState(true);
19583
19584
  const chatContainerRef = reactExports.useRef(null);
19584
19585
  const inputRef = reactExports.useRef(null);
19585
19586
  const [sessionId, setSessionId] = reactExports.useState(null);
@@ -19591,6 +19592,7 @@
19591
19592
  const wsRef = reactExports.useRef(null);
19592
19593
  const audioRef = reactExports.useRef(null);
19593
19594
  const [hasCheckedSession, setHasCheckedSession] = reactExports.useState(false);
19595
+ const [windowWidth, setWindowWidth] = reactExports.useState(typeof window !== "undefined" ? window.innerWidth : 1024);
19594
19596
  const normalizeIncomingMessage = (m2) => {
19595
19597
  if (!m2) return { id: void 0, role: "agent", content: "", timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }), created_at: Date.now() };
19596
19598
  if (m2.sent_by) {
@@ -19616,6 +19618,13 @@
19616
19618
  created_at: ts
19617
19619
  };
19618
19620
  };
19621
+ reactExports.useEffect(() => {
19622
+ const handleResize = () => {
19623
+ setWindowWidth(window.innerWidth);
19624
+ };
19625
+ window.addEventListener("resize", handleResize);
19626
+ return () => window.removeEventListener("resize", handleResize);
19627
+ }, []);
19619
19628
  reactExports.useEffect(() => {
19620
19629
  if (chatContainerRef.current) {
19621
19630
  chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;
@@ -19625,6 +19634,25 @@
19625
19634
  const id2 = getSessionId();
19626
19635
  setSessionId(id2);
19627
19636
  }, [widgetId]);
19637
+ reactExports.useEffect(() => {
19638
+ const dismissalKey = `live-chat-notification-dismissed/${widgetId}`;
19639
+ const dismissalTime = localStorage.getItem(dismissalKey);
19640
+ if (dismissalTime) {
19641
+ const dismissedAt = parseInt(dismissalTime);
19642
+ const now = Date.now();
19643
+ const timeSinceDismissal = now - dismissedAt;
19644
+ const oneDayInMs = 24 * 60 * 60 * 1e3;
19645
+ if (timeSinceDismissal < oneDayInMs) {
19646
+ setShowNotificationPreview(false);
19647
+ return;
19648
+ } else {
19649
+ localStorage.removeItem(dismissalKey);
19650
+ setShowNotificationPreview(true);
19651
+ }
19652
+ } else {
19653
+ setShowNotificationPreview(true);
19654
+ }
19655
+ }, [widgetId]);
19628
19656
  reactExports.useEffect(() => {
19629
19657
  if (!widgetId) return;
19630
19658
  fetchWidgetConfig(widgetId).then((data) => setConfig(data)).catch((err) => console.error("Failed to load widget config:", err));
@@ -19860,7 +19888,15 @@
19860
19888
  performSend();
19861
19889
  }
19862
19890
  };
19863
- const toggleWidget = () => setIsOpen((v2) => !v2);
19891
+ const toggleWidget = () => {
19892
+ setIsOpen((v2) => !v2);
19893
+ };
19894
+ const handleCloseNotification = (e) => {
19895
+ e.stopPropagation();
19896
+ const dismissalKey = `live-chat-notification-dismissed/${widgetId}`;
19897
+ localStorage.setItem(dismissalKey, Date.now().toString());
19898
+ setShowNotificationPreview(false);
19899
+ };
19864
19900
  if (!config) return null;
19865
19901
  const { header, chat_area, input_area, appearance } = ((_a = config.config) == null ? void 0 : _a.chat_widget) || {};
19866
19902
  const headerConfig = header || {};
@@ -19868,13 +19904,17 @@
19868
19904
  const chatAreaConfig = chat_area || {};
19869
19905
  const inputAreaConfig = input_area || {};
19870
19906
  const getResponsiveDimensions = () => {
19871
- const isMobile = typeof window !== "undefined" && window.innerWidth < 768;
19872
- if (isMobile) {
19907
+ const isMobile2 = windowWidth < 768;
19908
+ if (isMobile2) {
19873
19909
  return {
19874
19910
  width: "95vw",
19875
- height: "60vh",
19911
+ height: "85vh",
19912
+ // Changed from 60vh to 85vh for better mobile experience
19876
19913
  maxWidth: "95vw",
19877
- maxHeight: "80vh"
19914
+ maxHeight: "95vh",
19915
+ bottom: "0",
19916
+ right: "0",
19917
+ borderRadius: "12px 12px 0 0"
19878
19918
  };
19879
19919
  }
19880
19920
  return {
@@ -19886,7 +19926,11 @@
19886
19926
  };
19887
19927
  const getPositionStyles = () => {
19888
19928
  const position2 = appearanceConfig.position || "bottom-right";
19929
+ const isMobile2 = windowWidth < 768;
19889
19930
  const baseStyles = { position: "fixed", zIndex: 9999 };
19931
+ if (isMobile2) {
19932
+ return { ...baseStyles, left: 0, right: 0, bottom: 0 };
19933
+ }
19890
19934
  const desktopSpacing = "20px";
19891
19935
  switch (position2) {
19892
19936
  case "bottom-left":
@@ -19902,6 +19946,7 @@
19902
19946
  const responsiveDimensions = getResponsiveDimensions();
19903
19947
  const combinedMessages = [...messages || [], ...localMessages];
19904
19948
  const getContrastColor = (hex) => {
19949
+ if (!hex) return "#000";
19905
19950
  const c = hex.replace("#", "");
19906
19951
  const r2 = parseInt(c.substr(0, 2), 16);
19907
19952
  const g = parseInt(c.substr(2, 2), 16);
@@ -19909,7 +19954,70 @@
19909
19954
  const luminance = (0.299 * r2 + 0.587 * g + 0.114 * b) / 255;
19910
19955
  return luminance > 0.5 ? "#000000" : "#FFFFFF";
19911
19956
  };
19912
- return /* @__PURE__ */ React.createElement("div", { style: getPositionStyles() }, !isOpen && /* @__PURE__ */ React.createElement(
19957
+ const isMobile = windowWidth < 768;
19958
+ return /* @__PURE__ */ React.createElement("div", { style: getPositionStyles() }, !isOpen && showNotificationPreview && /* @__PURE__ */ React.createElement(
19959
+ "button",
19960
+ {
19961
+ onClick: toggleWidget,
19962
+ className: "rounded-2xl shadow-lg hover:shadow-xl transition-all duration-300 flex flex-col gap-2 p-4 max-w-xs responsive-notification",
19963
+ style: {
19964
+ backgroundColor: headerConfig.background_color || "#111827",
19965
+ color: "#FFFFFF",
19966
+ border: "none",
19967
+ cursor: "pointer",
19968
+ textAlign: "left",
19969
+ minWidth: isMobile ? "90vw" : "280px",
19970
+ maxWidth: isMobile ? "90vw" : "400px",
19971
+ margin: isMobile ? "0 auto" : "0"
19972
+ }
19973
+ },
19974
+ /* @__PURE__ */ React.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 flex-1" }, headerConfig.logo_url ? /* @__PURE__ */ React.createElement(
19975
+ "img",
19976
+ {
19977
+ src: headerConfig.logo_url,
19978
+ alt: "Chat",
19979
+ className: "responsive-notification-logo",
19980
+ style: {
19981
+ width: "32px",
19982
+ height: "32px",
19983
+ borderRadius: "50%",
19984
+ flexShrink: 0
19985
+ }
19986
+ }
19987
+ ) : /* @__PURE__ */ React.createElement(
19988
+ "div",
19989
+ {
19990
+ className: "rounded-full flex items-center justify-center responsive-notification-icon",
19991
+ style: {
19992
+ width: "32px",
19993
+ height: "32px",
19994
+ backgroundColor: headerConfig.background_color || "#111827",
19995
+ flexShrink: 0
19996
+ }
19997
+ },
19998
+ /* @__PURE__ */ React.createElement(
19999
+ "svg",
20000
+ {
20001
+ viewBox: "0 0 24 24",
20002
+ fill: "currentColor",
20003
+ style: {
20004
+ width: "16px",
20005
+ height: "16px"
20006
+ }
20007
+ },
20008
+ /* @__PURE__ */ React.createElement("path", { d: "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 9h12v2H6V9zm8 5H6v-2h8v2zm4-6H6V6h12v2z" })
20009
+ )
20010
+ ), /* @__PURE__ */ React.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React.createElement("h3", { className: "font-semibold text-sm" }, headerConfig.title || "Live Chat"), /* @__PURE__ */ React.createElement("p", { className: "text-xs opacity-70" }, "Just now"))), /* @__PURE__ */ React.createElement(
20011
+ "button",
20012
+ {
20013
+ onClick: handleCloseNotification,
20014
+ className: "text-gray-400 hover:text-white transition-colors flex-shrink-0 responsive-notification-close",
20015
+ style: { fontSize: "20px", padding: "0", border: "none", background: "none", cursor: "pointer" }
20016
+ },
20017
+ "×"
20018
+ )),
20019
+ /* @__PURE__ */ React.createElement("p", { className: "text-sm leading-relaxed text-gray-200", style: { fontSize: isMobile ? "13px" : "14px" } }, (inputAreaConfig == null ? void 0 : inputAreaConfig.first_ai_message) || headerConfig.subtitle || "Connect with visitors")
20020
+ ), !isOpen && !showNotificationPreview && /* @__PURE__ */ React.createElement(
19913
20021
  "button",
19914
20022
  {
19915
20023
  onClick: toggleWidget,
@@ -19917,48 +20025,314 @@
19917
20025
  style: {
19918
20026
  backgroundColor: headerConfig.background_color || "#111827",
19919
20027
  color: headerConfig.font_color || "#FFFFFF",
19920
- width: "56px",
19921
- height: "56px",
20028
+ width: isMobile ? "52px" : "56px",
20029
+ height: isMobile ? "52px" : "56px",
19922
20030
  border: "none",
19923
- cursor: "pointer"
20031
+ cursor: "pointer",
20032
+ margin: isMobile ? "16px" : "0"
19924
20033
  }
19925
20034
  },
19926
- headerConfig.logo_url ? /* @__PURE__ */ React.createElement("img", { src: headerConfig.logo_url, alt: "logo", style: { width: 28, height: 28 } }) : /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 24 24", fill: "currentColor", style: { width: 20, height: 20 } }, /* @__PURE__ */ React.createElement("path", { d: "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 9h12v2H6V9zm8 5H6v-2h8v2zm4-6H6V6h12v2z" }))
20035
+ headerConfig.logo_url ? /* @__PURE__ */ React.createElement(
20036
+ "img",
20037
+ {
20038
+ src: headerConfig.logo_url,
20039
+ alt: "logo",
20040
+ style: {
20041
+ width: isMobile ? 24 : 28,
20042
+ height: isMobile ? 24 : 28
20043
+ }
20044
+ }
20045
+ ) : /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 24 24", fill: "currentColor", style: { width: isMobile ? 18 : 20, height: isMobile ? 18 : 20 } }, /* @__PURE__ */ React.createElement("path", { d: "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 9h12v2H6V9zm8 5H6v-2h8v2zm4-6H6V6h12v2z" }))
19927
20046
  ), isOpen && /* @__PURE__ */ React.createElement(
19928
20047
  "div",
19929
20048
  {
19930
- className: "rounded-xl border shadow-lg overflow-hidden transition-all duration-300 flex flex-col",
20049
+ className: "rounded-xl shadow-lg overflow-hidden transition-all duration-300 flex flex-col",
19931
20050
  style: {
19932
20051
  width: responsiveDimensions.width,
19933
20052
  height: responsiveDimensions.height,
19934
20053
  maxWidth: responsiveDimensions.maxWidth,
19935
20054
  maxHeight: responsiveDimensions.maxHeight,
19936
20055
  backgroundColor: appearanceConfig.background_color || "#F9FAFB",
19937
- borderRadius: appearanceConfig.border_radius || "16px"
20056
+ borderRadius: isMobile ? responsiveDimensions.borderRadius : appearanceConfig.border_radius || "16px",
20057
+ ...isMobile ? { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 } : {}
19938
20058
  }
19939
20059
  },
19940
20060
  /* @__PURE__ */ React.createElement(
19941
20061
  "div",
19942
20062
  {
19943
- className: "p-3 sm:p-4 text-center flex-shrink-0 relative",
19944
- style: { backgroundColor: headerConfig.background_color || "#111827", color: headerConfig.font_color || "#FFFFFF", minHeight: 60 }
20063
+ className: "text-center flex-shrink-0 relative transition-colors duration-300",
20064
+ style: {
20065
+ backgroundColor: headerConfig.background_color || "#111827",
20066
+ color: headerConfig.font_color || "#FFFFFF",
20067
+ padding: isMobile ? "12px 16px" : "16px 20px",
20068
+ minHeight: "auto"
20069
+ }
20070
+ },
20071
+ /* @__PURE__ */ React.createElement(
20072
+ "button",
20073
+ {
20074
+ onClick: toggleWidget,
20075
+ className: "absolute right-3 top-1/2 transform -translate-y-1/2 hover:opacity-80 transition-opacity",
20076
+ style: {
20077
+ background: "none",
20078
+ border: "none",
20079
+ cursor: "pointer",
20080
+ fontSize: isMobile ? "28px" : "24px",
20081
+ color: getContrastColor(headerConfig.background_color || "#111827"),
20082
+ width: isMobile ? "40px" : "36px",
20083
+ height: isMobile ? "40px" : "36px",
20084
+ display: "flex",
20085
+ alignItems: "center",
20086
+ justifyContent: "center",
20087
+ padding: "0"
20088
+ }
20089
+ },
20090
+ "×"
20091
+ ),
20092
+ /* @__PURE__ */ React.createElement("div", { className: "flex flex-col items-center justify-center" }, headerConfig.logo_url && /* @__PURE__ */ React.createElement(
20093
+ "img",
20094
+ {
20095
+ src: headerConfig.logo_url,
20096
+ alt: "logo",
20097
+ style: {
20098
+ width: isMobile ? "28px" : "32px",
20099
+ height: isMobile ? "28px" : "32px",
20100
+ marginBottom: isMobile ? "6px" : "8px",
20101
+ borderRadius: "4px"
20102
+ }
20103
+ }
20104
+ ), /* @__PURE__ */ React.createElement("h2", { className: "font-semibold leading-tight", style: { fontSize: isMobile ? "14px" : "16px", margin: "0" } }, headerConfig.title || "Live Chat"), /* @__PURE__ */ React.createElement("p", { className: "opacity-80 leading-tight", style: { fontSize: isMobile ? "11px" : "13px", margin: "2px 0 0 0" } }, headerConfig.subtitle || "Connect with visitors"))
20105
+ ),
20106
+ /* @__PURE__ */ React.createElement(
20107
+ "div",
20108
+ {
20109
+ ref: chatContainerRef,
20110
+ className: "flex-1 relative overflow-y-auto",
20111
+ style: {
20112
+ backgroundColor: appearanceConfig.background_color || "#F9FAFB",
20113
+ paddingBottom: isMobile ? "8px" : "0"
20114
+ }
19945
20115
  },
19946
- /* @__PURE__ */ React.createElement("button", { onClick: toggleWidget, className: "absolute right-3 top-1/2 transform -translate-y-1/2 text-white", style: { background: "none", border: "none", cursor: "pointer" } }, "×"),
19947
- /* @__PURE__ */ React.createElement("div", { className: "flex flex-col items-center justify-center h-full" }, headerConfig.logo_url && /* @__PURE__ */ React.createElement("img", { src: headerConfig.logo_url, alt: "logo", style: { width: 36, height: 36 } }), /* @__PURE__ */ React.createElement("h2", { className: "font-semibold leading-tight text-sm sm:text-base" }, headerConfig.title || "Live Chat"), /* @__PURE__ */ React.createElement("p", { className: "text-xs sm:text-sm opacity-80 leading-tight" }, headerConfig.subtitle || "Connect with visitors"))
20116
+ appearanceConfig.background_image && /* @__PURE__ */ React.createElement("div", { className: "absolute inset-0 pointer-events-none", style: {
20117
+ backgroundImage: `url(${appearanceConfig.background_image})`,
20118
+ backgroundSize: appearanceConfig.background_size || "cover",
20119
+ backgroundPosition: appearanceConfig.background_position || "center",
20120
+ backgroundRepeat: appearanceConfig.background_repeat || "no-repeat",
20121
+ opacity: appearanceConfig.background_opacity ?? 1,
20122
+ zIndex: 0
20123
+ } }),
20124
+ /* @__PURE__ */ React.createElement("div", { className: "relative z-10 p-3 sm:p-4 space-y-2 sm:space-y-3", style: {
20125
+ backgroundColor: appearanceConfig.inner_background_color !== void 0 ? appearanceConfig.inner_background_color : "transparent",
20126
+ paddingBottom: isMobile ? "20px" : "16px"
20127
+ } }, combinedMessages.length === 0 ? /* @__PURE__ */ React.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React.createElement(
20128
+ "div",
20129
+ {
20130
+ className: `text-left p-3 inline-block rounded-lg`,
20131
+ style: {
20132
+ backgroundColor: chatAreaConfig.ai_response_color || "#E2E8F0",
20133
+ borderRadius: chatAreaConfig.chat_bubble_radius || "16px",
20134
+ color: chatAreaConfig.ai_font_color || "#111827",
20135
+ fontSize: isMobile ? "13px" : "14px",
20136
+ maxWidth: isMobile ? "85%" : "80%",
20137
+ wordBreak: "break-word"
20138
+ }
20139
+ },
20140
+ inputAreaConfig.first_ai_message || "Hello! How can I assist you today?"
20141
+ )) : combinedMessages.map((message) => /* @__PURE__ */ React.createElement("div", { key: message.id, className: `flex ${message.role === "user" ? "justify-end" : "justify-start"}` }, /* @__PURE__ */ React.createElement(
20142
+ "div",
20143
+ {
20144
+ className: `p-3 inline-block rounded-lg`,
20145
+ style: {
20146
+ backgroundColor: message.role === "user" ? chatAreaConfig.user_response_color || "#4ADE80" : message.isError ? "#FEE2E2" : chatAreaConfig.ai_response_color || "#E2E8F0",
20147
+ borderRadius: chatAreaConfig.chat_bubble_radius || "16px",
20148
+ fontSize: isMobile ? "13px" : "14px",
20149
+ color: message.role === "user" ? chatAreaConfig.user_font_color || "#111827" : message.isError ? "#991B1B" : chatAreaConfig.ai_font_color || "#111827",
20150
+ marginBottom: isMobile ? "4px" : "2px",
20151
+ maxWidth: isMobile ? "85%" : "80%",
20152
+ wordBreak: "break-word"
20153
+ }
20154
+ },
20155
+ message.role !== "system" ? /* @__PURE__ */ React.createElement(Markdown, { remarkPlugins: [remarkGfm] }, message.content) : /* @__PURE__ */ React.createElement("em", { className: "text-xs opacity-70" }, message.content),
20156
+ chatAreaConfig.show_timestamps && message.timestamp && /* @__PURE__ */ React.createElement("div", { className: "text-xs opacity-70 mt-1 text-right" }, message.timestamp)
20157
+ ))), localLoading && /* @__PURE__ */ React.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React.createElement(
20158
+ "div",
20159
+ {
20160
+ className: "text-left p-3 inline-block max-w-[85%]",
20161
+ style: {
20162
+ backgroundColor: chatAreaConfig.ai_response_color || "#E2E8F0",
20163
+ borderRadius: chatAreaConfig.chat_bubble_radius || "18px",
20164
+ fontSize: isMobile ? "14px" : "14px",
20165
+ color: chatAreaConfig.ai_font_color || "#111827"
20166
+ }
20167
+ },
20168
+ /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce" }), /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }), /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })), /* @__PURE__ */ React.createElement("span", { className: "text-sm", style: { fontSize: isMobile ? "13px" : "14px" } }, isConnecting ? "Connecting..." : "Thinking..."))
20169
+ )))
19948
20170
  ),
19949
- /* @__PURE__ */ React.createElement("div", { ref: chatContainerRef, className: "flex-1 relative overflow-y-auto", style: { backgroundColor: appearanceConfig.background_color || "#F9FAFB" } }, appearanceConfig.background_image && /* @__PURE__ */ React.createElement("div", { className: "absolute inset-0 pointer-events-none", style: {
19950
- backgroundImage: `url(${appearanceConfig.background_image})`,
19951
- backgroundSize: appearanceConfig.background_size || "cover",
19952
- backgroundPosition: appearanceConfig.background_position || "center",
19953
- backgroundRepeat: appearanceConfig.background_repeat || "no-repeat",
19954
- opacity: appearanceConfig.background_opacity ?? 1,
19955
- zIndex: 0
19956
- } }), /* @__PURE__ */ React.createElement("div", { className: "relative z-10 p-3 sm:p-4 space-y-2 sm:space-y-3", style: {
19957
- backgroundColor: appearanceConfig.inner_background_color !== void 0 ? appearanceConfig.inner_background_color : "transparent"
19958
- } }, combinedMessages.length === 0 ? /* @__PURE__ */ React.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React.createElement("div", { className: `text-left p-3 inline-block max-w-[80%]`, style: { backgroundColor: chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", color: chatAreaConfig.ai_font_color || "#111827", fontSize: "14px" } }, inputAreaConfig.first_ai_message || "Hello! How can I assist you today?")) : combinedMessages.map((message) => /* @__PURE__ */ React.createElement("div", { key: message.id, className: `flex ${message.role === "user" ? "justify-end" : "justify-start"}` }, /* @__PURE__ */ React.createElement("div", { className: `p-3 inline-block max-w-[80%]`, style: { backgroundColor: message.role === "user" ? chatAreaConfig.user_response_color || "#4ADE80" : message.isError ? "#FEE2E2" : chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", fontSize: "14px", color: message.role === "user" ? chatAreaConfig.user_font_color || "#111827" : message.isError ? "#991B1B" : chatAreaConfig.ai_font_color || "#111827" } }, message.role !== "system" ? /* @__PURE__ */ React.createElement(Markdown, { remarkPlugins: [remarkGfm] }, message.content) : /* @__PURE__ */ React.createElement("em", { className: "text-xs opacity-70" }, message.content), chatAreaConfig.show_timestamps && message.timestamp && /* @__PURE__ */ React.createElement("div", { className: "text-xs opacity-70 mt-1 text-right" }, message.timestamp)))), localLoading && /* @__PURE__ */ React.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React.createElement("div", { className: "text-left p-3 inline-block max-w-[85%]", style: { backgroundColor: chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", fontSize: "14px", color: chatAreaConfig.ai_font_color || "#111827" } }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce" }), /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }), /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })), /* @__PURE__ */ React.createElement("span", { className: "text-sm" }, isConnecting ? "Connecting..." : "Thinking...")))))),
19959
- /* @__PURE__ */ React.createElement("div", { className: "p-3 flex items-center gap-2 border-t flex-shrink-0", style: { backgroundColor: inputAreaConfig.background_color || "#FFF", borderColor: inputAreaConfig.border_color || "#D1D5DB", minHeight: 70 } }, /* @__PURE__ */ React.createElement("input", { ref: inputRef, value: inputMessage, onChange: (e) => setInputMessage(e.target.value), onKeyPress: handleKeyPress, disabled: localLoading, className: "flex-1 px-3 py-2 border rounded-lg", style: { borderColor: inputAreaConfig.border_color || "#D1D5DB", color: inputAreaConfig.text_color || "#111827", fontSize: "14px", backgroundColor: inputAreaConfig.background_color || "#FFF", minHeight: "44px" }, placeholder: inputAreaConfig.placeholder_text || "Type your message..." }), /* @__PURE__ */ React.createElement("button", { onClick: performSend, disabled: localLoading || !inputMessage.trim(), className: "rounded-full flex items-center justify-center", style: { backgroundColor: ((_b = inputAreaConfig.send_button) == null ? void 0 : _b.color) || "#2563EB", width: 44, height: 44 } }, localLoading ? /* @__PURE__ */ React.createElement("div", { className: "rounded-full animate-spin", style: { width: 16, height: 16, border: "2px solid #FFFFFF", borderTop: "2px solid transparent" } }) : /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 24 24", fill: "currentColor", style: { width: 18, height: 18, color: "#fff" } }, /* @__PURE__ */ React.createElement("path", { d: "M2 21l21-9L2 3v7l15 2-15 2v7z" })))),
19960
- inputAreaConfig.show_branding !== false && /* @__PURE__ */ React.createElement("div", { className: "px-3 pb-3 text-center text-xs opacity-80", style: { backgroundColor: inputAreaConfig.background_color } }, /* @__PURE__ */ React.createElement("a", { href: "https://www.getwidgets.app", target: "_blank", rel: "noopener noreferrer", style: { color: getContrastColor(inputAreaConfig.background_color || "#d52929ff") } }, "Powered by WidgetKraft"))
19961
- ));
20171
+ /* @__PURE__ */ React.createElement(
20172
+ "div",
20173
+ {
20174
+ className: "flex items-center gap-2 border-t flex-shrink-0",
20175
+ style: {
20176
+ backgroundColor: inputAreaConfig.background_color || "#FFF",
20177
+ borderColor: inputAreaConfig.border_color || "#D1D5DB",
20178
+ minHeight: isMobile ? 64 : 70,
20179
+ position: "relative",
20180
+ padding: isMobile ? "10px 12px" : "12px 16px",
20181
+ gap: isMobile ? "8px" : "12px"
20182
+ }
20183
+ },
20184
+ /* @__PURE__ */ React.createElement(
20185
+ "input",
20186
+ {
20187
+ ref: inputRef,
20188
+ value: inputMessage,
20189
+ onChange: (e) => setInputMessage(e.target.value),
20190
+ onKeyPress: handleKeyPress,
20191
+ disabled: localLoading,
20192
+ className: "flex-1 px-3 py-2 border rounded-lg",
20193
+ style: {
20194
+ borderColor: inputAreaConfig.border_color || "#D1D5DB",
20195
+ color: inputAreaConfig.text_color || "#111827",
20196
+ fontSize: isMobile ? "14px" : "14px",
20197
+ backgroundColor: inputAreaConfig.background_color || "#FFF",
20198
+ minHeight: "40px",
20199
+ padding: isMobile ? "8px 12px" : "10px 12px",
20200
+ lineHeight: "1.5"
20201
+ },
20202
+ placeholder: inputAreaConfig.placeholder_text || "Type your message..."
20203
+ }
20204
+ ),
20205
+ /* @__PURE__ */ React.createElement(
20206
+ "button",
20207
+ {
20208
+ onClick: performSend,
20209
+ disabled: localLoading || !inputMessage.trim(),
20210
+ className: "rounded-full flex items-center justify-center flex-shrink-0 hover:opacity-90 transition-opacity",
20211
+ style: {
20212
+ backgroundColor: ((_b = inputAreaConfig.send_button) == null ? void 0 : _b.color) || "#2563EB",
20213
+ width: isMobile ? "40px" : "44px",
20214
+ height: isMobile ? "40px" : "44px",
20215
+ minWidth: isMobile ? "40px" : "44px",
20216
+ minHeight: isMobile ? "40px" : "44px",
20217
+ opacity: localLoading || !inputMessage.trim() ? 0.5 : 1,
20218
+ transition: "opacity 0.2s",
20219
+ border: "none",
20220
+ cursor: "pointer"
20221
+ }
20222
+ },
20223
+ localLoading ? /* @__PURE__ */ React.createElement(
20224
+ "div",
20225
+ {
20226
+ className: "rounded-full animate-spin",
20227
+ style: {
20228
+ width: isMobile ? 18 : 16,
20229
+ height: isMobile ? 18 : 16,
20230
+ border: "2px solid #FFFFFF",
20231
+ borderTop: "2px solid transparent"
20232
+ }
20233
+ }
20234
+ ) : /* @__PURE__ */ React.createElement(
20235
+ "svg",
20236
+ {
20237
+ viewBox: "0 0 24 24",
20238
+ fill: "currentColor",
20239
+ style: {
20240
+ width: isMobile ? 20 : 18,
20241
+ height: isMobile ? 20 : 18,
20242
+ color: "#fff"
20243
+ }
20244
+ },
20245
+ /* @__PURE__ */ React.createElement("path", { d: "M2 21l21-9L2 3v7l15 2-15 2v7z" })
20246
+ )
20247
+ )
20248
+ ),
20249
+ inputAreaConfig.show_branding !== false && /* @__PURE__ */ React.createElement(
20250
+ "div",
20251
+ {
20252
+ className: "text-center text-xs",
20253
+ style: {
20254
+ backgroundColor: inputAreaConfig.background_color,
20255
+ padding: isMobile ? "8px 12px" : "12px 16px"
20256
+ }
20257
+ },
20258
+ /* @__PURE__ */ React.createElement(
20259
+ "a",
20260
+ {
20261
+ href: "https://www.widgetkraft.com",
20262
+ target: "_blank",
20263
+ rel: "noopener noreferrer",
20264
+ style: {
20265
+ color: getContrastColor(inputAreaConfig.background_color || "#d52929ff"),
20266
+ fontSize: isMobile ? "11px" : "12px",
20267
+ textDecoration: "none"
20268
+ }
20269
+ },
20270
+ "Powered by WidgetKraft"
20271
+ )
20272
+ )
20273
+ ), /* @__PURE__ */ React.createElement("style", { jsx: true }, `
20274
+ /* Hide scrollbar for all browsers */
20275
+ .hide-scrollbar::-webkit-scrollbar { display: none; }
20276
+ .hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
20277
+
20278
+ /* Mobile-first responsive design */
20279
+ @media (max-width: 640px) {
20280
+ .responsive-notification {
20281
+ margin: 16px auto !important;
20282
+ }
20283
+
20284
+ /* Improve text readability on small screens */
20285
+ .responsive-message-bubble {
20286
+ word-wrap: break-word;
20287
+ overflow-wrap: break-word;
20288
+ }
20289
+ }
20290
+
20291
+ @media (max-width: 480px) {
20292
+ .responsive-notification {
20293
+ margin: 12px auto !important;
20294
+ min-width: 85vw;
20295
+ }
20296
+ }
20297
+
20298
+ /* Touch-friendly sizes for mobile */
20299
+ @media (hover: none) and (pointer: coarse) {
20300
+ button {
20301
+ min-width: 44px;
20302
+ min-height: 44px;
20303
+ }
20304
+
20305
+ input {
20306
+ min-height: 44px;
20307
+ }
20308
+ }
20309
+
20310
+ /* Desktop optimizations */
20311
+ @media (min-width: 769px) {
20312
+ .responsive-notification:hover {
20313
+ transform: translateY(-2px);
20314
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
20315
+ }
20316
+ }
20317
+
20318
+ /* Scrollbar styling for chat container */
20319
+ .responsive-messages-area::-webkit-scrollbar {
20320
+ width: 6px;
20321
+ }
20322
+
20323
+ .responsive-messages-area::-webkit-scrollbar-track {
20324
+ background: transparent;
20325
+ }
20326
+
20327
+ .responsive-messages-area::-webkit-scrollbar-thumb {
20328
+ background: #ccc;
20329
+ border-radius: 3px;
20330
+ }
20331
+
20332
+ .responsive-messages-area::-webkit-scrollbar-thumb:hover {
20333
+ background: #999;
20334
+ }
20335
+ `));
19962
20336
  };
19963
20337
  function init({ widgetId, apiKey, mode = "inline" }) {
19964
20338
  const container = document.getElementById("livechat-root");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getwidgets/live-chat-widget",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "main": "dist/live-chat-widget.umd.js",
5
5
  "unpkg": "dist/live-chat-widget.umd.js",
6
6
  "type": "module",
@@ -11,6 +11,8 @@
11
11
  "build": "vite build"
12
12
  },
13
13
  "dependencies": {
14
+ "@emoji-mart/data": "^1.2.1",
15
+ "@emoji-mart/react": "^1.1.1",
14
16
  "axios": "^1.6.8",
15
17
  "lucide-react": "^0.456.0",
16
18
  "react": "^18.3.0",