schyma
Version:
JSON Schemas Visualizer React component
181 lines • 9.35 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importStar(require("react"));
const react_flow_smart_edge_1 = require("@tisoap/react-flow-smart-edge");
const reactflow_1 = require("reactflow");
const reusables_1 = require("../utils/reusables");
const dagreUtils_1 = require("../utils/dagreUtils");
const position = { x: 0, y: 0, zoom: 0.2 };
const initialEdges = [
{
id: 'edges-e5-7',
source: '0',
target: '1',
label: '+',
labelBgPadding: [8, 4],
labelBgBorderRadius: 4,
animated: true,
type: 'smart',
markerEnd: {
type: reactflow_1.MarkerType.ArrowClosed,
},
},
];
function Flow({ initialNode, nNodes, setnNodes, setCurrentNode, schema }) {
const { nodes: layoutedNodes, edges: layoutedEdges } = (0, dagreUtils_1.getLayoutedElements)([initialNode], initialEdges);
const [nodes, setNodes, onNodesChange] = (0, reactflow_1.useNodesState)(layoutedNodes);
const [edges, setEdges, onEdgesChange] = (0, reactflow_1.useEdgesState)(layoutedEdges);
const { setCenter } = (0, reactflow_1.useReactFlow)();
const onConnect = (0, react_1.useCallback)((connection) => setEdges((eds) => (0, reactflow_1.addEdge)(Object.assign(Object.assign({}, connection), { type: reactflow_1.ConnectionLineType.SmoothStep, animated: true }), eds)),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]);
const extractChildren = (props, parent) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const children = [];
for (const prop in props) {
const id = String(Math.floor(Math.random() * 1000000));
if (props[prop].$ref) {
const res = yield (0, reusables_1.resolveRef)(props[prop].$ref, schema);
children.push({
id,
type: 'input',
data: Object.assign(Object.assign(Object.assign(Object.assign({}, props[prop]), { label: prop, parent: parent.id, relations: Object.assign(Object.assign({}, parent.relations), { [parent.id]: 'node' }) }), res), { children: [] }),
position: position,
sourcePosition: reactflow_1.Position.Right,
targetPosition: reactflow_1.Position.Left,
});
}
else {
children.push({
id,
type: 'input',
data: Object.assign(Object.assign({}, props[prop]), { label: prop, id, parent: parent.id, relations: Object.assign(Object.assign({}, parent.relations), { [parent.id]: 'node' }), children: [] }),
position: position,
sourcePosition: reactflow_1.Position.Right,
targetPosition: reactflow_1.Position.Left,
});
}
}
return children;
});
(0, react_1.useEffect)(() => {
const fetchInitialChildren = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
const newNodes = [];
const properties = initialNode.data.properties;
const children = yield extractChildren(properties, initialNode);
newNodes.push({
id: initialNode.id,
type: 'input',
data: {
children,
label: initialNode.data.label,
description: initialNode.data.description,
properties: initialNode.data.properties,
relations: initialNode.data.relations,
},
position: { x: 0, y: 0 },
sourcePosition: reactflow_1.Position.Right,
targetPosition: reactflow_1.Position.Left,
});
setNodes(newNodes);
});
fetchInitialChildren();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Node focus when clicked
const focusNode = (children, zoom) => {
if (children.length === 0)
return;
let middleChild = children[Math.floor(children.length / 2)];
const middleChildWithLatestPosition = nodes.filter((a) => a.id == middleChild.id)[0];
if (middleChildWithLatestPosition) {
middleChild = middleChildWithLatestPosition;
}
setCenter(middleChild.position.x, middleChild.position.y, { zoom, duration: 1000 });
};
// On Node Click
const nodeClick = (_event, node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const findChildren = nodes.filter((item) => { var _a; return ((_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.parent) === node.id; });
if (!findChildren.length) {
const itemChildren = node.data.children;
const newEdges = [
...edges,
...itemChildren.map((item) => {
var _a;
return {
id: String(Math.floor(Math.random() * 1000000)),
source: (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.parent,
target: item === null || item === void 0 ? void 0 : item.id,
markerEnd: {
type: reactflow_1.MarkerType.ArrowClosed,
},
};
}),
];
//TODO: Fix nodes type error
const newNodes = nodes.concat(itemChildren);
const { nodes: layoutedNodes, edges: layoutedEdges } = (0, dagreUtils_1.getLayoutedElements)(newNodes, newEdges, 'LR');
setNodes([...layoutedNodes]);
setEdges([...layoutedEdges]);
if (itemChildren.length > 0) {
focusNode(itemChildren, 0.9);
}
}
else {
const newNodes = (0, reusables_1.removeElementsByParent)(nodes, node.id);
const newEdges = (0, reusables_1.removeEdgesByParent)(edges, node.id);
const { nodes: layoutedNodes, edges: layoutedEdges } = (0, dagreUtils_1.getLayoutedElements)(newNodes, newEdges, 'LR');
setNodes([...layoutedNodes]);
setEdges([...layoutedEdges]);
focusNode([node], 0.9);
}
});
//On Node Hover
function handleMouseEnter(_e, node) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!nNodes[node.id]) {
const itemChildren = [];
const nodeChildren = node.data.children;
yield Promise.all(nodeChildren.map((item) => tslib_1.__awaiter(this, void 0, void 0, function* () {
let children = [];
const label = item.data.label;
const extractProps = (0, reusables_1.propMerge)(item.data, label);
if (Object.keys(extractProps).length > 0) {
const res = yield extractChildren(extractProps, item);
children = res;
}
const relations = Object.assign(Object.assign({}, node.data.relations), item.data.relations);
itemChildren.push({
id: item.id,
type: (children === null || children === void 0 ? void 0 : children.length) > 0 ? 'default' : 'output',
data: {
label: item.data.label,
children: children,
parent: item.data.parent,
examples: item.data.examples,
description: item.data.description,
relations: relations,
},
position: position,
sourcePosition: reactflow_1.Position.Right,
targetPosition: reactflow_1.Position.Left,
});
})));
node.data.children = itemChildren;
nNodes[node.id] = node;
setnNodes(nNodes);
}
setCurrentNode(node);
});
}
const edgeTypes = {
smart: react_flow_smart_edge_1.SmartBezierEdge,
};
return (react_1.default.createElement(reactflow_1.ReactFlow, { nodes: nodes, edges: edges, edgeTypes: edgeTypes, onNodesChange: onNodesChange, connectionLineType: reactflow_1.ConnectionLineType.SmoothStep, onEdgesChange: onEdgesChange, onConnect: onConnect, onNodeMouseEnter: handleMouseEnter, onNodeClick: nodeClick, fitView: true, defaultViewport: { x: 1, y: 1, zoom: 0.9 } },
react_1.default.createElement(reactflow_1.MiniMap, null),
react_1.default.createElement(reactflow_1.Controls, null),
react_1.default.createElement(reactflow_1.Background, null)));
}
exports.default = ({ setCurrentNode, setnNodes, nNodes, initialNode, schema }) => (react_1.default.createElement(reactflow_1.ReactFlowProvider, null,
react_1.default.createElement(Flow, { setnNodes: setnNodes, nNodes: nNodes, setCurrentNode: setCurrentNode, initialNode: initialNode, schema: schema })));
//# sourceMappingURL=Nodes.js.map