@giddaa-housing/ui 1.0.0 → 1.2.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 (331) hide show
  1. package/css/generated/shared.css +1 -1
  2. package/css/giddaa.css +12 -2
  3. package/dist/accordion.d.ts +9 -10
  4. package/dist/accordion.js +41 -87
  5. package/dist/activity-timeline.d.ts +12 -16
  6. package/dist/activity-timeline.js +83 -198
  7. package/dist/alert.d.ts +8 -9
  8. package/dist/alert.js +53 -111
  9. package/dist/auth-layout.d.ts +4 -4
  10. package/dist/auth-layout.js +143 -294
  11. package/dist/avatar.d.ts +6 -6
  12. package/dist/avatar.js +49 -19
  13. package/dist/badge.d.ts +12 -14
  14. package/dist/badge.js +71 -11
  15. package/dist/bar-chart.d.ts +65 -67
  16. package/dist/bar-chart.js +232 -207
  17. package/dist/breadcrumb.d.ts +5 -5
  18. package/dist/breadcrumb.js +56 -118
  19. package/dist/bullet-chart.d.ts +41 -37
  20. package/dist/bullet-chart.js +125 -148
  21. package/dist/button-BZIeyUw6.d.ts +17 -0
  22. package/dist/button-group.d.ts +13 -16
  23. package/dist/button-group.js +39 -88
  24. package/dist/button.d.ts +2 -19
  25. package/dist/button.js +94 -13
  26. package/dist/calendar.d.ts +6 -6
  27. package/dist/calendar.js +138 -17
  28. package/dist/card.d.ts +14 -16
  29. package/dist/card.js +59 -145
  30. package/dist/carousel.d.ts +34 -35
  31. package/dist/carousel.js +335 -20
  32. package/dist/chart.d.ts +90 -63
  33. package/dist/chart.js +573 -28
  34. package/dist/checkbox.d.ts +10 -12
  35. package/dist/checkbox.js +82 -47
  36. package/dist/cn-BI_4DMBf.js +23 -0
  37. package/dist/collapsible.d.ts +7 -8
  38. package/dist/collapsible.js +22 -47
  39. package/dist/combobox.d.ts +10 -10
  40. package/dist/combobox.js +236 -44
  41. package/dist/cta.d.ts +12 -14
  42. package/dist/cta.js +175 -341
  43. package/dist/currency-selector.d.ts +31 -32
  44. package/dist/currency-selector.js +106 -184
  45. package/dist/data-table.d.ts +168 -0
  46. package/dist/data-table.js +676 -0
  47. package/dist/date-picker.d.ts +22 -23
  48. package/dist/date-picker.js +119 -192
  49. package/dist/details-card.d.ts +7 -7
  50. package/dist/details-card.js +104 -253
  51. package/dist/dialog.d.ts +13 -14
  52. package/dist/dialog.js +116 -209
  53. package/dist/dropdown-menu.d.ts +13 -13
  54. package/dist/dropdown-menu.js +180 -37
  55. package/dist/dropzone.d.ts +55 -55
  56. package/dist/dropzone.js +327 -439
  57. package/dist/editorial-card.d.ts +23 -25
  58. package/dist/editorial-card.js +129 -296
  59. package/dist/empty-state.d.ts +8 -9
  60. package/dist/empty-state.js +48 -105
  61. package/dist/field.d.ts +23 -25
  62. package/dist/field.js +110 -221
  63. package/dist/filter.d.ts +118 -0
  64. package/dist/filter.js +775 -0
  65. package/dist/footer.d.ts +8 -15
  66. package/dist/footer.js +197 -400
  67. package/dist/funnel-chart.d.ts +49 -48
  68. package/dist/funnel-chart.js +170 -189
  69. package/dist/gallery-indicator.d.ts +11 -12
  70. package/dist/gallery-indicator.js +75 -12
  71. package/dist/heatmap-chart.d.ts +47 -50
  72. package/dist/heatmap-chart.js +186 -237
  73. package/dist/infotip.d.ts +8 -9
  74. package/dist/infotip.js +33 -59
  75. package/dist/input-CfoEJ8A6.d.ts +12 -0
  76. package/dist/input-group.d.ts +16 -20
  77. package/dist/input-group.js +99 -23
  78. package/dist/input-size-context-C-SFx9sx.d.ts +10 -0
  79. package/dist/input-size-context.d.ts +2 -11
  80. package/dist/input-size-context.js +17 -9
  81. package/dist/input.d.ts +2 -13
  82. package/dist/input.js +27 -11
  83. package/dist/item.d.ts +7 -8
  84. package/dist/item.js +22 -59
  85. package/dist/kpi-card.d.ts +18 -20
  86. package/dist/kpi-card.js +84 -192
  87. package/dist/label.d.ts +6 -6
  88. package/dist/label.js +40 -8
  89. package/dist/line-chart.d.ts +200 -129
  90. package/dist/line-chart.js +330 -105
  91. package/dist/list-item.d.ts +22 -0
  92. package/dist/list-item.js +84 -0
  93. package/dist/logo.d.ts +4 -4
  94. package/dist/logo.js +92 -9
  95. package/dist/map-indicator.d.ts +7 -7
  96. package/dist/map-indicator.js +80 -106
  97. package/dist/match.d.ts +10 -11
  98. package/dist/match.js +62 -107
  99. package/dist/media-gallery-hero.d.ts +40 -42
  100. package/dist/media-gallery-hero.js +182 -343
  101. package/dist/media-player.d.ts +17 -17
  102. package/dist/media-player.js +873 -1348
  103. package/dist/multi-step-form.d.ts +56 -0
  104. package/dist/multi-step-form.js +342 -0
  105. package/dist/number-input.d.ts +34 -34
  106. package/dist/number-input.js +64 -117
  107. package/dist/page-header.d.ts +10 -11
  108. package/dist/page-header.js +34 -79
  109. package/dist/pagination.d.ts +17 -21
  110. package/dist/pagination.js +132 -207
  111. package/dist/password-input.d.ts +5 -13
  112. package/dist/password-input.js +31 -55
  113. package/dist/phone-input.d.ts +19 -20
  114. package/dist/phone-input.js +226 -344
  115. package/dist/photo-gallery.d.ts +19 -19
  116. package/dist/photo-gallery.js +313 -449
  117. package/dist/picker-lzgmsNfG.js +32 -0
  118. package/dist/pie-chart.d.ts +121 -90
  119. package/dist/pie-chart.js +183 -149
  120. package/dist/popover.d.ts +9 -9
  121. package/dist/popover.js +72 -23
  122. package/dist/price-tag.d.ts +26 -27
  123. package/dist/price-tag.js +113 -173
  124. package/dist/progress.d.ts +16 -17
  125. package/dist/progress.js +169 -24
  126. package/dist/property-listing-card.d.ts +14 -17
  127. package/dist/property-listing-card.js +102 -220
  128. package/dist/purchase-option-card.d.ts +79 -0
  129. package/dist/purchase-option-card.js +176 -0
  130. package/dist/radar-chart.d.ts +29 -31
  131. package/dist/radar-chart.js +162 -137
  132. package/dist/radio-group.d.ts +11 -13
  133. package/dist/radio-group.js +46 -60
  134. package/dist/review-block.d.ts +14 -16
  135. package/dist/review-block.js +154 -10
  136. package/dist/rich-text-editor.d.ts +30 -14
  137. package/dist/rich-text-editor.js +592 -716
  138. package/dist/scatter-chart.d.ts +45 -47
  139. package/dist/scatter-chart.js +236 -240
  140. package/dist/search-input.d.ts +8 -16
  141. package/dist/search-input.js +57 -109
  142. package/dist/select.d.ts +8 -8
  143. package/dist/select.js +144 -27
  144. package/dist/separator.d.ts +8 -9
  145. package/dist/separator.js +32 -8
  146. package/dist/sheet.d.ts +11 -11
  147. package/dist/sheet.js +103 -24
  148. package/dist/sidebar.d.ts +32 -37
  149. package/dist/sidebar.js +364 -634
  150. package/dist/size-context-D4mYvcg8.d.ts +10 -0
  151. package/dist/size-context.d.ts +2 -11
  152. package/dist/size-context.js +17 -9
  153. package/dist/skeleton.d.ts +4 -5
  154. package/dist/skeleton.js +12 -8
  155. package/dist/slider.d.ts +8 -9
  156. package/dist/slider.js +64 -135
  157. package/dist/sparkline.d.ts +68 -58
  158. package/dist/sparkline.js +315 -251
  159. package/dist/stepper.d.ts +23 -24
  160. package/dist/stepper.js +149 -246
  161. package/dist/styles.css +1004 -116
  162. package/dist/switch.d.ts +10 -12
  163. package/dist/switch.js +48 -70
  164. package/dist/table-card.d.ts +35 -0
  165. package/dist/table-card.js +125 -0
  166. package/dist/table.d.ts +18 -14
  167. package/dist/table.js +117 -154
  168. package/dist/tabs.d.ts +33 -15
  169. package/dist/tabs.js +110 -18
  170. package/dist/tag.d.ts +21 -23
  171. package/dist/tag.js +103 -159
  172. package/dist/testimonial-block.d.ts +18 -19
  173. package/dist/testimonial-block.js +189 -358
  174. package/dist/textarea-IS_D8pXf.d.ts +11 -0
  175. package/dist/textarea.d.ts +2 -12
  176. package/dist/textarea.js +24 -11
  177. package/dist/time-picker.d.ts +11 -11
  178. package/dist/time-picker.js +245 -302
  179. package/dist/toast.d.ts +16 -18
  180. package/dist/toast.js +154 -205
  181. package/dist/tooltip.d.ts +8 -9
  182. package/dist/tooltip.js +37 -12
  183. package/dist/tree-map.d.ts +59 -62
  184. package/dist/tree-map.js +226 -269
  185. package/dist/use-uncontrolled-CLfM1XbB.js +21 -0
  186. package/dist/waterfall-chart.d.ts +94 -97
  187. package/dist/waterfall-chart.js +455 -552
  188. package/package.json +36 -9
  189. package/dist/accordion.js.map +0 -1
  190. package/dist/activity-timeline.js.map +0 -1
  191. package/dist/alert.js.map +0 -1
  192. package/dist/auth-layout.js.map +0 -1
  193. package/dist/avatar.js.map +0 -1
  194. package/dist/badge.js.map +0 -1
  195. package/dist/bar-chart.js.map +0 -1
  196. package/dist/breadcrumb.js.map +0 -1
  197. package/dist/bullet-chart.js.map +0 -1
  198. package/dist/button-group.js.map +0 -1
  199. package/dist/button.js.map +0 -1
  200. package/dist/calendar.js.map +0 -1
  201. package/dist/card.js.map +0 -1
  202. package/dist/carousel.js.map +0 -1
  203. package/dist/chart.js.map +0 -1
  204. package/dist/checkbox.js.map +0 -1
  205. package/dist/chunk-322YCNVL.js +0 -278
  206. package/dist/chunk-322YCNVL.js.map +0 -1
  207. package/dist/chunk-3ACQVT7A.js +0 -25
  208. package/dist/chunk-3ACQVT7A.js.map +0 -1
  209. package/dist/chunk-3T65TLJX.js +0 -334
  210. package/dist/chunk-3T65TLJX.js.map +0 -1
  211. package/dist/chunk-6ZSGQHH2.js +0 -192
  212. package/dist/chunk-6ZSGQHH2.js.map +0 -1
  213. package/dist/chunk-7TBMLFGW.js +0 -41
  214. package/dist/chunk-7TBMLFGW.js.map +0 -1
  215. package/dist/chunk-B4H6RNDH.js +0 -135
  216. package/dist/chunk-B4H6RNDH.js.map +0 -1
  217. package/dist/chunk-BUXCGZ6X.js +0 -219
  218. package/dist/chunk-BUXCGZ6X.js.map +0 -1
  219. package/dist/chunk-CHII2QHH.js +0 -58
  220. package/dist/chunk-CHII2QHH.js.map +0 -1
  221. package/dist/chunk-DMNOXRRW.js +0 -147
  222. package/dist/chunk-DMNOXRRW.js.map +0 -1
  223. package/dist/chunk-EFSOSSIC.js +0 -130
  224. package/dist/chunk-EFSOSSIC.js.map +0 -1
  225. package/dist/chunk-FZDSVMKY.js +0 -363
  226. package/dist/chunk-FZDSVMKY.js.map +0 -1
  227. package/dist/chunk-GJOFIJS3.js +0 -246
  228. package/dist/chunk-GJOFIJS3.js.map +0 -1
  229. package/dist/chunk-HL3ZSYES.js +0 -23
  230. package/dist/chunk-HL3ZSYES.js.map +0 -1
  231. package/dist/chunk-JVLUBAPB.js +0 -129
  232. package/dist/chunk-JVLUBAPB.js.map +0 -1
  233. package/dist/chunk-KDPYSOYZ.js +0 -64
  234. package/dist/chunk-KDPYSOYZ.js.map +0 -1
  235. package/dist/chunk-KSMDANKI.js +0 -43
  236. package/dist/chunk-KSMDANKI.js.map +0 -1
  237. package/dist/chunk-MEKCCOP5.js +0 -46
  238. package/dist/chunk-MEKCCOP5.js.map +0 -1
  239. package/dist/chunk-NOFXVRWL.js +0 -451
  240. package/dist/chunk-NOFXVRWL.js.map +0 -1
  241. package/dist/chunk-PC5MHNVA.js +0 -171
  242. package/dist/chunk-PC5MHNVA.js.map +0 -1
  243. package/dist/chunk-QKAQZ2GU.js +0 -122
  244. package/dist/chunk-QKAQZ2GU.js.map +0 -1
  245. package/dist/chunk-QZHSHSVV.js +0 -26
  246. package/dist/chunk-QZHSHSVV.js.map +0 -1
  247. package/dist/chunk-RBMK26XD.js +0 -19
  248. package/dist/chunk-RBMK26XD.js.map +0 -1
  249. package/dist/chunk-SFNJGF6M.js +0 -262
  250. package/dist/chunk-SFNJGF6M.js.map +0 -1
  251. package/dist/chunk-UJJNLGTM.js +0 -112
  252. package/dist/chunk-UJJNLGTM.js.map +0 -1
  253. package/dist/chunk-VGR4ZWJ3.js +0 -418
  254. package/dist/chunk-VGR4ZWJ3.js.map +0 -1
  255. package/dist/chunk-XG47P6D4.js +0 -99
  256. package/dist/chunk-XG47P6D4.js.map +0 -1
  257. package/dist/chunk-XZZAHNVM.js +0 -21
  258. package/dist/chunk-XZZAHNVM.js.map +0 -1
  259. package/dist/chunk-Y4TTYVNE.js +0 -36
  260. package/dist/chunk-Y4TTYVNE.js.map +0 -1
  261. package/dist/chunk-YDWIHW6Q.js +0 -69
  262. package/dist/chunk-YDWIHW6Q.js.map +0 -1
  263. package/dist/collapsible.js.map +0 -1
  264. package/dist/combobox.js.map +0 -1
  265. package/dist/cta.js.map +0 -1
  266. package/dist/currency-selector.js.map +0 -1
  267. package/dist/date-picker.js.map +0 -1
  268. package/dist/details-card.js.map +0 -1
  269. package/dist/dialog.js.map +0 -1
  270. package/dist/dropdown-menu.js.map +0 -1
  271. package/dist/dropzone.js.map +0 -1
  272. package/dist/editorial-card.js.map +0 -1
  273. package/dist/empty-state.js.map +0 -1
  274. package/dist/field.js.map +0 -1
  275. package/dist/footer.js.map +0 -1
  276. package/dist/funnel-chart.js.map +0 -1
  277. package/dist/gallery-indicator.js.map +0 -1
  278. package/dist/heatmap-chart.js.map +0 -1
  279. package/dist/infotip.js.map +0 -1
  280. package/dist/input-group.js.map +0 -1
  281. package/dist/input-size-context.js.map +0 -1
  282. package/dist/input.js.map +0 -1
  283. package/dist/item.js.map +0 -1
  284. package/dist/kpi-card.js.map +0 -1
  285. package/dist/label.js.map +0 -1
  286. package/dist/line-chart.js.map +0 -1
  287. package/dist/logo.js.map +0 -1
  288. package/dist/map-indicator.js.map +0 -1
  289. package/dist/match.js.map +0 -1
  290. package/dist/media-gallery-hero.js.map +0 -1
  291. package/dist/media-player.js.map +0 -1
  292. package/dist/number-input.js.map +0 -1
  293. package/dist/page-header.js.map +0 -1
  294. package/dist/pagination.js.map +0 -1
  295. package/dist/password-input.js.map +0 -1
  296. package/dist/phone-input.js.map +0 -1
  297. package/dist/photo-gallery.js.map +0 -1
  298. package/dist/pie-chart.js.map +0 -1
  299. package/dist/popover.js.map +0 -1
  300. package/dist/price-tag.js.map +0 -1
  301. package/dist/progress.js.map +0 -1
  302. package/dist/property-listing-card.js.map +0 -1
  303. package/dist/radar-chart.js.map +0 -1
  304. package/dist/radio-group.js.map +0 -1
  305. package/dist/review-block.js.map +0 -1
  306. package/dist/rich-text-editor.js.map +0 -1
  307. package/dist/scatter-chart.js.map +0 -1
  308. package/dist/search-input.js.map +0 -1
  309. package/dist/select.js.map +0 -1
  310. package/dist/separator.js.map +0 -1
  311. package/dist/sheet.js.map +0 -1
  312. package/dist/sidebar.js.map +0 -1
  313. package/dist/size-context.js.map +0 -1
  314. package/dist/skeleton.js.map +0 -1
  315. package/dist/slider.js.map +0 -1
  316. package/dist/sparkline.js.map +0 -1
  317. package/dist/stepper.js.map +0 -1
  318. package/dist/switch.js.map +0 -1
  319. package/dist/tab-list.d.ts +0 -38
  320. package/dist/tab-list.js +0 -123
  321. package/dist/tab-list.js.map +0 -1
  322. package/dist/table.js.map +0 -1
  323. package/dist/tabs.js.map +0 -1
  324. package/dist/tag.js.map +0 -1
  325. package/dist/testimonial-block.js.map +0 -1
  326. package/dist/textarea.js.map +0 -1
  327. package/dist/time-picker.js.map +0 -1
  328. package/dist/toast.js.map +0 -1
  329. package/dist/tooltip.js.map +0 -1
  330. package/dist/tree-map.js.map +0 -1
  331. package/dist/waterfall-chart.js.map +0 -1
