rita-workspace 0.1.1 → 0.2.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/README.md CHANGED
@@ -2,103 +2,170 @@
2
2
 
3
3
  Multi-drawing workspace feature for Rita (Excalidraw fork based on B310-digital/excalidraw).
4
4
 
5
- ## Problem
5
+ ## Features
6
6
 
7
- Currently Rita only supports one active drawing at a time. Users need to manually export/import drawings to switch between them.
7
+ - **Multiple drawings** - Create and manage multiple drawings in one workspace
8
+ - **Menu integration** - Seamlessly integrates with Excalidraw's hamburger menu
9
+ - **Auto-save** - All drawings saved locally in IndexedDB
10
+ - **Rename & delete** - Full drawing management via dialog
8
11
 
9
- ## Solution
12
+ ## Installation
10
13
 
11
- Add a workspace feature that allows users to:
12
- - Create multiple drawings within a single workspace
13
- - Switch between drawings with a simple sidebar/tab GUI
14
- - Store all drawings locally in the browser (IndexedDB/localStorage)
15
- - Name and organize drawings
14
+ ```bash
15
+ npm install rita-workspace
16
+ # or
17
+ yarn add rita-workspace
18
+ ```
16
19
 
17
- ## Features
20
+ ## Integration Guide
18
21
 
19
- ### MVP (v1.0)
20
- - [ ] Sidebar with list of drawings
21
- - [ ] Create new drawing button
22
- - [ ] Switch between drawings (preserves state)
23
- - [ ] Rename drawings
24
- - [ ] Delete drawings
25
- - [ ] Auto-save to browser storage (IndexedDB)
26
- - [ ] Import existing .excalidraw files into workspace
27
-
28
- ### Future (v2.0+)
29
- - [ ] Folders/categories for drawings
30
- - [ ] Search drawings
31
- - [ ] Thumbnail previews
32
- - [ ] Export entire workspace
33
- - [ ] Cloud sync (optional)
34
- - [ ] Link/reference between drawings
35
-
36
- ## Technical Approach
37
-
38
- ### Storage
39
- - Use IndexedDB for persistent storage (better than localStorage for binary data)
40
- - Each drawing stored as separate entry with metadata
41
- - Workspace metadata stored separately
42
-
43
- ### Data Structure
44
- ```typescript
45
- interface Drawing {
46
- id: string;
47
- name: string;
48
- createdAt: Date;
49
- updatedAt: Date;
50
- elements: ExcalidrawElement[];
51
- appState: Partial<AppState>;
52
- files: BinaryFiles;
53
- }
22
+ Two files need to be modified in the B310/Excalidraw fork:
54
23
 
55
- interface Workspace {
56
- id: string;
57
- name: string;
58
- drawings: string[]; // Drawing IDs
59
- activeDrawingId: string;
60
- createdAt: Date;
61
- updatedAt: Date;
62
- }
24
+ ### 1. `excalidraw-app/App.tsx`
25
+
26
+ **Add import** (at the top with other imports):
27
+
28
+ ```tsx
29
+ import { WorkspaceProvider } from "rita-workspace";
30
+ ```
31
+
32
+ **Wrap with WorkspaceProvider** (in the `ExcalidrawApp` component):
33
+
34
+ ```tsx
35
+ const ExcalidrawApp = () => {
36
+ // ...
37
+ return (
38
+ <TopErrorBoundary>
39
+ <Provider store={appJotaiStore}>
40
+ <WorkspaceProvider> {/* <-- Add this */}
41
+ <ExcalidrawWrapper />
42
+ </WorkspaceProvider> {/* <-- And this */}
43
+ </Provider>
44
+ </TopErrorBoundary>
45
+ );
46
+ };
63
47
  ```
64
48
 
65
- ### UI Components
66
- - `WorkspaceSidebar` - Collapsible sidebar showing drawing list
67
- - `DrawingListItem` - Individual drawing entry with actions
68
- - `NewDrawingButton` - Creates new blank drawing
69
- - `WorkspaceProvider` - React context for workspace state
49
+ ### 2. `excalidraw-app/components/AppMainMenu.tsx`
70
50
 
71
- ## Integration with B310 Fork
51
+ **Add imports** (at the top):
72
52
 
73
- This feature will be implemented as a modular addition that can be:
74
- 1. Merged into the main B310 fork as a PR
75
- 2. Maintained as a separate layer/plugin for Rita
53
+ ```tsx
54
+ import React, { useState } from "react"; // Add useState
76
55
 
