2026-06-22 07:20:52 +00:00
|
|
|
import * as Y from 'yjs';
|
|
|
|
|
|
|
|
|
|
type ProjectMeta = {
|
|
|
|
|
id: string;
|
|
|
|
|
name: string;
|
|
|
|
|
createdAt: number;
|
|
|
|
|
updatedAt: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type Layer = {
|
|
|
|
|
id: string;
|
|
|
|
|
name: string;
|
|
|
|
|
visible: boolean;
|
|
|
|
|
locked: boolean;
|
2026-06-22 20:55:57 +00:00
|
|
|
color?: string;
|
|
|
|
|
lineType?: string;
|
|
|
|
|
transparency?: number;
|
|
|
|
|
sortOrder?: number;
|
2026-06-22 07:20:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type Element = {
|
|
|
|
|
id: string;
|
|
|
|
|
type: string;
|
|
|
|
|
layerId: string;
|
|
|
|
|
x: number;
|
|
|
|
|
y: number;
|
|
|
|
|
width: number;
|
|
|
|
|
height: number;
|
|
|
|
|
properties: Record<string, any>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type Block = {
|
|
|
|
|
id: string;
|
|
|
|
|
name: string;
|
|
|
|
|
elements: string[]; // element IDs
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type BlockInstance = {
|
|
|
|
|
id: string;
|
|
|
|
|
blockId: string;
|
|
|
|
|
x: number;
|
|
|
|
|
y: number;
|
|
|
|
|
properties: Record<string, any>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export class YjsDocument {
|
|
|
|
|
doc: Y.Doc;
|
|
|
|
|
projectMeta: Y.Map<any>;
|
|
|
|
|
layers: Y.Map<Layer>;
|
|
|
|
|
elements: Y.Array<Element>;
|
|
|
|
|
blocks: Y.Map<Block>;
|
|
|
|
|
blockInstances: Y.Array<BlockInstance>;
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
this.doc = new Y.Doc();
|
|
|
|
|
this.projectMeta = this.doc.getMap('projectMeta');
|
|
|
|
|
this.layers = this.doc.getMap('layers');
|
|
|
|
|
this.elements = this.doc.getArray('elements');
|
|
|
|
|
this.blocks = this.doc.getMap('blocks');
|
|
|
|
|
this.blockInstances = this.doc.getArray('blockInstances');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
destroy() {
|
|
|
|
|
this.doc.destroy();
|
|
|
|
|
}
|
2026-06-22 21:05:20 +00:00
|
|
|
|
|
|
|
|
// Create a new element
|
|
|
|
|
createElement(element: Element): void {
|
|
|
|
|
this.doc.transact(() => {
|
|
|
|
|
this.elements.push([element]);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update an existing element
|
|
|
|
|
updateElement(id: string, updates: Partial<Element>): void {
|
|
|
|
|
this.doc.transact(() => {
|
|
|
|
|
const index = this.elements.toArray().findIndex(el => el.id === id);
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
const currentElement = this.elements.get(index);
|
|
|
|
|
const updatedElement = { ...currentElement, ...updates };
|
|
|
|
|
this.elements.delete(index, 1);
|
|
|
|
|
this.elements.insert(index, [updatedElement]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete an element
|
|
|
|
|
deleteElement(id: string): void {
|
|
|
|
|
this.doc.transact(() => {
|
|
|
|
|
const index = this.elements.toArray().findIndex(el => el.id === id);
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
this.elements.delete(index, 1);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get all elements
|
|
|
|
|
getElements(): Element[] {
|
|
|
|
|
return this.elements.toArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get element by ID
|
|
|
|
|
getElementById(id: string): Element | undefined {
|
|
|
|
|
return this.elements.toArray().find(el => el.id === id);
|
|
|
|
|
}
|
2026-06-22 07:20:52 +00:00
|
|
|
}
|