@sonamu-kit/react-components 0.1.0 → 0.1.2
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/dist/components/index.d.ts +65 -0
- package/dist/components/ui/accordion.d.ts +7 -0
- package/dist/components/ui/alert-dialog.d.ts +20 -0
- package/dist/components/ui/alert.d.ts +8 -0
- package/dist/components/ui/aspect-ratio.d.ts +3 -0
- package/dist/components/ui/async-select.d.ts +36 -0
- package/dist/components/ui/avatar.d.ts +6 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/breadcrumb.d.ts +19 -0
- package/dist/components/ui/button.d.ts +13 -0
- package/dist/components/ui/calendar.d.ts +5 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/carousel.d.ts +18 -0
- package/dist/components/ui/checkbox.d.ts +8 -0
- package/dist/components/ui/collapsible.d.ts +5 -0
- package/dist/components/ui/combobox.d.ts +20 -0
- package/dist/components/ui/command.d.ts +80 -0
- package/dist/components/ui/common-modal.d.ts +28 -0
- package/dist/components/ui/context-menu.d.ts +27 -0
- package/dist/components/ui/date-input.d.ts +7 -0
- package/dist/components/ui/date-picker.d.ts +26 -0
- package/dist/components/ui/date-selector-multiple.d.ts +38 -0
- package/dist/components/ui/dialog.d.ts +19 -0
- package/dist/components/ui/drawer.d.ts +22 -0
- package/dist/components/ui/dropdown-menu.d.ts +27 -0
- package/dist/components/ui/form.d.ts +23 -0
- package/dist/components/ui/hover-card.d.ts +6 -0
- package/dist/components/ui/image-uploader.d.ts +14 -0
- package/dist/components/ui/input-otp.d.ts +34 -0
- package/dist/components/ui/input.d.ts +7 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/menubar.d.ts +28 -0
- package/dist/components/ui/month-picker-multiple.d.ts +41 -0
- package/dist/components/ui/multi-image-uploader.d.ts +15 -0
- package/dist/components/ui/multi-select.d.ts +229 -0
- package/dist/components/ui/navigation-menu.d.ts +12 -0
- package/dist/components/ui/pagination.d.ts +10 -0
- package/dist/components/ui/popover.d.ts +7 -0
- package/dist/components/ui/progress.d.ts +4 -0
- package/dist/components/ui/radio-group.d.ts +5 -0
- package/dist/components/ui/resizable.d.ts +23 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/select.d.ts +20 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/sheet.d.ts +25 -0
- package/dist/components/ui/sidebar.d.ts +69 -0
- package/dist/components/ui/skeleton.d.ts +2 -0
- package/dist/components/ui/slider.d.ts +8 -0
- package/dist/components/ui/sonner.d.ts +4 -0
- package/dist/components/ui/switch.d.ts +8 -0
- package/dist/components/ui/table.d.ts +24 -0
- package/dist/components/ui/tabs.d.ts +7 -0
- package/dist/components/ui/textarea.d.ts +7 -0
- package/dist/components/ui/toast.d.ts +15 -0
- package/dist/components/ui/toaster.d.ts +1 -0
- package/dist/components/ui/toggle-group.d.ts +12 -0
- package/dist/components/ui/toggle.d.ts +12 -0
- package/dist/components/ui/tooltip.d.ts +7 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-toast.d.ts +44 -0
- package/dist/index.d.ts +3 -0
- package/dist/lib/caster.d.ts +3 -0
- package/dist/lib/helpers.d.ts +72 -0
- package/dist/lib/index.d.ts +6 -0
- package/{src/lib/lazy-upload.ts → dist/lib/lazy-upload.d.ts} +1 -12
- package/dist/lib/use-mobile.d.ts +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/react-components.es.js +28375 -0
- package/package.json +105 -76
- package/COMPONENTS_LIST.md +0 -106
- package/COMPONENTS_STATUS.md +0 -114
- package/HELPERS_GUIDE.md +0 -489
- package/MIGRATION_PLAN.md +0 -404
- package/SETUP_GUIDE.md +0 -125
- package/components.json +0 -21
- package/postcss.config.js +0 -6
- package/src/components/index.ts +0 -315
- package/src/components/ui/accordion.tsx +0 -54
- package/src/components/ui/alert-dialog.tsx +0 -115
- package/src/components/ui/alert.tsx +0 -49
- package/src/components/ui/aspect-ratio.tsx +0 -5
- package/src/components/ui/async-select.tsx +0 -186
- package/src/components/ui/avatar.tsx +0 -45
- package/src/components/ui/badge.tsx +0 -38
- package/src/components/ui/breadcrumb.tsx +0 -102
- package/src/components/ui/button.tsx +0 -54
- package/src/components/ui/calendar.tsx +0 -193
- package/src/components/ui/card.tsx +0 -65
- package/src/components/ui/carousel.tsx +0 -243
- package/src/components/ui/checkbox.tsx +0 -67
- package/src/components/ui/collapsible.tsx +0 -9
- package/src/components/ui/combobox.tsx +0 -135
- package/src/components/ui/command.tsx +0 -143
- package/src/components/ui/common-modal.tsx +0 -95
- package/src/components/ui/context-menu.tsx +0 -189
- package/src/components/ui/date-picker.tsx +0 -112
- package/src/components/ui/date-selector-multiple.tsx +0 -197
- package/src/components/ui/dialog.tsx +0 -104
- package/src/components/ui/drawer.tsx +0 -100
- package/src/components/ui/dropdown-menu.tsx +0 -189
- package/src/components/ui/form.tsx +0 -171
- package/src/components/ui/hover-card.tsx +0 -27
- package/src/components/ui/image-uploader.tsx +0 -251
- package/src/components/ui/input-otp.tsx +0 -69
- package/src/components/ui/input.tsx +0 -38
- package/src/components/ui/label.tsx +0 -19
- package/src/components/ui/menubar.tsx +0 -231
- package/src/components/ui/month-picker-multiple.tsx +0 -351
- package/src/components/ui/multi-image-uploader.tsx +0 -283
- package/src/components/ui/multi-select.tsx +0 -1143
- package/src/components/ui/navigation-menu.tsx +0 -120
- package/src/components/ui/pagination.tsx +0 -72
- package/src/components/ui/popover.tsx +0 -42
- package/src/components/ui/progress.tsx +0 -25
- package/src/components/ui/radio-group.tsx +0 -38
- package/src/components/ui/resizable.tsx +0 -42
- package/src/components/ui/scroll-area.tsx +0 -46
- package/src/components/ui/select.tsx +0 -235
- package/src/components/ui/separator.tsx +0 -24
- package/src/components/ui/sheet.tsx +0 -119
- package/src/components/ui/sidebar.tsx +0 -683
- package/src/components/ui/skeleton.tsx +0 -7
- package/src/components/ui/slider.tsx +0 -57
- package/src/components/ui/sonner.tsx +0 -39
- package/src/components/ui/switch.tsx +0 -63
- package/src/components/ui/table.tsx +0 -94
- package/src/components/ui/tabs.tsx +0 -53
- package/src/components/ui/textarea.tsx +0 -34
- package/src/components/ui/toast.tsx +0 -122
- package/src/components/ui/toaster.tsx +0 -29
- package/src/components/ui/toggle-group.tsx +0 -55
- package/src/components/ui/toggle.tsx +0 -41
- package/src/components/ui/tooltip.tsx +0 -28
- package/src/hooks/index.ts +0 -2
- package/src/hooks/use-toast.ts +0 -189
- package/src/icons.d.ts +0 -1
- package/src/index.ts +0 -4
- package/src/lib/caster.ts +0 -66
- package/src/lib/helpers.ts +0 -394
- package/src/lib/index.ts +0 -31
- package/src/lib/use-mobile.ts +0 -19
- package/src/lib/utils.ts +0 -6
- package/src/styles/globals.css +0 -658
- package/tailwind.config.ts +0 -8
- package/tsconfig.json +0 -31
- package/tsconfig.node.json +0 -11
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import type { Override } from "../../lib/helpers";
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
|
|
5
|
-
export type InputProps = Override<
|
|
6
|
-
React.ComponentProps<"input">,
|
|
7
|
-
{
|
|
8
|
-
onValueChange?: (value: string) => void;
|
|
9
|
-
}
|
|
10
|
-
>;
|
|
11
|
-
|
|
12
|
-
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
13
|
-
({ className, type, onValueChange, onChange, ...props }, ref) => {
|
|
14
|
-
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
15
|
-
onValueChange?.(e.target.value);
|
|
16
|
-
onChange?.(e);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<input
|
|
21
|
-
type={type}
|
|
22
|
-
data-slot="input"
|
|
23
|
-
className={cn(
|
|
24
|
-
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base bg-input-background transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
25
|
-
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
26
|
-
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
27
|
-
className,
|
|
28
|
-
)}
|
|
29
|
-
ref={ref}
|
|
30
|
-
{...props}
|
|
31
|
-
onChange={handleChange}
|
|
32
|
-
/>
|
|
33
|
-
);
|
|
34
|
-
},
|
|
35
|
-
);
|
|
36
|
-
Input.displayName = "Input";
|
|
37
|
-
|
|
38
|
-
export { Input };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
|
|
5
|
-
import { cn } from "../../lib/utils";
|
|
6
|
-
|
|
7
|
-
const labelVariants = cva(
|
|
8
|
-
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
const Label = React.forwardRef<
|
|
12
|
-
React.ElementRef<typeof LabelPrimitive.Root>,
|
|
13
|
-
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>
|
|
14
|
-
>(({ className, ...props }, ref) => (
|
|
15
|
-
<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
|
|
16
|
-
));
|
|
17
|
-
Label.displayName = LabelPrimitive.Root.displayName;
|
|
18
|
-
|
|
19
|
-
export { Label };
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import * as MenubarPrimitive from "@radix-ui/react-menubar";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import CheckIcon from "~icons/lucide/check";
|
|
4
|
-
import ChevronRightIcon from "~icons/lucide/chevron-right";
|
|
5
|
-
import CircleIcon from "~icons/lucide/circle";
|
|
6
|
-
|
|
7
|
-
import { cn } from "../../lib/utils";
|
|
8
|
-
|
|
9
|
-
function MenubarMenu({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
|
|
10
|
-
return <MenubarPrimitive.Menu {...props} />;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function MenubarGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Group>) {
|
|
14
|
-
return <MenubarPrimitive.Group {...props} />;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function MenubarPortal({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
|
|
18
|
-
return <MenubarPrimitive.Portal {...props} />;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function MenubarRadioGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
|
|
22
|
-
return <MenubarPrimitive.RadioGroup {...props} />;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function MenubarSub({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
|
|
26
|
-
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const Menubar = React.forwardRef<
|
|
30
|
-
React.ElementRef<typeof MenubarPrimitive.Root>,
|
|
31
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
|
|
32
|
-
>(({ className, ...props }, ref) => (
|
|
33
|
-
<MenubarPrimitive.Root
|
|
34
|
-
ref={ref}
|
|
35
|
-
className={cn(
|
|
36
|
-
"flex h-10 items-center space-x-1 rounded-md border bg-background p-1",
|
|
37
|
-
className,
|
|
38
|
-
)}
|
|
39
|
-
{...props}
|
|
40
|
-
/>
|
|
41
|
-
));
|
|
42
|
-
Menubar.displayName = MenubarPrimitive.Root.displayName;
|
|
43
|
-
|
|
44
|
-
const MenubarTrigger = React.forwardRef<
|
|
45
|
-
React.ElementRef<typeof MenubarPrimitive.Trigger>,
|
|
46
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
|
|
47
|
-
>(({ className, ...props }, ref) => (
|
|
48
|
-
<MenubarPrimitive.Trigger
|
|
49
|
-
ref={ref}
|
|
50
|
-
className={cn(
|
|
51
|
-
"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
|
52
|
-
className,
|
|
53
|
-
)}
|
|
54
|
-
{...props}
|
|
55
|
-
/>
|
|
56
|
-
));
|
|
57
|
-
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
|
|
58
|
-
|
|
59
|
-
const MenubarSubTrigger = React.forwardRef<
|
|
60
|
-
React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
|
|
61
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
|
|
62
|
-
inset?: boolean;
|
|
63
|
-
}
|
|
64
|
-
>(({ className, inset, children, ...props }, ref) => (
|
|
65
|
-
<MenubarPrimitive.SubTrigger
|
|
66
|
-
ref={ref}
|
|
67
|
-
className={cn(
|
|
68
|
-
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
|
69
|
-
inset && "pl-8",
|
|
70
|
-
className,
|
|
71
|
-
)}
|
|
72
|
-
{...props}
|
|
73
|
-
>
|
|
74
|
-
{children}
|
|
75
|
-
<ChevronRightIcon className="ml-auto h-4 w-4" />
|
|
76
|
-
</MenubarPrimitive.SubTrigger>
|
|
77
|
-
));
|
|
78
|
-
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
|
|
79
|
-
|
|
80
|
-
const MenubarSubContent = React.forwardRef<
|
|
81
|
-
React.ElementRef<typeof MenubarPrimitive.SubContent>,
|
|
82
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
|
|
83
|
-
>(({ className, ...props }, ref) => (
|
|
84
|
-
<MenubarPrimitive.SubContent
|
|
85
|
-
ref={ref}
|
|
86
|
-
className={cn(
|
|
87
|
-
"z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground 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 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]",
|
|
88
|
-
className,
|
|
89
|
-
)}
|
|
90
|
-
{...props}
|
|
91
|
-
/>
|
|
92
|
-
));
|
|
93
|
-
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
|
|
94
|
-
|
|
95
|
-
const MenubarContent = React.forwardRef<
|
|
96
|
-
React.ElementRef<typeof MenubarPrimitive.Content>,
|
|
97
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
|
|
98
|
-
>(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => (
|
|
99
|
-
<MenubarPrimitive.Portal>
|
|
100
|
-
<MenubarPrimitive.Content
|
|
101
|
-
ref={ref}
|
|
102
|
-
align={align}
|
|
103
|
-
alignOffset={alignOffset}
|
|
104
|
-
sideOffset={sideOffset}
|
|
105
|
-
className={cn(
|
|
106
|
-
"z-50 min-w-48 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]",
|
|
107
|
-
className,
|
|
108
|
-
)}
|
|
109
|
-
{...props}
|
|
110
|
-
/>
|
|
111
|
-
</MenubarPrimitive.Portal>
|
|
112
|
-
));
|
|
113
|
-
MenubarContent.displayName = MenubarPrimitive.Content.displayName;
|
|
114
|
-
|
|
115
|
-
const MenubarItem = React.forwardRef<
|
|
116
|
-
React.ElementRef<typeof MenubarPrimitive.Item>,
|
|
117
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
|
|
118
|
-
inset?: boolean;
|
|
119
|
-
}
|
|
120
|
-
>(({ className, inset, ...props }, ref) => (
|
|
121
|
-
<MenubarPrimitive.Item
|
|
122
|
-
ref={ref}
|
|
123
|
-
className={cn(
|
|
124
|
-
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
|
125
|
-
inset && "pl-8",
|
|
126
|
-
className,
|
|
127
|
-
)}
|
|
128
|
-
{...props}
|
|
129
|
-
/>
|
|
130
|
-
));
|
|
131
|
-
MenubarItem.displayName = MenubarPrimitive.Item.displayName;
|
|
132
|
-
|
|
133
|
-
const MenubarCheckboxItem = React.forwardRef<
|
|
134
|
-
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
|
|
135
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
|
|
136
|
-
>(({ className, children, checked, ...props }, ref) => (
|
|
137
|
-
<MenubarPrimitive.CheckboxItem
|
|
138
|
-
ref={ref}
|
|
139
|
-
className={cn(
|
|
140
|
-
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
|
141
|
-
className,
|
|
142
|
-
)}
|
|
143
|
-
checked={checked}
|
|
144
|
-
{...props}
|
|
145
|
-
>
|
|
146
|
-
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
147
|
-
<MenubarPrimitive.ItemIndicator>
|
|
148
|
-
<CheckIcon className="h-4 w-4" />
|
|
149
|
-
</MenubarPrimitive.ItemIndicator>
|
|
150
|
-
</span>
|
|
151
|
-
{children}
|
|
152
|
-
</MenubarPrimitive.CheckboxItem>
|
|
153
|
-
));
|
|
154
|
-
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
|
|
155
|
-
|
|
156
|
-
const MenubarRadioItem = React.forwardRef<
|
|
157
|
-
React.ElementRef<typeof MenubarPrimitive.RadioItem>,
|
|
158
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
|
|
159
|
-
>(({ className, children, ...props }, ref) => (
|
|
160
|
-
<MenubarPrimitive.RadioItem
|
|
161
|
-
ref={ref}
|
|
162
|
-
className={cn(
|
|
163
|
-
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
|
164
|
-
className,
|
|
165
|
-
)}
|
|
166
|
-
{...props}
|
|
167
|
-
>
|
|
168
|
-
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
169
|
-
<MenubarPrimitive.ItemIndicator>
|
|
170
|
-
<CircleIcon className="h-2 w-2 fill-current" />
|
|
171
|
-
</MenubarPrimitive.ItemIndicator>
|
|
172
|
-
</span>
|
|
173
|
-
{children}
|
|
174
|
-
</MenubarPrimitive.RadioItem>
|
|
175
|
-
));
|
|
176
|
-
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
|
|
177
|
-
|
|
178
|
-
const MenubarLabel = React.forwardRef<
|
|
179
|
-
React.ElementRef<typeof MenubarPrimitive.Label>,
|
|
180
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
|
|
181
|
-
inset?: boolean;
|
|
182
|
-
}
|
|
183
|
-
>(({ className, inset, ...props }, ref) => (
|
|
184
|
-
<MenubarPrimitive.Label
|
|
185
|
-
ref={ref}
|
|
186
|
-
className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
|
|
187
|
-
{...props}
|
|
188
|
-
/>
|
|
189
|
-
));
|
|
190
|
-
MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
|
|
191
|
-
|
|
192
|
-
const MenubarSeparator = React.forwardRef<
|
|
193
|
-
React.ElementRef<typeof MenubarPrimitive.Separator>,
|
|
194
|
-
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
|
|
195
|
-
>(({ className, ...props }, ref) => (
|
|
196
|
-
<MenubarPrimitive.Separator
|
|
197
|
-
ref={ref}
|
|
198
|
-
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
|
199
|
-
{...props}
|
|
200
|
-
/>
|
|
201
|
-
));
|
|
202
|
-
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
|
|
203
|
-
|
|
204
|
-
const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
205
|
-
return (
|
|
206
|
-
<span
|
|
207
|
-
className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
|
|
208
|
-
{...props}
|
|
209
|
-
/>
|
|
210
|
-
);
|
|
211
|
-
};
|
|
212
|
-
MenubarShortcut.displayname = "MenubarShortcut";
|
|
213
|
-
|
|
214
|
-
export {
|
|
215
|
-
Menubar,
|
|
216
|
-
MenubarMenu,
|
|
217
|
-
MenubarTrigger,
|
|
218
|
-
MenubarContent,
|
|
219
|
-
MenubarItem,
|
|
220
|
-
MenubarSeparator,
|
|
221
|
-
MenubarLabel,
|
|
222
|
-
MenubarCheckboxItem,
|
|
223
|
-
MenubarRadioGroup,
|
|
224
|
-
MenubarRadioItem,
|
|
225
|
-
MenubarPortal,
|
|
226
|
-
MenubarSubContent,
|
|
227
|
-
MenubarSubTrigger,
|
|
228
|
-
MenubarGroup,
|
|
229
|
-
MenubarSub,
|
|
230
|
-
MenubarShortcut,
|
|
231
|
-
};
|
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { format } from "date-fns";
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
import type { DateRange } from "react-day-picker";
|
|
6
|
-
import { Button } from "./button";
|
|
7
|
-
import { Popover, PopoverContent, PopoverTrigger } from "./popover";
|
|
8
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
|
|
9
|
-
|
|
10
|
-
/** 단일 월 또는 월 범위 값 */
|
|
11
|
-
export type MonthPickerValue =
|
|
12
|
-
| { type: "single"; date: Date }
|
|
13
|
-
| { type: "range"; from: Date; to: Date };
|
|
14
|
-
|
|
15
|
-
interface MonthPickerMultipleProps {
|
|
16
|
-
/** Calendar icon component */
|
|
17
|
-
CalendarIcon: React.ComponentType<{ className?: string }>;
|
|
18
|
-
/** ChevronDown icon component */
|
|
19
|
-
ChevronDownIcon: React.ComponentType<{ className?: string }>;
|
|
20
|
-
/** Current value */
|
|
21
|
-
value?: MonthPickerValue;
|
|
22
|
-
/** Callback when value changes */
|
|
23
|
-
onChange?: (event: null, data: { value: MonthPickerValue | undefined }) => void;
|
|
24
|
-
/** Placeholder text when no value */
|
|
25
|
-
placeholder?: string;
|
|
26
|
-
/** Date format string for display */
|
|
27
|
-
dateFormat?: string;
|
|
28
|
-
/** Custom className for trigger button */
|
|
29
|
-
className?: string;
|
|
30
|
-
/** Year range for selection */
|
|
31
|
-
yearRange?: { start: number; end: number };
|
|
32
|
-
/** Default to range mode when opening */
|
|
33
|
-
defaultRangeMode?: boolean;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
37
|
-
|
|
38
|
-
export function MonthPickerMultiple({
|
|
39
|
-
CalendarIcon,
|
|
40
|
-
ChevronDownIcon,
|
|
41
|
-
value,
|
|
42
|
-
onChange,
|
|
43
|
-
placeholder,
|
|
44
|
-
dateFormat = "MMM/yyyy",
|
|
45
|
-
className = "",
|
|
46
|
-
yearRange = { start: 2020, end: 2030 },
|
|
47
|
-
defaultRangeMode = false,
|
|
48
|
-
}: MonthPickerMultipleProps) {
|
|
49
|
-
// Popover open state
|
|
50
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
51
|
-
|
|
52
|
-
// Temp states (managed internally)
|
|
53
|
-
const [tempIsRangeMode, setTempIsRangeMode] = React.useState(defaultRangeMode);
|
|
54
|
-
const [tempDate, setTempDate] = React.useState<Date | undefined>();
|
|
55
|
-
const [tempDateRange, setTempDateRange] = React.useState<DateRange | undefined>();
|
|
56
|
-
const [tempYear, setTempYear] = React.useState<number>(new Date().getFullYear());
|
|
57
|
-
const [tempRangeStartYear, setTempRangeStartYear] = React.useState<number>(
|
|
58
|
-
new Date().getFullYear(),
|
|
59
|
-
);
|
|
60
|
-
const [tempRangeEndYear, setTempRangeEndYear] = React.useState<number>(new Date().getFullYear());
|
|
61
|
-
|
|
62
|
-
const years = React.useMemo(
|
|
63
|
-
() =>
|
|
64
|
-
Array.from({ length: yearRange.end - yearRange.start + 1 }, (_, i) => yearRange.start + i),
|
|
65
|
-
[yearRange.start, yearRange.end],
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
// Initialize temp states when popover opens
|
|
69
|
-
React.useEffect(() => {
|
|
70
|
-
if (isOpen) {
|
|
71
|
-
if (value?.type === "range") {
|
|
72
|
-
setTempIsRangeMode(true);
|
|
73
|
-
setTempDateRange({ from: value.from, to: value.to });
|
|
74
|
-
setTempDate(undefined);
|
|
75
|
-
setTempRangeStartYear(value.from.getFullYear());
|
|
76
|
-
setTempRangeEndYear(value.to.getFullYear());
|
|
77
|
-
} else if (value?.type === "single") {
|
|
78
|
-
setTempIsRangeMode(false);
|
|
79
|
-
setTempDate(value.date);
|
|
80
|
-
setTempDateRange(undefined);
|
|
81
|
-
setTempYear(value.date.getFullYear());
|
|
82
|
-
} else {
|
|
83
|
-
setTempIsRangeMode(defaultRangeMode);
|
|
84
|
-
setTempDate(undefined);
|
|
85
|
-
setTempDateRange(undefined);
|
|
86
|
-
setTempYear(new Date().getFullYear());
|
|
87
|
-
setTempRangeStartYear(new Date().getFullYear());
|
|
88
|
-
setTempRangeEndYear(new Date().getFullYear());
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}, [isOpen, value, defaultRangeMode]);
|
|
92
|
-
|
|
93
|
-
const getDisplayDate = () => {
|
|
94
|
-
if (!value) {
|
|
95
|
-
return placeholder ?? `- ${format(new Date(), dateFormat)}`;
|
|
96
|
-
}
|
|
97
|
-
if (value.type === "single") {
|
|
98
|
-
return format(value.date, dateFormat);
|
|
99
|
-
}
|
|
100
|
-
return `${format(value.from, dateFormat)} - ${format(value.to, dateFormat)}`;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const isSaveEnabled = () => {
|
|
104
|
-
if (tempIsRangeMode) {
|
|
105
|
-
return !!(tempDateRange?.from && tempDateRange?.to);
|
|
106
|
-
}
|
|
107
|
-
return tempDate !== undefined;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const handleModeChange = (isRangeMode: boolean) => {
|
|
111
|
-
setTempIsRangeMode(isRangeMode);
|
|
112
|
-
if (isRangeMode) {
|
|
113
|
-
setTempDate(undefined);
|
|
114
|
-
} else {
|
|
115
|
-
setTempDateRange(undefined);
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const handleSave = () => {
|
|
120
|
-
if (onChange) {
|
|
121
|
-
if (tempIsRangeMode && tempDateRange?.from && tempDateRange?.to) {
|
|
122
|
-
onChange(null, {
|
|
123
|
-
value: {
|
|
124
|
-
type: "range",
|
|
125
|
-
from: tempDateRange.from,
|
|
126
|
-
to: tempDateRange.to,
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
} else if (!tempIsRangeMode && tempDate) {
|
|
130
|
-
onChange(null, { value: { type: "single", date: tempDate } });
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
setIsOpen(false);
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const handleCancel = () => {
|
|
137
|
-
setIsOpen(false);
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
return (
|
|
141
|
-
<div className="flex items-center gap-4">
|
|
142
|
-
<Popover open={isOpen} onOpenChange={setIsOpen}>
|
|
143
|
-
<PopoverTrigger asChild>
|
|
144
|
-
<Button variant="outline" className={`gap-2 h-8 text-xs ${className}`}>
|
|
145
|
-
<CalendarIcon className="h-4 w-4" />
|
|
146
|
-
{getDisplayDate()}
|
|
147
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
148
|
-
</Button>
|
|
149
|
-
</PopoverTrigger>
|
|
150
|
-
<PopoverContent className="w-auto p-0" align="start">
|
|
151
|
-
<div className="p-3 border-b space-y-2">
|
|
152
|
-
<div className="flex gap-2">
|
|
153
|
-
<Button
|
|
154
|
-
variant={!tempIsRangeMode ? "default" : "outline"}
|
|
155
|
-
size="sm"
|
|
156
|
-
onClick={() => handleModeChange(false)}
|
|
157
|
-
className="flex-1 h-7 text-xs"
|
|
158
|
-
>
|
|
159
|
-
Single Date
|
|
160
|
-
</Button>
|
|
161
|
-
<Button
|
|
162
|
-
variant={tempIsRangeMode ? "default" : "outline"}
|
|
163
|
-
size="sm"
|
|
164
|
-
onClick={() => handleModeChange(true)}
|
|
165
|
-
className="flex-1 h-7 text-xs"
|
|
166
|
-
>
|
|
167
|
-
Date Range
|
|
168
|
-
</Button>
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
{tempIsRangeMode ? (
|
|
172
|
-
<div className="flex">
|
|
173
|
-
{/* Start Date */}
|
|
174
|
-
<div className="p-4 space-y-2">
|
|
175
|
-
<div className="text-xs text-muted-foreground">Start Date</div>
|
|
176
|
-
<Select
|
|
177
|
-
value={tempRangeStartYear.toString()}
|
|
178
|
-
onValueChange={(value) => {
|
|
179
|
-
if (value) setTempRangeStartYear(parseInt(value));
|
|
180
|
-
}}
|
|
181
|
-
>
|
|
182
|
-
<SelectTrigger className="h-8 text-xs">
|
|
183
|
-
<SelectValue />
|
|
184
|
-
</SelectTrigger>
|
|
185
|
-
<SelectContent>
|
|
186
|
-
{years.map((year) => {
|
|
187
|
-
const isDisabled = tempDateRange?.to
|
|
188
|
-
? year > tempDateRange.to.getFullYear()
|
|
189
|
-
: false;
|
|
190
|
-
return (
|
|
191
|
-
<SelectItem key={year} value={year.toString()} disabled={isDisabled}>
|
|
192
|
-
{year}
|
|
193
|
-
</SelectItem>
|
|
194
|
-
);
|
|
195
|
-
})}
|
|
196
|
-
</SelectContent>
|
|
197
|
-
</Select>
|
|
198
|
-
<div className="grid grid-cols-3 gap-2">
|
|
199
|
-
{MONTHS.map((month, idx) => {
|
|
200
|
-
const isDisabled = tempDateRange?.to
|
|
201
|
-
? tempRangeStartYear > tempDateRange.to.getFullYear() ||
|
|
202
|
-
(tempRangeStartYear === tempDateRange.to.getFullYear() &&
|
|
203
|
-
idx > tempDateRange.to.getMonth())
|
|
204
|
-
: false;
|
|
205
|
-
return (
|
|
206
|
-
<Button
|
|
207
|
-
key={month}
|
|
208
|
-
variant={
|
|
209
|
-
tempDateRange?.from?.getMonth() === idx &&
|
|
210
|
-
tempDateRange?.from?.getFullYear() === tempRangeStartYear
|
|
211
|
-
? "default"
|
|
212
|
-
: "outline"
|
|
213
|
-
}
|
|
214
|
-
size="sm"
|
|
215
|
-
onClick={() => {
|
|
216
|
-
const newDate = new Date(tempRangeStartYear, idx, 1);
|
|
217
|
-
setTempDateRange({
|
|
218
|
-
from: newDate,
|
|
219
|
-
to: tempDateRange?.to,
|
|
220
|
-
});
|
|
221
|
-
}}
|
|
222
|
-
disabled={isDisabled}
|
|
223
|
-
className="h-8 text-xs"
|
|
224
|
-
>
|
|
225
|
-
{month}
|
|
226
|
-
</Button>
|
|
227
|
-
);
|
|
228
|
-
})}
|
|
229
|
-
</div>
|
|
230
|
-
</div>
|
|
231
|
-
{/* Divider */}
|
|
232
|
-
<div className="border-r" />
|
|
233
|
-
{/* End Date */}
|
|
234
|
-
<div className="p-4 space-y-2">
|
|
235
|
-
<div className="text-xs text-muted-foreground">End Date</div>
|
|
236
|
-
<Select
|
|
237
|
-
value={tempRangeEndYear.toString()}
|
|
238
|
-
onValueChange={(value) => {
|
|
239
|
-
if (value) setTempRangeEndYear(parseInt(value));
|
|
240
|
-
}}
|
|
241
|
-
>
|
|
242
|
-
<SelectTrigger className="h-8 text-xs">
|
|
243
|
-
<SelectValue />
|
|
244
|
-
</SelectTrigger>
|
|
245
|
-
<SelectContent>
|
|
246
|
-
{years.map((year) => {
|
|
247
|
-
const isDisabled = tempDateRange?.from
|
|
248
|
-
? year < tempDateRange.from.getFullYear()
|
|
249
|
-
: false;
|
|
250
|
-
return (
|
|
251
|
-
<SelectItem key={year} value={year.toString()} disabled={isDisabled}>
|
|
252
|
-
{year}
|
|
253
|
-
</SelectItem>
|
|
254
|
-
);
|
|
255
|
-
})}
|
|
256
|
-
</SelectContent>
|
|
257
|
-
</Select>
|
|
258
|
-
<div className="grid grid-cols-3 gap-2">
|
|
259
|
-
{MONTHS.map((month, idx) => {
|
|
260
|
-
const isDisabled = tempDateRange?.from
|
|
261
|
-
? tempRangeEndYear < tempDateRange.from.getFullYear() ||
|
|
262
|
-
(tempRangeEndYear === tempDateRange.from.getFullYear() &&
|
|
263
|
-
idx < tempDateRange.from.getMonth())
|
|
264
|
-
: false;
|
|
265
|
-
return (
|
|
266
|
-
<Button
|
|
267
|
-
key={month}
|
|
268
|
-
variant={
|
|
269
|
-
tempDateRange?.to?.getMonth() === idx &&
|
|
270
|
-
tempDateRange?.to?.getFullYear() === tempRangeEndYear
|
|
271
|
-
? "default"
|
|
272
|
-
: "outline"
|
|
273
|
-
}
|
|
274
|
-
size="sm"
|
|
275
|
-
onClick={() => {
|
|
276
|
-
const newDate = new Date(tempRangeEndYear, idx, 1);
|
|
277
|
-
setTempDateRange({
|
|
278
|
-
from: tempDateRange?.from,
|
|
279
|
-
to: newDate,
|
|
280
|
-
});
|
|
281
|
-
}}
|
|
282
|
-
disabled={isDisabled}
|
|
283
|
-
className="h-8 text-xs"
|
|
284
|
-
>
|
|
285
|
-
{month}
|
|
286
|
-
</Button>
|
|
287
|
-
);
|
|
288
|
-
})}
|
|
289
|
-
</div>
|
|
290
|
-
</div>
|
|
291
|
-
</div>
|
|
292
|
-
) : (
|
|
293
|
-
<div className="p-4 space-y-2">
|
|
294
|
-
<Select
|
|
295
|
-
value={tempYear.toString()}
|
|
296
|
-
onValueChange={(value) => {
|
|
297
|
-
if (value) setTempYear(parseInt(value));
|
|
298
|
-
}}
|
|
299
|
-
>
|
|
300
|
-
<SelectTrigger className="h-8 text-xs">
|
|
301
|
-
<SelectValue />
|
|
302
|
-
</SelectTrigger>
|
|
303
|
-
<SelectContent>
|
|
304
|
-
{years.map((year) => (
|
|
305
|
-
<SelectItem key={year} value={year.toString()}>
|
|
306
|
-
{year}
|
|
307
|
-
</SelectItem>
|
|
308
|
-
))}
|
|
309
|
-
</SelectContent>
|
|
310
|
-
</Select>
|
|
311
|
-
<div className="grid grid-cols-3 gap-2">
|
|
312
|
-
{MONTHS.map((month, idx) => (
|
|
313
|
-
<Button
|
|
314
|
-
key={month}
|
|
315
|
-
variant={
|
|
316
|
-
tempDate?.getMonth() === idx && tempDate?.getFullYear() === tempYear
|
|
317
|
-
? "default"
|
|
318
|
-
: "outline"
|
|
319
|
-
}
|
|
320
|
-
size="sm"
|
|
321
|
-
onClick={() => {
|
|
322
|
-
const newDate = new Date(tempYear, idx, 1);
|
|
323
|
-
setTempDate(newDate);
|
|
324
|
-
}}
|
|
325
|
-
className="h-8 text-xs"
|
|
326
|
-
>
|
|
327
|
-
{month}
|
|
328
|
-
</Button>
|
|
329
|
-
))}
|
|
330
|
-
</div>
|
|
331
|
-
</div>
|
|
332
|
-
)}
|
|
333
|
-
<div className="p-3 border-t flex justify-end gap-2">
|
|
334
|
-
<Button variant="outline" size="sm" onClick={handleCancel} className="h-8 text-xs">
|
|
335
|
-
Cancel
|
|
336
|
-
</Button>
|
|
337
|
-
<Button
|
|
338
|
-
variant="default"
|
|
339
|
-
size="sm"
|
|
340
|
-
onClick={handleSave}
|
|
341
|
-
disabled={!isSaveEnabled()}
|
|
342
|
-
className="h-8 text-xs"
|
|
343
|
-
>
|
|
344
|
-
Save
|
|
345
|
-
</Button>
|
|
346
|
-
</div>
|
|
347
|
-
</PopoverContent>
|
|
348
|
-
</Popover>
|
|
349
|
-
</div>
|
|
350
|
-
);
|
|
351
|
-
}
|