import React from 'react' import { TypeGuards } from '@codeleap/types' import { arePropsEqual } from '@codeleap/utils' import { Badge } from '../Badge' import { View } from '../View' import { IconProps } from './types' import { useNestedStylesByKey, AnyRecord, StyledComponentProps, IJSX, useTheme, StyledComponentWithProps } from '@codeleap/styles' import { MobileStyleRegistry } from '../../Registry' import { useStylesFor } from '../../hooks' export * from './styles' export * from './types' export const IconComponent = (props: IconProps) => { const { name, style, badge, badgeProps = {}, wrapperProps = {}, source, ...otherProps } = { ...Icon.defaultProps, ...props, } // Icons are React components registered on the theme object at app startup — they are not // font glyphs or image assets. If the name is not in the registry the component silently // renders nothing, so a missing registration will not crash but will produce an invisible slot. const icons = useTheme(store => store.theme?.icons) const styles = useStylesFor(Icon.styleRegistryName, style) const Component = icons?.[name] if (!name && !source) { return null } if (!Component) { return null } if (badge || TypeGuards.isNumber(badge)) { const badgeStyles = useNestedStylesByKey('badge', styles) // `size` is a shorthand not in RN's style spec; the @ts-expect-error suppresses that. // The wrapper needs an explicit size so Badge can be absolutely positioned correctly. const sized = { // @ts-expect-error height: styles.icon?.size || styles.icon?.height || props?.size, // @ts-expect-error width: styles.icon?.size || styles.icon?.width || props?.size, } return } return } function areEqual(prevProps, nextProps) { const check = ['name', 'style', 'renderEmptySpace', 'badgeProps', 'badge'] const res = arePropsEqual(prevProps, nextProps, { check }) return res } export const Icon = React.memo(IconComponent, areEqual) as StyledComponentWithProps Icon.styleRegistryName = 'Icon' Icon.elements = ['icon', 'iconBadgeWrapper', 'badge'] Icon.rootElement = 'icon' Icon.defaultProps = { badge: false, } as Partial Icon.withVariantTypes = (styles: S) => { return Icon as (props: StyledComponentProps) => IJSX } MobileStyleRegistry.registerComponent(Icon)