@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.
- package/README.md +3 -1
- package/dist/esm/lib-exports.js +545 -272
- package/dist/skippr-sdk.js +129 -129
- package/dist/types/components/HighlightOverlay.d.ts +1 -0
- package/dist/types/components/LiveAgent.d.ts +10 -4
- package/dist/types/context/LiveAgentContext.d.ts +4 -0
- package/dist/types/hooks/useSession.d.ts +3 -2
- package/dist/types/lib/constants.d.ts +1 -0
- package/package.json +1 -1
package/dist/esm/lib-exports.js
CHANGED
|
@@ -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
|
|
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({
|
|
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
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1871
|
+
/* @__PURE__ */ jsxs3("g", {
|
|
1612
1872
|
clipPath: `url(#${clipId})`,
|
|
1613
1873
|
children: [
|
|
1614
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1902
|
+
/* @__PURE__ */ jsxs3("defs", {
|
|
1643
1903
|
children: [
|
|
1644
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1912
|
+
/* @__PURE__ */ jsx3("stop", {
|
|
1653
1913
|
offset: "0.473958",
|
|
1654
1914
|
stopColor: "white"
|
|
1655
1915
|
}),
|
|
1656
|
-
/* @__PURE__ */
|
|
1916
|
+
/* @__PURE__ */ jsx3("stop", {
|
|
1657
1917
|
offset: "1",
|
|
1658
1918
|
stopColor: "#52FFF9"
|
|
1659
1919
|
})
|
|
1660
1920
|
]
|
|
1661
1921
|
}),
|
|
1662
|
-
/* @__PURE__ */
|
|
1922
|
+
/* @__PURE__ */ jsx3("clipPath", {
|
|
1663
1923
|
id: clipId,
|
|
1664
|
-
children: /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
1944
|
+
return /* @__PURE__ */ jsxs4("span", {
|
|
1685
1945
|
className: "skippr:relative skippr:inline-flex skippr:group",
|
|
1686
1946
|
children: [
|
|
1687
1947
|
children,
|
|
1688
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
1965
|
+
return /* @__PURE__ */ jsxs5(Fragment3, {
|
|
1706
1966
|
children: [
|
|
1707
|
-
/* @__PURE__ */
|
|
1967
|
+
/* @__PURE__ */ jsx5(Tooltip, {
|
|
1708
1968
|
label: isMuted ? "Unmute" : "Mute",
|
|
1709
1969
|
align: tooltipAlign,
|
|
1710
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
1975
|
+
children: isMuted ? /* @__PURE__ */ jsx5(MicOff, {
|
|
1716
1976
|
className: "skippr:size-5"
|
|
1717
|
-
}) : /* @__PURE__ */
|
|
1977
|
+
}) : /* @__PURE__ */ jsx5(Mic, {
|
|
1718
1978
|
className: "skippr:size-5"
|
|
1719
1979
|
})
|
|
1720
1980
|
})
|
|
1721
1981
|
}),
|
|
1722
|
-
showScreenShareToggle && /* @__PURE__ */
|
|
1982
|
+
showScreenShareToggle && /* @__PURE__ */ jsx5(Tooltip, {
|
|
1723
1983
|
label: isScreenSharing ? "Stop sharing" : "Share screen",
|
|
1724
1984
|
align: tooltipAlign,
|
|
1725
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
1990
|
+
children: isScreenSharing ? /* @__PURE__ */ jsx5(MonitorOff, {
|
|
1731
1991
|
className: "skippr:size-5"
|
|
1732
|
-
}) : /* @__PURE__ */
|
|
1992
|
+
}) : /* @__PURE__ */ jsx5(Monitor, {
|
|
1733
1993
|
className: "skippr:size-5"
|
|
1734
1994
|
})
|
|
1735
1995
|
})
|
|
1736
1996
|
}),
|
|
1737
|
-
/* @__PURE__ */
|
|
1997
|
+
/* @__PURE__ */ jsx5(Tooltip, {
|
|
1738
1998
|
label: "End session",
|
|
1739
1999
|
align: tooltipAlign,
|
|
1740
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
2005
|
+
children: /* @__PURE__ */ jsx5(PhoneOff, {
|
|
1746
2006
|
className: "skippr:size-5"
|
|
1747
2007
|
})
|
|
1748
2008
|
})
|
|
1749
2009
|
}),
|
|
1750
|
-
/* @__PURE__ */
|
|
2010
|
+
/* @__PURE__ */ jsx5(Tooltip, {
|
|
1751
2011
|
label: "Open chat & transcript",
|
|
1752
2012
|
align: tooltipAlign,
|
|
1753
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2029
|
+
return /* @__PURE__ */ jsx5(Tooltip, {
|
|
1770
2030
|
label: "Open Skippr assistant",
|
|
1771
2031
|
align: tooltipAlign,
|
|
1772
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
2038
|
+
/* @__PURE__ */ jsx5(Logo, {
|
|
1779
2039
|
className: "skippr:relative skippr:z-10 skippr:size-7"
|
|
1780
2040
|
}),
|
|
1781
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
2053
|
+
useEffect6(() => {
|
|
1794
2054
|
const timer = setTimeout(onDismiss, 5000);
|
|
1795
2055
|
return () => clearTimeout(timer);
|
|
1796
2056
|
}, [onDismiss]);
|
|
1797
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2080
|
+
welcomeMessage && !inSession && !welcomeDismissed && /* @__PURE__ */ jsx5(WelcomeBubble, {
|
|
1821
2081
|
message: welcomeMessage,
|
|
1822
2082
|
position,
|
|
1823
2083
|
onDismiss: onDismissWelcome
|
|
1824
2084
|
}),
|
|
1825
|
-
inSession ? /* @__PURE__ */
|
|
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
|
|
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
|
|
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
|
|
2177
|
+
import { useEffect as useEffect7, useState as useState4 } from "react";
|
|
1918
2178
|
function useAgentState(attributeKey, parse, initial) {
|
|
1919
|
-
const [value, setValue] =
|
|
2179
|
+
const [value, setValue] = useState4(initial);
|
|
1920
2180
|
const remoteParticipants = useRemoteParticipants();
|
|
1921
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
1990
|
-
const [remaining, setRemaining] =
|
|
1991
|
-
|
|
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
|
|
2268
|
+
import { useEffect as useEffect9, useState as useState6 } from "react";
|
|
2009
2269
|
function useElapsedSeconds(isRunning) {
|
|
2010
|
-
const [elapsed, setElapsed] =
|
|
2011
|
-
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2298
|
+
/* @__PURE__ */ jsxs6("div", {
|
|
2039
2299
|
className: "skippr:flex skippr:items-center skippr:gap-2",
|
|
2040
2300
|
children: [
|
|
2041
|
-
isConnected && /* @__PURE__ */
|
|
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__ */
|
|
2304
|
+
/* @__PURE__ */ jsxs6("span", {
|
|
2045
2305
|
className: "skippr:relative skippr:flex skippr:size-1.5",
|
|
2046
2306
|
children: [
|
|
2047
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2341
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2082
2342
|
function LoadingDots({ label }) {
|
|
2083
|
-
return /* @__PURE__ */
|
|
2343
|
+
return /* @__PURE__ */ jsxs7("div", {
|
|
2084
2344
|
className: "skippr:flex skippr:items-center skippr:gap-2 skippr:py-4",
|
|
2085
2345
|
children: [
|
|
2086
|
-
/* @__PURE__ */
|
|
2346
|
+
/* @__PURE__ */ jsxs7("div", {
|
|
2087
2347
|
className: "skippr:flex skippr:gap-1",
|
|
2088
2348
|
children: [
|
|
2089
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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__ */
|
|
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
|
|
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] =
|
|
2146
|
-
const [email, setEmail] =
|
|
2147
|
-
const handleRequestOtp =
|
|
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 =
|
|
2412
|
+
const handleVerifyOtp = useCallback6(async (code) => {
|
|
2153
2413
|
await verifyOtp(email, code);
|
|
2154
2414
|
}, [verifyOtp, email]);
|
|
2155
|
-
const handleBack =
|
|
2415
|
+
const handleBack = useCallback6(() => {
|
|
2156
2416
|
setStep("email");
|
|
2157
2417
|
}, []);
|
|
2158
|
-
const handleResend =
|
|
2418
|
+
const handleResend = useCallback6(async () => {
|
|
2159
2419
|
await requestOtp(email);
|
|
2160
2420
|
}, [requestOtp, email]);
|
|
2161
2421
|
if (step === "otp") {
|
|
2162
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2448
|
+
/* @__PURE__ */ jsxs8("div", {
|
|
2189
2449
|
className: "skippr:mb-4 skippr:text-center",
|
|
2190
2450
|
children: [
|
|
2191
|
-
/* @__PURE__ */
|
|
2451
|
+
/* @__PURE__ */ jsx9(Mail, {
|
|
2192
2452
|
className: "skippr:mx-auto skippr:mb-2 skippr:size-6 skippr:text-primary"
|
|
2193
2453
|
}),
|
|
2194
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2464
|
+
/* @__PURE__ */ jsxs8("form", {
|
|
2205
2465
|
onSubmit: handleSubmit,
|
|
2206
2466
|
className: "skippr:flex skippr:flex-col skippr:gap-3",
|
|
2207
2467
|
children: [
|
|
2208
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2477
|
+
/* @__PURE__ */ jsx9(Button, {
|
|
2218
2478
|
type: "submit",
|
|
2219
2479
|
disabled: isSubmitting || !email.trim(),
|
|
2220
2480
|
className: "skippr:w-full",
|
|
2221
|
-
children: isSubmitting ? /* @__PURE__ */
|
|
2481
|
+
children: isSubmitting ? /* @__PURE__ */ jsx9(LoaderCircle, {
|
|
2222
2482
|
className: "skippr:size-4 skippr:animate-spin"
|
|
2223
2483
|
}) : "Continue"
|
|
2224
2484
|
}),
|
|
2225
|
-
error && /* @__PURE__ */
|
|
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] =
|
|
2236
|
-
const [resendCooldown, setResendCooldown] =
|
|
2237
|
-
const inputRefs =
|
|
2238
|
-
const submittedRef =
|
|
2239
|
-
|
|
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
|
-
|
|
2502
|
+
useEffect10(() => {
|
|
2243
2503
|
if (error)
|
|
2244
2504
|
submittedRef.current = false;
|
|
2245
2505
|
}, [error]);
|
|
2246
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
2568
|
+
/* @__PURE__ */ jsxs8("div", {
|
|
2309
2569
|
className: "skippr:mb-4 skippr:text-center",
|
|
2310
2570
|
children: [
|
|
2311
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2588
|
+
/* @__PURE__ */ jsxs8("form", {
|
|
2329
2589
|
onSubmit: handleSubmit,
|
|
2330
2590
|
className: "skippr:flex skippr:flex-col skippr:gap-3",
|
|
2331
2591
|
children: [
|
|
2332
|
-
/* @__PURE__ */
|
|
2592
|
+
/* @__PURE__ */ jsx9("div", {
|
|
2333
2593
|
className: "skippr:flex skippr:justify-center skippr:gap-1.5",
|
|
2334
|
-
children: digits.map((digit, index2) => /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2617
|
+
children: isSubmitting ? /* @__PURE__ */ jsx9(LoaderCircle, {
|
|
2358
2618
|
className: "skippr:size-4 skippr:animate-spin"
|
|
2359
2619
|
}) : "Verify"
|
|
2360
2620
|
}),
|
|
2361
|
-
/* @__PURE__ */
|
|
2621
|
+
/* @__PURE__ */ jsxs8("div", {
|
|
2362
2622
|
className: "skippr:flex skippr:items-center skippr:justify-between skippr:text-xs",
|
|
2363
2623
|
children: [
|
|
2364
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2654
|
+
/* @__PURE__ */ jsxs9("div", {
|
|
2395
2655
|
className: "skippr:flex skippr:items-center skippr:justify-center skippr:gap-3",
|
|
2396
2656
|
children: [
|
|
2397
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2662
|
+
children: isMuted ? /* @__PURE__ */ jsx10(MicOff, {
|
|
2403
2663
|
className: "skippr:size-5"
|
|
2404
|
-
}) : /* @__PURE__ */
|
|
2664
|
+
}) : /* @__PURE__ */ jsx10(Mic, {
|
|
2405
2665
|
className: "skippr:size-5"
|
|
2406
2666
|
})
|
|
2407
2667
|
}),
|
|
2408
|
-
showScreenShareToggle && /* @__PURE__ */
|
|
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__ */
|
|
2673
|
+
children: isScreenSharing ? /* @__PURE__ */ jsx10(MonitorOff, {
|
|
2414
2674
|
className: "skippr:size-5"
|
|
2415
|
-
}) : /* @__PURE__ */
|
|
2675
|
+
}) : /* @__PURE__ */ jsx10(Monitor, {
|
|
2416
2676
|
className: "skippr:size-5"
|
|
2417
2677
|
})
|
|
2418
2678
|
}),
|
|
2419
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2684
|
+
children: /* @__PURE__ */ jsx10(PhoneOff, {
|
|
2425
2685
|
className: "skippr:size-5"
|
|
2426
2686
|
})
|
|
2427
2687
|
})
|
|
2428
2688
|
]
|
|
2429
2689
|
}),
|
|
2430
|
-
/* @__PURE__ */
|
|
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
|
|
2699
|
+
import { useEffect as useEffect12, useRef as useRef7 } from "react";
|
|
2440
2700
|
|
|
2441
2701
|
// src/components/ChatInput.tsx
|
|
2442
|
-
import { useEffect as
|
|
2443
|
-
import { jsx as
|
|
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] =
|
|
2447
|
-
const textareaRef =
|
|
2706
|
+
const [inputText, setInputText] = useState8("");
|
|
2707
|
+
const textareaRef = useRef6(null);
|
|
2448
2708
|
const canSend = inputText.trim().length > 0 && !isSendingChat;
|
|
2449
|
-
|
|
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__ */
|
|
2740
|
+
return /* @__PURE__ */ jsx11("form", {
|
|
2481
2741
|
onSubmit: handleSubmit,
|
|
2482
2742
|
className: "skippr:border-t skippr:border-border skippr:p-3",
|
|
2483
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2786
|
+
children: /* @__PURE__ */ jsx12(Sparkles, {
|
|
2527
2787
|
className: "skippr:size-3.5 skippr:text-primary-foreground"
|
|
2528
2788
|
})
|
|
2529
2789
|
}),
|
|
2530
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2808
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2549
2809
|
function TypingIndicator() {
|
|
2550
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2815
|
+
children: /* @__PURE__ */ jsx13(Sparkles, {
|
|
2556
2816
|
className: "skippr:size-3.5 skippr:text-primary-foreground"
|
|
2557
2817
|
})
|
|
2558
2818
|
}),
|
|
2559
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2822
|
+
/* @__PURE__ */ jsx13("span", {
|
|
2563
2823
|
children: "Agent is analyzing your screen"
|
|
2564
2824
|
}),
|
|
2565
|
-
/* @__PURE__ */
|
|
2825
|
+
/* @__PURE__ */ jsxs12("span", {
|
|
2566
2826
|
className: "skippr:inline-flex skippr:items-center skippr:gap-[2px]",
|
|
2567
2827
|
children: [
|
|
2568
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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 =
|
|
2854
|
+
const scrollRef = useRef7(null);
|
|
2595
2855
|
const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
|
|
2596
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2866
|
+
messages.length === 0 && !showTyping && /* @__PURE__ */ jsx14(LoadingDots, {
|
|
2607
2867
|
label: "Waiting for conversation to begin..."
|
|
2608
2868
|
}),
|
|
2609
|
-
messages.map((message) => /* @__PURE__ */
|
|
2869
|
+
messages.map((message) => /* @__PURE__ */ jsx14(ChatMessage, {
|
|
2610
2870
|
message
|
|
2611
2871
|
}, message.id)),
|
|
2612
|
-
showTyping && /* @__PURE__ */
|
|
2613
|
-
/* @__PURE__ */
|
|
2872
|
+
showTyping && /* @__PURE__ */ jsx14(TypingIndicator, {}),
|
|
2873
|
+
/* @__PURE__ */ jsx14("div", {
|
|
2614
2874
|
ref: scrollRef
|
|
2615
2875
|
})
|
|
2616
2876
|
]
|
|
2617
2877
|
}),
|
|
2618
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
2891
|
+
return /* @__PURE__ */ jsx15("div", {
|
|
2632
2892
|
className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
|
|
2633
|
-
children: /* @__PURE__ */
|
|
2893
|
+
children: /* @__PURE__ */ jsx15(LoadingDots, {
|
|
2634
2894
|
label: "Waiting for agenda to load..."
|
|
2635
2895
|
})
|
|
2636
2896
|
});
|
|
2637
2897
|
}
|
|
2638
|
-
return /* @__PURE__ */
|
|
2898
|
+
return /* @__PURE__ */ jsx15("div", {
|
|
2639
2899
|
className: "skippr:flex-1 skippr:overflow-y-auto skippr:px-4 skippr:py-4",
|
|
2640
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2908
|
+
/* @__PURE__ */ jsx15("div", {
|
|
2649
2909
|
className: "skippr:mt-0.5",
|
|
2650
|
-
children: isCompleted ? /* @__PURE__ */
|
|
2910
|
+
children: isCompleted ? /* @__PURE__ */ jsx15(CircleCheck, {
|
|
2651
2911
|
className: "skippr:size-4 skippr:text-chart-3"
|
|
2652
|
-
}) : isActive ? /* @__PURE__ */
|
|
2912
|
+
}) : isActive ? /* @__PURE__ */ jsx15(Circle, {
|
|
2653
2913
|
className: "skippr:size-4 skippr:fill-primary/30 skippr:text-primary"
|
|
2654
|
-
}) : /* @__PURE__ */
|
|
2914
|
+
}) : /* @__PURE__ */ jsx15(Circle, {
|
|
2655
2915
|
className: "skippr:size-4 skippr:text-muted-foreground/30"
|
|
2656
2916
|
})
|
|
2657
2917
|
}),
|
|
2658
|
-
/* @__PURE__ */
|
|
2918
|
+
/* @__PURE__ */ jsxs14("div", {
|
|
2659
2919
|
className: "skippr:min-w-0 skippr:flex-1",
|
|
2660
2920
|
children: [
|
|
2661
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
2773
|
-
!isAuthenticated && isValidating ? /* @__PURE__ */
|
|
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__ */
|
|
3035
|
+
children: /* @__PURE__ */ jsx18(LoadingDots, {
|
|
2776
3036
|
label: "Loading..."
|
|
2777
3037
|
})
|
|
2778
|
-
}) : !isAuthenticated ? /* @__PURE__ */
|
|
3038
|
+
}) : !isAuthenticated ? /* @__PURE__ */ jsx18(LoginFlow, {
|
|
2779
3039
|
requestOtp,
|
|
2780
3040
|
verifyOtp,
|
|
2781
3041
|
error: authError,
|
|
2782
3042
|
isSubmitting: isAuthSubmitting
|
|
2783
|
-
}) : /* @__PURE__ */
|
|
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__ */
|
|
3072
|
+
return /* @__PURE__ */ jsxs16(Fragment4, {
|
|
2813
3073
|
children: [
|
|
2814
|
-
isConnected && /* @__PURE__ */
|
|
2815
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3083
|
+
/* @__PURE__ */ jsx18(MessageCircle, {
|
|
2824
3084
|
className: "skippr:size-3.5"
|
|
2825
3085
|
}),
|
|
2826
3086
|
"Chat",
|
|
2827
|
-
activeTab === "chat" && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3097
|
+
/* @__PURE__ */ jsx18(Calendar, {
|
|
2838
3098
|
className: "skippr:size-3.5"
|
|
2839
3099
|
}),
|
|
2840
3100
|
"Agenda",
|
|
2841
|
-
activeTab === "agenda" && /* @__PURE__ */
|
|
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__ */
|
|
3108
|
+
/* @__PURE__ */ jsx18("div", {
|
|
2849
3109
|
className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
|
|
2850
|
-
children: isConnected || isStarting ? /* @__PURE__ */
|
|
3110
|
+
children: isConnected || isStarting ? /* @__PURE__ */ jsx18(ConnectedBody, {
|
|
2851
3111
|
activeTab,
|
|
2852
3112
|
autoFocusChat
|
|
2853
|
-
}) : /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
3176
|
+
children: isPanelOpen ? /* @__PURE__ */ jsx19(ChevronDown, {
|
|
2917
3177
|
className: "skippr:size-5"
|
|
2918
|
-
}) : /* @__PURE__ */
|
|
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
|
|
2926
|
-
function LiveAgent({
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
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] =
|
|
2963
|
-
const [isMinimized, setIsMinimized] =
|
|
2964
|
-
const [sidebarTab, setSidebarTab] =
|
|
2965
|
-
const [welcomeDismissed, setWelcomeDismissed] =
|
|
2966
|
-
const dismissWelcome =
|
|
2967
|
-
const [currentPosition, setCurrentPosition] =
|
|
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 =
|
|
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 =
|
|
2982
|
-
const closePanel =
|
|
2983
|
-
const togglePanel =
|
|
2984
|
-
const expandPanel =
|
|
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 =
|
|
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 =
|
|
2997
|
-
|
|
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__ */
|
|
3339
|
+
return /* @__PURE__ */ jsx20(LiveAgentContext.Provider, {
|
|
3068
3340
|
value: ctx,
|
|
3069
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
3077
|
-
connection && captureMode === "screenshare" && /* @__PURE__ */
|
|
3348
|
+
connection && /* @__PURE__ */ jsx20(RoomAudioRenderer, {}),
|
|
3349
|
+
connection && captureMode === "screenshare" && /* @__PURE__ */ jsx20(AutoStartMedia, {
|
|
3078
3350
|
pendingScreenStream
|
|
3079
3351
|
}),
|
|
3080
|
-
connection && captureMode === "auto" && /* @__PURE__ */
|
|
3081
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3085
|
-
isMinimized && /* @__PURE__ */
|
|
3357
|
+
showAgentStateBanner && /* @__PURE__ */ jsx20(AgentStateBanner, {}),
|
|
3358
|
+
isMinimized && /* @__PURE__ */ jsx20(MinimizedBubble, {
|
|
3086
3359
|
welcomeMessage,
|
|
3087
3360
|
welcomeDismissed,
|
|
3088
3361
|
onDismissWelcome: dismissWelcome
|
|
3089
3362
|
}),
|
|
3090
|
-
/* @__PURE__ */
|
|
3091
|
-
/* @__PURE__ */
|
|
3363
|
+
/* @__PURE__ */ jsx20(SidebarTrigger, {}),
|
|
3364
|
+
/* @__PURE__ */ jsx20(Sidebar, {
|
|
3092
3365
|
hideControls,
|
|
3093
3366
|
hideHeader,
|
|
3094
3367
|
startSessionLabel
|