@lets-events/react 12.3.10 → 12.5.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @lets-events/react
2
2
 
3
+ ## 12.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Drawer and DoubleCalendar Props
8
+
9
+ ## 12.4.1
10
+
11
+ ### Patch Changes
12
+
13
+ - test
14
+
15
+ ## 12.4.0
16
+
17
+ ### Minor Changes
18
+
19
+ - DoubleCalendar
20
+
3
21
  ## 12.3.10
4
22
 
5
23
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lets-events/react",
3
- "version": "12.3.10",
3
+ "version": "12.5.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -76,7 +76,8 @@ export const CalendarFooterStyled = styled("div", {
76
76
  borderTop: "2px solid $neutral100",
77
77
  padding: "$4 $16",
78
78
  display: "flex",
79
- justifyContent: "center",
79
+ gap: '1rem',
80
+ justifyContent: "flex-end",
80
81
  alignItems: "center",
81
82
  height: "3rem",
82
83
  });
@@ -88,7 +89,7 @@ export const DayPickerWrapperStyled = styled("div", {
88
89
  color: "$dark500",
89
90
  },
90
91
  ".rdp-root": {
91
- padding: "$8",
92
+ padding: "0 $8",
92
93
  },
93
94
  ".rdp-today .rdp-day_button": {
94
95
  color: "$brand500",
@@ -98,8 +99,8 @@ export const DayPickerWrapperStyled = styled("div", {
98
99
  color: "$dark400",
99
100
  },
100
101
  ".rdp-day_button": {
101
- height: "32px",
102
- width: "32px",
102
+ height: "28px",
103
+ width: "28px",
103
104
  borderRadius: "$sm",
104
105
  fontSize: "$14",
105
106
  color: "$text",
@@ -117,9 +118,10 @@ export const DayPickerWrapperStyled = styled("div", {
117
118
  borderColor: "transparent",
118
119
  },
119
120
  ".rdp-nav": {
121
+ position: "absolute",
122
+ width: "98%",
120
123
  display: "flex",
121
124
  justifyContent: "space-between",
122
- width: "100%",
123
125
  },
124
126
  ".rdp-nav .rdp-chevron": {
125
127
  display: "none",
@@ -159,8 +161,15 @@ export const DayPickerWrapperStyled = styled("div", {
159
161
  backgroundColor: "transparent",
160
162
  cursor: "pointer",
161
163
  },
164
+ ".rdp-months": {
165
+ display: "flex",
166
+ columnGap: "$16",
167
+ alignItems: "flex-start",
168
+ paddingTop: "$12",
169
+ },
162
170
  ".rdp-month": {
163
- marginTop: "-24px",
171
+ marginTop: "0",
172
+ paddingTop: "$6",
164
173
  },
165
174
  ".rdp-month_caption": {
166
175
  display: "flex",
@@ -212,9 +221,9 @@ export const DayPickerWrapperStyled = styled("div", {
212
221
  boxShadow: "none",
213
222
  },
214
223
  ".rdp-dropdown.rdp-months_dropdown:focus, .rdp-dropdown.rdp-years_dropdown:focus":
215
- {
216
- border: "none",
217
- },
224
+ {
225
+ border: "none",
226
+ },
218
227
  ".rdp-dropdown_root": {
219
228
  position: "relative",
220
229
  },
@@ -0,0 +1,170 @@
1
+ import React, { ComponentProps, useRef, useEffect, useState } from "react";
2
+ import { useOnClickOutside } from "../../hooks/useOnClickOutside";
3
+ import { DayPicker } from "react-day-picker";
4
+ import { ptBR } from "date-fns/locale";
5
+ import { 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
+ import {
11
+ CalendarContentStyled,
12
+ CalendarFooterStyled,
13
+ CalendarStyled,
14
+ DayPickerWrapperStyled,
15
+ CalendarButtonStyled,
16
+ } from "../Calendar/styledComponents";
17
+
18
+ export type DateRange = { from?: Date; to?: Date } | undefined;
19
+
20
+ export type DoubleCalendarProps = ComponentProps<typeof CalendarStyled> & {
21
+ calendarLayout?: "label" | "dropdown" | "dropdown-months" | "dropdown-years";
22
+ selected: DateRange;
23
+ setSelected: React.Dispatch<React.SetStateAction<DateRange>>;
24
+ position?: "top" | "bottom" | "top-right" | "bottom-right";
25
+ action?: boolean;
26
+ actionText?: string;
27
+ hasError?: boolean;
28
+ expand?: boolean;
29
+ allowPastDates?: boolean;
30
+ maxYearsFromNow?: number;
31
+ disabled?: boolean;
32
+ };
33
+
34
+ export function DoubleCalendar({
35
+ action,
36
+ actionText,
37
+ calendarLayout,
38
+ selected,
39
+ setSelected,
40
+ position = "bottom",
41
+ hasError,
42
+ expand,
43
+ allowPastDates = false,
44
+ maxYearsFromNow = 20,
45
+ disabled = false,
46
+ ...props
47
+ }: DoubleCalendarProps) {
48
+ const [startValue, setStartValue] = useState("");
49
+ const [endValue, setEndValue] = useState("");
50
+ const [showContainer, setShowCalendar] = useState(false);
51
+ const initialSelectedRef = useRef<DateRange | undefined>(undefined);
52
+
53
+ const dropdownRef = useRef<HTMLDivElement>(null);
54
+
55
+ useOnClickOutside(dropdownRef, () => {
56
+ setShowCalendar(false);
57
+ });
58
+ const today = new Date();
59
+ const maxDate = addYears(today, maxYearsFromNow);
60
+
61
+ useEffect(() => {
62
+ if (selected && selected.from) {
63
+ setStartValue(format(selected.from, "dd/MM/yyyy"));
64
+ } else {
65
+ setStartValue("");
66
+ }
67
+
68
+ if (selected && selected.to) {
69
+ setEndValue(format(selected.to, "dd/MM/yyyy"));
70
+ } else {
71
+ setEndValue("");
72
+ }
73
+ }, [selected]);
74
+
75
+ return (
76
+ <div>
77
+ <CalendarStyled {...props} expand={expand} ref={dropdownRef}>
78
+ <CalendarButtonStyled
79
+ expand={expand}
80
+ type="button"
81
+ onClick={() =>
82
+ setShowCalendar((prev) => {
83
+ const next = !prev;
84
+ if (!prev) initialSelectedRef.current = selected;
85
+ return next;
86
+ })
87
+ }
88
+ disabled={disabled}
89
+ >
90
+ <div style={{ display: "flex", gap: "8px", width: "100%" }}>
91
+ <TextField
92
+ placeholder="00/00/0000 - 00/00/0000"
93
+ type="text"
94
+ value={`${startValue || "00/00/0000"} - ${endValue || "00/00/0000"}`}
95
+ readOnly
96
+ inputMode="numeric"
97
+ textAlign={"right"}
98
+ color={hasError ? "error" : "default"}
99
+ disabled={disabled}
100
+ >
101
+ <TextFieldSlot>
102
+ <Icon name="calendar" size={"xl"} />
103
+ </TextFieldSlot>
104
+ </TextField>
105
+ </div>
106
+ </CalendarButtonStyled>
107
+
108
+ {showContainer && (
109
+ <CalendarContentStyled position={position}>
110
+ <Box>
111
+ <DayPickerWrapperStyled>
112
+ <DayPicker
113
+ mode="range"
114
+ numberOfMonths={2}
115
+ captionLayout={calendarLayout}
116
+ selected={selected as any}
117
+ onSelect={setSelected}
118
+ required
119
+ locale={ptBR}
120
+ disabled={allowPastDates ? undefined : { before: today }}
121
+ fromMonth={allowPastDates ? undefined : today}
122
+ toMonth={maxDate}
123
+ />
124
+ </DayPickerWrapperStyled>
125
+ </Box>
126
+
127
+ {action && (
128
+ <CalendarFooterStyled>
129
+ <div style={{ textAlign: "center", padding: "1rem" }}>
130
+ <span>
131
+ {`${selected?.from ? format(selected.from, "dd/MM/yyyy") : "00/00/0000"} — ${selected?.to ? format(selected.to, "dd/MM/yyyy") : "00/00/0000"}`}
132
+ </span>
133
+ </div>
134
+ <Button
135
+ style={{ margin: "0 0.5rem" }}
136
+ variant="text"
137
+ color="neutral"
138
+ type="button"
139
+ onClick={() => {
140
+ setSelected(initialSelectedRef.current);
141
+ setShowCalendar(false);
142
+ }}
143
+ size={"medium"}
144
+ fontWeight="regular"
145
+ >
146
+ Cancelar
147
+ </Button>
148
+ <Button
149
+ style={{ margin: "0 0.5rem" }}
150
+ variant="text"
151
+ color="brand"
152
+ type="button"
153
+ onClick={() => {
154
+ setShowCalendar(false);
155
+ }}
156
+ size={"medium"}
157
+ fontWeight="medium"
158
+ >
159
+ {actionText ?? "Aplicar"}
160
+ </Button>
161
+ </CalendarFooterStyled>
162
+ )}
163
+ </CalendarContentStyled>
164
+ )}
165
+ </CalendarStyled>
166
+ </div>
167
+ );
168
+ }
169
+
170
+ export default DoubleCalendar;
@@ -23,6 +23,7 @@ export type DrawerProps = ComponentProps<typeof DrawerOverlayStyled> & {
23
23
  goBackIcon?: ReactNode;
24
24
  goBackAction?: () => void;
25
25
  zIndex?: number;
26
+ clickOutsideAvailable?: boolean;
26
27
  };
27
28
 
28
29
  export function Drawer({
@@ -35,6 +36,7 @@ export function Drawer({
35
36
  goBackIcon,
36
37
  goBackAction,
37
38
  zIndex = 1000,
39
+ clickOutsideAvailable = true,
38
40
  }: DrawerProps) {
39
41
  useEffect(() => {
40
42
  if (isOpen) {
@@ -60,7 +62,7 @@ export function Drawer({
60
62
  css={{
61
63
  zIndex,
62
64
  }}
63
- onClick={onClose}
65
+ onClick={clickOutsideAvailable ? onClose : undefined}
64
66
  open={isOpen}
65
67
  />
66
68
  <DrawerWrapper
@@ -0,0 +1,93 @@
1
+ import { useCallback } from "react";
2
+ import { FieldValues, useController, RegisterOptions } from "react-hook-form";
3
+ import { Flex } from "../Flex";
4
+ import { FormLabel } from "./subComponents/FormLabel";
5
+ import { ErrorFormMessage } from "./subComponents/ErrorFormMessage";
6
+ import { DoubleCalendar, DateRange, DoubleCalendarProps } from "../DoubleCalendar";
7
+
8
+ export type DoubleCalendarFormFieldProps = Omit<
9
+ DoubleCalendarProps,
10
+ "selected" | "setSelected"
11
+ > & {
12
+ name: string;
13
+ label?: string;
14
+ required?: boolean;
15
+ validate?: (value: DateRange) => boolean | string;
16
+ validationErrorMessage?: string;
17
+ rules?: Omit<
18
+ RegisterOptions<FieldValues, string>,
19
+ "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
20
+ >;
21
+ disabled?: boolean;
22
+ allowPastDates?: boolean;
23
+ maxYearsFromNow?: number;
24
+ };
25
+
26
+ export const DoubleCalendarFormField = ({
27
+ name,
28
+ label,
29
+ required,
30
+ validate,
31
+ validationErrorMessage = "Este campo é obrigatório.",
32
+ rules,
33
+ allowPastDates,
34
+ maxYearsFromNow = 20,
35
+ disabled,
36
+ ...calendarProps
37
+ }: DoubleCalendarFormFieldProps) => {
38
+ const handleValidate = useCallback(
39
+ (value?: DateRange) => {
40
+ if (value === undefined || value === null) {
41
+ if (required) return validationErrorMessage;
42
+ return true;
43
+ }
44
+ return validate?.(value) ?? true;
45
+ },
46
+ [validate, required, validationErrorMessage]
47
+ );
48
+
49
+ const { field, fieldState } = useController({
50
+ name,
51
+ rules: {
52
+ required: required ? validationErrorMessage : false,
53
+ validate: handleValidate,
54
+ ...rules,
55
+ },
56
+ defaultValue: undefined,
57
+ });
58
+
59
+ const fieldError = fieldState.error;
60
+ const haveError = !!fieldError;
61
+ const errorMsg = fieldError?.message;
62
+
63
+ const { value: selected, onChange: setSelected } = field as any;
64
+
65
+ const handleCalendarChange = (range: DateRange) => {
66
+ setSelected(range);
67
+ };
68
+
69
+ return (
70
+ <Flex direction="column" style={{ flex: "1" }}>
71
+ {label && (
72
+ <FormLabel name={name} label={label} required={required} haveError={haveError} />
73
+ )}
74
+
75
+ <DoubleCalendar
76
+ selected={selected}
77
+ setSelected={(value) => {
78
+ const newValue = typeof value === "function" ? value(selected) : value;
79
+ handleCalendarChange(newValue);
80
+ }}
81
+ disabled={disabled}
82
+ hasError={haveError}
83
+ allowPastDates={allowPastDates}
84
+ maxYearsFromNow={maxYearsFromNow}
85
+ {...calendarProps}
86
+ />
87
+
88
+ <ErrorFormMessage message={errorMsg} />
89
+ </Flex>
90
+ );
91
+ };
92
+
93
+ export default DoubleCalendarFormField;
@@ -20,6 +20,7 @@ export const TextAreaFormField = ({
20
20
  placeholder,
21
21
  validate,
22
22
  validationErrorMessage = "Este campo é obrigatório.",
23
+ simpleLayout = false,
23
24
  ...props
24
25
  }: TextAreaFormFieldProps) => {
25
26
  const {
@@ -49,6 +50,7 @@ export const TextAreaFormField = ({
49
50
  {...register(name, validationRules)}
50
51
  placeholder={placeholder}
51
52
  color={haveError ? "error" : "default"}
53
+ simpleLayout={simpleLayout}
52
54
  aria-labelledby={`${name}-label`}
53
55
  />
54
56
  <ErrorFormMessage message={errorMsg} />
@@ -3,6 +3,8 @@ import { styled } from "../styles";
3
3
  import React, { ComponentProps, useRef, useState, useEffect } from "react";
4
4
  import { typographyValues } from "../types/typographyValues";
5
5
  import { Text } from "./Text";
6
+ import { Badge } from "./Badge";
7
+ import { Flex } from "./Flex";
6
8
 
7
9
  export const TextareaFieldStyle = styled(TextAreaRadix, {
8
10
  display: "flex",
@@ -77,12 +79,14 @@ export type TextareaFieldProps = Omit<
77
79
  ComponentProps<typeof TextareaFieldStyle>,
78
80
  "color"
79
81
  > &
80
- ComponentProps<typeof TextareaContainer>;
82
+ ComponentProps<typeof TextareaContainer> & {
83
+ simpleLayout?: boolean;
84
+ };
81
85
 
82
86
  export const TextareaField = React.forwardRef<
83
87
  HTMLTextAreaElement,
84
88
  TextareaFieldProps
85
- >(({ maxLength, color, ...props }, forwardedRef) => {
89
+ >(({ maxLength, color, simpleLayout = false, ...props }, forwardedRef) => {
86
90
  const inputRef = useRef<HTMLTextAreaElement>(null);
87
91
  const [remaining, setRemaining] = useState(maxLength);
88
92
 
@@ -100,28 +104,35 @@ export const TextareaField = React.forwardRef<
100
104
  };
101
105
 
102
106
  return (
103
- <TextareaContainer color={color}>
104
- <TextareaFieldStyle
105
- rows={4}
106
- ref={(r) => {
107
- if (!r) return;
108
- inputRef.current = r;
109
- if (forwardedRef) {
110
- if (typeof forwardedRef === "function") forwardedRef(r);
111
- else forwardedRef.current = r;
112
- }
113
- }}
114
- onInput={handleInput}
115
- maxLength={maxLength}
116
- {...props}
117
- />
118
- {maxLength && (
119
- <TextareaLimitIndicator>
120
- <Text typography="badgeMedium">
121
- {remaining}
122
- </Text>
123
- </TextareaLimitIndicator>
107
+ <Flex direction="column" align="end" style={{ position: 'relative' }}>
108
+ {maxLength && simpleLayout && (
109
+ <Badge size="sm" color="grey" style={{ position: 'absolute', right: 0, top: '-1.75rem' }}>
110
+ {remaining}
111
+ </Badge>
124
112
  )}
125
- </TextareaContainer>
113
+ <TextareaContainer color={color}>
114
+ <TextareaFieldStyle
115
+ rows={4}
116
+ ref={(r) => {
117
+ if (!r) return;
118
+ inputRef.current = r;
119
+ if (forwardedRef) {
120
+ if (typeof forwardedRef === "function") forwardedRef(r);
121
+ else forwardedRef.current = r;
122
+ }
123
+ }}
124
+ onInput={handleInput}
125
+ maxLength={maxLength}
126
+ {...props}
127
+ />
128
+ {maxLength && !simpleLayout && (
129
+ <TextareaLimitIndicator>
130
+ <Text typography="badgeMedium">
131
+ {remaining}
132
+ </Text>
133
+ </TextareaLimitIndicator>
134
+ )}
135
+ </TextareaContainer>
136
+ </Flex>
126
137
  );
127
138
  });
package/src/index.tsx CHANGED
@@ -17,6 +17,7 @@ export * from "./components/Badge";
17
17
  export * from "./components/Modal";
18
18
  export * from "./components/MenuDropdown";
19
19
  export * from "./components/Calendar";
20
+ export * from "./components/DoubleCalendar";
20
21
  export * from "./components/Drawer";
21
22
  export * from "./components/TimePicker";
22
23
  export * from "./components/Alert";
@@ -57,6 +58,7 @@ export * from "./components/FormFields/SwitchFormField";
57
58
  export * from "./components/FormFields/EmailFormField";
58
59
  export * from "./components/FormFields/RichEditorFormField";
59
60
  export * from "./components/FormFields/CalendarFormField";
61
+ export * from "./components/FormFields/DoubleCalendarFormField";
60
62
  export * from "./components/FormFields/TimePickerFormField";
61
63
 
62
64
  // Rich Editor
@@ -1,21 +0,0 @@
1
-
2
-
3
- > @lets-events/react@12.3.10 build
4
- > tsup src/index.tsx --format esm,cjs --dts --external react
5
-
6
- CLI Building entry: src/index.tsx
7
- CLI Using tsconfig: tsconfig.json
8
- CLI tsup v8.5.0
9
- CLI Using tsup config: /home/bia3003/Lets/design-system/packages/react/tsup.config.ts
10
- CLI Target: es6
11
- ESM Build start
12
- CJS Build start
13
- CJS dist/index.js 394.55 KB
14
- CJS ⚡️ Build success in 286ms
15
- ESM dist/index.mjs 380.48 KB
16
- ESM ⚡️ Build success in 287ms
17
- DTS Build start
18
- DTS ⚡️ Build success in 5710ms
19
- DTS dist/index.d.mts 401.14 KB
20
- DTS dist/index.d.ts 401.14 KB
21
- ⠙