@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,283 +0,0 @@
1
- import type React from "react";
2
- import { useCallback, useEffect, useRef, useState } from "react";
3
- import Loader2Icon from "~icons/lucide/loader2";
4
- import PlusIcon from "~icons/lucide/plus";
5
- import XIcon from "~icons/lucide/x";
6
- import { cn } from "../../lib/utils";
7
- import { Button } from "./button";
8
-
9
- export type MultiImageUploaderProps = {
10
- value?: string[];
11
- onValueChange?: (value: string[]) => void;
12
- onBlur?: React.FocusEventHandler<HTMLInputElement>;
13
- uploader?: (file: File) => Promise<string>;
14
- placeholder?: string;
15
- accept?: string;
16
- disabled?: boolean;
17
- className?: string;
18
- previewSize?: "sm" | "md" | "lg";
19
- maxImages?: number;
20
- mode?: "eager" | "lazy";
21
- };
22
-
23
- export function MultiImageUploader({
24
- value = [],
25
- onValueChange,
26
- onBlur,
27
- uploader,
28
- placeholder = "Click to upload",
29
- accept = "image/*",
30
- disabled = false,
31
- className,
32
- previewSize = "md",
33
- maxImages,
34
- mode = "eager",
35
- }: MultiImageUploaderProps) {
36
- const inputRef = useRef<HTMLInputElement>(null);
37
- const [isUploading, setIsUploading] = useState(false);
38
- const [dragOver, setDragOver] = useState(false);
39
- const [pendingFiles, setPendingFiles] = useState<File[]>([]);
40
- const [previewUrls, setPreviewUrls] = useState<string[]>([]);
41
-
42
- const sizeClasses = {
43
- sm: "h-20 w-20",
44
- md: "h-32 w-32",
45
- lg: "h-48 w-48",
46
- };
47
-
48
- const handleFilesChange = useCallback(
49
- async (files: FileList | null) => {
50
- if (!files || files.length === 0 || disabled) return;
51
-
52
- const fileArray = Array.from(files);
53
-
54
- if (mode === "lazy") {
55
- // Lazy mode: store files and create previews
56
- const newPendingFiles = [...pendingFiles, ...fileArray];
57
- const limitedFiles = maxImages ? newPendingFiles.slice(0, maxImages) : newPendingFiles;
58
-
59
- setPendingFiles(limitedFiles);
60
-
61
- // Create preview URLs
62
- const newPreviewUrls = fileArray.map((file) => URL.createObjectURL(file));
63
- const allPreviewUrls = [...previewUrls, ...newPreviewUrls];
64
- const limitedPreviewUrls = maxImages ? allPreviewUrls.slice(0, maxImages) : allPreviewUrls;
65
-
66
- setPreviewUrls(limitedPreviewUrls);
67
- // Don't call onValueChange in lazy mode - we'll update it after upload
68
- return;
69
- }
70
-
71
- // Eager mode: upload immediately
72
- if (!uploader) {
73
- console.error("uploader prop is required in eager mode");
74
- return;
75
- }
76
-
77
- setIsUploading(true);
78
- try {
79
- const uploadPromises = fileArray.map((file) => uploader(file));
80
- const uploadedUrls = await Promise.all(uploadPromises);
81
- const newValue = [...(value || []), ...uploadedUrls];
82
-
83
- // Limit to maxImages if specified
84
- const limitedValue = maxImages ? newValue.slice(0, maxImages) : newValue;
85
- onValueChange?.(limitedValue);
86
- } catch (error) {
87
- console.error("Upload failed:", error);
88
- } finally {
89
- setIsUploading(false);
90
- }
91
- },
92
- [uploader, onValueChange, disabled, value, maxImages, mode, pendingFiles, previewUrls],
93
- );
94
-
95
- const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
96
- handleFilesChange(e.target.files);
97
- e.target.value = "";
98
- };
99
-
100
- const handleDrop = useCallback(
101
- (e: React.DragEvent<HTMLDivElement>) => {
102
- e.preventDefault();
103
- e.stopPropagation();
104
- setDragOver(false);
105
- handleFilesChange(e.dataTransfer.files);
106
- },
107
- [handleFilesChange],
108
- );
109
-
110
- const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
111
- e.preventDefault();
112
- e.stopPropagation();
113
- if (!disabled) {
114
- setDragOver(true);
115
- }
116
- };
117
-
118
- const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
119
- e.preventDefault();
120
- e.stopPropagation();
121
- setDragOver(false);
122
- };
123
-
124
- const handleRemove = (index: number) => {
125
- if (mode === "lazy") {
126
- // In lazy mode, all displayed items are from previewUrls
127
- const newPendingFiles = [...pendingFiles];
128
- newPendingFiles.splice(index, 1);
129
- setPendingFiles(newPendingFiles);
130
-
131
- // Clean up preview URL
132
- const urlToRevoke = previewUrls[index];
133
- if (urlToRevoke) {
134
- URL.revokeObjectURL(urlToRevoke);
135
- }
136
- const newPreviewUrls = [...previewUrls];
137
- newPreviewUrls.splice(index, 1);
138
- setPreviewUrls(newPreviewUrls);
139
- } else {
140
- // Eager mode: remove from uploaded values
141
- const newValue = [...(value || [])];
142
- newValue.splice(index, 1);
143
- onValueChange?.(newValue);
144
- }
145
- };
146
-
147
- // Commit function for lazy mode
148
- const commitUpload = useCallback(async (): Promise<string[]> => {
149
- if (mode !== "lazy" || pendingFiles.length === 0 || !uploader) {
150
- return value || [];
151
- }
152
-
153
- setIsUploading(true);
154
- try {
155
- const uploadPromises = pendingFiles.map((file) => uploader(file));
156
- const uploadedUrls = await Promise.all(uploadPromises);
157
-
158
- // Clean up preview URLs
159
- for (const url of previewUrls) {
160
- URL.revokeObjectURL(url);
161
- }
162
- setPreviewUrls([]);
163
- setPendingFiles([]);
164
-
165
- const finalValue = [...(value || []), ...uploadedUrls];
166
- onValueChange?.(finalValue);
167
- return finalValue;
168
- } catch (error) {
169
- console.error("Upload failed:", error);
170
- return value || [];
171
- } finally {
172
- setIsUploading(false);
173
- }
174
- }, [mode, pendingFiles, uploader, value, previewUrls, onValueChange]);
175
-
176
- const handleClick = () => {
177
- if (!disabled && !isUploading) {
178
- inputRef.current?.click();
179
- }
180
- };
181
-
182
- // Listen for commit event in lazy mode
183
- useEffect(() => {
184
- if (mode !== "lazy") return;
185
-
186
- const handleCommit = async (event: Event) => {
187
- const customEvent = event as CustomEvent<{
188
- channel: string;
189
- done: (urls: string[]) => void;
190
- }>;
191
-
192
- if (customEvent.detail?.channel !== "image-uploader") return;
193
-
194
- const result = await commitUpload();
195
- customEvent.detail.done(result);
196
- };
197
-
198
- document.addEventListener("app:image-uploader/commit", handleCommit);
199
- return () => {
200
- document.removeEventListener("app:image-uploader/commit", handleCommit);
201
- };
202
- }, [mode, commitUpload]);
203
-
204
- // Clean up preview URLs on unmount
205
- useEffect(() => {
206
- return () => {
207
- for (const url of previewUrls) {
208
- URL.revokeObjectURL(url);
209
- }
210
- };
211
- }, [previewUrls]);
212
-
213
- const totalCount = mode === "lazy" ? pendingFiles.length : value?.length || 0;
214
- const canAddMore = !maxImages || totalCount < maxImages;
215
- const displayUrls = mode === "lazy" ? previewUrls : value;
216
-
217
- return (
218
- <div className={cn("flex flex-wrap gap-3", className)}>
219
- <input
220
- ref={inputRef}
221
- type="file"
222
- accept={accept}
223
- multiple
224
- onChange={handleInputChange}
225
- onBlur={onBlur}
226
- disabled={disabled || isUploading}
227
- className="sr-only"
228
- />
229
-
230
- {/* Existing and pending images */}
231
- {displayUrls?.map((url, index) => (
232
- <div
233
- key={`${url}-${index}`}
234
- className={cn("relative rounded-lg border overflow-hidden", sizeClasses[previewSize])}
235
- >
236
- <img src={url} alt={`Uploaded ${index + 1}`} className="h-full w-full object-cover" />
237
- {!disabled && (
238
- <Button
239
- type="button"
240
- variant="destructive"
241
- size="icon"
242
- className="absolute top-1 right-1 h-6 w-6 rounded-full"
243
- onClick={() => handleRemove(index)}
244
- >
245
- <XIcon className="h-3 w-3" />
246
- </Button>
247
- )}
248
- </div>
249
- ))}
250
-
251
- {/* Add button */}
252
- {canAddMore && (
253
- <div
254
- onClick={handleClick}
255
- onDrop={handleDrop}
256
- onDragOver={handleDragOver}
257
- onDragLeave={handleDragLeave}
258
- className={cn(
259
- "flex items-center justify-center rounded-lg border-2 border-dashed cursor-pointer transition-all",
260
- sizeClasses[previewSize],
261
- dragOver
262
- ? "border-primary bg-primary/5"
263
- : "border-muted-foreground/25 hover:border-muted-foreground/50",
264
- disabled && "opacity-50 cursor-not-allowed",
265
- isUploading && "cursor-wait",
266
- )}
267
- >
268
- {isUploading ? (
269
- <div className="flex flex-col items-center gap-2 text-muted-foreground">
270
- <Loader2Icon className="h-6 w-6 animate-spin" />
271
- <span className="text-xs">Uploading...</span>
272
- </div>
273
- ) : (
274
- <div className="flex flex-col items-center gap-2 text-muted-foreground p-2">
275
- <PlusIcon className="h-6 w-6" />
276
- <span className="text-xs text-center">{placeholder}</span>
277
- </div>
278
- )}
279
- </div>
280
- )}
281
- </div>
282
- );
283
- }