@arbidocs/blocks 0.4.129 → 0.4.131

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.
Files changed (121) hide show
  1. package/dist/agents/index.cjs +303 -303
  2. package/dist/agents/index.js +11 -11
  3. package/dist/calendar/CalendarPrint.d.ts +25 -0
  4. package/dist/calendar/booking-slots.d.ts +21 -0
  5. package/dist/calendar/index.cjs +381 -97
  6. package/dist/calendar/index.cjs.map +1 -1
  7. package/dist/calendar/index.d.ts +4 -0
  8. package/dist/calendar/index.js +277 -3
  9. package/dist/calendar/index.js.map +1 -1
  10. package/dist/calendar/print-layout.d.ts +16 -0
  11. package/dist/calendar/printCalendar.d.ts +6 -0
  12. package/dist/calls/composite-canvas.d.ts +52 -0
  13. package/dist/calls/index.cjs +374 -1
  14. package/dist/calls/index.cjs.map +1 -1
  15. package/dist/calls/index.d.ts +3 -0
  16. package/dist/calls/index.js +359 -4
  17. package/dist/calls/index.js.map +1 -1
  18. package/dist/calls/ringtone.d.ts +16 -0
  19. package/dist/calls/voice-levels.d.ts +32 -0
  20. package/dist/chat/ThreadVisualizer.d.ts +28 -0
  21. package/dist/chat/index.cjs +151 -135
  22. package/dist/chat/index.d.ts +2 -0
  23. package/dist/chat/index.js +4 -4
  24. package/dist/chat/thread-diagram.d.ts +26 -0
  25. package/dist/{chunk-H2KQ6OSU.js → chunk-26E6PHD2.js} +231 -6
  26. package/dist/chunk-26E6PHD2.js.map +1 -0
  27. package/dist/{chunk-2PNNCEPH.js → chunk-54ANPPMV.js} +4 -4
  28. package/dist/{chunk-2PNNCEPH.js.map → chunk-54ANPPMV.js.map} +1 -1
  29. package/dist/{chunk-IBZJYCYM.js → chunk-66TA5IBN.js} +17 -25
  30. package/dist/chunk-66TA5IBN.js.map +1 -0
  31. package/dist/{chunk-OYMWV45N.js → chunk-7D4W3SAH.js} +51 -4
  32. package/dist/chunk-7D4W3SAH.js.map +1 -0
  33. package/dist/{chunk-2DFDFOM7.js → chunk-7HAM7Y5U.js} +3 -3
  34. package/dist/{chunk-2DFDFOM7.js.map → chunk-7HAM7Y5U.js.map} +1 -1
  35. package/dist/{chunk-7423V6RM.cjs → chunk-7KH4M3KY.cjs} +8 -8
  36. package/dist/{chunk-7423V6RM.cjs.map → chunk-7KH4M3KY.cjs.map} +1 -1
  37. package/dist/{chunk-TGWTLNXW.cjs → chunk-BIXHB4LV.cjs} +3 -2
  38. package/dist/{chunk-TGWTLNXW.cjs.map → chunk-BIXHB4LV.cjs.map} +1 -1
  39. package/dist/{chunk-DZYAAL4H.cjs → chunk-BZF55UCE.cjs} +234 -5
  40. package/dist/chunk-BZF55UCE.cjs.map +1 -0
  41. package/dist/{chunk-3BJLNKOB.cjs → chunk-CDZVC32G.cjs} +5 -5
  42. package/dist/{chunk-3BJLNKOB.cjs.map → chunk-CDZVC32G.cjs.map} +1 -1
  43. package/dist/{chunk-PUCY3UXN.js → chunk-CXLVI3SB.js} +3 -3
  44. package/dist/{chunk-PUCY3UXN.js.map → chunk-CXLVI3SB.js.map} +1 -1
  45. package/dist/{chunk-KYDRUFWT.cjs → chunk-D4YR56FV.cjs} +5 -5
  46. package/dist/{chunk-KYDRUFWT.cjs.map → chunk-D4YR56FV.cjs.map} +1 -1
  47. package/dist/{chunk-6BTCDKCK.js → chunk-DI35D756.js} +4 -4
  48. package/dist/{chunk-6BTCDKCK.js.map → chunk-DI35D756.js.map} +1 -1
  49. package/dist/{chunk-TGJNPKST.js → chunk-GTCC2VAR.js} +3 -3
  50. package/dist/{chunk-TGJNPKST.js.map → chunk-GTCC2VAR.js.map} +1 -1
  51. package/dist/{chunk-6AALMYPS.cjs → chunk-HM23LXUP.cjs} +3 -3
  52. package/dist/{chunk-6AALMYPS.cjs.map → chunk-HM23LXUP.cjs.map} +1 -1
  53. package/dist/{chunk-HSFLEVZY.js → chunk-KLOSOT26.js} +10 -10
  54. package/dist/{chunk-HSFLEVZY.js.map → chunk-KLOSOT26.js.map} +1 -1
  55. package/dist/{chunk-SARREDFP.cjs → chunk-LC2KJSUS.cjs} +46 -46
  56. package/dist/{chunk-SARREDFP.cjs.map → chunk-LC2KJSUS.cjs.map} +1 -1
  57. package/dist/{chunk-MUMH3Z6K.cjs → chunk-LRD7BHAT.cjs} +50 -3
  58. package/dist/chunk-LRD7BHAT.cjs.map +1 -0
  59. package/dist/{chunk-CJBN5HIS.js → chunk-P5HOXWYL.js} +3 -3
  60. package/dist/{chunk-CJBN5HIS.js.map → chunk-P5HOXWYL.js.map} +1 -1
  61. package/dist/{chunk-5Y7JRY7Y.js → chunk-P5ST47VY.js} +3 -3
  62. package/dist/{chunk-5Y7JRY7Y.js.map → chunk-P5ST47VY.js.map} +1 -1
  63. package/dist/{chunk-A7NCSZAP.cjs → chunk-QZTNTP75.cjs} +17 -25
  64. package/dist/chunk-QZTNTP75.cjs.map +1 -0
  65. package/dist/{chunk-ENDP7JER.js → chunk-VW2C2AZL.js} +3 -3
  66. package/dist/{chunk-ENDP7JER.js.map → chunk-VW2C2AZL.js.map} +1 -1
  67. package/dist/{chunk-JLTXVW25.cjs → chunk-W27VK32R.cjs} +78 -78
  68. package/dist/{chunk-JLTXVW25.cjs.map → chunk-W27VK32R.cjs.map} +1 -1
  69. package/dist/{chunk-PJJY6CYL.cjs → chunk-WV4IDVDQ.cjs} +11 -11
  70. package/dist/{chunk-PJJY6CYL.cjs.map → chunk-WV4IDVDQ.cjs.map} +1 -1
  71. package/dist/{chunk-NYHGG2IA.cjs → chunk-ZV3BKLFY.cjs} +3 -3
  72. package/dist/{chunk-NYHGG2IA.cjs.map → chunk-ZV3BKLFY.cjs.map} +1 -1
  73. package/dist/collaboration/index.cjs +9 -9
  74. package/dist/collaboration/index.js +1 -1
  75. package/dist/connect/docx.cjs +4 -4
  76. package/dist/connect/docx.js +3 -3
  77. package/dist/connect/index.cjs +183 -146
  78. package/dist/connect/index.cjs.map +1 -1
  79. package/dist/connect/index.d.ts +1 -1
  80. package/dist/connect/index.js +134 -98
  81. package/dist/connect/index.js.map +1 -1
  82. package/dist/connection/ConnectedSettings.d.ts +42 -7
  83. package/dist/document-tools/index.cjs +1 -1
  84. package/dist/document-tools/index.js +1 -1
  85. package/dist/facts/fact-citations.d.ts +56 -0
  86. package/dist/facts/fact-table-column-resize.d.ts +18 -0
  87. package/dist/facts/index.cjs +194 -8
  88. package/dist/facts/index.cjs.map +1 -1
  89. package/dist/facts/index.d.ts +2 -0
  90. package/dist/facts/index.js +180 -5
  91. package/dist/facts/index.js.map +1 -1
  92. package/dist/files/index.cjs +1 -1
  93. package/dist/files/index.js +1 -1
  94. package/dist/home/index.cjs +17 -17
  95. package/dist/home/index.js +3 -3
  96. package/dist/index.cjs +517 -501
  97. package/dist/index.js +18 -18
  98. package/dist/settings/MoreInfo.d.ts +25 -0
  99. package/dist/settings/PlanCard.d.ts +1 -1
  100. package/dist/settings/index.cjs +79 -225
  101. package/dist/settings/index.cjs.map +1 -1
  102. package/dist/settings/index.d.ts +1 -1
  103. package/dist/settings/index.js +70 -215
  104. package/dist/settings/index.js.map +1 -1
  105. package/dist/shell/index.cjs +1 -1
  106. package/dist/shell/index.js +1 -1
  107. package/dist/site/index.cjs +5 -5
  108. package/dist/site/index.js +1 -1
  109. package/dist/studio/index.cjs +8 -8
  110. package/dist/studio/index.js +6 -6
  111. package/dist/workflow-canvas/index.cjs +64 -64
  112. package/dist/workflow-canvas/index.js +12 -12
  113. package/node_modules/@arbidocs/coedit/package.json +1 -1
  114. package/package.json +9 -4
  115. package/dist/chunk-A7NCSZAP.cjs.map +0 -1
  116. package/dist/chunk-DZYAAL4H.cjs.map +0 -1
  117. package/dist/chunk-H2KQ6OSU.js.map +0 -1
  118. package/dist/chunk-IBZJYCYM.js.map +0 -1
  119. package/dist/chunk-MUMH3Z6K.cjs.map +0 -1
  120. package/dist/chunk-OYMWV45N.js.map +0 -1
  121. package/dist/settings/FirmPool.d.ts +0 -82
