Projekt

Obecné

Profil

Stáhnout (3.19 KB) Statistiky
| Větev: | Revize:
1
import React from "react";
2
import { __RouterContext as RouterContext } from "react-router";
3
import PropTypes from "prop-types";
4
import invariant from "tiny-invariant";
5
import { resolveToLocation, normalizeToLocation } from "./utils/locationUtils";
6

    
7
// React 15 compat
8
const forwardRefShim = C => C;
9
let { forwardRef } = React;
10
if (typeof forwardRef === "undefined") {
11
  forwardRef = forwardRefShim;
12
}
13

    
14
function isModifiedEvent(event) {
15
  return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
16
}
17

    
18
const LinkAnchor = forwardRef(
19
  (
20
    {
21
      innerRef, // TODO: deprecate
22
      navigate,
23
      onClick,
24
      ...rest
25
    },
26
    forwardedRef
27
  ) => {
28
    const { target } = rest;
29

    
30
    let props = {
31
      ...rest,
32
      onClick: event => {
33
        try {
34
          if (onClick) onClick(event);
35
        } catch (ex) {
36
          event.preventDefault();
37
          throw ex;
38
        }
39

    
40
        if (
41
          !event.defaultPrevented && // onClick prevented default
42
          event.button === 0 && // ignore everything but left clicks
43
          (!target || target === "_self") && // let browser handle "target=_blank" etc.
44
          !isModifiedEvent(event) // ignore clicks with modifier keys
45
        ) {
46
          event.preventDefault();
47
          navigate();
48
        }
49
      }
50
    };
51

    
52
    // React 15 compat
53
    if (forwardRefShim !== forwardRef) {
54
      props.ref = forwardedRef || innerRef;
55
    } else {
56
      props.ref = innerRef;
57
    }
58

    
59
    return <a {...props} />;
60
  }
61
);
62

    
63
if (__DEV__) {
64
  LinkAnchor.displayName = "LinkAnchor";
65
}
66

    
67
/**
68
 * The public API for rendering a history-aware <a>.
69
 */
70
const Link = forwardRef(
71
  (
72
    {
73
      component = LinkAnchor,
74
      replace,
75
      to,
76
      innerRef, // TODO: deprecate
77
      ...rest
78
    },
79
    forwardedRef
80
  ) => {
81
    return (
82
      <RouterContext.Consumer>
83
        {context => {
84
          invariant(context, "You should not use <Link> outside a <Router>");
85

    
86
          const { history } = context;
87

    
88
          const location = normalizeToLocation(
89
            resolveToLocation(to, context.location),
90
            context.location
91
          );
92

    
93
          const href = location ? history.createHref(location) : "";
94
          const props = {
95
            ...rest,
96
            href,
97
            navigate() {
98
              const location = resolveToLocation(to, context.location);
99
              const method = replace ? history.replace : history.push;
100

    
101
              method(location);
102
            }
103
          };
104

    
105
          // React 15 compat
106
          if (forwardRefShim !== forwardRef) {
107
            props.ref = forwardedRef || innerRef;
108
          } else {
109
            props.innerRef = innerRef;
110
          }
111

    
112
          return React.createElement(component, props);
113
        }}
114
      </RouterContext.Consumer>
115
    );
116
  }
117
);
118

    
119
if (__DEV__) {
120
  const toType = PropTypes.oneOfType([
121
    PropTypes.string,
122
    PropTypes.object,
123
    PropTypes.func
124
  ]);
125
  const refType = PropTypes.oneOfType([
126
    PropTypes.string,
127
    PropTypes.func,
128
    PropTypes.shape({ current: PropTypes.any })
129
  ]);
130

    
131
  Link.displayName = "Link";
132

    
133
  Link.propTypes = {
134
    innerRef: refType,
135
    onClick: PropTypes.func,
136
    replace: PropTypes.bool,
137
    target: PropTypes.string,
138
    to: toType.isRequired
139
  };
140
}
141

    
142
export default Link;
(3-3/5)