@@ -5,14 +5,17 @@ import { withAlpha } from './utilities'
55import { segment } from './utils/segment'
66import * as ValueParser from './value-parser'
77
8- const functions : Record < string , ( designSystem : DesignSystem , ...args : string [ ] ) => string > = {
8+ const CSS_FUNCTIONS : Record <
9+ string ,
10+ ( designSystem : DesignSystem , source : AstNode , ...args : string [ ] ) => string
11+ > = {
912 '--alpha' : alpha ,
1013 '--spacing' : spacing ,
1114 '--theme' : theme ,
1215 theme : legacyTheme ,
1316}
1417
15- function alpha ( _designSystem : DesignSystem , value : string , ...rest : string [ ] ) {
18+ function alpha ( _designSystem : DesignSystem , _source : AstNode , value : string , ...rest : string [ ] ) {
1619 let [ color , alpha ] = segment ( value , '/' ) . map ( ( v ) => v . trim ( ) )
1720
1821 if ( ! color || ! alpha ) {
@@ -30,7 +33,7 @@ function alpha(_designSystem: DesignSystem, value: string, ...rest: string[]) {
3033 return withAlpha ( color , alpha )
3134}
3235
33- function spacing ( designSystem : DesignSystem , value : string , ...rest : string [ ] ) {
36+ function spacing ( designSystem : DesignSystem , _source : AstNode , value : string , ...rest : string [ ] ) {
3437 if ( ! value ) {
3538 throw new Error ( `The --spacing(…) function requires an argument, but received none.` )
3639 }
@@ -51,27 +54,44 @@ function spacing(designSystem: DesignSystem, value: string, ...rest: string[]) {
5154 return `calc(${ multiplier } * ${ value } )`
5255}
5356
54- function theme ( designSystem : DesignSystem , path : string , ...fallback : string [ ] ) {
57+ function theme ( designSystem : DesignSystem , source : AstNode , path : string , ...fallback : string [ ] ) {
5558 if ( ! path . startsWith ( '--' ) ) {
5659 throw new Error ( `The --theme(…) function can only be used with CSS variables from your theme.` )
5760 }
5861
59- let resolvedValue = designSystem . resolveThemeValue ( path )
62+ let inline = false
63+ if ( path . endsWith ( ' inline' ) ) {
64+ inline = true
65+ path = path . slice ( 0 , - 7 )
66+ }
67+
68+ // If the `--theme(…)` function is used within an at-rule (e.g. `@media (width >= theme(…)))`, we
69+ // have to always inline the result since CSS does not support CSS variables in these positions.
70+ if ( source . kind === 'at-rule' ) {
71+ inline = true
72+ }
73+
74+ let resolvedValue = designSystem . resolveThemeValue ( path , inline )
6075
6176 if ( ! resolvedValue && fallback . length > 0 ) {
6277 return fallback . join ( ', ' )
6378 }
6479
6580 if ( ! resolvedValue ) {
6681 throw new Error (
67- `Could not resolve value for theme function: \`theme(${ path } )\`. Consider checking if the path is correct or provide a fallback value to silence this error.` ,
82+ `Could not resolve value for theme function: \`theme(${ path } )\`. Consider checking if the variable name is correct or provide a fallback value to silence this error.` ,
6883 )
6984 }
7085
7186 return resolvedValue
7287}
7388
74- function legacyTheme ( designSystem : DesignSystem , path : string , ...fallback : string [ ] ) {
89+ function legacyTheme (
90+ designSystem : DesignSystem ,
91+ _source : AstNode ,
92+ path : string ,
93+ ...fallback : string [ ]
94+ ) {
7595 path = eventuallyUnquote ( path )
7696
7797 let resolvedValue = designSystem . resolveThemeValue ( path )
@@ -90,7 +110,7 @@ function legacyTheme(designSystem: DesignSystem, path: string, ...fallback: stri
90110}
91111
92112export const THEME_FUNCTION_INVOCATION = new RegExp (
93- Object . keys ( functions )
113+ Object . keys ( CSS_FUNCTIONS )
94114 . map ( ( x ) => `${ x } \\(` )
95115 . join ( '|' ) ,
96116)
@@ -101,7 +121,7 @@ export function substituteFunctions(ast: AstNode[], designSystem: DesignSystem)
101121 // Find all declaration values
102122 if ( node . kind === 'declaration' && node . value && THEME_FUNCTION_INVOCATION . test ( node . value ) ) {
103123 features |= Features . ThemeFunction
104- node . value = substituteFunctionsInValue ( node . value , designSystem )
124+ node . value = substituteFunctionsInValue ( node . value , node , designSystem )
105125 return
106126 }
107127
@@ -115,19 +135,27 @@ export function substituteFunctions(ast: AstNode[], designSystem: DesignSystem)
115135 THEME_FUNCTION_INVOCATION . test ( node . params )
116136 ) {
117137 features |= Features . ThemeFunction
118- node . params = substituteFunctionsInValue ( node . params , designSystem )
138+ node . params = substituteFunctionsInValue ( node . params , node , designSystem )
119139 }
120140 }
121141 } )
122142 return features
123143}
124144
125- export function substituteFunctionsInValue ( value : string , designSystem : DesignSystem ) : string {
145+ export function substituteFunctionsInValue (
146+ value : string ,
147+ source : AstNode ,
148+ designSystem : DesignSystem ,
149+ ) : string {
126150 let ast = ValueParser . parse ( value )
127151 ValueParser . walk ( ast , ( node , { replaceWith } ) => {
128- if ( node . kind === 'function' && node . value in functions ) {
152+ if ( node . kind === 'function' && node . value in CSS_FUNCTIONS ) {
129153 let args = segment ( ValueParser . toCss ( node . nodes ) . trim ( ) , ',' ) . map ( ( x ) => x . trim ( ) )
130- let result = functions [ node . value as keyof typeof functions ] ( designSystem , ...args )
154+ let result = CSS_FUNCTIONS [ node . value as keyof typeof CSS_FUNCTIONS ] (
155+ designSystem ,
156+ source ,
157+ ...args ,
158+ )
131159 return replaceWith ( ValueParser . parse ( result ) )
132160 }
133161 } )
0 commit comments