import { ClassRef } from 'treat' ; import { isBrowser , isDev } from './env' ; import { errorOnce , warnOnce } from './logger' ; import type { StyleInjector } from './StyleInjector' ; export interface RuleManager { increaseUsage ( className , cssText ) : void ; decreaseUsage ( className , byAmount ) : void ; } export class NullRuleManager implements RuleManager { increaseUsage ( ) { if ( isDev ) { if ( isBrowser ) { errorOnce ( 'Client-side injection of dynamic styles is not set up. Wrap the component tree inside a `<StyleInjectorProvider>` without parameters. Make sure that `useStyling()` and the `sx` prop are only used within the encapsulated components.' ) ; } else { warnOnce ( 'Server-side rendering of dynamic styles is not configured properly. Some of the initially applied CSS could not be prerendered. Please refer to the documentation at https://glaze.js.org/docs/server-side-rendering/ for further information.' ) ; } } } decreaseUsage ( ) { } } export class OptimizedRuleManager implements RuleManager { private injector : StyleInjector ; private ruleIndexesByClassName : Map < ClassRef , number > ; private usageCountsByClassName = new Map < ClassRef , number > ( ) ; constructor ( injector , initialRuleIndexesByClassName ) { this . injector = injector ; this . ruleIndexesByClassName = initialRuleIndexesByClassName ; } increaseUsage ( className , cssText ) { const prevUsageCount = this . usageCountsByClassName . get ( className ) || 0 ; if ( ! prevUsageCount && ! this . ruleIndexesByClassName . has ( className ) ) { if ( isDev && isBrowser && window . __glaze_disableStyleInjection ) { new NullRuleManager ( ) . increaseUsage ( ) ; return ; } this . ruleIndexesByClassName . set ( className , this . injector . addRule ( cssText ( ) ) ) ; } this . usageCountsByClassName . set ( className , prevUsageCount + 1 ) ; } decreaseUsage ( className , byAmount ) { if ( isDev && window . __glaze_disableStyleInjection ) return ; const nextUsageCount = this . usageCountsByClassName . get ( className ) ! - byAmount ; if ( nextUsageCount ) { this . usageCountsByClassName . set ( className , nextUsageCount ) ; } else { this . usageCountsByClassName . delete ( className ) ; this . injector . nullifyRule ( this . ruleIndexesByClassName . get ( className ) ! ) ; this . ruleIndexesByClassName . delete ( className ) ; } } }