@q9labsai/chalk-react 5.2.1 → 5.2.3

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.
@@ -866,7 +866,7 @@ function MediaRequestDialog({ request, onDecline, onAllow, onActionError }) {
866
866
  }
867
867
 
868
868
  // src/components/admission-panel/AdmissionPanel.tsx
869
- import React8, { useEffect as useEffect10, useState as useState14 } from "react";
869
+ import React8, { useEffect as useEffect10, useState as useState13 } from "react";
870
870
  import { IconButton, Spinner } from "@q9labsai/chalk-ui";
871
871
 
872
872
  // src/components/audio-output/AudioOutput.tsx
@@ -1226,7 +1226,7 @@ function useHaptics({ enabled = true } = {}) {
1226
1226
 
1227
1227
  // src/components/participant-tile/ParticipantTile.tsx
1228
1228
  import { Facehash as Facehash2 } from "@q9labsai/facehash/react";
1229
- import React5, { useMemo as useMemo6, useRef as useRef6, useState as useState12 } from "react";
1229
+ import React5, { useMemo as useMemo6, useRef as useRef6 } from "react";
1230
1230
 
1231
1231
  // src/internal/useMirrorSetting.ts
1232
1232
  import { useSyncExternalStore as useSyncExternalStore2 } from "react";
@@ -1478,7 +1478,7 @@ var ParticipantTileSurface = React5.memo(function ParticipantTileSurface2({
1478
1478
  onClick,
1479
1479
  onDoubleClick,
1480
1480
  pinned,
1481
- clickAction = "pin",
1481
+ onFollow,
1482
1482
  following = false,
1483
1483
  primary,
1484
1484
  className,
@@ -1492,34 +1492,24 @@ var ParticipantTileSurface = React5.memo(function ParticipantTileSurface2({
1492
1492
  }) {
1493
1493
  const prefersReducedMotion = usePrefersReducedMotion();
1494
1494
  const phone = useMediaQuery("(max-width:640px)");
1495
- const [optionsOpen, setOptionsOpen] = useState12(false);
1496
- const returnFocus = useRef6(null);
1497
- const openOptions = () => {
1498
- returnFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
1499
- setOptionsOpen(true);
1500
- };
1501
- const closeOptions = () => {
1502
- setOptionsOpen(false);
1503
- queueMicrotask(() => returnFocus.current?.focus());
1504
- };
1505
1495
  const [localMirrored] = useMirrorSetting();
1506
1496
  const mirrored = mirror ?? (participant.isLocal === true && localMirrored);
1507
1497
  const colors = useMemo6(() => getParticipantColor(participant.displayName || participant.id, gradientPreference), [gradientPreference, participant.displayName, participant.id]);
1508
1498
  const recipe = useMemo6(() => getParticipantAvatarRecipe(participant.displayName || participant.id, gradientPreference), [participant.displayName, participant.id, gradientPreference]);
1509
- const first = participant.displayName.split(" ")[0] ?? participant.displayName;
1510
- const actionLabel = clickAction === "follow" ? `${following ? "Stop following" : "Follow"} ${first}` : `${pinned ? "Unpin" : "Pin"} ${participant.displayName}`;
1499
+ const actionLabel = `${pinned ? "Unpin" : "Pin"} ${participant.displayName}`;
1500
+ const followLabel = following ? "Stop following" : "Follow";
1511
1501
  const hasPoorConnection = participant.connectionQuality !== void 0 && participant.connectionQuality > 0 && participant.connectionQuality <= 2;
1512
1502
  return /* @__PURE__ */ jsxs12(
1513
1503
  TileShell,
1514
1504
  {
1515
- label: clickAction === "follow" ? actionLabel : `Video tile for ${participant.displayName}`,
1505
+ label: `Video tile for ${participant.displayName}`,
1516
1506
  accentColor: colors.primary,
1517
- pinned: clickAction === "follow" ? following : pinned,
1507
+ pinned,
1518
1508
  ring: following,
1519
1509
  lift: !primary,
1520
1510
  speaking: mediaVisible && participant.isSpeaking && !participant.isMuted,
1521
1511
  audioLevel: participant.audioLevel,
1522
- onClick: onClick && phone && clickAction === "pin" ? openOptions : onClick,
1512
+ onClick,
1523
1513
  onDoubleClick,
1524
1514
  className: cn(aspectRatioClasses[aspectRatio], className),
1525
1515
  style,
@@ -1527,11 +1517,14 @@ var ParticipantTileSurface = React5.memo(function ParticipantTileSurface2({
1527
1517
  hidden,
1528
1518
  corner: /* @__PURE__ */ jsxs12(Fragment6, { children: [
1529
1519
  showStatus && hasPoorConnection ? /* @__PURE__ */ jsx27("span", { role: "img", "data-part": "tile-signal", "aria-label": `${participant.displayName} has a weak connection`, className: "pointer-events-none absolute top-2 left-2 z-30 flex h-6 items-center rounded-[6px] bg-[rgba(12,14,18,.75)] px-[7px]", children: /* @__PURE__ */ jsx27(SignalBars, {}) }) : null,
1530
- onClick && !phone ? /* @__PURE__ */ jsx27("span", { "data-part": "tile-menu", className: "absolute top-2 right-2 z-30 opacity-0 transition-opacity duration-150 group-hover/tile:opacity-100 focus-within:opacity-100", children: /* @__PURE__ */ jsx27(
1520
+ onClick || onFollow ? /* @__PURE__ */ jsx27("span", { "data-part": "tile-menu", className: "absolute top-2 right-2 z-30 transition-opacity duration-150 min-[641px]:opacity-0 group-hover/tile:opacity-100 focus-within:opacity-100", children: /* @__PURE__ */ jsxs12(
1531
1521
  ChalkMenu,
1532
1522
  {
1533
1523
  trigger: /* @__PURE__ */ jsx27("button", { type: "button", "aria-label": `More options for ${participant.displayName}`, className: "grid h-8 w-8 place-items-center rounded-full bg-[rgba(12,14,18,.75)] text-white outline-none hover:bg-[rgba(40,42,48,.95)] focus-visible:ring-2 focus-visible:ring-[var(--chalk-focus)]", children: /* @__PURE__ */ jsx27(StageIcon, { name: "more", size: 18 }) }),
1534
- children: /* @__PURE__ */ jsx27(ChalkMenuItem, { onClick, children: actionLabel })
1524
+ children: [
1525
+ onClick ? /* @__PURE__ */ jsx27(ChalkMenuItem, { onClick, children: actionLabel }) : null,
1526
+ onFollow ? /* @__PURE__ */ jsx27(ChalkMenuItem, { onClick: onFollow, children: followLabel }) : null
1527
+ ]
1535
1528
  }
1536
1529
  ) }) : null
1537
1530
  ] }),
@@ -1571,38 +1564,6 @@ var ParticipantTileSurface = React5.memo(function ParticipantTileSurface2({
1571
1564
  colors: recipe.facehashColors
1572
1565
  }
1573
1566
  ) : /* @__PURE__ */ jsx27(Avatar, { name: participant.displayName, src: participant.avatarUrl, size: "xl", generated: false, style: { width: "100%", height: "100%" } }) }) }),
1574
- phone && onClick && clickAction === "pin" ? /* @__PURE__ */ jsxs12(
1575
- ChalkSheet,
1576
- {
1577
- open: optionsOpen,
1578
- onOpenChange: (open) => {
1579
- if (open) openOptions();
1580
- else closeOptions();
1581
- },
1582
- title: `Options for ${participant.displayName}`,
1583
- children: [
1584
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3 px-2 pt-1 pb-3.5 text-base font-semibold", children: [
1585
- /* @__PURE__ */ jsx27(Avatar, { name: participant.displayName, size: "sm" }),
1586
- participant.displayName
1587
- ] }),
1588
- /* @__PURE__ */ jsxs12(
1589
- "button",
1590
- {
1591
- type: "button",
1592
- className: "flex min-h-[52px] w-full items-center gap-3.5 rounded-[16px] bg-[var(--chalk-raised)] px-4 text-left text-base leading-[1.4] hover:bg-[var(--chalk-hover)] active:bg-[var(--chalk-pressed)]",
1593
- onClick: () => {
1594
- onClick();
1595
- closeOptions();
1596
- },
1597
- children: [
1598
- /* @__PURE__ */ jsx27(StageIcon, { name: "pin", size: 20, className: "text-[var(--chalk-soft-text)]" }),
1599
- /* @__PURE__ */ jsx27("span", { children: pinned ? "Unpin" : "Pin" })
1600
- ]
1601
- }
1602
- )
1603
- ]
1604
- }
1605
- ) : null,
1606
1567
  children
1607
1568
  ]
1608
1569
  }
@@ -1615,7 +1576,7 @@ function SignalBars() {
1615
1576
  }
1616
1577
 
1617
1578
  // src/components/atomic/ReactionBubble.tsx
1618
- import React6, { useEffect as useEffect9, useState as useState13, useMemo as useMemo7 } from "react";
1579
+ import React6, { useEffect as useEffect9, useState as useState12, useMemo as useMemo7 } from "react";
1619
1580
  import { CELEBRATION_EMOJIS } from "@q9labsai/chalk-ui/reactions";
1620
1581
  import { jsx as jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
1621
1582
  var BASE_PARTICLE_COLORS = ["#14b8a6", "#f59e0b", "#ec4899", "#8b5cf6", "#06b6d4", "#22c55e"];
@@ -1659,7 +1620,7 @@ function getParticleStyle(particle) {
1659
1620
  };
1660
1621
  }
1661
1622
  var ReactionBubble = React6.memo(({ emoji, participantName, onComplete, duration: baseDuration = 3e3, animated = true, className }) => {
1662
- const [isVisible, setIsVisible] = useState13(true);
1623
+ const [isVisible, setIsVisible] = useState12(true);
1663
1624
  const prefersReducedMotion = usePrefersReducedMotion();
1664
1625
  const participantColors = useMemo7(() => getParticipantColor(participantName || "unknown"), [participantName]);
1665
1626
  const isCelebration = CELEBRATION_EMOJIS.includes(emoji);
@@ -1747,13 +1708,13 @@ function getWaitingLabel(joinedAt) {
1747
1708
  return `Waiting ${minutes} min`;
1748
1709
  }
1749
1710
  var AdmissionPanelSurface = React8.memo(({ participants, onAdmit, onDeny, onAdmitAll, onDenyAll, loading = false, className, onClose, inline = false }) => {
1750
- const [, setTick] = useState14(0);
1711
+ const [, setTick] = useState13(0);
1751
1712
  useEffect10(() => {
1752
1713
  const timer = window.setInterval(() => setTick((t) => t + 1), 6e4);
1753
1714
  return () => window.clearInterval(timer);
1754
1715
  }, []);
1755
- const [busy, setBusy] = useState14(false);
1756
- const [error, setError] = useState14(null);
1716
+ const [busy, setBusy] = useState13(false);
1717
+ const [error, setError] = useState13(null);
1757
1718
  const perform = async (action) => {
1758
1719
  if (busy) return;
1759
1720
  setBusy(true);
@@ -1826,7 +1787,7 @@ AdmissionPanel.displayName = "AdmissionPanel";
1826
1787
 
1827
1788
  // src/components/composite/ChatPanel.tsx
1828
1789
  import { CHALK_CHAT_ATTACHMENT_LIMITS, CHALK_CHAT_ATTACHMENT_MIME_TYPES } from "@q9labsai/chalk-client";
1829
- import React10, { useEffect as useEffect13, useLayoutEffect, useMemo as useMemo8, useRef as useRef9, useState as useState17 } from "react";
1790
+ import React10, { useEffect as useEffect13, useLayoutEffect, useMemo as useMemo8, useRef as useRef9, useState as useState16 } from "react";
1830
1791
  import { Button } from "@q9labsai/chalk-ui";
1831
1792
 
1832
1793
  // src/components/call-card/CallCardStyles.tsx
@@ -2689,14 +2650,14 @@ function CallCardStyles() {
2689
2650
 
2690
2651
  // src/components/composite/MessageBubble.tsx
2691
2652
  import { CHALK_REACTIONS } from "@q9labsai/chalk-client";
2692
- import React9, { useEffect as useEffect12, useRef as useRef8, useState as useState16 } from "react";
2653
+ import React9, { useEffect as useEffect12, useRef as useRef8, useState as useState15 } from "react";
2693
2654
 
2694
2655
  // src/components/composite/use-chat-attachment-previews.ts
2695
- import { useCallback as useCallback4, useEffect as useEffect11, useRef as useRef7, useState as useState15 } from "react";
2656
+ import { useCallback as useCallback4, useEffect as useEffect11, useRef as useRef7, useState as useState14 } from "react";
2696
2657
  function useChatAttachmentPreviews(attachments, resolveUrl) {
2697
- const [resolvedUrls, setResolvedUrls] = useState15(() => /* @__PURE__ */ new Map());
2698
- const [failedAttachmentIds, setFailedAttachmentIds] = useState15(() => /* @__PURE__ */ new Set());
2699
- const [retryGeneration, setRetryGeneration] = useState15(0);
2658
+ const [resolvedUrls, setResolvedUrls] = useState14(() => /* @__PURE__ */ new Map());
2659
+ const [failedAttachmentIds, setFailedAttachmentIds] = useState14(() => /* @__PURE__ */ new Set());
2660
+ const [retryGeneration, setRetryGeneration] = useState14(0);
2700
2661
  const resolvingAttachmentIds = useRef7(/* @__PURE__ */ new Set());
2701
2662
  const resolvedUrlsRef = useRef7(resolvedUrls);
2702
2663
  const failedAttachmentIdsRef = useRef7(failedAttachmentIds);
@@ -2779,9 +2740,9 @@ var MessageBubble = React9.memo(
2779
2740
  className
2780
2741
  }) => {
2781
2742
  const { resolvedUrls, failedAttachmentIds, markFailed, retry } = useChatAttachmentPreviews(attachments, onResolveAttachmentUrl);
2782
- const [reactionError, setReactionError] = useState16(null);
2783
- const [reacting, setReacting] = useState16(false);
2784
- const [reactionBarOpen, setReactionBarOpen] = useState16(false);
2743
+ const [reactionError, setReactionError] = useState15(null);
2744
+ const [reacting, setReacting] = useState15(false);
2745
+ const [reactionBarOpen, setReactionBarOpen] = useState15(false);
2785
2746
  const messageRef = useRef8(null);
2786
2747
  const press = useRef8(null);
2787
2748
  const cancelPress = () => {
@@ -2798,9 +2759,9 @@ var MessageBubble = React9.memo(
2798
2759
  document.addEventListener("pointerdown", dismiss);
2799
2760
  return () => document.removeEventListener("pointerdown", dismiss);
2800
2761
  }, [reactionBarOpen]);
2801
- const [photo, setPhoto] = useState16(null);
2802
- const [downloading, setDownloading] = useState16(false);
2803
- const [downloadError, setDownloadError] = useState16(null);
2762
+ const [photo, setPhoto] = useState15(null);
2763
+ const [downloading, setDownloading] = useState15(false);
2764
+ const [downloadError, setDownloadError] = useState15(null);
2804
2765
  const downloadController = useRef8(null);
2805
2766
  useEffect12(() => () => downloadController.current?.abort(), []);
2806
2767
  const downloadPhoto = async () => {
@@ -2832,7 +2793,7 @@ var MessageBubble = React9.memo(
2832
2793
  downloadController.current = null;
2833
2794
  }
2834
2795
  };
2835
- const [photoClosing, setPhotoClosing] = useState16(false);
2796
+ const [photoClosing, setPhotoClosing] = useState15(false);
2836
2797
  const closeTimer = useRef8(null);
2837
2798
  useEffect12(
2838
2799
  () => () => {
@@ -3188,12 +3149,12 @@ var ChatPanelSurface = React10.memo(
3188
3149
  autoScrollBehavior,
3189
3150
  className
3190
3151
  }) => {
3191
- const [draft, setDraft] = useState17("");
3192
- const [stagedFiles, setStagedFiles] = useState17([]);
3152
+ const [draft, setDraft] = useState16("");
3153
+ const [stagedFiles, setStagedFiles] = useState16([]);
3193
3154
  const uploads = useRef9(/* @__PURE__ */ new Map());
3194
- const [failedUploads, setFailedUploads] = useState17(/* @__PURE__ */ new Set());
3195
- const [uploading, setUploading] = useState17(/* @__PURE__ */ new Set());
3196
- const [previews, setPreviews] = useState17(/* @__PURE__ */ new Map());
3155
+ const [failedUploads, setFailedUploads] = useState16(/* @__PURE__ */ new Set());
3156
+ const [uploading, setUploading] = useState16(/* @__PURE__ */ new Set());
3157
+ const [previews, setPreviews] = useState16(/* @__PURE__ */ new Map());
3197
3158
  useEffect13(() => {
3198
3159
  const urls = new Map(stagedFiles.flatMap((file) => file instanceof File && file.type.startsWith("image/") ? [[file, URL.createObjectURL(file)]] : []));
3199
3160
  setPreviews(urls);
@@ -3201,9 +3162,9 @@ var ChatPanelSurface = React10.memo(
3201
3162
  for (const url of urls.values()) URL.revokeObjectURL(url);
3202
3163
  };
3203
3164
  }, [stagedFiles]);
3204
- const [sending, setSending] = useState17(false);
3205
- const [pickingFiles, setPickingFiles] = useState17(false);
3206
- const [composerError, setComposerError] = useState17(null);
3165
+ const [sending, setSending] = useState16(false);
3166
+ const [pickingFiles, setPickingFiles] = useState16(false);
3167
+ const [composerError, setComposerError] = useState16(null);
3207
3168
  const scrollRef = useRef9(null);
3208
3169
  const textareaRef = useRef9(null);
3209
3170
  const fileInputRef = useRef9(null);
@@ -3519,7 +3480,7 @@ var ChatPanel = React10.memo((props) => {
3519
3480
  ChatPanel.displayName = "ChatPanel";
3520
3481
 
3521
3482
  // src/components/composite/ReactionsOverlay.tsx
3522
- import { useEffect as useEffect14, useRef as useRef10, useState as useState18 } from "react";
3483
+ import { useEffect as useEffect14, useRef as useRef10, useState as useState17 } from "react";
3523
3484
  import { createPortal } from "react-dom";
3524
3485
 
3525
3486
  // src/components/composite/reaction-float.ts
@@ -3563,7 +3524,7 @@ function ReactionsOverlaySurface({ reactions, maxVisible = 6, className }) {
3563
3524
  return /* @__PURE__ */ jsx34("div", { ref: root, className: cn("pointer-events-none absolute inset-0 z-30", className), "aria-live": "polite", "aria-atomic": "false", children: reactions.slice(-maxVisible).map((reaction) => /* @__PURE__ */ jsx34(TileReaction, { reaction, root }, reaction.eventId)) });
3564
3525
  }
3565
3526
  function TileReaction({ reaction, root }) {
3566
- const [host, setHost] = useState18(null);
3527
+ const [host, setHost] = useState17(null);
3567
3528
  const emoji = useRef10(null);
3568
3529
  const reduced = usePrefersReducedMotion();
3569
3530
  useEffect14(() => {
@@ -3609,10 +3570,10 @@ function CommandErrorAlert({ message }) {
3609
3570
  }
3610
3571
 
3611
3572
  // src/components/control-bar/ControlBar.tsx
3612
- import React12, { useEffect as useEffect17, useRef as useRef12, useState as useState23 } from "react";
3573
+ import React12, { useEffect as useEffect17, useRef as useRef12, useState as useState22 } from "react";
3613
3574
 
3614
3575
  // src/components/device-popover/DevicePopover.tsx
3615
- import { useEffect as useEffect15, useRef as useRef11, useState as useState19 } from "react";
3576
+ import { useEffect as useEffect15, useRef as useRef11, useState as useState18 } from "react";
3616
3577
 
3617
3578
  // src/components/control-bar/ShellIcon.tsx
3618
3579
  import { Fragment as Fragment11, jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
@@ -4271,7 +4232,7 @@ var CALL_SHELL_CSS = `.chalk-shell-dock {
4271
4232
  // src/components/device-popover/DevicePopover.tsx
4272
4233
  import { Fragment as Fragment12, jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
4273
4234
  function InputLevel({ track }) {
4274
- const [level, setLevel] = useState19(0);
4235
+ const [level, setLevel] = useState18(0);
4275
4236
  useEffect15(() => {
4276
4237
  if (!track || track.readyState !== "live") return;
4277
4238
  const context = new AudioContext();
@@ -4295,7 +4256,7 @@ function InputLevel({ track }) {
4295
4256
  }
4296
4257
  function CameraPreview({ track, mirrored, open, selectedDeviceId, captureCameraPreview }) {
4297
4258
  const video = useRef11(null);
4298
- const [unavailable2, setUnavailable] = useState19(false);
4259
+ const [unavailable2, setUnavailable] = useState18(false);
4299
4260
  const trackEnabled = track?.enabled;
4300
4261
  useEffect15(() => {
4301
4262
  const element = video.current;
@@ -4364,7 +4325,7 @@ function DevicePopover({
4364
4325
  toggleDisabled,
4365
4326
  busy
4366
4327
  }) {
4367
- const [open, setOpen] = useState19(false);
4328
+ const [open, setOpen] = useState18(false);
4368
4329
  const mic = type === "mic";
4369
4330
  const label = mic ? isActive ? "Mute microphone" : "Unmute microphone" : isActive ? "Turn off camera" : "Turn on camera";
4370
4331
  return /* @__PURE__ */ jsxs20("div", { "data-part": `${type}-split`, className: cn("chalk-shell-split", className), "data-off": !isActive, children: [
@@ -4431,10 +4392,10 @@ function LeaveMenu({ onLeave, onEndForEveryone, renderButton }) {
4431
4392
  }
4432
4393
 
4433
4394
  // src/components/control-bar/DockLayout.tsx
4434
- import { useState as useState20 } from "react";
4395
+ import { useState as useState19 } from "react";
4435
4396
  import { Fragment as Fragment13, jsx as jsx41, jsxs as jsxs23 } from "react/jsx-runtime";
4436
4397
  function DockLayout({ layout, onLayoutChange, children }) {
4437
- const [open, setOpen] = useState20(false);
4398
+ const [open, setOpen] = useState19(false);
4438
4399
  return /* @__PURE__ */ jsxs23(Fragment13, { children: [
4439
4400
  /* @__PURE__ */ jsx41(ChalkIconButton, { size: "lg", "aria-label": "More options", "aria-haspopup": "dialog", "aria-expanded": open, onClick: () => setOpen(true), children: /* @__PURE__ */ jsx41("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx41("path", { "data-part": "dock-more-glyph", d: "M5 12h.01M12 12h.01M19 12h.01", strokeWidth: "3" }) }) }),
4440
4401
  /* @__PURE__ */ jsx41(ChalkSheet, { title: "More options", open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs23(
@@ -4475,7 +4436,7 @@ function DockLayout({ layout, onLayoutChange, children }) {
4475
4436
  }
4476
4437
 
4477
4438
  // src/components/control-bar/ShareControl.tsx
4478
- import { useState as useState21 } from "react";
4439
+ import { useState as useState20 } from "react";
4479
4440
  import { Fragment as Fragment14, jsx as jsx42, jsxs as jsxs24 } from "react/jsx-runtime";
4480
4441
  function SourceIcon({ source }) {
4481
4442
  return /* @__PURE__ */ jsx42("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: source === "monitor" ? /* @__PURE__ */ jsxs24(Fragment14, { children: [
@@ -4490,9 +4451,9 @@ function SourceIcon({ source }) {
4490
4451
  ] }) });
4491
4452
  }
4492
4453
  function ShareControl({ sharing, onToggle, onStart, disabled = false, startDisabled = false }) {
4493
- const [surface, setSurface] = useState21("window");
4494
- const [audio, setAudio] = useState21(true);
4495
- const [replace, setReplace] = useState21(false);
4454
+ const [surface, setSurface] = useState20("window");
4455
+ const [audio, setAudio] = useState20(true);
4456
+ const [replace, setReplace] = useState20(false);
4496
4457
  const start2 = (next) => {
4497
4458
  if (disabled || startDisabled) return;
4498
4459
  setSurface(next);
@@ -4547,7 +4508,7 @@ function ShareControl({ sharing, onToggle, onStart, disabled = false, startDisab
4547
4508
  }
4548
4509
 
4549
4510
  // src/components/control-bar/control-bar-behavior.ts
4550
- import { useCallback as useCallback5, useEffect as useEffect16, useMemo as useMemo9, useState as useState22 } from "react";
4511
+ import { useCallback as useCallback5, useEffect as useEffect16, useMemo as useMemo9, useState as useState21 } from "react";
4551
4512
  var DEFAULT_CONTROL_BAR_BUTTONS = ["mic", "video", "screenshare", "record", "whiteboard", "handraise", "leave", "participants", "chat", "reactions"];
4552
4513
  var EMPTY_DETECTED_DEVICES = {
4553
4514
  audioinput: [],
@@ -4584,7 +4545,7 @@ function useControlBarSurfaceBehavior({
4584
4545
  detectDevices = true
4585
4546
  }) {
4586
4547
  const themeVariables = useMemo9(() => getParticipantThemeVariables(participantColorSeed, participantGradientPreference), [participantColorSeed, participantGradientPreference]);
4587
- const [detectedDevices, setDetectedDevices] = useState22(EMPTY_DETECTED_DEVICES);
4548
+ const [detectedDevices, setDetectedDevices] = useState21(EMPTY_DETECTED_DEVICES);
4588
4549
  const buttonsToRender = buttons ?? DEFAULT_CONTROL_BAR_BUTTONS;
4589
4550
  useEffect16(() => {
4590
4551
  if (!detectDevices || density !== "comfortable" || !navigator.mediaDevices?.enumerateDevices) return;
@@ -4643,10 +4604,10 @@ function useConnectedControlBarBehavior(props) {
4643
4604
  const recordingStatus = recording.current?.status;
4644
4605
  const isRecording = recordingStatus === "recording" || recordingStatus === "stopping";
4645
4606
  const isRecordingPending = recordingStatus === "starting" || recordingStatus === "stopping";
4646
- const [noiseSuppression, setNoiseSuppression] = useState22(true);
4647
- const [commandError, setCommandError] = useState22(null);
4648
- const [commandSource, setCommandSource] = useState22();
4649
- const [commandAction, setCommandAction] = useState22();
4607
+ const [noiseSuppression, setNoiseSuppression] = useState21(true);
4608
+ const [commandError, setCommandError] = useState21(null);
4609
+ const [commandSource, setCommandSource] = useState21();
4610
+ const [commandAction, setCommandAction] = useState21();
4650
4611
  const run = useCallback5(
4651
4612
  async (command, source, action) => {
4652
4613
  setCommandError(null);
@@ -4806,8 +4767,8 @@ function ControlBarPresentation(props) {
4806
4767
  var ControlBarSurface = React12.memo((props) => {
4807
4768
  const { buttonsToRender, effectiveAudioInputDevices, effectiveAudioOutputDevices, effectiveVideoInputDevices, showLeave } = useControlBarSurfaceBehavior({ ...props, density: props.density ?? "comfortable", detectDevices: props.detectDevices ?? true });
4808
4769
  const dock = useRef12(null);
4809
- const [fullscreen, setFullscreen] = useState23(false);
4810
- const [canCaptureDisplay, setCanCaptureDisplay] = useState23(false);
4770
+ const [fullscreen, setFullscreen] = useState22(false);
4771
+ const [canCaptureDisplay, setCanCaptureDisplay] = useState22(false);
4811
4772
  useEffect17(() => setCanCaptureDisplay(typeof navigator.mediaDevices?.getDisplayMedia === "function"), []);
4812
4773
  useEffect17(() => {
4813
4774
  const changed = () => setFullscreen(Boolean(document.fullscreenElement));
@@ -4958,10 +4919,10 @@ function ControlBar(props) {
4958
4919
  }
4959
4920
 
4960
4921
  // src/components/participants-panel/ParticipantsPanel.tsx
4961
- import React13, { useMemo as useMemo10, useState as useState25 } from "react";
4922
+ import React13, { useMemo as useMemo10, useState as useState24 } from "react";
4962
4923
 
4963
4924
  // src/components/participants-panel/participant-row.tsx
4964
- import { useState as useState24, useRef as useRef13, useEffect as useEffect18 } from "react";
4925
+ import { useState as useState23, useRef as useRef13, useEffect as useEffect18 } from "react";
4965
4926
 
4966
4927
  // src/components/participants-panel/participant-options-menu-contract.ts
4967
4928
  function runParticipantAction(action, onClose, onCommandError) {
@@ -5129,14 +5090,15 @@ function ParticipantRow({
5129
5090
  onCommandError,
5130
5091
  participantVolumes,
5131
5092
  onParticipantVolumeChange,
5093
+ onParticipantClick,
5132
5094
  participantGradientPreference,
5133
5095
  generatedAvatars = true,
5134
5096
  menuOpen,
5135
5097
  onMenuToggle,
5136
5098
  onMenuClose
5137
5099
  }) {
5138
- const [isEditing, setIsEditing] = useState24(false);
5139
- const [editName, setEditName] = useState24(participant.displayName);
5100
+ const [isEditing, setIsEditing] = useState23(false);
5101
+ const [editName, setEditName] = useState23(participant.displayName);
5140
5102
  const inputRef = useRef13(null);
5141
5103
  const rootRef = useRef13(null);
5142
5104
  const hasVolumeControl = !!participantVolumes && !!onParticipantVolumeChange;
@@ -5161,78 +5123,100 @@ function ParticipantRow({
5161
5123
  }
5162
5124
  };
5163
5125
  const optionsButtonClassName = variant === "mobile" ? "text-[var(--chalk-app-text-muted)] hover:text-[var(--chalk-app-text)]" : variant === "sidebar" ? "opacity-70 text-[var(--chalk-app-text-muted)] hover:text-[var(--chalk-app-text)] hover:opacity-100" : "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100";
5164
- return /* @__PURE__ */ jsxs27("div", { ref: rootRef, className: "call-person-row group", children: [
5165
- /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
5166
- /* @__PURE__ */ jsx45("div", { className: "relative", children: /* @__PURE__ */ jsx45(Avatar, { name: participant.displayName, src: participant.avatarUrl, size: "sm", generated: generatedAvatars, className: "!h-8 !w-8", gradientPreference: participantGradientPreference }) }),
5167
- /* @__PURE__ */ jsxs27("div", { className: "flex flex-col min-w-0 flex-1", children: [
5168
- /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-1.5 w-full", children: [
5169
- isEditing ? /* @__PURE__ */ jsx45("div", { className: "flex items-center gap-1 flex-1", children: /* @__PURE__ */ jsx45(
5170
- "input",
5171
- {
5172
- ref: inputRef,
5173
- type: "text",
5174
- "aria-label": "Your name",
5175
- value: editName,
5176
- onChange: (e) => setEditName(e.target.value),
5177
- onKeyDown: handleKeyDown,
5178
- onBlur: handleSave,
5179
- className: "w-full min-w-0 rounded border border-[var(--chalk-app-control-active-line)]/30 bg-[var(--chalk-app-input)] px-1.5 py-0.5 text-sm font-normal text-[var(--chalk-app-text)] outline-none focus:border-[var(--chalk-app-control-active-line)]"
5180
- }
5181
- ) }) : /* @__PURE__ */ jsx45("span", { className: "min-w-0 truncate text-sm font-medium text-[var(--chalk-app-text)]", onClick: () => participant.isLocal && onUpdateDisplayName && setIsEditing(true), title: participant.isLocal && onUpdateDisplayName ? "Click to edit" : void 0, children: /* @__PURE__ */ jsx45("bdi", { children: participant.displayName }) }),
5182
- participant.isHost && !isEditing ? /* @__PURE__ */ jsx45("span", { className: "shrink-0 text-xs text-[var(--chalk-app-text-muted)]", children: "Host" }) : null,
5183
- participant.isLocal && !isEditing && /* @__PURE__ */ jsxs27("span", { className: "flex shrink-0 items-center gap-1 text-xs text-[var(--chalk-app-text-muted)]", children: [
5184
- "(You)",
5185
- onUpdateDisplayName && /* @__PURE__ */ jsx45("button", { type: "button", onClick: () => setIsEditing(true), "aria-label": "Edit your name", className: "call-edit-name", children: /* @__PURE__ */ jsx45(Edit02Icon, { className: "w-3 h-3" }) })
5126
+ return /* @__PURE__ */ jsxs27(
5127
+ "div",
5128
+ {
5129
+ ref: rootRef,
5130
+ className: "call-person-row group",
5131
+ onClick: (event) => {
5132
+ if (event.target instanceof Element && event.currentTarget.contains(event.target) && !event.target.closest("button, input, [role=menu]")) onParticipantClick?.(participant.id);
5133
+ },
5134
+ children: [
5135
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
5136
+ /* @__PURE__ */ jsx45("div", { className: "relative", children: /* @__PURE__ */ jsx45(Avatar, { name: participant.displayName, src: participant.avatarUrl, size: "sm", generated: generatedAvatars, className: "!h-8 !w-8", gradientPreference: participantGradientPreference }) }),
5137
+ /* @__PURE__ */ jsxs27("div", { className: "flex flex-col min-w-0 flex-1", children: [
5138
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-1.5 w-full", children: [
5139
+ isEditing ? /* @__PURE__ */ jsx45("div", { className: "flex items-center gap-1 flex-1", children: /* @__PURE__ */ jsx45(
5140
+ "input",
5141
+ {
5142
+ ref: inputRef,
5143
+ type: "text",
5144
+ "aria-label": "Your name",
5145
+ value: editName,
5146
+ onChange: (e) => setEditName(e.target.value),
5147
+ onKeyDown: handleKeyDown,
5148
+ onBlur: handleSave,
5149
+ className: "w-full min-w-0 rounded border border-[var(--chalk-app-control-active-line)]/30 bg-[var(--chalk-app-input)] px-1.5 py-0.5 text-sm font-normal text-[var(--chalk-app-text)] outline-none focus:border-[var(--chalk-app-control-active-line)]"
5150
+ }
5151
+ ) }) : /* @__PURE__ */ jsx45(
5152
+ "button",
5153
+ {
5154
+ type: "button",
5155
+ className: "min-w-0 truncate text-left text-sm font-medium text-[var(--chalk-app-text)]",
5156
+ onClick: () => {
5157
+ if (onParticipantClick) onParticipantClick(participant.id);
5158
+ else if (participant.isLocal && onUpdateDisplayName) setIsEditing(true);
5159
+ },
5160
+ "aria-label": onParticipantClick ? `Show ${participant.displayName} on main screen` : participant.displayName,
5161
+ children: /* @__PURE__ */ jsx45("bdi", { children: participant.displayName })
5162
+ }
5163
+ ),
5164
+ participant.isHost && !isEditing ? /* @__PURE__ */ jsx45("span", { className: "shrink-0 text-xs text-[var(--chalk-app-text-muted)]", children: "Host" }) : null,
5165
+ participant.isLocal && !isEditing && /* @__PURE__ */ jsxs27("span", { className: "flex shrink-0 items-center gap-1 text-xs text-[var(--chalk-app-text-muted)]", children: [
5166
+ "(You)",
5167
+ onUpdateDisplayName && /* @__PURE__ */ jsx45("button", { type: "button", onClick: () => setIsEditing(true), "aria-label": "Edit your name", className: "call-edit-name", children: /* @__PURE__ */ jsx45(Edit02Icon, { className: "w-3 h-3" }) })
5168
+ ] })
5169
+ ] }),
5170
+ /* @__PURE__ */ jsx45("div", { className: "flex items-center gap-1.5" })
5186
5171
  ] })
5187
5172
  ] }),
5188
- /* @__PURE__ */ jsx45("div", { className: "flex items-center gap-1.5" })
5189
- ] })
5190
- ] }),
5191
- /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-1 shrink-0", children: [
5192
- participant.isMuted ? /* @__PURE__ */ jsx45(MicrophoneOff01Icon, { className: "h-4 w-4 text-[var(--chalk-danger-text)]", "aria-label": "Microphone off", role: "img" }) : null,
5193
- participant.isHandRaised ? /* @__PURE__ */ jsxs27("span", { className: "call-hand", role: "img", "aria-label": `Hand raised${participant.handOrder ? `, number ${participant.handOrder}` : ""}`, children: [
5194
- "\u270B",
5195
- participant.handOrder
5196
- ] }) : null,
5197
- !participant.isVideoEnabled ? /* @__PURE__ */ jsx45(VideoOffIcon, { className: "h-4 w-4 text-[var(--chalk-app-text-muted)]", "aria-label": "Camera off", role: "img" }) : null,
5198
- showMenuButton && !isEditing && /* @__PURE__ */ jsxs27(
5199
- ChalkPopoverPrimitive.Root,
5200
- {
5201
- open: menuOpen,
5202
- onOpenChange: (open) => {
5203
- if (open) onMenuToggle();
5204
- else onMenuClose();
5205
- },
5206
- children: [
5207
- /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Trigger, { className: cn("call-person-options", optionsButtonClassName), "aria-label": `Options for ${participant.displayName}`, children: /* @__PURE__ */ jsx45("svg", { className: "size-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx45("path", { d: "M5 12h.01M12 12h.01M19 12h.01" }) }) }),
5208
- /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Portal, { container: rootRef.current?.closest("[data-chalk]") ?? void 0, children: /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Positioner, { side: "bottom", align: "end", sideOffset: 6, collisionPadding: 8, className: "chalk-popover-positioner", children: /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Popup, { "aria-label": `Options for ${participant.displayName}`, className: "chalk-menu w-60", children: /* @__PURE__ */ jsx45(
5209
- ParticipantOptionsMenu,
5210
- {
5211
- participant,
5212
- variant,
5213
- canManageParticipants,
5214
- onClose: onMenuClose,
5215
- onAssignRole,
5216
- onStopParticipantScreenShare,
5217
- onMuteParticipant,
5218
- onRequestUnmute,
5219
- onStopParticipantCamera,
5220
- onRequestStartCamera,
5221
- onRemoveParticipant,
5222
- onEditName: participant.isLocal ? () => {
5223
- setIsEditing(true);
5224
- onMenuClose();
5225
- } : void 0,
5226
- participantVolumes,
5227
- onParticipantVolumeChange,
5228
- onCommandError
5229
- }
5230
- ) }) }) })
5231
- ]
5232
- }
5233
- )
5234
- ] })
5235
- ] });
5173
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-1 shrink-0", children: [
5174
+ participant.isMuted ? /* @__PURE__ */ jsx45(MicrophoneOff01Icon, { className: "h-4 w-4 text-[var(--chalk-danger-text)]", "aria-label": "Microphone off", role: "img" }) : null,
5175
+ participant.isHandRaised ? /* @__PURE__ */ jsxs27("span", { className: "call-hand", role: "img", "aria-label": `Hand raised${participant.handOrder ? `, number ${participant.handOrder}` : ""}`, children: [
5176
+ "\u270B",
5177
+ participant.handOrder
5178
+ ] }) : null,
5179
+ !participant.isVideoEnabled ? /* @__PURE__ */ jsx45(VideoOffIcon, { className: "h-4 w-4 text-[var(--chalk-app-text-muted)]", "aria-label": "Camera off", role: "img" }) : null,
5180
+ showMenuButton && !isEditing && /* @__PURE__ */ jsxs27(
5181
+ ChalkPopoverPrimitive.Root,
5182
+ {
5183
+ open: menuOpen,
5184
+ onOpenChange: (open) => {
5185
+ if (open) onMenuToggle();
5186
+ else onMenuClose();
5187
+ },
5188
+ children: [
5189
+ /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Trigger, { className: cn("call-person-options", optionsButtonClassName), "aria-label": `Options for ${participant.displayName}`, children: /* @__PURE__ */ jsx45("svg", { className: "size-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx45("path", { d: "M5 12h.01M12 12h.01M19 12h.01" }) }) }),
5190
+ /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Portal, { container: rootRef.current?.closest("[data-chalk]") ?? void 0, children: /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Positioner, { side: "bottom", align: "end", sideOffset: 6, collisionPadding: 8, className: "chalk-popover-positioner", children: /* @__PURE__ */ jsx45(ChalkPopoverPrimitive.Popup, { "aria-label": `Options for ${participant.displayName}`, className: "chalk-menu w-60", children: /* @__PURE__ */ jsx45(
5191
+ ParticipantOptionsMenu,
5192
+ {
5193
+ participant,
5194
+ variant,
5195
+ canManageParticipants,
5196
+ onClose: onMenuClose,
5197
+ onAssignRole,
5198
+ onStopParticipantScreenShare,
5199
+ onMuteParticipant,
5200
+ onRequestUnmute,
5201
+ onStopParticipantCamera,
5202
+ onRequestStartCamera,
5203
+ onRemoveParticipant,
5204
+ onEditName: participant.isLocal ? () => {
5205
+ setIsEditing(true);
5206
+ onMenuClose();
5207
+ } : void 0,
5208
+ participantVolumes,
5209
+ onParticipantVolumeChange,
5210
+ onCommandError
5211
+ }
5212
+ ) }) }) })
5213
+ ]
5214
+ }
5215
+ )
5216
+ ] })
5217
+ ]
5218
+ }
5219
+ );
5236
5220
  }
5237
5221
 
5238
5222
  // src/components/participants-panel/ParticipantsPanel.tsx
@@ -5259,13 +5243,14 @@ var ParticipantsPanelSurface = React13.memo(
5259
5243
  onCommandError,
5260
5244
  participantVolumes,
5261
5245
  onParticipantVolumeChange,
5246
+ onParticipantClick,
5262
5247
  participantGradientPreference,
5263
5248
  generatedAvatars = true
5264
5249
  }) => {
5265
- const [query, setQuery] = useState25("");
5266
- const [activeMenuId, setActiveMenuId] = useState25(null);
5267
- const [muting, setMuting] = useState25(false);
5268
- const [error, setError] = useState25(null);
5250
+ const [query, setQuery] = useState24("");
5251
+ const [activeMenuId, setActiveMenuId] = useState24(null);
5252
+ const [muting, setMuting] = useState24(false);
5253
+ const [error, setError] = useState24(null);
5269
5254
  const filtered = participants.filter((person) => person.displayName.toLocaleLowerCase().includes(query.trim().toLocaleLowerCase()));
5270
5255
  const raised = participants.filter((person) => person.isHandRaised);
5271
5256
  const unmutedCount = participants.filter((person) => !person.isLocal && !person.isMuted).length;
@@ -5328,6 +5313,7 @@ var ParticipantsPanelSurface = React13.memo(
5328
5313
  ParticipantRow,
5329
5314
  {
5330
5315
  participant,
5316
+ onParticipantClick,
5331
5317
  variant,
5332
5318
  canManageParticipants,
5333
5319
  onAssignRole,
@@ -5368,7 +5354,7 @@ var ParticipantsPanel = React13.memo((props) => {
5368
5354
  const canRemoveParticipants = useCan("removeParticipant");
5369
5355
  const canManageAdmission = useCan("manageAdmission");
5370
5356
  const contextVolumeState = useParticipantVolumeContext();
5371
- const [localVolumes, setLocalVolumes] = useState25(/* @__PURE__ */ new Map());
5357
+ const [localVolumes, setLocalVolumes] = useState24(/* @__PURE__ */ new Map());
5372
5358
  const isControlled = props.participantVolumes !== void 0 && props.onParticipantVolumeChange !== void 0;
5373
5359
  const participantVolumes = isControlled ? props.participantVolumes : contextVolumeState?.volumes ?? localVolumes;
5374
5360
  const onParticipantVolumeChange = isControlled ? props.onParticipantVolumeChange : contextVolumeState?.setVolume ?? ((participantId, volume) => setLocalVolumes((current) => {
@@ -5420,26 +5406,15 @@ var ParticipantsPanel = React13.memo((props) => {
5420
5406
  ParticipantsPanel.displayName = "ParticipantsPanel";
5421
5407
 
5422
5408
  // src/components/chalk/StatusSurface.tsx
5423
- import { formatSyncConnectDiagnostic } from "@q9labsai/chalk-client";
5409
+ import { formatSyncConnectDiagnostic, getConnectionFailureDetail } from "@q9labsai/chalk-client";
5424
5410
  import { Fragment as Fragment18, jsx as jsx47, jsxs as jsxs29 } from "react/jsx-runtime";
5425
- var DEFAULT_FAILURE_DETAIL = "Something went wrong while joining. Try again.";
5426
- var FAILURE_DETAILS = {
5427
- "access.invalid": "Access to this call was rejected. Refresh the page and try again.",
5428
- "access.unavailable": "Couldn\u2019t get access to the call. Try again.",
5429
- "connection.sync_start_failed": "Couldn\u2019t reach the call service. Try again.",
5430
- "connection.sync_hello_timeout": "The call service did not respond in time. Try again.",
5431
- "connection.sync_recovery_exhausted": "The call connection could not recover. Try again.",
5432
- "connection.media_start_failed": "Audio and video could not connect. Try again.",
5433
- "connection.media_recovery_exhausted": "Audio and video could not reconnect. Try again.",
5434
- "environment.unsupported": "This browser cannot start the call. Use an up-to-date browser over HTTPS.",
5435
- "client.internal_error": DEFAULT_FAILURE_DETAIL
5436
- };
5437
5411
  function StatusSurface({ phase, callName = "the call", reason, episodeEndReason, endAction, errorCode, sync, theme, onRejoin, onHome, onRetry, onReportProblem, rejoinDisabled = false, retryPending = false }) {
5412
+ const connectionLost = phase === "failed" && errorCode === "connection.sync_recovery_exhausted";
5438
5413
  const copy = {
5439
5414
  entering: { title: `Joining ${callName}\u2026`, detail: "" },
5440
5415
  left: { title: `You left ${callName}`, detail: "" },
5441
5416
  "episode-ended": episodeEndReason === "maximum_duration" ? { title: "The call reached its time limit", detail: "This call has ended for everyone." } : { title: "The call ended", detail: "" },
5442
- failed: { title: `Couldn\u2019t connect to ${callName}`, detail: (errorCode && FAILURE_DETAILS[errorCode]) ?? DEFAULT_FAILURE_DETAIL },
5417
+ failed: { title: connectionLost ? "Connection lost" : `Couldn\u2019t connect to ${callName}`, detail: getConnectionFailureDetail({ code: errorCode, sync }) },
5443
5418
  removed: { title: `You were removed from ${callName}`, detail: "The host removed you from this call." },
5444
5419
  full: { title: "This call is full", detail: `${callName} has reached 100 people. Ask the host to make room, then try again.` },
5445
5420
  elsewhere: { title: "You joined from another tab", detail: `${callName} is open in another tab or window. Use it here instead?` }
@@ -5467,7 +5442,7 @@ function StatusSurface({ phase, callName = "the call", reason, episodeEndReason,
5467
5442
  ] }) : null,
5468
5443
  /* @__PURE__ */ jsxs29("div", { "data-part": "status-actions", className: "mt-5 flex gap-7", children: [
5469
5444
  phase === "episode-ended" && episodeEndReason === "maximum_duration" && endAction ? /* @__PURE__ */ jsx47(StatusAction, { icon: /* @__PURE__ */ jsx47(StatusIcon, { retry: true }), label: endAction.label, onClick: endAction.onClick }) : null,
5470
- canRetry && retry ? /* @__PURE__ */ jsx47(StatusAction, { icon: /* @__PURE__ */ jsx47(StatusIcon, { retry: true }), label: phase === "elsewhere" ? "Use here" : phase === "left" ? "Rejoin" : "Try again", onClick: retry, disabled: rejoinDisabled || retryPending }) : null,
5445
+ canRetry && retry ? /* @__PURE__ */ jsx47(StatusAction, { icon: /* @__PURE__ */ jsx47(StatusIcon, { retry: true }), label: phase === "elsewhere" ? "Use here" : phase === "left" || connectionLost ? "Rejoin" : "Try again", onClick: retry, disabled: rejoinDisabled || retryPending }) : null,
5471
5446
  phase !== "entering" && onHome ? /* @__PURE__ */ jsx47(StatusAction, { icon: /* @__PURE__ */ jsx47(StatusIcon, {}), label: "Home", onClick: onHome }) : null
5472
5447
  ] }),
5473
5448
  onReportProblem && phase !== "entering" ? /* @__PURE__ */ jsx47("button", { type: "button", onClick: onReportProblem, className: "mt-[18px] px-2.5 py-2 text-[13px] text-[var(--chalk-muted-text)] underline underline-offset-4 focus-visible:outline-2 focus-visible:outline-offset-2", children: "Report a problem" }) : null
@@ -5498,7 +5473,7 @@ function StatusAction({ icon, label, onClick, disabled }) {
5498
5473
  }
5499
5474
 
5500
5475
  // src/components/call-limbo/CallReady.tsx
5501
- import { useEffect as useEffect19, useId, useRef as useRef14, useState as useState26 } from "react";
5476
+ import { useEffect as useEffect19, useId, useRef as useRef14, useState as useState25 } from "react";
5502
5477
 
5503
5478
  // src/components/call-limbo/qr-code.ts
5504
5479
  function inviteQR(text) {
@@ -5641,13 +5616,13 @@ function inviteQR(text) {
5641
5616
  // src/components/call-limbo/CallReady.tsx
5642
5617
  import { Fragment as Fragment19, jsx as jsx48, jsxs as jsxs30 } from "react/jsx-runtime";
5643
5618
  function CallReady({ open, onClose, link = typeof location === "undefined" ? "" : location.href }) {
5644
- const [showQR, setShowQR] = useState26(false);
5619
+ const [showQR, setShowQR] = useState25(false);
5645
5620
  const qrRef = useRef14(null);
5646
5621
  const cardRef = useRef14(null);
5647
5622
  const phone = useIsMobile();
5648
5623
  const reducedMotion = usePrefersReducedMotion();
5649
- const [entered, setEntered] = useState26(false);
5650
- const [present, setPresent] = useState26(open);
5624
+ const [entered, setEntered] = useState25(false);
5625
+ const [present, setPresent] = useState25(open);
5651
5626
  const id = useId();
5652
5627
  const qr = showQR ? inviteQR(link) : null;
5653
5628
  const close = () => {
@@ -5728,11 +5703,11 @@ function CallReady({ open, onClose, link = typeof location === "undefined" ? ""
5728
5703
  }
5729
5704
 
5730
5705
  // src/components/toast-stack/ToastStack.tsx
5731
- import { memo, useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState28 } from "react";
5706
+ import { memo, useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState27 } from "react";
5732
5707
  import { flushSync as flushSync2 } from "react-dom";
5733
5708
 
5734
5709
  // src/components/toast-stack/useToastCapacity.ts
5735
- import { isValidElement as isValidElement2, useLayoutEffect as useLayoutEffect2, useState as useState27 } from "react";
5710
+ import { isValidElement as isValidElement2, useLayoutEffect as useLayoutEffect2, useState as useState26 } from "react";
5736
5711
  import { flushSync } from "react-dom";
5737
5712
 
5738
5713
  // src/components/toast-stack/toast-layout-snapshot.ts
@@ -5777,7 +5752,7 @@ function measureToastLayout(stack, snapshot) {
5777
5752
 
5778
5753
  // src/components/toast-stack/useToastCapacity.ts
5779
5754
  function useToastCapacity(stack, candidates, enabled, ownedIds) {
5780
- const [fit, setFit] = useState27(null);
5755
+ const [fit, setFit] = useState26(null);
5781
5756
  let count = candidates.length;
5782
5757
  if (enabled) {
5783
5758
  count = 0;
@@ -5871,7 +5846,7 @@ var ToastStack = memo(function ToastStack2({ toasts, onDismiss, maxVisible = 3,
5871
5846
  const stack = useRef15(null);
5872
5847
  const short = useShortCall(stack, onFold !== void 0);
5873
5848
  const candidates = maxVisible > 0 ? toasts.slice(-maxVisible) : [];
5874
- const [ownedIds, setOwnedIds] = useState28([]);
5849
+ const [ownedIds, setOwnedIds] = useState27([]);
5875
5850
  const fold = useRef15(onFold);
5876
5851
  const capacity = useToastCapacity(stack, candidates, onFold !== void 0 && short === false, ownedIds);
5877
5852
  const selected = onFold !== void 0 && short !== false ? [] : candidates.slice(candidates.length - capacity.count);
@@ -5880,7 +5855,7 @@ var ToastStack = memo(function ToastStack2({ toasts, onDismiss, maxVisible = 3,
5880
5855
  const foldedIds = folded.map((toast) => toast.id);
5881
5856
  const announced = useRef15(/* @__PURE__ */ new Map());
5882
5857
  const wasAnnounced = (toast) => announced.current.get(toast.id) === noticeIdentity(toast);
5883
- const [unheard, setUnheard] = useState28([]);
5858
+ const [unheard, setUnheard] = useState27([]);
5884
5859
  const reported = useRef15([]);
5885
5860
  const reporting = useRef15(false);
5886
5861
  useLayoutEffect3(() => {
@@ -5927,7 +5902,7 @@ var ToastStack = memo(function ToastStack2({ toasts, onDismiss, maxVisible = 3,
5927
5902
  ] });
5928
5903
  });
5929
5904
  function useShortCall(stack, enabled) {
5930
- const [short, setShort] = useState28(null);
5905
+ const [short, setShort] = useState27(null);
5931
5906
  useLayoutEffect3(() => {
5932
5907
  if (!enabled) {
5933
5908
  setShort(null);
@@ -5948,7 +5923,7 @@ function sameIds(a, b) {
5948
5923
  }
5949
5924
 
5950
5925
  // src/internal/call-motion.ts
5951
- import { useEffect as useEffect20, useState as useState29 } from "react";
5926
+ import { useEffect as useEffect20, useState as useState28 } from "react";
5952
5927
  var moves = /* @__PURE__ */ new WeakMap();
5953
5928
  function captureFlip(elements) {
5954
5929
  const previous = Array.from(elements, (element) => ({ element, box: element.getBoundingClientRect() }));
@@ -5976,7 +5951,7 @@ function playFlip(previous) {
5976
5951
  }
5977
5952
  var ACTIVE_LAYERS = '[role="menu"],[role="dialog"],[data-part="toast"],[data-part="notice-button"],[data-chalk-drawer]';
5978
5953
  function useIdleChrome(root, enabled) {
5979
- const [idle, setIdle] = useState29(false);
5954
+ const [idle, setIdle] = useState28(false);
5980
5955
  const fine = useMediaQuery("(pointer:fine) and (min-width:641px)");
5981
5956
  useEffect20(() => {
5982
5957
  const element = root.current;
@@ -6008,7 +5983,7 @@ function useIdleChrome(root, enabled) {
6008
5983
  }
6009
5984
 
6010
5985
  // src/components/space-header/SpaceHeader.tsx
6011
- import React14, { useCallback as useCallback6, useRef as useRef18, useState as useState31 } from "react";
5986
+ import React14, { useCallback as useCallback6, useRef as useRef18, useState as useState30 } from "react";
6012
5987
 
6013
5988
  // src/internal/useSoundsSetting.ts
6014
5989
  import { useSyncExternalStore as useSyncExternalStore3 } from "react";
@@ -6060,7 +6035,7 @@ function LayoutMenu({ layout, onLayoutChange }) {
6060
6035
 
6061
6036
  // src/components/space-header/CallDetails.tsx
6062
6037
  import { Dialog as Dialog2 } from "@base-ui/react/dialog";
6063
- import { useEffect as useEffect21, useRef as useRef16, useState as useState30 } from "react";
6038
+ import { useEffect as useEffect21, useRef as useRef16, useState as useState29 } from "react";
6064
6039
 
6065
6040
  // src/components/space-header/share-qr.ts
6066
6041
  function shareQr(text) {
@@ -6215,10 +6190,10 @@ function CallDialog({
6215
6190
  const container = useRef16(null);
6216
6191
  const reportInput = useRef16(null);
6217
6192
  const reportOpener = useRef16(null);
6218
- const [text, setText] = useState30("");
6219
- const [includeDiagnostics, setIncludeDiagnostics] = useState30(false);
6220
- const [status, setStatus] = useState30("idle");
6221
- const [error, setError] = useState30("");
6193
+ const [text, setText] = useState29("");
6194
+ const [includeDiagnostics, setIncludeDiagnostics] = useState29(false);
6195
+ const [status, setStatus] = useState29("idle");
6196
+ const [error, setError] = useState29("");
6222
6197
  useEffect21(() => {
6223
6198
  if (open && kind === "report") {
6224
6199
  setText("");
@@ -6353,7 +6328,7 @@ function CallDetails({
6353
6328
  }) {
6354
6329
  const link = shareUrl ?? (typeof location === "undefined" ? "" : location.href);
6355
6330
  const qr = shareQr(link);
6356
- const [details, setDetails] = useState30(false);
6331
+ const [details, setDetails] = useState29(false);
6357
6332
  return /* @__PURE__ */ jsxs32("div", { className: "chalk-details", children: [
6358
6333
  /* @__PURE__ */ jsxs32("div", { className: "chalk-shell-details-heading", children: [
6359
6334
  /* @__PURE__ */ jsx51("h2", { children: spaceName }),
@@ -6505,8 +6480,8 @@ var SpaceHeader = React14.memo((props) => {
6505
6480
  const [sounds, setSounds] = useSoundsSetting();
6506
6481
  const triggerRef = useRef18(null);
6507
6482
  const focusScope = useRef18(null);
6508
- const [open, setOpen] = useState31(false);
6509
- const [dialog, setDialog] = useState31({ kind: "shortcuts", open: false });
6483
+ const [open, setOpen] = useState30(false);
6484
+ const [dialog, setDialog] = useState30({ kind: "shortcuts", open: false });
6510
6485
  const showShortcuts = useCallback6(() => setDialog({ kind: "shortcuts", open: true }), []);
6511
6486
  useCallShortcuts(props.shortcuts, showShortcuts);
6512
6487
  const phone = useMediaQuery("(max-width: 640px)");
@@ -6593,16 +6568,16 @@ var SpaceHeader = React14.memo((props) => {
6593
6568
  SpaceHeader.displayName = "SpaceHeader";
6594
6569
 
6595
6570
  // src/components/composite/ScreenShareView.tsx
6596
- import { useEffect as useEffect23, useMemo as useMemo11, useRef as useRef19, useState as useState32 } from "react";
6571
+ import { useEffect as useEffect23, useMemo as useMemo11, useRef as useRef19, useState as useState31 } from "react";
6597
6572
  import { Fragment as Fragment23, jsx as jsx53, jsxs as jsxs34 } from "react/jsx-runtime";
6598
6573
  function ScreenSharePresentation({ sharedByName, media, mediaVisible, state, isLocal = false, hasAudio = false, capture: capture2, primary = true, pinned, hidden, style, onClick, onDoubleClick, onStopSharing, onChangeShare, switcher, className }) {
6599
6574
  const root = useRef19(null);
6600
- const [fill, setFill] = useState32(false);
6601
- const [controlsOpen, setControlsOpen] = useState32(false);
6602
- const [poppedOut, setPoppedOut] = useState32(false);
6603
- const [zoom, setZoom] = useState32(false);
6604
- const [pending, setPending] = useState32(false);
6605
- const [error, setError] = useState32(null);
6575
+ const [fill, setFill] = useState31(false);
6576
+ const [controlsOpen, setControlsOpen] = useState31(false);
6577
+ const [poppedOut, setPoppedOut] = useState31(false);
6578
+ const [zoom, setZoom] = useState31(false);
6579
+ const [pending, setPending] = useState31(false);
6580
+ const [error, setError] = useState31(null);
6606
6581
  const status = state ?? (mediaVisible ? "live" : "connecting");
6607
6582
  const name = isLocal ? "Your screen" : `${sharedByName}'s screen`;
6608
6583
  const source = capture2?.surface === "window" ? "a window" : capture2?.surface === "browser" ? "a tab" : capture2?.surface === "monitor" ? "your screen" : null;
@@ -6788,16 +6763,16 @@ function ScreenShareView(props) {
6788
6763
  }
6789
6764
 
6790
6765
  // src/components/stage/Stage.tsx
6791
- import { useCallback as useCallback7, useEffect as useEffect24, useLayoutEffect as useLayoutEffect5, useMemo as useMemo12, useRef as useRef22, useState as useState34 } from "react";
6766
+ import { useCallback as useCallback7, useEffect as useEffect24, useLayoutEffect as useLayoutEffect5, useMemo as useMemo12, useRef as useRef22, useState as useState33 } from "react";
6792
6767
  import { createPortal as createPortal2 } from "react-dom";
6793
6768
 
6794
6769
  // src/components/stage/useStageDimensions.ts
6795
- import { useLayoutEffect as useLayoutEffect4, useRef as useRef20, useState as useState33 } from "react";
6770
+ import { useLayoutEffect as useLayoutEffect4, useRef as useRef20, useState as useState32 } from "react";
6796
6771
  import { flushSync as flushSync3 } from "react-dom";
6797
6772
  function useStageDimensions(fallback3) {
6798
6773
  const ref = useRef20(null);
6799
6774
  const current = useRef20(fallback3);
6800
- const [dimensions, setDimensions] = useState33(fallback3);
6775
+ const [dimensions, setDimensions] = useState32(fallback3);
6801
6776
  useLayoutEffect4(() => {
6802
6777
  const element = ref.current;
6803
6778
  if (!element || typeof ResizeObserver === "undefined") return;
@@ -6993,7 +6968,7 @@ function createContentPlacement() {
6993
6968
  };
6994
6969
  }
6995
6970
  function PersistentStageContent({ placement, children }) {
6996
- const [host, setHost] = useState34(null);
6971
+ const [host, setHost] = useState33(null);
6997
6972
  useLayoutEffect5(() => {
6998
6973
  const element = document.createElement("div");
6999
6974
  Object.assign(element.style, TILE_FILL);
@@ -7018,7 +6993,6 @@ function Stage({
7018
6993
  pinnedId,
7019
6994
  followingId = null,
7020
6995
  onFollowChange,
7021
- clickAction = "pin",
7022
6996
  onPinnedChange,
7023
6997
  onOverflowClick,
7024
6998
  onItemClick,
@@ -7037,9 +7011,9 @@ function Stage({
7037
7011
  }) {
7038
7012
  const prefersReducedMotion = usePrefersReducedMotion();
7039
7013
  const { ref: boxRef, dimensions: box } = useStageDimensions(FALLBACK_BOX);
7040
- const [overflowOpen, setOverflowOpen] = useState34(false);
7041
- const [shareAspects, setShareAspects] = useState34(/* @__PURE__ */ new Map());
7042
- const [uncontrolledPinnedId, setUncontrolledPinnedId] = useState34(null);
7014
+ const [overflowOpen, setOverflowOpen] = useState33(false);
7015
+ const [shareAspects, setShareAspects] = useState33(/* @__PURE__ */ new Map());
7016
+ const [uncontrolledPinnedId, setUncontrolledPinnedId] = useState33(null);
7043
7017
  const activePinnedId = pinnedId === void 0 ? uncontrolledPinnedId : pinnedId;
7044
7018
  const orderRef = useRef22([]);
7045
7019
  const seenAtRef = useRef22(/* @__PURE__ */ new Map());
@@ -7120,7 +7094,7 @@ function Stage({
7120
7094
  return /* @__PURE__ */ jsx56(StageContentTile, { item, ...context });
7121
7095
  };
7122
7096
  const animate = animateOverride ?? !prefersReducedMotion;
7123
- const [displayed, setDisplayed] = useState34({
7097
+ const [displayed, setDisplayed] = useState33({
7124
7098
  source: ordered,
7125
7099
  geometry,
7126
7100
  tiles: ordered.map((item) => ({ item, frame: framesById.get(item.id), leaving: false }))
@@ -7186,15 +7160,14 @@ function Stage({
7186
7160
  for (const item of ordered) {
7187
7161
  map.set(item.id, {
7188
7162
  onClick: () => {
7189
- if (clickAction === "follow" && item.kind === "participant" && !item.participant.isLocal) onFollowChange?.(item.id);
7190
- else togglePin(item);
7163
+ togglePin(item);
7191
7164
  onItemClick?.(item);
7192
7165
  },
7193
7166
  onDoubleClick: onItemDoubleClick ? () => onItemDoubleClick(item) : void 0
7194
7167
  });
7195
7168
  }
7196
7169
  return map;
7197
- }, [clickAction, interactive, onFollowChange, onItemDoubleClick, onItemClick, ordered, togglePin]);
7170
+ }, [interactive, onItemDoubleClick, onItemClick, ordered, togglePin]);
7198
7171
  if (ordered.length === 0) {
7199
7172
  return /* @__PURE__ */ jsx56("div", { className: cn("flex h-full w-full items-center justify-center px-6 py-10", className), "data-tour": "video-grid", children: emptyState });
7200
7173
  }
@@ -7219,7 +7192,7 @@ function Stage({
7219
7192
  aspectRatio: "fill",
7220
7193
  primary: frame?.role === "primary",
7221
7194
  pinned,
7222
- clickAction: item.participant.isLocal ? "pin" : clickAction,
7195
+ onFollow: onFollowChange && !item.participant.isLocal ? () => onFollowChange(item.id) : void 0,
7223
7196
  following: followingId === item.id,
7224
7197
  onClick: click,
7225
7198
  onDoubleClick: doubleClick,
@@ -7280,7 +7253,6 @@ function Stage({
7280
7253
  setOverflowOpen(false);
7281
7254
  },
7282
7255
  children: [
7283
- clickAction === "follow" && !item.participant.isLocal ? `${followingId === item.id ? "Stop following" : "Follow"} ` : "",
7284
7256
  item.participant.displayName,
7285
7257
  item.participant.isMuted ? " \xB7 Muted" : ""
7286
7258
  ]
@@ -7489,7 +7461,7 @@ function SpacePresentation({ colorScheme = "dark", stageBackground, header, stag
7489
7461
  // src/components/space-view/SpaceView.tsx
7490
7462
  import "@q9labsai/chalk-client";
7491
7463
  import { DEFAULT_QUICK_REACTIONS as DEFAULT_QUICK_REACTIONS2 } from "@q9labsai/chalk-ui/reactions";
7492
- import { useCallback as useCallback14, useEffect as useEffect36, useMemo as useMemo18, useRef as useRef29, useState as useState45 } from "react";
7464
+ import { useCallback as useCallback14, useEffect as useEffect36, useMemo as useMemo18, useRef as useRef29, useState as useState44 } from "react";
7493
7465
 
7494
7466
  // src/components/space-header/call-diagnostics.ts
7495
7467
  function callDiagnostics(connection, media) {
@@ -7520,11 +7492,11 @@ function callCountdown(deadline, now, previousSeconds) {
7520
7492
  }
7521
7493
 
7522
7494
  // src/internal/useEpisodeDuration.ts
7523
- import { useEffect as useEffect26, useState as useState35 } from "react";
7495
+ import { useEffect as useEffect26, useState as useState34 } from "react";
7524
7496
  function useEpisodeDuration() {
7525
7497
  const connection = useConnection();
7526
7498
  const episodeStart = connection.episode?.startedAt ? Date.parse(connection.episode.startedAt) : null;
7527
- const [now, setNow] = useState35(() => Date.now());
7499
+ const [now, setNow] = useState34(() => Date.now());
7528
7500
  useEffect26(() => {
7529
7501
  if (episodeStart === null || Number.isNaN(episodeStart)) return;
7530
7502
  setNow(Date.now());
@@ -7580,16 +7552,17 @@ function createSoundPlayer({ outputDeviceId } = {}) {
7580
7552
  const created = !context;
7581
7553
  try {
7582
7554
  context ??= new AudioContext();
7555
+ if (created && outputDeviceId && "setSinkId" in context && typeof context.setSinkId === "function") void Promise.resolve(context.setSinkId(outputDeviceId)).catch(() => void 0);
7556
+ if (context.state === "suspended") void context.resume().catch(() => void 0);
7583
7557
  } catch {
7584
7558
  return;
7585
7559
  }
7586
- if (created && outputDeviceId && "setSinkId" in context && typeof context.setSinkId === "function") void Promise.resolve(context.setSinkId(outputDeviceId)).catch(() => void 0);
7587
- if (context.state === "suspended") void context.resume().catch(() => void 0);
7588
7560
  };
7589
7561
  if (typeof window !== "undefined") {
7590
7562
  window.addEventListener("click", unlock, { capture: true });
7591
7563
  window.addEventListener("keydown", unlock, { capture: true });
7592
7564
  }
7565
+ unlock();
7593
7566
  const tone = (frequency, offset, duration, volume = 0.07, type = "sine", to) => {
7594
7567
  if (!context || context.state !== "running") return;
7595
7568
  const oscillator = context.createOscillator(), gain = context.createGain(), time = context.currentTime + offset;
@@ -7628,44 +7601,47 @@ function createSoundPlayer({ outputDeviceId } = {}) {
7628
7601
  return {
7629
7602
  play(cue) {
7630
7603
  if (disposed || !context || context.state !== "running") return;
7631
- switch (cue) {
7632
- case "join":
7633
- tone(659, 0, 0.2);
7634
- tone(988, 0.1, 0.28, 0.06);
7635
- break;
7636
- case "leave":
7637
- tone(784, 0, 0.2);
7638
- tone(523, 0.1, 0.3, 0.06);
7639
- break;
7640
- case "knock":
7641
- thud(0);
7642
- thud(0.17);
7643
- break;
7644
- case "message":
7645
- tone(1175, 0, 0.16, 0.05, "triangle");
7646
- break;
7647
- case "hand-raise":
7648
- tone(1319, 0, 0.32, 0.045);
7649
- tone(1760, 0.07, 0.4, 0.035);
7650
- break;
7651
- case "mute":
7652
- tone(560, 0, 0.07, 0.06, "triangle", 380);
7653
- break;
7654
- case "unmute":
7655
- tone(420, 0, 0.07, 0.06, "triangle", 640);
7656
- break;
7657
- case "recording":
7658
- tone(587, 0, 0.14);
7659
- tone(587, 0.18, 0.14);
7660
- tone(880, 0.36, 0.32, 0.06);
7661
- break;
7662
- case "error":
7663
- tone(392, 0, 0.16, 0.05, "triangle");
7664
- tone(311, 0.13, 0.24, 0.05, "triangle");
7665
- break;
7666
- case "reaction":
7667
- tone(880, 0, 0.12, 0.035, "triangle");
7668
- break;
7604
+ try {
7605
+ switch (cue) {
7606
+ case "join":
7607
+ tone(659, 0, 0.16, 0.04);
7608
+ tone(988, 0.08, 0.22, 0.03);
7609
+ break;
7610
+ case "leave":
7611
+ tone(784, 0, 0.2);
7612
+ tone(523, 0.1, 0.3, 0.06);
7613
+ break;
7614
+ case "knock":
7615
+ thud(0);
7616
+ thud(0.17);
7617
+ break;
7618
+ case "message":
7619
+ tone(1175, 0, 0.16, 0.05, "triangle");
7620
+ break;
7621
+ case "hand-raise":
7622
+ tone(1319, 0, 0.32, 0.045);
7623
+ tone(1760, 0.07, 0.4, 0.035);
7624
+ break;
7625
+ case "mute":
7626
+ tone(560, 0, 0.07, 0.06, "triangle", 380);
7627
+ break;
7628
+ case "unmute":
7629
+ tone(420, 0, 0.07, 0.06, "triangle", 640);
7630
+ break;
7631
+ case "recording":
7632
+ tone(587, 0, 0.14);
7633
+ tone(587, 0.18, 0.14);
7634
+ tone(880, 0.36, 0.32, 0.06);
7635
+ break;
7636
+ case "error":
7637
+ tone(392, 0, 0.16, 0.05, "triangle");
7638
+ tone(311, 0.13, 0.24, 0.05, "triangle");
7639
+ break;
7640
+ case "reaction":
7641
+ tone(880, 0, 0.12, 0.035, "triangle");
7642
+ break;
7643
+ }
7644
+ } catch {
7669
7645
  }
7670
7646
  },
7671
7647
  dispose() {
@@ -7674,7 +7650,7 @@ function createSoundPlayer({ outputDeviceId } = {}) {
7674
7650
  window.removeEventListener("click", unlock, true);
7675
7651
  window.removeEventListener("keydown", unlock, true);
7676
7652
  }
7677
- if (context) void context.close();
7653
+ if (context) void Promise.resolve(context.close()).catch(() => void 0);
7678
7654
  }
7679
7655
  };
7680
7656
  }
@@ -7705,9 +7681,21 @@ function useSoundCues(enabled, createPlayer = createSoundPlayer) {
7705
7681
  const player = createPlayerRef.current({ outputDeviceId });
7706
7682
  playerRef.current = player;
7707
7683
  let previous = client.getSnapshot();
7684
+ const seenParticipants = new Set(previous.participants.roster.map((participant) => participant.participantId));
7685
+ let lastJoinAt = -Infinity;
7708
7686
  const unsubscribe = client.subscribe(() => {
7709
7687
  const next = client.getSnapshot();
7710
- if (enabledRef.current) for (const cue of diffSoundCues(previous, next)) player.play(cue);
7688
+ const hasNewParticipant = next.participants.roster.some((participant) => participant.participantId !== next.self.participantId && !seenParticipants.has(participant.participantId));
7689
+ if (enabledRef.current)
7690
+ for (const cue of diffSoundCues(previous, next)) {
7691
+ if (cue === "join") {
7692
+ const now = performance.now();
7693
+ if (!hasNewParticipant || now - lastJoinAt < 3e3) continue;
7694
+ lastJoinAt = now;
7695
+ }
7696
+ player.play(cue);
7697
+ }
7698
+ for (const participant of next.participants.roster) seenParticipants.add(participant.participantId);
7711
7699
  previous = next;
7712
7700
  });
7713
7701
  const offError = client.on("error", ({ error }) => playFailure(error));
@@ -7731,14 +7719,14 @@ function useSoundCues(enabled, createPlayer = createSoundPlayer) {
7731
7719
  }
7732
7720
 
7733
7721
  // src/components/composite/ReactionPicker.tsx
7734
- import React21, { useMemo as useMemo14, useState as useState37, useCallback as useCallback10, useEffect as useEffect29, useRef as useRef27 } from "react";
7722
+ import React21, { useMemo as useMemo14, useState as useState36, useCallback as useCallback10, useEffect as useEffect29, useRef as useRef27 } from "react";
7735
7723
  import { DEFAULT_QUICK_REACTIONS, EMOJI_CATEGORIES, EMOJI_KEYWORDS } from "@q9labsai/chalk-ui/reactions";
7736
7724
 
7737
7725
  // src/components/composite/ReactionTray.tsx
7738
- import { useCallback as useCallback9, useEffect as useEffect28, useLayoutEffect as useLayoutEffect6, useRef as useRef26, useState as useState36 } from "react";
7726
+ import { useCallback as useCallback9, useEffect as useEffect28, useLayoutEffect as useLayoutEffect6, useRef as useRef26, useState as useState35 } from "react";
7739
7727
  import { Fragment as Fragment27, jsx as jsx61, jsxs as jsxs39 } from "react/jsx-runtime";
7740
7728
  function ReactionTray({ isHandRaised, onToggleHandRaise, reactions, onSelect, onClose, position = "top", className }) {
7741
- const [more, setMore] = useState36(false);
7729
+ const [more, setMore] = useState35(false);
7742
7730
  const returnFocus = useRef26(null);
7743
7731
  const prefersReducedMotion = usePrefersReducedMotion();
7744
7732
  const { trigger } = useHaptics();
@@ -7823,8 +7811,8 @@ import { Fragment as Fragment28, jsx as jsx62, jsxs as jsxs40 } from "react/jsx-
7823
7811
  var ReactionPicker = React21.memo(({ isHandRaised, onToggleHandRaise, isOpen, onClose, onSelect, recentReactions = [], allowedReactions, position = "top", participantColorSeed, participantGradientPreference, className, size = "default" }) => {
7824
7812
  const prefersReducedMotion = usePrefersReducedMotion();
7825
7813
  const { trigger } = useHaptics();
7826
- const [activeCategory, setActiveCategory] = useState37("smileys");
7827
- const [searchQuery, setSearchQuery] = useState37("");
7814
+ const [activeCategory, setActiveCategory] = useState36("smileys");
7815
+ const [searchQuery, setSearchQuery] = useState36("");
7828
7816
  const inputRef = useRef27(null);
7829
7817
  const themeVariables = useMemo14(() => getParticipantThemeVariables(participantColorSeed, participantGradientPreference), [participantColorSeed, participantGradientPreference]);
7830
7818
  useEffect29(() => {
@@ -7981,7 +7969,7 @@ var ReactionPicker = React21.memo(({ isHandRaised, onToggleHandRaise, isOpen, on
7981
7969
  ReactionPicker.displayName = "ReactionPicker";
7982
7970
 
7983
7971
  // src/components/offline-actions/OfflineActions.tsx
7984
- import { useEffect as useEffect30, useState as useState38, useSyncExternalStore as useSyncExternalStore4 } from "react";
7972
+ import { useEffect as useEffect30, useState as useState37, useSyncExternalStore as useSyncExternalStore4 } from "react";
7985
7973
  import { jsx as jsx63 } from "react/jsx-runtime";
7986
7974
  var RECONNECTING_GRACE_MS = 2e3;
7987
7975
  function offlineNoticeText(pendingCount, online) {
@@ -8009,7 +7997,7 @@ function OfflineActions({ reconnecting: requestedReconnecting = false, hasNotice
8009
7997
  return null;
8010
7998
  }
8011
7999
  function useTrueFor(value, milliseconds) {
8012
- const [elapsed, setElapsed] = useState38(false);
8000
+ const [elapsed, setElapsed] = useState37(false);
8013
8001
  useEffect30(() => {
8014
8002
  setElapsed(false);
8015
8003
  if (!value) return;
@@ -8031,12 +8019,12 @@ function readOnline() {
8031
8019
  }
8032
8020
 
8033
8021
  // src/components/reconnecting-overlay/ReconnectingOverlay.tsx
8034
- import { memo as memo3, useEffect as useEffect31, useState as useState39 } from "react";
8022
+ import { memo as memo3, useEffect as useEffect31, useState as useState38 } from "react";
8035
8023
  import { jsx as jsx64 } from "react/jsx-runtime";
8036
8024
  var RECONNECTING_NOTICE_MS = 2e3;
8037
8025
  var ReconnectingOverlay = memo3(function ReconnectingOverlay2({ isVisible, status, onRetry, onLeft, message, showNotice }) {
8038
8026
  const reconnecting = isVisible && status === "reconnecting";
8039
- const [elapsed, setElapsed] = useState39(false);
8027
+ const [elapsed, setElapsed] = useState38(false);
8040
8028
  useEffect31(() => {
8041
8029
  setElapsed(false);
8042
8030
  if (!reconnecting) return;
@@ -8051,7 +8039,7 @@ var ReconnectingOverlay = memo3(function ReconnectingOverlay2({ isVisible, statu
8051
8039
  });
8052
8040
 
8053
8041
  // src/components/toast-stack/useCallToasts.ts
8054
- import { useCallback as useCallback11, useEffect as useEffect32, useRef as useRef28, useState as useState40 } from "react";
8042
+ import { useCallback as useCallback11, useEffect as useEffect32, useRef as useRef28, useState as useState39 } from "react";
8055
8043
 
8056
8044
  // src/components/toast-stack/call-events.tsx
8057
8045
  import { Fragment as Fragment29, jsx as jsx65, jsxs as jsxs41 } from "react/jsx-runtime";
@@ -8148,7 +8136,7 @@ function callEventToasts(previous, next) {
8148
8136
  // src/components/toast-stack/useCallToasts.ts
8149
8137
  function useCallToasts() {
8150
8138
  const client = useSpaceClient();
8151
- const [toasts, setToasts] = useState40([]);
8139
+ const [toasts, setToasts] = useState39([]);
8152
8140
  const sequence = useRef28(0);
8153
8141
  useEffect32(() => {
8154
8142
  setToasts([]);
@@ -8189,9 +8177,9 @@ function useCallToasts() {
8189
8177
  }
8190
8178
 
8191
8179
  // src/components/call-limbo/useCallLink.ts
8192
- import { useEffect as useEffect33, useState as useState41 } from "react";
8180
+ import { useEffect as useEffect33, useState as useState40 } from "react";
8193
8181
  function useCallLink(alone) {
8194
- const [open, setOpen] = useState41(alone);
8182
+ const [open, setOpen] = useState40(alone);
8195
8183
  useEffect33(() => {
8196
8184
  if (!alone) setOpen(false);
8197
8185
  }, [alone]);
@@ -8199,10 +8187,10 @@ function useCallLink(alone) {
8199
8187
  }
8200
8188
 
8201
8189
  // src/components/toast-stack/NoticeButton.tsx
8202
- import { useState as useState42 } from "react";
8190
+ import { useState as useState41 } from "react";
8203
8191
  import { jsx as jsx66, jsxs as jsxs42 } from "react/jsx-runtime";
8204
8192
  function NoticeButton({ toasts, onDismiss }) {
8205
- const [open, setOpen] = useState42(false);
8193
+ const [open, setOpen] = useState41(false);
8206
8194
  if (toasts.length === 0) return null;
8207
8195
  const label = toasts.length === 1 ? "1 notice" : `${toasts.length} notices`;
8208
8196
  const trigger = /* @__PURE__ */ jsxs42("button", { type: "button", "data-part": "notice-button", className: "chalk-notice-button", "aria-label": `Show ${label}`, children: [
@@ -8224,7 +8212,7 @@ function NoticeButton({ toasts, onDismiss }) {
8224
8212
  import { BoardToastContext as BoardToastContext2 } from "@q9labsai/chalk-whiteboard/react";
8225
8213
 
8226
8214
  // src/components/stage/SpaceStage.tsx
8227
- import { useCallback as useCallback13, useEffect as useEffect34, useMemo as useMemo17, useState as useState43 } from "react";
8215
+ import { useCallback as useCallback13, useEffect as useEffect34, useMemo as useMemo17, useState as useState42 } from "react";
8228
8216
 
8229
8217
  // src/components/board/Board.tsx
8230
8218
  import { useContext as useContext3, useMemo as useMemo16 } from "react";
@@ -8294,31 +8282,43 @@ function Board(props) {
8294
8282
 
8295
8283
  // src/components/stage/SpaceStage.tsx
8296
8284
  import { jsx as jsx68 } from "react/jsx-runtime";
8297
- function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, whiteboard, onOverflowClick, shareCapture, onStopSharing, onChangeShare, colorScheme = "dark", onCloseBoard, className }) {
8285
+ function SpaceStage({ pinnedId, onPinnedChange, tiles, layout, onLayoutChange, generatedAvatars = true, whiteboard, onOverflowClick, shareCapture, onStopSharing, onChangeShare, colorScheme = "dark", onCloseBoard, className }) {
8298
8286
  const items = useMemo17(() => buildStageItems(tiles, whiteboard?.isOpen === true), [tiles, whiteboard?.isOpen]);
8299
- const [selectedShare, setSelectedShare] = useState43(null);
8300
- const [pin, setPin] = useState43(null);
8301
- const [following, setFollowing] = useState43(null);
8287
+ const [selectedShare, setSelectedShare] = useState42(null);
8288
+ const [localPin, setLocalPin] = useState42(null);
8289
+ const pin = pinnedId === void 0 ? localPin : pinnedId;
8290
+ const setPin = useCallback13(
8291
+ (id) => {
8292
+ setLocalPin(id);
8293
+ onPinnedChange?.(id);
8294
+ },
8295
+ [onPinnedChange]
8296
+ );
8297
+ const [following, setFollowing] = useState42(void 0);
8302
8298
  const boardOpen = whiteboard?.isOpen === true && Boolean(whiteboard.props);
8303
8299
  useEffect34(() => {
8304
- if (!boardOpen) setFollowing(null);
8300
+ if (!boardOpen) setFollowing(void 0);
8305
8301
  }, [boardOpen]);
8306
8302
  const canFollow = boardOpen && Boolean(whiteboard?.sendView);
8307
- const followed = canFollow && tiles.some((tile) => tile.id === following) ? following : null;
8303
+ const target = following === void 0 ? whiteboard?.presenterId : following;
8304
+ const followed = canFollow && tiles.some((tile) => tile.id === target && !tile.isLocal) ? target ?? null : null;
8308
8305
  const activePin = items.some((item) => item.id === pin) ? pin : null;
8309
8306
  const shares = items.filter((item) => item.kind === "screen-share");
8310
8307
  const activeShare = selectedShare && shares.some((item) => item.id === selectedShare) ? selectedShare : null;
8311
8308
  useEffect34(() => {
8312
8309
  if (pin !== activePin) setPin(activePin);
8313
8310
  if (selectedShare !== activeShare) setSelectedShare(activeShare);
8314
- }, [pin, activePin, selectedShare, activeShare]);
8315
- const follow = useCallback13((id) => {
8316
- if (id) {
8317
- setPin(null);
8318
- setSelectedShare(null);
8319
- }
8320
- setFollowing(id);
8321
- }, []);
8311
+ }, [pin, activePin, selectedShare, activeShare, setPin]);
8312
+ const follow = useCallback13(
8313
+ (id) => {
8314
+ if (id) {
8315
+ setPin(null);
8316
+ setSelectedShare(null);
8317
+ }
8318
+ setFollowing(id);
8319
+ },
8320
+ [setPin]
8321
+ );
8322
8322
  const renderContentTile = useCallback13(
8323
8323
  (item, context) => {
8324
8324
  if (item.kind === "screen-share")
@@ -8369,15 +8369,14 @@ function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, wh
8369
8369
  Stage,
8370
8370
  {
8371
8371
  items,
8372
- layout,
8372
+ layout: activePin ? "focus" : layout,
8373
8373
  pinnedId: activePin ?? activeShare ?? (followed ? "whiteboard" : null),
8374
8374
  onPinnedChange: setPin,
8375
- onFollowChange: (id) => follow(followed === id ? null : id),
8375
+ onFollowChange: canFollow ? (id) => follow(followed === id ? null : id) : void 0,
8376
8376
  followingId: followed,
8377
- clickAction: canFollow ? "follow" : "pin",
8378
8377
  renderContentTile,
8379
8378
  onItemClick: focusContent,
8380
- onOverflowClick: canFollow ? void 0 : onOverflowClick,
8379
+ onOverflowClick,
8381
8380
  generatedAvatars,
8382
8381
  emptyState: /* @__PURE__ */ jsx68(QuietSpace, {}),
8383
8382
  className
@@ -8387,11 +8386,11 @@ function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, wh
8387
8386
  SpaceStage.displayName = "SpaceStage";
8388
8387
 
8389
8388
  // src/components/space-view/useDrawerPresence.ts
8390
- import { useEffect as useEffect35, useState as useState44 } from "react";
8389
+ import { useEffect as useEffect35, useState as useState43 } from "react";
8391
8390
  var DRAWER_EXIT_MS = 200;
8392
8391
  function useDrawerPresence(panel, exitMs) {
8393
- const [retained, setRetained] = useState44(panel);
8394
- const [state, setState] = useState44(panel === null ? "closed" : "open");
8392
+ const [retained, setRetained] = useState43(panel);
8393
+ const [state, setState] = useState43(panel === null ? "closed" : "open");
8395
8394
  useEffect35(() => {
8396
8395
  if (panel !== null) {
8397
8396
  setRetained(panel);
@@ -8441,6 +8440,7 @@ function SpaceView({
8441
8440
  onEndEpisode,
8442
8441
  className
8443
8442
  }) {
8443
+ const phone = useIsMobile();
8444
8444
  const effectiveShareUrl = inviteLink ?? shareUrl;
8445
8445
  const callToasts = useCallToasts();
8446
8446
  const [soundsEnabled] = useSoundsSetting();
@@ -8451,7 +8451,7 @@ function SpaceView({
8451
8451
  const media = useMedia();
8452
8452
  const connection = useConnection();
8453
8453
  const offline = useOffline();
8454
- const [dismissedOfflineNotice, setDismissedOfflineNotice] = useState45(null);
8454
+ const [dismissedOfflineNotice, setDismissedOfflineNotice] = useState44(null);
8455
8455
  const offlineNotice = offline.notice && offline.notice !== dismissedOfflineNotice ? offline.notice : null;
8456
8456
  const recording = useRecording();
8457
8457
  const canPublishScreen = useCan("publishScreen");
@@ -8462,9 +8462,9 @@ function SpaceView({
8462
8462
  const canManageRecording = useCan("manageRecording");
8463
8463
  const episodeDuration = useEpisodeDuration();
8464
8464
  const deadline = connection.episode?.deadline;
8465
- const [now, setNow] = useState45(Date.now);
8465
+ const [now, setNow] = useState44(Date.now);
8466
8466
  const previousCountdown = useRef29(null);
8467
- const [limitWarning, setLimitWarning] = useState45(null);
8467
+ const [limitWarning, setLimitWarning] = useState44(null);
8468
8468
  const countdown = callCountdown(deadline, now);
8469
8469
  useEffect36(() => {
8470
8470
  if (!deadline) return;
@@ -8480,13 +8480,14 @@ function SpaceView({
8480
8480
  if (previous?.deadline !== deadline) setLimitWarning(null);
8481
8481
  if (next.warning !== null) setLimitWarning({ id: `time-limit-${deadline}-${next.warning}`, minutes: next.warning });
8482
8482
  }, [deadline, now]);
8483
- const [uncontrolledLayout, setUncontrolledLayout] = useState45(controlledLayout ?? "focus");
8484
- const [activePanel, setActivePanel] = useState45(initialPanel);
8485
- const [isReactionPickerOpen, setReactionPickerOpen] = useState45(false);
8486
- const [commandError, setCommandError] = useState45(null);
8487
- const [commandSource, setCommandSource] = useState45();
8488
- const [commandAction, setCommandAction] = useState45();
8489
- const [retryCommand, setRetryCommand] = useState45();
8483
+ const [uncontrolledLayout, setUncontrolledLayout] = useState44(controlledLayout ?? "focus");
8484
+ const [pinnedId, setPinnedId] = useState44(null);
8485
+ const [activePanel, setActivePanel] = useState44(initialPanel);
8486
+ const [isReactionPickerOpen, setReactionPickerOpen] = useState44(false);
8487
+ const [commandError, setCommandError] = useState44(null);
8488
+ const [commandSource, setCommandSource] = useState44();
8489
+ const [commandAction, setCommandAction] = useState44();
8490
+ const [retryCommand, setRetryCommand] = useState44();
8490
8491
  const onCommandError = (failure, source, mediaSource, action, command) => {
8491
8492
  if (!failure && commandError && typeof commandError === "object") callToasts.dismissFailure(commandError.code);
8492
8493
  setCommandError(failure);
@@ -8521,7 +8522,9 @@ function SpaceView({
8521
8522
  ...feature("whiteboard") && canDrawWhiteboard ? ["whiteboard"] : [],
8522
8523
  "leave"
8523
8524
  ];
8525
+ const headerLayout = pinnedId ? "focus" : layout;
8524
8526
  const updateLayout = (nextLayout) => {
8527
+ if (nextLayout === "grid") setPinnedId(null);
8525
8528
  setUncontrolledLayout(nextLayout);
8526
8529
  onLayoutChange?.(nextLayout);
8527
8530
  };
@@ -8557,7 +8560,7 @@ function SpaceView({
8557
8560
  };
8558
8561
  const mappedFailure = mediaFailureToast(typeof displayedCommandError === "object" ? displayedCommandError : null, displayedCommandSource, externalCommandError != null ? externalCommandAction : commandAction, externalCommandError == null && retryCommand ? () => void retryMedia() : void 0);
8559
8562
  const commandToasts = mappedFailure ? [{ id: "space-command-error", ...mappedFailure }] : typeof displayedCommandError === "string" ? [{ id: "space-command-error", message: displayedCommandError, type: "error" }] : [];
8560
- const [boardToasts, setBoardToasts] = useState45([]);
8563
+ const [boardToasts, setBoardToasts] = useState44([]);
8561
8564
  const boardToastCount = useRef29(0);
8562
8565
  useEffect36(() => {
8563
8566
  if (!whiteboard?.isOpen) setBoardToasts([]);
@@ -8591,7 +8594,7 @@ function SpaceView({
8591
8594
  else if (id.startsWith("board-")) setBoardToasts((current) => current.filter((toast) => toast.id !== id));
8592
8595
  else callToasts.dismiss(id);
8593
8596
  };
8594
- const [foldedNotices, setFoldedNotices] = useState45([]);
8597
+ const [foldedNotices, setFoldedNotices] = useState44([]);
8595
8598
  const folded = toasts.filter((toast) => foldedNotices.includes(toast.id));
8596
8599
  return /* @__PURE__ */ jsx69(ParticipantVolumeProvider, { children: /* @__PURE__ */ jsx69(BoardToastContext2.Provider, { value: showBoardToast, children: /* @__PURE__ */ jsx69(
8597
8600
  SpacePresentation,
@@ -8619,7 +8622,7 @@ function SpaceView({
8619
8622
  onToggleHand: feature("handRaise") && canRaiseHand ? () => void runCommand(() => self.handRaised ? client.participants.lowerHand() : client.participants.raiseHand()) : void 0,
8620
8623
  onToggleChat: feature("chat") ? () => setActivePanel((current) => current === "chat" ? null : "chat") : void 0,
8621
8624
  onTogglePeople: feature("participants") ? () => setActivePanel((current) => current === "participants" ? null : "participants") : void 0,
8622
- onToggleLayout: () => updateLayout(layout === "grid" ? "focus" : "grid"),
8625
+ onToggleLayout: () => updateLayout(headerLayout === "grid" ? "focus" : "grid"),
8623
8626
  onClosePanel: () => setActivePanel(null),
8624
8627
  onPushToTalk: (enabled) => {
8625
8628
  if (enabled && connection.status !== "live") return;
@@ -8629,13 +8632,15 @@ function SpaceView({
8629
8632
  duration: episodeDuration,
8630
8633
  timeLeft: countdown.seconds,
8631
8634
  isRecording: recording.current?.status === "recording",
8632
- layout,
8635
+ layout: headerLayout,
8633
8636
  onLayoutChange: updateLayout,
8634
8637
  notices: folded.length ? /* @__PURE__ */ jsx69(NoticeButton, { toasts: folded, onDismiss: dismissToast }) : void 0
8635
8638
  },
8636
8639
  stage: /* @__PURE__ */ jsx69(
8637
8640
  SpaceStage,
8638
8641
  {
8642
+ pinnedId,
8643
+ onPinnedChange: setPinnedId,
8639
8644
  tiles,
8640
8645
  layout,
8641
8646
  onLayoutChange: updateLayout,
@@ -8691,7 +8696,20 @@ function SpaceView({
8691
8696
  ] }),
8692
8697
  sidebar: /* @__PURE__ */ jsxs43(CallCard, { state: drawer.state, panel: drawer.panel, onPanelChange: setActivePanel, peopleCount: participantsSlice.roster.length, participantsEnabled: feature("participants"), chatEnabled: feature("chat"), onClose: () => setActivePanel(null), children: [
8693
8698
  drawer.panel === "chat" && feature("chat") ? /* @__PURE__ */ jsx69(ChatPanel, { variant: "mobile", generatedAvatars, onClose: () => setActivePanel(null), pickChatFiles }) : null,
8694
- drawer.panel === "participants" && feature("participants") ? /* @__PURE__ */ jsx69(ParticipantsPanel, { variant: "mobile", admissionEnabled: feature("admission"), generatedAvatars, onCommandError, onClose: () => setActivePanel(null) }) : null,
8699
+ drawer.panel === "participants" && feature("participants") ? /* @__PURE__ */ jsx69(
8700
+ ParticipantsPanel,
8701
+ {
8702
+ onParticipantClick: (id) => {
8703
+ setPinnedId((current) => current === id ? null : id);
8704
+ if (phone) setActivePanel(null);
8705
+ },
8706
+ variant: "mobile",
8707
+ admissionEnabled: feature("admission"),
8708
+ generatedAvatars,
8709
+ onCommandError,
8710
+ onClose: () => setActivePanel(null)
8711
+ }
8712
+ ) : null,
8695
8713
  drawer.panel === "admission" && feature("admission") ? /* @__PURE__ */ jsx69(AdmissionPanel, { className: "h-full w-full rounded-none shadow-none", onClose: () => setActivePanel(null) }) : null
8696
8714
  ] }),
8697
8715
  toasts: /* @__PURE__ */ jsx69(ToastStack, { toasts, onDismiss: dismissToast, onFold: setFoldedNotices }),