Browse Source

remove flow. add typescript

KaFai Choi 5 years ago
parent
commit
5ebdeb579e
13 changed files with 319 additions and 725 deletions
  1. 5
    1
      .gitignore
  2. 0
    3
      index.js
  3. 0
    458
      js/WebViewTypes.js
  4. 9
    9
      package.json
  5. 69
    81
      src/WebView.android.tsx
  6. 110
    116
      src/WebView.ios.tsx
  7. 2
    2
      src/WebViewShared.ts
  8. 8
    0
      src/index.ts
  9. 69
    50
      src/types/WebViewTypes.ts
  10. 3
    0
      src/utils.ts
  11. 28
    0
      tsconfig.base.json
  12. 5
    0
      tsconfig.json
  13. 11
    5
      yarn.lock

+ 5
- 1
.gitignore View File

@@ -42,6 +42,9 @@ package-lock.json
42 42
 #
43 43
 bundles/
44 44
 
45
+# Typescript compile
46
+lib/
47
+
45 48
 # VS Code
46 49
 .vscode/*
47 50
 !.vscode/settings.json
@@ -51,4 +54,5 @@ bundles/
51 54
 
52 55
 android/gradle
53 56
 android/gradlew
54
-android/gradlew.bat
57
+android/gradlew.bat
58
+

+ 0
- 3
index.js View File

@@ -1,3 +0,0 @@
1
-import WebView from './js/WebView';
2
-
3
-export { WebView };

+ 0
- 458
js/WebViewTypes.js View File

@@ -1,458 +0,0 @@
1
-/**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @flow
9
- */
10
-
11
-'use strict';
12
-
13
-import type {Node, Element, ComponentType} from 'react';
14
-
15
-import type {SyntheticEvent} from 'CoreEventTypes';
16
-import type {EdgeInsetsProp} from 'EdgeInsetsPropType';
17
-import type {ViewStyleProp} from 'StyleSheet';
18
-import type {ViewProps} from 'ViewPropTypes';
19
-
20
-export type WebViewNativeEvent = $ReadOnly<{|
21
-  url: string,
22
-  loading: boolean,
23
-  title: string,
24
-  canGoBack: boolean,
25
-  canGoForward: boolean,
26
-|}>;
27
-
28
-export type WebViewProgressEvent = $ReadOnly<{|
29
-    ...WebViewNativeEvent,
30
-    progress: number,
31
-|}>
32
-
33
-export type WebViewNavigation = $ReadOnly<{|
34
-  ...WebViewNativeEvent,
35
-  navigationType:
36
-    | 'click'
37
-    | 'formsubmit'
38
-    | 'backforward'
39
-    | 'reload'
40
-    | 'formresubmit'
41
-    | 'other',
42
-|}>;
43
-
44
-export type WebViewMessage = $ReadOnly<{|
45
-  ...WebViewNativeEvent,
46
-  data: string,
47
-|}>;
48
-
49
-export type WebViewError = $ReadOnly<{|
50
-  ...WebViewNativeEvent,
51
-  /**
52
-   * `domain` is only used on iOS
53
-   */
54
-  domain: ?string,
55
-  code: number,
56
-  description: string,
57
-|}>;
58
-
59
-export type WebViewEvent = SyntheticEvent<WebViewNativeEvent>;
60
-
61
-export type WebViewNavigationEvent = SyntheticEvent<WebViewNavigation>;
62
-
63
-export type WebViewMessageEvent = SyntheticEvent<WebViewMessage>;
64
-
65
-export type WebViewErrorEvent = SyntheticEvent<WebViewError>;
66
-
67
-export type DataDetectorTypes =
68
-  | 'phoneNumber'
69
-  | 'link'
70
-  | 'address'
71
-  | 'calendarEvent'
72
-  | 'trackingNumber'
73
-  | 'flightNumber'
74
-  | 'lookupSuggestion'
75
-  | 'none'
76
-  | 'all';
77
-
78
-export type OverScrollModeType = 'always' | 'content' | 'never';
79
-
80
-export type WebViewSourceUri = $ReadOnly<{|
81
-  /**
82
-   * The URI to load in the `WebView`. Can be a local or remote file.
83
-   */
84
-  uri?: ?string,
85
-
86
-  /**
87
-   * The HTTP Method to use. Defaults to GET if not specified.
88
-   * NOTE: On Android, only GET and POST are supported.
89
-   */
90
-  method?: string,
91
-
92
-  /**
93
-   * Additional HTTP headers to send with the request.
94
-   * NOTE: On Android, this can only be used with GET requests.
95
-   */
96
-  headers?: Object,
97
-
98
-  /**
99
-   * The HTTP body to send with the request. This must be a valid
100
-   * UTF-8 string, and will be sent exactly as specified, with no
101
-   * additional encoding (e.g. URL-escaping or base64) applied.
102
-   * NOTE: On Android, this can only be used with POST requests.
103
-   */
104
-  body?: string,
105
-|}>;
106
-
107
-export type WebViewSourceHtml = $ReadOnly<{|
108
-  /**
109
-   * A static HTML page to display in the WebView.
110
-   */
111
-  html?: ?string,
112
-  /**
113
-   * The base URL to be used for any relative links in the HTML.
114
-   */
115
-  baseUrl?: ?string,
116
-|}>;
117
-
118
-export type WebViewSource = WebViewSourceUri | WebViewSourceHtml;
119
-
120
-export type WebViewNativeConfig = $ReadOnly<{|
121
-  /*
122
-   * The native component used to render the WebView.
123
-   */
124
-  component?: ComponentType<WebViewSharedProps>,
125
-  /*
126
-   * Set props directly on the native component WebView. Enables custom props which the
127
-   * original WebView doesn't pass through.
128
-   */
129
-  props?: ?Object,
130
-  /*
131
-   * Set the ViewManager to use for communication with the native side.
132
-   * @platform ios
133
-   */
134
-  viewManager?: ?Object,
135
-|}>;
136
-
137
-export type IOSWebViewProps = $ReadOnly<{|
138
-  /**
139
-   * If true, use WKWebView instead of UIWebView.
140
-   * @platform ios
141
-   */
142
-  useWebKit?: ?boolean,
143
-
144
-  /**
145
-   * Boolean value that determines whether the web view bounces
146
-   * when it reaches the edge of the content. The default value is `true`.
147
-   * @platform ios
148
-   */
149
-  bounces?: ?boolean,
150
-
151
-  /**
152
-   * A floating-point number that determines how quickly the scroll view
153
-   * decelerates after the user lifts their finger. You may also use the
154
-   * string shortcuts `"normal"` and `"fast"` which match the underlying iOS
155
-   * settings for `UIScrollViewDecelerationRateNormal` and
156
-   * `UIScrollViewDecelerationRateFast` respectively:
157
-   *
158
-   *   - normal: 0.998
159
-   *   - fast: 0.99 (the default for iOS web view)
160
-   * @platform ios
161
-   */
162
-  decelerationRate?: ?('fast' | 'normal' | number),
163
-
164
-  /**
165
-   * Boolean value that determines whether scrolling is enabled in the
166
-   * `WebView`. The default value is `true`.
167
-   * @platform ios
168
-   */
169
-  scrollEnabled?: ?boolean,
170
-
171
-  /**
172
-   * If the value of this property is true, the scroll view stops on multiples
173
-   * of the scroll view’s bounds when the user scrolls.
174
-   * The default value is false.
175
-   * @platform ios
176
-   */
177
-  pagingEnabled?: ?boolean,
178
-
179
-  /**
180
-   * The amount by which the web view content is inset from the edges of
181
-   * the scroll view. Defaults to {top: 0, left: 0, bottom: 0, right: 0}.
182
-   * @platform ios
183
-   */
184
-  contentInset?: ?EdgeInsetsProp,
185
-
186
-  /**
187
-   * Determines the types of data converted to clickable URLs in the web view's content.
188
-   * By default only phone numbers are detected.
189
-   *
190
-   * You can provide one type or an array of many types.
191
-   *
192
-   * Possible values for `dataDetectorTypes` are:
193
-   *
194
-   * - `'phoneNumber'`
195
-   * - `'link'`
196
-   * - `'address'`
197
-   * - `'calendarEvent'`
198
-   * - `'none'`
199
-   * - `'all'`
200
-   *
201
-   * With the new WebKit implementation, we have three new values:
202
-   * - `'trackingNumber'`,
203
-   * - `'flightNumber'`,
204
-   * - `'lookupSuggestion'`,
205
-   *
206
-   * @platform ios
207
-   */
208
-  dataDetectorTypes?:
209
-    | ?DataDetectorTypes
210
-    | $ReadOnlyArray<DataDetectorTypes>,
211
-
212
-  /**
213
-   * Function that allows custom handling of any web view requests. Return
214
-   * `true` from the function to continue loading the request and `false`
215
-   * to stop loading.
216
-   * @platform ios
217
-   */
218
-  onShouldStartLoadWithRequest?: (event: WebViewEvent) => mixed,
219
-
220
-  /**
221
-   * Boolean that determines whether HTML5 videos play inline or use the
222
-   * native full-screen controller. The default value is `false`.
223
-   *
224
-   * **NOTE** : In order for video to play inline, not only does this
225
-   * property need to be set to `true`, but the video element in the HTML
226
-   * document must also include the `webkit-playsinline` attribute.
227
-   * @platform ios
228
-   */
229
-  allowsInlineMediaPlayback?: ?boolean,
230
-  /**
231
-   * Hide the accessory view when the keyboard is open. Default is false to be
232
-   * backward compatible.
233
-   */
234
-  hideKeyboardAccessoryView?: ?boolean,
235
-  /**
236
-   * A Boolean value indicating whether horizontal swipe gestures will trigger
237
-   * back-forward list navigations.
238
-   */
239
-  allowsBackForwardNavigationGestures?: ?boolean,
240
-  /**
241
-   * The custom user agent string.
242
-   */
243
-  userAgent?: ?string,
244
-|}>;
245
-
246
-export type AndroidWebViewProps = $ReadOnly<{|
247
-  onNavigationStateChange?: (event: WebViewNavigation) => mixed,
248
-  onContentSizeChange?: (event: WebViewEvent) => mixed,
249
-
250
-  /**
251
-   * https://developer.android.com/reference/android/view/View#OVER_SCROLL_NEVER
252
-   * Sets the overScrollMode. Possible values are:
253
-   *
254
-   * - `'always'` (default)
255
-   * - `'content'`
256
-   * - `'never'`
257
-   *
258
-   * @platform android
259
-   */
260
-  overScrollMode?: ?OverScrollModeType,
261
-
262
-  /**
263
-   * Sets whether Geolocation is enabled. The default is false.
264
-   * @platform android
265
-   */
266
-  geolocationEnabled?: ?boolean,
267
-
268
-  /**
269
-   * Boolean that sets whether JavaScript running in the context of a file
270
-   * scheme URL should be allowed to access content from any origin.
271
-   * Including accessing content from other file scheme URLs
272
-   * @platform android
273
-   */
274
-  allowUniversalAccessFromFileURLs?: ?boolean,
275
-
276
-  /**
277
-   * Sets whether the webview allow access to file system.
278
-   * @platform android
279
-   */
280
-  allowFileAccess?: ?boolean,
281
-
282
-  /**
283
-   * Used on Android only, controls whether form autocomplete data should be saved
284
-   * @platform android
285
-   */
286
-  saveFormDataDisabled?: ?boolean,
287
-
288
-  /*
289
-   * Used on Android only, controls whether the given list of URL prefixes should
290
-   * make {@link com.facebook.react.views.webview.ReactWebViewClient} to launch a
291
-   * default activity intent for those URL instead of loading it within the webview.
292
-   * Use this to list URLs that WebView cannot handle, e.g. a PDF url.
293
-   * @platform android
294
-   */
295
-  urlPrefixesForDefaultIntent?: $ReadOnlyArray<string>,
296
-
297
-  /**
298
-   * Boolean value to enable JavaScript in the `WebView`. Used on Android only
299
-   * as JavaScript is enabled by default on iOS. The default value is `true`.
300
-   * @platform android
301
-   */
302
-  javaScriptEnabled?: ?boolean,
303
-
304
-  /**
305
-   * Boolean value to enable third party cookies in the `WebView`. Used on
306
-   * Android Lollipop and above only as third party cookies are enabled by
307
-   * default on Android Kitkat and below and on iOS. The default value is `true`.
308
-   * @platform android
309
-   */
310
-  thirdPartyCookiesEnabled?: ?boolean,
311
-
312
-  /**
313
-   * Boolean value to control whether DOM Storage is enabled. Used only in
314
-   * Android.
315
-   * @platform android
316
-   */
317
-  domStorageEnabled?: ?boolean,
318
-
319
-  /**
320
-   * Sets the user-agent for the `WebView`.
321
-   * @platform android
322
-   */
323
-  userAgent?: ?string,
324
-
325
-  /**
326
-   * Specifies the mixed content mode. i.e WebView will allow a secure origin to load content from any other origin.
327
-   *
328
-   * Possible values for `mixedContentMode` are:
329
-   *
330
-   * - `'never'` (default) - WebView will not allow a secure origin to load content from an insecure origin.
331
-   * - `'always'` - WebView will allow a secure origin to load content from any other origin, even if that origin is insecure.
332
-   * - `'compatibility'` -  WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content.
333
-   * @platform android
334
-   */
335
-  mixedContentMode?: ?('never' | 'always' | 'compatibility'),
336
-|}>;
337
-
338
-export type WebViewSharedProps =  $ReadOnly<{|
339
-  ...ViewProps,
340
-  ...IOSWebViewProps,
341
-  ...AndroidWebViewProps,
342
-  /**
343
-   * Deprecated. Use `source` instead.
344
-   */
345
-  url?: ?string,
346
-  /**
347
-   * Deprecated. Use `source` instead.
348
-   */
349
-  html?: ?string,
350
-
351
-  /**
352
-   * Loads static html or a uri (with optional headers) in the WebView.
353
-   */
354
-  source?: ?WebViewSource,
355
-
356
-  /**
357
-   * Function that returns a view to show if there's an error.
358
-   */
359
-  renderError: (errorDomain: ?string, errorCode: number, errorDesc: string) => Element<any>, // view to show if there's an error
360
-
361
-  /**
362
-   * Function that returns a loading indicator.
363
-   */
364
-  renderLoading: () => Element<any>,
365
-
366
-  /**
367
-   * Function that is invoked when the `WebView` has finished loading.
368
-   */
369
-  onLoad: (event: WebViewNavigationEvent) => mixed,
370
-
371
-  /**
372
-   * Function that is invoked when the `WebView` load succeeds or fails.
373
-   */
374
-  onLoadEnd: (event: WebViewNavigationEvent | WebViewErrorEvent) => mixed,
375
-
376
-  /**
377
-   * Function that is invoked when the `WebView` starts loading.
378
-   */
379
-  onLoadStart: (event: WebViewNavigationEvent) => mixed,
380
-
381
-  /**
382
-   * Function that is invoked when the `WebView` load fails.
383
-   */
384
-  onError: (event: WebViewErrorEvent) => mixed,
385
-
386
-  /**
387
-   * Controls whether to adjust the content inset for web views that are
388
-   * placed behind a navigation bar, tab bar, or toolbar. The default value
389
-   * is `true`.
390
-   */
391
-  automaticallyAdjustContentInsets?: ?boolean,
392
-
393
-  /**
394
-   * Function that is invoked when the `WebView` loading starts or ends.
395
-   */
396
-  onNavigationStateChange?: (event: WebViewNavigation) => mixed,
397
-
398
-  /**
399
-   * A function that is invoked when the webview calls `window.postMessage`.
400
-   * Setting this property will inject a `postMessage` global into your
401
-   * webview, but will still call pre-existing values of `postMessage`.
402
-   *
403
-   * `window.postMessage` accepts one argument, `data`, which will be
404
-   * available on the event object, `event.nativeEvent.data`. `data`
405
-   * must be a string.
406
-   */
407
-  onMessage?: (event: WebViewMessageEvent) => mixed,
408
-
409
-  /**
410
-   * Function that is invoked when the `WebView` is loading.
411
-   */
412
-  onLoadProgress?: (event: WebViewProgressEvent) => mixed,
413
-
414
-  /**
415
-   * Boolean value that forces the `WebView` to show the loading view
416
-   * on the first load.
417
-   */
418
-  startInLoadingState?: ?boolean,
419
-
420
-  /**
421
-   * Set this to provide JavaScript that will be injected into the web page
422
-   * when the view loads.
423
-   */
424
-  injectedJavaScript?: ?string,
425
-
426
-  /**
427
-   * Boolean that controls whether the web content is scaled to fit
428
-   * the view and enables the user to change the scale. The default value
429
-   * is `true`.
430
-   *
431
-   * On iOS, when `useWebKit=true`, this prop will not work.
432
-   */
433
-  scalesPageToFit?: ?boolean,
434
-
435
-  /**
436
-   * Boolean that determines whether HTML5 audio and video requires the user
437
-   * to tap them before they start playing. The default value is `true`.
438
-   */
439
-  mediaPlaybackRequiresUserAction?: ?boolean,
440
-
441
-  /**
442
-   * List of origin strings to allow being navigated to. The strings allow
443
-   * wildcards and get matched against *just* the origin (not the full URL).
444
-   * If the user taps to navigate to a new page but the new page is not in
445
-   * this whitelist, we will open the URL in Safari.
446
-   * The default whitelisted origins are "http://*" and "https://*".
447
-   */
448
-  originWhitelist?: $ReadOnlyArray<string>,
449
-
450
-  /**
451
-   * Override the native component used to render the WebView. Enables a custom native
452
-   * WebView which uses the same JavaScript as the original WebView.
453
-   */
454
-  nativeConfig?: ?WebViewNativeConfig,
455
-
456
-  style?: ViewStyleProp,
457
-  children: Node,
458
-|}>;

