@zayne-labs/ui-react 0.10.9 → 0.10.10

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 (76) hide show
  1. package/dist/esm/{cn-s-D7vHW1.js → cn-DdD3uYxA.js} +1 -1
  2. package/dist/esm/{cn-s-D7vHW1.js.map → cn-DdD3uYxA.js.map} +1 -1
  3. package/dist/esm/common/await/index.d.ts +46 -4
  4. package/dist/esm/common/await/index.js +86 -4
  5. package/dist/esm/common/await/index.js.map +1 -0
  6. package/dist/esm/common/error-boundary/index.d.ts +1 -1
  7. package/dist/esm/common/for/index.d.ts +23 -2
  8. package/dist/esm/common/for/index.js +1 -1
  9. package/dist/esm/common/presence/index.js +1 -1
  10. package/dist/esm/common/show/index.d.ts +32 -2
  11. package/dist/esm/common/slot/index.d.ts +16 -2
  12. package/dist/esm/common/suspense-with-boundary/index.d.ts +2 -2
  13. package/dist/esm/common/suspense-with-boundary/index.js +20 -3
  14. package/dist/esm/common/suspense-with-boundary/index.js.map +1 -0
  15. package/dist/esm/common/switch/index.d.ts +28 -2
  16. package/dist/esm/common/switch/index.js +37 -2
  17. package/dist/esm/common/switch/index.js.map +1 -0
  18. package/dist/esm/common/teleport/index.d.ts +14 -2
  19. package/dist/esm/common/teleport/index.js +31 -2
  20. package/dist/esm/common/teleport/index.js.map +1 -0
  21. package/dist/esm/{for-DK5rEY_m.js → for-BYsFEk3R.js} +1 -1
  22. package/dist/esm/{for-DK5rEY_m.js.map → for-BYsFEk3R.js.map} +1 -1
  23. package/dist/esm/{index-C0L6V4Zq.d.ts → index-BwhRxsrZ.d.ts} +3 -3
  24. package/dist/esm/{index-lw5txqar.d.ts → index-C_2Onnhl.d.ts} +4 -4
  25. package/dist/esm/{presence-CL5_GHQH.js → presence-CAQElNtY.js} +1 -1
  26. package/dist/esm/{presence-CL5_GHQH.js.map → presence-CAQElNtY.js.map} +1 -1
  27. package/dist/esm/ui/card/index.d.ts +20 -2
  28. package/dist/esm/ui/card/index.js +94 -4
  29. package/dist/esm/ui/card/index.js.map +1 -0
  30. package/dist/esm/ui/carousel/index.d.ts +95 -2
  31. package/dist/esm/ui/carousel/index.js +285 -13
  32. package/dist/esm/ui/carousel/index.js.map +1 -0
  33. package/dist/esm/ui/drag-scroll/index.d.ts +23 -2
  34. package/dist/esm/ui/drag-scroll/index.js +114 -3
  35. package/dist/esm/ui/drag-scroll/index.js.map +1 -0
  36. package/dist/esm/ui/drop-zone/index.d.ts +346 -2
  37. package/dist/esm/ui/drop-zone/index.js +1026 -14
  38. package/dist/esm/ui/drop-zone/index.js.map +1 -0
  39. package/dist/esm/ui/form/index.d.ts +227 -2
  40. package/dist/esm/ui/form/index.js +573 -5
  41. package/dist/esm/ui/form/index.js.map +1 -0
  42. package/package.json +6 -8
  43. package/dist/esm/await-DDgVzpvI.js +0 -87
  44. package/dist/esm/await-DDgVzpvI.js.map +0 -1
  45. package/dist/esm/card-DDLJVCwL.js +0 -95
  46. package/dist/esm/card-DDLJVCwL.js.map +0 -1
  47. package/dist/esm/carousel-B051PAAX.js +0 -285
  48. package/dist/esm/carousel-B051PAAX.js.map +0 -1
  49. package/dist/esm/common/index.d.ts +0 -9
  50. package/dist/esm/common/index.js +0 -11
  51. package/dist/esm/common-PS3X58Pj.js +0 -0
  52. package/dist/esm/drag-scroll-Bb1SG4On.js +0 -115
  53. package/dist/esm/drag-scroll-Bb1SG4On.js.map +0 -1
  54. package/dist/esm/drop-zone-FkkbzZ3j.js +0 -1019
  55. package/dist/esm/drop-zone-FkkbzZ3j.js.map +0 -1
  56. package/dist/esm/form-DyGy9LnA.js +0 -574
  57. package/dist/esm/form-DyGy9LnA.js.map +0 -1
  58. package/dist/esm/index-BJUTFSec.d.ts +0 -227
  59. package/dist/esm/index-BeCCgTjL.d.ts +0 -16
  60. package/dist/esm/index-BsGxDKlt.d.ts +0 -32
  61. package/dist/esm/index-C1GPFYKG.d.ts +0 -23
  62. package/dist/esm/index-CZjeBSoQ.d.ts +0 -14
  63. package/dist/esm/index-CffEFE66.d.ts +0 -28
  64. package/dist/esm/index-DFHOx2Pf.d.ts +0 -23
  65. package/dist/esm/index-DXwAMkn0.d.ts +0 -46
  66. package/dist/esm/index-RpfwCCWX.d.ts +0 -345
  67. package/dist/esm/index-bD-GMufy.d.ts +0 -20
  68. package/dist/esm/index-ipYGGqwN.d.ts +0 -95
  69. package/dist/esm/suspense-with-boundary-D-1NYDV4.js +0 -21
  70. package/dist/esm/suspense-with-boundary-D-1NYDV4.js.map +0 -1
  71. package/dist/esm/switch-Ch22z21e.js +0 -38
  72. package/dist/esm/switch-Ch22z21e.js.map +0 -1
  73. package/dist/esm/teleport-C8TzRm4M.js +0 -32
  74. package/dist/esm/teleport-C8TzRm4M.js.map +0 -1
  75. package/dist/esm/ui/index.d.ts +0 -6
  76. package/dist/esm/ui/index.js +0 -18
@@ -1,17 +1,1029 @@
1
1
  "use client";
2
2
 
3
3
 
