blixify-ui-web 1.2.111 → 1.2.112

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.
@@ -0,0 +1,877 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
45
+ var __generator = (this && this.__generator) || function (thisArg, body) {
46
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
47
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
+ function verb(n) { return function (v) { return step([n, v]); }; }
49
+ function step(op) {
50
+ if (f) throw new TypeError("Generator is already executing.");
51
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
52
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
53
+ if (y = 0, t) op = [op[0] & 2, t.value];
54
+ switch (op[0]) {
55
+ case 0: case 1: t = op; break;
56
+ case 4: _.label++; return { value: op[1], done: false };
57
+ case 5: _.label++; y = op[1]; op = [0]; continue;
58
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
+ default:
60
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
+ if (t[2]) _.ops.pop();
65
+ _.trys.pop(); continue;
66
+ }
67
+ op = body.call(thisArg, _);
68
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
+ }
71
+ };
72
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
73
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
74
+ if (ar || !(i in from)) {
75
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
76
+ ar[i] = from[i];
77
+ }
78
+ }
79
+ return to.concat(ar || Array.prototype.slice.call(from));
80
+ };
81
+ Object.defineProperty(exports, "__esModule", { value: true });
82
+ exports.DriveView = void 0;
83
+ var react_1 = require("@headlessui/react");
84
+ var HeroIcons = __importStar(require("@heroicons/react/24/outline"));
85
+ var react_2 = __importStar(require("react"));
86
+ var popUp_1 = require("../../advanced/popUp");
87
+ var uuid_1 = require("uuid");
88
+ var button_1 = require("../../action/button");
89
+ var emptyState_1 = require("../../display/emptyState");
90
+ var filePreview_1 = require("../../display/filePreview");
91
+ var loading_1 = require("../../display/loading");
92
+ var modal_1 = require("../../display/modal");
93
+ var newList_1 = require("../../display/newList");
94
+ var textInput_1 = require("../../input/textInput");
95
+ var uploadInput_1 = require("../../input/uploadInput");
96
+ var blobModule_1 = require("../blobModule");
97
+ var driveUtils_1 = require("./driveUtils");
98
+ var LAYOUT_STORAGE_PREFIX = "blixify-dtw-drive-layout-";
99
+ /**
100
+ * A folder browser over a collection whose rows are files and folders.
101
+ *
102
+ * INFO: the rows of the open folder arrive from DataTemplate's own list query,
103
+ * so pagination, tab filters and permission filters behave as on any other
104
+ * view. This component adds the folder tree it needs for the breadcrumb, the
105
+ * move picker and search paths, and performs the drive's own writes.
106
+ */
107
+ var DriveView = function (props) {
108
+ var _a, _b, _c;
109
+ var _d = (0, react_2.useState)(new Map()), folders = _d[0], setFolders = _d[1];
110
+ var _e = (0, react_2.useState)(function () {
111
+ try {
112
+ var stored = window.localStorage.getItem(LAYOUT_STORAGE_PREFIX + props.collectionId);
113
+ if (stored === "grid" || stored === "list")
114
+ return stored;
115
+ }
116
+ catch (err) { }
117
+ // INFO: a phone has no room for tiles and a menu per tile
118
+ return typeof window !== "undefined" && window.innerWidth < 640
119
+ ? "list"
120
+ : "grid";
121
+ }), layout = _e[0], setLayout = _e[1];
122
+ var _f = (0, react_2.useState)(false), newFolderOpen = _f[0], setNewFolderOpen = _f[1];
123
+ var _g = (0, react_2.useState)(""), folderName = _g[0], setFolderName = _g[1];
124
+ var _h = (0, react_2.useState)(null), renameRow = _h[0], setRenameRow = _h[1];
125
+ var _j = (0, react_2.useState)(""), renameValue = _j[0], setRenameValue = _j[1];
126
+ var _k = (0, react_2.useState)(null), moveRow = _k[0], setMoveRow = _k[1];
127
+ var _l = (0, react_2.useState)(null), deleteRow = _l[0], setDeleteRow = _l[1];
128
+ var _m = (0, react_2.useState)(null), deleteIds = _m[0], setDeleteIds = _m[1];
129
+ var _o = (0, react_2.useState)(null), previewRow = _o[0], setPreviewRow = _o[1];
130
+ var _p = (0, react_2.useState)(false), uploadOpen = _p[0], setUploadOpen = _p[1];
131
+ var _q = (0, react_2.useState)({
132
+ data: [],
133
+ upload: [],
134
+ remove: [],
135
+ }), uploadFiles = _q[0], setUploadFiles = _q[1];
136
+ var _r = (0, react_2.useState)({}), uploadStatus = _r[0], setUploadStatus = _r[1];
137
+ var _s = (0, react_2.useState)(false), working = _s[0], setWorking = _s[1];
138
+ var _t = (0, react_2.useState)(false), dragging = _t[0], setDragging = _t[1];
139
+ var _u = (0, react_2.useState)(""), modalError = _u[0], setModalError = _u[1];
140
+ // INFO: dragenter and dragleave fire for every child the pointer crosses, so a
141
+ // plain boolean flickers off over each tile; a depth count only reaches zero
142
+ // when the drag has really left the drive
143
+ var dragDepthRef = (0, react_2.useRef)(0);
144
+ var settings = props.settings;
145
+ var fileColumn = props.structure.find(function (eachColumn) { return eachColumn.id === settings.fileColumnId; });
146
+ // INFO: the same folder a file column's uploads use everywhere else, so a
147
+ // row deleted from another view removes the same storage folder
148
+ var storageCollection = (_a = fileColumn === null || fileColumn === void 0 ? void 0 : fileColumn.imageCollectionName) !== null && _a !== void 0 ? _a : props.collectionId;
149
+ var sortedRows = (0, driveUtils_1.handleSortDriveRows)(props.rows, settings);
150
+ var path = (0, driveUtils_1.handleBuildFolderPath)(folders, props.folderId);
151
+ (0, react_2.useEffect)(function () {
152
+ handleLoadFolders();
153
+ // eslint-disable-next-line react-hooks/exhaustive-deps
154
+ }, [props.collectionId, JSON.stringify(props.baseQuery)]);
155
+ var handleLoadFolders = function () { return __awaiter(void 0, void 0, void 0, function () {
156
+ var res, err_1;
157
+ var _a;
158
+ return __generator(this, function (_b) {
159
+ switch (_b.label) {
160
+ case 0:
161
+ _b.trys.push([0, 2, , 3]);
162
+ return [4 /*yield*/, props.readQuery.call({
163
+ type: "list",
164
+ query: __spreadArray(__spreadArray([], props.baseQuery, true), [
165
+ { type: "=", queryId: settings.kindColumnId, value: driveUtils_1.DRIVE_FOLDER },
166
+ ], false),
167
+ stopLimit: true,
168
+ })];
169
+ case 1:
170
+ res = _b.sent();
171
+ setFolders((0, driveUtils_1.handleMapDriveFolders)((_a = res === null || res === void 0 ? void 0 : res.data) !== null && _a !== void 0 ? _a : [], settings));
172
+ return [3 /*break*/, 3];
173
+ case 2:
174
+ err_1 = _b.sent();
175
+ return [3 /*break*/, 3];
176
+ case 3: return [2 /*return*/];
177
+ }
178
+ });
179
+ }); };
180
+ var handleChangeLayout = function (next) {
181
+ setLayout(next);
182
+ try {
183
+ window.localStorage.setItem(LAYOUT_STORAGE_PREFIX + props.collectionId, next);
184
+ }
185
+ catch (err) { }
186
+ };
187
+ var handleAfterWrite = function () { return __awaiter(void 0, void 0, void 0, function () {
188
+ return __generator(this, function (_a) {
189
+ switch (_a.label) {
190
+ case 0:
191
+ props.handleRefresh();
192
+ return [4 /*yield*/, handleLoadFolders()];
193
+ case 1:
194
+ _a.sent();
195
+ return [2 /*return*/];
196
+ }
197
+ });
198
+ }); };
199
+ var handleResolveFile = function (row) {
200
+ var _a, _b;
201
+ var value = row === null || row === void 0 ? void 0 : row[settings.fileColumnId];
202
+ var entry = Array.isArray(value) ? value[0] : value;
203
+ if (!(entry === null || entry === void 0 ? void 0 : entry.token) || !(entry === null || entry === void 0 ? void 0 : entry.fileName))
204
+ return null;
205
+ return {
206
+ fileName: (0, blobModule_1.renderImageUrlFromPath)(props.imageEndpoint, storageCollection, (0, driveUtils_1.handleGetRowId)(row), entry.fileName, entry.token, props.bucketName),
207
+ label: String((_a = row === null || row === void 0 ? void 0 : row[settings.nameColumnId]) !== null && _a !== void 0 ? _a : "") || undefined,
208
+ token: entry.token,
209
+ mimeType: (_b = entry.mimeType) !== null && _b !== void 0 ? _b : (0, filePreview_1.handleGuessMimeType)(entry.fileName),
210
+ };
211
+ };
212
+ var handleOpenRow = function (row) {
213
+ var _a;
214
+ if ((0, driveUtils_1.handleIsDriveFolder)(row, settings)) {
215
+ if (props.searching)
216
+ (_a = props.handleClearSearch) === null || _a === void 0 ? void 0 : _a.call(props);
217
+ props.handleChangeFolder((0, driveUtils_1.handleGetRowId)(row));
218
+ }
219
+ else
220
+ setPreviewRow(row);
221
+ };
222
+ var handleCloseModals = function () {
223
+ setNewFolderOpen(false);
224
+ setFolderName("");
225
+ setRenameRow(null);
226
+ setRenameValue("");
227
+ setMoveRow(null);
228
+ setDeleteRow(null);
229
+ setDeleteIds(null);
230
+ setModalError("");
231
+ };
232
+ var handleCreateFolder = function () { return __awaiter(void 0, void 0, void 0, function () {
233
+ var name, err_2;
234
+ var _a;
235
+ return __generator(this, function (_b) {
236
+ switch (_b.label) {
237
+ case 0:
238
+ name = folderName.trim();
239
+ if (!name)
240
+ return [2 /*return*/, setModalError("Name the folder.")];
241
+ if ((0, driveUtils_1.handleIsDuplicateFolderName)(folders, props.folderId, name))
242
+ return [2 /*return*/, setModalError("A folder named \"".concat(name, "\" is already here."))];
243
+ setWorking(true);
244
+ _b.label = 1;
245
+ case 1:
246
+ _b.trys.push([1, 4, , 5]);
247
+ return [4 /*yield*/, props.writeQuery.call("create", {
248
+ data: (_a = {},
249
+ _a[props.serverId] = (0, uuid_1.v4)(),
250
+ _a[settings.nameColumnId] = name,
251
+ _a[settings.kindColumnId] = driveUtils_1.DRIVE_FOLDER,
252
+ _a[settings.parentColumnId] = props.folderId,
253
+ _a),
254
+ })];
255
+ case 2:
256
+ _b.sent();
257
+ handleCloseModals();
258
+ return [4 /*yield*/, handleAfterWrite()];
259
+ case 3:
260
+ _b.sent();
261
+ return [3 /*break*/, 5];
262
+ case 4:
263
+ err_2 = _b.sent();
264
+ setModalError("The folder could not be created.");
265
+ return [3 /*break*/, 5];
266
+ case 5:
267
+ setWorking(false);
268
+ return [2 /*return*/];
269
+ }
270
+ });
271
+ }); };
272
+ var handleOpenRename = function (row) {
273
+ var _a;
274
+ setRenameRow(row);
275
+ setRenameValue(String((_a = row === null || row === void 0 ? void 0 : row[settings.nameColumnId]) !== null && _a !== void 0 ? _a : ""));
276
+ setModalError("");
277
+ };
278
+ var handleRename = function () { return __awaiter(void 0, void 0, void 0, function () {
279
+ var name, rowId, err_3;
280
+ var _a;
281
+ var _b;
282
+ return __generator(this, function (_c) {
283
+ switch (_c.label) {
284
+ case 0:
285
+ name = renameValue.trim();
286
+ if (!name)
287
+ return [2 /*return*/, setModalError("A name is required.")];
288
+ rowId = (0, driveUtils_1.handleGetRowId)(renameRow);
289
+ if ((0, driveUtils_1.handleIsDriveFolder)(renameRow, settings) &&
290
+ (0, driveUtils_1.handleIsDuplicateFolderName)(folders, String((_b = renameRow === null || renameRow === void 0 ? void 0 : renameRow[settings.parentColumnId]) !== null && _b !== void 0 ? _b : ""), name, rowId))
291
+ return [2 /*return*/, setModalError("A folder named \"".concat(name, "\" is already here."))];
292
+ setWorking(true);
293
+ _c.label = 1;
294
+ case 1:
295
+ _c.trys.push([1, 4, , 5]);
296
+ return [4 /*yield*/, props.writeQuery.call("update", {
297
+ id: rowId,
298
+ data: (_a = {}, _a[settings.nameColumnId] = name, _a),
299
+ })];
300
+ case 2:
301
+ _c.sent();
302
+ handleCloseModals();
303
+ return [4 /*yield*/, handleAfterWrite()];
304
+ case 3:
305
+ _c.sent();
306
+ return [3 /*break*/, 5];
307
+ case 4:
308
+ err_3 = _c.sent();
309
+ setModalError("The name could not be saved.");
310
+ return [3 /*break*/, 5];
311
+ case 5:
312
+ setWorking(false);
313
+ return [2 /*return*/];
314
+ }
315
+ });
316
+ }); };
317
+ var handleMove = function (targetFolderId) { return __awaiter(void 0, void 0, void 0, function () {
318
+ var rowId, err_4;
319
+ var _a;
320
+ var _b;
321
+ return __generator(this, function (_c) {
322
+ switch (_c.label) {
323
+ case 0:
324
+ rowId = (0, driveUtils_1.handleGetRowId)(moveRow);
325
+ if ((0, driveUtils_1.handleIsDriveFolder)(moveRow, settings) &&
326
+ (0, driveUtils_1.handleIsDuplicateFolderName)(folders, targetFolderId, String((_b = moveRow === null || moveRow === void 0 ? void 0 : moveRow[settings.nameColumnId]) !== null && _b !== void 0 ? _b : ""), rowId))
327
+ return [2 /*return*/, setModalError("A folder with this name is already there.")];
328
+ setWorking(true);
329
+ _c.label = 1;
330
+ case 1:
331
+ _c.trys.push([1, 4, , 5]);
332
+ return [4 /*yield*/, props.writeQuery.call("update", {
333
+ id: rowId,
334
+ data: (_a = {}, _a[settings.parentColumnId] = targetFolderId, _a),
335
+ })];
336
+ case 2:
337
+ _c.sent();
338
+ handleCloseModals();
339
+ return [4 /*yield*/, handleAfterWrite()];
340
+ case 3:
341
+ _c.sent();
342
+ return [3 /*break*/, 5];
343
+ case 4:
344
+ err_4 = _c.sent();
345
+ setModalError("The item could not be moved.");
346
+ return [3 /*break*/, 5];
347
+ case 5:
348
+ setWorking(false);
349
+ return [2 /*return*/];
350
+ }
351
+ });
352
+ }); };
353
+ /**
354
+ * INFO: a folder's contents are counted before anything is deleted, so the
355
+ * confirmation says what will go. Read from the whole collection, not the
356
+ * filtered list — a file hidden from this view would otherwise be left
357
+ * pointing at a folder that no longer exists.
358
+ */
359
+ var handleOpenDelete = function (row) { return __awaiter(void 0, void 0, void 0, function () {
360
+ var res, rowId, err_5;
361
+ var _a;
362
+ return __generator(this, function (_b) {
363
+ switch (_b.label) {
364
+ case 0:
365
+ setDeleteRow(row);
366
+ setModalError("");
367
+ if (!(0, driveUtils_1.handleIsDriveFolder)(row, settings)) {
368
+ setDeleteIds([(0, driveUtils_1.handleGetRowId)(row)]);
369
+ return [2 /*return*/];
370
+ }
371
+ setDeleteIds(null);
372
+ _b.label = 1;
373
+ case 1:
374
+ _b.trys.push([1, 3, , 4]);
375
+ return [4 /*yield*/, props.readQuery.call({
376
+ type: "list",
377
+ query: [],
378
+ stopLimit: true,
379
+ })];
380
+ case 2:
381
+ res = _b.sent();
382
+ rowId = (0, driveUtils_1.handleGetRowId)(row);
383
+ setDeleteIds(__spreadArray([
384
+ rowId
385
+ ], (0, driveUtils_1.handleCollectDescendantIds)((_a = res === null || res === void 0 ? void 0 : res.data) !== null && _a !== void 0 ? _a : [], settings, rowId), true));
386
+ return [3 /*break*/, 4];
387
+ case 3:
388
+ err_5 = _b.sent();
389
+ setModalError("The folder's contents could not be read.");
390
+ return [3 /*break*/, 4];
391
+ case 4: return [2 /*return*/];
392
+ }
393
+ });
394
+ }); };
395
+ var handleDelete = function () { return __awaiter(void 0, void 0, void 0, function () {
396
+ var form, err_6;
397
+ return __generator(this, function (_a) {
398
+ switch (_a.label) {
399
+ case 0:
400
+ if (!(deleteIds === null || deleteIds === void 0 ? void 0 : deleteIds.length))
401
+ return [2 /*return*/];
402
+ setWorking(true);
403
+ _a.label = 1;
404
+ case 1:
405
+ _a.trys.push([1, 5, , 6]);
406
+ return [4 /*yield*/, props.writeQuery.call("batchDelete", { id: deleteIds })];
407
+ case 2:
408
+ _a.sent();
409
+ form = new FormData();
410
+ form.append("data[assetCollectionName]", storageCollection);
411
+ form.append("data[assetParentId]", JSON.stringify(deleteIds));
412
+ if (props.bucketName)
413
+ form.append("data[bucketName]", props.bucketName);
414
+ return [4 /*yield*/, props.lib
415
+ .axios({
416
+ data: form,
417
+ method: "post",
418
+ url: "".concat(props.uploadEndpoint, "/batchDeleteDirectory"),
419
+ headers: { "Content-Type": "multipart/form-data" },
420
+ })
421
+ .catch(function () { })];
422
+ case 3:
423
+ _a.sent();
424
+ handleCloseModals();
425
+ return [4 /*yield*/, handleAfterWrite()];
426
+ case 4:
427
+ _a.sent();
428
+ return [3 /*break*/, 6];
429
+ case 5:
430
+ err_6 = _a.sent();
431
+ setModalError("The item could not be deleted.");
432
+ return [3 /*break*/, 6];
433
+ case 6:
434
+ setWorking(false);
435
+ return [2 /*return*/];
436
+ }
437
+ });
438
+ }); };
439
+ /**
440
+ * INFO: one row per file, each uploaded into its own row's storage folder
441
+ * first — a row is only created for a file that stored, and one failure does
442
+ * not stop the rest.
443
+ */
444
+ var handleUploadFiles = function (queued) { return __awaiter(void 0, void 0, void 0, function () {
445
+ var failed, _loop_1, _i, queued_1, eachFile;
446
+ var _a;
447
+ return __generator(this, function (_b) {
448
+ switch (_b.label) {
449
+ case 0:
450
+ if (!queued.length)
451
+ return [2 /*return*/];
452
+ setWorking(true);
453
+ setModalError("");
454
+ failed = 0;
455
+ _loop_1 = function (eachFile) {
456
+ var file, rowId, storedName, res, token, err_7;
457
+ var _c, _d, _e;
458
+ return __generator(this, function (_f) {
459
+ switch (_f.label) {
460
+ case 0:
461
+ setUploadStatus(function (current) {
462
+ var _a;
463
+ return (__assign(__assign({}, current), (_a = {}, _a[eachFile.token] = "uploading", _a)));
464
+ });
465
+ _f.label = 1;
466
+ case 1:
467
+ _f.trys.push([1, 4, , 5]);
468
+ file = eachFile.fileName;
469
+ rowId = (0, uuid_1.v4)();
470
+ storedName = "".concat((0, uuid_1.v4)(), "-").concat(file.name);
471
+ return [4 /*yield*/, props.handleUpload(props.uploadEndpoint, rowId, storageCollection, storedName, file, props.bucketName)];
472
+ case 2:
473
+ res = _f.sent();
474
+ token = (_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.data;
475
+ if (!token)
476
+ throw new Error("No token returned");
477
+ return [4 /*yield*/, props.writeQuery.call("create", {
478
+ data: __assign(__assign((_c = {}, _c[props.serverId] = rowId, _c[settings.nameColumnId] = file.name, _c[settings.kindColumnId] = driveUtils_1.DRIVE_FILE, _c[settings.parentColumnId] = props.folderId, _c[settings.fileColumnId] = [
479
+ { token: token, fileName: storedName, mimeType: file.type || undefined },
480
+ ], _c), (settings.sizeColumnId
481
+ ? (_d = {}, _d[settings.sizeColumnId] = file.size, _d) : {})), (settings.mimeTypeColumnId
482
+ ? (_e = {}, _e[settings.mimeTypeColumnId] = file.type, _e) : {})),
483
+ })];
484
+ case 3:
485
+ _f.sent();
486
+ setUploadStatus(function (current) {
487
+ var _a;
488
+ return (__assign(__assign({}, current), (_a = {}, _a[eachFile.token] = "done", _a)));
489
+ });
490
+ return [3 /*break*/, 5];
491
+ case 4:
492
+ err_7 = _f.sent();
493
+ failed += 1;
494
+ setUploadStatus(function (current) {
495
+ var _a;
496
+ return (__assign(__assign({}, current), (_a = {}, _a[eachFile.token] = "failed", _a)));
497
+ });
498
+ return [3 /*break*/, 5];
499
+ case 5: return [2 /*return*/];
500
+ }
501
+ });
502
+ };
503
+ _i = 0, queued_1 = queued;
504
+ _b.label = 1;
505
+ case 1:
506
+ if (!(_i < queued_1.length)) return [3 /*break*/, 4];
507
+ eachFile = queued_1[_i];
508
+ return [5 /*yield**/, _loop_1(eachFile)];
509
+ case 2:
510
+ _b.sent();
511
+ _b.label = 3;
512
+ case 3:
513
+ _i++;
514
+ return [3 /*break*/, 1];
515
+ case 4:
516
+ setWorking(false);
517
+ props.handleRefresh();
518
+ if (failed === 0)
519
+ handleCloseUpload();
520
+ else
521
+ setModalError("".concat(failed, " file(s) could not be uploaded."));
522
+ return [2 /*return*/];
523
+ }
524
+ });
525
+ }); };
526
+ var handleUploadAll = function () {
527
+ var _a;
528
+ return handleUploadFiles(((_a = uploadFiles.upload) !== null && _a !== void 0 ? _a : []).filter(function (eachFile) {
529
+ return uploadStatus[eachFile.token] !== "done" &&
530
+ eachFile.fileName instanceof File;
531
+ }));
532
+ };
533
+ /**
534
+ * INFO: a drop starts uploading at once — dragging files onto a folder is
535
+ * already the decision, so a confirm step would only be a second click. The
536
+ * dialog opens to show each file's progress and closes when all have stored.
537
+ */
538
+ var handleDropFiles = function (files) {
539
+ if (working || !files.length)
540
+ return;
541
+ var queued = files.map(function (eachFile) { return ({
542
+ token: (0, uuid_1.v4)(),
543
+ fileName: eachFile,
544
+ }); });
545
+ setUploadFiles({ data: [], upload: queued, remove: [] });
546
+ setUploadStatus(Object.fromEntries(queued.map(function (eachFile) { return [eachFile.token, "waiting"]; })));
547
+ setModalError("");
548
+ setUploadOpen(true);
549
+ handleUploadFiles(queued);
550
+ };
551
+ var handleOpenUpload = function () {
552
+ setUploadFiles({ data: [], upload: [], remove: [] });
553
+ setUploadStatus({});
554
+ setModalError("");
555
+ setUploadOpen(true);
556
+ };
557
+ var handleCloseUpload = function () {
558
+ setUploadOpen(false);
559
+ setUploadFiles({ data: [], upload: [], remove: [] });
560
+ setUploadStatus({});
561
+ setModalError("");
562
+ };
563
+ // INFO: only a drag carrying files, only for someone who may create, and not
564
+ // while the upload dialog is open — it has its own drop zone
565
+ var handleIsFileDrag = function (event) {
566
+ var _a, _b;
567
+ return props.canCreate &&
568
+ !uploadOpen &&
569
+ Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) !== null && _b !== void 0 ? _b : []).includes("Files");
570
+ };
571
+ var renderDropOverlay = function () {
572
+ if (!dragging)
573
+ return null;
574
+ var target = path.length ? path[path.length - 1].name : "Drive";
575
+ return (react_2.default.createElement("div", { "data-testid": "drive-drop-overlay", className: "pointer-events-none absolute inset-0 z-10 flex flex-col items-center justify-center gap-y-2 rounded-lg border-2 border-dashed border-primary-400 bg-primary-50/90" },
576
+ react_2.default.createElement(HeroIcons.ArrowUpTrayIcon, { className: "h-8 w-8 text-primary-500" }),
577
+ react_2.default.createElement("p", { className: "text-sm font-medium text-primary-700" },
578
+ "Drop to upload to ",
579
+ target)));
580
+ };
581
+ var renderMenu = function (row) { return (react_2.default.createElement(DriveItemMenu, { testId: "drive-menu-".concat((0, driveUtils_1.handleGetRowId)(row)), items: __spreadArray(__spreadArray([
582
+ {
583
+ text: "Details",
584
+ onClick: function () { return props.handleOpenDetails((0, driveUtils_1.handleGetRowId)(row)); },
585
+ }
586
+ ], (props.canUpdate
587
+ ? [
588
+ { text: "Rename", onClick: function () { return handleOpenRename(row); } },
589
+ {
590
+ text: "Move to…",
591
+ onClick: function () {
592
+ setMoveRow(row);
593
+ setModalError("");
594
+ },
595
+ },
596
+ ]
597
+ : []), true), (props.canDelete
598
+ ? [{ text: "Delete", onClick: function () { return handleOpenDelete(row); } }]
599
+ : []), true) })); };
600
+ var renderRowPath = function (row) {
601
+ var _a;
602
+ if (!props.searching)
603
+ return "";
604
+ var parentId = String((_a = row === null || row === void 0 ? void 0 : row[settings.parentColumnId]) !== null && _a !== void 0 ? _a : "");
605
+ var rowPath = (0, driveUtils_1.handleFormatFolderPath)((0, driveUtils_1.handleBuildFolderPath)(folders, parentId));
606
+ return rowPath ? "In ".concat(rowPath) : "At the top level";
607
+ };
608
+ var renderToolbar = function () { return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3 sm:flex-row sm:items-center sm:gap-x-3" },
609
+ react_2.default.createElement("nav", { "aria-label": "Drive path", className: "flex min-w-0 flex-row flex-wrap items-center gap-x-1 text-sm" },
610
+ react_2.default.createElement("button", { type: "button", className: "font-medium ".concat(props.folderId ? "text-primary-600 hover:underline" : "text-gray-900"), onClick: function () { return props.handleChangeFolder(""); } }, "Drive"),
611
+ path.map(function (eachFolder, eachIndex) { return (react_2.default.createElement(react_2.default.Fragment, { key: eachFolder.id },
612
+ react_2.default.createElement(HeroIcons.ChevronRightIcon, { className: "h-4 w-4 shrink-0 text-gray-400" }),
613
+ react_2.default.createElement("button", { type: "button", className: "truncate font-medium ".concat(eachIndex === path.length - 1
614
+ ? "text-gray-900"
615
+ : "text-primary-600 hover:underline"), onClick: function () { return props.handleChangeFolder(eachFolder.id); } }, eachFolder.name))); }),
616
+ props.searching && (react_2.default.createElement("span", { className: "ml-2 text-gray-500" }, "\u00B7 Search results"))),
617
+ react_2.default.createElement("div", { className: "grow" }),
618
+ react_2.default.createElement("div", { className: "flex flex-row flex-wrap items-center gap-2" },
619
+ react_2.default.createElement("div", { className: "flex flex-row overflow-hidden rounded-md border border-gray-200" }, ["grid", "list"].map(function (eachLayout) {
620
+ var Icon = eachLayout === "grid"
621
+ ? HeroIcons.Squares2X2Icon
622
+ : HeroIcons.ListBulletIcon;
623
+ return (react_2.default.createElement("button", { key: eachLayout, type: "button", "aria-label": eachLayout === "grid" ? "Grid view" : "List view", "aria-pressed": layout === eachLayout, className: "p-1.5 ".concat(layout === eachLayout
624
+ ? "bg-primary-50 text-primary-600"
625
+ : "bg-white text-gray-500 hover:bg-gray-50"), onClick: function () { return handleChangeLayout(eachLayout); } },
626
+ react_2.default.createElement(Icon, { className: "h-4 w-4" })));
627
+ })),
628
+ props.canCreate && (react_2.default.createElement(react_2.default.Fragment, null,
629
+ react_2.default.createElement(button_1.Button, { text: "New folder", type: "light", size: "extraSmall", className: "whitespace-nowrap sm:!px-3", icon: react_2.default.createElement(HeroIcons.FolderPlusIcon, { className: "mr-1 h-4 w-4" }), onClick: function () {
630
+ setFolderName("");
631
+ setModalError("");
632
+ setNewFolderOpen(true);
633
+ } }),
634
+ react_2.default.createElement(button_1.Button, { text: "Upload", type: "normal", size: "extraSmall", className: "whitespace-nowrap sm:!px-3", icon: react_2.default.createElement(HeroIcons.ArrowUpTrayIcon, { className: "mr-1 h-4 w-4" }), onClick: handleOpenUpload })))))); };
635
+ var renderFolderIcon = function (sizeClass) { return (react_2.default.createElement(HeroIcons.FolderIcon, { className: "".concat(sizeClass, " shrink-0 text-primary-400") })); };
636
+ // INFO: folders as compact rows above the file tiles, the way a file browser
637
+ // lays them out — a folder has no picture, so a tile-sized card for it is
638
+ // mostly empty space
639
+ var renderGrid = function () {
640
+ var folderRows = sortedRows.filter(function (eachRow) {
641
+ return (0, driveUtils_1.handleIsDriveFolder)(eachRow, settings);
642
+ });
643
+ var fileRows = sortedRows.filter(function (eachRow) { return !(0, driveUtils_1.handleIsDriveFolder)(eachRow, settings); });
644
+ return (react_2.default.createElement("div", { className: "flex flex-col gap-y-4" },
645
+ folderRows.length > 0 && (react_2.default.createElement("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4" }, folderRows.map(function (eachRow) {
646
+ var _a;
647
+ var rowId = (0, driveUtils_1.handleGetRowId)(eachRow);
648
+ return (react_2.default.createElement("div", { key: rowId, "data-testid": "drive-item-".concat(rowId), className: "flex min-w-0 flex-row items-center gap-x-2 rounded-lg border border-gray-200 bg-white pr-1 hover:bg-gray-50" },
649
+ react_2.default.createElement("button", { type: "button", onClick: function () { return handleOpenRow(eachRow); }, className: "flex min-w-0 grow flex-col items-start py-2 pl-3 text-left" },
650
+ react_2.default.createElement("span", { className: "flex w-full min-w-0 flex-row items-center gap-x-2" },
651
+ renderFolderIcon("h-5 w-5"),
652
+ react_2.default.createElement("span", { className: "truncate text-sm font-medium text-gray-900" }, String((_a = eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : ""))),
653
+ props.searching && (react_2.default.createElement("span", { className: "w-full truncate pl-7 text-xs text-gray-500" }, renderRowPath(eachRow)))),
654
+ renderMenu(eachRow)));
655
+ }))),
656
+ fileRows.length > 0 && (react_2.default.createElement("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4" }, fileRows.map(function (eachRow) {
657
+ var _a;
658
+ var rowId = (0, driveUtils_1.handleGetRowId)(eachRow);
659
+ var file = handleResolveFile(eachRow);
660
+ return (react_2.default.createElement("div", { key: rowId, "data-testid": "drive-item-".concat(rowId), className: "relative min-w-0" },
661
+ file ? (react_2.default.createElement(filePreview_1.FilePreview, { variant: "tile", file: file, onClick: function () { return handleOpenRow(eachRow); } })) : (react_2.default.createElement("button", { type: "button", onClick: function () { return handleOpenRow(eachRow); }, className: "flex aspect-video w-full flex-col items-center justify-center gap-y-2 rounded-lg border border-gray-200" },
662
+ react_2.default.createElement(HeroIcons.DocumentIcon, { className: "h-8 w-8 text-gray-400" }),
663
+ react_2.default.createElement("span", { className: "w-full truncate px-2 text-sm text-gray-900" }, String((_a = eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : "")))),
664
+ props.searching && (react_2.default.createElement("p", { className: "mt-1 truncate text-xs text-gray-500" }, renderRowPath(eachRow))),
665
+ react_2.default.createElement("div", { className: "absolute right-1 top-1 rounded-md bg-white/90 shadow-sm" }, renderMenu(eachRow))));
666
+ })))));
667
+ };
668
+ var renderList = function () { return (react_2.default.createElement(newList_1.NewList, { list: sortedRows.map(function (eachRow) {
669
+ var _a;
670
+ var isFolder = (0, driveUtils_1.handleIsDriveFolder)(eachRow, settings);
671
+ var rowPath = renderRowPath(eachRow);
672
+ var size = !isFolder && settings.sizeColumnId
673
+ ? eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.sizeColumnId]
674
+ : undefined;
675
+ var description = [
676
+ rowPath,
677
+ typeof size === "number" ? "".concat(Math.max(1, Math.round(size / 1024)), " KB") : "",
678
+ ]
679
+ .filter(function (eachPart) { return !!eachPart; })
680
+ .join(" · ");
681
+ return __assign(__assign({ id: (0, driveUtils_1.handleGetRowId)(eachRow), title: String((_a = eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : ""), icon: isFolder
682
+ ? renderFolderIcon("h-6 w-6")
683
+ : react_2.default.createElement(HeroIcons.DocumentIcon, { className: "h-6 w-6 text-gray-400" }) }, (description ? { description: description } : {})), { action: renderMenu(eachRow) });
684
+ }), hidePagination: true, onClickItem: function (item) {
685
+ return handleOpenRow(sortedRows.find(function (eachRow) { return (0, driveUtils_1.handleGetRowId)(eachRow) === item.id; }));
686
+ }, darkMode: props.darkMode })); };
687
+ var renderContent = function () {
688
+ if (props.loading)
689
+ return (react_2.default.createElement("div", { className: "flex flex-col items-center py-10" },
690
+ react_2.default.createElement(loading_1.Loading, null)));
691
+ if (!sortedRows.length)
692
+ return (react_2.default.createElement(emptyState_1.EmptyState, { text: props.searching ? "Nothing matches the search" : "This folder is empty", icon: renderFolderIcon("h-10 w-10") }));
693
+ return layout === "grid" ? renderGrid() : renderList();
694
+ };
695
+ var renderNameForm = function (value, onChange, onSubmit, submitText, placeholder) { return (
696
+ // INFO: a form so Enter — and a phone keyboard's Done, which submits rather
697
+ // than sending a keydown — commits; stopPropagation keeps the submit from
698
+ // reaching a form this view sits inside
699
+ react_2.default.createElement("form", { onSubmit: function (event) {
700
+ event.preventDefault();
701
+ event.stopPropagation();
702
+ onSubmit();
703
+ }, className: "flex flex-col gap-y-3" },
704
+ react_2.default.createElement(textInput_1.TextInput, { id: "drive-name", type: "text", label: "", placeholder: placeholder, value: value, autoFocus: true, onChange: function (event) { return onChange(event.target.value); } }),
705
+ modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
706
+ react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
707
+ react_2.default.createElement(button_1.Button, { text: "Cancel", type: "light", size: "small", onClick: handleCloseModals }),
708
+ react_2.default.createElement(button_1.Button, { text: working ? "Saving…" : submitText, type: "normal", size: "small", disable: working, onClick: onSubmit })))); };
709
+ var renderMoveContent = function () {
710
+ var _a;
711
+ if (!moveRow)
712
+ return null;
713
+ var rowId = (0, driveUtils_1.handleGetRowId)(moveRow);
714
+ var currentParent = String((_a = moveRow === null || moveRow === void 0 ? void 0 : moveRow[settings.parentColumnId]) !== null && _a !== void 0 ? _a : "");
715
+ var targets = (0, driveUtils_1.handleGetMoveTargets)(folders, rowId, (0, driveUtils_1.handleIsDriveFolder)(moveRow, settings))
716
+ .map(function (eachFolder) { return ({
717
+ folder: eachFolder,
718
+ label: (0, driveUtils_1.handleFormatFolderPath)((0, driveUtils_1.handleBuildFolderPath)(folders, eachFolder.id)),
719
+ }); })
720
+ .sort(function (a, b) {
721
+ return a.label.localeCompare(b.label, undefined, { numeric: true, sensitivity: "base" });
722
+ });
723
+ var options = __spreadArray([
724
+ { id: "", label: "Drive (top level)" }
725
+ ], targets.map(function (eachTarget) { return ({
726
+ id: eachTarget.folder.id,
727
+ label: eachTarget.label,
728
+ }); }), true).filter(function (eachOption) { return eachOption.id !== currentParent; });
729
+ return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
730
+ modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
731
+ react_2.default.createElement("div", { className: "max-h-80 overflow-y-auto" },
732
+ react_2.default.createElement(newList_1.NewList, { list: options.map(function (eachOption) { return ({
733
+ id: eachOption.id || "__root__",
734
+ title: eachOption.label,
735
+ icon: renderFolderIcon("h-5 w-5"),
736
+ }); }), hidePagination: true, onClickItem: function (item) {
737
+ return !working && handleMove(item.id === "__root__" ? "" : item.id);
738
+ } }))));
739
+ };
740
+ var renderDeleteContent = function () {
741
+ var _a, _b;
742
+ if (!deleteRow)
743
+ return null;
744
+ var isFolder = (0, driveUtils_1.handleIsDriveFolder)(deleteRow, settings);
745
+ var name = String((_a = deleteRow === null || deleteRow === void 0 ? void 0 : deleteRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : "");
746
+ var inside = ((_b = deleteIds === null || deleteIds === void 0 ? void 0 : deleteIds.length) !== null && _b !== void 0 ? _b : 1) - 1;
747
+ return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
748
+ react_2.default.createElement("p", { className: "text-sm text-gray-700" }, !isFolder
749
+ ? "Delete \"".concat(name, "\"? This cannot be undone.")
750
+ : deleteIds === null
751
+ ? "Counting what is inside…"
752
+ : inside > 0
753
+ ? "Delete \"".concat(name, "\" and the ").concat(inside, " item(s) inside it? This cannot be undone.")
754
+ : "Delete the empty folder \"".concat(name, "\"?")),
755
+ modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
756
+ react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
757
+ react_2.default.createElement(button_1.Button, { text: "Cancel", type: "light", size: "small", onClick: handleCloseModals }),
758
+ react_2.default.createElement(button_1.Button, { text: working ? "Deleting…" : "Delete", type: "danger", size: "small", disable: working || deleteIds === null, onClick: handleDelete }))));
759
+ };
760
+ var renderUploadContent = function () {
761
+ var _a;
762
+ var queued = (_a = uploadFiles.upload) !== null && _a !== void 0 ? _a : [];
763
+ return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
764
+ react_2.default.createElement(uploadInput_1.UploadInput, { lib: props.lib, id: "drive-upload", label: "", type: "multi", files: uploadFiles, disabled: working, onChange: function (_a) {
765
+ var value = _a.value, action = _a.action;
766
+ if (action === "upload")
767
+ setUploadFiles(function (current) {
768
+ var _a;
769
+ return (__assign(__assign({}, current), { upload: __spreadArray(__spreadArray([], ((_a = current.upload) !== null && _a !== void 0 ? _a : []), true), value, true) }));
770
+ });
771
+ if (action === "remove")
772
+ setUploadFiles(function (current) {
773
+ var _a;
774
+ return (__assign(__assign({}, current), { upload: ((_a = current.upload) !== null && _a !== void 0 ? _a : []).filter(function (eachFile) { return eachFile.token !== value.token; }) }));
775
+ });
776
+ } }),
777
+ queued.length > 0 && Object.keys(uploadStatus).length > 0 && (react_2.default.createElement("ul", { className: "flex flex-col gap-y-1 text-sm" }, queued.map(function (eachFile) {
778
+ var _a, _b;
779
+ return (react_2.default.createElement("li", { key: eachFile.token, className: "flex flex-row gap-x-2" },
780
+ react_2.default.createElement("span", { className: "truncate text-gray-700" }, (_b = (_a = eachFile.fileName) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : ""),
781
+ react_2.default.createElement("span", { className: "grow" }),
782
+ react_2.default.createElement("span", { className: uploadStatus[eachFile.token] === "failed"
783
+ ? "text-red-600"
784
+ : "text-gray-500" }, uploadStatus[eachFile.token] === "done"
785
+ ? "Uploaded"
786
+ : uploadStatus[eachFile.token] === "uploading"
787
+ ? "Uploading…"
788
+ : uploadStatus[eachFile.token] === "failed"
789
+ ? "Failed"
790
+ : "Waiting")));
791
+ }))),
792
+ modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
793
+ react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
794
+ react_2.default.createElement(button_1.Button, { text: "Close", type: "light", size: "small", onClick: handleCloseUpload }),
795
+ react_2.default.createElement(button_1.Button, { text: working ? "Uploading…" : "Upload ".concat(queued.length || "").trim(), type: "normal", size: "small", disable: working || queued.length === 0, onClick: handleUploadAll }))));
796
+ };
797
+ var renderPreviewContent = function () {
798
+ var _a, _b;
799
+ var file = previewRow ? handleResolveFile(previewRow) : null;
800
+ if (!file)
801
+ return null;
802
+ var kind = (0, filePreview_1.handleResolveFileKind)(file);
803
+ return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
804
+ kind === "image" && (
805
+ // eslint-disable-next-line jsx-a11y/img-redundant-alt
806
+ react_2.default.createElement("img", { src: file.fileName, alt: (_a = file.label) !== null && _a !== void 0 ? _a : "", className: "max-h-[70vh] w-full object-contain" })),
807
+ kind === "pdf" && (react_2.default.createElement("iframe", { title: (_b = file.label) !== null && _b !== void 0 ? _b : "Preview", src: file.fileName, className: "h-[70vh] w-full" })),
808
+ kind === "video" && (react_2.default.createElement("video", { src: file.fileName, controls: true, className: "max-h-[70vh] w-full" })),
809
+ kind !== "image" && kind !== "pdf" && kind !== "video" && (react_2.default.createElement("p", { className: "text-sm text-gray-600" }, "This file has no preview.")),
810
+ react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
811
+ react_2.default.createElement(button_1.Button, { text: "Details", type: "light", size: "small", onClick: function () {
812
+ var rowId = (0, driveUtils_1.handleGetRowId)(previewRow);
813
+ setPreviewRow(null);
814
+ props.handleOpenDetails(rowId);
815
+ } }),
816
+ react_2.default.createElement("a", { href: file.fileName, target: "_blank", rel: "noopener noreferrer", className: "rounded-md bg-primary-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-primary-700" }, "Download"))));
817
+ };
818
+ return (react_2.default.createElement("div", {
819
+ // INFO: a minimum height so an empty or near-empty folder is still a
820
+ // drop target worth aiming at
821
+ className: "relative mt-4 flex min-h-[240px] flex-col gap-y-4 rounded-lg p-4 ".concat(props.darkMode ? "bg-white/5" : "bg-white"), "data-testid": "drive-view", onDragEnter: function (event) {
822
+ if (!handleIsFileDrag(event))
823
+ return;
824
+ event.preventDefault();
825
+ dragDepthRef.current += 1;
826
+ setDragging(true);
827
+ }, onDragOver: function (event) {
828
+ if (handleIsFileDrag(event))
829
+ event.preventDefault();
830
+ }, onDragLeave: function (event) {
831
+ if (!handleIsFileDrag(event))
832
+ return;
833
+ dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
834
+ if (dragDepthRef.current === 0)
835
+ setDragging(false);
836
+ }, onDrop: function (event) {
837
+ var _a, _b;
838
+ dragDepthRef.current = 0;
839
+ setDragging(false);
840
+ if (!handleIsFileDrag(event) || !((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b.length))
841
+ return;
842
+ event.preventDefault();
843
+ handleDropFiles(Array.from(event.dataTransfer.files));
844
+ } },
845
+ renderToolbar(),
846
+ renderContent(),
847
+ renderDropOverlay(),
848
+ react_2.default.createElement(modal_1.Modal, { open: newFolderOpen, title: "New folder", onClose: handleCloseModals, renderContent: function () {
849
+ return renderNameForm(folderName, setFolderName, handleCreateFolder, "Create", "Folder name");
850
+ } }),
851
+ react_2.default.createElement(modal_1.Modal, { open: !!renameRow, title: "Rename", onClose: handleCloseModals, renderContent: function () {
852
+ return renderNameForm(renameValue, setRenameValue, handleRename, "Save", "Name");
853
+ } }),
854
+ react_2.default.createElement(modal_1.Modal, { open: !!moveRow, title: "Move \"".concat(String((_b = moveRow === null || moveRow === void 0 ? void 0 : moveRow[settings.nameColumnId]) !== null && _b !== void 0 ? _b : ""), "\" to"), onClose: handleCloseModals, renderContent: renderMoveContent }),
855
+ react_2.default.createElement(modal_1.Modal, { open: !!deleteRow, title: "Delete", onClose: handleCloseModals, renderContent: renderDeleteContent }),
856
+ react_2.default.createElement(modal_1.Modal, { open: uploadOpen, title: "Upload files", maxWidth: "2xl", onClose: handleCloseUpload, renderContent: renderUploadContent }),
857
+ react_2.default.createElement(modal_1.Modal, { open: !!previewRow, title: String((_c = previewRow === null || previewRow === void 0 ? void 0 : previewRow[settings.nameColumnId]) !== null && _c !== void 0 ? _c : ""), maxWidth: "4xl", onClose: function () { return setPreviewRow(null); }, renderContent: renderPreviewContent })));
858
+ };
859
+ exports.DriveView = DriveView;
860
+ /**
861
+ * The per-item action menu.
862
+ *
863
+ * INFO: portalled — the list layout sits in NewList's rounded card, which clips
864
+ * overflow, so an in-place panel was cut off at the row's edge. Button's own
865
+ * popUpMenuItems has no portal and a full-size trigger, hence a small one here.
866
+ */
867
+ var DriveItemMenu = function (props) {
868
+ var popUpRef = (0, react_2.useRef)(null);
869
+ return (react_2.default.createElement("div", { "data-testid": props.testId, onClick: function (event) { return event.stopPropagation(); } },
870
+ react_2.default.createElement(popUp_1.PopUp, { ref: popUpRef, portal: true, anchor: "right", direction: "bottom", lib: { Transition: react_1.Transition }, ctaComp: react_2.default.createElement("button", { type: "button", "aria-label": "Actions", className: "rounded-md p-1.5 text-gray-500 hover:bg-gray-100 hover:text-gray-700" },
871
+ react_2.default.createElement(HeroIcons.EllipsisVerticalIcon, { className: "h-4 w-4" })), renderComp: react_2.default.createElement("div", { className: "flex min-w-[140px] flex-col divide-y overflow-hidden rounded-md bg-white shadow-md" }, props.items.map(function (eachItem) { return (react_2.default.createElement("button", { key: eachItem.text, type: "button", className: "px-4 py-2 text-left text-sm hover:bg-gray-100 ".concat(eachItem.text === "Delete" ? "text-red-600" : "text-gray-900"), onClick: function () {
872
+ var _a;
873
+ (_a = popUpRef.current) === null || _a === void 0 ? void 0 : _a.handleOnClose();
874
+ eachItem.onClick();
875
+ } }, eachItem.text)); })) })));
876
+ };
877
+ //# sourceMappingURL=driveView.js.map