@lets-events/react 11.2.0 → 11.4.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.
@@ -0,0 +1,216 @@
1
+ import { DropdownMenu, Theme } from "@radix-ui/themes";
2
+ import { Button } from "./Button";
3
+ import { CheckboxGroup, CheckboxItem } from "./CheckboxGroup";
4
+ import { styled, css } from "../styles";
5
+ import { Text } from "./Text";
6
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7
+ import {
8
+ faChevronDown,
9
+ faChevronUp,
10
+ faX,
11
+ } from "@fortawesome/free-solid-svg-icons";
12
+ import { colors } from "@lets-events/tokens";
13
+ import { ComponentProps, useCallback, useMemo, useRef, useState } from "react";
14
+ import { Flex } from "./Flex";
15
+ import { CSS } from "@stitches/react";
16
+ import React from "react";
17
+ import { Badge } from "./Badge";
18
+
19
+ const StyledContent = styled(DropdownMenu.Content, {
20
+ backgroundColor: "$dark50",
21
+ borderRadius: "$sm",
22
+ padding: "$8 0",
23
+ boxShadow: "0px 2px 4px 0px #23354329, 0px 4px 4px 0px #23354314",
24
+ boxSizing: "border-box",
25
+ border: "1px solid $dark300",
26
+ });
27
+
28
+ const StyledTrigger = styled("div", {
29
+ minHeight: "40px",
30
+ borderRadius: "$sm",
31
+ cursor: "pointer",
32
+ display: "flex",
33
+ justifyContent: "start",
34
+ alignItems: "center",
35
+ padding: "$6 $14",
36
+ boxSizing: "border-box",
37
+ gap: "4px",
38
+
39
+ variants: {
40
+ color: {
41
+ default: {
42
+ border: "1px solid $dark300",
43
+ },
44
+ error: {
45
+ border: "1px solid $error400",
46
+ },
47
+ },
48
+ },
49
+
50
+ defaultVariants: {
51
+ color: "default",
52
+ },
53
+ });
54
+
55
+ const itemStyle: CSS = {
56
+ padding: "$4 $16",
57
+ minHeight: "$32",
58
+ height: "32px",
59
+ boxSizing: "border-box",
60
+ backgroundColor: "$dark50",
61
+ display: "block",
62
+
63
+ "&:hover": {
64
+ backgroundColor: "$dark100",
65
+ },
66
+ };
67
+
68
+ const BadgeWrapper = styled("div", {
69
+ flex: "1",
70
+ display: "flex",
71
+ justifyContent: "start",
72
+ flexWrap: "wrap",
73
+ gap: "4px",
74
+ });
75
+
76
+ const BadgeCloseBtn = styled("div", {
77
+ borderRadius: "100%",
78
+ width: "16px",
79
+ height: "16px",
80
+ minWidth: "16px",
81
+ minHeight: "16px",
82
+ display: "flex",
83
+ justifyContent: "center",
84
+ alignItems: "center",
85
+
86
+ "&:hover": {
87
+ backgroundColor: "$dark600",
88
+ },
89
+ });
90
+
91
+ export type MultiSelectProps = ComponentProps<typeof StyledTrigger> & {
92
+ placeholder?: string;
93
+ value?: string[];
94
+ onValueChange?: (v: string[]) => void;
95
+ options: Array<{
96
+ label: string;
97
+ value: string;
98
+ }>;
99
+ width?: string;
100
+ };
101
+
102
+ export const MultiSelect = React.forwardRef<HTMLDivElement, MultiSelectProps>(
103
+ (
104
+ {
105
+ placeholder,
106
+ value: selectedValues = [],
107
+ onValueChange,
108
+ options,
109
+ color,
110
+ width = "100%",
111
+ },
112
+ fowardedRef
113
+ ) => {
114
+ const [isOpen, setIsOpen] = useState(false);
115
+
116
+ const triggerRef = useRef<HTMLDivElement>(null);
117
+
118
+ const labelByValue = useMemo(() => {
119
+ return options.reduce<{ [key: string]: string }>((prev, curr) => {
120
+ return {
121
+ ...prev,
122
+ [curr.value]: curr.label,
123
+ };
124
+ }, {});
125
+ }, [options]);
126
+
127
+ const handleRemove = useCallback(
128
+ (value: string) => {
129
+ const newValue = selectedValues.filter((v) => v !== value);
130
+ onValueChange?.(newValue);
131
+ },
132
+ [selectedValues, onValueChange]
133
+ );
134
+
135
+ const menuWidth = triggerRef.current?.offsetWidth;
136
+
137
+ return (
138
+ <Theme>
139
+ <DropdownMenu.Root open={isOpen} onOpenChange={() => setIsOpen(false)}>
140
+ <DropdownMenu.Trigger onClick={() => setIsOpen(true)}>
141
+ <StyledTrigger
142
+ css={{
143
+ width,
144
+ }}
145
+ ref={(r) => {
146
+ if (!r) return;
147
+ triggerRef.current = r;
148
+ if (fowardedRef) {
149
+ if (typeof fowardedRef === "function") fowardedRef(r);
150
+ else {
151
+ fowardedRef.current = r;
152
+ }
153
+ }
154
+ }}
155
+ color={color}
156
+ >
157
+ {selectedValues.length === 0 ? (
158
+ <Text typography={"labelMedium"} css={{ flex: 1 }}>
159
+ {placeholder ?? "Selecione"}
160
+ </Text>
161
+ ) : (
162
+ <BadgeWrapper>
163
+ {selectedValues.map((value) => {
164
+ return (
165
+ <Badge key={value} size={"sm"} color={"dark"}>
166
+ <Flex justify={"between"} align={"center"}>
167
+ <Text typography={"badgeSmall"} color="dark100">
168
+ {labelByValue[value]}
169
+ </Text>
170
+ <BadgeCloseBtn
171
+ onClick={(e) => {
172
+ e.stopPropagation();
173
+ handleRemove(value);
174
+ }}
175
+ role="button"
176
+ >
177
+ <FontAwesomeIcon icon={faX} size="xs" />
178
+ </BadgeCloseBtn>
179
+ </Flex>
180
+ </Badge>
181
+ );
182
+ })}
183
+ </BadgeWrapper>
184
+ )}
185
+ <FontAwesomeIcon
186
+ icon={isOpen ? faChevronUp : faChevronDown}
187
+ size="sm"
188
+ color={colors.dark600}
189
+ />
190
+ </StyledTrigger>
191
+ </DropdownMenu.Trigger>
192
+ <StyledContent
193
+ css={{
194
+ width: menuWidth ? menuWidth + "px" : width,
195
+ }}
196
+ >
197
+ <CheckboxGroup
198
+ value={selectedValues}
199
+ onValueChange={(v) => {
200
+ onValueChange?.(v);
201
+ }}
202
+ >
203
+ <Flex direction={"column"} gap={8}>
204
+ {options.map(({ value, label }, i) => (
205
+ <CheckboxItem value={value} css={itemStyle} key={i}>
206
+ <Text typography={"labelSmall"}>{label}</Text>
207
+ </CheckboxItem>
208
+ ))}
209
+ </Flex>
210
+ </CheckboxGroup>
211
+ </StyledContent>
212
+ </DropdownMenu.Root>
213
+ </Theme>
214
+ );
215
+ }
216
+ );
@@ -8,7 +8,6 @@ import { colors, Colors } from "@lets-events/tokens";
8
8
  export const TextStyle = styled(TextRadix, {
9
9
  fontFamily: "$default",
10
10
  lineHeight: "$base",
11
- color: "$grey950",
12
11
  variants: {
13
12
  typography: typographyValues,
14
13
  fontWeight: {
@@ -31,7 +30,7 @@ export function Text({ color, ...props }: TextProps) {
31
30
  <TextStyle
32
31
  {...props}
33
32
  css={{
34
- color: color ? "$" + color : "$grey950",
33
+ color: color ? "$" + color : "$dark600",
35
34
  ...props.css,
36
35
  }}
37
36
  />
package/src/index.tsx CHANGED
@@ -15,7 +15,9 @@ export * from "./components/Filter";
15
15
  export * from "./components/Dropdown";
16
16
  export * from "./components/Badge";
17
17
  export * from "./components/Modal";
18
+ export * from "./components/MenuDropdown";
18
19
  export * from "./components/Calendar";
20
+ export * from "./components/Drawer";
19
21
  export * from "./components/TimePicker";
20
22
  export * from "./components/Alert";
21
23
  export * from "./components/Switch";
@@ -24,6 +26,7 @@ export * from "./components/Card";
24
26
  export * from "./components/TextareaField";
25
27
  export * from "./components/Toast";
26
28
  export * from "./components/Tooltip";
29
+ export * from "./components/MultiSelect";
27
30
 
28
31
  // Layouts
29
32
  export * from "./components/Flex";
@@ -38,3 +41,4 @@ export * from "./components/FormFields/FormLabel";
38
41
  export * from "./components/FormFields/TextAreaFormField";
39
42
  export * from "./components/FormFields/TextFormField";
40
43
  export * from "./components/FormFields/Form";
44
+ export * from "./components/FormFields/MultiSelectFormField";