4
- import "../../error-boundary-y9Samt_s.js";
5
- import "../../slot-WVWfOlr3.js";
6
- import "../../await-DDgVzpvI.js";
7
- import "../../for-DK5rEY_m.js";
8
- import "../../show-N1ZXBhoA.js";
9
- import "../../suspense-with-boundary-D-1NYDV4.js";
10
- import "../../switch-Ch22z21e.js";
11
- import "../../teleport-C8TzRm4M.js";
12
- import "../../common-PS3X58Pj.js";
13
- import "../../cn-s-D7vHW1.js";
14
- import "../../presence-CL5_GHQH.js";
15
- import { DropZoneArea, DropZoneContainer, DropZoneContext, DropZoneError, DropZoneFileClear, DropZoneFileItem, DropZoneFileItemDelete, DropZoneFileItemMetadata, DropZoneFileItemPreview, DropZoneFileItemProgress, DropZoneFileList, DropZoneInput, DropZoneRoot, DropZoneTrigger, drop_zone_parts_exports, useDropZone, useDropZoneStoreContext } from "../../drop-zone-FkkbzZ3j.js";
16
-
17
- export { drop_zone_parts_exports as DropZone, DropZoneArea, DropZoneContainer, DropZoneContext, DropZoneError, DropZoneFileClear, DropZoneFileItem, DropZoneFileItemDelete, DropZoneFileItemMetadata, DropZoneFileItemPreview, DropZoneFileItemProgress, DropZoneFileList, DropZoneInput, DropZoneRoot, DropZoneTrigger, useDropZone, useDropZoneStoreContext };
4
+ import { __export } from "../../chunk-CTAAG5j7.js";
5
+ import { SlotRoot } from "../../slot-WVWfOlr3.js";
6
+ import { For } from "../../for-BYsFEk3R.js";
7
+ import { Presence } from "../../presence-CAQElNtY.js";
8
+ import { cnMerge } from "../../cn-DdD3uYxA.js";
9
+ import { composeRefs, composeTwoEventHandlers } from "@zayne-labs/toolkit-react/utils";
10
+ import { isFile, isFunction, isNumber, isObject, isString } from "@zayne-labs/toolkit-type-helpers";
11
+ import { useCallback, useMemo, useRef } from "react";
12
+ import { createCustomContext, useCallbackRef, useConstant, useShallowCompSelector, useShallowCompValue, useStore, useUnmountEffect } from "@zayne-labs/toolkit-react";
13
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
14
+ import { createFileUrl, createStore, dataAttr, formatBytes, generateFileID, handleFileValidationAsync, toArray } from "@zayne-labs/toolkit-core";
15
+ import { createZustandContext } from "@zayne-labs/toolkit-react/zustand";
16
+
17
+ //#region src/components/ui/drop-zone/drop-zone-context.ts
18
+ const [DropZoneStoreContextProvider, useDropZoneStoreContext] = createZustandContext({
19
+ hookName: "useDropZoneStoreContext",
20
+ name: "DropZoneStoreContext",
21
+ providerName: "DropZoneRoot"
22
+ });
23
+ const [DropZoneRootContextProvider, useDropZoneRootContext] = createCustomContext({
24
+ hookName: "useDropZoneRootContext",
25
+ name: "DropZoneRootContext",
26
+ providerName: "DropZoneRoot"
27
+ });
28
+ const [FileItemContextProvider, useFileItemContext] = createCustomContext({
29
+ defaultValue: null,
30
+ hookName: "useFileItemContext",
31
+ name: "FileItemContext",
32
+ providerName: "FileItem",
33
+ strict: false
34
+ });
35
+
36
+ //#endregion
37
+ //#region src/components/ui/drop-zone/icons.tsx
38
+ const FileVideoIcon = (props) => /* @__PURE__ */ jsx("svg", {
39
+ xmlns: "http://www.w3.org/2000/svg",
40
+ width: "1em",
41
+ height: "1em",
42
+ viewBox: "0 0 24 24",
43
+ ...props,
44
+ children: /* @__PURE__ */ jsxs("g", {
45
+ fill: "none",
46
+ stroke: "currentColor",
47
+ strokeLinecap: "round",
48
+ strokeLinejoin: "round",
49
+ strokeWidth: "2",
50
+ children: [/* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }), /* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4m-10 3l5 3l-5 3z" })]
51
+ })
52
+ });
53
+ const FileAudioIcon = (props) => /* @__PURE__ */ jsx("svg", {
54
+ xmlns: "http://www.w3.org/2000/svg",
55
+ width: "1em",
56
+ height: "1em",
57
+ viewBox: "0 0 24 24",
58
+ ...props,
59
+ children: /* @__PURE__ */ jsxs("g", {
60
+ fill: "none",
61
+ stroke: "currentColor",
62
+ strokeLinecap: "round",
63
+ strokeLinejoin: "round",
64
+ strokeWidth: "2",
65
+ children: [/* @__PURE__ */ jsx("path", { d: "M17.5 22h.5a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3" }), /* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4M2 19a2 2 0 1 1 4 0v1a2 2 0 1 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 1 1-4 0v-1a2 2 0 1 1 4 0" })]
66
+ })
67
+ });
68
+ const FileTextIcon = (props) => /* @__PURE__ */ jsx("svg", {
69
+ xmlns: "http://www.w3.org/2000/svg",
70
+ width: "1em",
71
+ height: "1em",
72
+ viewBox: "0 0 24 24",
73
+ ...props,
74
+ children: /* @__PURE__ */ jsxs("g", {
75
+ fill: "none",
76
+ stroke: "currentColor",
77
+ strokeLinecap: "round",
78
+ strokeLinejoin: "round",
79
+ strokeWidth: "2",
80
+ children: [/* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }), /* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4M10 9H8m8 4H8m8 4H8" })]
81
+ })
82
+ });
83
+ const FileCodeIcon = (props) => /* @__PURE__ */ jsx("svg", {
84
+ xmlns: "http://www.w3.org/2000/svg",
85
+ width: "1em",
86
+ height: "1em",
87
+ viewBox: "0 0 24 24",
88
+ ...props,
89
+ children: /* @__PURE__ */ jsxs("g", {
90
+ fill: "none",
91
+ stroke: "currentColor",
92
+ strokeLinecap: "round",
93
+ strokeLinejoin: "round",
94
+ strokeWidth: "2",
95
+ children: [/* @__PURE__ */ jsx("path", { d: "M10 12.5L8 15l2 2.5m4-5l2 2.5l-2 2.5M14 2v4a2 2 0 0 0 2 2h4" }), /* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z" })]
96
+ })
97
+ });
98
+ const FileArchiveIcon = (props) => /* @__PURE__ */ jsx("svg", {
99
+ xmlns: "http://www.w3.org/2000/svg",
100
+ width: "1em",
101
+ height: "1em",
102
+ viewBox: "0 0 24 24",
103
+ ...props,
104
+ children: /* @__PURE__ */ jsxs("g", {
105
+ fill: "none",
106
+ stroke: "currentColor",
107
+ strokeLinecap: "round",
108
+ strokeLinejoin: "round",
109
+ strokeWidth: "2",
110
+ children: [
111
+ /* @__PURE__ */ jsx("path", { d: "M10 12v-1m0 7v-2m0-9V6m4-4v4a2 2 0 0 0 2 2h4" }),
112
+ /* @__PURE__ */ jsx("path", { d: "M15.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v16a2 2 0 0 0 .274 1.01" }),
113
+ /* @__PURE__ */ jsx("circle", {
114
+ cx: "10",
115
+ cy: "20",
116
+ r: "2"
117
+ })
118
+ ]
119
+ })
120
+ });
121
+ const FileCogIcon = (props) => /* @__PURE__ */ jsx("svg", {
122
+ xmlns: "http://www.w3.org/2000/svg",
123
+ width: "1em",
124
+ height: "1em",
125
+ viewBox: "0 0 24 24",
126
+ ...props,
127
+ children: /* @__PURE__ */ jsxs("g", {
128
+ fill: "none",
129
+ stroke: "currentColor",
130
+ strokeLinecap: "round",
131
+ strokeLinejoin: "round",
132
+ strokeWidth: "2",
133
+ children: [
134
+ /* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4M3.2 12.9l-.9-.4m.9 2.6l-.9.4" }),
135
+ /* @__PURE__ */ jsx("path", { d: "M4.677 21.5a2 2 0 0 0 1.313.5H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v2.5m.9 4.7l-.4-.9m.4 6.5l-.4.9m3-7.4l-.4.9m.4 6.5l-.4-.9m2.6-4.3l-.9.4m.9 2.6l-.9-.4" }),
136
+ /* @__PURE__ */ jsx("circle", {
137
+ cx: "6",
138
+ cy: "14",
139
+ r: "3"
140
+ })
141
+ ]
142
+ })
143
+ });
144
+ const FileIcon = (props) => /* @__PURE__ */ jsx("svg", {
145
+ xmlns: "http://www.w3.org/2000/svg",
146
+ width: "1em",
147
+ height: "1em",
148
+ viewBox: "0 0 24 24",
149
+ ...props,
150
+ children: /* @__PURE__ */ jsxs("g", {
151
+ fill: "none",
152
+ stroke: "currentColor",
153
+ strokeLinecap: "round",
154
+ strokeLinejoin: "round",
155
+ strokeWidth: "2",
156
+ children: [/* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }), /* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })]
157
+ })
158
+ });
159
+
160
+ //#endregion
161
+ //#region src/components/ui/drop-zone/utils.ts
162
+ const generateFileID$1 = generateFileID;
163
+ const createObjectURL = (file, disallowPreviewForNonImageFiles) => {
164
+ if (disallowPreviewForNonImageFiles && !file.type?.startsWith("image/")) return;
165
+ return createFileUrl(file);
166
+ };
167
+ const clearObjectURL = (fileState, disallowPreviewForNonImageFiles) => {
168
+ if (!isFile(fileState?.file)) return;
169
+ if (disallowPreviewForNonImageFiles && !fileState.file.type.startsWith("image/")) return;
170
+ if (!fileState.preview) return;
171
+ URL.revokeObjectURL(fileState.preview);
172
+ };
173
+ const isMatchingFile = (options) => {
174
+ const { fileState, fileStateOrID } = options;
175
+ const fileID = isFile(fileState) ? generateFileID$1(fileState) : fileState.id;
176
+ if (isString(fileStateOrID)) return fileID === fileStateOrID;
177
+ if (isFile(fileStateOrID)) {
178
+ const generatedFileID = generateFileID$1(fileStateOrID);
179
+ return fileID === generatedFileID;
180
+ }
181
+ return fileID === fileStateOrID.id;
182
+ };
183
+ const getScopeAttrs = (part) => {
184
+ return {
185
+ "data-slot": `dropzone-${part}`,
186
+ "data-scope": "dropzone",
187
+ "data-part": part
188
+ };
189
+ };
190
+ const dropZoneErrorSymbol = Symbol("DropZoneError");
191
+ var DropZoneError = class DropZoneError extends Error {
192
+ dropZoneErrorSymbol = dropZoneErrorSymbol;
193
+ file;
194
+ name = "DropZoneError";
195
+ constructor(ctx) {
196
+ const { file, message } = ctx;
197
+ super(message);
198
+ this.file = file;
199
+ }
200
+ static isError(error) {
201
+ if (!isObject(error)) return false;
202
+ if (error instanceof DropZoneError) return true;
203
+ const actualError = error;
204
+ return actualError.dropZoneErrorSymbol === dropZoneErrorSymbol && actualError.name === "DropZoneError";
205
+ }
206
+ };
207
+ const getErrorContext = (error) => {
208
+ if (DropZoneError.isError(error)) return {
209
+ cause: "custom-error",
210
+ code: "upload-error",
211
+ file: error.file ?? {},
212
+ message: error.message,
213
+ originalError: error.cause ?? error
214
+ };
215
+ const actualError = Error.isError(error) ? error : new Error("File upload failed", { cause: error });
216
+ return {
217
+ cause: "custom-error",
218
+ code: "upload-error",
219
+ file: isFile(actualError.cause) ? actualError.cause : {},
220
+ message: Error.isError(error) ? actualError.message : String(actualError),
221
+ originalError: actualError
222
+ };
223
+ };
224
+
225
+ //#endregion
226
+ //#region src/components/ui/drop-zone/drop-zone-store.ts
227
+ const createDropZoneStore = (initStoreValues) => {
228
+ const { allowedFileTypes, disablePreviewForNonImageFiles, initialFiles, inputRef, maxFileCount, maxFileSize, multiple, onFilesChange, onUpload, onValidationError, onValidationSuccess, rejectDuplicateFiles, validator } = initStoreValues;
229
+ const initialFileArray = toArray(initialFiles).filter(Boolean);
230
+ const clearInputValue = () => {
231
+ if (!inputRef.current) return;
232
+ inputRef.current.value = "";
233
+ };
234
+ const initFileStateArray = initialFileArray.map((fileMeta) => ({
235
+ file: fileMeta,
236
+ id: fileMeta.id,
237
+ preview: isString(fileMeta.url) ? fileMeta.url : void 0,
238
+ progress: 0,
239
+ status: "idle"
240
+ }));
241
+ const store = createStore((set, get) => ({
242
+ disabled: false,
243
+ errors: [],
244
+ fileStateArray: initFileStateArray,
245
+ isDraggingOver: false,
246
+ isInvalid: false,
247
+ actions: {
248
+ addFiles: async (files) => {
249
+ if (!files || files.length === 0) {
250
+ console.warn("No file selected!");
251
+ return;
252
+ }
253
+ const { actions, fileStateArray } = get();
254
+ const resolvedNewFiles = !multiple ? [files[0]] : files;
255
+ const { errors, validFiles } = await handleFileValidationAsync({
256
+ existingFiles: fileStateArray.map((fileWithPreview) => fileWithPreview.file),
257
+ hooks: {
258
+ onErrorEach: onValidationError,
259
+ onSuccessBatch: onValidationSuccess
260
+ },
261
+ newFiles: resolvedNewFiles,
262
+ settings: {
263
+ allowedFileTypes,
264
+ maxFileCount,
265
+ maxFileSize,
266
+ rejectDuplicateFiles,
267
+ validator
268
+ }
269
+ });
270
+ if (validFiles.length === 0) {
271
+ set({
272
+ errors,
273
+ isDraggingOver: false
274
+ });
275
+ return;
276
+ }
277
+ const newFileStateArray = validFiles.map((file) => ({
278
+ file,
279
+ id: generateFileID$1(file),
280
+ preview: createObjectURL(file, disablePreviewForNonImageFiles),
281
+ progress: 0,
282
+ status: "idle"
283
+ }));
284
+ set({
285
+ errors,
286
+ fileStateArray: !multiple ? newFileStateArray : [...fileStateArray, ...newFileStateArray],
287
+ isDraggingOver: false
288
+ });
289
+ await actions.handleFileUpload({ newFileStateArray });
290
+ },
291
+ clearErrors: () => {
292
+ set({
293
+ errors: [],
294
+ isInvalid: false
295
+ });
296
+ },
297
+ clearFiles: () => {
298
+ const { actions } = get();
299
+ actions.clearObjectURLs();
300
+ set({
301
+ errors: [],
302
+ fileStateArray: [],
303
+ isInvalid: false
304
+ });
305
+ },
306
+ clearObjectURLs: () => {
307
+ const { fileStateArray } = get();
308
+ for (const fileState of fileStateArray) clearObjectURL(fileState, disablePreviewForNonImageFiles);
309
+ },
310
+ handleChange: async (event) => {
311
+ const fileList = event.target.files;
312
+ const { actions } = get();
313
+ await actions.addFiles(fileList);
314
+ clearInputValue();
315
+ },
316
+ handleDragEnter: (event) => {
317
+ event.preventDefault();
318
+ event.stopPropagation();
319
+ set({ isDraggingOver: true });
320
+ },
321
+ handleDragLeave: (event) => {
322
+ event.preventDefault();
323
+ event.stopPropagation();
324
+ set({ isDraggingOver: false });
325
+ },
326
+ handleDragOver: (event) => {
327
+ event.preventDefault();
328
+ event.stopPropagation();
329
+ },
330
+ handleDrop: async (event) => {
331
+ event.preventDefault();
332
+ event.stopPropagation();
333
+ const { actions } = get();
334
+ const fileList = event.dataTransfer.files;
335
+ await actions.addFiles(fileList);
336
+ },
337
+ handleFileUpload: async (context) => {
338
+ const { newFileStateArray } = context;
339
+ const { actions } = get();
340
+ if (!onUpload) {
341
+ for (const fileState of newFileStateArray) actions.updateFileState({
342
+ fileStateOrID: fileState,
343
+ progress: 100,
344
+ status: "success"
345
+ });
346
+ return;
347
+ }
348
+ try {
349
+ await onUpload({
350
+ fileStateArray: newFileStateArray,
351
+ onError: (ctx) => {
352
+ const { error, fileStateOrID } = ctx;
353
+ const errorContext = getErrorContext(error);
354
+ actions.updateFileState({
355
+ error: errorContext,
356
+ fileStateOrID,
357
+ status: "error"
358
+ });
359
+ },
360
+ onProgress: (ctx) => {
361
+ const { fileStateOrID, progress } = ctx;
362
+ actions.updateFileState({
363
+ fileStateOrID,
364
+ progress
365
+ });
366
+ },
367
+ onSuccess: (ctx) => {
368
+ const { fileStateOrID } = ctx;
369
+ actions.updateFileState({
370
+ fileStateOrID,
371
+ progress: 100,
372
+ status: "success"
373
+ });
374
+ }
375
+ });
376
+ } catch (error) {
377
+ const errorContext = getErrorContext(error);
378
+ for (const fileState of newFileStateArray) actions.updateFileState({
379
+ error: errorContext,
380
+ fileStateOrID: fileState,
381
+ status: "error"
382
+ });
383
+ }
384
+ },
385
+ handleKeyDown: (event) => {
386
+ const isEnterKey = event.key === "Enter";
387
+ const isSpaceKey = event.key === " ";
388
+ if (!(isEnterKey || isSpaceKey)) return;
389
+ event.preventDefault();
390
+ const { actions } = get();
391
+ actions.openFilePicker();
392
+ },
393
+ handlePaste: async (event) => {
394
+ event.preventDefault();
395
+ event.stopPropagation();
396
+ const { actions } = get();
397
+ const fileList = event.clipboardData.files;
398
+ await actions.addFiles(fileList);
399
+ },
400
+ openFilePicker: () => {
401
+ inputRef.current?.click();
402
+ },
403
+ removeFile: (ctx) => {
404
+ const { fileStateOrID } = ctx;
405
+ const { fileStateArray } = get();
406
+ const updatedFileStateArray = fileStateArray.flatMap((fileState) => {
407
+ if (isMatchingFile({
408
+ fileState,
409
+ fileStateOrID
410
+ })) {
411
+ clearObjectURL(fileState, disablePreviewForNonImageFiles);
412
+ return [];
413
+ }
414
+ return fileState;
415
+ });
416
+ set({
417
+ errors: [],
418
+ fileStateArray: updatedFileStateArray
419
+ });
420
+ },
421
+ updateFileState: (ctx) => {
422
+ const { fileStateOrID,...updatedFileState } = ctx;
423
+ const { fileStateArray } = get();
424
+ const updatedFileStateArray = fileStateArray.map((fileState) => {
425
+ if (isMatchingFile({
426
+ fileState,
427
+ fileStateOrID
428
+ })) return {
429
+ ...fileState,
430
+ ...updatedFileState
431
+ };
432
+ return fileState;
433
+ });
434
+ set({ fileStateArray: updatedFileStateArray });
435
+ }
436
+ }
437
+ }));
438
+ store.subscribe.withSelector((state) => state.fileStateArray, (fileStateArray) => onFilesChange?.({ fileStateArray }));
439
+ store.subscribe.withSelector((state) => state.errors, (errors) => {
440
+ if (errors.length === 0) return;
441
+ store.setState({ isInvalid: true });
442
+ });
443
+ store.subscribe.withSelector((state) => state.isInvalid, (isInvalid) => {
444
+ if (!isInvalid) return;
445
+ setTimeout(() => store.setState({ isInvalid: !isInvalid }), 1500);
446
+ });
447
+ return store;
448
+ };
449
+
450
+ //#endregion
451
+ //#region src/components/ui/drop-zone/use-drop-zone.ts
452
+ const useDropZone = (props) => {
453
+ const { allowedFileTypes, disabled = false, disableInternalStateSubscription = false, disablePreviewForNonImageFiles = true, initialFiles, maxFileCount, maxFileSize, multiple, onFilesChange, onUpload, onValidationError, onValidationSuccess, rejectDuplicateFiles = true, shouldOpenFilePickerOnAreaClick = true, validator } = props ?? {};
454
+ const inputRef = useRef(null);
455
+ const savedOnFilesChange = useCallbackRef(onFilesChange);
456
+ const savedOnUpload = useCallbackRef(onUpload);
457
+ const savedOnUploadError = useCallbackRef(onValidationError);
458
+ const savedOnUploadSuccess = useCallbackRef(onValidationSuccess);
459
+ const savedValidator = useCallbackRef(validator);
460
+ const constantInitialFiles = useConstant(() => initialFiles);
461
+ const shallowComparedMaxFileSize = useShallowCompValue(maxFileSize);
462
+ const shallowComparedAllowedFileTypes = useShallowCompValue(allowedFileTypes);
463
+ const storeApi = useMemo(() => {
464
+ return createDropZoneStore({
465
+ allowedFileTypes: shallowComparedAllowedFileTypes,
466
+ disablePreviewForNonImageFiles,
467
+ initialFiles: constantInitialFiles,
468
+ inputRef,
469
+ maxFileCount,
470
+ maxFileSize: shallowComparedMaxFileSize,
471
+ multiple,
472
+ onFilesChange: savedOnFilesChange,
473
+ onUpload: savedOnUpload,
474
+ onValidationError: savedOnUploadError,
475
+ onValidationSuccess: savedOnUploadSuccess,
476
+ rejectDuplicateFiles,
477
+ validator: savedValidator
478
+ });
479
+ }, [
480
+ shallowComparedAllowedFileTypes,
481
+ disablePreviewForNonImageFiles,
482
+ constantInitialFiles,
483
+ maxFileCount,
484
+ shallowComparedMaxFileSize,
485
+ multiple,
486
+ savedOnFilesChange,
487
+ savedOnUpload,
488
+ savedOnUploadError,
489
+ savedOnUploadSuccess,
490
+ rejectDuplicateFiles,
491
+ savedValidator
492
+ ]);
493
+ const actions = storeApi.getState().actions;
494
+ useUnmountEffect(() => {
495
+ actions.clearObjectURLs();
496
+ });
497
+ const useDropZoneStore = (selector) => {
498
+ return useStore(storeApi, selector);
499
+ };
500
+ const isDraggingOver = useDropZoneStore((state) => !disableInternalStateSubscription ? state.isDraggingOver : null);
501
+ const hasFiles = useDropZoneStore((state) => !disableInternalStateSubscription ? state.fileStateArray.length > 0 : null);
502
+ const isInvalid = useDropZoneStore((state) => !disableInternalStateSubscription ? state.isInvalid : null);
503
+ const getContainerProps = useCallback((innerProps) => {
504
+ const isDisabled = disabled;
505
+ const onFileDrop = !isDisabled ? actions.handleDrop : void 0;
506
+ const onFilePaste = !isDisabled ? actions.handlePaste : void 0;
507
+ const onKeyDown = !isDisabled ? actions.handleKeyDown : void 0;
508
+ const tabIndex = !isDisabled ? 0 : void 0;
509
+ const onAreaClick = !isDisabled && shouldOpenFilePickerOnAreaClick ? actions.openFilePicker : void 0;
510
+ return {
511
+ ...getScopeAttrs("container"),
512
+ role: "region",
513
+ ...!disableInternalStateSubscription && {
514
+ "data-drag-over": dataAttr(isDraggingOver),
515
+ "data-invalid": dataAttr(isInvalid)
516
+ },
517
+ ...innerProps,
518
+ className: cnMerge(`relative flex flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed
519
+ p-6 transition-colors duration-250 ease-out outline-none select-none hover:bg-zu-accent/30
520
+ focus-visible:border-zu-ring/50`, `data-[disabled]:pointer-events-none data-[drag-over]:border-zu-primary/30
521
+ data-[drag-over]:bg-zu-accent/30 data-[dragging]:bg-zu-accent/30
522
+ data-[invalid]:border-zu-destructive data-[invalid]:ring-zu-destructive/20`, innerProps.className),
523
+ "data-disabled": dataAttr(isDisabled),
524
+ onClick: composeTwoEventHandlers(onAreaClick, innerProps.onClick),
525
+ onDragEnter: composeTwoEventHandlers(actions.handleDragEnter, innerProps.onDragEnter),
526
+ onDragLeave: composeTwoEventHandlers(actions.handleDragLeave, innerProps.onDragLeave),
527
+ onDragOver: composeTwoEventHandlers(actions.handleDragOver, innerProps.onDragOver),
528
+ onDrop: composeTwoEventHandlers(onFileDrop, innerProps.onDrop),
529
+ onKeyDown: composeTwoEventHandlers(onKeyDown, innerProps.onKeyDown),
530
+ onPaste: composeTwoEventHandlers(onFilePaste, innerProps.onPaste),
531
+ tabIndex
532
+ };
533
+ }, [
534
+ actions.handleDragEnter,
535
+ actions.handleDragLeave,
536
+ actions.handleDragOver,
537
+ actions.handleDrop,
538
+ actions.handleKeyDown,
539
+ actions.handlePaste,
540
+ actions.openFilePicker,
541
+ disableInternalStateSubscription,
542
+ disabled,
543
+ isDraggingOver,
544
+ isInvalid,
545
+ shouldOpenFilePickerOnAreaClick
546
+ ]);
547
+ const getInputProps = useCallback((innerProps) => {
548
+ const isDisabled = innerProps.disabled ?? disabled;
549
+ const onFileChange = !isDisabled ? actions.handleChange : void 0;
550
+ return {
551
+ ...getScopeAttrs("input"),
552
+ ...!disableInternalStateSubscription && { "data-drag-over": dataAttr(isDraggingOver) },
553
+ ...innerProps,
554
+ accept: allowedFileTypes ? allowedFileTypes.join(", ") : innerProps.accept,
555
+ className: cnMerge("hidden", innerProps.className),
556
+ "data-disabled": dataAttr(isDisabled),
557
+ disabled: isDisabled,
558
+ multiple: multiple ?? innerProps.multiple,
559
+ onChange: composeTwoEventHandlers(onFileChange, innerProps.onChange),
560
+ ref: composeRefs(inputRef, innerProps.ref),
561
+ type: "file"
562
+ };
563
+ }, [
564
+ actions.handleChange,
565
+ allowedFileTypes,
566
+ disableInternalStateSubscription,
567
+ disabled,
568
+ isDraggingOver,
569
+ multiple
570
+ ]);
571
+ const getTriggerProps = useCallback((innerProps) => {
572
+ const isDisabled = innerProps.disabled ?? disabled;
573
+ return {
574
+ ...getScopeAttrs("trigger"),
575
+ type: "button",
576
+ ...innerProps,
577
+ "data-disabled": dataAttr(isDisabled),
578
+ disabled: isDisabled,
579
+ onClick: composeTwoEventHandlers(actions.openFilePicker, innerProps.onClick)
580
+ };
581
+ }, [actions.openFilePicker, disabled]);
582
+ const getFileListProps = useCallback((innerProps) => {
583
+ const { orientation = "vertical",...restOfInnerProps } = innerProps;
584
+ return {
585
+ ...getScopeAttrs("file-list"),
586
+ "data-orientation": orientation,
587
+ ...!disableInternalStateSubscription && { "data-state": hasFiles ? "active" : "inactive" },
588
+ ...restOfInnerProps,
589
+ className: cnMerge(`flex flex-col gap-2 data-[state=active]:animate-files-in data-[state=inactive]:animate-out
590
+ data-[state=inactive]:fade-out-0 data-[state=inactive]:slide-out-to-top-2`, orientation === "horizontal" && "flex-row overflow-x-auto p-1.5", innerProps.className)
591
+ };
592
+ }, [disableInternalStateSubscription, hasFiles]);
593
+ const getFileItemProps = useCallbackRef((innerProps) => {
594
+ return {
595
+ ...getScopeAttrs("file-item"),
596
+ ...innerProps,
597
+ className: cnMerge("relative flex items-center gap-2.5 rounded-md border p-2", innerProps.className)
598
+ };
599
+ });
600
+ const getFileItemProgressProps = useCallbackRef((innerProps) => {
601
+ const { variant = "linear",...restOfInnerProps } = innerProps;
602
+ return {
603
+ ...getScopeAttrs("file-item-progress"),
604
+ role: "progressbar",
605
+ ...restOfInnerProps,
606
+ className: cnMerge("inline-flex", variant === "circular" && "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2", variant === "fill" && `absolute inset-0 bg-zu-primary/50 transition-[clip-path] duration-300 ease-linear
607
+ [clip-path:var(--clip-path)]`, variant === "linear" && "relative h-1.5 w-full overflow-hidden rounded-full bg-zu-primary/20", restOfInnerProps.className)
608
+ };
609
+ });
610
+ const getFileItemDeleteProps = useCallback((innerProps) => {
611
+ const { fileStateOrID,...restOfInnerProps } = innerProps;
612
+ const isDisabled = innerProps.disabled ?? disabled;
613
+ const onRemoveFile = () => fileStateOrID && actions.removeFile({ fileStateOrID });
614
+ return {
615
+ ...getScopeAttrs("file-item-delete"),
616
+ type: "button",
617
+ ...restOfInnerProps,
618
+ "data-disabled": dataAttr(isDisabled),
619
+ disabled: isDisabled,
620
+ onClick: composeTwoEventHandlers(onRemoveFile, restOfInnerProps.onClick)
621
+ };
622
+ }, [actions, disabled]);
623
+ const getFileItemPreviewProps = useCallbackRef((innerProps) => {
624
+ return {
625
+ ...getScopeAttrs("file-item-preview"),
626
+ ...innerProps,
627
+ className: cnMerge(`relative flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-md
628
+ bg-zu-accent/50 [&>svg]:size-10`, innerProps.className)
629
+ };
630
+ });
631
+ const getFileItemMetadataProps = useCallbackRef((innerProps) => {
632
+ return {
633
+ ...getScopeAttrs("file-item-metadata"),
634
+ ...innerProps,
635
+ className: cnMerge("flex min-w-0 grow flex-col", innerProps.className)
636
+ };
637
+ });
638
+ const getFileItemClearProps = useCallback((innerProps) => {
639
+ const isDisabled = innerProps.disabled ?? disabled;
640
+ return {
641
+ ...getScopeAttrs("file-item-clear"),
642
+ type: "button",
643
+ ...innerProps,
644
+ "data-disabled": dataAttr(isDisabled),
645
+ disabled: isDisabled,
646
+ onClick: composeTwoEventHandlers(actions.clearFiles, innerProps.onClick)
647
+ };
648
+ }, [actions.clearFiles, disabled]);
649
+ const propGetters = useMemo(() => ({
650
+ getContainerProps,
651
+ getFileItemClearProps,
652
+ getFileItemDeleteProps,
653
+ getFileItemMetadataProps,
654
+ getFileItemPreviewProps,
655
+ getFileItemProgressProps,
656
+ getFileItemProps,
657
+ getFileListProps,
658
+ getInputProps,
659
+ getTriggerProps
660
+ }), [
661
+ getContainerProps,
662
+ getFileListProps,
663
+ getFileItemClearProps,
664
+ getFileItemDeleteProps,
665
+ getFileItemMetadataProps,
666
+ getFileItemPreviewProps,
667
+ getFileItemProgressProps,
668
+ getFileItemProps,
669
+ getInputProps,
670
+ getTriggerProps
671
+ ]);
672
+ const savedUseDropZoneStore = useCallbackRef(useDropZoneStore);
673
+ return useMemo(() => ({
674
+ disabled,
675
+ disableInternalStateSubscription,
676
+ inputRef,
677
+ propGetters,
678
+ storeApi,
679
+ useDropZoneStore: savedUseDropZoneStore
680
+ }), [
681
+ disabled,
682
+ disableInternalStateSubscription,
683
+ propGetters,
684
+ storeApi,
685
+ savedUseDropZoneStore
686
+ ]);
687
+ };
688
+
689
+ //#endregion
690
+ //#region src/components/ui/drop-zone/drop-zone.tsx
691
+ function DropZoneRoot(props) {
692
+ const { children,...restOfProps } = props;
693
+ const { disabled, disableInternalStateSubscription, inputRef, propGetters, storeApi } = useDropZone(restOfProps);
694
+ const rootContextValue = useMemo(() => ({
695
+ disabled,
696
+ disableInternalStateSubscription,
697
+ inputRef,
698
+ propGetters
699
+ }), [
700
+ disableInternalStateSubscription,
701
+ disabled,
702
+ inputRef,
703
+ propGetters
704
+ ]);
705
+ return /* @__PURE__ */ jsx(DropZoneStoreContextProvider, {
706
+ store: storeApi,
707
+ children: /* @__PURE__ */ jsx(DropZoneRootContextProvider, {
708
+ value: rootContextValue,
709
+ children
710
+ })
711
+ });
712
+ }
713
+ function DropZoneContext(props) {
714
+ const { children, selector } = props;
715
+ const dropZoneCtx = useDropZoneStoreContext(useShallowCompSelector(selector));
716
+ return isFunction(children) ? children(dropZoneCtx) : children;
717
+ }
718
+ function DropZoneContainer(props) {
719
+ const { as: Element = "div", asChild,...restOfProps } = props;
720
+ const { disableInternalStateSubscription, propGetters } = useDropZoneRootContext();
721
+ const isDraggingOver = useDropZoneStoreContext((store) => disableInternalStateSubscription ? store.isDraggingOver : null);
722
+ const isInvalid = useDropZoneStoreContext((store) => disableInternalStateSubscription ? store.isInvalid : null);
723
+ const Component$1 = asChild ? SlotRoot : Element;
724
+ return /* @__PURE__ */ jsx(Component$1, { ...propGetters.getContainerProps({
725
+ ...disableInternalStateSubscription && {
726
+ "data-drag-over": dataAttr(isDraggingOver),
727
+ "data-invalid": dataAttr(isInvalid)
728
+ },
729
+ ...restOfProps
730
+ }) });
731
+ }
732
+ function DropZoneInput(props) {
733
+ const { asChild,...restOfProps } = props;
734
+ const { disableInternalStateSubscription, propGetters } = useDropZoneRootContext();
735
+ const isDraggingOver = useDropZoneStoreContext((store) => disableInternalStateSubscription ? store.isDraggingOver : null);
736
+ const Component$1 = asChild ? SlotRoot : "input";
737
+ return /* @__PURE__ */ jsx(Component$1, { ...propGetters.getInputProps({
738
+ ...disableInternalStateSubscription && { "data-drag-over": dataAttr(isDraggingOver) },
739
+ ...restOfProps
740
+ }) });
741
+ }
742
+ function DropZoneArea(props) {
743
+ const { children, classNames, extraProps, selector } = props;
744
+ return /* @__PURE__ */ jsxs(DropZoneContainer, {
745
+ ...extraProps?.container,
746
+ className: classNames?.container,
747
+ children: [/* @__PURE__ */ jsx(DropZoneInput, {
748
+ ...extraProps?.input,
749
+ className: classNames?.input
750
+ }), /* @__PURE__ */ jsx(DropZoneContext, {
751
+ selector,
752
+ children
753
+ })]
754
+ });
755
+ }
756
+ function DropZoneTrigger(props) {
757
+ const { asChild,...restOfProps } = props;
758
+ const { propGetters } = useDropZoneRootContext();
759
+ const Component$1 = asChild ? SlotRoot : "button";
760
+ return /* @__PURE__ */ jsx(Component$1, { ...propGetters.getTriggerProps(restOfProps) });
761
+ }
762
+ function DropZoneFileList(props) {
763
+ const { as: Element = "ul", asChild, children, forceMount = false, renderMode = "per-item",...restOfProps } = props;
764
+ const fileStateArray = useDropZoneStoreContext((store) => store.fileStateArray);
765
+ const actions = useDropZoneStoreContext((store) => store.actions);
766
+ const { disableInternalStateSubscription, propGetters } = useDropZoneRootContext();
767
+ const childrenMap = {
768
+ "manual-list": () => {
769
+ return children({
770
+ actions,
771
+ fileStateArray
772
+ });
773
+ },
774
+ "per-item": () => {
775
+ const childrenFn = children;
776
+ return /* @__PURE__ */ jsx(For, {
777
+ each: fileStateArray,
778
+ renderItem: (fileState, index, array) => childrenFn({
779
+ actions,
780
+ array,
781
+ fileState,
782
+ index
783
+ })
784
+ });
785
+ }
786
+ };
787
+ const hasFiles = fileStateArray.length > 0;
788
+ const Component$1 = asChild ? SlotRoot : Element;
789
+ return /* @__PURE__ */ jsx(Presence, {
790
+ present: hasFiles,
791
+ forceMount,
792
+ children: /* @__PURE__ */ jsx(Component$1, {
793
+ ...propGetters.getFileListProps({
794
+ ...disableInternalStateSubscription && { "data-state": hasFiles ? "active" : "inactive" },
795
+ ...restOfProps
796
+ }),
797
+ children: isFunction(children) ? childrenMap[renderMode]() : children
798
+ })
799
+ });
800
+ }
801
+ function DropZoneFileItem(props) {
802
+ const { as: Element = "li", asChild, fileState,...restOfProps } = props;
803
+ const { propGetters } = useDropZoneRootContext();
804
+ const Component$1 = asChild ? SlotRoot : Element;
805
+ const contextValue = useMemo(() => ({ fileState }), [fileState]);
806
+ return /* @__PURE__ */ jsx(FileItemContextProvider, {
807
+ value: contextValue,
808
+ children: /* @__PURE__ */ jsx(Component$1, { ...propGetters.getFileItemProps(restOfProps) })
809
+ });
810
+ }
811
+ function DropZoneFileItemDelete(props) {
812
+ const { asChild, fileStateOrID,...restOfProps } = props;
813
+ const { propGetters } = useDropZoneRootContext();
814
+ const fileItemContextValue = useFileItemContext();
815
+ const Component$1 = asChild ? SlotRoot : "button";
816
+ const resolvedFileStateOrID = fileStateOrID ?? fileItemContextValue?.fileState;
817
+ return /* @__PURE__ */ jsx(Component$1, { ...propGetters.getFileItemDeleteProps({
818
+ fileStateOrID: resolvedFileStateOrID,
819
+ ...restOfProps
820
+ }) });
821
+ }
822
+ function DropZoneFileItemProgress(props) {
823
+ const { as: Element = "span", asChild, forceMount = false, size = 40, variant = "linear",...restOfProps } = props;
824
+ const fileState = useFileItemContext()?.fileState;
825
+ const { propGetters } = useDropZoneRootContext();
826
+ if (!fileState) return null;
827
+ const currentProgress = fileState.progress;
828
+ if (!(forceMount || fileState.progress !== 100)) return null;
829
+ const Component$1 = asChild ? SlotRoot : Element;
830
+ const componentProps = propGetters.getFileItemProgressProps({
831
+ variant,
832
+ ...restOfProps
833
+ });
834
+ switch (variant) {
835
+ case "circular": {
836
+ const circumference = 2 * Math.PI * ((size - 4) / 2);
837
+ const strokeDashoffset = circumference - currentProgress / 100 * circumference;
838
+ return /* @__PURE__ */ jsx(Component$1, {
839
+ ...componentProps,
840
+ children: /* @__PURE__ */ jsxs("svg", {
841
+ className: "-rotate-90",
842
+ width: size,
843
+ height: size,
844
+ viewBox: `0 0 ${size} ${size}`,
845
+ fill: "none",
846
+ stroke: "currentColor",
847
+ children: [/* @__PURE__ */ jsx("circle", {
848
+ className: "text-zu-primary/20",
849
+ strokeWidth: "2",
850
+ cx: size / 2,
851
+ cy: size / 2,
852
+ r: (size - 4) / 2
853
+ }), /* @__PURE__ */ jsx("circle", {
854
+ className: "text-zu-primary transition-[stroke-dashoffset] duration-300 ease-linear",
855
+ strokeWidth: "2",
856
+ strokeLinecap: "round",
857
+ strokeDasharray: circumference,
858
+ strokeDashoffset,
859
+ cx: size / 2,
860
+ cy: size / 2,
861
+ r: (size - 4) / 2
862
+ })]
863
+ })
864
+ });
865
+ }
866
+ case "fill": {
867
+ const topInset = 100 - currentProgress;
868
+ return /* @__PURE__ */ jsx(Component$1, {
869
+ ...componentProps,
870
+ style: { "--clip-path": `inset(${topInset}% 0% 0% 0%)` }
871
+ });
872
+ }
873
+ case "linear": return /* @__PURE__ */ jsx(Component$1, {
874
+ ...componentProps,
875
+ children: /* @__PURE__ */ jsx("span", {
876
+ className: "inline-block size-full grow translate-x-(--translate-distance) bg-zu-primary transition-transform duration-300 ease-linear",
877
+ style: { "--translate-distance": `-${100 - currentProgress}%` }
878
+ })
879
+ });
880
+ default: return null;
881
+ }
882
+ }
883
+ function DropZoneFileItemPreview(props) {
884
+ const { as: Element = "span", asChild, children, fileState: fileStateProp, renderPreview = true,...restOfProps } = props;
885
+ const fileItemContextValue = useFileItemContext();
886
+ const { propGetters } = useDropZoneRootContext();
887
+ const fileState = fileStateProp ?? fileItemContextValue?.fileState;
888
+ if (!fileState) return null;
889
+ const fileType = fileState.file.type ?? "";
890
+ const fileExtension = fileState.file.name?.split(".").pop()?.toLowerCase() ?? "";
891
+ const Component$1 = asChild ? SlotRoot : Element;
892
+ const resolvedChildren = isFunction(children) ? children({
893
+ fileExtension,
894
+ fileState,
895
+ fileType
896
+ }) : children;
897
+ return /* @__PURE__ */ jsxs(Component$1, {
898
+ ...propGetters.getFileItemPreviewProps(restOfProps),
899
+ children: [renderPreview && getFilePreviewOrIcon({
900
+ fileExtension,
901
+ fileState,
902
+ fileType,
903
+ renderPreview
904
+ }), resolvedChildren]
905
+ });
906
+ }
907
+ const getFilePreviewOrIcon = (context) => {
908
+ const { fileExtension, fileState, fileType, renderPreview } = context;
909
+ const renderPreviewObject = isFunction(renderPreview) ? renderPreview({
910
+ fileExtension,
911
+ fileState,
912
+ fileType
913
+ }) : {};
914
+ switch (true) {
915
+ case fileType.startsWith("image/"): return renderPreviewObject.image?.node ?? /* @__PURE__ */ jsx("img", {
916
+ ...renderPreviewObject.image?.props,
917
+ src: fileState.preview,
918
+ alt: fileState.file.name ?? "",
919
+ className: cnMerge("size-full object-cover", renderPreviewObject.image?.props?.className)
920
+ });
921
+ case fileType.startsWith("video/"): return renderPreviewObject.video?.node ?? /* @__PURE__ */ jsx(FileVideoIcon, {
922
+ ...renderPreviewObject.video?.props,
923
+ className: cnMerge("size-full object-cover", renderPreviewObject.video?.props?.className)
924
+ });
925
+ case fileType.startsWith("audio/"): return renderPreviewObject.audio?.node ?? /* @__PURE__ */ jsx(FileAudioIcon, {
926
+ ...renderPreviewObject.audio?.props,
927
+ className: cnMerge("size-full object-cover", renderPreviewObject.audio?.props?.className)
928
+ });
929
+ case fileType.startsWith("text/") || [
930
+ "md",
931
+ "pdf",
932
+ "rtf",
933
+ "txt"
934
+ ].includes(fileExtension): return renderPreviewObject.text?.node ?? /* @__PURE__ */ jsx(FileTextIcon, { ...renderPreviewObject.text?.props });
935
+ case [
936
+ "c",
937
+ "cpp",
938
+ "cs",
939
+ "css",
940
+ "html",
941
+ "java",
942
+ "js",
943
+ "json",
944
+ "jsx",
945
+ "php",
946
+ "py",
947
+ "rb",
948
+ "ts",
949
+ "tsx",
950
+ "xml"
951
+ ].includes(fileExtension): return renderPreviewObject.code?.node ?? /* @__PURE__ */ jsx(FileCodeIcon, { ...renderPreviewObject.code?.props });
952
+ case [
953
+ "7z",
954
+ "bz2",
955
+ "gz",
956
+ "rar",
957
+ "tar",
958
+ "zip"
959
+ ].includes(fileExtension): return renderPreviewObject.archive?.node ?? /* @__PURE__ */ jsx(FileArchiveIcon, { ...renderPreviewObject.archive?.props });
960
+ case [
961
+ "apk",
962
+ "app",
963
+ "deb",
964
+ "exe",
965
+ "msi",
966
+ "rpm"
967
+ ].includes(fileExtension): return renderPreviewObject.executable?.node ?? /* @__PURE__ */ jsx(FileCogIcon, { ...renderPreviewObject.executable?.props });
968
+ default: return renderPreviewObject.default?.node ?? /* @__PURE__ */ jsx(FileIcon, { ...renderPreviewObject.default?.props });
969
+ }
970
+ };
971
+ function DropZoneFileItemMetadata(props) {
972
+ const { asChild, children, classNames, fileState: fileStateProp, size = "default",...restOfProps } = props;
973
+ const fileItemContextValue = useFileItemContext();
974
+ const { propGetters } = useDropZoneRootContext();
975
+ const fileState = fileStateProp ?? fileItemContextValue?.fileState;
976
+ if (!fileState) return null;
977
+ const Component$1 = asChild ? SlotRoot : "div";
978
+ const resolvedChildren = isFunction(children) ? children({ fileState }) : children;
979
+ const getDefaultMetadataChildren = () => {
980
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
981
+ /* @__PURE__ */ jsx("p", {
982
+ className: cnMerge("truncate", size === "default" && "text-[14px] font-medium", size === "sm" && "text-[13px] leading-snug", classNames?.name),
983
+ children: fileState.file.name
984
+ }),
985
+ /* @__PURE__ */ jsx("p", {
986
+ className: cnMerge("truncate text-zu-muted-foreground", size === "default" && "text-[12px]", size === "sm" && "text-[11px] leading-snug", classNames?.size),
987
+ children: isNumber(fileState.file.size) && formatBytes(fileState.file.size)
988
+ }),
989
+ fileState.error && /* @__PURE__ */ jsx("p", {
990
+ className: "text-[12px] text-zu-destructive",
991
+ children: fileState.error.message
992
+ })
993
+ ] });
994
+ };
995
+ return /* @__PURE__ */ jsx(Component$1, {
996
+ ...propGetters.getFileItemMetadataProps(restOfProps),
997
+ children: resolvedChildren ?? getDefaultMetadataChildren()
998
+ });
999
+ }
1000
+ function DropZoneFileClear(props) {
1001
+ const { asChild, forceMount = false,...restOfProps } = props;
1002
+ const { propGetters } = useDropZoneRootContext();
1003
+ const fileCount = useDropZoneStoreContext((state) => state.fileStateArray.length);
1004
+ if (!(forceMount || fileCount > 0)) return null;
1005
+ const Component$1 = asChild ? SlotRoot : "button";
1006
+ return /* @__PURE__ */ jsx(Component$1, { ...propGetters.getFileItemClearProps(restOfProps) });
1007
+ }
1008
+
1009
+ //#endregion
1010
+ //#region src/components/ui/drop-zone/drop-zone-parts.ts
1011
+ var drop_zone_parts_exports = __export({
1012
+ Area: () => DropZoneArea,
1013
+ Container: () => DropZoneContainer,
1014
+ Context: () => DropZoneContext,
1015
+ FileClear: () => DropZoneFileClear,
1016
+ FileItem: () => DropZoneFileItem,
1017
+ FileItemDelete: () => DropZoneFileItemDelete,
1018
+ FileItemMetadata: () => DropZoneFileItemMetadata,
1019
+ FileItemPreview: () => DropZoneFileItemPreview,
1020
+ FileItemProgress: () => DropZoneFileItemProgress,
1021
+ FileList: () => DropZoneFileList,
1022
+ Input: () => DropZoneInput,
1023
+ Root: () => DropZoneRoot,
1024
+ Trigger: () => DropZoneTrigger
1025
+ });
1026
+
1027
+ //#endregion
1028
+ export { drop_zone_parts_exports as DropZone, DropZoneArea, DropZoneContainer, DropZoneContext, DropZoneError, DropZoneFileClear, DropZoneFileItem, DropZoneFileItemDelete, DropZoneFileItemMetadata, DropZoneFileItemPreview, DropZoneFileItemProgress, DropZoneFileList, DropZoneInput, DropZoneRoot, DropZoneTrigger, useDropZone, useDropZoneStoreContext };
1029
+ //# sourceMappingURL=index.js.map