@6thquake/react-material
Version:
React components that implement Google's Material Design.
386 lines (332 loc) • 11.4 kB
JavaScript
"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);