@@ -19,3 +19,6 @@ export { MinimisedCall, IncomingCallCard, CallStateMessage, ConnectionOverlay }
19
19
  export { PreJoin, type PreJoinProps } from './PreJoin';
20
20
  export { DEFAULT_JOIN_CHOICES, describeMediaError, type JoinChoices, type MediaKind, } from './join-choices';
21
21
  export * from './webinar';
22
+ export { LEVEL_TICK_MS, useVoiceLevel, useVoiceLevels, useIsSpeaking, useSpeakingIds, useSpotlightId, startVoiceLevels, type VoiceSource, } from './voice-levels';
23
+ export { RINGTONE_MUTED_KEY, startRingtone, useRingtone, useRingtoneMuted } from './ringtone';
24
+ export { COMPOSITE_FPS, COMPOSITE_MAX_WIDTH, COMPOSITE_MAX_HEIGHT, fitStage, fitMedia, drawStageFrame, startCompositeCapture, type CompositeCapture, } from './composite-canvas';
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import { ConfirmDialog } from '../chunk-ECERC6TI.js';
3
- import '../chunk-TX2ZICS7.js';
4
3
  import { TabHeader } from '../chunk-4WWM3GQ5.js';
5
- import { NOTICE_MS, gridSlots, gridLayout, spotlightBox, CAPTION_TTL_MS, CAPTION_LINES, speakerAccent, formatElapsed, initialsOf } from '../chunk-Z3AZ7Q5X.js';
4
+ import '../chunk-TX2ZICS7.js';
5
+ import { NOTICE_MS, gridSlots, gridLayout, spotlightBox, CAPTION_TTL_MS, CAPTION_LINES, speakerAccent, formatElapsed, initialsOf, SPEAKING_LEVEL, nextSpotlight, INITIAL_SPOTLIGHT } from '../chunk-Z3AZ7Q5X.js';
6
6
  export { CAPTION_LINES, CAPTION_TTL_MS, INITIAL_SPOTLIGHT, MAX_GRID_TILES, NOTICE_MS, SPEAKER_ACCENTS, SPEAKING_LEVEL, TILE_ASPECT, formatElapsed, gridLayout, gridSlots, initialsOf, nearestCorner, nextSpotlight, pickSpotlight, rowCounts, speakerAccent, speakerBorder, spotlightBox, stageContentHeight } from '../chunk-Z3AZ7Q5X.js';
