@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.
Files changed (146) hide show
  1. package/dist/components/index.d.ts +65 -0
  2. package/dist/components/ui/accordion.d.ts +7 -0
  3. package/dist/components/ui/alert-dialog.d.ts +20 -0
  4. package/dist/components/ui/alert.d.ts +8 -0
  5. package/dist/components/ui/aspect-ratio.d.ts +3 -0
  6. package/dist/components/ui/async-select.d.ts +36 -0
  7. package/dist/components/ui/avatar.d.ts +6 -0
  8. package/dist/components/ui/badge.d.ts +9 -0
  9. package/dist/components/ui/breadcrumb.d.ts +19 -0
  10. package/dist/components/ui/button.d.ts +13 -0
  11. package/dist/components/ui/calendar.d.ts +5 -0
  12. package/dist/components/ui/card.d.ts +9 -0
  13. package/dist/components/ui/carousel.d.ts +18 -0
  14. package/dist/components/ui/checkbox.d.ts +8 -0
  15. package/dist/components/ui/collapsible.d.ts +5 -0
  16. package/dist/components/ui/combobox.d.ts +20 -0
  17. package/dist/components/ui/command.d.ts +80 -0
  18. package/dist/components/ui/common-modal.d.ts +28 -0
  19. package/dist/components/ui/context-menu.d.ts +27 -0
  20. package/dist/components/ui/date-input.d.ts +7 -0
  21. package/dist/components/ui/date-picker.d.ts +26 -0
  22. package/dist/components/ui/date-selector-multiple.d.ts +38 -0
  23. package/dist/components/ui/dialog.d.ts +19 -0
  24. package/dist/components/ui/drawer.d.ts +22 -0
  25. package/dist/components/ui/dropdown-menu.d.ts +27 -0
  26. package/dist/components/ui/form.d.ts +23 -0
  27. package/dist/components/ui/hover-card.d.ts +6 -0
  28. package/dist/components/ui/image-uploader.d.ts +14 -0
  29. package/dist/components/ui/input-otp.d.ts +34 -0
  30. package/dist/components/ui/input.d.ts +7 -0
  31. package/dist/components/ui/label.d.ts +5 -0
  32. package/dist/components/ui/menubar.d.ts +28 -0
  33. package/dist/components/ui/month-picker-multiple.d.ts +41 -0
  34. package/dist/components/ui/multi-image-uploader.d.ts +15 -0
  35. package/dist/components/ui/multi-select.d.ts +229 -0
  36. package/dist/components/ui/navigation-menu.d.ts +12 -0
  37. package/dist/components/ui/pagination.d.ts +10 -0
  38. package/dist/components/ui/popover.d.ts +7 -0
  39. package/dist/components/ui/progress.d.ts +4 -0
  40. package/dist/components/ui/radio-group.d.ts +5 -0
  41. package/dist/components/ui/resizable.d.ts +23 -0
  42. package/dist/components/ui/scroll-area.d.ts +5 -0
  43. package/dist/components/ui/select.d.ts +20 -0
  44. package/dist/components/ui/separator.d.ts +4 -0
  45. package/dist/components/ui/sheet.d.ts +25 -0
  46. package/dist/components/ui/sidebar.d.ts +69 -0
  47. package/dist/components/ui/skeleton.d.ts +2 -0
  48. package/dist/components/ui/slider.d.ts +8 -0
  49. package/dist/components/ui/sonner.d.ts +4 -0
  50. package/dist/components/ui/switch.d.ts +8 -0
  51. package/dist/components/ui/table.d.ts +24 -0
  52. package/dist/components/ui/tabs.d.ts +7 -0
  53. package/dist/components/ui/textarea.d.ts +7 -0
  54. package/dist/components/ui/toast.d.ts +15 -0
  55. package/dist/components/ui/toaster.d.ts +1 -0
  56. package/dist/components/ui/toggle-group.d.ts +12 -0
  57. package/dist/components/ui/toggle.d.ts +12 -0
  58. package/dist/components/ui/tooltip.d.ts +7 -0
  59. package/dist/hooks/index.d.ts +1 -0
  60. package/dist/hooks/use-toast.d.ts +44 -0
  61. package/dist/index.d.ts +3 -0
  62. package/dist/lib/caster.d.ts +3 -0
  63. package/dist/lib/helpers.d.ts +72 -0
  64. package/dist/lib/index.d.ts +6 -0
  65. package/{src/lib/lazy-upload.ts → dist/lib/lazy-upload.d.ts} +1 -12
  66. package/dist/lib/use-mobile.d.ts +1 -0
  67. package/dist/lib/utils.d.ts +2 -0
  68. package/dist/react-components.es.js +28375 -0
  69. package/package.json +105 -76
  70. package/COMPONENTS_LIST.md +0 -106
  71. package/COMPONENTS_STATUS.md +0 -114
  72. package/HELPERS_GUIDE.md +0 -489
  73. package/MIGRATION_PLAN.md +0 -404
  74. package/SETUP_GUIDE.md +0 -125
  75. package/components.json +0 -21
  76. package/postcss.config.js +0 -6
  77. package/src/components/index.ts +0 -315
  78. package/src/components/ui/accordion.tsx +0 -54
  79. package/src/components/ui/alert-dialog.tsx +0 -115
  80. package/src/components/ui/alert.tsx +0 -49
  81. package/src/components/ui/aspect-ratio.tsx +0 -5
  82. package/src/components/ui/async-select.tsx +0 -186
  83. package/src/components/ui/avatar.tsx +0 -45
  84. package/src/components/ui/badge.tsx +0 -38
  85. package/src/components/ui/breadcrumb.tsx +0 -102
  86. package/src/components/ui/button.tsx +0 -54
  87. package/src/components/ui/calendar.tsx +0 -193
  88. package/src/components/ui/card.tsx +0 -65
  89. package/src/components/ui/carousel.tsx +0 -243
  90. package/src/components/ui/checkbox.tsx +0 -67
  91. package/src/components/ui/collapsible.tsx +0 -9
  92. package/src/components/ui/combobox.tsx +0 -135
  93. package/src/components/ui/command.tsx +0 -143
  94. package/src/components/ui/common-modal.tsx +0 -95
  95. package/src/components/ui/context-menu.tsx +0 -189
  96. package/src/components/ui/date-picker.tsx +0 -112
  97. package/src/components/ui/date-selector-multiple.tsx +0 -197
  98. package/src/components/ui/dialog.tsx +0 -104
  99. package/src/components/ui/drawer.tsx +0 -100
  100. package/src/components/ui/dropdown-menu.tsx +0 -189
  101. package/src/components/ui/form.tsx +0 -171
  102. package/src/components/ui/hover-card.tsx +0 -27
  103. package/src/components/ui/image-uploader.tsx +0 -251
  104. package/src/components/ui/input-otp.tsx +0 -69
  105. package/src/components/ui/input.tsx +0 -38
  106. package/src/components/ui/label.tsx +0 -19
  107. package/src/components/ui/menubar.tsx +0 -231
  108. package/src/components/ui/month-picker-multiple.tsx +0 -351
  109. package/src/components/ui/multi-image-uploader.tsx +0 -283
  110. package/src/components/ui/multi-select.tsx +0 -1143
  111. package/src/components/ui/navigation-menu.tsx +0 -120
  112. package/src/components/ui/pagination.tsx +0 -72
  113. package/src/components/ui/popover.tsx +0 -42
  114. package/src/components/ui/progress.tsx +0 -25
  115. package/src/components/ui/radio-group.tsx +0 -38
  116. package/src/components/ui/resizable.tsx +0 -42
  117. package/src/components/ui/scroll-area.tsx +0 -46
  118. package/src/components/ui/select.tsx +0 -235
  119. package/src/components/ui/separator.tsx +0 -24
  120. package/src/components/ui/sheet.tsx +0 -119
  121. package/src/components/ui/sidebar.tsx +0 -683
  122. package/src/components/ui/skeleton.tsx +0 -7
  123. package/src/components/ui/slider.tsx +0 -57
  124. package/src/components/ui/sonner.tsx +0 -39
  125. package/src/components/ui/switch.tsx +0 -63
  126. package/src/components/ui/table.tsx +0 -94
  127. package/src/components/ui/tabs.tsx +0 -53
  128. package/src/components/ui/textarea.tsx +0 -34
  129. package/src/components/ui/toast.tsx +0 -122
  130. package/src/components/ui/toaster.tsx +0 -29
  131. package/src/components/ui/toggle-group.tsx +0 -55
  132. package/src/components/ui/toggle.tsx +0 -41
  133. package/src/components/ui/tooltip.tsx +0 -28
  134. package/src/hooks/index.ts +0 -2
  135. package/src/hooks/use-toast.ts +0 -189
  136. package/src/icons.d.ts +0 -1
  137. package/src/index.ts +0 -4
  138. package/src/lib/caster.ts +0 -66
  139. package/src/lib/helpers.ts +0 -394
  140. package/src/lib/index.ts +0 -31
  141. package/src/lib/use-mobile.ts +0 -19
  142. package/src/lib/utils.ts +0 -6
  143. package/src/styles/globals.css +0 -658
  144. package/tailwind.config.ts +0 -8
  145. package/tsconfig.json +0 -31
  146. package/tsconfig.node.json +0 -11
