react-intl 2.2.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/CONTRIBUTING.md +20 -0
  2. package/dist/react-intl.js +1017 -1475
  3. package/dist/react-intl.js.map +1 -1
  4. package/dist/react-intl.min.js +1 -2
  5. package/dist/react-intl.min.js.map +1 -1
  6. package/lib/index.es.js +983 -1428
  7. package/lib/index.js +990 -1435
  8. package/locale-data/af.js +1 -1
  9. package/locale-data/agq.js +1 -1
  10. package/locale-data/ak.js +1 -1
  11. package/locale-data/am.js +1 -1
  12. package/locale-data/ar.js +1 -1
  13. package/locale-data/ars.js +1 -0
  14. package/locale-data/as.js +1 -1
  15. package/locale-data/asa.js +1 -1
  16. package/locale-data/ast.js +1 -1
  17. package/locale-data/az.js +1 -1
  18. package/locale-data/bas.js +1 -1
  19. package/locale-data/be.js +1 -1
  20. package/locale-data/bem.js +1 -1
  21. package/locale-data/bez.js +1 -1
  22. package/locale-data/bg.js +1 -1
  23. package/locale-data/bh.js +1 -1
  24. package/locale-data/bm.js +1 -1
  25. package/locale-data/bn.js +1 -1
  26. package/locale-data/bo.js +1 -1
  27. package/locale-data/br.js +1 -1
  28. package/locale-data/brx.js +1 -1
  29. package/locale-data/bs.js +1 -1
  30. package/locale-data/ca.js +1 -1
  31. package/locale-data/ce.js +1 -1
  32. package/locale-data/cgg.js +1 -1
  33. package/locale-data/chr.js +1 -1
  34. package/locale-data/ckb.js +1 -1
  35. package/locale-data/cs.js +1 -1
  36. package/locale-data/cu.js +1 -1
  37. package/locale-data/cy.js +1 -1
  38. package/locale-data/da.js +1 -1
  39. package/locale-data/dav.js +1 -1
  40. package/locale-data/de.js +1 -1
  41. package/locale-data/dje.js +1 -1
  42. package/locale-data/dsb.js +1 -1
  43. package/locale-data/dua.js +1 -1
  44. package/locale-data/dv.js +1 -1
  45. package/locale-data/dyo.js +1 -1
  46. package/locale-data/dz.js +1 -1
  47. package/locale-data/ebu.js +1 -1
  48. package/locale-data/ee.js +1 -1
  49. package/locale-data/el.js +1 -1
  50. package/locale-data/en.js +1 -1
  51. package/locale-data/eo.js +1 -1
  52. package/locale-data/es.js +1 -1
  53. package/locale-data/et.js +1 -1
  54. package/locale-data/eu.js +1 -1
  55. package/locale-data/ewo.js +1 -1
  56. package/locale-data/fa.js +1 -1
  57. package/locale-data/ff.js +1 -1
  58. package/locale-data/fi.js +1 -1
  59. package/locale-data/fil.js +1 -1
  60. package/locale-data/fo.js +1 -1
  61. package/locale-data/fr.js +1 -1
  62. package/locale-data/fur.js +1 -1
  63. package/locale-data/fy.js +1 -1
  64. package/locale-data/ga.js +1 -1
  65. package/locale-data/gd.js +1 -1
  66. package/locale-data/gl.js +1 -1
  67. package/locale-data/gsw.js +1 -1
  68. package/locale-data/gu.js +1 -1
  69. package/locale-data/guw.js +1 -1
  70. package/locale-data/guz.js +1 -1
  71. package/locale-data/gv.js +1 -1
  72. package/locale-data/ha.js +1 -1
  73. package/locale-data/haw.js +1 -1
  74. package/locale-data/he.js +1 -1
  75. package/locale-data/hi.js +1 -1
  76. package/locale-data/hr.js +1 -1
  77. package/locale-data/hsb.js +1 -1
  78. package/locale-data/hu.js +1 -1
  79. package/locale-data/hy.js +1 -1
  80. package/locale-data/id.js +1 -1
  81. package/locale-data/ig.js +1 -1
  82. package/locale-data/ii.js +1 -1
  83. package/locale-data/in.js +1 -1
  84. package/locale-data/index.js +1 -10
  85. package/locale-data/is.js +1 -1
  86. package/locale-data/it.js +1 -1
  87. package/locale-data/iu.js +1 -1
  88. package/locale-data/iw.js +1 -1
  89. package/locale-data/ja.js +1 -1
  90. package/locale-data/jbo.js +1 -1
  91. package/locale-data/jgo.js +1 -1
  92. package/locale-data/ji.js +1 -1
  93. package/locale-data/jmc.js +1 -1
  94. package/locale-data/jv.js +1 -1
  95. package/locale-data/jw.js +1 -1
  96. package/locale-data/ka.js +1 -1
  97. package/locale-data/kab.js +1 -1
  98. package/locale-data/kaj.js +1 -1
  99. package/locale-data/kam.js +1 -1
  100. package/locale-data/kcg.js +1 -1
  101. package/locale-data/kde.js +1 -1
  102. package/locale-data/kea.js +1 -1
  103. package/locale-data/khq.js +1 -1
  104. package/locale-data/ki.js +1 -1
  105. package/locale-data/kk.js +1 -1
  106. package/locale-data/kkj.js +1 -1
  107. package/locale-data/kl.js +1 -1
  108. package/locale-data/kln.js +1 -1
  109. package/locale-data/km.js +1 -1
  110. package/locale-data/kn.js +1 -1
  111. package/locale-data/ko.js +1 -1
  112. package/locale-data/kok.js +1 -1
  113. package/locale-data/ks.js +1 -1
  114. package/locale-data/ksb.js +1 -1
  115. package/locale-data/ksf.js +1 -1
  116. package/locale-data/ksh.js +1 -1
  117. package/locale-data/ku.js +1 -1
  118. package/locale-data/kw.js +1 -1
  119. package/locale-data/ky.js +1 -1
  120. package/locale-data/lag.js +1 -1
  121. package/locale-data/lb.js +1 -1
  122. package/locale-data/lg.js +1 -1
  123. package/locale-data/lkt.js +1 -1
  124. package/locale-data/ln.js +1 -1
  125. package/locale-data/lo.js +1 -1
  126. package/locale-data/lrc.js +1 -1
  127. package/locale-data/lt.js +1 -1
  128. package/locale-data/lu.js +1 -1
  129. package/locale-data/luo.js +1 -1
  130. package/locale-data/luy.js +1 -1
  131. package/locale-data/lv.js +1 -1
  132. package/locale-data/mas.js +1 -1
  133. package/locale-data/mer.js +1 -1
  134. package/locale-data/mfe.js +1 -1
  135. package/locale-data/mg.js +1 -1
  136. package/locale-data/mgh.js +1 -1
  137. package/locale-data/mgo.js +1 -1
  138. package/locale-data/mk.js +1 -1
  139. package/locale-data/ml.js +1 -1
  140. package/locale-data/mn.js +1 -1
  141. package/locale-data/mo.js +1 -1
  142. package/locale-data/mr.js +1 -1
  143. package/locale-data/ms.js +1 -1
  144. package/locale-data/mt.js +1 -1
  145. package/locale-data/mua.js +1 -1
  146. package/locale-data/my.js +1 -1
  147. package/locale-data/mzn.js +1 -1
  148. package/locale-data/nah.js +1 -1
  149. package/locale-data/naq.js +1 -1
  150. package/locale-data/nb.js +1 -1
  151. package/locale-data/nd.js +1 -1
  152. package/locale-data/nds.js +1 -0
  153. package/locale-data/ne.js +1 -1
  154. package/locale-data/nl.js +1 -1
  155. package/locale-data/nmg.js +1 -1
  156. package/locale-data/nn.js +1 -1
  157. package/locale-data/nnh.js +1 -1
  158. package/locale-data/no.js +1 -1
  159. package/locale-data/nqo.js +1 -1
  160. package/locale-data/nr.js +1 -1
  161. package/locale-data/nso.js +1 -1
  162. package/locale-data/nus.js +1 -1
  163. package/locale-data/ny.js +1 -1
  164. package/locale-data/nyn.js +1 -1
  165. package/locale-data/om.js +1 -1
  166. package/locale-data/or.js +1 -1
  167. package/locale-data/os.js +1 -1
  168. package/locale-data/pa.js +1 -1
  169. package/locale-data/pap.js +1 -1
  170. package/locale-data/pl.js +1 -1
  171. package/locale-data/prg.js +1 -1
  172. package/locale-data/ps.js +1 -1
  173. package/locale-data/pt.js +1 -1
  174. package/locale-data/qu.js +1 -1
  175. package/locale-data/rm.js +1 -1
  176. package/locale-data/rn.js +1 -1
  177. package/locale-data/ro.js +1 -1
  178. package/locale-data/rof.js +1 -1
  179. package/locale-data/ru.js +1 -1
  180. package/locale-data/rw.js +1 -1
  181. package/locale-data/rwk.js +1 -1
  182. package/locale-data/sah.js +1 -1
  183. package/locale-data/saq.js +1 -1
  184. package/locale-data/sbp.js +1 -1
  185. package/locale-data/sdh.js +1 -1
  186. package/locale-data/se.js +1 -1
  187. package/locale-data/seh.js +1 -1
  188. package/locale-data/ses.js +1 -1
  189. package/locale-data/sg.js +1 -1
  190. package/locale-data/sh.js +1 -1
  191. package/locale-data/shi.js +1 -1
  192. package/locale-data/si.js +1 -1
  193. package/locale-data/sk.js +1 -1
  194. package/locale-data/sl.js +1 -1
  195. package/locale-data/sma.js +1 -1
  196. package/locale-data/smi.js +1 -1
  197. package/locale-data/smj.js +1 -1
  198. package/locale-data/smn.js +1 -1
  199. package/locale-data/sms.js +1 -1
  200. package/locale-data/sn.js +1 -1
  201. package/locale-data/so.js +1 -1
  202. package/locale-data/sq.js +1 -1
  203. package/locale-data/sr.js +1 -1
  204. package/locale-data/ss.js +1 -1
  205. package/locale-data/ssy.js +1 -1
  206. package/locale-data/st.js +1 -1
  207. package/locale-data/sv.js +1 -1
  208. package/locale-data/sw.js +1 -1
  209. package/locale-data/syr.js +1 -1
  210. package/locale-data/ta.js +1 -1
  211. package/locale-data/te.js +1 -1
  212. package/locale-data/teo.js +1 -1
  213. package/locale-data/th.js +1 -1
  214. package/locale-data/ti.js +1 -1
  215. package/locale-data/tig.js +1 -1
  216. package/locale-data/tk.js +1 -1
  217. package/locale-data/tl.js +1 -1
  218. package/locale-data/tn.js +1 -1
  219. package/locale-data/to.js +1 -1
  220. package/locale-data/tr.js +1 -1
  221. package/locale-data/ts.js +1 -1
  222. package/locale-data/twq.js +1 -1
  223. package/locale-data/tzm.js +1 -1
  224. package/locale-data/ug.js +1 -1
  225. package/locale-data/uk.js +1 -1
  226. package/locale-data/ur.js +1 -1
  227. package/locale-data/uz.js +1 -1
  228. package/locale-data/vai.js +1 -1
  229. package/locale-data/ve.js +1 -1
  230. package/locale-data/vi.js +1 -1
  231. package/locale-data/vo.js +1 -1
  232. package/locale-data/vun.js +1 -1
  233. package/locale-data/wa.js +1 -1
  234. package/locale-data/wae.js +1 -1
  235. package/locale-data/wo.js +1 -1
  236. package/locale-data/xh.js +1 -1
  237. package/locale-data/xog.js +1 -1
  238. package/locale-data/yav.js +1 -1
  239. package/locale-data/yi.js +1 -1
  240. package/locale-data/yo.js +1 -1
  241. package/locale-data/yue.js +1 -0
  242. package/locale-data/zgh.js +1 -1
  243. package/locale-data/zh.js +1 -1
  244. package/locale-data/zu.js +1 -1
  245. package/package.json +33 -27
  246. package/src/components/date.js +30 -29
  247. package/src/components/html-message.js +63 -62
  248. package/src/components/message.js +117 -114
  249. package/src/components/number.js +30 -29
  250. package/src/components/plural.js +37 -36
  251. package/src/components/provider.js +135 -134
  252. package/src/components/relative.js +128 -120
  253. package/src/components/time.js +30 -29
  254. package/src/define-messages.js +3 -3
  255. package/src/en.js +1 -1
  256. package/src/format.js +209 -208
  257. package/src/inject.js +38 -40
  258. package/src/locale-data-registry.js +21 -21
  259. package/src/plural.js +9 -9
  260. package/src/types.js +58 -48
  261. package/src/utils.js +65 -55
  262. package/yarn.lock +4832 -0
