link.tsx 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import * as React from 'react';
  2. import {Link as RouterLink, withRouter, WithRouterProps} from 'react-router';
  3. import isPropValid from '@emotion/is-prop-valid';
  4. import styled from '@emotion/styled';
  5. import * as Sentry from '@sentry/react';
  6. import {Location, LocationDescriptor} from 'history';
  7. type AnchorProps = React.HTMLProps<HTMLAnchorElement>;
  8. type ToLocationFunction = (location: Location) => LocationDescriptor;
  9. type Props = WithRouterProps & {
  10. // URL
  11. to: ToLocationFunction | LocationDescriptor;
  12. // Styles applied to the component's root
  13. className?: string;
  14. } & Omit<AnchorProps, 'href' | 'target' | 'as' | 'css'>;
  15. /**
  16. * A context-aware version of Link (from react-router) that falls
  17. * back to <a> if there is no router present
  18. */
  19. class Link extends React.Component<Props> {
  20. componentDidMount() {
  21. const isRouterPresent = this.props.location;
  22. if (!isRouterPresent) {
  23. Sentry.captureException(
  24. new Error('The link component was rendered without being wrapped by a <Router />')
  25. );
  26. }
  27. }
  28. render() {
  29. const {disabled, to, ref, location, ...props} = this.props;
  30. if (!disabled && location) {
  31. return <RouterLink to={to} ref={ref as any} {...props} />;
  32. }
  33. if (typeof to === 'string') {
  34. return <Anchor href={to} ref={ref} disabled={disabled} {...props} />;
  35. }
  36. return <Anchor href="" ref={ref} {...props} disabled />;
  37. }
  38. }
  39. export default withRouter(Link);
  40. const Anchor = styled('a', {
  41. shouldForwardProp: prop =>
  42. typeof prop === 'string' && isPropValid(prop) && prop !== 'disabled',
  43. })<{disabled?: boolean}>`
  44. ${p =>
  45. p.disabled &&
  46. `
  47. color:${p.theme.disabled};
  48. pointer-events: none;
  49. :hover {
  50. color: ${p.theme.disabled};
  51. }
  52. `};
  53. `;