import {
useMemo,
type PropsWithChildren
} from 'react'
import type { ColorValue, TextStyle } from 'react-native'
import type { HexColorToken } from '@helpwave/hightide-design/primitive-tokens'
import type { IconStyle } from '../../icons'
import { HexColorUtils } from '../../utils/hex'
import {
ContentThemeContext,
useContentTheme,
type ContentThemeContextValue
} from './ContentThemeContext'
export type ContentThemeRootProviderProps = PropsWithChildren & ContentThemeContextValue
export const ContentThemeRootProvider = ({
children,
foreground,
background,
textStyle,
iconStyle,
}: ContentThemeRootProviderProps) => {
const value = useMemo((): ContentThemeContextValue => ({
foreground,
background,
textStyle,
iconStyle,
}), [foreground, background, textStyle, iconStyle])
return (
{children}
)
}
type ColorOverride =
| ColorValue
| ((prev: HexColorToken) => ColorValue)
type TextStyleOverride =
| TextStyle
| ((prev: TextStyle, foreground: HexColorToken) => TextStyle)
type IconStyleOverride =
| IconStyle
| ((prev: IconStyle, foreground: HexColorToken) => IconStyle)
export type ContentThemeOverrideProviderProps = PropsWithChildren & {
foreground?: ColorOverride,
background?: ColorOverride,
textStyle?: TextStyleOverride,
iconStyle?: IconStyleOverride,
isKeepingTextColor?: boolean,
isKeepingIconColor?: boolean,
}
const resolveColorOverride = (
override: ColorOverride | undefined,
previous: HexColorToken
): HexColorToken | undefined => {
if (override === undefined) {
return undefined
}
const raw = typeof override === 'function' ? override(previous) : override
return HexColorUtils.tryParseColorValue(raw)
}
export const ContentThemeOverrideProvider = ({
children,
foreground: foregroundOverride,
background: backgroundOverride,
textStyle: textStyleOverride,
iconStyle: iconStyleOverride,
isKeepingIconColor = false,
isKeepingTextColor = false,
}: ContentThemeOverrideProviderProps) => {
const parent = useContentTheme()
const value = useMemo((): ContentThemeContextValue => {
const newForeground = resolveColorOverride(foregroundOverride, parent.foreground)
const newBackground = resolveColorOverride(backgroundOverride, parent.background)
let textStyle = typeof textStyleOverride === 'function'
? textStyleOverride(parent.textStyle, parent.foreground)
: textStyleOverride ?? parent.textStyle
if (!isKeepingTextColor && newForeground !== undefined) {
textStyle = { ...textStyle, color: newForeground }
}
let iconStyle = typeof iconStyleOverride === 'function'
? iconStyleOverride(parent.iconStyle, parent.foreground)
: iconStyleOverride ?? parent.iconStyle
if (!isKeepingIconColor && newForeground !== undefined) {
iconStyle = { ...iconStyle, color: newForeground }
}
return {
foreground: newForeground ?? parent.foreground,
background: newBackground ?? parent.background,
textStyle,
iconStyle,
}
}, [parent, foregroundOverride, textStyleOverride, iconStyleOverride, backgroundOverride, isKeepingTextColor, isKeepingIconColor])
return (
{children}
)
}