@noya-app/noya-file-explorer 0.0.2

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.
package/dist/index.mjs ADDED
@@ -0,0 +1,1857 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // ../../node_modules/tree-visit/lib/access.js
28
+ var require_access = __commonJS({
29
+ "../../node_modules/tree-visit/lib/access.js"(exports) {
30
+ "use strict";
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.accessPath = exports.access = void 0;
33
+ function access(node, indexPath, options) {
34
+ if (options.includeTraversalContext) {
35
+ const accessed = accessPath(node, indexPath, options);
36
+ return accessed[accessed.length - 1];
37
+ }
38
+ let path4 = indexPath.slice();
39
+ while (path4.length > 0) {
40
+ let index = path4.shift();
41
+ node = options.getChildren(node, path4)[index];
42
+ }
43
+ return node;
44
+ }
45
+ exports.access = access;
46
+ function accessPath(node, indexPath, options) {
47
+ let path4 = indexPath.slice();
48
+ let result = [node];
49
+ while (path4.length > 0) {
50
+ let index = path4.shift();
51
+ const context = options.includeTraversalContext ? {
52
+ getRoot: () => result[0],
53
+ getParent: () => result[result.length - 2],
54
+ getAncestors: () => result.slice(0, -1)
55
+ } : void 0;
56
+ node = options.getChildren(node, path4, context)[index];
57
+ result.push(node);
58
+ }
59
+ return result;
60
+ }
61
+ exports.accessPath = accessPath;
62
+ }
63
+ });
64
+
65
+ // ../../node_modules/tree-visit/lib/sort.js
66
+ var require_sort = __commonJS({
67
+ "../../node_modules/tree-visit/lib/sort.js"(exports) {
68
+ "use strict";
69
+ Object.defineProperty(exports, "__esModule", { value: true });
70
+ exports.sortPaths = exports.comparePathsByComponent = void 0;
71
+ function comparePathsByComponent(a, b) {
72
+ for (let i = 0; i < Math.min(a.length, b.length); i++) {
73
+ if (a[i] < b[i])
74
+ return -1;
75
+ if (a[i] > b[i])
76
+ return 1;
77
+ }
78
+ return a.length - b.length;
79
+ }
80
+ exports.comparePathsByComponent = comparePathsByComponent;
81
+ function sortPaths(indexPaths) {
82
+ return [...indexPaths].sort(comparePathsByComponent);
83
+ }
84
+ exports.sortPaths = sortPaths;
85
+ }
86
+ });
87
+
88
+ // ../../node_modules/tree-visit/lib/ancestors.js
89
+ var require_ancestors = __commonJS({
90
+ "../../node_modules/tree-visit/lib/ancestors.js"(exports) {
91
+ "use strict";
92
+ Object.defineProperty(exports, "__esModule", { value: true });
93
+ exports.ancestorPaths = void 0;
94
+ var sort_1 = require_sort();
95
+ function ancestorPaths2(paths, options) {
96
+ var _a;
97
+ const result = /* @__PURE__ */ new Map();
98
+ const compare = (_a = options === null || options === void 0 ? void 0 : options.compare) !== null && _a !== void 0 ? _a : sort_1.comparePathsByComponent;
99
+ const sortedIndexPaths = paths.sort(compare);
100
+ for (const indexPath of sortedIndexPaths) {
101
+ const foundParent = indexPath.some((_, index) => {
102
+ const parentKey = indexPath.slice(0, index).join();
103
+ return result.has(parentKey);
104
+ });
105
+ if (foundParent)
106
+ continue;
107
+ result.set(indexPath.join(), indexPath);
108
+ }
109
+ return Array.from(result.values());
110
+ }
111
+ exports.ancestorPaths = ancestorPaths2;
112
+ }
113
+ });
114
+
115
+ // ../../node_modules/tree-visit/lib/diagram/boxDiagram.js
116
+ var require_boxDiagram = __commonJS({
117
+ "../../node_modules/tree-visit/lib/diagram/boxDiagram.js"(exports) {
118
+ "use strict";
119
+ Object.defineProperty(exports, "__esModule", { value: true });
120
+ exports.boxDiagram = void 0;
121
+ var BoxDrawing;
122
+ (function(BoxDrawing2) {
123
+ BoxDrawing2["TopLeft"] = "\u250C";
124
+ BoxDrawing2["TopRight"] = "\u2510";
125
+ BoxDrawing2["BottomLeft"] = "\u2514";
126
+ BoxDrawing2["BottomRight"] = "\u2518";
127
+ BoxDrawing2["Horizontal"] = "\u2500";
128
+ BoxDrawing2["Vertical"] = "\u2502";
129
+ BoxDrawing2["BottomConnectorDown"] = "\u252C";
130
+ BoxDrawing2["BottomConnectorUp"] = "\u2534";
131
+ BoxDrawing2["TopConnectorUp"] = "\u2534";
132
+ })(BoxDrawing || (BoxDrawing = {}));
133
+ function wrapLabelInBox(label) {
134
+ const lines = label.split("\n");
135
+ const length = Math.max(...lines.map((line) => line.length));
136
+ const horizontalMargin = 1;
137
+ const width = length + horizontalMargin * 2 + 2;
138
+ const height = 2 + lines.length;
139
+ const diagram = [
140
+ [
141
+ BoxDrawing.TopLeft,
142
+ BoxDrawing.Horizontal.repeat(length + horizontalMargin * 2),
143
+ BoxDrawing.TopRight
144
+ ],
145
+ ...lines.map((line) => [
146
+ BoxDrawing.Vertical,
147
+ " ".repeat(horizontalMargin),
148
+ line + (line.length < length ? " ".repeat(length - line.length) : ""),
149
+ " ".repeat(horizontalMargin),
150
+ BoxDrawing.Vertical
151
+ ]),
152
+ [
153
+ BoxDrawing.BottomLeft,
154
+ BoxDrawing.Horizontal.repeat(length + horizontalMargin * 2),
155
+ BoxDrawing.BottomRight
156
+ ]
157
+ ];
158
+ return {
159
+ width,
160
+ height,
161
+ contents: diagram.map((parts) => parts.join(""))
162
+ };
163
+ }
164
+ function mergeBoxesHorizontal(boxes) {
165
+ const horizontalMargin = 1;
166
+ if (boxes.length === 0) {
167
+ throw new Error("Can't merge empty array of boxes");
168
+ }
169
+ return boxes.slice(1).reduce((result, box) => {
170
+ const height = Math.max(result.height, box.height);
171
+ const width = result.width + horizontalMargin + box.width;
172
+ const contents = [];
173
+ for (let i = 0; i < height; i++) {
174
+ contents.push((result.contents[i] || " ".repeat(result.width)) + " ".repeat(horizontalMargin) + (box.contents[i] || " ".repeat(box.width)));
175
+ }
176
+ return { height, width, contents: centerBlock(contents, width) };
177
+ }, boxes[0]);
178
+ }
179
+ function mergeBoxesVertical(boxes) {
180
+ const verticalMargin = 1;
181
+ if (boxes.length === 0) {
182
+ throw new Error("Can't merge empty array of boxes");
183
+ }
184
+ const width = Math.max(...boxes.map((box) => box.width));
185
+ return boxes.slice(1).reduce((result, box) => {
186
+ const height = result.height + verticalMargin + box.height;
187
+ const contents = [];
188
+ for (let i = 0; i < height; i++) {
189
+ if (i < result.height) {
190
+ contents.push(result.contents[i]);
191
+ } else if (i === result.height) {
192
+ contents.push(" ".repeat(width));
193
+ } else {
194
+ contents.push(box.contents[i - result.height - 1]);
195
+ }
196
+ }
197
+ return { height, width, contents: centerBlock(contents, width) };
198
+ }, boxes[0]);
199
+ }
200
+ function nodeDiagram(node, indexPath, options) {
201
+ const label = options.getLabel(node, indexPath);
202
+ const box = wrapLabelInBox(label);
203
+ const children = options.getChildren(node, indexPath);
204
+ if (children.length === 0)
205
+ return box;
206
+ const childBoxes = children.map((child, index) => {
207
+ const childBox = nodeDiagram(child, [...indexPath, index], options);
208
+ childBox.contents[0] = insertSubstring(childBox.contents[0], centerIndex(childBox.contents[0].length), BoxDrawing.TopConnectorUp);
209
+ return childBox;
210
+ });
211
+ const result = mergeBoxesVertical([box, mergeBoxesHorizontal(childBoxes)]);
212
+ const contents = result.contents;
213
+ const mid = centerIndex(result.width);
214
+ contents[box.height - 1] = insertSubstring(contents[box.height - 1], mid, BoxDrawing.BottomConnectorDown);
215
+ let min = contents[box.height + 1].indexOf(BoxDrawing.TopConnectorUp);
216
+ let max = contents[box.height + 1].lastIndexOf(BoxDrawing.TopConnectorUp);
217
+ for (let i = min; i <= max; i++) {
218
+ let character;
219
+ if (i === mid) {
220
+ character = childBoxes.length > 1 ? BoxDrawing.BottomConnectorUp : BoxDrawing.Vertical;
221
+ } else if (i === min) {
222
+ character = BoxDrawing.TopLeft;
223
+ } else if (i === max) {
224
+ character = BoxDrawing.TopRight;
225
+ } else {
226
+ character = BoxDrawing.Horizontal;
227
+ }
228
+ result.contents[box.height] = insertSubstring(result.contents[box.height], i, character);
229
+ }
230
+ return result;
231
+ }
232
+ function boxDiagram(node, options) {
233
+ return nodeDiagram(node, [], options).contents.join("\n");
234
+ }
235
+ exports.boxDiagram = boxDiagram;
236
+ function centerIndex(width) {
237
+ return Math.floor(width / 2);
238
+ }
239
+ function centerLine(line, width) {
240
+ const remainder = width - line.length;
241
+ if (remainder <= 0)
242
+ return line;
243
+ const prefixLength = centerIndex(remainder);
244
+ const suffixLength = centerIndex(remainder);
245
+ const result = " ".repeat(prefixLength) + line + " ".repeat(suffixLength);
246
+ return prefixLength + suffixLength + result.length < width ? result + " " : result;
247
+ }
248
+ function centerBlock(lines, width) {
249
+ return lines.map((line) => centerLine(line, width));
250
+ }
251
+ function insertSubstring(string, index, substring) {
252
+ if (index > string.length - 1)
253
+ return string;
254
+ return string.substring(0, index) + substring + string.substring(index + 1);
255
+ }
256
+ }
257
+ });
258
+
259
+ // ../../node_modules/tree-visit/lib/diagram/directoryDiagram.js
260
+ var require_directoryDiagram = __commonJS({
261
+ "../../node_modules/tree-visit/lib/diagram/directoryDiagram.js"(exports) {
262
+ "use strict";
263
+ Object.defineProperty(exports, "__esModule", { value: true });
264
+ exports.prefixBlock = exports.isMultiline = exports.directoryDiagram = void 0;
265
+ var LinePrefix;
266
+ (function(LinePrefix2) {
267
+ LinePrefix2["Child"] = "\u251C\u2500\u2500 ";
268
+ LinePrefix2["LastChild"] = "\u2514\u2500\u2500 ";
269
+ LinePrefix2["NestedChild"] = "\u2502 ";
270
+ LinePrefix2["LastNestedChild"] = " ";
271
+ })(LinePrefix || (LinePrefix = {}));
272
+ function nodeDiagram(node, indexPath, options) {
273
+ const label = options.getLabel(node, indexPath);
274
+ const depth = indexPath.length;
275
+ let rootLine = { label, depth, prefix: "", multilinePrefix: "" };
276
+ const children = options.getChildren(node, indexPath);
277
+ if (children.length === 0)
278
+ return [rootLine];
279
+ if (options.flattenSingleChildNodes && children.length === 1 && !isMultiline(label)) {
280
+ const [line] = nodeDiagram(children[0], [...indexPath, 0], options);
281
+ const hideRoot = indexPath.length === 0 && label === "";
282
+ rootLine.label = hideRoot ? `/ ${line.label}` : `${rootLine.label} / ${line.label}`;
283
+ return [rootLine];
284
+ }
285
+ const nestedLines = children.flatMap((file, index, array) => {
286
+ const childIsLast = index === array.length - 1;
287
+ const childLines = nodeDiagram(file, [...indexPath, index], options);
288
+ const childPrefix = childIsLast ? LinePrefix.LastChild : LinePrefix.Child;
289
+ const childMultilinePrefix = childIsLast ? LinePrefix.LastNestedChild : LinePrefix.NestedChild;
290
+ childLines.forEach((line) => {
291
+ if (line.depth === depth + 1) {
292
+ line.prefix = childPrefix + line.prefix;
293
+ line.multilinePrefix = childMultilinePrefix + line.multilinePrefix;
294
+ } else if (childIsLast) {
295
+ line.prefix = LinePrefix.LastNestedChild + line.prefix;
296
+ line.multilinePrefix = LinePrefix.LastNestedChild + line.multilinePrefix;
297
+ } else {
298
+ line.prefix = LinePrefix.NestedChild + line.prefix;
299
+ line.multilinePrefix = LinePrefix.NestedChild + line.multilinePrefix;
300
+ }
301
+ });
302
+ return childLines;
303
+ });
304
+ return [rootLine, ...nestedLines];
305
+ }
306
+ function directoryDiagram(node, options) {
307
+ const lines = nodeDiagram(node, [], options);
308
+ const strings = lines.map((line) => prefixBlock(line.label, line.prefix, line.multilinePrefix));
309
+ return strings.join("\n");
310
+ }
311
+ exports.directoryDiagram = directoryDiagram;
312
+ function isMultiline(line) {
313
+ return line.includes("\n");
314
+ }
315
+ exports.isMultiline = isMultiline;
316
+ function prefixBlock(block, prefix, multilinePrefix) {
317
+ if (!isMultiline(block))
318
+ return prefix + block;
319
+ return block.split("\n").map((line, index) => (index === 0 ? prefix : multilinePrefix) + line).join("\n");
320
+ }
321
+ exports.prefixBlock = prefixBlock;
322
+ }
323
+ });
324
+
325
+ // ../../node_modules/tree-visit/lib/diagram.js
326
+ var require_diagram = __commonJS({
327
+ "../../node_modules/tree-visit/lib/diagram.js"(exports) {
328
+ "use strict";
329
+ Object.defineProperty(exports, "__esModule", { value: true });
330
+ exports.diagram = void 0;
331
+ var boxDiagram_1 = require_boxDiagram();
332
+ var directoryDiagram_1 = require_directoryDiagram();
333
+ function diagram(node, options) {
334
+ if (options.type === "box") {
335
+ return (0, boxDiagram_1.boxDiagram)(node, options);
336
+ }
337
+ return (0, directoryDiagram_1.directoryDiagram)(node, options);
338
+ }
339
+ exports.diagram = diagram;
340
+ }
341
+ });
342
+
343
+ // ../../node_modules/tree-visit/lib/visit.js
344
+ var require_visit = __commonJS({
345
+ "../../node_modules/tree-visit/lib/visit.js"(exports) {
346
+ "use strict";
347
+ Object.defineProperty(exports, "__esModule", { value: true });
348
+ exports.visit = exports.STOP = exports.SKIP = void 0;
349
+ exports.SKIP = "skip";
350
+ exports.STOP = "stop";
351
+ function visit(node, options) {
352
+ const { onEnter, onLeave, getChildren, onDetectCycle, getIdentifier } = options;
353
+ let indexPath = [];
354
+ let stack = [{ node }];
355
+ const visited = onDetectCycle ? /* @__PURE__ */ new Set() : void 0;
356
+ const context = options.includeTraversalContext ? {
357
+ getRoot() {
358
+ return node;
359
+ },
360
+ getParent() {
361
+ var _a;
362
+ return (_a = stack[stack.length - 2]) === null || _a === void 0 ? void 0 : _a.node;
363
+ },
364
+ getAncestors() {
365
+ return stack.slice(0, -1).map((wrapper) => wrapper.node);
366
+ }
367
+ } : void 0;
368
+ const getIndexPath = options.reuseIndexPath ? () => indexPath : () => indexPath.slice();
369
+ while (stack.length > 0) {
370
+ let wrapper = stack[stack.length - 1];
371
+ if (wrapper.state === void 0) {
372
+ if (visited) {
373
+ const id = getIdentifier ? getIdentifier(wrapper.node) : wrapper.node;
374
+ if (visited.has(id)) {
375
+ const action = typeof onDetectCycle === "function" ? onDetectCycle(wrapper.node, getIndexPath(), context) : onDetectCycle;
376
+ if (action === "error") {
377
+ throw new Error("Cycle detected in tree");
378
+ } else {
379
+ wrapper.state = -1;
380
+ continue;
381
+ }
382
+ }
383
+ visited.add(id);
384
+ }
385
+ const enterResult = onEnter === null || onEnter === void 0 ? void 0 : onEnter(wrapper.node, getIndexPath());
386
+ if (enterResult === exports.STOP)
387
+ return;
388
+ wrapper.state = enterResult === exports.SKIP ? -1 : 0;
389
+ }
390
+ const children = wrapper.children || getChildren(wrapper.node, getIndexPath(), context);
391
+ if (!wrapper.children) {
392
+ wrapper.children = children;
393
+ }
394
+ if (wrapper.state !== -1) {
395
+ if (wrapper.state < children.length) {
396
+ let currentIndex = wrapper.state;
397
+ indexPath.push(currentIndex);
398
+ stack.push({ node: children[currentIndex] });
399
+ wrapper.state = currentIndex + 1;
400
+ continue;
401
+ }
402
+ const leaveResult = onLeave === null || onLeave === void 0 ? void 0 : onLeave(wrapper.node, getIndexPath());
403
+ if (leaveResult === exports.STOP)
404
+ return;
405
+ }
406
+ if (visited) {
407
+ const id = getIdentifier ? getIdentifier(wrapper.node) : wrapper.node;
408
+ visited.delete(id);
409
+ }
410
+ indexPath.pop();
411
+ stack.pop();
412
+ }
413
+ }
414
+ exports.visit = visit;
415
+ }
416
+ });
417
+
418
+ // ../../node_modules/tree-visit/lib/find.js
419
+ var require_find = __commonJS({
420
+ "../../node_modules/tree-visit/lib/find.js"(exports) {
421
+ "use strict";
422
+ Object.defineProperty(exports, "__esModule", { value: true });
423
+ exports.findAllIndexPaths = exports.findIndexPath = exports.findAll = exports.find = void 0;
424
+ var visit_1 = require_visit();
425
+ function find(node, options) {
426
+ let found;
427
+ (0, visit_1.visit)(node, Object.assign(Object.assign({}, options), { onEnter: (child, indexPath) => {
428
+ if (options.predicate(child, indexPath)) {
429
+ found = child;
430
+ return visit_1.STOP;
431
+ }
432
+ } }));
433
+ return found;
434
+ }
435
+ exports.find = find;
436
+ function findAll(node, options) {
437
+ let found = [];
438
+ (0, visit_1.visit)(node, {
439
+ onEnter: (child, indexPath) => {
440
+ if (options.predicate(child, indexPath)) {
441
+ found.push(child);
442
+ }
443
+ },
444
+ getChildren: options.getChildren
445
+ });
446
+ return found;
447
+ }
448
+ exports.findAll = findAll;
449
+ function findIndexPath(node, options) {
450
+ let found;
451
+ (0, visit_1.visit)(node, {
452
+ onEnter: (child, indexPath) => {
453
+ if (options.predicate(child, indexPath)) {
454
+ found = [...indexPath];
455
+ return visit_1.STOP;
456
+ }
457
+ },
458
+ getChildren: options.getChildren
459
+ });
460
+ return found;
461
+ }
462
+ exports.findIndexPath = findIndexPath;
463
+ function findAllIndexPaths(node, options) {
464
+ let found = [];
465
+ (0, visit_1.visit)(node, {
466
+ onEnter: (child, indexPath) => {
467
+ if (options.predicate(child, indexPath)) {
468
+ found.push([...indexPath]);
469
+ }
470
+ },
471
+ getChildren: options.getChildren
472
+ });
473
+ return found;
474
+ }
475
+ exports.findAllIndexPaths = findAllIndexPaths;
476
+ }
477
+ });
478
+
479
+ // ../../node_modules/tree-visit/lib/reduce.js
480
+ var require_reduce = __commonJS({
481
+ "../../node_modules/tree-visit/lib/reduce.js"(exports) {
482
+ "use strict";
483
+ Object.defineProperty(exports, "__esModule", { value: true });
484
+ exports.reduce = void 0;
485
+ var visit_1 = require_visit();
486
+ function reduce(node, options) {
487
+ let result = options.initialResult;
488
+ (0, visit_1.visit)(node, Object.assign(Object.assign({}, options), { onEnter: (child, indexPath) => {
489
+ result = options.nextResult(result, child, indexPath);
490
+ } }));
491
+ return result;
492
+ }
493
+ exports.reduce = reduce;
494
+ }
495
+ });
496
+
497
+ // ../../node_modules/tree-visit/lib/flat.js
498
+ var require_flat = __commonJS({
499
+ "../../node_modules/tree-visit/lib/flat.js"(exports) {
500
+ "use strict";
501
+ Object.defineProperty(exports, "__esModule", { value: true });
502
+ exports.flat = void 0;
503
+ var reduce_1 = require_reduce();
504
+ function flat(node, options) {
505
+ return (0, reduce_1.reduce)(node, Object.assign(Object.assign({}, options), { initialResult: [], nextResult: (result, child) => {
506
+ result.push(child);
507
+ return result;
508
+ } }));
509
+ }
510
+ exports.flat = flat;
511
+ }
512
+ });
513
+
514
+ // ../../node_modules/tree-visit/lib/flatMap.js
515
+ var require_flatMap = __commonJS({
516
+ "../../node_modules/tree-visit/lib/flatMap.js"(exports) {
517
+ "use strict";
518
+ Object.defineProperty(exports, "__esModule", { value: true });
519
+ exports.flatMap = void 0;
520
+ var reduce_1 = require_reduce();
521
+ function flatMap(node, options) {
522
+ return (0, reduce_1.reduce)(node, Object.assign(Object.assign({}, options), { initialResult: [], nextResult: (result, child, indexPath) => {
523
+ result.push(...options.transform(child, indexPath));
524
+ return result;
525
+ } }));
526
+ }
527
+ exports.flatMap = flatMap;
528
+ }
529
+ });
530
+
531
+ // ../../node_modules/tree-visit/lib/map.js
532
+ var require_map = __commonJS({
533
+ "../../node_modules/tree-visit/lib/map.js"(exports) {
534
+ "use strict";
535
+ Object.defineProperty(exports, "__esModule", { value: true });
536
+ exports.map = void 0;
537
+ var visit_1 = require_visit();
538
+ function map(node, options) {
539
+ const childrenMap = {};
540
+ (0, visit_1.visit)(node, Object.assign(Object.assign({}, options), { onLeave: (child, indexPath) => {
541
+ var _a, _b;
542
+ const keyIndexPath = [0, ...indexPath];
543
+ const key = keyIndexPath.join();
544
+ const transformed = options.transform(child, (_a = childrenMap[key]) !== null && _a !== void 0 ? _a : [], indexPath);
545
+ const parentKey = keyIndexPath.slice(0, -1).join();
546
+ const parentChildren = (_b = childrenMap[parentKey]) !== null && _b !== void 0 ? _b : [];
547
+ parentChildren.push(transformed);
548
+ childrenMap[parentKey] = parentChildren;
549
+ } }));
550
+ return childrenMap[""][0];
551
+ }
552
+ exports.map = map;
553
+ }
554
+ });
555
+
556
+ // ../../node_modules/tree-visit/lib/operation.js
557
+ var require_operation = __commonJS({
558
+ "../../node_modules/tree-visit/lib/operation.js"(exports) {
559
+ "use strict";
560
+ Object.defineProperty(exports, "__esModule", { value: true });
561
+ exports.splice = exports.applyOperations = exports.getReplaceOperations = exports.getRemovalOperations = exports.getInsertionOperations = exports.replaceOperation = exports.removeOperation = exports.insertOperation = void 0;
562
+ var ancestors_1 = require_ancestors();
563
+ var map_1 = require_map();
564
+ function insertOperation(index, nodes) {
565
+ return {
566
+ type: "insert",
567
+ index,
568
+ nodes
569
+ };
570
+ }
571
+ exports.insertOperation = insertOperation;
572
+ function removeOperation(indexes) {
573
+ return {
574
+ type: "remove",
575
+ indexes
576
+ };
577
+ }
578
+ exports.removeOperation = removeOperation;
579
+ function replaceOperation() {
580
+ return {
581
+ type: "replace"
582
+ };
583
+ }
584
+ exports.replaceOperation = replaceOperation;
585
+ function splitIndexPath(indexPath) {
586
+ return [indexPath.slice(0, -1), indexPath[indexPath.length - 1]];
587
+ }
588
+ function getInsertionOperations(indexPath, nodes, operations = /* @__PURE__ */ new Map()) {
589
+ var _a;
590
+ const [parentIndexPath, index] = splitIndexPath(indexPath);
591
+ for (let i = parentIndexPath.length - 1; i >= 0; i--) {
592
+ const parentKey = parentIndexPath.slice(0, i).join();
593
+ switch ((_a = operations.get(parentKey)) === null || _a === void 0 ? void 0 : _a.type) {
594
+ case "remove":
595
+ continue;
596
+ }
597
+ operations.set(parentKey, replaceOperation());
598
+ }
599
+ const operation = operations.get(parentIndexPath.join());
600
+ switch (operation === null || operation === void 0 ? void 0 : operation.type) {
601
+ case "remove":
602
+ operations.set(parentIndexPath.join(), {
603
+ type: "removeThenInsert",
604
+ removeIndexes: operation.indexes,
605
+ insertIndex: index,
606
+ insertNodes: nodes
607
+ });
608
+ break;
609
+ default:
610
+ operations.set(parentIndexPath.join(), insertOperation(index, nodes));
611
+ }
612
+ return operations;
613
+ }
614
+ exports.getInsertionOperations = getInsertionOperations;
615
+ function getRemovalOperations(indexPaths) {
616
+ var _a, _b;
617
+ const _ancestorIndexPaths = (0, ancestors_1.ancestorPaths)(indexPaths);
618
+ const indexesToRemove = /* @__PURE__ */ new Map();
619
+ for (const indexPath of _ancestorIndexPaths) {
620
+ const parentKey = indexPath.slice(0, -1).join();
621
+ const value = (_a = indexesToRemove.get(parentKey)) !== null && _a !== void 0 ? _a : [];
622
+ value.push(indexPath[indexPath.length - 1]);
623
+ indexesToRemove.set(parentKey, value);
624
+ }
625
+ const operations = /* @__PURE__ */ new Map();
626
+ for (const indexPath of _ancestorIndexPaths) {
627
+ for (let i = indexPath.length - 1; i >= 0; i--) {
628
+ const parentKey = indexPath.slice(0, i).join();
629
+ operations.set(parentKey, replaceOperation());
630
+ }
631
+ }
632
+ for (const indexPath of _ancestorIndexPaths) {
633
+ const parentKey = indexPath.slice(0, -1).join();
634
+ operations.set(parentKey, removeOperation((_b = indexesToRemove.get(parentKey)) !== null && _b !== void 0 ? _b : []));
635
+ }
636
+ return operations;
637
+ }
638
+ exports.getRemovalOperations = getRemovalOperations;
639
+ function getReplaceOperations(indexPath, node) {
640
+ const operations = /* @__PURE__ */ new Map();
641
+ const [parentIndexPath, index] = splitIndexPath(indexPath);
642
+ for (let i = parentIndexPath.length - 1; i >= 0; i--) {
643
+ const parentKey = parentIndexPath.slice(0, i).join();
644
+ operations.set(parentKey, replaceOperation());
645
+ }
646
+ operations.set(parentIndexPath.join(), {
647
+ type: "removeThenInsert",
648
+ removeIndexes: [index],
649
+ insertIndex: index,
650
+ insertNodes: [node]
651
+ });
652
+ return operations;
653
+ }
654
+ exports.getReplaceOperations = getReplaceOperations;
655
+ function applyOperations(node, operations, options) {
656
+ return (0, map_1.map)(node, Object.assign(Object.assign({}, options), {
657
+ // Avoid calling `getChildren` for every node in the tree.
658
+ // Return [] if we're just going to return the original node anyway.
659
+ getChildren: (node2, indexPath) => {
660
+ const key = indexPath.join();
661
+ const operation = operations.get(key);
662
+ switch (operation === null || operation === void 0 ? void 0 : operation.type) {
663
+ case "replace":
664
+ case "remove":
665
+ case "removeThenInsert":
666
+ case "insert":
667
+ return options.getChildren(node2, indexPath);
668
+ default:
669
+ return [];
670
+ }
671
+ },
672
+ transform: (node2, children, indexPath) => {
673
+ const key = indexPath.join();
674
+ const operation = operations.get(key);
675
+ switch (operation === null || operation === void 0 ? void 0 : operation.type) {
676
+ case "remove":
677
+ return options.create(node2, children.filter((_, index) => !operation.indexes.includes(index)), indexPath);
678
+ case "removeThenInsert":
679
+ const updatedChildren = children.filter((_, index) => !operation.removeIndexes.includes(index));
680
+ const adjustedIndex = operation.removeIndexes.reduce((index, removedIndex) => removedIndex < index ? index - 1 : index, operation.insertIndex);
681
+ return options.create(node2, splice(updatedChildren, adjustedIndex, 0, ...operation.insertNodes), indexPath);
682
+ case "insert":
683
+ return options.create(node2, splice(children, operation.index, 0, ...operation.nodes), indexPath);
684
+ case "replace":
685
+ return options.create(node2, children, indexPath);
686
+ default:
687
+ return node2;
688
+ }
689
+ }
690
+ }));
691
+ }
692
+ exports.applyOperations = applyOperations;
693
+ function splice(array, start, deleteCount, ...items) {
694
+ return [
695
+ ...array.slice(0, start),
696
+ ...items,
697
+ ...array.slice(start + deleteCount)
698
+ ];
699
+ }
700
+ exports.splice = splice;
701
+ }
702
+ });
703
+
704
+ // ../../node_modules/tree-visit/lib/insert.js
705
+ var require_insert = __commonJS({
706
+ "../../node_modules/tree-visit/lib/insert.js"(exports) {
707
+ "use strict";
708
+ Object.defineProperty(exports, "__esModule", { value: true });
709
+ exports.insert = void 0;
710
+ var operation_1 = require_operation();
711
+ function insert(node, options) {
712
+ const { nodes, at } = options;
713
+ if (at.length === 0) {
714
+ throw new Error(`Can't insert nodes at the root`);
715
+ }
716
+ const state = (0, operation_1.getInsertionOperations)(at, nodes);
717
+ return (0, operation_1.applyOperations)(node, state, options);
718
+ }
719
+ exports.insert = insert;
720
+ }
721
+ });
722
+
723
+ // ../../node_modules/tree-visit/lib/move.js
724
+ var require_move = __commonJS({
725
+ "../../node_modules/tree-visit/lib/move.js"(exports) {
726
+ "use strict";
727
+ Object.defineProperty(exports, "__esModule", { value: true });
728
+ exports.move = void 0;
729
+ var access_1 = require_access();
730
+ var ancestors_1 = require_ancestors();
731
+ var operation_1 = require_operation();
732
+ function move(node, options) {
733
+ if (options.indexPaths.length === 0)
734
+ return node;
735
+ for (const indexPath of options.indexPaths) {
736
+ if (indexPath.length === 0) {
737
+ throw new Error(`Can't move the root node`);
738
+ }
739
+ }
740
+ if (options.to.length === 0) {
741
+ throw new Error(`Can't move nodes to the root`);
742
+ }
743
+ const _ancestorIndexPaths = (0, ancestors_1.ancestorPaths)(options.indexPaths);
744
+ const nodesToInsert = _ancestorIndexPaths.map((indexPath) => (0, access_1.access)(node, indexPath, options));
745
+ const operations = (0, operation_1.getInsertionOperations)(options.to, nodesToInsert, (0, operation_1.getRemovalOperations)(_ancestorIndexPaths));
746
+ return (0, operation_1.applyOperations)(node, operations, options);
747
+ }
748
+ exports.move = move;
749
+ }
750
+ });
751
+
752
+ // ../../node_modules/tree-visit/lib/remove.js
753
+ var require_remove = __commonJS({
754
+ "../../node_modules/tree-visit/lib/remove.js"(exports) {
755
+ "use strict";
756
+ Object.defineProperty(exports, "__esModule", { value: true });
757
+ exports.remove = void 0;
758
+ var operation_1 = require_operation();
759
+ function remove(node, options) {
760
+ if (options.indexPaths.length === 0)
761
+ return node;
762
+ for (const indexPath of options.indexPaths) {
763
+ if (indexPath.length === 0) {
764
+ throw new Error(`Can't remove the root node`);
765
+ }
766
+ }
767
+ const operations = (0, operation_1.getRemovalOperations)(options.indexPaths);
768
+ return (0, operation_1.applyOperations)(node, operations, options);
769
+ }
770
+ exports.remove = remove;
771
+ }
772
+ });
773
+
774
+ // ../../node_modules/tree-visit/lib/replace.js
775
+ var require_replace = __commonJS({
776
+ "../../node_modules/tree-visit/lib/replace.js"(exports) {
777
+ "use strict";
778
+ Object.defineProperty(exports, "__esModule", { value: true });
779
+ exports.replace = void 0;
780
+ var operation_1 = require_operation();
781
+ function replace(node, options) {
782
+ if (options.at.length === 0)
783
+ return options.node;
784
+ const operations = (0, operation_1.getReplaceOperations)(options.at, options.node);
785
+ return (0, operation_1.applyOperations)(node, operations, options);
786
+ }
787
+ exports.replace = replace;
788
+ }
789
+ });
790
+
791
+ // ../../node_modules/tree-visit/lib/defineTree.js
792
+ var require_defineTree = __commonJS({
793
+ "../../node_modules/tree-visit/lib/defineTree.js"(exports) {
794
+ "use strict";
795
+ Object.defineProperty(exports, "__esModule", { value: true });
796
+ exports.defineTree = void 0;
797
+ var access_1 = require_access();
798
+ var diagram_1 = require_diagram();
799
+ var find_1 = require_find();
800
+ var flat_1 = require_flat();
801
+ var flatMap_1 = require_flatMap();
802
+ var insert_1 = require_insert();
803
+ var map_1 = require_map();
804
+ var move_1 = require_move();
805
+ var reduce_1 = require_reduce();
806
+ var remove_1 = require_remove();
807
+ var replace_1 = require_replace();
808
+ var visit_1 = require_visit();
809
+ var Tree = class _Tree {
810
+ constructor(getChildrenOrBaseOptions, appliedOptions) {
811
+ this.appliedOptions = appliedOptions;
812
+ this.getChildren = (node, indexPath, context) => {
813
+ return this._getChildren(node, indexPath, context);
814
+ };
815
+ this.mergeOptions = (options) => Object.assign(Object.assign(Object.assign({}, this.baseOptions), this.appliedOptions), options);
816
+ this.withOptions = (newOptions) => new _Tree(this.baseOptions, Object.assign(Object.assign({}, this.appliedOptions), newOptions));
817
+ this.access = (node, indexPath) => (0, access_1.access)(node, indexPath, this.mergeOptions({}));
818
+ this.accessPath = (node, indexPath) => (0, access_1.accessPath)(node, indexPath, this.mergeOptions({}));
819
+ this.diagram = (node, options) => typeof options === "function" ? (0, diagram_1.diagram)(node, this.mergeOptions({ getLabel: options })) : (0, diagram_1.diagram)(node, this.mergeOptions(options));
820
+ this.find = (node, predicateOrOptions) => typeof predicateOrOptions === "function" ? (0, find_1.find)(node, this.mergeOptions({ predicate: predicateOrOptions })) : (0, find_1.find)(node, this.mergeOptions(Object.assign({}, predicateOrOptions)));
821
+ this.findAll = (node, predicateOrOptions) => typeof predicateOrOptions === "function" ? (0, find_1.findAll)(node, this.mergeOptions({ predicate: predicateOrOptions })) : (0, find_1.findAll)(node, this.mergeOptions(Object.assign({}, predicateOrOptions)));
822
+ this.findIndexPath = (node, predicateOrOptions) => typeof predicateOrOptions === "function" ? (0, find_1.findIndexPath)(node, this.mergeOptions({ predicate: predicateOrOptions })) : (0, find_1.findIndexPath)(node, this.mergeOptions(Object.assign({}, predicateOrOptions)));
823
+ this.findAllIndexPaths = (node, predicateOrOptions) => typeof predicateOrOptions === "function" ? (0, find_1.findAllIndexPaths)(node, this.mergeOptions({ predicate: predicateOrOptions })) : (0, find_1.findAllIndexPaths)(node, this.mergeOptions(Object.assign({}, predicateOrOptions)));
824
+ this.flat = (node) => (0, flat_1.flat)(node, this.mergeOptions({}));
825
+ this.flatMap = (node, transform) => (0, flatMap_1.flatMap)(node, this.mergeOptions({ transform }));
826
+ this.reduce = (node, nextResult, initialResult) => (0, reduce_1.reduce)(node, this.mergeOptions({ nextResult, initialResult }));
827
+ this.map = (node, transform) => (0, map_1.map)(node, this.mergeOptions({ transform }));
828
+ this.visit = (node, onEnterOrOptions) => typeof onEnterOrOptions === "function" ? (0, visit_1.visit)(node, this.mergeOptions({ onEnter: onEnterOrOptions })) : (0, visit_1.visit)(node, this.mergeOptions(Object.assign({}, onEnterOrOptions)));
829
+ this.insert = (node, options) => (0, insert_1.insert)(node, this.mergeOptions(options));
830
+ this.remove = (node, options) => (0, remove_1.remove)(node, this.mergeOptions(options));
831
+ this.move = (node, options) => (0, move_1.move)(node, this.mergeOptions(options));
832
+ this.replace = (node, options) => (0, replace_1.replace)(node, this.mergeOptions(options));
833
+ this.baseOptions = typeof getChildrenOrBaseOptions === "function" ? { getChildren: getChildrenOrBaseOptions } : getChildrenOrBaseOptions;
834
+ this._getChildren = this.baseOptions.getChildren;
835
+ }
836
+ };
837
+ function defineTree2(getChildren) {
838
+ return new Tree(getChildren, {});
839
+ }
840
+ exports.defineTree = defineTree2;
841
+ }
842
+ });
843
+
844
+ // ../../node_modules/tree-visit/lib/indexPath.js
845
+ var require_indexPath = __commonJS({
846
+ "../../node_modules/tree-visit/lib/indexPath.js"(exports) {
847
+ "use strict";
848
+ Object.defineProperty(exports, "__esModule", { value: true });
849
+ }
850
+ });
851
+
852
+ // ../../node_modules/tree-visit/lib/options.js
853
+ var require_options = __commonJS({
854
+ "../../node_modules/tree-visit/lib/options.js"(exports) {
855
+ "use strict";
856
+ Object.defineProperty(exports, "__esModule", { value: true });
857
+ }
858
+ });
859
+
860
+ // ../../node_modules/tree-visit/lib/withOptions.js
861
+ var require_withOptions = __commonJS({
862
+ "../../node_modules/tree-visit/lib/withOptions.js"(exports) {
863
+ "use strict";
864
+ Object.defineProperty(exports, "__esModule", { value: true });
865
+ exports.withOptions = void 0;
866
+ var defineTree_1 = require_defineTree();
867
+ exports.withOptions = defineTree_1.defineTree;
868
+ }
869
+ });
870
+
871
+ // ../../node_modules/tree-visit/lib/index.js
872
+ var require_lib = __commonJS({
873
+ "../../node_modules/tree-visit/lib/index.js"(exports) {
874
+ "use strict";
875
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
876
+ if (k2 === void 0) k2 = k;
877
+ Object.defineProperty(o, k2, { enumerable: true, get: function() {
878
+ return m[k];
879
+ } });
880
+ } : function(o, m, k, k2) {
881
+ if (k2 === void 0) k2 = k;
882
+ o[k2] = m[k];
883
+ });
884
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
885
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
886
+ };
887
+ Object.defineProperty(exports, "__esModule", { value: true });
888
+ __exportStar(require_access(), exports);
889
+ __exportStar(require_ancestors(), exports);
890
+ __exportStar(require_defineTree(), exports);
891
+ __exportStar(require_diagram(), exports);
892
+ __exportStar(require_find(), exports);
893
+ __exportStar(require_flat(), exports);
894
+ __exportStar(require_flatMap(), exports);
895
+ __exportStar(require_indexPath(), exports);
896
+ __exportStar(require_insert(), exports);
897
+ __exportStar(require_map(), exports);
898
+ __exportStar(require_move(), exports);
899
+ __exportStar(require_options(), exports);
900
+ __exportStar(require_reduce(), exports);
901
+ __exportStar(require_remove(), exports);
902
+ __exportStar(require_replace(), exports);
903
+ __exportStar(require_sort(), exports);
904
+ __exportStar(require_visit(), exports);
905
+ __exportStar(require_withOptions(), exports);
906
+ }
907
+ });
908
+
909
+ // src/MediaCollection.tsx
910
+ import {
911
+ ActionMenu,
912
+ createSectionedMenu,
913
+ cssVars,
914
+ FileExplorerCollection,
915
+ FileExplorerDetail,
916
+ FileExplorerEmptyState,
917
+ FileExplorerLayout,
918
+ FileExplorerUploadButton,
919
+ MediaThumbnail
920
+ } from "@noya-app/noya-designsystem";
921
+ import {
922
+ DownloadIcon,
923
+ FolderIcon,
924
+ InputIcon,
925
+ OpenInNewWindowIcon,
926
+ ResetIcon,
927
+ TrashIcon,
928
+ UpdateIcon,
929
+ UploadIcon
930
+ } from "@noya-app/noya-icons";
931
+ import {
932
+ useAsset,
933
+ useAssetManager,
934
+ useAssets
935
+ } from "@noya-app/noya-multiplayer-react";
936
+ import { groupBy, isDeepEqual } from "@noya-app/noya-utils";
937
+ import {
938
+ downloadUrl,
939
+ memoGeneric,
940
+ useControlledOrUncontrolled
941
+ } from "@noya-app/react-utils";
942
+ import { fileOpen } from "browser-fs-access";
943
+ import {
944
+ forwardRef,
945
+ memo,
946
+ useCallback,
947
+ useEffect,
948
+ useImperativeHandle,
949
+ useMemo,
950
+ useRef,
951
+ useState
952
+ } from "react";
953
+
954
+ // src/utils/mediaItemTree.ts
955
+ var import_tree_visit = __toESM(require_lib());
956
+ import { uuid } from "@noya-app/noya-utils";
957
+ import { path } from "imfs";
958
+ var createMediaFolder = (folder) => {
959
+ return {
960
+ id: uuid(),
961
+ kind: "folder",
962
+ ...folder
963
+ };
964
+ };
965
+ var createMediaAsset = (asset) => {
966
+ return {
967
+ id: uuid(),
968
+ kind: "asset",
969
+ ...asset
970
+ };
971
+ };
972
+ var createMediaFile = (file) => {
973
+ return {
974
+ id: uuid(),
975
+ kind: "file",
976
+ ...file
977
+ };
978
+ };
979
+ var createMediaItem = (item) => {
980
+ return {
981
+ ...item
982
+ };
983
+ };
984
+ var rootMediaItem = {
985
+ id: "root",
986
+ kind: "folder"
987
+ };
988
+ var rootMediaItemPath = ".";
989
+ var rootMediaItemName = "All Files";
990
+ var PLACEHOLDER_ITEM_NAME = "placeholder";
991
+ var createMediaItemTree = (mediaMap) => {
992
+ const sortedMediaMap = Object.fromEntries(
993
+ Object.entries(mediaMap).sort((a, b) => a[0].localeCompare(b[0]))
994
+ );
995
+ const parentToChildrenMap = /* @__PURE__ */ new Map();
996
+ const idToPathMap = /* @__PURE__ */ new Map();
997
+ idToPathMap.set(rootMediaItem.id, rootMediaItemPath);
998
+ for (const [itemPath, item] of Object.entries(sortedMediaMap)) {
999
+ const parentPath = path.dirname(itemPath);
1000
+ const children = parentToChildrenMap.get(parentPath) ?? [];
1001
+ children.push(item);
1002
+ parentToChildrenMap.set(parentPath, children);
1003
+ idToPathMap.set(item.id, itemPath);
1004
+ }
1005
+ const tree = (0, import_tree_visit.defineTree)({
1006
+ getChildren: (item) => {
1007
+ const itemPath = item === rootMediaItem ? rootMediaItemPath : idToPathMap.get(item.id);
1008
+ if (!itemPath) return [];
1009
+ return parentToChildrenMap.get(itemPath) ?? [];
1010
+ },
1011
+ onDetectCycle: "skip",
1012
+ getIdentifier: (item) => item.id
1013
+ });
1014
+ const result = tree.withOptions({
1015
+ getLabel: (item) => idToPathMap.get(item.id) ?? ""
1016
+ });
1017
+ const mediaItemsWithRoot = [...Object.values(sortedMediaMap), rootMediaItem];
1018
+ const getNameForId = (id) => id === rootMediaItem.id ? rootMediaItemName : path.basename(idToPathMap.get(id) ?? "");
1019
+ const getParentIdForId = (id) => {
1020
+ const itemPath = idToPathMap.get(id);
1021
+ if (!itemPath) return;
1022
+ const parentPath = path.dirname(itemPath);
1023
+ return idToPathMap.get(parentPath);
1024
+ };
1025
+ return {
1026
+ ...result,
1027
+ idToPathMap,
1028
+ parentToChildrenMap,
1029
+ mediaItemsWithRoot,
1030
+ getParentIdForId,
1031
+ getNameForId
1032
+ };
1033
+ };
1034
+
1035
+ // src/MediaCollection.tsx
1036
+ import { path as path3 } from "imfs";
1037
+ import React from "react";
1038
+
1039
+ // src/utils/files.ts
1040
+ var import_tree_visit2 = __toESM(require_lib());
1041
+ import { path as path2 } from "imfs";
1042
+ var getVisibleItems = ({
1043
+ expandedMap,
1044
+ fileKindFilter,
1045
+ rootItemId,
1046
+ tree,
1047
+ showAllDescendants,
1048
+ showRootItem
1049
+ }) => {
1050
+ const filteredItems = [];
1051
+ const relativeRootItem = tree.find(rootMediaItem, (item) => item.id === rootItemId) ?? rootMediaItem;
1052
+ tree.visit(relativeRootItem, (item) => {
1053
+ if (relativeRootItem.id === item.id) {
1054
+ if (showRootItem) {
1055
+ filteredItems.push(item);
1056
+ }
1057
+ return;
1058
+ }
1059
+ if (item.kind === "file" && fileKindFilter === "all") {
1060
+ filteredItems.push(item);
1061
+ }
1062
+ if (item.kind === "asset" && (fileKindFilter === "assets" || fileKindFilter === "all")) {
1063
+ filteredItems.push(item);
1064
+ }
1065
+ if (item.kind === "folder" && (fileKindFilter === "directories" || fileKindFilter === "all")) {
1066
+ filteredItems.push(item);
1067
+ }
1068
+ if (!expandedMap[item.id] || !showAllDescendants) return "skip";
1069
+ });
1070
+ return filteredItems;
1071
+ };
1072
+ var basenameValidator = (basename) => {
1073
+ if (!basename || basename.trim() === "") return false;
1074
+ const invalidCharsRegex = /[/\\<>:"|?*]/;
1075
+ return !invalidCharsRegex.test(basename);
1076
+ };
1077
+ var validateMediaItemRename = ({
1078
+ basename,
1079
+ selectedItemPath,
1080
+ media
1081
+ }) => {
1082
+ if (!basenameValidator(basename)) return false;
1083
+ const newItemPath = path2.join(path2.dirname(selectedItemPath), basename);
1084
+ const newPathExists = media[newItemPath];
1085
+ if (newPathExists) return false;
1086
+ return true;
1087
+ };
1088
+ var movePathsIntoTarget = ({
1089
+ media,
1090
+ sourceItemPaths,
1091
+ targetItemPath,
1092
+ tree
1093
+ }) => {
1094
+ const ancestors = (0, import_tree_visit2.ancestorPaths)(
1095
+ sourceItemPaths.map((path4) => path4.split("/"))
1096
+ );
1097
+ const mediaClone = { ...media };
1098
+ for (const ancestor of ancestors) {
1099
+ const ancestorPath = ancestor.join("/");
1100
+ const ancestorItem = mediaClone[ancestorPath];
1101
+ const newAncestorPath = path2.join(
1102
+ targetItemPath,
1103
+ path2.basename(ancestorPath)
1104
+ );
1105
+ if (!ancestorItem) continue;
1106
+ const descendantPaths = tree.flat(ancestorItem).map((item) => tree.idToPathMap.get(item.id));
1107
+ for (const descendantPath of descendantPaths) {
1108
+ if (!descendantPath) continue;
1109
+ const newDescendantPath = descendantPath.replace(
1110
+ ancestorPath,
1111
+ newAncestorPath
1112
+ );
1113
+ const newPathIsValid = validateMediaItemRename({
1114
+ basename: path2.basename(descendantPath),
1115
+ selectedItemPath: newDescendantPath,
1116
+ media
1117
+ });
1118
+ if (newPathIsValid) {
1119
+ mediaClone[newDescendantPath] = mediaClone[descendantPath];
1120
+ delete mediaClone[descendantPath];
1121
+ }
1122
+ }
1123
+ }
1124
+ return mediaClone;
1125
+ };
1126
+ var moveUpAFolder = ({
1127
+ tree,
1128
+ media,
1129
+ selectedIds
1130
+ }) => {
1131
+ const indexPath = tree.findIndexPath(
1132
+ rootMediaItem,
1133
+ (item) => item.id === selectedIds[0]
1134
+ );
1135
+ if (!indexPath) return;
1136
+ const grandparentFolder = tree.access(
1137
+ rootMediaItem,
1138
+ indexPath.slice(0, indexPath.length - 2)
1139
+ );
1140
+ const grandparentFolderPath = tree.idToPathMap.get(grandparentFolder.id);
1141
+ if (!grandparentFolderPath) return;
1142
+ const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path4) => Boolean(path4));
1143
+ return movePathsIntoTarget({
1144
+ media,
1145
+ targetItemPath: grandparentFolderPath,
1146
+ sourceItemPaths,
1147
+ tree
1148
+ });
1149
+ };
1150
+ var getDepthMap = (item, tree, showAllDescendants) => {
1151
+ const depthMap = {};
1152
+ tree.visit(item, (item2, indexPath) => {
1153
+ if (showAllDescendants) {
1154
+ depthMap[item2.id] = Math.max(indexPath.length - 1, 0);
1155
+ } else {
1156
+ depthMap[item2.id] = 0;
1157
+ }
1158
+ });
1159
+ return depthMap;
1160
+ };
1161
+ var updateExpandedMap = ({
1162
+ item,
1163
+ expanded,
1164
+ expandable,
1165
+ expandedMap,
1166
+ tree
1167
+ }) => {
1168
+ const newExpandedMap = { ...expandedMap };
1169
+ const inner = (item2, expanded2) => {
1170
+ if (!expandable) return {};
1171
+ if (item2.id === rootMediaItem.id) return {};
1172
+ if (!expanded2) {
1173
+ const children = tree.getChildren(item2, []);
1174
+ children.forEach((child) => inner(child, false));
1175
+ }
1176
+ newExpandedMap[item2.id] = expanded2;
1177
+ };
1178
+ inner(item, expanded);
1179
+ return newExpandedMap;
1180
+ };
1181
+ var deleteMediaItems = ({
1182
+ selectedIds,
1183
+ media,
1184
+ tree
1185
+ }) => {
1186
+ const itemsToDelete = selectedIds.flatMap((mediaItemId) => {
1187
+ const mediaItem = tree.mediaItemsWithRoot.find(
1188
+ (item) => item.id === mediaItemId
1189
+ );
1190
+ if (!mediaItem) return [];
1191
+ return tree.flat(mediaItem);
1192
+ });
1193
+ const itemKeysToDelete = new Set(
1194
+ itemsToDelete.map((item) => tree.idToPathMap.get(item.id))
1195
+ );
1196
+ return Object.fromEntries(
1197
+ Object.entries(media).filter(([key]) => !itemKeysToDelete.has(key))
1198
+ );
1199
+ };
1200
+ var moveMediaInsideFolder = ({
1201
+ sourceItemIds,
1202
+ targetItemId,
1203
+ media,
1204
+ tree
1205
+ }) => {
1206
+ const targetItemPath = tree.idToPathMap.get(targetItemId);
1207
+ if (!targetItemPath) return media;
1208
+ const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path4) => Boolean(path4));
1209
+ return movePathsIntoTarget({
1210
+ media,
1211
+ sourceItemPaths,
1212
+ targetItemPath,
1213
+ tree
1214
+ });
1215
+ };
1216
+ var getParentDirectories = (mediaMap, folderId) => {
1217
+ const tree = createMediaItemTree(mediaMap);
1218
+ const indexPath = tree.findIndexPath(
1219
+ rootMediaItem,
1220
+ (item) => item.id === folderId
1221
+ );
1222
+ if (!indexPath) return [rootMediaItem];
1223
+ return tree.accessPath(rootMediaItem, indexPath);
1224
+ };
1225
+
1226
+ // src/MediaCollection.tsx
1227
+ var MediaThumbnailInternal = memoGeneric(
1228
+ ({ item, selected }) => {
1229
+ const asset = useAsset(item.kind === "asset" ? item.assetId : void 0);
1230
+ const isRoot = item.id === rootMediaItem.id;
1231
+ const isFolder = item.kind === "folder";
1232
+ return /* @__PURE__ */ React.createElement(
1233
+ MediaThumbnail,
1234
+ {
1235
+ contentType: asset?.contentType,
1236
+ iconName: isRoot ? "HomeIcon" : isFolder ? "FolderIcon" : void 0,
1237
+ url: asset?.url,
1238
+ selected
1239
+ }
1240
+ );
1241
+ }
1242
+ );
1243
+ var MediaCollection = memo(
1244
+ forwardRef(function MediaCollection2({
1245
+ onSelectionChange,
1246
+ selectedIds: selectedIdsProp,
1247
+ media,
1248
+ setMedia,
1249
+ viewType = "list",
1250
+ fileKindFilter = "all",
1251
+ showRootItem = false,
1252
+ initialExpanded,
1253
+ expandable = true,
1254
+ renamable = true,
1255
+ onDoubleClickItem,
1256
+ rootItemId = rootMediaItem.id,
1257
+ title,
1258
+ size = "medium",
1259
+ right,
1260
+ renderAction: renderActionProp,
1261
+ className,
1262
+ showUploadButton = true,
1263
+ showAllDescendants = true,
1264
+ scrollable = false,
1265
+ sortable = false,
1266
+ renderEmptyState
1267
+ }, ref) {
1268
+ const tree = useMemo(() => createMediaItemTree(media), [media]);
1269
+ const [tempItem, setTempItem] = useState(
1270
+ void 0
1271
+ );
1272
+ const treeWithTempItem = useMemo(
1273
+ () => createMediaItemTree({
1274
+ ...media,
1275
+ ...tempItem ? { [tempItem[0]]: tempItem[1] } : {}
1276
+ }),
1277
+ [media, tempItem]
1278
+ );
1279
+ const [selectedIds, setSelectedIds] = useControlledOrUncontrolled(
1280
+ {
1281
+ defaultValue: [],
1282
+ value: selectedIdsProp,
1283
+ onChange: onSelectionChange
1284
+ }
1285
+ );
1286
+ const assetManager = useAssetManager();
1287
+ const assets = useAssets();
1288
+ const [expandedMap, setExpandedMap] = useState({});
1289
+ const visibleItems = useMemo(
1290
+ () => getVisibleItems({
1291
+ expandedMap,
1292
+ fileKindFilter,
1293
+ rootItemId,
1294
+ tree: treeWithTempItem,
1295
+ showAllDescendants,
1296
+ showRootItem
1297
+ }),
1298
+ [
1299
+ expandedMap,
1300
+ fileKindFilter,
1301
+ rootItemId,
1302
+ treeWithTempItem,
1303
+ showAllDescendants,
1304
+ showRootItem
1305
+ ]
1306
+ );
1307
+ const depthMap = useMemo(
1308
+ () => getDepthMap(rootMediaItem, treeWithTempItem, showAllDescendants),
1309
+ [treeWithTempItem, showAllDescendants]
1310
+ );
1311
+ const collectionRef = useRef(null);
1312
+ const selectedMediaItems = useMemo(
1313
+ () => treeWithTempItem.mediaItemsWithRoot.filter(
1314
+ (item) => selectedIds.includes(item.id)
1315
+ ),
1316
+ [treeWithTempItem, selectedIds]
1317
+ );
1318
+ const groupedItems = groupBy(selectedMediaItems, (item) => item.kind);
1319
+ const selectedAssetItems = groupedItems.asset ?? [];
1320
+ const selectedFolderItems = groupedItems.folder ?? [];
1321
+ const singleItemSelected = selectedMediaItems.length === 1;
1322
+ const onlyAssetsSelected = selectedAssetItems.length > 0 && selectedAssetItems.length === selectedMediaItems.length;
1323
+ const onlyFoldersSelected = selectedFolderItems.length > 0 && selectedFolderItems.length === selectedMediaItems.length;
1324
+ const onlySingleFolderSelected = onlyFoldersSelected && selectedFolderItems.length === 1;
1325
+ const onlySingleAssetSelected = onlyAssetsSelected && selectedAssetItems.length === 1;
1326
+ const rootSelected = selectedIds.includes(rootMediaItem.id);
1327
+ const sameParentSelected = selectedMediaItems.every((item) => {
1328
+ const itemPath = tree.idToPathMap.get(item.id);
1329
+ const firstSelectedPath = tree.idToPathMap.get(selectedIds[0]);
1330
+ if (!itemPath || !firstSelectedPath) return false;
1331
+ return itemPath.startsWith(path3.dirname(firstSelectedPath));
1332
+ });
1333
+ const gridSize = useMemo(() => {
1334
+ if (viewType === "grid") {
1335
+ return size;
1336
+ }
1337
+ return "medium";
1338
+ }, [viewType, size]);
1339
+ useEffect(() => {
1340
+ if (initialExpanded) {
1341
+ setExpandedMap(initialExpanded);
1342
+ }
1343
+ }, [initialExpanded]);
1344
+ const handleExpanded = useCallback(
1345
+ (item) => {
1346
+ if (!expandable) return void 0;
1347
+ if (item.kind !== "folder") return void 0;
1348
+ if (item.id === rootMediaItem.id) return void 0;
1349
+ return expandedMap[item.id] ?? false;
1350
+ },
1351
+ [expandedMap, expandable]
1352
+ );
1353
+ const handleDelete = useCallback(
1354
+ (selectedIds2) => {
1355
+ const newMedia = deleteMediaItems({
1356
+ selectedIds: selectedIds2,
1357
+ media,
1358
+ tree
1359
+ });
1360
+ setSelectedIds([rootMediaItem.id]);
1361
+ setMedia({ name: "Delete items", timestamp: Date.now() }, newMedia);
1362
+ },
1363
+ [media, setMedia, setSelectedIds, tree]
1364
+ );
1365
+ const onRename = useCallback(
1366
+ (selectedItem, newName) => {
1367
+ if (!renamable) return;
1368
+ const selectedItemPath = treeWithTempItem.idToPathMap.get(
1369
+ selectedItem.id
1370
+ );
1371
+ if (!selectedItemPath) return;
1372
+ const mediaWithTempItem = {
1373
+ ...media,
1374
+ ...tempItem ? { [tempItem[0]]: tempItem[1] } : {}
1375
+ };
1376
+ const renameIsValid = validateMediaItemRename({
1377
+ basename: newName,
1378
+ selectedItemPath,
1379
+ media: mediaWithTempItem
1380
+ });
1381
+ if (!renameIsValid) {
1382
+ setTempItem(void 0);
1383
+ return;
1384
+ }
1385
+ const mediaClone = { ...media };
1386
+ delete mediaClone[selectedItemPath];
1387
+ setMedia(
1388
+ { name: "Rename media item", timestamp: Date.now() },
1389
+ {
1390
+ ...mediaClone,
1391
+ [path3.join(path3.dirname(selectedItemPath), newName)]: selectedItem
1392
+ }
1393
+ );
1394
+ setTempItem(void 0);
1395
+ },
1396
+ [media, renamable, setMedia, tempItem, treeWithTempItem.idToPathMap]
1397
+ );
1398
+ const handleAddFolder = useCallback(
1399
+ (currentFolderId) => {
1400
+ const newFolder = createMediaFolder();
1401
+ const currentFolderPath = tree.idToPathMap.get(currentFolderId);
1402
+ if (!currentFolderPath) return;
1403
+ setTempItem([
1404
+ path3.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1405
+ newFolder
1406
+ ]);
1407
+ setTimeout(() => {
1408
+ collectionRef.current?.editName(newFolder.id);
1409
+ }, 50);
1410
+ },
1411
+ [tree]
1412
+ );
1413
+ const handleAddFile = useCallback(
1414
+ (currentFolderId) => {
1415
+ const newFile = createMediaFile({
1416
+ content: "",
1417
+ encoding: "utf-8"
1418
+ });
1419
+ const currentFolderPath = tree.idToPathMap.get(
1420
+ currentFolderId ?? rootMediaItem.id
1421
+ );
1422
+ if (!currentFolderPath) return;
1423
+ setTempItem([
1424
+ path3.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1425
+ newFile
1426
+ ]);
1427
+ setTimeout(() => {
1428
+ collectionRef.current?.editName(newFile.id);
1429
+ }, 50);
1430
+ },
1431
+ [tree.idToPathMap]
1432
+ );
1433
+ const handleMoveUpAFolder = useCallback(
1434
+ (selectedIds2) => {
1435
+ const newMedia = moveUpAFolder({
1436
+ tree,
1437
+ media,
1438
+ selectedIds: selectedIds2
1439
+ });
1440
+ if (!newMedia) return;
1441
+ setMedia({ name: "Move items", timestamp: Date.now() }, newMedia);
1442
+ },
1443
+ [media, tree, setMedia]
1444
+ );
1445
+ const handleUpload = useCallback(
1446
+ async (selectedId) => {
1447
+ try {
1448
+ const files = await fileOpen({ multiple: true });
1449
+ if (!files || !Array.isArray(files) || files.length === 0) return;
1450
+ const parentPath = tree.idToPathMap.get(selectedId);
1451
+ if (!parentPath) return;
1452
+ const uploadPromises = files.map(async (file) => {
1453
+ const asset = await assetManager.create(file);
1454
+ const assetPath = path3.join(parentPath, path3.basename(file.name));
1455
+ return {
1456
+ assetPath,
1457
+ asset: createMediaAsset({ assetId: asset.id })
1458
+ };
1459
+ });
1460
+ const newMediaMap = await Promise.all(uploadPromises);
1461
+ setMedia(
1462
+ { name: "Add media items", timestamp: Date.now() },
1463
+ {
1464
+ ...media,
1465
+ ...Object.fromEntries(
1466
+ newMediaMap.map(({ assetPath, asset }) => [assetPath, asset])
1467
+ )
1468
+ }
1469
+ );
1470
+ } catch (error) {
1471
+ console.error("Failed to upload files:", error);
1472
+ }
1473
+ },
1474
+ [tree.idToPathMap, setMedia, media, assetManager]
1475
+ );
1476
+ const handleDownload = useCallback(
1477
+ async (selectedItems) => {
1478
+ const downloadPromises = selectedItems.filter((item) => item.kind === "asset").map(async (item) => {
1479
+ const asset = assets.find((a) => a.id === item.assetId);
1480
+ if (!asset?.url) return;
1481
+ return downloadUrl(asset.url, tree.getNameForId(item.id));
1482
+ });
1483
+ await Promise.all(downloadPromises);
1484
+ },
1485
+ [assets, tree]
1486
+ );
1487
+ const handlePreview = useCallback(
1488
+ async (selectedItems) => {
1489
+ const previewPromises = selectedItems.filter((item) => item.kind === "asset").map(async (item) => {
1490
+ const asset = assets.find((a) => a.id === item.assetId);
1491
+ if (!asset?.url) return;
1492
+ return window?.open(asset.url, "_blank");
1493
+ });
1494
+ await Promise.all(previewPromises);
1495
+ },
1496
+ [assets]
1497
+ );
1498
+ const handleReplace = useCallback(
1499
+ async (selectedItem) => {
1500
+ try {
1501
+ const file = await fileOpen();
1502
+ if (!file) return;
1503
+ const asset = await assetManager.create(file);
1504
+ const oldFile = selectedItem;
1505
+ const oldFilePath = tree.idToPathMap.get(oldFile.id);
1506
+ if (!oldFilePath || oldFile.kind !== "asset") return;
1507
+ setMedia(
1508
+ { name: "Replace media file", timestamp: Date.now() },
1509
+ {
1510
+ ...media,
1511
+ [oldFilePath]: createMediaAsset({
1512
+ ...oldFile,
1513
+ assetId: asset.id
1514
+ })
1515
+ }
1516
+ );
1517
+ } catch (error) {
1518
+ console.error("Failed to upload file:", error);
1519
+ }
1520
+ },
1521
+ [media, setMedia, assetManager, tree]
1522
+ );
1523
+ const handleRename = useCallback(
1524
+ (selectedItemId) => {
1525
+ collectionRef.current?.editName(selectedItemId);
1526
+ },
1527
+ [collectionRef]
1528
+ );
1529
+ const handleMoveMediaInsideFolder = useCallback(
1530
+ (sourceItem, targetItem) => {
1531
+ const sourceItemPath = tree.idToPathMap.get(sourceItem.id);
1532
+ const targetItemPath = tree.idToPathMap.get(targetItem.id);
1533
+ if (!sourceItemPath || !targetItemPath) return;
1534
+ const newMedia = moveMediaInsideFolder({
1535
+ sourceItemIds: [sourceItem.id],
1536
+ targetItemId: targetItem.id,
1537
+ media,
1538
+ tree
1539
+ });
1540
+ setMedia(
1541
+ {
1542
+ name: "Move media file inside folder",
1543
+ timestamp: Date.now()
1544
+ },
1545
+ newMedia
1546
+ );
1547
+ },
1548
+ [media, setMedia, tree]
1549
+ );
1550
+ const assetContextMenuItems = useMemo(() => {
1551
+ return createSectionedMenu(
1552
+ [
1553
+ !rootSelected && singleItemSelected && {
1554
+ title: "Rename",
1555
+ value: "rename",
1556
+ icon: /* @__PURE__ */ React.createElement(InputIcon, null)
1557
+ },
1558
+ onlySingleAssetSelected && {
1559
+ title: "Replace",
1560
+ value: "replace",
1561
+ icon: /* @__PURE__ */ React.createElement(UpdateIcon, null)
1562
+ },
1563
+ !rootSelected && {
1564
+ title: "Delete",
1565
+ value: "delete",
1566
+ icon: /* @__PURE__ */ React.createElement(TrashIcon, null)
1567
+ }
1568
+ ],
1569
+ [
1570
+ onlySingleFolderSelected && {
1571
+ title: "Add media",
1572
+ value: "upload",
1573
+ icon: /* @__PURE__ */ React.createElement(UploadIcon, null)
1574
+ },
1575
+ onlySingleFolderSelected && {
1576
+ title: "Add a Folder",
1577
+ value: "addFolder",
1578
+ icon: /* @__PURE__ */ React.createElement(FolderIcon, null)
1579
+ },
1580
+ onlyAssetsSelected && tree.mediaItemsWithRoot.length > 0 && {
1581
+ title: "Download",
1582
+ value: "download",
1583
+ icon: /* @__PURE__ */ React.createElement(DownloadIcon, null)
1584
+ },
1585
+ onlySingleAssetSelected && {
1586
+ title: "Preview",
1587
+ value: "preview",
1588
+ icon: /* @__PURE__ */ React.createElement(OpenInNewWindowIcon, null)
1589
+ }
1590
+ ],
1591
+ [
1592
+ !rootSelected && sameParentSelected && {
1593
+ title: "Move up a folder",
1594
+ value: "move",
1595
+ icon: /* @__PURE__ */ React.createElement(ResetIcon, null)
1596
+ }
1597
+ ]
1598
+ );
1599
+ }, [
1600
+ rootSelected,
1601
+ singleItemSelected,
1602
+ onlySingleAssetSelected,
1603
+ onlySingleFolderSelected,
1604
+ onlyAssetsSelected,
1605
+ tree.mediaItemsWithRoot.length,
1606
+ sameParentSelected
1607
+ ]);
1608
+ const handleMenuAction = useCallback(
1609
+ async (action, selectedItems) => {
1610
+ if (selectedItems.length === 0) return;
1611
+ switch (action) {
1612
+ case "rename":
1613
+ handleRename(selectedItems[0].id);
1614
+ return;
1615
+ case "delete":
1616
+ handleDelete(selectedIds);
1617
+ return;
1618
+ case "replace":
1619
+ handleReplace(selectedItems[0]);
1620
+ return;
1621
+ case "upload":
1622
+ handleUpload(selectedItems[0].id);
1623
+ return;
1624
+ case "addFolder":
1625
+ handleAddFolder(selectedItems[0].id);
1626
+ return;
1627
+ case "preview":
1628
+ handlePreview(selectedItems);
1629
+ return;
1630
+ case "download":
1631
+ handleDownload(selectedItems);
1632
+ return;
1633
+ case "move":
1634
+ handleMoveUpAFolder(selectedIds);
1635
+ return;
1636
+ }
1637
+ },
1638
+ [
1639
+ handleRename,
1640
+ handleDelete,
1641
+ selectedIds,
1642
+ handleReplace,
1643
+ handleUpload,
1644
+ handleAddFolder,
1645
+ handlePreview,
1646
+ handleDownload,
1647
+ handleMoveUpAFolder
1648
+ ]
1649
+ );
1650
+ const handleSetExpanded = useCallback(
1651
+ (item, expanded) => {
1652
+ setExpandedMap(
1653
+ (prev) => updateExpandedMap({
1654
+ item,
1655
+ expanded,
1656
+ expandable,
1657
+ expandedMap: prev,
1658
+ tree
1659
+ })
1660
+ );
1661
+ },
1662
+ [expandable, tree]
1663
+ );
1664
+ const renderAction = useMemo(() => {
1665
+ if (renderActionProp) return renderActionProp;
1666
+ return ({
1667
+ selected,
1668
+ onOpenChange
1669
+ }) => /* @__PURE__ */ React.createElement(
1670
+ ActionMenu,
1671
+ {
1672
+ menuItems: assetContextMenuItems,
1673
+ onSelect: (action) => handleMenuAction(action, selectedMediaItems),
1674
+ selected,
1675
+ onOpenChange,
1676
+ style: {
1677
+ backgroundColor: selected ? cssVars.colors.primaryPastel : "transparent"
1678
+ }
1679
+ }
1680
+ );
1681
+ }, [
1682
+ assetContextMenuItems,
1683
+ handleMenuAction,
1684
+ renderActionProp,
1685
+ selectedMediaItems
1686
+ ]);
1687
+ useImperativeHandle(ref, () => ({
1688
+ upload: (selectedId) => handleUpload(selectedId),
1689
+ delete: handleDelete,
1690
+ download: handleDownload,
1691
+ rename: handleRename,
1692
+ addFolder: handleAddFolder,
1693
+ addFile: handleAddFile,
1694
+ moveUpAFolder: handleMoveUpAFolder,
1695
+ replace: handleReplace,
1696
+ preview: handlePreview,
1697
+ moveMediaInsideFolder: handleMoveMediaInsideFolder
1698
+ }));
1699
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
1700
+ FileExplorerLayout,
1701
+ {
1702
+ title: title ?? rootMediaItemName,
1703
+ right: /* @__PURE__ */ React.createElement(
1704
+ FileExplorerUploadButton,
1705
+ {
1706
+ showUploadButton,
1707
+ onUpload: () => handleUpload(rootMediaItem.id)
1708
+ },
1709
+ right
1710
+ ),
1711
+ className
1712
+ },
1713
+ /* @__PURE__ */ React.createElement(
1714
+ FileExplorerCollection,
1715
+ {
1716
+ ref: collectionRef,
1717
+ scrollable,
1718
+ items: visibleItems,
1719
+ viewType,
1720
+ size: gridSize,
1721
+ getId: (file) => file.id,
1722
+ getName: (file) => {
1723
+ if (file.id === tempItem?.[1].id) {
1724
+ return "";
1725
+ }
1726
+ return treeWithTempItem.getNameForId(file.id);
1727
+ },
1728
+ expandable,
1729
+ sortable,
1730
+ getPlaceholder: (item) => {
1731
+ switch (item.kind) {
1732
+ case "folder":
1733
+ return "Enter folder name";
1734
+ case "asset":
1735
+ case "file":
1736
+ return "Enter file name";
1737
+ }
1738
+ },
1739
+ getExpanded: handleExpanded,
1740
+ setExpanded: handleSetExpanded,
1741
+ getRenamable: (item) => {
1742
+ if (item.id === rootMediaItem.id) return false;
1743
+ return true;
1744
+ },
1745
+ getDepth: (item) => depthMap[item.id],
1746
+ menuItems: assetContextMenuItems,
1747
+ onSelectMenuItem: handleMenuAction,
1748
+ onSelectionChange: setSelectedIds,
1749
+ onDoubleClickItem,
1750
+ onRename,
1751
+ renamable,
1752
+ selectedIds,
1753
+ renderThumbnail: (props) => /* @__PURE__ */ React.createElement(MediaThumbnailInternal, { ...props }),
1754
+ renderAction,
1755
+ renderDetail: (file, selected) => {
1756
+ if (file.kind !== "asset") return null;
1757
+ const asset = assets.find((a) => a.id === file.assetId);
1758
+ if (!asset) return null;
1759
+ return /* @__PURE__ */ React.createElement(FileExplorerDetail, { selected }, (asset.size / 1024).toFixed(1), "KB");
1760
+ },
1761
+ renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ React.createElement(FileExplorerEmptyState, null),
1762
+ itemRoleDescription: "clickable file item",
1763
+ getDropTargetParentIndex: (overIndex) => {
1764
+ const item = visibleItems[overIndex];
1765
+ const parentIndex = visibleItems.findIndex(
1766
+ (i) => i.id === tree.getParentIdForId(item.id)
1767
+ );
1768
+ return parentIndex === -1 ? void 0 : parentIndex;
1769
+ },
1770
+ acceptsDrop: (sourceIndex, targetIndex, position) => {
1771
+ const sourceItem = visibleItems[sourceIndex];
1772
+ const targetItem = visibleItems[targetIndex];
1773
+ if (position !== "inside" || targetItem.kind === "asset") {
1774
+ return false;
1775
+ }
1776
+ const sourcePath = tree.findIndexPath(
1777
+ rootMediaItem,
1778
+ (item) => item.id === sourceItem.id
1779
+ );
1780
+ const targetPath = tree.findIndexPath(
1781
+ rootMediaItem,
1782
+ (item) => item.id === targetItem.id
1783
+ );
1784
+ if (!sourcePath || !targetPath) return false;
1785
+ if (isDeepEqual(sourcePath, targetPath.slice(0, sourcePath.length))) {
1786
+ return false;
1787
+ }
1788
+ return true;
1789
+ },
1790
+ onMoveItem: (sourceIndex, targetIndex, position) => {
1791
+ const sourceItem = visibleItems[sourceIndex];
1792
+ const targetItem = visibleItems[targetIndex];
1793
+ if (position === "inside") {
1794
+ handleMoveMediaInsideFolder(sourceItem, targetItem);
1795
+ }
1796
+ },
1797
+ onFilesDrop: async (event) => {
1798
+ event.preventDefault();
1799
+ const files = Array.from(event.dataTransfer.files);
1800
+ if (files.length === 0) return;
1801
+ try {
1802
+ const uploadPromises = files.map(async (file) => {
1803
+ const asset = await assetManager.create(file);
1804
+ return {
1805
+ asset: createMediaAsset({
1806
+ assetId: asset.id
1807
+ }),
1808
+ name: file.name
1809
+ };
1810
+ });
1811
+ const newMediaItems = await Promise.all(uploadPromises);
1812
+ const rootItemPath = tree.idToPathMap.get(rootItemId);
1813
+ if (!rootItemPath) return;
1814
+ setMedia(
1815
+ { name: "Add media files", timestamp: Date.now() },
1816
+ {
1817
+ ...media,
1818
+ ...Object.fromEntries(
1819
+ newMediaItems.map((item) => [
1820
+ path3.join(rootItemPath, item.name),
1821
+ item.asset
1822
+ ])
1823
+ )
1824
+ }
1825
+ );
1826
+ } catch (error) {
1827
+ console.error("Failed to upload dropped files:", error);
1828
+ }
1829
+ }
1830
+ }
1831
+ )
1832
+ ));
1833
+ })
1834
+ );
1835
+ export {
1836
+ MediaCollection,
1837
+ PLACEHOLDER_ITEM_NAME,
1838
+ basenameValidator,
1839
+ createMediaAsset,
1840
+ createMediaFile,
1841
+ createMediaFolder,
1842
+ createMediaItem,
1843
+ createMediaItemTree,
1844
+ deleteMediaItems,
1845
+ getDepthMap,
1846
+ getParentDirectories,
1847
+ getVisibleItems,
1848
+ moveMediaInsideFolder,
1849
+ movePathsIntoTarget,
1850
+ moveUpAFolder,
1851
+ rootMediaItem,
1852
+ rootMediaItemName,
1853
+ rootMediaItemPath,
1854
+ updateExpandedMap,
1855
+ validateMediaItemRename
1856
+ };
1857
+ //# sourceMappingURL=index.mjs.map