@noya-app/noya-file-explorer 0.0.15 → 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 +27 -0
- package/dist/index.css +916 -843
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +11207 -45
- package/dist/index.d.ts +11207 -45
- package/dist/index.js +1361 -160
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1399 -156
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- package/src/MediaCollection.tsx +156 -97
- 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 -1
- package/src/utils/files.ts +28 -37
- package/src/utils/handleFileDrop.ts +165 -0
- package/src/utils/resourceUtils.ts +329 -0
- package/src/formatByteSize.ts +0 -8
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,38 +1111,43 @@ 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,
|
|
1116
|
+
acceptsMediaItemDrop: () => acceptsMediaItemDrop,
|
|
1117
|
+
acceptsResourceDrop: () => acceptsResourceDrop,
|
|
1114
1118
|
basenameValidator: () => basenameValidator,
|
|
1115
1119
|
createMediaAsset: () => createMediaAsset,
|
|
1116
1120
|
createMediaFile: () => createMediaFile,
|
|
1117
1121
|
createMediaFolder: () => createMediaFolder,
|
|
1118
1122
|
createMediaItem: () => createMediaItem,
|
|
1119
1123
|
createMediaItemTree: () => createMediaItemTree,
|
|
1120
|
-
|
|
1121
|
-
formatByteSize: () => formatByteSize,
|
|
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
|
|
|
1137
|
-
// src/formatByteSize.ts
|
|
1138
|
-
var byteSizeUnits = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
1139
|
-
function formatByteSize(size) {
|
|
1140
|
-
const unitIndex = Math.floor(Math.log(size) / Math.log(1024));
|
|
1141
|
-
const unit = byteSizeUnits[unitIndex];
|
|
1142
|
-
const value = size / Math.pow(1024, unitIndex);
|
|
1143
|
-
return `${value.toFixed(1)} ${unit}`;
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
1151
|
// src/MediaCollection.tsx
|
|
1147
1152
|
var import_noya_designsystem = require("@noya-app/noya-designsystem");
|
|
1148
1153
|
var import_noya_icons = require("@noya-app/noya-icons");
|
|
@@ -1234,10 +1239,15 @@ var createMediaItemTree = (mediaMap) => {
|
|
|
1234
1239
|
};
|
|
1235
1240
|
|
|
1236
1241
|
// src/MediaCollection.tsx
|
|
1237
|
-
var
|
|
1242
|
+
var import_imfs4 = require("imfs");
|
|
1238
1243
|
var import_react2 = __toESM(require("react"));
|
|
1239
1244
|
|
|
1240
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");
|
|
1241
1251
|
var import_imfs2 = require("imfs");
|
|
1242
1252
|
var import_tree_visit2 = __toESM(require_lib());
|
|
1243
1253
|
var getVisibleItems = ({
|
|
@@ -1249,7 +1259,7 @@ var getVisibleItems = ({
|
|
|
1249
1259
|
showRootItem
|
|
1250
1260
|
}) => {
|
|
1251
1261
|
const filteredItems = [];
|
|
1252
|
-
const relativeRootItem = tree.find(
|
|
1262
|
+
const relativeRootItem = tree.find(import_noya_schemas.rootResource, (item) => item.id === rootItemId) ?? import_noya_schemas.rootResource;
|
|
1253
1263
|
tree.visit(relativeRootItem, (item) => {
|
|
1254
1264
|
if (relativeRootItem.id === item.id) {
|
|
1255
1265
|
if (showRootItem) {
|
|
@@ -1257,13 +1267,16 @@ var getVisibleItems = ({
|
|
|
1257
1267
|
}
|
|
1258
1268
|
return;
|
|
1259
1269
|
}
|
|
1260
|
-
if (item.
|
|
1270
|
+
if (item.type === "file" && fileKindFilter === "all") {
|
|
1261
1271
|
filteredItems.push(item);
|
|
1262
1272
|
}
|
|
1263
|
-
if (item.
|
|
1273
|
+
if (item.type === "asset" && (fileKindFilter === "assets" || fileKindFilter === "all")) {
|
|
1264
1274
|
filteredItems.push(item);
|
|
1265
1275
|
}
|
|
1266
|
-
if (item.
|
|
1276
|
+
if (item.type === "directory" && (fileKindFilter === "directories" || fileKindFilter === "all")) {
|
|
1277
|
+
filteredItems.push(item);
|
|
1278
|
+
}
|
|
1279
|
+
if (item.type === "resource" && (fileKindFilter === "resources" || fileKindFilter === "all")) {
|
|
1267
1280
|
filteredItems.push(item);
|
|
1268
1281
|
}
|
|
1269
1282
|
if (!expandedMap[item.id] || !showAllDescendants) return "skip";
|
|
@@ -1275,7 +1288,7 @@ var basenameValidator = (basename) => {
|
|
|
1275
1288
|
const invalidCharsRegex = /[/\\<>:"|?*]/;
|
|
1276
1289
|
return !invalidCharsRegex.test(basename);
|
|
1277
1290
|
};
|
|
1278
|
-
var
|
|
1291
|
+
var validateResourceRename = ({
|
|
1279
1292
|
basename,
|
|
1280
1293
|
selectedItemPath,
|
|
1281
1294
|
media
|
|
@@ -1293,7 +1306,7 @@ var movePathsIntoTarget = ({
|
|
|
1293
1306
|
tree
|
|
1294
1307
|
}) => {
|
|
1295
1308
|
const ancestors = (0, import_tree_visit2.ancestorPaths)(
|
|
1296
|
-
sourceItemPaths.map((
|
|
1309
|
+
sourceItemPaths.map((path7) => path7.split("/"))
|
|
1297
1310
|
);
|
|
1298
1311
|
const mediaClone = { ...media };
|
|
1299
1312
|
for (const ancestor of ancestors) {
|
|
@@ -1311,7 +1324,7 @@ var movePathsIntoTarget = ({
|
|
|
1311
1324
|
ancestorPath,
|
|
1312
1325
|
newAncestorPath
|
|
1313
1326
|
);
|
|
1314
|
-
const newPathIsValid =
|
|
1327
|
+
const newPathIsValid = validateResourceRename({
|
|
1315
1328
|
basename: import_imfs2.path.basename(descendantPath),
|
|
1316
1329
|
selectedItemPath: newDescendantPath,
|
|
1317
1330
|
media
|
|
@@ -1330,17 +1343,17 @@ var moveUpAFolder = ({
|
|
|
1330
1343
|
selectedIds
|
|
1331
1344
|
}) => {
|
|
1332
1345
|
const indexPath = tree.findPath(
|
|
1333
|
-
|
|
1346
|
+
import_noya_schemas.rootResource,
|
|
1334
1347
|
(item) => item.id === selectedIds[0]
|
|
1335
1348
|
);
|
|
1336
1349
|
if (!indexPath) return;
|
|
1337
1350
|
const grandparentFolder = tree.access(
|
|
1338
|
-
|
|
1351
|
+
import_noya_schemas.rootResource,
|
|
1339
1352
|
indexPath.slice(0, indexPath.length - 2)
|
|
1340
1353
|
);
|
|
1341
1354
|
const grandparentFolderPath = tree.idToPathMap.get(grandparentFolder.id);
|
|
1342
1355
|
if (!grandparentFolderPath) return;
|
|
1343
|
-
const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((
|
|
1356
|
+
const sourceItemPaths = selectedIds.map((id) => tree.idToPathMap.get(id)).filter((path7) => Boolean(path7));
|
|
1344
1357
|
return movePathsIntoTarget({
|
|
1345
1358
|
media,
|
|
1346
1359
|
targetItemPath: grandparentFolderPath,
|
|
@@ -1369,7 +1382,7 @@ var updateExpandedMap = ({
|
|
|
1369
1382
|
const newExpandedMap = { ...expandedMap };
|
|
1370
1383
|
const inner = (item2, expanded2) => {
|
|
1371
1384
|
if (!expandable) return {};
|
|
1372
|
-
if (item2.id ===
|
|
1385
|
+
if (item2.id === import_noya_schemas.rootResource.id) return {};
|
|
1373
1386
|
if (!expanded2) {
|
|
1374
1387
|
const children = tree.getChildren(item2, []);
|
|
1375
1388
|
children.forEach((child) => inner(child, false));
|
|
@@ -1379,13 +1392,13 @@ var updateExpandedMap = ({
|
|
|
1379
1392
|
inner(item, expanded);
|
|
1380
1393
|
return newExpandedMap;
|
|
1381
1394
|
};
|
|
1382
|
-
var
|
|
1395
|
+
var deleteResources = ({
|
|
1383
1396
|
selectedIds,
|
|
1384
1397
|
media,
|
|
1385
1398
|
tree
|
|
1386
1399
|
}) => {
|
|
1387
1400
|
const itemsToDelete = selectedIds.flatMap((mediaItemId) => {
|
|
1388
|
-
const mediaItem = tree.
|
|
1401
|
+
const mediaItem = tree.resourcesWithRoot.find(
|
|
1389
1402
|
(item) => item.id === mediaItemId
|
|
1390
1403
|
);
|
|
1391
1404
|
if (!mediaItem) return [];
|
|
@@ -1406,7 +1419,7 @@ var moveMediaInsideFolder = ({
|
|
|
1406
1419
|
}) => {
|
|
1407
1420
|
const targetItemPath = tree.idToPathMap.get(targetItemId);
|
|
1408
1421
|
if (!targetItemPath) return media;
|
|
1409
|
-
const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((
|
|
1422
|
+
const sourceItemPaths = sourceItemIds.map((id) => tree.idToPathMap.get(id)).filter((path7) => Boolean(path7));
|
|
1410
1423
|
return movePathsIntoTarget({
|
|
1411
1424
|
media,
|
|
1412
1425
|
sourceItemPaths,
|
|
@@ -1414,7 +1427,213 @@ var moveMediaInsideFolder = ({
|
|
|
1414
1427
|
tree
|
|
1415
1428
|
});
|
|
1416
1429
|
};
|
|
1417
|
-
var getParentDirectories = (
|
|
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);
|
|
1435
|
+
};
|
|
1436
|
+
var renameResourceAndDescendantPaths = ({
|
|
1437
|
+
newName,
|
|
1438
|
+
selectedItemPath,
|
|
1439
|
+
media,
|
|
1440
|
+
tree
|
|
1441
|
+
}) => {
|
|
1442
|
+
const mediaClone = { ...media };
|
|
1443
|
+
const selectedItem = mediaClone[selectedItemPath];
|
|
1444
|
+
if (!selectedItem) return mediaClone;
|
|
1445
|
+
const parentPath = import_imfs2.path.dirname(selectedItemPath);
|
|
1446
|
+
const newItemPath = import_imfs2.path.join(parentPath, newName);
|
|
1447
|
+
const descendants = tree.flat(selectedItem).map((item) => tree.idToPathMap.get(item.id));
|
|
1448
|
+
for (const descendantPath of descendants) {
|
|
1449
|
+
if (!descendantPath) continue;
|
|
1450
|
+
const newDescendantPath = descendantPath.replace(
|
|
1451
|
+
selectedItemPath,
|
|
1452
|
+
newItemPath
|
|
1453
|
+
);
|
|
1454
|
+
mediaClone[newDescendantPath] = {
|
|
1455
|
+
...mediaClone[descendantPath],
|
|
1456
|
+
path: newDescendantPath
|
|
1457
|
+
};
|
|
1458
|
+
delete mediaClone[descendantPath];
|
|
1459
|
+
}
|
|
1460
|
+
return mediaClone;
|
|
1461
|
+
};
|
|
1462
|
+
|
|
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 = ({
|
|
1509
|
+
media,
|
|
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)
|
|
1524
|
+
);
|
|
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
|
|
1532
|
+
);
|
|
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];
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
return mediaClone;
|
|
1545
|
+
};
|
|
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);
|
|
1575
|
+
} else {
|
|
1576
|
+
depthMap[item2.id] = 0;
|
|
1577
|
+
}
|
|
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) => {
|
|
1418
1637
|
const tree = createMediaItemTree(mediaMap);
|
|
1419
1638
|
const indexPath = tree.findPath(
|
|
1420
1639
|
rootMediaItem,
|
|
@@ -1423,7 +1642,7 @@ var getParentDirectories = (mediaMap, folderId) => {
|
|
|
1423
1642
|
if (!indexPath) return [rootMediaItem];
|
|
1424
1643
|
return tree.accessPath(rootMediaItem, indexPath);
|
|
1425
1644
|
};
|
|
1426
|
-
var
|
|
1645
|
+
var mediaRenameMediaItemAndDescendantPaths = ({
|
|
1427
1646
|
newName,
|
|
1428
1647
|
selectedItemPath,
|
|
1429
1648
|
media,
|
|
@@ -1432,8 +1651,8 @@ var renameMediaItemAndDescendantPaths = ({
|
|
|
1432
1651
|
const mediaClone = { ...media };
|
|
1433
1652
|
const selectedItem = mediaClone[selectedItemPath];
|
|
1434
1653
|
if (!selectedItem) return mediaClone;
|
|
1435
|
-
const parentPath =
|
|
1436
|
-
const newItemPath =
|
|
1654
|
+
const parentPath = import_imfs3.path.dirname(selectedItemPath);
|
|
1655
|
+
const newItemPath = import_imfs3.path.join(parentPath, newName);
|
|
1437
1656
|
const descendants = tree.flat(selectedItem).map((item) => tree.idToPathMap.get(item.id));
|
|
1438
1657
|
for (const descendantPath of descendants) {
|
|
1439
1658
|
if (!descendantPath) continue;
|
|
@@ -1454,7 +1673,7 @@ var extensionToContentType = {
|
|
|
1454
1673
|
jpeg: "image/jpeg"
|
|
1455
1674
|
};
|
|
1456
1675
|
function encodeFileContentForThumbnail(pathProp, item) {
|
|
1457
|
-
const extension =
|
|
1676
|
+
const extension = import_imfs4.path.extname(pathProp).slice(1);
|
|
1458
1677
|
const contentType = extensionToContentType[extension];
|
|
1459
1678
|
if (contentType) {
|
|
1460
1679
|
if (item.encoding === "base64") {
|
|
@@ -1481,7 +1700,8 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
|
|
|
1481
1700
|
item,
|
|
1482
1701
|
selected,
|
|
1483
1702
|
size,
|
|
1484
|
-
path: pathProp
|
|
1703
|
+
path: pathProp,
|
|
1704
|
+
renderThumbnailIcon
|
|
1485
1705
|
}) => {
|
|
1486
1706
|
const asset = (0, import_noya_multiplayer_react.useAsset)(item.kind === "asset" ? item.assetId : void 0);
|
|
1487
1707
|
const isRoot = item.id === rootMediaItem.id;
|
|
@@ -1489,9 +1709,13 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
|
|
|
1489
1709
|
const isFile = item.kind === "file";
|
|
1490
1710
|
let contentType;
|
|
1491
1711
|
let url;
|
|
1712
|
+
let width;
|
|
1713
|
+
let height;
|
|
1492
1714
|
if (asset) {
|
|
1493
1715
|
contentType = asset.contentType;
|
|
1494
1716
|
url = asset.url;
|
|
1717
|
+
width = asset.width ?? void 0;
|
|
1718
|
+
height = asset.height ?? void 0;
|
|
1495
1719
|
} else if (isFile && pathProp) {
|
|
1496
1720
|
const encoded = encodeFileContentForThumbnail(pathProp, item);
|
|
1497
1721
|
if (encoded) {
|
|
@@ -1499,7 +1723,8 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
|
|
|
1499
1723
|
url = encoded.url;
|
|
1500
1724
|
}
|
|
1501
1725
|
}
|
|
1502
|
-
const fileName = pathProp ?
|
|
1726
|
+
const fileName = pathProp ? import_imfs4.path.basename(pathProp) : void 0;
|
|
1727
|
+
const dimensions = width && height ? { width, height } : void 0;
|
|
1503
1728
|
return /* @__PURE__ */ import_react2.default.createElement(
|
|
1504
1729
|
import_noya_designsystem.MediaThumbnail,
|
|
1505
1730
|
{
|
|
@@ -1508,7 +1733,9 @@ var MediaThumbnailInternal = (0, import_react_utils.memoGeneric)(
|
|
|
1508
1733
|
url,
|
|
1509
1734
|
selected,
|
|
1510
1735
|
size,
|
|
1511
|
-
fileName
|
|
1736
|
+
fileName,
|
|
1737
|
+
renderThumbnailIcon,
|
|
1738
|
+
dimensions
|
|
1512
1739
|
}
|
|
1513
1740
|
);
|
|
1514
1741
|
}
|
|
@@ -1540,7 +1767,10 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1540
1767
|
sortable = false,
|
|
1541
1768
|
renderEmptyState,
|
|
1542
1769
|
sharedDragProps,
|
|
1543
|
-
onClickItem
|
|
1770
|
+
onClickItem,
|
|
1771
|
+
renderThumbnailIcon,
|
|
1772
|
+
onDidDeleteItems,
|
|
1773
|
+
onAssetsUploaded
|
|
1544
1774
|
}, ref) {
|
|
1545
1775
|
const setMedia = (0, import_react.useCallback)(
|
|
1546
1776
|
(...args) => {
|
|
@@ -1581,7 +1811,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1581
1811
|
const assets = (0, import_noya_multiplayer_react.useAssets)();
|
|
1582
1812
|
const [expandedMap, setExpandedMap] = (0, import_react.useState)({});
|
|
1583
1813
|
const visibleItems = (0, import_react.useMemo)(
|
|
1584
|
-
() =>
|
|
1814
|
+
() => mediaGetVisibleItems({
|
|
1585
1815
|
expandedMap,
|
|
1586
1816
|
fileKindFilter,
|
|
1587
1817
|
rootItemId,
|
|
@@ -1599,7 +1829,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1599
1829
|
]
|
|
1600
1830
|
);
|
|
1601
1831
|
const depthMap = (0, import_react.useMemo)(
|
|
1602
|
-
() =>
|
|
1832
|
+
() => mediaGetDepthMap(rootMediaItem, treeWithTempItem, showAllDescendants),
|
|
1603
1833
|
[treeWithTempItem, showAllDescendants]
|
|
1604
1834
|
);
|
|
1605
1835
|
const collectionRef = (0, import_react.useRef)(null);
|
|
@@ -1622,7 +1852,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1622
1852
|
const itemPath = tree.idToPathMap.get(item.id);
|
|
1623
1853
|
const firstSelectedPath = tree.idToPathMap.get(selectedIds[0]);
|
|
1624
1854
|
if (!itemPath || !firstSelectedPath) return false;
|
|
1625
|
-
return itemPath.startsWith(
|
|
1855
|
+
return itemPath.startsWith(import_imfs4.path.dirname(firstSelectedPath));
|
|
1626
1856
|
});
|
|
1627
1857
|
(0, import_react.useEffect)(() => {
|
|
1628
1858
|
if (initialExpanded) {
|
|
@@ -1638,17 +1868,39 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1638
1868
|
},
|
|
1639
1869
|
[expandedMap, expandable]
|
|
1640
1870
|
);
|
|
1871
|
+
const openConfirmationDialog = (0, import_noya_designsystem.useOpenConfirmationDialog)();
|
|
1641
1872
|
const handleDelete = (0, import_react.useCallback)(
|
|
1642
|
-
(selectedIds2) => {
|
|
1643
|
-
const
|
|
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;
|
|
1879
|
+
const deletedItems = Object.entries(media).flatMap(
|
|
1880
|
+
([path7, item]) => {
|
|
1881
|
+
if (selectedIds2.includes(item.id)) {
|
|
1882
|
+
return [[path7, item]];
|
|
1883
|
+
}
|
|
1884
|
+
return [];
|
|
1885
|
+
}
|
|
1886
|
+
);
|
|
1887
|
+
const newMedia = mediaDeleteMediaItems({
|
|
1644
1888
|
selectedIds: selectedIds2,
|
|
1645
1889
|
media,
|
|
1646
1890
|
tree
|
|
1647
1891
|
});
|
|
1648
1892
|
setSelectedIds([rootMediaItem.id]);
|
|
1649
1893
|
setMedia({ name: "Delete items", timestamp: Date.now() }, newMedia);
|
|
1894
|
+
onDidDeleteItems?.(deletedItems);
|
|
1650
1895
|
},
|
|
1651
|
-
[
|
|
1896
|
+
[
|
|
1897
|
+
media,
|
|
1898
|
+
setMedia,
|
|
1899
|
+
setSelectedIds,
|
|
1900
|
+
tree,
|
|
1901
|
+
onDidDeleteItems,
|
|
1902
|
+
openConfirmationDialog
|
|
1903
|
+
]
|
|
1652
1904
|
);
|
|
1653
1905
|
const onRename = (0, import_react.useCallback)(
|
|
1654
1906
|
(selectedItem, newName) => {
|
|
@@ -1657,7 +1909,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1657
1909
|
selectedItem.id
|
|
1658
1910
|
);
|
|
1659
1911
|
if (!selectedItemPath) return;
|
|
1660
|
-
const renameIsValid =
|
|
1912
|
+
const renameIsValid = mediaValidateMediaItemRename({
|
|
1661
1913
|
basename: newName,
|
|
1662
1914
|
selectedItemPath,
|
|
1663
1915
|
media: temp.media
|
|
@@ -1666,7 +1918,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1666
1918
|
setTempItem(void 0);
|
|
1667
1919
|
return;
|
|
1668
1920
|
}
|
|
1669
|
-
const mediaWithRenamedDescendantPaths =
|
|
1921
|
+
const mediaWithRenamedDescendantPaths = mediaRenameMediaItemAndDescendantPaths({
|
|
1670
1922
|
newName,
|
|
1671
1923
|
selectedItemPath,
|
|
1672
1924
|
media: temp.media,
|
|
@@ -1686,7 +1938,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1686
1938
|
const currentFolderPath = tree.idToPathMap.get(currentFolderId);
|
|
1687
1939
|
if (!currentFolderPath) return;
|
|
1688
1940
|
setTempItem([
|
|
1689
|
-
|
|
1941
|
+
import_imfs4.path.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
|
|
1690
1942
|
newFolder
|
|
1691
1943
|
]);
|
|
1692
1944
|
setTimeout(() => {
|
|
@@ -1706,7 +1958,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1706
1958
|
);
|
|
1707
1959
|
if (!currentFolderPath) return;
|
|
1708
1960
|
setTempItem([
|
|
1709
|
-
|
|
1961
|
+
import_imfs4.path.join(currentFolderPath, PLACEHOLDER_ITEM_NAME),
|
|
1710
1962
|
newFile
|
|
1711
1963
|
]);
|
|
1712
1964
|
setTimeout(() => {
|
|
@@ -1717,7 +1969,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1717
1969
|
);
|
|
1718
1970
|
const handleMoveUpAFolder = (0, import_react.useCallback)(
|
|
1719
1971
|
(selectedIds2) => {
|
|
1720
|
-
const newMedia =
|
|
1972
|
+
const newMedia = mediaMoveUpAFolder({
|
|
1721
1973
|
tree,
|
|
1722
1974
|
media,
|
|
1723
1975
|
selectedIds: selectedIds2
|
|
@@ -1737,30 +1989,35 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1737
1989
|
if (!parentPath) return;
|
|
1738
1990
|
const uploadPromises = files.map(async (file) => {
|
|
1739
1991
|
const asset = await assetManager.create(file);
|
|
1740
|
-
const assetPath =
|
|
1992
|
+
const assetPath = import_imfs4.path.join(parentPath, import_imfs4.path.basename(file.name));
|
|
1741
1993
|
return {
|
|
1742
1994
|
assetPath,
|
|
1743
1995
|
asset: createMediaAsset({ assetId: asset.id })
|
|
1744
1996
|
};
|
|
1745
1997
|
});
|
|
1746
1998
|
setIsUploading(true);
|
|
1747
|
-
const
|
|
1999
|
+
const uploadedAssets = await Promise.all(uploadPromises);
|
|
2000
|
+
const newMediaMap = Object.fromEntries(
|
|
2001
|
+
uploadedAssets.map(({ assetPath, asset }) => [assetPath, asset])
|
|
2002
|
+
);
|
|
1748
2003
|
setMedia(
|
|
1749
2004
|
{ name: "Add media items", timestamp: Date.now() },
|
|
1750
2005
|
{
|
|
1751
2006
|
...media,
|
|
1752
|
-
...
|
|
1753
|
-
newMediaMap.map(({ assetPath, asset }) => [assetPath, asset])
|
|
1754
|
-
)
|
|
2007
|
+
...newMediaMap
|
|
1755
2008
|
}
|
|
1756
2009
|
);
|
|
2010
|
+
onAssetsUploaded?.(newMediaMap);
|
|
1757
2011
|
} catch (error) {
|
|
1758
|
-
|
|
2012
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2013
|
+
} else {
|
|
2014
|
+
console.error("Failed to upload files:", error);
|
|
2015
|
+
}
|
|
1759
2016
|
} finally {
|
|
1760
2017
|
setIsUploading(false);
|
|
1761
2018
|
}
|
|
1762
2019
|
},
|
|
1763
|
-
[tree.idToPathMap, setMedia, media, assetManager]
|
|
2020
|
+
[tree.idToPathMap, setMedia, media, assetManager, onAssetsUploaded]
|
|
1764
2021
|
);
|
|
1765
2022
|
const handleDownload = (0, import_react.useCallback)(
|
|
1766
2023
|
async (selectedItems) => {
|
|
@@ -1804,7 +2061,10 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1804
2061
|
}
|
|
1805
2062
|
);
|
|
1806
2063
|
} catch (error) {
|
|
1807
|
-
|
|
2064
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2065
|
+
} else {
|
|
2066
|
+
console.error("Failed to upload files:", error);
|
|
2067
|
+
}
|
|
1808
2068
|
}
|
|
1809
2069
|
},
|
|
1810
2070
|
[media, setMedia, assetManager, tree]
|
|
@@ -1817,10 +2077,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1817
2077
|
);
|
|
1818
2078
|
const handleMoveMediaInsideFolder = (0, import_react.useCallback)(
|
|
1819
2079
|
(sourceItem, targetItem) => {
|
|
1820
|
-
const
|
|
1821
|
-
const targetItemPath = tree.idToPathMap.get(targetItem.id);
|
|
1822
|
-
if (!sourceItemPath || !targetItemPath) return;
|
|
1823
|
-
const newMedia = moveMediaInsideFolder({
|
|
2080
|
+
const newMedia = mediaMoveMediaInsideFolder({
|
|
1824
2081
|
sourceItemIds: [sourceItem.id],
|
|
1825
2082
|
targetItemId: targetItem.id,
|
|
1826
2083
|
media,
|
|
@@ -1857,12 +2114,12 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1857
2114
|
],
|
|
1858
2115
|
[
|
|
1859
2116
|
onlySingleFolderSelected && {
|
|
1860
|
-
title: "
|
|
2117
|
+
title: "Upload Files",
|
|
1861
2118
|
value: "upload",
|
|
1862
2119
|
icon: /* @__PURE__ */ import_react2.default.createElement(import_noya_icons.UploadIcon, null)
|
|
1863
2120
|
},
|
|
1864
2121
|
onlySingleFolderSelected && {
|
|
1865
|
-
title: "Add
|
|
2122
|
+
title: "Add Folder",
|
|
1866
2123
|
value: "addFolder",
|
|
1867
2124
|
icon: /* @__PURE__ */ import_react2.default.createElement(import_noya_icons.FolderIcon, null)
|
|
1868
2125
|
},
|
|
@@ -1939,7 +2196,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1939
2196
|
const handleSetExpanded = (0, import_react.useCallback)(
|
|
1940
2197
|
(item, expanded) => {
|
|
1941
2198
|
setExpandedMap(
|
|
1942
|
-
(prev) =>
|
|
2199
|
+
(prev) => mediaUpdateExpandedMap({
|
|
1943
2200
|
item,
|
|
1944
2201
|
expanded,
|
|
1945
2202
|
expandable,
|
|
@@ -1986,7 +2243,8 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
1986
2243
|
moveUpAFolder: handleMoveUpAFolder,
|
|
1987
2244
|
replace: handleReplace,
|
|
1988
2245
|
preview: handlePreview,
|
|
1989
|
-
moveMediaInsideFolder: handleMoveMediaInsideFolder
|
|
2246
|
+
moveMediaInsideFolder: handleMoveMediaInsideFolder,
|
|
2247
|
+
getItemAtIndex: (index) => visibleItems[index]
|
|
1990
2248
|
}));
|
|
1991
2249
|
return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(
|
|
1992
2250
|
import_noya_designsystem.FileExplorerLayout,
|
|
@@ -2028,6 +2286,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
2028
2286
|
return "Enter folder name";
|
|
2029
2287
|
case "asset":
|
|
2030
2288
|
case "file":
|
|
2289
|
+
case "noyaFile":
|
|
2031
2290
|
return "Enter file name";
|
|
2032
2291
|
}
|
|
2033
2292
|
},
|
|
@@ -2050,7 +2309,8 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
2050
2309
|
MediaThumbnailInternal,
|
|
2051
2310
|
{
|
|
2052
2311
|
...props,
|
|
2053
|
-
path: tree.idToPathMap.get(props.item.id)
|
|
2312
|
+
path: tree.idToPathMap.get(props.item.id),
|
|
2313
|
+
renderThumbnailIcon
|
|
2054
2314
|
}
|
|
2055
2315
|
),
|
|
2056
2316
|
renderAction,
|
|
@@ -2058,7 +2318,7 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
2058
2318
|
if (file.kind !== "asset") return null;
|
|
2059
2319
|
const asset = assets.find((a) => a.id === file.assetId);
|
|
2060
2320
|
if (!asset) return null;
|
|
2061
|
-
return /* @__PURE__ */ import_react2.default.createElement(import_noya_designsystem.FileExplorerDetail, { selected, size }, formatByteSize(asset.size));
|
|
2321
|
+
return /* @__PURE__ */ import_react2.default.createElement(import_noya_designsystem.FileExplorerDetail, { selected, size }, (0, import_noya_designsystem.formatByteSize)(asset.size));
|
|
2062
2322
|
},
|
|
2063
2323
|
renderEmptyState: () => renderEmptyState?.() ?? /* @__PURE__ */ import_react2.default.createElement(import_noya_designsystem.FileExplorerEmptyState, null),
|
|
2064
2324
|
itemRoleDescription: "clickable file item",
|
|
@@ -2079,93 +2339,1034 @@ var MediaCollection = (0, import_react.memo)(
|
|
|
2079
2339
|
if (sourceListId !== targetListId) {
|
|
2080
2340
|
return false;
|
|
2081
2341
|
}
|
|
2342
|
+
if (sourceListId !== sortableId || targetListId !== sortableId) {
|
|
2343
|
+
return false;
|
|
2344
|
+
}
|
|
2082
2345
|
const sourceItem = visibleItems[sourceIndex];
|
|
2083
2346
|
const targetItem = visibleItems[targetIndex];
|
|
2084
|
-
|
|
2085
|
-
|
|
2347
|
+
return acceptsMediaItemDrop({
|
|
2348
|
+
position,
|
|
2349
|
+
sourceItem,
|
|
2350
|
+
targetItem,
|
|
2351
|
+
tree
|
|
2352
|
+
});
|
|
2353
|
+
},
|
|
2354
|
+
onMoveItem: ({
|
|
2355
|
+
sourceListId,
|
|
2356
|
+
sourceIndex,
|
|
2357
|
+
targetListId,
|
|
2358
|
+
targetIndex,
|
|
2359
|
+
position
|
|
2360
|
+
}) => {
|
|
2361
|
+
if (sourceListId !== sortableId || targetListId !== sortableId) {
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
const sourceItem = visibleItems[sourceIndex];
|
|
2365
|
+
const targetItem = visibleItems[targetIndex];
|
|
2366
|
+
if (position === "inside") {
|
|
2367
|
+
handleMoveMediaInsideFolder(sourceItem, targetItem);
|
|
2086
2368
|
}
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
)
|
|
2372
|
+
));
|
|
2373
|
+
})
|
|
2374
|
+
);
|
|
2375
|
+
function acceptsMediaItemDrop(parameters) {
|
|
2376
|
+
const { position, sourceItem, targetItem, tree } = parameters;
|
|
2377
|
+
if (position !== "inside" || targetItem.kind === "asset") {
|
|
2378
|
+
return false;
|
|
2379
|
+
}
|
|
2380
|
+
const sourcePath = tree.findPath(
|
|
2381
|
+
rootMediaItem,
|
|
2382
|
+
(item) => item.id === sourceItem.id
|
|
2383
|
+
);
|
|
2384
|
+
const targetPath = tree.findPath(
|
|
2385
|
+
rootMediaItem,
|
|
2386
|
+
(item) => item.id === targetItem.id
|
|
2387
|
+
);
|
|
2388
|
+
if (!sourcePath || !targetPath) return false;
|
|
2389
|
+
if ((0, import_noya_utils2.isDeepEqual)(sourcePath, targetPath.slice(0, sourcePath.length))) {
|
|
2390
|
+
return false;
|
|
2391
|
+
}
|
|
2392
|
+
return true;
|
|
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))
|
|
2090
2448
|
);
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
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])
|
|
2094
2846
|
);
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
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);
|
|
2098
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;
|
|
2099
3151
|
return true;
|
|
2100
3152
|
},
|
|
2101
|
-
|
|
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
|
+
}
|
|
2102
3235
|
const sourceItem = visibleItems[sourceIndex];
|
|
2103
3236
|
const targetItem = visibleItems[targetIndex];
|
|
2104
|
-
|
|
2105
|
-
|
|
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;
|
|
2106
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);
|
|
2107
3261
|
},
|
|
2108
3262
|
onFilesDrop: async (event) => {
|
|
2109
3263
|
event.preventDefault();
|
|
2110
|
-
const
|
|
2111
|
-
if (
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
const rootItemPath = tree.idToPathMap.get(rootItemId);
|
|
2124
|
-
if (!rootItemPath) return;
|
|
2125
|
-
setMedia(
|
|
2126
|
-
{ name: "Add media files", timestamp: Date.now() },
|
|
2127
|
-
{
|
|
2128
|
-
...media,
|
|
2129
|
-
...Object.fromEntries(
|
|
2130
|
-
newMediaItems.map((item) => [
|
|
2131
|
-
import_imfs3.path.join(rootItemPath, item.name),
|
|
2132
|
-
item.asset
|
|
2133
|
-
])
|
|
2134
|
-
)
|
|
2135
|
-
}
|
|
2136
|
-
);
|
|
2137
|
-
} catch (error) {
|
|
2138
|
-
console.error("Failed to upload dropped files:", error);
|
|
2139
|
-
}
|
|
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
|
+
);
|
|
2140
3277
|
}
|
|
2141
3278
|
}
|
|
2142
|
-
)
|
|
2143
|
-
|
|
2144
|
-
|
|
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
|
+
)
|
|
2145
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
|
+
}
|
|
2146
3333
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2147
3334
|
0 && (module.exports = {
|
|
2148
3335
|
MediaCollection,
|
|
2149
3336
|
PLACEHOLDER_ITEM_NAME,
|
|
3337
|
+
ResourceExplorer,
|
|
3338
|
+
ResourceThumbnail,
|
|
3339
|
+
acceptsMediaItemDrop,
|
|
3340
|
+
acceptsResourceDrop,
|
|
2150
3341
|
basenameValidator,
|
|
2151
3342
|
createMediaAsset,
|
|
2152
3343
|
createMediaFile,
|
|
2153
3344
|
createMediaFolder,
|
|
2154
3345
|
createMediaItem,
|
|
2155
3346
|
createMediaItemTree,
|
|
2156
|
-
|
|
2157
|
-
formatByteSize,
|
|
3347
|
+
deleteResources,
|
|
2158
3348
|
getDepthMap,
|
|
2159
3349
|
getParentDirectories,
|
|
2160
3350
|
getVisibleItems,
|
|
3351
|
+
gridThumbnailDimension,
|
|
3352
|
+
mediaDeleteMediaItems,
|
|
3353
|
+
mediaGetDepthMap,
|
|
3354
|
+
mediaGetParentDirectories,
|
|
3355
|
+
mediaGetVisibleItems,
|
|
3356
|
+
mediaMoveMediaInsideFolder,
|
|
3357
|
+
mediaMovePathsIntoTarget,
|
|
3358
|
+
mediaMoveUpAFolder,
|
|
3359
|
+
mediaRenameMediaItemAndDescendantPaths,
|
|
3360
|
+
mediaUpdateExpandedMap,
|
|
3361
|
+
mediaValidateMediaItemRename,
|
|
2161
3362
|
moveMediaInsideFolder,
|
|
2162
3363
|
movePathsIntoTarget,
|
|
2163
3364
|
moveUpAFolder,
|
|
2164
|
-
|
|
3365
|
+
renameResourceAndDescendantPaths,
|
|
2165
3366
|
rootMediaItem,
|
|
2166
3367
|
rootMediaItemName,
|
|
2167
3368
|
rootMediaItemPath,
|
|
2168
3369
|
updateExpandedMap,
|
|
2169
|
-
|
|
3370
|
+
validateResourceRename
|
|
2170
3371
|
});
|
|
2171
3372
|
//# sourceMappingURL=index.js.map
|