@skippr/live-agent-sdk 0.30.0 → 0.31.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.
@@ -316,632 +316,235 @@ var DOM_SNAPSHOT_TOPIC = "skippr.dom-snapshot";
316
316
  var DOM_EVENTS_TOPIC = "skippr.dom-events";
317
317
  var HIGHLIGHT_TOPIC = "skippr.highlight";
318
318
  var NAME_MAX_CHARS = 80;
319
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/createLucideIcon.js
320
- import { forwardRef as forwardRef2, createElement as createElement3 } from "react";
321
-
322
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
323
- var mergeClasses = (...classes) => classes.filter((className, index, array) => {
324
- return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
325
- }).join(" ").trim();
326
-
327
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js
328
- var toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
329
-
330
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js
331
- var toCamelCase = (string) => string.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase());
332
319
 
333
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js
334
- var toPascalCase = (string) => {
335
- const camelCase = toCamelCase(string);
336
- return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
337
- };
320
+ // src/components/AutoStartMedia.tsx
321
+ import { useConnectionState, useLocalParticipant } from "@livekit/components-react/hooks";
322
+ import { ConnectionState, Track } from "livekit-client";
323
+ import { useEffect as useEffect3, useRef } from "react";
324
+ function AutoStartMedia({ pendingScreenStream }) {
325
+ const { localParticipant } = useLocalParticipant();
326
+ const connectionState = useConnectionState();
327
+ const didStartRef = useRef(false);
328
+ useEffect3(() => {
329
+ if (didStartRef.current)
330
+ return;
331
+ if (connectionState !== ConnectionState.Connected)
332
+ return;
333
+ didStartRef.current = true;
334
+ localParticipant.setMicrophoneEnabled(true).catch((error) => console.error("Failed to enable microphone:", error));
335
+ if (pendingScreenStream) {
336
+ const videoTrack = pendingScreenStream.getVideoTracks()[0];
337
+ if (videoTrack) {
338
+ videoTrack.contentHint = "detail";
339
+ localParticipant.publishTrack(videoTrack, { source: Track.Source.ScreenShare }).catch((error) => {
340
+ console.error("Failed to publish screen share track:", error);
341
+ for (const track of pendingScreenStream.getTracks())
342
+ track.stop();
343
+ });
344
+ }
345
+ }
346
+ }, [connectionState, localParticipant, pendingScreenStream]);
347
+ return null;
348
+ }
338
349
 
339
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/Icon.js
340
- import { forwardRef, createElement as createElement2 } from "react";
350
+ // src/components/DomCapture.tsx
351
+ import { useConnectionState as useConnectionState2, useLocalParticipant as useLocalParticipant2 } from "@livekit/components-react/hooks";
352
+ import { ConnectionState as ConnectionState2, ScreenSharePresets, Track as Track2 } from "livekit-client";
353
+ import { useEffect as useEffect4, useRef as useRef2 } from "react";
341
354
 
