@arbidocs/blocks 0.4.129 → 0.4.130

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 (173) hide show
  1. package/README.md +4 -3
  2. package/dist/agents/index.cjs +216 -216
  3. package/dist/agents/index.js +5 -5
  4. package/dist/calendar/CalendarPrint.d.ts +25 -0
  5. package/dist/calendar/booking-slots.d.ts +21 -0
  6. package/dist/calendar/index.cjs +381 -97
  7. package/dist/calendar/index.cjs.map +1 -1
  8. package/dist/calendar/index.d.ts +4 -0
  9. package/dist/calendar/index.js +277 -3
  10. package/dist/calendar/index.js.map +1 -1
  11. package/dist/calendar/print-layout.d.ts +16 -0
  12. package/dist/calendar/printCalendar.d.ts +6 -0
  13. package/dist/calls/composite-canvas.d.ts +52 -0
  14. package/dist/calls/index.cjs +376 -3
  15. package/dist/calls/index.cjs.map +1 -1
  16. package/dist/calls/index.d.ts +3 -0
  17. package/dist/calls/index.js +360 -5
  18. package/dist/calls/index.js.map +1 -1
  19. package/dist/calls/ringtone.d.ts +16 -0
  20. package/dist/calls/voice-levels.d.ts +32 -0
  21. package/dist/chat/ThreadVisualizer.d.ts +28 -0
  22. package/dist/chat/index.cjs +93 -77
  23. package/dist/chat/index.d.ts +2 -0
  24. package/dist/chat/index.js +2 -2
  25. package/dist/chat/open-document.d.ts +5 -1
  26. package/dist/chat/thread-diagram.d.ts +26 -0
  27. package/dist/{chunk-DQCYCEDR.js → chunk-2Q7FDZAY.js} +3 -3
  28. package/dist/{chunk-DQCYCEDR.js.map → chunk-2Q7FDZAY.js.map} +1 -1
  29. package/dist/{chunk-S7PSMMRG.js → chunk-444XKG46.js} +3 -3
  30. package/dist/{chunk-S7PSMMRG.js.map → chunk-444XKG46.js.map} +1 -1
  31. package/dist/{chunk-7423V6RM.cjs → chunk-4QIIDXLF.cjs} +8 -8
  32. package/dist/{chunk-7423V6RM.cjs.map → chunk-4QIIDXLF.cjs.map} +1 -1
  33. package/dist/{chunk-OYMWV45N.js → chunk-4RLCRFZS.js} +63 -13
  34. package/dist/chunk-4RLCRFZS.js.map +1 -0
  35. package/dist/{chunk-DZYAAL4H.cjs → chunk-4S5IDT5F.cjs} +231 -2
  36. package/dist/chunk-4S5IDT5F.cjs.map +1 -0
  37. package/dist/{chunk-CJBN5HIS.js → chunk-4UMXQPNA.js} +20 -8
  38. package/dist/chunk-4UMXQPNA.js.map +1 -0
  39. package/dist/{chunk-IBZJYCYM.js → chunk-66TA5IBN.js} +17 -25
  40. package/dist/chunk-66TA5IBN.js.map +1 -0
  41. package/dist/{chunk-OR4CO743.cjs → chunk-AAFX64WD.cjs} +3 -3
  42. package/dist/{chunk-OR4CO743.cjs.map → chunk-AAFX64WD.cjs.map} +1 -1
  43. package/dist/{chunk-MUMH3Z6K.cjs → chunk-ARDHLU73.cjs} +61 -11
  44. package/dist/chunk-ARDHLU73.cjs.map +1 -0
  45. package/dist/{chunk-TGWTLNXW.cjs → chunk-BIXHB4LV.cjs} +3 -2
  46. package/dist/{chunk-TGWTLNXW.cjs.map → chunk-BIXHB4LV.cjs.map} +1 -1
  47. package/dist/chunk-C4WSHRR6.cjs +166 -0
  48. package/dist/chunk-C4WSHRR6.cjs.map +1 -0
  49. package/dist/{chunk-ZAVEMQ37.cjs → chunk-DWZXSPMB.cjs} +3 -3
  50. package/dist/{chunk-ZAVEMQ37.cjs.map → chunk-DWZXSPMB.cjs.map} +1 -1
  51. package/dist/{chunk-5HFPRI3W.js → chunk-FUTMU4FR.js} +3 -3
  52. package/dist/{chunk-5HFPRI3W.js.map → chunk-FUTMU4FR.js.map} +1 -1
  53. package/dist/{chunk-5Y7JRY7Y.js → chunk-GDBDHOI4.js} +3 -3
  54. package/dist/{chunk-5Y7JRY7Y.js.map → chunk-GDBDHOI4.js.map} +1 -1
  55. package/dist/{chunk-TGJNPKST.js → chunk-GTCC2VAR.js} +3 -3
  56. package/dist/{chunk-TGJNPKST.js.map → chunk-GTCC2VAR.js.map} +1 -1
  57. package/dist/{chunk-3BJLNKOB.cjs → chunk-GZPTWHP5.cjs} +22 -10
  58. package/dist/chunk-GZPTWHP5.cjs.map +1 -0
  59. package/dist/{chunk-OUW6G4O2.cjs → chunk-HFGXA5CL.cjs} +4 -4
  60. package/dist/{chunk-OUW6G4O2.cjs.map → chunk-HFGXA5CL.cjs.map} +1 -1
  61. package/dist/{chunk-SWQX6CTT.cjs → chunk-JKB7WT7L.cjs} +2 -2
  62. package/dist/chunk-JKB7WT7L.cjs.map +1 -0
  63. package/dist/{chunk-S6BOINC4.cjs → chunk-OGBXV326.cjs} +7 -7
  64. package/dist/{chunk-S6BOINC4.cjs.map → chunk-OGBXV326.cjs.map} +1 -1
  65. package/dist/{chunk-DJM7DLCT.cjs → chunk-OPTBQSCV.cjs} +3 -3
  66. package/dist/{chunk-DJM7DLCT.cjs.map → chunk-OPTBQSCV.cjs.map} +1 -1
  67. package/dist/{chunk-GFYGYME3.js → chunk-OQ7RUNOC.js} +3 -3
  68. package/dist/{chunk-GFYGYME3.js.map → chunk-OQ7RUNOC.js.map} +1 -1
  69. package/dist/{chunk-NYHGG2IA.cjs → chunk-QDEODGXE.cjs} +5 -5
  70. package/dist/{chunk-NYHGG2IA.cjs.map → chunk-QDEODGXE.cjs.map} +1 -1
  71. package/dist/{chunk-6BTCDKCK.js → chunk-QYTYW74G.js} +4 -4
  72. package/dist/{chunk-6BTCDKCK.js.map → chunk-QYTYW74G.js.map} +1 -1
  73. package/dist/{chunk-A7NCSZAP.cjs → chunk-QZTNTP75.cjs} +17 -25
  74. package/dist/chunk-QZTNTP75.cjs.map +1 -0
  75. package/dist/{chunk-OB5F4577.cjs → chunk-R26BK7YL.cjs} +4 -4
  76. package/dist/{chunk-OB5F4577.cjs.map → chunk-R26BK7YL.cjs.map} +1 -1
  77. package/dist/{chunk-A2YAC22G.js → chunk-RI6DZA5X.js} +3 -3
  78. package/dist/{chunk-A2YAC22G.js.map → chunk-RI6DZA5X.js.map} +1 -1
  79. package/dist/{chunk-H2KQ6OSU.js → chunk-SZX44LCT.js} +230 -5
  80. package/dist/chunk-SZX44LCT.js.map +1 -0
  81. package/dist/{chunk-7QDX2CO4.cjs → chunk-TP6PLDNM.cjs} +4 -4
  82. package/dist/{chunk-7QDX2CO4.cjs.map → chunk-TP6PLDNM.cjs.map} +1 -1
  83. package/dist/{chunk-JLTXVW25.cjs → chunk-TT6XV6WM.cjs} +17 -17
  84. package/dist/{chunk-JLTXVW25.cjs.map → chunk-TT6XV6WM.cjs.map} +1 -1
  85. package/dist/{chunk-HSFLEVZY.js → chunk-UMIY4SQS.js} +6 -6
  86. package/dist/{chunk-HSFLEVZY.js.map → chunk-UMIY4SQS.js.map} +1 -1
  87. package/dist/{chunk-ECERC6TI.js → chunk-VHJHY7TT.js} +3 -3
  88. package/dist/{chunk-ECERC6TI.js.map → chunk-VHJHY7TT.js.map} +1 -1
  89. package/dist/{chunk-D3N67Q4D.js → chunk-W3VYZXNS.js} +3 -3
  90. package/dist/{chunk-D3N67Q4D.js.map → chunk-W3VYZXNS.js.map} +1 -1
  91. package/dist/{chunk-JK45LSIH.cjs → chunk-WXYQ66KC.cjs} +5 -5
  92. package/dist/{chunk-JK45LSIH.cjs.map → chunk-WXYQ66KC.cjs.map} +1 -1
  93. package/dist/{chunk-ZCF2JJFA.js → chunk-Y3KA6X7B.js} +3 -3
  94. package/dist/{chunk-ZCF2JJFA.js.map → chunk-Y3KA6X7B.js.map} +1 -1
  95. package/dist/{chunk-GYCQ3FNL.js → chunk-YBLIKTJK.js} +2 -2
  96. package/dist/chunk-YBLIKTJK.js.map +1 -0
  97. package/dist/chunk-YNIBUKV5.js +163 -0
  98. package/dist/chunk-YNIBUKV5.js.map +1 -0
  99. package/dist/citations/index.cjs +12 -11
  100. package/dist/citations/index.js +3 -2
  101. package/dist/collaboration/index.cjs +42 -42
  102. package/dist/collaboration/index.js +2 -2
  103. package/dist/connect/docx.cjs +7 -5
  104. package/dist/connect/docx.cjs.map +1 -1
  105. package/dist/connect/docx.js +6 -4
  106. package/dist/connect/docx.js.map +1 -1
  107. package/dist/connect/index.cjs +237 -194
  108. package/dist/connect/index.cjs.map +1 -1
  109. package/dist/connect/index.d.ts +1 -1
  110. package/dist/connect/index.js +190 -147
  111. package/dist/connect/index.js.map +1 -1
  112. package/dist/connection/ConnectedSettings.d.ts +46 -20
  113. package/dist/connection/ConnectionProvider.d.ts +5 -0
  114. package/dist/connection/mail/ConnectedMailComposer.d.ts +2 -3
  115. package/dist/connection/mail/ConnectedMailbox.d.ts +2 -3
  116. package/dist/connection/mail/MailComposerForm.d.ts +2 -3
  117. package/dist/connection/mail/index.d.ts +2 -2
  118. package/dist/connection/mail/mailbox.d.ts +1 -4
  119. package/dist/connection/mail/types.d.ts +0 -8
  120. package/dist/facts/fact-citations.d.ts +56 -0
  121. package/dist/facts/fact-table-column-resize.d.ts +18 -0
  122. package/dist/facts/index.cjs +197 -10
  123. package/dist/facts/index.cjs.map +1 -1
  124. package/dist/facts/index.d.ts +2 -0
  125. package/dist/facts/index.js +182 -6
  126. package/dist/facts/index.js.map +1 -1
  127. package/dist/files/index.cjs +4 -4
  128. package/dist/files/index.js +3 -3
  129. package/dist/home/index.cjs +20 -19
  130. package/dist/home/index.cjs.map +1 -1
  131. package/dist/home/index.js +5 -4
  132. package/dist/home/index.js.map +1 -1
  133. package/dist/index.cjs +485 -469
  134. package/dist/index.d.ts +2 -1
  135. package/dist/index.js +13 -13
  136. package/dist/provider/BlocksProvider.d.ts +39 -4
  137. package/dist/provider/dialogs.d.ts +31 -0
  138. package/dist/retrieval/index.cjs +5 -4
  139. package/dist/retrieval/index.js +3 -2
  140. package/dist/settings/MoreInfo.d.ts +25 -0
  141. package/dist/settings/PlanCard.d.ts +1 -1
  142. package/dist/settings/index.cjs +106 -252
  143. package/dist/settings/index.cjs.map +1 -1
  144. package/dist/settings/index.d.ts +1 -1
  145. package/dist/settings/index.js +71 -216
  146. package/dist/settings/index.js.map +1 -1
  147. package/dist/shell/index.cjs +48 -47
  148. package/dist/shell/index.js +4 -3
  149. package/dist/studio/index.cjs +15 -14
  150. package/dist/studio/index.cjs.map +1 -1
  151. package/dist/studio/index.js +7 -6
  152. package/dist/studio/index.js.map +1 -1
  153. package/dist/workflow-canvas/index.cjs +14 -14
  154. package/dist/workflow-canvas/index.js +6 -6
  155. package/dist/workspaces/index.cjs +3 -3
  156. package/dist/workspaces/index.js +2 -2
  157. package/node_modules/@arbidocs/coedit/package.json +1 -1
  158. package/package.json +9 -4
  159. package/dist/chunk-3BJLNKOB.cjs.map +0 -1
  160. package/dist/chunk-76JDDMSP.js +0 -31
  161. package/dist/chunk-76JDDMSP.js.map +0 -1
  162. package/dist/chunk-A7NCSZAP.cjs.map +0 -1
  163. package/dist/chunk-C54XEN5T.cjs +0 -34
  164. package/dist/chunk-C54XEN5T.cjs.map +0 -1
  165. package/dist/chunk-CJBN5HIS.js.map +0 -1
  166. package/dist/chunk-DZYAAL4H.cjs.map +0 -1
  167. package/dist/chunk-GYCQ3FNL.js.map +0 -1
  168. package/dist/chunk-H2KQ6OSU.js.map +0 -1
  169. package/dist/chunk-IBZJYCYM.js.map +0 -1
  170. package/dist/chunk-MUMH3Z6K.cjs.map +0 -1
  171. package/dist/chunk-OYMWV45N.js.map +0 -1
  172. package/dist/chunk-SWQX6CTT.cjs.map +0 -1
  173. 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
- import { ConfirmDialog } from '../chunk-ECERC6TI.js';
3
- import '../chunk-TX2ZICS7.js';
2
+ import { ConfirmDialog } from '../chunk-VHJHY7TT.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 { NOTICE_MS, gridSlots, gridLayout, spotlightBox, CAPTION_TTL_MS, CAPTION_LINES, speakerAccent, formatElapsed, initialsOf, SPEAKING_LEVEL, nextSpotlight, INITIAL_SPOTLIGHT } from '../chunk-Z3AZ7Q5X.js';
6
5
  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
6
  import '../chunk-NPLYHR2E.js';
8
7
  import '../chunk-7F6CBP3Z.js';
8
+ import '../chunk-TX2ZICS7.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