@lets-events/react 6.1.0 → 7.0.0

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.
@@ -1,34 +1,35 @@
1
- import React, { ComponentProps, useEffect, useState } from 'react'
2
- import { DayPicker } from 'react-day-picker';
3
- import { ptBR } from 'date-fns/locale';
1
+ import React, { ComponentProps, useEffect, useState } from "react";
2
+ import { DayPicker } from "react-day-picker";
3
+ import { ptBR } from "date-fns/locale";
4
4
  import { Dialog as Calendaradix } from "@radix-ui/themes";
5
- import { parse, isValid, format, addYears } from 'date-fns';
6
- import { Button } from '../Button';
7
- import { Box } from '../Box';
8
- import { TextField, TextFieldSlot } from '../TextField';
9
- import Icon from '../Icon';
5
+ import { parse, isValid, format, addYears } from "date-fns";
6
+ import { Button } from "../Button";
7
+ import { Box } from "../Box";
8
+ import { TextField, TextFieldSlot } from "../TextField";
9
+ import Icon from "../Icon";
10
10
  import {
11
11
  CalendarContentStyled,
12
12
  CalendarFooterStyled,
13
13
  CalendarStyled,
14
- DayPickerWrapperStyled
15
- } from './styledComponents';
14
+ DayPickerWrapperStyled,
15
+ CalendarTitleStyled,
16
+ } from "./styledComponents";
16
17
 
17
18
  export type CalendarProps = ComponentProps<typeof CalendarStyled> & {
18
- calendarLayout?: "label" | "dropdown" | "dropdown-months" | "dropdown-years"
19
- selected: Date | undefined
20
- setSelected: React.Dispatch<React.SetStateAction<Date | undefined>>
21
- action?: boolean
22
- actionText?: string
23
- onAction?: () => void
24
- }
19
+ calendarLayout?: "label" | "dropdown" | "dropdown-months" | "dropdown-years";
20
+ selected: Date | undefined;
21
+ setSelected: React.Dispatch<React.SetStateAction<Date | undefined>>;
22
+ action?: boolean;
23
+ actionText?: string;
24
+ onAction?: () => void;
25
+ };
25
26
 
26
27
  function formatToDateMask(value: string): string {
27
- const numeric = value.replace(/\D/g, '').slice(0, 8)
28
- const parts = numeric.match(/^(\d{0,2})(\d{0,2})(\d{0,4})$/)
29
- if (!parts) return ''
30
- const [, day, month, year] = parts
31
- return [day, month, year].filter(Boolean).join('/')
28
+ const numeric = value.replace(/\D/g, "").slice(0, 8);
29
+ const parts = numeric.match(/^(\d{0,2})(\d{0,2})(\d{0,4})$/);
30
+ if (!parts) return "";
31
+ const [, day, month, year] = parts;
32
+ return [day, month, year].filter(Boolean).join("/");
32
33
  }
33
34
 
34
35
  export function Calendar({
@@ -40,34 +41,34 @@ export function Calendar({
40
41
  onAction,
41
42
  ...props
42
43
  }: CalendarProps) {
43
- const [inputValue, setInputValue] = useState('')
44
+ const [inputValue, setInputValue] = useState("");
44
45
 
45
- const today = new Date()
46
- const maxDate = addYears(today, 20)
46
+ const today = new Date();
47
+ const maxDate = addYears(today, 20);
47
48
 
48
49
  useEffect(() => {
49
- console.log('selected', selected)
50
+ console.log("selected", selected);
50
51
  if (selected) {
51
- setInputValue(format(selected, 'dd/MM/yyyy'))
52
+ setInputValue(format(selected, "dd/MM/yyyy"));
52
53
  } else {
53
- setInputValue('')
54
+ setInputValue("");
54
55
  }
55
- }, [selected])
56
+ }, [selected]);
56
57
 
57
58
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
58
- const masked = formatToDateMask(e.target.value)
59
- setInputValue(masked)
59
+ const masked = formatToDateMask(e.target.value);
60
+ setInputValue(masked);
60
61
 
61
- const parsed = parse(masked, 'dd/MM/yyyy', new Date())
62
+ const parsed = parse(masked, "dd/MM/yyyy", new Date());
62
63
  if (isValid(parsed)) {
63
- setSelected(parsed)
64
+ setSelected(parsed);
64
65
  } else {
65
- console.warn('Data inválida inserida no input:', masked)
66
+ console.warn("Data inválida inserida no input:", masked);
66
67
  }
67
- }
68
+ };
68
69
 
