| 83 | } |
| 84 | |
| 85 | function theme( |
| 86 | designSystem: DesignSystem, |
| 87 | source: AstNode, |
| 88 | path: string, |
| 89 | ...fallback: string[] |
| 90 | ): string { |
| 91 | if (!path.startsWith(class="st">'--')) { |
| 92 | throw new Error(`The --theme(…) function can only be used with CSS variables from your theme.`) |
| 93 | } |
| 94 | |
| 95 | let inline = false |
| 96 | |
| 97 | class="cm">// Handle `--theme(… inline)` to force inline resolution |
| 98 | if (path.endsWith(class="st">' inline')) { |
| 99 | inline = true |
| 100 | path = path.slice(0, -7) |
| 101 | } |
| 102 | |
| 103 | class="cm">// If the `--theme(…)` function is used within an at-rule (e.g. `@media (width >= --theme(…)))`, |
| 104 | class="cm">// we have to always inline the result since CSS does not support CSS variables in these positions |
| 105 | if (source.kind === class="st">'at-rule') { |
| 106 | inline = true |
| 107 | } |
| 108 | |
| 109 | let resolvedValue = designSystem.resolveThemeValue(path, inline) |
| 110 | |
| 111 | if (!resolvedValue) { |
| 112 | if (fallback.length > 0) return fallback.join(class="st">', ') |
| 113 | throw new Error( |
| 114 | `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.`, |
| 115 | ) |
| 116 | } |
| 117 | |
| 118 | if (fallback.length === 0) { |
| 119 | return resolvedValue |
| 120 | } |
| 121 | |
| 122 | let joinedFallback = fallback.join(class="st">', ') |
| 123 | if (joinedFallback === class="st">'initial') return resolvedValue |
| 124 | |
| 125 | class="cm">// When the resolved value returns `initial`, resolve with the fallback value |
| 126 | if (resolvedValue === class="st">'initial') return joinedFallback |
| 127 | |
| 128 | class="cm">// Inject the fallback of a `--theme(…)` function into the fallback of a referenced `--theme(…)` |
| 129 | class="cm">// function or `var(…)` declaration. If the referenced function already defines a fallback, we use |
| 130 | class="cm">// a potential fallback value of `initial` in the referenced function to determine if we should |
| 131 | class="cm">// inject the fallback value of the caller. If that's not the case, we keep the fallback as-is |
| 132 | class="cm">// (this is needed for theme variables in reference-mode). |
| 133 | if ( |
| 134 | resolvedValue.startsWith(class="st">'var(') || |
| 135 | resolvedValue.startsWith(class="st">'theme(') || |
| 136 | resolvedValue.startsWith(class="st">'--theme(') |
| 137 | ) { |
| 138 | let valueAst = ValueParser.parse(resolvedValue) |
| 139 | injectFallbackForInitialFallback(valueAst, joinedFallback) |
| 140 | return ValueParser.toCss(valueAst) |
| 141 | } |
| 142 | |