Skip to content

Commit

Permalink
fix(templates): infer variants types in generated theme
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamincanac committed Dec 18, 2024
1 parent 607792e commit 2c99bb8
Showing 1 changed file with 28 additions and 10 deletions.
38 changes: 28 additions & 10 deletions src/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,47 @@ export function getTemplates(options: ModuleOptions, uiConfig: Record<string, an
const template = (theme as any)[component]
const result = typeof template === 'function' ? template(options) : template

const variants = Object.keys(result.variants || {})
const variants = Object.entries(result.variants || {})
.filter(([_, values]) => {
const keys = Object.keys(values as Record<string, unknown>)
return keys.some(key => key !== 'true' && key !== 'false')
})
.map(([key]) => key)

let json = JSON.stringify(result, null, 2)

for (const variant of variants) {
json = json.replace(new RegExp(`("${variant}": "[^"]+")`, 'g'), '$1 as const')
json = json.replace(new RegExp(`("${variant}": "[^"]+")`, 'g'), `$1 as typeof ${variant}[number]`)
json = json.replace(new RegExp(`("${variant}": \\[\\s*)((?:"[^"]+",?\\s*)+)(\\])`, 'g'), (_, before, match, after) => {
const replaced = match.replace(/("[^"]+")/g, '$1 as const')
const replaced = match.replace(/("[^"]+")/g, `$1 as typeof ${variant}[number]`)
return `${before}${replaced}${after}`
})
}

// For local development, directly import from theme
function generateVariantDeclarations(variants: string[]) {
return variants.map((variant) => {
const keys = Object.keys(result.variants[variant])
return `const ${variant} = ${JSON.stringify(keys, null, 2)} as const`
})
}

// For local development, import directly from theme
if (process.env.DEV) {
const templatePath = fileURLToPath(new URL(`./theme/${kebabCase(component)}`, import.meta.url))
return [
`import template from ${JSON.stringify(fileURLToPath(new URL(`./theme/${kebabCase(component)}`, import.meta.url)))}`,
`const result = typeof template === 'function' ? template(${JSON.stringify(options)}) : template`,
`const json = ${json}`,
`export default result as typeof json`
].join('\n')
`import template from ${JSON.stringify(templatePath)}`,
...generateVariantDeclarations(variants),
`const result = typeof template === 'function' ? template(${JSON.stringify(options, null, 2)}) : template`,
`const theme = ${json}`,
`export default result as typeof theme`
].join('\n\n')
}

return `export default ${json}`
// For production build
return [
...generateVariantDeclarations(variants),
`export default ${json}`
].join('\n\n')
}
})
}
Expand Down

0 comments on commit 2c99bb8

Please sign in to comment.