mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-04-18 12:12:58 +08:00
Compare commits
1 Commits
0.0.116
...
necolas/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6f8c111af |
8
.babelrc
Normal file
8
.babelrc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
"react-native"
|
||||
],
|
||||
"plugins": [
|
||||
[ "transform-react-remove-prop-types", { "mode": "wrap" } ]
|
||||
]
|
||||
}
|
||||
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
# EditorConfig: http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
14
.eslintrc
14
.eslintrc
@@ -24,16 +24,7 @@
|
||||
"globals": {
|
||||
"document": false,
|
||||
"navigator": false,
|
||||
"window": false,
|
||||
// Flow global types
|
||||
"HTMLInputElement": false,
|
||||
"ReactClass": false,
|
||||
"ReactComponent": false,
|
||||
"ReactElement": false,
|
||||
"ReactPropsChainableTypeChecker": false,
|
||||
"ReactPropsCheckType": false,
|
||||
"ReactPropTypes": false,
|
||||
"SyntheticEvent": false
|
||||
"window": false
|
||||
},
|
||||
"rules": {
|
||||
"camelcase": 0,
|
||||
@@ -129,6 +120,9 @@
|
||||
|
||||
// react
|
||||
"react/display-name": 0,
|
||||
"react/jsx-handler-names": [2, {
|
||||
"eventHandlerPrefix": "_handle"
|
||||
}],
|
||||
"react/jsx-no-bind": 2,
|
||||
"react/jsx-no-duplicate-props": 2,
|
||||
"react/jsx-no-undef": 2,
|
||||
|
||||
14
.flowconfig
14
.flowconfig
@@ -1,14 +0,0 @@
|
||||
[ignore]
|
||||
.*/__tests__/.*
|
||||
.*/benchmarks/.*
|
||||
.*/docs/.*
|
||||
.*/node_modules/animated/*
|
||||
.*/node_modules/babel-plugin-transform-react-remove-prop-types/*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
types
|
||||
|
||||
[options]
|
||||
unsafe.enable_getters_and_setters=true
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
node_modules
|
||||
dist
|
||||
dist-examples
|
||||
|
||||
@@ -5,5 +5,4 @@ before_script:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
script:
|
||||
- npm run lint
|
||||
- npm test
|
||||
|
||||
@@ -6,7 +6,7 @@ Before opening an issue, please search the [issue
|
||||
tracker](https://github.com/necolas/react-native-web/issues) to make sure your
|
||||
issue hasn't already been reported.
|
||||
|
||||
## Getting started
|
||||
## Development
|
||||
|
||||
Visit the [Issue tracker](https://github.com/necolas/react-native-web/issues)
|
||||
to find a list of open issues that need attention.
|
||||
@@ -23,79 +23,48 @@ Install dependencies (requires [yarn](https://yarnpkg.com/en/docs/install):
|
||||
yarn
|
||||
```
|
||||
|
||||
## Automated tests
|
||||
|
||||
To run flow:
|
||||
Run the examples:
|
||||
|
||||
```
|
||||
yarn flow
|
||||
npm run examples
|
||||
```
|
||||
|
||||
To run the unit tests:
|
||||
Run the benchmarks in a browser by opening `./performance/index.html` after running:
|
||||
|
||||
```
|
||||
yarn jest
|
||||
npm run build:performance
|
||||
```
|
||||
|
||||
…in watch mode:
|
||||
### Building
|
||||
|
||||
```
|
||||
yarn jest:watch
|
||||
npm run build
|
||||
```
|
||||
|
||||
To run all automated tests:
|
||||
To create a UMD build:
|
||||
|
||||
```
|
||||
yarn test
|
||||
npm run build:umd
|
||||
```
|
||||
|
||||
## Visual tests
|
||||
### Testing and Linting
|
||||
|
||||
To run the interactive storybook:
|
||||
To run the tests:
|
||||
|
||||
```
|
||||
yarn docs:start
|
||||
npm run test
|
||||
```
|
||||
|
||||
To generate a static build of the storybook:
|
||||
To continuously watch and run tests, run the following:
|
||||
|
||||
```
|
||||
yarn docs:build
|
||||
npm run test:watch
|
||||
```
|
||||
|
||||
To run the performance benchmarks in a browser (opening `./benchmarks/index.html`):
|
||||
To perform only linting, run the following:
|
||||
|
||||
```
|
||||
yarn benchmark
|
||||
```
|
||||
|
||||
## Compile and build
|
||||
|
||||
To compile the source code to `dist`:
|
||||
|
||||
```
|
||||
yarn compile
|
||||
```
|
||||
|
||||
To create a UMD bundle of the library:
|
||||
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
|
||||
### Pre-commit
|
||||
|
||||
To format and lint code before commit:
|
||||
|
||||
```
|
||||
yarn precommit
|
||||
```
|
||||
|
||||
To format and lint the entire project:
|
||||
|
||||
```
|
||||
yarn fmt
|
||||
yarn lint
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### New Features
|
||||
@@ -112,10 +81,8 @@ that we won't want to accept.
|
||||
* Make sure all tests pass and there are no linting errors.
|
||||
* Submit a pull request, referencing any issues it addresses.
|
||||
|
||||
Please try to keep your pull request focused in scope and avoid including
|
||||
unrelated commits.
|
||||
Please try to keep your pull request focused in scope and avoid including unrelated commits.
|
||||
|
||||
After you have submitted your pull request, we'll try to get back to you as
|
||||
soon as possible. We may suggest some changes or improvements.
|
||||
After you have submitted your pull request, we'll try to get back to you as soon as possible. We may suggest some changes or improvements.
|
||||
|
||||
Thank you for contributing!
|
||||
87
README.md
87
README.md
@@ -16,39 +16,88 @@ Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
|
||||
## Overview
|
||||
|
||||
"React Native for Web" is a project to bring React Native's building blocks and
|
||||
touch handling to the Web.
|
||||
touch handling to the Web. [Read more](#why).
|
||||
|
||||
Browse the [UI Explorer](https://necolas.github.io/react-native-web/storybook/)
|
||||
to see React Native examples running on Web. Or remix the [React Native for
|
||||
Web: Playground](https://glitch.com/edit/#!/react-native-web-playground) on
|
||||
Glitch.
|
||||
Browse the UI Explorer to see React Native [examples running on
|
||||
Web](https://necolas.github.io/react-native-web/storybook/). Or try it out
|
||||
online with [React Native for Web: Playground](https://www.webpackbin.com/bins/-KgucwxRbn7HRU-V-3Bc).
|
||||
|
||||
## Quick start
|
||||
|
||||
To install in your app:
|
||||
|
||||
```
|
||||
npm install --save react@15.6 react-dom@15.6 react-native-web
|
||||
npm install --save react@15.4 react-dom@15.4 react-native-web
|
||||
```
|
||||
|
||||
NOTE: React Native for Web supports React/ReactDOM 15.4, 15.5, or 15.6.
|
||||
Read the [Getting Started](docs/guides/getting-started.md) guide.
|
||||
|
||||
Then read the [Getting Started](docs/guides/getting-started.md) guide.
|
||||
Alternatively, you can quickly setup a local project
|
||||
using [create-react-app](https://github.com/facebookincubator/create-react-app)
|
||||
(which supports `react-native-web` out-of-the-box once installed) and
|
||||
[react-native-web-starter](https://github.com/grabcode/react-native-web-starter).
|
||||
|
||||
## Documentation
|
||||
|
||||
The [UI Explorer](https://necolas.github.io/react-native-web/storybook/)
|
||||
interactively documents all the APIs and Components.
|
||||
|
||||
Guides:
|
||||
|
||||
* [Getting started](docs/guides/getting-started.md)
|
||||
* [Style](docs/guides/style.md)
|
||||
* [Accessibility](docs/guides/accessibility.md)
|
||||
* [Direct manipulation](docs/guides/direct-manipulation.md)
|
||||
* [Internationalization](docs/guides/internationalization.md)
|
||||
* [Advanced use](docs/guides/advanced.md)
|
||||
* [Known issues](docs/guides/known-issues.md)
|
||||
* [Style](docs/guides/style.md)
|
||||
|
||||
Exported modules:
|
||||
|
||||
* Components
|
||||
* [`ActivityIndicator`](docs/components/ActivityIndicator.md)
|
||||
* [`Button`](docs/components/Button.md)
|
||||
* [`Image`](docs/components/Image.md)
|
||||
* [`ListView`](docs/components/ListView.md)
|
||||
* [`ProgressBar`](docs/components/ProgressBar.md)
|
||||
* [`ScrollView`](docs/components/ScrollView.md)
|
||||
* [`Switch`](docs/components/Switch.md)
|
||||
* [`Text`](docs/components/Text.md)
|
||||
* [`TextInput`](docs/components/TextInput.md)
|
||||
* [`TouchableHighlight`](http://facebook.github.io/react-native/releases/0.22/docs/touchablehighlight.html) (mirrors React Native)
|
||||
* [`TouchableOpacity`](http://facebook.github.io/react-native/releases/0.22/docs/touchableopacity.html) (mirrors React Native)
|
||||
* [`TouchableWithoutFeedback`](docs/components/TouchableWithoutFeedback.md)
|
||||
* [`View`](docs/components/View.md)
|
||||
* APIs
|
||||
* [`Animated`](http://facebook.github.io/react-native/releases/0.20/docs/animated.html) (mirrors React Native)
|
||||
* [`AppRegistry`](docs/apis/AppRegistry.md)
|
||||
* [`AppState`](docs/apis/AppState.md)
|
||||
* [`AsyncStorage`](docs/apis/AsyncStorage.md)
|
||||
* [`Clipboard`](docs/apis/Clipboard.md)
|
||||
* [`Dimensions`](docs/apis/Dimensions.md)
|
||||
* [`I18nManager`](docs/apis/I18nManager.md)
|
||||
* [`NativeMethods`](docs/apis/NativeMethods.md)
|
||||
* [`NetInfo`](docs/apis/NetInfo.md)
|
||||
* [`PanResponder`](http://facebook.github.io/react-native/releases/0.20/docs/panresponder.html#content) (mirrors React Native)
|
||||
* [`PixelRatio`](docs/apis/PixelRatio.md)
|
||||
* [`Platform`](docs/apis/Platform.md)
|
||||
* [`StyleSheet`](docs/apis/StyleSheet.md)
|
||||
* [`Vibration`](docs/apis/Vibration.md)
|
||||
|
||||
<span id="#why"></span>
|
||||
|
||||
## Why?
|
||||
|
||||
There are many different teams at Twitter building web applications with React.
|
||||
We want to share React components, libraries, and APIs between teams…much like
|
||||
the OSS community tries to do. At our scale, this involves dealing with
|
||||
multiple, inter-related problems including: a common way to handle style,
|
||||
animation, touch, viewport adaptation, accessibility, themes, RTL layout, and
|
||||
server-rendering.
|
||||
|
||||
This is hard to do with React DOM, as the components are essentially the same
|
||||
low-level building blocks that the browser provides. However, React Native
|
||||
avoids, solves, or can solve almost all these problems facing Web teams.
|
||||
Central to this is React Native's JavaScript style API (not strictly
|
||||
"CSS-in-JS") which avoids the key [problems with
|
||||
CSS](https://speakerdeck.com/vjeux/react-css-in-js) by giving up some of the
|
||||
complexity of CSS.
|
||||
|
||||
## Example code
|
||||
|
||||
@@ -91,16 +140,10 @@ AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-ro
|
||||
|
||||
## Related projects
|
||||
|
||||
* [react-primitives](https://github.com/lelandrichardson/react-primitives/)
|
||||
* [react-sketchapp](https://github.com/airbnb/react-sketchapp)
|
||||
* [reactxp](https://github.com/microsoft/reactxp)
|
||||
* [react-native-web-player](https://github.com/dabbott/react-native-web-player)
|
||||
|
||||
## Start kits
|
||||
|
||||
* [create-react-app](https://github.com/facebookincubator/create-react-app) ([on Glitch](https://glitch.com/edit/#!/react-native-web-playground))
|
||||
* [react-native-web-starter](https://github.com/grabcode/react-native-web-starter)
|
||||
* [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack)
|
||||
* [react-native-web-player](https://github.com/dabbott/react-native-web-player)
|
||||
* [reactxp](https://github.com/microsoft/reactxp)
|
||||
* [react-web](https://github.com/taobaofed/react-web)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# Performance
|
||||
|
||||
To run these benchmarks:
|
||||
|
||||
```
|
||||
npm run build:performance
|
||||
open ./performance/index.html
|
||||
```
|
||||
|
||||
Append `?fastest` to the URL to include the fastest "other libraries", and
|
||||
`?all` to include all the "other libraries".
|
||||
|
||||
## Notes
|
||||
|
||||
The components used in the render benchmarks are simple enough to be
|
||||
implemented by multiple UI or style libraries. The implementations are not
|
||||
equivalent in functionality. For example, React Native for Web's stylesheet is
|
||||
unique in that it also converts React Native styles to DOM styles, has
|
||||
deterministic resolution, and supports RTL layout.
|
||||
|
||||
`react-native-web/stylesheet` is a comparative baseline that implements a
|
||||
simple `View` without much of React Native's functionality.
|
||||
|
||||
## Benchmark results
|
||||
|
||||
Typical render timings*: mean ± two standard deviations.
|
||||
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) | Tweets (ms) |
|
||||
| :--- | ---: | ---: | ---: |
|
||||
| `css-modules` | `84.19` `±14.69` | `183.37` `±22.98` | |
|
||||
| `react-native-web/stylesheet@0.0.113` | `88.83` `±14.31` | `185.54` `±24.62` | |
|
||||
| `react-native-web@0.0.113` | `110.45` `±19.63` | `251.53` `±32.52` | `15.52` `±7.93ms` |
|
||||
|
||||
Other libraries
|
||||
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) |
|
||||
| :--- | ---: | ---: |
|
||||
| `aphrodite@1.2.3` | `84.68` `±18.80` | `180.62` `±41.98` |
|
||||
| `styletron@2.5.1` | `83.93` `±13.10` | `185.96` `±45.65` |
|
||||
| `react-jss@7.0.1` | `174.75` `±30.87` | `411.77` `±83.83` |
|
||||
| `glamor@3.0.0-3` | `255.21` `±45.68` | `545.74` `±107.79` |
|
||||
| `reactxp@0.34.3` | `237.46` `±36.72` | `514.48` `±84.87` |
|
||||
| `styled-components@2.1.1` | `266.91` `±50.04` | `598.29` `±95.13` |
|
||||
| `styled-components/primitives@2.1.1` | `266.62` `±50.39` | `567.13` `±68.12` |
|
||||
| `radium@0.19.1` | `518.48` `±69.74` | `1058.85` `±120.85` |
|
||||
|
||||
These results indicate that styled render performance is not a significant
|
||||
differentiating factor between `aphrodite`, `css-modules`, `react-native-web`,
|
||||
and `styletron`.
|
||||
|
||||
*MacBook Pro (13-inch, Early 2015); 3.1 GHz Intel Core i7; 16 GB 1867 MHz DDR3. Google Chrome 58 (2x CPU slowdown).
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "benchmarks",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"aphrodite": "^1.2.3",
|
||||
"classnames": "^2.2.5",
|
||||
"glamor": "^3.0.0-3",
|
||||
"marky": "^1.2.0",
|
||||
"radium": "^0.19.1",
|
||||
"react-jss": "^7.0.1",
|
||||
"react-primitives": "^0.4.3",
|
||||
"reactxp": "0.34.3",
|
||||
"styled-components": "^2.1.1",
|
||||
"styletron-client": "^2.5.7",
|
||||
"styletron-utils": "^2.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"css-loader": "^0.28.4",
|
||||
"react-addons-perf": "^15.4.2",
|
||||
"style-loader": "^0.18.2"
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import Radium from 'radium';
|
||||
import React from 'react';
|
||||
import View from '../View/radium';
|
||||
|
||||
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) =>
|
||||
<View
|
||||
{...other}
|
||||
style={[
|
||||
styles[`color${color}`],
|
||||
fixed && styles.fixed,
|
||||
layout === 'row' && styles.row,
|
||||
outer && styles.outer
|
||||
]}
|
||||
/>;
|
||||
|
||||
const styles = {
|
||||
outer: {
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
}
|
||||
};
|
||||
|
||||
export default Radium(Box);
|
||||
@@ -1,30 +0,0 @@
|
||||
import styled from 'styled-components/primitives';
|
||||
|
||||
const getColor = color => {
|
||||
switch (color) {
|
||||
case 0:
|
||||
return '#222';
|
||||
case 1:
|
||||
return '#666';
|
||||
case 2:
|
||||
return '#999';
|
||||
case 3:
|
||||
return 'blue';
|
||||
case 4:
|
||||
return 'orange';
|
||||
case 5:
|
||||
return 'red';
|
||||
default:
|
||||
return 'transparent';
|
||||
}
|
||||
};
|
||||
|
||||
const Box = styled.View`
|
||||
flex-direction: ${props => (props.layout === 'column' ? 'column' : 'row')};
|
||||
padding: ${props => (props.outer ? '4px' : '0')};
|
||||
height: ${props => (props.fixed ? '20px' : 'auto')};
|
||||
width: ${props => (props.fixed ? '20px' : 'auto')};
|
||||
background-color: ${props => getColor(props.color)};
|
||||
`;
|
||||
|
||||
export default Box;
|
||||
@@ -1,13 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import React from 'react';
|
||||
import styles from './styles.css';
|
||||
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const props = this.props;
|
||||
return <div {...props} className={classnames(styles.initial, props.className)} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default View;
|
||||
@@ -1,31 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import Radium from 'radium';
|
||||
import React from 'react';
|
||||
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const { style, ...other } = this.props;
|
||||
return <div {...other} style={[styles.root, style]} />;
|
||||
}
|
||||
}
|
||||
|
||||
const styles = {
|
||||
root: {
|
||||
alignItems: 'stretch',
|
||||
borderWidth: 0,
|
||||
borderStyle: 'solid',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
flexBasis: 'auto',
|
||||
flexDirection: 'column',
|
||||
flexShrink: 0,
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
position: 'relative',
|
||||
// fix flexbox bugs
|
||||
minHeight: 0,
|
||||
minWidth: 0
|
||||
}
|
||||
};
|
||||
|
||||
export default Radium(View);
|
||||
@@ -1,9 +0,0 @@
|
||||
import Box from './components/Box/radium';
|
||||
import View from './components/View/radium';
|
||||
|
||||
const api = {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
|
||||
export default api;
|
||||
@@ -1,7 +0,0 @@
|
||||
import Box from './components/Box/styled-components';
|
||||
import styled from 'styled-components/primitives';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View: styled.View
|
||||
};
|
||||
2
core.js
2
core.js
@@ -1 +1 @@
|
||||
module.exports = require('./dist/core');
|
||||
module.exports = require('./dist/core')
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
`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).
|
||||
`AppRegistry.runApplication` (see the [client and server rendering
|
||||
guide](../guides/rendering.md) for more details).
|
||||
|
||||
To "stop" an application when a view should be destroyed, call
|
||||
`AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was passed
|
||||
@@ -14,7 +15,8 @@ into `runApplication`. These should always be used as a pair.
|
||||
(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 ] }`.
|
||||
Return object is of type `{ element: ReactElement; stylesheet: ReactElement }`.
|
||||
It's recommended that you use `sheetsheet` to render the style sheet in an app
|
||||
|
||||
static **registerConfig**(config: Array<AppConfig>)
|
||||
|
||||
@@ -40,9 +42,6 @@ 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
|
||||
|
||||
42
docs/apis/NativeMethods.md
Normal file
42
docs/apis/NativeMethods.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# NativeMethods
|
||||
|
||||
React Native for Web provides several methods to directly access the underlying
|
||||
DOM node. This can be useful in cases when you want to focus a view or measure
|
||||
its on-screen dimensions, for example.
|
||||
|
||||
The methods described are available on most of the default components provided
|
||||
by React Native for Web. Note, however, that they are *not* available on the
|
||||
composite components that you define in your own app. For more information, see
|
||||
[Direct Manipulation](../guides/direct-manipulation.md).
|
||||
|
||||
## Methods
|
||||
|
||||
**blur**()
|
||||
|
||||
Removes focus from an input or view. This is the opposite of `focus()`.
|
||||
|
||||
**focus**()
|
||||
|
||||
Requests focus for the given input or view. The exact behavior triggered will
|
||||
depend the type of view.
|
||||
|
||||
**measure**(callback: (x, y, width, height, pageX, pageY) => void)
|
||||
|
||||
For a given view, `measure` determines the offset relative to the parent view,
|
||||
width, height, and the offset relative to the viewport. Returns the values via
|
||||
an async callback.
|
||||
|
||||
Note that these measurements are not available until after the rendering has
|
||||
been completed.
|
||||
|
||||
**measureLayout**(relativeToNativeNode: DOMNode, onSuccess: (x, y, width, height) => void)
|
||||
|
||||
Like `measure`, but measures the view relative to another view, specified as
|
||||
`relativeToNativeNode`. This means that the returned `x`, `y` are relative to
|
||||
the origin `x`, `y` of the ancestor view.
|
||||
|
||||
**setNativeProps**(nativeProps: Object)
|
||||
|
||||
This function sends props straight to the underlying DOM node. See the [direct
|
||||
manipulation](../guides/direct-manipulation.md) guide for cases where
|
||||
`setNativeProps` should be used.
|
||||
@@ -32,7 +32,7 @@ static **removeEventListener**(eventName: ChangeEventName, handler: Function)
|
||||
**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.
|
||||
internet connectivity.
|
||||
|
||||
**isConnected.addEventListener**(eventName: ChangeEventName, handler: Function)
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# 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).
|
||||
CSS without requiring a compile-time step. Some styles cannot be resolved
|
||||
outside of the render loop and are applied as inline styles. Read more about
|
||||
[how to style your application](../guides/style.md).
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -16,10 +15,9 @@ Each key of the object passed to `create` must define a style object.
|
||||
|
||||
Flattens an array of styles into a single style object.
|
||||
|
||||
(web) **getStyleSheets**: function
|
||||
**renderToString**: function
|
||||
|
||||
Returns an array of stylesheets (`{ id, textContent }`). Useful for
|
||||
compile-time or server-side rendering.
|
||||
Returns a string of the stylesheet for use in server-side rendering.
|
||||
|
||||
## Properties
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ If `true`, disable all interactions for this element.
|
||||
|
||||
This function is called on press.
|
||||
|
||||
**testID**: ?string
|
||||
testID: ?string
|
||||
|
||||
Used to locate this view in end-to-end tests.
|
||||
|
||||
|
||||
34
docs/components/ListView.md
Normal file
34
docs/components/ListView.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# ListView
|
||||
|
||||
TODO
|
||||
|
||||
## Props
|
||||
|
||||
[...ScrollView props](./ScrollView.md)
|
||||
|
||||
**children**: any
|
||||
|
||||
Content to display over the image.
|
||||
|
||||
**style**: style
|
||||
|
||||
+ ...[View#style](View.md)
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
import React, { Component, PropTypes } from 'react'
|
||||
import { ListView } from 'react-native'
|
||||
|
||||
export default class ListViewExample extends Component {
|
||||
static propTypes = {}
|
||||
|
||||
static defaultProps = {}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ListView />
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -103,11 +103,8 @@ 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.
|
||||
Callback that is called when a key is pressed. Pressed key value is passed as
|
||||
an argument to the callback handler. Fires before `onChange` callbacks.
|
||||
|
||||
**onSelectionChange**: ?function
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ NOTE: `View` will transfer all other props to the rendered HTML element.
|
||||
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.
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**accessibilityLiveRegion**: ?enum('assertive', 'none', 'polite')
|
||||
|
||||
@@ -29,7 +29,7 @@ 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.
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
(web) **accessibilityRole**: ?enum(roles)
|
||||
|
||||
@@ -38,7 +38,7 @@ 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.
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**accessible**: ?boolean
|
||||
|
||||
@@ -47,7 +47,7 @@ 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.
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**children**: ?element
|
||||
|
||||
@@ -69,7 +69,7 @@ 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.
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**onLayout**: ?function
|
||||
|
||||
@@ -132,15 +132,15 @@ Controls whether the View can be the target of touch events. The enhanced
|
||||
`box-none` is the equivalent of:
|
||||
|
||||
```css
|
||||
.box-none { pointer-events: none !important; }
|
||||
.box-none > * { pointer-events: auto; }
|
||||
.box-none { pointer-events: none }
|
||||
.box-none * { pointer-events: auto }
|
||||
```
|
||||
|
||||
`box-only` is the equivalent of:
|
||||
|
||||
```css
|
||||
.box-only { pointer-events: auto !important; }
|
||||
.box-only > * { pointer-events: none; }
|
||||
.box-only { pointer-events: auto }
|
||||
.box-only * { pointer-events: none }
|
||||
```
|
||||
|
||||
**style**: ?style
|
||||
@@ -158,7 +158,6 @@ Controls whether the View can be the target of touch events. The enhanced
|
||||
+ `animationTimingFunction` ‡
|
||||
+ `backfaceVisibility`
|
||||
+ `backgroundAttachment` ‡
|
||||
+ `backgroundBlendMode` ‡
|
||||
+ `backgroundClip` ‡
|
||||
+ `backgroundColor`
|
||||
+ `backgroundImage` ‡
|
||||
@@ -280,7 +279,7 @@ Default:
|
||||
};
|
||||
```
|
||||
|
||||
(See [facebook/yoga](https://github.com/facebook/yoga)).
|
||||
(See [facebook/css-layout](https://github.com/facebook/css-layout)).
|
||||
|
||||
**testID**: ?string
|
||||
|
||||
|
||||
@@ -40,40 +40,35 @@ using `aria-label`.
|
||||
In some cases, we also want to alert the end user of the type of selected
|
||||
component (i.e., that it is a “button”). To provide more context to screen
|
||||
readers, you should specify the `accessibilityRole` property. (Note that React
|
||||
Native for Web also provides a compatibility mapping of equivalent
|
||||
Native for Web provides a compatibility mapping of equivalent
|
||||
`accessibilityTraits` and `accessibilityComponentType` values to
|
||||
`accessibilityRole`).
|
||||
|
||||
The `accessibilityRole` prop is used to infer an [analogous HTML
|
||||
element][html-aria-url] and ARIA `role`, where possible. In most cases, both
|
||||
the element and ARIA `role` are rendered. While this may contradict some ARIA
|
||||
recommendations, it also helps avoid certain HTML5 conformance errors and
|
||||
accessibility anti-patterns (e.g., giving a `heading` role to a `button`
|
||||
element) and browser bugs.
|
||||
element][html-aria-url] to use in addition to the resulting ARIA `role`, where
|
||||
possible. While this may contradict some ARIA recommendations, it also helps
|
||||
avoid certain HTML5 conformance errors and accessibility anti-patterns (e.g.,
|
||||
giving a `heading` role to a `button` element).
|
||||
|
||||
For example:
|
||||
|
||||
* `<View accessibilityRole='article' />` => `<article role='article' />`.
|
||||
* `<View accessibilityRole='banner' />` => `<header role='banner' />`.
|
||||
* `<View accessibilityRole='button' />` => `<div role='button' tabIndex='0' />`.
|
||||
* `<Text accessibilityRole='label' />` => `<label />`.
|
||||
* `<View accessibilityRole='button' />` => `<button type='button' role='button' />`.
|
||||
* `<Text accessibilityRole='link' href='/' />` => `<a role='link' href='/' />`.
|
||||
* `<View accessibilityRole='main' />` => `<main role='main' />`.
|
||||
|
||||
In the example below, the `TouchableHighlight` is announced by screen
|
||||
readers as a button.
|
||||
In the example below, the `TouchableWithoutFeedback` is announced by screen
|
||||
readers as a native Button.
|
||||
|
||||
```js
|
||||
<TouchableHighlight accessibilityRole="button" onPress={this._handlePress}>
|
||||
```
|
||||
<TouchableWithoutFeedback accessibilityRole="button" onPress={this._onPress}>
|
||||
<View style={styles.button}>
|
||||
<Text style={styles.buttonText}>Press me!</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</TouchableWithoutFeedback>
|
||||
```
|
||||
|
||||
Note: The `button` role is not implemented using the native `button` element
|
||||
due to browsers limiting the use of flexbox layout on its children.
|
||||
|
||||
Note: Avoid changing `accessibilityRole` values over time or after user
|
||||
actions. Generally, accessibility APIs do not provide a means of notifying
|
||||
assistive technologies of a `role` value change.
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
# Advanced use
|
||||
|
||||
## Use with existing React DOM components
|
||||
|
||||
React Native for Web exports a web-specific module called `createDOMElement`,
|
||||
which can be used to wrap React DOM components. This allows you to use React
|
||||
Native's accessibility and style optimizations.
|
||||
|
||||
In the example below, `Video` will now accept common React Native props such as
|
||||
`accessibilityLabel`, `accessible`, `style`, and even the Responder event
|
||||
props.
|
||||
|
||||
```js
|
||||
import { createDOMElement } from 'react-native';
|
||||
|
||||
const Video = (props) => createDOMElement('video', props);
|
||||
```
|
||||
|
||||
This also works with composite components defined in your existing component
|
||||
gallery or dependencies ([live example](https://www.webpackbin.com/bins/-KiTSGFw3fB9Szg7quLI)).
|
||||
|
||||
```js
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import { createDOMElement, StyleSheet } from 'react-native';
|
||||
|
||||
const CustomButton = (props) => createDOMElement(RaisedButton, {
|
||||
...props,
|
||||
style: [ styles.button, props.style ]
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
padding: 20
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Remember that React Native styles are not the same as React DOM styles, and
|
||||
care needs to be taken not to pass React DOM styles into your React Native
|
||||
wrapped components.
|
||||
|
||||
## Use as a library framework
|
||||
|
||||
The React Native (for Web) building blocks can be used to create higher-level
|
||||
components and abstractions. In the example below, a `styled` function provides
|
||||
an API inspired by styled-components ([live
|
||||
example](https://www.webpackbin.com/bins/-KjT9ziwv4O7FDZdvsnX)).
|
||||
|
||||
```js
|
||||
const { createDOMElement, StyleSheet } = ReactNative;
|
||||
|
||||
/**
|
||||
* styled API
|
||||
*/
|
||||
const styled = (Component, styler) => {
|
||||
const isDOMComponent = typeof Component === 'string';
|
||||
|
||||
class Styled extends React.Component {
|
||||
static contextTypes = {
|
||||
getTheme: React.PropTypes.func
|
||||
};
|
||||
|
||||
render() {
|
||||
const theme = this.context.getTheme && this.context.getTheme();
|
||||
const localProps = { ...this.props, theme };
|
||||
const nextProps = { ...this.props }
|
||||
const style = typeof styler === 'function' ? styler(localProps) : styler;
|
||||
nextProps.style = [ style, this.props.style ];
|
||||
|
||||
return (
|
||||
isDOMComponent
|
||||
? createDOMElement(Component, nextProps)
|
||||
: <Component {...nextProps} />
|
||||
);
|
||||
}
|
||||
}
|
||||
return Styled;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#2196F3',
|
||||
flex: 1,
|
||||
justifyContent: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
const StyledView = styled(View, styles.container);
|
||||
```
|
||||
|
||||
## Use with react-sketchapp
|
||||
|
||||
Use with [react-sketchapp](http://airbnb.io/react-sketchapp/) requires that you
|
||||
alias `react-native` to `react-sketchapp`. This will allow you to render your
|
||||
existing React Native components in Sketch. Sketch-specific components like
|
||||
`Artboard` should be imported from `react-sketchapp`.
|
||||
|
||||
If you're using `skpm`, you can rely on an [undocumented
|
||||
feature](https://github.com/sketch-pm/skpm/blob/master/lib/utils/webpackConfig.js)
|
||||
which will merge your `webpack.config.js`, `.babelrc`, or `package.json` Babel
|
||||
config into its internal webpack config. The simplest option may be to use the
|
||||
[babel-plugin-module-alias](https://www.npmjs.com/package/babel-plugin-module-alias)
|
||||
and configure it in your `package.json`.
|
||||
@@ -1,68 +1,27 @@
|
||||
# Direct manipulation
|
||||
|
||||
React Native for Web provides several methods to directly access the underlying
|
||||
DOM node. This can be useful when you need to make changes directly to a
|
||||
component without using state/props to trigger a re-render of the entire
|
||||
subtree, or when you want to focus a view or measure its on-screen dimensions.
|
||||
It is sometimes necessary to make changes directly to a component without using
|
||||
state/props to trigger a re-render of the entire subtree – in the browser, this
|
||||
is done by directly modifying a DOM node. `setNativeProps` is the React Native
|
||||
equivalent to setting properties directly on a DOM node. Use direct
|
||||
manipulation when frequent re-rendering creates a performance bottleneck. Direct
|
||||
manipulation will not be a tool that you reach for frequently.
|
||||
|
||||
The methods described are available on most of the default components provided
|
||||
by React Native for Web. Note, however, that they are *not* available on the
|
||||
composite components that you define in your own app.
|
||||
|
||||
## Instance methods
|
||||
|
||||
**blur**()
|
||||
|
||||
Removes focus from an input or view. This is the opposite of `focus()`.
|
||||
|
||||
**focus**()
|
||||
|
||||
Requests focus for the given input or view. The exact behavior triggered will
|
||||
depend the type of view.
|
||||
|
||||
**measure**(callback: (x, y, width, height, pageX, pageY) => void)
|
||||
|
||||
For a given view, `measure` determines the offset relative to the parent view,
|
||||
width, height, and the offset relative to the viewport. Returns the values via
|
||||
an async callback.
|
||||
|
||||
Note that these measurements are not available until after the rendering has
|
||||
been completed.
|
||||
|
||||
**measureLayout**(relativeToNativeNode: DOMNode, onSuccess: (x, y, width, height) => void)
|
||||
|
||||
Like `measure`, but measures the view relative to another view, specified as
|
||||
`relativeToNativeNode`. This means that the returned `x`, `y` are relative to
|
||||
the origin `x`, `y` of the ancestor view.
|
||||
|
||||
**setNativeProps**(nativeProps: Object)
|
||||
|
||||
This function sends props straight to the underlying DOM node. See the [direct
|
||||
manipulation](../guides/direct-manipulation.md) guide for cases where
|
||||
`setNativeProps` should be used.
|
||||
|
||||
## About `setNativeProps`
|
||||
|
||||
`setNativeProps` is the React Native equivalent to setting properties directly
|
||||
on a DOM node. Use direct manipulation when frequent re-rendering creates a
|
||||
performance bottleneck. Direct manipulation will not be a tool that you reach
|
||||
for frequently.
|
||||
|
||||
### `setNativeProps` and `shouldComponentUpdate`
|
||||
## `setNativeProps` and `shouldComponentUpdate`
|
||||
|
||||
`setNativeProps` is imperative and stores state in the native layer (DOM,
|
||||
UIView, etc.) and not within your React components, which makes your code more
|
||||
difficult to reason about. Before you use it, try to solve your problem with
|
||||
`setState` and `shouldComponentUpdate`.
|
||||
|
||||
### Avoiding conflicts with the render function
|
||||
## Avoiding conflicts with the render function
|
||||
|
||||
If you update a property that is also managed by the render function, you might
|
||||
end up with some unpredictable and confusing bugs because anytime the component
|
||||
re-renders and that property changes, whatever value was previously set from
|
||||
`setNativeProps` will be completely ignored and overridden.
|
||||
|
||||
### Why use `setNativeProps` on Web?
|
||||
## Why use `setNativeProps` on Web?
|
||||
|
||||
Using `setNativeProps` in web-specific code is required when making changes to
|
||||
`className` or `style`, as these properties are controlled by React Native for
|
||||
@@ -76,7 +35,7 @@ setOpacityTo(value) {
|
||||
}
|
||||
```
|
||||
|
||||
### Composite components and `setNativeProps`
|
||||
## Composite components and `setNativeProps`
|
||||
|
||||
Composite components are not backed by a DOM node, so you cannot call
|
||||
`setNativeProps` on them. Consider this example:
|
||||
@@ -104,7 +63,7 @@ prop on it and have that work - you would need to pass the style prop down to a
|
||||
child, unless you are wrapping a native component. Similarly, we are going to
|
||||
forward `setNativeProps` to a native-backed child component.
|
||||
|
||||
### Forward `setNativeProps` to a child
|
||||
## Forward `setNativeProps` to a child
|
||||
|
||||
All we need to do is provide a `setNativeProps` method on our component that
|
||||
calls `setNativeProps` on the appropriate child with the given arguments.
|
||||
@@ -127,7 +86,7 @@ class MyButton extends React.Component {
|
||||
|
||||
You can now use `MyButton` inside of `TouchableOpacity`!
|
||||
|
||||
### `setNativeProps` to clear `TextInput` value
|
||||
## `setNativeProps` to clear `TextInput` value
|
||||
|
||||
Another very common use case of `setNativeProps` is to clear the value of a
|
||||
`TextInput`. For example, the following code demonstrates clearing the input
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
# Getting started
|
||||
|
||||
This guide will help you to correctly configure build and test tools to work
|
||||
with React Native for Web.
|
||||
|
||||
Alternatively, you can quickly setup a local project using
|
||||
[create-react-app](https://github.com/facebookincubator/create-react-app)
|
||||
(which supports `react-native-web` out-of-the-box once installed),
|
||||
[react-native-web-starter](https://github.com/grabcode/react-native-web-starter),
|
||||
or [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack).
|
||||
|
||||
It is recommended that your application provide a `Promise` and `Array.from`
|
||||
polyfill.
|
||||
|
||||
## Webpack and Babel
|
||||
|
||||
[Webpack](https://webpack.js.org) is a popular build tool for web apps. Below is an
|
||||
[Webpack](webpack.js.org) is a popular build tool for web apps. Below is an
|
||||
example of how to configure a build that uses [Babel](https://babeljs.io/) to
|
||||
compile your JavaScript for the web.
|
||||
|
||||
@@ -70,7 +61,7 @@ module.exports = {
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
})
|
||||
],
|
||||
},
|
||||
|
||||
resolve: {
|
||||
// Maps the 'react-native' import to 'react-native-web'.
|
||||
@@ -117,26 +108,6 @@ if (Platform.OS === 'web') {
|
||||
}
|
||||
```
|
||||
|
||||
More significant platform differences should use platform-specific files (see
|
||||
the webpack configuration above for resolving `*.web.js` files):
|
||||
|
||||
For example, with the following files in your project:
|
||||
|
||||
```
|
||||
MyComponent.android.js
|
||||
MyComponent.ios.js
|
||||
MyComponent.web.js
|
||||
```
|
||||
|
||||
And the following import:
|
||||
|
||||
```js
|
||||
import MyComponent from './MyComponent';
|
||||
```
|
||||
|
||||
React Native will automatically import the correct variant for each specific
|
||||
target platform.
|
||||
|
||||
## Client-side rendering
|
||||
|
||||
Rendering using `ReactNative`:
|
||||
@@ -169,8 +140,8 @@ AppRegistry.runApplication('App', {
|
||||
})
|
||||
```
|
||||
|
||||
Rendering within `ReactDOM.render` also works when introducing
|
||||
`react-native-web` to an existing web app, but otherwise it is not recommended.
|
||||
Rendering within `ReactDOM.render` also works when introduce `react-native-web`
|
||||
to an existing web app, but it is not recommended oherwise.
|
||||
|
||||
## Server-side rendering
|
||||
|
||||
@@ -187,18 +158,6 @@ const AppContainer = (props) => { /* ... */ }
|
||||
AppRegistry.registerComponent('App', () => AppContainer)
|
||||
|
||||
// prerender the app
|
||||
const { element, stylesheets } = AppRegistry.getApplication('App', { initialProps });
|
||||
const { element, stylesheet } = AppRegistry.getApplication('App', { initialProps });
|
||||
const initialHTML = ReactDOMServer.renderToString(element);
|
||||
const initialStyles = stylesheets.map((sheet) => ReactDOMServer.renderToStaticMarkup(sheet)).join('\n');
|
||||
|
||||
// construct HTML document
|
||||
const document = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
${initialStyles}
|
||||
</head>
|
||||
<body>
|
||||
${initialHTML}
|
||||
`
|
||||
```
|
||||
|
||||
@@ -1,90 +1,73 @@
|
||||
# Style
|
||||
|
||||
React Native relies on JavaScript to define and resolve the styles of your
|
||||
application. React Native for Web implements the React Native style API in a
|
||||
way that avoids *all* the [problems with CSS at
|
||||
scale](https://speakerdeck.com/vjeux/react-css-in-js):
|
||||
React Native for Web relies on JavaScript to define styles for your
|
||||
application. This allows you to avoid issues arising from the [7 deadly sins of
|
||||
CSS](https://speakerdeck.com/vjeux/react-css-in-js):
|
||||
|
||||
1. No local variables
|
||||
2. Implicit dependencies
|
||||
1. Global namespace
|
||||
2. Dependency hell
|
||||
3. No dead code elimination
|
||||
4. No code minification
|
||||
5. No sharing of constants
|
||||
6. Non-deterministic resolution
|
||||
7. No isolation
|
||||
|
||||
At the same time, it has several benefits:
|
||||
|
||||
1. Simple API and expressive subset of CSS
|
||||
2. Generates CSS; the minimum required
|
||||
3. Good runtime performance
|
||||
4. Support for static and dynamic styles
|
||||
5. Support for RTL layouts
|
||||
6. Easy pre-rendering of critical CSS
|
||||
7. Lack of isolation
|
||||
|
||||
## Defining styles
|
||||
|
||||
Styles should be defined outside of the component. Using `StyleSheet.create` is
|
||||
optional but provides the best performance (by relying on generated CSS
|
||||
stylesheets). Avoid creating unregistered style objects.
|
||||
Styles should be defined outside of the component:
|
||||
|
||||
```js
|
||||
class Example extends React.Component {}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
heading: {
|
||||
color: 'gray',
|
||||
fontSize: '2rem'
|
||||
},
|
||||
text: {
|
||||
marginTop: '1rem',
|
||||
margin: 10
|
||||
color: 'gray',
|
||||
fontSize: '1.25rem'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
See the `style` documentation of individual components for supported properties.
|
||||
Using `StyleSheet.create` is optional but provides the best performance
|
||||
(`style` is resolved to CSS stylesheets). Avoid creating unregistered style
|
||||
objects.
|
||||
|
||||
The attribute names and values are a subset of CSS. See the `style`
|
||||
documentation of individual components.
|
||||
|
||||
## Using styles
|
||||
|
||||
All the React Native components accept a `style` property. The value can be a
|
||||
registered object, a plain object, or an array.
|
||||
All the React Native components accept a `style` attribute.
|
||||
|
||||
```js
|
||||
// registered object
|
||||
<Text style={styles.text} />
|
||||
<View style={styles.view} />
|
||||
|
||||
// plain object
|
||||
<View style={{ transform: [ { translateX } ] }} />
|
||||
|
||||
// array of registered or plain objects
|
||||
<View style={[ styles.container, this.props.style ]} />
|
||||
```
|
||||
|
||||
The array syntax will merge styles from left-to-right as normal JavaScript
|
||||
objects, and can be used to conditionally apply styles:
|
||||
A common pattern is to conditionally add style based on a condition:
|
||||
|
||||
```js
|
||||
// either
|
||||
<View style={[
|
||||
styles.container,
|
||||
styles.base,
|
||||
this.state.active && styles.active
|
||||
]} />
|
||||
```
|
||||
|
||||
When styles are registered with `StyleSheet.create`, the return value is a
|
||||
number and not a style object. This is important for performance optimizations,
|
||||
but still allows you to merge styles in a deterministic manner at runtime. If
|
||||
you need access to the underlying style objects you need to use
|
||||
`StyleSheet.flatten` (but be aware that this is not the optimized path).
|
||||
|
||||
## Composing styles
|
||||
|
||||
To let other components customize the style of a component's children you can
|
||||
expose a prop so styles can be explicitly passed into the component.
|
||||
In order to let a call site customize the style of your component children, you
|
||||
can pass styles around. Use `View.propTypes.style` and `Text.propTypes.style` in
|
||||
order to make sure only valid styles are being passed.
|
||||
|
||||
```js
|
||||
class List extends React.Component {
|
||||
static propTypes = {
|
||||
style: ViewPropTypes.style,
|
||||
elementStyle: ViewPropTypes.style,
|
||||
style: View.propTypes.style,
|
||||
elementStyle: View.propTypes.style,
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -107,126 +90,56 @@ In another file:
|
||||
|
||||
You also have much greater control over how styles are composed when compared
|
||||
to using class names. For example, you may choose to accept a limited subset
|
||||
of style props in the component's API, and control when they are applied.
|
||||
|
||||
## How styles are resolved
|
||||
|
||||
React Native style resolution is deterministic and slightly different from CSS.
|
||||
|
||||
In the following HTML/CSS example, the `.margin` selector is defined last in
|
||||
the CSS and takes precedence over the previous rules, resulting in a margin of
|
||||
`0, 0, 0, 0`.
|
||||
|
||||
```html
|
||||
<style>
|
||||
.marginTop { margin-top: 10px; }
|
||||
.marginBottom { margin-bottom: 20px; }
|
||||
.margin { margin: 0; }
|
||||
</style>
|
||||
<div class="marginTop marginBottom margin"></div>
|
||||
```
|
||||
|
||||
But in React Native the most *specific* style property takes precedence,
|
||||
resulting in margins of `10, 0, 20, 0`.
|
||||
of style props in the component's API, and control when they are applied:
|
||||
|
||||
```js
|
||||
const style = [
|
||||
{ marginTop: 10 },
|
||||
{ marginBottom: 20 },
|
||||
{ margin: 0 }
|
||||
];
|
||||
|
||||
const Box = () => <View style={style} />
|
||||
```
|
||||
|
||||
## Implementation details
|
||||
|
||||
React Native for Web transforms React Native styles into React DOM styles. Any
|
||||
styles defined using `StyleSheet.create` will ultimately be rendered using CSS
|
||||
class names.
|
||||
|
||||
React Native for Web introduced a novel strategy to achieve this. Each rule is
|
||||
broken down into declarations, properties are expanded to their long-form, and
|
||||
the resulting key-value pairs are mapped to unique "atomic CSS" class names.
|
||||
|
||||
Input:
|
||||
|
||||
```js
|
||||
const Box = () => <View style={styles.box} />
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
box: {
|
||||
margin: 0
|
||||
class List extends React.Component {
|
||||
static propTypes = {
|
||||
children: React.PropTypes.any,
|
||||
// limit which styles are accepted
|
||||
style: React.PropTypes.shape({
|
||||
borderColor: View.propTypes.borderColor,
|
||||
borderWidth: View.propTypes.borderWidth
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View
|
||||
children={children}
|
||||
style={[
|
||||
this.props.style,
|
||||
// override border-color when scrolling
|
||||
isScrolling && { borderColor: 'transparent' }
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```html
|
||||
<style>
|
||||
.rn-1mnahxq { margin-top: 0px; }
|
||||
.rn-61z16t { margin-right: 0px; }
|
||||
.rn-p1pxzi { margin-bottom: 0px; }
|
||||
.rn-11wrixw { margin-left: 0px; }
|
||||
</style>
|
||||
|
||||
<div class="rn-156q2ks rn-61z16t rn-p1pxzi rn-11wrixw"></div>
|
||||
```
|
||||
|
||||
This ensures that CSS order doesn't impact rendering and CSS rules are
|
||||
efficiently deduplicated. Rather than the total CSS growing in proportion to
|
||||
the number of *rules*, it grows in proportion to the number of *unique
|
||||
declarations*. As a result, the DOM style sheet is only written to when new
|
||||
unique declarations are defined and it is usually small enough to be
|
||||
pre-rendered and inlined.
|
||||
|
||||
Class names are deterministic, which means that the resulting CSS and HTML is
|
||||
consistent across builds – important for large apps using code-splitting and
|
||||
deploying incremental updates.
|
||||
|
||||
At runtime registered styles are resolved to DOM style props and memoized.
|
||||
Any dynamic styles that contain declarations previously registered as static
|
||||
styles can also be converted to CSS class names. Otherwise, they render as
|
||||
inline styles.
|
||||
|
||||
All this allows React Native for Web to support the rich functionality of React
|
||||
Native styles (including RTL layouts and `setNativeProps`) while providing one
|
||||
of the [fastest](https://github.com/necolas/react-native-web/blob/master/benchmarks/README.md),
|
||||
safest, and most efficient styles-in-JavaScript solutions.
|
||||
|
||||
## FAQs
|
||||
|
||||
### What about Media Queries?
|
||||
## Media Queries
|
||||
|
||||
`StyleSheet.create` is a way of defining the styles your application requires;
|
||||
it does not concern itself with _where_ or _when_ those styles are applied to
|
||||
elements.
|
||||
|
||||
Media Queries may not be most appropriate for component-based designs. React
|
||||
Native provides the `Dimensions` API and `onLayout` props. If you do need Media
|
||||
Queries, using the `matchMedia` DOM API has the benefit of allowing you to swap
|
||||
out entire components, not just styles. There are also many React libraries
|
||||
wrapping JavaScript Media Query API's, e.g.,
|
||||
[react-media](https://github.com/reacttraining/react-media),
|
||||
There are various React libraries wrapping JavaScript Media Query API's, e.g.,
|
||||
[react-media-queries](https://github.com/bloodyowl/react-media-queries),
|
||||
[media-query-fascade](https://github.com/tanem/media-query-facade), or
|
||||
[react-responsive](https://github.com/contra/react-responsive).
|
||||
[react-responsive](https://github.com/contra/react-responsive). This has the
|
||||
benefit of co-locating breakpoint-specific DOM and style changes.
|
||||
|
||||
### What about pseudo-classes and pseudo-elements?
|
||||
## Pseudo-classes and pseudo-elements
|
||||
|
||||
Pseudo-classes like `:hover` and `:focus` can be implemented with events (e.g.
|
||||
`onFocus`). Pseudo-elements are not supported; elements should be used instead.
|
||||
|
||||
### Do I need a CSS reset?
|
||||
### Reset
|
||||
|
||||
No. React Native for Web includes a very small CSS reset that removes unwanted
|
||||
User Agent styles from (pseudo-)elements beyond the reach of React (e.g.,
|
||||
`html`, `body`) or inline styles (e.g., `::-moz-focus-inner`). The rest is
|
||||
handled at the component-level.
|
||||
You **do not** need to include a CSS reset or
|
||||
[normalize.css](https://necolas.github.io/normalize.css/).
|
||||
|
||||
### What about using Dev Tools?
|
||||
|
||||
React Dev Tools supports inspecting and editing of React Native styles. It's
|
||||
recommended that you rely more on React Dev Tools and live/hot-reloading rather
|
||||
than inspecting and editing the DOM directly.
|
||||
React Native for Web includes a very small CSS reset taken from normalize.css.
|
||||
It removes unwanted User Agent styles from (pseudo-)elements beyond the reach
|
||||
of React (e.g., `html`, `body`) or inline styles (e.g., `::-moz-focus-inner`).
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "yarn && build-storybook -o ./dist -c ./storybook/.storybook",
|
||||
"start": "start-storybook -p 9001 -c ./storybook/.storybook --dont-track",
|
||||
"publish": "yarn build && git checkout gh-pages && rm -rf ./storybook && mv docs/dist storybook && git add -A && git commit -m \"Storybook deploy\" && git push origin gh-pages && git checkout -"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kadira/storybook": "^2.35.3",
|
||||
"@kadira/storybook-addon-options": "^1.0.2"
|
||||
}
|
||||
}
|
||||
BIN
docs/static/components.png
vendored
Normal file
BIN
docs/static/components.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/static/styling-strategy.png
vendored
Normal file
BIN
docs/static/styling-strategy.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
@@ -1 +0,0 @@
|
||||
import '@kadira/storybook-addon-options/register';
|
||||
@@ -1,23 +0,0 @@
|
||||
import { setOptions } from '@kadira/storybook-addon-options';
|
||||
import centered from './decorator-centered';
|
||||
import { configure, addDecorator } from '@kadira/storybook';
|
||||
|
||||
const context = require.context('../', true, /Screen\.js$/);
|
||||
|
||||
addDecorator(centered);
|
||||
|
||||
setOptions({
|
||||
name: 'React Native Web',
|
||||
url: 'https://necolas.github.io/react-native-web',
|
||||
goFullScreen: false,
|
||||
showLeftPanel: true,
|
||||
showDownPanel: false,
|
||||
showSearchBox: false,
|
||||
downPanelInRight: false
|
||||
});
|
||||
|
||||
function loadStories() {
|
||||
context.keys().forEach(context);
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
||||
@@ -1,18 +0,0 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
minHeight: '100vh',
|
||||
maxWidth: 680,
|
||||
marginHorizontal: 'auto'
|
||||
}
|
||||
});
|
||||
|
||||
export default function(renderStory) {
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
{renderStory()}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* eslint-disable react/jsx-sort-props */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import PropAnimating from './examples/PropAnimating';
|
||||
import PropColor from './examples/PropColor';
|
||||
import PropHidesWhenStopped from './examples/PropHidesWhenStopped';
|
||||
import PropSize from './examples/PropSize';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, { Description, DocItem, Section } from '../../ui-explorer';
|
||||
|
||||
const ActivityIndicatorScreen = () =>
|
||||
<UIExplorer title="ActivityIndicator" url="components/ActivityIndicator">
|
||||
<Description>Displays a customizable activity indicator</Description>
|
||||
<Section title="Props">
|
||||
<DocItem name="...View props" />
|
||||
|
||||
<DocItem
|
||||
name="animating"
|
||||
typeInfo="?boolean = true"
|
||||
description="Whether to show the indicator or hide it."
|
||||
example={{
|
||||
render: () => <PropAnimating />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="color"
|
||||
typeInfo="?color = #1976D2"
|
||||
description="The foreground color of the spinner."
|
||||
example={{
|
||||
render: () => <PropColor />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="hidesWhenStopped"
|
||||
typeInfo="?boolean = true"
|
||||
description="Whether the indicator should hide when not animating."
|
||||
example={{
|
||||
render: () => <PropHidesWhenStopped />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="size"
|
||||
typeInfo="?enum('small', 'large') | number = 'small'"
|
||||
description="Size of the indicator. Small has a height of 20px, large has a height of 36px."
|
||||
example={{
|
||||
render: () => <PropSize />
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
storiesOf('Components', module).add('ActivityIndicator', ActivityIndicatorScreen);
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||
import React from 'react';
|
||||
|
||||
const ActivityIndicatorAnimatingExample = () =>
|
||||
<View style={styles.horizontal}>
|
||||
<ActivityIndicator />
|
||||
<ActivityIndicator animating={false} />
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontal: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row'
|
||||
}
|
||||
});
|
||||
|
||||
export default ActivityIndicatorAnimatingExample;
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||
|
||||
const ActivityIndicatorColorExample = () =>
|
||||
<View style={styles.horizontal}>
|
||||
<ActivityIndicator color="#1DA1F2" style={styles.rightPadding} />
|
||||
<ActivityIndicator color="#17BF63" style={styles.rightPadding} />
|
||||
<ActivityIndicator color="#F45D22" style={styles.rightPadding} />
|
||||
<ActivityIndicator color="#794BC4" style={styles.rightPadding} />
|
||||
<ActivityIndicator color="#E0245E" style={styles.rightPadding} />
|
||||
<ActivityIndicator color="#FFAD1F" style={styles.rightPadding} />
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontal: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
rightPadding: {
|
||||
paddingRight: 10
|
||||
}
|
||||
});
|
||||
|
||||
ActivityIndicatorColorExample.metadata = {
|
||||
id: 'ActivityIndicator.props.color',
|
||||
description: ''
|
||||
};
|
||||
|
||||
export default ActivityIndicatorColorExample;
|
||||
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||
import { bool } from 'prop-types';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
class ToggleAnimatingActivityIndicator extends PureComponent {
|
||||
static propTypes = {
|
||||
hidesWhenStopped: bool,
|
||||
style: ActivityIndicator.propTypes.style
|
||||
};
|
||||
|
||||
state = {
|
||||
animating: true
|
||||
};
|
||||
|
||||
setToggleTimeout = () => {
|
||||
this._timer = setTimeout(() => {
|
||||
this.setState({ animating: !this.state.animating });
|
||||
this.setToggleTimeout();
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.setToggleTimeout();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ActivityIndicator
|
||||
animating={this.state.animating}
|
||||
hidesWhenStopped={this.props.hidesWhenStopped}
|
||||
size="large"
|
||||
style={[styles.centering, this.props.style]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ActivityIndicatorHidesWhenStoppedExample = () =>
|
||||
<View style={[styles.horizontal]}>
|
||||
<ToggleAnimatingActivityIndicator hidesWhenStopped={false} style={styles.rightPadding} />
|
||||
<ToggleAnimatingActivityIndicator />
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontal: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
rightPadding: {
|
||||
paddingRight: 10
|
||||
}
|
||||
});
|
||||
|
||||
ActivityIndicatorHidesWhenStoppedExample.metadata = {
|
||||
id: 'ActivityIndicator.props.hidesWhenStopped',
|
||||
description: ''
|
||||
};
|
||||
|
||||
export default ActivityIndicatorHidesWhenStoppedExample;
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||
|
||||
const sizes = [20, 'small', 36, 'large', 60];
|
||||
|
||||
const ActivityIndicatorSizeExample = () =>
|
||||
<View style={styles.horizontal}>
|
||||
{sizes.map((size, i) => <ActivityIndicator key={i} size={size} style={styles.rightPadding} />)}
|
||||
<ActivityIndicator size="large" style={styles.large} />
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontal: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
rightPadding: {
|
||||
paddingRight: 10
|
||||
},
|
||||
large: { marginLeft: 20, transform: [{ scale: 1.75 }] }
|
||||
});
|
||||
|
||||
ActivityIndicatorSizeExample.metadata = {
|
||||
id: 'ActivityIndicator.props.size',
|
||||
description: ''
|
||||
};
|
||||
|
||||
export default ActivityIndicatorSizeExample;
|
||||
@@ -1,67 +0,0 @@
|
||||
/* eslint-disable react/jsx-sort-props */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropColor from './examples/PropColor';
|
||||
import PropDisabled from './examples/PropDisabled';
|
||||
import PropOnPress from './examples/PropOnPress';
|
||||
import UIExplorer, { AppText, Code, Description, DocItem, Section } from '../../ui-explorer';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
|
||||
const ButtonScreen = () =>
|
||||
<UIExplorer title="Button" url="components/Button">
|
||||
<Description>
|
||||
<AppText>
|
||||
A basic button component. Supports a minimal level of customization. You can build your own
|
||||
custom button using <Code>TouchableOpacity</Code> or <Code>TouchableNativeFeedback</Code>.
|
||||
</AppText>
|
||||
</Description>
|
||||
|
||||
<Section title="Props">
|
||||
<DocItem
|
||||
name="accessibilityLabel"
|
||||
typeInfo="?string"
|
||||
description="Overrides the text that's read by a screen reader when the user interacts with the element."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="color"
|
||||
typeInfo="?string"
|
||||
description="Background color of the button."
|
||||
example={{
|
||||
render: () => <PropColor />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="disabled"
|
||||
typeInfo="?boolean"
|
||||
description="If true, disable all interactions for this element."
|
||||
example={{
|
||||
render: () => <PropDisabled />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onPress"
|
||||
typeInfo="function"
|
||||
description="This function is called on press."
|
||||
example={{
|
||||
render: () => <PropOnPress />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="testID"
|
||||
typeInfo="?string"
|
||||
description="Used to locate this view in end-to-end tests."
|
||||
/>
|
||||
|
||||
<DocItem name="title" typeInfo="string" description="Text to display inside the button." />
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
storiesOf('Components', module).add('Button', ButtonScreen);
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { DividerVertical } from '../helpers';
|
||||
import { Button, View } from 'react-native';
|
||||
|
||||
const emptyFunction = () => {};
|
||||
|
||||
const ButtonColorExample = () =>
|
||||
<View>
|
||||
<Button color="#17BF63" onPress={emptyFunction} title="Press me" />
|
||||
<DividerVertical />
|
||||
<Button color="#F45D22" onPress={emptyFunction} title="Press me" />
|
||||
<DividerVertical />
|
||||
<Button color="#794BC4" onPress={emptyFunction} title="Press me" />
|
||||
<DividerVertical />
|
||||
<Button color="#E0245E" onPress={emptyFunction} title="Press me" />
|
||||
</View>;
|
||||
|
||||
export default ButtonColorExample;
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button } from 'react-native';
|
||||
|
||||
const onPress = () => {
|
||||
console.error('Disabled button should not trigger onPress!');
|
||||
};
|
||||
const ButtonDisabledExample = () => <Button disabled onPress={onPress} title="Disabled button" />;
|
||||
|
||||
export default ButtonDisabledExample;
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { DividerHorizontal } from '../helpers';
|
||||
import { Button, StyleSheet, View } from 'react-native';
|
||||
|
||||
const emptyFunction = () => {};
|
||||
|
||||
const ButtonOnPressExample = () =>
|
||||
<View style={styles.horizontal}>
|
||||
<Button
|
||||
accessibilityLabel="This sounds great!"
|
||||
onPress={emptyFunction}
|
||||
title="This looks great!"
|
||||
/>
|
||||
<DividerHorizontal />
|
||||
<Button color="#841584" onPress={emptyFunction} title="Ok!" />
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontal: {
|
||||
flexDirection: 'row'
|
||||
}
|
||||
});
|
||||
|
||||
export default ButtonOnPressExample;
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
|
||||
const DividerHorizontal = () => <View style={styles.horizontalDivider} />;
|
||||
const DividerVertical = () => <View style={styles.verticalDivider} />;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontalDivider: {
|
||||
width: '0.6rem'
|
||||
},
|
||||
verticalDivider: {
|
||||
height: '1.3125rem'
|
||||
}
|
||||
});
|
||||
|
||||
export { DividerHorizontal, DividerVertical };
|
||||
@@ -1,174 +0,0 @@
|
||||
/* eslint-disable react/jsx-sort-props */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropChildren from './examples/PropChildren';
|
||||
import PropDefaultSource from './examples/PropDefaultSource';
|
||||
import PropDraggable from './examples/PropDraggable';
|
||||
import PropOnError from './examples/PropOnError';
|
||||
import PropOnLoad from './examples/PropOnLoad';
|
||||
import PropOnLoadEnd from './examples/PropOnLoadEnd';
|
||||
import PropOnLoadStart from './examples/PropOnLoadStart';
|
||||
import PropResizeMode from './examples/PropResizeMode';
|
||||
import PropSource from './examples/PropSource';
|
||||
import StaticGetSizeExample from './examples/StaticGetSize';
|
||||
import StaticPrefetchExample from './examples/StaticPrefetch';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, { AppText, Code, Description, DocItem, Section } from '../../ui-explorer';
|
||||
|
||||
const ImageScreen = () =>
|
||||
<UIExplorer title="Image" url="components/Image">
|
||||
<Description>
|
||||
An accessibile image component with support for image resizing, default image, and child
|
||||
content.
|
||||
</Description>
|
||||
|
||||
<Section title="Props">
|
||||
<DocItem name="...View props" />
|
||||
|
||||
<DocItem
|
||||
name="children"
|
||||
typeInfo="?any"
|
||||
description="Content to display over the image."
|
||||
example={{
|
||||
render: () => <PropChildren />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="defaultSource"
|
||||
typeInfo="?object"
|
||||
description={
|
||||
<AppText>
|
||||
An image to display as a placeholder while downloading the final image off the network.{' '}
|
||||
<Code>{'{ uri: string, width, height }'}</Code>
|
||||
</AppText>
|
||||
}
|
||||
example={{
|
||||
render: () => <PropDefaultSource />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
label="web"
|
||||
name="draggable"
|
||||
typeInfo="?boolean = true"
|
||||
description="When false, the image will not be draggable"
|
||||
example={{
|
||||
render: () => <PropDraggable />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onError"
|
||||
typeInfo="?function"
|
||||
description={
|
||||
<AppText>
|
||||
Invoked on load error with <Code>{'{nativeEvent: {error}}'}</Code>.
|
||||
</AppText>
|
||||
}
|
||||
example={{
|
||||
render: () => <PropOnError />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onLoad"
|
||||
typeInfo="?function"
|
||||
description="Invoked when load completes successfully."
|
||||
example={{
|
||||
render: () => <PropOnLoad />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onLoadEnd"
|
||||
typeInfo="?function"
|
||||
description="Invoked when load either succeeds or fails."
|
||||
example={{
|
||||
render: () => <PropOnLoadEnd />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onLoadStart"
|
||||
typeInfo="?function"
|
||||
description="Invoked on load start."
|
||||
example={{
|
||||
render: () => <PropOnLoadStart />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="resizeMode"
|
||||
typeInfo="?enum('center', 'contain', 'cover', 'none', 'repeat', 'stretch') = 'cover';"
|
||||
description="Determines how to resize the image when the frame doesn't match the raw image dimensions."
|
||||
example={{
|
||||
render: () => <PropResizeMode />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="source"
|
||||
typeInfo="?object"
|
||||
description={
|
||||
<AppText>
|
||||
<Code>uri</Code> is a string representing the resource identifier for the image, which
|
||||
could be an http address or a base64 encoded image.{' '}
|
||||
<Code>{'{ uri: string, width, height }'}</Code>
|
||||
</AppText>
|
||||
}
|
||||
example={{
|
||||
render: () => <PropSource />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem name="style" typeInfo="?style" />
|
||||
</Section>
|
||||
|
||||
<Section title="Properties">
|
||||
<DocItem
|
||||
name="static resizeMode"
|
||||
typeInfo="object"
|
||||
example={{
|
||||
code: '<Image resizeMode={Image.resizeMode.contain} />'
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title="Methods">
|
||||
<DocItem
|
||||
name="static getSize"
|
||||
typeInfo="(uri: string, success: (width, height) => {}, failure: function) => void"
|
||||
description={[
|
||||
<AppText key={1}>
|
||||
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.
|
||||
</AppText>,
|
||||
<AppText key={2}>
|
||||
(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.)
|
||||
</AppText>
|
||||
]}
|
||||
example={{
|
||||
render: () => <StaticGetSizeExample />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="static prefetch"
|
||||
typeInfo="(url: string) => Promise"
|
||||
description="Prefetches a remote image for later use by downloading it."
|
||||
example={{
|
||||
render: () => <StaticPrefetchExample />
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
storiesOf('Components', module).add('Image', ImageScreen);
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/*
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
export default class MultipleSourcesExample extends PureComponent {
|
||||
state = {
|
||||
width: 30,
|
||||
height: 30
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
||||
<Text style={styles.touchableText} onPress={this.decreaseImageSize}>
|
||||
Decrease image size
|
||||
</Text>
|
||||
<Text style={styles.touchableText} onPress={this.increaseImageSize}>
|
||||
Increase image size
|
||||
</Text>
|
||||
</View>
|
||||
<Text>Container image size: {this.state.width}x{this.state.height} </Text>
|
||||
<View style={{ height: this.state.height, width: this.state.width }}>
|
||||
<Image
|
||||
style={{ flex: 1 }}
|
||||
source={[
|
||||
{ uri: 'http://facebook.github.io/react/img/logo_small.png', width: 38, height: 38 },
|
||||
{
|
||||
uri: 'http://facebook.github.io/react/img/logo_small_2x.png',
|
||||
width: 76,
|
||||
height: 76
|
||||
},
|
||||
{ uri: 'http://facebook.github.io/react/img/logo_og.png', width: 400, height: 400 }
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
increaseImageSize = () => {
|
||||
if (this.state.width >= 100) {
|
||||
return;
|
||||
}
|
||||
this.setState(state => ({
|
||||
width: state.width + 10,
|
||||
height: state.height + 10
|
||||
}));
|
||||
};
|
||||
|
||||
decreaseImageSize = () => {
|
||||
if (this.state.width <= 10) {
|
||||
return;
|
||||
}
|
||||
this.setState(state => ({
|
||||
width: state.width - 10,
|
||||
height: state.height - 10
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
touchableText: {
|
||||
color: 'blue',
|
||||
fontWeight: '500'
|
||||
}
|
||||
});
|
||||
*/
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import * as helpers from '../helpers';
|
||||
import { oneOf } from 'prop-types';
|
||||
import sources from '../sources';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { ActivityIndicator, Image, Text, View } from 'react-native';
|
||||
|
||||
class NetworkImageExample extends PureComponent {
|
||||
state = {
|
||||
error: false,
|
||||
loading: false
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
logMethod: oneOf(['onError', 'onLoad', 'onLoadEnd', 'onLoadStart']),
|
||||
source: Image.propTypes.source
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
logList: []
|
||||
};
|
||||
|
||||
render() {
|
||||
const loader = this.state.loading
|
||||
? <View>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
: null;
|
||||
|
||||
return (
|
||||
<View style={[helpers.styles.row, helpers.styles.centerRow]}>
|
||||
<Image
|
||||
defaultSource={sources.placeholder}
|
||||
onError={this._handleError}
|
||||
onLoad={this._handleLoad}
|
||||
onLoadEnd={this._handleLoadEnd}
|
||||
onLoadStart={this._handleLoadStart}
|
||||
source={this.props.source}
|
||||
style={helpers.styles.base}
|
||||
>
|
||||
{loader}
|
||||
</Image>
|
||||
{this.state.message &&
|
||||
<Text style={helpers.styles.marginLeft}>
|
||||
{this.state.message}
|
||||
</Text>}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleError = e => {
|
||||
const nextState = { loading: false };
|
||||
if (this.props.logMethod === 'onError') {
|
||||
nextState.message = `✘ onError ${JSON.stringify(e.nativeEvent)}`;
|
||||
}
|
||||
this.setState(() => nextState);
|
||||
};
|
||||
|
||||
_handleLoad = () => {
|
||||
const nextState = { loading: false };
|
||||
if (this.props.logMethod === 'onLoad') {
|
||||
nextState.message = '✔ onLoad';
|
||||
}
|
||||
this.setState(() => nextState);
|
||||
};
|
||||
|
||||
_handleLoadEnd = () => {
|
||||
const nextState = { loading: false };
|
||||
if (this.props.logMethod === 'onLoadEnd') {
|
||||
nextState.message = '✔ onLoadEnd';
|
||||
}
|
||||
this.setState(() => nextState);
|
||||
};
|
||||
|
||||
_handleLoadStart = () => {
|
||||
const nextState = { loading: true };
|
||||
if (this.props.logMethod === 'onLoadStart') {
|
||||
nextState.message = '✔ onLoadStart';
|
||||
}
|
||||
this.setState(() => nextState);
|
||||
};
|
||||
}
|
||||
|
||||
export default NetworkImageExample;
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import sources from '../sources';
|
||||
import React from 'react';
|
||||
import { Image, StyleSheet, Text } from 'react-native';
|
||||
|
||||
const ImageChildrenExample = () =>
|
||||
<Image source={sources.large} style={styles.image}>
|
||||
<Text style={styles.text}>React</Text>
|
||||
</Image>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
backgroundColor: 'transparent',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
text: {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'white'
|
||||
}
|
||||
});
|
||||
|
||||
export default ImageChildrenExample;
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import * as helpers from '../helpers';
|
||||
import sources from '../sources';
|
||||
import React from 'react';
|
||||
import { Image } from 'react-native';
|
||||
|
||||
const ImageDefaultSourceExample = () =>
|
||||
<Image
|
||||
defaultSource={sources.placeholder}
|
||||
source={sources.largeAlt}
|
||||
style={helpers.styles.base}
|
||||
/>;
|
||||
|
||||
export default ImageDefaultSourceExample;
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import sources from '../sources';
|
||||
import React from 'react';
|
||||
import { Image, StyleSheet, View } from 'react-native';
|
||||
|
||||
const ImageDraggableExample = () =>
|
||||
<View style={styles.container}>
|
||||
<Image draggable={false} source={sources.large} style={styles.image} />
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
image: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
backgroundColor: 'transparent',
|
||||
marginRight: 10
|
||||
}
|
||||
});
|
||||
|
||||
export default ImageDraggableExample;
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import NetworkImage from './NetworkImage';
|
||||
import React from 'react';
|
||||
import sources from '../sources';
|
||||
|
||||
const ImageOnErrorExample = () => <NetworkImage logMethod="onError" source={sources.broken} />;
|
||||
|
||||
export default ImageOnErrorExample;
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { createUncachedURI } from '../helpers';
|
||||
import NetworkImage from './NetworkImage';
|
||||
import React from 'react';
|
||||
import sources from '../sources';
|
||||
|
||||
const ImageOnLoadExample = () =>
|
||||
<NetworkImage logMethod="onLoad" source={createUncachedURI(sources.small)} />;
|
||||
|
||||
export default ImageOnLoadExample;
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { createUncachedURI } from '../helpers';
|
||||
import NetworkImage from './NetworkImage';
|
||||
import React from 'react';
|
||||
import sources from '../sources';
|
||||
|
||||
const ImageOnLoadEndExample = () =>
|
||||
<NetworkImage logMethod="onLoadEnd" source={createUncachedURI(sources.small)} />;
|
||||
|
||||
export default ImageOnLoadEndExample;
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { createUncachedURI } from '../helpers';
|
||||
import NetworkImage from './NetworkImage';
|
||||
import React from 'react';
|
||||
import sources from '../sources';
|
||||
|
||||
const ImageOnLoadStartExample = () =>
|
||||
<NetworkImage logMethod="onLoadStart" source={createUncachedURI(sources.small)} />;
|
||||
|
||||
export default ImageOnLoadStartExample;
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import sources from '../sources';
|
||||
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const ImageResizeModeExample = () =>
|
||||
<View>
|
||||
{[sources.small, sources.large].map((source, i) => {
|
||||
return (
|
||||
<View key={i}>
|
||||
<View style={styles.horizontal}>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>Contain</Text>
|
||||
<Image
|
||||
resizeMode={Image.resizeMode.contain}
|
||||
source={source}
|
||||
style={styles.resizeMode}
|
||||
/>
|
||||
</View>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>Cover</Text>
|
||||
<Image
|
||||
resizeMode={Image.resizeMode.cover}
|
||||
source={source}
|
||||
style={styles.resizeMode}
|
||||
/>
|
||||
</View>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>Stretch</Text>
|
||||
<Image
|
||||
resizeMode={Image.resizeMode.stretch}
|
||||
source={source}
|
||||
style={styles.resizeMode}
|
||||
/>
|
||||
</View>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>Repeat</Text>
|
||||
<Image resizeMode={'repeat'} source={source} style={styles.resizeMode} />
|
||||
</View>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>Center</Text>
|
||||
<Image resizeMode={'center'} source={source} style={styles.resizeMode} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontal: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
resizeMode: {
|
||||
borderColor: 'black',
|
||||
borderWidth: 0.5,
|
||||
height: 60,
|
||||
width: 90
|
||||
},
|
||||
resizeModeText: {
|
||||
fontSize: 11,
|
||||
marginBottom: 3
|
||||
},
|
||||
leftMargin: {
|
||||
marginLeft: 10
|
||||
}
|
||||
});
|
||||
|
||||
export default ImageResizeModeExample;
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import sources from '../sources';
|
||||
import React from 'react';
|
||||
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const ImageSourceExample = () =>
|
||||
<View style={styles.row}>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>Static image</Text>
|
||||
<Image source={sources.static} style={styles.image} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>Animated GIF</Text>
|
||||
<Image source={sources.animatedGif} style={styles.image} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>Data PNG</Text>
|
||||
<Image source={sources.dataPng} style={styles.image} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>Data SVG</Text>
|
||||
<Image source={sources.dataSvg} style={styles.image} />
|
||||
</View>
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap'
|
||||
},
|
||||
column: {
|
||||
marginRight: '1rem'
|
||||
},
|
||||
text: {
|
||||
marginBottom: '0.5rem'
|
||||
},
|
||||
image: {
|
||||
flex: 1,
|
||||
height: 50,
|
||||
resizeMode: 'contain'
|
||||
}
|
||||
});
|
||||
|
||||
export default ImageSourceExample;
|
||||
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { createUncachedURI } from '../helpers';
|
||||
import sources from '../sources';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Button, Image, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
class ImageGetSizeExample extends PureComponent {
|
||||
static propTypes = {
|
||||
source: Image.propTypes.source
|
||||
};
|
||||
|
||||
state = {
|
||||
showButton: true,
|
||||
startLoad: false,
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
|
||||
render() {
|
||||
const { showButton, startLoad } = this.state;
|
||||
|
||||
return (
|
||||
<View>
|
||||
{showButton
|
||||
? <View style={styles.button}>
|
||||
<Button onPress={this._handlePress} title="(4.7MB) Get image dimensions" />
|
||||
</View>
|
||||
: null}
|
||||
{startLoad
|
||||
? <View>
|
||||
<Text>
|
||||
Source dimensions:{' '}
|
||||
{JSON.stringify({ width: this.state.width, height: this.state.height })}
|
||||
</Text>
|
||||
<Image source={createUncachedURI(this.props.source.uri)} style={styles.image} />
|
||||
</View>
|
||||
: null}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handlePress = () => {
|
||||
Image.getSize(this.props.source.uri, (width, height) => {
|
||||
this.setState({ startLoad: true, showButton: false, width, height });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
maxWidth: 300
|
||||
},
|
||||
image: {
|
||||
backgroundColor: '#eee',
|
||||
height: 227,
|
||||
marginTop: 10,
|
||||
width: 323
|
||||
}
|
||||
});
|
||||
|
||||
const StaticGetSizeExample = () => <ImageGetSizeExample source={sources.huge} />;
|
||||
|
||||
export default StaticGetSizeExample;
|
||||
@@ -1,98 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { createUncachedURI } from '../helpers';
|
||||
import sources from '../sources';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Button, Image, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
class ImagePrefetchExample extends PureComponent {
|
||||
static propTypes = {
|
||||
source: Image.propTypes.source
|
||||
};
|
||||
|
||||
state = {
|
||||
events: [],
|
||||
showButton: true,
|
||||
startLoad: false
|
||||
};
|
||||
|
||||
render() {
|
||||
const { showButton, startLoad } = this.state;
|
||||
|
||||
return (
|
||||
<View>
|
||||
{showButton
|
||||
? <View style={styles.button}>
|
||||
<Button onPress={this._handlePress} title="Prefetch image" />
|
||||
</View>
|
||||
: null}
|
||||
{startLoad
|
||||
? <View>
|
||||
<Text>
|
||||
{this.state.events.join('\n')}
|
||||
</Text>
|
||||
<Image
|
||||
onLoad={this._handleLoad}
|
||||
onLoadEnd={this._handleLoadEnd}
|
||||
onLoadStart={this._handleLoadStart}
|
||||
source={this.props.source}
|
||||
style={styles.image}
|
||||
/>
|
||||
</View>
|
||||
: null}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleLoad = () => {
|
||||
const startTime = this._startTime;
|
||||
this._loadEventFired(`✔ (prefetched) onLoad (+${Date.now() - startTime}ms)`);
|
||||
};
|
||||
|
||||
_handleLoadEnd = () => {
|
||||
const startTime = this._startTime;
|
||||
this._loadEventFired(`✔ (prefetched) onLoadEnd (+${Date.now() - startTime}ms)`);
|
||||
};
|
||||
|
||||
_handleLoadStart = () => {
|
||||
const startTime = this._startTime;
|
||||
this._loadEventFired(`✔ (prefetched) onLoadStart (+${Date.now() - startTime}ms)`);
|
||||
};
|
||||
|
||||
_handlePress = () => {
|
||||
this._startTime = this._startTime || Date.now();
|
||||
|
||||
Image.prefetch(createUncachedURI(this.props.source.uri)).then(
|
||||
() => {
|
||||
this._loadEventFired('✔ Prefetch OK');
|
||||
this.setState(() => ({ startLoad: true }));
|
||||
},
|
||||
error => {
|
||||
this._loadEventFired(`✘ Prefetch failed (+${Date.now() - this._startTime}ms)`);
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
_loadEventFired = event => {
|
||||
this.setState(state => ({ events: [...state.events, event], showButton: false }));
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
maxWidth: 300
|
||||
},
|
||||
image: {
|
||||
backgroundColor: '#eee',
|
||||
height: 150,
|
||||
marginTop: 10,
|
||||
width: 150
|
||||
}
|
||||
});
|
||||
|
||||
const StaticPrefetchExample = () => <ImagePrefetchExample source={sources.prefetchable} />;
|
||||
|
||||
export default StaticPrefetchExample;
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
// import React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
const createUncachedURI = source => {
|
||||
const helper = str => `${str}?t=${Date.now()}`;
|
||||
const uri = typeof source === 'string' ? source : source.uri;
|
||||
return typeof source === 'string' ? helper(uri) : { ...source, uri: helper(uri) };
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
height: 38,
|
||||
width: 38
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
centerRow: {
|
||||
alignItems: 'center'
|
||||
},
|
||||
marginLeft: {
|
||||
marginLeft: '1rem'
|
||||
}
|
||||
});
|
||||
|
||||
export { createUncachedURI, styles };
|
||||
@@ -1,28 +0,0 @@
|
||||
import placeholder from './bunny.png';
|
||||
import staticImage from './uie_thumb_normal@2x.png';
|
||||
|
||||
const dataPng =
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
|
||||
const dataSvg =
|
||||
'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>';
|
||||
|
||||
const sources = {
|
||||
animatedGif: {
|
||||
uri:
|
||||
'http://38.media.tumblr.com/9e9bd08c6e2d10561dd1fb4197df4c4e/tumblr_mfqekpMktw1rn90umo1_500.gif'
|
||||
},
|
||||
broken: { uri: 'http://TYPO_ERROR.github.io/image.png' },
|
||||
small: { uri: 'http://facebook.github.io/react/img/logo_small_2x.png' },
|
||||
large: { uri: 'http://facebook.github.io/react/img/logo_og.png' },
|
||||
largeAlt: { uri: 'http://facebook.github.io/origami/public/images/birds.jpg' },
|
||||
placeholder,
|
||||
prefetchable: { uri: 'http://origami.design/public/images/bird-logo.png' },
|
||||
static: staticImage,
|
||||
huge: {
|
||||
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/d7/Chestnut-mandibled_Toucan.jpg'
|
||||
},
|
||||
dataPng,
|
||||
dataSvg
|
||||
};
|
||||
|
||||
export default sources;
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import PropColor from './examples/PropColor';
|
||||
import CustomSize from './examples/CustomSize';
|
||||
import PropIndeterminate from './examples/PropIndeterminate';
|
||||
import PropProgress from './examples/PropProgress';
|
||||
import PropTrackColor from './examples/PropTrackColor';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, { Description, DocItem, Section } from '../../ui-explorer';
|
||||
|
||||
const ProgressBarScreen = () =>
|
||||
<UIExplorer title="ProgressBar" url="components/ProgressBar">
|
||||
<Description>Display an activity progress bar</Description>
|
||||
<Section title="Props">
|
||||
<DocItem name="...View props" />
|
||||
|
||||
<DocItem
|
||||
description="Color of the progress bar."
|
||||
example={{
|
||||
render: () => <PropColor />
|
||||
}}
|
||||
name="color"
|
||||
typeInfo="?string = #1976D2"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="Whether the progress bar will show indeterminate progress."
|
||||
example={{
|
||||
render: () => <PropIndeterminate />
|
||||
}}
|
||||
name="indeterminate"
|
||||
typeInfo="?boolean = true"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="The progress value (between 0 and 1)."
|
||||
example={{
|
||||
render: () => <PropProgress />
|
||||
}}
|
||||
name="progress"
|
||||
typeInfo="?number"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="Color of the track bar."
|
||||
example={{
|
||||
render: () => <PropTrackColor />
|
||||
}}
|
||||
name="trackColor"
|
||||
typeInfo="?string = 'transparent'"
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title="More examples">
|
||||
<DocItem
|
||||
description="Custom sizes can be created using styles"
|
||||
example={{
|
||||
code: '<ProgressBar style={{ borderRadius: 10, height: 10 }} trackColor="#D1E3F6" />',
|
||||
render: () => <CustomSize />
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
storiesOf('Components', module).add('ProgressBar', ProgressBarScreen);
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { DividerVertical } from '../helpers';
|
||||
import React from 'react';
|
||||
import { ProgressBar, StyleSheet, View } from 'react-native';
|
||||
|
||||
const ProgressBarCustomSizeExample = () =>
|
||||
<View>
|
||||
<ProgressBar color="#1DA1F2" progress={0.33} style={styles.one} trackColor="#D1E3F6" />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#1DA1F2" progress={0.33} style={styles.two} trackColor="#D1E3F6" />
|
||||
</View>;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
one: {
|
||||
borderRadius: 10,
|
||||
height: 10
|
||||
},
|
||||
two: {
|
||||
borderRadius: 10,
|
||||
height: 20
|
||||
}
|
||||
});
|
||||
|
||||
export default ProgressBarCustomSizeExample;
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { DividerVertical } from '../helpers';
|
||||
import { ProgressBar, View } from 'react-native';
|
||||
|
||||
const ProgressBarColorExample = () =>
|
||||
<View>
|
||||
<ProgressBar color="#1DA1F2" progress={0.2} />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#17BF63" progress={0.4} />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#F45D22" progress={0.6} />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#794BC4" progress={0.8} />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#E0245E" progress={1.0} />
|
||||
</View>;
|
||||
|
||||
export default ProgressBarColorExample;
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ProgressBar } from 'react-native';
|
||||
|
||||
const ProgressBarIndeterminateExample = () => <ProgressBar indeterminate trackColor="#D1E3F6" />;
|
||||
|
||||
export default ProgressBarIndeterminateExample;
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { DividerVertical } from '../helpers';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { ProgressBar, StyleSheet, View } from 'react-native';
|
||||
|
||||
class ProgressBarProgressExample extends PureComponent {
|
||||
state = { progress: 0 };
|
||||
|
||||
componentDidMount() {
|
||||
this._updateProgress();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.cancelAnimationFrame(this._frame);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<ProgressBar color="#794BC4" progress={0.2} style={styles.progress} />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#794BC4" progress={this._getProgress(0.2)} style={styles.progress} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_getProgress(offset) {
|
||||
const progress = this.state.progress + offset;
|
||||
return Math.sin(progress % Math.PI) % 1;
|
||||
}
|
||||
|
||||
_updateProgress() {
|
||||
const progress = this.state.progress + 0.01;
|
||||
this.setState(() => ({ progress }));
|
||||
this._frame = window.requestAnimationFrame(() => this._updateProgress());
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
progress: {
|
||||
minWidth: 200
|
||||
}
|
||||
});
|
||||
|
||||
export default ProgressBarProgressExample;
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { DividerVertical } from '../helpers';
|
||||
import React from 'react';
|
||||
import { ProgressBar, View } from 'react-native';
|
||||
|
||||
const ProgressBarTrackColorExample = () =>
|
||||
<View>
|
||||
<ProgressBar color="#1DA1F2" progress={0.1} trackColor="#17BF63" />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#1DA1F2" progress={0.2} trackColor="#F45D22" />
|
||||
<DividerVertical />
|
||||
<ProgressBar color="#1DA1F2" progress={0.3} trackColor="#794BC4" />
|
||||
</View>;
|
||||
|
||||
export default ProgressBarTrackColorExample;
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
|
||||
const DividerHorizontal = () => <View style={styles.horizontalDivider} />;
|
||||
const DividerVertical = () => <View style={styles.verticalDivider} />;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontalDivider: {
|
||||
width: '0.6rem'
|
||||
},
|
||||
verticalDivider: {
|
||||
height: '1.3125rem'
|
||||
}
|
||||
});
|
||||
|
||||
export { DividerHorizontal, DividerVertical };
|
||||
@@ -1,171 +0,0 @@
|
||||
/* eslint-disable react/jsx-no-bind, react/jsx-sort-props */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { HorizontalExample } from './examples/Horizontal';
|
||||
import ScrollToExample from './examples/ScrollTo';
|
||||
import ScrollToEndExample from './examples/ScrollToEnd';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, {
|
||||
AppText,
|
||||
Code,
|
||||
Description,
|
||||
DocItem,
|
||||
Section,
|
||||
TextList
|
||||
} from '../../ui-explorer';
|
||||
|
||||
const ScrollViewScreen = () =>
|
||||
<UIExplorer title="ScrollView" url="components/ScrollView">
|
||||
<Description>
|
||||
<AppText>
|
||||
A scrollable <Code>View</Code> that provides itegration with the touch-locking responder
|
||||
system. <Code>ScrollView</Code>'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 <Code>{'{ flex: 1}'}</Code> down the view stack).
|
||||
</AppText>
|
||||
</Description>
|
||||
|
||||
<Section title="Props">
|
||||
<DocItem name="...View props" />
|
||||
|
||||
<DocItem
|
||||
name="contentContainerStyle"
|
||||
typeInfo="?style"
|
||||
description="These styles will be applied to the scroll view content container which wraps all of the child views."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="horizontal"
|
||||
typeInfo="?boolean = false"
|
||||
description="When true, the scroll view's children are arranged horizontally in a row instead of vertically in a column."
|
||||
example={{
|
||||
render: () => <HorizontalExample />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="keyboardDismissMode"
|
||||
typeInfo="?enum('none', 'on-drag') = 'none'"
|
||||
description={[
|
||||
<AppText>
|
||||
Determines whether the keyboard gets dismissed in response to a scroll drag.
|
||||
</AppText>,
|
||||
<TextList
|
||||
items={[
|
||||
<AppText>
|
||||
<Code>none</Code> (the default): drags do not dismiss the keyboard.
|
||||
</AppText>,
|
||||
<AppText>
|
||||
<Code>on-drag</Code>: the keyboard is dismissed when a drag begins.
|
||||
</AppText>,
|
||||
<AppText>
|
||||
<Code>interactive</Code> (not supported on web; same as <Code>none</Code>)
|
||||
</AppText>
|
||||
]}
|
||||
/>
|
||||
]}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onContentSizeChange"
|
||||
typeInfo="?function"
|
||||
description={
|
||||
<AppText>
|
||||
Called when scrollable content view of the <Code>ScrollView</Code> changes. It's
|
||||
implemented using the <Code>onLayout</Code> handler attached to the content container
|
||||
which this <Code>ScrollView</Code> renders.
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onScroll"
|
||||
typeInfo="?function"
|
||||
description={[
|
||||
<AppText>
|
||||
Fires at most once per frame during scrolling. The frequency of the events can be
|
||||
contolled using the <Code>scrollEventThrottle</Code> prop.
|
||||
</AppText>,
|
||||
<AppText>Invoked on scroll with the following event:</AppText>,
|
||||
<Code>{`{
|
||||
nativeEvent: {
|
||||
contentOffset: { x, y },
|
||||
contentSize: { height, width },
|
||||
layoutMeasurement: { height, width }
|
||||
}
|
||||
}`}</Code>
|
||||
]}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="scrollEnabled"
|
||||
typeInfo="?boolean = true"
|
||||
description="When false, the content does not scroll."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="scrollEventThrottle"
|
||||
typeInfo="?number = 0"
|
||||
description={
|
||||
<AppText>
|
||||
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{' '}
|
||||
<Code>0</Code>, which means the scroll event will be sent only once each time the view
|
||||
is scrolled.
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title="Instance methods">
|
||||
<DocItem
|
||||
name="getInnerViewNode"
|
||||
typeInfo="() => node"
|
||||
description="Returns a reference to the underlying content container DOM node within the ScrollView."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="getScrollableNode"
|
||||
typeInfo="() => node"
|
||||
description="Returns a reference to the underlying scrollable DOM node."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="getScrollResponder"
|
||||
typeInfo="() => ScrollResponder"
|
||||
description={
|
||||
<AppText>
|
||||
Returns a reference to the underlying scroll responder, which supports operations like{' '}
|
||||
<Code>scrollTo</Code>. All <Code>ScrollView</Code>-like components should implement this
|
||||
method so that they can be composed while providing access to the underlying scroll
|
||||
responder's methods.
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="scrollTo"
|
||||
typeInfo="(options: { x: number = 0; y: number = 0; animated: boolean = true }) => void"
|
||||
description="Scrolls to a given `x`, `y` offset (animation is not currently supported)."
|
||||
example={{
|
||||
render: () => <ScrollToExample />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="scrollToEnd"
|
||||
typeInfo="(options: { animated: boolean = true }) => void"
|
||||
description="Scrolls to the end of the scroll view."
|
||||
example={{
|
||||
render: () => <ScrollToEndExample />
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
storiesOf('Components', module).add('ScrollView', ScrollViewScreen);
|
||||
@@ -1,69 +0,0 @@
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { action } from '@kadira/storybook';
|
||||
import { ScrollView, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const onScroll = action('ScrollView.onScroll');
|
||||
|
||||
const VerticalExample = () =>
|
||||
<View style={styles.scrollViewContainer}>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollViewContentContainerStyle}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={16} // ~60 events per second
|
||||
style={styles.scrollViewStyle}
|
||||
>
|
||||
{Array.from({ length: 50 }).map((item, i) =>
|
||||
<View key={i} style={[styles.box, styles.horizontalBox]}>
|
||||
<Text>
|
||||
{i}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>;
|
||||
|
||||
const HorizontalExample = () =>
|
||||
<View style={styles.scrollViewContainer}>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollViewContentContainerStyle}
|
||||
horizontal
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={16} // ~60 events per second
|
||||
style={styles.scrollViewStyle}
|
||||
>
|
||||
{Array.from({ length: 50 }).map((item, i) =>
|
||||
<View key={i} style={[styles.box, styles.horizontalBox]}>
|
||||
<Text>
|
||||
{i}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>;
|
||||
|
||||
export { HorizontalExample, VerticalExample };
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
box: {
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center',
|
||||
borderWidth: 1
|
||||
},
|
||||
scrollViewContainer: {
|
||||
height: 200,
|
||||
width: 300
|
||||
},
|
||||
scrollViewStyle: {
|
||||
borderWidth: 1
|
||||
},
|
||||
scrollViewContentContainerStyle: {
|
||||
backgroundColor: '#eee',
|
||||
padding: 10
|
||||
}
|
||||
});
|
||||
@@ -1,63 +0,0 @@
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Button, ScrollView, StyleSheet, Text, TouchableHighlight, View } from 'react-native';
|
||||
|
||||
export default class ScrollToExample extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.scrollViewContainer}>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollViewContentContainerStyle}
|
||||
ref={scrollview => {
|
||||
this.scrollview = scrollview;
|
||||
}}
|
||||
scrollEventThrottle={16} // ~60 events per second
|
||||
style={styles.scrollViewStyle}
|
||||
>
|
||||
{Array.from({ length: 50 }).map((item, i) =>
|
||||
<TouchableHighlight
|
||||
key={i}
|
||||
onPress={() => {}}
|
||||
style={[styles.box, styles.horizontalBox]}
|
||||
>
|
||||
<Text>
|
||||
{i}
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
)}
|
||||
</ScrollView>
|
||||
<Button
|
||||
onPress={() => {
|
||||
this.scrollview.scrollTo({ y: 100 });
|
||||
}}
|
||||
title="Scroll to 100px"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
box: {
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center',
|
||||
borderWidth: 1
|
||||
},
|
||||
scrollViewContainer: {
|
||||
height: 150,
|
||||
width: 300
|
||||
},
|
||||
scrollViewStyle: {
|
||||
borderWidth: 1,
|
||||
marginBottom: '1.3125rem'
|
||||
},
|
||||
scrollViewContentContainerStyle: {
|
||||
backgroundColor: '#eee',
|
||||
padding: 10
|
||||
}
|
||||
});
|
||||
@@ -1,59 +0,0 @@
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Button, ScrollView, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
export default class ScrollToEndExample extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.scrollViewContainer}>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollViewContentContainerStyle}
|
||||
ref={scrollview => {
|
||||
this.scrollview = scrollview;
|
||||
}}
|
||||
scrollEventThrottle={16} // ~60 events per second
|
||||
style={styles.scrollViewStyle}
|
||||
>
|
||||
{Array.from({ length: 50 }).map((item, i) =>
|
||||
<View key={i} style={[styles.box, styles.horizontalBox]}>
|
||||
<Text>
|
||||
{i}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
<Button
|
||||
onPress={() => {
|
||||
this.scrollview.scrollToEnd();
|
||||
}}
|
||||
title="Scroll to end"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
box: {
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center',
|
||||
borderWidth: 1
|
||||
},
|
||||
scrollViewContainer: {
|
||||
height: 150,
|
||||
width: 300
|
||||
},
|
||||
scrollViewStyle: {
|
||||
borderWidth: 1,
|
||||
marginBottom: '1.3125rem'
|
||||
},
|
||||
scrollViewContentContainerStyle: {
|
||||
backgroundColor: '#eee',
|
||||
padding: 10
|
||||
}
|
||||
});
|
||||
@@ -1,129 +0,0 @@
|
||||
/* eslint-disable react/jsx-sort-props */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import CustomSize from './examples/CustomSize';
|
||||
import PropActiveThumbColor from './examples/PropActiveThumbColor';
|
||||
import PropActiveTrackColor from './examples/PropActiveTrackColor';
|
||||
import PropDisabled from './examples/PropDisabled';
|
||||
import PropOnValueChange from './examples/PropOnValueChange';
|
||||
import PropThumbColor from './examples/PropThumbColor';
|
||||
import PropTrackColor from './examples/PropTrackColor';
|
||||
import PropValue from './examples/PropValue';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, { AppText, Code, Description, DocItem, Section } from '../../ui-explorer';
|
||||
|
||||
const SwitchScreen = () =>
|
||||
<UIExplorer title="Switch" url="components/Switch">
|
||||
<Description>
|
||||
<AppText>
|
||||
This is a controlled component that requires an <Code>onValueChange</Code> callback that
|
||||
updates the value prop in order for the component to reflect user actions. If the{' '}
|
||||
<Code>value</Code> prop is not updated, the component will continue to render the supplied{' '}
|
||||
<Code>value</Code> prop instead of the expected result of any user actions.
|
||||
</AppText>
|
||||
</Description>
|
||||
|
||||
<Section title="Props">
|
||||
<DocItem name="...View props" />
|
||||
|
||||
<DocItem
|
||||
description="The color of the thumb grip when the switch is turned on."
|
||||
example={{
|
||||
render: () => <PropActiveThumbColor />
|
||||
}}
|
||||
name="activeThumbColor"
|
||||
typeInfo="?color = #009688"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="The color of the track when the switch is turned on."
|
||||
example={{
|
||||
render: () => <PropActiveTrackColor />
|
||||
}}
|
||||
name="activeTrackColor"
|
||||
typeInfo="?color = #A3D3CF"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="If true, the user won't be able to interact with the switch."
|
||||
example={{
|
||||
render: () => <PropDisabled />
|
||||
}}
|
||||
name="disabled"
|
||||
typeInfo="?boolean = false"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="Invoked with the new value when the value changes."
|
||||
example={{
|
||||
render: () => <PropOnValueChange />
|
||||
}}
|
||||
name="onValueChange"
|
||||
typeInfo="?function"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="The color of the thumb grip when the switch is turned off."
|
||||
example={{
|
||||
render: () => <PropThumbColor />
|
||||
}}
|
||||
name="thumbColor"
|
||||
typeInfo="?color = #FAFAFA"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="The color of the track when the switch is turned off."
|
||||
example={{
|
||||
render: () => <PropTrackColor />
|
||||
}}
|
||||
name="trackColor"
|
||||
typeInfo="?color = #939393"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="The value of the switch. If `true` the switch will be turned on."
|
||||
example={{
|
||||
render: () => <PropValue />
|
||||
}}
|
||||
name="value"
|
||||
typeInfo="?boolean = false"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="(For compatibility with React Native. Equivalent to "activeTrackColor")"
|
||||
label="compat"
|
||||
name="onTintColor"
|
||||
typeInfo="?color"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="(For compatibility with React Native. Equivalent to "trackColor")"
|
||||
label="compat"
|
||||
name="tintColor"
|
||||
typeInfo="?color"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="(For compatibility with React Native. Equivalent to "thumbColor")"
|
||||
label="compat"
|
||||
name="thumbTintColor"
|
||||
typeInfo="?color"
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title="More examples">
|
||||
<DocItem
|
||||
description="Custom sizes can be created using styles"
|
||||
example={{
|
||||
code: '<Switch style={{ height: 30 }} />',
|
||||
render: () => <CustomSize />
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
storiesOf('Components', module).add('Switch', SwitchScreen);
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Switch, View } from 'react-native';
|
||||
|
||||
class CustomSizeExample extends PureComponent {
|
||||
state = {
|
||||
firstIsOn: true,
|
||||
secondIsOn: false
|
||||
};
|
||||
|
||||
render() {
|
||||
const { firstIsOn, secondIsOn } = this.state;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Switch
|
||||
onValueChange={this._handleFirst}
|
||||
style={{ marginBottom: 10, height: 30 }}
|
||||
value={firstIsOn}
|
||||
/>
|
||||
<Switch
|
||||
onValueChange={this._handleSecond}
|
||||
style={{ height: 30, width: 150 }}
|
||||
value={secondIsOn}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleFirst = value => {
|
||||
this.setState({ firstIsOn: value });
|
||||
};
|
||||
|
||||
_handleSecond = value => {
|
||||
this.setState({ secondIsOn: value });
|
||||
};
|
||||
}
|
||||
|
||||
export default CustomSizeExample;
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { Switch, View } from 'react-native';
|
||||
|
||||
const colors = ['#1DA1F2', '#17BF63', '#F45D22', '#794BC4', '#E0245E'];
|
||||
const itemStyle = [styles.marginVertical, styles.marginRight];
|
||||
|
||||
const SwitchActiveThumbColorExample = () =>
|
||||
<View style={styles.row}>
|
||||
<View style={itemStyle}>
|
||||
<Switch value={true} />
|
||||
</View>
|
||||
{colors.map((color, i) =>
|
||||
<View key={i} style={itemStyle}>
|
||||
<Switch activeThumbColor={color} activeTrackColor="#ccc" value={true} />
|
||||
</View>
|
||||
)}
|
||||
</View>;
|
||||
|
||||
export default SwitchActiveThumbColorExample;
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { Switch, View } from 'react-native';
|
||||
|
||||
const colors = ['#1DA1F2', '#17BF63', '#F45D22', '#794BC4', '#E0245E'];
|
||||
const itemStyle = [styles.marginVertical, styles.marginRight];
|
||||
|
||||
const SwitchActiveTrackColorExample = () =>
|
||||
<View style={styles.row}>
|
||||
<View style={itemStyle}>
|
||||
<Switch value={true} />
|
||||
</View>
|
||||
{colors.map((color, i) =>
|
||||
<View key={i} style={itemStyle}>
|
||||
<Switch activeThumbColor="#ccc" activeTrackColor={color} value={true} />
|
||||
</View>
|
||||
)}
|
||||
</View>;
|
||||
|
||||
export default SwitchActiveTrackColorExample;
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { Switch, View } from 'react-native';
|
||||
|
||||
const SwitchDisabledExample = () =>
|
||||
<View style={styles.row}>
|
||||
<View style={styles.marginRight}>
|
||||
<Switch disabled={true} value={false} />
|
||||
</View>
|
||||
<View style={styles.marginRight}>
|
||||
<Switch disabled={true} value={true} />
|
||||
</View>
|
||||
</View>;
|
||||
|
||||
export default SwitchDisabledExample;
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { styles } from '../helpers';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Switch, Text, View } from 'react-native';
|
||||
|
||||
class SwitchOnValueChangeExample extends PureComponent {
|
||||
state = {
|
||||
eventSwitchIsOn: false,
|
||||
eventSwitchRegressionIsOn: true
|
||||
};
|
||||
|
||||
render() {
|
||||
const { eventSwitchIsOn, eventSwitchRegressionIsOn } = this.state;
|
||||
|
||||
return (
|
||||
<View style={styles.row}>
|
||||
<View style={[styles.alignCenter, styles.marginRight]}>
|
||||
<Switch
|
||||
onValueChange={this._handleEventSwitch}
|
||||
style={styles.marginBottom}
|
||||
value={eventSwitchIsOn}
|
||||
/>
|
||||
<Switch
|
||||
onValueChange={this._handleEventSwitch}
|
||||
style={styles.marginBottom}
|
||||
value={eventSwitchIsOn}
|
||||
/>
|
||||
<Text>
|
||||
{eventSwitchIsOn ? 'On' : 'Off'}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.alignCenter}>
|
||||
<Switch
|
||||
onValueChange={this._handleEventSwitchRegression}
|
||||
style={styles.marginBottom}
|
||||
value={eventSwitchRegressionIsOn}
|
||||
/>
|
||||
<Switch
|
||||
onValueChange={this._handleEventSwitchRegression}
|
||||
style={styles.marginBottom}
|
||||
value={eventSwitchRegressionIsOn}
|
||||
/>
|
||||
<Text>
|
||||
{eventSwitchRegressionIsOn ? 'On' : 'Off'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleEventSwitch = value => {
|
||||
this.setState({ eventSwitchIsOn: value });
|
||||
};
|
||||
|
||||
_handleEventSwitchRegression = value => {
|
||||
this.setState({ eventSwitchRegressionIsOn: value });
|
||||
};
|
||||
}
|
||||
|
||||
export default SwitchOnValueChangeExample;
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { Switch, View } from 'react-native';
|
||||
|
||||
const colors = ['#ddd', '#aaa', '#999', '#666', '#000'];
|
||||
const itemStyle = [styles.marginVertical, styles.marginRight];
|
||||
|
||||
const SwitchThumbColorExample = () =>
|
||||
<View style={styles.row}>
|
||||
<View style={itemStyle}>
|
||||
<Switch value={false} />
|
||||
</View>
|
||||
{colors.map((color, i) =>
|
||||
<View key={i} style={itemStyle}>
|
||||
<Switch thumbColor={color} value={false} />
|
||||
</View>
|
||||
)}
|
||||
</View>;
|
||||
|
||||
export default SwitchThumbColorExample;
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { Switch, View } from 'react-native';
|
||||
|
||||
const colors = ['#ddd', '#aaa', '#999', '#666', '#000'];
|
||||
const itemStyle = [styles.marginVertical, styles.marginRight];
|
||||
|
||||
const SwitchTrackColorExample = () =>
|
||||
<View style={styles.row}>
|
||||
<View style={itemStyle}>
|
||||
<Switch value={false} />
|
||||
</View>
|
||||
{colors.map((color, i) =>
|
||||
<View key={i} style={itemStyle}>
|
||||
<Switch trackColor={color} value={false} />
|
||||
</View>
|
||||
)}
|
||||
</View>;
|
||||
|
||||
export default SwitchTrackColorExample;
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { styles } from '../helpers';
|
||||
import React from 'react';
|
||||
import { Switch, View } from 'react-native';
|
||||
|
||||
const SwitchValueExample = () =>
|
||||
<View style={styles.row}>
|
||||
<View style={styles.marginRight}>
|
||||
<Switch value={false} />
|
||||
</View>
|
||||
<View style={styles.marginRight}>
|
||||
<Switch value={true} />
|
||||
</View>
|
||||
</View>;
|
||||
|
||||
export default SwitchValueExample;
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
|
||||
const DividerHorizontal = () => <View style={styles.horizontalDivider} />;
|
||||
const DividerVertical = () => <View style={styles.verticalDivider} />;
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
horizontalDivider: {
|
||||
width: '0.6rem'
|
||||
},
|
||||
verticalDivider: {
|
||||
height: '1.3125rem'
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap'
|
||||
},
|
||||
marginRight: {
|
||||
marginRight: 10
|
||||
},
|
||||
marginBottom: {
|
||||
marginBottom: 10
|
||||
},
|
||||
marginVertical: {
|
||||
marginVertical: 5
|
||||
},
|
||||
alignCenter: {
|
||||
alignItems: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
export { DividerHorizontal, DividerVertical };
|
||||
@@ -1,262 +0,0 @@
|
||||
/* eslint-disable react/jsx-sort-props */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import PropChildren from './examples/PropChildren';
|
||||
import PropNumberOfLines from './examples/PropNumberOfLines';
|
||||
import PropOnPress from './examples/PropOnPress';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, {
|
||||
AppText,
|
||||
Code,
|
||||
Description,
|
||||
DocItem,
|
||||
Section,
|
||||
StyleList
|
||||
} from '../../ui-explorer';
|
||||
|
||||
const TextScreen = () =>
|
||||
<UIExplorer title="Text" url="components/Text">
|
||||
<Description>
|
||||
<AppText>
|
||||
Text is component for displaying text. It supports style, basic touch handling, and inherits
|
||||
typographic styles from ancestor elements.
|
||||
</AppText>
|
||||
<AppText>
|
||||
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.
|
||||
</AppText>
|
||||
<AppText>NOTE: Text will transfer all other props to the rendered HTML element.</AppText>
|
||||
</Description>
|
||||
|
||||
<Section title="Props">
|
||||
<DocItem
|
||||
name="accessibilityLabel"
|
||||
typeInfo="?string"
|
||||
description="Overrides the text that is read by a screen reader when the user interacts with the element. (This is implemented using 'aria-label'.)"
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="accessibilityLiveRegion"
|
||||
typeInfo="?enum('assertive', 'none', 'polite')"
|
||||
description={
|
||||
<AppText>
|
||||
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 <Code>polite</Code> (recommended), updates take low priority. When regions
|
||||
are specified as <Code>assertive</Code>, assistive technologies will interrupt and
|
||||
immediately notify the user. (This is implemented using 'aria-live'.)
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
label="web"
|
||||
name="accessibilityRole"
|
||||
typeInfo="?enum(roles)"
|
||||
description={
|
||||
<AppText>
|
||||
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 <Code>accessibilityRole</Code> of{' '}
|
||||
<Code>button</Code>. For compatibility with React Native{' '}
|
||||
<Code>accessibilityTraits</Code> and <Code>accessibilityComponentType</Code> are mapped
|
||||
to <Code>accessibilityRole</Code>. (This is implemented using ARIA roles.)
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="accessible"
|
||||
typeInfo="?boolean"
|
||||
description={
|
||||
<AppText>
|
||||
When <Code>true</Code>, 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 <Code>accessibilityRole</Code> of <Code>button</Code> and{' '}
|
||||
<Code>link</Code> are accessible. (This is implemented using 'tabindex'.)
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="children"
|
||||
typeInfo="?any"
|
||||
description={`Child content. Nested text components will inherit the styles of their parents
|
||||
(only backgroundColor is inherited from non-Text parents). <Text>
|
||||
only supports other <Text> and raw text (strings) as children.`}
|
||||
example={{
|
||||
render: () => <PropChildren />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="importantForAccessibility"
|
||||
typeInfo="?enum('auto', 'no', 'no-hide-descendants', 'yes')"
|
||||
description={[
|
||||
<AppText>
|
||||
A value of <Code>no</Code> will remove the element from the tab flow.
|
||||
</AppText>,
|
||||
<AppText>
|
||||
A value of <Code>no-hide-descendants</Code> will hide the element and its children from
|
||||
assistive technologies. (This is implemented using 'aria-hidden'.)
|
||||
</AppText>
|
||||
]}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="numberOfLines"
|
||||
typeInfo="?number"
|
||||
description="Truncates the text with an ellipsis after this many lines. Currently only supports `1`."
|
||||
example={{
|
||||
render: () => <PropNumberOfLines />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onLayout"
|
||||
typeInfo="?function"
|
||||
description={
|
||||
<AppText>
|
||||
Invoked on mount and layout changes with{' '}
|
||||
<Code>{'{ nativeEvent: { layout: { x, y, width, height } } }'}</Code>, where{' '}
|
||||
<Code>x</Code> and <Code>y</Code> are the offsets from the parent node.
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onPress"
|
||||
typeInfo="?function"
|
||||
description="Called when the Text is pressed"
|
||||
example={{
|
||||
render: () => <PropOnPress />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="selectable"
|
||||
typeInfo="?boolean"
|
||||
description="When false, the text is not selectable."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="style"
|
||||
typeInfo="?style"
|
||||
description={<StyleList stylePropTypes={stylePropTypes} />}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="testID"
|
||||
typeInfo="?string"
|
||||
description="Used to locate this view in end-to-end tests. The test ID is rendered to a 'data-testid' DOM attribute"
|
||||
/>
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
const stylePropTypes = [
|
||||
{
|
||||
name: '...View#style'
|
||||
},
|
||||
{
|
||||
name: 'color',
|
||||
typeInfo: 'color'
|
||||
},
|
||||
{
|
||||
name: 'fontFamily',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'fontFeatureSettings',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'fontSize',
|
||||
typeInfo: 'number | string'
|
||||
},
|
||||
{
|
||||
name: 'fontStyle',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'fontWeight',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'letterSpacing',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'lineHeight',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'textAlign',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'textAlignVertical',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'textDecorationLine',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'textIndent',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'textOverflow',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'textRendering',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'textShadowColor',
|
||||
typeInfo: 'color'
|
||||
},
|
||||
{
|
||||
name: 'textShadowOffset',
|
||||
typeInfo: '{ height: number, width: number }'
|
||||
},
|
||||
{
|
||||
name: 'textShadowRadius',
|
||||
typeInfo: 'number | string'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'textTransform',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'unicodeBidi',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'whiteSpace',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'wordWrap',
|
||||
typeInfo: 'string'
|
||||
},
|
||||
{
|
||||
name: 'writingDirection',
|
||||
typeInfo: 'string'
|
||||
}
|
||||
];
|
||||
|
||||
storiesOf('Components', module).add('Text', TextScreen);
|
||||
@@ -1,56 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Image, Text, View } from 'react-native';
|
||||
|
||||
const Entity = ({ children }) =>
|
||||
<Text style={{ fontWeight: '500', color: '#527fe4' }}>
|
||||
{children}
|
||||
</Text>;
|
||||
|
||||
const TextChildrenExample = () =>
|
||||
<View>
|
||||
<Text>
|
||||
This text contains an inline blue view{' '}
|
||||
<View style={{ width: 25, height: 25, backgroundColor: 'steelblue' }} /> and an inline image{' '}
|
||||
<Image
|
||||
source={{ uri: 'http://lorempixel.com/30/11' }}
|
||||
style={{ width: 30, height: 11, resizeMode: 'cover' }}
|
||||
/>
|
||||
. Neat, huh?
|
||||
</Text>
|
||||
|
||||
<View>
|
||||
<Text>
|
||||
(Normal text,
|
||||
<Text style={{ fontWeight: 'bold' }}>
|
||||
(and bold
|
||||
<Text style={{ fontSize: 11, color: '#527fe4' }}>(and tiny inherited bold blue)</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
<Text style={{ opacity: 0.7 }}>
|
||||
(opacity
|
||||
<Text>
|
||||
(is inherited
|
||||
<Text style={{ opacity: 0.7 }}>
|
||||
(and accumulated
|
||||
<Text style={{ backgroundColor: '#ffaaaa' }}>(and also applies to the background)</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
<Text style={{ fontSize: 12 }}>
|
||||
<Entity>Entity Name</Entity>
|
||||
</Text>
|
||||
</View>
|
||||
</View>;
|
||||
|
||||
export default TextChildrenExample;
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
|
||||
const TextNumberOfLinesExample = () =>
|
||||
<View style={{ maxWidth: 320 }}>
|
||||
<Text numberOfLines={1}>
|
||||
Maximum of one line, no matter how much I write here. If I keep writing, it
|
||||
{"'"}
|
||||
ll just truncate after one line.
|
||||
</Text>
|
||||
<Text numberOfLines={2} style={{ marginTop: 20 }}>
|
||||
Maximum of two lines, no matter how much I write here. If I keep writing, it
|
||||
{"'"}
|
||||
ll just truncate after two lines.
|
||||
</Text>
|
||||
<Text style={{ marginTop: 20 }}>
|
||||
No maximum lines specified, no matter how much I write here. If I keep writing, it
|
||||
{"'"}
|
||||
ll just keep going and going.
|
||||
</Text>
|
||||
</View>;
|
||||
|
||||
export default TextNumberOfLinesExample;
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
const TextOnLayoutExample = () => <Text />;
|
||||
|
||||
export default TextOnLayoutExample;
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
class TextOnPressExample extends React.Component {
|
||||
state = { timesPressed: 0 };
|
||||
|
||||
render() {
|
||||
let textLog = '';
|
||||
if (this.state.timesPressed > 1) {
|
||||
textLog = this.state.timesPressed + 'x text onPress';
|
||||
} else if (this.state.timesPressed > 0) {
|
||||
textLog = 'text onPress';
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text onPress={this._handlePress} style={styles.textBlock}>
|
||||
Text has built-in onPress handling
|
||||
</Text>
|
||||
<View style={styles.logBox}>
|
||||
<Text>
|
||||
{textLog}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handlePress = () => {
|
||||
this.setState({
|
||||
timesPressed: this.state.timesPressed + 1
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
logBox: {
|
||||
padding: 20,
|
||||
marginTop: 10,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: '#f0f0f0',
|
||||
backgroundColor: '#f9f9f9'
|
||||
},
|
||||
textBlock: {
|
||||
fontWeight: '500',
|
||||
color: 'blue'
|
||||
}
|
||||
});
|
||||
|
||||
export default TextOnPressExample;
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/*
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
const ViewStyleExample = () => null;
|
||||
|
||||
export default ViewStyleExample;
|
||||
*/
|
||||
@@ -1,445 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/*
|
||||
import createReactClass from 'create-react-class';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, { PropText, StyleList } from '../../ui-explorer';
|
||||
import { Image, Text, View } from 'react-native';
|
||||
|
||||
const AttributeToggler = createReactClass({
|
||||
getInitialState: function() {
|
||||
return { fontWeight: 'bold', fontSize: 15 };
|
||||
},
|
||||
toggleWeight: function() {
|
||||
this.setState({
|
||||
fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold'
|
||||
});
|
||||
},
|
||||
increaseSize: function() {
|
||||
this.setState({
|
||||
fontSize: this.state.fontSize + 1
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
const curStyle = { fontWeight: this.state.fontWeight, fontSize: this.state.fontSize };
|
||||
return (
|
||||
<View>
|
||||
<Text style={curStyle}>
|
||||
Tap the controls below to change attributes.
|
||||
</Text>
|
||||
<Text>
|
||||
<Text>See how it will even work on <Text style={curStyle}>this nested text</Text></Text>
|
||||
</Text>
|
||||
<Text onPress={this.toggleWeight} style={{ backgroundColor: '#ffaaaa', marginTop: 5 }}>
|
||||
Toggle Weight
|
||||
</Text>
|
||||
<Text onPress={this.increaseSize} style={{ backgroundColor: '#aaaaff', marginTop: 5 }}>
|
||||
Increase Size
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const examples = [
|
||||
{
|
||||
title: 'Wrap',
|
||||
render: function() {
|
||||
return (
|
||||
<Text style={{ WebkitFontSmoothing: 'antialiased' }}>
|
||||
The text should wrap if it goes on multiple lines. See, this is going to
|
||||
the next line.
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Padding',
|
||||
render: function() {
|
||||
return (
|
||||
<Text style={{ padding: 10 }}>
|
||||
This text is indented by 10px padding on all sides.
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Font Family',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{ fontFamily: 'Cochin' }}>
|
||||
Cochin
|
||||
</Text>
|
||||
<Text style={{ fontFamily: 'Cochin', fontWeight: 'bold' }}>
|
||||
Cochin bold
|
||||
</Text>
|
||||
<Text style={{ fontFamily: 'Helvetica' }}>
|
||||
Helvetica
|
||||
</Text>
|
||||
<Text style={{ fontFamily: 'Helvetica', fontWeight: 'bold' }}>
|
||||
Helvetica bold
|
||||
</Text>
|
||||
<Text style={{ fontFamily: 'Verdana' }}>
|
||||
Verdana
|
||||
</Text>
|
||||
<Text style={{ fontFamily: 'Verdana', fontWeight: 'bold' }}>
|
||||
Verdana bold
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Font Size',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{ fontSize: 23 }}>
|
||||
Size 23
|
||||
</Text>
|
||||
<Text style={{ fontSize: 8 }}>
|
||||
Size 8
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Color',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{ color: 'red' }}>
|
||||
Red color
|
||||
</Text>
|
||||
<Text style={{ color: 'blue' }}>
|
||||
Blue color
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Font Weight',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{ fontSize: 20, fontWeight: '100' }}>
|
||||
Move fast and be ultralight
|
||||
</Text>
|
||||
<Text style={{ fontSize: 20, fontWeight: '200' }}>
|
||||
Move fast and be light
|
||||
</Text>
|
||||
<Text style={{ fontSize: 20, fontWeight: 'normal' }}>
|
||||
Move fast and be normal
|
||||
</Text>
|
||||
<Text style={{ fontSize: 20, fontWeight: 'bold' }}>
|
||||
Move fast and be bold
|
||||
</Text>
|
||||
<Text style={{ fontSize: 20, fontWeight: '900' }}>
|
||||
Move fast and be ultrabold
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Font Style',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{ fontStyle: 'normal' }}>
|
||||
Normal text
|
||||
</Text>
|
||||
<Text style={{ fontStyle: 'italic' }}>
|
||||
Italic text
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Text Decoration',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{ textDecorationLine: 'underline', textDecorationStyle: 'solid' }}>
|
||||
Solid underline
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationStyle: 'double',
|
||||
textDecorationColor: '#ff0000'
|
||||
}}
|
||||
>
|
||||
Double underline with custom color
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationStyle: 'dashed',
|
||||
textDecorationColor: '#9CDC40'
|
||||
}}
|
||||
>
|
||||
Dashed underline with custom color
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationStyle: 'dotted',
|
||||
textDecorationColor: 'blue'
|
||||
}}
|
||||
>
|
||||
Dotted underline with custom color
|
||||
</Text>
|
||||
<Text style={{ textDecorationLine: 'none' }}>
|
||||
None textDecoration
|
||||
</Text>
|
||||
<Text style={{ textDecorationLine: 'line-through', textDecorationStyle: 'solid' }}>
|
||||
Solid line-through
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'double',
|
||||
textDecorationColor: '#ff0000'
|
||||
}}
|
||||
>
|
||||
Double line-through with custom color
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'dashed',
|
||||
textDecorationColor: '#9CDC40'
|
||||
}}
|
||||
>
|
||||
Dashed line-through with custom color
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'dotted',
|
||||
textDecorationColor: 'blue'
|
||||
}}
|
||||
>
|
||||
Dotted line-through with custom color
|
||||
</Text>
|
||||
<Text style={{ textDecorationLine: 'underline line-through' }}>
|
||||
Both underline and line-through
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Text Align',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
auto (default) - english LTR
|
||||
</Text>
|
||||
<Text>
|
||||
أحب اللغة العربية auto (default) - arabic RTL
|
||||
</Text>
|
||||
<Text style={{ textAlign: 'left' }}>
|
||||
left left left left left left left left left left left left left left left
|
||||
</Text>
|
||||
<Text style={{ textAlign: 'center' }}>
|
||||
center center center center center center center center center center center
|
||||
</Text>
|
||||
<Text style={{ textAlign: 'right' }}>
|
||||
right right right right right right right right right right right right right
|
||||
</Text>
|
||||
<Text style={{ textAlign: 'justify' }}>
|
||||
justify: this text component{"'"}s contents are laid out with "textAlign: justify"
|
||||
and as you can see all of the lines except the last one span the
|
||||
available width of the parent container.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Letter Spacing',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{ letterSpacing: 0 }}>
|
||||
letterSpacing = 0
|
||||
</Text>
|
||||
<Text style={{ letterSpacing: 2, marginTop: 5 }}>
|
||||
letterSpacing = 2
|
||||
</Text>
|
||||
<Text style={{ letterSpacing: 9, marginTop: 5 }}>
|
||||
letterSpacing = 9
|
||||
</Text>
|
||||
<Text style={{ letterSpacing: -1, marginTop: 5 }}>
|
||||
letterSpacing = -1
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Spaces',
|
||||
render: function() {
|
||||
return (
|
||||
<Text>
|
||||
A {'generated'} {' '} {'string'} and some spaces
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Line Height',
|
||||
render: function() {
|
||||
return (
|
||||
<Text>
|
||||
<Text style={{ lineHeight: 35 }}>
|
||||
A lot of space between the lines of this long passage that should
|
||||
wrap once.
|
||||
</Text>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Empty Text',
|
||||
description: "It's ok to have Text with zero or null children.",
|
||||
render: function() {
|
||||
return <Text />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Toggling Attributes',
|
||||
render: function() {
|
||||
return <AttributeToggler />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'backgroundColor attribute',
|
||||
description: 'backgroundColor is inherited from all types of views.',
|
||||
render: function() {
|
||||
return (
|
||||
<Text style={{ backgroundColor: 'yellow' }}>
|
||||
Yellow container background,
|
||||
<Text style={{ backgroundColor: '#ffaaaa' }}>
|
||||
{' '}red background,
|
||||
<Text style={{ backgroundColor: '#aaaaff' }}>
|
||||
{' '}blue background,
|
||||
<Text>
|
||||
{' '}inherited blue background,
|
||||
<Text style={{ backgroundColor: '#aaffaa' }}>
|
||||
{' '}nested green background.
|
||||
</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Text highlighting (tap the link to see highlight)',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
Lorem ipsum dolor sit amet,
|
||||
{' '}
|
||||
<Text
|
||||
onPress={() => null}
|
||||
style={{ backgroundColor: 'white', textDecorationLine: 'underline', color: 'blue' }}
|
||||
suppressHighlighting={false}
|
||||
>
|
||||
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
|
||||
magna aliqua. Ut enim ad minim veniam, quis nostrud
|
||||
</Text>
|
||||
{' '}
|
||||
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'allowFontScaling attribute',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
By default, text will respect Text Size accessibility setting on iOS.
|
||||
It means that all font sizes will be increased or descreased depending on the value of
|
||||
Text Size setting in
|
||||
{' '}
|
||||
<Text style={{ fontWeight: 'bold' }}>
|
||||
Settings.app - Display & Brightness - Text Size
|
||||
</Text>
|
||||
</Text>
|
||||
<Text style={{ marginTop: 10 }}>
|
||||
You can disable scaling for your Text component by passing
|
||||
{' '}
|
||||
{'"'}
|
||||
allowFontScaling=
|
||||
{'{'}
|
||||
false
|
||||
{'}"'}
|
||||
{' '}
|
||||
prop.
|
||||
</Text>
|
||||
<Text allowFontScaling={false} style={{ marginTop: 20 }}>
|
||||
This text will not scale.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Text shadow',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 20,
|
||||
textShadowOffset: { width: 2, height: 2 },
|
||||
textShadowRadius: 1,
|
||||
textShadowColor: '#00cccc'
|
||||
}}
|
||||
>
|
||||
Demo text shadow
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Line break mode',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the end.
|
||||
</Text>
|
||||
<Text lineBreakMode="middle" numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the middle.
|
||||
</Text>
|
||||
<Text lineBreakMode="head" numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the beginning.
|
||||
</Text>
|
||||
<Text lineBreakMode="clip" numberOfLines={1}>
|
||||
This very looooooooooooooooooooooooooooong text should be clipped.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
*/
|
||||
@@ -1,362 +0,0 @@
|
||||
/* eslint-disable react/jsx-sort-props */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import PropAutoCapitalize from './examples/PropAutoCapitalize';
|
||||
import PropBlurOnSubmit from './examples/PropBlurOnSubmit';
|
||||
import PropClearTextOnFocus from './examples/PropClearTextOnFocus';
|
||||
import PropEditable from './examples/PropEditable';
|
||||
import PropKeyboardType from './examples/PropKeyboardType';
|
||||
import PropMaxLength from './examples/PropMaxLength';
|
||||
import PropMultiline from './examples/PropMultiline';
|
||||
import PropNumberOfLines from './examples/PropNumberOfLines';
|
||||
import PropOnSelectionChange from './examples/PropOnSelectionChange';
|
||||
import PropPlaceholder from './examples/PropPlaceholder';
|
||||
import PropSecureTextEntry from './examples/PropSecureTextEntry';
|
||||
import PropSelectTextOnFocus from './examples/PropSelectTextOnFocus';
|
||||
import TextInputEvents from './examples/TextInputEvents';
|
||||
import TextInputRewrite, { TextInputRewriteInvalidCharacters } from './examples/Rewrite';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import UIExplorer, {
|
||||
AppText,
|
||||
Code,
|
||||
Description,
|
||||
DocItem,
|
||||
Section,
|
||||
StyleList,
|
||||
TextList
|
||||
} from '../../ui-explorer';
|
||||
|
||||
const TextInputScreen = () =>
|
||||
<UIExplorer title="TextInput" url="components/TextInput">
|
||||
<Description>
|
||||
<AppText>
|
||||
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 <Code>multiline</Code>.
|
||||
</AppText>
|
||||
</Description>
|
||||
|
||||
<Section title="Props">
|
||||
<DocItem name="...View props" />
|
||||
|
||||
<DocItem
|
||||
name="autoCapitalize"
|
||||
typeInfo="?enum('characters', 'none', 'sentences', 'words') = 'sentences'"
|
||||
description={[
|
||||
<AppText key={1}>
|
||||
Automatically capitalize certain characters (only available in Chrome and iOS Safari).
|
||||
</AppText>,
|
||||
<TextList
|
||||
key={2}
|
||||
items={[
|
||||
<AppText>
|
||||
<Code>characters</Code>: Automatically capitalize all characters.
|
||||
</AppText>,
|
||||
<AppText>
|
||||
<Code>none</Code>: Completely disables automatic capitalization.
|
||||
</AppText>,
|
||||
<AppText>
|
||||
<Code>sentences</Code>: Automatically capitalize the first letter of sentences.
|
||||
</AppText>,
|
||||
<AppText>
|
||||
<Code>words</Code>: Automatically capitalize the first letter of words.
|
||||
</AppText>
|
||||
]}
|
||||
/>
|
||||
]}
|
||||
example={{
|
||||
render: () => <PropAutoCapitalize />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
label="web"
|
||||
name="autoComplete"
|
||||
typeInfo="?string"
|
||||
description={
|
||||
<AppText>
|
||||
Indicates whether the value of the control can be automatically completed by the
|
||||
browser.{' '}
|
||||
<AppText
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"
|
||||
target="_blank"
|
||||
>
|
||||
Accepted values.
|
||||
</AppText>
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="autoCorrect"
|
||||
typeInfo="?boolean = true"
|
||||
description="Automatically correct spelling mistakes (only available in iOS Safari)."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="autoFocus"
|
||||
typeInfo="?boolean = false"
|
||||
description="If `true`, focuses the input on `componentDidMount`. Only the first form element in a document with `autofocus` is focused."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="blurOnSubmit"
|
||||
typeInfo="?boolean"
|
||||
description={
|
||||
<AppText>
|
||||
If <Code>true</Code>, the text field will blur when submitted. The default value is{' '}
|
||||
<Code>true</Code> for single-line fields and <Code>false</Code> for multiline fields.
|
||||
Note, for multiline fields setting <Code>blurOnSubmit</Code> to <Code>true</Code> means
|
||||
that pressing return will blur the field and trigger the <Code>onSubmitEditing</Code>{' '}
|
||||
event instead of inserting a newline into the field.
|
||||
</AppText>
|
||||
}
|
||||
example={{
|
||||
render: () => <PropBlurOnSubmit />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="clearTextOnFocus"
|
||||
typeInfo="?boolean = false"
|
||||
description="If `true`, clears the text field automatically when focused."
|
||||
example={{
|
||||
render: () => <PropClearTextOnFocus />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="defaultValue"
|
||||
typeInfo="?string"
|
||||
description={
|
||||
<AppText>
|
||||
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{' '}
|
||||
<Code>value</Code> prop to keep the controlled state in sync.
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="editable"
|
||||
typeInfo="?boolean = true"
|
||||
description="If `false`, text is not editable (i.e., read-only). "
|
||||
example={{
|
||||
render: () => <PropEditable />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="keyboardType"
|
||||
typeInfo="enum('default', 'email-address', 'numeric', 'phone-pad', 'search', 'url', 'web-search') = 'default'"
|
||||
description="Determines which keyboard to open on devices with a virtual keyboard. Safari iOS requires an ancestral `<form action>` element to display the `search` keyboard). (Not available when `multiline` is `true`.)"
|
||||
example={{
|
||||
render: () => <PropKeyboardType />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="maxLength"
|
||||
typeInfo="?number"
|
||||
description="Limits the maximum number of characters that can be entered."
|
||||
example={{
|
||||
render: () => <PropMaxLength />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="multiline"
|
||||
typeInfo="?boolean = false"
|
||||
description="If true, the text input can be multiple lines."
|
||||
example={{
|
||||
render: () => <PropMultiline />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="numberOfLines"
|
||||
typeInfo="?number"
|
||||
description="Sets the number of lines for a multiline `TextInput`. (Requires `multiline` to be `true`.)"
|
||||
example={{
|
||||
render: () => <PropNumberOfLines />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onBlur"
|
||||
typeInfo="?function"
|
||||
description="Callback that is called when the text input is blurred."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onChange"
|
||||
typeInfo="?function"
|
||||
description="Callback that is called when the text input's text changes."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onChangeText"
|
||||
typeInfo="?function"
|
||||
description="Callback that is called when the text input's text changes. The text is passed as an argument to the callback handler."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onFocus"
|
||||
typeInfo="?function"
|
||||
description="Callback that is called when the text input is focused."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onKeyPress"
|
||||
typeInfo="?function"
|
||||
description={
|
||||
<AppText>
|
||||
Callback that is called when a key is pressed. This will be called with{' '}
|
||||
<Code>{`{
|
||||
nativeEvent: { key: keyValue } }`}</Code>{' '}
|
||||
where keyValue is <Code>Enter</Code> or <Code>Backspace</Code> for respective keys and
|
||||
the typed-in character otherwise including <Code>' '</Code>
|
||||
for space. Modifier keys (e.g., <Code>shiftKey</Code>) are also included in the{' '}
|
||||
<Code>nativeEvent</Code>. Fires before <Code>onChange</Code> callbacks.
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onSelectionChange"
|
||||
typeInfo="?function"
|
||||
description={
|
||||
<AppText>
|
||||
Callback that is called when the text input's selection changes. This will be called
|
||||
with <Code>{'{ nativeEvent: { selection: { start, end } } }'}</Code>.
|
||||
</AppText>
|
||||
}
|
||||
example={{
|
||||
render: () => <PropOnSelectionChange />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="onSubmitEditing"
|
||||
typeInfo="?function"
|
||||
description="Callback that is called when the keyboard's submit button is pressed. When multiline={true}, this is only called if blurOnSubmit={true}."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="placeholder"
|
||||
typeInfo="?string"
|
||||
description="The string that will be rendered in an empty `TextInput` before text has been entered."
|
||||
example={{
|
||||
render: () => <PropPlaceholder />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="secureTextEntry"
|
||||
typeInfo="?boolean = false"
|
||||
description="If true, the text input obscures the text entered so that sensitive text like passwords stay secure. (Not available when `multiline` is `true`.)"
|
||||
example={{
|
||||
render: () => <PropSecureTextEntry />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="selection"
|
||||
typeInfo="?{ start: number, end: ?number }"
|
||||
description="The start and end of the text input's selection. Set start and end to the same value to position the cursor."
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="selectTextOnFocus"
|
||||
typeInfo="?boolean = false"
|
||||
description="If `true`, all text will automatically be selected on focus."
|
||||
example={{
|
||||
render: () => <PropSelectTextOnFocus />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="style"
|
||||
typeInfo="?style"
|
||||
description={
|
||||
<StyleList
|
||||
stylePropTypes={[
|
||||
{
|
||||
name: '...Text#style'
|
||||
},
|
||||
{
|
||||
label: 'web',
|
||||
name: 'resize',
|
||||
typeInfo: 'string'
|
||||
}
|
||||
]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
name="value"
|
||||
typeInfo="?string"
|
||||
description={
|
||||
<AppText>
|
||||
The value to show for the text input. <Code>TextInput</Code> is a controlled component,
|
||||
which means the native <Code>value</Code> will be forced to match this prop if provided.
|
||||
Read about how{' '}
|
||||
<AppText
|
||||
children="React form components"
|
||||
href="https://facebook.github.io/react/docs/forms.html"
|
||||
target="_blank"
|
||||
/>{' '}
|
||||
work. To prevent user edits to the value set <Code>{'editable={false}'}</Code>.
|
||||
</AppText>
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title="Instance methods">
|
||||
<DocItem name="blur" typeInfo="() => void" description="Blur the underlying DOM input." />
|
||||
|
||||
<DocItem
|
||||
name="clear"
|
||||
typeInfo="() => void"
|
||||
description="Clear the text from the underlying DOM input."
|
||||
/>
|
||||
|
||||
<DocItem name="focus" typeInfo="() => void" description="Focus the underlying DOM input." />
|
||||
|
||||
<DocItem
|
||||
name="isFocused"
|
||||
typeInfo="() => boolean"
|
||||
description="Returns `true` if the input is currently focused; `false` otherwise."
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section title="More examples">
|
||||
<DocItem
|
||||
description="TextInput events"
|
||||
example={{
|
||||
render: () => <TextInputEvents />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="Rewrite (<sp> to '_' with maxLength)"
|
||||
example={{
|
||||
render: () => <TextInputRewrite />
|
||||
}}
|
||||
/>
|
||||
|
||||
<DocItem
|
||||
description="Rewrite (no spaces allowed)"
|
||||
example={{
|
||||
render: () => <TextInputRewriteInvalidCharacters />
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
</UIExplorer>;
|
||||
|
||||
storiesOf('Components', module).add('TextInput', TextInputScreen);
|
||||
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/*
|
||||
import React from 'react';
|
||||
import { StyleSheet, TextInput } from 'react-native';
|
||||
|
||||
class AutoExpandingTextInput extends React.Component {
|
||||
state: any;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
text:
|
||||
'React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React. The focus of React Native is on developer efficiency across all the platforms you care about — learn once, write anywhere. Facebook uses React Native in multiple production apps and will continue investing in React Native.',
|
||||
height: 0
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TextInput
|
||||
{...this.props}
|
||||
multiline={true}
|
||||
onChangeText={text => {
|
||||
this.setState({ text });
|
||||
}}
|
||||
onContentSizeChange={event => {
|
||||
this.setState({ height: event.nativeEvent.contentSize.height });
|
||||
}}
|
||||
style={[styles.default, { height: Math.max(35, this.state.height) }]}
|
||||
value={this.state.text}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
default: {
|
||||
height: 26,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#0f0f0f',
|
||||
flex: 1,
|
||||
fontSize: 13,
|
||||
padding: 4
|
||||
},
|
||||
eventLabel: {
|
||||
margin: 3,
|
||||
fontSize: 12
|
||||
}
|
||||
});
|
||||
|
||||
const AutoExpandingTextInputExample = () =>
|
||||
<AutoExpandingTextInput
|
||||
enablesReturnKeyAutomatically={true}
|
||||
placeholder="height increases with content"
|
||||
returnKeyType="default"
|
||||
/>;
|
||||
|
||||
export default AutoExpandingTextInputExample;
|
||||
*/
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { WithLabel, styles } from '../helpers';
|
||||
import { TextInput, View } from 'react-native';
|
||||
|
||||
const TextInputAutoCapitalizeExample = () =>
|
||||
<View>
|
||||
<WithLabel label="none">
|
||||
<TextInput autoCapitalize="none" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="sentences">
|
||||
<TextInput autoCapitalize="sentences" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="words">
|
||||
<TextInput autoCapitalize="words" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="characters">
|
||||
<TextInput autoCapitalize="characters" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
</View>;
|
||||
|
||||
export default TextInputAutoCapitalizeExample;
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { TextInput } from 'react-native';
|
||||
|
||||
const TextInputAutoFocusExample = () => <TextInput autoFocus={true} style={styles.default} />;
|
||||
|
||||
export default TextInputAutoFocusExample;
|
||||
@@ -1,55 +0,0 @@
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { TextInput, View } from 'react-native';
|
||||
|
||||
class TextInputBlurOnSubmitExample extends React.Component {
|
||||
_nodes = {};
|
||||
|
||||
focusNextField = nextField => {
|
||||
this._nodes[nextField].focus();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
blurOnSubmit={false}
|
||||
placeholder="blurOnSubmit = false"
|
||||
ref={c => {
|
||||
this._nodes['1'] = c;
|
||||
}}
|
||||
style={styles.textinput}
|
||||
/>
|
||||
<TextInput
|
||||
blurOnSubmit={true}
|
||||
onSubmitEditing={() => this.focusNextField('3')}
|
||||
placeholder="blurOnSubmit = true"
|
||||
ref={c => {
|
||||
this._nodes['2'] = c;
|
||||
}}
|
||||
style={styles.textinput}
|
||||
/>
|
||||
<TextInput
|
||||
blurOnSubmit={true}
|
||||
multiline={true}
|
||||
onSubmitEditing={e => {
|
||||
console.log(e.nativeEvent);
|
||||
}}
|
||||
placeholder="blurOnSubmit = true"
|
||||
ref={c => {
|
||||
this._nodes['3'] = c;
|
||||
}}
|
||||
style={styles.multiline}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TextInputBlurOnSubmitExample;
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles, WithLabel } from '../helpers';
|
||||
import { TextInput, View } from 'react-native';
|
||||
|
||||
const TextInputClearButtonModeExample = () =>
|
||||
<View>
|
||||
<WithLabel label="never">
|
||||
<TextInput clearButtonMode="never" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="while editing">
|
||||
<TextInput clearButtonMode="while-editing" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="unless editing">
|
||||
<TextInput clearButtonMode="unless-editing" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="always">
|
||||
<TextInput clearButtonMode="always" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
</View>;
|
||||
|
||||
export default TextInputClearButtonModeExample;
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { TextInput, View } from 'react-native';
|
||||
|
||||
const TextInputClearTextOnFocusExample = () =>
|
||||
<View>
|
||||
<TextInput
|
||||
clearTextOnFocus={true}
|
||||
defaultValue="text is cleared on focus"
|
||||
placeholder="text is cleared on focus"
|
||||
style={styles.textinput}
|
||||
/>
|
||||
<TextInput
|
||||
clearTextOnFocus={true}
|
||||
defaultValue="text is cleared on focus"
|
||||
multiline={true}
|
||||
placeholder="text is cleared on focus"
|
||||
style={styles.multiline}
|
||||
/>
|
||||
</View>;
|
||||
|
||||
export default TextInputClearTextOnFocusExample;
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles } from '../helpers';
|
||||
import { TextInput, View } from 'react-native';
|
||||
|
||||
const TextInputEditableExample = () =>
|
||||
<View>
|
||||
<TextInput defaultValue="uneditable text input" editable={false} style={styles.textinput} />
|
||||
<TextInput
|
||||
defaultValue="uneditable multiline text input"
|
||||
editable={false}
|
||||
multiline={true}
|
||||
style={styles.multiline}
|
||||
/>
|
||||
</View>;
|
||||
|
||||
export default TextInputEditableExample;
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles, WithLabel } from '../helpers';
|
||||
import { TextInput, View } from 'react-native';
|
||||
|
||||
const keyboardTypes = [
|
||||
'default',
|
||||
//'ascii-capable',
|
||||
//'numbers-and-punctuation',
|
||||
'url',
|
||||
'number-pad',
|
||||
'phone-pad',
|
||||
//'name-phone-pad',
|
||||
'email-address',
|
||||
//'decimal-pad',
|
||||
//'twitter',
|
||||
'web-search',
|
||||
'numeric'
|
||||
];
|
||||
|
||||
const TextInputKeyboardTypeExample = () =>
|
||||
<View>
|
||||
{keyboardTypes.map(type =>
|
||||
<WithLabel key={type} label={type}>
|
||||
<TextInput keyboardType={type} style={styles.textinput} />
|
||||
</WithLabel>
|
||||
)}
|
||||
</View>;
|
||||
|
||||
export default TextInputKeyboardTypeExample;
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { styles, WithLabel } from '../helpers';
|
||||
import { TextInput, View } from 'react-native';
|
||||
|
||||
const TextInputMaxLengthExample = () =>
|
||||
<View>
|
||||
<WithLabel label="maxLength: 5">
|
||||
<TextInput maxLength={5} style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="maxLength: 5 with placeholder">
|
||||
<TextInput maxLength={5} placeholder="ZIP code entry" style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="maxLength: 5 with default value already set">
|
||||
<TextInput defaultValue="94025" maxLength={5} style={styles.textinput} />
|
||||
</WithLabel>
|
||||
<WithLabel label="maxLength: 5 with very long default value already set">
|
||||
<TextInput defaultValue="9402512345" maxLength={5} style={styles.textinput} />
|
||||
</WithLabel>
|
||||
</View>;
|
||||
|
||||
export default TextInputMaxLengthExample;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user