boldr-ui
Version:
UI components for Boldr
111 lines (96 loc) • 2.74 kB
Flow
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Route from 'react-router-dom/Route';
const isModifiedEvent = event =>
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
export default class LinkContainer extends Component {
static contextTypes = {
router: PropTypes.shape({
history: PropTypes.shape({
push: PropTypes.func.isRequired,
replace: PropTypes.func.isRequired,
createHref: PropTypes.func.isRequired,
}).isRequired,
}).isRequired,
};
static propTypes = {
children: PropTypes.element.isRequired,
onClick: PropTypes.func,
replace: PropTypes.bool,
to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
exact: PropTypes.bool,
strict: PropTypes.bool,
className: PropTypes.string,
activeClassName: PropTypes.string,
style: PropTypes.object,
activeStyle: PropTypes.object,
isActive: PropTypes.func,
};
static defaultProps = {
replace: false,
exact: false,
strict: false,
activeClassName: 'active',
};
handleClick = event => {
const { children, onClick } = this.props;
if (children.props.onClick) {
children.props.onClick(event);
}
if (onClick) {
onClick(event);
}
if (
// onClick prevented default
!event.defaultPrevented &&
// ignore right clicks
event.button === 0 &&
// ignore clicks with modifier keys
!isModifiedEvent(event)
) {
event.preventDefault();
const { history } = this.context.router;
const { replace, to } = this.props;
if (replace) {
history.replace(to);
} else {
history.push(to);
}
}
};
render() {
const {
children,
replace, // eslint-disable-line no-unused-vars
to,
exact,
strict,
activeClassName,
className,
activeStyle,
style,
isActive: getIsActive,
...props
} = this.props;
const href = this.context.router.history.createHref(
typeof to === 'string' ? { pathname: to } : to,
);
return (
<Route
path={typeof to === 'object' ? to.pathname : to}
exact={exact}
strict={strict}
children={({ location, match }) => {
const isActive = !!(getIsActive ? getIsActive(match, location) : match);
return React.cloneElement(React.Children.only(children), {
...props,
className: isActive ? [className, activeClassName].join(' ') : className,
style: isActive ? { ...style, ...activeStyle } : style,
href,
onClick: this.handleClick,
});
}}
/>
);
}
}