torch-glare 1.0.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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +207 -0
  3. package/cli/bin/addComponent.js +278 -0
  4. package/cli/bin/addHooks.js +75 -0
  5. package/cli/bin/addLayout.js +71 -0
  6. package/cli/bin/addProvider.js +71 -0
  7. package/cli/bin/addUtils.js +74 -0
  8. package/cli/bin/cli.js +73 -0
  9. package/cli/bin/init/init.js +15 -0
  10. package/cli/bin/init/tailwindInit.js +174 -0
  11. package/cli/bin/update.js +147 -0
  12. package/lib/components/ActionButton.tsx +63 -0
  13. package/lib/components/ActionsGroup.tsx +34 -0
  14. package/lib/components/AlertDialog.tsx +211 -0
  15. package/lib/components/Badge.tsx +116 -0
  16. package/lib/components/BadgeField.tsx +192 -0
  17. package/lib/components/Button.tsx +277 -0
  18. package/lib/components/Card.tsx +63 -0
  19. package/lib/components/Checkbox.tsx +104 -0
  20. package/lib/components/CountBadge.tsx +54 -0
  21. package/lib/components/DatePicker.tsx +464 -0
  22. package/lib/components/Drawer.tsx +118 -0
  23. package/lib/components/DropdownMenu.tsx +399 -0
  24. package/lib/components/FieldHint.tsx +76 -0
  25. package/lib/components/ImageAttachment.tsx +171 -0
  26. package/lib/components/InnerLabelField.tsx +155 -0
  27. package/lib/components/Input.tsx +179 -0
  28. package/lib/components/InputField.tsx +147 -0
  29. package/lib/components/Label.tsx +107 -0
  30. package/lib/components/LabelField.tsx +75 -0
  31. package/lib/components/LabeledCheckBox.tsx +65 -0
  32. package/lib/components/LabeledRadio.tsx +45 -0
  33. package/lib/components/LinkButton.tsx +90 -0
  34. package/lib/components/LoginButton.tsx +56 -0
  35. package/lib/components/PasswordLevel.tsx +58 -0
  36. package/lib/components/Popover.tsx +274 -0
  37. package/lib/components/ProfileMenu.tsx +90 -0
  38. package/lib/components/Radio.tsx +69 -0
  39. package/lib/components/RadioCard.tsx +70 -0
  40. package/lib/components/RingLoading.tsx +190 -0
  41. package/lib/components/SearchField.tsx +49 -0
  42. package/lib/components/Select.tsx +417 -0
  43. package/lib/components/SlideDatePicker.tsx +120 -0
  44. package/lib/components/SpinLoading.tsx +190 -0
  45. package/lib/components/Switcher.tsx +56 -0
  46. package/lib/components/TabFormItem.tsx +158 -0
  47. package/lib/components/Table.tsx +395 -0
  48. package/lib/components/Textarea.tsx +108 -0
  49. package/lib/components/Tooltip.tsx +111 -0
  50. package/lib/components/TransparentLabel.tsx +72 -0
  51. package/lib/components/TreeDropDown.tsx +69 -0
  52. package/lib/hooks/MobileSlidePicker/components/Picker.tsx +218 -0
  53. package/lib/hooks/MobileSlidePicker/components/PickerColumn.tsx +238 -0
  54. package/lib/hooks/MobileSlidePicker/components/PickerItem.tsx +64 -0
  55. package/lib/hooks/MobileSlidePicker/index.ts +10 -0
  56. package/lib/hooks/useActiveTreeItem.tsx +61 -0
  57. package/lib/hooks/useClickOutside.tsx +20 -0
  58. package/lib/hooks/useResize.tsx +78 -0
  59. package/lib/layouts/CLayout.tsx +326 -0
  60. package/lib/layouts/FieldSection.tsx +64 -0
  61. package/lib/layouts/TreeSubLayout.tsx +187 -0
  62. package/lib/providers/ThemeProvider.tsx +99 -0
  63. package/lib/utils/cn.ts +6 -0
  64. package/lib/utils/convertImageFileToDataUrl.ts +17 -0
  65. package/lib/utils/resize.ts +35 -0
  66. package/lib/utils/types.ts +12 -0
  67. package/package.json +28 -0
  68. package/torch-glare.js +24 -0
