@muhgholy/next-drive 4.23.7 → 4.23.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 (95) hide show
  1. package/README.md +152 -1
  2. package/dist/{chunk-LAKT7IJJ.cjs → chunk-V75PCJHT.cjs} +962 -773
  3. package/dist/chunk-V75PCJHT.cjs.map +1 -0
  4. package/dist/{chunk-MVYNW56R.js → chunk-XUPDNN2U.js} +957 -770
  5. package/dist/chunk-XUPDNN2U.js.map +1 -0
  6. package/dist/client/components/drive/{RenameAccountDialog.d.ts → account/rename.d.ts} +2 -2
  7. package/dist/client/components/drive/account/rename.d.ts.map +1 -0
  8. package/dist/client/components/drive/{dnd-provider.d.ts → dnd/context.d.ts} +1 -1
  9. package/dist/client/components/drive/dnd/context.d.ts.map +1 -0
  10. package/dist/client/components/drive/{CreateFolderDialog.d.ts → folder/create.d.ts} +2 -2
  11. package/dist/client/components/drive/folder/create.d.ts.map +1 -0
  12. package/dist/client/components/drive/{RenameDialog.d.ts → item/rename.d.ts} +3 -3
  13. package/dist/client/components/drive/item/rename.d.ts.map +1 -0
  14. package/dist/client/components/{dialog.d.ts → shared/confirm.d.ts} +2 -2
  15. package/dist/client/components/shared/confirm.d.ts.map +1 -0
  16. package/dist/client/components/ui/{alert-dialog.d.ts → alert-modal.d.ts} +1 -1
  17. package/dist/client/components/ui/alert-modal.d.ts.map +1 -0
  18. package/dist/client/components/ui/{dialog-fullscreen.d.ts → fullscreen.d.ts} +1 -1
  19. package/dist/client/components/ui/fullscreen.d.ts.map +1 -0
  20. package/dist/client/components/ui/{dialog.d.ts → modal.d.ts} +1 -1
  21. package/dist/client/components/ui/modal.d.ts.map +1 -0
  22. package/dist/client/context.d.ts.map +1 -1
  23. package/dist/client/file-chooser.d.ts +1 -0
  24. package/dist/client/file-chooser.d.ts.map +1 -1
  25. package/dist/client/hooks/{useUpload.d.ts → use-upload.d.ts} +2 -2
  26. package/dist/client/hooks/use-upload.d.ts.map +1 -0
  27. package/dist/client/index.cjs +315 -206
  28. package/dist/client/index.cjs.map +1 -1
  29. package/dist/client/index.d.ts +12 -11
  30. package/dist/client/index.d.ts.map +1 -1
  31. package/dist/client/index.js +314 -205
  32. package/dist/client/index.js.map +1 -1
  33. package/dist/server/actions/auth.d.ts +4 -0
  34. package/dist/server/actions/auth.d.ts.map +1 -0
  35. package/dist/server/actions/cors.d.ts +4 -0
  36. package/dist/server/actions/cors.d.ts.map +1 -0
  37. package/dist/server/actions/drive.d.ts +18 -0
  38. package/dist/server/actions/drive.d.ts.map +1 -0
  39. package/dist/server/actions/public.d.ts +4 -0
  40. package/dist/server/actions/public.d.ts.map +1 -0
  41. package/dist/server/actions/shared.d.ts +14 -0
  42. package/dist/server/actions/shared.d.ts.map +1 -0
  43. package/dist/server/config.d.ts.map +1 -1
  44. package/dist/server/controllers/drive.d.ts +26 -0
  45. package/dist/server/controllers/drive.d.ts.map +1 -1
  46. package/dist/server/database/mongoose/schema/drive.d.ts +1 -0
  47. package/dist/server/database/mongoose/schema/drive.d.ts.map +1 -1
  48. package/dist/server/express.cjs +11 -11
  49. package/dist/server/express.js +2 -2
  50. package/dist/server/hono.cjs +11 -11
  51. package/dist/server/hono.js +2 -2
  52. package/dist/server/index.cjs +24 -16
  53. package/dist/server/index.d.ts +2 -2
  54. package/dist/server/index.d.ts.map +1 -1
  55. package/dist/server/index.js +1 -1
  56. package/dist/server/security/{cryptoUtils.d.ts → crypto-utils.d.ts} +1 -1
  57. package/dist/server/security/crypto-utils.d.ts.map +1 -0
  58. package/dist/server/security/{mimeFilter.d.ts → mime-filter.d.ts} +1 -1
  59. package/dist/server/security/mime-filter.d.ts.map +1 -0
  60. package/dist/server/storage-adapters/google.d.ts.map +1 -0
  61. package/dist/server/storage-adapters/local.d.ts.map +1 -0
  62. package/dist/server/utils/{folderValidation.d.ts → folder-validation.d.ts} +1 -1
  63. package/dist/server/utils/folder-validation.d.ts.map +1 -0
  64. package/dist/server/utils/{imageConvert.d.ts → image-convert.d.ts} +1 -1
  65. package/dist/server/utils/image-convert.d.ts.map +1 -0
  66. package/dist/server/zod/schemas.d.ts +5 -0
  67. package/dist/server/zod/schemas.d.ts.map +1 -1
  68. package/dist/types/lib/database/drive.d.ts +1 -0
  69. package/dist/types/lib/database/drive.d.ts.map +1 -1
  70. package/dist/types/lib/database/index.d.ts +2 -2
  71. package/dist/types/lib/database/index.d.ts.map +1 -1
  72. package/dist/types/server/config.d.ts +17 -0
  73. package/dist/types/server/config.d.ts.map +1 -1
  74. package/dist/types/server/index.d.ts +5 -5
  75. package/dist/types/server/index.d.ts.map +1 -1
  76. package/package.json +2 -1
  77. package/dist/chunk-LAKT7IJJ.cjs.map +0 -1
  78. package/dist/chunk-MVYNW56R.js.map +0 -1
  79. package/dist/client/components/dialog.d.ts.map +0 -1
  80. package/dist/client/components/drive/CreateFolderDialog.d.ts.map +0 -1
  81. package/dist/client/components/drive/RenameAccountDialog.d.ts.map +0 -1
  82. package/dist/client/components/drive/RenameDialog.d.ts.map +0 -1
  83. package/dist/client/components/drive/dnd-provider.d.ts.map +0 -1
  84. package/dist/client/components/ui/alert-dialog.d.ts.map +0 -1
  85. package/dist/client/components/ui/dialog-fullscreen.d.ts.map +0 -1
  86. package/dist/client/components/ui/dialog.d.ts.map +0 -1
  87. package/dist/client/hooks/useUpload.d.ts.map +0 -1
  88. package/dist/server/providers/google.d.ts.map +0 -1
  89. package/dist/server/providers/local.d.ts.map +0 -1
  90. package/dist/server/security/cryptoUtils.d.ts.map +0 -1
  91. package/dist/server/security/mimeFilter.d.ts.map +0 -1
  92. package/dist/server/utils/folderValidation.d.ts.map +0 -1
  93. package/dist/server/utils/imageConvert.d.ts.map +0 -1
  94. /package/dist/server/{providers → storage-adapters}/google.d.ts +0 -0
  95. /package/dist/server/{providers → storage-adapters}/local.d.ts +0 -0
