react-xarrows
Advanced tools
Comparing version 1.5.0 to 1.5.1
## 1.5.0 | ||
- properties that are completely removed and no longer supported: `consoleWarning`, `monitorDOMchanges` and `registerEvents`. | ||
issues related to jest and other issues has fixed. | ||
now update position is occur during the component render and not as sideEffect(useEffect). | ||
dependencies changed: prop-types added in lodash replaced with lodash.isequal and lodash.pick. | ||
#### docs | ||
- issues related to jest and other issues has fixed. | ||
- dependencies changed: prop-types added in lodash replaced with lodash.isequal and lodash.pick. | ||
- v1.5.1 - minor code and docs updates. | ||
improved documentation: | ||
@@ -22,29 +22,19 @@ - added CHANGELOG.md file. | ||
added support for javascript projects that imported the lib locally. many changes to the repo folders structure. | ||
#### 1.2.1 | ||
minor bug fix (intellij suggestinons did not apear) | ||
#### 1.2.2 | ||
bug fixes(1#changing anchors refs without remounting broke the arrow. 2#other minors) | ||
## 1.1.6 | ||
errors and warnings improved. smart adjustments for diffrent positioning style(of anchors elemntes and common ancestor element) . minor bug fixes | ||
## 1.2.0 bug fixes and code structure changed | ||
The lib not worked properly on js projects(only worked well on ts). now working well on both. | ||
- v1.2.1 - minor bug fix (intellij suggestinons did not apear) | ||
- v1.2.2 - bug fixes(1#changing anchors refs without remounting broke the arrow. 2#other minors) | ||
## 1.1.5 | ||
optimazed calculations and label positioning. (Buzier curve extrema point are calculated now using derivatives and not by interpolation) other improvements as well. | ||
## 1.1.4 | ||
bug fixes, calculation optimizations, and smart svg canvas size adjusment. | ||
## 1.1.3 | ||
an entirely new algorithm to calculate arrow path and curveness. now the arrow acting "smarter". this include bug fixes,improvements and some adjustments. | ||
monitorDOMchanges prop default changed to true. | ||
## 1.1.2 | ||
bug fix. (the first arrow fixed the headarrow style for all next comming arrows) | ||
## 1.1.1 | ||
bug fix now labels not exceed the svg canvas. the headArrow is calcualted now . this means the line ends at the start at the arrow - and this is more natural looking(especially at large headarrows). | ||
## 1.1.0 bug fixes and features update | ||
props added:`label`, `dashness` and `advanced`. | ||
`arrowStyle` removed and all his contained properties flattened to be props of xarrow directly. `strokeColor` renamed to `lineColor`. | ||
- v1.1.1 - bug fix now labels not exceed the svg canvas. the headArrow is calcualted now . this means the line ends at the start at the arrow - and this is more natural looking(especially at large headarrows). | ||
- v1.1.2 - bug fix. (the first arrow fixed the headarrow style for all next comming arrows) | ||
- v1.1.3 - an entirely new algorithm to calculate arrow path and curveness. now the arrow acting "smarter". this include bug fixes,improvements and some adjustments. | ||
monitorDOMchanges prop default changed to true. | ||
- v1.1.4 - bug fixes, calculation optimizations, and smart svg canvas size adjusment. | ||
- v1.1.5 - optimazed calculations and label positioning. (Buzier curve extrema point are calculated now using derivatives and not by interpolation) other improvements as well. | ||
- v1.1.6 - errors and warnings improved. smart adjustments for diffrent positioning style(of anchors elemntes and common ancestor element) . minor bug fixes | ||
@@ -51,0 +41,0 @@ ## 1.0.0 |
@@ -20,14 +20,8 @@ import React from "react"; | ||
}; | ||
consoleWarning?: boolean; | ||
passProps?: React.SVGProps<SVGPathElement>; | ||
advanced?: { | ||
extendSVGcanvas?: number; | ||
passProps?: { | ||
SVGcanvas?: React.SVGAttributes<SVGSVGElement>; | ||
arrowBody?: React.SVGProps<SVGPathElement>; | ||
arrowHead?: React.SVGProps<SVGPathElement>; | ||
}; | ||
}; | ||
monitorDOMchanges?: boolean; | ||
registerEvents?: registerEventsType[]; | ||
extendSVGcanvas?: number; | ||
SVGcanvasProps?: React.SVGAttributes<SVGSVGElement>; | ||
arrowBodyProps?: React.SVGProps<SVGPathElement>; | ||
arrowHeadProps?: React.SVGProps<SVGPathElement>; | ||
divContainerProps?: React.HTMLProps<HTMLDivElement>; | ||
}; | ||
@@ -34,0 +28,0 @@ export declare type anchorType = anchorPositionType | anchorCustomPositionType; |
250
lib/index.js
"use strict"; | ||
//// @ts-nocheck | ||
// @ts-nocheck | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
@@ -22,2 +22,13 @@ if (k2 === undefined) k2 = k; | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -32,4 +43,6 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
const prop_types_1 = __importDefault(require("prop-types")); | ||
const buzzier_1 = require("./utils/buzzier"); | ||
const anchors_1 = require("./utils/anchors"); | ||
const Xarrow = (props) => { | ||
let { startAnchor, endAnchor, label, color, lineColor, headColor, strokeWidth, headSize, path, curveness, dashness, passProps, advanced, } = props; | ||
let { startAnchor, endAnchor, label, color, lineColor, headColor, strokeWidth, headSize, path, curveness, dashness, passProps, SVGcanvasProps, arrowBodyProps, arrowHeadProps, divContainerProps, extendSVGcanvas } = props, extraProps = __rest(props, ["startAnchor", "endAnchor", "label", "color", "lineColor", "headColor", "strokeWidth", "headSize", "path", "curveness", "dashness", "passProps", "SVGcanvasProps", "arrowBodyProps", "arrowHeadProps", "divContainerProps", "extendSVGcanvas"]); | ||
const selfRef = react_1.useRef(null); | ||
@@ -39,2 +52,7 @@ const [anchorsRefs, setAnchorsRefs] = react_1.useState({ start: null, end: null }); | ||
const [prevProps, setPrevProps] = react_1.useState(null); | ||
/** | ||
* determine a an update is needed and update if so. | ||
* update is needed if one of the connected elements position was changed since last render, or if the ref to one | ||
* of the elements has changed(it points to a different element). | ||
*/ | ||
const updateIfNeeded = () => { | ||
@@ -75,3 +93,2 @@ // check if anchors refs changed | ||
const initProps = () => { | ||
// testUserGivenProperties(); | ||
setPrevProps(props); | ||
@@ -153,4 +170,2 @@ }; | ||
} | ||
let { passProps: adPassProps = { SVGcanvas: {}, arrowHead: {}, arrowBody: {} }, extendSVGcanvas: extendSVGcanvas = 0, } = advanced; | ||
let { SVGcanvas = {}, arrowBody = {}, arrowHead = {} } = adPassProps; | ||
const getSelfPos = () => { | ||
@@ -167,115 +182,32 @@ let { left: xarrowElemX, top: xarrowElemY, } = selfRef.current.getBoundingClientRect(); | ||
const getAnchorsPos = () => { | ||
if (!anchorsRefs.start) | ||
return; | ||
let s = anchorsRefs.start.getBoundingClientRect(); | ||
let e = anchorsRefs.end.getBoundingClientRect(); | ||
let yOffset = 0; | ||
let xOffset = 0; | ||
return { | ||
start: { | ||
x: s.x + xOffset, | ||
y: s.y + yOffset, | ||
right: s.right + xOffset, | ||
bottom: s.bottom + yOffset, | ||
x: s.left, | ||
y: s.top, | ||
right: s.right, | ||
bottom: s.bottom, | ||
}, | ||
end: { | ||
x: e.x + xOffset, | ||
y: e.y + yOffset, | ||
right: e.right + xOffset, | ||
bottom: e.bottom + yOffset, | ||
x: e.left, | ||
y: e.top, | ||
right: e.right, | ||
bottom: e.bottom, | ||
}, | ||
}; | ||
}; | ||
/** | ||
* The Main logic of path calculation for the arrow. | ||
* calculate new path and adjust canvas based on given properties. | ||
* */ | ||
const updatePosition = (positions) => { | ||
// calculate new position and path and set state based on given properties | ||
let { start: sPos } = positions; | ||
let { end: ePos } = positions; | ||
let headOrient = 0; | ||
////////////////////////////////////////////////////////////////////// | ||
// declare relevant functions for later use for start and end refs(instead doing all twice) | ||
const getAnchorsDefaultOffsets = (width, height) => { | ||
return { | ||
middle: { rightness: width * 0.5, bottomness: height * 0.5 }, | ||
left: { rightness: 0, bottomness: height * 0.5 }, | ||
right: { rightness: width, bottomness: height * 0.5 }, | ||
top: { rightness: width * 0.5, bottomness: 0 }, | ||
bottom: { rightness: width * 0.5, bottomness: height }, | ||
}; | ||
}; | ||
const prepareAnchorLines = (anchor, anchorPos) => { | ||
let defsOffsets = getAnchorsDefaultOffsets(anchorPos.right - anchorPos.x, anchorPos.bottom - anchorPos.y); | ||
// convert given anchors to array if array not already given | ||
let anchorChoice = Array.isArray(anchor) ? anchor : [anchor]; | ||
if (anchorChoice.length == 0) | ||
anchorChoice = ["auto"]; | ||
//now map each item in the list to relevant object | ||
let anchorChoiceMapped = anchorChoice.map((anchorChoice) => { | ||
if (utils_1.typeOf(anchorChoice) === "string") { | ||
anchorChoice = anchorChoice; | ||
return { | ||
position: anchorChoice, | ||
offset: { rightness: 0, bottomness: 0 }, | ||
}; | ||
} | ||
else if (utils_1.typeOf(anchorChoice) === "object") { | ||
if (!anchorChoice.offset) | ||
anchorChoice.offset = { rightness: 0, bottomness: 0 }; | ||
if (!anchorChoice.offset.bottomness) | ||
anchorChoice.offset.bottomness = 0; | ||
if (!anchorChoice.offset.rightness) | ||
anchorChoice.offset.rightness = 0; | ||
anchorChoice = anchorChoice; | ||
return anchorChoice; | ||
} | ||
}); | ||
//now build the object that represents the users possibilities for different anchors | ||
let anchorPossibilities = []; | ||
if (anchorChoiceMapped.map((a) => a.position).includes("auto")) { | ||
let autoAnchor = anchorChoiceMapped.find((a) => a.position === "auto"); | ||
["left", "right", "top", "bottom"].forEach((anchor) => { | ||
let offset = defsOffsets[anchor]; | ||
offset.rightness += autoAnchor.offset.rightness; | ||
offset.bottomness += autoAnchor.offset.bottomness; | ||
anchorPossibilities.push({ position: anchor, offset }); | ||
}); | ||
} | ||
else { | ||
anchorChoiceMapped.forEach((customAnchor) => { | ||
let offset = defsOffsets[customAnchor.position]; | ||
offset.rightness += customAnchor.offset.rightness; | ||
offset.bottomness += customAnchor.offset.bottomness; | ||
anchorPossibilities.push({ position: customAnchor.position, offset }); | ||
}); | ||
} | ||
// now prepare this list of anchors to object expected by the `getShortestLine` function | ||
return anchorPossibilities.map((pos) => ({ | ||
x: anchorPos.x + pos.offset.rightness, | ||
y: anchorPos.y + pos.offset.bottomness, | ||
anchorPosition: pos.position, | ||
})); | ||
}; | ||
//end declare functions | ||
///////////////////////////////////////////////////////////////////////////////////////// | ||
let startPointsObj = prepareAnchorLines(startAnchor, sPos); | ||
let endPointsObj = prepareAnchorLines(endAnchor, ePos); | ||
const dist = (p1, p2) => { | ||
//length of line | ||
return Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2)); | ||
}; | ||
const getShortestLine = (sPoints, ePoints) => { | ||
// closes tPair Of Points which feet to the specified anchors | ||
let minDist = Infinity, d = Infinity; | ||
let closestPair; | ||
sPoints.forEach((sp) => { | ||
ePoints.forEach((ep) => { | ||
d = dist(sp, ep); | ||
if (d < minDist) { | ||
minDist = d; | ||
closestPair = { startPointObj: sp, endPointObj: ep }; | ||
} | ||
}); | ||
}); | ||
return closestPair; | ||
}; | ||
let { startPointObj, endPointObj } = getShortestLine(startPointsObj, endPointsObj); | ||
// convert startAnchor and endAnchor to list of objects represents allowed anchors. | ||
let startPointsObj = anchors_1.prepareAnchorLines(startAnchor, sPos); | ||
let endPointsObj = anchors_1.prepareAnchorLines(endAnchor, ePos); | ||
// choose the smallest path for 2 points from these possibilities. | ||
let { startPointObj, endPointObj } = anchors_1.getShortestLine(startPointsObj, endPointsObj); | ||
let startAnchorPosition = startPointObj.anchorPosition, endAnchorPosition = endPointObj.anchorPosition; | ||
@@ -318,5 +250,8 @@ let startPoint = lodash_pick_1.default(startPointObj, ["x", "y"]), endPoint = lodash_pick_1.default(endPointObj, ["x", "y"]); | ||
if (cu === 0) { | ||
// in case of straight path | ||
let headAngel = Math.atan(absDy / absDx); | ||
x2 -= headOffset * xSign * Math.cos(headAngel); | ||
y2 -= headOffset * ySign * Math.sin(headAngel); | ||
// cpx2 -= headOffset * xSign * Math.cos(headAngel); | ||
// cpy2 -= headOffset * ySign * Math.sin(headAngel); | ||
headAngel *= ySign; | ||
@@ -334,3 +269,5 @@ if (xSign < 0) | ||
else { | ||
// in case of smooth path | ||
if (endAnchorPosition === "middle") { | ||
// in case a middle anchor is chosen for endAnchor choose from which side to attach to the middle of the element | ||
if (absDx > absDy) { | ||
@@ -345,2 +282,4 @@ endAnchorPosition = xSign ? "left" : "right"; | ||
x2 -= headOffset * xSign; | ||
// cpx2 -= headOffset * xSign * 2; | ||
// cpx1 += headOffset * xSign; | ||
xHeadOffset = (headOffset * xSign) / 3; | ||
@@ -363,2 +302,4 @@ yHeadOffset = (headSize * strokeWidth * xSign) / 2; | ||
y2 -= headOffset * ySign; | ||
// cpy1 += headOffset * ySign; | ||
// cpy2 -= headOffset * ySign; | ||
if (endAnchorPosition === "top") { | ||
@@ -376,2 +317,3 @@ headOrient = 270; | ||
} | ||
// if (endAnchorPosition == startAnchorPosition) headOrient += 180; | ||
let arrowHeadOffset = { x: xHeadOffset, y: yHeadOffset }; | ||
@@ -386,2 +328,6 @@ let cpx1 = x1, cpy1 = y1, cpx2 = x2, cpy2 = y2; | ||
cpx2 -= absDx * cu * xSign; | ||
// if (absDx < 2 * headOffset) { | ||
// cpx1 += headOffset * xSign - absDx / 2; | ||
// cpx2 -= headOffset * xSign * 2 - absDx; | ||
// } | ||
// cpx1 += headOffset * 2 * xSign; | ||
@@ -428,2 +374,3 @@ // cpx2 -= headOffset * 2 * xSign; | ||
} | ||
// smart select best curve for the current anchors | ||
let selectedCurviness = ""; | ||
@@ -448,49 +395,5 @@ if (["left", "right"].includes(startAnchorPosition)) | ||
//////////////////////////////////// | ||
// Buzier curve calculations | ||
// bzCurve function: bz = (1−t)^3*p1 + 3(1−t)^2*t*p2 +3(1−t)*t^2*p3 + t^3*p4 | ||
// dt(bz) = -3 p1 (1 - t)^2 + 3 p2 (1 - t)^2 - 6 p2 (1 - t) t + 6 p3 (1 - t) t - 3 p3 t^2 + 3 p4 t^2 | ||
// when p1=(x1,y1),p2=(cpx1,cpy1),p3=(cpx2,cpy2),p4=(x2,y2) | ||
// then extrema points is when dt(bz) = 0 | ||
// solutions => t = ((-6 p1 + 12 p2 - 6 p3) ± sqrt((6 p1 - 12 p2 + 6 p3)^2 - 4 (3 p2 - 3 p1) (-3 p1 + 9 p2 - 9 p3 + 3 p4)))/(2 (-3 p1 + 9 p2 - 9 p3 + 3 p4)) when (p1 + 3 p3!=3 p2 + p4) | ||
// xSol1,2 = ((-6 x1 + 12 cpx1 - 6 cpx2) ± sqrt((6 x1 - 12 cpx1 + 6 cxp2)^2 - 4 (3 cpx1 - 3 x1) (-3 x1 + 9 cpx1 - 9 cpx2 + 3 x2)))/(2 (-3 x1 + 9 cpx1 - 9 cpx2 + 3 x2)) | ||
// ySol1,2 = ((-6 y1 + 12 cpy1 - 6 cpy2) ± sqrt((6 y1 - 12 cpy1 + 6 cyp2)^2 - 4 (3 cpy1 - 3 y1) (-3 y1 + 9 cpy1 - 9 cpy2 + 3 y2)))/(2 (-3 y1 + 9 cpy1 - 9 cpy2 + 3 y2)) | ||
// now in javascript: | ||
let txSol1 = (-6 * x1 + | ||
12 * cpx1 - | ||
6 * cpx2 + | ||
Math.sqrt(Math.pow((6 * x1 - 12 * cpx1 + 6 * cpx2), 2) - | ||
4 * (3 * cpx1 - 3 * x1) * (-3 * x1 + 9 * cpx1 - 9 * cpx2 + 3 * x2))) / | ||
(2 * (-3 * x1 + 9 * cpx1 - 9 * cpx2 + 3 * x2)); | ||
let txSol2 = (-6 * x1 + | ||
12 * cpx1 - | ||
6 * cpx2 - | ||
Math.sqrt(Math.pow((6 * x1 - 12 * cpx1 + 6 * cpx2), 2) - | ||
4 * (3 * cpx1 - 3 * x1) * (-3 * x1 + 9 * cpx1 - 9 * cpx2 + 3 * x2))) / | ||
(2 * (-3 * x1 + 9 * cpx1 - 9 * cpx2 + 3 * x2)); | ||
let tySol1 = (-6 * y1 + | ||
12 * cpy1 - | ||
6 * cpy2 + | ||
Math.sqrt(Math.pow((6 * y1 - 12 * cpy1 + 6 * cpy2), 2) - | ||
4 * (3 * cpy1 - 3 * y1) * (-3 * y1 + 9 * cpy1 - 9 * cpy2 + 3 * y2))) / | ||
(2 * (-3 * y1 + 9 * cpy1 - 9 * cpy2 + 3 * y2)); | ||
let tySol2 = (-6 * y1 + | ||
12 * cpy1 - | ||
6 * cpy2 - | ||
Math.sqrt(Math.pow((6 * y1 - 12 * cpy1 + 6 * cpy2), 2) - | ||
4 * (3 * cpy1 - 3 * y1) * (-3 * y1 + 9 * cpy1 - 9 * cpy2 + 3 * y2))) / | ||
(2 * (-3 * y1 + 9 * cpy1 - 9 * cpy2 + 3 * y2)); | ||
const bzx = (t) => Math.pow((1 - t), 3) * x1 + | ||
3 * Math.pow((1 - t), 2) * t * cpx1 + | ||
3 * (1 - t) * Math.pow(t, 2) * cpx2 + | ||
Math.pow(t, 3) * x2; | ||
const bzy = (t) => Math.pow((1 - t), 3) * y1 + | ||
3 * Math.pow((1 - t), 2) * t * cpy1 + | ||
3 * (1 - t) * Math.pow(t, 2) * cpy2 + | ||
Math.pow(t, 3) * y2; | ||
//////////////////////////////////// | ||
// canvas smart size adjustments | ||
let xSol1 = bzx(txSol1); | ||
let xSol2 = bzx(txSol2); | ||
let ySol1 = bzy(tySol1); | ||
let ySol2 = bzy(tySol2); | ||
const [xSol1, xSol2] = buzzier_1.buzzierMinSols(x1, cpx1, cpx2, x2); | ||
const [ySol1, ySol2] = buzzier_1.buzzierMinSols(y1, cpy1, cpy2, y2); | ||
if (xSol1 < 0) | ||
@@ -512,10 +415,12 @@ excLeft += -xSol1; | ||
cpy2 += excUp; | ||
let cw = absDx + excLeft + excRight, ch = absDy + excUp + excDown; | ||
const cw = absDx + excLeft + excRight, ch = absDy + excUp + excDown; | ||
cx0 -= excLeft; | ||
cy0 -= excUp; | ||
//labels | ||
let labelStartPos = { x: bzx(0.01), y: bzy(0.01) }; | ||
let labelMiddlePos = { x: bzx(0.5), y: bzy(0.5) }; | ||
let labelEndPos = { x: bzx(0.99), y: bzy(0.99) }; | ||
let arrowEnd = { x: bzx(1), y: bzy(1) }; | ||
const bzx = buzzier_1.bzFunction(x1, cpx1, cpx2, x2); | ||
const bzy = buzzier_1.bzFunction(y1, cpy1, cpy2, y2); | ||
const labelStartPos = { x: bzx(0.01), y: bzy(0.01) }; | ||
const labelMiddlePos = { x: bzx(0.5), y: bzy(0.5) }; | ||
const labelEndPos = { x: bzx(0.99), y: bzy(0.99) }; | ||
const arrowEnd = { x: bzx(1), y: bzy(1) }; | ||
setSt({ | ||
@@ -551,6 +456,6 @@ cx0, | ||
}; | ||
let fHeadSize = headSize * strokeWidth; //factored headsize | ||
let xOffsetHead = st.x2 - st.arrowHeadOffset.x; | ||
let yOffsetHead = st.y2 - st.arrowHeadOffset.y; | ||
let arrowPath = `M ${st.x1} ${st.y1} C ${st.cpx1} ${st.cpy1}, ${st.cpx2} ${st.cpy2}, ${st.x2} ${st.y2}`; | ||
const fHeadSize = headSize * strokeWidth; //factored headsize | ||
const xOffsetHead = st.x2 - st.arrowHeadOffset.x; | ||
const yOffsetHead = st.y2 - st.arrowHeadOffset.y; | ||
let arrowPath = `M ${st.x1} ${st.y1} C ${st.cpx1} ${st.cpy1}, ${st.cpx2} ${st.cpy2}, ${st.x2} ${st.y2} `; | ||
if (path === "straight") | ||
@@ -560,3 +465,3 @@ arrowPath = `M ${st.x1} ${st.y1} ${st.x2} ${st.y2}`; | ||
arrowPath = `M ${st.x1} ${st.y1} L ${st.cpx1} ${st.cpy1} L ${st.cpx2} ${st.cpy2} L ${st.x2} ${st.y2}`; | ||
return (react_1.default.createElement("div", { style: { position: "absolute" } }, | ||
return (react_1.default.createElement("div", Object.assign({ style: { position: "absolute" } }, divContainerProps, extraProps), | ||
react_1.default.createElement("svg", Object.assign({ ref: selfRef, width: st.cw, height: st.ch, style: { | ||
@@ -568,9 +473,12 @@ // border: "2px yellow dashed", | ||
pointerEvents: "none", | ||
}, overflow: "auto" }, SVGcanvas), | ||
}, overflow: "auto" }, SVGcanvasProps), | ||
react_1.default.createElement("circle", { r: "5", cx: st.cpx1, cy: st.cpy1, fill: "green" }), | ||
react_1.default.createElement("circle", { r: "5", cx: st.cpx2, cy: st.cpy2, fill: "blue" }), | ||
react_1.default.createElement("rect", { x: st.excLeft, y: st.excUp, width: st.absDx, height: st.absDy, fill: "none", stroke: "pink", strokeWidth: "2px" }), | ||
react_1.default.createElement("path", Object.assign({ d: arrowPath, stroke: lineColor, strokeDasharray: `${dashStroke} ${dashNone}`, strokeWidth: strokeWidth, fill: "transparent", | ||
// markerEnd={`url(#${arrowHeadId})`} | ||
pointerEvents: "visibleStroke" }, passProps, arrowBody), animationSpeed ? (react_1.default.createElement("animate", { attributeName: "stroke-dashoffset", values: `${dashoffset * animationDirection};0`, dur: `${1 / animationSpeed}s`, repeatCount: "indefinite" })) : null), | ||
pointerEvents: "visibleStroke" }, passProps, arrowBodyProps), animationSpeed ? (react_1.default.createElement("animate", { attributeName: "stroke-dashoffset", values: `${dashoffset * animationDirection};0`, dur: `${1 / animationSpeed}s`, repeatCount: "indefinite" })) : null), | ||
react_1.default.createElement("path", Object.assign({ d: `M 0 0 L ${fHeadSize} ${fHeadSize / 2} L 0 ${fHeadSize} L ${fHeadSize / 4} ${fHeadSize / 2} z`, fill: headColor, | ||
// pointerEvents="all" | ||
transform: `translate(${xOffsetHead},${yOffsetHead}) rotate(${st.headOrient})` }, passProps, arrowHead))), | ||
transform: `translate(${xOffsetHead},${yOffsetHead}) rotate(${st.headOrient})` }, passProps, arrowHeadProps))), | ||
labelStart ? (react_1.default.createElement("div", { style: { | ||
@@ -635,2 +543,7 @@ transform: st.dx < 0 ? "translate(-100% , -50%)" : "translate(-0% , -50%)", | ||
passProps: prop_types_1.default.object, | ||
arrowBodyProps: prop_types_1.default.object, | ||
arrowHeadProps: prop_types_1.default.object, | ||
SVGcanvasProps: prop_types_1.default.object, | ||
divContainerProps: prop_types_1.default.object, | ||
extendSVGcanvas: prop_types_1.default.number, | ||
}; | ||
@@ -650,8 +563,9 @@ Xarrow.defaultProps = { | ||
passProps: {}, | ||
advanced: { | ||
extendSVGcanvas: 0, | ||
passProps: { arrowBody: {}, arrowHead: {}, SVGcanvas: {} }, | ||
}, | ||
arrowBodyProps: {}, | ||
arrowHeadProps: {}, | ||
SVGcanvasProps: {}, | ||
divContainerProps: {}, | ||
extendSVGcanvas: 0, | ||
}; | ||
exports.default = Xarrow; | ||
//# sourceMappingURL=index.js.map |
@@ -1,6 +0,5 @@ | ||
import { refType } from "./index"; | ||
declare type extendedJtypes = "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "null" | "array"; | ||
export declare const getElementByPropGiven: (ref: refType) => HTMLElement; | ||
export declare const getElementByPropGiven: (ref: any) => HTMLElement; | ||
export declare const typeOf: (arg: any) => extendedJtypes; | ||
export {}; | ||
//# sourceMappingURL=utils.d.ts.map |
{ | ||
"name": "react-xarrows", | ||
"version": "1.5.0", | ||
"version": "1.5.1", | ||
"author": "Eliav Louski", | ||
@@ -43,3 +43,4 @@ "description": "Draw arrows (or lines) between components in React!", | ||
"scripts": { | ||
"build": "tsc -p ." | ||
"build": "tsc -p .", | ||
"start": "yarn --cwd .\\examples\\ start" | ||
}, | ||
@@ -46,0 +47,0 @@ "browserslist": [ |
@@ -7,2 +7,7 @@ # react-xarrows | ||
[![npm version](https://badge.fury.io/js/react-xarrows.svg)](https://github.com/Eliav2/react-xarrows) | ||
[![downloads](https://img.shields.io/npm/dw/react-xarrows)](https://www.npmjs.com/package/react-xarrows) | ||
[![issues](https://img.shields.io/github/issues/Eliav2/react-xarrows)](https://github.com/Eliav2/react-xarrows/issues) | ||
[![licence](https://img.shields.io/npm/l/react-xarrows)](https://github.com/Eliav2/react-xarrows/blob/master/LICENSE) | ||
#### main features | ||
@@ -17,7 +22,7 @@ | ||
found a problem? not a problem! post a new issue([here](https://github.com/Eliav2/react-xarrows/issues)) and i will do my best to fix it. | ||
found a problem? not a problem! post a new issue([here](https://github.com/Eliav2/react-xarrows/issues)). | ||
liked my work? please star [this repo](https://github.com/Eliav2/react-xarrows). | ||
this project developed with the help of using codesandbox. [see and fork easily here](https://codesandbox.io/s/github/Eliav2/react-xarrows). | ||
[see and fork easily on codesandbox](https://codesandbox.io/s/github/Eliav2/react-xarrows). | ||
@@ -79,3 +84,3 @@ ## installation | ||
```jsx | ||
```js | ||
export type xarrowPropsType = { | ||
@@ -96,10 +101,7 @@ start: refType; | ||
passProps?: React.SVGProps<SVGPathElement>; | ||
advanced?: { | ||
extendSVGcanvas?: number; | ||
passProps?: { | ||
SVGcanvas?: React.SVGAttributes<SVGSVGElement>; | ||
arrowBody?: React.SVGProps<SVGPathElement>; | ||
arrowHead?: React.SVGProps<SVGPathElement>; | ||
}; | ||
}; | ||
extendSVGcanvas?: number; | ||
SVGcanvasProps?: React.SVGAttributes<SVGSVGElement>; | ||
arrowBodyProps?: React.SVGProps<SVGPathElement>; | ||
arrowHeadProps?: React.SVGProps<SVGPathElement>; | ||
divContainerProps?: React.HTMLProps<HTMLDivElement>; | ||
}; | ||
@@ -117,15 +119,8 @@ | ||
export type labelType = JSX.Element; | ||
export type domEventType = keyof GlobalEventHandlersEventMap; | ||
export type registerEventsType = { | ||
ref: refType; | ||
eventName: domEventType; | ||
callback?: CallableFunction; | ||
}; | ||
``` | ||
you can keep things simple or provide more detailed props for more custom behavior - the API except both. | ||
for example - you can provide:<br/> `label:"middleLabel"` and the string will appear as middle label.<br/> or customize the labels as you please: `label:{end:<div style={{ fontSize: "1.3em", fontFamily: "fantasy", fontStyle: "italic" }}>big end label</div>}}`. | ||
##### API flexibility | ||
This API has built in such way that most props can accept different types. you can keep things simple or provide more detailed props for more custom behavior - the API except both(see `startAnchor` or `label` properties for good examples).<br/> | ||
see typescript types above for detailed descriptions of what type excepts every prop. | ||
### Properties | ||
## Properties | ||
@@ -146,7 +141,5 @@ #### 'start' and 'end' | ||
- `endAnchor= { position: "auto", offset: { rightness: 20 } }` will choose automatic anchoring for end anchor but will offset it 20 pixels to the right after normal positioning. | ||
- `endAnchor= ["right", {position: "left", offset: {bottomness: -10}}]` only right and left anchors are allowed for endAnchor, and the left side will be offset 10 pixels up | ||
- `endAnchor= ["right", {position: "left", offset: {bottomness: -10}}]` only right and left anchors will be allowed for endAnchor, and if the left side connected then it will be offset 10 pixels up. | ||
#### label | ||
changed api since v1.4.0. now each label can be jsx element or string, but not object. | ||
can be a string that will default to be at the middle or an object that describes where to place label and how to customize it. see `label` at `xarrowPropsType` above. | ||
@@ -204,6 +197,11 @@ examples: | ||
### passing props | ||
The xarrow is fully customizable, and you can pass props to any part of the component. | ||
if unlisted(unknown) property is passed to xarrow so by default it'll be passed down to `divConatiner`. | ||
#### passProps | ||
new and powerful feature! | ||
you can pass properties to visible parts of the arrow (such event handlers and much more). | ||
you can pass properties to visible parts(body and head) of the arrow (such event handlers and much more). | ||
this supposed to be enough for most cases. | ||
examples: | ||
@@ -215,6 +213,23 @@ | ||
#### advanced | ||
### advanced customization | ||
here i will provide some flexibility to the API for some cases that i may not thought of. | ||
The properties below can be used to customize the arrow even farther: | ||
#### arrowBodyProps, arrowHeadProps, SVGcanvasProps, divContainerProps | ||
![image](https://user-images.githubusercontent.com/47307889/95031511-09ed5100-06bf-11eb-95a3-4cdc8d0be0ad.png) | ||
if you wish you can pass props specific part of the component. | ||
- `divContainerProps` - the container which contains the SVG canvas, and the optional labels elements. It takes no place, and located where you normaly placed him in the elements tree(no offset). The SVGcanvas and the labels will be placed in a offset from this div. | ||
- `SVGcanvasProps` - the svg canvas which contains arrow head and body. | ||
- `arrowBodyProps` - the body of the arrow | ||
- `arrowHeadProps` - the arrow head. | ||
Note that `arrowBody` and `arrowHead` receives props of svg path element, `SVGcanvas` receives props of svg element, and `divContainerProps` of a div element. | ||
examples: | ||
- `arrowHead = {onClick: () => console.log("head clicked!")}` - now only the head will console log a message when clicked. | ||
##### extendSVGcanvas | ||
@@ -227,8 +242,3 @@ | ||
if you wish you can pass props specifically to either the body of the arrow,or his head,or even the svg canvas which contains both of them. | ||
note that `arrowBody` and `arrowHead` receives props of svg path element and `SVGcanvas` receives props of svg element. | ||
examples: | ||
- `advanced= {{passProps: {arrowHead:{onClick: () => console.log("head clicked!")}}}}` - now only the head will console log a message when clicked. | ||
### default props | ||
@@ -252,3 +262,7 @@ | ||
passProps: {}, | ||
advanced: { extendSVGcanvas: 0, passProps: { arrowBody: {}, arrowHead: {}, SVGcanvas: {} } }, | ||
arrowBodyProps: {}, | ||
arrowHeadProps: {}, | ||
SVGcanvasProps: {}, | ||
divContainerProps: {}, | ||
extendSVGcanvas: 0, | ||
}; | ||
@@ -258,2 +272,2 @@ ``` | ||
## Versions | ||
See CHANGELOG.md in this repo. | ||
See [CHANGELOG.md](https://github.com/Eliav2/react-xarrows/blob/master/CHANGELOG.md) in this repo. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
79289
32
824
263
1