+ 9
- 9
package.json View File

@@ -1,8 +1,8 @@
1 1
 {
2 2
   "name": "react-native-webview",
3 3
   "description": "React Native WebView component for iOS, Android, and Windows 10 (coming soon)",
4
-  "main": "index.js",
5
-  "typings": "typings/index.d.ts",
4
+  "main": "lib/index.js",
5
+  "types": "lib/index.d.ts",
6 6
   "author": "Jamon Holmgren <jamon@infinite.red>",
7 7
   "contributors": [
8 8
     "Thibault Malbranche <malbranche.thibault@gmail.com>"
@@ -11,11 +11,10 @@
11 11
   "version": "2.12.1",
12 12
   "homepage": "https://github.com/react-native-community/react-native-webview#readme",
13 13
   "scripts": {
14
-    "test:ios:flow": "flow check",
15
-    "test:android:flow": "flow check --flowconfig-name .flowconfig.android",
14
+    "compile": "tsc",
16 15
     "ci:publish": "yarn semantic-release",
17
-    "ci:test": "yarn ci:test:flow",
18
-    "ci:test:flow": "yarn test:ios:flow && yarn test:android:flow",
16
+    "ci:test": "yarn ci:test:compile",
17
+    "ci:test:compile": "yarn compile",
19 18
     "semantic-release": "semantic-release"
20 19
   },
21 20
   "peerDependencies": {
@@ -24,15 +23,16 @@
24 23
   },
25 24
   "dependencies": {
26 25
     "escape-string-regexp": "^1.0.5",
27
-    "fbjs": "^0.8.17"
26
+    "invariant": "^2.2.4"
28 27
   },
29 28
   "devDependencies": {
30 29
     "@semantic-release/git": "7.0.5",
30
+    "@types/invariant": "^2.2.29",
31 31
     "@types/react": "^16.4.18",
32 32
     "@types/react-native": "^0.57.6",
33
-    "flow-bin": "^0.80.0",
34 33
     "react-native": "^0.57",
35
-    "semantic-release": "15.10.3"
34
+    "semantic-release": "15.10.3",
35
+    "typescript": "^3.1.6"
36 36
   },
37 37
   "repository": {
38 38
     "type": "git",

js/WebView.android.js → src/WebView.android.tsx View File

@@ -1,51 +1,37 @@
1
-/**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @flow
9
- */
10
-
11
-'use strict';
1
+import React from "react";
12 2
 
13
-import React from 'react';
14
-
15
-import ReactNative from 'react-native';
3
+import ReactNative from "react-native";
16 4
 import {
17 5
   ActivityIndicator,
18 6
   StyleSheet,
19 7
   UIManager,
20 8
   View,
21
-  Image,
22 9
   requireNativeComponent,
23
-  NativeModules
24
-} from 'react-native';
10
+  NativeModules,
11
+  Image,
12
+  NativeSyntheticEvent
13
+} from "react-native";
25 14
 
26
-import invariant from 'fbjs/lib/invariant';
27
-import keyMirror from 'fbjs/lib/keyMirror';
15
+import invariant from "invariant";
28 16
 
29
-import WebViewShared from './WebViewShared';
30
-import type {
31
-  WebViewEvent,
17
+import WebViewShared from "./WebViewShared";
18
+import {
19
+  WebViewSourceUri,
32 20
   WebViewError,
33 21
   WebViewErrorEvent,
34 22
   WebViewMessageEvent,
35
-  WebViewNavigation,
36 23
   WebViewNavigationEvent,
37 24
   WebViewSharedProps,
38 25
   WebViewSource,
39
-  WebViewProgressEvent,
40
-} from './WebViewTypes';
41
-
42
-const resolveAssetSource = Image.resolveAssetSource;
43
-
44
-const WebViewState = keyMirror({
45
-  IDLE: null,
46
-  LOADING: null,
47
-  ERROR: null,
48
-});
26
+  WebViewProgressEvent
27
+} from "./types/WebViewTypes";
28
+import { isWebViewUriSource } from "./utils";
29
+
30
+enum WebViewState {
31
+  IDLE = "IDLE",
32
+  LOADING = "LOADING",
33
+  ERROR = "ERROR"
34
+}
49 35
 
50 36
 const defaultRenderLoading = () => (
51 37
   <View style={styles.loadingView}>
@@ -53,36 +39,38 @@ const defaultRenderLoading = () => (
53 39
   </View>
54 40
 );
55 41
 
56
-type State = {|
57
-  viewState: WebViewState,
58
-  lastErrorEvent: ?WebViewError,
59
-|};
42
+type State = {
43
+  viewState: WebViewState;
44
+  lastErrorEvent: WebViewError;
45
+};
60 46
 
61 47
 /**
62 48
  * Renders a native WebView.
63 49
  */
64
-class WebView extends React.Component<WebViewSharedProps, State> {
50
+export default class WebView extends React.Component<WebViewSharedProps, State> {
65 51
   static defaultProps = {
66
-    overScrollMode: 'always',
52
+    overScrollMode: "always",
67 53
     javaScriptEnabled: true,
68 54
     thirdPartyCookiesEnabled: true,
69 55
     scalesPageToFit: true,
70 56
     allowFileAccess: false,
71 57
     saveFormDataDisabled: false,
72
-    originWhitelist: WebViewShared.defaultOriginWhitelist,
58
+    originWhitelist: WebViewShared.defaultOriginWhitelist
73 59
   };
74 60
 
75 61
   static isFileUploadSupported = async () => {
76 62
     // native implementation should return "true" only for Android 5+
77 63
     return NativeModules.RNCWebView.isFileUploadSupported();
78
-  }
64
+  };
79 65
 
80
-  state = {
81
-    viewState: this.props.startInLoadingState ? WebViewState.LOADING : WebViewState.IDLE,
82
-    lastErrorEvent: null,
66
+  state: State = {
67
+    viewState: this.props.startInLoadingState
68
+      ? WebViewState.LOADING
69
+      : WebViewState.IDLE,
70
+    lastErrorEvent: null
83 71
   };
84 72
 
85
-  webViewRef = React.createRef();
73
+  webViewRef = React.createRef<React.ComponentClass>();
86 74
 
87 75
   render() {
88 76
     let otherView = null;
@@ -91,17 +79,17 @@ class WebView extends React.Component<WebViewSharedProps, State> {
91 79
       otherView = (this.props.renderLoading || defaultRenderLoading)();
92 80
     } else if (this.state.viewState === WebViewState.ERROR) {
93 81
       const errorEvent = this.state.lastErrorEvent;
94
-      invariant(errorEvent != null, 'lastErrorEvent expected to be non-null');
82
+      invariant(errorEvent != null, "lastErrorEvent expected to be non-null");
95 83
       otherView =
96 84
         this.props.renderError &&
97 85
         this.props.renderError(
98 86
           errorEvent.domain,
99 87
           errorEvent.code,
100
-          errorEvent.description,
88
+          errorEvent.description
101 89
         );
102 90
     } else if (this.state.viewState !== WebViewState.IDLE) {
103 91
       console.error(
104
-        'RNCWebView invalid state encountered: ' + this.state.viewState,
92
+        "RNCWebView invalid state encountered: " + this.state.viewState
105 93
       );
106 94
     }
107 95
 
@@ -121,18 +109,20 @@ class WebView extends React.Component<WebViewSharedProps, State> {
121 109
       source = { uri: this.props.url };
122 110
     }
123 111
 
124
-    if (source.method === 'POST' && source.headers) {
125
-      console.warn(
126
-        'WebView: `source.headers` is not supported when using POST.',
127
-      );
128
-    } else if (source.method === 'GET' && source.body) {
129
-      console.warn('WebView: `source.body` is not supported when using GET.');
112
+    if (isWebViewUriSource(source)) {
113
+      if (source.method === "POST" && source.headers) {
114
+        console.warn(
115
+          "WebView: `source.headers` is not supported when using POST."
116
+        );
117
+      } else if (source.method === "GET" && source.body) {
118
+        console.warn("WebView: `source.body` is not supported when using GET.");
119
+      }
130 120
     }
131 121
 
132 122
     const nativeConfig = this.props.nativeConfig || {};
133 123
 
134 124
     const originWhitelist = (this.props.originWhitelist || []).map(
135
-      WebViewShared.originWhitelistToRegex,
125
+      WebViewShared.originWhitelistToRegex
136 126
     );
137 127
 
138 128
     let NativeWebView = nativeConfig.component || RNCWebView;
@@ -142,7 +132,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
142 132
         ref={this.webViewRef}
143 133
         key="webViewKey"
144 134
         style={webViewStyles}
145
-        source={resolveAssetSource(source)}
135
+        source={Image.resolveAssetSource(source as WebViewSourceUri)} // typing issue of not compatible of WebViewSourceHtml in react native.
146 136
         scalesPageToFit={this.props.scalesPageToFit}
147 137
         allowFileAccess={this.props.allowFileAccess}
148 138
         injectedJavaScript={this.props.injectedJavaScript}
@@ -150,7 +140,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
150 140
         javaScriptEnabled={this.props.javaScriptEnabled}
151 141
         thirdPartyCookiesEnabled={this.props.thirdPartyCookiesEnabled}
152 142
         domStorageEnabled={this.props.domStorageEnabled}
153
-        messagingEnabled={typeof this.props.onMessage === 'function'}
143
+        messagingEnabled={typeof this.props.onMessage === "function"}
154 144
         onMessage={this.onMessage}
155 145
         overScrollMode={this.props.overScrollMode}
156 146
         contentInset={this.props.contentInset}
@@ -190,7 +180,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
190 180
     UIManager.dispatchViewManagerCommand(
191 181
       this.getWebViewHandle(),
192 182
       UIManager.RNCWebView.Commands.goForward,
193
-      null,
183
+      null
194 184
     );
195 185
   };
196 186
 
@@ -198,18 +188,18 @@ class WebView extends React.Component<WebViewSharedProps, State> {
198 188
     UIManager.dispatchViewManagerCommand(
199 189
       this.getWebViewHandle(),
200 190
       UIManager.RNCWebView.Commands.goBack,
201
-      null,
191
+      null
202 192
     );
203 193
   };
204 194
 
205 195
   reload = () => {
206 196
     this.setState({
207
-      viewState: WebViewState.LOADING,
197
+      viewState: WebViewState.LOADING
208 198
     });
209 199
     UIManager.dispatchViewManagerCommand(
210 200
       this.getWebViewHandle(),
211 201
       UIManager.RNCWebView.Commands.reload,
212
-      null,
202
+      null
213 203
     );
214 204
   };
215 205
 
@@ -217,7 +207,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
217 207
     UIManager.dispatchViewManagerCommand(
218 208
       this.getWebViewHandle(),
219 209
       UIManager.RNCWebView.Commands.stopLoading,
220
-      null,
210
+      null
221 211
     );
222 212
   };
223 213
 
@@ -225,7 +215,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
225 215
     UIManager.dispatchViewManagerCommand(
226 216
       this.getWebViewHandle(),
227 217
       UIManager.RNCWebView.Commands.postMessage,
228
-      [String(data)],
218
+      [String(data)]
229 219
     );
230 220
   };
231 221
 
@@ -239,7 +229,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
239 229
     UIManager.dispatchViewManagerCommand(
240 230
       this.getWebViewHandle(),
241 231
       UIManager.RNCWebView.Commands.injectJavaScript,
242
-      [data],
232
+      [data]
243 233
     );
244 234
   };
245 235
 
@@ -268,11 +258,11 @@ class WebView extends React.Component<WebViewSharedProps, State> {
268 258
     const { onError, onLoadEnd } = this.props;
269 259
     onError && onError(event);
270 260
     onLoadEnd && onLoadEnd(event);
271
-    console.warn('Encountered an error loading page', event.nativeEvent);
261
+    console.warn("Encountered an error loading page", event.nativeEvent);
272 262
 
273 263
     this.setState({
274 264
       lastErrorEvent: event.nativeEvent,
275
-      viewState: WebViewState.ERROR,
265
+      viewState: WebViewState.ERROR
276 266
     });
277 267
   };
278 268
 
@@ -281,7 +271,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
281 271
     onLoad && onLoad(event);
282 272
     onLoadEnd && onLoadEnd(event);
283 273
     this.setState({
284
-      viewState: WebViewState.IDLE,
274
+      viewState: WebViewState.IDLE
285 275
     });
286 276
     this.updateNavigationState(event);
287 277
   };
@@ -290,31 +280,29 @@ class WebView extends React.Component<WebViewSharedProps, State> {
290 280
     const { onMessage } = this.props;
291 281
     onMessage && onMessage(event);
292 282
   };
293
-  
294
-  onLoadingProgress = (event: WebViewProgressEvent) => {
295
-    const { onLoadProgress} = this.props;
283
+
284
+  onLoadingProgress = (event: NativeSyntheticEvent<WebViewProgressEvent>) => {
285
+    const { onLoadProgress } = this.props;
296 286
     onLoadProgress && onLoadProgress(event);
297
-  }
287
+  };
298 288
 }
299 289
 
300
-const RNCWebView = requireNativeComponent('RNCWebView');
290
+const RNCWebView = requireNativeComponent("RNCWebView");
301 291
 
302 292
 const styles = StyleSheet.create({
303 293
   container: {
304
-    flex: 1,
294
+    flex: 1
305 295
   },
306 296
   hidden: {
307 297
     height: 0,
308
-    flex: 0, // disable 'flex:1' when hiding a View
298
+    flex: 0 // disable 'flex:1' when hiding a View
309 299
   },
310 300
   loadingView: {
311 301
     flex: 1,
312
-    justifyContent: 'center',
313
-    alignItems: 'center',
302
+    justifyContent: "center",
303
+    alignItems: "center"
314 304
   },
315 305
   loadingProgressBar: {
316
-    height: 20,
317
-  },
318
-});
319
-
320
-module.exports = WebView;
306
+    height: 20
307
+  }
308
+});

