Files
lit-examples/lit-components/lit-node-editor/store.ts
rodydavis b9e42c3ef4
Build and Deploy / build-and-deploy (push) Has been cancelled
fix(lit-components): fix rendering and interaction issues in force-graph, html-table, and draggable-dom
- lit-force-graph: Refactored for instance reuse, better lifecycle management, and added dynamic imports for AR/VR modes.
- lit-html-table: Improved visual design, readability of headers, and fixed reactivity in editable mode.
- lit-draggable-dom: Fixed clipping issues by switching to relative/absolute positioning and resolved a panning speed bug caused by CSS variable inheritance.
2026-05-17 00:41:14 -07:00

146 lines
2.9 KiB
TypeScript

/**
* Node or Edge ID type
*/
export type ID = string;
/**
* Node store with NodeEdges
*/
export class Store<T extends BaseNode> {
nodes: T[] = [];
edges: NodeEdge[] = [];
/**
* Parse a JSON object into a Store
*
* @param value JSON String
* @returns Store
*/
static fromJson<T extends BaseNode>(value: string) {
const { nodes, edges } = JSON.parse(value);
const store = new Store<T>();
if (nodes) store.nodes = nodes;
if (edges) store.edges = edges;
return store;
}
/**
* Save the store to a JSON string
*
* @returns JSON String
*/
toJson() {
const value = {
nodes: this.nodes,
edges: this.edges,
};
return JSON.stringify(value, null, 2);
}
private getNodeIndex(id: ID): number {
return this.nodes.findIndex((n) => n.id === id);
}
createNode(node: T): void {
const index = this.getNodeIndex(node.id);
if (index === -1) {
this.nodes.push(node);
} else {
this.nodes[index] = node;
}
}
retrieveNode(id: ID): T | undefined {
return this.nodes.find((node) => node.id === id);
}
retrieveEdgesForNode(id: ID): NodeEdge[] {
return this.edges.filter(
(edge) => edge.startNode === id || edge.endNode === id
);
}
updateNode(node: T): void {
const index = this.getNodeIndex(node.id);
if (index === -1) return;
this.nodes[index] = node;
}
deleteNode(id: ID): void {
const index = this.getNodeIndex(id);
if (index === -1) return;
this.nodes.splice(index, 1);
// Delete connected edges
const nodeEdges = this.retrieveEdgesForNode(id);
for (const edge of nodeEdges) {
this.deleteEdge(edge.id);
}
}
private getEdgeIndex(id: ID): number {
return this.edges.findIndex((n) => n.id === id);
}
createEdge(edge: NodeEdge): void {
const index = this.getEdgeIndex(edge.id);
if (index === -1) {
this.edges.push(edge);
} else {
this.edges[index] = edge;
}
}
retrieveEdge(id: ID): NodeEdge | undefined {
return this.edges.find((edge) => edge.id === id);
}
updateEdge(edge: NodeEdge): void {
const index = this.getEdgeIndex(edge.id);
if (index === -1) return;
this.edges[index] = edge;
}
deleteEdge(id: ID): void {
const index = this.getEdgeIndex(id);
if (index === -1) return;
this.edges.splice(index, 1);
}
linkNodes(start: T, end: T, name: string): void {
const randomId = generateRandomId();
this.createEdge({
id: randomId,
startNode: start.id,
endNode: end.id,
name,
type: "edge",
});
}
}
/**
* Node Edge
*/
export interface NodeEdge extends BaseNode {
startNode: ID;
endNode: ID;
type: "edge";
}
/**
* Base Node
*/
export interface BaseNode {
id: ID;
name: string;
readonly type: "node" | "edge";
}
function generateRandomId(): string {
return (
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15)
);
}