react-conventions
Version:
An open source set of React components that implement Ambassador's Design and UX patterns.
250 lines (199 loc) • 9.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _Icon = require('../Icon');
var _Icon2 = _interopRequireDefault(_Icon);
var _style = require('./style.scss');
var _style2 = _interopRequireDefault(_style);
var _immutable = require('immutable');
var _immutable2 = _interopRequireDefault(_immutable);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Breadcrumb = function (_React$Component) {
_inherits(Breadcrumb, _React$Component);
function Breadcrumb(props) {
_classCallCheck(this, Breadcrumb);
var _this = _possibleConstructorReturn(this, (Breadcrumb.__proto__ || Object.getPrototypeOf(Breadcrumb)).call(this, props));
_this.state = {
minimized: false,
childrenWidth: 0,
dropdownOpen: false,
routes: _immutable2.default.fromJS(_this.props.routes)
};
_this.handleResize = function () {
var breadcrumbsStyle = window.getComputedStyle(_this._breadcrumbsContainer);
var breadcrumbsRect = _this._breadcrumbsContainer.getBoundingClientRect();
var offsetValue = _this.props.offset || 0;
var calculatedBreadcrumbWidth = breadcrumbsRect.width - (parseInt(breadcrumbsStyle.paddingLeft) + parseInt(breadcrumbsStyle.paddingRight)) - offsetValue;
if (_this.state.routes.size > 1 && _this.state.childrenWidth > calculatedBreadcrumbWidth) {
_this.setState({ minimized: true });
} else {
_this.setState({ minimized: false, dropdownOpen: false });
}
};
_this.getChildrenWidth = function () {
var children = [].slice.call(_this._breadcrumbsContainer.children);
var width = 0;
children.map(function (element, index) {
var elemStyles = window.getComputedStyle(element);
width += element.getBoundingClientRect().width + parseInt(elemStyles.marginLeft) + parseInt(elemStyles.marginRight);
});
return width;
};
_this.getDropdownChildrenHeight = function () {
var children = [].slice.call(_this._breadcrumbsDropdown.children);
var height = 0;
children.map(function (element, index) {
var elemStyles = window.getComputedStyle(element);
height += element.getBoundingClientRect().height;
});
return height;
};
_this.componentWillReceiveProps = function (nextProps) {
_this.setState({ childrenWidth: _this.getChildrenWidth(), routes: _immutable2.default.fromJS(nextProps.routes) }, function () {
_this.handleResize();
});
};
_this.componentDidMount = function () {
_this.setState({ childrenWidth: _this.getChildrenWidth() }, function () {
_this.handleResize();
window.addEventListener('resize', _this.handleResize);
});
};
_this.componentWillUnmount = function () {
window.removeEventListener('resize', _this.handleResize);
document.removeEventListener('click', _this.toggleDropdown);
};
_this.toggleDropdown = function () {
_this.setState({ dropdownOpen: !_this.state.dropdownOpen }, function () {
if (_this.state.dropdownOpen) {
document.addEventListener('click', _this.toggleDropdown);
} else {
document.removeEventListener('click', _this.toggleDropdown);
}
});
};
_this.shouldComponentUpdate = function (nextProps, nextState) {
return nextState.minimized !== _this.state.minimized || nextState.dropdownOpen !== _this.state.dropdownOpen || !_immutable2.default.is(nextState.routes, _this.state.routes);
};
_this.getTags = function () {
var depth = _this.state.routes.size;
var that = _this;
var rootRendered = false;
return _this.state.routes.map(function (item, index) {
var title = item.get('title');
if (title === undefined) return;
var tags = [];
if (!that.state.minimized && rootRendered) {
tags.push(_react2.default.createElement(_Icon2.default, { key: index, name: 'icon-arrow-68', className: _style2.default['icon-arrow-68'], width: '14', height: '14', color: '#879098' }));
tags.push(_react2.default.createElement(
'span',
{ className: _style2.default.secondary },
title
));
return tags;
}
if (!that.state.minimized) {
tags.push(_react2.default.createElement(
'h2',
{ className: _style2.default.primary },
title
));
rootRendered = true;
return tags;
}
if (rootRendered && index === depth - 1) {
tags.push(_react2.default.createElement(_Icon2.default, { key: index, name: 'icon-arrow-68', className: _style2.default['icon-arrow-68'], width: '14', height: '14', color: '#879098' }));
tags.push(_react2.default.createElement(
'span',
{ className: _style2.default.secondary },
title
));
return tags;
}
if (!rootRendered) {
tags.push(_react2.default.createElement(
'span',
{ className: _style2.default.ellipsis, onClick: that.toggleDropdown },
'...'
));
rootRendered = true;
return tags;
}
});
};
_this.getHiddenTags = function () {
var depth = _this.state.routes.size;
return _this.state.routes.map(function (item, index) {
var title = item.get('title');
if (title === undefined) return;
var tags = [];
if (index + 1 < depth) {
tags.push(_react2.default.createElement(
'li',
{ className: _style2.default['dropdown-item'] },
title
));
}
return tags;
});
};
_this.getStyle = function () {
var style = {
height: '0px',
opacity: '0',
transition: 'height 250ms cubic-bezier(0.46, 0.03, 0.52, 0.96) 0ms, opacity 0ms cubic-bezier(0.46, 0.03, 0.52, 0.96) 250ms'
};
if (_this.state.dropdownOpen && _this.state.minimized) {
style.height = _this.getDropdownChildrenHeight() + 'px';
style.opacity = '1';
style.transition = 'height 250ms cubic-bezier(0.46, 0.03, 0.52, 0.96) 0ms, opacity 250ms cubic-bezier(0.46, 0.03, 0.52, 0.96) 0ms';
}
return style;
};
return _this;
}
_createClass(Breadcrumb, [{
key: 'render',
value: function render() {
var _this2 = this;
var breadcrumbs = this.getTags();
return _react2.default.createElement(
'div',
{ className: _style2.default['breadcrumbs-container'] },
_react2.default.createElement(
'div',
{ className: _style2.default.breadcrumb, ref: function ref(c) {
return _this2._breadcrumbsContainer = c;
} },
this.getTags()
),
_react2.default.createElement(
'ul',
{ className: _style2.default['breadcrumbs-dropdown'], style: this.getStyle(), ref: function ref(c) {
return _this2._breadcrumbsDropdown = c;
} },
this.getHiddenTags()
)
);
}
}]);
return Breadcrumb;
}(_react2.default.Component);
Breadcrumb.propTypes = {
/**
* The array of routes to generate the Breadcrumbs.
*/
routes: _react2.default.PropTypes.array.isRequired,
/**
* Optional offset to trigger 'minimize' state.
*/
offset: _react2.default.PropTypes.number
};
exports.default = Breadcrumb;