@@ -5,6 +5,7 @@ import React3__default, { createContext, useContext, useState, useCallback, useR
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { Slot } from '@radix-ui/react-slot';
7
7
  import { cva } from 'class-variance-authority';
8
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
8
9
  import * as SheetPrimitive from '@radix-ui/react-dialog';
9
10
  import { X, ChevronRight, Check, Circle, Loader2, Folder, FolderPlus, Menu, RotateCcw, Trash2, Group, Search, ArrowUpDown, Calendar, ArrowDownAZ, ArrowUpAZ, ArrowDown01, ArrowUp01, LayoutGrid, List, RefreshCw, Upload, CheckCircle2, Cloud, AlertCircle, Pencil, FileText, HardDrive, Database, ChevronsUpDown, Plus, Settings2, Trash, FolderOpen, Clock } from 'lucide-react';
10
11
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
@@ -12,7 +13,6 @@ import * as LabelPrimitive from '@radix-ui/react-label';
12
13
  import { useForm } from 'react-hook-form';
13
14
  import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, pointerWithin, closestCenter, useDroppable } from '@dnd-kit/core';
14
15
  import { sortableKeyboardCoordinates, arrayMove, SortableContext, rectSortingStrategy, useSortable } from '@dnd-kit/sortable';
15
- import * as ProgressPrimitive from '@radix-ui/react-progress';
16
16
  import { startOfWeek, subWeeks, isToday, isYesterday, isAfter } from 'date-fns';
17
17
  import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
18
18
  import { CSS } from '@dnd-kit/utilities';
@@ -66,9 +66,15 @@ var DriveProvider = (props) => {
66
66
  headers,
67
67
  credentials: withCredentials ? "include" : "same-origin"
68
68
  });
69
- return await res.json();
69
+ try {
70
+ return await res.json();
71
+ } catch (parseErr) {
72
+ const detail = parseErr instanceof Error ? parseErr.message : String(parseErr);
73
+ return { status: res.status || 0, message: `Could not read the server response for "${action}" (${detail})` };
74
+ }
70
75
  } catch (err) {
71
- return { status: 0, message: err instanceof Error ? err.message : "Network error \u2014 please check your connection" };
76
+ const detail = err instanceof Error ? err.message : String(err);
77
+ return { status: 0, message: `Network request failed for "${action}" (${detail})` };
72
78
  }
73
79
  }, [apiEndpoint, activeAccountId, withCredentials]);
