react-embed-docs 0.1.0

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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/dist/client/components/Breadcrumbs.d.ts +21 -0
  4. package/dist/client/components/Breadcrumbs.d.ts.map +1 -0
  5. package/dist/client/components/Breadcrumbs.js +123 -0
  6. package/dist/client/components/DocsLayout.d.ts +20 -0
  7. package/dist/client/components/DocsLayout.d.ts.map +1 -0
  8. package/dist/client/components/DocsLayout.js +387 -0
  9. package/dist/client/components/DocumentContent.d.ts +5 -0
  10. package/dist/client/components/DocumentContent.d.ts.map +1 -0
  11. package/dist/client/components/DocumentContent.js +15 -0
  12. package/dist/client/components/DocumentEdit.d.ts +6 -0
  13. package/dist/client/components/DocumentEdit.d.ts.map +1 -0
  14. package/dist/client/components/DocumentEdit.js +153 -0
  15. package/dist/client/components/DocumentList.d.ts +5 -0
  16. package/dist/client/components/DocumentList.d.ts.map +1 -0
  17. package/dist/client/components/DocumentList.js +39 -0
  18. package/dist/client/components/DocumentProvider.d.ts +42 -0
  19. package/dist/client/components/DocumentProvider.d.ts.map +1 -0
  20. package/dist/client/components/DocumentProvider.js +47 -0
  21. package/dist/client/components/DocumentView.d.ts +6 -0
  22. package/dist/client/components/DocumentView.d.ts.map +1 -0
  23. package/dist/client/components/DocumentView.js +58 -0
  24. package/dist/client/components/DragOverlayItem.d.ts +5 -0
  25. package/dist/client/components/DragOverlayItem.d.ts.map +1 -0
  26. package/dist/client/components/DragOverlayItem.js +9 -0
  27. package/dist/client/components/EmojiPicker.d.ts +8 -0
  28. package/dist/client/components/EmojiPicker.d.ts.map +1 -0
  29. package/dist/client/components/EmojiPicker.js +48 -0
  30. package/dist/client/components/ExportButton.d.ts +22 -0
  31. package/dist/client/components/ExportButton.d.ts.map +1 -0
  32. package/dist/client/components/ExportButton.js +97 -0
  33. package/dist/client/components/Layout.d.ts +7 -0
  34. package/dist/client/components/Layout.d.ts.map +1 -0
  35. package/dist/client/components/Layout.js +172 -0
  36. package/dist/client/components/ReactEmbedDocs.d.ts +8 -0
  37. package/dist/client/components/ReactEmbedDocs.d.ts.map +1 -0
  38. package/dist/client/components/ReactEmbedDocs.js +8 -0
  39. package/dist/client/components/SearchInput.d.ts +2 -0
  40. package/dist/client/components/SearchInput.d.ts.map +1 -0
  41. package/dist/client/components/SearchInput.js +7 -0
  42. package/dist/client/components/Sidebar.d.ts +10 -0
  43. package/dist/client/components/Sidebar.d.ts.map +1 -0
  44. package/dist/client/components/Sidebar.js +176 -0
  45. package/dist/client/components/SortableTreeItem.d.ts +13 -0
  46. package/dist/client/components/SortableTreeItem.d.ts.map +1 -0
  47. package/dist/client/components/SortableTreeItem.js +24 -0
  48. package/dist/client/components/VersionHistory.d.ts +14 -0
  49. package/dist/client/components/VersionHistory.d.ts.map +1 -0
  50. package/dist/client/components/VersionHistory.js +102 -0
  51. package/dist/client/hooks/useCollaboration.d.ts +99 -0
  52. package/dist/client/hooks/useCollaboration.d.ts.map +1 -0
  53. package/dist/client/hooks/useCollaboration.js +180 -0
  54. package/dist/client/hooks/useDocsQuery.d.ts +84 -0
  55. package/dist/client/hooks/useDocsQuery.d.ts.map +1 -0
  56. package/dist/client/hooks/useDocsQuery.js +241 -0
  57. package/dist/client/hooks/useExport.d.ts +31 -0
  58. package/dist/client/hooks/useExport.d.ts.map +1 -0
  59. package/dist/client/hooks/useExport.js +66 -0
  60. package/dist/client/hooks/useFileUpload.d.ts +44 -0
  61. package/dist/client/hooks/useFileUpload.d.ts.map +1 -0
  62. package/dist/client/hooks/useFileUpload.js +193 -0
  63. package/dist/client/hooks/useSystemTheme.d.ts +2 -0
  64. package/dist/client/hooks/useSystemTheme.d.ts.map +1 -0
  65. package/dist/client/hooks/useSystemTheme.js +19 -0
  66. package/dist/client/hooks/useVersions.d.ts +105 -0
  67. package/dist/client/hooks/useVersions.d.ts.map +1 -0
  68. package/dist/client/hooks/useVersions.js +129 -0
  69. package/dist/client/index.d.ts +23 -0
  70. package/dist/client/index.d.ts.map +1 -0
  71. package/dist/client/index.js +18 -0
  72. package/dist/client/lib/blocknoteTheme.d.ts +13 -0
  73. package/dist/client/lib/blocknoteTheme.d.ts.map +1 -0
  74. package/dist/client/lib/blocknoteTheme.js +76 -0
  75. package/dist/client/lib/path.d.ts +8 -0
  76. package/dist/client/lib/path.d.ts.map +1 -0
  77. package/dist/client/lib/path.js +30 -0
  78. package/dist/client/providers/DocumentProvider.d.ts +1 -0
  79. package/dist/client/providers/DocumentProvider.d.ts.map +1 -0
  80. package/dist/client/providers/DocumentProvider.js +1 -0
  81. package/dist/server/CollaborationService.d.ts +134 -0
  82. package/dist/server/CollaborationService.d.ts.map +1 -0
  83. package/dist/server/CollaborationService.js +307 -0
  84. package/dist/server/DocsService.d.ts +115 -0
  85. package/dist/server/DocsService.d.ts.map +1 -0
  86. package/dist/server/DocsService.js +512 -0
  87. package/dist/server/ExportService.d.ts +106 -0
  88. package/dist/server/ExportService.d.ts.map +1 -0
  89. package/dist/server/ExportService.js +501 -0
  90. package/dist/server/FilesService.d.ts +44 -0
  91. package/dist/server/FilesService.d.ts.map +1 -0
  92. package/dist/server/FilesService.js +78 -0
  93. package/dist/server/VersioningService.d.ts +112 -0
  94. package/dist/server/VersioningService.d.ts.map +1 -0
  95. package/dist/server/VersioningService.js +264 -0
  96. package/dist/server/db.d.ts +7 -0
  97. package/dist/server/db.d.ts.map +1 -0
  98. package/dist/server/db.js +22 -0
  99. package/dist/server/index.d.ts +55 -0
  100. package/dist/server/index.d.ts.map +1 -0
  101. package/dist/server/index.js +36 -0
  102. package/dist/server/routes.d.ts +9 -0
  103. package/dist/server/routes.d.ts.map +1 -0
  104. package/dist/server/routes.js +483 -0
  105. package/dist/server/schema.d.ts +587 -0
  106. package/dist/server/schema.d.ts.map +1 -0
  107. package/dist/server/schema.js +126 -0
  108. package/dist/shared/types.d.ts +314 -0
  109. package/dist/shared/types.d.ts.map +1 -0
  110. package/dist/shared/types.js +48 -0
  111. package/drizzle/migrations/0000_gray_monster_badoon.sql +88 -0
  112. package/drizzle/migrations/meta/0000_snapshot.json +574 -0
  113. package/drizzle/migrations/meta/_journal.json +13 -0
  114. package/package.json +109 -0
  115. package/styles/docs.css +981 -0
