Use a bit flags for theme options instead of an object with booleans (#14337)

This PR is a small improvement to the theme options where it's just a
simple number now instead of an object with booleans.
This commit is contained in:
Robin Malfait 2024-09-06 00:38:43 +02:00 committed by GitHub
parent af774e8f24
commit 7f06777d6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 41 deletions

View File

@ -1,4 +1,5 @@
import type { DesignSystem } from '../design-system'
import { ThemeOptions } from '../theme'
import { resolveConfig, type ConfigFile } from './config/resolve-config'
import type { ResolvedConfig } from './config/types'
@ -24,11 +25,11 @@ export function applyConfigToTheme(designSystem: DesignSystem, configs: ConfigFi
for (let [path, value] of themeableValues(theme)) {
let name = keyPathToCssProperty(path)
designSystem.theme.add(`--${name}`, value as any, {
isInline: true,
isReference: true,
isDefault: true,
})
designSystem.theme.add(
`--${name}`,
value as any,
ThemeOptions.INLINE | ThemeOptions.REFERENCE | ThemeOptions.DEFAULT,
)
}
// If someone has updated `fontFamily.sans` or `fontFamily.mono` in a JS
@ -38,11 +39,7 @@ export function applyConfigToTheme(designSystem: DesignSystem, configs: ConfigFi
// `--font-family-sans--feature-settings` (which the `--default-font-*`
// variables reference) won't exist in the generated CSS.
if (Object.hasOwn(theme, 'fontFamily')) {
let options = {
isInline: true,
isReference: false,
isDefault: true,
}
let options = ThemeOptions.INLINE | ThemeOptions.DEFAULT
// Replace `--default-font-*` with `fontFamily.sans` values
{

View File

@ -7,7 +7,7 @@ import { substituteFunctions, THEME_FUNCTION_INVOCATION } from './css-functions'
import * as CSS from './css-parser'
import { buildDesignSystem, type DesignSystem } from './design-system'
import { registerPlugins, type CssPluginOptions, type Plugin } from './plugin-api'
import { Theme } from './theme'
import { Theme, ThemeOptions } from './theme'
import { segment } from './utils/segment'
const IS_VALID_UTILITY_NAME = /^[a-z][a-zA-Z0-9/%._-]*$/
@ -26,21 +26,19 @@ function throwOnConfig(): never {
}
function parseThemeOptions(selector: string) {
let isReference = false
let isInline = false
let isDefault = false
let options = ThemeOptions.NONE
for (let option of segment(selector.slice(6) /* '@theme'.length */, ' ')) {
if (option === 'reference') {
isReference = true
options |= ThemeOptions.REFERENCE
} else if (option === 'inline') {
isInline = true
options |= ThemeOptions.INLINE
} else if (option === 'default') {
isDefault = true
options |= ThemeOptions.DEFAULT
}
}
return { isReference, isInline, isDefault }
return options
}
async function parseCss(
@ -267,7 +265,7 @@ async function parseCss(
if (node.selector !== '@theme' && !node.selector.startsWith('@theme ')) return
let { isReference, isInline, isDefault } = parseThemeOptions(node.selector)
let themeOptions = parseThemeOptions(node.selector)
// Record all custom properties in the `@theme` declaration
walk(node.nodes, (child, { replaceWith }) => {
@ -281,7 +279,7 @@ async function parseCss(
if (child.kind === 'comment') return
if (child.kind === 'declaration' && child.property.startsWith('--')) {
theme.add(child.property, child.value ?? '', { isReference, isInline, isDefault })
theme.add(child.property, child.value ?? '', themeOptions)
return
}
@ -297,7 +295,7 @@ async function parseCss(
// Keep a reference to the first `@theme` rule to update with the full theme
// later, and delete any other `@theme` rules.
if (!firstThemeRule && !isReference) {
if (!firstThemeRule && !(themeOptions & ThemeOptions.REFERENCE)) {
firstThemeRule = node
} else {
replaceWith([])
@ -341,7 +339,7 @@ async function parseCss(
let nodes = []
for (let [key, value] of theme.entries()) {
if (value.isReference) continue
if (value.options & ThemeOptions.REFERENCE) continue
nodes.push(decl(key, value.value))
}

View File

@ -1,18 +1,16 @@
import { escape } from './utils/escape'
export class Theme {
constructor(
private values = new Map<
string,
{ value: string; isReference: boolean; isInline: boolean; isDefault: boolean }
>(),
) {}
export const enum ThemeOptions {
NONE = 0,
INLINE = 1 << 0,
REFERENCE = 1 << 1,
DEFAULT = 1 << 2,
}
add(
key: string,
value: string,
{ isReference = false, isInline = false, isDefault = false } = {},
): void {
export class Theme {
constructor(private values = new Map<string, { value: string; options: number }>()) {}
add(key: string, value: string, options = ThemeOptions.NONE): void {
if (key.endsWith('-*')) {
if (value !== 'initial') {
throw new Error(`Invalid theme value \`${value}\` for namespace \`${key}\``)
@ -24,15 +22,15 @@ export class Theme {
}
}
if (isDefault) {
if (options & ThemeOptions.DEFAULT) {
let existing = this.values.get(key)
if (existing && !existing.isDefault) return
if (existing && !(existing.options & ThemeOptions.DEFAULT)) return
}
if (value === 'initial') {
this.values.delete(key)
} else {
this.values.set(key, { value, isReference, isInline, isDefault })
this.values.set(key, { value, options })
}
}
@ -68,7 +66,7 @@ export class Theme {
}
hasDefault(key: string): boolean {
return this.values.get(key)?.isDefault ?? false
return ((this.values.get(key)?.options ?? 0) & ThemeOptions.DEFAULT) === ThemeOptions.DEFAULT
}
entries() {
@ -111,7 +109,7 @@ export class Theme {
let value = this.values.get(themeKey)!
if (value.isInline) {
if (value.options & ThemeOptions.INLINE) {
return value.value
}
@ -141,7 +139,7 @@ export class Theme {
let nestedValue = this.values.get(nestedKey)!
if (!nestedValue) continue
if (nestedValue.isInline) {
if (nestedValue.options & ThemeOptions.INLINE) {
extra[name] = nestedValue.value
} else {
extra[name] = this.#var(nestedKey)!
@ -150,7 +148,7 @@ export class Theme {
let value = this.values.get(themeKey)!
if (value.isInline) {
if (value.options & ThemeOptions.INLINE) {
return [value.value, extra]
}