polymorph-sdk 0.2.5 → 0.2.6

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.js CHANGED
@@ -16532,39 +16532,39 @@ function Lt() {
16532
16532
  return s = c = void 0, p = t, u = n.apply(a, i), u;
16533
16533
  }
16534
16534
  function E(t) {
16535
- return p = t, d = setTimeout(R, i), m ? C(t) : u;
16535
+ return p = t, d = setTimeout(j, i), m ? C(t) : u;
16536
16536
  }
16537
16537
  function O(t) {
16538
16538
  var n = t - f, a = t - p, s = i - n;
16539
16539
  return b ? v(s, l - a) : s;
16540
16540
  }
16541
- function j(t) {
16541
+ function Mg(t) {
16542
16542
  var n = t - f, a = t - p;
16543
16543
  return f === void 0 || n >= i || n < 0 || b && a >= l;
16544
16544
  }
16545
- function R() {
16545
+ function j() {
16546
16546
  var t = y();
16547
- if (j(t)) return Gg(t);
16548
- d = setTimeout(R, O(t));
16547
+ if (Mg(t)) return Ng(t);
16548
+ d = setTimeout(j, O(t));
16549
16549
  }
16550
- function Gg(t) {
16550
+ function Ng(t) {
16551
16551
  return d = void 0, S && s ? C(t) : (s = c = void 0, u);
16552
16552
  }
16553
- function Kg() {
16553
+ function Pg() {
16554
16554
  d !== void 0 && clearTimeout(d), p = 0, s = f = c = d = void 0;
16555
16555
  }
16556
- function V() {
16557
- return d === void 0 ? u : Gg(y());
16556
+ function Fg() {
16557
+ return d === void 0 ? u : Ng(y());
16558
16558
  }
16559
- function H() {
16560
- var t = y(), n = j(t);
16559
+ function R() {
16560
+ var t = y(), n = Mg(t);
16561
16561
  if (s = arguments, c = this, f = t, n) {
16562
16562
  if (d === void 0) return E(f);
16563
- if (b) return d = setTimeout(R, i), C(f);
16563
+ if (b) return d = setTimeout(j, i), C(f);
16564
16564
  }
16565
- return d === void 0 && (d = setTimeout(R, i)), u;
16565
+ return d === void 0 && (d = setTimeout(j, i)), u;
16566
16566
  }
16567
- return H.cancel = Kg, H.flush = V, H;
16567
+ return R.cancel = Pg, R.flush = Fg, R;
16568
16568
  }
16569
16569
  function x(t) {
16570
16570
  var n = typeof t;
@@ -17680,45 +17680,47 @@ function RoomHandler({ setRoom: t, addMessage: n, isVoiceEnabled: i }) {
17680
17680
  }, [a, n]), i ? /* @__PURE__ */ jsx(ba, {}) : null;
17681
17681
  }
17682
17682
  var styles_module_default = {
17683
- widgetRoot: "_widgetRoot_lqi22_1",
17684
- bottomRight: "_bottomRight_lqi22_11",
17685
- bottomLeft: "_bottomLeft_lqi22_16",
17686
- fab: "_fab_lqi22_22",
17687
- fabOpen: "_fabOpen_lqi22_42",
17688
- notificationDot: "_notificationDot_lqi22_53",
17689
- notificationPulse: "_notificationPulse_lqi22_1",
17690
- fabWiggle: "_fabWiggle_lqi22_75",
17691
- panel: "_panel_lqi22_101",
17692
- panelHidden: "_panelHidden_lqi22_121",
17693
- header: "_header_lqi22_126",
17694
- chatThread: "_chatThread_lqi22_133",
17695
- messageBubble: "_messageBubble_lqi22_142",
17696
- messageAppear: "_messageAppear_lqi22_1",
17697
- agentMessage: "_agentMessage_lqi22_161",
17698
- userMessage: "_userMessage_lqi22_166",
17699
- senderLabel: "_senderLabel_lqi22_170",
17700
- voiceLabel: "_voiceLabel_lqi22_176",
17701
- voiceOverlay: "_voiceOverlay_lqi22_181",
17702
- voiceBars: "_voiceBars_lqi22_190",
17703
- voiceBar: "_voiceBar_lqi22_190",
17704
- toggleGroup: "_toggleGroup_lqi22_223",
17705
- voiceToggle: "_voiceToggle_lqi22_228",
17706
- voiceToggleActive: "_voiceToggleActive_lqi22_248",
17707
- screenShareToggleActive: "_screenShareToggleActive_lqi22_256",
17708
- inputBar: "_inputBar_lqi22_264",
17709
- inputField: "_inputField_lqi22_271",
17710
- iconButton: "_iconButton_lqi22_293",
17711
- iconButtonActive: "_iconButtonActive_lqi22_320",
17712
- statusBadge: "_statusBadge_lqi22_323",
17713
- errorText: "_errorText_lqi22_329",
17714
- thinkingDots: "_thinkingDots_lqi22_334",
17715
- thinkingDot: "_thinkingDot_lqi22_334",
17716
- identityForm: "_identityForm_lqi22_365",
17717
- formField: "_formField_lqi22_373",
17718
- formLabel: "_formLabel_lqi22_378",
17719
- formInput: "_formInput_lqi22_383",
17720
- formError: "_formError_lqi22_401",
17721
- formSubmitButton: "_formSubmitButton_lqi22_405"
17683
+ widgetRoot: "_widgetRoot_1e1lr_1",
17684
+ bottomRight: "_bottomRight_1e1lr_11",
17685
+ bottomLeft: "_bottomLeft_1e1lr_16",
17686
+ fab: "_fab_1e1lr_22",
17687
+ fabOpen: "_fabOpen_1e1lr_42",
17688
+ notificationDot: "_notificationDot_1e1lr_53",
17689
+ notificationPulse: "_notificationPulse_1e1lr_1",
17690
+ fabWiggle: "_fabWiggle_1e1lr_75",
17691
+ panel: "_panel_1e1lr_101",
17692
+ panelHidden: "_panelHidden_1e1lr_121",
17693
+ header: "_header_1e1lr_126",
17694
+ chatThread: "_chatThread_1e1lr_133",
17695
+ messageBubble: "_messageBubble_1e1lr_142",
17696
+ messageAppear: "_messageAppear_1e1lr_1",
17697
+ agentMessage: "_agentMessage_1e1lr_161",
17698
+ userMessage: "_userMessage_1e1lr_166",
17699
+ senderLabel: "_senderLabel_1e1lr_170",
17700
+ voiceLabel: "_voiceLabel_1e1lr_176",
17701
+ voiceOverlay: "_voiceOverlay_1e1lr_181",
17702
+ voiceBars: "_voiceBars_1e1lr_190",
17703
+ voiceBar: "_voiceBar_1e1lr_190",
17704
+ toggleGroup: "_toggleGroup_1e1lr_223",
17705
+ voiceToggle: "_voiceToggle_1e1lr_228",
17706
+ voiceToggleActive: "_voiceToggleActive_1e1lr_248",
17707
+ screenShareToggleActive: "_screenShareToggleActive_1e1lr_256",
17708
+ inputBar: "_inputBar_1e1lr_264",
17709
+ inputField: "_inputField_1e1lr_271",
17710
+ iconButton: "_iconButton_1e1lr_293",
17711
+ iconButtonActive: "_iconButtonActive_1e1lr_320",
17712
+ statusBadge: "_statusBadge_1e1lr_323",
17713
+ errorText: "_errorText_1e1lr_329",
17714
+ thinkingDots: "_thinkingDots_1e1lr_334",
17715
+ thinkingDot: "_thinkingDot_1e1lr_334",
17716
+ identityForm: "_identityForm_1e1lr_365",
17717
+ formField: "_formField_1e1lr_373",
17718
+ formLabel: "_formLabel_1e1lr_378",
17719
+ formInput: "_formInput_1e1lr_383",
17720
+ formError: "_formError_1e1lr_401",
17721
+ formSubmitButton: "_formSubmitButton_1e1lr_405",
17722
+ termsBar: "_termsBar_1e1lr_424",
17723
+ termsLabel: "_termsLabel_1e1lr_430"
17722
17724
  };
17723
17725
  function hexToMantineTuple(t) {
17724
17726
  let n = Number.parseInt(t.slice(1, 3), 16), i = Number.parseInt(t.slice(3, 5), 16), a = Number.parseInt(t.slice(5, 7), 16), s = (t) => `#${[
@@ -17754,6 +17756,12 @@ function buildWidgetTheme(t = "#171717") {
17754
17756
  function resolveApiBaseUrl(t) {
17755
17757
  return t || (typeof window < "u" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") ? "http://localhost:8080" : "https://api.usepolymorph.com");
17756
17758
  }
17759
+ function uuid() {
17760
+ return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (t) => {
17761
+ let n = Math.random() * 16 | 0;
17762
+ return (t === "x" ? n : n & 3 | 8).toString(16);
17763
+ });
17764
+ }
17757
17765
  function storageKey(t, n) {
17758
17766
  return n ? `${t}:${n}` : t;
17759
17767
  }
@@ -17763,6 +17771,13 @@ function loadStoredIdentity(t) {
17763
17771
  if (n) return JSON.parse(n);
17764
17772
  } catch {}
17765
17773
  }
17774
+ function loadTermsAccepted(t) {
17775
+ try {
17776
+ return localStorage.getItem(storageKey("polymorph_tc_accepted", t)) === "true";
17777
+ } catch {
17778
+ return !1;
17779
+ }
17780
+ }
17766
17781
  async function ensureCsrf(t, n, i) {
17767
17782
  let a = storageKey("polymorph.csrf", n);
17768
17783
  if (!sessionStorage.getItem(a)) try {
@@ -17792,19 +17807,19 @@ function buildAuthHeaders(t, n) {
17792
17807
  return i;
17793
17808
  }
17794
17809
  function usePolymorphSession(t) {
17795
- let n = resolveApiBaseUrl(t.apiBaseUrl), a = t.configId || t.apiKey, [c, l] = useState("idle"), [f, p] = useState(null), [m, g] = useState([]), [v, y] = useState(!1), [b, x] = useState(!1), [S, C] = useState(!1), [w, E] = useState(!1), [O, j] = useState(!1), [R, Gg] = useState(0), [Kg, V] = useState(null), [H, qg] = useState(null), [K, Jg] = useState(t.user ?? loadStoredIdentity(a)), X = useRef(null), Yg = useRef([]), Xg = useRef(!1), Zg = useRef(t.fetchOptions);
17796
- Zg.current = t.fetchOptions, useEffect(() => {
17810
+ let n = resolveApiBaseUrl(t.apiBaseUrl), a = t.autoCapture ?? !0, c = t.configId || t.apiKey, [l, f] = useState("idle"), [p, m] = useState(null), [g, v] = useState([]), [y, b] = useState(!1), [x, S] = useState(!1), [C, w] = useState(!1), [E, O] = useState(!1), [Mg, j] = useState(!1), [Ng, Pg] = useState(0), [Fg, R] = useState(null), [V, Ig] = useState(null), [H, Lg] = useState(t.user ?? loadStoredIdentity(c)), [Rg, zg] = useState(loadTermsAccepted(c)), K = useRef(null), Bg = useRef([]), Vg = useRef([]), Hg = useRef(!1), Ug = useRef(t.fetchOptions);
17811
+ Ug.current = t.fetchOptions, useEffect(() => {
17797
17812
  let i = !1;
17798
- async function s() {
17813
+ async function a() {
17799
17814
  try {
17800
- let s = Zg.current;
17801
- !t.apiKey && s?.credentials === "include" && await ensureCsrf(n, a, s);
17802
- let c = t.configId ? `?config_id=${t.configId}` : "", l = await fetch(`${n}/widget-configs/resolve${c}`, {
17815
+ let a = Ug.current;
17816
+ !t.apiKey && a?.credentials === "include" && await ensureCsrf(n, c, a);
17817
+ let s = t.configId ? `?config_id=${t.configId}` : "", l = await fetch(`${n}/widget-configs/resolve${s}`, {
17803
17818
  headers: {
17804
- ...buildAuthHeaders(t, a),
17805
- ...s?.headers instanceof Headers ? Object.fromEntries(s.headers.entries()) : s?.headers
17819
+ ...buildAuthHeaders(t, c),
17820
+ ...a?.headers instanceof Headers ? Object.fromEntries(a.headers.entries()) : a?.headers
17806
17821
  },
17807
- credentials: s?.credentials
17822
+ credentials: a?.credentials
17808
17823
  });
17809
17824
  if (!l.ok) return;
17810
17825
  let u = await l.json();
@@ -17819,20 +17834,23 @@ function usePolymorphSession(t) {
17819
17834
  enableVoice: u.enable_voice,
17820
17835
  greeting: u.greeting,
17821
17836
  collectEmail: u.collect_email,
17822
- collectPhone: u.collect_phone
17837
+ collectPhone: u.collect_phone,
17838
+ alwaysOn: u.always_on ?? !1,
17839
+ enableTermsAndConditions: u.enable_terms_and_conditions ?? !1,
17840
+ termsAndConditionsText: u.terms_and_conditions_text ?? ""
17823
17841
  };
17824
- qg(d);
17825
- let f = K?.name, p = d.greeting || (f ? `Hey ${f}! How can I help ya today?` : "Hey! How can I help ya today?");
17826
- g((t) => t.length > 0 ? t : [{
17842
+ Ig(d);
17843
+ let f = H?.name, p = d.greeting || (f ? `Hey ${f}! How can I help ya today?` : "Hey! How can I help ya today?");
17844
+ v((t) => t.length > 0 ? t : [{
17827
17845
  id: "greeting",
17828
17846
  role: "agent",
17829
17847
  text: p,
17830
17848
  source: "chat",
17831
17849
  timestamp: Date.now()
17832
- }]), y(!1), x(!1);
17850
+ }]), b(!1), S(!1);
17833
17851
  } catch {}
17834
17852
  }
17835
- return s(), () => {
17853
+ return a(), () => {
17836
17854
  i = !0;
17837
17855
  };
17838
17856
  }, [
@@ -17840,21 +17858,41 @@ function usePolymorphSession(t) {
17840
17858
  t.apiKey,
17841
17859
  t.configId,
17842
17860
  t.agentName,
17843
- a,
17861
+ c,
17844
17862
  t,
17845
- K?.name
17863
+ H?.name
17846
17864
  ]);
17847
- let Z = H ? {
17848
- collectEmail: H.collectEmail,
17849
- collectPhone: H.collectPhone
17850
- } : null, Qg = Z !== null && (Z.collectEmail !== "hidden" || Z.collectPhone !== "hidden") && !K?.name, $g = useCallback((t) => {
17851
- Jg(t);
17865
+ let Wg = V ? {
17866
+ collectEmail: V.collectEmail,
17867
+ collectPhone: V.collectPhone
17868
+ } : null, Gg = Wg !== null && (Wg.collectEmail !== "hidden" || Wg.collectPhone !== "hidden") && !H?.name, Kg = useCallback((t) => {
17869
+ Lg(t);
17852
17870
  try {
17853
- localStorage.setItem(storageKey("polymorph_user_identity", a), JSON.stringify(t));
17871
+ localStorage.setItem(storageKey("polymorph_user_identity", c), JSON.stringify(t));
17854
17872
  } catch {}
17855
- }, [a]), e_ = useCallback((t, n, i, a, s) => {
17856
- t === "agent" && !Xg.current && (j(!0), Gg((t) => t + 1)), g((c) => [...c, {
17857
- id: crypto.randomUUID(),
17873
+ }, [c]), qg = useCallback(() => {
17874
+ zg(!0);
17875
+ try {
17876
+ localStorage.setItem(storageKey("polymorph_tc_accepted", c), "true");
17877
+ } catch {}
17878
+ }, [c]), Jg = V?.enableTermsAndConditions === !0 && !Rg, Yg = useRef(typeof document < "u" ? document.title : ""), [X, Xg] = useState(0);
17879
+ useEffect(() => {
17880
+ if (X === 0) {
17881
+ document.title = Yg.current;
17882
+ return;
17883
+ }
17884
+ let t = Yg.current, n = !0;
17885
+ document.title = `(${X}) New message${X > 1 ? "s" : ""} - ${t}`;
17886
+ let i = setInterval(() => {
17887
+ n = !n, document.title = n ? `(${X}) New message${X > 1 ? "s" : ""} - ${t}` : t;
17888
+ }, 1500);
17889
+ return () => {
17890
+ clearInterval(i), document.title = t;
17891
+ };
17892
+ }, [X]);
17893
+ let Zg = useCallback((t, n, i, a, s) => {
17894
+ t === "agent" && !Hg.current && (j(!0), Pg((t) => t + 1), Xg((t) => t + 1)), v((c) => [...c, {
17895
+ id: uuid(),
17858
17896
  role: t,
17859
17897
  text: n,
17860
17898
  source: i,
@@ -17862,137 +17900,206 @@ function usePolymorphSession(t) {
17862
17900
  senderName: a,
17863
17901
  senderType: s
17864
17902
  }]);
17865
- }, []), t_ = useCallback(() => {
17866
- j(!1);
17867
- }, []), n_ = useCallback((t) => {
17868
- Xg.current = t, t && j(!1);
17869
- }, []), Q = useCallback(async () => {
17870
- if (!(c === "connecting" || c === "connected")) {
17871
- l("connecting"), V(null);
17903
+ }, []), Qg = useCallback(() => {
17904
+ j(!1), Xg(0);
17905
+ }, []), $g = useCallback((t) => {
17906
+ Hg.current = t, t && (j(!1), Xg(0));
17907
+ }, []), Z = useCallback(async () => {
17908
+ if (!(l === "connecting" || l === "connected")) {
17909
+ f("connecting"), R(null);
17872
17910
  try {
17873
- let { headers: i,...s } = t.fetchOptions ?? {}, c = {};
17874
- if (t.apiKey) c.Authorization = `Bearer ${t.apiKey}`;
17875
- else if (s.credentials === "include") {
17876
- await ensureCsrf(n, a, s);
17877
- let t = sessionStorage.getItem(storageKey("polymorph.csrf", a));
17878
- t && (c["x-csrf-token"] = t);
17911
+ let { headers: i,...a } = t.fetchOptions ?? {}, s = {};
17912
+ if (t.apiKey) s.Authorization = `Bearer ${t.apiKey}`;
17913
+ else if (a.credentials === "include") {
17914
+ await ensureCsrf(n, c, a);
17915
+ let t = sessionStorage.getItem(storageKey("polymorph.csrf", c));
17916
+ t && (s["x-csrf-token"] = t);
17879
17917
  }
17880
- let l = storageKey("polymorph_widget_session", a), u = localStorage.getItem(l) ?? void 0;
17881
- u || (u = `widget-session-${crypto.randomUUID().slice(0, 12)}`, localStorage.setItem(l, u));
17882
- let d = H?.id ?? t.configId, f = await fetch(`${n}/voice-rooms/start`, {
17918
+ let l = storageKey("polymorph_widget_session", c), u = localStorage.getItem(l) ?? void 0;
17919
+ u || (u = `widget-session-${uuid().slice(0, 12)}`, localStorage.setItem(l, u));
17920
+ let d = V?.id ?? t.configId, f = await fetch(`${n}/voice-rooms/start`, {
17883
17921
  method: "POST",
17884
17922
  headers: {
17885
17923
  "Content-Type": "application/json",
17886
- ...c,
17924
+ ...s,
17887
17925
  ...i instanceof Headers ? Object.fromEntries(i.entries()) : i
17888
17926
  },
17889
17927
  body: JSON.stringify({
17890
17928
  agent_name: t.agentName || "custom-voice-agent",
17891
17929
  config_id: d ?? void 0,
17892
17930
  metadata: d ? void 0 : t.metadata,
17893
- user_name: K?.name,
17894
- user_email: K?.email,
17895
- user_phone: K?.phone,
17931
+ user_name: H?.name,
17932
+ user_email: H?.email,
17933
+ user_phone: H?.phone,
17896
17934
  external_user_id: u
17897
17935
  }),
17898
- ...s
17936
+ ...a
17899
17937
  });
17900
- if (f.status === 403 && sessionStorage.removeItem(storageKey("polymorph.csrf", a)), !f.ok) throw Error(await f.text() || "Failed to start session");
17901
- let m = await f.json();
17902
- p({
17903
- token: m.token,
17904
- livekitUrl: m.livekit_url
17905
- }), m.id && m.join_token && t.onSessionStart?.({
17906
- roomId: m.id,
17907
- joinToken: m.join_token
17938
+ if (f.status === 403 && sessionStorage.removeItem(storageKey("polymorph.csrf", c)), !f.ok) throw Error(await f.text() || "Failed to start session");
17939
+ let p = await f.json();
17940
+ m({
17941
+ token: p.token,
17942
+ livekitUrl: p.livekit_url
17943
+ }), p.id && p.join_token && t.onSessionStart?.({
17944
+ roomId: p.id,
17945
+ joinToken: p.join_token
17908
17946
  });
17909
17947
  } catch (t) {
17910
- V(t instanceof Error ? t.message : "Something went wrong"), l("error");
17948
+ R(t instanceof Error ? t.message : "Something went wrong"), f("error");
17911
17949
  }
17912
17950
  }
17913
17951
  }, [
17914
17952
  t,
17915
- c,
17916
- K,
17953
+ l,
17917
17954
  H,
17955
+ V,
17918
17956
  n,
17919
- a
17957
+ c
17920
17958
  ]);
17921
- return {
17922
- status: c,
17923
- roomConnection: f,
17924
- messages: m,
17925
- isVoiceEnabled: v,
17926
- isMicActive: b,
17927
- isScreenSharing: S,
17928
- hasObserver: w,
17929
- hasUnread: O,
17930
- wiggleKey: R,
17931
- error: Kg,
17932
- needsIdentityForm: Qg,
17933
- identityCollection: Z,
17934
- resolvedConfig: H,
17935
- connect: Q,
17936
- disconnect: useCallback(() => {
17937
- X.current?.disconnect(), X.current = null, p(null), l("idle"), y(!1), x(!1), C(!1), E(!1);
17938
- }, []),
17939
- addMessage: e_,
17940
- sendMessage: useCallback((t) => {
17941
- if (!t.trim()) return;
17942
- let n = t.trim();
17943
- e_("user", n, "chat");
17944
- let i = X.current;
17945
- if (i) {
17946
- let t = new TextEncoder().encode(JSON.stringify({ text: n }));
17947
- i.localParticipant.publishData(t, {
17948
- reliable: !0,
17949
- topic: "chat_message"
17950
- });
17951
- } else Yg.current.push(n), Q();
17952
- }, [e_, Q]),
17953
- toggleMic: useCallback(async () => {
17954
- let t = X.current;
17955
- if (t) try {
17956
- let n = !t.localParticipant.isMicrophoneEnabled;
17957
- await t.localParticipant.setMicrophoneEnabled(n), x(n);
17958
- } catch {}
17959
- }, []),
17960
- toggleVoice: useCallback(async () => {
17961
- let t = X.current;
17962
- if (!t) {
17963
- y(!0), x(!0), await Q();
17964
- return;
17959
+ useEffect(() => {
17960
+ V?.alwaysOn && l === "idle" && Z();
17961
+ }, [
17962
+ V?.alwaysOn,
17963
+ l,
17964
+ Z
17965
+ ]);
17966
+ let e_ = useCallback(() => {
17967
+ K.current?.disconnect(), K.current = null, m(null), f("idle"), b(!1), S(!1), w(!1), O(!1);
17968
+ }, []), t_ = useCallback((t) => {
17969
+ if (!t.trim()) return;
17970
+ let n = t.trim();
17971
+ Zg("user", n, "chat");
17972
+ let i = K.current;
17973
+ if (i) {
17974
+ let t = new TextEncoder().encode(JSON.stringify({ text: n }));
17975
+ i.localParticipant.publishData(t, {
17976
+ reliable: !0,
17977
+ topic: "chat_message"
17978
+ });
17979
+ } else Bg.current.push(n), Z();
17980
+ }, [Zg, Z]), n_ = useCallback(async () => {
17981
+ let t = K.current;
17982
+ if (t) try {
17983
+ let n = !t.localParticipant.isMicrophoneEnabled;
17984
+ await t.localParticipant.setMicrophoneEnabled(n), S(n);
17985
+ } catch (t) {
17986
+ t instanceof DOMException && t.name === "NotAllowedError" && R("Microphone access denied. Please allow mic access in your browser settings.");
17987
+ }
17988
+ }, []), r_ = useCallback(async () => {
17989
+ let t = K.current;
17990
+ if (!t) {
17991
+ b(!0), S(!0), await Z();
17992
+ return;
17993
+ }
17994
+ try {
17995
+ let n = !y;
17996
+ await t.localParticipant.setMicrophoneEnabled(n), b(n), S(n);
17997
+ let i = new TextEncoder().encode(JSON.stringify({ voice_enabled: n }));
17998
+ t.localParticipant.publishData(i, {
17999
+ reliable: !0,
18000
+ topic: "voice_mode"
18001
+ });
18002
+ } catch (t) {
18003
+ t instanceof DOMException && t.name === "NotAllowedError" && (R("Microphone access denied. Please allow mic access in your browser settings."), b(!1), S(!1));
18004
+ }
18005
+ }, [y, Z]), i_ = useCallback(async () => {
18006
+ let t = K.current;
18007
+ if (t) try {
18008
+ let n = !t.localParticipant.isScreenShareEnabled;
18009
+ await t.localParticipant.setScreenShareEnabled(n), w(n);
18010
+ } catch {}
18011
+ }, []), Q = useCallback((t, n) => {
18012
+ let i = {
18013
+ type: t,
18014
+ payload: n,
18015
+ url: typeof window < "u" ? window.location.href : void 0,
18016
+ timestamp: Date.now()
18017
+ }, a = K.current;
18018
+ if (a) {
18019
+ let t = new TextEncoder().encode(JSON.stringify(i));
18020
+ a.localParticipant.publishData(t, {
18021
+ reliable: !0,
18022
+ topic: "widget_event"
18023
+ });
18024
+ } else Vg.current.push(i);
18025
+ }, []);
18026
+ return useEffect(() => {
18027
+ a && Q("page_view", { referrer: typeof document < "u" ? document.referrer : "" });
18028
+ }, [a, Q]), useEffect(() => {
18029
+ if (!a) return;
18030
+ let t, n = () => {
18031
+ clearTimeout(t), t = setTimeout(() => Q("idle"), 3e4);
18032
+ }, i = [
18033
+ "mousemove",
18034
+ "keydown",
18035
+ "click",
18036
+ "scroll",
18037
+ "touchstart"
18038
+ ];
18039
+ for (let t of i) window.addEventListener(t, n, { passive: !0 });
18040
+ return n(), () => {
18041
+ clearTimeout(t);
18042
+ for (let t of i) window.removeEventListener(t, n);
18043
+ };
18044
+ }, [a, Q]), useEffect(() => {
18045
+ if (!a) return;
18046
+ let t = [], n = (n) => {
18047
+ let i = Date.now();
18048
+ for (t.push({
18049
+ target: n.target,
18050
+ time: i
18051
+ }); t.length > 0 && i - t[0].time > 1e3;) t.shift();
18052
+ if (t.filter((t) => t.target === n.target).length >= 3) {
18053
+ let i = n.target;
18054
+ Q("rage_click", {
18055
+ element: i?.tagName?.toLowerCase(),
18056
+ text: i?.textContent?.slice(0, 100)
18057
+ }), t.length = 0;
17965
18058
  }
17966
- try {
17967
- let n = !v;
17968
- await t.localParticipant.setMicrophoneEnabled(n), y(n), x(n);
17969
- let i = new TextEncoder().encode(JSON.stringify({ voice_enabled: n }));
17970
- t.localParticipant.publishData(i, {
17971
- reliable: !0,
17972
- topic: "voice_mode"
17973
- });
17974
- } catch {}
17975
- }, [v, Q]),
17976
- toggleScreenShare: useCallback(async () => {
17977
- let t = X.current;
17978
- if (t) try {
17979
- let n = !t.localParticipant.isScreenShareEnabled;
17980
- await t.localParticipant.setScreenShareEnabled(n), C(n);
17981
- } catch {}
17982
- }, []),
18059
+ };
18060
+ return window.addEventListener("click", n), () => window.removeEventListener("click", n);
18061
+ }, [a, Q]), {
18062
+ status: l,
18063
+ roomConnection: p,
18064
+ messages: g,
18065
+ isVoiceEnabled: y,
18066
+ isMicActive: x,
18067
+ isScreenSharing: C,
18068
+ hasObserver: E,
18069
+ hasUnread: Mg,
18070
+ wiggleKey: Ng,
18071
+ error: Fg,
18072
+ needsIdentityForm: Gg,
18073
+ identityCollection: Wg,
18074
+ resolvedConfig: V,
18075
+ connect: Z,
18076
+ disconnect: e_,
18077
+ addMessage: Zg,
18078
+ sendMessage: t_,
18079
+ toggleMic: n_,
18080
+ toggleVoice: r_,
18081
+ toggleScreenShare: i_,
17983
18082
  setRoom: useCallback((t) => {
17984
- if (X.current = t, t) {
17985
- l("connected");
18083
+ if (K.current = t, t) {
18084
+ f("connected");
17986
18085
  let n = () => {
17987
- E(Array.from(t.remoteParticipants.values()).some((t) => t.kind !== ParticipantInfo_Kind.AGENT));
18086
+ O(Array.from(t.remoteParticipants.values()).some((t) => t.kind !== ParticipantInfo_Kind.AGENT));
17988
18087
  };
17989
18088
  n(), t.on(RoomEvent.ParticipantConnected, n), t.on(RoomEvent.ParticipantDisconnected, n);
17990
- let i = Yg.current.splice(0);
17991
- if (i.length > 0) {
17992
- let n = !1, a = () => {
18089
+ let i = Vg.current.splice(0);
18090
+ for (let n of i) {
18091
+ let i = new TextEncoder().encode(JSON.stringify(n));
18092
+ t.localParticipant.publishData(i, {
18093
+ reliable: !0,
18094
+ topic: "widget_event"
18095
+ });
18096
+ }
18097
+ let a = Bg.current.splice(0);
18098
+ if (a.length > 0) {
18099
+ let n = !1, i = () => {
17993
18100
  if (!n) {
17994
18101
  n = !0;
17995
- for (let n of i) {
18102
+ for (let n of a) {
17996
18103
  let i = new TextEncoder().encode(JSON.stringify({ text: n }));
17997
18104
  t.localParticipant.publishData(i, {
17998
18105
  reliable: !0,
@@ -18001,21 +18108,25 @@ function usePolymorphSession(t) {
18001
18108
  }
18002
18109
  }
18003
18110
  };
18004
- if (t.remoteParticipants.size > 0) setTimeout(a, 500);
18111
+ if (t.remoteParticipants.size > 0) setTimeout(i, 500);
18005
18112
  else {
18006
18113
  let n = () => {
18007
- t.off(RoomEvent.ParticipantConnected, n), setTimeout(a, 500);
18114
+ t.off(RoomEvent.ParticipantConnected, n), setTimeout(i, 500);
18008
18115
  };
18009
18116
  t.on(RoomEvent.ParticipantConnected, n), setTimeout(() => {
18010
- t.off(RoomEvent.ParticipantConnected, n), a();
18117
+ t.off(RoomEvent.ParticipantConnected, n), i();
18011
18118
  }, 5e3);
18012
18119
  }
18013
18120
  }
18014
18121
  }
18015
18122
  }, []),
18016
- setUser: $g,
18017
- clearUnread: t_,
18018
- setPanelOpen: n_
18123
+ setUser: Kg,
18124
+ clearUnread: Qg,
18125
+ setPanelOpen: $g,
18126
+ emitEvent: Q,
18127
+ setError: R,
18128
+ needsTermsAcceptance: Jg,
18129
+ acceptTerms: qg
18019
18130
  };
18020
18131
  }
18021
18132
  function ChatThread({ messages: t, primaryColor: n, status: a }) {
@@ -18064,42 +18175,44 @@ function ChatThread({ messages: t, primaryColor: n, status: a }) {
18064
18175
  });
18065
18176
  }
18066
18177
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[a-zA-Z]{2,}$/, PHONE_DIGITS_RE = /\d/g;
18067
- function IdentityForm({ collectEmail: t, collectPhone: n, primaryColor: a, onSubmit: s }) {
18068
- let [c, l] = useState(""), [u, f] = useState(""), [g, v] = useState(""), [y, b] = useState({}), x = useCallback(() => {
18178
+ function IdentityForm({ collectEmail: t, collectPhone: n, primaryColor: a, onSubmit: s, enableTermsAndConditions: c, termsAndConditionsText: l }) {
18179
+ let [u, f] = useState(""), [g, v] = useState(""), [y, b] = useState(""), [x, S] = useState(!1), [C, w] = useState({}), E = useCallback(() => {
18069
18180
  let i = {};
18070
- if (c.trim() || (i.name = "Name is required"), t === "required" && !u.trim() && (i.email = "Email is required"), u.trim() && !EMAIL_RE.test(u.trim()) && (i.email = "Invalid email format"), n === "required" && !g.trim() && (i.phone = "Phone is required"), g.trim()) {
18071
- let t = (g.trim().match(PHONE_DIGITS_RE) || []).length;
18181
+ if (u.trim() || (i.name = "Name is required"), t === "required" && !g.trim() && (i.email = "Email is required"), g.trim() && !EMAIL_RE.test(g.trim()) && (i.email = "Invalid email format"), n === "required" && !y.trim() && (i.phone = "Phone is required"), y.trim()) {
18182
+ let t = (y.trim().match(PHONE_DIGITS_RE) || []).length;
18072
18183
  (t < 7 || t > 15) && (i.phone = "Enter a valid phone number (7–15 digits)");
18073
18184
  }
18074
- return t === "optional" && n === "optional" && !u.trim() && !g.trim() && (i.contact = "Please provide either an email or phone number"), i;
18185
+ return t === "optional" && n === "optional" && !g.trim() && !y.trim() && (i.contact = "Please provide either an email or phone number"), c && !x && (i.terms = "You must accept the terms and conditions"), i;
18075
18186
  }, [
18076
- c,
18077
18187
  u,
18078
18188
  g,
18189
+ y,
18079
18190
  t,
18080
- n
18081
- ]), S = useCallback((t) => {
18191
+ n,
18192
+ c,
18193
+ x
18194
+ ]), O = useCallback((t) => {
18082
18195
  t.preventDefault();
18083
- let n = x();
18196
+ let n = E();
18084
18197
  if (Object.keys(n).length > 0) {
18085
- b(n);
18198
+ w(n);
18086
18199
  return;
18087
18200
  }
18088
18201
  s({
18089
- name: c.trim(),
18090
- ...u.trim() && { email: u.trim() },
18091
- ...g.trim() && { phone: g.trim() }
18202
+ name: u.trim(),
18203
+ ...g.trim() && { email: g.trim() },
18204
+ ...y.trim() && { phone: y.trim() }
18092
18205
  });
18093
18206
  }, [
18094
- x,
18207
+ E,
18095
18208
  s,
18096
- c,
18097
18209
  u,
18098
- g
18210
+ g,
18211
+ y
18099
18212
  ]);
18100
18213
  return /* @__PURE__ */ jsxs("form", {
18101
18214
  className: styles_module_default.identityForm,
18102
- onSubmit: S,
18215
+ onSubmit: O,
18103
18216
  children: [
18104
18217
  /* @__PURE__ */ jsxs("label", {
18105
18218
  className: styles_module_default.formField,
@@ -18114,13 +18227,13 @@ function IdentityForm({ collectEmail: t, collectPhone: n, primaryColor: a, onSub
18114
18227
  /* @__PURE__ */ jsx("input", {
18115
18228
  className: styles_module_default.formInput,
18116
18229
  type: "text",
18117
- value: c,
18118
- onChange: (t) => l(t.target.value),
18230
+ value: u,
18231
+ onChange: (t) => f(t.target.value),
18119
18232
  placeholder: "Your name"
18120
18233
  }),
18121
- y.name && /* @__PURE__ */ jsx("div", {
18234
+ C.name && /* @__PURE__ */ jsx("div", {
18122
18235
  className: styles_module_default.formError,
18123
- children: y.name
18236
+ children: C.name
18124
18237
  })
18125
18238
  ]
18126
18239
  }),
@@ -18141,13 +18254,13 @@ function IdentityForm({ collectEmail: t, collectPhone: n, primaryColor: a, onSub
18141
18254
  /* @__PURE__ */ jsx("input", {
18142
18255
  className: styles_module_default.formInput,
18143
18256
  type: "email",
18144
- value: u,
18145
- onChange: (t) => f(t.target.value),
18257
+ value: g,
18258
+ onChange: (t) => v(t.target.value),
18146
18259
  placeholder: "you@example.com"
18147
18260
  }),
18148
- y.email && /* @__PURE__ */ jsx("div", {
18261
+ C.email && /* @__PURE__ */ jsx("div", {
18149
18262
  className: styles_module_default.formError,
18150
- children: y.email
18263
+ children: C.email
18151
18264
  })
18152
18265
  ]
18153
18266
  }),
@@ -18168,19 +18281,31 @@ function IdentityForm({ collectEmail: t, collectPhone: n, primaryColor: a, onSub
18168
18281
  /* @__PURE__ */ jsx("input", {
18169
18282
  className: styles_module_default.formInput,
18170
18283
  type: "tel",
18171
- value: g,
18172
- onChange: (t) => v(t.target.value),
18284
+ value: y,
18285
+ onChange: (t) => b(t.target.value),
18173
18286
  placeholder: "+1 (555) 123-4567"
18174
18287
  }),
18175
- y.phone && /* @__PURE__ */ jsx("div", {
18288
+ C.phone && /* @__PURE__ */ jsx("div", {
18176
18289
  className: styles_module_default.formError,
18177
- children: y.phone
18290
+ children: C.phone
18178
18291
  })
18179
18292
  ]
18180
18293
  }),
18181
- y.contact && /* @__PURE__ */ jsx("div", {
18294
+ C.contact && /* @__PURE__ */ jsx("div", {
18295
+ className: styles_module_default.formError,
18296
+ children: C.contact
18297
+ }),
18298
+ c && /* @__PURE__ */ jsxs("label", {
18299
+ className: styles_module_default.termsLabel,
18300
+ children: [/* @__PURE__ */ jsx("input", {
18301
+ type: "checkbox",
18302
+ checked: x,
18303
+ onChange: (t) => S(t.target.checked)
18304
+ }), /* @__PURE__ */ jsx("span", { children: l })]
18305
+ }),
18306
+ C.terms && /* @__PURE__ */ jsx("div", {
18182
18307
  className: styles_module_default.formError,
18183
- children: y.contact
18308
+ children: C.terms
18184
18309
  }),
18185
18310
  /* @__PURE__ */ jsx("button", {
18186
18311
  type: "submit",
@@ -18447,7 +18572,11 @@ function WidgetPanel({ session: t, onClose: n, hidden: a }) {
18447
18572
  collectEmail: t.identityCollection.collectEmail,
18448
18573
  collectPhone: t.identityCollection.collectPhone,
18449
18574
  primaryColor: v,
18450
- onSubmit: t.setUser
18575
+ onSubmit: (n) => {
18576
+ t.setUser(n), g?.enableTermsAndConditions && t.acceptTerms();
18577
+ },
18578
+ enableTermsAndConditions: g?.enableTermsAndConditions,
18579
+ termsAndConditionsText: g?.termsAndConditionsText
18451
18580
  }) : /* @__PURE__ */ jsxs(Fragment, { children: [
18452
18581
  /* @__PURE__ */ jsx(ChatThread, {
18453
18582
  messages: t.messages,
@@ -18467,6 +18596,18 @@ function WidgetPanel({ session: t, onClose: n, hidden: a }) {
18467
18596
  className: styles_module_default.errorText,
18468
18597
  children: t.error
18469
18598
  }),
18599
+ t.needsTermsAcceptance && g?.termsAndConditionsText && /* @__PURE__ */ jsx("div", {
18600
+ className: styles_module_default.termsBar,
18601
+ children: /* @__PURE__ */ jsxs("label", {
18602
+ className: styles_module_default.termsLabel,
18603
+ children: [/* @__PURE__ */ jsx("input", {
18604
+ type: "checkbox",
18605
+ onChange: (n) => {
18606
+ n.target.checked && t.acceptTerms();
18607
+ }
18608
+ }), /* @__PURE__ */ jsx("span", { children: g.termsAndConditionsText })]
18609
+ })
18610
+ }),
18470
18611
  /* @__PURE__ */ jsxs("div", {
18471
18612
  className: styles_module_default.inputBar,
18472
18613
  children: [
@@ -18478,14 +18619,14 @@ function WidgetPanel({ session: t, onClose: n, hidden: a }) {
18478
18619
  onChange: (t) => c(t.target.value),
18479
18620
  onInput: S,
18480
18621
  onKeyDown: x,
18481
- disabled: t.status === "connecting",
18622
+ disabled: t.status === "connecting" || t.needsTermsAcceptance,
18482
18623
  rows: 1
18483
18624
  }),
18484
18625
  /* @__PURE__ */ jsx("button", {
18485
18626
  type: "button",
18486
18627
  className: styles_module_default.iconButton,
18487
18628
  onClick: b,
18488
- disabled: !s.trim() || t.status === "connecting",
18629
+ disabled: !s.trim() || t.status === "connecting" || t.needsTermsAcceptance,
18489
18630
  children: /* @__PURE__ */ jsx(SendIcon, {})
18490
18631
  }),
18491
18632
  t.isVoiceEnabled && y && t.status === "connected" && /* @__PURE__ */ jsx("button", {
@@ -18533,57 +18674,60 @@ function FabCloseIcon() {
18533
18674
  });
18534
18675
  }
18535
18676
  function PolymorphWidget(t) {
18536
- let [n, i] = useState(!1), a = usePolymorphSession(t), c = a.resolvedConfig, f = c?.primaryColor || "#171717", g = c?.position || "bottom-right", v = c?.darkMode ?? !1, y = buildWidgetTheme(f), { hasUnread: b, clearUnread: x, setPanelOpen: S } = a, C = useRef(null);
18677
+ let [n, a] = useState(!1), c = usePolymorphSession(t), f = c.resolvedConfig, g = f?.primaryColor || "#171717", v = f?.position || "bottom-right", y = f?.darkMode ?? !1, b = buildWidgetTheme(g), { hasUnread: x, clearUnread: S, setPanelOpen: C } = c, w = useRef(null);
18537
18678
  useEffect(() => {
18538
- let t = () => a.disconnect();
18679
+ let t = () => c.disconnect();
18539
18680
  return window.addEventListener("beforeunload", t), () => {
18540
- window.removeEventListener("beforeunload", t), a.disconnect();
18681
+ window.removeEventListener("beforeunload", t), c.disconnect();
18541
18682
  };
18542
- }, [a.disconnect]);
18543
- let w = useMemo(() => a.isVoiceEnabled ? {
18683
+ }, [c.disconnect]);
18684
+ let E = useCallback((t) => {
18685
+ t === MediaDeviceFailure.PermissionDenied && c.setError("Microphone access denied. Please allow mic access in your browser settings.");
18686
+ }, [c.setError]), O = useMemo(() => c.isVoiceEnabled ? {
18544
18687
  echoCancellation: !0,
18545
18688
  noiseSuppression: !0,
18546
18689
  autoGainControl: !0
18547
- } : !1, [a.isVoiceEnabled]);
18690
+ } : !1, [c.isVoiceEnabled]);
18548
18691
  return /* @__PURE__ */ jsx("div", {
18549
- ref: C,
18550
- className: `polymorph-widget ${styles_module_default.widgetRoot} ${g === "bottom-left" ? styles_module_default.bottomLeft : styles_module_default.bottomRight}`,
18551
- style: { colorScheme: v ? "dark" : "light" },
18692
+ ref: w,
18693
+ className: `polymorph-widget ${styles_module_default.widgetRoot} ${v === "bottom-left" ? styles_module_default.bottomLeft : styles_module_default.bottomRight}`,
18694
+ style: { colorScheme: y ? "dark" : "light" },
18552
18695
  children: /* @__PURE__ */ jsxs(MantineProvider, {
18553
- theme: y,
18554
- forceColorScheme: v ? "dark" : "light",
18696
+ theme: b,
18697
+ forceColorScheme: y ? "dark" : "light",
18555
18698
  cssVariablesSelector: ".polymorph-widget",
18556
- getRootElement: () => C.current ?? void 0,
18699
+ getRootElement: () => w.current ?? void 0,
18557
18700
  children: [
18558
18701
  /* @__PURE__ */ jsx(WidgetPanel, {
18559
- session: a,
18702
+ session: c,
18560
18703
  onClose: () => {
18561
- i(!1), S(!1);
18704
+ a(!1), C(!1);
18562
18705
  },
18563
18706
  hidden: !n
18564
18707
  }),
18565
18708
  /* @__PURE__ */ jsxs("button", {
18566
18709
  type: "button",
18567
- className: `${styles_module_default.fab} ${n ? styles_module_default.fabOpen : ""} ${b && !n ? styles_module_default.fabWiggle : ""}`,
18568
- style: { backgroundColor: f },
18710
+ className: `${styles_module_default.fab} ${n ? styles_module_default.fabOpen : ""} ${x && !n ? styles_module_default.fabWiggle : ""}`,
18711
+ style: { backgroundColor: g },
18569
18712
  onClick: () => {
18570
18713
  let t = !n;
18571
- i(t), S(t), t && x();
18714
+ a(t), C(t), t && S();
18572
18715
  },
18573
- children: [b && !n && /* @__PURE__ */ jsx("span", { className: styles_module_default.notificationDot }), jsx(n ? FabCloseIcon : ChatIcon, {})]
18574
- }, a.wiggleKey),
18575
- a.roomConnection && /* @__PURE__ */ jsx(W, {
18576
- token: a.roomConnection.token,
18577
- serverUrl: a.roomConnection.livekitUrl,
18716
+ children: [x && !n && /* @__PURE__ */ jsx("span", { className: styles_module_default.notificationDot }), jsx(n ? FabCloseIcon : ChatIcon, {})]
18717
+ }, c.wiggleKey),
18718
+ c.roomConnection && /* @__PURE__ */ jsx(W, {
18719
+ token: c.roomConnection.token,
18720
+ serverUrl: c.roomConnection.livekitUrl,
18578
18721
  connect: !0,
18579
- audio: w,
18722
+ audio: O,
18580
18723
  video: !1,
18581
18724
  style: { display: "none" },
18582
- onDisconnected: a.disconnect,
18725
+ onDisconnected: c.disconnect,
18726
+ onMediaDeviceFailure: E,
18583
18727
  children: /* @__PURE__ */ jsx(RoomHandler, {
18584
- setRoom: a.setRoom,
18585
- addMessage: a.addMessage,
18586
- isVoiceEnabled: a.isVoiceEnabled
18728
+ setRoom: c.setRoom,
18729
+ addMessage: c.addMessage,
18730
+ isVoiceEnabled: c.isVoiceEnabled
18587
18731
  })
18588
18732
  })
18589
18733
  ]