@krizaka/ui 2.3.0 → 2.4.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 (280) hide show
  1. package/README.md +16 -1
  2. package/dist/audio-player.d.ts +113 -0
  3. package/dist/audio-player.js +207 -0
  4. package/dist/audio-player.js.map +1 -0
  5. package/dist/chunk-2USC2YT6.js +17 -0
  6. package/dist/chunk-2USC2YT6.js.map +1 -0
  7. package/dist/chunk-EUPTXKH7.js +95 -0
  8. package/dist/chunk-EUPTXKH7.js.map +1 -0
  9. package/dist/chunk-RUPRYJ45.js +82 -0
  10. package/dist/chunk-RUPRYJ45.js.map +1 -0
  11. package/dist/chunk-XUMJA5ZI.js +283 -0
  12. package/dist/chunk-XUMJA5ZI.js.map +1 -0
  13. package/dist/chunk-YH4LMWRU.js +92 -0
  14. package/dist/chunk-YH4LMWRU.js.map +1 -0
  15. package/dist/chunk-YX6CNVJA.js +94 -0
  16. package/dist/chunk-YX6CNVJA.js.map +1 -0
  17. package/dist/chunk-ZIXB33X7.js +95 -0
  18. package/dist/chunk-ZIXB33X7.js.map +1 -0
  19. package/dist/combobox.d.ts +188 -0
  20. package/dist/combobox.js +16 -0
  21. package/dist/combobox.js.map +1 -0
  22. package/dist/data-table.d.ts +246 -0
  23. package/dist/data-table.js +290 -0
  24. package/dist/data-table.js.map +1 -0
  25. package/dist/date-picker.d.ts +288 -0
  26. package/dist/date-picker.js +364 -0
  27. package/dist/date-picker.js.map +1 -0
  28. package/dist/file-upload.d.ts +238 -0
  29. package/dist/file-upload.js +437 -0
  30. package/dist/file-upload.js.map +1 -0
  31. package/dist/filter-bar.d.ts +139 -0
  32. package/dist/filter-bar.js +155 -0
  33. package/dist/filter-bar.js.map +1 -0
  34. package/dist/image-cropper.d.ts +115 -0
  35. package/dist/image-cropper.js +166 -0
  36. package/dist/image-cropper.js.map +1 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/media-capture.d.ts +155 -0
  39. package/dist/media-capture.js +242 -0
  40. package/dist/media-capture.js.map +1 -0
  41. package/dist/native/media-capture.d.ts +49 -0
  42. package/dist/native/media-capture.js +113 -0
  43. package/dist/native/media-capture.js.map +1 -0
  44. package/dist/native/video-player.d.ts +50 -0
  45. package/dist/native/video-player.js +69 -0
  46. package/dist/native/video-player.js.map +1 -0
  47. package/dist/native.d.ts +66 -2
  48. package/dist/native.js +166 -68
  49. package/dist/native.js.map +1 -1
  50. package/dist/pagination.d.ts +141 -0
  51. package/dist/pagination.js +165 -0
  52. package/dist/pagination.js.map +1 -0
  53. package/dist/search-field.d.ts +100 -0
  54. package/dist/search-field.js +167 -0
  55. package/dist/search-field.js.map +1 -0
  56. package/dist/tag-input.d.ts +44 -0
  57. package/dist/tag-input.js +67 -0
  58. package/dist/tag-input.js.map +1 -0
  59. package/dist/video-player.d.ts +204 -0
  60. package/dist/video-player.js +371 -0
  61. package/dist/video-player.js.map +1 -0
  62. package/dist/video-trimmer.d.ts +142 -0
  63. package/dist/video-trimmer.js +193 -0
  64. package/dist/video-trimmer.js.map +1 -0
  65. package/package.json +232 -4
  66. package/registry/alert.json +1 -1
  67. package/registry/audio-player.json +282 -0
  68. package/registry/avatar.json +1 -1
  69. package/registry/badge.json +1 -1
  70. package/registry/button.json +1 -1
  71. package/registry/card.json +1 -1
  72. package/registry/checkbox.json +1 -1
  73. package/registry/chip-link.json +1 -1
  74. package/registry/chip.json +1 -1
  75. package/registry/combobox.json +475 -0
  76. package/registry/command.json +1 -1
  77. package/registry/confirm-button.json +1 -1
  78. package/registry/countdown.json +1 -1
  79. package/registry/data-table.json +500 -0
  80. package/registry/date-picker.json +978 -0
  81. package/registry/dialog.json +1 -1
  82. package/registry/dropdown-menu.json +1 -1
  83. package/registry/empty-state.json +1 -1
  84. package/registry/examples/audio-player/podcast.d.ts +4 -0
  85. package/registry/examples/audio-player/podcast.js +22 -0
  86. package/registry/examples/audio-player/podcast.tsx +19 -0
  87. package/registry/examples/audio-player/voice-note.d.ts +4 -0
  88. package/registry/examples/audio-player/voice-note.js +12 -0
  89. package/registry/examples/audio-player/voice-note.tsx +12 -0
  90. package/registry/examples/combobox/async.d.ts +4 -0
  91. package/registry/examples/combobox/async.js +23 -0
  92. package/registry/examples/combobox/async.tsx +22 -0
  93. package/registry/examples/combobox/creatable.d.ts +4 -0
  94. package/registry/examples/combobox/creatable.js +32 -0
  95. package/registry/examples/combobox/creatable.tsx +28 -0
  96. package/registry/examples/combobox/invalid.d.ts +4 -0
  97. package/registry/examples/combobox/invalid.js +23 -0
  98. package/registry/examples/combobox/invalid.tsx +17 -0
  99. package/registry/examples/combobox/multiple.d.ts +4 -0
  100. package/registry/examples/combobox/multiple.js +29 -0
  101. package/registry/examples/combobox/multiple.tsx +26 -0
  102. package/registry/examples/data-table/cards.d.ts +4 -0
  103. package/registry/examples/data-table/cards.js +21 -0
  104. package/registry/examples/data-table/cards.tsx +20 -0
  105. package/registry/examples/data-table/empty.d.ts +4 -0
  106. package/registry/examples/data-table/empty.js +26 -0
  107. package/registry/examples/data-table/empty.tsx +21 -0
  108. package/registry/examples/data-table/error.d.ts +4 -0
  109. package/registry/examples/data-table/error.js +28 -0
  110. package/registry/examples/data-table/error.tsx +29 -0
  111. package/registry/examples/data-table/jobs.d.ts +4 -0
  112. package/registry/examples/data-table/jobs.js +37 -0
  113. package/registry/examples/data-table/jobs.tsx +36 -0
  114. package/registry/examples/data-table/loading.d.ts +4 -0
  115. package/registry/examples/data-table/loading.js +16 -0
  116. package/registry/examples/data-table/loading.tsx +12 -0
  117. package/registry/examples/data-table/virtualized.d.ts +4 -0
  118. package/registry/examples/data-table/virtualized.js +21 -0
  119. package/registry/examples/data-table/virtualized.tsx +20 -0
  120. package/registry/examples/date-picker/calendar.d.ts +4 -0
  121. package/registry/examples/date-picker/calendar.js +14 -0
  122. package/registry/examples/date-picker/calendar.tsx +16 -0
  123. package/registry/examples/date-picker/french.d.ts +4 -0
  124. package/registry/examples/date-picker/french.js +20 -0
  125. package/registry/examples/date-picker/french.tsx +14 -0
  126. package/registry/examples/date-picker/open.d.ts +4 -0
  127. package/registry/examples/date-picker/open.js +11 -0
  128. package/registry/examples/date-picker/open.tsx +8 -0
  129. package/registry/examples/date-picker/range.d.ts +4 -0
  130. package/registry/examples/date-picker/range.js +29 -0
  131. package/registry/examples/date-picker/range.tsx +25 -0
  132. package/registry/examples/date-picker/schedule.d.ts +4 -0
  133. package/registry/examples/date-picker/schedule.js +26 -0
  134. package/registry/examples/date-picker/schedule.tsx +22 -0
  135. package/registry/examples/file-upload/images.d.ts +4 -0
  136. package/registry/examples/file-upload/images.js +32 -0
  137. package/registry/examples/file-upload/images.tsx +25 -0
  138. package/registry/examples/file-upload/states.d.ts +4 -0
  139. package/registry/examples/file-upload/states.js +28 -0
  140. package/registry/examples/file-upload/states.tsx +23 -0
  141. package/registry/examples/file-upload/tus.d.ts +4 -0
  142. package/registry/examples/file-upload/tus.js +23 -0
  143. package/registry/examples/file-upload/tus.tsx +26 -0
  144. package/registry/examples/file-upload/video.d.ts +4 -0
  145. package/registry/examples/file-upload/video.js +39 -0
  146. package/registry/examples/file-upload/video.tsx +36 -0
  147. package/registry/examples/filter-bar/address.d.ts +4 -0
  148. package/registry/examples/filter-bar/address.js +29 -0
  149. package/registry/examples/filter-bar/address.tsx +27 -0
  150. package/registry/examples/filter-bar/jobs.d.ts +4 -0
  151. package/registry/examples/filter-bar/jobs.js +37 -0
  152. package/registry/examples/filter-bar/jobs.tsx +37 -0
  153. package/registry/examples/filter-bar/menu.d.ts +4 -0
  154. package/registry/examples/filter-bar/menu.js +27 -0
  155. package/registry/examples/filter-bar/menu.tsx +23 -0
  156. package/registry/examples/image-cropper/avatar.d.ts +4 -0
  157. package/registry/examples/image-cropper/avatar.js +13 -0
  158. package/registry/examples/image-cropper/avatar.tsx +14 -0
  159. package/registry/examples/image-cropper/banner.d.ts +4 -0
  160. package/registry/examples/image-cropper/banner.js +11 -0
  161. package/registry/examples/image-cropper/banner.tsx +10 -0
  162. package/registry/examples/image-cropper/vertical-video.d.ts +4 -0
  163. package/registry/examples/image-cropper/vertical-video.js +12 -0
  164. package/registry/examples/image-cropper/vertical-video.tsx +16 -0
  165. package/registry/examples/media-capture/clip.d.ts +4 -0
  166. package/registry/examples/media-capture/clip.js +20 -0
  167. package/registry/examples/media-capture/clip.tsx +18 -0
  168. package/registry/examples/media-capture/native/photo.d.ts +4 -0
  169. package/registry/examples/media-capture/native/photo.dark.png +0 -0
  170. package/registry/examples/media-capture/native/photo.js +27 -0
  171. package/registry/examples/media-capture/native/photo.light.png +0 -0
  172. package/registry/examples/media-capture/native/photo.tsx +20 -0
  173. package/registry/examples/media-capture/profile-photo.d.ts +4 -0
  174. package/registry/examples/media-capture/profile-photo.js +24 -0
  175. package/registry/examples/media-capture/profile-photo.tsx +20 -0
  176. package/registry/examples/pagination/cursor.d.ts +4 -0
  177. package/registry/examples/pagination/cursor.js +24 -0
  178. package/registry/examples/pagination/cursor.tsx +20 -0
  179. package/registry/examples/pagination/links.d.ts +4 -0
  180. package/registry/examples/pagination/links.js +11 -0
  181. package/registry/examples/pagination/links.tsx +6 -0
  182. package/registry/examples/pagination/native/cursor.d.ts +4 -0
  183. package/registry/examples/pagination/native/cursor.dark.png +0 -0
  184. package/registry/examples/pagination/native/cursor.js +19 -0
  185. package/registry/examples/pagination/native/cursor.light.png +0 -0
  186. package/registry/examples/pagination/native/cursor.tsx +13 -0
  187. package/registry/examples/pagination/native/pages.d.ts +4 -0
  188. package/registry/examples/pagination/native/pages.dark.png +0 -0
  189. package/registry/examples/pagination/native/pages.js +21 -0
  190. package/registry/examples/pagination/native/pages.light.png +0 -0
  191. package/registry/examples/pagination/native/pages.tsx +14 -0
  192. package/registry/examples/pagination/results.d.ts +4 -0
  193. package/registry/examples/pagination/results.js +23 -0
  194. package/registry/examples/pagination/results.tsx +19 -0
  195. package/registry/examples/pagination/table-footer.d.ts +4 -0
  196. package/registry/examples/pagination/table-footer.js +31 -0
  197. package/registry/examples/pagination/table-footer.tsx +27 -0
  198. package/registry/examples/search-field/global.d.ts +4 -0
  199. package/registry/examples/search-field/global.js +19 -0
  200. package/registry/examples/search-field/global.tsx +15 -0
  201. package/registry/examples/search-field/native/default.d.ts +4 -0
  202. package/registry/examples/search-field/native/default.dark.png +0 -0
  203. package/registry/examples/search-field/native/default.js +13 -0
  204. package/registry/examples/search-field/native/default.light.png +0 -0
  205. package/registry/examples/search-field/native/default.tsx +7 -0
  206. package/registry/examples/search-field/suggestions.d.ts +4 -0
  207. package/registry/examples/search-field/suggestions.js +30 -0
  208. package/registry/examples/search-field/suggestions.tsx +27 -0
  209. package/registry/examples/search-field/toolbar.d.ts +4 -0
  210. package/registry/examples/search-field/toolbar.js +17 -0
  211. package/registry/examples/search-field/toolbar.tsx +21 -0
  212. package/registry/examples/tag-input/recipients.d.ts +4 -0
  213. package/registry/examples/tag-input/recipients.js +23 -0
  214. package/registry/examples/tag-input/recipients.tsx +20 -0
  215. package/registry/examples/tag-input/video-tags.d.ts +4 -0
  216. package/registry/examples/tag-input/video-tags.js +26 -0
  217. package/registry/examples/tag-input/video-tags.tsx +22 -0
  218. package/registry/examples/video-player/default.d.ts +4 -0
  219. package/registry/examples/video-player/default.js +12 -0
  220. package/registry/examples/video-player/default.tsx +8 -0
  221. package/registry/examples/video-player/gated.d.ts +4 -0
  222. package/registry/examples/video-player/gated.js +26 -0
  223. package/registry/examples/video-player/gated.tsx +23 -0
  224. package/registry/examples/video-player/native/default.d.ts +4 -0
  225. package/registry/examples/video-player/native/default.dark.png +0 -0
  226. package/registry/examples/video-player/native/default.js +18 -0
  227. package/registry/examples/video-player/native/default.light.png +0 -0
  228. package/registry/examples/video-player/native/default.tsx +12 -0
  229. package/registry/examples/video-player/signed-source.d.ts +4 -0
  230. package/registry/examples/video-player/signed-source.js +16 -0
  231. package/registry/examples/video-player/signed-source.tsx +15 -0
  232. package/registry/examples/video-player/vertical.d.ts +4 -0
  233. package/registry/examples/video-player/vertical.js +12 -0
  234. package/registry/examples/video-player/vertical.tsx +12 -0
  235. package/registry/examples/video-trimmer/custom.d.ts +4 -0
  236. package/registry/examples/video-trimmer/custom.js +24 -0
  237. package/registry/examples/video-trimmer/custom.tsx +26 -0
  238. package/registry/examples/video-trimmer/filmstrip.d.ts +4 -0
  239. package/registry/examples/video-trimmer/filmstrip.js +15 -0
  240. package/registry/examples/video-trimmer/filmstrip.tsx +13 -0
  241. package/registry/examples/video-trimmer/playhead.d.ts +4 -0
  242. package/registry/examples/video-trimmer/playhead.js +15 -0
  243. package/registry/examples/video-trimmer/playhead.tsx +13 -0
  244. package/registry/field.json +1 -1
  245. package/registry/file-upload.json +471 -0
  246. package/registry/filter-bar.json +347 -0
  247. package/registry/glow-card.json +1 -1
  248. package/registry/image-cropper.json +313 -0
  249. package/registry/index.json +255 -1
  250. package/registry/iso.json +1 -1
  251. package/registry/kbd.json +1 -1
  252. package/registry/loader.json +1 -1
  253. package/registry/marquee.json +1 -1
  254. package/registry/mascots.json +1 -1
  255. package/registry/media-capture.json +347 -0
  256. package/registry/meter.json +3 -3
  257. package/registry/nav-bar.json +1 -1
  258. package/registry/number-ticker.json +1 -1
  259. package/registry/page-header.json +1 -1
  260. package/registry/pagination.json +475 -0
  261. package/registry/popover.json +1 -1
  262. package/registry/progress.json +5 -5
  263. package/registry/radio-group.json +1 -1
  264. package/registry/search-field.json +436 -0
  265. package/registry/section-backdrop.json +1 -1
  266. package/registry/separator.json +1 -1
  267. package/registry/skeleton.json +1 -1
  268. package/registry/slider.json +1 -1
  269. package/registry/slot.json +1 -1
  270. package/registry/spinner.json +1 -1
  271. package/registry/stat.json +1 -1
  272. package/registry/stepper.json +1 -1
  273. package/registry/switch.json +1 -1
  274. package/registry/tabs.json +1 -1
  275. package/registry/tag-input.json +363 -0
  276. package/registry/theme.json +1 -1
  277. package/registry/toast.json +1 -1
  278. package/registry/tooltip.json +1 -1
  279. package/registry/video-player.json +598 -0
  280. package/registry/video-trimmer.json +385 -0