74
80
  const fetchItems = useCallback(async () => {
@@ -290,7 +296,7 @@ var getChunkSize = (fileSize) => {
290
296
  if (fileSize < 1024 * 1024 * 1024) return 8 * 1024 * 1024;
291
297
  return 16 * 1024 * 1024;
292
298
  };
293
- var useUpload = (apiEndpoint, activeAccountId, withCredentials = false, onUploadComplete) => {
299
+ var useUpload = (apiEndpoint, activeAccountId, withCredentials = false, onUploadComplete, unauthenticated = false) => {
294
300
  const [uploads, setUploads] = useState([]);
295
301
  const abortControllers = useRef(/* @__PURE__ */ new Map());
296
302
  const filesRef = useRef(/* @__PURE__ */ new Map());
@@ -343,9 +349,9 @@ var useUpload = (apiEndpoint, activeAccountId, withCredentials = false, onUpload
343
349
  addLog(uploadId, "success", `Chunk uploaded successfully`);
344
350
  return [true, data.data, false];
345
351
  } catch (error) {
346
- const errorMsg = error instanceof Error ? error.message : "Network error during upload";
347
- addLog(uploadId, "error", `Network/Fetch error: ${errorMsg}`);
348
- return [false, errorMsg, true];
352
+ const detail = error instanceof Error ? error.message : String(error);
353
+ addLog(uploadId, "error", `Network/Fetch error: ${detail}`);
354
+ return [false, `Upload connection failed: ${detail}`, true];
349
355
  }
350
356
  };
351
357
  const processItem = async (item, file, folderId) => {
@@ -374,6 +380,7 @@ var useUpload = (apiEndpoint, activeAccountId, withCredentials = false, onUpload
374
380
  formData.append("fileType", file.type);
375
381
  formData.append("folderId", folderId || "root");
376
382
  if (driveId) formData.append("driveId", driveId);
383
+ if (unauthenticated) formData.append("unauthenticated", "true");
377
384
  let attempts = 0;
378
385
  let success = false;
379
386
  while (!success && attempts < 3 && !controller.signal.aborted) {
@@ -533,6 +540,39 @@ function Button({
533
540
  }
534
541
  );
535
542
  }
543
+ function Progress({
544
+ className,
545
+ value,
546
+ indicatorClassName,
547
+ indeterminate = false,
548
+ ...props
549
+ }) {
550
+ const isIndeterminate = indeterminate || value === void 0;
551
+ return /* @__PURE__ */ jsx(
552
+ ProgressPrimitive.Root,
553
+ {
554
+ "data-slot": "progress",
555
+ className: cn(
556
+ "nd:bg-primary/20 nd:relative nd:h-2 nd:w-full nd:overflow-hidden nd:rounded-full",
557
+ className
558
+ ),
559
+ ...props,
560
+ children: /* @__PURE__ */ jsx(
561
+ ProgressPrimitive.Indicator,
562
+ {
563
+ "data-slot": "progress-indicator",
564
+ className: cn(
565
+ "nd:bg-primary nd:h-full nd:flex-1 nd:transition-all",
566
+ isIndeterminate && "nd:w-1/3 nd:animate-[indeterminate_1.5s_ease-in-out_infinite]",
567
+ !isIndeterminate && "nd:w-full",
568
+ indicatorClassName
569
+ ),
570
+ style: isIndeterminate ? void 0 : { transform: `translateX(-${100 - (value || 0)}%)` }
571
+ }
572
+ )
573
+ }
574
+ );
575
+ }
536
576
  function Dialog2({ ...props }) {
537
577
  return /* @__PURE__ */ jsx(SheetPrimitive.Root, { "data-slot": "dialog2", ...props });
538
578
  }
@@ -1031,7 +1071,7 @@ function Label2({
1031
1071
  }
1032
1072
  );
1033
1073
  }
1034
- var DialogConfirmation = (props) => {
1074
+ var DriveConfirm = (props) => {
1035
1075
  const { title, description, onConfirm, disableEscapeKeyDown, inputs, onClose, open } = props;
1036
1076
  const [error, setError] = useState(null);
1037
1077
  const [isLoading, setIsLoading] = useState(false);
@@ -1128,11 +1168,29 @@ var DialogConfirmation = (props) => {
1128
1168
  )
1129
1169
  ] }, input.id)) }),
1130
1170
  /* @__PURE__ */ jsxs(DialogFooter, { children: [
1131
- /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, disabled: isLoading, children: "Cancel" }),
1132
1171
  /* @__PURE__ */ jsx(
1133
1172
  Button,
1134
1173
  {
1135
- onClick: handleConfirm,
1174
+ type: "button",
1175
+ variant: "outline",
1176
+ onClick: (e) => {
1177
+ e.preventDefault();
1178
+ e.stopPropagation();
1179
+ handleClose();
1180
+ },
1181
+ disabled: isLoading,
1182
+ children: "Cancel"
1183
+ }
1184
+ ),
1185
+ /* @__PURE__ */ jsx(
1186
+ Button,
1187
+ {
1188
+ type: "button",
1189
+ onClick: (e) => {
1190
+ e.preventDefault();
1191
+ e.stopPropagation();
1192
+ void handleConfirm();
1193
+ },
1136
1194
  disabled: isLoading || !isFormValid(),
1137
1195
  children: "Confirm"
1138
1196
  }
@@ -1142,7 +1200,7 @@ var DialogConfirmation = (props) => {
1142
1200
  }
1143
1201
  ) });
1144
1202
  };