js/WebView.ios.js → src/WebView.ios.tsx View File

@@ -1,14 +1,4 @@
1
-/**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @flow
9
- */
10
-
11
-import React from 'react';
1
+import React from "react";
12 2
 import {
13 3
   ActivityIndicator,
14 4
   Linking,
@@ -20,30 +10,31 @@ import {
20 10
   NativeModules,
21 11
   Image,
22 12
   findNodeHandle,
23
-} from 'react-native';
13
+  NativeSyntheticEvent
14
+} from "react-native";
24 15
 
25
-import invariant from 'fbjs/lib/invariant';
26
-import keyMirror from 'fbjs/lib/keyMirror';
16
+import invariant from "invariant";
27 17
 
28
-import WebViewShared from './WebViewShared';
29
-import type {
30
-  WebViewEvent,
18
+import WebViewShared from "./WebViewShared";
19
+import {
20
+  WebViewSourceUri,
31 21
   WebViewError,
22
+  WebViewIOSLoadRequestEvent,
32 23
   WebViewErrorEvent,
33 24
   WebViewMessageEvent,
34 25
   WebViewNavigationEvent,
35 26
   WebViewSharedProps,
36 27
   WebViewSource,
37
-  WebViewProgressEvent,
38
-} from './WebViewTypes';
28
+  WebViewProgressEvent
29
+} from "./types/WebViewTypes";
39 30
 
