refactor: replace workspace engine and drag/pointer logic with a new layout system and physics model.refactor: replace the workspace engine and drag/pointer logic with a new layout system.

This commit is contained in:
2025-11-26 12:28:02 +01:00
parent e5e71cc5f8
commit 27eea08605
10 changed files with 264 additions and 3970 deletions
+96
View File
@@ -0,0 +1,96 @@
export interface LayoutItem {
id: string;
x: number;
y: number;
z: number;
rotation: number;
width: number;
height: number;
ref: HTMLElement;
}
export class LayoutStore {
items = new Map<string, LayoutItem>();
zCounter = 100;
register(id: string, ref: HTMLElement, initialData: Partial<LayoutItem>) {
const existing = this.items.get(id);
this.items.set(id, {
id,
ref,
x: existing?.x ?? 0,
y: existing?.y ?? 0,
z: existing?.z ?? 0,
rotation: existing?.rotation ?? 0,
width: 200,
height: 200,
...initialData
});
}
initialize(id: string, ref: HTMLElement, config: {
x?: number;
y?: number;
rotation?: number;
z: number;
width: number;
height: number;
}) {
if (this.items.has(id)) {
// Update ref if it changed
const item = this.items.get(id)!;
if (item.ref !== ref) {
item.ref = ref;
this.update(id, {}); // Re-apply styles
}
return;
}
// Apply defaults if not provided
const x = config.x ?? Math.random() * 500;
const y = config.y ?? Math.random() * 500;
const rotation = config.rotation ?? (Math.random() * 10 - 5);
this.register(id, ref, {
...config,
x,
y,
rotation
});
// Apply immediately
this.update(id, {});
}
unregister(id: string) {
this.items.delete(id);
}
// Fast Update: Updates internal state AND applies CSS transform immediately
update(id: string, updates: Partial<LayoutItem>) {
const item = this.items.get(id);
if (!item) return;
Object.assign(item, updates);
if (updates.z) this.zCounter = Math.max(this.zCounter, updates.z);
// Direct DOM manipulation (The "Engine" part)
if (item.ref) {
item.ref.style.transform =
`translate3d(${item.x}px, ${item.y}px, 0) rotate(${item.rotation}deg)`;
item.ref.style.zIndex = String(item.z);
}
}
bringToFront(id: string) {
this.update(id, { z: ++this.zCounter });
}
getSnapshot() {
// Return serializable data for persistence
return Array.from(this.items.values()).map(({ ref: _ref, ...data }) => data);
}
}
// Singleton or Context-provided instance
export const globalLayout = new LayoutStore();