342
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/defaultAttributes.js
343
- var defaultAttributes = {
344
- xmlns: "http://www.w3.org/2000/svg",
345
- width: 24,
346
- height: 24,
347
- viewBox: "0 0 24 24",
348
- fill: "none",
349
- stroke: "currentColor",
350
- strokeWidth: 2,
351
- strokeLinecap: "round",
352
- strokeLinejoin: "round"
355
+ // src/capture/a11yUtils.ts
356
+ var ROLE_BY_TAG = {
357
+ a: "link",
358
+ button: "button",
359
+ input: "input",
360
+ select: "select",
361
+ textarea: "textarea",
362
+ label: "label",
363
+ nav: "navigation",
364
+ main: "main",
365
+ header: "header",
366
+ footer: "footer",
367
+ aside: "complementary",
368
+ form: "form",
369
+ h1: "heading",
370
+ h2: "heading",
371
+ h3: "heading",
372
+ h4: "heading",
373
+ h5: "heading",
374
+ h6: "heading",
375
+ img: "image",
376
+ ul: "list",
377
+ ol: "list",
378
+ li: "listitem",
379
+ table: "table",
380
+ tr: "row",
381
+ td: "cell",
382
+ th: "columnheader",
383
+ video: "video",
384
+ iframe: "iframe",
385
+ canvas: "canvas",
386
+ audio: "audio",
387
+ embed: "embed",
388
+ object: "object"
353
389
  };
354
-
355
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js
356
- var hasA11yProp = (props) => {
357
- for (const prop in props) {
358
- if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
359
- return true;
390
+ function inferRole(element) {
391
+ const explicitRole = element.getAttribute("role");
392
+ if (explicitRole)
393
+ return explicitRole;
394
+ const tagName = element.tagName.toLowerCase();
395
+ if (tagName === "input") {
396
+ const inputType = element.type;
397
+ if (inputType === "checkbox")
398
+ return "checkbox";
399
+ if (inputType === "radio")
400
+ return "radio";
401
+ if (inputType === "submit" || inputType === "button")
402
+ return "button";
403
+ return "input";
404
+ }
405
+ return ROLE_BY_TAG[tagName] ?? null;
406
+ }
407
+ function accessibleName(element, options = {}) {
408
+ const ariaLabel = element.getAttribute("aria-label");
409
+ if (ariaLabel)
410
+ return ariaLabel.trim().slice(0, NAME_MAX_CHARS);
411
+ if (!options.quick) {
412
+ const labelledBy = element.getAttribute("aria-labelledby");
413
+ if (labelledBy) {
414
+ const labelElement = document.getElementById(labelledBy);
415
+ if (labelElement)
416
+ return (labelElement.textContent || "").trim().slice(0, NAME_MAX_CHARS);
417
+ }
418
+ if (element.tagName === "INPUT" || element.tagName === "SELECT" || element.tagName === "TEXTAREA") {
419
+ const elementId = element.id;
420
+ if (elementId) {
421
+ const associatedLabel = document.querySelector(`label[for="${CSS.escape(elementId)}"]`);
422
+ if (associatedLabel?.textContent) {
423
+ return associatedLabel.textContent.trim().slice(0, NAME_MAX_CHARS);
424
+ }
425
+ }
426
+ const placeholder = element.getAttribute("placeholder");
427
+ if (placeholder)
428
+ return placeholder.trim().slice(0, NAME_MAX_CHARS);
360
429
  }
361
430
  }
362
- return false;
363
- };
364
-
365
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/context.js
366
- import { createContext as createContext2, useContext, useMemo, createElement } from "react";
367
- "use client";
368
- var LucideContext = createContext2({});
369
- var useLucideContext = () => useContext(LucideContext);
370
-
371
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/Icon.js
372
- "use client";
373
- var Icon = forwardRef(({ color, size, strokeWidth, absoluteStrokeWidth, className = "", children, iconNode, ...rest }, ref) => {
374
- const {
375
- size: contextSize = 24,
376
- strokeWidth: contextStrokeWidth = 2,
377
- absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,
378
- color: contextColor = "currentColor",
379
- className: contextClass = ""
380
- } = useLucideContext() ?? {};
381
- const calculatedStrokeWidth = absoluteStrokeWidth ?? contextAbsoluteStrokeWidth ? Number(strokeWidth ?? contextStrokeWidth) * 24 / Number(size ?? contextSize) : strokeWidth ?? contextStrokeWidth;
382
- return createElement2("svg", {
383
- ref,
384
- ...defaultAttributes,
385
- width: size ?? contextSize ?? defaultAttributes.width,
386
- height: size ?? contextSize ?? defaultAttributes.height,
387
- stroke: color ?? contextColor,
388
- strokeWidth: calculatedStrokeWidth,
389
- className: mergeClasses("lucide", contextClass, className),
390
- ...!children && !hasA11yProp(rest) && { "aria-hidden": "true" },
391
- ...rest
392
- }, [
393
- ...iconNode.map(([tag, attrs]) => createElement2(tag, attrs)),
394
- ...Array.isArray(children) ? children : [children]
395
- ]);
396
- });
397
-
398
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/createLucideIcon.js
399
- var createLucideIcon = (iconName, iconNode) => {
400
- const Component = forwardRef2(({ className, ...props }, ref) => createElement3(Icon, {
401
- ref,
402
- iconNode,
403
- className: mergeClasses(`lucide-${toKebabCase(toPascalCase(iconName))}`, `lucide-${iconName}`, className),
404
- ...props
405
- }));
406
- Component.displayName = toPascalCase(iconName);
407
- return Component;
408
- };
431
+ if (element.tagName === "IMG") {
432
+ const altText = element.getAttribute("alt");
433
+ if (altText)
434
+ return altText.trim().slice(0, NAME_MAX_CHARS);
435
+ }
436
+ const titleAttr = element.getAttribute("title");
437
+ if (titleAttr)
438
+ return titleAttr.trim().slice(0, NAME_MAX_CHARS);
439
+ const textContent = (element.textContent || "").replace(/\s+/g, " ").trim();
440
+ if (textContent)
441
+ return textContent.slice(0, NAME_MAX_CHARS);
442
+ return "";
443
+ }
409
444
 
410
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle-check.js
411
- var __iconNode = [
412
- ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
413
- ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
414
- ];
415
- var CircleCheck = createLucideIcon("circle-check", __iconNode);
416
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/loader-circle.js
417
- var __iconNode2 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
418
- var LoaderCircle = createLucideIcon("loader-circle", __iconNode2);
419
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/sparkles.js
420
- var __iconNode3 = [
421
- [
422
- "path",
423
- {
424
- d: "M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",
425
- key: "1s2grr"
426
- }
427
- ],
428
- ["path", { d: "M20 2v4", key: "1rf3ol" }],
429
- ["path", { d: "M22 4h-4", key: "gwowj6" }],
430
- ["circle", { cx: "4", cy: "20", r: "2", key: "6kqj1y" }]
431
- ];
432
- var Sparkles = createLucideIcon("sparkles", __iconNode3);
433
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/calendar.js
434
- var __iconNode4 = [
435
- ["path", { d: "M8 2v4", key: "1cmpym" }],
436
- ["path", { d: "M16 2v4", key: "4m81vk" }],
437
- ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
438
- ["path", { d: "M3 10h18", key: "8toen8" }]
445
+ // src/capture/a11yTree.ts
446
+ var REF_PREFIX = "r-";
447
+ var VALUE_MAX_CHARS = 80;
448
+ var HREF_MAX_CHARS = 60;
449
+ var PAGE_CONTENT_MAX_BYTES = 14000;
450
+ var NODE_LIMIT = 1500;
451
+ var SENSITIVE_IFRAME_HOSTS = [
452
+ "js.stripe.com",
453
+ "checkout.stripe.com",
454
+ "connect.stripe.com",
455
+ "plaid.com",
456
+ "production.plaid.com",
457
+ "cdn.plaid.com",
458
+ "auth0.com",
459
+ "login.auth0.com",
460
+ "recaptcha.net",
461
+ "www.google.com",
462
+ "hcaptcha.com",
463
+ "newassets.hcaptcha.com",
464
+ "challenges.cloudflare.com"
439
465
  ];
440
- var Calendar = createLucideIcon("calendar", __iconNode4);
441
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/chevron-down.js
442
- var __iconNode5 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
443
- var ChevronDown = createLucideIcon("chevron-down", __iconNode5);
444
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle.js
445
- var __iconNode6 = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
446
- var Circle = createLucideIcon("circle", __iconNode6);
447
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/eye.js
448
- var __iconNode7 = [
449
- [
450
- "path",
451
- {
452
- d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",
453
- key: "1nclc0"
454
- }
455
- ],
456
- ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
457
- ];
458
- var Eye = createLucideIcon("eye", __iconNode7);
459
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mail.js
460
- var __iconNode8 = [
461
- ["path", { d: "m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7", key: "132q7q" }],
462
- ["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2", key: "izxlao" }]
463
- ];
464
- var Mail = createLucideIcon("mail", __iconNode8);
465
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-circle.js
466
- var __iconNode9 = [
467
- [
468
- "path",
469
- {
470
- d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",
471
- key: "1sd12s"
472
- }
473
- ]
474
- ];
475
- var MessageCircle = createLucideIcon("message-circle", __iconNode9);
476
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic-off.js
477
- var __iconNode10 = [
478
- ["path", { d: "M12 19v3", key: "npa21l" }],
479
- ["path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33", key: "1gzdoj" }],
480
- ["path", { d: "M16.95 16.95A7 7 0 0 1 5 12v-2", key: "cqa7eg" }],
481
- ["path", { d: "M18.89 13.23A7 7 0 0 0 19 12v-2", key: "16hl24" }],
482
- ["path", { d: "m2 2 20 20", key: "1ooewy" }],
483
- ["path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12", key: "r2i35w" }]
484
- ];
485
- var MicOff = createLucideIcon("mic-off", __iconNode10);
486
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic.js
487
- var __iconNode11 = [
488
- ["path", { d: "M12 19v3", key: "npa21l" }],
489
- ["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
490
- ["rect", { x: "9", y: "2", width: "6", height: "13", rx: "3", key: "s6n7sd" }]
491
- ];
492
- var Mic = createLucideIcon("mic", __iconNode11);
493
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/minimize-2.js
494
- var __iconNode12 = [
495
- ["path", { d: "m14 10 7-7", key: "oa77jy" }],
496
- ["path", { d: "M20 10h-6V4", key: "mjg0md" }],
497
- ["path", { d: "m3 21 7-7", key: "tjx5ai" }],
498
- ["path", { d: "M4 14h6v6", key: "rmj7iw" }]
499
- ];
500
- var Minimize2 = createLucideIcon("minimize-2", __iconNode12);
501
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor-off.js
502
- var __iconNode13 = [
503
- ["path", { d: "M12 17v4", key: "1riwvh" }],
504
- ["path", { d: "M17 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 1.184-1.826", key: "cv7jms" }],
505
- ["path", { d: "m2 2 20 20", key: "1ooewy" }],
506
- ["path", { d: "M8 21h8", key: "1ev6f3" }],
507
- ["path", { d: "M8.656 3H20a2 2 0 0 1 2 2v10a2 2 0 0 1-.293 1.042", key: "z8ni2w" }]
508
- ];
509
- var MonitorOff = createLucideIcon("monitor-off", __iconNode13);
510
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor.js
511
- var __iconNode14 = [
512
- ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
513
- ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
514
- ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
515
- ];
516
- var Monitor = createLucideIcon("monitor", __iconNode14);
517
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/phone-off.js
518
- var __iconNode15 = [
519
- [
520
- "path",
521
- {
522
- d: "M10.1 13.9a14 14 0 0 0 3.732 2.668 1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2 18 18 0 0 1-12.728-5.272",
523
- key: "1wngk7"
524
- }
525
- ],
526
- ["path", { d: "M22 2 2 22", key: "y4kqgn" }],
527
- [
528
- "path",
529
- {
530
- d: "M4.76 13.582A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 .244.473",
531
- key: "10hv5p"
532
- }
533
- ]
534
- ];
535
- var PhoneOff = createLucideIcon("phone-off", __iconNode15);
536
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/send.js
537
- var __iconNode16 = [
538
- [
539
- "path",
540
- {
541
- d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",
542
- key: "1ffxy3"
543
- }
544
- ],
545
- ["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
546
- ];
547
- var Send = createLucideIcon("send", __iconNode16);
548
- // src/hooks/useAgentVoiceState.ts
549
- import { useVoiceAssistant } from "@livekit/components-react/hooks";
550
- function useAgentVoiceState() {
551
- const { state } = useVoiceAssistant();
552
- return {
553
- state,
554
- isSpeaking: state === "speaking",
555
- isListening: state === "listening"
556
- };
466
+ var MASK_AUTOCOMPLETE_VALUES = new Set([
467
+ "cc-number",
468
+ "cc-exp",
469
+ "cc-exp-month",
470
+ "cc-exp-year",
471
+ "cc-csc",
472
+ "cc-name",
473
+ "cc-given-name",
474
+ "cc-family-name",
475
+ "current-password",
476
+ "new-password",
477
+ "one-time-code"
478
+ ]);
479
+ var MASK_INPUT_TYPES = new Set(["password", "hidden"]);
480
+ var MASK_NAME_PATTERN = /password|secret|token|api[_-]?key|ssn|tax[_-]?id|social[_-]?security|cvv|cvc|pin/i;
481
+ var refCounter = 0;
482
+ function generateNextRef() {
483
+ refCounter += 1;
484
+ return `${REF_PREFIX}${refCounter}`;
557
485
  }
558
-
559
- // src/hooks/useLiveAgent.ts
560
- import { use } from "react";
561
- function useLiveAgent() {
562
- const ctx = use(LiveAgentContext);
563
- if (!ctx) {
564
- throw new Error("useLiveAgent must be used within a <LiveAgent> provider");
486
+ function advanceCounterPastExisting(ref) {
487
+ const parsedRefNumber = Number.parseInt(ref.slice(REF_PREFIX.length), 10);
488
+ if (Number.isFinite(parsedRefNumber) && parsedRefNumber > refCounter) {
489
+ refCounter = parsedRefNumber;
565
490
  }
566
- const { connection, shouldConnect, ...publicValue } = ctx;
567
- return publicValue;
568
491
  }
569
-
570
- // src/hooks/useMediaControls.ts
571
- import { useLocalParticipant } from "@livekit/components-react/hooks";
572
- import { ScreenSharePresets } from "livekit-client";
573
- import { useCallback as useCallback3 } from "react";
574
- var SCREEN_SHARE_OPTIONS = {
575
- video: { displaySurface: "browser" },
576
- resolution: ScreenSharePresets.h720fps30.resolution,
577
- contentHint: "detail"
578
- };
579
- function useMediaControls() {
580
- const { localParticipant } = useLocalParticipant();
581
- const isMuted = !localParticipant.isMicrophoneEnabled;
582
- const isScreenSharing = localParticipant.isScreenShareEnabled;
583
- const toggleMute = useCallback3(async () => {
584
- try {
585
- await localParticipant.setMicrophoneEnabled(isMuted);
586
- } catch (error) {
587
- console.error("Failed to toggle microphone:", error);
588
- }
589
- }, [localParticipant, isMuted]);
590
- const toggleScreenShare = useCallback3(async () => {
591
- try {
592
- await localParticipant.setScreenShareEnabled(!isScreenSharing, SCREEN_SHARE_OPTIONS);
593
- } catch (error) {
594
- console.error("Failed to toggle screen share:", error);
595
- }
596
- }, [localParticipant, isScreenSharing]);
597
- return { isMuted, toggleMute, isScreenSharing, toggleScreenShare };
492
+ function intersectsViewport(rect, viewportWidth, viewportHeight) {
493
+ if (rect.width <= 0 || rect.height <= 0)
494
+ return false;
495
+ if (rect.bottom <= 0 || rect.top >= viewportHeight)
496
+ return false;
497
+ if (rect.right <= 0 || rect.left >= viewportWidth)
498
+ return false;
499
+ return true;
598
500
  }
599
-
600
- // src/components/AgentStateBanner.tsx
601
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
602
- function AgentStateBanner() {
603
- const { isConnected } = useLiveAgent();
604
- const { isScreenSharing } = useMediaControls();
605
- const { state } = useAgentVoiceState();
606
- if (!isConnected)
607
- return null;
608
- return /* @__PURE__ */ jsx("div", {
609
- className: "skippr:fixed skippr:top-0 skippr:left-0 skippr:right-0 skippr:z-[2147483647] skippr:flex skippr:justify-center skippr:pointer-events-none",
610
- children: /* @__PURE__ */ jsx("div", {
611
- className: "skippr:pointer-events-auto skippr:flex skippr:items-center skippr:gap-2 skippr:bg-indigo-500/95 skippr:backdrop-blur-sm skippr:text-white skippr:text-xs skippr:font-medium skippr:px-4 skippr:py-1.5 skippr:rounded-b-lg skippr:shadow-lg",
612
- children: /* @__PURE__ */ jsx(BannerContent, {
613
- state,
614
- isScreenSharing
615
- })
616
- })
617
- });
501
+ function isVisible(element, rect) {
502
+ if (!intersectsViewport(rect, window.innerWidth, window.innerHeight))
503
+ return false;
504
+ const style = window.getComputedStyle(element);
505
+ if (style.visibility === "hidden" || style.display === "none")
506
+ return false;
507
+ if (Number.parseFloat(style.opacity || "1") <= 0.01)
508
+ return false;
509
+ return true;
618
510
  }
619
- function BannerContent({
620
- state,
621
- isScreenSharing
622
- }) {
623
- if (state === "speaking") {
624
- return /* @__PURE__ */ jsxs(Fragment, {
625
- children: [
626
- /* @__PURE__ */ jsx(SpeakingBars, {}),
627
- /* @__PURE__ */ jsx("span", {
628
- children: "Skippr is talking"
629
- })
630
- ]
631
- });
632
- }
633
- if (state === "thinking") {
634
- return /* @__PURE__ */ jsxs(Fragment, {
635
- children: [
636
- /* @__PURE__ */ jsx(ThinkingDots, {}),
637
- /* @__PURE__ */ jsx("span", {
638
- children: "Skippr is thinking"
639
- })
640
- ]
641
- });
642
- }
643
- if (state === "listening" && isScreenSharing) {
644
- return /* @__PURE__ */ jsxs(Fragment, {
645
- children: [
646
- /* @__PURE__ */ jsx(ObservingDot, {}),
647
- /* @__PURE__ */ jsx(Eye, {
648
- className: "skippr:size-3.5"
649
- }),
650
- /* @__PURE__ */ jsx("span", {
651
- children: "Skippr is observing this page"
652
- })
653
- ]
654
- });
511
+ function isInteractive(element, role) {
512
+ if (role && role !== "heading" && role !== "image" && role !== "list" && role !== "listitem") {
513
+ const interactiveRoles = [
514
+ "button",
515
+ "link",
516
+ "input",
517
+ "select",
518
+ "textarea",
519
+ "checkbox",
520
+ "radio",
521
+ "tab",
522
+ "menuitem",
523
+ "option",
524
+ "switch",
525
+ "slider"
526
+ ];
527
+ if (interactiveRoles.includes(role))
528
+ return true;
655
529
  }
656
- return /* @__PURE__ */ jsxs(Fragment, {
657
- children: [
658
- /* @__PURE__ */ jsx(ObservingDot, {}),
659
- /* @__PURE__ */ jsx("span", {
660
- children: "Skippr is connected"
661
- })
662
- ]
663
- });
530
+ if (element.tabIndex >= 0)
531
+ return true;
532
+ if (element.hasAttribute("onclick") || element.hasAttribute("contenteditable"))
533
+ return true;
534
+ return false;
664
535
  }
665
- function ObservingDot() {
666
- return /* @__PURE__ */ jsxs("span", {
667
- className: "skippr:relative skippr:flex skippr:size-1.5",
668
- children: [
669
- /* @__PURE__ */ jsx("span", {
670
- className: "skippr:absolute skippr:inline-flex skippr:size-full skippr:animate-ping skippr:rounded-full skippr:bg-emerald-400 skippr:opacity-75"
671
- }),
672
- /* @__PURE__ */ jsx("span", {
673
- className: "skippr:relative skippr:inline-flex skippr:size-1.5 skippr:rounded-full skippr:bg-emerald-400"
674
- })
675
- ]
676
- });
536
+ function isBlindRegion(role) {
537
+ return role === "video" || role === "iframe" || role === "canvas" || role === "audio" || role === "embed" || role === "object";
677
538
  }
678
- function ThinkingDots() {
679
- return /* @__PURE__ */ jsxs("span", {
680
- className: "skippr:flex skippr:items-center skippr:gap-[3px]",
681
- children: [
682
- /* @__PURE__ */ jsx("span", {
683
- className: "skippr:size-1 skippr:rounded-full skippr:bg-white skippr:animate-bounce skippr:[animation-delay:0ms]"
684
- }),
685
- /* @__PURE__ */ jsx("span", {
686
- className: "skippr:size-1 skippr:rounded-full skippr:bg-white skippr:animate-bounce skippr:[animation-delay:150ms]"
687
- }),
688
- /* @__PURE__ */ jsx("span", {
689
- className: "skippr:size-1 skippr:rounded-full skippr:bg-white skippr:animate-bounce skippr:[animation-delay:300ms]"
690
- })
691
- ]
692
- });
693
- }
694
- function SpeakingBars() {
695
- return /* @__PURE__ */ jsxs("span", {
696
- className: "skippr:flex skippr:items-center skippr:gap-[2px] skippr:h-3.5",
697
- children: [
698
- /* @__PURE__ */ jsx("span", {
699
- className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_infinite] skippr:h-1.5"
700
- }),
701
- /* @__PURE__ */ jsx("span", {
702
- className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.15s_infinite] skippr:h-3"
703
- }),
704
- /* @__PURE__ */ jsx("span", {
705
- className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.3s_infinite] skippr:h-2"
706
- }),
707
- /* @__PURE__ */ jsx("span", {
708
- className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.45s_infinite] skippr:h-3.5"
709
- }),
710
- /* @__PURE__ */ jsx("span", {
711
- className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.6s_infinite] skippr:h-1"
712
- })
713
- ]
714
- });
715
- }
716
-
717
- // src/components/AutoStartMedia.tsx
718
- import { useConnectionState, useLocalParticipant as useLocalParticipant2 } from "@livekit/components-react/hooks";
719
- import { ConnectionState, Track } from "livekit-client";
720
- import { useEffect as useEffect3, useRef } from "react";
721
- function AutoStartMedia({ pendingScreenStream }) {
722
- const { localParticipant } = useLocalParticipant2();
723
- const connectionState = useConnectionState();
724
- const didStartRef = useRef(false);
725
- useEffect3(() => {
726
- if (didStartRef.current)
727
- return;
728
- if (connectionState !== ConnectionState.Connected)
729
- return;
730
- didStartRef.current = true;
731
- localParticipant.setMicrophoneEnabled(true).catch((error) => console.error("Failed to enable microphone:", error));
732
- if (pendingScreenStream) {
733
- const videoTrack = pendingScreenStream.getVideoTracks()[0];
734
- if (videoTrack) {
735
- videoTrack.contentHint = "detail";
736
- localParticipant.publishTrack(videoTrack, { source: Track.Source.ScreenShare }).catch((error) => {
737
- console.error("Failed to publish screen share track:", error);
738
- for (const track of pendingScreenStream.getTracks())
739
- track.stop();
740
- });
741
- }
742
- }
743
- }, [connectionState, localParticipant, pendingScreenStream]);
744
- return null;
745
- }
746
-
747
- // src/components/DomCapture.tsx
748
- import { useConnectionState as useConnectionState2, useLocalParticipant as useLocalParticipant3 } from "@livekit/components-react/hooks";
749
- import { ConnectionState as ConnectionState2, ScreenSharePresets as ScreenSharePresets2, Track as Track2 } from "livekit-client";
750
- import { useEffect as useEffect4, useRef as useRef2 } from "react";
751
-
752
- // src/capture/a11yUtils.ts
753
- var ROLE_BY_TAG = {
754
- a: "link",
755
- button: "button",
756
- input: "input",
757
- select: "select",
758
- textarea: "textarea",
759
- label: "label",
760
- nav: "navigation",
761
- main: "main",
762
- header: "header",
763
- footer: "footer",
764
- aside: "complementary",
765
- form: "form",
766
- h1: "heading",
767
- h2: "heading",
768
- h3: "heading",
769
- h4: "heading",
770
- h5: "heading",
771
- h6: "heading",
772
- img: "image",
773
- ul: "list",
774
- ol: "list",
775
- li: "listitem",
776
- table: "table",
777
- tr: "row",
778
- td: "cell",
779
- th: "columnheader",
780
- video: "video",
781
- iframe: "iframe",
782
- canvas: "canvas",
783
- audio: "audio",
784
- embed: "embed",
785
- object: "object"
786
- };
787
- function inferRole(element) {
788
- const explicitRole = element.getAttribute("role");
789
- if (explicitRole)
790
- return explicitRole;
791
- const tagName = element.tagName.toLowerCase();
792
- if (tagName === "input") {
793
- const inputType = element.type;
794
- if (inputType === "checkbox")
795
- return "checkbox";
796
- if (inputType === "radio")
797
- return "radio";
798
- if (inputType === "submit" || inputType === "button")
799
- return "button";
800
- return "input";
801
- }
802
- return ROLE_BY_TAG[tagName] ?? null;
803
- }
804
- function accessibleName(element, options = {}) {
805
- const ariaLabel = element.getAttribute("aria-label");
806
- if (ariaLabel)
807
- return ariaLabel.trim().slice(0, NAME_MAX_CHARS);
808
- if (!options.quick) {
809
- const labelledBy = element.getAttribute("aria-labelledby");
810
- if (labelledBy) {
811
- const labelElement = document.getElementById(labelledBy);
812
- if (labelElement)
813
- return (labelElement.textContent || "").trim().slice(0, NAME_MAX_CHARS);
814
- }
815
- if (element.tagName === "INPUT" || element.tagName === "SELECT" || element.tagName === "TEXTAREA") {
816
- const elementId = element.id;
817
- if (elementId) {
818
- const associatedLabel = document.querySelector(`label[for="${CSS.escape(elementId)}"]`);
819
- if (associatedLabel?.textContent) {
820
- return associatedLabel.textContent.trim().slice(0, NAME_MAX_CHARS);
821
- }
822
- }
823
- const placeholder = element.getAttribute("placeholder");
824
- if (placeholder)
825
- return placeholder.trim().slice(0, NAME_MAX_CHARS);
826
- }
827
- }
828
- if (element.tagName === "IMG") {
829
- const altText = element.getAttribute("alt");
830
- if (altText)
831
- return altText.trim().slice(0, NAME_MAX_CHARS);
832
- }
833
- const titleAttr = element.getAttribute("title");
834
- if (titleAttr)
835
- return titleAttr.trim().slice(0, NAME_MAX_CHARS);
836
- const textContent = (element.textContent || "").replace(/\s+/g, " ").trim();
837
- if (textContent)
838
- return textContent.slice(0, NAME_MAX_CHARS);
839
- return "";
840
- }
841
-
842
- // src/capture/a11yTree.ts
843
- var REF_PREFIX = "r-";
844
- var VALUE_MAX_CHARS = 80;
845
- var HREF_MAX_CHARS = 60;
846
- var PAGE_CONTENT_MAX_BYTES = 14000;
847
- var NODE_LIMIT = 1500;
848
- var SENSITIVE_IFRAME_HOSTS = [
849
- "js.stripe.com",
850
- "checkout.stripe.com",
851
- "connect.stripe.com",
852
- "plaid.com",
853
- "production.plaid.com",
854
- "cdn.plaid.com",
855
- "auth0.com",
856
- "login.auth0.com",
857
- "recaptcha.net",
858
- "www.google.com",
859
- "hcaptcha.com",
860
- "newassets.hcaptcha.com",
861
- "challenges.cloudflare.com"
862
- ];
863
- var MASK_AUTOCOMPLETE_VALUES = new Set([
864
- "cc-number",
865
- "cc-exp",
866
- "cc-exp-month",
867
- "cc-exp-year",
868
- "cc-csc",
869
- "cc-name",
870
- "cc-given-name",
871
- "cc-family-name",
872
- "current-password",
873
- "new-password",
874
- "one-time-code"
875
- ]);
876
- var MASK_INPUT_TYPES = new Set(["password", "hidden"]);
877
- var MASK_NAME_PATTERN = /password|secret|token|api[_-]?key|ssn|tax[_-]?id|social[_-]?security|cvv|cvc|pin/i;
878
- var refCounter = 0;
879
- function generateNextRef() {
880
- refCounter += 1;
881
- return `${REF_PREFIX}${refCounter}`;
882
- }
883
- function advanceCounterPastExisting(ref) {
884
- const parsedRefNumber = Number.parseInt(ref.slice(REF_PREFIX.length), 10);
885
- if (Number.isFinite(parsedRefNumber) && parsedRefNumber > refCounter) {
886
- refCounter = parsedRefNumber;
887
- }
888
- }
889
- function intersectsViewport(rect, viewportWidth, viewportHeight) {
890
- if (rect.width <= 0 || rect.height <= 0)
891
- return false;
892
- if (rect.bottom <= 0 || rect.top >= viewportHeight)
893
- return false;
894
- if (rect.right <= 0 || rect.left >= viewportWidth)
895
- return false;
896
- return true;
897
- }
898
- function isVisible(element, rect) {
899
- if (!intersectsViewport(rect, window.innerWidth, window.innerHeight))
900
- return false;
901
- const style = window.getComputedStyle(element);
902
- if (style.visibility === "hidden" || style.display === "none")
903
- return false;
904
- if (Number.parseFloat(style.opacity || "1") <= 0.01)
905
- return false;
906
- return true;
907
- }
908
- function isInteractive(element, role) {
909
- if (role && role !== "heading" && role !== "image" && role !== "list" && role !== "listitem") {
910
- const interactiveRoles = [
911
- "button",
912
- "link",
913
- "input",
914
- "select",
915
- "textarea",
916
- "checkbox",
917
- "radio",
918
- "tab",
919
- "menuitem",
920
- "option",
921
- "switch",
922
- "slider"
923
- ];
924
- if (interactiveRoles.includes(role))
925
- return true;
926
- }
927
- if (element.tabIndex >= 0)
928
- return true;
929
- if (element.hasAttribute("onclick") || element.hasAttribute("contenteditable"))
930
- return true;
931
- return false;
932
- }
933
- function isBlindRegion(role) {
934
- return role === "video" || role === "iframe" || role === "canvas" || role === "audio" || role === "embed" || role === "object";
935
- }
936
- function getIframeHost(element) {
937
- const src = element.getAttribute("src");
938
- if (!src)
939
- return null;
940
- try {
941
- return new URL(src, window.location.href).host;
942
- } catch {
943
- return null;
944
- }
539
+ function getIframeHost(element) {
540
+ const src = element.getAttribute("src");
541
+ if (!src)
542
+ return null;
543
+ try {
544
+ return new URL(src, window.location.href).host;
545
+ } catch {
546
+ return null;
547
+ }
945
548
  }
946
549
  function isSensitiveIframe(element) {
947
550
  const host = getIframeHost(element);
@@ -1160,7 +763,7 @@ function walkAndCollect(element, depth, entries) {
1160
763
  function dropSmallestAreaEntriesUntilUnderLimit(entries) {
1161
764
  if (entries.length <= NODE_LIMIT)
1162
765
  return entries;
1163
- const indexedEntries = entries.map((entry, index2) => ({ entry, index: index2 }));
766
+ const indexedEntries = entries.map((entry, index) => ({ entry, index }));
1164
767
  const entriesByAreaAscending = indexedEntries.slice(1).sort((a, b) => a.entry.area - b.entry.area);
1165
768
  const indicesToDrop = new Set(entriesByAreaAscending.slice(0, entries.length - NODE_LIMIT).map((indexed) => indexed.index));
1166
769
  const keptEntries = [];
@@ -1387,7 +990,7 @@ async function snapToCanvas(element, options = {}) {
1387
990
  // src/components/DomCapture.tsx
1388
991
  var SNAPSHOT_INTERVAL_MS = 2000;
1389
992
  var A11Y_PUBLISH_INTERVAL_MS = 2000;
1390
- var CAPTURE_PRESET = ScreenSharePresets2.h1080fps30;
993
+ var CAPTURE_PRESET = ScreenSharePresets.h1080fps30;
1391
994
  var CAPTURE_FPS = CAPTURE_PRESET.encoding.maxFramerate ?? 30;
1392
995
  var CAPTURE_BITRATE = 4000000;
1393
996
  var DOM_SNAPSHOT_GZIP_THRESHOLD_BYTES = 14000;
@@ -1492,7 +1095,7 @@ async function unpublishAndStopTrack(localParticipant, videoTrack) {
1492
1095
  videoTrack.stop();
1493
1096
  }
1494
1097
  function DomCapture() {
1495
- const { localParticipant } = useLocalParticipant3();
1098
+ const { localParticipant } = useLocalParticipant2();
1496
1099
  const connectionState = useConnectionState2();
1497
1100
  const didStartRef = useRef2(false);
1498
1101
  useEffect4(() => {
@@ -1591,8 +1194,8 @@ function DomCapture() {
1591
1194
 
1592
1195
  // src/components/HighlightOverlay.tsx
1593
1196
  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";
1197
+ import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef3, useState as useState3 } from "react";
1198
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
1596
1199
  var TOOLTIP_MAX_WIDTH = 280;
1597
1200
  var TOOLTIP_GAP = 8;
1598
1201
  var VIEWPORT_MARGIN = 8;
@@ -1703,11 +1306,11 @@ function HighlightOverlay() {
1703
1306
  const [overlayState, setOverlayState] = useState3(null);
1704
1307
  const targetElementRef = useRef3(null);
1705
1308
  const pendingFrameRef = useRef3(null);
1706
- const clearOverlay = useCallback4(() => {
1309
+ const clearOverlay = useCallback3(() => {
1707
1310
  targetElementRef.current = null;
1708
1311
  setOverlayState(null);
1709
1312
  }, []);
1710
- const recomputeRect = useCallback4(() => {
1313
+ const recomputeRect = useCallback3(() => {
1711
1314
  pendingFrameRef.current = null;
1712
1315
  const target = targetElementRef.current;
1713
1316
  if (!target)
@@ -1719,12 +1322,12 @@ function HighlightOverlay() {
1719
1322
  const rect2 = getRectInTopViewport(target);
1720
1323
  setOverlayState((prev) => prev ? { ...prev, rect: rect2 } : prev);
1721
1324
  }, [clearOverlay]);
1722
- const scheduleRecompute = useCallback4(() => {
1325
+ const scheduleRecompute = useCallback3(() => {
1723
1326
  if (pendingFrameRef.current !== null)
1724
1327
  return;
1725
1328
  pendingFrameRef.current = window.requestAnimationFrame(recomputeRect);
1726
1329
  }, [recomputeRect]);
1727
- const onHighlightMessage = useCallback4((msg) => {
1330
+ const onHighlightMessage = useCallback3((msg) => {
1728
1331
  const parsed = parseHighlightMessage(msg.payload);
1729
1332
  if (!parsed)
1730
1333
  return;
@@ -1762,93 +1365,514 @@ function HighlightOverlay() {
1762
1365
  win.addEventListener("scroll", onScroll, { capture: true, passive: true });
1763
1366
  win.addEventListener("resize", onResize, { passive: true });
1764
1367
  }
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"
1368
+ const resizeObserver = new ResizeObserver(scheduleRecompute);
1369
+ resizeObserver.observe(target);
1370
+ const scrollContainer = findScrollableAncestor(target);
1371
+ const mutationObserver = new MutationObserver(() => {
1372
+ if (!targetElementRef.current?.isConnected) {
1373
+ clearOverlay();
1374
+ return;
1375
+ }
1376
+ scheduleRecompute();
1377
+ });
1378
+ mutationObserver.observe(scrollContainer, { childList: true, subtree: true });
1379
+ return () => {
1380
+ for (const win of watchedWindows) {
1381
+ win.removeEventListener("scroll", onScroll, { capture: true });
1382
+ win.removeEventListener("resize", onResize);
1383
+ }
1384
+ resizeObserver.disconnect();
1385
+ mutationObserver.disconnect();
1386
+ if (pendingFrameRef.current !== null) {
1387
+ window.cancelAnimationFrame(pendingFrameRef.current);
1388
+ pendingFrameRef.current = null;
1389
+ }
1390
+ };
1391
+ }, [overlayState, scheduleRecompute, clearOverlay]);
1392
+ if (!overlayState)
1393
+ return null;
1394
+ const { rect, message } = overlayState;
1395
+ const ringStyle = {
1396
+ position: "fixed",
1397
+ left: `${rect.left}px`,
1398
+ top: `${rect.top}px`,
1399
+ width: `${rect.width}px`,
1400
+ height: `${rect.height}px`,
1401
+ pointerEvents: "none",
1402
+ zIndex: Z_INDEX,
1403
+ boxShadow: `0 0 0 2px ${RING_INNER}, 0 0 0 6px ${RING_OUTER}`,
1404
+ borderRadius: "4px",
1405
+ transition: "none"
1406
+ };
1407
+ const showTooltipBelow = rect.top < TOOLTIP_TOP_THRESHOLD;
1408
+ const tooltipTop = showTooltipBelow ? rect.bottom + TOOLTIP_GAP : rect.top - TOOLTIP_GAP;
1409
+ const tooltipTransform = showTooltipBelow ? "translateY(0)" : "translateY(-100%)";
1410
+ const tooltipLeft = Math.min(Math.max(rect.left, VIEWPORT_MARGIN), window.innerWidth - TOOLTIP_MAX_WIDTH - VIEWPORT_MARGIN);
1411
+ const tooltipStyle = {
1412
+ position: "fixed",
1413
+ left: `${tooltipLeft}px`,
1414
+ top: `${tooltipTop}px`,
1415
+ transform: tooltipTransform,
1416
+ maxWidth: `${TOOLTIP_MAX_WIDTH}px`,
1417
+ pointerEvents: "none",
1418
+ zIndex: Z_INDEX,
1419
+ background: "rgba(45, 43, 61, 0.96)",
1420
+ color: "#ffffff",
1421
+ padding: "6px 10px",
1422
+ borderRadius: "8px",
1423
+ fontSize: "13px",
1424
+ lineHeight: "1.35",
1425
+ fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif',
1426
+ boxShadow: "0 6px 20px rgba(0, 0, 0, 0.25)",
1427
+ whiteSpace: "normal",
1428
+ wordWrap: "break-word"
1429
+ };
1430
+ return /* @__PURE__ */ jsxs(Fragment, {
1431
+ children: [
1432
+ /* @__PURE__ */ jsx("div", {
1433
+ "data-skippr-private": "true",
1434
+ style: ringStyle,
1435
+ "aria-hidden": "true"
1436
+ }),
1437
+ message && /* @__PURE__ */ jsx("div", {
1438
+ "data-skippr-private": "true",
1439
+ style: tooltipStyle,
1440
+ role: "tooltip",
1441
+ children: message
1442
+ })
1443
+ ]
1444
+ });
1445
+ }
1446
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/createLucideIcon.js
1447
+ import { forwardRef as forwardRef2, createElement as createElement3 } from "react";
1448
+
1449
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
1450
+ var mergeClasses = (...classes) => classes.filter((className, index, array) => {
1451
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
1452
+ }).join(" ").trim();
1453
+
1454
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js
1455
+ var toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
1456
+
1457
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js
1458
+ var toCamelCase = (string) => string.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase());
1459
+
1460
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js
1461
+ var toPascalCase = (string) => {
1462
+ const camelCase = toCamelCase(string);
1463
+ return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
1464
+ };
1465
+
1466
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/Icon.js
1467
+ import { forwardRef, createElement as createElement2 } from "react";
1468
+
1469
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/defaultAttributes.js
1470
+ var defaultAttributes = {
1471
+ xmlns: "http://www.w3.org/2000/svg",
1472
+ width: 24,
1473
+ height: 24,
1474
+ viewBox: "0 0 24 24",
1475
+ fill: "none",
1476
+ stroke: "currentColor",
1477
+ strokeWidth: 2,
1478
+ strokeLinecap: "round",
1479
+ strokeLinejoin: "round"
1480
+ };
1481
+
1482
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js
1483
+ var hasA11yProp = (props) => {
1484
+ for (const prop in props) {
1485
+ if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
1486
+ return true;
1487
+ }
1488
+ }
1489
+ return false;
1490
+ };
1491
+
1492
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/context.js
1493
+ import { createContext as createContext2, useContext, useMemo, createElement } from "react";
1494
+ "use client";
1495
+ var LucideContext = createContext2({});
1496
+ var useLucideContext = () => useContext(LucideContext);
1497
+
1498
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/Icon.js
1499
+ "use client";
1500
+ var Icon = forwardRef(({ color, size, strokeWidth, absoluteStrokeWidth, className = "", children, iconNode, ...rest }, ref) => {
1501
+ const {
1502
+ size: contextSize = 24,
1503
+ strokeWidth: contextStrokeWidth = 2,
1504
+ absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,
1505
+ color: contextColor = "currentColor",
1506
+ className: contextClass = ""
1507
+ } = useLucideContext() ?? {};
1508
+ const calculatedStrokeWidth = absoluteStrokeWidth ?? contextAbsoluteStrokeWidth ? Number(strokeWidth ?? contextStrokeWidth) * 24 / Number(size ?? contextSize) : strokeWidth ?? contextStrokeWidth;
1509
+ return createElement2("svg", {
1510
+ ref,
1511
+ ...defaultAttributes,
1512
+ width: size ?? contextSize ?? defaultAttributes.width,
1513
+ height: size ?? contextSize ?? defaultAttributes.height,
1514
+ stroke: color ?? contextColor,
1515
+ strokeWidth: calculatedStrokeWidth,
1516
+ className: mergeClasses("lucide", contextClass, className),
1517
+ ...!children && !hasA11yProp(rest) && { "aria-hidden": "true" },
1518
+ ...rest
1519
+ }, [
1520
+ ...iconNode.map(([tag, attrs]) => createElement2(tag, attrs)),
1521
+ ...Array.isArray(children) ? children : [children]
1522
+ ]);
1523
+ });
1524
+
1525
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/createLucideIcon.js
1526
+ var createLucideIcon = (iconName, iconNode) => {
1527
+ const Component = forwardRef2(({ className, ...props }, ref) => createElement3(Icon, {
1528
+ ref,
1529
+ iconNode,
1530
+ className: mergeClasses(`lucide-${toKebabCase(toPascalCase(iconName))}`, `lucide-${iconName}`, className),
1531
+ ...props
1532
+ }));
1533
+ Component.displayName = toPascalCase(iconName);
1534
+ return Component;
1535
+ };
1536
+
1537
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle-check.js
1538
+ var __iconNode = [
1539
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
1540
+ ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
1541
+ ];
1542
+ var CircleCheck = createLucideIcon("circle-check", __iconNode);
1543
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/loader-circle.js
1544
+ var __iconNode2 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
1545
+ var LoaderCircle = createLucideIcon("loader-circle", __iconNode2);
1546
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/sparkles.js
1547
+ var __iconNode3 = [
1548
+ [
1549
+ "path",
1550
+ {
1551
+ d: "M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",
1552
+ key: "1s2grr"
1553
+ }
1554
+ ],
1555
+ ["path", { d: "M20 2v4", key: "1rf3ol" }],
1556
+ ["path", { d: "M22 4h-4", key: "gwowj6" }],
1557
+ ["circle", { cx: "4", cy: "20", r: "2", key: "6kqj1y" }]
1558
+ ];
1559
+ var Sparkles = createLucideIcon("sparkles", __iconNode3);
1560
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/calendar.js
1561
+ var __iconNode4 = [
1562
+ ["path", { d: "M8 2v4", key: "1cmpym" }],
1563
+ ["path", { d: "M16 2v4", key: "4m81vk" }],
1564
+ ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
1565
+ ["path", { d: "M3 10h18", key: "8toen8" }]
1566
+ ];
1567
+ var Calendar = createLucideIcon("calendar", __iconNode4);
1568
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/chevron-down.js
1569
+ var __iconNode5 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
1570
+ var ChevronDown = createLucideIcon("chevron-down", __iconNode5);
1571
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle.js
1572
+ var __iconNode6 = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
1573
+ var Circle = createLucideIcon("circle", __iconNode6);
1574
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mail.js
1575
+ var __iconNode7 = [
1576
+ ["path", { d: "m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7", key: "132q7q" }],
1577
+ ["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2", key: "izxlao" }]
1578
+ ];
1579
+ var Mail = createLucideIcon("mail", __iconNode7);
1580
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-circle.js
1581
+ var __iconNode8 = [
1582
+ [
1583
+ "path",
1584
+ {
1585
+ d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",
1586
+ key: "1sd12s"
1587
+ }
1588
+ ]
1589
+ ];
1590
+ var MessageCircle = createLucideIcon("message-circle", __iconNode8);
1591
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-square.js
1592
+ var __iconNode9 = [
1593
+ [
1594
+ "path",
1595
+ {
1596
+ d: "M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z",
1597
+ key: "18887p"
1598
+ }
1599
+ ]
1600
+ ];
1601
+ var MessageSquare = createLucideIcon("message-square", __iconNode9);
1602
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic-off.js
1603
+ var __iconNode10 = [
1604
+ ["path", { d: "M12 19v3", key: "npa21l" }],
1605
+ ["path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33", key: "1gzdoj" }],
1606
+ ["path", { d: "M16.95 16.95A7 7 0 0 1 5 12v-2", key: "cqa7eg" }],
1607
+ ["path", { d: "M18.89 13.23A7 7 0 0 0 19 12v-2", key: "16hl24" }],
1608
+ ["path", { d: "m2 2 20 20", key: "1ooewy" }],
1609
+ ["path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12", key: "r2i35w" }]
1610
+ ];
1611
+ var MicOff = createLucideIcon("mic-off", __iconNode10);
1612
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic.js
1613
+ var __iconNode11 = [
1614
+ ["path", { d: "M12 19v3", key: "npa21l" }],
1615
+ ["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
1616
+ ["rect", { x: "9", y: "2", width: "6", height: "13", rx: "3", key: "s6n7sd" }]
1617
+ ];
1618
+ var Mic = createLucideIcon("mic", __iconNode11);
1619
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/minimize-2.js
1620
+ var __iconNode12 = [
1621
+ ["path", { d: "m14 10 7-7", key: "oa77jy" }],
1622
+ ["path", { d: "M20 10h-6V4", key: "mjg0md" }],
1623
+ ["path", { d: "m3 21 7-7", key: "tjx5ai" }],
1624
+ ["path", { d: "M4 14h6v6", key: "rmj7iw" }]
1625
+ ];
1626
+ var Minimize2 = createLucideIcon("minimize-2", __iconNode12);
1627
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor-off.js
1628
+ var __iconNode13 = [
1629
+ ["path", { d: "M12 17v4", key: "1riwvh" }],
1630
+ ["path", { d: "M17 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 1.184-1.826", key: "cv7jms" }],
1631
+ ["path", { d: "m2 2 20 20", key: "1ooewy" }],
1632
+ ["path", { d: "M8 21h8", key: "1ev6f3" }],
1633
+ ["path", { d: "M8.656 3H20a2 2 0 0 1 2 2v10a2 2 0 0 1-.293 1.042", key: "z8ni2w" }]
1634
+ ];
1635
+ var MonitorOff = createLucideIcon("monitor-off", __iconNode13);
1636
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor.js
1637
+ var __iconNode14 = [
1638
+ ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
1639
+ ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
1640
+ ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
1641
+ ];
1642
+ var Monitor = createLucideIcon("monitor", __iconNode14);
1643
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/phone-off.js
1644
+ var __iconNode15 = [
1645
+ [
1646
+ "path",
1647
+ {
1648
+ d: "M10.1 13.9a14 14 0 0 0 3.732 2.668 1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2 18 18 0 0 1-12.728-5.272",
1649
+ key: "1wngk7"
1650
+ }
1651
+ ],
1652
+ ["path", { d: "M22 2 2 22", key: "y4kqgn" }],
1653
+ [
1654
+ "path",
1655
+ {
1656
+ d: "M4.76 13.582A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 .244.473",
1657
+ key: "10hv5p"
1658
+ }
1659
+ ]
1660
+ ];
1661
+ var PhoneOff = createLucideIcon("phone-off", __iconNode15);
1662
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/send.js
1663
+ var __iconNode16 = [
1664
+ [
1665
+ "path",
1666
+ {
1667
+ d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",
1668
+ key: "1ffxy3"
1669
+ }
1670
+ ],
1671
+ ["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
1672
+ ];
1673
+ var Send = createLucideIcon("send", __iconNode16);
1674
+ // src/components/MinimizedBubble.tsx
1675
+ import { useEffect as useEffect6 } from "react";
1676
+
1677
+ // src/hooks/useLiveAgent.ts
1678
+ import { use } from "react";
1679
+ function useLiveAgent() {
1680
+ const ctx = use(LiveAgentContext);
1681
+ if (!ctx) {
1682
+ throw new Error("useLiveAgent must be used within a <LiveAgent> provider");
1683
+ }
1684
+ const { connection, shouldConnect, ...publicValue } = ctx;
1685
+ return publicValue;
1686
+ }
1687
+
1688
+ // src/hooks/useMediaControls.ts
1689
+ import { useLocalParticipant as useLocalParticipant3 } from "@livekit/components-react/hooks";
1690
+ import { ScreenSharePresets as ScreenSharePresets2 } from "livekit-client";
1691
+ import { useCallback as useCallback4 } from "react";
1692
+ var SCREEN_SHARE_OPTIONS = {
1693
+ video: { displaySurface: "browser" },
1694
+ resolution: ScreenSharePresets2.h720fps30.resolution,
1695
+ contentHint: "detail"
1696
+ };
1697
+ function useMediaControls() {
1698
+ const { localParticipant } = useLocalParticipant3();
1699
+ const isMuted = !localParticipant.isMicrophoneEnabled;
1700
+ const isScreenSharing = localParticipant.isScreenShareEnabled;
1701
+ const toggleMute = useCallback4(async () => {
1702
+ try {
1703
+ await localParticipant.setMicrophoneEnabled(isMuted);
1704
+ } catch (error) {
1705
+ console.error("Failed to toggle microphone:", error);
1706
+ }
1707
+ }, [localParticipant, isMuted]);
1708
+ const toggleScreenShare = useCallback4(async () => {
1709
+ try {
1710
+ await localParticipant.setScreenShareEnabled(!isScreenSharing, SCREEN_SHARE_OPTIONS);
1711
+ } catch (error) {
1712
+ console.error("Failed to toggle screen share:", error);
1713
+ }
1714
+ }, [localParticipant, isScreenSharing]);
1715
+ return { isMuted, toggleMute, isScreenSharing, toggleScreenShare };
1716
+ }
1717
+
1718
+ // src/lib/utils.ts
1719
+ import { clsx } from "clsx";
1720
+ import { twMerge } from "tailwind-merge";
1721
+ function cn(...inputs) {
1722
+ return twMerge(clsx(inputs));
1723
+ }
1724
+
1725
+ // src/hooks/useAgentVoiceState.ts
1726
+ import { useVoiceAssistant } from "@livekit/components-react/hooks";
1727
+ function useAgentVoiceState() {
1728
+ const { state } = useVoiceAssistant();
1729
+ return {
1730
+ state,
1731
+ isSpeaking: state === "speaking",
1732
+ isListening: state === "listening"
1803
1733
  };
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"
1734
+ }
1735
+
1736
+ // src/components/LauncherStatusPill.tsx
1737
+ import { jsx as jsx2, jsxs as jsxs2, Fragment as Fragment2 } from "react/jsx-runtime";
1738
+ function pillStatusFromAgent(state, canSeePage) {
1739
+ if (state === "speaking")
1740
+ return "talking";
1741
+ if (state === "thinking")
1742
+ return "thinking";
1743
+ return canSeePage ? "observing" : "connected";
1744
+ }
1745
+ function LauncherStatusPill() {
1746
+ const { isConnected, expandPanel, setSidebarTab, position, captureMode } = useLiveAgent();
1747
+ const { state } = useAgentVoiceState();
1748
+ const { isScreenSharing } = useMediaControls();
1749
+ if (!isConnected)
1750
+ return null;
1751
+ const canSeePage = captureMode === "auto" || isScreenSharing;
1752
+ const status = pillStatusFromAgent(state, canSeePage);
1753
+ const openChat = () => {
1754
+ setSidebarTab("chat");
1755
+ expandPanel();
1826
1756
  };
1827
- return /* @__PURE__ */ jsxs2(Fragment2, {
1757
+ return /* @__PURE__ */ jsx2("button", {
1758
+ type: "button",
1759
+ onClick: openChat,
1760
+ className: cn("skippr:fixed skippr:bottom-20 skippr:z-[9999]", "skippr:flex skippr:items-center skippr:gap-2", "skippr:rounded-full skippr:bg-bubble/95 skippr:backdrop-blur-sm", "skippr:px-3 skippr:py-1.5", "skippr:text-xs skippr:font-medium skippr:text-white", "skippr:shadow-[0_8px_24px_rgba(45,43,61,0.35)]", "skippr:cursor-pointer skippr:transition-colors skippr:hover:bg-bubble", "skippr:animate-[skippr-bubble-in_0.28s_ease-out]", position === "right" ? "skippr:right-6" : "skippr:left-6"),
1761
+ "aria-label": `Skippr is ${status} — click to open chat`,
1762
+ children: /* @__PURE__ */ jsxs2("span", {
1763
+ className: "skippr:flex skippr:items-center skippr:gap-2 skippr:animate-[skippr-pill-content_0.22s_ease-out]",
1764
+ children: [
1765
+ status === "observing" && /* @__PURE__ */ jsxs2(Fragment2, {
1766
+ children: [
1767
+ /* @__PURE__ */ jsx2(ObservingIcon, {}),
1768
+ /* @__PURE__ */ jsx2("span", {
1769
+ children: "Skippr is observing"
1770
+ })
1771
+ ]
1772
+ }),
1773
+ status === "connected" && /* @__PURE__ */ jsxs2(Fragment2, {
1774
+ children: [
1775
+ /* @__PURE__ */ jsx2(ConnectedDot, {}),
1776
+ /* @__PURE__ */ jsx2("span", {
1777
+ children: "Skippr is connected"
1778
+ })
1779
+ ]
1780
+ }),
1781
+ status === "talking" && /* @__PURE__ */ jsxs2(Fragment2, {
1782
+ children: [
1783
+ /* @__PURE__ */ jsx2(SpeakingBars, {}),
1784
+ /* @__PURE__ */ jsx2("span", {
1785
+ children: "Skippr is talking"
1786
+ })
1787
+ ]
1788
+ }),
1789
+ status === "thinking" && /* @__PURE__ */ jsxs2(Fragment2, {
1790
+ children: [
1791
+ /* @__PURE__ */ jsx2(ThinkingDots, {}),
1792
+ /* @__PURE__ */ jsx2("span", {
1793
+ children: "Skippr is thinking"
1794
+ })
1795
+ ]
1796
+ })
1797
+ ]
1798
+ }, status)
1799
+ });
1800
+ }
1801
+ function ConnectedDot() {
1802
+ return /* @__PURE__ */ jsxs2("span", {
1803
+ className: "skippr:relative skippr:flex skippr:size-2",
1828
1804
  children: [
1829
- /* @__PURE__ */ jsx2("div", {
1830
- "data-skippr-private": "true",
1831
- style: ringStyle,
1832
- "aria-hidden": "true"
1805
+ /* @__PURE__ */ jsx2("span", {
1806
+ className: "skippr:absolute skippr:inline-flex skippr:size-full skippr:animate-ping skippr:rounded-full skippr:bg-emerald-400 skippr:opacity-75"
1833
1807
  }),
1834
- message && /* @__PURE__ */ jsx2("div", {
1835
- "data-skippr-private": "true",
1836
- style: tooltipStyle,
1837
- role: "tooltip",
1838
- children: message
1808
+ /* @__PURE__ */ jsx2("span", {
1809
+ className: "skippr:relative skippr:inline-flex skippr:size-2 skippr:rounded-full skippr:bg-emerald-400"
1839
1810
  })
1840
1811
  ]
1841
1812
  });
1842
1813
  }
1843
-
1844
- // src/components/MinimizedBubble.tsx
1845
- import { useEffect as useEffect6 } from "react";
1846
-
1847
- // src/lib/utils.ts
1848
- import { clsx } from "clsx";
1849
- import { twMerge } from "tailwind-merge";
1850
- function cn(...inputs) {
1851
- return twMerge(clsx(inputs));
1814
+ function ObservingIcon() {
1815
+ return /* @__PURE__ */ jsxs2("svg", {
1816
+ viewBox: "0 0 24 24",
1817
+ className: "skippr:size-3.5",
1818
+ fill: "none",
1819
+ stroke: "currentColor",
1820
+ strokeWidth: "2",
1821
+ strokeLinecap: "round",
1822
+ strokeLinejoin: "round",
1823
+ "aria-hidden": "true",
1824
+ children: [
1825
+ /* @__PURE__ */ jsx2("path", {
1826
+ d: "M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"
1827
+ }),
1828
+ /* @__PURE__ */ jsx2("circle", {
1829
+ cx: "12",
1830
+ cy: "12",
1831
+ r: "3",
1832
+ fill: "currentColor",
1833
+ stroke: "none",
1834
+ className: "skippr:origin-center skippr:animate-[skippr-banner-look_2.4s_ease-in-out_infinite]"
1835
+ })
1836
+ ]
1837
+ });
1838
+ }
1839
+ function SpeakingBars() {
1840
+ return /* @__PURE__ */ jsxs2("span", {
1841
+ className: "skippr:flex skippr:items-center skippr:gap-[2px] skippr:h-3.5",
1842
+ children: [
1843
+ /* @__PURE__ */ jsx2("span", {
1844
+ className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_infinite] skippr:h-1.5"
1845
+ }),
1846
+ /* @__PURE__ */ jsx2("span", {
1847
+ className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.15s_infinite] skippr:h-3"
1848
+ }),
1849
+ /* @__PURE__ */ jsx2("span", {
1850
+ className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.3s_infinite] skippr:h-2"
1851
+ }),
1852
+ /* @__PURE__ */ jsx2("span", {
1853
+ className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.45s_infinite] skippr:h-3.5"
1854
+ }),
1855
+ /* @__PURE__ */ jsx2("span", {
1856
+ className: "skippr:w-[2px] skippr:rounded-sm skippr:bg-white skippr:animate-[skippr-speak_1.1s_ease-in-out_0.6s_infinite] skippr:h-1"
1857
+ })
1858
+ ]
1859
+ });
1860
+ }
1861
+ function ThinkingDots() {
1862
+ return /* @__PURE__ */ jsxs2("span", {
1863
+ className: "skippr:flex skippr:items-center skippr:gap-[3px]",
1864
+ children: [
1865
+ /* @__PURE__ */ jsx2("span", {
1866
+ className: "skippr:size-1 skippr:rounded-full skippr:bg-white skippr:animate-bounce skippr:[animation-delay:0ms]"
1867
+ }),
1868
+ /* @__PURE__ */ jsx2("span", {
1869
+ className: "skippr:size-1 skippr:rounded-full skippr:bg-white skippr:animate-bounce skippr:[animation-delay:150ms]"
1870
+ }),
1871
+ /* @__PURE__ */ jsx2("span", {
1872
+ className: "skippr:size-1 skippr:rounded-full skippr:bg-white skippr:animate-bounce skippr:[animation-delay:300ms]"
1873
+ })
1874
+ ]
1875
+ });
1852
1876
  }
1853
1877
 
1854
1878
  // src/components/Logo.tsx
@@ -1933,115 +1957,72 @@ function Logo({ className }) {
1933
1957
  });
1934
1958
  }
1935
1959
 
1936
- // src/components/ui/tooltip.tsx
1937
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1938
- var ALIGN_CLASSES = {
1939
- center: "skippr:left-1/2 skippr:-translate-x-1/2",
1940
- start: "skippr:left-0",
1941
- end: "skippr:right-0"
1942
- };
1943
- function Tooltip({ label, children, position = "top", align = "center" }) {
1944
- return /* @__PURE__ */ jsxs4("span", {
1945
- className: "skippr:relative skippr:inline-flex skippr:group",
1946
- children: [
1947
- children,
1948
- /* @__PURE__ */ jsx4("span", {
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"),
1950
- "aria-hidden": "true",
1951
- children: label
1952
- })
1953
- ]
1954
- });
1955
- }
1956
-
1957
1960
  // src/components/MinimizedBubble.tsx
1958
- import { jsx as jsx5, jsxs as jsxs5, Fragment as Fragment3 } from "react/jsx-runtime";
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";
1960
- function ConnectedBubbleContent() {
1961
- const { expandPanel, disconnect, position, captureMode } = useLiveAgent();
1961
+ import { jsx as jsx4, jsxs as jsxs4, Fragment as Fragment3 } from "react/jsx-runtime";
1962
+ var CONTROL_BUTTON = "skippr:flex skippr:size-12 skippr:items-center skippr:justify-center skippr:rounded-[14px] skippr:cursor-pointer skippr:transition-all skippr:hover:-translate-y-0.5 skippr:active:translate-y-0";
1963
+ var CONTROL_SHADOW = "skippr:shadow-[0_4px_16px_rgba(0,0,0,0.15),0_2px_4px_rgba(0,0,0,0.1)]";
1964
+ function ConnectedLauncher() {
1965
+ const { expandPanel, disconnect, captureMode, setSidebarTab } = useLiveAgent();
1962
1966
  const { isMuted, toggleMute, isScreenSharing, toggleScreenShare } = useMediaControls();
1963
- const tooltipAlign = position === "right" ? "end" : "start";
1964
1967
  const showScreenShareToggle = captureMode === "screenshare";
1965
- return /* @__PURE__ */ jsxs5(Fragment3, {
1968
+ const openChat = () => {
1969
+ setSidebarTab("chat");
1970
+ expandPanel();
1971
+ };
1972
+ return /* @__PURE__ */ jsxs4(Fragment3, {
1966
1973
  children: [
1967
- /* @__PURE__ */ jsx5(Tooltip, {
1968
- label: isMuted ? "Unmute" : "Mute",
1969
- align: tooltipAlign,
1970
- children: /* @__PURE__ */ jsx5("button", {
1971
- type: "button",
1972
- onClick: toggleMute,
1973
- "aria-label": isMuted ? "Unmute" : "Mute",
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"),
1975
- children: isMuted ? /* @__PURE__ */ jsx5(MicOff, {
1976
- className: "skippr:size-5"
1977
- }) : /* @__PURE__ */ jsx5(Mic, {
1978
- className: "skippr:size-5"
1979
- })
1974
+ /* @__PURE__ */ jsx4("button", {
1975
+ type: "button",
1976
+ onClick: toggleMute,
1977
+ "aria-label": isMuted ? "Unmute" : "Mute",
1978
+ className: cn(CONTROL_BUTTON, CONTROL_SHADOW, isMuted ? "skippr:bg-destructive/10 skippr:text-destructive skippr:hover:bg-destructive/20" : "skippr:bg-white skippr:text-foreground skippr:hover:bg-muted"),
1979
+ children: isMuted ? /* @__PURE__ */ jsx4(MicOff, {
1980
+ className: "skippr:size-5"
1981
+ }) : /* @__PURE__ */ jsx4(Mic, {
1982
+ className: "skippr:size-5"
1980
1983
  })
1981
1984
  }),
1982
- showScreenShareToggle && /* @__PURE__ */ jsx5(Tooltip, {
1983
- label: isScreenSharing ? "Stop sharing" : "Share screen",
1984
- align: tooltipAlign,
1985
- children: /* @__PURE__ */ jsx5("button", {
1986
- type: "button",
1987
- onClick: toggleScreenShare,
1988
- "aria-label": isScreenSharing ? "Stop sharing screen" : "Share screen",
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"),
1990
- children: isScreenSharing ? /* @__PURE__ */ jsx5(MonitorOff, {
1991
- className: "skippr:size-5"
1992
- }) : /* @__PURE__ */ jsx5(Monitor, {
1993
- className: "skippr:size-5"
1994
- })
1985
+ showScreenShareToggle && /* @__PURE__ */ jsx4("button", {
1986
+ type: "button",
1987
+ onClick: toggleScreenShare,
1988
+ "aria-label": isScreenSharing ? "Stop sharing screen" : "Share screen",
1989
+ className: cn(CONTROL_BUTTON, CONTROL_SHADOW, isScreenSharing ? "skippr:bg-primary skippr:text-primary-foreground skippr:hover:bg-primary/90" : "skippr:bg-white skippr:text-foreground skippr:hover:bg-muted"),
1990
+ children: isScreenSharing ? /* @__PURE__ */ jsx4(MonitorOff, {
1991
+ className: "skippr:size-5"
1992
+ }) : /* @__PURE__ */ jsx4(Monitor, {
1993
+ className: "skippr:size-5"
1995
1994
  })
1996
1995
  }),
1997
- /* @__PURE__ */ jsx5(Tooltip, {
1998
- label: "End session",
1999
- align: tooltipAlign,
2000
- children: /* @__PURE__ */ jsx5("button", {
2001
- type: "button",
2002
- onClick: () => disconnect(),
2003
- "aria-label": "End session",
2004
- className: cn(BUBBLE_BUTTON, "skippr:bg-destructive skippr:text-destructive-foreground skippr:hover:bg-destructive/90"),
2005
- children: /* @__PURE__ */ jsx5(PhoneOff, {
2006
- className: "skippr:size-5"
2007
- })
1996
+ /* @__PURE__ */ jsx4("button", {
1997
+ type: "button",
1998
+ onClick: () => disconnect(),
1999
+ "aria-label": "End session",
2000
+ className: cn(CONTROL_BUTTON, "skippr:bg-destructive skippr:text-destructive-foreground skippr:hover:bg-destructive/90", "skippr:shadow-[0_4px_16px_rgba(217,79,79,0.45),0_2px_4px_rgba(0,0,0,0.1)]"),
2001
+ children: /* @__PURE__ */ jsx4(PhoneOff, {
2002
+ className: "skippr:size-5"
2008
2003
  })
2009
2004
  }),
2010
- /* @__PURE__ */ jsx5(Tooltip, {
2011
- label: "Open chat & transcript",
2012
- align: tooltipAlign,
2013
- children: /* @__PURE__ */ jsx5("button", {
2014
- type: "button",
2015
- onClick: expandPanel,
2016
- "aria-label": "Open chat & transcript",
2017
- className: cn(BUBBLE_BUTTON, "skippr:bg-bubble skippr:hover:brightness-110"),
2018
- children: /* @__PURE__ */ jsx5(Logo, {
2019
- className: "skippr:size-7"
2020
- })
2005
+ /* @__PURE__ */ jsx4("button", {
2006
+ type: "button",
2007
+ onClick: openChat,
2008
+ "aria-label": "Open chat",
2009
+ className: cn(CONTROL_BUTTON, "skippr:bg-bubble skippr:text-white skippr:overflow-hidden", "skippr:shadow-[0_4px_16px_rgba(45,43,61,0.45),0_2px_4px_rgba(0,0,0,0.1)]", "skippr:hover:shadow-[0_6px_24px_rgba(45,43,61,0.55),0_4px_8px_rgba(0,0,0,0.1)]"),
2010
+ children: /* @__PURE__ */ jsx4(MessageSquare, {
2011
+ className: "skippr:size-5"
2021
2012
  })
2022
2013
  })
2023
2014
  ]
2024
2015
  });
2025
2016
  }
2026
- function IdleBubbleContent() {
2027
- const { expandPanel, position } = useLiveAgent();
2028
- const tooltipAlign = position === "right" ? "end" : "start";
2029
- return /* @__PURE__ */ jsx5(Tooltip, {
2030
- label: "Open Skippr assistant",
2031
- align: tooltipAlign,
2032
- children: /* @__PURE__ */ jsxs5("button", {
2033
- type: "button",
2034
- onClick: expandPanel,
2035
- "aria-label": "Skippr assistant",
2036
- className: cn(BUBBLE_BUTTON, "skippr:relative skippr:bg-bubble skippr:hover:brightness-110"),
2037
- children: [
2038
- /* @__PURE__ */ jsx5(Logo, {
2039
- className: "skippr:relative skippr:z-10 skippr:size-7"
2040
- }),
2041
- /* @__PURE__ */ jsx5("span", {
2042
- className: "skippr:absolute skippr:-inset-[3px] skippr:animate-pulse skippr:rounded-[17px] skippr:border-2 skippr:border-bubble/50"
2043
- })
2044
- ]
2017
+ function IdleLauncher() {
2018
+ const { expandPanel } = useLiveAgent();
2019
+ return /* @__PURE__ */ jsx4("button", {
2020
+ type: "button",
2021
+ onClick: expandPanel,
2022
+ "aria-label": "Skippr assistant",
2023
+ className: cn("skippr:flex skippr:size-12 skippr:items-center skippr:justify-center", "skippr:rounded-[14px] skippr:bg-bubble skippr:cursor-pointer", "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"),
2024
+ children: /* @__PURE__ */ jsx4(Logo, {
2025
+ className: "skippr:size-7"
2045
2026
  })
2046
2027
  });
2047
2028
  }
@@ -2054,14 +2035,14 @@ function WelcomeBubble({
2054
2035
  const timer = setTimeout(onDismiss, 5000);
2055
2036
  return () => clearTimeout(timer);
2056
2037
  }, [onDismiss]);
2057
- return /* @__PURE__ */ jsxs5("button", {
2038
+ return /* @__PURE__ */ jsxs4("button", {
2058
2039
  type: "button",
2059
2040
  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"),
2060
2041
  onClick: onDismiss,
2061
2042
  "aria-label": "Dismiss",
2062
2043
  children: [
2063
2044
  message,
2064
- /* @__PURE__ */ jsx5("span", {
2045
+ /* @__PURE__ */ jsx4("span", {
2065
2046
  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]")
2066
2047
  })
2067
2048
  ]
@@ -2074,15 +2055,20 @@ function MinimizedBubble({
2074
2055
  }) {
2075
2056
  const { isConnected, isStarting, position } = useLiveAgent();
2076
2057
  const inSession = isConnected || isStarting;
2077
- return /* @__PURE__ */ jsxs5("div", {
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"),
2058
+ return /* @__PURE__ */ jsxs4(Fragment3, {
2079
2059
  children: [
2080
- welcomeMessage && !inSession && !welcomeDismissed && /* @__PURE__ */ jsx5(WelcomeBubble, {
2081
- message: welcomeMessage,
2082
- position,
2083
- onDismiss: onDismissWelcome
2084
- }),
2085
- inSession ? /* @__PURE__ */ jsx5(ConnectedBubbleContent, {}) : /* @__PURE__ */ jsx5(IdleBubbleContent, {})
2060
+ /* @__PURE__ */ jsx4(LauncherStatusPill, {}),
2061
+ /* @__PURE__ */ jsxs4("div", {
2062
+ 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"),
2063
+ children: [
2064
+ welcomeMessage && !inSession && !welcomeDismissed && /* @__PURE__ */ jsx4(WelcomeBubble, {
2065
+ message: welcomeMessage,
2066
+ position,
2067
+ onDismiss: onDismissWelcome
2068
+ }),
2069
+ inSession ? /* @__PURE__ */ jsx4(ConnectedLauncher, {}) : /* @__PURE__ */ jsx4(IdleLauncher, {})
2070
+ ]
2071
+ })
2086
2072
  ]
2087
2073
  });
2088
2074
  }
@@ -2284,50 +2270,50 @@ function useElapsedSeconds(isRunning) {
2284
2270
  }
2285
2271
 
2286
2272
  // src/components/ChatHeader.tsx
2287
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2273
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2288
2274
  function ChatHeader() {
2289
2275
  const { isConnected, minimizePanel, minimizable } = useLiveAgent();
2290
2276
  const elapsed = useElapsedSeconds(isConnected);
2291
- return /* @__PURE__ */ jsxs6("header", {
2277
+ return /* @__PURE__ */ jsxs5("header", {
2292
2278
  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",
2293
2279
  children: [
2294
- /* @__PURE__ */ jsx6("p", {
2280
+ /* @__PURE__ */ jsx5("p", {
2295
2281
  className: "skippr:text-sm skippr:font-semibold skippr:text-primary-foreground",
2296
2282
  children: "Skippr"
2297
2283
  }),
2298
- /* @__PURE__ */ jsxs6("div", {
2284
+ /* @__PURE__ */ jsxs5("div", {
2299
2285
  className: "skippr:flex skippr:items-center skippr:gap-2",
2300
2286
  children: [
2301
- isConnected && /* @__PURE__ */ jsxs6("div", {
2287
+ isConnected && /* @__PURE__ */ jsxs5("div", {
2302
2288
  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",
2303
2289
  children: [
2304
- /* @__PURE__ */ jsxs6("span", {
2290
+ /* @__PURE__ */ jsxs5("span", {
2305
2291
  className: "skippr:relative skippr:flex skippr:size-1.5",
2306
2292
  children: [
2307
- /* @__PURE__ */ jsx6("span", {
2293
+ /* @__PURE__ */ jsx5("span", {
2308
2294
  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"
2309
2295
  }),
2310
- /* @__PURE__ */ jsx6("span", {
2296
+ /* @__PURE__ */ jsx5("span", {
2311
2297
  className: "skippr:relative skippr:inline-flex skippr:size-1.5 skippr:rounded-full skippr:bg-red-400"
2312
2298
  })
2313
2299
  ]
2314
2300
  }),
2315
- /* @__PURE__ */ jsx6("span", {
2301
+ /* @__PURE__ */ jsx5("span", {
2316
2302
  className: "skippr:text-[10px] skippr:font-medium skippr:text-primary-foreground",
2317
2303
  children: "REC"
2318
2304
  }),
2319
- /* @__PURE__ */ jsx6("span", {
2305
+ /* @__PURE__ */ jsx5("span", {
2320
2306
  className: "skippr:text-[10px] skippr:font-mono skippr:text-primary-foreground",
2321
2307
  children: formatTime(elapsed)
2322
2308
  })
2323
2309
  ]
2324
2310
  }),
2325
- minimizable && /* @__PURE__ */ jsx6("button", {
2311
+ minimizable && /* @__PURE__ */ jsx5("button", {
2326
2312
  type: "button",
2327
2313
  onClick: minimizePanel,
2328
2314
  "aria-label": "Minimize",
2329
2315
  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",
2330
- children: /* @__PURE__ */ jsx6(Minimize2, {
2316
+ children: /* @__PURE__ */ jsx5(Minimize2, {
2331
2317
  className: "skippr:size-3.5"
2332
2318
  })
2333
2319
  })
@@ -2338,26 +2324,26 @@ function ChatHeader() {
2338
2324
  }
2339
2325
 
2340
2326
  // src/components/LoadingDots.tsx
2341
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2327
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2342
2328
  function LoadingDots({ label }) {
2343
- return /* @__PURE__ */ jsxs7("div", {
2329
+ return /* @__PURE__ */ jsxs6("div", {
2344
2330
  className: "skippr:flex skippr:items-center skippr:gap-2 skippr:py-4",
2345
2331
  children: [
2346
- /* @__PURE__ */ jsxs7("div", {
2332
+ /* @__PURE__ */ jsxs6("div", {
2347
2333
  className: "skippr:flex skippr:gap-1",
2348
2334
  children: [
2349
- /* @__PURE__ */ jsx7("span", {
2335
+ /* @__PURE__ */ jsx6("span", {
2350
2336
  className: "skippr:size-1.5 skippr:rounded-full skippr:bg-muted-foreground/40 skippr:animate-bounce skippr:[animation-delay:0ms]"
2351
2337
  }),
2352
- /* @__PURE__ */ jsx7("span", {
2338
+ /* @__PURE__ */ jsx6("span", {
2353
2339
  className: "skippr:size-1.5 skippr:rounded-full skippr:bg-muted-foreground/40 skippr:animate-bounce skippr:[animation-delay:150ms]"
2354
2340
  }),
2355
- /* @__PURE__ */ jsx7("span", {
2341
+ /* @__PURE__ */ jsx6("span", {
2356
2342
  className: "skippr:size-1.5 skippr:rounded-full skippr:bg-muted-foreground/40 skippr:animate-bounce skippr:[animation-delay:300ms]"
2357
2343
  })
2358
2344
  ]
2359
2345
  }),
2360
- /* @__PURE__ */ jsx7("p", {
2346
+ /* @__PURE__ */ jsx6("p", {
2361
2347
  className: "skippr:text-xs skippr:text-muted-foreground",
2362
2348
  children: label
2363
2349
  })
@@ -2370,7 +2356,7 @@ import { useCallback as useCallback6, useEffect as useEffect10, useRef as useRef
2370
2356
 
2371
2357
  // src/components/ui/button.tsx
2372
2358
  import { forwardRef as forwardRef3 } from "react";
2373
- import { jsx as jsx8 } from "react/jsx-runtime";
2359
+ import { jsx as jsx7 } from "react/jsx-runtime";
2374
2360
  var variantClasses = {
2375
2361
  default: "skippr:bg-primary skippr:text-primary-foreground skippr:hover:bg-primary/90",
2376
2362
  destructive: "skippr:bg-destructive skippr:text-white skippr:hover:bg-destructive/90",
@@ -2389,7 +2375,7 @@ var sizeClasses = {
2389
2375
  "icon-lg": "skippr:size-10"
2390
2376
  };
2391
2377
  var Button = forwardRef3(({ className, variant = "default", size = "default", ...props }, ref) => {
2392
- return /* @__PURE__ */ jsx8("button", {
2378
+ return /* @__PURE__ */ jsx7("button", {
2393
2379
  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),
2394
2380
  ref,
2395
2381
  ...props
@@ -2398,7 +2384,7 @@ var Button = forwardRef3(({ className, variant = "default", size = "default", ..
2398
2384
  Button.displayName = "Button";
2399
2385
 
2400
2386
  // src/components/LoginFlow.tsx
2401
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2387
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2402
2388
  var OTP_LENGTH = 6;
2403
2389
  var DIGIT_KEYS = ["d0", "d1", "d2", "d3", "d4", "d5"];
2404
2390
  function LoginFlow({ requestOtp, verifyOtp, error, isSubmitting }) {
@@ -2419,7 +2405,7 @@ function LoginFlow({ requestOtp, verifyOtp, error, isSubmitting }) {
2419
2405
  await requestOtp(email);
2420
2406
  }, [requestOtp, email]);
2421
2407
  if (step === "otp") {
2422
- return /* @__PURE__ */ jsx9(OtpStep, {
2408
+ return /* @__PURE__ */ jsx8(OtpStep, {
2423
2409
  email,
2424
2410
  onSubmit: handleVerifyOtp,
2425
2411
  onResend: handleResend,
@@ -2428,7 +2414,7 @@ function LoginFlow({ requestOtp, verifyOtp, error, isSubmitting }) {
2428
2414
  isSubmitting
2429
2415
  });
2430
2416
  }
2431
- return /* @__PURE__ */ jsx9(EmailStep, {
2417
+ return /* @__PURE__ */ jsx8(EmailStep, {
2432
2418
  email,
2433
2419
  onEmailChange: setEmail,
2434
2420
  onSubmit: handleRequestOtp,
@@ -2442,30 +2428,30 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
2442
2428
  if (email.trim())
2443
2429
  onSubmit(email.trim());
2444
2430
  }
2445
- return /* @__PURE__ */ jsxs8("div", {
2431
+ return /* @__PURE__ */ jsxs7("div", {
2446
2432
  className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:px-4 skippr:py-4",
2447
2433
  children: [
2448
- /* @__PURE__ */ jsxs8("div", {
2434
+ /* @__PURE__ */ jsxs7("div", {
2449
2435
  className: "skippr:mb-4 skippr:text-center",
2450
2436
  children: [
2451
- /* @__PURE__ */ jsx9(Mail, {
2437
+ /* @__PURE__ */ jsx8(Mail, {
2452
2438
  className: "skippr:mx-auto skippr:mb-2 skippr:size-6 skippr:text-primary"
2453
2439
  }),
2454
- /* @__PURE__ */ jsx9("p", {
2440
+ /* @__PURE__ */ jsx8("p", {
2455
2441
  className: "skippr:text-sm skippr:font-medium skippr:text-foreground",
2456
2442
  children: "Sign in to continue"
2457
2443
  }),
2458
- /* @__PURE__ */ jsx9("p", {
2444
+ /* @__PURE__ */ jsx8("p", {
2459
2445
  className: "skippr:mt-1 skippr:text-xs skippr:text-muted-foreground",
2460
2446
  children: "Your email will be used to identify you across sessions"
2461
2447
  })
2462
2448
  ]
2463
2449
  }),
2464
- /* @__PURE__ */ jsxs8("form", {
2450
+ /* @__PURE__ */ jsxs7("form", {
2465
2451
  onSubmit: handleSubmit,
2466
2452
  className: "skippr:flex skippr:flex-col skippr:gap-3",
2467
2453
  children: [
2468
- /* @__PURE__ */ jsx9("input", {
2454
+ /* @__PURE__ */ jsx8("input", {
2469
2455
  type: "email",
2470
2456
  placeholder: "you@example.com",
2471
2457
  value: email,
@@ -2474,15 +2460,15 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
2474
2460
  required: true,
2475
2461
  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"
2476
2462
  }),
2477
- /* @__PURE__ */ jsx9(Button, {
2463
+ /* @__PURE__ */ jsx8(Button, {
2478
2464
  type: "submit",
2479
2465
  disabled: isSubmitting || !email.trim(),
2480
2466
  className: "skippr:w-full",
2481
- children: isSubmitting ? /* @__PURE__ */ jsx9(LoaderCircle, {
2467
+ children: isSubmitting ? /* @__PURE__ */ jsx8(LoaderCircle, {
2482
2468
  className: "skippr:size-4 skippr:animate-spin"
2483
2469
  }) : "Continue"
2484
2470
  }),
2485
- error && /* @__PURE__ */ jsx9("p", {
2471
+ error && /* @__PURE__ */ jsx8("p", {
2486
2472
  className: "skippr:text-xs skippr:text-center skippr:text-destructive",
2487
2473
  children: error
2488
2474
  })
@@ -2562,22 +2548,22 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2562
2548
  submittedRef.current = false;
2563
2549
  inputRefs.current[0]?.focus();
2564
2550
  }
2565
- return /* @__PURE__ */ jsxs8("div", {
2551
+ return /* @__PURE__ */ jsxs7("div", {
2566
2552
  className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:px-4 skippr:py-4",
2567
2553
  children: [
2568
- /* @__PURE__ */ jsxs8("div", {
2554
+ /* @__PURE__ */ jsxs7("div", {
2569
2555
  className: "skippr:mb-4 skippr:text-center",
2570
2556
  children: [
2571
- /* @__PURE__ */ jsx9("p", {
2557
+ /* @__PURE__ */ jsx8("p", {
2572
2558
  className: "skippr:text-sm skippr:font-medium skippr:text-foreground",
2573
2559
  children: "Enter verification code"
2574
2560
  }),
2575
- /* @__PURE__ */ jsxs8("p", {
2561
+ /* @__PURE__ */ jsxs7("p", {
2576
2562
  className: "skippr:mt-1 skippr:text-xs skippr:text-muted-foreground",
2577
2563
  children: [
2578
2564
  "We sent a 6-digit code to",
2579
2565
  " ",
2580
- /* @__PURE__ */ jsx9("span", {
2566
+ /* @__PURE__ */ jsx8("span", {
2581
2567
  className: "skippr:font-medium skippr:text-foreground",
2582
2568
  children: email
2583
2569
  })
@@ -2585,13 +2571,13 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2585
2571
  })
2586
2572
  ]
2587
2573
  }),
2588
- /* @__PURE__ */ jsxs8("form", {
2574
+ /* @__PURE__ */ jsxs7("form", {
2589
2575
  onSubmit: handleSubmit,
2590
2576
  className: "skippr:flex skippr:flex-col skippr:gap-3",
2591
2577
  children: [
2592
- /* @__PURE__ */ jsx9("div", {
2578
+ /* @__PURE__ */ jsx8("div", {
2593
2579
  className: "skippr:flex skippr:justify-center skippr:gap-1.5",
2594
- children: digits.map((digit, index2) => /* @__PURE__ */ jsx9("input", {
2580
+ children: digits.map((digit, index2) => /* @__PURE__ */ jsx8("input", {
2595
2581
  ref: (el) => {
2596
2582
  inputRefs.current[index2] = el;
2597
2583
  },
@@ -2606,29 +2592,29 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2606
2592
  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"
2607
2593
  }, DIGIT_KEYS[index2]))
2608
2594
  }),
2609
- error && /* @__PURE__ */ jsx9("p", {
2595
+ error && /* @__PURE__ */ jsx8("p", {
2610
2596
  className: "skippr:text-xs skippr:text-center skippr:text-destructive",
2611
2597
  children: error
2612
2598
  }),
2613
- /* @__PURE__ */ jsx9(Button, {
2599
+ /* @__PURE__ */ jsx8(Button, {
2614
2600
  type: "submit",
2615
2601
  disabled: isSubmitting || digits.join("").length !== OTP_LENGTH,
2616
2602
  className: "skippr:w-full",
2617
- children: isSubmitting ? /* @__PURE__ */ jsx9(LoaderCircle, {
2603
+ children: isSubmitting ? /* @__PURE__ */ jsx8(LoaderCircle, {
2618
2604
  className: "skippr:size-4 skippr:animate-spin"
2619
2605
  }) : "Verify"
2620
2606
  }),
2621
- /* @__PURE__ */ jsxs8("div", {
2607
+ /* @__PURE__ */ jsxs7("div", {
2622
2608
  className: "skippr:flex skippr:items-center skippr:justify-between skippr:text-xs",
2623
2609
  children: [
2624
- /* @__PURE__ */ jsx9("button", {
2610
+ /* @__PURE__ */ jsx8("button", {
2625
2611
  type: "button",
2626
2612
  onClick: onBack,
2627
2613
  disabled: isSubmitting,
2628
2614
  className: "skippr:text-muted-foreground hover:skippr:text-foreground skippr:transition-colors disabled:skippr:opacity-50",
2629
2615
  children: "Change email"
2630
2616
  }),
2631
- /* @__PURE__ */ jsx9("button", {
2617
+ /* @__PURE__ */ jsx8("button", {
2632
2618
  type: "button",
2633
2619
  onClick: handleResend,
2634
2620
  disabled: isSubmitting || resendCooldown > 0,
@@ -2644,50 +2630,50 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
2644
2630
  }
2645
2631
 
2646
2632
  // src/components/MeetingControls.tsx
2647
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2648
- var CONTROL_BUTTON = "skippr:flex skippr:size-11 skippr:cursor-pointer skippr:items-center skippr:justify-center skippr:rounded-full skippr:transition-colors";
2633
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2634
+ var CONTROL_BUTTON2 = "skippr:flex skippr:size-11 skippr:cursor-pointer skippr:items-center skippr:justify-center skippr:rounded-full skippr:transition-colors";
2649
2635
  function MeetingControls({ onHangUp, showScreenShareToggle = true }) {
2650
2636
  const { isMuted, toggleMute, isScreenSharing, toggleScreenShare } = useMediaControls();
2651
- return /* @__PURE__ */ jsxs9("div", {
2637
+ return /* @__PURE__ */ jsxs8("div", {
2652
2638
  className: "skippr:shrink-0 skippr:border-t skippr:border-border skippr:bg-background skippr:px-4 skippr:py-4",
2653
2639
  children: [
2654
- /* @__PURE__ */ jsxs9("div", {
2640
+ /* @__PURE__ */ jsxs8("div", {
2655
2641
  className: "skippr:flex skippr:items-center skippr:justify-center skippr:gap-3",
2656
2642
  children: [
2657
- /* @__PURE__ */ jsx10("button", {
2643
+ /* @__PURE__ */ jsx9("button", {
2658
2644
  type: "button",
2659
2645
  onClick: toggleMute,
2660
2646
  "aria-label": isMuted ? "Unmute" : "Mute",
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"),
2662
- children: isMuted ? /* @__PURE__ */ jsx10(MicOff, {
2647
+ className: cn(CONTROL_BUTTON2, isMuted ? "skippr:bg-destructive/15 skippr:text-destructive skippr:hover:bg-destructive/25" : "skippr:bg-muted skippr:text-foreground skippr:hover:bg-muted/80"),
2648
+ children: isMuted ? /* @__PURE__ */ jsx9(MicOff, {
2663
2649
  className: "skippr:size-5"
2664
- }) : /* @__PURE__ */ jsx10(Mic, {
2650
+ }) : /* @__PURE__ */ jsx9(Mic, {
2665
2651
  className: "skippr:size-5"
2666
2652
  })
2667
2653
  }),
2668
- showScreenShareToggle && /* @__PURE__ */ jsx10("button", {
2654
+ showScreenShareToggle && /* @__PURE__ */ jsx9("button", {
2669
2655
  type: "button",
2670
2656
  onClick: toggleScreenShare,
2671
2657
  "aria-label": isScreenSharing ? "Stop sharing screen" : "Share screen",
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"),
2673
- children: isScreenSharing ? /* @__PURE__ */ jsx10(MonitorOff, {
2658
+ className: cn(CONTROL_BUTTON2, isScreenSharing ? "skippr:bg-bubble skippr:text-white skippr:hover:brightness-110" : "skippr:bg-muted skippr:text-foreground skippr:hover:bg-muted/80"),
2659
+ children: isScreenSharing ? /* @__PURE__ */ jsx9(MonitorOff, {
2674
2660
  className: "skippr:size-5"
2675
- }) : /* @__PURE__ */ jsx10(Monitor, {
2661
+ }) : /* @__PURE__ */ jsx9(Monitor, {
2676
2662
  className: "skippr:size-5"
2677
2663
  })
2678
2664
  }),
2679
- /* @__PURE__ */ jsx10("button", {
2665
+ /* @__PURE__ */ jsx9("button", {
2680
2666
  type: "button",
2681
2667
  onClick: onHangUp,
2682
2668
  "aria-label": "End session",
2683
- className: cn(CONTROL_BUTTON, "skippr:bg-destructive skippr:text-destructive-foreground skippr:hover:bg-destructive/90"),
2684
- children: /* @__PURE__ */ jsx10(PhoneOff, {
2669
+ className: cn(CONTROL_BUTTON2, "skippr:bg-destructive skippr:text-destructive-foreground skippr:hover:bg-destructive/90"),
2670
+ children: /* @__PURE__ */ jsx9(PhoneOff, {
2685
2671
  className: "skippr:size-5"
2686
2672
  })
2687
2673
  })
2688
2674
  ]
2689
2675
  }),
2690
- /* @__PURE__ */ jsx10("p", {
2676
+ /* @__PURE__ */ jsx9("p", {
2691
2677
  className: "skippr:mt-3 skippr:text-center skippr:text-[10px] skippr:text-muted-foreground",
2692
2678
  children: "Powered by Skippr"
2693
2679
  })
@@ -2700,7 +2686,7 @@ import { useEffect as useEffect12, useRef as useRef7 } from "react";
2700
2686
 
2701
2687
  // src/components/ChatInput.tsx
2702
2688
  import { useEffect as useEffect11, useRef as useRef6, useState as useState8 } from "react";
2703
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2689
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2704
2690
  var MAX_INPUT_HEIGHT = 60;
2705
2691
  function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2706
2692
  const [inputText, setInputText] = useState8("");
@@ -2737,13 +2723,13 @@ function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2737
2723
  handleSubmit(e);
2738
2724
  }
2739
2725
  }
2740
- return /* @__PURE__ */ jsx11("form", {
2726
+ return /* @__PURE__ */ jsx10("form", {
2741
2727
  onSubmit: handleSubmit,
2742
2728
  className: "skippr:border-t skippr:border-border skippr:p-3",
2743
- children: /* @__PURE__ */ jsxs10("div", {
2729
+ children: /* @__PURE__ */ jsxs9("div", {
2744
2730
  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",
2745
2731
  children: [
2746
- /* @__PURE__ */ jsx11("textarea", {
2732
+ /* @__PURE__ */ jsx10("textarea", {
2747
2733
  ref: textareaRef,
2748
2734
  rows: 1,
2749
2735
  value: inputText,
@@ -2753,12 +2739,12 @@ function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2753
2739
  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",
2754
2740
  style: { maxHeight: `${MAX_INPUT_HEIGHT}px` }
2755
2741
  }),
2756
- /* @__PURE__ */ jsx11("button", {
2742
+ /* @__PURE__ */ jsx10("button", {
2757
2743
  type: "submit",
2758
2744
  disabled: !canSend,
2759
2745
  "aria-label": "Send message",
2760
2746
  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"),
2761
- children: /* @__PURE__ */ jsx11(Send, {
2747
+ children: /* @__PURE__ */ jsx10(Send, {
2762
2748
  className: "skippr:size-3.5"
2763
2749
  })
2764
2750
  })
@@ -2768,7 +2754,7 @@ function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
2768
2754
  }
2769
2755
 
2770
2756
  // src/components/ChatMessage.tsx
2771
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2757
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2772
2758
  function formatTimestamp(ts) {
2773
2759
  return new Date(ts).toLocaleTimeString("en-US", {
2774
2760
  hour: "numeric",
@@ -2778,23 +2764,23 @@ function formatTimestamp(ts) {
2778
2764
  }
2779
2765
  function ChatMessage({ message }) {
2780
2766
  const isAgent = message.role === "assistant";
2781
- return /* @__PURE__ */ jsxs11("div", {
2767
+ return /* @__PURE__ */ jsxs10("div", {
2782
2768
  className: cn("skippr:flex skippr:gap-2", isAgent ? "skippr:items-start" : "skippr:justify-end"),
2783
2769
  children: [
2784
- isAgent && /* @__PURE__ */ jsx12("div", {
2770
+ isAgent && /* @__PURE__ */ jsx11("div", {
2785
2771
  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",
2786
- children: /* @__PURE__ */ jsx12(Sparkles, {
2772
+ children: /* @__PURE__ */ jsx11(Sparkles, {
2787
2773
  className: "skippr:size-3.5 skippr:text-primary-foreground"
2788
2774
  })
2789
2775
  }),
2790
- /* @__PURE__ */ jsxs11("div", {
2776
+ /* @__PURE__ */ jsxs10("div", {
2791
2777
  className: cn("skippr:flex skippr:max-w-[80%] skippr:flex-col", isAgent ? "skippr:items-start" : "skippr:items-end"),
2792
2778
  children: [
2793
- /* @__PURE__ */ jsx12("div", {
2779
+ /* @__PURE__ */ jsx11("div", {
2794
2780
  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"),
2795
2781
  children: message.content
2796
2782
  }),
2797
- message.timestamp && /* @__PURE__ */ jsx12("span", {
2783
+ message.timestamp && /* @__PURE__ */ jsx11("span", {
2798
2784
  className: "skippr:mt-1 skippr:px-1 skippr:text-[10px] skippr:text-muted-foreground/60",
2799
2785
  children: formatTimestamp(message.timestamp)
2800
2786
  })
@@ -2805,33 +2791,33 @@ function ChatMessage({ message }) {
2805
2791
  }
2806
2792
 
2807
2793
  // src/components/TypingIndicator.tsx
2808
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2794
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2809
2795
  function TypingIndicator() {
2810
- return /* @__PURE__ */ jsxs12("div", {
2796
+ return /* @__PURE__ */ jsxs11("div", {
2811
2797
  className: "skippr:flex skippr:items-start skippr:gap-2 skippr:animate-skippr-tab-fade",
2812
2798
  children: [
2813
- /* @__PURE__ */ jsx13("div", {
2799
+ /* @__PURE__ */ jsx12("div", {
2814
2800
  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",
2815
- children: /* @__PURE__ */ jsx13(Sparkles, {
2801
+ children: /* @__PURE__ */ jsx12(Sparkles, {
2816
2802
  className: "skippr:size-3.5 skippr:text-primary-foreground"
2817
2803
  })
2818
2804
  }),
2819
- /* @__PURE__ */ jsxs12("div", {
2805
+ /* @__PURE__ */ jsxs11("div", {
2820
2806
  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",
2821
2807
  children: [
2822
- /* @__PURE__ */ jsx13("span", {
2808
+ /* @__PURE__ */ jsx12("span", {
2823
2809
  children: "Agent is analyzing your screen"
2824
2810
  }),
2825
- /* @__PURE__ */ jsxs12("span", {
2811
+ /* @__PURE__ */ jsxs11("span", {
2826
2812
  className: "skippr:inline-flex skippr:items-center skippr:gap-[2px]",
2827
2813
  children: [
2828
- /* @__PURE__ */ jsx13("span", {
2814
+ /* @__PURE__ */ jsx12("span", {
2829
2815
  className: "skippr:size-1 skippr:rounded-full skippr:bg-primary skippr:animate-skippr-thinking-dot skippr:[animation-delay:0ms]"
2830
2816
  }),
2831
- /* @__PURE__ */ jsx13("span", {
2817
+ /* @__PURE__ */ jsx12("span", {
2832
2818
  className: "skippr:size-1 skippr:rounded-full skippr:bg-primary skippr:animate-skippr-thinking-dot skippr:[animation-delay:200ms]"
2833
2819
  }),
2834
- /* @__PURE__ */ jsx13("span", {
2820
+ /* @__PURE__ */ jsx12("span", {
2835
2821
  className: "skippr:size-1 skippr:rounded-full skippr:bg-primary skippr:animate-skippr-thinking-dot skippr:[animation-delay:400ms]"
2836
2822
  })
2837
2823
  ]
@@ -2843,7 +2829,7 @@ function TypingIndicator() {
2843
2829
  }
2844
2830
 
2845
2831
  // src/components/MessageList.tsx
2846
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2832
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2847
2833
  function MessageList({
2848
2834
  messages,
2849
2835
  isStreaming,
@@ -2857,25 +2843,25 @@ function MessageList({
2857
2843
  scrollRef.current?.scrollIntoView({ behavior: "smooth" });
2858
2844
  }, [messages.length, lastMessage?.content]);
2859
2845
  const showTyping = isStreaming && lastMessage?.role === "assistant" && lastMessage.content === "";
2860
- return /* @__PURE__ */ jsxs13("div", {
2846
+ return /* @__PURE__ */ jsxs12("div", {
2861
2847
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
2862
2848
  children: [
2863
- /* @__PURE__ */ jsxs13("div", {
2849
+ /* @__PURE__ */ jsxs12("div", {
2864
2850
  className: "skippr:min-h-0 skippr:flex-1 skippr:space-y-4 skippr:overflow-y-auto skippr:p-4",
2865
2851
  children: [
2866
- messages.length === 0 && !showTyping && /* @__PURE__ */ jsx14(LoadingDots, {
2852
+ messages.length === 0 && !showTyping && /* @__PURE__ */ jsx13(LoadingDots, {
2867
2853
  label: "Waiting for conversation to begin..."
2868
2854
  }),
2869
- messages.map((message) => /* @__PURE__ */ jsx14(ChatMessage, {
2855
+ messages.map((message) => /* @__PURE__ */ jsx13(ChatMessage, {
2870
2856
  message
2871
2857
  }, message.id)),
2872
- showTyping && /* @__PURE__ */ jsx14(TypingIndicator, {}),
2873
- /* @__PURE__ */ jsx14("div", {
2858
+ showTyping && /* @__PURE__ */ jsx13(TypingIndicator, {}),
2859
+ /* @__PURE__ */ jsx13("div", {
2874
2860
  ref: scrollRef
2875
2861
  })
2876
2862
  ]
2877
2863
  }),
2878
- /* @__PURE__ */ jsx14(ChatInput, {
2864
+ /* @__PURE__ */ jsx13(ChatInput, {
2879
2865
  sendChatMessage,
2880
2866
  isSendingChat,
2881
2867
  autoFocus
@@ -2885,49 +2871,49 @@ function MessageList({
2885
2871
  }
2886
2872
 
2887
2873
  // src/components/SessionAgenda.tsx
2888
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
2874
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2889
2875
  function SessionAgenda({ phases, hasStarted }) {
2890
2876
  if (phases.length === 0 || !hasStarted) {
2891
- return /* @__PURE__ */ jsx15("div", {
2877
+ return /* @__PURE__ */ jsx14("div", {
2892
2878
  className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
2893
- children: /* @__PURE__ */ jsx15(LoadingDots, {
2879
+ children: /* @__PURE__ */ jsx14(LoadingDots, {
2894
2880
  label: "Waiting for agenda to load..."
2895
2881
  })
2896
2882
  });
2897
2883
  }
2898
- return /* @__PURE__ */ jsx15("div", {
2884
+ return /* @__PURE__ */ jsx14("div", {
2899
2885
  className: "skippr:flex-1 skippr:overflow-y-auto skippr:px-4 skippr:py-4",
2900
- children: /* @__PURE__ */ jsx15("div", {
2886
+ children: /* @__PURE__ */ jsx14("div", {
2901
2887
  className: "skippr:space-y-1",
2902
2888
  children: phases.map((phase) => {
2903
2889
  const isActive = phase.status === "active";
2904
2890
  const isCompleted = phase.status === "completed";
2905
- return /* @__PURE__ */ jsxs14("div", {
2891
+ return /* @__PURE__ */ jsxs13("div", {
2906
2892
  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"),
2907
2893
  children: [
2908
- /* @__PURE__ */ jsx15("div", {
2894
+ /* @__PURE__ */ jsx14("div", {
2909
2895
  className: "skippr:mt-0.5",
2910
- children: isCompleted ? /* @__PURE__ */ jsx15(CircleCheck, {
2896
+ children: isCompleted ? /* @__PURE__ */ jsx14(CircleCheck, {
2911
2897
  className: "skippr:size-4 skippr:text-chart-3"
2912
- }) : isActive ? /* @__PURE__ */ jsx15(Circle, {
2898
+ }) : isActive ? /* @__PURE__ */ jsx14(Circle, {
2913
2899
  className: "skippr:size-4 skippr:fill-primary/30 skippr:text-primary"
2914
- }) : /* @__PURE__ */ jsx15(Circle, {
2900
+ }) : /* @__PURE__ */ jsx14(Circle, {
2915
2901
  className: "skippr:size-4 skippr:text-muted-foreground/30"
2916
2902
  })
2917
2903
  }),
2918
- /* @__PURE__ */ jsxs14("div", {
2904
+ /* @__PURE__ */ jsxs13("div", {
2919
2905
  className: "skippr:min-w-0 skippr:flex-1",
2920
2906
  children: [
2921
- /* @__PURE__ */ jsx15("p", {
2907
+ /* @__PURE__ */ jsx14("p", {
2922
2908
  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"),
2923
2909
  children: phase.name
2924
2910
  }),
2925
- phase.highlights.length > 0 && /* @__PURE__ */ jsx15("ul", {
2911
+ phase.highlights.length > 0 && /* @__PURE__ */ jsx14("ul", {
2926
2912
  className: "skippr:mt-1 skippr:space-y-0.5",
2927
- children: phase.highlights.map((text) => /* @__PURE__ */ jsxs14("li", {
2913
+ children: phase.highlights.map((text) => /* @__PURE__ */ jsxs13("li", {
2928
2914
  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"),
2929
2915
  children: [
2930
- /* @__PURE__ */ jsx15("span", {
2916
+ /* @__PURE__ */ jsx14("span", {
2931
2917
  className: "skippr:size-1 skippr:shrink-0 skippr:rounded-full skippr:bg-current"
2932
2918
  }),
2933
2919
  text
@@ -2944,12 +2930,12 @@ function SessionAgenda({ phases, hasStarted }) {
2944
2930
  }
2945
2931
 
2946
2932
  // src/components/SessionWarningBanner.tsx
2947
- import { jsx as jsx16 } from "react/jsx-runtime";
2933
+ import { jsx as jsx15 } from "react/jsx-runtime";
2948
2934
  var SESSION_WARNING_THRESHOLD_SECS = 60;
2949
2935
  function SessionWarningBanner({ remaining }) {
2950
2936
  if (remaining === null || remaining <= 0 || remaining > SESSION_WARNING_THRESHOLD_SECS)
2951
2937
  return null;
2952
- return /* @__PURE__ */ jsx16("div", {
2938
+ return /* @__PURE__ */ jsx15("div", {
2953
2939
  "data-testid": "session-warning-banner",
2954
2940
  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",
2955
2941
  children: "Session ending soon"
@@ -2957,24 +2943,24 @@ function SessionWarningBanner({ remaining }) {
2957
2943
  }
2958
2944
 
2959
2945
  // src/components/StartSessionPrompt.tsx
2960
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2946
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2961
2947
  function StartSessionPrompt({
2962
2948
  onStartSession,
2963
2949
  isStarting,
2964
2950
  error,
2965
2951
  label = "Talk to Skippr"
2966
2952
  }) {
2967
- return /* @__PURE__ */ jsxs15("div", {
2953
+ return /* @__PURE__ */ jsxs14("div", {
2968
2954
  className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:items-center skippr:justify-center skippr:gap-3 skippr:px-4",
2969
2955
  children: [
2970
- /* @__PURE__ */ jsx17("button", {
2956
+ /* @__PURE__ */ jsx16("button", {
2971
2957
  type: "button",
2972
2958
  onClick: onStartSession,
2973
2959
  disabled: isStarting,
2974
2960
  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",
2975
2961
  children: isStarting ? "Starting..." : label
2976
2962
  }),
2977
- error && /* @__PURE__ */ jsx17("p", {
2963
+ error && /* @__PURE__ */ jsx16("p", {
2978
2964
  className: "skippr:text-xs skippr:text-destructive",
2979
2965
  children: error
2980
2966
  })
@@ -2983,7 +2969,7 @@ function StartSessionPrompt({
2983
2969
  }
2984
2970
 
2985
2971
  // src/components/Sidebar.tsx
2986
- import { jsx as jsx18, jsxs as jsxs16, Fragment as Fragment4 } from "react/jsx-runtime";
2972
+ import { jsx as jsx17, jsxs as jsxs15, Fragment as Fragment4 } from "react/jsx-runtime";
2987
2973
  function Sidebar({
2988
2974
  hideControls = false,
2989
2975
  hideHeader = false,
@@ -3025,22 +3011,22 @@ function Sidebar({
3025
3011
  document.body.style.transition = "";
3026
3012
  };
3027
3013
  }, [isSidebar, isPanelOpen, position]);
3028
- return /* @__PURE__ */ jsxs16("div", {
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"),
3014
+ return /* @__PURE__ */ jsxs15("div", {
3015
+ 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-[min(460px,calc(100vh-200px))] 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"),
3030
3016
  style: { width: isPanelOpen ? SIDEBAR_WIDTH : undefined },
3031
3017
  children: [
3032
- !hideHeader && /* @__PURE__ */ jsx18(ChatHeader, {}),
3033
- !isAuthenticated && isValidating ? /* @__PURE__ */ jsx18("div", {
3018
+ !hideHeader && /* @__PURE__ */ jsx17(ChatHeader, {}),
3019
+ !isAuthenticated && isValidating ? /* @__PURE__ */ jsx17("div", {
3034
3020
  className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
3035
- children: /* @__PURE__ */ jsx18(LoadingDots, {
3021
+ children: /* @__PURE__ */ jsx17(LoadingDots, {
3036
3022
  label: "Loading..."
3037
3023
  })
3038
- }) : !isAuthenticated ? /* @__PURE__ */ jsx18(LoginFlow, {
3024
+ }) : !isAuthenticated ? /* @__PURE__ */ jsx17(LoginFlow, {
3039
3025
  requestOtp,
3040
3026
  verifyOtp,
3041
3027
  error: authError,
3042
3028
  isSubmitting: isAuthSubmitting
3043
- }) : /* @__PURE__ */ jsx18(AuthenticatedContent, {
3029
+ }) : /* @__PURE__ */ jsx17(AuthenticatedContent, {
3044
3030
  isConnected,
3045
3031
  onStartSession: startSession,
3046
3032
  onDisconnect: disconnect,
@@ -3069,50 +3055,50 @@ function AuthenticatedContent({
3069
3055
  autoFocusChat,
3070
3056
  showScreenShareToggle
3071
3057
  }) {
3072
- return /* @__PURE__ */ jsxs16(Fragment4, {
3058
+ return /* @__PURE__ */ jsxs15(Fragment4, {
3073
3059
  children: [
3074
- isConnected && /* @__PURE__ */ jsx18(ConnectedBanner, {}),
3075
- /* @__PURE__ */ jsxs16("div", {
3060
+ isConnected && /* @__PURE__ */ jsx17(ConnectedBanner, {}),
3061
+ /* @__PURE__ */ jsxs15("div", {
3076
3062
  className: "skippr:flex skippr:gap-2 skippr:border-b skippr:border-border skippr:px-3 skippr:py-2",
3077
3063
  children: [
3078
- /* @__PURE__ */ jsxs16("button", {
3064
+ /* @__PURE__ */ jsxs15("button", {
3079
3065
  type: "button",
3080
3066
  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"),
3081
3067
  onClick: () => onTabChange("chat"),
3082
3068
  children: [
3083
- /* @__PURE__ */ jsx18(MessageCircle, {
3069
+ /* @__PURE__ */ jsx17(MessageCircle, {
3084
3070
  className: "skippr:size-3.5"
3085
3071
  }),
3086
3072
  "Chat",
3087
- activeTab === "chat" && /* @__PURE__ */ jsx18("span", {
3073
+ activeTab === "chat" && /* @__PURE__ */ jsx17("span", {
3088
3074
  className: "skippr:absolute skippr:-bottom-2 skippr:left-3 skippr:right-3 skippr:h-0.5 skippr:rounded-full skippr:bg-foreground"
3089
3075
  })
3090
3076
  ]
3091
3077
  }),
3092
- /* @__PURE__ */ jsxs16("button", {
3078
+ /* @__PURE__ */ jsxs15("button", {
3093
3079
  type: "button",
3094
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 === "agenda" ? "skippr:text-foreground" : "skippr:text-muted-foreground skippr:hover:text-foreground"),
3095
3081
  onClick: () => onTabChange("agenda"),
3096
3082
  children: [
3097
- /* @__PURE__ */ jsx18(Calendar, {
3083
+ /* @__PURE__ */ jsx17(Calendar, {
3098
3084
  className: "skippr:size-3.5"
3099
3085
  }),
3100
3086
  "Agenda",
3101
- activeTab === "agenda" && /* @__PURE__ */ jsx18("span", {
3087
+ activeTab === "agenda" && /* @__PURE__ */ jsx17("span", {
3102
3088
  className: "skippr:absolute skippr:-bottom-2 skippr:left-3 skippr:right-3 skippr:h-0.5 skippr:rounded-full skippr:bg-foreground"
3103
3089
  })
3104
3090
  ]
3105
3091
  })
3106
3092
  ]
3107
3093
  }),
3108
- /* @__PURE__ */ jsx18("div", {
3094
+ /* @__PURE__ */ jsx17("div", {
3109
3095
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
3110
- children: isConnected || isStarting ? /* @__PURE__ */ jsx18(ConnectedBody, {
3096
+ children: isConnected || isStarting ? /* @__PURE__ */ jsx17(ConnectedBody, {
3111
3097
  activeTab,
3112
3098
  autoFocusChat
3113
- }) : /* @__PURE__ */ jsx18("div", {
3099
+ }) : /* @__PURE__ */ jsx17("div", {
3114
3100
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col skippr:animate-skippr-tab-fade",
3115
- children: /* @__PURE__ */ jsx18(StartSessionPrompt, {
3101
+ children: /* @__PURE__ */ jsx17(StartSessionPrompt, {
3116
3102
  onStartSession,
3117
3103
  isStarting,
3118
3104
  error,
@@ -3120,7 +3106,7 @@ function AuthenticatedContent({
3120
3106
  })
3121
3107
  }, `${activeTab}-empty`)
3122
3108
  }),
3123
- isConnected && !hideControls && /* @__PURE__ */ jsx18(MeetingControls, {
3109
+ isConnected && !hideControls && /* @__PURE__ */ jsx17(MeetingControls, {
3124
3110
  onHangUp: onDisconnect,
3125
3111
  showScreenShareToggle
3126
3112
  })
@@ -3129,7 +3115,7 @@ function AuthenticatedContent({
3129
3115
  }
3130
3116
  function ConnectedBanner() {
3131
3117
  const remaining = useSessionRemaining();
3132
- return /* @__PURE__ */ jsx18(SessionWarningBanner, {
3118
+ return /* @__PURE__ */ jsx17(SessionWarningBanner, {
3133
3119
  remaining
3134
3120
  });
3135
3121
  }
@@ -3140,17 +3126,17 @@ function ConnectedBody({
3140
3126
  const { allMessages, agentState, sendChatMessage, isSendingChat } = useCombinedMessages();
3141
3127
  const { phases } = usePhaseUpdates();
3142
3128
  if (activeTab === "agenda") {
3143
- return /* @__PURE__ */ jsx18("div", {
3129
+ return /* @__PURE__ */ jsx17("div", {
3144
3130
  className: "skippr:min-h-0 skippr:flex-1 skippr:overflow-y-auto skippr:animate-skippr-tab-fade",
3145
- children: /* @__PURE__ */ jsx18(SessionAgenda, {
3131
+ children: /* @__PURE__ */ jsx17(SessionAgenda, {
3146
3132
  phases,
3147
3133
  hasStarted: allMessages.length > 0 || agentState === "speaking"
3148
3134
  })
3149
3135
  }, "agenda");
3150
3136
  }
3151
- return /* @__PURE__ */ jsx18("div", {
3137
+ return /* @__PURE__ */ jsx17("div", {
3152
3138
  className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col skippr:animate-skippr-tab-fade",
3153
- children: /* @__PURE__ */ jsx18(MessageList, {
3139
+ children: /* @__PURE__ */ jsx17(MessageList, {
3154
3140
  messages: allMessages,
3155
3141
  isStreaming: agentState === "speaking",
3156
3142
  sendChatMessage,
@@ -3161,28 +3147,28 @@ function ConnectedBody({
3161
3147
  }
3162
3148
 
3163
3149
  // src/components/SidebarTrigger.tsx
3164
- import { jsx as jsx19 } from "react/jsx-runtime";
3150
+ import { jsx as jsx18 } from "react/jsx-runtime";
3165
3151
  function SidebarTrigger() {
3166
3152
  const { isPanelOpen, togglePanel, minimizePanel, minimizable, position, isMinimized } = useLiveAgent();
3167
3153
  if (isMinimized)
3168
3154
  return null;
3169
3155
  const handleClick = isPanelOpen && minimizable ? minimizePanel : togglePanel;
3170
- return /* @__PURE__ */ jsx19("button", {
3156
+ return /* @__PURE__ */ jsx18("button", {
3171
3157
  type: "button",
3172
3158
  onClick: handleClick,
3173
3159
  title: isPanelOpen ? "Close chat" : "Open chat",
3174
3160
  "aria-label": isPanelOpen ? "Close chat" : "Open chat",
3175
3161
  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"),
3176
- children: isPanelOpen ? /* @__PURE__ */ jsx19(ChevronDown, {
3162
+ children: isPanelOpen ? /* @__PURE__ */ jsx18(ChevronDown, {
3177
3163
  className: "skippr:size-5"
3178
- }) : /* @__PURE__ */ jsx19(Logo, {
3164
+ }) : /* @__PURE__ */ jsx18(Logo, {
3179
3165
  className: "skippr:size-7"
3180
3166
  })
3181
3167
  });
3182
3168
  }
3183
3169
 
3184
3170
  // src/components/LiveAgent.tsx
3185
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
3171
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
3186
3172
  function LiveAgent(props) {
3187
3173
  const {
3188
3174
  agentId,
@@ -3198,7 +3184,6 @@ function LiveAgent(props) {
3198
3184
  hideHeader = false,
3199
3185
  startSessionLabel = "Talk to Skippr",
3200
3186
  autoFocusChat = true,
3201
- showAgentStateBanner = true,
3202
3187
  children
3203
3188
  } = props;
3204
3189
  const captureMode = props.captureMode ?? "screenshare";
@@ -3336,32 +3321,31 @@ function LiveAgent(props) {
3336
3321
  captureMode,
3337
3322
  agentControls
3338
3323
  ]);
3339
- return /* @__PURE__ */ jsx20(LiveAgentContext.Provider, {
3324
+ return /* @__PURE__ */ jsx19(LiveAgentContext.Provider, {
3340
3325
  value: ctx,
3341
- children: /* @__PURE__ */ jsxs17(LiveKitRoom, {
3326
+ children: /* @__PURE__ */ jsxs16(LiveKitRoom, {
3342
3327
  serverUrl: connection?.livekitUrl,
3343
3328
  token: connection?.token,
3344
3329
  connect: shouldConnect,
3345
3330
  audio: true,
3346
3331
  onDisconnected: disconnect,
3347
3332
  children: [
3348
- connection && /* @__PURE__ */ jsx20(RoomAudioRenderer, {}),
3349
- connection && captureMode === "screenshare" && /* @__PURE__ */ jsx20(AutoStartMedia, {
3333
+ connection && /* @__PURE__ */ jsx19(RoomAudioRenderer, {}),
3334
+ connection && captureMode === "screenshare" && /* @__PURE__ */ jsx19(AutoStartMedia, {
3350
3335
  pendingScreenStream
3351
3336
  }),
3352
- connection && captureMode === "auto" && /* @__PURE__ */ jsx20(DomCapture, {}),
3353
- connection && captureMode === "auto" && agentControls?.highlight && /* @__PURE__ */ jsx20(HighlightOverlay, {}),
3354
- /* @__PURE__ */ jsxs17("div", {
3337
+ connection && captureMode === "auto" && /* @__PURE__ */ jsx19(DomCapture, {}),
3338
+ connection && captureMode === "auto" && agentControls?.highlight && /* @__PURE__ */ jsx19(HighlightOverlay, {}),
3339
+ /* @__PURE__ */ jsxs16("div", {
3355
3340
  id: WIDGET_ROOT_ID,
3356
3341
  children: [
3357
- showAgentStateBanner && /* @__PURE__ */ jsx20(AgentStateBanner, {}),
3358
- isMinimized && /* @__PURE__ */ jsx20(MinimizedBubble, {
3342
+ isMinimized && /* @__PURE__ */ jsx19(MinimizedBubble, {
3359
3343
  welcomeMessage,
3360
3344
  welcomeDismissed,
3361
3345
  onDismissWelcome: dismissWelcome
3362
3346
  }),
3363
- /* @__PURE__ */ jsx20(SidebarTrigger, {}),
3364
- /* @__PURE__ */ jsx20(Sidebar, {
3347
+ /* @__PURE__ */ jsx19(SidebarTrigger, {}),
3348
+ /* @__PURE__ */ jsx19(Sidebar, {
3365
3349
  hideControls,
3366
3350
  hideHeader,
3367
3351
  startSessionLabel