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)