1145
- var RenameAccountDialog = (props) => {
1203
+ var DriveAccountRename = (props) => {
1146
1204
  const { open, onClose, account, onConfirm } = props;
1147
1205
  const {
1148
1206
  register,
@@ -1203,52 +1261,65 @@ var RenameAccountDialog = (props) => {
1203
1261
  e.preventDefault();
1204
1262
  }
1205
1263
  },
1206
- children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(handleFormSubmit), children: [
1207
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
1208
- /* @__PURE__ */ jsx(DialogTitle, { children: "Rename Account" }),
1209
- /* @__PURE__ */ jsx(DialogDescription, { children: "Enter a new display name for this storage account." })
1210
- ] }),
1211
- errors.name && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
1212
- /* @__PURE__ */ jsx(AlertCircle, { className: "nd:h-4 nd:w-4" }),
1213
- /* @__PURE__ */ jsx(AlertTitle, { children: "Error" }),
1214
- /* @__PURE__ */ jsx(AlertDescription, { children: errors.name.message })
1215
- ] }),
1216
- /* @__PURE__ */ jsx("div", { className: "nd:grid nd:gap-4 nd:py-4", children: /* @__PURE__ */ jsxs("div", { className: "nd:grid nd:gap-2", children: [
1217
- /* @__PURE__ */ jsx(Label2, { htmlFor: "rename-account-input", children: "Account name" }),
1218
- /* @__PURE__ */ jsx(
1219
- Input,
1220
- {
1221
- id: "rename-account-input",
1222
- ...register("name", {
1223
- required: "Account name is required",
1224
- validate: (value) => {
1225
- const trimmed = value.trim();
1226
- if (!trimmed) return "Account name cannot be empty";
1227
- if (trimmed.length > 255)
1228
- return "Account name is too long";
1229
- return true;
1264
+ children: /* @__PURE__ */ jsxs(
1265
+ "form",
1266
+ {
1267
+ onSubmit: (e) => {
1268
+ e.stopPropagation();
1269
+ void handleSubmit(handleFormSubmit)(e);
1270
+ },
1271
+ children: [
1272
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
1273
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Rename Account" }),
1274
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Enter a new display name for this storage account." })
1275
+ ] }),
1276
+ errors.name && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
1277
+ /* @__PURE__ */ jsx(AlertCircle, { className: "nd:h-4 nd:w-4" }),
1278
+ /* @__PURE__ */ jsx(AlertTitle, { children: "Error" }),
1279
+ /* @__PURE__ */ jsx(AlertDescription, { children: errors.name.message })
1280
+ ] }),
1281
+ /* @__PURE__ */ jsx("div", { className: "nd:grid nd:gap-4 nd:py-4", children: /* @__PURE__ */ jsxs("div", { className: "nd:grid nd:gap-2", children: [
1282
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "rename-account-input", children: "Account name" }),
1283
+ /* @__PURE__ */ jsx(
1284
+ Input,
1285
+ {
1286
+ id: "rename-account-input",
1287
+ ...register("name", {
1288
+ required: "Account name is required",
1289
+ validate: (value) => {
1290
+ const trimmed = value.trim();
1291
+ if (!trimmed) return "Account name cannot be empty";
1292
+ if (trimmed.length > 255)
1293
+ return "Account name is too long";
1294
+ return true;
1295
+ }
1296
+ }),
1297
+ placeholder: "Enter account name",
1298
+ disabled: isSubmitting,
1299
+ autoComplete: "off"
1230
1300
  }
1231
- }),
1232
- placeholder: "Enter account name",
1233
- disabled: isSubmitting,
1234
- autoComplete: "off"
1235
- }
1236
- )
1237
- ] }) }),
1238
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
1239
- /* @__PURE__ */ jsx(
1240
- Button,
1241
- {
1242
- type: "button",
1243
- variant: "outline",
1244
- onClick: handleClose,
1245
- disabled: isSubmitting,
1246
- children: "Cancel"
1247
- }
1248
- ),
1249
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? "Saving..." : "Save" })
1250
- ] })
1251
- ] })
1301
+ )
1302
+ ] }) }),
1303
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
1304
+ /* @__PURE__ */ jsx(
1305
+ Button,
1306
+ {
1307
+ type: "button",
1308
+ variant: "outline",
1309
+ onClick: (e) => {
1310
+ e.preventDefault();
1311
+ e.stopPropagation();
1312
+ handleClose();
1313
+ },
1314
+ disabled: isSubmitting,
1315
+ children: "Cancel"
1316
+ }
1317
+ ),
1318
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? "Saving..." : "Save" })
1319
+ ] })
1320
+ ]
1321
+ }
1322
+ )
1252
1323
  }
1253
1324
  ) });
1254
1325
  };
@@ -1325,39 +1396,6 @@ var DriveDndProvider = (props) => {
1325
1396
  }
1326
1397
  ) : children });
1327
1398
  };
1328
- function Progress({
1329
- className,
1330
- value,
1331
- indicatorClassName,
1332
- indeterminate = false,
1333
- ...props
1334
- }) {
1335
- const isIndeterminate = indeterminate || value === void 0;
1336
- return /* @__PURE__ */ jsx(
1337
- ProgressPrimitive.Root,
1338
- {
1339
- "data-slot": "progress",
1340
- className: cn(
1341
- "nd:bg-primary/20 nd:relative nd:h-2 nd:w-full nd:overflow-hidden nd:rounded-full",
1342
- className
1343
- ),
1344
- ...props,
1345
- children: /* @__PURE__ */ jsx(
1346
- ProgressPrimitive.Indicator,
1347
- {
1348
- "data-slot": "progress-indicator",
1349
- className: cn(
1350
- "nd:bg-primary nd:h-full nd:flex-1 nd:transition-all",
1351
- isIndeterminate && "nd:w-1/3 nd:animate-[indeterminate_1.5s_ease-in-out_infinite]",
1352
- !isIndeterminate && "nd:w-full",
1353
- indicatorClassName
1354
- ),
1355
- style: isIndeterminate ? void 0 : { transform: `translateX(-${100 - (value || 0)}%)` }
1356
- }
1357
- )
1358
- }
1359
- );
1360
- }
1361
1399
  var ContextMenu = ContextMenuPrimitive.Root;
1362
1400
  var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
1363
1401
  var ContextMenuSubTrigger = React3.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
@@ -1469,7 +1507,7 @@ var ContextMenuSeparator = React3.forwardRef(({ className, ...props }, ref) => /
1469
1507
  }
1470
1508
  ));
1471
1509
  ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
