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.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 = 1;
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.jsx)("div", { style: { padding: "8px 20px 0" }, children: drawings.map((drawing) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1267
- "div",
1268
- {
1269
- onClick: () => {
1270
- if (editingId || confirmDeleteId) return;
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,