40
-const resolveAssetSource = Image.resolveAssetSource;
31
+type DecelerationRate = number | "normal" | "fast";
41 32
 
42 33
 // Imported from https://github.com/facebook/react-native/blob/master/Libraries/Components/ScrollView/processDecelerationRate.js
43
-function processDecelerationRate(decelerationRate) {
44
-  if (decelerationRate === 'normal') {
34
+function processDecelerationRate(decelerationRate: DecelerationRate) {
35
+  if (decelerationRate === "normal") {
45 36
     decelerationRate = 0.998;
46
-  } else if (decelerationRate === 'fast') {
37
+  } else if (decelerationRate === "fast") {
47 38
     decelerationRate = 0.99;
48 39
   }
49 40
   return decelerationRate;
@@ -52,53 +43,45 @@ function processDecelerationRate(decelerationRate) {
52 43
 const RNCUIWebViewManager = NativeModules.RNCUIWebViewManager;
53 44
 const RNCWKWebViewManager = NativeModules.RNCWKWebViewManager;
54 45
 
55
-const BGWASH = 'rgba(255,255,255,0.8)';
46
+const BGWASH = "rgba(255,255,255,0.8)";
56 47
 
57
-const WebViewState = keyMirror({
58
-  IDLE: null,
59
-  LOADING: null,
60
-  ERROR: null,
61
-});
48
+enum WebViewState {
49
+  IDLE = "IDLE",
50
+  LOADING = "LOADING",
51
+  ERROR = "ERROR"
52
+}
62 53
 
63
-const NavigationType = keyMirror({
64
-  click: true,
65
-  formsubmit: true,
66
-  backforward: true,
67
-  reload: true,
68
-  formresubmit: true,
69
-  other: true,
70
-});
54
+enum NavigationType {
55
+  click = "click",
56
+  formsubmit = "formsubmit",
57
+  backforward = "backforward",
58
+  reload = "reload",
59
+  formresubmit = "formresubmit",
60
+  other = "other"
61
+}
62
+
63
+const JSNavigationScheme = "react-js-navigation";
71 64
 
72
-const JSNavigationScheme = 'react-js-navigation';
73
-
74
-type State = {|
75
-  viewState: WebViewState,
76
-  lastErrorEvent: ?WebViewError,
77
-|};
78
-
79
-const DataDetectorTypes = [
80
-  'phoneNumber',
81
-  'link',
82
-  'address',
83
-  'calendarEvent',
84
-  'trackingNumber',
85
-  'flightNumber',
86
-  'lookupSuggestion',
87
-  'none',
88
-  'all',
89
-];
65
+type State = {
66
+  viewState: WebViewState;
67
+  lastErrorEvent: WebViewError;
68
+};
90 69
 
91 70
 const defaultRenderLoading = () => (
92 71
   <View style={styles.loadingView}>
93 72
     <ActivityIndicator />
94 73
   </View>
95 74
 );
96
-const defaultRenderError = (errorDomain, errorCode, errorDesc) => (
75
+const defaultRenderError = (
76
+  errorDomain: string,
77
+  errorCode: number,
78
+  errorDesc: string
79
+) => (
97 80
   <View style={styles.errorContainer}>
98 81
     <Text style={styles.errorTextTitle}>Error loading page</Text>
99
-    <Text style={styles.errorText}>{'Domain: ' + errorDomain}</Text>
100
-    <Text style={styles.errorText}>{'Error Code: ' + errorCode}</Text>
101
-    <Text style={styles.errorText}>{'Description: ' + errorDesc}</Text>
82
+    <Text style={styles.errorText}>{"Domain: " + errorDomain}</Text>
83
+    <Text style={styles.errorText}>{"Error Code: " + errorCode}</Text>
84
+    <Text style={styles.errorText}>{"Description: " + errorDesc}</Text>
102 85
   </View>
103 86
 );
104 87
 
@@ -124,28 +107,31 @@ const defaultRenderError = (errorDomain, errorCode, errorDesc) => (
124 107
  * You can use this component to navigate back and forth in the web view's
125 108
  * history and configure various properties for the web content.
126 109
  */
127
-class WebView extends React.Component<WebViewSharedProps, State> {
110
+export default class WebView extends React.Component<
111
+  WebViewSharedProps,
112
+  State
113
+> {
128 114
   static JSNavigationScheme = JSNavigationScheme;
129 115
   static NavigationType = NavigationType;
130 116
 
131 117
   static defaultProps = {
132 118
     useWebKit: true,
133
-    originWhitelist: WebViewShared.defaultOriginWhitelist,
119
+    originWhitelist: WebViewShared.defaultOriginWhitelist
134 120
   };
135 121
 
136 122
   static isFileUploadSupported = async () => {
137 123
     // no native implementation for iOS, depends only on permissions
138 124
     return true;
139
-  }
125
+  };
140 126
 
141
-  state = {
127
+  state: State = {
142 128
     viewState: this.props.startInLoadingState
143 129
       ? WebViewState.LOADING
144 130
       : WebViewState.IDLE,
145
-    lastErrorEvent: null,
131
+    lastErrorEvent: null
146 132
   };
147 133
 
148
-  webViewRef = React.createRef();
134
+  webViewRef = React.createRef<React.ComponentClass>();
149 135
 
150 136
   UNSAFE_componentWillMount() {
151 137
     if (
@@ -153,7 +139,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
153 139
       this.props.scalesPageToFit !== undefined
154 140
     ) {
155 141
       console.warn(
156
-        'The scalesPageToFit property is not supported when useWebKit = true',
142
+        "The scalesPageToFit property is not supported when useWebKit = true"
157 143
       );
158 144
     }
159 145
     if (
@@ -161,7 +147,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
161 147
       this.props.allowsBackForwardNavigationGestures
162 148
     ) {
163 149
       console.warn(
164
-        'The allowsBackForwardNavigationGestures property is not supported when useWebKit = false',
150
+        "The allowsBackForwardNavigationGestures property is not supported when useWebKit = false"
165 151
       );
166 152
     }
167 153
   }
@@ -181,15 +167,15 @@ class WebView extends React.Component<WebViewSharedProps, State> {
181 167
       otherView = (this.props.renderLoading || defaultRenderLoading)();
182 168
     } else if (this.state.viewState === WebViewState.ERROR) {
183 169
       const errorEvent = this.state.lastErrorEvent;
184
-      invariant(errorEvent != null, 'lastErrorEvent expected to be non-null');
170
+      invariant(errorEvent != null, "lastErrorEvent expected to be non-null");
185 171
       otherView = (this.props.renderError || defaultRenderError)(
186 172
         errorEvent.domain,
187 173
         errorEvent.code,
188
-        errorEvent.description,
174
+        errorEvent.description
189 175
       );
190 176
     } else if (this.state.viewState !== WebViewState.IDLE) {
191 177
       console.error(
192
-        'RNCWebView invalid state encountered: ' + this.state.viewState,
178
+        "RNCWebView invalid state encountered: " + this.state.viewState
193 179
       );
194 180
     }
195 181
 
@@ -213,15 +199,17 @@ class WebView extends React.Component<WebViewSharedProps, State> {
213 199
     }
214 200
 
215 201
     const compiledWhitelist = [
216
-      'about:blank',
217
-      ...(this.props.originWhitelist || []),
202
+      "about:blank",
203
+      ...(this.props.originWhitelist || [])
218 204
     ].map(WebViewShared.originWhitelistToRegex);
219
-    const onShouldStartLoadWithRequest = event => {
205
+    const onShouldStartLoadWithRequest = (
206
+      event: NativeSyntheticEvent<WebViewIOSLoadRequestEvent>
207
+    ) => {
220 208
       let shouldStart = true;
221 209
       const { url } = event.nativeEvent;
222 210
       const origin = WebViewShared.extractOrigin(url);
223 211
       const passesWhitelist = compiledWhitelist.some(x =>
224
-        new RegExp(x).test(origin),
212
+        new RegExp(x).test(origin)
225 213
       );
226 214
       shouldStart = shouldStart && passesWhitelist;
227 215
       if (!passesWhitelist) {
@@ -232,15 +220,15 @@ class WebView extends React.Component<WebViewSharedProps, State> {
232 220
           shouldStart &&
233 221
           this.props.onShouldStartLoadWithRequest(event.nativeEvent);
234 222
       }
235
-      invariant(viewManager != null, 'viewManager expected to be non-null');
223
+      invariant(viewManager != null, "viewManager expected to be non-null");
236 224
       viewManager.startLoadWithResult(
237 225
         !!shouldStart,
238
-        event.nativeEvent.lockIdentifier,
226
+        event.nativeEvent.lockIdentifier
239 227
       );
240 228
     };
241 229
 
242 230
     const decelerationRate = processDecelerationRate(
243
-      this.props.decelerationRate,
231
+      this.props.decelerationRate
244 232
     );
245 233
 
246 234
     let source: WebViewSource = this.props.source || {};
@@ -250,7 +238,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
250 238
       source = { uri: this.props.url };
251 239
     }
252 240
 
253
-    const messagingEnabled = typeof this.props.onMessage === 'function';
241
+    const messagingEnabled = typeof this.props.onMessage === "function";
254 242
 
255 243
     let NativeWebView = nativeConfig.component;
256 244
 
@@ -265,7 +253,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
265 253
         ref={this.webViewRef}
266 254
         key="webViewKey"
267 255
         style={webViewStyles}
268
-        source={resolveAssetSource(source)}
256
+        source={Image.resolveAssetSource(source as WebViewSourceUri)} // typing issue of not compatible of WebViewSourceHtml in react native.
269 257
         injectedJavaScript={this.props.injectedJavaScript}
270 258
         bounces={this.props.bounces}
271 259
         scrollEnabled={this.props.scrollEnabled}
@@ -276,7 +264,9 @@ class WebView extends React.Component<WebViewSharedProps, State> {
276 264
           this.props.automaticallyAdjustContentInsets
277 265
         }
278 266
         hideKeyboardAccessoryView={this.props.hideKeyboardAccessoryView}
279
-        allowsBackForwardNavigationGestures={this.props.allowsBackForwardNavigationGestures}
267
+        allowsBackForwardNavigationGestures={
268
+          this.props.allowsBackForwardNavigationGestures
269
+        }
280 270
         userAgent={this.props.userAgent}
281 271
         onLoadingStart={this._onLoadingStart}
282 272
         onLoadingFinish={this._onLoadingFinish}
@@ -318,7 +308,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
318 308
     UIManager.dispatchViewManagerCommand(
319 309
       this.getWebViewHandle(),
320 310
       this._getCommands().goForward,
321
-      null,
311
+      null
322 312
     );
323 313
   };
324 314
 
@@ -329,7 +319,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
329 319
     UIManager.dispatchViewManagerCommand(
330 320
       this.getWebViewHandle(),
331 321
       this._getCommands().goBack,
332
-      null,
322
+      null
333 323
     );
334 324
   };
335 325
 
@@ -341,7 +331,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
341 331
     UIManager.dispatchViewManagerCommand(
342 332
       this.getWebViewHandle(),
343 333
       this._getCommands().reload,
344
-      null,
334
+      null
345 335
     );
346 336
   };
347 337
 
@@ -352,7 +342,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
352 342
     UIManager.dispatchViewManagerCommand(
353 343
       this.getWebViewHandle(),
354 344
       this._getCommands().stopLoading,
355
-      null,
345
+      null
356 346
     );
357 347
   };
358 348
 
@@ -370,7 +360,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
370 360
     UIManager.dispatchViewManagerCommand(
371 361
       this.getWebViewHandle(),
372 362
       this._getCommands().postMessage,
373
-      [String(data)],
363
+      [String(data)]
374 364
     );
375 365
   };
376 366
 
@@ -384,7 +374,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
384 374
     UIManager.dispatchViewManagerCommand(
385 375
       this.getWebViewHandle(),
386 376
       this._getCommands().injectJavaScript,
387
-      [data],
377
+      [data]
388 378
     );
389 379
   };
390 380
 
@@ -416,11 +406,11 @@ class WebView extends React.Component<WebViewSharedProps, State> {
416 406
     const { onError, onLoadEnd } = this.props;
417 407
     onError && onError(event);
418 408
     onLoadEnd && onLoadEnd(event);
419
-    console.warn('Encountered an error loading page', event.nativeEvent);
409
+    console.warn("Encountered an error loading page", event.nativeEvent);
420 410
 
421 411
     this.setState({
422 412
       lastErrorEvent: event.nativeEvent,
423
-      viewState: WebViewState.ERROR,
413
+      viewState: WebViewState.ERROR
424 414
     });
425 415
   };
426 416
 
@@ -429,7 +419,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
429 419
     onLoad && onLoad(event);
430 420
     onLoadEnd && onLoadEnd(event);
431 421
     this.setState({
432
-      viewState: WebViewState.IDLE,
422
+      viewState: WebViewState.IDLE
433 423
     });
434 424
     this._updateNavigationState(event);
435 425
   };
@@ -439,73 +429,77 @@ class WebView extends React.Component<WebViewSharedProps, State> {
439 429
     onMessage && onMessage(event);
440 430
   };
441 431
 
442
-  _onLoadingProgress = (event: WebViewProgressEvent) => {
443
-    const {onLoadProgress} = this.props;
432
+  _onLoadingProgress = (event: NativeSyntheticEvent<WebViewProgressEvent>) => {
433
+    const { onLoadProgress } = this.props;
444 434
     onLoadProgress && onLoadProgress(event);
445
-  }
435
+  };
446 436
 
447 437
   componentDidUpdate(prevProps: WebViewSharedProps) {
448 438
     if (!(prevProps.useWebKit && this.props.useWebKit)) {
449 439
       return;
450 440
     }
451 441
 
452
-    this._showRedboxOnPropChanges(prevProps, 'allowsInlineMediaPlayback');
453
-    this._showRedboxOnPropChanges(prevProps, 'mediaPlaybackRequiresUserAction');
454
-    this._showRedboxOnPropChanges(prevProps, 'dataDetectorTypes');
442
+    this._showRedboxOnPropChanges(prevProps, "allowsInlineMediaPlayback");
443
+    this._showRedboxOnPropChanges(prevProps, "mediaPlaybackRequiresUserAction");
444
+    this._showRedboxOnPropChanges(prevProps, "dataDetectorTypes");
455 445
 
456 446
     if (this.props.scalesPageToFit !== undefined) {
457 447
       console.warn(
458
-        'The scalesPageToFit property is not supported when useWebKit = true',
448
+        "The scalesPageToFit property is not supported when useWebKit = true"
459 449
       );
460 450
     }
461 451
   }
462 452
 
463
-  _showRedboxOnPropChanges(prevProps, propName: string) {
453
+  _showRedboxOnPropChanges(
454
+    prevProps: WebViewSharedProps,
455
+    propName:
456
+      | "allowsInlineMediaPlayback"
457
+      | "mediaPlaybackRequiresUserAction"
458
+      | "dataDetectorTypes"
459
+  ) {
464 460
     if (this.props[propName] !== prevProps[propName]) {
465 461
       console.error(
466
-        `Changes to property ${propName} do nothing after the initial render.`,
462
+        `Changes to property ${propName} do nothing after the initial render.`
467 463
       );
468 464
     }
469 465
   }
470 466
 }
471 467
 
472
-const RNCUIWebView = requireNativeComponent('RNCUIWebView');
473
-const RNCWKWebView = requireNativeComponent('RNCWKWebView');
468
+const RNCUIWebView = requireNativeComponent("RNCUIWebView");
469
+const RNCWKWebView = requireNativeComponent("RNCWKWebView");
474 470
 
475 471
 const styles = StyleSheet.create({
476 472
   container: {
477
-    flex: 1,
473
+    flex: 1
478 474
   },
479 475
   errorContainer: {
480 476
     flex: 1,
481
-    justifyContent: 'center',
482
-    alignItems: 'center',
483
-    backgroundColor: BGWASH,
477
+    justifyContent: "center",
478
+    alignItems: "center",
479
+    backgroundColor: BGWASH
484 480
   },
485 481
   errorText: {
486 482
     fontSize: 14,
487
-    textAlign: 'center',
488
-    marginBottom: 2,
483
+    textAlign: "center",
484
+    marginBottom: 2
489 485
   },
490 486
   errorTextTitle: {
491 487
     fontSize: 15,
492
-    fontWeight: '500',
493
-    marginBottom: 10,
488
+    fontWeight: "500",
489
+    marginBottom: 10
494 490
   },
495 491
   hidden: {
496 492
     height: 0,
497
-    flex: 0, // disable 'flex:1' when hiding a View
493
+    flex: 0 // disable 'flex:1' when hiding a View
498 494
   },
499 495
   loadingView: {
500 496
     backgroundColor: BGWASH,
501 497
     flex: 1,
502
-    justifyContent: 'center',
503
-    alignItems: 'center',
504
-    height: 100,
498
+    justifyContent: "center",
499
+    alignItems: "center",
500
+    height: 100
505 501
   },
506 502
   webView: {
507
-    backgroundColor: '#ffffff',
508
-  },
503
+    backgroundColor: "#ffffff"
504
+  }
509 505
 });
510
-
511
-module.exports = WebView;

js/WebViewShared.js → src/WebViewShared.ts View File

@@ -5,7 +5,7 @@
5 5
  * LICENSE file in the root directory of this source tree.
6 6
  *
7 7
  * @format
8
- * @flow
8
+ * @typescript
9 9
  */
10 10
 
11 11
 'use strict';
@@ -23,4 +23,4 @@ const WebViewShared = {
23 23
   },
24 24
 };
