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,211 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
5
+
6
+ import { cn } from "../utils/cn"
7
+ import { buttonVariants } from "./Button"
8
+ import { ButtonVariant } from "@/utils/types"
9
+ import { cva } from "class-variance-authority"
10
+
11
+ const StatusTextStyle = cva("", {
12
+ variants: {
13
+ variant: {
14
+ default: "[&_strong]:text-content-presentation-global-primary [&_[data-description]]:text-content-presentation-global-primary",
15
+ info: "[&_strong]:text-content-presentation-state-information [&_[data-description]]:text-content-presentation-state-information",
16
+ success: "[&_strong]:text-content-presentation-state-success [&_[data-description]]:text-content-presentation-state-success",
17
+ warning: "[&_strong]:text-content-presentation-state-warning [&_[data-description]]:text-content-presentation-state-warning",
18
+ error: "[&_strong]:text-content-presentation-state-negative [&_[data-description]]:text-content-presentation-state-negative",
19
+ }
20
+ },
21
+ defaultVariants: {
22
+ variant: "default",
23
+ },
24
+ });
25
+
26
+
27
+ const AlertDialog = AlertDialogPrimitive.Root
28
+
29
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger
30
+
31
+ const AlertDialogPortal = AlertDialogPrimitive.Portal
32
+
33
+ const AlertDialogOverlay = React.forwardRef<
34
+ React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
35
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
36
+ >(({ className, ...props }, ref) => (
37
+ <AlertDialogPrimitive.Overlay
38
+ className={cn(
39
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
40
+ className
41
+ )}
42
+ {...props}
43
+ ref={ref}
44
+ />
45
+ ))
46
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
47
+
48
+ const AlertDialogContent = React.forwardRef<
49
+ React.ElementRef<typeof AlertDialogPrimitive.Content>,
50
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> & {
51
+ variant?: "info" | "success" | "warning" | "error" | "default"
52
+ }
53
+ >(({ className, variant = "default", ...props }, ref) => (
54
+ <AlertDialogPortal>
55
+ <AlertDialogOverlay />
56
+ <AlertDialogPrimitive.Content
57
+ ref={ref}
58
+ className={cn(StatusTextStyle({ variant }),
59
+ "text-content-presentation-global-primary max-w-[800px] !m-1 sm:m-0",
60
+ "fixed left-[50%] top-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%] gap-2 border bg-background-presentation-body-overlay-primary p-2 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
61
+ "rounded-[16px] border-2 border-border-presentation-global-primary",
62
+ className
63
+ )}
64
+ {...props}
65
+ />
66
+ </AlertDialogPortal>
67
+ ))
68
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
69
+
70
+ const AlertDialogHeader = ({
71
+ className,
72
+ ...props
73
+ }: React.HTMLAttributes<HTMLDivElement>) => (
74
+ <div
75
+ className={cn(
76
+ "flex justify-between space-x-2 text-left",
77
+ className
78
+ )}
79
+ {...props}
80
+ />
81
+ )
82
+ AlertDialogHeader.displayName = "AlertDialogHeader"
83
+
84
+ const AlertDialogFooter = ({
85
+ className,
86
+ ...props
87
+ }: React.HTMLAttributes<HTMLDivElement>) => (
88
+ <div
89
+ className={cn(
90
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
91
+ className
92
+ )}
93
+ {...props}
94
+ />
95
+ )
96
+ AlertDialogFooter.displayName = "AlertDialogFooter"
97
+
98
+ const AlertDialogTitle = React.forwardRef<
99
+ React.ElementRef<typeof AlertDialogPrimitive.Title>,
100
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
101
+ >(({ className, ...props }, ref) => (
102
+ <AlertDialogPrimitive.Title
103
+ ref={ref}
104
+ className={cn("typography-display-medium-semibold", className)}
105
+ {...props}
106
+ />
107
+ ))
108
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
109
+
110
+ const AlertDialogLabel = React.forwardRef<
111
+ React.ElementRef<typeof AlertDialogPrimitive.Title>,
112
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title> & {
113
+ title: string
114
+ }
115
+ >(({ className, title, ...props }, ref) => {
116
+ const words = title.split(' ');
117
+ const firstWord = words[0];
118
+ const restOfTitle = words.slice(1).join(' ');
119
+
120
+ return (
121
+ <AlertDialogPrimitive.Title
122
+ ref={ref}
123
+ className={cn("text-lg font-semibold", className)}
124
+ {...props}
125
+ >
126
+ <p >
127
+ <strong >{firstWord}</strong>
128
+ {restOfTitle.length > 0 && ' ' + restOfTitle}
129
+ </p>
130
+ </AlertDialogPrimitive.Title>
131
+ )
132
+ })
133
+ AlertDialogLabel.displayName = "AlertDialogLabel"
134
+
135
+ const AlertDialogDescription = React.forwardRef<
136
+ React.ElementRef<typeof AlertDialogPrimitive.Description>,
137
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
138
+ >(({ className, ...props }, ref) => (
139
+ <AlertDialogPrimitive.Description
140
+ data-description=""
141
+ ref={ref}
142
+ className={cn("bg-background-presentation-form-base border border-border-presentation-global-primary p-2 rounded-[8px]"
143
+ , "p-[12px_8px_12px_8px] sm:p-[24px_48px_48px_48px] typography-body-large-medium",
144
+ className)}
145
+
146
+ {...props}
147
+ >
148
+ {props.children}
149
+ </AlertDialogPrimitive.Description>
150
+ ))
151
+ AlertDialogDescription.displayName =
152
+ AlertDialogPrimitive.Description.displayName
153
+
154
+ const AlertDialogAction = React.forwardRef<
155
+ React.ElementRef<typeof AlertDialogPrimitive.Action>,
156
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> & {
157
+ size?: "M" | "S" | "L" | "XL"
158
+ variant?: ButtonVariant
159
+ buttonType?: "button" | "icon"
160
+ }
161
+ >(({ className,
162
+ size = "M",
163
+ variant = "BorderStyle",
164
+ buttonType = "button",
165
+ ...props }, ref) => (
166
+ <AlertDialogPrimitive.Action
167
+ ref={ref}
168
+ className={cn(buttonVariants({ variant: variant, size: size, buttonType: buttonType }), className)}
169
+ {...props}
170
+ />
171
+ ))
172
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
173
+
174
+ const AlertDialogCancel = React.forwardRef<
175
+ React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
176
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel> & {
177
+ size?: "M" | "S" | "L" | "XL"
178
+ variant?: ButtonVariant
179
+ buttonType?: "button" | "icon"
180
+ }
181
+ >(({ className,
182
+ size = "M",
183
+ variant = "RedSecStyle",
184
+ buttonType = "icon",
185
+ ...props }, ref) => (
186
+ <AlertDialogPrimitive.Cancel
187
+ ref={ref}
188
+ className={cn(
189
+ buttonVariants({ variant: variant, size: size, buttonType: buttonType }),
190
+ "",
191
+ className
192
+ )}
193
+ {...props}
194
+ />
195
+ ))
196
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
197
+
198
+ export {
199
+ AlertDialog,
200
+ AlertDialogPortal,
201
+ AlertDialogOverlay,
202
+ AlertDialogTrigger,
203
+ AlertDialogContent,
204
+ AlertDialogHeader,
205
+ AlertDialogFooter,
206
+ AlertDialogTitle,
207
+ AlertDialogLabel,
208
+ AlertDialogDescription,
209
+ AlertDialogAction,
210
+ AlertDialogCancel,
211
+ }
@@ -0,0 +1,116 @@
1
+ import { ReactNode, HTMLAttributes } from "react";
2
+ import { cva, VariantProps } from "class-variance-authority";
3
+ import { cn } from "../utils/cn";
4
+ import { Themes } from "../utils/types";
5
+
6
+ export const badgeBase = cva(
7
+ [
8
+ "px-[6px]",
9
+ "[&_p]:text-content-presentation-action-light-primary",
10
+ "[&_i]:!leading-0",
11
+ "flex",
12
+ "justify-center",
13
+ "items-center",
14
+ "border",
15
+ "rounded-[6px]",
16
+ "transition-all",
17
+ "duration-300",
18
+ "ease-in-out",
19
+ "w-fit",
20
+ "cursor-pointer",
21
+ "[&_i]:leading-0",
22
+ ],
23
+ {
24
+ variants: {
25
+ size: {
26
+ XS: "h-[18px] [&_i]:text-[12px] [&_p]:typography-body-small-medium",
27
+ S: "h-[22px] [&_i]:text-[12px] [&_p]:typography-body-small-medium",
28
+ M: "h-[26px] [&_i]:text-[16px] [&_p]:typography-body-medium-medium",
29
+ },
30
+ variant: {
31
+ highlight: ["h-[20px] [&_i]:text-[12px] [&_p]:typography-body-small-medium",
32
+ "bg-background-presentation-badge-gray border-transparent px-[3px]"
33
+ ],
34
+ green: "border-border-presentation-badge-green bg-background-presentation-badge-green [&_i]:text-content-presentation-badge-green",
35
+ greenLight: "border-border-presentation-badge-green-light bg-background-presentation-badge-green-light [&_i]:text-content-presentation-badge-green-light",
36
+ cocktailGreen: "border-border-presentation-badge-cocktail-green bg-background-presentation-badge-cocktail-green [&_i]:text-content-presentation-badge-cocktail-green",
37
+ yellow: "border-border-presentation-badge-yellow bg-background-presentation-badge-yellow [&_i]:text-content-presentation-badge-yellow",
38
+ redOrange: "border-border-presentation-badge-red-orange bg-background-presentation-badge-red-orange [&_i]:text-content-presentation-badge-red-orange",
39
+ redLight: "border-border-presentation-badge-red bg-background-presentation-badge-red [&_i]:text-content-presentation-badge-red",
40
+ rose: "border-border-presentation-badge-rose bg-background-presentation-badge-rose [&_i]:text-content-presentation-badge-rose",
41
+ purple: "border-border-presentation-badge-purple bg-background-presentation-badge-purple [&_i]:text-content-presentation-badge-purple",
42
+ bluePurple: "border-border-presentation-badge-blue-purple bg-background-presentation-badge-blue-purple [&_i]:text-content-presentation-badge-blue-purple",
43
+ blue: "border-border-presentation-badge-blue bg-background-presentation-badge-blue [&_i]:text-content-presentation-badge-blue",
44
+ navy: "border-border-presentation-badge-navy bg-background-presentation-badge-navy [&_i]:text-content-presentation-badge-navy",
45
+ gray: "border-border-presentation-badge-gray bg-background-presentation-badge-gray [&_i]:text-content-presentation-badge-gray",
46
+ },
47
+ },
48
+ defaultVariants: {
49
+ size: "S",
50
+ variant: "green",
51
+ },
52
+ }
53
+ );
54
+
55
+ interface BadgeProps extends HTMLAttributes<HTMLButtonElement>,
56
+ VariantProps<typeof badgeBase> {
57
+ label?: string;
58
+ onUnselect?: () => void;
59
+ isSelected?: boolean;
60
+ badgeIcon?: ReactNode;
61
+ className?: string;
62
+ theme?: Themes
63
+ }
64
+
65
+ export const Badge: React.FC<BadgeProps> = ({
66
+ label,
67
+ onUnselect,
68
+ isSelected,
69
+ badgeIcon,
70
+ theme,
71
+ size = "S",
72
+ variant = "green",
73
+ className,
74
+ ...props
75
+ }) => {
76
+ return (
77
+ <span
78
+ {...props}
79
+ data-theme={theme}
80
+ className={cn(
81
+ badgeBase({ size, variant }),
82
+ {
83
+ "cursor-default": isSelected,
84
+ },
85
+ className
86
+ )}
87
+ >
88
+ <div className={"flex justify-center items-center"}>
89
+ {!badgeIcon ? (
90
+ <i className={cn("ri-circle-fill !text-[8px]", { "hidden": variant === "highlight" })}></i>
91
+ ) : (
92
+ badgeIcon
93
+ )}
94
+ </div>
95
+
96
+ <p className="px-[3px] whitespace-nowrap">{label}</p>
97
+ {isSelected && (
98
+ <button
99
+ onClick={onUnselect}
100
+ className="rounded-[2px] flex justify-center items-center cursor-pointer"
101
+ tabIndex={0}
102
+ role="button"
103
+ aria-label="Remove badge"
104
+ onKeyDown={(e) => {
105
+ if (e.key === 'Enter' || e.key === ' ') {
106
+ e.preventDefault();
107
+ onUnselect?.();
108
+ }
109
+ }}
110
+ >
111
+ <i className="ri-close-line !text-content-presentation-action-light-primary"></i>
112
+ </button>
113
+ )}
114
+ </span>
115
+ );
116
+ };
@@ -0,0 +1,192 @@
1
+ "use client";
2
+ import {
3
+ forwardRef,
4
+ InputHTMLAttributes,
5
+ ReactNode,
6
+ useEffect,
7
+ useRef,
8
+ useState,
9
+ } from "react";
10
+ import { cn } from "../utils/cn";
11
+ import { Tooltip, ToolTipSide } from "./Tooltip";
12
+ import { Popover, PopoverContent, PopoverTrigger } from "./Popover";
13
+ import { Themes } from "../utils/types";
14
+ import { Icon, Input, Group, Trilling } from "./Input";
15
+
16
+ export interface Props
17
+ extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "variant"> {
18
+ size?: "XS" | "S" | "M"; // this is used to change the size style of the component
19
+ variant?: "SystemStyle" | "PresentationStyle";
20
+ icon?: ReactNode; // to add left side icon if you pass it
21
+ popoverChildren?: ReactNode; // to add drop down list if you pass it
22
+ errorMessage?: string; // to show tooltip component when error_message not null
23
+ onTable?: boolean; // to change the border style of the component when it is on table
24
+ toolTipSide?: ToolTipSide;
25
+ badgesChildren?: ReactNode;
26
+ label?: string;
27
+ required?: boolean;
28
+ theme?: Themes
29
+ actionButton?: ReactNode
30
+ }
31
+
32
+
33
+ export const BadgeField = forwardRef<HTMLInputElement, Props>(
34
+ (
35
+ {
36
+ size = "M",
37
+ label,
38
+ required,
39
+ icon,
40
+ popoverChildren,
41
+ errorMessage,
42
+ onTable,
43
+ variant = "PresentationStyle",
44
+ toolTipSide,
45
+ className,
46
+ badgesChildren,
47
+ actionButton,
48
+ theme,
49
+ children,
50
+ ...props
51
+ },
52
+ forwardedRef
53
+ ) => {
54
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
55
+ const inputRef = useRef<HTMLInputElement>(null);
56
+ const sectionRef = useRef<HTMLDivElement>(null);
57
+ const popoverRef = useRef<HTMLDivElement>(null);
58
+ const [dropDownListWidth, setDropDownListWidth] = useState(0);
59
+
60
+ useInitialLoad({
61
+ forwardedRef,
62
+ inputRef,
63
+ sectionRef,
64
+ popoverRef,
65
+ setIsPopoverOpen,
66
+ });
67
+
68
+ return (
69
+ <Popover open={isPopoverOpen}>
70
+ <Tooltip
71
+ toolTipSide={toolTipSide}
72
+ open={errorMessage !== undefined}
73
+ text={errorMessage}
74
+ >
75
+ <PopoverTrigger asChild>
76
+ <Group
77
+ error={errorMessage !== undefined}
78
+ onTable={onTable}
79
+ data-theme={theme}
80
+ variant={variant}
81
+ size={size === "XS" ? "S" : size}
82
+ ref={sectionRef}
83
+ onFocus={(e: any) => {
84
+ setDropDownListWidth(e.currentTarget.offsetWidth);
85
+ setIsPopoverOpen(true);
86
+ }}
87
+ className={cn("flex gap-1 flex-row w-full relative p-1 flex-nowrap overflow-hidden justify-end h-fit items-center",
88
+ {
89
+ "flex-wrap justify-start": isPopoverOpen,
90
+ },
91
+ className
92
+ )}
93
+ >
94
+ {icon && (
95
+ <Icon >
96
+ {icon}
97
+ </Icon>
98
+ )}
99
+
100
+ {badgesChildren}
101
+
102
+ <Input
103
+ {...props}
104
+ onFocus={() => setIsPopoverOpen(true)}
105
+ ref={inputRef}
106
+ className={cn(
107
+ "min-w-[100px] w-full", // Added w-full to Input
108
+ {
109
+ "!h-[18px]": size === "XS",
110
+ "!h-[22px]": size === "S",
111
+ "!h-[24px]": size === "M",
112
+ }
113
+ )}
114
+ />
115
+ {
116
+ actionButton && (
117
+ <Trilling className="py-0" > {/* Keep the ActionButton right aligned */}
118
+ {actionButton}
119
+ </Trilling>
120
+ )
121
+ }
122
+ </Group>
123
+ </PopoverTrigger>
124
+ </Tooltip>
125
+
126
+ {popoverChildren && (
127
+ <PopoverContent
128
+ data-theme={theme}
129
+ ref={popoverRef}
130
+ style={{ width: dropDownListWidth }}
131
+ onOpenAutoFocus={(e: any) => e.preventDefault()}
132
+ variant={variant}
133
+ >
134
+ {popoverChildren}
135
+ </PopoverContent>
136
+ )}
137
+ </Popover>
138
+ );
139
+ }
140
+ );
141
+ BadgeField.displayName = "BadgeField";
142
+
143
+
144
+ const useInitialLoad = ({
145
+ forwardedRef,
146
+ inputRef,
147
+ sectionRef,
148
+ popoverRef,
149
+ setIsPopoverOpen,
150
+ }: {
151
+ forwardedRef: React.Ref<HTMLInputElement> | ((instance: HTMLInputElement | null) => void);
152
+ inputRef: React.RefObject<HTMLInputElement | null>;
153
+ sectionRef: React.RefObject<HTMLDivElement | null>;
154
+ popoverRef: React.RefObject<HTMLDivElement | null>;
155
+ setIsPopoverOpen: (value: boolean) => void;
156
+ }) => {
157
+
158
+ // set the reference
159
+ useEffect(() => {
160
+ if (!forwardedRef) return;
161
+ if (typeof forwardedRef === "function") {
162
+ forwardedRef(inputRef.current);
163
+ } else {
164
+ forwardedRef.current = inputRef.current;
165
+ }
166
+ }, [forwardedRef, inputRef]);
167
+
168
+
169
+ // detect click outside
170
+ useEffect(() => {
171
+ const handleOutsideClick = (event: MouseEvent) => {
172
+ if (
173
+ sectionRef.current &&
174
+ !sectionRef.current.contains(event.target as Node) &&
175
+ !popoverRef.current?.contains(event.target as Node)
176
+ ) {
177
+ setIsPopoverOpen(false);
178
+ } else {
179
+ setIsPopoverOpen(true);
180
+ inputRef.current?.focus();
181
+ }
182
+ };
183
+
184
+ document.addEventListener("mousedown", handleOutsideClick);
185
+ document.addEventListener("pointerdown", handleOutsideClick);
186
+
187
+ return () => {
188
+ document.removeEventListener("mousedown", handleOutsideClick);
189
+ document.removeEventListener("pointerdown", handleOutsideClick);
190
+ };
191
+ }, [sectionRef, popoverRef, setIsPopoverOpen, inputRef]);
192
+ };