rita-workspace 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +36 -3
- package/dist/index.d.ts +36 -3
- package/dist/index.js +614 -184
- package/dist/index.mjs +608 -184
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,16 +41,22 @@ __export(index_exports, {
|
|
|
41
41
|
addDrawingToWorkspace: () => addDrawingToWorkspace,
|
|
42
42
|
closeDB: () => closeDB,
|
|
43
43
|
createDrawing: () => createDrawing,
|
|
44
|
+
createFolder: () => createFolder,
|
|
44
45
|
deleteDrawing: () => deleteDrawing,
|
|
46
|
+
deleteFolder: () => deleteFolder,
|
|
45
47
|
duplicateDrawing: () => duplicateDrawing,
|
|
46
48
|
getAllDrawings: () => getAllDrawings,
|
|
49
|
+
getAllFolders: () => getAllFolders,
|
|
47
50
|
getDB: () => getDB,
|
|
48
51
|
getDrawing: () => getDrawing,
|
|
52
|
+
getFolder: () => getFolder,
|
|
49
53
|
getOrCreateDefaultWorkspace: () => getOrCreateDefaultWorkspace,
|
|
50
54
|
getTranslations: () => getTranslations,
|
|
51
55
|
getWorkspace: () => getWorkspace,
|
|
52
56
|
isLanguageSupported: () => isLanguageSupported,
|
|
57
|
+
moveDrawingToFolder: () => moveDrawingToFolder,
|
|
53
58
|
removeDrawingFromWorkspace: () => removeDrawingFromWorkspace,
|
|
59
|
+
renameFolder: () => renameFolder,
|
|
54
60
|
setActiveDrawing: () => setActiveDrawing,
|
|
55
61
|
updateDrawing: () => updateDrawing,
|
|
56
62
|
updateWorkspace: () => updateWorkspace,
|
|
@@ -63,12 +69,12 @@ module.exports = __toCommonJS(index_exports);
|
|
|
63
69
|
// src/storage/db.ts
|
|
64
70
|
var import_idb = require("idb");
|
|
65
71
|
var DB_NAME = "rita-workspace";
|
|
66
|
-
var DB_VERSION =
|
|
72
|
+
var DB_VERSION = 2;
|
|
67
73
|
var dbInstance = null;
|
|
68
74
|
async function getDB() {
|
|
69
75
|
if (dbInstance) return dbInstance;
|
|
70
76
|
dbInstance = await (0, import_idb.openDB)(DB_NAME, DB_VERSION, {
|
|
71
|
-
upgrade(db) {
|
|
77
|
+
upgrade(db, oldVersion) {
|
|
72
78
|
if (!db.objectStoreNames.contains("workspaces")) {
|
|
73
79
|
const workspaceStore = db.createObjectStore("workspaces", { keyPath: "id" });
|
|
74
80
|
workspaceStore.createIndex("by-updated", "updatedAt");
|
|
@@ -77,6 +83,10 @@ async function getDB() {
|
|
|
77
83
|
const drawingStore = db.createObjectStore("drawings", { keyPath: "id" });
|
|
78
84
|
drawingStore.createIndex("by-updated", "updatedAt");
|
|
79
85
|
}
|
|
86
|
+
if (oldVersion < 2) {
|
|
87
|
+
const folderStore = db.createObjectStore("folders", { keyPath: "id" });
|
|
88
|
+
folderStore.createIndex("by-name", "name");
|
|
89
|
+
}
|
|
80
90
|
}
|
|
81
91
|
});
|
|
82
92
|
return dbInstance;
|
|
@@ -90,12 +100,13 @@ async function closeDB() {
|
|
|
90
100
|
|
|
91
101
|
// src/storage/drawingStore.ts
|
|
92
102
|
var import_nanoid = require("nanoid");
|
|
93
|
-
async function createDrawing(name = "Untitled", elements = [], appState = {}) {
|
|
103
|
+
async function createDrawing(name = "Untitled", elements = [], appState = {}, folderId) {
|
|
94
104
|
const db = await getDB();
|
|
95
105
|
const now = Date.now();
|
|
96
106
|
const drawing = {
|
|
97
107
|
id: (0, import_nanoid.nanoid)(),
|
|
98
108
|
name,
|
|
109
|
+
folderId: folderId || null,
|
|
99
110
|
elements,
|
|
100
111
|
appState,
|
|
101
112
|
files: {},
|
|
@@ -138,9 +149,62 @@ async function duplicateDrawing(id, newName) {
|
|
|
138
149
|
return createDrawing(
|
|
139
150
|
newName || `${existing.name} (copy)`,
|
|
140
151
|
existing.elements,
|
|
141
|
-
existing.appState
|
|
152
|
+
existing.appState,
|
|
153
|
+
existing.folderId
|
|
142
154
|
);
|
|
143
155
|
}
|
|
156
|
+
async function moveDrawingToFolder(drawingId, folderId) {
|
|
157
|
+
return updateDrawing(drawingId, { folderId });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/storage/folderStore.ts
|
|
161
|
+
var import_nanoid2 = require("nanoid");
|
|
162
|
+
async function createFolder(name) {
|
|
163
|
+
const db = await getDB();
|
|
164
|
+
const now = Date.now();
|
|
165
|
+
const folder = {
|
|
166
|
+
id: (0, import_nanoid2.nanoid)(),
|
|
167
|
+
name,
|
|
168
|
+
createdAt: now,
|
|
169
|
+
updatedAt: now
|
|
170
|
+
};
|
|
171
|
+
await db.put("folders", folder);
|
|
172
|
+
return folder;
|
|
173
|
+
}
|
|
174
|
+
async function getFolder(id) {
|
|
175
|
+
const db = await getDB();
|
|
176
|
+
return db.get("folders", id);
|
|
177
|
+
}
|
|
178
|
+
async function getAllFolders() {
|
|
179
|
+
const db = await getDB();
|
|
180
|
+
return db.getAllFromIndex("folders", "by-name");
|
|
181
|
+
}
|
|
182
|
+
async function renameFolder(id, name) {
|
|
183
|
+
const db = await getDB();
|
|
184
|
+
const existing = await db.get("folders", id);
|
|
185
|
+
if (!existing) return void 0;
|
|
186
|
+
const updated = {
|
|
187
|
+
...existing,
|
|
188
|
+
name,
|
|
189
|
+
updatedAt: Date.now()
|
|
190
|
+
};
|
|
191
|
+
await db.put("folders", updated);
|
|
192
|
+
return updated;
|
|
193
|
+
}
|
|
194
|
+
async function deleteFolder(id) {
|
|
195
|
+
const db = await getDB();
|
|
196
|
+
const allDrawings = await db.getAll("drawings");
|
|
197
|
+
const tx = db.transaction(["drawings", "folders"], "readwrite");
|
|
198
|
+
for (const drawing of allDrawings) {
|
|
199
|
+
if (drawing.folderId === id) {
|
|
200
|
+
drawing.folderId = null;
|
|
201
|
+
drawing.updatedAt = Date.now();
|
|
202
|
+
await tx.objectStore("drawings").put(drawing);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
await tx.objectStore("folders").delete(id);
|
|
206
|
+
await tx.done;
|
|
207
|
+
}
|
|
144
208
|
|
|
145
209
|
// src/storage/workspaceStore.ts
|
|
146
210
|
var DEFAULT_WORKSPACE_ID = "default";
|
|
@@ -246,6 +310,14 @@ var sv = {
|
|
|
246
310
|
importWorkspace: "Importera arbetsyta",
|
|
247
311
|
exportDrawing: "Spara som .excalidraw",
|
|
248
312
|
importDrawing: "\xD6ppna .excalidraw",
|
|
313
|
+
// Folders
|
|
314
|
+
createFolder: "Skapa mapp",
|
|
315
|
+
renameFolder: "Byt namn p\xE5 mapp",
|
|
316
|
+
deleteFolder: "Ta bort mapp",
|
|
317
|
+
deleteFolderConfirm: "Vill du ta bort denna mapp? Ritningarna flyttas till rotniv\xE5n.",
|
|
318
|
+
moveToFolder: "Flytta till mapp",
|
|
319
|
+
moveToRoot: "Ingen mapp",
|
|
320
|
+
newFolderName: "Ny mapp",
|
|
249
321
|
// Shortcuts
|
|
250
322
|
shortcutNewDrawing: "Ctrl+Alt+N"
|
|
251
323
|
};
|
|
@@ -285,6 +357,14 @@ var en = {
|
|
|
285
357
|
importWorkspace: "Import workspace",
|
|
286
358
|
exportDrawing: "Save as .excalidraw",
|
|
287
359
|
importDrawing: "Open .excalidraw",
|
|
360
|
+
// Folders
|
|
361
|
+
createFolder: "Create folder",
|
|
362
|
+
renameFolder: "Rename folder",
|
|
363
|
+
deleteFolder: "Delete folder",
|
|
364
|
+
deleteFolderConfirm: "Delete this folder? Drawings will be moved to root.",
|
|
365
|
+
moveToFolder: "Move to folder",
|
|
366
|
+
moveToRoot: "No folder",
|
|
367
|
+
newFolderName: "New folder",
|
|
288
368
|
// Shortcuts
|
|
289
369
|
shortcutNewDrawing: "Ctrl+Alt+N"
|
|
290
370
|
};
|
|
@@ -367,6 +447,7 @@ function isDrawingOpenedEarlierInOtherTab(drawingId) {
|
|
|
367
447
|
function WorkspaceProvider({ children, lang = "en" }) {
|
|
368
448
|
const [workspace, setWorkspace] = (0, import_react.useState)(null);
|
|
369
449
|
const [drawings, setDrawings] = (0, import_react.useState)([]);
|
|
450
|
+
const [folders, setFolders] = (0, import_react.useState)([]);
|
|
370
451
|
const [activeDrawing, setActiveDrawing2] = (0, import_react.useState)(null);
|
|
371
452
|
const [isLoading, setIsLoading] = (0, import_react.useState)(true);
|
|
372
453
|
const [error, setError] = (0, import_react.useState)(null);
|
|
@@ -442,6 +523,8 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
442
523
|
const allDrawings = await getAllDrawings();
|
|
443
524
|
const wsDrawings = allDrawings.filter((d) => ws.drawingIds.includes(d.id));
|
|
444
525
|
setDrawings(wsDrawings);
|
|
526
|
+
const allFolders = await getAllFolders();
|
|
527
|
+
setFolders(allFolders);
|
|
445
528
|
const lastDrawingId = sessionStorage.getItem("rita-workspace-tab-drawing");
|
|
446
529
|
let active = null;
|
|
447
530
|
if (lastDrawingId) {
|
|
@@ -474,14 +557,16 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
474
557
|
const allDrawings = await getAllDrawings();
|
|
475
558
|
const wsDrawings = allDrawings.filter((d) => workspace.drawingIds.includes(d.id));
|
|
476
559
|
setDrawings(wsDrawings);
|
|
560
|
+
const allFolders = await getAllFolders();
|
|
561
|
+
setFolders(allFolders);
|
|
477
562
|
} catch (err) {
|
|
478
563
|
}
|
|
479
564
|
}, [workspace]);
|
|
480
|
-
const createNewDrawing = (0, import_react.useCallback)(async (name) => {
|
|
565
|
+
const createNewDrawing = (0, import_react.useCallback)(async (name, folderId) => {
|
|
481
566
|
if (!workspace) return null;
|
|
482
567
|
try {
|
|
483
568
|
const defaultName = `${t.newDrawing} ${drawings.length + 1}`;
|
|
484
|
-
const drawing = await createDrawing(name || defaultName);
|
|
569
|
+
const drawing = await createDrawing(name || defaultName, [], {}, folderId);
|
|
485
570
|
await addDrawingToWorkspace(workspace.id, drawing.id);
|
|
486
571
|
setDrawings((prev) => [...prev, drawing]);
|
|
487
572
|
setActiveDrawing2(drawing);
|
|
@@ -714,9 +799,52 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
714
799
|
setError(err instanceof Error ? err.message : "Failed to import drawing");
|
|
715
800
|
}
|
|
716
801
|
}, [workspace, t]);
|
|
802
|
+
const createFolder2 = (0, import_react.useCallback)(async (name) => {
|
|
803
|
+
try {
|
|
804
|
+
const folder = await createFolder(name);
|
|
805
|
+
setFolders((prev) => [...prev, folder]);
|
|
806
|
+
return folder;
|
|
807
|
+
} catch (err) {
|
|
808
|
+
setError(err instanceof Error ? err.message : "Failed to create folder");
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
}, []);
|
|
812
|
+
const renameFolder2 = (0, import_react.useCallback)(async (id, name) => {
|
|
813
|
+
try {
|
|
814
|
+
const updated = await renameFolder(id, name);
|
|
815
|
+
if (updated) {
|
|
816
|
+
setFolders((prev) => prev.map((f) => f.id === id ? updated : f));
|
|
817
|
+
}
|
|
818
|
+
} catch (err) {
|
|
819
|
+
setError(err instanceof Error ? err.message : "Failed to rename folder");
|
|
820
|
+
}
|
|
821
|
+
}, []);
|
|
822
|
+
const deleteFolder2 = (0, import_react.useCallback)(async (id) => {
|
|
823
|
+
try {
|
|
824
|
+
await deleteFolder(id);
|
|
825
|
+
setFolders((prev) => prev.filter((f) => f.id !== id));
|
|
826
|
+
setDrawings((prev) => prev.map((d) => d.folderId === id ? { ...d, folderId: null } : d));
|
|
827
|
+
} catch (err) {
|
|
828
|
+
setError(err instanceof Error ? err.message : "Failed to delete folder");
|
|
829
|
+
}
|
|
830
|
+
}, []);
|
|
831
|
+
const moveDrawingToFolder2 = (0, import_react.useCallback)(async (drawingId, folderId) => {
|
|
832
|
+
try {
|
|
833
|
+
const updated = await moveDrawingToFolder(drawingId, folderId);
|
|
834
|
+
if (updated) {
|
|
835
|
+
setDrawings((prev) => prev.map((d) => d.id === drawingId ? updated : d));
|
|
836
|
+
if (activeDrawing?.id === drawingId) {
|
|
837
|
+
setActiveDrawing2(updated);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
} catch (err) {
|
|
841
|
+
setError(err instanceof Error ? err.message : "Failed to move drawing");
|
|
842
|
+
}
|
|
843
|
+
}, [activeDrawing]);
|
|
717
844
|
const value = {
|
|
718
845
|
workspace,
|
|
719
846
|
drawings,
|
|
847
|
+
folders,
|
|
720
848
|
activeDrawing,
|
|
721
849
|
isLoading,
|
|
722
850
|
error,
|
|
@@ -728,6 +856,10 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
728
856
|
renameDrawing,
|
|
729
857
|
removeDrawing,
|
|
730
858
|
duplicateCurrentDrawing,
|
|
859
|
+
createFolder: createFolder2,
|
|
860
|
+
renameFolder: renameFolder2,
|
|
861
|
+
deleteFolder: deleteFolder2,
|
|
862
|
+
moveDrawingToFolder: moveDrawingToFolder2,
|
|
731
863
|
saveCurrentDrawing,
|
|
732
864
|
saveDrawingById,
|
|
733
865
|
refreshDrawings,
|
|
@@ -1081,11 +1213,16 @@ var DrawingsDialog = ({
|
|
|
1081
1213
|
}) => {
|
|
1082
1214
|
const {
|
|
1083
1215
|
drawings,
|
|
1216
|
+
folders,
|
|
1084
1217
|
activeDrawing,
|
|
1085
1218
|
switchDrawing,
|
|
1086
1219
|
createNewDrawing,
|
|
1087
1220
|
renameDrawing,
|
|
1088
1221
|
removeDrawing,
|
|
1222
|
+
createFolder: createFolder2,
|
|
1223
|
+
renameFolder: renameFolder2,
|
|
1224
|
+
deleteFolder: deleteFolder2,
|
|
1225
|
+
moveDrawingToFolder: moveDrawingToFolder2,
|
|
1089
1226
|
exportWorkspace,
|
|
1090
1227
|
importWorkspace,
|
|
1091
1228
|
exportDrawingAsExcalidraw,
|
|
@@ -1099,21 +1236,39 @@ var DrawingsDialog = ({
|
|
|
1099
1236
|
const [editingId, setEditingId] = (0, import_react5.useState)(null);
|
|
1100
1237
|
const [editName, setEditName] = (0, import_react5.useState)("");
|
|
1101
1238
|
const [confirmDeleteId, setConfirmDeleteId] = (0, import_react5.useState)(null);
|
|
1239
|
+
const [switchingId, setSwitchingId] = (0, import_react5.useState)(null);
|
|
1240
|
+
const [expandedFolders, setExpandedFolders] = (0, import_react5.useState)(/* @__PURE__ */ new Set());
|
|
1241
|
+
const [creatingFolder, setCreatingFolder] = (0, import_react5.useState)(false);
|
|
1242
|
+
const [newFolderName, setNewFolderName] = (0, import_react5.useState)("");
|
|
1243
|
+
const [editingFolderId, setEditingFolderId] = (0, import_react5.useState)(null);
|
|
1244
|
+
const [editFolderName, setEditFolderName] = (0, import_react5.useState)("");
|
|
1245
|
+
const [confirmDeleteFolderId, setConfirmDeleteFolderId] = (0, import_react5.useState)(null);
|
|
1246
|
+
const [movingDrawingId, setMovingDrawingId] = (0, import_react5.useState)(null);
|
|
1247
|
+
const [searchQuery, setSearchQuery] = (0, import_react5.useState)("");
|
|
1102
1248
|
const [position, setPosition] = (0, import_react5.useState)(null);
|
|
1103
1249
|
const dragRef = (0, import_react5.useRef)(null);
|
|
1104
1250
|
const dialogRef = (0, import_react5.useRef)(null);
|
|
1251
|
+
const newFolderInputRef = (0, import_react5.useRef)(null);
|
|
1105
1252
|
const prevOpenRef = (0, import_react5.useRef)(false);
|
|
1106
1253
|
(0, import_react5.useEffect)(() => {
|
|
1107
1254
|
if (open) {
|
|
1108
1255
|
refreshDrawings();
|
|
1109
1256
|
if (!prevOpenRef.current) {
|
|
1110
1257
|
setPosition(null);
|
|
1258
|
+
setSearchQuery("");
|
|
1259
|
+
setExpandedFolders(new Set(folders.map((f) => f.id)));
|
|
1111
1260
|
}
|
|
1112
1261
|
}
|
|
1113
1262
|
prevOpenRef.current = open;
|
|
1114
|
-
}, [open, refreshDrawings]);
|
|
1263
|
+
}, [open, refreshDrawings, folders]);
|
|
1264
|
+
(0, import_react5.useEffect)(() => {
|
|
1265
|
+
if (creatingFolder && newFolderInputRef.current) {
|
|
1266
|
+
newFolderInputRef.current.focus();
|
|
1267
|
+
}
|
|
1268
|
+
}, [creatingFolder]);
|
|
1115
1269
|
const handleMouseDown = (0, import_react5.useCallback)((e) => {
|
|
1116
1270
|
if (e.target.closest("button")) return;
|
|
1271
|
+
if (e.target.closest("input")) return;
|
|
1117
1272
|
if (!dialogRef.current) return;
|
|
1118
1273
|
const rect = dialogRef.current.getBoundingClientRect();
|
|
1119
1274
|
const currentX = position?.x ?? rect.left;
|
|
@@ -1134,11 +1289,13 @@ var DrawingsDialog = ({
|
|
|
1134
1289
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1135
1290
|
}, [position]);
|
|
1136
1291
|
const handleSelect = (0, import_react5.useCallback)(async (drawing) => {
|
|
1292
|
+
setSwitchingId(drawing.id);
|
|
1137
1293
|
await switchDrawing(drawing.id);
|
|
1138
1294
|
onDrawingSelect?.(drawing);
|
|
1295
|
+
setSwitchingId(null);
|
|
1139
1296
|
}, [switchDrawing, onDrawingSelect]);
|
|
1140
|
-
const handleCreate = (0, import_react5.useCallback)(async () => {
|
|
1141
|
-
const newDrawing = await createNewDrawing();
|
|
1297
|
+
const handleCreate = (0, import_react5.useCallback)(async (folderId) => {
|
|
1298
|
+
const newDrawing = await createNewDrawing(void 0, folderId);
|
|
1142
1299
|
if (newDrawing) onDrawingSelect?.(newDrawing);
|
|
1143
1300
|
}, [createNewDrawing, onDrawingSelect]);
|
|
1144
1301
|
const handleStartEdit = (0, import_react5.useCallback)((drawing) => {
|
|
@@ -1160,6 +1317,42 @@ var DrawingsDialog = ({
|
|
|
1160
1317
|
await removeDrawing(id);
|
|
1161
1318
|
setConfirmDeleteId(null);
|
|
1162
1319
|
}, [removeDrawing]);
|
|
1320
|
+
const handleCreateFolder = (0, import_react5.useCallback)(async () => {
|
|
1321
|
+
if (newFolderName.trim()) {
|
|
1322
|
+
const folder = await createFolder2(newFolderName.trim());
|
|
1323
|
+
if (folder) {
|
|
1324
|
+
setExpandedFolders((prev) => /* @__PURE__ */ new Set([...prev, folder.id]));
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
setCreatingFolder(false);
|
|
1328
|
+
setNewFolderName("");
|
|
1329
|
+
}, [newFolderName, createFolder2]);
|
|
1330
|
+
const handleSaveFolderEdit = (0, import_react5.useCallback)(async () => {
|
|
1331
|
+
if (editingFolderId && editFolderName.trim()) {
|
|
1332
|
+
await renameFolder2(editingFolderId, editFolderName.trim());
|
|
1333
|
+
}
|
|
1334
|
+
setEditingFolderId(null);
|
|
1335
|
+
setEditFolderName("");
|
|
1336
|
+
}, [editingFolderId, editFolderName, renameFolder2]);
|
|
1337
|
+
const handleDeleteFolder = (0, import_react5.useCallback)(async (id) => {
|
|
1338
|
+
await deleteFolder2(id);
|
|
1339
|
+
setConfirmDeleteFolderId(null);
|
|
1340
|
+
}, [deleteFolder2]);
|
|
1341
|
+
const handleMoveToFolder = (0, import_react5.useCallback)(async (drawingId, folderId) => {
|
|
1342
|
+
await moveDrawingToFolder2(drawingId, folderId);
|
|
1343
|
+
setMovingDrawingId(null);
|
|
1344
|
+
}, [moveDrawingToFolder2]);
|
|
1345
|
+
const toggleFolder = (0, import_react5.useCallback)((folderId) => {
|
|
1346
|
+
setExpandedFolders((prev) => {
|
|
1347
|
+
const next = new Set(prev);
|
|
1348
|
+
if (next.has(folderId)) {
|
|
1349
|
+
next.delete(folderId);
|
|
1350
|
+
} else {
|
|
1351
|
+
next.add(folderId);
|
|
1352
|
+
}
|
|
1353
|
+
return next;
|
|
1354
|
+
});
|
|
1355
|
+
}, []);
|
|
1163
1356
|
const getLocale = () => {
|
|
1164
1357
|
if (!effectiveLang) return "en-US";
|
|
1165
1358
|
const baseLang = effectiveLang.split("-")[0].toLowerCase();
|
|
@@ -1174,6 +1367,14 @@ var DrawingsDialog = ({
|
|
|
1174
1367
|
});
|
|
1175
1368
|
};
|
|
1176
1369
|
if (!open) return null;
|
|
1370
|
+
const query = searchQuery.toLowerCase().trim();
|
|
1371
|
+
const filteredDrawings = query ? drawings.filter((d) => d.name.toLowerCase().includes(query)) : drawings;
|
|
1372
|
+
const rootDrawings = filteredDrawings.filter((d) => !d.folderId);
|
|
1373
|
+
const drawingsByFolder = {};
|
|
1374
|
+
for (const folder of folders) {
|
|
1375
|
+
drawingsByFolder[folder.id] = filteredDrawings.filter((d) => d.folderId === folder.id);
|
|
1376
|
+
}
|
|
1377
|
+
const filteredFolders = query ? folders.filter((f) => f.name.toLowerCase().includes(query) || (drawingsByFolder[f.id] || []).length > 0) : folders;
|
|
1177
1378
|
const dialogStyle = position ? {
|
|
1178
1379
|
position: "fixed",
|
|
1179
1380
|
left: position.x,
|
|
@@ -1207,6 +1408,324 @@ var DrawingsDialog = ({
|
|
|
1207
1408
|
color: "var(--text-secondary-color, #888)",
|
|
1208
1409
|
padding: "16px 20px 8px"
|
|
1209
1410
|
};
|
|
1411
|
+
const renderDrawingRow = (drawing) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1412
|
+
"div",
|
|
1413
|
+
{
|
|
1414
|
+
onClick: () => {
|
|
1415
|
+
if (editingId || confirmDeleteId || switchingId || movingDrawingId) return;
|
|
1416
|
+
if (activeDrawing?.id !== drawing.id) handleSelect(drawing);
|
|
1417
|
+
},
|
|
1418
|
+
style: {
|
|
1419
|
+
padding: "10px 12px",
|
|
1420
|
+
display: "flex",
|
|
1421
|
+
alignItems: "center",
|
|
1422
|
+
gap: "12px",
|
|
1423
|
+
borderRadius: "8px",
|
|
1424
|
+
marginBottom: "4px",
|
|
1425
|
+
cursor: editingId || confirmDeleteId || switchingId ? "default" : "pointer",
|
|
1426
|
+
backgroundColor: activeDrawing?.id === drawing.id ? "var(--color-primary-light, rgba(108, 99, 255, 0.1))" : "transparent",
|
|
1427
|
+
transition: "background-color 0.15s",
|
|
1428
|
+
opacity: switchingId && switchingId !== drawing.id ? 0.5 : 1
|
|
1429
|
+
},
|
|
1430
|
+
children: [
|
|
1431
|
+
renderThumbnail && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
1432
|
+
width: "64px",
|
|
1433
|
+
height: "48px",
|
|
1434
|
+
flexShrink: 0,
|
|
1435
|
+
borderRadius: "4px",
|
|
1436
|
+
overflow: "hidden",
|
|
1437
|
+
border: "1px solid var(--default-border-color, #e0e0e0)",
|
|
1438
|
+
backgroundColor: "#fff",
|
|
1439
|
+
display: "flex",
|
|
1440
|
+
alignItems: "center",
|
|
1441
|
+
justifyContent: "center"
|
|
1442
|
+
}, children: renderThumbnail(drawing) }),
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, minWidth: 0 }, children: editingId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: "6px", alignItems: "center" }, children: [
|
|
1444
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1445
|
+
"input",
|
|
1446
|
+
{
|
|
1447
|
+
type: "text",
|
|
1448
|
+
value: editName,
|
|
1449
|
+
onChange: (e) => setEditName(e.target.value),
|
|
1450
|
+
onKeyDown: (e) => {
|
|
1451
|
+
if (e.key === "Enter") handleSaveEdit();
|
|
1452
|
+
if (e.key === "Escape") handleCancelEdit();
|
|
1453
|
+
},
|
|
1454
|
+
onClick: (e) => e.stopPropagation(),
|
|
1455
|
+
autoFocus: true,
|
|
1456
|
+
style: {
|
|
1457
|
+
flex: 1,
|
|
1458
|
+
padding: "4px 8px",
|
|
1459
|
+
fontSize: "14px",
|
|
1460
|
+
border: "1px solid var(--color-primary, #6c63ff)",
|
|
1461
|
+
borderRadius: "4px",
|
|
1462
|
+
outline: "none"
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
),
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1467
|
+
"button",
|
|
1468
|
+
{
|
|
1469
|
+
onClick: (e) => {
|
|
1470
|
+
e.stopPropagation();
|
|
1471
|
+
handleSaveEdit();
|
|
1472
|
+
},
|
|
1473
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "var(--color-primary, #6c63ff)", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1474
|
+
children: t.save
|
|
1475
|
+
}
|
|
1476
|
+
),
|
|
1477
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1478
|
+
"button",
|
|
1479
|
+
{
|
|
1480
|
+
onClick: (e) => {
|
|
1481
|
+
e.stopPropagation();
|
|
1482
|
+
handleCancelEdit();
|
|
1483
|
+
},
|
|
1484
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1485
|
+
children: t.cancel
|
|
1486
|
+
}
|
|
1487
|
+
)
|
|
1488
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1489
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1491
|
+
"span",
|
|
1492
|
+
{
|
|
1493
|
+
onClick: (e) => {
|
|
1494
|
+
e.stopPropagation();
|
|
1495
|
+
handleStartEdit(drawing);
|
|
1496
|
+
},
|
|
1497
|
+
style: {
|
|
1498
|
+
fontWeight: activeDrawing?.id === drawing.id ? 600 : 400,
|
|
1499
|
+
fontSize: "14px",
|
|
1500
|
+
overflow: "hidden",
|
|
1501
|
+
textOverflow: "ellipsis",
|
|
1502
|
+
whiteSpace: "nowrap",
|
|
1503
|
+
cursor: "text"
|
|
1504
|
+
},
|
|
1505
|
+
title: t.rename,
|
|
1506
|
+
children: [
|
|
1507
|
+
switchingId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { display: "inline-block", animation: "spin 1s linear infinite", marginRight: "4px" }, children: "\u23F3" }) : activeDrawing?.id === drawing.id ? "\u2713 " : "",
|
|
1508
|
+
drawing.name
|
|
1509
|
+
]
|
|
1510
|
+
}
|
|
1511
|
+
),
|
|
1512
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1513
|
+
"button",
|
|
1514
|
+
{
|
|
1515
|
+
onClick: (e) => {
|
|
1516
|
+
e.stopPropagation();
|
|
1517
|
+
handleStartEdit(drawing);
|
|
1518
|
+
},
|
|
1519
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "0 2px", fontSize: "12px", opacity: 0.4, flexShrink: 0 },
|
|
1520
|
+
title: t.rename,
|
|
1521
|
+
children: "\u270F\uFE0F"
|
|
1522
|
+
}
|
|
1523
|
+
)
|
|
1524
|
+
] }),
|
|
1525
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { fontSize: "11px", color: "var(--text-secondary-color, #888)", marginTop: "1px" }, children: [
|
|
1526
|
+
t.modified,
|
|
1527
|
+
": ",
|
|
1528
|
+
formatDate(drawing.updatedAt)
|
|
1529
|
+
] })
|
|
1530
|
+
] }) }),
|
|
1531
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", gap: "2px", alignItems: "center" }, children: confirmDeleteId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1532
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1533
|
+
"button",
|
|
1534
|
+
{
|
|
1535
|
+
onClick: (e) => {
|
|
1536
|
+
e.stopPropagation();
|
|
1537
|
+
handleDelete(drawing.id);
|
|
1538
|
+
},
|
|
1539
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "#dc3545", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1540
|
+
children: t.delete
|
|
1541
|
+
}
|
|
1542
|
+
),
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1544
|
+
"button",
|
|
1545
|
+
{
|
|
1546
|
+
onClick: (e) => {
|
|
1547
|
+
e.stopPropagation();
|
|
1548
|
+
setConfirmDeleteId(null);
|
|
1549
|
+
},
|
|
1550
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1551
|
+
children: t.cancel
|
|
1552
|
+
}
|
|
1553
|
+
)
|
|
1554
|
+
] }) : movingDrawingId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", flexDirection: "column", gap: "2px", fontSize: "12px" }, children: [
|
|
1555
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1556
|
+
"button",
|
|
1557
|
+
{
|
|
1558
|
+
onClick: () => handleMoveToFolder(drawing.id, null),
|
|
1559
|
+
style: { padding: "3px 8px", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", backgroundColor: !drawing.folderId ? "var(--color-primary-light, rgba(108, 99, 255, 0.1))" : "transparent", color: "inherit", textAlign: "left" },
|
|
1560
|
+
children: t.moveToRoot
|
|
1561
|
+
}
|
|
1562
|
+
),
|
|
1563
|
+
folders.map((folder) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1564
|
+
"button",
|
|
1565
|
+
{
|
|
1566
|
+
onClick: () => handleMoveToFolder(drawing.id, folder.id),
|
|
1567
|
+
style: { padding: "3px 8px", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", backgroundColor: drawing.folderId === folder.id ? "var(--color-primary-light, rgba(108, 99, 255, 0.1))" : "transparent", color: "inherit", textAlign: "left" },
|
|
1568
|
+
children: [
|
|
1569
|
+
"\u{1F4C1} ",
|
|
1570
|
+
folder.name
|
|
1571
|
+
]
|
|
1572
|
+
},
|
|
1573
|
+
folder.id
|
|
1574
|
+
)),
|
|
1575
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1576
|
+
"button",
|
|
1577
|
+
{
|
|
1578
|
+
onClick: () => setMovingDrawingId(null),
|
|
1579
|
+
style: { padding: "3px 8px", border: "none", cursor: "pointer", backgroundColor: "transparent", color: "var(--text-secondary-color, #888)", textAlign: "left" },
|
|
1580
|
+
children: t.cancel
|
|
1581
|
+
}
|
|
1582
|
+
)
|
|
1583
|
+
] }) : editingId !== drawing.id && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1584
|
+
folders.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1585
|
+
"button",
|
|
1586
|
+
{
|
|
1587
|
+
onClick: (e) => {
|
|
1588
|
+
e.stopPropagation();
|
|
1589
|
+
setMovingDrawingId(drawing.id);
|
|
1590
|
+
},
|
|
1591
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1592
|
+
title: t.moveToFolder,
|
|
1593
|
+
children: "\u{1F4C1}"
|
|
1594
|
+
}
|
|
1595
|
+
),
|
|
1596
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1597
|
+
"button",
|
|
1598
|
+
{
|
|
1599
|
+
onClick: (e) => {
|
|
1600
|
+
e.stopPropagation();
|
|
1601
|
+
exportDrawingAsExcalidraw(drawing.id);
|
|
1602
|
+
},
|
|
1603
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1604
|
+
title: t.exportDrawing,
|
|
1605
|
+
children: "\u{1F4BE}"
|
|
1606
|
+
}
|
|
1607
|
+
),
|
|
1608
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1609
|
+
"button",
|
|
1610
|
+
{
|
|
1611
|
+
onClick: (e) => {
|
|
1612
|
+
e.stopPropagation();
|
|
1613
|
+
setConfirmDeleteId(drawing.id);
|
|
1614
|
+
},
|
|
1615
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1616
|
+
title: t.delete,
|
|
1617
|
+
disabled: drawings.length <= 1,
|
|
1618
|
+
children: "\u{1F5D1}\uFE0F"
|
|
1619
|
+
}
|
|
1620
|
+
)
|
|
1621
|
+
] }) })
|
|
1622
|
+
]
|
|
1623
|
+
},
|
|
1624
|
+
drawing.id
|
|
1625
|
+
);
|
|
1626
|
+
const renderFolderGroup = (folder) => {
|
|
1627
|
+
const folderDrawings = drawingsByFolder[folder.id] || [];
|
|
1628
|
+
const isExpanded = expandedFolders.has(folder.id);
|
|
1629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { marginBottom: "4px" }, children: [
|
|
1630
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1631
|
+
"div",
|
|
1632
|
+
{
|
|
1633
|
+
onClick: () => toggleFolder(folder.id),
|
|
1634
|
+
style: {
|
|
1635
|
+
padding: "8px 12px",
|
|
1636
|
+
display: "flex",
|
|
1637
|
+
alignItems: "center",
|
|
1638
|
+
gap: "8px",
|
|
1639
|
+
borderRadius: "8px",
|
|
1640
|
+
cursor: "pointer",
|
|
1641
|
+
backgroundColor: "var(--color-surface-mid, rgba(0, 0, 0, 0.03))"
|
|
1642
|
+
},
|
|
1643
|
+
children: [
|
|
1644
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: "12px", width: "16px", textAlign: "center", flexShrink: 0 }, children: isExpanded ? "\u25BC" : "\u25B6" }),
|
|
1645
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: "16px", flexShrink: 0 }, children: "\u{1F4C1}" }),
|
|
1646
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, minWidth: 0 }, children: editingFolderId === folder.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: "6px", alignItems: "center" }, onClick: (e) => e.stopPropagation(), children: [
|
|
1647
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1648
|
+
"input",
|
|
1649
|
+
{
|
|
1650
|
+
type: "text",
|
|
1651
|
+
value: editFolderName,
|
|
1652
|
+
onChange: (e) => setEditFolderName(e.target.value),
|
|
1653
|
+
onKeyDown: (e) => {
|
|
1654
|
+
if (e.key === "Enter") handleSaveFolderEdit();
|
|
1655
|
+
if (e.key === "Escape") {
|
|
1656
|
+
setEditingFolderId(null);
|
|
1657
|
+
setEditFolderName("");
|
|
1658
|
+
}
|
|
1659
|
+
},
|
|
1660
|
+
autoFocus: true,
|
|
1661
|
+
style: { flex: 1, padding: "2px 6px", fontSize: "14px", border: "1px solid var(--color-primary, #6c63ff)", borderRadius: "4px", outline: "none" }
|
|
1662
|
+
}
|
|
1663
|
+
),
|
|
1664
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1665
|
+
"button",
|
|
1666
|
+
{
|
|
1667
|
+
onClick: handleSaveFolderEdit,
|
|
1668
|
+
style: { padding: "2px 8px", fontSize: "12px", backgroundColor: "var(--color-primary, #6c63ff)", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1669
|
+
children: t.save
|
|
1670
|
+
}
|
|
1671
|
+
)
|
|
1672
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { fontWeight: 600, fontSize: "14px" }, children: [
|
|
1673
|
+
folder.name,
|
|
1674
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { fontWeight: 400, fontSize: "12px", color: "var(--text-secondary-color, #888)", marginLeft: "6px" }, children: [
|
|
1675
|
+
"(",
|
|
1676
|
+
folderDrawings.length,
|
|
1677
|
+
")"
|
|
1678
|
+
] })
|
|
1679
|
+
] }) }),
|
|
1680
|
+
confirmDeleteFolderId === folder.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", gap: "4px" }, children: [
|
|
1681
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1682
|
+
"button",
|
|
1683
|
+
{
|
|
1684
|
+
onClick: () => handleDeleteFolder(folder.id),
|
|
1685
|
+
style: { padding: "2px 8px", fontSize: "12px", backgroundColor: "#dc3545", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1686
|
+
children: t.delete
|
|
1687
|
+
}
|
|
1688
|
+
),
|
|
1689
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1690
|
+
"button",
|
|
1691
|
+
{
|
|
1692
|
+
onClick: () => setConfirmDeleteFolderId(null),
|
|
1693
|
+
style: { padding: "2px 8px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1694
|
+
children: t.cancel
|
|
1695
|
+
}
|
|
1696
|
+
)
|
|
1697
|
+
] }) : editingFolderId !== folder.id && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", gap: "2px" }, children: [
|
|
1698
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1699
|
+
"button",
|
|
1700
|
+
{
|
|
1701
|
+
onClick: () => {
|
|
1702
|
+
setEditingFolderId(folder.id);
|
|
1703
|
+
setEditFolderName(folder.name);
|
|
1704
|
+
},
|
|
1705
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "2px", fontSize: "12px", opacity: 0.5 },
|
|
1706
|
+
title: t.renameFolder,
|
|
1707
|
+
children: "\u270F\uFE0F"
|
|
1708
|
+
}
|
|
1709
|
+
),
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1711
|
+
"button",
|
|
1712
|
+
{
|
|
1713
|
+
onClick: () => setConfirmDeleteFolderId(folder.id),
|
|
1714
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "2px", fontSize: "12px", opacity: 0.5 },
|
|
1715
|
+
title: t.deleteFolder,
|
|
1716
|
+
children: "\u{1F5D1}\uFE0F"
|
|
1717
|
+
}
|
|
1718
|
+
)
|
|
1719
|
+
] })
|
|
1720
|
+
]
|
|
1721
|
+
}
|
|
1722
|
+
),
|
|
1723
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { paddingLeft: "24px", marginTop: "2px" }, children: [
|
|
1724
|
+
folderDrawings.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "8px 12px", fontSize: "12px", color: "var(--text-secondary-color, #888)", fontStyle: "italic" }, children: t.noDrawingsYet }),
|
|
1725
|
+
folderDrawings.map(renderDrawingRow)
|
|
1726
|
+
] })
|
|
1727
|
+
] }, folder.id);
|
|
1728
|
+
};
|
|
1210
1729
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1211
1730
|
"div",
|
|
1212
1731
|
{
|
|
@@ -1262,181 +1781,32 @@ var DrawingsDialog = ({
|
|
|
1262
1781
|
]
|
|
1263
1782
|
}
|
|
1264
1783
|
),
|
|
1784
|
+
drawings.length > 3 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "8px 20px", borderBottom: "1px solid var(--default-border-color, #e0e0e0)" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1785
|
+
"input",
|
|
1786
|
+
{
|
|
1787
|
+
type: "text",
|
|
1788
|
+
value: searchQuery,
|
|
1789
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
1790
|
+
placeholder: "\u{1F50D}",
|
|
1791
|
+
style: {
|
|
1792
|
+
width: "100%",
|
|
1793
|
+
padding: "6px 12px",
|
|
1794
|
+
fontSize: "14px",
|
|
1795
|
+
border: "1px solid var(--default-border-color, #e0e0e0)",
|
|
1796
|
+
borderRadius: "6px",
|
|
1797
|
+
outline: "none",
|
|
1798
|
+
backgroundColor: "transparent",
|
|
1799
|
+
color: "inherit",
|
|
1800
|
+
boxSizing: "border-box"
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
) }),
|
|
1265
1804
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { flex: 1, overflow: "auto" }, children: [
|
|
1266
|
-
drawings.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
if (activeDrawing?.id !== drawing.id) handleSelect(drawing);
|
|
1272
|
-
},
|
|
1273
|
-
style: {
|
|
1274
|
-
padding: "10px 12px",
|
|
1275
|
-
display: "flex",
|
|
1276
|
-
alignItems: "center",
|
|
1277
|
-
gap: "12px",
|
|
1278
|
-
borderRadius: "8px",
|
|
1279
|
-
marginBottom: "4px",
|
|
1280
|
-
cursor: editingId || confirmDeleteId ? "default" : "pointer",
|
|
1281
|
-
backgroundColor: activeDrawing?.id === drawing.id ? "var(--color-primary-light, rgba(108, 99, 255, 0.1))" : "transparent",
|
|
1282
|
-
transition: "background-color 0.15s"
|
|
1283
|
-
},
|
|
1284
|
-
children: [
|
|
1285
|
-
renderThumbnail && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
1286
|
-
width: "64px",
|
|
1287
|
-
height: "48px",
|
|
1288
|
-
flexShrink: 0,
|
|
1289
|
-
borderRadius: "4px",
|
|
1290
|
-
overflow: "hidden",
|
|
1291
|
-
border: "1px solid var(--default-border-color, #e0e0e0)",
|
|
1292
|
-
backgroundColor: "#fff",
|
|
1293
|
-
display: "flex",
|
|
1294
|
-
alignItems: "center",
|
|
1295
|
-
justifyContent: "center"
|
|
1296
|
-
}, children: renderThumbnail(drawing) }),
|
|
1297
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, minWidth: 0 }, children: editingId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: "6px", alignItems: "center" }, children: [
|
|
1298
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1299
|
-
"input",
|
|
1300
|
-
{
|
|
1301
|
-
type: "text",
|
|
1302
|
-
value: editName,
|
|
1303
|
-
onChange: (e) => setEditName(e.target.value),
|
|
1304
|
-
onKeyDown: (e) => {
|
|
1305
|
-
if (e.key === "Enter") handleSaveEdit();
|
|
1306
|
-
if (e.key === "Escape") handleCancelEdit();
|
|
1307
|
-
},
|
|
1308
|
-
onClick: (e) => e.stopPropagation(),
|
|
1309
|
-
autoFocus: true,
|
|
1310
|
-
style: {
|
|
1311
|
-
flex: 1,
|
|
1312
|
-
padding: "4px 8px",
|
|
1313
|
-
fontSize: "14px",
|
|
1314
|
-
border: "1px solid var(--color-primary, #6c63ff)",
|
|
1315
|
-
borderRadius: "4px",
|
|
1316
|
-
outline: "none"
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
),
|
|
1320
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1321
|
-
"button",
|
|
1322
|
-
{
|
|
1323
|
-
onClick: (e) => {
|
|
1324
|
-
e.stopPropagation();
|
|
1325
|
-
handleSaveEdit();
|
|
1326
|
-
},
|
|
1327
|
-
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "var(--color-primary, #6c63ff)", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1328
|
-
children: t.save
|
|
1329
|
-
}
|
|
1330
|
-
),
|
|
1331
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1332
|
-
"button",
|
|
1333
|
-
{
|
|
1334
|
-
onClick: (e) => {
|
|
1335
|
-
e.stopPropagation();
|
|
1336
|
-
handleCancelEdit();
|
|
1337
|
-
},
|
|
1338
|
-
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1339
|
-
children: t.cancel
|
|
1340
|
-
}
|
|
1341
|
-
)
|
|
1342
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1343
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
|
|
1344
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1345
|
-
"span",
|
|
1346
|
-
{
|
|
1347
|
-
onClick: (e) => {
|
|
1348
|
-
e.stopPropagation();
|
|
1349
|
-
handleStartEdit(drawing);
|
|
1350
|
-
},
|
|
1351
|
-
style: {
|
|
1352
|
-
fontWeight: activeDrawing?.id === drawing.id ? 600 : 400,
|
|
1353
|
-
fontSize: "14px",
|
|
1354
|
-
overflow: "hidden",
|
|
1355
|
-
textOverflow: "ellipsis",
|
|
1356
|
-
whiteSpace: "nowrap",
|
|
1357
|
-
cursor: "text"
|
|
1358
|
-
},
|
|
1359
|
-
title: t.rename,
|
|
1360
|
-
children: [
|
|
1361
|
-
activeDrawing?.id === drawing.id && "\u2713 ",
|
|
1362
|
-
drawing.name
|
|
1363
|
-
]
|
|
1364
|
-
}
|
|
1365
|
-
),
|
|
1366
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1367
|
-
"button",
|
|
1368
|
-
{
|
|
1369
|
-
onClick: (e) => {
|
|
1370
|
-
e.stopPropagation();
|
|
1371
|
-
handleStartEdit(drawing);
|
|
1372
|
-
},
|
|
1373
|
-
style: { background: "none", border: "none", cursor: "pointer", padding: "0 2px", fontSize: "12px", opacity: 0.4, flexShrink: 0 },
|
|
1374
|
-
title: t.rename,
|
|
1375
|
-
children: "\u270F\uFE0F"
|
|
1376
|
-
}
|
|
1377
|
-
)
|
|
1378
|
-
] }),
|
|
1379
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { fontSize: "11px", color: "var(--text-secondary-color, #888)", marginTop: "1px" }, children: [
|
|
1380
|
-
t.modified,
|
|
1381
|
-
": ",
|
|
1382
|
-
formatDate(drawing.updatedAt)
|
|
1383
|
-
] })
|
|
1384
|
-
] }) }),
|
|
1385
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", gap: "2px" }, children: confirmDeleteId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1386
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1387
|
-
"button",
|
|
1388
|
-
{
|
|
1389
|
-
onClick: (e) => {
|
|
1390
|
-
e.stopPropagation();
|
|
1391
|
-
handleDelete(drawing.id);
|
|
1392
|
-
},
|
|
1393
|
-
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "#dc3545", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1394
|
-
children: t.delete
|
|
1395
|
-
}
|
|
1396
|
-
),
|
|
1397
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1398
|
-
"button",
|
|
1399
|
-
{
|
|
1400
|
-
onClick: (e) => {
|
|
1401
|
-
e.stopPropagation();
|
|
1402
|
-
setConfirmDeleteId(null);
|
|
1403
|
-
},
|
|
1404
|
-
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1405
|
-
children: t.cancel
|
|
1406
|
-
}
|
|
1407
|
-
)
|
|
1408
|
-
] }) : editingId !== drawing.id && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1409
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1410
|
-
"button",
|
|
1411
|
-
{
|
|
1412
|
-
onClick: (e) => {
|
|
1413
|
-
e.stopPropagation();
|
|
1414
|
-
exportDrawingAsExcalidraw(drawing.id);
|
|
1415
|
-
},
|
|
1416
|
-
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1417
|
-
title: t.exportDrawing,
|
|
1418
|
-
children: "\u{1F4BE}"
|
|
1419
|
-
}
|
|
1420
|
-
),
|
|
1421
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1422
|
-
"button",
|
|
1423
|
-
{
|
|
1424
|
-
onClick: (e) => {
|
|
1425
|
-
e.stopPropagation();
|
|
1426
|
-
setConfirmDeleteId(drawing.id);
|
|
1427
|
-
},
|
|
1428
|
-
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1429
|
-
title: t.delete,
|
|
1430
|
-
disabled: drawings.length <= 1,
|
|
1431
|
-
children: "\u{1F5D1}\uFE0F"
|
|
1432
|
-
}
|
|
1433
|
-
)
|
|
1434
|
-
] }) })
|
|
1435
|
-
]
|
|
1436
|
-
},
|
|
1437
|
-
drawing.id
|
|
1438
|
-
)) }),
|
|
1439
|
-
drawings.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "24px 20px", textAlign: "center", color: "var(--text-secondary-color, #666)" }, children: [
|
|
1805
|
+
(drawings.length > 0 || folders.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "8px 20px 0" }, children: [
|
|
1806
|
+
filteredFolders.map(renderFolderGroup),
|
|
1807
|
+
rootDrawings.map(renderDrawingRow)
|
|
1808
|
+
] }),
|
|
1809
|
+
drawings.length === 0 && folders.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "24px 20px", textAlign: "center", color: "var(--text-secondary-color, #666)" }, children: [
|
|
1440
1810
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t.noDrawingsYet }),
|
|
1441
1811
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t.clickNewToStart })
|
|
1442
1812
|
] }),
|
|
@@ -1448,7 +1818,7 @@ var DrawingsDialog = ({
|
|
|
1448
1818
|
icon: "\u{1F4C4}",
|
|
1449
1819
|
label: t.createNewDrawing,
|
|
1450
1820
|
description: t.createNewDrawingDesc,
|
|
1451
|
-
onClick: handleCreate,
|
|
1821
|
+
onClick: () => handleCreate(),
|
|
1452
1822
|
primary: true
|
|
1453
1823
|
}
|
|
1454
1824
|
),
|
|
@@ -1460,6 +1830,60 @@ var DrawingsDialog = ({
|
|
|
1460
1830
|
description: t.openFromFileDesc,
|
|
1461
1831
|
onClick: importExcalidrawFile
|
|
1462
1832
|
}
|
|
1833
|
+
),
|
|
1834
|
+
creatingFolder ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center", padding: "4px 0" }, children: [
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1836
|
+
"input",
|
|
1837
|
+
{
|
|
1838
|
+
ref: newFolderInputRef,
|
|
1839
|
+
type: "text",
|
|
1840
|
+
value: newFolderName,
|
|
1841
|
+
onChange: (e) => setNewFolderName(e.target.value),
|
|
1842
|
+
onKeyDown: (e) => {
|
|
1843
|
+
if (e.key === "Enter") handleCreateFolder();
|
|
1844
|
+
if (e.key === "Escape") {
|
|
1845
|
+
setCreatingFolder(false);
|
|
1846
|
+
setNewFolderName("");
|
|
1847
|
+
}
|
|
1848
|
+
},
|
|
1849
|
+
placeholder: t.newFolderName,
|
|
1850
|
+
style: {
|
|
1851
|
+
flex: 1,
|
|
1852
|
+
padding: "8px 12px",
|
|
1853
|
+
fontSize: "14px",
|
|
1854
|
+
border: "1px solid var(--color-primary, #6c63ff)",
|
|
1855
|
+
borderRadius: "8px",
|
|
1856
|
+
outline: "none"
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
),
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1861
|
+
"button",
|
|
1862
|
+
{
|
|
1863
|
+
onClick: handleCreateFolder,
|
|
1864
|
+
style: { padding: "8px 16px", fontSize: "14px", backgroundColor: "var(--color-primary, #6c63ff)", color: "#fff", border: "none", borderRadius: "8px", cursor: "pointer" },
|
|
1865
|
+
children: t.save
|
|
1866
|
+
}
|
|
1867
|
+
),
|
|
1868
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1869
|
+
"button",
|
|
1870
|
+
{
|
|
1871
|
+
onClick: () => {
|
|
1872
|
+
setCreatingFolder(false);
|
|
1873
|
+
setNewFolderName("");
|
|
1874
|
+
},
|
|
1875
|
+
style: { padding: "8px 16px", fontSize: "14px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "8px", cursor: "pointer", color: "inherit" },
|
|
1876
|
+
children: t.cancel
|
|
1877
|
+
}
|
|
1878
|
+
)
|
|
1879
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1880
|
+
ActionButton,
|
|
1881
|
+
{
|
|
1882
|
+
icon: "\u{1F4C1}",
|
|
1883
|
+
label: t.createFolder,
|
|
1884
|
+
description: "",
|
|
1885
|
+
onClick: () => setCreatingFolder(true)
|
|
1886
|
+
}
|
|
1463
1887
|
)
|
|
1464
1888
|
] }),
|
|
1465
1889
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: sectionHeaderStyle, children: t.sectionWorkspace }),
|
|
@@ -1706,16 +2130,22 @@ function WorkspacePlugin(props) {
|
|
|
1706
2130
|
addDrawingToWorkspace,
|
|
1707
2131
|
closeDB,
|
|
1708
2132
|
createDrawing,
|
|
2133
|
+
createFolder,
|
|
1709
2134
|
deleteDrawing,
|
|
2135
|
+
deleteFolder,
|
|
1710
2136
|
duplicateDrawing,
|
|
1711
2137
|
getAllDrawings,
|
|
2138
|
+
getAllFolders,
|
|
1712
2139
|
getDB,
|
|
1713
2140
|
getDrawing,
|
|
2141
|
+
getFolder,
|
|
1714
2142
|
getOrCreateDefaultWorkspace,
|
|
1715
2143
|
getTranslations,
|
|
1716
2144
|
getWorkspace,
|
|
1717
2145
|
isLanguageSupported,
|
|
2146
|
+
moveDrawingToFolder,
|
|
1718
2147
|
removeDrawingFromWorkspace,
|
|
2148
|
+
renameFolder,
|
|
1719
2149
|
setActiveDrawing,
|
|
1720
2150
|
updateDrawing,
|
|
1721
2151
|
updateWorkspace,
|