@@ -1,243 +0,0 @@
1
- "use client";
2
-
3
- import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react";
4
- import * as React from "react";
5
- import ArrowLeftIcon from "~icons/lucide/arrow-left";
6
- import ArrowRightIcon from "~icons/lucide/arrow-right";
7
-
8
- import { cn } from "../../lib/utils";
9
- import { Button } from "./button";
10
-
11
- type CarouselApi = UseEmblaCarouselType[1];
12
- type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
13
- type CarouselOptions = UseCarouselParameters[0];
14
- type CarouselPlugin = UseCarouselParameters[1];
15
-
16
- type CarouselProps = {
17
- opts?: CarouselOptions;
18
- plugins?: CarouselPlugin;
19
- orientation?: "horizontal" | "vertical";
20
- setApi?: (api: CarouselApi) => void;
21
- };
22
-
23
- type CarouselContextProps = {
24
- carouselRef: ReturnType<typeof useEmblaCarousel>[0];
25
- api: ReturnType<typeof useEmblaCarousel>[1];
26
- scrollPrev: () => void;
27
- scrollNext: () => void;
28
- canScrollPrev: boolean;
29
- canScrollNext: boolean;
30
- } & CarouselProps;
31
-
32
- const CarouselContext = React.createContext<CarouselContextProps | null>(null);
33
-
34
- function useCarousel() {
35
- const context = React.useContext(CarouselContext);
36
-
37
- if (!context) {
38
- throw new Error("useCarousel must be used within a <Carousel />");
39
- }
40
-
41
- return context;
42
- }
43
-
44
- const Carousel = React.forwardRef<
45
- HTMLDivElement,
46
- React.HTMLAttributes<HTMLDivElement> & CarouselProps
47
- >(({ orientation = "horizontal", opts, setApi, plugins, className, children, ...props }, ref) => {
48
- const [carouselRef, api] = useEmblaCarousel(
49
- {
50
- ...opts,
51
- axis: orientation === "horizontal" ? "x" : "y",
52
- },
53
- plugins,
54
- );
55
- const [canScrollPrev, setCanScrollPrev] = React.useState(false);
56
- const [canScrollNext, setCanScrollNext] = React.useState(false);
57
-
58
- const onSelect = React.useCallback((api: CarouselApi) => {
59
- if (!api) {
60
- return;
61
- }
62
-
63
- setCanScrollPrev(api.canScrollPrev());
64
- setCanScrollNext(api.canScrollNext());
65
- }, []);
66
-
67
- const scrollPrev = React.useCallback(() => {
68
- api?.scrollPrev();
69
- }, [api]);
70
-
71
- const scrollNext = React.useCallback(() => {
72
- api?.scrollNext();
73
- }, [api]);
74
-
75
- const handleKeyDown = React.useCallback(
76
- (event: React.KeyboardEvent<HTMLDivElement>) => {
77
- if (event.key === "ArrowLeft") {
78
- event.preventDefault();
79
- scrollPrev();
80
- } else if (event.key === "ArrowRight") {
81
- event.preventDefault();
82
- scrollNext();
83
- }
84
- },
85
- [scrollPrev, scrollNext],
86
- );
87
-
88
- React.useEffect(() => {
89
- if (!api || !setApi) {
90
- return;
91
- }
92
-
93
- setApi(api);
94
- }, [api, setApi]);
95
-
96
- React.useEffect(() => {
97
- if (!api) {
98
- return;
99
- }
100
-
101
- onSelect(api);
102
- api.on("reInit", onSelect);
103
- api.on("select", onSelect);
104
-
105
- return () => {
106
- api?.off("select", onSelect);
107
- };
108
- }, [api, onSelect]);
109
-
110
- return (
111
- <CarouselContext.Provider
112
- value={{
113
- carouselRef,
114
- api: api,
115
- opts,
116
- orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
117
- scrollPrev,
118
- scrollNext,
119
- canScrollPrev,
120
- canScrollNext,
121
- }}
122
- >
123
- <div
124
- ref={ref}
125
- onKeyDownCapture={handleKeyDown}
126
- className={cn("relative", className)}
127
- role="region"
128
- aria-roledescription="carousel"
129
- {...props}
130
- >
131
- {children}
132
- </div>
133
- </CarouselContext.Provider>
134
- );
135
- });
136
- Carousel.displayName = "Carousel";
137
-
138
- const CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
139
- ({ className, ...props }, ref) => {
140
- const { carouselRef, orientation } = useCarousel();
141
-
142
- return (
143
- <div ref={carouselRef} className="overflow-hidden">
144
- <div
145
- ref={ref}
146
- className={cn(
147
- "flex",
148
- orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
149
- className,
150
- )}
151
- {...props}
152
- />
153
- </div>
154
- );
155
- },
156
- );
157
- CarouselContent.displayName = "CarouselContent";
158
-
159
- const CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
160
- ({ className, ...props }, ref) => {
161
- const { orientation } = useCarousel();
162
-
163
- return (
164
- <div
165
- ref={ref}
166
- role="group"
167
- aria-roledescription="slide"
168
- className={cn(
169
- "min-w-0 shrink-0 grow-0 basis-full",
170
- orientation === "horizontal" ? "pl-4" : "pt-4",
171
- className,
172
- )}
173
- {...props}
174
- />
175
- );
176
- },
177
- );
178
- CarouselItem.displayName = "CarouselItem";
179
-
180
- const CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(
181
- ({ className, variant = "outline", size = "icon", ...props }, ref) => {
182
- const { orientation, scrollPrev, canScrollPrev } = useCarousel();
183
-
184
- return (
185
- <Button
186
- ref={ref}
187
- variant={variant}
188
- size={size}
189
- className={cn(
190
- "absolute h-8 w-8 rounded-full",
191
- orientation === "horizontal"
192
- ? "-left-12 top-1/2 -translate-y-1/2"
193
- : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
194
- className,
195
- )}
196
- disabled={!canScrollPrev}
197
- onClick={scrollPrev}
198
- {...props}
199
- >
200
- <ArrowLeftIcon className="h-4 w-4" />
201
- <span className="sr-only">Previous slide</span>
202
- </Button>
203
- );
204
- },
205
- );
206
- CarouselPrevious.displayName = "CarouselPrevious";
207
-
208
- const CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(
209
- ({ className, variant = "outline", size = "icon", ...props }, ref) => {
210
- const { orientation, scrollNext, canScrollNext } = useCarousel();
211
-
212
- return (
213
- <Button
214
- ref={ref}
215
- variant={variant}
216
- size={size}
217
- className={cn(
218
- "absolute h-8 w-8 rounded-full",
219
- orientation === "horizontal"
220
- ? "-right-12 top-1/2 -translate-y-1/2"
221
- : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
222
- className,
223
- )}
224
- disabled={!canScrollNext}
225
- onClick={scrollNext}
226
- {...props}
227
- >
228
- <ArrowRightIcon className="h-4 w-4" />
229
- <span className="sr-only">Next slide</span>
230
- </Button>
231
- );
232
- },
233
- );
234
- CarouselNext.displayName = "CarouselNext";
235
-
236
- export {
237
- type CarouselApi,
238
- Carousel,
239
- CarouselContent,
240
- CarouselItem,
241
- CarouselPrevious,
242
- CarouselNext,
243
- };
@@ -1,67 +0,0 @@
1
- "use client";
2
-
3
- import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
4
- import * as React from "react";
5
- import CheckIcon from "~icons/lucide/check";
6
- import type { Override } from "../../lib/helpers";
7
- import { cn } from "../../lib/utils";
8
-
9
- type CheckboxProps = Override<
10
- React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>,
11
- {
12
- name?: string;
13
- onValueChange?: (checked: boolean) => void;
14
- onBlur?: React.FocusEventHandler<HTMLInputElement>;
15
- }
16
- >;
17
-
18
- const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
19
- ({ className, name, checked, defaultChecked, onValueChange, onBlur, ...props }, ref) => {
20
- const inputRef = React.useRef<HTMLInputElement>(null);
21
-
22
- // biome-ignore lint/style/noNonNullAssertion: useImperativeHandle은 ref가 할당된 후 실행되므로 안전함
23
- React.useImperativeHandle(ref, () => inputRef.current!);
24
-
25
- const handleCheckedChange = (newChecked: boolean | "indeterminate") => {
26
- const boolValue = newChecked === "indeterminate" ? false : newChecked;
27
- onValueChange?.(boolValue);
28
- };
29
-
30
- return (
31
- <>
32
- <input
33
- type="checkbox"
34
- ref={inputRef}
35
- name={name}
36
- defaultChecked={defaultChecked === true}
37
- onBlur={onBlur}
38
- className="sr-only"
39
- tabIndex={-1}
40
- aria-hidden="true"
41
- />
42
- <CheckboxPrimitive.Root
43
- data-slot="checkbox"
44
- checked={checked}
45
- defaultChecked={defaultChecked}
46
- onCheckedChange={handleCheckedChange}
47
- className={cn(
48
- "peer border border-muted-foreground/30 bg-input-background dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
49
- className,
50
- )}
51
- {...props}
52
- >
53
- <CheckboxPrimitive.Indicator
54
- data-slot="checkbox-indicator"
55
- className="flex items-center justify-center text-current transition-none"
56
- >
57
- <CheckIcon className="size-3.5" />
58
- </CheckboxPrimitive.Indicator>
59
- </CheckboxPrimitive.Root>
60
- </>
61
- );
62
- },
63
- );
64
-
65
- Checkbox.displayName = "Checkbox";
66
-
67
- export { Checkbox };
@@ -1,9 +0,0 @@
1
- import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
2
-
3
- const Collapsible = CollapsiblePrimitive.Root;
4
-
5
- const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
6
-
7
- const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
8
-
9
- export { Collapsible, CollapsibleTrigger, CollapsibleContent };
@@ -1,135 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import CheckIcon from "~icons/lucide/check";
5
- import ChevronsUpDownIcon from "~icons/lucide/chevrons-up-down";
6
- import XCircleIcon from "~icons/lucide/x-circle";
7
-
8
- import { cn } from "../../lib/utils";
9
- import { Button } from "./button";
10
- import {
11
- Command,
12
- CommandEmpty,
13
- CommandGroup,
14
- CommandInput,
15
- CommandItem,
16
- CommandList,
17
- } from "./command";
18
- import { Popover, PopoverContent, PopoverTrigger } from "./popover";
19
-
20
- export interface ComboboxOption {
21
- value: string;
22
- label: string;
23
- }
24
-
25
- interface ComboboxProps {
26
- options: ComboboxOption[];
27
- name?: string;
28
- value?: string;
29
- onValueChange?: (value: string | undefined) => void;
30
- onBlur?: React.FocusEventHandler<HTMLInputElement>;
31
- placeholder?: string;
32
- searchPlaceholder?: string;
33
- emptyText?: string;
34
- disabled?: boolean;
35
- className?: string;
36
- clearable?: boolean;
37
- }
38
-
39
- const Combobox = React.forwardRef<HTMLInputElement, ComboboxProps>(
40
- (
41
- {
42
- options,
43
- name,
44
- value,
45
- onValueChange,
46
- onBlur,
47
- placeholder = "Select option...",
48
- searchPlaceholder = "Search...",
49
- emptyText = "No option found.",
50
- disabled = false,
51
- className,
52
- clearable = false,
53
- },
54
- ref,
55
- ) => {
56
- const [open, setOpen] = React.useState(false);
57
- const inputRef = React.useRef<HTMLInputElement>(null);
58
-
59
- // biome-ignore lint/style/noNonNullAssertion: useImperativeHandle은 ref가 할당된 후 실행되므로 안전함
60
- React.useImperativeHandle(ref, () => inputRef.current!);
61
-
62
- const handleSelect = (currentValue: string) => {
63
- const newValue = currentValue === value ? "" : currentValue;
64
- onValueChange?.(newValue || undefined);
65
- setOpen(false);
66
- };
67
-
68
- const handleClear = (e: React.MouseEvent) => {
69
- e.preventDefault();
70
- e.stopPropagation();
71
- onValueChange?.(undefined);
72
- setOpen(false);
73
- };
74
-
75
- const hasValue = Boolean(value);
76
-
77
- return (
78
- <>
79
- <input type="hidden" ref={inputRef} name={name} value={value || ""} onBlur={onBlur} />
80
- <Popover open={open} onOpenChange={setOpen}>
81
- <PopoverTrigger asChild>
82
- <Button
83
- variant="outline"
84
- role="combobox"
85
- aria-expanded={open}
86
- disabled={disabled}
87
- className={cn("w-full justify-between", className)}
88
- >
89
- <span className="flex-1 truncate text-left">
90
- {value ? options.find((option) => option.value === value)?.label : placeholder}
91
- </span>
92
- <div className="flex items-center gap-1 shrink-0 pl-2">
93
- {clearable && hasValue && (
94
- <span
95
- className="flex items-center justify-center"
96
- onMouseDown={(e) => e.stopPropagation()}
97
- onClick={handleClear}
98
- >
99
- <XCircleIcon className="h-4 w-4 cursor-pointer opacity-50 hover:opacity-100 transition-opacity" />
100
- </span>
101
- )}
102
- <ChevronsUpDownIcon className="h-4 w-4 opacity-50" />
103
- </div>
104
- </Button>
105
- </PopoverTrigger>
106
- <PopoverContent className="w-full p-0">
107
- <Command>
108
- <CommandInput placeholder={searchPlaceholder} className="h-9" />
109
- <CommandList>
110
- <CommandEmpty>{emptyText}</CommandEmpty>
111
- <CommandGroup>
112
- {options.map((option) => (
113
- <CommandItem key={option.value} value={option.value} onSelect={handleSelect}>
114
- {option.label}
115
- <CheckIcon
116
- className={cn(
117
- "ml-auto",
118
- value === option.value ? "opacity-100" : "opacity-0",
119
- )}
120
- />
121
- </CommandItem>
122
- ))}
123
- </CommandGroup>
124
- </CommandList>
125
- </Command>
126
- </PopoverContent>
127
- </Popover>
128
- </>
129
- );
130
- },
131
- );
132
-
133
- Combobox.displayName = "Combobox";
134
-
135
- export { Combobox };
@@ -1,143 +0,0 @@
1
- "use client";
2
-
3
- import type { DialogProps } from "@radix-ui/react-dialog";
4
- import { Command as CommandPrimitive } from "cmdk";
5
- import * as React from "react";
6
- import SearchIcon from "~icons/lucide/search";
7
-
8
- import { cn } from "../../lib/utils";
9
- import { Dialog, DialogContent } from "./dialog";
10
-
11
- const Command = React.forwardRef<
12
- React.ElementRef<typeof CommandPrimitive>,
13
- React.ComponentPropsWithoutRef<typeof CommandPrimitive>
14
- >(({ className, ...props }, ref) => (
15
- <CommandPrimitive
16
- ref={ref}
17
- className={cn(
18
- "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
19
- className,
20
- )}
21
- {...props}
22
- />
23
- ));
24
- Command.displayName = CommandPrimitive.displayName;
25
-
26
- const CommandDialog = ({ children, ...props }: DialogProps) => {
27
- return (
28
- <Dialog {...props}>
29
- <DialogContent className="overflow-hidden p-0 shadow-lg">
30
- <Command className="**:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 **:[[cmdk-group]]:px-2 **:[[cmdk-input-wrapper]_svg]:size-5 **:[[cmdk-input]]:h-12 **:[[cmdk-item]]:px-2 **:[[cmdk-item]]:py-3 **:[[cmdk-item]_svg]:size-5">
31
- {children}
32
- </Command>
33
- </DialogContent>
34
- </Dialog>
35
- );
36
- };
37
-
38
- const CommandInput = React.forwardRef<
39
- React.ElementRef<typeof CommandPrimitive.Input>,
40
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
41
- >(({ className, ...props }, ref) => (
42
- <div className="flex items-center border-b px-3" cmdk-input-wrapper="">
43
- <SearchIcon className="mr-2 h-4 w-4 shrink-0 opacity-50" />
44
- <CommandPrimitive.Input
45
- ref={ref}
46
- className={cn(
47
- "flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
48
- className,
49
- )}
50
- {...props}
51
- />
52
- </div>
53
- ));
54
-
55
- CommandInput.displayName = CommandPrimitive.Input.displayName;
56
-
57
- const CommandList = React.forwardRef<
58
- React.ElementRef<typeof CommandPrimitive.List>,
59
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
60
- >(({ className, ...props }, ref) => (
61
- <CommandPrimitive.List
62
- ref={ref}
63
- className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
64
- {...props}
65
- />
66
- ));
67
-
68
- CommandList.displayName = CommandPrimitive.List.displayName;
69
-
70
- const CommandEmpty = React.forwardRef<
71
- React.ElementRef<typeof CommandPrimitive.Empty>,
72
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
73
- >((props, ref) => (
74
- <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />
75
- ));
76
-
77
- CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
78
-
79
- const CommandGroup = React.forwardRef<
80
- React.ElementRef<typeof CommandPrimitive.Group>,
81
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
82
- >(({ className, ...props }, ref) => (
83
- <CommandPrimitive.Group
84
- ref={ref}
85
- className={cn(
86
- "overflow-hidden p-1 text-foreground **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground",
87
- className,
88
- )}
89
- {...props}
90
- />
91
- ));
92
-
93
- CommandGroup.displayName = CommandPrimitive.Group.displayName;
94
-
95
- const CommandSeparator = React.forwardRef<
96
- React.ElementRef<typeof CommandPrimitive.Separator>,
97
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
98
- >(({ className, ...props }, ref) => (
99
- <CommandPrimitive.Separator
100
- ref={ref}
101
- className={cn("-mx-1 h-px bg-border", className)}
102
- {...props}
103
- />
104
- ));
105
- CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
106
-
107
- const CommandItem = React.forwardRef<
108
- React.ElementRef<typeof CommandPrimitive.Item>,
109
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
110
- >(({ className, ...props }, ref) => (
111
- <CommandPrimitive.Item
112
- ref={ref}
113
- className={cn(
114
- "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 **:[svg]:pointer-events-none **:[svg]:size-4 **:[svg]:shrink-0",
115
- className,
116
- )}
117
- {...props}
118
- />
119
- ));
120
-
121
- CommandItem.displayName = CommandPrimitive.Item.displayName;
122
-
123
- const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
124
- return (
125
- <span
126
- className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
127
- {...props}
128
- />
129
- );
130
- };
131
- CommandShortcut.displayName = "CommandShortcut";
132
-
133
- export {
134
- Command,
135
- CommandDialog,
136
- CommandInput,
137
- CommandList,
138
- CommandEmpty,
139
- CommandGroup,
140
- CommandItem,
141
- CommandShortcut,
142
- CommandSeparator,
143
- };
@@ -1,95 +0,0 @@
1
- "use client";
2
-
3
- import { atom, useAtom } from "jotai";
4
- import type * as React from "react";
5
- import { cn } from "../../lib/utils";
6
- import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "./dialog";
7
-
8
- type ExtendedModalProps = {
9
- title?: string;
10
- description?: string;
11
- className?: string;
12
- onCompleted?: (data?: unknown) => void;
13
- };
14
-
15
- export const commonModalAtom = atom<
16
- {
17
- open: boolean;
18
- reactNode: React.ReactNode | null;
19
- } & ExtendedModalProps
20
- >({
21
- open: false,
22
- reactNode: null,
23
- });
24
-
25
- type CommonModalProps = {
26
- className?: string;
27
- };
28
-
29
- export function CommonModal({ className }: CommonModalProps) {
30
- const [atomValue, setAtomValue] = useAtom(commonModalAtom);
31
- const { open, reactNode, title, description, className: modalClassName } = atomValue;
32
-
33
- const closeAndClear = () => {
34
- setAtomValue({
35
- open: false,
36
- reactNode: null,
37
- });
38
- };
39
-
40
- return (
41
- <Dialog
42
- open={open}
43
- onOpenChange={(isOpen) => {
44
- if (!isOpen) {
45
- closeAndClear();
46
- }
47
- }}
48
- >
49
- <DialogContent className={cn("max-w-4xl", modalClassName, className)}>
50
- {(title || description) && (
51
- <DialogHeader>
52
- {title && <DialogTitle>{title}</DialogTitle>}
53
- {description && <DialogDescription>{description}</DialogDescription>}
54
- </DialogHeader>
55
- )}
56
- {reactNode}
57
- </DialogContent>
58
- </Dialog>
59
- );
60
- }
61
-
62
- export function useCommonModal() {
63
- const [atomValue, setAtomValue] = useAtom(commonModalAtom);
64
- const { open, reactNode, onCompleted } = atomValue;
65
-
66
- const openModal = (reactNode: React.ReactNode, props?: ExtendedModalProps) => {
67
- setAtomValue({
68
- open: true,
69
- reactNode,
70
- ...props,
71
- });
72
- };
73
-
74
- const closeModal = () => {
75
- setAtomValue({
76
- open: false,
77
- reactNode: null,
78
- });
79
- };
80
-
81
- const doneModal = (data?: unknown) => {
82
- closeModal();
83
- if (onCompleted) {
84
- onCompleted(data);
85
- }
86
- };
87
-
88
- return {
89
- open,
90
- reactNode,
91
- openModal,
92
- closeModal,
93
- doneModal,
94
- };
95
- }