@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.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
  }
@@ -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 path3 } from "imfs";
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((path4) => path4.split("/"))
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((path4) => Boolean(path4));
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((path4) => Boolean(path4));
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 = path3.extname(pathProp).slice(1);
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 ? path3.basename(pathProp) : void 0;
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(path3.dirname(firstSelectedPath));
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 handleExpanded = useCallback(
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
- path3.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
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
- path3.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
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 = path3.join(parentPath, path3.basename(file.name));
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: "Add media",
1976
+ title: "Upload Files",
1849
1977
  value: "upload",
1850
1978
  icon: /* @__PURE__ */ React.createElement(UploadIcon, null)
1851
1979
  },
1852
1980
  onlySingleFolderSelected && {
1853
- title: "Add a Folder",
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: handleExpanded,
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 / 1024).toFixed(1), "KB");
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
- const sourceItem = visibleItems[sourceIndex];
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 sourcePath = tree.findPath(
2074
- rootMediaItem,
2075
- (item) => item.id === sourceItem.id
2076
- );
2077
- const targetPath = tree.findPath(
2078
- rootMediaItem,
2079
- (item) => item.id === targetItem.id
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: ({ 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
+ }
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 files = Array.from(event.dataTransfer.files);
2097
- if (files.length === 0) return;
2098
- try {
2099
- const uploadPromises = files.map(async (file) => {
2100
- const asset = await assetManager.create(file);
2101
- return {
2102
- asset: createMediaAsset({
2103
- assetId: asset.id
2104
- }),
2105
- name: file.name
2106
- };
2107
- });
2108
- const newMediaItems = await Promise.all(uploadPromises);
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,