rita-workspace 0.5.33 → 0.5.35

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 CHANGED
@@ -6,6 +6,8 @@ interface Drawing {
6
6
  id: string;
7
7
  name: string;
8
8
  folderId?: string | null;
9
+ /** Manual sort position. Lower = earlier in list. Falls back to createdAt when unset. */
10
+ position?: number;
9
11
  elements: unknown[];
10
12
  appState: Record<string, unknown>;
11
13
  files: Record<string, unknown>;
@@ -64,6 +66,12 @@ declare function updateDrawing(id: string, updates: Partial<Omit<Drawing, 'id' |
64
66
  declare function deleteDrawing(id: string): Promise<boolean>;
65
67
  declare function duplicateDrawing(id: string, newName?: string): Promise<Drawing | undefined>;
66
68
  declare function moveDrawingToFolder(drawingId: string, folderId: string | null): Promise<Drawing | undefined>;
69
+ /**
70
+ * Re-number `position` for the given drawing IDs in the order provided (0..N-1).
71
+ * Drawings not in `orderedIds` are left untouched (caller should pass the full
72
+ * sorted slice that the user reordered, e.g. all root drawings or all in a folder).
73
+ */
74
+ declare function reorderDrawings(orderedIds: string[]): Promise<void>;
67
75
 
68
76
  declare function createFolder(name: string): Promise<Folder>;
69
77
  declare function getFolder(id: string): Promise<Folder | undefined>;
@@ -123,6 +131,8 @@ interface Translations {
123
131
  newFolderName: string;
124
132
  backupReminder: string;
125
133
  days: string;
134
+ autoStartLabel: string;
135
+ autoStartDesc: string;
126
136
  shortcutNewDrawing: string;
127
137
  }
128
138
  declare function getTranslations(langCode?: string): Translations;
@@ -147,6 +157,9 @@ interface WorkspaceContextValue {
147
157
  renameFolder: (id: string, name: string) => Promise<void>;
148
158
  deleteFolder: (id: string) => Promise<void>;
149
159
  moveDrawingToFolder: (drawingId: string, folderId: string | null) => Promise<void>;
160
+ /** Re-numbers `position` for the given drawing IDs in order. Use the full ordered slice
161
+ * the user reordered (e.g. all root drawings, or all drawings in a folder). */
162
+ reorderDrawings: (orderedIds: string[]) => Promise<void>;
150
163
  saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
151
164
  saveDrawingById: (id: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
152
165
  refreshDrawings: () => Promise<void>;
@@ -388,4 +401,4 @@ interface WorkspacePluginProps {
388
401
  */
389
402
  declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
390
403
 
391
- export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
404
+ export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, reorderDrawings, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ interface Drawing {
6
6
  id: string;
7
7
  name: string;
8
8
  folderId?: string | null;
9
+ /** Manual sort position. Lower = earlier in list. Falls back to createdAt when unset. */
10
+ position?: number;
9
11
  elements: unknown[];
10
12
  appState: Record<string, unknown>;
11
13
  files: Record<string, unknown>;
@@ -64,6 +66,12 @@ declare function updateDrawing(id: string, updates: Partial<Omit<Drawing, 'id' |
64
66
  declare function deleteDrawing(id: string): Promise<boolean>;
65
67
  declare function duplicateDrawing(id: string, newName?: string): Promise<Drawing | undefined>;
66
68
  declare function moveDrawingToFolder(drawingId: string, folderId: string | null): Promise<Drawing | undefined>;
69
+ /**
70
+ * Re-number `position` for the given drawing IDs in the order provided (0..N-1).
71
+ * Drawings not in `orderedIds` are left untouched (caller should pass the full
72
+ * sorted slice that the user reordered, e.g. all root drawings or all in a folder).
73
+ */
74
+ declare function reorderDrawings(orderedIds: string[]): Promise<void>;
67
75
 
68
76
  declare function createFolder(name: string): Promise<Folder>;
69
77
  declare function getFolder(id: string): Promise<Folder | undefined>;
@@ -123,6 +131,8 @@ interface Translations {
123
131
  newFolderName: string;
124
132
  backupReminder: string;
125
133
  days: string;
134
+ autoStartLabel: string;
135
+ autoStartDesc: string;
126
136
  shortcutNewDrawing: string;
127
137
  }
128
138
  declare function getTranslations(langCode?: string): Translations;
@@ -147,6 +157,9 @@ interface WorkspaceContextValue {
147
157
  renameFolder: (id: string, name: string) => Promise<void>;
148
158
  deleteFolder: (id: string) => Promise<void>;
149
159
  moveDrawingToFolder: (drawingId: string, folderId: string | null) => Promise<void>;
160
+ /** Re-numbers `position` for the given drawing IDs in order. Use the full ordered slice
161
+ * the user reordered (e.g. all root drawings, or all drawings in a folder). */
162
+ reorderDrawings: (orderedIds: string[]) => Promise<void>;
150
163
  saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
151
164
  saveDrawingById: (id: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
152
165
  refreshDrawings: () => Promise<void>;
@@ -388,4 +401,4 @@ interface WorkspacePluginProps {
388
401
  */
389
402
  declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
390
403
 
391
- export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
404
+ export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, reorderDrawings, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
package/dist/index.js CHANGED
@@ -59,6 +59,7 @@ __export(index_exports, {
59
59
  moveDrawingToFolder: () => moveDrawingToFolder,
60
60
  removeDrawingFromWorkspace: () => removeDrawingFromWorkspace,
61
61
  renameFolder: () => renameFolder,
62
+ reorderDrawings: () => reorderDrawings,
62
63
  setActiveDrawing: () => setActiveDrawing,
63
64
  updateDrawing: () => updateDrawing,
64
65
  updateWorkspace: () => updateWorkspace,
@@ -177,6 +178,17 @@ async function duplicateDrawing(id, newName) {
177
178
  async function moveDrawingToFolder(drawingId, folderId) {
178
179
  return updateDrawing(drawingId, { folderId });
179
180
  }
181
+ async function reorderDrawings(orderedIds) {
182
+ const db = await getDB();
183
+ const tx = db.transaction("drawings", "readwrite");
184
+ const store = tx.objectStore("drawings");
185
+ for (let i = 0; i < orderedIds.length; i++) {
186
+ const existing = await store.get(orderedIds[i]);
187
+ if (!existing) continue;
188
+ await store.put({ ...existing, position: i });
189
+ }
190
+ await tx.done;
191
+ }
180
192
 
181
193
  // src/storage/folderStore.ts
182
194
  var import_nanoid2 = require("nanoid");
@@ -315,8 +327,8 @@ var sv = {
315
327
  // Actions with descriptions
316
328
  createNewDrawing: "Skapa ny ritning",
317
329
  createNewDrawingDesc: "Skapar en tom ritning i din arbetsyta",
318
- openFromFile: "\xD6ppna ritning fr\xE5n fil",
319
- openFromFileDesc: "\xD6ppnar en sparad ritning fr\xE5n din dator",
330
+ openFromFile: "Importera ritning fr\xE5n fil",
331
+ openFromFileDesc: "Importerar en sparad ritning fr\xE5n din dator",
320
332
  saveAllBackup: "Spara alla ritningar (backup)",
321
333
  saveAllBackupDesc: "Ladda ner hela din arbetsyta som backup",
322
334
  loadBackup: "L\xE4s in sparad arbetsyta",
@@ -342,6 +354,9 @@ var sv = {
342
354
  // Backup reminder
343
355
  backupReminder: "Senaste backup:",
344
356
  days: "dagar sedan",
357
+ // Auto-start
358
+ autoStartLabel: "Starta Rita i arbetsl\xE4ge",
359
+ autoStartDesc: "Aktivera arbetsl\xE4ge automatiskt n\xE4r Rita \xF6ppnas",
345
360
  // Shortcuts
346
361
  shortcutNewDrawing: "Ctrl+Alt+N"
347
362
  };
@@ -365,8 +380,8 @@ var en = {
365
380
  // Actions with descriptions
366
381
  createNewDrawing: "Create new drawing",
367
382
  createNewDrawingDesc: "Creates an empty drawing in your workspace",
368
- openFromFile: "Open drawing from file",
369
- openFromFileDesc: "Opens a saved drawing from your computer",
383
+ openFromFile: "Import drawing from file",
384
+ openFromFileDesc: "Imports a saved drawing from your computer",
370
385
  saveAllBackup: "Save all drawings (backup)",
371
386
  saveAllBackupDesc: "Download your entire workspace as a backup",
372
387
  loadBackup: "Load saved workspace",
@@ -392,6 +407,9 @@ var en = {
392
407
  // Backup reminder
393
408
  backupReminder: "Last backup:",
394
409
  days: "days ago",
410
+ // Auto-start
411
+ autoStartLabel: "Start Rita in workspace mode",
412
+ autoStartDesc: "Automatically enable workspace mode when Rita opens",
395
413
  // Shortcuts
396
414
  shortcutNewDrawing: "Ctrl+Alt+N"
397
415
  };
@@ -1251,6 +1269,19 @@ function WorkspaceProvider({ children, lang = "en" }) {
1251
1269
  setError(err instanceof Error ? err.message : "Failed to move drawing");
1252
1270
  }
1253
1271
  }, []);
1272
+ const reorderDrawings2 = (0, import_react.useCallback)(async (orderedIds) => {
1273
+ const positionMap = new Map(orderedIds.map((id, idx) => [id, idx]));
1274
+ setDrawings((prev) => prev.map(
1275
+ (d) => positionMap.has(d.id) ? { ...d, position: positionMap.get(d.id) } : d
1276
+ ));
1277
+ try {
1278
+ await reorderDrawings(orderedIds);
1279
+ broadcastWorkspaceChange();
1280
+ } catch (err) {
1281
+ setError(err instanceof Error ? err.message : "Failed to reorder drawings");
1282
+ refreshDrawingsRef.current();
1283
+ }
1284
+ }, []);
1254
1285
  const value = {
1255
1286
  workspace,
1256
1287
  drawings,
@@ -1270,6 +1301,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
1270
1301
  renameFolder: renameFolder2,
1271
1302
  deleteFolder: deleteFolder2,
1272
1303
  moveDrawingToFolder: moveDrawingToFolder2,
1304
+ reorderDrawings: reorderDrawings2,
1273
1305
  saveCurrentDrawing,
1274
1306
  saveDrawingById,
1275
1307
  refreshDrawings,
@@ -1638,6 +1670,7 @@ var DrawingsDialog = ({
1638
1670
  renameFolder: renameFolder2,
1639
1671
  deleteFolder: deleteFolder2,
1640
1672
  moveDrawingToFolder: moveDrawingToFolder2,
1673
+ reorderDrawings: reorderDrawings2,
1641
1674
  exportWorkspace,
1642
1675
  importWorkspace,
1643
1676
  exportDrawingAsExcalidraw,
@@ -1664,8 +1697,31 @@ var DrawingsDialog = ({
1664
1697
  const [movingDrawingId, setMovingDrawingId] = (0, import_react5.useState)(null);
1665
1698
  const [searchQuery, setSearchQuery] = (0, import_react5.useState)("");
1666
1699
  const [isRefreshing, setIsRefreshing] = (0, import_react5.useState)(false);
1700
+ const [autoStart, setAutoStart] = (0, import_react5.useState)(() => {
1701
+ try {
1702
+ return localStorage.getItem("rita-workspace-auto-start") === "true";
1703
+ } catch {
1704
+ return false;
1705
+ }
1706
+ });
1707
+ const handleToggleAutoStart = (0, import_react5.useCallback)(() => {
1708
+ setAutoStart((prev) => {
1709
+ const next = !prev;
1710
+ try {
1711
+ if (next) {
1712
+ localStorage.setItem("rita-workspace-auto-start", "true");
1713
+ } else {
1714
+ localStorage.removeItem("rita-workspace-auto-start");
1715
+ }
1716
+ } catch {
1717
+ }
1718
+ return next;
1719
+ });
1720
+ }, []);
1667
1721
  const [draggingDrawingId, setDraggingDrawingId] = (0, import_react5.useState)(null);
1668
1722
  const [dropTargetFolderId, setDropTargetFolderId] = (0, import_react5.useState)(null);
1723
+ const [dropTargetDrawingId, setDropTargetDrawingId] = (0, import_react5.useState)(null);
1724
+ const [dropTargetPosition, setDropTargetPosition] = (0, import_react5.useState)(null);
1669
1725
  const [position, setPosition] = (0, import_react5.useState)(null);
1670
1726
  const dragRef = (0, import_react5.useRef)(null);
1671
1727
  const dialogRef = (0, import_react5.useRef)(null);
@@ -1773,6 +1829,28 @@ var DrawingsDialog = ({
1773
1829
  setSelectedId(null);
1774
1830
  moveDrawingToFolder2(drawingId, folderId);
1775
1831
  }, [moveDrawingToFolder2]);
1832
+ const handleReorderDrop = (0, import_react5.useCallback)((draggedId, targetId, pos) => {
1833
+ if (draggedId === targetId) return;
1834
+ const target = drawings.find((d) => d.id === targetId);
1835
+ if (!target) return;
1836
+ const scopeFolderId = target.folderId ?? null;
1837
+ const scope = drawings.filter((d) => (d.folderId ?? null) === scopeFolderId).sort((a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt));
1838
+ const withoutDragged = scope.filter((d) => d.id !== draggedId);
1839
+ const targetIdx = withoutDragged.findIndex((d) => d.id === targetId);
1840
+ if (targetIdx === -1) return;
1841
+ const insertIdx = pos === "before" ? targetIdx : targetIdx + 1;
1842
+ const dragged = drawings.find((d) => d.id === draggedId);
1843
+ if (!dragged) return;
1844
+ if ((dragged.folderId ?? null) !== scopeFolderId) {
1845
+ moveDrawingToFolder2(draggedId, scopeFolderId);
1846
+ }
1847
+ const ordered = [
1848
+ ...withoutDragged.slice(0, insertIdx),
1849
+ dragged,
1850
+ ...withoutDragged.slice(insertIdx)
1851
+ ].map((d) => d.id);
1852
+ reorderDrawings2(ordered);
1853
+ }, [drawings, reorderDrawings2, moveDrawingToFolder2]);
1776
1854
  const toggleFolder = (0, import_react5.useCallback)((folderId) => {
1777
1855
  setExpandedFolders((prev) => {
1778
1856
  const next = new Set(prev);
@@ -1805,7 +1883,9 @@ var DrawingsDialog = ({
1805
1883
  const { rootDrawings, drawingsByFolder, filteredFolders } = (0, import_react5.useMemo)(() => {
1806
1884
  const query = searchQuery.toLowerCase().trim();
1807
1885
  const filtered = query ? drawings.filter((d) => d.name.toLowerCase().includes(query)) : drawings;
1808
- const sorted = [...filtered].sort((a, b) => a.createdAt - b.createdAt);
1886
+ const sorted = [...filtered].sort(
1887
+ (a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt)
1888
+ );
1809
1889
  const root = sorted.filter((d) => !d.folderId);
1810
1890
  const byFolder = {};
1811
1891
  for (const folder of folders) {
@@ -1860,6 +1940,34 @@ var DrawingsDialog = ({
1860
1940
  onDragEnd: () => {
1861
1941
  setDraggingDrawingId(null);
1862
1942
  setDropTargetFolderId(null);
1943
+ setDropTargetDrawingId(null);
1944
+ setDropTargetPosition(null);
1945
+ },
1946
+ onDragOver: (e) => {
1947
+ if (!draggingDrawingId || draggingDrawingId === drawing.id) return;
1948
+ e.preventDefault();
1949
+ e.dataTransfer.dropEffect = "move";
1950
+ const rect = e.currentTarget.getBoundingClientRect();
1951
+ const isBefore = e.clientY < rect.top + rect.height / 2;
1952
+ setDropTargetDrawingId(drawing.id);
1953
+ setDropTargetPosition(isBefore ? "before" : "after");
1954
+ },
1955
+ onDragLeave: (e) => {
1956
+ if (e.currentTarget.contains(e.relatedTarget)) return;
1957
+ if (dropTargetDrawingId === drawing.id) {
1958
+ setDropTargetDrawingId(null);
1959
+ setDropTargetPosition(null);
1960
+ }
1961
+ },
1962
+ onDrop: (e) => {
1963
+ if (!draggingDrawingId || !dropTargetPosition || draggingDrawingId === drawing.id) return;
1964
+ e.preventDefault();
1965
+ e.stopPropagation();
1966
+ handleReorderDrop(draggingDrawingId, drawing.id, dropTargetPosition);
1967
+ setDraggingDrawingId(null);
1968
+ setDropTargetDrawingId(null);
1969
+ setDropTargetPosition(null);
1970
+ setDropTargetFolderId(null);
1863
1971
  },
1864
1972
  onMouseEnter: () => setHoveredId(drawing.id),
1865
1973
  onMouseLeave: () => setHoveredId(null),
@@ -1875,6 +1983,7 @@ var DrawingsDialog = ({
1875
1983
  handleSelect(drawing);
1876
1984
  },
1877
1985
  style: {
1986
+ position: "relative",
1878
1987
  padding: "10px 12px",
1879
1988
  display: "flex",
1880
1989
  alignItems: "center",
@@ -1889,6 +1998,16 @@ var DrawingsDialog = ({
1889
1998
  opacity: draggingDrawingId === drawing.id ? 0.4 : switchingId && switchingId !== drawing.id ? 0.5 : 1
1890
1999
  },
1891
2000
  children: [
2001
+ dropTargetDrawingId === drawing.id && dropTargetPosition && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
2002
+ position: "absolute",
2003
+ left: 4,
2004
+ right: 4,
2005
+ [dropTargetPosition === "before" ? "top" : "bottom"]: -2,
2006
+ height: "3px",
2007
+ backgroundColor: "var(--color-primary, #6c63ff)",
2008
+ borderRadius: "2px",
2009
+ pointerEvents: "none"
2010
+ } }),
1892
2011
  renderThumbnail && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
1893
2012
  width: "64px",
1894
2013
  height: "48px",
@@ -2481,7 +2600,37 @@ var DrawingsDialog = ({
2481
2600
  onClick: importWorkspace
2482
2601
  }
2483
2602
  )
2484
- ] })
2603
+ ] }),
2604
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "0 20px 16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2605
+ "label",
2606
+ {
2607
+ style: {
2608
+ display: "flex",
2609
+ alignItems: "center",
2610
+ gap: "10px",
2611
+ padding: "10px 12px",
2612
+ border: "1px solid var(--default-border-color, #e0e0e0)",
2613
+ borderRadius: "8px",
2614
+ cursor: "pointer",
2615
+ userSelect: "none"
2616
+ },
2617
+ children: [
2618
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2619
+ "input",
2620
+ {
2621
+ type: "checkbox",
2622
+ checked: autoStart,
2623
+ onChange: handleToggleAutoStart,
2624
+ style: { width: "16px", height: "16px", cursor: "pointer", flexShrink: 0 }
2625
+ }
2626
+ ),
2627
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2628
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: "14px", fontWeight: 500 }, children: t.autoStartLabel }),
2629
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: "12px", color: "var(--text-secondary-color, #888)", marginTop: "2px" }, children: t.autoStartDesc })
2630
+ ] })
2631
+ ]
2632
+ }
2633
+ ) })
2485
2634
  ]
2486
2635
  }
2487
2636
  )
@@ -2815,6 +2964,7 @@ function WorkspacePlugin(props) {
2815
2964
  moveDrawingToFolder,
2816
2965
  removeDrawingFromWorkspace,
2817
2966
  renameFolder,
2967
+ reorderDrawings,
2818
2968
  setActiveDrawing,
2819
2969
  updateDrawing,
2820
2970
  updateWorkspace,
package/dist/index.mjs CHANGED
@@ -106,6 +106,17 @@ async function duplicateDrawing(id, newName) {
106
106
  async function moveDrawingToFolder(drawingId, folderId) {
107
107
  return updateDrawing(drawingId, { folderId });
108
108
  }
109
+ async function reorderDrawings(orderedIds) {
110
+ const db = await getDB();
111
+ const tx = db.transaction("drawings", "readwrite");
112
+ const store = tx.objectStore("drawings");
113
+ for (let i = 0; i < orderedIds.length; i++) {
114
+ const existing = await store.get(orderedIds[i]);
115
+ if (!existing) continue;
116
+ await store.put({ ...existing, position: i });
117
+ }
118
+ await tx.done;
119
+ }
109
120
 
110
121
  // src/storage/folderStore.ts
111
122
  import { nanoid as nanoid2 } from "nanoid";
@@ -244,8 +255,8 @@ var sv = {
244
255
  // Actions with descriptions
245
256
  createNewDrawing: "Skapa ny ritning",
246
257
  createNewDrawingDesc: "Skapar en tom ritning i din arbetsyta",
247
- openFromFile: "\xD6ppna ritning fr\xE5n fil",
248
- openFromFileDesc: "\xD6ppnar en sparad ritning fr\xE5n din dator",
258
+ openFromFile: "Importera ritning fr\xE5n fil",
259
+ openFromFileDesc: "Importerar en sparad ritning fr\xE5n din dator",
249
260
  saveAllBackup: "Spara alla ritningar (backup)",
250
261
  saveAllBackupDesc: "Ladda ner hela din arbetsyta som backup",
251
262
  loadBackup: "L\xE4s in sparad arbetsyta",
@@ -271,6 +282,9 @@ var sv = {
271
282
  // Backup reminder
272
283
  backupReminder: "Senaste backup:",
273
284
  days: "dagar sedan",
285
+ // Auto-start
286
+ autoStartLabel: "Starta Rita i arbetsl\xE4ge",
287
+ autoStartDesc: "Aktivera arbetsl\xE4ge automatiskt n\xE4r Rita \xF6ppnas",
274
288
  // Shortcuts
275
289
  shortcutNewDrawing: "Ctrl+Alt+N"
276
290
  };
@@ -294,8 +308,8 @@ var en = {
294
308
  // Actions with descriptions
295
309
  createNewDrawing: "Create new drawing",
296
310
  createNewDrawingDesc: "Creates an empty drawing in your workspace",
297
- openFromFile: "Open drawing from file",
298
- openFromFileDesc: "Opens a saved drawing from your computer",
311
+ openFromFile: "Import drawing from file",
312
+ openFromFileDesc: "Imports a saved drawing from your computer",
299
313
  saveAllBackup: "Save all drawings (backup)",
300
314
  saveAllBackupDesc: "Download your entire workspace as a backup",
301
315
  loadBackup: "Load saved workspace",
@@ -321,6 +335,9 @@ var en = {
321
335
  // Backup reminder
322
336
  backupReminder: "Last backup:",
323
337
  days: "days ago",
338
+ // Auto-start
339
+ autoStartLabel: "Start Rita in workspace mode",
340
+ autoStartDesc: "Automatically enable workspace mode when Rita opens",
324
341
  // Shortcuts
325
342
  shortcutNewDrawing: "Ctrl+Alt+N"
326
343
  };
@@ -1180,6 +1197,19 @@ function WorkspaceProvider({ children, lang = "en" }) {
1180
1197
  setError(err instanceof Error ? err.message : "Failed to move drawing");
1181
1198
  }
1182
1199
  }, []);
1200
+ const reorderDrawings2 = useCallback(async (orderedIds) => {
1201
+ const positionMap = new Map(orderedIds.map((id, idx) => [id, idx]));
1202
+ setDrawings((prev) => prev.map(
1203
+ (d) => positionMap.has(d.id) ? { ...d, position: positionMap.get(d.id) } : d
1204
+ ));
1205
+ try {
1206
+ await reorderDrawings(orderedIds);
1207
+ broadcastWorkspaceChange();
1208
+ } catch (err) {
1209
+ setError(err instanceof Error ? err.message : "Failed to reorder drawings");
1210
+ refreshDrawingsRef.current();
1211
+ }
1212
+ }, []);
1183
1213
  const value = {
1184
1214
  workspace,
1185
1215
  drawings,
@@ -1199,6 +1229,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
1199
1229
  renameFolder: renameFolder2,
1200
1230
  deleteFolder: deleteFolder2,
1201
1231
  moveDrawingToFolder: moveDrawingToFolder2,
1232
+ reorderDrawings: reorderDrawings2,
1202
1233
  saveCurrentDrawing,
1203
1234
  saveDrawingById,
1204
1235
  refreshDrawings,
@@ -1567,6 +1598,7 @@ var DrawingsDialog = ({
1567
1598
  renameFolder: renameFolder2,
1568
1599
  deleteFolder: deleteFolder2,
1569
1600
  moveDrawingToFolder: moveDrawingToFolder2,
1601
+ reorderDrawings: reorderDrawings2,
1570
1602
  exportWorkspace,
1571
1603
  importWorkspace,
1572
1604
  exportDrawingAsExcalidraw,
@@ -1593,8 +1625,31 @@ var DrawingsDialog = ({
1593
1625
  const [movingDrawingId, setMovingDrawingId] = useState4(null);
1594
1626
  const [searchQuery, setSearchQuery] = useState4("");
1595
1627
  const [isRefreshing, setIsRefreshing] = useState4(false);
1628
+ const [autoStart, setAutoStart] = useState4(() => {
1629
+ try {
1630
+ return localStorage.getItem("rita-workspace-auto-start") === "true";
1631
+ } catch {
1632
+ return false;
1633
+ }
1634
+ });
1635
+ const handleToggleAutoStart = useCallback2(() => {
1636
+ setAutoStart((prev) => {
1637
+ const next = !prev;
1638
+ try {
1639
+ if (next) {
1640
+ localStorage.setItem("rita-workspace-auto-start", "true");
1641
+ } else {
1642
+ localStorage.removeItem("rita-workspace-auto-start");
1643
+ }
1644
+ } catch {
1645
+ }
1646
+ return next;
1647
+ });
1648
+ }, []);
1596
1649
  const [draggingDrawingId, setDraggingDrawingId] = useState4(null);
1597
1650
  const [dropTargetFolderId, setDropTargetFolderId] = useState4(null);
1651
+ const [dropTargetDrawingId, setDropTargetDrawingId] = useState4(null);
1652
+ const [dropTargetPosition, setDropTargetPosition] = useState4(null);
1598
1653
  const [position, setPosition] = useState4(null);
1599
1654
  const dragRef = useRef3(null);
1600
1655
  const dialogRef = useRef3(null);
@@ -1702,6 +1757,28 @@ var DrawingsDialog = ({
1702
1757
  setSelectedId(null);
1703
1758
  moveDrawingToFolder2(drawingId, folderId);
1704
1759
  }, [moveDrawingToFolder2]);
1760
+ const handleReorderDrop = useCallback2((draggedId, targetId, pos) => {
1761
+ if (draggedId === targetId) return;
1762
+ const target = drawings.find((d) => d.id === targetId);
1763
+ if (!target) return;
1764
+ const scopeFolderId = target.folderId ?? null;
1765
+ const scope = drawings.filter((d) => (d.folderId ?? null) === scopeFolderId).sort((a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt));
1766
+ const withoutDragged = scope.filter((d) => d.id !== draggedId);
1767
+ const targetIdx = withoutDragged.findIndex((d) => d.id === targetId);
1768
+ if (targetIdx === -1) return;
1769
+ const insertIdx = pos === "before" ? targetIdx : targetIdx + 1;
1770
+ const dragged = drawings.find((d) => d.id === draggedId);
1771
+ if (!dragged) return;
1772
+ if ((dragged.folderId ?? null) !== scopeFolderId) {
1773
+ moveDrawingToFolder2(draggedId, scopeFolderId);
1774
+ }
1775
+ const ordered = [
1776
+ ...withoutDragged.slice(0, insertIdx),
1777
+ dragged,
1778
+ ...withoutDragged.slice(insertIdx)
1779
+ ].map((d) => d.id);
1780
+ reorderDrawings2(ordered);
1781
+ }, [drawings, reorderDrawings2, moveDrawingToFolder2]);
1705
1782
  const toggleFolder = useCallback2((folderId) => {
1706
1783
  setExpandedFolders((prev) => {
1707
1784
  const next = new Set(prev);
@@ -1734,7 +1811,9 @@ var DrawingsDialog = ({
1734
1811
  const { rootDrawings, drawingsByFolder, filteredFolders } = useMemo(() => {
1735
1812
  const query = searchQuery.toLowerCase().trim();
1736
1813
  const filtered = query ? drawings.filter((d) => d.name.toLowerCase().includes(query)) : drawings;
1737
- const sorted = [...filtered].sort((a, b) => a.createdAt - b.createdAt);
1814
+ const sorted = [...filtered].sort(
1815
+ (a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt)
1816
+ );
1738
1817
  const root = sorted.filter((d) => !d.folderId);
1739
1818
  const byFolder = {};
1740
1819
  for (const folder of folders) {
@@ -1789,6 +1868,34 @@ var DrawingsDialog = ({
1789
1868
  onDragEnd: () => {
1790
1869
  setDraggingDrawingId(null);
1791
1870
  setDropTargetFolderId(null);
1871
+ setDropTargetDrawingId(null);
1872
+ setDropTargetPosition(null);
1873
+ },
1874
+ onDragOver: (e) => {
1875
+ if (!draggingDrawingId || draggingDrawingId === drawing.id) return;
1876
+ e.preventDefault();
1877
+ e.dataTransfer.dropEffect = "move";
1878
+ const rect = e.currentTarget.getBoundingClientRect();
1879
+ const isBefore = e.clientY < rect.top + rect.height / 2;
1880
+ setDropTargetDrawingId(drawing.id);
1881
+ setDropTargetPosition(isBefore ? "before" : "after");
1882
+ },
1883
+ onDragLeave: (e) => {
1884
+ if (e.currentTarget.contains(e.relatedTarget)) return;
1885
+ if (dropTargetDrawingId === drawing.id) {
1886
+ setDropTargetDrawingId(null);
1887
+ setDropTargetPosition(null);
1888
+ }
1889
+ },
1890
+ onDrop: (e) => {
1891
+ if (!draggingDrawingId || !dropTargetPosition || draggingDrawingId === drawing.id) return;
1892
+ e.preventDefault();
1893
+ e.stopPropagation();
1894
+ handleReorderDrop(draggingDrawingId, drawing.id, dropTargetPosition);
1895
+ setDraggingDrawingId(null);
1896
+ setDropTargetDrawingId(null);
1897
+ setDropTargetPosition(null);
1898
+ setDropTargetFolderId(null);
1792
1899
  },
1793
1900
  onMouseEnter: () => setHoveredId(drawing.id),
1794
1901
  onMouseLeave: () => setHoveredId(null),
@@ -1804,6 +1911,7 @@ var DrawingsDialog = ({
1804
1911
  handleSelect(drawing);
1805
1912
  },
1806
1913
  style: {
1914
+ position: "relative",
1807
1915
  padding: "10px 12px",
1808
1916
  display: "flex",
1809
1917
  alignItems: "center",
@@ -1818,6 +1926,16 @@ var DrawingsDialog = ({
1818
1926
  opacity: draggingDrawingId === drawing.id ? 0.4 : switchingId && switchingId !== drawing.id ? 0.5 : 1
1819
1927
  },
1820
1928
  children: [
1929
+ dropTargetDrawingId === drawing.id && dropTargetPosition && /* @__PURE__ */ jsx6("div", { style: {
1930
+ position: "absolute",
1931
+ left: 4,
1932
+ right: 4,
1933
+ [dropTargetPosition === "before" ? "top" : "bottom"]: -2,
1934
+ height: "3px",
1935
+ backgroundColor: "var(--color-primary, #6c63ff)",
1936
+ borderRadius: "2px",
1937
+ pointerEvents: "none"
1938
+ } }),
1821
1939
  renderThumbnail && /* @__PURE__ */ jsx6("div", { style: {
1822
1940
  width: "64px",
1823
1941
  height: "48px",
@@ -2410,7 +2528,37 @@ var DrawingsDialog = ({
2410
2528
  onClick: importWorkspace
2411
2529
  }
2412
2530
  )
2413
- ] })
2531
+ ] }),
2532
+ /* @__PURE__ */ jsx6("div", { style: { padding: "0 20px 16px" }, children: /* @__PURE__ */ jsxs4(
2533
+ "label",
2534
+ {
2535
+ style: {
2536
+ display: "flex",
2537
+ alignItems: "center",
2538
+ gap: "10px",
2539
+ padding: "10px 12px",
2540
+ border: "1px solid var(--default-border-color, #e0e0e0)",
2541
+ borderRadius: "8px",
2542
+ cursor: "pointer",
2543
+ userSelect: "none"
2544
+ },
2545
+ children: [
2546
+ /* @__PURE__ */ jsx6(
2547
+ "input",
2548
+ {
2549
+ type: "checkbox",
2550
+ checked: autoStart,
2551
+ onChange: handleToggleAutoStart,
2552
+ style: { width: "16px", height: "16px", cursor: "pointer", flexShrink: 0 }
2553
+ }
2554
+ ),
2555
+ /* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0 }, children: [
2556
+ /* @__PURE__ */ jsx6("div", { style: { fontSize: "14px", fontWeight: 500 }, children: t.autoStartLabel }),
2557
+ /* @__PURE__ */ jsx6("div", { style: { fontSize: "12px", color: "var(--text-secondary-color, #888)", marginTop: "2px" }, children: t.autoStartDesc })
2558
+ ] })
2559
+ ]
2560
+ }
2561
+ ) })
2414
2562
  ]
2415
2563
  }
2416
2564
  )
@@ -2743,6 +2891,7 @@ export {
2743
2891
  moveDrawingToFolder,
2744
2892
  removeDrawingFromWorkspace,
2745
2893
  renameFolder,
2894
+ reorderDrawings,
2746
2895
  setActiveDrawing,
2747
2896
  updateDrawing,
2748
2897
  updateWorkspace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rita-workspace",
3
- "version": "0.5.33",
3
+ "version": "0.5.35",
4
4
  "description": "Multi-drawing workspace feature for Rita (Excalidraw fork)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",