1472
- var CreateFolderDialog = (props) => {
1510
+ var DriveFolderCreate = (props) => {
1473
1511
  const { open, onClose, onConfirm } = props;
1474
1512
  const {
1475
1513
  register,
@@ -1521,56 +1559,69 @@ var CreateFolderDialog = (props) => {
1521
1559
  e.preventDefault();
1522
1560
  }
1523
1561
  },
1524
- children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(handleFormSubmit), children: [
1525
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
1526
- /* @__PURE__ */ jsx(DialogTitle, { children: "Create New Folder" }),
1527
- /* @__PURE__ */ jsx(DialogDescription, { children: "Enter a name for the new folder" })
1528
- ] }),
1529
- errors.name && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
1530
- /* @__PURE__ */ jsx(AlertCircle, { className: "nd:h-4 nd:w-4" }),
1531
- /* @__PURE__ */ jsx(AlertTitle, { children: "Error" }),
1532
- /* @__PURE__ */ jsx(AlertDescription, { children: errors.name.message })
1533
- ] }),
1534
- /* @__PURE__ */ jsx("div", { className: "nd:grid nd:gap-4 nd:py-4", children: /* @__PURE__ */ jsxs("div", { className: "nd:grid nd:gap-2", children: [
1535
- /* @__PURE__ */ jsx(Label2, { htmlFor: "folder-name", children: "Folder name" }),
1536
- /* @__PURE__ */ jsx(
1537
- Input,
1538
- {
1539
- id: "folder-name",
1540
- ...register("name", {
1541
- required: "Folder name is required",
1542
- validate: (value) => {
1543
- const trimmed = value.trim();
1544
- if (!trimmed) return "Folder name cannot be empty";
1545
- if (trimmed.length > 255)
1546
- return "Folder name is too long";
1547
- return true;
1562
+ children: /* @__PURE__ */ jsxs(
1563
+ "form",
1564
+ {
1565
+ onSubmit: (e) => {
1566
+ e.stopPropagation();
1567
+ void handleSubmit(handleFormSubmit)(e);
1568
+ },
1569
+ children: [
1570
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
1571
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Create New Folder" }),
1572
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Enter a name for the new folder" })
1573
+ ] }),
1574
+ errors.name && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
1575
+ /* @__PURE__ */ jsx(AlertCircle, { className: "nd:h-4 nd:w-4" }),
1576
+ /* @__PURE__ */ jsx(AlertTitle, { children: "Error" }),
1577
+ /* @__PURE__ */ jsx(AlertDescription, { children: errors.name.message })
1578
+ ] }),
1579
+ /* @__PURE__ */ jsx("div", { className: "nd:grid nd:gap-4 nd:py-4", children: /* @__PURE__ */ jsxs("div", { className: "nd:grid nd:gap-2", children: [
1580
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "folder-name", children: "Folder name" }),
1581
+ /* @__PURE__ */ jsx(
1582
+ Input,
1583
+ {
1584
+ id: "folder-name",
1585
+ ...register("name", {
1586
+ required: "Folder name is required",
1587
+ validate: (value) => {
1588
+ const trimmed = value.trim();
1589
+ if (!trimmed) return "Folder name cannot be empty";
1590
+ if (trimmed.length > 255)
1591
+ return "Folder name is too long";
1592
+ return true;
1593
+ }
1594
+ }),
1595
+ placeholder: "Enter folder name",
1596
+ disabled: isSubmitting,
1597
+ autoComplete: "off"
1548
1598
  }
1549
- }),
1550
- placeholder: "Enter folder name",
1551
- disabled: isSubmitting,
1552
- autoComplete: "off"
1553
- }
1554
- )
1555
- ] }) }),
1556
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
1557
- /* @__PURE__ */ jsx(
1558
- Button,
1559
- {
1560
- type: "button",
1561
- variant: "outline",
1562
- onClick: handleClose,
1563
- disabled: isSubmitting,
1564
- children: "Cancel"
1565
- }
1566
- ),
1567
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? "Creating..." : "Create" })
1568
- ] })
1569
- ] })
1599
+ )
1600
+ ] }) }),
1601
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
1602
+ /* @__PURE__ */ jsx(
1603
+ Button,
1604
+ {
1605
+ type: "button",
1606
+ variant: "outline",
1607
+ onClick: (e) => {
1608
+ e.preventDefault();
1609
+ e.stopPropagation();
1610
+ handleClose();
1611
+ },
1612
+ disabled: isSubmitting,
1613
+ children: "Cancel"
1614
+ }
1615
+ ),
1616
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? "Creating..." : "Create" })
1617
+ ] })
1618
+ ]
1619
+ }
1620
+ )
1570
1621
  }
1571
1622
  ) });
1572
1623
  };
