mediasfu-reactjs
Version:
MediaSFU Prebuilt ReactJS SDK - Compatible with React 18 & 19, TypeScript & JavaScript
463 lines • 23.5 kB
TypeScript
import React from "react";
import { Socket } from "socket.io-client";
import { CaptureCanvasStreamParameters, CaptureCanvasStreamType, EventType, OnScreenChangesParameters, OnScreenChangesType, Participant, PrepopulateUserMediaParameters, PrepopulateUserMediaType, RePortParameters, RePortType, ShowAlert, WhiteboardUser } from "../../@types/types";
import { ModalRenderMode } from '../menuComponents/MenuModal';
export interface ConfigureWhiteboardModalParameters extends OnScreenChangesParameters, CaptureCanvasStreamParameters, PrepopulateUserMediaParameters, RePortParameters {
participants: Participant[];
showAlert?: ShowAlert;
socket: Socket;
itemPageLimit: number;
islevel: string;
roomName: string;
eventType: EventType;
shareScreenStarted: boolean;
shared: boolean;
breakOutRoomStarted: boolean;
breakOutRoomEnded: boolean;
recordStarted: boolean;
recordResumed: boolean;
recordPaused: boolean;
recordStopped: boolean;
recordingMediaOptions: string;
canStartWhiteboard: boolean;
whiteboardStarted: boolean;
whiteboardEnded: boolean;
hostLabel: string;
updateWhiteboardStarted: (started: boolean) => void;
updateWhiteboardEnded: (ended: boolean) => void;
updateWhiteboardUsers: (users: WhiteboardUser[]) => void;
updateCanStartWhiteboard: (canStart: boolean) => void;
updateIsConfigureWhiteboardModalVisible: (isVisible: boolean) => void;
onScreenChanges: OnScreenChangesType;
captureCanvasStream: CaptureCanvasStreamType;
prepopulateUserMedia: PrepopulateUserMediaType;
rePort: RePortType;
getUpdatedAllParams: () => ConfigureWhiteboardModalParameters;
[key: string]: any;
}
export interface ConfigureWhiteboardModalOptions {
isVisible: boolean;
onConfigureWhiteboardClose: () => void;
parameters: ConfigureWhiteboardModalParameters;
backgroundColor?: string;
position?: string;
title?: React.ReactNode;
overlayProps?: React.HTMLAttributes<HTMLDivElement>;
contentProps?: React.HTMLAttributes<HTMLDivElement>;
headerProps?: React.HTMLAttributes<HTMLDivElement>;
titleProps?: React.HTMLAttributes<HTMLHeadingElement>;
closeButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
closeIconComponent?: React.ReactNode;
headerDividerProps?: React.HTMLAttributes<HTMLHRElement>;
bodyProps?: React.HTMLAttributes<HTMLDivElement>;
listsWrapperProps?: React.HTMLAttributes<HTMLDivElement>;
assignedSectionProps?: React.HTMLAttributes<HTMLDivElement>;
pendingSectionProps?: React.HTMLAttributes<HTMLDivElement>;
assignedTitleProps?: React.HTMLAttributes<HTMLHeadingElement>;
pendingTitleProps?: React.HTMLAttributes<HTMLHeadingElement>;
assignedListProps?: React.HTMLAttributes<HTMLUListElement>;
pendingListProps?: React.HTMLAttributes<HTMLUListElement>;
assignedItemProps?: React.LiHTMLAttributes<HTMLLIElement>;
pendingItemProps?: React.LiHTMLAttributes<HTMLLIElement>;
assignedActionButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
pendingActionButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
footerProps?: React.HTMLAttributes<HTMLDivElement>;
saveButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
actionsWrapperProps?: React.HTMLAttributes<HTMLDivElement>;
startButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
updateButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
stopButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
sectionDividerProps?: React.HTMLAttributes<HTMLHRElement>;
assignedTitle?: React.ReactNode;
pendingTitle?: React.ReactNode;
saveButtonLabel?: React.ReactNode;
startButtonLabel?: React.ReactNode;
updateButtonLabel?: React.ReactNode;
stopButtonLabel?: React.ReactNode;
addIcon?: React.ReactNode;
removeIcon?: React.ReactNode;
saveIcon?: React.ReactNode;
startIcon?: React.ReactNode;
updateIcon?: React.ReactNode;
stopIcon?: React.ReactNode;
emptyAssignedState?: React.ReactNode | ((context: {
participants: Participant[];
}) => React.ReactNode);
emptyPendingState?: React.ReactNode | ((context: {
participants: Participant[];
}) => React.ReactNode);
renderTitle?: (options: {
defaultTitle: React.ReactNode;
}) => React.ReactNode;
renderHeader?: (options: {
defaultHeader: React.ReactNode;
}) => React.ReactNode;
renderLists?: (options: {
defaultLists: React.ReactNode;
assignedParticipants: Participant[];
pendingParticipants: Participant[];
}) => React.ReactNode;
renderAssignedList?: (options: {
defaultAssignedList: React.ReactNode;
participants: Participant[];
removeParticipant: (participant: Participant) => void;
}) => React.ReactNode;
renderPendingList?: (options: {
defaultPendingList: React.ReactNode;
participants: Participant[];
addParticipant: (participant: Participant) => void;
}) => React.ReactNode;
renderAssignedItem?: (options: {
defaultItem: React.ReactNode;
participant: Participant;
remove: () => void;
index: number;
}) => React.ReactNode;
renderPendingItem?: (options: {
defaultItem: React.ReactNode;
participant: Participant;
add: () => void;
index: number;
}) => React.ReactNode;
renderFooter?: (options: {
defaultFooter: React.ReactNode;
isEditing: boolean;
canStartWhiteboard: boolean;
}) => React.ReactNode;
renderActions?: (options: {
defaultActions: React.ReactNode;
isEditing: boolean;
canStartWhiteboard: boolean;
whiteboardStarted: boolean;
whiteboardEnded: boolean;
}) => React.ReactNode;
renderBody?: (options: {
defaultBody: React.ReactNode;
isEditing: boolean;
assignedParticipants: Participant[];
pendingParticipants: Participant[];
}) => React.ReactNode;
renderContent?: (options: {
defaultContent: React.ReactNode;
isEditing: boolean;
canStartWhiteboard: boolean;
}) => React.ReactNode;
/** Theme control - whether dark mode is active */
isDarkMode?: boolean;
/** Enable glassmorphism effects (modern UI) */
enableGlassmorphism?: boolean;
/** Render mode: modal (default overlay), sidebar (inline for desktop), inline (no wrapper) */
renderMode?: ModalRenderMode;
}
export type ConfigureWhiteboardModalType = (options: ConfigureWhiteboardModalOptions) => React.JSX.Element;
/**
* ConfigureWhiteboardModal - A comprehensive modal for configuring and managing collaborative whiteboard sessions.
*
* This component provides a sophisticated interface for host-controlled whiteboard management, including
* participant selection, access control, session lifecycle management, and compatibility checks with other
* session features like screen sharing and recording.
*
* **Key Features:**
* - **Participant Management**: Dual-list interface for assigning/removing whiteboard access from participants
* - **Session Control**: Start, stop, and update whiteboard sessions with socket-based synchronization
* - **Access Validation**: Automatic checks for host permissions and session state compatibility
* - **Screen Share Integration**: Validates compatibility with active screen sharing sessions
* - **Recording Integration**: Ensures whiteboard works correctly with recording states (started, paused, resumed, stopped)
* - **Breakout Room Awareness**: Handles whiteboard availability during breakout room sessions
* - **Canvas Stream Management**: Integrates with captureCanvasStream for whiteboard video streaming
* - **User Media Sync**: Prepopulates user media when whiteboard state changes via prepopulateUserMedia
* - **Pagination Support**: Handles large participant lists with configurable page limits
* - **Real-time Updates**: Socket-based synchronization for whiteboard state across all participants
* - **Granular Customization**: Extensive HTML attributes and render hooks for all UI elements
* - **Empty States**: Custom messages for empty assigned/pending participant lists
* - **Responsive Layout**: Flexible positioning and responsive design
*
* @component
*
* @param {ConfigureWhiteboardModalOptions} props - Configuration options for ConfigureWhiteboardModal
* @param {boolean} props.isVisible - Controls modal visibility
* @param {() => void} props.onConfigureWhiteboardClose - Callback function invoked when modal is closed
* @param {ConfigureWhiteboardModalParameters} props.parameters - Comprehensive parameters object containing:
* - **State Properties**: participants, islevel, roomName, eventType, shareScreenStarted, shared, breakOutRoomStarted, breakOutRoomEnded, recordStarted, recordResumed, recordPaused, recordStopped, recordingMediaOptions, canStartWhiteboard, whiteboardStarted, whiteboardEnded, hostLabel
* - **Configuration**: socket, itemPageLimit
* - **Update Functions**: updateWhiteboardStarted, updateWhiteboardEnded, updateWhiteboardUsers, updateCanStartWhiteboard, updateIsConfigureWhiteboardModalVisible
* - **MediaSFU Functions**: onScreenChanges, captureCanvasStream, prepopulateUserMedia, rePort
* - **Optional**: showAlert (for displaying validation messages)
* @param {string} [props.backgroundColor="#83c0e9"] - Background color for modal content
* @param {string} [props.position="topRight"] - Modal screen position
* @param {React.ReactNode} [props.title] - Custom title content (default: "Configure Whiteboard")
* @param {React.HTMLAttributes<HTMLDivElement>} [props.overlayProps] - HTML attributes for overlay container
* @param {React.HTMLAttributes<HTMLDivElement>} [props.contentProps] - HTML attributes for content wrapper
* @param {React.HTMLAttributes<HTMLDivElement>} [props.headerProps] - HTML attributes for header section
* @param {React.HTMLAttributes<HTMLHeadingElement>} [props.titleProps] - HTML attributes for title element
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.closeButtonProps] - HTML attributes for close button
* @param {React.ReactNode} [props.closeIconComponent] - Custom close icon component
* @param {React.HTMLAttributes<HTMLHRElement>} [props.headerDividerProps] - HTML attributes for header divider
* @param {React.HTMLAttributes<HTMLDivElement>} [props.bodyProps] - HTML attributes for body section
* @param {React.HTMLAttributes<HTMLDivElement>} [props.listsWrapperProps] - HTML attributes for lists container
* @param {React.HTMLAttributes<HTMLDivElement>} [props.assignedSectionProps] - HTML attributes for assigned participants section
* @param {React.HTMLAttributes<HTMLDivElement>} [props.pendingSectionProps] - HTML attributes for pending participants section
* @param {React.HTMLAttributes<HTMLHeadingElement>} [props.assignedTitleProps] - HTML attributes for assigned list title
* @param {React.HTMLAttributes<HTMLHeadingElement>} [props.pendingTitleProps] - HTML attributes for pending list title
* @param {React.HTMLAttributes<HTMLUListElement>} [props.assignedListProps] - HTML attributes for assigned list
* @param {React.HTMLAttributes<HTMLUListElement>} [props.pendingListProps] - HTML attributes for pending list
* @param {React.LiHTMLAttributes<HTMLLIElement>} [props.assignedItemProps] - HTML attributes for assigned list items
* @param {React.LiHTMLAttributes<HTMLLIElement>} [props.pendingItemProps] - HTML attributes for pending list items
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.assignedActionButtonProps] - HTML attributes for remove buttons
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.pendingActionButtonProps] - HTML attributes for add buttons
* @param {React.HTMLAttributes<HTMLDivElement>} [props.footerProps] - HTML attributes for footer section
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.saveButtonProps] - HTML attributes for save button
* @param {React.HTMLAttributes<HTMLDivElement>} [props.actionsWrapperProps] - HTML attributes for actions wrapper
* @param {React.ButtonHTMLAttributes<HTMLButtonButton>} [props.startButtonProps] - HTML attributes for start button
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.updateButtonProps] - HTML attributes for update button
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.stopButtonProps] - HTML attributes for stop button
* @param {React.HTMLAttributes<HTMLHRElement>} [props.sectionDividerProps] - HTML attributes for section divider
* @param {React.ReactNode} [props.assignedTitle] - Custom title for assigned participants section
* @param {React.ReactNode} [props.pendingTitle] - Custom title for pending participants section
* @param {React.ReactNode} [props.saveButtonLabel] - Custom label for save button
* @param {React.ReactNode} [props.startButtonLabel] - Custom label for start button
* @param {React.ReactNode} [props.updateButtonLabel] - Custom label for update button
* @param {React.ReactNode} [props.stopButtonLabel] - Custom label for stop button
* @param {React.ReactNode} [props.addIcon] - Custom icon for add action buttons
* @param {React.ReactNode} [props.removeIcon] - Custom icon for remove action buttons
* @param {React.ReactNode} [props.saveIcon] - Custom icon for save button
* @param {React.ReactNode} [props.startIcon] - Custom icon for start button
* @param {React.ReactNode} [props.updateIcon] - Custom icon for update button
* @param {React.ReactNode} [props.stopIcon] - Custom icon for stop button
* @param {React.ReactNode | ((context: {participants: Participant[]}) => React.ReactNode)} [props.emptyAssignedState] - Content shown when no participants assigned
* @param {React.ReactNode | ((context: {participants: Participant[]}) => React.ReactNode)} [props.emptyPendingState] - Content shown when no participants pending
* @param {(options: {defaultTitle: React.ReactNode}) => React.ReactNode} [props.renderTitle] - Custom render function for title
* @param {(options: {defaultHeader: React.ReactNode}) => React.ReactNode} [props.renderHeader] - Custom render function for header
* @param {(options: {defaultLists: React.ReactNode; assignedParticipants: Participant[]; pendingParticipants: Participant[]}) => React.ReactNode} [props.renderLists] - Custom render function for participant lists
* @param {(options: {defaultAssignedList: React.ReactNode; participants: Participant[]; removeParticipant: (p: Participant) => void}) => React.ReactNode} [props.renderAssignedList] - Custom render function for assigned list
* @param {(options: {defaultPendingList: React.ReactNode; participants: Participant[]; addParticipant: (p: Participant) => void}) => React.ReactNode} [props.renderPendingList] - Custom render function for pending list
* @param {(options: {defaultItem: React.ReactNode; participant: Participant; remove: () => void; index: number}) => React.ReactNode} [props.renderAssignedItem] - Custom render function for assigned items
* @param {(options: {defaultItem: React.ReactNode; participant: Participant; add: () => void; index: number}) => React.ReactNode} [props.renderPendingItem] - Custom render function for pending items
* @param {(options: {defaultFooter: React.ReactNode; isEditing: boolean; canStartWhiteboard: boolean}) => React.ReactNode} [props.renderFooter] - Custom render function for footer
* @param {(options: {defaultActions: React.ReactNode; isEditing: boolean; canStartWhiteboard: boolean; whiteboardStarted: boolean; whiteboardEnded: boolean}) => React.ReactNode} [props.renderActions] - Custom render function for action buttons
* @param {(options: {defaultBody: React.ReactNode; isEditing: boolean; assignedParticipants: Participant[]; pendingParticipants: Participant[]}) => React.ReactNode} [props.renderBody] - Custom render function for body
* @param {(options: {defaultContent: React.ReactNode; isEditing: boolean; canStartWhiteboard: boolean}) => React.ReactNode} [props.renderContent] - Custom render function for entire content
*
* @returns {React.JSX.Element} The rendered ConfigureWhiteboardModal component
*
* @example
* // Basic usage for whiteboard configuration
* ```tsx
* import React, { useState } from 'react';
* import { ConfigureWhiteboardModal } from 'mediasfu-reactjs';
* import { io } from 'socket.io-client';
*
* const BasicWhiteboardConfig = () => {
* const [showModal, setShowModal] = useState(true);
* const socket = io('https://mediasfu.com');
*
* const participants = [
* { id: '1', name: 'Alice', islevel: '1', useBoard: false },
* { id: '2', name: 'Bob', islevel: '1', useBoard: false }
* ];
*
* const parameters = {
* participants,
* socket,
* itemPageLimit: 10,
* islevel: '2',
* roomName: 'meeting-room-123',
* eventType: 'meeting' as const,
* shareScreenStarted: false,
* shared: false,
* breakOutRoomStarted: false,
* breakOutRoomEnded: true,
* recordStarted: false,
* recordResumed: false,
* recordPaused: false,
* recordStopped: false,
* recordingMediaOptions: 'video',
* canStartWhiteboard: true,
* whiteboardStarted: false,
* whiteboardEnded: true,
* hostLabel: 'Host',
* updateWhiteboardStarted: (started) => console.log('Whiteboard started:', started),
* updateWhiteboardEnded: (ended) => console.log('Whiteboard ended:', ended),
* updateWhiteboardUsers: (users) => console.log('Whiteboard users:', users),
* updateCanStartWhiteboard: (can) => console.log('Can start:', can),
* updateIsConfigureWhiteboardModalVisible: (visible) => setShowModal(visible),
* onScreenChanges: async ({ changed }) => console.log('Screen changed:', changed),
* captureCanvasStream: async (options) => console.log('Capture canvas stream'),
* prepopulateUserMedia: async ({ name }) => console.log('Prepopulate for:', name),
* rePort: async ({ restart }) => console.log('Report restart:', restart),
* getUpdatedAllParams: () => parameters
* };
*
* return (
* <ConfigureWhiteboardModal
* isVisible={showModal}
* onConfigureWhiteboardClose={() => setShowModal(false)}
* parameters={parameters}
* />
* );
* };
* ```
*
* @example
* // Custom styled with validation alerts
* ```tsx
* import React, { useState } from 'react';
* import { ConfigureWhiteboardModal } from 'mediasfu-reactjs';
* import { io } from 'socket.io-client';
*
* const CustomStyledWhiteboardConfig = () => {
* const [showModal, setShowModal] = useState(true);
* const [alertMessage, setAlertMessage] = useState('');
* const socket = io('https://mediasfu.com');
*
* const showAlert = ({ message, type }) => {
* setAlertMessage(`${type}: ${message}`);
* setTimeout(() => setAlertMessage(''), 5000);
* };
*
* const parameters = {
* // ... (same as basic example)
* showAlert,
* getUpdatedAllParams: () => parameters
* };
*
* return (
* <>
* {alertMessage && <div className="alert">{alertMessage}</div>}
* <ConfigureWhiteboardModal
* isVisible={showModal}
* onConfigureWhiteboardClose={() => setShowModal(false)}
* parameters={parameters}
* backgroundColor="#2c3e50"
* position="bottomRight"
* assignedTitle={<h3 style={{ color: '#2ecc71' }}>✅ Whiteboard Users</h3>}
* pendingTitle={<h3 style={{ color: '#95a5a6' }}>👥 Available Participants</h3>}
* startButtonProps={{
* style: {
* backgroundColor: '#2ecc71',
* color: '#fff',
* padding: '12px 24px'
* }
* }}
* />
* </>
* );
* };
* ```
*
* @example
* // Analytics tracking for whiteboard management
* ```tsx
* import React, { useState } from 'react';
* import { ConfigureWhiteboardModal } from 'mediasfu-reactjs';
* import { io } from 'socket.io-client';
*
* const AnalyticsWhiteboardConfig = () => {
* const [showModal, setShowModal] = useState(true);
* const socket = io('https://mediasfu.com');
*
* const parameters = {
* // ... (basic parameters)
* updateWhiteboardStarted: (started) => {
* analytics.track('Whiteboard Started', {
* roomName: 'meeting-room-123',
* timestamp: new Date()
* });
* },
* updateWhiteboardUsers: (users) => {
* analytics.track('Whiteboard Users Updated', {
* userCount: users.length,
* users: users.map(u => u.name)
* });
* },
* getUpdatedAllParams: () => parameters
* };
*
* return (
* <ConfigureWhiteboardModal
* isVisible={showModal}
* onConfigureWhiteboardClose={() => {
* analytics.track('Whiteboard Config Closed');
* setShowModal(false);
* }}
* parameters={parameters}
* renderActions={({ defaultActions, whiteboardStarted }) => {
* React.useEffect(() => {
* if (whiteboardStarted) {
* analytics.track('Whiteboard Session Active');
* }
* }, [whiteboardStarted]);
* return defaultActions;
* }}
* />
* );
* };
* ```
*
* @example
* // Integration with MediasfuGeneric using uiOverrides
* ```tsx
* import React, { useState } from 'react';
* import { MediasfuGeneric, ConfigureWhiteboardModal } from 'mediasfu-reactjs';
*
* const CustomWhiteboardComponent = (props) => (
* <ConfigureWhiteboardModal
* {...props}
* position="topLeft"
* renderBody={({ assignedParticipants, pendingParticipants, isEditing }) => (
* <div className="custom-whiteboard-config">
* <div className="participants-stats">
* <div className="stat-card">
* <h4>{assignedParticipants.length}</h4>
* <p>Active on Whiteboard</p>
* </div>
* <div className="stat-card">
* <h4>{pendingParticipants.length}</h4>
* <p>Can Be Added</p>
* </div>
* </div>
* <div className="participants-grid">
* <div className="assigned-column">
* <h3>🎨 Whiteboard Access</h3>
* {assignedParticipants.map(p => (
* <div key={p.id} className="participant-card active">
* {p.name}
* {isEditing && <button>Remove</button>}
* </div>
* ))}
* </div>
* <div className="pending-column">
* <h3>👥 Other Participants</h3>
* {pendingParticipants.map(p => (
* <div key={p.id} className="participant-card">
* {p.name}
* {isEditing && <button>Add</button>}
* </div>
* ))}
* </div>
* </div>
* </div>
* )}
* />
* );
*
* const App = () => {
* const [credentials] = useState({
* apiUserName: 'user123',
* apiKey: 'your-api-key'
* });
*
* return (
* <MediasfuGeneric
* credentials={credentials}
* uiOverrides={{
* ConfigureWhiteboardModal: CustomWhiteboardComponent
* }}
* />
* );
* };
* ```
*/
declare const ConfigureWhiteboard: React.FC<ConfigureWhiteboardModalOptions>;
export default ConfigureWhiteboard;
//# sourceMappingURL=ConfigureWhiteboardModal.d.ts.map