7
7
  import '../chunk-NPLYHR2E.js';
8
8
  import '../chunk-7F6CBP3Z.js';
9
9
  import { fromNow } from '../chunk-OXF2IFXG.js';
10
10
  import '../chunk-VUNV25KB.js';
11
- import { forwardRef, useState, useRef, useMemo, useEffect, useCallback } from 'react';
11
+ import { forwardRef, useState, useRef, useMemo, useEffect, useSyncExternalStore, useCallback } from 'react';
12
12
  import { Button, cn, Tooltip, TooltipTrigger, TooltipContent, Separator, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuCheckboxItem, TabsList, TabsTrigger, Tabs, TabsContent, Input, Textarea, Dialog, DialogContent, DialogTitle, DialogDescription, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@arbidocs/react/ui';
13
13
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
14
14
  import { MonitorUp, MicOff, AudioLines, SignalLow, Users, Mic, Captions, Lock, LockOpen, Video, VideoOff, ChevronUp, Loader2, Circle, PhoneOff, MoreHorizontal, LayoutGrid, UserRound, PictureInPicture2, Phone, X, Maximize2, BellOff, Bell, CalendarCheck, Radio, SquareX, EyeOff, Hand, Search, Send, MessageCircleQuestion, UserX, CheckCheck, RotateCcw, Trash2, MessageSquareText } from 'lucide-react';
@@ -2747,7 +2747,362 @@ function WebinarViewer({
2747
2747
  }
2748
2748
  );
2749
2749
  }