@@ -0,0 +1,238 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const fileUpload: tailwind_variants.TVReturnType<{
5
+ [key: string]: {
6
+ [key: string]: tailwind_variants.ClassValue | {
7
+ error?: tailwind_variants.ClassValue;
8
+ body?: tailwind_variants.ClassValue;
9
+ meta?: tailwind_variants.ClassValue;
10
+ list?: tailwind_variants.ClassValue;
11
+ zoneIcon?: tailwind_variants.ClassValue;
12
+ zoneTitle?: tailwind_variants.ClassValue;
13
+ zoneHint?: tailwind_variants.ClassValue;
14
+ refusals?: tailwind_variants.ClassValue;
15
+ item?: tailwind_variants.ClassValue;
16
+ preview?: tailwind_variants.ClassValue;
17
+ name?: tailwind_variants.ClassValue;
18
+ actions?: tailwind_variants.ClassValue;
19
+ zone?: tailwind_variants.ClassValue;
20
+ browse?: tailwind_variants.ClassValue;
21
+ action?: tailwind_variants.ClassValue;
22
+ };
23
+ };
24
+ } | {
25
+ [x: string]: {
26
+ [x: string]: tailwind_variants.ClassValue | {
27
+ error?: tailwind_variants.ClassValue;
28
+ body?: tailwind_variants.ClassValue;
29
+ meta?: tailwind_variants.ClassValue;
30
+ list?: tailwind_variants.ClassValue;
31
+ zoneIcon?: tailwind_variants.ClassValue;
32
+ zoneTitle?: tailwind_variants.ClassValue;
33
+ zoneHint?: tailwind_variants.ClassValue;
34
+ refusals?: tailwind_variants.ClassValue;
35
+ item?: tailwind_variants.ClassValue;
36
+ preview?: tailwind_variants.ClassValue;
37
+ name?: tailwind_variants.ClassValue;
38
+ actions?: tailwind_variants.ClassValue;
39
+ zone?: tailwind_variants.ClassValue;
40
+ browse?: tailwind_variants.ClassValue;
41
+ action?: tailwind_variants.ClassValue;
42
+ };
43
+ };
44
+ } | {}, {
45
+ zone: string;
46
+ zoneIcon: string;
47
+ zoneTitle: string;
48
+ zoneHint: string;
49
+ browse: string;
50
+ refusals: string;
51
+ list: string;
52
+ item: string;
53
+ preview: string;
54
+ body: string;
55
+ name: string;
56
+ meta: string;
57
+ error: string;
58
+ actions: string;
59
+ action: string;
60
+ }, undefined, {
61
+ [key: string]: {
62
+ [key: string]: tailwind_variants.ClassValue | {
63
+ error?: tailwind_variants.ClassValue;
64
+ body?: tailwind_variants.ClassValue;
65
+ meta?: tailwind_variants.ClassValue;
66
+ list?: tailwind_variants.ClassValue;
67
+ zoneIcon?: tailwind_variants.ClassValue;
68
+ zoneTitle?: tailwind_variants.ClassValue;
69
+ zoneHint?: tailwind_variants.ClassValue;
70
+ refusals?: tailwind_variants.ClassValue;
71
+ item?: tailwind_variants.ClassValue;
72
+ preview?: tailwind_variants.ClassValue;
73
+ name?: tailwind_variants.ClassValue;
74
+ actions?: tailwind_variants.ClassValue;
75
+ zone?: tailwind_variants.ClassValue;
76
+ browse?: tailwind_variants.ClassValue;
77
+ action?: tailwind_variants.ClassValue;
78
+ };
79
+ };
80
+ } | {}, {
81
+ zone: string;
82
+ zoneIcon: string;
83
+ zoneTitle: string;
84
+ zoneHint: string;
85
+ browse: string;
86
+ refusals: string;
87
+ list: string;
88
+ item: string;
89
+ preview: string;
90
+ body: string;
91
+ name: string;
92
+ meta: string;
93
+ error: string;
94
+ actions: string;
95
+ action: string;
96
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
97
+ zone: string;
98
+ zoneIcon: string;
99
+ zoneTitle: string;
100
+ zoneHint: string;
101
+ browse: string;
102
+ refusals: string;
103
+ list: string;
104
+ item: string;
105
+ preview: string;
106
+ body: string;
107
+ name: string;
108
+ meta: string;
109
+ error: string;
110
+ actions: string;
111
+ action: string;
112
+ }>>;
113
+ /** Why a file was refused. */
114
+ type FileRejection = {
115
+ file: File;
116
+ reason: "type" | "size" | "count";
117
+ };
118
+ /** Whether a file matches an `accept` list (`"video/*,.mov,image/png"`). */
119
+ declare function acceptsFile(file: File, accept?: string): boolean;
120
+ /** A size in the locale's words (`"1.4 GB"`, `"820 kB"`), through `@krizaka/intl`. */
121
+ declare function formatBytes(bytes: number, locale?: string): string;
122
+ type DropzoneProps = {
123
+ /** The title in the zone ("Drop your video here"), passed translated. */
124
+ title: string;
125
+ /** The button that opens the file picker ("Choose a file"), passed translated. */
126
+ browseLabel: string;
127
+ /** What is accepted, in words ("MP4 or MOV, up to 4 GB"). */
128
+ hint?: string;
129
+ /** The types accepted, as the `accept` attribute (`"video/*"`, `"image/png,.pdf"`). */
130
+ accept?: string;
131
+ /** The largest file, in bytes. */
132
+ maxSize?: number;
133
+ /** The most files at once (1 unless `multiple`). */
134
+ maxFiles?: number;
135
+ /** Several files at once. */
136
+ multiple?: boolean;
137
+ /** Not available (an upload is running). */
138
+ disabled?: boolean;
139
+ /** On a phone, opens the camera directly (`"environment"` the back one, `"user"` the front one). */
140
+ capture?: "user" | "environment";
141
+ /** Called with the files accepted (never empty). */
142
+ onFiles: (files: File[]) => void;
143
+ /** Called with the files refused and why (show `refusalLabel`'s words, or your own). */
144
+ onReject?: (rejections: FileRejection[]) => void;
145
+ /** The words of a refusal, shown in the zone: `(r) => r.file.name + " is too large"`. Without it, nothing is shown. */
146
+ refusalLabel?: (rejection: FileRejection) => string;
147
+ /** An icon instead of the upload glyph. */
148
+ icon?: React.ReactNode;
149
+ /** Classes merged on the zone. */
150
+ className?: string;
151
+ };
152
+ /** A zone to drop files on, with a button that opens the picker: checks type, size and count. */
153
+ declare function Dropzone({ title, browseLabel, hint, accept, maxSize, maxFiles, multiple, disabled, capture, onFiles, onReject, refusalLabel, icon, className, }: DropzoneProps): React.JSX.Element;
154
+ type UploadStatus = "queued" | "uploading" | "paused" | "done" | "error";
155
+ type UploadItem = {
156
+ /** A stable id. */
157
+ id: string;
158
+ /** The file's name. */
159
+ name: string;
160
+ /** Its size, in bytes. */
161
+ size: number;
162
+ /** Its MIME type (`video/mp4`): picks the preview. */
163
+ type?: string;
164
+ /** Sent so far, between 0 and 1. */
165
+ progress: number;
166
+ /** Where it stands. */
167
+ status: UploadStatus;
168
+ /** Why it failed, passed translated. */
169
+ error?: string;
170
+ /** A preview (an object URL of the file, a thumbnail from the server). */
171
+ previewUrl?: string;
172
+ /** Bytes per second, for the speed and the time left. */
173
+ speed?: number;
174
+ };
175
+ type UploadListLabels = {
176
+ /** The list's accessible name ("Uploads"). */
177
+ list: string;
178
+ pause: (name: string) => string;
179
+ resume: (name: string) => string;
180
+ retry: (name: string) => string;
181
+ cancel: (name: string) => string;
182
+ remove: (name: string) => string;
183
+ /** A state in words: `(status) => "Paused"`… */
184
+ status: (status: UploadStatus) => string;
185
+ /** The time left: `(seconds) => "2 min left"`. */
186
+ remaining: (seconds: number) => string;
187
+ };
188
+ declare const uploadListLabels: UploadListLabels;
189
+ type UploadListProps = {
190
+ /** The uploads, as `useUploadQueue` gives them (or your own state). */
191
+ items: readonly UploadItem[];
192
+ /** Pauses an upload (shown while it uploads, when given). */
193
+ onPause?: (id: string) => void;
194
+ /** Resumes a paused one. */
195
+ onResume?: (id: string) => void;
196
+ /** Tries a failed one again. */
197
+ onRetry?: (id: string) => void;
198
+ /** Stops an upload under way and drops it. */
199
+ onCancel?: (id: string) => void;
200
+ /** Drops a finished or failed one from the list. */
201
+ onRemove?: (id: string) => void;
202
+ /** The locale of sizes and speeds. Default `"en"`. */
203
+ locale?: string;
204
+ /** The words, passed translated; English by default. */
205
+ labels?: Partial<UploadListLabels>;
206
+ /** Classes merged on the list. */
207
+ className?: string;
208
+ };
209
+ /** The files being sent: preview, size, progress, speed and time left, and the actions each state allows. */
210
+ declare function UploadList({ items, onPause, onResume, onRetry, onCancel, onRemove, locale, labels: given, className }: UploadListProps): React.JSX.Element;
211
+ type UploadContext = {
212
+ /** Aborted on pause and cancel: stop sending (`tusUpload.abort()`, `xhr.abort()`). */
213
+ signal: AbortSignal;
214
+ /** Report the bytes sent so far. */
215
+ onProgress: (sent: number) => void;
216
+ /** `true` when this call resumes a paused or failed upload (a Tus client then continues from its offset). */
217
+ resumed: boolean;
218
+ };
219
+ type UploadQueueOptions = {
220
+ /** Sends one file; resolves when it is done, rejects on failure (its `message` becomes the item's error). */
221
+ upload: (file: File, context: UploadContext) => Promise<void>;
222
+ /** How many files go at once. Default 2. */
223
+ concurrency?: number;
224
+ /** Makes an object URL for each file to preview (revoked when it leaves). Default `true`. */
225
+ previews?: boolean;
226
+ };
227
+ /** The state of an upload queue around the app's `upload` function: `add`, `pause`, `resume`, `retry`, `cancel`, `remove`. */
228
+ declare function useUploadQueue(options: UploadQueueOptions): {
229
+ items: UploadItem[];
230
+ add: (files: readonly File[]) => void;
231
+ pause: (id: string) => void;
232
+ resume: (id: string) => void;
233
+ retry: (id: string) => void;
234
+ cancel: (id: string) => void;
235
+ remove: (id: string) => void;
236
+ };
237
+
238
+ export { Dropzone, type DropzoneProps, type FileRejection, type UploadContext, type UploadItem, UploadList, type UploadListLabels, type UploadListProps, type UploadQueueOptions, type UploadStatus, acceptsFile, fileUpload, formatBytes, uploadListLabels, useUploadQueue };
@@ -0,0 +1,437 @@
1
+ "use client";
2
+ import {
3
+ CloseGlyph,
4
+ FileGlyph,
5
+ PauseGlyph,
6
+ PlayGlyph,
7
+ RetryGlyph,
8
+ UploadGlyph
9
+ } from "./chunk-YX6CNVJA.js";
10
+
11
+ // src/file-upload/file-upload.tsx
12
+ import { getNumberFormat } from "@krizaka/intl";
13
+ import * as React2 from "react";
14
+ import { tv as tv2 } from "tailwind-variants";
15
+
16
+ // src/progress/progress.tsx
17
+ import * as React from "react";
18
+ import { tv } from "tailwind-variants";
19
+ import { jsx, jsxs } from "react/jsx-runtime";
20
+ var progress = tv({
21
+ slots: {
22
+ root: "relative",
23
+ track: "",
24
+ indicator: "",
25
+ center: "absolute inset-0 flex flex-col items-center justify-center text-center",
26
+ buffer: "absolute inset-y-0 left-0 -z-10 rounded-full bg-accent/25 transition-[width] duration-500 motion-reduce:transition-none",
27
+ frame: "flex w-full flex-col gap-1.5",
28
+ header: "flex items-baseline gap-2 text-xs",
29
+ caption: "min-w-0 flex-1 truncate font-medium text-fg",
30
+ figure: "shrink-0 tabular-nums text-fg-secondary"
31
+ },
32
+ variants: {
33
+ variant: {
34
+ bar: {
35
+ root: "relative isolate w-full overflow-hidden rounded-full bg-surface-3",
36
+ indicator: "kz-progress h-full rounded-full bg-linear-to-r from-accent to-accent-2 transition-[width] duration-500 motion-reduce:transition-none data-[state=indeterminate]:w-2/5"
37
+ },
38
+ ring: {
39
+ root: "inline-flex shrink-0 items-center justify-center",
40
+ track: "stroke-border-default",
41
+ indicator: "stroke-accent transition-[stroke-dashoffset] duration-1000 motion-reduce:transition-none data-[state=indeterminate]:origin-center data-[state=indeterminate]:animate-spin motion-reduce:data-[state=indeterminate]:animate-none"
42
+ }
43
+ },
44
+ size: { sm: {}, md: {}, lg: {} },
45
+ status: {
46
+ active: {},
47
+ // Paused: the fill rests, striped — the task is waiting for someone, not broken.
48
+ paused: { indicator: "kz-progress-paused opacity-70" },
49
+ // Failed: the fill turns to the danger colour where it stopped.
50
+ error: { indicator: "from-danger to-danger stroke-danger" }
51
+ }
52
+ },
53
+ compoundVariants: [
54
+ { variant: "bar", size: "sm", class: { root: "h-1" } },
55
+ { variant: "bar", size: "md", class: { root: "h-2" } },
56
+ { variant: "bar", size: "lg", class: { root: "h-3" } },
57
+ { variant: "ring", size: "sm", class: { root: "h-10 w-10" } },
58
+ { variant: "ring", size: "md", class: { root: "h-20 w-20" } },
59
+ { variant: "ring", size: "lg", class: { root: "h-36 w-36" } }
60
+ ],
61
+ defaultVariants: { variant: "bar", size: "md", status: "active" }
62
+ });
63
+ var STROKE = { sm: 12, md: 9, lg: 7 };
64
+ function Progress({
65
+ variant = "bar",
66
+ size = "md",
67
+ value,
68
+ max = 100,
69
+ label,
70
+ valueText,
71
+ className,
72
+ children,
73
+ buffer,
74
+ segments,
75
+ status = "active",
76
+ showLabel,
77
+ eta,
78
+ ...props
79
+ }) {
80
+ const s = progress({ variant, size, status });
81
+ const maskId = `kz-seg-${React.useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
82
+ const known = typeof value === "number" && Number.isFinite(value);
83
+ const ratio = known ? Math.min(1, Math.max(0, value / (max || 1))) : 0;
84
+ const percent = Math.round(ratio * 100);
85
+ const state = !known ? "indeterminate" : ratio >= 1 ? "complete" : "loading";
86
+ const aria = {
87
+ role: "progressbar",
88
+ "aria-label": label,
89
+ "aria-valuemin": known ? 0 : void 0,
90
+ "aria-valuemax": known ? max : void 0,
91
+ "aria-valuenow": known ? Math.min(max, Math.max(0, value)) : void 0,
92
+ "aria-valuetext": [known ? valueText ?? `${percent}%` : valueText, eta].filter(Boolean).join(", ") || void 0,
93
+ "data-state": state,
94
+ "data-status": status === "active" ? void 0 : status,
95
+ "data-value": known ? value : void 0,
96
+ "data-variant": variant
97
+ };
98
+ if (variant === "ring") {
99
+ const stroke = STROKE[size];
100
+ const r = 50 - stroke / 2;
101
+ return /* @__PURE__ */ jsxs("div", { ...aria, className: s.root({ className }), ...props, children: [
102
+ /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 100 100", className: "h-full w-full -rotate-90", "aria-hidden": true, children: [
103
+ segments && segments > 1 && /* @__PURE__ */ jsx("mask", { id: maskId, children: /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r, fill: "none", stroke: "white", strokeWidth: stroke + 2, pathLength: 100, strokeDasharray: `${100 / segments - 2} 2` }) }),
104
+ /* @__PURE__ */ jsxs("g", { mask: segments && segments > 1 ? `url(#${maskId})` : void 0, children: [
105
+ /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r, fill: "none", strokeWidth: stroke, className: s.track() }),
106
+ /* @__PURE__ */ jsx(
107
+ "circle",
108
+ {
109
+ cx: "50",
110
+ cy: "50",
111
+ r,
112
+ fill: "none",
113
+ strokeWidth: stroke,
114
+ strokeLinecap: "round",
115
+ pathLength: 100,
116
+ strokeDasharray: 100,
117
+ strokeDashoffset: known ? 100 - percent : 75,
118
+ "data-state": state,
119
+ className: s.indicator()
120
+ }
121
+ )
122
+ ] })
123
+ ] }),
124
+ children !== void 0 && /* @__PURE__ */ jsx("div", { className: s.center(), children })
125
+ ] });
126
+ }
127
+ const segmented = segments && segments > 1 ? { "--kz-segments": segments } : void 0;
128
+ const bufferRatio = typeof buffer === "number" && Number.isFinite(buffer) ? Math.min(1, Math.max(0, buffer / (max || 1))) : null;
129
+ const bar = /* @__PURE__ */ jsxs("div", { ...aria, className: s.root({ className: [segmented && "kz-progress-segmented", className].filter(Boolean).join(" ") || void 0 }), style: segmented, ...props, children: [
130
+ /* @__PURE__ */ jsx("div", { "data-state": state, className: s.indicator(), style: known ? { width: `${ratio * 100}%` } : void 0 }),
131
+ bufferRatio !== null && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: s.buffer(), style: { width: `${bufferRatio * 100}%` } })
132
+ ] });
133
+ if (!showLabel) return bar;
134
+ const figure = [known ? valueText ?? `${percent} %` : valueText, eta].filter(Boolean).join(" \xB7 ");
135
+ return /* @__PURE__ */ jsxs("div", { className: s.frame(), children: [
136
+ /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: s.header(), children: [
137
+ /* @__PURE__ */ jsx("span", { className: s.caption(), children: label }),
138
+ figure && /* @__PURE__ */ jsx("span", { className: s.figure(), children: figure })
139
+ ] }),
140
+ bar
141
+ ] });
142
+ }
143
+
144
+ // src/file-upload/file-upload.tsx
145
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
146
+ var fileUpload = tv2({
147
+ slots: {
148
+ zone: "relative flex w-full flex-col items-center justify-center gap-3 rounded-xl border-2 border-dashed border-border-default bg-surface-1 px-6 py-10 text-center transition-colors data-[dragging]:border-accent data-[dragging]:bg-accent-soft data-[disabled]:opacity-50 has-[:focus-visible]:border-accent",
149
+ zoneIcon: "flex h-12 w-12 items-center justify-center rounded-full bg-surface-3 text-fg-secondary",
150
+ zoneTitle: "text-sm font-semibold text-fg",
151
+ zoneHint: "text-xs text-fg-secondary",
152
+ browse: "inline-flex h-9 items-center justify-center rounded-lg bg-accent px-4 text-sm font-semibold text-on-accent transition-colors hover:bg-accent-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:pointer-events-none",
153
+ refusals: "w-full text-left text-xs font-medium text-fg-danger",
154
+ list: "flex w-full flex-col gap-2",
155
+ item: "flex items-center gap-3 rounded-xl border border-border-default bg-surface-1 p-3 data-[status=error]:border-danger/60",
156
+ preview: "flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-surface-3 text-fg-secondary",
157
+ body: "flex min-w-0 flex-1 flex-col gap-1.5",
158
+ name: "truncate text-sm font-semibold text-fg",
159
+ meta: "flex flex-wrap gap-x-2 text-xs tabular-nums text-fg-secondary",
160
+ error: "text-xs font-medium text-fg-danger",
161
+ actions: "flex shrink-0 items-center gap-1",
162
+ action: "inline-flex h-8 w-8 items-center justify-center rounded-md text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
163
+ }
164
+ });
165
+ function acceptsFile(file, accept) {
166
+ if (!accept) return true;
167
+ const name = file.name.toLowerCase();
168
+ const type = file.type.toLowerCase();
169
+ return accept.split(",").map((rule) => rule.trim().toLowerCase()).filter(Boolean).some((rule) => rule.startsWith(".") ? name.endsWith(rule) : rule.endsWith("/*") ? type.startsWith(rule.slice(0, -1)) : type === rule);
170
+ }
171
+ function formatBytes(bytes, locale = "en") {
172
+ const units = ["byte", "kilobyte", "megabyte", "gigabyte", "terabyte"];
173
+ let value = Math.max(0, bytes);
174
+ let unit = 0;
175
+ while (value >= 1e3 && unit < units.length - 1) {
176
+ value /= 1e3;
177
+ unit += 1;
178
+ }
179
+ return getNumberFormat(locale, { style: "unit", unit: units[unit], unitDisplay: "short", maximumFractionDigits: value < 10 && unit > 0 ? 1 : 0 }).format(value);
180
+ }
181
+ function Dropzone({
182
+ title,
183
+ browseLabel,
184
+ hint,
185
+ accept,
186
+ maxSize,
187
+ maxFiles,
188
+ multiple,
189
+ disabled,
190
+ capture,
191
+ onFiles,
192
+ onReject,
193
+ refusalLabel,
194
+ icon,
195
+ className
196
+ }) {
197
+ const s = fileUpload();
198
+ const input = React2.useRef(null);
199
+ const [dragging, setDragging] = React2.useState(false);
200
+ const [refused, setRefused] = React2.useState([]);
201
+ const depth = React2.useRef(0);
202
+ const id = React2.useId();
203
+ const limit = maxFiles ?? (multiple ? Infinity : 1);
204
+ const take = (list) => {
205
+ const files = [...list];
206
+ const accepted = [];
207
+ const rejections = [];
208
+ for (const file of files) {
209
+ if (!acceptsFile(file, accept)) rejections.push({ file, reason: "type" });
210
+ else if (maxSize !== void 0 && file.size > maxSize) rejections.push({ file, reason: "size" });
211
+ else if (accepted.length >= limit) rejections.push({ file, reason: "count" });
212
+ else accepted.push(file);
213
+ }
214
+ setRefused(rejections);
215
+ if (accepted.length) onFiles(accepted);
216
+ if (rejections.length) onReject?.(rejections);
217
+ };
218
+ return /* @__PURE__ */ jsxs2(
219
+ "div",
220
+ {
221
+ className: s.zone({ className }),
222
+ "data-dragging": dragging ? "" : void 0,
223
+ "data-disabled": disabled ? "" : void 0,
224
+ onDragEnter: (event) => {
225
+ if (disabled) return;
226
+ event.preventDefault();
227
+ depth.current += 1;
228
+ setDragging(true);
229
+ },
230
+ onDragOver: (event) => {
231
+ if (disabled) return;
232
+ event.preventDefault();
233
+ event.dataTransfer.dropEffect = "copy";
234
+ },
235
+ onDragLeave: () => {
236
+ depth.current = Math.max(0, depth.current - 1);
237
+ if (depth.current === 0) setDragging(false);
238
+ },
239
+ onDrop: (event) => {
240
+ if (disabled) return;
241
+ event.preventDefault();
242
+ depth.current = 0;
243
+ setDragging(false);
244
+ take(event.dataTransfer.files);
245
+ },
246
+ children: [
247
+ /* @__PURE__ */ jsx2("span", { className: s.zoneIcon(), "aria-hidden": true, children: icon ?? /* @__PURE__ */ jsx2(UploadGlyph, { className: "h-6 w-6" }) }),
248
+ /* @__PURE__ */ jsx2("p", { id: `${id}-title`, className: s.zoneTitle(), children: title }),
249
+ hint ? /* @__PURE__ */ jsx2("p", { id: `${id}-hint`, className: s.zoneHint(), children: hint }) : null,
250
+ /* @__PURE__ */ jsx2(
251
+ "button",
252
+ {
253
+ type: "button",
254
+ className: s.browse(),
255
+ disabled,
256
+ "aria-describedby": [`${id}-title`, hint ? `${id}-hint` : null].filter(Boolean).join(" "),
257
+ onClick: () => input.current?.click(),
258
+ children: browseLabel
259
+ }
260
+ ),
261
+ /* @__PURE__ */ jsx2(
262
+ "input",
263
+ {
264
+ ref: input,
265
+ type: "file",
266
+ tabIndex: -1,
267
+ "aria-hidden": true,
268
+ className: "sr-only",
269
+ accept,
270
+ multiple,
271
+ capture,
272
+ disabled,
273
+ onChange: (event) => {
274
+ if (event.target.files?.length) take(event.target.files);
275
+ event.target.value = "";
276
+ }
277
+ }
278
+ ),
279
+ refusalLabel && refused.length > 0 ? /* @__PURE__ */ jsx2("ul", { role: "alert", className: s.refusals(), children: refused.map((r) => /* @__PURE__ */ jsx2("li", { children: refusalLabel(r) }, `${r.file.name}-${r.reason}`)) }) : null
280
+ ]
281
+ }
282
+ );
283
+ }
284
+ var uploadListLabels = {
285
+ list: "Uploads",
286
+ pause: (name) => `Pause ${name}`,
287
+ resume: (name) => `Resume ${name}`,
288
+ retry: (name) => `Retry ${name}`,
289
+ cancel: (name) => `Cancel ${name}`,
290
+ remove: (name) => `Remove ${name}`,
291
+ status: (status) => ({ queued: "Waiting", uploading: "Uploading", paused: "Paused", done: "Uploaded", error: "Failed" })[status],
292
+ remaining: (seconds) => seconds < 60 ? `${Math.ceil(seconds)} s left` : `${Math.ceil(seconds / 60)} min left`
293
+ };
294
+ function Preview({ item }) {
295
+ if (item.previewUrl && item.type?.startsWith("image/")) return /* @__PURE__ */ jsx2("img", { src: item.previewUrl, alt: "", className: "h-full w-full object-cover" });
296
+ if (item.previewUrl && item.type?.startsWith("video/")) return /* @__PURE__ */ jsx2("video", { src: item.previewUrl, muted: true, playsInline: true, preload: "metadata", className: "h-full w-full object-cover", "aria-hidden": true });
297
+ return /* @__PURE__ */ jsx2(FileGlyph, { className: "h-5 w-5" });
298
+ }
299
+ function UploadList({ items, onPause, onResume, onRetry, onCancel, onRemove, locale = "en", labels: given, className }) {
300
+ const labels = { ...uploadListLabels, ...given };
301
+ const s = fileUpload();
302
+ const action = (label, run, glyph) => /* @__PURE__ */ jsx2("button", { type: "button", className: s.action(), "aria-label": label, title: label, onClick: run, children: glyph });
303
+ return /* @__PURE__ */ jsx2("ul", { "aria-label": labels.list, className: s.list({ className }), children: items.map((item) => {
304
+ const left = item.status === "uploading" && item.speed ? (1 - item.progress) * item.size / item.speed : null;
305
+ return /* @__PURE__ */ jsxs2("li", { className: s.item(), "data-status": item.status, children: [
306
+ /* @__PURE__ */ jsx2("span", { className: s.preview(), children: /* @__PURE__ */ jsx2(Preview, { item }) }),
307
+ /* @__PURE__ */ jsxs2("div", { className: s.body(), children: [
308
+ /* @__PURE__ */ jsx2("p", { className: s.name(), children: item.name }),
309
+ item.status !== "done" && item.status !== "error" ? /* @__PURE__ */ jsx2(Progress, { size: "sm", label: item.name, value: item.status === "queued" ? null : Math.round(item.progress * 100) }) : null,
310
+ /* @__PURE__ */ jsxs2("p", { className: s.meta(), children: [
311
+ /* @__PURE__ */ jsx2("span", { children: labels.status(item.status) }),
312
+ /* @__PURE__ */ jsx2("span", { children: item.status === "done" ? formatBytes(item.size, locale) : `${formatBytes(item.progress * item.size, locale)} / ${formatBytes(item.size, locale)}` }),
313
+ item.status === "uploading" && item.speed ? /* @__PURE__ */ jsxs2("span", { children: [
314
+ formatBytes(item.speed, locale),
315
+ "/s"
316
+ ] }) : null,
317
+ left !== null ? /* @__PURE__ */ jsx2("span", { children: labels.remaining(left) }) : null
318
+ ] }),
319
+ item.status === "error" && item.error ? /* @__PURE__ */ jsx2("p", { role: "alert", className: s.error(), children: item.error }) : null
320
+ ] }),
321
+ /* @__PURE__ */ jsxs2("div", { className: s.actions(), children: [
322
+ item.status === "uploading" && onPause && action(labels.pause(item.name), () => onPause(item.id), /* @__PURE__ */ jsx2(PauseGlyph, { className: "h-4 w-4" })),
323
+ item.status === "paused" && onResume && action(labels.resume(item.name), () => onResume(item.id), /* @__PURE__ */ jsx2(PlayGlyph, { className: "h-4 w-4" })),
324
+ item.status === "error" && onRetry && action(labels.retry(item.name), () => onRetry(item.id), /* @__PURE__ */ jsx2(RetryGlyph, { className: "h-4 w-4" })),
325
+ (item.status === "done" || item.status === "error") && onRemove ? action(labels.remove(item.name), () => onRemove(item.id), /* @__PURE__ */ jsx2(CloseGlyph, { className: "h-4 w-4" })) : item.status !== "done" && onCancel ? action(labels.cancel(item.name), () => onCancel(item.id), /* @__PURE__ */ jsx2(CloseGlyph, { className: "h-4 w-4" })) : null
326
+ ] })
327
+ ] }, item.id);
328
+ }) });
329
+ }
330
+ function createQueue(initial, emit) {
331
+ let current = initial;
332
+ const options = () => current;
333
+ const entries = /* @__PURE__ */ new Map();
334
+ const sync = () => emit([...entries.values()].map((e) => e.item));
335
+ const patch = (id, next) => {
336
+ const entry = entries.get(id);
337
+ if (!entry) return;
338
+ entry.item = { ...entry.item, ...next };
339
+ sync();
340
+ };
341
+ const pump = () => {
342
+ const { upload, concurrency = 2 } = options();
343
+ const all = [...entries.values()];
344
+ let running = all.filter((e) => e.item.status === "uploading").length;
345
+ for (const entry of all) {
346
+ if (running >= concurrency) break;
347
+ if (entry.item.status !== "queued") continue;
348
+ running += 1;
349
+ const controller = new AbortController();
350
+ const resumed = entry.started;
351
+ entry.controller = controller;
352
+ entry.started = true;
353
+ entry.last = { at: Date.now(), sent: entry.item.progress * entry.item.size };
354
+ patch(entry.item.id, { status: "uploading", error: void 0 });
355
+ upload(entry.file, {
356
+ signal: controller.signal,
357
+ resumed,
358
+ onProgress: (sent) => {
359
+ if (controller.signal.aborted) return;
360
+ const now = Date.now();
361
+ const last = entry.last ?? { at: now, sent };
362
+ const fresh = now - last.at > 400;
363
+ const speed = fresh ? (sent - last.sent) / (now - last.at) * 1e3 : entry.item.speed;
364
+ if (fresh) entry.last = { at: now, sent };
365
+ patch(entry.item.id, { progress: entry.item.size ? Math.min(1, sent / entry.item.size) : 0, speed });
366
+ }
367
+ }).then(
368
+ () => {
369
+ if (controller.signal.aborted) return;
370
+ patch(entry.item.id, { status: "done", progress: 1, speed: void 0 });
371
+ pump();
372
+ },
373
+ (error) => {
374
+ if (controller.signal.aborted) return;
375
+ patch(entry.item.id, { status: "error", error: error instanceof Error ? error.message : String(error), speed: void 0 });
376
+ pump();
377
+ }
378
+ );
379
+ }
380
+ };
381
+ const release = (entry) => {
382
+ entry.controller?.abort();
383
+ if (entry.item.previewUrl) URL.revokeObjectURL(entry.item.previewUrl);
384
+ };
385
+ return {
386
+ configure(next) {
387
+ current = next;
388
+ },
389
+ add(files) {
390
+ const { previews = true } = options();
391
+ for (const file of files) {
392
+ const id = `${file.name}-${file.size}-${Math.random().toString(36).slice(2, 8)}`;
393
+ const previewUrl = previews && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : void 0;
394
+ entries.set(id, { file, controller: null, started: false, item: { id, name: file.name, size: file.size, type: file.type, progress: 0, status: "queued", previewUrl } });
395
+ }
396
+ sync();
397
+ pump();
398
+ },
399
+ pause(id) {
400
+ entries.get(id)?.controller?.abort();
401
+ patch(id, { status: "paused", speed: void 0 });
402
+ pump();
403
+ },
404
+ resume(id) {
405
+ patch(id, { status: "queued" });
406
+ pump();
407
+ },
408
+ remove(id) {
409
+ const entry = entries.get(id);
410
+ if (!entry) return;
411
+ release(entry);
412
+ entries.delete(id);
413
+ sync();
414
+ pump();
415
+ },
416
+ dispose() {
417
+ for (const entry of entries.values()) release(entry);
418
+ }
419
+ };
420
+ }
421
+ function useUploadQueue(options) {
422
+ const [items, setItems] = React2.useState([]);
423
+ const [queue] = React2.useState(() => createQueue(options, setItems));
424
+ React2.useLayoutEffect(() => queue.configure(options));
425
+ React2.useEffect(() => () => queue.dispose(), [queue]);
426
+ return { items, add: queue.add, pause: queue.pause, resume: queue.resume, retry: queue.resume, cancel: queue.remove, remove: queue.remove };
427
+ }
428
+ export {
429
+ Dropzone,
430
+ UploadList,
431
+ acceptsFile,
432
+ fileUpload,
433
+ formatBytes,
434
+ uploadListLabels,
435
+ useUploadQueue
436
+ };
437
+ //# sourceMappingURL=file-upload.js.map