Skip to content

Commit

Permalink
fix(patterns): JSX patterns props passing with jsxStyleProps set to m…
Browse files Browse the repository at this point in the history
…inimal/none (#1767)

* fix(patterns): with jsxStyleProps set to minimal/none

* chore: jsx pattern rest/styleprops output

* wip: mergeCss with styleProps.minimal

* fix: mergeCss on config.jsxStyleProps minimal

* refactor: patterns jsx

* fix: vue pattern

* refactor: codegen tests jsx import source

* chore: refactor

---------

Co-authored-by: Segun Adebayo <[email protected]>
  • Loading branch information
astahmer and segunadebayo authored Dec 21, 2023
1 parent 4402ddc commit d30b173
Show file tree
Hide file tree
Showing 44 changed files with 1,452 additions and 329 deletions.
6 changes: 6 additions & 0 deletions .changeset/friendly-peas-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@pandacss/generator': patch
---

Fix issue where style props wouldn't be properly passed when using `config.jsxStyleProps` set to `minimal` or `none`
with JSX patterns (`Box`, `Stack`, `Flex`, etc.)
45 changes: 34 additions & 11 deletions packages/generator/src/artifacts/preact-jsx/pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { match } from 'ts-pattern'
import type { Context } from '../../engines'

export function generatePreactJsxPattern(ctx: Context, filters?: ArtifactFilters) {
const { typeName, factoryName } = ctx.jsx
const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx

const details = ctx.patterns.filterDetails(filters)

Expand All @@ -17,25 +17,48 @@ export function generatePreactJsxPattern(ctx: Context, filters?: ArtifactFilters
js: outdent`
import { h } from 'preact'
import { forwardRef } from 'preact/compat'
${ctx.file.import(factoryName, './factory')}
${ctx.file.import('mergeCss', '../css/css')}
${ctx.file.import('splitProps', '../helpers')}
${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
${ctx.file.import(factoryName, './factory')}
export const ${jsxName} = /* @__PURE__ */ forwardRef(function ${jsxName}(props, ref) {
${match(props.length)
${match(jsxStyleProps)
.with(
'none',
() => outdent`
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const Comp = ${factoryName}("${jsxElement}", { base: styleProps })
return h(Comp, { ref, ...restProps })
`,
)
.with(
0,
'minimal',
() => outdent`
const styleProps = ${styleFnName}()
return h(${factoryName}.${jsxElement}, { ref, ...styleProps, ...props })
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const cssProps = { css: mergeCss(styleProps, props.css) }
const mergedProps = { ref, ...restProps, ...cssProps }
return h(${factoryName}.${jsxElement}, mergedProps)
`,
)
.otherwise(
.with(
'all',
() => outdent`
const { ${props.join(', ')}, ...restProps } = props
const styleProps = ${styleFnName}({${props.join(', ')}})
return h(${factoryName}.${jsxElement}, { ref, ...styleProps, ...restProps })
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const mergedProps = { ref, ...styleProps, ...restProps }
return h(${factoryName}.${jsxElement}, mergedProps)
`,
)}
)
.exhaustive()}
})
`,

Expand Down
47 changes: 35 additions & 12 deletions packages/generator/src/artifacts/qwik-jsx/pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { match } from 'ts-pattern'
import type { Context } from '../../engines'

export function generateQwikJsxPattern(ctx: Context, filters?: ArtifactFilters) {
const { typeName, factoryName } = ctx.jsx
const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx

const details = ctx.patterns.filterDetails(filters)

Expand All @@ -16,25 +16,48 @@ export function generateQwikJsxPattern(ctx: Context, filters?: ArtifactFilters)
name: dashName,
js: outdent`
import { h } from '@builder.io/qwik'
${ctx.file.import(factoryName, './factory')}
${ctx.file.import('mergeCss', '../css/css')}
${ctx.file.import('splitProps', '../helpers')}
${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
${ctx.file.import(factoryName, './factory')}
export const ${jsxName} = function ${jsxName}(props) {
${match(props.length)
export const ${jsxName} = /* @__PURE__ */ function ${jsxName}(props) {
${match(jsxStyleProps)
.with(
0,
'none',
() => outdent`
const styleProps = ${styleFnName}()
return h(${factoryName}.${jsxElement}, { ...styleProps, ...props })
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const Comp = ${factoryName}("${jsxElement}", { base: styleProps })
return h(Comp, restProps)
`,
)
.otherwise(
.with(
'minimal',
() => outdent`
const { ${props.join(', ')}, ...restProps } = props
const styleProps = ${styleFnName}({${props.join(', ')}})
return h(${factoryName}.${jsxElement}, { ...styleProps, ...restProps })
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const cssProps = { css: mergeCss(styleProps, props.css) }
const mergedProps = { ...restProps, ...cssProps }
return h(${factoryName}.${jsxElement}, mergedProps)
`,
)}
)
.with(
'all',
() => outdent`
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const mergedProps = { ...styleProps, ...restProps }
return h(${factoryName}.${jsxElement}, mergedProps)
`,
)
.exhaustive()}
}
`,

Expand Down
47 changes: 35 additions & 12 deletions packages/generator/src/artifacts/react-jsx/pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { match } from 'ts-pattern'
import type { Context } from '../../engines'

export function generateReactJsxPattern(ctx: Context, filters?: ArtifactFilters) {
const { typeName, factoryName } = ctx.jsx
const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx

const details = ctx.patterns.filterDetails(filters)

Expand All @@ -16,26 +16,49 @@ export function generateReactJsxPattern(ctx: Context, filters?: ArtifactFilters)
name: dashName,
js: outdent`
import { createElement, forwardRef } from 'react'
${ctx.file.import(factoryName, './factory')}
${ctx.file.import('mergeCss', '../css/css')}
${ctx.file.import('splitProps', '../helpers')}
${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
${ctx.file.import(factoryName, './factory')}
export const ${jsxName} = /* @__PURE__ */ forwardRef(function ${jsxName}(props, ref) {
${match(props.length)
${match(jsxStyleProps)
.with(
'none',
() => outdent`
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const Comp = ${factoryName}("${jsxElement}", { base: styleProps })
return createElement(Comp, { ref, ...restProps })
`,
)
.with(
0,
'minimal',
() => outdent`
const styleProps = ${styleFnName}()
return createElement(${factoryName}.${jsxElement}, { ref, ...styleProps, ...props })
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const cssProps = { css: mergeCss(styleProps, props.css) }
const mergedProps = { ref, ...restProps, ...cssProps }
return createElement(${factoryName}.${jsxElement}, mergedProps)
`,
)
.otherwise(
.with(
'all',
() => outdent`
const { ${props.join(', ')}, ...restProps } = props
const styleProps = ${styleFnName}({${props.join(', ')}})
return createElement(${factoryName}.${jsxElement}, { ref, ...styleProps, ...restProps })
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const mergedProps = { ref, ...styleProps, ...restProps }
return createElement(${factoryName}.${jsxElement}, mergedProps)
`,
)}
})
)
.exhaustive()}
})
`,

dts: outdent`
Expand Down
48 changes: 36 additions & 12 deletions packages/generator/src/artifacts/solid-jsx/pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { match } from 'ts-pattern'
import type { Context } from '../../engines'

export function generateSolidJsxPattern(ctx: Context, filters?: ArtifactFilters) {
const { typeName, factoryName } = ctx.jsx
const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx

const details = ctx.patterns.filterDetails(filters)

Expand All @@ -15,27 +15,51 @@ export function generateSolidJsxPattern(ctx: Context, filters?: ArtifactFilters)
return {
name: dashName,
js: outdent`
import { splitProps, mergeProps } from 'solid-js'
import { createMemo, mergeProps, splitProps } from 'solid-js'
import { createComponent } from 'solid-js/web'
${ctx.file.import(factoryName, './factory')}
${ctx.file.import('mergeCss', '../css/css')}
${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
${ctx.file.import(factoryName, './factory')}
export function ${jsxName}(props) {
${match(props.length)
export const ${jsxName} = /* @__PURE__ */ function ${jsxName}(props) {
${match(jsxStyleProps)
.with(
0,
'none',
() => outdent`
const styleProps = ${styleFnName}()
return createComponent(${factoryName}.${jsxElement}, mergeProps(styleProps, props))
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const Comp = ${factoryName}("${jsxElement}", { base: styleProps })
return createComponent(Comp, restProps)
`,
)
.otherwise(
.with(
'minimal',
() => outdent`
const [patternProps, restProps] = splitProps(props, [${props.map((v) => JSON.stringify(v)).join(', ')}]);
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const cssProps = createMemo(() => {
const styleProps = ${styleFnName}(patternProps)
return createComponent(${factoryName}.${jsxElement}, mergeProps(styleProps, restProps))
return { css: mergeCss(styleProps, props.css) }
})
const mergedProps = mergeProps(restProps, cssProps)
return createComponent(${factoryName}.${jsxElement}, mergedProps)
`,
)}
)
.with(
'all',
() => outdent`
const [patternProps, restProps] = splitProps(props, ${JSON.stringify(props)})
const styleProps = ${styleFnName}(patternProps)
const mergedProps = mergeProps(styleProps, restProps)
return createComponent(${factoryName}.${jsxElement}, mergedProps)
`,
)
.exhaustive()}
}
`,

Expand Down
2 changes: 1 addition & 1 deletion packages/generator/src/artifacts/vue-jsx/jsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function generateVueJsxFactory(ctx: Context) {
const combinedProps = computed(() => Object.assign({}, defaultProps, attrs))
const splittedProps = computed(() => {
return splitProps(combinedProps.value, normalizeHTMLProps.keys, shouldForwardProp, __cvaFn__.variantKeys, isCssProperty)
return splitProps(combinedProps.value, normalizeHTMLProps.keys, __shouldForwardProps__, __cvaFn__.variantKeys, isCssProperty)
})
const recipeClass = computed(() => {
Expand Down
50 changes: 43 additions & 7 deletions packages/generator/src/artifacts/vue-jsx/pattern.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,70 @@
import type { ArtifactFilters } from '@pandacss/types'
import { outdent } from 'outdent'
import { match } from 'ts-pattern'
import type { Context } from '../../engines'

export function generateVueJsxPattern(ctx: Context, filters?: ArtifactFilters) {
const { typeName, factoryName } = ctx.jsx
const { typeName, factoryName, styleProps: jsxStyleProps } = ctx.jsx

const details = ctx.patterns.filterDetails(filters)

return details.map((pattern) => {
const { upperName, styleFnName, dashName, jsxName, props, blocklistType } = pattern
const { description, jsxElement = 'div' } = pattern.config
const propList = props.map((v) => JSON.stringify(v)).join(', ')

return {
name: dashName,
js: outdent`
import { defineComponent, h, computed } from 'vue'
${ctx.file.import(factoryName, './factory')}
${ctx.file.import('mergeCss', '../css/css')}
${ctx.file.import(styleFnName, `../patterns/${dashName}`)}
${ctx.file.import(factoryName, './factory')}
export const ${jsxName} = defineComponent({
export const ${jsxName} = /* @__PURE__ */ defineComponent({
name: '${jsxName}',
inheritAttrs: false,
props: [${propList}],
props: ${JSON.stringify(props)},
setup(props, { attrs, slots }) {
${match(jsxStyleProps)
.with(
'none',
() => outdent`
const Comp = computed(() => {
const styleProps = ${styleFnName}(props)
return ${factoryName}("${jsxElement}", { base: styleProps })
})
return () => {
return h(Comp.value, attrs, slots)
}
`,
)
.with(
'minimal',
() => outdent`
const cssProps = computed(() => {
const styleProps = ${styleFnName}(props)
return { css: mergeCss(styleProps, attrs.css) }
})
return () => {
const mergedProps = { ...attrs, ...cssProps.value }
return h(${factoryName}.${jsxElement}, mergedProps, slots)
}
`,
)
.with(
'all',
() => outdent`
const styleProps = computed(() => ${styleFnName}(props))
return () => {
const computedProps = { ...styleProps.value, ...attrs }
return h(${factoryName}.${jsxElement}, computedProps, slots)
const mergedProps = { ...styleProps.value, ...attrs }
return h(${factoryName}.${jsxElement}, mergedProps, slots)
}
`,
)
.exhaustive()}
}
})
`,
Expand Down
Loading

3 comments on commit d30b173

@vercel
Copy link

@vercel vercel bot commented on d30b173 Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on d30b173 Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

panda-docs – ./website

panda-docs-chakra-ui.vercel.app
panda-docs-git-main-chakra-ui.vercel.app
panda-docs.vercel.app
panda-css.com

@vercel
Copy link

@vercel vercel bot commented on d30b173 Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

panda-studio – ./

panda-studio-chakra-ui.vercel.app
panda-app.vercel.app
panda-studio-git-main-chakra-ui.vercel.app

Please sign in to comment.