@noya-app/noya-file-explorer 0.0.31 → 0.0.33

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
@@ -1100,10 +1100,620 @@ var require_lib = __commonJS({
1100
1100
  }
1101
1101
  });
1102
1102
 
1103
+ // src/GitFileExplorer.tsx
1104
+ import {
1105
+ Button,
1106
+ createSectionedMenu,
1107
+ cx,
1108
+ DropdownMenu,
1109
+ IconButton,
1110
+ List,
1111
+ MediaThumbnail,
1112
+ Section,
1113
+ Small,
1114
+ useOpenConfirmationDialog
1115
+ } from "@noya-app/noya-designsystem";
1116
+ import {
1117
+ InputIcon,
1118
+ PlusIcon,
1119
+ TrashIcon,
1120
+ UploadIcon
1121
+ } from "@noya-app/noya-icons";
1122
+ import { useFileDropTarget } from "@noya-app/react-utils";
1123
+ import React, {
1124
+ forwardRef,
1125
+ memo,
1126
+ useCallback as useCallback3,
1127
+ useEffect,
1128
+ useImperativeHandle,
1129
+ useMemo as useMemo2,
1130
+ useRef,
1131
+ useState as useState3
1132
+ } from "react";
1133
+
1134
+ // src/git/gitFileTree.ts
1135
+ function parseFilesToTree(files) {
1136
+ const items = [];
1137
+ const seenDirs = /* @__PURE__ */ new Set();
1138
+ const sortedFiles = [...files].sort();
1139
+ for (const filePath of sortedFiles) {
1140
+ const parts = filePath.split("/");
1141
+ let currentPath = "";
1142
+ for (let i = 0; i < parts.length - 1; i++) {
1143
+ currentPath = currentPath ? `${currentPath}/${parts[i]}` : parts[i];
1144
+ if (!seenDirs.has(currentPath)) {
1145
+ seenDirs.add(currentPath);
1146
+ items.push({
1147
+ id: `dir:${currentPath}`,
1148
+ name: parts[i],
1149
+ path: currentPath,
1150
+ isDirectory: true,
1151
+ depth: i
1152
+ });
1153
+ }
1154
+ }
1155
+ items.push({
1156
+ id: `file:${filePath}`,
1157
+ name: parts[parts.length - 1],
1158
+ path: filePath,
1159
+ isDirectory: false,
1160
+ depth: parts.length - 1
1161
+ });
1162
+ }
1163
+ return items;
1164
+ }
1165
+ function getVisibleItems(items, expandedDirs) {
1166
+ const visible = [];
1167
+ const collapsedPrefixes = [];
1168
+ for (const item of items) {
1169
+ const isHidden = collapsedPrefixes.some(
1170
+ (prefix) => item.path.startsWith(prefix + "/")
1171
+ );
1172
+ if (isHidden) continue;
1173
+ visible.push(item);
1174
+ if (item.isDirectory && !expandedDirs.has(item.path)) {
1175
+ collapsedPrefixes.push(item.path);
1176
+ }
1177
+ }
1178
+ return visible;
1179
+ }
1180
+ function createTempFileItem(name = "") {
1181
+ return {
1182
+ id: "temp:new-file",
1183
+ name,
1184
+ path: name,
1185
+ isDirectory: false,
1186
+ depth: 0
1187
+ };
1188
+ }
1189
+ function isTempItem(item) {
1190
+ return item.id === "temp:new-file";
1191
+ }
1192
+ function computeRenamedPath(oldPath, newName) {
1193
+ const pathParts = oldPath.split("/");
1194
+ pathParts[pathParts.length - 1] = newName;
1195
+ return pathParts.join("/");
1196
+ }
1197
+
1198
+ // src/git/useGitFileOperations.ts
1199
+ import {
1200
+ collectDroppedFiles,
1201
+ readFileAsText
1202
+ } from "@noya-app/react-utils";
1203
+ import { fileOpen } from "browser-fs-access";
1204
+ import { useCallback, useState } from "react";
1205
+ function useGitFileOperations({
1206
+ repoId,
1207
+ repoFilesState,
1208
+ gitManager
1209
+ }) {
1210
+ const [isUploading, setIsUploading] = useState(false);
1211
+ const createFile = useCallback(
1212
+ async (path7, content = "") => {
1213
+ try {
1214
+ await gitManager.patchFiles(
1215
+ repoId,
1216
+ { create: [{ path: path7, content }] },
1217
+ repoFilesState.ref
1218
+ );
1219
+ } catch (error) {
1220
+ alert(`Failed to create file: ${error}`);
1221
+ throw error;
1222
+ }
1223
+ },
1224
+ [gitManager, repoId, repoFilesState.ref]
1225
+ );
1226
+ const renameFile = useCallback(
1227
+ async (item, newName) => {
1228
+ if (isTempItem(item)) {
1229
+ if (!newName) return;
1230
+ await createFile(newName);
1231
+ return;
1232
+ }
1233
+ if (item.isDirectory) {
1234
+ alert("Renaming directories is not yet supported");
1235
+ return;
1236
+ }
1237
+ if (newName === item.name) return;
1238
+ const newPath = computeRenamedPath(item.path, newName);
1239
+ try {
1240
+ await gitManager.patchFiles(
1241
+ repoId,
1242
+ { rename: [{ oldPath: item.path, newPath }] },
1243
+ repoFilesState.ref
1244
+ );
1245
+ } catch (error) {
1246
+ alert(`Failed to rename file: ${error}`);
1247
+ throw error;
1248
+ }
1249
+ },
1250
+ [gitManager, repoId, repoFilesState.ref, createFile]
1251
+ );
1252
+ const deleteFiles = useCallback(
1253
+ async (items) => {
1254
+ const pathsToDelete = /* @__PURE__ */ new Set();
1255
+ for (const item of items) {
1256
+ if (item.isDirectory) {
1257
+ const dirPrefix = item.path + "/";
1258
+ for (const filePath of repoFilesState.files) {
1259
+ if (filePath.startsWith(dirPrefix)) {
1260
+ pathsToDelete.add(filePath);
1261
+ }
1262
+ }
1263
+ } else {
1264
+ pathsToDelete.add(item.path);
1265
+ }
1266
+ }
1267
+ if (pathsToDelete.size === 0) {
1268
+ return;
1269
+ }
1270
+ try {
1271
+ await gitManager.patchFiles(
1272
+ repoId,
1273
+ { delete: Array.from(pathsToDelete).map((path7) => ({ path: path7 })) },
1274
+ repoFilesState.ref
1275
+ );
1276
+ } catch (error) {
1277
+ alert(`Failed to delete files: ${error}`);
1278
+ throw error;
1279
+ }
1280
+ },
1281
+ [gitManager, repoId, repoFilesState.ref, repoFilesState.files]
1282
+ );
1283
+ const uploadFiles = useCallback(async () => {
1284
+ try {
1285
+ const files = await fileOpen({ multiple: true });
1286
+ if (!files || Array.isArray(files) && files.length === 0) return;
1287
+ const fileArray = Array.isArray(files) ? files : [files];
1288
+ setIsUploading(true);
1289
+ const createOperations = await Promise.all(
1290
+ fileArray.map(async (file) => ({
1291
+ path: file.name,
1292
+ content: await readFileAsText(file)
1293
+ }))
1294
+ );
1295
+ await gitManager.patchFiles(
1296
+ repoId,
1297
+ { create: createOperations },
1298
+ repoFilesState.ref
1299
+ );
1300
+ } catch (error) {
1301
+ if (error instanceof Error && error.name === "AbortError") {
1302
+ } else {
1303
+ alert(`Failed to upload files: ${error}`);
1304
+ }
1305
+ } finally {
1306
+ setIsUploading(false);
1307
+ }
1308
+ }, [gitManager, repoId, repoFilesState.ref]);
1309
+ const handleFileDrop = useCallback(
1310
+ async (event) => {
1311
+ event.preventDefault();
1312
+ try {
1313
+ setIsUploading(true);
1314
+ const droppedFiles = await collectDroppedFiles(event.dataTransfer);
1315
+ if (droppedFiles.length === 0) return;
1316
+ const createOperations = await Promise.all(
1317
+ droppedFiles.map(async ({ file, relativePath }) => ({
1318
+ path: relativePath,
1319
+ content: await readFileAsText(file)
1320
+ }))
1321
+ );
1322
+ await gitManager.patchFiles(
1323
+ repoId,
1324
+ { create: createOperations },
1325
+ repoFilesState.ref
1326
+ );
1327
+ } catch (error) {
1328
+ alert(`Failed to upload files: ${error}`);
1329
+ } finally {
1330
+ setIsUploading(false);
1331
+ }
1332
+ },
1333
+ [gitManager, repoId, repoFilesState.ref]
1334
+ );
1335
+ return {
1336
+ isUploading,
1337
+ createFile,
1338
+ renameFile,
1339
+ deleteFiles,
1340
+ uploadFiles,
1341
+ handleFileDrop
1342
+ };
1343
+ }
1344
+
1345
+ // src/git/useGitFileTree.ts
1346
+ import { useCallback as useCallback2, useMemo, useState as useState2 } from "react";
1347
+ function useGitFileTree({ repoFilesState }) {
1348
+ const [expandedDirs, setExpandedDirs] = useState2(
1349
+ () => /* @__PURE__ */ new Set()
1350
+ );
1351
+ const [tempItem, setTempItem] = useState2(void 0);
1352
+ const allItems = useMemo(
1353
+ () => parseFilesToTree(repoFilesState.files),
1354
+ [repoFilesState.files]
1355
+ );
1356
+ const allItemsWithTemp = useMemo(() => {
1357
+ if (!tempItem) return allItems;
1358
+ return [...allItems, tempItem];
1359
+ }, [allItems, tempItem]);
1360
+ const visibleItems = useMemo(
1361
+ () => getVisibleItems(allItemsWithTemp, expandedDirs),
1362
+ [allItemsWithTemp, expandedDirs]
1363
+ );
1364
+ const getExpanded = useCallback2(
1365
+ (item) => {
1366
+ if (!item.isDirectory) return void 0;
1367
+ return expandedDirs.has(item.path);
1368
+ },
1369
+ [expandedDirs]
1370
+ );
1371
+ const setExpanded = useCallback2((item, expanded) => {
1372
+ if (!item.isDirectory) return;
1373
+ setExpandedDirs((prev) => {
1374
+ const next = new Set(prev);
1375
+ if (expanded) {
1376
+ next.add(item.path);
1377
+ } else {
1378
+ next.delete(item.path);
1379
+ }
1380
+ return next;
1381
+ });
1382
+ }, []);
1383
+ const toggleExpanded = useCallback2((item) => {
1384
+ if (!item.isDirectory) return;
1385
+ setExpandedDirs((prev) => {
1386
+ const next = new Set(prev);
1387
+ if (next.has(item.path)) {
1388
+ next.delete(item.path);
1389
+ } else {
1390
+ next.add(item.path);
1391
+ }
1392
+ return next;
1393
+ });
1394
+ }, []);
1395
+ const addTempItem = useCallback2(() => {
1396
+ const newItem = createTempFileItem();
1397
+ setTempItem(newItem);
1398
+ return newItem;
1399
+ }, []);
1400
+ const clearTempItem = useCallback2(() => {
1401
+ setTempItem(void 0);
1402
+ }, []);
1403
+ return {
1404
+ visibleItems,
1405
+ tempItem,
1406
+ getExpanded,
1407
+ setExpanded,
1408
+ toggleExpanded,
1409
+ addTempItem,
1410
+ clearTempItem
1411
+ };
1412
+ }
1413
+
1414
+ // src/GitFileExplorer.tsx
1415
+ function useDelayedTrue(condition, delayMs) {
1416
+ const [delayedValue, setDelayedValue] = useState3(false);
1417
+ useEffect(() => {
1418
+ if (!condition) {
1419
+ setDelayedValue(false);
1420
+ return;
1421
+ }
1422
+ const timeout = setTimeout(() => {
1423
+ setDelayedValue(true);
1424
+ }, delayMs);
1425
+ return () => clearTimeout(timeout);
1426
+ }, [condition, delayMs]);
1427
+ return delayedValue;
1428
+ }
1429
+ var GitFileExplorerInner = memo(
1430
+ forwardRef(function GitFileExplorer({
1431
+ repoId,
1432
+ repoFilesState,
1433
+ gitManager,
1434
+ selectedIds: selectedIdsProp,
1435
+ onSelectionChange,
1436
+ onFileSelect,
1437
+ className,
1438
+ title = "Files"
1439
+ }, ref) {
1440
+ const [internalSelectedIds, setInternalSelectedIds] = useState3(
1441
+ []
1442
+ );
1443
+ const selectedIds = selectedIdsProp ?? internalSelectedIds;
1444
+ const baseSetSelectedIds = onSelectionChange ?? setInternalSelectedIds;
1445
+ const dropTargetRef = useRef(null);
1446
+ const collectionRef = useRef(null);
1447
+ const openConfirmationDialog = useOpenConfirmationDialog();
1448
+ const {
1449
+ visibleItems,
1450
+ getExpanded,
1451
+ setExpanded,
1452
+ toggleExpanded,
1453
+ addTempItem,
1454
+ clearTempItem
1455
+ } = useGitFileTree({ repoFilesState });
1456
+ const setSelectedIds = useCallback3(
1457
+ (ids) => {
1458
+ baseSetSelectedIds(ids);
1459
+ if (ids.length === 1) {
1460
+ const item = visibleItems.find((i) => i.id === ids[0]);
1461
+ if (item && !item.isDirectory) {
1462
+ onFileSelect?.(item.path);
1463
+ }
1464
+ }
1465
+ },
1466
+ [baseSetSelectedIds, visibleItems, onFileSelect]
1467
+ );
1468
+ const {
1469
+ isUploading,
1470
+ renameFile,
1471
+ deleteFiles,
1472
+ uploadFiles,
1473
+ handleFileDrop
1474
+ } = useGitFileOperations({ repoId, repoFilesState, gitManager });
1475
+ const { dropTargetProps, isDropTargetActive } = useFileDropTarget(
1476
+ dropTargetRef,
1477
+ handleFileDrop
1478
+ );
1479
+ const handleAddFile = useCallback3(() => {
1480
+ const newItem = addTempItem();
1481
+ setTimeout(() => {
1482
+ collectionRef.current?.editName(newItem.id);
1483
+ }, 50);
1484
+ }, [addTempItem]);
1485
+ const handleStartRename = useCallback3((itemId) => {
1486
+ collectionRef.current?.editName(itemId);
1487
+ }, []);
1488
+ const handleRename = useCallback3(
1489
+ async (item, newName) => {
1490
+ if (isTempItem(item)) {
1491
+ clearTempItem();
1492
+ if (!newName) return;
1493
+ }
1494
+ await renameFile(item, newName);
1495
+ },
1496
+ [renameFile, clearTempItem]
1497
+ );
1498
+ const handleDelete = useCallback3(
1499
+ async (items) => {
1500
+ if (items.length === 0) return;
1501
+ const fileCount = items.filter((item) => !item.isDirectory).length;
1502
+ const dirCount = items.filter((item) => item.isDirectory).length;
1503
+ let description;
1504
+ if (dirCount > 0 && fileCount > 0) {
1505
+ description = `Are you sure you want to delete ${fileCount} file(s) and ${dirCount} folder(s)? This action cannot be undone.`;
1506
+ } else if (dirCount > 0) {
1507
+ description = `Are you sure you want to delete ${dirCount} folder(s) and all their contents? This action cannot be undone.`;
1508
+ } else {
1509
+ description = `Are you sure you want to delete ${fileCount} file(s)? This action cannot be undone.`;
1510
+ }
1511
+ const confirmed = await openConfirmationDialog({
1512
+ title: "Delete",
1513
+ description
1514
+ });
1515
+ if (!confirmed) return;
1516
+ await deleteFiles(items);
1517
+ setSelectedIds([]);
1518
+ },
1519
+ [deleteFiles, setSelectedIds, openConfirmationDialog]
1520
+ );
1521
+ const handleDoubleClick = useCallback3(
1522
+ (itemId) => {
1523
+ const item = visibleItems.find((i) => i.id === itemId);
1524
+ if (!item) return;
1525
+ if (item.isDirectory) {
1526
+ toggleExpanded(item);
1527
+ } else {
1528
+ onFileSelect?.(item.path);
1529
+ }
1530
+ },
1531
+ [visibleItems, toggleExpanded, onFileSelect]
1532
+ );
1533
+ const headerMenuItems = useMemo2(
1534
+ () => createSectionedMenu([
1535
+ {
1536
+ title: "New File",
1537
+ value: "newFile",
1538
+ icon: /* @__PURE__ */ React.createElement(PlusIcon, null)
1539
+ },
1540
+ {
1541
+ title: "Upload Files",
1542
+ value: "uploadFiles",
1543
+ icon: /* @__PURE__ */ React.createElement(UploadIcon, null)
1544
+ }
1545
+ ]),
1546
+ []
1547
+ );
1548
+ const handleHeaderMenuAction = useCallback3(
1549
+ (action) => {
1550
+ switch (action) {
1551
+ case "newFile":
1552
+ handleAddFile();
1553
+ break;
1554
+ case "uploadFiles":
1555
+ uploadFiles();
1556
+ break;
1557
+ }
1558
+ },
1559
+ [handleAddFile, uploadFiles]
1560
+ );
1561
+ const handleMenuAction = useCallback3(
1562
+ (action, items) => {
1563
+ switch (action) {
1564
+ case "addFile":
1565
+ handleAddFile();
1566
+ break;
1567
+ case "rename":
1568
+ if (items.length === 1) {
1569
+ handleStartRename(items[0].id);
1570
+ }
1571
+ break;
1572
+ case "delete":
1573
+ handleDelete(items);
1574
+ break;
1575
+ }
1576
+ },
1577
+ [handleAddFile, handleStartRename, handleDelete]
1578
+ );
1579
+ const menuItems = useMemo2(() => {
1580
+ const singleSelected = selectedIds.length === 1;
1581
+ const hasSelection = selectedIds.length > 0;
1582
+ const selectedItem = singleSelected ? visibleItems.find((item) => selectedIds.includes(item.id)) : void 0;
1583
+ const isFile = selectedItem && !selectedItem.isDirectory;
1584
+ return createSectionedMenu(
1585
+ [
1586
+ {
1587
+ title: "Add File",
1588
+ value: "addFile",
1589
+ icon: /* @__PURE__ */ React.createElement(PlusIcon, null)
1590
+ }
1591
+ ],
1592
+ [
1593
+ singleSelected && isFile && {
1594
+ title: "Rename",
1595
+ value: "rename",
1596
+ icon: /* @__PURE__ */ React.createElement(InputIcon, null)
1597
+ },
1598
+ hasSelection && {
1599
+ title: "Delete",
1600
+ value: "delete",
1601
+ icon: /* @__PURE__ */ React.createElement(TrashIcon, null)
1602
+ }
1603
+ ]
1604
+ );
1605
+ }, [selectedIds, visibleItems]);
1606
+ useImperativeHandle(ref, () => ({
1607
+ addFile: handleAddFile,
1608
+ delete: (ids) => {
1609
+ const items = visibleItems.filter((item) => ids.includes(item.id));
1610
+ handleDelete(items);
1611
+ },
1612
+ rename: (id) => {
1613
+ handleStartRename(id);
1614
+ }
1615
+ }));
1616
+ const isRefreshing = repoFilesState.fetchState === "refreshing";
1617
+ const isLoading = repoFilesState.fetchState === "loading";
1618
+ const showLoading = useDelayedTrue(isLoading, 500);
1619
+ const renderEmptyState = useCallback3(() => {
1620
+ const hasError = !!repoFilesState.error;
1621
+ let content = null;
1622
+ if (isLoading && showLoading) {
1623
+ content = /* @__PURE__ */ React.createElement(Small, null, "Loading files...");
1624
+ } else if (isLoading) {
1625
+ content = null;
1626
+ } else if (hasError) {
1627
+ content = /* @__PURE__ */ React.createElement(Small, null, "Error: ", repoFilesState.error);
1628
+ } else {
1629
+ content = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Small, null, "No files yet"), /* @__PURE__ */ React.createElement(Button, { onClick: handleAddFile }, "Add a file"));
1630
+ }
1631
+ return /* @__PURE__ */ React.createElement("div", { className: "n-mx-3 n-flex-1 n-flex n-flex-col n-items-center n-justify-center n-gap-2" }, content);
1632
+ }, [repoFilesState.error, handleAddFile, isLoading, showLoading]);
1633
+ return /* @__PURE__ */ React.createElement(
1634
+ Section,
1635
+ {
1636
+ title,
1637
+ className: cx("n-px-3", className),
1638
+ right: /* @__PURE__ */ React.createElement("div", { className: "n-flex n-items-center n-gap-1" }, isRefreshing && /* @__PURE__ */ React.createElement(Small, { color: "textDisabled" }, "Syncing..."), isUploading && /* @__PURE__ */ React.createElement(Small, { color: "textDisabled" }, "Uploading..."), /* @__PURE__ */ React.createElement(
1639
+ DropdownMenu,
1640
+ {
1641
+ items: headerMenuItems,
1642
+ onSelect: handleHeaderMenuAction
1643
+ },
1644
+ /* @__PURE__ */ React.createElement(IconButton, { iconName: "DotsVerticalIcon" })
1645
+ ))
1646
+ },
1647
+ /* @__PURE__ */ React.createElement(
1648
+ "div",
1649
+ {
1650
+ ref: dropTargetRef,
1651
+ className: cx(
1652
+ "n-flex n-flex-col n-flex-1 -n-mx-3",
1653
+ isDropTargetActive && "n-bg-blue-500/10 n-ring-2 n-ring-blue-500 n-ring-inset"
1654
+ ),
1655
+ ...dropTargetProps
1656
+ },
1657
+ /* @__PURE__ */ React.createElement(
1658
+ List,
1659
+ {
1660
+ ref: collectionRef,
1661
+ className: "n-flex-1",
1662
+ scrollable: true,
1663
+ expandable: true,
1664
+ renamable: true,
1665
+ size: "small",
1666
+ items: visibleItems,
1667
+ getId: (item) => item.id,
1668
+ getName: (item) => isTempItem(item) ? "" : item.name,
1669
+ getDepth: (item) => item.depth,
1670
+ getExpanded,
1671
+ setExpanded,
1672
+ getRenamable: (item) => !item.isDirectory,
1673
+ getPlaceholder: () => "Enter file name",
1674
+ selectedIds,
1675
+ onSelectionChange: setSelectedIds,
1676
+ onDoubleClickItem: handleDoubleClick,
1677
+ onRename: handleRename,
1678
+ menuItems,
1679
+ onSelectMenuItem: handleMenuAction,
1680
+ renderEmptyState,
1681
+ renameSelectsBeforeDot: true,
1682
+ renderThumbnail: ({ item, selected }) => /* @__PURE__ */ React.createElement(
1683
+ MediaThumbnail,
1684
+ {
1685
+ iconName: item.isDirectory ? "FolderIcon" : void 0,
1686
+ fileName: item.isDirectory ? void 0 : item.name,
1687
+ selected,
1688
+ size: "small"
1689
+ }
1690
+ )
1691
+ }
1692
+ )
1693
+ )
1694
+ );
1695
+ })
1696
+ );
1697
+ var GitFileExplorer2 = memo(
1698
+ forwardRef(function GitFileExplorer3(props, ref) {
1699
+ if (!props.repoFilesState) {
1700
+ return /* @__PURE__ */ React.createElement(Section, { title: props.title, className: cx("n-px-3", props.className) }, null);
1701
+ }
1702
+ return /* @__PURE__ */ React.createElement(
1703
+ GitFileExplorerInner,
1704
+ {
1705
+ ...props,
1706
+ repoFilesState: props.repoFilesState,
1707
+ ref
1708
+ }
1709
+ );
1710
+ })
1711
+ );
1712
+
1103
1713
  // src/MediaCollection.tsx