@@ -0,0 +1,307 @@
1
+ import { eq, and, sql } from 'drizzle-orm';
2
+ import * as Y from 'yjs';
3
+ import { Awareness } from 'y-protocols/awareness';
4
+ import { documentsTable, documentPresenceTable } from './schema.js';
5
+ /**
6
+ * Service for real-time collaborative editing using Yjs
7
+ */
8
+ export class CollaborationService {
9
+ db;
10
+ docs = new Map();
11
+ awarenessMap = new Map();
12
+ updateTimers = new Map();
13
+ DEBOUNCE_MS = 500;
14
+ constructor(db) {
15
+ this.db = db;
16
+ }
17
+ /**
18
+ * Get or create a Yjs document for collaborative editing
19
+ */
20
+ async getOrCreateYDoc(documentId) {
21
+ if (this.docs.has(documentId)) {
22
+ return this.docs.get(documentId);
23
+ }
24
+ const ydoc = new Y.Doc();
25
+ // Load persisted state from database
26
+ const persisted = await this.db.query.documentsTable.findFirst({
27
+ where: eq(documentsTable.id, documentId),
28
+ columns: { ydocState: true, content: true },
29
+ });
30
+ if (persisted?.ydocState) {
31
+ // Apply persisted Yjs state
32
+ try {
33
+ const state = Buffer.from(persisted.ydocState, 'base64');
34
+ Y.applyUpdate(ydoc, new Uint8Array(state));
35
+ }
36
+ catch (e) {
37
+ console.warn('Failed to apply persisted Yjs state:', e);
38
+ }
39
+ }
40
+ else if (persisted?.content) {
41
+ // Convert BlockNote JSON to Yjs document
42
+ this.blockNoteToYDoc(ydoc, persisted.content);
43
+ }
44
+ // Set up persistence on updates (debounced)
45
+ ydoc.on('update', (update) => {
46
+ this.schedulePersist(documentId, ydoc);
47
+ });
48
+ this.docs.set(documentId, ydoc);
49
+ return ydoc;
50
+ }
51
+ /**
52
+ * Get or create awareness for a document
53
+ */
54
+ getOrCreateAwareness(documentId) {
55
+ if (this.awarenessMap.has(documentId)) {
56
+ return this.awarenessMap.get(documentId);
57
+ }
58
+ const awareness = new Awareness(this.getOrCreateYDoc(documentId));
59
+ this.awarenessMap.set(documentId, awareness);
60
+ return awareness;
61
+ }
62
+ /**
63
+ * Handle a new WebSocket connection for collaborative editing
64
+ */
65
+ async handleConnection(documentId, userId, userInfo, connection) {
66
+ const ydoc = await this.getOrCreateYDoc(documentId);
67
+ const awareness = this.getOrCreateAwareness(documentId);
68
+ // Generate user color if not provided
69
+ const color = userInfo.color || this.generateColor(userId);
70
+ // Set local awareness state
71
+ const localState = {
72
+ user: { id: userId, name: userInfo.name, color },
73
+ cursor: null,
74
+ selection: null,
75
+ };
76
+ awareness.setLocalState(localState);
77
+ // Send initial sync step 1
78
+ const syncMessage = this.encodeSyncMessage(ydoc);
79
+ connection.send(syncMessage);
80
+ // Handle incoming messages
81
+ connection.onMessage((data) => {
82
+ this.handleMessage(documentId, data, connection, userId);
83
+ });
84
+ // Handle disconnect
85
+ connection.onClose(async () => {
86
+ await this.handleDisconnect(documentId, userId);
87
+ });
88
+ // Update presence in database
89
+ await this.updatePresence(documentId, userId, userInfo.name, color);
90
+ }
91
+ /**
92
+ * Handle incoming WebSocket message
93
+ */
94
+ async handleMessage(documentId, data, connection, userId) {
95
+ const ydoc = await this.getOrCreateYDoc(documentId);
96
+ const awareness = this.getOrCreateAwareness(documentId);
97
+ try {
98
+ // Decode message
99
+ const messageType = data[0];
100
+ if (messageType === 0) {
101
+ // Sync message
102
+ const update = data.slice(1);
103
+ Y.applyUpdate(ydoc, update);
104
+ // Broadcast to other clients
105
+ this.broadcast(documentId, data, userId);
106
+ }
107
+ else if (messageType === 1) {
108
+ // Awareness message
109
+ const awarenessUpdate = data.slice(1);
110
+ awareness.applyUpdate(new Uint8Array(awarenessUpdate));
111
+ // Broadcast awareness to others
112
+ this.broadcast(documentId, data, userId);
113
+ }
114
+ }
115
+ catch (error) {
116
+ console.error('Failed to handle message:', error);
117
+ }
118
+ }
119
+ /**
120
+ * Handle client disconnect
121
+ */
122
+ async handleDisconnect(documentId, userId) {
123
+ // Remove from awareness
124
+ const awareness = this.awarenessMap.get(documentId);
125
+ if (awareness) {
126
+ awareness.setLocalState(null);
127
+ }
128
+ // Remove from database presence
129
+ await this.db
130
+ .delete(documentPresenceTable)
131
+ .where(and(eq(documentPresenceTable.documentId, documentId), eq(documentPresenceTable.userId, userId)));
132
+ // Persist final state
133
+ const ydoc = this.docs.get(documentId);
134
+ if (ydoc) {
135
+ await this.persistYDoc(documentId, ydoc);
136
+ }
137
+ }
138
+ /**
139
+ * Broadcast message to all connected clients except sender
140
+ */
141
+ broadcast(documentId, data, excludeUserId) {
142
+ // This is handled by the WebSocket server implementation
143
+ // The service just prepares the message
144
+ }
145
+ /**
146
+ * Schedule persistence to database (debounced)
147
+ */
148
+ schedulePersist(documentId, ydoc) {
149
+ const existingTimer = this.updateTimers.get(documentId);
150
+ if (existingTimer) {
151
+ clearTimeout(existingTimer);
152
+ }
153
+ const timer = setTimeout(async () => {
154
+ await this.persistYDoc(documentId, ydoc);
155
+ this.updateTimers.delete(documentId);
156
+ }, this.DEBOUNCE_MS);
157
+ this.updateTimers.set(documentId, timer);
158
+ }
159
+ /**
160
+ * Persist Yjs document state to database
161
+ */
162
+ async persistYDoc(documentId, ydoc) {
163
+ try {
164
+ const stateVector = Y.encodeStateAsUpdate(ydoc);
165
+ const ydocState = Buffer.from(stateVector).toString('base64');
166
+ // Convert Yjs back to BlockNote JSON for search indexing
167
+ const content = this.yjsToBlockNote(ydoc);
168
+ await this.db
169
+ .update(documentsTable)
170
+ .set({
171
+ ydocState,
172
+ content: content,
173
+ updatedAt: new Date(),
174
+ })
175
+ .where(eq(documentsTable.id, documentId));
176
+ }
177
+ catch (error) {
178
+ console.error('Failed to persist Yjs document:', error);
179
+ }
180
+ }
181
+ /**
182
+ * Update user presence in database
183
+ */
184
+ async updatePresence(documentId, userId, userName, userColor) {
185
+ // Delete old presence record if exists
186
+ await this.db
187
+ .delete(documentPresenceTable)
188
+ .where(and(eq(documentPresenceTable.documentId, documentId), eq(documentPresenceTable.userId, userId)));
189
+ // Insert new presence
190
+ await this.db.insert(documentPresenceTable).values({
191
+ documentId,
192
+ userId,
193
+ userName,
194
+ userColor,
195
+ lastSeenAt: new Date(),
196
+ });
197
+ }
198
+ /**
199
+ * Get active users for a document
200
+ */
201
+ async getActiveUsers(documentId) {
202
+ const users = await this.db.query.documentPresenceTable.findMany({
203
+ where: eq(documentPresenceTable.documentId, documentId),
204
+ orderBy: (table, { desc }) => [desc(table.lastSeenAt)],
205
+ });
206
+ return users.map((u) => ({
207
+ userId: u.userId,
208
+ userName: u.userName,
209
+ userColor: u.userColor,
210
+ lastSeenAt: u.lastSeenAt,
211
+ }));
212
+ }
213
+ /**
214
+ * Clean up stale presence records (older than 5 minutes)
215
+ */
216
+ async cleanupStalePresence() {
217
+ const result = await this.db
218
+ .delete(documentPresenceTable)
219
+ .where(sql `${documentPresenceTable.lastSeenAt} < NOW() - INTERVAL '5 minutes'`);
220
+ return result.length;
221
+ }
222
+ /**
223
+ * Convert BlockNote content to Yjs document
224
+ */
225
+ blockNoteToYDoc(ydoc, content) {
226
+ const blocks = ydoc.getArray('blocks');
227
+ blocks.delete(0, blocks.length);
228
+ if (Array.isArray(content)) {
229
+ content.forEach((block) => {
230
+ blocks.push([this.serializeBlock(block)]);
231
+ });
232
+ }
233
+ }
234
+ /**
235
+ * Convert Yjs document to BlockNote content
236
+ */
237
+ yjsToBlockNote(ydoc) {
238
+ const blocks = ydoc.getArray('blocks');
239
+ const content = [];
240
+ blocks.forEach((blockData) => {
241
+ content.push(this.deserializeBlock(blockData));
242
+ });
243
+ return content;
244
+ }
245
+ /**
246
+ * Serialize a BlockNote block for Yjs
247
+ */
248
+ serializeBlock(block) {
249
+ return {
250
+ id: block.id || this.generateId(),
251
+ type: block.type,
252
+ props: block.props || {},
253
+ content: block.content || [],
254
+ children: block.children?.map((c) => this.serializeBlock(c)) || [],
255
+ };
256
+ }
257
+ /**
258
+ * Deserialize a Yjs block to BlockNote format
259
+ */
260
+ deserializeBlock(blockData) {
261
+ return {
262
+ id: blockData.id,
263
+ type: blockData.type,
264
+ props: blockData.props || {},
265
+ content: blockData.content || [],
266
+ children: blockData.children?.map((c) => this.deserializeBlock(c)) || [],
267
+ };
268
+ }
269
+ /**
270
+ * Encode sync message for initial document sync
271
+ */
272
+ encodeSyncMessage(ydoc) {
273
+ const state = Y.encodeStateAsUpdate(ydoc);
274
+ const message = new Uint8Array(1 + state.length);
275
+ message[0] = 0; // Sync message type
276
+ message.set(state, 1);
277
+ return message;
278
+ }
279
+ /**
280
+ * Generate a unique ID
281
+ */
282
+ generateId() {
283
+ return Math.random().toString(36).substring(2, 15);
284
+ }
285
+ /**
286
+ * Generate a consistent color for a user
287
+ */
288
+ generateColor(userId) {
289
+ const colors = [
290
+ '#EF4444', // red
291
+ '#F97316', // orange
292
+ '#F59E0B', // amber
293
+ '#84CC16', // lime
294
+ '#10B981', // emerald
295
+ '#06B6D4', // cyan
296
+ '#3B82F6', // blue
297
+ '#8B5CF6', // violet
298
+ '#EC4899', // pink
299
+ '#F43F5E', // rose
300
+ ];
301
+ let hash = 0;
302
+ for (let i = 0; i < userId.length; i++) {
303
+ hash = userId.charCodeAt(i) + ((hash << 5) - hash);
304
+ }
305
+ return colors[Math.abs(hash) % colors.length];
306
+ }
307
+ }
@@ -0,0 +1,115 @@
1
+ import type { CreateDocument, Document, ListDocumentsFilters, ListDocumentsOptions, SearchResult } from '../shared/types.js';
2
+ import { DB } from './db.js';
3
+ import { type UpdateDocument } from './schema.js';
4
+ /**
5
+ * Document without content field - used for list/tree views
6
+ * to reduce payload size
7
+ */
8
+ export type DocumentSummary = Omit<Document, 'content' | 'searchIndex'>;
9
+ /**
10
+ * DocsService
11
+ * Handles all CRUD operations for documents with BlockNote content
12
+ */
13
+ export declare class DocsService {
14
+ private readonly db;
15
+ constructor(db: DB);
16
+ /**
17
+ * List documents with filtering and pagination
18
+ * Returns documents without content field to reduce payload size
19
+ */
20
+ list(filters?: ListDocumentsFilters, options?: ListDocumentsOptions): Promise<{
21
+ documents: DocumentSummary[];
22
+ total: number;
23
+ }>;
24
+ /**
25
+ * Full-text search with ranking using searchIndex column
26
+ * More efficient than JSONB search for large datasets
27
+ */
28
+ searchText(query: string, options?: {
29
+ limit?: number;
30
+ offset?: number;
31
+ }): Promise<{
32
+ results: Array<{
33
+ document: Document;
34
+ rank: number;
35
+ }>;
36
+ total: number;
37
+ }>;
38
+ /**
39
+ * Advanced search with highlighting
40
+ * Searches JSONB content directly for more precise matching
41
+ */
42
+ search(query: string, options?: {
43
+ limit?: number;
44
+ offset?: number;
45
+ }): Promise<{
46
+ results: SearchResult[];
47
+ total: number;
48
+ }>;
49
+ private extractFromContentItem;
50
+ /**
51
+ * Extract text highlights from BlockNote content
52
+ * Returns surrounding context around matched text
53
+ */
54
+ private extractHighlights;
55
+ /**
56
+ * Extract plain text from BlockNote content
57
+ * Used for building search index
58
+ */
59
+ extractTextFromContent(content: unknown): string;
60
+ /**
61
+ * Build search index from title and content
62
+ * Concatenates title and extracted text for full-text search
63
+ */
64
+ buildSearchIndex(title: string, content: unknown): string;
65
+ /**
66
+ * Get document by ID
67
+ */
68
+ getById(id: string): Promise<Document | undefined>;
69
+ /**
70
+ * Get document by slug
71
+ */
72
+ getBySlug(slug: string): Promise<Document | undefined>;
73
+ /**
74
+ * Create new document
75
+ * Automatically generates search index from title and content
76
+ */
77
+ create(data: CreateDocument): Promise<Document>;
78
+ /**
79
+ * Update existing document
80
+ * Rebuilds search index if title or content changes
81
+ */
82
+ update(id: string, data: UpdateDocument): Promise<Document | undefined>;
83
+ /**
84
+ * Soft delete document
85
+ * Sets deletedAt timestamp instead of removing from database
86
+ */
87
+ delete(id: string): Promise<Document | undefined>;
88
+ /**
89
+ * Get children documents by parent ID
90
+ * Returns documents without content field
91
+ */
92
+ getChildren(parentId: string): Promise<DocumentSummary[]>;
93
+ /**
94
+ * Get all documents as flat tree structure
95
+ * Useful for building document tree UI
96
+ * Returns documents without content field
97
+ */
98
+ getTree(): Promise<DocumentSummary[]>;
99
+ /**
100
+ * Reorder document - move to new parent and/or position
101
+ * Automatically reorders siblings to maintain consistent ordering
102
+ */
103
+ reorder(id: string, newParentId: string | null, newOrder: number): Promise<Document | undefined>;
104
+ /**
105
+ * Update just the order field of a document
106
+ */
107
+ updateOrder(id: string, order: number): Promise<Document | undefined>;
108
+ /**
109
+ * Get breadcrumb path for a document
110
+ * Returns array of ancestors from root to parent, plus the document itself
111
+ * Returns documents without content field
112
+ */
113
+ getBreadcrumbs(id: string): Promise<DocumentSummary[]>;
114
+ }
115
+ //# sourceMappingURL=DocsService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocsService.d.ts","sourceRoot":"","sources":["../../src/server/DocsService.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAIV,cAAc,EACd,QAAQ,EACR,oBAAoB,EACpB,oBAAoB,EACpB,YAAY,EACb,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAC5B,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,aAAa,CAAA;AAEpB;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC,CAAA;AAEvE;;;GAGG;AACH,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,EAAE;IAEnC;;;OAGG;IACG,IAAI,CACR,OAAO,GAAE,oBAAyB,EAClC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC;QAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IA0E3D;;;OAGG;IACG,UAAU,CACd,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAChD,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,QAAQ,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IA0CnF;;;OAGG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAChD,OAAO,CAAC;QAAE,OAAO,EAAE,YAAY,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAkDtD,OAAO,CAAC,sBAAsB;IAkB9B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;;OAGG;IACH,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAqChD;;;OAGG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM;IAKzD;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAWxD;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAW5D;;;OAGG;IACG,MAAM,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IAiCrD;;;OAGG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IA8B7E;;;OAGG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAevD;;;OAGG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA2B/D;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAwB3C;;;OAGG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAwEtG;;OAEG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAgB3E;;;;OAIG;IACG,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAyC7D"}