209 | {
210 | permission &&
211 | <>
212 |
215 |
218 | >
219 | }
220 |
256 |
275 | setIsOpen(false)}
279 | actions={[{label:'Delete', effect:deleteNode}]}
280 | />
281 | {
283 | if (n.type === 'input') return '#0041d0';
284 | if (n.type === 'selectorNode') return bgColor;
285 | if (n.type === 'output') return '#ff0072';
286 | }}
287 | nodeColor={(n) => {
288 | if (n.type === 'selectorNode') return bgColor;
289 | return '#fff';
290 | }}
291 | />
292 |
293 |
294 |
295 | )
296 | }
297 |
298 | export default Reactflow
299 |
--------------------------------------------------------------------------------
/src/components/Reactflow/Sidebar.js:
--------------------------------------------------------------------------------
1 | import React, { DragEvent } from 'react';
2 |
3 | const onDragStart = (event, nodeType) => {
4 | event.stopPropagation();
5 | event.dataTransfer.setData('application/reactflow', nodeType);
6 | event.dataTransfer.effectAllowed = 'move';
7 | };
8 |
9 | const Sidebar = () => {
10 | return (
11 |
23 | );
24 | };
25 |
26 | export default Sidebar;
--------------------------------------------------------------------------------
/src/components/Reactflow/contextMenu.js:
--------------------------------------------------------------------------------
1 | import { FC, memo } from 'react';
2 |
3 | // type Action = {
4 | // label: string;
5 | // effect: (...args: any[]) => any;
6 | // };
7 |
8 | // type Position = {
9 | // x: number;
10 | // y: number;
11 | // };
12 |
13 | // type Props = {
14 | // actions: Action[];
15 | // isOpen: boolean;
16 | // position: Position;
17 | // onMouseLeave: () => void;
18 | // };
19 |
20 | export const ContextMenu = memo(
21 | ({ isOpen, position, actions = [], onMouseLeave }) =>
22 | isOpen ? (
23 |
195 | {showXarrow ? (
196 | <>
197 |
310 |
311 | {labels.start ? (
312 |
320 | {labels.start}
321 |
322 | ) : null}
323 | {labels.middle ? (
324 |
333 | {labels.middle}
334 |
335 | ) : null}
336 | {labels.end ? (
337 |
0 ? 'translate(-100% , -50%)' : 'translate(-0% , -50%)',
340 | width: 'max-content',
341 | position: 'absolute',
342 | left: st.cx0 + st.labelEndPos.x,
343 | top: st.cy0 + st.labelEndPos.y + strokeWidth + 5,
344 | }}>
345 | {labels.end}
346 |
347 | ) : null}
348 | {_debug ? (
349 | <>
350 | {/* possible anchor connections */}
351 | {[...st.startPoints, ...st.endPoints].map((p, i) => {
352 | return (
353 |
367 | );
368 | })}
369 | >
370 | ) : null}
371 | >
372 | ) : null}
373 |
374 | );
375 | };
376 |
377 | //////////////////////////////
378 | // propTypes
379 |
380 | Xarrow.propTypes = XarrowPropTypes;
381 |
382 | export default Xarrow;
383 |
--------------------------------------------------------------------------------
/src/components/Xarrow/Line/anchors.js:
--------------------------------------------------------------------------------
1 |
2 | const getAnchorsDefaultOffsets = (width, height) => {
3 | return {
4 | middle: { x: width * 0.5, y: height * 0.5 },
5 | left: { x: 0, y: height * 0.5 },
6 | right: { x: width, y: height * 0.5 },
7 | top: { x: width * 0.5, y: 0 },
8 | bottom: { x: width * 0.5, y: height },
9 | };
10 | };
11 |
12 | export const calcAnchors = (anchors, anchorPos) => {
13 | // now prepare this list of anchors to object expected by the `getShortestLine` function
14 | return anchors.map((anchor) => {
15 | let defsOffsets = getAnchorsDefaultOffsets(anchorPos.right - anchorPos.x, anchorPos.bottom - anchorPos.y);
16 | let { x, y } = defsOffsets[anchor.position];
17 | return {
18 | x: anchorPos.x + x + anchor.offset.x,
19 | y: anchorPos.y + y + anchor.offset.y,
20 | anchor: anchor,
21 | };
22 | });
23 | };
24 |
25 | if (require.main === module) {
26 | // const res = parseAnchor(['auto'], {
27 | // x: 0,
28 | // y: 0,
29 | // bottom: 10,
30 | // right: 20,
31 | // });
32 | // console.log(res);
33 | }
34 |
--------------------------------------------------------------------------------
/src/components/Xarrow/Line/propTypes.js:
--------------------------------------------------------------------------------
1 | import PT from 'prop-types';
2 | import { arrowShapes, cAnchorEdge, cPaths, cSvgElems } from '../constants';
3 |
4 | const pAnchorPositionType = PT.oneOf(cAnchorEdge);
5 |
6 | const pAnchorCustomPositionType = PT.exact({
7 | position: pAnchorPositionType.isRequired,
8 | offset: PT.exact({
9 | x: PT.number,
10 | y: PT.number,
11 | }).isRequired,
12 | });
13 |
14 | const _pAnchorType = PT.oneOfType([pAnchorPositionType, pAnchorCustomPositionType]);
15 |
16 | const pAnchorType = PT.oneOfType([_pAnchorType, PT.arrayOf(_pAnchorType)]);
17 |
18 | const pRefType = PT.oneOfType([PT.string, PT.exact({ current: PT.any })]);
19 |
20 | const _pLabelType = PT.oneOfType([PT.element, PT.string]);
21 |
22 | const pLabelsType = PT.exact({
23 | start: _pLabelType,
24 | middle: _pLabelType,
25 | end: _pLabelType,
26 | });
27 |
28 | const pSvgEdgeShapeType = PT.oneOf(Object.keys(arrowShapes));
29 | // const pSvgElemType = PT.oneOf(cSvgElems);
30 | const pSvgElemType = PT.any;
31 | const pSvgEdgeType = PT.oneOfType([
32 | pSvgEdgeShapeType,
33 | PT.exact({
34 | svgElem: pSvgElemType,
35 | offsetForward: PT.number,
36 | }).isRequired,
37 | ]);
38 |
39 | const XarrowPropTypes = {
40 | start: pRefType.isRequired,
41 | end: pRefType.isRequired,
42 | startAnchor: pAnchorType,
43 | endAnchor: pAnchorType,
44 | labels: PT.oneOfType([_pLabelType, pLabelsType]),
45 | color: PT.string,
46 | lineColor: PT.string,
47 | showHead: PT.bool,
48 | headColor: PT.string,
49 | headSize: PT.number,
50 | tailSize: PT.number,
51 | tailColor: PT.string,
52 | strokeWidth: PT.number,
53 | showTail: PT.bool,
54 | path: PT.oneOf(cPaths),
55 | showXarrow: PT.bool,
56 | curveness: PT.number,
57 | gridBreak: PT.string,
58 | dashness: PT.oneOfType([PT.bool, PT.object]),
59 | headShape: pSvgEdgeType,
60 | tailShape: pSvgEdgeType,
61 | animateDrawing: PT.oneOfType([PT.bool, PT.number]),
62 | zIndex: PT.number,
63 | passProps: PT.object,
64 | arrowBodyProps: PT.object,
65 | arrowHeadProps: PT.object,
66 | arrowTailProps: PT.object,
67 | SVGcanvasProps: PT.object,
68 | divContainerProps: PT.object,
69 | _extendSVGcanvas: PT.number,
70 | _debug: PT.bool,
71 | _cpx1Offset: PT.number,
72 | _cpy1Offset: PT.number,
73 | _cpx2Offset: PT.number,
74 | _cpy2Offset: PT.number,
75 | };
76 |
77 | export default XarrowPropTypes;
78 |
--------------------------------------------------------------------------------
/src/components/Xarrow/Line/useXarrowProps.js:
--------------------------------------------------------------------------------
1 | import React, { useLayoutEffect, useRef, useState } from 'react';
2 | import { getElementByPropGiven, getElemPos, xStr2absRelative } from './utils';
3 | import _ from 'lodash';
4 | import { arrowShapes, cAnchorEdge, cArrowShapes } from '../constants';
5 |
6 | const parseLabels = (label) => {
7 | let parsedLabel = { start: null, middle: null, end: null };
8 | if (label) {
9 | if (typeof label === 'string' || React.isValidElement(label)) parsedLabel.middle = label;
10 | else {
11 | for (let key in label) {
12 | parsedLabel[key] = label[key];
13 | }
14 | }
15 | }
16 | return parsedLabel;
17 | };
18 |
19 | // remove 'auto' as possible anchor from anchorCustomPositionType.position
20 | // interface anchorCustomPositionType2 extends Omit