rita-workspace 0.5.0 → 0.5.2
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 +720 -198
- package/dist/index.mjs +715 -199
- 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
|
};
|
|
@@ -326,17 +406,23 @@ function useWorkspaceLang() {
|
|
|
326
406
|
var TAB_ID = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
327
407
|
var TABS_KEY = "rita-workspace-tabs";
|
|
328
408
|
var TAB_CHANNEL = "rita-workspace-tabs";
|
|
409
|
+
var tabsMapCache = null;
|
|
410
|
+
var tabsMapRaw = null;
|
|
329
411
|
function getTabsMap() {
|
|
330
412
|
try {
|
|
331
|
-
const raw =
|
|
413
|
+
const raw = localStorage.getItem(TABS_KEY) || "{}";
|
|
414
|
+
if (raw === tabsMapRaw && tabsMapCache) return tabsMapCache;
|
|
415
|
+
tabsMapRaw = raw;
|
|
416
|
+
const parsed = JSON.parse(raw);
|
|
332
417
|
const result = {};
|
|
333
|
-
for (const [tabId, value] of Object.entries(
|
|
418
|
+
for (const [tabId, value] of Object.entries(parsed)) {
|
|
334
419
|
if (typeof value === "string") {
|
|
335
420
|
result[tabId] = { drawingId: value, openedAt: 0 };
|
|
336
421
|
} else if (value && typeof value === "object" && "drawingId" in value) {
|
|
337
422
|
result[tabId] = value;
|
|
338
423
|
}
|
|
339
424
|
}
|
|
425
|
+
tabsMapCache = result;
|
|
340
426
|
return result;
|
|
341
427
|
} catch {
|
|
342
428
|
return {};
|
|
@@ -353,7 +439,10 @@ function setTabDrawing(drawingId) {
|
|
|
353
439
|
} else {
|
|
354
440
|
delete tabs[TAB_ID];
|
|
355
441
|
}
|
|
356
|
-
|
|
442
|
+
const json = JSON.stringify(tabs);
|
|
443
|
+
localStorage.setItem(TABS_KEY, json);
|
|
444
|
+
tabsMapCache = tabs;
|
|
445
|
+
tabsMapRaw = json;
|
|
357
446
|
}
|
|
358
447
|
function isDrawingOpenedEarlierInOtherTab(drawingId) {
|
|
359
448
|
const tabs = getTabsMap();
|
|
@@ -367,6 +456,7 @@ function isDrawingOpenedEarlierInOtherTab(drawingId) {
|
|
|
367
456
|
function WorkspaceProvider({ children, lang = "en" }) {
|
|
368
457
|
const [workspace, setWorkspace] = (0, import_react.useState)(null);
|
|
369
458
|
const [drawings, setDrawings] = (0, import_react.useState)([]);
|
|
459
|
+
const [folders, setFolders] = (0, import_react.useState)([]);
|
|
370
460
|
const [activeDrawing, setActiveDrawing2] = (0, import_react.useState)(null);
|
|
371
461
|
const [isLoading, setIsLoading] = (0, import_react.useState)(true);
|
|
372
462
|
const [error, setError] = (0, import_react.useState)(null);
|
|
@@ -442,6 +532,8 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
442
532
|
const allDrawings = await getAllDrawings();
|
|
443
533
|
const wsDrawings = allDrawings.filter((d) => ws.drawingIds.includes(d.id));
|
|
444
534
|
setDrawings(wsDrawings);
|
|
535
|
+
const allFolders = await getAllFolders();
|
|
536
|
+
setFolders(allFolders);
|
|
445
537
|
const lastDrawingId = sessionStorage.getItem("rita-workspace-tab-drawing");
|
|
446
538
|
let active = null;
|
|
447
539
|
if (lastDrawingId) {
|
|
@@ -474,14 +566,20 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
474
566
|
const allDrawings = await getAllDrawings();
|
|
475
567
|
const wsDrawings = allDrawings.filter((d) => workspace.drawingIds.includes(d.id));
|
|
476
568
|
setDrawings(wsDrawings);
|
|
569
|
+
const allFolders = await getAllFolders();
|
|
570
|
+
setFolders(allFolders);
|
|
477
571
|
} catch (err) {
|
|
478
572
|
}
|
|
479
573
|
}, [workspace]);
|
|
480
|
-
const
|
|
574
|
+
const drawingsRef = (0, import_react.useRef)(drawings);
|
|
575
|
+
drawingsRef.current = drawings;
|
|
576
|
+
const activeDrawingIdRef = (0, import_react.useRef)(activeDrawing?.id ?? null);
|
|
577
|
+
activeDrawingIdRef.current = activeDrawing?.id ?? null;
|
|
578
|
+
const createNewDrawing = (0, import_react.useCallback)(async (name, folderId) => {
|
|
481
579
|
if (!workspace) return null;
|
|
482
580
|
try {
|
|
483
|
-
const defaultName = `${t.newDrawing} ${
|
|
484
|
-
const drawing = await createDrawing(name || defaultName);
|
|
581
|
+
const defaultName = `${t.newDrawing} ${drawingsRef.current.length + 1}`;
|
|
582
|
+
const drawing = await createDrawing(name || defaultName, [], {}, folderId);
|
|
485
583
|
await addDrawingToWorkspace(workspace.id, drawing.id);
|
|
486
584
|
setDrawings((prev) => [...prev, drawing]);
|
|
487
585
|
setActiveDrawing2(drawing);
|
|
@@ -496,7 +594,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
496
594
|
setError(err instanceof Error ? err.message : "Failed to create drawing");
|
|
497
595
|
return null;
|
|
498
596
|
}
|
|
499
|
-
}, [workspace,
|
|
597
|
+
}, [workspace, t]);
|
|
500
598
|
const switchDrawing = (0, import_react.useCallback)(async (id) => {
|
|
501
599
|
if (!workspace) return;
|
|
502
600
|
try {
|
|
@@ -515,23 +613,23 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
515
613
|
const updated = await updateDrawing(id, { name });
|
|
516
614
|
if (updated) {
|
|
517
615
|
setDrawings((prev) => prev.map((d) => d.id === id ? updated : d));
|
|
518
|
-
if (
|
|
616
|
+
if (activeDrawingIdRef.current === id) {
|
|
519
617
|
setActiveDrawing2(updated);
|
|
520
618
|
}
|
|
521
619
|
}
|
|
522
620
|
} catch (err) {
|
|
523
621
|
setError(err instanceof Error ? err.message : "Failed to rename drawing");
|
|
524
622
|
}
|
|
525
|
-
}, [
|
|
623
|
+
}, []);
|
|
526
624
|
const removeDrawing = (0, import_react.useCallback)(async (id) => {
|
|
527
|
-
if (!workspace ||
|
|
625
|
+
if (!workspace || drawingsRef.current.length <= 1) return;
|
|
528
626
|
try {
|
|
529
627
|
await deleteDrawing(id);
|
|
530
628
|
const updatedWorkspace = await removeDrawingFromWorkspace(workspace.id, id);
|
|
531
629
|
setDrawings((prev) => prev.filter((d) => d.id !== id));
|
|
532
630
|
if (updatedWorkspace) {
|
|
533
631
|
setWorkspace(updatedWorkspace);
|
|
534
|
-
if (
|
|
632
|
+
if (activeDrawingIdRef.current === id && updatedWorkspace.activeDrawingId) {
|
|
535
633
|
const newActive = await getDrawing(updatedWorkspace.activeDrawingId);
|
|
536
634
|
setActiveDrawing2(newActive || null);
|
|
537
635
|
}
|
|
@@ -539,11 +637,11 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
539
637
|
} catch (err) {
|
|
540
638
|
setError(err instanceof Error ? err.message : "Failed to delete drawing");
|
|
541
639
|
}
|
|
542
|
-
}, [workspace
|
|
640
|
+
}, [workspace]);
|
|
543
641
|
const duplicateCurrentDrawing = (0, import_react.useCallback)(async () => {
|
|
544
|
-
if (!
|
|
642
|
+
if (!activeDrawingIdRef.current || !workspace) return null;
|
|
545
643
|
try {
|
|
546
|
-
const duplicate = await duplicateDrawing(
|
|
644
|
+
const duplicate = await duplicateDrawing(activeDrawingIdRef.current);
|
|
547
645
|
if (duplicate) {
|
|
548
646
|
await addDrawingToWorkspace(workspace.id, duplicate.id);
|
|
549
647
|
setDrawings((prev) => [...prev, duplicate]);
|
|
@@ -558,7 +656,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
558
656
|
setError(err instanceof Error ? err.message : "Failed to duplicate drawing");
|
|
559
657
|
return null;
|
|
560
658
|
}
|
|
561
|
-
}, [
|
|
659
|
+
}, [workspace]);
|
|
562
660
|
const saveCurrentDrawing = (0, import_react.useCallback)(async (elements, appState, files) => {
|
|
563
661
|
if (!activeDrawing) return;
|
|
564
662
|
try {
|
|
@@ -714,9 +812,52 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
714
812
|
setError(err instanceof Error ? err.message : "Failed to import drawing");
|
|
715
813
|
}
|
|
716
814
|
}, [workspace, t]);
|
|
815
|
+
const createFolder2 = (0, import_react.useCallback)(async (name) => {
|
|
816
|
+
try {
|
|
817
|
+
const folder = await createFolder(name);
|
|
818
|
+
setFolders((prev) => [...prev, folder]);
|
|
819
|
+
return folder;
|
|
820
|
+
} catch (err) {
|
|
821
|
+
setError(err instanceof Error ? err.message : "Failed to create folder");
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
}, []);
|
|
825
|
+
const renameFolder2 = (0, import_react.useCallback)(async (id, name) => {
|
|
826
|
+
try {
|
|
827
|
+
const updated = await renameFolder(id, name);
|
|
828
|
+
if (updated) {
|
|
829
|
+
setFolders((prev) => prev.map((f) => f.id === id ? updated : f));
|
|
830
|
+
}
|
|
831
|
+
} catch (err) {
|
|
832
|
+
setError(err instanceof Error ? err.message : "Failed to rename folder");
|
|
833
|
+
}
|
|
834
|
+
}, []);
|
|
835
|
+
const deleteFolder2 = (0, import_react.useCallback)(async (id) => {
|
|
836
|
+
try {
|
|
837
|
+
await deleteFolder(id);
|
|
838
|
+
setFolders((prev) => prev.filter((f) => f.id !== id));
|
|
839
|
+
setDrawings((prev) => prev.map((d) => d.folderId === id ? { ...d, folderId: null } : d));
|
|
840
|
+
} catch (err) {
|
|
841
|
+
setError(err instanceof Error ? err.message : "Failed to delete folder");
|
|
842
|
+
}
|
|
843
|
+
}, []);
|
|
844
|
+
const moveDrawingToFolder2 = (0, import_react.useCallback)(async (drawingId, folderId) => {
|
|
845
|
+
try {
|
|
846
|
+
const updated = await moveDrawingToFolder(drawingId, folderId);
|
|
847
|
+
if (updated) {
|
|
848
|
+
setDrawings((prev) => prev.map((d) => d.id === drawingId ? updated : d));
|
|
849
|
+
if (activeDrawingIdRef.current === drawingId) {
|
|
850
|
+
setActiveDrawing2(updated);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
} catch (err) {
|
|
854
|
+
setError(err instanceof Error ? err.message : "Failed to move drawing");
|
|
855
|
+
}
|
|
856
|
+
}, []);
|
|
717
857
|
const value = {
|
|
718
858
|
workspace,
|
|
719
859
|
drawings,
|
|
860
|
+
folders,
|
|
720
861
|
activeDrawing,
|
|
721
862
|
isLoading,
|
|
722
863
|
error,
|
|
@@ -728,6 +869,10 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
728
869
|
renameDrawing,
|
|
729
870
|
removeDrawing,
|
|
730
871
|
duplicateCurrentDrawing,
|
|
872
|
+
createFolder: createFolder2,
|
|
873
|
+
renameFolder: renameFolder2,
|
|
874
|
+
deleteFolder: deleteFolder2,
|
|
875
|
+
moveDrawingToFolder: moveDrawingToFolder2,
|
|
731
876
|
saveCurrentDrawing,
|
|
732
877
|
saveDrawingById,
|
|
733
878
|
refreshDrawings,
|
|
@@ -1081,11 +1226,16 @@ var DrawingsDialog = ({
|
|
|
1081
1226
|
}) => {
|
|
1082
1227
|
const {
|
|
1083
1228
|
drawings,
|
|
1229
|
+
folders,
|
|
1084
1230
|
activeDrawing,
|
|
1085
1231
|
switchDrawing,
|
|
1086
1232
|
createNewDrawing,
|
|
1087
1233
|
renameDrawing,
|
|
1088
1234
|
removeDrawing,
|
|
1235
|
+
createFolder: createFolder2,
|
|
1236
|
+
renameFolder: renameFolder2,
|
|
1237
|
+
deleteFolder: deleteFolder2,
|
|
1238
|
+
moveDrawingToFolder: moveDrawingToFolder2,
|
|
1089
1239
|
exportWorkspace,
|
|
1090
1240
|
importWorkspace,
|
|
1091
1241
|
exportDrawingAsExcalidraw,
|
|
@@ -1099,21 +1249,44 @@ var DrawingsDialog = ({
|
|
|
1099
1249
|
const [editingId, setEditingId] = (0, import_react5.useState)(null);
|
|
1100
1250
|
const [editName, setEditName] = (0, import_react5.useState)("");
|
|
1101
1251
|
const [confirmDeleteId, setConfirmDeleteId] = (0, import_react5.useState)(null);
|
|
1252
|
+
const [switchingId, setSwitchingId] = (0, import_react5.useState)(null);
|
|
1253
|
+
const [expandedFolders, setExpandedFolders] = (0, import_react5.useState)(/* @__PURE__ */ new Set());
|
|
1254
|
+
const [creatingFolder, setCreatingFolder] = (0, import_react5.useState)(false);
|
|
1255
|
+
const [newFolderName, setNewFolderName] = (0, import_react5.useState)("");
|
|
1256
|
+
const [editingFolderId, setEditingFolderId] = (0, import_react5.useState)(null);
|
|
1257
|
+
const [editFolderName, setEditFolderName] = (0, import_react5.useState)("");
|
|
1258
|
+
const [confirmDeleteFolderId, setConfirmDeleteFolderId] = (0, import_react5.useState)(null);
|
|
1259
|
+
const [movingDrawingId, setMovingDrawingId] = (0, import_react5.useState)(null);
|
|
1260
|
+
const [searchQuery, setSearchQuery] = (0, import_react5.useState)("");
|
|
1261
|
+
const [busyFolderId, setBusyFolderId] = (0, import_react5.useState)(null);
|
|
1262
|
+
const [isRefreshing, setIsRefreshing] = (0, import_react5.useState)(false);
|
|
1263
|
+
const [draggingDrawingId, setDraggingDrawingId] = (0, import_react5.useState)(null);
|
|
1264
|
+
const [dropTargetFolderId, setDropTargetFolderId] = (0, import_react5.useState)(null);
|
|
1102
1265
|
const [position, setPosition] = (0, import_react5.useState)(null);
|
|
1103
1266
|
const dragRef = (0, import_react5.useRef)(null);
|
|
1104
1267
|
const dialogRef = (0, import_react5.useRef)(null);
|
|
1268
|
+
const newFolderInputRef = (0, import_react5.useRef)(null);
|
|
1105
1269
|
const prevOpenRef = (0, import_react5.useRef)(false);
|
|
1106
1270
|
(0, import_react5.useEffect)(() => {
|
|
1107
1271
|
if (open) {
|
|
1108
|
-
|
|
1272
|
+
setIsRefreshing(true);
|
|
1273
|
+
refreshDrawings().finally(() => setIsRefreshing(false));
|
|
1109
1274
|
if (!prevOpenRef.current) {
|
|
1110
1275
|
setPosition(null);
|
|
1276
|
+
setSearchQuery("");
|
|
1277
|
+
setExpandedFolders(new Set(folders.map((f) => f.id)));
|
|
1111
1278
|
}
|
|
1112
1279
|
}
|
|
1113
1280
|
prevOpenRef.current = open;
|
|
1114
|
-
}, [open, refreshDrawings]);
|
|
1281
|
+
}, [open, refreshDrawings, folders]);
|
|
1282
|
+
(0, import_react5.useEffect)(() => {
|
|
1283
|
+
if (creatingFolder && newFolderInputRef.current) {
|
|
1284
|
+
newFolderInputRef.current.focus();
|
|
1285
|
+
}
|
|
1286
|
+
}, [creatingFolder]);
|
|
1115
1287
|
const handleMouseDown = (0, import_react5.useCallback)((e) => {
|
|
1116
1288
|
if (e.target.closest("button")) return;
|
|
1289
|
+
if (e.target.closest("input")) return;
|
|
1117
1290
|
if (!dialogRef.current) return;
|
|
1118
1291
|
const rect = dialogRef.current.getBoundingClientRect();
|
|
1119
1292
|
const currentX = position?.x ?? rect.left;
|
|
@@ -1134,11 +1307,13 @@ var DrawingsDialog = ({
|
|
|
1134
1307
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1135
1308
|
}, [position]);
|
|
1136
1309
|
const handleSelect = (0, import_react5.useCallback)(async (drawing) => {
|
|
1310
|
+
setSwitchingId(drawing.id);
|
|
1137
1311
|
await switchDrawing(drawing.id);
|
|
1138
1312
|
onDrawingSelect?.(drawing);
|
|
1313
|
+
setSwitchingId(null);
|
|
1139
1314
|
}, [switchDrawing, onDrawingSelect]);
|
|
1140
|
-
const handleCreate = (0, import_react5.useCallback)(async () => {
|
|
1141
|
-
const newDrawing = await createNewDrawing();
|
|
1315
|
+
const handleCreate = (0, import_react5.useCallback)(async (folderId) => {
|
|
1316
|
+
const newDrawing = await createNewDrawing(void 0, folderId);
|
|
1142
1317
|
if (newDrawing) onDrawingSelect?.(newDrawing);
|
|
1143
1318
|
}, [createNewDrawing, onDrawingSelect]);
|
|
1144
1319
|
const handleStartEdit = (0, import_react5.useCallback)((drawing) => {
|
|
@@ -1160,6 +1335,48 @@ var DrawingsDialog = ({
|
|
|
1160
1335
|
await removeDrawing(id);
|
|
1161
1336
|
setConfirmDeleteId(null);
|
|
1162
1337
|
}, [removeDrawing]);
|
|
1338
|
+
const handleCreateFolder = (0, import_react5.useCallback)(async () => {
|
|
1339
|
+
if (newFolderName.trim()) {
|
|
1340
|
+
setBusyFolderId("__creating__");
|
|
1341
|
+
const folder = await createFolder2(newFolderName.trim());
|
|
1342
|
+
if (folder) {
|
|
1343
|
+
setExpandedFolders((prev) => /* @__PURE__ */ new Set([...prev, folder.id]));
|
|
1344
|
+
}
|
|
1345
|
+
setBusyFolderId(null);
|
|
1346
|
+
}
|
|
1347
|
+
setCreatingFolder(false);
|
|
1348
|
+
setNewFolderName("");
|
|
1349
|
+
}, [newFolderName, createFolder2]);
|
|
1350
|
+
const handleSaveFolderEdit = (0, import_react5.useCallback)(async () => {
|
|
1351
|
+
if (editingFolderId && editFolderName.trim()) {
|
|
1352
|
+
setBusyFolderId(editingFolderId);
|
|
1353
|
+
await renameFolder2(editingFolderId, editFolderName.trim());
|
|
1354
|
+
setBusyFolderId(null);
|
|
1355
|
+
}
|
|
1356
|
+
setEditingFolderId(null);
|
|
1357
|
+
setEditFolderName("");
|
|
1358
|
+
}, [editingFolderId, editFolderName, renameFolder2]);
|
|
1359
|
+
const handleDeleteFolder = (0, import_react5.useCallback)(async (id) => {
|
|
1360
|
+
setBusyFolderId(id);
|
|
1361
|
+
await deleteFolder2(id);
|
|
1362
|
+
setBusyFolderId(null);
|
|
1363
|
+
setConfirmDeleteFolderId(null);
|
|
1364
|
+
}, [deleteFolder2]);
|
|
1365
|
+
const handleMoveToFolder = (0, import_react5.useCallback)(async (drawingId, folderId) => {
|
|
1366
|
+
await moveDrawingToFolder2(drawingId, folderId);
|
|
1367
|
+
setMovingDrawingId(null);
|
|
1368
|
+
}, [moveDrawingToFolder2]);
|
|
1369
|
+
const toggleFolder = (0, import_react5.useCallback)((folderId) => {
|
|
1370
|
+
setExpandedFolders((prev) => {
|
|
1371
|
+
const next = new Set(prev);
|
|
1372
|
+
if (next.has(folderId)) {
|
|
1373
|
+
next.delete(folderId);
|
|
1374
|
+
} else {
|
|
1375
|
+
next.add(folderId);
|
|
1376
|
+
}
|
|
1377
|
+
return next;
|
|
1378
|
+
});
|
|
1379
|
+
}, []);
|
|
1163
1380
|
const getLocale = () => {
|
|
1164
1381
|
if (!effectiveLang) return "en-US";
|
|
1165
1382
|
const baseLang = effectiveLang.split("-")[0].toLowerCase();
|
|
@@ -1174,6 +1391,17 @@ var DrawingsDialog = ({
|
|
|
1174
1391
|
});
|
|
1175
1392
|
};
|
|
1176
1393
|
if (!open) return null;
|
|
1394
|
+
const { rootDrawings, drawingsByFolder, filteredFolders } = (0, import_react5.useMemo)(() => {
|
|
1395
|
+
const query = searchQuery.toLowerCase().trim();
|
|
1396
|
+
const filtered = query ? drawings.filter((d) => d.name.toLowerCase().includes(query)) : drawings;
|
|
1397
|
+
const root = filtered.filter((d) => !d.folderId);
|
|
1398
|
+
const byFolder = {};
|
|
1399
|
+
for (const folder of folders) {
|
|
1400
|
+
byFolder[folder.id] = filtered.filter((d) => d.folderId === folder.id);
|
|
1401
|
+
}
|
|
1402
|
+
const foldersFiltered = query ? folders.filter((f) => f.name.toLowerCase().includes(query) || (byFolder[f.id] || []).length > 0) : folders;
|
|
1403
|
+
return { rootDrawings: root, drawingsByFolder: byFolder, filteredFolders: foldersFiltered };
|
|
1404
|
+
}, [drawings, folders, searchQuery]);
|
|
1177
1405
|
const dialogStyle = position ? {
|
|
1178
1406
|
position: "fixed",
|
|
1179
1407
|
left: position.x,
|
|
@@ -1207,6 +1435,355 @@ var DrawingsDialog = ({
|
|
|
1207
1435
|
color: "var(--text-secondary-color, #888)",
|
|
1208
1436
|
padding: "16px 20px 8px"
|
|
1209
1437
|
};
|
|
1438
|
+
const renderDrawingRow = (drawing) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1439
|
+
"div",
|
|
1440
|
+
{
|
|
1441
|
+
draggable: !editingId && !confirmDeleteId,
|
|
1442
|
+
onDragStart: (e) => {
|
|
1443
|
+
setDraggingDrawingId(drawing.id);
|
|
1444
|
+
e.dataTransfer.effectAllowed = "move";
|
|
1445
|
+
e.dataTransfer.setData("text/plain", drawing.id);
|
|
1446
|
+
},
|
|
1447
|
+
onDragEnd: () => {
|
|
1448
|
+
setDraggingDrawingId(null);
|
|
1449
|
+
setDropTargetFolderId("__none__");
|
|
1450
|
+
setTimeout(() => setDropTargetFolderId(null), 0);
|
|
1451
|
+
},
|
|
1452
|
+
onClick: () => {
|
|
1453
|
+
if (editingId || confirmDeleteId || switchingId || movingDrawingId) return;
|
|
1454
|
+
if (activeDrawing?.id !== drawing.id) handleSelect(drawing);
|
|
1455
|
+
},
|
|
1456
|
+
style: {
|
|
1457
|
+
padding: "10px 12px",
|
|
1458
|
+
display: "flex",
|
|
1459
|
+
alignItems: "center",
|
|
1460
|
+
gap: "12px",
|
|
1461
|
+
borderRadius: "8px",
|
|
1462
|
+
marginBottom: "4px",
|
|
1463
|
+
cursor: draggingDrawingId ? "grabbing" : editingId || confirmDeleteId || switchingId ? "default" : "pointer",
|
|
1464
|
+
backgroundColor: activeDrawing?.id === drawing.id ? "var(--color-primary-light, rgba(108, 99, 255, 0.1))" : "transparent",
|
|
1465
|
+
transition: "background-color 0.15s",
|
|
1466
|
+
opacity: draggingDrawingId === drawing.id ? 0.4 : switchingId && switchingId !== drawing.id ? 0.5 : 1
|
|
1467
|
+
},
|
|
1468
|
+
children: [
|
|
1469
|
+
renderThumbnail && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
1470
|
+
width: "64px",
|
|
1471
|
+
height: "48px",
|
|
1472
|
+
flexShrink: 0,
|
|
1473
|
+
borderRadius: "4px",
|
|
1474
|
+
overflow: "hidden",
|
|
1475
|
+
border: "1px solid var(--default-border-color, #e0e0e0)",
|
|
1476
|
+
backgroundColor: "#fff",
|
|
1477
|
+
display: "flex",
|
|
1478
|
+
alignItems: "center",
|
|
1479
|
+
justifyContent: "center"
|
|
1480
|
+
}, children: renderThumbnail(drawing) }),
|
|
1481
|
+
/* @__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: [
|
|
1482
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1483
|
+
"input",
|
|
1484
|
+
{
|
|
1485
|
+
type: "text",
|
|
1486
|
+
value: editName,
|
|
1487
|
+
onChange: (e) => setEditName(e.target.value),
|
|
1488
|
+
onKeyDown: (e) => {
|
|
1489
|
+
if (e.key === "Enter") handleSaveEdit();
|
|
1490
|
+
if (e.key === "Escape") handleCancelEdit();
|
|
1491
|
+
},
|
|
1492
|
+
onClick: (e) => e.stopPropagation(),
|
|
1493
|
+
autoFocus: true,
|
|
1494
|
+
style: {
|
|
1495
|
+
flex: 1,
|
|
1496
|
+
padding: "4px 8px",
|
|
1497
|
+
fontSize: "14px",
|
|
1498
|
+
border: "1px solid var(--color-primary, #6c63ff)",
|
|
1499
|
+
borderRadius: "4px",
|
|
1500
|
+
outline: "none"
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
),
|
|
1504
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1505
|
+
"button",
|
|
1506
|
+
{
|
|
1507
|
+
onClick: (e) => {
|
|
1508
|
+
e.stopPropagation();
|
|
1509
|
+
handleSaveEdit();
|
|
1510
|
+
},
|
|
1511
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "var(--color-primary, #6c63ff)", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1512
|
+
children: t.save
|
|
1513
|
+
}
|
|
1514
|
+
),
|
|
1515
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1516
|
+
"button",
|
|
1517
|
+
{
|
|
1518
|
+
onClick: (e) => {
|
|
1519
|
+
e.stopPropagation();
|
|
1520
|
+
handleCancelEdit();
|
|
1521
|
+
},
|
|
1522
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1523
|
+
children: t.cancel
|
|
1524
|
+
}
|
|
1525
|
+
)
|
|
1526
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1527
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
|
|
1528
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1529
|
+
"span",
|
|
1530
|
+
{
|
|
1531
|
+
onClick: (e) => {
|
|
1532
|
+
e.stopPropagation();
|
|
1533
|
+
handleStartEdit(drawing);
|
|
1534
|
+
},
|
|
1535
|
+
style: {
|
|
1536
|
+
fontWeight: activeDrawing?.id === drawing.id ? 600 : 400,
|
|
1537
|
+
fontSize: "14px",
|
|
1538
|
+
overflow: "hidden",
|
|
1539
|
+
textOverflow: "ellipsis",
|
|
1540
|
+
whiteSpace: "nowrap",
|
|
1541
|
+
cursor: "text"
|
|
1542
|
+
},
|
|
1543
|
+
title: t.rename,
|
|
1544
|
+
children: [
|
|
1545
|
+
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 " : "",
|
|
1546
|
+
drawing.name
|
|
1547
|
+
]
|
|
1548
|
+
}
|
|
1549
|
+
),
|
|
1550
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1551
|
+
"button",
|
|
1552
|
+
{
|
|
1553
|
+
onClick: (e) => {
|
|
1554
|
+
e.stopPropagation();
|
|
1555
|
+
handleStartEdit(drawing);
|
|
1556
|
+
},
|
|
1557
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "0 2px", fontSize: "12px", opacity: 0.4, flexShrink: 0 },
|
|
1558
|
+
title: t.rename,
|
|
1559
|
+
children: "\u270F\uFE0F"
|
|
1560
|
+
}
|
|
1561
|
+
)
|
|
1562
|
+
] }),
|
|
1563
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { fontSize: "11px", color: "var(--text-secondary-color, #888)", marginTop: "1px" }, children: [
|
|
1564
|
+
t.modified,
|
|
1565
|
+
": ",
|
|
1566
|
+
formatDate(drawing.updatedAt)
|
|
1567
|
+
] })
|
|
1568
|
+
] }) }),
|
|
1569
|
+
/* @__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: [
|
|
1570
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1571
|
+
"button",
|
|
1572
|
+
{
|
|
1573
|
+
onClick: (e) => {
|
|
1574
|
+
e.stopPropagation();
|
|
1575
|
+
handleDelete(drawing.id);
|
|
1576
|
+
},
|
|
1577
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "#dc3545", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1578
|
+
children: t.delete
|
|
1579
|
+
}
|
|
1580
|
+
),
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1582
|
+
"button",
|
|
1583
|
+
{
|
|
1584
|
+
onClick: (e) => {
|
|
1585
|
+
e.stopPropagation();
|
|
1586
|
+
setConfirmDeleteId(null);
|
|
1587
|
+
},
|
|
1588
|
+
style: { padding: "4px 10px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1589
|
+
children: t.cancel
|
|
1590
|
+
}
|
|
1591
|
+
)
|
|
1592
|
+
] }) : movingDrawingId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", flexDirection: "column", gap: "2px", fontSize: "12px" }, children: [
|
|
1593
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1594
|
+
"button",
|
|
1595
|
+
{
|
|
1596
|
+
onClick: () => handleMoveToFolder(drawing.id, null),
|
|
1597
|
+
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" },
|
|
1598
|
+
children: t.moveToRoot
|
|
1599
|
+
}
|
|
1600
|
+
),
|
|
1601
|
+
folders.map((folder) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1602
|
+
"button",
|
|
1603
|
+
{
|
|
1604
|
+
onClick: () => handleMoveToFolder(drawing.id, folder.id),
|
|
1605
|
+
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" },
|
|
1606
|
+
children: [
|
|
1607
|
+
"\u{1F4C1} ",
|
|
1608
|
+
folder.name
|
|
1609
|
+
]
|
|
1610
|
+
},
|
|
1611
|
+
folder.id
|
|
1612
|
+
)),
|
|
1613
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1614
|
+
"button",
|
|
1615
|
+
{
|
|
1616
|
+
onClick: () => setMovingDrawingId(null),
|
|
1617
|
+
style: { padding: "3px 8px", border: "none", cursor: "pointer", backgroundColor: "transparent", color: "var(--text-secondary-color, #888)", textAlign: "left" },
|
|
1618
|
+
children: t.cancel
|
|
1619
|
+
}
|
|
1620
|
+
)
|
|
1621
|
+
] }) : editingId !== drawing.id && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1622
|
+
folders.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1623
|
+
"button",
|
|
1624
|
+
{
|
|
1625
|
+
onClick: (e) => {
|
|
1626
|
+
e.stopPropagation();
|
|
1627
|
+
setMovingDrawingId(drawing.id);
|
|
1628
|
+
},
|
|
1629
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1630
|
+
title: t.moveToFolder,
|
|
1631
|
+
children: "\u{1F4C1}"
|
|
1632
|
+
}
|
|
1633
|
+
),
|
|
1634
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1635
|
+
"button",
|
|
1636
|
+
{
|
|
1637
|
+
onClick: (e) => {
|
|
1638
|
+
e.stopPropagation();
|
|
1639
|
+
exportDrawingAsExcalidraw(drawing.id);
|
|
1640
|
+
},
|
|
1641
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1642
|
+
title: t.exportDrawing,
|
|
1643
|
+
children: "\u{1F4BE}"
|
|
1644
|
+
}
|
|
1645
|
+
),
|
|
1646
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1647
|
+
"button",
|
|
1648
|
+
{
|
|
1649
|
+
onClick: (e) => {
|
|
1650
|
+
e.stopPropagation();
|
|
1651
|
+
setConfirmDeleteId(drawing.id);
|
|
1652
|
+
},
|
|
1653
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "4px", fontSize: "14px", opacity: 0.5 },
|
|
1654
|
+
title: t.delete,
|
|
1655
|
+
disabled: drawings.length <= 1,
|
|
1656
|
+
children: "\u{1F5D1}\uFE0F"
|
|
1657
|
+
}
|
|
1658
|
+
)
|
|
1659
|
+
] }) })
|
|
1660
|
+
]
|
|
1661
|
+
},
|
|
1662
|
+
drawing.id
|
|
1663
|
+
);
|
|
1664
|
+
const renderFolderGroup = (folder) => {
|
|
1665
|
+
const folderDrawings = drawingsByFolder[folder.id] || [];
|
|
1666
|
+
const isExpanded = expandedFolders.has(folder.id);
|
|
1667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { marginBottom: "4px" }, children: [
|
|
1668
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1669
|
+
"div",
|
|
1670
|
+
{
|
|
1671
|
+
onClick: () => toggleFolder(folder.id),
|
|
1672
|
+
onDragOver: (e) => {
|
|
1673
|
+
if (!draggingDrawingId) return;
|
|
1674
|
+
e.preventDefault();
|
|
1675
|
+
e.dataTransfer.dropEffect = "move";
|
|
1676
|
+
setDropTargetFolderId(folder.id);
|
|
1677
|
+
},
|
|
1678
|
+
onDragLeave: () => {
|
|
1679
|
+
if (dropTargetFolderId === folder.id) setDropTargetFolderId(null);
|
|
1680
|
+
},
|
|
1681
|
+
onDrop: (e) => {
|
|
1682
|
+
e.preventDefault();
|
|
1683
|
+
if (draggingDrawingId) {
|
|
1684
|
+
handleMoveToFolder(draggingDrawingId, folder.id);
|
|
1685
|
+
setDraggingDrawingId(null);
|
|
1686
|
+
setDropTargetFolderId(null);
|
|
1687
|
+
setExpandedFolders((prev) => /* @__PURE__ */ new Set([...prev, folder.id]));
|
|
1688
|
+
}
|
|
1689
|
+
},
|
|
1690
|
+
style: {
|
|
1691
|
+
padding: "8px 12px",
|
|
1692
|
+
display: "flex",
|
|
1693
|
+
alignItems: "center",
|
|
1694
|
+
gap: "8px",
|
|
1695
|
+
borderRadius: "8px",
|
|
1696
|
+
cursor: "pointer",
|
|
1697
|
+
backgroundColor: dropTargetFolderId === folder.id ? "var(--color-primary-light, rgba(108, 99, 255, 0.2))" : "var(--color-surface-mid, rgba(0, 0, 0, 0.03))",
|
|
1698
|
+
border: dropTargetFolderId === folder.id ? "2px dashed var(--color-primary, #6c63ff)" : "2px solid transparent",
|
|
1699
|
+
transition: "background-color 0.15s, border-color 0.15s"
|
|
1700
|
+
},
|
|
1701
|
+
children: [
|
|
1702
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: "12px", width: "16px", textAlign: "center", flexShrink: 0 }, children: isExpanded ? "\u25BC" : "\u25B6" }),
|
|
1703
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: "16px", flexShrink: 0 }, children: busyFolderId === folder.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { display: "inline-block", animation: "spin 1s linear infinite" }, children: "\u23F3" }) : "\u{1F4C1}" }),
|
|
1704
|
+
/* @__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: [
|
|
1705
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1706
|
+
"input",
|
|
1707
|
+
{
|
|
1708
|
+
type: "text",
|
|
1709
|
+
value: editFolderName,
|
|
1710
|
+
onChange: (e) => setEditFolderName(e.target.value),
|
|
1711
|
+
onKeyDown: (e) => {
|
|
1712
|
+
if (e.key === "Enter") handleSaveFolderEdit();
|
|
1713
|
+
if (e.key === "Escape") {
|
|
1714
|
+
setEditingFolderId(null);
|
|
1715
|
+
setEditFolderName("");
|
|
1716
|
+
}
|
|
1717
|
+
},
|
|
1718
|
+
autoFocus: true,
|
|
1719
|
+
style: { flex: 1, padding: "2px 6px", fontSize: "14px", border: "1px solid var(--color-primary, #6c63ff)", borderRadius: "4px", outline: "none" }
|
|
1720
|
+
}
|
|
1721
|
+
),
|
|
1722
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1723
|
+
"button",
|
|
1724
|
+
{
|
|
1725
|
+
onClick: handleSaveFolderEdit,
|
|
1726
|
+
style: { padding: "2px 8px", fontSize: "12px", backgroundColor: "var(--color-primary, #6c63ff)", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1727
|
+
children: t.save
|
|
1728
|
+
}
|
|
1729
|
+
)
|
|
1730
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { fontWeight: 600, fontSize: "14px" }, children: [
|
|
1731
|
+
folder.name,
|
|
1732
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { fontWeight: 400, fontSize: "12px", color: "var(--text-secondary-color, #888)", marginLeft: "6px" }, children: [
|
|
1733
|
+
"(",
|
|
1734
|
+
folderDrawings.length,
|
|
1735
|
+
")"
|
|
1736
|
+
] })
|
|
1737
|
+
] }) }),
|
|
1738
|
+
confirmDeleteFolderId === folder.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", gap: "4px" }, children: [
|
|
1739
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1740
|
+
"button",
|
|
1741
|
+
{
|
|
1742
|
+
onClick: () => handleDeleteFolder(folder.id),
|
|
1743
|
+
style: { padding: "2px 8px", fontSize: "12px", backgroundColor: "#dc3545", color: "#fff", border: "none", borderRadius: "4px", cursor: "pointer" },
|
|
1744
|
+
children: t.delete
|
|
1745
|
+
}
|
|
1746
|
+
),
|
|
1747
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1748
|
+
"button",
|
|
1749
|
+
{
|
|
1750
|
+
onClick: () => setConfirmDeleteFolderId(null),
|
|
1751
|
+
style: { padding: "2px 8px", fontSize: "12px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "4px", cursor: "pointer", color: "inherit" },
|
|
1752
|
+
children: t.cancel
|
|
1753
|
+
}
|
|
1754
|
+
)
|
|
1755
|
+
] }) : editingFolderId !== folder.id && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", gap: "2px" }, children: [
|
|
1756
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1757
|
+
"button",
|
|
1758
|
+
{
|
|
1759
|
+
onClick: () => {
|
|
1760
|
+
setEditingFolderId(folder.id);
|
|
1761
|
+
setEditFolderName(folder.name);
|
|
1762
|
+
},
|
|
1763
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "2px", fontSize: "12px", opacity: 0.5 },
|
|
1764
|
+
title: t.renameFolder,
|
|
1765
|
+
children: "\u270F\uFE0F"
|
|
1766
|
+
}
|
|
1767
|
+
),
|
|
1768
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1769
|
+
"button",
|
|
1770
|
+
{
|
|
1771
|
+
onClick: () => setConfirmDeleteFolderId(folder.id),
|
|
1772
|
+
style: { background: "none", border: "none", cursor: "pointer", padding: "2px", fontSize: "12px", opacity: 0.5 },
|
|
1773
|
+
title: t.deleteFolder,
|
|
1774
|
+
children: "\u{1F5D1}\uFE0F"
|
|
1775
|
+
}
|
|
1776
|
+
)
|
|
1777
|
+
] })
|
|
1778
|
+
]
|
|
1779
|
+
}
|
|
1780
|
+
),
|
|
1781
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { paddingLeft: "24px", marginTop: "2px" }, children: [
|
|
1782
|
+
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 }),
|
|
1783
|
+
folderDrawings.map(renderDrawingRow)
|
|
1784
|
+
] })
|
|
1785
|
+
] }, folder.id);
|
|
1786
|
+
};
|
|
1210
1787
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1211
1788
|
"div",
|
|
1212
1789
|
{
|
|
@@ -1262,181 +1839,65 @@ var DrawingsDialog = ({
|
|
|
1262
1839
|
]
|
|
1263
1840
|
}
|
|
1264
1841
|
),
|
|
1842
|
+
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)(
|
|
1843
|
+
"input",
|
|
1844
|
+
{
|
|
1845
|
+
type: "text",
|
|
1846
|
+
value: searchQuery,
|
|
1847
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
1848
|
+
placeholder: "\u{1F50D}",
|
|
1849
|
+
style: {
|
|
1850
|
+
width: "100%",
|
|
1851
|
+
padding: "6px 12px",
|
|
1852
|
+
fontSize: "14px",
|
|
1853
|
+
border: "1px solid var(--default-border-color, #e0e0e0)",
|
|
1854
|
+
borderRadius: "6px",
|
|
1855
|
+
outline: "none",
|
|
1856
|
+
backgroundColor: "transparent",
|
|
1857
|
+
color: "inherit",
|
|
1858
|
+
boxSizing: "border-box"
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
) }),
|
|
1265
1862
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { flex: 1, overflow: "auto" }, children: [
|
|
1266
|
-
drawings.length
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
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: [
|
|
1863
|
+
isRefreshing && drawings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "24px 20px", textAlign: "center", color: "var(--text-secondary-color, #666)" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { display: "inline-block", animation: "spin 1s linear infinite", fontSize: "24px" }, children: "\u23F3" }) }) : drawings.length > 0 || folders.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "8px 20px 0" }, children: [
|
|
1864
|
+
filteredFolders.map(renderFolderGroup),
|
|
1865
|
+
draggingDrawingId && folders.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1866
|
+
"div",
|
|
1867
|
+
{
|
|
1868
|
+
onDragOver: (e) => {
|
|
1869
|
+
e.preventDefault();
|
|
1870
|
+
e.dataTransfer.dropEffect = "move";
|
|
1871
|
+
setDropTargetFolderId("__root__");
|
|
1872
|
+
},
|
|
1873
|
+
onDragLeave: () => {
|
|
1874
|
+
if (dropTargetFolderId === "__root__") setDropTargetFolderId(null);
|
|
1875
|
+
},
|
|
1876
|
+
onDrop: (e) => {
|
|
1877
|
+
e.preventDefault();
|
|
1878
|
+
if (draggingDrawingId) {
|
|
1879
|
+
handleMoveToFolder(draggingDrawingId, null);
|
|
1880
|
+
setDraggingDrawingId(null);
|
|
1881
|
+
setDropTargetFolderId(null);
|
|
1882
|
+
}
|
|
1883
|
+
},
|
|
1884
|
+
style: {
|
|
1885
|
+
padding: "8px 12px",
|
|
1886
|
+
marginBottom: "4px",
|
|
1887
|
+
borderRadius: "8px",
|
|
1888
|
+
textAlign: "center",
|
|
1889
|
+
fontSize: "12px",
|
|
1890
|
+
color: "var(--text-secondary-color, #888)",
|
|
1891
|
+
backgroundColor: dropTargetFolderId === "__root__" ? "var(--color-primary-light, rgba(108, 99, 255, 0.2))" : "transparent",
|
|
1892
|
+
border: "2px dashed var(--default-border-color, #ccc)",
|
|
1893
|
+
borderColor: dropTargetFolderId === "__root__" ? "var(--color-primary, #6c63ff)" : "var(--default-border-color, #ccc)",
|
|
1894
|
+
transition: "background-color 0.15s, border-color 0.15s"
|
|
1895
|
+
},
|
|
1896
|
+
children: t.moveToRoot
|
|
1897
|
+
}
|
|
1898
|
+
),
|
|
1899
|
+
rootDrawings.map(renderDrawingRow)
|
|
1900
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "24px 20px", textAlign: "center", color: "var(--text-secondary-color, #666)" }, children: [
|
|
1440
1901
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t.noDrawingsYet }),
|
|
1441
1902
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t.clickNewToStart })
|
|
1442
1903
|
] }),
|
|
@@ -1448,7 +1909,7 @@ var DrawingsDialog = ({
|
|
|
1448
1909
|
icon: "\u{1F4C4}",
|
|
1449
1910
|
label: t.createNewDrawing,
|
|
1450
1911
|
description: t.createNewDrawingDesc,
|
|
1451
|
-
onClick: handleCreate,
|
|
1912
|
+
onClick: () => handleCreate(),
|
|
1452
1913
|
primary: true
|
|
1453
1914
|
}
|
|
1454
1915
|
),
|
|
@@ -1460,6 +1921,61 @@ var DrawingsDialog = ({
|
|
|
1460
1921
|
description: t.openFromFileDesc,
|
|
1461
1922
|
onClick: importExcalidrawFile
|
|
1462
1923
|
}
|
|
1924
|
+
),
|
|
1925
|
+
creatingFolder ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center", padding: "4px 0" }, children: [
|
|
1926
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1927
|
+
"input",
|
|
1928
|
+
{
|
|
1929
|
+
ref: newFolderInputRef,
|
|
1930
|
+
type: "text",
|
|
1931
|
+
value: newFolderName,
|
|
1932
|
+
onChange: (e) => setNewFolderName(e.target.value),
|
|
1933
|
+
onKeyDown: (e) => {
|
|
1934
|
+
if (e.key === "Enter") handleCreateFolder();
|
|
1935
|
+
if (e.key === "Escape") {
|
|
1936
|
+
setCreatingFolder(false);
|
|
1937
|
+
setNewFolderName("");
|
|
1938
|
+
}
|
|
1939
|
+
},
|
|
1940
|
+
placeholder: t.newFolderName,
|
|
1941
|
+
style: {
|
|
1942
|
+
flex: 1,
|
|
1943
|
+
padding: "8px 12px",
|
|
1944
|
+
fontSize: "14px",
|
|
1945
|
+
border: "1px solid var(--color-primary, #6c63ff)",
|
|
1946
|
+
borderRadius: "8px",
|
|
1947
|
+
outline: "none"
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
),
|
|
1951
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1952
|
+
"button",
|
|
1953
|
+
{
|
|
1954
|
+
onClick: handleCreateFolder,
|
|
1955
|
+
disabled: busyFolderId === "__creating__",
|
|
1956
|
+
style: { padding: "8px 16px", fontSize: "14px", backgroundColor: "var(--color-primary, #6c63ff)", color: "#fff", border: "none", borderRadius: "8px", cursor: "pointer", opacity: busyFolderId === "__creating__" ? 0.6 : 1 },
|
|
1957
|
+
children: busyFolderId === "__creating__" ? "\u23F3" : t.save
|
|
1958
|
+
}
|
|
1959
|
+
),
|
|
1960
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1961
|
+
"button",
|
|
1962
|
+
{
|
|
1963
|
+
onClick: () => {
|
|
1964
|
+
setCreatingFolder(false);
|
|
1965
|
+
setNewFolderName("");
|
|
1966
|
+
},
|
|
1967
|
+
style: { padding: "8px 16px", fontSize: "14px", backgroundColor: "transparent", border: "1px solid var(--default-border-color, #ccc)", borderRadius: "8px", cursor: "pointer", color: "inherit" },
|
|
1968
|
+
children: t.cancel
|
|
1969
|
+
}
|
|
1970
|
+
)
|
|
1971
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1972
|
+
ActionButton,
|
|
1973
|
+
{
|
|
1974
|
+
icon: "\u{1F4C1}",
|
|
1975
|
+
label: t.createFolder,
|
|
1976
|
+
description: "",
|
|
1977
|
+
onClick: () => setCreatingFolder(true)
|
|
1978
|
+
}
|
|
1463
1979
|
)
|
|
1464
1980
|
] }),
|
|
1465
1981
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: sectionHeaderStyle, children: t.sectionWorkspace }),
|
|
@@ -1706,16 +2222,22 @@ function WorkspacePlugin(props) {
|
|
|
1706
2222
|
addDrawingToWorkspace,
|
|
1707
2223
|
closeDB,
|
|
1708
2224
|
createDrawing,
|
|
2225
|
+
createFolder,
|
|
1709
2226
|
deleteDrawing,
|
|
2227
|
+
deleteFolder,
|
|
1710
2228
|
duplicateDrawing,
|
|
1711
2229
|
getAllDrawings,
|
|
2230
|
+
getAllFolders,
|
|
1712
2231
|
getDB,
|
|
1713
2232
|
getDrawing,
|
|
2233
|
+
getFolder,
|
|
1714
2234
|
getOrCreateDefaultWorkspace,
|
|
1715
2235
|
getTranslations,
|
|
1716
2236
|
getWorkspace,
|
|
1717
2237
|
isLanguageSupported,
|
|
2238
|
+
moveDrawingToFolder,
|
|
1718
2239
|
removeDrawingFromWorkspace,
|
|
2240
|
+
renameFolder,
|
|
1719
2241
|
setActiveDrawing,
|
|
1720
2242
|
updateDrawing,
|
|
1721
2243
|
updateWorkspace,
|