69
70
  return (
70
- <Calendaradix.Root >
71
+ <Calendaradix.Root>
71
72
  <CalendarStyled {...props}>
72
73
  <Calendaradix.Trigger>
73
74
  <TextField
@@ -78,12 +79,13 @@ export function Calendar({
78
79
  inputMode="numeric"
79
80
  >
80
81
  <TextFieldSlot>
81
- <Icon name="calendar" size={'xl'} />
82
+ <Icon name="calendar" size={"xl"} />
82
83
  </TextFieldSlot>
83
84
  </TextField>
84
85
  </Calendaradix.Trigger>
85
86
 
86
87
  <CalendarContentStyled>
88
+ <CalendarTitleStyled>Calendário</CalendarTitleStyled>
87
89
  <Box>
88
90
  <DayPickerWrapperStyled>
89
91
  <DayPicker
@@ -104,13 +106,13 @@ export function Calendar({
104
106
  <CalendarFooterStyled>
105
107
  <Calendaradix.Close>
106
108
  <Button
107
- variant='text'
108
- color='brand'
109
+ variant="text"
110
+ color="brand"
109
111
  onClick={onAction}
110
- typography='buttonMedium'
111
- fontWeight='medium'
112
+ typography="buttonMedium"
113
+ fontWeight="medium"
112
114
  >
113
- {actionText ?? 'Aplicar'}
115
+ {actionText ?? "Aplicar"}
114
116
  </Button>
115
117
  </Calendaradix.Close>
116
118
  </CalendarFooterStyled>
@@ -118,5 +120,5 @@ export function Calendar({
118
120
  </CalendarContentStyled>
119
121
  </CalendarStyled>
120
122
  </Calendaradix.Root>
121
- )
123
+ );
122
124
  }
@@ -9,7 +9,9 @@ export const CalendarStyled = styled('div', {
9
9
  maxWidth: '200px',
10
10
  borderRadius: '$sm',
11
11
  })
12
-
12
+ export const CalendarTitleStyled = styled(Calendaradix.Title, {
13
+ display: 'none',
14
+ })
13
15
  export const CalendarContentStyled = styled(Calendaradix.Content, {
14
16
  fontFamily: '$default',
15
17
  lineHeight: '$base',
@@ -29,6 +29,7 @@ export const FlexStyled = styled(FlexRadix, {
29
29
  'column-reverse': { flexDirection: 'column-reverse' },
30
30
  },
31
31
  gap: {
32
+ 0: { gap: '0px' },
32
33
  2: { gap: '$2' },
33
34
  4: { gap: '$4' },
34
35
  6: { gap: '$6' },
@@ -3,27 +3,31 @@ import { styled } from '../styles'
3
3
  import { TextField as TextFieldRadix } from "@radix-ui/themes";
4
4
  import Icon from './Icon';
5
5
  import { typographyValues } from '../types/typographyValues';
6
+ import { TextStyle } from './Text';
7
+ import { Flex } from './Flex';
6
8
 
7
9
  export const TextFieldStyled = styled(TextFieldRadix.Root, {
8
10
  height: '$40',
9
11
  fontFamily: '$default',
10
- padding: '$12 $14',
12
+ padding: '0',
11
13
  borderRadius: '$sm',
12
14
  boxSizing: 'border-box',
13
15
  color: '$dark500',
14
16
  border: '1px solid $dark300',
15
17
  position: 'relative',
16
18
  display: 'flex',
19
+ width: '100%',
20
+ alignItems: 'center',
17
21
 
18
22
  'input': {
19
23
  order: 1,
20
- border: 'none',
21
24
  outline: 'none',
22
- padding: 0,
25
+ border: 'none',
23
26
  margin: 0,
24
27
  width: '100%',
25
28
  font: 'inherit',
26
- textAlign: 'inherit',
29
+ textAlign: 'left',
30
+ padding: '0 $14'
27
31
  },
28
32
 
29
33
  '&:has(input:focus)': {
@@ -153,6 +157,7 @@ export const TextFieldSlotStyled = styled(TextFieldRadix.Slot, {
153
157
  })
154
158
 
155
159
  export type TextFieldProps = ComponentProps<typeof TextFieldStyled> & {
160
+ addon?:string
156
161
  placeholder?: string
157
162
  children?: React.ReactNode
158
163
  isValid?: boolean
@@ -173,6 +178,20 @@ export type TextFieldSlotProps = Omit<ComponentProps<typeof TextFieldStyled>, 'c
173
178
  textAlign?: 'left' | 'right' | 'center'
174
179
  }
175
180
 
181
+
182
+ const InputAddon = styled(TextStyle, {
183
+ boxSizing: 'border-box',
184
+ border: '1px solid $dark300',
185
+ height: '$40',
186
+ padding: '0',
187
+ color: '$dark600',
188
+ borderRadius: '$sm 0px 0px $sm',
189
+ borderRightWidth: '0px',
190
+ margin: 'auto 0',
191
+ display: 'flex',
192
+ alignItems: 'center'
193
+ })
194
+
176
195
  export function TextField({
177
196
  children,
178
197
  isValid,
@@ -180,33 +199,40 @@ export function TextField({
180
199
  color,
181
200
  typography,
182
201
  fontWeight,
202
+ addon,
183
203
  textAlign = 'right',
184
204
  ...props
185
205
  }: TextFieldProps) {
186
206
  return (
187
- <TextFieldStyled
188
- color={color}
189
- isValid={isValid}
190
- name={name}
191
- typography={typography}
192
- fontWeight={fontWeight}
193
- textAlign={textAlign}
194
- {...props}
195
- >
196
- {children}
197
- {isValid && (
198
- <TextFieldSlot
207
+ <Flex gap={'0'} css={{width: '100%'}}>
208
+ {!!addon && (
209
+ <InputAddon typography="labelSmall">{addon}</InputAddon>
210
+ )}
211
+ <TextFieldStyled
212
+ color={color}
213
+ isValid={isValid}
214
+ name={name}
215
+ typography={typography}
216
+ fontWeight={fontWeight}
217
+ textAlign={textAlign}
218
+ style={!!addon ? {borderTopLeftRadius:'0px', borderBottomLeftRadius: '0px'}: undefined}
219
+ {...props}
220
+ >
221
+ {children}
222
+ {isValid && (
223
+ <TextFieldSlot
199
224
  position='flex-end'
200
225
  name={name}
201
226
  color={color as TextFieldSlotProps['color']}
202
227
  typography={typography}
203
228
  fontWeight={fontWeight}
204
229
  textAlign={textAlign}
205
- >
206
- <Icon name='check' />
207
- </TextFieldSlot>
208
- )}
209
- </TextFieldStyled>
230
+ >
231
+ <Icon name='check' />
232
+ </TextFieldSlot>
233
+ )}
234
+ </TextFieldStyled>
235
+ </Flex>
210
236
  )
211
237
  }
212
238
 
@@ -1,118 +1,184 @@
1
- import React, { useCallback, useState } from 'react'
2
- import { Dialog as TimePickerRadix } from '@radix-ui/themes'
3
- import { Box } from './Box'
4
- import { Button } from './Button'
5
- import { TextField, TextFieldSlot } from './TextField'
6
- import { Text } from './Text'
7
- import Icon from './Icon'
8
- import { styled } from '../styles'
1
+ import React, { useCallback, useState } from "react";
2
+ import { Dialog as TimePickerRadix } from "@radix-ui/themes";
3
+ import { Box } from "./Box";
4
+ import { Button } from "./Button";
5
+ import { TextField, TextFieldSlot } from "./TextField";
6
+ import { Text } from "./Text";
7
+ import Icon from "./Icon";
8
+ import { styled } from "../styles";
9
9
 
10
- export const TimePickerStyled = styled('div', {
11
- fontFamily: '$default',
12
- lineHeight: '$base',
13
- fontSize: '$14',
14
- maxWidth: '200px',
15
- borderRadius: '$sm',
16
- })
10
+ export const TimePickerStyled = styled("div", {
11
+ fontFamily: "$default",
12
+ lineHeight: "$base",
13
+ fontSize: "$14",
14
+ maxWidth: "200px",
15
+ borderRadius: "$sm",
16
+ });
17
+ export const TimePickerTitleStyled = styled(TimePickerRadix.Title, {
18
+ display: "none",
19
+ });
17
20
  export const TimePickerDialogStyled = styled(TimePickerRadix.Content, {
18
- width: '100%',
19
- maxWidth: '8.875rem',
20
- border: '1px solid $neutral300',
21
- borderRadius: '$sm',
22
- boxShadow: '0px 2px 8px 0px $shadow50',
23
- })
24
- export const TimePickerFooterStyled = styled('div', {
25
- borderTop: '2px solid $neutral100',
26
- padding: '$4 $16',
27
- display: 'flex',
28
- justifyContent: 'center',
29
- alignItems: 'center',
30
- height: '3rem',
31
- })
32
- export const TimerPickerContentStyled = styled('div', {
33
- display: 'flex',
34
- gap: '$16',
35
- alignItems: 'center',
36
- padding: '$16 $16 $8 ',
37
- '& > div:nth-child(2)': {
38
- order: 2
39
- }
40
- })
21
+ width: "100%",
22
+ maxWidth: "8.875rem",
23
+ border: "1px solid $neutral300",
24
+ borderRadius: "$sm",
25
+ boxShadow: "0px 2px 8px 0px $shadow50",
26
+ });
27
+ export const TimePickerFooterStyled = styled("div", {
28
+ borderTop: "2px solid $neutral100",
29
+ padding: "$4 $16",
30
+ display: "flex",
31
+ justifyContent: "center",
32
+ alignItems: "center",
33
+ height: "3rem",
34
+ });
35
+ export const TimerPickerContentStyled = styled("div", {
36
+ display: "flex",
37
+ gap: "$16",
38
+ alignItems: "center",
39
+ padding: "$16 $16 $8 ",
40
+ "& > div:nth-child(2)": {
41
+ order: 2,
42
+ },
43
+ });
41
44
  export type TimePickerProps = {
42
- selected: string | undefined
43
- setSelected: React.Dispatch<React.SetStateAction<string | undefined>>
44
- }
45
+ selected: string | undefined;
46
+ setSelected: React.Dispatch<React.SetStateAction<string | undefined>>;
47
+ };
45
48
 
46
49
  export function TimePicker({ selected, setSelected }: TimePickerProps) {
47
- const [hours, setHours] = useState('00')
48
- const [minutes, setMinutes] = useState('00')
50
+ const [hours, setHours] = useState("00");
51
+ const [minutes, setMinutes] = useState("00");
49
52
 
50
- const pad = (num: number) => String(num).padStart(2, '0')
53
+ const pad = (num: number) => String(num).padStart(2, "0");
51
54
 
52
- const handleInputValue = useCallback((time: string) => {
53
- setSelected(time)
54
- }, [setSelected])
55
+ const handleInputValue = useCallback(
56
+ (time: string) => {
57
+ setSelected(time);
58
+ },
59
+ [setSelected]
60
+ );
55
61
 
56
- const handleIncrement = useCallback((type: 'hours' | 'minutes') => {
57
- if (type === 'hours') {
58
- const next = (parseInt(hours) + 1) % 24
59
- setHours(pad(next))
60
- } else {
61
- const next = (parseInt(minutes) + 1) % 60
62
- setMinutes(pad(next))
63
- }
64
- }, [hours, minutes])
62
+ const handleIncrement = useCallback(
63
+ (type: "hours" | "minutes") => {
64
+ if (type === "hours") {
65
+ const next = (parseInt(hours) + 1) % 24;
66
+ setHours(pad(next));
67
+ } else {
68
+ const next = (parseInt(minutes) + 1) % 60;
69
+ setMinutes(pad(next));
70
+ }
71
+ },
72
+ [hours, minutes]
73
+ );
65
74
 
66
- const handleDecrement = useCallback((type: 'hours' | 'minutes') => {
67
- if (type === 'hours') {
68
- const prev = (parseInt(hours) - 1 + 24) % 24
69
- setHours(pad(prev))
70
- } else {
71
- const prev = (parseInt(minutes) - 1 + 60) % 60
72
- setMinutes(pad(prev))
73
- }
74
- }, [hours, minutes])
75
+ const handleDecrement = useCallback(
76
+ (type: "hours" | "minutes") => {
77
+ if (type === "hours") {
78
+ const prev = (parseInt(hours) - 1 + 24) % 24;
79
+ setHours(pad(prev));
80
+ } else {
81
+ const prev = (parseInt(minutes) - 1 + 60) % 60;
82
+ setMinutes(pad(prev));
83
+ }
84
+ },
85
+ [hours, minutes]
86
+ );
75
87
 
76
88
  return (
77
89
  <TimePickerRadix.Root>
78
- <TimePickerStyled >
90
+ <TimePickerStyled>
79
91
  <TimePickerRadix.Trigger>
80
- <TextField value={selected} readOnly type="text" placeholder="00:00" typography="labelSmall" fontWeight="regular">
92
+ <TextField
93
+ value={selected}
94
+ readOnly
95
+ type="text"
96
+ placeholder="00:00"
97
+ typography="labelSmall"
98
+ fontWeight="regular"
99
+ >
81
100
  <TextFieldSlot>
82
101
  <Icon name="clock" size="xl" />
83
102
  </TextFieldSlot>
84
103
  </TextField>
85
104
  </TimePickerRadix.Trigger>
86
105
  <TimePickerDialogStyled>
106
+ <TimePickerTitleStyled>Horário</TimePickerTitleStyled>
87
107
  <TimerPickerContentStyled>
88
- {['hours', 'minutes'].map((unit) => (
89
- <Box key={unit} style={{ display: 'flex', alignItems: 'center', flexDirection: 'column' }}>
90
- <Button variant='text' onClick={() => handleIncrement(unit as 'hours' | 'minutes')}>
91
- <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
92
- <path d="M0 8C0 3.58172 3.58172 0 8 0H24C28.4183 0 32 3.58172 32 8V24C32 28.4183 28.4183 32 24 32H8C3.58172 32 0 28.4183 0 24V8Z" fill="white" />
93
- <path d="M16.7063 12.2937C16.3157 11.9031 15.6813 11.9031 15.2907 12.2937L10.2907 17.2937C9.9001 17.6843 9.9001 18.3187 10.2907 18.7093C10.6813 19.1 11.3157 19.1 11.7063 18.7093L16.0001 14.4156L20.2938 18.7062C20.6845 19.0968 21.3188 19.0968 21.7095 18.7062C22.1001 18.3156 22.1001 17.6812 21.7095 17.2906L16.7095 12.2906L16.7063 12.2937Z" fill="#808289" />
108
+ {["hours", "minutes"].map((unit) => (
109
+ <Box
110
+ key={unit}
111
+ style={{
112
+ display: "flex",
113
+ alignItems: "center",
114
+ flexDirection: "column",
115
+ }}
116
+ >
117
+ <Button
118
+ variant="text"
119
+ onClick={() => handleIncrement(unit as "hours" | "minutes")}
120
+ >
121
+ <svg
122
+ xmlns="http://www.w3.org/2000/svg"
123
+ width="32"
124
+ height="32"
125
+ viewBox="0 0 32 32"
126
+ fill="none"
127
+ >
128
+ <path
129
+ d="M0 8C0 3.58172 3.58172 0 8 0H24C28.4183 0 32 3.58172 32 8V24C32 28.4183 28.4183 32 24 32H8C3.58172 32 0 28.4183 0 24V8Z"
130
+ fill="white"
131
+ />
132
+ <path
133
+ d="M16.7063 12.2937C16.3157 11.9031 15.6813 11.9031 15.2907 12.2937L10.2907 17.2937C9.9001 17.6843 9.9001 18.3187 10.2907 18.7093C10.6813 19.1 11.3157 19.1 11.7063 18.7093L16.0001 14.4156L20.2938 18.7062C20.6845 19.0968 21.3188 19.0968 21.7095 18.7062C22.1001 18.3156 22.1001 17.6812 21.7095 17.2906L16.7095 12.2906L16.7063 12.2937Z"
134
+ fill="#808289"
135
+ />
94
136
  </svg>
95
137
  </Button>
96
- <TextField value={unit === 'hours' ? hours : minutes} onChange={(e) => handleInputValue(e.target.value)} type="text" placeholder="00" typography="labelSmall" fontWeight="regular" textAlign="center" style={{ padding: '4px' }} />
138
+ <TextField
139
+ value={unit === "hours" ? hours : minutes}
140
+ onChange={(e) => handleInputValue(e.target.value)}
141
+ type="text"
142
+ placeholder="00"
143
+ typography="labelSmall"
144
+ fontWeight="regular"
145
+ textAlign="center"
146
+ style={{ padding: "4px" }}
147
+ />
97
148
 
98
- <Button variant='text' onClick={() => handleDecrement(unit as 'hours' | 'minutes')}>
99
- <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
100
- <path d="M0 8C0 3.58172 3.58172 0 8 0H24C28.4183 0 32 3.58172 32 8V24C32 28.4183 28.4183 32 24 32H8C3.58172 32 0 28.4183 0 24V8Z" fill="white" />
101
- <path d="M15.2937 19.7063C15.6843 20.0969 16.3187 20.0969 16.7093 19.7063L21.7093 14.7063C22.0999 14.3157 22.0999 13.6813 21.7093 13.2907C21.3187 12.9 20.6843 12.9 20.2937 13.2907L15.9999 17.5844L11.7062 13.2938C11.3155 12.9032 10.6812 12.9032 10.2905 13.2938C9.8999 13.6844 9.8999 14.3188 10.2905 14.7094L15.2905 19.7094L15.2937 19.7063Z" fill="#808289" />
149
+ <Button
150
+ variant="text"
151
+ onClick={() => handleDecrement(unit as "hours" | "minutes")}
152
+ >
153
+ <svg
154
+ xmlns="http://www.w3.org/2000/svg"
155
+ width="32"
156
+ height="32"
157
+ viewBox="0 0 32 32"
158
+ fill="none"
159
+ >
160
+ <path
161
+ d="M0 8C0 3.58172 3.58172 0 8 0H24C28.4183 0 32 3.58172 32 8V24C32 28.4183 28.4183 32 24 32H8C3.58172 32 0 28.4183 0 24V8Z"
162
+ fill="white"
163
+ />
164
+ <path
165
+ d="M15.2937 19.7063C15.6843 20.0969 16.3187 20.0969 16.7093 19.7063L21.7093 14.7063C22.0999 14.3157 22.0999 13.6813 21.7093 13.2907C21.3187 12.9 20.6843 12.9 20.2937 13.2907L15.9999 17.5844L11.7062 13.2938C11.3155 12.9032 10.6812 12.9032 10.2905 13.2938C9.8999 13.6844 9.8999 14.3188 10.2905 14.7094L15.2905 19.7094L15.2937 19.7063Z"
166
+ fill="#808289"
167
+ />
102
168
  </svg>
103
169
  </Button>
104
170
  </Box>
105
171
  ))}
106
- <Text >:</Text>
172
+ <Text>:</Text>
107
173
  </TimerPickerContentStyled>
108
174
  <TimePickerFooterStyled>
109
175
  <TimePickerRadix.Close>
110
176
  <Button
111
- variant='text'
112
- color='brand'
177
+ variant="text"
178
+ color="brand"
113
179
  onClick={() => handleInputValue(`${hours}:${minutes}`)}
114
- typography='buttonMedium'
115
- fontWeight='medium'
180
+ typography="buttonMedium"
181
+ fontWeight="medium"
116
182
  >
117
183
  Aplicar
118
184
  </Button>
@@ -121,5 +187,5 @@ export function TimePicker({ selected, setSelected }: TimePickerProps) {
121
187
  </TimePickerDialogStyled>
122
188
  </TimePickerStyled>
123
189
  </TimePickerRadix.Root>
124
- )
190
+ );
125
191
  }