Add WebView Flow types

This commit is contained in:
empyrical 2018-09-09 22:40:32 -06:00
parent 13ab5d6b41
commit 133f1e36bc
No known key found for this signature in database
GPG Key ID: 361A79873FCD3959
8 changed files with 627 additions and 57 deletions

88
.flowconfig Normal file
View File

@ -0,0 +1,88 @@
[ignore]
; This flowconfig is forked by platform - the only difference between them is which suffix is ignored.
.*/*[.]android.js
;.*/*[.]ios.js
; Ignore templates for 'react-native init'
.*/local-cli/templates/.*
; Ignore the Dangerfile
node_modules/react-native/bots/dangerfile.js
; Ignore "BUCK" generated dirs
node_modules/react-native/\.buckd/
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
; Ignore polyfills
.*/Libraries/polyfills/.*
; Ignore metro
.*/node_modules/metro/.*
; Ignore "config-chain"'s test folder - it has a corrupt JSON file that's tripping flow
.*/node_modules/config-chain/test/*.
; These should not be required directly
; require from fbjs/lib instead: require('fbjs/lib/invariant')
.*/node_modules/invariant/.*
.*/node_modules/warning/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow/
node_modules/react-native/flow-github/
[lints]
[options]
emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
module.system=haste
module.system.haste.use_name_reducers=true
# keep the following in sync with server/haste/hasteImpl.js
# get basename
module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
# strip .js or .js.flow suffix
module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
# strip platform suffix
module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
module.system.haste.paths.blacklist=.*/__tests__/.*
module.system.haste.paths.blacklist=.*/__mocks__/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/js/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/Libraries/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/RNTester/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/IntegrationTests/.*
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
; Surpress error `Duplicate module provider` until the slimmening is done
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Components/WebView/*.
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Components/WKWebView/*.
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[strict]

88
.flowconfig.android Normal file
View File

@ -0,0 +1,88 @@
[ignore]
; This flowconfig is forked by platform - the only difference between them is which suffix is ignored.
;.*/*[.]android.js
.*/*[.]ios.js
; Ignore templates for 'react-native init'
.*/local-cli/templates/.*
; Ignore the Dangerfile
node_modules/react-native/bots/dangerfile.js
; Ignore "BUCK" generated dirs
node_modules/react-native/\.buckd/
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
; Ignore polyfills
.*/Libraries/polyfills/.*
; Ignore metro
.*/node_modules/metro/.*
; Ignore "config-chain"'s test folder - it has a corrupt JSON file that's tripping flow
.*/node_modules/config-chain/test/*.
; These should not be required directly
; require from fbjs/lib instead: require('fbjs/lib/invariant')
.*/node_modules/invariant/.*
.*/node_modules/warning/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow/
node_modules/react-native/flow-github/
[lints]
[options]
emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
module.system=haste
module.system.haste.use_name_reducers=true
# keep the following in sync with server/haste/hasteImpl.js
# get basename
module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
# strip .js or .js.flow suffix
module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
# strip platform suffix
module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
module.system.haste.paths.blacklist=.*/__tests__/.*
module.system.haste.paths.blacklist=.*/__mocks__/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/js/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/Libraries/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/RNTester/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/IntegrationTests/.*
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
; Surpress error `Duplicate module provider` until the slimmening is done
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Components/WebView/*.
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Components/WKWebView/*.
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[strict]

View File

@ -15,14 +15,20 @@ import { requireNativeComponent } from 'react-native';
const RCTWKWebView = requireNativeComponent('RCTWKWebView');
class WKWebView extends React.Component {
componentWillReceiveProps(nextProps) {
type RCTWKWebViewProps = {
allowsInlineMediaPlayback?: boolean,
mediaPlaybackRequiresUserAction?: boolean,
dataDetectorTypes?: boolean,
};
class WKWebView extends React.Component<RCTWKWebViewProps> {
componentWillReceiveProps(nextProps: RCTWKWebViewProps) {
this.showRedboxOnPropChanges(nextProps, 'allowsInlineMediaPlayback');
this.showRedboxOnPropChanges(nextProps, 'mediaPlaybackRequiresUserAction');
this.showRedboxOnPropChanges(nextProps, 'dataDetectorTypes');
}
showRedboxOnPropChanges(nextProps, propName) {
showRedboxOnPropChanges(nextProps: RCTWKWebViewProps, propName: string) {
if (this.props[propName] !== nextProps[propName]) {
console.error(`Changes to property ${propName} do nothing after the initial render.`);
}

View File

@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
'use strict';
@ -21,9 +22,16 @@ import {
requireNativeComponent
} from 'react-native';
import invariant from 'fbjs/lib/invariant';
import keyMirror from 'fbjs/lib/keyMirror';
import WebViewShared from './WebViewShared';
import type {
WebViewErrorEvent,
WebViewEvent,
WebViewSharedProps,
WebViewSource,
} from './WebViewTypes';
const resolveAssetSource = Image.resolveAssetSource;
@ -41,10 +49,52 @@ const defaultRenderLoading = () => (
</View>
);
type State = {|
viewState: WebViewState,
lastErrorEvent: ?WebViewErrorEvent,
startInLoadingState: boolean,
|};
type WebViewPropsAndroid = $ReadOnly<{|
...WebViewSharedProps,
onNavigationStateChange?: (event: WebViewEvent) => any,
onContentSizeChange?: (event: WebViewEvent) => any,
/**
* Sets whether Geolocation is enabled. The default is false.
* @platform android
*/
geolocationEnabled?: ?boolean,
/**
* Boolean that sets whether JavaScript running in the context of a file
* scheme URL should be allowed to access content from any origin.
* Including accessing content from other file scheme URLs
* @platform android
*/
allowUniversalAccessFromFileURLs?: ?boolean,
/**
* Used on Android only, controls whether form autocomplete data should be saved
* @platform android
*/
saveFormDataDisabled?: ?boolean,
/*
* Used on Android only, controls whether the given list of URL prefixes should
* make {@link com.facebook.react.views.webview.ReactWebViewClient} to launch a
* default activity intent for those URL instead of loading it within the webview.
* Use this to list URLs that WebView cannot handle, e.g. a PDF url.
* @platform android
*/
urlPrefixesForDefaultIntent?: $ReadOnlyArray<string>,
|}>;
/**
* Renders a native WebView.
*/
class WebView extends React.Component {
class WebView extends React.Component<WebViewPropsAndroid, State> {
static defaultProps = {
javaScriptEnabled: true,
thirdPartyCookiesEnabled: true,
@ -55,7 +105,7 @@ class WebView extends React.Component {
state = {
viewState: WebViewState.IDLE,
lastErrorEvent: null,
lastErrorEvent: (null: ?WebViewErrorEvent),
startInLoadingState: true,
};
@ -72,6 +122,7 @@ class WebView extends React.Component {
otherView = (this.props.renderLoading || defaultRenderLoading)();
} else if (this.state.viewState === WebViewState.ERROR) {
const errorEvent = this.state.lastErrorEvent;
invariant(errorEvent != null, 'lastErrorEvent expected to be non-null');
otherView =
this.props.renderError &&
this.props.renderError(
@ -81,7 +132,7 @@ class WebView extends React.Component {
);
} else if (this.state.viewState !== WebViewState.IDLE) {
console.error(
'RCTWebView invalid state encountered: ' + this.state.loading,
'RCTWebView invalid state encountered: ' + this.state.viewState,
);
}
@ -94,11 +145,11 @@ class WebView extends React.Component {
webViewStyles.push(styles.hidden);
}
const source = this.props.source || {};
if (this.props.html) {
source.html = this.props.html;
} else if (this.props.url) {
source.uri = this.props.url;
let source = this.props.source || ({}: WebViewSource);
if (!this.props.source && this.props.html) {
source = { html: this.props.html };
} else if (!this.props.source && this.props.url) {
source = { uri: this.props.url };
}
if (source.method === 'POST' && source.headers) {
@ -198,7 +249,7 @@ class WebView extends React.Component {
);
};
postMessage = data => {
postMessage = (data: string) => {
UIManager.dispatchViewManagerCommand(
this.getWebViewHandle(),
UIManager.RCTWebView.Commands.postMessage,
@ -212,7 +263,7 @@ class WebView extends React.Component {
* on pages with a Content Security Policy that disallows eval(). If you need that
* functionality, look into postMessage/onMessage.
*/
injectJavaScript = data => {
injectJavaScript = (data: string) => {
UIManager.dispatchViewManagerCommand(
this.getWebViewHandle(),
UIManager.RCTWebView.Commands.injectJavaScript,
@ -224,7 +275,7 @@ class WebView extends React.Component {
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
*/
updateNavigationState = event => {
updateNavigationState = (event: WebViewEvent) => {
if (this.props.onNavigationStateChange) {
this.props.onNavigationStateChange(event.nativeEvent);
}
@ -234,13 +285,13 @@ class WebView extends React.Component {
return ReactNative.findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
};
onLoadingStart = event => {
onLoadingStart = (event: WebViewEvent) => {
const onLoadStart = this.props.onLoadStart;
onLoadStart && onLoadStart(event);
this.updateNavigationState(event);
};
onLoadingError = event => {
onLoadingError = (event: WebViewEvent) => {
event.persist(); // persist this event because we need to store it
const { onError, onLoadEnd } = this.props;
onError && onError(event);
@ -253,7 +304,7 @@ class WebView extends React.Component {
});
};
onLoadingFinish = event => {
onLoadingFinish = (event: WebViewEvent) => {
const { onLoad, onLoadEnd } = this.props;
onLoad && onLoad(event);
onLoadEnd && onLoadEnd(event);
@ -263,7 +314,7 @@ class WebView extends React.Component {
this.updateNavigationState(event);
};
onMessage = (event) => {
onMessage = (event: WebViewEvent) => {
const { onMessage } = this.props;
onMessage && onMessage(event);
};

View File

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*
* @format
* @noflow
* @flow
*/
'use strict';
@ -29,6 +29,12 @@ import invariant from 'fbjs/lib/invariant';
import keyMirror from 'fbjs/lib/keyMirror';
import WebViewShared from './WebViewShared';
import type {
WebViewErrorEvent,
WebViewEvent,
WebViewSharedProps,
WebViewSource,
} from './WebViewTypes';
const resolveAssetSource = Image.resolveAssetSource;
@ -65,13 +71,11 @@ const NavigationType = keyMirror({
const JSNavigationScheme = 'react-js-navigation';
// type ErrorEvent = {
// domain: any,
// code: any,
// description: any,
// };
// type Event = Object;
type State = {|
viewState: WebViewState,
lastErrorEvent: ?WebViewErrorEvent,
startInLoadingState: boolean,
|};
const DataDetectorTypes = [
'phoneNumber',
@ -121,7 +125,7 @@ const defaultRenderError = (errorDomain, errorCode, errorDesc) => (
* You can use this component to navigate back and forth in the web view's
* history and configure various properties for the web content.
*/
class WebView extends React.Component {
class WebView extends React.Component<WebViewSharedProps, State> {
static JSNavigationScheme = JSNavigationScheme;
static NavigationType = NavigationType;
@ -132,7 +136,7 @@ class WebView extends React.Component {
state = {
viewState: WebViewState.IDLE,
lastErrorEvent: null,
lastErrorEvent: (null: ?WebViewErrorEvent),
startInLoadingState: true,
};
@ -174,7 +178,7 @@ class WebView extends React.Component {
);
} else if (this.state.viewState !== WebViewState.IDLE) {
console.error(
'RCTWebView invalid state encountered: ' + this.state.loading,
'RCTWebView invalid state encountered: ' + this.state.viewState,
);
}
@ -217,6 +221,7 @@ class WebView extends React.Component {
shouldStart &&
this.props.onShouldStartLoadWithRequest(event.nativeEvent);
}
invariant(viewManager != null, 'viewManager expected to be non-null');
viewManager.startLoadWithResult(
!!shouldStart,
event.nativeEvent.lockIdentifier,
@ -227,11 +232,11 @@ class WebView extends React.Component {
this.props.decelerationRate,
);
const source = this.props.source || {};
if (this.props.html) {
source.html = this.props.html;
} else if (this.props.url) {
source.uri = this.props.url;
let source = this.props.source || ({}: WebViewSource);
if (!this.props.source && this.props.html) {
source = { html: this.props.html };
} else if (!this.props.source && this.props.url) {
source = { uri: this.props.url };
}
const messagingEnabled = typeof this.props.onMessage === 'function';
@ -345,7 +350,7 @@ class WebView extends React.Component {
* document.addEventListener('message', e => { document.title = e.data; });
* ```
*/
postMessage = data => {
postMessage = (data: string) => {
UIManager.dispatchViewManagerCommand(
this.getWebViewHandle(),
this._getCommands().postMessage,
@ -359,7 +364,7 @@ class WebView extends React.Component {
* on pages with a Content Security Policy that disallows eval(). If you need that
* functionality, look into postMessage/onMessage.
*/
injectJavaScript = data => {
injectJavaScript = (data: string) => {
UIManager.dispatchViewManagerCommand(
this.getWebViewHandle(),
this._getCommands().injectJavaScript,
@ -371,7 +376,7 @@ class WebView extends React.Component {
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
*/
_updateNavigationState = (event) => {
_updateNavigationState = (event: WebViewEvent) => {
if (this.props.onNavigationStateChange) {
this.props.onNavigationStateChange(event.nativeEvent);
}
@ -384,13 +389,13 @@ class WebView extends React.Component {
return ReactNative.findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
};
_onLoadingStart = (event) => {
_onLoadingStart = (event: WebViewEvent) => {
const onLoadStart = this.props.onLoadStart;
onLoadStart && onLoadStart(event);
this._updateNavigationState(event);
};
_onLoadingError = (event) => {
_onLoadingError = (event: WebViewEvent) => {
event.persist(); // persist this event because we need to store it
const { onError, onLoadEnd } = this.props;
onError && onError(event);
@ -403,7 +408,7 @@ class WebView extends React.Component {
});
};
_onLoadingFinish = (event) => {
_onLoadingFinish = (event: WebViewEvent) => {
const { onLoad, onLoadEnd } = this.props;
onLoad && onLoad(event);
onLoadEnd && onLoadEnd(event);
@ -413,12 +418,12 @@ class WebView extends React.Component {
this._updateNavigationState(event);
};
_onMessage = (event) => {
_onMessage = (event: WebViewEvent) => {
const { onMessage } = this.props;
onMessage && onMessage(event);
};
componentDidUpdate(prevProps) {
componentDidUpdate(prevProps: WebViewSharedProps) {
if (!(prevProps.useWebKit && this.props.useWebKit)) {
return;
}
@ -434,7 +439,7 @@ class WebView extends React.Component {
}
}
_showRedboxOnPropChanges(prevProps, propName) {
_showRedboxOnPropChanges(prevProps, propName: string) {
if (this.props[propName] !== prevProps[propName]) {
console.error(
`Changes to property ${propName} do nothing after the initial render.`,
@ -443,16 +448,8 @@ class WebView extends React.Component {
}
}
const RCTWebView = requireNativeComponent(
'RCTWebView',
WebView,
WebView.extraNativeComponentConfig,
);
const RCTWKWebView = requireNativeComponent(
'RCTWKWebView',
WebView,
WebView.extraNativeComponentConfig,
);
const RCTWebView = requireNativeComponent('RCTWebView');
const RCTWKWebView = requireNativeComponent('RCTWKWebView');
const styles = StyleSheet.create({
container: {

View File

@ -14,11 +14,11 @@ const escapeStringRegexp = require('escape-string-regexp');
const WebViewShared = {
defaultOriginWhitelist: ['http://*', 'https://*'],
extractOrigin: (url) => {
extractOrigin: (url: string) => {
const result = /^[A-Za-z0-9]+:(\/\/)?[^/]*/.exec(url);
return result === null ? null : result[0];
return result === null ? '' : result[0];
},
originWhitelistToRegex: (originWhitelist) => {
originWhitelistToRegex: (originWhitelist: string) => {
return escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*');
},
};

332
js/WebViewTypes.js Normal file
View File

@ -0,0 +1,332 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
'use strict';
import type {Node, Element} from 'react';
import type {EdgeInsetsProp} from 'EdgeInsetsPropType';
import type {ViewStyleProp} from 'StyleSheet';
import type {ViewProps} from 'ViewPropTypes';
export type WebViewErrorEvent = {
domain: any,
code: any,
description: any,
};
export type WebViewEvent = Object;
export type DataDetectorTypes =
| 'phoneNumber'
| 'link'
| 'address'
| 'calendarEvent'
| 'trackingNumber'
| 'flightNumber'
| 'lookupSuggestion'
| 'none'
| 'all';
export type WebViewSourceUri = {|
/**
* The URI to load in the `WebView`. Can be a local or remote file.
*/
uri?: ?string,
/**
* The HTTP Method to use. Defaults to GET if not specified.
* NOTE: On Android, only GET and POST are supported.
*/
method?: string,
/**
* Additional HTTP headers to send with the request.
* NOTE: On Android, this can only be used with GET requests.
*/
headers?: Object,
/**
* The HTTP body to send with the request. This must be a valid
* UTF-8 string, and will be sent exactly as specified, with no
* additional encoding (e.g. URL-escaping or base64) applied.
* NOTE: On Android, this can only be used with POST requests.
*/
body?: string,
|};
export type WebViewSourceHtml = {|
/**
* A static HTML page to display in the WebView.
*/
html?: ?string,
/**
* The base URL to be used for any relative links in the HTML.
*/
baseUrl?: ?string,
|};
export type WebViewSource = WebViewSourceUri | WebViewSourceHtml;
export type WebViewNativeConfig = $ReadOnly<{|
/*
* The native component used to render the WebView.
*/
component?: ?any,
/*
* Set props directly on the native component WebView. Enables custom props which the
* original WebView doesn't pass through.
*/
props?: ?Object,
/*
* Set the ViewManager to use for communication with the native side.
* @platform ios
*/
viewManager?: ?Object,
|}>;
export type WebViewSharedProps = $ReadOnly<{|
...ViewProps,
/**
* Deprecated. Use `source` instead.
*/
url?: ?string,
/**
* Deprecated. Use `source` instead.
*/
html?: ?string,
/**
* Loads static html or a uri (with optional headers) in the WebView.
*/
source?: ?WebViewSource,
/**
* If true, use WKWebView instead of UIWebView.
* @platform ios
*/
useWebKit?: ?boolean,
/**
* Function that returns a view to show if there's an error.
*/
renderError: (errorDomain: any, errorCode: any, errorDesc: any) => Element<any>, // view to show if there's an error
/**
* Function that returns a loading indicator.
*/
renderLoading: () => Element<any>,
/**
* Function that is invoked when the `WebView` has finished loading.
*/
onLoad: (event: WebViewEvent) => any,
/**
* Function that is invoked when the `WebView` load succeeds or fails.
*/
onLoadEnd: (event: WebViewEvent) => any,
/**
* Function that is invoked when the `WebView` starts loading.
*/
onLoadStart: (event: WebViewEvent) => any,
/**
* Function that is invoked when the `WebView` load fails.
*/
onError: (event: WebViewEvent) => any,
/**
* Boolean value that determines whether the web view bounces
* when it reaches the edge of the content. The default value is `true`.
* @platform ios
*/
bounces?: ?boolean,
/**
* A floating-point number that determines how quickly the scroll view
* decelerates after the user lifts their finger. You may also use the
* string shortcuts `"normal"` and `"fast"` which match the underlying iOS
* settings for `UIScrollViewDecelerationRateNormal` and
* `UIScrollViewDecelerationRateFast` respectively:
*
* - normal: 0.998
* - fast: 0.99 (the default for iOS web view)
* @platform ios
*/
decelerationRate?: ?('fast' | 'normal' | number),
/**
* Boolean value that determines whether scrolling is enabled in the
* `WebView`. The default value is `true`.
* @platform ios
*/
scrollEnabled?: ?boolean,
/**
* Controls whether to adjust the content inset for web views that are
* placed behind a navigation bar, tab bar, or toolbar. The default value
* is `true`.
*/
automaticallyAdjustContentInsets?: ?boolean,
/**
* The amount by which the web view content is inset from the edges of
* the scroll view. Defaults to {top: 0, left: 0, bottom: 0, right: 0}.
* @platform ios
*/
contentInset?: ?EdgeInsetsProp,
/**
* Function that is invoked when the `WebView` loading starts or ends.
*/
onNavigationStateChange?: (event: WebViewEvent) => any,
/**
* A function that is invoked when the webview calls `window.postMessage`.
* Setting this property will inject a `postMessage` global into your
* webview, but will still call pre-existing values of `postMessage`.
*
* `window.postMessage` accepts one argument, `data`, which will be
* available on the event object, `event.nativeEvent.data`. `data`
* must be a string.
*/
onMessage?: (event: WebViewEvent) => any,
/**
* Boolean value that forces the `WebView` to show the loading view
* on the first load.
*/
startInLoadingState?: ?boolean,
/**
* Determines the types of data converted to clickable URLs in the web view's content.
* By default only phone numbers are detected.
*
* You can provide one type or an array of many types.
*
* Possible values for `dataDetectorTypes` are:
*
* - `'phoneNumber'`
* - `'link'`
* - `'address'`
* - `'calendarEvent'`
* - `'none'`
* - `'all'`
*
* With the new WebKit implementation, we have three new values:
* - `'trackingNumber'`,
* - `'flightNumber'`,
* - `'lookupSuggestion'`,
*
* @platform ios
*/
dataDetectorTypes?:
| ?DataDetectorTypes
| $ReadOnlyArray<DataDetectorTypes>,
/**
* Boolean value to enable JavaScript in the `WebView`. Used on Android only
* as JavaScript is enabled by default on iOS. The default value is `true`.
* @platform android
*/
javaScriptEnabled?: ?boolean,
/**
* Boolean value to enable third party cookies in the `WebView`. Used on
* Android Lollipop and above only as third party cookies are enabled by
* default on Android Kitkat and below and on iOS. The default value is `true`.
* @platform android
*/
thirdPartyCookiesEnabled?: ?boolean,
/**
* Boolean value to control whether DOM Storage is enabled. Used only in
* Android.
* @platform android
*/
domStorageEnabled?: ?boolean,
/**
* Set this to provide JavaScript that will be injected into the web page
* when the view loads.
*/
injectedJavaScript?: ?string,
/**
* Sets the user-agent for the `WebView`.
* @platform android
*/
userAgent?: ?string,
/**
* Boolean that controls whether the web content is scaled to fit
* the view and enables the user to change the scale. The default value
* is `true`.
*
* On iOS, when `useWebKit=true`, this prop will not work.
*/
scalesPageToFit?: ?boolean,
/**
* Function that allows custom handling of any web view requests. Return
* `true` from the function to continue loading the request and `false`
* to stop loading.
* @platform ios
*/
onShouldStartLoadWithRequest?: (event: WebViewEvent) => any,
/**
* Boolean that determines whether HTML5 videos play inline or use the
* native full-screen controller. The default value is `false`.
*
* **NOTE** : In order for video to play inline, not only does this
* property need to be set to `true`, but the video element in the HTML
* document must also include the `webkit-playsinline` attribute.
* @platform ios
*/
allowsInlineMediaPlayback?: ?boolean,
/**
* Boolean that determines whether HTML5 audio and video requires the user
* to tap them before they start playing. The default value is `true`.
*/
mediaPlaybackRequiresUserAction?: ?boolean,
/**
* List of origin strings to allow being navigated to. The strings allow
* wildcards and get matched against *just* the origin (not the full URL).
* If the user taps to navigate to a new page but the new page is not in
* this whitelist, we will open the URL in Safari.
* The default whitelisted origins are "http://*" and "https://*".
*/
originWhitelist?: $ReadOnlyArray<string>,
/**
* Specifies the mixed content mode. i.e WebView will allow a secure origin to load content from any other origin.
*
* Possible values for `mixedContentMode` are:
*
* - `'never'` (default) - WebView will not allow a secure origin to load content from an insecure origin.
* - `'always'` - WebView will allow a secure origin to load content from any other origin, even if that origin is insecure.
* - `'compatibility'` - WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content.
* @platform android
*/
mixedContentMode?: ?('never' | 'always' | 'compatibility'),
/**
* Override the native component used to render the WebView. Enables a custom native
* WebView which uses the same JavaScript as the original WebView.
*/
nativeConfig?: ?WebViewNativeConfig,
style?: ViewStyleProp,
children: Node,
|}>;

View File

@ -5,12 +5,20 @@
"author": "Jamon Holmgren <jamon@infinite.red>",
"version": "0.1.0",
"homepage": "https://github.com/react-native-community/react-native-webview#readme",
"scripts": {
"flow": "flow check",
"flow-android": "flow check --flowconfig-name .flowconfig.android"
},
"peerDependencies": {
"react": "^16.0",
"react-native": "^0.56"
"react-native": "~0.57.0-rc.4"
},
"dependencies": {
"escape-string-regexp": "^1.0.5",
"fbjs": "^0.8.17"
},
"devDependencies": {
"flow-bin": "^0.80.0",
"react-native": "~0.57.0-rc.4"
}
}