package/dist/dropzone.js CHANGED
@@ -1,463 +1,351 @@
1
1
  "use client";
2
- import {
3
- cn
4
- } from "./chunk-Y4TTYVNE.js";
5
-
6
- // src/dropzone.tsx
2
+ import { t as cn } from "./cn-BI_4DMBf.js";
7
3
  import { UploadCloud } from "lucide-react";
8
- import {
9
- createContext,
10
- use
11
- } from "react";
12
-
13
- // src/lib/use-file-picker.ts
14
- import {
15
- useCallback,
16
- useRef,
17
- useState
18
- } from "react";
19
- function useFilePicker({
20
- accept = "*",
21
- disabled = false,
22
- maxFiles = Number.POSITIVE_INFINITY,
23
- maxSize = Number.POSITIVE_INFINITY,
24
- multiple = false,
25
- onFilesAccepted,
26
- onFilesChange,
27
- onFilesRejected
28
- } = {}) {
29
- const inputRef = useRef(null);
30
- const dragDepthRef = useRef(0);
31
- const [isDragging, setIsDragging] = useState(false);
32
- const pickFiles = useCallback(
33
- (files) => {
34
- const incomingFiles = Array.from(files);
35
- const limit = multiple ? maxFiles : 1;
36
- const acceptedFiles = [];
37
- const rejectedFiles = [];
38
- if (incomingFiles.length === 0 || disabled) {
39
- return { acceptedFiles, rejectedFiles };
40
- }
41
- for (const [index, file] of incomingFiles.entries()) {
42
- const errors = [];
43
- if (index >= limit) {
44
- errors.push({
45
- code: "too-many-files",
46
- message: multiple ? `You can only select up to ${limit} files.` : "You can only select one file."
47
- });
48
- } else {
49
- errors.push(...validateFile(file, { accept, maxSize }));
50
- }
51
- if (errors.length > 0) {
52
- rejectedFiles.push({ file, errors });
53
- continue;
54
- }
55
- acceptedFiles.push(file);
56
- }
57
- const result = { acceptedFiles, rejectedFiles };
58
- if (acceptedFiles.length > 0) {
59
- onFilesAccepted?.(acceptedFiles);
60
- }
61
- if (rejectedFiles.length > 0) {
62
- onFilesRejected?.(rejectedFiles);
63
- }
64
- onFilesChange?.(result);
65
- if (inputRef.current) {
66
- inputRef.current.value = "";
67
- }
68
- return result;
69
- },
70
- [
71
- accept,
72
- disabled,
73
- maxFiles,
74
- maxSize,
75
- multiple,
76
- onFilesAccepted,
77
- onFilesChange,
78
- onFilesRejected
79
- ]
80
- );
81
- const handleFileChange = useCallback(
82
- (event) => {
83
- if (event.target.files) {
84
- pickFiles(event.target.files);
85
- }
86
- },
87
- [pickFiles]
88
- );
89
- const openFileDialog = useCallback(() => {
90
- if (disabled) return;
91
- inputRef.current?.click();
92
- }, [disabled]);
93
- const handleDragEnter = useCallback(
94
- (event) => {
95
- event.preventDefault();
96
- event.stopPropagation();
97
- if (disabled) return;
98
- dragDepthRef.current += 1;
99
- setIsDragging(true);
100
- },
101
- [disabled]
102
- );
103
- const handleDragLeave = useCallback(
104
- (event) => {
105
- event.preventDefault();
106
- event.stopPropagation();
107
- if (disabled) return;
108
- dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
109
- if (dragDepthRef.current === 0) {
110
- setIsDragging(false);
111
- }
112
- },
113
- [disabled]
114
- );
115
- const handleDragOver = useCallback((event) => {
116
- event.preventDefault();
117
- event.stopPropagation();
118
- }, []);
119
- const handleDrop = useCallback(
120
- (event) => {
121
- event.preventDefault();
122
- event.stopPropagation();
123
- dragDepthRef.current = 0;
124
- setIsDragging(false);
125
- if (event.dataTransfer.files.length > 0) {
126
- pickFiles(event.dataTransfer.files);
127
- }
128
- },
129
- [pickFiles]
130
- );
131
- const getInputProps = useCallback(
132
- (props = {}) => {
133
- const { onChange, ref, ...inputProps } = props;
134
- return {
135
- ...inputProps,
136
- type: "file",
137
- accept: inputProps.accept ?? accept,
138
- disabled: inputProps.disabled ?? disabled,
139
- multiple: inputProps.multiple ?? multiple,
140
- ref: (node) => {
141
- inputRef.current = node;
142
- assignRef(ref, node);
143
- },
144
- onChange: (event) => {
145
- onChange?.(event);
146
- if (!event.defaultPrevented) {
147
- handleFileChange(event);
148
- }
149
- }
150
- };
151
- },
152
- [accept, disabled, handleFileChange, multiple]
153
- );
154
- return {
155
- getInputProps,
156
- handleDragEnter,
157
- handleDragLeave,
158
- handleDragOver,
159
- handleDrop,
160
- handleFileChange,
161
- inputRef,
162
- isDragging,
163
- openFileDialog,
164
- pickFiles
165
- };
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { createContext, use, useCallback, useRef, useState } from "react";
6
+ //#region src/lib/use-file-picker.ts
7
+ function useFilePicker({ accept = "*", disabled = false, maxFiles = Number.POSITIVE_INFINITY, maxSize = Number.POSITIVE_INFINITY, multiple = false, onFilesAccepted, onFilesChange, onFilesRejected } = {}) {
8
+ const inputRef = useRef(null);
9
+ const dragDepthRef = useRef(0);
10
+ const [isDragging, setIsDragging] = useState(false);
11
+ const pickFiles = useCallback((files) => {
12
+ const incomingFiles = Array.from(files);
13
+ const limit = multiple ? maxFiles : 1;
14
+ const acceptedFiles = [];
15
+ const rejectedFiles = [];
16
+ if (incomingFiles.length === 0 || disabled) return {
17
+ acceptedFiles,
18
+ rejectedFiles
19
+ };
20
+ for (const [index, file] of incomingFiles.entries()) {
21
+ const errors = [];
22
+ if (index >= limit) errors.push({
23
+ code: "too-many-files",
24
+ message: multiple ? `You can only select up to ${limit} files.` : "You can only select one file."
25
+ });
26
+ else errors.push(...validateFile(file, {
27
+ accept,
28
+ maxSize
29
+ }));
30
+ if (errors.length > 0) {
31
+ rejectedFiles.push({
32
+ file,
33
+ errors
34
+ });
35
+ continue;
36
+ }
37
+ acceptedFiles.push(file);
38
+ }
39
+ const result = {
40
+ acceptedFiles,
41
+ rejectedFiles
42
+ };
43
+ if (acceptedFiles.length > 0) onFilesAccepted?.(acceptedFiles);
44
+ if (rejectedFiles.length > 0) onFilesRejected?.(rejectedFiles);
45
+ onFilesChange?.(result);
46
+ if (inputRef.current) inputRef.current.value = "";
47
+ return result;
48
+ }, [
49
+ accept,
50
+ disabled,
51
+ maxFiles,
52
+ maxSize,
53
+ multiple,
54
+ onFilesAccepted,
55
+ onFilesChange,
56
+ onFilesRejected
57
+ ]);
58
+ const handleFileChange = useCallback((event) => {
59
+ if (event.target.files) pickFiles(event.target.files);
60
+ }, [pickFiles]);
61
+ const openFileDialog = useCallback(() => {
62
+ if (disabled) return;
63
+ inputRef.current?.click();
64
+ }, [disabled]);
65
+ const handleDragEnter = useCallback((event) => {
66
+ event.preventDefault();
67
+ event.stopPropagation();
68
+ if (disabled) return;
69
+ dragDepthRef.current += 1;
70
+ setIsDragging(true);
71
+ }, [disabled]);
72
+ const handleDragLeave = useCallback((event) => {
73
+ event.preventDefault();
74
+ event.stopPropagation();
75
+ if (disabled) return;
76
+ dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
77
+ if (dragDepthRef.current === 0) setIsDragging(false);
78
+ }, [disabled]);
79
+ const handleDragOver = useCallback((event) => {
80
+ event.preventDefault();
81
+ event.stopPropagation();
82
+ }, []);
83
+ const handleDrop = useCallback((event) => {
84
+ event.preventDefault();
85
+ event.stopPropagation();
86
+ dragDepthRef.current = 0;
87
+ setIsDragging(false);
88
+ if (event.dataTransfer.files.length > 0) pickFiles(event.dataTransfer.files);
89
+ }, [pickFiles]);
90
+ return {
91
+ getInputProps: useCallback((props = {}) => {
92
+ const { onChange, ref, ...inputProps } = props;
93
+ return {
94
+ ...inputProps,
95
+ type: "file",
96
+ accept: inputProps.accept ?? accept,
97
+ disabled: inputProps.disabled ?? disabled,
98
+ multiple: inputProps.multiple ?? multiple,
99
+ ref: (node) => {
100
+ inputRef.current = node;
101
+ assignRef(ref, node);
102
+ },
103
+ onChange: (event) => {
104
+ onChange?.(event);
105
+ if (!event.defaultPrevented) handleFileChange(event);
106
+ }
107
+ };
108
+ }, [
109
+ accept,
110
+ disabled,
111
+ handleFileChange,
112
+ multiple
113
+ ]),
114
+ handleDragEnter,
115
+ handleDragLeave,
116
+ handleDragOver,
117
+ handleDrop,
118
+ handleFileChange,
119
+ inputRef,
120
+ isDragging,
121
+ openFileDialog,
122
+ pickFiles
123
+ };
166
124
  }
167
125
  function validateFile(file, options = {}) {
168
- const { accept = "*", maxSize = Number.POSITIVE_INFINITY } = options;
169
- const errors = [];
170
- if (file.size > maxSize) {
171
- errors.push({
172
- code: "file-too-large",
173
- message: `File "${file.name}" exceeds the maximum size of ${formatBytes(maxSize)}.`
174
- });
175
- }
176
- if (!isAcceptedFile(file, accept)) {
177
- errors.push({
178
- code: "file-invalid-type",
179
- message: `File "${file.name}" is not an accepted file type.`
180
- });
181
- }
182
- return errors;
126
+ const { accept = "*", maxSize = Number.POSITIVE_INFINITY } = options;
127
+ const errors = [];
128
+ if (file.size > maxSize) errors.push({
129
+ code: "file-too-large",
130
+ message: `File "${file.name}" exceeds the maximum size of ${formatBytes(maxSize)}.`
131
+ });
132
+ if (!isAcceptedFile(file, accept)) errors.push({
133
+ code: "file-invalid-type",
134
+ message: `File "${file.name}" is not an accepted file type.`
135
+ });
136
+ return errors;
183
137
  }
184
138
  function isAcceptedFile(file, accept = "*") {
185
- if (accept === "*" || accept.trim() === "") return true;
186
- const acceptedTypes = accept.split(",").map((type) => type.trim().toLowerCase()).filter(Boolean);
187
- if (acceptedTypes.length === 0) return true;
188
- const fileType = file.type.toLowerCase();
189
- const fileExtension = getFileExtension(file.name);
190
- return acceptedTypes.some((acceptedType) => {
191
- if (acceptedType.startsWith(".")) {
192
- return fileExtension === acceptedType;
193
- }
194
- if (acceptedType.endsWith("/*")) {
195
- return fileType.startsWith(acceptedType.slice(0, -1));
196
- }
197
- return fileType === acceptedType;
198
- });
139
+ if (accept === "*" || accept.trim() === "") return true;
140
+ const acceptedTypes = accept.split(",").map((type) => type.trim().toLowerCase()).filter(Boolean);
141
+ if (acceptedTypes.length === 0) return true;
142
+ const fileType = file.type.toLowerCase();
143
+ const fileExtension = getFileExtension(file.name);
144
+ return acceptedTypes.some((acceptedType) => {
145
+ if (acceptedType.startsWith(".")) return fileExtension === acceptedType;
146
+ if (acceptedType.endsWith("/*")) return fileType.startsWith(acceptedType.slice(0, -1));
147
+ return fileType === acceptedType;
148
+ });
199
149
  }
200
150
  function formatBytes(bytes, decimals = 2) {
201
- if (bytes === 0) return "0 Bytes";
202
- if (!Number.isFinite(bytes)) return "unlimited";
203
- const unit = 1024;
204
- const precision = Math.max(0, decimals);
205
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
206
- const sizeIndex = Math.min(
207
- Math.floor(Math.log(bytes) / Math.log(unit)),
208
- sizes.length - 1
209
- );
210
- return `${Number.parseFloat((bytes / unit ** sizeIndex).toFixed(precision))} ${sizes[sizeIndex]}`;
151
+ if (bytes === 0) return "0 Bytes";
152
+ if (!Number.isFinite(bytes)) return "unlimited";
153
+ const unit = 1024;
154
+ const precision = Math.max(0, decimals);
155
+ const sizes = [
156
+ "Bytes",
157
+ "KB",
158
+ "MB",
159
+ "GB",
160
+ "TB",
161
+ "PB"
162
+ ];
163
+ const sizeIndex = Math.min(Math.floor(Math.log(bytes) / Math.log(unit)), sizes.length - 1);
164
+ return `${Number.parseFloat((bytes / unit ** sizeIndex).toFixed(precision))} ${sizes[sizeIndex]}`;
211
165
  }
212
166
  function getFileExtension(fileName) {
213
- const extension = fileName.toLowerCase().split(".").pop();
214
- return extension && extension !== fileName.toLowerCase() ? `.${extension}` : "";
167
+ const extension = fileName.toLowerCase().split(".").pop();
168
+ return extension && extension !== fileName.toLowerCase() ? `.${extension}` : "";
215
169
  }
216
170
  function assignRef(ref, value) {
217
- if (!ref) return;
218
- if (typeof ref === "function") {
219
- ref(value);
220
- return;
221
- }
222
- ref.current = value;
171
+ if (!ref) return;
172
+ if (typeof ref === "function") {
173
+ ref(value);
174
+ return;
175
+ }
176
+ ref.current = value;
223
177
  }
224
-
225
- // src/dropzone.tsx
226
- import { jsx, jsxs } from "react/jsx-runtime";
227
- var DropzoneContext = createContext(null);
178
+ //#endregion
179
+ //#region src/dropzone.tsx
180
+ const DropzoneContext = createContext(null);
228
181
  function useDropzoneContext() {
229
- const ctx = use(DropzoneContext);
230
- if (!ctx) {
231
- throw new Error(
232
- "Dropzone compound components must be rendered inside <Dropzone>."
233
- );
234
- }
235
- return ctx;
182
+ const ctx = use(DropzoneContext);
183
+ if (!ctx) throw new Error("Dropzone compound components must be rendered inside <Dropzone>.");
184
+ return ctx;
236
185
  }
237
- function Dropzone({
238
- children,
239
- className,
240
- disabled,
241
- ...options
242
- }) {
243
- const {
244
- isDragging,
245
- openFileDialog,
246
- getInputProps,
247
- handleDragEnter,
248
- handleDragLeave,
249
- handleDragOver,
250
- handleDrop
251
- } = useFilePicker({ ...options, disabled });
252
- return /* @__PURE__ */ jsx(
253
- DropzoneContext.Provider,
254
- {
255
- value: {
256
- isDragging,
257
- isDisabled: disabled ?? false,
258
- openFileDialog,
259
- getInputProps,
260
- handleDragEnter,
261
- handleDragLeave,
262
- handleDragOver,
263
- handleDrop
264
- },
265
- children: /* @__PURE__ */ jsx("div", { "data-slot": "dropzone", className: cn("relative", className), children })
266
- }
267
- );
186
+ /**
187
+ * Context provider that owns the `useFilePicker` instance.
188
+ * Wrap `<DropzoneArea>` and `<DropzoneInput>` (plus any content helpers)
189
+ * inside this component.
190
+ *
191
+ * @example
192
+ * ```tsx
193
+ * <Dropzone accept="image/*" multiple maxFiles={5} onFilesAccepted={handleFiles}>
194
+ * <DropzoneArea>
195
+ * <DropzoneIcon />
196
+ * <DropzoneTitle>Choose a file or drag & drop</DropzoneTitle>
197
+ * <DropzoneDescription>JPEG, PNG – up to 2 MB</DropzoneDescription>
198
+ * <DropzoneTrigger />
199
+ * </DropzoneArea>
200
+ * <DropzoneInput />
201
+ * </Dropzone>
202
+ * ```
203
+ */
204
+ function Dropzone({ children, className, disabled, ...options }) {
205
+ const { isDragging, openFileDialog, getInputProps, handleDragEnter, handleDragLeave, handleDragOver, handleDrop } = useFilePicker({
206
+ ...options,
207
+ disabled
208
+ });
209
+ return /* @__PURE__ */ jsx(DropzoneContext.Provider, {
210
+ value: {
211
+ isDragging,
212
+ isDisabled: disabled ?? false,
213
+ openFileDialog,
214
+ getInputProps,
215
+ handleDragEnter,
216
+ handleDragLeave,
217
+ handleDragOver,
218
+ handleDrop
219
+ },
220
+ children: /* @__PURE__ */ jsx("div", {
221
+ "data-slot": "dropzone",
222
+ className: cn("relative", className),
223
+ children
224
+ })
225
+ });
268
226
  }
269
- function DropzoneArea({
270
- children,
271
- className,
272
- label = "Upload files. Click to browse, or drag and drop files here.",
273
- ...props
274
- }) {
275
- const {
276
- isDragging,
277
- isDisabled,
278
- openFileDialog,
279
- handleDragEnter,
280
- handleDragLeave,
281
- handleDragOver,
282
- handleDrop
283
- } = useDropzoneContext();
284
- function handleKeyDown(e) {
285
- if (e.key === "Enter" || e.key === " ") {
286
- e.preventDefault();
287
- openFileDialog();
288
- }
289
- }
290
- return (
291
- // biome-ignore lint/a11y/useSemanticElements: The dropzone contains block-level compound content and owns drag events.
292
- /* @__PURE__ */ jsxs(
293
- "div",
294
- {
295
- "data-slot": "dropzone-area",
296
- "data-dragging": isDragging ? "true" : void 0,
297
- "data-disabled": isDisabled ? "true" : void 0,
298
- role: "button",
299
- tabIndex: isDisabled ? -1 : 0,
300
- "aria-label": label,
301
- "aria-disabled": isDisabled,
302
- onClick: isDisabled ? void 0 : openFileDialog,
303
- onKeyDown: isDisabled ? void 0 : handleKeyDown,
304
- onDragEnter: isDisabled ? void 0 : handleDragEnter,
305
- onDragLeave: isDisabled ? void 0 : handleDragLeave,
306
- onDragOver: isDisabled ? void 0 : handleDragOver,
307
- onDrop: isDisabled ? void 0 : handleDrop,
308
- className: cn(
309
- // Layout & base
310
- "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",
311
- // Default colours (design tokens)
312
- "border-line bg-surface-brand-subtle",
313
- // Focus ring – matches other interactive controls in the system
314
- "focus-visible:border-line-focus focus-visible:ring-2 focus-visible:ring-line-focus/35 focus-visible:outline-none",
315
- // Dragging variant
316
- "data-[dragging=true]:border-dashed data-[dragging=true]:border-line-focus data-[dragging=true]:bg-surface-brand/10",
317
- // Disabled variant
318
- "data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50",
319
- className
320
- ),
321
- ...props,
322
- children: [
323
- children,
324
- /* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: isDragging ? "Drop files to upload." : "" })
325
- ]
326
- }
327
- )
328
- );
227
+ /**
228
+ * The visual, interactive drop zone.
229
+ *
230
+ * - Behaves as a `button` (role, tabIndex, Enter/Space keyboard support).
231
+ * - Announces drag-state changes to screen readers via a live region.
232
+ * - Applies design-token-based styles and reacts to `data-dragging` /
233
+ * `data-disabled` for visual feedback.
234
+ */
235
+ function DropzoneArea({ children, className, label = "Upload files. Click to browse, or drag and drop files here.", ...props }) {
236
+ const { isDragging, isDisabled, openFileDialog, handleDragEnter, handleDragLeave, handleDragOver, handleDrop } = useDropzoneContext();
237
+ function handleKeyDown(e) {
238
+ if (e.key === "Enter" || e.key === " ") {
239
+ e.preventDefault();
240
+ openFileDialog();
241
+ }
242
+ }
243
+ return /* @__PURE__ */ jsxs("div", {
244
+ "data-slot": "dropzone-area",
245
+ "data-dragging": isDragging ? "true" : void 0,
246
+ "data-disabled": isDisabled ? "true" : void 0,
247
+ role: "button",
248
+ tabIndex: isDisabled ? -1 : 0,
249
+ "aria-label": label,
250
+ "aria-disabled": isDisabled,
251
+ onClick: isDisabled ? void 0 : openFileDialog,
252
+ onKeyDown: isDisabled ? void 0 : handleKeyDown,
253
+ onDragEnter: isDisabled ? void 0 : handleDragEnter,
254
+ onDragLeave: isDisabled ? void 0 : handleDragLeave,
255
+ onDragOver: isDisabled ? void 0 : handleDragOver,
256
+ onDrop: isDisabled ? void 0 : handleDrop,
257
+ className: cn("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", "border-line bg-surface-brand-subtle", "focus-visible:border-line-focus focus-visible:ring-2 focus-visible:ring-line-focus/35 focus-visible:outline-none", "data-[dragging=true]:border-dashed data-[dragging=true]:border-line-focus data-[dragging=true]:bg-surface-brand/10", "data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50", className),
258
+ ...props,
259
+ children: [children, /* @__PURE__ */ jsx("span", {
260
+ className: "sr-only",
261
+ "aria-live": "polite",
262
+ "aria-atomic": "true",
263
+ children: isDragging ? "Drop files to upload." : ""
264
+ })]
265
+ });
329
266
  }
267
+ /**
268
+ * The hidden `<input type="file">` that backs the drop zone.
269
+ * Rendered off-screen (not `display:none`) so it remains accessible.
270
+ * Place it as a sibling to `<DropzoneArea>` inside `<Dropzone>`.
271
+ */
330
272
  function DropzoneInput({ className, ...props }) {
331
- const { getInputProps } = useDropzoneContext();
332
- return /* @__PURE__ */ jsx(
333
- "input",
334
- {
335
- ...getInputProps({
336
- // sr-only keeps it in the a11y tree without being visible
337
- className: cn("sr-only", className),
338
- // Prevent it from receiving keyboard focus independently
339
- tabIndex: -1,
340
- ...props
341
- })
342
- }
343
- );
273
+ const { getInputProps } = useDropzoneContext();
274
+ return /* @__PURE__ */ jsx("input", { ...getInputProps({
275
+ className: cn("sr-only", className),
276
+ tabIndex: -1,
277
+ ...props
278
+ }) });
344
279
  }
345
- function useDropzoneStateLabel({
346
- children,
347
- disabledLabel,
348
- draggingLabel,
349
- idleLabel
350
- }) {
351
- const { isDragging, isDisabled } = useDropzoneContext();
352
- if (isDisabled && disabledLabel !== void 0) {
353
- return disabledLabel;
354
- }
355
- if (isDragging && draggingLabel !== void 0) {
356
- return draggingLabel;
357
- }
358
- return idleLabel ?? children;
280
+ function useDropzoneStateLabel({ children, disabledLabel, draggingLabel, idleLabel }) {
281
+ const { isDragging, isDisabled } = useDropzoneContext();
282
+ if (isDisabled && disabledLabel !== void 0) return disabledLabel;
283
+ if (isDragging && draggingLabel !== void 0) return draggingLabel;
284
+ return idleLabel ?? children;
359
285
  }
360
- function DropzoneIcon({
361
- className,
362
- children,
363
- ...props
364
- }) {
365
- return /* @__PURE__ */ jsx(
366
- "div",
367
- {
368
- "data-slot": "dropzone-icon",
369
- "aria-hidden": "true",
370
- className: cn(
371
- "mb-4 flex size-11 shrink-0 items-center justify-center rounded-full",
372
- // Solid brand fill with an inset ring for depth
373
- "bg-surface-brand text-fg-on-brand ring-1 ring-fg-on-brand/10 ring-inset",
374
- className
375
- ),
376
- ...props,
377
- children: children ?? /* @__PURE__ */ jsx(UploadCloud, { className: "size-5" })
378
- }
379
- );
286
+ /**
287
+ * A centred, brand-coloured icon container pre-populated with an upload cloud
288
+ * icon. Pass `children` to swap the icon.
289
+ */
290
+ function DropzoneIcon({ className, children, ...props }) {
291
+ return /* @__PURE__ */ jsx("div", {
292
+ "data-slot": "dropzone-icon",
293
+ "aria-hidden": "true",
294
+ className: cn("mb-4 flex size-11 shrink-0 items-center justify-center rounded-full", "bg-surface-brand text-fg-on-brand ring-1 ring-fg-on-brand/10 ring-inset", className),
295
+ ...props,
296
+ children: children ?? /* @__PURE__ */ jsx(UploadCloud, { className: "size-5" })
297
+ });
380
298
  }
381
- function DropzoneTitle({
382
- className,
383
- children,
384
- disabledLabel,
385
- draggingLabel,
386
- idleLabel,
387
- ...props
388
- }) {
389
- const label = useDropzoneStateLabel({
390
- children,
391
- disabledLabel,
392
- draggingLabel,
393
- idleLabel
394
- });
395
- return /* @__PURE__ */ jsx(
396
- "p",
397
- {
398
- "data-slot": "dropzone-title",
399
- className: cn(
400
- "text-gdt-md font-semibold leading-snug text-fg-primary",
401
- className
402
- ),
403
- ...props,
404
- children: label
405
- }
406
- );
299
+ /**
300
+ * Primary heading text inside the drop zone.
301
+ */
302
+ function DropzoneTitle({ className, children, disabledLabel, draggingLabel, idleLabel, ...props }) {
303
+ const label = useDropzoneStateLabel({
304
+ children,
305
+ disabledLabel,
306
+ draggingLabel,
307
+ idleLabel
308
+ });
309
+ return /* @__PURE__ */ jsx("p", {
310
+ "data-slot": "dropzone-title",
311
+ className: cn("text-gdt-md font-semibold leading-snug text-fg-primary", className),
312
+ ...props,
313
+ children: label
314
+ });
407
315
  }
408
- function DropzoneDescription({
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-description",
426
- className: cn("mt-1 text-gdt-sm text-fg-secondary", className),
427
- ...props,
428
- children: label
429
- }
430
- );
316
+ /**
317
+ * Secondary descriptive text inside the drop zone (file-type hints, size
318
+ * limits, etc.).
319
+ */
320
+ function DropzoneDescription({ className, children, disabledLabel, draggingLabel, idleLabel, ...props }) {
321
+ const label = useDropzoneStateLabel({
322
+ children,
323
+ disabledLabel,
324
+ draggingLabel,
325
+ idleLabel
326
+ });
327
+ return /* @__PURE__ */ jsx("p", {
328
+ "data-slot": "dropzone-description",
329
+ className: cn("mt-1 text-gdt-sm text-fg-secondary", className),
330
+ ...props,
331
+ children: label
332
+ });
431
333
  }
432
- function DropzoneTrigger({
433
- className,
434
- children = "Browse File",
435
- ...props
436
- }) {
437
- return /* @__PURE__ */ jsx(
438
- "span",
439
- {
440
- "data-slot": "dropzone-trigger",
441
- "aria-hidden": "true",
442
- className: cn(
443
- "mt-5 inline-flex h-8 shrink-0 items-center justify-center rounded-full px-4",
444
- "bg-action-primary text-gdt-sm font-medium text-fg-on-brand",
445
- "transition-colors duration-150",
446
- className
447
- ),
448
- ...props,
449
- children
450
- }
451
- );
334
+ /**
335
+ * A decorative "Browse File" pill that visually suggests the click action.
336
+ *
337
+ * This element is `aria-hidden` because the surrounding `<DropzoneArea>`
338
+ * already exposes a labelled `button` role to assistive technologies.
339
+ * The pill is purely a visual affordance.
340
+ */
341
+ function DropzoneTrigger({ className, children = "Browse File", ...props }) {
342
+ return /* @__PURE__ */ jsx("span", {
343
+ "data-slot": "dropzone-trigger",
344
+ "aria-hidden": "true",
345
+ className: cn("mt-5 inline-flex h-8 shrink-0 items-center justify-center rounded-full px-4", "bg-action-primary text-gdt-sm font-medium text-fg-on-brand", "transition-colors duration-150", className),
346
+ ...props,
347
+ children
348
+ });
452
349
  }
453
- export {
454
- Dropzone,
455
- DropzoneArea,
456
- DropzoneDescription,
457
- DropzoneIcon,
458
- DropzoneInput,
459
- DropzoneTitle,
460
- DropzoneTrigger,
461
- useDropzoneContext
462
- };
463
- //# sourceMappingURL=dropzone.js.map
350
+ //#endregion
351
+ export { Dropzone, DropzoneArea, DropzoneDescription, DropzoneIcon, DropzoneInput, DropzoneTitle, DropzoneTrigger, useDropzoneContext };