@q9labsai/chalk-react 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +102 -0
- package/dist/bindings/hooks.d.ts +2 -0
- package/dist/{chunk-QDEKMRH2.js → chunk-CYC2G42K.js} +66 -58
- package/dist/{chunk-XOHNIYSR.js → chunk-G62BKRNX.js} +1534 -948
- package/dist/{chunk-ZFWIMKUC.js → chunk-HWQLW4JR.js} +55 -7
- package/dist/components/board/BoardMenu.d.ts +4 -1
- package/dist/components/board/board-draw-policy.d.ts +15 -0
- package/dist/components/board/board-model.d.ts +5 -1
- package/dist/components/board/board-view-versions.d.ts +1 -7
- package/dist/components/chalk/Chalk.d.ts +4 -0
- package/dist/components/chalk/ReportProblemDialog.d.ts +12 -0
- package/dist/components/chalk/StatusSurface.d.ts +3 -2
- package/dist/components/chalk-ui/ChalkSheet.d.ts +1 -1
- package/dist/components/chalk-ui/ChalkToast.d.ts +7 -1
- package/dist/components/control-bar/command-failure.d.ts +105 -1
- package/dist/components/control-bar/control-bar-behavior.d.ts +5 -1
- package/dist/components/index.js +3 -3
- package/dist/components/offline-actions/OfflineActions.d.ts +2 -1
- package/dist/components/space-header/CallDetails.d.ts +4 -2
- package/dist/components/space-header/space-header-contract.d.ts +5 -0
- package/dist/components/space-view/SpaceView.d.ts +8 -3
- package/dist/components/stage/Stage.d.ts +1 -1
- package/dist/components/stage/stage-items.d.ts +4 -0
- package/dist/components/stage/stage-layout.d.ts +6 -2
- package/dist/components/toast-stack/CallEventIcon.d.ts +1 -1
- package/dist/components/toast-stack/NoticeButton.d.ts +7 -0
- package/dist/components/toast-stack/ToastStack.d.ts +13 -2
- package/dist/components/toast-stack/call-events.d.ts +2 -1
- package/dist/components/toast-stack/notice-announcement.d.ts +4 -0
- package/dist/components/toast-stack/toast-layout-snapshot.d.ts +4 -0
- package/dist/components/toast-stack/useToastCapacity.d.ts +7 -0
- package/dist/headless.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +24 -3
- package/dist/internal/whiteboard-view-limits.d.ts +1 -0
- package/dist/public-surface.contract.d.ts +1 -1
- package/dist/test-support/index.js +3 -3
- package/package.json +5 -5
|
@@ -3,14 +3,17 @@ import {
|
|
|
3
3
|
DEFAULT_SPOTLIGHT_OPTIONS,
|
|
4
4
|
EMPTY_GEOMETRY,
|
|
5
5
|
MORE_TILE_ID,
|
|
6
|
+
WHITEBOARD_ITEM_ID,
|
|
6
7
|
buildStageItems,
|
|
7
8
|
choosePrimary,
|
|
8
9
|
fitGrid,
|
|
9
10
|
fitSpotlight,
|
|
11
|
+
floatingSpeakerId,
|
|
10
12
|
gridOrder,
|
|
11
13
|
isContentItem,
|
|
14
|
+
speakingParticipantId,
|
|
12
15
|
stabilizeOrder
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-HWQLW4JR.js";
|
|
14
17
|
import {
|
|
15
18
|
ArrowLeft01Icon,
|
|
16
19
|
ArrowRight01Icon,
|
|
@@ -102,6 +105,13 @@ function useWhiteboard() {
|
|
|
102
105
|
function useCan(capability) {
|
|
103
106
|
return useSelf().can(capability);
|
|
104
107
|
}
|
|
108
|
+
function useCanDrawWhiteboard() {
|
|
109
|
+
const whiteboard = useWhiteboard();
|
|
110
|
+
const roleDefault = useCan("drawWhiteboard");
|
|
111
|
+
if (whiteboard.engine.status === "unsubscribed") return roleDefault;
|
|
112
|
+
if (whiteboard.access.policy === null) return roleDefault && whiteboard.access.canDraw;
|
|
113
|
+
return whiteboard.access.canDraw;
|
|
114
|
+
}
|
|
105
115
|
function useScreenShare() {
|
|
106
116
|
const client = useSpaceClient();
|
|
107
117
|
const { screenShare } = useMedia();
|
|
@@ -385,7 +395,7 @@ function ChalkTooltip({ trigger, children }) {
|
|
|
385
395
|
|
|
386
396
|
// src/components/chalk-ui/ChalkPopover.tsx
|
|
387
397
|
import { Popover } from "@base-ui/react/popover";
|
|
388
|
-
import {
|
|
398
|
+
import { useState as useState3 } from "react";
|
|
389
399
|
import { jsx as jsx17, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
390
400
|
function ChalkPopover({
|
|
391
401
|
trigger,
|
|
@@ -397,20 +407,12 @@ function ChalkPopover({
|
|
|
397
407
|
open,
|
|
398
408
|
onOpenChange
|
|
399
409
|
}) {
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
{
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
},
|
|
407
|
-
style: { display: "contents" },
|
|
408
|
-
children: /* @__PURE__ */ jsxs5(Popover.Root, { open, onOpenChange, children: [
|
|
409
|
-
tooltip ? /* @__PURE__ */ jsx17(ChalkTooltip, { trigger: /* @__PURE__ */ jsx17(Popover.Trigger, { render: trigger }), children: tooltip }) : /* @__PURE__ */ jsx17(Popover.Trigger, { render: trigger }),
|
|
410
|
-
/* @__PURE__ */ jsx17(Popover.Portal, { container, children: /* @__PURE__ */ jsx17(Popover.Positioner, { side: "bottom", align: "start", alignOffset, sideOffset: 8, collisionPadding: 8, className: "chalk-popover-positioner", children: /* @__PURE__ */ jsx17(Popover.Popup, { "aria-label": label, "data-part": "popover", className: cn("chalk-menu chalk-popover", className), children }) }) })
|
|
411
|
-
] })
|
|
412
|
-
}
|
|
413
|
-
);
|
|
410
|
+
const [holder, setHolder] = useState3(null);
|
|
411
|
+
const root = holder?.closest("[data-chalk]") ?? null;
|
|
412
|
+
return /* @__PURE__ */ jsx17("span", { ref: setHolder, style: { display: "contents" }, children: /* @__PURE__ */ jsxs5(Popover.Root, { open, onOpenChange, children: [
|
|
413
|
+
tooltip ? /* @__PURE__ */ jsx17(ChalkTooltip, { trigger: /* @__PURE__ */ jsx17(Popover.Trigger, { render: trigger }), children: tooltip }) : /* @__PURE__ */ jsx17(Popover.Trigger, { render: trigger }),
|
|
414
|
+
/* @__PURE__ */ jsx17(Popover.Portal, { container: root ?? holder, children: /* @__PURE__ */ jsx17(Popover.Positioner, { side: "bottom", align: "start", alignOffset, sideOffset: 8, collisionPadding: 8, collisionBoundary: root ?? void 0, className: "chalk-popover-positioner", children: /* @__PURE__ */ jsx17(Popover.Popup, { "aria-label": label, "data-part": "popover", className: cn("chalk-menu chalk-popover", className), children }) }) })
|
|
415
|
+
] }) });
|
|
414
416
|
}
|
|
415
417
|
|
|
416
418
|
// src/components/chalk-ui/ChalkSegmentedControl.tsx
|
|
@@ -437,12 +439,12 @@ function ChalkSegmentedControl({
|
|
|
437
439
|
}
|
|
438
440
|
|
|
439
441
|
// src/components/chalk-ui/ChalkCopyButton.tsx
|
|
440
|
-
import { useEffect as useEffect2, useRef as
|
|
442
|
+
import { useEffect as useEffect2, useRef as useRef3, useState as useState4 } from "react";
|
|
441
443
|
import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
442
444
|
function ChalkCopyButton({ text, label = "Copy link", announcement = "Link copied", showLabel = false }) {
|
|
443
|
-
const [copied, setCopied] =
|
|
444
|
-
const [error, setError] =
|
|
445
|
-
const timer =
|
|
445
|
+
const [copied, setCopied] = useState4(false);
|
|
446
|
+
const [error, setError] = useState4(false);
|
|
447
|
+
const timer = useRef3(void 0);
|
|
446
448
|
useEffect2(() => () => clearTimeout(timer.current), []);
|
|
447
449
|
const copy = async () => {
|
|
448
450
|
try {
|
|
@@ -472,10 +474,10 @@ function ChalkCopyButton({ text, label = "Copy link", announcement = "Link copie
|
|
|
472
474
|
|
|
473
475
|
// src/components/chalk-ui/ChalkSheet.tsx
|
|
474
476
|
import { Dialog } from "@base-ui/react/dialog";
|
|
475
|
-
import { useCallback as useCallback2, useState as
|
|
477
|
+
import { useCallback as useCallback2, useState as useState5 } from "react";
|
|
476
478
|
import { jsx as jsx20, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
477
479
|
function ChalkSheet({ open, onOpenChange, title, accessibleLabel, children, variant = "default" }) {
|
|
478
|
-
const [container, setContainer] =
|
|
480
|
+
const [container, setContainer] = useState5(null);
|
|
479
481
|
const attach = useCallback2((element) => setContainer(element?.closest("[data-chalk]") ?? element), []);
|
|
480
482
|
return /* @__PURE__ */ jsx20("span", { ref: attach, style: { display: "contents" }, children: /* @__PURE__ */ jsx20(Dialog.Root, { open, onOpenChange, children: container ? /* @__PURE__ */ jsxs7(Dialog.Portal, { container, children: [
|
|
481
483
|
/* @__PURE__ */ jsx20(Dialog.Backdrop, { "data-part": "sheet-scrim", className: "chalk-sheet-scrim" }),
|
|
@@ -503,32 +505,53 @@ function ChalkSheet({ open, onOpenChange, title, accessibleLabel, children, vari
|
|
|
503
505
|
}
|
|
504
506
|
|
|
505
507
|
// src/components/chalk-ui/ChalkToast.tsx
|
|
506
|
-
import { useEffect as useEffect3, useRef as
|
|
508
|
+
import { useEffect as useEffect3, useRef as useRef4, useState as useState6 } from "react";
|
|
509
|
+
|
|
510
|
+
// src/components/toast-stack/notice-announcement.ts
|
|
511
|
+
import { Children, Fragment as Fragment4, isValidElement } from "react";
|
|
512
|
+
function literalText(node) {
|
|
513
|
+
if (typeof node === "string" || typeof node === "number" || typeof node === "bigint") return String(node);
|
|
514
|
+
if (node == null || typeof node === "boolean") return "";
|
|
515
|
+
if (isValidElement(node)) return typeof node.type === "string" || node.type === Fragment4 ? literalText(node.props.children) : "";
|
|
516
|
+
if (typeof node === "object" && "then" in node) return "";
|
|
517
|
+
return typeof node === "object" && Symbol.iterator in node ? Children.toArray(node).map(literalText).join("") : "";
|
|
518
|
+
}
|
|
519
|
+
function noticeAnnouncement(toast) {
|
|
520
|
+
return toast.announcementText ?? literalText(toast.message);
|
|
521
|
+
}
|
|
522
|
+
function noticeIdentity(toast) {
|
|
523
|
+
return JSON.stringify([noticeAnnouncement(toast), toast.announcementKey, toast.type ?? "info"]);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// src/components/chalk-ui/ChalkToast.tsx
|
|
507
527
|
import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
508
|
-
function ChalkToast({ message, type = "info", duration = type === "info" ? 5e3 : Infinity, action, icon, onDismiss }) {
|
|
509
|
-
const dismissRef =
|
|
528
|
+
function ChalkToast({ message, announcementKey, announcementText, type = "info", duration = type === "info" ? 5e3 : Infinity, action, icon, announce = true, onDismiss }) {
|
|
529
|
+
const dismissRef = useRef4(onDismiss);
|
|
510
530
|
dismissRef.current = onDismiss;
|
|
511
|
-
const
|
|
531
|
+
const identity = noticeIdentity({ message, announcementText, announcementKey, type });
|
|
532
|
+
const [lifetime, setLifetime] = useState6({ identity, exiting: false });
|
|
533
|
+
if (lifetime.identity !== identity) setLifetime({ identity, exiting: false });
|
|
534
|
+
const exiting = lifetime.identity === identity && lifetime.exiting;
|
|
512
535
|
useEffect3(() => {
|
|
513
536
|
if (duration === Infinity) return;
|
|
514
|
-
const timer = setTimeout(() =>
|
|
537
|
+
const timer = setTimeout(() => setLifetime({ identity, exiting: true }), duration);
|
|
515
538
|
return () => clearTimeout(timer);
|
|
516
|
-
}, [duration]);
|
|
539
|
+
}, [duration, identity]);
|
|
517
540
|
useEffect3(() => {
|
|
518
541
|
if (!exiting) return;
|
|
519
542
|
const timer = setTimeout(() => dismissRef.current(), 160);
|
|
520
543
|
return () => clearTimeout(timer);
|
|
521
|
-
}, [exiting]);
|
|
522
|
-
return /* @__PURE__ */ jsxs8("div", { "data-part": "toast", "data-exiting": exiting || void 0, className: "chalk-toast",
|
|
544
|
+
}, [exiting, identity]);
|
|
545
|
+
return /* @__PURE__ */ jsxs8("div", { "data-part": "toast", "data-type": type, "data-exiting": exiting || void 0, className: "chalk-toast", role: announce ? type === "error" ? "alert" : "status" : void 0, "aria-live": announce ? type === "error" ? "assertive" : "polite" : void 0, "aria-atomic": announce || void 0, children: [
|
|
523
546
|
icon,
|
|
524
|
-
/* @__PURE__ */ jsx21("span", {
|
|
547
|
+
/* @__PURE__ */ jsx21("span", { children: message }),
|
|
525
548
|
action ? /* @__PURE__ */ jsx21(ChalkButton, { onClick: action.onClick, children: action.label }) : null,
|
|
526
|
-
type === "error" ? /* @__PURE__ */ jsx21("button", { type: "button", "data-part": "toast-dismiss", className: "chalk-dismiss", "aria-label": "Dismiss", onClick: () =>
|
|
549
|
+
type === "error" ? /* @__PURE__ */ jsx21("button", { type: "button", "data-part": "toast-dismiss", className: "chalk-dismiss", "aria-label": "Dismiss", onClick: () => setLifetime({ identity, exiting: true }), children: /* @__PURE__ */ jsx21("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx21("path", { d: "m6 6 12 12M6 18 18 6" }) }) }) : null
|
|
527
550
|
] });
|
|
528
551
|
}
|
|
529
552
|
|
|
530
553
|
// src/components/call-limbo/CallLimbo.tsx
|
|
531
|
-
import { useEffect as useEffect4, useRef as
|
|
554
|
+
import { useEffect as useEffect4, useRef as useRef5, useState as useState7 } from "react";
|
|
532
555
|
|
|
533
556
|
// src/theme.ts
|
|
534
557
|
var LIGHT_CHALK_THEME_TOKENS = {
|
|
@@ -612,28 +635,29 @@ function chalkThemeStyle(theme, colorScheme = theme?.colorScheme ?? "dark") {
|
|
|
612
635
|
}
|
|
613
636
|
|
|
614
637
|
// src/components/toast-stack/CallEventIcon.tsx
|
|
615
|
-
import { Fragment as
|
|
638
|
+
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
616
639
|
function CallEventIcon({ kind, error = false }) {
|
|
617
640
|
const paths2 = {
|
|
641
|
+
speaker: /* @__PURE__ */ jsx22("path", { d: "M11 5 6 9H3v6h3l5 4V5ZM15 8a6 6 0 0 1 0 8M18 5a10 10 0 0 1 0 14" }),
|
|
618
642
|
microphone: /* @__PURE__ */ jsx22("path", { d: "M2 2l20 20M15 9.3V5a3 3 0 0 0-5.7-1.3M9 9v2a3 3 0 0 0 5.1 2.1M17 17a7 7 0 0 1-12-6v-1M19 10v1a7 7 0 0 1-.1 1.2M12 18v4" }),
|
|
619
|
-
"microphone-on": /* @__PURE__ */ jsxs9(
|
|
643
|
+
"microphone-on": /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
620
644
|
/* @__PURE__ */ jsx22("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
|
|
621
645
|
/* @__PURE__ */ jsx22("path", { d: "M19 10v1a7 7 0 0 1-14 0v-1M12 18v4" })
|
|
622
646
|
] }),
|
|
623
647
|
camera: /* @__PURE__ */ jsx22("path", { d: "M2 2l20 20M10.7 6H14a2 2 0 0 1 2 2v3.3l1 1 4-2.8v8M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2" }),
|
|
624
|
-
screen: /* @__PURE__ */ jsxs9(
|
|
648
|
+
screen: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
625
649
|
/* @__PURE__ */ jsx22("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
|
|
626
650
|
/* @__PURE__ */ jsx22("path", { d: "M8 21h8M12 17v4M9.5 7.5l5 5M14.5 7.5l-5 5" })
|
|
627
651
|
] }),
|
|
628
|
-
recording: /* @__PURE__ */ jsxs9(
|
|
652
|
+
recording: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
629
653
|
/* @__PURE__ */ jsx22("circle", { cx: "12", cy: "12", r: "9" }),
|
|
630
654
|
/* @__PURE__ */ jsx22("circle", { cx: "12", cy: "12", r: "3.5", fill: "currentColor" })
|
|
631
655
|
] }),
|
|
632
|
-
hand: /* @__PURE__ */ jsxs9(
|
|
656
|
+
hand: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
633
657
|
/* @__PURE__ */ jsx22("path", { d: "M18 11V6a2 2 0 0 0-4 0v5M14 10V4a2 2 0 0 0-4 0v6M10 10.5V6a2 2 0 0 0-4 0v8" }),
|
|
634
658
|
/* @__PURE__ */ jsx22("path", { d: "M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.3l-3.6-3.6a2 2 0 0 1 2.8-2.8L7 15" })
|
|
635
659
|
] }),
|
|
636
|
-
host: /* @__PURE__ */ jsxs9(
|
|
660
|
+
host: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
637
661
|
/* @__PURE__ */ jsx22("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
|
|
638
662
|
/* @__PURE__ */ jsx22("circle", { cx: "9", cy: "7", r: "4" }),
|
|
639
663
|
/* @__PURE__ */ jsx22("path", { d: "M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8" })
|
|
@@ -645,9 +669,9 @@ function CallEventIcon({ kind, error = false }) {
|
|
|
645
669
|
// src/components/call-limbo/CallLimbo.tsx
|
|
646
670
|
import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
647
671
|
function CallLimbo({ spaceName = "Call", message, detail, action, children, overlay = false, active = true, initiallyCovered = false, theme, recorded = false, blocking = true, className }) {
|
|
648
|
-
const layerRef =
|
|
672
|
+
const layerRef = useRef5(null);
|
|
649
673
|
const reducedMotion = usePrefersReducedMotion();
|
|
650
|
-
const [covered, setCovered] =
|
|
674
|
+
const [covered, setCovered] = useState7(active || initiallyCovered);
|
|
651
675
|
useEffect4(() => {
|
|
652
676
|
let nextFrame = 0;
|
|
653
677
|
const frame = requestAnimationFrame(() => {
|
|
@@ -724,11 +748,112 @@ function CallLimbo({ spaceName = "Call", message, detail, action, children, over
|
|
|
724
748
|
] });
|
|
725
749
|
}
|
|
726
750
|
|
|
727
|
-
// src/components/
|
|
728
|
-
import {
|
|
729
|
-
function
|
|
730
|
-
return cause instanceof
|
|
751
|
+
// src/components/control-bar/command-failure.ts
|
|
752
|
+
import { SpaceClientError } from "@q9labsai/chalk-client";
|
|
753
|
+
function commandFailure(cause) {
|
|
754
|
+
return cause instanceof SpaceClientError ? cause : new SpaceClientError({
|
|
755
|
+
code: "client.internal_error",
|
|
756
|
+
recoverable: false,
|
|
757
|
+
message: cause instanceof Error ? cause.message : "This command could not be completed."
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
var again = ({ recoverable }) => recoverable ? " Try again." : "";
|
|
761
|
+
var device = ({ source }) => source ?? "device";
|
|
762
|
+
var settings = (context) => `Couldn\u2019t change ${context.source === "screen" ? "screen sharing" : `your ${device(context)} settings`}.`;
|
|
763
|
+
var stop = (context) => context.source === "screen" ? "Couldn\u2019t stop screen sharing." : settings(context);
|
|
764
|
+
var start = (context) => context.source === "screen" ? "Your screen couldn\u2019t be shared." : `Your ${device(context)} couldn\u2019t start.`;
|
|
765
|
+
var test = () => "Couldn\u2019t play the speaker test. Check your browser\u2019s audio settings and system volume.";
|
|
766
|
+
var operationCopy = {
|
|
767
|
+
start: (context) => `${start(context)}${again(context)}`,
|
|
768
|
+
stop: (context) => `${stop(context)}${again(context)}`,
|
|
769
|
+
select: (context) => `Couldn\u2019t select your ${device(context)}.${again(context)}`,
|
|
770
|
+
test: (context) => `${test(context)}${again(context)}`,
|
|
771
|
+
request: (context) => `Couldn\u2019t respond to the ${device(context)} request.${again(context)}`,
|
|
772
|
+
change: (context) => `${settings(context)}${again(context)}`
|
|
773
|
+
};
|
|
774
|
+
var generic = { copy: operationCopy, retry: true };
|
|
775
|
+
var unavailable = { copy: operationCopy, retry: false };
|
|
776
|
+
var specific = (copy) => ({ copy: { ...operationCopy, start: copy, select: copy, request: copy, change: copy }, retry: false });
|
|
777
|
+
var capture = (context) => `${settings(context)} Check that it is connected and available${context.recoverable ? ", then try again" : ""}.`;
|
|
778
|
+
var captureStart = (context) => context.source === "screen" ? `${start(context)}${again(context)}` : `Your ${device(context)} couldn\u2019t start. Check that it is connected and available${context.recoverable ? ", then try again" : ""}.`;
|
|
779
|
+
var MEDIA_FAILURE_POLICY = {
|
|
780
|
+
"access.invalid": specific(() => "Your call access is unavailable. Rejoin the call."),
|
|
781
|
+
"access.unavailable": specific(() => "Your call access is unavailable. Rejoin the call."),
|
|
782
|
+
"chat.cursor_reset_required": unavailable,
|
|
783
|
+
"chat.payload_invalid": unavailable,
|
|
784
|
+
"client.internal_error": generic,
|
|
785
|
+
"collaboration.unavailable": unavailable,
|
|
786
|
+
"command.rate_limited": generic,
|
|
787
|
+
"command.rejected": unavailable,
|
|
788
|
+
"connection.invalid_state": {
|
|
789
|
+
copy: {
|
|
790
|
+
...operationCopy,
|
|
791
|
+
start: (context) => `That change was interrupted.${again(context)}`,
|
|
792
|
+
stop: (context) => `That change was interrupted.${again(context)}`,
|
|
793
|
+
select: (context) => `That change was interrupted.${again(context)}`,
|
|
794
|
+
change: (context) => `That change was interrupted.${again(context)}`
|
|
795
|
+
},
|
|
796
|
+
retry: true
|
|
797
|
+
},
|
|
798
|
+
"connection.join_cleanup_unconfirmed": unavailable,
|
|
799
|
+
"connection.leave_unconfirmed": unavailable,
|
|
800
|
+
"connection.media_recovery_exhausted": unavailable,
|
|
801
|
+
"connection.media_start_failed": generic,
|
|
802
|
+
"connection.state_digest_recovery_failed": unavailable,
|
|
803
|
+
"connection.sync_recovery_exhausted": unavailable,
|
|
804
|
+
"connection.sync_start_failed": unavailable,
|
|
805
|
+
"connection.sync_hello_timeout": unavailable,
|
|
806
|
+
"environment.unsupported": {
|
|
807
|
+
copy: {
|
|
808
|
+
...operationCopy,
|
|
809
|
+
start: () => "Media capture is unavailable in this environment. Use a supported browser over HTTPS or the native app.",
|
|
810
|
+
request: () => "Media capture is unavailable in this environment. Use a supported browser over HTTPS or the native app.",
|
|
811
|
+
select: (context) => context.source === "speaker" ? "This browser can\u2019t change your speaker. Use your system sound settings to choose an output device." : "Media capture is unavailable in this environment. Use a supported browser over HTTPS or the native app.",
|
|
812
|
+
test: () => "This browser can\u2019t play a speaker test. Check your browser\u2019s audio settings or use another supported browser.",
|
|
813
|
+
change: (context) => context.source === "speaker" ? "This browser can\u2019t change your speaker. Use your system sound settings to choose an output device." : "Media capture is unavailable in this environment. Use a supported browser over HTTPS or the native app."
|
|
814
|
+
},
|
|
815
|
+
retry: false
|
|
816
|
+
},
|
|
817
|
+
"episode.ended": { copy: { start: () => "This call has ended.", stop: () => "This call has ended.", select: () => "This call has ended.", test: () => "This call has ended.", request: () => "This call has ended.", change: () => "This call has ended." }, retry: false },
|
|
818
|
+
"media.permission_denied": specific(
|
|
819
|
+
(context) => context.source === "screen" ? `Your screen couldn\u2019t be shared. Allow screen recording for your browser in System Settings${context.recoverable ? ", then try again" : ""}.` : context.source === "speaker" ? "Chalk can\u2019t use your speaker. Check your browser\u2019s audio permissions and system sound settings." : `Chalk can\u2019t use your ${device(context)}. Click the camera icon in the address bar and allow ${context.source === "camera" ? "Camera" : context.source === "microphone" ? "Microphone" : "Camera and Microphone"}.`
|
|
820
|
+
),
|
|
821
|
+
"media.device_not_found": specific((context) => `No ${device(context)} found. Connect one${context.recoverable ? ", then try again" : ""}.`),
|
|
822
|
+
"media.device_busy": { ...specific((context) => `Your ${device(context)} is being used by another app. Close it there${context.recoverable ? ", then try again" : ""}.`), retry: true },
|
|
823
|
+
"media.device_constraint_invalid": specific((context) => `Your ${device(context)} doesn\u2019t support these settings. Choose another ${device(context)}${context.recoverable ? ", then try again" : ""}.`),
|
|
824
|
+
"media.capture_failed": { copy: { ...operationCopy, start: captureStart, request: captureStart, change: (context) => context.source === "screen" ? `${settings(context)}${again(context)}` : capture(context) }, retry: true },
|
|
825
|
+
"media.request_invalid": {
|
|
826
|
+
copy: {
|
|
827
|
+
...operationCopy,
|
|
828
|
+
test: () => "The speaker test is no longer available.",
|
|
829
|
+
request: () => "The media request is no longer active.",
|
|
830
|
+
select: (context) => `Choose a valid ${device(context)} from the device list.`,
|
|
831
|
+
start: () => "This media action is no longer available.",
|
|
832
|
+
stop: () => "This media action is no longer available.",
|
|
833
|
+
change: () => "This media action is no longer available."
|
|
834
|
+
},
|
|
835
|
+
retry: false
|
|
836
|
+
},
|
|
837
|
+
"media.timeout": generic,
|
|
838
|
+
"offline.discarded": unavailable,
|
|
839
|
+
"participant.invalid": unavailable,
|
|
840
|
+
"reaction.invalid": unavailable,
|
|
841
|
+
"whiteboard.unavailable": unavailable
|
|
842
|
+
};
|
|
843
|
+
function commandFailurePresentation(failure, source, operation = "change", hasExactRetry = false) {
|
|
844
|
+
if (!Object.hasOwn(MEDIA_FAILURE_POLICY, failure.code)) return { message: "This media action couldn\u2019t be completed.", retry: false };
|
|
845
|
+
if (!source && operation === "change" && !failure.code.startsWith("media.")) return { message: failure.message, retry: false };
|
|
846
|
+
const rule = MEDIA_FAILURE_POLICY[failure.code];
|
|
847
|
+
const context = { source, recoverable: failure.recoverable };
|
|
848
|
+
const message = rule.copy[operation](context);
|
|
849
|
+
return { message, retry: failure.recoverable && rule.retry && hasExactRetry && source !== void 0 && source !== "speaker" && (operation === "start" || operation === "stop") };
|
|
850
|
+
}
|
|
851
|
+
function commandFailureMessage(failure, source, operation) {
|
|
852
|
+
return commandFailurePresentation(failure, source, operation).message;
|
|
731
853
|
}
|
|
854
|
+
|
|
855
|
+
// src/components/media-request-dialog/media-request-dialog-state.ts
|
|
856
|
+
import { useEffect as useEffect5, useMemo as useMemo2, useState as useState8 } from "react";
|
|
732
857
|
function formatExpiryLabel(expiresAtMs, now) {
|
|
733
858
|
if (!Number.isFinite(expiresAtMs)) return null;
|
|
734
859
|
const remainingSeconds = Math.max(0, Math.ceil((expiresAtMs - now) / 1e3));
|
|
@@ -739,9 +864,9 @@ function formatExpiryLabel(expiresAtMs, now) {
|
|
|
739
864
|
}
|
|
740
865
|
function useMediaRequestDialogState({ request, onDecline, onAllow, onActionError }) {
|
|
741
866
|
const expiresAtMs = useMemo2(() => Date.parse(request.expiresAt), [request.expiresAt]);
|
|
742
|
-
const [now, setNow] =
|
|
743
|
-
const [pendingAction, setPendingAction] =
|
|
744
|
-
const [errorMessageState, setErrorMessage] =
|
|
867
|
+
const [now, setNow] = useState8(() => Date.now());
|
|
868
|
+
const [pendingAction, setPendingAction] = useState8(null);
|
|
869
|
+
const [errorMessageState, setErrorMessage] = useState8(null);
|
|
745
870
|
useEffect5(() => {
|
|
746
871
|
setNow(Date.now());
|
|
747
872
|
setPendingAction(null);
|
|
@@ -760,7 +885,7 @@ function useMediaRequestDialogState({ request, onDecline, onAllow, onActionError
|
|
|
760
885
|
setPendingAction(action);
|
|
761
886
|
setErrorMessage(null);
|
|
762
887
|
Promise.resolve().then(handler).then(() => onActionError?.(null, action)).catch((cause) => {
|
|
763
|
-
const message =
|
|
888
|
+
const message = commandFailureMessage(commandFailure(cause), request.kind === "start_camera" ? "camera" : "microphone", "request");
|
|
764
889
|
setErrorMessage(message);
|
|
765
890
|
onActionError?.(message, action);
|
|
766
891
|
}).finally(() => setPendingAction(null));
|
|
@@ -771,7 +896,7 @@ function useMediaRequestDialogState({ request, onDecline, onAllow, onActionError
|
|
|
771
896
|
// src/components/media-request-dialog/MediaRequestDialog.tsx
|
|
772
897
|
import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
773
898
|
function MediaRequestDialog({ request, onDecline, onAllow, onActionError }) {
|
|
774
|
-
const { isExpired, expiryLabel, pendingAction, errorMessage
|
|
899
|
+
const { isExpired, expiryLabel, pendingAction, errorMessage, runAction } = useMediaRequestDialogState({ request, onDecline, onAllow, onActionError });
|
|
775
900
|
const RequestIcon = request.kind === "unmute" ? Microphone01Icon : Video01Icon;
|
|
776
901
|
return /* @__PURE__ */ jsxs11(
|
|
777
902
|
"div",
|
|
@@ -794,7 +919,7 @@ function MediaRequestDialog({ request, onDecline, onAllow, onActionError }) {
|
|
|
794
919
|
expiryLabel ? /* @__PURE__ */ jsx24("p", { className: "mt-1 text-xs text-[var(--chalk-app-text-muted)]", role: "status", children: expiryLabel }) : null
|
|
795
920
|
] })
|
|
796
921
|
] }),
|
|
797
|
-
|
|
922
|
+
errorMessage ? /* @__PURE__ */ jsx24("p", { className: "mt-3 rounded-md border border-[var(--chalk-app-danger)]/35 bg-[var(--chalk-app-danger)]/10 px-3 py-2 text-sm text-[var(--chalk-app-danger)]", role: "alert", children: errorMessage }) : null,
|
|
798
923
|
/* @__PURE__ */ jsxs11("div", { className: "mt-4 flex justify-end gap-2", children: [
|
|
799
924
|
/* @__PURE__ */ jsx24("button", { type: "button", className: "rounded-lg px-3 py-2 text-sm text-[var(--chalk-app-text-muted)] hover:bg-[var(--chalk-app-control-hover)] disabled:cursor-not-allowed disabled:opacity-55", onClick: () => runAction("decline"), disabled: isExpired || pendingAction !== null, children: "Not now" }),
|
|
800
925
|
/* @__PURE__ */ jsx24(
|
|
@@ -814,11 +939,11 @@ function MediaRequestDialog({ request, onDecline, onAllow, onActionError }) {
|
|
|
814
939
|
}
|
|
815
940
|
|
|
816
941
|
// src/components/admission-panel/AdmissionPanel.tsx
|
|
817
|
-
import React8, { useEffect as useEffect10, useState as
|
|
942
|
+
import React8, { useEffect as useEffect10, useState as useState15 } from "react";
|
|
818
943
|
import { IconButton, Spinner } from "@q9labsai/chalk-ui";
|
|
819
944
|
|
|
820
945
|
// src/components/audio-output/AudioOutput.tsx
|
|
821
|
-
import { useCallback as useCallback3, useEffect as useEffect6, useMemo as useMemo4, useRef as
|
|
946
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef6, useState as useState10 } from "react";
|
|
822
947
|
|
|
823
948
|
// src/selectors/space-selectors.ts
|
|
824
949
|
function toVideoParticipants(participants, remoteMedia, localId, displayName, localMedia) {
|
|
@@ -879,11 +1004,11 @@ function toAudioParticipants(remoteMedia) {
|
|
|
879
1004
|
}
|
|
880
1005
|
|
|
881
1006
|
// src/components/participants-panel/participant-volume-context.tsx
|
|
882
|
-
import { createContext as createContext2, useContext as useContext2, useMemo as useMemo3, useState as
|
|
1007
|
+
import { createContext as createContext2, useContext as useContext2, useMemo as useMemo3, useState as useState9 } from "react";
|
|
883
1008
|
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
884
1009
|
var ParticipantVolumeContext = createContext2(null);
|
|
885
1010
|
function ParticipantVolumeProvider({ children }) {
|
|
886
|
-
const [volumes, setVolumes] =
|
|
1011
|
+
const [volumes, setVolumes] = useState9(/* @__PURE__ */ new Map());
|
|
887
1012
|
const value = useMemo3(
|
|
888
1013
|
() => ({
|
|
889
1014
|
volumes,
|
|
@@ -924,11 +1049,11 @@ function AudioOutput({ participants, volume = 1, audioOutputDeviceId, getPartici
|
|
|
924
1049
|
}, [participants, contextParticipants, participantState.roster]);
|
|
925
1050
|
const effectiveAudioOutputDeviceId = audioOutputDeviceId ?? media.selection.speaker ?? void 0;
|
|
926
1051
|
const effectiveGetParticipantVolume = getParticipantVolume ?? ((participantId) => (volumeContext?.volumes.get(participantId) ?? 100) / 100);
|
|
927
|
-
const audioElementsRef =
|
|
928
|
-
const screenShareAudioRef =
|
|
929
|
-
const pendingAutoplayRetryRef =
|
|
930
|
-
const [needsAutoplayUnlock, setNeedsAutoplayUnlock] =
|
|
931
|
-
const resumeAudioRef =
|
|
1052
|
+
const audioElementsRef = useRef6(/* @__PURE__ */ new Map());
|
|
1053
|
+
const screenShareAudioRef = useRef6(/* @__PURE__ */ new Map());
|
|
1054
|
+
const pendingAutoplayRetryRef = useRef6(/* @__PURE__ */ new Set());
|
|
1055
|
+
const [needsAutoplayUnlock, setNeedsAutoplayUnlock] = useState10(false);
|
|
1056
|
+
const resumeAudioRef = useRef6(null);
|
|
932
1057
|
const markAutoplayBlocked = (el) => {
|
|
933
1058
|
pendingAutoplayRetryRef.current.add(el);
|
|
934
1059
|
setNeedsAutoplayUnlock(true);
|
|
@@ -1174,7 +1299,7 @@ function useHaptics({ enabled = true } = {}) {
|
|
|
1174
1299
|
|
|
1175
1300
|
// src/components/participant-tile/ParticipantTile.tsx
|
|
1176
1301
|
import { Facehash as Facehash2 } from "@q9labsai/facehash/react";
|
|
1177
|
-
import React5, { useMemo as useMemo6, useRef as
|
|
1302
|
+
import React5, { useMemo as useMemo6, useRef as useRef8, useState as useState13 } from "react";
|
|
1178
1303
|
|
|
1179
1304
|
// src/internal/useMirrorSetting.ts
|
|
1180
1305
|
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
@@ -1215,33 +1340,33 @@ function setMirrored(next) {
|
|
|
1215
1340
|
|
|
1216
1341
|
// src/components/stage/StageIcon.tsx
|
|
1217
1342
|
import "react";
|
|
1218
|
-
import { Fragment as
|
|
1343
|
+
import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1219
1344
|
var paths = {
|
|
1220
|
-
share: /* @__PURE__ */ jsxs12(
|
|
1345
|
+
share: /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1221
1346
|
/* @__PURE__ */ jsx27("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
|
|
1222
1347
|
/* @__PURE__ */ jsx27("path", { d: "M8 21h8M12 17v4M9 10l3-3 3 3M12 7v6" })
|
|
1223
1348
|
] }),
|
|
1224
|
-
fill: /* @__PURE__ */ jsxs12(
|
|
1349
|
+
fill: /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1225
1350
|
/* @__PURE__ */ jsx27("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
1226
1351
|
/* @__PURE__ */ jsx27("path", { d: "M7 12h10M7 12l2.5-2.5M7 12l2.5 2.5M17 12l-2.5-2.5M17 12l-2.5 2.5" })
|
|
1227
1352
|
] }),
|
|
1228
|
-
fit: /* @__PURE__ */ jsxs12(
|
|
1353
|
+
fit: /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1229
1354
|
/* @__PURE__ */ jsx27("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
1230
1355
|
/* @__PURE__ */ jsx27("rect", { x: "7.5", y: "9", width: "9", height: "6", rx: "1" })
|
|
1231
1356
|
] }),
|
|
1232
|
-
"zoom-in": /* @__PURE__ */ jsxs12(
|
|
1357
|
+
"zoom-in": /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1233
1358
|
/* @__PURE__ */ jsx27("circle", { cx: "11", cy: "11", r: "7" }),
|
|
1234
1359
|
/* @__PURE__ */ jsx27("path", { d: "M21 21l-4.3-4.3M8 11h6M11 8v6" })
|
|
1235
1360
|
] }),
|
|
1236
|
-
"zoom-out": /* @__PURE__ */ jsxs12(
|
|
1361
|
+
"zoom-out": /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1237
1362
|
/* @__PURE__ */ jsx27("circle", { cx: "11", cy: "11", r: "7" }),
|
|
1238
1363
|
/* @__PURE__ */ jsx27("path", { d: "M21 21l-4.3-4.3M8 11h6" })
|
|
1239
1364
|
] }),
|
|
1240
|
-
pip: /* @__PURE__ */ jsxs12(
|
|
1365
|
+
pip: /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1241
1366
|
/* @__PURE__ */ jsx27("rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }),
|
|
1242
1367
|
/* @__PURE__ */ jsx27("rect", { x: "12", y: "12", width: "7", height: "5", rx: "1", fill: "currentColor" })
|
|
1243
1368
|
] }),
|
|
1244
|
-
volume: /* @__PURE__ */ jsxs12(
|
|
1369
|
+
volume: /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1245
1370
|
/* @__PURE__ */ jsx27("path", { d: "M11 5L6 9H2v6h4l5 4z" }),
|
|
1246
1371
|
/* @__PURE__ */ jsx27("path", { d: "M15.5 8.5a5 5 0 0 1 0 7M19 5a10 10 0 0 1 0 14" })
|
|
1247
1372
|
] }),
|
|
@@ -1249,12 +1374,12 @@ var paths = {
|
|
|
1249
1374
|
pause: /* @__PURE__ */ jsx27("path", { d: "M9 5v14M15 5v14", strokeWidth: "2.5" }),
|
|
1250
1375
|
more: /* @__PURE__ */ jsx27("path", { d: "M5 12h.01M12 12h.01M19 12h.01", strokeWidth: "3" }),
|
|
1251
1376
|
mute: /* @__PURE__ */ jsx27("path", { d: "M2 2l20 20M15 9.3V5a3 3 0 0 0-5.7-1.3M9 9v2a3 3 0 0 0 5.1 2.1M17 17a7 7 0 0 1-12-6v-1M19 10v1a7 7 0 0 1-.1 1.2M12 18v4" }),
|
|
1252
|
-
hand: /* @__PURE__ */ jsxs12(
|
|
1377
|
+
hand: /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1253
1378
|
/* @__PURE__ */ jsx27("path", { d: "M18 11V6a2 2 0 0 0-4 0v5M14 10V4a2 2 0 0 0-4 0v6M10 10.5V6a2 2 0 0 0-4 0v8" }),
|
|
1254
1379
|
/* @__PURE__ */ jsx27("path", { d: "M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.3l-3.6-3.6a2 2 0 0 1 2.8-2.8L7 15" })
|
|
1255
1380
|
] }),
|
|
1256
1381
|
pin: /* @__PURE__ */ jsx27("path", { d: "M12 17v5M9 10.8a2 2 0 0 1-1.1 1.8l-1.8.9A2 2 0 0 0 5 15.2V17h14v-1.8a2 2 0 0 0-1.1-1.8l-1.8-.9a2 2 0 0 1-1.1-1.8V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" }),
|
|
1257
|
-
pen: /* @__PURE__ */ jsxs12(
|
|
1382
|
+
pen: /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
1258
1383
|
/* @__PURE__ */ jsx27("path", { d: "M17 3a2.85 2.85 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5z" }),
|
|
1259
1384
|
/* @__PURE__ */ jsx27("path", { d: "M15 5l4 4" })
|
|
1260
1385
|
] })
|
|
@@ -1264,7 +1389,7 @@ function StageIcon({ name, size = 16, ...props }) {
|
|
|
1264
1389
|
}
|
|
1265
1390
|
|
|
1266
1391
|
// src/components/atomic/Avatar.tsx
|
|
1267
|
-
import React3, { useEffect as useEffect7, useMemo as useMemo5, useState as
|
|
1392
|
+
import React3, { useEffect as useEffect7, useMemo as useMemo5, useState as useState11 } from "react";
|
|
1268
1393
|
import { Facehash } from "@q9labsai/facehash/react";
|
|
1269
1394
|
import { jsx as jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1270
1395
|
var GeneratedFacehash = Facehash;
|
|
@@ -1283,7 +1408,7 @@ var statusColorMap = {
|
|
|
1283
1408
|
offline: "var(--chalk-muted-text)"
|
|
1284
1409
|
};
|
|
1285
1410
|
var Avatar = React3.memo(({ name, src, size = "md", status, className, style, gradientPreference, generated = true, animated = true }) => {
|
|
1286
|
-
const [imageError, setImageError] =
|
|
1411
|
+
const [imageError, setImageError] = useState11(false);
|
|
1287
1412
|
const hasUploadedImage = Boolean(src) && !imageError;
|
|
1288
1413
|
const shouldShowGeneratedAvatar = generated && Boolean(name) && !hasUploadedImage;
|
|
1289
1414
|
useEffect7(() => {
|
|
@@ -1360,10 +1485,10 @@ function TileShell({ label, accentColor, pinned = false, ring = false, speaking
|
|
|
1360
1485
|
}
|
|
1361
1486
|
|
|
1362
1487
|
// src/components/participant-tile/useVideoTrack.ts
|
|
1363
|
-
import { useEffect as useEffect8, useRef as
|
|
1488
|
+
import { useEffect as useEffect8, useRef as useRef7, useState as useState12 } from "react";
|
|
1364
1489
|
function useVideoTrack(videoRef, track, enabled) {
|
|
1365
|
-
const [status, setStatus] =
|
|
1366
|
-
const loadedRef =
|
|
1490
|
+
const [status, setStatus] = useState12("idle");
|
|
1491
|
+
const loadedRef = useRef7(false);
|
|
1367
1492
|
useEffect8(() => {
|
|
1368
1493
|
const video = videoRef.current;
|
|
1369
1494
|
loadedRef.current = false;
|
|
@@ -1403,7 +1528,7 @@ function useVideoTrack(videoRef, track, enabled) {
|
|
|
1403
1528
|
}
|
|
1404
1529
|
|
|
1405
1530
|
// src/components/participant-tile/ParticipantTile.tsx
|
|
1406
|
-
import { Fragment as
|
|
1531
|
+
import { Fragment as Fragment7, jsx as jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1407
1532
|
var aspectRatioClasses = {
|
|
1408
1533
|
"16:9": "aspect-video",
|
|
1409
1534
|
"4:3": "aspect-[4/3]",
|
|
@@ -1411,7 +1536,7 @@ var aspectRatioClasses = {
|
|
|
1411
1536
|
fill: ""
|
|
1412
1537
|
};
|
|
1413
1538
|
var ParticipantTile = React5.memo(function ParticipantTile2({ videoTrack, ...props }) {
|
|
1414
|
-
const videoRef =
|
|
1539
|
+
const videoRef = useRef8(null);
|
|
1415
1540
|
const status = useVideoTrack(videoRef, videoTrack, props.participant.isVideoEnabled === true);
|
|
1416
1541
|
return /* @__PURE__ */ jsx30(ParticipantTileSurface, { ...props, media: /* @__PURE__ */ jsx30("video", { ref: videoRef, autoPlay: true, playsInline: true, muted: true, className: "h-full w-full object-cover" }), mediaVisible: status === "playing" });
|
|
1417
1542
|
});
|
|
@@ -1440,8 +1565,8 @@ var ParticipantTileSurface = React5.memo(function ParticipantTileSurface2({
|
|
|
1440
1565
|
}) {
|
|
1441
1566
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
1442
1567
|
const phone = useMediaQuery("(max-width:640px)");
|
|
1443
|
-
const [optionsOpen, setOptionsOpen] =
|
|
1444
|
-
const returnFocus =
|
|
1568
|
+
const [optionsOpen, setOptionsOpen] = useState13(false);
|
|
1569
|
+
const returnFocus = useRef8(null);
|
|
1445
1570
|
const openOptions = () => {
|
|
1446
1571
|
returnFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
1447
1572
|
setOptionsOpen(true);
|
|
@@ -1473,9 +1598,9 @@ var ParticipantTileSurface = React5.memo(function ParticipantTileSurface2({
|
|
|
1473
1598
|
style,
|
|
1474
1599
|
dataTour: participant.isLocal ? "local-video" : "video-grid",
|
|
1475
1600
|
hidden,
|
|
1476
|
-
corner: /* @__PURE__ */ jsxs15(
|
|
1477
|
-
showStatus && hasPoorConnection ? /* @__PURE__ */ jsx30("span", { role: "img", "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__ */ jsx30(SignalBars, {}) }) : null,
|
|
1478
|
-
onClick && !phone ? /* @__PURE__ */ jsx30("span", { 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__ */ jsx30(
|
|
1601
|
+
corner: /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
1602
|
+
showStatus && hasPoorConnection ? /* @__PURE__ */ jsx30("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__ */ jsx30(SignalBars, {}) }) : null,
|
|
1603
|
+
onClick && !phone ? /* @__PURE__ */ jsx30("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__ */ jsx30(
|
|
1479
1604
|
ChalkMenu,
|
|
1480
1605
|
{
|
|
1481
1606
|
trigger: /* @__PURE__ */ jsx30("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__ */ jsx30(StageIcon, { name: "more", size: 18 }) }),
|
|
@@ -1483,13 +1608,16 @@ var ParticipantTileSurface = React5.memo(function ParticipantTileSurface2({
|
|
|
1483
1608
|
}
|
|
1484
1609
|
) }) : null
|
|
1485
1610
|
] }),
|
|
1486
|
-
chip: showName || showStatus ? /* @__PURE__ */ jsxs15(
|
|
1611
|
+
chip: showName || showStatus ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
1487
1612
|
pinned && /* @__PURE__ */ jsx30(StageIcon, { name: "pin", size: 14, "aria-label": "Pinned" }),
|
|
1488
|
-
showName && /* @__PURE__ */ jsxs15(
|
|
1489
|
-
participant.displayName,
|
|
1490
|
-
|
|
1613
|
+
showName && /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
1614
|
+
/* @__PURE__ */ jsxs15("span", { dir: "auto", "data-part": "tile-full-name", className: "min-w-0 truncate [unicode-bidi:plaintext]", title: participant.displayName, children: [
|
|
1615
|
+
participant.displayName,
|
|
1616
|
+
participant.isLocal && participant.displayName !== "You" && /* @__PURE__ */ jsx30("span", { className: "text-white", children: " (You)" })
|
|
1617
|
+
] }),
|
|
1618
|
+
/* @__PURE__ */ jsx30("span", { dir: "auto", "data-part": "tile-short-name", className: "hidden min-w-0 truncate [unicode-bidi:plaintext]", children: participant.isLocal ? "You" : participant.displayName.split(" ")[0] })
|
|
1491
1619
|
] }),
|
|
1492
|
-
following ? /* @__PURE__ */ jsx30("span", { className: "shrink-0 font-semibold opacity-80", children: "following" }) : null,
|
|
1620
|
+
following ? /* @__PURE__ */ jsx30("span", { "data-part": "tile-following", className: "shrink-0 font-semibold opacity-80", children: "following" }) : null,
|
|
1493
1621
|
showStatus && participant.isMuted && /* @__PURE__ */ jsx30(StageIcon, { name: "mute", size: 14, className: "shrink-0 text-[#ff6b6b]", "aria-label": "Muted" }),
|
|
1494
1622
|
showStatus && participant.isHandRaised && /* @__PURE__ */ jsxs15("span", { className: "flex shrink-0 items-center text-[#e2bd3a]", role: "img", "aria-label": `Hand raised${participant.handRaiseOrder ? `, number ${participant.handRaiseOrder}` : ""}`, children: [
|
|
1495
1623
|
/* @__PURE__ */ jsx30(StageIcon, { name: "hand", size: 14 }),
|
|
@@ -1560,7 +1688,7 @@ function SignalBars() {
|
|
|
1560
1688
|
}
|
|
1561
1689
|
|
|
1562
1690
|
// src/components/atomic/ReactionBubble.tsx
|
|
1563
|
-
import React6, { useEffect as useEffect9, useState as
|
|
1691
|
+
import React6, { useEffect as useEffect9, useState as useState14, useMemo as useMemo7 } from "react";
|
|
1564
1692
|
import { CELEBRATION_EMOJIS } from "@q9labsai/chalk-ui/reactions";
|
|
1565
1693
|
import { jsx as jsx31, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1566
1694
|
var BASE_PARTICLE_COLORS = ["#14b8a6", "#f59e0b", "#ec4899", "#8b5cf6", "#06b6d4", "#22c55e"];
|
|
@@ -1604,7 +1732,7 @@ function getParticleStyle(particle) {
|
|
|
1604
1732
|
};
|
|
1605
1733
|
}
|
|
1606
1734
|
var ReactionBubble = React6.memo(({ emoji, participantName, onComplete, duration: baseDuration = 3e3, animated = true, className }) => {
|
|
1607
|
-
const [isVisible, setIsVisible] =
|
|
1735
|
+
const [isVisible, setIsVisible] = useState14(true);
|
|
1608
1736
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
1609
1737
|
const participantColors = useMemo7(() => getParticipantColor(participantName || "unknown"), [participantName]);
|
|
1610
1738
|
const isCelebration = CELEBRATION_EMOJIS.includes(emoji);
|
|
@@ -1681,7 +1809,7 @@ var VolumeSlider = React7.memo(({ value, onChange, muted = false, onMuteToggle,
|
|
|
1681
1809
|
VolumeSlider.displayName = "VolumeSlider";
|
|
1682
1810
|
|
|
1683
1811
|
// src/components/admission-panel/AdmissionPanel.tsx
|
|
1684
|
-
import { Fragment as
|
|
1812
|
+
import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1685
1813
|
var TEXT_BUTTON_CLASS = "inline-flex h-7 items-center rounded-[6px] px-2 text-xs font-semibold text-[var(--chalk-app-text-muted)] transition-colors hover:bg-[var(--chalk-app-control-hover)] hover:text-[var(--chalk-app-text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--chalk-app-control-active-line)]";
|
|
1686
1814
|
var ADMIT_BUTTON_CLASS = "inline-flex h-8 items-center rounded-[7px] border border-transparent bg-[var(--chalk-app-control-active)] px-3 text-[13px] font-semibold text-[var(--chalk-app-control-active-text)] transition-colors hover:border-[var(--chalk-app-control-active-line)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--chalk-app-control-active-line)]";
|
|
1687
1815
|
var DENY_BUTTON_CLASS = "inline-flex h-8 items-center rounded-[7px] px-2.5 text-[13px] font-semibold text-[var(--chalk-app-text-muted)] transition-colors hover:bg-[var(--chalk-app-control-hover)] hover:text-[var(--chalk-app-danger)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--chalk-app-control-active-line)]";
|
|
@@ -1692,13 +1820,13 @@ function getWaitingLabel(joinedAt) {
|
|
|
1692
1820
|
return `Waiting ${minutes} min`;
|
|
1693
1821
|
}
|
|
1694
1822
|
var AdmissionPanelSurface = React8.memo(({ participants, onAdmit, onDeny, onAdmitAll, onDenyAll, loading = false, className, onClose, inline = false }) => {
|
|
1695
|
-
const [, setTick] =
|
|
1823
|
+
const [, setTick] = useState15(0);
|
|
1696
1824
|
useEffect10(() => {
|
|
1697
1825
|
const timer = window.setInterval(() => setTick((t) => t + 1), 6e4);
|
|
1698
1826
|
return () => window.clearInterval(timer);
|
|
1699
1827
|
}, []);
|
|
1700
|
-
const [busy, setBusy] =
|
|
1701
|
-
const [error, setError] =
|
|
1828
|
+
const [busy, setBusy] = useState15(false);
|
|
1829
|
+
const [error, setError] = useState15(null);
|
|
1702
1830
|
const perform = async (action) => {
|
|
1703
1831
|
if (busy) return;
|
|
1704
1832
|
setBusy(true);
|
|
@@ -1712,7 +1840,7 @@ var AdmissionPanelSurface = React8.memo(({ participants, onAdmit, onDeny, onAdmi
|
|
|
1712
1840
|
}
|
|
1713
1841
|
};
|
|
1714
1842
|
const pending = participants.length;
|
|
1715
|
-
const list = /* @__PURE__ */ jsxs18(
|
|
1843
|
+
const list = /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
1716
1844
|
error ? /* @__PURE__ */ jsx33("p", { role: "alert", className: "text-sm text-[var(--chalk-danger-text)]", children: error }) : null,
|
|
1717
1845
|
pending > 0 ? /* @__PURE__ */ jsxs18("div", { className: "flex h-9 items-center justify-between gap-2", children: [
|
|
1718
1846
|
/* @__PURE__ */ jsx33("span", { className: "text-xs font-semibold uppercase tracking-[0.08em] text-[var(--chalk-app-text-muted)]", "aria-live": "polite", children: pending === 1 ? "1 waiting" : `${pending} waiting` }),
|
|
@@ -1771,7 +1899,7 @@ AdmissionPanel.displayName = "AdmissionPanel";
|
|
|
1771
1899
|
|
|
1772
1900
|
// src/components/composite/ChatPanel.tsx
|
|
1773
1901
|
import { CHALK_CHAT_ATTACHMENT_LIMITS, CHALK_CHAT_ATTACHMENT_MIME_TYPES } from "@q9labsai/chalk-client";
|
|
1774
|
-
import React10, { useEffect as useEffect13, useLayoutEffect, useMemo as useMemo8, useRef as
|
|
1902
|
+
import React10, { useEffect as useEffect13, useLayoutEffect, useMemo as useMemo8, useRef as useRef11, useState as useState18 } from "react";
|
|
1775
1903
|
import { Button } from "@q9labsai/chalk-ui";
|
|
1776
1904
|
|
|
1777
1905
|
// src/components/call-card/CallCardStyles.tsx
|
|
@@ -2634,21 +2762,21 @@ function CallCardStyles() {
|
|
|
2634
2762
|
|
|
2635
2763
|
// src/components/composite/MessageBubble.tsx
|
|
2636
2764
|
import { CHALK_REACTIONS } from "@q9labsai/chalk-client";
|
|
2637
|
-
import React9, { useEffect as useEffect12, useRef as
|
|
2765
|
+
import React9, { useEffect as useEffect12, useRef as useRef10, useState as useState17 } from "react";
|
|
2638
2766
|
|
|
2639
2767
|
// src/components/composite/use-chat-attachment-previews.ts
|
|
2640
|
-
import { useCallback as useCallback4, useEffect as useEffect11, useRef as
|
|
2768
|
+
import { useCallback as useCallback4, useEffect as useEffect11, useRef as useRef9, useState as useState16 } from "react";
|
|
2641
2769
|
function useChatAttachmentPreviews(attachments, resolveUrl) {
|
|
2642
|
-
const [resolvedUrls, setResolvedUrls] =
|
|
2643
|
-
const [failedAttachmentIds, setFailedAttachmentIds] =
|
|
2644
|
-
const [retryGeneration, setRetryGeneration] =
|
|
2645
|
-
const resolvingAttachmentIds =
|
|
2646
|
-
const resolvedUrlsRef =
|
|
2647
|
-
const failedAttachmentIdsRef =
|
|
2770
|
+
const [resolvedUrls, setResolvedUrls] = useState16(() => /* @__PURE__ */ new Map());
|
|
2771
|
+
const [failedAttachmentIds, setFailedAttachmentIds] = useState16(() => /* @__PURE__ */ new Set());
|
|
2772
|
+
const [retryGeneration, setRetryGeneration] = useState16(0);
|
|
2773
|
+
const resolvingAttachmentIds = useRef9(/* @__PURE__ */ new Set());
|
|
2774
|
+
const resolvedUrlsRef = useRef9(resolvedUrls);
|
|
2775
|
+
const failedAttachmentIdsRef = useRef9(failedAttachmentIds);
|
|
2648
2776
|
const currentAttachmentIds = new Set(attachments.map((attachment) => attachment.attachmentId));
|
|
2649
2777
|
const currentImageIds = new Set(attachments.filter((attachment) => attachment.mimeType.startsWith("image/")).map((attachment) => attachment.attachmentId));
|
|
2650
|
-
const currentAttachmentIdsRef =
|
|
2651
|
-
const currentImageIdsRef =
|
|
2778
|
+
const currentAttachmentIdsRef = useRef9(currentAttachmentIds);
|
|
2779
|
+
const currentImageIdsRef = useRef9(currentImageIds);
|
|
2652
2780
|
resolvedUrlsRef.current = resolvedUrls;
|
|
2653
2781
|
failedAttachmentIdsRef.current = failedAttachmentIds;
|
|
2654
2782
|
currentAttachmentIdsRef.current = currentAttachmentIds;
|
|
@@ -2697,7 +2825,7 @@ function useChatAttachmentPreviews(attachments, resolveUrl) {
|
|
|
2697
2825
|
}
|
|
2698
2826
|
|
|
2699
2827
|
// src/components/composite/MessageBubble.tsx
|
|
2700
|
-
import { Fragment as
|
|
2828
|
+
import { Fragment as Fragment9, jsx as jsx35, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2701
2829
|
var MessageBubble = React9.memo(
|
|
2702
2830
|
({
|
|
2703
2831
|
content,
|
|
@@ -2724,11 +2852,11 @@ var MessageBubble = React9.memo(
|
|
|
2724
2852
|
className
|
|
2725
2853
|
}) => {
|
|
2726
2854
|
const { resolvedUrls, failedAttachmentIds, markFailed, retry } = useChatAttachmentPreviews(attachments, onResolveAttachmentUrl);
|
|
2727
|
-
const [reactionError, setReactionError] =
|
|
2728
|
-
const [reacting, setReacting] =
|
|
2729
|
-
const [reactionBarOpen, setReactionBarOpen] =
|
|
2730
|
-
const messageRef =
|
|
2731
|
-
const press =
|
|
2855
|
+
const [reactionError, setReactionError] = useState17(null);
|
|
2856
|
+
const [reacting, setReacting] = useState17(false);
|
|
2857
|
+
const [reactionBarOpen, setReactionBarOpen] = useState17(false);
|
|
2858
|
+
const messageRef = useRef10(null);
|
|
2859
|
+
const press = useRef10(null);
|
|
2732
2860
|
const cancelPress = () => {
|
|
2733
2861
|
if (press.current) clearTimeout(press.current.timer);
|
|
2734
2862
|
press.current = null;
|
|
@@ -2743,10 +2871,10 @@ var MessageBubble = React9.memo(
|
|
|
2743
2871
|
document.addEventListener("pointerdown", dismiss);
|
|
2744
2872
|
return () => document.removeEventListener("pointerdown", dismiss);
|
|
2745
2873
|
}, [reactionBarOpen]);
|
|
2746
|
-
const [photo, setPhoto] =
|
|
2747
|
-
const [downloading, setDownloading] =
|
|
2748
|
-
const [downloadError, setDownloadError] =
|
|
2749
|
-
const downloadController =
|
|
2874
|
+
const [photo, setPhoto] = useState17(null);
|
|
2875
|
+
const [downloading, setDownloading] = useState17(false);
|
|
2876
|
+
const [downloadError, setDownloadError] = useState17(null);
|
|
2877
|
+
const downloadController = useRef10(null);
|
|
2750
2878
|
useEffect12(() => () => downloadController.current?.abort(), []);
|
|
2751
2879
|
const downloadPhoto = async () => {
|
|
2752
2880
|
if (!photo || downloading) return;
|
|
@@ -2777,8 +2905,8 @@ var MessageBubble = React9.memo(
|
|
|
2777
2905
|
downloadController.current = null;
|
|
2778
2906
|
}
|
|
2779
2907
|
};
|
|
2780
|
-
const [photoClosing, setPhotoClosing] =
|
|
2781
|
-
const closeTimer =
|
|
2908
|
+
const [photoClosing, setPhotoClosing] = useState17(false);
|
|
2909
|
+
const closeTimer = useRef10(null);
|
|
2782
2910
|
useEffect12(
|
|
2783
2911
|
() => () => {
|
|
2784
2912
|
if (closeTimer.current) clearTimeout(closeTimer.current);
|
|
@@ -2801,7 +2929,7 @@ var MessageBubble = React9.memo(
|
|
|
2801
2929
|
const changePhoto = (step) => {
|
|
2802
2930
|
if (photos.length > 1) setPhoto(photos[(photoIndex + step + photos.length) % photos.length]);
|
|
2803
2931
|
};
|
|
2804
|
-
const viewer =
|
|
2932
|
+
const viewer = useRef10(null);
|
|
2805
2933
|
const react = async (emoji) => {
|
|
2806
2934
|
if (!onReact || reacting) return;
|
|
2807
2935
|
setReactionBarOpen(false);
|
|
@@ -2996,7 +3124,7 @@ var MessageBubble = React9.memo(
|
|
|
2996
3124
|
},
|
|
2997
3125
|
children: [
|
|
2998
3126
|
photo ? /* @__PURE__ */ jsx35("img", { src: resolvedUrls.get(photo.attachmentId), alt: photo.fileName }) : null,
|
|
2999
|
-
photos.length > 1 ? /* @__PURE__ */ jsxs19(
|
|
3127
|
+
photos.length > 1 ? /* @__PURE__ */ jsxs19(Fragment9, { children: [
|
|
3000
3128
|
/* @__PURE__ */ jsx35("button", { type: "button", className: "call-photo-viewer-control call-photo-previous", "aria-label": "Previous image", onClick: () => changePhoto(-1), children: /* @__PURE__ */ jsx35(ArrowLeft01Icon, {}) }),
|
|
3001
3129
|
/* @__PURE__ */ jsx35("button", { type: "button", className: "call-photo-viewer-control call-photo-next", "aria-label": "Next image", onClick: () => changePhoto(1), children: /* @__PURE__ */ jsx35(ArrowRight01Icon, {}) })
|
|
3002
3130
|
] }) : null
|
|
@@ -3099,7 +3227,7 @@ function describeChatUploadFile(file) {
|
|
|
3099
3227
|
}
|
|
3100
3228
|
|
|
3101
3229
|
// src/components/composite/ChatPanel.tsx
|
|
3102
|
-
import { Fragment as
|
|
3230
|
+
import { Fragment as Fragment10, jsx as jsx36, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3103
3231
|
var ChatPanelPresentation = React10.memo((props) => {
|
|
3104
3232
|
return /* @__PURE__ */ jsx36(ChatPanelSurface, { ...props });
|
|
3105
3233
|
});
|
|
@@ -3133,12 +3261,12 @@ var ChatPanelSurface = React10.memo(
|
|
|
3133
3261
|
autoScrollBehavior,
|
|
3134
3262
|
className
|
|
3135
3263
|
}) => {
|
|
3136
|
-
const [draft, setDraft] =
|
|
3137
|
-
const [stagedFiles, setStagedFiles] =
|
|
3138
|
-
const uploads =
|
|
3139
|
-
const [failedUploads, setFailedUploads] =
|
|
3140
|
-
const [uploading, setUploading] =
|
|
3141
|
-
const [previews, setPreviews] =
|
|
3264
|
+
const [draft, setDraft] = useState18("");
|
|
3265
|
+
const [stagedFiles, setStagedFiles] = useState18([]);
|
|
3266
|
+
const uploads = useRef11(/* @__PURE__ */ new Map());
|
|
3267
|
+
const [failedUploads, setFailedUploads] = useState18(/* @__PURE__ */ new Set());
|
|
3268
|
+
const [uploading, setUploading] = useState18(/* @__PURE__ */ new Set());
|
|
3269
|
+
const [previews, setPreviews] = useState18(/* @__PURE__ */ new Map());
|
|
3142
3270
|
useEffect13(() => {
|
|
3143
3271
|
const urls = new Map(stagedFiles.flatMap((file) => file instanceof File && file.type.startsWith("image/") ? [[file, URL.createObjectURL(file)]] : []));
|
|
3144
3272
|
setPreviews(urls);
|
|
@@ -3146,15 +3274,15 @@ var ChatPanelSurface = React10.memo(
|
|
|
3146
3274
|
for (const url of urls.values()) URL.revokeObjectURL(url);
|
|
3147
3275
|
};
|
|
3148
3276
|
}, [stagedFiles]);
|
|
3149
|
-
const [sending, setSending] =
|
|
3150
|
-
const [pickingFiles, setPickingFiles] =
|
|
3151
|
-
const [composerError, setComposerError] =
|
|
3152
|
-
const scrollRef =
|
|
3153
|
-
const textareaRef =
|
|
3154
|
-
const fileInputRef =
|
|
3155
|
-
const isAtBottomRef =
|
|
3156
|
-
const lastMarkedSequenceRef =
|
|
3157
|
-
const restoreScrollRef =
|
|
3277
|
+
const [sending, setSending] = useState18(false);
|
|
3278
|
+
const [pickingFiles, setPickingFiles] = useState18(false);
|
|
3279
|
+
const [composerError, setComposerError] = useState18(null);
|
|
3280
|
+
const scrollRef = useRef11(null);
|
|
3281
|
+
const textareaRef = useRef11(null);
|
|
3282
|
+
const fileInputRef = useRef11(null);
|
|
3283
|
+
const isAtBottomRef = useRef11(true);
|
|
3284
|
+
const lastMarkedSequenceRef = useRef11(localReadThroughSequence);
|
|
3285
|
+
const restoreScrollRef = useRef11(null);
|
|
3158
3286
|
const grouped = useMemo8(() => groupChatMessages(messages), [messages]);
|
|
3159
3287
|
const latestSequence = messages.at(-1)?.sequence;
|
|
3160
3288
|
useLayoutEffect(() => {
|
|
@@ -3398,7 +3526,7 @@ var ChatPanelSurface = React10.memo(
|
|
|
3398
3526
|
/* @__PURE__ */ jsx36("button", { type: "button", disabled: sending || pickingFiles, "aria-label": `Remove ${describeChatUploadFile(file).fileName}`, onClick: () => removeFile(file), children: /* @__PURE__ */ jsx36(Cancel01Icon, { className: "h-3.5 w-3.5" }) })
|
|
3399
3527
|
] }, `${describeChatUploadFile(file).fileName}-${describeChatUploadFile(file).byteLength}-${index}`)) }) : null,
|
|
3400
3528
|
/* @__PURE__ */ jsx36("div", { className: "call-composer", children: /* @__PURE__ */ jsxs20("div", { className: "call-composer-field", children: [
|
|
3401
|
-
onUploadAttachment ? /* @__PURE__ */ jsxs20(
|
|
3529
|
+
onUploadAttachment ? /* @__PURE__ */ jsxs20(Fragment10, { children: [
|
|
3402
3530
|
!pickChatFiles ? /* @__PURE__ */ jsx36("input", { ref: fileInputRef, type: "file", multiple: true, className: "sr-only", "aria-label": "Choose attachments", accept: CHALK_CHAT_ATTACHMENT_MIME_TYPES.join(","), onChange: (event) => selectFiles(event.target.files) }) : null,
|
|
3403
3531
|
/* @__PURE__ */ jsx36(Button, { type: "button", variant: "ghost", size: "icon", className: "call-attach-button", disabled: disabled || sending || pickingFiles || stagedFiles.length >= CHALK_CHAT_ATTACHMENT_LIMITS.maximumPerMessage, onClick: () => void chooseFiles(), "aria-label": "Attach files", children: /* @__PURE__ */ jsx36("svg", { className: "size-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx36("path", { d: "M20.5 11.2l-8.4 8.4a5 5 0 0 1-7.1-7.1l8.4-8.4a3.3 3.3 0 0 1 4.7 4.7l-8.4 8.4a1.7 1.7 0 0 1-2.4-2.4l7.7-7.7" }) }) })
|
|
3404
3532
|
] }) : null,
|
|
@@ -3464,7 +3592,7 @@ var ChatPanel = React10.memo((props) => {
|
|
|
3464
3592
|
ChatPanel.displayName = "ChatPanel";
|
|
3465
3593
|
|
|
3466
3594
|
// src/components/composite/ReactionsOverlay.tsx
|
|
3467
|
-
import { useEffect as useEffect14, useRef as
|
|
3595
|
+
import { useEffect as useEffect14, useRef as useRef12, useState as useState19 } from "react";
|
|
3468
3596
|
import { createPortal } from "react-dom";
|
|
3469
3597
|
|
|
3470
3598
|
// src/components/composite/reaction-float.ts
|
|
@@ -3495,7 +3623,7 @@ function reactionPresentationStyle(eventId, progress) {
|
|
|
3495
3623
|
}
|
|
3496
3624
|
|
|
3497
3625
|
// src/components/composite/ReactionsOverlay.tsx
|
|
3498
|
-
import { Fragment as
|
|
3626
|
+
import { Fragment as Fragment11, jsx as jsx37, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3499
3627
|
function ReactionsOverlayPresentation({ reactions, elapsedMs, maxVisible = 6, className }) {
|
|
3500
3628
|
return /* @__PURE__ */ jsx37("div", { className: cn("pointer-events-none absolute inset-0 z-30 overflow-hidden", className), "aria-live": "off", children: reactions.slice(-maxVisible).map((reaction) => {
|
|
3501
3629
|
const duration = Math.max(1, reaction.expiresAtMs - reaction.occurredAtMs);
|
|
@@ -3504,12 +3632,12 @@ function ReactionsOverlayPresentation({ reactions, elapsedMs, maxVisible = 6, cl
|
|
|
3504
3632
|
}) });
|
|
3505
3633
|
}
|
|
3506
3634
|
function ReactionsOverlaySurface({ reactions, maxVisible = 6, className }) {
|
|
3507
|
-
const root =
|
|
3635
|
+
const root = useRef12(null);
|
|
3508
3636
|
return /* @__PURE__ */ jsx37("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__ */ jsx37(TileReaction, { reaction, root }, reaction.eventId)) });
|
|
3509
3637
|
}
|
|
3510
3638
|
function TileReaction({ reaction, root }) {
|
|
3511
|
-
const [host, setHost] =
|
|
3512
|
-
const emoji =
|
|
3639
|
+
const [host, setHost] = useState19(null);
|
|
3640
|
+
const emoji = useRef12(null);
|
|
3513
3641
|
const reduced = usePrefersReducedMotion();
|
|
3514
3642
|
useEffect14(() => {
|
|
3515
3643
|
const frame = root.current?.closest("[data-part=call-frame]");
|
|
@@ -3529,7 +3657,7 @@ function TileReaction({ reaction, root }) {
|
|
|
3529
3657
|
);
|
|
3530
3658
|
return () => animation.cancel();
|
|
3531
3659
|
}, [host, reduced]);
|
|
3532
|
-
return /* @__PURE__ */ jsxs21(
|
|
3660
|
+
return /* @__PURE__ */ jsxs21(Fragment11, { children: [
|
|
3533
3661
|
/* @__PURE__ */ jsxs21("span", { className: "sr-only", children: [
|
|
3534
3662
|
reaction.displayName,
|
|
3535
3663
|
" reacted ",
|
|
@@ -3554,68 +3682,68 @@ function CommandErrorAlert({ message }) {
|
|
|
3554
3682
|
}
|
|
3555
3683
|
|
|
3556
3684
|
// src/components/control-bar/ControlBar.tsx
|
|
3557
|
-
import React12, { useEffect as useEffect17, useRef as
|
|
3685
|
+
import React12, { useEffect as useEffect17, useRef as useRef14, useState as useState24 } from "react";
|
|
3558
3686
|
|
|
3559
3687
|
// src/components/device-popover/DevicePopover.tsx
|
|
3560
3688
|
import { Menu as Menu2 } from "@base-ui/react/menu";
|
|
3561
|
-
import { useEffect as useEffect15, useRef as
|
|
3689
|
+
import { useEffect as useEffect15, useRef as useRef13, useState as useState20 } from "react";
|
|
3562
3690
|
|
|
3563
3691
|
// src/components/control-bar/ShellIcon.tsx
|
|
3564
|
-
import { Fragment as
|
|
3692
|
+
import { Fragment as Fragment12, jsx as jsx39, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3565
3693
|
var GLYPHS = {
|
|
3566
|
-
flip: /* @__PURE__ */ jsxs22(
|
|
3694
|
+
flip: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3567
3695
|
/* @__PURE__ */ jsx39("path", { d: "M3 8h3l2-3h8l2 3h3v12H3z" }),
|
|
3568
3696
|
/* @__PURE__ */ jsx39("path", { d: "M8 14a4 4 0 0 1 7-2l1 1M16 10v3h-3M16 15a4 4 0 0 1-7 2l-1-1M8 19v-3h3" })
|
|
3569
3697
|
] }),
|
|
3570
|
-
mic: /* @__PURE__ */ jsxs22(
|
|
3698
|
+
mic: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3571
3699
|
/* @__PURE__ */ jsx39("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
|
|
3572
3700
|
/* @__PURE__ */ jsx39("path", { d: "M19 10v1a7 7 0 0 1-14 0v-1M12 18v4" })
|
|
3573
3701
|
] }),
|
|
3574
|
-
micOff: /* @__PURE__ */ jsx39(
|
|
3575
|
-
cam: /* @__PURE__ */ jsxs22(
|
|
3702
|
+
micOff: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M2 2l20 20M15 9.3V5a3 3 0 0 0-5.7-1.3M9 9v2a3 3 0 0 0 5.1 2.1M17 17a7 7 0 0 1-12-6v-1M19 10v1a7 7 0 0 1-.1 1.2M12 18v4" }) }),
|
|
3703
|
+
cam: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3576
3704
|
/* @__PURE__ */ jsx39("path", { d: "M16 10.5l5-3v9l-5-3z" }),
|
|
3577
3705
|
/* @__PURE__ */ jsx39("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" })
|
|
3578
3706
|
] }),
|
|
3579
|
-
camOff: /* @__PURE__ */ jsx39(
|
|
3580
|
-
hang: /* @__PURE__ */ jsx39(
|
|
3581
|
-
down: /* @__PURE__ */ jsx39(
|
|
3582
|
-
up2: /* @__PURE__ */ jsx39(
|
|
3583
|
-
right: /* @__PURE__ */ jsx39(
|
|
3584
|
-
grid: /* @__PURE__ */ jsxs22(
|
|
3707
|
+
camOff: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M2 2l20 20M10.7 6H14a2 2 0 0 1 2 2v3.3l1 1 4-2.8v8M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2" }) }),
|
|
3708
|
+
hang: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { transform: "rotate(135 12 12)", d: "M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z" }) }),
|
|
3709
|
+
down: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M6 9l6 6 6-6" }) }),
|
|
3710
|
+
up2: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M18 15l-6-6-6 6" }) }),
|
|
3711
|
+
right: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M9 18l6-6-6-6" }) }),
|
|
3712
|
+
grid: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3585
3713
|
/* @__PURE__ */ jsx39("rect", { x: "3", y: "3", width: "7.5", height: "7.5", rx: "1.5" }),
|
|
3586
3714
|
/* @__PURE__ */ jsx39("rect", { x: "13.5", y: "3", width: "7.5", height: "7.5", rx: "1.5" }),
|
|
3587
3715
|
/* @__PURE__ */ jsx39("rect", { x: "3", y: "13.5", width: "7.5", height: "7.5", rx: "1.5" }),
|
|
3588
3716
|
/* @__PURE__ */ jsx39("rect", { x: "13.5", y: "13.5", width: "7.5", height: "7.5", rx: "1.5" })
|
|
3589
3717
|
] }),
|
|
3590
|
-
spot: /* @__PURE__ */ jsxs22(
|
|
3718
|
+
spot: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3591
3719
|
/* @__PURE__ */ jsx39("rect", { x: "3", y: "3", width: "18", height: "12.5", rx: "2" }),
|
|
3592
3720
|
/* @__PURE__ */ jsx39("path", { d: "M4 20.5h3M10.5 20.5h3M17 20.5h3" })
|
|
3593
3721
|
] }),
|
|
3594
|
-
smile: /* @__PURE__ */ jsxs22(
|
|
3722
|
+
smile: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3595
3723
|
/* @__PURE__ */ jsx39("circle", { cx: "12", cy: "12", r: "9" }),
|
|
3596
3724
|
/* @__PURE__ */ jsx39("path", { d: "M8.5 14.5s1.3 1.8 3.5 1.8 3.5-1.8 3.5-1.8M9 9.5h.01M15 9.5h.01" })
|
|
3597
3725
|
] }),
|
|
3598
|
-
pen: /* @__PURE__ */ jsxs22(
|
|
3726
|
+
pen: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3599
3727
|
/* @__PURE__ */ jsx39("path", { d: "M17 3a2.85 2.85 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5z" }),
|
|
3600
3728
|
/* @__PURE__ */ jsx39("path", { d: "M15 5l4 4" })
|
|
3601
3729
|
] }),
|
|
3602
|
-
rec: /* @__PURE__ */ jsxs22(
|
|
3730
|
+
rec: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3603
3731
|
/* @__PURE__ */ jsx39("circle", { cx: "12", cy: "12", r: "9" }),
|
|
3604
3732
|
/* @__PURE__ */ jsx39("circle", { cx: "12", cy: "12", r: "3.5", fill: "currentColor" })
|
|
3605
3733
|
] }),
|
|
3606
|
-
max: /* @__PURE__ */ jsx39(
|
|
3607
|
-
min: /* @__PURE__ */ jsx39(
|
|
3608
|
-
chat: /* @__PURE__ */ jsx39(
|
|
3609
|
-
users: /* @__PURE__ */ jsxs22(
|
|
3734
|
+
max: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3" }) }),
|
|
3735
|
+
min: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3" }) }),
|
|
3736
|
+
chat: /* @__PURE__ */ jsx39(Fragment12, { children: /* @__PURE__ */ jsx39("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22z" }) }),
|
|
3737
|
+
users: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3610
3738
|
/* @__PURE__ */ jsx39("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
|
|
3611
3739
|
/* @__PURE__ */ jsx39("circle", { cx: "9", cy: "7", r: "4" }),
|
|
3612
3740
|
/* @__PURE__ */ jsx39("path", { d: "M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8" })
|
|
3613
3741
|
] }),
|
|
3614
|
-
share: /* @__PURE__ */ jsxs22(
|
|
3742
|
+
share: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3615
3743
|
/* @__PURE__ */ jsx39("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
|
|
3616
3744
|
/* @__PURE__ */ jsx39("path", { d: "M8 21h8M12 17v4M9 10l3-3 3 3M12 7v6" })
|
|
3617
3745
|
] }),
|
|
3618
|
-
shareOff: /* @__PURE__ */ jsxs22(
|
|
3746
|
+
shareOff: /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
3619
3747
|
/* @__PURE__ */ jsx39("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
|
|
3620
3748
|
/* @__PURE__ */ jsx39("path", { d: "M8 21h8M12 17v4M9.5 7.5l5 5M14.5 7.5l-5 5" })
|
|
3621
3749
|
] })
|
|
@@ -4215,9 +4343,9 @@ var CALL_SHELL_CSS = `.chalk-shell-dock {
|
|
|
4215
4343
|
`;
|
|
4216
4344
|
|
|
4217
4345
|
// src/components/device-popover/DevicePopover.tsx
|
|
4218
|
-
import { Fragment as
|
|
4346
|
+
import { Fragment as Fragment13, jsx as jsx41, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
4219
4347
|
function InputLevel({ track }) {
|
|
4220
|
-
const [level, setLevel] =
|
|
4348
|
+
const [level, setLevel] = useState20(0);
|
|
4221
4349
|
useEffect15(() => {
|
|
4222
4350
|
if (!track || track.readyState !== "live") return;
|
|
4223
4351
|
const context = new AudioContext();
|
|
@@ -4240,8 +4368,8 @@ function InputLevel({ track }) {
|
|
|
4240
4368
|
return /* @__PURE__ */ jsx41("span", { className: "chalk-shell-level", role: "meter", "aria-label": "Input level", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": level, children: /* @__PURE__ */ jsx41("i", { style: { transform: `scaleX(${level / 100})` } }) });
|
|
4241
4369
|
}
|
|
4242
4370
|
function CameraPreview({ track, mirrored, open, selectedDeviceId, captureCameraPreview }) {
|
|
4243
|
-
const video =
|
|
4244
|
-
const [
|
|
4371
|
+
const video = useRef13(null);
|
|
4372
|
+
const [unavailable2, setUnavailable] = useState20(false);
|
|
4245
4373
|
const trackEnabled = track?.enabled;
|
|
4246
4374
|
useEffect15(() => {
|
|
4247
4375
|
const element = video.current;
|
|
@@ -4276,7 +4404,7 @@ function CameraPreview({ track, mirrored, open, selectedDeviceId, captureCameraP
|
|
|
4276
4404
|
}, [track, trackEnabled, open, selectedDeviceId, captureCameraPreview]);
|
|
4277
4405
|
return /* @__PURE__ */ jsxs23("div", { className: "chalk-shell-preview", children: [
|
|
4278
4406
|
/* @__PURE__ */ jsx41("video", { ref: video, autoPlay: true, muted: true, playsInline: true, style: { transform: mirrored ? "scaleX(-1)" : void 0 } }),
|
|
4279
|
-
/* @__PURE__ */ jsx41("small", { children:
|
|
4407
|
+
/* @__PURE__ */ jsx41("small", { children: unavailable2 ? "Camera preview unavailable. Check camera access." : "Only you see this preview" })
|
|
4280
4408
|
] });
|
|
4281
4409
|
}
|
|
4282
4410
|
function DeviceSwitch({ label, checked, onChange }) {
|
|
@@ -4310,7 +4438,7 @@ function DevicePopover({
|
|
|
4310
4438
|
toggleDisabled,
|
|
4311
4439
|
busy
|
|
4312
4440
|
}) {
|
|
4313
|
-
const [open, setOpen] =
|
|
4441
|
+
const [open, setOpen] = useState20(false);
|
|
4314
4442
|
const mic = type === "mic";
|
|
4315
4443
|
const label = mic ? isActive ? "Mute microphone" : "Unmute microphone" : isActive ? "Turn off camera" : "Turn on camera";
|
|
4316
4444
|
return /* @__PURE__ */ jsxs23("div", { "data-part": `${type}-split`, className: cn("chalk-shell-split", className), "data-off": !isActive, children: [
|
|
@@ -4332,20 +4460,20 @@ function DevicePopover({
|
|
|
4332
4460
|
children: [
|
|
4333
4461
|
!mic ? /* @__PURE__ */ jsx41(CameraPreview, { track, mirrored, open, selectedDeviceId, captureCameraPreview }) : null,
|
|
4334
4462
|
/* @__PURE__ */ jsx41(ChalkMenuLabel, { children: mic ? "Microphone" : "Camera" }),
|
|
4335
|
-
devices.length ? devices.map((
|
|
4336
|
-
|
|
4337
|
-
mic && selectedDeviceId ===
|
|
4338
|
-
] }) },
|
|
4339
|
-
mic ? /* @__PURE__ */ jsxs23(
|
|
4463
|
+
devices.length ? devices.map((device2) => /* @__PURE__ */ jsx41(ChalkMenuItem, { checked: selectedDeviceId === device2.deviceId, onClick: () => onDeviceChange(device2.deviceId), closeOnClick: false, children: /* @__PURE__ */ jsxs23("span", { className: "chalk-shell-device-label", children: [
|
|
4464
|
+
device2.label || (mic ? "Microphone" : "Camera"),
|
|
4465
|
+
mic && selectedDeviceId === device2.deviceId ? /* @__PURE__ */ jsx41(InputLevel, { track }) : null
|
|
4466
|
+
] }) }, device2.deviceId)) : /* @__PURE__ */ jsx41(ChalkMenuItem, { disabled: true, children: "No devices found" }),
|
|
4467
|
+
mic ? /* @__PURE__ */ jsxs23(Fragment13, { children: [
|
|
4340
4468
|
/* @__PURE__ */ jsx41(DeviceSwitch, { label: "Noise suppression", checked: noiseSuppression, onChange: onNoiseSuppressionChange }),
|
|
4341
4469
|
/* @__PURE__ */ jsx41(Menu2.Separator, { className: "chalk-shell-menu-separator" }),
|
|
4342
4470
|
/* @__PURE__ */ jsx41(ChalkMenuLabel, { children: "Speaker" }),
|
|
4343
|
-
secondaryDevices?.map((
|
|
4471
|
+
secondaryDevices?.map((device2) => /* @__PURE__ */ jsx41(ChalkMenuItem, { checked: selectedSecondaryDeviceId === device2.deviceId, onClick: () => onSecondaryDeviceChange?.(device2.deviceId), closeOnClick: false, children: device2.label || "Speaker" }, device2.deviceId)),
|
|
4344
4472
|
/* @__PURE__ */ jsxs23(ChalkMenuItem, { disabled: !onTestSpeaker, onClick: onTestSpeaker, closeOnClick: false, children: [
|
|
4345
4473
|
/* @__PURE__ */ jsx41(VolumeHighIcon, {}),
|
|
4346
4474
|
"Test speaker"
|
|
4347
4475
|
] })
|
|
4348
|
-
] }) : /* @__PURE__ */ jsxs23(
|
|
4476
|
+
] }) : /* @__PURE__ */ jsxs23(Fragment13, { children: [
|
|
4349
4477
|
/* @__PURE__ */ jsx41(Menu2.Separator, { className: "chalk-shell-menu-separator" }),
|
|
4350
4478
|
/* @__PURE__ */ jsx41(DeviceSwitch, { label: "Mirror my video", checked: mirrored, onChange: onMirrorChange })
|
|
4351
4479
|
] })
|
|
@@ -4378,11 +4506,11 @@ function LeaveMenu({ onLeave, onEndForEveryone, renderButton }) {
|
|
|
4378
4506
|
}
|
|
4379
4507
|
|
|
4380
4508
|
// src/components/control-bar/DockLayout.tsx
|
|
4381
|
-
import { useState as
|
|
4382
|
-
import { Fragment as
|
|
4509
|
+
import { useState as useState21 } from "react";
|
|
4510
|
+
import { Fragment as Fragment14, jsx as jsx44, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4383
4511
|
function DockLayout({ layout, onLayoutChange, children }) {
|
|
4384
|
-
const [open, setOpen] =
|
|
4385
|
-
return /* @__PURE__ */ jsxs26(
|
|
4512
|
+
const [open, setOpen] = useState21(false);
|
|
4513
|
+
return /* @__PURE__ */ jsxs26(Fragment14, { children: [
|
|
4386
4514
|
/* @__PURE__ */ jsx44(ChalkIconButton, { size: "lg", "aria-label": "More options", "aria-haspopup": "dialog", "aria-expanded": open, onClick: () => setOpen(true), children: /* @__PURE__ */ jsx44("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__ */ jsx44("path", { "data-part": "dock-more-glyph", d: "M5 12h.01M12 12h.01M19 12h.01", strokeWidth: "3" }) }) }),
|
|
4387
4515
|
/* @__PURE__ */ jsx44(ChalkSheet, { title: "More options", open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs26(
|
|
4388
4516
|
"div",
|
|
@@ -4423,25 +4551,25 @@ function DockLayout({ layout, onLayoutChange, children }) {
|
|
|
4423
4551
|
|
|
4424
4552
|
// src/components/control-bar/ShareControl.tsx
|
|
4425
4553
|
import { Menu as Menu4 } from "@base-ui/react/menu";
|
|
4426
|
-
import { useState as
|
|
4427
|
-
import { Fragment as
|
|
4554
|
+
import { useState as useState22 } from "react";
|
|
4555
|
+
import { Fragment as Fragment15, jsx as jsx45, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4428
4556
|
function SourceIcon({ source }) {
|
|
4429
|
-
return /* @__PURE__ */ jsx45("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__ */ jsxs27(
|
|
4557
|
+
return /* @__PURE__ */ jsx45("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__ */ jsxs27(Fragment15, { children: [
|
|
4430
4558
|
/* @__PURE__ */ jsx45("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
|
|
4431
4559
|
/* @__PURE__ */ jsx45("path", { d: "M8 21h8M12 17v4" })
|
|
4432
|
-
] }) : source === "window" ? /* @__PURE__ */ jsxs27(
|
|
4560
|
+
] }) : source === "window" ? /* @__PURE__ */ jsxs27(Fragment15, { children: [
|
|
4433
4561
|
/* @__PURE__ */ jsx45("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2" }),
|
|
4434
4562
|
/* @__PURE__ */ jsx45("path", { d: "M3 9h18M6.5 6.5h.01M9 6.5h.01" })
|
|
4435
|
-
] }) : /* @__PURE__ */ jsxs27(
|
|
4563
|
+
] }) : /* @__PURE__ */ jsxs27(Fragment15, { children: [
|
|
4436
4564
|
/* @__PURE__ */ jsx45("path", { d: "M3 20V7a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v10z" }),
|
|
4437
4565
|
/* @__PURE__ */ jsx45("path", { d: "M3 11h18" })
|
|
4438
4566
|
] }) });
|
|
4439
4567
|
}
|
|
4440
4568
|
function ShareControl({ sharing, onToggle, onStart, disabled = false, startDisabled = false }) {
|
|
4441
|
-
const [surface, setSurface] =
|
|
4442
|
-
const [audio, setAudio] =
|
|
4443
|
-
const [replace, setReplace] =
|
|
4444
|
-
const
|
|
4569
|
+
const [surface, setSurface] = useState22("window");
|
|
4570
|
+
const [audio, setAudio] = useState22(true);
|
|
4571
|
+
const [replace, setReplace] = useState22(false);
|
|
4572
|
+
const start2 = (next) => {
|
|
4445
4573
|
if (disabled || startDisabled) return;
|
|
4446
4574
|
setSurface(next);
|
|
4447
4575
|
setReplace(false);
|
|
@@ -4451,7 +4579,7 @@ function ShareControl({ sharing, onToggle, onStart, disabled = false, startDisab
|
|
|
4451
4579
|
/* @__PURE__ */ jsx45(
|
|
4452
4580
|
ChalkTooltip,
|
|
4453
4581
|
{
|
|
4454
|
-
trigger: /* @__PURE__ */ jsx45("button", { type: "button", className: "chalk-shell-main", disabled, "aria-label": sharing ? "Stop sharing" : "Share screen", "aria-pressed": sharing, onClick: () => sharing || !onStart ? onToggle?.() :
|
|
4582
|
+
trigger: /* @__PURE__ */ jsx45("button", { type: "button", className: "chalk-shell-main", disabled, "aria-label": sharing ? "Stop sharing" : "Share screen", "aria-pressed": sharing, onClick: () => sharing || !onStart ? onToggle?.() : start2(surface), children: /* @__PURE__ */ jsx45(ShellIcon, { name: sharing ? "shareOff" : "share" }) }),
|
|
4455
4583
|
children: sharing ? "Stop sharing" : "Share screen"
|
|
4456
4584
|
}
|
|
4457
4585
|
),
|
|
@@ -4461,16 +4589,16 @@ function ShareControl({ sharing, onToggle, onStart, disabled = false, startDisab
|
|
|
4461
4589
|
side: "top",
|
|
4462
4590
|
className: "chalk-device-menu",
|
|
4463
4591
|
trigger: /* @__PURE__ */ jsx45("button", { type: "button", className: "chalk-shell-caret", disabled: disabled || startDisabled, "aria-label": "Share options", children: /* @__PURE__ */ jsx45(ShellIcon, { name: "down" }) }),
|
|
4464
|
-
children: sharing && !replace ? /* @__PURE__ */ jsxs27(
|
|
4592
|
+
children: sharing && !replace ? /* @__PURE__ */ jsxs27(Fragment15, { children: [
|
|
4465
4593
|
/* @__PURE__ */ jsx45(ChalkMenuLabel, { children: "Sharing your screen" }),
|
|
4466
4594
|
/* @__PURE__ */ jsx45(Menu4.Item, { className: "chalk-menu-item", disabled: disabled || startDisabled, closeOnClick: false, onClick: () => setReplace(true), children: "Share something else" }),
|
|
4467
4595
|
/* @__PURE__ */ jsx45(ChalkMenuItem, { onClick: onToggle, children: "Stop sharing" })
|
|
4468
|
-
] }) : /* @__PURE__ */ jsxs27(
|
|
4596
|
+
] }) : /* @__PURE__ */ jsxs27(Fragment15, { children: [
|
|
4469
4597
|
[
|
|
4470
4598
|
{ value: "monitor", label: "Entire screen", description: "Everything on one display" },
|
|
4471
4599
|
{ value: "window", label: "Window", description: "One app, like Slides or Figma" },
|
|
4472
4600
|
{ value: "browser", label: "Browser tab", description: "One tab, and its sound if you like" }
|
|
4473
|
-
].map((option) => /* @__PURE__ */ jsxs27(Menu4.Item, { className: "chalk-menu-item chalk-shell-source", disabled: disabled || startDisabled, role: "menuitemradio", "aria-label": option.label, "aria-checked": surface === option.value, onClick: () =>
|
|
4601
|
+
].map((option) => /* @__PURE__ */ jsxs27(Menu4.Item, { className: "chalk-menu-item chalk-shell-source", disabled: disabled || startDisabled, role: "menuitemradio", "aria-label": option.label, "aria-checked": surface === option.value, onClick: () => start2(option.value), children: [
|
|
4474
4602
|
/* @__PURE__ */ jsx45(SourceIcon, { source: option.value }),
|
|
4475
4603
|
/* @__PURE__ */ jsxs27("span", { className: "chalk-shell-device-label", children: [
|
|
4476
4604
|
/* @__PURE__ */ jsx45("span", { children: option.label }),
|
|
@@ -4478,7 +4606,7 @@ function ShareControl({ sharing, onToggle, onStart, disabled = false, startDisab
|
|
|
4478
4606
|
] }),
|
|
4479
4607
|
/* @__PURE__ */ jsx45("span", { className: "chalk-menu-check", "aria-hidden": "true", children: surface === option.value ? /* @__PURE__ */ jsx45("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx45("path", { d: "M20 6L9 17l-5-5" }) }) : null })
|
|
4480
4608
|
] }, option.value)),
|
|
4481
|
-
surface === "browser" ? /* @__PURE__ */ jsxs27(
|
|
4609
|
+
surface === "browser" ? /* @__PURE__ */ jsxs27(Fragment15, { children: [
|
|
4482
4610
|
/* @__PURE__ */ jsx45(Menu4.Separator, { className: "chalk-shell-menu-separator" }),
|
|
4483
4611
|
/* @__PURE__ */ jsxs27(Menu4.CheckboxItem, { className: "chalk-menu-item", checked: audio, onCheckedChange: setAudio, closeOnClick: false, children: [
|
|
4484
4612
|
/* @__PURE__ */ jsxs27("span", { className: "chalk-shell-device-label", children: [
|
|
@@ -4495,19 +4623,7 @@ function ShareControl({ sharing, onToggle, onStart, disabled = false, startDisab
|
|
|
4495
4623
|
}
|
|
4496
4624
|
|
|
4497
4625
|
// src/components/control-bar/control-bar-behavior.ts
|
|
4498
|
-
import { useCallback as useCallback5, useEffect as useEffect16, useMemo as useMemo9, useState as
|
|
4499
|
-
|
|
4500
|
-
// src/components/control-bar/command-failure.ts
|
|
4501
|
-
import { SpaceClientError } from "@q9labsai/chalk-client";
|
|
4502
|
-
function commandFailure(cause) {
|
|
4503
|
-
return cause instanceof SpaceClientError ? cause : new SpaceClientError({
|
|
4504
|
-
code: "client.internal_error",
|
|
4505
|
-
recoverable: false,
|
|
4506
|
-
message: cause instanceof Error ? cause.message : "This command could not be completed."
|
|
4507
|
-
});
|
|
4508
|
-
}
|
|
4509
|
-
|
|
4510
|
-
// src/components/control-bar/control-bar-behavior.ts
|
|
4626
|
+
import { useCallback as useCallback5, useEffect as useEffect16, useMemo as useMemo9, useState as useState23 } from "react";
|
|
4511
4627
|
var DEFAULT_CONTROL_BAR_BUTTONS = ["mic", "video", "screenshare", "record", "whiteboard", "handraise", "leave", "participants", "chat", "reactions"];
|
|
4512
4628
|
var EMPTY_DETECTED_DEVICES = {
|
|
4513
4629
|
audioinput: [],
|
|
@@ -4517,10 +4633,10 @@ var EMPTY_DETECTED_DEVICES = {
|
|
|
4517
4633
|
function mergeDevices(...deviceGroups) {
|
|
4518
4634
|
const devicesById = /* @__PURE__ */ new Map();
|
|
4519
4635
|
for (const deviceGroup of deviceGroups) {
|
|
4520
|
-
for (const
|
|
4521
|
-
const existing = devicesById.get(
|
|
4522
|
-
if (!existing || !existing.label &&
|
|
4523
|
-
devicesById.set(
|
|
4636
|
+
for (const device2 of deviceGroup ?? []) {
|
|
4637
|
+
const existing = devicesById.get(device2.deviceId);
|
|
4638
|
+
if (!existing || !existing.label && device2.label) {
|
|
4639
|
+
devicesById.set(device2.deviceId, device2);
|
|
4524
4640
|
}
|
|
4525
4641
|
}
|
|
4526
4642
|
}
|
|
@@ -4544,7 +4660,7 @@ function useControlBarSurfaceBehavior({
|
|
|
4544
4660
|
detectDevices = true
|
|
4545
4661
|
}) {
|
|
4546
4662
|
const themeVariables = useMemo9(() => getParticipantThemeVariables(participantColorSeed, participantGradientPreference), [participantColorSeed, participantGradientPreference]);
|
|
4547
|
-
const [detectedDevices, setDetectedDevices] =
|
|
4663
|
+
const [detectedDevices, setDetectedDevices] = useState23(EMPTY_DETECTED_DEVICES);
|
|
4548
4664
|
const buttonsToRender = buttons ?? DEFAULT_CONTROL_BAR_BUTTONS;
|
|
4549
4665
|
useEffect16(() => {
|
|
4550
4666
|
if (!detectDevices || density !== "comfortable" || !navigator.mediaDevices?.enumerateDevices) return;
|
|
@@ -4554,9 +4670,9 @@ function useControlBarSurfaceBehavior({
|
|
|
4554
4670
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
4555
4671
|
if (!cancelled) {
|
|
4556
4672
|
setDetectedDevices({
|
|
4557
|
-
audioinput: devices.filter((
|
|
4558
|
-
audiooutput: devices.filter((
|
|
4559
|
-
videoinput: devices.filter((
|
|
4673
|
+
audioinput: devices.filter((device2) => device2.kind === "audioinput"),
|
|
4674
|
+
audiooutput: devices.filter((device2) => device2.kind === "audiooutput"),
|
|
4675
|
+
videoinput: devices.filter((device2) => device2.kind === "videoinput")
|
|
4560
4676
|
});
|
|
4561
4677
|
}
|
|
4562
4678
|
} catch {
|
|
@@ -4594,7 +4710,7 @@ function useConnectedControlBarBehavior(props) {
|
|
|
4594
4710
|
const canPublishScreen = useCan("publishScreen");
|
|
4595
4711
|
const canSendReaction = useCan("sendReaction");
|
|
4596
4712
|
const canRaiseHand = useCan("raiseHand");
|
|
4597
|
-
const canDrawWhiteboard =
|
|
4713
|
+
const canDrawWhiteboard = useCanDrawWhiteboard();
|
|
4598
4714
|
const canManageRecording = useCan("manageRecording");
|
|
4599
4715
|
const live = useConnection().status === "live";
|
|
4600
4716
|
const microphoneEnabled = media.local.microphone.state === "enabled";
|
|
@@ -4603,18 +4719,26 @@ function useConnectedControlBarBehavior(props) {
|
|
|
4603
4719
|
const recordingStatus = recording.current?.status;
|
|
4604
4720
|
const isRecording = recordingStatus === "recording" || recordingStatus === "stopping";
|
|
4605
4721
|
const isRecordingPending = recordingStatus === "starting" || recordingStatus === "stopping";
|
|
4606
|
-
const [noiseSuppression, setNoiseSuppression] =
|
|
4607
|
-
const [commandError, setCommandError] =
|
|
4722
|
+
const [noiseSuppression, setNoiseSuppression] = useState23(true);
|
|
4723
|
+
const [commandError, setCommandError] = useState23(null);
|
|
4724
|
+
const [commandSource, setCommandSource] = useState23();
|
|
4725
|
+
const [commandAction, setCommandAction] = useState23();
|
|
4608
4726
|
const run = useCallback5(
|
|
4609
|
-
async (command, source) => {
|
|
4727
|
+
async (command, source, action) => {
|
|
4610
4728
|
setCommandError(null);
|
|
4611
|
-
|
|
4729
|
+
setCommandSource(void 0);
|
|
4730
|
+
setCommandAction(void 0);
|
|
4731
|
+
props.onCommandError?.(null, source === "speaker" ? void 0 : source, source, action);
|
|
4612
4732
|
try {
|
|
4613
4733
|
await command();
|
|
4614
4734
|
} catch (cause) {
|
|
4615
4735
|
const failure = commandFailure(cause);
|
|
4616
|
-
if (!props.onCommandError)
|
|
4617
|
-
|
|
4736
|
+
if (!props.onCommandError) {
|
|
4737
|
+
setCommandError(failure);
|
|
4738
|
+
setCommandSource(source);
|
|
4739
|
+
setCommandAction(action);
|
|
4740
|
+
}
|
|
4741
|
+
props.onCommandError?.(failure, source === "speaker" ? void 0 : source, source, action, command);
|
|
4618
4742
|
}
|
|
4619
4743
|
},
|
|
4620
4744
|
[props.onCommandError]
|
|
@@ -4637,9 +4761,9 @@ function useConnectedControlBarBehavior(props) {
|
|
|
4637
4761
|
if (button === "record") return canManageRecording;
|
|
4638
4762
|
return true;
|
|
4639
4763
|
});
|
|
4640
|
-
const audioInputDevices = media.devices.microphones.map((
|
|
4641
|
-
const audioOutputDevices = media.devices.speakers.map((
|
|
4642
|
-
const videoInputDevices = media.devices.cameras.map((
|
|
4764
|
+
const audioInputDevices = media.devices.microphones.map((device2) => ({ ...device2, kind: "audioinput" }));
|
|
4765
|
+
const audioOutputDevices = media.devices.speakers.map((device2) => ({ ...device2, kind: "audiooutput" }));
|
|
4766
|
+
const videoInputDevices = media.devices.cameras.map((device2) => ({ ...device2, kind: "videoinput" }));
|
|
4643
4767
|
const surfaceProps = {
|
|
4644
4768
|
...props,
|
|
4645
4769
|
detectDevices: false,
|
|
@@ -4656,9 +4780,13 @@ function useConnectedControlBarBehavior(props) {
|
|
|
4656
4780
|
await media.local.microphone.track?.applyConstraints({ noiseSuppression: enabled });
|
|
4657
4781
|
setNoiseSuppression(enabled);
|
|
4658
4782
|
}, "microphone") : void 0,
|
|
4659
|
-
onStartScreenShare: (options) => void run(
|
|
4660
|
-
|
|
4661
|
-
|
|
4783
|
+
onStartScreenShare: (options) => void run(
|
|
4784
|
+
async () => {
|
|
4785
|
+
await client.media.setScreenShareEnabled(true, options);
|
|
4786
|
+
},
|
|
4787
|
+
"screen",
|
|
4788
|
+
"start"
|
|
4789
|
+
),
|
|
4662
4790
|
shareUrl: props.shareUrl,
|
|
4663
4791
|
isMuted: !microphoneEnabled,
|
|
4664
4792
|
microphonePending: media.local.microphone.state === "requesting",
|
|
@@ -4680,39 +4808,43 @@ function useConnectedControlBarBehavior(props) {
|
|
|
4680
4808
|
selectedAudioInput: media.selection.microphone ?? void 0,
|
|
4681
4809
|
selectedAudioOutput: media.selection.speaker ?? void 0,
|
|
4682
4810
|
selectedVideoInput: media.selection.camera ?? void 0,
|
|
4683
|
-
onTestSpeaker: () => void run(
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4811
|
+
onTestSpeaker: () => void run(
|
|
4812
|
+
async () => {
|
|
4813
|
+
const context = new AudioContext();
|
|
4814
|
+
const oscillator = context.createOscillator();
|
|
4815
|
+
const gain = context.createGain();
|
|
4816
|
+
const output = context.createMediaStreamDestination();
|
|
4817
|
+
const audio = new Audio();
|
|
4818
|
+
try {
|
|
4819
|
+
if (media.selection.speaker && audio.setSinkId) await audio.setSinkId(media.selection.speaker);
|
|
4820
|
+
audio.srcObject = output.stream;
|
|
4821
|
+
oscillator.connect(gain).connect(output);
|
|
4822
|
+
gain.gain.value = 0.15;
|
|
4823
|
+
oscillator.frequency.value = 440;
|
|
4824
|
+
oscillator.start();
|
|
4825
|
+
await audio.play();
|
|
4826
|
+
await new Promise((resolve) => {
|
|
4827
|
+
oscillator.onended = () => resolve();
|
|
4828
|
+
oscillator.stop(context.currentTime + 0.4);
|
|
4829
|
+
});
|
|
4830
|
+
} finally {
|
|
4831
|
+
audio.pause();
|
|
4832
|
+
audio.srcObject = null;
|
|
4833
|
+
oscillator.disconnect();
|
|
4834
|
+
gain.disconnect();
|
|
4835
|
+
output.stream.getTracks().forEach((track) => track.stop());
|
|
4836
|
+
await context.close();
|
|
4837
|
+
}
|
|
4838
|
+
},
|
|
4839
|
+
"speaker",
|
|
4840
|
+
"test"
|
|
4841
|
+
),
|
|
4842
|
+
onToggleMute: () => void run(() => client.media.setMicrophoneEnabled(!microphoneEnabled), "microphone", microphoneEnabled ? "stop" : "start"),
|
|
4843
|
+
onToggleVideo: () => void run(() => client.media.setCameraEnabled(!cameraEnabled), "camera", cameraEnabled ? "stop" : "start"),
|
|
4844
|
+
onAudioInputChange: (deviceId) => void run(() => client.media.selectMicrophone(deviceId), "microphone", "select"),
|
|
4845
|
+
onAudioOutputChange: (deviceId) => void run(() => client.media.selectSpeaker(deviceId), "speaker", "select"),
|
|
4846
|
+
onVideoInputChange: (deviceId) => void run(() => client.media.selectCamera(deviceId), "camera", "select"),
|
|
4847
|
+
onToggleScreenShare: () => void run(() => client.media.setScreenShareEnabled(!screenSharing), "screen", screenSharing ? "stop" : "start"),
|
|
4716
4848
|
onToggleRecording: () => void run(() => recordingStatus === "recording" ? client.recording.stop() : client.recording.start()),
|
|
4717
4849
|
onToggleChat: props.onToggleChat,
|
|
4718
4850
|
onToggleParticipants: props.onToggleParticipants,
|
|
@@ -4722,7 +4854,7 @@ function useConnectedControlBarBehavior(props) {
|
|
|
4722
4854
|
onLeft: leave,
|
|
4723
4855
|
onEndForEveryone: props.onEndForEveryone
|
|
4724
4856
|
};
|
|
4725
|
-
return { surfaceProps, commandError };
|
|
4857
|
+
return { surfaceProps, commandError, commandSource, commandAction };
|
|
4726
4858
|
}
|
|
4727
4859
|
|
|
4728
4860
|
// src/components/control-bar/next-camera.ts
|
|
@@ -4732,26 +4864,26 @@ function facing(label) {
|
|
|
4732
4864
|
return void 0;
|
|
4733
4865
|
}
|
|
4734
4866
|
function nextCamera(devices, selectedId, track) {
|
|
4735
|
-
const
|
|
4736
|
-
const currentId = selectedId ??
|
|
4737
|
-
const index = devices.findIndex((
|
|
4867
|
+
const settings2 = track?.getSettings();
|
|
4868
|
+
const currentId = selectedId ?? settings2?.deviceId;
|
|
4869
|
+
const index = devices.findIndex((device2) => device2.deviceId === currentId);
|
|
4738
4870
|
const current = devices[index];
|
|
4739
4871
|
const capabilities = track?.getCapabilities?.().facingMode;
|
|
4740
|
-
const currentFacing = (current && facing(current.label)) ??
|
|
4872
|
+
const currentFacing = (current && facing(current.label)) ?? settings2?.facingMode ?? (capabilities?.length === 1 ? capabilities[0] : void 0);
|
|
4741
4873
|
const opposite = currentFacing === "user" ? "environment" : currentFacing === "environment" ? "user" : void 0;
|
|
4742
|
-
return opposite && devices.find((
|
|
4874
|
+
return opposite && devices.find((device2) => device2.deviceId !== currentId && facing(device2.label) === opposite) || devices[(index + 1) % devices.length];
|
|
4743
4875
|
}
|
|
4744
4876
|
|
|
4745
4877
|
// src/components/control-bar/ControlBar.tsx
|
|
4746
|
-
import { Fragment as
|
|
4878
|
+
import { Fragment as Fragment16, jsx as jsx46, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4747
4879
|
function ControlBarPresentation(props) {
|
|
4748
4880
|
return /* @__PURE__ */ jsx46(ControlBarSurface, { ...props, detectDevices: props.displayOnly ? false : props.detectDevices });
|
|
4749
4881
|
}
|
|
4750
4882
|
var ControlBarSurface = React12.memo((props) => {
|
|
4751
4883
|
const { buttonsToRender, effectiveAudioInputDevices, effectiveAudioOutputDevices, effectiveVideoInputDevices, showLeave } = useControlBarSurfaceBehavior({ ...props, density: props.density ?? "comfortable", detectDevices: props.detectDevices ?? true });
|
|
4752
|
-
const dock =
|
|
4753
|
-
const [fullscreen, setFullscreen] =
|
|
4754
|
-
const [canCaptureDisplay, setCanCaptureDisplay] =
|
|
4884
|
+
const dock = useRef14(null);
|
|
4885
|
+
const [fullscreen, setFullscreen] = useState24(false);
|
|
4886
|
+
const [canCaptureDisplay, setCanCaptureDisplay] = useState24(false);
|
|
4755
4887
|
useEffect17(() => setCanCaptureDisplay(typeof navigator.mediaDevices?.getDisplayMedia === "function"), []);
|
|
4756
4888
|
useEffect17(() => {
|
|
4757
4889
|
const changed = () => setFullscreen(Boolean(document.fullscreenElement));
|
|
@@ -4894,19 +5026,19 @@ var ControlBarSurface = React12.memo((props) => {
|
|
|
4894
5026
|
});
|
|
4895
5027
|
ControlBarSurface.displayName = "ControlBarSurface";
|
|
4896
5028
|
function ControlBar(props) {
|
|
4897
|
-
const { surfaceProps, commandError } = useConnectedControlBarBehavior(props);
|
|
4898
|
-
return /* @__PURE__ */ jsxs28(
|
|
5029
|
+
const { surfaceProps, commandError, commandSource, commandAction } = useConnectedControlBarBehavior(props);
|
|
5030
|
+
return /* @__PURE__ */ jsxs28(Fragment16, { children: [
|
|
4899
5031
|
/* @__PURE__ */ jsx46(ControlBarSurface, { ...surfaceProps }),
|
|
4900
|
-
!props.onCommandError ? /* @__PURE__ */ jsx46(CommandErrorAlert, { message: commandError
|
|
5032
|
+
!props.onCommandError ? /* @__PURE__ */ jsx46(CommandErrorAlert, { message: commandError ? commandFailureMessage(commandError, commandSource, commandAction) : void 0 }) : null
|
|
4901
5033
|
] });
|
|
4902
5034
|
}
|
|
4903
5035
|
|
|
4904
5036
|
// src/components/participants-panel/ParticipantsPanel.tsx
|
|
4905
5037
|
import { Popover as Popover3 } from "@base-ui/react/popover";
|
|
4906
|
-
import React13, { useMemo as useMemo10, useState as
|
|
5038
|
+
import React13, { useMemo as useMemo10, useState as useState26 } from "react";
|
|
4907
5039
|
|
|
4908
5040
|
// src/components/participants-panel/participant-row.tsx
|
|
4909
|
-
import { useState as
|
|
5041
|
+
import { useState as useState25, useRef as useRef15, useEffect as useEffect18 } from "react";
|
|
4910
5042
|
import { Popover as Popover2 } from "@base-ui/react/popover";
|
|
4911
5043
|
|
|
4912
5044
|
// src/components/participants-panel/participant-options-menu-contract.ts
|
|
@@ -4928,7 +5060,7 @@ function runParticipantAction(action, onClose, onCommandError) {
|
|
|
4928
5060
|
}
|
|
4929
5061
|
|
|
4930
5062
|
// src/components/participants-panel/participant-options-menu.tsx
|
|
4931
|
-
import { Fragment as
|
|
5063
|
+
import { Fragment as Fragment17, jsx as jsx47, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4932
5064
|
function ParticipantOptionsMenu({
|
|
4933
5065
|
participant,
|
|
4934
5066
|
variant,
|
|
@@ -4953,7 +5085,7 @@ function ParticipantOptionsMenu({
|
|
|
4953
5085
|
const volumeMuted = volume <= 0;
|
|
4954
5086
|
const menuItemClassName = cn("flex w-full items-center gap-3 rounded-[8px] px-3 py-2.5 text-left text-sm font-medium text-[var(--chalk-app-text)] transition-colors hover:bg-[var(--chalk-app-control-hover)]");
|
|
4955
5087
|
const dividerClassName = "my-1.5 h-px bg-[var(--chalk-app-line)]";
|
|
4956
|
-
return /* @__PURE__ */ jsxs29(
|
|
5088
|
+
return /* @__PURE__ */ jsxs29(Fragment17, { children: [
|
|
4957
5089
|
hasLocalActions ? /* @__PURE__ */ jsxs29("button", { type: "button", onClick: onEditName, className: menuItemClassName, children: [
|
|
4958
5090
|
/* @__PURE__ */ jsx47(Edit02Icon, { className: "h-4 w-4" }),
|
|
4959
5091
|
"Edit Name"
|
|
@@ -4978,7 +5110,7 @@ function ParticipantOptionsMenu({
|
|
|
4978
5110
|
)
|
|
4979
5111
|
] }) : null,
|
|
4980
5112
|
hasVolumeControl && hasManageActions ? /* @__PURE__ */ jsx47("div", { className: dividerClassName }) : null,
|
|
4981
|
-
hasManageActions ? /* @__PURE__ */ jsxs29(
|
|
5113
|
+
hasManageActions ? /* @__PURE__ */ jsxs29(Fragment17, { children: [
|
|
4982
5114
|
!participant.isMuted && onMuteParticipant ? /* @__PURE__ */ jsxs29(
|
|
4983
5115
|
"button",
|
|
4984
5116
|
{
|
|
@@ -5081,10 +5213,10 @@ function ParticipantRow({
|
|
|
5081
5213
|
onMenuToggle,
|
|
5082
5214
|
onMenuClose
|
|
5083
5215
|
}) {
|
|
5084
|
-
const [isEditing, setIsEditing] =
|
|
5085
|
-
const [editName, setEditName] =
|
|
5086
|
-
const inputRef =
|
|
5087
|
-
const rootRef =
|
|
5216
|
+
const [isEditing, setIsEditing] = useState25(false);
|
|
5217
|
+
const [editName, setEditName] = useState25(participant.displayName);
|
|
5218
|
+
const inputRef = useRef15(null);
|
|
5219
|
+
const rootRef = useRef15(null);
|
|
5088
5220
|
const hasVolumeControl = !!participantVolumes && !!onParticipantVolumeChange;
|
|
5089
5221
|
const showMenuButton = canManageParticipants || hasVolumeControl || participant.isLocal && !!onUpdateDisplayName;
|
|
5090
5222
|
useEffect18(() => {
|
|
@@ -5182,7 +5314,7 @@ function ParticipantRow({
|
|
|
5182
5314
|
}
|
|
5183
5315
|
|
|
5184
5316
|
// src/components/participants-panel/ParticipantsPanel.tsx
|
|
5185
|
-
import { Fragment as
|
|
5317
|
+
import { Fragment as Fragment18, jsx as jsx49, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5186
5318
|
var ParticipantsPanelSurface = React13.memo(
|
|
5187
5319
|
({
|
|
5188
5320
|
participants,
|
|
@@ -5208,10 +5340,10 @@ var ParticipantsPanelSurface = React13.memo(
|
|
|
5208
5340
|
participantGradientPreference,
|
|
5209
5341
|
generatedAvatars = true
|
|
5210
5342
|
}) => {
|
|
5211
|
-
const [query, setQuery] =
|
|
5212
|
-
const [activeMenuId, setActiveMenuId] =
|
|
5213
|
-
const [muting, setMuting] =
|
|
5214
|
-
const [error, setError] =
|
|
5343
|
+
const [query, setQuery] = useState26("");
|
|
5344
|
+
const [activeMenuId, setActiveMenuId] = useState26(null);
|
|
5345
|
+
const [muting, setMuting] = useState26(false);
|
|
5346
|
+
const [error, setError] = useState26(null);
|
|
5215
5347
|
const filtered = participants.filter((person) => person.displayName.toLocaleLowerCase().includes(query.trim().toLocaleLowerCase()));
|
|
5216
5348
|
const raised = participants.filter((person) => person.isHandRaised);
|
|
5217
5349
|
const unmutedCount = participants.filter((person) => !person.isLocal && !person.isMuted).length;
|
|
@@ -5257,11 +5389,11 @@ var ParticipantsPanelSurface = React13.memo(
|
|
|
5257
5389
|
/* @__PURE__ */ jsx49(Search01Icon, { "aria-hidden": "true" }),
|
|
5258
5390
|
/* @__PURE__ */ jsx49("input", { "aria-label": "Search people", placeholder: "Search people", value: query, onChange: (event) => setQuery(event.target.value) })
|
|
5259
5391
|
] }) : null,
|
|
5260
|
-
canManageAdmission && admissionEnabled && admissionCount > 0 ? /* @__PURE__ */ jsxs31(
|
|
5392
|
+
canManageAdmission && admissionEnabled && admissionCount > 0 ? /* @__PURE__ */ jsxs31(Fragment18, { children: [
|
|
5261
5393
|
/* @__PURE__ */ jsx49(AdmissionPanel, { inline: true }),
|
|
5262
5394
|
/* @__PURE__ */ jsx49("h3", { className: "call-people-section", children: "In the call" })
|
|
5263
5395
|
] }) : null,
|
|
5264
|
-
!query && raised.length > 1 ? /* @__PURE__ */ jsxs31(
|
|
5396
|
+
!query && raised.length > 1 ? /* @__PURE__ */ jsxs31(Fragment18, { children: [
|
|
5265
5397
|
/* @__PURE__ */ jsx49("h3", { className: "call-people-section", children: "Raised hands" }),
|
|
5266
5398
|
raised.map((person) => /* @__PURE__ */ jsxs31("div", { className: "call-raised-row", children: [
|
|
5267
5399
|
person.handOrder !== void 0 ? /* @__PURE__ */ jsx49("span", { className: "call-hand-number", children: person.handOrder }) : null,
|
|
@@ -5314,7 +5446,7 @@ var ParticipantsPanel = React13.memo((props) => {
|
|
|
5314
5446
|
const canRemoveParticipants = useCan("removeParticipant");
|
|
5315
5447
|
const canManageAdmission = useCan("manageAdmission");
|
|
5316
5448
|
const contextVolumeState = useParticipantVolumeContext();
|
|
5317
|
-
const [localVolumes, setLocalVolumes] =
|
|
5449
|
+
const [localVolumes, setLocalVolumes] = useState26(/* @__PURE__ */ new Map());
|
|
5318
5450
|
const isControlled = props.participantVolumes !== void 0 && props.onParticipantVolumeChange !== void 0;
|
|
5319
5451
|
const participantVolumes = isControlled ? props.participantVolumes : contextVolumeState?.volumes ?? localVolumes;
|
|
5320
5452
|
const onParticipantVolumeChange = isControlled ? props.onParticipantVolumeChange : contextVolumeState?.setVolume ?? ((participantId, volume) => setLocalVolumes((current) => {
|
|
@@ -5365,15 +5497,9 @@ var ParticipantsPanel = React13.memo((props) => {
|
|
|
5365
5497
|
});
|
|
5366
5498
|
ParticipantsPanel.displayName = "ParticipantsPanel";
|
|
5367
5499
|
|
|
5368
|
-
// src/components/toast-stack/ToastStack.tsx
|
|
5369
|
-
import { memo } from "react";
|
|
5370
|
-
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
5371
|
-
var ToastStack = memo(function ToastStack2({ toasts, onDismiss, maxVisible = 3, className }) {
|
|
5372
|
-
return /* @__PURE__ */ jsx50("div", { "data-part": "toast-stack", className: cn("chalk-toasts", className), children: toasts.slice(-maxVisible).map((toast) => /* @__PURE__ */ jsx50(ChalkToast, { ...toast, onDismiss: () => onDismiss(toast.id) }, toast.id)) });
|
|
5373
|
-
});
|
|
5374
|
-
|
|
5375
5500
|
// src/components/chalk/StatusSurface.tsx
|
|
5376
|
-
import {
|
|
5501
|
+
import { formatSyncConnectDiagnostic } from "@q9labsai/chalk-client";
|
|
5502
|
+
import { Fragment as Fragment19, jsx as jsx50, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5377
5503
|
var DEFAULT_FAILURE_DETAIL = "Something went wrong while joining. Try again.";
|
|
5378
5504
|
var FAILURE_DETAILS = {
|
|
5379
5505
|
"access.invalid": "Access to this call was rejected. Refresh the page and try again.",
|
|
@@ -5386,7 +5512,7 @@ var FAILURE_DETAILS = {
|
|
|
5386
5512
|
"environment.unsupported": "This browser cannot start the call. Use an up-to-date browser over HTTPS.",
|
|
5387
5513
|
"client.internal_error": DEFAULT_FAILURE_DETAIL
|
|
5388
5514
|
};
|
|
5389
|
-
function StatusSurface({ phase, callName = "the call", reason, errorCode, theme, onRejoin, onHome, onRetry, onReportProblem, rejoinDisabled = false, retryPending = false }) {
|
|
5515
|
+
function StatusSurface({ phase, callName = "the call", reason, errorCode, sync, theme, onRejoin, onHome, onRetry, onReportProblem, rejoinDisabled = false, retryPending = false }) {
|
|
5390
5516
|
const copy = {
|
|
5391
5517
|
entering: { title: `Joining ${callName}\u2026`, detail: "" },
|
|
5392
5518
|
left: { title: `You left ${callName}`, detail: "" },
|
|
@@ -5407,31 +5533,34 @@ function StatusSurface({ phase, callName = "the call", reason, errorCode, theme,
|
|
|
5407
5533
|
style: { ...chalkThemeStyle(theme), fontSize: 14, lineHeight: 1.4 },
|
|
5408
5534
|
className: "chalk-root relative flex h-full min-h-0 w-full flex-col items-center justify-center gap-3 bg-[var(--chalk-canvas)] p-6 text-center text-[var(--chalk-text)]",
|
|
5409
5535
|
children: [
|
|
5410
|
-
/* @__PURE__ */
|
|
5411
|
-
reason || copy.detail ? /* @__PURE__ */
|
|
5536
|
+
/* @__PURE__ */ jsx50("h1", { role: phase === "entering" ? "status" : void 0, style: { fontSize: 22, fontWeight: 600, lineHeight: 1.4, fontFamily: "inherit", letterSpacing: "normal", textWrap: "wrap" }, children: copy.title }),
|
|
5537
|
+
reason || copy.detail ? /* @__PURE__ */ jsx50("p", { className: "text-[14px] text-[var(--chalk-muted-text)]", children: reason ?? copy.detail }) : null,
|
|
5412
5538
|
phase === "failed" && errorCode ? /* @__PURE__ */ jsxs32("p", { className: "text-[13px] text-[var(--chalk-muted-text)]", children: [
|
|
5413
5539
|
"Reference:",
|
|
5414
5540
|
" ",
|
|
5415
|
-
/* @__PURE__ */
|
|
5541
|
+
/* @__PURE__ */ jsxs32("code", { dir: "ltr", className: "break-all", children: [
|
|
5542
|
+
errorCode,
|
|
5543
|
+
sync ? ` ${formatSyncConnectDiagnostic(sync)}` : ""
|
|
5544
|
+
] })
|
|
5416
5545
|
] }) : null,
|
|
5417
5546
|
/* @__PURE__ */ jsxs32("div", { "data-part": "status-actions", className: "mt-5 flex gap-7", children: [
|
|
5418
|
-
canRetry && retry ? /* @__PURE__ */
|
|
5419
|
-
phase !== "entering" && onHome ? /* @__PURE__ */
|
|
5547
|
+
canRetry && retry ? /* @__PURE__ */ jsx50(StatusAction, { icon: /* @__PURE__ */ jsx50(StatusIcon, { retry: true }), label: phase === "elsewhere" ? "Use here" : phase === "left" ? "Rejoin" : "Try again", onClick: retry, disabled: rejoinDisabled || retryPending }) : null,
|
|
5548
|
+
phase !== "entering" && onHome ? /* @__PURE__ */ jsx50(StatusAction, { icon: /* @__PURE__ */ jsx50(StatusIcon, {}), label: "Home", onClick: onHome }) : null
|
|
5420
5549
|
] }),
|
|
5421
|
-
onReportProblem && phase !== "entering" ? /* @__PURE__ */
|
|
5550
|
+
onReportProblem && phase !== "entering" ? /* @__PURE__ */ jsx50("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
|
|
5422
5551
|
]
|
|
5423
5552
|
}
|
|
5424
5553
|
);
|
|
5425
5554
|
}
|
|
5426
5555
|
function StatusIcon({ retry = false }) {
|
|
5427
|
-
return /* @__PURE__ */
|
|
5428
|
-
/* @__PURE__ */
|
|
5429
|
-
/* @__PURE__ */
|
|
5430
|
-
] }) : /* @__PURE__ */
|
|
5556
|
+
return /* @__PURE__ */ jsx50("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: retry ? /* @__PURE__ */ jsxs32(Fragment19, { children: [
|
|
5557
|
+
/* @__PURE__ */ jsx50("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
5558
|
+
/* @__PURE__ */ jsx50("path", { d: "M3 3v5h5" })
|
|
5559
|
+
] }) : /* @__PURE__ */ jsx50("path", { d: "M3 10.5L12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z" }) });
|
|
5431
5560
|
}
|
|
5432
5561
|
function StatusAction({ icon, label, onClick, disabled }) {
|
|
5433
5562
|
return /* @__PURE__ */ jsxs32("button", { type: "button", onClick, disabled, style: { fontSize: 13, fontWeight: 500, lineHeight: 1.4 }, className: "group flex flex-col items-center gap-2 text-[var(--chalk-soft-text)] outline-none disabled:pointer-events-none disabled:opacity-50", children: [
|
|
5434
|
-
/* @__PURE__ */
|
|
5563
|
+
/* @__PURE__ */ jsx50(
|
|
5435
5564
|
"span",
|
|
5436
5565
|
{
|
|
5437
5566
|
"aria-hidden": "true",
|
|
@@ -5446,7 +5575,7 @@ function StatusAction({ icon, label, onClick, disabled }) {
|
|
|
5446
5575
|
}
|
|
5447
5576
|
|
|
5448
5577
|
// src/components/call-limbo/CallReady.tsx
|
|
5449
|
-
import { useEffect as useEffect19, useId, useRef as
|
|
5578
|
+
import { useEffect as useEffect19, useId, useRef as useRef16, useState as useState27 } from "react";
|
|
5450
5579
|
|
|
5451
5580
|
// src/components/call-limbo/qr-code.ts
|
|
5452
5581
|
function inviteQR(text) {
|
|
@@ -5587,15 +5716,15 @@ function inviteQR(text) {
|
|
|
5587
5716
|
}
|
|
5588
5717
|
|
|
5589
5718
|
// src/components/call-limbo/CallReady.tsx
|
|
5590
|
-
import { Fragment as
|
|
5719
|
+
import { Fragment as Fragment20, jsx as jsx51, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5591
5720
|
function CallReady({ open, onClose, link = typeof location === "undefined" ? "" : location.href }) {
|
|
5592
|
-
const [showQR, setShowQR] =
|
|
5593
|
-
const qrRef =
|
|
5594
|
-
const cardRef =
|
|
5721
|
+
const [showQR, setShowQR] = useState27(false);
|
|
5722
|
+
const qrRef = useRef16(null);
|
|
5723
|
+
const cardRef = useRef16(null);
|
|
5595
5724
|
const phone = useIsMobile();
|
|
5596
5725
|
const reducedMotion = usePrefersReducedMotion();
|
|
5597
|
-
const [entered, setEntered] =
|
|
5598
|
-
const [present, setPresent] =
|
|
5726
|
+
const [entered, setEntered] = useState27(false);
|
|
5727
|
+
const [present, setPresent] = useState27(open);
|
|
5599
5728
|
const id = useId();
|
|
5600
5729
|
const qr = showQR ? inviteQR(link) : null;
|
|
5601
5730
|
const close = () => {
|
|
@@ -5624,31 +5753,31 @@ function CallReady({ open, onClose, link = typeof location === "undefined" ? ""
|
|
|
5624
5753
|
clearTimeout(timer);
|
|
5625
5754
|
};
|
|
5626
5755
|
}, [open, reducedMotion]);
|
|
5627
|
-
const content = /* @__PURE__ */ jsxs33(
|
|
5756
|
+
const content = /* @__PURE__ */ jsxs33(Fragment20, { children: [
|
|
5628
5757
|
/* @__PURE__ */ jsxs33("div", { className: "-mt-1.5 mb-0.5 flex items-center justify-between", children: [
|
|
5629
|
-
/* @__PURE__ */
|
|
5630
|
-
/* @__PURE__ */
|
|
5758
|
+
/* @__PURE__ */ jsx51("h2", { id, "data-part": "ready-title", tabIndex: -1, style: { fontSize: 15, fontWeight: 600, lineHeight: 1.4, fontFamily: "inherit", letterSpacing: "normal", textWrap: "wrap", outline: "none" }, children: "Your call is ready" }),
|
|
5759
|
+
/* @__PURE__ */ jsx51("button", { type: "button", "data-part": "ready-dismiss", className: "chalk-dismiss max-sm:!h-11 max-sm:!w-11", "aria-label": "Close call link", onClick: close, children: /* @__PURE__ */ jsx51("svg", { width: "20", height: "20", style: { width: 20, height: 20 }, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx51("path", { d: "m6 6 12 12M6 18 18 6" }) }) })
|
|
5631
5760
|
] }),
|
|
5632
|
-
/* @__PURE__ */
|
|
5761
|
+
/* @__PURE__ */ jsx51("p", { className: "mr-1 text-[13px] text-[var(--chalk-muted-text)]", children: "Share this link with people you want in the call" }),
|
|
5633
5762
|
/* @__PURE__ */ jsxs33("div", { "data-part": "ready-link", style: { borderRadius: 999 }, className: "mt-3 flex h-11 items-center justify-between gap-2 bg-[var(--chalk-raised)] pl-3.5 pr-1 font-medium", children: [
|
|
5634
|
-
/* @__PURE__ */
|
|
5763
|
+
/* @__PURE__ */ jsx51("span", { className: "min-w-0 truncate", children: link.replace(/^https?:\/\//, "") }),
|
|
5635
5764
|
/* @__PURE__ */ jsxs33("span", { className: "flex gap-0.5", children: [
|
|
5636
|
-
/* @__PURE__ */
|
|
5637
|
-
/* @__PURE__ */
|
|
5638
|
-
/* @__PURE__ */
|
|
5639
|
-
/* @__PURE__ */
|
|
5640
|
-
/* @__PURE__ */
|
|
5765
|
+
/* @__PURE__ */ jsx51("button", { type: "button", className: "chalk-copy", "aria-label": showQR ? "Hide QR code" : "Show QR code", "aria-expanded": showQR, "aria-controls": `${id}-qr`, onClick: () => setShowQR(!showQR), children: /* @__PURE__ */ jsxs33("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", "aria-hidden": "true", children: [
|
|
5766
|
+
/* @__PURE__ */ jsx51("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1.5" }),
|
|
5767
|
+
/* @__PURE__ */ jsx51("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1.5" }),
|
|
5768
|
+
/* @__PURE__ */ jsx51("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1.5" }),
|
|
5769
|
+
/* @__PURE__ */ jsx51("path", { d: "M14 14h3v3M21 14v.01M14 21h3M21 17v4h-1" })
|
|
5641
5770
|
] }) }),
|
|
5642
|
-
/* @__PURE__ */
|
|
5771
|
+
/* @__PURE__ */ jsx51(ChalkCopyButton, { text: link, announcement: "Copied" })
|
|
5643
5772
|
] })
|
|
5644
5773
|
] }),
|
|
5645
|
-
/* @__PURE__ */
|
|
5646
|
-
qr ? /* @__PURE__ */
|
|
5647
|
-
/* @__PURE__ */
|
|
5774
|
+
/* @__PURE__ */ jsx51("div", { ref: qrRef, id: `${id}-qr`, hidden: !showQR, children: /* @__PURE__ */ jsxs33("div", { className: "mt-3 flex items-center gap-3.5", children: [
|
|
5775
|
+
qr ? /* @__PURE__ */ jsx51("svg", { role: "img", "aria-label": "Scan to join this call", width: "104", height: "104", viewBox: `-4 -4 ${qr.length + 8} ${qr.length + 8}`, className: "shrink-0 rounded-lg bg-white p-1", shapeRendering: "crispEdges", children: /* @__PURE__ */ jsx51("path", { fill: "#000", d: qr.flatMap((row, y) => row.flatMap((dark, x) => dark ? [`M${x} ${y}h1v1h-1z`] : [])).join("") }) }) : null,
|
|
5776
|
+
/* @__PURE__ */ jsx51("p", { className: "text-[13px] text-[var(--chalk-soft-text)]", children: qr ? "Scan with a phone camera to join this call." : "This link is too long for a QR code. Copy the link to share it." })
|
|
5648
5777
|
] }) })
|
|
5649
5778
|
] });
|
|
5650
5779
|
if (phone)
|
|
5651
|
-
return /* @__PURE__ */
|
|
5780
|
+
return /* @__PURE__ */ jsx51(
|
|
5652
5781
|
ChalkSheet,
|
|
5653
5782
|
{
|
|
5654
5783
|
variant: "ready",
|
|
@@ -5657,10 +5786,10 @@ function CallReady({ open, onClose, link = typeof location === "undefined" ? ""
|
|
|
5657
5786
|
if (!value) onClose();
|
|
5658
5787
|
},
|
|
5659
5788
|
title: "Your call is ready",
|
|
5660
|
-
children: /* @__PURE__ */
|
|
5789
|
+
children: /* @__PURE__ */ jsx51("section", { ref: cardRef, "aria-labelledby": id, children: content })
|
|
5661
5790
|
}
|
|
5662
5791
|
);
|
|
5663
|
-
return present ? /* @__PURE__ */
|
|
5792
|
+
return present ? /* @__PURE__ */ jsx51(
|
|
5664
5793
|
"section",
|
|
5665
5794
|
{
|
|
5666
5795
|
ref: cardRef,
|
|
@@ -5675,8 +5804,228 @@ function CallReady({ open, onClose, link = typeof location === "undefined" ? ""
|
|
|
5675
5804
|
) : null;
|
|
5676
5805
|
}
|
|
5677
5806
|
|
|
5807
|
+
// src/components/toast-stack/ToastStack.tsx
|
|
5808
|
+
import { memo, useLayoutEffect as useLayoutEffect3, useRef as useRef17, useState as useState29 } from "react";
|
|
5809
|
+
import { flushSync as flushSync2 } from "react-dom";
|
|
5810
|
+
|
|
5811
|
+
// src/components/toast-stack/useToastCapacity.ts
|
|
5812
|
+
import { isValidElement as isValidElement2, useLayoutEffect as useLayoutEffect2, useState as useState28 } from "react";
|
|
5813
|
+
import { flushSync } from "react-dom";
|
|
5814
|
+
|
|
5815
|
+
// src/components/toast-stack/toast-layout-snapshot.ts
|
|
5816
|
+
function captureToastLayout(toast) {
|
|
5817
|
+
const snapshot = document.createElement("div");
|
|
5818
|
+
copyAttributes(toast, snapshot);
|
|
5819
|
+
for (const child of toast.childNodes) snapshot.appendChild(copyLayout(child));
|
|
5820
|
+
return snapshot;
|
|
5821
|
+
}
|
|
5822
|
+
function copyAttributes(source, target) {
|
|
5823
|
+
for (const { name, value } of source.attributes) {
|
|
5824
|
+
if (!/^(?:on|src|href|xlink:href|id$|name$|action$|formaction$|autoplay$|autofocus$|role$|aria-live$|aria-atomic$|tabindex$|contenteditable$)/i.test(name)) target.setAttribute(name, value);
|
|
5825
|
+
}
|
|
5826
|
+
}
|
|
5827
|
+
function copyLayout(node) {
|
|
5828
|
+
if (!(node instanceof Element)) return document.createTextNode(node instanceof Text ? node.data : "");
|
|
5829
|
+
const opaque = node.localName.includes("-") || /^(?:img|video|audio|canvas|iframe|object|embed|script|style|link|image|use|animate|animateMotion|animateTransform|set)$/.test(node.localName);
|
|
5830
|
+
if (opaque) {
|
|
5831
|
+
const placeholder = document.createElement("span");
|
|
5832
|
+
const size = node.getBoundingClientRect();
|
|
5833
|
+
placeholder.style.cssText = `display:inline-block;width:${size.width}px;height:${size.height}px;flex-shrink:0`;
|
|
5834
|
+
return placeholder;
|
|
5835
|
+
}
|
|
5836
|
+
const copy = document.createElementNS(node.namespaceURI, node.localName);
|
|
5837
|
+
copyAttributes(node, copy);
|
|
5838
|
+
for (const child of node.childNodes) copy.appendChild(copyLayout(child));
|
|
5839
|
+
return copy;
|
|
5840
|
+
}
|
|
5841
|
+
function measureToastLayout(stack, snapshot) {
|
|
5842
|
+
const probe = captureToastLayout(snapshot);
|
|
5843
|
+
probe.dataset.part = "toast-measurement";
|
|
5844
|
+
probe.inert = true;
|
|
5845
|
+
probe.setAttribute("aria-hidden", "true");
|
|
5846
|
+
Object.assign(probe.style, { position: "absolute", left: "0", top: "0", width: "max-content", visibility: "hidden", pointerEvents: "none", animation: "none", transition: "none", transform: "none" });
|
|
5847
|
+
stack.appendChild(probe);
|
|
5848
|
+
try {
|
|
5849
|
+
return Math.max(probe.offsetHeight, Math.ceil(probe.getBoundingClientRect().height));
|
|
5850
|
+
} finally {
|
|
5851
|
+
probe.remove();
|
|
5852
|
+
}
|
|
5853
|
+
}
|
|
5854
|
+
|
|
5855
|
+
// src/components/toast-stack/useToastCapacity.ts
|
|
5856
|
+
function useToastCapacity(stack, candidates, enabled, ownedIds) {
|
|
5857
|
+
const [fit, setFit] = useState28(null);
|
|
5858
|
+
let count = candidates.length;
|
|
5859
|
+
if (enabled) {
|
|
5860
|
+
count = 0;
|
|
5861
|
+
let used = 0;
|
|
5862
|
+
if (fit)
|
|
5863
|
+
for (const toast of candidates.slice().reverse()) {
|
|
5864
|
+
const measured = fit.measurements.get(toast.id);
|
|
5865
|
+
const height = measured && sameLayout(measured.toast, toast) ? measured.height : 48;
|
|
5866
|
+
const next = used + (count ? fit.gap : 0) + height;
|
|
5867
|
+
if (fit.width > 0 && next > fit.available) break;
|
|
5868
|
+
used = next;
|
|
5869
|
+
count += 1;
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
const selected = candidates.slice(candidates.length - count);
|
|
5873
|
+
const ready = fit !== null && selected.every((toast) => {
|
|
5874
|
+
const measured = fit.measurements.get(toast.id);
|
|
5875
|
+
return measured !== void 0 && sameLayout(measured.toast, toast);
|
|
5876
|
+
});
|
|
5877
|
+
useLayoutEffect2(() => {
|
|
5878
|
+
const node = stack.current;
|
|
5879
|
+
if (!enabled || !node) return;
|
|
5880
|
+
const elements = [...node.children].filter((child) => child instanceof HTMLElement);
|
|
5881
|
+
const measure = () => {
|
|
5882
|
+
const style = getComputedStyle(node);
|
|
5883
|
+
const padding = (parseFloat(style.paddingTop) || 0) + (parseFloat(style.paddingBottom) || 0);
|
|
5884
|
+
const width = node.clientWidth;
|
|
5885
|
+
const available = Math.max(0, node.clientHeight - padding);
|
|
5886
|
+
const gap = parseFloat(style.rowGap) || 0;
|
|
5887
|
+
const mounted = selected.filter((toast) => ownedIds.includes(toast.id));
|
|
5888
|
+
const updates = /* @__PURE__ */ new Map();
|
|
5889
|
+
mounted.forEach((toast, index) => {
|
|
5890
|
+
const element = elements[index];
|
|
5891
|
+
if (!element) return;
|
|
5892
|
+
const height = Math.max(element.offsetHeight, Math.ceil(element.getBoundingClientRect().height));
|
|
5893
|
+
const old = fit?.measurements.get(toast.id);
|
|
5894
|
+
const markup = element.innerHTML;
|
|
5895
|
+
if (!old || old.height !== height || old.width !== width || old.markup !== markup || !sameLayout(old.toast, toast)) {
|
|
5896
|
+
updates.set(toast.id, { toast, height, width, markup, snapshot: captureToastLayout(element) });
|
|
5897
|
+
}
|
|
5898
|
+
});
|
|
5899
|
+
for (const toast of candidates) {
|
|
5900
|
+
const old = fit?.measurements.get(toast.id);
|
|
5901
|
+
if (old && old.width !== width && !mounted.includes(toast) && sameLayout(old.toast, toast)) {
|
|
5902
|
+
updates.set(toast.id, { ...old, width, height: measureToastLayout(node, old.snapshot) });
|
|
5903
|
+
}
|
|
5904
|
+
}
|
|
5905
|
+
setFit((previous) => {
|
|
5906
|
+
const measurements = new Map(previous?.measurements);
|
|
5907
|
+
const present = new Set(candidates.map((toast) => toast.id));
|
|
5908
|
+
for (const id of measurements.keys()) if (!present.has(id)) measurements.delete(id);
|
|
5909
|
+
const changed = measurements.size !== previous?.measurements.size || updates.size > 0;
|
|
5910
|
+
for (const [id, measurement] of updates) measurements.set(id, measurement);
|
|
5911
|
+
return !changed && previous?.width === width && previous.available === available && previous.gap === gap ? previous : { width, available, gap, measurements };
|
|
5912
|
+
});
|
|
5913
|
+
};
|
|
5914
|
+
measure();
|
|
5915
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
5916
|
+
let active = true;
|
|
5917
|
+
const observer = new ResizeObserver(() => {
|
|
5918
|
+
if (active) flushSync(measure);
|
|
5919
|
+
});
|
|
5920
|
+
observer.observe(node);
|
|
5921
|
+
for (const element of elements) observer.observe(element);
|
|
5922
|
+
return () => {
|
|
5923
|
+
active = false;
|
|
5924
|
+
observer.disconnect();
|
|
5925
|
+
};
|
|
5926
|
+
});
|
|
5927
|
+
return { count, ready: !enabled || ready };
|
|
5928
|
+
}
|
|
5929
|
+
function sameLayout(previous, next) {
|
|
5930
|
+
return previous.id === next.id && noticeIdentity(previous) === noticeIdentity(next) && previous.action?.label === next.action?.label && sameLayoutValue(previous.message, next.message) && sameLayoutValue(previous.icon, next.icon);
|
|
5931
|
+
}
|
|
5932
|
+
function sameLayoutValue(previous, next, seen = /* @__PURE__ */ new WeakMap()) {
|
|
5933
|
+
if (Object.is(previous, next)) return true;
|
|
5934
|
+
if (typeof previous === "function" && typeof next === "function") return true;
|
|
5935
|
+
if (previous === null || next === null || typeof previous !== "object" || typeof next !== "object") return false;
|
|
5936
|
+
if (isValidElement2(previous) || isValidElement2(next)) return isValidElement2(previous) && isValidElement2(next) && previous.type === next.type && sameLayoutValue(previous.props, next.props, seen);
|
|
5937
|
+
if (Object.getPrototypeOf(previous) !== Object.getPrototypeOf(next)) return false;
|
|
5938
|
+
if (seen.get(previous) === next) return true;
|
|
5939
|
+
seen.set(previous, next);
|
|
5940
|
+
const keys = Object.keys(previous).filter((key) => key !== "ref");
|
|
5941
|
+
return keys.length === Object.keys(next).filter((key) => key !== "ref").length && keys.every((key) => Object.hasOwn(next, key) && sameLayoutValue(Reflect.get(previous, key), Reflect.get(next, key), seen));
|
|
5942
|
+
}
|
|
5943
|
+
|
|
5944
|
+
// src/components/toast-stack/ToastStack.tsx
|
|
5945
|
+
import { Fragment as Fragment21, jsx as jsx52, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
5946
|
+
var FOLD_BELOW_PX = 620;
|
|
5947
|
+
var ToastStack = memo(function ToastStack2({ toasts, onDismiss, maxVisible = 3, className, onFold }) {
|
|
5948
|
+
const stack = useRef17(null);
|
|
5949
|
+
const short = useShortCall(stack, onFold !== void 0);
|
|
5950
|
+
const candidates = maxVisible > 0 ? toasts.slice(-maxVisible) : [];
|
|
5951
|
+
const [ownedIds, setOwnedIds] = useState29([]);
|
|
5952
|
+
const fold = useRef17(onFold);
|
|
5953
|
+
const capacity = useToastCapacity(stack, candidates, onFold !== void 0 && short === false, ownedIds);
|
|
5954
|
+
const selected = onFold !== void 0 && short !== false ? [] : candidates.slice(candidates.length - capacity.count);
|
|
5955
|
+
const shown = onFold || fold.current ? selected.filter((toast) => ownedIds.includes(toast.id)) : selected;
|
|
5956
|
+
const folded = onFold !== void 0 && short !== null ? toasts.filter((toast) => !selected.includes(toast)) : [];
|
|
5957
|
+
const foldedIds = folded.map((toast) => toast.id);
|
|
5958
|
+
const announced = useRef17(/* @__PURE__ */ new Map());
|
|
5959
|
+
const wasAnnounced = (toast) => announced.current.get(toast.id) === noticeIdentity(toast);
|
|
5960
|
+
const [unheard, setUnheard] = useState29([]);
|
|
5961
|
+
const reported = useRef17([]);
|
|
5962
|
+
const reporting = useRef17(false);
|
|
5963
|
+
useLayoutEffect3(() => {
|
|
5964
|
+
const replacement = fold.current !== onFold;
|
|
5965
|
+
if (replacement) {
|
|
5966
|
+
if (!onFold) fold.current?.([]);
|
|
5967
|
+
fold.current = onFold;
|
|
5968
|
+
}
|
|
5969
|
+
const selectedIds = selected.map((toast) => toast.id);
|
|
5970
|
+
setOwnedIds((previous) => sameIds(previous, selectedIds) ? previous : selectedIds);
|
|
5971
|
+
const unchanged = sameIds(reported.current, foldedIds);
|
|
5972
|
+
if (!unchanged) reported.current = foldedIds;
|
|
5973
|
+
if (!unchanged || replacement && !reporting.current) {
|
|
5974
|
+
reporting.current = true;
|
|
5975
|
+
queueMicrotask(() => {
|
|
5976
|
+
reporting.current = false;
|
|
5977
|
+
});
|
|
5978
|
+
fold.current?.(reported.current);
|
|
5979
|
+
}
|
|
5980
|
+
if (!capacity.ready) return;
|
|
5981
|
+
const present = new Set(toasts.map((toast) => toast.id));
|
|
5982
|
+
for (const id of announced.current.keys()) if (!present.has(id)) announced.current.delete(id);
|
|
5983
|
+
const eligible = onFold ? toasts : shown;
|
|
5984
|
+
const fresh = eligible.filter((toast) => !wasAnnounced(toast)).map((toast) => toast.id);
|
|
5985
|
+
for (const toast of eligible) announced.current.set(toast.id, noticeIdentity(toast));
|
|
5986
|
+
const kept = unheard.filter((id) => eligible.some((toast) => toast.id === id));
|
|
5987
|
+
if (fresh.length) setUnheard(fresh);
|
|
5988
|
+
else if (kept.length < unheard.length) setUnheard(kept);
|
|
5989
|
+
});
|
|
5990
|
+
useLayoutEffect3(
|
|
5991
|
+
() => () => {
|
|
5992
|
+
reported.current = [];
|
|
5993
|
+
fold.current?.([]);
|
|
5994
|
+
},
|
|
5995
|
+
[]
|
|
5996
|
+
);
|
|
5997
|
+
const announcing = (onFold ? toasts : shown).filter((toast) => unheard.includes(toast.id));
|
|
5998
|
+
return /* @__PURE__ */ jsxs34(Fragment21, { children: [
|
|
5999
|
+
/* @__PURE__ */ jsx52("div", { ref: stack, "data-part": "toast-stack", className: cn("chalk-toasts", className), children: shown.map((toast) => /* @__PURE__ */ jsx52(ChalkToast, { ...toast, announce: toast.announcementText === void 0 && noticeAnnouncement(toast) === "", onDismiss: () => onDismiss(toast.id) }, toast.id)) }),
|
|
6000
|
+
/* @__PURE__ */ jsxs34("div", { "data-part": "notice-announcer", className: "sr-only", children: [
|
|
6001
|
+
/* @__PURE__ */ jsx52("div", { "aria-live": "polite", children: announcing.filter((toast) => toast.type !== "error").map((toast) => /* @__PURE__ */ jsx52("div", { children: noticeAnnouncement(toast) }, JSON.stringify([toast.id, noticeIdentity(toast)]))) }),
|
|
6002
|
+
/* @__PURE__ */ jsx52("div", { "aria-live": "assertive", children: announcing.filter((toast) => toast.type === "error").map((toast) => /* @__PURE__ */ jsx52("div", { children: noticeAnnouncement(toast) }, JSON.stringify([toast.id, noticeIdentity(toast)]))) })
|
|
6003
|
+
] })
|
|
6004
|
+
] });
|
|
6005
|
+
});
|
|
6006
|
+
function useShortCall(stack, enabled) {
|
|
6007
|
+
const [short, setShort] = useState29(null);
|
|
6008
|
+
useLayoutEffect3(() => {
|
|
6009
|
+
if (!enabled) {
|
|
6010
|
+
setShort(null);
|
|
6011
|
+
return;
|
|
6012
|
+
}
|
|
6013
|
+
const call = stack.current?.closest("[data-part='call-frame']");
|
|
6014
|
+
const read3 = () => setShort(Boolean(call && call.clientHeight > 0 && call.clientHeight < FOLD_BELOW_PX));
|
|
6015
|
+
read3();
|
|
6016
|
+
if (!call || typeof ResizeObserver === "undefined") return;
|
|
6017
|
+
const observer = new ResizeObserver(() => flushSync2(read3));
|
|
6018
|
+
observer.observe(call);
|
|
6019
|
+
return () => observer.disconnect();
|
|
6020
|
+
}, [stack, enabled]);
|
|
6021
|
+
return short;
|
|
6022
|
+
}
|
|
6023
|
+
function sameIds(a, b) {
|
|
6024
|
+
return a.length === b.length && a.every((id, index) => id === b[index]);
|
|
6025
|
+
}
|
|
6026
|
+
|
|
5678
6027
|
// src/internal/call-motion.ts
|
|
5679
|
-
import { useEffect as useEffect20, useState as
|
|
6028
|
+
import { useEffect as useEffect20, useState as useState30 } from "react";
|
|
5680
6029
|
var moves = /* @__PURE__ */ new WeakMap();
|
|
5681
6030
|
function captureFlip(elements) {
|
|
5682
6031
|
const previous = Array.from(elements, (element) => ({ element, box: element.getBoundingClientRect() }));
|
|
@@ -5702,8 +6051,9 @@ function playFlip(previous) {
|
|
|
5702
6051
|
}
|
|
5703
6052
|
return next.map(({ element, next: box }) => ({ element, box }));
|
|
5704
6053
|
}
|
|
6054
|
+
var ACTIVE_LAYERS = '[role="menu"],[role="dialog"],[data-part="toast"],[data-part="notice-button"],[data-chalk-drawer]';
|
|
5705
6055
|
function useIdleChrome(root, enabled) {
|
|
5706
|
-
const [idle, setIdle] =
|
|
6056
|
+
const [idle, setIdle] = useState30(false);
|
|
5707
6057
|
const fine = useMediaQuery("(pointer:fine) and (min-width:641px)");
|
|
5708
6058
|
useEffect20(() => {
|
|
5709
6059
|
const element = root.current;
|
|
@@ -5713,7 +6063,7 @@ function useIdleChrome(root, enabled) {
|
|
|
5713
6063
|
setIdle(false);
|
|
5714
6064
|
clearTimeout(timer);
|
|
5715
6065
|
timer = setTimeout(() => {
|
|
5716
|
-
const layer = element.querySelector(
|
|
6066
|
+
const layer = element.querySelector(ACTIVE_LAYERS);
|
|
5717
6067
|
const focused = element.querySelector(".chalk-frame-header :focus-visible,.chalk-frame-dock :focus-visible");
|
|
5718
6068
|
if (!layer && !focused) setIdle(true);
|
|
5719
6069
|
else poke();
|
|
@@ -5721,8 +6071,7 @@ function useIdleChrome(root, enabled) {
|
|
|
5721
6071
|
};
|
|
5722
6072
|
for (const event of ["pointermove", "pointerdown", "keydown", "focusin"]) element.addEventListener(event, poke);
|
|
5723
6073
|
const observer = new MutationObserver((records) => {
|
|
5724
|
-
|
|
5725
|
-
if (records.some((record) => [...record.addedNodes, ...record.removedNodes].some((node) => node instanceof Element && (node.matches(selector) || node.querySelector(selector))))) poke();
|
|
6074
|
+
if (records.some((record) => [...record.addedNodes, ...record.removedNodes].some((node) => node instanceof Element && (node.matches(ACTIVE_LAYERS) || node.querySelector(ACTIVE_LAYERS))))) poke();
|
|
5726
6075
|
});
|
|
5727
6076
|
observer.observe(element, { childList: true, subtree: true });
|
|
5728
6077
|
poke();
|
|
@@ -5736,7 +6085,7 @@ function useIdleChrome(root, enabled) {
|
|
|
5736
6085
|
}
|
|
5737
6086
|
|
|
5738
6087
|
// src/components/space-header/SpaceHeader.tsx
|
|
5739
|
-
import React14, { useCallback as useCallback6, useRef as useRef20, useState as
|
|
6088
|
+
import React14, { useCallback as useCallback6, useRef as useRef20, useState as useState32 } from "react";
|
|
5740
6089
|
|
|
5741
6090
|
// src/internal/useSoundsSetting.ts
|
|
5742
6091
|
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
@@ -5788,7 +6137,7 @@ function LayoutMenu({ layout, onLayoutChange }) {
|
|
|
5788
6137
|
|
|
5789
6138
|
// src/components/space-header/CallDetails.tsx
|
|
5790
6139
|
import { Dialog as Dialog2 } from "@base-ui/react/dialog";
|
|
5791
|
-
import { useEffect as useEffect21, useRef as useRef18, useState as
|
|
6140
|
+
import { useEffect as useEffect21, useRef as useRef18, useState as useState31 } from "react";
|
|
5792
6141
|
|
|
5793
6142
|
// src/components/space-header/share-qr.ts
|
|
5794
6143
|
function shareQr(text) {
|
|
@@ -5918,7 +6267,7 @@ function shareQr(text) {
|
|
|
5918
6267
|
}
|
|
5919
6268
|
|
|
5920
6269
|
// src/components/space-header/CallDetails.tsx
|
|
5921
|
-
import { Fragment as
|
|
6270
|
+
import { Fragment as Fragment22, jsx as jsx54, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
5922
6271
|
var CALL_SHORTCUTS = [
|
|
5923
6272
|
["Mute or unmute", "\u2318 D"],
|
|
5924
6273
|
["Turn camera on or off", "\u2318 E"],
|
|
@@ -5936,17 +6285,21 @@ function CallDialog({
|
|
|
5936
6285
|
onClose,
|
|
5937
6286
|
onReportProblem,
|
|
5938
6287
|
diagnostics,
|
|
5939
|
-
returnFocus
|
|
6288
|
+
returnFocus,
|
|
6289
|
+
focusScope,
|
|
6290
|
+
unavailableReason
|
|
5940
6291
|
}) {
|
|
5941
6292
|
const container = useRef18(null);
|
|
5942
6293
|
const reportInput = useRef18(null);
|
|
5943
|
-
const
|
|
5944
|
-
const [
|
|
5945
|
-
const [
|
|
5946
|
-
const [
|
|
6294
|
+
const reportOpener = useRef18(null);
|
|
6295
|
+
const [text, setText] = useState31("");
|
|
6296
|
+
const [includeDiagnostics, setIncludeDiagnostics] = useState31(false);
|
|
6297
|
+
const [status, setStatus] = useState31("idle");
|
|
6298
|
+
const [error, setError] = useState31("");
|
|
5947
6299
|
useEffect21(() => {
|
|
5948
6300
|
if (open && kind === "report") {
|
|
5949
6301
|
setText("");
|
|
6302
|
+
setIncludeDiagnostics(false);
|
|
5950
6303
|
setError("");
|
|
5951
6304
|
setStatus("idle");
|
|
5952
6305
|
}
|
|
@@ -5962,68 +6315,107 @@ function CallDialog({
|
|
|
5962
6315
|
Dialog2.Root,
|
|
5963
6316
|
{
|
|
5964
6317
|
open,
|
|
5965
|
-
onOpenChange: (open2) => {
|
|
6318
|
+
onOpenChange: (open2, event) => {
|
|
6319
|
+
if (!open2 && status === "sending") {
|
|
6320
|
+
event.cancel();
|
|
6321
|
+
return;
|
|
6322
|
+
}
|
|
5966
6323
|
if (!open2) onClose();
|
|
5967
6324
|
},
|
|
5968
|
-
children: /* @__PURE__ */
|
|
6325
|
+
children: /* @__PURE__ */ jsxs35(Dialog2.Portal, { container, children: [
|
|
5969
6326
|
/* @__PURE__ */ jsx54(Dialog2.Backdrop, { className: "chalk-shell-modal-backdrop" }),
|
|
5970
|
-
/* @__PURE__ */
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
)
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
] }) : /* @__PURE__ */ jsxs34(
|
|
5989
|
-
"form",
|
|
5990
|
-
{
|
|
5991
|
-
className: "chalk-shell-report",
|
|
5992
|
-
onSubmit: (event) => {
|
|
5993
|
-
event.preventDefault();
|
|
5994
|
-
if (!text.trim() || !onReportProblem || status === "sending") return;
|
|
5995
|
-
setStatus("sending");
|
|
5996
|
-
setError("");
|
|
5997
|
-
void Promise.resolve().then(() => onReportProblem({ description: text.trim(), diagnostics: includeDiagnostics ? diagnostics : void 0 })).then(
|
|
5998
|
-
() => setStatus("sent"),
|
|
5999
|
-
() => {
|
|
6000
|
-
setStatus("idle");
|
|
6001
|
-
setError("Your report could not be sent. Try again.");
|
|
6327
|
+
/* @__PURE__ */ jsxs35(
|
|
6328
|
+
Dialog2.Popup,
|
|
6329
|
+
{
|
|
6330
|
+
initialFocus: kind === "report" ? () => {
|
|
6331
|
+
const opener = reportInput.current?.ownerDocument.activeElement;
|
|
6332
|
+
reportOpener.current = opener instanceof HTMLElement && focusScope.current?.contains(opener) ? opener : null;
|
|
6333
|
+
return reportInput.current;
|
|
6334
|
+
} : void 0,
|
|
6335
|
+
finalFocus: kind === "report" ? () => reportFocusTarget(focusScope.current, reportOpener.current) : returnFocus,
|
|
6336
|
+
className: "chalk-shell-modal",
|
|
6337
|
+
children: [
|
|
6338
|
+
kind === "report" && status === "sent" ? null : /* @__PURE__ */ jsxs35("div", { className: "chalk-shell-modal-heading", children: [
|
|
6339
|
+
/* @__PURE__ */ jsx54(Dialog2.Title, { children: kind === "shortcuts" ? "Keyboard shortcuts" : "Report a problem" }),
|
|
6340
|
+
/* @__PURE__ */ jsx54(
|
|
6341
|
+
Dialog2.Close,
|
|
6342
|
+
{
|
|
6343
|
+
disabled: status === "sending",
|
|
6344
|
+
render: /* @__PURE__ */ jsx54(ChalkIconButton, { "aria-label": "Close", size: "sm", children: /* @__PURE__ */ jsx54("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx54("path", { d: "m6 6 12 12M6 18 18 6" }) }) })
|
|
6002
6345
|
}
|
|
6003
|
-
)
|
|
6004
|
-
},
|
|
6005
|
-
children: [
|
|
6006
|
-
/* @__PURE__ */ jsx54("
|
|
6007
|
-
/* @__PURE__ */ jsx54("
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6346
|
+
)
|
|
6347
|
+
] }),
|
|
6348
|
+
kind === "shortcuts" ? /* @__PURE__ */ jsx54("dl", { className: "chalk-shell-shortcuts", children: CALL_SHORTCUTS.map(([label, keys]) => /* @__PURE__ */ jsxs35("div", { style: { display: "contents" }, children: [
|
|
6349
|
+
/* @__PURE__ */ jsx54("dt", { children: label }),
|
|
6350
|
+
/* @__PURE__ */ jsx54("dd", { children: keys.split(" ").map((key, index) => /* @__PURE__ */ jsx54("kbd", { children: key }, `${key}${index}`)) })
|
|
6351
|
+
] }, label)) }) : status === "sent" ? /* @__PURE__ */ jsxs35("div", { className: "chalk-shell-report-sent", role: "status", children: [
|
|
6352
|
+
/* @__PURE__ */ jsx54("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx54("path", { d: "m5 12 4 4L19 6" }) }),
|
|
6353
|
+
/* @__PURE__ */ jsx54(Dialog2.Title, { children: "Sent" }),
|
|
6354
|
+
/* @__PURE__ */ jsx54("p", { children: "Thanks. We\u2019ll look into it." }),
|
|
6355
|
+
/* @__PURE__ */ jsx54(ChalkButton, { variant: "solid", onClick: onClose, children: "Done" })
|
|
6356
|
+
] }) : /* @__PURE__ */ jsxs35(
|
|
6357
|
+
"form",
|
|
6358
|
+
{
|
|
6359
|
+
className: "chalk-shell-report",
|
|
6360
|
+
onSubmit: (event) => {
|
|
6361
|
+
event.preventDefault();
|
|
6362
|
+
if (!text.trim() || !onReportProblem || status === "sending" || unavailableReason) return;
|
|
6363
|
+
setStatus("sending");
|
|
6364
|
+
setError("");
|
|
6365
|
+
void Promise.resolve().then(() => onReportProblem({ description: text.trim(), diagnostics: includeDiagnostics && diagnostics.trim() ? diagnostics : void 0 })).then(
|
|
6366
|
+
() => setStatus("sent"),
|
|
6367
|
+
() => {
|
|
6368
|
+
setStatus("idle");
|
|
6369
|
+
setError("Your report could not be sent. Try again.");
|
|
6370
|
+
}
|
|
6371
|
+
);
|
|
6372
|
+
},
|
|
6373
|
+
children: [
|
|
6374
|
+
/* @__PURE__ */ jsx54("label", { htmlFor: "chalk-problem", children: "What went wrong?" }),
|
|
6375
|
+
/* @__PURE__ */ jsx54("textarea", { ref: reportInput, id: "chalk-problem", rows: 4, required: true, disabled: status === "sending", value: text, onChange: (event) => setText(Array.from(event.target.value).slice(0, 1e3).join("")), placeholder: "Tell us what happened\u2026" }),
|
|
6376
|
+
diagnostics.trim() ? /* @__PURE__ */ jsxs35("label", { className: "chalk-shell-report-check", children: [
|
|
6377
|
+
/* @__PURE__ */ jsx54("input", { type: "checkbox", disabled: status === "sending", checked: includeDiagnostics, onChange: (event) => setIncludeDiagnostics(event.target.checked) }),
|
|
6378
|
+
" Include diagnostics"
|
|
6379
|
+
] }) : null,
|
|
6380
|
+
error ? /* @__PURE__ */ jsx54("p", { role: "alert", children: error }) : null,
|
|
6381
|
+
unavailableReason ? /* @__PURE__ */ jsx54("p", { role: "alert", children: unavailableReason }) : null,
|
|
6382
|
+
/* @__PURE__ */ jsxs35("div", { className: "chalk-shell-report-actions", children: [
|
|
6383
|
+
/* @__PURE__ */ jsx54(ChalkButton, { onClick: onClose, disabled: status === "sending", children: "Cancel" }),
|
|
6384
|
+
/* @__PURE__ */ jsx54(ChalkButton, { type: "submit", variant: "solid", disabled: !text.trim() || status === "sending" || Boolean(unavailableReason), children: status === "sending" ? "Sending\u2026" : "Send" })
|
|
6385
|
+
] })
|
|
6386
|
+
]
|
|
6387
|
+
}
|
|
6388
|
+
)
|
|
6389
|
+
]
|
|
6390
|
+
}
|
|
6391
|
+
)
|
|
6021
6392
|
] })
|
|
6022
6393
|
}
|
|
6023
6394
|
)
|
|
6024
6395
|
}
|
|
6025
6396
|
);
|
|
6026
6397
|
}
|
|
6398
|
+
function reportFocusTarget(scope, opener) {
|
|
6399
|
+
if (usableReportFocusTarget(opener)) return opener;
|
|
6400
|
+
if (!scope?.isConnected) return false;
|
|
6401
|
+
for (const selector of ['button[data-part="call-name"]', '[data-part="status-actions"] button', 'main, [role="main"]']) {
|
|
6402
|
+
for (const target of [scope, ...scope.querySelectorAll(selector)]) {
|
|
6403
|
+
if (!target.matches(selector) || !usableReportFocusTarget(target)) continue;
|
|
6404
|
+
if (target.matches('main, [role="main"]')) target.tabIndex = -1;
|
|
6405
|
+
return target;
|
|
6406
|
+
}
|
|
6407
|
+
}
|
|
6408
|
+
return false;
|
|
6409
|
+
}
|
|
6410
|
+
function usableReportFocusTarget(target) {
|
|
6411
|
+
if (!target?.isConnected || target.matches(':disabled, [aria-disabled="true"]') || target.closest("[inert]") || target.getClientRects().length === 0) return false;
|
|
6412
|
+
const visibility = getComputedStyle(target).visibility;
|
|
6413
|
+
if (visibility === "hidden" || visibility === "collapse") return false;
|
|
6414
|
+
for (let element = target; element; element = element.parentElement) {
|
|
6415
|
+
if (getComputedStyle(element).opacity === "0") return false;
|
|
6416
|
+
}
|
|
6417
|
+
return true;
|
|
6418
|
+
}
|
|
6027
6419
|
function CallDetails({
|
|
6028
6420
|
shareUrl,
|
|
6029
6421
|
spaceName,
|
|
@@ -6038,46 +6430,46 @@ function CallDetails({
|
|
|
6038
6430
|
}) {
|
|
6039
6431
|
const link = shareUrl ?? (typeof location === "undefined" ? "" : location.href);
|
|
6040
6432
|
const qr = shareQr(link);
|
|
6041
|
-
const [details, setDetails] =
|
|
6042
|
-
return /* @__PURE__ */
|
|
6043
|
-
/* @__PURE__ */
|
|
6433
|
+
const [details, setDetails] = useState31(false);
|
|
6434
|
+
return /* @__PURE__ */ jsxs35("div", { className: "chalk-details", children: [
|
|
6435
|
+
/* @__PURE__ */ jsxs35("div", { className: "chalk-shell-details-heading", children: [
|
|
6044
6436
|
/* @__PURE__ */ jsx54("h2", { children: spaceName }),
|
|
6045
6437
|
/* @__PURE__ */ jsx54(ChalkIconButton, { "aria-label": "Close", size: "sm", onClick: onClose, children: /* @__PURE__ */ jsx54("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx54("path", { d: "m6 6 12 12M6 18 18 6" }) }) })
|
|
6046
6438
|
] }),
|
|
6047
|
-
/* @__PURE__ */
|
|
6439
|
+
/* @__PURE__ */ jsxs35("section", { className: "chalk-shell-section", children: [
|
|
6048
6440
|
/* @__PURE__ */ jsx54("h3", { className: "chalk-shell-label", children: "Share" }),
|
|
6049
|
-
/* @__PURE__ */
|
|
6441
|
+
/* @__PURE__ */ jsxs35("div", { className: "chalk-shell-link", children: [
|
|
6050
6442
|
/* @__PURE__ */ jsx54("span", { dir: "ltr", children: link.replace(/^https?:\/\//, "") }),
|
|
6051
6443
|
/* @__PURE__ */ jsx54(ChalkCopyButton, { text: link, label: "Copy link" })
|
|
6052
6444
|
] }),
|
|
6053
|
-
qr ? /* @__PURE__ */
|
|
6054
|
-
/* @__PURE__ */
|
|
6445
|
+
qr ? /* @__PURE__ */ jsxs35("div", { className: "chalk-shell-qr-row", children: [
|
|
6446
|
+
/* @__PURE__ */ jsxs35("svg", { "data-part": "share-qr", className: "chalk-shell-qr", viewBox: `0 0 ${qr.length + 8} ${qr.length + 8}`, role: "img", "aria-label": "Scan to join this call", shapeRendering: "crispEdges", children: [
|
|
6055
6447
|
/* @__PURE__ */ jsx54("rect", { width: "100%", height: "100%", fill: "white" }),
|
|
6056
6448
|
/* @__PURE__ */ jsx54("path", { d: qr.flatMap((row, y) => row.flatMap((dark, x) => dark ? [`M${x + 4},${y + 4}h1v1h-1z`] : [])).join("") })
|
|
6057
6449
|
] }),
|
|
6058
6450
|
/* @__PURE__ */ jsx54("p", { children: "Scan with a phone camera to join this call." })
|
|
6059
6451
|
] }) : null
|
|
6060
6452
|
] }),
|
|
6061
|
-
diagnostics.length ? /* @__PURE__ */
|
|
6062
|
-
/* @__PURE__ */
|
|
6453
|
+
diagnostics.length ? /* @__PURE__ */ jsxs35("section", { className: "chalk-shell-section", children: [
|
|
6454
|
+
/* @__PURE__ */ jsxs35("button", { type: "button", className: "chalk-shell-detail-action chalk-shell-connection", "aria-expanded": details, onClick: () => setDetails(!details), children: [
|
|
6063
6455
|
/* @__PURE__ */ jsx54("span", { className: "chalk-shell-connection-bars", "aria-hidden": "true", children: [6, 9, 12, 15].map((height) => /* @__PURE__ */ jsx54("i", { style: { height } }, height)) }),
|
|
6064
|
-
/* @__PURE__ */
|
|
6456
|
+
/* @__PURE__ */ jsxs35("span", { children: [
|
|
6065
6457
|
"Connection: ",
|
|
6066
6458
|
diagnostics[0]?.value.toLowerCase()
|
|
6067
6459
|
] }),
|
|
6068
6460
|
/* @__PURE__ */ jsx54("span", { className: "chalk-shell-connection-details", children: details ? "Hide details" : "Details" }),
|
|
6069
6461
|
/* @__PURE__ */ jsx54(ShellIcon, { name: details ? "up2" : "down", size: 18 })
|
|
6070
6462
|
] }),
|
|
6071
|
-
details ? /* @__PURE__ */
|
|
6072
|
-
/* @__PURE__ */ jsx54("dl", { className: "chalk-shell-diagnostics", children: diagnostics.map(({ label, value }) => /* @__PURE__ */
|
|
6463
|
+
details ? /* @__PURE__ */ jsxs35(Fragment22, { children: [
|
|
6464
|
+
/* @__PURE__ */ jsx54("dl", { className: "chalk-shell-diagnostics", children: diagnostics.map(({ label, value }) => /* @__PURE__ */ jsxs35("div", { style: { display: "contents" }, children: [
|
|
6073
6465
|
/* @__PURE__ */ jsx54("dt", { children: label }),
|
|
6074
6466
|
/* @__PURE__ */ jsx54("dd", { children: value })
|
|
6075
6467
|
] }, label)) }),
|
|
6076
6468
|
/* @__PURE__ */ jsx54("div", { className: "chalk-shell-diagnostics-copy", children: /* @__PURE__ */ jsx54(ChalkCopyButton, { text: diagnostics.map(({ label, value }) => `${label}: ${value}`).join("\n"), label: "Copy diagnostics", announcement: "Diagnostics copied", showLabel: true }) })
|
|
6077
6469
|
] }) : null
|
|
6078
6470
|
] }) : null,
|
|
6079
|
-
/* @__PURE__ */
|
|
6080
|
-
/* @__PURE__ */
|
|
6471
|
+
/* @__PURE__ */ jsxs35("section", { className: "chalk-shell-section", children: [
|
|
6472
|
+
/* @__PURE__ */ jsxs35("div", { className: "chalk-details-row", children: [
|
|
6081
6473
|
/* @__PURE__ */ jsx54("span", { children: "Appearance" }),
|
|
6082
6474
|
/* @__PURE__ */ jsx54(
|
|
6083
6475
|
ChalkSegmentedControl,
|
|
@@ -6093,15 +6485,15 @@ function CallDetails({
|
|
|
6093
6485
|
}
|
|
6094
6486
|
)
|
|
6095
6487
|
] }),
|
|
6096
|
-
/* @__PURE__ */
|
|
6488
|
+
/* @__PURE__ */ jsxs35("button", { type: "button", role: "switch", "aria-label": "Sounds", "aria-checked": sounds, className: "chalk-shell-detail-action", onClick: () => onSoundsChange(!sounds), children: [
|
|
6097
6489
|
/* @__PURE__ */ jsx54("span", { children: "Sounds" }),
|
|
6098
6490
|
/* @__PURE__ */ jsx54("span", { className: "chalk-switch", "aria-checked": sounds, "aria-hidden": "true", children: /* @__PURE__ */ jsx54("span", {}) })
|
|
6099
6491
|
] }),
|
|
6100
|
-
/* @__PURE__ */
|
|
6492
|
+
/* @__PURE__ */ jsxs35("button", { type: "button", className: "chalk-shell-detail-action", "aria-haspopup": "dialog", onClick: () => onDialog("shortcuts"), children: [
|
|
6101
6493
|
"Keyboard shortcuts",
|
|
6102
6494
|
/* @__PURE__ */ jsx54(ShellIcon, { name: "right", size: 18 })
|
|
6103
6495
|
] }),
|
|
6104
|
-
onReportProblem ? /* @__PURE__ */
|
|
6496
|
+
onReportProblem ? /* @__PURE__ */ jsxs35("button", { type: "button", className: "chalk-shell-detail-action", "aria-haspopup": "dialog", onClick: () => onDialog("report"), children: [
|
|
6105
6497
|
"Report a problem",
|
|
6106
6498
|
/* @__PURE__ */ jsx54(ShellIcon, { name: "right", size: 18 })
|
|
6107
6499
|
] }) : null
|
|
@@ -6181,18 +6573,19 @@ function formatDuration(seconds) {
|
|
|
6181
6573
|
}
|
|
6182
6574
|
|
|
6183
6575
|
// src/components/space-header/SpaceHeader.tsx
|
|
6184
|
-
import { Fragment as
|
|
6576
|
+
import { Fragment as Fragment23, jsx as jsx55, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
6185
6577
|
var SpaceHeader = React14.memo((props) => {
|
|
6186
6578
|
const { spaceName, duration = 0, isRecording = false, layout = "focus", onLayoutChange, className, weakConnection } = props;
|
|
6187
6579
|
const [sounds, setSounds] = useSoundsSetting();
|
|
6188
6580
|
const triggerRef = useRef20(null);
|
|
6189
|
-
const
|
|
6190
|
-
const [
|
|
6581
|
+
const focusScope = useRef20(null);
|
|
6582
|
+
const [open, setOpen] = useState32(false);
|
|
6583
|
+
const [dialog, setDialog] = useState32({ kind: "shortcuts", open: false });
|
|
6191
6584
|
const showShortcuts = useCallback6(() => setDialog({ kind: "shortcuts", open: true }), []);
|
|
6192
6585
|
useCallShortcuts(props.shortcuts, showShortcuts);
|
|
6193
6586
|
const phone = useMediaQuery("(max-width: 640px)");
|
|
6194
6587
|
const chevron = /* @__PURE__ */ jsx55("svg", { width: phone ? "16" : "14", height: phone ? "16" : "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", "aria-hidden": "true", children: /* @__PURE__ */ jsx55("path", { d: "m6 9 6 6 6-6" }) });
|
|
6195
|
-
const trigger = /* @__PURE__ */
|
|
6588
|
+
const trigger = /* @__PURE__ */ jsxs36("button", { ref: triggerRef, type: "button", "data-part": "call-name", "aria-label": "Call details", className: "chalk-call-name", children: [
|
|
6196
6589
|
/* @__PURE__ */ jsx55("span", { dir: "auto", children: spaceName }),
|
|
6197
6590
|
/* @__PURE__ */ jsx55("span", { "data-part": "call-timer", className: "chalk-call-timer", children: formatDuration(duration) }),
|
|
6198
6591
|
chevron
|
|
@@ -6201,26 +6594,28 @@ var SpaceHeader = React14.memo((props) => {
|
|
|
6201
6594
|
CallDetails,
|
|
6202
6595
|
{
|
|
6203
6596
|
...props,
|
|
6597
|
+
onReportProblem: props.reportUnavailableReason ? void 0 : props.onReportProblem,
|
|
6204
6598
|
onClose: () => setOpen(false),
|
|
6205
6599
|
sounds,
|
|
6206
6600
|
onSoundsChange: setSounds,
|
|
6207
6601
|
onDialog: (kind) => {
|
|
6208
6602
|
setOpen(false);
|
|
6209
|
-
|
|
6603
|
+
if (kind === "report" && props.onOpenReportProblem) props.onOpenReportProblem();
|
|
6604
|
+
else setDialog({ kind, open: true });
|
|
6210
6605
|
}
|
|
6211
6606
|
}
|
|
6212
6607
|
);
|
|
6213
|
-
return /* @__PURE__ */
|
|
6608
|
+
return /* @__PURE__ */ jsxs36("header", { ref: focusScope, "data-part": "header-region", className: cn("chalk-header", className), role: "banner", children: [
|
|
6214
6609
|
/* @__PURE__ */ jsx55(ShellStyles, {}),
|
|
6215
|
-
/* @__PURE__ */
|
|
6216
|
-
phone ? /* @__PURE__ */
|
|
6217
|
-
/* @__PURE__ */
|
|
6610
|
+
/* @__PURE__ */ jsxs36("div", { className: "chalk-header-title flex min-w-0 items-center gap-3", children: [
|
|
6611
|
+
phone ? /* @__PURE__ */ jsxs36(Fragment23, { children: [
|
|
6612
|
+
/* @__PURE__ */ jsxs36("button", { ref: triggerRef, type: "button", "data-call-link-trigger": true, "data-part": "call-name", className: "chalk-call-name chalk-call-name-phone", "aria-label": "Call details", "aria-haspopup": "dialog", "aria-expanded": open, onClick: () => setOpen(true), children: [
|
|
6218
6613
|
/* @__PURE__ */ jsx55("span", { dir: "auto", children: spaceName }),
|
|
6219
6614
|
chevron
|
|
6220
6615
|
] }),
|
|
6221
6616
|
/* @__PURE__ */ jsx55("span", { "data-part": "call-timer", className: "chalk-call-timer", children: formatDuration(duration) }),
|
|
6222
|
-
/* @__PURE__ */
|
|
6223
|
-
props.onCallLinkToggle ? /* @__PURE__ */
|
|
6617
|
+
/* @__PURE__ */ jsxs36(ChalkSheet, { variant: "details", open, onOpenChange: setOpen, title: spaceName, accessibleLabel: "Call details", children: [
|
|
6618
|
+
props.onCallLinkToggle ? /* @__PURE__ */ jsxs36(
|
|
6224
6619
|
"button",
|
|
6225
6620
|
{
|
|
6226
6621
|
type: "button",
|
|
@@ -6240,46 +6635,59 @@ var SpaceHeader = React14.memo((props) => {
|
|
|
6240
6635
|
] })
|
|
6241
6636
|
] }) : /* @__PURE__ */ jsx55(ChalkPopover, { open, onOpenChange: setOpen, tooltip: "Call details", trigger, label: "Call details", className: "chalk-call-details", alignOffset: -2, children: content }),
|
|
6242
6637
|
weakConnection ? /* @__PURE__ */ jsx55("span", { className: "chalk-shell-quality", role: "img", "aria-label": "Your connection is weak", children: [5, 8, 11, 15].map((height) => /* @__PURE__ */ jsx55("i", { style: { height } }, height)) }) : null,
|
|
6243
|
-
isRecording ? /* @__PURE__ */
|
|
6638
|
+
isRecording ? /* @__PURE__ */ jsxs36("span", { className: "chalk-shell-recording", children: [
|
|
6244
6639
|
/* @__PURE__ */ jsx55("i", {}),
|
|
6245
6640
|
"Rec"
|
|
6246
6641
|
] }) : null
|
|
6247
6642
|
] }),
|
|
6248
|
-
|
|
6249
|
-
|
|
6643
|
+
props.notices,
|
|
6644
|
+
/* @__PURE__ */ jsxs36("div", { className: "chalk-header-layout flex items-center gap-2", children: [
|
|
6645
|
+
props.onTogglePeople ? /* @__PURE__ */ jsxs36("button", { type: "button", className: "chalk-shell-people-pill", "aria-label": `People, ${props.people?.length ?? 0}`, onClick: props.onTogglePeople, children: [
|
|
6250
6646
|
/* @__PURE__ */ jsx55("span", { className: "chalk-shell-faces", children: props.people?.slice(0, 3).map((person) => /* @__PURE__ */ jsx55(Avatar, { name: person.displayName, size: "xs" }, person.participantId)) }),
|
|
6251
6647
|
/* @__PURE__ */ jsx55("span", { children: props.people?.length ?? 0 }),
|
|
6252
6648
|
props.knockCount ? /* @__PURE__ */ jsx55("span", { "aria-label": `${props.knockCount} waiting to join`, children: props.knockCount }) : null
|
|
6253
6649
|
] }) : null,
|
|
6254
6650
|
onLayoutChange ? /* @__PURE__ */ jsx55(LayoutMenu, { layout, onLayoutChange }) : null
|
|
6255
6651
|
] }),
|
|
6256
|
-
/* @__PURE__ */ jsx55(
|
|
6652
|
+
/* @__PURE__ */ jsx55(
|
|
6653
|
+
CallDialog,
|
|
6654
|
+
{
|
|
6655
|
+
focusScope,
|
|
6656
|
+
returnFocus: triggerRef,
|
|
6657
|
+
kind: dialog.kind,
|
|
6658
|
+
open: dialog.open,
|
|
6659
|
+
onClose: () => setDialog((current) => ({ ...current, open: false })),
|
|
6660
|
+
onReportProblem: props.onReportProblem,
|
|
6661
|
+
unavailableReason: props.reportUnavailableReason,
|
|
6662
|
+
diagnostics: props.diagnostics?.map(({ label, value }) => `${label}: ${value}`).join("\n") ?? ""
|
|
6663
|
+
}
|
|
6664
|
+
)
|
|
6257
6665
|
] });
|
|
6258
6666
|
});
|
|
6259
6667
|
SpaceHeader.displayName = "SpaceHeader";
|
|
6260
6668
|
|
|
6261
6669
|
// src/components/composite/ScreenShareView.tsx
|
|
6262
|
-
import { useEffect as useEffect23, useMemo as useMemo11, useRef as useRef21, useState as
|
|
6263
|
-
import { Fragment as
|
|
6264
|
-
function ScreenSharePresentation({ sharedByName, media, mediaVisible, state, isLocal = false, hasAudio = false, capture, primary = true, pinned, hidden, style, onClick, onDoubleClick, onStopSharing, onChangeShare, switcher, className }) {
|
|
6670
|
+
import { useEffect as useEffect23, useMemo as useMemo11, useRef as useRef21, useState as useState33 } from "react";
|
|
6671
|
+
import { Fragment as Fragment24, jsx as jsx56, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
6672
|
+
function ScreenSharePresentation({ sharedByName, media, mediaVisible, state, isLocal = false, hasAudio = false, capture: capture2, primary = true, pinned, hidden, style, onClick, onDoubleClick, onStopSharing, onChangeShare, switcher, className }) {
|
|
6265
6673
|
const root = useRef21(null);
|
|
6266
|
-
const [fill, setFill] =
|
|
6267
|
-
const [controlsOpen, setControlsOpen] =
|
|
6268
|
-
const [poppedOut, setPoppedOut] =
|
|
6269
|
-
const [zoom, setZoom] =
|
|
6270
|
-
const [pending, setPending] =
|
|
6271
|
-
const [error, setError] =
|
|
6674
|
+
const [fill, setFill] = useState33(false);
|
|
6675
|
+
const [controlsOpen, setControlsOpen] = useState33(false);
|
|
6676
|
+
const [poppedOut, setPoppedOut] = useState33(false);
|
|
6677
|
+
const [zoom, setZoom] = useState33(false);
|
|
6678
|
+
const [pending, setPending] = useState33(false);
|
|
6679
|
+
const [error, setError] = useState33(null);
|
|
6272
6680
|
const status = state ?? (mediaVisible ? "live" : "connecting");
|
|
6273
6681
|
const name = isLocal ? "Your screen" : `${sharedByName}'s screen`;
|
|
6274
|
-
const source =
|
|
6275
|
-
const run = async (command) => {
|
|
6682
|
+
const source = capture2?.surface === "window" ? "a window" : capture2?.surface === "browser" ? "a tab" : capture2?.surface === "monitor" ? "your screen" : null;
|
|
6683
|
+
const run = async (command, source2, action) => {
|
|
6276
6684
|
if (pending) return;
|
|
6277
6685
|
setPending(true);
|
|
6278
6686
|
setError(null);
|
|
6279
6687
|
try {
|
|
6280
6688
|
await command();
|
|
6281
6689
|
} catch (cause) {
|
|
6282
|
-
setError(cause instanceof Error ? cause.message : "The share could not be changed.");
|
|
6690
|
+
setError(source2 ? commandFailureMessage(commandFailure(cause), source2, action) : cause instanceof Error ? cause.message : "The share could not be changed.");
|
|
6283
6691
|
} finally {
|
|
6284
6692
|
setPending(false);
|
|
6285
6693
|
}
|
|
@@ -6317,12 +6725,12 @@ function ScreenSharePresentation({ sharedByName, media, mediaVisible, state, isL
|
|
|
6317
6725
|
hidden,
|
|
6318
6726
|
style,
|
|
6319
6727
|
className: cn("h-full w-full", className),
|
|
6320
|
-
chip: /* @__PURE__ */
|
|
6728
|
+
chip: /* @__PURE__ */ jsxs37(Fragment24, { children: [
|
|
6321
6729
|
/* @__PURE__ */ jsx56(StageIcon, { name: "share", size: 14, className: "shrink-0" }),
|
|
6322
6730
|
/* @__PURE__ */ jsx56("span", { dir: "auto", className: "min-w-0 truncate [unicode-bidi:plaintext]", children: name }),
|
|
6323
6731
|
!isLocal && hasAudio ? /* @__PURE__ */ jsx56(StageIcon, { name: "volume", size: 14, "aria-label": "With share audio", className: "shrink-0" }) : null
|
|
6324
6732
|
] }),
|
|
6325
|
-
children: /* @__PURE__ */
|
|
6733
|
+
children: /* @__PURE__ */ jsxs37(
|
|
6326
6734
|
"div",
|
|
6327
6735
|
{
|
|
6328
6736
|
ref: root,
|
|
@@ -6339,43 +6747,43 @@ function ScreenSharePresentation({ sharedByName, media, mediaVisible, state, isL
|
|
|
6339
6747
|
children: media
|
|
6340
6748
|
}
|
|
6341
6749
|
) }),
|
|
6342
|
-
poppedOut ? /* @__PURE__ */
|
|
6750
|
+
poppedOut ? /* @__PURE__ */ jsxs37("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-2.5 p-4 text-center text-[var(--chalk-muted-text)]", children: [
|
|
6343
6751
|
/* @__PURE__ */ jsx56(StageIcon, { name: "pip", size: 32 }),
|
|
6344
|
-
/* @__PURE__ */
|
|
6752
|
+
/* @__PURE__ */ jsxs37("p", { className: "font-medium text-[var(--chalk-text)]", children: [
|
|
6345
6753
|
name,
|
|
6346
6754
|
" is in a picture-in-picture window"
|
|
6347
6755
|
] }),
|
|
6348
6756
|
/* @__PURE__ */ jsx56(ChalkButton, { className: "!h-8 !px-3", onClick: () => void popout(), children: "Bring it back" })
|
|
6349
6757
|
] }) : null,
|
|
6350
|
-
status === "connecting" ? /* @__PURE__ */
|
|
6758
|
+
status === "connecting" ? /* @__PURE__ */ jsxs37("div", { role: "status", className: "absolute inset-0 flex flex-col items-center justify-center gap-3 bg-[var(--chalk-tile)] text-[var(--chalk-muted-text)]", children: [
|
|
6351
6759
|
/* @__PURE__ */ jsx56("span", { className: "h-[18px] w-[18px] rounded-[50%] border-2 border-[var(--chalk-line-strong)] border-t-[var(--chalk-text)] motion-safe:animate-spin motion-safe:[animation-duration:.9s] motion-reduce:border-t-[var(--chalk-muted-text)]" }),
|
|
6352
|
-
/* @__PURE__ */
|
|
6760
|
+
/* @__PURE__ */ jsxs37("p", { className: "font-medium text-[var(--chalk-text)]", children: [
|
|
6353
6761
|
"Connecting to ",
|
|
6354
6762
|
sharedByName,
|
|
6355
6763
|
"\u2019s screen\u2026"
|
|
6356
6764
|
] })
|
|
6357
6765
|
] }) : null,
|
|
6358
|
-
status === "paused" ? /* @__PURE__ */
|
|
6766
|
+
status === "paused" ? /* @__PURE__ */ jsxs37("div", { role: "status", className: "pointer-events-none absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 text-white", children: [
|
|
6359
6767
|
/* @__PURE__ */ jsx56("span", { className: "grid h-12 w-12 place-items-center rounded-[50%] bg-[rgba(12,14,18,.82)]", children: /* @__PURE__ */ jsx56(StageIcon, { name: "pause", size: 24 }) }),
|
|
6360
|
-
/* @__PURE__ */
|
|
6768
|
+
/* @__PURE__ */ jsxs37("p", { className: "rounded-[8px] bg-[rgba(12,14,18,.82)] px-3 py-1.5 font-semibold", children: [
|
|
6361
6769
|
sharedByName,
|
|
6362
6770
|
" paused sharing"
|
|
6363
6771
|
] })
|
|
6364
6772
|
] }) : null,
|
|
6365
|
-
status === "low-quality" ? /* @__PURE__ */
|
|
6773
|
+
status === "low-quality" ? /* @__PURE__ */ jsxs37("div", { role: "status", "data-part": "share-low-quality", className: "absolute top-2 left-2 z-30 flex h-7 items-center gap-2 rounded-[6px] bg-[rgba(12,14,18,.82)] px-2.5 text-[12px] font-medium text-white", children: [
|
|
6366
6774
|
/* @__PURE__ */ jsx56(SignalBars, {}),
|
|
6367
|
-
/* @__PURE__ */
|
|
6775
|
+
/* @__PURE__ */ jsxs37("span", { children: [
|
|
6368
6776
|
sharedByName,
|
|
6369
6777
|
"\u2019s connection is slow"
|
|
6370
6778
|
] })
|
|
6371
6779
|
] }) : null,
|
|
6372
6780
|
primary ? switcher : null,
|
|
6373
|
-
isLocal && primary ? /* @__PURE__ */
|
|
6374
|
-
/* @__PURE__ */
|
|
6781
|
+
isLocal && primary ? /* @__PURE__ */ jsxs37("div", { "data-part": "share-local-overlay", role: "group", "aria-label": "Your share", className: "absolute top-2.5 right-2.5 left-2.5 z-30 flex items-center gap-2 rounded-[12px] bg-[rgba(12,14,18,.86)] p-2 pl-3.5 text-white max-[640px]:flex-wrap", children: [
|
|
6782
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
6375
6783
|
/* @__PURE__ */ jsx56("b", { className: "truncate font-semibold", children: source ? `You\u2019re sharing ${source}` : "You\u2019re screen sharing" }),
|
|
6376
|
-
|
|
6784
|
+
capture2?.surface === "monitor" || capture2?.surface === "browser" ? /* @__PURE__ */ jsxs37("span", { className: "text-[12px] text-[#c9cbd1]", children: [
|
|
6377
6785
|
"Seeing a mirror effect? That\u2019s normal when you share ",
|
|
6378
|
-
|
|
6786
|
+
capture2.surface === "browser" ? "this tab" : "your whole screen",
|
|
6379
6787
|
"."
|
|
6380
6788
|
] }) : null
|
|
6381
6789
|
] }),
|
|
@@ -6387,12 +6795,12 @@ function ScreenSharePresentation({ sharedByName, media, mediaVisible, state, isL
|
|
|
6387
6795
|
{ surface: "monitor", label: "Entire screen" },
|
|
6388
6796
|
{ surface: "window", label: "Window" },
|
|
6389
6797
|
{ surface: "browser", label: "Browser tab" }
|
|
6390
|
-
].map((option) => /* @__PURE__ */ jsx56(ChalkMenuItem, { onClick: () => void run(() => onChangeShare({ surface: option.surface, audio: option.surface === "browser" })), children: option.label }, option.surface))
|
|
6798
|
+
].map((option) => /* @__PURE__ */ jsx56(ChalkMenuItem, { onClick: () => void run(() => onChangeShare({ surface: option.surface, audio: option.surface === "browser" }), "screen", "start"), children: option.label }, option.surface))
|
|
6391
6799
|
}
|
|
6392
6800
|
) : null,
|
|
6393
|
-
onStopSharing ? /* @__PURE__ */ jsx56(ChalkButton, { disabled: pending, tone: "danger", className: "!h-8 !bg-[var(--chalk-danger)] !px-3 !text-white hover:!bg-[var(--chalk-danger-hover)]", onClick: () => void run(onStopSharing), children: "Stop sharing" }) : null
|
|
6801
|
+
onStopSharing ? /* @__PURE__ */ jsx56(ChalkButton, { disabled: pending, tone: "danger", className: "!h-8 !bg-[var(--chalk-danger)] !px-3 !text-white hover:!bg-[var(--chalk-danger-hover)]", onClick: () => void run(onStopSharing, "screen", "stop"), children: "Stop sharing" }) : null
|
|
6394
6802
|
] }) : null,
|
|
6395
|
-
primary && !isLocal && status !== "connecting" ? /* @__PURE__ */
|
|
6803
|
+
primary && !isLocal && status !== "connecting" ? /* @__PURE__ */ jsxs37("div", { role: "toolbar", "aria-label": "Share controls", className: cn("absolute right-2 bottom-2 z-30 flex gap-1.5 opacity-0 transition-opacity duration-150 group-hover/tile:opacity-100 focus-within:opacity-100", controlsOpen && "opacity-100"), children: [
|
|
6396
6804
|
/* @__PURE__ */ jsx56(ShareControl2, { label: fill ? "Fit the whole screen" : "Fill the tile", pressed: fill, onClick: () => setFill(!fill), children: /* @__PURE__ */ jsx56(StageIcon, { name: fill ? "fit" : "fill", size: 16 }) }),
|
|
6397
6805
|
/* @__PURE__ */ jsx56(ShareControl2, { label: zoom ? "Zoom out" : "Zoom in", pressed: zoom, onClick: () => setZoom(!zoom), children: /* @__PURE__ */ jsx56(StageIcon, { name: zoom ? "zoom-out" : "zoom-in", size: 16 }) }),
|
|
6398
6806
|
/* @__PURE__ */ jsx56(ShareControl2, { label: "Pop out", onClick: () => void popout(), children: /* @__PURE__ */ jsx56(StageIcon, { name: "pip", size: 16 }) }),
|
|
@@ -6454,16 +6862,17 @@ function ScreenShareView(props) {
|
|
|
6454
6862
|
}
|
|
6455
6863
|
|
|
6456
6864
|
// src/components/stage/Stage.tsx
|
|
6457
|
-
import { useCallback as useCallback7, useEffect as useEffect24, useMemo as useMemo12, useRef as useRef24, useState as
|
|
6865
|
+
import { useCallback as useCallback7, useEffect as useEffect24, useLayoutEffect as useLayoutEffect5, useMemo as useMemo12, useRef as useRef24, useState as useState35 } from "react";
|
|
6866
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
6458
6867
|
|
|
6459
6868
|
// src/components/stage/useStageDimensions.ts
|
|
6460
|
-
import { useLayoutEffect as
|
|
6461
|
-
import { flushSync } from "react-dom";
|
|
6869
|
+
import { useLayoutEffect as useLayoutEffect4, useRef as useRef22, useState as useState34 } from "react";
|
|
6870
|
+
import { flushSync as flushSync3 } from "react-dom";
|
|
6462
6871
|
function useStageDimensions(fallback3) {
|
|
6463
6872
|
const ref = useRef22(null);
|
|
6464
6873
|
const current = useRef22(fallback3);
|
|
6465
|
-
const [dimensions, setDimensions] =
|
|
6466
|
-
|
|
6874
|
+
const [dimensions, setDimensions] = useState34(fallback3);
|
|
6875
|
+
useLayoutEffect4(() => {
|
|
6467
6876
|
const element = ref.current;
|
|
6468
6877
|
if (!element || typeof ResizeObserver === "undefined") return;
|
|
6469
6878
|
const style = getComputedStyle(element);
|
|
@@ -6481,7 +6890,7 @@ function useStageDimensions(fallback3) {
|
|
|
6481
6890
|
if (width <= 0 || height <= 0 || width === current.current.width && height === current.current.height) return;
|
|
6482
6891
|
const next = { width, height };
|
|
6483
6892
|
current.current = next;
|
|
6484
|
-
|
|
6893
|
+
flushSync3(() => setDimensions(next));
|
|
6485
6894
|
});
|
|
6486
6895
|
observer.observe(element);
|
|
6487
6896
|
return () => observer.disconnect();
|
|
@@ -6503,7 +6912,7 @@ var StageMotion = class extends Component {
|
|
|
6503
6912
|
getSnapshotBeforeUpdate(previous) {
|
|
6504
6913
|
if (!this.props.animate || !this.animationsSupported() || previous.motionKey === this.props.motionKey) return null;
|
|
6505
6914
|
const elements = this.elements();
|
|
6506
|
-
return { play: captureFlip(elements), previous: new Set(elements) };
|
|
6915
|
+
return { play: captureFlip(elements.filter((element) => element.dataset.stageItem !== WHITEBOARD_ITEM_ID)), previous: new Set(elements) };
|
|
6507
6916
|
}
|
|
6508
6917
|
componentDidUpdate(previous, _state, snapshot) {
|
|
6509
6918
|
if (!this.animationsSupported()) return;
|
|
@@ -6534,7 +6943,7 @@ var StageMotion = class extends Component {
|
|
|
6534
6943
|
} else if (entering.has(element)) {
|
|
6535
6944
|
const transform = getComputedStyle(element).transform;
|
|
6536
6945
|
const enter = element.animate(
|
|
6537
|
-
[
|
|
6946
|
+
element.dataset.stageItem === WHITEBOARD_ITEM_ID ? [{ opacity: 0 }, { opacity: 1 }] : [
|
|
6538
6947
|
{ opacity: 0, transform: `${transform} scale(.97)` },
|
|
6539
6948
|
{ opacity: 1, transform }
|
|
6540
6949
|
],
|
|
@@ -6555,7 +6964,7 @@ var StageMotion = class extends Component {
|
|
|
6555
6964
|
|
|
6556
6965
|
// src/components/stage/StageContentTile.tsx
|
|
6557
6966
|
import React17, { useRef as useRef23 } from "react";
|
|
6558
|
-
import { Fragment as
|
|
6967
|
+
import { Fragment as Fragment25, jsx as jsx58, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
6559
6968
|
var BOARD_ACCENT = "var(--chalk-app-line-strong, currentColor)";
|
|
6560
6969
|
function contentTileLabel(item) {
|
|
6561
6970
|
return item.kind === "whiteboard" ? "Whiteboard tile" : `Screen share tile for ${item.participant.displayName}`;
|
|
@@ -6579,7 +6988,7 @@ var StageContentTile = React17.memo(function StageContentTile2({ item, active, .
|
|
|
6579
6988
|
}
|
|
6580
6989
|
);
|
|
6581
6990
|
});
|
|
6582
|
-
var StageContentTileSurface = React17.memo(function StageContentTileSurface2({ item, pinned, onClick, onDoubleClick, className, style, hidden, media, mediaVisible, primary, state, onStopSharing, onChangeShare, capture, switcher }) {
|
|
6991
|
+
var StageContentTileSurface = React17.memo(function StageContentTileSurface2({ item, pinned, onClick, onDoubleClick, className, style, hidden, media, mediaVisible, primary, state, onStopSharing, onChangeShare, capture: capture2, switcher }) {
|
|
6583
6992
|
if (item.kind === "screen-share")
|
|
6584
6993
|
return /* @__PURE__ */ jsx58(
|
|
6585
6994
|
ScreenSharePresentation,
|
|
@@ -6599,12 +7008,12 @@ var StageContentTileSurface = React17.memo(function StageContentTileSurface2({ i
|
|
|
6599
7008
|
hidden,
|
|
6600
7009
|
onStopSharing,
|
|
6601
7010
|
onChangeShare,
|
|
6602
|
-
capture,
|
|
7011
|
+
capture: capture2,
|
|
6603
7012
|
switcher
|
|
6604
7013
|
}
|
|
6605
7014
|
);
|
|
6606
7015
|
const accentColor = BOARD_ACCENT;
|
|
6607
|
-
return /* @__PURE__ */
|
|
7016
|
+
return /* @__PURE__ */ jsxs38(
|
|
6608
7017
|
TileShell,
|
|
6609
7018
|
{
|
|
6610
7019
|
label: contentTileLabel(item),
|
|
@@ -6616,7 +7025,7 @@ var StageContentTileSurface = React17.memo(function StageContentTileSurface2({ i
|
|
|
6616
7025
|
style,
|
|
6617
7026
|
dataTour: "video-grid",
|
|
6618
7027
|
hidden,
|
|
6619
|
-
chip: primary ? null : /* @__PURE__ */
|
|
7028
|
+
chip: primary ? null : /* @__PURE__ */ jsxs38(Fragment25, { children: [
|
|
6620
7029
|
/* @__PURE__ */ jsx58(StageIcon, { name: "pen", size: 14, className: "shrink-0" }),
|
|
6621
7030
|
/* @__PURE__ */ jsx58("span", { className: "min-w-0 truncate", children: contentTileName(item) })
|
|
6622
7031
|
] }),
|
|
@@ -6631,9 +7040,49 @@ StageContentTile.displayName = "StageContentTile";
|
|
|
6631
7040
|
StageContentTileSurface.displayName = "StageContentTileSurface";
|
|
6632
7041
|
|
|
6633
7042
|
// src/components/stage/Stage.tsx
|
|
6634
|
-
import { jsx as jsx59, jsxs as
|
|
7043
|
+
import { Fragment as Fragment26, jsx as jsx59, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
6635
7044
|
var FALLBACK_BOX = { width: 960, height: 540 };
|
|
6636
7045
|
var TILE_FILL = { width: "100%", height: "100%" };
|
|
7046
|
+
function createContentPlacement() {
|
|
7047
|
+
let host = null;
|
|
7048
|
+
let home = null;
|
|
7049
|
+
let overflow = null;
|
|
7050
|
+
const move = () => {
|
|
7051
|
+
const target = overflow ?? home;
|
|
7052
|
+
if (host && target && host.parentNode !== target) target.appendChild(host);
|
|
7053
|
+
};
|
|
7054
|
+
return {
|
|
7055
|
+
attachHost: (element) => {
|
|
7056
|
+
host = element;
|
|
7057
|
+
move();
|
|
7058
|
+
},
|
|
7059
|
+
attachHome: (element) => {
|
|
7060
|
+
home = element;
|
|
7061
|
+
move();
|
|
7062
|
+
},
|
|
7063
|
+
attachOverflow: (element) => {
|
|
7064
|
+
overflow = element;
|
|
7065
|
+
move();
|
|
7066
|
+
}
|
|
7067
|
+
};
|
|
7068
|
+
}
|
|
7069
|
+
function PersistentStageContent({ placement, children }) {
|
|
7070
|
+
const [host, setHost] = useState35(null);
|
|
7071
|
+
useLayoutEffect5(() => {
|
|
7072
|
+
const element = document.createElement("div");
|
|
7073
|
+
Object.assign(element.style, TILE_FILL);
|
|
7074
|
+
placement.attachHost(element);
|
|
7075
|
+
setHost(element);
|
|
7076
|
+
return () => {
|
|
7077
|
+
placement.attachHost(null);
|
|
7078
|
+
element.remove();
|
|
7079
|
+
};
|
|
7080
|
+
}, [placement]);
|
|
7081
|
+
return /* @__PURE__ */ jsxs39(Fragment26, { children: [
|
|
7082
|
+
/* @__PURE__ */ jsx59("div", { ref: placement.attachHome, style: TILE_FILL }),
|
|
7083
|
+
host && createPortal2(children, host)
|
|
7084
|
+
] });
|
|
7085
|
+
}
|
|
6637
7086
|
function frameStyle(frame) {
|
|
6638
7087
|
return { position: "absolute", left: 0, top: 0, transform: `translate(${frame.x}px, ${frame.y}px)`, width: frame.width, height: frame.height, zIndex: frame.role === "primary" ? 1 : 2 };
|
|
6639
7088
|
}
|
|
@@ -6662,14 +7111,15 @@ function Stage({
|
|
|
6662
7111
|
}) {
|
|
6663
7112
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
6664
7113
|
const { ref: boxRef, dimensions: box } = useStageDimensions(FALLBACK_BOX);
|
|
6665
|
-
const [overflowOpen, setOverflowOpen] =
|
|
6666
|
-
const [shareAspects, setShareAspects] =
|
|
6667
|
-
const [uncontrolledPinnedId, setUncontrolledPinnedId] =
|
|
7114
|
+
const [overflowOpen, setOverflowOpen] = useState35(false);
|
|
7115
|
+
const [shareAspects, setShareAspects] = useState35(/* @__PURE__ */ new Map());
|
|
7116
|
+
const [uncontrolledPinnedId, setUncontrolledPinnedId] = useState35(null);
|
|
6668
7117
|
const activePinnedId = pinnedId === void 0 ? uncontrolledPinnedId : pinnedId;
|
|
6669
7118
|
const orderRef = useRef24([]);
|
|
6670
7119
|
const seenAtRef = useRef24(/* @__PURE__ */ new Map());
|
|
6671
7120
|
const nextSeenRef = useRef24(0);
|
|
6672
7121
|
const lastSpeakerRef = useRef24(null);
|
|
7122
|
+
const lastRemoteSpeakerRef = useRef24(null);
|
|
6673
7123
|
const ordered = useMemo12(() => {
|
|
6674
7124
|
if (!interactive) {
|
|
6675
7125
|
seenAtRef.current = new Map(items.map((item, index) => [item.id, index]));
|
|
@@ -6692,8 +7142,9 @@ function Stage({
|
|
|
6692
7142
|
}, [ordered]);
|
|
6693
7143
|
useEffect24(() => {
|
|
6694
7144
|
orderRef.current = ordered.map((item) => item.id);
|
|
6695
|
-
const speaking = ordered
|
|
6696
|
-
if (speaking) lastSpeakerRef.current = speaking
|
|
7145
|
+
const speaking = speakingParticipantId(ordered);
|
|
7146
|
+
if (speaking) lastSpeakerRef.current = speaking;
|
|
7147
|
+
lastRemoteSpeakerRef.current = floatingSpeakerId(ordered, lastRemoteSpeakerRef.current);
|
|
6697
7148
|
}, [ordered]);
|
|
6698
7149
|
const primary = useMemo12(() => layout === "grid" ? null : choosePrimary(ordered, { layout, pinnedId: activePinnedId, lastSpeakerId: interactive ? lastSpeakerRef.current : null, seenAt: seenAtRef.current }), [activePinnedId, interactive, layout, ordered]);
|
|
6699
7150
|
const geometry = useMemo12(() => {
|
|
@@ -6711,21 +7162,39 @@ function Stage({
|
|
|
6711
7162
|
);
|
|
6712
7163
|
}
|
|
6713
7164
|
const track = primary.kind === "screen-share" ? primary.participant.screenShareTrack : null;
|
|
6714
|
-
const
|
|
7165
|
+
const settings2 = track?.getSettings();
|
|
6715
7166
|
const observedAspect = shareAspects.get(primary.id);
|
|
6716
|
-
const aspect = primary.kind === "whiteboard" ? null : observedAspect ?? (primary.kind === "screen-share" && primary.participant.screenShareAspect ? primary.participant.screenShareAspect :
|
|
7167
|
+
const aspect = primary.kind === "whiteboard" ? null : observedAspect ?? (primary.kind === "screen-share" && primary.participant.screenShareAspect ? primary.participant.screenShareAspect : settings2?.width && settings2.height ? settings2.width / settings2.height : 16 / 9);
|
|
6717
7168
|
const remaining = ordered.filter((item) => item.id !== primary.id);
|
|
6718
7169
|
const strip = [...remaining.filter(isContentItem), ...remaining.filter((item) => !isContentItem(item))];
|
|
7170
|
+
const speakerId = floatingSpeakerId(remaining, interactive ? lastRemoteSpeakerRef.current : null);
|
|
7171
|
+
const localId = remaining.find((item) => item.kind === "participant" && item.participant.isLocal)?.id ?? null;
|
|
6719
7172
|
return fitSpotlight(
|
|
6720
7173
|
box,
|
|
6721
7174
|
primary.id,
|
|
6722
7175
|
strip.map((item) => item.id),
|
|
6723
|
-
{
|
|
7176
|
+
{
|
|
7177
|
+
...DEFAULT_SPOTLIGHT_OPTIONS,
|
|
7178
|
+
primaryAspect: aspect,
|
|
7179
|
+
content: primary.kind !== "participant",
|
|
7180
|
+
floatingPhonePeople: primary.kind === "whiteboard",
|
|
7181
|
+
speakerId,
|
|
7182
|
+
localId,
|
|
7183
|
+
wideIds: primary.kind === "screen-share" ? ordered.filter((item) => item.kind === "whiteboard").map((item) => item.id) : wideIds,
|
|
7184
|
+
maxPerPage
|
|
7185
|
+
}
|
|
6724
7186
|
);
|
|
6725
|
-
}, [activePinnedId, box, layout, maxPerPage, minTileWidth, ordered, primary, shareAspects]);
|
|
7187
|
+
}, [activePinnedId, box, interactive, layout, maxPerPage, minTileWidth, ordered, primary, shareAspects]);
|
|
6726
7188
|
const framesById = useMemo12(() => new Map(geometry.frames.map((frame) => [frame.id, frame])), [geometry.frames]);
|
|
7189
|
+
const foldedContent = ordered.filter((item) => item.kind !== "participant" && !framesById.has(item.id));
|
|
7190
|
+
const renderContent = (item, context, primaryRenderer) => {
|
|
7191
|
+
if (primaryRenderer && renderPrimaryContent) return /* @__PURE__ */ jsx59(StageContentTileSurface, { item, ...context, mediaVisible: true, media: renderPrimaryContent(item) });
|
|
7192
|
+
if (renderContentTile) return renderContentTile(item, context);
|
|
7193
|
+
if (renderPrimaryContent) return /* @__PURE__ */ jsx59(StageContentTileSurface, { item, ...context, mediaVisible: true, media: renderPrimaryContent(item) });
|
|
7194
|
+
return /* @__PURE__ */ jsx59(StageContentTile, { item, ...context });
|
|
7195
|
+
};
|
|
6727
7196
|
const animate = animateOverride ?? !prefersReducedMotion;
|
|
6728
|
-
const [displayed, setDisplayed] =
|
|
7197
|
+
const [displayed, setDisplayed] = useState35({
|
|
6729
7198
|
source: ordered,
|
|
6730
7199
|
geometry,
|
|
6731
7200
|
tiles: ordered.map((item) => ({ item, frame: framesById.get(item.id), leaving: false }))
|
|
@@ -6735,6 +7204,19 @@ function Stage({
|
|
|
6735
7204
|
const tiles = ordered.map((item) => ({ item, frame: framesById.get(item.id), leaving: false }));
|
|
6736
7205
|
setDisplayed({ source: ordered, geometry, tiles: [...tiles, ...animate ? displayed.tiles.filter((tile) => !present.has(tile.item.id)).map((tile) => ({ ...tile, leaving: true, departedAt: tile.departedAt ?? performance.now() })) : []] });
|
|
6737
7206
|
}
|
|
7207
|
+
const contentPlacements = useRef24(/* @__PURE__ */ new Map());
|
|
7208
|
+
const contentPlacement = (id) => {
|
|
7209
|
+
let placement = contentPlacements.current.get(id);
|
|
7210
|
+
if (!placement) {
|
|
7211
|
+
placement = createContentPlacement();
|
|
7212
|
+
contentPlacements.current.set(id, placement);
|
|
7213
|
+
}
|
|
7214
|
+
return placement;
|
|
7215
|
+
};
|
|
7216
|
+
useEffect24(() => {
|
|
7217
|
+
const present = new Set(displayed.tiles.map(({ item }) => item.id));
|
|
7218
|
+
for (const id of contentPlacements.current.keys()) if (!present.has(id)) contentPlacements.current.delete(id);
|
|
7219
|
+
}, [displayed.tiles]);
|
|
6738
7220
|
useEffect24(() => {
|
|
6739
7221
|
const departing = displayed.tiles.filter((tile) => tile.leaving);
|
|
6740
7222
|
if (!departing.length) return;
|
|
@@ -6791,8 +7273,8 @@ function Stage({
|
|
|
6791
7273
|
return /* @__PURE__ */ jsx59("div", { className: cn("flex h-full w-full items-center justify-center px-6 py-10", className), "data-tour": "video-grid", children: emptyState });
|
|
6792
7274
|
}
|
|
6793
7275
|
const participantCount = ordered.filter((item) => item.kind === "participant").length;
|
|
6794
|
-
return /* @__PURE__ */
|
|
6795
|
-
/* @__PURE__ */ jsx59("div", { ref: boxRef, className: "relative h-full w-full outline-none", role: "group", "aria-label": `Stage with ${participantCount} ${participantCount === 1 ? "participant" : "participants"}`, "aria-disabled": interactive ? void 0 : true, "data-testid": "stage", children: /* @__PURE__ */
|
|
7276
|
+
return /* @__PURE__ */ jsxs39("div", { className: cn("relative h-full w-full", className), "data-tour": "video-grid", children: [
|
|
7277
|
+
/* @__PURE__ */ jsx59("div", { ref: boxRef, className: "relative h-full w-full outline-none", role: "group", "aria-label": `Stage with ${participantCount} ${participantCount === 1 ? "participant" : "participants"}`, "aria-disabled": interactive ? void 0 : true, "data-testid": "stage", children: /* @__PURE__ */ jsxs39(StageMotion, { rootRef: tilesRef, motionKey, animate, children: [
|
|
6796
7278
|
displayed.tiles.map(({ item, frame, leaving }) => {
|
|
6797
7279
|
const onPage = Boolean(frame) && !leaving;
|
|
6798
7280
|
const style = TILE_FILL;
|
|
@@ -6821,14 +7303,10 @@ function Stage({
|
|
|
6821
7303
|
gradientPreference
|
|
6822
7304
|
}
|
|
6823
7305
|
);
|
|
6824
|
-
} else if (frame?.role === "primary" && renderPrimaryContent) {
|
|
6825
|
-
content = /* @__PURE__ */ jsx59(StageContentTileSurface, { item, ...renderContext, mediaVisible: true, media: renderPrimaryContent(item) });
|
|
6826
|
-
} else if (renderContentTile) {
|
|
6827
|
-
content = renderContentTile(item, renderContext);
|
|
6828
|
-
} else if (renderPrimaryContent) {
|
|
6829
|
-
content = /* @__PURE__ */ jsx59(StageContentTileSurface, { item, ...renderContext, mediaVisible: true, media: renderPrimaryContent(item) });
|
|
6830
7306
|
} else {
|
|
6831
|
-
|
|
7307
|
+
const inOverflow = overflowOpen && foldedContent.some((folded) => folded.id === item.id);
|
|
7308
|
+
const context = inOverflow ? { ...renderContext, active: true, primary: true, hidden: false, onClick: void 0, onDoubleClick: void 0 } : renderContext;
|
|
7309
|
+
content = /* @__PURE__ */ jsx59(PersistentStageContent, { placement: contentPlacement(item.id), children: renderContent(item, context, renderContext.primary) });
|
|
6832
7310
|
}
|
|
6833
7311
|
return /* @__PURE__ */ jsx59(
|
|
6834
7312
|
"div",
|
|
@@ -6845,15 +7323,16 @@ function Stage({
|
|
|
6845
7323
|
item.id
|
|
6846
7324
|
);
|
|
6847
7325
|
}),
|
|
6848
|
-
geometry.frames.filter((frame) => frame.id === MORE_TILE_ID).map((frame) => /* @__PURE__ */
|
|
7326
|
+
geometry.frames.filter((frame) => frame.id === MORE_TILE_ID).map((frame) => /* @__PURE__ */ jsxs39(
|
|
6849
7327
|
"button",
|
|
6850
7328
|
{
|
|
6851
7329
|
type: "button",
|
|
6852
7330
|
"data-stage-item": MORE_TILE_ID,
|
|
7331
|
+
"data-stage-role": frame.role,
|
|
6853
7332
|
style: frameStyle(frame),
|
|
6854
|
-
onClick: onOverflowClick ?? (() => setOverflowOpen(true)),
|
|
7333
|
+
onClick: foldedContent.length ? () => setOverflowOpen(true) : onOverflowClick ?? (() => setOverflowOpen(true)),
|
|
6855
7334
|
disabled: !interactive,
|
|
6856
|
-
"aria-label": `Show ${geometry.overflowCount} more participants`,
|
|
7335
|
+
"aria-label": `Show ${geometry.overflowCount} more ${foldedContent.length ? "items" : "participants"}`,
|
|
6857
7336
|
className: "grid place-items-center rounded-[12px] bg-[var(--chalk-raised)] text-[22px] font-semibold text-[var(--chalk-text)] hover:bg-[var(--chalk-hover)] max-[640px]:rounded-[14px]",
|
|
6858
7337
|
children: [
|
|
6859
7338
|
"+",
|
|
@@ -6863,23 +7342,26 @@ function Stage({
|
|
|
6863
7342
|
frame.id
|
|
6864
7343
|
))
|
|
6865
7344
|
] }) }),
|
|
6866
|
-
/* @__PURE__ */
|
|
6867
|
-
"
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
7345
|
+
/* @__PURE__ */ jsxs39(ChalkSheet, { variant: "stage", open: overflowOpen, onOpenChange: setOverflowOpen, title: foldedContent.length ? "People and shared content" : "People", children: [
|
|
7346
|
+
overflowOpen && foldedContent.map((item) => /* @__PURE__ */ jsx59("div", { ref: contentPlacement(item.id).attachOverflow, className: "relative mb-3 aspect-video max-h-full w-full" }, item.id)),
|
|
7347
|
+
ordered.filter((item) => item.kind === "participant").map((item) => /* @__PURE__ */ jsxs39(
|
|
7348
|
+
"button",
|
|
7349
|
+
{
|
|
7350
|
+
type: "button",
|
|
7351
|
+
className: "min-h-11 w-full rounded-xl px-4 text-left hover:bg-[var(--chalk-hover)]",
|
|
7352
|
+
onClick: () => {
|
|
7353
|
+
handlersById.get(item.id)?.onClick();
|
|
7354
|
+
setOverflowOpen(false);
|
|
7355
|
+
},
|
|
7356
|
+
children: [
|
|
7357
|
+
clickAction === "follow" && !item.participant.isLocal ? `${followingId === item.id ? "Stop following" : "Follow"} ` : "",
|
|
7358
|
+
item.participant.displayName,
|
|
7359
|
+
item.participant.isMuted ? " \xB7 Muted" : ""
|
|
7360
|
+
]
|
|
6874
7361
|
},
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
item.participant.isMuted ? " \xB7 Muted" : ""
|
|
6879
|
-
]
|
|
6880
|
-
},
|
|
6881
|
-
item.id
|
|
6882
|
-
)) })
|
|
7362
|
+
item.id
|
|
7363
|
+
))
|
|
7364
|
+
] })
|
|
6883
7365
|
] });
|
|
6884
7366
|
}
|
|
6885
7367
|
Stage.displayName = "Stage";
|
|
@@ -6966,7 +7448,7 @@ WhiteboardView.displayName = "WhiteboardView";
|
|
|
6966
7448
|
|
|
6967
7449
|
// src/components/call-card/CallCard.tsx
|
|
6968
7450
|
import { useEffect as useEffect25, useId as useId2, useRef as useRef25 } from "react";
|
|
6969
|
-
import { Fragment as
|
|
7451
|
+
import { Fragment as Fragment27, jsx as jsx62, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
6970
7452
|
function CallCard({ state, onClose, interactive = true, children, panel, onPanelChange, peopleCount, chatEnabled = true, participantsEnabled = true }) {
|
|
6971
7453
|
const phone = useIsMobile();
|
|
6972
7454
|
const id = useId2();
|
|
@@ -6989,9 +7471,9 @@ function CallCard({ state, onClose, interactive = true, children, panel, onPanel
|
|
|
6989
7471
|
openerRef.current = null;
|
|
6990
7472
|
if (opener?.isConnected) opener.focus({ preventScroll: true });
|
|
6991
7473
|
}, [interactive, state]);
|
|
6992
|
-
const content = /* @__PURE__ */
|
|
7474
|
+
const content = /* @__PURE__ */ jsxs40(Fragment27, { children: [
|
|
6993
7475
|
/* @__PURE__ */ jsx62(CallCardStyles, {}),
|
|
6994
|
-
onPanelChange ? /* @__PURE__ */
|
|
7476
|
+
onPanelChange ? /* @__PURE__ */ jsxs40(
|
|
6995
7477
|
"div",
|
|
6996
7478
|
{
|
|
6997
7479
|
className: "call-card-tabs",
|
|
@@ -7017,7 +7499,7 @@ function CallCard({ state, onClose, interactive = true, children, panel, onPanel
|
|
|
7017
7499
|
"aria-selected": tab === "participants" ? panel !== "chat" : panel === "chat",
|
|
7018
7500
|
tabIndex: (tab === "participants" ? panel !== "chat" : panel === "chat") ? 0 : -1,
|
|
7019
7501
|
onClick: () => onPanelChange(tab),
|
|
7020
|
-
children: tab === "participants" ? /* @__PURE__ */
|
|
7502
|
+
children: tab === "participants" ? /* @__PURE__ */ jsxs40(Fragment27, { children: [
|
|
7021
7503
|
"People",
|
|
7022
7504
|
/* @__PURE__ */ jsx62("span", { className: "call-card-count", children: peopleCount })
|
|
7023
7505
|
] }) : "Chat"
|
|
@@ -7049,29 +7531,29 @@ function CallCard({ state, onClose, interactive = true, children, panel, onPanel
|
|
|
7049
7531
|
event.preventDefault();
|
|
7050
7532
|
onClose?.();
|
|
7051
7533
|
};
|
|
7052
|
-
return /* @__PURE__ */ jsx62(
|
|
7534
|
+
return /* @__PURE__ */ jsx62(Fragment27, { children: /* @__PURE__ */ jsx62("div", { ref: drawerRef, "data-part": "panel-card", tabIndex: interactive ? -1 : void 0, "data-state": state, "data-chalk-drawer": true, onKeyDown: interactive ? handleKeyDown : void 0, "aria-disabled": interactive ? void 0 : true, className: "chalk-drawer min-h-0 outline-none focus-visible:outline-none", children: /* @__PURE__ */ jsx62("div", { "data-part": "panel-content", className: cn("chalk-drawer-content flex min-h-0 flex-col overflow-hidden bg-[var(--chalk-app-panel)] text-[var(--chalk-app-text)]"), children: content }) }) });
|
|
7053
7535
|
}
|
|
7054
7536
|
|
|
7055
7537
|
// src/components/space-view/SpacePresentation.tsx
|
|
7056
7538
|
import { useRef as useRef26 } from "react";
|
|
7057
|
-
import { jsx as jsx63, jsxs as
|
|
7539
|
+
import { jsx as jsx63, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
7058
7540
|
function SpacePresentation({ colorScheme = "dark", stageBackground, header, stage, controls, compactControls, stageOverlay, sidebar, mediaOutput, toasts, overlays, dialogs, renderToken, interactive = true, className }) {
|
|
7059
7541
|
const root = useRef26(null);
|
|
7060
7542
|
const idle = useIdleChrome(root, interactive);
|
|
7061
|
-
return /* @__PURE__ */
|
|
7543
|
+
return /* @__PURE__ */ jsxs41("main", { ref: root, "data-chalk": true, "data-part": "call-frame", "data-idle": idle, "data-chalk-theme": colorScheme, "data-recording-space-render-token": renderToken, inert: interactive ? void 0 : true, className: cn("chalk-root chalk-frame", className), children: [
|
|
7062
7544
|
mediaOutput,
|
|
7063
7545
|
/* @__PURE__ */ jsx63(SpaceHeader, { ...header, className: cn("chalk-frame-header", header.className) }),
|
|
7064
|
-
/* @__PURE__ */ jsx63("section", { "data-part": "stage-region", "data-stage-background": stageBackground, className: "chalk-frame-stage", "aria-label": "Space stage", children: /* @__PURE__ */
|
|
7546
|
+
/* @__PURE__ */ jsx63("section", { "data-part": "stage-region", "data-stage-background": stageBackground, className: "chalk-frame-stage", "aria-label": "Space stage", children: /* @__PURE__ */ jsxs41("div", { "data-part": "stage-layout", className: "chalk-stage-layout", children: [
|
|
7065
7547
|
stage,
|
|
7066
7548
|
stageOverlay
|
|
7067
7549
|
] }) }),
|
|
7068
|
-
/* @__PURE__ */
|
|
7550
|
+
/* @__PURE__ */ jsxs41("div", { "data-part": "dock-region", className: "chalk-frame-dock", children: [
|
|
7069
7551
|
/* @__PURE__ */ jsx63("div", { className: compactControls ? "chalk-frame-regular" : void 0, style: compactControls ? void 0 : { display: "contents" }, children: controls }),
|
|
7070
7552
|
compactControls ? /* @__PURE__ */ jsx63("div", { className: "chalk-frame-compact", children: compactControls }) : null
|
|
7071
7553
|
] }),
|
|
7072
7554
|
sidebar,
|
|
7073
7555
|
toasts,
|
|
7074
|
-
/* @__PURE__ */
|
|
7556
|
+
/* @__PURE__ */ jsxs41("div", { "data-part": "overlays-region", className: "chalk-frame-overlays", children: [
|
|
7075
7557
|
overlays,
|
|
7076
7558
|
dialogs
|
|
7077
7559
|
] })
|
|
@@ -7079,9 +7561,9 @@ function SpacePresentation({ colorScheme = "dark", stageBackground, header, stag
|
|
|
7079
7561
|
}
|
|
7080
7562
|
|
|
7081
7563
|
// src/components/space-view/SpaceView.tsx
|
|
7082
|
-
import
|
|
7564
|
+
import "@q9labsai/chalk-client";
|
|
7083
7565
|
import { DEFAULT_QUICK_REACTIONS as DEFAULT_QUICK_REACTIONS2 } from "@q9labsai/chalk-ui/reactions";
|
|
7084
|
-
import { useCallback as
|
|
7566
|
+
import { useCallback as useCallback16, useEffect as useEffect40, useMemo as useMemo19, useRef as useRef34, useState as useState50 } from "react";
|
|
7085
7567
|
|
|
7086
7568
|
// src/components/space-header/call-diagnostics.ts
|
|
7087
7569
|
function callDiagnostics(connection, media) {
|
|
@@ -7095,19 +7577,19 @@ function callDiagnostics(connection, media) {
|
|
|
7095
7577
|
["Speaker", media.devices.speakers, media.selection.speaker],
|
|
7096
7578
|
["Camera", media.devices.cameras, media.selection.camera]
|
|
7097
7579
|
]) {
|
|
7098
|
-
const
|
|
7099
|
-
if (
|
|
7580
|
+
const device2 = devices.find((item) => item.deviceId === selected);
|
|
7581
|
+
if (device2?.label) rows.push({ label, value: device2.label });
|
|
7100
7582
|
}
|
|
7101
7583
|
if (media.screenShare.capture?.label) rows.push({ label: "Sharing", value: media.screenShare.capture.label });
|
|
7102
7584
|
return rows;
|
|
7103
7585
|
}
|
|
7104
7586
|
|
|
7105
7587
|
// src/internal/useEpisodeDuration.ts
|
|
7106
|
-
import { useEffect as useEffect26, useState as
|
|
7588
|
+
import { useEffect as useEffect26, useState as useState36 } from "react";
|
|
7107
7589
|
function useEpisodeDuration() {
|
|
7108
7590
|
const connection = useConnection();
|
|
7109
7591
|
const episodeStart = connection.episode?.startedAt ? Date.parse(connection.episode.startedAt) : null;
|
|
7110
|
-
const [now, setNow] =
|
|
7592
|
+
const [now, setNow] = useState36(() => Date.now());
|
|
7111
7593
|
useEffect26(() => {
|
|
7112
7594
|
if (episodeStart === null || Number.isNaN(episodeStart)) return;
|
|
7113
7595
|
setNow(Date.now());
|
|
@@ -7314,19 +7796,19 @@ function useSoundCues(enabled, createPlayer = createSoundPlayer) {
|
|
|
7314
7796
|
}
|
|
7315
7797
|
|
|
7316
7798
|
// src/components/composite/ReactionPicker.tsx
|
|
7317
|
-
import React21, { useMemo as useMemo14, useState as
|
|
7799
|
+
import React21, { useMemo as useMemo14, useState as useState38, useCallback as useCallback10, useEffect as useEffect29, useRef as useRef29 } from "react";
|
|
7318
7800
|
import { DEFAULT_QUICK_REACTIONS, EMOJI_CATEGORIES, EMOJI_KEYWORDS } from "@q9labsai/chalk-ui/reactions";
|
|
7319
7801
|
|
|
7320
7802
|
// src/components/composite/ReactionTray.tsx
|
|
7321
|
-
import { useCallback as useCallback9, useEffect as useEffect28, useLayoutEffect as
|
|
7322
|
-
import { Fragment as
|
|
7803
|
+
import { useCallback as useCallback9, useEffect as useEffect28, useLayoutEffect as useLayoutEffect6, useRef as useRef28, useState as useState37 } from "react";
|
|
7804
|
+
import { Fragment as Fragment28, jsx as jsx64, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
7323
7805
|
function ReactionTray({ isHandRaised, onToggleHandRaise, reactions, onSelect, onClose, position = "top", className }) {
|
|
7324
|
-
const [more, setMore] =
|
|
7806
|
+
const [more, setMore] = useState37(false);
|
|
7325
7807
|
const returnFocus = useRef28(null);
|
|
7326
7808
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
7327
7809
|
const { trigger } = useHaptics();
|
|
7328
7810
|
const listRef = useRef28(null);
|
|
7329
|
-
|
|
7811
|
+
useLayoutEffect6(() => {
|
|
7330
7812
|
returnFocus.current = document.activeElement;
|
|
7331
7813
|
const tray = listRef.current;
|
|
7332
7814
|
const frame = tray?.closest("[data-part='call-frame']");
|
|
@@ -7384,12 +7866,12 @@ function ReactionTray({ isHandRaised, onToggleHandRaise, reactions, onSelect, on
|
|
|
7384
7866
|
};
|
|
7385
7867
|
const buttons = (more ? reactions : reactions.slice(0, 6)).map((emoji) => /* @__PURE__ */ jsx64("button", { type: "button", onClick: () => handleSelect(emoji), className: "chalk-shell-emoji", "aria-label": `React with ${emoji}`, children: /* @__PURE__ */ jsx64("span", { "aria-hidden": "true", children: emoji }) }, emoji));
|
|
7386
7868
|
const trayClassName = cn("absolute z-50", !prefersReducedMotion && "chalk-shell-reactions-enter", className);
|
|
7387
|
-
return /* @__PURE__ */
|
|
7869
|
+
return /* @__PURE__ */ jsxs42(Fragment28, { children: [
|
|
7388
7870
|
/* @__PURE__ */ jsx64(ShellStyles, {}),
|
|
7389
7871
|
/* @__PURE__ */ jsx64("div", { className: "fixed inset-0 z-20", onClick: onClose, "aria-hidden": "true" }),
|
|
7390
|
-
/* @__PURE__ */
|
|
7391
|
-
onToggleHandRaise ? /* @__PURE__ */
|
|
7392
|
-
/* @__PURE__ */
|
|
7872
|
+
/* @__PURE__ */ jsxs42("div", { ref: listRef, className: cn(trayClassName, "chalk-shell-reactions", more && "chalk-shell-reactions-expanded"), role: "toolbar", "aria-label": "Reactions", onKeyDown: handleKeyDown, children: [
|
|
7873
|
+
onToggleHandRaise ? /* @__PURE__ */ jsxs42("button", { type: "button", className: "chalk-shell-raise", "aria-pressed": isHandRaised, onClick: onToggleHandRaise, children: [
|
|
7874
|
+
/* @__PURE__ */ jsxs42("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: [
|
|
7393
7875
|
/* @__PURE__ */ jsx64("path", { d: "M18 11V6a2 2 0 0 0-4 0v5M14 10V4a2 2 0 0 0-4 0v6M10 10.5V6a2 2 0 0 0-4 0v8" }),
|
|
7394
7876
|
/* @__PURE__ */ jsx64("path", { d: "M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.3l-3.6-3.6a2 2 0 0 1 2.8-2.8L7 15" })
|
|
7395
7877
|
] }),
|
|
@@ -7402,12 +7884,12 @@ function ReactionTray({ isHandRaised, onToggleHandRaise, reactions, onSelect, on
|
|
|
7402
7884
|
}
|
|
7403
7885
|
|
|
7404
7886
|
// src/components/composite/ReactionPicker.tsx
|
|
7405
|
-
import { Fragment as
|
|
7887
|
+
import { Fragment as Fragment29, jsx as jsx65, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
7406
7888
|
var ReactionPicker = React21.memo(({ isHandRaised, onToggleHandRaise, isOpen, onClose, onSelect, recentReactions = [], allowedReactions, position = "top", participantColorSeed, participantGradientPreference, className, size = "default" }) => {
|
|
7407
7889
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
7408
7890
|
const { trigger } = useHaptics();
|
|
7409
|
-
const [activeCategory, setActiveCategory] =
|
|
7410
|
-
const [searchQuery, setSearchQuery] =
|
|
7891
|
+
const [activeCategory, setActiveCategory] = useState38("smileys");
|
|
7892
|
+
const [searchQuery, setSearchQuery] = useState38("");
|
|
7411
7893
|
const inputRef = useRef29(null);
|
|
7412
7894
|
const themeVariables = useMemo14(() => getParticipantThemeVariables(participantColorSeed, participantGradientPreference), [participantColorSeed, participantGradientPreference]);
|
|
7413
7895
|
useEffect29(() => {
|
|
@@ -7466,9 +7948,9 @@ var ReactionPicker = React21.memo(({ isHandRaised, onToggleHandRaise, isOpen, on
|
|
|
7466
7948
|
}
|
|
7467
7949
|
);
|
|
7468
7950
|
}
|
|
7469
|
-
return /* @__PURE__ */
|
|
7951
|
+
return /* @__PURE__ */ jsxs43(Fragment29, { children: [
|
|
7470
7952
|
/* @__PURE__ */ jsx65("div", { className: "fixed inset-0 z-20", onClick: onClose, "aria-hidden": "true" }),
|
|
7471
|
-
/* @__PURE__ */
|
|
7953
|
+
/* @__PURE__ */ jsxs43(
|
|
7472
7954
|
"div",
|
|
7473
7955
|
{
|
|
7474
7956
|
className: cn(
|
|
@@ -7502,7 +7984,7 @@ var ReactionPicker = React21.memo(({ isHandRaised, onToggleHandRaise, isOpen, on
|
|
|
7502
7984
|
},
|
|
7503
7985
|
`quick-${emoji}-${index}`
|
|
7504
7986
|
)) }) }),
|
|
7505
|
-
!allowedReactions ? /* @__PURE__ */
|
|
7987
|
+
!allowedReactions ? /* @__PURE__ */ jsxs43("div", { className: cn("flex items-center gap-2 border-b border-[var(--chalk-line)] bg-[var(--chalk-stage)] focus-within:bg-[var(--chalk-stage)] transition-colors", size === "mini" ? "px-1.5 py-1" : size === "compact" ? "px-2 py-1.5" : "px-3 py-2"), children: [
|
|
7506
7988
|
/* @__PURE__ */ jsx65(Search01Icon, { size: 16, className: "text-[var(--chalk-muted-text)] shrink-0" }),
|
|
7507
7989
|
/* @__PURE__ */ jsx65(
|
|
7508
7990
|
"input",
|
|
@@ -7519,7 +8001,7 @@ var ReactionPicker = React21.memo(({ isHandRaised, onToggleHandRaise, isOpen, on
|
|
|
7519
8001
|
),
|
|
7520
8002
|
/* @__PURE__ */ jsx65("kbd", { className: "hidden sm:inline-flex items-center gap-1 px-1.5 py-0.5 rounded border border-[var(--chalk-line)] bg-[var(--chalk-canvas)] text-[10px] font-medium text-[var(--chalk-muted-text)] uppercase", children: "Esc" })
|
|
7521
8003
|
] }) : null,
|
|
7522
|
-
!allowedReactions ? /* @__PURE__ */
|
|
8004
|
+
!allowedReactions ? /* @__PURE__ */ jsxs43("div", { className: cn("flex", size === "mini" ? "h-36" : size === "compact" ? "h-48" : "h-64"), children: [
|
|
7523
8005
|
!isSearching && /* @__PURE__ */ jsx65("div", { className: cn("flex flex-col items-center py-2 gap-1 border-r border-[var(--chalk-line)] bg-[var(--chalk-stage)] overflow-y-auto [&::-webkit-scrollbar]:hidden [scrollbar-width:none]", size === "mini" ? "w-8" : size === "compact" ? "w-10" : "w-12"), children: categories.map(([key, category]) => /* @__PURE__ */ jsx65(
|
|
7524
8006
|
"button",
|
|
7525
8007
|
{
|
|
@@ -7564,7 +8046,7 @@ var ReactionPicker = React21.memo(({ isHandRaised, onToggleHandRaise, isOpen, on
|
|
|
7564
8046
|
ReactionPicker.displayName = "ReactionPicker";
|
|
7565
8047
|
|
|
7566
8048
|
// src/components/offline-actions/OfflineActions.tsx
|
|
7567
|
-
import { useEffect as useEffect30, useState as
|
|
8049
|
+
import { useEffect as useEffect30, useState as useState39, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
7568
8050
|
import { jsx as jsx66 } from "react/jsx-runtime";
|
|
7569
8051
|
var RECONNECTING_GRACE_MS = 2e3;
|
|
7570
8052
|
function offlineNoticeText(pendingCount, online) {
|
|
@@ -7572,9 +8054,8 @@ function offlineNoticeText(pendingCount, online) {
|
|
|
7572
8054
|
if (pendingCount === 0) return online ? "Reconnecting\u2026" : "You're offline. Reconnecting\u2026";
|
|
7573
8055
|
return `${state}. ${pendingCount === 1 ? "1 action" : `${pendingCount} actions`} will send when you're back.`;
|
|
7574
8056
|
}
|
|
7575
|
-
function OfflineActions({ reconnecting: requestedReconnecting = false } = {}) {
|
|
8057
|
+
function OfflineActions({ reconnecting: requestedReconnecting = false, hasNotice = false } = {}) {
|
|
7576
8058
|
const client = useSpaceClient();
|
|
7577
|
-
const [dismissedNotice, setDismissedNotice] = useState36(null);
|
|
7578
8059
|
const connection = useConnection();
|
|
7579
8060
|
const offline = useOffline();
|
|
7580
8061
|
const online = useSyncExternalStore4(subscribeToOnline, readOnline, () => true);
|
|
@@ -7587,13 +8068,13 @@ function OfflineActions({ reconnecting: requestedReconnecting = false } = {}) {
|
|
|
7587
8068
|
const messagesOnly = offline.pending.every((action) => action.kind === "chat_message");
|
|
7588
8069
|
const pendingDetail = count ? `${count} ${messagesOnly ? count === 1 ? "message" : "messages" : count === 1 ? "action" : "actions"} will send when you\u2019re back` : void 0;
|
|
7589
8070
|
const notice = reconnecting ? reconnectingNoticeDue ? `${offlineNoticeText(0, online)}${pendingDetail ? ` ${pendingDetail}` : ""}` : null : connection.syncHealth === "degraded" ? "Connection is slow" : null;
|
|
7590
|
-
if (
|
|
8071
|
+
if (hasNotice) return null;
|
|
7591
8072
|
if (notice)
|
|
7592
8073
|
return /* @__PURE__ */ jsx66("div", { role: "status", "data-part": "connection-notice", style: { pointerEvents: "none" }, className: "absolute inset-x-4 top-16 z-50 mx-auto w-fit max-w-[calc(100%_-_2rem)] rounded-full bg-[var(--chalk-surface)] px-3 py-1 text-center text-sm text-[var(--chalk-text)]", children: notice });
|
|
7593
8074
|
return null;
|
|
7594
8075
|
}
|
|
7595
8076
|
function useTrueFor(value, milliseconds) {
|
|
7596
|
-
const [elapsed, setElapsed] =
|
|
8077
|
+
const [elapsed, setElapsed] = useState39(false);
|
|
7597
8078
|
useEffect30(() => {
|
|
7598
8079
|
setElapsed(false);
|
|
7599
8080
|
if (!value) return;
|
|
@@ -7615,12 +8096,12 @@ function readOnline() {
|
|
|
7615
8096
|
}
|
|
7616
8097
|
|
|
7617
8098
|
// src/components/reconnecting-overlay/ReconnectingOverlay.tsx
|
|
7618
|
-
import { memo as memo3, useEffect as useEffect31, useState as
|
|
8099
|
+
import { memo as memo3, useEffect as useEffect31, useState as useState40 } from "react";
|
|
7619
8100
|
import { jsx as jsx67 } from "react/jsx-runtime";
|
|
7620
8101
|
var RECONNECTING_NOTICE_MS = 2e3;
|
|
7621
8102
|
var ReconnectingOverlay = memo3(function ReconnectingOverlay2({ isVisible, status, onRetry, onLeft, message, showNotice }) {
|
|
7622
8103
|
const reconnecting = isVisible && status === "reconnecting";
|
|
7623
|
-
const [elapsed, setElapsed] =
|
|
8104
|
+
const [elapsed, setElapsed] = useState40(false);
|
|
7624
8105
|
useEffect31(() => {
|
|
7625
8106
|
setElapsed(false);
|
|
7626
8107
|
if (!reconnecting) return;
|
|
@@ -7635,55 +8116,14 @@ var ReconnectingOverlay = memo3(function ReconnectingOverlay2({ isVisible, statu
|
|
|
7635
8116
|
});
|
|
7636
8117
|
|
|
7637
8118
|
// src/components/toast-stack/useCallToasts.ts
|
|
7638
|
-
import { useCallback as useCallback11, useEffect as useEffect32, useRef as useRef30, useState as
|
|
8119
|
+
import { useCallback as useCallback11, useEffect as useEffect32, useRef as useRef30, useState as useState41 } from "react";
|
|
7639
8120
|
|
|
7640
8121
|
// src/components/toast-stack/call-events.tsx
|
|
7641
|
-
import { Fragment as
|
|
7642
|
-
function mediaFailureToast(failure, source) {
|
|
8122
|
+
import { Fragment as Fragment30, jsx as jsx68, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
8123
|
+
function mediaFailureToast(failure, source, action, onRetry) {
|
|
7643
8124
|
if (!failure) return null;
|
|
7644
|
-
const
|
|
7645
|
-
|
|
7646
|
-
if (source === "screen" && failure.code.startsWith("media."))
|
|
7647
|
-
return {
|
|
7648
|
-
icon,
|
|
7649
|
-
type: "error",
|
|
7650
|
-
message: /* @__PURE__ */ jsxs43(Fragment27, { children: [
|
|
7651
|
-
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, children: "Your screen couldn\u2019t be shared." }),
|
|
7652
|
-
" Allow screen recording for your browser in System Settings, then try again."
|
|
7653
|
-
] })
|
|
7654
|
-
};
|
|
7655
|
-
if (failure.code === "media.permission_denied")
|
|
7656
|
-
return {
|
|
7657
|
-
icon,
|
|
7658
|
-
type: "error",
|
|
7659
|
-
message: /* @__PURE__ */ jsxs43(Fragment27, { children: [
|
|
7660
|
-
/* @__PURE__ */ jsxs43("b", { style: { fontWeight: 600 }, children: [
|
|
7661
|
-
"Chalk can\u2019t use your ",
|
|
7662
|
-
device,
|
|
7663
|
-
"."
|
|
7664
|
-
] }),
|
|
7665
|
-
" Click the camera icon in the address bar and allow ",
|
|
7666
|
-
source === "camera" ? "Camera" : source === "microphone" ? "Microphone" : "Camera and Microphone",
|
|
7667
|
-
"."
|
|
7668
|
-
] })
|
|
7669
|
-
};
|
|
7670
|
-
if (failure.code === "media.device_not_found")
|
|
7671
|
-
return {
|
|
7672
|
-
icon,
|
|
7673
|
-
type: "error",
|
|
7674
|
-
message: /* @__PURE__ */ jsxs43(Fragment27, { children: [
|
|
7675
|
-
/* @__PURE__ */ jsxs43("b", { style: { fontWeight: 600 }, children: [
|
|
7676
|
-
"No ",
|
|
7677
|
-
device,
|
|
7678
|
-
" found."
|
|
7679
|
-
] }),
|
|
7680
|
-
" Plug one in, or check that your Mac can see it in System Settings."
|
|
7681
|
-
] })
|
|
7682
|
-
};
|
|
7683
|
-
if (failure.code === "media.device_busy") return { icon, type: "error", message: `Your ${device} is being used by another app. Close it there, then try again.` };
|
|
7684
|
-
if (failure.code === "media.device_constraint_invalid") return { icon, type: "error", message: `Your ${device} doesn\u2019t support these settings. Choose another ${device}, then try again.` };
|
|
7685
|
-
if (failure.code === "media.capture_failed") return { icon, type: "error", message: `Your ${device} couldn\u2019t start. Check that it is connected and available, then try again.` };
|
|
7686
|
-
return { icon, type: "error", message: failure.message };
|
|
8125
|
+
const presentation = commandFailurePresentation(failure, source, action, onRetry !== void 0);
|
|
8126
|
+
return { icon: /* @__PURE__ */ jsx68(CallEventIcon, { kind: source ?? "microphone", error: true }), type: "error", message: presentation.message, action: presentation.retry && onRetry ? { label: "Try again", onClick: onRetry } : void 0 };
|
|
7687
8127
|
}
|
|
7688
8128
|
function callEventToasts(previous, next) {
|
|
7689
8129
|
if (previous.connection.status !== "live" || next.connection.status !== "live") return [];
|
|
@@ -7695,16 +8135,16 @@ function callEventToasts(previous, next) {
|
|
|
7695
8135
|
if (!old && person.participantId !== next.self.participantId)
|
|
7696
8136
|
events.push({
|
|
7697
8137
|
icon: /* @__PURE__ */ jsx68(Avatar, { name: person.displayName, size: "xs", style: { width: 28, height: 28 }, generated: true, animated: false }),
|
|
7698
|
-
message: /* @__PURE__ */
|
|
8138
|
+
message: /* @__PURE__ */ jsxs44(Fragment30, { children: [
|
|
7699
8139
|
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, dir: "auto", children: person.displayName }),
|
|
7700
8140
|
" ",
|
|
7701
8141
|
"joined"
|
|
7702
8142
|
] })
|
|
7703
8143
|
});
|
|
7704
|
-
if (old && !old.handRaised && person.handRaised)
|
|
8144
|
+
if (old && !old.handRaised && person.handRaised && person.participantId !== next.self.participantId)
|
|
7705
8145
|
events.push({
|
|
7706
8146
|
icon: /* @__PURE__ */ jsx68(CallEventIcon, { kind: "hand" }),
|
|
7707
|
-
message: /* @__PURE__ */
|
|
8147
|
+
message: /* @__PURE__ */ jsxs44(Fragment30, { children: [
|
|
7708
8148
|
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, dir: "auto", children: person.displayName }),
|
|
7709
8149
|
" ",
|
|
7710
8150
|
"raised a hand"
|
|
@@ -7713,7 +8153,7 @@ function callEventToasts(previous, next) {
|
|
|
7713
8153
|
if (old?.media.screenShare === "active" && person.media.screenShare === "inactive")
|
|
7714
8154
|
events.push({
|
|
7715
8155
|
icon: /* @__PURE__ */ jsx68(CallEventIcon, { kind: "screen" }),
|
|
7716
|
-
message: /* @__PURE__ */
|
|
8156
|
+
message: /* @__PURE__ */ jsxs44(Fragment30, { children: [
|
|
7717
8157
|
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, dir: "auto", children: person.displayName }),
|
|
7718
8158
|
" ",
|
|
7719
8159
|
"stopped sharing"
|
|
@@ -7725,7 +8165,7 @@ function callEventToasts(previous, next) {
|
|
|
7725
8165
|
if (becameHost)
|
|
7726
8166
|
events.push({
|
|
7727
8167
|
icon: /* @__PURE__ */ jsx68(CallEventIcon, { kind: "host" }),
|
|
7728
|
-
message: departedHost ? /* @__PURE__ */
|
|
8168
|
+
message: departedHost ? /* @__PURE__ */ jsxs44(Fragment30, { children: [
|
|
7729
8169
|
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, dir: "auto", children: departedHost.displayName }),
|
|
7730
8170
|
" left. You\u2019re now the host."
|
|
7731
8171
|
] }) : "You\u2019re now the host."
|
|
@@ -7734,7 +8174,7 @@ function callEventToasts(previous, next) {
|
|
|
7734
8174
|
if (!after.has(person.participantId) && person.participantId !== next.self.participantId && !(person === departedHost && becameHost))
|
|
7735
8175
|
events.push({
|
|
7736
8176
|
icon: /* @__PURE__ */ jsx68(Avatar, { name: person.displayName, size: "xs", style: { width: 28, height: 28 }, generated: true, animated: false }),
|
|
7737
|
-
message: /* @__PURE__ */
|
|
8177
|
+
message: /* @__PURE__ */ jsxs44(Fragment30, { children: [
|
|
7738
8178
|
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, dir: "auto", children: person.displayName }),
|
|
7739
8179
|
" ",
|
|
7740
8180
|
"left"
|
|
@@ -7745,7 +8185,7 @@ function callEventToasts(previous, next) {
|
|
|
7745
8185
|
if (wasRecording !== isRecording)
|
|
7746
8186
|
events.push({
|
|
7747
8187
|
icon: /* @__PURE__ */ jsx68(CallEventIcon, { kind: "recording", error: isRecording }),
|
|
7748
|
-
message: isRecording ? /* @__PURE__ */
|
|
8188
|
+
message: isRecording ? /* @__PURE__ */ jsxs44(Fragment30, { children: [
|
|
7749
8189
|
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, children: "Recording started." }),
|
|
7750
8190
|
" Everyone in the call can see it."
|
|
7751
8191
|
] }) : "Recording stopped"
|
|
@@ -7754,13 +8194,13 @@ function callEventToasts(previous, next) {
|
|
|
7754
8194
|
if (previous.media.selection[source] !== next.media.selection[source]) {
|
|
7755
8195
|
const devices = source === "camera" ? next.media.devices.cameras : next.media.devices.microphones;
|
|
7756
8196
|
const oldDevices = source === "camera" ? previous.media.devices.cameras : previous.media.devices.microphones;
|
|
7757
|
-
const disconnected = oldDevices.find((
|
|
7758
|
-
if (!disconnected || devices.some((
|
|
7759
|
-
const selected = devices.find((
|
|
8197
|
+
const disconnected = oldDevices.find((device2) => device2.deviceId === previous.media.selection[source]);
|
|
8198
|
+
if (!disconnected || devices.some((device2) => device2.deviceId === disconnected.deviceId)) continue;
|
|
8199
|
+
const selected = devices.find((device2) => device2.deviceId === next.media.selection[source]);
|
|
7760
8200
|
if (selected)
|
|
7761
8201
|
events.push({
|
|
7762
8202
|
icon: /* @__PURE__ */ jsx68(CallEventIcon, { kind: source === "microphone" ? "microphone-on" : source }),
|
|
7763
|
-
message: /* @__PURE__ */
|
|
8203
|
+
message: /* @__PURE__ */ jsxs44(Fragment30, { children: [
|
|
7764
8204
|
`${disconnected.label || source} disconnected. Switched to `,
|
|
7765
8205
|
/* @__PURE__ */ jsx68("b", { style: { fontWeight: 600 }, children: selected.label || source })
|
|
7766
8206
|
] })
|
|
@@ -7773,7 +8213,7 @@ function callEventToasts(previous, next) {
|
|
|
7773
8213
|
// src/components/toast-stack/useCallToasts.ts
|
|
7774
8214
|
function useCallToasts() {
|
|
7775
8215
|
const client = useSpaceClient();
|
|
7776
|
-
const [toasts, setToasts] =
|
|
8216
|
+
const [toasts, setToasts] = useState41([]);
|
|
7777
8217
|
const sequence = useRef30(0);
|
|
7778
8218
|
useEffect32(() => {
|
|
7779
8219
|
setToasts([]);
|
|
@@ -7797,18 +8237,7 @@ function useCallToasts() {
|
|
|
7797
8237
|
const toast = mediaFailureToast(error, failedSource);
|
|
7798
8238
|
if (toast) {
|
|
7799
8239
|
const id = `call-event-${++sequence.current}`;
|
|
7800
|
-
|
|
7801
|
-
label: "Try again",
|
|
7802
|
-
onClick: () => {
|
|
7803
|
-
void client.media.setScreenShareEnabled(true).then(
|
|
7804
|
-
() => {
|
|
7805
|
-
setToasts((current) => current.filter((event) => event.id !== id));
|
|
7806
|
-
},
|
|
7807
|
-
() => void 0
|
|
7808
|
-
);
|
|
7809
|
-
}
|
|
7810
|
-
} : void 0;
|
|
7811
|
-
setToasts((current) => [...current, { ...toast, action, failureCode: error.code, id }].slice(-20));
|
|
8240
|
+
setToasts((current) => [...current, { ...toast, failureCode: error.code, id }].slice(-20));
|
|
7812
8241
|
}
|
|
7813
8242
|
failedSource = void 0;
|
|
7814
8243
|
});
|
|
@@ -7825,15 +8254,37 @@ function useCallToasts() {
|
|
|
7825
8254
|
}
|
|
7826
8255
|
|
|
7827
8256
|
// src/components/call-limbo/useCallLink.ts
|
|
7828
|
-
import { useEffect as useEffect33, useState as
|
|
8257
|
+
import { useEffect as useEffect33, useState as useState42 } from "react";
|
|
7829
8258
|
function useCallLink(alone) {
|
|
7830
|
-
const [open, setOpen] =
|
|
8259
|
+
const [open, setOpen] = useState42(alone);
|
|
7831
8260
|
useEffect33(() => {
|
|
7832
8261
|
if (!alone) setOpen(false);
|
|
7833
8262
|
}, [alone]);
|
|
7834
8263
|
return { open, toggle: () => setOpen((current) => !current), close: () => setOpen(false) };
|
|
7835
8264
|
}
|
|
7836
8265
|
|
|
8266
|
+
// src/components/toast-stack/NoticeButton.tsx
|
|
8267
|
+
import { useState as useState43 } from "react";
|
|
8268
|
+
import { jsx as jsx69, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
8269
|
+
function NoticeButton({ toasts, onDismiss }) {
|
|
8270
|
+
const [open, setOpen] = useState43(false);
|
|
8271
|
+
if (toasts.length === 0) return null;
|
|
8272
|
+
const label = toasts.length === 1 ? "1 notice" : `${toasts.length} notices`;
|
|
8273
|
+
const trigger = /* @__PURE__ */ jsxs45("button", { type: "button", "data-part": "notice-button", className: "chalk-notice-button", "aria-label": `Show ${label}`, children: [
|
|
8274
|
+
/* @__PURE__ */ jsxs45("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
8275
|
+
/* @__PURE__ */ jsx69("circle", { cx: "12", cy: "12", r: "9" }),
|
|
8276
|
+
/* @__PURE__ */ jsx69("path", { d: "M12 7.5v5.5M12 16.5h.01" })
|
|
8277
|
+
] }),
|
|
8278
|
+
toasts.length > 1 ? /* @__PURE__ */ jsx69("span", { children: toasts.length }) : null
|
|
8279
|
+
] });
|
|
8280
|
+
return /* @__PURE__ */ jsx69(ChalkPopover, { open, onOpenChange: setOpen, tooltip: label, trigger, label: "Notices", className: "chalk-notice-list", children: toasts.map((toast) => /* @__PURE__ */ jsxs45("div", { "data-part": "notice", "data-type": toast.type ?? "info", className: "chalk-notice", children: [
|
|
8281
|
+
toast.icon,
|
|
8282
|
+
/* @__PURE__ */ jsx69("span", { children: toast.message }),
|
|
8283
|
+
toast.action ? /* @__PURE__ */ jsx69(ChalkButton, { onClick: toast.action.onClick, children: toast.action.label }) : null,
|
|
8284
|
+
/* @__PURE__ */ jsx69("button", { type: "button", className: "chalk-dismiss", "aria-label": "Dismiss", onClick: () => onDismiss(toast.id), children: /* @__PURE__ */ jsx69("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx69("path", { d: "m6 6 12 12M6 18 18 6" }) }) })
|
|
8285
|
+
] }, toast.id)) });
|
|
8286
|
+
}
|
|
8287
|
+
|
|
7837
8288
|
// src/components/board/board-toasts.ts
|
|
7838
8289
|
import { createContext as createContext3, useCallback as useCallback12, useContext as useContext3, useEffect as useEffect34, useMemo as useMemo15 } from "react";
|
|
7839
8290
|
var BoardToastContext = createContext3(() => void 0);
|
|
@@ -7856,13 +8307,16 @@ function useBoardToast(lifetime) {
|
|
|
7856
8307
|
}
|
|
7857
8308
|
|
|
7858
8309
|
// src/components/stage/SpaceStage.tsx
|
|
7859
|
-
import { useCallback as
|
|
8310
|
+
import { useCallback as useCallback15, useEffect as useEffect38, useMemo as useMemo18, useState as useState48 } from "react";
|
|
8311
|
+
|
|
8312
|
+
// src/internal/whiteboard-view-limits.ts
|
|
8313
|
+
var WHITEBOARD_VIEW_PEOPLE_MAX = 500;
|
|
7860
8314
|
|
|
7861
8315
|
// src/components/board/board-history.ts
|
|
7862
|
-
import { useEffect as useEffect35, useState as
|
|
8316
|
+
import { useEffect as useEffect35, useState as useState44 } from "react";
|
|
7863
8317
|
import { observeEngineHistory } from "@q9labsai/chalk-whiteboard/react";
|
|
7864
8318
|
function useEngineHistory(root, engine) {
|
|
7865
|
-
const [history, setHistory] =
|
|
8319
|
+
const [history, setHistory] = useState44({ canUndo: false, canRedo: false });
|
|
7866
8320
|
useEffect35(() => {
|
|
7867
8321
|
const canvas = root.current?.querySelector(".excalidraw");
|
|
7868
8322
|
if (!engine || !canvas) return;
|
|
@@ -7872,27 +8326,11 @@ function useEngineHistory(root, engine) {
|
|
|
7872
8326
|
}
|
|
7873
8327
|
|
|
7874
8328
|
// src/components/board/board-view-versions.ts
|
|
7875
|
-
|
|
7876
|
-
#versions = /* @__PURE__ */ new Map();
|
|
7877
|
-
isNew(view) {
|
|
7878
|
-
if (!view.originParticipantId) return true;
|
|
7879
|
-
return view.originSequence > (this.#versions.get(`${view.originParticipantId}:${view.originEpoch ?? ""}`) ?? 0);
|
|
7880
|
-
}
|
|
7881
|
-
remember(view) {
|
|
7882
|
-
if (!view.originParticipantId || !this.isNew(view)) return;
|
|
7883
|
-
const origin = `${view.originParticipantId}:${view.originEpoch ?? ""}`;
|
|
7884
|
-
this.#versions.delete(origin);
|
|
7885
|
-
this.#versions.set(origin, view.originSequence);
|
|
7886
|
-
if (this.#versions.size > 256) {
|
|
7887
|
-
const oldest = this.#versions.keys().next().value;
|
|
7888
|
-
if (oldest !== void 0) this.#versions.delete(oldest);
|
|
7889
|
-
}
|
|
7890
|
-
}
|
|
7891
|
-
};
|
|
8329
|
+
import { ChalkWhiteboardViewVersions } from "@q9labsai/chalk-client";
|
|
7892
8330
|
|
|
7893
8331
|
// src/components/board/Board.tsx
|
|
7894
8332
|
import { WhiteboardCanvas as WhiteboardCanvas2 } from "@q9labsai/chalk-whiteboard/react";
|
|
7895
|
-
import { useCallback as
|
|
8333
|
+
import { useCallback as useCallback14, useEffect as useEffect37, useMemo as useMemo17, useRef as useRef33, useState as useState47 } from "react";
|
|
7896
8334
|
|
|
7897
8335
|
// src/components/board/board-model.ts
|
|
7898
8336
|
import { ChalkWhiteboardViewBounds } from "@q9labsai/chalk-client";
|
|
@@ -7906,6 +8344,11 @@ var ISLAND_PLACES = [
|
|
|
7906
8344
|
{ id: "bottom", label: "Bottom" },
|
|
7907
8345
|
{ id: "top", label: "Top" }
|
|
7908
8346
|
];
|
|
8347
|
+
var DRAW_POLICIES = [
|
|
8348
|
+
{ id: "everyone", label: "Everyone" },
|
|
8349
|
+
{ id: "hosts", label: "Only hosts" },
|
|
8350
|
+
{ id: "picked", label: "Picked people" }
|
|
8351
|
+
];
|
|
7909
8352
|
var PEN_COLORS = [
|
|
7910
8353
|
{ id: "ink", label: "Ink" },
|
|
7911
8354
|
{ id: "red", label: "Red" },
|
|
@@ -8131,88 +8574,88 @@ function sceneSignature(engine) {
|
|
|
8131
8574
|
}
|
|
8132
8575
|
|
|
8133
8576
|
// src/components/board/BoardCursors.tsx
|
|
8134
|
-
import { useEffect as useEffect36, useRef as useRef31, useState as
|
|
8577
|
+
import { useEffect as useEffect36, useRef as useRef31, useState as useState45 } from "react";
|
|
8135
8578
|
|
|
8136
8579
|
// src/components/board/BoardIcon.tsx
|
|
8137
|
-
import { Fragment as
|
|
8580
|
+
import { Fragment as Fragment31, jsx as jsx70, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
8138
8581
|
var GLYPHS2 = {
|
|
8139
|
-
select: /* @__PURE__ */
|
|
8140
|
-
hand: /* @__PURE__ */
|
|
8141
|
-
pen: /* @__PURE__ */
|
|
8142
|
-
highlighter: /* @__PURE__ */
|
|
8143
|
-
/* @__PURE__ */
|
|
8144
|
-
/* @__PURE__ */
|
|
8582
|
+
select: /* @__PURE__ */ jsx70("path", { d: "M5 3l14 7-6.5 2L10 19z" }),
|
|
8583
|
+
hand: /* @__PURE__ */ jsx70("path", { d: "M18 11V6a2 2 0 0 0-4 0M14 10V4a2 2 0 0 0-4 0v2M10 10.5V6a2 2 0 0 0-4 0v8M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.3l-3.6-3.6a2 2 0 0 1 2.8-2.8L7 15" }),
|
|
8584
|
+
pen: /* @__PURE__ */ jsx70("path", { d: "M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z" }),
|
|
8585
|
+
highlighter: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8586
|
+
/* @__PURE__ */ jsx70("path", { d: "M9 11l-6 6v3h9l3-3" }),
|
|
8587
|
+
/* @__PURE__ */ jsx70("path", { d: "M22 12l-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4" })
|
|
8145
8588
|
] }),
|
|
8146
|
-
rectangle: /* @__PURE__ */
|
|
8147
|
-
ellipse: /* @__PURE__ */
|
|
8148
|
-
diamond: /* @__PURE__ */
|
|
8149
|
-
arrow: /* @__PURE__ */
|
|
8150
|
-
line: /* @__PURE__ */
|
|
8151
|
-
text: /* @__PURE__ */
|
|
8152
|
-
note: /* @__PURE__ */
|
|
8153
|
-
/* @__PURE__ */
|
|
8154
|
-
/* @__PURE__ */
|
|
8589
|
+
rectangle: /* @__PURE__ */ jsx70("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
8590
|
+
ellipse: /* @__PURE__ */ jsx70("ellipse", { cx: "12", cy: "12", rx: "9", ry: "6.5" }),
|
|
8591
|
+
diamond: /* @__PURE__ */ jsx70("path", { d: "M12 3l9 9-9 9-9-9z" }),
|
|
8592
|
+
arrow: /* @__PURE__ */ jsx70("path", { d: "M5 19L19 5M9 5h10v10" }),
|
|
8593
|
+
line: /* @__PURE__ */ jsx70("path", { d: "M4 20L20 4" }),
|
|
8594
|
+
text: /* @__PURE__ */ jsx70("path", { d: "M5 6V4h14v2M12 4v16M9 20h6" }),
|
|
8595
|
+
note: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8596
|
+
/* @__PURE__ */ jsx70("path", { d: "M5 3h14a2 2 0 0 1 2 2v9l-7 7H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" }),
|
|
8597
|
+
/* @__PURE__ */ jsx70("path", { d: "M14 21v-5a2 2 0 0 1 2-2h5" })
|
|
8155
8598
|
] }),
|
|
8156
|
-
eraser: /* @__PURE__ */
|
|
8157
|
-
laser: /* @__PURE__ */
|
|
8158
|
-
/* @__PURE__ */
|
|
8159
|
-
/* @__PURE__ */
|
|
8599
|
+
eraser: /* @__PURE__ */ jsx70("path", { d: "M7 21h10M5.5 13.5l7-7a2 2 0 0 1 2.8 0l3.2 3.2a2 2 0 0 1 0 2.8L11 19H8l-2.5-2.5a2 2 0 0 1 0-3z" }),
|
|
8600
|
+
laser: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8601
|
+
/* @__PURE__ */ jsx70("circle", { cx: "12", cy: "12", r: "2.5", fill: "currentColor" }),
|
|
8602
|
+
/* @__PURE__ */ jsx70("path", { d: "M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M18.4 5.6l-2.1 2.1M7.7 16.3l-2.1 2.1" })
|
|
8160
8603
|
] }),
|
|
8161
|
-
undo: /* @__PURE__ */
|
|
8162
|
-
/* @__PURE__ */
|
|
8163
|
-
/* @__PURE__ */
|
|
8604
|
+
undo: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8605
|
+
/* @__PURE__ */ jsx70("path", { d: "M9 14L4 9l5-5" }),
|
|
8606
|
+
/* @__PURE__ */ jsx70("path", { d: "M4 9h10.5a5.5 5.5 0 0 1 0 11H11" })
|
|
8164
8607
|
] }),
|
|
8165
|
-
redo: /* @__PURE__ */
|
|
8166
|
-
/* @__PURE__ */
|
|
8167
|
-
/* @__PURE__ */
|
|
8608
|
+
redo: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8609
|
+
/* @__PURE__ */ jsx70("path", { d: "M15 14l5-5-5-5" }),
|
|
8610
|
+
/* @__PURE__ */ jsx70("path", { d: "M20 9H9.5a5.5 5.5 0 0 0 0 11H13" })
|
|
8168
8611
|
] }),
|
|
8169
|
-
minus: /* @__PURE__ */
|
|
8170
|
-
plus: /* @__PURE__ */
|
|
8171
|
-
fit: /* @__PURE__ */
|
|
8172
|
-
download: /* @__PURE__ */
|
|
8173
|
-
copy: /* @__PURE__ */
|
|
8174
|
-
/* @__PURE__ */
|
|
8175
|
-
/* @__PURE__ */
|
|
8612
|
+
minus: /* @__PURE__ */ jsx70("path", { d: "M5 12h14" }),
|
|
8613
|
+
plus: /* @__PURE__ */ jsx70("path", { d: "M12 5v14M5 12h14" }),
|
|
8614
|
+
fit: /* @__PURE__ */ jsx70("path", { d: "M4 9V5a1 1 0 0 1 1-1h4M20 9V5a1 1 0 0 0-1-1h-4M4 15v4a1 1 0 0 0 1 1h4M20 15v4a1 1 0 0 1-1 1h-4" }),
|
|
8615
|
+
download: /* @__PURE__ */ jsx70("path", { d: "M12 3v12M7 10l5 5 5-5M4 21h16" }),
|
|
8616
|
+
copy: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8617
|
+
/* @__PURE__ */ jsx70("rect", { x: "9", y: "9", width: "12", height: "12", rx: "2" }),
|
|
8618
|
+
/* @__PURE__ */ jsx70("path", { d: "M5 15V5a2 2 0 0 1 2-2h10" })
|
|
8176
8619
|
] }),
|
|
8177
|
-
trash: /* @__PURE__ */
|
|
8178
|
-
close: /* @__PURE__ */
|
|
8179
|
-
check: /* @__PURE__ */
|
|
8180
|
-
target: /* @__PURE__ */
|
|
8181
|
-
/* @__PURE__ */
|
|
8182
|
-
/* @__PURE__ */
|
|
8620
|
+
trash: /* @__PURE__ */ jsx70("path", { d: "M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3" }),
|
|
8621
|
+
close: /* @__PURE__ */ jsx70("path", { d: "M6 6l12 12M18 6L6 18" }),
|
|
8622
|
+
check: /* @__PURE__ */ jsx70("path", { d: "M5 12l5 5 9-10" }),
|
|
8623
|
+
target: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8624
|
+
/* @__PURE__ */ jsx70("circle", { cx: "12", cy: "12", r: "9" }),
|
|
8625
|
+
/* @__PURE__ */ jsx70("circle", { cx: "12", cy: "12", r: "4" })
|
|
8183
8626
|
] }),
|
|
8184
|
-
eye: /* @__PURE__ */
|
|
8185
|
-
/* @__PURE__ */
|
|
8186
|
-
/* @__PURE__ */
|
|
8627
|
+
eye: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8628
|
+
/* @__PURE__ */ jsx70("path", { d: "M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z" }),
|
|
8629
|
+
/* @__PURE__ */ jsx70("circle", { cx: "12", cy: "12", r: "3" })
|
|
8187
8630
|
] }),
|
|
8188
|
-
wifiOff: /* @__PURE__ */
|
|
8189
|
-
lock: /* @__PURE__ */
|
|
8190
|
-
/* @__PURE__ */
|
|
8191
|
-
/* @__PURE__ */
|
|
8631
|
+
wifiOff: /* @__PURE__ */ jsx70("path", { d: "M2 2l20 20M8.5 16.5a5 5 0 0 1 7 0M5 12.9a10 10 0 0 1 5-2.7M10.7 5.1A16 16 0 0 1 22 9M2 8.8a15 15 0 0 1 4.2-2.5M12 20h.01" }),
|
|
8632
|
+
lock: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8633
|
+
/* @__PURE__ */ jsx70("rect", { x: "5", y: "11", width: "14", height: "9", rx: "2" }),
|
|
8634
|
+
/* @__PURE__ */ jsx70("path", { d: "M8 11V8a4 4 0 0 1 8 0v3" })
|
|
8192
8635
|
] }),
|
|
8193
|
-
more: /* @__PURE__ */
|
|
8194
|
-
/* @__PURE__ */
|
|
8195
|
-
/* @__PURE__ */
|
|
8196
|
-
/* @__PURE__ */
|
|
8636
|
+
more: /* @__PURE__ */ jsxs46(Fragment31, { children: [
|
|
8637
|
+
/* @__PURE__ */ jsx70("circle", { cx: "5", cy: "12", r: "1.2" }),
|
|
8638
|
+
/* @__PURE__ */ jsx70("circle", { cx: "12", cy: "12", r: "1.2" }),
|
|
8639
|
+
/* @__PURE__ */ jsx70("circle", { cx: "19", cy: "12", r: "1.2" })
|
|
8197
8640
|
] }),
|
|
8198
|
-
chevron: /* @__PURE__ */
|
|
8641
|
+
chevron: /* @__PURE__ */ jsx70("path", { d: "M6 9l6 6 6-6" })
|
|
8199
8642
|
};
|
|
8200
8643
|
function BoardIcon({ name, size = 20, className }) {
|
|
8201
|
-
return /* @__PURE__ */
|
|
8644
|
+
return /* @__PURE__ */ jsx70("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": "true", children: GLYPHS2[name] });
|
|
8202
8645
|
}
|
|
8203
8646
|
function GripIcon({ className }) {
|
|
8204
|
-
return /* @__PURE__ */
|
|
8647
|
+
return /* @__PURE__ */ jsx70("svg", { width: "10", height: "18", viewBox: "0 0 10 18", fill: "currentColor", className, "aria-hidden": "true", children: [3, 9, 15].flatMap((y) => [/* @__PURE__ */ jsx70("circle", { cx: "2.5", cy: y, r: "1.5" }, `l${y}`), /* @__PURE__ */ jsx70("circle", { cx: "7.5", cy: y, r: "1.5" }, `r${y}`)]) });
|
|
8205
8648
|
}
|
|
8206
8649
|
function CursorArrow({ color }) {
|
|
8207
8650
|
const path = "M3.2 2.6V20.2L8 15.7L11.3 22.6L14.6 21L11.4 14.2L17.9 13.6Z";
|
|
8208
|
-
return /* @__PURE__ */
|
|
8209
|
-
/* @__PURE__ */
|
|
8210
|
-
/* @__PURE__ */
|
|
8651
|
+
return /* @__PURE__ */ jsxs46("svg", { className: "chalk-board-cursor-arrow", width: "22", height: "26", viewBox: "0 0 22 26", fill: "none", "aria-hidden": "true", children: [
|
|
8652
|
+
/* @__PURE__ */ jsx70("path", { d: path, fill: "#fff", stroke: "#fff", strokeWidth: "5", strokeLinejoin: "round" }),
|
|
8653
|
+
/* @__PURE__ */ jsx70("path", { d: path, fill: color, stroke: color, strokeWidth: "2.2", strokeLinejoin: "round" })
|
|
8211
8654
|
] });
|
|
8212
8655
|
}
|
|
8213
8656
|
|
|
8214
8657
|
// src/components/board/BoardCursors.tsx
|
|
8215
|
-
import { jsx as
|
|
8658
|
+
import { jsx as jsx71, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
8216
8659
|
var REST_RATE = 16;
|
|
8217
8660
|
var STALE_MS = 1e4;
|
|
8218
8661
|
var NAME_HOLD_MS = 700;
|
|
@@ -8230,7 +8673,7 @@ function rememberCursor(cursors, cursor) {
|
|
|
8230
8673
|
}
|
|
8231
8674
|
function BoardCursors({ cursorsRef, cameraRef, colorFor, hidden }) {
|
|
8232
8675
|
const layer = useRef31(null);
|
|
8233
|
-
const [people, setPeople] =
|
|
8676
|
+
const [people, setPeople] = useState45([]);
|
|
8234
8677
|
const tracked = useRef31(/* @__PURE__ */ new Map());
|
|
8235
8678
|
const pointer = useRef31(null);
|
|
8236
8679
|
useEffect36(() => {
|
|
@@ -8308,18 +8751,18 @@ function BoardCursors({ cursorsRef, cameraRef, colorFor, hidden }) {
|
|
|
8308
8751
|
board.removeEventListener("pointerleave", leave);
|
|
8309
8752
|
};
|
|
8310
8753
|
}, []);
|
|
8311
|
-
return /* @__PURE__ */
|
|
8312
|
-
/* @__PURE__ */
|
|
8313
|
-
/* @__PURE__ */
|
|
8314
|
-
/* @__PURE__ */
|
|
8315
|
-
/* @__PURE__ */
|
|
8754
|
+
return /* @__PURE__ */ jsx71("div", { ref: layer, className: "chalk-board-cursors", "aria-hidden": "true", "data-hidden": hidden || void 0, children: people.map((person) => /* @__PURE__ */ jsxs47("div", { className: "chalk-board-cursor", "data-cursor": person.id, children: [
|
|
8755
|
+
/* @__PURE__ */ jsx71(CursorArrow, { color: colorFor(person.id) }),
|
|
8756
|
+
/* @__PURE__ */ jsxs47("span", { className: "chalk-board-cursor-tag", children: [
|
|
8757
|
+
/* @__PURE__ */ jsx71("span", { className: "chalk-board-cursor-name", style: { background: colorFor(person.id) }, children: person.name.split(" ")[0] }),
|
|
8758
|
+
/* @__PURE__ */ jsx71(Avatar, { name: person.name, size: "xs", animated: false, className: "chalk-board-cursor-avatar" })
|
|
8316
8759
|
] })
|
|
8317
8760
|
] }, person.id)) });
|
|
8318
8761
|
}
|
|
8319
8762
|
|
|
8320
8763
|
// src/components/board/BoardIsland.tsx
|
|
8321
|
-
import { useLayoutEffect as
|
|
8322
|
-
import { Fragment as
|
|
8764
|
+
import { useLayoutEffect as useLayoutEffect7, useRef as useRef32, useState as useState46 } from "react";
|
|
8765
|
+
import { Fragment as Fragment32, jsx as jsx72, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
8323
8766
|
var TOOLS = [
|
|
8324
8767
|
[
|
|
8325
8768
|
{ tool: "selection", label: "Select", key: "V", glyph: "select" },
|
|
@@ -8341,41 +8784,41 @@ var TOOLS = [
|
|
|
8341
8784
|
var LONG_PRESS_MS = 500;
|
|
8342
8785
|
var DRAG_START_PX = 4;
|
|
8343
8786
|
function Tip({ label, keyName, children }) {
|
|
8344
|
-
return /* @__PURE__ */
|
|
8787
|
+
return /* @__PURE__ */ jsxs48(ChalkTooltip, { trigger: children, children: [
|
|
8345
8788
|
label,
|
|
8346
|
-
keyName ? /* @__PURE__ */
|
|
8789
|
+
keyName ? /* @__PURE__ */ jsx72("kbd", { className: "chalk-board-kbd", children: keyName }) : null
|
|
8347
8790
|
] });
|
|
8348
8791
|
}
|
|
8349
8792
|
function ToolButton({ entry, active, onTool }) {
|
|
8350
|
-
return /* @__PURE__ */
|
|
8793
|
+
return /* @__PURE__ */ jsx72(Tip, { label: entry.label, keyName: entry.key, children: /* @__PURE__ */ jsx72("button", { type: "button", className: "chalk-board-tool", "aria-label": entry.label, "aria-keyshortcuts": entry.key, "aria-pressed": active, onClick: () => onTool(entry.tool), children: /* @__PURE__ */ jsx72(BoardIcon, { name: entry.glyph }) }) });
|
|
8351
8794
|
}
|
|
8352
8795
|
function ShapesButton({ tool, shape, onTool, side }) {
|
|
8353
8796
|
const active = SHAPES.some((entry) => entry.id === tool);
|
|
8354
|
-
return /* @__PURE__ */
|
|
8797
|
+
return /* @__PURE__ */ jsx72(
|
|
8355
8798
|
ChalkMenu,
|
|
8356
8799
|
{
|
|
8357
8800
|
side,
|
|
8358
|
-
trigger: /* @__PURE__ */
|
|
8359
|
-
/* @__PURE__ */
|
|
8360
|
-
/* @__PURE__ */
|
|
8801
|
+
trigger: /* @__PURE__ */ jsxs48("button", { type: "button", className: "chalk-board-tool", "aria-label": "Shapes", "aria-keyshortcuts": "R", "aria-pressed": active, children: [
|
|
8802
|
+
/* @__PURE__ */ jsx72(BoardIcon, { name: shape }),
|
|
8803
|
+
/* @__PURE__ */ jsx72(BoardIcon, { name: "chevron", size: 9, className: "chalk-board-tool-caret" })
|
|
8361
8804
|
] }),
|
|
8362
|
-
children: SHAPES.map((entry) => /* @__PURE__ */
|
|
8363
|
-
/* @__PURE__ */
|
|
8805
|
+
children: SHAPES.map((entry) => /* @__PURE__ */ jsxs48(ChalkMenuItem, { checked: tool === entry.id, onClick: () => onTool(entry.id), children: [
|
|
8806
|
+
/* @__PURE__ */ jsx72(BoardIcon, { name: entry.id, size: 18 }),
|
|
8364
8807
|
entry.label,
|
|
8365
|
-
/* @__PURE__ */
|
|
8808
|
+
/* @__PURE__ */ jsx72("kbd", { className: "chalk-board-menu-kbd", children: entry.key })
|
|
8366
8809
|
] }, entry.id))
|
|
8367
8810
|
}
|
|
8368
8811
|
);
|
|
8369
8812
|
}
|
|
8370
8813
|
function ColorPanel({ color, width, surface, theme, onColor, onWidth }) {
|
|
8371
|
-
return /* @__PURE__ */
|
|
8372
|
-
/* @__PURE__ */
|
|
8373
|
-
/* @__PURE__ */
|
|
8814
|
+
return /* @__PURE__ */ jsxs48("div", { className: "chalk-board-colors", children: [
|
|
8815
|
+
/* @__PURE__ */ jsx72("div", { role: "radiogroup", "aria-label": "Colour", className: "chalk-board-swatches", children: PEN_COLORS.map((entry) => /* @__PURE__ */ jsx72("button", { type: "button", role: "radio", "aria-checked": color === entry.id, "aria-label": entry.label, className: "chalk-board-swatch", onClick: () => onColor(entry.id), children: /* @__PURE__ */ jsx72("i", { style: { background: penHex(entry.id, surface, theme) } }) }, entry.id)) }),
|
|
8816
|
+
/* @__PURE__ */ jsx72("div", { role: "radiogroup", "aria-label": "Stroke width", className: "chalk-board-swatches", children: PEN_WIDTHS.map((entry) => /* @__PURE__ */ jsx72("button", { type: "button", role: "radio", "aria-checked": width === entry.id, "aria-label": entry.label, className: "chalk-board-width", onClick: () => onWidth(entry.id), children: /* @__PURE__ */ jsx72("i", { style: { height: entry.units } }) }, entry.id)) })
|
|
8374
8817
|
] });
|
|
8375
8818
|
}
|
|
8376
8819
|
function ColorButton(props) {
|
|
8377
8820
|
const swatch = penHex(props.color, props.surface, props.theme);
|
|
8378
|
-
return /* @__PURE__ */
|
|
8821
|
+
return /* @__PURE__ */ jsx72(
|
|
8379
8822
|
ChalkPopover,
|
|
8380
8823
|
{
|
|
8381
8824
|
label: "Colour and width",
|
|
@@ -8383,8 +8826,8 @@ function ColorButton(props) {
|
|
|
8383
8826
|
open: props.open,
|
|
8384
8827
|
onOpenChange: props.onOpenChange,
|
|
8385
8828
|
className: "chalk-board-color-popover",
|
|
8386
|
-
trigger: props.trigger ?? /* @__PURE__ */
|
|
8387
|
-
children: /* @__PURE__ */
|
|
8829
|
+
trigger: props.trigger ?? /* @__PURE__ */ jsx72("button", { type: "button", className: "chalk-board-tool", "aria-label": `Colour: ${PEN_COLORS.find((entry) => entry.id === props.color).label}`, children: /* @__PURE__ */ jsx72("span", { className: "chalk-board-tool-swatch", style: { background: swatch } }) }),
|
|
8830
|
+
children: /* @__PURE__ */ jsx72(ColorPanel, { ...props })
|
|
8388
8831
|
}
|
|
8389
8832
|
);
|
|
8390
8833
|
}
|
|
@@ -8401,20 +8844,20 @@ function roveFocus(event, vertical) {
|
|
|
8401
8844
|
buttons[next]?.focus();
|
|
8402
8845
|
}
|
|
8403
8846
|
function Separator() {
|
|
8404
|
-
return /* @__PURE__ */
|
|
8847
|
+
return /* @__PURE__ */ jsx72("span", { className: "chalk-board-separator", "aria-hidden": "true" });
|
|
8405
8848
|
}
|
|
8406
8849
|
function ToolRow({ tool, shape, onTool, place, canUndo, canRedo, onUndo, onRedo, ...colors }) {
|
|
8407
|
-
const groups = TOOLS.map((group, index) => /* @__PURE__ */
|
|
8408
|
-
group.map((entry) => /* @__PURE__ */
|
|
8409
|
-
index === 1 ? /* @__PURE__ */
|
|
8850
|
+
const groups = TOOLS.map((group, index) => /* @__PURE__ */ jsxs48("span", { className: "chalk-board-group", children: [
|
|
8851
|
+
group.map((entry) => /* @__PURE__ */ jsx72(ToolButton, { entry, active: tool === entry.tool, onTool }, entry.tool)),
|
|
8852
|
+
index === 1 ? /* @__PURE__ */ jsx72(ShapesButton, { tool, shape, onTool, side: place === "top" ? "bottom" : "top" }) : null
|
|
8410
8853
|
] }, index));
|
|
8411
|
-
return /* @__PURE__ */
|
|
8412
|
-
groups.flatMap((group, index) => [index > 0 ? /* @__PURE__ */
|
|
8413
|
-
/* @__PURE__ */
|
|
8414
|
-
/* @__PURE__ */
|
|
8415
|
-
/* @__PURE__ */
|
|
8416
|
-
/* @__PURE__ */
|
|
8417
|
-
/* @__PURE__ */
|
|
8854
|
+
return /* @__PURE__ */ jsxs48(Fragment32, { children: [
|
|
8855
|
+
groups.flatMap((group, index) => [index > 0 ? /* @__PURE__ */ jsx72(Separator, {}, `s${index}`) : null, group]),
|
|
8856
|
+
/* @__PURE__ */ jsx72(Separator, {}),
|
|
8857
|
+
/* @__PURE__ */ jsx72(Tip, { label: "Undo", keyName: "\u2318Z", children: /* @__PURE__ */ jsx72("button", { type: "button", className: "chalk-board-tool", "aria-label": "Undo", disabled: !canUndo, onClick: onUndo, children: /* @__PURE__ */ jsx72(BoardIcon, { name: "undo" }) }) }),
|
|
8858
|
+
/* @__PURE__ */ jsx72(Tip, { label: "Redo", keyName: "\u21E7\u2318Z", children: /* @__PURE__ */ jsx72("button", { type: "button", className: "chalk-board-tool", "aria-label": "Redo", disabled: !canRedo, onClick: onRedo, children: /* @__PURE__ */ jsx72(BoardIcon, { name: "redo" }) }) }),
|
|
8859
|
+
/* @__PURE__ */ jsx72(Separator, {}),
|
|
8860
|
+
/* @__PURE__ */ jsx72(ColorButton, { ...colors })
|
|
8418
8861
|
] });
|
|
8419
8862
|
}
|
|
8420
8863
|
function nearestPlace(board, x, y) {
|
|
@@ -8426,18 +8869,18 @@ function BoardIsland(props) {
|
|
|
8426
8869
|
const island = useRef32(null);
|
|
8427
8870
|
const tabStop = useRef32(null);
|
|
8428
8871
|
const reduced = usePrefersReducedMotion();
|
|
8429
|
-
const [drag, setDrag] =
|
|
8872
|
+
const [drag, setDrag] = useState46(null);
|
|
8430
8873
|
const dropRect = useRef32(null);
|
|
8431
|
-
const [expanded, setExpanded] =
|
|
8432
|
-
const [colorsOpen, setColorsOpen] =
|
|
8874
|
+
const [expanded, setExpanded] = useState46(false);
|
|
8875
|
+
const [colorsOpen, setColorsOpen] = useState46(false);
|
|
8433
8876
|
const press = useRef32({ long: false });
|
|
8434
|
-
|
|
8877
|
+
useLayoutEffect7(() => {
|
|
8435
8878
|
const buttons = [...island.current?.querySelectorAll("button") ?? []];
|
|
8436
|
-
const
|
|
8437
|
-
tabStop.current =
|
|
8438
|
-
for (const button of buttons) button.tabIndex = button ===
|
|
8879
|
+
const stop2 = buttons.find((button) => button === tabStop.current && !button.disabled) ?? buttons.find((button) => !button.disabled);
|
|
8880
|
+
tabStop.current = stop2 ?? null;
|
|
8881
|
+
for (const button of buttons) button.tabIndex = button === stop2 ? 0 : -1;
|
|
8439
8882
|
});
|
|
8440
|
-
|
|
8883
|
+
useLayoutEffect7(() => {
|
|
8441
8884
|
const element = island.current;
|
|
8442
8885
|
const from = dropRect.current;
|
|
8443
8886
|
dropRect.current = null;
|
|
@@ -8454,13 +8897,13 @@ function BoardIsland(props) {
|
|
|
8454
8897
|
const startDrag = (event) => {
|
|
8455
8898
|
const board = island.current?.parentElement;
|
|
8456
8899
|
if (!board || event.button !== 0) return;
|
|
8457
|
-
const
|
|
8900
|
+
const start2 = { x: event.clientX, y: event.clientY };
|
|
8458
8901
|
let moved = false;
|
|
8459
8902
|
const grip = event.currentTarget;
|
|
8460
8903
|
grip.setPointerCapture(event.pointerId);
|
|
8461
8904
|
const move = (next) => {
|
|
8462
|
-
const dx = next.clientX -
|
|
8463
|
-
const dy = next.clientY -
|
|
8905
|
+
const dx = next.clientX - start2.x;
|
|
8906
|
+
const dy = next.clientY - start2.y;
|
|
8464
8907
|
if (!moved && Math.hypot(dx, dy) < DRAG_START_PX) return;
|
|
8465
8908
|
moved = true;
|
|
8466
8909
|
setDrag({ x: dx, y: dy, near: nearestPlace(board.getBoundingClientRect(), next.clientX, next.clientY) });
|
|
@@ -8493,7 +8936,7 @@ function BoardIsland(props) {
|
|
|
8493
8936
|
};
|
|
8494
8937
|
if (compact && !expanded) {
|
|
8495
8938
|
const cancelPress = () => clearTimeout(press.current.timer);
|
|
8496
|
-
return /* @__PURE__ */
|
|
8939
|
+
return /* @__PURE__ */ jsx72("div", { ref: island, className: "chalk-board-island", "data-place": "compact", children: /* @__PURE__ */ jsx72(
|
|
8497
8940
|
ColorButton,
|
|
8498
8941
|
{
|
|
8499
8942
|
...props,
|
|
@@ -8501,7 +8944,7 @@ function BoardIsland(props) {
|
|
|
8501
8944
|
onOpenChange: (open) => {
|
|
8502
8945
|
if (!open) setColorsOpen(false);
|
|
8503
8946
|
},
|
|
8504
|
-
trigger: /* @__PURE__ */
|
|
8947
|
+
trigger: /* @__PURE__ */ jsxs48(
|
|
8505
8948
|
"button",
|
|
8506
8949
|
{
|
|
8507
8950
|
type: "button",
|
|
@@ -8522,8 +8965,8 @@ function BoardIsland(props) {
|
|
|
8522
8965
|
if (!press.current.long) setExpanded(true);
|
|
8523
8966
|
},
|
|
8524
8967
|
children: [
|
|
8525
|
-
/* @__PURE__ */
|
|
8526
|
-
/* @__PURE__ */
|
|
8968
|
+
/* @__PURE__ */ jsx72(BoardIcon, { name: "pen" }),
|
|
8969
|
+
/* @__PURE__ */ jsx72("span", { className: "chalk-board-tool-dot", style: { background: penHex(props.color, props.surface, props.theme) } })
|
|
8527
8970
|
]
|
|
8528
8971
|
}
|
|
8529
8972
|
)
|
|
@@ -8531,9 +8974,9 @@ function BoardIsland(props) {
|
|
|
8531
8974
|
) });
|
|
8532
8975
|
}
|
|
8533
8976
|
const vertical = place === "left" && !compact;
|
|
8534
|
-
return /* @__PURE__ */
|
|
8535
|
-
drag ? ISLAND_PLACES.map((entry) => /* @__PURE__ */
|
|
8536
|
-
/* @__PURE__ */
|
|
8977
|
+
return /* @__PURE__ */ jsxs48(Fragment32, { children: [
|
|
8978
|
+
drag ? ISLAND_PLACES.map((entry) => /* @__PURE__ */ jsx72("div", { className: "chalk-board-dropzone", "data-zone": entry.id, "data-near": drag.near === entry.id || void 0, "aria-hidden": "true" }, entry.id)) : null,
|
|
8979
|
+
/* @__PURE__ */ jsxs48(
|
|
8537
8980
|
"div",
|
|
8538
8981
|
{
|
|
8539
8982
|
ref: island,
|
|
@@ -8553,11 +8996,11 @@ function BoardIsland(props) {
|
|
|
8553
8996
|
for (const button of event.currentTarget.querySelectorAll("button")) button.tabIndex = button === event.target ? 0 : -1;
|
|
8554
8997
|
},
|
|
8555
8998
|
children: [
|
|
8556
|
-
compact ? /* @__PURE__ */
|
|
8557
|
-
/* @__PURE__ */
|
|
8558
|
-
/* @__PURE__ */
|
|
8559
|
-
] }) : /* @__PURE__ */
|
|
8560
|
-
/* @__PURE__ */
|
|
8999
|
+
compact ? /* @__PURE__ */ jsxs48(Fragment32, { children: [
|
|
9000
|
+
/* @__PURE__ */ jsx72("button", { type: "button", className: "chalk-board-tool", "aria-label": "Close drawing tools", onClick: () => setExpanded(false), children: /* @__PURE__ */ jsx72(BoardIcon, { name: "close" }) }),
|
|
9001
|
+
/* @__PURE__ */ jsx72(Separator, {})
|
|
9002
|
+
] }) : /* @__PURE__ */ jsx72(Tip, { label: "Move the tools", children: /* @__PURE__ */ jsx72("button", { type: "button", className: "chalk-board-grip", "aria-label": "Move the tools. Use Alt and the arrow keys to dock them left, bottom or top.", onPointerDown: startDrag, onKeyDown: gripKeys, children: /* @__PURE__ */ jsx72(GripIcon, {}) }) }),
|
|
9003
|
+
/* @__PURE__ */ jsx72(ToolRow, { ...props, place: compact ? "bottom" : place })
|
|
8561
9004
|
]
|
|
8562
9005
|
}
|
|
8563
9006
|
)
|
|
@@ -8566,54 +9009,76 @@ function BoardIsland(props) {
|
|
|
8566
9009
|
|
|
8567
9010
|
// src/components/board/BoardMenu.tsx
|
|
8568
9011
|
import { Menu as Menu5 } from "@base-ui/react/menu";
|
|
8569
|
-
import { Fragment as
|
|
9012
|
+
import { Fragment as Fragment33, jsx as jsx73, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
8570
9013
|
function SurfacePreview({ surface }) {
|
|
8571
|
-
return /* @__PURE__ */
|
|
9014
|
+
return /* @__PURE__ */ jsx73("span", { className: "chalk-board-tile-preview", "data-surface": surface, "aria-hidden": "true", children: surface === "dots" ? null : /* @__PURE__ */ jsx73("svg", { viewBox: "0 0 60 38", width: "100%", height: "100%", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: /* @__PURE__ */ jsx73("path", { d: "M14 22c5-8 9-8 12 0s8 6 12-2 6-6 8 0" }) }) });
|
|
8572
9015
|
}
|
|
8573
9016
|
function IslandPreview({ place }) {
|
|
8574
|
-
return /* @__PURE__ */
|
|
9017
|
+
return /* @__PURE__ */ jsx73("span", { className: "chalk-board-tile-preview", "data-island": place, "aria-hidden": "true", children: /* @__PURE__ */ jsx73("i", {}) });
|
|
8575
9018
|
}
|
|
8576
9019
|
function Tiles({ label, value, options, onChange, preview }) {
|
|
8577
|
-
return /* @__PURE__ */
|
|
8578
|
-
/* @__PURE__ */
|
|
8579
|
-
/* @__PURE__ */
|
|
9020
|
+
return /* @__PURE__ */ jsxs49(Fragment33, { children: [
|
|
9021
|
+
/* @__PURE__ */ jsx73("div", { className: "chalk-board-menu-sublabel", children: label }),
|
|
9022
|
+
/* @__PURE__ */ jsx73(Menu5.RadioGroup, { value, onValueChange: (next) => onChange(next), className: "chalk-board-tiles", "aria-label": label, children: options.map((option) => /* @__PURE__ */ jsxs49(Menu5.RadioItem, { value: option.id, closeOnClick: false, className: "chalk-board-tile", children: [
|
|
8580
9023
|
preview(option.id),
|
|
8581
9024
|
option.label
|
|
8582
9025
|
] }, option.id)) })
|
|
8583
9026
|
] });
|
|
8584
9027
|
}
|
|
8585
|
-
function
|
|
8586
|
-
return /* @__PURE__ */
|
|
9028
|
+
function Check({ on }) {
|
|
9029
|
+
return /* @__PURE__ */ jsx73("span", { "data-part": "menu-check", className: "chalk-menu-check", "aria-hidden": "true", children: on ? /* @__PURE__ */ jsx73("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx73("path", { d: "M20 6L9 17l-5-5" }) }) : null });
|
|
9030
|
+
}
|
|
9031
|
+
function PickedPeople({ people, onPick }) {
|
|
9032
|
+
if (people.length === 0) return /* @__PURE__ */ jsx73("p", { className: "chalk-board-picked-note", children: "No one else is here yet. Hosts can always draw." });
|
|
9033
|
+
return /* @__PURE__ */ jsxs49(Fragment33, { children: [
|
|
9034
|
+
/* @__PURE__ */ jsx73("div", { className: "chalk-board-picked", role: "group", "aria-label": "Picked people", children: people.map((person) => /* @__PURE__ */ jsxs49(Menu5.CheckboxItem, { className: "chalk-menu-item", checked: person.picked, onCheckedChange: (picked) => onPick(person.id, picked), closeOnClick: false, children: [
|
|
9035
|
+
/* @__PURE__ */ jsx73(Check, { on: person.picked }),
|
|
9036
|
+
/* @__PURE__ */ jsx73("span", { className: "chalk-board-picked-name", children: person.name })
|
|
9037
|
+
] }, person.id)) }),
|
|
9038
|
+
people.some((person) => person.picked) ? null : /* @__PURE__ */ jsx73("p", { className: "chalk-board-picked-note", children: "Only hosts can draw until you pick someone." })
|
|
9039
|
+
] });
|
|
9040
|
+
}
|
|
9041
|
+
function WhoCanDrawSection({ policy, people, onPolicy, onPick }) {
|
|
9042
|
+
return /* @__PURE__ */ jsxs49(Fragment33, { children: [
|
|
9043
|
+
/* @__PURE__ */ jsx73(Menu5.Separator, { className: "chalk-board-menu-rule" }),
|
|
9044
|
+
/* @__PURE__ */ jsx73(ChalkMenuLabel, { children: "Who can draw" }),
|
|
9045
|
+
DRAW_POLICIES.map((option) => /* @__PURE__ */ jsx73(ChalkMenuItem, { checked: policy === option.id, closeOnClick: false, onClick: () => onPolicy(option.id), children: option.label }, option.id)),
|
|
9046
|
+
policy === "picked" ? /* @__PURE__ */ jsx73(PickedPeople, { people, onPick }) : null
|
|
9047
|
+
] });
|
|
9048
|
+
}
|
|
9049
|
+
function BoardMenu({ surface, onSurface, place, onPlace, onDownload, onCopy, whoCanDraw, onBring, onClear, onClose }) {
|
|
9050
|
+
return /* @__PURE__ */ jsxs49(
|
|
8587
9051
|
ChalkMenu,
|
|
8588
9052
|
{
|
|
8589
9053
|
className: "chalk-board-menu",
|
|
8590
|
-
trigger: /* @__PURE__ */
|
|
9054
|
+
trigger: /* @__PURE__ */ jsx73("button", { type: "button", className: "chalk-board-menu-button", "aria-label": "Board menu", children: /* @__PURE__ */ jsx73(BoardIcon, { name: "more" }) }),
|
|
8591
9055
|
children: [
|
|
8592
|
-
/* @__PURE__ */
|
|
8593
|
-
/* @__PURE__ */
|
|
9056
|
+
/* @__PURE__ */ jsxs49(ChalkMenuItem, { onClick: onDownload, children: [
|
|
9057
|
+
/* @__PURE__ */ jsx73(BoardIcon, { name: "download", size: 18 }),
|
|
8594
9058
|
"Download as PNG"
|
|
8595
9059
|
] }),
|
|
8596
|
-
/* @__PURE__ */
|
|
8597
|
-
/* @__PURE__ */
|
|
9060
|
+
/* @__PURE__ */ jsxs49(ChalkMenuItem, { onClick: onCopy, children: [
|
|
9061
|
+
/* @__PURE__ */ jsx73(BoardIcon, { name: "copy", size: 18 }),
|
|
8598
9062
|
"Copy as image"
|
|
8599
9063
|
] }),
|
|
8600
|
-
/* @__PURE__ */
|
|
8601
|
-
/* @__PURE__ */
|
|
8602
|
-
/* @__PURE__ */
|
|
8603
|
-
place ? /* @__PURE__ */
|
|
8604
|
-
|
|
8605
|
-
onBring ? /* @__PURE__ */
|
|
8606
|
-
|
|
9064
|
+
/* @__PURE__ */ jsx73(Menu5.Separator, { className: "chalk-board-menu-rule" }),
|
|
9065
|
+
/* @__PURE__ */ jsx73(ChalkMenuLabel, { children: "Board appearance" }),
|
|
9066
|
+
/* @__PURE__ */ jsx73(Tiles, { label: "Surface", value: surface, options: SURFACES, onChange: onSurface, preview: (id) => /* @__PURE__ */ jsx73(SurfacePreview, { surface: id }) }),
|
|
9067
|
+
place ? /* @__PURE__ */ jsx73(Tiles, { label: "Tool island", value: place, options: ISLAND_PLACES, onChange: onPlace, preview: (id) => /* @__PURE__ */ jsx73(IslandPreview, { place: id }) }) : null,
|
|
9068
|
+
whoCanDraw ? /* @__PURE__ */ jsx73(WhoCanDrawSection, { ...whoCanDraw }) : null,
|
|
9069
|
+
onBring || onClear ? /* @__PURE__ */ jsx73(Menu5.Separator, { className: "chalk-board-menu-rule" }) : null,
|
|
9070
|
+
onBring ? /* @__PURE__ */ jsxs49(ChalkMenuItem, { onClick: onBring, children: [
|
|
9071
|
+
/* @__PURE__ */ jsx73(BoardIcon, { name: "target", size: 18 }),
|
|
8607
9072
|
"Bring everyone here"
|
|
8608
9073
|
] }) : null,
|
|
8609
|
-
onClear ? /* @__PURE__ */
|
|
8610
|
-
/* @__PURE__ */
|
|
9074
|
+
onClear ? /* @__PURE__ */ jsx73(ChalkMenuItem, { onClick: onClear, children: /* @__PURE__ */ jsxs49("span", { className: "chalk-board-danger", children: [
|
|
9075
|
+
/* @__PURE__ */ jsx73(BoardIcon, { name: "trash", size: 18 }),
|
|
8611
9076
|
"Clear board"
|
|
8612
9077
|
] }) }) : null,
|
|
8613
|
-
onClose ? /* @__PURE__ */
|
|
8614
|
-
/* @__PURE__ */
|
|
8615
|
-
/* @__PURE__ */
|
|
8616
|
-
/* @__PURE__ */
|
|
9078
|
+
onClose ? /* @__PURE__ */ jsxs49(Fragment33, { children: [
|
|
9079
|
+
/* @__PURE__ */ jsx73(Menu5.Separator, { className: "chalk-board-menu-rule" }),
|
|
9080
|
+
/* @__PURE__ */ jsxs49(ChalkMenuItem, { onClick: onClose, children: [
|
|
9081
|
+
/* @__PURE__ */ jsx73(BoardIcon, { name: "close", size: 18 }),
|
|
8617
9082
|
"Close board"
|
|
8618
9083
|
] })
|
|
8619
9084
|
] }) : null
|
|
@@ -8622,10 +9087,43 @@ function BoardMenu({ surface, onSurface, place, onPlace, onDownload, onCopy, onB
|
|
|
8622
9087
|
);
|
|
8623
9088
|
}
|
|
8624
9089
|
|
|
9090
|
+
// src/components/board/board-draw-policy.ts
|
|
9091
|
+
import { useCallback as useCallback13, useMemo as useMemo16 } from "react";
|
|
9092
|
+
function useWhoCanDraw(toast) {
|
|
9093
|
+
const client = useSpaceClient();
|
|
9094
|
+
const isHost = useCan("manageWhiteboard");
|
|
9095
|
+
const self = useSelf();
|
|
9096
|
+
const { roster } = useParticipants();
|
|
9097
|
+
const { access } = useWhiteboard();
|
|
9098
|
+
const transport = client.whiteboard.transport();
|
|
9099
|
+
const people = useMemo16(
|
|
9100
|
+
() => roster.filter((person) => person.participantId !== self.participantId && !person.capabilities.includes("manageWhiteboard")).map((person) => ({
|
|
9101
|
+
id: person.participantId,
|
|
9102
|
+
name: person.displayName,
|
|
9103
|
+
picked: access.permissions.some((permission) => permission.participantId === person.participantId && permission.canDraw)
|
|
9104
|
+
})),
|
|
9105
|
+
[roster, self.participantId, access.permissions]
|
|
9106
|
+
);
|
|
9107
|
+
const onPolicy = useCallback13(
|
|
9108
|
+
(policy) => {
|
|
9109
|
+
transport?.setDrawPolicy?.(policy).catch(() => toast({ type: "error", message: "Could not change who can draw. Try again." }));
|
|
9110
|
+
},
|
|
9111
|
+
[transport, toast]
|
|
9112
|
+
);
|
|
9113
|
+
const onPick = useCallback13(
|
|
9114
|
+
(id, picked) => {
|
|
9115
|
+
transport?.setDrawPermission(id, picked).catch(() => toast({ type: "error", message: "Could not change who can draw. Try again." }));
|
|
9116
|
+
},
|
|
9117
|
+
[transport, toast]
|
|
9118
|
+
);
|
|
9119
|
+
if (!isHost || access.policy === null || !transport?.setDrawPolicy) return void 0;
|
|
9120
|
+
return { policy: access.policy, people, onPolicy, onPick };
|
|
9121
|
+
}
|
|
9122
|
+
|
|
8625
9123
|
// src/components/board/BoardStyles.tsx
|
|
8626
|
-
import { jsx as
|
|
9124
|
+
import { jsx as jsx74 } from "react/jsx-runtime";
|
|
8627
9125
|
function BoardStyles() {
|
|
8628
|
-
return /* @__PURE__ */
|
|
9126
|
+
return /* @__PURE__ */ jsx74("style", { href: "chalk-board", precedence: "default", children: BOARD_CSS });
|
|
8629
9127
|
}
|
|
8630
9128
|
var BOARD_CSS = `.chalk-board {
|
|
8631
9129
|
--board-shadow: 0 0 0 1px var(--chalk-line-strong), 0 8px 24px rgba(0,0,0,.35);
|
|
@@ -8728,6 +9226,9 @@ body:has(.chalk-board) :is(.excalidraw-modal-container, .excalidraw-tooltip) {di
|
|
|
8728
9226
|
.chalk-board-tile-preview[data-island="left"] i {left:5px; top:20%; bottom:20%; width:5px;}
|
|
8729
9227
|
.chalk-board-menu-kbd {margin-left:auto; padding-left:18px; font:600 11px ui-monospace, SFMono-Regular, Menlo, monospace; color:var(--chalk-muted-text);}
|
|
8730
9228
|
.chalk-board-danger {display:contents; color:var(--chalk-danger-text);}
|
|
9229
|
+
.chalk-board-picked {max-height:220px; overflow-y:auto; padding-left:16px;}
|
|
9230
|
+
.chalk-board-picked-name {min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
|
|
9231
|
+
.chalk-board-picked-note {margin:0; padding:4px 10px 8px 26px; font-size:12px; line-height:1.4; color:var(--chalk-muted-text);}
|
|
8731
9232
|
|
|
8732
9233
|
.chalk-board-zoom {position:absolute; right:12px; bottom:12px; z-index:5; height:40px; display:flex; align-items:center; border-radius:999px; padding:0 4px; transition:translate .2s ease-out;}
|
|
8733
9234
|
.chalk-board-zoom button {height:32px; min-width:32px; border-radius:999px; display:grid; place-items:center; padding:0 6px !important; font-size:13px; font-weight:600; font-variant-numeric:tabular-nums;}
|
|
@@ -8796,7 +9297,7 @@ body:has(.chalk-board) :is(.excalidraw-modal-container, .excalidraw-tooltip) {di
|
|
|
8796
9297
|
`;
|
|
8797
9298
|
|
|
8798
9299
|
// src/components/board/Board.tsx
|
|
8799
|
-
import { Fragment as
|
|
9300
|
+
import { Fragment as Fragment34, jsx as jsx75, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
8800
9301
|
var SURFACE_KEY = "chalk.board.surface";
|
|
8801
9302
|
var ISLAND_KEY = "chalk.board.island";
|
|
8802
9303
|
var COMPACT_BELOW_PX = 1060;
|
|
@@ -8814,15 +9315,15 @@ function fitContent(engine, animate) {
|
|
|
8814
9315
|
function isTyping(target) {
|
|
8815
9316
|
return target instanceof HTMLElement && (target.isContentEditable || target.tagName === "TEXTAREA" || target.tagName === "INPUT");
|
|
8816
9317
|
}
|
|
8817
|
-
function useCamera(engine, root,
|
|
9318
|
+
function useCamera(engine, root, onLeadingMove, onMoved, onViewportReady) {
|
|
8818
9319
|
const cameraRef = useRef33({ scrollX: 0, scrollY: 0, zoom: 1 });
|
|
8819
9320
|
const viewportRef = useRef33({ width: 1, height: 1 });
|
|
8820
9321
|
const expected = useRef33(null);
|
|
8821
9322
|
const glide = useRef33(0);
|
|
8822
|
-
const [zoom, setZoom] =
|
|
9323
|
+
const [zoom, setZoom] = useState47(1);
|
|
8823
9324
|
const reduced = usePrefersReducedMotion();
|
|
8824
|
-
const
|
|
8825
|
-
|
|
9325
|
+
const leading = useRef33(onLeadingMove);
|
|
9326
|
+
leading.current = onLeadingMove;
|
|
8826
9327
|
const moved = useRef33(onMoved);
|
|
8827
9328
|
moved.current = onMoved;
|
|
8828
9329
|
const resized = useRef33(onViewportReady);
|
|
@@ -8845,6 +9346,7 @@ function useCamera(engine, root, onManualMove, onMoved, onViewportReady) {
|
|
|
8845
9346
|
return engine.api.onScrollChange((scrollX, scrollY, next) => {
|
|
8846
9347
|
const camera = { scrollX, scrollY, zoom: next.value };
|
|
8847
9348
|
if (camera.zoom !== clampZoom(camera.zoom)) {
|
|
9349
|
+
leading.current();
|
|
8848
9350
|
expected.current = { ...camera, zoom: clampZoom(camera.zoom) };
|
|
8849
9351
|
setCamera(engine, expected.current);
|
|
8850
9352
|
return;
|
|
@@ -8853,7 +9355,7 @@ function useCamera(engine, root, onManualMove, onMoved, onViewportReady) {
|
|
|
8853
9355
|
if (expected.current && sameCamera(camera, expected.current)) return;
|
|
8854
9356
|
expected.current = null;
|
|
8855
9357
|
cancelAnimationFrame(glide.current);
|
|
8856
|
-
|
|
9358
|
+
leading.current();
|
|
8857
9359
|
moved.current();
|
|
8858
9360
|
});
|
|
8859
9361
|
}, [engine, root]);
|
|
@@ -8870,10 +9372,16 @@ function useCamera(engine, root, onManualMove, onMoved, onViewportReady) {
|
|
|
8870
9372
|
return () => observer.disconnect();
|
|
8871
9373
|
}, [root]);
|
|
8872
9374
|
useEffect37(() => () => cancelAnimationFrame(glide.current), []);
|
|
8873
|
-
const move =
|
|
8874
|
-
(target, animate) => {
|
|
9375
|
+
const move = useCallback14(
|
|
9376
|
+
(target, animate, source) => {
|
|
8875
9377
|
if (!engine) return;
|
|
9378
|
+
if (source !== "follow") leading.current();
|
|
8876
9379
|
cancelAnimationFrame(glide.current);
|
|
9380
|
+
if (sameCamera(target, cameraRef.current)) {
|
|
9381
|
+
expected.current = target;
|
|
9382
|
+
moved.current();
|
|
9383
|
+
return;
|
|
9384
|
+
}
|
|
8877
9385
|
const set = (camera) => {
|
|
8878
9386
|
expected.current = camera;
|
|
8879
9387
|
setCamera(engine, camera);
|
|
@@ -8886,16 +9394,22 @@ function useCamera(engine, root, onManualMove, onMoved, onViewportReady) {
|
|
|
8886
9394
|
const from = cameraRef.current;
|
|
8887
9395
|
const started = performance.now();
|
|
8888
9396
|
const step = (now) => {
|
|
8889
|
-
const progress = Math.min(1, (now - started) / GLIDE_MS);
|
|
9397
|
+
const progress = Math.max(0, Math.min(1, (now - started) / GLIDE_MS));
|
|
8890
9398
|
set(mixCamera(from, target, 1 - (1 - progress) ** 3));
|
|
8891
9399
|
if (progress < 1) glide.current = requestAnimationFrame(step);
|
|
8892
|
-
else
|
|
9400
|
+
else {
|
|
9401
|
+
if (source !== "follow") leading.current();
|
|
9402
|
+
moved.current();
|
|
9403
|
+
}
|
|
8893
9404
|
};
|
|
8894
9405
|
glide.current = requestAnimationFrame(step);
|
|
8895
9406
|
},
|
|
8896
9407
|
[engine, reduced]
|
|
8897
9408
|
);
|
|
8898
|
-
|
|
9409
|
+
const fit = useCallback14(() => {
|
|
9410
|
+
if (engine) fitContent(engine, false);
|
|
9411
|
+
}, [engine]);
|
|
9412
|
+
return useMemo17(() => ({ cameraRef, viewportRef, zoom, move, fit }), [move, zoom, fit]);
|
|
8899
9413
|
}
|
|
8900
9414
|
function useBoardKeys(root, handlers) {
|
|
8901
9415
|
const latest = useRef33(handlers);
|
|
@@ -8972,29 +9486,30 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
8972
9486
|
const boardSession = useWhiteboard().engine;
|
|
8973
9487
|
const offline = connection.status === "reconnecting";
|
|
8974
9488
|
const phone = useMediaQuery("(max-width: 640px)");
|
|
8975
|
-
const [engine, setEngine] =
|
|
9489
|
+
const [engine, setEngine] = useState47(null);
|
|
8976
9490
|
const toast = useBoardToast(engine);
|
|
8977
|
-
const
|
|
8978
|
-
const [
|
|
8979
|
-
const [
|
|
8980
|
-
const [
|
|
8981
|
-
const [
|
|
8982
|
-
const [
|
|
8983
|
-
const [
|
|
9491
|
+
const whoCanDraw = useWhoCanDraw(toast);
|
|
9492
|
+
const [surface, setSurface] = useState47(() => readStored(SURFACE_KEY, SURFACES, "chalkboard"));
|
|
9493
|
+
const [place, setPlace] = useState47(() => readStored(ISLAND_KEY, ISLAND_PLACES, "bottom"));
|
|
9494
|
+
const [tool, setTool] = useState47("pen");
|
|
9495
|
+
const [shape, setShape] = useState47("rectangle");
|
|
9496
|
+
const [color, setColor] = useState47("ink");
|
|
9497
|
+
const [width, setWidth] = useState47("medium");
|
|
9498
|
+
const [elementCount, setElementCount] = useState47(0);
|
|
8984
9499
|
const empty = elementCount === 0;
|
|
8985
|
-
const [narrow, setNarrow] =
|
|
8986
|
-
const [announcement, setAnnouncement] =
|
|
9500
|
+
const [narrow, setNarrow] = useState47(false);
|
|
9501
|
+
const [announcement, setAnnouncement] = useState47("");
|
|
8987
9502
|
const canDraw = primary && (board.collab?.canDraw ?? board.canDraw ?? true);
|
|
8988
9503
|
const compact = phone || narrow;
|
|
8989
9504
|
const history = useEngineHistory(root, engine);
|
|
8990
9505
|
const touched = useRef33(false);
|
|
8991
9506
|
const views = useRef33(/* @__PURE__ */ new Map());
|
|
8992
9507
|
const cursors = useRef33(/* @__PURE__ */ new Map());
|
|
8993
|
-
const pen =
|
|
9508
|
+
const pen = useMemo17(() => ({ color, width, surface, theme: colorScheme }), [color, width, surface, colorScheme]);
|
|
8994
9509
|
const followingRef = useRef33(following);
|
|
8995
9510
|
followingRef.current = following;
|
|
8996
|
-
const nameOf =
|
|
8997
|
-
const colorFor =
|
|
9511
|
+
const nameOf = useCallback14((id) => first(people.find((person) => person.id === id)?.displayName ?? "Someone"), [people]);
|
|
9512
|
+
const colorFor = useCallback14(
|
|
8998
9513
|
(id) => personColor(
|
|
8999
9514
|
Math.max(
|
|
9000
9515
|
0,
|
|
@@ -9003,7 +9518,7 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9003
9518
|
),
|
|
9004
9519
|
[people]
|
|
9005
9520
|
);
|
|
9006
|
-
const stopFollowing =
|
|
9521
|
+
const stopFollowing = useCallback14(() => {
|
|
9007
9522
|
const current = followingRef.current;
|
|
9008
9523
|
if (!current) return;
|
|
9009
9524
|
followingRef.current = null;
|
|
@@ -9013,14 +9528,32 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9013
9528
|
const shareView = useRef33(() => false);
|
|
9014
9529
|
const viewSender = useRef33(sendView);
|
|
9015
9530
|
viewSender.current = sendView;
|
|
9531
|
+
const selectedFollow = useRef33(following);
|
|
9016
9532
|
const ownParticipantId = useSelf().participantId;
|
|
9017
|
-
const appliedVersions = useRef33(new
|
|
9533
|
+
const appliedVersions = useRef33(new ChalkWhiteboardViewVersions());
|
|
9534
|
+
const { roster } = useParticipants();
|
|
9535
|
+
const previousRoster = useRef33(new Set(roster.map((person) => person.participantId)));
|
|
9536
|
+
useEffect37(() => {
|
|
9537
|
+
const next = new Set(roster.map((person) => person.participantId));
|
|
9538
|
+
for (const id of previousRoster.current) {
|
|
9539
|
+
if (next.has(id)) continue;
|
|
9540
|
+
appliedVersions.current.forgetParticipant(id);
|
|
9541
|
+
for (const [publisher, view] of views.current) {
|
|
9542
|
+
if (publisher === id || view.originParticipantId === id) views.current.delete(publisher);
|
|
9543
|
+
}
|
|
9544
|
+
cursors.current.delete(id);
|
|
9545
|
+
}
|
|
9546
|
+
previousRoster.current = next;
|
|
9547
|
+
}, [roster]);
|
|
9018
9548
|
const viewsAvailable = sendView !== void 0;
|
|
9019
9549
|
const reapplyView = useRef33(() => void 0);
|
|
9020
9550
|
const camera = useCamera(
|
|
9021
9551
|
engine,
|
|
9022
9552
|
root,
|
|
9023
|
-
|
|
9553
|
+
() => {
|
|
9554
|
+
stopFollowing();
|
|
9555
|
+
shareView.current(false, true);
|
|
9556
|
+
},
|
|
9024
9557
|
() => shareView.current(false),
|
|
9025
9558
|
() => reapplyView.current()
|
|
9026
9559
|
);
|
|
@@ -9028,21 +9561,35 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9028
9561
|
if (!visible || !viewsAvailable || !engine) return;
|
|
9029
9562
|
let last = 0;
|
|
9030
9563
|
let pending;
|
|
9564
|
+
let pendingLead = false;
|
|
9031
9565
|
const send = (bring2) => {
|
|
9566
|
+
const lead = pendingLead || bring2;
|
|
9567
|
+
pendingLead = false;
|
|
9032
9568
|
const followedView = followingRef.current ? views.current.get(followingRef.current) : void 0;
|
|
9033
|
-
|
|
9569
|
+
const selected = followedView !== void 0 && selectedFollow.current === followingRef.current;
|
|
9570
|
+
if (followedView && !followedView.originParticipantId && !followedView.ownerId && !bring2) return true;
|
|
9034
9571
|
const view = followedView ?? visibleView(camera.cameraRef.current, camera.viewportRef.current);
|
|
9035
9572
|
last = performance.now();
|
|
9036
|
-
const rectangle = { x: view.x, y: view.y, width: view.width, height: view.height, bring: bring2 };
|
|
9037
|
-
|
|
9573
|
+
const rectangle = { x: view.x, y: view.y, width: view.width, height: view.height, bring: bring2, lead: lead || selected };
|
|
9574
|
+
let outgoing = rectangle;
|
|
9575
|
+
if (followedView && !lead) {
|
|
9576
|
+
if (followedView.ownerId) {
|
|
9577
|
+
outgoing = { ...rectangle, originParticipantId: followedView.participantId, originSequence: followedView.ownerSequence };
|
|
9578
|
+
} else if (followedView.originParticipantId && followedView.originSequence !== void 0) {
|
|
9579
|
+
outgoing = { ...rectangle, originParticipantId: followedView.originParticipantId, originSequence: followedView.originSequence, ...followedView.originEpoch ? { originEpoch: followedView.originEpoch } : {} };
|
|
9580
|
+
}
|
|
9581
|
+
}
|
|
9038
9582
|
try {
|
|
9039
|
-
|
|
9583
|
+
const sent = viewSender.current?.(outgoing) ?? false;
|
|
9584
|
+
if (sent && selected) selectedFollow.current = null;
|
|
9585
|
+
return sent;
|
|
9040
9586
|
} catch (error) {
|
|
9041
9587
|
console.warn("Board view dropped.", { operation: "sendView", error });
|
|
9042
9588
|
return false;
|
|
9043
9589
|
}
|
|
9044
9590
|
};
|
|
9045
|
-
shareView.current = (bring2) => {
|
|
9591
|
+
shareView.current = (bring2, lead = false) => {
|
|
9592
|
+
pendingLead ||= lead;
|
|
9046
9593
|
if (bring2) return send(true);
|
|
9047
9594
|
clearTimeout(pending);
|
|
9048
9595
|
pending = setTimeout(() => send(false), Math.max(0, VIEW_SEND_MS - (performance.now() - last)));
|
|
@@ -9059,13 +9606,13 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9059
9606
|
};
|
|
9060
9607
|
}, [boardSession.sceneId, boardSession.status, camera.cameraRef, camera.viewportRef, connection.status, engine, visible, viewsAvailable]);
|
|
9061
9608
|
const { move, viewportRef } = camera;
|
|
9062
|
-
const goTo =
|
|
9609
|
+
const goTo = useCallback14(
|
|
9063
9610
|
(participantId, animate, selected = false) => {
|
|
9064
9611
|
const view = views.current.get(participantId);
|
|
9065
9612
|
if (!view || viewportRef.current.width <= 0 || viewportRef.current.height <= 0) return;
|
|
9066
|
-
if (!selected && !appliedVersions.current.isNew(view)) return;
|
|
9067
|
-
appliedVersions.current.remember(view);
|
|
9068
|
-
move(cameraForView(view, viewportRef.current), animate);
|
|
9613
|
+
if (!selected && !appliedVersions.current.isNew(view, participantId)) return;
|
|
9614
|
+
appliedVersions.current.remember(view, participantId);
|
|
9615
|
+
move(cameraForView(view, viewportRef.current), animate, "follow");
|
|
9069
9616
|
},
|
|
9070
9617
|
[move, viewportRef]
|
|
9071
9618
|
);
|
|
@@ -9074,17 +9621,23 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9074
9621
|
};
|
|
9075
9622
|
const subscribe3 = board.collab?.subscribe;
|
|
9076
9623
|
const latestView = useRef33(() => void 0);
|
|
9624
|
+
useEffect37(
|
|
9625
|
+
() => subscribe3?.((event) => {
|
|
9626
|
+
if (event.type !== "snapshot") return;
|
|
9627
|
+
views.current.clear();
|
|
9628
|
+
appliedVersions.current.clear();
|
|
9629
|
+
}),
|
|
9630
|
+
[subscribe3]
|
|
9631
|
+
);
|
|
9077
9632
|
latestView.current = (event) => {
|
|
9078
9633
|
const previous = views.current.get(event.participantId);
|
|
9079
|
-
if (!event.bring)
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
if (event.originParticipantId && previous?.originParticipantId === event.originParticipantId && event.originEpoch === previous.originEpoch && event.originSequence <= previous.originSequence) return;
|
|
9083
|
-
}
|
|
9634
|
+
if (!event.bring && (event.participantId === ownParticipantId || !event.ownerId && event.originParticipantId === ownParticipantId)) return;
|
|
9635
|
+
if (!event.bring && !appliedVersions.current.isNew(event, event.participantId)) return;
|
|
9636
|
+
if (!event.ownerId && !event.bring && event.originParticipantId && previous?.originParticipantId === event.originParticipantId && event.originEpoch === previous.originEpoch && event.originSequence <= previous.originSequence) return;
|
|
9084
9637
|
const newPeer = !previous;
|
|
9085
9638
|
views.current.delete(event.participantId);
|
|
9086
|
-
views.current.set(event.participantId,
|
|
9087
|
-
if (views.current.size >
|
|
9639
|
+
views.current.set(event.participantId, { ...event, bring: false });
|
|
9640
|
+
if (views.current.size > WHITEBOARD_VIEW_PEOPLE_MAX) {
|
|
9088
9641
|
const oldest = views.current.keys().next().value;
|
|
9089
9642
|
if (oldest !== void 0) views.current.delete(oldest);
|
|
9090
9643
|
}
|
|
@@ -9092,6 +9645,7 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9092
9645
|
shareView.current(false);
|
|
9093
9646
|
}
|
|
9094
9647
|
if (event.bring) {
|
|
9648
|
+
appliedVersions.current.remember(event, event.participantId);
|
|
9095
9649
|
followingRef.current = event.participantId;
|
|
9096
9650
|
onFollow(event.participantId);
|
|
9097
9651
|
toast({ message: `${nameOf(event.participantId)} brought everyone to this view` });
|
|
@@ -9108,7 +9662,11 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9108
9662
|
});
|
|
9109
9663
|
}, [subscribe3]);
|
|
9110
9664
|
useEffect37(() => {
|
|
9111
|
-
|
|
9665
|
+
selectedFollow.current = following;
|
|
9666
|
+
if (following) {
|
|
9667
|
+
goTo(following, true, true);
|
|
9668
|
+
shareView.current(false);
|
|
9669
|
+
}
|
|
9112
9670
|
}, [following, goTo]);
|
|
9113
9671
|
useEffect37(() => {
|
|
9114
9672
|
if (engine && canDraw) applyTool(engine, tool, pen);
|
|
@@ -9123,7 +9681,7 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9123
9681
|
setElementCount(engine.api.getSceneElements().length);
|
|
9124
9682
|
if (hasContent(engine)) {
|
|
9125
9683
|
touched.current = true;
|
|
9126
|
-
if (!followingRef.current)
|
|
9684
|
+
if (!followingRef.current) camera.fit();
|
|
9127
9685
|
}
|
|
9128
9686
|
const offDown = engine.api.onPointerDown(() => {
|
|
9129
9687
|
touched.current = true;
|
|
@@ -9133,7 +9691,10 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9133
9691
|
setElementCount(count);
|
|
9134
9692
|
if (!touched.current && count > 0) {
|
|
9135
9693
|
touched.current = true;
|
|
9136
|
-
if (!followingRef.current)
|
|
9694
|
+
if (!followingRef.current)
|
|
9695
|
+
requestAnimationFrame(() => {
|
|
9696
|
+
if (!followingRef.current) camera.fit();
|
|
9697
|
+
});
|
|
9137
9698
|
}
|
|
9138
9699
|
const editing = appState.editingTextElement !== null;
|
|
9139
9700
|
if (!wasEditing && editing) beforeEditing = sceneSignature(engine);
|
|
@@ -9147,7 +9708,7 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9147
9708
|
offDown();
|
|
9148
9709
|
offChange();
|
|
9149
9710
|
};
|
|
9150
|
-
}, [engine]);
|
|
9711
|
+
}, [engine, camera.fit]);
|
|
9151
9712
|
useEffect37(() => {
|
|
9152
9713
|
const element = root.current;
|
|
9153
9714
|
if (!element) return;
|
|
@@ -9155,19 +9716,19 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9155
9716
|
observer.observe(element);
|
|
9156
9717
|
return () => observer.disconnect();
|
|
9157
9718
|
}, []);
|
|
9158
|
-
const chooseTool =
|
|
9719
|
+
const chooseTool = useCallback14((next) => {
|
|
9159
9720
|
if (next === "rectangle" || next === "ellipse" || next === "diamond" || next === "arrow" || next === "line") setShape(next);
|
|
9160
9721
|
setTool(next);
|
|
9161
9722
|
}, []);
|
|
9162
|
-
const undo =
|
|
9723
|
+
const undo = useCallback14(() => {
|
|
9163
9724
|
const container = root.current?.querySelector(".excalidraw");
|
|
9164
9725
|
if (container) pressHistory(container, false);
|
|
9165
9726
|
}, []);
|
|
9166
|
-
const redo =
|
|
9727
|
+
const redo = useCallback14(() => {
|
|
9167
9728
|
const container = root.current?.querySelector(".excalidraw");
|
|
9168
9729
|
if (container) pressHistory(container, true);
|
|
9169
9730
|
}, []);
|
|
9170
|
-
const zoomBy =
|
|
9731
|
+
const zoomBy = useCallback14(
|
|
9171
9732
|
(factor) => {
|
|
9172
9733
|
stopFollowing();
|
|
9173
9734
|
camera.move(zoomAroundCentre(camera.cameraRef.current, camera.viewportRef.current, camera.cameraRef.current.zoom * factor), true);
|
|
@@ -9249,34 +9810,34 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9249
9810
|
const surfaceVars = { "--board-selection": selectionColor(surface, colorScheme) };
|
|
9250
9811
|
const followed = following ? nameOf(following) : null;
|
|
9251
9812
|
const ready = engine !== null;
|
|
9252
|
-
return /* @__PURE__ */
|
|
9253
|
-
/* @__PURE__ */
|
|
9254
|
-
/* @__PURE__ */
|
|
9255
|
-
!ready ? /* @__PURE__ */
|
|
9256
|
-
/* @__PURE__ */
|
|
9813
|
+
return /* @__PURE__ */ jsxs50("div", { ref: root, className: "chalk-board", "data-surface": surface, "data-theme": colorScheme, "data-ready": ready || void 0, "data-compact": compact || void 0, "data-primary": primary || void 0, "data-elements": elementCount, style: surfaceVars, hidden: !visible, children: [
|
|
9814
|
+
/* @__PURE__ */ jsx75(BoardStyles, {}),
|
|
9815
|
+
/* @__PURE__ */ jsx75(WhiteboardCanvas2, { ...board, headless: true, canDraw, collab: board.collab ? { ...board.collab, canDraw, canManage: isHost } : void 0, inkColor: ink, theme: "light", isVisible: visible, className: "chalk-board-engine", onEngineReady: setEngine }),
|
|
9816
|
+
!ready ? /* @__PURE__ */ jsxs50("div", { className: "chalk-board-loading", role: "status", children: [
|
|
9817
|
+
/* @__PURE__ */ jsx75("span", { className: "chalk-board-spinner", "aria-hidden": "true" }),
|
|
9257
9818
|
"Opening board"
|
|
9258
9819
|
] }) : null,
|
|
9259
|
-
primary && ready && empty ? /* @__PURE__ */
|
|
9260
|
-
primary && tool === "note" && canDraw ? /* @__PURE__ */
|
|
9261
|
-
primary ? /* @__PURE__ */
|
|
9262
|
-
primary && ready ? /* @__PURE__ */
|
|
9263
|
-
/* @__PURE__ */
|
|
9264
|
-
followed ? /* @__PURE__ */
|
|
9265
|
-
/* @__PURE__ */
|
|
9820
|
+
primary && ready && empty ? /* @__PURE__ */ jsx75(BoardHint, { canDraw }) : null,
|
|
9821
|
+
primary && tool === "note" && canDraw ? /* @__PURE__ */ jsx75("div", { className: "chalk-board-note-layer", "aria-hidden": "true", onPointerDown: placeNoteAt }) : null,
|
|
9822
|
+
primary ? /* @__PURE__ */ jsx75(BoardCursors, { cursorsRef: cursors, cameraRef: camera.cameraRef, colorFor, hidden: offline }) : null,
|
|
9823
|
+
primary && ready ? /* @__PURE__ */ jsxs50(Fragment34, { children: [
|
|
9824
|
+
/* @__PURE__ */ jsxs50("div", { className: "chalk-board-chips", "data-low": !compact && place === "top" && canDraw || void 0, children: [
|
|
9825
|
+
followed ? /* @__PURE__ */ jsxs50("div", { className: "chalk-board-chip", role: "status", children: [
|
|
9826
|
+
/* @__PURE__ */ jsx75(BoardIcon, { name: "eye", size: 16 }),
|
|
9266
9827
|
"Following ",
|
|
9267
9828
|
followed,
|
|
9268
|
-
/* @__PURE__ */
|
|
9829
|
+
/* @__PURE__ */ jsx75("button", { type: "button", className: "chalk-board-chip-button", onClick: stopFollowing, children: "Stop" })
|
|
9269
9830
|
] }) : null,
|
|
9270
|
-
offline ? /* @__PURE__ */
|
|
9271
|
-
/* @__PURE__ */
|
|
9831
|
+
offline ? /* @__PURE__ */ jsxs50("div", { className: "chalk-board-chip", "data-quiet": true, role: "status", children: [
|
|
9832
|
+
/* @__PURE__ */ jsx75(BoardIcon, { name: "wifiOff", size: 16 }),
|
|
9272
9833
|
"Offline. Your drawing will sync."
|
|
9273
9834
|
] }) : null
|
|
9274
9835
|
] }),
|
|
9275
|
-
!canDraw ? /* @__PURE__ */
|
|
9276
|
-
/* @__PURE__ */
|
|
9836
|
+
!canDraw ? /* @__PURE__ */ jsxs50("div", { className: "chalk-board-view-only", children: [
|
|
9837
|
+
/* @__PURE__ */ jsx75(BoardIcon, { name: "lock", size: 14 }),
|
|
9277
9838
|
"View only"
|
|
9278
9839
|
] }) : null,
|
|
9279
|
-
/* @__PURE__ */
|
|
9840
|
+
/* @__PURE__ */ jsx75("div", { className: "chalk-board-corner", children: /* @__PURE__ */ jsx75(
|
|
9280
9841
|
BoardMenu,
|
|
9281
9842
|
{
|
|
9282
9843
|
surface,
|
|
@@ -9285,22 +9846,23 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9285
9846
|
onPlace: (next) => choosePlace(next, true),
|
|
9286
9847
|
onDownload: () => void download(),
|
|
9287
9848
|
onCopy: () => void copy(),
|
|
9849
|
+
whoCanDraw,
|
|
9288
9850
|
onBring: isHost && sendView ? bring : void 0,
|
|
9289
9851
|
onClear: isHost ? () => void clear() : void 0,
|
|
9290
9852
|
onClose
|
|
9291
9853
|
}
|
|
9292
9854
|
) }),
|
|
9293
|
-
/* @__PURE__ */
|
|
9294
|
-
/* @__PURE__ */
|
|
9295
|
-
/* @__PURE__ */
|
|
9855
|
+
/* @__PURE__ */ jsxs50("div", { className: "chalk-board-zoom", role: "group", "aria-label": "Zoom", children: [
|
|
9856
|
+
/* @__PURE__ */ jsx75("button", { type: "button", "aria-label": "Zoom out", onClick: () => zoomBy(1 / ZOOM_STEP), children: /* @__PURE__ */ jsx75(BoardIcon, { name: "minus", size: 16 }) }),
|
|
9857
|
+
/* @__PURE__ */ jsxs50("button", { type: "button", "aria-label": `Zoom ${Math.round(camera.zoom * 100)}%, reset to 100%`, className: "chalk-board-zoom-value", onClick: () => zoomBy(1 / camera.cameraRef.current.zoom), children: [
|
|
9296
9858
|
Math.round(camera.zoom * 100),
|
|
9297
9859
|
"%"
|
|
9298
9860
|
] }),
|
|
9299
|
-
/* @__PURE__ */
|
|
9300
|
-
/* @__PURE__ */
|
|
9301
|
-
/* @__PURE__ */
|
|
9861
|
+
/* @__PURE__ */ jsx75("button", { type: "button", "aria-label": "Zoom in", onClick: () => zoomBy(ZOOM_STEP), children: /* @__PURE__ */ jsx75(BoardIcon, { name: "plus", size: 16 }) }),
|
|
9862
|
+
/* @__PURE__ */ jsx75("span", { className: "chalk-board-zoom-rule", "aria-hidden": "true" }),
|
|
9863
|
+
/* @__PURE__ */ jsx75("button", { type: "button", "aria-label": "Fit to content", onClick: fit, children: /* @__PURE__ */ jsx75(BoardIcon, { name: "fit", size: 16 }) })
|
|
9302
9864
|
] }),
|
|
9303
|
-
canDraw ? /* @__PURE__ */
|
|
9865
|
+
canDraw ? /* @__PURE__ */ jsx75(
|
|
9304
9866
|
BoardIsland,
|
|
9305
9867
|
{
|
|
9306
9868
|
tool,
|
|
@@ -9321,26 +9883,26 @@ function Board({ board, primary, visible, colorScheme, people, following, onFoll
|
|
|
9321
9883
|
compact
|
|
9322
9884
|
}
|
|
9323
9885
|
) : null,
|
|
9324
|
-
/* @__PURE__ */
|
|
9886
|
+
/* @__PURE__ */ jsx75("div", { className: "chalk-board-announcer", "aria-live": "polite", children: announcement })
|
|
9325
9887
|
] }) : null
|
|
9326
9888
|
] });
|
|
9327
9889
|
}
|
|
9328
9890
|
function BoardHint({ canDraw }) {
|
|
9329
9891
|
if (!canDraw)
|
|
9330
|
-
return /* @__PURE__ */
|
|
9331
|
-
return /* @__PURE__ */
|
|
9332
|
-
/* @__PURE__ */
|
|
9333
|
-
/* @__PURE__ */
|
|
9334
|
-
/* @__PURE__ */
|
|
9335
|
-
/* @__PURE__ */
|
|
9892
|
+
return /* @__PURE__ */ jsx75("div", { className: "chalk-board-hint", children: /* @__PURE__ */ jsx75("p", { children: "Nothing here yet. When someone draws, it shows up here." }) });
|
|
9893
|
+
return /* @__PURE__ */ jsxs50("div", { className: "chalk-board-hint", children: [
|
|
9894
|
+
/* @__PURE__ */ jsx75("p", { children: "An empty board. Draw, type or add a sticky note." }),
|
|
9895
|
+
/* @__PURE__ */ jsxs50("ul", { children: [
|
|
9896
|
+
/* @__PURE__ */ jsxs50("li", { children: [
|
|
9897
|
+
/* @__PURE__ */ jsx75("kbd", { children: "P" }),
|
|
9336
9898
|
" Pen"
|
|
9337
9899
|
] }),
|
|
9338
|
-
/* @__PURE__ */
|
|
9339
|
-
/* @__PURE__ */
|
|
9900
|
+
/* @__PURE__ */ jsxs50("li", { children: [
|
|
9901
|
+
/* @__PURE__ */ jsx75("kbd", { children: "T" }),
|
|
9340
9902
|
" Text"
|
|
9341
9903
|
] }),
|
|
9342
|
-
/* @__PURE__ */
|
|
9343
|
-
/* @__PURE__ */
|
|
9904
|
+
/* @__PURE__ */ jsxs50("li", { children: [
|
|
9905
|
+
/* @__PURE__ */ jsx75("kbd", { children: "N" }),
|
|
9344
9906
|
" Sticky note"
|
|
9345
9907
|
] })
|
|
9346
9908
|
] })
|
|
@@ -9348,12 +9910,12 @@ function BoardHint({ canDraw }) {
|
|
|
9348
9910
|
}
|
|
9349
9911
|
|
|
9350
9912
|
// src/components/stage/SpaceStage.tsx
|
|
9351
|
-
import { jsx as
|
|
9913
|
+
import { jsx as jsx76 } from "react/jsx-runtime";
|
|
9352
9914
|
function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, whiteboard, onOverflowClick, shareCapture, onStopSharing, onChangeShare, colorScheme = "dark", onCloseBoard, className }) {
|
|
9353
|
-
const items =
|
|
9354
|
-
const [selectedShare, setSelectedShare] =
|
|
9355
|
-
const [pin, setPin] =
|
|
9356
|
-
const [following, setFollowing] =
|
|
9915
|
+
const items = useMemo18(() => buildStageItems(tiles, whiteboard?.isOpen === true), [tiles, whiteboard?.isOpen]);
|
|
9916
|
+
const [selectedShare, setSelectedShare] = useState48(null);
|
|
9917
|
+
const [pin, setPin] = useState48(null);
|
|
9918
|
+
const [following, setFollowing] = useState48(null);
|
|
9357
9919
|
const boardOpen = whiteboard?.isOpen === true && Boolean(whiteboard.props);
|
|
9358
9920
|
useEffect38(() => {
|
|
9359
9921
|
if (!boardOpen) setFollowing(null);
|
|
@@ -9367,17 +9929,17 @@ function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, wh
|
|
|
9367
9929
|
if (pin !== activePin) setPin(activePin);
|
|
9368
9930
|
if (selectedShare !== activeShare) setSelectedShare(activeShare);
|
|
9369
9931
|
}, [pin, activePin, selectedShare, activeShare]);
|
|
9370
|
-
const follow =
|
|
9932
|
+
const follow = useCallback15((id) => {
|
|
9371
9933
|
if (id) {
|
|
9372
9934
|
setPin(null);
|
|
9373
9935
|
setSelectedShare(null);
|
|
9374
9936
|
}
|
|
9375
9937
|
setFollowing(id);
|
|
9376
9938
|
}, []);
|
|
9377
|
-
const renderContentTile =
|
|
9939
|
+
const renderContentTile = useCallback15(
|
|
9378
9940
|
(item, context) => {
|
|
9379
9941
|
if (item.kind === "screen-share")
|
|
9380
|
-
return /* @__PURE__ */
|
|
9942
|
+
return /* @__PURE__ */ jsx76(
|
|
9381
9943
|
StageContentTile,
|
|
9382
9944
|
{
|
|
9383
9945
|
item,
|
|
@@ -9385,7 +9947,7 @@ function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, wh
|
|
|
9385
9947
|
capture: item.participant.isLocal ? shareCapture : void 0,
|
|
9386
9948
|
onStopSharing: item.participant.isLocal ? onStopSharing : void 0,
|
|
9387
9949
|
onChangeShare: item.participant.isLocal ? onChangeShare : void 0,
|
|
9388
|
-
switcher: shares.length > 1 ? /* @__PURE__ */
|
|
9950
|
+
switcher: shares.length > 1 ? /* @__PURE__ */ jsx76("div", { role: "group", "aria-label": "Whose screen is big", className: cn("absolute left-2 z-30 flex rounded-[999px] bg-[rgba(12,14,18,.82)] p-[3px]", item.participant.screenShareState === "low-quality" ? "top-11" : "top-2"), children: shares.map((share) => /* @__PURE__ */ jsx76(
|
|
9389
9951
|
"button",
|
|
9390
9952
|
{
|
|
9391
9953
|
type: "button",
|
|
@@ -9402,25 +9964,25 @@ function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, wh
|
|
|
9402
9964
|
}
|
|
9403
9965
|
);
|
|
9404
9966
|
const boardProps = whiteboard?.props;
|
|
9405
|
-
return /* @__PURE__ */
|
|
9967
|
+
return /* @__PURE__ */ jsx76(
|
|
9406
9968
|
StageContentTileSurface,
|
|
9407
9969
|
{
|
|
9408
9970
|
item,
|
|
9409
9971
|
...context,
|
|
9410
9972
|
mediaVisible: Boolean(boardProps),
|
|
9411
|
-
media: boardProps ? /* @__PURE__ */
|
|
9973
|
+
media: boardProps ? /* @__PURE__ */ jsx76("div", { className: cn("h-full", !context.primary && "pointer-events-none"), inert: !context.primary || void 0, children: /* @__PURE__ */ jsx76(Board, { board: boardProps, primary: context.primary, visible: context.active, colorScheme, people: tiles, following: followed, onFollow: follow, sendView: canFollow ? whiteboard?.sendView : void 0, onClose: onCloseBoard }) }) : null
|
|
9412
9974
|
}
|
|
9413
9975
|
);
|
|
9414
9976
|
},
|
|
9415
9977
|
[follow, whiteboard, shares, shareCapture, onStopSharing, onChangeShare, colorScheme, tiles, followed, canFollow, onCloseBoard]
|
|
9416
9978
|
);
|
|
9417
|
-
const focusContent =
|
|
9979
|
+
const focusContent = useCallback15(
|
|
9418
9980
|
(item) => {
|
|
9419
9981
|
if (item.kind !== "participant") onLayoutChange?.("focus");
|
|
9420
9982
|
},
|
|
9421
9983
|
[onLayoutChange]
|
|
9422
9984
|
);
|
|
9423
|
-
return /* @__PURE__ */
|
|
9985
|
+
return /* @__PURE__ */ jsx76(
|
|
9424
9986
|
Stage,
|
|
9425
9987
|
{
|
|
9426
9988
|
items,
|
|
@@ -9434,7 +9996,7 @@ function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, wh
|
|
|
9434
9996
|
onItemClick: focusContent,
|
|
9435
9997
|
onOverflowClick: canFollow ? void 0 : onOverflowClick,
|
|
9436
9998
|
generatedAvatars,
|
|
9437
|
-
emptyState: /* @__PURE__ */
|
|
9999
|
+
emptyState: /* @__PURE__ */ jsx76(QuietSpace, {}),
|
|
9438
10000
|
className
|
|
9439
10001
|
}
|
|
9440
10002
|
);
|
|
@@ -9442,11 +10004,11 @@ function SpaceStage({ tiles, layout, onLayoutChange, generatedAvatars = true, wh
|
|
|
9442
10004
|
SpaceStage.displayName = "SpaceStage";
|
|
9443
10005
|
|
|
9444
10006
|
// src/components/space-view/useDrawerPresence.ts
|
|
9445
|
-
import { useEffect as useEffect39, useState as
|
|
10007
|
+
import { useEffect as useEffect39, useState as useState49 } from "react";
|
|
9446
10008
|
var DRAWER_EXIT_MS = 200;
|
|
9447
10009
|
function useDrawerPresence(panel, exitMs) {
|
|
9448
|
-
const [retained, setRetained] =
|
|
9449
|
-
const [state, setState] =
|
|
10010
|
+
const [retained, setRetained] = useState49(panel);
|
|
10011
|
+
const [state, setState] = useState49(panel === null ? "closed" : "open");
|
|
9450
10012
|
useEffect39(() => {
|
|
9451
10013
|
if (panel !== null) {
|
|
9452
10014
|
setRetained(panel);
|
|
@@ -9464,7 +10026,7 @@ function useDrawerPresence(panel, exitMs) {
|
|
|
9464
10026
|
}
|
|
9465
10027
|
|
|
9466
10028
|
// src/components/space-view/SpaceView.tsx
|
|
9467
|
-
import { Fragment as
|
|
10029
|
+
import { Fragment as Fragment35, jsx as jsx77, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
9468
10030
|
function SpaceView({
|
|
9469
10031
|
colorScheme = "dark",
|
|
9470
10032
|
onColorSchemeChange,
|
|
@@ -9473,6 +10035,8 @@ function SpaceView({
|
|
|
9473
10035
|
callLinkOpen,
|
|
9474
10036
|
onCallLinkToggle,
|
|
9475
10037
|
onReportProblem,
|
|
10038
|
+
reportUnavailableReason,
|
|
10039
|
+
onOpenReportProblem,
|
|
9476
10040
|
inviteLink,
|
|
9477
10041
|
pickChatFiles,
|
|
9478
10042
|
stageBackground = true,
|
|
@@ -9482,6 +10046,8 @@ function SpaceView({
|
|
|
9482
10046
|
features,
|
|
9483
10047
|
generatedAvatars = true,
|
|
9484
10048
|
commandError: externalCommandError,
|
|
10049
|
+
commandSource: externalCommandSource,
|
|
10050
|
+
commandAction: externalCommandAction,
|
|
9485
10051
|
onDismissCommandError,
|
|
9486
10052
|
onToggleWhiteboard,
|
|
9487
10053
|
whiteboard,
|
|
@@ -9500,29 +10066,36 @@ function SpaceView({
|
|
|
9500
10066
|
const callLink = useCallLink(participantsSlice.roster.length <= 1);
|
|
9501
10067
|
const media = useMedia();
|
|
9502
10068
|
const connection = useConnection();
|
|
10069
|
+
const offline = useOffline();
|
|
10070
|
+
const [dismissedOfflineNotice, setDismissedOfflineNotice] = useState50(null);
|
|
10071
|
+
const offlineNotice = offline.notice && offline.notice !== dismissedOfflineNotice ? offline.notice : null;
|
|
9503
10072
|
const recording = useRecording();
|
|
9504
10073
|
const canPublishScreen = useCan("publishScreen");
|
|
9505
10074
|
const canSendReaction = useCan("sendReaction");
|
|
9506
10075
|
const canRaiseHand = useCan("raiseHand");
|
|
9507
|
-
const canDrawWhiteboard =
|
|
10076
|
+
const canDrawWhiteboard = useCanDrawWhiteboard();
|
|
9508
10077
|
const canManageAdmission = useCan("manageAdmission");
|
|
9509
10078
|
const canManageRecording = useCan("manageRecording");
|
|
9510
10079
|
const episodeDuration = useEpisodeDuration();
|
|
9511
|
-
const [uncontrolledLayout, setUncontrolledLayout] =
|
|
9512
|
-
const [activePanel, setActivePanel] =
|
|
9513
|
-
const [isReactionPickerOpen, setReactionPickerOpen] =
|
|
9514
|
-
const [commandError, setCommandError] =
|
|
9515
|
-
const [commandSource, setCommandSource] =
|
|
9516
|
-
const
|
|
10080
|
+
const [uncontrolledLayout, setUncontrolledLayout] = useState50(controlledLayout ?? "focus");
|
|
10081
|
+
const [activePanel, setActivePanel] = useState50(initialPanel);
|
|
10082
|
+
const [isReactionPickerOpen, setReactionPickerOpen] = useState50(false);
|
|
10083
|
+
const [commandError, setCommandError] = useState50(null);
|
|
10084
|
+
const [commandSource, setCommandSource] = useState50();
|
|
10085
|
+
const [commandAction, setCommandAction] = useState50();
|
|
10086
|
+
const [retryCommand, setRetryCommand] = useState50();
|
|
10087
|
+
const onCommandError = (failure, source, mediaSource, action, command) => {
|
|
9517
10088
|
if (!failure && commandError && typeof commandError === "object") callToasts.dismissFailure(commandError.code);
|
|
9518
10089
|
setCommandError(failure);
|
|
9519
|
-
setCommandSource(source);
|
|
10090
|
+
setCommandSource(mediaSource ?? source);
|
|
10091
|
+
setCommandAction(action);
|
|
10092
|
+
setRetryCommand(() => command);
|
|
9520
10093
|
if (failure && typeof failure !== "string") playSound("error", failure);
|
|
9521
10094
|
};
|
|
9522
10095
|
const layout = onLayoutChange ? controlledLayout ?? uncontrolledLayout : uncontrolledLayout;
|
|
9523
10096
|
const feature = (name) => features?.[name] !== false;
|
|
9524
10097
|
const localId = self.participantId ?? "local";
|
|
9525
|
-
const tiles =
|
|
10098
|
+
const tiles = useMemo19(
|
|
9526
10099
|
() => toVideoParticipants(participantsSlice.roster, media.remote, localId, self.displayName ?? "You", media.local).map((tile) => ({
|
|
9527
10100
|
...tile,
|
|
9528
10101
|
screenShareHasAudio: tile.isLocal ? media.screenShare.hasAudio : participantsSlice.roster.find((person) => person.participantId === tile.id)?.media.screenShareHasAudio
|
|
@@ -9552,37 +10125,41 @@ function SpaceView({
|
|
|
9552
10125
|
const playSound = useSoundCues(feature("sounds") && soundsEnabled);
|
|
9553
10126
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
9554
10127
|
const drawer = useDrawerPresence(activePanel, prefersReducedMotion ? 0 : DRAWER_EXIT_MS);
|
|
9555
|
-
const runCommand =
|
|
10128
|
+
const runCommand = useCallback16(async (command, source, action) => {
|
|
9556
10129
|
try {
|
|
9557
10130
|
await command();
|
|
9558
10131
|
setCommandError(null);
|
|
10132
|
+
setCommandSource(void 0);
|
|
10133
|
+
setCommandAction(void 0);
|
|
10134
|
+
setRetryCommand(void 0);
|
|
9559
10135
|
} catch (cause) {
|
|
9560
10136
|
setCommandError(commandFailure(cause));
|
|
10137
|
+
setCommandSource(source);
|
|
10138
|
+
setCommandAction(action);
|
|
10139
|
+
setRetryCommand(() => command);
|
|
9561
10140
|
}
|
|
9562
10141
|
}, []);
|
|
9563
10142
|
const leaveCall = onLeft ? () => void runCommand(async () => onLeft()) : void 0;
|
|
9564
10143
|
const endCallForEveryone = onEndEpisode ? () => void runCommand(async () => onEndEpisode()) : void 0;
|
|
9565
10144
|
const displayedCommandError = externalCommandError ?? commandError;
|
|
9566
|
-
const
|
|
10145
|
+
const displayedCommandSource = externalCommandError != null ? externalCommandSource : commandSource;
|
|
9567
10146
|
const retryMedia = async () => {
|
|
10147
|
+
if (!retryCommand) return;
|
|
9568
10148
|
try {
|
|
9569
|
-
|
|
9570
|
-
else if (commandSource === "camera") await client.media.setCameraEnabled(true);
|
|
9571
|
-
else if (commandSource === "microphone") await client.media.setMicrophoneEnabled(true);
|
|
10149
|
+
await retryCommand();
|
|
9572
10150
|
onCommandError(null);
|
|
9573
10151
|
} catch (cause) {
|
|
9574
|
-
|
|
9575
|
-
onCommandError(cause instanceof SpaceClientError2 ? cause : { code: "client.internal_error", recoverable: true, message: "Your device couldn\u2019t start. Try again." }, commandSource);
|
|
10152
|
+
onCommandError(commandFailure(cause), commandSource, commandSource, commandAction, retryCommand);
|
|
9576
10153
|
}
|
|
9577
10154
|
};
|
|
9578
|
-
const
|
|
9579
|
-
const commandToasts = mappedFailure ? [{ id: "space-command-error", ...mappedFailure
|
|
9580
|
-
const [boardToasts, setBoardToasts] =
|
|
10155
|
+
const mappedFailure = mediaFailureToast(typeof displayedCommandError === "object" ? displayedCommandError : null, displayedCommandSource, externalCommandError != null ? externalCommandAction : commandAction, externalCommandError == null && retryCommand ? () => void retryMedia() : void 0);
|
|
10156
|
+
const commandToasts = mappedFailure ? [{ id: "space-command-error", ...mappedFailure }] : typeof displayedCommandError === "string" ? [{ id: "space-command-error", message: displayedCommandError, type: "error" }] : [];
|
|
10157
|
+
const [boardToasts, setBoardToasts] = useState50([]);
|
|
9581
10158
|
const boardToastCount = useRef34(0);
|
|
9582
10159
|
useEffect40(() => {
|
|
9583
10160
|
if (!whiteboard?.isOpen) setBoardToasts([]);
|
|
9584
10161
|
}, [whiteboard?.isOpen]);
|
|
9585
|
-
const showBoardToast =
|
|
10162
|
+
const showBoardToast = useCallback16((toast) => {
|
|
9586
10163
|
if (!toast) {
|
|
9587
10164
|
setBoardToasts([]);
|
|
9588
10165
|
return;
|
|
@@ -9596,7 +10173,21 @@ function SpaceView({
|
|
|
9596
10173
|
setCommandError(null);
|
|
9597
10174
|
onDismissCommandError?.();
|
|
9598
10175
|
};
|
|
9599
|
-
|
|
10176
|
+
const toasts = [
|
|
10177
|
+
...callToasts.toasts.filter((toast) => !(typeof displayedCommandError === "object" && displayedCommandError && toast.failureCode === displayedCommandError.code)),
|
|
10178
|
+
...whiteboard?.isOpen ? boardToasts : [],
|
|
10179
|
+
...commandToasts,
|
|
10180
|
+
...offlineNotice ? [{ id: "offline-notice", message: offlineNotice }] : []
|
|
10181
|
+
];
|
|
10182
|
+
const dismissToast = (id) => {
|
|
10183
|
+
if (id === "space-command-error") dismissCommandError();
|
|
10184
|
+
else if (id === "offline-notice") setDismissedOfflineNotice(offline.notice ?? null);
|
|
10185
|
+
else if (id.startsWith("board-")) setBoardToasts((current) => current.filter((toast) => toast.id !== id));
|
|
10186
|
+
else callToasts.dismiss(id);
|
|
10187
|
+
};
|
|
10188
|
+
const [foldedNotices, setFoldedNotices] = useState50([]);
|
|
10189
|
+
const folded = toasts.filter((toast) => foldedNotices.includes(toast.id));
|
|
10190
|
+
return /* @__PURE__ */ jsx77(ParticipantVolumeProvider, { children: /* @__PURE__ */ jsx77(BoardToastContext.Provider, { value: showBoardToast, children: /* @__PURE__ */ jsx77(
|
|
9600
10191
|
SpacePresentation,
|
|
9601
10192
|
{
|
|
9602
10193
|
colorScheme,
|
|
@@ -9612,11 +10203,13 @@ function SpaceView({
|
|
|
9612
10203
|
callLinkOpen: callLinkOpen ?? callLink.open,
|
|
9613
10204
|
onCallLinkToggle: onCallLinkToggle ?? callLink.toggle,
|
|
9614
10205
|
onReportProblem,
|
|
10206
|
+
onOpenReportProblem,
|
|
10207
|
+
reportUnavailableReason,
|
|
9615
10208
|
diagnostics: callDiagnostics(connection, media),
|
|
9616
10209
|
shortcuts: {
|
|
9617
10210
|
isMuted: media.local.microphone.state !== "enabled",
|
|
9618
|
-
onToggleMute: connection.status === "live" || media.local.microphone.state === "enabled" ? () => void runCommand(() => client.media.setMicrophoneEnabled(media.local.microphone.state !== "enabled")) : void 0,
|
|
9619
|
-
onToggleVideo: connection.status === "live" || media.local.camera.state === "enabled" ? () => void runCommand(() => client.media.setCameraEnabled(media.local.camera.state !== "enabled")) : void 0,
|
|
10211
|
+
onToggleMute: connection.status === "live" || media.local.microphone.state === "enabled" ? () => void runCommand(() => client.media.setMicrophoneEnabled(media.local.microphone.state !== "enabled"), "microphone", media.local.microphone.state === "enabled" ? "stop" : "start") : void 0,
|
|
10212
|
+
onToggleVideo: connection.status === "live" || media.local.camera.state === "enabled" ? () => void runCommand(() => client.media.setCameraEnabled(media.local.camera.state !== "enabled"), "camera", media.local.camera.state === "enabled" ? "stop" : "start") : void 0,
|
|
9620
10213
|
onToggleHand: feature("handRaise") && canRaiseHand ? () => void runCommand(() => self.handRaised ? client.participants.lowerHand() : client.participants.raiseHand()) : void 0,
|
|
9621
10214
|
onToggleChat: feature("chat") ? () => setActivePanel((current) => current === "chat" ? null : "chat") : void 0,
|
|
9622
10215
|
onTogglePeople: feature("participants") ? () => setActivePanel((current) => current === "participants" ? null : "participants") : void 0,
|
|
@@ -9624,15 +10217,16 @@ function SpaceView({
|
|
|
9624
10217
|
onClosePanel: () => setActivePanel(null),
|
|
9625
10218
|
onPushToTalk: (enabled) => {
|
|
9626
10219
|
if (enabled && connection.status !== "live") return;
|
|
9627
|
-
void runCommand(() => client.media.setMicrophoneEnabled(enabled));
|
|
10220
|
+
void runCommand(() => client.media.setMicrophoneEnabled(enabled), "microphone", enabled ? "start" : "stop");
|
|
9628
10221
|
}
|
|
9629
10222
|
},
|
|
9630
10223
|
duration: episodeDuration,
|
|
9631
10224
|
isRecording: recording.current?.status === "recording",
|
|
9632
10225
|
layout,
|
|
9633
|
-
onLayoutChange: updateLayout
|
|
10226
|
+
onLayoutChange: updateLayout,
|
|
10227
|
+
notices: folded.length ? /* @__PURE__ */ jsx77(NoticeButton, { toasts: folded, onDismiss: dismissToast }) : void 0
|
|
9634
10228
|
},
|
|
9635
|
-
stage: /* @__PURE__ */
|
|
10229
|
+
stage: /* @__PURE__ */ jsx77(
|
|
9636
10230
|
SpaceStage,
|
|
9637
10231
|
{
|
|
9638
10232
|
tiles,
|
|
@@ -9653,7 +10247,7 @@ function SpaceView({
|
|
|
9653
10247
|
className: "h-full"
|
|
9654
10248
|
}
|
|
9655
10249
|
),
|
|
9656
|
-
controls: /* @__PURE__ */
|
|
10250
|
+
controls: /* @__PURE__ */ jsx77(
|
|
9657
10251
|
ControlBar,
|
|
9658
10252
|
{
|
|
9659
10253
|
density: "comfortable",
|
|
@@ -9673,9 +10267,9 @@ function SpaceView({
|
|
|
9673
10267
|
onEndForEveryone: endCallForEveryone
|
|
9674
10268
|
}
|
|
9675
10269
|
),
|
|
9676
|
-
stageOverlay: /* @__PURE__ */
|
|
9677
|
-
feature("reactions") ? /* @__PURE__ */
|
|
9678
|
-
feature("reactions") && canSendReaction && connection.status === "live" ? /* @__PURE__ */
|
|
10270
|
+
stageOverlay: /* @__PURE__ */ jsxs51(Fragment35, { children: [
|
|
10271
|
+
feature("reactions") ? /* @__PURE__ */ jsx77(ReactionsOverlay, {}) : null,
|
|
10272
|
+
feature("reactions") && canSendReaction && connection.status === "live" ? /* @__PURE__ */ jsx77("div", { className: "absolute bottom-24 left-1/2 z-50 -translate-x-1/2", children: /* @__PURE__ */ jsx77(
|
|
9679
10273
|
ReactionPicker,
|
|
9680
10274
|
{
|
|
9681
10275
|
isHandRaised: self.handRaised,
|
|
@@ -9688,28 +10282,18 @@ function SpaceView({
|
|
|
9688
10282
|
}
|
|
9689
10283
|
) }) : null
|
|
9690
10284
|
] }),
|
|
9691
|
-
sidebar: /* @__PURE__ */
|
|
9692
|
-
drawer.panel === "chat" && feature("chat") ? /* @__PURE__ */
|
|
9693
|
-
drawer.panel === "participants" && feature("participants") ? /* @__PURE__ */
|
|
9694
|
-
drawer.panel === "admission" && feature("admission") ? /* @__PURE__ */
|
|
10285
|
+
sidebar: /* @__PURE__ */ jsxs51(CallCard, { state: drawer.state, panel: drawer.panel, onPanelChange: setActivePanel, peopleCount: participantsSlice.roster.length, participantsEnabled: feature("participants"), chatEnabled: feature("chat"), onClose: () => setActivePanel(null), children: [
|
|
10286
|
+
drawer.panel === "chat" && feature("chat") ? /* @__PURE__ */ jsx77(ChatPanel, { variant: "mobile", generatedAvatars, onClose: () => setActivePanel(null), pickChatFiles }) : null,
|
|
10287
|
+
drawer.panel === "participants" && feature("participants") ? /* @__PURE__ */ jsx77(ParticipantsPanel, { variant: "mobile", admissionEnabled: feature("admission"), generatedAvatars, onCommandError, onClose: () => setActivePanel(null) }) : null,
|
|
10288
|
+
drawer.panel === "admission" && feature("admission") ? /* @__PURE__ */ jsx77(AdmissionPanel, { className: "h-full w-full rounded-none shadow-none", onClose: () => setActivePanel(null) }) : null
|
|
9695
10289
|
] }),
|
|
9696
|
-
toasts: /* @__PURE__ */
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
onDismiss: (id) => {
|
|
9701
|
-
if (id === "space-command-error") dismissCommandError();
|
|
9702
|
-
else if (id.startsWith("board-")) setBoardToasts((current) => current.filter((toast) => toast.id !== id));
|
|
9703
|
-
else callToasts.dismiss(id);
|
|
9704
|
-
}
|
|
9705
|
-
}
|
|
9706
|
-
),
|
|
9707
|
-
mediaOutput: /* @__PURE__ */ jsx76("div", { className: "[&>div]:top-[68px] [&>div>button]:h-11 [&>div>button]:shadow-[0_8px_24px_rgba(0,0,0,.4)]", children: /* @__PURE__ */ jsx76(AudioOutput, { resumeAudioLabel: "Your browser paused the sound. Click to hear the call" }) }),
|
|
9708
|
-
overlays: /* @__PURE__ */ jsxs49(Fragment32, { children: [
|
|
9709
|
-
/* @__PURE__ */ jsx76(CallReady, { open: callLinkOpen ?? callLink.open, onClose: onCallLinkToggle ?? callLink.close, link: effectiveShareUrl }),
|
|
10290
|
+
toasts: /* @__PURE__ */ jsx77(ToastStack, { toasts, onDismiss: dismissToast, onFold: setFoldedNotices }),
|
|
10291
|
+
mediaOutput: /* @__PURE__ */ jsx77("div", { className: "[&>div]:top-[68px] [&>div>button]:h-11 [&>div>button]:shadow-[0_8px_24px_rgba(0,0,0,.4)]", children: /* @__PURE__ */ jsx77(AudioOutput, { resumeAudioLabel: "Your browser paused the sound. Click to hear the call" }) }),
|
|
10292
|
+
overlays: /* @__PURE__ */ jsxs51(Fragment35, { children: [
|
|
10293
|
+
/* @__PURE__ */ jsx77(CallReady, { open: callLinkOpen ?? callLink.open, onClose: onCallLinkToggle ?? callLink.close, link: effectiveShareUrl }),
|
|
9710
10294
|
overlay,
|
|
9711
|
-
reconnecting && reconnecting.status !== "reconnecting" ? /* @__PURE__ */
|
|
9712
|
-
/* @__PURE__ */
|
|
10295
|
+
reconnecting && reconnecting.status !== "reconnecting" ? /* @__PURE__ */ jsx77(ReconnectingOverlay, { ...reconnecting }) : null,
|
|
10296
|
+
/* @__PURE__ */ jsx77(OfflineActions, { reconnecting: reconnecting?.status === "reconnecting" && reconnecting.isVisible, hasNotice: offlineNotice !== null })
|
|
9713
10297
|
] }),
|
|
9714
10298
|
className
|
|
9715
10299
|
}
|
|
@@ -9729,7 +10313,9 @@ export {
|
|
|
9729
10313
|
useRecording,
|
|
9730
10314
|
useWhiteboard,
|
|
9731
10315
|
useCan,
|
|
10316
|
+
useCanDrawWhiteboard,
|
|
9732
10317
|
useScreenShare,
|
|
10318
|
+
commandFailure,
|
|
9733
10319
|
chalkThemeStyle,
|
|
9734
10320
|
ChalkButton,
|
|
9735
10321
|
ChalkIconButton,
|
|
@@ -9766,9 +10352,9 @@ export {
|
|
|
9766
10352
|
ControlBarPresentation,
|
|
9767
10353
|
ControlBar,
|
|
9768
10354
|
ParticipantsPanel,
|
|
9769
|
-
ToastStack,
|
|
9770
10355
|
StatusSurface,
|
|
9771
10356
|
CallReady,
|
|
10357
|
+
ToastStack,
|
|
9772
10358
|
CallCard,
|
|
9773
10359
|
captureFlip,
|
|
9774
10360
|
CallDialog,
|