forked from cschroeter/park-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate-style-context.tsx
59 lines (54 loc) · 1.56 KB
/
create-style-context.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import {
createComponent,
createContext,
mergeProps,
useContext,
type ComponentProps,
type ValidComponent,
} from 'solid-js'
import { Dynamic } from 'solid-js/web'
type GenericProps = Record<string, unknown>
type StyleRecipe = {
(props: GenericProps): Record<string, string>
splitVariantProps: (props: GenericProps) => any
}
export const createStyleContext = <R extends StyleRecipe>(recipe: R) => {
const StyleContext = createContext<Record<string, string> | null>(null)
const withProvider = <T extends ValidComponent, P = ComponentProps<T>>(
Component: T,
slot?: string,
) => {
const StyledComponent = (props: P & Parameters<R>[0]) => {
const [variantProps, componentProps] = recipe.splitVariantProps(props)
const styleProperties = recipe(variantProps)
return (
<StyleContext.Provider value={styleProperties}>
<Dynamic
component={Component}
class={styleProperties?.[slot ?? '']}
{...componentProps}
/>
</StyleContext.Provider>
)
}
return StyledComponent
}
const withContext = <T extends ValidComponent, P = ComponentProps<T>>(
Component: T,
slot?: string,
): T => {
if (!slot) return Component
const StyledComponent = (props: P) => {
const styleProperties = useContext(StyleContext)
return createComponent(
Dynamic,
mergeProps(props, { component: Component, class: styleProperties?.[slot ?? ''] }),
)
}
return StyledComponent as T
}
return {
withProvider,
withContext,
}
}