@giddaa-housing/ui 0.1.0

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 (248) hide show
  1. package/README.md +41 -0
  2. package/dist/accordion.d.ts +11 -0
  3. package/dist/accordion.js +124 -0
  4. package/dist/accordion.js.map +1 -0
  5. package/dist/alert.d.ts +18 -0
  6. package/dist/alert.js +152 -0
  7. package/dist/alert.js.map +1 -0
  8. package/dist/avatar.d.ts +14 -0
  9. package/dist/avatar.js +152 -0
  10. package/dist/avatar.js.map +1 -0
  11. package/dist/badge.d.ts +14 -0
  12. package/dist/badge.js +119 -0
  13. package/dist/badge.js.map +1 -0
  14. package/dist/bar-chart.d.ts +136 -0
  15. package/dist/bar-chart.js +302 -0
  16. package/dist/bar-chart.js.map +1 -0
  17. package/dist/base.css +32 -0
  18. package/dist/breadcrumb.d.ts +12 -0
  19. package/dist/breadcrumb.js +161 -0
  20. package/dist/breadcrumb.js.map +1 -0
  21. package/dist/bullet-chart.d.ts +98 -0
  22. package/dist/bullet-chart.js +189 -0
  23. package/dist/bullet-chart.js.map +1 -0
  24. package/dist/button-group.d.ts +18 -0
  25. package/dist/button-group.js +170 -0
  26. package/dist/button-group.js.map +1 -0
  27. package/dist/button.d.ts +19 -0
  28. package/dist/button.js +146 -0
  29. package/dist/button.js.map +1 -0
  30. package/dist/calendar.d.ts +9 -0
  31. package/dist/calendar.js +293 -0
  32. package/dist/calendar.js.map +1 -0
  33. package/dist/card.d.ts +18 -0
  34. package/dist/card.js +186 -0
  35. package/dist/card.js.map +1 -0
  36. package/dist/carousel.d.ts +53 -0
  37. package/dist/carousel.js +396 -0
  38. package/dist/carousel.js.map +1 -0
  39. package/dist/chart.d.ts +122 -0
  40. package/dist/chart.js +494 -0
  41. package/dist/chart.js.map +1 -0
  42. package/dist/checkbox.d.ts +73 -0
  43. package/dist/checkbox.js +87 -0
  44. package/dist/checkbox.js.map +1 -0
  45. package/dist/collapsible.d.ts +8 -0
  46. package/dist/collapsible.js +82 -0
  47. package/dist/collapsible.js.map +1 -0
  48. package/dist/combobox.d.ts +30 -0
  49. package/dist/combobox.js +713 -0
  50. package/dist/combobox.js.map +1 -0
  51. package/dist/date-picker.d.ts +22 -0
  52. package/dist/date-picker.js +528 -0
  53. package/dist/date-picker.js.map +1 -0
  54. package/dist/dialog.d.ts +30 -0
  55. package/dist/dialog.js +339 -0
  56. package/dist/dialog.js.map +1 -0
  57. package/dist/dropdown-menu.d.ts +35 -0
  58. package/dist/dropdown-menu.js +376 -0
  59. package/dist/dropdown-menu.js.map +1 -0
  60. package/dist/dropzone.d.ts +128 -0
  61. package/dist/dropzone.js +490 -0
  62. package/dist/dropzone.js.map +1 -0
  63. package/dist/empty-state.d.ts +17 -0
  64. package/dist/empty-state.js +146 -0
  65. package/dist/empty-state.js.map +1 -0
  66. package/dist/field.d.ts +29 -0
  67. package/dist/field.js +345 -0
  68. package/dist/field.js.map +1 -0
  69. package/dist/files/red-hat-display-latin-300-italic.woff +0 -0
  70. package/dist/files/red-hat-display-latin-300-italic.woff2 +0 -0
  71. package/dist/files/red-hat-display-latin-300-normal.woff +0 -0
  72. package/dist/files/red-hat-display-latin-300-normal.woff2 +0 -0
  73. package/dist/files/red-hat-display-latin-400-italic.woff +0 -0
  74. package/dist/files/red-hat-display-latin-400-italic.woff2 +0 -0
  75. package/dist/files/red-hat-display-latin-400-normal.woff +0 -0
  76. package/dist/files/red-hat-display-latin-400-normal.woff2 +0 -0
  77. package/dist/files/red-hat-display-latin-500-italic.woff +0 -0
  78. package/dist/files/red-hat-display-latin-500-italic.woff2 +0 -0
  79. package/dist/files/red-hat-display-latin-500-normal.woff +0 -0
  80. package/dist/files/red-hat-display-latin-500-normal.woff2 +0 -0
  81. package/dist/files/red-hat-display-latin-600-italic.woff +0 -0
  82. package/dist/files/red-hat-display-latin-600-italic.woff2 +0 -0
  83. package/dist/files/red-hat-display-latin-600-normal.woff +0 -0
  84. package/dist/files/red-hat-display-latin-600-normal.woff2 +0 -0
  85. package/dist/files/red-hat-display-latin-700-italic.woff +0 -0
  86. package/dist/files/red-hat-display-latin-700-italic.woff2 +0 -0
  87. package/dist/files/red-hat-display-latin-700-normal.woff +0 -0
  88. package/dist/files/red-hat-display-latin-700-normal.woff2 +0 -0
  89. package/dist/files/red-hat-display-latin-800-italic.woff +0 -0
  90. package/dist/files/red-hat-display-latin-800-italic.woff2 +0 -0
  91. package/dist/files/red-hat-display-latin-800-normal.woff +0 -0
  92. package/dist/files/red-hat-display-latin-800-normal.woff2 +0 -0
  93. package/dist/files/red-hat-display-latin-900-italic.woff +0 -0
  94. package/dist/files/red-hat-display-latin-900-italic.woff2 +0 -0
  95. package/dist/files/red-hat-display-latin-900-normal.woff +0 -0
  96. package/dist/files/red-hat-display-latin-900-normal.woff2 +0 -0
  97. package/dist/files/red-hat-display-latin-ext-300-italic.woff +0 -0
  98. package/dist/files/red-hat-display-latin-ext-300-italic.woff2 +0 -0
  99. package/dist/files/red-hat-display-latin-ext-300-normal.woff +0 -0
  100. package/dist/files/red-hat-display-latin-ext-300-normal.woff2 +0 -0
  101. package/dist/files/red-hat-display-latin-ext-400-italic.woff +0 -0
  102. package/dist/files/red-hat-display-latin-ext-400-italic.woff2 +0 -0
  103. package/dist/files/red-hat-display-latin-ext-400-normal.woff +0 -0
  104. package/dist/files/red-hat-display-latin-ext-400-normal.woff2 +0 -0
  105. package/dist/files/red-hat-display-latin-ext-500-italic.woff +0 -0
  106. package/dist/files/red-hat-display-latin-ext-500-italic.woff2 +0 -0
  107. package/dist/files/red-hat-display-latin-ext-500-normal.woff +0 -0
  108. package/dist/files/red-hat-display-latin-ext-500-normal.woff2 +0 -0
  109. package/dist/files/red-hat-display-latin-ext-600-italic.woff +0 -0
  110. package/dist/files/red-hat-display-latin-ext-600-italic.woff2 +0 -0
  111. package/dist/files/red-hat-display-latin-ext-600-normal.woff +0 -0
  112. package/dist/files/red-hat-display-latin-ext-600-normal.woff2 +0 -0
  113. package/dist/files/red-hat-display-latin-ext-700-italic.woff +0 -0
  114. package/dist/files/red-hat-display-latin-ext-700-italic.woff2 +0 -0
  115. package/dist/files/red-hat-display-latin-ext-700-normal.woff +0 -0
  116. package/dist/files/red-hat-display-latin-ext-700-normal.woff2 +0 -0
  117. package/dist/files/red-hat-display-latin-ext-800-italic.woff +0 -0
  118. package/dist/files/red-hat-display-latin-ext-800-italic.woff2 +0 -0
  119. package/dist/files/red-hat-display-latin-ext-800-normal.woff +0 -0
  120. package/dist/files/red-hat-display-latin-ext-800-normal.woff2 +0 -0
  121. package/dist/files/red-hat-display-latin-ext-900-italic.woff +0 -0
  122. package/dist/files/red-hat-display-latin-ext-900-italic.woff2 +0 -0
  123. package/dist/files/red-hat-display-latin-ext-900-normal.woff +0 -0
  124. package/dist/files/red-hat-display-latin-ext-900-normal.woff2 +0 -0
  125. package/dist/funnel-chart.d.ts +84 -0
  126. package/dist/funnel-chart.js +569 -0
  127. package/dist/funnel-chart.js.map +1 -0
  128. package/dist/index.d.ts +87 -0
  129. package/dist/index.js +10448 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/input-group.d.ts +31 -0
  132. package/dist/input-group.js +380 -0
  133. package/dist/input-group.js.map +1 -0
  134. package/dist/input-size-context.d.ts +11 -0
  135. package/dist/input-size-context.js +24 -0
  136. package/dist/input-size-context.js.map +1 -0
  137. package/dist/input.d.ts +13 -0
  138. package/dist/input.js +83 -0
  139. package/dist/input.js.map +1 -0
  140. package/dist/item.d.ts +8 -0
  141. package/dist/item.js +93 -0
  142. package/dist/item.js.map +1 -0
  143. package/dist/kpi-card.d.ts +24 -0
  144. package/dist/kpi-card.js +243 -0
  145. package/dist/kpi-card.js.map +1 -0
  146. package/dist/label.d.ts +8 -0
  147. package/dist/label.js +68 -0
  148. package/dist/label.js.map +1 -0
  149. package/dist/line-chart.d.ts +155 -0
  150. package/dist/line-chart.js +269 -0
  151. package/dist/line-chart.js.map +1 -0
  152. package/dist/logo.d.ts +6 -0
  153. package/dist/logo.js +146 -0
  154. package/dist/logo.js.map +1 -0
  155. package/dist/number-input.d.ts +41 -0
  156. package/dist/number-input.js +418 -0
  157. package/dist/number-input.js.map +1 -0
  158. package/dist/page-header.d.ts +13 -0
  159. package/dist/page-header.js +113 -0
  160. package/dist/page-header.js.map +1 -0
  161. package/dist/pagination.d.ts +35 -0
  162. package/dist/pagination.js +352 -0
  163. package/dist/pagination.js.map +1 -0
  164. package/dist/password-input.d.ts +13 -0
  165. package/dist/password-input.js +356 -0
  166. package/dist/password-input.js.map +1 -0
  167. package/dist/phone-input.d.ts +21 -0
  168. package/dist/phone-input.js +573 -0
  169. package/dist/phone-input.js.map +1 -0
  170. package/dist/photo-gallery.d.ts +42 -0
  171. package/dist/photo-gallery.js +756 -0
  172. package/dist/photo-gallery.js.map +1 -0
  173. package/dist/pie-chart.d.ts +125 -0
  174. package/dist/pie-chart.js +192 -0
  175. package/dist/pie-chart.js.map +1 -0
  176. package/dist/popover.d.ts +20 -0
  177. package/dist/popover.js +169 -0
  178. package/dist/popover.js.map +1 -0
  179. package/dist/progress.d.ts +28 -0
  180. package/dist/progress.js +315 -0
  181. package/dist/progress.js.map +1 -0
  182. package/dist/radio-group.d.ts +32 -0
  183. package/dist/radio-group.js +100 -0
  184. package/dist/radio-group.js.map +1 -0
  185. package/dist/red-hat-display.css +2 -0
  186. package/dist/rich-text-editor.d.ts +16 -0
  187. package/dist/rich-text-editor.js +1000 -0
  188. package/dist/rich-text-editor.js.map +1 -0
  189. package/dist/search-input.d.ts +19 -0
  190. package/dist/search-input.js +411 -0
  191. package/dist/search-input.js.map +1 -0
  192. package/dist/select.d.ts +21 -0
  193. package/dist/select.js +305 -0
  194. package/dist/select.js.map +1 -0
  195. package/dist/separator.d.ts +10 -0
  196. package/dist/separator.js +72 -0
  197. package/dist/separator.js.map +1 -0
  198. package/dist/sheet.d.ts +24 -0
  199. package/dist/sheet.js +282 -0
  200. package/dist/sheet.js.map +1 -0
  201. package/dist/sidebar.d.ts +70 -0
  202. package/dist/sidebar.js +1078 -0
  203. package/dist/sidebar.js.map +1 -0
  204. package/dist/size-context.d.ts +11 -0
  205. package/dist/size-context.js +22 -0
  206. package/dist/size-context.js.map +1 -0
  207. package/dist/skeleton.d.ts +5 -0
  208. package/dist/skeleton.js +48 -0
  209. package/dist/skeleton.js.map +1 -0
  210. package/dist/sparkline.d.ts +94 -0
  211. package/dist/sparkline.js +568 -0
  212. package/dist/sparkline.js.map +1 -0
  213. package/dist/stepper.d.ts +43 -0
  214. package/dist/stepper.js +296 -0
  215. package/dist/stepper.js.map +1 -0
  216. package/dist/styles.css +2 -0
  217. package/dist/switch.d.ts +29 -0
  218. package/dist/switch.js +108 -0
  219. package/dist/switch.js.map +1 -0
  220. package/dist/tab-list.d.ts +38 -0
  221. package/dist/tab-list.js +394 -0
  222. package/dist/tab-list.js.map +1 -0
  223. package/dist/table.d.ts +69 -0
  224. package/dist/table.js +197 -0
  225. package/dist/table.js.map +1 -0
  226. package/dist/tabs.d.ts +18 -0
  227. package/dist/tabs.js +159 -0
  228. package/dist/tabs.js.map +1 -0
  229. package/dist/tag.d.ts +25 -0
  230. package/dist/tag.js +160 -0
  231. package/dist/tag.js.map +1 -0
  232. package/dist/textarea.d.ts +12 -0
  233. package/dist/textarea.js +78 -0
  234. package/dist/textarea.js.map +1 -0
  235. package/dist/theme/giddaa.css +2 -0
  236. package/dist/time-picker.d.ts +13 -0
  237. package/dist/time-picker.js +472 -0
  238. package/dist/time-picker.js.map +1 -0
  239. package/dist/toast.d.ts +23 -0
  240. package/dist/toast.js +330 -0
  241. package/dist/toast.js.map +1 -0
  242. package/dist/tooltip.d.ts +11 -0
  243. package/dist/tooltip.js +96 -0
  244. package/dist/tooltip.js.map +1 -0
  245. package/dist/tree-map.d.ts +127 -0
  246. package/dist/tree-map.js +652 -0
  247. package/dist/tree-map.js.map +1 -0
  248. package/package.json +328 -0
