import { useIsomorphicLayoutEffect } from '@tamagui/constants'
import { ClientOnly } from '@tamagui/use-did-finish-ssr'
import React, { useEffect } from 'react'
import { getSetting } from '../config'
import { ComponentContext } from '../contexts/ComponentContext'
import { stopAccumulatingRules } from '../helpers/insertStyleRule'
import { updateMediaListeners } from '../hooks/useMedia'
import { resolveAnimationDriver } from '../helpers/resolveAnimationDriver'
import type { AnimationDriver, TamaguiProviderProps } from '../types'
import { TamaguiRoot } from './TamaguiRoot'
import { ThemeProvider } from './ThemeProvider'
// cache first theme key per config to avoid Object.keys allocation on every render
let _cachedFirstKey: string | undefined
let _cachedConfig: any
function firstThemeKey(config: any): string | undefined {
if (config !== _cachedConfig) {
_cachedConfig = config
_cachedFirstKey = config?.themes ? Object.keys(config.themes)[0] : undefined
}
return _cachedFirstKey
}
export function TamaguiProvider({
children,
disableInjectCSS,
config,
className,
defaultTheme: defaultThemeProp,
reset,
insets,
}: TamaguiProviderProps) {
// fall back to first theme when defaultTheme is null/undefined
// (e.g. useColorScheme() returns null on first render in RN 0.83+)
const defaultTheme = defaultThemeProp || firstThemeKey(config) || 'light'
useIsomorphicLayoutEffect(() => {
stopAccumulatingRules()
updateMediaListeners()
}, [])
const memoizedInsets = React.useMemo(
() => insets,
[insets?.top, insets?.right, insets?.bottom, insets?.left]
)
// Get the default animation driver from config
// config.animations is already normalized to the default driver in createTamagui
// resolveAnimationDriver handles edge cases where raw multi-driver object leaks through
const defaultAnimationDriver: AnimationDriver | null = React.useMemo(
() => resolveAnimationDriver(config?.animations),
[config?.animations]
)
useEffect(() => {
defaultAnimationDriver?.onMount?.()
}, [])
let contents = (
{children}
)
if (getSetting('disableSSR')) {
// never changes so conditional render fine, no re-parenting risk
contents = {contents}
}
return (
<>
{contents}
{process.env.TAMAGUI_TARGET !== 'native' && config && !disableInjectCSS && (
)}
>
)
}