move cached parsers to designSystem
This commit is contained in:
parent
d04a17c102
commit
115417fed4
7 changed files with 137 additions and 176 deletions
|
|
@ -1,9 +1,8 @@
|
|||
import { scanDir } from '@tailwindcss/oxide'
|
||||
import { bench } from 'vitest'
|
||||
import { parseCandidate, parseVariant } from './candidate'
|
||||
import { parseCandidate } from './candidate'
|
||||
import { buildDesignSystem } from './design-system'
|
||||
import { Theme } from './theme'
|
||||
import { DefaultMap } from './utils/default-map'
|
||||
|
||||
// FOLDER=path/to/folder vitest bench
|
||||
const root = process.env.FOLDER || process.cwd()
|
||||
|
|
@ -15,10 +14,6 @@ const designSystem = buildDesignSystem(new Theme())
|
|||
|
||||
bench('parseCandidate', () => {
|
||||
for (let candidate of result.candidates) {
|
||||
parseCandidate(
|
||||
candidate,
|
||||
designSystem.utilities,
|
||||
new DefaultMap((variant, map) => parseVariant(variant, designSystem.variants, map)),
|
||||
)
|
||||
parseCandidate(candidate, designSystem)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { parseCandidate, parseVariant } from './candidate'
|
||||
import { buildDesignSystem } from './design-system'
|
||||
import { Theme } from './theme'
|
||||
import { Utilities } from './utilities'
|
||||
import { DefaultMap } from './utils/default-map'
|
||||
import { Variants } from './variants'
|
||||
|
||||
function run(
|
||||
|
|
@ -11,11 +11,12 @@ function run(
|
|||
utilities ??= new Utilities()
|
||||
variants ??= new Variants()
|
||||
|
||||
let parsedVariants = new DefaultMap((variant, map) => {
|
||||
return parseVariant(variant, variants!, map)
|
||||
})
|
||||
let designSystem = buildDesignSystem(new Theme())
|
||||
|
||||
return parseCandidate(candidate, utilities, parsedVariants)
|
||||
designSystem.utilities = utilities
|
||||
designSystem.variants = variants
|
||||
|
||||
return designSystem.parseCandidate(candidate)
|
||||
}
|
||||
|
||||
it('should skip unknown utilities', () => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import type { DesignSystem } from './design-system'
|
||||
import { decodeArbitraryValue } from './utils/decode-arbitrary-value'
|
||||
import { segment } from './utils/segment'
|
||||
|
||||
|
|
@ -206,14 +207,7 @@ export type Candidate =
|
|||
important: boolean
|
||||
}
|
||||
|
||||
export function parseCandidate(
|
||||
input: string,
|
||||
utilities: {
|
||||
has: (value: string) => boolean
|
||||
kind: (root: string) => Omit<Candidate['kind'], 'arbitrary'>
|
||||
},
|
||||
parsedVariants: { get: (value: string) => Variant | null },
|
||||
): Candidate | null {
|
||||
export function parseCandidate(input: string, designSystem: DesignSystem): Candidate | null {
|
||||
// hover:focus:underline
|
||||
// ^^^^^ ^^^^^^ -> Variants
|
||||
// ^^^^^^^^^ -> Base
|
||||
|
|
@ -228,7 +222,7 @@ export function parseCandidate(
|
|||
let parsedCandidateVariants: Variant[] = []
|
||||
|
||||
for (let variant of rawVariants) {
|
||||
let parsedVariant = parsedVariants.get(variant)
|
||||
let parsedVariant = designSystem.parseVariant(variant)
|
||||
if (parsedVariant === null) return null
|
||||
|
||||
// Variants are applied left-to-right meaning that any representing pseudo-
|
||||
|
|
@ -320,7 +314,7 @@ export function parseCandidate(
|
|||
base = base.slice(1)
|
||||
}
|
||||
|
||||
let [root, value] = findRoot(base, utilities)
|
||||
let [root, value] = findRoot(base, designSystem.utilities)
|
||||
|
||||
let modifierSegment: string | null = null
|
||||
|
||||
|
|
@ -335,13 +329,13 @@ export function parseCandidate(
|
|||
modifierSegment = rootModifierSegment
|
||||
|
||||
// Try to find the root and value, without the modifier present
|
||||
;[root, value] = findRoot(rootWithoutModifier, utilities)
|
||||
;[root, value] = findRoot(rootWithoutModifier, designSystem.utilities)
|
||||
}
|
||||
|
||||
// If there's no root, the candidate isn't a valid class and can be discarded.
|
||||
if (root === null) return null
|
||||
|
||||
let kind = utilities.kind(root)
|
||||
let kind = designSystem.utilities.kind(root)
|
||||
|
||||
if (kind === 'static') {
|
||||
if (value !== null) return null
|
||||
|
|
@ -475,15 +469,7 @@ function parseModifier(modifier: string): CandidateModifier {
|
|||
}
|
||||
}
|
||||
|
||||
export function parseVariant(
|
||||
variant: string,
|
||||
variants: {
|
||||
has: (value: string) => boolean
|
||||
kind: (root: string) => Omit<Variant['kind'], 'arbitrary'>
|
||||
compounds: (root: string) => boolean
|
||||
},
|
||||
parsedVariants: { get: (value: string) => Variant | null },
|
||||
): Variant | null {
|
||||
export function parseVariant(variant: string, designSystem: DesignSystem): Variant | null {
|
||||
// Arbitrary variants
|
||||
if (variant[0] === '[' && variant[variant.length - 1] === ']') {
|
||||
/**
|
||||
|
|
@ -535,20 +521,20 @@ export function parseVariant(
|
|||
// - `group-hover/foo/bar`
|
||||
if (additionalModifier) return null
|
||||
|
||||
let [root, value] = findRoot(variantWithoutModifier, variants)
|
||||
let [root, value] = findRoot(variantWithoutModifier, designSystem.variants)
|
||||
|
||||
// Variant is invalid, therefore the candidate is invalid and we can skip
|
||||
// continue parsing it.
|
||||
if (root === null) return null
|
||||
|
||||
switch (variants.kind(root)) {
|
||||
switch (designSystem.variants.kind(root)) {
|
||||
case 'static': {
|
||||
if (value !== null) return null
|
||||
|
||||
return {
|
||||
kind: 'static',
|
||||
root,
|
||||
compounds: variants.compounds(root),
|
||||
compounds: designSystem.variants.compounds(root),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -564,7 +550,7 @@ export function parseVariant(
|
|||
kind: 'arbitrary',
|
||||
value: decodeArbitraryValue(value.slice(1, -1)),
|
||||
},
|
||||
compounds: variants.compounds(root),
|
||||
compounds: designSystem.variants.compounds(root),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -573,14 +559,14 @@ export function parseVariant(
|
|||
root,
|
||||
modifier: modifier === null ? null : parseModifier(modifier),
|
||||
value: { kind: 'named', value },
|
||||
compounds: variants.compounds(root),
|
||||
compounds: designSystem.variants.compounds(root),
|
||||
}
|
||||
}
|
||||
|
||||
case 'compound': {
|
||||
if (value === null) return null
|
||||
|
||||
let subVariant = parsedVariants.get(value)
|
||||
let subVariant = designSystem.parseVariant(value)
|
||||
if (subVariant === null) return null
|
||||
if (subVariant.compounds === false) return null
|
||||
|
||||
|
|
@ -589,7 +575,7 @@ export function parseVariant(
|
|||
root,
|
||||
modifier: modifier === null ? null : { kind: 'named', value: modifier },
|
||||
variant: subVariant,
|
||||
compounds: variants.compounds(root),
|
||||
compounds: designSystem.variants.compounds(root),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,102 +1,14 @@
|
|||
import { rule, type AstNode, type Rule } from './ast'
|
||||
import { parseCandidate, parseVariant, type Candidate, type Variant } from './candidate'
|
||||
import { type Candidate, type Variant } from './candidate'
|
||||
import { type DesignSystem } from './design-system'
|
||||
import GLOBAL_PROPERTY_ORDER from './property-order'
|
||||
import { DefaultMap } from './utils/default-map'
|
||||
import { escape } from './utils/escape'
|
||||
import type { Variants } from './variants'
|
||||
|
||||
export function createParsedVariants(
|
||||
designSystem: DesignSystem,
|
||||
): DefaultMap<string, Variant | null> {
|
||||
return new DefaultMap((variant, map) => {
|
||||
return parseVariant(variant, designSystem.variants, map)
|
||||
})
|
||||
}
|
||||
|
||||
export function createParsedCandidates(
|
||||
designSystem: DesignSystem,
|
||||
parsedVariants: DefaultMap<string, Variant | null>,
|
||||
) {
|
||||
return new DefaultMap((candidate) => {
|
||||
return parseCandidate(candidate, designSystem.utilities, parsedVariants)
|
||||
})
|
||||
}
|
||||
|
||||
export function createParsedAstNodes(
|
||||
designSystem: DesignSystem,
|
||||
parsedCandidates: DefaultMap<string, Candidate | null>,
|
||||
) {
|
||||
return new DefaultMap((rawCandidate: string) => {
|
||||
let candidate = parsedCandidates.get(rawCandidate)
|
||||
if (candidate === null) return null
|
||||
|
||||
let nodes: AstNode[] = []
|
||||
|
||||
// Handle arbitrary properties
|
||||
if (candidate.kind === 'arbitrary') {
|
||||
let compileFn = designSystem.utilities.getArbitrary()
|
||||
|
||||
// Build the node
|
||||
let compiledNodes = compileFn(candidate)
|
||||
if (compiledNodes === undefined) return null
|
||||
|
||||
nodes = compiledNodes
|
||||
}
|
||||
|
||||
// Handle named utilities
|
||||
else if (candidate.kind === 'static' || candidate.kind === 'functional') {
|
||||
// Safety: At this point it is safe to use TypeScript's non-null assertion
|
||||
// operator because if the `candidate.root` didn't exist, `parseCandidate`
|
||||
// would have returned `null` and we would have returned early resulting
|
||||
// in not hitting this code path.
|
||||
let { compileFn } = designSystem.utilities.get(candidate.root)!
|
||||
|
||||
// Build the node
|
||||
let compiledNodes = compileFn(candidate)
|
||||
if (compiledNodes === undefined) return null
|
||||
|
||||
nodes = compiledNodes
|
||||
}
|
||||
|
||||
let propertySort = getPropertySort(nodes)
|
||||
|
||||
if (candidate.important) {
|
||||
applyImportant(nodes)
|
||||
}
|
||||
|
||||
let node: Rule = {
|
||||
kind: 'rule',
|
||||
selector: `.${escape(rawCandidate)}`,
|
||||
nodes,
|
||||
}
|
||||
|
||||
for (let variant of candidate.variants) {
|
||||
let result = applyVariant(node, variant, designSystem.variants)
|
||||
|
||||
// When the variant results in `null`, it means that the variant cannot be
|
||||
// applied to the rule. Discard the candidate and continue to the next
|
||||
// one.
|
||||
if (result === null) return null
|
||||
}
|
||||
|
||||
return {
|
||||
node,
|
||||
propertySort,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function compileCandidates(
|
||||
rawCandidates: Iterable<string>,
|
||||
designSystem: DesignSystem,
|
||||
{
|
||||
parsedVariants = createParsedVariants(designSystem),
|
||||
parsedCandidates = createParsedCandidates(designSystem, parsedVariants),
|
||||
parsedAstNodes = createParsedAstNodes(designSystem, parsedCandidates),
|
||||
invalidRawCandidates = new Set<string>(),
|
||||
throwOnInvalidCandidate = false,
|
||||
} = {},
|
||||
{ throwOnInvalidCandidate = false } = {},
|
||||
) {
|
||||
let nodeSorting = new Map<
|
||||
AstNode,
|
||||
|
|
@ -107,30 +19,30 @@ export function compileCandidates(
|
|||
|
||||
// Parse candidates and variants
|
||||
for (let rawCandidate of rawCandidates) {
|
||||
let candidate = parsedCandidates.get(rawCandidate)
|
||||
let candidate = designSystem.parseCandidate(rawCandidate)
|
||||
if (candidate === null) {
|
||||
if (throwOnInvalidCandidate) {
|
||||
throw new Error(`Cannot apply unknown utility class: ${rawCandidate}`)
|
||||
}
|
||||
invalidRawCandidates.add(rawCandidate)
|
||||
designSystem.invalidRawCandidates.add(rawCandidate)
|
||||
continue // Bail, invalid candidate
|
||||
}
|
||||
candidates.set(candidate, rawCandidate)
|
||||
}
|
||||
|
||||
// Sort the variants
|
||||
let variants = Array.from(parsedVariants.values()).sort((a, z) => {
|
||||
let variants = Array.from(designSystem.parsedVariants.values()).sort((a, z) => {
|
||||
return designSystem.variants.compare(a, z)
|
||||
})
|
||||
|
||||
// Create the AST
|
||||
next: for (let [candidate, rawCandidate] of candidates) {
|
||||
let astNode = parsedAstNodes.get(rawCandidate)
|
||||
let astNode = designSystem.parseAstNode(rawCandidate)
|
||||
if (astNode === null) {
|
||||
if (throwOnInvalidCandidate) {
|
||||
throw new Error(`Cannot apply unknown utility class: ${rawCandidate}`)
|
||||
}
|
||||
invalidRawCandidates.add(rawCandidate)
|
||||
designSystem.invalidRawCandidates.add(rawCandidate)
|
||||
continue next
|
||||
}
|
||||
|
||||
|
|
@ -191,6 +103,65 @@ export function compileCandidates(
|
|||
}
|
||||
}
|
||||
|
||||
export function parseAstNodes(rawCandidate: string, designSystem: DesignSystem) {
|
||||
let candidate = designSystem.parseCandidate(rawCandidate)
|
||||
if (candidate === null) return null
|
||||
|
||||
let nodes: AstNode[] = []
|
||||
|
||||
// Handle arbitrary properties
|
||||
if (candidate.kind === 'arbitrary') {
|
||||
let compileFn = designSystem.utilities.getArbitrary()
|
||||
|
||||
// Build the node
|
||||
let compiledNodes = compileFn(candidate)
|
||||
if (compiledNodes === undefined) return null
|
||||
|
||||
nodes = compiledNodes
|
||||
}
|
||||
|
||||
// Handle named utilities
|
||||
else if (candidate.kind === 'static' || candidate.kind === 'functional') {
|
||||
// Safety: At this point it is safe to use TypeScript's non-null assertion
|
||||
// operator because if the `candidate.root` didn't exist, `parseCandidate`
|
||||
// would have returned `null` and we would have returned early resulting
|
||||
// in not hitting this code path.
|
||||
let { compileFn } = designSystem.utilities.get(candidate.root)!
|
||||
|
||||
// Build the node
|
||||
let compiledNodes = compileFn(candidate)
|
||||
if (compiledNodes === undefined) return null
|
||||
|
||||
nodes = compiledNodes
|
||||
}
|
||||
|
||||
let propertySort = getPropertySort(nodes)
|
||||
|
||||
if (candidate.important) {
|
||||
applyImportant(nodes)
|
||||
}
|
||||
|
||||
let node: Rule = {
|
||||
kind: 'rule',
|
||||
selector: `.${escape(rawCandidate)}`,
|
||||
nodes,
|
||||
}
|
||||
|
||||
for (let variant of candidate.variants) {
|
||||
let result = applyVariant(node, variant, designSystem.variants)
|
||||
|
||||
// When the variant results in `null`, it means that the variant cannot be
|
||||
// applied to the rule. Discard the candidate and continue to the next
|
||||
// one.
|
||||
if (result === null) return null
|
||||
}
|
||||
|
||||
return {
|
||||
node,
|
||||
propertySort,
|
||||
}
|
||||
}
|
||||
|
||||
export function applyVariant(node: Rule, variant: Variant, variants: Variants): null | void {
|
||||
if (variant.kind === 'arbitrary') {
|
||||
node.nodes = [rule(variant.selector, node.nodes)]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import { toCss } from './ast'
|
||||
import { compileCandidates } from './compile'
|
||||
import { parseCandidate, parseVariant } from './candidate'
|
||||
import { compileCandidates, parseAstNodes as parseAstNode } from './compile'
|
||||
import { getClassList, getVariants, type ClassEntry, type VariantEntry } from './intellisense'
|
||||
import { getClassOrder } from './sort'
|
||||
import type { Theme } from './theme'
|
||||
import { Utilities, createUtilities } from './utilities'
|
||||
import { DefaultMap } from './utils/default-map'
|
||||
import { Variants, createVariants } from './variants'
|
||||
|
||||
export type DesignSystem = {
|
||||
|
|
@ -15,13 +17,35 @@ export type DesignSystem = {
|
|||
getClassOrder(classes: string[]): [string, bigint | null][]
|
||||
getClassList(): ClassEntry[]
|
||||
getVariants(): VariantEntry[]
|
||||
|
||||
parseCandidate(candidate: string): ReturnType<typeof parseCandidate>
|
||||
parseVariant(variant: string): ReturnType<typeof parseVariant>
|
||||
parseAstNode(candidate: string): ReturnType<typeof parseAstNode>
|
||||
|
||||
parsedCandidates: DefaultMap<string, ReturnType<typeof parseCandidate>>
|
||||
parsedVariants: DefaultMap<string, ReturnType<typeof parseVariant>>
|
||||
parsedAstNodes: DefaultMap<string, ReturnType<typeof parseAstNode>>
|
||||
|
||||
invalidRawCandidates: Set<string>
|
||||
}
|
||||
|
||||
export function buildDesignSystem(theme: Theme): DesignSystem {
|
||||
return {
|
||||
let utilities = createUtilities(theme)
|
||||
let variants = createVariants(theme)
|
||||
let invalidRawCandidates = new Set<string>()
|
||||
|
||||
let parsedVariants = new DefaultMap((variant) => parseVariant(variant, designSystem))
|
||||
let parsedCandidates = new DefaultMap((candidate) => parseCandidate(candidate, designSystem))
|
||||
let parsedAstNodes = new DefaultMap((candidate) => parseAstNode(candidate, designSystem))
|
||||
|
||||
let designSystem: DesignSystem = {
|
||||
theme,
|
||||
utilities: createUtilities(theme),
|
||||
variants: createVariants(theme),
|
||||
utilities,
|
||||
variants,
|
||||
parsedCandidates,
|
||||
parsedVariants,
|
||||
parsedAstNodes,
|
||||
invalidRawCandidates,
|
||||
|
||||
candidatesToCss(classes: string[]) {
|
||||
let result: (string | null)[] = []
|
||||
|
|
@ -47,5 +71,17 @@ export function buildDesignSystem(theme: Theme): DesignSystem {
|
|||
getVariants() {
|
||||
return getVariants(this)
|
||||
},
|
||||
|
||||
parseCandidate(candidate: string) {
|
||||
return parsedCandidates.get(candidate)
|
||||
},
|
||||
parseVariant(variant: string) {
|
||||
return parsedVariants.get(variant)
|
||||
},
|
||||
parseAstNode(candidate: string) {
|
||||
return parsedAstNodes.get(candidate)
|
||||
},
|
||||
}
|
||||
|
||||
return designSystem
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
import { Features, transform } from 'lightningcss'
|
||||
import { version } from '../package.json'
|
||||
import { WalkAction, comment, decl, rule, toCss, walk, type AstNode, type Rule } from './ast'
|
||||
import {
|
||||
compileCandidates,
|
||||
createParsedAstNodes,
|
||||
createParsedCandidates,
|
||||
createParsedVariants,
|
||||
} from './compile'
|
||||
import { compileCandidates } from './compile'
|
||||
import * as CSS from './css-parser'
|
||||
import { buildDesignSystem } from './design-system'
|
||||
import { Theme } from './theme'
|
||||
|
|
@ -107,10 +102,6 @@ export function compile(
|
|||
}
|
||||
|
||||
let designSystem = buildDesignSystem(theme)
|
||||
let invalidRawCandidates = new Set<string>()
|
||||
let parsedVariants = createParsedVariants(designSystem)
|
||||
let parsedCandidates = createParsedCandidates(designSystem, parsedVariants)
|
||||
let parsedAstNodes = createParsedAstNodes(designSystem, parsedCandidates)
|
||||
|
||||
let tailwindUtilitiesNode: Rule | null = null
|
||||
|
||||
|
|
@ -121,12 +112,7 @@ export function compile(
|
|||
tailwindUtilitiesNode = node
|
||||
|
||||
// Set the `@tailwind utilities` nodes, to the actual generated CSS
|
||||
node.nodes = compileCandidates(rawCandidates, designSystem, {
|
||||
parsedVariants,
|
||||
parsedCandidates,
|
||||
parsedAstNodes,
|
||||
invalidRawCandidates,
|
||||
}).astNodes
|
||||
node.nodes = compileCandidates(rawCandidates, designSystem).astNodes
|
||||
|
||||
// Stop walking after finding `@tailwind utilities` to avoid walking all
|
||||
// of the generated CSS. This means `@tailwind utilities` can only appear
|
||||
|
|
@ -148,10 +134,6 @@ export function compile(
|
|||
{
|
||||
// Parse the candidates to an AST that we can replace the `@apply` rule with.
|
||||
let candidateAst = compileCandidates(candidates, designSystem, {
|
||||
parsedVariants,
|
||||
parsedCandidates,
|
||||
parsedAstNodes,
|
||||
invalidRawCandidates,
|
||||
throwOnInvalidCandidate: true,
|
||||
}).astNodes
|
||||
|
||||
|
|
@ -194,7 +176,7 @@ export function compile(
|
|||
|
||||
let allValidCandidates = new Set<string>()
|
||||
for (let rawCandidate of rawCandidates) {
|
||||
if (!invalidRawCandidates.has(rawCandidate)) {
|
||||
if (!designSystem.invalidRawCandidates.has(rawCandidate)) {
|
||||
allValidCandidates.add(rawCandidate)
|
||||
}
|
||||
}
|
||||
|
|
@ -205,7 +187,7 @@ export function compile(
|
|||
// Add all new candidates unless we know that they are invalid.
|
||||
let previousSize = allValidCandidates.size
|
||||
for (let candidate of newRawCandidates) {
|
||||
if (!invalidRawCandidates.has(candidate)) {
|
||||
if (!designSystem.invalidRawCandidates.has(candidate)) {
|
||||
allValidCandidates.add(candidate)
|
||||
}
|
||||
}
|
||||
|
|
@ -217,18 +199,13 @@ export function compile(
|
|||
}
|
||||
|
||||
if (tailwindUtilitiesNode) {
|
||||
let previousAstNodeCount = parsedAstNodes.size
|
||||
let newNodes = compileCandidates(allValidCandidates, designSystem, {
|
||||
parsedVariants,
|
||||
parsedCandidates,
|
||||
parsedAstNodes,
|
||||
invalidRawCandidates,
|
||||
}).astNodes
|
||||
let previousAstNodeCount = designSystem.parsedAstNodes.size
|
||||
let newNodes = compileCandidates(allValidCandidates, designSystem).astNodes
|
||||
|
||||
// If no new ast nodes were generated, then we can return the original
|
||||
// CSS. This currently assumes that we only add new ast nodes and never
|
||||
// remove any.
|
||||
if (previousAstNodeCount === parsedAstNodes.size) {
|
||||
if (previousAstNodeCount === designSystem.parsedAstNodes.size) {
|
||||
return compiledCss
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { decl, rule } from './ast'
|
||||
import { parseVariant, type Variant } from './candidate'
|
||||
import { applyVariant } from './compile'
|
||||
import type { DesignSystem } from './design-system'
|
||||
import { DefaultMap } from './utils/default-map'
|
||||
|
||||
interface ClassMetadata {
|
||||
modifiers: string[]
|
||||
|
|
@ -60,9 +58,6 @@ export interface VariantEntry {
|
|||
|
||||
export function getVariants(design: DesignSystem) {
|
||||
let list: VariantEntry[] = []
|
||||
let parsedVariants = new DefaultMap<string, Variant | null>((variant, map) =>
|
||||
parseVariant(variant, design.variants, map),
|
||||
)
|
||||
|
||||
for (let [root, variant] of design.variants.entries()) {
|
||||
if (variant.kind === 'arbitrary') continue
|
||||
|
|
@ -74,7 +69,7 @@ export function getVariants(design: DesignSystem) {
|
|||
if (value) name += `-${value}`
|
||||
if (modifier) name += `/${modifier}`
|
||||
|
||||
let variant = parsedVariants.get(name)
|
||||
let variant = design.parseVariant(name)
|
||||
|
||||
if (!variant) return []
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue