Files
web-cad/frontend/src/crdt/YjsDocument.ts
T

151 lines
3.4 KiB
TypeScript
Raw Normal View History

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;
color?: string;
lineType?: string;
transparency?: number;
sortOrder?: number;
};
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();
}
// 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);
}
// Helper method to create a rectangle element
createRectangle(x: number, y: number, width: number, height: number): void {
const element: Element = {
id: Date.now().toString(),
type: 'rect',
layerId: 'default',
x,
y,
width,
height,
properties: {}
};
this.createElement(element);
}
// Helper method to create a circle element
createCircle(x: number, y: number, radius: number): void {
const element: Element = {
id: Date.now().toString(),
type: 'circle',
layerId: 'default',
x: x - radius,
y: y - radius,
width: radius * 2,
height: radius * 2,
properties: { radius }
};
this.createElement(element);
}
// Helper method to create a line element
createLine(x1: number, y1: number, x2: number, y2: number): void {
const element: Element = {
id: Date.now().toString(),
type: 'line',
layerId: 'default',
x: Math.min(x1, x2),
y: Math.min(y1, y2),
width: Math.abs(x2 - x1),
height: Math.abs(y2 - y1),
properties: { x1, y1, x2, y2 }
};
this.createElement(element);
}
}