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