import * as React from "react"; type ElementProps = { type: string; style: any; props: any; elements?: ElementProps[]; key: string; }; export function mapElementWithKey(fn) { return function (element, key) { return fn({ ...element, key }); }; } // Initialize these outside of the function so they only get created once const focusableTypes = new Set([ "View", "ButtonContainerView", "FocusableView", "CollapsibleTextContainer", "BorderContainerView", ]); const cellPlayerTypes = new Set([ "Image", "LiveImage", "Button", "DynamicBadge", ]); /** * Maps a provided node in a master cell configuration to a React Component tree with appropriate props & styles * Curried function of the form elementMapper(components)(element) * @param {Object} components map of primitive React components to use to render the elements * @param {Object} element element in the current master cell configuration * @param {String} element.type type of the component to render. Should match an entry in the components map * @param {Object} element.style style object for the component * @param {Object} element.props React props to pass to the component * @param {?[Object]} element.elements Optional array of nested elements to render within the current node * @returns {Object} React component */ export function elementMapper( components, otherProps?: { skipButtons?: boolean; cellUUID?: string; [key: string]: any; emitAsyncElementRegistrate?: () => void; emitAsyncElementLayout?: () => void; } ) { return function Element({ type, style, props, elements = [], key, }: ElementProps) { const propsForCellPlayer = cellPlayerTypes.has(type) ? { cellUUID: otherProps?.cellUUID, } : {}; const propsForFocusable = focusableTypes.has(type) ? { ...otherProps, // eslint-disable-next-line react/prop-types preferredFocus: otherProps?.preferredFocus && props?.preferredFocus, } : {}; const componentProps = { style, skipButtons: otherProps?.skipButtons, emitAsyncElementRegistrate: otherProps?.emitAsyncElementRegistrate, emitAsyncElementLayout: otherProps?.emitAsyncElementLayout, ...props, ...propsForFocusable, ...propsForCellPlayer, }; const { hidden } = componentProps; if (hidden) return null; const Component = components[type]; const fn = mapElementWithKey(elementMapper(components, otherProps)); return ( {focusableTypes.has(type) && elements.length > 0 ? elements.map(fn) : null} ); }; }