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/README.md +104 -0
- package/dist/index.css +168 -0
- package/dist/index.d.mts +145 -0
- package/dist/index.d.ts +145 -0
- package/dist/index.js +657 -0
- package/dist/index.mjs +610 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Rita Workspace
|
|
2
|
+
|
|
3
|
+
Multi-drawing workspace feature for Rita (Excalidraw fork based on B310-digital/excalidraw).
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
Currently Rita only supports one active drawing at a time. Users need to manually export/import drawings to switch between them.
|
|
8
|
+
|
|
9
|
+
## Solution
|
|
10
|
+
|
|
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
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
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
|
+
}
|
|
54
|
+
|
|
55
|
+
interface Workspace {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
drawings: string[]; // Drawing IDs
|
|
59
|
+
activeDrawingId: string;
|
|
60
|
+
createdAt: Date;
|
|
61
|
+
updatedAt: Date;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
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
|
|
70
|
+
|
|
71
|
+
## Integration with B310 Fork
|
|
72
|
+
|
|
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
|
|
76
|
+
|
|
77
|
+
## Development
|
|
78
|
+
|
|
79
|
+
### Prerequisites
|
|
80
|
+
- Node.js 18+
|
|
81
|
+
- Yarn
|
|
82
|
+
- B310 Excalidraw fork cloned locally
|
|
83
|
+
|
|
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
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Links
|
|
97
|
+
|
|
98
|
+
- **B310 Excalidraw Fork:** https://github.com/b310-digital/excalidraw
|
|
99
|
+
- **Original Excalidraw:** https://github.com/excalidraw/excalidraw
|
|
100
|
+
- **Rita:** Your local Rita deployment
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT (same as Excalidraw)
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/* src/ui/DrawingList/DrawingList.module.css */
|
|
2
|
+
.list {
|
|
3
|
+
list-style: none;
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
}
|
|
7
|
+
.empty {
|
|
8
|
+
padding: 24px 16px;
|
|
9
|
+
text-align: center;
|
|
10
|
+
color: #868e96;
|
|
11
|
+
font-size: 14px;
|
|
12
|
+
}
|
|
13
|
+
.item {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: space-between;
|
|
17
|
+
padding: 10px 16px;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
border-left: 3px solid transparent;
|
|
20
|
+
transition: background 0.1s, border-color 0.1s;
|
|
21
|
+
}
|
|
22
|
+
.item:hover {
|
|
23
|
+
background: #e9ecef;
|
|
24
|
+
}
|
|
25
|
+
.item.active {
|
|
26
|
+
background: #e7f5ff;
|
|
27
|
+
border-left-color: #228be6;
|
|
28
|
+
}
|
|
29
|
+
.itemContent {
|
|
30
|
+
flex: 1;
|
|
31
|
+
min-width: 0;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: 2px;
|
|
35
|
+
}
|
|
36
|
+
.name {
|
|
37
|
+
font-size: 14px;
|
|
38
|
+
font-weight: 500;
|
|
39
|
+
color: #212529;
|
|
40
|
+
white-space: nowrap;
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
text-overflow: ellipsis;
|
|
43
|
+
}
|
|
44
|
+
.date {
|
|
45
|
+
font-size: 11px;
|
|
46
|
+
color: #868e96;
|
|
47
|
+
}
|
|
48
|
+
.editInput {
|
|
49
|
+
font-size: 14px;
|
|
50
|
+
font-weight: 500;
|
|
51
|
+
padding: 2px 6px;
|
|
52
|
+
border: 1px solid #228be6;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
outline: none;
|
|
55
|
+
width: 100%;
|
|
56
|
+
}
|
|
57
|
+
.actions {
|
|
58
|
+
display: flex;
|
|
59
|
+
gap: 4px;
|
|
60
|
+
opacity: 0;
|
|
61
|
+
transition: opacity 0.1s;
|
|
62
|
+
}
|
|
63
|
+
.item:hover .actions {
|
|
64
|
+
opacity: 1;
|
|
65
|
+
}
|
|
66
|
+
.actionButton {
|
|
67
|
+
background: none;
|
|
68
|
+
border: none;
|
|
69
|
+
padding: 4px;
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
font-size: 14px;
|
|
72
|
+
border-radius: 4px;
|
|
73
|
+
line-height: 1;
|
|
74
|
+
}
|
|
75
|
+
.actionButton:hover {
|
|
76
|
+
background: #dee2e6;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* src/ui/Sidebar/Sidebar.module.css */
|
|
80
|
+
.sidebar {
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-direction: column;
|
|
83
|
+
height: 100%;
|
|
84
|
+
background: #f8f9fa;
|
|
85
|
+
border-right: 1px solid #dee2e6;
|
|
86
|
+
font-family:
|
|
87
|
+
-apple-system,
|
|
88
|
+
BlinkMacSystemFont,
|
|
89
|
+
"Segoe UI",
|
|
90
|
+
Roboto,
|
|
91
|
+
sans-serif;
|
|
92
|
+
}
|
|
93
|
+
.header {
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
justify-content: space-between;
|
|
97
|
+
padding: 12px 16px;
|
|
98
|
+
border-bottom: 1px solid #dee2e6;
|
|
99
|
+
}
|
|
100
|
+
.title {
|
|
101
|
+
margin: 0;
|
|
102
|
+
font-size: 14px;
|
|
103
|
+
font-weight: 600;
|
|
104
|
+
color: #495057;
|
|
105
|
+
}
|
|
106
|
+
.closeButton {
|
|
107
|
+
background: none;
|
|
108
|
+
border: none;
|
|
109
|
+
font-size: 16px;
|
|
110
|
+
color: #6c757d;
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
padding: 4px 8px;
|
|
113
|
+
border-radius: 4px;
|
|
114
|
+
}
|
|
115
|
+
.closeButton:hover {
|
|
116
|
+
background: #e9ecef;
|
|
117
|
+
color: #495057;
|
|
118
|
+
}
|
|
119
|
+
.content {
|
|
120
|
+
flex: 1;
|
|
121
|
+
overflow-y: auto;
|
|
122
|
+
padding: 8px 0;
|
|
123
|
+
}
|
|
124
|
+
.loading {
|
|
125
|
+
padding: 16px;
|
|
126
|
+
text-align: center;
|
|
127
|
+
color: #6c757d;
|
|
128
|
+
font-size: 14px;
|
|
129
|
+
}
|
|
130
|
+
.footer {
|
|
131
|
+
padding: 12px;
|
|
132
|
+
border-top: 1px solid #dee2e6;
|
|
133
|
+
}
|
|
134
|
+
.newButton {
|
|
135
|
+
width: 100%;
|
|
136
|
+
padding: 10px 16px;
|
|
137
|
+
background: #228be6;
|
|
138
|
+
color: white;
|
|
139
|
+
border: none;
|
|
140
|
+
border-radius: 6px;
|
|
141
|
+
font-size: 14px;
|
|
142
|
+
font-weight: 500;
|
|
143
|
+
cursor: pointer;
|
|
144
|
+
transition: background 0.15s;
|
|
145
|
+
}
|
|
146
|
+
.newButton:hover:not(:disabled) {
|
|
147
|
+
background: #1c7ed6;
|
|
148
|
+
}
|
|
149
|
+
.newButton:disabled {
|
|
150
|
+
opacity: 0.6;
|
|
151
|
+
cursor: not-allowed;
|
|
152
|
+
}
|
|
153
|
+
.toggleButton {
|
|
154
|
+
position: fixed;
|
|
155
|
+
top: 12px;
|
|
156
|
+
left: 12px;
|
|
157
|
+
z-index: 100;
|
|
158
|
+
padding: 8px 12px;
|
|
159
|
+
background: #f8f9fa;
|
|
160
|
+
border: 1px solid #dee2e6;
|
|
161
|
+
border-radius: 6px;
|
|
162
|
+
font-size: 16px;
|
|
163
|
+
cursor: pointer;
|
|
164
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
165
|
+
}
|
|
166
|
+
.toggleButton:hover {
|
|
167
|
+
background: #e9ecef;
|
|
168
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { IDBPDatabase, DBSchema } from 'idb';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface Drawing {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
elements: unknown[];
|
|
9
|
+
appState: Record<string, unknown>;
|
|
10
|
+
files: Record<string, unknown>;
|
|
11
|
+
createdAt: number;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
}
|
|
14
|
+
interface Workspace {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
drawingIds: string[];
|
|
18
|
+
activeDrawingId: string | null;
|
|
19
|
+
createdAt: number;
|
|
20
|
+
updatedAt: number;
|
|
21
|
+
}
|
|
22
|
+
interface RitaWorkspaceDB extends DBSchema {
|
|
23
|
+
workspaces: {
|
|
24
|
+
key: string;
|
|
25
|
+
value: Workspace;
|
|
26
|
+
indexes: {
|
|
27
|
+
'by-updated': number;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
drawings: {
|
|
31
|
+
key: string;
|
|
32
|
+
value: Drawing;
|
|
33
|
+
indexes: {
|
|
34
|
+
'by-updated': number;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
declare function getDB(): Promise<IDBPDatabase<RitaWorkspaceDB>>;
|
|
39
|
+
declare function closeDB(): Promise<void>;
|
|
40
|
+
|
|
41
|
+
declare function createDrawing(name?: string, elements?: unknown[], appState?: Record<string, unknown>): Promise<Drawing>;
|
|
42
|
+
declare function getDrawing(id: string): Promise<Drawing | undefined>;
|
|
43
|
+
declare function getAllDrawings(): Promise<Drawing[]>;
|
|
44
|
+
declare function updateDrawing(id: string, updates: Partial<Omit<Drawing, 'id' | 'createdAt'>>): Promise<Drawing | undefined>;
|
|
45
|
+
declare function deleteDrawing(id: string): Promise<boolean>;
|
|
46
|
+
declare function duplicateDrawing(id: string, newName?: string): Promise<Drawing | undefined>;
|
|
47
|
+
|
|
48
|
+
declare function getOrCreateDefaultWorkspace(): Promise<Workspace>;
|
|
49
|
+
declare function getWorkspace(id: string): Promise<Workspace | undefined>;
|
|
50
|
+
declare function updateWorkspace(id: string, updates: Partial<Omit<Workspace, 'id' | 'createdAt'>>): Promise<Workspace | undefined>;
|
|
51
|
+
declare function addDrawingToWorkspace(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
|
|
52
|
+
declare function removeDrawingFromWorkspace(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
|
|
53
|
+
declare function setActiveDrawing(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
|
|
54
|
+
|
|
55
|
+
interface WorkspaceContextValue {
|
|
56
|
+
workspace: Workspace | null;
|
|
57
|
+
drawings: Drawing[];
|
|
58
|
+
activeDrawing: Drawing | null;
|
|
59
|
+
isLoading: boolean;
|
|
60
|
+
error: string | null;
|
|
61
|
+
createNewDrawing: (name?: string) => Promise<Drawing | null>;
|
|
62
|
+
switchDrawing: (id: string) => Promise<void>;
|
|
63
|
+
renameDrawing: (id: string, name: string) => Promise<void>;
|
|
64
|
+
removeDrawing: (id: string) => Promise<void>;
|
|
65
|
+
duplicateCurrentDrawing: () => Promise<Drawing | null>;
|
|
66
|
+
saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>) => Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
declare function useWorkspace(): WorkspaceContextValue;
|
|
69
|
+
interface WorkspaceProviderProps {
|
|
70
|
+
children: ReactNode;
|
|
71
|
+
}
|
|
72
|
+
declare function WorkspaceProvider({ children }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
|
|
73
|
+
|
|
74
|
+
interface SidebarProps {
|
|
75
|
+
isOpen?: boolean;
|
|
76
|
+
onToggle?: () => void;
|
|
77
|
+
width?: number;
|
|
78
|
+
}
|
|
79
|
+
declare function Sidebar({ isOpen, onToggle, width }: SidebarProps): react_jsx_runtime.JSX.Element;
|
|
80
|
+
|
|
81
|
+
declare function DrawingList(): react_jsx_runtime.JSX.Element;
|
|
82
|
+
|
|
83
|
+
interface DrawingListItemProps {
|
|
84
|
+
drawing: Drawing;
|
|
85
|
+
isActive: boolean;
|
|
86
|
+
onSelect: () => void;
|
|
87
|
+
onRename: (name: string) => void;
|
|
88
|
+
onDelete: () => void;
|
|
89
|
+
canDelete: boolean;
|
|
90
|
+
}
|
|
91
|
+
declare function DrawingListItem({ drawing, isActive, onSelect, onRename, onDelete, canDelete, }: DrawingListItemProps): react_jsx_runtime.JSX.Element;
|
|
92
|
+
|
|
93
|
+
interface ExcalidrawAPI {
|
|
94
|
+
getSceneElements: () => unknown[];
|
|
95
|
+
getAppState: () => Record<string, unknown>;
|
|
96
|
+
updateScene: (scene: {
|
|
97
|
+
elements?: unknown[];
|
|
98
|
+
appState?: Record<string, unknown>;
|
|
99
|
+
}) => void;
|
|
100
|
+
resetScene: () => void;
|
|
101
|
+
}
|
|
102
|
+
interface UseExcalidrawBridgeOptions {
|
|
103
|
+
excalidrawAPI: ExcalidrawAPI | null;
|
|
104
|
+
autoSaveInterval?: number;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Hook to bridge workspace state with Excalidraw API
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```tsx
|
|
111
|
+
* const [excalidrawAPI, setExcalidrawAPI] = useState(null);
|
|
112
|
+
*
|
|
113
|
+
* useExcalidrawBridge({ excalidrawAPI });
|
|
114
|
+
*
|
|
115
|
+
* return <Excalidraw excalidrawAPI={setExcalidrawAPI} />;
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
declare function useExcalidrawBridge({ excalidrawAPI, autoSaveInterval, }: UseExcalidrawBridgeOptions): {
|
|
119
|
+
scheduleSave: () => void;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
interface WorkspacePluginProps {
|
|
123
|
+
children: ReactNode;
|
|
124
|
+
defaultSidebarOpen?: boolean;
|
|
125
|
+
sidebarWidth?: number;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* WorkspacePlugin - Wraps Excalidraw to add multi-drawing workspace support
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```tsx
|
|
132
|
+
* import { WorkspacePlugin } from '@rita/workspace';
|
|
133
|
+
*
|
|
134
|
+
* function App() {
|
|
135
|
+
* return (
|
|
136
|
+
* <WorkspacePlugin>
|
|
137
|
+
* <Excalidraw />
|
|
138
|
+
* </WorkspacePlugin>
|
|
139
|
+
* );
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
|
|
144
|
+
|
|
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 };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { IDBPDatabase, DBSchema } from 'idb';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface Drawing {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
elements: unknown[];
|
|
9
|
+
appState: Record<string, unknown>;
|
|
10
|
+
files: Record<string, unknown>;
|
|
11
|
+
createdAt: number;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
}
|
|
14
|
+
interface Workspace {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
drawingIds: string[];
|
|
18
|
+
activeDrawingId: string | null;
|
|
19
|
+
createdAt: number;
|
|
20
|
+
updatedAt: number;
|
|
21
|
+
}
|
|
22
|
+
interface RitaWorkspaceDB extends DBSchema {
|
|
23
|
+
workspaces: {
|
|
24
|
+
key: string;
|
|
25
|
+
value: Workspace;
|
|
26
|
+
indexes: {
|
|
27
|
+
'by-updated': number;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
drawings: {
|
|
31
|
+
key: string;
|
|
32
|
+
value: Drawing;
|
|
33
|
+
indexes: {
|
|
34
|
+
'by-updated': number;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
declare function getDB(): Promise<IDBPDatabase<RitaWorkspaceDB>>;
|
|
39
|
+
declare function closeDB(): Promise<void>;
|
|
40
|
+
|
|
41
|
+
declare function createDrawing(name?: string, elements?: unknown[], appState?: Record<string, unknown>): Promise<Drawing>;
|
|
42
|
+
declare function getDrawing(id: string): Promise<Drawing | undefined>;
|
|
43
|
+
declare function getAllDrawings(): Promise<Drawing[]>;
|
|
44
|
+
declare function updateDrawing(id: string, updates: Partial<Omit<Drawing, 'id' | 'createdAt'>>): Promise<Drawing | undefined>;
|
|
45
|
+
declare function deleteDrawing(id: string): Promise<boolean>;
|
|
46
|
+
declare function duplicateDrawing(id: string, newName?: string): Promise<Drawing | undefined>;
|
|
47
|
+
|
|
48
|
+
declare function getOrCreateDefaultWorkspace(): Promise<Workspace>;
|
|
49
|
+
declare function getWorkspace(id: string): Promise<Workspace | undefined>;
|
|
50
|
+
declare function updateWorkspace(id: string, updates: Partial<Omit<Workspace, 'id' | 'createdAt'>>): Promise<Workspace | undefined>;
|
|
51
|
+
declare function addDrawingToWorkspace(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
|
|
52
|
+
declare function removeDrawingFromWorkspace(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
|
|
53
|
+
declare function setActiveDrawing(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
|
|
54
|
+
|
|
55
|
+
interface WorkspaceContextValue {
|
|
56
|
+
workspace: Workspace | null;
|
|
57
|
+
drawings: Drawing[];
|
|
58
|
+
activeDrawing: Drawing | null;
|
|
59
|
+
isLoading: boolean;
|
|
60
|
+
error: string | null;
|
|
61
|
+
createNewDrawing: (name?: string) => Promise<Drawing | null>;
|
|
62
|
+
switchDrawing: (id: string) => Promise<void>;
|
|
63
|
+
renameDrawing: (id: string, name: string) => Promise<void>;
|
|
64
|
+
removeDrawing: (id: string) => Promise<void>;
|
|
65
|
+
duplicateCurrentDrawing: () => Promise<Drawing | null>;
|
|
66
|
+
saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>) => Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
declare function useWorkspace(): WorkspaceContextValue;
|
|
69
|
+
interface WorkspaceProviderProps {
|
|
70
|
+
children: ReactNode;
|
|
71
|
+
}
|
|
72
|
+
declare function WorkspaceProvider({ children }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
|
|
73
|
+
|
|
74
|
+
interface SidebarProps {
|
|
75
|
+
isOpen?: boolean;
|
|
76
|
+
onToggle?: () => void;
|
|
77
|
+
width?: number;
|
|
78
|
+
}
|
|
79
|
+
declare function Sidebar({ isOpen, onToggle, width }: SidebarProps): react_jsx_runtime.JSX.Element;
|
|
80
|
+
|
|
81
|
+
declare function DrawingList(): react_jsx_runtime.JSX.Element;
|
|
82
|
+
|
|
83
|
+
interface DrawingListItemProps {
|
|
84
|
+
drawing: Drawing;
|
|
85
|
+
isActive: boolean;
|
|
86
|
+
onSelect: () => void;
|
|
87
|
+
onRename: (name: string) => void;
|
|
88
|
+
onDelete: () => void;
|
|
89
|
+
canDelete: boolean;
|
|
90
|
+
}
|
|
91
|
+
declare function DrawingListItem({ drawing, isActive, onSelect, onRename, onDelete, canDelete, }: DrawingListItemProps): react_jsx_runtime.JSX.Element;
|
|
92
|
+
|
|
93
|
+
interface ExcalidrawAPI {
|
|
94
|
+
getSceneElements: () => unknown[];
|
|
95
|
+
getAppState: () => Record<string, unknown>;
|
|
96
|
+
updateScene: (scene: {
|
|
97
|
+
elements?: unknown[];
|
|
98
|
+
appState?: Record<string, unknown>;
|
|
99
|
+
}) => void;
|
|
100
|
+
resetScene: () => void;
|
|
101
|
+
}
|
|
102
|
+
interface UseExcalidrawBridgeOptions {
|
|
103
|
+
excalidrawAPI: ExcalidrawAPI | null;
|
|
104
|
+
autoSaveInterval?: number;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Hook to bridge workspace state with Excalidraw API
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```tsx
|
|
111
|
+
* const [excalidrawAPI, setExcalidrawAPI] = useState(null);
|
|
112
|
+
*
|
|
113
|
+
* useExcalidrawBridge({ excalidrawAPI });
|
|
114
|
+
*
|
|
115
|
+
* return <Excalidraw excalidrawAPI={setExcalidrawAPI} />;
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
declare function useExcalidrawBridge({ excalidrawAPI, autoSaveInterval, }: UseExcalidrawBridgeOptions): {
|
|
119
|
+
scheduleSave: () => void;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
interface WorkspacePluginProps {
|
|
123
|
+
children: ReactNode;
|
|
124
|
+
defaultSidebarOpen?: boolean;
|
|
125
|
+
sidebarWidth?: number;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* WorkspacePlugin - Wraps Excalidraw to add multi-drawing workspace support
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```tsx
|
|
132
|
+
* import { WorkspacePlugin } from '@rita/workspace';
|
|
133
|
+
*
|
|
134
|
+
* function App() {
|
|
135
|
+
* return (
|
|
136
|
+
* <WorkspacePlugin>
|
|
137
|
+
* <Excalidraw />
|
|
138
|
+
* </WorkspacePlugin>
|
|
139
|
+
* );
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
|
|
144
|
+
|
|
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 };
|