UNPKG

mediasfu-reactjs

Version:

MediaSFU Prebuilt ReactJS SDK - Compatible with React 18 & 19, TypeScript & JavaScript

484 lines 21.5 kB
import React from "react"; import { ConnectSocketType, ShowAlert, ConnectLocalSocketType, RecordingParams, MeetingRoomParams, CreateMediaSFURoomOptions, JoinMediaSFURoomOptions, EventType } from "../../@types/types"; import { CreateRoomOnMediaSFUType, JoinRoomOnMediaSFUType } from "../../methods/utils/joinRoomOnMediaSFU"; import { Socket } from "socket.io-client"; export interface JoinLocalEventRoomParameters { eventID: string; userName: string; secureCode?: string; videoPreference?: string | null; audioPreference?: string | null; audioOutputPreference?: string | null; } export interface JoinLocalEventRoomOptions { joinData: JoinLocalEventRoomParameters; link?: string; } export interface CreateLocalRoomParameters { eventID: string; duration: number; capacity: number; userName: string; scheduledDate: Date; secureCode: string; waitRoom?: boolean; recordingParams?: RecordingParams; eventRoomParams?: MeetingRoomParams; videoPreference?: string | null; audioPreference?: string | null; audioOutputPreference?: string | null; mediasfuURL?: string; } export interface CreateLocalRoomOptions { createData: CreateLocalRoomParameters; link?: string; } export interface CreateJoinLocalRoomResponse { success: boolean; secret: string; reason?: string; url?: string; } export interface PreJoinPageParameters { imgSrc?: string; showAlert?: ShowAlert; updateIsLoadingModalVisible: (visible: boolean) => void; connectSocket: ConnectSocketType; connectLocalSocket?: ConnectLocalSocketType; updateSocket: (socket: Socket) => void; updateLocalSocket?: (socket: Socket) => void; updateValidated: (validated: boolean) => void; updateApiUserName: (userName: string) => void; updateApiToken: (token: string) => void; updateLink: (link: string) => void; updateRoomName: (roomName: string) => void; updateMember: (member: string) => void; updateAudioPreference?: (deviceId: string) => void; updateVideoPreference?: (deviceId: string) => void; updateAudioOutputPreference?: (deviceId: string) => void; updateIsDarkMode?: (isDarkMode: boolean) => void; updateEventType?: (eventType: EventType) => void; updateVirtualBackground?: (background: any) => void; updateCurrentFacingMode?: (facingMode: string) => void; updateKeepBackground?: (keep: boolean) => void; updateAppliedBackground?: (applied: boolean) => void; updateSelfieSegmentation?: (selfieSegmentation: any) => void; } export interface Credentials { apiUserName: string; apiKey: string; } export interface PreJoinPageOptions { localLink?: string; connectMediaSFU?: boolean; parameters: PreJoinPageParameters; credentials?: Credentials; returnUI?: boolean; noUIPreJoinOptions?: CreateMediaSFURoomOptions | JoinMediaSFURoomOptions; createMediaSFURoom?: CreateRoomOnMediaSFUType; joinMediaSFURoom?: JoinRoomOnMediaSFUType; containerProps?: React.HTMLAttributes<HTMLDivElement>; logoContainerProps?: React.HTMLAttributes<HTMLDivElement>; logoImageProps?: React.ImgHTMLAttributes<HTMLImageElement>; inputContainerProps?: React.HTMLAttributes<HTMLDivElement>; orContainerProps?: React.HTMLAttributes<HTMLDivElement>; orTextProps?: React.HTMLAttributes<HTMLSpanElement>; toggleContainerProps?: React.HTMLAttributes<HTMLDivElement>; toggleButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>; createButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>; joinButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>; createNameInputProps?: React.InputHTMLAttributes<HTMLInputElement>; durationInputProps?: React.InputHTMLAttributes<HTMLInputElement>; capacityInputProps?: React.InputHTMLAttributes<HTMLInputElement>; eventTypeSelectProps?: React.SelectHTMLAttributes<HTMLSelectElement>; joinNameInputProps?: React.InputHTMLAttributes<HTMLInputElement>; eventIdInputProps?: React.InputHTMLAttributes<HTMLInputElement>; errorProps?: React.HTMLAttributes<HTMLParagraphElement>; renderContainer?: (options: { defaultContainer: React.ReactNode; isCreateMode: boolean; error: string; }) => React.ReactNode; renderLogo?: (options: { defaultLogo: React.ReactNode; }) => React.ReactNode; renderCreateForm?: (options: { defaultContent: React.ReactNode; values: { name: string; duration: string; eventType: string; capacity: string; }; submit: () => Promise<void>; setValues: { onNameChange: React.ChangeEventHandler<HTMLInputElement>; onDurationChange: React.ChangeEventHandler<HTMLInputElement>; onEventTypeChange: React.ChangeEventHandler<HTMLSelectElement>; onCapacityChange: React.ChangeEventHandler<HTMLInputElement>; }; }) => React.ReactNode; renderJoinForm?: (options: { defaultContent: React.ReactNode; values: { name: string; eventID: string; }; submit: () => Promise<void>; setValues: { onNameChange: React.ChangeEventHandler<HTMLInputElement>; onEventIDChange: React.ChangeEventHandler<HTMLInputElement>; }; }) => React.ReactNode; renderToggle?: (options: { defaultToggle: React.ReactNode; isCreateMode: boolean; toggle: () => void; }) => React.ReactNode; renderError?: (options: { defaultError: React.ReactNode; error: string; }) => React.ReactNode; renderContent?: (options: { defaultContent: React.ReactNode; isCreateMode: boolean; error: string; }) => React.ReactNode; } export type PreJoinPageType = (options: PreJoinPageOptions) => React.JSX.Element; /** * PreJoinPage - A comprehensive pre-meeting entry page with dual create/join functionality. * * This component provides a complete pre-meeting interface allowing users to either create new * meeting rooms or join existing ones. It handles form validation, API integration, socket * connections, and supports both UI and headless (no-UI) modes for flexible integration. * * **Key Features:** * - **Dual Mode Operation**: Seamless toggle between room creation and joining interfaces * - **Room Creation**: Configure event type (chat/broadcast/webinar/conference), duration, capacity * - **Room Joining**: Enter event ID, username, and optional security code * - **API Integration**: Connects to MediaSFU or local server for room management * - **Socket Management**: Establishes WebSocket connections for real-time communication * - **Form Validation**: Comprehensive validation with user-friendly error messages * - **Headless Mode**: Support for no-UI operation with programmatic configuration * - **Credential Management**: Handles API authentication and token management * - **Loading States**: Integrated loading modal during connection/validation * - **Custom Styling**: 20+ HTML attribute props for complete visual customization * - **Render Hooks**: Six custom render functions for logo, forms, toggle, errors, and container * - **Media Preferences**: Configure video, audio, and audio output settings before joining * - **Local/Remote Servers**: Flexible connection to MediaSFU cloud or local instances * - **Scheduled Events**: Support for scheduled meeting times with date/time pickers * - **Security Features**: Optional secure codes and waiting room functionality * - **Recording Configuration**: Pre-configure recording parameters and event room settings * - **Responsive Design**: Mobile-friendly interface with touch-optimized controls * * @component * * @param {PreJoinPageOptions} props - Configuration options for PreJoinPage * @param {PreJoinPageParameters} props.parameters - Core parameters for room operations and state management * @param {ShowAlert} [props.parameters.showAlert] - Function to display alert messages to users * @param {() => void} props.parameters.updateIsLoadingModalVisible - Function to toggle loading modal visibility * @param {ConnectSocketType} [props.parameters.connectSocket] - Function to establish MediaSFU socket connection * @param {ConnectLocalSocketType} [props.parameters.connectLocalSocket] - Function to establish local server socket connection * @param {(socket: Socket) => void} props.parameters.updateSocket - Function to update the active socket instance * @param {(socket: Socket) => void} [props.parameters.updateLocalSocket] - Function to update the local socket instance * @param {() => void} props.parameters.updateValidated - Function to mark connection as validated * @param {(userName: string) => void} props.parameters.updateApiUserName - Function to store API username * @param {(token: string) => void} props.parameters.updateApiToken - Function to store API authentication token * @param {(link: string) => void} props.parameters.updateLink - Function to store meeting link * @param {(roomName: string) => void} props.parameters.updateRoomName - Function to store room name * @param {(member: string) => void} props.parameters.updateMember - Function to store member name * @param {string} [props.parameters.imgSrc] - Logo image source URL for branding * @param {Credentials} [props.credentials=user_credentials] - API credentials (apiUserName and apiKey) * @param {boolean} [props.returnUI=false] - Flag to enable UI mode (true) or headless mode (false) * @param {CreateMediaSFURoomOptions | JoinMediaSFURoomOptions} [props.noUIPreJoinOptions] - Configuration for headless mode operation * @param {string} [props.localLink=""] - URL for local server connection (empty string for MediaSFU cloud) * @param {boolean} [props.connectMediaSFU=true] - Flag to enable MediaSFU cloud connection * @param {CreateRoomOnMediaSFUType} [props.createMediaSFURoom=createRoomOnMediaSFU] - Function to create room on MediaSFU * @param {JoinRoomOnMediaSFUType} [props.joinMediaSFURoom=joinRoomOnMediaSFU] - Function to join room on MediaSFU * @param {React.HTMLAttributes<HTMLDivElement>} [props.containerProps] - HTML attributes for main container * @param {React.HTMLAttributes<HTMLDivElement>} [props.logoContainerProps] - HTML attributes for logo container * @param {React.ImgHTMLAttributes<HTMLImageElement>} [props.logoImageProps] - HTML attributes for logo image * @param {React.HTMLAttributes<HTMLDivElement>} [props.inputContainerProps] - HTML attributes for input fields container * @param {React.HTMLAttributes<HTMLDivElement>} [props.orContainerProps] - HTML attributes for "OR" separator container * @param {React.HTMLAttributes<HTMLSpanElement>} [props.orTextProps] - HTML attributes for "OR" text element * @param {React.HTMLAttributes<HTMLDivElement>} [props.toggleContainerProps] - HTML attributes for mode toggle container * @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.toggleButtonProps] - HTML attributes for toggle button * @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.createButtonProps] - HTML attributes for create room button * @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.joinButtonProps] - HTML attributes for join room button * @param {React.InputHTMLAttributes<HTMLInputElement>} [props.createNameInputProps] - HTML attributes for create mode name input * @param {React.InputHTMLAttributes<HTMLInputElement>} [props.durationInputProps] - HTML attributes for duration input * @param {React.InputHTMLAttributes<HTMLInputElement>} [props.capacityInputProps] - HTML attributes for capacity input * @param {React.SelectHTMLAttributes<HTMLSelectElement>} [props.eventTypeSelectProps] - HTML attributes for event type select * @param {React.InputHTMLAttributes<HTMLInputElement>} [props.joinNameInputProps] - HTML attributes for join mode name input * @param {React.InputHTMLAttributes<HTMLInputElement>} [props.eventIdInputProps] - HTML attributes for event ID input * @param {React.HTMLAttributes<HTMLDivElement>} [props.errorProps] - HTML attributes for error message container * @param {(options: {defaultContainer: React.ReactNode}) => React.ReactNode} [props.renderContainer] - Custom render function for main container * @param {(options: {defaultLogo: React.ReactNode; imgSrc?: string}) => React.ReactNode} [props.renderLogo] - Custom render function for logo * @param {(options: {defaultForm: React.ReactNode}) => React.ReactNode} [props.renderCreateForm] - Custom render function for create room form * @param {(options: {defaultForm: React.ReactNode}) => React.ReactNode} [props.renderJoinForm] - Custom render function for join room form * @param {(options: {defaultToggle: React.ReactNode; isCreateMode: boolean; toggle: () => void}) => React.ReactNode} [props.renderToggle] - Custom render function for mode toggle * @param {(options: {defaultError: React.ReactNode; error: string}) => React.ReactNode} [props.renderError] - Custom render function for error display * @param {(options: {defaultContent: React.ReactNode; isCreateMode: boolean; error: string}) => React.ReactNode} [props.renderContent] - Custom render function for entire content area * * @returns {React.JSX.Element} The rendered pre-join page component * * @example * // Basic usage with UI mode * ```tsx * import React from 'react'; * import { PreJoinPage } from 'mediasfu-reactjs'; * * const BasicPreJoin = () => { * const handleAlert = (message: string) => { * alert(message); * }; * * return ( * <PreJoinPage * credentials={{ * apiUserName: 'user123', * apiKey: 'your-api-key' * }} * returnUI={true} * parameters={{ * showAlert: handleAlert, * updateIsLoadingModalVisible: (visible) => console.log('Loading:', visible), * connectSocket: async ({ socket, apiUserName, apiToken }) => { * // Socket connection logic * }, * updateSocket: (socket) => console.log('Socket updated'), * updateValidated: () => console.log('Validated'), * updateApiUserName: (name) => console.log('API User:', name), * updateApiToken: (token) => console.log('Token set'), * updateLink: (link) => console.log('Link:', link), * updateRoomName: (room) => console.log('Room:', room), * updateMember: (member) => console.log('Member:', member), * imgSrc: 'https://example.com/logo.png' * }} * connectMediaSFU={true} * /> * ); * }; * ``` * * @example * // Custom styled with branding and validation * ```tsx * import React, { useState } from 'react'; * import { PreJoinPage } from 'mediasfu-reactjs'; * * const BrandedPreJoin = () => { * const [isLoading, setIsLoading] = useState(false); * * return ( * <PreJoinPage * credentials={{ * apiUserName: 'company_user', * apiKey: 'company_api_key' * }} * returnUI={true} * parameters={{ * showAlert: (message) => { * console.log('Alert:', message); * }, * updateIsLoadingModalVisible: setIsLoading, * connectSocket: async (options) => {}, * updateSocket: (socket) => {}, * updateValidated: () => {}, * updateApiUserName: (name) => {}, * updateApiToken: (token) => {}, * updateLink: (link) => {}, * updateRoomName: (room) => {}, * updateMember: (member) => {}, * imgSrc: 'https://company.com/logo.svg' * }} * containerProps={{ * style: { * background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', * minHeight: '100vh', * fontFamily: "'Inter', sans-serif" * } * }} * createButtonProps={{ * style: { * backgroundColor: '#10b981', * padding: '14px 28px', * borderRadius: '8px', * fontSize: '16px', * fontWeight: '600', * border: 'none', * cursor: 'pointer', * transition: 'all 0.3s' * } * }} * joinButtonProps={{ * style: { * backgroundColor: '#3b82f6', * padding: '14px 28px', * borderRadius: '8px', * fontSize: '16px', * fontWeight: '600', * border: 'none', * cursor: 'pointer' * } * }} * renderLogo={({ imgSrc }) => ( * <div style={{ textAlign: 'center', marginBottom: '40px' }}> * <img src={imgSrc} alt="Company Logo" style={{ width: '200px' }} /> * <h1 style={{ color: 'white', marginTop: '20px' }}>Welcome to Our Platform</h1> * </div> * )} * /> * ); * }; * ``` * * @example * // Analytics tracking with event monitoring * ```tsx * import React, { useEffect } from 'react'; * import { PreJoinPage } from 'mediasfu-reactjs'; * * const AnalyticsPreJoin = () => { * useEffect(() => { * analytics.page('Pre-Join Page Viewed'); * }, []); * * return ( * <PreJoinPage * credentials={{ * apiUserName: 'analytics_user', * apiKey: 'analytics_key' * }} * returnUI={true} * parameters={{ * showAlert: (message) => { * analytics.track('Alert Shown', { message }); * alert(message); * }, * updateIsLoadingModalVisible: (visible) => { * analytics.track('Loading State Changed', { visible }); * }, * connectSocket: async (options) => { * analytics.track('Socket Connection Initiated', { * apiUserName: options.apiUserName * }); * }, * updateValidated: () => { * analytics.track('Connection Validated'); * }, * updateRoomName: (room) => { * analytics.track('Room Entered', { roomName: room }); * }, * updateSocket: (socket) => {}, * updateApiUserName: (name) => {}, * updateApiToken: (token) => {}, * updateLink: (link) => {}, * updateMember: (member) => {} * }} * renderToggle={({ defaultToggle, isCreateMode, toggle }) => ( * <div onClick={() => { * analytics.track('Mode Toggled', { * from: isCreateMode ? 'create' : 'join', * to: isCreateMode ? 'join' : 'create' * }); * toggle(); * }}> * {defaultToggle} * </div> * )} * createMediaSFURoom={async (options) => { * analytics.track('Room Creation Attempted', { * eventType: options.eventType, * duration: options.duration, * capacity: options.capacity * }); * const result = await createRoomOnMediaSFU(options); * analytics.track('Room Created Successfully', { * eventType: options.eventType * }); * return result; * }} * joinMediaSFURoom={async (options) => { * analytics.track('Room Join Attempted', { * eventID: options.eventID * }); * const result = await joinRoomOnMediaSFU(options); * analytics.track('Room Joined Successfully'); * return result; * }} * /> * ); * }; * ``` * * @example * // Integration with MediasfuGeneric using uiOverrides * ```tsx * import React, { useState } from 'react'; * import { MediasfuGeneric, PreJoinPage } from 'mediasfu-reactjs'; * * const CustomPreJoin = (props) => ( * <PreJoinPage * {...props} * renderContent={({ defaultContent, isCreateMode, error }) => ( * <div className="custom-prejoin-wrapper"> * <div className="welcome-banner"> * <h2>🎥 {isCreateMode ? 'Start Your Meeting' : 'Join the Meeting'}</h2> * <p>Connect with your team in seconds</p> * </div> * {error && ( * <div className="error-banner" style={{ * backgroundColor: '#fee', * color: '#c00', * padding: '12px', * borderRadius: '6px', * marginBottom: '20px' * }}> * ⚠️ {error} * </div> * )} * {defaultContent} * <div className="help-section"> * <a href="/help">Need help?</a> * <span> | </span> * <a href="/privacy">Privacy Policy</a> * </div> * </div> * )} * renderCreateForm={({ defaultForm }) => ( * <div className="enhanced-create-form"> * <div className="form-header"> * <h3>Create New Room</h3> * <p>Set up your meeting parameters</p> * </div> * {defaultForm} * <div className="form-footer"> * <small>🔒 Your meeting will be secure and encrypted</small> * </div> * </div> * )} * /> * ); * * const App = () => { * const [credentials] = useState({ * apiUserName: 'user123', * apiKey: 'your-api-key' * }); * * return ( * <MediasfuGeneric * credentials={credentials} * uiOverrides={{ * PreJoinPage: CustomPreJoin * }} * /> * ); * }; * ``` */ declare const PreJoinPage: React.FC<PreJoinPageOptions>; export default PreJoinPage; //# sourceMappingURL=PreJoinPage.d.ts.map