import { CacheProvider as EmotionCacheProvider } from '@emotion/react' ; import createEmotionCache , { EmotionCache } from '@emotion/cache' ; import { useMemo } from 'react' ; import { useSubscription } from 'use-subscription' ; import { TssCacheProvider } from 'tss-react' ; class Informative { private callback = new Set < ( ) => void > ( ) ; addListener ( cb ) { this . callback . add ( cb ) ; return ( ) => void this . callback . delete ( cb ) ; } private pendingInform = false ; inform ( ) { if ( this . pendingInform ) return ; requestAnimationFrame ( ( ) => { this . pendingInform = false ; this . callback . forEach ( ( x ) => x ( ) ) ; } ) ; } } class EmotionInformativeSheetsRegistry { reg = new Informative ( ) ; constructor ( public cache ) { const orig = cache . sheet . insert ; cache . sheet . insert = ( ... args ) => { const r = orig . call ( cache . sheet , ... args ) ; this . reg . inform ( ) ; return r ; } ; } toString ( ) { return this . cache . sheet . tags . map ( ( x ) => x . innerHTML ) . join ( '\n' ) ; } } const emotionRegistryMap = new WeakMap < ShadowRoot , EmotionInformativeSheetsRegistry > ( ) ; const emotion2RegistryMap = new WeakMap < ShadowRoot , EmotionInformativeSheetsRegistry > ( ) ; function createSubscription ( registry ) { return { getCurrentValue : ( ) => registry ?. toString ( ) , subscribe : ( callback ) => registry ?. reg . addListener ( callback ) ?? ( ( ) => 0 ) , } ; } param ref returns export function useCurrentShadowRootStyles ( ref ) { const emotionSubscription = useMemo ( ( ) => { const root = ref ?. getRootNode ( ) as ShadowRoot ; const registry = emotionRegistryMap . get ( root ) ; return createSubscription ( registry ) ; } , [ ref ] ) ; const emotion2Subscription = useMemo ( ( ) => { const root = ref ?. getRootNode ( ) as ShadowRoot ; const registry = emotion2RegistryMap . get ( root ) ; return createSubscription ( registry ) ; } , [ ref ] ) ; return [ useSubscription ( emotionSubscription ) , useSubscription ( emotion2Subscription ) ] . filter ( Boolean ) . join ( '\n' ) ; } const initOnceMap = new WeakMap < ShadowRoot , unknown > ( ) ; function initOnce < T > ( keyBy , init ) { if ( initOnceMap . has ( keyBy ) ) return initOnceMap . get ( keyBy ) as T ; const val = init ( ) ; initOnceMap . set ( keyBy , val ) ; return val ; } function createElement ( key , kind ) { const e = document . createElement ( key ) ; e . setAttribute ( 'data-' + kind , 'true' ) ; return e ; } internal export interface ShadowRootStyleProviderProps extends React . PropsWithChildren < { } > { shadow : ShadowRoot ; } internal export function ShadowRootStyleProvider ( props ) { const { shadow , children } = props ; const { muiEmotionCache , tssEmotionCache } = initOnce ( shadow , ( ) => init ( props ) ) ; return ( < EmotionCacheProvider value = { muiEmotionCache } > < TssCacheProvider value = { tssEmotionCache } > { children } < /TssCacheProvider> < /EmotionCacheProvider>); } function init ( { shadow } ) { const head = shadow . appendChild ( createElement ( 'head' , 'css-container' ) ) ; const MuiInsertionPoint = head . appendChild ( createElement ( 'div' , 'mui-area' ) ) ; const TSSInsertionPoint = head . appendChild ( createElement ( 'div' , 'tss-area' ) ) ; const instanceID = Math . random ( ) . toString ( 36 ) . slice ( 2 ) . replace ( /\d/g , 'x' ) ; const muiEmotionCache = createEmotionCache ( { container : MuiInsertionPoint , key : 'mui-' + instanceID , speedy : false , } ) ; const tssEmotionCache = createEmotionCache ( { container : TSSInsertionPoint , key : 'tss-' + instanceID , speedy : false , } ) ; emotionRegistryMap . set ( shadow , new EmotionInformativeSheetsRegistry ( muiEmotionCache ) ) ; emotion2RegistryMap . set ( shadow , new EmotionInformativeSheetsRegistry ( tssEmotionCache ) ) ; return { muiEmotionCache , tssEmotionCache } ; }