@noya-app/noya-file-explorer 0.0.15 → 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/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 path4 = indexPath.slice();
42
- while (path4.length > 0) {
43
- let index = path4.shift();
44
- const children = options.getChildren(node, path4);
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 path4 = indexPath.slice();
57
+ let path5 = indexPath.slice();
58
58
  let result = [node];
59
- while (path4.length > 0) {
60
- let index = path4.shift();
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, path4, context);
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 path4 = indexPath.slice();
78
- while (path4.length > 0) {
79
- let index = path4.shift();
80
- node = options.getChildren(node, path4)[index];
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 path4 = indexPath.slice();
85
+ let path5 = indexPath.slice();
86
86
  let result = [node];
87
- while (path4.length > 0) {
88
- let index = path4.shift();
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, path4, context)[index];
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(path4, otherPath) {
605
- const length = Math.min(path4.length, otherPath.length);
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 (path4[i] !== otherPath[i]) {
608
- return path4.slice(0, i);
607
+ if (path5[i] !== otherPath[i]) {
608
+ return path5.slice(0, i);
609
609
  }
610
610
  }
611
- return path4.slice(0, length);
611
+ return path5.slice(0, length);
612
612
  }
613
- function transformPath(path4, operation, otherPath, count = 1) {
614
- if (otherPath.length > path4.length || (0, sort_1.comparePathsByComponent)(otherPath, path4) > 0) {
615
- return path4;
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(path4, otherPath);
621
- const adjustmentIndex = common.length === path4.length || common.length === otherPath.length ? common.length - 1 : common.length;
622
- const pathValue = path4[adjustmentIndex];
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 = [...path4];
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 = [...path4];
632
+ const newPath = [...path5];
633
633
  newPath[adjustmentIndex] -= count;
634
634
  return newPath;
635
635
  }
636
636
  }
637
- return path4;
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((path4) => path4 ? (0, transformPath_1.transformPath)(path4, "insert", otherPath, operation.nodes.length) : void 0);
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((path4) => {
807
+ return transformedPaths.map((path5) => {
808
808
  for (const otherPath of otherPaths) {
809
- path4 = path4 ? (0, transformPath_1.transformPath)(path4, "remove", otherPath) : void 0;
809
+ path5 = path5 ? (0, transformPath_1.transformPath)(path5, "remove", otherPath) : void 0;
810
810
  }
811
- return path4;
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: path4, deleteCount = 0, nodes, track } = options;
949
- if (path4.length === 0) {
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(path4, deleteCount);
953
- const operations = (0, operation_1.getInsertionOperations)(path4, nodes, (0, operation_1.getRemovalOperations)(pathsToRemove));
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(path4, deleteCount) {
960
+ function getPathsToRemove(path5, deleteCount) {
961
961
  let pathsToRemove = [];
962
- let parentPath = path4.slice(0, -1);
963
- let index = path4[path4.length - 1];
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
  }
@@ -1100,15 +1100,6 @@ var require_lib = __commonJS({
1100
1100
  }
1101
1101
  });
1102
1102
 
1103
- // src/formatByteSize.ts
1104
- var byteSizeUnits = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1105
- function formatByteSize(size) {
1106
- const unitIndex = Math.floor(Math.log(size) / Math.log(1024));
1107
- const unit = byteSizeUnits[unitIndex];
1108
- const value = size / Math.pow(1024, unitIndex);
1109
- return `${value.toFixed(1)} ${unit}`;
1110
- }
1111
-
1112
1103
  // src/MediaCollection.tsx
1113
1104
  import {
1114
1105
  ActionMenu,
@@ -1119,6 +1110,7 @@ import {
1119
1110
  FileExplorerEmptyState,
1120
1111
  FileExplorerLayout,
1121
1112
  FileExplorerUploadButton,
1113
+ formatByteSize,
1122
1114
  MediaThumbnail
1123
1115
  } from "@noya-app/noya-designsystem";
1124
1116
  import {
@@ -1236,7 +1228,7 @@ var createMediaItemTree = (mediaMap) => {
1236
1228
  };
1237
1229
 
1238
1230
  // src/MediaCollection.tsx
1239
- import { path as path3 } from "imfs";
1231
+ import { path as path4 } from "imfs";
1240
1232
  import React from "react";
1241
1233
 
1242
1234
  // src/utils/files.ts
@@ -1259,6 +1251,9 @@ var getVisibleItems = ({
1259
1251
  }
1260
1252
  return;
1261
1253
  }
1254
+ if (item.kind === "noyaFile" && fileKindFilter === "all") {
1255
+ filteredItems.push(item);
1256
+ }
1262
1257
  if (item.kind === "file" && fileKindFilter === "all") {
1263
1258
  filteredItems.push(item);
1264
1259
  }
@@ -1295,7 +1290,7 @@ var movePathsIntoTarget = ({
1295
1290
  tree
1296
1291
  }) => {
1297
1292
  const ancestors = (0, import_tree_visit2.ancestorPaths)(
1298
- sourceItemPaths.map((path4) => path4.split("/"))
1293
+ sourceItemPaths.map((path5) => path5.split("/"))
1299
1294
  );
1300
1295
  const mediaClone = { ...media };
1301
1296
  for (const ancestor of ancestors) {
@@ -1342,7 +1337,7 @@ var moveUpAFolder = ({
1342
1337
  );
1343
1338
  const grandparentFolderPath = tree.idToPathMap.get(grandparentFolder.id);
1344
1339
  if (!grandparentFolderPath) return;
1345
- const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path4) => Boolean(path4));
1340
+ const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path5) => Boolean(path5));
1346
1341
  return movePathsIntoTarget({
1347
1342
  media,
1348
1343
  targetItemPath: grandparentFolderPath,
@@ -1408,7 +1403,7 @@ var moveMediaInsideFolder = ({
1408
1403
  }) => {
1409
1404
  const targetItemPath = tree.idToPathMap.get(targetItemId);
1410
1405
  if (!targetItemPath) return media;
1411
- const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path4) => Boolean(path4));
1406
+ const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path5) => Boolean(path5));
1412
1407
  return movePathsIntoTarget({
1413
1408
  media,
1414
1409
  sourceItemPaths,
@@ -1449,6 +1444,115 @@ var renameMediaItemAndDescendantPaths = ({
1449
1444
  return mediaClone;
1450
1445
  };
1451
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
+
1452
1556
  // src/MediaCollection.tsx
1453
1557
  var extensionToContentType = {
1454
1558
  svg: "image/svg+xml",
@@ -1456,7 +1560,7 @@ var extensionToContentType = {
1456
1560
  jpeg: "image/jpeg"
1457
1561
  };
1458
1562
  function encodeFileContentForThumbnail(pathProp, item) {
1459
- const extension = path3.extname(pathProp).slice(1);
1563
+ const extension = path4.extname(pathProp).slice(1);
1460
1564
  const contentType = extensionToContentType[extension];
1461
1565
  if (contentType) {
1462
1566
  if (item.encoding === "base64") {
@@ -1483,7 +1587,8 @@ var MediaThumbnailInternal = memoGeneric(
1483
1587
  item,
1484
1588
  selected,
1485
1589
  size,
1486
- path: pathProp
1590
+ path: pathProp,
1591
+ renderThumbnailIcon
1487
1592
  }) => {
1488
1593
  const asset = useAsset(item.kind === "asset" ? item.assetId : void 0);
1489
1594
  const isRoot = item.id === rootMediaItem.id;
@@ -1501,7 +1606,7 @@ var MediaThumbnailInternal = memoGeneric(
1501
1606
  url = encoded.url;
1502
1607
  }
1503
1608
  }
1504
- const fileName = pathProp ? path3.basename(pathProp) : void 0;
1609
+ const fileName = pathProp ? path4.basename(pathProp) : void 0;
1505
1610
  return /* @__PURE__ */ React.createElement(
1506
1611
  MediaThumbnail,
1507
1612
  {
@@ -1510,7 +1615,8 @@ var MediaThumbnailInternal = memoGeneric(
1510
1615
  url,
1511
1616
  selected,
1512
1617
  size,
1513
- fileName
1618
+ fileName,
1619
+ renderThumbnailIcon
1514
1620
  }
1515
1621
  );
1516
1622
  }
@@ -1542,7 +1648,9 @@ var MediaCollection = memo(
1542
1648
  sortable = false,
1543
1649
  renderEmptyState,
1544
1650
  sharedDragProps,
1545
- onClickItem
1651
+ onClickItem,
1652
+ renderThumbnailIcon,
1653
+ onDidDeleteItems
1546
1654
  }, ref) {
1547
1655
  const setMedia = useCallback(
1548
1656
  (...args) => {
@@ -1624,7 +1732,7 @@ var MediaCollection = memo(
1624
1732
  const itemPath = tree.idToPathMap.get(item.id);
1625
1733
  const firstSelectedPath = tree.idToPathMap.get(selectedIds[0]);
1626
1734
  if (!itemPath || !firstSelectedPath) return false;
1627
- return itemPath.startsWith(path3.dirname(firstSelectedPath));
1735
+ return itemPath.startsWith(path4.dirname(firstSelectedPath));
1628
1736
  });
1629
1737
  useEffect(() => {
1630
1738
  if (initialExpanded) {
@@ -1642,6 +1750,14 @@ var MediaCollection = memo(
1642
1750
  );
1643
1751
  const handleDelete = useCallback(
1644
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
+ );
1645
1761
  const newMedia = deleteMediaItems({
1646
1762
  selectedIds: selectedIds2,
1647
1763
  media,
@@ -1649,8 +1765,9 @@ var MediaCollection = memo(
1649
1765
  });
1650
1766
  setSelectedIds([rootMediaItem.id]);
1651
1767
  setMedia({ name: "Delete items", timestamp: Date.now() }, newMedia);
1768
+ onDidDeleteItems?.(deletedItems);
1652
1769
  },
1653
- [media, setMedia, setSelectedIds, tree]
1770
+ [media, setMedia, setSelectedIds, tree, onDidDeleteItems]
1654
1771
  );
1655
1772
  const onRename = useCallback(
1656
1773
  (selectedItem, newName) => {
@@ -1688,7 +1805,7 @@ var MediaCollection = memo(
1688
1805
  const currentFolderPath = tree.idToPathMap.get(currentFolderId);
1689
1806
  if (!currentFolderPath) return;
1690
1807
  setTempItem([
1691
- path3.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1808
+ path4.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1692
1809
  newFolder
1693
1810
  ]);
1694
1811
  setTimeout(() => {
@@ -1708,7 +1825,7 @@ var MediaCollection = memo(
1708
1825
  );
1709
1826
  if (!currentFolderPath) return;
1710
1827
  setTempItem([
1711
- path3.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1828
+ path4.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1712
1829
  newFile
1713
1830
  ]);
1714
1831
  setTimeout(() => {
@@ -1739,7 +1856,7 @@ var MediaCollection = memo(
1739
1856
  if (!parentPath) return;
1740
1857
  const uploadPromises = files.map(async (file) => {
1741
1858
  const asset = await assetManager.create(file);
1742
- const assetPath = path3.join(parentPath, path3.basename(file.name));
1859
+ const assetPath = path4.join(parentPath, path4.basename(file.name));
1743
1860
  return {
1744
1861
  assetPath,
1745
1862
  asset: createMediaAsset({ assetId: asset.id })
@@ -1819,9 +1936,6 @@ var MediaCollection = memo(
1819
1936
  );
1820
1937
  const handleMoveMediaInsideFolder = useCallback(
1821
1938
  (sourceItem, targetItem) => {
1822
- const sourceItemPath = tree.idToPathMap.get(sourceItem.id);
1823
- const targetItemPath = tree.idToPathMap.get(targetItem.id);
1824
- if (!sourceItemPath || !targetItemPath) return;
1825
1939
  const newMedia = moveMediaInsideFolder({
1826
1940
  sourceItemIds: [sourceItem.id],
1827
1941
  targetItemId: targetItem.id,
@@ -1859,12 +1973,12 @@ var MediaCollection = memo(
1859
1973
  ],
1860
1974
  [
1861
1975
  onlySingleFolderSelected && {
1862
- title: "Add media",
1976
+ title: "Upload Files",
1863
1977
  value: "upload",
1864
1978
  icon: /* @__PURE__ */ React.createElement(UploadIcon, null)
1865
1979
  },
1866
1980
  onlySingleFolderSelected && {
1867
- title: "Add a Folder",
1981
+ title: "Add Folder",
1868
1982
  value: "addFolder",
1869
1983
  icon: /* @__PURE__ */ React.createElement(FolderIcon, null)
1870
1984
  },
@@ -1988,7 +2102,8 @@ var MediaCollection = memo(
1988
2102
  moveUpAFolder: handleMoveUpAFolder,
1989
2103
  replace: handleReplace,
1990
2104
  preview: handlePreview,
1991
- moveMediaInsideFolder: handleMoveMediaInsideFolder
2105
+ moveMediaInsideFolder: handleMoveMediaInsideFolder,
2106
+ getItemAtIndex: (index) => visibleItems[index]
1992
2107
  }));
1993
2108
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
1994
2109
  FileExplorerLayout,
@@ -2030,6 +2145,7 @@ var MediaCollection = memo(
2030
2145
  return "Enter folder name";
2031
2146
  case "asset":
2032
2147
  case "file":
2148
+ case "noyaFile":
2033
2149
  return "Enter file name";
2034
2150
  }
2035
2151
  },
@@ -2052,7 +2168,8 @@ var MediaCollection = memo(
2052
2168
  MediaThumbnailInternal,
2053
2169
  {
2054
2170
  ...props,
2055
- path: tree.idToPathMap.get(props.item.id)
2171
+ path: tree.idToPathMap.get(props.item.id),
2172
+ renderThumbnailIcon
2056
2173
  }
2057
2174
  ),
2058
2175
  renderAction,
@@ -2081,26 +2198,28 @@ var MediaCollection = memo(
2081
2198
  if (sourceListId !== targetListId) {
2082
2199
  return false;
2083
2200
  }
2084
- const sourceItem = visibleItems[sourceIndex];
2085
- const targetItem = visibleItems[targetIndex];
2086
- if (position !== "inside" || targetItem.kind === "asset") {
2087
- return false;
2088
- }
2089
- const sourcePath = tree.findPath(
2090
- rootMediaItem,
2091
- (item) => item.id === sourceItem.id
2092
- );
2093
- const targetPath = tree.findPath(
2094
- rootMediaItem,
2095
- (item) => item.id === targetItem.id
2096
- );
2097
- if (!sourcePath || !targetPath) return false;
2098
- if (isDeepEqual(sourcePath, targetPath.slice(0, sourcePath.length))) {
2201
+ if (sourceListId !== sortableId || targetListId !== sortableId) {
2099
2202
  return false;
2100
2203
  }
2101
- return true;
2204
+ const sourceItem = visibleItems[sourceIndex];
2205
+ const targetItem = visibleItems[targetIndex];
2206
+ return acceptsMediaItemDrop({
2207
+ position,
2208
+ sourceItem,
2209
+ targetItem,
2210
+ tree
2211
+ });
2102
2212
  },
2103
- onMoveItem: ({ sourceIndex, targetIndex, position }) => {
2213
+ onMoveItem: ({
2214
+ sourceListId,
2215
+ sourceIndex,
2216
+ targetListId,
2217
+ targetIndex,
2218
+ position
2219
+ }) => {
2220
+ if (sourceListId !== sortableId || targetListId !== sortableId) {
2221
+ return;
2222
+ }
2104
2223
  const sourceItem = visibleItems[sourceIndex];
2105
2224
  const targetItem = visibleItems[targetIndex];
2106
2225
  if (position === "inside") {
@@ -2109,45 +2228,48 @@ var MediaCollection = memo(
2109
2228
  },
2110
2229
  onFilesDrop: async (event) => {
2111
2230
  event.preventDefault();
2112
- const files = Array.from(event.dataTransfer.files);
2113
- if (files.length === 0) return;
2114
- try {
2115
- const uploadPromises = files.map(async (file) => {
2116
- const asset = await assetManager.create(file);
2117
- return {
2118
- asset: createMediaAsset({
2119
- assetId: asset.id
2120
- }),
2121
- name: file.name
2122
- };
2123
- });
2124
- const newMediaItems = await Promise.all(uploadPromises);
2125
- const rootItemPath = tree.idToPathMap.get(rootItemId);
2126
- if (!rootItemPath) return;
2127
- setMedia(
2128
- { name: "Add media files", timestamp: Date.now() },
2129
- {
2130
- ...media,
2131
- ...Object.fromEntries(
2132
- newMediaItems.map((item) => [
2133
- path3.join(rootItemPath, item.name),
2134
- item.asset
2135
- ])
2136
- )
2137
- }
2138
- );
2139
- } catch (error) {
2140
- console.error("Failed to upload dropped files:", error);
2141
- }
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
+ );
2142
2244
  }
2143
2245
  }
2144
2246
  )
2145
2247
  ));
2146
2248
  })
2147
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
+ }
2148
2269
  export {
2149
2270
  MediaCollection,
2150
2271
  PLACEHOLDER_ITEM_NAME,
2272
+ acceptsMediaItemDrop,
2151
2273
  basenameValidator,
2152
2274
  createMediaAsset,
2153
2275
  createMediaFile,
@@ -2155,7 +2277,6 @@ export {
2155
2277
  createMediaItem,
2156
2278
  createMediaItemTree,
2157
2279
  deleteMediaItems,
2158
- formatByteSize,
2159
2280
  getDepthMap,
2160
2281
  getParentDirectories,
2161
2282
  getVisibleItems,