UNPKG

mediasfu-reactnative

Version:
154 lines 6.39 kB
// MainScreenComponent.tsx import React, { useEffect } from 'react'; import { View, StyleSheet, Dimensions, } from 'react-native'; /** * Type guard to determine if a child component conforms to ResizableChildOptions. * @param child - The child to check. * @returns True if the child is a React element with ResizableChildOptions, false otherwise. */ const isResizableChild = (child) => (child && typeof child === 'object' && 'props' in child && typeof child.props === 'object'); /** * MainScreenComponent dynamically adjusts the layout and dimensions of its child components based on window size, * stacking mode, and specified width/height fractions, supporting flexible and responsive screen layouts. * * This component determines the appropriate dimensions for main and secondary components based on stacking mode, screen width, * and main component size, and can conditionally arrange child components in a column or row based on screen width. * * @component * @param {MainScreenComponentOptions} props - Configuration options for MainScreenComponent. * @param {React.ReactNode} props.children - Child components to render inside the screen container. * @param {number} props.mainSize - Percentage size of the main component when stacking. * @param {boolean} props.doStack - Flag indicating if components should be stacked vertically or horizontally. * @param {number} [props.containerWidthFraction=1] - Fraction of window width for container width. * @param {number} [props.containerHeightFraction=1] - Fraction of window height for container height. * @param {Function} props.updateComponentSizes - Callback to update sizes of main and secondary components. * @param {number} [props.defaultFraction=0.94] - Adjustment fraction for height when controls are visible. * @param {boolean} props.showControls - Flag indicating if controls are shown, affecting height calculation. * @param {ComponentSizes} props.componentSizes - Current sizes of the components (main and secondary). * * @returns {JSX.Element} The MainScreenComponent with dynamically calculated dimensions and layout. * * @example * ```tsx * import React, { useState } from 'react'; * import { MainScreenComponent } from 'mediasfu-reactnative'; * * function App() { * const [componentSizes, setComponentSizes] = useState<ComponentSizes>({ * mainHeight: 0, * otherHeight: 0, * mainWidth: 0, * otherWidth: 0, * }); * * return ( * <MainScreenComponent * mainSize={70} * doStack={true} * containerWidthFraction={1} * containerHeightFraction={1} * updateComponentSizes={setComponentSizes} * showControls={true} * componentSizes={componentSizes} * > * <MainContent /> * <SecondaryContent /> * </MainScreenComponent> * ); * } * * export default App; * ``` */ const MainScreenComponent = ({ children, mainSize, doStack, containerWidthFraction = 1, containerHeightFraction = 1, updateComponentSizes, defaultFraction = 0.94, showControls, componentSizes, }) => { const { width: windowWidth, height: windowHeight } = Dimensions.get('window'); // Calculate parent dimensions based on fractions and control visibility const parentWidth = containerWidthFraction * windowWidth; const parentHeight = showControls ? containerHeightFraction * windowHeight * defaultFraction : containerHeightFraction * windowHeight; // Determine if the screen is wide let isWideScreen = parentWidth >= 768; if (!isWideScreen && parentWidth > 1.5 * parentHeight) { isWideScreen = true; } /** * Computes the dimensions for the main and other components based on stacking mode and screen width. * @returns {ComponentSizes} The calculated sizes for the components. */ const computeDimensions = () => { if (doStack) { if (isWideScreen) { return { mainHeight: parentHeight, otherHeight: parentHeight, mainWidth: Math.floor((mainSize / 100) * parentWidth), otherWidth: Math.floor(((100 - mainSize) / 100) * parentWidth), }; } return { mainHeight: Math.floor((mainSize / 100) * parentHeight), otherHeight: Math.floor(((100 - mainSize) / 100) * parentHeight), mainWidth: parentWidth, otherWidth: parentWidth, }; } return { mainHeight: parentHeight, otherHeight: parentHeight, mainWidth: parentWidth, otherWidth: parentWidth, }; }; useEffect(() => { const { mainHeight, otherHeight, mainWidth, otherWidth, } = computeDimensions(); updateComponentSizes({ mainHeight, otherHeight, mainWidth, otherWidth, }); }, [parentWidth, parentHeight, mainSize, doStack, isWideScreen]); return (<View style={[ styles.screenContainer, { flexDirection: isWideScreen ? 'row' : 'column', width: parentWidth, height: parentHeight, }, ]}> {/* Render child components with updated dimensions */} {React.Children.map(children, (child, index) => { if (isResizableChild(child)) { const childStyle = doStack ? { height: index === 0 ? componentSizes.mainHeight : componentSizes.otherHeight, width: index === 0 ? componentSizes.mainWidth : componentSizes.otherWidth, } : { height: componentSizes.mainHeight, width: componentSizes.mainWidth, }; return React.cloneElement(child, { mainSize, isWideScreen, style: [child.props.style, childStyle], key: index, }); } return null; })} </View>); }; export default MainScreenComponent; /** * Stylesheet for the MainScreenComponent. */ const styles = StyleSheet.create({ screenContainer: { flex: 1, padding: 0, margin: 0, }, }); //# sourceMappingURL=MainScreenComponent.js.map