@pandabox/unplugin
Version:
Panda CSS as a Vite/Rollup/Webpack/Esbuild plugin
95 lines (79 loc) • 2.83 kB
text/typescript
import { compact } from '@pandacss/shared'
import { type RecipeConfig } from '@pandacss/types'
import { type PandaPluginContext } from './create-context'
type Cva = Pick<RecipeConfig, 'base' | 'variants' | 'compoundVariants'>
const defaults = (conf: Cva) => ({
base: {},
variants: {},
defaultVariants: {},
compoundVariants: [],
...conf,
})
export const createCva = (config: Cva, mergeCss: PandaPluginContext['mergeCss']) => {
const { base, variants, defaultVariants, compoundVariants } = defaults(config)
function resolve(props = {}) {
const computedVariants = { ...defaultVariants, ...compact(props) }
let variantCss = { ...base }
for (const [key, value] of Object.entries(computedVariants)) {
const variantStyleObj = variants[key]?.[value as any]
if (variantStyleObj) {
variantCss = mergeCss(variantCss, variantStyleObj)
}
}
const compoundVariantCss = getCompoundVariantCss(compoundVariants, computedVariants, mergeCss)
return mergeCss(variantCss, compoundVariantCss)
}
return resolve
}
function getCompoundVariantCss(
compoundVariants: any[],
variantMap: Record<string, string>,
mergeCss: PandaPluginContext['mergeCss'],
) {
let result = {}
compoundVariants.forEach((compoundVariant) => {
const isMatching = Object.entries(compoundVariant).every(([key, value]) => {
if (key === 'css') return true
const values = Array.isArray(value) ? value : [value]
return values.some((value) => variantMap[key] === value)
})
if (isMatching) {
result = mergeCss(result, compoundVariant.css)
}
})
return result
}
export const transformCva = (
name: string,
config: Pick<RecipeConfig, 'base' | 'variants' | 'compoundVariants'>,
css: PandaPluginContext['css'],
) => {
const { base, variants, defaultVariants, compoundVariants } = defaults(config)
return `(function () {
const base = ${JSON.stringify(css(base))}
const variantStyles = ${JSON.stringify(
Object.fromEntries(
Object.entries(variants).map(([variantKey, variantMap]) => [
variantKey,
Object.fromEntries(
Object.entries(variantMap).map(([valueKey, variantStyle]) => [valueKey, css(variantStyle)]),
),
]),
),
null,
2,
)}
const defaultVariants = ${JSON.stringify(defaultVariants)}
return function ${name}(variants) {
${
compoundVariants.length > 0
? `
const classList = [inlineCva(base, defaultVariants, variantStyles, variants)]
const compoundVariants = ${JSON.stringify(compoundVariants)}
addCompoundVariantCss(compoundVariants, variantProps, classList)
return classList.join(' ')`
: `return inlineCva(base, defaultVariants, variantStyles, variants)`
}
}
})()`
}