import { useMemo } from 'react';
import { observer } from 'mobx-react';
import { computed } from 'mobx';
import ElementContext from '../utils/ElementContext';
import { Edge, Graph, isGraph, isEdge, isNode, Node } from '../types';
import { ATTR_DATA_ID, ATTR_DATA_KIND, ATTR_DATA_TYPE } from '../const';
import ComputeElementDimensions from './ComputeElementDimensions';
import { useDndManager } from '../behavior/useDndManager';
interface ElementWrapperProps {
element: Graph | Edge | Node;
level?: number; // used for groups to set z-index keeping child groups drawn on top of their parent.
}
const NodeElementComponent: React.FunctionComponent<{ element: Node }> = observer(({ element }) => {
const dndManager = useDndManager();
const isDragging = dndManager.isDragging();
const dragItem = dndManager.getItem();
const controller = element.hasController() && element.getController();
const isVisible = useMemo(
() => computed(() => controller && controller.shouldRenderNode(element)),
[element, controller]
);
if (isVisible.get() || (isDragging && dragItem === element)) {
return ;
}
return null;
});
// in a separate component so that changes to behaviors do not re-render children
const ElementComponent: React.FunctionComponent = observer(({ element }) => {
const kind = element.getKind();
const type = element.getType();
const controller = element.hasController() && element.getController();
const Component = useMemo(() => controller && controller.getComponent(kind, type), [controller, kind, type]);
if (Component) {
return (
);
}
return null;
});
const ElementChildren: React.FunctionComponent = observer(({ element, level }) => (
<>
{element
.getChildren()
.filter(isEdge)
.map((e) => (
))}
{element
.getChildren()
.filter(isNode)
.map((e) => (
))}
>
));
const ElementWrapper: React.FunctionComponent = observer(({ element, level = 0 }) => {
if (!element.isVisible()) {
if (!isNode(element) || element.isDimensionsInitialized()) {
return null;
}
}
if (isEdge(element)) {
const source = element.getSourceAnchorNode();
const target = element.getTargetAnchorNode();
if ((source && !source.isVisible()) || (target && !target.isVisible())) {
return null;
}
}
const commonAttrs = {
[ATTR_DATA_ID]: element.getId(),
[ATTR_DATA_KIND]: element.getKind(),
[ATTR_DATA_TYPE]: element.getType()
};
if (isGraph(element)) {
return (
);
}
if (isNode(element)) {
if (!element.isDimensionsInitialized()) {
return (
);
}
if (!element.isGroup() || element.isCollapsed()) {
const { x, y } = element.getPosition();
return (
);
}
return (
);
}
return (
);
});
export default ElementWrapper;