Skip to content

Commit 7f06777

Browse files
authored
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.
1 parent af774e8 commit 7f06777

File tree

3 files changed

+34
-41
lines changed

3 files changed

+34
-41
lines changed

packages/tailwindcss/src/compat/apply-config-to-theme.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { DesignSystem } from '../design-system'
2+
import { ThemeOptions } from '../theme'
23
import { resolveConfig, type ConfigFile } from './config/resolve-config'
34
import type { ResolvedConfig } from './config/types'
45

@@ -24,11 +25,11 @@ export function applyConfigToTheme(designSystem: DesignSystem, configs: ConfigFi
2425

2526
for (let [path, value] of themeableValues(theme)) {
2627
let name = keyPathToCssProperty(path)
27-
designSystem.theme.add(`--${name}`, value as any, {
28-
isInline: true,
29-
isReference: true,
30-
isDefault: true,
31-
})
28+
designSystem.theme.add(
29+
`--${name}`,
30+
value as any,
31+
ThemeOptions.INLINE | ThemeOptions.REFERENCE | ThemeOptions.DEFAULT,
32+
)
3233
}
3334

3435
// If someone has updated `fontFamily.sans` or `fontFamily.mono` in a JS
@@ -38,11 +39,7 @@ export function applyConfigToTheme(designSystem: DesignSystem, configs: ConfigFi
3839
// `--font-family-sans--feature-settings` (which the `--default-font-*`
3940
// variables reference) won't exist in the generated CSS.
4041
if (Object.hasOwn(theme, 'fontFamily')) {
41-
let options = {
42-
isInline: true,
43-
isReference: false,
44-
isDefault: true,
45-
}
42+
let options = ThemeOptions.INLINE | ThemeOptions.DEFAULT
4643

4744
// Replace `--default-font-*` with `fontFamily.sans` values
4845
{

packages/tailwindcss/src/index.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { substituteFunctions, THEME_FUNCTION_INVOCATION } from './css-functions'
77
import * as CSS from './css-parser'
88
import { buildDesignSystem, type DesignSystem } from './design-system'
99
import { registerPlugins, type CssPluginOptions, type Plugin } from './plugin-api'
10-
import { Theme } from './theme'
10+
import { Theme, ThemeOptions } from './theme'
1111
import { segment } from './utils/segment'
1212

1313
const IS_VALID_UTILITY_NAME = /^[a-z][a-zA-Z0-9/%._-]*$/
@@ -26,21 +26,19 @@ function throwOnConfig(): never {
2626
}
2727

2828
function parseThemeOptions(selector: string) {
29-
let isReference = false
30-
let isInline = false
31-
let isDefault = false
29+
let options = ThemeOptions.NONE
3230

3331
for (let option of segment(selector.slice(6) /* '@theme'.length */, ' ')) {
3432
if (option === 'reference') {
35-
isReference = true
33+
options |= ThemeOptions.REFERENCE
3634
} else if (option === 'inline') {
37-
isInline = true
35+
options |= ThemeOptions.INLINE
3836
} else if (option === 'default') {
39-
isDefault = true
37+
options |= ThemeOptions.DEFAULT
4038
}
4139
}
4240

43-
return { isReference, isInline, isDefault }
41+
return options
4442
}
4543

4644
async function parseCss(
@@ -267,7 +265,7 @@ async function parseCss(
267265

268266
if (node.selector !== '@theme' && !node.selector.startsWith('@theme ')) return
269267

270-
let { isReference, isInline, isDefault } = parseThemeOptions(node.selector)
268+
let themeOptions = parseThemeOptions(node.selector)
271269

272270
// Record all custom properties in the `@theme` declaration
273271
walk(node.nodes, (child, { replaceWith }) => {
@@ -281,7 +279,7 @@ async function parseCss(
281279

282280
if (child.kind === 'comment') return
283281
if (child.kind === 'declaration' && child.property.startsWith('--')) {
284-
theme.add(child.property, child.value ?? '', { isReference, isInline, isDefault })
282+
theme.add(child.property, child.value ?? '', themeOptions)
285283
return
286284
}
287285

@@ -297,7 +295,7 @@ async function parseCss(
297295

298296
// Keep a reference to the first `@theme` rule to update with the full theme
299297
// later, and delete any other `@theme` rules.
300-
if (!firstThemeRule && !isReference) {
298+
if (!firstThemeRule && !(themeOptions & ThemeOptions.REFERENCE)) {
301299
firstThemeRule = node
302300
} else {
303301
replaceWith([])
@@ -341,7 +339,7 @@ async function parseCss(
341339
let nodes = []
342340

343341
for (let [key, value] of theme.entries()) {
344-
if (value.isReference) continue
342+
if (value.options & ThemeOptions.REFERENCE) continue
345343
nodes.push(decl(key, value.value))
346344
}
347345

packages/tailwindcss/src/theme.ts

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
import { escape } from './utils/escape'
22

3+
export const enum ThemeOptions {
4+
NONE = 0,
5+
INLINE = 1 << 0,
6+
REFERENCE = 1 << 1,
7+
DEFAULT = 1 << 2,
8+
}
9+
310
export class Theme {
4-
constructor(
5-
private values = new Map<
6-
string,
7-
{ value: string; isReference: boolean; isInline: boolean; isDefault: boolean }
8-
>(),
9-
) {}
10-
11-
add(
12-
key: string,
13-
value: string,
14-
{ isReference = false, isInline = false, isDefault = false } = {},
15-
): void {
11+
constructor(private values = new Map<string, { value: string; options: number }>()) {}
12+
13+
add(key: string, value: string, options = ThemeOptions.NONE): void {
1614
if (key.endsWith('-*')) {
1715
if (value !== 'initial') {
1816
throw new Error(`Invalid theme value \`${value}\` for namespace \`${key}\``)
@@ -24,15 +22,15 @@ export class Theme {
2422
}
2523
}
2624

27-
if (isDefault) {
25+
if (options & ThemeOptions.DEFAULT) {
2826
let existing = this.values.get(key)
29-
if (existing && !existing.isDefault) return
27+
if (existing && !(existing.options & ThemeOptions.DEFAULT)) return
3028
}
3129

3230
if (value === 'initial') {
3331
this.values.delete(key)
3432
} else {
35-
this.values.set(key, { value, isReference, isInline, isDefault })
33+
this.values.set(key, { value, options })
3634
}
3735
}
3836

@@ -68,7 +66,7 @@ export class Theme {
6866
}
6967

7068
hasDefault(key: string): boolean {
71-
return this.values.get(key)?.isDefault ?? false
69+
return ((this.values.get(key)?.options ?? 0) & ThemeOptions.DEFAULT) === ThemeOptions.DEFAULT
7270
}
7371

7472
entries() {
@@ -111,7 +109,7 @@ export class Theme {
111109

112110
let value = this.values.get(themeKey)!
113111

114-
if (value.isInline) {
112+
if (value.options & ThemeOptions.INLINE) {
115113
return value.value
116114
}
117115

@@ -141,7 +139,7 @@ export class Theme {
141139
let nestedValue = this.values.get(nestedKey)!
142140
if (!nestedValue) continue
143141

144-
if (nestedValue.isInline) {
142+
if (nestedValue.options & ThemeOptions.INLINE) {
145143
extra[name] = nestedValue.value
146144
} else {
147145
extra[name] = this.#var(nestedKey)!
@@ -150,7 +148,7 @@ export class Theme {
150148

151149
let value = this.values.get(themeKey)!
152150

153-
if (value.isInline) {
151+
if (value.options & ThemeOptions.INLINE) {
154152
return [value.value, extra]
155153
}
156154

0 commit comments

Comments
 (0)