@lets-events/react 7.1.0 → 7.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +9 -10
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +1571 -71
- package/dist/index.d.ts +1571 -71
- package/dist/index.js +1025 -229
- package/dist/index.mjs +988 -200
- package/package.json +1 -1
- package/src/components/Alert.tsx +200 -153
- package/src/components/Badge.tsx +0 -1
- package/src/components/Calendar/index.tsx +5 -2
- package/src/components/Card.tsx +69 -0
- package/src/components/Step.tsx +107 -91
- package/src/components/Text.tsx +5 -7
- package/src/components/TextField.tsx +52 -43
- package/src/components/TextareaField.tsx +101 -0
- package/src/components/TimePicker.tsx +30 -4
- package/src/index.tsx +2 -0
package/src/components/Step.tsx
CHANGED
|
@@ -1,148 +1,164 @@
|
|
|
1
|
-
import React, { ComponentProps, ElementType } from
|
|
2
|
-
import { styled } from
|
|
1
|
+
import React, { ComponentProps, ElementType } from "react";
|
|
2
|
+
import { styled } from "../styles";
|
|
3
3
|
import { Box, Tabs as StepRadix } from "@radix-ui/themes";
|
|
4
4
|
|
|
5
|
-
export const StepStyled = styled(
|
|
6
|
-
fontFamily:
|
|
7
|
-
color:
|
|
8
|
-
letterSpacing:
|
|
9
|
-
|
|
10
|
-
})
|
|
5
|
+
export const StepStyled = styled("div", {
|
|
6
|
+
fontFamily: "$default",
|
|
7
|
+
color: "$gray100",
|
|
8
|
+
letterSpacing: "0px",
|
|
9
|
+
});
|
|
11
10
|
|
|
12
11
|
const StepTriggerStyled = styled(StepRadix.Trigger, {
|
|
13
|
-
all:
|
|
14
|
-
position:
|
|
15
|
-
display:
|
|
16
|
-
alignItems:
|
|
17
|
-
justifyContent:
|
|
18
|
-
fontSize:
|
|
19
|
-
fontWeight:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'&:last-of-type': {
|
|
12
|
+
all: "unset",
|
|
13
|
+
position: "relative",
|
|
14
|
+
display: "flex",
|
|
15
|
+
alignItems: "center",
|
|
16
|
+
justifyContent: "center",
|
|
17
|
+
fontSize: "$16",
|
|
18
|
+
fontWeight: "$medium",
|
|
19
|
+
|
|
20
|
+
minWidth: "32px",
|
|
21
|
+
minHeight: "32px",
|
|
22
|
+
marginRight: "40px",
|
|
23
|
+
|
|
24
|
+
"&:last-of-type": {
|
|
28
25
|
marginRight: 0,
|
|
29
26
|
},
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
justifyContent: 'center',
|
|
28
|
+
"& > span:first-of-type": {
|
|
29
|
+
width: "32px",
|
|
30
|
+
height: "32px",
|
|
31
|
+
borderRadius: "$full",
|
|
32
|
+
backgroundColor: "$neutral50",
|
|
33
|
+
border: "1px solid $neutral200",
|
|
34
|
+
color: "$gray700",
|
|
35
|
+
display: "flex",
|
|
36
|
+
alignItems: "center",
|
|
37
|
+
justifyContent: "center",
|
|
42
38
|
zIndex: 1,
|
|
43
|
-
position:
|
|
44
|
-
|
|
39
|
+
position: "relative",
|
|
45
40
|
},
|
|
46
41
|
|
|
47
|
-
|
|
48
42
|
'&[data-state="active"] > span:first-of-type': {
|
|
49
|
-
backgroundColor:
|
|
50
|
-
borderColor:
|
|
51
|
-
color:
|
|
43
|
+
backgroundColor: "$blue500",
|
|
44
|
+
borderColor: "$blue500",
|
|
45
|
+
color: "white",
|
|
52
46
|
},
|
|
53
47
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
display: 'none',
|
|
48
|
+
"& > span:last-of-type": {
|
|
49
|
+
display: "none",
|
|
57
50
|
},
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
'&:not(:first-of-type)::before': {
|
|
52
|
+
"&:not(:first-of-type)::before": {
|
|
61
53
|
content: '""',
|
|
62
|
-
position:
|
|
63
|
-
top:
|
|
64
|
-
right:
|
|
65
|
-
transform:
|
|
66
|
-
width:
|
|
67
|
-
height:
|
|
68
|
-
borderRadius:
|
|
69
|
-
backgroundColor:
|
|
54
|
+
position: "absolute",
|
|
55
|
+
top: "50%",
|
|
56
|
+
right: "calc(100% + 4px)",
|
|
57
|
+
transform: "translateY(-50%)",
|
|
58
|
+
width: "32px",
|
|
59
|
+
height: "8px",
|
|
60
|
+
borderRadius: "$sm",
|
|
61
|
+
backgroundColor: "$neutral50",
|
|
70
62
|
zIndex: 0,
|
|
71
63
|
},
|
|
72
64
|
|
|
73
|
-
|
|
74
65
|
'&[data-state="active"]::before': {
|
|
75
|
-
backgroundColor:
|
|
66
|
+
backgroundColor: "$blue500",
|
|
76
67
|
},
|
|
77
68
|
|
|
78
69
|
'&[data-filled="true"] > span:first-of-type': {
|
|
79
|
-
backgroundColor:
|
|
80
|
-
borderColor:
|
|
81
|
-
color:
|
|
70
|
+
backgroundColor: "$blue500",
|
|
71
|
+
borderColor: "$blue500",
|
|
72
|
+
color: "white",
|
|
82
73
|
},
|
|
83
74
|
|
|
84
75
|
'&[data-filled="true"]::before': {
|
|
85
|
-
backgroundColor:
|
|
76
|
+
backgroundColor: "$blue500",
|
|
86
77
|
},
|
|
87
78
|
});
|
|
88
79
|
|
|
89
80
|
const StepListStyled = styled(StepRadix.List, {
|
|
90
|
-
display:
|
|
91
|
-
alignItems:
|
|
92
|
-
justifyContent:
|
|
93
|
-
gap:
|
|
94
|
-
|
|
81
|
+
display: "flex",
|
|
82
|
+
alignItems: "center",
|
|
83
|
+
justifyContent: "flex-start",
|
|
84
|
+
gap: "$4",
|
|
95
85
|
});
|
|
96
86
|
|
|
97
87
|
export type StepProps = ComponentProps<typeof StepStyled> & {
|
|
98
|
-
children: React.ReactNode
|
|
99
|
-
defaultValue: number
|
|
100
|
-
|
|
101
|
-
}
|
|
88
|
+
children: React.ReactNode;
|
|
89
|
+
defaultValue: number;
|
|
90
|
+
};
|
|
102
91
|
export function Step({ children, defaultValue, ...props }: StepProps) {
|
|
103
92
|
return (
|
|
104
93
|
<StepRadix.Root defaultValue={String(defaultValue)}>
|
|
105
|
-
<StepStyled {...props}>
|
|
106
|
-
{children}
|
|
107
|
-
</StepStyled>
|
|
94
|
+
<StepStyled {...props}>{children}</StepStyled>
|
|
108
95
|
</StepRadix.Root>
|
|
109
|
-
|
|
110
|
-
)
|
|
96
|
+
);
|
|
111
97
|
}
|
|
112
98
|
|
|
113
|
-
export function StepTrigger({
|
|
114
|
-
|
|
115
|
-
|
|
99
|
+
export function StepTrigger({
|
|
100
|
+
value,
|
|
101
|
+
children,
|
|
102
|
+
currentStep,
|
|
103
|
+
...props
|
|
104
|
+
}: {
|
|
105
|
+
value: number;
|
|
106
|
+
children: React.ReactNode | string;
|
|
107
|
+
currentStep?: number;
|
|
108
|
+
onClick: () => void;
|
|
109
|
+
}) {
|
|
110
|
+
const isActiveOrPrevious = currentStep !== undefined && value <= currentStep;
|
|
116
111
|
return (
|
|
117
|
-
<StepTriggerStyled
|
|
118
|
-
|
|
112
|
+
<StepTriggerStyled
|
|
113
|
+
data-filled={isActiveOrPrevious}
|
|
114
|
+
value={String(value)}
|
|
115
|
+
{...props}
|
|
116
|
+
>
|
|
117
|
+
{children}
|
|
118
|
+
</StepTriggerStyled>
|
|
119
|
+
);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
export function StepContent({
|
|
122
|
+
export function StepContent({
|
|
123
|
+
value,
|
|
124
|
+
children,
|
|
125
|
+
...props
|
|
126
|
+
}: {
|
|
127
|
+
value: number;
|
|
128
|
+
children: React.ReactNode;
|
|
129
|
+
}) {
|
|
122
130
|
return (
|
|
123
131
|
<StepRadix.Content value={String(value)} {...props}>
|
|
124
132
|
{children}
|
|
125
133
|
</StepRadix.Content>
|
|
126
|
-
)
|
|
134
|
+
);
|
|
127
135
|
}
|
|
128
136
|
|
|
129
|
-
export function StepList({
|
|
137
|
+
export function StepList({
|
|
138
|
+
children,
|
|
139
|
+
currentStep,
|
|
140
|
+
...props
|
|
141
|
+
}: {
|
|
142
|
+
children: React.ReactNode;
|
|
143
|
+
currentStep: number;
|
|
144
|
+
}) {
|
|
130
145
|
return (
|
|
131
146
|
<StepListStyled {...props}>
|
|
132
147
|
{React.Children.map(children, (child) => {
|
|
133
148
|
if (React.isValidElement(child) && child.type === StepTrigger) {
|
|
134
|
-
return React.cloneElement(child, { currentStep } as any)
|
|
149
|
+
return React.cloneElement(child, { currentStep } as any);
|
|
135
150
|
}
|
|
136
|
-
return child
|
|
151
|
+
return child;
|
|
137
152
|
})}
|
|
138
153
|
</StepListStyled>
|
|
139
|
-
)
|
|
154
|
+
);
|
|
140
155
|
}
|
|
141
156
|
|
|
142
|
-
export function StepWrapper({
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
157
|
+
export function StepWrapper({
|
|
158
|
+
children,
|
|
159
|
+
...props
|
|
160
|
+
}: {
|
|
161
|
+
children: React.ReactNode;
|
|
162
|
+
}) {
|
|
163
|
+
return <Box {...props}>{children}</Box>;
|
|
164
|
+
}
|
package/src/components/Text.tsx
CHANGED
|
@@ -15,18 +15,16 @@ export const TextStyle = styled(TextRadix, {
|
|
|
15
15
|
medium: { fontWeight: '$medium' },
|
|
16
16
|
semibold: { fontWeight: '$semibold' },
|
|
17
17
|
bold: { fontWeight: '$bold' },
|
|
18
|
-
}
|
|
19
|
-
}
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
20
|
})
|
|
21
21
|
|
|
22
22
|
export type TextProps = ComponentProps<typeof TextStyle> & {
|
|
23
|
-
as?: ElementType
|
|
23
|
+
as?: ElementType
|
|
24
24
|
asChild?: boolean
|
|
25
25
|
css?: CSS
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export function Text({ ...props }: TextProps) {
|
|
29
|
-
return
|
|
30
|
-
|
|
31
|
-
)
|
|
32
|
-
}
|
|
29
|
+
return <TextStyle {...props} />
|
|
30
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { ComponentProps } from 'react'
|
|
1
|
+
import { ComponentProps, ReactNode } from 'react'
|
|
2
2
|
import { styled } from '../styles'
|
|
3
|
-
import { TextField as TextFieldRadix } from
|
|
4
|
-
import Icon from './Icon'
|
|
5
|
-
import { typographyValues } from '../types/typographyValues'
|
|
6
|
-
import { TextStyle } from './Text'
|
|
7
|
-
import { Flex } from './Flex'
|
|
3
|
+
import { TextField as TextFieldRadix } from '@radix-ui/themes'
|
|
4
|
+
import Icon from './Icon'
|
|
5
|
+
import { typographyValues } from '../types/typographyValues'
|
|
6
|
+
import { TextStyle } from './Text'
|
|
7
|
+
import { Flex } from './Flex'
|
|
8
|
+
import { format, MaskOptions, useMask, unformat } from '@react-input/mask'
|
|
8
9
|
|
|
9
10
|
export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
10
11
|
height: '$40',
|
|
11
12
|
fontFamily: '$default',
|
|
12
|
-
padding: '0',
|
|
13
13
|
borderRadius: '$sm',
|
|
14
14
|
boxSizing: 'border-box',
|
|
15
15
|
color: '$dark500',
|
|
@@ -18,8 +18,9 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
18
18
|
display: 'flex',
|
|
19
19
|
width: '100%',
|
|
20
20
|
alignItems: 'center',
|
|
21
|
-
|
|
22
|
-
'
|
|
21
|
+
padding: '0 $14',
|
|
22
|
+
gap: '$14',
|
|
23
|
+
input: {
|
|
23
24
|
order: 1,
|
|
24
25
|
outline: 'none',
|
|
25
26
|
border: 'none',
|
|
@@ -27,7 +28,6 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
27
28
|
width: '100%',
|
|
28
29
|
font: 'inherit',
|
|
29
30
|
textAlign: 'left',
|
|
30
|
-
padding: '0 $14'
|
|
31
31
|
},
|
|
32
32
|
|
|
33
33
|
'&:has(input:focus)': {
|
|
@@ -70,7 +70,7 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
70
70
|
border: '1px solid $error100',
|
|
71
71
|
cursor: 'not-allowed',
|
|
72
72
|
},
|
|
73
|
-
}
|
|
73
|
+
},
|
|
74
74
|
},
|
|
75
75
|
|
|
76
76
|
typography: typographyValues,
|
|
@@ -87,7 +87,7 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
87
87
|
},
|
|
88
88
|
isValid: {
|
|
89
89
|
true: {},
|
|
90
|
-
false: {}
|
|
90
|
+
false: {},
|
|
91
91
|
},
|
|
92
92
|
},
|
|
93
93
|
|
|
@@ -98,7 +98,7 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
98
98
|
border: '1px solid $error400',
|
|
99
99
|
color: '$error400',
|
|
100
100
|
backgroundColor: '$error50',
|
|
101
|
-
|
|
101
|
+
input: {
|
|
102
102
|
'&::placeholder': {
|
|
103
103
|
color: '$error400',
|
|
104
104
|
},
|
|
@@ -108,7 +108,7 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
108
108
|
border: '2px solid $error400',
|
|
109
109
|
},
|
|
110
110
|
'&:has(input:disabled)': {
|
|
111
|
-
|
|
111
|
+
input: {
|
|
112
112
|
backgroundColor: '$error50',
|
|
113
113
|
},
|
|
114
114
|
backgroundColor: '$error50',
|
|
@@ -116,7 +116,7 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
116
116
|
border: '1px solid $error100',
|
|
117
117
|
cursor: 'not-allowed',
|
|
118
118
|
},
|
|
119
|
-
}
|
|
119
|
+
},
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
isValid: true,
|
|
@@ -130,8 +130,8 @@ export const TextFieldStyled = styled(TextFieldRadix.Root, {
|
|
|
130
130
|
border: '1px solid $dark200',
|
|
131
131
|
cursor: 'not-allowed',
|
|
132
132
|
},
|
|
133
|
-
}
|
|
134
|
-
}
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
135
|
],
|
|
136
136
|
})
|
|
137
137
|
|
|
@@ -139,6 +139,7 @@ export const TextFieldSlotStyled = styled(TextFieldRadix.Slot, {
|
|
|
139
139
|
display: 'flex',
|
|
140
140
|
alignItems: 'center',
|
|
141
141
|
justifyContent: 'center',
|
|
142
|
+
padding: 4,
|
|
142
143
|
|
|
143
144
|
variants: {
|
|
144
145
|
typography: typographyValues,
|
|
@@ -152,12 +153,12 @@ export const TextFieldSlotStyled = styled(TextFieldRadix.Slot, {
|
|
|
152
153
|
left: { textAlign: 'left' },
|
|
153
154
|
right: { textAlign: 'right' },
|
|
154
155
|
center: { textAlign: 'center' },
|
|
155
|
-
}
|
|
156
|
-
}
|
|
156
|
+
},
|
|
157
|
+
},
|
|
157
158
|
})
|
|
158
159
|
|
|
159
160
|
export type TextFieldProps = ComponentProps<typeof TextFieldStyled> & {
|
|
160
|
-
addon?:
|
|
161
|
+
addon?: ReactNode
|
|
161
162
|
placeholder?: string
|
|
162
163
|
children?: React.ReactNode
|
|
163
164
|
isValid?: boolean
|
|
@@ -165,35 +166,41 @@ export type TextFieldProps = ComponentProps<typeof TextFieldStyled> & {
|
|
|
165
166
|
typography?: string
|
|
166
167
|
fontWeight?: 'regular' | 'medium' | 'semibold' | 'bold'
|
|
167
168
|
textAlign?: 'left' | 'right' | 'center'
|
|
169
|
+
mask?: MaskOptions
|
|
168
170
|
}
|
|
169
171
|
|
|
170
|
-
export type TextFieldSlotProps = Omit<
|
|
172
|
+
export type TextFieldSlotProps = Omit<
|
|
173
|
+
ComponentProps<typeof TextFieldStyled>,
|
|
174
|
+
'color'
|
|
175
|
+
> & {
|
|
171
176
|
placeholder?: string
|
|
172
177
|
children?: React.ReactNode
|
|
173
178
|
position?: 'flex-start' | 'flex-end'
|
|
174
179
|
onClick?: () => void
|
|
175
|
-
color?:
|
|
180
|
+
color?: 'error' | 'success' | undefined
|
|
176
181
|
typography?: string
|
|
177
182
|
fontWeight?: 'regular' | 'medium' | 'semibold' | 'bold'
|
|
178
183
|
textAlign?: 'left' | 'right' | 'center'
|
|
179
184
|
}
|
|
180
185
|
|
|
181
|
-
|
|
182
186
|
const InputAddon = styled(TextStyle, {
|
|
183
187
|
boxSizing: 'border-box',
|
|
184
188
|
border: '1px solid $dark300',
|
|
185
189
|
height: '$40',
|
|
186
|
-
padding: '0
|
|
190
|
+
padding: '0 $12',
|
|
191
|
+
margin: '0 auto',
|
|
192
|
+
|
|
187
193
|
color: '$dark600',
|
|
194
|
+
whiteSpace: 'nowrap',
|
|
188
195
|
borderRadius: '$sm 0px 0px $sm',
|
|
189
196
|
borderRightWidth: '0px',
|
|
190
|
-
margin: 'auto 0',
|
|
191
197
|
display: 'flex',
|
|
192
198
|
flexWrap: 'nowrap',
|
|
193
199
|
alignItems: 'center',
|
|
194
|
-
whiteSpace: 'nowrap',
|
|
195
200
|
lineHeight: 1,
|
|
196
201
|
})
|
|
202
|
+
export const maskFormat = format
|
|
203
|
+
export const maskUnformat = unformat
|
|
197
204
|
|
|
198
205
|
export function TextField({
|
|
199
206
|
children,
|
|
@@ -203,14 +210,16 @@ export function TextField({
|
|
|
203
210
|
typography,
|
|
204
211
|
fontWeight,
|
|
205
212
|
addon,
|
|
206
|
-
textAlign = '
|
|
213
|
+
textAlign = 'left',
|
|
214
|
+
mask,
|
|
207
215
|
...props
|
|
208
216
|
}: TextFieldProps) {
|
|
217
|
+
const maskRef = mask ? useMask(mask) : undefined
|
|
218
|
+
|
|
209
219
|
return (
|
|
210
220
|
<Flex gap={'0'} css={{ width: '100%' }}>
|
|
211
|
-
{!!addon &&
|
|
212
|
-
|
|
213
|
-
)}
|
|
221
|
+
{!!addon && <InputAddon typography="labelSmall">{addon}</InputAddon>}
|
|
222
|
+
|
|
214
223
|
<TextFieldStyled
|
|
215
224
|
color={color}
|
|
216
225
|
isValid={isValid}
|
|
@@ -218,20 +227,25 @@ export function TextField({
|
|
|
218
227
|
typography={typography}
|
|
219
228
|
fontWeight={fontWeight}
|
|
220
229
|
textAlign={textAlign}
|
|
221
|
-
|
|
230
|
+
ref={maskRef}
|
|
222
231
|
{...props}
|
|
232
|
+
style={
|
|
233
|
+
addon
|
|
234
|
+
? { borderTopLeftRadius: '0px', borderBottomLeftRadius: '0px' }
|
|
235
|
+
: undefined
|
|
236
|
+
}
|
|
223
237
|
>
|
|
224
238
|
{children}
|
|
225
239
|
{isValid && (
|
|
226
240
|
<TextFieldSlot
|
|
227
|
-
position=
|
|
241
|
+
position="flex-end"
|
|
228
242
|
name={name}
|
|
229
243
|
color={color as TextFieldSlotProps['color']}
|
|
230
244
|
typography={typography}
|
|
231
245
|
fontWeight={fontWeight}
|
|
232
246
|
textAlign={textAlign}
|
|
233
247
|
>
|
|
234
|
-
<Icon name=
|
|
248
|
+
<Icon name="check" />
|
|
235
249
|
</TextFieldSlot>
|
|
236
250
|
)}
|
|
237
251
|
</TextFieldStyled>
|
|
@@ -256,17 +270,14 @@ export function TextFieldSlot({
|
|
|
256
270
|
color: undefined,
|
|
257
271
|
}
|
|
258
272
|
|
|
259
|
-
return
|
|
273
|
+
return onClick ? (
|
|
260
274
|
<TextFieldSlotStyled
|
|
261
275
|
{...sharedStyles}
|
|
262
276
|
style={{
|
|
263
|
-
position: '
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
textAlign: textAlign,
|
|
267
|
-
padding: 13,
|
|
277
|
+
float: position === 'flex-start' ? 'left' : 'right',
|
|
278
|
+
order: position === 'flex-start' ? 0 : 2,
|
|
279
|
+
textAlign,
|
|
268
280
|
zIndex: 2,
|
|
269
|
-
top: 0,
|
|
270
281
|
cursor: 'pointer',
|
|
271
282
|
}}
|
|
272
283
|
onClick={() => onClick()}
|
|
@@ -279,9 +290,7 @@ export function TextFieldSlot({
|
|
|
279
290
|
style={{
|
|
280
291
|
float: position === 'flex-start' ? 'left' : 'right',
|
|
281
292
|
order: position === 'flex-start' ? 0 : 2,
|
|
282
|
-
|
|
283
|
-
marginRight: position === 'flex-end' ? 0 : 15,
|
|
284
|
-
textAlign: textAlign,
|
|
293
|
+
textAlign,
|
|
285
294
|
}}
|
|
286
295
|
>
|
|
287
296
|
{children}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { TextArea as TextAreaRadix } from '@radix-ui/themes'
|
|
2
|
+
import { styled } from '../styles'
|
|
3
|
+
import { ComponentProps, useRef } from 'react'
|
|
4
|
+
import { typographyValues } from '../types/typographyValues'
|
|
5
|
+
import { Text } from './Text'
|
|
6
|
+
|
|
7
|
+
export const TextareaFieldStyle = styled(TextAreaRadix, {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
width: 'fit-content',
|
|
10
|
+
flex: 1,
|
|
11
|
+
textarea: {
|
|
12
|
+
width: '100%',
|
|
13
|
+
minHeight: '3.75rem',
|
|
14
|
+
border: 'none',
|
|
15
|
+
padding: '$12 $14',
|
|
16
|
+
fontFamily: '$default',
|
|
17
|
+
fontSize: '$16',
|
|
18
|
+
outline: 'none',
|
|
19
|
+
resize: 'vertical',
|
|
20
|
+
},
|
|
21
|
+
variants: {
|
|
22
|
+
typography: typographyValues,
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
typography: 'bodyM',
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
export type TextareaFieldProps = ComponentProps<typeof TextareaFieldStyle> & {
|
|
30
|
+
limit: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const TextareaContainer = styled('div', {
|
|
34
|
+
position: 'relative',
|
|
35
|
+
display: 'flex',
|
|
36
|
+
overflow: 'hidden',
|
|
37
|
+
// width: '100%',
|
|
38
|
+
border: '1px solid',
|
|
39
|
+
borderColor: '$dark300',
|
|
40
|
+
borderRadius: '$2xs',
|
|
41
|
+
|
|
42
|
+
'&:has(textarea:focus)': {
|
|
43
|
+
border: '1px solid $brand300',
|
|
44
|
+
},
|
|
45
|
+
'&:has(textarea:disabled)': {
|
|
46
|
+
backgroundColor: '$dark100',
|
|
47
|
+
color: '$dark400',
|
|
48
|
+
border: '1px solid $dark200',
|
|
49
|
+
cursor: 'not-allowed',
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const TextareaLimitIndicator = styled('div', {
|
|
54
|
+
position: 'absolute',
|
|
55
|
+
bottom: 0,
|
|
56
|
+
left: 0,
|
|
57
|
+
padding: '$12 $16',
|
|
58
|
+
borderTop: '1px solid $neutral300',
|
|
59
|
+
width: '100%',
|
|
60
|
+
flex: 1,
|
|
61
|
+
display: 'flex',
|
|
62
|
+
span: {
|
|
63
|
+
backgroundColor: '$neutral200',
|
|
64
|
+
color: '$neutral700',
|
|
65
|
+
borderRadius: '$2xs',
|
|
66
|
+
padding: '$4',
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
export function TextareaField({ maxLength, ...props }: TextareaFieldProps) {
|
|
71
|
+
const inputRef = useRef<HTMLTextAreaElement>(null)
|
|
72
|
+
const badgeRef = useRef<HTMLSpanElement>(null)
|
|
73
|
+
|
|
74
|
+
if (!maxLength) {
|
|
75
|
+
return (
|
|
76
|
+
<TextareaContainer>
|
|
77
|
+
<TextareaFieldStyle {...props} ref={inputRef}></TextareaFieldStyle>
|
|
78
|
+
</TextareaContainer>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
const handleInput = () => {
|
|
82
|
+
const remainingChars = maxLength - (inputRef?.current?.value.length || 0)
|
|
83
|
+
if (badgeRef.current) badgeRef.current.textContent = String(remainingChars)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<TextareaContainer css={{ paddingBottom: '3.25rem' }}>
|
|
88
|
+
<TextareaFieldStyle
|
|
89
|
+
ref={inputRef}
|
|
90
|
+
onInput={handleInput}
|
|
91
|
+
maxLength={maxLength}
|
|
92
|
+
{...props}
|
|
93
|
+
></TextareaFieldStyle>
|
|
94
|
+
<TextareaLimitIndicator>
|
|
95
|
+
<Text typography={'badgeMedium'} ref={badgeRef}>
|
|
96
|
+
{maxLength}
|
|
97
|
+
</Text>
|
|
98
|
+
</TextareaLimitIndicator>
|
|
99
|
+
</TextareaContainer>
|
|
100
|
+
)
|
|
101
|
+
}
|