-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.ts
128 lines (109 loc) · 3.28 KB
/
index.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import * as React from 'react'
import type { PolymorphicPropsWithRef } from 'react-polymorphic-types'
import type { TW, StyleConfig, StyleProps } from 'twind/style'
import isPropValid from '@emotion/is-prop-valid'
import { style, tw as defaultTW } from 'twind/style'
export * from 'twind/style'
export interface ShouldForwardProp {
(prop: string, defaultValidatorFn: (prop: string) => boolean): boolean
}
export interface StyledOptions {
shouldForwardProp?: ShouldForwardProp
}
export interface StyledComponent<Variants, Tag extends React.ElementType> {
<T extends React.ElementType = Tag>(
props: PolymorphicPropsWithRef<StyleProps<Variants>, T>,
): React.ReactElement<any, any> | null
// defaultProps?: Partial<P>;
// displayName?: string;
/**
* CSS Selector associated with the current component.
*
* ```js
* const button = style({
* base: {
* color: "DarkSlateGray"
* }
* })
*
* const article = style({
* base: {
* [button]: { boxShadow: "0 0 0 5px" }
* }
* })
* ```
*/
toString(): string
/**
* CSS Class associated with the current component.
*
* ```js
* const button = style({
* base: {
* color: "DarkSlateGray"
* }
* })
*
* <div className={button.className} />
* ```
*/
readonly className: string
/**
* CSS Selector associated with the current component.
*
* ```js
* const button = style({
* base: {
* color: "DarkSlateGray"
* }
* })
*
* const Card = styled({
* base: {
* [Button.selector]: { boxShadow: "0 0 0 5px" }
* }
* })
* ```
*/
readonly selector: string
}
export function styled<Variants, BaseVariants, Tag extends React.ElementType>(
this: TW | null | undefined | void,
base: StyledComponent<BaseVariants, Tag>,
config?: StyledOptions & StyleConfig<Variants, BaseVariants>,
): StyledComponent<BaseVariants & Variants, Tag> & string
export function styled<Variants, Tag extends React.ElementType = 'div'>(
this: TW | null | undefined | void,
tag?: Tag,
config?: StyledOptions & StyleConfig<Variants>,
): StyledComponent<Variants, Tag> & string
export function styled<Tag extends React.ElementType, Variants>(
this: TW | null | undefined | void,
tag: Tag = 'div' as Tag,
{ shouldForwardProp = isPropValid, ...config }: StyledOptions & StyleConfig<Variants> = {},
) {
const tw = typeof this == 'function' ? this : defaultTW
const component = style(config)
const validateProp = (prop: string): boolean => shouldForwardProp(prop, isPropValid)
const filterProps = (props: any): any =>
Object.keys(props)
.filter(validateProp)
.reduce(($props, key) => {
if (key != 'class') {
$props[key] = props[key]
}
return $props
}, {} as any)
const sc = React.forwardRef(
<T extends React.ElementType = Tag>(
{ as = tag as unknown as T, ...props }: PolymorphicPropsWithRef<StyleProps<Variants>, T>,
ref: React.ForwardedRef<any>,
) =>
React.createElement(as, {
...(typeof as == 'string' ? filterProps(props) : props),
ref,
className: tw(component((typeof as == 'string' ? { ...props, as } : props) as any)),
}),
)
return Object.defineProperties(sc, Object.getOwnPropertyDescriptors(component))
}