mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-04-23 20:10:41 +08:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5395a3e8bc | ||
|
|
45b3d8b0df | ||
|
|
f1ee3c003a | ||
|
|
606181406c | ||
|
|
b537400f38 | ||
|
|
0a4fdc155e | ||
|
|
0b8e59974b | ||
|
|
22eebea633 | ||
|
|
5dd414f9aa | ||
|
|
72c72f6530 | ||
|
|
de970f9dbb | ||
|
|
e8d6c5b4dd | ||
|
|
e91a5ae13e | ||
|
|
b08bfb9ad5 | ||
|
|
5353011ee4 | ||
|
|
5faa3af19a | ||
|
|
c8461c9c11 | ||
|
|
3112e2ba56 | ||
|
|
fee03e101c | ||
|
|
c730a20a26 | ||
|
|
f7ed60ac67 | ||
|
|
417716391a | ||
|
|
ee5e3cb3ca | ||
|
|
2298c5d6e3 | ||
|
|
ca9f870ff6 | ||
|
|
e9b2fd8bc4 | ||
|
|
09a4985fd2 | ||
|
|
a9e61b4cd5 | ||
|
|
6ef19c3ccd | ||
|
|
0d29458874 | ||
|
|
1795bae8b5 | ||
|
|
c1152ee09a | ||
|
|
182149aac7 | ||
|
|
d6df440987 | ||
|
|
df16c24d68 | ||
|
|
8a2c259235 | ||
|
|
a7f265de11 | ||
|
|
581529540a | ||
|
|
8ad61d9061 | ||
|
|
3d79861970 | ||
|
|
0a84ccb299 | ||
|
|
3aa37450a0 |
19
README.md
19
README.md
@@ -23,12 +23,10 @@ it out](https://glitch.com/edit/#!/react-native-web-playground) on Glitch.
|
|||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
NOTE: React Native for Web supports React/ReactDOM 15.4, 15.5, or 15.6.
|
|
||||||
|
|
||||||
Install in your existing app using `yarn` or `npm`:
|
Install in your existing app using `yarn` or `npm`:
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn add react@15.6 react-dom@15.6 react-native-web
|
yarn add react react-dom react-native-web
|
||||||
```
|
```
|
||||||
|
|
||||||
Add the `react-native-web/babel` plugin to your Babel configuration. This will
|
Add the `react-native-web/babel` plugin to your Babel configuration. This will
|
||||||
@@ -46,6 +44,8 @@ by the app.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
(For React/ReactDOM 15.4 – 15.6 support, install `react-native-web@<0.1.0`)
|
||||||
|
|
||||||
See the [Getting Started](docs/guides/getting-started.md) guide for more details.
|
See the [Getting Started](docs/guides/getting-started.md) guide for more details.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
@@ -64,13 +64,6 @@ Guides:
|
|||||||
* [Advanced use](docs/guides/advanced.md)
|
* [Advanced use](docs/guides/advanced.md)
|
||||||
* [Known issues](docs/guides/known-issues.md)
|
* [Known issues](docs/guides/known-issues.md)
|
||||||
|
|
||||||
## Starter kits
|
|
||||||
|
|
||||||
* [Glitch](https://glitch.com/edit/#!/react-native-web-playground)
|
|
||||||
* [create-react-app](https://github.com/facebookincubator/create-react-app)
|
|
||||||
* [react-native-web-starter](https://github.com/grabcode/react-native-web-starter)
|
|
||||||
* [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack)
|
|
||||||
|
|
||||||
## Example code
|
## Example code
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -110,6 +103,12 @@ AppRegistry.registerComponent('MyApp', () => App)
|
|||||||
AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-root') })
|
AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-root') })
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Starter kits
|
||||||
|
|
||||||
|
* [Glitch](https://glitch.com/edit/#!/react-native-web-playground)
|
||||||
|
* [create-react-app](https://github.com/facebookincubator/create-react-app)
|
||||||
|
* [re-start](https://github.com/react-everywhere/re-start)
|
||||||
|
|
||||||
## Related projects
|
## Related projects
|
||||||
|
|
||||||
* [react-primitives](https://github.com/lelandrichardson/react-primitives/)
|
* [react-primitives](https://github.com/lelandrichardson/react-primitives/)
|
||||||
|
|||||||
@@ -12,13 +12,14 @@ import View from 'react-native-web/dist/components/View';
|
|||||||
|
|
||||||
exports[`2. Rewrite react-native paths for react-native-web 1`] = `
|
exports[`2. Rewrite react-native paths for react-native-web 1`] = `
|
||||||
"
|
"
|
||||||
import { Switch, Text, View as MyView } from 'react-native';
|
import { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';
|
||||||
|
|
||||||
↓ ↓ ↓ ↓ ↓ ↓
|
↓ ↓ ↓ ↓ ↓ ↓
|
||||||
|
|
||||||
import Switch from 'react-native-web/dist/components/Switch';
|
import Switch from 'react-native-web/dist/components/Switch';
|
||||||
import Text from 'react-native-web/dist/components/Text';
|
import Text from 'react-native-web/dist/components/Text';
|
||||||
import MyView from 'react-native-web/dist/components/View';
|
import MyView from 'react-native-web/dist/components/View';
|
||||||
|
import ViewPropTypes from 'react-native-web/dist/components/View/ViewPropTypes';
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -102,3 +103,59 @@ const { InvalidThing, TouchableOpacity } = require('react-native');
|
|||||||
const TouchableOpacity = require('react-native-web/dist/components/Touchable/TouchableOpacity');
|
const TouchableOpacity = require('react-native-web/dist/components/Touchable/TouchableOpacity');
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`10. Rewrite react-native paths for react-native-web 1`] = `
|
||||||
|
"
|
||||||
|
export { View } from 'react-native';
|
||||||
|
|
||||||
|
↓ ↓ ↓ ↓ ↓ ↓
|
||||||
|
|
||||||
|
export { default as View } from 'react-native-web/dist/components/View';
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`11. Rewrite react-native paths for react-native-web 1`] = `
|
||||||
|
"
|
||||||
|
export { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';
|
||||||
|
|
||||||
|
↓ ↓ ↓ ↓ ↓ ↓
|
||||||
|
|
||||||
|
export { default as Switch } from 'react-native-web/dist/components/Switch';
|
||||||
|
export { default as Text } from 'react-native-web/dist/components/Text';
|
||||||
|
export { default as MyView } from 'react-native-web/dist/components/View';
|
||||||
|
export { default as ViewPropTypes } from 'react-native-web/dist/components/View/ViewPropTypes';
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`12. Rewrite react-native paths for react-native-web 1`] = `
|
||||||
|
"
|
||||||
|
export { createElement, Switch, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
↓ ↓ ↓ ↓ ↓ ↓
|
||||||
|
|
||||||
|
export { default as createElement } from 'react-native-web/dist/modules/createElement';
|
||||||
|
export { default as Switch } from 'react-native-web/dist/components/Switch';
|
||||||
|
export { default as StyleSheet } from 'react-native-web/dist/apis/StyleSheet';
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`13. Rewrite react-native paths for react-native-web 1`] = `
|
||||||
|
"
|
||||||
|
export { InvalidThing, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
|
↓ ↓ ↓ ↓ ↓ ↓
|
||||||
|
|
||||||
|
export { InvalidThing } from 'react-native-web';
|
||||||
|
export { default as TouchableOpacity } from 'react-native-web/dist/components/Touchable/TouchableOpacity';
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`14. Rewrite react-native paths for react-native-web 1`] = `
|
||||||
|
"
|
||||||
|
export { default as RNW } from 'react-native';
|
||||||
|
|
||||||
|
↓ ↓ ↓ ↓ ↓ ↓
|
||||||
|
|
||||||
|
export { default as RNW } from 'react-native-web';
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ pluginTester({
|
|||||||
tests: [
|
tests: [
|
||||||
// import react-native
|
// import react-native
|
||||||
"import { View } from 'react-native';",
|
"import { View } from 'react-native';",
|
||||||
"import { Switch, Text, View as MyView } from 'react-native';",
|
"import { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';",
|
||||||
"import { createElement, Switch, StyleSheet } from 'react-native';",
|
"import { createElement, Switch, StyleSheet } from 'react-native';",
|
||||||
"import { InvalidThing, TouchableOpacity } from 'react-native';",
|
"import { InvalidThing, TouchableOpacity } from 'react-native';",
|
||||||
"import * as RNW from 'react-native';",
|
"import * as RNW from 'react-native';",
|
||||||
@@ -30,6 +30,13 @@ pluginTester({
|
|||||||
// "let { Switch, Text, View: MyView } = require('react-native-web');",
|
// "let { Switch, Text, View: MyView } = require('react-native-web');",
|
||||||
// "var { createElement, Switch, StyleSheet } = require('react-native-web');",
|
// "var { createElement, Switch, StyleSheet } = require('react-native-web');",
|
||||||
// "const { InvalidThing, TouchableOpacity } = require('react-native-web');",
|
// "const { InvalidThing, TouchableOpacity } = require('react-native-web');",
|
||||||
|
|
||||||
|
// export react-native
|
||||||
|
"export { View } from 'react-native';",
|
||||||
|
"export { Switch, Text, View as MyView, ViewPropTypes } from 'react-native';",
|
||||||
|
"export { createElement, Switch, StyleSheet } from 'react-native';",
|
||||||
|
"export { InvalidThing, TouchableOpacity } from 'react-native';",
|
||||||
|
"export { default as RNW } from 'react-native';",
|
||||||
{
|
{
|
||||||
code: "const RNW = require('react-native');",
|
code: "const RNW = require('react-native');",
|
||||||
output: "const RNW = require('react-native');",
|
output: "const RNW = require('react-native');",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const getDistLocation = importName => {
|
|||||||
case 'AppRegistry':
|
case 'AppRegistry':
|
||||||
case 'AppState':
|
case 'AppState':
|
||||||
case 'AsyncStorage':
|
case 'AsyncStorage':
|
||||||
case 'BackAndroid':
|
case 'BackHandler':
|
||||||
case 'Clipboard':
|
case 'Clipboard':
|
||||||
case 'Dimensions':
|
case 'Dimensions':
|
||||||
case 'Easing':
|
case 'Easing':
|
||||||
@@ -69,11 +69,15 @@ const getDistLocation = importName => {
|
|||||||
// propTypes
|
// propTypes
|
||||||
case 'ColorPropType':
|
case 'ColorPropType':
|
||||||
case 'EdgeInsetsPropType':
|
case 'EdgeInsetsPropType':
|
||||||
case 'PointPropType':
|
case 'PointPropType': {
|
||||||
case 'TextPropTypes':
|
|
||||||
case 'ViewPropTypes': {
|
|
||||||
return `${root}/propTypes/${importName}`;
|
return `${root}/propTypes/${importName}`;
|
||||||
}
|
}
|
||||||
|
case 'TextPropTypes': {
|
||||||
|
return `${root}/components/Text/${importName}`;
|
||||||
|
}
|
||||||
|
case 'ViewPropTypes': {
|
||||||
|
return `${root}/components/View/${importName}`;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@@ -102,7 +106,7 @@ module.exports = function({ types: t }) {
|
|||||||
visitor: {
|
visitor: {
|
||||||
ImportDeclaration(path) {
|
ImportDeclaration(path) {
|
||||||
const { source, specifiers } = path.node;
|
const { source, specifiers } = path.node;
|
||||||
if (source.value === 'react-native' && specifiers.length) {
|
if (source && source.value === 'react-native' && specifiers.length) {
|
||||||
const imports = specifiers
|
const imports = specifiers
|
||||||
.map(specifier => {
|
.map(specifier => {
|
||||||
if (t.isImportSpecifier(specifier)) {
|
if (t.isImportSpecifier(specifier)) {
|
||||||
@@ -123,6 +127,35 @@ module.exports = function({ types: t }) {
|
|||||||
path.replaceWithMultiple(imports);
|
path.replaceWithMultiple(imports);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ExportNamedDeclaration(path) {
|
||||||
|
const { source, specifiers } = path.node;
|
||||||
|
if (source && source.value === 'react-native' && specifiers.length) {
|
||||||
|
const exports = specifiers
|
||||||
|
.map(specifier => {
|
||||||
|
if (t.isExportSpecifier(specifier)) {
|
||||||
|
const exportName = specifier.exported.name;
|
||||||
|
const localName = specifier.local.name;
|
||||||
|
const distLocation = getDistLocation(localName);
|
||||||
|
|
||||||
|
if (distLocation) {
|
||||||
|
return t.exportNamedDeclaration(
|
||||||
|
null,
|
||||||
|
[t.exportSpecifier(t.identifier('default'), t.identifier(exportName))],
|
||||||
|
t.stringLiteral(distLocation)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return t.exportNamedDeclaration(
|
||||||
|
null,
|
||||||
|
[specifier],
|
||||||
|
t.stringLiteral('react-native-web')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
path.replaceWithMultiple(exports);
|
||||||
|
}
|
||||||
|
},
|
||||||
VariableDeclaration(path) {
|
VariableDeclaration(path) {
|
||||||
if (isReactNativeRequire(t, path.node)) {
|
if (isReactNativeRequire(t, path.node)) {
|
||||||
const { id } = path.node.declarations[0];
|
const { id } = path.node.declarations[0];
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
# AppRegistry
|
|
||||||
|
|
||||||
`AppRegistry` is the control point for registering, running, prerendering, and
|
|
||||||
unmounting all apps. App root components should register themselves with
|
|
||||||
`AppRegistry.registerComponent`. Apps can be run by invoking
|
|
||||||
`AppRegistry.runApplication` (see the [getting started guide](../guides/getting-started.md) for more details).
|
|
||||||
|
|
||||||
To "stop" an application when a view should be destroyed, call
|
|
||||||
`AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was passed
|
|
||||||
into `runApplication`. These should always be used as a pair.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
(web) static **getApplication**(appKey:string, appParameters: object)
|
|
||||||
|
|
||||||
Returns the given application element. Use this for server-side rendering.
|
|
||||||
Return object is of type `{ element: ReactElement; stylesheets: [ ReactElement ] }`.
|
|
||||||
|
|
||||||
static **registerConfig**(config: Array<AppConfig>)
|
|
||||||
|
|
||||||
Registry multiple applications. `AppConfig` is of type `{ appKey: string;
|
|
||||||
component: ComponentProvider; run?: Function }`.
|
|
||||||
|
|
||||||
static **registerComponent**(appKey: string, getComponentFunc: ComponentProvider)
|
|
||||||
|
|
||||||
Register a component provider under the given `appKey`.
|
|
||||||
|
|
||||||
static **registerRunnable**(appKey: string, run: Function)
|
|
||||||
|
|
||||||
Register a custom render function for an application. The function will receive
|
|
||||||
the `appParameters` passed to `runApplication`.
|
|
||||||
|
|
||||||
static **getAppKeys**()
|
|
||||||
|
|
||||||
Returns all registered app keys.
|
|
||||||
|
|
||||||
static **runApplication**(appKey: string, appParameters?: object)
|
|
||||||
|
|
||||||
Runs the application that was registered under `appKey`. The `appParameters`
|
|
||||||
must include the `rootTag` into which the application is rendered, and
|
|
||||||
optionally any `initialProps`.
|
|
||||||
|
|
||||||
On web, if the `rootTag` is a sub-section of your application it should be
|
|
||||||
styled as `position:relative` and given an explicit height.
|
|
||||||
|
|
||||||
static **unmountApplicationComponentAtRootTag**(rootTag: HTMLElement)
|
|
||||||
|
|
||||||
To "stop" an application when a view should be destroyed, call
|
|
||||||
`AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was passed
|
|
||||||
into `runApplication`
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
AppRegistry.registerComponent('MyApp', () => AppComponent)
|
|
||||||
AppRegistry.runApplication('MyApp', {
|
|
||||||
initialProps: {},
|
|
||||||
rootTag: document.getElementById('react-root')
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
## AppState
|
|
||||||
|
|
||||||
`AppState` can tell you if the app is in the foreground or background, and
|
|
||||||
notify you when the state changes.
|
|
||||||
|
|
||||||
States
|
|
||||||
|
|
||||||
* `active` - The app is running in the foreground
|
|
||||||
* `background` - The app is running in the background (i.e., the user has not focused the app's tab).
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
static **currentState**
|
|
||||||
|
|
||||||
Returns the current state of the app: `active` or `background`.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **addEventListener**(type: string, handler: Function)
|
|
||||||
|
|
||||||
Add a handler to `AppState` changes by listening to the `change` event type and
|
|
||||||
providing the `handler`. The handler is called with the app state value.
|
|
||||||
|
|
||||||
static **removeEventListener**(type: string, handler: Function)
|
|
||||||
|
|
||||||
Remove a handler by passing the change event `type` and the `handler`.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
To see the current state, you can check `AppState.currentState`, which will be
|
|
||||||
kept up-to-date. This example will only ever appear to say "Current state is:
|
|
||||||
active" because the app is only visible to the user when in the `active` state,
|
|
||||||
and the null state will happen only momentarily.
|
|
||||||
|
|
||||||
```js
|
|
||||||
class Example extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.state = { currentAppState: AppState.currentState }
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
AppState.addEventListener('change', this._handleAppStateChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
AppState.removeEventListener('change', this._handleAppStateChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleAppStateChange = (currentAppState) => {
|
|
||||||
this.setState({ currentAppState });
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Text>Current state is: {this.state.currentAppState}</Text>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
# AsyncStorage
|
|
||||||
|
|
||||||
`AsyncStorage` is a simple, asynchronous, persistent, key-value storage system
|
|
||||||
that is global to the domain. It's a facade over, and should be used instead of
|
|
||||||
`window.localStorage` to provide an asynchronous API and multi functions. Each
|
|
||||||
method returns a `Promise` object.
|
|
||||||
|
|
||||||
It is recommended that you use an abstraction on top of `AsyncStorage` instead
|
|
||||||
of `AsyncStorage` directly for anything more than light usage since it operates
|
|
||||||
globally.
|
|
||||||
|
|
||||||
The batched functions are useful for executing a lot of operations at once,
|
|
||||||
allowing for optimizations to provide the convenience of a single promise after
|
|
||||||
all operations are complete.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **clear**()
|
|
||||||
|
|
||||||
Erases all AsyncStorage. You probably don't want to call this - use
|
|
||||||
`removeItem` or `multiRemove` to clear only your own keys instead. Returns a
|
|
||||||
Promise object.
|
|
||||||
|
|
||||||
static **getAllKeys**()
|
|
||||||
|
|
||||||
Gets all known keys. Returns a Promise object.
|
|
||||||
|
|
||||||
static **getItem**(key: string)
|
|
||||||
|
|
||||||
Fetches the value of the given key. Returns a Promise object.
|
|
||||||
|
|
||||||
static **mergeItem**(key: string, value: string)
|
|
||||||
|
|
||||||
Merges existing value with input value, assuming they are stringified JSON.
|
|
||||||
Returns a Promise object.
|
|
||||||
|
|
||||||
static **multiGet**(keys: Array<string>)
|
|
||||||
|
|
||||||
`multiGet` results in an array of key-value pair arrays that matches the input
|
|
||||||
format of `multiSet`. Returns a Promise object.
|
|
||||||
|
|
||||||
```js
|
|
||||||
multiGet(['k1', 'k2']) -> [['k1', 'val1'], ['k2', 'val2']]
|
|
||||||
```
|
|
||||||
|
|
||||||
static **multiMerge**(keyValuePairs: Array<Array<string>>)
|
|
||||||
|
|
||||||
multiMerge takes an array of key-value array pairs that match the output of
|
|
||||||
`multiGet`. It merges existing values with input values, assuming they are
|
|
||||||
stringified JSON. Returns a Promise object.
|
|
||||||
|
|
||||||
static **multiRemove**(keys: Array<string>)
|
|
||||||
|
|
||||||
Delete all the keys in the keys array. Returns a Promise object.
|
|
||||||
|
|
||||||
static **multiSet**(keyValuePairs: Array<Array<string>>)
|
|
||||||
|
|
||||||
`multiSet` takes an array of key-value array pairs that match the output of
|
|
||||||
`multiGet`. Returns a Promise object.
|
|
||||||
|
|
||||||
```js
|
|
||||||
multiSet([['k1', 'val1'], ['k2', 'val2']]);
|
|
||||||
```
|
|
||||||
|
|
||||||
static **removeItem**(key: string)
|
|
||||||
|
|
||||||
Removes the value of the given key. Returns a Promise object.
|
|
||||||
|
|
||||||
static **setItem**(key: string, value: string)
|
|
||||||
|
|
||||||
Sets the value of the given key. Returns a Promise object.
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Clipboard
|
|
||||||
|
|
||||||
Clipboard gives you an interface for setting to the clipboard. (Getting
|
|
||||||
clipboard content is not supported on web.)
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **getString**()
|
|
||||||
|
|
||||||
Returns a `Promise` of an empty string.
|
|
||||||
|
|
||||||
static **setString**(content: string): boolean
|
|
||||||
|
|
||||||
Copies a string to the clipboard. On web, some browsers may not support copying
|
|
||||||
to the clipboard, therefore, this function returns a boolean to indicate if the
|
|
||||||
copy was successful.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Dimensions
|
|
||||||
|
|
||||||
Note: dimensions may change (e.g due to device rotation) so any rendering logic
|
|
||||||
or styles that depend on these constants should try to call this function on
|
|
||||||
every render, rather than caching the value.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **get**(dimension: string)
|
|
||||||
|
|
||||||
Get a dimension (e.g., `"window"` or `"screen"`).
|
|
||||||
|
|
||||||
Example: `const { height, width } = Dimensions.get('window')`
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# I18nManager
|
|
||||||
|
|
||||||
Control and set the layout and writing direction of the application.
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
**isRTL**: bool = false
|
|
||||||
|
|
||||||
Whether the application is currently in RTL mode.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **allowRTL**(allowRTL: bool)
|
|
||||||
|
|
||||||
Allow the application to display in RTL mode.
|
|
||||||
|
|
||||||
static **forceRTL**(forceRTL: bool)
|
|
||||||
|
|
||||||
Force the application to display in RTL mode.
|
|
||||||
|
|
||||||
static **setPreferredLanguageRTL**(isRTL: bool)
|
|
||||||
|
|
||||||
Set the application's preferred writing direction to RTL. You will need to
|
|
||||||
determine the user's preferred locale server-side (from HTTP headers) and
|
|
||||||
decide whether it's an RTL language.
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
# NetInfo
|
|
||||||
|
|
||||||
`NetInfo` asynchronously determines the online/offline status of the
|
|
||||||
application.
|
|
||||||
|
|
||||||
Connection types:
|
|
||||||
|
|
||||||
* `bluetooth` - The user agent is using a Bluetooth connection.
|
|
||||||
* `cellular` - The user agent is using a cellular connection (e.g., EDGE, HSPA, LTE, etc.).
|
|
||||||
* `ethernet` - The user agent is using an Ethernet connection.
|
|
||||||
* `mixed` - The user agent is using multiple connection types.
|
|
||||||
* `none` - The user agent will not contact the network (offline).
|
|
||||||
* `other` - The user agent is using a connection type that is not one of enumerated connection types.
|
|
||||||
* `unknown` - The user agent has established a network connection, but is unable to determine what is the underlying connection technology.
|
|
||||||
* `wifi` - The user agent is using a Wi-Fi connection.
|
|
||||||
* `wimax` - The user agent is using a WiMAX connection.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
Note that support for retrieving the connection type depends upon browswer
|
|
||||||
support (and is limited to mobile browsers). It will default to `unknown` when
|
|
||||||
support is missing.
|
|
||||||
|
|
||||||
static **addEventListener**(eventName: ChangeEventName, handler: Function)
|
|
||||||
|
|
||||||
static **fetch**(): Promise
|
|
||||||
|
|
||||||
static **removeEventListener**(eventName: ChangeEventName, handler: Function)
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
**isConnected**: bool = true
|
|
||||||
|
|
||||||
Available on all user agents. Asynchronously fetch a boolean to determine
|
|
||||||
internet connectivity. Use this if you are only interested with whether the device has internet connectivity.
|
|
||||||
|
|
||||||
**isConnected.addEventListener**(eventName: ChangeEventName, handler: Function)
|
|
||||||
|
|
||||||
**isConnected.fetch**(): Promise
|
|
||||||
|
|
||||||
**isConnected.removeEventListener**(eventName: ChangeEventName, handler: Function)
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
Fetching the connection type:
|
|
||||||
|
|
||||||
```js
|
|
||||||
NetInfo.fetch().then((connectionType) => {
|
|
||||||
console.log('Connection type:', connectionType);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Subscribing to changes in the connection type:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const handleConnectivityTypeChange = (connectionType) => {
|
|
||||||
console.log('Current connection type:', connectionType);
|
|
||||||
}
|
|
||||||
NetInfo.addEventListener('change', handleConnectivityTypeChange);
|
|
||||||
```
|
|
||||||
|
|
||||||
Fetching the connection status:
|
|
||||||
|
|
||||||
```js
|
|
||||||
NetInfo.isConnected.fetch().then((isConnected) => {
|
|
||||||
console.log('Connection status:', (isConnected ? 'online' : 'offline'));
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Subscribing to changes in the connection status:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const handleConnectivityStatusChange = (isConnected) => {
|
|
||||||
console.log('Current connection status:', (isConnected ? 'online' : 'offline'));
|
|
||||||
}
|
|
||||||
NetInfo.isConnected.addEventListener('change', handleConnectivityStatusChange);
|
|
||||||
```
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# PixelRatio
|
|
||||||
|
|
||||||
`PixelRatio` gives access to the device pixel density.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **get**()
|
|
||||||
|
|
||||||
Returns the device pixel density. Some examples:
|
|
||||||
|
|
||||||
* PixelRatio.get() === 1
|
|
||||||
* mdpi Android devices (160 dpi)
|
|
||||||
* PixelRatio.get() === 1.5
|
|
||||||
* hdpi Android devices (240 dpi)
|
|
||||||
* PixelRatio.get() === 2
|
|
||||||
* iPhone 4, 4S
|
|
||||||
* iPhone 5, 5c, 5s
|
|
||||||
* iPhone 6
|
|
||||||
* xhdpi Android devices (320 dpi)
|
|
||||||
* PixelRatio.get() === 3
|
|
||||||
* iPhone 6 plus
|
|
||||||
* xxhdpi Android devices (480 dpi)
|
|
||||||
* PixelRatio.get() === 3.5
|
|
||||||
* Nexus 6
|
|
||||||
|
|
||||||
static **getPixelSizeForLayoutSize**(layoutSize: number)
|
|
||||||
|
|
||||||
Converts a layout size (dp) to pixel size (px). Guaranteed to return an integer
|
|
||||||
number.
|
|
||||||
|
|
||||||
static **roundToNearestPixel**(layoutSize: number)
|
|
||||||
|
|
||||||
Rounds a layout size (dp) to the nearest layout size that corresponds to an
|
|
||||||
integer number of pixels. For example, on a device with a PixelRatio of 3,
|
|
||||||
`PixelRatio.roundToNearestPixel(8.4)` = `8.33`, which corresponds to exactly
|
|
||||||
`(8.33 * 3)` = `25` pixels.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
Fetching a correctly sized image. You should get a higher resolution image if
|
|
||||||
you are on a high pixel density device. A good rule of thumb is to multiply the
|
|
||||||
size of the image you display by the pixel ratio.
|
|
||||||
|
|
||||||
```js
|
|
||||||
const image = getImage({
|
|
||||||
width: PixelRatio.getPixelSizeForLayoutSize(200),
|
|
||||||
height: PixelRatio.getPixelSizeForLayoutSize(100),
|
|
||||||
});
|
|
||||||
|
|
||||||
<Image source={image} style={{ width: 200, height: 100 }} />
|
|
||||||
```
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# Platform
|
|
||||||
|
|
||||||
Detect what is the platform in which the app is running. This piece of
|
|
||||||
functionality can be useful when only small parts of a component are platform
|
|
||||||
specific.
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
**OS**: string
|
|
||||||
|
|
||||||
`Platform.OS` will be `web` when running in a Web browser.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { Platform } from 'react-native';
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
height: (Platform.OS === 'web') ? 200 : 100,
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
**select**(object): any
|
|
||||||
|
|
||||||
`Platform.select` takes an object containing `Platform.OS` as keys and returns
|
|
||||||
the value for the platform you are currently running on.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { Platform } from 'react-native';
|
|
||||||
|
|
||||||
const containerStyles = {
|
|
||||||
flex: 1,
|
|
||||||
...Platform.select({
|
|
||||||
android: {
|
|
||||||
backgroundColor: 'blue'
|
|
||||||
},
|
|
||||||
ios: {
|
|
||||||
backgroundColor: 'red'
|
|
||||||
},
|
|
||||||
web: {
|
|
||||||
backgroundColor: 'green'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
```
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
# StyleSheet
|
|
||||||
|
|
||||||
The `StyleSheet` abstraction converts predefined styles to (vendor-prefixed)
|
|
||||||
CSS without requiring a compile-time step. Styles that cannot be resolved
|
|
||||||
outside of the render loop (e.g., dynamic positioning) are usually applied as
|
|
||||||
inline styles. Read more about [how to style your
|
|
||||||
application](../guides/style.md).
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
**create**(obj: {[key: string]: any})
|
|
||||||
|
|
||||||
Each key of the object passed to `create` must define a style object.
|
|
||||||
|
|
||||||
**flatten**: function
|
|
||||||
|
|
||||||
Flattens an array of styles into a single style object.
|
|
||||||
|
|
||||||
(web) **getStyleSheets**: function
|
|
||||||
|
|
||||||
Returns an array of stylesheets (`{ id, textContent }`). Useful for
|
|
||||||
compile-time or server-side rendering.
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
**absoluteFill**: number
|
|
||||||
|
|
||||||
A very common pattern is to create overlays with position absolute and zero positioning,
|
|
||||||
so `absoluteFill` can be used for convenience and to reduce duplication of these repeated
|
|
||||||
styles.
|
|
||||||
|
|
||||||
```js
|
|
||||||
<View style={StyleSheet.absoluteFill} />
|
|
||||||
```
|
|
||||||
|
|
||||||
**absoluteFillObject**: object
|
|
||||||
|
|
||||||
Sometimes you may want `absoluteFill` but with a couple tweaks - `absoluteFillObject` can be
|
|
||||||
used to create a customized entry in a `StyleSheet`, e.g.:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
wrapper: {
|
|
||||||
...StyleSheet.absoluteFillObject,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
top: 10
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
**hairlineWidth**: number
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
<View style={styles.container}>
|
|
||||||
<Text
|
|
||||||
children={'Title text'}
|
|
||||||
style={[
|
|
||||||
styles.title,
|
|
||||||
this.props.isActive && styles.activeTitle
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
borderRadius: 4,
|
|
||||||
borderWidth: 0.5,
|
|
||||||
borderColor: '#d6d7da',
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
fontSize: 19,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
},
|
|
||||||
activeTitle: {
|
|
||||||
color: 'red',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Vibration
|
|
||||||
|
|
||||||
Vibration is described as a pattern of on-off pulses, which may be of varying
|
|
||||||
lengths. The pattern may consist of either a single integer, describing the
|
|
||||||
number of milliseconds to vibrate, or an array of integers describing a pattern
|
|
||||||
of vibrations and pauses. Vibration is controlled with a single method:
|
|
||||||
`Vibration.vibrate()`.
|
|
||||||
|
|
||||||
The vibration is asynchronous so this method will return immediately. There
|
|
||||||
will be no effect on devices that do not support vibration.
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **cancel**()
|
|
||||||
|
|
||||||
Stop the vibration.
|
|
||||||
|
|
||||||
static **vibrate**(pattern)
|
|
||||||
|
|
||||||
Start the vibration pattern.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
Vibrate once for 200ms:
|
|
||||||
|
|
||||||
```js
|
|
||||||
Vibration.vibrate(200);
|
|
||||||
Vibration.vibrate([200]);
|
|
||||||
```
|
|
||||||
|
|
||||||
Vibrate for 200ms, pause for 100ms, vibrate for 200ms:
|
|
||||||
|
|
||||||
```js
|
|
||||||
Vibration.vibrate([200, 100, 200]);
|
|
||||||
```
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
# ActivityIndicator
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
[...View props](./View.md)
|
|
||||||
|
|
||||||
**animating**: boolean = true
|
|
||||||
|
|
||||||
Whether to show the indicator or hide it.
|
|
||||||
|
|
||||||
**color**: ?color = '#1976D2'
|
|
||||||
|
|
||||||
The foreground color of the spinner.
|
|
||||||
|
|
||||||
**hidesWhenStopped**: ?boolean = true
|
|
||||||
|
|
||||||
Whether the indicator should hide when not animating.
|
|
||||||
|
|
||||||
**size**: ?enum('small, 'large') | number = 'small'
|
|
||||||
|
|
||||||
Size of the indicator. Small has a height of `20`, large has a height of `36`.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
import React, { Component } from 'react'
|
|
||||||
import { ActivityIndicator, StyleSheet, View } from 'react-native'
|
|
||||||
|
|
||||||
class ToggleAnimatingActivityIndicator extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.state = { animating: true }
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
this.setToggleTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<ActivityIndicator
|
|
||||||
animating={this.state.animating}
|
|
||||||
size="large"
|
|
||||||
style={[styles.centering, { height: 80 }]}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_setToggleTimeout() {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({ animating: !this.state.animating })
|
|
||||||
this._setToggleTimeout()
|
|
||||||
}, 1200)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
centering: {
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
},
|
|
||||||
gray: {
|
|
||||||
backgroundColor: '#cccccc'
|
|
||||||
},
|
|
||||||
horizontal: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-around'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# Button
|
|
||||||
|
|
||||||
A basic button component. Supports a minimal level of customization. You can
|
|
||||||
build your own custom button using `TouchableOpacity` or
|
|
||||||
`TouchableNativeFeedback`.
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
**accessibilityLabel**: ?string
|
|
||||||
|
|
||||||
Overrides the text that's read by a screen reader when the user interacts
|
|
||||||
with the element.
|
|
||||||
|
|
||||||
**color**: ?string
|
|
||||||
|
|
||||||
Background color of the button.
|
|
||||||
|
|
||||||
**disabled**: ?boolean
|
|
||||||
|
|
||||||
If `true`, disable all interactions for this element.
|
|
||||||
|
|
||||||
**onPress**: function
|
|
||||||
|
|
||||||
This function is called on press.
|
|
||||||
|
|
||||||
**testID**: ?string
|
|
||||||
|
|
||||||
Used to locate this view in end-to-end tests.
|
|
||||||
|
|
||||||
**title**: string
|
|
||||||
|
|
||||||
Text to display inside the button.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
<Button
|
|
||||||
accessibilityLabel="Learn more about this purple button"
|
|
||||||
color="#841584"
|
|
||||||
onPress={onPressLearnMore}
|
|
||||||
title="Learn More"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
# Image
|
|
||||||
|
|
||||||
An accessibile image component with support for image resizing, default image,
|
|
||||||
and child content.
|
|
||||||
|
|
||||||
Unsupported React Native props:
|
|
||||||
`capInsets` (ios),
|
|
||||||
`onProgress` (ios)
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
**accessibilityLabel**: ?string
|
|
||||||
|
|
||||||
The text that's read by a screenreader when someone interacts with the image.
|
|
||||||
|
|
||||||
**accessible**: ?boolean
|
|
||||||
|
|
||||||
When `true`, indicates the image is an accessibility element.
|
|
||||||
|
|
||||||
**children**: ?any
|
|
||||||
|
|
||||||
Content to display over the image.
|
|
||||||
|
|
||||||
**defaultSource**: ?object
|
|
||||||
|
|
||||||
An image to display as a placeholder while downloading the final image off the
|
|
||||||
network. `{ uri: string, width, height }`
|
|
||||||
|
|
||||||
**onError**: ?function
|
|
||||||
|
|
||||||
Invoked on load error with `{nativeEvent: {error}}`.
|
|
||||||
|
|
||||||
**onLayout**: ?function
|
|
||||||
|
|
||||||
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,
|
|
||||||
height } } }`, where `x` and `y` are the offsets from the parent node.
|
|
||||||
|
|
||||||
**onLoad**: ?function
|
|
||||||
|
|
||||||
Invoked when load completes successfully.
|
|
||||||
|
|
||||||
**onLoadEnd**: ?function
|
|
||||||
|
|
||||||
Invoked when load either succeeds or fails,
|
|
||||||
|
|
||||||
**onLoadStart**: ?function
|
|
||||||
|
|
||||||
Invoked on load start.
|
|
||||||
|
|
||||||
**resizeMode**: ?enum('center', 'contain', 'cover', 'none', 'repeat', 'stretch') = 'cover'
|
|
||||||
|
|
||||||
Determines how to resize the image when the frame doesn't match the raw image
|
|
||||||
dimensions.
|
|
||||||
|
|
||||||
**source**: ?object
|
|
||||||
|
|
||||||
`uri` is a string representing the resource identifier for the image, which
|
|
||||||
could be an http address or a base64 encoded image. `{ uri: string, width, height }`
|
|
||||||
|
|
||||||
**style**: ?style
|
|
||||||
|
|
||||||
+ ...[View#style](./View.md)
|
|
||||||
+ `resizeMode`
|
|
||||||
|
|
||||||
**testID**: ?string
|
|
||||||
|
|
||||||
Used to locate a view in end-to-end tests.
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
static **resizeMode**: object
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
```
|
|
||||||
<Image resizeMode={Image.resizeMode.contain} />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
static **getSize**(uri: string, success: (width, height) => {}, failure: function)
|
|
||||||
|
|
||||||
Retrieve the width and height (in pixels) of an image prior to displaying it.
|
|
||||||
This method can fail if the image cannot be found, or fails to download.
|
|
||||||
|
|
||||||
(In order to retrieve the image dimensions, the image may first need to be
|
|
||||||
loaded or downloaded, after which it will be cached. This means that in
|
|
||||||
principle you could use this method to preload images, however it is not
|
|
||||||
optimized for that purpose, and may in future be implemented in a way that does
|
|
||||||
not fully load/download the image data.)
|
|
||||||
|
|
||||||
static **prefetch**(url: string): Promise
|
|
||||||
|
|
||||||
Prefetches a remote image for later use by downloading it.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
import placeholderAvatar from './placeholderAvatar.png'
|
|
||||||
import React, { Component } from 'react'
|
|
||||||
import { Image, PropTypes, StyleSheet } from 'react-native'
|
|
||||||
|
|
||||||
export default class ImageExample extends Component {
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context)
|
|
||||||
this.state = { loading: true }
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
size: PropTypes.oneOf(['small', 'normal', 'large']),
|
|
||||||
testID: Image.propTypes.testID,
|
|
||||||
user: PropTypes.object
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
size: 'normal'
|
|
||||||
}
|
|
||||||
|
|
||||||
_onLoad(e) {
|
|
||||||
console.log('Avatar.onLoad', e)
|
|
||||||
this.setState({ loading: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { size, testID, user } = this.props
|
|
||||||
const loadingStyle = this.state.loading ? { styles.loading } : { }
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Image
|
|
||||||
accessibilityLabel={`${user.name}'s profile picture`}
|
|
||||||
defaultSource={{ uri: placeholderAvatar }}
|
|
||||||
onLoad={this._onLoad.bind(this)}
|
|
||||||
resizeMode='cover'
|
|
||||||
source={{ uri: user.avatarUrl }}
|
|
||||||
style={[
|
|
||||||
styles.base,
|
|
||||||
styles[size],
|
|
||||||
loadingStyle
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
base: {
|
|
||||||
borderColor: 'white',
|
|
||||||
borderRadius: 5,
|
|
||||||
borderWidth: 5
|
|
||||||
},
|
|
||||||
loading: {
|
|
||||||
opacity: 0.5
|
|
||||||
},
|
|
||||||
small: {
|
|
||||||
height: 32,
|
|
||||||
width: 32
|
|
||||||
},
|
|
||||||
normal: {
|
|
||||||
height: 48,
|
|
||||||
width: 48
|
|
||||||
},
|
|
||||||
large: {
|
|
||||||
height: 64,
|
|
||||||
width: 64
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# ProgressBar
|
|
||||||
|
|
||||||
Display an activity progress bar.
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
[...View props](./View.md)
|
|
||||||
|
|
||||||
**color**: ?string = '#1976D2'
|
|
||||||
|
|
||||||
Color of the progress bar.
|
|
||||||
|
|
||||||
**indeterminate**: ?boolean = true
|
|
||||||
|
|
||||||
Whether the progress bar will show indeterminate progress.
|
|
||||||
|
|
||||||
**progress**: ?number
|
|
||||||
|
|
||||||
The progress value (between 0 and 1).
|
|
||||||
|
|
||||||
**testID**: ?string
|
|
||||||
|
|
||||||
Used to locate this view in end-to-end tests.
|
|
||||||
|
|
||||||
(web) **trackColor**: ?string = 'transparent'
|
|
||||||
|
|
||||||
Color of the track bar.
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
# ScrollView
|
|
||||||
|
|
||||||
A scrollable `View` that provides itegration with the touch-locking "responder"
|
|
||||||
system. `ScrollView`'s must have a bounded height: either set the height of the
|
|
||||||
view directly (discouraged) or make sure all parent views have bounded height
|
|
||||||
(e.g., transfer `{ flex: 1}` down the view stack).
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
[...View props](./View.md)
|
|
||||||
|
|
||||||
**contentContainerStyle**: ?style
|
|
||||||
|
|
||||||
These styles will be applied to the scroll view content container which wraps
|
|
||||||
all of the child views.
|
|
||||||
|
|
||||||
**horizontal**: ?boolean = false
|
|
||||||
|
|
||||||
When `true`, the scroll view's children are arranged horizontally in a row
|
|
||||||
instead of vertically in a column.
|
|
||||||
|
|
||||||
**keyboardDismissMode**: ?enum('none', 'on-drag') = 'none'
|
|
||||||
|
|
||||||
Determines whether the keyboard gets dismissed in response to a scroll drag.
|
|
||||||
|
|
||||||
* `none` (the default), drags do not dismiss the keyboard.
|
|
||||||
* `on-drag`, the keyboard is dismissed when a drag begins.
|
|
||||||
* `interactive` (not supported on web; same as `none`)
|
|
||||||
|
|
||||||
**onContentSizeChange**: ?function
|
|
||||||
|
|
||||||
Called when scrollable content view of the `ScrollView` changes. It's
|
|
||||||
implemented using the `onLayout` handler attached to the content container
|
|
||||||
which this `ScrollView` renders.
|
|
||||||
|
|
||||||
**onScroll**: ?function
|
|
||||||
|
|
||||||
Fires at most once per frame during scrolling. The frequency of the events can
|
|
||||||
be contolled using the `scrollEventThrottle` prop.
|
|
||||||
|
|
||||||
Invoked on scroll with the following event:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
nativeEvent: {
|
|
||||||
contentOffset: { x, y },
|
|
||||||
contentSize: { height, width },
|
|
||||||
layoutMeasurement: { height, width }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**refreshControl**: ?element
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
A [RefreshControl](../RefreshControl) component, used to provide
|
|
||||||
pull-to-refresh functionality for the `ScrollView`.
|
|
||||||
|
|
||||||
**scrollEnabled**: ?boolean = true
|
|
||||||
|
|
||||||
When false, the content does not scroll.
|
|
||||||
|
|
||||||
**scrollEventThrottle**: ?number = 0
|
|
||||||
|
|
||||||
This controls how often the scroll event will be fired while scrolling (as a
|
|
||||||
time interval in ms). A lower number yields better accuracy for code that is
|
|
||||||
tracking the scroll position, but can lead to scroll performance problems. The
|
|
||||||
default value is `0`, which means the scroll event will be sent only once each
|
|
||||||
time the view is scrolled.
|
|
||||||
|
|
||||||
## Instance methods
|
|
||||||
|
|
||||||
**getInnerViewNode()**: any
|
|
||||||
|
|
||||||
Returns a reference to the underlying content container DOM node within the `ScrollView`.
|
|
||||||
|
|
||||||
**getScrollableNode()**: any
|
|
||||||
|
|
||||||
Returns a reference to the underlying scrollable DOM node.
|
|
||||||
|
|
||||||
**getScrollResponder()**: Component
|
|
||||||
|
|
||||||
Returns a reference to the underlying scroll responder, which supports
|
|
||||||
operations like `scrollTo`. All `ScrollView`-like components should implement
|
|
||||||
this method so that they can be composed while providing access to the
|
|
||||||
underlying scroll responder's methods.
|
|
||||||
|
|
||||||
**scrollTo(options: { x: number = 0; y: number = 0; animated: boolean = true })**
|
|
||||||
|
|
||||||
Scrolls to a given `x`, `y` offset (animation is not currently supported).
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
import React, { Component } from 'react'
|
|
||||||
import { ScrollView, StyleSheet } from 'react-native'
|
|
||||||
import Item from './Item'
|
|
||||||
|
|
||||||
export default class ScrollViewExample extends Component {
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context)
|
|
||||||
this.state = {
|
|
||||||
items: Array.from(new Array(20)).map((_, i) => ({ id: i }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onScroll(e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<ScrollView
|
|
||||||
children={this.state.items.map((item) => <Item {...item} />)}
|
|
||||||
contentContainerStyle={styles.container}
|
|
||||||
horizontal
|
|
||||||
onScroll={(e) => this.onScroll(e)}
|
|
||||||
scrollEventThrottle={100}
|
|
||||||
style={styles.root}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
root: {
|
|
||||||
borderWidth: 1
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
padding: 10
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
# Switch
|
|
||||||
|
|
||||||
This is a controlled component that requires an `onValueChange` callback that
|
|
||||||
updates the value prop in order for the component to reflect user actions. If
|
|
||||||
the `value` prop is not updated, the component will continue to render the
|
|
||||||
supplied `value` prop instead of the expected result of any user actions.
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
[...View props](./View.md)
|
|
||||||
|
|
||||||
**disabled**: ?boolean = false
|
|
||||||
|
|
||||||
If `true` the user won't be able to interact with the switch.
|
|
||||||
|
|
||||||
**onValueChange**: ?function
|
|
||||||
|
|
||||||
Invoked with the new value when the value changes.
|
|
||||||
|
|
||||||
**value**: ?boolean = false
|
|
||||||
|
|
||||||
The value of the switch. If `true` the switch will be turned on.
|
|
||||||
|
|
||||||
(web) **activeThumbColor**: ?color = #009688
|
|
||||||
|
|
||||||
The color of the thumb grip when the switch is turned on.
|
|
||||||
|
|
||||||
(web) **activeTrackColor**: ?color = #A3D3CF
|
|
||||||
|
|
||||||
The color of the track when the switch is turned on.
|
|
||||||
|
|
||||||
(web) **thumbColor**: ?color = #FAFAFA
|
|
||||||
|
|
||||||
The color of the thumb grip when the switch is turned off.
|
|
||||||
|
|
||||||
(web) **trackColor**: ?color = #939393
|
|
||||||
|
|
||||||
The color of the track when the switch is turned off.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
import React, { Component } from 'react'
|
|
||||||
import { Switch, View } from 'react-native'
|
|
||||||
|
|
||||||
class ColorSwitchExample extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.state = {
|
|
||||||
colorTrueSwitchIsOn: true,
|
|
||||||
colorFalseSwitchIsOn: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<View>
|
|
||||||
<Switch
|
|
||||||
activeThumbColor='#428BCA'
|
|
||||||
activeTrackColor='#A0C4E3'
|
|
||||||
onValueChange={(value) => this.setState({ colorFalseSwitchIsOn: value })}
|
|
||||||
value={this.state.colorFalseSwitchIsOn}
|
|
||||||
/>
|
|
||||||
<Switch
|
|
||||||
activeThumbColor='#5CB85C'
|
|
||||||
activeTrackColor='#ADDAAD'
|
|
||||||
onValueChange={(value) => this.setState({ colorTrueSwitchIsOn: value })}
|
|
||||||
thumbColor='#EBA9A7'
|
|
||||||
trackColor='#D9534F'
|
|
||||||
value={this.state.colorTrueSwitchIsOn}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
# Text
|
|
||||||
|
|
||||||
`Text` is component for displaying text. It supports style, basic touch
|
|
||||||
handling, and inherits typographic styles from ancestor elements.
|
|
||||||
|
|
||||||
The `Text` is unique relative to layout: child elements use text layout
|
|
||||||
(`inline`) rather than flexbox layout. This means that elements inside of a
|
|
||||||
`Text` are not rectangles, as they wrap when reaching the edge of their
|
|
||||||
container.
|
|
||||||
|
|
||||||
Unsupported React Native props:
|
|
||||||
`allowFontScaling` (ios),
|
|
||||||
`suppressHighlighting` (ios)
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
NOTE: `Text` will transfer all other props to the rendered HTML element.
|
|
||||||
|
|
||||||
(web) **accessibilityLabel**: ?string
|
|
||||||
|
|
||||||
Overrides the text that's read by a screen reader when the user interacts
|
|
||||||
with the element. (This is implemented using `aria-label`.)
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
|
||||||
|
|
||||||
(web) **accessibilityRole**: ?oneOf(roles)
|
|
||||||
|
|
||||||
Allows assistive technologies to present and support interaction with the view
|
|
||||||
in a manner that is consistent with user expectations for similar views of that
|
|
||||||
type. For example, marking a touchable view with an `accessibilityRole` of
|
|
||||||
`button`. (This is implemented using [ARIA roles](http://www.w3.org/TR/wai-aria/roles#role_definitions)).
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
|
||||||
|
|
||||||
**accessible**: ?boolean
|
|
||||||
|
|
||||||
When `true`, indicates that the view is an accessibility element (i.e.,
|
|
||||||
focusable) and groups its child content. By default, all the touchable elements
|
|
||||||
and elements with `accessibilityRole` of `button` and `link` are accessible.
|
|
||||||
(This is implemented using `tabindex`.)
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
|
||||||
|
|
||||||
**children**: ?any
|
|
||||||
|
|
||||||
Child content.
|
|
||||||
|
|
||||||
**importantForAccessibility**: ?enum('auto', 'no-hide-descendants', 'yes')
|
|
||||||
|
|
||||||
A value of `no` will remove the element from the tab flow.
|
|
||||||
|
|
||||||
A value of `no-hide-descendants` will hide the element and its children from
|
|
||||||
assistive technologies. (This is implemented using `aria-hidden`.)
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
|
||||||
|
|
||||||
**numberOfLines**: ?number
|
|
||||||
|
|
||||||
Truncates the text with an ellipsis after this many lines. Currently only supports `1`.
|
|
||||||
|
|
||||||
**onLayout**: ?function
|
|
||||||
|
|
||||||
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,
|
|
||||||
height } } }`, where `x` and `y` are the offsets from the parent node.
|
|
||||||
|
|
||||||
**onPress**: ?function
|
|
||||||
|
|
||||||
This function is called on press.
|
|
||||||
|
|
||||||
**selectable**: ?boolean
|
|
||||||
|
|
||||||
When `false`, the text is not selectable.
|
|
||||||
|
|
||||||
**style**: ?style
|
|
||||||
|
|
||||||
+ ...[View#style](View.md)
|
|
||||||
+ `color`
|
|
||||||
+ `fontFamily`
|
|
||||||
+ `fontFeatureSettings` ‡
|
|
||||||
+ `fontSize`
|
|
||||||
+ `fontStyle`
|
|
||||||
+ `fontWeight`
|
|
||||||
+ `letterSpacing`
|
|
||||||
+ `lineHeight`
|
|
||||||
+ `textAlign`
|
|
||||||
+ `textAlignVertical`
|
|
||||||
+ `textDecorationLine`
|
|
||||||
+ `textIndent` ‡
|
|
||||||
+ `textOverflow` ‡
|
|
||||||
+ `textRendering` ‡
|
|
||||||
+ `textShadowColor`
|
|
||||||
+ `textShadowOffset`
|
|
||||||
+ `textShadowRadius`
|
|
||||||
+ `textTransform` ‡
|
|
||||||
+ `unicodeBidi` ‡
|
|
||||||
+ `whiteSpace`
|
|
||||||
+ `wordWrap` ‡
|
|
||||||
+ `writingDirection`
|
|
||||||
|
|
||||||
‡ web only.
|
|
||||||
|
|
||||||
**testID**: ?string
|
|
||||||
|
|
||||||
Used to locate this view in end-to-end tests.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
import React, { Component, PropTypes } from 'react'
|
|
||||||
import { StyleSheet, Text } from 'react-native'
|
|
||||||
|
|
||||||
export default class PrettyText extends Component {
|
|
||||||
static propTypes = {
|
|
||||||
...Text.propTypes,
|
|
||||||
color: PropTypes.oneOf(['white', 'gray', 'red']),
|
|
||||||
size: PropTypes.oneOf(['small', 'normal', 'large']),
|
|
||||||
weight: PropTypes.oneOf(['light', 'normal', 'bold'])
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
...Text.defaultProps,
|
|
||||||
color: 'gray',
|
|
||||||
size: 'normal',
|
|
||||||
weight: 'normal'
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { color, size, style, weight, ...other } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Text
|
|
||||||
...other
|
|
||||||
style={[
|
|
||||||
style,
|
|
||||||
colorStyles[color],
|
|
||||||
sizeStyles[size],
|
|
||||||
weightStyles[weight]
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const colorStyles = StyleSheet.create({
|
|
||||||
white: { color: 'white' },
|
|
||||||
gray: { color: 'gray' },
|
|
||||||
red: { color: 'red' }
|
|
||||||
})
|
|
||||||
|
|
||||||
const sizeStyles = StyleSheet.create({
|
|
||||||
small: { fontSize: '0.85rem', padding: '0.5rem' },
|
|
||||||
normal: { fontSize: '1rem', padding: '0.75rem' },
|
|
||||||
large: { fontSize: '1.5rem', padding: '1rem' }
|
|
||||||
})
|
|
||||||
|
|
||||||
const weightStyles = StyleSheet.create({
|
|
||||||
light: { fontWeight: '300' },
|
|
||||||
normal: { fontWeight: '400' },
|
|
||||||
bold: { fontWeight: '700' }
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
# TextInput
|
|
||||||
|
|
||||||
Accessible single- and multi-line text input via a keyboard. Supports features
|
|
||||||
such as auto-complete, auto-focus, placeholder text, and event callbacks.
|
|
||||||
|
|
||||||
Note: some props are exclusive to or excluded from `multiline`.
|
|
||||||
|
|
||||||
Unsupported React Native props:
|
|
||||||
`onEndEditing`,
|
|
||||||
`clearButtonMode` (ios),
|
|
||||||
`enablesReturnKeyAutomatically` (ios),
|
|
||||||
`placeholderTextColor`,
|
|
||||||
`returnKeyType` (ios),
|
|
||||||
`selectionState` (ios),
|
|
||||||
`underlineColorAndroid` (android)
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
[...View props](./View.md)
|
|
||||||
|
|
||||||
**autoCapitalize**: ?enum('characters', 'none', 'sentences', 'words') = 'sentences'
|
|
||||||
|
|
||||||
Automatically capitalize certain characters (only available in Chrome and iOS Safari).
|
|
||||||
|
|
||||||
* `characters`: Automatically capitalize all characters.
|
|
||||||
* `none`: Completely disables automatic capitalization
|
|
||||||
* `sentences`: Automatically capitalize the first letter of sentences.
|
|
||||||
* `words`: Automatically capitalize the first letter of words.
|
|
||||||
|
|
||||||
(web) **autoComplete**: ?string
|
|
||||||
|
|
||||||
Indicates whether the value of the control can be automatically completed by
|
|
||||||
the browser. [Accepted values](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
|
|
||||||
|
|
||||||
**autoCorrect**: ?boolean = true
|
|
||||||
|
|
||||||
Automatically correct spelling mistakes (only available in iOS Safari).
|
|
||||||
|
|
||||||
**autoFocus**: ?boolean = false
|
|
||||||
|
|
||||||
If `true`, focuses the input on `componentDidMount`. Only the first form element
|
|
||||||
in a document with `autofocus` is focused.
|
|
||||||
|
|
||||||
**blurOnSubmit**: ?boolean
|
|
||||||
|
|
||||||
If `true`, the text field will blur when submitted. The default value is `true`
|
|
||||||
for single-line fields and `false` for multiline fields. Note, for multiline
|
|
||||||
fields setting `blurOnSubmit` to `true` means that pressing return will blur
|
|
||||||
the field and trigger the `onSubmitEditing` event instead of inserting a
|
|
||||||
newline into the field.
|
|
||||||
|
|
||||||
**clearTextOnFocus**: ?boolean = false
|
|
||||||
|
|
||||||
If `true`, clears the text field automatically when focused.
|
|
||||||
|
|
||||||
**defaultValue**: ?string
|
|
||||||
|
|
||||||
Provides an initial value that will change when the user starts typing. Useful
|
|
||||||
for simple use-cases where you don't want to deal with listening to events and
|
|
||||||
updating the `value` prop to keep the controlled state in sync.
|
|
||||||
|
|
||||||
**editable**: ?boolean = true
|
|
||||||
|
|
||||||
If `false`, text is not editable (i.e., read-only).
|
|
||||||
|
|
||||||
**keyboardType**: enum('default', 'email-address', 'numeric', 'phone-pad', 'search', 'url', 'web-search') = 'default'
|
|
||||||
|
|
||||||
Determines which keyboard to open. (NOTE: Safari iOS requires an ancestral
|
|
||||||
`<form action>` element to display the `search` keyboard).
|
|
||||||
|
|
||||||
(Not available when `multiline` is `true`.)
|
|
||||||
|
|
||||||
**maxLength**: ?number
|
|
||||||
|
|
||||||
Limits the maximum number of characters that can be entered.
|
|
||||||
|
|
||||||
**multiline**: ?boolean = false
|
|
||||||
|
|
||||||
If true, the text input can be multiple lines.
|
|
||||||
|
|
||||||
**numberOfLines**: ?number = 2
|
|
||||||
|
|
||||||
Sets the number of lines for a multiline `TextInput`.
|
|
||||||
|
|
||||||
(Requires `multiline` to be `true`.)
|
|
||||||
|
|
||||||
**onBlur**: ?function
|
|
||||||
|
|
||||||
Callback that is called when the text input is blurred.
|
|
||||||
|
|
||||||
**onChange**: ?function
|
|
||||||
|
|
||||||
Callback that is called when the text input's text changes.
|
|
||||||
|
|
||||||
**onChangeText**: ?function
|
|
||||||
|
|
||||||
Callback that is called when the text input's text changes. The text is passed
|
|
||||||
as an argument to the callback handler.
|
|
||||||
|
|
||||||
**onFocus**: ?function
|
|
||||||
|
|
||||||
Callback that is called when the text input is focused.
|
|
||||||
|
|
||||||
**onKeyPress**: ?function
|
|
||||||
|
|
||||||
Callback that is called when a key is pressed. This will be called with `{
|
|
||||||
nativeEvent: { key: keyValue } }` where keyValue is 'Enter` or 'Backspace' for
|
|
||||||
respective keys and the typed-in character otherwise including ' ' for space.
|
|
||||||
Modifier keys are also included in the nativeEvent. Fires before onChange
|
|
||||||
callbacks.
|
|
||||||
|
|
||||||
**onSelectionChange**: ?function
|
|
||||||
|
|
||||||
Callback that is called when the text input's selection changes. This will be called with
|
|
||||||
`{ nativeEvent: { selection: { start, end } } }`.
|
|
||||||
|
|
||||||
**onSubmitEditing**: ?function
|
|
||||||
|
|
||||||
Callback that is called when the keyboard's submit button is pressed.
|
|
||||||
|
|
||||||
**placeholder**: ?string
|
|
||||||
|
|
||||||
The string that will be rendered in an empty `TextInput` before text has been
|
|
||||||
entered.
|
|
||||||
|
|
||||||
**secureTextEntry**: ?boolean = false
|
|
||||||
|
|
||||||
If true, the text input obscures the text entered so that sensitive text like
|
|
||||||
passwords stay secure.
|
|
||||||
|
|
||||||
(Not available when `multiline` is `true`.)
|
|
||||||
|
|
||||||
**selection**: ?{ start: number, end: ?number }
|
|
||||||
|
|
||||||
The start and end of the text input's selection. Set start and end to the same value to position the cursor.
|
|
||||||
|
|
||||||
**selectTextOnFocus**: ?boolean = false
|
|
||||||
|
|
||||||
If `true`, all text will automatically be selected on focus.
|
|
||||||
|
|
||||||
**style**: ?style
|
|
||||||
|
|
||||||
+ ...[Text#style](./Text.md)
|
|
||||||
+ `resize` ‡
|
|
||||||
|
|
||||||
‡ web only.
|
|
||||||
|
|
||||||
**testID**: ?string
|
|
||||||
|
|
||||||
Used to locate this view in end-to-end tests.
|
|
||||||
|
|
||||||
**value**: ?string
|
|
||||||
|
|
||||||
The value to show for the text input. `TextInput` is a controlled component,
|
|
||||||
which means the native `value` will be forced to match this prop if provided.
|
|
||||||
Read about how [React form
|
|
||||||
components](https://facebook.github.io/react/docs/forms.html) work. To prevent
|
|
||||||
user edits to the value set `editable={false}`.
|
|
||||||
|
|
||||||
## Instance methods
|
|
||||||
|
|
||||||
**blur()**
|
|
||||||
|
|
||||||
Blur the underlying DOM input.
|
|
||||||
|
|
||||||
**clear()**
|
|
||||||
|
|
||||||
Clear the text from the underlying DOM input.
|
|
||||||
|
|
||||||
**focus()**
|
|
||||||
|
|
||||||
Focus the underlying DOM input.
|
|
||||||
|
|
||||||
**isFocused()**
|
|
||||||
|
|
||||||
Returns `true` if the input is currently focused; `false` otherwise.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
import React, { Component } from 'react'
|
|
||||||
import { StyleSheet, TextInput } from 'react-native'
|
|
||||||
|
|
||||||
export default class TextInputExample extends Component {
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context)
|
|
||||||
this.state = { isFocused: false }
|
|
||||||
}
|
|
||||||
|
|
||||||
_onBlur(e) {
|
|
||||||
this.setState({ isFocused: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
_onFocus(e) {
|
|
||||||
this.setState({ isFocused: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<TextInput
|
|
||||||
accessibilityLabel='Write a status update'
|
|
||||||
maxNumberOfLines={5}
|
|
||||||
multiline
|
|
||||||
numberOfLines={2}
|
|
||||||
onBlur={this._onBlur.bind(this)}
|
|
||||||
onFocus={this._onFocus.bind(this)}
|
|
||||||
placeholder={`What's happening?`}
|
|
||||||
style={[
|
|
||||||
styles.default
|
|
||||||
this.state.isFocused && styles.focused
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
default: {
|
|
||||||
borderColor: 'gray',
|
|
||||||
borderBottomWidth: 2
|
|
||||||
},
|
|
||||||
focused: {
|
|
||||||
borderColor: 'blue'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# TouchableWithoutFeedback
|
|
||||||
|
|
||||||
Do not use unless you have a very good reason. All the elements that respond to
|
|
||||||
press should have a visual feedback when touched. This is one of the primary
|
|
||||||
reason a "web" app doesn't feel "native".
|
|
||||||
|
|
||||||
**NOTE: `TouchableWithoutFeedback` supports only one child**. If you wish to have
|
|
||||||
several child components, wrap them in a View.
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
[...View props](./View.md)
|
|
||||||
|
|
||||||
**delayLongPress**: ?number
|
|
||||||
|
|
||||||
Delay in ms, from `onPressIn`, before `onLongPress` is called.
|
|
||||||
|
|
||||||
**delayPressIn**: ?number
|
|
||||||
|
|
||||||
Delay in ms, from the start of the touch, before `onPressIn` is called.
|
|
||||||
|
|
||||||
**delayPressOut**: ?number
|
|
||||||
|
|
||||||
Delay in ms, from the release of the touch, before `onPressOut` is called.
|
|
||||||
|
|
||||||
**disabled**: ?boolean
|
|
||||||
|
|
||||||
If `true`, disable all interactions for this component.
|
|
||||||
|
|
||||||
**onLongPress**: ?function
|
|
||||||
|
|
||||||
**onPress**: ?function
|
|
||||||
|
|
||||||
Called when the touch is released, but not if cancelled (e.g. by a scroll that steals the responder lock).
|
|
||||||
|
|
||||||
**onPressIn**: ?function
|
|
||||||
|
|
||||||
**onPressOut**: ?function
|
|
||||||
|
|
||||||
**pressRetentionOffset**: ?`{top: number, left: number, bottom: number, right: number}`
|
|
||||||
|
|
||||||
When the scroll view is disabled, this defines how far your touch may move off
|
|
||||||
of the button, before deactivating the button. Once deactivated, try moving it
|
|
||||||
back and you'll see that the button is once again reactivated! Move it back and
|
|
||||||
forth several times while the scroll view is disabled. Ensure you pass in a
|
|
||||||
constant to reduce memory allocations.
|
|
||||||
@@ -1,317 +0,0 @@
|
|||||||
# View
|
|
||||||
|
|
||||||
`View` is the fundamental UI building block. It is a component that supports
|
|
||||||
style, layout with flexbox, and accessibility controls. It can be nested
|
|
||||||
inside another `View` and has 0-to-many children of any type.
|
|
||||||
|
|
||||||
Also, refer to React Native's documentation about the [Gesture Responder
|
|
||||||
System](http://facebook.github.io/react-native/releases/0.22/docs/gesture-responder-system.html).
|
|
||||||
|
|
||||||
Unsupported React Native props: `collapsable`, `onAccessibilityTap`, `onMagicTap`.
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
NOTE: `View` will transfer all other props to the rendered HTML element.
|
|
||||||
|
|
||||||
**accessibilityLabel**: ?string
|
|
||||||
|
|
||||||
Overrides the text that's read by a screen reader when the user interacts
|
|
||||||
with the element. (This is implemented using `aria-label`.)
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility.md) for more information.
|
|
||||||
|
|
||||||
**accessibilityLiveRegion**: ?enum('assertive', 'none', 'polite')
|
|
||||||
|
|
||||||
Indicates to assistive technologies whether to notify the user when the view
|
|
||||||
changes. The values of this attribute are expressed in degrees of importance.
|
|
||||||
When regions are specified as `polite` (recommended), updates take low
|
|
||||||
priority. When regions are specified as `assertive`, assistive technologies
|
|
||||||
will interrupt and immediately notify the user. (This is implemented using
|
|
||||||
[`aria-live`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-live).)
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility.md) for more information.
|
|
||||||
|
|
||||||
(web) **accessibilityRole**: ?enum(roles)
|
|
||||||
|
|
||||||
Allows assistive technologies to present and support interaction with the view
|
|
||||||
in a manner that is consistent with user expectations for similar views of that
|
|
||||||
type. For example, marking a touchable view with an `accessibilityRole` of
|
|
||||||
`button`. (This is implemented using [ARIA roles](http://www.w3.org/TR/wai-aria/roles#role_definitions)).
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility.md) for more information.
|
|
||||||
|
|
||||||
**accessible**: ?boolean
|
|
||||||
|
|
||||||
When `true`, indicates that the view is an accessibility element (i.e.,
|
|
||||||
focusable) and groups its child content. By default, all the touchable elements
|
|
||||||
and elements with `accessibilityRole` of `button` and `link` are accessible.
|
|
||||||
(This is implemented using `tabindex`.)
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility.md) for more information.
|
|
||||||
|
|
||||||
**children**: ?element
|
|
||||||
|
|
||||||
Child content.
|
|
||||||
|
|
||||||
**hitSlop**: ?object
|
|
||||||
|
|
||||||
This defines how far a touch event can start away from the view (in pixels).
|
|
||||||
Typical interface guidelines recommend touch targets that are at least 30 - 40
|
|
||||||
points/density-independent pixels.
|
|
||||||
|
|
||||||
For example, if a touchable view has a height of `20` the touchable height can
|
|
||||||
be extended to `40` with `hitSlop={{top: 10, bottom: 10, left: 0, right: 0}}`.
|
|
||||||
|
|
||||||
**importantForAccessibility**: ?enum('auto', 'no', 'no-hide-descendants', 'yes')
|
|
||||||
|
|
||||||
A value of `no` will remove the element from the tab flow.
|
|
||||||
|
|
||||||
A value of `no-hide-descendants` will hide the element and its children from
|
|
||||||
assistive technologies. (This is implemented using `aria-hidden`.)
|
|
||||||
|
|
||||||
See the [Accessibility guide](../guides/accessibility.md) for more information.
|
|
||||||
|
|
||||||
**onLayout**: ?function
|
|
||||||
|
|
||||||
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,
|
|
||||||
height } } }`, where `x` and `y` are the offsets from the parent node.
|
|
||||||
|
|
||||||
**onMoveShouldSetResponder**: ?function => boolean
|
|
||||||
|
|
||||||
Does this view want to "claim" touch responsiveness? This is called for every
|
|
||||||
touch move on the `View` when it is not the responder.
|
|
||||||
|
|
||||||
**onMoveShouldSetResponderCapture**: ?function => boolean
|
|
||||||
|
|
||||||
If a parent `View` wants to prevent a child `View` from becoming responder on a
|
|
||||||
move, it should have this handler return `true`.
|
|
||||||
|
|
||||||
**onResponderGrant**: ?function
|
|
||||||
|
|
||||||
The `View` is now responding to touch events. This is the time to highlight and
|
|
||||||
show the user what is happening. For most touch interactions, you'll simply
|
|
||||||
want to wrap your component in `TouchableHighlight` or `TouchableOpacity`.
|
|
||||||
|
|
||||||
**onResponderMove**: ?function
|
|
||||||
|
|
||||||
The user is moving their finger.
|
|
||||||
|
|
||||||
**onResponderReject**: ?function
|
|
||||||
|
|
||||||
Another responder is already active and will not release it to the `View`
|
|
||||||
asking to be the responder.
|
|
||||||
|
|
||||||
**onResponderRelease**: ?function
|
|
||||||
|
|
||||||
Fired at the end of the touch.
|
|
||||||
|
|
||||||
**onResponderTerminate**: ?function
|
|
||||||
|
|
||||||
The responder has been taken from the `View`.
|
|
||||||
|
|
||||||
**onResponderTerminationRequest**: ?function
|
|
||||||
|
|
||||||
Some other `View` wants to become responder and is asking this `View` to
|
|
||||||
release its responder. Returning `true` allows its release.
|
|
||||||
|
|
||||||
**onStartShouldSetResponder**: ?function => boolean
|
|
||||||
|
|
||||||
Does this view want to become responder on the start of a touch?
|
|
||||||
|
|
||||||
**onStartShouldSetResponderCapture**: ?function => boolean
|
|
||||||
|
|
||||||
If a parent `View` wants to prevent a child `View` from becoming the responder
|
|
||||||
on a touch start, it should have this handler return `true`.
|
|
||||||
|
|
||||||
**pointerEvents**: ?enum('auto', 'box-only', 'box-none', 'none') = 'auto'
|
|
||||||
|
|
||||||
Controls whether the View can be the target of touch events. The enhanced
|
|
||||||
`pointerEvents` modes provided are not part of the CSS spec, therefore,
|
|
||||||
`pointerEvents` is excluded from `style`.
|
|
||||||
|
|
||||||
`box-none` is the equivalent of:
|
|
||||||
|
|
||||||
```css
|
|
||||||
.box-none { pointer-events: none !important; }
|
|
||||||
.box-none > * { pointer-events: auto; }
|
|
||||||
```
|
|
||||||
|
|
||||||
`box-only` is the equivalent of:
|
|
||||||
|
|
||||||
```css
|
|
||||||
.box-only { pointer-events: auto !important; }
|
|
||||||
.box-only > * { pointer-events: none; }
|
|
||||||
```
|
|
||||||
|
|
||||||
**style**: ?style
|
|
||||||
|
|
||||||
+ `alignContent`
|
|
||||||
+ `alignItems`
|
|
||||||
+ `alignSelf`
|
|
||||||
+ `animationDelay` ‡
|
|
||||||
+ `animationDirection` ‡
|
|
||||||
+ `animationDuration` ‡
|
|
||||||
+ `animationFillMode` ‡
|
|
||||||
+ `animationIterationCount` ‡
|
|
||||||
+ `animationName` ‡
|
|
||||||
+ `animationPlayState` ‡
|
|
||||||
+ `animationTimingFunction` ‡
|
|
||||||
+ `backfaceVisibility`
|
|
||||||
+ `backgroundAttachment` ‡
|
|
||||||
+ `backgroundBlendMode` ‡
|
|
||||||
+ `backgroundClip` ‡
|
|
||||||
+ `backgroundColor`
|
|
||||||
+ `backgroundImage` ‡
|
|
||||||
+ `backgroundOrigin` ‡
|
|
||||||
+ `backgroundPosition` ‡
|
|
||||||
+ `backgroundRepeat` ‡
|
|
||||||
+ `backgroundSize` ‡
|
|
||||||
+ `borderColor` (single value)
|
|
||||||
+ `borderTopColor`
|
|
||||||
+ `borderBottomColor`
|
|
||||||
+ `borderRightColor`
|
|
||||||
+ `borderLeftColor`
|
|
||||||
+ `borderRadius` (single value)
|
|
||||||
+ `borderTopLeftRadius`
|
|
||||||
+ `borderTopRightRadius`
|
|
||||||
+ `borderBottomLeftRadius`
|
|
||||||
+ `borderBottomRightRadius`
|
|
||||||
+ `borderStyle` (single value)
|
|
||||||
+ `borderTopStyle`
|
|
||||||
+ `borderRightStyle`
|
|
||||||
+ `borderBottomStyle`
|
|
||||||
+ `borderLeftStyle`
|
|
||||||
+ `borderWidth` (single value)
|
|
||||||
+ `borderBottomWidth`
|
|
||||||
+ `borderLeftWidth`
|
|
||||||
+ `borderRightWidth`
|
|
||||||
+ `borderTopWidth`
|
|
||||||
+ `bottom`
|
|
||||||
+ `boxShadow` ‡
|
|
||||||
+ `boxSizing`
|
|
||||||
+ `clip` ‡
|
|
||||||
+ `cursor` ‡
|
|
||||||
+ `display`
|
|
||||||
+ `filter` ‡
|
|
||||||
+ `flex` (number)
|
|
||||||
+ `flexBasis`
|
|
||||||
+ `flexDirection`
|
|
||||||
+ `flexGrow`
|
|
||||||
+ `flexShrink`
|
|
||||||
+ `flexWrap`
|
|
||||||
+ `gridAutoColumns` ‡
|
|
||||||
+ `gridAutoFlow` ‡
|
|
||||||
+ `gridAutoRows` ‡
|
|
||||||
+ `gridColumnEnd` ‡
|
|
||||||
+ `gridColumnGap` ‡
|
|
||||||
+ `gridColumnStart` ‡
|
|
||||||
+ `gridRowEnd` ‡
|
|
||||||
+ `gridRowGap` ‡
|
|
||||||
+ `gridRowStart` ‡
|
|
||||||
+ `gridTemplateColumns` ‡
|
|
||||||
+ `gridTemplateRows` ‡
|
|
||||||
+ `gridTemplateAreas` ‡
|
|
||||||
+ `height`
|
|
||||||
+ `justifyContent`
|
|
||||||
+ `left`
|
|
||||||
+ `margin` (single value)
|
|
||||||
+ `marginBottom`
|
|
||||||
+ `marginHorizontal`
|
|
||||||
+ `marginLeft`
|
|
||||||
+ `marginRight`
|
|
||||||
+ `marginTop`
|
|
||||||
+ `marginVertical`
|
|
||||||
+ `maxHeight`
|
|
||||||
+ `maxWidth`
|
|
||||||
+ `minHeight`
|
|
||||||
+ `minWidth`
|
|
||||||
+ `opacity`
|
|
||||||
+ `order`
|
|
||||||
+ `outline` ‡
|
|
||||||
+ `outlineColor` ‡
|
|
||||||
+ `overflow`
|
|
||||||
+ `overflowX` ‡
|
|
||||||
+ `overflowY` ‡
|
|
||||||
+ `padding` (single value)
|
|
||||||
+ `paddingBottom`
|
|
||||||
+ `paddingHorizontal`
|
|
||||||
+ `paddingLeft`
|
|
||||||
+ `paddingRight`
|
|
||||||
+ `paddingTop`
|
|
||||||
+ `paddingVertical`
|
|
||||||
+ `perspective` ‡
|
|
||||||
+ `perspectiveOrigin` ‡
|
|
||||||
+ `position`
|
|
||||||
+ `right`
|
|
||||||
+ `shadowColor`
|
|
||||||
+ `shadowOffset`
|
|
||||||
+ `shadowOpacity`
|
|
||||||
+ `shadowRadius`
|
|
||||||
+ `top`
|
|
||||||
+ `transform`
|
|
||||||
+ `transformOrigin` ‡
|
|
||||||
+ `transitionDelay` ‡
|
|
||||||
+ `transitionDuration` ‡
|
|
||||||
+ `transitionProperty` ‡
|
|
||||||
+ `transitionTimingFunction` ‡
|
|
||||||
+ `userSelect` ‡
|
|
||||||
+ `visibility` ‡
|
|
||||||
+ `width`
|
|
||||||
+ `willChange` ‡
|
|
||||||
+ `zIndex`
|
|
||||||
|
|
||||||
‡ web only.
|
|
||||||
|
|
||||||
Default:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
alignItems: 'stretch',
|
|
||||||
borderWidth: 0,
|
|
||||||
borderStyle: 'solid',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
display: 'flex',
|
|
||||||
flexBasis: 'auto',
|
|
||||||
flexDirection: 'column',
|
|
||||||
flexShrink: 0,
|
|
||||||
margin: 0,
|
|
||||||
padding: 0,
|
|
||||||
position: 'relative'
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
(See [facebook/yoga](https://github.com/facebook/yoga)).
|
|
||||||
|
|
||||||
**testID**: ?string
|
|
||||||
|
|
||||||
Used to locate this view in end-to-end tests.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```js
|
|
||||||
import React, { Component, PropTypes } from 'react'
|
|
||||||
import { StyleSheet, View } from 'react-native'
|
|
||||||
|
|
||||||
export default class ViewExample extends Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<View style={styles.row}>
|
|
||||||
{
|
|
||||||
['1', '2', '3', '4', '5'].map((value, i) => {
|
|
||||||
return <View children={value} key={i} style={styles.cell} />
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
row: {
|
|
||||||
flexDirection: 'row'
|
|
||||||
},
|
|
||||||
cell: {
|
|
||||||
flexGrow: 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
@@ -36,7 +36,7 @@ const babelLoaderConfiguration = {
|
|||||||
cacheDirectory: true,
|
cacheDirectory: true,
|
||||||
// This aliases 'react-native' to 'react-native-web' and includes only
|
// This aliases 'react-native' to 'react-native-web' and includes only
|
||||||
// the modules needed by the app
|
// the modules needed by the app
|
||||||
plugins: ['react-native-web/babel']
|
plugins: ['react-native-web/babel'],
|
||||||
// The 'react-native' preset is recommended (or use your own .babelrc)
|
// The 'react-native' preset is recommended (or use your own .babelrc)
|
||||||
presets: ['react-native']
|
presets: ['react-native']
|
||||||
}
|
}
|
||||||
@@ -127,6 +127,7 @@ import AppHeader from './src/AppHeader';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactNative from 'react-native';
|
import ReactNative from 'react-native';
|
||||||
|
|
||||||
|
// use .hydrate if hydrating a SSR app
|
||||||
ReactNative.render(<AppHeader />, document.getElementById('react-app-header'))
|
ReactNative.render(<AppHeader />, document.getElementById('react-app-header'))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const DimensionsScreen = () => (
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<DocItem
|
<DocItem
|
||||||
name="static addEventLitener"
|
name="static addEventListener"
|
||||||
typeInfo="(type: string, handler: function) => void"
|
typeInfo="(type: string, handler: function) => void"
|
||||||
description={[
|
description={[
|
||||||
<AppText>Add an event handler. Supported events:</AppText>,
|
<AppText>Add an event handler. Supported events:</AppText>,
|
||||||
@@ -65,7 +65,7 @@ const DimensionsScreen = () => (
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<DocItem
|
<DocItem
|
||||||
name="static removeEventLitener"
|
name="static removeEventListener"
|
||||||
typeInfo="(type: string, handler: function) => void"
|
typeInfo="(type: string, handler: function) => void"
|
||||||
description="Remove an event handler."
|
description="Remove an event handler."
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -8,61 +8,94 @@ import UIExplorer, {
|
|||||||
Code,
|
Code,
|
||||||
Description,
|
Description,
|
||||||
DocItem,
|
DocItem,
|
||||||
|
ExternalLink,
|
||||||
Section,
|
Section,
|
||||||
storiesOf,
|
storiesOf
|
||||||
TextList
|
|
||||||
} from '../../ui-explorer';
|
} from '../../ui-explorer';
|
||||||
|
|
||||||
const NetInfoScreen = () => (
|
const NetInfoScreen = () => (
|
||||||
<UIExplorer title="NetInfo" url="2-apis/NetInfo">
|
<UIExplorer title="NetInfo" url="2-apis/NetInfo">
|
||||||
<Description>
|
<Description>
|
||||||
<AppText>
|
<AppText>
|
||||||
NetInfo asynchronously determines the online/offline status of the application.
|
NetInfo asynchronously determines the online/offline status and additional connection
|
||||||
|
information (where available) of the application.
|
||||||
</AppText>
|
</AppText>
|
||||||
<AppText>
|
<AppText>
|
||||||
Note that support for retrieving the connection type depends upon browser support (and is
|
Note that connection type information is limited to how well the browser supports the{' '}
|
||||||
limited to mobile browsers). It will default to <Code>unknown</Code> when support is
|
<ExternalLink href="https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation">
|
||||||
missing.
|
NetworkInformation API
|
||||||
|
</ExternalLink>. Connection types will be <Code>unknown</Code> when support is missing.
|
||||||
</AppText>
|
</AppText>
|
||||||
</Description>
|
</Description>
|
||||||
|
|
||||||
|
<Section title="Types">
|
||||||
|
<DocItem
|
||||||
|
description={
|
||||||
|
<AppText>
|
||||||
|
One of <Code>slow-2g</Code>, <Code>2g</Code>, <Code>3g</Code>, <Code>4g</Code>,{' '}
|
||||||
|
<Code>unknown</Code>.
|
||||||
|
</AppText>
|
||||||
|
}
|
||||||
|
name="ConnectionType"
|
||||||
|
/>
|
||||||
|
<DocItem
|
||||||
|
description={
|
||||||
|
<AppText>
|
||||||
|
One of <Code>bluebooth</Code>, <Code>cellular</Code>, <Code>ethernet</Code>,{' '}
|
||||||
|
<Code>mixed</Code>, <Code>mixed</Code>, <Code>none</Code>, <Code>other</Code>,{' '}
|
||||||
|
<Code>unknown</Code>, <Code>wifi</Code>, <Code>wimax</Code>
|
||||||
|
</AppText>
|
||||||
|
}
|
||||||
|
name="EffectiveConnectionType"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DocItem
|
||||||
|
description={
|
||||||
|
<Code>{`{
|
||||||
|
effectiveType: EffectiveConnectionType;
|
||||||
|
type: ConnectionType;
|
||||||
|
downlink?: number;
|
||||||
|
downlinkMax?: number;
|
||||||
|
rtt?: number;
|
||||||
|
}`}</Code>
|
||||||
|
}
|
||||||
|
name="ConnectionEventType"
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
|
||||||
<Section title="Methods">
|
<Section title="Methods">
|
||||||
<DocItem
|
<DocItem
|
||||||
description={[
|
description={
|
||||||
<AppText>
|
<AppText>
|
||||||
Invokes the listener whenever network status changes. The listener receives one of the
|
Adds an event handler. The <Code>connectionChange</Code> event fires when the network
|
||||||
following connectivity types (from the DOM connection API):
|
status changes. The argument to the event handler is an object of type{' '}
|
||||||
</AppText>,
|
<Code>ConnectionEventType</Code>.
|
||||||
<TextList
|
</AppText>
|
||||||
items={[
|
}
|
||||||
'bluetooth',
|
|
||||||
'cellular',
|
|
||||||
'ethernet',
|
|
||||||
'mixed',
|
|
||||||
'none',
|
|
||||||
'other',
|
|
||||||
'unknown',
|
|
||||||
'wifi',
|
|
||||||
'wimax'
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
]}
|
|
||||||
example={{
|
example={{
|
||||||
code: "NetInfo.addEventListener('change', (connectionType) => {})"
|
code: `NetInfo.addEventListener('connectionChange', ({ effectiveType, type }) => {
|
||||||
|
console.log('Effective connection type:', effectiveType);
|
||||||
|
console.log('Connection type:', type);
|
||||||
|
})`
|
||||||
}}
|
}}
|
||||||
name="static addEventListener"
|
name="static addEventListener"
|
||||||
typeInfo="(eventName, handler) => void"
|
typeInfo="(eventName, handler) => void"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DocItem
|
<DocItem
|
||||||
description="Returns a promise that resolves with one of the connectivity types listed above."
|
description={
|
||||||
|
<AppText>
|
||||||
|
Returns a promise that resolves with an object of type <Code>ConnectionEventType</Code>.
|
||||||
|
</AppText>
|
||||||
|
}
|
||||||
example={{
|
example={{
|
||||||
code: `NetInfo.fetch().then((connectionType) => {
|
code: `NetInfo.getConnectionInfo().then(({ effectiveType, type }) => {
|
||||||
console.log('Connection type:', connectionType);
|
console.log('Effective connection type:', effectiveType);
|
||||||
|
console.log('Connection type:', type);
|
||||||
});`
|
});`
|
||||||
}}
|
}}
|
||||||
name="static fetch"
|
name="static getConnectionInfo"
|
||||||
typeInfo="() => Promise<string>"
|
typeInfo="() => Promise<ConnectionEventType>"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DocItem
|
<DocItem
|
||||||
@@ -76,7 +109,7 @@ const NetInfoScreen = () => (
|
|||||||
<DocItem
|
<DocItem
|
||||||
description="An object with the same methods as above but the listener receives a boolean which represents the internet connectivity. Use this if you are only interested with whether the device has internet connectivity."
|
description="An object with the same methods as above but the listener receives a boolean which represents the internet connectivity. Use this if you are only interested with whether the device has internet connectivity."
|
||||||
example={{
|
example={{
|
||||||
code: `NetInfo.isConnected.fetch().then((isConnected) => {
|
code: `NetInfo.isConnected.getConnectionInfo().then((isConnected) => {
|
||||||
console.log('Connection status:', (isConnected ? 'online' : 'offline'));
|
console.log('Connection status:', (isConnected ? 'online' : 'offline'));
|
||||||
});`
|
});`
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -4,16 +4,27 @@
|
|||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { bool } from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, Text } from 'react-native';
|
import { StyleSheet, Text } from 'react-native';
|
||||||
|
|
||||||
const AppText = ({ style, ...rest }) => (
|
class AppText extends React.PureComponent {
|
||||||
<Text
|
static contextTypes = {
|
||||||
{...rest}
|
isInAParentText: bool
|
||||||
accessibilityRole={rest.href ? 'link' : undefined}
|
};
|
||||||
style={[styles.baseText, style, rest.href && styles.link]}
|
|
||||||
/>
|
render() {
|
||||||
);
|
const { style, ...rest } = this.props;
|
||||||
|
const isInAParentText = this.context;
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
{...rest}
|
||||||
|
accessibilityRole={rest.href ? 'link' : undefined}
|
||||||
|
style={[!isInAParentText && styles.baseText, style, rest.href && styles.link]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default AppText;
|
export default AppText;
|
||||||
|
|
||||||
|
|||||||
4
jest-setup-framework.js
Normal file
4
jest-setup-framework.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import Enzyme from 'enzyme';
|
||||||
|
import Adapter from 'enzyme-adapter-react-16';
|
||||||
|
|
||||||
|
Enzyme.configure({ adapter: new Adapter() });
|
||||||
48
package.json
48
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-native-web",
|
"name": "react-native-web",
|
||||||
"version": "0.0.128",
|
"version": "0.1.9",
|
||||||
"description": "React Native for Web",
|
"description": "React Native for Web",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -44,8 +44,12 @@
|
|||||||
"jest": {
|
"jest": {
|
||||||
"testEnvironment": "jsdom",
|
"testEnvironment": "jsdom",
|
||||||
"timers": "fake",
|
"timers": "fake",
|
||||||
|
"setupFiles": [
|
||||||
|
"raf/polyfill"
|
||||||
|
],
|
||||||
|
"setupTestFrameworkScriptFile": "<rootDir>/jest-setup-framework.js",
|
||||||
"snapshotSerializers": [
|
"snapshotSerializers": [
|
||||||
"<rootDir>/node_modules/enzyme-to-json/serializer"
|
"enzyme-to-json/serializer"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
@@ -59,14 +63,14 @@
|
|||||||
"animated": "^0.2.0",
|
"animated": "^0.2.0",
|
||||||
"array-find-index": "^1.0.2",
|
"array-find-index": "^1.0.2",
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"create-react-class": "^15.6.0",
|
"create-react-class": "^15.6.2",
|
||||||
"debounce": "1.0.2",
|
"debounce": "1.0.2",
|
||||||
"deep-assign": "^2.0.0",
|
"deep-assign": "^2.0.0",
|
||||||
"fbjs": "^0.8.14",
|
"fbjs": "^0.8.16",
|
||||||
"hyphenate-style-name": "^1.0.2",
|
"hyphenate-style-name": "^1.0.2",
|
||||||
"inline-style-prefixer": "^3.0.7",
|
"inline-style-prefixer": "^3.0.8",
|
||||||
"normalize-css-color": "^1.0.2",
|
"normalize-css-color": "^1.0.2",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.6.0",
|
||||||
"react-timer-mixin": "^0.13.3"
|
"react-timer-mixin": "^0.13.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -75,31 +79,33 @@
|
|||||||
"babel-eslint": "^7.2.3",
|
"babel-eslint": "^7.2.3",
|
||||||
"babel-loader": "^7.1.2",
|
"babel-loader": "^7.1.2",
|
||||||
"babel-plugin-tester": "^4.0.0",
|
"babel-plugin-tester": "^4.0.0",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.8",
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.9",
|
||||||
"babel-preset-react-native": "^3.0.2",
|
"babel-preset-react-native": "^4.0.0",
|
||||||
"caniuse-api": "^2.0.0",
|
"caniuse-api": "^2.0.0",
|
||||||
"del-cli": "^1.1.0",
|
"del-cli": "^1.1.0",
|
||||||
"enzyme": "^2.9.1",
|
"enzyme": "^3.0.0",
|
||||||
"enzyme-to-json": "^1.5.1",
|
"enzyme-adapter-react-16": "^1.0.0",
|
||||||
|
"enzyme-to-json": "^3.0.1",
|
||||||
"eslint": "^4.6.1",
|
"eslint": "^4.6.1",
|
||||||
"eslint-config-prettier": "^2.4.0",
|
"eslint-config-prettier": "^2.6.0",
|
||||||
"eslint-plugin-promise": "^3.5.0",
|
"eslint-plugin-promise": "^3.5.0",
|
||||||
"eslint-plugin-react": "^7.3.0",
|
"eslint-plugin-react": "^7.4.0",
|
||||||
"file-loader": "^0.11.2",
|
"file-loader": "^1.1.4",
|
||||||
"flow-bin": "^0.49.1",
|
"flow-bin": "^0.49.1",
|
||||||
"jest": "^21.0.2",
|
"jest": "^21.2.1",
|
||||||
"lint-staged": "^4.1.3",
|
"lint-staged": "^4.1.3",
|
||||||
"prettier": "^1.6.1",
|
"prettier": "^1.7.3",
|
||||||
"react": "^15.6.1",
|
"raf": "^3.3.2",
|
||||||
"react-dom": "^15.6.1",
|
"react": "^16.0.0",
|
||||||
"react-test-renderer": "^15.6.1",
|
"react-dom": "^16.0.0",
|
||||||
|
"react-test-renderer": "^16.0.0",
|
||||||
"url-loader": "^0.5.9",
|
"url-loader": "^0.5.9",
|
||||||
"webpack": "^3.5.6",
|
"webpack": "^3.6.0",
|
||||||
"webpack-bundle-analyzer": "^2.9.0"
|
"webpack-bundle-analyzer": "^2.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "15.4.x || 15.5.x || 15.6.x",
|
"react": "16.x.x",
|
||||||
"react-dom": "15.4.x || 15.5.x || 15.6.x"
|
"react-dom": "16.x.x"
|
||||||
},
|
},
|
||||||
"author": "Nicolas Gallagher",
|
"author": "Nicolas Gallagher",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const browserList = {
|
|||||||
firefox: 40,
|
firefox: 40,
|
||||||
ios_saf: 7,
|
ios_saf: 7,
|
||||||
safari: 7,
|
safari: 7,
|
||||||
ie: 11,
|
ie: 10,
|
||||||
ie_mob: 11,
|
ie_mob: 11,
|
||||||
edge: 12,
|
edge: 12,
|
||||||
opera: 16,
|
opera: 16,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ exports[`apis/AppRegistry/renderApplication getApplication 3`] = `
|
|||||||
.rn-textAlign-1ttztb7{text-align:inherit}
|
.rn-textAlign-1ttztb7{text-align:inherit}
|
||||||
.rn-textDecoration-bauka4{text-decoration:none}
|
.rn-textDecoration-bauka4{text-decoration:none}
|
||||||
.rn-listStyle-1ebb2ja{list-style:none}
|
.rn-listStyle-1ebb2ja{list-style:none}
|
||||||
.rn-alignItems-1oszu61{-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
|
.rn-alignItems-1oszu61{-ms-flex-align:stretch;-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
|
||||||
.rn-borderTopStyle-1efd50x{border-top-style:solid}
|
.rn-borderTopStyle-1efd50x{border-top-style:solid}
|
||||||
.rn-borderRightStyle-14skgim{border-right-style:solid}
|
.rn-borderRightStyle-14skgim{border-right-style:solid}
|
||||||
.rn-borderBottomStyle-rull8r{border-bottom-style:solid}
|
.rn-borderBottomStyle-rull8r{border-bottom-style:solid}
|
||||||
@@ -50,10 +50,10 @@ exports[`apis/AppRegistry/renderApplication getApplication 3`] = `
|
|||||||
.rn-boxSizing-deolkf{box-sizing:border-box}
|
.rn-boxSizing-deolkf{box-sizing:border-box}
|
||||||
.rn-display-6koalj{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}
|
.rn-display-6koalj{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}
|
||||||
.rn-display-xoduu5{display:-webkit-inline-box;display:-moz-inline-box;display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}
|
.rn-display-xoduu5{display:-webkit-inline-box;display:-moz-inline-box;display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}
|
||||||
.rn-flexShrink-1pxmb3b{-webkit-flex-shrink:0 !important;flex-shrink:0 !important}
|
.rn-flexShrink-1pxmb3b{-ms-flex-negative:0 !important;-webkit-flex-shrink:0 !important;flex-shrink:0 !important}
|
||||||
.rn-flexShrink-1awmn5t{-webkit-flex-shrink:1 !important;flex-shrink:1 !important}
|
.rn-flexShrink-1awmn5t{-ms-flex-negative:1 !important;-webkit-flex-shrink:1 !important;flex-shrink:1 !important}
|
||||||
.rn-flexBasis-7vfszb{-webkit-flex-basis:auto !important;flex-basis:auto !important}
|
.rn-flexBasis-7vfszb{-ms-flex-preferred-size:auto !important;-webkit-flex-basis:auto !important;flex-basis:auto !important}
|
||||||
.rn-flexDirection-eqz5dr{-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
|
.rn-flexDirection-eqz5dr{-ms-flex-direction:column;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
|
||||||
.rn-marginTop-1mnahxq{margin-top:0px}
|
.rn-marginTop-1mnahxq{margin-top:0px}
|
||||||
.rn-marginRight-61z16t{margin-right:0px}
|
.rn-marginRight-61z16t{margin-right:0px}
|
||||||
.rn-marginBottom-p1pxzi{margin-bottom:0px}
|
.rn-marginBottom-p1pxzi{margin-bottom:0px}
|
||||||
@@ -66,6 +66,6 @@ exports[`apis/AppRegistry/renderApplication getApplication 3`] = `
|
|||||||
.rn-paddingLeft-gy4na3{padding-left:0px}
|
.rn-paddingLeft-gy4na3{padding-left:0px}
|
||||||
.rn-zIndex-1lgpqti{z-index:0}
|
.rn-zIndex-1lgpqti{z-index:0}
|
||||||
.rn-zIndex-1wyyakw{z-index:-1}
|
.rn-zIndex-1wyyakw{z-index:-1}
|
||||||
.rn-flex-13awgt0{-webkit-flex:1;flex:1}
|
.rn-flex-13awgt0{-ms-flex:1;-webkit-flex:1;flex:1}
|
||||||
.rn-flexGrow-1m1wadx{-webkit-flex-grow:1 !important;flex-grow:1 !important}</style>"
|
.rn-flexGrow-1m1wadx{-ms-flex-positive:1 !important;-webkit-flex-grow:1 !important;flex-grow:1 !important}</style>"
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ export default class AsyncStorage {
|
|||||||
}, callback);
|
}, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (stub) Flushes any pending requests using a single batch call to get the data.
|
||||||
|
*/
|
||||||
|
static flushGetRequests() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets *all* keys known to the app, for all callers, libraries, etc.
|
* Gets *all* keys known to the app, for all callers, libraries, etc.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
function emptyFunction() {}
|
function emptyFunction() {}
|
||||||
|
|
||||||
const BackAndroid = {
|
const BackHandler = {
|
||||||
exitApp: emptyFunction,
|
exitApp: emptyFunction,
|
||||||
addEventListener() {
|
addEventListener() {
|
||||||
return {
|
return {
|
||||||
@@ -22,4 +22,4 @@ const BackAndroid = {
|
|||||||
removeEventListener: emptyFunction
|
removeEventListener: emptyFunction
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BackAndroid;
|
export default BackHandler;
|
||||||
@@ -3,31 +3,44 @@
|
|||||||
import NetInfo from '..';
|
import NetInfo from '..';
|
||||||
|
|
||||||
describe('apis/NetInfo', () => {
|
describe('apis/NetInfo', () => {
|
||||||
|
describe('getConnectionInfo', () => {
|
||||||
|
test('fills out basic fields', done => {
|
||||||
|
NetInfo.getConnectionInfo().then(result => {
|
||||||
|
expect(result.effectiveType).toBeDefined();
|
||||||
|
expect(result.type).toBeDefined();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('isConnected', () => {
|
describe('isConnected', () => {
|
||||||
const handler = () => {};
|
const handler = () => {};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
try {
|
try {
|
||||||
NetInfo.isConnected.removeEventListener('change', handler);
|
NetInfo.isConnected.removeEventListener('connectionChange', handler);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('addEventListener', () => {
|
describe('addEventListener', () => {
|
||||||
test('throws if the provided "eventType" is not supported', () => {
|
test('throws if the provided "eventType" is not supported', () => {
|
||||||
expect(() => NetInfo.isConnected.addEventListener('foo', handler)).toThrow();
|
expect(() => NetInfo.isConnected.addEventListener('foo', handler)).toThrow();
|
||||||
expect(() => NetInfo.isConnected.addEventListener('change', handler)).not.toThrow();
|
expect(() =>
|
||||||
|
NetInfo.isConnected.addEventListener('connectionChange', handler)
|
||||||
|
).not.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeEventListener', () => {
|
describe('removeEventListener', () => {
|
||||||
test('throws if the handler is not registered', () => {
|
test('throws if the handler is not registered', () => {
|
||||||
expect(() => NetInfo.isConnected.removeEventListener('change', handler)).toThrow;
|
expect(() => NetInfo.isConnected.removeEventListener('connectionChange', handler)).toThrow;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('throws if the provided "eventType" is not supported', () => {
|
test('throws if the provided "eventType" is not supported', () => {
|
||||||
NetInfo.isConnected.addEventListener('change', handler);
|
NetInfo.isConnected.addEventListener('connectionChange', handler);
|
||||||
expect(() => NetInfo.isConnected.removeEventListener('foo', handler)).toThrow;
|
expect(() => NetInfo.isConnected.removeEventListener('foo', handler)).toThrow;
|
||||||
expect(() => NetInfo.isConnected.removeEventListener('change', handler)).not.toThrow;
|
expect(() => NetInfo.isConnected.removeEventListener('connectionChange', handler)).not
|
||||||
|
.toThrow;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,27 @@ const connection =
|
|||||||
window.navigator.mozConnection ||
|
window.navigator.mozConnection ||
|
||||||
window.navigator.webkitConnection);
|
window.navigator.webkitConnection);
|
||||||
|
|
||||||
const eventTypes = ['change'];
|
// Prevent the underlying event handlers from leaking and include additional
|
||||||
|
// properties available in browsers
|
||||||
|
const getConnectionInfoObject = () => {
|
||||||
|
const result = {};
|
||||||
|
if (!connection) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (const prop in connection) {
|
||||||
|
if (typeof connection[prop] !== 'function') {
|
||||||
|
result[prop] = connection[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Map React Native events to browser equivalents
|
||||||
|
const eventTypesMap = {
|
||||||
|
change: 'change',
|
||||||
|
connectionChange: 'change'
|
||||||
|
};
|
||||||
|
const eventTypes = Object.keys(eventTypesMap);
|
||||||
|
|
||||||
const connectionListeners = [];
|
const connectionListeners = [];
|
||||||
|
|
||||||
@@ -31,6 +51,9 @@ const connectionListeners = [];
|
|||||||
const NetInfo = {
|
const NetInfo = {
|
||||||
addEventListener(type: string, handler: Function): { remove: () => void } {
|
addEventListener(type: string, handler: Function): { remove: () => void } {
|
||||||
invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type);
|
invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type);
|
||||||
|
if (type === 'change') {
|
||||||
|
console.warn('Listening to event `change` is deprecated. Use `connectionChange` instead.');
|
||||||
|
}
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
console.error(
|
console.error(
|
||||||
'Network Connection API is not supported. Not listening for connection type changes.'
|
'Network Connection API is not supported. Not listening for connection type changes.'
|
||||||
@@ -40,21 +63,25 @@ const NetInfo = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.addEventListener(type, handler);
|
connection.addEventListener(eventTypesMap[type], handler);
|
||||||
return {
|
return {
|
||||||
remove: () => NetInfo.removeEventListener(type, handler)
|
remove: () => NetInfo.removeEventListener(eventTypesMap[type], handler)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
removeEventListener(type: string, handler: Function): void {
|
removeEventListener(type: string, handler: Function): void {
|
||||||
invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type);
|
invariant(eventTypes.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type);
|
||||||
|
if (type === 'change') {
|
||||||
|
console.warn('Listening to event `change` is deprecated. Use `connectionChange` instead.');
|
||||||
|
}
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connection.removeEventListener(type, handler);
|
connection.removeEventListener(eventTypesMap[type], handler);
|
||||||
},
|
},
|
||||||
|
|
||||||
fetch(): Promise<any> {
|
fetch(): Promise<any> {
|
||||||
|
console.warn('`fetch` is deprecated. Use `getConnectionInfo` instead.');
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
resolve(connection.type);
|
resolve(connection.type);
|
||||||
@@ -64,6 +91,16 @@ const NetInfo = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getConnectionInfo(): Promise<Object> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve({
|
||||||
|
effectiveType: 'unknown',
|
||||||
|
type: 'unknown',
|
||||||
|
...getConnectionInfoObject()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
isConnected: {
|
isConnected: {
|
||||||
addEventListener(type: string, handler: Function): { remove: () => void } {
|
addEventListener(type: string, handler: Function): { remove: () => void } {
|
||||||
invariant(
|
invariant(
|
||||||
@@ -71,6 +108,10 @@ const NetInfo = {
|
|||||||
'Trying to subscribe to unknown event: "%s"',
|
'Trying to subscribe to unknown event: "%s"',
|
||||||
type
|
type
|
||||||
);
|
);
|
||||||
|
if (type === 'change') {
|
||||||
|
console.warn('Listening to event `change` is deprecated. Use `connectionChange` instead.');
|
||||||
|
}
|
||||||
|
|
||||||
const onlineCallback = () => handler(true);
|
const onlineCallback = () => handler(true);
|
||||||
const offlineCallback = () => handler(false);
|
const offlineCallback = () => handler(false);
|
||||||
connectionListeners.push([handler, onlineCallback, offlineCallback]);
|
connectionListeners.push([handler, onlineCallback, offlineCallback]);
|
||||||
@@ -79,7 +120,7 @@ const NetInfo = {
|
|||||||
window.addEventListener('offline', offlineCallback, false);
|
window.addEventListener('offline', offlineCallback, false);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
remove: () => NetInfo.isConnected.removeEventListener(type, handler)
|
remove: () => NetInfo.isConnected.removeEventListener(eventTypesMap[type], handler)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -89,6 +130,9 @@ const NetInfo = {
|
|||||||
'Trying to subscribe to unknown event: "%s"',
|
'Trying to subscribe to unknown event: "%s"',
|
||||||
type
|
type
|
||||||
);
|
);
|
||||||
|
if (type === 'change') {
|
||||||
|
console.warn('Listening to event `change` is deprecated. Use `connectionChange` instead.');
|
||||||
|
}
|
||||||
|
|
||||||
const listenerIndex = findIndex(connectionListeners, pair => pair[0] === handler);
|
const listenerIndex = findIndex(connectionListeners, pair => pair[0] === handler);
|
||||||
invariant(
|
invariant(
|
||||||
@@ -103,7 +147,12 @@ const NetInfo = {
|
|||||||
connectionListeners.splice(listenerIndex, 1);
|
connectionListeners.splice(listenerIndex, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
fetch(): Promise<any> {
|
fetch(): Promise<boolean> {
|
||||||
|
console.warn('`fetch` is deprecated. Use `getConnectionInfo` instead.');
|
||||||
|
return NetInfo.isConnected.getConnectionInfo();
|
||||||
|
},
|
||||||
|
|
||||||
|
getConnectionInfo(): Promise<boolean> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
resolve(window.navigator.onLine);
|
resolve(window.navigator.onLine);
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ StyleSheetValidation.addValidStylePropTypes({
|
|||||||
borderSpacing: oneOf([number, string]),
|
borderSpacing: oneOf([number, string]),
|
||||||
clear: string,
|
clear: string,
|
||||||
cursor: string,
|
cursor: string,
|
||||||
|
fill: string,
|
||||||
float: oneOf(['left', 'none', 'right']),
|
float: oneOf(['left', 'none', 'right']),
|
||||||
font: string /* @private */,
|
font: string /* @private */,
|
||||||
listStyle: string,
|
listStyle: string,
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ import ViewPropTypes from '../View/ViewPropTypes';
|
|||||||
import { bool, number, oneOf, oneOfType, string } from 'prop-types';
|
import { bool, number, oneOf, oneOfType, string } from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
const createSvgCircle = style => (
|
||||||
|
<circle cx="16" cy="16" fill="none" r="14" strokeWidth="4" style={style} />
|
||||||
|
);
|
||||||
|
|
||||||
class ActivityIndicator extends Component {
|
class ActivityIndicator extends Component {
|
||||||
static displayName = 'ActivityIndicator';
|
static displayName = 'ActivityIndicator';
|
||||||
|
|
||||||
@@ -40,29 +44,15 @@ class ActivityIndicator extends Component {
|
|||||||
|
|
||||||
const svg = (
|
const svg = (
|
||||||
<svg height="100%" viewBox="0 0 32 32" width="100%">
|
<svg height="100%" viewBox="0 0 32 32" width="100%">
|
||||||
<circle
|
{createSvgCircle({
|
||||||
cx="16"
|
stroke: color,
|
||||||
cy="16"
|
opacity: 0.2
|
||||||
fill="none"
|
})}
|
||||||
r="14"
|
{createSvgCircle({
|
||||||
strokeWidth="4"
|
stroke: color,
|
||||||
style={{
|
strokeDasharray: 80,
|
||||||
stroke: color,
|
strokeDashoffset: 60
|
||||||
opacity: 0.2
|
})}
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<circle
|
|
||||||
cx="16"
|
|
||||||
cy="16"
|
|
||||||
fill="none"
|
|
||||||
r="14"
|
|
||||||
strokeWidth="4"
|
|
||||||
style={{
|
|
||||||
stroke: color,
|
|
||||||
strokeDasharray: 80,
|
|
||||||
strokeDashoffset: 60
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -19,21 +19,21 @@ describe('components/Switch', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
describe('onValueChange', () => {
|
describe('onValueChange', () => {
|
||||||
test('when value is "false" it receives "true"', () => {
|
test('when value is "false" it receives "true"', () => {
|
||||||
const handleValueChange = (value) => expect(value === true).toBeTruthy();
|
const onValueChange = jest.fn();
|
||||||
const component = shallow(<Switch onValueChange={handleValueChange} value={false} />);
|
const component = shallow(<Switch onValueChange={onValueChange} value={false} />);
|
||||||
component.find('input').simulate('click');
|
component.find('input').simulate('change', { nativeEvent: { target: { checked: true } } });
|
||||||
|
expect(onValueChange).toHaveBeenCalledWith(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('when value is "true" it receives "false"', () => {
|
test('when value is "true" it receives "false"', () => {
|
||||||
const handleValueChange = (value) => expect(value === false).toBeTruthy();
|
const onValueChange = jest.fn();
|
||||||
const component = shallow(<Switch onValueChange={handleValueChange} value />);
|
const component = shallow(<Switch onValueChange={onValueChange} value />);
|
||||||
component.find('input').simulate('click');
|
component.find('input').simulate('change', { nativeEvent: { target: { checked: false } } });
|
||||||
|
expect(onValueChange).toHaveBeenCalledWith(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
describe('value', () => {
|
describe('value', () => {
|
||||||
test('when "false" an unchecked checkbox is rendered', () => {
|
test('when "false" an unchecked checkbox is rendered', () => {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const TextStylePropTypes = {
|
|||||||
letterSpacing: numberOrString,
|
letterSpacing: numberOrString,
|
||||||
lineHeight: numberOrString,
|
lineHeight: numberOrString,
|
||||||
textAlign: TextAlignPropType,
|
textAlign: TextAlignPropType,
|
||||||
textAlignVertical: oneOf(['auto', 'bottom', 'center', 'top']),
|
textAlignVertical: string,
|
||||||
textDecorationColor: ColorPropType,
|
textDecorationColor: ColorPropType,
|
||||||
textDecorationLine: string,
|
textDecorationLine: string,
|
||||||
textDecorationStyle: string,
|
textDecorationStyle: string,
|
||||||
|
|||||||
@@ -366,12 +366,12 @@ describe('components/TextInput', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// default selection is 0
|
// default selection is 0
|
||||||
expect(inputDefaultSelection.node.selectionStart).toEqual(0);
|
expect(inputDefaultSelection.instance().selectionStart).toEqual(0);
|
||||||
expect(inputDefaultSelection.node.selectionEnd).toEqual(0);
|
expect(inputDefaultSelection.instance().selectionEnd).toEqual(0);
|
||||||
|
|
||||||
// custom selection sets cursor at custom position
|
// custom selection sets cursor at custom position
|
||||||
expect(inputCustomSelection.node.selectionStart).toEqual(cursorLocation.start);
|
expect(inputCustomSelection.instance().selectionStart).toEqual(cursorLocation.start);
|
||||||
expect(inputCustomSelection.node.selectionEnd).toEqual(cursorLocation.end);
|
expect(inputCustomSelection.instance().selectionEnd).toEqual(cursorLocation.end);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ class View extends Component {
|
|||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
React.Children.toArray(this.props.children).forEach(item => {
|
React.Children.toArray(this.props.children).forEach(item => {
|
||||||
invariant(typeof item !== 'string', 'A text node cannot be a child of a <View>');
|
invariant(
|
||||||
|
typeof item !== 'string',
|
||||||
|
`Unexpected text node: ${item}. A text node cannot be a child of a <View>.`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
134
src/index.js
134
src/index.js
@@ -1,134 +1,2 @@
|
|||||||
import {
|
import ReactNative from './module';
|
||||||
// top-level API
|
|
||||||
findNodeHandle,
|
|
||||||
render,
|
|
||||||
unmountComponentAtNode,
|
|
||||||
|
|
||||||
// modules
|
|
||||||
createElement,
|
|
||||||
NativeModules,
|
|
||||||
processColor,
|
|
||||||
|
|
||||||
// APIs
|
|
||||||
Animated,
|
|
||||||
AppRegistry,
|
|
||||||
AppState,
|
|
||||||
AsyncStorage,
|
|
||||||
BackAndroid,
|
|
||||||
Clipboard,
|
|
||||||
Dimensions,
|
|
||||||
Easing,
|
|
||||||
I18nManager,
|
|
||||||
InteractionManager,
|
|
||||||
Keyboard,
|
|
||||||
Linking,
|
|
||||||
NetInfo,
|
|
||||||
PanResponder,
|
|
||||||
PixelRatio,
|
|
||||||
Platform,
|
|
||||||
StyleSheet,
|
|
||||||
UIManager,
|
|
||||||
Vibration,
|
|
||||||
|
|
||||||
// components
|
|
||||||
ActivityIndicator,
|
|
||||||
Button,
|
|
||||||
FlatList,
|
|
||||||
Image,
|
|
||||||
KeyboardAvoidingView,
|
|
||||||
ListView,
|
|
||||||
Modal,
|
|
||||||
Picker,
|
|
||||||
ProgressBar,
|
|
||||||
RefreshControl,
|
|
||||||
ScrollView,
|
|
||||||
SectionList,
|
|
||||||
Slider,
|
|
||||||
StatusBar,
|
|
||||||
Switch,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Touchable,
|
|
||||||
TouchableHighlight,
|
|
||||||
TouchableNativeFeedback,
|
|
||||||
TouchableOpacity,
|
|
||||||
TouchableWithoutFeedback,
|
|
||||||
View,
|
|
||||||
VirtualizedList,
|
|
||||||
|
|
||||||
// propTypes
|
|
||||||
ColorPropType,
|
|
||||||
EdgeInsetsPropType,
|
|
||||||
PointPropType,
|
|
||||||
TextPropTypes,
|
|
||||||
ViewPropTypes
|
|
||||||
} from './module';
|
|
||||||
|
|
||||||
const ReactNative = {
|
|
||||||
// top-level API
|
|
||||||
findNodeHandle,
|
|
||||||
render,
|
|
||||||
unmountComponentAtNode,
|
|
||||||
|
|
||||||
// modules
|
|
||||||
createElement,
|
|
||||||
NativeModules,
|
|
||||||
processColor,
|
|
||||||
|
|
||||||
// APIs
|
|
||||||
Animated,
|
|
||||||
AppRegistry,
|
|
||||||
AppState,
|
|
||||||
AsyncStorage,
|
|
||||||
BackAndroid,
|
|
||||||
BackHandler: BackAndroid,
|
|
||||||
Clipboard,
|
|
||||||
Dimensions,
|
|
||||||
Easing,
|
|
||||||
I18nManager,
|
|
||||||
InteractionManager,
|
|
||||||
Keyboard,
|
|
||||||
Linking,
|
|
||||||
NetInfo,
|
|
||||||
PanResponder,
|
|
||||||
PixelRatio,
|
|
||||||
Platform,
|
|
||||||
StyleSheet,
|
|
||||||
UIManager,
|
|
||||||
Vibration,
|
|
||||||
|
|
||||||
// components
|
|
||||||
ActivityIndicator,
|
|
||||||
Button,
|
|
||||||
FlatList,
|
|
||||||
Image,
|
|
||||||
KeyboardAvoidingView,
|
|
||||||
ListView,
|
|
||||||
Modal,
|
|
||||||
Picker,
|
|
||||||
ProgressBar,
|
|
||||||
RefreshControl,
|
|
||||||
ScrollView,
|
|
||||||
SectionList,
|
|
||||||
Slider,
|
|
||||||
StatusBar,
|
|
||||||
Switch,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Touchable,
|
|
||||||
TouchableHighlight,
|
|
||||||
TouchableNativeFeedback,
|
|
||||||
TouchableOpacity,
|
|
||||||
TouchableWithoutFeedback,
|
|
||||||
View,
|
|
||||||
VirtualizedList,
|
|
||||||
|
|
||||||
// propTypes
|
|
||||||
ColorPropType,
|
|
||||||
EdgeInsetsPropType,
|
|
||||||
PointPropType,
|
|
||||||
TextPropTypes,
|
|
||||||
ViewPropTypes
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = ReactNative;
|
module.exports = ReactNative;
|
||||||
|
|||||||
240
src/module.js
240
src/module.js
@@ -1,61 +1,191 @@
|
|||||||
export { default as createElement } from './modules/createElement';
|
import createElement from './modules/createElement';
|
||||||
export { default as findNodeHandle } from './modules/findNodeHandle';
|
import findNodeHandle from './modules/findNodeHandle';
|
||||||
export { default as NativeModules } from './modules/NativeModules';
|
import NativeModules from './modules/NativeModules';
|
||||||
export { default as processColor } from './modules/processColor';
|
import processColor from './modules/processColor';
|
||||||
export { render, unmountComponentAtNode } from 'react-dom';
|
import { hydrate, render, unmountComponentAtNode } from 'react-dom';
|
||||||
|
|
||||||
// APIs
|
// APIs
|
||||||
export { default as Animated } from './apis/Animated';
|
import Animated from './apis/Animated';
|
||||||
export { default as AppRegistry } from './apis/AppRegistry';
|
import AppRegistry from './apis/AppRegistry';
|
||||||
export { default as AppState } from './apis/AppState';
|
import AppState from './apis/AppState';
|
||||||
export { default as AsyncStorage } from './apis/AsyncStorage';
|
import AsyncStorage from './apis/AsyncStorage';
|
||||||
export { default as BackAndroid } from './apis/BackAndroid';
|
import BackHandler from './apis/BackHandler';
|
||||||
export { default as Clipboard } from './apis/Clipboard';
|
import Clipboard from './apis/Clipboard';
|
||||||
export { default as Dimensions } from './apis/Dimensions';
|
import Dimensions from './apis/Dimensions';
|
||||||
export { default as Easing } from './apis/Easing';
|
import Easing from './apis/Easing';
|
||||||
export { default as I18nManager } from './apis/I18nManager';
|
import I18nManager from './apis/I18nManager';
|
||||||
export { default as Keyboard } from './apis/Keyboard';
|
import Keyboard from './apis/Keyboard';
|
||||||
export { default as InteractionManager } from './apis/InteractionManager';
|
import InteractionManager from './apis/InteractionManager';
|
||||||
export { default as Linking } from './apis/Linking';
|
import Linking from './apis/Linking';
|
||||||
export { default as NetInfo } from './apis/NetInfo';
|
import NetInfo from './apis/NetInfo';
|
||||||
export { default as PanResponder } from './apis/PanResponder';
|
import PanResponder from './apis/PanResponder';
|
||||||
export { default as PixelRatio } from './apis/PixelRatio';
|
import PixelRatio from './apis/PixelRatio';
|
||||||
export { default as Platform } from './apis/Platform';
|
import Platform from './apis/Platform';
|
||||||
export { default as StyleSheet } from './apis/StyleSheet';
|
import StyleSheet from './apis/StyleSheet';
|
||||||
export { default as UIManager } from './apis/UIManager';
|
import UIManager from './apis/UIManager';
|
||||||
export { default as Vibration } from './apis/Vibration';
|
import Vibration from './apis/Vibration';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
export { default as ActivityIndicator } from './components/ActivityIndicator';
|
import ActivityIndicator from './components/ActivityIndicator';
|
||||||
export { default as Button } from './components/Button';
|
import Button from './components/Button';
|
||||||
export { default as FlatList } from './components/FlatList';
|
import FlatList from './components/FlatList';
|
||||||
export { default as Image } from './components/Image';
|
import Image from './components/Image';
|
||||||
export { default as KeyboardAvoidingView } from './components/KeyboardAvoidingView';
|
import KeyboardAvoidingView from './components/KeyboardAvoidingView';
|
||||||
export { default as ListView } from './components/ListView';
|
import ListView from './components/ListView';
|
||||||
export { default as Modal } from './components/Modal';
|
import Modal from './components/Modal';
|
||||||
export { default as Picker } from './components/Picker';
|
import Picker from './components/Picker';
|
||||||
export { default as ProgressBar } from './components/ProgressBar';
|
import ProgressBar from './components/ProgressBar';
|
||||||
export { default as RefreshControl } from './components/RefreshControl';
|
import RefreshControl from './components/RefreshControl';
|
||||||
export { default as ScrollView } from './components/ScrollView';
|
import ScrollView from './components/ScrollView';
|
||||||
export { default as SectionList } from './components/SectionList';
|
import SectionList from './components/SectionList';
|
||||||
export { default as Slider } from './components/Slider';
|
import Slider from './components/Slider';
|
||||||
export { default as StatusBar } from './components/StatusBar';
|
import StatusBar from './components/StatusBar';
|
||||||
export { default as Switch } from './components/Switch';
|
import Switch from './components/Switch';
|
||||||
export { default as Text } from './components/Text';
|
import Text from './components/Text';
|
||||||
export { default as TextInput } from './components/TextInput';
|
import TextInput from './components/TextInput';
|
||||||
export { default as Touchable } from './components/Touchable/Touchable';
|
import Touchable from './components/Touchable/Touchable';
|
||||||
export { default as TouchableHighlight } from './components/Touchable/TouchableHighlight';
|
import TouchableHighlight from './components/Touchable/TouchableHighlight';
|
||||||
export { default as TouchableNativeFeedback } from './components/Touchable/TouchableNativeFeedback';
|
import TouchableNativeFeedback from './components/Touchable/TouchableNativeFeedback';
|
||||||
export { default as TouchableOpacity } from './components/Touchable/TouchableOpacity';
|
import TouchableOpacity from './components/Touchable/TouchableOpacity';
|
||||||
export {
|
import TouchableWithoutFeedback from './components/Touchable/TouchableWithoutFeedback';
|
||||||
default as TouchableWithoutFeedback
|
import View from './components/View';
|
||||||
} from './components/Touchable/TouchableWithoutFeedback';
|
import VirtualizedList from './components/VirtualizedList';
|
||||||
export { default as View } from './components/View';
|
|
||||||
export { default as VirtualizedList } from './components/VirtualizedList';
|
|
||||||
|
|
||||||
// propTypes
|
// propTypes
|
||||||
export { default as ColorPropType } from './propTypes/ColorPropType';
|
import ColorPropType from './propTypes/ColorPropType';
|
||||||
export { default as EdgeInsetsPropType } from './propTypes/EdgeInsetsPropType';
|
import EdgeInsetsPropType from './propTypes/EdgeInsetsPropType';
|
||||||
export { default as PointPropType } from './propTypes/PointPropType';
|
import PointPropType from './propTypes/PointPropType';
|
||||||
export { default as TextPropTypes } from './components/Text/TextPropTypes';
|
import TextPropTypes from './components/Text/TextPropTypes';
|
||||||
export { default as ViewPropTypes } from './components/View/ViewPropTypes';
|
import ViewPropTypes from './components/View/ViewPropTypes';
|
||||||
|
|
||||||
|
export {
|
||||||
|
// top-level API
|
||||||
|
findNodeHandle,
|
||||||
|
hydrate,
|
||||||
|
render,
|
||||||
|
unmountComponentAtNode,
|
||||||
|
// modules
|
||||||
|
createElement,
|
||||||
|
NativeModules,
|
||||||
|
processColor,
|
||||||
|
// APIs
|
||||||
|
Animated,
|
||||||
|
AppRegistry,
|
||||||
|
AppState,
|
||||||
|
AsyncStorage,
|
||||||
|
BackHandler,
|
||||||
|
Clipboard,
|
||||||
|
Dimensions,
|
||||||
|
Easing,
|
||||||
|
I18nManager,
|
||||||
|
InteractionManager,
|
||||||
|
Keyboard,
|
||||||
|
Linking,
|
||||||
|
NetInfo,
|
||||||
|
PanResponder,
|
||||||
|
PixelRatio,
|
||||||
|
Platform,
|
||||||
|
StyleSheet,
|
||||||
|
UIManager,
|
||||||
|
Vibration,
|
||||||
|
// components
|
||||||
|
ActivityIndicator,
|
||||||
|
Button,
|
||||||
|
FlatList,
|
||||||
|
Image,
|
||||||
|
KeyboardAvoidingView,
|
||||||
|
ListView,
|
||||||
|
Modal,
|
||||||
|
Picker,
|
||||||
|
ProgressBar,
|
||||||
|
RefreshControl,
|
||||||
|
ScrollView,
|
||||||
|
SectionList,
|
||||||
|
Slider,
|
||||||
|
StatusBar,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Touchable,
|
||||||
|
TouchableHighlight,
|
||||||
|
TouchableNativeFeedback,
|
||||||
|
TouchableOpacity,
|
||||||
|
TouchableWithoutFeedback,
|
||||||
|
View,
|
||||||
|
VirtualizedList,
|
||||||
|
// propTypes
|
||||||
|
ColorPropType,
|
||||||
|
EdgeInsetsPropType,
|
||||||
|
PointPropType,
|
||||||
|
TextPropTypes,
|
||||||
|
ViewPropTypes
|
||||||
|
};
|
||||||
|
|
||||||
|
const ReactNative = {
|
||||||
|
// top-level API
|
||||||
|
findNodeHandle,
|
||||||
|
hydrate,
|
||||||
|
render,
|
||||||
|
unmountComponentAtNode,
|
||||||
|
|
||||||
|
// modules
|
||||||
|
createElement,
|
||||||
|
NativeModules,
|
||||||
|
processColor,
|
||||||
|
|
||||||
|
// APIs
|
||||||
|
Animated,
|
||||||
|
AppRegistry,
|
||||||
|
AppState,
|
||||||
|
AsyncStorage,
|
||||||
|
BackHandler,
|
||||||
|
Clipboard,
|
||||||
|
Dimensions,
|
||||||
|
Easing,
|
||||||
|
I18nManager,
|
||||||
|
InteractionManager,
|
||||||
|
Keyboard,
|
||||||
|
Linking,
|
||||||
|
NetInfo,
|
||||||
|
PanResponder,
|
||||||
|
PixelRatio,
|
||||||
|
Platform,
|
||||||
|
StyleSheet,
|
||||||
|
UIManager,
|
||||||
|
Vibration,
|
||||||
|
|
||||||
|
// components
|
||||||
|
ActivityIndicator,
|
||||||
|
Button,
|
||||||
|
FlatList,
|
||||||
|
Image,
|
||||||
|
KeyboardAvoidingView,
|
||||||
|
ListView,
|
||||||
|
Modal,
|
||||||
|
Picker,
|
||||||
|
ProgressBar,
|
||||||
|
RefreshControl,
|
||||||
|
ScrollView,
|
||||||
|
SectionList,
|
||||||
|
Slider,
|
||||||
|
StatusBar,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Touchable,
|
||||||
|
TouchableHighlight,
|
||||||
|
TouchableNativeFeedback,
|
||||||
|
TouchableOpacity,
|
||||||
|
TouchableWithoutFeedback,
|
||||||
|
View,
|
||||||
|
VirtualizedList,
|
||||||
|
|
||||||
|
// propTypes
|
||||||
|
ColorPropType,
|
||||||
|
EdgeInsetsPropType,
|
||||||
|
PointPropType,
|
||||||
|
TextPropTypes,
|
||||||
|
ViewPropTypes
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReactNative;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const ImageLoader = {
|
|||||||
getSize(uri, success, failure) {
|
getSize(uri, success, failure) {
|
||||||
let complete = false;
|
let complete = false;
|
||||||
const interval = setInterval(callback, 16);
|
const interval = setInterval(callback, 16);
|
||||||
const requestId = ImageLoader.load(uri, callback, callback);
|
const requestId = ImageLoader.load(uri, callback, errorCallback);
|
||||||
|
|
||||||
function callback() {
|
function callback() {
|
||||||
const image = requests[`${requestId}`];
|
const image = requests[`${requestId}`];
|
||||||
@@ -38,6 +38,14 @@ const ImageLoader = {
|
|||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function errorCallback() {
|
||||||
|
if (typeof failure === 'function') {
|
||||||
|
failure();
|
||||||
|
}
|
||||||
|
ImageLoader.abort(requestId);
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
load(uri, onLoad, onError): number {
|
load(uri, onLoad, onError): number {
|
||||||
id += 1;
|
id += 1;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
// based on https://github.com/facebook/react/pull/4303/files
|
// based on https://github.com/facebook/react/pull/4303/files
|
||||||
|
|
||||||
import EventPluginHub from 'react-dom/lib/EventPluginHub';
|
|
||||||
import normalizeNativeEvent from '../normalizeNativeEvent';
|
import normalizeNativeEvent from '../normalizeNativeEvent';
|
||||||
import ResponderEventPlugin from 'react-dom/lib/ResponderEventPlugin';
|
import ReactDOM from 'react-dom';
|
||||||
import ResponderTouchHistoryStore from 'react-dom/lib/ResponderTouchHistoryStore';
|
import ReactDOMUnstableNativeDependencies from 'react-dom/unstable-native-dependencies';
|
||||||
|
|
||||||
|
const { EventPluginHub } = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
||||||
|
const { ResponderEventPlugin, ResponderTouchHistoryStore } = ReactDOMUnstableNativeDependencies;
|
||||||
|
|
||||||
const topMouseDown = 'topMouseDown';
|
const topMouseDown = 'topMouseDown';
|
||||||
const topMouseMove = 'topMouseMove';
|
const topMouseMove = 'topMouseMove';
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import crossFade from 'inline-style-prefixer/static/plugins/crossFade';
|
|||||||
import cursor from 'inline-style-prefixer/static/plugins/cursor';
|
import cursor from 'inline-style-prefixer/static/plugins/cursor';
|
||||||
import filter from 'inline-style-prefixer/static/plugins/filter';
|
import filter from 'inline-style-prefixer/static/plugins/filter';
|
||||||
import flex from 'inline-style-prefixer/static/plugins/flex';
|
import flex from 'inline-style-prefixer/static/plugins/flex';
|
||||||
|
import flexboxIE from 'inline-style-prefixer/static/plugins/flexboxIE';
|
||||||
import flexboxOld from 'inline-style-prefixer/static/plugins/flexboxOld';
|
import flexboxOld from 'inline-style-prefixer/static/plugins/flexboxOld';
|
||||||
import gradient from 'inline-style-prefixer/static/plugins/gradient';
|
import gradient from 'inline-style-prefixer/static/plugins/gradient';
|
||||||
import imageSet from 'inline-style-prefixer/static/plugins/imageSet';
|
import imageSet from 'inline-style-prefixer/static/plugins/imageSet';
|
||||||
@@ -21,6 +22,7 @@ export default {
|
|||||||
cursor,
|
cursor,
|
||||||
filter,
|
filter,
|
||||||
flex,
|
flex,
|
||||||
|
flexboxIE,
|
||||||
flexboxOld,
|
flexboxOld,
|
||||||
gradient,
|
gradient,
|
||||||
imageSet,
|
imageSet,
|
||||||
@@ -82,13 +84,13 @@ export default {
|
|||||||
columns: wm,
|
columns: wm,
|
||||||
columnSpan: wm,
|
columnSpan: wm,
|
||||||
columnWidth: wm,
|
columnWidth: wm,
|
||||||
flex: w,
|
flex: wms,
|
||||||
flexBasis: w,
|
flexBasis: w,
|
||||||
flexDirection: w,
|
flexDirection: wms,
|
||||||
flexGrow: w,
|
flexGrow: w,
|
||||||
flexFlow: w,
|
flexFlow: wms,
|
||||||
flexShrink: w,
|
flexShrink: w,
|
||||||
flexWrap: w,
|
flexWrap: wms,
|
||||||
alignContent: w,
|
alignContent: w,
|
||||||
alignItems: w,
|
alignItems: w,
|
||||||
alignSelf: w,
|
alignSelf: w,
|
||||||
@@ -122,6 +124,7 @@ export default {
|
|||||||
wrapFlow: ms,
|
wrapFlow: ms,
|
||||||
wrapThrough: ms,
|
wrapThrough: ms,
|
||||||
wrapMargin: ms,
|
wrapMargin: ms,
|
||||||
|
touchAction: ms,
|
||||||
gridTemplateColumns: ms,
|
gridTemplateColumns: ms,
|
||||||
gridTemplateRows: ms,
|
gridTemplateRows: ms,
|
||||||
gridTemplateAreas: ms,
|
gridTemplateAreas: ms,
|
||||||
|
|||||||
Reference in New Issue
Block a user