@skippr/live-agent-sdk 0.72.0 → 0.74.0

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.
@@ -50,6 +50,28 @@ function useAgentCursor() {
50
50
 
51
51
  // src/context/LiveAgentContext.tsx
52
52
  import { createContext } from "react";
53
+
54
+ // src/lib/constants.ts
55
+ var SIDEBAR_WIDTH = 280;
56
+ var CAPTURE_MODE = {
57
+ Screenshare: "screenshare",
58
+ Auto: "auto"
59
+ };
60
+ var DEFAULT_CAPTURE_MODE = CAPTURE_MODE.Auto;
61
+ var WIDGET_ROOT_ID = "skippr-sdk-root";
62
+ var REF_ATTR = "data-skippr-ref";
63
+ var PRIVATE_ATTR = "data-skippr-private";
64
+ var DOM_SNAPSHOT_TOPIC = "skippr.dom-snapshot";
65
+ var DOM_EVENTS_TOPIC = "skippr.dom-events";
66
+ var HIGHLIGHT_TOPIC = "skippr.highlight";
67
+ var PAGE_ACTIONS_TOPIC = "skippr.page-actions";
68
+ var TEXT_MODE_TOPIC = "skippr.text-mode";
69
+ var ACTION_CONTROL_TOPIC = "skippr.action-control";
70
+ var SESSION_HOLD_TOPIC = "skippr.session-hold";
71
+ var PLAN_ATTR = "skippr.action-plan";
72
+ var NAME_MAX_CHARS = 80;
73
+
74
+ // src/context/LiveAgentContext.tsx
53
75
  var LiveAgentContext = createContext(null);
54
76
 
55
77
  // src/hooks/useAdoptionGoals.ts
@@ -415,21 +437,6 @@ function useLiveAgent() {
415
437
  // src/hooks/usePlanUpdates.ts
416
438
  import { useCallback as useCallback4 } from "react";
417
439
 
418
- // src/lib/constants.ts
419
- var SIDEBAR_WIDTH = 280;
420
- var WIDGET_ROOT_ID = "skippr-sdk-root";
421
- var REF_ATTR = "data-skippr-ref";
422
- var PRIVATE_ATTR = "data-skippr-private";
423
- var DOM_SNAPSHOT_TOPIC = "skippr.dom-snapshot";
424
- var DOM_EVENTS_TOPIC = "skippr.dom-events";
425
- var HIGHLIGHT_TOPIC = "skippr.highlight";
426
- var PAGE_ACTIONS_TOPIC = "skippr.page-actions";
427
- var TEXT_MODE_TOPIC = "skippr.text-mode";
428
- var ACTION_CONTROL_TOPIC = "skippr.action-control";
429
- var SESSION_HOLD_TOPIC = "skippr.session-hold";
430
- var PLAN_ATTR = "skippr.action-plan";
431
- var NAME_MAX_CHARS = 80;
432
-
433
440
  // src/hooks/useAgentState.ts
434
441
  import { useRemoteParticipants } from "@livekit/components-react/hooks";
435
442
  import { useEffect as useEffect5, useState as useState5 } from "react";
@@ -536,7 +543,7 @@ async function exchangeForBearerToken(appKey, userToken) {
536
543
  return { token, expiresAt: new Date(expiresAt).getTime() };
537
544
  }
538
545
  function useSession({
539
- captureMode = "screenshare",
546
+ captureMode = DEFAULT_CAPTURE_MODE,
540
547
  authToken,
541
548
  appKey,
542
549
  getUserToken,
@@ -689,7 +696,7 @@ function useSession({
689
696
  setErrorCode(null);
690
697
  onStart?.();
691
698
  let screenStream = null;
692
- if (captureMode === "screenshare") {
699
+ if (captureMode === CAPTURE_MODE.Screenshare) {
693
700
  screenStream = await requestScreenShare();
694
701
  }
695
702
  const enabledControls = {};
@@ -844,6 +851,15 @@ function clampLauncherBottom(px) {
844
851
  const maxBottom = window.innerHeight - LAUNCHER_HEIGHT_PX - VIEWPORT_MARGIN_PX;
845
852
  return Math.round(Math.min(Math.max(px, VIEWPORT_MARGIN_PX), maxBottom));
846
853
  }
854
+ function verticalAlignToBottomPx(align) {
855
+ if (align === "top") {
856
+ return clampLauncherBottom(window.innerHeight - LAUNCHER_HEIGHT_PX - DEFAULT_LAUNCHER_BOTTOM_PX);
857
+ }
858
+ if (align === "middle") {
859
+ return clampLauncherBottom(window.innerHeight / 2 - LAUNCHER_HEIGHT_PX / 2);
860
+ }
861
+ return clampLauncherBottom(DEFAULT_LAUNCHER_BOTTOM_PX);
862
+ }
847
863
  function launcherPopsDown(bottomPx) {
848
864
  return bottomPx + LAUNCHER_HEIGHT_PX / 2 > window.innerHeight / 2;
849
865
  }
@@ -3933,8 +3949,8 @@ function SessionControlBar() {
3933
3949
  }, [isHeld, minimizePanel]);
3934
3950
  const isReady = state === "listening" || state === "thinking" || state === "speaking";
3935
3951
  const { barRefs, isTalking } = useMicLevel(isReady && !isMuted && !textMode && !isHeld);
3936
- const showScreenShareToggle = captureMode === "screenshare";
3937
- const showActionControl = captureMode === "auto" && actionsActive;
3952
+ const showScreenShareToggle = captureMode === CAPTURE_MODE.Screenshare;
3953
+ const showActionControl = captureMode === CAPTURE_MODE.Auto && actionsActive;
3938
3954
  const screenShareExtra = showScreenShareToggle ? SCREEN_SHARE_EXTRA_WIDTH : 0;
3939
3955
  const actionControlExtra = showActionControl ? ACTION_CONTROL_EXTRA_WIDTH : 0;
3940
3956
  let barWidth = STANDBY_BAR_WIDTH;
@@ -5580,6 +5596,14 @@ function SidebarTrigger() {
5580
5596
 
5581
5597
  // src/components/LiveAgent.tsx
5582
5598
  import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
5599
+ function readSavedLauncherBottom() {
5600
+ try {
5601
+ const saved = Number.parseInt(localStorage.getItem("skippr_widget_bottom") ?? "", 10);
5602
+ return Number.isFinite(saved) && saved > 0 ? saved : null;
5603
+ } catch {
5604
+ return null;
5605
+ }
5606
+ }
5583
5607
  function AgentCursorMount({ animated }) {
5584
5608
  return /* @__PURE__ */ jsx22(AgentCursor, {
5585
5609
  target: useAgentCursor(),
@@ -5606,6 +5630,7 @@ function LiveAgent(props) {
5606
5630
  getUserToken,
5607
5631
  userToken,
5608
5632
  position = "right",
5633
+ verticalAlign = "bottom",
5609
5634
  variant = "floating",
5610
5635
  minimizable = true,
5611
5636
  defaultOpen = false,
@@ -5617,10 +5642,10 @@ function LiveAgent(props) {
5617
5642
  animateAgentCursor = false,
5618
5643
  children
5619
5644
  } = props;
5620
- const captureMode = props.captureMode ?? "screenshare";
5645
+ const captureMode = props.captureMode ?? DEFAULT_CAPTURE_MODE;
5621
5646
  let hostAgentControls;
5622
5647
  if ("agentControls" in props && props.agentControls) {
5623
- if (captureMode === "auto") {
5648
+ if (captureMode === CAPTURE_MODE.Auto) {
5624
5649
  hostAgentControls = props.agentControls;
5625
5650
  } else {
5626
5651
  console.warn('[Skippr] agentControls requires captureMode: "auto"');
@@ -5772,16 +5797,13 @@ function LiveAgent(props) {
5772
5797
  localStorage.setItem("skippr_widget_position", pos);
5773
5798
  } catch {}
5774
5799
  }, []);
5775
- const [launcherBottomPx, setLauncherBottomPxState] = useState18(() => {
5776
- try {
5777
- const saved = Number.parseInt(localStorage.getItem("skippr_widget_bottom") ?? "", 10);
5778
- if (Number.isFinite(saved) && saved > 0)
5779
- return clampLauncherBottom(saved);
5780
- } catch {}
5781
- return DEFAULT_LAUNCHER_BOTTOM_PX;
5782
- });
5800
+ const savedLauncherBottom = readSavedLauncherBottom();
5801
+ const hasDraggedRef = useRef17(savedLauncherBottom !== null);
5802
+ const verticalAlignRef = useRef17(verticalAlign);
5803
+ const [launcherBottomPx, setLauncherBottomPxState] = useState18(() => savedLauncherBottom !== null ? clampLauncherBottom(savedLauncherBottom) : verticalAlignToBottomPx(verticalAlign));
5783
5804
  const [popsDown, setPopsDown] = useState18(() => launcherPopsDown(launcherBottomPx));
5784
5805
  const setLauncherBottomPx = useCallback15((px) => {
5806
+ hasDraggedRef.current = true;
5785
5807
  setLauncherBottomPxState(px);
5786
5808
  setPopsDown(launcherPopsDown(px));
5787
5809
  try {
@@ -5796,9 +5818,9 @@ function LiveAgent(props) {
5796
5818
  }, [setPositionWithPersist, setLauncherBottomPx]);
5797
5819
  useEffect25(() => {
5798
5820
  const syncToViewport = () => {
5799
- const clamped = clampLauncherBottom(launcherBottomPxRef.current);
5800
- setLauncherBottomPxState(clamped);
5801
- setPopsDown(launcherPopsDown(clamped));
5821
+ const next = hasDraggedRef.current ? clampLauncherBottom(launcherBottomPxRef.current) : verticalAlignToBottomPx(verticalAlignRef.current);
5822
+ setLauncherBottomPxState(next);
5823
+ setPopsDown(launcherPopsDown(next));
5802
5824
  };
5803
5825
  syncToViewport();
5804
5826
  window.addEventListener("resize", syncToViewport);
@@ -5962,16 +5984,16 @@ function LiveAgent(props) {
5962
5984
  onDisconnected: handleRoomDisconnected,
5963
5985
  children: [
5964
5986
  connection && !textMode && /* @__PURE__ */ jsx22(RoomAudioRenderer, {}),
5965
- connection && captureMode === "screenshare" && /* @__PURE__ */ jsx22(AutoStartMedia, {
5987
+ connection && captureMode === CAPTURE_MODE.Screenshare && /* @__PURE__ */ jsx22(AutoStartMedia, {
5966
5988
  pendingScreenStream
5967
5989
  }),
5968
- connection && captureMode === "auto" && /* @__PURE__ */ jsx22(DomCapture, {}),
5990
+ connection && captureMode === CAPTURE_MODE.Auto && /* @__PURE__ */ jsx22(DomCapture, {}),
5969
5991
  /* @__PURE__ */ jsxs19(ShadowHost, {
5970
5992
  children: [
5971
- connection && captureMode === "auto" && agentControls?.highlight && /* @__PURE__ */ jsx22(HighlightOverlay, {}),
5972
- connection && captureMode === "auto" && agentControls?.actions && /* @__PURE__ */ jsx22(PageActionHandler, {}),
5973
- connection && captureMode === "auto" && agentControls?.actions && /* @__PURE__ */ jsx22(PlanPanelOpener, {}),
5974
- connection && captureMode === "auto" && (agentControls?.highlight || agentControls?.actions) && /* @__PURE__ */ jsx22(AgentCursorMount, {
5993
+ connection && captureMode === CAPTURE_MODE.Auto && agentControls?.highlight && /* @__PURE__ */ jsx22(HighlightOverlay, {}),
5994
+ connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx22(PageActionHandler, {}),
5995
+ connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx22(PlanPanelOpener, {}),
5996
+ connection && captureMode === CAPTURE_MODE.Auto && (agentControls?.highlight || agentControls?.actions) && /* @__PURE__ */ jsx22(AgentCursorMount, {
5975
5997
  animated: shouldAnimateCursor
5976
5998
  }),
5977
5999
  /* @__PURE__ */ jsxs19("div", {