Skip to content

Commit 58f492a

Browse files
committed
fix(style-context): solid-js
1 parent b375edc commit 58f492a

File tree

3 files changed

+77
-40
lines changed

3 files changed

+77
-40
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@pandacss/generator': patch
3+
---
4+
5+
**Style Context (Solid)**
6+
7+
- Fix issue where `withProvider` does not properly provide context leading to runtime errors when wrapping headless
8+
component libraries like Ark UI.
9+
10+
- Refactor `withProvider` and `withContext` types to ensure required props are properly extracted from the component
11+
props.

packages/generator/src/artifacts/solid-jsx/create-style-context.ts

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function generateSolidCreateStyleContext(ctx: Context) {
1111
${ctx.file.import(factoryName, './factory')}
1212
${ctx.file.import('getDisplayName', './factory-helper')}
1313
import { createComponent, mergeProps } from 'solid-js/web'
14-
import { createContext, useContext, createMemo } from 'solid-js'
14+
import { createContext, createMemo, splitProps, useContext } from 'solid-js'
1515
1616
export function createStyleContext(recipe) {
1717
const StyleContext = createContext({})
@@ -22,7 +22,7 @@ export function generateSolidCreateStyleContext(ctx: Context) {
2222
const { unstyled, ...restProps } = props
2323
if (unstyled) return restProps
2424
if (isConfigRecipe) {
25-
return { ...restProps, className: cx(slotStyles, restProps.className) }
25+
return { ...restProps, class: cx(slotStyles, restProps.class) }
2626
}
2727
${outdent.string(
2828
match(ctx.config.jsxStyleProps)
@@ -32,29 +32,33 @@ export function generateSolidCreateStyleContext(ctx: Context) {
3232
.otherwise(() => `return restProps`),
3333
)}
3434
}
35-
3635
3736
const withRootProvider = (Component, options) => {
3837
const WithRootProvider = (props) => {
39-
const finalProps = createMemo(() => {
40-
const [variantProps, restProps] = svaFn.splitVariantProps(props)
41-
42-
const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
43-
slotStyles._classNameMap = svaFn.classNameMap
38+
const [variantProps, otherProps] = svaFn.splitVariantProps(props)
39+
const [local, propsWithoutChildren] = splitProps(otherProps, ['children'])
40+
41+
const slotStyles = createMemo(() => {
42+
const styles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
43+
styles._classNameMap = svaFn.classNameMap
44+
return styles
45+
})
4446
45-
const mergedProps = options?.defaultProps ? mergeProps(options.defaultProps, restProps) : restProps
46-
47-
return { mergedProps, slotStyles }
47+
const mergedProps = createMemo(() => {
48+
if (!options?.defaultProps) return propsWithoutChildren
49+
return { ...options.defaultProps, ...propsWithoutChildren }
4850
})
4951
5052
return createComponent(StyleContext.Provider, {
51-
value: finalProps().slotStyles,
53+
get value() {
54+
return slotStyles()
55+
},
5256
get children() {
5357
return createComponent(
5458
Component,
55-
mergeProps(finalProps().mergedProps, {
59+
mergeProps(mergedProps, {
5660
get children() {
57-
return props.children
61+
return local.children
5862
},
5963
}),
6064
)
@@ -64,45 +68,51 @@ export function generateSolidCreateStyleContext(ctx: Context) {
6468
6569
const componentName = getDisplayName(Component)
6670
WithRootProvider.displayName = \`withRootProvider(\${componentName})\`
67-
6871
return WithRootProvider
6972
}
7073
7174
const withProvider = (Component, slot, options) => {
7275
const StyledComponent = ${factoryName}(Component, {}, options)
7376
7477
const WithProvider = (props) => {
75-
const finalProps = createMemo(() => {
76-
const [variantProps, restProps] = svaFn.splitVariantProps(props)
78+
const [variantProps, restProps] = svaFn.splitVariantProps(props)
79+
const [local, propsWithoutChildren] = splitProps(restProps, ["children"])
7780
78-
const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
79-
slotStyles._classNameMap = svaFn.classNameMap
81+
const slotStyles = createMemo(() => {
82+
const styles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
83+
styles._classNameMap = svaFn.classNameMap
84+
return styles
85+
})
8086
81-
const propsWithClass = { ...restProps, class: restProps.class ?? options?.defaultProps?.class }
82-
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
83-
resolvedProps.class = cx(resolvedProps.class, slotStyles._classNameMap[slot])
84-
85-
return { slotStyles, resolvedProps }
87+
const resolvedProps = createMemo(() => {
88+
const propsWithClass = {
89+
...propsWithoutChildren,
90+
class: propsWithoutChildren.class ?? options?.defaultProps?.class,
91+
}
92+
const resolved = getResolvedProps(propsWithClass, slotStyles()[slot])
93+
resolved.class = cx(resolved.class, slotStyles()._classNameMap[slot])
94+
return resolved
8695
})
8796
8897
return createComponent(StyleContext.Provider, {
89-
value: finalProps().slotStyles,
98+
get value() {
99+
return slotStyles()
100+
},
90101
get children() {
91102
return createComponent(
92103
StyledComponent,
93-
mergeProps(finalProps().resolvedProps, {
104+
mergeProps(resolvedProps, {
94105
get children() {
95-
return props.children
106+
return local.children
96107
},
97-
}),
108+
})
98109
)
99110
},
100111
})
101112
}
102113
103114
const componentName = getDisplayName(Component)
104115
WithProvider.displayName = \`withProvider(\${componentName})\`
105-
106116
return WithProvider
107117
}
108118
@@ -111,19 +121,30 @@ export function generateSolidCreateStyleContext(ctx: Context) {
111121
112122
const WithContext = (props) => {
113123
const slotStyles = useContext(StyleContext)
114-
const finalProps = createMemo(() => {
115-
const propsWithClass = { ...props, class: props.class ?? options?.defaultProps?.class }
116-
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
117-
resolvedProps.class = cx(resolvedProps.class, slotStyles._classNameMap?.[slot])
118-
return resolvedProps
124+
const [local, propsWithoutChildren] = splitProps(props, ["children"])
125+
126+
const resolvedProps = createMemo(() => {
127+
const propsWithClass = {
128+
...propsWithoutChildren,
129+
class: propsWithoutChildren.class ?? options?.defaultProps?.class,
130+
}
131+
const resolved = getResolvedProps(propsWithClass, slotStyles[slot])
132+
resolved.class = cx(resolved.class, slotStyles._classNameMap?.[slot])
133+
return resolved
119134
})
120135
121-
return createComponent(StyledComponent, finalProps())
136+
return createComponent(
137+
StyledComponent,
138+
mergeProps(resolvedProps, {
139+
get children() {
140+
return local.children
141+
},
142+
})
143+
)
122144
}
123145
124146
const componentName = getDisplayName(Component)
125147
WithContext.displayName = \`withContext(\${componentName})\`
126-
127148
return WithContext
128149
}
129150
@@ -144,10 +165,11 @@ export function generateSolidCreateStyleContext(ctx: Context) {
144165
unstyled?: boolean | undefined
145166
}
146167
147-
interface WithProviderOptions<P = {}> {
168+
interface WithProviderOptions<P> {
148169
defaultProps?: Partial<P> | undefined
149170
}
150-
type ElementType<P extends Record<string, any> = {}> = keyof JSX.IntrinsicElements | Component<P>
171+
172+
type ElementType = keyof JSX.IntrinsicElements | Component<any>
151173
152174
type SvaFn<S extends string = any> = SlotRecipeRuntimeFn<S, any>
153175
interface SlotRecipeFn {
@@ -157,7 +179,11 @@ export function generateSolidCreateStyleContext(ctx: Context) {
157179
}
158180
type SlotRecipe = SvaFn | SlotRecipeFn
159181
160-
type InferSlot<R extends SlotRecipe> = R extends SlotRecipeFn ? R['__slot'] : R extends SvaFn<infer S> ? S : never
182+
type InferSlot<R extends SlotRecipe> = R extends SlotRecipeFn
183+
? R['__slot']
184+
: R extends SvaFn<infer S>
185+
? S
186+
: never
161187
162188
type StyleContextProvider<T extends ElementType, R extends SlotRecipe> = Component<
163189
JsxHTMLProps<ComponentProps<T> & UnstyledProps, Assign<RecipeVariantProps<R>, JsxStyleProps>>

packages/generator/src/artifacts/solid-jsx/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export interface AsProps {
3535
as?: ElementType | undefined
3636
}
3737
38-
export type ElementType<P = any> = keyof JSX.IntrinsicElements | Component<P>
38+
export type ElementType = keyof JSX.IntrinsicElements | Component<any>
3939
4040
export interface ${componentName}<T extends ElementType, P extends Dict = {}> {
4141
(props: JsxHTMLProps<ComponentProps<T> & UnstyledProps & AsProps, Assign<JsxStyleProps, P>>): JSX.Element

0 commit comments

Comments
 (0)