UNPKG

react-annotation

Version:

React components for annotating SVG elements

416 lines (357 loc) 15.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _alignment4 = _interopRequireDefault(require("viz-annotation/lib/Note/alignment")); var _Handle = _interopRequireDefault(require("../Handle")); var _lineTypeVertical = _interopRequireDefault(require("viz-annotation/lib/Note/lineType-vertical")); var _lineTypeHorizontal = _interopRequireDefault(require("viz-annotation/lib/Note/lineType-horizontal")); var _propTypes = _interopRequireDefault(require("prop-types")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var getOuterBBox = function getOuterBBox() { for (var _len = arguments.length, domNodes = new Array(_len), _key = 0; _key < _len; _key++) { domNodes[_key] = arguments[_key]; } return domNodes.concat().reduce(function (p, c) { if (c) { var bbox = c.getBBox(); p.x = Math.min(p.x, bbox.x); p.y = Math.min(p.y, bbox.y); p.width = Math.max(p.width, bbox.width); var yOffset = c && c.attributes && c.attributes.y; p.height = Math.max(p.height, (yOffset && parseFloat(yOffset.value) || 0) + bbox.height); } return p; }, { x: 0, y: 0, width: 0, height: 0 }); }; var Note = /*#__PURE__*/ function (_React$Component) { _inherits(Note, _React$Component); function Note(props) { var _this; _classCallCheck(this, Note); _this = _possibleConstructorReturn(this, _getPrototypeOf(Note).call(this, props)); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", { translateX: 0, translateY: 0, labelOffset: 0, changed: 0, bbox: { width: 0, height: 0, x: 0, y: 0 } }); _this.updateText = _this.updateText.bind(_assertThisInitialized(_assertThisInitialized(_this))); // this.note = React.createRef() // this.title = React.createRef() // this.label = React.createRef() return _this; } _createClass(Note, [{ key: "componentDidMount", value: function componentDidMount() { this.updateText(this.props); } }, { key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { if (nextProps.title !== this.props.title || nextProps.label !== this.props.label || nextProps.wrap !== this.props.wrap) { this.updateText(nextProps); } if (nextProps.editMode && (nextProps.align === "dynamic" || !nextProps.align)) { this.updateText(nextProps); } } }, { key: "updateText", value: function updateText(_ref) { var _this2 = this; var orientation = _ref.orientation, padding = _ref.padding, align = _ref.align, lineType = _ref.lineType, label = _ref.label, title = _ref.title, wrap = _ref.wrap, wrapSplitter = _ref.wrapSplitter, dx = _ref.dx, dy = _ref.dy; var newState = { titleWrapped: null, labelWrapped: null }; newState.changed = this.state.changed + 1; if (title) { newState.titleWrapped = this.title && this.wrapText(this.title, newState.changed, title, wrap, wrapSplitter); } if (label) newState.labelWrapped = this.label && this.wrapText(this.label, newState.changed, label, wrap, wrapSplitter); this.setState(newState, function () { var setLabel = function setLabel() { var bbox = getOuterBBox(_this2.title, _this2.label); var noteParams = { padding: padding, bbox: bbox, offset: { x: dx, y: dy }, orientation: orientation, align: align }; if (lineType === "vertical") noteParams.orientation = "leftRight";else if (lineType === "horizontal") noteParams.orientation = "topBottom"; var _alignment = (0, _alignment4.default)(noteParams), x = _alignment.x, y = _alignment.y; _this2.setState({ translateX: x, translateY: y, bbox: bbox }); }; _this2.setState({ labelOffset: title && _this2.title.getBBox().height || 0 }, setLabel); }); } }, { key: "wrapText", value: function wrapText(textRef, key, text, width, wrapSplitter) { var initialAttrs = { x: 0, dy: "1.2em" }; var words = text.split(wrapSplitter || /[ \t\r\n]+/).reverse().filter(function (w) { return w !== ""; }); var word, line = []; var tspans = []; while (word = words.pop()) { line.push(word); textRef.lastChild.textContent = line.join(" "); var length = textRef.lastChild.getComputedTextLength(); textRef.lastChild.textContent = ""; if (length > width && line.length > 1) { line.pop(); tspans.push(_react.default.createElement("tspan", _extends({ key: tspans.length + text }, initialAttrs), line.join(" "))); line = [word]; } } if (line.length !== 0) { tspans.push(_react.default.createElement("tspan", _extends({ key: tspans.length + text }, initialAttrs), line.join(" "))); } return _react.default.createElement("tspan", _extends({}, initialAttrs, { key: key + text }), tspans); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var _this$props = this.props, orientation = _this$props.orientation, padding = _this$props.padding, align = _this$props.align, dx = _this$props.dx, dy = _this$props.dy, lineType = _this$props.lineType; if (this.state.bbox.width && (prevProps.dx !== this.props.dx || prevProps.dy !== this.props.dy) && (this.title || this.label)) { var bbox = getOuterBBox(this.title, this.label); var noteParams = { padding: padding, bbox: bbox, offset: { x: dx, y: dy }, orientation: orientation, align: align }; if (lineType === "vertical") noteParams.orientation = "leftRight";else if (lineType === "horizontal") noteParams.orientation = "topBottom"; var _alignment2 = (0, _alignment4.default)(noteParams), x = _alignment2.x, y = _alignment2.y; var updates = { bbox: bbox }; if (this.state.translateX !== x) updates.translateX = x; if (this.state.translateY !== y) updates.translateY = y; if (updates.translateX !== undefined || updates.translateY !== undefined) { this.setState(updates); } } else if (this.state.align !== prevProps.align || this.props.orientation !== prevProps.orientation || this.props.padding !== prevProps.padding) { var _noteParams = { padding: padding, bbox: this.state.bbox, offset: { x: dx, y: dy }, orientation: orientation, align: align }; if (lineType === "vertical") _noteParams.orientation = "leftRight";else if (lineType === "horizontal") _noteParams.orientation = "topBottom"; var _alignment3 = (0, _alignment4.default)(_noteParams), _x = _alignment3.x, _y = _alignment3.y; var _updates = {}; if (this.state.translateX !== _x) _updates.translateX = _x; if (this.state.translateY !== _y) _updates.translateY = _y; if (_updates.translateX !== undefined || _updates.translateY !== undefined) { this.setState(_updates); } } } }, { key: "render", value: function render() { var _this3 = this; var _this$props2 = this.props, dx = _this$props2.dx, dy = _this$props2.dy, title = _this$props2.title, label = _this$props2.label, align = _this$props2.align, editMode = _this$props2.editMode, lineType = _this$props2.lineType, color = _this$props2.color, titleColor = _this$props2.titleColor, labelColor = _this$props2.labelColor, bgPadding = _this$props2.bgPadding; var bgPaddingFinal = { top: 0, bottom: 0, left: 0, right: 0 }; if (typeof bgPadding === "number") { bgPaddingFinal = { top: bgPadding, bottom: bgPadding, left: bgPadding, right: bgPadding }; } else if (bgPadding && _typeof(bgPadding) === "object") { bgPaddingFinal = Object.assign(bgPaddingFinal, bgPadding); } var noteTitle, noteText, noteLineType; if (title) { noteTitle = _react.default.createElement("text", { ref: function ref(el) { return _this3.title = el; }, className: "annotation-note-title", fontWeight: "bold", key: "title", fill: titleColor || color }, this.state.titleWrapped || _react.default.createElement("tspan", { x: 0, dy: ".8em" }, title)); } if (label) { noteText = _react.default.createElement("text", { ref: function ref(el) { return _this3.label = el; }, className: "annotation-note-label", y: this.state.labelOffset * 1.1, key: "label", fill: labelColor || color }, this.state.labelWrapped || _react.default.createElement("tspan", { x: 0, dy: ".8em" }, label)); } if (lineType && this.state.bbox.width) { var noteParams = { bbox: this.state.bbox, align: align, offset: { x: dx, y: dy } }; var noteComponent = (lineType === "vertical" && (0, _lineTypeVertical.default)(noteParams) || lineType === "horizontal" && (0, _lineTypeHorizontal.default)(noteParams)).components[0]; noteLineType = _react.default.createElement(noteComponent.type, _extends({ className: noteComponent.className }, noteComponent.attrs, { stroke: color })); } var handle; if (editMode) { handle = _react.default.createElement(_Handle.default, { handleStart: this.props.dragStart, handleStop: this.props.dragEnd, handleDrag: this.props.dragNote }); } return _react.default.createElement("g", _extends({ transform: "translate(".concat(dx, ", ").concat(dy, ")"), className: "annotation-note" }, this.props.gProps), _react.default.createElement("g", { className: "annotation-note-content", transform: "translate(".concat(this.state.translateX, ",\n ").concat(this.state.translateY, ")"), ref: function ref(el) { return _this3.note = el; } }, _react.default.createElement("rect", { className: "annotation-note-bg", width: this.state.bbox.width + bgPaddingFinal.left + bgPaddingFinal.right, x: -bgPaddingFinal.left, y: -bgPaddingFinal.top, height: this.state.bbox.height + bgPaddingFinal.top + bgPaddingFinal.bottom, stroke: "none", fill: "white", fillOpacity: "0" }), noteTitle, noteText), noteLineType, handle); } }]); return Note; }(_react.default.Component); exports.default = Note; Note.defaultProps = { wrap: 120, align: "dynamic", orientation: "topBottom", padding: 3 }; Note.propTypes = { dx: _propTypes.default.number, dy: _propTypes.default.number, title: _propTypes.default.string, label: _propTypes.default.string, orientation: _propTypes.default.oneOf(["leftRight", "topBottom"]), padding: _propTypes.default.number, bgPadding: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.object]), align: _propTypes.default.oneOf(["left", "right", "middle", "top", "bottom", "dynamic"]), editMode: _propTypes.default.bool, lineType: _propTypes.default.oneOf(["vertical", "horizontal"]), color: _propTypes.default.string, titleColor: _propTypes.default.string, labelColor: _propTypes.default.string };