1573
- var RenameDialog = (props) => {
1624
+ var DriveItemRename = (props) => {
1574
1625
  const { open, onClose, item, onConfirm } = props;
1575
1626
  const {
1576
1627
  register,
@@ -1630,57 +1681,70 @@ var RenameDialog = (props) => {
1630
1681
  e.preventDefault();
1631
1682
  }
1632
1683
  },
1633
- children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(handleFormSubmit), children: [
1634
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
1635
- /* @__PURE__ */ jsxs(DialogTitle, { children: [
1636
- "Rename ",
1637
- itemType
1638
- ] }),
1639
- /* @__PURE__ */ jsxs(DialogDescription, { children: [
1640
- "Enter a new name for this ",
1641
- itemType.toLowerCase()
1642
- ] })
1643
- ] }),
1644
- errors.name && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
1645
- /* @__PURE__ */ jsx(AlertCircle, { className: "nd:h-4 nd:w-4" }),
1646
- /* @__PURE__ */ jsx(AlertTitle, { children: "Error" }),
1647
- /* @__PURE__ */ jsx(AlertDescription, { children: errors.name.message })
1648
- ] }),
1649
- /* @__PURE__ */ jsx("div", { className: "nd:grid nd:gap-4 nd:py-4", children: /* @__PURE__ */ jsxs("div", { className: "nd:grid nd:gap-2", children: [
1650
- /* @__PURE__ */ jsx(Label2, { htmlFor: "rename-input", children: "Name" }),
1651
- /* @__PURE__ */ jsx(
1652
- Input,
1653
- {
1654
- id: "rename-input",
1655
- ...register("name", {
1656
- required: "Name is required",
1657
- validate: (value) => {
1658
- const trimmed = value.trim();
1659
- if (!trimmed) return "Name cannot be empty";
1660
- if (trimmed.length > 255) return "Name is too long";
1661
- return true;
1684
+ children: /* @__PURE__ */ jsxs(
1685
+ "form",
1686
+ {
1687
+ onSubmit: (e) => {
1688
+ e.stopPropagation();
1689
+ void handleSubmit(handleFormSubmit)(e);
1690
+ },
1691
+ children: [
1692
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
1693
+ /* @__PURE__ */ jsxs(DialogTitle, { children: [
1694
+ "Rename ",
1695
+ itemType
1696
+ ] }),
1697
+ /* @__PURE__ */ jsxs(DialogDescription, { children: [
1698
+ "Enter a new name for this ",
1699
+ itemType.toLowerCase()
1700
+ ] })
1701
+ ] }),
1702
+ errors.name && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
1703
+ /* @__PURE__ */ jsx(AlertCircle, { className: "nd:h-4 nd:w-4" }),
1704
+ /* @__PURE__ */ jsx(AlertTitle, { children: "Error" }),
1705
+ /* @__PURE__ */ jsx(AlertDescription, { children: errors.name.message })
1706
+ ] }),
1707
+ /* @__PURE__ */ jsx("div", { className: "nd:grid nd:gap-4 nd:py-4", children: /* @__PURE__ */ jsxs("div", { className: "nd:grid nd:gap-2", children: [
1708
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "rename-input", children: "Name" }),
1709
+ /* @__PURE__ */ jsx(
1710
+ Input,
1711
+ {
1712
+ id: "rename-input",
1713
+ ...register("name", {
1714
+ required: "Name is required",
1715
+ validate: (value) => {
1716
+ const trimmed = value.trim();
1717
+ if (!trimmed) return "Name cannot be empty";
1718
+ if (trimmed.length > 255) return "Name is too long";
1719
+ return true;
1720
+ }
1721
+ }),
1722
+ placeholder: "Enter name",
1723
+ disabled: isSubmitting,
1724
+ autoComplete: "off"
1662
1725
  }
1663
- }),
1664
- placeholder: "Enter name",
1665
- disabled: isSubmitting,
1666
- autoComplete: "off"
1667
- }
1668
- )
1669
- ] }) }),
1670
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
1671
- /* @__PURE__ */ jsx(
1672
- Button,
1673
- {
1674
- type: "button",
1675
- variant: "outline",
1676
- onClick: handleClose,
1677
- disabled: isSubmitting,
1678
- children: "Cancel"
1679
- }
1680
- ),
1681
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? "Renaming..." : "Rename" })
1682
- ] })
1683
- ] })
1726
+ )
1727
+ ] }) }),
1728
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
1729
+ /* @__PURE__ */ jsx(
1730
+ Button,
1731
+ {
1732
+ type: "button",
1733
+ variant: "outline",
1734
+ onClick: (e) => {
1735
+ e.preventDefault();
1736
+ e.stopPropagation();
1737
+ handleClose();
1738
+ },
1739
+ disabled: isSubmitting,
1740
+ children: "Cancel"
1741
+ }
1742
+ ),
1743
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? "Renaming..." : "Rename" })
1744
+ ] })
1745
+ ]
1746
+ }
1747
+ )
1684
1748
  }
1685
1749
  ) });
1686
1750
  };
@@ -1962,7 +2026,7 @@ var DriveFileGrid = (props) => {
1962
2026
  hasMore && /* @__PURE__ */ jsx("div", { ref: observerTarget, className: "nd:flex nd:justify-center nd:py-6", children: isLoadingMore && /* @__PURE__ */ jsx(Loader2, { className: "nd:size-6 nd:animate-spin nd:text-muted-foreground" }) })
1963
2027
  ] }),