@@ -0,0 +1,65 @@
1
+ 'use client';
2
+ import { InputHTMLAttributes, forwardRef, useState } from "react";
3
+ import { Label } from "./Label";
4
+ import { cn } from "../utils/cn";
5
+ import { cva } from "class-variance-authority";
6
+ import { Themes } from "../utils/types";
7
+ import { Checkbox } from "./Checkbox";
8
+
9
+ interface Props extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
10
+ label: string;
11
+ id: string;
12
+ secondaryLabel?: string;
13
+ requiredLabel?: string;
14
+ directions?: "vertical" | "horizontal";
15
+ size?: "S" | "M" | "L";
16
+ theme?: Themes
17
+ }
18
+
19
+ export const LabeledCheckBox = forwardRef<HTMLInputElement, Props>(
20
+ (
21
+ {
22
+ id,
23
+ label,
24
+ secondaryLabel,
25
+ requiredLabel,
26
+ type = "checkbox",
27
+ directions,
28
+ theme,
29
+ className,
30
+ size = "M",
31
+ ...props
32
+ },
33
+ ref
34
+ ) => {
35
+ return (
36
+ <label
37
+ htmlFor={id}
38
+ data-theme={theme}
39
+ className={cn("flex items-center gap-1 group", className)}
40
+ >
41
+ <Checkbox
42
+ {...props}
43
+ id={id}
44
+ disabled={props.disabled}
45
+ type={type}
46
+ size={size}
47
+ ref={ref}
48
+ >
49
+ <Label
50
+ className="leading-none"
51
+ htmlFor={id}
52
+ label={label}
53
+ secondaryLabel={secondaryLabel}
54
+ requiredLabel={requiredLabel}
55
+ size={size}
56
+ directions={directions}
57
+ />
58
+ </Checkbox>
59
+ </label>
60
+ );
61
+ }
62
+ );
63
+
64
+ LabeledCheckBox.displayName = "LabeledCheckBox";
65
+
@@ -0,0 +1,45 @@
1
+ 'use client'
2
+ import { InputHTMLAttributes, forwardRef } from "react";
3
+ import { Label } from "./Label";
4
+ import { Radio } from "./Radio";
5
+
6
+ interface Props extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
7
+ label?: string;
8
+ secondaryLabel?: string;
9
+ requiredLabel?: string;
10
+ size?: "S" | "M" | "L";
11
+ directions?: "vertical" | "horizontal";
12
+ theme?: "dark" | "light" | "default";
13
+ }
14
+
15
+ export const LabeledRadio = forwardRef<HTMLInputElement, Props>(
16
+ (
17
+ {
18
+ label,
19
+ theme,
20
+ secondaryLabel,
21
+ requiredLabel,
22
+ size = "M",
23
+ type = "radio",
24
+ directions,
25
+ className,
26
+ ...props
27
+ },
28
+ ref
29
+ ) => {
30
+ return (
31
+ <Radio {...props} data-theme={theme} checked={props.checked} size={size} ref={ref} >
32
+ <Label
33
+ htmlFor={props.id}
34
+ label={label}
35
+ secondaryLabel={secondaryLabel}
36
+ requiredLabel={requiredLabel}
37
+ size={size}
38
+ directions={directions}
39
+ />
40
+ </Radio>
41
+ );
42
+ }
43
+ );
44
+
45
+ LabeledRadio.displayName = "LabeledRadio";
@@ -0,0 +1,90 @@
1
+ import React, { AnchorHTMLAttributes, SVGProps } from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { cn } from "../utils/cn";
4
+ import { Themes } from "../utils/types";
5
+
6
+ // Link button base styles
7
+ export const linkButtonStyles = cva(
8
+ [
9
+ "bg-background-presentation-action-link-primary w-fit",
10
+ "flex items-center justify-center",
11
+ "rounded-[6px]",
12
+ "p-[2px]",
13
+ "text-content-presentation-action-link",
14
+ "hover:bg-background-presentation-action-link-hover hover:px-[2px]",
15
+ "transition-all duration-250 ease-in-out",
16
+ "group", // Add group class here
17
+ ],
18
+ {
19
+ variants: {
20
+ size: {
21
+ S: "h-[24px] typography-body-small-semibold",
22
+ M: "h-[26px] typography-body-medium-semibold",
23
+ },
24
+ },
25
+ defaultVariants: {
26
+ size: "S",
27
+ },
28
+ }
29
+ );
30
+
31
+ interface Props extends AnchorHTMLAttributes<HTMLAnchorElement> {
32
+ size?: "S" | "M"; // this props will change the button style size see on figma design file
33
+ theme?: Themes
34
+ }
35
+
36
+ export const LinkButton: React.FC<Props> = ({ theme, size = "S", className, ...props }) => {
37
+ return (
38
+ <a
39
+ {...props}
40
+ data-theme={theme}
41
+ className={cn(
42
+ linkButtonStyles({
43
+ size: size,
44
+ }),
45
+ className
46
+ )}
47
+ >
48
+ <p className="px-[3px]">{props.children}</p>
49
+ <div
50
+ className={cn(
51
+ "rounded-[4px]",
52
+ "bg-background-presentation-state-information-primary",
53
+ "transition-all duration-[100] ease-in-out",
54
+ "h-0 w-0 p-0",
55
+ "opacity-0 group-hover:opacity-100",
56
+ "p-[3px]",
57
+ {
58
+ "group-hover:w-[20px] group-hover:h-[20px]": size === "S",
59
+ "group-hover:w-[22px] group-hover:h-[22px]": size === "M",
60
+ }
61
+ )}
62
+ >
63
+ <Arrow
64
+ className={cn("rtl:rotate-[260deg]", {
65
+ "group-hover:w-[14px] group-hover:h-[14px]": size === "S",
66
+ "group-hover:w-[16px] group-hover:h-[16px]": size === "M",
67
+ })}
68
+ />
69
+ </div>
70
+ </a>
71
+ );
72
+ };
73
+
74
+ const Arrow = (props: SVGProps<SVGSVGElement>) => (
75
+ <svg
76
+ viewBox="0 0 10 10"
77
+ fill="none"
78
+ xmlns="http://www.w3.org/2000/svg"
79
+ {...props}
80
+ >
81
+ <path
82
+ d="M1.81582 1.58451L3.2807 0.119629L9.12479 0.875203L9.88037 6.71929L8.41549 8.18417L7.78584 3.31409L3.35267 7.74727L2.25272 6.64733L6.6859 2.21415L1.81582 1.58451Z"
83
+ fill="#F9F9F9"
84
+ />
85
+ <path
86
+ d="M0.325211 8.57478L1.48169 7.4183L2.58164 8.51824L1.42515 9.67472L0.325211 8.57478Z"
87
+ fill="#F9F9F9"
88
+ />
89
+ </svg>
90
+ );
@@ -0,0 +1,56 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+ import { cn } from "../utils/cn"; // Assuming you have a `cn` utility
3
+ import { ButtonHTMLAttributes } from "react";
4
+ import { LoadingIcon } from "./Button";
5
+ import { Themes } from "../utils/types";
6
+
7
+ const buttonVariants = cva(
8
+ "w-full h-[42px] rounded-[8px] typography-body-large-regular flex justify-center items-center transition-all duration-250 ease-in-out border",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: [
13
+ "bg-background-system-body-primary",
14
+ "text-content-system-global-primary",
15
+ "border-border-system-global-primary",
16
+ "hover:border-[#9748FF]",
17
+ ],
18
+ noBg: [
19
+ "bg-transparent",
20
+ "border-border-system-global-primary",
21
+ "text-content-system-global-primary",
22
+ "hover:border-[#9748FF]",
23
+ "no-underline",
24
+ ],
25
+ },
26
+ },
27
+ defaultVariants: {
28
+ variant: "default",
29
+ },
30
+ }
31
+ );
32
+
33
+ export interface ButtonProps
34
+ extends ButtonHTMLAttributes<HTMLButtonElement>,
35
+ VariantProps<typeof buttonVariants> {
36
+ isLoading?: boolean;
37
+ theme?: Themes
38
+ }
39
+
40
+ export function LoginButton({
41
+ variant = "default",
42
+ className,
43
+ isLoading,
44
+ theme,
45
+ ...props
46
+ }: ButtonProps) {
47
+ return (
48
+ <button data-theme={theme} {...props} className={cn(buttonVariants({ variant, className }))}>
49
+ {isLoading ? (
50
+ <LoadingIcon className="w-[20px] h-[20px]" />
51
+ ) : (
52
+ props.children
53
+ )}
54
+ </button>
55
+ );
56
+ }
@@ -0,0 +1,58 @@
1
+ import { Themes } from "../utils/types";
2
+ import { cn } from "../utils/cn"; // Assuming you have a `cn` utility
3
+ import { HTMLAttributes, useEffect, useState } from "react";
4
+
5
+ interface PassCheckProps extends HTMLAttributes<HTMLDivElement> {
6
+ value: string; // The password value to check
7
+ theme?: Themes
8
+ }
9
+
10
+ export function PasswordLevel({ theme, value, className, ...props }: PassCheckProps) {
11
+ const [level, setLevel] = useState<number>(0);
12
+
13
+ useEffect(() => {
14
+ const symbolRegex = /[!@#$%^&*(),.?":{}|<>]/;
15
+ const uppercaseRegex = /[A-Z]/;
16
+ let passwordLev = 0;
17
+ if (value.length >= 6) passwordLev++;
18
+ if (symbolRegex.test(value)) passwordLev++;
19
+ if (uppercaseRegex.test(value)) passwordLev++;
20
+ setLevel(passwordLev);
21
+ }, [value]);
22
+
23
+ return (
24
+ <div
25
+ data-theme={theme}
26
+ {...props}
27
+ className={cn(
28
+ "bg-background-system-body-secondary rounded-[4px] border border-solid border-border-system-global-primary p-[4px] grid grid-cols-3 gap-[4px] w-full ",
29
+ className
30
+ )}
31
+ >
32
+ <div
33
+ className={cn(
34
+ "h-[4px] rounded-[8px] transition-all duration-300 ease-in-out bg-border-system-global-secondary",
35
+ {
36
+ "bg-border-presentation-state-negative": level >= 1,
37
+ }
38
+ )}
39
+ />
40
+ <div
41
+ className={cn(
42
+ "h-[4px] rounded-[8px] transition-all duration-300 ease-in-out bg-border-system-global-secondary",
43
+ {
44
+ "bg-border-presentation-state-warning": level >= 2,
45
+ }
46
+ )}
47
+ />
48
+ <div
49
+ className={cn(
50
+ "h-[4px] rounded-[8px] transition-all duration-300 ease-in-out bg-border-system-global-secondary",
51
+ {
52
+ "bg-border-presentation-state-success": level >= 3,
53
+ }
54
+ )}
55
+ />
56
+ </div>
57
+ );
58
+ }
@@ -0,0 +1,274 @@
1
+ 'use client'
2
+ import { cva, VariantProps } from "class-variance-authority";
3
+ import { cn } from "../utils/cn";
4
+ import React, { useEffect, useRef } from "react";
5
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
6
+ import { Slot } from "@radix-ui/react-slot";
7
+ import { Themes } from "../utils/types";
8
+
9
+ interface LocalPopOverProps extends VariantProps<typeof dropdownMenuStyles> {
10
+ variant?: "SystemStyle" | "PresentationStyle";
11
+ className?: string;
12
+ overlayBlur?: boolean;
13
+ }
14
+
15
+ const dropdownMenuStyles = cva(
16
+ [
17
+ "p-1 max-h-[200px] z-[1000]",
18
+ "rounded-[8px]",
19
+ "border",
20
+ "min-w-[240px]",
21
+ "outline-none",
22
+ "overflow-scroll",
23
+ "data-[state=open]:animate-in",
24
+ "data-[state=closed]:animate-out",
25
+ "data-[state=closed]:fade-out-0",
26
+ "data-[state=open]:fade-in-0",
27
+ "scrollbar-hide",
28
+ "overflow-x-hidden",
29
+ ],
30
+ {
31
+ variants: {
32
+ variant: {
33
+ SystemStyle: [
34
+ "border-border-system-global-secondary",
35
+ "bg-background-system-body-primary",
36
+ "shadow-[0px_0px_18px_0px_rgba(0,0,0,0.75)]",
37
+ ],
38
+ PresentationStyle: [
39
+ "border-border-presentation-global-primary",
40
+ "bg-background-presentation-form-base",
41
+ "shadow-[0px_0px_10px_0px_rgba(0,0,0,0.4),0px_4px_4px_0px_rgba(0,0,0,0.2)]",
42
+ ],
43
+ },
44
+ overlayBlur: {
45
+ true: ["h-fit"],
46
+ },
47
+ defaultVariants: {
48
+ variant: "PresentationStyle",
49
+ },
50
+ },
51
+ }
52
+ );
53
+
54
+ const Popover = PopoverPrimitive.Root;
55
+
56
+ const PopoverTrigger = React.forwardRef<
57
+ React.ElementRef<typeof PopoverPrimitive.Trigger>,
58
+ React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Trigger> & {
59
+ className?: string
60
+ }
61
+ >(({ className, ...props }, ref) => (
62
+ <PopoverPrimitive.Trigger
63
+ ref={ref}
64
+ className={cn(
65
+ "z-[20] transition-all duration-300 data-[state=open]:z-[49]",
66
+ className
67
+ )}
68
+ {...props}
69
+ />
70
+ ));
71
+
72
+ PopoverTrigger.displayName = PopoverPrimitive.Trigger.displayName;
73
+
74
+ const PopoverContent = React.forwardRef<
75
+ React.ElementRef<typeof PopoverPrimitive.Content>,
76
+ React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> &
77
+ LocalPopOverProps & {
78
+ theme?: Themes
79
+ }
80
+ >(
81
+ (
82
+ {
83
+ className,
84
+ align = "center",
85
+ sideOffset = 4,
86
+ variant = "SystemStyle",
87
+ overlayBlur = false,
88
+ theme,
89
+ ...props
90
+ },
91
+ ref
92
+ ) => (
93
+ <PopoverPrimitive.Portal>
94
+ {overlayBlur ? (
95
+ <div className="relative z-[42]" data-theme={theme}>
96
+ <div className="fixed top-0 left-0 flex h-full w-full items-center flex-shrink-0 bg-[rgba(16,7,25,0.32)] backdrop-blur-[8px] transition-all duration-300"></div>
97
+ <PopoverPrimitive.Content
98
+ ref={ref}
99
+ align={align}
100
+ sideOffset={sideOffset}
101
+ className={cn(
102
+ dropdownMenuStyles({ variant, overlayBlur }),
103
+ className
104
+ )}
105
+ {...props}
106
+ />
107
+ </div>
108
+ ) : (
109
+ <PopoverPrimitive.Content
110
+ data-theme={theme}
111
+ ref={ref}
112
+ align={align}
113
+ sideOffset={sideOffset}
114
+ className={cn(
115
+ dropdownMenuStyles({ variant, overlayBlur }),
116
+ className
117
+ )}
118
+ {...props}
119
+ />
120
+ )}
121
+ </PopoverPrimitive.Portal>
122
+ )
123
+ );
124
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
125
+
126
+ // Define the Props interface with a generic type parameter
127
+ interface Props<T extends React.ElementType = "li">
128
+ extends React.HTMLAttributes<HTMLElement>,
129
+ VariantProps<typeof PopoverItemStyles> {
130
+ asChild?: boolean;
131
+ as?: T; // The `as` prop can be any valid HTML element or React component
132
+ }
133
+
134
+ // Define the PopoverItem component with a generic type parameter
135
+ const PopoverItem = <T extends React.ElementType = "li">({
136
+ variant = "SystemStyle",
137
+ size = "M",
138
+ asChild,
139
+ className,
140
+ children,
141
+ active,
142
+ as = "li" as T, // Default to "li" if `as` is not provided
143
+ ...props
144
+ }: Props<T> & Omit<React.ComponentPropsWithoutRef<T>, keyof Props<T>>) => {
145
+ const Component = asChild ? Slot : as;
146
+ const ref = useRef<HTMLLIElement>(null);
147
+
148
+ // Scroll to the selected item when the dropdown is opened
149
+ useEffect(() => {
150
+ if (active && ref.current) {
151
+ ref.current.scrollIntoView({ behavior: "auto", block: "center" });
152
+ }
153
+ }, [active]);
154
+
155
+ return (
156
+ <Component
157
+ {...(props as React.ComponentPropsWithoutRef<T>)} // Spread the props dynamically
158
+ className={cn(
159
+ PopoverItemStyles({
160
+ variant,
161
+ size,
162
+ active,
163
+ }),
164
+ className
165
+ )}
166
+ /// <reference path="" />
167
+ ref={ref}
168
+ >
169
+ {children}
170
+ </Component>
171
+ );
172
+ };
173
+
174
+
175
+ export { Popover, PopoverTrigger, PopoverContent, PopoverItem };
176
+
177
+ export const PopoverItemStyles = cva(
178
+ [
179
+ "text-content-presentation-action-light-primary",
180
+ "outline-none",
181
+ "border",
182
+ "border-transparent",
183
+ "flex",
184
+ "gap-[8px]",
185
+ "items-center",
186
+ "justify-start",
187
+ "text-overflow",
188
+ "overflow-hidden",
189
+ "px-[12px]",
190
+ "rounded-[4px]",
191
+ "transition-all",
192
+ "ease-in-out",
193
+ "duration-300",
194
+ ],
195
+ {
196
+ variants: {
197
+ variant: {
198
+ Default: [
199
+ "text-content-presentation-action-light-primary",
200
+ "bg-background-presentation-action-dropdown-primary",
201
+ "hover:bg-background-presentation-action-hover",
202
+ "hover:text-content-presentation-action-hover",
203
+ "focus:bg-background-presentation-action-selected",
204
+ "focus:text-content-presentation-action-light-primary",
205
+ "active:border-border-presentation-action-disabled",
206
+ "active:bg-background-presentation-action-selected",
207
+ "active:text-content-presentation-action-light-primary",
208
+ "active:border-border-presentation-action-disabled",
209
+ "disabled:text-content-presentation-state-disabled",
210
+ "disabled:bg-white-00",
211
+ ],
212
+ Warning: [
213
+ "bg-background-presentation-action-dropdown-primary",
214
+ "text-content-presentation-state-information",
215
+ "hover:bg-background-presentation-state-information-primary",
216
+ "hover:text-content-presentation-action-hover",
217
+ ],
218
+ Negative: [
219
+ "bg-background-presentation-action-dropdown-primary",
220
+ "text-content-presentation-state-negative",
221
+ "hover:bg-background-presentation-state-negative-primary",
222
+ "hover:!text-content-presentation-action-hover",
223
+ "focus:text-content-presentation-state-negative",
224
+ "active:text-content-presentation-state-negative",
225
+ ],
226
+ SystemStyle: [
227
+ "bg-background-system-body-primary",
228
+ "text-content-system-global-primary",
229
+ "hover:!bg-background-system-action-secondary-hover",
230
+ "hover:!text-content-system-action-primary-hover",
231
+ "hover:!border-border-system-action-primary-hover",
232
+ "focus:bg-background-System-Action-Primary-Selected",
233
+ "focus:border-transparent",
234
+ "active:border-transparent",
235
+ "active:bg-background-System-Action-Primary-Selected",
236
+ "disabled:bg-background-system-body-secondary",
237
+ "disabled:text-content-system-global-disabled",
238
+ ],
239
+ },
240
+ size: {
241
+ S: ["typography-body-small-regular", "h-[24px]"],
242
+ M: ["typography-body-medium-regular", "h-[32px]"],
243
+ },
244
+
245
+ disabled: {
246
+ true: [
247
+ "text-content-presentation-state-disabled",
248
+ "bg-white-00",
249
+ ],
250
+ },
251
+
252
+ active: {
253
+ true: [
254
+ "bg-background-presentation-action-selected",
255
+ "text-content-presentation-action-light-primary",
256
+ ],
257
+ },
258
+
259
+ defaultVariants: {
260
+ variant: "Default",
261
+ size: "M",
262
+ active: false,
263
+ disabled: false,
264
+ },
265
+ },
266
+ compoundVariants: [
267
+ {
268
+ active: true,
269
+ variant: "Warning",
270
+ className: ["text-content-presentation-state-negative"],
271
+ },
272
+ ],
273
+ }
274
+ );
@@ -0,0 +1,90 @@
1
+ import { HTMLAttributes, ReactNode, useEffect, useState } from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { cn } from "../utils/cn";
4
+ import { Popover, PopoverContent, PopoverTrigger } from "./Popover";
5
+
6
+ // Define the base styles and variants using `cva`
7
+ export const profileItemStyles = cva(
8
+ "flex items-center justify-between group w-full p-[6px] outline-none rounded-[8px] fucus:bg-background-system-action-primary-selected active:bg-background-system-action-primary-selected transition-all ease-in-out duration-150",
9
+ {
10
+ variants: {
11
+ selected: {
12
+ true: "bg-background-system-action-primary-selected",
13
+ }
14
+ },
15
+ }
16
+ );
17
+
18
+ interface ProfileItemProps extends HTMLAttributes<HTMLButtonElement> {
19
+ label: ReactNode;
20
+ selected?: boolean
21
+ icon?: string;
22
+ theme?: "dark" | "light" | "default";
23
+ popoverChildren?: ReactNode
24
+ overlayBlur?: boolean
25
+ }
26
+
27
+ export const ProfileMenu: React.FC<ProfileItemProps> = ({
28
+ label,
29
+ selected,
30
+ icon,
31
+ theme,
32
+ className,
33
+ popoverChildren,
34
+ overlayBlur,
35
+ ...props
36
+ }) => {
37
+
38
+ const [isOpen, setIsOpen] = useState(selected);
39
+ const [dropdownWidth, setDropdownWidth] = useState(0);
40
+
41
+ useEffect(() => {
42
+ setIsOpen(selected);
43
+ }, [selected])
44
+ return (
45
+ <Popover onOpenChange={(open) => setIsOpen(open)} >
46
+ <PopoverTrigger asChild>
47
+ <button
48
+ {...props}
49
+ data-theme={theme}
50
+ className={cn(
51
+ profileItemStyles({ selected }),
52
+ className
53
+ )}
54
+ onPointerDown={(e: any) => {
55
+ props.onPointerDown && props.onPointerDown(e);
56
+ setDropdownWidth(e.currentTarget.offsetWidth);
57
+ }}
58
+ >
59
+ <div className="flex items-center gap-2">
60
+ <div className="flex items-center">
61
+ <span className="h-[28px] w-[2px] bg-transparent group-hover:bg-[#9748FF] group-hover:mr-[6px] transition-all ease-in-out duration-150"></span>
62
+ <img className="w-[28px] h-[28px] rounded-full object-cover" src={icon} alt="" />
63
+ </div>
64
+
65
+ <p
66
+ className={cn(
67
+ "typography-body-medium-medium text-content-system-global-primary",
68
+ )}
69
+ >
70
+ {label}
71
+ </p>
72
+ </div>
73
+
74
+
75
+ <i className={cn("ri-arrow-down-s-line text-[18px] text-content-system-global-primary group-hover:text-[#9748FF] transition-all ease-in-out duration-150", { "rotate-180": isOpen && popoverChildren })}></i>
76
+ </button>
77
+ </PopoverTrigger>
78
+ {
79
+ popoverChildren &&
80
+ <PopoverContent
81
+ overlayBlur={overlayBlur}
82
+ style={{ width: `${dropdownWidth}px` }}
83
+ theme={theme}>
84
+ {popoverChildren}
85
+ </PopoverContent>
86
+ }
87
+ </Popover>
88
+ );
89
+ };
90
+