77
- ## Development
56
+ // Add after other imports:
57
+ import { WorkspaceMenuItems, DrawingsDialog } from "rita-workspace";
58
+ ```
78
59
 
79
- ### Prerequisites
80
- - Node.js 18+
81
- - Yarn
82
- - B310 Excalidraw fork cloned locally
60
+ **Add state and menu items** (inside the component):
61
+
62
+ ```tsx
63
+ export const AppMainMenu: React.FC<{...}> = React.memo((props) => {
64
+ const [showDrawingsDialog, setShowDrawingsDialog] = useState(false); // Add this
65
+
66
+ return (
67
+ <> {/* Add fragment */}
68
+ <MainMenu>
69
+ <MainMenu.DefaultItems.LoadScene />
70
+ <MainMenu.DefaultItems.SaveToActiveFile />
71
+
72
+ {/* === RITA WORKSPACE: Add this block === */}
73
+ <MainMenu.Sub>
74
+ <MainMenu.Sub.Trigger>📄 Ritningar</MainMenu.Sub.Trigger>
75
+ <MainMenu.Sub.Content>
76
+ <WorkspaceMenuItems
77
+ onManageDrawings={() => setShowDrawingsDialog(true)}
78
+ />
79
+ </MainMenu.Sub.Content>
80
+ </MainMenu.Sub>
81
+ {/* === END RITA WORKSPACE === */}
82
+
83
+ <MainMenu.DefaultItems.Export />
84
+ {/* ... rest of menu items ... */}
85
+ </MainMenu>
86
+
87
+ {/* === RITA WORKSPACE: Add dialog === */}
88
+ <DrawingsDialog
89
+ open={showDrawingsDialog}
90
+ onClose={() => setShowDrawingsDialog(false)}
91
+ />
92
+ </> {/* Close fragment */}
93
+ );
94
+ });
95
+ ```
83
96
 
84
- ### Setup
85
- ```bash
86
- # Clone B310 fork
87
- git clone https://github.com/b310-digital/excalidraw.git rita
88
- cd rita
89
-
90
- # Apply workspace patches
91
- git remote add workspace https://github.com/farapholch/rita-workspace.git
92
- git fetch workspace
93
- git merge workspace/main
97
+ ## Result
98
+
99
+ After integration, a "📄 Ritningar" submenu appears in the hamburger menu:
100
+
101
+ ```
102
+ ┌─────────────────────────┐
103
+ 📂 Open │
104
+ 💾 Save │
105
+ 📄 Ritningar ▶ │──┐
106
+ 📤 Export │ │ ┌─────────────────────┐
107
+ │ ... │ └──│ ✓ Current drawing │
108
+ └─────────────────────────┘ │ Sketch 2 │
109
+ │ Project X │
110
+ │ ─────────────────── │
111
+ │ + Ny ritning │
112
+ │ 📄 Hantera... │
113
+ └─────────────────────┘
114
+ ```
115
+
116
+ ## API Reference
117
+
118
+ ### Components
119
+
120
+ | Component | Description |
121
+ |-----------|-------------|
122
+ | `WorkspaceProvider` | React context provider - wrap your app with this |
123
+ | `WorkspaceMenuItems` | Menu items for Excalidraw's MainMenu |
124
+ | `DrawingsDialog` | Modal dialog for managing all drawings |
125
+
126
+ ### Hooks
127
+
128
+ | Hook | Description |
129
+ |------|-------------|
130
+ | `useWorkspace()` | Access workspace state and actions |
131
+
132
+ ### useWorkspace() returns
133
+
134
+ ```tsx
135
+ const {
136
+ drawings, // Drawing[] - all drawings
137
+ activeDrawing, // Drawing | null - currently active
138
+ isLoading, // boolean
139
+ createNewDrawing, // () => Promise<Drawing>
140
+ switchDrawing, // (id: string) => Promise<void>
141
+ renameDrawing, // (id: string, name: string) => Promise<void>
142
+ removeDrawing, // (id: string) => Promise<void>
143
+ saveCurrentDrawing, // (elements, appState, files?) => Promise<void>
144
+ } = useWorkspace();
145
+ ```
146
+
147
+ ## Data Storage
148
+
149
+ Drawings are stored in IndexedDB with the following structure:
150
+
151
+ ```typescript
152
+ interface Drawing {
153
+ id: string;
154
+ name: string;
155
+ elements: ExcalidrawElement[];
156
+ appState: Record<string, unknown>;
157
+ files: Record<string, unknown>;
158
+ createdAt: number;
159
+ updatedAt: number;
160
+ }
94
161
  ```