1964
2028
  /* @__PURE__ */ jsx(
1965
- CreateFolderDialog,
2029
+ DriveFolderCreate,
1966
2030
  {
1967
2031
  open: dialogs.newFolder,
1968
2032
  onClose: () => setDialogs((prev) => ({ ...prev, newFolder: false })),
@@ -1972,7 +2036,7 @@ var DriveFileGrid = (props) => {
1972
2036
  }
1973
2037
  ),
1974
2038
  /* @__PURE__ */ jsx(
1975
- RenameDialog,
2039
+ DriveItemRename,
1976
2040
  {
1977
2041
  open: dialogs.rename,
1978
2042
  onClose: () => {
@@ -1987,7 +2051,7 @@ var DriveFileGrid = (props) => {
1987
2051
  }
1988
2052
  ),
1989
2053
  /* @__PURE__ */ jsx(
1990
- DialogConfirmation,
2054
+ DriveConfirm,
1991
2055
  {
1992
2056
  open: dialogs.delete,
1993
2057
  onClose: () => {
@@ -2248,7 +2312,7 @@ var DriveHeader = ({ className }) => {
2248
2312
  )
2249
2313
  ] }),
2250
2314
  /* @__PURE__ */ jsx(
2251
- DialogConfirmation,
2315
+ DriveConfirm,
2252
2316
  {
2253
2317
  open: dialogs.delete,
2254
2318
  onClose: () => setDialogs((prev) => ({ ...prev, delete: false })),
@@ -2264,7 +2328,7 @@ var DriveHeader = ({ className }) => {
2264
2328
  }
2265
2329
  ),
2266
2330
  /* @__PURE__ */ jsx(
2267
- DialogConfirmation,
2331
+ DriveConfirm,
2268
2332
  {
2269
2333
  open: dialogs.emptyTrash,
2270
2334
  onClose: () => setDialogs((prev) => ({ ...prev, emptyTrash: false })),
@@ -2278,7 +2342,7 @@ var DriveHeader = ({ className }) => {
2278
2342
  }
2279
2343
  ),
2280
2344
  /* @__PURE__ */ jsx(
2281
- CreateFolderDialog,
2345
+ DriveFolderCreate,
2282
2346
  {
2283
2347
  open: dialogs.newFolder,
2284
2348
  onClose: () => setDialogs((prev) => ({ ...prev, newFolder: false })),
@@ -2988,7 +3052,7 @@ var ChooserSidebar = (props) => {
2988
3052
  ] }),
2989
3053
  /* @__PURE__ */ jsx("div", { className: "nd:p-2.5 nd:border-t nd:border-border/50 nd:bg-background/50 nd:dark:bg-background/30", children: /* @__PURE__ */ jsx(DriveStorageIndicator, {}) }),
2990
3054
  /* @__PURE__ */ jsx(
2991
- RenameAccountDialog,
3055
+ DriveAccountRename,
2992
3056
  {
2993
3057
  open: renameDialog.open,
2994
3058
  onClose: () => setRenameDialog({ open: false, account: null }),
@@ -2997,7 +3061,7 @@ var ChooserSidebar = (props) => {
2997
3061
  }
2998
3062
  ),
2999
3063
  /* @__PURE__ */ jsx(
3000
- DialogConfirmation,
3064
+ DriveConfirm,
3001
3065
  {
3002
3066
  open: deleteDialog.open,
3003
3067
  onClose: () => setDeleteDialog({ open: false, account: null }),
@@ -3037,11 +3101,46 @@ var DriveFileChooser = (props) => {
3037
3101
  className,
3038
3102
  disabled = false,
3039
3103
  error,
3040
- helperText
3104
+ helperText,
3105
+ allowUnauthenticated = false
3041
3106
  } = props;
3042
- const { items, selectedFileIds, setSelectedFileIds, createUrl, triggerFetch } = useDrive();
3107
+ const { items, selectedFileIds, setSelectedFileIds, createUrl, triggerFetch, apiEndpoint, activeAccountId, withCredentials, callAPI } = useDrive();
3043
3108
  useStyleInjector();
3044
3109
  const [isOpen, setIsOpen] = useState(false);
3110
+ const fileInputRef = useRef(null);
3111
+ const valueRef = useRef(value);
3112
+ valueRef.current = value;
3113
+ const [authed, setAuthed] = useState(allowUnauthenticated ? null : true);
3114
+ useEffect(() => {
3115
+ if (!allowUnauthenticated) return;
3116
+ callAPI("information").then((res) => setAuthed(res.status === 200 ? !!res.data?.authenticated : false));
3117
+ }, [allowUnauthenticated, callAPI]);
3118
+ const unauthenticatedMode = allowUnauthenticated && authed === false;
3119
+ const handleUploaded = useCallback((item) => {
3120
+ const isFile = item?.information?.type === "FILE";
3121
+ const uploaded = {
3122
+ id: item.id,
3123
+ file: { name: item.name, mime: isFile ? item.information.mime : "", size: isFile ? item.information.sizeInBytes : 0 }
3124
+ };
3125
+ const current = valueRef.current;
3126
+ if (multiple) {
3127
+ const arr = Array.isArray(current) ? current : current ? [current] : [];
3128
+ onChange([...arr, uploaded]);
3129
+ } else {
3130
+ onChange(uploaded);
3131
+ }
3132
+ }, [multiple, onChange]);
3133
+ const { uploads, uploadFiles } = useUpload(apiEndpoint, activeAccountId, withCredentials, handleUploaded, unauthenticatedMode);
3134
+ const openPicker = useCallback(() => {
3135
+ if (unauthenticatedMode) fileInputRef.current?.click();
3136
+ else setIsOpen(true);
3137
+ }, [unauthenticatedMode]);
3138
+ const handleFilePick = useCallback((e) => {
3139
+ const picked = Array.from(e.target.files ?? []);
3140
+ if (picked.length) uploadFiles(multiple ? picked : [picked[0]], null);
3141
+ e.target.value = "";
3142
+ }, [uploadFiles, multiple]);
3143
+ const activeUploads = unauthenticatedMode ? uploads.filter((u) => ["queued", "uploading", "error"].includes(u.status)) : [];
3045
3144
  useEffect(() => {
3046
3145
  if (isOpen) {
3047
3146
  triggerFetch();
@@ -3075,8 +3174,8 @@ var DriveFileChooser = (props) => {
3075
3174
  {
3076
3175
  type: "button",
3077
3176
  variant: "outline",
3078
- onClick: () => setIsOpen(true),
3079
- disabled,
3177
+ onClick: openPicker,
3178
+ disabled: disabled || allowUnauthenticated && authed === null,
3080
3179
  className: cn(
3081
3180
  "nd:w-full nd:h-auto nd:justify-start nd:gap-3 nd:px-3 nd:py-2.5 nd:border-dashed",
3082
3181
  error && "nd:border-destructive"
@@ -3105,7 +3204,7 @@ var DriveFileChooser = (props) => {
3105
3204
  ] })
3106
3205
  ] }),
3107
3206
  /* @__PURE__ */ jsxs("div", { className: "nd:flex nd:items-center nd:gap-1 nd:shrink-0", children: [
3108
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setIsOpen(true), disabled, children: "Change" }),
3207
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: openPicker, disabled, children: "Change" }),
3109
3208
  !disabled && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "nd:size-8", onClick: () => handleRemove(displayFiles[0].id), children: /* @__PURE__ */ jsx(X, { className: "nd:size-4" }) })
3110
3209
  ] })
3111
3210
  ] }),
