@@ -16,10 +16,91 @@ import { className, getDebugName } from "../utils.js";
1616
1717// == Global CSS ===============================================================
1818export function globalCss ( selector : string , rule : GlobalCSSRule ) {
19- gStyle ( selector , transform ( rule ) as GlobalStyleRule ) ;
19+ const transformedStyle = transform ( {
20+ selectors : {
21+ [ selector ] : {
22+ ...rule
23+ }
24+ }
25+ } ) as CSSRule ;
26+
27+ const { selectors, ...atRuleStyles } = transformedStyle ;
28+ if ( selectors !== undefined ) {
29+ Object . entries ( selectors ) . forEach ( ( [ selector , styles ] ) => {
30+ gStyle ( selector , styles as GlobalStyleRule ) ;
31+ } ) ;
32+ }
33+
34+ if ( atRuleStyles !== undefined ) {
35+ const otherStyles = hoistSelectors ( atRuleStyles ) ;
36+ Object . entries ( otherStyles . selectors ) . forEach ( ( [ atRule , atRuleStyles ] ) => {
37+ gStyle ( atRule , atRuleStyles as GlobalStyleRule ) ;
38+ } ) ;
39+ }
2040}
2141export const globalStyle = globalCss ;
2242
43+ // TODO: Make more type-safe
44+ type UnknownObject = Record < string , unknown > ;
45+ type CSSRuleMap = Record < string , CSSRule > ;
46+ interface HoistResult {
47+ selectors : CSSRuleMap ;
48+ }
49+
50+ function hoistSelectors ( input : CSSRule ) : HoistResult {
51+ const result : HoistResult = {
52+ selectors : { }
53+ } ;
54+
55+ function processAtRules ( obj : UnknownObject , path : string [ ] = [ ] ) {
56+ for ( const key in obj ) {
57+ if ( key === "selectors" ) {
58+ // Hoist each selector when selectors are found
59+ const selectors = obj [ key ] as CSSRuleMap ;
60+ for ( const selector in selectors ) {
61+ if ( ! result . selectors [ selector ] ) {
62+ result . selectors [ selector ] = { } ;
63+ }
64+
65+ // Create nested object structure based on current path
66+ let current = result . selectors [ selector ] as UnknownObject ;
67+ for ( let i = 0 ; i < path . length ; i += 2 ) {
68+ const atRule = path [ i ] ;
69+ const condition = path [ i + 1 ] ;
70+
71+ if ( ! current [ atRule ] ) {
72+ current [ atRule ] = { } ;
73+ }
74+ const atRuleObj = current [ atRule ] as UnknownObject ;
75+ if ( ! atRuleObj [ condition ] ) {
76+ atRuleObj [ condition ] = { } ;
77+ }
78+
79+ current = atRuleObj [ condition ] as UnknownObject ;
80+ }
81+
82+ // Copy style properties
83+ Object . assign ( current , selectors [ selector ] ) ;
84+ }
85+ } else if ( typeof obj [ key ] === "object" && obj [ key ] !== null ) {
86+ // at-rule found (e.g: @media, @supports)
87+ const atRules = obj [ key ] as UnknownObject ;
88+ for ( const condition in atRules ) {
89+ // Add current at-rule and condition to path and recursively call
90+ processAtRules ( atRules [ condition ] as UnknownObject , [
91+ ...path ,
92+ key ,
93+ condition
94+ ] ) ;
95+ }
96+ }
97+ }
98+ }
99+
100+ processAtRules ( input as UnknownObject ) ;
101+ return result ;
102+ }
103+
23104// == CSS ======================================================================
24105export function css ( style : ComplexCSSRule , debugId ?: string ) {
25106 return vStyle ( transform ( style ) , debugId ) ;
0 commit comments