/
system.ts
93 lines (84 loc) · 2.6 KB
/
system.ts
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import {
css,
isStyleProp,
StyleProps,
SystemStyleObject,
} from "@chakra-ui/styled-system"
import { Dict, filterUndefined, objectFilter, runIfFn } from "@chakra-ui/utils"
import _styled, { CSSObject, FunctionInterpolation } from "@emotion/styled"
import { shouldForwardProp } from "./should-forward-prop"
import { As, ChakraComponent, ChakraProps, PropsOf } from "./system.types"
import { DOMElements } from "./system.utils"
type StyleResolverProps = SystemStyleObject & {
__css?: SystemStyleObject
sx?: SystemStyleObject
theme: any
css?: CSSObject
}
interface GetStyleObject {
(options: {
baseStyle?:
| SystemStyleObject
| ((props: StyleResolverProps) => SystemStyleObject)
}): FunctionInterpolation<StyleResolverProps>
}
/**
* Style resolver function that manages how style props are merged
* in combination with other possible ways of defining styles.
*
* For example, take a component defined this way:
* ```jsx
* <Box fontSize="24px" sx={{ fontSize: "40px" }}></Box>
* ```
*
* We want to manage the priority of the styles properly to prevent unwanted
* behaviors. Right now, the `sx` prop has the highest priority so the resolved
* fontSize will be `40px`
*/
export const toCSSObject: GetStyleObject =
({ baseStyle }) =>
(props) => {
const { theme, css: cssProp, __css, sx, ...rest } = props
const styleProps = objectFilter(rest, (_, prop) => isStyleProp(prop))
const finalBaseStyle = runIfFn(baseStyle, props)
const finalStyles = Object.assign(
{},
__css,
finalBaseStyle,
filterUndefined(styleProps),
sx,
)
const computedCSS = css(finalStyles)(props.theme)
return cssProp ? [computedCSS, cssProp] : computedCSS
}
export interface ChakraStyledOptions extends Dict {
shouldForwardProp?(prop: string): boolean
label?: string
baseStyle?:
| SystemStyleObject
| ((props: StyleResolverProps) => SystemStyleObject)
}
export function styled<T extends As, P = {}>(
component: T,
options?: ChakraStyledOptions,
) {
const { baseStyle, ...styledOptions } = options ?? {}
if (!styledOptions.shouldForwardProp) {
styledOptions.shouldForwardProp = shouldForwardProp
}
const styleObject = toCSSObject({ baseStyle })
return _styled(
component as React.ComponentType<any>,
styledOptions,
)(styleObject) as ChakraComponent<T, P>
}
export type HTMLChakraComponents = {
[Tag in DOMElements]: ChakraComponent<Tag, {}>
}
export type HTMLChakraProps<T extends As> = Omit<
PropsOf<T>,
T extends "svg"
? "ref" | "children" | keyof StyleProps
: "ref" | keyof StyleProps
> &
ChakraProps & { as?: As }