@@ -3118,7 +3217,7 @@ var DriveFileChooser = (props) => {
3118
3217
  " selected"
3119
3218
  ] }),
3120
3219
  /* @__PURE__ */ jsxs("div", { className: "nd:flex nd:items-center nd:gap-1", children: [
3121
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "nd:h-7 nd:text-xs", onClick: () => setIsOpen(true), disabled, children: "Add more" }),
3220
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "nd:h-7 nd:text-xs", onClick: openPicker, disabled, children: "Add more" }),
3122
3221
  !disabled && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "nd:h-7 nd:text-xs nd:text-muted-foreground", onClick: () => onChange([]), children: "Clear" })
3123
3222
  ] })
3124
3223
  ] }),
@@ -3137,6 +3236,16 @@ var DriveFileChooser = (props) => {
3137
3236
  ] })
3138
3237
  ),
3139
3238
  error && helperText && /* @__PURE__ */ jsx("p", { className: "nd:text-xs nd:text-destructive nd:mt-1.5", children: helperText }),
3239
+ unauthenticatedMode && /* @__PURE__ */ jsx("input", { ref: fileInputRef, type: "file", accept, multiple, className: "nd:hidden", onChange: handleFilePick }),
3240
+ activeUploads.length > 0 && /* @__PURE__ */ jsx("div", { className: "nd:mt-2 nd:space-y-2", children: activeUploads.map((u) => /* @__PURE__ */ jsxs("div", { className: "nd:rounded-lg nd:border nd:px-3 nd:py-2", children: [
3241
+ /* @__PURE__ */ jsxs("div", { className: "nd:flex nd:items-center nd:gap-2", children: [
3242
+ u.status === "error" ? /* @__PURE__ */ jsx(X, { className: "nd:size-4 nd:text-destructive nd:shrink-0" }) : /* @__PURE__ */ jsx(Loader2, { className: "nd:size-4 nd:animate-spin nd:text-muted-foreground nd:shrink-0" }),
3243
+ /* @__PURE__ */ jsx("span", { className: "nd:text-sm nd:truncate nd:flex-1", children: u.name }),
3244
+ /* @__PURE__ */ jsx("span", { className: "nd:text-xs nd:text-muted-foreground nd:shrink-0", children: u.status === "error" ? "Failed" : `${Math.round(u.currentChunk / Math.max(1, u.totalChunks) * 100)}%` })
3245
+ ] }),
3246
+ u.status !== "error" && /* @__PURE__ */ jsx(Progress, { value: Math.round(u.currentChunk / Math.max(1, u.totalChunks) * 100), className: "nd:mt-1.5" }),
3247
+ u.status === "error" && u.error && /* @__PURE__ */ jsx("p", { className: "nd:text-xs nd:text-destructive nd:mt-1", children: u.error })
3248
+ ] }, u.id)) }),
3140
3249
  /* @__PURE__ */ jsx(Dialog2, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs(Dialog2Content, { showCloseButton: false, className: "nd-drive-root", children: [
3141
3250
  /* @__PURE__ */ jsxs(Dialog2Header, { className: "nd:gap-2", children: [
3142
3251
  /* @__PURE__ */ jsx(MobileSidebarSheet, {}),
@@ -3425,7 +3534,7 @@ var SidebarContent = (props) => {
3425
3534
  ] }),
3426
3535
  /* @__PURE__ */ jsx("div", { className: "nd:p-2.5 nd:border-t nd:border-border/50 nd:bg-background/50 nd:dark:bg-background/30", children: /* @__PURE__ */ jsx(DriveStorageIndicator, {}) }),
3427
3536
  /* @__PURE__ */ jsx(
3428
- RenameAccountDialog,
3537
+ DriveAccountRename,
3429
3538
  {
3430
3539
  open: renameDialog.open,
3431
3540
  onClose: () => setRenameDialog({ open: false, account: null }),
@@ -3434,7 +3543,7 @@ var SidebarContent = (props) => {
3434
3543
  }
3435
3544
  ),
3436
3545
  /* @__PURE__ */ jsx(
3437
- DialogConfirmation,
3546
+ DriveConfirm,
3438
3547
  {
3439
3548
  open: deleteDialog.open,
3440
3549
  onClose: () => setDeleteDialog({ open: false, account: null }),
@@ -3794,7 +3903,7 @@ var DriveExplorer = (props) => {
3794
3903
  ] }) : /* @__PURE__ */ jsx("div", { className: "nd:px-2 nd:py-6 nd:text-center", children: /* @__PURE__ */ jsx("p", { className: "nd:text-xs nd:text-muted-foreground", children: "No actions available" }) }) })
3795
3904
  ] }),
3796
3905
  /* @__PURE__ */ jsx(
3797
- CreateFolderDialog,
3906
+ DriveFolderCreate,
3798
3907
  {
3799
3908
  open: dialogs.newFolder,
3800
3909
  onClose: () => setDialogs((prev) => ({ ...prev, newFolder: false })),
@@ -3804,7 +3913,7 @@ var DriveExplorer = (props) => {
3804
3913
  }
3805
3914
  ),
3806
3915
  /* @__PURE__ */ jsx(
3807
- RenameDialog,
3916
+ DriveItemRename,
3808
3917
  {
3809
3918
  open: dialogs.rename,
3810
3919
  onClose: () => {
@@ -3819,7 +3928,7 @@ var DriveExplorer = (props) => {
3819
3928
  }
3820
3929
  ),
3821
3930
  /* @__PURE__ */ jsx(
3822
- DialogConfirmation,
3931
+ DriveConfirm,
3823
3932
  {
3824
3933
  open: dialogs.delete,
3825
3934
  onClose: () => {