@lets-events/react 12.1.13 → 12.2.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,8 +1,7 @@
1
1
  import React, { useCallback, useRef, useState } from "react";
2
2
  import { DropdownMenu, Theme } from "@radix-ui/themes";
3
- import { CheckboxGroup, CheckboxItem } from "./CheckboxGroup";
4
- import { styled } from "../styles";
5
- import { Text } from "./Text";
3
+ import { CheckboxGroup, CheckboxItem } from "../CheckboxGroup";
4
+ import { Text } from "../Text";
6
5
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7
6
  import {
8
7
  faChevronDown,
@@ -11,109 +10,8 @@ import {
11
10
  } from "@fortawesome/free-solid-svg-icons";
12
11
  import { colors } from "@lets-events/tokens";
13
12
  import { ComponentProps, useMemo } from "react";
14
- import { Flex } from "./Flex";
15
- import { CSS } from "@stitches/react";
16
-
17
- const StyledContent = styled(DropdownMenu.Content, {
18
- backgroundColor: "$dark50",
19
- borderRadius: "$sm",
20
- padding: "$8 0",
21
- boxShadow: "0px 2px 4px 0px #23354329, 0px 4px 4px 0px #23354314",
22
- boxSizing: "border-box",
23
- border: "1px solid $dark300",
24
- zIndex: 999999,
25
- minWidth: "var(--radix-dropdown-menu-trigger-width)",
26
- maxWidth: "var(--radix-dropdown-menu-trigger-width)",
27
- });
28
-
29
- const StyledTrigger = styled("div", {
30
- minHeight: "40px",
31
- borderRadius: "$sm",
32
- cursor: "pointer",
33
- display: "flex",
34
- justifyContent: "start",
35
- alignItems: "center",
36
- padding: "$6 $14",
37
- boxSizing: "border-box",
38
- gap: "4px",
39
- width: "100%",
40
-
41
- variants: {
42
- color: {
43
- default: {
44
- border: "1px solid $dark300",
45
- },
46
- error: {
47
- border: "1px solid $error400",
48
- },
49
- },
50
- disabled: {
51
- true: {
52
- cursor: "not-allowed",
53
- border: "1px solid $dark100",
54
- },
55
- },
56
- },
57
-
58
- defaultVariants: {
59
- color: "default",
60
- },
61
- });
62
-
63
- const itemStyle: CSS = {
64
- padding: "$4 $16",
65
- minHeight: "$32",
66
- boxSizing: "border-box",
67
- backgroundColor: "$dark50",
68
- display: "block",
69
- cursor: "pointer",
70
-
71
- "&:hover": {
72
- backgroundColor: "$dark100",
73
- },
74
- };
75
-
76
- const StyledItem = styled("div", {
77
- ...itemStyle,
78
- });
79
-
80
- const BadgeCloseBtn = styled("div", {
81
- cursor: "pointer",
82
- });
83
-
84
- const StyledFlexWithMaxHeight = styled(Flex, {
85
- variants: {
86
- hasMaxHeight: {
87
- true: {
88
- overflowY: "auto",
89
- "&::-webkit-scrollbar": {
90
- width: "4px",
91
- },
92
- "&::-webkit-scrollbar-track": {
93
- backgroundColor: "$dark100",
94
- borderRadius: "2px",
95
- },
96
- "&::-webkit-scrollbar-thumb": {
97
- backgroundColor: "$dark300",
98
- borderRadius: "2px",
99
- "&:hover": {
100
- backgroundColor: "$dark400",
101
- },
102
- },
103
- },
104
- },
105
- },
106
-
107
- defaultVariants: {
108
- hasMaxHeight: false,
109
- },
110
- });
111
- const StyledText = styled(Text, {
112
- flex: 1,
113
- overflow: "hidden",
114
- whiteSpace: "nowrap",
115
- textOverflow: "ellipsis",
116
- });
13
+ import { Flex } from "../Flex";
14
+ import { BadgeCloseBtn, ButtonSelectAllStyled, itemStyle, StyledContent, StyledFlexSelectedItems, StyledFlexWithMaxHeight, StyledItem, StyledText, StyledTrigger } from "./styledComponents";
117
15
 
118
16
  export type MultiSelectProps = ComponentProps<typeof StyledTrigger> & {
119
17
  placeholder?: string;
@@ -130,6 +28,9 @@ export type MultiSelectProps = ComponentProps<typeof StyledTrigger> & {
130
28
  selectedOrientation?: "row" | "column";
131
29
  disabled?: boolean;
132
30
  maxHeight?: string;
31
+ selectedAllOptions?: boolean;
32
+ selectedAllText?: string;
33
+ selectedScroll?: boolean;
133
34
  };
134
35
 
135
36
  export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
@@ -147,12 +48,15 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
147
48
  selectedOrientation = "column",
148
49
  disabled = false,
149
50
  maxHeight,
51
+ selectedAllOptions = false,
52
+ selectedAllText,
53
+ selectedScroll = false
150
54
  },
151
55
  fowardedRef
152
56
  ) => {
153
57
  const [isOpen, setIsOpen] = useState(false);
154
-
155
58
  const triggerRef = useRef<HTMLDivElement>(null);
59
+ const [allOptionsSelected, setAllOptionsSelected] = useState(false)
156
60
  const labelByValue = useMemo(() => {
157
61
  return options.reduce<{ [key: string]: string }>((prev, curr) => {
158
62
  return {
@@ -170,12 +74,27 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
170
74
  [selectedValues, onValueChange]
171
75
  );
172
76
 
77
+ const handleSelectAll = useCallback(
78
+ (e: React.MouseEvent) => {
79
+ e.preventDefault();
80
+ e.stopPropagation();
81
+ const allSelected = selectedValues.length === options.length;
82
+ if (allSelected) {
83
+ onValueChange?.([]);
84
+ setAllOptionsSelected(false)
85
+ } else {
86
+ onValueChange?.(options.map((o) => o.value));
87
+ setAllOptionsSelected(true)
88
+ }
89
+ },
90
+ [selectedValues, options, onValueChange]
91
+ );
92
+
173
93
  const text = useMemo(() => {
174
94
  if (selectedValues.length > 0 && singleSelect) {
175
95
  const value = selectedValues[0];
176
96
  return labelByValue[value];
177
97
  }
178
-
179
98
  return placeholder ?? "Selecione";
180
99
  }, [selectedValues, placeholder, singleSelect]);
181
100
 
@@ -183,6 +102,7 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
183
102
  onValueChange?.([v]);
184
103
  setIsOpen(false);
185
104
  };
105
+
186
106
  const handleToggle = useCallback(
187
107
  (e: React.MouseEvent) => {
188
108
  e.preventDefault();
@@ -194,8 +114,8 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
194
114
  );
195
115
 
196
116
  return (
197
- <Theme>
198
- <DropdownMenu.Root>
117
+ <Theme style={width !== "100%" ? { width } : undefined}>
118
+ <DropdownMenu.Root open={isOpen} onOpenChange={setIsOpen}>
199
119
  <DropdownMenu.Trigger>
200
120
  <StyledTrigger
201
121
  ref={(r) => {
@@ -203,9 +123,7 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
203
123
  triggerRef.current = r;
204
124
  if (fowardedRef) {
205
125
  if (typeof fowardedRef === "function") fowardedRef(r);
206
- else {
207
- fowardedRef.current = r;
208
- }
126
+ else fowardedRef.current = r;
209
127
  }
210
128
  }}
211
129
  color={color}
@@ -236,7 +154,10 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
236
154
  <CheckboxGroup
237
155
  value={selectedValues}
238
156
  onValueChange={(v) => {
239
- onValueChange?.(v);
157
+ onValueChange?.(v)
158
+ if (allOptionsSelected) {
159
+ setAllOptionsSelected(false)
160
+ }
240
161
  }}
241
162
  >
242
163
  <StyledFlexWithMaxHeight
@@ -245,6 +166,18 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
245
166
  hasMaxHeight={!!maxHeight}
246
167
  style={maxHeight ? { maxHeight } : undefined}
247
168
  >
169
+ {selectedAllOptions && (
170
+ <ButtonSelectAllStyled
171
+ css={itemStyle}
172
+ onClick={(e) => handleSelectAll(e)}
173
+ >
174
+ <div className={allOptionsSelected ? "checked" : ""}></div>
175
+ <Text typography="labelSmall">
176
+ {selectedAllText ? selectedAllText : "Selecionar Todos"}
177
+ </Text>
178
+ </ButtonSelectAllStyled>
179
+ )}
180
+
248
181
  {options.map(({ value, label }, i) => (
249
182
  <CheckboxItem value={value} css={itemStyle} key={i}>
250
183
  <Text typography={"labelSmall"}>{label}</Text>
@@ -269,41 +202,39 @@ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
269
202
  </StyledContent>
270
203
  </DropdownMenu.Root>
271
204
  {selectedValues.length > 0 && showSelectedValues && (
272
- <>
273
- <Flex
274
- direction={selectedOrientation}
275
- gap={8}
276
- align={selectedOrientation === "column" ? "start" : "center"}
277
- justify={"start"}
278
- css={{ margin: "8px 0" }}
279
- >
280
- {selectedValues.map((value) => (
281
- <Flex
282
- key={value}
283
- gap={4}
284
- align={"center"}
285
- css={{ flexWrap: "wrap" }}
205
+ <StyledFlexSelectedItems
206
+ direction={selectedOrientation}
207
+ gap={8}
208
+ align={selectedOrientation === "column" ? "start" : "center"}
209
+ justify={"start"}
210
+ css={{ ...(selectedScroll && { maxHeight: maxHeight || "400px" }) }}
211
+ >
212
+ {selectedValues.map((value) => (
213
+ <Flex
214
+ key={value}
215
+ gap={4}
216
+ align={"center"}
217
+ css={{ flexWrap: "wrap" }}
218
+ >
219
+ <BadgeCloseBtn
220
+ onClick={(e) => {
221
+ e.stopPropagation();
222
+ handleRemove(value);
223
+ }}
224
+ role="button"
225
+ >
226
+ <FontAwesomeIcon icon={faSquareXmark} size="sm" />
227
+ </BadgeCloseBtn>
228
+ <Text
229
+ typography={"captionMedium"}
230
+ fontWeight={"regular"}
231
+ color="dark600"
286
232
  >
287
- <BadgeCloseBtn
288
- onClick={(e) => {
289
- e.stopPropagation();
290
- handleRemove(value);
291
- }}
292
- role="button"
293
- >
294
- <FontAwesomeIcon icon={faSquareXmark} size="sm" />
295
- </BadgeCloseBtn>
296
- <Text
297
- typography={"captionMedium"}
298
- fontWeight={"regular"}
299
- color="dark600"
300
- >
301
- {labelByValue[value]}
302
- </Text>
303
- </Flex>
304
- ))}
305
- </Flex>
306
- </>
233
+ {labelByValue[value]}
234
+ </Text>
235
+ </Flex>
236
+ ))}
237
+ </StyledFlexSelectedItems>
307
238
  )}
308
239
  </Theme>
309
240
  );
@@ -0,0 +1,159 @@
1
+ import { DropdownMenu } from "@radix-ui/themes";
2
+ import { styled } from "../../styles";
3
+ import { CSS } from "@stitches/react";
4
+ import { Flex } from "../Flex";
5
+ import { Text } from "../Text";
6
+
7
+ export const StyledContent = styled(DropdownMenu.Content, {
8
+ backgroundColor: "$dark50",
9
+ borderRadius: "$sm",
10
+ padding: "$8 0",
11
+ boxShadow: "0px 2px 4px 0px #23354329, 0px 4px 4px 0px #23354314",
12
+ boxSizing: "border-box",
13
+ border: "1px solid $dark300",
14
+ zIndex: 999999,
15
+ minWidth: "var(--radix-dropdown-menu-trigger-width)",
16
+ maxWidth: "var(--radix-dropdown-menu-trigger-width)",
17
+ });
18
+
19
+ export const StyledTrigger = styled("div", {
20
+ minHeight: "40px",
21
+ borderRadius: "$sm",
22
+ cursor: "pointer",
23
+ display: "flex",
24
+ justifyContent: "start",
25
+ alignItems: "center",
26
+ padding: "$6 $14",
27
+ boxSizing: "border-box",
28
+ gap: "4px",
29
+ width: "100%",
30
+
31
+ variants: {
32
+ color: {
33
+ default: {
34
+ border: "1px solid $dark300",
35
+ },
36
+ error: {
37
+ border: "1px solid $error400",
38
+ },
39
+ },
40
+ disabled: {
41
+ true: {
42
+ cursor: "not-allowed",
43
+ border: "1px solid $dark100",
44
+ },
45
+ },
46
+ },
47
+
48
+ defaultVariants: {
49
+ color: "default",
50
+ },
51
+ });
52
+
53
+ export const itemStyle: CSS = {
54
+ padding: "$4 $16",
55
+ minHeight: "$32",
56
+ boxSizing: "border-box",
57
+ backgroundColor: "$dark50",
58
+ display: "block",
59
+ cursor: "pointer",
60
+
61
+ "&:hover": {
62
+ backgroundColor: "$dark100",
63
+ },
64
+ };
65
+
66
+ export const StyledItem = styled("div", {
67
+ ...itemStyle,
68
+ });
69
+
70
+ export const BadgeCloseBtn = styled("div", {
71
+ cursor: "pointer",
72
+ });
73
+
74
+ export const StyledFlexWithMaxHeight = styled(Flex, {
75
+ variants: {
76
+ hasMaxHeight: {
77
+ true: {
78
+ overflowY: "auto",
79
+ "&::-webkit-scrollbar": {
80
+ width: "4px",
81
+ },
82
+ "&::-webkit-scrollbar-track": {
83
+ backgroundColor: "$dark100",
84
+ borderRadius: "2px",
85
+ },
86
+ "&::-webkit-scrollbar-thumb": {
87
+ backgroundColor: "$dark300",
88
+ borderRadius: "2px",
89
+ "&:hover": {
90
+ backgroundColor: "$dark400",
91
+ },
92
+ },
93
+ },
94
+ },
95
+ },
96
+
97
+ defaultVariants: {
98
+ hasMaxHeight: false,
99
+ },
100
+ });
101
+ export const StyledFlexSelectedItems = styled(Flex, {
102
+ overflowY: "auto",
103
+ margin: "8px 0",
104
+ "&::-webkit-scrollbar": {
105
+ width: "4px",
106
+ },
107
+ "&::-webkit-scrollbar-track": {
108
+ backgroundColor: "$dark100",
109
+ borderRadius: "2px",
110
+ },
111
+ "&::-webkit-scrollbar-thumb": {
112
+ backgroundColor: "$dark300",
113
+ borderRadius: "2px",
114
+ "&:hover": {
115
+ backgroundColor: "$dark400",
116
+ },
117
+ },
118
+ });
119
+ export const StyledText = styled(Text, {
120
+ flex: 1,
121
+ overflow: "hidden",
122
+ whiteSpace: "nowrap",
123
+ textOverflow: "ellipsis",
124
+ });
125
+ export const ButtonSelectAllStyled = styled("button", {
126
+ display: "flex !important",
127
+ alignItems: "center",
128
+ justifyContent: "flex-start",
129
+ gap: "$8",
130
+ border: "none",
131
+ "div": {
132
+ backgroundCcolor: "#fff",
133
+ borderRadius: "2px",
134
+ height: "$16",
135
+ width: "$16",
136
+ position: "relative",
137
+ border: "2px solid $dark300",
138
+ cursor: "pointer",
139
+ boxSizing: "border-box",
140
+ "&.checked::before": {
141
+ backgroundImage:
142
+ "url(\"data:image/svg+xml,%3Csvg%20width='16'%20height='16'%20viewBox='0%200%2014%2014'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M2%200C0.896875%200%200%200.896875%200%202V12C0%2013.1031%200.896875%2014%202%2014H12C13.1031%2014%2014%2013.1031%2014%2012V2C14%200.896875%2013.1031%200%2012%200H2ZM10.5312%205.53125L6.53125%209.53125C6.2375%209.825%205.7625%209.825%205.47188%209.53125L3.47187%207.53125C3.17812%207.2375%203.17812%206.7625%203.47187%206.47188C3.76562%206.18125%204.24062%206.17813%204.53125%206.47188L6%207.94063L9.46875%204.46875C9.7625%204.175%2010.2375%204.175%2010.5281%204.46875C10.8187%204.7625%2010.8219%205.2375%2010.5281%205.52812L10.5312%205.53125Z'%20fill='%23004ED2'/%3E%3C/svg%3E\")",
143
+ content: "",
144
+ width: "1rem",
145
+ height: "1rem",
146
+ position: "absolute",
147
+ top: "-1px",
148
+ right: "-2px",
149
+ zIndex: "2",
150
+ backgroundRepeat: "no-repeat",
151
+ }
152
+ },
153
+ "&:hover": {
154
+ "div": {
155
+ transition: "all 300ms ease-out",
156
+ boxShadow: "rgba(56, 129, 255, 0.5) 0px 0px 0px 4px",
157
+ }
158
+ },
159
+ });