@noya-app/noya-file-explorer 0.0.16 → 0.0.17
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/.turbo/turbo-build.log +13 -13
- package/CHANGELOG.md +13 -0
- package/dist/index.css +853 -894
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +624 -33
- package/dist/index.d.ts +624 -33
- package/dist/index.js +1346 -265
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1384 -262
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/MediaCollection.tsx +74 -53
- package/src/ResourceExplorer.tsx +1141 -0
- package/src/__tests__/deleteMediaItems.test.ts +7 -7
- package/src/__tests__/getDepthMap.test.ts +7 -7
- package/src/__tests__/getParentDirectories.test.ts +6 -6
- package/src/__tests__/getVisibleItems.test.ts +9 -9
- package/src/__tests__/moveMediaInsideFolder.test.ts +11 -11
- package/src/__tests__/movePathsIntoTarget.test.ts +9 -9
- package/src/__tests__/moveUpAFolder.test.ts +7 -7
- package/src/__tests__/renameMediaItemAndDescendantPaths.test.ts +6 -6
- package/src/__tests__/updateExpandedMap.test.ts +8 -8
- package/src/__tests__/validateMediaItemRename.test.ts +11 -11
- package/src/index.ts +2 -0
- package/src/utils/files.ts +25 -37
- package/src/utils/handleFileDrop.ts +38 -15
- package/src/utils/resourceUtils.ts +329 -0
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
|
|
48
|
-
while (
|
|
49
|
-
let index =
|
|
50
|
-
const children = options.getChildren(node,
|
|
47
|
+
let path7 = indexPath.slice();
|
|
48
|
+
while (path7.length > 0) {
|
|
49
|
+
let index = path7.shift();
|
|
50
|
+
const children = options.getChildren(node, path7);
|
|
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
|
|
63
|
+
let path7 = indexPath.slice();
|
|
64
64
|
let result = [node];
|
|
65
|
-
while (
|
|
66
|
-
let index =
|
|
65
|
+
while (path7.length > 0) {
|
|
66
|
+
let index = path7.shift();
|
|
67
67
|
const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
|
|
68
|
-
const children = options.getChildren(node,
|
|
68
|
+
const children = options.getChildren(node, path7, 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
|
|
84
|
-
while (
|
|
85
|
-
let index =
|
|
86
|
-
node = options.getChildren(node,
|
|
83
|
+
let path7 = indexPath.slice();
|
|
84
|
+
while (path7.length > 0) {
|
|
85
|
+
let index = path7.shift();
|
|
86
|
+
node = options.getChildren(node, path7)[index];
|
|
87
87
|
}
|
|
88
88
|
return node;
|
|
89
89
|
}
|
|
90
90
|
function accessPath(node, indexPath, options) {
|
|
91
|
-
let
|
|
91
|
+
let path7 = indexPath.slice();
|
|
92
92
|
let result = [node];
|
|
93
|
-
while (
|
|
94
|
-
let index =
|
|
93
|
+
while (path7.length > 0) {
|
|
94
|
+
let index = path7.shift();
|
|
95
95
|
const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
|
|
96
|
-
node = options.getChildren(node,
|
|
96
|
+
node = options.getChildren(node, path7, context)[index];
|
|
97
97
|
result.push(node);
|
|
98
98
|
}
|
|
99
99
|
return result;
|
|
@@ -135,9 +135,9 @@ var require_ancestors = __commonJS({
|
|
|
135
135
|
"../../node_modules/tree-visit/lib/ancestors.js"(exports2) {
|
|
136
136
|
"use strict";
|
|
137
137
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
138
|
-
exports2.ancestorPaths =
|
|
138
|
+
exports2.ancestorPaths = ancestorPaths3;
|
|
139
139
|
var sort_1 = require_sort();
|
|
140
|
-
function
|
|
140
|
+
function ancestorPaths3(paths, options) {
|
|
141
141
|
var _a;
|
|
142
142
|
const result = /* @__PURE__ */ new Map();
|
|
143
143
|
const compare = (_a = options === null || options === void 0 ? void 0 : options.compare) !== null && _a !== void 0 ? _a : sort_1.comparePathsByComponent;
|
|
@@ -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(
|
|
611
|
-
const length = Math.min(
|
|
610
|
+
function commonAncestor(path7, otherPath) {
|
|
611
|
+
const length = Math.min(path7.length, otherPath.length);
|
|
612
612
|
for (let i = 0; i < length; i++) {
|
|
613
|
-
if (
|
|
614
|
-
return
|
|
613
|
+
if (path7[i] !== otherPath[i]) {
|
|
614
|
+
return path7.slice(0, i);
|
|
615
615
|
}
|
|
616
616
|
}
|
|
617
|
-
return
|
|
617
|
+
return path7.slice(0, length);
|
|
618
618
|
}
|
|
619
|
-
function transformPath(
|
|
620
|
-
if (otherPath.length >
|
|
621
|
-
return
|
|
619
|
+
function transformPath(path7, operation, otherPath, count = 1) {
|
|
620
|
+
if (otherPath.length > path7.length || (0, sort_1.comparePathsByComponent)(otherPath, path7) > 0) {
|
|
621
|
+
return path7;
|
|
622
622
|
}
|
|
623
623
|
if (otherPath.length === 0 && operation === "remove") {
|
|
624
624
|
return void 0;
|
|
625
625
|
}
|
|
626
|
-
const common = commonAncestor(
|
|
627
|
-
const adjustmentIndex = common.length ===
|
|
628
|
-
const pathValue =
|
|
626
|
+
const common = commonAncestor(path7, otherPath);
|
|
627
|
+
const adjustmentIndex = common.length === path7.length || common.length === otherPath.length ? common.length - 1 : common.length;
|
|
628
|
+
const pathValue = path7[adjustmentIndex];
|
|
629
629
|
const otherPathValue = otherPath[adjustmentIndex];
|
|
630
630
|
if (operation === "insert" && otherPathValue <= pathValue) {
|
|
631
|
-
const newPath = [...
|
|
631
|
+
const newPath = [...path7];
|
|
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 = [...
|
|
638
|
+
const newPath = [...path7];
|
|
639
639
|
newPath[adjustmentIndex] -= count;
|
|
640
640
|
return newPath;
|
|
641
641
|
}
|
|
642
642
|
}
|
|
643
|
-
return
|
|
643
|
+
return path7;
|
|
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((
|
|
809
|
+
return transformedPaths.map((path7) => path7 ? (0, transformPath_1.transformPath)(path7, "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((
|
|
813
|
+
return transformedPaths.map((path7) => {
|
|
814
814
|
for (const otherPath of otherPaths) {
|
|
815
|
-
|
|
815
|
+
path7 = path7 ? (0, transformPath_1.transformPath)(path7, "remove", otherPath) : void 0;
|
|
816
816
|
}
|
|
817
|
-
return
|
|
817
|
+
return path7;
|
|
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:
|
|
955
|
-
if (
|
|
954
|
+
const { path: path7, deleteCount = 0, nodes, track } = options;
|
|
955
|
+
if (path7.length === 0) {
|
|
956
956
|
throw new Error(`Can't splice at the root`);
|
|
957
957
|
}
|
|
958
|
-
const pathsToRemove = getPathsToRemove(
|
|
959
|
-
const operations = (0, operation_1.getInsertionOperations)(
|
|
958
|
+
const pathsToRemove = getPathsToRemove(path7, deleteCount);
|
|
959
|
+
const operations = (0, operation_1.getInsertionOperations)(path7, 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(
|
|
966
|
+
function getPathsToRemove(path7, deleteCount) {
|
|
967
967
|
let pathsToRemove = [];
|
|
968
|
-
let parentPath =
|
|
969
|
-
let index =
|
|
968
|
+
let parentPath = path7.slice(0, -1);
|
|
969
|
+
let index = path7[path7.length - 1];
|
|
970
970
|
for (let i = 0; i < deleteCount; i++) {
|
|
971
971
|
pathsToRemove.push(parentPath.concat(index + i));
|
|
972
972
|
}
|
|
@@ -1111,26 +1111,40 @@ var src_exports = {};
|
|
|
1111
1111
|
__export(src_exports, {
|
|
1112
1112
|
MediaCollection: () => MediaCollection,
|
|
1113
1113
|
PLACEHOLDER_ITEM_NAME: () => PLACEHOLDER_ITEM_NAME,
|
|
1114
|
+
ResourceExplorer: () => ResourceExplorer,
|
|
1115
|
+
ResourceThumbnail: () => ResourceThumbnail,
|
|
1114
1116
|
acceptsMediaItemDrop: () => acceptsMediaItemDrop,
|
|
1117
|
+
acceptsResourceDrop: () => acceptsResourceDrop,
|
|
1115
1118
|
basenameValidator: () => basenameValidator,
|
|
1116
1119
|
createMediaAsset: () => createMediaAsset,
|
|
1117
1120
|
createMediaFile: () => createMediaFile,
|
|
1118
1121
|
createMediaFolder: () => createMediaFolder,
|
|
1119
1122
|
createMediaItem: () => createMediaItem,
|
|
1120
1123
|
createMediaItemTree: () => createMediaItemTree,
|
|
1121
|
-
|
|
1124
|
+
deleteResources: () => deleteResources,
|
|
1122
1125
|
getDepthMap: () => getDepthMap,
|
|
1123
1126
|
getParentDirectories: () => getParentDirectories,
|
|
1124
1127
|
getVisibleItems: () => getVisibleItems,
|
|
1128
|
+
gridThumbnailDimension: () => gridThumbnailDimension,
|
|
1129
|
+
mediaDeleteMediaItems: () => mediaDeleteMediaItems,
|
|
1130
|
+
mediaGetDepthMap: () => mediaGetDepthMap,
|
|
1131
|
+
mediaGetParentDirectories: () => mediaGetParentDirectories,
|
|
1132
|
+
mediaGetVisibleItems: () => mediaGetVisibleItems,
|
|
1133
|
+
mediaMoveMediaInsideFolder: () => mediaMoveMediaInsideFolder,
|
|
1134
|
+
mediaMovePathsIntoTarget: () => mediaMovePathsIntoTarget,
|
|
1135
|
+
mediaMoveUpAFolder: () => mediaMoveUpAFolder,
|
|
1136
|
+
mediaRenameMediaItemAndDescendantPaths: () => mediaRenameMediaItemAndDescendantPaths,
|
|
1137
|
+
mediaUpdateExpandedMap: () => mediaUpdateExpandedMap,
|
|
1138
|
+
mediaValidateMediaItemRename: () => mediaValidateMediaItemRename,
|
|
1125
1139
|
moveMediaInsideFolder: () => moveMediaInsideFolder,
|
|
1126
1140
|
movePathsIntoTarget: () => movePathsIntoTarget,
|
|
1127
1141
|
moveUpAFolder: () => moveUpAFolder,
|
|
1128
|
-
|
|
1142
|
+
renameResourceAndDescendantPaths: () => renameResourceAndDescendantPaths,
|
|
1129
1143
|
rootMediaItem: () => rootMediaItem,
|
|
1130
1144
|
rootMediaItemName: () => rootMediaItemName,
|
|
1131
1145
|
rootMediaItemPath: () => rootMediaItemPath,
|
|
1132
1146
|
updateExpandedMap: () => updateExpandedMap,
|
|
1133
|
-
|
|
1147
|
+
validateResourceRename: () => validateResourceRename
|
|
1134
1148
|
});
|
|
1135
1149
|
module.exports = __toCommonJS(src_exports);
|
|
1136
1150
|
|
|
@@ -1229,6 +1243,11 @@ var import_imfs4 = require("imfs");
|
|
|
1229
1243
|
var import_react2 = __toESM(require("react"));
|
|
1230
1244
|
|
|
1231
1245
|
// src/utils/files.ts
|
|
1246
|
+
var import_imfs3 = require("imfs");
|
|
1247
|
+
var import_tree_visit3 = __toESM(require_lib());
|
|
1248
|
+
|
|
1249
|
+
// src/utils/resourceUtils.ts
|
|
1250
|
+
var import_noya_schemas = require("@noya-app/noya-schemas");
|
|
1232
1251
|
var import_imfs2 = require("imfs");
|
|
1233
1252
|
var import_tree_visit2 = __toESM(require_lib());
|
|
1234
1253
|
var getVisibleItems = ({
|
|
@@ -1240,7 +1259,7 @@ var getVisibleItems = ({
|
|
|
1240
1259
|
showRootItem
|
|
1241
1260
|
}) => {
|
|
1242
1261
|
const filteredItems = [];
|
|
1243
|
-
const relativeRootItem = tree.find(
|
|
1262
|
+
const relativeRootItem = tree.find(import_noya_schemas.rootResource, (item) => item.id === rootItemId) ?? import_noya_schemas.rootResource;
|
|
1244
1263
|
tree.visit(relativeRootItem, (item) => {
|
|
1245
1264
|
if (relativeRootItem.id === item.id) {
|
|
1246
1265
|
if (showRootItem) {
|
|
@@ -1248,16 +1267,16 @@ var getVisibleItems = ({
|
|
|
1248
1267
|
}
|
|
1249
1268
|
return;
|
|
1250
1269
|
}
|
|
1251
|
-
if (item.
|
|
1270
|
+
if (item.type === "file" && fileKindFilter === "all") {
|
|
1252
1271
|
filteredItems.push(item);
|
|
1253
1272
|
}
|
|
1254
|
-
if (item.
|
|
1273
|
+
if (item.type === "asset" && (fileKindFilter === "assets" || fileKindFilter === "all")) {
|
|
1255
1274
|
filteredItems.push(item);
|
|
1256
1275
|
}
|
|
1257
|
-
if (item.
|
|
1276
|
+
if (item.type === "directory" && (fileKindFilter === "directories" || fileKindFilter === "all")) {
|
|
1258
1277
|
filteredItems.push(item);
|
|
1259
1278
|
}
|
|
1260
|
-
if (item.
|
|
1279
|
+
if (item.type === "resource" && (fileKindFilter === "resources" || fileKindFilter === "all")) {
|
|
1261
1280
|
filteredItems.push(item);
|
|
1262
1281
|
}
|
|
1263
1282
|
if (!expandedMap[item.id] || !showAllDescendants) return "skip";
|
|
@@ -1269,7 +1288,7 @@ var basenameValidator = (basename) => {
|
|
|
1269
1288
|
const invalidCharsRegex = /[/\\<>:"|?*]/;
|
|
1270
1289
|
return !invalidCharsRegex.test(basename);
|
|
1271
1290
|
};
|
|
1272
|
-
var
|
|
1291
|
+
var validateResourceRename = ({
|
|
1273
1292
|
basename,
|
|
1274
1293
|
selectedItemPath,
|
|
1275
1294
|
media
|
|
@@ -1287,7 +1306,7 @@ var movePathsIntoTarget = ({
|
|
|
1287
1306
|
tree
|
|
1288
1307
|
}) => {
|
|
1289
1308
|
const ancestors = (0, import_tree_visit2.ancestorPaths)(
|
|
1290
|
-
sourceItemPaths.map((
|
|
1309
|
+
sourceItemPaths.map((path7) => path7.split("/"))
|
|
1291
1310
|
);
|
|
1292
1311
|
const mediaClone = { ...media };
|
|
1293
1312
|
for (const ancestor of ancestors) {
|
|
@@ -1305,7 +1324,7 @@ var movePathsIntoTarget = ({
|
|
|
1305
1324
|
ancestorPath,
|
|
1306
1325
|
newAncestorPath
|
|
1307
1326
|
);
|
|
1308
|
-
const newPathIsValid =
|
|
1327
|
+
const newPathIsValid = validateResourceRename({
|
|
1309
1328
|
basename: import_imfs2.path.basename(descendantPath),
|
|
1310
1329
|
selectedItemPath: newDescendantPath,
|
|
1311
1330
|
media
|
|
@@ -1324,17 +1343,17 @@ var moveUpAFolder = ({
|
|
|
1324
1343
|
selectedIds
|
|
1325
1344
|
}) => {
|
|
1326
1345
|
const indexPath = tree.findPath(
|
|
1327
|
-
|
|
1346
|
+
import_noya_schemas.rootResource,
|
|
1328
1347
|
(item) => item.id === selectedIds[0]
|
|
1329
1348
|
);
|
|
1330
1349
|
if (!indexPath) return;
|
|
1331
1350
|
const grandparentFolder = tree.access(
|
|
1332
|
-
|
|
1351
|
+
import_noya_schemas.rootResource,
|
|
1333
1352
|
indexPath.slice(0, indexPath.length - 2)
|
|
1334
1353
|
);
|
|
1335
1354
|
const grandparentFolderPath = tree.idToPathMap.get(grandparentFolder.id);
|
|
1336
1355
|
if (!grandparentFolderPath) return;
|
|
1337
|
-
const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((
|
|
1356
|
+
const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path7) => Boolean(path7));
|
|
1338
1357
|
return movePathsIntoTarget({
|
|
1339
1358
|
media,
|
|
1340
1359
|
targetItemPath: grandparentFolderPath,
|
|
@@ -1363,7 +1382,7 @@ var updateExpandedMap = ({
|
|
|
1363
1382
|
const newExpandedMap = { ...expandedMap };
|
|
1364
1383
|
const inner = (item2, expanded2) => {
|
|
1365
1384
|
if (!expandable) return {};
|
|
1366
|
-
if (item2.id ===
|
|
1385
|
+
if (item2.id === import_noya_schemas.rootResource.id) return {};
|
|
1367
1386
|
if (!expanded2) {
|
|
1368
1387
|
const children = tree.getChildren(item2, []);
|
|
1369
1388
|
children.forEach((child) => inner(child, false));
|
|
@@ -1373,13 +1392,13 @@ var updateExpandedMap = ({
|
|
|
1373
1392
|
inner(item, expanded);
|
|
1374
1393
|
return newExpandedMap;
|
|
1375
1394
|
};
|
|
1376
|
-
var
|
|
1395
|
+
var deleteResources = ({
|
|
1377
1396
|
selectedIds,
|
|
1378
1397
|
media,
|
|
1379
1398
|
tree
|
|
1380
1399
|
}) => {
|
|
1381
1400
|
const itemsToDelete = selectedIds.flatMap((mediaItemId) => {
|
|
1382
|
-
const mediaItem = tree.
|
|
1401
|
+
const mediaItem = tree.resourcesWithRoot.find(
|
|
1383
1402
|
(item) => item.id === mediaItemId
|
|
1384
1403
|
);
|
|
1385
1404
|
if (!mediaItem) return [];
|
|
@@ -1400,7 +1419,7 @@ var moveMediaInsideFolder = ({
|
|
|
1400
1419
|
}) => {
|
|
1401
1420
|
const targetItemPath = tree.idToPathMap.get(targetItemId);
|
|
1402
1421
|
if (!targetItemPath) return media;
|
|
1403
|
-
const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((
|
|
1422
|
+
const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path7) => Boolean(path7));
|
|
1404
1423
|
return movePathsIntoTarget({
|
|
1405
1424
|
media,
|
|
1406
1425
|
sourceItemPaths,
|
|
@@ -1408,16 +1427,13 @@ var moveMediaInsideFolder = ({
|
|
|
1408
1427
|
tree
|
|
1409
1428
|
});
|
|
1410
1429
|
};
|
|
1411
|
-
var getParentDirectories = (
|
|
1412
|
-
const tree =
|
|
1413
|
-
const indexPath = tree.findPath(
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
);
|
|
1417
|
-
if (!indexPath) return [rootMediaItem];
|
|
1418
|
-
return tree.accessPath(rootMediaItem, indexPath);
|
|
1430
|
+
var getParentDirectories = (resourceMap, folderId) => {
|
|
1431
|
+
const tree = (0, import_noya_schemas.createResourceTree)(resourceMap);
|
|
1432
|
+
const indexPath = tree.findPath(import_noya_schemas.rootResource, (item) => item.id === folderId);
|
|
1433
|
+
if (!indexPath) return [import_noya_schemas.rootResource];
|
|
1434
|
+
return tree.accessPath(import_noya_schemas.rootResource, indexPath);
|
|
1419
1435
|
};
|
|
1420
|
-
var
|
|
1436
|
+
var renameResourceAndDescendantPaths = ({
|
|
1421
1437
|
newName,
|
|
1422
1438
|
selectedItemPath,
|
|
1423
1439
|
media,
|
|
@@ -1435,175 +1451,280 @@ var renameMediaItemAndDescendantPaths = ({
|
|
|
1435
1451
|
selectedItemPath,
|
|
1436
1452
|
newItemPath
|
|
1437
1453
|
);
|
|
1438
|
-
mediaClone[newDescendantPath] =
|
|
1454
|
+
mediaClone[newDescendantPath] = {
|
|
1455
|
+
...mediaClone[descendantPath],
|
|
1456
|
+
path: newDescendantPath
|
|
1457
|
+
};
|
|
1439
1458
|
delete mediaClone[descendantPath];
|
|
1440
1459
|
}
|
|
1441
1460
|
return mediaClone;
|
|
1442
1461
|
};
|
|
1443
1462
|
|
|
1444
|
-
// src/utils/
|
|
1445
|
-
var
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1463
|
+
// src/utils/files.ts
|
|
1464
|
+
var mediaGetVisibleItems = ({
|
|
1465
|
+
expandedMap,
|
|
1466
|
+
fileKindFilter,
|
|
1467
|
+
rootItemId,
|
|
1468
|
+
tree,
|
|
1469
|
+
showAllDescendants,
|
|
1470
|
+
showRootItem
|
|
1471
|
+
}) => {
|
|
1472
|
+
const filteredItems = [];
|
|
1473
|
+
const relativeRootItem = tree.find(rootMediaItem, (item) => item.id === rootItemId) ?? rootMediaItem;
|
|
1474
|
+
tree.visit(relativeRootItem, (item) => {
|
|
1475
|
+
if (relativeRootItem.id === item.id) {
|
|
1476
|
+
if (showRootItem) {
|
|
1477
|
+
filteredItems.push(item);
|
|
1478
|
+
}
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
if (item.kind === "noyaFile" && fileKindFilter === "all") {
|
|
1482
|
+
filteredItems.push(item);
|
|
1483
|
+
}
|
|
1484
|
+
if (item.kind === "file" && fileKindFilter === "all") {
|
|
1485
|
+
filteredItems.push(item);
|
|
1486
|
+
}
|
|
1487
|
+
if (item.kind === "asset" && (fileKindFilter === "assets" || fileKindFilter === "all")) {
|
|
1488
|
+
filteredItems.push(item);
|
|
1489
|
+
}
|
|
1490
|
+
if (item.kind === "folder" && (fileKindFilter === "directories" || fileKindFilter === "all")) {
|
|
1491
|
+
filteredItems.push(item);
|
|
1492
|
+
}
|
|
1493
|
+
if (!expandedMap[item.id] || !showAllDescendants) return "skip";
|
|
1494
|
+
});
|
|
1495
|
+
return filteredItems;
|
|
1496
|
+
};
|
|
1497
|
+
var mediaValidateMediaItemRename = ({
|
|
1498
|
+
basename,
|
|
1499
|
+
selectedItemPath,
|
|
1500
|
+
media
|
|
1501
|
+
}) => {
|
|
1502
|
+
if (!basenameValidator(basename)) return false;
|
|
1503
|
+
const newItemPath = import_imfs3.path.join(import_imfs3.path.dirname(selectedItemPath), basename);
|
|
1504
|
+
const newPathExists = media[newItemPath];
|
|
1505
|
+
if (newPathExists) return false;
|
|
1506
|
+
return true;
|
|
1507
|
+
};
|
|
1508
|
+
var mediaMovePathsIntoTarget = ({
|
|
1455
1509
|
media,
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1510
|
+
sourceItemPaths,
|
|
1511
|
+
targetItemPath,
|
|
1512
|
+
tree
|
|
1513
|
+
}) => {
|
|
1514
|
+
const ancestors = (0, import_tree_visit3.ancestorPaths)(
|
|
1515
|
+
sourceItemPaths.map((path7) => path7.split("/"))
|
|
1516
|
+
);
|
|
1517
|
+
const mediaClone = { ...media };
|
|
1518
|
+
for (const ancestor of ancestors) {
|
|
1519
|
+
const ancestorPath = ancestor.join("/");
|
|
1520
|
+
const ancestorItem = mediaClone[ancestorPath];
|
|
1521
|
+
const newAncestorPath = import_imfs3.path.join(
|
|
1522
|
+
targetItemPath,
|
|
1523
|
+
import_imfs3.path.basename(ancestorPath)
|
|
1462
1524
|
);
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
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, ""))
|
|
1525
|
+
if (!ancestorItem) continue;
|
|
1526
|
+
const descendantPaths = tree.flat(ancestorItem).map((item) => tree.idToPathMap.get(item.id));
|
|
1527
|
+
for (const descendantPath of descendantPaths) {
|
|
1528
|
+
if (!descendantPath) continue;
|
|
1529
|
+
const newDescendantPath = descendantPath.replace(
|
|
1530
|
+
ancestorPath,
|
|
1531
|
+
newAncestorPath
|
|
1508
1532
|
);
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
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
|
-
}
|
|
1533
|
+
const newPathIsValid = mediaValidateMediaItemRename({
|
|
1534
|
+
basename: import_imfs3.path.basename(descendantPath),
|
|
1535
|
+
selectedItemPath: newDescendantPath,
|
|
1536
|
+
media
|
|
1537
|
+
});
|
|
1538
|
+
if (newPathIsValid) {
|
|
1539
|
+
mediaClone[newDescendantPath] = mediaClone[descendantPath];
|
|
1540
|
+
delete mediaClone[descendantPath];
|
|
1530
1541
|
}
|
|
1531
1542
|
}
|
|
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
1543
|
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
// src/MediaCollection.tsx
|
|
1554
|
-
var extensionToContentType = {
|
|
1555
|
-
svg: "image/svg+xml",
|
|
1556
|
-
png: "image/png",
|
|
1557
|
-
jpeg: "image/jpeg"
|
|
1544
|
+
return mediaClone;
|
|
1558
1545
|
};
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1546
|
+
var mediaMoveUpAFolder = ({
|
|
1547
|
+
tree,
|
|
1548
|
+
media,
|
|
1549
|
+
selectedIds
|
|
1550
|
+
}) => {
|
|
1551
|
+
const indexPath = tree.findPath(
|
|
1552
|
+
rootMediaItem,
|
|
1553
|
+
(item) => item.id === selectedIds[0]
|
|
1554
|
+
);
|
|
1555
|
+
if (!indexPath) return;
|
|
1556
|
+
const grandparentFolder = tree.access(
|
|
1557
|
+
rootMediaItem,
|
|
1558
|
+
indexPath.slice(0, indexPath.length - 2)
|
|
1559
|
+
);
|
|
1560
|
+
const grandparentFolderPath = tree.idToPathMap.get(grandparentFolder.id);
|
|
1561
|
+
if (!grandparentFolderPath) return;
|
|
1562
|
+
const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path7) => Boolean(path7));
|
|
1563
|
+
return mediaMovePathsIntoTarget({
|
|
1564
|
+
media,
|
|
1565
|
+
targetItemPath: grandparentFolderPath,
|
|
1566
|
+
sourceItemPaths,
|
|
1567
|
+
tree
|
|
1568
|
+
});
|
|
1569
|
+
};
|
|
1570
|
+
var mediaGetDepthMap = (item, tree, showAllDescendants) => {
|
|
1571
|
+
const depthMap = {};
|
|
1572
|
+
tree.visit(item, (item2, indexPath) => {
|
|
1573
|
+
if (showAllDescendants) {
|
|
1574
|
+
depthMap[item2.id] = Math.max(indexPath.length - 1, 0);
|
|
1568
1575
|
} else {
|
|
1569
|
-
|
|
1570
|
-
return {
|
|
1571
|
-
contentType,
|
|
1572
|
-
url: `data:${contentType},${encodeURIComponent(item.content)}`
|
|
1573
|
-
};
|
|
1574
|
-
} catch (error) {
|
|
1575
|
-
console.warn("Failed to encode content:", error);
|
|
1576
|
-
return { contentType };
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
return void 0;
|
|
1581
|
-
}
|
|
1582
|
-
var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
|
|
1583
|
-
({
|
|
1584
|
-
item,
|
|
1585
|
-
selected,
|
|
1586
|
-
size,
|
|
1587
|
-
path: pathProp,
|
|
1588
|
-
renderThumbnailIcon
|
|
1589
|
-
}) => {
|
|
1590
|
-
const asset = (0, import_noya_multiplayer_react.useAsset)(item.kind === "asset" ? item.assetId : void 0);
|
|
1591
|
-
const isRoot = item.id === rootMediaItem.id;
|
|
1592
|
-
const isFolder = item.kind === "folder";
|
|
1593
|
-
const isFile = item.kind === "file";
|
|
1594
|
-
let contentType;
|
|
1595
|
-
let url;
|
|
1596
|
-
if (asset) {
|
|
1597
|
-
contentType = asset.contentType;
|
|
1598
|
-
url = asset.url;
|
|
1599
|
-
} else if (isFile && pathProp) {
|
|
1600
|
-
const encoded = encodeFileContentForThumbnail(pathProp, item);
|
|
1601
|
-
if (encoded) {
|
|
1602
|
-
contentType = encoded.contentType;
|
|
1603
|
-
url = encoded.url;
|
|
1604
|
-
}
|
|
1576
|
+
depthMap[item2.id] = 0;
|
|
1605
1577
|
}
|
|
1606
|
-
|
|
1578
|
+
});
|
|
1579
|
+
return depthMap;
|
|
1580
|
+
};
|
|
1581
|
+
var mediaUpdateExpandedMap = ({
|
|
1582
|
+
item,
|
|
1583
|
+
expanded,
|
|
1584
|
+
expandable,
|
|
1585
|
+
expandedMap,
|
|
1586
|
+
tree
|
|
1587
|
+
}) => {
|
|
1588
|
+
const newExpandedMap = { ...expandedMap };
|
|
1589
|
+
const inner = (item2, expanded2) => {
|
|
1590
|
+
if (!expandable) return {};
|
|
1591
|
+
if (item2.id === rootMediaItem.id) return {};
|
|
1592
|
+
if (!expanded2) {
|
|
1593
|
+
const children = tree.getChildren(item2, []);
|
|
1594
|
+
children.forEach((child) => inner(child, false));
|
|
1595
|
+
}
|
|
1596
|
+
newExpandedMap[item2.id] = expanded2;
|
|
1597
|
+
};
|
|
1598
|
+
inner(item, expanded);
|
|
1599
|
+
return newExpandedMap;
|
|
1600
|
+
};
|
|
1601
|
+
var mediaDeleteMediaItems = ({
|
|
1602
|
+
selectedIds,
|
|
1603
|
+
media,
|
|
1604
|
+
tree
|
|
1605
|
+
}) => {
|
|
1606
|
+
const itemsToDelete = selectedIds.flatMap((mediaItemId) => {
|
|
1607
|
+
const mediaItem = tree.mediaItemsWithRoot.find(
|
|
1608
|
+
(item) => item.id === mediaItemId
|
|
1609
|
+
);
|
|
1610
|
+
if (!mediaItem) return [];
|
|
1611
|
+
return tree.flat(mediaItem);
|
|
1612
|
+
});
|
|
1613
|
+
const itemKeysToDelete = new Set(
|
|
1614
|
+
itemsToDelete.map((item) => tree.idToPathMap.get(item.id))
|
|
1615
|
+
);
|
|
1616
|
+
return Object.fromEntries(
|
|
1617
|
+
Object.entries(media).filter(([key]) => !itemKeysToDelete.has(key))
|
|
1618
|
+
);
|
|
1619
|
+
};
|
|
1620
|
+
var mediaMoveMediaInsideFolder = ({
|
|
1621
|
+
sourceItemIds,
|
|
1622
|
+
targetItemId,
|
|
1623
|
+
media,
|
|
1624
|
+
tree
|
|
1625
|
+
}) => {
|
|
1626
|
+
const targetItemPath = tree.idToPathMap.get(targetItemId);
|
|
1627
|
+
if (!targetItemPath) return media;
|
|
1628
|
+
const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path7) => Boolean(path7));
|
|
1629
|
+
return mediaMovePathsIntoTarget({
|
|
1630
|
+
media,
|
|
1631
|
+
sourceItemPaths,
|
|
1632
|
+
targetItemPath,
|
|
1633
|
+
tree
|
|
1634
|
+
});
|
|
1635
|
+
};
|
|
1636
|
+
var mediaGetParentDirectories = (mediaMap, folderId) => {
|
|
1637
|
+
const tree = createMediaItemTree(mediaMap);
|
|
1638
|
+
const indexPath = tree.findPath(
|
|
1639
|
+
rootMediaItem,
|
|
1640
|
+
(item) => item.id === folderId
|
|
1641
|
+
);
|
|
1642
|
+
if (!indexPath) return [rootMediaItem];
|
|
1643
|
+
return tree.accessPath(rootMediaItem, indexPath);
|
|
1644
|
+
};
|
|
1645
|
+
var mediaRenameMediaItemAndDescendantPaths = ({
|
|
1646
|
+
newName,
|
|
1647
|
+
selectedItemPath,
|
|
1648
|
+
media,
|
|
1649
|
+
tree
|
|
1650
|
+
}) => {
|
|
1651
|
+
const mediaClone = { ...media };
|
|
1652
|
+
const selectedItem = mediaClone[selectedItemPath];
|
|
1653
|
+
if (!selectedItem) return mediaClone;
|
|
1654
|
+
const parentPath = import_imfs3.path.dirname(selectedItemPath);
|
|
1655
|
+
const newItemPath = import_imfs3.path.join(parentPath, newName);
|
|
1656
|
+
const descendants = tree.flat(selectedItem).map((item) => tree.idToPathMap.get(item.id));
|
|
1657
|
+
for (const descendantPath of descendants) {
|
|
1658
|
+
if (!descendantPath) continue;
|
|
1659
|
+
const newDescendantPath = descendantPath.replace(
|
|
1660
|
+
selectedItemPath,
|
|
1661
|
+
newItemPath
|
|
1662
|
+
);
|
|
1663
|
+
mediaClone[newDescendantPath] = mediaClone[descendantPath];
|
|
1664
|
+
delete mediaClone[descendantPath];
|
|
1665
|
+
}
|
|
1666
|
+
return mediaClone;
|
|
1667
|
+
};
|
|
1668
|
+
|
|
1669
|
+
// src/MediaCollection.tsx
|
|
1670
|
+
var extensionToContentType = {
|
|
1671
|
+
svg: "image/svg+xml",
|
|
1672
|
+
png: "image/png",
|
|
1673
|
+
jpeg: "image/jpeg"
|
|
1674
|
+
};
|
|
1675
|
+
function encodeFileContentForThumbnail(pathProp, item) {
|
|
1676
|
+
const extension = import_imfs4.path.extname(pathProp).slice(1);
|
|
1677
|
+
const contentType = extensionToContentType[extension];
|
|
1678
|
+
if (contentType) {
|
|
1679
|
+
if (item.encoding === "base64") {
|
|
1680
|
+
return {
|
|
1681
|
+
contentType,
|
|
1682
|
+
url: `data:${contentType};base64,${item.content}`
|
|
1683
|
+
};
|
|
1684
|
+
} else {
|
|
1685
|
+
try {
|
|
1686
|
+
return {
|
|
1687
|
+
contentType,
|
|
1688
|
+
url: `data:${contentType},${encodeURIComponent(item.content)}`
|
|
1689
|
+
};
|
|
1690
|
+
} catch (error) {
|
|
1691
|
+
console.warn("Failed to encode content:", error);
|
|
1692
|
+
return { contentType };
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
return void 0;
|
|
1697
|
+
}
|
|
1698
|
+
var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
|
|
1699
|
+
({
|
|
1700
|
+
item,
|
|
1701
|
+
selected,
|
|
1702
|
+
size,
|
|
1703
|
+
path: pathProp,
|
|
1704
|
+
renderThumbnailIcon
|
|
1705
|
+
}) => {
|
|
1706
|
+
const asset = (0, import_noya_multiplayer_react.useAsset)(item.kind === "asset" ? item.assetId : void 0);
|
|
1707
|
+
const isRoot = item.id === rootMediaItem.id;
|
|
1708
|
+
const isFolder = item.kind === "folder";
|
|
1709
|
+
const isFile = item.kind === "file";
|
|
1710
|
+
let contentType;
|
|
1711
|
+
let url;
|
|
1712
|
+
let width;
|
|
1713
|
+
let height;
|
|
1714
|
+
if (asset) {
|
|
1715
|
+
contentType = asset.contentType;
|
|
1716
|
+
url = asset.url;
|
|
1717
|
+
width = asset.width ?? void 0;
|
|
1718
|
+
height = asset.height ?? void 0;
|
|
1719
|
+
} else if (isFile && pathProp) {
|
|
1720
|
+
const encoded = encodeFileContentForThumbnail(pathProp, item);
|
|
1721
|
+
if (encoded) {
|
|
1722
|
+
contentType = encoded.contentType;
|
|
1723
|
+
url = encoded.url;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
const fileName = pathProp ? import_imfs4.path.basename(pathProp) : void 0;
|
|
1727
|
+
const dimensions = width && height ? { width, height } : void 0;
|
|
1607
1728
|
return /* @__PURE__ */ import_react2.default.createElement(
|
|
1608
1729
|
import_noya_designsystem.MediaThumbnail,
|
|
1609
1730
|
{
|
|
@@ -1613,7 +1734,8 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
|
|
|
1613
1734
|
selected,
|
|
1614
1735
|
size,
|
|
1615
1736
|
fileName,
|
|
1616
|
-
renderThumbnailIcon
|
|
1737
|
+
renderThumbnailIcon,
|
|
1738
|
+
dimensions
|
|
1617
1739
|
}
|
|
1618
1740
|
);
|
|
1619
1741
|
}
|
|
@@ -1647,7 +1769,8 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1647
1769
|
sharedDragProps,
|
|
1648
1770
|
onClickItem,
|
|
1649
1771
|
renderThumbnailIcon,
|
|
1650
|
-
onDidDeleteItems
|
|
1772
|
+
onDidDeleteItems,
|
|
1773
|
+
onAssetsUploaded
|
|
1651
1774
|
}, ref) {
|
|
1652
1775
|
const setMedia = (0, import_react.useCallback)(
|
|
1653
1776
|
(...args) => {
|
|
@@ -1688,7 +1811,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1688
1811
|
const assets = (0, import_noya_multiplayer_react.useAssets)();
|
|
1689
1812
|
const [expandedMap, setExpandedMap] = (0, import_react.useState)({});
|
|
1690
1813
|
const visibleItems = (0, import_react.useMemo)(
|
|
1691
|
-
() =>
|
|
1814
|
+
() => mediaGetVisibleItems({
|
|
1692
1815
|
expandedMap,
|
|
1693
1816
|
fileKindFilter,
|
|
1694
1817
|
rootItemId,
|
|
@@ -1706,7 +1829,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1706
1829
|
]
|
|
1707
1830
|
);
|
|
1708
1831
|
const depthMap = (0, import_react.useMemo)(
|
|
1709
|
-
() =>
|
|
1832
|
+
() => mediaGetDepthMap(rootMediaItem, treeWithTempItem, showAllDescendants),
|
|
1710
1833
|
[treeWithTempItem, showAllDescendants]
|
|
1711
1834
|
);
|
|
1712
1835
|
const collectionRef = (0, import_react.useRef)(null);
|
|
@@ -1745,17 +1868,23 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1745
1868
|
},
|
|
1746
1869
|
[expandedMap, expandable]
|
|
1747
1870
|
);
|
|
1871
|
+
const openConfirmationDialog = (0, import_noya_designsystem.useOpenConfirmationDialog)();
|
|
1748
1872
|
const handleDelete = (0, import_react.useCallback)(
|
|
1749
|
-
(selectedIds2) => {
|
|
1873
|
+
async (selectedIds2) => {
|
|
1874
|
+
const ok = await openConfirmationDialog({
|
|
1875
|
+
title: "Delete items",
|
|
1876
|
+
description: "Are you sure you want to delete these items? This action cannot be undone."
|
|
1877
|
+
});
|
|
1878
|
+
if (!ok) return;
|
|
1750
1879
|
const deletedItems = Object.entries(media).flatMap(
|
|
1751
|
-
([
|
|
1880
|
+
([path7, item]) => {
|
|
1752
1881
|
if (selectedIds2.includes(item.id)) {
|
|
1753
|
-
return [[
|
|
1882
|
+
return [[path7, item]];
|
|
1754
1883
|
}
|
|
1755
1884
|
return [];
|
|
1756
1885
|
}
|
|
1757
1886
|
);
|
|
1758
|
-
const newMedia =
|
|
1887
|
+
const newMedia = mediaDeleteMediaItems({
|
|
1759
1888
|
selectedIds: selectedIds2,
|
|
1760
1889
|
media,
|
|
1761
1890
|
tree
|
|
@@ -1764,7 +1893,14 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1764
1893
|
setMedia({ name: "Delete items", timestamp: Date.now() }, newMedia);
|
|
1765
1894
|
onDidDeleteItems?.(deletedItems);
|
|
1766
1895
|
},
|
|
1767
|
-
[
|
|
1896
|
+
[
|
|
1897
|
+
media,
|
|
1898
|
+
setMedia,
|
|
1899
|
+
setSelectedIds,
|
|
1900
|
+
tree,
|
|
1901
|
+
onDidDeleteItems,
|
|
1902
|
+
openConfirmationDialog
|
|
1903
|
+
]
|
|
1768
1904
|
);
|
|
1769
1905
|
const onRename = (0, import_react.useCallback)(
|
|
1770
1906
|
(selectedItem, newName) => {
|
|
@@ -1773,7 +1909,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1773
1909
|
selectedItem.id
|
|
1774
1910
|
);
|
|
1775
1911
|
if (!selectedItemPath) return;
|
|
1776
|
-
const renameIsValid =
|
|
1912
|
+
const renameIsValid = mediaValidateMediaItemRename({
|
|
1777
1913
|
basename: newName,
|
|
1778
1914
|
selectedItemPath,
|
|
1779
1915
|
media: temp.media
|
|
@@ -1782,7 +1918,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1782
1918
|
setTempItem(void 0);
|
|
1783
1919
|
return;
|
|
1784
1920
|
}
|
|
1785
|
-
const mediaWithRenamedDescendantPaths =
|
|
1921
|
+
const mediaWithRenamedDescendantPaths = mediaRenameMediaItemAndDescendantPaths({
|
|
1786
1922
|
newName,
|
|
1787
1923
|
selectedItemPath,
|
|
1788
1924
|
media: temp.media,
|
|
@@ -1833,7 +1969,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1833
1969
|
);
|
|
1834
1970
|
const handleMoveUpAFolder = (0, import_react.useCallback)(
|
|
1835
1971
|
(selectedIds2) => {
|
|
1836
|
-
const newMedia =
|
|
1972
|
+
const newMedia = mediaMoveUpAFolder({
|
|
1837
1973
|
tree,
|
|
1838
1974
|
media,
|
|
1839
1975
|
selectedIds: selectedIds2
|
|
@@ -1860,23 +1996,28 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1860
1996
|
};
|
|
1861
1997
|
});
|
|
1862
1998
|
setIsUploading(true);
|
|
1863
|
-
const
|
|
1999
|
+
const uploadedAssets = await Promise.all(uploadPromises);
|
|
2000
|
+
const newMediaMap = Object.fromEntries(
|
|
2001
|
+
uploadedAssets.map(({ assetPath, asset }) => [assetPath, asset])
|
|
2002
|
+
);
|
|
1864
2003
|
setMedia(
|
|
1865
2004
|
{ name: "Add media items", timestamp: Date.now() },
|
|
1866
2005
|
{
|
|
1867
2006
|
...media,
|
|
1868
|
-
...
|
|
1869
|
-
newMediaMap.map(({ assetPath, asset }) => [assetPath, asset])
|
|
1870
|
-
)
|
|
2007
|
+
...newMediaMap
|
|
1871
2008
|
}
|
|
1872
2009
|
);
|
|
2010
|
+
onAssetsUploaded?.(newMediaMap);
|
|
1873
2011
|
} catch (error) {
|
|
1874
|
-
|
|
2012
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2013
|
+
} else {
|
|
2014
|
+
console.error("Failed to upload files:", error);
|
|
2015
|
+
}
|
|
1875
2016
|
} finally {
|
|
1876
2017
|
setIsUploading(false);
|
|
1877
2018
|
}
|
|
1878
2019
|
},
|
|
1879
|
-
[tree.idToPathMap, setMedia, media, assetManager]
|
|
2020
|
+
[tree.idToPathMap, setMedia, media, assetManager, onAssetsUploaded]
|
|
1880
2021
|
);
|
|
1881
2022
|
const handleDownload = (0, import_react.useCallback)(
|
|
1882
2023
|
async (selectedItems) => {
|
|
@@ -1920,7 +2061,10 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1920
2061
|
}
|
|
1921
2062
|
);
|
|
1922
2063
|
} catch (error) {
|
|
1923
|
-
|
|
2064
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2065
|
+
} else {
|
|
2066
|
+
console.error("Failed to upload files:", error);
|
|
2067
|
+
}
|
|
1924
2068
|
}
|
|
1925
2069
|
},
|
|
1926
2070
|
[media, setMedia, assetManager, tree]
|
|
@@ -1933,7 +2077,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1933
2077
|
);
|
|
1934
2078
|
const handleMoveMediaInsideFolder = (0, import_react.useCallback)(
|
|
1935
2079
|
(sourceItem, targetItem) => {
|
|
1936
|
-
const newMedia =
|
|
2080
|
+
const newMedia = mediaMoveMediaInsideFolder({
|
|
1937
2081
|
sourceItemIds: [sourceItem.id],
|
|
1938
2082
|
targetItemId: targetItem.id,
|
|
1939
2083
|
media,
|
|
@@ -2052,7 +2196,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
2052
2196
|
const handleSetExpanded = (0, import_react.useCallback)(
|
|
2053
2197
|
(item, expanded) => {
|
|
2054
2198
|
setExpandedMap(
|
|
2055
|
-
(prev) =>
|
|
2199
|
+
(prev) => mediaUpdateExpandedMap({
|
|
2056
2200
|
item,
|
|
2057
2201
|
expanded,
|
|
2058
2202
|
expandable,
|
|
@@ -2222,22 +2366,6 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
2222
2366
|
if (position === "inside") {
|
|
2223
2367
|
handleMoveMediaInsideFolder(sourceItem, targetItem);
|
|
2224
2368
|
}
|
|
2225
|
-
},
|
|
2226
|
-
onFilesDrop: async (event) => {
|
|
2227
|
-
event.preventDefault();
|
|
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
|
-
);
|
|
2241
2369
|
}
|
|
2242
2370
|
}
|
|
2243
2371
|
)
|
|
@@ -2263,29 +2391,982 @@ function acceptsMediaItemDrop(parameters) {
|
|
|
2263
2391
|
}
|
|
2264
2392
|
return true;
|
|
2265
2393
|
}
|
|
2394
|
+
|
|
2395
|
+
// src/ResourceExplorer.tsx
|
|
2396
|
+
var import_noya_designsystem2 = require("@noya-app/noya-designsystem");
|
|
2397
|
+
var import_noya_icons2 = require("@noya-app/noya-icons");
|
|
2398
|
+
var import_noya_multiplayer_react2 = require("@noya-app/noya-multiplayer-react");
|
|
2399
|
+
var import_noya_schemas3 = require("@noya-app/noya-schemas");
|
|
2400
|
+
var import_noya_utils4 = require("@noya-app/noya-utils");
|
|
2401
|
+
var import_react_utils2 = require("@noya-app/react-utils");
|
|
2402
|
+
var import_browser_fs_access2 = require("browser-fs-access");
|
|
2403
|
+
var import_react3 = require("react");
|
|
2404
|
+
var import_imfs6 = require("imfs");
|
|
2405
|
+
var import_react4 = __toESM(require("react"));
|
|
2406
|
+
|
|
2407
|
+
// src/utils/handleFileDrop.ts
|
|
2408
|
+
var import_noya_schemas2 = require("@noya-app/noya-schemas");
|
|
2409
|
+
var import_noya_utils3 = require("@noya-app/noya-utils");
|
|
2410
|
+
var import_imfs5 = require("imfs");
|
|
2411
|
+
function isDirectoryEntry(entry) {
|
|
2412
|
+
return entry.isDirectory;
|
|
2413
|
+
}
|
|
2414
|
+
function isFileEntry(entry) {
|
|
2415
|
+
return entry.isFile;
|
|
2416
|
+
}
|
|
2417
|
+
async function handleDataTransfer({
|
|
2418
|
+
accessibleByFileId,
|
|
2419
|
+
dataTransfer,
|
|
2420
|
+
rootItemPath,
|
|
2421
|
+
resourceMap
|
|
2422
|
+
}) {
|
|
2423
|
+
try {
|
|
2424
|
+
const dataTransferItems = Array.from(dataTransfer.items ?? []);
|
|
2425
|
+
const supportsEntries = dataTransferItems.some(
|
|
2426
|
+
(item) => typeof item?.webkitGetAsEntry === "function"
|
|
2427
|
+
);
|
|
2428
|
+
const collectFromEntry = async (entry, basePath) => {
|
|
2429
|
+
if (!entry) return [];
|
|
2430
|
+
if (isFileEntry(entry)) {
|
|
2431
|
+
const file = await new Promise(
|
|
2432
|
+
(resolve) => entry.file((f) => resolve(f))
|
|
2433
|
+
);
|
|
2434
|
+
return [
|
|
2435
|
+
{
|
|
2436
|
+
file,
|
|
2437
|
+
relativePath: import_imfs5.path.join(basePath, file.name)
|
|
2438
|
+
}
|
|
2439
|
+
];
|
|
2440
|
+
}
|
|
2441
|
+
if (isDirectoryEntry(entry)) {
|
|
2442
|
+
const reader = entry.createReader();
|
|
2443
|
+
const readAll = async () => {
|
|
2444
|
+
const all = [];
|
|
2445
|
+
while (true) {
|
|
2446
|
+
const entries = await new Promise(
|
|
2447
|
+
(resolve) => reader.readEntries((ents) => resolve(ents))
|
|
2448
|
+
);
|
|
2449
|
+
if (!entries.length) break;
|
|
2450
|
+
all.push(...entries);
|
|
2451
|
+
}
|
|
2452
|
+
return all;
|
|
2453
|
+
};
|
|
2454
|
+
const children = await readAll();
|
|
2455
|
+
const results = await Promise.all(
|
|
2456
|
+
children.map(
|
|
2457
|
+
(child) => collectFromEntry(child, import_imfs5.path.join(basePath, entry.name))
|
|
2458
|
+
)
|
|
2459
|
+
);
|
|
2460
|
+
return results.flat();
|
|
2461
|
+
}
|
|
2462
|
+
return [];
|
|
2463
|
+
};
|
|
2464
|
+
let dropped = [];
|
|
2465
|
+
if (supportsEntries) {
|
|
2466
|
+
const topLevelEntries = dataTransferItems.flatMap((item) => {
|
|
2467
|
+
const entry = item.webkitGetAsEntry?.();
|
|
2468
|
+
if (!entry) return [];
|
|
2469
|
+
return [entry];
|
|
2470
|
+
});
|
|
2471
|
+
const nested = await Promise.all(
|
|
2472
|
+
topLevelEntries.map((entry) => collectFromEntry(entry, ""))
|
|
2473
|
+
);
|
|
2474
|
+
dropped = nested.flat();
|
|
2475
|
+
} else {
|
|
2476
|
+
const files = Array.from(dataTransfer.files);
|
|
2477
|
+
if (files.length === 0) return;
|
|
2478
|
+
dropped = files.map((file) => ({
|
|
2479
|
+
file,
|
|
2480
|
+
// Best effort: try webkitRelativePath; fall back to name
|
|
2481
|
+
relativePath: file.webkitRelativePath && file.webkitRelativePath.length > 0 ? file.webkitRelativePath : file.name
|
|
2482
|
+
}));
|
|
2483
|
+
}
|
|
2484
|
+
if (dropped.length === 0) return;
|
|
2485
|
+
const folderRelativePaths = /* @__PURE__ */ new Set();
|
|
2486
|
+
for (const { relativePath } of dropped) {
|
|
2487
|
+
const dir = import_imfs5.path.dirname(relativePath);
|
|
2488
|
+
if (dir && dir !== ".") {
|
|
2489
|
+
const parts = dir.split("/").filter(Boolean);
|
|
2490
|
+
let acc = "";
|
|
2491
|
+
for (const part of parts) {
|
|
2492
|
+
acc = acc ? import_imfs5.path.join(acc, part) : part;
|
|
2493
|
+
folderRelativePaths.add(acc);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
const folderEntries = Array.from(folderRelativePaths).map((rel) => import_imfs5.path.join(rootItemPath, rel)).filter((full) => !resourceMap[full]).map((full) => [
|
|
2498
|
+
full,
|
|
2499
|
+
(0, import_noya_schemas2.createDirectoryResource)({
|
|
2500
|
+
id: (0, import_noya_utils3.uuid)(),
|
|
2501
|
+
path: full,
|
|
2502
|
+
accessibleByFileId,
|
|
2503
|
+
stableId: (0, import_noya_utils3.uuid)()
|
|
2504
|
+
})
|
|
2505
|
+
]);
|
|
2506
|
+
const uploadResults = await Promise.all(
|
|
2507
|
+
dropped.map(
|
|
2508
|
+
async ({ file, relativePath }) => {
|
|
2509
|
+
return [
|
|
2510
|
+
import_imfs5.path.join(rootItemPath, relativePath),
|
|
2511
|
+
(0, import_noya_schemas2.createAssetResource)({
|
|
2512
|
+
id: (0, import_noya_utils3.uuid)(),
|
|
2513
|
+
asset: {
|
|
2514
|
+
content: import_noya_utils3.Base64.encode(await file.arrayBuffer()),
|
|
2515
|
+
contentType: file.type,
|
|
2516
|
+
encoding: "base64"
|
|
2517
|
+
},
|
|
2518
|
+
path: import_imfs5.path.join(rootItemPath, relativePath),
|
|
2519
|
+
accessibleByFileId,
|
|
2520
|
+
stableId: (0, import_noya_utils3.uuid)()
|
|
2521
|
+
})
|
|
2522
|
+
];
|
|
2523
|
+
}
|
|
2524
|
+
)
|
|
2525
|
+
);
|
|
2526
|
+
return {
|
|
2527
|
+
...resourceMap,
|
|
2528
|
+
...Object.fromEntries([...folderEntries, ...uploadResults])
|
|
2529
|
+
};
|
|
2530
|
+
} catch (error) {
|
|
2531
|
+
console.error("Failed to upload dropped files:", error);
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
// src/ResourceExplorer.tsx
|
|
2536
|
+
var gridThumbnailDimension = {
|
|
2537
|
+
width: 800,
|
|
2538
|
+
height: 800
|
|
2539
|
+
};
|
|
2540
|
+
var ResourceThumbnail = (0, import_react_utils2.memoGeneric)(
|
|
2541
|
+
({
|
|
2542
|
+
item,
|
|
2543
|
+
selected,
|
|
2544
|
+
size,
|
|
2545
|
+
path: pathProp,
|
|
2546
|
+
renderThumbnailIcon,
|
|
2547
|
+
className,
|
|
2548
|
+
url: urlProp,
|
|
2549
|
+
contentType: contentTypeProp,
|
|
2550
|
+
viewType
|
|
2551
|
+
}) => {
|
|
2552
|
+
const asset = (0, import_noya_multiplayer_react2.useAsset)(item.type === "asset" ? item.assetId : void 0);
|
|
2553
|
+
const isRoot = item.id === import_noya_schemas3.rootResource.id;
|
|
2554
|
+
const isFolder = item.type === "directory";
|
|
2555
|
+
let contentType;
|
|
2556
|
+
let url;
|
|
2557
|
+
if (asset) {
|
|
2558
|
+
contentType = asset.contentType;
|
|
2559
|
+
url = asset.url;
|
|
2560
|
+
} else if (urlProp) {
|
|
2561
|
+
url = urlProp;
|
|
2562
|
+
contentType = contentTypeProp;
|
|
2563
|
+
}
|
|
2564
|
+
const fileName = pathProp ? import_imfs6.path.basename(pathProp) : void 0;
|
|
2565
|
+
return /* @__PURE__ */ import_react4.default.createElement(
|
|
2566
|
+
import_noya_designsystem2.MediaThumbnail,
|
|
2567
|
+
{
|
|
2568
|
+
contentType,
|
|
2569
|
+
iconName: isRoot ? "HomeIcon" : isFolder ? "FolderIcon" : void 0,
|
|
2570
|
+
url,
|
|
2571
|
+
selected,
|
|
2572
|
+
size,
|
|
2573
|
+
fileName,
|
|
2574
|
+
renderThumbnailIcon,
|
|
2575
|
+
dimensions: viewType === "grid" ? gridThumbnailDimension : void 0,
|
|
2576
|
+
className
|
|
2577
|
+
}
|
|
2578
|
+
);
|
|
2579
|
+
}
|
|
2580
|
+
);
|
|
2581
|
+
var ResourceExplorer = (0, import_react3.memo)(
|
|
2582
|
+
(0, import_react3.forwardRef)(
|
|
2583
|
+
function ResourceExplorer2({
|
|
2584
|
+
parentFileId,
|
|
2585
|
+
sortableId,
|
|
2586
|
+
onSelectionChange,
|
|
2587
|
+
selectedIds: selectedIdsProp,
|
|
2588
|
+
media,
|
|
2589
|
+
setMedia: setMediaProp,
|
|
2590
|
+
readOnly = false,
|
|
2591
|
+
viewType = "list",
|
|
2592
|
+
fileKindFilter = "all",
|
|
2593
|
+
showRootItem = false,
|
|
2594
|
+
initialExpanded,
|
|
2595
|
+
expandable = true,
|
|
2596
|
+
renamable = true,
|
|
2597
|
+
onDoubleClickItem,
|
|
2598
|
+
rootItemId = import_noya_schemas3.rootResource.id,
|
|
2599
|
+
title,
|
|
2600
|
+
size = "medium",
|
|
2601
|
+
right,
|
|
2602
|
+
renderAction: renderActionProp,
|
|
2603
|
+
className,
|
|
2604
|
+
showUploadButton = true,
|
|
2605
|
+
showAllDescendants = true,
|
|
2606
|
+
scrollable = false,
|
|
2607
|
+
sortable = false,
|
|
2608
|
+
renderEmptyState,
|
|
2609
|
+
sharedDragProps,
|
|
2610
|
+
onClickItem,
|
|
2611
|
+
renderThumbnailIcon,
|
|
2612
|
+
onDidDeleteItems,
|
|
2613
|
+
onAssetsUploaded,
|
|
2614
|
+
itemClassName,
|
|
2615
|
+
itemStyle,
|
|
2616
|
+
publishedResources,
|
|
2617
|
+
virtualized = false,
|
|
2618
|
+
renderUser
|
|
2619
|
+
}, ref) {
|
|
2620
|
+
const setMedia = (0, import_react3.useCallback)(
|
|
2621
|
+
(...args) => {
|
|
2622
|
+
setMediaProp?.(...args);
|
|
2623
|
+
},
|
|
2624
|
+
[setMediaProp]
|
|
2625
|
+
);
|
|
2626
|
+
const tree = (0, import_react3.useMemo)(() => (0, import_noya_schemas3.createResourceTree)(media), [media]);
|
|
2627
|
+
const [tempItem, setTempItem] = (0, import_react3.useState)(
|
|
2628
|
+
void 0
|
|
2629
|
+
);
|
|
2630
|
+
const mediaWithTempItem = (0, import_react3.useMemo)(
|
|
2631
|
+
() => ({
|
|
2632
|
+
...media,
|
|
2633
|
+
...tempItem ? { [tempItem[0]]: tempItem[1] } : {}
|
|
2634
|
+
}),
|
|
2635
|
+
[media, tempItem]
|
|
2636
|
+
);
|
|
2637
|
+
const treeWithTempItem = (0, import_react3.useMemo)(
|
|
2638
|
+
() => (0, import_noya_schemas3.createResourceTree)(mediaWithTempItem),
|
|
2639
|
+
[mediaWithTempItem]
|
|
2640
|
+
);
|
|
2641
|
+
const temp = (0, import_react3.useMemo)(
|
|
2642
|
+
() => ({
|
|
2643
|
+
media: mediaWithTempItem,
|
|
2644
|
+
tree: treeWithTempItem
|
|
2645
|
+
}),
|
|
2646
|
+
[mediaWithTempItem, treeWithTempItem]
|
|
2647
|
+
);
|
|
2648
|
+
const [selectedIds, setSelectedIds] = (0, import_react_utils2.useControlledOrUncontrolled)({
|
|
2649
|
+
defaultValue: [],
|
|
2650
|
+
value: selectedIdsProp,
|
|
2651
|
+
onChange: onSelectionChange
|
|
2652
|
+
});
|
|
2653
|
+
const assetManager = (0, import_noya_multiplayer_react2.useAssetManager)();
|
|
2654
|
+
const assets = (0, import_noya_multiplayer_react2.useAssets)();
|
|
2655
|
+
const [expandedMap, setExpandedMap] = (0, import_react3.useState)({});
|
|
2656
|
+
const visibleItems = (0, import_react3.useMemo)(
|
|
2657
|
+
() => getVisibleItems({
|
|
2658
|
+
expandedMap,
|
|
2659
|
+
fileKindFilter,
|
|
2660
|
+
rootItemId,
|
|
2661
|
+
tree: treeWithTempItem,
|
|
2662
|
+
showAllDescendants,
|
|
2663
|
+
showRootItem
|
|
2664
|
+
}),
|
|
2665
|
+
[
|
|
2666
|
+
expandedMap,
|
|
2667
|
+
fileKindFilter,
|
|
2668
|
+
rootItemId,
|
|
2669
|
+
treeWithTempItem,
|
|
2670
|
+
showAllDescendants,
|
|
2671
|
+
showRootItem
|
|
2672
|
+
]
|
|
2673
|
+
);
|
|
2674
|
+
const depthMap = (0, import_react3.useMemo)(
|
|
2675
|
+
() => getDepthMap(import_noya_schemas3.rootResource, treeWithTempItem, showAllDescendants),
|
|
2676
|
+
[treeWithTempItem, showAllDescendants]
|
|
2677
|
+
);
|
|
2678
|
+
const collectionRef = (0, import_react3.useRef)(null);
|
|
2679
|
+
const selectedResources = (0, import_react3.useMemo)(
|
|
2680
|
+
() => treeWithTempItem.resourcesWithRoot.filter(
|
|
2681
|
+
(item) => selectedIds.includes(item.id)
|
|
2682
|
+
),
|
|
2683
|
+
[treeWithTempItem, selectedIds]
|
|
2684
|
+
);
|
|
2685
|
+
const groupedItems = (0, import_noya_utils4.groupBy)(selectedResources, (item) => item.type);
|
|
2686
|
+
const selectedAssetItems = groupedItems.asset ?? [];
|
|
2687
|
+
const selectedFolderItems = groupedItems.folder ?? [];
|
|
2688
|
+
const singleItemSelected = selectedResources.length === 1;
|
|
2689
|
+
const onlyAssetsSelected = selectedAssetItems.length > 0 && selectedAssetItems.length === selectedResources.length;
|
|
2690
|
+
const onlyFoldersSelected = selectedFolderItems.length > 0 && selectedFolderItems.length === selectedResources.length;
|
|
2691
|
+
const onlySingleFolderSelected = onlyFoldersSelected && selectedFolderItems.length === 1;
|
|
2692
|
+
const onlySingleAssetSelected = onlyAssetsSelected && selectedAssetItems.length === 1;
|
|
2693
|
+
const rootSelected = selectedIds.includes(import_noya_schemas3.rootResource.id);
|
|
2694
|
+
const sameParentSelected = selectedResources.every((item) => {
|
|
2695
|
+
const itemPath = tree.idToPathMap.get(item.id);
|
|
2696
|
+
const firstSelectedPath = tree.idToPathMap.get(selectedIds[0]);
|
|
2697
|
+
if (!itemPath || !firstSelectedPath) return false;
|
|
2698
|
+
return itemPath.startsWith(import_imfs6.path.dirname(firstSelectedPath));
|
|
2699
|
+
});
|
|
2700
|
+
(0, import_react3.useEffect)(() => {
|
|
2701
|
+
if (initialExpanded) {
|
|
2702
|
+
setExpandedMap(initialExpanded);
|
|
2703
|
+
}
|
|
2704
|
+
}, [initialExpanded]);
|
|
2705
|
+
const getExpanded = (0, import_react3.useCallback)(
|
|
2706
|
+
(item) => {
|
|
2707
|
+
if (!expandable) return void 0;
|
|
2708
|
+
if (item.type !== "directory") return void 0;
|
|
2709
|
+
if (item.id === import_noya_schemas3.rootResource.id) return void 0;
|
|
2710
|
+
return expandedMap[item.id] ?? false;
|
|
2711
|
+
},
|
|
2712
|
+
[expandedMap, expandable]
|
|
2713
|
+
);
|
|
2714
|
+
const openConfirmationDialog = (0, import_noya_designsystem2.useOpenConfirmationDialog)();
|
|
2715
|
+
const handleDelete = (0, import_react3.useCallback)(
|
|
2716
|
+
async (selectedIds2) => {
|
|
2717
|
+
const ok = await openConfirmationDialog({
|
|
2718
|
+
title: "Delete items",
|
|
2719
|
+
description: "Are you sure you want to delete these items? This action cannot be undone."
|
|
2720
|
+
});
|
|
2721
|
+
if (!ok) return;
|
|
2722
|
+
const deletedItems = Object.entries(media).flatMap(
|
|
2723
|
+
([path7, item]) => {
|
|
2724
|
+
if (selectedIds2.includes(item.id)) {
|
|
2725
|
+
return [[path7, item]];
|
|
2726
|
+
}
|
|
2727
|
+
return [];
|
|
2728
|
+
}
|
|
2729
|
+
);
|
|
2730
|
+
const newMedia = deleteResources({
|
|
2731
|
+
selectedIds: selectedIds2,
|
|
2732
|
+
media,
|
|
2733
|
+
tree
|
|
2734
|
+
});
|
|
2735
|
+
setSelectedIds([import_noya_schemas3.rootResource.id]);
|
|
2736
|
+
setMedia({ name: "Delete items", timestamp: Date.now() }, newMedia);
|
|
2737
|
+
onDidDeleteItems?.(deletedItems);
|
|
2738
|
+
},
|
|
2739
|
+
[
|
|
2740
|
+
media,
|
|
2741
|
+
setMedia,
|
|
2742
|
+
setSelectedIds,
|
|
2743
|
+
tree,
|
|
2744
|
+
onDidDeleteItems,
|
|
2745
|
+
openConfirmationDialog
|
|
2746
|
+
]
|
|
2747
|
+
);
|
|
2748
|
+
const onRename = (0, import_react3.useCallback)(
|
|
2749
|
+
(selectedItem, newName) => {
|
|
2750
|
+
if (!renamable) return;
|
|
2751
|
+
const selectedItemPath = treeWithTempItem.idToPathMap.get(
|
|
2752
|
+
selectedItem.id
|
|
2753
|
+
);
|
|
2754
|
+
if (!selectedItemPath) return;
|
|
2755
|
+
const renameIsValid = validateResourceRename({
|
|
2756
|
+
basename: newName,
|
|
2757
|
+
selectedItemPath,
|
|
2758
|
+
media: temp.media
|
|
2759
|
+
});
|
|
2760
|
+
if (!renameIsValid) {
|
|
2761
|
+
setTempItem(void 0);
|
|
2762
|
+
return;
|
|
2763
|
+
}
|
|
2764
|
+
const mediaWithRenamedDescendantPaths = renameResourceAndDescendantPaths({
|
|
2765
|
+
newName,
|
|
2766
|
+
selectedItemPath,
|
|
2767
|
+
media: temp.media,
|
|
2768
|
+
tree: temp.tree
|
|
2769
|
+
});
|
|
2770
|
+
setMedia(
|
|
2771
|
+
{ name: "Rename media item", timestamp: Date.now() },
|
|
2772
|
+
mediaWithRenamedDescendantPaths
|
|
2773
|
+
);
|
|
2774
|
+
setTempItem(void 0);
|
|
2775
|
+
},
|
|
2776
|
+
[
|
|
2777
|
+
renamable,
|
|
2778
|
+
setMedia,
|
|
2779
|
+
temp.media,
|
|
2780
|
+
temp.tree,
|
|
2781
|
+
treeWithTempItem.idToPathMap
|
|
2782
|
+
]
|
|
2783
|
+
);
|
|
2784
|
+
const handleAddFolder = (0, import_react3.useCallback)(
|
|
2785
|
+
(currentFolderId) => {
|
|
2786
|
+
const currentFolderPath = tree.idToPathMap.get(currentFolderId);
|
|
2787
|
+
if (!currentFolderPath) return;
|
|
2788
|
+
const newFolderPath = import_imfs6.path.join(
|
|
2789
|
+
currentFolderPath,
|
|
2790
|
+
import_noya_schemas3.PLACEHOLDER_ITEM_NAME
|
|
2791
|
+
);
|
|
2792
|
+
const newFolder = (0, import_noya_schemas3.createDirectoryResource)({
|
|
2793
|
+
path: newFolderPath,
|
|
2794
|
+
accessibleByFileId: parentFileId,
|
|
2795
|
+
id: newFolderPath,
|
|
2796
|
+
stableId: (0, import_noya_utils4.uuid)()
|
|
2797
|
+
});
|
|
2798
|
+
setTempItem([newFolderPath, newFolder]);
|
|
2799
|
+
setTimeout(() => {
|
|
2800
|
+
collectionRef.current?.editName(newFolder.id);
|
|
2801
|
+
}, 50);
|
|
2802
|
+
},
|
|
2803
|
+
[parentFileId, tree]
|
|
2804
|
+
);
|
|
2805
|
+
const handleMoveUpAFolder = (0, import_react3.useCallback)(
|
|
2806
|
+
(selectedIds2) => {
|
|
2807
|
+
const newMedia = moveUpAFolder({
|
|
2808
|
+
tree,
|
|
2809
|
+
media,
|
|
2810
|
+
selectedIds: selectedIds2
|
|
2811
|
+
});
|
|
2812
|
+
if (!newMedia) return;
|
|
2813
|
+
setMedia({ name: "Move items", timestamp: Date.now() }, newMedia);
|
|
2814
|
+
},
|
|
2815
|
+
[media, tree, setMedia]
|
|
2816
|
+
);
|
|
2817
|
+
const [isUploading, setIsUploading] = (0, import_react3.useState)(false);
|
|
2818
|
+
const handleUpload = (0, import_react3.useCallback)(
|
|
2819
|
+
async (selectedId) => {
|
|
2820
|
+
try {
|
|
2821
|
+
const files = await (0, import_browser_fs_access2.fileOpen)({ multiple: true });
|
|
2822
|
+
if (!files || !Array.isArray(files) || files.length === 0) return;
|
|
2823
|
+
const parentPath = tree.idToPathMap.get(selectedId);
|
|
2824
|
+
if (!parentPath) return;
|
|
2825
|
+
const uploadPromises = files.map(async (file) => {
|
|
2826
|
+
const assetPath = import_imfs6.path.join(parentPath, import_imfs6.path.basename(file.name));
|
|
2827
|
+
return {
|
|
2828
|
+
assetPath,
|
|
2829
|
+
asset: (0, import_noya_schemas3.createAssetResource)({
|
|
2830
|
+
id: (0, import_noya_utils4.uuid)(),
|
|
2831
|
+
asset: {
|
|
2832
|
+
content: import_noya_utils4.Base64.encode(await file.arrayBuffer()),
|
|
2833
|
+
contentType: file.type,
|
|
2834
|
+
encoding: "base64"
|
|
2835
|
+
},
|
|
2836
|
+
path: assetPath,
|
|
2837
|
+
accessibleByFileId: parentFileId,
|
|
2838
|
+
stableId: (0, import_noya_utils4.uuid)()
|
|
2839
|
+
})
|
|
2840
|
+
};
|
|
2841
|
+
});
|
|
2842
|
+
setIsUploading(true);
|
|
2843
|
+
const uploadedAssets = await Promise.all(uploadPromises);
|
|
2844
|
+
const newMediaMap = Object.fromEntries(
|
|
2845
|
+
uploadedAssets.map(({ assetPath, asset }) => [assetPath, asset])
|
|
2846
|
+
);
|
|
2847
|
+
setMedia(
|
|
2848
|
+
{ name: "Add media items", timestamp: Date.now() },
|
|
2849
|
+
{
|
|
2850
|
+
...media,
|
|
2851
|
+
...newMediaMap
|
|
2852
|
+
}
|
|
2853
|
+
);
|
|
2854
|
+
onAssetsUploaded?.(newMediaMap);
|
|
2855
|
+
} catch (error) {
|
|
2856
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2857
|
+
} else {
|
|
2858
|
+
console.error("Failed to upload files:", error);
|
|
2859
|
+
}
|
|
2860
|
+
} finally {
|
|
2861
|
+
setIsUploading(false);
|
|
2862
|
+
}
|
|
2863
|
+
},
|
|
2864
|
+
[tree, setMedia, media, onAssetsUploaded, parentFileId]
|
|
2865
|
+
);
|
|
2866
|
+
const handleDownload = (0, import_react3.useCallback)(
|
|
2867
|
+
async (selectedItems) => {
|
|
2868
|
+
const downloadPromises = selectedItems.filter((item) => item.type === "asset").map(async (item) => {
|
|
2869
|
+
const asset = assets.find((a) => a.id === item.assetId);
|
|
2870
|
+
if (!asset?.url) return;
|
|
2871
|
+
return (0, import_react_utils2.downloadUrl)(asset.url, tree.getNameForId(item.id));
|
|
2872
|
+
});
|
|
2873
|
+
await Promise.all(downloadPromises);
|
|
2874
|
+
},
|
|
2875
|
+
[assets, tree]
|
|
2876
|
+
);
|
|
2877
|
+
const handlePreview = (0, import_react3.useCallback)(
|
|
2878
|
+
async (selectedItems) => {
|
|
2879
|
+
const previewPromises = selectedItems.filter((item) => item.type === "asset").map(async (item) => {
|
|
2880
|
+
const asset = assets.find((a) => a.id === item.assetId);
|
|
2881
|
+
if (!asset?.url) return;
|
|
2882
|
+
return window?.open(asset.url, "_blank");
|
|
2883
|
+
});
|
|
2884
|
+
await Promise.all(previewPromises);
|
|
2885
|
+
},
|
|
2886
|
+
[assets]
|
|
2887
|
+
);
|
|
2888
|
+
const handleReplace = (0, import_react3.useCallback)(
|
|
2889
|
+
async (selectedItem) => {
|
|
2890
|
+
try {
|
|
2891
|
+
const file = await (0, import_browser_fs_access2.fileOpen)();
|
|
2892
|
+
if (!file) return;
|
|
2893
|
+
const asset = await assetManager.create(file);
|
|
2894
|
+
const oldFile = selectedItem;
|
|
2895
|
+
const oldFilePath = tree.idToPathMap.get(oldFile.id);
|
|
2896
|
+
if (!oldFilePath || oldFile.type !== "asset") return;
|
|
2897
|
+
setMedia(
|
|
2898
|
+
{ name: "Replace media file", timestamp: Date.now() },
|
|
2899
|
+
{
|
|
2900
|
+
...media,
|
|
2901
|
+
[oldFilePath]: (0, import_noya_schemas3.createAssetResource)({
|
|
2902
|
+
...oldFile,
|
|
2903
|
+
assetId: asset.id
|
|
2904
|
+
})
|
|
2905
|
+
}
|
|
2906
|
+
);
|
|
2907
|
+
} catch (error) {
|
|
2908
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2909
|
+
} else {
|
|
2910
|
+
console.error("Failed to upload files:", error);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
},
|
|
2914
|
+
[media, setMedia, assetManager, tree]
|
|
2915
|
+
);
|
|
2916
|
+
const handleRename = (0, import_react3.useCallback)(
|
|
2917
|
+
(selectedItemId) => {
|
|
2918
|
+
collectionRef.current?.editName(selectedItemId);
|
|
2919
|
+
},
|
|
2920
|
+
[collectionRef]
|
|
2921
|
+
);
|
|
2922
|
+
const handleMoveMediaInsideFolder = (0, import_react3.useCallback)(
|
|
2923
|
+
(sourceItems, targetItem) => {
|
|
2924
|
+
const newMedia = moveMediaInsideFolder({
|
|
2925
|
+
sourceItemIds: sourceItems.map((item) => item.id),
|
|
2926
|
+
targetItemId: targetItem.id,
|
|
2927
|
+
media,
|
|
2928
|
+
tree
|
|
2929
|
+
});
|
|
2930
|
+
setMedia(
|
|
2931
|
+
{
|
|
2932
|
+
name: "Move media file inside folder",
|
|
2933
|
+
timestamp: Date.now()
|
|
2934
|
+
},
|
|
2935
|
+
newMedia
|
|
2936
|
+
);
|
|
2937
|
+
},
|
|
2938
|
+
[media, setMedia, tree]
|
|
2939
|
+
);
|
|
2940
|
+
const assetContextMenuItems = (0, import_react3.useMemo)(() => {
|
|
2941
|
+
return (0, import_noya_designsystem2.createSectionedMenu)(
|
|
2942
|
+
[
|
|
2943
|
+
!rootSelected && singleItemSelected && {
|
|
2944
|
+
title: "Rename",
|
|
2945
|
+
value: "rename",
|
|
2946
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.InputIcon, null)
|
|
2947
|
+
},
|
|
2948
|
+
onlySingleAssetSelected && {
|
|
2949
|
+
title: "Replace",
|
|
2950
|
+
value: "replace",
|
|
2951
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.UpdateIcon, null)
|
|
2952
|
+
},
|
|
2953
|
+
!rootSelected && {
|
|
2954
|
+
title: "Delete",
|
|
2955
|
+
value: "delete",
|
|
2956
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.TrashIcon, null)
|
|
2957
|
+
}
|
|
2958
|
+
],
|
|
2959
|
+
[
|
|
2960
|
+
onlySingleFolderSelected && {
|
|
2961
|
+
title: "Upload Files",
|
|
2962
|
+
value: "upload",
|
|
2963
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.UploadIcon, null)
|
|
2964
|
+
},
|
|
2965
|
+
onlySingleFolderSelected && {
|
|
2966
|
+
title: "Add Folder",
|
|
2967
|
+
value: "addFolder",
|
|
2968
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.FolderIcon, null)
|
|
2969
|
+
},
|
|
2970
|
+
onlyAssetsSelected && tree.resourcesWithRoot.length > 0 && {
|
|
2971
|
+
title: "Download",
|
|
2972
|
+
value: "download",
|
|
2973
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.DownloadIcon, null)
|
|
2974
|
+
},
|
|
2975
|
+
onlySingleAssetSelected && {
|
|
2976
|
+
title: "Preview",
|
|
2977
|
+
value: "preview",
|
|
2978
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.OpenInNewWindowIcon, null)
|
|
2979
|
+
}
|
|
2980
|
+
],
|
|
2981
|
+
[
|
|
2982
|
+
!rootSelected && sameParentSelected && {
|
|
2983
|
+
title: "Move up a folder",
|
|
2984
|
+
value: "move",
|
|
2985
|
+
icon: /* @__PURE__ */ import_react4.default.createElement(import_noya_icons2.ResetIcon, null)
|
|
2986
|
+
}
|
|
2987
|
+
]
|
|
2988
|
+
);
|
|
2989
|
+
}, [
|
|
2990
|
+
rootSelected,
|
|
2991
|
+
singleItemSelected,
|
|
2992
|
+
onlySingleAssetSelected,
|
|
2993
|
+
onlySingleFolderSelected,
|
|
2994
|
+
onlyAssetsSelected,
|
|
2995
|
+
tree.resourcesWithRoot.length,
|
|
2996
|
+
sameParentSelected
|
|
2997
|
+
]);
|
|
2998
|
+
const handleMenuAction = (0, import_react3.useCallback)(
|
|
2999
|
+
async (action, selectedItems) => {
|
|
3000
|
+
if (selectedItems.length === 0) return;
|
|
3001
|
+
switch (action) {
|
|
3002
|
+
case "rename":
|
|
3003
|
+
handleRename(selectedItems[0].id);
|
|
3004
|
+
return;
|
|
3005
|
+
case "delete":
|
|
3006
|
+
handleDelete(selectedIds);
|
|
3007
|
+
return;
|
|
3008
|
+
case "replace":
|
|
3009
|
+
handleReplace(selectedItems[0]);
|
|
3010
|
+
return;
|
|
3011
|
+
case "upload":
|
|
3012
|
+
handleUpload(selectedItems[0].id);
|
|
3013
|
+
return;
|
|
3014
|
+
case "addFolder":
|
|
3015
|
+
handleAddFolder(selectedItems[0].id);
|
|
3016
|
+
return;
|
|
3017
|
+
case "preview":
|
|
3018
|
+
handlePreview(selectedItems);
|
|
3019
|
+
return;
|
|
3020
|
+
case "download":
|
|
3021
|
+
handleDownload(selectedItems);
|
|
3022
|
+
return;
|
|
3023
|
+
case "move":
|
|
3024
|
+
handleMoveUpAFolder(selectedIds);
|
|
3025
|
+
return;
|
|
3026
|
+
}
|
|
3027
|
+
},
|
|
3028
|
+
[
|
|
3029
|
+
handleRename,
|
|
3030
|
+
handleDelete,
|
|
3031
|
+
selectedIds,
|
|
3032
|
+
handleReplace,
|
|
3033
|
+
handleUpload,
|
|
3034
|
+
handleAddFolder,
|
|
3035
|
+
handlePreview,
|
|
3036
|
+
handleDownload,
|
|
3037
|
+
handleMoveUpAFolder
|
|
3038
|
+
]
|
|
3039
|
+
);
|
|
3040
|
+
const handleSetExpanded = (0, import_react3.useCallback)(
|
|
3041
|
+
(item, expanded) => {
|
|
3042
|
+
setExpandedMap(
|
|
3043
|
+
(prev) => updateExpandedMap({
|
|
3044
|
+
item,
|
|
3045
|
+
expanded,
|
|
3046
|
+
expandable,
|
|
3047
|
+
expandedMap: prev,
|
|
3048
|
+
tree
|
|
3049
|
+
})
|
|
3050
|
+
);
|
|
3051
|
+
},
|
|
3052
|
+
[expandable, tree]
|
|
3053
|
+
);
|
|
3054
|
+
const renderAction = (0, import_react3.useMemo)(() => {
|
|
3055
|
+
if (renderActionProp) return renderActionProp;
|
|
3056
|
+
return ({
|
|
3057
|
+
selected,
|
|
3058
|
+
onOpenChange
|
|
3059
|
+
}) => /* @__PURE__ */ import_react4.default.createElement(
|
|
3060
|
+
"div",
|
|
3061
|
+
{
|
|
3062
|
+
style: {
|
|
3063
|
+
minWidth: "75px",
|
|
3064
|
+
display: "flex",
|
|
3065
|
+
justifyContent: "flex-end"
|
|
3066
|
+
}
|
|
3067
|
+
},
|
|
3068
|
+
/* @__PURE__ */ import_react4.default.createElement(
|
|
3069
|
+
import_noya_designsystem2.ActionMenu,
|
|
3070
|
+
{
|
|
3071
|
+
menuItems: assetContextMenuItems,
|
|
3072
|
+
onSelect: (action) => handleMenuAction(action, selectedResources),
|
|
3073
|
+
selected,
|
|
3074
|
+
onOpenChange,
|
|
3075
|
+
variant: viewType === "grid" ? "normal" : "bare",
|
|
3076
|
+
style: {
|
|
3077
|
+
backgroundColor: selected ? import_noya_designsystem2.cssVars.colors.selectedListItemBackground : "transparent",
|
|
3078
|
+
color: selected ? import_noya_designsystem2.cssVars.colors.selectedListItemText : void 0
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
)
|
|
3082
|
+
);
|
|
3083
|
+
}, [
|
|
3084
|
+
assetContextMenuItems,
|
|
3085
|
+
handleMenuAction,
|
|
3086
|
+
renderActionProp,
|
|
3087
|
+
selectedResources,
|
|
3088
|
+
viewType
|
|
3089
|
+
]);
|
|
3090
|
+
(0, import_react3.useImperativeHandle)(ref, () => ({
|
|
3091
|
+
upload: (selectedId) => handleUpload(selectedId),
|
|
3092
|
+
delete: handleDelete,
|
|
3093
|
+
download: handleDownload,
|
|
3094
|
+
rename: handleRename,
|
|
3095
|
+
addFolder: handleAddFolder,
|
|
3096
|
+
moveUpAFolder: handleMoveUpAFolder,
|
|
3097
|
+
replace: handleReplace,
|
|
3098
|
+
preview: handlePreview,
|
|
3099
|
+
moveMediaInsideFolder: handleMoveMediaInsideFolder,
|
|
3100
|
+
getItemAtIndex: (index) => visibleItems[index]
|
|
3101
|
+
}));
|
|
3102
|
+
const diffResources = (0, import_react3.useMemo)(() => {
|
|
3103
|
+
if (!publishedResources) return;
|
|
3104
|
+
const diff = (0, import_noya_schemas3.diffResourceMaps)(publishedResources, media, "stableId");
|
|
3105
|
+
return {
|
|
3106
|
+
added: new Set(
|
|
3107
|
+
diff.addedResources.map((resource) => resource.stableId)
|
|
3108
|
+
),
|
|
3109
|
+
removed: new Set(
|
|
3110
|
+
diff.removedResources.map((resource) => resource.stableId)
|
|
3111
|
+
),
|
|
3112
|
+
modified: new Set(
|
|
3113
|
+
diff.modifiedResources.map((resource) => resource.stableId)
|
|
3114
|
+
)
|
|
3115
|
+
};
|
|
3116
|
+
}, [media, publishedResources]);
|
|
3117
|
+
const keyExtractor = (0, import_react3.useCallback)((item) => item.id, []);
|
|
3118
|
+
const renderCollection = (virtualizedSize) => /* @__PURE__ */ import_react4.default.createElement(
|
|
3119
|
+
import_noya_designsystem2.FileExplorerCollection,
|
|
3120
|
+
{
|
|
3121
|
+
ref: collectionRef,
|
|
3122
|
+
sortableId,
|
|
3123
|
+
scrollable,
|
|
3124
|
+
sharedDragProps,
|
|
3125
|
+
items: visibleItems,
|
|
3126
|
+
viewType,
|
|
3127
|
+
size,
|
|
3128
|
+
getId: keyExtractor,
|
|
3129
|
+
getName: (file) => {
|
|
3130
|
+
if (file.id === tempItem?.[1].id) {
|
|
3131
|
+
return "";
|
|
3132
|
+
}
|
|
3133
|
+
return treeWithTempItem.getNameForId(file.id);
|
|
3134
|
+
},
|
|
3135
|
+
expandable,
|
|
3136
|
+
sortable,
|
|
3137
|
+
getPlaceholder: (item) => {
|
|
3138
|
+
switch (item.type) {
|
|
3139
|
+
case "directory":
|
|
3140
|
+
return "Enter folder name";
|
|
3141
|
+
case "resource":
|
|
3142
|
+
case "asset":
|
|
3143
|
+
case "file":
|
|
3144
|
+
return "Enter file name";
|
|
3145
|
+
}
|
|
3146
|
+
},
|
|
3147
|
+
getExpanded,
|
|
3148
|
+
setExpanded: handleSetExpanded,
|
|
3149
|
+
getRenamable: (item) => {
|
|
3150
|
+
if (item.id === import_noya_schemas3.rootResource.id) return false;
|
|
3151
|
+
return true;
|
|
3152
|
+
},
|
|
3153
|
+
getDepth: (item) => depthMap[item.id],
|
|
3154
|
+
menuItems: assetContextMenuItems,
|
|
3155
|
+
onSelectMenuItem: handleMenuAction,
|
|
3156
|
+
onSelectionChange: setSelectedIds,
|
|
3157
|
+
onClickItem,
|
|
3158
|
+
onClick: () => {
|
|
3159
|
+
setSelectedIds([]);
|
|
3160
|
+
},
|
|
3161
|
+
onDoubleClickItem,
|
|
3162
|
+
onRename,
|
|
3163
|
+
renamable,
|
|
3164
|
+
selectedIds,
|
|
3165
|
+
itemClassName,
|
|
3166
|
+
itemStyle,
|
|
3167
|
+
virtualized: virtualizedSize,
|
|
3168
|
+
renderThumbnail: (props) => /* @__PURE__ */ import_react4.default.createElement(
|
|
3169
|
+
ResourceThumbnail,
|
|
3170
|
+
{
|
|
3171
|
+
...props,
|
|
3172
|
+
path: tree.idToPathMap.get(props.item.id),
|
|
3173
|
+
renderThumbnailIcon,
|
|
3174
|
+
viewType
|
|
3175
|
+
}
|
|
3176
|
+
),
|
|
3177
|
+
renderAction,
|
|
3178
|
+
renderRight: (file) => {
|
|
3179
|
+
if (file.type !== "asset") return null;
|
|
3180
|
+
const publishStatus = getPublishStatus({
|
|
3181
|
+
resource: file,
|
|
3182
|
+
diff: diffResources
|
|
3183
|
+
});
|
|
3184
|
+
return /* @__PURE__ */ import_react4.default.createElement(
|
|
3185
|
+
"div",
|
|
3186
|
+
{
|
|
3187
|
+
style: { display: "flex", alignItems: "center", gap: "1.5px" }
|
|
3188
|
+
},
|
|
3189
|
+
publishStatus && /* @__PURE__ */ import_react4.default.createElement(
|
|
3190
|
+
import_noya_designsystem2.Chip,
|
|
3191
|
+
{
|
|
3192
|
+
colorScheme: publishStatus === "Modified" ? "info" : publishStatus === "Added" ? "secondary" : "primary"
|
|
3193
|
+
},
|
|
3194
|
+
publishStatus
|
|
3195
|
+
),
|
|
3196
|
+
renderUser?.(file)
|
|
3197
|
+
);
|
|
3198
|
+
},
|
|
3199
|
+
renderDetail: (file, selected) => {
|
|
3200
|
+
if (file.type !== "asset") return null;
|
|
3201
|
+
const asset = assets.find((a) => a.id === file.assetId);
|
|
3202
|
+
if (!asset) return null;
|
|
3203
|
+
return /* @__PURE__ */ import_react4.default.createElement(
|
|
3204
|
+
import_noya_designsystem2.FileExplorerDetail,
|
|
3205
|
+
{
|
|
3206
|
+
selected,
|
|
3207
|
+
size,
|
|
3208
|
+
style: { minWidth: "75px", textAlign: "right" }
|
|
3209
|
+
},
|
|
3210
|
+
(0, import_noya_designsystem2.formatByteSize)(asset.size)
|
|
3211
|
+
);
|
|
3212
|
+
},
|
|
3213
|
+
renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ import_react4.default.createElement(import_noya_designsystem2.FileExplorerEmptyState, null),
|
|
3214
|
+
itemRoleDescription: "clickable file item",
|
|
3215
|
+
getDropTargetParentIndex: (overIndex) => {
|
|
3216
|
+
const item = visibleItems[overIndex];
|
|
3217
|
+
const parentIndex = visibleItems.findIndex(
|
|
3218
|
+
(i) => i.id === tree.getParentIdForId(item.id)
|
|
3219
|
+
);
|
|
3220
|
+
return parentIndex === -1 ? void 0 : parentIndex;
|
|
3221
|
+
},
|
|
3222
|
+
acceptsDrop: ({
|
|
3223
|
+
sourceIndex,
|
|
3224
|
+
targetIndex,
|
|
3225
|
+
position,
|
|
3226
|
+
sourceListId,
|
|
3227
|
+
targetListId
|
|
3228
|
+
}) => {
|
|
3229
|
+
if (sourceListId !== targetListId) {
|
|
3230
|
+
return false;
|
|
3231
|
+
}
|
|
3232
|
+
if (sourceListId !== sortableId || targetListId !== sortableId) {
|
|
3233
|
+
return false;
|
|
3234
|
+
}
|
|
3235
|
+
const sourceItem = visibleItems[sourceIndex];
|
|
3236
|
+
const targetItem = visibleItems[targetIndex];
|
|
3237
|
+
return acceptsResourceDrop({
|
|
3238
|
+
position,
|
|
3239
|
+
sourceItem,
|
|
3240
|
+
targetItem,
|
|
3241
|
+
tree
|
|
3242
|
+
});
|
|
3243
|
+
},
|
|
3244
|
+
onMoveItem: ({
|
|
3245
|
+
sourceListId,
|
|
3246
|
+
sourceIndex,
|
|
3247
|
+
targetListId,
|
|
3248
|
+
targetIndex,
|
|
3249
|
+
position
|
|
3250
|
+
}) => {
|
|
3251
|
+
if (sourceListId !== sortableId || targetListId !== sortableId || position !== "inside") {
|
|
3252
|
+
return;
|
|
3253
|
+
}
|
|
3254
|
+
const selectedItems = visibleItems.filter(
|
|
3255
|
+
(item) => selectedIds.includes(item.id)
|
|
3256
|
+
);
|
|
3257
|
+
const sourceItem = visibleItems[sourceIndex];
|
|
3258
|
+
const itemsToMove = selectedIds.includes(sourceItem.id) ? selectedItems : [sourceItem];
|
|
3259
|
+
const targetItem = visibleItems[targetIndex];
|
|
3260
|
+
handleMoveMediaInsideFolder(itemsToMove, targetItem);
|
|
3261
|
+
},
|
|
3262
|
+
onFilesDrop: async (event) => {
|
|
3263
|
+
event.preventDefault();
|
|
3264
|
+
const rootItemPath = tree.idToPathMap.get(rootItemId);
|
|
3265
|
+
if (!rootItemPath) return;
|
|
3266
|
+
const newMedia = await handleDataTransfer({
|
|
3267
|
+
dataTransfer: event.dataTransfer,
|
|
3268
|
+
rootItemPath,
|
|
3269
|
+
resourceMap: media,
|
|
3270
|
+
accessibleByFileId: parentFileId
|
|
3271
|
+
});
|
|
3272
|
+
if (!newMedia) return;
|
|
3273
|
+
setMedia(
|
|
3274
|
+
{ name: "Add media files", timestamp: Date.now() },
|
|
3275
|
+
newMedia
|
|
3276
|
+
);
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
);
|
|
3280
|
+
return /* @__PURE__ */ import_react4.default.createElement(
|
|
3281
|
+
import_noya_designsystem2.FileExplorerLayout,
|
|
3282
|
+
{
|
|
3283
|
+
title: title ?? import_noya_schemas3.rootResourceName,
|
|
3284
|
+
right: !readOnly && /* @__PURE__ */ import_react4.default.createElement(
|
|
3285
|
+
import_noya_designsystem2.FileExplorerUploadButton,
|
|
3286
|
+
{
|
|
3287
|
+
showUploadButton,
|
|
3288
|
+
onUpload: () => handleUpload(import_noya_schemas3.rootResource.id),
|
|
3289
|
+
isUploading
|
|
3290
|
+
},
|
|
3291
|
+
right
|
|
3292
|
+
),
|
|
3293
|
+
className
|
|
3294
|
+
},
|
|
3295
|
+
virtualized ? /* @__PURE__ */ import_react4.default.createElement(import_react_utils2.AutoSizer, null, ({ width, height }) => (
|
|
3296
|
+
// add 24px to account for the -mx-3 on the Collection component
|
|
3297
|
+
renderCollection({ width: width + 24, height })
|
|
3298
|
+
)) : renderCollection(void 0)
|
|
3299
|
+
);
|
|
3300
|
+
}
|
|
3301
|
+
)
|
|
3302
|
+
);
|
|
3303
|
+
function acceptsResourceDrop(parameters) {
|
|
3304
|
+
const { position, sourceItem, targetItem, tree } = parameters;
|
|
3305
|
+
if (position !== "inside" || targetItem.type === "asset") {
|
|
3306
|
+
return false;
|
|
3307
|
+
}
|
|
3308
|
+
const sourcePath = tree.findPath(
|
|
3309
|
+
import_noya_schemas3.rootResource,
|
|
3310
|
+
(item) => item.id === sourceItem.id
|
|
3311
|
+
);
|
|
3312
|
+
const targetPath = tree.findPath(
|
|
3313
|
+
import_noya_schemas3.rootResource,
|
|
3314
|
+
(item) => item.id === targetItem.id
|
|
3315
|
+
);
|
|
3316
|
+
if (!sourcePath || !targetPath) return false;
|
|
3317
|
+
if ((0, import_noya_utils4.isDeepEqual)(sourcePath, targetPath.slice(0, sourcePath.length))) {
|
|
3318
|
+
return false;
|
|
3319
|
+
}
|
|
3320
|
+
return true;
|
|
3321
|
+
}
|
|
3322
|
+
function getPublishStatus({
|
|
3323
|
+
resource,
|
|
3324
|
+
diff
|
|
3325
|
+
}) {
|
|
3326
|
+
if (!diff) return void 0;
|
|
3327
|
+
return diff.modified.has(resource.stableId) ? "Modified" : diff.added.has(resource.stableId) ? "Added" : diff.removed.has(resource.stableId) ? "Removed" : (
|
|
3328
|
+
// We don't have to check for the specific ID, since if anything had been published
|
|
3329
|
+
// but removed, it will be in the removed set
|
|
3330
|
+
"Published"
|
|
3331
|
+
);
|
|
3332
|
+
}
|
|
2266
3333
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2267
3334
|
0 && (module.exports = {
|
|
2268
3335
|
MediaCollection,
|
|
2269
3336
|
PLACEHOLDER_ITEM_NAME,
|
|
3337
|
+
ResourceExplorer,
|
|
3338
|
+
ResourceThumbnail,
|
|
2270
3339
|
acceptsMediaItemDrop,
|
|
3340
|
+
acceptsResourceDrop,
|
|
2271
3341
|
basenameValidator,
|
|
2272
3342
|
createMediaAsset,
|
|
2273
3343
|
createMediaFile,
|
|
2274
3344
|
createMediaFolder,
|
|
2275
3345
|
createMediaItem,
|
|
2276
3346
|
createMediaItemTree,
|
|
2277
|
-
|
|
3347
|
+
deleteResources,
|
|
2278
3348
|
getDepthMap,
|
|
2279
3349
|
getParentDirectories,
|
|
2280
3350
|
getVisibleItems,
|
|
3351
|
+
gridThumbnailDimension,
|
|
3352
|
+
mediaDeleteMediaItems,
|
|
3353
|
+
mediaGetDepthMap,
|
|
3354
|
+
mediaGetParentDirectories,
|
|
3355
|
+
mediaGetVisibleItems,
|
|
3356
|
+
mediaMoveMediaInsideFolder,
|
|
3357
|
+
mediaMovePathsIntoTarget,
|
|
3358
|
+
mediaMoveUpAFolder,
|
|
3359
|
+
mediaRenameMediaItemAndDescendantPaths,
|
|
3360
|
+
mediaUpdateExpandedMap,
|
|
3361
|
+
mediaValidateMediaItemRename,
|
|
2281
3362
|
moveMediaInsideFolder,
|
|
2282
3363
|
movePathsIntoTarget,
|
|
2283
3364
|
moveUpAFolder,
|
|
2284
|
-
|
|
3365
|
+
renameResourceAndDescendantPaths,
|
|
2285
3366
|
rootMediaItem,
|
|
2286
3367
|
rootMediaItemName,
|
|
2287
3368
|
rootMediaItemPath,
|
|
2288
3369
|
updateExpandedMap,
|
|
2289
|
-
|
|
3370
|
+
validateResourceRename
|
|
2290
3371
|
});
|
|
2291
3372
|
//# sourceMappingURL=index.js.map
|