2750
+ var LEVEL_TICK_MS = 60;
2751
+ var SPEAKING_RELEASE_MS = 350;
2752
+ var EMPTY2 = { levels: {}, speaking: [], spotlight: null };
2753
+ var snapshot = EMPTY2;
2754
+ var listeners = /* @__PURE__ */ new Set();
2755
+ function publish(next) {
2756
+ snapshot = next;
2757
+ listeners.forEach((fn) => fn());
2758
+ }
2759
+ function subscribe(fn) {
2760
+ listeners.add(fn);
2761
+ return () => listeners.delete(fn);
2762
+ }
2763
+ var get = () => snapshot;
2764
+ function useVoiceLevel(identity) {
2765
+ return useSyncExternalStore(
2766
+ subscribe,
2767
+ () => identity ? get().levels[identity] ?? 0 : 0,
2768
+ () => 0
2769
+ );
2770
+ }
2771
+ function useVoiceLevels() {
2772
+ return useSyncExternalStore(
2773
+ subscribe,
2774
+ () => get().levels,
2775
+ () => EMPTY2.levels
2776
+ );
2777
+ }
2778
+ function useIsSpeaking(identity) {
2779
+ return useSyncExternalStore(
2780
+ subscribe,
2781
+ () => identity ? get().speaking.includes(identity) : false,
2782
+ () => false
2783
+ );
2784
+ }
2785
+ function useSpeakingIds() {
2786
+ const key = useSyncExternalStore(
2787
+ subscribe,
2788
+ () => get().speaking.join("\n"),
2789
+ () => ""
2790
+ );
2791
+ return key ? key.split("\n") : [];
2792
+ }
2793
+ function useSpotlightId() {
2794
+ return useSyncExternalStore(
2795
+ subscribe,
2796
+ () => get().spotlight,
2797
+ () => null
2798
+ );
2799
+ }
2800
+ function startVoiceLevels(sources) {
2801
+ let ctx = null;
2802
+ try {
2803
+ ctx = typeof AudioContext !== "undefined" ? new AudioContext() : null;
2804
+ } catch {
2805
+ ctx = null;
2806
+ }
2807
+ const meters = /* @__PURE__ */ new Map();
2808
+ const smoothed = /* @__PURE__ */ new Map();
2809
+ const loudAt = /* @__PURE__ */ new Map();
2810
+ let spot = INITIAL_SPOTLIGHT;
2811
+ const meterFor = (s) => {
2812
+ if (!ctx || !s.track || s.track.readyState === "ended") return null;
2813
+ const have = meters.get(s.identity);
2814
+ if (have && have.track === s.track) return have;
2815
+ have?.source.disconnect();
2816
+ try {
2817
+ const source = ctx.createMediaStreamSource(new MediaStream([s.track]));
2818
+ const analyser = ctx.createAnalyser();
2819
+ analyser.fftSize = 512;
2820
+ source.connect(analyser);
2821
+ const m = { track: s.track, source, analyser, buf: new Float32Array(analyser.fftSize) };
2822
+ meters.set(s.identity, m);
2823
+ return m;
2824
+ } catch {
2825
+ return null;
2826
+ }
2827
+ };
2828
+ const tick = () => {
2829
+ if (ctx?.state === "suspended") void ctx.resume().catch(() => void 0);
2830
+ const now = Date.now();
2831
+ const list = sources();
2832
+ const seen = /* @__PURE__ */ new Set();
2833
+ const levels = {};
2834
+ for (const s of list) {
2835
+ seen.add(s.identity);
2836
+ let raw = 0;
2837
+ const m = s.muted ? null : meterFor(s);
2838
+ if (m) {
2839
+ m.analyser.getFloatTimeDomainData(m.buf);
2840
+ let sum = 0;
2841
+ for (let i = 0; i < m.buf.length; i++) sum += m.buf[i] * m.buf[i];
2842
+ raw = Math.min(1, Math.sqrt(sum / m.buf.length) * 5);
2843
+ }
2844
+ const prev2 = smoothed.get(s.identity) ?? 0;
2845
+ const level = raw >= prev2 ? raw : prev2 * 0.8 + raw * 0.2;
2846
+ smoothed.set(s.identity, level);
2847
+ if (level >= SPEAKING_LEVEL) loudAt.set(s.identity, now);
2848
+ levels[s.identity] = Math.round(level * 20) / 20;
2849
+ }
2850
+ for (const id2 of [...meters.keys()]) {
2851
+ if (!seen.has(id2)) {
2852
+ meters.get(id2)?.source.disconnect();
2853
+ meters.delete(id2);
2854
+ smoothed.delete(id2);
2855
+ loudAt.delete(id2);
2856
+ }
2857
+ }
2858
+ const speaking = list.map((s) => s.identity).filter((id2) => now - (loudAt.get(id2) ?? -Infinity) <= SPEAKING_RELEASE_MS).sort((a, b) => (smoothed.get(b) ?? 0) - (smoothed.get(a) ?? 0));
2859
+ spot = nextSpotlight(spot, Object.fromEntries(smoothed), now, {
2860
+ exclude: list.filter((s) => s.local).map((s) => s.identity)
2861
+ });
2862
+ if (spot.id && !seen.has(spot.id)) spot = INITIAL_SPOTLIGHT;
2863
+ const prev = snapshot;
2864
+ const same = prev.spotlight === spot.id && prev.speaking.join("\n") === speaking.join("\n") && Object.keys(levels).length === Object.keys(prev.levels).length && Object.entries(levels).every(([k, v]) => prev.levels[k] === v);
2865
+ if (!same) publish({ levels, speaking, spotlight: spot.id });
2866
+ };
2867
+ const id = setInterval(tick, LEVEL_TICK_MS);
2868
+ return () => {
2869
+ clearInterval(id);
2870
+ for (const m of meters.values()) m.source.disconnect();
2871
+ meters.clear();
2872
+ void ctx?.close().catch(() => void 0);
2873
+ publish(EMPTY2);
2874
+ };
2875
+ }
2876
+ var RINGTONE_MUTED_KEY = "arbi-call-ringtone-muted";
2877
+ var RING_ON_S = 1.2;
2878
+ var RING_PERIOD_S = 4;
2879
+ var GAIN = 0.08;
2880
+ function audioContextCtor() {
2881
+ if (typeof window === "undefined") return null;
2882
+ return window.AudioContext ?? window.webkitAudioContext ?? null;
2883
+ }
2884
+ function startRingtone() {
2885
+ const Ctor = audioContextCtor();
2886
+ if (!Ctor) return () => {
2887
+ };
2888
+ let ctx;
2889
+ try {
2890
+ ctx = new Ctor();
2891
+ } catch {
2892
+ return () => {
2893
+ };
2894
+ }
2895
+ const out = ctx.createGain();
2896
+ out.gain.value = 0;
2897
+ out.connect(ctx.destination);
2898
+ const oscillators = [440, 480].map((frequency) => {
2899
+ const osc = ctx.createOscillator();
2900
+ osc.type = "sine";
2901
+ osc.frequency.value = frequency;
2902
+ osc.connect(out);
2903
+ osc.start();
2904
+ return osc;
2905
+ });
2906
+ let nextRingAt = ctx.currentTime + 0.05;
2907
+ const schedule = () => {
2908
+ while (nextRingAt < ctx.currentTime + RING_PERIOD_S * 2) {
2909
+ out.gain.setValueAtTime(0, nextRingAt);
2910
+ out.gain.linearRampToValueAtTime(GAIN, nextRingAt + 0.03);
2911
+ out.gain.setValueAtTime(GAIN, nextRingAt + RING_ON_S - 0.03);
2912
+ out.gain.linearRampToValueAtTime(0, nextRingAt + RING_ON_S);
2913
+ nextRingAt += RING_PERIOD_S;
2914
+ }
2915
+ };
2916
+ schedule();
2917
+ const timer = setInterval(schedule, 1e3);
2918
+ void ctx.resume().catch(() => {
2919
+ });
2920
+ let stopped = false;
2921
+ return () => {
2922
+ if (stopped) return;
2923
+ stopped = true;
2924
+ clearInterval(timer);
2925
+ for (const osc of oscillators) {
2926
+ try {
2927
+ osc.stop();
2928
+ } catch {
2929
+ }
2930
+ }
2931
+ void ctx.close().catch(() => {
2932
+ });
2933
+ };
2934
+ }
2935
+ function readMuted() {
2936
+ try {
2937
+ return localStorage.getItem(RINGTONE_MUTED_KEY) === "1";
2938
+ } catch {
2939
+ return false;
2940
+ }
2941
+ }
2942
+ function useRingtoneMuted() {
2943
+ const [muted, setMutedState] = useState(readMuted);
2944
+ const setMuted = useCallback((next) => {
2945
+ setMutedState(next);
2946
+ try {
2947
+ if (next) localStorage.setItem(RINGTONE_MUTED_KEY, "1");
2948
+ else localStorage.removeItem(RINGTONE_MUTED_KEY);
2949
+ } catch {
2950
+ }
2951
+ }, []);
2952
+ return [muted, setMuted];
2953
+ }
2954
+ function useRingtone(ringing, muted) {
2955
+ useEffect(() => {
2956
+ if (!ringing || muted) return;
2957
+ return startRingtone();
2958
+ }, [ringing, muted]);
2959
+ }
2960
+
2961
+ // src/calls/composite-canvas.ts
2962
+ var COMPOSITE_FPS = 15;
2963
+ var COMPOSITE_MAX_WIDTH = 1280;
2964
+ var COMPOSITE_MAX_HEIGHT = 720;
2965
+ function fitStage(stage, canvas) {
2966
+ if (stage.width <= 0 || stage.height <= 0) return { scale: 0, dx: 0, dy: 0 };
2967
+ const scale = Math.min(canvas.width / stage.width, canvas.height / stage.height);
2968
+ return {
2969
+ scale,
2970
+ dx: (canvas.width - stage.width * scale) / 2,
2971
+ dy: (canvas.height - stage.height * scale) / 2
2972
+ };
2973
+ }
2974
+ function fitMedia(src, box, mode) {
2975
+ const srcRatio = src.width / src.height;
2976
+ const boxRatio = box.width / box.height;
2977
+ if (mode === "contain") {
2978
+ const dw = srcRatio > boxRatio ? box.width : box.height * srcRatio;
2979
+ const dh = srcRatio > boxRatio ? box.width / srcRatio : box.height;
2980
+ return {
2981
+ sx: 0,
2982
+ sy: 0,
2983
+ sw: src.width,
2984
+ sh: src.height,
2985
+ dx: box.x + (box.width - dw) / 2,
2986
+ dy: box.y + (box.height - dh) / 2,
2987
+ dw,
2988
+ dh
2989
+ };
2990
+ }
2991
+ const sw = srcRatio > boxRatio ? src.height * boxRatio : src.width;
2992
+ const sh = srcRatio > boxRatio ? src.height : src.width / boxRatio;
2993
+ return {
2994
+ sx: (src.width - sw) / 2,
2995
+ sy: (src.height - sh) / 2,
2996
+ sw,
2997
+ sh,
2998
+ dx: box.x,
2999
+ dy: box.y,
3000
+ dw: box.width,
3001
+ dh: box.height
3002
+ };
3003
+ }
3004
+ function drawStageFrame(ctx, stage, width, height) {
3005
+ ctx.fillStyle = "#111";
3006
+ ctx.fillRect(0, 0, width, height);
3007
+ const stageRect = stage.getBoundingClientRect();
3008
+ const { scale, dx, dy } = fitStage(stageRect, { width, height });
3009
+ if (!scale) {
3010
+ ctx.fillStyle = "#bbb";
3011
+ ctx.font = "24px sans-serif";
3012
+ ctx.textAlign = "center";
3013
+ ctx.fillText("Video paused", width / 2, height / 2);
3014
+ ctx.textAlign = "start";
3015
+ return;
3016
+ }
3017
+ const tiles = Array.from(stage.querySelectorAll(".lk-participant-tile"));
3018
+ for (const tile of tiles) {
3019
+ const r = tile.getBoundingClientRect();
3020
+ if (r.width <= 0 || r.height <= 0) continue;
3021
+ const box = {
3022
+ x: dx + (r.left - stageRect.left) * scale,
3023
+ y: dy + (r.top - stageRect.top) * scale,
3024
+ width: r.width * scale,
3025
+ height: r.height * scale
3026
+ };
3027
+ ctx.fillStyle = "#222";
3028
+ ctx.fillRect(box.x, box.y, box.width, box.height);
3029
+ const video = tile.querySelector("video");
3030
+ if (video && video.readyState >= 2 && video.videoWidth > 0 && video.videoHeight > 0) {
3031
+ const screen = tile.getAttribute("data-lk-source") === "screen_share";
3032
+ const f = fitMedia(
3033
+ { width: video.videoWidth, height: video.videoHeight },
3034
+ box,
3035
+ screen ? "contain" : "cover"
3036
+ );
3037
+ try {
3038
+ ctx.drawImage(video, f.sx, f.sy, f.sw, f.sh, f.dx, f.dy, f.dw, f.dh);
3039
+ } catch {
3040
+ }
3041
+ }
3042
+ if (tile.getAttribute("data-lk-speaking") === "true") {
3043
+ ctx.strokeStyle = "#4ade80";
3044
+ ctx.lineWidth = 3;
3045
+ ctx.strokeRect(box.x + 1.5, box.y + 1.5, box.width - 3, box.height - 3);
3046
+ }
3047
+ const name = tile.querySelector(".lk-participant-name")?.textContent?.trim();
3048
+ if (name) {
3049
+ ctx.font = `${Math.max(11, Math.round(14 * Math.min(1, scale * 1.2)))}px sans-serif`;
3050
+ const w = ctx.measureText(name).width;
3051
+ ctx.fillStyle = "rgba(0,0,0,0.6)";
3052
+ ctx.fillRect(box.x + 6, box.y + box.height - 26, w + 12, 20);
3053
+ ctx.fillStyle = "#fff";
3054
+ ctx.fillText(name, box.x + 12, box.y + box.height - 11);
3055
+ }
3056
+ }
3057
+ }
3058
+ function startCompositeCapture(stage) {
3059
+ const canvas = document.createElement("canvas");
3060
+ canvas.width = COMPOSITE_MAX_WIDTH;
3061
+ canvas.height = COMPOSITE_MAX_HEIGHT;
3062
+ const ctx = canvas.getContext("2d");
3063
+ if (!ctx) throw new Error("This browser cannot draw the recording");
3064
+ const draw = () => drawStageFrame(ctx, stage, canvas.width, canvas.height);
3065
+ draw();
3066
+ const timer = setInterval(draw, Math.round(1e3 / COMPOSITE_FPS));
3067
+ const video = canvas.captureStream(COMPOSITE_FPS);
3068
+ const audio = new AudioContext();
3069
+ const destination = audio.createMediaStreamDestination();
3070
+ const sources = /* @__PURE__ */ new Map();
3071
+ const stream = new MediaStream([
3072
+ ...video.getVideoTracks(),
3073
+ ...destination.stream.getAudioTracks()
3074
+ ]);
3075
+ return {
3076
+ stream,
3077
+ setAudioTracks(tracks) {
3078
+ const wanted = new Map(tracks.map((t) => [t.id, t]));
3079
+ for (const [id, node] of sources) {
3080
+ if (!wanted.has(id)) {
3081
+ node.disconnect();
3082
+ sources.delete(id);
3083
+ }
3084
+ }
3085
+ for (const [id, track] of wanted) {
3086
+ if (sources.has(id) || track.readyState === "ended") continue;
3087
+ try {
3088
+ const node = audio.createMediaStreamSource(new MediaStream([track]));
3089
+ node.connect(destination);
3090
+ sources.set(id, node);
3091
+ } catch {
3092
+ }
3093
+ }
3094
+ if (audio.state === "suspended") void audio.resume().catch(() => void 0);
3095
+ },
3096
+ dispose() {
3097
+ clearInterval(timer);
3098
+ for (const node of sources.values()) node.disconnect();
3099
+ sources.clear();
3100
+ video.getTracks().forEach((t) => t.stop());
3101
+ void audio.close().catch(() => void 0);
3102
+ }
3103
+ };
3104
+ }
2750
3105
 
