mediasfu-reactjs
Version:
MediaSFU Prebuilt ReactJS SDK - Compatible with React 18 & 19, TypeScript & JavaScript
423 lines • 15.3 kB
TypeScript
import React from "react";
import { IconDefinition } from "@fortawesome/free-solid-svg-icons";
export interface ButtonTouch {
name?: string;
icon?: IconDefinition;
alternateIcon?: IconDefinition;
onPress?: () => void;
backgroundColor?: {
default?: string;
};
active?: boolean;
alternateIconComponent?: React.JSX.Element;
iconComponent?: React.JSX.Element;
customComponent?: React.JSX.Element;
color?: string;
activeColor?: string;
inActiveColor?: string;
show?: boolean;
disabled?: boolean;
buttonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
style?: React.CSSProperties;
className?: string;
iconWrapperProps?: React.HTMLAttributes<HTMLSpanElement>;
textProps?: React.HTMLAttributes<HTMLSpanElement>;
contentWrapperProps?: React.HTMLAttributes<HTMLDivElement>;
renderContent?: (options: {
index: number;
isActive: boolean;
defaultIcon: React.ReactNode;
defaultLabel: React.ReactNode;
defaultContent: React.ReactNode;
direction: "horizontal" | "vertical";
}) => React.ReactNode;
renderButton?: (options: {
index: number;
button: ButtonTouch;
defaultButton: React.ReactNode;
defaultProps: React.ButtonHTMLAttributes<HTMLButtonElement>;
direction: "horizontal" | "vertical";
}) => React.ReactNode;
}
export interface ControlButtonsComponentTouchOptions {
buttons: ButtonTouch[];
position?: "left" | "right" | "middle";
location?: "top" | "bottom" | "center";
direction?: "horizontal" | "vertical";
buttonsContainerStyle?: React.CSSProperties;
alternateIconComponent?: React.JSX.Element;
iconComponent?: React.JSX.Element;
showAspect?: boolean;
containerProps?: React.HTMLAttributes<HTMLDivElement>;
buttonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
buttonStyle?: React.CSSProperties;
buttonClassName?: string;
iconWrapperProps?: React.HTMLAttributes<HTMLSpanElement>;
textProps?: React.HTMLAttributes<HTMLSpanElement>;
textStyle?: React.CSSProperties;
contentWrapperProps?: React.HTMLAttributes<HTMLDivElement>;
renderButton?: (options: {
index: number;
button: ButtonTouch;
defaultButton: React.ReactNode;
defaultProps: React.ButtonHTMLAttributes<HTMLButtonElement>;
direction: "horizontal" | "vertical";
}) => React.ReactNode;
renderButtonContent?: (options: {
index: number;
button: ButtonTouch;
defaultIcon: React.ReactNode;
defaultLabel: React.ReactNode;
defaultContent: React.ReactNode;
direction: "horizontal" | "vertical";
}) => React.ReactNode;
gap?: number | string;
}
export type ControlButtonsComponentTouchType = (options: ControlButtonsComponentTouchOptions) => React.JSX.Element;
/**
* ControlButtonsComponentTouch - Touch-optimized control buttons for mobile and tablet devices.
*
* This component provides a touch-friendly interface for media control buttons, specifically designed
* for mobile and tablet experiences with larger hit areas, optimized spacing, and touch-specific interactions.
* It offers the same flexibility as other control button components while prioritizing touch usability.
*
* **Key Features:**
* - **Touch-Optimized**: Larger hit areas and spacing optimized for finger interactions
* - **Flexible Layout**: Horizontal or vertical button arrangements with gap control
* - **Positioning Control**: Nine-point positioning system (left/middle/right × top/center/bottom)
* - **Per-Button Customization**: Individual button styling, colors, icons, and behavior
* - **Active State Management**: Clear visual feedback for active/inactive button states
* - **Custom Components**: Support for custom button components and icon replacements
* - **Render Hooks**: Complete override capability for button content and structure
* - **Visibility Control**: Individual button show/hide with conditional rendering
* - **Disabled States**: Proper disabled styling and interaction blocking
* - **Icon Flexibility**: Support for FontAwesome icons, custom icons, and alternate icons
* - **HTML Attributes**: Granular control over all button elements (button, icon wrapper, text, content)
* - **Shared and Individual Props**: Shared defaults with per-button override capability
* - **Accessibility**: Touch-friendly ARIA attributes and semantic HTML
*
* @component
*
* @param {ControlButtonsComponentTouchOptions} props - Configuration options for ControlButtonsComponentTouch
* @param {ButtonTouch[]} props.buttons - Array of touch button configurations with individual settings
* @param {"left" | "right" | "middle"} [props.position="left"] - Horizontal alignment of button container
* @param {"top" | "bottom" | "center"} [props.location="top"] - Vertical alignment of button container
* @param {"horizontal" | "vertical"} [props.direction="horizontal"] - Button layout direction
* @param {React.CSSProperties} [props.buttonsContainerStyle] - Additional styles for button container
* @param {React.JSX.Element} [props.alternateIconComponent] - Default alternate icon component for all buttons
* @param {React.JSX.Element} [props.iconComponent] - Default primary icon component for all buttons
* @param {boolean} [props.showAspect=false] - Controls overall visibility of button container
* @param {React.HTMLAttributes<HTMLDivElement>} [props.containerProps] - HTML attributes for container wrapper
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} [props.buttonProps] - Shared HTML attributes for all buttons
* @param {React.CSSProperties} [props.buttonStyle] - Shared CSS styles applied to all buttons
* @param {string} [props.buttonClassName] - Shared class name appended to all buttons
* @param {React.HTMLAttributes<HTMLSpanElement>} [props.iconWrapperProps] - Shared HTML attributes for icon wrappers
* @param {React.HTMLAttributes<HTMLSpanElement>} [props.textProps] - Shared HTML attributes for text labels
* @param {React.HTMLAttributes<HTMLDivElement>} [props.contentWrapperProps] - Shared HTML attributes for content wrappers
* @param {(options: {index: number; button: ButtonTouch; defaultButton: React.ReactNode; defaultProps: React.ButtonHTMLAttributes<HTMLButtonElement>; direction: "horizontal" | "vertical"}) => React.ReactNode} [props.renderButton] - Custom render function for entire button
* @param {(options: {index: number; button: ButtonTouch; defaultIcon: React.ReactNode; defaultLabel: React.ReactNode; defaultContent: React.ReactNode; direction: "horizontal" | "vertical"}) => React.ReactNode} [props.renderButtonContent] - Custom render function for button content
* @param {number | string} [props.gap] - Spacing between buttons (CSS gap value)
*
* @returns {React.JSX.Element} The rendered touch-optimized control buttons component
*
* @example
* // Basic touch controls for mobile video player
* ```tsx
* import React, { useState } from 'react';
* import { ControlButtonsComponentTouch } from 'mediasfu-reactjs';
* import { faPlay, faPause, faVolumeUp, faExpand } from '@fortawesome/free-solid-svg-icons';
*
* const MobileVideoControls = () => {
* const [isPlaying, setIsPlaying] = useState(false);
* const [isMuted, setIsMuted] = useState(false);
*
* const buttons = [
* {
* name: 'Play',
* icon: faPlay,
* alternateIcon: faPause,
* active: isPlaying,
* onPress: () => setIsPlaying(!isPlaying),
* show: true
* },
* {
* name: 'Volume',
* icon: faVolumeUp,
* active: !isMuted,
* onPress: () => setIsMuted(!isMuted),
* show: true
* },
* {
* name: 'Fullscreen',
* icon: faExpand,
* onPress: () => console.log('Enter fullscreen'),
* show: true
* }
* ];
*
* return (
* <ControlButtonsComponentTouch
* buttons={buttons}
* direction="horizontal"
* position="middle"
* location="bottom"
* showAspect={true}
* gap={16}
* />
* );
* };
* ```
*
* @example
* // Custom styled touch controls with haptic feedback
* ```tsx
* import React, { useState } from 'react';
* import { ControlButtonsComponentTouch } from 'mediasfu-reactjs';
* import { faVideo, faMicrophone, faPhoneSlash } from '@fortawesome/free-solid-svg-icons';
*
* const MeetingTouchControls = () => {
* const [videoOn, setVideoOn] = useState(true);
* const [audioOn, setAudioOn] = useState(true);
*
* const triggerHaptic = () => {
* if ('vibrate' in navigator) {
* navigator.vibrate(10); // Short haptic feedback
* }
* };
*
* const buttons = [
* {
* name: 'Camera',
* icon: faVideo,
* active: videoOn,
* onPress: () => {
* triggerHaptic();
* setVideoOn(!videoOn);
* },
* backgroundColor: { default: '#34495e' },
* activeColor: '#2ecc71',
* inActiveColor: '#e74c3c',
* show: true,
* style: { minWidth: '60px', minHeight: '60px' }
* },
* {
* name: 'Mic',
* icon: faMicrophone,
* active: audioOn,
* onPress: () => {
* triggerHaptic();
* setAudioOn(!audioOn);
* },
* backgroundColor: { default: '#34495e' },
* activeColor: '#2ecc71',
* inActiveColor: '#e74c3c',
* show: true,
* style: { minWidth: '60px', minHeight: '60px' }
* },
* {
* name: 'End Call',
* icon: faPhoneSlash,
* onPress: () => {
* triggerHaptic();
* console.log('End call');
* },
* backgroundColor: { default: '#c0392b' },
* color: '#fff',
* show: true,
* style: { minWidth: '60px', minHeight: '60px' }
* }
* ];
*
* return (
* <ControlButtonsComponentTouch
* buttons={buttons}
* direction="horizontal"
* position="middle"
* location="bottom"
* showAspect={true}
* buttonsContainerStyle={{
* padding: '20px',
* borderRadius: '16px',
* backgroundColor: 'rgba(0,0,0,0.9)'
* }}
* gap={20}
* />
* );
* };
* ```
*
* @example
* // Analytics tracking for touch interactions
* ```tsx
* import React, { useState } from 'react';
* import { ControlButtonsComponentTouch } from 'mediasfu-reactjs';
* import { faThumbsUp, faHand, faComment } from '@fortawesome/free-solid-svg-icons';
*
* const InteractiveTouchControls = () => {
* const [reactions, setReactions] = useState({ like: 0, hand: 0, comment: 0 });
*
* const trackTouchInteraction = (action: string, touchData: any) => {
* analytics.track('Touch Control Interaction', {
* action,
* device: 'mobile',
* timestamp: new Date(),
* ...touchData
* });
* };
*
* const buttons = [
* {
* name: '👍',
* icon: faThumbsUp,
* onPress: () => {
* const newCount = reactions.like + 1;
* setReactions({ ...reactions, like: newCount });
* trackTouchInteraction('Like', { count: newCount });
* },
* show: true
* },
* {
* name: '✋',
* icon: faHand,
* onPress: () => {
* const newCount = reactions.hand + 1;
* setReactions({ ...reactions, hand: newCount });
* trackTouchInteraction('Raise Hand', { count: newCount });
* },
* show: true
* },
* {
* name: '💬',
* icon: faComment,
* onPress: () => {
* trackTouchInteraction('Open Chat', {});
* console.log('Open chat');
* },
* show: true
* }
* ];
*
* return (
* <ControlButtonsComponentTouch
* buttons={buttons}
* direction="vertical"
* position="right"
* location="center"
* showAspect={true}
* renderButtonContent={({ defaultContent, button, index }) => (
* <div
* className="touch-button-content"
* onTouchStart={(e) => {
* trackTouchInteraction('Touch Start', {
* buttonName: button.name,
* touchCount: e.touches.length
* });
* }}
* >
* {defaultContent}
* </div>
* )}
* />
* );
* };
* ```
*
* @example
* // Integration with MediasfuGeneric using uiOverrides
* ```tsx
* import React, { useState } from 'react';
* import { MediasfuGeneric, ControlButtonsComponentTouch } from 'mediasfu-reactjs';
*
* const CustomTouchControlsComponent = (props) => (
* <ControlButtonsComponentTouch
* {...props}
* direction="horizontal"
* position="middle"
* location="bottom"
* gap={24}
* renderButton={({ defaultButton, button, index }) => (
* <div
* className="custom-touch-button-wrapper"
* style={{
* position: 'relative',
* touchAction: 'manipulation' // Optimize for touch
* }}
* >
* <button
* className={`touch-optimized-button ${button.active ? 'active' : ''}`}
* onClick={button.onPress}
* style={{
* minWidth: '56px',
* minHeight: '56px',
* borderRadius: '50%',
* border: 'none',
* cursor: 'pointer',
* WebkitTapHighlightColor: 'transparent' // Remove tap highlight
* }}
* >
* <span className="button-icon" style={{ fontSize: '24px' }}>
* Icon content here
* </span>
* </button>
* {button.active && (
* <div className="active-pulse" style={{
* position: 'absolute',
* inset: '-4px',
* borderRadius: '50%',
* border: '2px solid #2ecc71',
* animation: 'pulse 1.5s infinite'
* }} />
* )}
* </div>
* )}
* />
* );
*
* const App = () => {
* const [credentials] = useState({
* apiUserName: 'user123',
* apiKey: 'your-api-key'
* });
*
* return (
* <MediasfuGeneric
* credentials={credentials}
* uiOverrides={{
* ControlButtonsComponentTouch: CustomTouchControlsComponent
* }}
* />
* );
* };
* ```
* active: true,
* backgroundColor: { default: "#047857" },
* renderContent: ({ defaultContent }) => (
* <span className="touch-button__content">{defaultContent}</span>
* ),
* },
* {
* name: "Pause",
* icon: faPause,
* onPress: () => console.log("Pause button pressed"),
* buttonProps: { 'aria-label': 'Pause media' },
* },
* ];
*
* return (
* <ControlButtonsComponentTouch
* showAspect
* direction="horizontal"
* buttons={buttons}
* containerProps={{ 'aria-label': 'mobile controls', role: 'toolbar' }}
* buttonProps={{ type: 'button' }}
* gap={12}
* />
* );
* }
*
* export default App;
* ```
*/
declare const ControlButtonsComponentTouch: React.FC<ControlButtonsComponentTouchOptions>;
export default ControlButtonsComponentTouch;
//# sourceMappingURL=ControlButtonsComponentTouch.d.ts.map