Skip to content

Commit

Permalink
refactor(unplugin): HMR + transform (#46)
Browse files Browse the repository at this point in the history
* fix(unplugin): outfile HMR

* wip e2e test with vitest + playwright

* test: make snapshot of scenarios folder before running tests / restore original state after

* chore: simplify stuff

* test: add virtual-file scenario

* chore: rm unused deps

* feat(unplugin): optimizeJs by default

* feat: transform cva to optimized fn

* chore: copy test from unplugin-panda-macro to unplugin
refactor: dont transform cva for unplugin-panda-macro

* chore: dont version panda.css file

* feat(unplugin): granular JS optimization logic + ignore `with { type: "runtime" }`

* chore: add changeset
  • Loading branch information
astahmer authored Apr 1, 2024
1 parent 8b2726e commit c1b48fd
Show file tree
Hide file tree
Showing 55 changed files with 2,601 additions and 82 deletions.
20 changes: 20 additions & 0 deletions .changeset/fifty-doors-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'@pandabox/unplugin': minor
---

- Fix CSS generation when using `outfile`

- Add `optimizeJs` option to optionally transform your source code by inlining the `css` / `cva` / `${patternFn}`
resulting classNames or even simplify `styled` JSX factory to their primitive HTML tags (originally coming from
`@pandabox/unplugin-panda-macro`)

-> This is enabled by default and can be disabled by setting `optimizeJs` to `false` or `"macro"` (to only transform
functions using `with { type: "macro" }`)

- Transform `cva` to an optimized string-version of the `cva` function :

-> Style objects are converted to class strings, this might not work when styles should be merged and you can opt-out
of this by using `with { type: "runtime" }` on your `cva` import or by setting `optimizeJs` to false (or `macro` to
only transform functions using `with { type: "macro" }`)

- Add e2e tests (in-browser + HMR)
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ pnpm-debug.log*
styled-system
.vercel
.turbo
scenarios-temp
panda.css
12 changes: 12 additions & 0 deletions packages/unplugin-panda-macro/__tests__/samples/only-cva.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ const atomicRecipe = cva({
lg: { padding: '8', fontSize: '24px' },
},
},
compoundVariants: [
{
visual: 'outline',
size: 'lg',
css: {
borderWidth: '3px',
},
},
],
defaultVariants: {
visual: 'solid',
},
})

