@flowengage/react-chatbot 6.0.18 → 6.0.20

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.
@@ -3357,7 +3357,10 @@ function Rr({ siteId: e, config: t, children: n, language: r = "en" }) {
3357
3357
  }), await Rt({
3358
3358
  ...r,
3359
3359
  callId: r.callId || O.callId
3360
- })), await k.current.acceptCall(O.callId, y), mt.current = O.callId, Je(O.callId), Xe((e) => e === "connected" || j.current ? "connected" : "connecting"), Ue(null), w(!0);
3360
+ })), await k.current.acceptCall(O.callId, y), at.current?.emit("call:accepted", {
3361
+ callId: O.callId,
3362
+ chatId: y
3363
+ }), mt.current = O.callId, Je(O.callId), Xe((e) => e === "connected" || j.current ? "connected" : "connecting"), Ue(null), w(!0);
3361
3364
  } catch (e) {
3362
3365
  if (ht.current = null, Pt("accept_call_failed"), e?.status === 404 || e?.status === 409 || e?.status === 422) {
3363
3366
  nt(Pr(e, "This visitor call is no longer available."));
@@ -3380,9 +3383,14 @@ function Rr({ siteId: e, config: t, children: n, language: r = "en" }) {
3380
3383
  Pt("reject_call_without_server_context");
3381
3384
  return;
3382
3385
  }
3383
- Mt(), jt();
3386
+ let e = O.callId;
3387
+ Mt(), jt(), at.current?.emit("call:rejected", {
3388
+ callId: e,
3389
+ chatId: y,
3390
+ reason: "visitor_declined"
3391
+ });
3384
3392
  try {
3385
- await k.current.rejectCall(O.callId, y);
3393
+ await k.current.rejectCall(e, y);
3386
3394
  } catch (e) {
3387
3395
  nt(Pr(e, "We couldn't decline the call cleanly."));
3388
3396
  } finally {
@@ -29412,6 +29420,11 @@ function Ck(e) {
29412
29420
  flowengage_highlight: async (e) => {
29413
29421
  $("flowengage_highlight ▶", e);
29414
29422
  let t = mk(e), n = t?.section_id || t?.sectionId, r = t?.section_text || t?.sectionText;
29423
+ if (typeof window < "u" && window.__fe_user_nav_during_speech) {
29424
+ let e = window.__fe_user_nav_during_speech, t = window.location.pathname;
29425
+ if (Date.now() - e.ts >= 3e4) window.__fe_user_nav_during_speech = null;
29426
+ else return $("flowengage_highlight ✖ blocked — user navigated during speech", e), `NAV_CHANGED: The visitor navigated from "${e.fromPageName}" to "${e.toPageName}" (current path: ${t}) while you were speaking. STOP the current walkthrough immediately. DO NOT call flowengage_highlight again. Say out loud: "I see you've navigated to the ${e.toPageName} page — do you want me to continue what I was explaining, or shall I guide you through this page?" Wait for the visitor's answer before doing anything else.`;
29427
+ }
29415
29428
  xk();
29416
29429
  let i = hr(n || null, r || null);
29417
29430
  if (!i && r) {
@@ -30132,7 +30145,7 @@ function Fk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30132
30145
  let v = {
30133
30146
  clientTools: t,
30134
30147
  connectionType: "websocket",
30135
- minSpeechDurationMs: 100,
30148
+ minSpeechDurationMs: 50,
30136
30149
  ..._ ? { signedUrl: _ } : { agentId: r }
30137
30150
  }, b = (p.split("/").filter(Boolean).pop() || "").replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()), x = "";
30138
30151
  m && m.includes("|") && (x = m.split("|").map((e) => e.trim()).filter(Boolean).reduce((e, t) => e.length <= t.length ? e : t));
@@ -30243,13 +30256,28 @@ function Fk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30243
30256
  t = n;
30244
30257
  return;
30245
30258
  }
30259
+ let r = t;
30246
30260
  t = n;
30247
- let r = window.location.href, i = typeof document < "u" ? document.title : "", a = typeof document < "u" ? Array.from(document.querySelectorAll("h1, h2, h3, h4")).filter((e) => !e.closest("#flowengage-root, .flowengage-shell")).map((e) => ({
30261
+ let i = window.location.href, a = typeof document < "u" ? document.title : "", o = typeof document < "u" ? Array.from(document.querySelectorAll("h1, h2, h3, h4")).filter((e) => !e.closest("#flowengage-root, .flowengage-shell")).map((e) => ({
30248
30262
  tag: e.tagName,
30249
30263
  text: e.textContent.trim()
30250
30264
  })).filter((e) => e.text.length > 0 && e.text.length < 200).slice(0, 20) : [];
30251
30265
  try {
30252
- S.current?.sendContextualUpdate?.(`PAGE CHANGED — visitor navigated manually. Current URL is now: ${r}. Page title: "${i}". Sections on this page: ${JSON.stringify(a)}. When the visitor asks about "this page", "current page", or "what page am I on", refer to this new URL — not any previously mentioned page.`);
30266
+ SD();
30267
+ } catch {}
30268
+ let s = (e) => (e.split("/").filter(Boolean).pop() || "").replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()) || "Home", c = s(r), l = s(n);
30269
+ typeof window < "u" && (window.__fe_user_nav_during_speech = {
30270
+ fromPath: r,
30271
+ toPath: n,
30272
+ fromPageName: c,
30273
+ toPageName: l,
30274
+ ts: Date.now()
30275
+ });
30276
+ try {
30277
+ S.current?.sendUserMessage?.(`I just navigated to the ${l} page`);
30278
+ } catch {}
30279
+ try {
30280
+ S.current?.sendContextualUpdate?.(`VISITOR NAVIGATED WHILE YOU WERE SPEAKING. You were explaining "${c}". Visitor moved to "${l}" (${i}). Page title: "${a}". Sections on this page: ${JSON.stringify(o)}. Ask: "I see you've navigated to the ${l} page — do you want me to continue what I was explaining, or would you like to know about this page?" If "continue": resume verbally, do NOT call flowengage_highlight (wrong page DOM). If they want this page: call flowengage_highlight for sections of "${l}". Do NOT highlight anything until the visitor answers.`);
30253
30281
  } catch {}
30254
30282
  };
30255
30283
  c = window.history.pushState.bind(window.history), window.history.pushState = (...e) => {
@@ -30269,7 +30297,7 @@ function Fk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30269
30297
  if (i) try {
30270
30298
  He(i);
30271
30299
  } catch {}
30272
- Ar(), le.current &&= (clearTimeout(le.current), null), ue.current &&= (clearTimeout(ue.current), null), ce.current = !1, de.current = !1, se.current = "idle", c && typeof window < "u" && (window.history.pushState = c), d && typeof window < "u" && window.removeEventListener("popstate", d);
30300
+ typeof window < "u" && (window.__fe_user_nav_during_speech = null), Ar(), le.current &&= (clearTimeout(le.current), null), ue.current &&= (clearTimeout(ue.current), null), ce.current = !1, de.current = !1, se.current = "idle", c && typeof window < "u" && (window.history.pushState = c), d && typeof window < "u" && window.removeEventListener("popstate", d);
30273
30301
  let t = o || S.current, n = E.current, r = ie.current;
30274
30302
  if (t?.endSession?.().catch(() => {}), n && s && a) {
30275
30303
  let e = r ? Math.round((Date.now() - r) / 1e3) : 0, t = JSON.stringify({
@@ -30630,7 +30658,19 @@ var Lk = () => /* @__PURE__ */ g("div", {
30630
30658
  })
30631
30659
  });
30632
30660
  function Rk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i, quickChatOptions: a, onQuickChatSelect: o, isMobile: s, chatHistory: l, isAiTyping: u, isAgentTyping: d, activeScreen: f, agentName: v, agentHeadshot: y, fallbackAgentName: b, input: x, setInput: S, onSubmit: C, isConversationEnded: w, isLoading: T, isRateLimited: ee, rateLimitMessage: te, selectedFile: ne, onFileSelect: re, onRemoveSelectedFile: E, attachmentError: ie, isUploadingAttachment: ae, requiresEmail: oe, emailInput: D, setEmailInput: se, emailError: ce, emailCaptureSuccess: le, replyContext: ue, setReplyContext: de, webRTCError: fe, micError: pe, setMicError: me, dismissCallError: he, activeCallId: ge, isCallMuted: _e, toggleCallMute: ve, endWebRTCCall: ye, formatCallDuration: be, callDurationSeconds: xe, isCallMinimized: Se, onExpand: Ce, onCollapse: we, onStartVoice: Te, onNewChat: Ee, showPoweredBy: De, getVisitorChatHistory: Oe, resumeChat: ke, isSessionRestoring: Ae, isClosing: je }) {
30633
- let Me = l.length > 0, Ne = T || ee || w, Pe = !!ge, [Fe, Ie] = m(!1), [Le, Re] = m(!1), [ze, Be] = m([]), [Ve, He] = m(!1), O = p(null), Ue = async () => {
30661
+ let Me = l.length > 0, Ne = T || ee || w, Pe = !!ge, [Fe, Ie] = m(!1), [Le, Re] = m(!1), [ze, Be] = m([]), [Ve, He] = m(!1), O = p(null), [Ue, We] = m(() => typeof window < "u" ? window.visualViewport?.height ?? window.innerHeight : 600), [Ge, Ke] = m(0);
30662
+ c(() => {
30663
+ if (!s) return;
30664
+ let e = window.visualViewport;
30665
+ if (!e) return;
30666
+ let t = () => {
30667
+ We(e.height), Ke(Math.max(0, window.innerHeight - e.offsetTop - e.height));
30668
+ };
30669
+ return e.addEventListener("resize", t), e.addEventListener("scroll", t), t(), () => {
30670
+ e.removeEventListener("resize", t), e.removeEventListener("scroll", t);
30671
+ };
30672
+ }, [s]);
30673
+ let qe = s && window.innerHeight - Ue > 150, Je = async () => {
30634
30674
  Ie(!1), Re(!0), He(!0);
30635
30675
  try {
30636
30676
  let e = await Oe();
@@ -30640,7 +30680,7 @@ function Rk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
30640
30680
  } finally {
30641
30681
  He(!1);
30642
30682
  }
30643
- }, We = async (e) => {
30683
+ }, Ye = async (e) => {
30644
30684
  Re(!1), ke?.(e.chatId);
30645
30685
  };
30646
30686
  return c(() => {
@@ -30657,9 +30697,8 @@ function Rk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
30657
30697
  position: "fixed",
30658
30698
  left: "8px",
30659
30699
  right: "8px",
30660
- bottom: 0,
30661
- width: "calc(100% - 16px)",
30662
- height: "90dvh",
30700
+ bottom: `${Ge}px`,
30701
+ height: Ue > 0 ? `${Math.round(Ue * .92)}px` : "90dvh",
30663
30702
  background: r,
30664
30703
  borderRadius: "16px 16px 0 0",
30665
30704
  display: "flex",
@@ -30949,7 +30988,7 @@ function Rk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
30949
30988
  margin: "0 14px"
30950
30989
  } }), /* @__PURE__ */ _("button", {
30951
30990
  type: "button",
30952
- onClick: Ue,
30991
+ onClick: Je,
30953
30992
  style: {
30954
30993
  display: "flex",
30955
30994
  alignItems: "center",
@@ -31140,7 +31179,7 @@ function Rk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
31140
31179
  },
31141
31180
  children: "Loading past conversations..."
31142
31181
  }) : ze.length > 0 ? /* @__PURE__ */ g("div", { children: ze.map((e) => /* @__PURE__ */ _("div", {
31143
- onClick: () => We(e),
31182
+ onClick: () => Ye(e),
31144
31183
  style: {
31145
31184
  padding: "16px 20px",
31146
31185
  borderBottom: "1px solid #f3f4f6",
@@ -31357,11 +31396,12 @@ function Rk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
31357
31396
  inputPlaceholder: e.inputPlaceholder
31358
31397
  })
31359
31398
  }),
31360
- /* @__PURE__ */ g("div", {
31399
+ !qe && /* @__PURE__ */ g("div", {
31361
31400
  style: {
31362
31401
  flexShrink: 0,
31363
31402
  textAlign: "center",
31364
- padding: "12px 20px 18px",
31403
+ padding: "8px 20px",
31404
+ paddingBottom: "max(12px, env(safe-area-inset-bottom, 12px))",
31365
31405
  pointerEvents: "none"
31366
31406
  },
31367
31407
  children: De && /* @__PURE__ */ _("span", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowengage/react-chatbot",
3
- "version": "6.0.18",
3
+ "version": "6.0.20",
4
4
  "description": "Embeddable AI chat widget for React — powered by FlowEngage. Drop it in with a single siteId.",
5
5
  "keywords": [
6
6
  "chatbot",