2751
- export { BackstageBanner, CallControlBar, CallControlButton, CallFocus, CallGrid, CallHeader, CallNotice, CallParticipants, CallPersonLabel, CallSidePanel, CallStageFrame, CallStateMessage, CallStatusChip, CallTile, CaptionsStrip, ChatPermissionSetting, ConnectionOverlay, ControlBadge, ControlDivider, ControlGroup, DEFAULT_JOIN_CHOICES, ElapsedTime, EncryptionStatusChip, IncomingCallCard, LeaveButton, LobbyRequests, MediaControl, MinimisedCall, MoreMenu, OnStageCheck, PanelComposer, PreJoin, QAPanel, RaiseHandButton, RecordControl, RecordingStatusChip, SpeakingNow, TranscriptionStatusChip, VoiceMeter, WebinarAudiencePanel, WebinarEndConfirm, WebinarLiveChip, WebinarLiveControl, WebinarViewer, WebinarWaiting, chatPermissionSection, describeMediaError, sortQuestions, useBriefNotice, useElementSize, useShortcutKeys };
3106
+ export { BackstageBanner, COMPOSITE_FPS, COMPOSITE_MAX_HEIGHT, COMPOSITE_MAX_WIDTH, CallControlBar, CallControlButton, CallFocus, CallGrid, CallHeader, CallNotice, CallParticipants, CallPersonLabel, CallSidePanel, CallStageFrame, CallStateMessage, CallStatusChip, CallTile, CaptionsStrip, ChatPermissionSetting, ConnectionOverlay, ControlBadge, ControlDivider, ControlGroup, DEFAULT_JOIN_CHOICES, ElapsedTime, EncryptionStatusChip, IncomingCallCard, LEVEL_TICK_MS, LeaveButton, LobbyRequests, MediaControl, MinimisedCall, MoreMenu, OnStageCheck, PanelComposer, PreJoin, QAPanel, RINGTONE_MUTED_KEY, RaiseHandButton, RecordControl, RecordingStatusChip, SpeakingNow, TranscriptionStatusChip, VoiceMeter, WebinarAudiencePanel, WebinarEndConfirm, WebinarLiveChip, WebinarLiveControl, WebinarViewer, WebinarWaiting, chatPermissionSection, describeMediaError, drawStageFrame, fitMedia, fitStage, sortQuestions, startCompositeCapture, startRingtone, startVoiceLevels, useBriefNotice, useElementSize, useIsSpeaking, useRingtone, useRingtoneMuted, useShortcutKeys, useSpeakingIds, useSpotlightId, useVoiceLevel, useVoiceLevels };
2752
3107
  //# sourceMappingURL=index.js.map
2753
3108
  //# sourceMappingURL=index.js.map