export const App = () => {
Expand Down
88 changes: 84 additions & 4 deletions packages/unplugin-panda-macro/__tests__/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,33 @@ describe('atomic', () => {
"import 'virtual:panda.css'
import { cva } from '../styled-system/css'
const atomicRecipe = () => ""
const atomicRecipe = cva({
base: {
display: 'flex',
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' },
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' },
},
},
compoundVariants: [
{
visual: 'outline',
size: 'lg',
css: {
borderWidth: '3px',
},
},
],
defaultVariants: {
visual: 'solid',
},
})
export const App = () => {
return <div className="d_flex bg_red.200 text_white p_4 fs_12px">Atomic Button</div>
Expand Down Expand Up @@ -351,7 +377,21 @@ describe('atomic', () => {
bg: 'green.100',
})
const atomicRecipe = () => ""
const atomicRecipe = cva({
base: {
display: 'flex',
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' },
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' },
},
},
})
export const App = () => {
return (
Expand Down Expand Up @@ -662,7 +702,33 @@ describe('grouped', () => {
"import 'virtual:panda.css'
import { cva } from '../styled-system/css'
const atomicRecipe = () => ""
const atomicRecipe = cva({
base: {
display: 'flex',
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' },
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' },
},
},
compoundVariants: [
{
visual: 'outline',
size: 'lg',
css: {
borderWidth: '3px',
},
},
],
defaultVariants: {
visual: 'solid',
},
})
export const App = () => {
return <div className="kUuLsR">Atomic Button</div>
Expand Down Expand Up @@ -777,7 +843,21 @@ describe('grouped', () => {
bg: 'green.100',
})
const atomicRecipe = () => ""
const atomicRecipe = cva({
base: {
display: 'flex',
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' },
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' },
},
},
})
export const App = () => {
return (
Expand Down
1 change: 1 addition & 0 deletions packages/unplugin-panda-macro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"@pandacss/shared": "^0.36.1",
"@rollup/pluginutils": "^5.1.0",
"magic-string": "^0.30.7",
"outdent": "^0.8.0",
"postcss": "^8.4.35",
"ts-morph": "21.0.1",
"unplugin": "^1.7.1"
Expand Down
10 changes: 9 additions & 1 deletion packages/unplugin-panda-macro/src/plugin/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,15 @@ export const unpluginFactory: UnpluginFactory<PluginOptions | undefined> = (rawO
const parserResult = panda.project.parseSourceFile(id)
if (!parserResult) return null

return tranformPanda(ctx, { code, id, output: options.output, sourceFile, parserResult })
return tranformPanda(ctx, {
code,
id,
output: options.output,
sourceFile,
parserResult,
keepRecipeClassNames: options.keepRecipeClassNames,
onlyMacroImports: options.onlyMacroImports,
})
},
vite: {
async handleHotUpdate(hmr: HmrContext) {
Expand Down
12 changes: 3 additions & 9 deletions packages/unplugin-panda-macro/src/plugin/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { box, extractCallExpressionArguments, unbox } from '@pandacss/extractor'
import { toHash } from '@pandacss/shared'
import { type ParserResultInterface, type SystemStyleObject, type RecipeConfig } from '@pandacss/types'
import MagicString from 'magic-string'
import { CallExpression, ImportDeclaration, Node, SourceFile } from 'ts-morph'
import { CallExpression, Node, SourceFile } from 'ts-morph'

import { type MacroContext } from './create-context'
import { createCva } from './create-cva'
Expand Down Expand Up @@ -196,14 +196,8 @@ export const tranformPanda = (ctx: MacroContext, options: TransformArgs) => {
const varName = getVariableName(node)
if (!varName) return

cvaConfigs.set(varName, {
config: recipe,
resolve: createCva(recipe, mergeCss),
})

// Replace cva declarations with a dummy function, in case it's exported and used elsewhere
// `const xxx = cva({ ... })` -> `const xxx = () => ""`
s.update(node.getStart(), node.getEnd(), '() => ""')
const resolve = createCva(recipe, mergeCss)
cvaConfigs.set(varName, { config: recipe, resolve })
})

// Replace cva usages with the result of the function call
Expand Down
6 changes: 5 additions & 1 deletion packages/unplugin/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,8 @@ dist

## Panda
styled-system
styled-system-studio
styled-system-studio

src/panda.css
playground/panda.css
panda.css
4 changes: 4 additions & 0 deletions packages/unplugin/__tests__/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module '*?raw' {
const src: string
export default src
}
30 changes: 30 additions & 0 deletions packages/unplugin/__tests__/samples/css-with-raw.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'virtual:panda.css'
import { css } from '../styled-system/css'

const overrides = css.raw({
bg: 'green.100',
})

export const App = () => {
return (
<div
className={css(
{
display: 'flex',
flexDirection: 'column',
fontWeight: 'semibold',
color: 'green.300',
textAlign: 'center',
textStyle: '4xl',
},
{
bg: 'yellow.200',
color: 'red.500',
},
overrides,
)}
>
<span>Hello from Panda</span>
</div>
)
}
53 changes: 53 additions & 0 deletions packages/unplugin/__tests__/samples/full.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { css, cva } from '../styled-system/css'
import { center } from '../styled-system/patterns'
import { button } from '../styled-system/recipes'
import 'virtual:panda.css'

const overrides = css.raw({
bg: 'green.100',
})

const atomicRecipe = cva({
base: {
display: 'flex',
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' },
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' },
},
},
})

export const App = () => {
return (
<div className={center({ h: 'full' })}>
<div
className={css(
{
display: 'flex',
flexDirection: 'column',
fontWeight: 'semibold',
color: 'green.300',
textAlign: 'center',
textStyle: '4xl',
},
{
bg: 'yellow.200',
color: 'red.500',
},
overrides,
)}
>
<span>🐼</span>
<span>Hello from Panda</span>
</div>
<div className={button({ visual: 'funky', size: 'lg' })}>Button</div>
<div className={atomicRecipe({ visual: 'solid', size: 'sm' })}>Atomic Button</div>
</div>
)
}
19 changes: 19 additions & 0 deletions packages/unplugin/__tests__/samples/only-css-raw.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'virtual:panda.css'
import { css } from '../styled-system/css'

const styles = css.raw({
display: 'flex',
flexDirection: 'column',
fontWeight: 'semibold',
color: 'green.300',
textAlign: 'center',
textStyle: '4xl',
})

export const App = () => {
return (
<div>
<span>Hello from Panda</span>
</div>
)
}
19 changes: 19 additions & 0 deletions packages/unplugin/__tests__/samples/only-css.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'virtual:panda.css'
import { css } from '../styled-system/css'

export const App = () => {
return (
<div
className={css({
display: 'flex',
flexDirection: 'column',
fontWeight: 'semibold',
color: 'green.300',
textAlign: 'center',
textStyle: '4xl',
})}
>
<span>Hello from Panda</span>
</div>
)
}
34 changes: 34 additions & 0 deletions packages/unplugin/__tests__/samples/only-cva.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'virtual:panda.css'
import { cva } from '../styled-system/css'

const atomicRecipe = cva({
base: {
display: 'flex',
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' },
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' },
},
},
compoundVariants: [
{
visual: 'outline',
size: 'lg',
css: {
borderWidth: '3px',
},
},
],
defaultVariants: {
visual: 'solid',
},
})

export const App = () => {
return <div className={atomicRecipe({ visual: 'solid', size: 'sm' })}>Atomic Button</div>
}
Loading

0 comments on commit c1b48fd

Please sign in to comment.