@zayne-labs/ui-react 0.10.4 → 0.10.6

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