1104
1714
  import {
1105
1715
  ActionMenu,
1106
- createSectionedMenu,
1716
+ createSectionedMenu as createSectionedMenu2,
1107
1717
  cssVars,
1108
1718
  FileExplorerCollection,
1109
1719
  FileExplorerDetail,
@@ -1111,18 +1721,18 @@ import {
1111
1721
  FileExplorerLayout,
1112
1722
  FileExplorerUploadButton,
1113
1723
  formatByteSize,
1114
- MediaThumbnail,
1115
- useOpenConfirmationDialog
1724
+ MediaThumbnail as MediaThumbnail2,
1725
+ useOpenConfirmationDialog as useOpenConfirmationDialog2
1116
1726
  } from "@noya-app/noya-designsystem";
1117
1727
  import {
1118
1728
  DownloadIcon,
1119
1729
  FolderIcon,
1120
- InputIcon,
1730
+ InputIcon as InputIcon2,
1121
1731
  OpenInNewWindowIcon,
1122
1732
  ResetIcon,
1123
- TrashIcon,
1733
+ TrashIcon as TrashIcon2,
1124
1734
  UpdateIcon,
1125
- UploadIcon
1735
+ UploadIcon as UploadIcon2
1126
1736
  } from "@noya-app/noya-icons";
1127
1737
  import {
1128
1738
  useAsset,
@@ -1135,16 +1745,16 @@ import {
1135
1745
  memoGeneric,
1136
1746
  useControlledOrUncontrolled
1137
1747
  } from "@noya-app/react-utils";
1138
- import { fileOpen } from "browser-fs-access";
1748
+ import { fileOpen as fileOpen2 } from "browser-fs-access";
1139
1749
  import {
1140
- forwardRef,
1141
- memo,
1142
- useCallback,
1143
- useEffect,
1144
- useImperativeHandle,
1145
- useMemo,
1146
- useRef,
1147
- useState
1750
+ forwardRef as forwardRef2,
1751
+ memo as memo2,
1752
+ useCallback as useCallback4,
1753
+ useEffect as useEffect2,
1754
+ useImperativeHandle as useImperativeHandle2,
1755
+ useMemo as useMemo3,
1756
+ useRef as useRef2,
1757
+ useState as useState4
1148
1758
  } from "react";
1149
1759
 
1150
1760
  // src/utils/mediaItemTree.ts
@@ -1230,7 +1840,7 @@ var createMediaItemTree = (mediaMap) => {
1230
1840
 
1231
1841
  // src/MediaCollection.tsx
1232
1842
  import { path as path4 } from "imfs";
1233
- import React from "react";
1843
+ import React2 from "react";
1234
1844
 
1235
1845
  // src/utils/files.ts
1236
1846
  var import_tree_visit3 = __toESM(require_lib());
@@ -1243,7 +1853,7 @@ import {
1243
1853
  rootResource
1244
1854
  } from "@noya-app/noya-schemas";
1245
1855
  import { path as path2 } from "imfs";
1246
- var getVisibleItems = ({
1856
+ var getVisibleItems2 = ({
1247
1857
  expandedMap,
1248
1858
  fileKindFilter,
1249
1859
  rootItemId,
@@ -1718,8 +2328,8 @@ var MediaThumbnailInternal = memoGeneric(
1718
2328
  }
1719
2329
  const fileName = pathProp ? path4.basename(pathProp) : void 0;
1720
2330
  const dimensions = width && height ? { width, height } : void 0;
1721
- return /* @__PURE__ */ React.createElement(
1722
- MediaThumbnail,
2331
+ return /* @__PURE__ */ React2.createElement(
2332
+ MediaThumbnail2,
1723
2333
  {
1724
2334
  contentType,
1725
2335
  iconName: isRoot ? "HomeIcon" : isFolder ? "FolderIcon" : void 0,
@@ -1733,8 +2343,8 @@ var MediaThumbnailInternal = memoGeneric(
1733
2343
  );
1734
2344
  }
1735
2345
  );
1736
- var MediaCollection = memo(
1737
- forwardRef(function MediaCollection2({
2346
+ var MediaCollection = memo2(
2347
+ forwardRef2(function MediaCollection2({
1738
2348
  sortableId,
1739
2349
  onSelectionChange,
1740
2350
  selectedIds: selectedIdsProp,
@@ -1765,28 +2375,28 @@ var MediaCollection = memo(
1765
2375
  onDidDeleteItems,
1766
2376
  onAssetsUploaded
1767
2377
  }, ref) {
1768
- const setMedia = useCallback(
2378
+ const setMedia = useCallback4(
1769
2379
  (...args) => {
1770
2380
  setMediaProp?.(...args);
1771
2381
  },
1772
2382
  [setMediaProp]
1773
2383
  );
1774
- const tree = useMemo(() => createMediaItemTree(media), [media]);
1775
- const [tempItem, setTempItem] = useState(
2384
+ const tree = useMemo3(() => createMediaItemTree(media), [media]);
2385
+ const [tempItem, setTempItem] = useState4(
1776
2386
  void 0
1777
2387
  );
1778
- const mediaWithTempItem = useMemo(
2388
+ const mediaWithTempItem = useMemo3(
1779
2389
  () => ({
1780
2390
  ...media,
1781
2391
  ...tempItem ? { [tempItem[0]]: tempItem[1] } : {}
1782
2392
  }),
1783
2393
  [media, tempItem]
1784
2394
  );
1785
- const treeWithTempItem = useMemo(
2395
+ const treeWithTempItem = useMemo3(
1786
2396
  () => createMediaItemTree(mediaWithTempItem),
1787
2397
  [mediaWithTempItem]
1788
2398
  );
1789
- const temp = useMemo(
2399
+ const temp = useMemo3(
1790
2400
  () => ({
1791
2401
  media: mediaWithTempItem,
1792
2402
  tree: treeWithTempItem
@@ -1802,8 +2412,8 @@ var MediaCollection = memo(
1802
2412
  );
1803
2413
  const assetManager = useAssetManager();
1804
2414
  const assets = useAssets();
1805
- const [expandedMap, setExpandedMap] = useState({});
1806
- const visibleItems = useMemo(
2415
+ const [expandedMap, setExpandedMap] = useState4({});
2416
+ const visibleItems = useMemo3(
1807
2417
  () => mediaGetVisibleItems({
1808
2418
  expandedMap,
1809
2419
  fileKindFilter,
@@ -1821,12 +2431,12 @@ var MediaCollection = memo(
1821
2431
  showRootItem
1822
2432
  ]
1823
2433
  );
1824
- const depthMap = useMemo(
2434
+ const depthMap = useMemo3(
1825
2435
  () => mediaGetDepthMap(rootMediaItem, treeWithTempItem, showAllDescendants),
1826
2436
  [treeWithTempItem, showAllDescendants]
1827
2437
  );
1828
- const collectionRef = useRef(null);
1829
- const selectedMediaItems = useMemo(
2438
+ const collectionRef = useRef2(null);
2439
+ const selectedMediaItems = useMemo3(
1830
2440
  () => treeWithTempItem.mediaItemsWithRoot.filter(
1831
2441
  (item) => selectedIds.includes(item.id)
1832
2442
  ),
@@ -1847,12 +2457,12 @@ var MediaCollection = memo(
1847
2457
  if (!itemPath || !firstSelectedPath) return false;
1848
2458
  return itemPath.startsWith(path4.dirname(firstSelectedPath));
1849
2459
  });
1850
- useEffect(() => {
2460
+ useEffect2(() => {
1851
2461
  if (initialExpanded) {
1852
2462
  setExpandedMap(initialExpanded);
1853
2463
  }
1854
2464
  }, [initialExpanded]);
1855
- const getExpanded = useCallback(
2465
+ const getExpanded = useCallback4(
1856
2466
  (item) => {
1857
2467
  if (!expandable) return void 0;
1858
2468
  if (item.kind !== "folder") return void 0;
@@ -1861,8 +2471,8 @@ var MediaCollection = memo(
1861
2471
  },
1862
2472
  [expandedMap, expandable]
1863
2473
  );
1864
- const openConfirmationDialog = useOpenConfirmationDialog();
1865
- const handleDelete = useCallback(
2474
+ const openConfirmationDialog = useOpenConfirmationDialog2();
2475
+ const handleDelete = useCallback4(
1866
2476
  async (selectedIds2) => {
1867
2477
  const ok = await openConfirmationDialog({
1868
2478
  title: "Delete items",
@@ -1895,7 +2505,7 @@ var MediaCollection = memo(
1895
2505
  openConfirmationDialog
1896
2506
  ]
1897
2507
  );
1898
- const onRename = useCallback(
2508
+ const onRename = useCallback4(
1899
2509
  (selectedItem, newName) => {
1900
2510
  if (!renamable) return;
1901
2511
  const selectedItemPath = treeWithTempItem.idToPathMap.get(
@@ -1925,7 +2535,7 @@ var MediaCollection = memo(
1925
2535
  },
1926
2536
  [renamable, setMedia, temp.media, temp.tree, treeWithTempItem.idToPathMap]
1927
2537
  );
1928
- const handleAddFolder = useCallback(
2538
+ const handleAddFolder = useCallback4(
1929
2539
  (currentFolderId) => {
1930
2540
  const newFolder = createMediaFolder();
1931
2541
  const currentFolderPath = tree.idToPathMap.get(currentFolderId);
@@ -1940,7 +2550,7 @@ var MediaCollection = memo(
1940
2550
  },
1941
2551
  [tree]
1942
2552
  );
1943
- const handleAddFile = useCallback(
2553
+ const handleAddFile = useCallback4(
1944
2554
  (currentFolderId) => {
1945
2555
  const newFile = createMediaFile({
1946
2556
  content: "",
@@ -1960,7 +2570,7 @@ var MediaCollection = memo(
1960
2570
  },
1961
2571
  [tree.idToPathMap]
1962
2572
  );
1963
- const handleMoveUpAFolder = useCallback(
2573
+ const handleMoveUpAFolder = useCallback4(
1964
2574
  (selectedIds2) => {
1965
2575
  const newMedia = mediaMoveUpAFolder({
1966
2576
  tree,
@@ -1972,11 +2582,11 @@ var MediaCollection = memo(
1972
2582
  },
1973
2583
  [media, tree, setMedia]
1974
2584
  );
1975
- const [isUploading, setIsUploading] = useState(false);
1976
- const handleUpload = useCallback(
2585
+ const [isUploading, setIsUploading] = useState4(false);
2586
+ const handleUpload = useCallback4(
1977
2587
  async (selectedId) => {
1978
2588
  try {
1979
- const files = await fileOpen({ multiple: true });
2589
+ const files = await fileOpen2({ multiple: true });
1980
2590
  if (!files || !Array.isArray(files) || files.length === 0) return;
1981
2591
  const parentPath = tree.idToPathMap.get(selectedId);
1982
2592
  if (!parentPath) return;
@@ -2013,7 +2623,7 @@ var MediaCollection = memo(
2013
2623
  },
2014
2624
  [tree.idToPathMap, setMedia, media, assetManager, onAssetsUploaded]
2015
2625
  );
2016
- const handleDownload = useCallback(
2626
+ const handleDownload = useCallback4(
2017
2627
  async (selectedItems) => {
2018
2628
  const downloadPromises = selectedItems.filter((item) => item.kind === "asset").map(async (item) => {
2019
2629
  const asset = assets.find((a) => a.stableId === item.assetId) ?? assets.find((a) => a.id === item.assetId);
@@ -2024,7 +2634,7 @@ var MediaCollection = memo(
2024
2634
  },
2025
2635
  [assets, tree]
2026
2636
  );
2027
- const handlePreview = useCallback(
2637
+ const handlePreview = useCallback4(
2028
2638
  async (selectedItems) => {
2029
2639
  const previewPromises = selectedItems.filter((item) => item.kind === "asset").map(async (item) => {
2030
2640
  const asset = assets.find((a) => a.stableId === item.assetId) ?? assets.find((a) => a.id === item.assetId);
@@ -2035,10 +2645,10 @@ var MediaCollection = memo(
2035
2645
  },
2036
2646
  [assets]
2037
2647
  );
2038
- const handleReplace = useCallback(
2648
+ const handleReplace = useCallback4(
2039
2649
  async (selectedItem) => {
2040
2650
  try {
2041
- const file = await fileOpen();
2651
+ const file = await fileOpen2();
2042
2652
  if (!file) return;
2043
2653
  const created = await assetManager.create(file);
2044
2654
  const assetStableId = created.id;
@@ -2064,13 +2674,13 @@ var MediaCollection = memo(
2064
2674
  },
2065
2675
  [media, setMedia, assetManager, tree]
2066
2676
  );
2067
- const handleRename = useCallback(
2677
+ const handleRename = useCallback4(
2068
2678
  (selectedItemId) => {
2069
2679
  collectionRef.current?.editName(selectedItemId);
2070
2680
  },
2071
2681
  [collectionRef]
2072
2682
  );
2073
- const handleMoveMediaInsideFolder = useCallback(
2683
+ const handleMoveMediaInsideFolder = useCallback4(
2074
2684
  (sourceItem, targetItem) => {
2075
2685
  const newMedia = mediaMoveMediaInsideFolder({
2076
2686
  sourceItemIds: [sourceItem.id],
@@ -2088,52 +2698,52 @@ var MediaCollection = memo(
2088
2698
  },
2089
2699
  [media, setMedia, tree]
2090
2700
  );
2091
- const assetContextMenuItems = useMemo(() => {
2092
- return createSectionedMenu(
2701
+ const assetContextMenuItems = useMemo3(() => {
2702
+ return createSectionedMenu2(
2093
2703
  [
2094
2704
  !rootSelected && singleItemSelected && {
2095
2705
  title: "Rename",
2096
2706
  value: "rename",
2097
- icon: /* @__PURE__ */ React.createElement(InputIcon, null)
2707
+ icon: /* @__PURE__ */ React2.createElement(InputIcon2, null)
2098
2708
  },
2099
2709
  onlySingleAssetSelected && {
2100
2710
  title: "Replace",
2101
2711
  value: "replace",
2102
- icon: /* @__PURE__ */ React.createElement(UpdateIcon, null)
2712
+ icon: /* @__PURE__ */ React2.createElement(UpdateIcon, null)
2103
2713
  },
2104
2714
  !rootSelected && {
2105
2715
  title: "Delete",
2106
2716
  value: "delete",
2107
- icon: /* @__PURE__ */ React.createElement(TrashIcon, null)
2717
+ icon: /* @__PURE__ */ React2.createElement(TrashIcon2, null)
2108
2718
  }
2109
2719
  ],
2110
2720
  [
2111
2721
  onlySingleFolderSelected && {
2112
2722
  title: "Upload Files",
2113
2723
  value: "upload",
2114
- icon: /* @__PURE__ */ React.createElement(UploadIcon, null)
2724
+ icon: /* @__PURE__ */ React2.createElement(UploadIcon2, null)
2115
2725
  },
2116
2726
  onlySingleFolderSelected && {
2117
2727
  title: "Add Folder",
2118
2728
  value: "addFolder",
2119
- icon: /* @__PURE__ */ React.createElement(FolderIcon, null)
2729
+ icon: /* @__PURE__ */ React2.createElement(FolderIcon, null)
2120
2730
  },
2121
2731
  onlyAssetsSelected && tree.mediaItemsWithRoot.length > 0 && {
2122
2732
  title: "Download",
2123
2733
  value: "download",
2124
- icon: /* @__PURE__ */ React.createElement(DownloadIcon, null)
2734
+ icon: /* @__PURE__ */ React2.createElement(DownloadIcon, null)
2125
2735
  },
2126
2736
  onlySingleAssetSelected && {
2127
2737
  title: "Preview",
2128
2738
  value: "preview",
2129
- icon: /* @__PURE__ */ React.createElement(OpenInNewWindowIcon, null)
2739
+ icon: /* @__PURE__ */ React2.createElement(OpenInNewWindowIcon, null)
2130
2740
  }
2131
2741
  ],
2132
2742
  [
2133
2743
  !rootSelected && sameParentSelected && {
2134
2744
  title: "Move up a folder",
2135
2745
  value: "move",
2136
- icon: /* @__PURE__ */ React.createElement(ResetIcon, null)
2746
+ icon: /* @__PURE__ */ React2.createElement(ResetIcon, null)
2137
2747
  }
2138
2748
  ]
2139
2749
  );
@@ -2146,7 +2756,7 @@ var MediaCollection = memo(
2146
2756
  tree.mediaItemsWithRoot.length,
2147
2757
  sameParentSelected
2148
2758
  ]);
2149
- const handleMenuAction = useCallback(
2759
+ const handleMenuAction = useCallback4(
2150
2760
  async (action, selectedItems) => {
2151
2761
  if (selectedItems.length === 0) return;
2152
2762
  switch (action) {
@@ -2188,7 +2798,7 @@ var MediaCollection = memo(
2188
2798
  handleMoveUpAFolder
2189
2799
  ]
2190
2800
  );
2191
- const handleSetExpanded = useCallback(
2801
+ const handleSetExpanded = useCallback4(
2192
2802
  (item, expanded) => {
2193
2803
  setExpandedMap(
2194
2804
  (prev) => mediaUpdateExpandedMap({
@@ -2202,12 +2812,12 @@ var MediaCollection = memo(
2202
2812
  },
2203
2813
  [expandable, tree]
2204
2814
  );
2205
- const renderAction = useMemo(() => {
2815
+ const renderAction = useMemo3(() => {
2206
2816
  if (renderActionProp) return renderActionProp;
2207
2817
  return ({
2208
2818
  selected,
2209
2819
  onOpenChange
2210
- }) => /* @__PURE__ */ React.createElement(
2820
+ }) => /* @__PURE__ */ React2.createElement(
2211
2821
  ActionMenu,
2212
2822
  {
2213
2823
  menuItems: assetContextMenuItems,
@@ -2228,7 +2838,7 @@ var MediaCollection = memo(
2228
2838
  selectedMediaItems,
2229
2839
  viewType
2230
2840
  ]);
2231
- useImperativeHandle(ref, () => ({
2841
+ useImperativeHandle2(ref, () => ({
2232
2842
  upload: (selectedId) => handleUpload(selectedId),
2233
2843
  delete: handleDelete,
2234
2844
  download: handleDownload,
@@ -2241,11 +2851,11 @@ var MediaCollection = memo(
2241
2851
  moveMediaInsideFolder: handleMoveMediaInsideFolder,
2242
2852
  getItemAtIndex: (index) => visibleItems[index]
2243
2853
  }));
2244
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
2854
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
2245
2855
  FileExplorerLayout,
2246
2856
  {
2247
2857
  title: title ?? rootMediaItemName,
2248
- right: !readOnly && /* @__PURE__ */ React.createElement(
2858
+ right: !readOnly && /* @__PURE__ */ React2.createElement(
2249
2859
  FileExplorerUploadButton,
2250
2860
  {
2251
2861
  showUploadButton,
@@ -2256,7 +2866,7 @@ var MediaCollection = memo(
2256
2866
  ),
2257
2867
  className
2258
2868
  },
2259
- /* @__PURE__ */ React.createElement(
2869
+ /* @__PURE__ */ React2.createElement(
2260
2870
  FileExplorerCollection,
2261
2871
  {
2262
2872
  ref: collectionRef,
@@ -2300,7 +2910,7 @@ var MediaCollection = memo(
2300
2910
  onRename,
2301
2911
  renamable,
2302
2912
  selectedIds,
2303
- renderThumbnail: (props) => /* @__PURE__ */ React.createElement(
2913
+ renderThumbnail: (props) => /* @__PURE__ */ React2.createElement(
2304
2914
  MediaThumbnailInternal,
2305
2915
  {
2306
2916
  ...props,
@@ -2313,9 +2923,9 @@ var MediaCollection = memo(
2313
2923
  if (file.kind !== "asset") return null;
2314
2924
  const asset = assets.find((a) => a.stableId === file.assetId) ?? assets.find((a) => a.id === file.assetId);
2315
2925
  if (!asset) return null;
2316
- return /* @__PURE__ */ React.createElement(FileExplorerDetail, { selected, size }, formatByteSize(asset.size));
2926
+ return /* @__PURE__ */ React2.createElement(FileExplorerDetail, { selected, size }, formatByteSize(asset.size));
2317
2927
  },
2318
- renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ React.createElement(FileExplorerEmptyState, null),
2928
+ renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ React2.createElement(FileExplorerEmptyState, null),
2319
2929
  itemRoleDescription: "clickable file item",
2320
2930
  getDropTargetParentIndex: (overIndex) => {
2321
2931
  const item = visibleItems[overIndex];
@@ -2391,7 +3001,7 @@ function acceptsMediaItemDrop(parameters) {
2391
3001
  import {
2392
3002
  ActionMenu as ActionMenu2,
2393
3003
  Chip,
2394
- createSectionedMenu as createSectionedMenu2,
3004
+ createSectionedMenu as createSectionedMenu3,
2395
3005
  cssVars as cssVars2,
2396
3006
  FileExplorerCollection as FileExplorerCollection2,
2397
3007
  FileExplorerDetail as FileExplorerDetail2,
@@ -2399,18 +3009,18 @@ import {
2399
3009
  FileExplorerLayout as FileExplorerLayout2,
2400
3010
  FileExplorerUploadButton as FileExplorerUploadButton2,
2401
3011
  formatByteSize as formatByteSize2,
2402
- MediaThumbnail as MediaThumbnail2,
2403
- useOpenConfirmationDialog as useOpenConfirmationDialog2
3012
+ MediaThumbnail as MediaThumbnail3,
3013
+ useOpenConfirmationDialog as useOpenConfirmationDialog3
2404
3014
  } from "@noya-app/noya-designsystem";
2405
3015
  import {
2406
3016
  DownloadIcon as DownloadIcon2,
2407
3017
  FolderIcon as FolderIcon2,
2408
- InputIcon as InputIcon2,
3018
+ InputIcon as InputIcon3,
2409
3019
  OpenInNewWindowIcon as OpenInNewWindowIcon2,
2410
3020
  ResetIcon as ResetIcon2,
2411
- TrashIcon as TrashIcon2,
3021
+ TrashIcon as TrashIcon3,
2412
3022
  UpdateIcon as UpdateIcon2,
2413
- UploadIcon as UploadIcon2
3023
+ UploadIcon as UploadIcon3
2414
3024
  } from "@noya-app/noya-icons";
2415
3025
  import {
2416
3026
  useAsset as useAsset2,
@@ -2433,19 +3043,19 @@ import {
2433
3043
  SingleDimensionAutoSizer,
2434
3044
  useControlledOrUncontrolled as useControlledOrUncontrolled2
2435
3045
  } from "@noya-app/react-utils";
2436
- import { fileOpen as fileOpen2 } from "browser-fs-access";
3046
+ import { fileOpen as fileOpen3 } from "browser-fs-access";
2437
3047
  import {
2438
- forwardRef as forwardRef2,
2439
- memo as memo2,
2440
- useCallback as useCallback2,
2441
- useEffect as useEffect2,
2442
- useImperativeHandle as useImperativeHandle2,
2443
- useMemo as useMemo2,
2444
- useRef as useRef2,
2445
- useState as useState2
3048
+ forwardRef as forwardRef3,
3049
+ memo as memo3,
3050
+ useCallback as useCallback5,
3051
+ useEffect as useEffect3,
3052
+ useImperativeHandle as useImperativeHandle3,
3053
+ useMemo as useMemo4,
3054
+ useRef as useRef3,
3055
+ useState as useState5
2446
3056
  } from "react";
2447
3057
  import { path as path6 } from "imfs";
2448
- import React2 from "react";
3058
+ import React3 from "react";
2449
3059
 
2450
3060
  // src/utils/contentType.ts
2451
3061
  function getContentTypeFromFile(file) {
@@ -2529,13 +3139,8 @@ import {
2529
3139
  createDirectoryResource
2530
3140
  } from "@noya-app/noya-schemas";
2531
3141
  import { Base64, uuid as uuid2 } from "@noya-app/noya-utils";
3142
+ import { collectDroppedFiles as collectDroppedFiles2 } from "@noya-app/react-utils";
2532
3143
  import { path as path5 } from "imfs";
2533
- function isDirectoryEntry(entry) {
2534
- return entry.isDirectory;
2535
- }
2536
- function isFileEntry(entry) {
2537
- return entry.isFile;
2538
- }
2539
3144
  async function handleDataTransfer({
2540
3145
  accessibleByFileId,
2541
3146
  dataTransfer,
@@ -2543,66 +3148,7 @@ async function handleDataTransfer({
2543
3148
  resourceMap
2544
3149
  }) {
2545
3150
  try {
2546
- const dataTransferItems = Array.from(dataTransfer.items ?? []);
2547
- const supportsEntries = dataTransferItems.some(
2548
- (item) => typeof item?.webkitGetAsEntry === "function"
2549
- );
2550
- const collectFromEntry = async (entry, basePath) => {
2551
- if (!entry) return [];
2552
- if (isFileEntry(entry)) {
2553
- const file = await new Promise(
2554
- (resolve) => entry.file((f) => resolve(f))
2555
- );
2556
- return [
2557
- {
2558
- file,
2559
- relativePath: path5.join(basePath, file.name)
2560
- }
2561
- ];
2562
- }
2563
- if (isDirectoryEntry(entry)) {
2564
- const reader = entry.createReader();
2565
- const readAll = async () => {
2566
- const all = [];
2567
- while (true) {
2568
- const entries = await new Promise(
2569
- (resolve) => reader.readEntries((ents) => resolve(ents))
2570
- );
2571
- if (!entries.length) break;
2572
- all.push(...entries);
2573
- }
2574
- return all;
2575
- };
2576
- const children = await readAll();
2577
- const results = await Promise.all(
2578
- children.map(
2579
- (child) => collectFromEntry(child, path5.join(basePath, entry.name))
2580
- )
2581
- );
2582
- return results.flat();
2583
- }
2584
- return [];
2585
- };
2586
- let dropped = [];
2587
- if (supportsEntries) {
2588
- const topLevelEntries = dataTransferItems.flatMap((item) => {
2589
- const entry = item.webkitGetAsEntry?.();
2590
- if (!entry) return [];
2591
- return [entry];
2592
- });
2593
- const nested = await Promise.all(
2594
- topLevelEntries.map((entry) => collectFromEntry(entry, ""))
2595
- );
2596
- dropped = nested.flat();
2597
- } else {
2598
- const files = Array.from(dataTransfer.files);
2599
- if (files.length === 0) return;
2600
- dropped = files.map((file) => ({
2601
- file,
2602
- // Best effort: try webkitRelativePath; fall back to name
2603
- relativePath: file.webkitRelativePath && file.webkitRelativePath.length > 0 ? file.webkitRelativePath : file.name
2604
- }));
2605
- }
3151
+ const dropped = await collectDroppedFiles2(dataTransfer);
2606
3152
  if (dropped.length === 0) return;
2607
3153
  const folderRelativePaths = /* @__PURE__ */ new Set();
2608
3154
  for (const { relativePath } of dropped) {
@@ -2684,8 +3230,8 @@ var ResourceThumbnail = memoGeneric2(
2684
3230
  contentType = contentTypeProp;
2685
3231
  }
2686
3232
  const fileName = pathProp ? path6.basename(pathProp) : void 0;
2687
- return /* @__PURE__ */ React2.createElement(
2688
- MediaThumbnail2,
3233
+ return /* @__PURE__ */ React3.createElement(
3234
+ MediaThumbnail3,
2689
3235
  {
2690
3236
  contentType,
2691
3237
  iconName: isRoot ? "HomeIcon" : isFolder ? "FolderIcon" : void 0,
@@ -2700,8 +3246,8 @@ var ResourceThumbnail = memoGeneric2(
2700
3246
  );
2701
3247
  }
2702
3248
  );
2703
- var ResourceExplorer = memo2(
2704
- forwardRef2(
3249
+ var ResourceExplorer = memo3(
3250
+ forwardRef3(
2705
3251
  function ResourceExplorer2({
2706
3252
  parentFileId,
2707
3253
  sortableId,
@@ -2740,28 +3286,28 @@ var ResourceExplorer = memo2(
2740
3286
  renderUser,
2741
3287
  showFileSizes = true
2742
3288
  }, ref) {
2743
- const setMedia = useCallback2(
3289
+ const setMedia = useCallback5(
2744
3290
  (...args) => {
2745
3291
  setMediaProp?.(...args);
2746
3292
  },
2747
3293
  [setMediaProp]
2748
3294
  );
2749
- const tree = useMemo2(() => createResourceTree2(media), [media]);
2750
- const [tempItem, setTempItem] = useState2(
3295
+ const tree = useMemo4(() => createResourceTree2(media), [media]);
3296
+ const [tempItem, setTempItem] = useState5(
2751
3297
  void 0
2752
3298
  );
2753
- const mediaWithTempItem = useMemo2(
3299
+ const mediaWithTempItem = useMemo4(
2754
3300
  () => ({
2755
3301
  ...media,
2756
3302
  ...tempItem ? { [tempItem[0]]: tempItem[1] } : {}
2757
3303
  }),
2758
3304
  [media, tempItem]
2759
3305
  );
2760
- const treeWithTempItem = useMemo2(
3306
+ const treeWithTempItem = useMemo4(
2761
3307
  () => createResourceTree2(mediaWithTempItem),
2762
3308
  [mediaWithTempItem]
2763
3309
  );
2764
- const temp = useMemo2(
3310
+ const temp = useMemo4(
2765
3311
  () => ({
2766
3312
  media: mediaWithTempItem,
2767
3313
  tree: treeWithTempItem
@@ -2775,9 +3321,9 @@ var ResourceExplorer = memo2(
2775
3321
  });
2776
3322
  const assetManager = useAssetManager2();
2777
3323
  const assets = useAssets2();
2778
- const [expandedMap, setExpandedMap] = useState2({});
2779
- const visibleItems = useMemo2(
2780
- () => getVisibleItems({
3324
+ const [expandedMap, setExpandedMap] = useState5({});
3325
+ const visibleItems = useMemo4(
3326
+ () => getVisibleItems2({
2781
3327
  expandedMap,
2782
3328
  fileKindFilter,
2783
3329
  rootItemId,
@@ -2794,12 +3340,12 @@ var ResourceExplorer = memo2(
2794
3340
  showRootItem
2795
3341
  ]
2796
3342
  );
2797
- const depthMap = useMemo2(
3343
+ const depthMap = useMemo4(
2798
3344
  () => getDepthMap(rootResource2, treeWithTempItem, showAllDescendants),
2799
3345
  [treeWithTempItem, showAllDescendants]
2800
3346
  );
2801
- const collectionRef = useRef2(null);
2802
- const selectedResources = useMemo2(
3347
+ const collectionRef = useRef3(null);
3348
+ const selectedResources = useMemo4(
2803
3349
  () => treeWithTempItem.resourcesWithRoot.filter(
2804
3350
  (item) => selectedIds.includes(item.id)
2805
3351
  ),
@@ -2820,12 +3366,12 @@ var ResourceExplorer = memo2(
2820
3366
  if (!itemPath || !firstSelectedPath) return false;
2821
3367
  return itemPath.startsWith(path6.dirname(firstSelectedPath));
2822
3368
  });
2823
- useEffect2(() => {
3369
+ useEffect3(() => {
2824
3370
  if (initialExpanded) {
2825
3371
  setExpandedMap(initialExpanded);
2826
3372
  }
2827
3373
  }, [initialExpanded]);
2828
- const getExpanded = useCallback2(
3374
+ const getExpanded = useCallback5(
2829
3375
  (item) => {
2830
3376
  if (!expandable) return void 0;
2831
3377
  if (item.type !== "directory") return void 0;
@@ -2834,8 +3380,8 @@ var ResourceExplorer = memo2(
2834
3380
  },
2835
3381
  [expandedMap, expandable]
2836
3382
  );
2837
- const openConfirmationDialog = useOpenConfirmationDialog2();
2838
- const handleDelete = useCallback2(
3383
+ const openConfirmationDialog = useOpenConfirmationDialog3();
3384
+ const handleDelete = useCallback5(
2839
3385
  async (selectedIds2) => {
2840
3386
  const ok = await openConfirmationDialog({
2841
3387
  title: "Delete items",
@@ -2868,7 +3414,7 @@ var ResourceExplorer = memo2(
2868
3414
  openConfirmationDialog
2869
3415
  ]
2870
3416
  );
2871
- const onRename = useCallback2(
3417
+ const onRename = useCallback5(
2872
3418
  (selectedItem, newName) => {
2873
3419
  if (!renamable) return;
2874
3420
  const selectedItemPath = treeWithTempItem.idToPathMap.get(
@@ -2904,7 +3450,7 @@ var ResourceExplorer = memo2(
2904
3450
  treeWithTempItem.idToPathMap
2905
3451
  ]
2906
3452
  );
2907
- const handleAddFolder = useCallback2(
3453
+ const handleAddFolder = useCallback5(
2908
3454
  (currentFolderId) => {
2909
3455
  const currentFolderPath = tree.idToPathMap.get(currentFolderId);
2910
3456
  if (!currentFolderPath) return;
@@ -2925,7 +3471,7 @@ var ResourceExplorer = memo2(
2925
3471
  },
2926
3472
  [parentFileId, tree]
2927
3473
  );
2928
- const handleMoveUpAFolder = useCallback2(
3474
+ const handleMoveUpAFolder = useCallback5(
2929
3475
  (selectedIds2) => {
2930
3476
  const newMedia = moveUpAFolder({
2931
3477
  tree,
@@ -2937,11 +3483,11 @@ var ResourceExplorer = memo2(
2937
3483
  },
2938
3484
  [media, tree, setMedia]
2939
3485
  );
2940
- const [isUploading, setIsUploading] = useState2(false);
2941
- const handleUpload = useCallback2(
3486
+ const [isUploading, setIsUploading] = useState5(false);
3487
+ const handleUpload = useCallback5(
2942
3488
  async (selectedId) => {
2943
3489
  try {
2944
- const files = await fileOpen2({ multiple: true });
3490
+ const files = await fileOpen3({ multiple: true });
2945
3491
  if (!files || !Array.isArray(files) || files.length === 0) return;
2946
3492
  const parentPath = tree.idToPathMap.get(selectedId);
2947
3493
  if (!parentPath) return;
@@ -2986,7 +3532,7 @@ var ResourceExplorer = memo2(
2986
3532
  },
2987
3533
  [tree, setMedia, media, onAssetsUploaded, parentFileId]
2988
3534
  );
2989
- const handleDownload = useCallback2(
3535
+ const handleDownload = useCallback5(
2990
3536
  async (selectedItems) => {
2991
3537
  const downloadPromises = selectedItems.filter((item) => item.type === "asset").map(async (item) => {
2992
3538
  const asset = assets.find((a) => a.stableId === item.assetId) ?? assets.find((a) => a.id === item.assetId);
@@ -2997,7 +3543,7 @@ var ResourceExplorer = memo2(
2997
3543
  },
2998
3544
  [assets, tree]
2999
3545
  );
3000
- const handlePreview = useCallback2(
3546
+ const handlePreview = useCallback5(
3001
3547
  async (selectedItems) => {
3002
3548
  const previewPromises = selectedItems.filter((item) => item.type === "asset").map(async (item) => {
3003
3549
  const asset = assets.find((a) => a.stableId === item.assetId) ?? assets.find((a) => a.id === item.assetId);
@@ -3008,10 +3554,10 @@ var ResourceExplorer = memo2(
3008
3554
  },
3009
3555
  [assets]
3010
3556
  );
3011
- const handleReplace = useCallback2(
3557
+ const handleReplace = useCallback5(
3012
3558
  async (selectedItem) => {
3013
3559
  try {
3014
- const file = await fileOpen2();
3560
+ const file = await fileOpen3();
3015
3561
  if (!file) return;
3016
3562
  const created = await assetManager.create(file);
3017
3563
  const assetStableId = created.id;
@@ -3037,13 +3583,13 @@ var ResourceExplorer = memo2(
3037
3583
  },
3038
3584
  [media, setMedia, assetManager, tree]
3039
3585
  );
3040
- const handleRename = useCallback2(
3586
+ const handleRename = useCallback5(
3041
3587
  (selectedItemId) => {
3042
3588
  collectionRef.current?.editName(selectedItemId);
3043
3589
  },
3044
3590
  [collectionRef]
3045
3591
  );
3046
- const handleMoveMediaInsideFolder = useCallback2(
3592
+ const handleMoveMediaInsideFolder = useCallback5(
3047
3593
  (sourceItems, targetItem) => {
3048
3594
  const newMedia = moveMediaInsideFolder({
3049
3595
  sourceItemIds: sourceItems.map((item) => item.id),
@@ -3061,52 +3607,52 @@ var ResourceExplorer = memo2(
3061
3607
  },
3062
3608
  [media, setMedia, tree]
3063
3609
  );
3064
- const assetContextMenuItems = useMemo2(() => {
3065
- return createSectionedMenu2(
3610
+ const assetContextMenuItems = useMemo4(() => {
3611
+ return createSectionedMenu3(
3066
3612
  [
3067
3613
  !rootSelected && singleItemSelected && {
3068
3614
  title: "Rename",
3069
3615
  value: "rename",
3070
- icon: /* @__PURE__ */ React2.createElement(InputIcon2, null)
3616
+ icon: /* @__PURE__ */ React3.createElement(InputIcon3, null)
3071
3617
  },
3072
3618
  onlySingleAssetSelected && {
3073
3619
  title: "Replace",
3074
3620
  value: "replace",
3075
- icon: /* @__PURE__ */ React2.createElement(UpdateIcon2, null)
3621
+ icon: /* @__PURE__ */ React3.createElement(UpdateIcon2, null)
3076
3622
  },
3077
3623
  !rootSelected && {
3078
3624
  title: "Delete",
3079
3625
  value: "delete",
3080
- icon: /* @__PURE__ */ React2.createElement(TrashIcon2, null)
3626
+ icon: /* @__PURE__ */ React3.createElement(TrashIcon3, null)
3081
3627
  }
3082
3628
  ],
3083
3629
  [
3084
3630
  onlySingleFolderSelected && {
3085
3631
  title: "Upload Files",
3086
3632
  value: "upload",
3087
- icon: /* @__PURE__ */ React2.createElement(UploadIcon2, null)
3633
+ icon: /* @__PURE__ */ React3.createElement(UploadIcon3, null)
3088
3634
  },
3089
3635
  onlySingleFolderSelected && {
3090
3636
  title: "Add Folder",
3091
3637
  value: "addFolder",
3092
- icon: /* @__PURE__ */ React2.createElement(FolderIcon2, null)
3638
+ icon: /* @__PURE__ */ React3.createElement(FolderIcon2, null)
3093
3639
  },
3094
3640
  onlyAssetsSelected && tree.resourcesWithRoot.length > 0 && {
3095
3641
  title: "Download",
3096
3642
  value: "download",
3097
- icon: /* @__PURE__ */ React2.createElement(DownloadIcon2, null)
3643
+ icon: /* @__PURE__ */ React3.createElement(DownloadIcon2, null)
3098
3644
  },
3099
3645
  onlySingleAssetSelected && {
3100
3646
  title: "Preview",
3101
3647
  value: "preview",
3102
- icon: /* @__PURE__ */ React2.createElement(OpenInNewWindowIcon2, null)
3648
+ icon: /* @__PURE__ */ React3.createElement(OpenInNewWindowIcon2, null)
3103
3649
  }
3104
3650
  ],
3105
3651
  [
3106
3652
  !rootSelected && sameParentSelected && {
3107
3653
  title: "Move up a folder",
3108
3654
  value: "move",
3109
- icon: /* @__PURE__ */ React2.createElement(ResetIcon2, null)
3655
+ icon: /* @__PURE__ */ React3.createElement(ResetIcon2, null)
3110
3656
  }
3111
3657
  ]
3112
3658
  );
@@ -3119,7 +3665,7 @@ var ResourceExplorer = memo2(
3119
3665
  tree.resourcesWithRoot.length,
3120
3666
  sameParentSelected
3121
3667
  ]);
3122
- const handleMenuAction = useCallback2(
3668
+ const handleMenuAction = useCallback5(
3123
3669
  async (action, selectedItems) => {
3124
3670
  if (selectedItems.length === 0) return;
3125
3671
  switch (action) {
@@ -3161,7 +3707,7 @@ var ResourceExplorer = memo2(
3161
3707
  handleMoveUpAFolder
3162
3708
  ]
3163
3709
  );
3164
- const handleSetExpanded = useCallback2(
3710
+ const handleSetExpanded = useCallback5(
3165
3711
  (item, expanded) => {
3166
3712
  setExpandedMap(
3167
3713
  (prev) => updateExpandedMap({
@@ -3175,12 +3721,12 @@ var ResourceExplorer = memo2(
3175
3721
  },
3176
3722
  [expandable, tree]
3177
3723
  );
3178
- const renderAction = useMemo2(() => {
3724
+ const renderAction = useMemo4(() => {
3179
3725
  if (renderActionProp) return renderActionProp;
3180
3726
  return ({
3181
3727
  selected,
3182
3728
  onOpenChange
3183
- }) => /* @__PURE__ */ React2.createElement(
3729
+ }) => /* @__PURE__ */ React3.createElement(
3184
3730
  "div",
3185
3731
  {
3186
3732
  style: {
@@ -3189,7 +3735,7 @@ var ResourceExplorer = memo2(
3189
3735
  justifyContent: "flex-end"
3190
3736
  }
3191
3737
  },
3192
- /* @__PURE__ */ React2.createElement(
3738
+ /* @__PURE__ */ React3.createElement(
3193
3739
  ActionMenu2,
3194
3740
  {
3195
3741
  menuItems: assetContextMenuItems,
@@ -3211,7 +3757,7 @@ var ResourceExplorer = memo2(
3211
3757
  selectedResources,
3212
3758
  viewType
3213
3759
  ]);
3214
- useImperativeHandle2(ref, () => ({
3760
+ useImperativeHandle3(ref, () => ({
3215
3761
  upload: (selectedId) => handleUpload(selectedId),
3216
3762
  delete: handleDelete,
3217
3763
  download: handleDownload,
@@ -3223,7 +3769,7 @@ var ResourceExplorer = memo2(
3223
3769
  moveMediaInsideFolder: handleMoveMediaInsideFolder,
3224
3770
  getItemAtIndex: (index) => visibleItems[index]
3225
3771
  }));
3226
- const diffResources = useMemo2(() => {
3772
+ const diffResources = useMemo4(() => {
3227
3773
  if (!publishedResources) return;
3228
3774
  const diff = diffResourceMaps(publishedResources, media, "stableId");
3229
3775
  return {
@@ -3238,8 +3784,8 @@ var ResourceExplorer = memo2(
3238
3784
  )
3239
3785
  };
3240
3786
  }, [media, publishedResources]);
3241
- const keyExtractor = useCallback2((item) => item.id, []);
3242
- const renderCollection = (virtualizedHeight) => /* @__PURE__ */ React2.createElement(
3787
+ const keyExtractor = useCallback5((item) => item.id, []);
3788
+ const renderCollection = (virtualizedHeight) => /* @__PURE__ */ React3.createElement(
3243
3789
  FileExplorerCollection2,
3244
3790
  {
3245
3791
  ref: collectionRef,
@@ -3290,7 +3836,7 @@ var ResourceExplorer = memo2(
3290
3836
  itemClassName,
3291
3837
  itemStyle,
3292
3838
  virtualized: virtualizedHeight,
3293
- renderThumbnail: (props) => /* @__PURE__ */ React2.createElement(
3839
+ renderThumbnail: (props) => /* @__PURE__ */ React3.createElement(
3294
3840
  ResourceThumbnail,
3295
3841
  {
3296
3842
  ...props,
@@ -3306,12 +3852,12 @@ var ResourceExplorer = memo2(
3306
3852
  resource: file,
3307
3853
  diff: diffResources
3308
3854
  });
3309
- return /* @__PURE__ */ React2.createElement(
3855
+ return /* @__PURE__ */ React3.createElement(
3310
3856
  "div",
3311
3857
  {
3312
3858
  style: { display: "flex", alignItems: "center", gap: "6px" }
3313
3859
  },
3314
- publishStatus && /* @__PURE__ */ React2.createElement(
3860
+ publishStatus && /* @__PURE__ */ React3.createElement(
3315
3861
  Chip,
3316
3862
  {
3317
3863
  colorScheme: publishStatus === "Modified" ? "info" : publishStatus === "Added" ? "secondary" : "primary"
@@ -3326,7 +3872,7 @@ var ResourceExplorer = memo2(
3326
3872
  if (file.type !== "asset") return null;
3327
3873
  const asset = assets.find((a) => a.stableId === file.assetId) ?? assets.find((a) => a.id === file.assetId);
3328
3874
  if (!asset) return null;
3329
- return /* @__PURE__ */ React2.createElement(
3875
+ return /* @__PURE__ */ React3.createElement(
3330
3876
  FileExplorerDetail2,
3331
3877
  {
3332
3878
  selected,
@@ -3336,7 +3882,7 @@ var ResourceExplorer = memo2(
3336
3882
  formatByteSize2(asset.size)
3337
3883
  );
3338
3884
  },
3339
- renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ React2.createElement(FileExplorerEmptyState2, null),
3885
+ renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ React3.createElement(FileExplorerEmptyState2, null),
3340
3886
  itemRoleDescription: "clickable file item",
3341
3887
  getDropTargetParentIndex: (overIndex) => {
3342
3888
  const item = visibleItems[overIndex];
@@ -3403,11 +3949,11 @@ var ResourceExplorer = memo2(
3403
3949
  }
3404
3950
  }
3405
3951
  );
3406
- return /* @__PURE__ */ React2.createElement(
3952
+ return /* @__PURE__ */ React3.createElement(
3407
3953
  FileExplorerLayout2,
3408
3954
  {
3409
3955
  title: title ?? rootResourceName,
3410
- right: !readOnly && /* @__PURE__ */ React2.createElement(
3956
+ right: !readOnly && /* @__PURE__ */ React3.createElement(
3411
3957
  FileExplorerUploadButton2,
3412
3958
  {
3413
3959
  showUploadButton,
@@ -3418,7 +3964,7 @@ var ResourceExplorer = memo2(
3418
3964
  ),
3419
3965
  className
3420
3966
  },
3421
- virtualized ? /* @__PURE__ */ React2.createElement(SingleDimensionAutoSizer, { dimension: "height" }, (height) => renderCollection(height)) : renderCollection(void 0)
3967
+ virtualized ? /* @__PURE__ */ React3.createElement(SingleDimensionAutoSizer, { dimension: "height" }, (height) => renderCollection(height)) : renderCollection(void 0)
3422
3968
  );
3423
3969
  }
3424
3970
  )
@@ -3454,6 +4000,7 @@ function getPublishStatus({
3454
4000
  );
3455
4001
  }
3456
4002
  export {
4003
+ GitFileExplorer2 as GitFileExplorer,
3457
4004
  MediaCollection,
3458
4005
  PLACEHOLDER_ITEM_NAME,
3459
4006
  ResourceExplorer,
@@ -3471,7 +4018,7 @@ export {
3471
4018
  getContentTypeFromFile,
3472
4019
  getDepthMap,
3473
4020
  getParentDirectories,
3474
- getVisibleItems,
4021
+ getVisibleItems2 as getVisibleItems,
3475
4022
  gridThumbnailDimension,
3476
4023
  mediaDeleteMediaItems,
3477
4024
  mediaGetDepthMap,