@noya-app/noya-file-explorer 0.0.14 → 0.0.16
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/.eslintrc.js +1 -5
- package/.turbo/turbo-build.log +13 -13
- package/CHANGELOG.md +25 -0
- package/dist/index.css +166 -34
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +10577 -4
- package/dist/index.d.ts +10577 -4
- package/dist/index.js +251 -113
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +251 -113
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- package/src/MediaCollection.tsx +114 -66
- package/src/utils/files.ts +3 -0
- package/src/utils/handleFileDrop.ts +142 -0
package/dist/index.mjs
CHANGED
|
@@ -38,10 +38,10 @@ var require_access = __commonJS({
|
|
|
38
38
|
const accessed = _getPath(node, indexPath, options);
|
|
39
39
|
return accessed[accessed.length - 1];
|
|
40
40
|
}
|
|
41
|
-
let
|
|
42
|
-
while (
|
|
43
|
-
let index =
|
|
44
|
-
const children = options.getChildren(node,
|
|
41
|
+
let path5 = indexPath.slice();
|
|
42
|
+
while (path5.length > 0) {
|
|
43
|
+
let index = path5.shift();
|
|
44
|
+
const children = options.getChildren(node, path5);
|
|
45
45
|
const child = children[index];
|
|
46
46
|
if (!child) {
|
|
47
47
|
return void 0;
|
|
@@ -54,12 +54,12 @@ var require_access = __commonJS({
|
|
|
54
54
|
return _getPath(node, indexPath, options).slice(0, -1);
|
|
55
55
|
}
|
|
56
56
|
function _getPath(node, indexPath, options) {
|
|
57
|
-
let
|
|
57
|
+
let path5 = indexPath.slice();
|
|
58
58
|
let result = [node];
|
|
59
|
-
while (
|
|
60
|
-
let index =
|
|
59
|
+
while (path5.length > 0) {
|
|
60
|
+
let index = path5.shift();
|
|
61
61
|
const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
|
|
62
|
-
const children = options.getChildren(node,
|
|
62
|
+
const children = options.getChildren(node, path5, context);
|
|
63
63
|
const child = children[index];
|
|
64
64
|
if (!child) {
|
|
65
65
|
return result;
|
|
@@ -74,20 +74,20 @@ var require_access = __commonJS({
|
|
|
74
74
|
const accessed = accessPath(node, indexPath, options);
|
|
75
75
|
return accessed[accessed.length - 1];
|
|
76
76
|
}
|
|
77
|
-
let
|
|
78
|
-
while (
|
|
79
|
-
let index =
|
|
80
|
-
node = options.getChildren(node,
|
|
77
|
+
let path5 = indexPath.slice();
|
|
78
|
+
while (path5.length > 0) {
|
|
79
|
+
let index = path5.shift();
|
|
80
|
+
node = options.getChildren(node, path5)[index];
|
|
81
81
|
}
|
|
82
82
|
return node;
|
|
83
83
|
}
|
|
84
84
|
function accessPath(node, indexPath, options) {
|
|
85
|
-
let
|
|
85
|
+
let path5 = indexPath.slice();
|
|
86
86
|
let result = [node];
|
|
87
|
-
while (
|
|
88
|
-
let index =
|
|
87
|
+
while (path5.length > 0) {
|
|
88
|
+
let index = path5.shift();
|
|
89
89
|
const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
|
|
90
|
-
node = options.getChildren(node,
|
|
90
|
+
node = options.getChildren(node, path5, context)[index];
|
|
91
91
|
result.push(node);
|
|
92
92
|
}
|
|
93
93
|
return result;
|
|
@@ -601,40 +601,40 @@ var require_transformPath = __commonJS({
|
|
|
601
601
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
602
602
|
exports.transformPath = transformPath;
|
|
603
603
|
var sort_1 = require_sort();
|
|
604
|
-
function commonAncestor(
|
|
605
|
-
const length = Math.min(
|
|
604
|
+
function commonAncestor(path5, otherPath) {
|
|
605
|
+
const length = Math.min(path5.length, otherPath.length);
|
|
606
606
|
for (let i = 0; i < length; i++) {
|
|
607
|
-
if (
|
|
608
|
-
return
|
|
607
|
+
if (path5[i] !== otherPath[i]) {
|
|
608
|
+
return path5.slice(0, i);
|
|
609
609
|
}
|
|
610
610
|
}
|
|
611
|
-
return
|
|
611
|
+
return path5.slice(0, length);
|
|
612
612
|
}
|
|
613
|
-
function transformPath(
|
|
614
|
-
if (otherPath.length >
|
|
615
|
-
return
|
|
613
|
+
function transformPath(path5, operation, otherPath, count = 1) {
|
|
614
|
+
if (otherPath.length > path5.length || (0, sort_1.comparePathsByComponent)(otherPath, path5) > 0) {
|
|
615
|
+
return path5;
|
|
616
616
|
}
|
|
617
617
|
if (otherPath.length === 0 && operation === "remove") {
|
|
618
618
|
return void 0;
|
|
619
619
|
}
|
|
620
|
-
const common = commonAncestor(
|
|
621
|
-
const adjustmentIndex = common.length ===
|
|
622
|
-
const pathValue =
|
|
620
|
+
const common = commonAncestor(path5, otherPath);
|
|
621
|
+
const adjustmentIndex = common.length === path5.length || common.length === otherPath.length ? common.length - 1 : common.length;
|
|
622
|
+
const pathValue = path5[adjustmentIndex];
|
|
623
623
|
const otherPathValue = otherPath[adjustmentIndex];
|
|
624
624
|
if (operation === "insert" && otherPathValue <= pathValue) {
|
|
625
|
-
const newPath = [...
|
|
625
|
+
const newPath = [...path5];
|
|
626
626
|
newPath[adjustmentIndex] += count;
|
|
627
627
|
return newPath;
|
|
628
628
|
} else if (operation === "remove") {
|
|
629
629
|
if (otherPathValue === pathValue) {
|
|
630
630
|
return void 0;
|
|
631
631
|
} else if (otherPathValue < pathValue) {
|
|
632
|
-
const newPath = [...
|
|
632
|
+
const newPath = [...path5];
|
|
633
633
|
newPath[adjustmentIndex] -= count;
|
|
634
634
|
return newPath;
|
|
635
635
|
}
|
|
636
636
|
}
|
|
637
|
-
return
|
|
637
|
+
return path5;
|
|
638
638
|
}
|
|
639
639
|
}
|
|
640
640
|
});
|
|
@@ -800,15 +800,15 @@ var require_operation = __commonJS({
|
|
|
800
800
|
switch (operation.type) {
|
|
801
801
|
case "insert": {
|
|
802
802
|
const otherPath = parentPath.concat(operation.index);
|
|
803
|
-
return transformedPaths.map((
|
|
803
|
+
return transformedPaths.map((path5) => path5 ? (0, transformPath_1.transformPath)(path5, "insert", otherPath, operation.nodes.length) : void 0);
|
|
804
804
|
}
|
|
805
805
|
case "remove": {
|
|
806
806
|
const otherPaths = [...operation.indexes].reverse().map((index) => parentPath.concat(index));
|
|
807
|
-
return transformedPaths.map((
|
|
807
|
+
return transformedPaths.map((path5) => {
|
|
808
808
|
for (const otherPath of otherPaths) {
|
|
809
|
-
|
|
809
|
+
path5 = path5 ? (0, transformPath_1.transformPath)(path5, "remove", otherPath) : void 0;
|
|
810
810
|
}
|
|
811
|
-
return
|
|
811
|
+
return path5;
|
|
812
812
|
});
|
|
813
813
|
}
|
|
814
814
|
case "removeThenInsert": {
|
|
@@ -945,22 +945,22 @@ var require_splice = __commonJS({
|
|
|
945
945
|
return _spliceWithPathTracking(node, options);
|
|
946
946
|
}
|
|
947
947
|
function _spliceWithPathTracking(node, options) {
|
|
948
|
-
const { path:
|
|
949
|
-
if (
|
|
948
|
+
const { path: path5, deleteCount = 0, nodes, track } = options;
|
|
949
|
+
if (path5.length === 0) {
|
|
950
950
|
throw new Error(`Can't splice at the root`);
|
|
951
951
|
}
|
|
952
|
-
const pathsToRemove = getPathsToRemove(
|
|
953
|
-
const operations = (0, operation_1.getInsertionOperations)(
|
|
952
|
+
const pathsToRemove = getPathsToRemove(path5, deleteCount);
|
|
953
|
+
const operations = (0, operation_1.getInsertionOperations)(path5, nodes, (0, operation_1.getRemovalOperations)(pathsToRemove));
|
|
954
954
|
const transformedPaths = track ? (0, operation_1.transformPathsByOperations)(track, operations) : [];
|
|
955
955
|
return {
|
|
956
956
|
node: (0, operation_1.applyOperations)(node, operations, options),
|
|
957
957
|
paths: transformedPaths
|
|
958
958
|
};
|
|
959
959
|
}
|
|
960
|
-
function getPathsToRemove(
|
|
960
|
+
function getPathsToRemove(path5, deleteCount) {
|
|
961
961
|
let pathsToRemove = [];
|
|
962
|
-
let parentPath =
|
|
963
|
-
let index =
|
|
962
|
+
let parentPath = path5.slice(0, -1);
|
|
963
|
+
let index = path5[path5.length - 1];
|
|
964
964
|
for (let i = 0; i < deleteCount; i++) {
|
|
965
965
|
pathsToRemove.push(parentPath.concat(index + i));
|
|
966
966
|
}
|
|
@@ -1110,6 +1110,7 @@ import {
|
|
|
1110
1110
|
FileExplorerEmptyState,
|
|
1111
1111
|
FileExplorerLayout,
|
|
1112
1112
|
FileExplorerUploadButton,
|
|
1113
|
+
formatByteSize,
|
|
1113
1114
|
MediaThumbnail
|
|
1114
1115
|
} from "@noya-app/noya-designsystem";
|
|
1115
1116
|
import {
|
|
@@ -1227,7 +1228,7 @@ var createMediaItemTree = (mediaMap) => {
|
|
|
1227
1228
|
};
|
|
1228
1229
|
|
|
1229
1230
|
// src/MediaCollection.tsx
|
|
1230
|
-
import { path as
|
|
1231
|
+
import { path as path4 } from "imfs";
|
|
1231
1232
|
import React from "react";
|
|
1232
1233
|
|
|
1233
1234
|
// src/utils/files.ts
|
|
@@ -1250,6 +1251,9 @@ var getVisibleItems = ({
|
|
|
1250
1251
|
}
|
|
1251
1252
|
return;
|
|
1252
1253
|
}
|
|
1254
|
+
if (item.kind === "noyaFile" && fileKindFilter === "all") {
|
|
1255
|
+
filteredItems.push(item);
|
|
1256
|
+
}
|
|
1253
1257
|
if (item.kind === "file" && fileKindFilter === "all") {
|
|
1254
1258
|
filteredItems.push(item);
|
|
1255
1259
|
}
|
|
@@ -1286,7 +1290,7 @@ var movePathsIntoTarget = ({
|
|
|
1286
1290
|
tree
|
|
1287
1291
|
}) => {
|
|
1288
1292
|
const ancestors = (0, import_tree_visit2.ancestorPaths)(
|
|
1289
|
-
sourceItemPaths.map((
|
|
1293
|
+
sourceItemPaths.map((path5) => path5.split("/"))
|
|
1290
1294
|
);
|
|
1291
1295
|
const mediaClone = { ...media };
|
|
1292
1296
|
for (const ancestor of ancestors) {
|
|
@@ -1333,7 +1337,7 @@ var moveUpAFolder = ({
|
|
|
1333
1337
|
);
|
|
1334
1338
|
const grandparentFolderPath = tree.idToPathMap.get(grandparentFolder.id);
|
|
1335
1339
|
if (!grandparentFolderPath) return;
|
|
1336
|
-
const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((
|
|
1340
|
+
const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path5) => Boolean(path5));
|
|
1337
1341
|
return movePathsIntoTarget({
|
|
1338
1342
|
media,
|
|
1339
1343
|
targetItemPath: grandparentFolderPath,
|
|
@@ -1399,7 +1403,7 @@ var moveMediaInsideFolder = ({
|
|
|
1399
1403
|
}) => {
|
|
1400
1404
|
const targetItemPath = tree.idToPathMap.get(targetItemId);
|
|
1401
1405
|
if (!targetItemPath) return media;
|
|
1402
|
-
const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((
|
|
1406
|
+
const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path5) => Boolean(path5));
|
|
1403
1407
|
return movePathsIntoTarget({
|
|
1404
1408
|
media,
|
|
1405
1409
|
sourceItemPaths,
|
|
@@ -1440,6 +1444,115 @@ var renameMediaItemAndDescendantPaths = ({
|
|
|
1440
1444
|
return mediaClone;
|
|
1441
1445
|
};
|
|
1442
1446
|
|
|
1447
|
+
// src/utils/handleFileDrop.ts
|
|
1448
|
+
import { path as path3 } from "imfs";
|
|
1449
|
+
function isDirectoryEntry(entry) {
|
|
1450
|
+
return entry.isDirectory;
|
|
1451
|
+
}
|
|
1452
|
+
function isFileEntry(entry) {
|
|
1453
|
+
return entry.isFile;
|
|
1454
|
+
}
|
|
1455
|
+
async function handleDataTransfer({
|
|
1456
|
+
dataTransfer,
|
|
1457
|
+
rootItemPath,
|
|
1458
|
+
media,
|
|
1459
|
+
uploadAsset
|
|
1460
|
+
}) {
|
|
1461
|
+
try {
|
|
1462
|
+
const dataTransferItems = Array.from(dataTransfer.items ?? []);
|
|
1463
|
+
const supportsEntries = dataTransferItems.some(
|
|
1464
|
+
(item) => typeof item?.webkitGetAsEntry === "function"
|
|
1465
|
+
);
|
|
1466
|
+
const collectFromEntry = async (entry, basePath) => {
|
|
1467
|
+
if (!entry) return [];
|
|
1468
|
+
if (isFileEntry(entry)) {
|
|
1469
|
+
const file = await new Promise(
|
|
1470
|
+
(resolve) => entry.file((f) => resolve(f))
|
|
1471
|
+
);
|
|
1472
|
+
return [
|
|
1473
|
+
{
|
|
1474
|
+
file,
|
|
1475
|
+
relativePath: path3.join(basePath, file.name)
|
|
1476
|
+
}
|
|
1477
|
+
];
|
|
1478
|
+
}
|
|
1479
|
+
if (isDirectoryEntry(entry)) {
|
|
1480
|
+
const reader = entry.createReader();
|
|
1481
|
+
const readAll = async () => {
|
|
1482
|
+
const all = [];
|
|
1483
|
+
while (true) {
|
|
1484
|
+
const entries = await new Promise(
|
|
1485
|
+
(resolve) => reader.readEntries((ents) => resolve(ents))
|
|
1486
|
+
);
|
|
1487
|
+
if (!entries.length) break;
|
|
1488
|
+
all.push(...entries);
|
|
1489
|
+
}
|
|
1490
|
+
return all;
|
|
1491
|
+
};
|
|
1492
|
+
const children = await readAll();
|
|
1493
|
+
const results = await Promise.all(
|
|
1494
|
+
children.map(
|
|
1495
|
+
(child) => collectFromEntry(child, path3.join(basePath, entry.name))
|
|
1496
|
+
)
|
|
1497
|
+
);
|
|
1498
|
+
return results.flat();
|
|
1499
|
+
}
|
|
1500
|
+
return [];
|
|
1501
|
+
};
|
|
1502
|
+
let dropped = [];
|
|
1503
|
+
if (supportsEntries) {
|
|
1504
|
+
const topLevelEntries = dataTransferItems.flatMap((item) => {
|
|
1505
|
+
const entry = item.webkitGetAsEntry?.();
|
|
1506
|
+
if (!entry) return [];
|
|
1507
|
+
return [entry];
|
|
1508
|
+
});
|
|
1509
|
+
const nested = await Promise.all(
|
|
1510
|
+
topLevelEntries.map((entry) => collectFromEntry(entry, ""))
|
|
1511
|
+
);
|
|
1512
|
+
dropped = nested.flat();
|
|
1513
|
+
} else {
|
|
1514
|
+
const files = Array.from(dataTransfer.files);
|
|
1515
|
+
if (files.length === 0) return;
|
|
1516
|
+
dropped = files.map((file) => ({
|
|
1517
|
+
file,
|
|
1518
|
+
// Best effort: try webkitRelativePath; fall back to name
|
|
1519
|
+
relativePath: file.webkitRelativePath && file.webkitRelativePath.length > 0 ? file.webkitRelativePath : file.name
|
|
1520
|
+
}));
|
|
1521
|
+
}
|
|
1522
|
+
if (dropped.length === 0) return;
|
|
1523
|
+
const folderRelativePaths = /* @__PURE__ */ new Set();
|
|
1524
|
+
for (const { relativePath } of dropped) {
|
|
1525
|
+
const dir = path3.dirname(relativePath);
|
|
1526
|
+
if (dir && dir !== ".") {
|
|
1527
|
+
const parts = dir.split("/").filter(Boolean);
|
|
1528
|
+
let acc = "";
|
|
1529
|
+
for (const part of parts) {
|
|
1530
|
+
acc = acc ? path3.join(acc, part) : part;
|
|
1531
|
+
folderRelativePaths.add(acc);
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
const folderEntries = Array.from(folderRelativePaths).map((rel) => path3.join(rootItemPath, rel)).filter((full) => !media[full]).map((full) => [full, createMediaFolder()]);
|
|
1536
|
+
const uploadResults = await Promise.all(
|
|
1537
|
+
dropped.map(
|
|
1538
|
+
async ({ file, relativePath }) => {
|
|
1539
|
+
const asset = await uploadAsset(file);
|
|
1540
|
+
return [
|
|
1541
|
+
path3.join(rootItemPath, relativePath),
|
|
1542
|
+
createMediaAsset({ assetId: asset.id })
|
|
1543
|
+
];
|
|
1544
|
+
}
|
|
1545
|
+
)
|
|
1546
|
+
);
|
|
1547
|
+
return {
|
|
1548
|
+
...media,
|
|
1549
|
+
...Object.fromEntries([...folderEntries, ...uploadResults])
|
|
1550
|
+
};
|
|
1551
|
+
} catch (error) {
|
|
1552
|
+
console.error("Failed to upload dropped files:", error);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1443
1556
|
// src/MediaCollection.tsx
|
|
1444
1557
|
var extensionToContentType = {
|
|
1445
1558
|
svg: "image/svg+xml",
|
|
@@ -1447,7 +1560,7 @@ var extensionToContentType = {
|
|
|
1447
1560
|
jpeg: "image/jpeg"
|
|
1448
1561
|
};
|
|
1449
1562
|
function encodeFileContentForThumbnail(pathProp, item) {
|
|
1450
|
-
const extension =
|
|
1563
|
+
const extension = path4.extname(pathProp).slice(1);
|
|
1451
1564
|
const contentType = extensionToContentType[extension];
|
|
1452
1565
|
if (contentType) {
|
|
1453
1566
|
if (item.encoding === "base64") {
|
|
@@ -1474,7 +1587,8 @@ var MediaThumbnailInternal = memoGeneric(
|
|
|
1474
1587
|
item,
|
|
1475
1588
|
selected,
|
|
1476
1589
|
size,
|
|
1477
|
-
path: pathProp
|
|
1590
|
+
path: pathProp,
|
|
1591
|
+
renderThumbnailIcon
|
|
1478
1592
|
}) => {
|
|
1479
1593
|
const asset = useAsset(item.kind === "asset" ? item.assetId : void 0);
|
|
1480
1594
|
const isRoot = item.id === rootMediaItem.id;
|
|
@@ -1492,7 +1606,7 @@ var MediaThumbnailInternal = memoGeneric(
|
|
|
1492
1606
|
url = encoded.url;
|
|
1493
1607
|
}
|
|
1494
1608
|
}
|
|
1495
|
-
const fileName = pathProp ?
|
|
1609
|
+
const fileName = pathProp ? path4.basename(pathProp) : void 0;
|
|
1496
1610
|
return /* @__PURE__ */ React.createElement(
|
|
1497
1611
|
MediaThumbnail,
|
|
1498
1612
|
{
|
|
@@ -1501,7 +1615,8 @@ var MediaThumbnailInternal = memoGeneric(
|
|
|
1501
1615
|
url,
|
|
1502
1616
|
selected,
|
|
1503
1617
|
size,
|
|
1504
|
-
fileName
|
|
1618
|
+
fileName,
|
|
1619
|
+
renderThumbnailIcon
|
|
1505
1620
|
}
|
|
1506
1621
|
);
|
|
1507
1622
|
}
|
|
@@ -1532,7 +1647,10 @@ var MediaCollection = memo(
|
|
|
1532
1647
|
scrollable = false,
|
|
1533
1648
|
sortable = false,
|
|
1534
1649
|
renderEmptyState,
|
|
1535
|
-
sharedDragProps
|
|
1650
|
+
sharedDragProps,
|
|
1651
|
+
onClickItem,
|
|
1652
|
+
renderThumbnailIcon,
|
|
1653
|
+
onDidDeleteItems
|
|
1536
1654
|
}, ref) {
|
|
1537
1655
|
const setMedia = useCallback(
|
|
1538
1656
|
(...args) => {
|
|
@@ -1614,14 +1732,14 @@ var MediaCollection = memo(
|
|
|
1614
1732
|
const itemPath = tree.idToPathMap.get(item.id);
|
|
1615
1733
|
const firstSelectedPath = tree.idToPathMap.get(selectedIds[0]);
|
|
1616
1734
|
if (!itemPath || !firstSelectedPath) return false;
|
|
1617
|
-
return itemPath.startsWith(
|
|
1735
|
+
return itemPath.startsWith(path4.dirname(firstSelectedPath));
|
|
1618
1736
|
});
|
|
1619
1737
|
useEffect(() => {
|
|
1620
1738
|
if (initialExpanded) {
|
|
1621
1739
|
setExpandedMap(initialExpanded);
|
|
1622
1740
|
}
|
|
1623
1741
|
}, [initialExpanded]);
|
|
1624
|
-
const
|
|
1742
|
+
const getExpanded = useCallback(
|
|
1625
1743
|
(item) => {
|
|
1626
1744
|
if (!expandable) return void 0;
|
|
1627
1745
|
if (item.kind !== "folder") return void 0;
|
|
@@ -1632,6 +1750,14 @@ var MediaCollection = memo(
|
|
|
1632
1750
|
);
|
|
1633
1751
|
const handleDelete = useCallback(
|
|
1634
1752
|
(selectedIds2) => {
|
|
1753
|
+
const deletedItems = Object.entries(media).flatMap(
|
|
1754
|
+
([path5, item]) => {
|
|
1755
|
+
if (selectedIds2.includes(item.id)) {
|
|
1756
|
+
return [[path5, item]];
|
|
1757
|
+
}
|
|
1758
|
+
return [];
|
|
1759
|
+
}
|
|
1760
|
+
);
|
|
1635
1761
|
const newMedia = deleteMediaItems({
|
|
1636
1762
|
selectedIds: selectedIds2,
|
|
1637
1763
|
media,
|
|
@@ -1639,8 +1765,9 @@ var MediaCollection = memo(
|
|
|
1639
1765
|
});
|
|
1640
1766
|
setSelectedIds([rootMediaItem.id]);
|
|
1641
1767
|
setMedia({ name: "Delete items", timestamp: Date.now() }, newMedia);
|
|
1768
|
+
onDidDeleteItems?.(deletedItems);
|
|
1642
1769
|
},
|
|
1643
|
-
[media, setMedia, setSelectedIds, tree]
|
|
1770
|
+
[media, setMedia, setSelectedIds, tree, onDidDeleteItems]
|
|
1644
1771
|
);
|
|
1645
1772
|
const onRename = useCallback(
|
|
1646
1773
|
(selectedItem, newName) => {
|
|
@@ -1678,7 +1805,7 @@ var MediaCollection = memo(
|
|
|
1678
1805
|
const currentFolderPath = tree.idToPathMap.get(currentFolderId);
|
|
1679
1806
|
if (!currentFolderPath) return;
|
|
1680
1807
|
setTempItem([
|
|
1681
|
-
|
|
1808
|
+
path4.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
|
|
1682
1809
|
newFolder
|
|
1683
1810
|
]);
|
|
1684
1811
|
setTimeout(() => {
|
|
@@ -1698,7 +1825,7 @@ var MediaCollection = memo(
|
|
|
1698
1825
|
);
|
|
1699
1826
|
if (!currentFolderPath) return;
|
|
1700
1827
|
setTempItem([
|
|
1701
|
-
|
|
1828
|
+
path4.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
|
|
1702
1829
|
newFile
|
|
1703
1830
|
]);
|
|
1704
1831
|
setTimeout(() => {
|
|
@@ -1719,6 +1846,7 @@ var MediaCollection = memo(
|
|
|
1719
1846
|
},
|
|
1720
1847
|
[media, tree, setMedia]
|
|
1721
1848
|
);
|
|
1849
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
1722
1850
|
const handleUpload = useCallback(
|
|
1723
1851
|
async (selectedId) => {
|
|
1724
1852
|
try {
|
|
@@ -1728,12 +1856,13 @@ var MediaCollection = memo(
|
|
|
1728
1856
|
if (!parentPath) return;
|
|
1729
1857
|
const uploadPromises = files.map(async (file) => {
|
|
1730
1858
|
const asset = await assetManager.create(file);
|
|
1731
|
-
const assetPath =
|
|
1859
|
+
const assetPath = path4.join(parentPath, path4.basename(file.name));
|
|
1732
1860
|
return {
|
|
1733
1861
|
assetPath,
|
|
1734
1862
|
asset: createMediaAsset({ assetId: asset.id })
|
|
1735
1863
|
};
|
|
1736
1864
|
});
|
|
1865
|
+
setIsUploading(true);
|
|
1737
1866
|
const newMediaMap = await Promise.all(uploadPromises);
|
|
1738
1867
|
setMedia(
|
|
1739
1868
|
{ name: "Add media items", timestamp: Date.now() },
|
|
@@ -1746,6 +1875,8 @@ var MediaCollection = memo(
|
|
|
1746
1875
|
);
|
|
1747
1876
|
} catch (error) {
|
|
1748
1877
|
console.error("Failed to upload files:", error);
|
|
1878
|
+
} finally {
|
|
1879
|
+
setIsUploading(false);
|
|
1749
1880
|
}
|
|
1750
1881
|
},
|
|
1751
1882
|
[tree.idToPathMap, setMedia, media, assetManager]
|
|
@@ -1805,9 +1936,6 @@ var MediaCollection = memo(
|
|
|
1805
1936
|
);
|
|
1806
1937
|
const handleMoveMediaInsideFolder = useCallback(
|
|
1807
1938
|
(sourceItem, targetItem) => {
|
|
1808
|
-
const sourceItemPath = tree.idToPathMap.get(sourceItem.id);
|
|
1809
|
-
const targetItemPath = tree.idToPathMap.get(targetItem.id);
|
|
1810
|
-
if (!sourceItemPath || !targetItemPath) return;
|
|
1811
1939
|
const newMedia = moveMediaInsideFolder({
|
|
1812
1940
|
sourceItemIds: [sourceItem.id],
|
|
1813
1941
|
targetItemId: targetItem.id,
|
|
@@ -1845,12 +1973,12 @@ var MediaCollection = memo(
|
|
|
1845
1973
|
],
|
|
1846
1974
|
[
|
|
1847
1975
|
onlySingleFolderSelected && {
|
|
1848
|
-
title: "
|
|
1976
|
+
title: "Upload Files",
|
|
1849
1977
|
value: "upload",
|
|
1850
1978
|
icon: /* @__PURE__ */ React.createElement(UploadIcon, null)
|
|
1851
1979
|
},
|
|
1852
1980
|
onlySingleFolderSelected && {
|
|
1853
|
-
title: "Add
|
|
1981
|
+
title: "Add Folder",
|
|
1854
1982
|
value: "addFolder",
|
|
1855
1983
|
icon: /* @__PURE__ */ React.createElement(FolderIcon, null)
|
|
1856
1984
|
},
|
|
@@ -1974,7 +2102,8 @@ var MediaCollection = memo(
|
|
|
1974
2102
|
moveUpAFolder: handleMoveUpAFolder,
|
|
1975
2103
|
replace: handleReplace,
|
|
1976
2104
|
preview: handlePreview,
|
|
1977
|
-
moveMediaInsideFolder: handleMoveMediaInsideFolder
|
|
2105
|
+
moveMediaInsideFolder: handleMoveMediaInsideFolder,
|
|
2106
|
+
getItemAtIndex: (index) => visibleItems[index]
|
|
1978
2107
|
}));
|
|
1979
2108
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
1980
2109
|
FileExplorerLayout,
|
|
@@ -1984,7 +2113,8 @@ var MediaCollection = memo(
|
|
|
1984
2113
|
FileExplorerUploadButton,
|
|
1985
2114
|
{
|
|
1986
2115
|
showUploadButton,
|
|
1987
|
-
onUpload: () => handleUpload(rootMediaItem.id)
|
|
2116
|
+
onUpload: () => handleUpload(rootMediaItem.id),
|
|
2117
|
+
isUploading
|
|
1988
2118
|
},
|
|
1989
2119
|
right
|
|
1990
2120
|
),
|
|
@@ -2015,10 +2145,11 @@ var MediaCollection = memo(
|
|
|
2015
2145
|
return "Enter folder name";
|
|
2016
2146
|
case "asset":
|
|
2017
2147
|
case "file":
|
|
2148
|
+
case "noyaFile":
|
|
2018
2149
|
return "Enter file name";
|
|
2019
2150
|
}
|
|
2020
2151
|
},
|
|
2021
|
-
getExpanded
|
|
2152
|
+
getExpanded,
|
|
2022
2153
|
setExpanded: handleSetExpanded,
|
|
2023
2154
|
getRenamable: (item) => {
|
|
2024
2155
|
if (item.id === rootMediaItem.id) return false;
|
|
@@ -2028,6 +2159,7 @@ var MediaCollection = memo(
|
|
|
2028
2159
|
menuItems: assetContextMenuItems,
|
|
2029
2160
|
onSelectMenuItem: handleMenuAction,
|
|
2030
2161
|
onSelectionChange: setSelectedIds,
|
|
2162
|
+
onClickItem,
|
|
2031
2163
|
onDoubleClickItem,
|
|
2032
2164
|
onRename,
|
|
2033
2165
|
renamable,
|
|
@@ -2036,7 +2168,8 @@ var MediaCollection = memo(
|
|
|
2036
2168
|
MediaThumbnailInternal,
|
|
2037
2169
|
{
|
|
2038
2170
|
...props,
|
|
2039
|
-
path: tree.idToPathMap.get(props.item.id)
|
|
2171
|
+
path: tree.idToPathMap.get(props.item.id),
|
|
2172
|
+
renderThumbnailIcon
|
|
2040
2173
|
}
|
|
2041
2174
|
),
|
|
2042
2175
|
renderAction,
|
|
@@ -2044,7 +2177,7 @@ var MediaCollection = memo(
|
|
|
2044
2177
|
if (file.kind !== "asset") return null;
|
|
2045
2178
|
const asset = assets.find((a) => a.id === file.assetId);
|
|
2046
2179
|
if (!asset) return null;
|
|
2047
|
-
return /* @__PURE__ */ React.createElement(FileExplorerDetail, { selected, size }, (asset.size
|
|
2180
|
+
return /* @__PURE__ */ React.createElement(FileExplorerDetail, { selected, size }, formatByteSize(asset.size));
|
|
2048
2181
|
},
|
|
2049
2182
|
renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ React.createElement(FileExplorerEmptyState, null),
|
|
2050
2183
|
itemRoleDescription: "clickable file item",
|
|
@@ -2065,26 +2198,28 @@ var MediaCollection = memo(
|
|
|
2065
2198
|
if (sourceListId !== targetListId) {
|
|
2066
2199
|
return false;
|
|
2067
2200
|
}
|
|
2068
|
-
|
|
2069
|
-
const targetItem = visibleItems[targetIndex];
|
|
2070
|
-
if (position !== "inside" || targetItem.kind === "asset") {
|
|
2201
|
+
if (sourceListId !== sortableId || targetListId !== sortableId) {
|
|
2071
2202
|
return false;
|
|
2072
2203
|
}
|
|
2073
|
-
const
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
);
|
|
2081
|
-
if (!sourcePath || !targetPath) return false;
|
|
2082
|
-
if (isDeepEqual(sourcePath, targetPath.slice(0, sourcePath.length))) {
|
|
2083
|
-
return false;
|
|
2084
|
-
}
|
|
2085
|
-
return true;
|
|
2204
|
+
const sourceItem = visibleItems[sourceIndex];
|
|
2205
|
+
const targetItem = visibleItems[targetIndex];
|
|
2206
|
+
return acceptsMediaItemDrop({
|
|
2207
|
+
position,
|
|
2208
|
+
sourceItem,
|
|
2209
|
+
targetItem,
|
|
2210
|
+
tree
|
|
2211
|
+
});
|
|
2086
2212
|
},
|
|
2087
|
-
onMoveItem: ({
|
|
2213
|
+
onMoveItem: ({
|
|
2214
|
+
sourceListId,
|
|
2215
|
+
sourceIndex,
|
|
2216
|
+
targetListId,
|
|
2217
|
+
targetIndex,
|
|
2218
|
+
position
|
|
2219
|
+
}) => {
|
|
2220
|
+
if (sourceListId !== sortableId || targetListId !== sortableId) {
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2088
2223
|
const sourceItem = visibleItems[sourceIndex];
|
|
2089
2224
|
const targetItem = visibleItems[targetIndex];
|
|
2090
2225
|
if (position === "inside") {
|
|
@@ -2093,45 +2228,48 @@ var MediaCollection = memo(
|
|
|
2093
2228
|
},
|
|
2094
2229
|
onFilesDrop: async (event) => {
|
|
2095
2230
|
event.preventDefault();
|
|
2096
|
-
const
|
|
2097
|
-
if (
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
const rootItemPath = tree.idToPathMap.get(rootItemId);
|
|
2110
|
-
if (!rootItemPath) return;
|
|
2111
|
-
setMedia(
|
|
2112
|
-
{ name: "Add media files", timestamp: Date.now() },
|
|
2113
|
-
{
|
|
2114
|
-
...media,
|
|
2115
|
-
...Object.fromEntries(
|
|
2116
|
-
newMediaItems.map((item) => [
|
|
2117
|
-
path3.join(rootItemPath, item.name),
|
|
2118
|
-
item.asset
|
|
2119
|
-
])
|
|
2120
|
-
)
|
|
2121
|
-
}
|
|
2122
|
-
);
|
|
2123
|
-
} catch (error) {
|
|
2124
|
-
console.error("Failed to upload dropped files:", error);
|
|
2125
|
-
}
|
|
2231
|
+
const rootItemPath = tree.idToPathMap.get(rootItemId);
|
|
2232
|
+
if (!rootItemPath) return;
|
|
2233
|
+
const newMedia = await handleDataTransfer({
|
|
2234
|
+
dataTransfer: event.dataTransfer,
|
|
2235
|
+
rootItemPath,
|
|
2236
|
+
media,
|
|
2237
|
+
uploadAsset: (file) => assetManager.create(file)
|
|
2238
|
+
});
|
|
2239
|
+
if (!newMedia) return;
|
|
2240
|
+
setMedia(
|
|
2241
|
+
{ name: "Add media files", timestamp: Date.now() },
|
|
2242
|
+
newMedia
|
|
2243
|
+
);
|
|
2126
2244
|
}
|
|
2127
2245
|
}
|
|
2128
2246
|
)
|
|
2129
2247
|
));
|
|
2130
2248
|
})
|
|
2131
2249
|
);
|
|
2250
|
+
function acceptsMediaItemDrop(parameters) {
|
|
2251
|
+
const { position, sourceItem, targetItem, tree } = parameters;
|
|
2252
|
+
if (position !== "inside" || targetItem.kind === "asset") {
|
|
2253
|
+
return false;
|
|
2254
|
+
}
|
|
2255
|
+
const sourcePath = tree.findPath(
|
|
2256
|
+
rootMediaItem,
|
|
2257
|
+
(item) => item.id === sourceItem.id
|
|
2258
|
+
);
|
|
2259
|
+
const targetPath = tree.findPath(
|
|
2260
|
+
rootMediaItem,
|
|
2261
|
+
(item) => item.id === targetItem.id
|
|
2262
|
+
);
|
|
2263
|
+
if (!sourcePath || !targetPath) return false;
|
|
2264
|
+
if (isDeepEqual(sourcePath, targetPath.slice(0, sourcePath.length))) {
|
|
2265
|
+
return false;
|
|
2266
|
+
}
|
|
2267
|
+
return true;
|
|
2268
|
+
}
|
|
2132
2269
|
export {
|
|
2133
2270
|
MediaCollection,
|
|
2134
2271
|
PLACEHOLDER_ITEM_NAME,
|
|
2272
|
+
acceptsMediaItemDrop,
|
|
2135
2273
|
basenameValidator,
|
|
2136
2274
|
createMediaAsset,
|
|
2137
2275
|
createMediaFile,
|