25 25
 
26
-module.exports = WebViewShared;
26
+export default WebViewShared

+ 8
- 0
src/index.ts View File

@@ -0,0 +1,8 @@
1
+import IOSWebView from "./WebView.ios"; 
2
+import AndroidWebView from "./WebView.android"; 
3
+
4
+declare var _test1: typeof IOSWebView;
5
+declare var _test2: typeof AndroidWebView;
6
+
7
+/// export to get the shape of the module
8
+export default { WebView: IOSWebView}

typings/index.d.ts → src/types/WebViewTypes.ts View File

@@ -1,5 +1,20 @@
1
-import { ComponentType, ReactElement, ReactNode, Component } from 'react';
2
-import { Insets, NativeSyntheticEvent, StyleProp, ViewProps, ViewStyle } from 'react-native';
1
+import { ComponentType, ReactElement, ReactNode } from "react";
2
+import {
3
+  Insets,
4
+  NativeSyntheticEvent,
5
+  StyleProp,
6
+  ViewProps,
7
+  ViewStyle
8
+} from "react-native";
9
+
10
+declare module "react-native" {
11
+  interface UIManagerStatic {
12
+    dispatchViewManagerCommand(node: any, callback: any, x: any): void;
13
+    RNCUIWebView: any;
14
+    RNCWKWebView: any;
15
+    RNCWebView: any;
16
+  }
17
+}
3 18
 
