@skippr/live-agent-sdk 0.28.0 → 0.29.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.
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/components/LiveAgent.tsx
10
10
  import { LiveKitRoom, RoomAudioRenderer } from "@livekit/components-react";
11
- import { useCallback as useCallback6, useEffect as useEffect13, useMemo as useMemo5, useRef as useRef7, useState as useState8 } from "react";
11
+ import { useCallback as useCallback7, useEffect as useEffect14, useMemo as useMemo5, useRef as useRef8, useState as useState9 } from "react";
12
12
 
13
13
  // src/context/LiveAgentContext.tsx
14
14
  import { createContext } from "react";
@@ -176,6 +176,7 @@ async function exchangeForBearerToken(appKey, userToken) {
176
176
  function useSession({
177
177
  agentId,
178
178
  captureMode = "screenshare",
179
+ agentControls,
179
180
  authToken,
180
181
  appKey,
181
182
  userToken
@@ -207,6 +208,7 @@ function useSession({
207
208
  stale = true;
208
209
  };
209
210
  }, [authToken, appKey, userToken]);
211
+ const highlightOptIn = agentControls?.highlight;
210
212
  const startSession = useCallback2(async () => {
211
213
  if (!bearerToken) {
212
214
  setError("No auth token available");
@@ -225,13 +227,18 @@ function useSession({
225
227
  screenStream = null;
226
228
  }
227
229
  }
230
+ const requestAgentControls = highlightOptIn === true ? { highlight: true } : undefined;
228
231
  const headers = { Authorization: `Bearer ${bearerToken}` };
229
232
  try {
230
233
  const createResp = await fetch(`${API_URL2}/v1/sessions`, {
231
234
  method: "POST",
232
235
  credentials: "omit",
233
236
  headers: { "Content-Type": "application/json", ...headers },
234
- body: JSON.stringify({ agentId, captureMode })
237
+ body: JSON.stringify({
238
+ agentId,
239
+ captureMode,
240
+ agentControls: requestAgentControls
241
+ })
235
242
  });
236
243
  if (!createResp.ok) {
237
244
  const body = await createResp.json().catch(() => null);
@@ -266,7 +273,7 @@ function useSession({
266
273
  } finally {
267
274
  setIsStarting(false);
268
275
  }
269
- }, [agentId, captureMode, bearerToken]);
276
+ }, [agentId, captureMode, highlightOptIn, bearerToken]);
270
277
  const disconnect = useCallback2(async () => {
271
278
  if (sessionId && bearerToken) {
272
279
  try {
@@ -307,6 +314,7 @@ var REF_ATTR = "data-skippr-ref";
307
314
  var PRIVATE_ATTR = "data-skippr-private";
308
315
  var DOM_SNAPSHOT_TOPIC = "skippr.dom-snapshot";
309
316
  var DOM_EVENTS_TOPIC = "skippr.dom-events";
317
+ var HIGHLIGHT_TOPIC = "skippr.highlight";
310
318
  var NAME_MAX_CHARS = 80;
311
319
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/createLucideIcon.js
312
320
  import { forwardRef as forwardRef2, createElement as createElement3 } from "react";
@@ -1581,8 +1589,260 @@ function DomCapture() {
1581
1589
  return null;
1582
1590
  }
1583
1591
 
1592
+ // src/components/HighlightOverlay.tsx
1593
+ import { useDataChannel } from "@livekit/components-react/hooks";
1594
+ import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef3, useState as useState3 } from "react";
1595
+ import { jsx as jsx2, jsxs as jsxs2, Fragment as Fragment2 } from "react/jsx-runtime";
1596
+ var TOOLTIP_MAX_WIDTH = 280;
1597
+ var TOOLTIP_GAP = 8;
1598
+ var VIEWPORT_MARGIN = 8;
1599
+ var TOOLTIP_TOP_THRESHOLD = 48;
1600
+ var Z_INDEX = 2147483646;
1601
+ var RING_INNER = "oklab(0.585 0.0288678 -0.231205 / 0.95)";
1602
+ var RING_OUTER = "oklab(0.585 0.0288678 -0.231205 / 0.25)";
1603
+ var textDecoder = new TextDecoder;
1604
+ function parseHighlightMessage(payload) {
1605
+ try {
1606
+ const json = JSON.parse(textDecoder.decode(payload));
1607
+ if (!json || typeof json !== "object")
1608
+ return null;
1609
+ if (json.type === "show" && typeof json.ref === "string") {
1610
+ return {
1611
+ type: "show",
1612
+ ref: json.ref,
1613
+ message: typeof json.message === "string" ? json.message : ""
1614
+ };
1615
+ }
1616
+ if (json.type === "clear")
1617
+ return { type: "clear" };
1618
+ return null;
1619
+ } catch {
1620
+ return null;
1621
+ }
1622
+ }
1623
+ function safeGetIframeDocument(iframe) {
1624
+ try {
1625
+ return iframe.contentDocument;
1626
+ } catch {
1627
+ return null;
1628
+ }
1629
+ }
1630
+ function safeQuerySelector(doc, selector) {
1631
+ try {
1632
+ return doc.querySelector(selector);
1633
+ } catch {
1634
+ return null;
1635
+ }
1636
+ }
1637
+ function safeQueryAllIframes(doc) {
1638
+ try {
1639
+ return Array.from(doc.querySelectorAll("iframe"));
1640
+ } catch {
1641
+ return [];
1642
+ }
1643
+ }
1644
+ function findElementInDocumentTree(rootDoc, selector) {
1645
+ const hit = safeQuerySelector(rootDoc, selector);
1646
+ if (hit)
1647
+ return hit;
1648
+ for (const iframe of safeQueryAllIframes(rootDoc)) {
1649
+ const innerDoc = safeGetIframeDocument(iframe);
1650
+ if (!innerDoc)
1651
+ continue;
1652
+ const nested = findElementInDocumentTree(innerDoc, selector);
1653
+ if (nested)
1654
+ return nested;
1655
+ }
1656
+ return null;
1657
+ }
1658
+ function findElementByRef(ref) {
1659
+ const selector = `[${REF_ATTR}="${CSS.escape(ref)}"]`;
1660
+ return findElementInDocumentTree(document, selector);
1661
+ }
1662
+ function findIframeHostingDocument(targetDoc) {
1663
+ const queue = [document];
1664
+ while (queue.length > 0) {
1665
+ const doc = queue.shift();
1666
+ if (!doc)
1667
+ continue;
1668
+ for (const iframe of safeQueryAllIframes(doc)) {
1669
+ if (safeGetIframeDocument(iframe) === targetDoc)
1670
+ return iframe;
1671
+ const innerDoc = safeGetIframeDocument(iframe);
1672
+ if (innerDoc)
1673
+ queue.push(innerDoc);
1674
+ }
1675
+ }
1676
+ return null;
1677
+ }
1678
+ function getRectInTopViewport(el) {
1679
+ let rect = el.getBoundingClientRect();
1680
+ let ownerDoc = el.ownerDocument;
1681
+ while (ownerDoc && ownerDoc !== document) {
1682
+ const hostingIframe = findIframeHostingDocument(ownerDoc);
1683
+ if (!hostingIframe)
1684
+ return rect;
1685
+ const iframeRect = hostingIframe.getBoundingClientRect();
1686
+ rect = new DOMRect(rect.left + iframeRect.left, rect.top + iframeRect.top, rect.width, rect.height);
1687
+ ownerDoc = hostingIframe.ownerDocument;
1688
+ }
1689
+ return rect;
1690
+ }
1691
+ function findScrollableAncestor(el) {
1692
+ const win = el.ownerDocument?.defaultView ?? window;
1693
+ let node = el.parentElement;
1694
+ while (node) {
1695
+ const overflow = win.getComputedStyle(node).overflow;
1696
+ if (/auto|scroll|overlay/.test(overflow))
1697
+ return node;
1698
+ node = node.parentElement;
1699
+ }
1700
+ return el.ownerDocument?.documentElement ?? document.documentElement;
1701
+ }
1702
+ function HighlightOverlay() {
1703
+ const [overlayState, setOverlayState] = useState3(null);
1704
+ const targetElementRef = useRef3(null);
1705
+ const pendingFrameRef = useRef3(null);
1706
+ const clearOverlay = useCallback4(() => {
1707
+ targetElementRef.current = null;
1708
+ setOverlayState(null);
1709
+ }, []);
1710
+ const recomputeRect = useCallback4(() => {
1711
+ pendingFrameRef.current = null;
1712
+ const target = targetElementRef.current;
1713
+ if (!target)
1714
+ return;
1715
+ if (!target.isConnected) {
1716
+ clearOverlay();
1717
+ return;
1718
+ }
1719
+ const rect2 = getRectInTopViewport(target);
1720
+ setOverlayState((prev) => prev ? { ...prev, rect: rect2 } : prev);
1721
+ }, [clearOverlay]);
1722
+ const scheduleRecompute = useCallback4(() => {
1723
+ if (pendingFrameRef.current !== null)
1724
+ return;
1725
+ pendingFrameRef.current = window.requestAnimationFrame(recomputeRect);
1726
+ }, [recomputeRect]);
1727
+ const onHighlightMessage = useCallback4((msg) => {
1728
+ const parsed = parseHighlightMessage(msg.payload);
1729
+ if (!parsed)
1730
+ return;
1731
+ if (parsed.type === "clear") {
1732
+ clearOverlay();
1733
+ return;
1734
+ }
1735
+ const target = findElementByRef(parsed.ref);
1736
+ if (!target) {
1737
+ clearOverlay();
1738
+ return;
1739
+ }
1740
+ targetElementRef.current = target;
1741
+ setOverlayState({
1742
+ ref: parsed.ref,
1743
+ message: parsed.message ?? "",
1744
+ rect: getRectInTopViewport(target)
1745
+ });
1746
+ }, [clearOverlay]);
1747
+ useDataChannel(HIGHLIGHT_TOPIC, onHighlightMessage);
1748
+ useEffect5(() => {
1749
+ if (!overlayState)
1750
+ return;
1751
+ const target = targetElementRef.current;
1752
+ if (!target)
1753
+ return;
1754
+ const onScroll = () => scheduleRecompute();
1755
+ const onResize = () => scheduleRecompute();
1756
+ const watchedWindows = new Set;
1757
+ watchedWindows.add(window);
1758
+ const ownerWindow = target.ownerDocument?.defaultView;
1759
+ if (ownerWindow && ownerWindow !== window)
1760
+ watchedWindows.add(ownerWindow);
1761
+ for (const win of watchedWindows) {
1762
+ win.addEventListener("scroll", onScroll, { capture: true, passive: true });
1763
+ win.addEventListener("resize", onResize, { passive: true });
1764
+ }
1765
+ const resizeObserver = new ResizeObserver(scheduleRecompute);
1766
+ resizeObserver.observe(target);
1767
+ const scrollContainer = findScrollableAncestor(target);
1768
+ const mutationObserver = new MutationObserver(() => {
1769
+ if (!targetElementRef.current?.isConnected) {
1770
+ clearOverlay();
1771
+ return;
1772
+ }
1773
+ scheduleRecompute();
1774
+ });
1775
+ mutationObserver.observe(scrollContainer, { childList: true, subtree: true });
1776
+ return () => {
1777
+ for (const win of watchedWindows) {
1778
+ win.removeEventListener("scroll", onScroll, { capture: true });
1779
+ win.removeEventListener("resize", onResize);
1780
+ }
1781
+ resizeObserver.disconnect();
1782
+ mutationObserver.disconnect();
1783
+ if (pendingFrameRef.current !== null) {
1784
+ window.cancelAnimationFrame(pendingFrameRef.current);
1785
+ pendingFrameRef.current = null;
1786
+ }
1787
+ };
1788
+ }, [overlayState, scheduleRecompute, clearOverlay]);
1789
+ if (!overlayState)
1790
+ return null;
1791
+ const { rect, message } = overlayState;
1792
+ const ringStyle = {
1793
+ position: "fixed",
1794
+ left: `${rect.left}px`,
1795
+ top: `${rect.top}px`,
1796
+ width: `${rect.width}px`,
1797
+ height: `${rect.height}px`,
1798
+ pointerEvents: "none",
1799
+ zIndex: Z_INDEX,
1800
+ boxShadow: `0 0 0 2px ${RING_INNER}, 0 0 0 6px ${RING_OUTER}`,
1801
+ borderRadius: "4px",
1802
+ transition: "none"
1803
+ };
1804
+ const showTooltipBelow = rect.top < TOOLTIP_TOP_THRESHOLD;
1805
+ const tooltipTop = showTooltipBelow ? rect.bottom + TOOLTIP_GAP : rect.top - TOOLTIP_GAP;
1806
+ const tooltipTransform = showTooltipBelow ? "translateY(0)" : "translateY(-100%)";
1807
+ const tooltipLeft = Math.min(Math.max(rect.left, VIEWPORT_MARGIN), window.innerWidth - TOOLTIP_MAX_WIDTH - VIEWPORT_MARGIN);
1808
+ const tooltipStyle = {
1809
+ position: "fixed",
1810
+ left: `${tooltipLeft}px`,
1811
+ top: `${tooltipTop}px`,
1812
+ transform: tooltipTransform,
1813
+ maxWidth: `${TOOLTIP_MAX_WIDTH}px`,
1814
+ pointerEvents: "none",
1815
+ zIndex: Z_INDEX,
1816
+ background: "rgba(45, 43, 61, 0.96)",
1817
+ color: "#ffffff",
1818
+ padding: "6px 10px",
1819
+ borderRadius: "8px",
1820
+ fontSize: "13px",
1821
+ lineHeight: "1.35",
1822
+ fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif',
1823
+ boxShadow: "0 6px 20px rgba(0, 0, 0, 0.25)",
1824
+ whiteSpace: "normal",
1825
+ wordWrap: "break-word"
1826
+ };
1827
+ return /* @__PURE__ */ jsxs2(Fragment2, {
1828
+ children: [
1829
+ /* @__PURE__ */ jsx2("div", {
1830
+ "data-skippr-private": "true",
1831
+ style: ringStyle,
1832
+ "aria-hidden": "true"
1833
+ }),
1834
+ message && /* @__PURE__ */ jsx2("div", {
1835
+ "data-skippr-private": "true",
1836
+ style: tooltipStyle,
1837
+ role: "tooltip",
1838
+ children: message
1839
+ })
1840
+ ]
1841
+ });
1842
+ }
1843
+
1584
1844
  // src/components/MinimizedBubble.tsx
1585
- import { useEffect as useEffect5 } from "react";
1845
+ import { useEffect as useEffect6 } from "react";
1586
1846
 
1587
1847
  // src/lib/utils.ts
1588
1848
  import { clsx } from "clsx";
@@ -1593,12 +1853,12 @@ function cn(...inputs) {
1593
1853
 
1594
1854
  // src/components/Logo.tsx
1595
1855
  import { useId } from "react";
1596
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1856
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1597
1857
  function Logo({ className }) {
1598
1858
  const reactId = useId().replace(/:/g, "");
1599
1859
  const clipId = `skippr-logo-clip-${reactId}`;
1600
1860
  const gradientId = `skippr-logo-gradient-${reactId}`;
1601
- return /* @__PURE__ */ jsxs2("svg", {
1861
+ return /* @__PURE__ */ jsxs3("svg", {
1602
1862
  width: "1em",
1603
1863
  height: "1em",
1604
1864
  viewBox: "0 0 30 30",
@@ -1608,14 +1868,14 @@ function Logo({ className }) {
1608
1868
  "aria-label": "Skippr",
1609
1869
  className,
1610
1870
  children: [
1611
- /* @__PURE__ */ jsxs2("g", {
1871
+ /* @__PURE__ */ jsxs3("g", {
1612
1872
  clipPath: `url(#${clipId})`,
1613
1873
  children: [
1614
- /* @__PURE__ */ jsx2("path", {
1874
+ /* @__PURE__ */ jsx3("path", {
1615
1875
  d: "M0 10C0 4.47715 4.47715 0 10 0H20C25.5228 0 30 4.47715 30 10V20C30 25.5228 25.5228 30 20 30H10C4.47715 30 0 25.5228 0 20V10Z",
1616
1876
  fill: "#2D2D3F"
1617
1877
  }),
1618
- /* @__PURE__ */ jsx2("rect", {
1878
+ /* @__PURE__ */ jsx3("rect", {
1619
1879
  x: "7.83325",
1620
1880
  y: "14.9404",
1621
1881
  width: "12.4083",
@@ -1624,11 +1884,11 @@ function Logo({ className }) {
1624
1884
  transform: "rotate(-45 7.83325 14.9404)",
1625
1885
  fill: "#52FFF9"
1626
1886
  }),
1627
- /* @__PURE__ */ jsx2("path", {
1887
+ /* @__PURE__ */ jsx3("path", {
1628
1888
  d: "M18.8975 12.5928C20.2728 12.5928 21.3877 13.647 21.3877 14.9474C21.3877 16.2479 20.2728 17.3021 18.8975 17.3021L11.4269 17.3021C10.0516 17.3021 8.93665 16.2479 8.93665 14.9474C8.93665 13.647 10.0516 12.5928 11.4269 12.5928L18.8975 12.5928Z",
1629
1889
  fill: `url(#${gradientId})`
1630
1890
  }),
1631
- /* @__PURE__ */ jsx2("rect", {
1891
+ /* @__PURE__ */ jsx3("rect", {
1632
1892
  x: "10.1665",
1633
1893
  y: "20.4404",
1634
1894
  width: "12.4083",
@@ -1639,9 +1899,9 @@ function Logo({ className }) {
1639
1899
  })
1640
1900
  ]
1641
1901
  }),
1642
- /* @__PURE__ */ jsxs2("defs", {
1902
+ /* @__PURE__ */ jsxs3("defs", {
1643
1903
  children: [
1644
- /* @__PURE__ */ jsxs2("linearGradient", {
1904
+ /* @__PURE__ */ jsxs3("linearGradient", {
1645
1905
  id: gradientId,
1646
1906
  x1: "18.9237",
1647
1907
  y1: "16.9997",
@@ -1649,19 +1909,19 @@ function Logo({ className }) {
1649
1909
  y2: "14.1904",
1650
1910
  gradientUnits: "userSpaceOnUse",
1651
1911
  children: [
1652
- /* @__PURE__ */ jsx2("stop", {
1912
+ /* @__PURE__ */ jsx3("stop", {
1653
1913
  offset: "0.473958",
1654
1914
  stopColor: "white"
1655
1915
  }),
1656
- /* @__PURE__ */ jsx2("stop", {
1916
+ /* @__PURE__ */ jsx3("stop", {
1657
1917
  offset: "1",
1658
1918
  stopColor: "#52FFF9"
1659
1919
  })
1660
1920
  ]
1661
1921
  }),
1662
- /* @__PURE__ */ jsx2("clipPath", {
1922
+ /* @__PURE__ */ jsx3("clipPath", {
1663
1923
  id: clipId,
1664
- children: /* @__PURE__ */ jsx2("rect", {
1924
+ children: /* @__PURE__ */ jsx3("rect", {
1665
1925
  width: "30",
1666
1926
  height: "30",
1667
1927
  fill: "white"
@@ -1674,18 +1934,18 @@ function Logo({ className }) {
1674
1934
  }
1675
1935
 
1676
1936
  // src/components/ui/tooltip.tsx
1677
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1937
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1678
1938
  var ALIGN_CLASSES = {
1679
1939
  center: "skippr:left-1/2 skippr:-translate-x-1/2",
1680
1940
  start: "skippr:left-0",
1681
1941
  end: "skippr:right-0"
1682
1942
  };
1683
1943
  function Tooltip({ label, children, position = "top", align = "center" }) {
1684
- return /* @__PURE__ */ jsxs3("span", {
1944
+ return /* @__PURE__ */ jsxs4("span", {
1685
1945
  className: "skippr:relative skippr:inline-flex skippr:group",
1686
1946
  children: [
1687
1947
  children,
1688
- /* @__PURE__ */ jsx3("span", {
1948
+ /* @__PURE__ */ jsx4("span", {
1689
1949
  className: cn("skippr:pointer-events-none skippr:absolute skippr:z-10", "skippr:whitespace-nowrap skippr:rounded-md skippr:bg-foreground skippr:px-2 skippr:py-1", "skippr:text-[11px] skippr:text-background skippr:font-medium", "skippr:opacity-0 skippr:scale-95 skippr:transition-all skippr:duration-150", "skippr:group-hover:opacity-100 skippr:group-hover:scale-100", "skippr:group-focus-within:opacity-100 skippr:group-focus-within:scale-100", ALIGN_CLASSES[align], position === "top" && "skippr:bottom-full skippr:mb-1.5", position === "bottom" && "skippr:top-full skippr:mt-1.5"),
1690
1950
  "aria-hidden": "true",
1691
1951
  children: label
@@ -1695,67 +1955,67 @@ function Tooltip({ label, children, position = "top", align = "center" }) {
1695
1955
  }
1696
1956
 
1697
1957
  // src/components/MinimizedBubble.tsx
1698
- import { jsx as jsx4, jsxs as jsxs4, Fragment as Fragment2 } from "react/jsx-runtime";
1958
+ import { jsx as jsx5, jsxs as jsxs5, Fragment as Fragment3 } from "react/jsx-runtime";
1699
1959
  var BUBBLE_BUTTON = "skippr:flex skippr:size-12 skippr:cursor-pointer skippr:items-center skippr:justify-center skippr:rounded-[14px] skippr:shadow-[0_4px_16px_rgba(45,43,61,0.45),0_2px_4px_rgba(0,0,0,0.1)] skippr:transition-all skippr:hover:-translate-y-0.5 skippr:active:translate-y-0";
1700
1960
  function ConnectedBubbleContent() {
1701
1961
  const { expandPanel, disconnect, position, captureMode } = useLiveAgent();
1702
1962
  const { isMuted, toggleMute, isScreenSharing, toggleScreenShare } = useMediaControls();
1703
1963
  const tooltipAlign = position === "right" ? "end" : "start";
1704
1964
  const showScreenShareToggle = captureMode === "screenshare";
1705
- return /* @__PURE__ */ jsxs4(Fragment2, {
1965
+ return /* @__PURE__ */ jsxs5(Fragment3, {
1706
1966
  children: [
1707
- /* @__PURE__ */ jsx4(Tooltip, {
1967
+ /* @__PURE__ */ jsx5(Tooltip, {
1708
1968
  label: isMuted ? "Unmute" : "Mute",
1709
1969
  align: tooltipAlign,
1710
- children: /* @__PURE__ */ jsx4("button", {
1970
+ children: /* @__PURE__ */ jsx5("button", {
1711
1971
  type: "button",
1712
1972
  onClick: toggleMute,
1713
1973
  "aria-label": isMuted ? "Unmute" : "Mute",
1714
1974
  className: cn(BUBBLE_BUTTON, isMuted ? "skippr:bg-destructive skippr:text-destructive-foreground skippr:hover:bg-destructive/90" : "skippr:bg-white skippr:text-foreground skippr:hover:bg-muted"),
1715
- children: isMuted ? /* @__PURE__ */ jsx4(MicOff, {
1975
+ children: isMuted ? /* @__PURE__ */ jsx5(MicOff, {
1716
1976
  className: "skippr:size-5"
1717
- }) : /* @__PURE__ */ jsx4(Mic, {
1977
+ }) : /* @__PURE__ */ jsx5(Mic, {
1718
1978
  className: "skippr:size-5"
1719
1979
  })
1720
1980
  })
1721
1981
  }),
1722
- showScreenShareToggle && /* @__PURE__ */ jsx4(Tooltip, {
1982
+ showScreenShareToggle && /* @__PURE__ */ jsx5(Tooltip, {
1723
1983
  label: isScreenSharing ? "Stop sharing" : "Share screen",
1724
1984
  align: tooltipAlign,
1725
- children: /* @__PURE__ */ jsx4("button", {
1985
+ children: /* @__PURE__ */ jsx5("button", {
1726
1986
  type: "button",
1727
1987
  onClick: toggleScreenShare,
1728
1988
  "aria-label": isScreenSharing ? "Stop sharing screen" : "Share screen",
1729
1989
  className: cn(BUBBLE_BUTTON, isScreenSharing ? "skippr:bg-bubble skippr:text-white skippr:hover:brightness-110" : "skippr:bg-white skippr:text-foreground skippr:hover:bg-muted"),
1730
- children: isScreenSharing ? /* @__PURE__ */ jsx4(MonitorOff, {
1990
+ children: isScreenSharing ? /* @__PURE__ */ jsx5(MonitorOff, {
1731
1991
  className: "skippr:size-5"
1732
- }) : /* @__PURE__ */ jsx4(Monitor, {
1992
+ }) : /* @__PURE__ */ jsx5(Monitor, {
1733
1993
  className: "skippr:size-5"
1734
1994
  })
1735
1995
  })
1736
1996
  }),
1737
- /* @__PURE__ */ jsx4(Tooltip, {
1997
+ /* @__PURE__ */ jsx5(Tooltip, {
1738
1998
  label: "End session",
1739
1999
  align: tooltipAlign,
1740
- children: /* @__PURE__ */ jsx4("button", {
2000
+ children: /* @__PURE__ */ jsx5("button", {
1741
2001
  type: "button",
1742
2002
  onClick: () => disconnect(),
1743
2003
  "aria-label": "End session",
1744
2004
  className: cn(BUBBLE_BUTTON, "skippr:bg-destructive skippr:text-destructive-foreground skippr:hover:bg-destructive/90"),
1745
- children: /* @__PURE__ */ jsx4(PhoneOff, {
2005
+ children: /* @__PURE__ */ jsx5(PhoneOff, {
1746
2006
  className: "skippr:size-5"
1747
2007
  })
1748
2008
  })
1749
2009
  }),
1750
- /* @__PURE__ */ jsx4(Tooltip, {
2010
+ /* @__PURE__ */ jsx5(Tooltip, {
1751
2011
  label: "Open chat & transcript",
1752
2012
  align: tooltipAlign,
1753
- children: /* @__PURE__ */ jsx4("button", {
2013
+ children: /* @__PURE__ */ jsx5("button", {
1754
2014
  type: "button",
1755
2015
  onClick: expandPanel,
1756
2016
  "aria-label": "Open chat & transcript",
1757
2017
  className: cn(BUBBLE_BUTTON, "skippr:bg-bubble skippr:hover:brightness-110"),
1758
- children: /* @__PURE__ */ jsx4(Logo, {
2018
+ children: /* @__PURE__ */ jsx5(Logo, {
1759
2019
  className: "skippr:size-7"
1760
2020
  })
1761
2021
  })
@@ -1766,19 +2026,19 @@ function ConnectedBubbleContent() {
1766
2026
  function IdleBubbleContent() {
1767
2027
  const { expandPanel, position } = useLiveAgent();
1768
2028
  const tooltipAlign = position === "right" ? "end" : "start";
1769
- return /* @__PURE__ */ jsx4(Tooltip, {
2029
+ return /* @__PURE__ */ jsx5(Tooltip, {
1770
2030
  label: "Open Skippr assistant",
1771
2031
  align: tooltipAlign,
1772
- children: /* @__PURE__ */ jsxs4("button", {
2032
+ children: /* @__PURE__ */ jsxs5("button", {
1773
2033
  type: "button",
1774
2034
  onClick: expandPanel,
1775
2035
  "aria-label": "Skippr assistant",
1776
2036
  className: cn(BUBBLE_BUTTON, "skippr:relative skippr:bg-bubble skippr:hover:brightness-110"),
1777
2037
  children: [
1778
- /* @__PURE__ */ jsx4(Logo, {
2038
+ /* @__PURE__ */ jsx5(Logo, {
1779
2039
  className: "skippr:relative skippr:z-10 skippr:size-7"
1780
2040
  }),
1781
- /* @__PURE__ */ jsx4("span", {
2041
+ /* @__PURE__ */ jsx5("span", {
1782
2042
  className: "skippr:absolute skippr:-inset-[3px] skippr:animate-pulse skippr:rounded-[17px] skippr:border-2 skippr:border-bubble/50"
1783
2043
  })
1784
2044
  ]
@@ -1790,18 +2050,18 @@ function WelcomeBubble({
1790
2050
  position,
1791
2051
  onDismiss
1792
2052
  }) {
1793
- useEffect5(() => {
2053
+ useEffect6(() => {
1794
2054
  const timer = setTimeout(onDismiss, 5000);
1795
2055
  return () => clearTimeout(timer);
1796
2056
  }, [onDismiss]);
1797
- return /* @__PURE__ */ jsxs4("button", {
2057
+ return /* @__PURE__ */ jsxs5("button", {
1798
2058
  type: "button",
1799
2059
  className: cn("skippr:absolute skippr:bottom-full skippr:mb-3", "skippr:max-w-64 skippr:rounded-xl skippr:bg-card skippr:shadow-lg", "skippr:border skippr:border-border skippr:px-4 skippr:py-3", "skippr:text-sm skippr:text-foreground skippr:leading-relaxed skippr:text-left", "skippr:animate-[skippr-fade-in_0.3s_ease-out]", "skippr:cursor-pointer", position === "right" ? "skippr:right-0" : "skippr:left-0"),
1800
2060
  onClick: onDismiss,
1801
2061
  "aria-label": "Dismiss",
1802
2062
  children: [
1803
2063
  message,
1804
- /* @__PURE__ */ jsx4("span", {
2064
+ /* @__PURE__ */ jsx5("span", {
1805
2065
  className: cn("skippr:absolute skippr:top-full skippr:size-2.5", "skippr:border-l skippr:border-t skippr:border-border skippr:bg-card", "skippr:rotate-[225deg]", position === "right" ? "skippr:right-5" : "skippr:left-5", "skippr:-mt-[5px]")
1806
2066
  })
1807
2067
  ]
@@ -1814,21 +2074,21 @@ function MinimizedBubble({
1814
2074
  }) {
1815
2075
  const { isConnected, isStarting, position } = useLiveAgent();
1816
2076
  const inSession = isConnected || isStarting;
1817
- return /* @__PURE__ */ jsxs4("div", {
2077
+ return /* @__PURE__ */ jsxs5("div", {
1818
2078
  className: cn("skippr:fixed skippr:bottom-6 skippr:z-[9999]", "skippr:flex skippr:items-center skippr:gap-2", position === "right" ? "skippr:right-6" : "skippr:left-6"),
1819
2079
  children: [
1820
- welcomeMessage && !inSession && !welcomeDismissed && /* @__PURE__ */ jsx4(WelcomeBubble, {
2080
+ welcomeMessage && !inSession && !welcomeDismissed && /* @__PURE__ */ jsx5(WelcomeBubble, {
1821
2081
  message: welcomeMessage,
1822
2082
  position,
1823
2083
  onDismiss: onDismissWelcome
1824
2084
  }),
1825
- inSession ? /* @__PURE__ */ jsx4(ConnectedBubbleContent, {}) : /* @__PURE__ */ jsx4(IdleBubbleContent, {})
2085
+ inSession ? /* @__PURE__ */ jsx5(ConnectedBubbleContent, {}) : /* @__PURE__ */ jsx5(IdleBubbleContent, {})
1826
2086
  ]
1827
2087
  });
1828
2088
  }
1829
2089
 
1830
2090
  // src/components/Sidebar.tsx
1831
- import { useEffect as useEffect12 } from "react";
2091
+ import { useEffect as useEffect13 } from "react";
1832
2092
 
1833
2093
  // src/hooks/useCombinedMessages.ts
1834
2094
  import { useMemo as useMemo4 } from "react";
@@ -1910,15 +2170,15 @@ function useCombinedMessages() {
1910
2170
  }
1911
2171
 
1912
2172
  // src/hooks/usePhaseUpdates.ts
1913
- import { useCallback as useCallback4 } from "react";
2173
+ import { useCallback as useCallback5 } from "react";
1914
2174
 
1915
2175
  // src/hooks/useAgentState.ts
1916
2176
  import { useRemoteParticipants } from "@livekit/components-react/hooks";
1917
- import { useEffect as useEffect6, useState as useState3 } from "react";
2177
+ import { useEffect as useEffect7, useState as useState4 } from "react";
1918
2178
  function useAgentState(attributeKey, parse, initial) {
1919
- const [value, setValue] = useState3(initial);
2179
+ const [value, setValue] = useState4(initial);
1920
2180
  const remoteParticipants = useRemoteParticipants();
1921
- useEffect6(() => {
2181
+ useEffect7(() => {
1922
2182
  const agentParticipant = remoteParticipants.find((p) => p.attributes?.[attributeKey]);
1923
2183
  if (agentParticipant) {
1924
2184
  const attr = agentParticipant.attributes?.[attributeKey];
@@ -1964,13 +2224,13 @@ function parsePhases(json) {
1964
2224
  return null;
1965
2225
  }
1966
2226
  function usePhaseUpdates() {
1967
- const parse = useCallback4(parsePhases, []);
2227
+ const parse = useCallback5(parsePhases, []);
1968
2228
  const phases = useAgentState("phases", parse, []);
1969
2229
  return { phases };
1970
2230
  }
1971
2231
 
1972
2232
  // src/hooks/useSessionRemaining.ts
1973
- import { useEffect as useEffect7, useRef as useRef3, useState as useState4 } from "react";
2233
+ import { useEffect as useEffect8, useRef as useRef4, useState as useState5 } from "react";
1974
2234
 
1975
2235
  // src/lib/format.ts
1976
2236
  function formatTime(seconds) {
@@ -1986,9 +2246,9 @@ function parseNumber(s) {
1986
2246
  // src/hooks/useSessionRemaining.ts
1987
2247
  function useSessionRemaining() {
1988
2248
  const maxCallDuration = useAgentState("maxCallDuration", parseNumber, null);
1989
- const endTimeRef = useRef3(null);
1990
- const [remaining, setRemaining] = useState4(null);
1991
- useEffect7(() => {
2249
+ const endTimeRef = useRef4(null);
2250
+ const [remaining, setRemaining] = useState5(null);
2251
+ useEffect8(() => {
1992
2252
  if (maxCallDuration === null || endTimeRef.current !== null)
1993
2253
  return;
1994
2254
  const endTime = Date.now() + maxCallDuration * 1000;
@@ -2005,10 +2265,10 @@ function useSessionRemaining() {
2005
2265
  }
2006
2266
 
2007
2267
  // src/hooks/useElapsedSeconds.ts
2008
- import { useEffect as useEffect8, useState as useState5 } from "react";
2268
+ import { useEffect as useEffect9, useState as useState6 } from "react";
2009
2269
  function useElapsedSeconds(isRunning) {
2010
- const [elapsed, setElapsed] = useState5(0);
2011
- useEffect8(() => {
2270
+ const [elapsed, setElapsed] = useState6(0);
2271
+ useEffect9(() => {
2012
2272
  if (!isRunning) {
2013
2273
  setElapsed(0);
2014
2274
  return;
@@ -2024,50 +2284,50 @@ function useElapsedSeconds(isRunning) {
2024
2284
  }
2025
2285
 
2026
2286
  // src/components/ChatHeader.tsx
2027
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2287
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2028
2288
  function ChatHeader() {
2029
2289
  const { isConnected, minimizePanel, minimizable } = useLiveAgent();
2030
2290
  const elapsed = useElapsedSeconds(isConnected);
2031
- return /* @__PURE__ */ jsxs5("header", {
2291
+ return /* @__PURE__ */ jsxs6("header", {
2032
2292
  className: "skippr:sticky skippr:top-0 skippr:z-10 skippr:flex skippr:shrink-0 skippr:items-center skippr:justify-between skippr:border-b skippr:border-border skippr:bg-primary skippr:px-4 skippr:py-3",
2033
2293
  children: [
2034
- /* @__PURE__ */ jsx5("p", {
2294
+ /* @__PURE__ */ jsx6("p", {
2035
2295
  className: "skippr:text-sm skippr:font-semibold skippr:text-primary-foreground",
2036
2296
  children: "Skippr"
2037
2297
  }),
2038
- /* @__PURE__ */ jsxs5("div", {
2298
+ /* @__PURE__ */ jsxs6("div", {
2039
2299
  className: "skippr:flex skippr:items-center skippr:gap-2",
2040
2300
  children: [
2041
- isConnected && /* @__PURE__ */ jsxs5("div", {
2301
+ isConnected && /* @__PURE__ */ jsxs6("div", {
2042
2302
  className: "skippr:flex skippr:items-center skippr:gap-1.5 skippr:rounded-full skippr:bg-primary-foreground/20 skippr:px-2.5 skippr:py-1",
2043
2303
  children: [
2044
- /* @__PURE__ */ jsxs5("span", {
2304
+ /* @__PURE__ */ jsxs6("span", {
2045
2305
  className: "skippr:relative skippr:flex skippr:size-1.5",
2046
2306
  children: [
2047
- /* @__PURE__ */ jsx5("span", {
2307
+ /* @__PURE__ */ jsx6("span", {
2048
2308
  className: "skippr:absolute skippr:inline-flex skippr:h-full skippr:w-full skippr:animate-ping skippr:rounded-full skippr:bg-red-400 skippr:opacity-75"
2049
2309
  }),
2050
- /* @__PURE__ */ jsx5("span", {
2310
+ /* @__PURE__ */ jsx6("span", {
2051
2311
  className: "skippr:relative skippr:inline-flex skippr:size-1.5 skippr:rounded-full skippr:bg-red-400"
2052
2312
  })
2053
2313
  ]
2054
2314
  }),
2055
- /* @__PURE__ */ jsx5("span", {
2315
+ /* @__PURE__ */ jsx6("span", {
2056
2316
  className: "skippr:text-[10px] skippr:font-medium skippr:text-primary-foreground",
2057
2317
  children: "REC"
2058
2318
  }),
2059
- /* @__PURE__ */ jsx5("span", {
2319
+ /* @__PURE__ */ jsx6("span", {
2060
2320
  className: "skippr:text-[10px] skippr:font-mono skippr:text-primary-foreground",
2061
2321
  children: formatTime(elapsed)
2062
2322
  })
2063
2323
  ]
2064
2324
  }),
2065
- minimizable && /* @__PURE__ */ jsx5("button", {
2325
+ minimizable && /* @__PURE__ */ jsx6("button", {
2066
2326
  type: "button",
2067
2327
  onClick: minimizePanel,
2068
2328
  "aria-label": "Minimize",
2069
2329
  className: "skippr:flex skippr:size-6 skippr:cursor-pointer skippr:items-center skippr:justify-center skippr:rounded-md skippr:text-primary-foreground/70 skippr:transition-colors skippr:hover:bg-primary-foreground/10 skippr:hover:text-primary-foreground",
2070
- children: /* @__PURE__ */ jsx5(Minimize2, {
2330
+ children: /* @__PURE__ */ jsx6(Minimize2, {
2071
2331
  className: "skippr:size-3.5"
2072
2332
  })
2073
2333
  })
@@ -2078,26 +2338,26 @@ function ChatHeader() {
2078
2338
  }
2079
2339
 
2080
2340
  // src/components/LoadingDots.tsx
2081
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2341
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2082
2342
  function LoadingDots({ label }) {
2083
- return /* @__PURE__ */ jsxs6("div", {
2343
+ return /* @__PURE__ */ jsxs7("div", {
2084
2344
  className: "skippr:flex skippr:items-center skippr:gap-2 skippr:py-4",
2085
2345
  children: [
2086
- /* @__PURE__ */ jsxs6("div", {
2346
+ /* @__PURE__ */ jsxs7("div", {
2087
2347
  className: "skippr:flex skippr:gap-1",
2088
2348
  children: [
2089
- /* @__PURE__ */ jsx6("span", {
2349
+ /* @__PURE__ */ jsx7("span", {
2090
2350
  className: "skippr:size-1.5 skippr:rounded-full skippr:bg-muted-foreground/40 skippr:animate-bounce skippr:[animation-delay:0ms]"
2091
2351
  }),
2092
- /* @__PURE__ */ jsx6("span", {
2352
+ /* @__PURE__ */ jsx7("span", {
2093
2353
  className: "skippr:size-1.5 skippr:rounded-full skippr:bg-muted-foreground/40 skippr:animate-bounce skippr:[animation-delay:150ms]"
2094
2354
  }),
2095
- /* @__PURE__ */ jsx6("span", {
2355
+ /* @__PURE__ */ jsx7("span", {
2096
2356
  className: "skippr:size-1.5 skippr:rounded-full skippr:bg-muted-foreground/40 skippr:animate-bounce skippr:[animation-delay:300ms]"
2097
2357
  })
2098
2358
  ]
2099
2359
  }),
2100
- /* @__PURE__ */ jsx6("p", {
2360
+ /* @__PURE__ */ jsx7("p", {
2101
2361
  className: "skippr:text-xs skippr:text-muted-foreground",
2102
2362
  children: label
2103
2363
  })
@@ -2106,11 +2366,11 @@ function LoadingDots({ label }) {
2106
2366
  }
2107
2367
 
2108
2368
  // src/components/LoginFlow.tsx
2109
- import { useCallback as useCallback5, useEffect as useEffect9, useRef as useRef4, useState as useState6 } from "react";
2369
+ import { useCallback as useCallback6, useEffect as useEffect10, useRef as useRef5, useState as useState7 } from "react";
2110
2370
 
2111
2371
  // src/components/ui/button.tsx
2112
2372
  import { forwardRef as forwardRef3 } from "react";
2113
- import { jsx as jsx7 } from "react/jsx-runtime";
2373
+ import { jsx as jsx8 } from "react/jsx-runtime";
2114
2374
  var variantClasses = {
2115
2375
  default: "skippr:bg-primary skippr:text-primary-foreground skippr:hover:bg-primary/90",
2116
2376
  destructive: "skippr:bg-destructive skippr:text-white skippr:hover:bg-destructive/90",
@@ -2129,7 +2389,7 @@ var sizeClasses = {
2129
2389
  "icon-lg": "skippr:size-10"
2130
2390
  };
2131
2391
  var Button = forwardRef3(({ className, variant = "default", size = "default", ...props }, ref) => {
2132
- return /* @__PURE__ */ jsx7("button", {
2392
+ return /* @__PURE__ */ jsx8("button", {
2133
2393
  className: cn("skippr:inline-flex skippr:items-center skippr:justify-center skippr:gap-2 skippr:whitespace-nowrap skippr:rounded-md skippr:text-sm skippr:font-medium skippr:ring-offset-background skippr:transition-all skippr:cursor-pointer skippr:focus-visible:outline-none skippr:focus-visible:ring-2 skippr:focus-visible:ring-ring skippr:focus-visible:ring-offset-2 skippr:disabled:pointer-events-none skippr:disabled:opacity-50 skippr:shrink-0 skippr:[&_svg]:pointer-events-none skippr:[&_svg:not([class*='size-'])]:size-4 skippr:[&_svg]:shrink-0", variantClasses[variant], sizeClasses[size], className),
2134
2394
  ref,
2135
2395
  ...props
@@ -2138,28 +2398,28 @@ var Button = forwardRef3(({ className, variant = "default", size = "default", ..
2138
2398
  Button.displayName = "Button";
2139
2399
 
2140
2400
  // src/components/LoginFlow.tsx
2141
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2401
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2142
2402
  var OTP_LENGTH = 6;
2143
2403
  var DIGIT_KEYS = ["d0", "d1", "d2", "d3", "d4", "d5"];
2144
2404
  function LoginFlow({ requestOtp, verifyOtp, error, isSubmitting }) {
2145
- const [step, setStep] = useState6("email");
2146
- const [email, setEmail] = useState6("");
2147
- const handleRequestOtp = useCallback5(async (emailValue) => {
2405
+ const [step, setStep] = useState7("email");
2406
+ const [email, setEmail] = useState7("");
2407
+ const handleRequestOtp = useCallback6(async (emailValue) => {
2148
2408
  const success = await requestOtp(emailValue);
2149
2409
  if (success)
2150
2410
  setStep("otp");
2151
2411
  }, [requestOtp]);
2152
- const handleVerifyOtp = useCallback5(async (code) => {
2412
+ const handleVerifyOtp = useCallback6(async (code) => {
2153
2413
  await verifyOtp(email, code);
2154
2414
  }, [verifyOtp, email]);
2155
- const handleBack = useCallback5(() => {
2415
+ const handleBack = useCallback6(() => {
2156
2416
  setStep("email");
2157
2417
  }, []);
2158
- const handleResend = useCallback5(async () => {
2418
+ const handleResend = useCallback6(async () => {
2159
2419
  await requestOtp(email);
2160
2420
  }, [requestOtp, email]);
2161
2421
  if (step === "otp") {
2162
- return /* @__PURE__ */ jsx8(OtpStep, {
2422
+ return /* @__PURE__ */ jsx9(OtpStep, {
2163
2423
  email,
2164
2424
  onSubmit: handleVerifyOtp,
2165
2425
  onResend: handleResend,
@@ -2168,7 +2428,7 @@ function LoginFlow({ requestOtp, verifyOtp, error, isSubmitting }) {
2168
2428
  isSubmitting
2169
2429
  });
2170
2430
  }
2171
- return /* @__PURE__ */ jsx8(EmailStep, {
2431
+ return /* @__PURE__ */ jsx9(EmailStep, {
2172
2432
  email,
2173
2433
  onEmailChange: setEmail,
2174
2434
  onSubmit: handleRequestOtp,
@@ -2182,30 +2442,30 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
2182
2442
  if (email.trim())
2183
2443
  onSubmit(email.trim());
2184
2444
  }
2185
- return /* @__PURE__ */ jsxs7("div", {
2445
+ return /* @__PURE__ */ jsxs8("div", {
2186
2446
  className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:px-4 skippr:py-4",
2187
2447
  children: [
2188
- /* @__PURE__ */ jsxs7("div", {
2448
+ /* @__PURE__ */ jsxs8("div", {
2189
2449
  className: "skippr:mb-4 skippr:text-center",
2190
2450
  children: [
2191
- /* @__PURE__ */ jsx8(Mail, {
2451
+ /* @__PURE__ */ jsx9(Mail, {
2192
2452
  className: "skippr:mx-auto skippr:mb-2 skippr:size-6 skippr:text-primary"
2193
2453
  }),
2194
- /* @__PURE__ */ jsx8("p", {
2454
+ /* @__PURE__ */ jsx9("p", {
2195
2455
  className: "skippr:text-sm skippr:font-medium skippr:text-foreground",
2196
2456
  children: "Sign in to continue"
2197
2457
  }),
2198
- /* @__PURE__ */ jsx8("p", {
2458
+ /* @__PURE__ */ jsx9("p", {
2199
2459
  className: "skippr:mt-1 skippr:text-xs skippr:text-muted-foreground",
2200
2460
  children: "Your email will be used to identify you across sessions"
2201
2461
  })
2202
2462
  ]
2203
2463
  }),
2204
- /* @__PURE__ */ jsxs7("form", {
2464
+ /* @__PURE__ */ jsxs8("form", {
2205
2465
  onSubmit: handleSubmit,
2206
2466
  className: "skippr:flex skippr:flex-col skippr:gap-3",
2207
2467
  children: [
2208
- /* @__PURE__ */ jsx8("input", {
2468
+ /* @__PURE__ */ jsx9("input", {
2209
2469
  type: "email",
2210
2470
  placeholder: "you@example.com",
2211
2471
  value: email,
@@ -2214,15 +2474,15 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
2214
2474
  required: true,
2215
2475
  className: "skippr:w-full skippr:rounded-md skippr:border skippr:border-border skippr:bg-background skippr:px-3 skippr:py-2 skippr:text-sm skippr:text-foreground skippr:placeholder-muted-foreground skippr:outline-none focus:skippr:ring-2 focus:skippr:ring-primary/30 focus:skippr:border-primary disabled:skippr:opacity-50"
2216
2476
  }),
2217
- /* @__PURE__ */ jsx8(Button, {
2477
+ /* @__PURE__ */ jsx9(Button, {
2218
2478
  type: "submit",
2219
2479
  disabled: isSubmitting || !email.trim(),
2220
2480
  className: "skippr:w-full",
2221
- children: isSubmitting ? /* @__PURE__ */ jsx8(LoaderCircle, {
2481
+ children: isSubmitting ? /* @__PURE__ */ jsx9(LoaderCircle, {
2222
2482
  className: "skippr:size-4 skippr:animate-spin"
2223
2483
  }) : "Continue"
2224
2484
  }),
2225
- error && /* @__PURE__ */ jsx8("p", {
2485
+ error && /* @__PURE__ */ jsx9("p", {
2226
2486
  className: "skippr:text-xs skippr:text-center skippr:text-destructive",
2227
2487
  children: error
2228
2488
  })
@@ -2232,30 +2492,30 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
2232
2492
  });
2233
2493
  }
2234
2494
  function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2235
- const [digits, setDigits] = useState6(Array(OTP_LENGTH).fill(""));
2236
- const [resendCooldown, setResendCooldown] = useState6(0);
2237
- const inputRefs = useRef4([]);
2238
- const submittedRef = useRef4(false);
2239
- useEffect9(() => {
2495
+ const [digits, setDigits] = useState7(Array(OTP_LENGTH).fill(""));
2496
+ const [resendCooldown, setResendCooldown] = useState7(0);
2497
+ const inputRefs = useRef5([]);
2498
+ const submittedRef = useRef5(false);
2499
+ useEffect10(() => {
2240
2500
  inputRefs.current[0]?.focus();
2241
2501
  }, []);
2242
- useEffect9(() => {
2502
+ useEffect10(() => {
2243
2503
  if (error)
2244
2504
  submittedRef.current = false;
2245
2505
  }, [error]);
2246
- useEffect9(() => {
2506
+ useEffect10(() => {
2247
2507
  if (resendCooldown <= 0)
2248
2508
  return;
2249
2509
  const timer = setTimeout(() => setResendCooldown((c) => c - 1), 1000);
2250
2510
  return () => clearTimeout(timer);
2251
2511
  }, [resendCooldown]);
2252
- const submitCode = useCallback5((code) => {
2512
+ const submitCode = useCallback6((code) => {
2253
2513
  if (submittedRef.current || isSubmitting)
2254
2514
  return;
2255
2515
  submittedRef.current = true;
2256
2516
  onSubmit(code);
2257
2517
  }, [onSubmit, isSubmitting]);
2258
- const handleDigitChange = useCallback5((index2, value) => {
2518
+ const handleDigitChange = useCallback6((index2, value) => {
2259
2519
  const digit = value.replace(/\D/g, "").slice(-1);
2260
2520
  const newDigits = [...digits];
2261
2521
  newDigits[index2] = digit;
@@ -2269,12 +2529,12 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2269
2529
  submitCode(code);
2270
2530
  }
2271
2531
  }, [digits, submitCode]);
2272
- const handleKeyDown = useCallback5((index2, e) => {
2532
+ const handleKeyDown = useCallback6((index2, e) => {
2273
2533
  if (e.key === "Backspace" && !digits[index2] && index2 > 0) {
2274
2534
  inputRefs.current[index2 - 1]?.focus();
2275
2535
  }
2276
2536
  }, [digits]);
2277
- const handlePaste = useCallback5((e) => {
2537
+ const handlePaste = useCallback6((e) => {
2278
2538
  e.preventDefault();
2279
2539
  const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, OTP_LENGTH);
2280
2540
  if (pasted.length > 0) {
@@ -2302,22 +2562,22 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2302
2562
  submittedRef.current = false;
2303
2563
  inputRefs.current[0]?.focus();
2304
2564
  }
2305
- return /* @__PURE__ */ jsxs7("div", {
2565
+ return /* @__PURE__ */ jsxs8("div", {
2306
2566
  className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:px-4 skippr:py-4",
2307
2567
  children: [
2308
- /* @__PURE__ */ jsxs7("div", {
2568
+ /* @__PURE__ */ jsxs8("div", {
2309
2569
  className: "skippr:mb-4 skippr:text-center",
2310
2570
  children: [
2311
- /* @__PURE__ */ jsx8("p", {
2571
+ /* @__PURE__ */ jsx9("p", {
2312
2572
  className: "skippr:text-sm skippr:font-medium skippr:text-foreground",
2313
2573
  children: "Enter verification code"
2314
2574
  }),
2315
- /* @__PURE__ */ jsxs7("p", {
2575
+ /* @__PURE__ */ jsxs8("p", {
2316
2576
  className: "skippr:mt-1 skippr:text-xs skippr:text-muted-foreground",
2317
2577
  children: [
2318
2578
  "We sent a 6-digit code to",
2319
2579
  " ",
2320
- /* @__PURE__ */ jsx8("span", {
2580
+ /* @__PURE__ */ jsx9("span", {
2321
2581
  className: "skippr:font-medium skippr:text-foreground",
2322
2582
  children: email
2323
2583
  })
@@ -2325,13 +2585,13 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2325
2585
  })
2326
2586
  ]
2327
2587
  }),
2328
- /* @__PURE__ */ jsxs7("form", {
2588
+ /* @__PURE__ */ jsxs8("form", {
2329
2589
  onSubmit: handleSubmit,
2330
2590
  className: "skippr:flex skippr:flex-col skippr:gap-3",
2331
2591
  children: [
2332
- /* @__PURE__ */ jsx8("div", {
2592
+ /* @__PURE__ */ jsx9("div", {
2333
2593
  className: "skippr:flex skippr:justify-center skippr:gap-1.5",
2334
- children: digits.map((digit, index2) => /* @__PURE__ */ jsx8("input", {
2594
+ children: digits.map((digit, index2) => /* @__PURE__ */ jsx9("input", {
2335
2595
  ref: (el) => {
2336
2596
  inputRefs.current[index2] = el;
2337
2597
  },
@@ -2346,29 +2606,29 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2346
2606
  className: "skippr:h-10 skippr:w-10 skippr:rounded-md skippr:border skippr:border-border skippr:bg-background skippr:text-center skippr:text-sm skippr:font-semibold skippr:text-foreground skippr:outline-none focus:skippr:ring-2 focus:skippr:ring-primary/30 focus:skippr:border-primary disabled:skippr:opacity-50"
2347
2607
  }, DIGIT_KEYS[index2]))
2348
2608
  }),
2349
- error && /* @__PURE__ */ jsx8("p", {
2609
+ error && /* @__PURE__ */ jsx9("p", {
2350
2610
  className: "skippr:text-xs skippr:text-center skippr:text-destructive",
2351
2611
  children: error
2352
2612
  }),
2353
- /* @__PURE__ */ jsx8(Button, {
2613
+ /* @__PURE__ */ jsx9(Button, {
2354
2614
  type: "submit",
2355
2615
  disabled: isSubmitting || digits.join("").length !== OTP_LENGTH,
2356
2616
  className: "skippr:w-full",
2357
- children: isSubmitting ? /* @__PURE__ */ jsx8(LoaderCircle, {
2617
+ children: isSubmitting ? /* @__PURE__ */ jsx9(LoaderCircle, {
2358
2618
  className: "skippr:size-4 skippr:animate-spin"
2359
2619
  }) : "Verify"
2360
2620
  }),
2361
- /* @__PURE__ */ jsxs7("div", {
2621
+ /* @__PURE__ */ jsxs8("div", {
2362
2622
  className: "skippr:flex skippr:items-center skippr:justify-between skippr:text-xs",
2363
2623
  children: [
2364
- /* @__PURE__ */ jsx8("button", {
2624
+ /* @__PURE__ */ jsx9("button", {
2365
2625
  type: "button",
2366
2626
  onClick: onBack,
2367
2627
  disabled: isSubmitting,
2368
2628
  className: "skippr:text-muted-foreground hover:skippr:text-foreground skippr:transition-colors disabled:skippr:opacity-50",
2369
2629
  children: "Change email"
2370
2630
  }),
2371
- /* @__PURE__ */ jsx8("button", {
2631
+ /* @__PURE__ */ jsx9("button", {
2372
2632
  type: "button",
2373
2633
  onClick: handleResend,
2374
2634
  disabled: isSubmitting || resendCooldown > 0,
@@ -2384,50 +2644,50 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2384
2644
  }
2385
2645
 
2386
2646
  // src/components/MeetingControls.tsx
2387
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2647
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2388
2648
  var CONTROL_BUTTON = "skippr:flex skippr:size-11 skippr:cursor-pointer skippr:items-center skippr:justify-center skippr:rounded-full skippr:transition-colors";
2389
2649
  function MeetingControls({ onHangUp, showScreenShareToggle = true }) {
2390
2650
  const { isMuted, toggleMute, isScreenSharing, toggleScreenShare } = useMediaControls();
2391
- return /* @__PURE__ */ jsxs8("div", {
2651
+ return /* @__PURE__ */ jsxs9("div", {
2392
2652
  className: "skippr:shrink-0 skippr:border-t skippr:border-border skippr:bg-background skippr:px-4 skippr:py-4",
2393
2653
  children: [
2394
- /* @__PURE__ */ jsxs8("div", {
2654
+ /* @__PURE__ */ jsxs9("div", {
2395
2655
  className: "skippr:flex skippr:items-center skippr:justify-center skippr:gap-3",
2396
2656
  children: [
2397
- /* @__PURE__ */ jsx9("button", {
2657
+ /* @__PURE__ */ jsx10("button", {
2398
2658
  type: "button",
2399
2659
  onClick: toggleMute,
2400
2660
  "aria-label": isMuted ? "Unmute" : "Mute",
2401
2661
  className: cn(CONTROL_BUTTON, isMuted ? "skippr:bg-destructive/15 skippr:text-destructive skippr:hover:bg-destructive/25" : "skippr:bg-muted skippr:text-foreground skippr:hover:bg-muted/80"),
2402
- children: isMuted ? /* @__PURE__ */ jsx9(MicOff, {
2662
+ children: isMuted ? /* @__PURE__ */ jsx10(MicOff, {
2403
2663
  className: "skippr:size-5"
2404
- }) : /* @__PURE__ */ jsx9(Mic, {
2664
+ }) : /* @__PURE__ */ jsx10(Mic, {
2405
2665
  className: "skippr:size-5"
2406
2666
  })
2407
2667
  }),
2408
- showScreenShareToggle && /* @__PURE__ */ jsx9("button", {
2668
+ showScreenShareToggle && /* @__PURE__ */ jsx10("button", {
2409
2669
  type: "button",
2410
2670
  onClick: toggleScreenShare,
2411
2671
  "aria-label": isScreenSharing ? "Stop sharing screen" : "Share screen",
2412
2672
  className: cn(CONTROL_BUTTON, isScreenSharing ? "skippr:bg-bubble skippr:text-white skippr:hover:brightness-110" : "skippr:bg-muted skippr:text-foreground skippr:hover:bg-muted/80"),
2413
- children: isScreenSharing ? /* @__PURE__ */ jsx9(MonitorOff, {
2673
+ children: isScreenSharing ? /* @__PURE__ */ jsx10(MonitorOff, {
2414
2674
  className: "skippr:size-5"
2415
- }) : /* @__PURE__ */ jsx9(Monitor, {
2675
+ }) : /* @__PURE__ */ jsx10(Monitor, {
2416
2676
  className: "skippr:size-5"
2417
2677
  })
2418
2678
  }),
2419
- /* @__PURE__ */ jsx9("button", {
2679
+ /* @__PURE__ */ jsx10("button", {
2420
2680
  type: "button",
2421
2681
  onClick: onHangUp,
2422
2682
  "aria-label": "End session",
2423
2683
  className: cn(CONTROL_BUTTON, "skippr:bg-destructive skippr:text-destructive-foreground skippr:hover:bg-destructive/90"),
2424
- children: /* @__PURE__ */ jsx9(PhoneOff, {
2684
+ children: /* @__PURE__ */ jsx10(PhoneOff, {
2425
2685
  className: "skippr:size-5"
2426
2686
  })
2427
2687
  })
2428
2688
  ]
2429
2689
  }),
2430
- /* @__PURE__ */ jsx9("p", {
2690
+ /* @__PURE__ */ jsx10("p", {
2431
2691
  className: "skippr:mt-3 skippr:text-center skippr:text-[10px] skippr:text-muted-foreground",
2432
2692
  children: "Powered by Skippr"
2433
2693
  })
@@ -2436,17 +2696,17 @@ function MeetingControls({ onHangUp, showScreenShareToggle = true }) {
2436
2696
  }
2437
2697
 
2438
2698
  // src/components/MessageList.tsx
2439
- import { useEffect as useEffect11, useRef as useRef6 } from "react";
2699
+ import { useEffect as useEffect12, useRef as useRef7 } from "react";
2440
2700
 
2441
2701
  // src/components/ChatInput.tsx
2442
- import { useEffect as useEffect10, useRef as useRef5, useState as useState7 } from "react";
2443
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2702
+ import { useEffect as useEffect11, useRef as useRef6, useState as useState8 } from "react";
2703
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2444
2704
  var MAX_INPUT_HEIGHT = 60;
2445
2705
  function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2446
- const [inputText, setInputText] = useState7("");
2447
- const textareaRef = useRef5(null);
2706
+ const [inputText, setInputText] = useState8("");
2707
+ const textareaRef = useRef6(null);
2448
2708
  const canSend = inputText.trim().length > 0 && !isSendingChat;
2449
- useEffect10(() => {
2709
+ useEffect11(() => {
2450
2710
  if (autoFocus)
2451
2711
  textareaRef.current?.focus();
2452
2712
  }, [autoFocus]);
@@ -2477,13 +2737,13 @@ function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2477
2737
  handleSubmit(e);
2478
2738
  }
2479
2739
  }
2480
- return /* @__PURE__ */ jsx10("form", {
2740
+ return /* @__PURE__ */ jsx11("form", {
2481
2741
  onSubmit: handleSubmit,
2482
2742
  className: "skippr:border-t skippr:border-border skippr:p-3",
2483
- children: /* @__PURE__ */ jsxs9("div", {
2743
+ children: /* @__PURE__ */ jsxs10("div", {
2484
2744
  className: "skippr:flex skippr:items-center skippr:gap-2 skippr:rounded-xl skippr:bg-background skippr:ring-1 skippr:ring-foreground/10 skippr:px-3 skippr:py-2",
2485
2745
  children: [
2486
- /* @__PURE__ */ jsx10("textarea", {
2746
+ /* @__PURE__ */ jsx11("textarea", {
2487
2747
  ref: textareaRef,
2488
2748
  rows: 1,
2489
2749
  value: inputText,
@@ -2493,12 +2753,12 @@ function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2493
2753
  className: "skippr:flex-1 skippr:resize-none skippr:overflow-y-auto skippr:bg-transparent skippr:text-sm skippr:leading-5 skippr:text-foreground skippr:placeholder:text-muted-foreground skippr:outline-none",
2494
2754
  style: { maxHeight: `${MAX_INPUT_HEIGHT}px` }
2495
2755
  }),
2496
- /* @__PURE__ */ jsx10("button", {
2756
+ /* @__PURE__ */ jsx11("button", {
2497
2757
  type: "submit",
2498
2758
  disabled: !canSend,
2499
2759
  "aria-label": "Send message",
2500
2760
  className: cn("skippr:flex skippr:size-8 skippr:shrink-0 skippr:items-center skippr:justify-center skippr:rounded-lg skippr:transition-colors", canSend ? "skippr:bg-primary skippr:text-primary-foreground skippr:hover:bg-primary/90" : "skippr:bg-muted-foreground/20 skippr:text-muted-foreground/60"),
2501
- children: /* @__PURE__ */ jsx10(Send, {
2761
+ children: /* @__PURE__ */ jsx11(Send, {
2502
2762
  className: "skippr:size-3.5"
2503
2763
  })
2504
2764
  })
@@ -2508,7 +2768,7 @@ function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2508
2768
  }
2509
2769
 
2510
2770
  // src/components/ChatMessage.tsx
2511
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2771
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2512
2772
  function formatTimestamp(ts) {
2513
2773
  return new Date(ts).toLocaleTimeString("en-US", {
2514
2774
  hour: "numeric",
@@ -2518,23 +2778,23 @@ function formatTimestamp(ts) {
2518
2778
  }
2519
2779
  function ChatMessage({ message }) {
2520
2780
  const isAgent = message.role === "assistant";
2521
- return /* @__PURE__ */ jsxs10("div", {
2781
+ return /* @__PURE__ */ jsxs11("div", {
2522
2782
  className: cn("skippr:flex skippr:gap-2", isAgent ? "skippr:items-start" : "skippr:justify-end"),
2523
2783
  children: [
2524
- isAgent && /* @__PURE__ */ jsx11("div", {
2784
+ isAgent && /* @__PURE__ */ jsx12("div", {
2525
2785
  className: "skippr:mt-0.5 skippr:flex skippr:size-7 skippr:shrink-0 skippr:items-center skippr:justify-center skippr:rounded-md skippr:bg-primary",
2526
- children: /* @__PURE__ */ jsx11(Sparkles, {
2786
+ children: /* @__PURE__ */ jsx12(Sparkles, {
2527
2787
  className: "skippr:size-3.5 skippr:text-primary-foreground"
2528
2788
  })
2529
2789
  }),
2530
- /* @__PURE__ */ jsxs10("div", {
2790
+ /* @__PURE__ */ jsxs11("div", {
2531
2791
  className: cn("skippr:flex skippr:max-w-[80%] skippr:flex-col", isAgent ? "skippr:items-start" : "skippr:items-end"),
2532
2792
  children: [
2533
- /* @__PURE__ */ jsx11("div", {
2793
+ /* @__PURE__ */ jsx12("div", {
2534
2794
  className: cn("skippr:rounded-2xl skippr:px-4 skippr:py-2.5 skippr:text-sm skippr:leading-relaxed", isAgent ? "skippr:border skippr:border-border skippr:bg-card skippr:text-foreground" : "skippr:bg-primary skippr:text-primary-foreground"),
2535
2795
  children: message.content
2536
2796
  }),
2537
- message.timestamp && /* @__PURE__ */ jsx11("span", {
2797
+ message.timestamp && /* @__PURE__ */ jsx12("span", {
2538
2798
  className: "skippr:mt-1 skippr:px-1 skippr:text-[10px] skippr:text-muted-foreground/60",
2539
2799
  children: formatTimestamp(message.timestamp)
2540
2800
  })
@@ -2545,33 +2805,33 @@ function ChatMessage({ message }) {
2545
2805
  }
2546
2806
 
2547
2807
  // src/components/TypingIndicator.tsx
2548
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2808
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2549
2809
  function TypingIndicator() {
2550
- return /* @__PURE__ */ jsxs11("div", {
2810
+ return /* @__PURE__ */ jsxs12("div", {
2551
2811
  className: "skippr:flex skippr:items-start skippr:gap-2 skippr:animate-skippr-tab-fade",
2552
2812
  children: [
2553
- /* @__PURE__ */ jsx12("div", {
2813
+ /* @__PURE__ */ jsx13("div", {
2554
2814
  className: "skippr:mt-0.5 skippr:flex skippr:size-7 skippr:shrink-0 skippr:items-center skippr:justify-center skippr:rounded-md skippr:bg-primary",
2555
- children: /* @__PURE__ */ jsx12(Sparkles, {
2815
+ children: /* @__PURE__ */ jsx13(Sparkles, {
2556
2816
  className: "skippr:size-3.5 skippr:text-primary-foreground"
2557
2817
  })
2558
2818
  }),
2559
- /* @__PURE__ */ jsxs11("div", {
2819
+ /* @__PURE__ */ jsxs12("div", {
2560
2820
  className: "skippr:inline-flex skippr:items-center skippr:gap-1 skippr:rounded-2xl skippr:border skippr:border-primary/20 skippr:bg-primary/10 skippr:px-4 skippr:py-2 skippr:text-xs skippr:text-primary",
2561
2821
  children: [
2562
- /* @__PURE__ */ jsx12("span", {
2822
+ /* @__PURE__ */ jsx13("span", {
2563
2823
  children: "Agent is analyzing your screen"
2564
2824
  }),
2565
- /* @__PURE__ */ jsxs11("span", {
2825
+ /* @__PURE__ */ jsxs12("span", {
2566
2826
  className: "skippr:inline-flex skippr:items-center skippr:gap-[2px]",
2567
2827
  children: [
2568
- /* @__PURE__ */ jsx12("span", {
2828
+ /* @__PURE__ */ jsx13("span", {
2569
2829
  className: "skippr:size-1 skippr:rounded-full skippr:bg-primary skippr:animate-skippr-thinking-dot skippr:[animation-delay:0ms]"
2570
2830
  }),
2571
- /* @__PURE__ */ jsx12("span", {
2831
+ /* @__PURE__ */ jsx13("span", {
2572
2832
  className: "skippr:size-1 skippr:rounded-full skippr:bg-primary skippr:animate-skippr-thinking-dot skippr:[animation-delay:200ms]"
2573
2833
  }),
2574
- /* @__PURE__ */ jsx12("span", {
2834
+ /* @__PURE__ */ jsx13("span", {
2575
2835
  className: "skippr:size-1 skippr:rounded-full skippr:bg-primary skippr:animate-skippr-thinking-dot skippr:[animation-delay:400ms]"
2576
2836
  })
2577
2837
  ]
@@ -2583,7 +2843,7 @@ function TypingIndicator() {
2583
2843
  }
2584
2844
 
2585
2845
  // src/components/MessageList.tsx
2586
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2846
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2587
2847
  function MessageList({
2588
2848
  messages,
2589
2849
  isStreaming,
@@ -2591,31 +2851,31 @@ function MessageList({
2591
2851
  isSendingChat,
2592
2852
  autoFocus = false
2593
2853
  }) {
2594
- const scrollRef = useRef6(null);
2854
+ const scrollRef = useRef7(null);
2595
2855
  const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
2596
- useEffect11(() => {
2856
+ useEffect12(() => {
2597
2857
  scrollRef.current?.scrollIntoView({ behavior: "smooth" });
2598
2858
  }, [messages.length, lastMessage?.content]);
2599
2859
  const showTyping = isStreaming && lastMessage?.role === "assistant" && lastMessage.content === "";
2600
- return /* @__PURE__ */ jsxs12("div", {
2860
+ return /* @__PURE__ */ jsxs13("div", {
2601
2861
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
2602
2862
  children: [
2603
- /* @__PURE__ */ jsxs12("div", {
2863
+ /* @__PURE__ */ jsxs13("div", {
2604
2864
  className: "skippr:min-h-0 skippr:flex-1 skippr:space-y-4 skippr:overflow-y-auto skippr:p-4",
2605
2865
  children: [
2606
- messages.length === 0 && !showTyping && /* @__PURE__ */ jsx13(LoadingDots, {
2866
+ messages.length === 0 && !showTyping && /* @__PURE__ */ jsx14(LoadingDots, {
2607
2867
  label: "Waiting for conversation to begin..."
2608
2868
  }),
2609
- messages.map((message) => /* @__PURE__ */ jsx13(ChatMessage, {
2869
+ messages.map((message) => /* @__PURE__ */ jsx14(ChatMessage, {
2610
2870
  message
2611
2871
  }, message.id)),
2612
- showTyping && /* @__PURE__ */ jsx13(TypingIndicator, {}),
2613
- /* @__PURE__ */ jsx13("div", {
2872
+ showTyping && /* @__PURE__ */ jsx14(TypingIndicator, {}),
2873
+ /* @__PURE__ */ jsx14("div", {
2614
2874
  ref: scrollRef
2615
2875
  })
2616
2876
  ]
2617
2877
  }),
2618
- /* @__PURE__ */ jsx13(ChatInput, {
2878
+ /* @__PURE__ */ jsx14(ChatInput, {
2619
2879
  sendChatMessage,
2620
2880
  isSendingChat,
2621
2881
  autoFocus
@@ -2625,49 +2885,49 @@ function MessageList({
2625
2885
  }
2626
2886
 
2627
2887
  // src/components/SessionAgenda.tsx
2628
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2888
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
2629
2889
  function SessionAgenda({ phases, hasStarted }) {
2630
2890
  if (phases.length === 0 || !hasStarted) {
2631
- return /* @__PURE__ */ jsx14("div", {
2891
+ return /* @__PURE__ */ jsx15("div", {
2632
2892
  className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
2633
- children: /* @__PURE__ */ jsx14(LoadingDots, {
2893
+ children: /* @__PURE__ */ jsx15(LoadingDots, {
2634
2894
  label: "Waiting for agenda to load..."
2635
2895
  })
2636
2896
  });
2637
2897
  }
2638
- return /* @__PURE__ */ jsx14("div", {
2898
+ return /* @__PURE__ */ jsx15("div", {
2639
2899
  className: "skippr:flex-1 skippr:overflow-y-auto skippr:px-4 skippr:py-4",
2640
- children: /* @__PURE__ */ jsx14("div", {
2900
+ children: /* @__PURE__ */ jsx15("div", {
2641
2901
  className: "skippr:space-y-1",
2642
2902
  children: phases.map((phase) => {
2643
2903
  const isActive = phase.status === "active";
2644
2904
  const isCompleted = phase.status === "completed";
2645
- return /* @__PURE__ */ jsxs13("div", {
2905
+ return /* @__PURE__ */ jsxs14("div", {
2646
2906
  className: cn("skippr:flex skippr:items-start skippr:gap-2.5 skippr:rounded-lg skippr:p-2 skippr:transition-colors", isActive && "skippr:bg-primary/10"),
2647
2907
  children: [
2648
- /* @__PURE__ */ jsx14("div", {
2908
+ /* @__PURE__ */ jsx15("div", {
2649
2909
  className: "skippr:mt-0.5",
2650
- children: isCompleted ? /* @__PURE__ */ jsx14(CircleCheck, {
2910
+ children: isCompleted ? /* @__PURE__ */ jsx15(CircleCheck, {
2651
2911
  className: "skippr:size-4 skippr:text-chart-3"
2652
- }) : isActive ? /* @__PURE__ */ jsx14(Circle, {
2912
+ }) : isActive ? /* @__PURE__ */ jsx15(Circle, {
2653
2913
  className: "skippr:size-4 skippr:fill-primary/30 skippr:text-primary"
2654
- }) : /* @__PURE__ */ jsx14(Circle, {
2914
+ }) : /* @__PURE__ */ jsx15(Circle, {
2655
2915
  className: "skippr:size-4 skippr:text-muted-foreground/30"
2656
2916
  })
2657
2917
  }),
2658
- /* @__PURE__ */ jsxs13("div", {
2918
+ /* @__PURE__ */ jsxs14("div", {
2659
2919
  className: "skippr:min-w-0 skippr:flex-1",
2660
2920
  children: [
2661
- /* @__PURE__ */ jsx14("p", {
2921
+ /* @__PURE__ */ jsx15("p", {
2662
2922
  className: cn("skippr:text-sm", isCompleted && "skippr:text-muted-foreground skippr:line-through", isActive && "skippr:font-medium skippr:text-foreground", phase.status === "pending" && "skippr:text-muted-foreground"),
2663
2923
  children: phase.name
2664
2924
  }),
2665
- phase.highlights.length > 0 && /* @__PURE__ */ jsx14("ul", {
2925
+ phase.highlights.length > 0 && /* @__PURE__ */ jsx15("ul", {
2666
2926
  className: "skippr:mt-1 skippr:space-y-0.5",
2667
- children: phase.highlights.map((text) => /* @__PURE__ */ jsxs13("li", {
2927
+ children: phase.highlights.map((text) => /* @__PURE__ */ jsxs14("li", {
2668
2928
  className: cn("skippr:flex skippr:items-center skippr:gap-1.5 skippr:text-[11px] skippr:leading-tight", isCompleted ? "skippr:text-muted-foreground/40 skippr:line-through" : "skippr:text-muted-foreground/70"),
2669
2929
  children: [
2670
- /* @__PURE__ */ jsx14("span", {
2930
+ /* @__PURE__ */ jsx15("span", {
2671
2931
  className: "skippr:size-1 skippr:shrink-0 skippr:rounded-full skippr:bg-current"
2672
2932
  }),
2673
2933
  text
@@ -2684,12 +2944,12 @@ function SessionAgenda({ phases, hasStarted }) {
2684
2944
  }
2685
2945
 
2686
2946
  // src/components/SessionWarningBanner.tsx
2687
- import { jsx as jsx15 } from "react/jsx-runtime";
2947
+ import { jsx as jsx16 } from "react/jsx-runtime";
2688
2948
  var SESSION_WARNING_THRESHOLD_SECS = 60;
2689
2949
  function SessionWarningBanner({ remaining }) {
2690
2950
  if (remaining === null || remaining <= 0 || remaining > SESSION_WARNING_THRESHOLD_SECS)
2691
2951
  return null;
2692
- return /* @__PURE__ */ jsx15("div", {
2952
+ return /* @__PURE__ */ jsx16("div", {
2693
2953
  "data-testid": "session-warning-banner",
2694
2954
  className: "skippr:bg-red-50 skippr:px-4 skippr:py-1.5 skippr:text-center skippr:text-xs skippr:font-medium skippr:text-red-700",
2695
2955
  children: "Session ending soon"
@@ -2697,24 +2957,24 @@ function SessionWarningBanner({ remaining }) {
2697
2957
  }
2698
2958
 
2699
2959
  // src/components/StartSessionPrompt.tsx
2700
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2960
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2701
2961
  function StartSessionPrompt({
2702
2962
  onStartSession,
2703
2963
  isStarting,
2704
2964
  error,
2705
2965
  label = "Talk to Skippr"
2706
2966
  }) {
2707
- return /* @__PURE__ */ jsxs14("div", {
2967
+ return /* @__PURE__ */ jsxs15("div", {
2708
2968
  className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:items-center skippr:justify-center skippr:gap-3 skippr:px-4",
2709
2969
  children: [
2710
- /* @__PURE__ */ jsx16("button", {
2970
+ /* @__PURE__ */ jsx17("button", {
2711
2971
  type: "button",
2712
2972
  onClick: onStartSession,
2713
2973
  disabled: isStarting,
2714
2974
  className: "skippr:cursor-pointer skippr:rounded-xl skippr:bg-primary skippr:px-8 skippr:py-3 skippr:text-sm skippr:font-medium skippr:text-primary-foreground skippr:transition-all skippr:hover:bg-primary/90 skippr:disabled:cursor-not-allowed skippr:disabled:opacity-60",
2715
2975
  children: isStarting ? "Starting..." : label
2716
2976
  }),
2717
- error && /* @__PURE__ */ jsx16("p", {
2977
+ error && /* @__PURE__ */ jsx17("p", {
2718
2978
  className: "skippr:text-xs skippr:text-destructive",
2719
2979
  children: error
2720
2980
  })
@@ -2723,7 +2983,7 @@ function StartSessionPrompt({
2723
2983
  }
2724
2984
 
2725
2985
  // src/components/Sidebar.tsx
2726
- import { jsx as jsx17, jsxs as jsxs15, Fragment as Fragment3 } from "react/jsx-runtime";
2986
+ import { jsx as jsx18, jsxs as jsxs16, Fragment as Fragment4 } from "react/jsx-runtime";
2727
2987
  function Sidebar({
2728
2988
  hideControls = false,
2729
2989
  hideHeader = false,
@@ -2751,7 +3011,7 @@ function Sidebar({
2751
3011
  } = useLiveAgent();
2752
3012
  const isFloating = variant === "floating";
2753
3013
  const isSidebar = variant === "sidebar";
2754
- useEffect12(() => {
3014
+ useEffect13(() => {
2755
3015
  if (!isSidebar)
2756
3016
  return;
2757
3017
  const prop = position === "right" ? "marginRight" : "marginLeft";
@@ -2765,22 +3025,22 @@ function Sidebar({
2765
3025
  document.body.style.transition = "";
2766
3026
  };
2767
3027
  }, [isSidebar, isPanelOpen, position]);
2768
- return /* @__PURE__ */ jsxs15("div", {
3028
+ return /* @__PURE__ */ jsxs16("div", {
2769
3029
  className: cn("skippr:fixed skippr:z-[9999]", "skippr:bg-card", "skippr:flex skippr:flex-col", "skippr:overflow-hidden", isFloating && "skippr:border skippr:border-border skippr:bottom-[88px] skippr:h-[calc(100vh-112px)] skippr:rounded-2xl skippr:shadow-[0_8px_30px_rgba(0,0,0,0.16),0_4px_12px_rgba(0,0,0,0.08)]", isFloating && (position === "right" ? "skippr:right-6" : "skippr:left-6"), isFloating && "skippr:transition-[opacity,transform] skippr:duration-300 skippr:ease-in-out", isFloating && (position === "right" ? "skippr:origin-bottom-right" : "skippr:origin-bottom-left"), isFloating && !isPanelOpen && "skippr:scale-0 skippr:opacity-0 skippr:pointer-events-none", isFloating && isPanelOpen && "skippr:scale-100 skippr:opacity-100", isSidebar && "skippr:top-0 skippr:h-full", isSidebar && "skippr:transition-[width] skippr:duration-300 skippr:ease-in-out", isSidebar && position === "right" && "skippr:right-0 skippr:border-l skippr:border-l-border", isSidebar && position === "left" && "skippr:left-0 skippr:border-r skippr:border-r-border", isSidebar && !isPanelOpen && "skippr:w-0 skippr:border-0"),
2770
3030
  style: { width: isPanelOpen ? SIDEBAR_WIDTH : undefined },
2771
3031
  children: [
2772
- !hideHeader && /* @__PURE__ */ jsx17(ChatHeader, {}),
2773
- !isAuthenticated && isValidating ? /* @__PURE__ */ jsx17("div", {
3032
+ !hideHeader && /* @__PURE__ */ jsx18(ChatHeader, {}),
3033
+ !isAuthenticated && isValidating ? /* @__PURE__ */ jsx18("div", {
2774
3034
  className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
2775
- children: /* @__PURE__ */ jsx17(LoadingDots, {
3035
+ children: /* @__PURE__ */ jsx18(LoadingDots, {
2776
3036
  label: "Loading..."
2777
3037
  })
2778
- }) : !isAuthenticated ? /* @__PURE__ */ jsx17(LoginFlow, {
3038
+ }) : !isAuthenticated ? /* @__PURE__ */ jsx18(LoginFlow, {
2779
3039
  requestOtp,
2780
3040
  verifyOtp,
2781
3041
  error: authError,
2782
3042
  isSubmitting: isAuthSubmitting
2783
- }) : /* @__PURE__ */ jsx17(AuthenticatedContent, {
3043
+ }) : /* @__PURE__ */ jsx18(AuthenticatedContent, {
2784
3044
  isConnected,
2785
3045
  onStartSession: startSession,
2786
3046
  onDisconnect: disconnect,
@@ -2809,50 +3069,50 @@ function AuthenticatedContent({
2809
3069
  autoFocusChat,
2810
3070
  showScreenShareToggle
2811
3071
  }) {
2812
- return /* @__PURE__ */ jsxs15(Fragment3, {
3072
+ return /* @__PURE__ */ jsxs16(Fragment4, {
2813
3073
  children: [
2814
- isConnected && /* @__PURE__ */ jsx17(ConnectedBanner, {}),
2815
- /* @__PURE__ */ jsxs15("div", {
3074
+ isConnected && /* @__PURE__ */ jsx18(ConnectedBanner, {}),
3075
+ /* @__PURE__ */ jsxs16("div", {
2816
3076
  className: "skippr:flex skippr:gap-2 skippr:border-b skippr:border-border skippr:px-3 skippr:py-2",
2817
3077
  children: [
2818
- /* @__PURE__ */ jsxs15("button", {
3078
+ /* @__PURE__ */ jsxs16("button", {
2819
3079
  type: "button",
2820
3080
  className: cn("skippr:relative skippr:inline-flex skippr:cursor-pointer skippr:items-center skippr:gap-1.5 skippr:rounded-lg skippr:px-3 skippr:py-2 skippr:text-sm skippr:font-medium skippr:transition-all", activeTab === "chat" ? "skippr:text-foreground" : "skippr:text-muted-foreground skippr:hover:text-foreground"),
2821
3081
  onClick: () => onTabChange("chat"),
2822
3082
  children: [
2823
- /* @__PURE__ */ jsx17(MessageCircle, {
3083
+ /* @__PURE__ */ jsx18(MessageCircle, {
2824
3084
  className: "skippr:size-3.5"
2825
3085
  }),
2826
3086
  "Chat",
2827
- activeTab === "chat" && /* @__PURE__ */ jsx17("span", {
3087
+ activeTab === "chat" && /* @__PURE__ */ jsx18("span", {
2828
3088
  className: "skippr:absolute skippr:-bottom-2 skippr:left-3 skippr:right-3 skippr:h-0.5 skippr:rounded-full skippr:bg-foreground"
2829
3089
  })
2830
3090
  ]
2831
3091
  }),
2832
- /* @__PURE__ */ jsxs15("button", {
3092
+ /* @__PURE__ */ jsxs16("button", {
2833
3093
  type: "button",
2834
3094
  className: cn("skippr:relative skippr:inline-flex skippr:cursor-pointer skippr:items-center skippr:gap-1.5 skippr:rounded-lg skippr:px-3 skippr:py-2 skippr:text-sm skippr:font-medium skippr:transition-all", activeTab === "agenda" ? "skippr:text-foreground" : "skippr:text-muted-foreground skippr:hover:text-foreground"),
2835
3095
  onClick: () => onTabChange("agenda"),
2836
3096
  children: [
2837
- /* @__PURE__ */ jsx17(Calendar, {
3097
+ /* @__PURE__ */ jsx18(Calendar, {
2838
3098
  className: "skippr:size-3.5"
2839
3099
  }),
2840
3100
  "Agenda",
2841
- activeTab === "agenda" && /* @__PURE__ */ jsx17("span", {
3101
+ activeTab === "agenda" && /* @__PURE__ */ jsx18("span", {
2842
3102
  className: "skippr:absolute skippr:-bottom-2 skippr:left-3 skippr:right-3 skippr:h-0.5 skippr:rounded-full skippr:bg-foreground"
2843
3103
  })
2844
3104
  ]
2845
3105
  })
2846
3106
  ]
2847
3107
  }),
2848
- /* @__PURE__ */ jsx17("div", {
3108
+ /* @__PURE__ */ jsx18("div", {
2849
3109
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
2850
- children: isConnected || isStarting ? /* @__PURE__ */ jsx17(ConnectedBody, {
3110
+ children: isConnected || isStarting ? /* @__PURE__ */ jsx18(ConnectedBody, {
2851
3111
  activeTab,
2852
3112
  autoFocusChat
2853
- }) : /* @__PURE__ */ jsx17("div", {
3113
+ }) : /* @__PURE__ */ jsx18("div", {
2854
3114
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col skippr:animate-skippr-tab-fade",
2855
- children: /* @__PURE__ */ jsx17(StartSessionPrompt, {
3115
+ children: /* @__PURE__ */ jsx18(StartSessionPrompt, {
2856
3116
  onStartSession,
2857
3117
  isStarting,
2858
3118
  error,
@@ -2860,7 +3120,7 @@ function AuthenticatedContent({
2860
3120
  })
2861
3121
  }, `${activeTab}-empty`)
2862
3122
  }),
2863
- isConnected && !hideControls && /* @__PURE__ */ jsx17(MeetingControls, {
3123
+ isConnected && !hideControls && /* @__PURE__ */ jsx18(MeetingControls, {
2864
3124
  onHangUp: onDisconnect,
2865
3125
  showScreenShareToggle
2866
3126
  })
@@ -2869,7 +3129,7 @@ function AuthenticatedContent({
2869
3129
  }
2870
3130
  function ConnectedBanner() {
2871
3131
  const remaining = useSessionRemaining();
2872
- return /* @__PURE__ */ jsx17(SessionWarningBanner, {
3132
+ return /* @__PURE__ */ jsx18(SessionWarningBanner, {
2873
3133
  remaining
2874
3134
  });
2875
3135
  }
@@ -2880,17 +3140,17 @@ function ConnectedBody({
2880
3140
  const { allMessages, agentState, sendChatMessage, isSendingChat } = useCombinedMessages();
2881
3141
  const { phases } = usePhaseUpdates();
2882
3142
  if (activeTab === "agenda") {
2883
- return /* @__PURE__ */ jsx17("div", {
3143
+ return /* @__PURE__ */ jsx18("div", {
2884
3144
  className: "skippr:min-h-0 skippr:flex-1 skippr:overflow-y-auto skippr:animate-skippr-tab-fade",
2885
- children: /* @__PURE__ */ jsx17(SessionAgenda, {
3145
+ children: /* @__PURE__ */ jsx18(SessionAgenda, {
2886
3146
  phases,
2887
3147
  hasStarted: allMessages.length > 0 || agentState === "speaking"
2888
3148
  })
2889
3149
  }, "agenda");
2890
3150
  }
2891
- return /* @__PURE__ */ jsx17("div", {
3151
+ return /* @__PURE__ */ jsx18("div", {
2892
3152
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col skippr:animate-skippr-tab-fade",
2893
- children: /* @__PURE__ */ jsx17(MessageList, {
3153
+ children: /* @__PURE__ */ jsx18(MessageList, {
2894
3154
  messages: allMessages,
2895
3155
  isStreaming: agentState === "speaking",
2896
3156
  sendChatMessage,
@@ -2901,46 +3161,55 @@ function ConnectedBody({
2901
3161
  }
2902
3162
 
2903
3163
  // src/components/SidebarTrigger.tsx
2904
- import { jsx as jsx18 } from "react/jsx-runtime";
3164
+ import { jsx as jsx19 } from "react/jsx-runtime";
2905
3165
  function SidebarTrigger() {
2906
3166
  const { isPanelOpen, togglePanel, minimizePanel, minimizable, position, isMinimized } = useLiveAgent();
2907
3167
  if (isMinimized)
2908
3168
  return null;
2909
3169
  const handleClick = isPanelOpen && minimizable ? minimizePanel : togglePanel;
2910
- return /* @__PURE__ */ jsx18("button", {
3170
+ return /* @__PURE__ */ jsx19("button", {
2911
3171
  type: "button",
2912
3172
  onClick: handleClick,
2913
3173
  title: isPanelOpen ? "Close chat" : "Open chat",
2914
3174
  "aria-label": isPanelOpen ? "Close chat" : "Open chat",
2915
3175
  className: cn("skippr:fixed skippr:bottom-6 skippr:z-[9998]", "skippr:flex skippr:size-12 skippr:items-center skippr:justify-center", "skippr:rounded-[14px] skippr:bg-bubble skippr:text-white", "skippr:shadow-[0_4px_16px_rgba(45,43,61,0.45),0_2px_4px_rgba(0,0,0,0.1)] skippr:transition-all", "skippr:cursor-pointer skippr:hover:brightness-110 skippr:hover:-translate-y-0.5 skippr:active:translate-y-0", position === "right" ? "skippr:right-6" : "skippr:left-6"),
2916
- children: isPanelOpen ? /* @__PURE__ */ jsx18(ChevronDown, {
3176
+ children: isPanelOpen ? /* @__PURE__ */ jsx19(ChevronDown, {
2917
3177
  className: "skippr:size-5"
2918
- }) : /* @__PURE__ */ jsx18(Logo, {
3178
+ }) : /* @__PURE__ */ jsx19(Logo, {
2919
3179
  className: "skippr:size-7"
2920
3180
  })
2921
3181
  });
2922
3182
  }
2923
3183
 
2924
3184
  // src/components/LiveAgent.tsx
2925
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
2926
- function LiveAgent({
2927
- agentId,
2928
- authToken: authTokenProp,
2929
- appKey,
2930
- userToken,
2931
- position = "right",
2932
- variant = "floating",
2933
- minimizable = true,
2934
- defaultOpen = false,
2935
- welcomeMessage,
2936
- hideControls = false,
2937
- hideHeader = false,
2938
- startSessionLabel = "Talk to Skippr",
2939
- autoFocusChat = true,
2940
- showAgentStateBanner = true,
2941
- captureMode = "screenshare",
2942
- children
2943
- }) {
3185
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
3186
+ function LiveAgent(props) {
3187
+ const {
3188
+ agentId,
3189
+ authToken: authTokenProp,
3190
+ appKey,
3191
+ userToken,
3192
+ position = "right",
3193
+ variant = "floating",
3194
+ minimizable = true,
3195
+ defaultOpen = false,
3196
+ welcomeMessage,
3197
+ hideControls = false,
3198
+ hideHeader = false,
3199
+ startSessionLabel = "Talk to Skippr",
3200
+ autoFocusChat = true,
3201
+ showAgentStateBanner = true,
3202
+ children
3203
+ } = props;
3204
+ const captureMode = props.captureMode ?? "screenshare";
3205
+ let agentControls;
3206
+ if ("agentControls" in props && props.agentControls) {
3207
+ if (captureMode === "auto") {
3208
+ agentControls = props.agentControls;
3209
+ } else {
3210
+ console.warn('[Skippr] agentControls requires captureMode: "auto"');
3211
+ }
3212
+ }
2944
3213
  const auth = useAuth({ appKey });
2945
3214
  const effectiveAuthToken = authTokenProp || auth.authToken || undefined;
2946
3215
  const {
@@ -2955,16 +3224,17 @@ function LiveAgent({
2955
3224
  } = useSession({
2956
3225
  agentId,
2957
3226
  captureMode,
3227
+ agentControls,
2958
3228
  authToken: effectiveAuthToken,
2959
3229
  appKey,
2960
3230
  userToken
2961
3231
  });
2962
- const [isPanelOpen, setIsPanelOpen] = useState8(defaultOpen);
2963
- const [isMinimized, setIsMinimized] = useState8(minimizable && !defaultOpen);
2964
- const [sidebarTab, setSidebarTab] = useState8("agenda");
2965
- const [welcomeDismissed, setWelcomeDismissed] = useState8(false);
2966
- const dismissWelcome = useCallback6(() => setWelcomeDismissed(true), []);
2967
- const [currentPosition, setCurrentPosition] = useState8(() => {
3232
+ const [isPanelOpen, setIsPanelOpen] = useState9(defaultOpen);
3233
+ const [isMinimized, setIsMinimized] = useState9(minimizable && !defaultOpen);
3234
+ const [sidebarTab, setSidebarTab] = useState9("agenda");
3235
+ const [welcomeDismissed, setWelcomeDismissed] = useState9(false);
3236
+ const dismissWelcome = useCallback7(() => setWelcomeDismissed(true), []);
3237
+ const [currentPosition, setCurrentPosition] = useState9(() => {
2968
3238
  try {
2969
3239
  const saved = localStorage.getItem("skippr_widget_position");
2970
3240
  if (saved === "left" || saved === "right")
@@ -2972,20 +3242,20 @@ function LiveAgent({
2972
3242
  } catch {}
2973
3243
  return position;
2974
3244
  });
2975
- const setPositionWithPersist = useCallback6((pos) => {
3245
+ const setPositionWithPersist = useCallback7((pos) => {
2976
3246
  setCurrentPosition(pos);
2977
3247
  try {
2978
3248
  localStorage.setItem("skippr_widget_position", pos);
2979
3249
  } catch {}
2980
3250
  }, []);
2981
- const openPanel = useCallback6(() => setIsPanelOpen(true), []);
2982
- const closePanel = useCallback6(() => setIsPanelOpen(false), []);
2983
- const togglePanel = useCallback6(() => setIsPanelOpen((prev) => !prev), []);
2984
- const expandPanel = useCallback6(() => {
3251
+ const openPanel = useCallback7(() => setIsPanelOpen(true), []);
3252
+ const closePanel = useCallback7(() => setIsPanelOpen(false), []);
3253
+ const togglePanel = useCallback7(() => setIsPanelOpen((prev) => !prev), []);
3254
+ const expandPanel = useCallback7(() => {
2985
3255
  setIsMinimized(false);
2986
3256
  setIsPanelOpen(true);
2987
3257
  }, []);
2988
- const minimizePanel = useCallback6(() => {
3258
+ const minimizePanel = useCallback7(() => {
2989
3259
  if (!minimizable)
2990
3260
  return;
2991
3261
  setIsMinimized(true);
@@ -2993,8 +3263,8 @@ function LiveAgent({
2993
3263
  }, [minimizable]);
2994
3264
  const isConnected = connection !== null;
2995
3265
  const isAuthenticated = !!userToken || !!authTokenProp || auth.isAuthenticated;
2996
- const prevConnectionRef = useRef7(connection);
2997
- useEffect13(() => {
3266
+ const prevConnectionRef = useRef8(connection);
3267
+ useEffect14(() => {
2998
3268
  const connectionChanged = prevConnectionRef.current !== connection;
2999
3269
  prevConnectionRef.current = connection;
3000
3270
  if (connectionChanged && minimizable) {
@@ -3032,7 +3302,8 @@ function LiveAgent({
3032
3302
  sidebarTab,
3033
3303
  setSidebarTab,
3034
3304
  autoFocusChat,
3035
- captureMode
3305
+ captureMode,
3306
+ agentControls
3036
3307
  }), [
3037
3308
  connection,
3038
3309
  shouldConnect,
@@ -3062,33 +3333,35 @@ function LiveAgent({
3062
3333
  auth.isSubmitting,
3063
3334
  sidebarTab,
3064
3335
  autoFocusChat,
3065
- captureMode
3336
+ captureMode,
3337
+ agentControls
3066
3338
  ]);
3067
- return /* @__PURE__ */ jsx19(LiveAgentContext.Provider, {
3339
+ return /* @__PURE__ */ jsx20(LiveAgentContext.Provider, {
3068
3340
  value: ctx,
3069
- children: /* @__PURE__ */ jsxs16(LiveKitRoom, {
3341
+ children: /* @__PURE__ */ jsxs17(LiveKitRoom, {
3070
3342
  serverUrl: connection?.livekitUrl,
3071
3343
  token: connection?.token,
3072
3344
  connect: shouldConnect,
3073
3345
  audio: true,
3074
3346
  onDisconnected: disconnect,
3075
3347
  children: [
3076
- connection && /* @__PURE__ */ jsx19(RoomAudioRenderer, {}),
3077
- connection && captureMode === "screenshare" && /* @__PURE__ */ jsx19(AutoStartMedia, {
3348
+ connection && /* @__PURE__ */ jsx20(RoomAudioRenderer, {}),
3349
+ connection && captureMode === "screenshare" && /* @__PURE__ */ jsx20(AutoStartMedia, {
3078
3350
  pendingScreenStream
3079
3351
  }),
3080
- connection && captureMode === "auto" && /* @__PURE__ */ jsx19(DomCapture, {}),
3081
- /* @__PURE__ */ jsxs16("div", {
3352
+ connection && captureMode === "auto" && /* @__PURE__ */ jsx20(DomCapture, {}),
3353
+ connection && captureMode === "auto" && agentControls?.highlight && /* @__PURE__ */ jsx20(HighlightOverlay, {}),
3354
+ /* @__PURE__ */ jsxs17("div", {
3082
3355
  id: WIDGET_ROOT_ID,
3083
3356
  children: [
3084
- showAgentStateBanner && /* @__PURE__ */ jsx19(AgentStateBanner, {}),
3085
- isMinimized && /* @__PURE__ */ jsx19(MinimizedBubble, {
3357
+ showAgentStateBanner && /* @__PURE__ */ jsx20(AgentStateBanner, {}),
3358
+ isMinimized && /* @__PURE__ */ jsx20(MinimizedBubble, {
3086
3359
  welcomeMessage,
3087
3360
  welcomeDismissed,
3088
3361
  onDismissWelcome: dismissWelcome
3089
3362
  }),
3090
- /* @__PURE__ */ jsx19(SidebarTrigger, {}),
3091
- /* @__PURE__ */ jsx19(Sidebar, {
3363
+ /* @__PURE__ */ jsx20(SidebarTrigger, {}),
3364
+ /* @__PURE__ */ jsx20(Sidebar, {
3092
3365
  hideControls,
3093
3366
  hideHeader,
3094
3367
  startSessionLabel