rita-workspace 0.1.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 ADDED
@@ -0,0 +1,657 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DrawingList: () => DrawingList,
24
+ DrawingListItem: () => DrawingListItem,
25
+ Sidebar: () => Sidebar,
26
+ WorkspacePlugin: () => WorkspacePlugin,
27
+ WorkspaceProvider: () => WorkspaceProvider,
28
+ addDrawingToWorkspace: () => addDrawingToWorkspace,
29
+ closeDB: () => closeDB,
30
+ createDrawing: () => createDrawing,
31
+ deleteDrawing: () => deleteDrawing,
32
+ duplicateDrawing: () => duplicateDrawing,
33
+ getAllDrawings: () => getAllDrawings,
34
+ getDB: () => getDB,
35
+ getDrawing: () => getDrawing,
36
+ getOrCreateDefaultWorkspace: () => getOrCreateDefaultWorkspace,
37
+ getWorkspace: () => getWorkspace,
38
+ removeDrawingFromWorkspace: () => removeDrawingFromWorkspace,
39
+ setActiveDrawing: () => setActiveDrawing,
40
+ updateDrawing: () => updateDrawing,
41
+ updateWorkspace: () => updateWorkspace,
42
+ useExcalidrawBridge: () => useExcalidrawBridge,
43
+ useWorkspace: () => useWorkspace
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/storage/db.ts
48
+ var import_idb = require("idb");
49
+ var DB_NAME = "rita-workspace";
50
+ var DB_VERSION = 1;
51
+ var dbInstance = null;
52
+ async function getDB() {
53
+ if (dbInstance) return dbInstance;
54
+ dbInstance = await (0, import_idb.openDB)(DB_NAME, DB_VERSION, {
55
+ upgrade(db) {
56
+ if (!db.objectStoreNames.contains("workspaces")) {
57
+ const workspaceStore = db.createObjectStore("workspaces", { keyPath: "id" });
58
+ workspaceStore.createIndex("by-updated", "updatedAt");
59
+ }
60
+ if (!db.objectStoreNames.contains("drawings")) {
61
+ const drawingStore = db.createObjectStore("drawings", { keyPath: "id" });
62
+ drawingStore.createIndex("by-updated", "updatedAt");
63
+ }
64
+ }
65
+ });
66
+ return dbInstance;
67
+ }
68
+ async function closeDB() {
69
+ if (dbInstance) {
70
+ dbInstance.close();
71
+ dbInstance = null;
72
+ }
73
+ }
74
+
75
+ // src/storage/drawingStore.ts
76
+ var import_nanoid = require("nanoid");
77
+ async function createDrawing(name = "Untitled", elements = [], appState = {}) {
78
+ const db = await getDB();
79
+ const now = Date.now();
80
+ const drawing = {
81
+ id: (0, import_nanoid.nanoid)(),
82
+ name,
83
+ elements,
84
+ appState,
85
+ files: {},
86
+ createdAt: now,
87
+ updatedAt: now
88
+ };
89
+ await db.put("drawings", drawing);
90
+ return drawing;
91
+ }
92
+ async function getDrawing(id) {
93
+ const db = await getDB();
94
+ return db.get("drawings", id);
95
+ }
96
+ async function getAllDrawings() {
97
+ const db = await getDB();
98
+ return db.getAllFromIndex("drawings", "by-updated");
99
+ }
100
+ async function updateDrawing(id, updates) {
101
+ const db = await getDB();
102
+ const existing = await db.get("drawings", id);
103
+ if (!existing) return void 0;
104
+ const updated = {
105
+ ...existing,
106
+ ...updates,
107
+ updatedAt: Date.now()
108
+ };
109
+ await db.put("drawings", updated);
110
+ return updated;
111
+ }
112
+ async function deleteDrawing(id) {
113
+ const db = await getDB();
114
+ const existing = await db.get("drawings", id);
115
+ if (!existing) return false;
116
+ await db.delete("drawings", id);
117
+ return true;
118
+ }
119
+ async function duplicateDrawing(id, newName) {
120
+ const existing = await getDrawing(id);
121
+ if (!existing) return void 0;
122
+ return createDrawing(
123
+ newName || `${existing.name} (copy)`,
124
+ existing.elements,
125
+ existing.appState
126
+ );
127
+ }
128
+
129
+ // src/storage/workspaceStore.ts
130
+ var DEFAULT_WORKSPACE_ID = "default";
131
+ async function getOrCreateDefaultWorkspace() {
132
+ const db = await getDB();
133
+ let workspace = await db.get("workspaces", DEFAULT_WORKSPACE_ID);
134
+ if (!workspace) {
135
+ const firstDrawing = await createDrawing("Ritning 1");
136
+ const now = Date.now();
137
+ workspace = {
138
+ id: DEFAULT_WORKSPACE_ID,
139
+ name: "My Workspace",
140
+ drawingIds: [firstDrawing.id],
141
+ activeDrawingId: firstDrawing.id,
142
+ createdAt: now,
143
+ updatedAt: now
144
+ };
145
+ await db.put("workspaces", workspace);
146
+ }
147
+ return workspace;
148
+ }
149
+ async function getWorkspace(id) {
150
+ const db = await getDB();
151
+ return db.get("workspaces", id);
152
+ }
153
+ async function updateWorkspace(id, updates) {
154
+ const db = await getDB();
155
+ const existing = await db.get("workspaces", id);
156
+ if (!existing) return void 0;
157
+ const updated = {
158
+ ...existing,
159
+ ...updates,
160
+ updatedAt: Date.now()
161
+ };
162
+ await db.put("workspaces", updated);
163
+ return updated;
164
+ }
165
+ async function addDrawingToWorkspace(workspaceId, drawingId) {
166
+ const workspace = await getWorkspace(workspaceId);
167
+ if (!workspace) return void 0;
168
+ if (!workspace.drawingIds.includes(drawingId)) {
169
+ workspace.drawingIds.push(drawingId);
170
+ return updateWorkspace(workspaceId, {
171
+ drawingIds: workspace.drawingIds
172
+ });
173
+ }
174
+ return workspace;
175
+ }
176
+ async function removeDrawingFromWorkspace(workspaceId, drawingId) {
177
+ const workspace = await getWorkspace(workspaceId);
178
+ if (!workspace) return void 0;
179
+ const newDrawingIds = workspace.drawingIds.filter((id) => id !== drawingId);
180
+ if (newDrawingIds.length === 0) {
181
+ return workspace;
182
+ }
183
+ const newActiveId = workspace.activeDrawingId === drawingId ? newDrawingIds[0] : workspace.activeDrawingId;
184
+ return updateWorkspace(workspaceId, {
185
+ drawingIds: newDrawingIds,
186
+ activeDrawingId: newActiveId
187
+ });
188
+ }
189
+ async function setActiveDrawing(workspaceId, drawingId) {
190
+ return updateWorkspace(workspaceId, { activeDrawingId: drawingId });
191
+ }
192
+
193
+ // src/state/WorkspaceContext.tsx
194
+ var import_react = require("react");
195
+ var import_jsx_runtime = require("react/jsx-runtime");
196
+ var WorkspaceContext = (0, import_react.createContext)(null);
197
+ function useWorkspace() {
198
+ const context = (0, import_react.useContext)(WorkspaceContext);
199
+ if (!context) {
200
+ throw new Error("useWorkspace must be used within a WorkspaceProvider");
201
+ }
202
+ return context;
203
+ }
204
+ function WorkspaceProvider({ children }) {
205
+ const [workspace, setWorkspace] = (0, import_react.useState)(null);
206
+ const [drawings, setDrawings] = (0, import_react.useState)([]);
207
+ const [activeDrawing, setActiveDrawing2] = (0, import_react.useState)(null);
208
+ const [isLoading, setIsLoading] = (0, import_react.useState)(true);
209
+ const [error, setError] = (0, import_react.useState)(null);
210
+ (0, import_react.useEffect)(() => {
211
+ async function init() {
212
+ try {
213
+ setIsLoading(true);
214
+ const ws = await getOrCreateDefaultWorkspace();
215
+ setWorkspace(ws);
216
+ const allDrawings = await getAllDrawings();
217
+ const wsDrawings = allDrawings.filter((d) => ws.drawingIds.includes(d.id));
218
+ setDrawings(wsDrawings);
219
+ if (ws.activeDrawingId) {
220
+ const active = await getDrawing(ws.activeDrawingId);
221
+ setActiveDrawing2(active || null);
222
+ }
223
+ } catch (err) {
224
+ setError(err instanceof Error ? err.message : "Failed to load workspace");
225
+ } finally {
226
+ setIsLoading(false);
227
+ }
228
+ }
229
+ init();
230
+ }, []);
231
+ const createNewDrawing = (0, import_react.useCallback)(async (name) => {
232
+ if (!workspace) return null;
233
+ try {
234
+ const drawing = await createDrawing(name || `Ritning ${drawings.length + 1}`);
235
+ await addDrawingToWorkspace(workspace.id, drawing.id);
236
+ await setActiveDrawing(workspace.id, drawing.id);
237
+ setDrawings((prev) => [...prev, drawing]);
238
+ setActiveDrawing2(drawing);
239
+ setWorkspace((prev) => prev ? {
240
+ ...prev,
241
+ drawingIds: [...prev.drawingIds, drawing.id],
242
+ activeDrawingId: drawing.id
243
+ } : null);
244
+ return drawing;
245
+ } catch (err) {
246
+ setError(err instanceof Error ? err.message : "Failed to create drawing");
247
+ return null;
248
+ }
249
+ }, [workspace, drawings.length]);
250
+ const switchDrawing = (0, import_react.useCallback)(async (id) => {
251
+ if (!workspace) return;
252
+ try {
253
+ const drawing = await getDrawing(id);
254
+ if (drawing) {
255
+ await setActiveDrawing(workspace.id, id);
256
+ setActiveDrawing2(drawing);
257
+ setWorkspace((prev) => prev ? { ...prev, activeDrawingId: id } : null);
258
+ }
259
+ } catch (err) {
260
+ setError(err instanceof Error ? err.message : "Failed to switch drawing");
261
+ }
262
+ }, [workspace]);
263
+ const renameDrawing = (0, import_react.useCallback)(async (id, name) => {
264
+ try {
265
+ const updated = await updateDrawing(id, { name });
266
+ if (updated) {
267
+ setDrawings((prev) => prev.map((d) => d.id === id ? updated : d));
268
+ if (activeDrawing?.id === id) {
269
+ setActiveDrawing2(updated);
270
+ }
271
+ }
272
+ } catch (err) {
273
+ setError(err instanceof Error ? err.message : "Failed to rename drawing");
274
+ }
275
+ }, [activeDrawing]);
276
+ const removeDrawing = (0, import_react.useCallback)(async (id) => {
277
+ if (!workspace || drawings.length <= 1) return;
278
+ try {
279
+ await deleteDrawing(id);
280
+ const updatedWorkspace = await removeDrawingFromWorkspace(workspace.id, id);
281
+ setDrawings((prev) => prev.filter((d) => d.id !== id));
282
+ if (updatedWorkspace) {
283
+ setWorkspace(updatedWorkspace);
284
+ if (activeDrawing?.id === id && updatedWorkspace.activeDrawingId) {
285
+ const newActive = await getDrawing(updatedWorkspace.activeDrawingId);
286
+ setActiveDrawing2(newActive || null);
287
+ }
288
+ }
289
+ } catch (err) {
290
+ setError(err instanceof Error ? err.message : "Failed to delete drawing");
291
+ }
292
+ }, [workspace, drawings.length, activeDrawing]);
293
+ const duplicateCurrentDrawing = (0, import_react.useCallback)(async () => {
294
+ if (!activeDrawing || !workspace) return null;
295
+ try {
296
+ const duplicate = await duplicateDrawing(activeDrawing.id);
297
+ if (duplicate) {
298
+ await addDrawingToWorkspace(workspace.id, duplicate.id);
299
+ setDrawings((prev) => [...prev, duplicate]);
300
+ setWorkspace((prev) => prev ? {
301
+ ...prev,
302
+ drawingIds: [...prev.drawingIds, duplicate.id]
303
+ } : null);
304
+ return duplicate;
305
+ }
306
+ return null;
307
+ } catch (err) {
308
+ setError(err instanceof Error ? err.message : "Failed to duplicate drawing");
309
+ return null;
310
+ }
311
+ }, [activeDrawing, workspace]);
312
+ const saveCurrentDrawing = (0, import_react.useCallback)(async (elements, appState) => {
313
+ if (!activeDrawing) return;
314
+ try {
315
+ const updated = await updateDrawing(activeDrawing.id, { elements, appState });
316
+ if (updated) {
317
+ setActiveDrawing2(updated);
318
+ setDrawings((prev) => prev.map((d) => d.id === updated.id ? updated : d));
319
+ }
320
+ } catch (err) {
321
+ setError(err instanceof Error ? err.message : "Failed to save drawing");
322
+ }
323
+ }, [activeDrawing]);
324
+ const value = {
325
+ workspace,
326
+ drawings,
327
+ activeDrawing,
328
+ isLoading,
329
+ error,
330
+ createNewDrawing,
331
+ switchDrawing,
332
+ renameDrawing,
333
+ removeDrawing,
334
+ duplicateCurrentDrawing,
335
+ saveCurrentDrawing
336
+ };
337
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceContext.Provider, { value, children });
338
+ }
339
+
340
+ // src/ui/Sidebar/Sidebar.tsx
341
+ var import_react3 = require("react");
342
+
343
+ // src/ui/DrawingList/DrawingListItem.tsx
344
+ var import_react2 = require("react");
345
+
346
+ // src/ui/DrawingList/DrawingList.module.css
347
+ var DrawingList_default = {};
348
+
349
+ // src/ui/DrawingList/DrawingListItem.tsx
350
+ var import_jsx_runtime2 = require("react/jsx-runtime");
351
+ function DrawingListItem({
352
+ drawing,
353
+ isActive,
354
+ onSelect,
355
+ onRename,
356
+ onDelete,
357
+ canDelete
358
+ }) {
359
+ const [isEditing, setIsEditing] = (0, import_react2.useState)(false);
360
+ const [editName, setEditName] = (0, import_react2.useState)(drawing.name);
361
+ const inputRef = (0, import_react2.useRef)(null);
362
+ (0, import_react2.useEffect)(() => {
363
+ if (isEditing && inputRef.current) {
364
+ inputRef.current.focus();
365
+ inputRef.current.select();
366
+ }
367
+ }, [isEditing]);
368
+ const handleSubmit = () => {
369
+ const trimmed = editName.trim();
370
+ if (trimmed && trimmed !== drawing.name) {
371
+ onRename(trimmed);
372
+ } else {
373
+ setEditName(drawing.name);
374
+ }
375
+ setIsEditing(false);
376
+ };
377
+ const handleKeyDown = (e) => {
378
+ if (e.key === "Enter") {
379
+ handleSubmit();
380
+ } else if (e.key === "Escape") {
381
+ setEditName(drawing.name);
382
+ setIsEditing(false);
383
+ }
384
+ };
385
+ const handleDoubleClick = (e) => {
386
+ e.stopPropagation();
387
+ setIsEditing(true);
388
+ };
389
+ const handleDeleteClick = (e) => {
390
+ e.stopPropagation();
391
+ if (window.confirm(`Ta bort "${drawing.name}"?`)) {
392
+ onDelete();
393
+ }
394
+ };
395
+ const formatDate = (timestamp) => {
396
+ const date = new Date(timestamp);
397
+ return date.toLocaleDateString("sv-SE", {
398
+ month: "short",
399
+ day: "numeric",
400
+ hour: "2-digit",
401
+ minute: "2-digit"
402
+ });
403
+ };
404
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
405
+ "li",
406
+ {
407
+ className: `${DrawingList_default.item} ${isActive ? DrawingList_default.active : ""}`,
408
+ onClick: onSelect,
409
+ children: [
410
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: DrawingList_default.itemContent, children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
411
+ "input",
412
+ {
413
+ ref: inputRef,
414
+ type: "text",
415
+ value: editName,
416
+ onChange: (e) => setEditName(e.target.value),
417
+ onBlur: handleSubmit,
418
+ onKeyDown: handleKeyDown,
419
+ className: DrawingList_default.editInput,
420
+ onClick: (e) => e.stopPropagation()
421
+ }
422
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
423
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
424
+ "span",
425
+ {
426
+ className: DrawingList_default.name,
427
+ onDoubleClick: handleDoubleClick,
428
+ title: "Dubbelklicka f\xF6r att byta namn",
429
+ children: drawing.name
430
+ }
431
+ ),
432
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: DrawingList_default.date, children: formatDate(drawing.updatedAt) })
433
+ ] }) }),
434
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: DrawingList_default.actions, children: [
435
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
436
+ "button",
437
+ {
438
+ className: DrawingList_default.actionButton,
439
+ onClick: handleDoubleClick,
440
+ title: "Byt namn (F2)",
441
+ children: "\u270F\uFE0F"
442
+ }
443
+ ),
444
+ canDelete && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
445
+ "button",
446
+ {
447
+ className: DrawingList_default.actionButton,
448
+ onClick: handleDeleteClick,
449
+ title: "Ta bort",
450
+ children: "\u{1F5D1}\uFE0F"
451
+ }
452
+ )
453
+ ] })
454
+ ]
455
+ }
456
+ );
457
+ }
458
+
459
+ // src/ui/DrawingList/DrawingList.tsx
460
+ var import_jsx_runtime3 = require("react/jsx-runtime");
461
+ function DrawingList() {
462
+ const { drawings, activeDrawing, switchDrawing, renameDrawing, removeDrawing } = useWorkspace();
463
+ if (drawings.length === 0) {
464
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: DrawingList_default.empty, children: "Inga ritningar" });
465
+ }
466
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: DrawingList_default.list, children: drawings.map((drawing) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
467
+ DrawingListItem,
468
+ {
469
+ drawing,
470
+ isActive: drawing.id === activeDrawing?.id,
471
+ onSelect: () => switchDrawing(drawing.id),
472
+ onRename: (name) => renameDrawing(drawing.id, name),
473
+ onDelete: () => removeDrawing(drawing.id),
474
+ canDelete: drawings.length > 1
475
+ },
476
+ drawing.id
477
+ )) });
478
+ }
479
+
480
+ // src/ui/Sidebar/Sidebar.module.css
481
+ var Sidebar_default = {};
482
+
483
+ // src/ui/Sidebar/Sidebar.tsx
484
+ var import_jsx_runtime4 = require("react/jsx-runtime");
485
+ function Sidebar({ isOpen = true, onToggle, width = 250 }) {
486
+ const { createNewDrawing, isLoading } = useWorkspace();
487
+ const [isCreating, setIsCreating] = (0, import_react3.useState)(false);
488
+ const handleCreateNew = async () => {
489
+ setIsCreating(true);
490
+ await createNewDrawing();
491
+ setIsCreating(false);
492
+ };
493
+ if (!isOpen) {
494
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
495
+ "button",
496
+ {
497
+ className: Sidebar_default.toggleButton,
498
+ onClick: onToggle,
499
+ title: "Open sidebar (Ctrl+B)",
500
+ "aria-label": "Open sidebar",
501
+ children: "\u2630"
502
+ }
503
+ );
504
+ }
505
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("aside", { className: Sidebar_default.sidebar, style: { width }, children: [
506
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: Sidebar_default.header, children: [
507
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: Sidebar_default.title, children: "Ritningar" }),
508
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
509
+ "button",
510
+ {
511
+ className: Sidebar_default.closeButton,
512
+ onClick: onToggle,
513
+ title: "Close sidebar (Ctrl+B)",
514
+ "aria-label": "Close sidebar",
515
+ children: "\u2715"
516
+ }
517
+ )
518
+ ] }),
519
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: Sidebar_default.content, children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: Sidebar_default.loading, children: "Laddar..." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DrawingList, {}) }),
520
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("footer", { className: Sidebar_default.footer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
521
+ "button",
522
+ {
523
+ className: Sidebar_default.newButton,
524
+ onClick: handleCreateNew,
525
+ disabled: isCreating,
526
+ children: isCreating ? "Skapar..." : "+ Ny ritning"
527
+ }
528
+ ) })
529
+ ] });
530
+ }
531
+
532
+ // src/integration/useExcalidrawBridge.ts
533
+ var import_react4 = require("react");
534
+ function useExcalidrawBridge({
535
+ excalidrawAPI,
536
+ autoSaveInterval = 2e3
537
+ }) {
538
+ const { activeDrawing, saveCurrentDrawing } = useWorkspace();
539
+ const saveTimeoutRef = (0, import_react4.useRef)(null);
540
+ const lastDrawingIdRef = (0, import_react4.useRef)(null);
541
+ (0, import_react4.useEffect)(() => {
542
+ if (!excalidrawAPI || !activeDrawing) return;
543
+ if (lastDrawingIdRef.current === activeDrawing.id) return;
544
+ lastDrawingIdRef.current = activeDrawing.id;
545
+ excalidrawAPI.updateScene({
546
+ elements: activeDrawing.elements,
547
+ appState: activeDrawing.appState
548
+ });
549
+ }, [excalidrawAPI, activeDrawing]);
550
+ const scheduleSave = (0, import_react4.useCallback)(() => {
551
+ if (!excalidrawAPI) return;
552
+ if (saveTimeoutRef.current) {
553
+ clearTimeout(saveTimeoutRef.current);
554
+ }
555
+ saveTimeoutRef.current = setTimeout(async () => {
556
+ const elements = excalidrawAPI.getSceneElements();
557
+ const appState = excalidrawAPI.getAppState();
558
+ await saveCurrentDrawing(elements, appState);
559
+ }, autoSaveInterval);
560
+ }, [excalidrawAPI, saveCurrentDrawing, autoSaveInterval]);
561
+ (0, import_react4.useEffect)(() => {
562
+ return () => {
563
+ if (saveTimeoutRef.current) {
564
+ clearTimeout(saveTimeoutRef.current);
565
+ }
566
+ };
567
+ }, []);
568
+ return {
569
+ scheduleSave
570
+ };
571
+ }
572
+
573
+ // src/WorkspacePlugin.tsx
574
+ var import_react5 = require("react");
575
+ var import_jsx_runtime5 = require("react/jsx-runtime");
576
+ function WorkspacePluginInner({
577
+ children,
578
+ defaultSidebarOpen = true,
579
+ sidebarWidth = 250
580
+ }) {
581
+ const [sidebarOpen, setSidebarOpen] = (0, import_react5.useState)(defaultSidebarOpen);
582
+ const { activeDrawing } = useWorkspace();
583
+ (0, import_react5.useEffect)(() => {
584
+ const handleKeyDown = (e) => {
585
+ if (e.ctrlKey && e.key === "b") {
586
+ e.preventDefault();
587
+ setSidebarOpen((prev) => !prev);
588
+ }
589
+ if (e.ctrlKey && e.shiftKey && e.key === "N") {
590
+ e.preventDefault();
591
+ }
592
+ };
593
+ window.addEventListener("keydown", handleKeyDown);
594
+ return () => window.removeEventListener("keydown", handleKeyDown);
595
+ }, []);
596
+ const handleToggleSidebar = (0, import_react5.useCallback)(() => {
597
+ setSidebarOpen((prev) => !prev);
598
+ }, []);
599
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
600
+ "div",
601
+ {
602
+ style: {
603
+ display: "flex",
604
+ height: "100%",
605
+ width: "100%"
606
+ },
607
+ children: [
608
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
609
+ Sidebar,
610
+ {
611
+ isOpen: sidebarOpen,
612
+ onToggle: handleToggleSidebar,
613
+ width: sidebarWidth
614
+ }
615
+ ),
616
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
617
+ "main",
618
+ {
619
+ style: {
620
+ flex: 1,
621
+ height: "100%",
622
+ overflow: "hidden"
623
+ },
624
+ children
625
+ }
626
+ )
627
+ ]
628
+ }
629
+ );
630
+ }
631
+ function WorkspacePlugin(props) {
632
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkspaceProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkspacePluginInner, { ...props }) });
633
+ }
634
+ // Annotate the CommonJS export names for ESM import in node:
635
+ 0 && (module.exports = {
636
+ DrawingList,
637
+ DrawingListItem,
638
+ Sidebar,
639
+ WorkspacePlugin,
640
+ WorkspaceProvider,
641
+ addDrawingToWorkspace,
642
+ closeDB,
643
+ createDrawing,
644
+ deleteDrawing,
645
+ duplicateDrawing,
646
+ getAllDrawings,
647
+ getDB,
648
+ getDrawing,
649
+ getOrCreateDefaultWorkspace,
650
+ getWorkspace,
651
+ removeDrawingFromWorkspace,
652
+ setActiveDrawing,
653
+ updateDrawing,
654
+ updateWorkspace,
655
+ useExcalidrawBridge,
656
+ useWorkspace
657
+ });