UNPKG

@joint/react

Version:

React bindings and hooks for JointJS to build interactive diagrams and graphs.

132 lines (122 loc) 4.07 kB
import type { dia } from '@joint/core'; import { REACT_TYPE } from '../../models/react-element'; import type { GraphLink } from '../../types/link-types'; import type { GraphElement } from '../../types/element-types'; import { isCellInstance, isLinkInstance, isUnsized } from '../is'; import { getTargetOrSource } from './get-link-targe-and-source-ids'; import { isReactElement } from '../is-react-element'; interface Options { readonly graph: dia.Graph; readonly initialLinks?: Array<dia.Link | GraphLink>; readonly initialElements?: Array<dia.Element | GraphElement>; } /** * Process a link: convert GraphLink to a standard JointJS link if needed. * @param link - The link to process. * @group utils * @description * This function is used to process a link and convert it to a standard JointJS link if needed. * It also converts the source and target of the link to a standard format. * @returns * A standard JointJS link or a JSON representation of the link. */ export function processLink(link: dia.Link | GraphLink): dia.Link | dia.Cell.JSON { if (isLinkInstance(link)) { const json = link.toJSON(); const source = getTargetOrSource(json.source); const target = getTargetOrSource(json.target); return { ...json, source, target, }; } const source = getTargetOrSource(link.source); const target = getTargetOrSource(link.target); return { ...link, type: link.type ?? 'standard.Link', source, target, } as dia.Cell.JSON; } /** * Set links to the graph. * @param options - The options for setting links. * @group utils * @description * This function is used to set links to the graph. * It processes the links and adds them to the graph. * It also converts the source and target of the links to a standard format. */ export function setLinks(options: Options) { const { graph, initialLinks } = options; if (initialLinks === undefined) { return; } // Process links if provided. graph.addCells( initialLinks.map((item) => { const link = processLink(item); if (link.z === undefined) { link.z = 0; } return link; }) ); } /** * Process an element: create a ReactElement if applicable, otherwise a standard Cell. * @param element - The element to process. * @param unsizedIds - A set of unsized element IDs. * @returns A standard JointJS element or a JSON representation of the element. * @group utils * @description * This function is used to process an element and convert it to a standard JointJS element if needed. * It also checks if the element is a ReactElement and if it has a size. * If the element is a ReactElement and has no size, it adds its ID to the unsizedIds set. * @private */ export function processElement<T extends dia.Element | GraphElement>( element: T, unsizedIds?: Set<string> ): dia.Element | dia.Cell.JSON { const stringId = String(element.id); if (isCellInstance(element)) { const size = element.size(); if (isReactElement(element) && isUnsized(size.width, size.height)) { unsizedIds?.add(stringId); } return element; } const { type = REACT_TYPE, x, y, width, height } = element; if (isUnsized(width, height)) { unsizedIds?.add(stringId); } return { type, position: { x, y }, size: { width, height }, ...element, } as dia.Cell.JSON; } /** * Set elements to the graph. * @param options - The options for setting elements. * @group utils * @description * This function is used to set elements to the graph. * @returns A set of unsized element IDs. * It processes the elements and adds them to the graph. * It also checks for unsized elements and returns their IDs. */ export function setElements(options: Options) { const { graph, initialElements } = options; if (initialElements === undefined) { return new Set<string>(); } const unsizedIds = new Set<string>(); // Process elements if provided. graph.addCells(initialElements.map((item) => processElement(item, unsizedIds))); return unsizedIds; }