@@ -4,7 +4,8 @@
4
4
  * See the accompanying LICENSE file for terms.
5
5
  */
6
6
 
7
- import {Component, Children, PropTypes} from 'react';
7
+ import {Component, Children} from 'react';
8
+ import PropTypes from 'prop-types';
8
9
  import IntlMessageFormat from 'intl-messageformat';
9
10
  import IntlRelativeFormat from 'intl-relativeformat';
10
11
  import IntlPluralFormat from '../plural';
@@ -21,156 +22,156 @@ const intlFormatPropNames = Object.keys(intlFormatPropTypes);
21
22
  // These are not a static property on the `IntlProvider` class so the intl
22
23
  // config values can be inherited from an <IntlProvider> ancestor.
23
24
  const defaultProps = {
24
- formats : {},
25
- messages: {},
26
- textComponent: 'span',
25
+ formats: {},
26
+ messages: {},
27
+ textComponent: 'span',
27
28
 
28
- defaultLocale : 'en',
29
- defaultFormats: {},
29
+ defaultLocale: 'en',
30
+ defaultFormats: {},
30
31
  };
31
32
 
32
33
  export default class IntlProvider extends Component {
33
- static displayName = 'IntlProvider';
34
-
35
- static contextTypes = {
36
- intl: intlShape,
37
- };
38
-
39
- static childContextTypes = {
40
- intl: intlShape.isRequired,
41
- };
34
+ static displayName = 'IntlProvider';
35
+
36
+ static contextTypes = {
37
+ intl: intlShape,
38
+ };
39
+
40
+ static childContextTypes = {
41
+ intl: intlShape.isRequired,
42
+ };
43
+
44
+ static propTypes = {
45
+ ...intlConfigPropTypes,
46
+ children: PropTypes.element.isRequired,
47
+ initialNow: PropTypes.any,
48
+ };
49
+
50
+ constructor(props, context = {}) {
51
+ super(props, context);
52
+
53
+ invariant(
54
+ typeof Intl !== 'undefined',
55
+ '[React Intl] The `Intl` APIs must be available in the runtime, ' +
56
+ 'and do not appear to be built-in. An `Intl` polyfill should be loaded.\n' +
57
+ 'See: http://formatjs.io/guides/runtime-environments/'
58
+ );
59
+
60
+ const {intl: intlContext} = context;
61
+
62
+ // Used to stabilize time when performing an initial rendering so that
63
+ // all relative times use the same reference "now" time.
64
+ let initialNow;
65
+ if (isFinite(props.initialNow)) {
66
+ initialNow = Number(props.initialNow);
67
+ } else {
68
+ // When an `initialNow` isn't provided via `props`, look to see an
69
+ // <IntlProvider> exists in the ancestry and call its `now()`
70
+ // function to propagate its value for "now".
71
+ initialNow = intlContext ? intlContext.now() : Date.now();
72
+ }
42
73
 
43
- static propTypes = {
44
- ...intlConfigPropTypes,
45
- children : PropTypes.element.isRequired,
46
- initialNow: PropTypes.any,
74
+ // Creating `Intl*` formatters is expensive. If there's a parent
75
+ // `<IntlProvider>`, then its formatters will be used. Otherwise, this
76
+ // memoize the `Intl*` constructors and cache them for the lifecycle of
77
+ // this IntlProvider instance.
78
+ const {
79
+ formatters = {
80
+ getDateTimeFormat: memoizeIntlConstructor(Intl.DateTimeFormat),
81
+ getNumberFormat: memoizeIntlConstructor(Intl.NumberFormat),
82
+ getMessageFormat: memoizeIntlConstructor(IntlMessageFormat),
83
+ getRelativeFormat: memoizeIntlConstructor(IntlRelativeFormat),
84
+ getPluralFormat: memoizeIntlConstructor(IntlPluralFormat),
85
+ },
86
+ } =
87
+ intlContext || {};
88
+
89
+ this.state = {
90
+ ...formatters,
91
+
92
+ // Wrapper to provide stable "now" time for initial render.
93
+ now: () => {
94
+ return this._didDisplay ? Date.now() : initialNow;
95
+ },
47
96
  };
97
+ }
98
+
99
+ getConfig() {
100
+ const {intl: intlContext} = this.context;
101
+
102
+ // Build a whitelisted config object from `props`, defaults, and
103
+ // `context.intl`, if an <IntlProvider> exists in the ancestry.
104
+ let config = filterProps(this.props, intlConfigPropNames, intlContext);
105
+
106
+ // Apply default props. This must be applied last after the props have
107
+ // been resolved and inherited from any <IntlProvider> in the ancestry.
108
+ // This matches how React resolves `defaultProps`.
109
+ for (let propName in defaultProps) {
110
+ if (config[propName] === undefined) {
111
+ config[propName] = defaultProps[propName];
112
+ }
113
+ }
48
114
 
49
- constructor(props, context = {}) {
50
- super(props, context);
115
+ if (!hasLocaleData(config.locale)) {
116
+ const {locale, defaultLocale, defaultFormats} = config;
51
117
 
52
- invariant(typeof Intl !== 'undefined',
53
- '[React Intl] The `Intl` APIs must be available in the runtime, ' +
54
- 'and do not appear to be built-in. An `Intl` polyfill should be loaded.\n' +
55
- 'See: http://formatjs.io/guides/runtime-environments/'
118
+ if (process.env.NODE_ENV !== 'production') {
119
+ console.error(
120
+ `[React Intl] Missing locale data for locale: "${locale}". ` +
121
+ `Using default locale: "${defaultLocale}" as fallback.`
56
122
  );
57
-
58
- const {intl: intlContext} = context;
59
-
60
- // Used to stabilize time when performing an initial rendering so that
61
- // all relative times use the same reference "now" time.
62
- let initialNow;
63
- if (isFinite(props.initialNow)) {
64
- initialNow = Number(props.initialNow);
65
- } else {
66
- // When an `initialNow` isn't provided via `props`, look to see an
67
- // <IntlProvider> exists in the ancestry and call its `now()`
68
- // function to propagate its value for "now".
69
- initialNow = intlContext ? intlContext.now() : Date.now();
70
- }
71
-
72
- // Creating `Intl*` formatters is expensive. If there's a parent
73
- // `<IntlProvider>`, then its formatters will be used. Otherwise, this
74
- // memoize the `Intl*` constructors and cache them for the lifecycle of
75
- // this IntlProvider instance.
76
- const {formatters = {
77
- getDateTimeFormat: memoizeIntlConstructor(Intl.DateTimeFormat),
78
- getNumberFormat : memoizeIntlConstructor(Intl.NumberFormat),
79
- getMessageFormat : memoizeIntlConstructor(IntlMessageFormat),
80
- getRelativeFormat: memoizeIntlConstructor(IntlRelativeFormat),
81
- getPluralFormat : memoizeIntlConstructor(IntlPluralFormat),
82
- }} = (intlContext || {});
83
-
84
- this.state = {
85
- ...formatters,
86
-
87
- // Wrapper to provide stable "now" time for initial render.
88
- now: () => {
89
- return this._didDisplay ? Date.now() : initialNow;
90
- },
91
- };
123
+ }
124
+
125
+ // Since there's no registered locale data for `locale`, this will
126
+ // fallback to the `defaultLocale` to make sure things can render.
127
+ // The `messages` are overridden to the `defaultProps` empty object
128
+ // to maintain referential equality across re-renders. It's assumed
129
+ // each <FormattedMessage> contains a `defaultMessage` prop.
130
+ config = {
131
+ ...config,
132
+ locale: defaultLocale,
133
+ formats: defaultFormats,
134
+ messages: defaultProps.messages,
135
+ };
92
136
  }
93
137
 
94
- getConfig() {
95
- const {intl: intlContext} = this.context;
96
-
97
- // Build a whitelisted config object from `props`, defaults, and
98
- // `context.intl`, if an <IntlProvider> exists in the ancestry.
99
- let config = filterProps(this.props, intlConfigPropNames, intlContext);
100
-
101
- // Apply default props. This must be applied last after the props have
102
- // been resolved and inherited from any <IntlProvider> in the ancestry.
103
- // This matches how React resolves `defaultProps`.
104
- for (let propName in defaultProps) {
105
- if (config[propName] === undefined) {
106
- config[propName] = defaultProps[propName];
107
- }
108
- }
109
-
110
- if (!hasLocaleData(config.locale)) {
111
- const {
112
- locale,
113
- defaultLocale,
114
- defaultFormats,
115
- } = config;
116
-
117
- if (process.env.NODE_ENV !== 'production') {
118
- console.error(
119
- `[React Intl] Missing locale data for locale: "${locale}". ` +
120
- `Using default locale: "${defaultLocale}" as fallback.`
121
- );
122
- }
123
-
124
- // Since there's no registered locale data for `locale`, this will
125
- // fallback to the `defaultLocale` to make sure things can render.
126
- // The `messages` are overridden to the `defaultProps` empty object
127
- // to maintain referential equality across re-renders. It's assumed
128
- // each <FormattedMessage> contains a `defaultMessage` prop.
129
- config = {
130
- ...config,
131
- locale : defaultLocale,
132
- formats : defaultFormats,
133
- messages: defaultProps.messages,
134
- };
135
- }
136
-
137
- return config;
138
- }
138
+ return config;
139
+ }
139
140
 
140
- getBoundFormatFns(config, state) {
141
- return intlFormatPropNames.reduce((boundFormatFns, name) => {
142
- boundFormatFns[name] = format[name].bind(null, config, state);
143
- return boundFormatFns;
144
- }, {});
145
- }
141
+ getBoundFormatFns(config, state) {
142
+ return intlFormatPropNames.reduce((boundFormatFns, name) => {
143
+ boundFormatFns[name] = format[name].bind(null, config, state);
144
+ return boundFormatFns;
145
+ }, {});
146
+ }
146
147
 
147
- getChildContext() {
148
- const config = this.getConfig();
148
+ getChildContext() {
149
+ const config = this.getConfig();
149
150
 
150
- // Bind intl factories and current config to the format functions.
151
- const boundFormatFns = this.getBoundFormatFns(config, this.state);
151
+ // Bind intl factories and current config to the format functions.
152
+ const boundFormatFns = this.getBoundFormatFns(config, this.state);
152
153
 
153
- const {now, ...formatters} = this.state;
154
+ const {now, ...formatters} = this.state;
154
155
 
155
- return {
156
- intl: {
157
- ...config,
158
- ...boundFormatFns,
159
- formatters,
160
- now,
161
- },
162
- };
163
- }
156
+ return {
157
+ intl: {
158
+ ...config,
159
+ ...boundFormatFns,
160
+ formatters,
161
+ now,
162
+ },
163
+ };
164
+ }
164
165
 
165
- shouldComponentUpdate(...next) {
166
- return shouldIntlComponentUpdate(this, ...next);
167
- }
166
+ shouldComponentUpdate(...next) {
167
+ return shouldIntlComponentUpdate(this, ...next);
168
+ }
168
169
 
169
- componentDidMount() {
170
- this._didDisplay = true;
171
- }
170
+ componentDidMount() {
171
+ this._didDisplay = true;
172
+ }
172
173
 
173
- render() {
174
- return Children.only(this.props.children);
175
- }
174
+ render() {
175
+ return Children.only(this.props.children);
176
+ }
176
177
  }
@@ -4,160 +4,168 @@
4
4
  * See the accompanying LICENSE file for terms.
5
5
  */
6
6
 
7
- import React, {Component, PropTypes} from 'react';
7
+ import React, {Component} from 'react';
8
+ import PropTypes from 'prop-types';
8
9
  import {intlShape, relativeFormatPropTypes} from '../types';
9
10
  import {invariantIntlContext, shouldIntlComponentUpdate} from '../utils';
10
11
 
11
12
  const SECOND = 1000;
12
13
  const MINUTE = 1000 * 60;
13
- const HOUR = 1000 * 60 * 60;
14
- const DAY = 1000 * 60 * 60 * 24;
14
+ const HOUR = 1000 * 60 * 60;
15
+ const DAY = 1000 * 60 * 60 * 24;
15
16
 
16
17
  // The maximum timer delay value is a 32-bit signed integer.
17
18
  // See: https://mdn.io/setTimeout
18
19
  const MAX_TIMER_DELAY = 2147483647;
19
20
 
20
21
  function selectUnits(delta) {
21
- let absDelta = Math.abs(delta);
22
+ let absDelta = Math.abs(delta);
22
23
 
23
- if (absDelta < MINUTE) {
24
- return 'second';
25
- }
24
+ if (absDelta < MINUTE) {
25
+ return 'second';
26
+ }
26
27
 
27
- if (absDelta < HOUR) {
28
- return 'minute';
29
- }
28
+ if (absDelta < HOUR) {
29
+ return 'minute';
30
+ }
30
31
 
31
- if (absDelta < DAY) {
32
- return 'hour';
33
- }
32
+ if (absDelta < DAY) {
33
+ return 'hour';
34
+ }
34
35
 
35
- // The maximum scheduled delay will be measured in days since the maximum
36
- // timer delay is less than the number of milliseconds in 25 days.
37
- return 'day';
36
+ // The maximum scheduled delay will be measured in days since the maximum
37
+ // timer delay is less than the number of milliseconds in 25 days.
38
+ return 'day';
38
39
  }
39
40
 
40
41
  function getUnitDelay(units) {
41
- switch (units) {
42
- case 'second': return SECOND;
43
- case 'minute': return MINUTE;
44
- case 'hour' : return HOUR;
45
- case 'day' : return DAY;
46
- default : return MAX_TIMER_DELAY;
47
- }
42
+ switch (units) {
43
+ case 'second':
44
+ return SECOND;
45
+ case 'minute':
46
+ return MINUTE;
47
+ case 'hour':
48
+ return HOUR;
49
+ case 'day':
50
+ return DAY;
51
+ default:
52
+ return MAX_TIMER_DELAY;
53
+ }
48
54
  }
49
55
 
50
56
  function isSameDate(a, b) {
51
- if (a === b) {
52
- return true;
53
- }
57
+ if (a === b) {
58
+ return true;
59
+ }
54
60
 
55
- let aTime = new Date(a).getTime();
56
- let bTime = new Date(b).getTime();
61
+ let aTime = new Date(a).getTime();
62
+ let bTime = new Date(b).getTime();
57
63
 
58
- return isFinite(aTime) && isFinite(bTime) && aTime === bTime;
64
+ return isFinite(aTime) && isFinite(bTime) && aTime === bTime;
59
65
  }
60
66
 
61
67
  export default class FormattedRelative extends Component {
62
- static displayName = 'FormattedRelative';
63
-
64
- static contextTypes = {
65
- intl: intlShape,
66
- };
67
-
68
- static propTypes = {
69
- ...relativeFormatPropTypes,
70
- value : PropTypes.any.isRequired,
71
- format : PropTypes.string,
72
- updateInterval: PropTypes.number,
73
- initialNow : PropTypes.any,
74
- children : PropTypes.func,
75
- };
76
-
77
- static defaultProps = {
78
- updateInterval: 1000 * 10,
79
- };
80
-
81
- constructor(props, context) {
82
- super(props, context);
83
- invariantIntlContext(context);
84
-
85
- let now = isFinite(props.initialNow) ?
86
- Number(props.initialNow) : context.intl.now();
87
-
88
- // `now` is stored as state so that `render()` remains a function of
89
- // props + state, instead of accessing `Date.now()` inside `render()`.
90
- this.state = {now};
91
- }
92
-
93
- scheduleNextUpdate(props, state) {
94
- const {updateInterval} = props;
95
-
96
- // If the `updateInterval` is falsy, including `0`, then auto updates
97
- // have been turned off, so we bail and skip scheduling an update.
98
- if (!updateInterval) {
99
- return;
100
- }
101
-
102
- let time = new Date(props.value).getTime();
103
- let delta = time - state.now;
104
- let units = props.units || selectUnits(delta);
105
-
106
- let unitDelay = getUnitDelay(units);
107
- let unitRemainder = Math.abs(delta % unitDelay);
108
-
109
- // We want the largest possible timer delay which will still display
110
- // accurate information while reducing unnecessary re-renders. The delay
111
- // should be until the next "interesting" moment, like a tick from
112
- // "1 minute ago" to "2 minutes ago" when the delta is 120,000ms.
113
- let delay = delta < 0 ?
114
- Math.max(updateInterval, unitDelay - unitRemainder) :
115
- Math.max(updateInterval, unitRemainder);
116
-
117
- clearTimeout(this._timer);
118
-
119
- this._timer = setTimeout(() => {
120
- this.setState({now: this.context.intl.now()});
121
- }, delay);
122
- }
123
-
124
- componentDidMount() {
125
- this.scheduleNextUpdate(this.props, this.state);
68
+ static displayName = 'FormattedRelative';
69
+
70
+ static contextTypes = {
71
+ intl: intlShape,
72
+ };
73
+
74
+ static propTypes = {
75
+ ...relativeFormatPropTypes,
76
+ value: PropTypes.any.isRequired,
77
+ format: PropTypes.string,
78
+ updateInterval: PropTypes.number,
79
+ initialNow: PropTypes.any,
80
+ children: PropTypes.func,
81
+ };
82
+
83
+ static defaultProps = {
84
+ updateInterval: 1000 * 10,
85
+ };
86
+
87
+ constructor(props, context) {
88
+ super(props, context);
89
+ invariantIntlContext(context);
90
+
91
+ let now = isFinite(props.initialNow)
92
+ ? Number(props.initialNow)
93
+ : context.intl.now();
94
+
95
+ // `now` is stored as state so that `render()` remains a function of
96
+ // props + state, instead of accessing `Date.now()` inside `render()`.
97
+ this.state = {now};
98
+ }
99
+
100
+ scheduleNextUpdate(props, state) {
101
+ // Cancel and pending update because we're scheduling a new update.
102
+ clearTimeout(this._timer);
103
+
104
+ const {value, units, updateInterval} = props;
105
+ const time = new Date(value).getTime();
106
+
107
+ // If the `updateInterval` is falsy, including `0` or we don't have a
108
+ // valid date, then auto updates have been turned off, so we bail and
109
+ // skip scheduling an update.
110
+ if (!updateInterval || !isFinite(time)) {
111
+ return;
126
112
  }
127
113
 
128
- componentWillReceiveProps({value: nextValue}) {
129
- // When the `props.value` date changes, `state.now` needs to be updated,
130
- // and the next update can be rescheduled.
131
- if (!isSameDate(nextValue, this.props.value)) {
132
- this.setState({now: this.context.intl.now()});
133
- }
114
+ const delta = time - state.now;
115
+ const unitDelay = getUnitDelay(units || selectUnits(delta));
116
+ const unitRemainder = Math.abs(delta % unitDelay);
117
+
118
+ // We want the largest possible timer delay which will still display
119
+ // accurate information while reducing unnecessary re-renders. The delay
120
+ // should be until the next "interesting" moment, like a tick from
121
+ // "1 minute ago" to "2 minutes ago" when the delta is 120,000ms.
122
+ const delay =
123
+ delta < 0
124
+ ? Math.max(updateInterval, unitDelay - unitRemainder)
125
+ : Math.max(updateInterval, unitRemainder);
126
+
127
+ this._timer = setTimeout(() => {
128
+ this.setState({now: this.context.intl.now()});
129
+ }, delay);
130
+ }
131
+
132
+ componentDidMount() {
133
+ this.scheduleNextUpdate(this.props, this.state);
134
+ }
135
+
136
+ componentWillReceiveProps({value: nextValue}) {
137
+ // When the `props.value` date changes, `state.now` needs to be updated,
138
+ // and the next update can be rescheduled.
139
+ if (!isSameDate(nextValue, this.props.value)) {
140
+ this.setState({now: this.context.intl.now()});
134
141
  }
142
+ }
135
143
 
136
- shouldComponentUpdate(...next) {
137
- return shouldIntlComponentUpdate(this, ...next);
138
- }
144
+ shouldComponentUpdate(...next) {
145
+ return shouldIntlComponentUpdate(this, ...next);
146
+ }
139
147
 
140
- componentWillUpdate(nextProps, nextState) {
141
- this.scheduleNextUpdate(nextProps, nextState);
142
- }
148
+ componentWillUpdate(nextProps, nextState) {
149
+ this.scheduleNextUpdate(nextProps, nextState);
150
+ }
143
151
 
144
- componentWillUnmount() {
145
- clearTimeout(this._timer);
146
- }
152
+ componentWillUnmount() {
153
+ clearTimeout(this._timer);
154
+ }
147
155
 
148
- render() {
149
- const {formatRelative, textComponent: Text} = this.context.intl;
150
- const {value, children} = this.props;
156
+ render() {
157
+ const {formatRelative, textComponent: Text} = this.context.intl;
158
+ const {value, children} = this.props;
151
159
 
152
- let formattedRelative = formatRelative(value, {
153
- ...this.props,
154
- ...this.state,
155
- });
160
+ let formattedRelative = formatRelative(value, {
161
+ ...this.props,
162
+ ...this.state,
163
+ });
156
164
 
157
- if (typeof children === 'function') {
158
- return children(formattedRelative);
159
- }
160
-
161
- return <Text>{formattedRelative}</Text>;
165
+ if (typeof children === 'function') {
166
+ return children(formattedRelative);
162
167
  }
168
+
169
+ return <Text>{formattedRelative}</Text>;
170
+ }
163
171
  }
@@ -4,43 +4,44 @@
4
4
  * See the accompanying LICENSE file for terms.
5
5
  */
6
6
 
7
- import React, {Component, PropTypes} from 'react';
7
+ import React, {Component} from 'react';
8
+ import PropTypes from 'prop-types';
8
9
  import {intlShape, dateTimeFormatPropTypes} from '../types';
9
10
  import {invariantIntlContext, shouldIntlComponentUpdate} from '../utils';
10
11
 
11
12
  export default class FormattedTime extends Component {
12
- static displayName = 'FormattedTime';
13
-
14
- static contextTypes = {
15
- intl: intlShape,
16
- };
17
-
18
- static propTypes = {
19
- ...dateTimeFormatPropTypes,
20
- value : PropTypes.any.isRequired,
21
- format : PropTypes.string,
22
- children: PropTypes.func,
23
- };
24
-
25
- constructor(props, context) {
26
- super(props, context);
27
- invariantIntlContext(context);
28
- }
13
+ static displayName = 'FormattedTime';
29
14
 
30
- shouldComponentUpdate(...next) {
31
- return shouldIntlComponentUpdate(this, ...next);
32
- }
15
+ static contextTypes = {
16
+ intl: intlShape,
17
+ };
18
+
19
+ static propTypes = {
20
+ ...dateTimeFormatPropTypes,
21
+ value: PropTypes.any.isRequired,
22
+ format: PropTypes.string,
23
+ children: PropTypes.func,
24
+ };
33
25
 
34
- render() {
35
- const {formatTime, textComponent: Text} = this.context.intl;
36
- const {value, children} = this.props;
26
+ constructor(props, context) {
27
+ super(props, context);
28
+ invariantIntlContext(context);
29
+ }
37
30
 
38
- let formattedTime = formatTime(value, this.props);
31
+ shouldComponentUpdate(...next) {
32
+ return shouldIntlComponentUpdate(this, ...next);
33
+ }
39
34
 
40
- if (typeof children === 'function') {
41
- return children(formattedTime);
42
- }
35
+ render() {
36
+ const {formatTime, textComponent: Text} = this.context.intl;
37
+ const {value, children} = this.props;
43
38
 
44
- return <Text>{formattedTime}</Text>;
39
+ let formattedTime = formatTime(value, this.props);
40
+
41
+ if (typeof children === 'function') {
42
+ return children(formattedTime);
45
43
  }
44
+
45
+ return <Text>{formattedTime}</Text>;
46
+ }
46
47
  }
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  export default function defineMessages(messageDescriptors) {
8
- // This simply returns what's passed-in because it's meant to be a hook for
9
- // babel-plugin-react-intl.
10
- return messageDescriptors;
8
+ // This simply returns what's passed-in because it's meant to be a hook for
9
+ // babel-plugin-react-intl.
10
+ return messageDescriptors;
11
11
  }