import type { ReactNode, ForwardRefExoticComponent, RefAttributes } from 'react' import React, { useCallback, useEffect, useRef, useState } from 'react' import type { RootContextProps } from './RootContext' import { PicassoRootNodeContext, RootContext } from './RootContext' import type { EnvironmentType, TextLabelProps } from '../types' import type { PicassoRootNodeProps } from './PicassoRootNode' import type { BreakpointKeys } from './config/breakpoints' import { useScreens } from './config/breakpoints' export interface PicassoGlobalStylesProviderProps extends TextLabelProps { children?: ReactNode RootComponent: ForwardRefExoticComponent< PicassoRootNodeProps & RefAttributes > environment: EnvironmentType<'test' | 'temploy'> disableTransitions?: boolean responsive?: boolean } const breakpointKeyByRange: Record = { xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', xl: 'xl', } const PicassoGlobalStylesProvider = ( props: PicassoGlobalStylesProviderProps ) => { const { children, RootComponent, environment, titleCase, disableTransitions, responsive, } = props const rootRef = useRef(null) // The ref alone is not enough for consumers that read the root node during // the tree's first render pass (refs populate at commit, and a ref mutation // triggers no re-render) — mirror the node into state so they re-render // once it exists const [rootNode, setRootNode] = useState(null) const attachRootRef = useCallback((node: HTMLDivElement | null) => { rootRef.current = node setRootNode(node) }, []) const screens = useScreens() const currentBreakpointRange = screens(breakpointKeyByRange) const [contextValue, setContextValue] = useState({ rootRef, currentBreakpointRange, hasTopBar: false, setHasTopBar: (hasTopBar: boolean) => { setContextValue(context => ({ ...context, hasTopBar, })) }, environment, titleCase, hasDrawer: false, setHasDrawer: (hasDrawer: boolean) => { setContextValue(context => ({ ...context, hasDrawer, })) }, hasSidebar: false, setHasSidebar: (hasSidebar: boolean) => { setContextValue(context => ({ ...context, hasSidebar, })) }, disableTransitions, responsive, }) useEffect(() => { if (contextValue.currentBreakpointRange !== currentBreakpointRange) { setContextValue({ ...contextValue, currentBreakpointRange, }) } }, [currentBreakpointRange]) return ( {children} ) } export default PicassoGlobalStylesProvider