4 19
 export interface WebViewNativeEvent {
5 20
   readonly url: string;
@@ -12,7 +27,13 @@ export interface WebViewNativeEvent {
12 27
 export interface WebViewIOSLoadRequestEvent extends WebViewNativeEvent {
13 28
   target: number;
14 29
   lockIdentifier: number;
15
-  navigationType: "click" | "formsubmit" | "backforward" | "reload" | "formresubmit" | "other";
30
+  navigationType:
31
+    | "click"
32
+    | "formsubmit"
33
+    | "backforward"
34
+    | "reload"
35
+    | "formresubmit"
36
+    | "other";
16 37
 }
17 38
 
18 39
 export interface WebViewProgressEvent extends WebViewNativeEvent {
@@ -21,12 +42,12 @@ export interface WebViewProgressEvent extends WebViewNativeEvent {
21 42
 
22 43
 export interface WebViewNavigation extends WebViewNativeEvent {
23 44
   readonly navigationType:
24
-    | 'click'
25
-    | 'formsubmit'
26
-    | 'backforward'
27
-    | 'reload'
28
-    | 'formresubmit'
29
-    | 'other';
45
+    | "click"
46
+    | "formsubmit"
47
+    | "backforward"
48
+    | "reload"
49
+    | "formresubmit"
50
+    | "other";
30 51
 }
31 52
 
32 53
 export interface WebViewMessage extends WebViewNativeEvent {
@@ -48,17 +69,17 @@ export type WebViewMessageEvent = NativeSyntheticEvent<WebViewMessage>;
48 69
 export type WebViewErrorEvent = NativeSyntheticEvent<WebViewError>;
49 70
 
50 71
 export type DataDetectorTypes =
51
-  | 'phoneNumber'
52
-  | 'link'
53
-  | 'address'
54
-  | 'calendarEvent'
55
-  | 'trackingNumber'
56
-  | 'flightNumber'
57
-  | 'lookupSuggestion'
58
-  | 'none'
59
-  | 'all';
60
-
61
-export type OverScrollModeType = 'always' | 'content' | 'never';
72
+  | "phoneNumber"
73
+  | "link"
74
+  | "address"
75
+  | "calendarEvent"
76
+  | "trackingNumber"
77
+  | "flightNumber"
78
+  | "lookupSuggestion"
79
+  | "none"
80
+  | "all";
81
+
82
+export type OverScrollModeType = "always" | "content" | "never";
62 83
 
63 84
 export interface WebViewSourceUri {
64 85
   /**
@@ -76,7 +97,7 @@ export interface WebViewSourceUri {
76 97
    * Additional HTTP headers to send with the request.
77 98
    * NOTE: On Android, this can only be used with GET requests.
78 99
    */
79
-  headers?: {[key: string]: string};
100
+  headers?: { [key: string]: string };
80 101
 
81 102
   /**
82 103
    * The HTTP body to send with the request. This must be a valid
@@ -102,18 +123,18 @@ export type WebViewSource = WebViewSourceUri | WebViewSourceHtml;
102 123
 
103 124
 export interface WebViewNativeConfig {
104 125
   /*
105
-    * The native component used to render the WebView.
106
-    */
126
+   * The native component used to render the WebView.
127
+   */
107 128
   component?: ComponentType<WebViewSharedProps>;
108 129
   /*
109
-    * Set props directly on the native component WebView. Enables custom props which the
110
-    * original WebView doesn't pass through.
111
-    */
130
+   * Set props directly on the native component WebView. Enables custom props which the
131
+   * original WebView doesn't pass through.
132
+   */
112 133
   props?: any;
113 134
   /*
114
-    * Set the ViewManager to use for communication with the native side.
115
-    * @platform ios
116
-    */
135
+   * Set the ViewManager to use for communication with the native side.
136
+   * @platform ios
137
+   */
117 138
   viewManager?: any;
118 139
 }
119 140
 
@@ -142,7 +163,7 @@ export interface IOSWebViewProps {
142 163
    *   - fast: 0.99 (the default for iOS web view)
143 164
    * @platform ios
144 165
    */
145
-  decelerationRate?: 'fast' | 'normal' | number;
166
+  decelerationRate?: "fast" | "normal" | number;
146 167
 
147 168
   /**
148 169
    * Boolean value that determines whether scrolling is enabled in the
@@ -157,7 +178,7 @@ export interface IOSWebViewProps {
157 178
    * The default value is false.
158 179
    * @platform ios
159 180
    */
160
-  pagingEnabled?: boolean,
181
+  pagingEnabled?: boolean;
161 182
 
162 183
   /**
163 184
    * The amount by which the web view content is inset from the edges of
@@ -216,7 +237,7 @@ export interface IOSWebViewProps {
216 237
   /**
217 238
    * If true, this will be able horizontal swipe gestures when using the WKWebView. The default value is `false`.
218 239
    */
219
-  allowsBackForwardNavigationGestures?: boolean
240
+  allowsBackForwardNavigationGestures?: boolean;
220 241
 }
221 242
 
222 243
 export interface AndroidWebViewProps {
@@ -262,12 +283,12 @@ export interface AndroidWebViewProps {
262 283
   saveFormDataDisabled?: boolean;
263 284
 
264 285
   /*
265
-    * Used on Android only, controls whether the given list of URL prefixes should
266
-    * make {@link com.facebook.react.views.webview.ReactWebViewClient} to launch a
267
-    * default activity intent for those URL instead of loading it within the webview.
268
-    * Use this to list URLs that WebView cannot handle, e.g. a PDF url.
269
-    * @platform android
270
-    */
286
+   * Used on Android only, controls whether the given list of URL prefixes should
287
+   * make {@link com.facebook.react.views.webview.ReactWebViewClient} to launch a
288
+   * default activity intent for those URL instead of loading it within the webview.
289
+   * Use this to list URLs that WebView cannot handle, e.g. a PDF url.
290
+   * @platform android
291
+   */
271 292
   urlPrefixesForDefaultIntent?: string[];
272 293
 
273 294
   /**
@@ -308,10 +329,13 @@ export interface AndroidWebViewProps {
308 329
    * - `'compatibility'` -  WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content.
309 330
    * @platform android
310 331
    */
311
-  mixedContentMode?: 'never' | 'always' | 'compatibility';
332
+  mixedContentMode?: "never" | "always" | "compatibility";
312 333
 }
313 334
 
314
-export interface WebViewSharedProps extends ViewProps, IOSWebViewProps, AndroidWebViewProps {
335
+export interface WebViewSharedProps
336
+  extends ViewProps,
337
+    IOSWebViewProps,
338
+    AndroidWebViewProps {
315 339
   /**
316 340
    * @Deprecated. Use `source` instead.
317 341
    */
@@ -329,7 +353,11 @@ export interface WebViewSharedProps extends ViewProps, IOSWebViewProps, AndroidW
329 353
   /**
330 354
    * Function that returns a view to show if there's an error.
331 355
    */
332
-  renderError?: (errorDomain: string | undefined, errorCode: number, errorDesc: string) => ReactElement<any>; // view to show if there's an error
356
+  renderError?: (
357
+    errorDomain: string | undefined,
358
+    errorCode: number,
359
+    errorDesc: string
360
+  ) => ReactElement<any>; // view to show if there's an error
333 361
 
334 362
   /**
335 363
    * Function that returns a loading indicator.
@@ -429,12 +457,3 @@ export interface WebViewSharedProps extends ViewProps, IOSWebViewProps, AndroidW
429 457
   style?: StyleProp<ViewStyle>;
430 458
   children?: ReactNode;
431 459
 }
432
-
433
-export class WebView extends Component<WebViewSharedProps> {
434
-  public goForward: () => void;
435
-  public goBack: () => void;
436
-  public reload: () => void;
437
-  public stopLoading: () => void;
438
-  public postMessage: (msg: string) => void;
439
-  public injectJavaScript: (js: string) => void;
440
-}

+ 3
- 0
src/utils.ts View File

@@ -0,0 +1,3 @@
1
+import { WebViewSourceUri } from "./types/WebViewTypes";
2
+export const isWebViewUriSource = (source: any): source is WebViewSourceUri =>
3
+  typeof source !== "number" && !("html" in source);

+ 28
- 0
tsconfig.base.json View File

@@ -0,0 +1,28 @@
1
+{
2
+  "compilerOptions": {
3
+    "declaration": true,
4
+    "declarationDir": "lib",    
5
+    "esModuleInterop": true,
6
+    "isolatedModules": false,
7
+    "outDir": "./lib",
8
+    "moduleResolution": "node",
9
+    "module": "esnext",
10
+    "experimentalDecorators": true,
11
+    "allowSyntheticDefaultImports": true,
12
+    "lib": ["es6"],
13
+    "sourceMap": true,
14
+    "removeComments": true,
15
+    "jsx": "react-native",
16
+    "strict": true,
17
+    "noImplicitAny": true,
18
+    "strictNullChecks": false,
19
+    "strictFunctionTypes": true,
20
+    "noImplicitThis": true,
21
+    "alwaysStrict": true,
22
+    "noUnusedLocals": true,
23
+    "noImplicitReturns": true,
24
+    "noFallthroughCasesInSwitch": true,
25
+    "resolveJsonModule": true,
26
+    "target": "esnext"
27
+  }
28
+}

+ 5
- 0
tsconfig.json View File

@@ -0,0 +1,5 @@
1
+{
2
+  "extends": "./tsconfig.base.json",
3
+  "include": ["src", "./typings.d.ts", "types", "test"],
4
+  "exclude": ["node_modules", "dist"]  
5
+}

+ 11
- 5
yarn.lock View File

@@ -739,6 +739,11 @@
739 739
     into-stream "^4.0.0"
740 740
     lodash "^4.17.4"
741 741
 
742
+"@types/invariant@^2.2.29":
743
+  version "2.2.29"
744
+  resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.29.tgz#aa845204cd0a289f65d47e0de63a6a815e30cc66"
745
+  integrity sha512-lRVw09gOvgviOfeUrKc/pmTiRZ7g7oDOU6OAutyuSHpm1/o2RaBQvRhgK8QEdu+FFuw/wnWb29A/iuxv9i8OpQ==
746
+
742 747
 "@types/prop-types@*":
743 748
   version "15.5.6"
744 749
   resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.6.tgz#9c03d3fed70a8d517c191b7734da2879b50ca26c"
@@ -2572,7 +2577,7 @@ fbjs-scripts@^0.8.1:
2572 2577
     semver "^5.1.0"
2573 2578
     through2 "^2.0.0"
2574 2579
 
2575
-fbjs@^0.8.17, fbjs@^0.8.9:
2580
+fbjs@^0.8.9:
2576 2581
   version "0.8.17"
2577 2582
   resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
2578 2583
   dependencies:
@@ -2673,10 +2678,6 @@ find-versions@^2.0.0:
2673 2678
     array-uniq "^1.0.0"
2674 2679
     semver-regex "^1.0.0"
2675 2680
 
2676
-flow-bin@^0.80.0:
2677
-  version "0.80.0"
2678
-  resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.80.0.tgz#04cc1ee626a6f50786f78170c92ebe1745235403"
2679
-
2680 2681
 flush-write-stream@^1.0.0:
2681 2682
   version "1.0.3"
2682 2683
   resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd"
@@ -6374,6 +6375,11 @@ typedarray@^0.0.6:
6374 6375
   version "0.0.6"
6375 6376
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
6376 6377
 
6378
+typescript@^3.1.6:
6379
+  version "3.1.6"
6380
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.6.tgz#b6543a83cfc8c2befb3f4c8fba6896f5b0c9be68"
6381
+  integrity sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==
6382
+
6377 6383
 ua-parser-js@^0.7.18:
6378 6384
   version "0.7.18"
6379 6385
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"