@giddaa-housing/ui 1.0.0 → 1.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 (326) hide show
  1. package/css/generated/shared.css +1 -1
  2. package/dist/accordion.d.ts +9 -10
  3. package/dist/accordion.js +41 -87
  4. package/dist/activity-timeline.d.ts +12 -16
  5. package/dist/activity-timeline.js +83 -198
  6. package/dist/alert.d.ts +8 -9
  7. package/dist/alert.js +53 -111
  8. package/dist/auth-layout.d.ts +4 -4
  9. package/dist/auth-layout.js +143 -294
  10. package/dist/avatar.d.ts +6 -6
  11. package/dist/avatar.js +49 -19
  12. package/dist/badge.d.ts +12 -14
  13. package/dist/badge.js +71 -11
  14. package/dist/bar-chart.d.ts +65 -67
  15. package/dist/bar-chart.js +232 -207
  16. package/dist/breadcrumb.d.ts +5 -5
  17. package/dist/breadcrumb.js +56 -118
  18. package/dist/bullet-chart.d.ts +33 -33
  19. package/dist/bullet-chart.js +121 -148
  20. package/dist/button-BZIeyUw6.d.ts +17 -0
  21. package/dist/button-group.d.ts +13 -16
  22. package/dist/button-group.js +39 -88
  23. package/dist/button.d.ts +2 -19
  24. package/dist/button.js +94 -13
  25. package/dist/calendar.d.ts +6 -6
  26. package/dist/calendar.js +138 -17
  27. package/dist/card.d.ts +14 -16
  28. package/dist/card.js +59 -145
  29. package/dist/carousel.d.ts +34 -35
  30. package/dist/carousel.js +335 -20
  31. package/dist/chart.d.ts +58 -59
  32. package/dist/chart.js +376 -28
  33. package/dist/checkbox.d.ts +10 -12
  34. package/dist/checkbox.js +82 -47
  35. package/dist/cn-BI_4DMBf.js +23 -0
  36. package/dist/collapsible.d.ts +7 -8
  37. package/dist/collapsible.js +22 -47
  38. package/dist/combobox.d.ts +10 -10
  39. package/dist/combobox.js +236 -44
  40. package/dist/cta.d.ts +12 -14
  41. package/dist/cta.js +175 -341
  42. package/dist/currency-selector.d.ts +31 -32
  43. package/dist/currency-selector.js +106 -184
  44. package/dist/data-table.d.ts +164 -0
  45. package/dist/data-table.js +673 -0
  46. package/dist/date-picker.d.ts +22 -23
  47. package/dist/date-picker.js +119 -192
  48. package/dist/details-card.d.ts +7 -7
  49. package/dist/details-card.js +104 -253
  50. package/dist/dialog.d.ts +13 -14
  51. package/dist/dialog.js +116 -209
  52. package/dist/dropdown-menu.d.ts +13 -13
  53. package/dist/dropdown-menu.js +180 -37
  54. package/dist/dropzone.d.ts +55 -55
  55. package/dist/dropzone.js +327 -439
  56. package/dist/editorial-card.d.ts +23 -25
  57. package/dist/editorial-card.js +129 -296
  58. package/dist/empty-state.d.ts +8 -9
  59. package/dist/empty-state.js +48 -105
  60. package/dist/field.d.ts +23 -25
  61. package/dist/field.js +110 -221
  62. package/dist/filter.d.ts +118 -0
  63. package/dist/filter.js +775 -0
  64. package/dist/footer.d.ts +8 -15
  65. package/dist/footer.js +197 -400
  66. package/dist/funnel-chart.d.ts +38 -41
  67. package/dist/funnel-chart.js +167 -189
  68. package/dist/gallery-indicator.d.ts +11 -12
  69. package/dist/gallery-indicator.js +75 -12
  70. package/dist/heatmap-chart.d.ts +47 -50
  71. package/dist/heatmap-chart.js +186 -237
  72. package/dist/infotip.d.ts +8 -9
  73. package/dist/infotip.js +33 -59
  74. package/dist/input-CfoEJ8A6.d.ts +12 -0
  75. package/dist/input-group.d.ts +16 -20
  76. package/dist/input-group.js +99 -23
  77. package/dist/input-size-context-C-SFx9sx.d.ts +10 -0
  78. package/dist/input-size-context.d.ts +2 -11
  79. package/dist/input-size-context.js +17 -9
  80. package/dist/input.d.ts +2 -13
  81. package/dist/input.js +27 -11
  82. package/dist/item.d.ts +7 -8
  83. package/dist/item.js +22 -59
  84. package/dist/kpi-card.d.ts +18 -20
  85. package/dist/kpi-card.js +84 -192
  86. package/dist/label.d.ts +6 -6
  87. package/dist/label.js +40 -8
  88. package/dist/line-chart.d.ts +88 -89
  89. package/dist/line-chart.js +142 -104
  90. package/dist/logo.d.ts +4 -4
  91. package/dist/logo.js +92 -9
  92. package/dist/map-indicator.d.ts +7 -7
  93. package/dist/map-indicator.js +80 -106
  94. package/dist/match.d.ts +10 -11
  95. package/dist/match.js +62 -107
  96. package/dist/media-gallery-hero.d.ts +40 -42
  97. package/dist/media-gallery-hero.js +182 -343
  98. package/dist/media-player.d.ts +17 -17
  99. package/dist/media-player.js +873 -1348
  100. package/dist/multi-step-form.d.ts +56 -0
  101. package/dist/multi-step-form.js +342 -0
  102. package/dist/number-input.d.ts +34 -34
  103. package/dist/number-input.js +61 -117
  104. package/dist/page-header.d.ts +10 -11
  105. package/dist/page-header.js +34 -79
  106. package/dist/pagination.d.ts +17 -21
  107. package/dist/pagination.js +132 -207
  108. package/dist/password-input.d.ts +5 -13
  109. package/dist/password-input.js +31 -55
  110. package/dist/phone-input.d.ts +19 -20
  111. package/dist/phone-input.js +226 -344
  112. package/dist/photo-gallery.d.ts +19 -19
  113. package/dist/photo-gallery.js +313 -449
  114. package/dist/picker-lzgmsNfG.js +32 -0
  115. package/dist/pie-chart.d.ts +60 -60
  116. package/dist/pie-chart.js +140 -148
  117. package/dist/popover.d.ts +9 -9
  118. package/dist/popover.js +72 -23
  119. package/dist/price-tag.d.ts +26 -27
  120. package/dist/price-tag.js +113 -173
  121. package/dist/progress.d.ts +16 -17
  122. package/dist/progress.js +169 -24
  123. package/dist/property-listing-card.d.ts +14 -17
  124. package/dist/property-listing-card.js +102 -220
  125. package/dist/radar-chart.d.ts +29 -31
  126. package/dist/radar-chart.js +162 -137
  127. package/dist/radio-group.d.ts +11 -13
  128. package/dist/radio-group.js +46 -60
  129. package/dist/review-block.d.ts +14 -16
  130. package/dist/review-block.js +154 -10
  131. package/dist/rich-text-editor.d.ts +30 -14
  132. package/dist/rich-text-editor.js +592 -716
  133. package/dist/scatter-chart.d.ts +45 -47
  134. package/dist/scatter-chart.js +236 -240
  135. package/dist/search-input.d.ts +8 -16
  136. package/dist/search-input.js +57 -109
  137. package/dist/select.d.ts +8 -8
  138. package/dist/select.js +144 -27
  139. package/dist/separator.d.ts +8 -9
  140. package/dist/separator.js +32 -8
  141. package/dist/sheet.d.ts +11 -11
  142. package/dist/sheet.js +103 -24
  143. package/dist/sidebar.d.ts +32 -37
  144. package/dist/sidebar.js +364 -634
  145. package/dist/size-context-D4mYvcg8.d.ts +10 -0
  146. package/dist/size-context.d.ts +2 -11
  147. package/dist/size-context.js +17 -9
  148. package/dist/skeleton.d.ts +4 -5
  149. package/dist/skeleton.js +12 -8
  150. package/dist/slider.d.ts +8 -9
  151. package/dist/slider.js +64 -135
  152. package/dist/sparkline.d.ts +43 -46
  153. package/dist/sparkline.js +221 -251
  154. package/dist/stepper.d.ts +23 -24
  155. package/dist/stepper.js +149 -246
  156. package/dist/styles.css +510 -108
  157. package/dist/switch.d.ts +10 -12
  158. package/dist/switch.js +48 -70
  159. package/dist/table-card.d.ts +35 -0
  160. package/dist/table-card.js +125 -0
  161. package/dist/table.d.ts +18 -14
  162. package/dist/table.js +113 -154
  163. package/dist/tabs.d.ts +23 -15
  164. package/dist/tabs.js +71 -18
  165. package/dist/tag.d.ts +21 -23
  166. package/dist/tag.js +103 -159
  167. package/dist/testimonial-block.d.ts +18 -19
  168. package/dist/testimonial-block.js +189 -358
  169. package/dist/textarea-IS_D8pXf.d.ts +11 -0
  170. package/dist/textarea.d.ts +2 -12
  171. package/dist/textarea.js +24 -11
  172. package/dist/time-picker.d.ts +11 -11
  173. package/dist/time-picker.js +245 -302
  174. package/dist/toast.d.ts +16 -18
  175. package/dist/toast.js +154 -205
  176. package/dist/tooltip.d.ts +8 -9
  177. package/dist/tooltip.js +37 -12
  178. package/dist/tree-map.d.ts +54 -57
  179. package/dist/tree-map.js +227 -269
  180. package/dist/use-uncontrolled-CLfM1XbB.js +21 -0
  181. package/dist/waterfall-chart.d.ts +94 -97
  182. package/dist/waterfall-chart.js +455 -552
  183. package/package.json +28 -9
  184. package/dist/accordion.js.map +0 -1
  185. package/dist/activity-timeline.js.map +0 -1
  186. package/dist/alert.js.map +0 -1
  187. package/dist/auth-layout.js.map +0 -1
  188. package/dist/avatar.js.map +0 -1
  189. package/dist/badge.js.map +0 -1
  190. package/dist/bar-chart.js.map +0 -1
  191. package/dist/breadcrumb.js.map +0 -1
  192. package/dist/bullet-chart.js.map +0 -1
  193. package/dist/button-group.js.map +0 -1
  194. package/dist/button.js.map +0 -1
  195. package/dist/calendar.js.map +0 -1
  196. package/dist/card.js.map +0 -1
  197. package/dist/carousel.js.map +0 -1
  198. package/dist/chart.js.map +0 -1
  199. package/dist/checkbox.js.map +0 -1
  200. package/dist/chunk-322YCNVL.js +0 -278
  201. package/dist/chunk-322YCNVL.js.map +0 -1
  202. package/dist/chunk-3ACQVT7A.js +0 -25
  203. package/dist/chunk-3ACQVT7A.js.map +0 -1
  204. package/dist/chunk-3T65TLJX.js +0 -334
  205. package/dist/chunk-3T65TLJX.js.map +0 -1
  206. package/dist/chunk-6ZSGQHH2.js +0 -192
  207. package/dist/chunk-6ZSGQHH2.js.map +0 -1
  208. package/dist/chunk-7TBMLFGW.js +0 -41
  209. package/dist/chunk-7TBMLFGW.js.map +0 -1
  210. package/dist/chunk-B4H6RNDH.js +0 -135
  211. package/dist/chunk-B4H6RNDH.js.map +0 -1
  212. package/dist/chunk-BUXCGZ6X.js +0 -219
  213. package/dist/chunk-BUXCGZ6X.js.map +0 -1
  214. package/dist/chunk-CHII2QHH.js +0 -58
  215. package/dist/chunk-CHII2QHH.js.map +0 -1
  216. package/dist/chunk-DMNOXRRW.js +0 -147
  217. package/dist/chunk-DMNOXRRW.js.map +0 -1
  218. package/dist/chunk-EFSOSSIC.js +0 -130
  219. package/dist/chunk-EFSOSSIC.js.map +0 -1
  220. package/dist/chunk-FZDSVMKY.js +0 -363
  221. package/dist/chunk-FZDSVMKY.js.map +0 -1
  222. package/dist/chunk-GJOFIJS3.js +0 -246
  223. package/dist/chunk-GJOFIJS3.js.map +0 -1
  224. package/dist/chunk-HL3ZSYES.js +0 -23
  225. package/dist/chunk-HL3ZSYES.js.map +0 -1
  226. package/dist/chunk-JVLUBAPB.js +0 -129
  227. package/dist/chunk-JVLUBAPB.js.map +0 -1
  228. package/dist/chunk-KDPYSOYZ.js +0 -64
  229. package/dist/chunk-KDPYSOYZ.js.map +0 -1
  230. package/dist/chunk-KSMDANKI.js +0 -43
  231. package/dist/chunk-KSMDANKI.js.map +0 -1
  232. package/dist/chunk-MEKCCOP5.js +0 -46
  233. package/dist/chunk-MEKCCOP5.js.map +0 -1
  234. package/dist/chunk-NOFXVRWL.js +0 -451
  235. package/dist/chunk-NOFXVRWL.js.map +0 -1
  236. package/dist/chunk-PC5MHNVA.js +0 -171
  237. package/dist/chunk-PC5MHNVA.js.map +0 -1
  238. package/dist/chunk-QKAQZ2GU.js +0 -122
  239. package/dist/chunk-QKAQZ2GU.js.map +0 -1
  240. package/dist/chunk-QZHSHSVV.js +0 -26
  241. package/dist/chunk-QZHSHSVV.js.map +0 -1
  242. package/dist/chunk-RBMK26XD.js +0 -19
  243. package/dist/chunk-RBMK26XD.js.map +0 -1
  244. package/dist/chunk-SFNJGF6M.js +0 -262
  245. package/dist/chunk-SFNJGF6M.js.map +0 -1
  246. package/dist/chunk-UJJNLGTM.js +0 -112
  247. package/dist/chunk-UJJNLGTM.js.map +0 -1
  248. package/dist/chunk-VGR4ZWJ3.js +0 -418
  249. package/dist/chunk-VGR4ZWJ3.js.map +0 -1
  250. package/dist/chunk-XG47P6D4.js +0 -99
  251. package/dist/chunk-XG47P6D4.js.map +0 -1
  252. package/dist/chunk-XZZAHNVM.js +0 -21
  253. package/dist/chunk-XZZAHNVM.js.map +0 -1
  254. package/dist/chunk-Y4TTYVNE.js +0 -36
  255. package/dist/chunk-Y4TTYVNE.js.map +0 -1
  256. package/dist/chunk-YDWIHW6Q.js +0 -69
  257. package/dist/chunk-YDWIHW6Q.js.map +0 -1
  258. package/dist/collapsible.js.map +0 -1
  259. package/dist/combobox.js.map +0 -1
  260. package/dist/cta.js.map +0 -1
  261. package/dist/currency-selector.js.map +0 -1
  262. package/dist/date-picker.js.map +0 -1
  263. package/dist/details-card.js.map +0 -1
  264. package/dist/dialog.js.map +0 -1
  265. package/dist/dropdown-menu.js.map +0 -1
  266. package/dist/dropzone.js.map +0 -1
  267. package/dist/editorial-card.js.map +0 -1
  268. package/dist/empty-state.js.map +0 -1
  269. package/dist/field.js.map +0 -1
  270. package/dist/footer.js.map +0 -1
  271. package/dist/funnel-chart.js.map +0 -1
  272. package/dist/gallery-indicator.js.map +0 -1
  273. package/dist/heatmap-chart.js.map +0 -1
  274. package/dist/infotip.js.map +0 -1
  275. package/dist/input-group.js.map +0 -1
  276. package/dist/input-size-context.js.map +0 -1
  277. package/dist/input.js.map +0 -1
  278. package/dist/item.js.map +0 -1
  279. package/dist/kpi-card.js.map +0 -1
  280. package/dist/label.js.map +0 -1
  281. package/dist/line-chart.js.map +0 -1
  282. package/dist/logo.js.map +0 -1
  283. package/dist/map-indicator.js.map +0 -1
  284. package/dist/match.js.map +0 -1
  285. package/dist/media-gallery-hero.js.map +0 -1
  286. package/dist/media-player.js.map +0 -1
  287. package/dist/number-input.js.map +0 -1
  288. package/dist/page-header.js.map +0 -1
  289. package/dist/pagination.js.map +0 -1
  290. package/dist/password-input.js.map +0 -1
  291. package/dist/phone-input.js.map +0 -1
  292. package/dist/photo-gallery.js.map +0 -1
  293. package/dist/pie-chart.js.map +0 -1
  294. package/dist/popover.js.map +0 -1
  295. package/dist/price-tag.js.map +0 -1
  296. package/dist/progress.js.map +0 -1
  297. package/dist/property-listing-card.js.map +0 -1
  298. package/dist/radar-chart.js.map +0 -1
  299. package/dist/radio-group.js.map +0 -1
  300. package/dist/review-block.js.map +0 -1
  301. package/dist/rich-text-editor.js.map +0 -1
  302. package/dist/scatter-chart.js.map +0 -1
  303. package/dist/search-input.js.map +0 -1
  304. package/dist/select.js.map +0 -1
  305. package/dist/separator.js.map +0 -1
  306. package/dist/sheet.js.map +0 -1
  307. package/dist/sidebar.js.map +0 -1
  308. package/dist/size-context.js.map +0 -1
  309. package/dist/skeleton.js.map +0 -1
  310. package/dist/slider.js.map +0 -1
  311. package/dist/sparkline.js.map +0 -1
  312. package/dist/stepper.js.map +0 -1
  313. package/dist/switch.js.map +0 -1
  314. package/dist/tab-list.d.ts +0 -38
  315. package/dist/tab-list.js +0 -123
  316. package/dist/tab-list.js.map +0 -1
  317. package/dist/table.js.map +0 -1
  318. package/dist/tabs.js.map +0 -1
  319. package/dist/tag.js.map +0 -1
  320. package/dist/testimonial-block.js.map +0 -1
  321. package/dist/textarea.js.map +0 -1
  322. package/dist/time-picker.js.map +0 -1
  323. package/dist/toast.js.map +0 -1
  324. package/dist/tooltip.js.map +0 -1
  325. package/dist/tree-map.js.map +0 -1
  326. 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 };