import cn from 'classnames'; import { RtBreakpointSegmentsProps, RtFrameProps, RtFrameRootProps, } from './rt-frame.types'; import { ElementRef, ElementType, ForwardedRef, forwardRef, ReactNode, useContext, useEffect, } from 'react'; import { handleRootAbstractions } from './utils/handle-root-abstractions'; import { ColorClassKeys, getColorClasses, getTypographyClasses, TypographyClassKeys, } from './utils/get-frame-classes'; import { useComputedMediaTheme } from './hooks/use-computed-media-theme'; import { useFrame } from './hooks/use-frame'; import { FrameContext, SurfaceContext, BreakpointConfigContext, BreakpointClusterContext, } from '@dpa/react-frame-context'; // eslint-disable-next-line @nx/enforce-module-boundaries import { _V_PREFIX_ } from '../../../../../tools/constants'; import { RtFrameRootStyled, StyledProps, } from './styled-components/rt-frame-styled'; import { useBreakpoint } from './hooks/use-breakpoint'; const RtInternalCompoundedFrame: ( props: RtFrameProps & { ref?: ForwardedRef> } ) => ReactNode = forwardRef((props, ref) => { const { children, as: renderAs, surface, surfaceState = 'native', className, bgTransparent, achromatic, primitive, theme, scheme, modifier, use, sizeScheme, typescale, typographyScheme, operatorScheme, breakpointScheme, breakpointXs, breakpointSm, breakpointMd, breakpointLg, isFontSizeProvider = false, borderColorSurfaceUse, ...rest } = props; const { computedThemeMediaValue } = useComputedMediaTheme(); const { isStyledComponent, breakpointConfig, hasNewBreakpoints, isRootAFontSizeProvider, Component, } = useBreakpoint({ breakpointXs, breakpointSm, breakpointMd, breakpointLg, as: renderAs, isFontSizeProvider, }); const { propsAbstractions, parentAbstractions, currentAbstractions, hasNewTypography, hasNewColors, } = useFrame(props, computedThemeMediaValue); useEffect(() => { if (Object.values(parentAbstractions).length === 0) { console.warn('RtFrame: There must be an root element.'); } }, [currentAbstractions, parentAbstractions]); const parentSurface = useContext(SurfaceContext); const breakpointClustersContext = useContext( BreakpointClusterContext ); const Content = ( {children} ); const SurfaceContextAndContent = surface ? ( {Content} ) : ( Content ); const FrameContextAndContent = hasNewTypography || hasNewColors ? ( {SurfaceContextAndContent} ) : ( SurfaceContextAndContent ); const BreakpointClusterContextAndContent = hasNewBreakpoints ? ( {FrameContextAndContent} ) : ( FrameContextAndContent ); return BreakpointClusterContextAndContent; }); /** * Рутовый фрейм, который определяет дефолтные абстракции дизайн системы Ritm на `body`. * * Должен быть в каждом приложении. */ function RtFrameRoot(props: RtFrameRootProps) { const { children, breakpointConfig, isFontSizeProvider = false } = props; const { computedThemeMediaValue } = useComputedMediaTheme(); const { currentAbstractions } = useFrame(props, computedThemeMediaValue); useEffect(() => { if (typeof document !== 'undefined') { handleRootAbstractions(ColorClassKeys, currentAbstractions); handleRootAbstractions(TypographyClassKeys, currentAbstractions); } }, [currentAbstractions]); return ( {children} ); } type CompoundedComponent = typeof RtInternalCompoundedFrame & { Root: typeof RtFrameRoot; displayName?: string; }; /** * Компонент для переопределения дефолтных абстракции дизайн системы Ritm. * Также используется при верстке для декларации поверхностей, для установки цвета текста и фона на поверхности. * * Приложение обязательно должно иметь корневой с установленными дефолтными абстракциями на приложении. * * {@link RtFrameProps} */ const RtFrame = RtInternalCompoundedFrame as CompoundedComponent; RtFrame.Root = RtFrameRoot; RtFrame.displayName = 'RtFrame'; export { RtFrame, RtFrameRoot };