UNPKG

@6thquake/react-material

Version:

React components that implement Google's Material Design.

386 lines (332 loc) 11.4 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.Line = exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _propTypes = _interopRequireDefault(require("prop-types")); var _react = _interopRequireWildcard(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _pubsubJs = _interopRequireDefault(require("pubsub-js")); var _Arrow = _interopRequireDefault(require("../Arrow.js")); var defaultAnchor = { x: 0.5, y: 1 }; var defaultBorderColor = '#000'; var defaultBorderStyle = 'solid'; var defaultBorderWidth = 1; var optionalStyleProps = { borderColor: _propTypes.default.string, borderStyle: _propTypes.default.string, borderWidth: _propTypes.default.number, className: _propTypes.default.string, zIndex: _propTypes.default.number }; var LineTo = /*#__PURE__*/ function (_Component) { (0, _inherits2.default)(LineTo, _Component); function LineTo(props) { var _this; (0, _classCallCheck2.default)(this, LineTo); _this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(LineTo).call(this, props)); _this.state = { fromAnchor: 'center middle', toAnchor: 'center middle' }; return _this; } (0, _createClass2.default)(LineTo, [{ key: "componentWillMount", value: function componentWillMount() { // this.fromAnchor = this.parseAnchor(this.props.fromAnchor); // this.toAnchor = this.parseAnchor(this.props.toAnchor); this.delay = this.parseDelay(this.props.delay); } }, { key: "componentDidMount", value: function componentDidMount() { var _this2 = this; this.delay = this.parseDelay(this.props.delay); if (typeof this.delay !== 'undefined') { this.deferUpdate(this.delay); } this.pubsub_token = _pubsubJs.default.subscribe('boxMove', function (msg, data) { _this2.setState({ fromAnchor: data[0], toAnchor: data[1] }); }); } }, { key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { /* if (nextProps.fromAnchor !== this.props.fromAnchor) { this.fromAnchor = this.parseAnchor(this.props.fromAnchor); } if (nextProps.toAnchor !== this.props.toAnchor) { this.toAnchor = this.parseAnchor(this.props.toAnchor); } */ this.delay = this.parseDelay(nextProps.delay); if (typeof this.delay !== 'undefined') { this.deferUpdate(this.delay); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { if (this.t) { clearTimeout(this.t); this.t = null; } } }, { key: "shouldComponentUpdate", value: function shouldComponentUpdate() { // Always update component if the parent component has been updated. // The reason for this is that we would not only like to update // this component when the props have changed, but also when // the position of our target elements has changed. // We could return true only if the positions of `from` and `to` have // changed, but that may be expensive and unnecessary. return true; } // Forced update after delay (MS) }, { key: "deferUpdate", value: function deferUpdate(delay) { var _this3 = this; if (this.t) { clearTimeout(this.t); } this.t = setTimeout(function () { return _this3.forceUpdate(); }, delay); } }, { key: "parseDelay", value: function parseDelay(value) { if (typeof value === 'undefined') { return value; } if (typeof value === 'boolean' && value) { return 0; } var delay = parseInt(value, 10); if (isNaN(delay) || !isFinite(delay)) { throw new Error("LinkTo could not parse delay attribute \"".concat(value, "\"")); } return delay; } }, { key: "parseAnchorText", value: function parseAnchorText(value) { // Try to infer the relevant axis. switch (value) { case 'top': return { y: 0 }; case 'left': return { x: 0 }; case 'top-middle': return { y: 0.25 }; case 'left-center': return { x: 0.25 }; case 'middle': return { y: 0.5 }; case 'center': return { x: 0.5 }; case 'middle-bottom': return { y: 0.75 }; case 'center-right': return { x: 0.75 }; case 'bottom': return { y: 1 }; case 'right': return { x: 1 }; } return null; } }, { key: "parseAnchor", value: function parseAnchor(value) { if (!value) { return defaultAnchor; } var parts = value.split(' '); if (parts.length > 2) { throw new Error('LinkTo anchor format is "<x> <y>"'); } var _parts = (0, _slicedToArray2.default)(parts, 2), x = _parts[0], y = _parts[1]; return (0, _extends2.default)({}, defaultAnchor, x ? this.parseAnchorText(x) : {}, y ? this.parseAnchorText(y) : {}); } }, { key: "detect", value: function detect() { var _this$props = this.props, from = _this$props.from, to = _this$props.to; if (!from || !to) { return false; } var anchor0 = this.parseAnchor(this.state.fromAnchor); var anchor1 = this.parseAnchor(this.state.toAnchor); var box0 = from.getBoundingClientRect(); var box1 = to.getBoundingClientRect(); var offsetX = window.pageXOffset; var offsetY = window.pageYOffset; var x0 = box0.left + box0.width * anchor0.x + offsetX; var x1 = box1.left + box1.width * anchor1.x + offsetX; var y0 = box0.top + box0.height * anchor0.y + offsetY; var y1 = box1.top + box1.height * anchor1.y + offsetY; return { x0: x0, y0: y0, x1: x1, y1: y1 }; } }, { key: "render", value: function render() { var points = this.detect(); var doc = document.documentElement; var body = document.body; var offsetX = (doc.scrollLeft || body.scrollLeft || 0) - (doc.clientLeft || body.clientLeft || 0); var offsetY = (doc.scrollTop || body.scrollTop || 0) - (doc.clientTop || body.clientTop || 0); var toX = points.x1 - offsetX - 120; var toY = points.y1 - offsetY - 415; return points ? _react.default.createElement("div", null, _react.default.createElement(Line, (0, _extends2.default)({}, points, this.props, { toX: toX, toY: toY }))) : null; } }]); return LineTo; }(_react.Component); exports.default = LineTo; LineTo.propTypes = (0, _extends2.default)({}, { // from: PropTypes.string.isRequired, // to: PropTypes.string.isRequired, // within: PropTypes.string, // fromAnchor: PropTypes.string, // toAnchor: PropTypes.string, delay: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.bool]) }, optionalStyleProps); var Line = /*#__PURE__*/ function (_PureComponent) { (0, _inherits2.default)(Line, _PureComponent); function Line() { (0, _classCallCheck2.default)(this, Line); return (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(Line).apply(this, arguments)); } (0, _createClass2.default)(Line, [{ key: "componentDidMount", value: function componentDidMount() { document.body.appendChild(this.el); document.body.appendChild(this.arrow); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { document.body.removeChild(this.el); document.body.removeChild(this.arrow); } }, { key: "render", value: function render() { var _this4 = this; var _this$props2 = this.props, x0 = _this$props2.x0, y0 = _this$props2.y0, x1 = _this$props2.x1, y1 = _this$props2.y1; var dy = y1 - y0; var dx = x1 - x0; var angle = Math.atan2(dy, dx) * 180 / Math.PI; var length = Math.sqrt(dx * dx + dy * dy); var linePositionStyle = { position: 'absolute', top: "".concat(y0, "px"), left: "".concat(x0, "px"), width: "".concat(length, "px"), zIndex: Number.isFinite(this.props.zIndex) ? String(this.props.zIndex) : '1', transform: "rotate(".concat(angle, "deg)"), // Rotate around (x0, y0) transformOrigin: '0 0' }; var arrowPositionStyle = { transform: "rotate(".concat(angle, "deg )"), padding: '0', margin: '0', position: 'absolute', top: "".concat(y1 - 10, "px"), left: "".concat(x1 - 5, "px"), zIndex: '2' }; var defaultStyle = { borderTopColor: this.props.borderColor || defaultBorderColor, borderTopStyle: this.props.borderStyle || defaultBorderStyle, borderTopWidth: this.props.borderWidth || defaultBorderWidth }; var lineprops = { // className: this.props.className, style: (0, _extends2.default)({}, defaultStyle, linePositionStyle) }; // We need a wrapper element to prevent an exception when then // React component is removed. This is because we manually // move the rendered DOM element after creation. return _react.default.createElement("div", null, _react.default.createElement("div", { className: "react-lineto-placeholder" }, _react.default.createElement("div", (0, _extends2.default)({ ref: function ref(el) { _this4.el = el; } }, lineprops))), _react.default.createElement("div", { ref: function ref(arrow) { _this4.arrow = arrow; }, style: arrowPositionStyle }, _react.default.createElement(_Arrow.default, { arrowStyle: this.props.arrowStyle }))); } }]); return Line; }(_react.PureComponent); exports.Line = Line; Line.propTypes = (0, _extends2.default)({}, { x0: _propTypes.default.number.isRequired, y0: _propTypes.default.number.isRequired, x1: _propTypes.default.number.isRequired, y1: _propTypes.default.number.isRequired }, optionalStyleProps);