UNPKG

react-router

Version:
144 lines (113 loc) 4.47 kB
var _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; }; function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } import React from 'react'; import invariant from 'invariant'; import { routerShape } from './PropTypes'; import { ContextSubscriber } from './ContextUtils'; var _React$PropTypes = React.PropTypes, bool = _React$PropTypes.bool, object = _React$PropTypes.object, string = _React$PropTypes.string, func = _React$PropTypes.func, oneOfType = _React$PropTypes.oneOfType; function isLeftClickEvent(event) { return event.button === 0; } function isModifiedEvent(event) { return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); } // TODO: De-duplicate against hasAnyProperties in createTransitionManager. function isEmptyObject(object) { for (var p in object) { if (Object.prototype.hasOwnProperty.call(object, p)) return false; }return true; } function resolveToLocation(to, router) { return typeof to === 'function' ? to(router.location) : to; } /** * A <Link> is used to create an <a> element that links to a route. * When that route is active, the link gets the value of its * activeClassName prop. * * For example, assuming you have the following route: * * <Route path="/posts/:postID" component={Post} /> * * You could use the following component to link to that route: * * <Link to={`/posts/${post.id}`} /> * * Links may pass along location state and/or query string parameters * in the state/query props, respectively. * * <Link ... query={{ show: true }} state={{ the: 'state' }} /> */ var Link = React.createClass({ displayName: 'Link', mixins: [ContextSubscriber('router')], contextTypes: { router: routerShape }, propTypes: { to: oneOfType([string, object, func]), query: object, hash: string, state: object, activeStyle: object, activeClassName: string, onlyActiveOnIndex: bool.isRequired, onClick: func, target: string }, getDefaultProps: function getDefaultProps() { return { onlyActiveOnIndex: false, style: {} }; }, handleClick: function handleClick(event) { if (this.props.onClick) this.props.onClick(event); if (event.defaultPrevented) return; var router = this.context.router; !router ? process.env.NODE_ENV !== 'production' ? invariant(false, '<Link>s rendered outside of a router context cannot navigate.') : invariant(false) : void 0; if (isModifiedEvent(event) || !isLeftClickEvent(event)) return; // If target prop is set (e.g. to "_blank"), let browser handle link. /* istanbul ignore if: untestable with Karma */ if (this.props.target) return; event.preventDefault(); router.push(resolveToLocation(this.props.to, router)); }, render: function render() { var _props = this.props, to = _props.to, activeClassName = _props.activeClassName, activeStyle = _props.activeStyle, onlyActiveOnIndex = _props.onlyActiveOnIndex, props = _objectWithoutProperties(_props, ['to', 'activeClassName', 'activeStyle', 'onlyActiveOnIndex']); // Ignore if rendered outside the context of router to simplify unit testing. var router = this.context.router; if (router) { // If user does not specify a `to` prop, return an empty anchor tag. if (!to) { return React.createElement('a', props); } var toLocation = resolveToLocation(to, router); props.href = router.createHref(toLocation); if (activeClassName || activeStyle != null && !isEmptyObject(activeStyle)) { if (router.isActive(toLocation, onlyActiveOnIndex)) { if (activeClassName) { if (props.className) { props.className += ' ' + activeClassName; } else { props.className = activeClassName; } } if (activeStyle) props.style = _extends({}, props.style, activeStyle); } } } return React.createElement('a', _extends({}, props, { onClick: this.handleClick })); } }); export default Link;