@appsocom/react 0.0.0-stage → 0.5.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Appsotech Limited
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,33 @@
1
- # Temporary Holding Version
1
+ # @appsocom/react
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ React hooks and components for [Appsocom Live](https://live.appsocom.com) video calls: a complete call screen in one component, or the pieces and hooks to build your own.
4
+
5
+ ```bash
6
+ npm install @appsocom/react @appsocom/client
7
+ ```
8
+
9
+ ```tsx
10
+ import { VideoConference } from "@appsocom/react";
11
+ import "@appsocom/react/styles.css";
12
+
13
+ <VideoConference url="https://api.appsocom.dev" token={token} onLeft={(reason) => console.log(reason)} />
14
+ ```
15
+
16
+ `VideoConference` shows a pre-join screen (camera preview, mic level, device pickers, blur and noise suppression), then the grid, controls and chat. Use `prejoin={false}` to join straight away, `chat={false}` to hide chat, and `layout="grid" | "focus"` to pick a layout.
17
+
18
+ Build your own from `SfuRoom`, `VideoGrid`, `ParticipantTile`, `ControlBar`, `DeviceSelect`, `PreJoin`, `ChatPanel`, `ConnectionBanner` and `VideoTrack`, with hooks such as `useParticipants`, `useLocalParticipant`, `useActiveSpeakers`, `useChat` and `useRaisedHands`.
19
+
20
+ ```tsx
21
+ <SfuRoom url={url} token={token}>
22
+ <MyGrid />
23
+ </SfuRoom>
24
+
25
+ function MyGrid() {
26
+ const participants = useParticipants();
27
+ return participants.map((p) => <ParticipantTile key={p.id} participant={p} />);
28
+ }
29
+ ```
30
+
31
+ Guide: [UI kits](https://docs.appsocom.dev/ui-kits)
32
+
33
+ Docs: [docs.appsocom.dev](https://docs.appsocom.dev) · License: MIT
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Ready-made web UI for sfukit: video grid, participant tiles, control bar,
3
+ * device pickers, prejoin screen and an all-in-one <VideoConference>.
4
+ * Styles: import "@appsocom/react/styles.css" (theme with CSS variables), or
5
+ * style the `sfk-*` classes yourself.
6
+ */
7
+ import { type CSSProperties, type ReactNode } from "react";
8
+ import { type JoinOptions, type Room } from "@appsocom/client";
9
+ import type { LessonState, Participant } from "@appsocom/protocol";
10
+ declare const paths: Record<string, string>;
11
+ export declare function Icon({ name, size }: {
12
+ name: keyof typeof paths | string;
13
+ size?: number;
14
+ }): import("react").JSX.Element;
15
+ /** A <video> showing one track. Muted by default (audio is played by the room). */
16
+ export declare function VideoTrack({ track, mirror, fit, className, style, }: {
17
+ track: MediaStreamTrack | null | undefined;
18
+ mirror?: boolean;
19
+ fit?: "cover" | "contain";
20
+ className?: string;
21
+ style?: CSSProperties;
22
+ }): import("react").JSX.Element;
23
+ /** Live audio level of a track, 0..1 (for mic meters). */
24
+ export declare function useAudioLevel(track: MediaStreamTrack | null | undefined): number;
25
+ /** Cameras, mics or speakers, kept up to date as devices are plugged in. */
26
+ export declare function useMediaDevices(kind: MediaDeviceKind): MediaDeviceInfo[];
27
+ export interface ParticipantTileProps {
28
+ /** A remote participant. Leave out (with `local`) for your own tile. */
29
+ participant?: Participant;
30
+ local?: boolean;
31
+ /** Camera (default) or their screen share. */
32
+ source?: "camera" | "screen";
33
+ /** Moderators get a menu on remote tiles (mute, stop camera, let present, remove). Default true. */
34
+ moderation?: boolean;
35
+ /** Receive this video only while the tile is on screen. Default true. */
36
+ subscribeWhenVisible?: boolean;
37
+ className?: string;
38
+ children?: ReactNode;
39
+ }
40
+ /** One participant: video (or initials), name, mic state, speaking ring, quality, role, hand. */
41
+ export declare function ParticipantTile({ participant, local, source, moderation, subscribeWhenVisible, className, children, }: ParticipantTileProps): import("react").JSX.Element | null;
42
+ export interface VideoGridProps {
43
+ /** "auto" (default): spotlight a screen share or the moderator's spotlight, otherwise a grid. "speaker": active speaker large. */
44
+ layout?: "auto" | "grid" | "speaker";
45
+ /** Show your own tile. Default true. */
46
+ includeLocal?: boolean;
47
+ /** Receive video only for tiles on screen. Default true. */
48
+ subscribeWhenVisible?: boolean;
49
+ className?: string;
50
+ }
51
+ /** Everyone's video, laid out to fit. Screen shares and spotlighted people get the big spot. */
52
+ export declare function VideoGrid({ layout, includeLocal, subscribeWhenVisible, className }: VideoGridProps): import("react").JSX.Element;
53
+ /**
54
+ * A <select> of cameras, mics or speakers. Inside a room, picking one switches
55
+ * the room's device; outside (prejoin), pass value/onChange.
56
+ */
57
+ export declare function DeviceSelect({ kind, value, onChange, label, className, }: {
58
+ kind: MediaDeviceKind;
59
+ value?: string;
60
+ onChange?: (deviceId: string, device: MediaDeviceInfo | undefined) => void;
61
+ label?: string;
62
+ className?: string;
63
+ }): import("react").JSX.Element | null;
64
+ export interface ControlBarProps {
65
+ /** Which buttons to show. All default to true (shown when your permissions allow). */
66
+ controls?: Partial<Record<"mic" | "camera" | "screen" | "blur" | "noise" | "devices" | "hand" | "chat" | "leave", boolean>>;
67
+ /** Called after leaving. */
68
+ onLeave?: () => void;
69
+ /** Called when the chat button is pressed (if you show a chat panel). */
70
+ onToggleChat?: () => void;
71
+ className?: string;
72
+ children?: ReactNode;
73
+ }
74
+ /** Mic, camera, screen share, blur, noise suppression, devices, raise hand, leave. */
75
+ export declare function ControlBar({ controls, onLeave, onToggleChat, className, children }: ControlBarProps): import("react").JSX.Element;
76
+ /** Data-saver picker (rendered inside the ControlBar's devices popover too). */
77
+ export declare function DataSaverSelect({ label, className }: {
78
+ label?: string;
79
+ className?: string;
80
+ }): import("react").JSX.Element | null;
81
+ /** "12.4 MB used · about 85 MB per hour". Renders nothing until there's a reading. */
82
+ export declare function DataUsageMeter({ className }: {
83
+ className?: string;
84
+ }): import("react").JSX.Element | null;
85
+ /** "Reconnecting…" banner while the room or media connection is down, or a note while on audio fallback. */
86
+ export declare function ConnectionBanner(): import("react").JSX.Element | null;
87
+ /** Simple chat panel (room.chat / room.sendChat). */
88
+ export declare function ChatPanel({ className }: {
89
+ className?: string;
90
+ }): import("react").JSX.Element;
91
+ export interface PreJoinChoices {
92
+ name: string;
93
+ audio: boolean;
94
+ video: boolean;
95
+ audioDeviceId?: string;
96
+ videoDeviceId?: string;
97
+ backgroundBlur: boolean;
98
+ noiseSuppression: boolean;
99
+ }
100
+ export interface PreJoinProps {
101
+ onSubmit: (choices: PreJoinChoices) => void;
102
+ /** Ask for a display name. Default false (names usually come from the token). */
103
+ askName?: boolean;
104
+ defaults?: Partial<PreJoinChoices>;
105
+ joinLabel?: string;
106
+ /** Show blur / noise suppression toggles when supported. Default true. */
107
+ showEffects?: boolean;
108
+ className?: string;
109
+ }
110
+ /** Camera preview, mic level, device pickers and on/off toggles before joining. */
111
+ export declare function PreJoin({ onSubmit, askName, defaults, joinLabel, showEffects, className }: PreJoinProps): import("react").JSX.Element;
112
+ export interface SfuRoomProps extends Omit<JoinOptions, "url" | "token"> {
113
+ url: string;
114
+ token: string;
115
+ /** Device choices from <PreJoin> (applied once joined). */
116
+ audioDeviceId?: string;
117
+ videoDeviceId?: string;
118
+ audioOutputDeviceId?: string;
119
+ /** Shown while joining. */
120
+ connecting?: ReactNode;
121
+ /** Shown if joining fails (default: the error message). */
122
+ renderError?: (error: Error) => ReactNode;
123
+ onJoined?: (room: Room) => void;
124
+ onLeft?: (reason: string) => void;
125
+ onError?: (error: Error) => void;
126
+ children?: ReactNode;
127
+ }
128
+ /** Joins a room while mounted and provides it to the hooks/components inside. */
129
+ export declare function SfuRoom(props: SfuRoomProps): import("react").JSX.Element;
130
+ export interface VideoConferenceProps extends Omit<SfuRoomProps, "children"> {
131
+ /** Show <PreJoin> first. Default true. */
132
+ prejoin?: boolean;
133
+ /** Show a chat panel toggle. Default true. */
134
+ chat?: boolean;
135
+ layout?: VideoGridProps["layout"];
136
+ className?: string;
137
+ }
138
+ /** The whole call UI in one component: prejoin → grid + controls + chat. */
139
+ export declare function VideoConference({ prejoin, chat, layout, className, ...roomProps }: VideoConferenceProps): import("react").JSX.Element;
140
+ /** A readable version of simple TeX for the board (x^2 → x², \\frac{a}{b} → a⁄b). */
141
+ export declare function texToText(tex: string): string;
142
+ /** The AI teacher's whiteboard (16:10, scales to its width). */
143
+ export declare function LessonWhiteboard({ lesson, className }: {
144
+ lesson: LessonState;
145
+ className?: string;
146
+ }): import("react").JSX.Element;
147
+ /** The current slide of an AI lesson (nothing when none is shown). */
148
+ export declare function LessonSlideView({ lesson, className }: {
149
+ lesson: LessonState;
150
+ className?: string;
151
+ }): import("react").JSX.Element | null;
152
+ /** A one-line status for an AI lesson: section, who's speaking, timer. */
153
+ export declare function LessonStatusBar({ lesson, names }: {
154
+ lesson: LessonState;
155
+ names?: (userId: string) => string;
156
+ }): import("react").JSX.Element;
157
+ export {};