@@ -0,0 +1,490 @@
1
+ // src/components/ui/dropzone.tsx
2
+ import { UploadCloud } from "lucide-react";
3
+ import {
4
+ createContext,
5
+ use
6
+ } from "react";
7
+
8
+ // src/lib/cn.ts
9
+ import { clsx } from "clsx";
10
+ import { extendTailwindMerge } from "tailwind-merge";
11
+ var twMerge = extendTailwindMerge({
12
+ extend: {
13
+ classGroups: {
14
+ "font-size": [
15
+ {
16
+ text: [
17
+ "gdt-display",
18
+ "gdt-h1",
19
+ "gdt-h2",
20
+ "gdt-h3",
21
+ "gdt-h4",
22
+ "gdt-h5",
23
+ "gdt-xl",
24
+ "gdt-lg",
25
+ "gdt-md",
26
+ "gdt-sm",
27
+ "gdt-xs",
28
+ "gdt-subtext",
29
+ "gdt-capitalized"
30
+ ]
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ });
36
+ function cn(...inputs) {
37
+ return twMerge(clsx(inputs));
38
+ }
39
+
40
+ // src/lib/use-file-picker.ts
41
+ import {
42
+ useCallback,
43
+ useRef,
44
+ useState
45
+ } from "react";
46
+ function useFilePicker({
47
+ accept = "*",
48
+ disabled = false,
49
+ maxFiles = Number.POSITIVE_INFINITY,
50
+ maxSize = Number.POSITIVE_INFINITY,
51
+ multiple = false,
52
+ onFilesAccepted,
53
+ onFilesChange,
54
+ onFilesRejected
55
+ } = {}) {
56
+ const inputRef = useRef(null);
57
+ const dragDepthRef = useRef(0);
58
+ const [isDragging, setIsDragging] = useState(false);
59
+ const pickFiles = useCallback(
60
+ (files) => {
61
+ const incomingFiles = Array.from(files);
62
+ const limit = multiple ? maxFiles : 1;
63
+ const acceptedFiles = [];
64
+ const rejectedFiles = [];
65
+ if (incomingFiles.length === 0 || disabled) {
66
+ return { acceptedFiles, rejectedFiles };
67
+ }
68
+ for (const [index, file] of incomingFiles.entries()) {
69
+ const errors = [];
70
+ if (index >= limit) {
71
+ errors.push({
72
+ code: "too-many-files",
73
+ message: multiple ? `You can only select up to ${limit} files.` : "You can only select one file."
74
+ });
75
+ } else {
76
+ errors.push(...validateFile(file, { accept, maxSize }));
77
+ }
78
+ if (errors.length > 0) {
79
+ rejectedFiles.push({ file, errors });
80
+ continue;
81
+ }
82
+ acceptedFiles.push(file);
83
+ }
84
+ const result = { acceptedFiles, rejectedFiles };
85
+ if (acceptedFiles.length > 0) {
86
+ onFilesAccepted?.(acceptedFiles);
87
+ }
88
+ if (rejectedFiles.length > 0) {
89
+ onFilesRejected?.(rejectedFiles);
90
+ }
91
+ onFilesChange?.(result);
92
+ if (inputRef.current) {
93
+ inputRef.current.value = "";
94
+ }
95
+ return result;
96
+ },
97
+ [
98
+ accept,
99
+ disabled,
100
+ maxFiles,
101
+ maxSize,
102
+ multiple,
103
+ onFilesAccepted,
104
+ onFilesChange,
105
+ onFilesRejected
106
+ ]
107
+ );
108
+ const handleFileChange = useCallback(
109
+ (event) => {
110
+ if (event.target.files) {
111
+ pickFiles(event.target.files);
112
+ }
113
+ },
114
+ [pickFiles]
115
+ );
116
+ const openFileDialog = useCallback(() => {
117
+ if (disabled) return;
118
+ inputRef.current?.click();
119
+ }, [disabled]);
120
+ const handleDragEnter = useCallback(
121
+ (event) => {
122
+ event.preventDefault();
123
+ event.stopPropagation();
124
+ if (disabled) return;
125
+ dragDepthRef.current += 1;
126
+ setIsDragging(true);
127
+ },
128
+ [disabled]
129
+ );
130
+ const handleDragLeave = useCallback(
131
+ (event) => {
132
+ event.preventDefault();
133
+ event.stopPropagation();
134
+ if (disabled) return;
135
+ dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
136
+ if (dragDepthRef.current === 0) {
137
+ setIsDragging(false);
138
+ }
139
+ },
140
+ [disabled]
141
+ );
142
+ const handleDragOver = useCallback((event) => {
143
+ event.preventDefault();
144
+ event.stopPropagation();
145
+ }, []);
146
+ const handleDrop = useCallback(
147
+ (event) => {
148
+ event.preventDefault();
149
+ event.stopPropagation();
150
+ dragDepthRef.current = 0;
151
+ setIsDragging(false);
152
+ if (event.dataTransfer.files.length > 0) {
153
+ pickFiles(event.dataTransfer.files);
154
+ }
155
+ },
156
+ [pickFiles]
157
+ );
158
+ const getInputProps = useCallback(
159
+ (props = {}) => {
160
+ const { onChange, ref, ...inputProps } = props;
161
+ return {
162
+ ...inputProps,
163
+ type: "file",
164
+ accept: inputProps.accept ?? accept,
165
+ disabled: inputProps.disabled ?? disabled,
166
+ multiple: inputProps.multiple ?? multiple,
167
+ ref: (node) => {
168
+ inputRef.current = node;
169
+ assignRef(ref, node);
170
+ },
171
+ onChange: (event) => {
172
+ onChange?.(event);
173
+ if (!event.defaultPrevented) {
174
+ handleFileChange(event);
175
+ }
176
+ }
177
+ };
178
+ },
179
+ [accept, disabled, handleFileChange, multiple]
180
+ );
181
+ return {
182
+ getInputProps,
183
+ handleDragEnter,
184
+ handleDragLeave,
185
+ handleDragOver,
186
+ handleDrop,
187
+ handleFileChange,
188
+ inputRef,
189
+ isDragging,
190
+ openFileDialog,
191
+ pickFiles
192
+ };
193
+ }
194
+ function validateFile(file, options = {}) {
195
+ const { accept = "*", maxSize = Number.POSITIVE_INFINITY } = options;
196
+ const errors = [];
197
+ if (file.size > maxSize) {
198
+ errors.push({
199
+ code: "file-too-large",
200
+ message: `File "${file.name}" exceeds the maximum size of ${formatBytes(maxSize)}.`
201
+ });
202
+ }
203
+ if (!isAcceptedFile(file, accept)) {
204
+ errors.push({
205
+ code: "file-invalid-type",
206
+ message: `File "${file.name}" is not an accepted file type.`
207
+ });
208
+ }
209
+ return errors;
210
+ }
211
+ function isAcceptedFile(file, accept = "*") {
212
+ if (accept === "*" || accept.trim() === "") return true;
213
+ const acceptedTypes = accept.split(",").map((type) => type.trim().toLowerCase()).filter(Boolean);
214
+ if (acceptedTypes.length === 0) return true;
215
+ const fileType = file.type.toLowerCase();
216
+ const fileExtension = getFileExtension(file.name);
217
+ return acceptedTypes.some((acceptedType) => {
218
+ if (acceptedType.startsWith(".")) {
219
+ return fileExtension === acceptedType;
220
+ }
221
+ if (acceptedType.endsWith("/*")) {
222
+ return fileType.startsWith(acceptedType.slice(0, -1));
223
+ }
224
+ return fileType === acceptedType;
225
+ });
226
+ }
227
+ function formatBytes(bytes, decimals = 2) {
228
+ if (bytes === 0) return "0 Bytes";
229
+ if (!Number.isFinite(bytes)) return "unlimited";
230
+ const unit = 1024;
231
+ const precision = Math.max(0, decimals);
232
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
233
+ const sizeIndex = Math.min(
234
+ Math.floor(Math.log(bytes) / Math.log(unit)),
235
+ sizes.length - 1
236
+ );
237
+ return `${Number.parseFloat((bytes / unit ** sizeIndex).toFixed(precision))} ${sizes[sizeIndex]}`;
238
+ }
239
+ function getFileExtension(fileName) {
240
+ const extension = fileName.toLowerCase().split(".").pop();
241
+ return extension && extension !== fileName.toLowerCase() ? `.${extension}` : "";
242
+ }
243
+ function assignRef(ref, value) {
244
+ if (!ref) return;
245
+ if (typeof ref === "function") {
246
+ ref(value);
247
+ return;
248
+ }
249
+ ref.current = value;
250
+ }
251
+
252
+ // src/components/ui/dropzone.tsx
253
+ import { jsx, jsxs } from "react/jsx-runtime";
254
+ var DropzoneContext = createContext(null);
255
+ function useDropzoneContext() {
256
+ const ctx = use(DropzoneContext);
257
+ if (!ctx) {
258
+ throw new Error(
259
+ "Dropzone compound components must be rendered inside <Dropzone>."
260
+ );
261
+ }
262
+ return ctx;
263
+ }
264
+ function Dropzone({
265
+ children,
266
+ className,
267
+ disabled,
268
+ ...options
269
+ }) {
270
+ const {
271
+ isDragging,
272
+ openFileDialog,
273
+ getInputProps,
274
+ handleDragEnter,
275
+ handleDragLeave,
276
+ handleDragOver,
277
+ handleDrop
278
+ } = useFilePicker({ ...options, disabled });
279
+ return /* @__PURE__ */ jsx(
280
+ DropzoneContext.Provider,
281
+ {
282
+ value: {
283
+ isDragging,
284
+ isDisabled: disabled ?? false,
285
+ openFileDialog,
286
+ getInputProps,
287
+ handleDragEnter,
288
+ handleDragLeave,
289
+ handleDragOver,
290
+ handleDrop
291
+ },
292
+ children: /* @__PURE__ */ jsx("div", { "data-slot": "dropzone", className: cn("relative", className), children })
293
+ }
294
+ );
295
+ }
296
+ function DropzoneArea({
297
+ children,
298
+ className,
299
+ label = "Upload files. Click to browse, or drag and drop files here.",
300
+ ...props
301
+ }) {
302
+ const {
303
+ isDragging,
304
+ isDisabled,
305
+ openFileDialog,
306
+ handleDragEnter,
307
+ handleDragLeave,
308
+ handleDragOver,
309
+ handleDrop
310
+ } = useDropzoneContext();
311
+ function handleKeyDown(e) {
312
+ if (e.key === "Enter" || e.key === " ") {
313
+ e.preventDefault();
314
+ openFileDialog();
315
+ }
316
+ }
317
+ return (
318
+ // biome-ignore lint/a11y/useSemanticElements: The dropzone contains block-level compound content and owns drag events.
319
+ /* @__PURE__ */ jsxs(
320
+ "div",
321
+ {
322
+ "data-slot": "dropzone-area",
323
+ "data-dragging": isDragging ? "true" : void 0,
324
+ "data-disabled": isDisabled ? "true" : void 0,
325
+ role: "button",
326
+ tabIndex: isDisabled ? -1 : 0,
327
+ "aria-label": label,
328
+ "aria-disabled": isDisabled,
329
+ onClick: isDisabled ? void 0 : openFileDialog,
330
+ onKeyDown: isDisabled ? void 0 : handleKeyDown,
331
+ onDragEnter: isDisabled ? void 0 : handleDragEnter,
332
+ onDragLeave: isDisabled ? void 0 : handleDragLeave,
333
+ onDragOver: isDisabled ? void 0 : handleDragOver,
334
+ onDrop: isDisabled ? void 0 : handleDrop,
335
+ className: cn(
336
+ // Layout & base
337
+ "flex min-h-48 w-full cursor-pointer flex-col items-center justify-center rounded-xl border p-8 text-center transition-colors duration-150 select-none",
338
+ // Default colours (design tokens)
339
+ "border-line bg-surface-brand-subtle",
340
+ // Focus ring – matches other interactive controls in the system
341
+ "focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-ring/20 focus-visible:border-ring",
342
+ // Dragging variant
343
+ "data-[dragging=true]:border-dashed data-[dragging=true]:border-line-focus data-[dragging=true]:bg-surface-brand/10",
344
+ // Disabled variant
345
+ "data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50",
346
+ className
347
+ ),
348
+ ...props,
349
+ children: [
350
+ children,
351
+ /* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: isDragging ? "Drop files to upload." : "" })
352
+ ]
353
+ }
354
+ )
355
+ );
356
+ }
357
+ function DropzoneInput({ className, ...props }) {
358
+ const { getInputProps } = useDropzoneContext();
359
+ return /* @__PURE__ */ jsx(
360
+ "input",
361
+ {
362
+ ...getInputProps({
363
+ // sr-only keeps it in the a11y tree without being visible
364
+ className: cn("sr-only", className),
365
+ // Prevent it from receiving keyboard focus independently
366
+ tabIndex: -1,
367
+ ...props
368
+ })
369
+ }
370
+ );
371
+ }
372
+ function useDropzoneStateLabel({
373
+ children,
374
+ disabledLabel,
375
+ draggingLabel,
376
+ idleLabel
377
+ }) {
378
+ const { isDragging, isDisabled } = useDropzoneContext();
379
+ if (isDisabled && disabledLabel !== void 0) {
380
+ return disabledLabel;
381
+ }
382
+ if (isDragging && draggingLabel !== void 0) {
383
+ return draggingLabel;
384
+ }
385
+ return idleLabel ?? children;
386
+ }
387
+ function DropzoneIcon({
388
+ className,
389
+ children,
390
+ ...props
391
+ }) {
392
+ return /* @__PURE__ */ jsx(
393
+ "div",
394
+ {
395
+ "data-slot": "dropzone-icon",
396
+ "aria-hidden": "true",
397
+ className: cn(
398
+ "mb-4 flex size-11 shrink-0 items-center justify-center rounded-full",
399
+ // Solid brand fill with an inset ring for depth
400
+ "bg-surface-brand text-fg-on-brand ring-1 ring-inset ring-white/10",
401
+ className
402
+ ),
403
+ ...props,
404
+ children: children ?? /* @__PURE__ */ jsx(UploadCloud, { className: "size-5" })
405
+ }
406
+ );
407
+ }
408
+ function DropzoneTitle({
409
+ className,
410
+ children,
411
+ disabledLabel,
412
+ draggingLabel,
413
+ idleLabel,
414
+ ...props
415
+ }) {
416
+ const label = useDropzoneStateLabel({
417
+ children,
418
+ disabledLabel,
419
+ draggingLabel,
420
+ idleLabel
421
+ });
422
+ return /* @__PURE__ */ jsx(
423
+ "p",
424
+ {
425
+ "data-slot": "dropzone-title",
426
+ className: cn(
427
+ "text-lg font-semibold leading-snug text-fg-primary",
428
+ className
429
+ ),
430
+ ...props,
431
+ children: label
432
+ }
433
+ );
434
+ }
435
+ function DropzoneDescription({
436
+ className,
437
+ children,
438
+ disabledLabel,
439
+ draggingLabel,
440
+ idleLabel,
441
+ ...props
442
+ }) {
443
+ const label = useDropzoneStateLabel({
444
+ children,
445
+ disabledLabel,
446
+ draggingLabel,
447
+ idleLabel
448
+ });
449
+ return /* @__PURE__ */ jsx(
450
+ "p",
451
+ {
452
+ "data-slot": "dropzone-description",
453
+ className: cn("mt-1 text-sm text-fg-muted", className),
454
+ ...props,
455
+ children: label
456
+ }
457
+ );
458
+ }
459
+ function DropzoneTrigger({
460
+ className,
461
+ children = "Browse File",
462
+ ...props
463
+ }) {
464
+ return /* @__PURE__ */ jsx(
465
+ "span",
466
+ {
467
+ "data-slot": "dropzone-trigger",
468
+ "aria-hidden": "true",
469
+ className: cn(
470
+ "mt-5 inline-flex h-8 shrink-0 items-center justify-center rounded-lg px-4",
471
+ "bg-primary text-sm font-medium text-primary-foreground",
472
+ "transition-colors duration-150",
473
+ className
474
+ ),
475
+ ...props,
476
+ children
477
+ }
478
+ );
479
+ }
480
+ export {
481
+ Dropzone,
482
+ DropzoneArea,
483
+ DropzoneDescription,
484
+ DropzoneIcon,
485
+ DropzoneInput,
486
+ DropzoneTitle,
487
+ DropzoneTrigger,
488
+ useDropzoneContext
489
+ };
490
+ //# sourceMappingURL=dropzone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/dropzone.tsx","../src/lib/cn.ts","../src/lib/use-file-picker.ts"],"sourcesContent":["\"use client\";\n\nimport { UploadCloud } from \"lucide-react\";\nimport {\n\ttype ComponentProps,\n\tcreateContext,\n\ttype KeyboardEvent,\n\ttype ReactNode,\n\tuse,\n} from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport {\n\ttype UseFilePickerOptions,\n\ttype UseFilePickerReturn,\n\tuseFilePicker,\n} from \"../../lib/use-file-picker\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Context\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype DropzoneContextValue = Pick<\n\tUseFilePickerReturn,\n\t| \"isDragging\"\n\t| \"openFileDialog\"\n\t| \"getInputProps\"\n\t| \"handleDragEnter\"\n\t| \"handleDragLeave\"\n\t| \"handleDragOver\"\n\t| \"handleDrop\"\n> & { isDisabled: boolean };\n\nconst DropzoneContext = createContext<DropzoneContextValue | null>(null);\n\nfunction useDropzoneContext(): DropzoneContextValue {\n\tconst ctx = use(DropzoneContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"Dropzone compound components must be rendered inside <Dropzone>.\",\n\t\t);\n\t}\n\treturn ctx;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Root\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface DropzoneProps extends UseFilePickerOptions {\n\tchildren?: ReactNode;\n\tclassName?: string;\n}\n\n/**\n * Context provider that owns the `useFilePicker` instance.\n * Wrap `<DropzoneArea>` and `<DropzoneInput>` (plus any content helpers)\n * inside this component.\n *\n * @example\n * ```tsx\n * <Dropzone accept=\"image/*\" multiple maxFiles={5} onFilesAccepted={handleFiles}>\n * <DropzoneArea>\n * <DropzoneIcon />\n * <DropzoneTitle>Choose a file or drag & drop</DropzoneTitle>\n * <DropzoneDescription>JPEG, PNG – up to 2 MB</DropzoneDescription>\n * <DropzoneTrigger />\n * </DropzoneArea>\n * <DropzoneInput />\n * </Dropzone>\n * ```\n */\nfunction Dropzone({\n\tchildren,\n\tclassName,\n\tdisabled,\n\t...options\n}: DropzoneProps) {\n\tconst {\n\t\tisDragging,\n\t\topenFileDialog,\n\t\tgetInputProps,\n\t\thandleDragEnter,\n\t\thandleDragLeave,\n\t\thandleDragOver,\n\t\thandleDrop,\n\t} = useFilePicker({ ...options, disabled });\n\n\treturn (\n\t\t<DropzoneContext.Provider\n\t\t\tvalue={{\n\t\t\t\tisDragging,\n\t\t\t\tisDisabled: disabled ?? false,\n\t\t\t\topenFileDialog,\n\t\t\t\tgetInputProps,\n\t\t\t\thandleDragEnter,\n\t\t\t\thandleDragLeave,\n\t\t\t\thandleDragOver,\n\t\t\t\thandleDrop,\n\t\t\t}}\n\t\t>\n\t\t\t<div data-slot=\"dropzone\" className={cn(\"relative\", className)}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</DropzoneContext.Provider>\n\t);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Area (the interactive drop target)\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface DropzoneAreaProps\n\textends Omit<ComponentProps<\"div\">, \"onClick\" | \"onKeyDown\"> {\n\t/**\n\t * Accessible label for the drop zone.\n\t * Defaults to a sensible description.\n\t */\n\tlabel?: string;\n}\n\n/**\n * The visual, interactive drop zone.\n *\n * - Behaves as a `button` (role, tabIndex, Enter/Space keyboard support).\n * - Announces drag-state changes to screen readers via a live region.\n * - Applies design-token-based styles and reacts to `data-dragging` /\n * `data-disabled` for visual feedback.\n */\nfunction DropzoneArea({\n\tchildren,\n\tclassName,\n\tlabel = \"Upload files. Click to browse, or drag and drop files here.\",\n\t...props\n}: DropzoneAreaProps) {\n\tconst {\n\t\tisDragging,\n\t\tisDisabled,\n\t\topenFileDialog,\n\t\thandleDragEnter,\n\t\thandleDragLeave,\n\t\thandleDragOver,\n\t\thandleDrop,\n\t} = useDropzoneContext();\n\n\tfunction handleKeyDown(e: KeyboardEvent<HTMLDivElement>) {\n\t\tif (e.key === \"Enter\" || e.key === \" \") {\n\t\t\te.preventDefault();\n\t\t\topenFileDialog();\n\t\t}\n\t}\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useSemanticElements: The dropzone contains block-level compound content and owns drag events.\n\t\t<div\n\t\t\tdata-slot=\"dropzone-area\"\n\t\t\t// Data attributes drive all variant styles – no runtime class toggling.\n\t\t\tdata-dragging={isDragging ? \"true\" : undefined}\n\t\t\tdata-disabled={isDisabled ? \"true\" : undefined}\n\t\t\t// Accessibility ──────────────────────────────────────────────────────\n\t\t\trole=\"button\"\n\t\t\ttabIndex={isDisabled ? -1 : 0}\n\t\t\taria-label={label}\n\t\t\taria-disabled={isDisabled}\n\t\t\t// Interaction ────────────────────────────────────────────────────────\n\t\t\tonClick={isDisabled ? undefined : openFileDialog}\n\t\t\tonKeyDown={isDisabled ? undefined : handleKeyDown}\n\t\t\tonDragEnter={isDisabled ? undefined : handleDragEnter}\n\t\t\tonDragLeave={isDisabled ? undefined : handleDragLeave}\n\t\t\tonDragOver={isDisabled ? undefined : handleDragOver}\n\t\t\tonDrop={isDisabled ? undefined : handleDrop}\n\t\t\t// Styles ─────────────────────────────────────────────────────────────\n\t\t\tclassName={cn(\n\t\t\t\t// Layout & base\n\t\t\t\t\"flex min-h-48 w-full cursor-pointer flex-col items-center justify-center rounded-xl border p-8 text-center transition-colors duration-150 select-none\",\n\t\t\t\t// Default colours (design tokens)\n\t\t\t\t\"border-line bg-surface-brand-subtle\",\n\t\t\t\t// Focus ring – matches other interactive controls in the system\n\t\t\t\t\"focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-ring/20 focus-visible:border-ring\",\n\t\t\t\t// Dragging variant\n\t\t\t\t\"data-[dragging=true]:border-dashed data-[dragging=true]:border-line-focus data-[dragging=true]:bg-surface-brand/10\",\n\t\t\t\t// Disabled variant\n\t\t\t\t\"data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\n\t\t\t{/* Live region: announces drag-state changes to screen-reader users */}\n\t\t\t<span className=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n\t\t\t\t{isDragging ? \"Drop files to upload.\" : \"\"}\n\t\t\t</span>\n\t\t</div>\n\t);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Input (visually hidden but present in the a11y tree)\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype DropzoneInputProps = Omit<ComponentProps<\"input\">, \"type\">;\n\n/**\n * The hidden `<input type=\"file\">` that backs the drop zone.\n * Rendered off-screen (not `display:none`) so it remains accessible.\n * Place it as a sibling to `<DropzoneArea>` inside `<Dropzone>`.\n */\nfunction DropzoneInput({ className, ...props }: DropzoneInputProps) {\n\tconst { getInputProps } = useDropzoneContext();\n\treturn (\n\t\t<input\n\t\t\t{...getInputProps({\n\t\t\t\t// sr-only keeps it in the a11y tree without being visible\n\t\t\t\tclassName: cn(\"sr-only\", className),\n\t\t\t\t// Prevent it from receiving keyboard focus independently\n\t\t\t\ttabIndex: -1,\n\t\t\t\t...props,\n\t\t\t})}\n\t\t/>\n\t);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Content helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype DropzoneStateLabelProps = {\n\tchildren?: ReactNode;\n\tdisabledLabel?: ReactNode;\n\tdraggingLabel?: ReactNode;\n\tidleLabel?: ReactNode;\n};\n\ntype DropzoneTextProps = Omit<ComponentProps<\"p\">, \"children\"> &\n\tDropzoneStateLabelProps;\n\nfunction useDropzoneStateLabel({\n\tchildren,\n\tdisabledLabel,\n\tdraggingLabel,\n\tidleLabel,\n}: DropzoneStateLabelProps) {\n\tconst { isDragging, isDisabled } = useDropzoneContext();\n\n\tif (isDisabled && disabledLabel !== undefined) {\n\t\treturn disabledLabel;\n\t}\n\n\tif (isDragging && draggingLabel !== undefined) {\n\t\treturn draggingLabel;\n\t}\n\n\treturn idleLabel ?? children;\n}\n\n/**\n * A centred, brand-coloured icon container pre-populated with an upload cloud\n * icon. Pass `children` to swap the icon.\n */\nfunction DropzoneIcon({\n\tclassName,\n\tchildren,\n\t...props\n}: ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"dropzone-icon\"\n\t\t\taria-hidden=\"true\"\n\t\t\tclassName={cn(\n\t\t\t\t\"mb-4 flex size-11 shrink-0 items-center justify-center rounded-full\",\n\t\t\t\t// Solid brand fill with an inset ring for depth\n\t\t\t\t\"bg-surface-brand text-fg-on-brand ring-1 ring-inset ring-white/10\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children ?? <UploadCloud className=\"size-5\" />}\n\t\t</div>\n\t);\n}\n\n/**\n * Primary heading text inside the drop zone.\n */\nfunction DropzoneTitle({\n\tclassName,\n\tchildren,\n\tdisabledLabel,\n\tdraggingLabel,\n\tidleLabel,\n\t...props\n}: DropzoneTextProps) {\n\tconst label = useDropzoneStateLabel({\n\t\tchildren,\n\t\tdisabledLabel,\n\t\tdraggingLabel,\n\t\tidleLabel,\n\t});\n\n\treturn (\n\t\t<p\n\t\t\tdata-slot=\"dropzone-title\"\n\t\t\tclassName={cn(\n\t\t\t\t\"text-lg font-semibold leading-snug text-fg-primary\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{label}\n\t\t</p>\n\t);\n}\n\n/**\n * Secondary descriptive text inside the drop zone (file-type hints, size\n * limits, etc.).\n */\nfunction DropzoneDescription({\n\tclassName,\n\tchildren,\n\tdisabledLabel,\n\tdraggingLabel,\n\tidleLabel,\n\t...props\n}: DropzoneTextProps) {\n\tconst label = useDropzoneStateLabel({\n\t\tchildren,\n\t\tdisabledLabel,\n\t\tdraggingLabel,\n\t\tidleLabel,\n\t});\n\n\treturn (\n\t\t<p\n\t\t\tdata-slot=\"dropzone-description\"\n\t\t\tclassName={cn(\"mt-1 text-sm text-fg-muted\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{label}\n\t\t</p>\n\t);\n}\n\n/**\n * A decorative \"Browse File\" pill that visually suggests the click action.\n *\n * This element is `aria-hidden` because the surrounding `<DropzoneArea>`\n * already exposes a labelled `button` role to assistive technologies.\n * The pill is purely a visual affordance.\n */\nfunction DropzoneTrigger({\n\tclassName,\n\tchildren = \"Browse File\",\n\t...props\n}: ComponentProps<\"span\">) {\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"dropzone-trigger\"\n\t\t\taria-hidden=\"true\"\n\t\t\tclassName={cn(\n\t\t\t\t\"mt-5 inline-flex h-8 shrink-0 items-center justify-center rounded-lg px-4\",\n\t\t\t\t\"bg-primary text-sm font-medium text-primary-foreground\",\n\t\t\t\t\"transition-colors duration-150\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</span>\n\t);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Exports\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport {\n\tDropzone,\n\tDropzoneArea,\n\tDropzoneDescription,\n\tDropzoneIcon,\n\tDropzoneInput,\n\tDropzoneTitle,\n\tDropzoneTrigger,\n\tuseDropzoneContext,\n};\n","import { type ClassValue, clsx } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n\textend: {\n\t\tclassGroups: {\n\t\t\t\"font-size\": [\n\t\t\t\t{\n\t\t\t\t\ttext: [\n\t\t\t\t\t\t\"gdt-display\",\n\t\t\t\t\t\t\"gdt-h1\",\n\t\t\t\t\t\t\"gdt-h2\",\n\t\t\t\t\t\t\"gdt-h3\",\n\t\t\t\t\t\t\"gdt-h4\",\n\t\t\t\t\t\t\"gdt-h5\",\n\t\t\t\t\t\t\"gdt-xl\",\n\t\t\t\t\t\t\"gdt-lg\",\n\t\t\t\t\t\t\"gdt-md\",\n\t\t\t\t\t\t\"gdt-sm\",\n\t\t\t\t\t\t\"gdt-xs\",\n\t\t\t\t\t\t\"gdt-subtext\",\n\t\t\t\t\t\t\"gdt-capitalized\",\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n});\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import {\n\ttype ChangeEvent,\n\ttype ComponentPropsWithoutRef,\n\ttype DragEvent,\n\ttype Ref,\n\ttype RefObject,\n\tuseCallback,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\ntype FilePickerErrorCode =\n\t| \"file-invalid-type\"\n\t| \"file-too-large\"\n\t| \"too-many-files\";\n\ntype FilePickerError = {\n\tcode: FilePickerErrorCode;\n\tmessage: string;\n};\n\ntype FileRejection = {\n\tfile: File;\n\terrors: FilePickerError[];\n};\n\ntype FilePickerResult = {\n\tacceptedFiles: File[];\n\trejectedFiles: FileRejection[];\n};\n\ntype UseFilePickerOptions = {\n\taccept?: string;\n\tdisabled?: boolean;\n\tmaxFiles?: number;\n\tmaxSize?: number;\n\tmultiple?: boolean;\n\tonFilesAccepted?: (files: File[]) => void;\n\tonFilesChange?: (result: FilePickerResult) => void;\n\tonFilesRejected?: (rejectedFiles: FileRejection[]) => void;\n};\n\ntype FilePickerInputProps = Omit<\n\tComponentPropsWithoutRef<\"input\">,\n\t\"type\" | \"accept\" | \"multiple\"\n> & {\n\taccept?: string;\n\tmultiple?: boolean;\n\tref?: Ref<HTMLInputElement>;\n};\n\ntype UseFilePickerReturn = {\n\tgetInputProps: (props?: FilePickerInputProps) => FilePickerInputProps & {\n\t\ttype: \"file\";\n\t\tref: Ref<HTMLInputElement>;\n\t};\n\thandleDragEnter: (event: DragEvent<HTMLElement>) => void;\n\thandleDragLeave: (event: DragEvent<HTMLElement>) => void;\n\thandleDragOver: (event: DragEvent<HTMLElement>) => void;\n\thandleDrop: (event: DragEvent<HTMLElement>) => void;\n\thandleFileChange: (event: ChangeEvent<HTMLInputElement>) => void;\n\tinputRef: RefObject<HTMLInputElement | null>;\n\tisDragging: boolean;\n\topenFileDialog: () => void;\n\tpickFiles: (files: FileList | File[]) => FilePickerResult;\n};\n\nfunction useFilePicker({\n\taccept = \"*\",\n\tdisabled = false,\n\tmaxFiles = Number.POSITIVE_INFINITY,\n\tmaxSize = Number.POSITIVE_INFINITY,\n\tmultiple = false,\n\tonFilesAccepted,\n\tonFilesChange,\n\tonFilesRejected,\n}: UseFilePickerOptions = {}): UseFilePickerReturn {\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst dragDepthRef = useRef(0);\n\tconst [isDragging, setIsDragging] = useState(false);\n\n\tconst pickFiles = useCallback(\n\t\t(files: FileList | File[]): FilePickerResult => {\n\t\t\tconst incomingFiles = Array.from(files);\n\t\t\tconst limit = multiple ? maxFiles : 1;\n\t\t\tconst acceptedFiles: File[] = [];\n\t\t\tconst rejectedFiles: FileRejection[] = [];\n\n\t\t\tif (incomingFiles.length === 0 || disabled) {\n\t\t\t\treturn { acceptedFiles, rejectedFiles };\n\t\t\t}\n\n\t\t\tfor (const [index, file] of incomingFiles.entries()) {\n\t\t\t\tconst errors: FilePickerError[] = [];\n\n\t\t\t\tif (index >= limit) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"too-many-files\",\n\t\t\t\t\t\tmessage: multiple\n\t\t\t\t\t\t\t? `You can only select up to ${limit} files.`\n\t\t\t\t\t\t\t: \"You can only select one file.\",\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\terrors.push(...validateFile(file, { accept, maxSize }));\n\t\t\t\t}\n\n\t\t\t\tif (errors.length > 0) {\n\t\t\t\t\trejectedFiles.push({ file, errors });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tacceptedFiles.push(file);\n\t\t\t}\n\n\t\t\tconst result = { acceptedFiles, rejectedFiles };\n\n\t\t\tif (acceptedFiles.length > 0) {\n\t\t\t\tonFilesAccepted?.(acceptedFiles);\n\t\t\t}\n\n\t\t\tif (rejectedFiles.length > 0) {\n\t\t\t\tonFilesRejected?.(rejectedFiles);\n\t\t\t}\n\n\t\t\tonFilesChange?.(result);\n\n\t\t\tif (inputRef.current) {\n\t\t\t\tinputRef.current.value = \"\";\n\t\t\t}\n\n\t\t\treturn result;\n\t\t},\n\t\t[\n\t\t\taccept,\n\t\t\tdisabled,\n\t\t\tmaxFiles,\n\t\t\tmaxSize,\n\t\t\tmultiple,\n\t\t\tonFilesAccepted,\n\t\t\tonFilesChange,\n\t\t\tonFilesRejected,\n\t\t],\n\t);\n\n\tconst handleFileChange = useCallback(\n\t\t(event: ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (event.target.files) {\n\t\t\t\tpickFiles(event.target.files);\n\t\t\t}\n\t\t},\n\t\t[pickFiles],\n\t);\n\n\tconst openFileDialog = useCallback(() => {\n\t\tif (disabled) return;\n\t\tinputRef.current?.click();\n\t}, [disabled]);\n\n\tconst handleDragEnter = useCallback(\n\t\t(event: DragEvent<HTMLElement>) => {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tif (disabled) return;\n\n\t\t\tdragDepthRef.current += 1;\n\t\t\tsetIsDragging(true);\n\t\t},\n\t\t[disabled],\n\t);\n\n\tconst handleDragLeave = useCallback(\n\t\t(event: DragEvent<HTMLElement>) => {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tif (disabled) return;\n\n\t\t\tdragDepthRef.current = Math.max(0, dragDepthRef.current - 1);\n\t\t\tif (dragDepthRef.current === 0) {\n\t\t\t\tsetIsDragging(false);\n\t\t\t}\n\t\t},\n\t\t[disabled],\n\t);\n\n\tconst handleDragOver = useCallback((event: DragEvent<HTMLElement>) => {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t}, []);\n\n\tconst handleDrop = useCallback(\n\t\t(event: DragEvent<HTMLElement>) => {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tdragDepthRef.current = 0;\n\t\t\tsetIsDragging(false);\n\n\t\t\tif (event.dataTransfer.files.length > 0) {\n\t\t\t\tpickFiles(event.dataTransfer.files);\n\t\t\t}\n\t\t},\n\t\t[pickFiles],\n\t);\n\n\tconst getInputProps = useCallback(\n\t\t(props: FilePickerInputProps = {}) => {\n\t\t\tconst { onChange, ref, ...inputProps } = props;\n\n\t\t\treturn {\n\t\t\t\t...inputProps,\n\t\t\t\ttype: \"file\" as const,\n\t\t\t\taccept: inputProps.accept ?? accept,\n\t\t\t\tdisabled: inputProps.disabled ?? disabled,\n\t\t\t\tmultiple: inputProps.multiple ?? multiple,\n\t\t\t\tref: (node: HTMLInputElement | null) => {\n\t\t\t\t\tinputRef.current = node;\n\t\t\t\t\tassignRef(ref, node);\n\t\t\t\t},\n\t\t\t\tonChange: (event: ChangeEvent<HTMLInputElement>) => {\n\t\t\t\t\tonChange?.(event);\n\t\t\t\t\tif (!event.defaultPrevented) {\n\t\t\t\t\t\thandleFileChange(event);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t[accept, disabled, handleFileChange, multiple],\n\t);\n\n\treturn {\n\t\tgetInputProps,\n\t\thandleDragEnter,\n\t\thandleDragLeave,\n\t\thandleDragOver,\n\t\thandleDrop,\n\t\thandleFileChange,\n\t\tinputRef,\n\t\tisDragging,\n\t\topenFileDialog,\n\t\tpickFiles,\n\t};\n}\n\nfunction validateFile(\n\tfile: File,\n\toptions: Pick<UseFilePickerOptions, \"accept\" | \"maxSize\"> = {},\n): FilePickerError[] {\n\tconst { accept = \"*\", maxSize = Number.POSITIVE_INFINITY } = options;\n\tconst errors: FilePickerError[] = [];\n\n\tif (file.size > maxSize) {\n\t\terrors.push({\n\t\t\tcode: \"file-too-large\",\n\t\t\tmessage: `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`,\n\t\t});\n\t}\n\n\tif (!isAcceptedFile(file, accept)) {\n\t\terrors.push({\n\t\t\tcode: \"file-invalid-type\",\n\t\t\tmessage: `File \"${file.name}\" is not an accepted file type.`,\n\t\t});\n\t}\n\n\treturn errors;\n}\n\nfunction isAcceptedFile(file: File, accept = \"*\") {\n\tif (accept === \"*\" || accept.trim() === \"\") return true;\n\n\tconst acceptedTypes = accept\n\t\t.split(\",\")\n\t\t.map((type) => type.trim().toLowerCase())\n\t\t.filter(Boolean);\n\n\tif (acceptedTypes.length === 0) return true;\n\n\tconst fileType = file.type.toLowerCase();\n\tconst fileExtension = getFileExtension(file.name);\n\n\treturn acceptedTypes.some((acceptedType) => {\n\t\tif (acceptedType.startsWith(\".\")) {\n\t\t\treturn fileExtension === acceptedType;\n\t\t}\n\n\t\tif (acceptedType.endsWith(\"/*\")) {\n\t\t\treturn fileType.startsWith(acceptedType.slice(0, -1));\n\t\t}\n\n\t\treturn fileType === acceptedType;\n\t});\n}\n\nfunction formatBytes(bytes: number, decimals = 2): string {\n\tif (bytes === 0) return \"0 Bytes\";\n\tif (!Number.isFinite(bytes)) return \"unlimited\";\n\n\tconst unit = 1024;\n\tconst precision = Math.max(0, decimals);\n\tconst sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n\tconst sizeIndex = Math.min(\n\t\tMath.floor(Math.log(bytes) / Math.log(unit)),\n\t\tsizes.length - 1,\n\t);\n\n\treturn `${Number.parseFloat((bytes / unit ** sizeIndex).toFixed(precision))} ${sizes[sizeIndex]}`;\n}\n\nfunction getFileExtension(fileName: string) {\n\tconst extension = fileName.toLowerCase().split(\".\").pop();\n\treturn extension && extension !== fileName.toLowerCase()\n\t\t? `.${extension}`\n\t\t: \"\";\n}\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n\tif (!ref) return;\n\n\tif (typeof ref === \"function\") {\n\t\tref(value);\n\t\treturn;\n\t}\n\n\tref.current = value;\n}\n\nexport { formatBytes, isAcceptedFile, useFilePicker, validateFile };\nexport type {\n\tFilePickerError,\n\tFilePickerErrorCode,\n\tFilePickerInputProps,\n\tFilePickerResult,\n\tFileRejection,\n\tUseFilePickerOptions,\n\tUseFilePickerReturn,\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,17 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import { VariantProps } from 'class-variance-authority';
3
+ import * as React from 'react';
4
+
5
+ declare function Empty({ className, variant, ...props }: React.ComponentProps<"div"> & {
6
+ variant?: "filled" | "outline" | "default";
7
+ }): React.JSX.Element;
8
+ declare function EmptyHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
9
+ declare const emptyMediaVariants: (props?: ({
10
+ variant?: "default" | "icon" | null | undefined;
11
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
12
+ declare function EmptyMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>): React.JSX.Element;
13
+ declare function EmptyTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
14
+ declare function EmptyDescription({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
15
+ declare function EmptyContent({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
16
+
17
+ export { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle };