@@ -36,76 +36,103 @@ type CommonProps = {
36
36
37
37
type OmittedTypes = "variant" | "size" | "children"
38
38
39
- type ButtonTypeProps = CommonProps &
40
- Omit < ButtonProps , OmittedTypes > & {
41
- componentType : "button"
42
- }
39
+ type ButtonTwoLinesProps = Omit < ButtonProps , OmittedTypes > & CommonProps
43
40
44
- type ButtonLinkTypeProps = CommonProps &
45
- Omit < ButtonLinkProps , OmittedTypes > & {
46
- componentType : "link"
47
- }
48
-
49
- type ButtonTwoLinesProps = ButtonTypeProps | ButtonLinkTypeProps
50
-
51
- const ButtonTwoLines = ( {
52
- iconAlignment = "start" ,
41
+ /**
42
+ * Button that renders two styled lines of text
43
+ */
44
+ export const ButtonTwoLines = ( {
53
45
className,
46
+ iconAlignment = "start" ,
54
47
size = "md" ,
55
48
...props
56
49
} : ButtonTwoLinesProps ) => {
57
50
const isIconLeft = [ "left" , "start" ] . includes ( iconAlignment )
58
51
59
- const commonClassStyles = cn (
60
- isIconLeft ? "text-start justify-start" : "text-end justify-end" ,
61
- size === "md" ? "py-4" : "py-2" ,
62
- className
52
+ const [ childProps , ownProps ] = createSplitProps < ButtonTwoLinesProps > ( ) (
53
+ { ...props , isIconLeft } ,
54
+ [
55
+ "reverseTextOrder" ,
56
+ "mainText" ,
57
+ "helperText" ,
58
+ "variant" ,
59
+ "icon" ,
60
+ "isIconLeft" ,
61
+ "isSecondary" ,
62
+ "size" ,
63
+ ]
63
64
)
64
65
65
- if ( props . componentType === "link" ) {
66
- const { buttonProps, ...rest } = props
67
- return (
68
- < ButtonLink
69
- className = { commonClassStyles }
70
- // size={size}
71
- buttonProps = { buttonProps }
72
- { ...rest }
73
- >
74
- < ChildContent
75
- { ...rest }
76
- size = { size }
77
- isSecondary = { buttonProps ?. isSecondary }
78
- isIconLeft = { isIconLeft }
79
- />
80
- </ ButtonLink >
81
- )
82
- }
83
66
return (
84
- < Button className = { commonClassStyles } size = { size } { ...props } >
85
- < ChildContent { ...props } size = { size } isIconLeft = { isIconLeft } />
67
+ < Button
68
+ className = { cn (
69
+ isIconLeft ? "justify-start text-start" : "justify-end text-end" ,
70
+ size === "md" ? "py-4" : "py-2" ,
71
+ className
72
+ ) }
73
+ { ...ownProps }
74
+ >
75
+ < ChildContent { ...childProps } />
86
76
</ Button >
87
77
)
88
78
}
89
79
90
- export default ButtonTwoLines
91
-
92
- const ChildContent = (
93
- props : Omit < ButtonTwoLinesProps , "iconAlignment" | "buttonProps" > & {
94
- isIconLeft : boolean
95
- isSecondary ?: boolean
96
- }
97
- ) => {
98
- const {
99
- reverseTextOrder = false ,
100
- size,
101
- mainText,
102
- helperText,
103
- icon : Icon ,
104
- isIconLeft,
105
- isSecondary,
106
- variant,
107
- } = props
80
+ type ButtonLinkTwoLinesProps = Omit < ButtonLinkProps , OmittedTypes > & CommonProps
81
+
82
+ /**
83
+ * ButtonLink that renders two styled lines of text
84
+ */
85
+ export const ButtonLinkTwoLines = ( {
86
+ className,
87
+ iconAlignment = "start" ,
88
+ size = "md" ,
89
+ ...props
90
+ } : ButtonLinkTwoLinesProps ) => {
91
+ const isIconLeft = [ "left" , "start" ] . includes ( iconAlignment )
92
+
93
+ const [ childProps , ownProps ] = createSplitProps < ButtonLinkTwoLinesProps > ( ) (
94
+ { ...props , isIconLeft } ,
95
+ [
96
+ "reverseTextOrder" ,
97
+ "mainText" ,
98
+ "helperText" ,
99
+ "variant" ,
100
+ "icon" ,
101
+ "isIconLeft" ,
102
+ "isSecondary" ,
103
+ "size" ,
104
+ ]
105
+ )
106
+
107
+ return (
108
+ < ButtonLink
109
+ className = { cn (
110
+ isIconLeft ? "justify-start text-start" : "justify-end text-end" ,
111
+ size === "md" ? "py-4" : "py-2" ,
112
+ className
113
+ ) }
114
+ { ...ownProps }
115
+ >
116
+ < ChildContent { ...childProps } />
117
+ </ ButtonLink >
118
+ )
119
+ }
120
+
121
+ type ChildContentProps = Omit < CommonProps , "iconAlignment" > & {
122
+ isIconLeft : boolean
123
+ isSecondary ?: boolean
124
+ }
108
125
126
+ const ChildContent = ( {
127
+ helperText,
128
+ icon : Icon ,
129
+ mainText,
130
+ reverseTextOrder = false ,
131
+ size,
132
+ variant,
133
+ isIconLeft,
134
+ isSecondary,
135
+ } : ChildContentProps ) => {
109
136
const ButtonIcon = ( ) => (
110
137
< Icon
111
138
// TODO: Text size here should not be marked important after migration
@@ -141,3 +168,36 @@ const ChildContent = (
141
168
</ >
142
169
)
143
170
}
171
+
172
+ /**
173
+ * Split props ripped from Ark UI and simplified:
174
+ * https://github.com/chakra-ui/ark/blob/main/packages/react/src/utils/create-split-props.ts
175
+ */
176
+ type EnsureKeys < ExpectedKeys extends ( keyof ChildContentProps ) [ ] > =
177
+ keyof ChildContentProps extends ExpectedKeys [ number ]
178
+ ? unknown
179
+ : `Missing required keys: ${Exclude < keyof ChildContentProps , ExpectedKeys [ number ] > & string } `
180
+
181
+ function createSplitProps < ParentProps > ( ) {
182
+ return <
183
+ Keys extends ( keyof ChildContentProps ) [ ] ,
184
+ Props = Required < ParentProps > ,
185
+ > (
186
+ props : Props ,
187
+ keys : Keys & EnsureKeys < Keys >
188
+ ) =>
189
+ ( keys as string [ ] ) . reduce <
190
+ [ ChildContentProps , Omit < Props , Extract < ( typeof keys ) [ number ] , string > > ]
191
+ > (
192
+ ( previousValue , currentValue ) => {
193
+ const [ target , source ] = previousValue
194
+ const key = currentValue
195
+ if ( source [ key ] !== undefined ) {
196
+ target [ key ] = source [ key ]
197
+ }
198
+ delete source [ key ]
199
+ return [ target , source ]
200
+ } ,
201
+ [ { } as ChildContentProps , { ...props } ]
202
+ )
203
+ }
0 commit comments