streemo-video-call-sdk 0.2.4 → 0.2.6

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/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { PropsWithChildren, Component, ReactNode, ErrorInfo } from 'react';
4
+ export { StreemoThemeProvider, Theme, ThemeMode, ThemeTokens, createTheme, useTheme } from 'streemo-ui-kit-web/theme';
4
5
  import { T as TokenProvider, S as ServerAuthConfig } from './sdkConfig-C9Fey7R2.js';
5
6
  export { a as SDKError, b as SDKErrorCode, c as ServerTokenProviderOptions, d as TokenProviderContext, V as VideoSDKConfig, e as createServerTokenProvider, f as defaultApiBaseUrl, g as defaultWsBaseUrlFromApi, h as getVideoSDKConfig, i as initVideoSDK, m as mapSDKErrorToUIMessage } from './sdkConfig-C9Fey7R2.js';
6
7
 
@@ -223,6 +224,8 @@ declare function useCall({ roomId, enabled }: UseCallParams): {
223
224
  hasCameraTrack: boolean;
224
225
  toggleMic: () => void;
225
226
  toggleCamera: () => void;
227
+ screenSharing: boolean;
228
+ toggleScreenShare: () => Promise<void>;
226
229
  sendChatMessage: (text: string, senderName?: string) => void;
227
230
  editChatMessage: (id: string, text: string) => void;
228
231
  deleteChatMessage: (id: string) => void;
@@ -416,6 +419,8 @@ declare function useWebRTCCall(params: UseWebRTCCallParams): {
416
419
  hasCameraTrack: boolean;
417
420
  toggleMic: () => void;
418
421
  toggleCamera: () => void;
422
+ screenSharing: boolean;
423
+ toggleScreenShare: () => Promise<void>;
419
424
  sendChatMessage: (text: string, senderName?: string) => void;
420
425
  editChatMessage: (id: string, text: string) => void;
421
426
  deleteChatMessage: (id: string) => void;
package/dist/index.js CHANGED
@@ -193,17 +193,27 @@ function useStreemoContext() {
193
193
  }
194
194
 
195
195
  // src/theme/StreemoTheme.tsx
196
+ import { createTheme, themeToCssVars } from "streemo-ui-kit-web/theme";
196
197
  import { jsx as jsx2 } from "react/jsx-runtime";
197
198
  function StreemoTheme({ theme, mode = "light", children }) {
198
- const style = {
199
- ["--st-color-primary"]: theme?.primary ?? "#635bff",
200
- ["--st-color-bg"]: theme?.background ?? (mode === "dark" ? "#111827" : "#ffffff"),
201
- ["--st-color-text"]: theme?.text ?? (mode === "dark" ? "#f9fafb" : "#0f172a"),
202
- ["--st-radius"]: theme?.radius ?? "10px"
203
- };
199
+ const themeConfig = createTheme({
200
+ mode,
201
+ tokens: theme ? {
202
+ colors: {
203
+ primary: theme.primary,
204
+ background: theme.background,
205
+ text: theme.text
206
+ },
207
+ radius: theme.radius ? { md: parseInt(theme.radius, 10) || 10, lg: 12 } : void 0
208
+ } : void 0
209
+ });
210
+ const style = themeToCssVars(themeConfig);
204
211
  return /* @__PURE__ */ jsx2("div", { className: `st-theme st-theme--${mode}`, style, children });
205
212
  }
206
213
 
214
+ // src/index.ts
215
+ import { createTheme as createTheme2, StreemoThemeProvider, useTheme } from "streemo-ui-kit-web/theme";
216
+
207
217
  // src/hooks/useChat.ts
208
218
  import { useEffect as useEffect2, useState as useState2 } from "react";
209
219
  function useChat() {
@@ -631,6 +641,9 @@ var RENEGOTIATION_RETRY_DELAY_MS = 6e3;
631
641
  var RENEGOTIATION_MAX_RETRIES = 3;
632
642
  var DISCONNECTED_CLEANUP_DELAY_MS = 1e4;
633
643
  var NETWORK_STATS_POLL_MS = 5e3;
644
+ function isVideoTransceiver(t) {
645
+ return t.kind === "video";
646
+ }
634
647
  var AUDIO_CONSTRAINTS = {
635
648
  echoCancellation: true,
636
649
  noiseSuppression: true,
@@ -820,6 +833,8 @@ function useWebRTCCall(params) {
820
833
  const [cameraEnabled, setCameraEnabled] = useState6(true);
821
834
  const [hasMicTrack, setHasMicTrack] = useState6(false);
822
835
  const [hasCameraTrack, setHasCameraTrack] = useState6(false);
836
+ const [screenSharing, setScreenSharing] = useState6(false);
837
+ const screenTrackRef = useRef2(null);
823
838
  const clearRenegotiationRetry = useCallback2((targetUserId) => {
824
839
  const timer = renegotiationTimersRef.current.get(targetUserId);
825
840
  if (timer) {
@@ -1572,6 +1587,83 @@ function useWebRTCCall(params) {
1572
1587
  });
1573
1588
  setCameraEnabled(nextEnabled);
1574
1589
  }, [cameraEnabled]);
1590
+ const stopScreenShare = useCallback2(() => {
1591
+ const stream = localStreamRef.current;
1592
+ if (!stream || !screenTrackRef.current) return;
1593
+ navigator.mediaDevices.getUserMedia({ audio: false, video: VIDEO_CONSTRAINTS }).then((cameraStream) => {
1594
+ const cameraTrack = cameraStream.getVideoTracks()[0];
1595
+ if (!cameraTrack) return;
1596
+ const oldTrack = stream.getVideoTracks()[0];
1597
+ if (oldTrack) {
1598
+ stream.removeTrack(oldTrack);
1599
+ oldTrack.stop();
1600
+ }
1601
+ stream.addTrack(cameraTrack);
1602
+ screenTrackRef.current = null;
1603
+ setScreenSharing(false);
1604
+ setLocalStream(new MediaStream(stream.getTracks()));
1605
+ peersRef.current.forEach((peer) => {
1606
+ const videoSender = peer.getSenders().find((s) => s.track?.kind === "video");
1607
+ if (videoSender) {
1608
+ videoSender.replaceTrack(cameraTrack);
1609
+ } else {
1610
+ const videoTransceiver = peer.getTransceivers().find(isVideoTransceiver);
1611
+ if (videoTransceiver) {
1612
+ videoTransceiver.sender.replaceTrack(cameraTrack);
1613
+ } else {
1614
+ peer.addTrack(cameraTrack, localStreamRef.current);
1615
+ }
1616
+ }
1617
+ });
1618
+ cameraStream.getTracks().filter((t) => t !== cameraTrack).forEach((t) => t.stop());
1619
+ }).catch(() => {
1620
+ setScreenSharing(false);
1621
+ screenTrackRef.current = null;
1622
+ });
1623
+ }, []);
1624
+ const toggleScreenShare = useCallback2(async () => {
1625
+ const stream = localStreamRef.current;
1626
+ if (!stream) return;
1627
+ if (screenSharing) {
1628
+ stopScreenShare();
1629
+ return;
1630
+ }
1631
+ try {
1632
+ const screenStream = await navigator.mediaDevices.getDisplayMedia({
1633
+ video: true,
1634
+ audio: false
1635
+ });
1636
+ const screenTrack = screenStream.getVideoTracks()[0];
1637
+ if (!screenTrack) return;
1638
+ screenTrackRef.current = screenTrack;
1639
+ screenTrack.onended = () => stopScreenShare();
1640
+ const oldVideoTrack = stream.getVideoTracks()[0];
1641
+ if (oldVideoTrack) {
1642
+ stream.removeTrack(oldVideoTrack);
1643
+ oldVideoTrack.stop();
1644
+ }
1645
+ stream.addTrack(screenTrack);
1646
+ setScreenSharing(true);
1647
+ setLocalStream(new MediaStream(stream.getTracks()));
1648
+ peersRef.current.forEach((peer) => {
1649
+ const videoSender = peer.getSenders().find((s) => s.track?.kind === "video");
1650
+ if (videoSender) {
1651
+ videoSender.replaceTrack(screenTrack);
1652
+ } else {
1653
+ const videoTransceiver = peer.getTransceivers().find(isVideoTransceiver);
1654
+ if (videoTransceiver) {
1655
+ videoTransceiver.sender.replaceTrack(screenTrack);
1656
+ } else {
1657
+ peer.addTrack(screenTrack, localStreamRef.current);
1658
+ }
1659
+ }
1660
+ });
1661
+ screenStream.getTracks().filter((t) => t !== screenTrack).forEach((t) => t.stop());
1662
+ } catch {
1663
+ setScreenSharing(false);
1664
+ screenTrackRef.current = null;
1665
+ }
1666
+ }, [screenSharing, stopScreenShare]);
1575
1667
  const sendChatMessage = useCallback2(
1576
1668
  (text, senderName = "\u0413\u043E\u0441\u0442\u044C") => {
1577
1669
  const normalizedText = text.trim();
@@ -1665,6 +1757,8 @@ function useWebRTCCall(params) {
1665
1757
  hasCameraTrack,
1666
1758
  toggleMic,
1667
1759
  toggleCamera,
1760
+ screenSharing,
1761
+ toggleScreenShare,
1668
1762
  sendChatMessage,
1669
1763
  editChatMessage,
1670
1764
  deleteChatMessage,
@@ -1737,11 +1831,12 @@ function ChannelPreview({ channel, active, onSelect }) {
1737
1831
  }
1738
1832
 
1739
1833
  // src/components/ui/LoadingSpinner.tsx
1834
+ import { Spinner } from "streemo-ui-kit-web";
1740
1835
  import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
1741
1836
  function LoadingSpinner({ label = "Loading..." }) {
1742
1837
  return /* @__PURE__ */ jsxs2("div", { className: "st-spinner", role: "status", "aria-live": "polite", children: [
1743
- /* @__PURE__ */ jsx5("span", { className: "st-spinner__dot" }),
1744
- /* @__PURE__ */ jsx5("span", { children: label })
1838
+ /* @__PURE__ */ jsx5(Spinner, { size: 20 }),
1839
+ label != null && /* @__PURE__ */ jsx5("span", { children: label })
1745
1840
  ] });
1746
1841
  }
1747
1842
 
@@ -2042,19 +2137,10 @@ function MuteButton() {
2042
2137
  }
2043
2138
 
2044
2139
  // src/components/video/ScreenShareButton.tsx
2045
- import { useState as useState11 } from "react";
2046
2140
  import { jsx as jsx23 } from "react/jsx-runtime";
2047
2141
  function ScreenShareButton() {
2048
- const [sharing, setSharing] = useState11(false);
2049
- return /* @__PURE__ */ jsx23(
2050
- "button",
2051
- {
2052
- onClick: () => {
2053
- setSharing((prev) => !prev);
2054
- },
2055
- children: sharing ? "Stop share" : "Share screen"
2056
- }
2057
- );
2142
+ const call = useCallRoomContext();
2143
+ return /* @__PURE__ */ jsx23("button", { onClick: () => void call.toggleScreenShare(), children: call.screenSharing ? "Stop share" : "Share screen" });
2058
2144
  }
2059
2145
 
2060
2146
  // src/components/video/CallControls.tsx
@@ -2070,12 +2156,10 @@ function CallControls() {
2070
2156
  }
2071
2157
 
2072
2158
  // src/components/ui/Avatar.tsx
2159
+ import { Avatar as StreemoAvatar } from "streemo-ui-kit-web";
2073
2160
  import { jsx as jsx25 } from "react/jsx-runtime";
2074
2161
  function Avatar({ name, image, size = 32 }) {
2075
- if (image) {
2076
- return /* @__PURE__ */ jsx25("img", { className: "st-avatar", src: image, alt: name, style: { width: size, height: size } });
2077
- }
2078
- return /* @__PURE__ */ jsx25("div", { className: "st-avatar st-avatar--fallback", style: { width: size, height: size }, children: name.slice(0, 1).toUpperCase() });
2162
+ return /* @__PURE__ */ jsx25(StreemoAvatar, { name, src: image ?? void 0, size });
2079
2163
  }
2080
2164
 
2081
2165
  // src/components/ui/PresenceBadge.tsx
@@ -2113,7 +2197,7 @@ var ErrorBoundary = class extends Component {
2113
2197
  };
2114
2198
 
2115
2199
  // src/ChatPanel.tsx
2116
- import { useEffect as useEffect8, useMemo as useMemo11, useRef as useRef4, useState as useState12 } from "react";
2200
+ import { useEffect as useEffect8, useMemo as useMemo11, useRef as useRef4, useState as useState11 } from "react";
2117
2201
  import { jsx as jsx29, jsxs as jsxs11 } from "react/jsx-runtime";
2118
2202
  function ChatPanel({
2119
2203
  messages,
@@ -2131,9 +2215,9 @@ function ChatPanel({
2131
2215
  onFocusChange,
2132
2216
  placeholder = "Write a message..."
2133
2217
  }) {
2134
- const [draft, setDraft] = useState12("");
2135
- const [editingId, setEditingId] = useState12(null);
2136
- const [editingText, setEditingText] = useState12("");
2218
+ const [draft, setDraft] = useState11("");
2219
+ const [editingId, setEditingId] = useState11(null);
2220
+ const [editingText, setEditingText] = useState11("");
2137
2221
  const listRef = useRef4(null);
2138
2222
  const typingTimeoutRef = useRef4(null);
2139
2223
  const typingLine = useMemo11(() => {
@@ -2373,12 +2457,14 @@ export {
2373
2457
  StreemoClient,
2374
2458
  StreemoProvider,
2375
2459
  StreemoTheme,
2460
+ StreemoThemeProvider,
2376
2461
  Thread,
2377
2462
  TypingIndicator,
2378
2463
  UserStatus,
2379
2464
  VideoCallWidget,
2380
2465
  VideoTile,
2381
2466
  createServerTokenProvider,
2467
+ createTheme2 as createTheme,
2382
2468
  defaultApiBaseUrl,
2383
2469
  defaultWsBaseUrlFromApi,
2384
2470
  getVideoSDKConfig,
@@ -2392,6 +2478,7 @@ export {
2392
2478
  useParticipants,
2393
2479
  usePresence,
2394
2480
  useStreemoContext,
2481
+ useTheme,
2395
2482
  useTyping,
2396
2483
  useWebRTCCall
2397
2484
  };