95
162
 
96
163
  ## Links
97
164
 
165
+ - **npm:** https://www.npmjs.com/package/rita-workspace
98
166
  - **B310 Excalidraw Fork:** https://github.com/b310-digital/excalidraw
99
167
  - **Original Excalidraw:** https://github.com/excalidraw/excalidraw
100
- - **Rita:** Your local Rita deployment
101
168
 
102
169
  ## License
103
170
 
104
- MIT (same as Excalidraw)
171
+ MIT
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { IDBPDatabase, DBSchema } from 'idb';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import { ReactNode } from 'react';
3
+ import React, { ReactNode } from 'react';
4
4
 
5
5
  interface Drawing {
6
6
  id: string;
@@ -90,6 +90,88 @@ interface DrawingListItemProps {
90
90
  }
91
91
  declare function DrawingListItem({ drawing, isActive, onSelect, onRename, onDelete, canDelete, }: DrawingListItemProps): react_jsx_runtime.JSX.Element;
92
92
 
93
+ /**
94
+ * Workspace Menu Items
95
+ *
96
+ * These components can be inserted into Excalidraw's main menu
97
+ * to provide workspace/multi-drawing functionality.
98
+ */
99
+
100
+ interface WorkspaceMenuItemsProps {
101
+ /**
102
+ * Called when a drawing is selected from the submenu
103
+ */
104
+ onDrawingSelect?: (drawing: Drawing) => void;
105
+ /**
106
+ * Called when "Manage Drawings" is clicked
107
+ */
108
+ onManageDrawings?: () => void;
109
+ /**
110
+ * Render function for menu item - allows integration with Excalidraw's DropdownMenuItem
111
+ */
112
+ renderMenuItem?: (props: {
113
+ icon: React.ReactNode;
114
+ children: React.ReactNode;
115
+ onSelect: () => void;
116
+ shortcut?: string;
117
+ }) => React.ReactNode;
118
+ /**
119
+ * Render function for submenu - allows integration with Excalidraw's DropdownMenuSub
120
+ */
121
+ renderSubMenu?: (props: {
122
+ trigger: React.ReactNode;
123
+ children: React.ReactNode;
124
+ }) => React.ReactNode;
125
+ /**
126
+ * Render function for separator
127
+ */
128
+ renderSeparator?: () => React.ReactNode;
129
+ }
130
+ /**
131
+ * WorkspaceMenuItems - provides menu items for workspace functionality
132
+ *
133
+ * Usage with Excalidraw's menu system:
134
+ * ```tsx
135
+ * <MainMenu>
136
+ * <MainMenu.DefaultItems.LoadScene />
137
+ * <MainMenu.DefaultItems.SaveToActiveFile />
138
+ * <MainMenu.Separator />
139
+ * <WorkspaceMenuItems
140
+ * renderMenuItem={(props) => <MainMenu.Item {...props} />}
141
+ * renderSubMenu={(props) => <MainMenu.Sub>{props.children}</MainMenu.Sub>}
142
+ * renderSeparator={() => <MainMenu.Separator />}
143
+ * />
144
+ * </MainMenu>
145
+ * ```
146
+ */
147
+ declare const WorkspaceMenuItems: React.FC<WorkspaceMenuItemsProps>;
148
+
149
+ /**
150
+ * Drawings Dialog
151
+ *
152
+ * A modal dialog for managing all drawings in the workspace.
153
+ * Provides full CRUD operations: view, rename, delete, create new.
154
+ */
155
+
156
+ interface DrawingsDialogProps {
157
+ /**
158
+ * Whether the dialog is open
159
+ */
160
+ open: boolean;
161
+ /**
162
+ * Called when the dialog should close
163
+ */
164
+ onClose: () => void;
165
+ /**
166
+ * Called when a drawing is selected
167
+ */
168
+ onDrawingSelect?: (drawing: Drawing) => void;
169
+ }
170
+ /**
171
+ * DrawingsDialog - modal for managing workspace drawings
172
+ */
173
+ declare const DrawingsDialog: React.FC<DrawingsDialogProps>;
174
+
93
175
  interface ExcalidrawAPI {
94
176
  getSceneElements: () => unknown[];
95
177
  getAppState: () => Record<string, unknown>;
@@ -142,4 +224,4 @@ interface WorkspacePluginProps {
142
224
  */
143
225
  declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
144
226
 
145
- export { type Drawing, DrawingList, DrawingListItem, Sidebar, type Workspace, type WorkspaceContextValue, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getWorkspace, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace };
227
+ export { type Drawing, DrawingList, DrawingListItem, DrawingsDialog, type DrawingsDialogProps, Sidebar, type Workspace, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getWorkspace, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { IDBPDatabase, DBSchema } from 'idb';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import { ReactNode } from 'react';
3
+ import React, { ReactNode } from 'react';
4
4
 
5
5
  interface Drawing {
6
6
  id: string;
@@ -90,6 +90,88 @@ interface DrawingListItemProps {
90
90
  }
91
91
  declare function DrawingListItem({ drawing, isActive, onSelect, onRename, onDelete, canDelete, }: DrawingListItemProps): react_jsx_runtime.JSX.Element;
92
92
 
93
+ /**
94
+ * Workspace Menu Items
95
+ *
96
+ * These components can be inserted into Excalidraw's main menu
97
+ * to provide workspace/multi-drawing functionality.
98
+ */
99
+
100
+ interface WorkspaceMenuItemsProps {
101
+ /**
102
+ * Called when a drawing is selected from the submenu
103
+ */
104
+ onDrawingSelect?: (drawing: Drawing) => void;
105
+ /**
106
+ * Called when "Manage Drawings" is clicked
107
+ */
108
+ onManageDrawings?: () => void;
109
+ /**
110
+ * Render function for menu item - allows integration with Excalidraw's DropdownMenuItem
111
+ */
112
+ renderMenuItem?: (props: {
113
+ icon: React.ReactNode;
114
+ children: React.ReactNode;
115
+ onSelect: () => void;
116
+ shortcut?: string;
117
+ }) => React.ReactNode;
118
+ /**
119
+ * Render function for submenu - allows integration with Excalidraw's DropdownMenuSub
120
+ */
121
+ renderSubMenu?: (props: {
122
+ trigger: React.ReactNode;
123
+ children: React.ReactNode;
124
+ }) => React.ReactNode;
125
+ /**
126
+ * Render function for separator
127
+ */
128
+ renderSeparator?: () => React.ReactNode;
129
+ }
130
+ /**
131
+ * WorkspaceMenuItems - provides menu items for workspace functionality
132
+ *
133
+ * Usage with Excalidraw's menu system:
134
+ * ```tsx
135
+ * <MainMenu>
136
+ * <MainMenu.DefaultItems.LoadScene />
137
+ * <MainMenu.DefaultItems.SaveToActiveFile />
138
+ * <MainMenu.Separator />
139
+ * <WorkspaceMenuItems
140
+ * renderMenuItem={(props) => <MainMenu.Item {...props} />}
141
+ * renderSubMenu={(props) => <MainMenu.Sub>{props.children}</MainMenu.Sub>}
142
+ * renderSeparator={() => <MainMenu.Separator />}
143
+ * />
144
+ * </MainMenu>
145
+ * ```
146
+ */
147
+ declare const WorkspaceMenuItems: React.FC<WorkspaceMenuItemsProps>;
148
+
149
+ /**
150
+ * Drawings Dialog
151
+ *
152
+ * A modal dialog for managing all drawings in the workspace.
153
+ * Provides full CRUD operations: view, rename, delete, create new.
154
+ */
155
+
156
+ interface DrawingsDialogProps {
157
+ /**
158
+ * Whether the dialog is open
159
+ */
160
+ open: boolean;
161
+ /**
162
+ * Called when the dialog should close
163
+ */
164
+ onClose: () => void;
165
+ /**
166
+ * Called when a drawing is selected
167
+ */
168
+ onDrawingSelect?: (drawing: Drawing) => void;
169
+ }
170
+ /**
171
+ * DrawingsDialog - modal for managing workspace drawings
172
+ */
173
+ declare const DrawingsDialog: React.FC<DrawingsDialogProps>;
174
+
93
175
  interface ExcalidrawAPI {
94
176
  getSceneElements: () => unknown[];
95
177
  getAppState: () => Record<string, unknown>;
@@ -142,4 +224,4 @@ interface WorkspacePluginProps {
142
224
  */
143
225
  declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
144
226
 
145
- export { type Drawing, DrawingList, DrawingListItem, Sidebar, type Workspace, type WorkspaceContextValue, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getWorkspace, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace };
227
+ export { type Drawing, DrawingList, DrawingListItem, DrawingsDialog, type DrawingsDialogProps, Sidebar, type Workspace, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getWorkspace, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace };