@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/dist/index.js CHANGED
@@ -44,10 +44,10 @@ var require_access = __commonJS({
44
44
  const accessed = _getPath(node, indexPath, options);
45
45
  return accessed[accessed.length - 1];
46
46
  }
47
- let path4 = indexPath.slice();
48
- while (path4.length > 0) {
49
- let index = path4.shift();
50
- const children = options.getChildren(node, path4);
47
+ let path5 = indexPath.slice();
48
+ while (path5.length > 0) {
49
+ let index = path5.shift();
50
+ const children = options.getChildren(node, path5);
51
51
  const child = children[index];
52
52
  if (!child) {
53
53
  return void 0;
@@ -60,12 +60,12 @@ var require_access = __commonJS({
60
60
  return _getPath(node, indexPath, options).slice(0, -1);
61
61
  }
62
62
  function _getPath(node, indexPath, options) {
63
- let path4 = indexPath.slice();
63
+ let path5 = indexPath.slice();
64
64
  let result = [node];
65
- while (path4.length > 0) {
66
- let index = path4.shift();
65
+ while (path5.length > 0) {
66
+ let index = path5.shift();
67
67
  const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
68
- const children = options.getChildren(node, path4, context);
68
+ const children = options.getChildren(node, path5, context);
69
69
  const child = children[index];
70
70
  if (!child) {
71
71
  return result;
@@ -80,20 +80,20 @@ var require_access = __commonJS({
80
80
  const accessed = accessPath(node, indexPath, options);
81
81
  return accessed[accessed.length - 1];
82
82
  }
83
- let path4 = indexPath.slice();
84
- while (path4.length > 0) {
85
- let index = path4.shift();
86
- node = options.getChildren(node, path4)[index];
83
+ let path5 = indexPath.slice();
84
+ while (path5.length > 0) {
85
+ let index = path5.shift();
86
+ node = options.getChildren(node, path5)[index];
87
87
  }
88
88
  return node;
89
89
  }
90
90
  function accessPath(node, indexPath, options) {
91
- let path4 = indexPath.slice();
91
+ let path5 = indexPath.slice();
92
92
  let result = [node];
93
- while (path4.length > 0) {
94
- let index = path4.shift();
93
+ while (path5.length > 0) {
94
+ let index = path5.shift();
95
95
  const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
96
- node = options.getChildren(node, path4, context)[index];
96
+ node = options.getChildren(node, path5, context)[index];
97
97
  result.push(node);
98
98
  }
99
99
  return result;
@@ -607,40 +607,40 @@ var require_transformPath = __commonJS({
607
607
  Object.defineProperty(exports2, "__esModule", { value: true });
608
608
  exports2.transformPath = transformPath;
609
609
  var sort_1 = require_sort();
610
- function commonAncestor(path4, otherPath) {
611
- const length = Math.min(path4.length, otherPath.length);
610
+ function commonAncestor(path5, otherPath) {
611
+ const length = Math.min(path5.length, otherPath.length);
612
612
  for (let i = 0; i < length; i++) {
613
- if (path4[i] !== otherPath[i]) {
614
- return path4.slice(0, i);
613
+ if (path5[i] !== otherPath[i]) {
614
+ return path5.slice(0, i);
615
615
  }
616
616
  }
617
- return path4.slice(0, length);
617
+ return path5.slice(0, length);
618
618
  }
619
- function transformPath(path4, operation, otherPath, count = 1) {
620
- if (otherPath.length > path4.length || (0, sort_1.comparePathsByComponent)(otherPath, path4) > 0) {
621
- return path4;
619
+ function transformPath(path5, operation, otherPath, count = 1) {
620
+ if (otherPath.length > path5.length || (0, sort_1.comparePathsByComponent)(otherPath, path5) > 0) {
621
+ return path5;
622
622
  }
623
623
  if (otherPath.length === 0 && operation === "remove") {
624
624
  return void 0;
625
625
  }
626
- const common = commonAncestor(path4, otherPath);
627
- const adjustmentIndex = common.length === path4.length || common.length === otherPath.length ? common.length - 1 : common.length;
628
- const pathValue = path4[adjustmentIndex];
626
+ const common = commonAncestor(path5, otherPath);
627
+ const adjustmentIndex = common.length === path5.length || common.length === otherPath.length ? common.length - 1 : common.length;
628
+ const pathValue = path5[adjustmentIndex];
629
629
  const otherPathValue = otherPath[adjustmentIndex];
630
630
  if (operation === "insert" && otherPathValue <= pathValue) {
631
- const newPath = [...path4];
631
+ const newPath = [...path5];
632
632
  newPath[adjustmentIndex] += count;
633
633
  return newPath;
634
634
  } else if (operation === "remove") {
635
635
  if (otherPathValue === pathValue) {
636
636
  return void 0;
637
637
  } else if (otherPathValue < pathValue) {
638
- const newPath = [...path4];
638
+ const newPath = [...path5];
639
639
  newPath[adjustmentIndex] -= count;
640
640
  return newPath;
641
641
  }
642
642
  }
643
- return path4;
643
+ return path5;
644
644
  }
645
645
  }
646
646
  });
@@ -806,15 +806,15 @@ var require_operation = __commonJS({
806
806
  switch (operation.type) {
807
807
  case "insert": {
808
808
  const otherPath = parentPath.concat(operation.index);
809
- return transformedPaths.map((path4) => path4 ? (0, transformPath_1.transformPath)(path4, "insert", otherPath, operation.nodes.length) : void 0);
809
+ return transformedPaths.map((path5) => path5 ? (0, transformPath_1.transformPath)(path5, "insert", otherPath, operation.nodes.length) : void 0);
810
810
  }
811
811
  case "remove": {
812
812
  const otherPaths = [...operation.indexes].reverse().map((index) => parentPath.concat(index));
813
- return transformedPaths.map((path4) => {
813
+ return transformedPaths.map((path5) => {
814
814
  for (const otherPath of otherPaths) {
815
- path4 = path4 ? (0, transformPath_1.transformPath)(path4, "remove", otherPath) : void 0;
815
+ path5 = path5 ? (0, transformPath_1.transformPath)(path5, "remove", otherPath) : void 0;
816
816
  }
817
- return path4;
817
+ return path5;
818
818
  });
819
819
  }
820
820
  case "removeThenInsert": {
@@ -951,22 +951,22 @@ var require_splice = __commonJS({
951
951
  return _spliceWithPathTracking(node, options);
952
952
  }
953
953
  function _spliceWithPathTracking(node, options) {
954
- const { path: path4, deleteCount = 0, nodes, track } = options;
955
- if (path4.length === 0) {
954
+ const { path: path5, deleteCount = 0, nodes, track } = options;
955
+ if (path5.length === 0) {
956
956
  throw new Error(`Can't splice at the root`);
957
957
  }
958
- const pathsToRemove = getPathsToRemove(path4, deleteCount);
959
- const operations = (0, operation_1.getInsertionOperations)(path4, nodes, (0, operation_1.getRemovalOperations)(pathsToRemove));
958
+ const pathsToRemove = getPathsToRemove(path5, deleteCount);
959
+ const operations = (0, operation_1.getInsertionOperations)(path5, nodes, (0, operation_1.getRemovalOperations)(pathsToRemove));
960
960
  const transformedPaths = track ? (0, operation_1.transformPathsByOperations)(track, operations) : [];
961
961
  return {
962
962
  node: (0, operation_1.applyOperations)(node, operations, options),
963
963
  paths: transformedPaths
964
964
  };
965
965
  }
966
- function getPathsToRemove(path4, deleteCount) {
966
+ function getPathsToRemove(path5, deleteCount) {
967
967
  let pathsToRemove = [];
968
- let parentPath = path4.slice(0, -1);
969
- let index = path4[path4.length - 1];
968
+ let parentPath = path5.slice(0, -1);
969
+ let index = path5[path5.length - 1];
970
970
  for (let i = 0; i < deleteCount; i++) {
971
971
  pathsToRemove.push(parentPath.concat(index + i));
972
972
  }
@@ -1111,6 +1111,7 @@ var src_exports = {};
1111
1111
  __export(src_exports, {
1112
1112
  MediaCollection: () => MediaCollection,
1113
1113
  PLACEHOLDER_ITEM_NAME: () => PLACEHOLDER_ITEM_NAME,
1114
+ acceptsMediaItemDrop: () => acceptsMediaItemDrop,
1114
1115
  basenameValidator: () => basenameValidator,
1115
1116
  createMediaAsset: () => createMediaAsset,
1116
1117
  createMediaFile: () => createMediaFile,
@@ -1224,7 +1225,7 @@ var createMediaItemTree = (mediaMap) => {
1224
1225
  };
1225
1226
 
1226
1227
  // src/MediaCollection.tsx
1227
- var import_imfs3 = require("imfs");
1228
+ var import_imfs4 = require("imfs");
1228
1229
  var import_react2 = __toESM(require("react"));
1229
1230
 
1230
1231
  // src/utils/files.ts
@@ -1247,6 +1248,9 @@ var getVisibleItems = ({
1247
1248
  }
1248
1249
  return;
1249
1250
  }
1251
+ if (item.kind === "noyaFile" && fileKindFilter === "all") {
1252
+ filteredItems.push(item);
1253
+ }
1250
1254
  if (item.kind === "file" && fileKindFilter === "all") {
1251
1255
  filteredItems.push(item);
1252
1256
  }
@@ -1283,7 +1287,7 @@ var movePathsIntoTarget = ({
1283
1287
  tree
1284
1288
  }) => {
1285
1289
  const ancestors = (0, import_tree_visit2.ancestorPaths)(
1286
- sourceItemPaths.map((path4) => path4.split("/"))
1290
+ sourceItemPaths.map((path5) => path5.split("/"))
1287
1291
  );
1288
1292
  const mediaClone = { ...media };
1289
1293
  for (const ancestor of ancestors) {
@@ -1330,7 +1334,7 @@ var moveUpAFolder = ({
1330
1334
  );
1331
1335
  const grandparentFolderPath = tree.idToPathMap.get(grandparentFolder.id);
1332
1336
  if (!grandparentFolderPath) return;
1333
- const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path4) => Boolean(path4));
1337
+ const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path5) => Boolean(path5));
1334
1338
  return movePathsIntoTarget({
1335
1339
  media,
1336
1340
  targetItemPath: grandparentFolderPath,
@@ -1396,7 +1400,7 @@ var moveMediaInsideFolder = ({
1396
1400
  }) => {
1397
1401
  const targetItemPath = tree.idToPathMap.get(targetItemId);
1398
1402
  if (!targetItemPath) return media;
1399
- const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path4) => Boolean(path4));
1403
+ const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path5) => Boolean(path5));
1400
1404
  return movePathsIntoTarget({
1401
1405
  media,
1402
1406
  sourceItemPaths,
@@ -1437,6 +1441,115 @@ var renameMediaItemAndDescendantPaths = ({
1437
1441
  return mediaClone;
1438
1442
  };
1439
1443
 
1444
+ // src/utils/handleFileDrop.ts
1445
+ var import_imfs3 = require("imfs");
1446
+ function isDirectoryEntry(entry) {
1447
+ return entry.isDirectory;
1448
+ }
1449
+ function isFileEntry(entry) {
1450
+ return entry.isFile;
1451
+ }
1452
+ async function handleDataTransfer({
1453
+ dataTransfer,
1454
+ rootItemPath,
1455
+ media,
1456
+ uploadAsset
1457
+ }) {
1458
+ try {
1459
+ const dataTransferItems = Array.from(dataTransfer.items ?? []);
1460
+ const supportsEntries = dataTransferItems.some(
1461
+ (item) => typeof item?.webkitGetAsEntry === "function"
1462
+ );
1463
+ const collectFromEntry = async (entry, basePath) => {
1464
+ if (!entry) return [];
1465
+ if (isFileEntry(entry)) {
1466
+ const file = await new Promise(
1467
+ (resolve) => entry.file((f) => resolve(f))
1468
+ );
1469
+ return [
1470
+ {
1471
+ file,
1472
+ relativePath: import_imfs3.path.join(basePath, file.name)
1473
+ }
1474
+ ];
1475
+ }
1476
+ if (isDirectoryEntry(entry)) {
1477
+ const reader = entry.createReader();
1478
+ const readAll = async () => {
1479
+ const all = [];
1480
+ while (true) {
1481
+ const entries = await new Promise(
1482
+ (resolve) => reader.readEntries((ents) => resolve(ents))
1483
+ );
1484
+ if (!entries.length) break;
1485
+ all.push(...entries);
1486
+ }
1487
+ return all;
1488
+ };
1489
+ const children = await readAll();
1490
+ const results = await Promise.all(
1491
+ children.map(
1492
+ (child) => collectFromEntry(child, import_imfs3.path.join(basePath, entry.name))
1493
+ )
1494
+ );
1495
+ return results.flat();
1496
+ }
1497
+ return [];
1498
+ };
1499
+ let dropped = [];
1500
+ if (supportsEntries) {
1501
+ const topLevelEntries = dataTransferItems.flatMap((item) => {
1502
+ const entry = item.webkitGetAsEntry?.();
1503
+ if (!entry) return [];
1504
+ return [entry];
1505
+ });
1506
+ const nested = await Promise.all(
1507
+ topLevelEntries.map((entry) => collectFromEntry(entry, ""))
1508
+ );
1509
+ dropped = nested.flat();
1510
+ } else {
1511
+ const files = Array.from(dataTransfer.files);
1512
+ if (files.length === 0) return;
1513
+ dropped = files.map((file) => ({
1514
+ file,
1515
+ // Best effort: try webkitRelativePath; fall back to name
1516
+ relativePath: file.webkitRelativePath && file.webkitRelativePath.length > 0 ? file.webkitRelativePath : file.name
1517
+ }));
1518
+ }
1519
+ if (dropped.length === 0) return;
1520
+ const folderRelativePaths = /* @__PURE__ */ new Set();
1521
+ for (const { relativePath } of dropped) {
1522
+ const dir = import_imfs3.path.dirname(relativePath);
1523
+ if (dir && dir !== ".") {
1524
+ const parts = dir.split("/").filter(Boolean);
1525
+ let acc = "";
1526
+ for (const part of parts) {
1527
+ acc = acc ? import_imfs3.path.join(acc, part) : part;
1528
+ folderRelativePaths.add(acc);
1529
+ }
1530
+ }
1531
+ }
1532
+ const folderEntries = Array.from(folderRelativePaths).map((rel) => import_imfs3.path.join(rootItemPath, rel)).filter((full) => !media[full]).map((full) => [full, createMediaFolder()]);
1533
+ const uploadResults = await Promise.all(
1534
+ dropped.map(
1535
+ async ({ file, relativePath }) => {
1536
+ const asset = await uploadAsset(file);
1537
+ return [
1538
+ import_imfs3.path.join(rootItemPath, relativePath),
1539
+ createMediaAsset({ assetId: asset.id })
1540
+ ];
1541
+ }
1542
+ )
1543
+ );
1544
+ return {
1545
+ ...media,
1546
+ ...Object.fromEntries([...folderEntries, ...uploadResults])
1547
+ };
1548
+ } catch (error) {
1549
+ console.error("Failed to upload dropped files:", error);
1550
+ }
1551
+ }
1552
+
1440
1553
  // src/MediaCollection.tsx
1441
1554
  var extensionToContentType = {
1442
1555
  svg: "image/svg+xml",
@@ -1444,7 +1557,7 @@ var extensionToContentType = {
1444
1557
  jpeg: "image/jpeg"
1445
1558
  };
1446
1559
  function encodeFileContentForThumbnail(pathProp, item) {
1447
- const extension = import_imfs3.path.extname(pathProp).slice(1);
1560
+ const extension = import_imfs4.path.extname(pathProp).slice(1);
1448
1561
  const contentType = extensionToContentType[extension];
1449
1562
  if (contentType) {
1450
1563
  if (item.encoding === "base64") {
@@ -1471,7 +1584,8 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
1471
1584
  item,
1472
1585
  selected,
1473
1586
  size,
1474
- path: pathProp
1587
+ path: pathProp,
1588
+ renderThumbnailIcon
1475
1589
  }) => {
1476
1590
  const asset = (0, import_noya_multiplayer_react.useAsset)(item.kind === "asset" ? item.assetId : void 0);
1477
1591
  const isRoot = item.id === rootMediaItem.id;
@@ -1489,7 +1603,7 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
1489
1603
  url = encoded.url;
1490
1604
  }
1491
1605
  }
1492
- const fileName = pathProp ? import_imfs3.path.basename(pathProp) : void 0;
1606
+ const fileName = pathProp ? import_imfs4.path.basename(pathProp) : void 0;
1493
1607
  return /* @__PURE__ */ import_react2.default.createElement(
1494
1608
  import_noya_designsystem.MediaThumbnail,
1495
1609
  {
@@ -1498,7 +1612,8 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
1498
1612
  url,
1499
1613
  selected,
1500
1614
  size,
1501
- fileName
1615
+ fileName,
1616
+ renderThumbnailIcon
1502
1617
  }
1503
1618
  );
1504
1619
  }
@@ -1529,7 +1644,10 @@ var MediaCollection = (0, import_react.memo)(
1529
1644
  scrollable = false,
1530
1645
  sortable = false,
1531
1646
  renderEmptyState,
1532
- sharedDragProps
1647
+ sharedDragProps,
1648
+ onClickItem,
1649
+ renderThumbnailIcon,
1650
+ onDidDeleteItems
1533
1651
  }, ref) {
1534
1652
  const setMedia = (0, import_react.useCallback)(
1535
1653
  (...args) => {
@@ -1611,14 +1729,14 @@ var MediaCollection = (0, import_react.memo)(
1611
1729
  const itemPath = tree.idToPathMap.get(item.id);
1612
1730
  const firstSelectedPath = tree.idToPathMap.get(selectedIds[0]);
1613
1731
  if (!itemPath || !firstSelectedPath) return false;
1614
- return itemPath.startsWith(import_imfs3.path.dirname(firstSelectedPath));
1732
+ return itemPath.startsWith(import_imfs4.path.dirname(firstSelectedPath));
1615
1733
  });
1616
1734
  (0, import_react.useEffect)(() => {
1617
1735
  if (initialExpanded) {
1618
1736
  setExpandedMap(initialExpanded);
1619
1737
  }
1620
1738
  }, [initialExpanded]);
1621
- const handleExpanded = (0, import_react.useCallback)(
1739
+ const getExpanded = (0, import_react.useCallback)(
1622
1740
  (item) => {
1623
1741
  if (!expandable) return void 0;
1624
1742
  if (item.kind !== "folder") return void 0;
@@ -1629,6 +1747,14 @@ var MediaCollection = (0, import_react.memo)(
1629
1747
  );
1630
1748
  const handleDelete = (0, import_react.useCallback)(
1631
1749
  (selectedIds2) => {
1750
+ const deletedItems = Object.entries(media).flatMap(
1751
+ ([path5, item]) => {
1752
+ if (selectedIds2.includes(item.id)) {
1753
+ return [[path5, item]];
1754
+ }
1755
+ return [];
1756
+ }
1757
+ );
1632
1758
  const newMedia = deleteMediaItems({
1633
1759
  selectedIds: selectedIds2,
1634
1760
  media,
@@ -1636,8 +1762,9 @@ var MediaCollection = (0, import_react.memo)(
1636
1762
  });
1637
1763
  setSelectedIds([rootMediaItem.id]);
1638
1764
  setMedia({ name: "Delete items", timestamp: Date.now() }, newMedia);
1765
+ onDidDeleteItems?.(deletedItems);
1639
1766
  },
1640
- [media, setMedia, setSelectedIds, tree]
1767
+ [media, setMedia, setSelectedIds, tree, onDidDeleteItems]
1641
1768
  );
1642
1769
  const onRename = (0, import_react.useCallback)(
1643
1770
  (selectedItem, newName) => {
@@ -1675,7 +1802,7 @@ var MediaCollection = (0, import_react.memo)(
1675
1802
  const currentFolderPath = tree.idToPathMap.get(currentFolderId);
1676
1803
  if (!currentFolderPath) return;
1677
1804
  setTempItem([
1678
- import_imfs3.path.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1805
+ import_imfs4.path.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1679
1806
  newFolder
1680
1807
  ]);
1681
1808
  setTimeout(() => {
@@ -1695,7 +1822,7 @@ var MediaCollection = (0, import_react.memo)(
1695
1822
  );
1696
1823
  if (!currentFolderPath) return;
1697
1824
  setTempItem([
1698
- import_imfs3.path.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1825
+ import_imfs4.path.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
1699
1826
  newFile
1700
1827
  ]);
1701
1828
  setTimeout(() => {
@@ -1716,6 +1843,7 @@ var MediaCollection = (0, import_react.memo)(
1716
1843
  },
1717
1844
  [media, tree, setMedia]
1718
1845
  );
1846
+ const [isUploading, setIsUploading] = (0, import_react.useState)(false);
1719
1847
  const handleUpload = (0, import_react.useCallback)(
1720
1848
  async (selectedId) => {
1721
1849
  try {
@@ -1725,12 +1853,13 @@ var MediaCollection = (0, import_react.memo)(
1725
1853
  if (!parentPath) return;
1726
1854
  const uploadPromises = files.map(async (file) => {
1727
1855
  const asset = await assetManager.create(file);
1728
- const assetPath = import_imfs3.path.join(parentPath, import_imfs3.path.basename(file.name));
1856
+ const assetPath = import_imfs4.path.join(parentPath, import_imfs4.path.basename(file.name));
1729
1857
  return {
1730
1858
  assetPath,
1731
1859
  asset: createMediaAsset({ assetId: asset.id })
1732
1860
  };
1733
1861
  });
1862
+ setIsUploading(true);
1734
1863
  const newMediaMap = await Promise.all(uploadPromises);
1735
1864
  setMedia(
1736
1865
  { name: "Add media items", timestamp: Date.now() },
@@ -1743,6 +1872,8 @@ var MediaCollection = (0, import_react.memo)(
1743
1872
  );
1744
1873
  } catch (error) {
1745
1874
  console.error("Failed to upload files:", error);
1875
+ } finally {
1876
+ setIsUploading(false);
1746
1877
  }
1747
1878
  },
1748
1879
  [tree.idToPathMap, setMedia, media, assetManager]
@@ -1802,9 +1933,6 @@ var MediaCollection = (0, import_react.memo)(
1802
1933
  );
1803
1934
  const handleMoveMediaInsideFolder = (0, import_react.useCallback)(
1804
1935
  (sourceItem, targetItem) => {
1805
- const sourceItemPath = tree.idToPathMap.get(sourceItem.id);
1806
- const targetItemPath = tree.idToPathMap.get(targetItem.id);
1807
- if (!sourceItemPath || !targetItemPath) return;
1808
1936
  const newMedia = moveMediaInsideFolder({
1809
1937
  sourceItemIds: [sourceItem.id],
1810
1938
  targetItemId: targetItem.id,
@@ -1842,12 +1970,12 @@ var MediaCollection = (0, import_react.memo)(
1842
1970
  ],
1843
1971
  [
1844
1972
  onlySingleFolderSelected && {
1845
- title: "Add media",
1973
+ title: "Upload Files",
1846
1974
  value: "upload",
1847
1975
  icon: /* @__PURE__ */ import_react2.default.createElement(import_noya_icons.UploadIcon, null)
1848
1976
  },
1849
1977
  onlySingleFolderSelected && {
1850
- title: "Add a Folder",
1978
+ title: "Add Folder",
1851
1979
  value: "addFolder",
1852
1980
  icon: /* @__PURE__ */ import_react2.default.createElement(import_noya_icons.FolderIcon, null)
1853
1981
  },
@@ -1971,7 +2099,8 @@ var MediaCollection = (0, import_react.memo)(
1971
2099
  moveUpAFolder: handleMoveUpAFolder,
1972
2100
  replace: handleReplace,
1973
2101
  preview: handlePreview,
1974
- moveMediaInsideFolder: handleMoveMediaInsideFolder
2102
+ moveMediaInsideFolder: handleMoveMediaInsideFolder,
2103
+ getItemAtIndex: (index) => visibleItems[index]
1975
2104
  }));
1976
2105
  return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(
1977
2106
  import_noya_designsystem.FileExplorerLayout,
@@ -1981,7 +2110,8 @@ var MediaCollection = (0, import_react.memo)(
1981
2110
  import_noya_designsystem.FileExplorerUploadButton,
1982
2111
  {
1983
2112
  showUploadButton,
1984
- onUpload: () => handleUpload(rootMediaItem.id)
2113
+ onUpload: () => handleUpload(rootMediaItem.id),
2114
+ isUploading
1985
2115
  },
1986
2116
  right
1987
2117
  ),
@@ -2012,10 +2142,11 @@ var MediaCollection = (0, import_react.memo)(
2012
2142
  return "Enter folder name";
2013
2143
  case "asset":
2014
2144
  case "file":
2145
+ case "noyaFile":
2015
2146
  return "Enter file name";
2016
2147
  }
2017
2148
  },
2018
- getExpanded: handleExpanded,
2149
+ getExpanded,
2019
2150
  setExpanded: handleSetExpanded,
2020
2151
  getRenamable: (item) => {
2021
2152
  if (item.id === rootMediaItem.id) return false;
@@ -2025,6 +2156,7 @@ var MediaCollection = (0, import_react.memo)(
2025
2156
  menuItems: assetContextMenuItems,
2026
2157
  onSelectMenuItem: handleMenuAction,
2027
2158
  onSelectionChange: setSelectedIds,
2159
+ onClickItem,
2028
2160
  onDoubleClickItem,
2029
2161
  onRename,
2030
2162
  renamable,
@@ -2033,7 +2165,8 @@ var MediaCollection = (0, import_react.memo)(
2033
2165
  MediaThumbnailInternal,
2034
2166
  {
2035
2167
  ...props,
2036
- path: tree.idToPathMap.get(props.item.id)
2168
+ path: tree.idToPathMap.get(props.item.id),
2169
+ renderThumbnailIcon
2037
2170
  }
2038
2171
  ),
2039
2172
  renderAction,
@@ -2041,7 +2174,7 @@ var MediaCollection = (0, import_react.memo)(
2041
2174
  if (file.kind !== "asset") return null;
2042
2175
  const asset = assets.find((a) => a.id === file.assetId);
2043
2176
  if (!asset) return null;
2044
- return /* @__PURE__ */ import_react2.default.createElement(import_noya_designsystem.FileExplorerDetail, { selected, size }, (asset.size / 1024).toFixed(1), "KB");
2177
+ return /* @__PURE__ */ import_react2.default.createElement(import_noya_designsystem.FileExplorerDetail, { selected, size }, (0, import_noya_designsystem.formatByteSize)(asset.size));
2045
2178
  },
2046
2179
  renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ import_react2.default.createElement(import_noya_designsystem.FileExplorerEmptyState, null),
2047
2180
  itemRoleDescription: "clickable file item",
@@ -2062,26 +2195,28 @@ var MediaCollection = (0, import_react.memo)(
2062
2195
  if (sourceListId !== targetListId) {
2063
2196
  return false;
2064
2197
  }
2065
- const sourceItem = visibleItems[sourceIndex];
2066
- const targetItem = visibleItems[targetIndex];
2067
- if (position !== "inside" || targetItem.kind === "asset") {
2198
+ if (sourceListId !== sortableId || targetListId !== sortableId) {
2068
2199
  return false;
2069
2200
  }
2070
- const sourcePath = tree.findPath(
2071
- rootMediaItem,
2072
- (item) => item.id === sourceItem.id
2073
- );
2074
- const targetPath = tree.findPath(
2075
- rootMediaItem,
2076
- (item) => item.id === targetItem.id
2077
- );
2078
- if (!sourcePath || !targetPath) return false;
2079
- if ((0, import_noya_utils2.isDeepEqual)(sourcePath, targetPath.slice(0, sourcePath.length))) {
2080
- return false;
2081
- }
2082
- return true;
2201
+ const sourceItem = visibleItems[sourceIndex];
2202
+ const targetItem = visibleItems[targetIndex];
2203
+ return acceptsMediaItemDrop({
2204
+ position,
2205
+ sourceItem,
2206
+ targetItem,
2207
+ tree
2208
+ });
2083
2209
  },
2084
- onMoveItem: ({ sourceIndex, targetIndex, position }) => {
2210
+ onMoveItem: ({
2211
+ sourceListId,
2212
+ sourceIndex,
2213
+ targetListId,
2214
+ targetIndex,
2215
+ position
2216
+ }) => {
2217
+ if (sourceListId !== sortableId || targetListId !== sortableId) {
2218
+ return;
2219
+ }
2085
2220
  const sourceItem = visibleItems[sourceIndex];
2086
2221
  const targetItem = visibleItems[targetIndex];
2087
2222
  if (position === "inside") {
@@ -2090,46 +2225,49 @@ var MediaCollection = (0, import_react.memo)(
2090
2225
  },
2091
2226
  onFilesDrop: async (event) => {
2092
2227
  event.preventDefault();
2093
- const files = Array.from(event.dataTransfer.files);
2094
- if (files.length === 0) return;
2095
- try {
2096
- const uploadPromises = files.map(async (file) => {
2097
- const asset = await assetManager.create(file);
2098
- return {
2099
- asset: createMediaAsset({
2100
- assetId: asset.id
2101
- }),
2102
- name: file.name
2103
- };
2104
- });
2105
- const newMediaItems = await Promise.all(uploadPromises);
2106
- const rootItemPath = tree.idToPathMap.get(rootItemId);
2107
- if (!rootItemPath) return;
2108
- setMedia(
2109
- { name: "Add media files", timestamp: Date.now() },
2110
- {
2111
- ...media,
2112
- ...Object.fromEntries(
2113
- newMediaItems.map((item) => [
2114
- import_imfs3.path.join(rootItemPath, item.name),
2115
- item.asset
2116
- ])
2117
- )
2118
- }
2119
- );
2120
- } catch (error) {
2121
- console.error("Failed to upload dropped files:", error);
2122
- }
2228
+ const rootItemPath = tree.idToPathMap.get(rootItemId);
2229
+ if (!rootItemPath) return;
2230
+ const newMedia = await handleDataTransfer({
2231
+ dataTransfer: event.dataTransfer,
2232
+ rootItemPath,
2233
+ media,
2234
+ uploadAsset: (file) => assetManager.create(file)
2235
+ });
2236
+ if (!newMedia) return;
2237
+ setMedia(
2238
+ { name: "Add media files", timestamp: Date.now() },
2239
+ newMedia
2240
+ );
2123
2241
  }
2124
2242
  }
2125
2243
  )
2126
2244
  ));
2127
2245
  })
2128
2246
  );
2247
+ function acceptsMediaItemDrop(parameters) {
2248
+ const { position, sourceItem, targetItem, tree } = parameters;
2249
+ if (position !== "inside" || targetItem.kind === "asset") {
2250
+ return false;
2251
+ }
2252
+ const sourcePath = tree.findPath(
2253
+ rootMediaItem,
2254
+ (item) => item.id === sourceItem.id
2255
+ );
2256
+ const targetPath = tree.findPath(
2257
+ rootMediaItem,
2258
+ (item) => item.id === targetItem.id
2259
+ );
2260
+ if (!sourcePath || !targetPath) return false;
2261
+ if ((0, import_noya_utils2.isDeepEqual)(sourcePath, targetPath.slice(0, sourcePath.length))) {
2262
+ return false;
2263
+ }
2264
+ return true;
2265
+ }
2129
2266
  // Annotate the CommonJS export names for ESM import in node:
2130
2267
  0 && (module.exports = {
2131
2268
  MediaCollection,
2132
2269
  PLACEHOLDER_ITEM_NAME,
2270
+ acceptsMediaItemDrop,
2133
2271
  basenameValidator,
2134
2272
  createMediaAsset,
2135
2273
  createMediaFile,