Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c400a662b | ||
|
|
e78ce713cb | ||
|
|
70282cb4ca | ||
|
|
7abdb33a1d | ||
|
|
a9c7b38df9 | ||
|
|
d57fb6407a | ||
|
|
bcdeda5dab | ||
|
|
edef737249 | ||
|
|
9163b974db | ||
|
|
a388ef3e26 | ||
|
|
a84ecefa5d | ||
|
|
54af7e9da2 | ||
|
|
be3c78f317 | ||
|
|
6b85f5a22a | ||
|
|
875a2c98b3 | ||
|
|
6525d9d84a | ||
|
|
61356a786b | ||
|
|
864250f34d | ||
|
|
7ee570f0ed | ||
|
|
118b64a932 | ||
|
|
3cc1e480a7 | ||
|
|
124de7562d | ||
|
|
7aef8f04c1 | ||
|
|
08a353fbef | ||
|
|
51557d306b | ||
|
|
6b910166b2 | ||
|
|
668d389035 | ||
|
|
79a6a5a486 | ||
|
|
1c37a42566 | ||
|
|
c38369ac0f | ||
|
|
03769f7d45 | ||
|
|
eb43a8f3e7 | ||
|
|
cdf13b880d | ||
|
|
47fad1ef58 | ||
|
|
5f69c8e8b8 | ||
|
|
21550db5f2 | ||
|
|
1cae5d55a1 | ||
|
|
11d23f850a | ||
|
|
d994a25017 | ||
|
|
756df70154 | ||
|
|
f0b06419f9 | ||
|
|
60ff75705e | ||
|
|
5e8ad67296 | ||
|
|
ba24a882be | ||
|
|
c7686209cd | ||
|
|
f1b281ae32 | ||
|
|
b676fbd5e0 | ||
|
|
51aef6c791 | ||
|
|
ae9a9cde5f | ||
|
|
beb907b180 | ||
|
|
a3362e1f38 | ||
|
|
64d2d34367 | ||
|
|
d83cd45b6f | ||
|
|
227971d22c | ||
|
|
4822cf4620 | ||
|
|
91e4528eac | ||
|
|
1ee64d8285 | ||
|
|
66a4c13bf3 | ||
|
|
9012e98ba7 | ||
|
|
046e01dfa9 | ||
|
|
6e71e1e058 | ||
|
|
d5a9f3e779 | ||
|
|
f16f5f21ce | ||
|
|
0bb7e67e63 | ||
|
|
c6b54930b6 | ||
|
|
599f1fcaf5 | ||
|
|
3f7a4e455f | ||
|
|
1f3e9cc6ee | ||
|
|
17ed63129f | ||
|
|
769334d04e | ||
|
|
dad80d5718 | ||
|
|
d8e93058da | ||
|
|
4ae894313f | ||
|
|
438f398022 | ||
|
|
630ee24fdd | ||
|
|
ae13873c2c | ||
|
|
7705f521c8 | ||
|
|
cbd98a8bd7 | ||
|
|
1f80e4c105 | ||
|
|
dbc8f31be6 | ||
|
|
ed994dc670 | ||
|
|
a57e58607a | ||
|
|
03ea259d70 | ||
|
|
e39b58fd04 | ||
|
|
ab45211401 | ||
|
|
32183bb92a | ||
|
|
761c42301d | ||
|
|
0863894f40 | ||
|
|
8f736ddefe | ||
|
|
ab686e2a07 | ||
|
|
2c14bdab2e | ||
|
|
0b8b064757 | ||
|
|
93eadb734b | ||
|
|
8d561d7309 | ||
|
|
cdca9e1e2b | ||
|
|
170bab659d | ||
|
|
941c628445 | ||
|
|
547c375bd6 | ||
|
|
aa85876eb2 | ||
|
|
50b168cc41 |
8
.babelrc
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
"react-native"
|
||||
],
|
||||
"plugins": [
|
||||
[ "transform-react-remove-prop-types", { "mode": "wrap" } ]
|
||||
]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
# EditorConfig: http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
37
.eslintrc
@@ -14,7 +14,6 @@
|
||||
"prettier/react"
|
||||
],
|
||||
"plugins": [
|
||||
"jsx-a11y",
|
||||
"promise",
|
||||
"react"
|
||||
],
|
||||
@@ -25,7 +24,16 @@
|
||||
"globals": {
|
||||
"document": false,
|
||||
"navigator": false,
|
||||
"window": false
|
||||
"window": false,
|
||||
// Flow global types
|
||||
"HTMLInputElement": false,
|
||||
"ReactClass": false,
|
||||
"ReactComponent": false,
|
||||
"ReactElement": false,
|
||||
"ReactPropsChainableTypeChecker": false,
|
||||
"ReactPropsCheckType": false,
|
||||
"ReactPropTypes": false,
|
||||
"SyntheticEvent": false
|
||||
},
|
||||
"rules": {
|
||||
"camelcase": 0,
|
||||
@@ -119,33 +127,8 @@
|
||||
// promise
|
||||
"promise/param-names": 2,
|
||||
|
||||
// jsx accessibility
|
||||
"jsx-a11y/aria-props": 2,
|
||||
"jsx-a11y/aria-proptypes": 2,
|
||||
"jsx-a11y/aria-role": 2,
|
||||
"jsx-a11y/aria-unsupported-elements": 2,
|
||||
"jsx-a11y/heading-has-content": 2,
|
||||
"jsx-a11y/href-no-hash": 2,
|
||||
"jsx-a11y/html-has-lang": 2,
|
||||
"jsx-a11y/img-has-alt": 2,
|
||||
"jsx-a11y/img-redundant-alt": 2,
|
||||
"jsx-a11y/label-has-for": 2,
|
||||
"jsx-a11y/mouse-events-have-key-events": 2,
|
||||
"jsx-a11y/no-access-key": 2,
|
||||
"jsx-a11y/no-marquee": 2,
|
||||
"jsx-a11y/no-onchange": 0,
|
||||
"jsx-a11y/onclick-has-focus": 2,
|
||||
"jsx-a11y/onclick-has-role": 2,
|
||||
"jsx-a11y/role-has-required-aria-props": 2,
|
||||
"jsx-a11y/role-supports-aria-props": 2,
|
||||
"jsx-a11y/scope": 2,
|
||||
"jsx-a11y/tabindex-no-positive": 2,
|
||||
|
||||
// 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,
|
||||
|
||||
13
.flowconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
[ignore]
|
||||
.*/__tests__/.*
|
||||
.*/benchmarks/.*
|
||||
.*/docs/.*
|
||||
.*/node_modules/animated/*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
types
|
||||
|
||||
[options]
|
||||
unsafe.enable_getters_and_setters=true
|
||||
87
CONTRIBUTING.md → .github/CONTRIBUTING.md
vendored
@@ -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.
|
||||
|
||||
## Development
|
||||
## Getting started
|
||||
|
||||
Visit the [Issue tracker](https://github.com/necolas/react-native-web/issues)
|
||||
to find a list of open issues that need attention.
|
||||
@@ -23,47 +23,66 @@ Install dependencies (requires [yarn](https://yarnpkg.com/en/docs/install):
|
||||
yarn
|
||||
```
|
||||
|
||||
Run the examples:
|
||||
## Unit tests
|
||||
|
||||
To run the unit tests:
|
||||
|
||||
```
|
||||
npm run examples
|
||||
npm test
|
||||
```
|
||||
|
||||
Run the benchmarks in a browser by opening `./performance/index.html` after running:
|
||||
|
||||
```
|
||||
npm run build:performance
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
To create a UMD build:
|
||||
|
||||
```
|
||||
npm run build:umd
|
||||
```
|
||||
|
||||
### Testing and Linting
|
||||
|
||||
To run the tests:
|
||||
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
||||
To continuously watch and run tests, run the following:
|
||||
…in watch mode:
|
||||
|
||||
```
|
||||
npm run test:watch
|
||||
```
|
||||
|
||||
To perform only linting, run the following:
|
||||
## Visual tests
|
||||
|
||||
Run the interactive storybook:
|
||||
|
||||
```
|
||||
npm run docs:start
|
||||
```
|
||||
|
||||
Run generate a static build of the storybook:
|
||||
|
||||
```
|
||||
npm run docs:build
|
||||
```
|
||||
|
||||
Run the performance benchmarks in a browser (opening `./performance/index.html`):
|
||||
|
||||
```
|
||||
npm run benchmarks
|
||||
```
|
||||
|
||||
## Compile and build
|
||||
|
||||
Compile the source code to `dist`:
|
||||
|
||||
```
|
||||
npm run compile
|
||||
```
|
||||
|
||||
To create a UMD bundle of the library:
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Pre-commit
|
||||
|
||||
Before creating a commit run:
|
||||
|
||||
```
|
||||
npm run precommit
|
||||
```
|
||||
|
||||
To format and lint the entire project:
|
||||
|
||||
```
|
||||
npm run fmt
|
||||
npm run lint
|
||||
```
|
||||
|
||||
@@ -81,8 +100,10 @@ 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!
|
||||
1
.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
node_modules
|
||||
dist
|
||||
dist-examples
|
||||
|
||||
@@ -5,4 +5,5 @@ before_script:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
script:
|
||||
- npm run lint
|
||||
- npm test
|
||||
|
||||
42
README.md
@@ -18,36 +18,31 @@ Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
|
||||
"React Native for Web" is a project to bring React Native's building blocks and
|
||||
touch handling to the Web. [Read more](#why).
|
||||
|
||||
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](http://codepen.io/necolas/pen/PZzwBR).
|
||||
Browse the [UI Explorer](https://necolas.github.io/react-native-web/storybook/)
|
||||
to see React Native examples running on Web. 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.4 react-native-web
|
||||
npm install --save react@15.5 react-dom@15.5 react-native-web
|
||||
```
|
||||
|
||||
Read the [Client and Server rendering](docs/guides/rendering.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).
|
||||
Read the [Getting Started](docs/guides/getting-started.md) guide.
|
||||
|
||||
## Documentation
|
||||
|
||||
Guides:
|
||||
|
||||
* [Getting started](docs/guides/getting-started.md)
|
||||
* [Style](docs/guides/style.md)
|
||||
* [Accessibility](docs/guides/accessibility.md)
|
||||
* [Client and server rendering](docs/guides/rendering.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)
|
||||
* [React Native](docs/guides/react-native.md)
|
||||
* [Style](docs/guides/style.md)
|
||||
|
||||
Exported modules:
|
||||
|
||||
@@ -88,17 +83,16 @@ Exported modules:
|
||||
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.
|
||||
multiple, inter-related problems including: component styles, animation, touch
|
||||
interactions, layout adaptation, accessibility, RTL layout, theming, and build-
|
||||
or 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.
|
||||
avoids, solves, or can solve almost all these problems. 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
|
||||
|
||||
@@ -141,11 +135,11 @@ AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-ro
|
||||
|
||||
## Related projects
|
||||
|
||||
* [react-native-web-starter](https://github.com/grabcode/react-native-web-starter)
|
||||
* [react-native-web-player](https://github.com/dabbott/react-native-web-player)
|
||||
* [react-native-web-starter](https://github.com/grabcode/react-native-web-starter)
|
||||
* [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack)
|
||||
* [reactxp](https://github.com/microsoft/reactxp)
|
||||
* [react-web](https://github.com/taobaofed/react-web)
|
||||
* [react-native-for-web](https://github.com/KodersLab/react-native-for-web)
|
||||
* [rhinos-app](https://github.com/rhinos-app/rhinos-app-dev)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
40
benchmarks/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Performance
|
||||
|
||||
To run these benchmarks:
|
||||
|
||||
```
|
||||
npm run build:performance
|
||||
open ./performance/index.html
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
`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` | `87.67` `±15.22` | `170.85` `±16.87` | |
|
||||
| `react-native-web/stylesheet@0.0.84` | `90.02` `±13.16` | `186.66` `±19.23` | |
|
||||
| `react-native-web@0.0.84` | `102.72` `±19.26` | `222.35` `±18.95` | `12.81` `±5.45ms` |
|
||||
|
||||
Other libraries
|
||||
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) |
|
||||
| :--- | ---: | ---: |
|
||||
| `styletron@2.5.1` | `88.48` `±12.00` | `171.89` `±13.28` |
|
||||
| `aphrodite@1.2.0` | `101.32` `±20.33` | `220.33` `±31.41` |
|
||||
| `glamor@3.0.0-1` | `129.00` `±14.92` | `264.57` `±28.54` |
|
||||
| `react-jss@5.4.1` | `137.33` `±21.55` | `314.91` `±29.03` |
|
||||
| `reactxp@0.34.3` | `223.82` `±32.77` | `461.56` `±34.43` |
|
||||
| `styled-components@2.0.0-11` | `277.53` `±28.83` | `627.91` `±43.13` |
|
||||
|
||||
*MacBook Pro (13-inch, Early 2011); 2.7 GHz Intel Core i7; 16 GB 1600 MHz DDR3. Google Chrome 56.
|
||||
@@ -23,7 +23,7 @@ const median = values => {
|
||||
}
|
||||
|
||||
const numbers = [...values].sort((a, b) => a - b);
|
||||
return (numbers[numbers.length - 1 >> 1] + numbers[numbers.length >> 1]) / 2;
|
||||
return (numbers[(numbers.length - 1) >> 1] + numbers[numbers.length >> 1]) / 2;
|
||||
};
|
||||
|
||||
const standardDeviation = values => {
|
||||
11
benchmarks/index.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Performance tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="root"></div>
|
||||
<script src="dist/performance.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
49
benchmarks/index.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import aphrodite from './src/aphrodite';
|
||||
import cssModules from './src/css-modules';
|
||||
import glamor from './src/glamor';
|
||||
import jss from './src/jss';
|
||||
import reactNative from './src/react-native';
|
||||
import reactNativeStyleSheet from './src/react-native-stylesheet';
|
||||
import styledComponents from './src/styled-components';
|
||||
import styletron from './src/styletron';
|
||||
import xp from './src/reactxp';
|
||||
|
||||
import renderDeepTree from './tests/renderDeepTree';
|
||||
import renderTweet from './tests/renderTweet';
|
||||
import renderWideTree from './tests/renderWideTree';
|
||||
|
||||
const testAll = window.location.search === '?all';
|
||||
|
||||
const coreTests = [
|
||||
() => renderTweet('react-native-web', reactNative),
|
||||
|
||||
() => renderDeepTree('css-modules', cssModules),
|
||||
() => renderWideTree('css-modules', cssModules),
|
||||
() => renderDeepTree('react-native-web/stylesheet', reactNativeStyleSheet),
|
||||
() => renderWideTree('react-native-web/stylesheet', reactNativeStyleSheet),
|
||||
() => renderDeepTree('react-native-web', reactNative),
|
||||
() => renderWideTree('react-native-web', reactNative)
|
||||
];
|
||||
|
||||
/**
|
||||
* Optionally run tests using other libraries
|
||||
*/
|
||||
const extraTests = [
|
||||
() => renderDeepTree('styletron', styletron),
|
||||
() => renderWideTree('styletron', styletron),
|
||||
() => renderDeepTree('aphrodite', aphrodite),
|
||||
() => renderWideTree('aphrodite', aphrodite),
|
||||
() => renderDeepTree('glamor', glamor),
|
||||
() => renderWideTree('glamor', glamor),
|
||||
() => renderDeepTree('react-jss', jss),
|
||||
() => renderWideTree('react-jss', jss),
|
||||
() => renderDeepTree('reactxp', xp),
|
||||
() => renderWideTree('reactxp', xp),
|
||||
() => renderDeepTree('styled-components', styledComponents),
|
||||
() => renderWideTree('styled-components', styledComponents)
|
||||
];
|
||||
|
||||
const tests = testAll ? coreTests.concat(extraTests) : coreTests;
|
||||
|
||||
// run benchmarks
|
||||
tests.reduce((promise, test) => promise.then(test()), Promise.resolve());
|
||||
20
benchmarks/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "performance",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"aphrodite": "^1.2.1",
|
||||
"classnames": "^2.2.5",
|
||||
"glamor": "2.20.25",
|
||||
"marky": "^1.2.0",
|
||||
"react-jss": "^6.1.1",
|
||||
"reactxp": "^0.34.3",
|
||||
"styled-components": "2.0.0-17",
|
||||
"styletron-client": "^2.5.7",
|
||||
"styletron-utils": "^2.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"css-loader": "^0.28.1",
|
||||
"react-addons-perf": "^15.4.2",
|
||||
"style-loader": "^0.17.0"
|
||||
}
|
||||
}
|
||||
7
benchmarks/src/aphrodite.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/aphrodite';
|
||||
import View from './components/View/aphrodite';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
@@ -15,15 +15,7 @@ class AppText extends PureComponent {
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
align,
|
||||
color,
|
||||
fontStyle,
|
||||
size,
|
||||
uppercase,
|
||||
weight,
|
||||
...other
|
||||
} = this.props;
|
||||
const { align, color, fontStyle, size, uppercase, weight, ...other } = this.props;
|
||||
|
||||
const style = [
|
||||
styles.root,
|
||||
49
benchmarks/src/components/Box/aphrodite.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react';
|
||||
import View from '../View/aphrodite';
|
||||
import { StyleSheet } from 'aphrodite';
|
||||
|
||||
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 = StyleSheet.create({
|
||||
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
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Box;
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import React from 'react';
|
||||
import View from '../View/index.css-modules';
|
||||
import View from '../View/css-modules';
|
||||
import styles from './styles.css';
|
||||
|
||||
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { css } from 'glamor';
|
||||
import React from 'react';
|
||||
import View from '../View/index.glamor';
|
||||
import View from '../View/glamor';
|
||||
|
||||
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
|
||||
<View
|
||||
@@ -16,34 +15,34 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
);
|
||||
|
||||
const styles = {
|
||||
outer: css({
|
||||
outer: {
|
||||
padding: 4
|
||||
}),
|
||||
row: css({
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
}),
|
||||
color0: css({
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
}),
|
||||
color1: css({
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
}),
|
||||
color2: css({
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
}),
|
||||
color3: css({
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
}),
|
||||
color4: css({
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
}),
|
||||
color5: css({
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
}),
|
||||
fixed: css({
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Box;
|
||||
50
benchmarks/src/components/Box/jss.js
Normal file
@@ -0,0 +1,50 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import injectSheet from 'react-jss';
|
||||
import React from 'react';
|
||||
import View from '../View/jss';
|
||||
|
||||
const Box = ({ classes, color, fixed = false, layout = 'column', outer = false, ...other }) => (
|
||||
<View
|
||||
{...other}
|
||||
className={classnames({
|
||||
[classes[`color${color}`]]: true,
|
||||
[classes.fixed]: fixed,
|
||||
[classes.row]: layout === 'row',
|
||||
[classes.outer]: 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
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = injectSheet(styles)(Box);
|
||||
49
benchmarks/src/components/Box/react-native-stylesheet.js
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react';
|
||||
import StyleSheet from 'react-native/apis/StyleSheet';
|
||||
import View from '../View/react-native-stylesheet';
|
||||
|
||||
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 = StyleSheet.create({
|
||||
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
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Box;
|
||||
48
benchmarks/src/components/Box/reactxp.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react';
|
||||
import { Styles, View } from 'reactxp';
|
||||
|
||||
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: Styles.createViewStyle({
|
||||
padding: 4
|
||||
}),
|
||||
row: Styles.createViewStyle({
|
||||
flexDirection: 'row'
|
||||
}),
|
||||
color0: Styles.createViewStyle({
|
||||
backgroundColor: '#222'
|
||||
}),
|
||||
color1: Styles.createViewStyle({
|
||||
backgroundColor: '#666'
|
||||
}),
|
||||
color2: Styles.createViewStyle({
|
||||
backgroundColor: '#999'
|
||||
}),
|
||||
color3: Styles.createViewStyle({
|
||||
backgroundColor: 'blue'
|
||||
}),
|
||||
color4: Styles.createViewStyle({
|
||||
backgroundColor: 'orange'
|
||||
}),
|
||||
color5: Styles.createViewStyle({
|
||||
backgroundColor: 'red'
|
||||
}),
|
||||
fixed: Styles.createViewStyle({
|
||||
width: 20,
|
||||
height: 20
|
||||
})
|
||||
};
|
||||
|
||||
module.exports = Box;
|
||||
@@ -1,5 +1,5 @@
|
||||
import styled from 'styled-components';
|
||||
import View from '../View/index.styled';
|
||||
import View from '../View/styled-components';
|
||||
|
||||
const getColor = color => {
|
||||
switch (color) {
|
||||
@@ -21,10 +21,10 @@ const getColor = color => {
|
||||
};
|
||||
|
||||
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'};
|
||||
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)};
|
||||
`;
|
||||
|
||||
49
benchmarks/src/components/Box/styletron.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { injectStylePrefixed } from 'styletron-utils';
|
||||
import React from 'react';
|
||||
import View, { styletron } from '../View/styletron';
|
||||
|
||||
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: injectStylePrefixed(styletron, {
|
||||
padding: '4px'
|
||||
}),
|
||||
row: injectStylePrefixed(styletron, {
|
||||
flexDirection: 'row'
|
||||
}),
|
||||
color0: injectStylePrefixed(styletron, {
|
||||
backgroundColor: '#222'
|
||||
}),
|
||||
color1: injectStylePrefixed(styletron, {
|
||||
backgroundColor: '#666'
|
||||
}),
|
||||
color2: injectStylePrefixed(styletron, {
|
||||
backgroundColor: '#999'
|
||||
}),
|
||||
color3: injectStylePrefixed(styletron, {
|
||||
backgroundColor: 'blue'
|
||||
}),
|
||||
color4: injectStylePrefixed(styletron, {
|
||||
backgroundColor: 'orange'
|
||||
}),
|
||||
color5: injectStylePrefixed(styletron, {
|
||||
backgroundColor: 'red'
|
||||
}),
|
||||
fixed: injectStylePrefixed(styletron, {
|
||||
width: '20px',
|
||||
height: '20px'
|
||||
})
|
||||
};
|
||||
|
||||
module.exports = Box;
|
||||
@@ -17,10 +17,12 @@ class GridView extends Component {
|
||||
return (
|
||||
<View {...other} style={[style, styles.root, hasGap && styles.hasGap]}>
|
||||
{React.Children.map(children, child => {
|
||||
return child &&
|
||||
return (
|
||||
child &&
|
||||
React.cloneElement(child, {
|
||||
style: [child.props.style, styles.column, hasGap && styles.hasGapColumn]
|
||||
});
|
||||
})
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
@@ -40,7 +42,7 @@ const styles = StyleSheet.create({
|
||||
minWidth: 0 // 2
|
||||
},
|
||||
hasGap: {
|
||||
marginHorizontal: theme.createLength(theme.spaceX * (-0.5), 'rem')
|
||||
marginHorizontal: theme.createLength(theme.spaceX * -0.5, 'rem')
|
||||
},
|
||||
hasGapColumn: {
|
||||
marginHorizontal: theme.createLength(theme.spaceX * 0.5, 'rem')
|
||||
19
benchmarks/src/components/Icons/DirectMessage.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createDOMElement } from 'react-native';
|
||||
import React from 'react';
|
||||
import styles from './styles';
|
||||
|
||||
const IconDirectMessage = props =>
|
||||
createDOMElement('svg', {
|
||||
children: (
|
||||
<g>
|
||||
<path d="M43.34 14H12.66L28 27.946z" />
|
||||
<path d="M51.392 14.789L30.018 34.22c-.009.008-.028.006-.039.012-.563.5-1.266.768-1.98.768-.72 0-1.442-.258-2.017-.78L4.609 14.79A3.957 3.957 0 0 0 3 18v37a1.998 1.998 0 0 0 2 2c.464 0 .924-.162 1.292-.473L19 46h30c2.243 0 4-1.757 4-4V18a3.96 3.96 0 0 0-1.608-3.211z" />
|
||||
</g>
|
||||
),
|
||||
style: [styles.icon, props.style],
|
||||
viewBox: '0 0 56 72'
|
||||
});
|
||||
|
||||
IconDirectMessage.metadata = { height: 72, width: 56 };
|
||||
|
||||
export default IconDirectMessage;
|
||||
18
benchmarks/src/components/Icons/Heart.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { createDOMElement } from 'react-native';
|
||||
import React from 'react';
|
||||
import styles from './styles';
|
||||
|
||||
const IconHeart = props =>
|
||||
createDOMElement('svg', {
|
||||
children: (
|
||||
<g>
|
||||
<path d="M38.723 12c-7.187 0-11.16 7.306-11.723 8.131C26.437 19.306 22.504 12 15.277 12 8.791 12 3.533 18.163 3.533 24.647 3.533 39.964 21.891 55.907 27 56c5.109-.093 23.467-16.036 23.467-31.353C50.467 18.163 45.209 12 38.723 12z" />
|
||||
</g>
|
||||
),
|
||||
style: [styles.icon, props.style],
|
||||
viewBox: '0 0 54 72'
|
||||
});
|
||||
|
||||
IconHeart.metadata = { height: 72, width: 54 };
|
||||
|
||||
export default IconHeart;
|
||||
18
benchmarks/src/components/Icons/Reply.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { createDOMElement } from 'react-native';
|
||||
import React from 'react';
|
||||
import styles from './styles';
|
||||
|
||||
const IconReply = props =>
|
||||
createDOMElement('svg', {
|
||||
children: (
|
||||
<g>
|
||||
<path d="M41 31h-9V19a2.999 2.999 0 0 0-4.817-2.386l-21 16a3 3 0 0 0-.001 4.773l21 16a3.006 3.006 0 0 0 3.15.301A2.997 2.997 0 0 0 32 51V39h9c5.514 0 10 4.486 10 10a4 4 0 0 0 8 0c0-9.925-8.075-18-18-18z" />
|
||||
</g>
|
||||
),
|
||||
style: [styles.icon, props.style],
|
||||
viewBox: '0 0 62 72'
|
||||
});
|
||||
|
||||
IconReply.metadata = { height: 72, width: 62 };
|
||||
|
||||
export default IconReply;
|
||||
18
benchmarks/src/components/Icons/Retweet.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { createDOMElement } from 'react-native';
|
||||
import React from 'react';
|
||||
import styles from './styles';
|
||||
|
||||
const IconRetweet = props =>
|
||||
createDOMElement('svg', {
|
||||
children: (
|
||||
<g>
|
||||
<path d="M70.676 36.644A3 3 0 0 0 68 35h-7V19a4 4 0 0 0-4-4H34a4 4 0 0 0 0 8h18a1 1 0 0 1 1 .998V35h-7a3.001 3.001 0 0 0-2.419 4.775l11 15a3.003 3.003 0 0 0 4.839-.001l11-15a3.001 3.001 0 0 0 .256-3.13zM40.001 48H22a.995.995 0 0 1-.992-.96L21.001 36h7a3.001 3.001 0 0 0 2.419-4.775l-11-15a3.003 3.003 0 0 0-4.839.001l-11 15A3 3 0 0 0 6.001 36h7l.011 16.003a4 4 0 0 0 4 3.997h22.989a4 4 0 0 0 0-8z" />
|
||||
</g>
|
||||
),
|
||||
style: [styles.icon, props.style],
|
||||
viewBox: '0 0 74 72'
|
||||
});
|
||||
|
||||
IconRetweet.metadata = { height: 72, width: 74 };
|
||||
|
||||
export default IconRetweet;
|
||||
@@ -17,17 +17,16 @@ class DeepTree extends Component {
|
||||
<Box color={id % 3} components={components} layout={depth % 2 === 0 ? 'column' : 'row'} outer>
|
||||
{depth === 0 && <Box color={id % 3 + 3} components={components} fixed />}
|
||||
{depth !== 0 &&
|
||||
Array.from({ length: breadth })
|
||||
.map((el, i) => (
|
||||
<DeepTree
|
||||
breadth={breadth}
|
||||
components={components}
|
||||
depth={depth - 1}
|
||||
id={i}
|
||||
key={i}
|
||||
wrap={wrap}
|
||||
/>
|
||||
))}
|
||||
Array.from({ length: breadth }).map((el, i) => (
|
||||
<DeepTree
|
||||
breadth={breadth}
|
||||
components={components}
|
||||
depth={depth - 1}
|
||||
id={i}
|
||||
key={i}
|
||||
wrap={wrap}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
for (let i = 0; i < wrap; i++) {
|
||||
@@ -18,14 +18,7 @@ class UserNames extends PureComponent {
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
fullName,
|
||||
layout,
|
||||
onPress,
|
||||
screenName,
|
||||
style,
|
||||
...other
|
||||
} = this.props;
|
||||
const { fullName, layout, onPress, screenName, style, ...other } = this.props;
|
||||
|
||||
return (
|
||||
<AppText
|
||||
31
benchmarks/src/components/View/aphrodite.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react';
|
||||
import { css, StyleSheet } from 'aphrodite';
|
||||
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const { style, ...other } = this.props;
|
||||
return <div {...other} className={css(styles.root, style)} />;
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
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
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = View;
|
||||
13
benchmarks/src/components/View/css-modules.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/* 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)} />;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = View;
|
||||
@@ -2,7 +2,12 @@
|
||||
import { css } from 'glamor';
|
||||
import React from 'react';
|
||||
|
||||
const View = props => <div {...props} className={css(viewStyle, props.style)} />;
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const { style, ...other } = this.props;
|
||||
return <div {...other} className={css(viewStyle, ...style)} />;
|
||||
}
|
||||
}
|
||||
|
||||
const viewStyle = {
|
||||
alignItems: 'stretch',
|
||||
@@ -16,14 +21,6 @@ const viewStyle = {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
position: 'relative',
|
||||
// button and anchor reset
|
||||
backgroundColor: 'transparent',
|
||||
color: 'inherit',
|
||||
font: 'inherit',
|
||||
textAlign: 'inherit',
|
||||
textDecorationLine: 'none',
|
||||
// list reset
|
||||
listStyle: 'none',
|
||||
// fix flexbox bugs
|
||||
minHeight: 0,
|
||||
minWidth: 0
|
||||
32
benchmarks/src/components/View/jss.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import injectSheet from 'react-jss';
|
||||
import React from 'react';
|
||||
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const { classes, className, ...other } = this.props;
|
||||
return <div {...other} className={classnames(classes.root, className)} />;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = injectSheet(styles)(View);
|
||||
35
benchmarks/src/components/View/react-native-stylesheet.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react';
|
||||
import StyleSheet from 'react-native/apis/StyleSheet';
|
||||
import registry from 'react-native/apis/StyleSheet/registry';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const { style, ...other } = this.props;
|
||||
const styleProps = registry.resolve([styles.root, style]) || emptyObject;
|
||||
return <div {...other} {...styleProps} />;
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
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
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = View;
|
||||
@@ -12,12 +12,6 @@ const View = styled.div`
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
text-align: inherit;
|
||||
text-decoration: none;
|
||||
list-style: none;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
`;
|
||||
@@ -10,12 +10,6 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
text-align: inherit;
|
||||
text-decoration: none;
|
||||
list-style: none;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
33
benchmarks/src/components/View/styletron.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import Styletron from 'styletron-client';
|
||||
import { injectStylePrefixed } from 'styletron-utils';
|
||||
import React from 'react';
|
||||
|
||||
export const styletron = new Styletron();
|
||||
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const { style, ...other } = this.props;
|
||||
return <div {...other} className={classnames(viewStyle, ...style)} />;
|
||||
}
|
||||
}
|
||||
|
||||
const viewStyle = injectStylePrefixed(styletron, {
|
||||
alignItems: 'stretch',
|
||||
borderWidth: '0px',
|
||||
borderStyle: 'solid',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
flexBasis: 'auto',
|
||||
flexDirection: 'column',
|
||||
flexShrink: '0',
|
||||
margin: '0px',
|
||||
padding: '0px',
|
||||
position: 'relative',
|
||||
// fix flexbox bugs
|
||||
minHeight: '0px',
|
||||
minWidth: '0px'
|
||||
});
|
||||
|
||||
export default View;
|
||||
7
benchmarks/src/css-modules.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/css-modules';
|
||||
import View from './components/View/css-modules';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
7
benchmarks/src/glamor.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/glamor';
|
||||
import View from './components/View/glamor';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
7
benchmarks/src/jss.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/jss';
|
||||
import View from './components/View/jss';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
7
benchmarks/src/react-native-stylesheet.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/react-native-stylesheet';
|
||||
import View from './components/View/react-native-stylesheet';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
9
benchmarks/src/react-native.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import Box from './components/Box/react-native';
|
||||
import Tweet from './components/Tweet';
|
||||
import { View } from 'react-native';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Tweet,
|
||||
View
|
||||
};
|
||||
7
benchmarks/src/reactxp.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/reactxp';
|
||||
import { View } from 'reactxp';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
7
benchmarks/src/styled-components.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/styled-components';
|
||||
import View from './components/View/styled-components';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
7
benchmarks/src/styletron.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Box from './components/Box/styletron';
|
||||
import View from './components/View/styletron';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
View
|
||||
};
|
||||
14
benchmarks/tests/renderDeepTree.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import createRenderBenchmark from '../createRenderBenchmark';
|
||||
import NestedTree from '../src/components/NestedTree';
|
||||
import React from 'react';
|
||||
|
||||
const renderDeepTree = (label, components) =>
|
||||
createRenderBenchmark({
|
||||
name: `Deep tree [${label}]`,
|
||||
runs: 20,
|
||||
getElement() {
|
||||
return <NestedTree breadth={3} components={components} depth={6} id={0} wrap={1} />;
|
||||
}
|
||||
});
|
||||
|
||||
export default renderDeepTree;
|
||||
@@ -1,5 +1,5 @@
|
||||
import createRenderBenchmark from '../createRenderBenchmark';
|
||||
import Tweet from '../components/Tweet';
|
||||
import Tweet from '../src/components/Tweet';
|
||||
import React from 'react';
|
||||
|
||||
const tweet1 = {
|
||||
@@ -96,17 +96,18 @@ const tweet2 = {
|
||||
}
|
||||
};
|
||||
|
||||
const renderTweet = (label, components) => createRenderBenchmark({
|
||||
name: `Tweet [${label}]`,
|
||||
runs: 10,
|
||||
getElement() {
|
||||
return (
|
||||
<div style={{ width: 500 }}>
|
||||
<Tweet tweet={tweet1} />
|
||||
<Tweet tweet={tweet2} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
const renderTweet = (label, components) =>
|
||||
createRenderBenchmark({
|
||||
name: `Tweet [${label}]`,
|
||||
runs: 10,
|
||||
getElement() {
|
||||
return (
|
||||
<div style={{ width: 500 }}>
|
||||
<Tweet tweet={tweet1} />
|
||||
<Tweet tweet={tweet2} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default renderTweet;
|
||||
14
benchmarks/tests/renderWideTree.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import createRenderBenchmark from '../createRenderBenchmark';
|
||||
import NestedTree from '../src/components/NestedTree';
|
||||
import React from 'react';
|
||||
|
||||
const renderWideTree = (label, components) =>
|
||||
createRenderBenchmark({
|
||||
name: `Wide tree [${label}]`,
|
||||
runs: 20,
|
||||
getElement() {
|
||||
return <NestedTree breadth={10} components={components} depth={3} id={0} wrap={4} />;
|
||||
}
|
||||
});
|
||||
|
||||
export default renderWideTree;
|
||||
@@ -10,17 +10,23 @@ module.exports = {
|
||||
filename: 'performance.bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: 'style-loader!css-loader?module&localIdentName=[hash:base64:8]'
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: { module: true, localIdentName: '[hash:base64:8]' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
cacheDirectory: true
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: { cacheDirectory: true }
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -33,13 +39,11 @@ module.exports = {
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
}),
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
dead_code: true,
|
||||
screw_ie8: true,
|
||||
warnings: true
|
||||
warnings: false
|
||||
}
|
||||
})
|
||||
],
|
||||
@@ -14,16 +14,30 @@ ansi-styles@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
||||
|
||||
aphrodite@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/aphrodite/-/aphrodite-1.2.1.tgz#a7b5066b198730be7b7a88f78dbefd77d4df5683"
|
||||
dependencies:
|
||||
asap "^2.0.3"
|
||||
inline-style-prefixer "^3.0.1"
|
||||
string-hash "^1.1.3"
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
|
||||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
asap@~2.0.3:
|
||||
asap@^2.0.3, asap@~2.0.3:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
|
||||
|
||||
assert@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
|
||||
dependencies:
|
||||
util "0.10.3"
|
||||
|
||||
autoprefixer@^6.3.1:
|
||||
version "6.7.5"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.5.tgz#50848f39dc08730091d9495023487e7cc21f518d"
|
||||
@@ -62,7 +76,7 @@ big.js@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
|
||||
|
||||
bowser@^1.0.0:
|
||||
bowser@^1.0.0, bowser@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.6.0.tgz#37fc387b616cb6aef370dab4d6bd402b74c5c54d"
|
||||
|
||||
@@ -175,9 +189,15 @@ css-color-names@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
||||
|
||||
css-loader@^0.26.2:
|
||||
version "0.26.2"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.26.2.tgz#a9cd4c2b1a559b45d8efc04fc311ab5d2aaccb9d"
|
||||
css-in-js-utils@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/css-in-js-utils/-/css-in-js-utils-1.0.3.tgz#9ac7e02f763cf85d94017666565ed68a5b5f3215"
|
||||
dependencies:
|
||||
hyphenate-style-name "^1.0.2"
|
||||
|
||||
css-loader@^0.28.1:
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.1.tgz#220325599f8f00452d9ceb4c3ca6c8a66798642d"
|
||||
dependencies:
|
||||
babel-code-frame "^6.11.0"
|
||||
css-selector-tokenizer "^0.7.0"
|
||||
@@ -190,6 +210,7 @@ css-loader@^0.26.2:
|
||||
postcss-modules-local-by-default "^1.0.1"
|
||||
postcss-modules-scope "^1.0.0"
|
||||
postcss-modules-values "^1.1.0"
|
||||
postcss-value-parser "^3.3.0"
|
||||
source-list-map "^0.1.7"
|
||||
|
||||
css-selector-tokenizer@^0.6.0:
|
||||
@@ -208,14 +229,20 @@ css-selector-tokenizer@^0.7.0:
|
||||
fastparse "^1.1.1"
|
||||
regexpu-core "^1.0.0"
|
||||
|
||||
css-to-react-native@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.1.tgz#179b25cba8cab7798118b1679b81f4d6b3fa0de3"
|
||||
css-to-react-native@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.3.tgz#7d3a11409ac283acef447a13d3bbd09980c68a4f"
|
||||
dependencies:
|
||||
css-color-keywords "^1.0.0"
|
||||
fbjs "^0.8.5"
|
||||
postcss-value-parser "^3.3.0"
|
||||
|
||||
css-vendor@^0.3.8:
|
||||
version "0.3.8"
|
||||
resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-0.3.8.tgz#6421cfd3034ce664fe7673972fd0119fc28941fa"
|
||||
dependencies:
|
||||
is-in-browser "^1.0.2"
|
||||
|
||||
cssesc@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
|
||||
@@ -302,7 +329,7 @@ fastparse@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
|
||||
|
||||
fbjs@^0.8.5, fbjs@^0.8.8, fbjs@^0.8.9:
|
||||
fbjs@^0.8.4, fbjs@^0.8.5, fbjs@^0.8.8, fbjs@^0.8.9:
|
||||
version "0.8.9"
|
||||
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.9.tgz#180247fbd347dcc9004517b904f865400a0c8f14"
|
||||
dependencies:
|
||||
@@ -322,21 +349,14 @@ function-bind@^1.0.2:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
|
||||
|
||||
glamor@3.0.0-1:
|
||||
version "3.0.0-1"
|
||||
resolved "https://registry.yarnpkg.com/glamor/-/glamor-3.0.0-1.tgz#60f489e96d96c12620803d3677ac26413cb76a95"
|
||||
dependencies:
|
||||
babel-runtime "^6.18.0"
|
||||
fbjs "^0.8.8"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
glamor@^2.20.22:
|
||||
version "2.20.24"
|
||||
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.24.tgz#a299af2eec687322634ba38e4a0854d8743d2041"
|
||||
glamor@2.20.25:
|
||||
version "2.20.25"
|
||||
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.25.tgz#71b84b82b67a9327771ac59de53ee915d148a4a3"
|
||||
dependencies:
|
||||
babel-runtime "^6.18.0"
|
||||
fbjs "^0.8.8"
|
||||
object-assign "^4.1.0"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
has-ansi@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -354,11 +374,15 @@ has@^1.0.1:
|
||||
dependencies:
|
||||
function-bind "^1.0.2"
|
||||
|
||||
hoist-non-react-statics@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
|
||||
|
||||
html-comment-regex@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
|
||||
|
||||
hyphenate-style-name@^1.0.1:
|
||||
hyphenate-style-name@^1.0.1, hyphenate-style-name@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
|
||||
|
||||
@@ -374,17 +398,32 @@ ieee754@^1.1.4:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
|
||||
|
||||
ifvisible.js@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/ifvisible.js/-/ifvisible.js-1.0.6.tgz#52eb151ce89c56f15316226462e892d1f8451261"
|
||||
|
||||
indexes-of@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
|
||||
|
||||
inline-style-prefixer@^2.0.5:
|
||||
inherits@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
|
||||
|
||||
inline-style-prefixer@^2.0.1, inline-style-prefixer@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz#c153c7e88fd84fef5c602e95a8168b2770671fe7"
|
||||
dependencies:
|
||||
bowser "^1.0.0"
|
||||
hyphenate-style-name "^1.0.1"
|
||||
|
||||
inline-style-prefixer@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/inline-style-prefixer/-/inline-style-prefixer-3.0.2.tgz#989865e0c5de7a946acbea71e16e02741efe0dd7"
|
||||
dependencies:
|
||||
bowser "^1.6.0"
|
||||
css-in-js-utils "^1.0.3"
|
||||
|
||||
is-absolute-url@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
|
||||
@@ -393,6 +432,10 @@ is-function@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
|
||||
|
||||
is-in-browser@1.0.2, is-in-browser@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.0.2.tgz#f688bea8f1e5aadc3244ebc870d188cfb9b613cf"
|
||||
|
||||
is-plain-obj@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||
@@ -447,6 +490,71 @@ json5@^0.5.0:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
||||
|
||||
jss-camel-case@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-camel-case/-/jss-camel-case-4.0.0.tgz#39ef2a137aaa1e2f160ab826845305f8efabcfd5"
|
||||
|
||||
jss-compose@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jss-compose/-/jss-compose-3.0.1.tgz#0ac07f20baf1d523c211016d383dab08dcfe4186"
|
||||
dependencies:
|
||||
warning "^3.0.0"
|
||||
|
||||
jss-default-unit@^6.0.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-default-unit/-/jss-default-unit-6.1.0.tgz#ea6ca838de119c17adbce597b21ba9c20f7f4d84"
|
||||
|
||||
jss-expand@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-expand/-/jss-expand-3.0.0.tgz#ce22bf8f9d99afa822738d82dcc3bdbf32766b1d"
|
||||
|
||||
jss-extend@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-extend/-/jss-extend-4.0.0.tgz#1c377d4efd67f34c997b699aa8bc1dab1c7edf95"
|
||||
dependencies:
|
||||
warning "^3.0.0"
|
||||
|
||||
jss-global@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-global/-/jss-global-1.0.0.tgz#ba87850cd56d32e0623c3878fd5ef376a61e6f65"
|
||||
|
||||
jss-nested@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-nested/-/jss-nested-4.0.0.tgz#70d8aaaeb0ae1c0ca6ac74b329255b71e58bf72e"
|
||||
dependencies:
|
||||
warning "^3.0.0"
|
||||
|
||||
jss-preset-default@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-preset-default/-/jss-preset-default-2.0.0.tgz#0368d99626b31067e8d04ab3c7cb17ba8354d422"
|
||||
dependencies:
|
||||
jss-camel-case "^4.0.0"
|
||||
jss-compose "^3.0.0"
|
||||
jss-default-unit "^6.0.0"
|
||||
jss-expand "^3.0.0"
|
||||
jss-extend "^4.0.0"
|
||||
jss-global "^1.0.0"
|
||||
jss-nested "^4.0.0"
|
||||
jss-props-sort "^4.0.0"
|
||||
jss-vendor-prefixer "^5.0.0"
|
||||
|
||||
jss-props-sort@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-props-sort/-/jss-props-sort-4.0.0.tgz#ef4239c6795ca304c18dce9e0395a1789ed9f78a"
|
||||
|
||||
jss-vendor-prefixer@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jss-vendor-prefixer/-/jss-vendor-prefixer-5.1.0.tgz#59b73544de81e6b2efd71f6d3b744671826865a2"
|
||||
dependencies:
|
||||
css-vendor "^0.3.8"
|
||||
|
||||
jss@^7.0.0:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/jss/-/jss-7.0.3.tgz#87a4ff5c9398f7ee7ddc06a6b02255a4c74d9e1b"
|
||||
dependencies:
|
||||
is-in-browser "1.0.2"
|
||||
warning "3.0.0"
|
||||
|
||||
loader-utils@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.0.2.tgz#a9f923c865a974623391a8602d031137fad74830"
|
||||
@@ -467,6 +575,10 @@ lodash.uniq@^4.3.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
||||
lodash@^4.17.1:
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||
|
||||
loose-envify@^1.0.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
|
||||
@@ -477,9 +589,9 @@ macaddress@^0.2.8:
|
||||
version "0.2.8"
|
||||
resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
|
||||
|
||||
marky@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/marky/-/marky-1.1.3.tgz#b5b914c661f73355862a77acf21aadfc60745e37"
|
||||
marky@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.0.tgz#9617ed647bbbea8f45d19526da33dec70606df42"
|
||||
|
||||
math-expression-evaluator@^1.2.14:
|
||||
version "1.2.16"
|
||||
@@ -771,6 +883,12 @@ promise@^7.1.1:
|
||||
dependencies:
|
||||
asap "~2.0.3"
|
||||
|
||||
prop-types@^15.5.4, prop-types@^15.5.8:
|
||||
version "15.5.8"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.8.tgz#6b7b2e141083be38c8595aa51fc55775c7199394"
|
||||
dependencies:
|
||||
fbjs "^0.8.9"
|
||||
|
||||
q@^1.1.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
|
||||
@@ -782,6 +900,36 @@ query-string@^4.1.0:
|
||||
object-assign "^4.1.0"
|
||||
strict-uri-encode "^1.0.0"
|
||||
|
||||
react-addons-perf@^15.4.2:
|
||||
version "15.4.2"
|
||||
resolved "https://registry.yarnpkg.com/react-addons-perf/-/react-addons-perf-15.4.2.tgz#110bdcf5c459c4f77cb85ed634bcd3397536383b"
|
||||
dependencies:
|
||||
fbjs "^0.8.4"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
react-jss@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-6.1.1.tgz#01a548e6531b691186c3e8d8250980fb2938f1fe"
|
||||
dependencies:
|
||||
hoist-non-react-statics "^1.2.0"
|
||||
jss "^7.0.0"
|
||||
jss-preset-default "^2.0.0"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
reactxp@^0.34.3:
|
||||
version "0.34.3"
|
||||
resolved "https://registry.yarnpkg.com/reactxp/-/reactxp-0.34.3.tgz#6481992e57758ae6ffffbfde3d497527bb495032"
|
||||
dependencies:
|
||||
assert "^1.3.0"
|
||||
ifvisible.js "^1.0.6"
|
||||
lodash "^4.17.1"
|
||||
rebound "^0.0.13"
|
||||
synctasks "^0.2.9"
|
||||
|
||||
rebound@^0.0.13:
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/rebound/-/rebound-0.0.13.tgz#4a225254caf7da756797b19c5817bf7a7941fac1"
|
||||
|
||||
reduce-css-calc@^1.2.6:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
|
||||
@@ -852,35 +1000,56 @@ strict-uri-encode@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
|
||||
string-hash@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
|
||||
|
||||
strip-ansi@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
style-loader@^0.13.2:
|
||||
version "0.13.2"
|
||||
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.13.2.tgz#74533384cf698c7104c7951150b49717adc2f3bb"
|
||||
style-loader@^0.17.0:
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.17.0.tgz#e8254bccdb7af74bd58274e36107b4d5ab4df310"
|
||||
dependencies:
|
||||
loader-utils "^1.0.2"
|
||||
|
||||
styled-components@2.0.0-7:
|
||||
version "2.0.0-7"
|
||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.0.0-7.tgz#a420b99622eacec26ae3d62c1c75985791d9691b"
|
||||
styled-components@2.0.0-17:
|
||||
version "2.0.0-17"
|
||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.0.0-17.tgz#9d49e5b351f2c3e13698ee00d189a3c951735088"
|
||||
dependencies:
|
||||
buffer "^5.0.3"
|
||||
css-to-react-native "2.0.1"
|
||||
css-to-react-native "^2.0.3"
|
||||
fbjs "^0.8.9"
|
||||
glamor "^2.20.22"
|
||||
hoist-non-react-statics "^1.2.0"
|
||||
inline-style-prefixer "^2.0.5"
|
||||
is-function "^1.0.1"
|
||||
is-plain-object "^2.0.1"
|
||||
stylis "^1.2.0"
|
||||
prop-types "^15.5.4"
|
||||
stylis "^2.0.0"
|
||||
supports-color "^3.2.3"
|
||||
|
||||
stylis@^1.2.0:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-1.2.6.tgz#d7e72d3c8de52684a4f6cc82b3086e3634dc3c13"
|
||||
styletron-client@^2.5.7:
|
||||
version "2.5.7"
|
||||
resolved "https://registry.yarnpkg.com/styletron-client/-/styletron-client-2.5.7.tgz#104fa4dc564cd3fe78eb92488e5ef9039c9e242f"
|
||||
dependencies:
|
||||
styletron-core "^2.5.7"
|
||||
|
||||
styletron-core@^2.5.7:
|
||||
version "2.5.7"
|
||||
resolved "https://registry.yarnpkg.com/styletron-core/-/styletron-core-2.5.7.tgz#2c4a1fae537b42235462e438c24ab619bbf8993e"
|
||||
|
||||
styletron-utils@^2.5.4:
|
||||
version "2.5.4"
|
||||
resolved "https://registry.yarnpkg.com/styletron-utils/-/styletron-utils-2.5.4.tgz#f08cca7d58ee0338ce85e408cb32900e65620240"
|
||||
dependencies:
|
||||
inline-style-prefixer "^2.0.1"
|
||||
|
||||
stylis@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-2.0.3.tgz#054b0ad1f636181664246c103adf506c84b502e7"
|
||||
|
||||
supports-color@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -904,6 +1073,10 @@ svgo@^0.7.0:
|
||||
sax "~1.2.1"
|
||||
whet.extend "~0.9.9"
|
||||
|
||||
synctasks@^0.2.9:
|
||||
version "0.2.17"
|
||||
resolved "https://registry.yarnpkg.com/synctasks/-/synctasks-0.2.17.tgz#38852f008878de2e941b6e458ddf552245268da1"
|
||||
|
||||
ua-parser-js@^0.7.9:
|
||||
version "0.7.12"
|
||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
|
||||
@@ -922,10 +1095,22 @@ uniqs@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
|
||||
|
||||
util@0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
|
||||
dependencies:
|
||||
inherits "2.0.1"
|
||||
|
||||
vendors@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22"
|
||||
|
||||
warning@3.0.0, warning@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
whatwg-fetch@>=0.10.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.2.tgz#fe294d1d89e36c5be8b3195057f2e4bc74fc980e"
|
||||
2
core.js
@@ -1 +1 @@
|
||||
module.exports = require('./dist/core')
|
||||
module.exports = require('./dist/core');
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
`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 [client and server rendering
|
||||
guide](../guides/rendering.md) for more details).
|
||||
`AppRegistry.runApplication` (see the [getting started guide](../guides/getting-started.md) for more details).
|
||||
|
||||
To "stop" an application when a view should be destroyed, call
|
||||
`AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was passed
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# StyleSheet
|
||||
|
||||
The `StyleSheet` abstraction converts predefined styles to (vendor-prefixed)
|
||||
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).
|
||||
CSS without requiring a compile-time step. Styles that cannot be resolved
|
||||
outside of the render loop (e.g., dynamic positioning) are usually applied as
|
||||
inline styles. Read more about [how to style your
|
||||
application](../guides/style.md).
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -15,7 +16,7 @@ Each key of the object passed to `create` must define a style object.
|
||||
|
||||
Flattens an array of styles into a single style object.
|
||||
|
||||
**renderToString**: function
|
||||
(web) **renderToString**: function
|
||||
|
||||
Returns a string of the stylesheet for use in server-side rendering.
|
||||
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
|
||||
[...View props](./View.md)
|
||||
|
||||
**animating**: bool = true
|
||||
**animating**: boolean = true
|
||||
|
||||
Whether to show the indicator or hide it.
|
||||
|
||||
**color**: string = '#1976D2'
|
||||
**color**: ?color = '#1976D2'
|
||||
|
||||
The foreground color of the spinner.
|
||||
|
||||
**hidesWhenStopped**: bool = true
|
||||
**hidesWhenStopped**: ?boolean = true
|
||||
|
||||
Whether the indicator should hide when not animating.
|
||||
|
||||
**size**: oneOf('small, 'large') | number = 'small'
|
||||
**size**: ?enum('small, 'large') | number = 'small'
|
||||
|
||||
Size of the indicator. Small has a height of `20`, large has a height of `36`.
|
||||
|
||||
|
||||
@@ -6,23 +6,27 @@ build your own custom button using `TouchableOpacity` or
|
||||
|
||||
## Props
|
||||
|
||||
**accessibilityLabel**: string
|
||||
**accessibilityLabel**: ?string
|
||||
|
||||
Defines the text available to assistive technologies upon interaction with the
|
||||
element. (This is implemented using `aria-label`.)
|
||||
Overrides the text that's read by a screen reader when the user interacts
|
||||
with the element.
|
||||
|
||||
**color**: string
|
||||
**color**: ?string
|
||||
|
||||
Background color of the button.
|
||||
|
||||
**disabled**: bool = false
|
||||
**disabled**: ?boolean
|
||||
|
||||
If true, disable all interactions for this component
|
||||
If `true`, disable all interactions for this element.
|
||||
|
||||
**onPress**: function
|
||||
|
||||
This function is called on press.
|
||||
|
||||
**testID**: ?string
|
||||
|
||||
Used to locate this view in end-to-end tests.
|
||||
|
||||
**title**: string
|
||||
|
||||
Text to display inside the button.
|
||||
|
||||
@@ -9,65 +9,66 @@ Unsupported React Native props:
|
||||
|
||||
## Props
|
||||
|
||||
**accessibilityLabel**: string
|
||||
**accessibilityLabel**: ?string
|
||||
|
||||
The text that's read by a screenreader when someone interacts with the image.
|
||||
|
||||
**accessible**: bool
|
||||
**accessible**: ?boolean
|
||||
|
||||
When `false`, the view is hidden from screenreaders. Default: `true`.
|
||||
When `true`, indicates the image is an accessibility element.
|
||||
|
||||
**children**: any
|
||||
**children**: ?any
|
||||
|
||||
Content to display over the image.
|
||||
|
||||
**defaultSource**: { uri: string }
|
||||
**defaultSource**: ?object
|
||||
|
||||
An image to display as a placeholder while downloading the final image off the network.
|
||||
An image to display as a placeholder while downloading the final image off the
|
||||
network. `{ uri: string, width, height }`
|
||||
|
||||
**onError**: function
|
||||
**onError**: ?function
|
||||
|
||||
Invoked on load error with `{nativeEvent: {error}}`.
|
||||
|
||||
**onLayout**: function
|
||||
**onLayout**: ?function
|
||||
|
||||
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,
|
||||
height } } }`, where `x` and `y` are the offsets from the parent node.
|
||||
|
||||
**onLoad**: function
|
||||
**onLoad**: ?function
|
||||
|
||||
Invoked when load completes successfully.
|
||||
|
||||
**onLoadEnd**: function
|
||||
**onLoadEnd**: ?function
|
||||
|
||||
Invoked when load either succeeds or fails,
|
||||
|
||||
**onLoadStart**: function
|
||||
**onLoadStart**: ?function
|
||||
|
||||
Invoked on load start.
|
||||
|
||||
**resizeMode**: oneOf('center', 'contain', 'cover', 'none', 'repeat', 'stretch') = 'cover'
|
||||
**resizeMode**: ?enum('center', 'contain', 'cover', 'none', 'repeat', 'stretch') = 'cover'
|
||||
|
||||
Determines how to resize the image when the frame doesn't match the raw image
|
||||
dimensions.
|
||||
|
||||
**source**: { uri: string }
|
||||
**source**: ?object
|
||||
|
||||
`uri` is a string representing the resource identifier for the image, which
|
||||
could be an http address or a base64 encoded image.
|
||||
could be an http address or a base64 encoded image. `{ uri: string, width, height }`
|
||||
|
||||
**style**: style
|
||||
**style**: ?style
|
||||
|
||||
+ ...[View#style](./View.md)
|
||||
+ `resizeMode`
|
||||
|
||||
**testID**: string
|
||||
**testID**: ?string
|
||||
|
||||
Used to locate a view in end-to-end tests.
|
||||
|
||||
## Properties
|
||||
|
||||
static **resizeMode**: Object
|
||||
static **resizeMode**: object
|
||||
|
||||
Example usage:
|
||||
|
||||
|
||||
@@ -6,18 +6,22 @@ Display an activity progress bar.
|
||||
|
||||
[...View props](./View.md)
|
||||
|
||||
**color**: string = '#1976D2'
|
||||
**color**: ?string = '#1976D2'
|
||||
|
||||
Color of the progress bar.
|
||||
|
||||
**indeterminate**: bool = true
|
||||
**indeterminate**: ?boolean = true
|
||||
|
||||
Whether the progress bar will show indeterminate progress.
|
||||
|
||||
**progress**: number
|
||||
**progress**: ?number
|
||||
|
||||
The progress value (between 0 and 1).
|
||||
|
||||
(web) **trackColor**: string = 'transparent'
|
||||
**testID**: ?string
|
||||
|
||||
Used to locate this view in end-to-end tests.
|
||||
|
||||
(web) **trackColor**: ?string = 'transparent'
|
||||
|
||||
Color of the track bar.
|
||||
|
||||
@@ -9,17 +9,17 @@ view directly (discouraged) or make sure all parent views have bounded height
|
||||
|
||||
[...View props](./View.md)
|
||||
|
||||
**contentContainerStyle**: style
|
||||
**contentContainerStyle**: ?style
|
||||
|
||||
These styles will be applied to the scroll view content container which wraps
|
||||
all of the child views.
|
||||
|
||||
**horizontal**: bool = false
|
||||
**horizontal**: ?boolean = false
|
||||
|
||||
When true, the scroll view's children are arranged horizontally in a row
|
||||
When `true`, the scroll view's children are arranged horizontally in a row
|
||||
instead of vertically in a column.
|
||||
|
||||
**keyboardDismissMode**: oneOf('none', 'on-drag') = 'none'
|
||||
**keyboardDismissMode**: ?enum('none', 'on-drag') = 'none'
|
||||
|
||||
Determines whether the keyboard gets dismissed in response to a scroll drag.
|
||||
|
||||
@@ -27,13 +27,13 @@ Determines whether the keyboard gets dismissed in response to a scroll drag.
|
||||
* `on-drag`, the keyboard is dismissed when a drag begins.
|
||||
* `interactive` (not supported on web; same as `none`)
|
||||
|
||||
**onContentSizeChange**: function
|
||||
**onContentSizeChange**: ?function
|
||||
|
||||
Called when scrollable content view of the `ScrollView` changes. It's
|
||||
implemented using the `onLayout` handler attached to the content container
|
||||
which this `ScrollView` renders.
|
||||
|
||||
**onScroll**: function
|
||||
**onScroll**: ?function
|
||||
|
||||
Fires at most once per frame during scrolling. The frequency of the events can
|
||||
be contolled using the `scrollEventThrottle` prop.
|
||||
@@ -50,18 +50,18 @@ Invoked on scroll with the following event:
|
||||
}
|
||||
```
|
||||
|
||||
**refreshControl**: element
|
||||
**refreshControl**: ?element
|
||||
|
||||
TODO
|
||||
|
||||
A [RefreshControl](../RefreshControl) component, used to provide
|
||||
pull-to-refresh functionality for the `ScrollView`.
|
||||
|
||||
**scrollEnabled**: bool = true
|
||||
**scrollEnabled**: ?boolean = true
|
||||
|
||||
When false, the content does not scroll.
|
||||
|
||||
**scrollEventThrottle**: number = 0
|
||||
**scrollEventThrottle**: ?number = 0
|
||||
|
||||
This controls how often the scroll event will be fired while scrolling (as a
|
||||
time interval in ms). A lower number yields better accuracy for code that is
|
||||
|
||||
@@ -9,31 +9,31 @@ supplied `value` prop instead of the expected result of any user actions.
|
||||
|
||||
[...View props](./View.md)
|
||||
|
||||
**disabled**: bool = false
|
||||
**disabled**: ?boolean = false
|
||||
|
||||
If `true` the user won't be able to interact with the switch.
|
||||
|
||||
**onValueChange**: func
|
||||
**onValueChange**: ?function
|
||||
|
||||
Invoked with the new value when the value changes.
|
||||
|
||||
**value**: bool = false
|
||||
**value**: ?boolean = false
|
||||
|
||||
The value of the switch. If `true` the switch will be turned on.
|
||||
|
||||
(web) **activeThumbColor**: color = #009688
|
||||
(web) **activeThumbColor**: ?color = #009688
|
||||
|
||||
The color of the thumb grip when the switch is turned on.
|
||||
|
||||
(web) **activeTrackColor**: color = #A3D3CF
|
||||
(web) **activeTrackColor**: ?color = #A3D3CF
|
||||
|
||||
The color of the track when the switch is turned on.
|
||||
|
||||
(web) **thumbColor**: color = #FAFAFA
|
||||
(web) **thumbColor**: ?color = #FAFAFA
|
||||
|
||||
The color of the thumb grip when the switch is turned off.
|
||||
|
||||
(web) **trackColor**: color = #939393
|
||||
(web) **trackColor**: ?color = #939393
|
||||
|
||||
The color of the track when the switch is turned off.
|
||||
|
||||
|
||||
@@ -16,49 +16,62 @@ Unsupported React Native props:
|
||||
|
||||
NOTE: `Text` will transfer all other props to the rendered HTML element.
|
||||
|
||||
(web) **accessibilityLabel**: string
|
||||
(web) **accessibilityLabel**: ?string
|
||||
|
||||
Defines the text available to assistive technologies upon interaction with the
|
||||
element. (This is implemented using `aria-label`.)
|
||||
Overrides the text that's read by a screen reader when the user interacts
|
||||
with the element. (This is implemented using `aria-label`.)
|
||||
|
||||
(web) **accessibilityRole**: oneOf(roles)
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
(web) **accessibilityRole**: ?oneOf(roles)
|
||||
|
||||
Allows assistive technologies to present and support interaction with the view
|
||||
in a manner that is consistent with user expectations for similar views of that
|
||||
type. For example, marking a touchable view with an `accessibilityRole` of
|
||||
`button`. (This is implemented using [ARIA roles](http://www.w3.org/TR/wai-aria/roles#role_definitions)).
|
||||
|
||||
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.
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**accessible**: bool = true
|
||||
**accessible**: ?boolean
|
||||
|
||||
When `false`, the text is hidden from assistive technologies. (This is
|
||||
implemented using `aria-hidden`.)
|
||||
When `true`, indicates that the view is an accessibility element (i.e.,
|
||||
focusable) and groups its child content. By default, all the touchable elements
|
||||
and elements with `accessibilityRole` of `button` and `link` are accessible.
|
||||
(This is implemented using `tabindex`.)
|
||||
|
||||
**children**: any
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**children**: ?any
|
||||
|
||||
Child content.
|
||||
|
||||
**numberOfLines**: number
|
||||
**importantForAccessibility**: ?enum('auto', 'no-hide-descendants', 'yes')
|
||||
|
||||
A value of `no` will remove the element from the tab flow.
|
||||
|
||||
A value of `no-hide-descendants` will hide the element and its children from
|
||||
assistive technologies. (This is implemented using `aria-hidden`.)
|
||||
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**numberOfLines**: ?number
|
||||
|
||||
Truncates the text with an ellipsis after this many lines. Currently only supports `1`.
|
||||
|
||||
**onLayout**: function
|
||||
**onLayout**: ?function
|
||||
|
||||
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,
|
||||
height } } }`, where `x` and `y` are the offsets from the parent node.
|
||||
|
||||
**onPress**: function
|
||||
**onPress**: ?function
|
||||
|
||||
This function is called on press.
|
||||
|
||||
**selectable**: bool = true
|
||||
**selectable**: ?boolean
|
||||
|
||||
Lets the user select the text.
|
||||
When `false`, the text is not selectable.
|
||||
|
||||
**style**: style
|
||||
**style**: ?style
|
||||
|
||||
+ ...[View#style](View.md)
|
||||
+ `color`
|
||||
@@ -72,6 +85,7 @@ Lets the user select the text.
|
||||
+ `textAlign`
|
||||
+ `textAlignVertical`
|
||||
+ `textDecorationLine`
|
||||
+ `textIndent` ‡
|
||||
+ `textOverflow` ‡
|
||||
+ `textRendering` ‡
|
||||
+ `textShadowColor`
|
||||
@@ -85,7 +99,7 @@ Lets the user select the text.
|
||||
|
||||
‡ web only.
|
||||
|
||||
**testID**: string
|
||||
**testID**: ?string
|
||||
|
||||
Used to locate this view in end-to-end tests.
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Unsupported React Native props:
|
||||
|
||||
[...View props](./View.md)
|
||||
|
||||
**autoCapitalize**: oneOf('characters', 'none', 'sentences', 'words') = 'sentences'
|
||||
**autoCapitalize**: ?enum('characters', 'none', 'sentences', 'words') = 'sentences'
|
||||
|
||||
Automatically capitalize certain characters (only available in Chrome and iOS Safari).
|
||||
|
||||
@@ -27,21 +27,21 @@ Automatically capitalize certain characters (only available in Chrome and iOS Sa
|
||||
* `sentences`: Automatically capitalize the first letter of sentences.
|
||||
* `words`: Automatically capitalize the first letter of words.
|
||||
|
||||
(web) **autoComplete**: string
|
||||
(web) **autoComplete**: ?string
|
||||
|
||||
Indicates whether the value of the control can be automatically completed by
|
||||
the browser. [Accepted values](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
|
||||
|
||||
**autoCorrect**: bool = true
|
||||
**autoCorrect**: ?boolean = true
|
||||
|
||||
Automatically correct spelling mistakes (only available in iOS Safari).
|
||||
|
||||
**autoFocus**: bool = false
|
||||
**autoFocus**: ?boolean = false
|
||||
|
||||
If `true`, focuses the input on `componentDidMount`. Only the first form element
|
||||
in a document with `autofocus` is focused.
|
||||
|
||||
**blurOnSubmit**: bool
|
||||
**blurOnSubmit**: ?boolean
|
||||
|
||||
If `true`, the text field will blur when submitted. The default value is `true`
|
||||
for single-line fields and `false` for multiline fields. Note, for multiline
|
||||
@@ -49,110 +49,104 @@ fields setting `blurOnSubmit` to `true` means that pressing return will blur
|
||||
the field and trigger the `onSubmitEditing` event instead of inserting a
|
||||
newline into the field.
|
||||
|
||||
**clearTextOnFocus**: bool = false
|
||||
**clearTextOnFocus**: ?boolean = false
|
||||
|
||||
If `true`, clears the text field automatically when focused.
|
||||
|
||||
**defaultValue**: string
|
||||
**defaultValue**: ?string
|
||||
|
||||
Provides an initial value that will change when the user starts typing. Useful
|
||||
for simple use-cases where you don't want to deal with listening to events and
|
||||
updating the `value` prop to keep the controlled state in sync.
|
||||
|
||||
**editable**: bool = true
|
||||
**editable**: ?boolean = true
|
||||
|
||||
If `false`, text is not editable (i.e., read-only).
|
||||
|
||||
**keyboardType**: oneOf('default', 'email-address', 'numeric', 'phone-pad', 'search', 'url', 'web-search') = 'default'
|
||||
**keyboardType**: enum('default', 'email-address', 'numeric', 'phone-pad', 'search', 'url', 'web-search') = 'default'
|
||||
|
||||
Determines which keyboard to open. (NOTE: Safari iOS requires an ancestral
|
||||
`<form action>` element to display the `search` keyboard).
|
||||
|
||||
(Not available when `multiline` is `true`.)
|
||||
|
||||
**maxLength**: number
|
||||
**maxLength**: ?number
|
||||
|
||||
Limits the maximum number of characters that can be entered.
|
||||
|
||||
(web) **maxNumberOfLines**: number = numberOfLines
|
||||
|
||||
Limits the maximum number of lines for a multiline `TextInput`.
|
||||
|
||||
(Requires `multiline` to be `true`.)
|
||||
|
||||
**multiline**: bool = false
|
||||
**multiline**: ?boolean = false
|
||||
|
||||
If true, the text input can be multiple lines.
|
||||
|
||||
**numberOfLines**: number = 2
|
||||
**numberOfLines**: ?number = 2
|
||||
|
||||
Sets the initial number of lines for a multiline `TextInput`.
|
||||
Sets the number of lines for a multiline `TextInput`.
|
||||
|
||||
(Requires `multiline` to be `true`.)
|
||||
|
||||
**onBlur**: function
|
||||
**onBlur**: ?function
|
||||
|
||||
Callback that is called when the text input is blurred.
|
||||
|
||||
**onChange**: function
|
||||
**onChange**: ?function
|
||||
|
||||
Callback that is called when the text input's text changes.
|
||||
|
||||
**onChangeText**: function
|
||||
**onChangeText**: ?function
|
||||
|
||||
Callback that is called when the text input's text changes. The text is passed
|
||||
as an argument to the callback handler.
|
||||
|
||||
**onFocus**: function
|
||||
**onFocus**: ?function
|
||||
|
||||
Callback that is called when the text input is focused.
|
||||
|
||||
**onKeyPress**: function
|
||||
**onKeyPress**: ?function
|
||||
|
||||
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
|
||||
**onSelectionChange**: ?function
|
||||
|
||||
Callback that is called when the text input's selection changes. This will be called with
|
||||
`{ nativeEvent: { selection: { start, end } } }`.
|
||||
|
||||
**onSubmitEditing**: function
|
||||
**onSubmitEditing**: ?function
|
||||
|
||||
Callback that is called when the keyboard's submit button is pressed.
|
||||
|
||||
**placeholder**: string
|
||||
**placeholder**: ?string
|
||||
|
||||
The string that will be rendered in an empty `TextInput` before text has been
|
||||
entered.
|
||||
|
||||
**secureTextEntry**: bool = false
|
||||
**secureTextEntry**: ?boolean = false
|
||||
|
||||
If true, the text input obscures the text entered so that sensitive text like
|
||||
passwords stay secure.
|
||||
|
||||
(Not available when `multiline` is `true`.)
|
||||
|
||||
**selection**: { start: number, end: ?number }
|
||||
**selection**: ?{ start: number, end: ?number }
|
||||
|
||||
The start and end of the text input's selection. Set start and end to the same value to position the cursor.
|
||||
|
||||
**selectTextOnFocus**: bool = false
|
||||
**selectTextOnFocus**: ?boolean = false
|
||||
|
||||
If `true`, all text will automatically be selected on focus.
|
||||
|
||||
**style**: style
|
||||
**style**: ?style
|
||||
|
||||
+ ...[Text#style](./Text.md)
|
||||
+ `resize` ‡
|
||||
|
||||
‡ web only.
|
||||
|
||||
**testID**: string
|
||||
**testID**: ?string
|
||||
|
||||
Used to locate this view in end-to-end tests.
|
||||
|
||||
**value**: string
|
||||
**value**: ?string
|
||||
|
||||
The value to show for the text input. `TextInput` is a controlled component,
|
||||
which means the native `value` will be forced to match this prop if provided.
|
||||
|
||||
@@ -11,58 +11,33 @@ several child components, wrap them in a View.
|
||||
|
||||
[...View props](./View.md)
|
||||
|
||||
**accessibilityLabel**: string
|
||||
|
||||
Overrides the text that's read by the screen reader when the user interacts
|
||||
with the element.
|
||||
|
||||
(web) **accessibilityRole**: oneOf(roles) = 'button'
|
||||
|
||||
Allows assistive technologies to present and support interaction with the view
|
||||
|
||||
**accessible**: bool = true
|
||||
|
||||
When `false`, the view is hidden from screenreaders.
|
||||
|
||||
**children**: View
|
||||
|
||||
**delayLongPress**: number
|
||||
**delayLongPress**: ?number
|
||||
|
||||
Delay in ms, from `onPressIn`, before `onLongPress` is called.
|
||||
|
||||
**delayPressIn**: number
|
||||
**delayPressIn**: ?number
|
||||
|
||||
Delay in ms, from the start of the touch, before `onPressIn` is called.
|
||||
|
||||
**delayPressOut**: number
|
||||
**delayPressOut**: ?number
|
||||
|
||||
Delay in ms, from the release of the touch, before `onPressOut` is called.
|
||||
|
||||
**disabled**: bool
|
||||
**disabled**: ?boolean
|
||||
|
||||
If true, disable all interactions for this component.
|
||||
If `true`, disable all interactions for this component.
|
||||
|
||||
**hitSlop**: `{top: number, left: number, bottom: number, right: number}`
|
||||
**onLongPress**: ?function
|
||||
|
||||
This defines how far your touch can start away from the button. This is added
|
||||
to `pressRetentionOffset` when moving off of the button.
|
||||
|
||||
**onLayout**: function
|
||||
|
||||
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,
|
||||
height } } }`, where `x` and `y` are the offsets from the parent node.
|
||||
|
||||
**onLongPress**: function
|
||||
|
||||
**onPress**: function
|
||||
**onPress**: ?function
|
||||
|
||||
Called when the touch is released, but not if cancelled (e.g. by a scroll that steals the responder lock).
|
||||
|
||||
**onPressIn**: function
|
||||
**onPressIn**: ?function
|
||||
|
||||
**onPressOut**: function
|
||||
**onPressOut**: ?function
|
||||
|
||||
**pressRetentionOffset**: `{top: number, left: number, bottom: number, right: number}`
|
||||
**pressRetentionOffset**: ?`{top: number, left: number, bottom: number, right: number}`
|
||||
|
||||
When the scroll view is disabled, this defines how far your touch may move off
|
||||
of the button, before deactivating the button. Once deactivated, try moving it
|
||||
|
||||
@@ -7,23 +7,20 @@ inside another `View` and has 0-to-many children of any type.
|
||||
Also, refer to React Native's documentation about the [Gesture Responder
|
||||
System](http://facebook.github.io/react-native/releases/0.22/docs/gesture-responder-system.html).
|
||||
|
||||
Unsupported React Native props:
|
||||
`onAccessibilityTap`,
|
||||
`hitSlop`,
|
||||
`onMagicTap`
|
||||
Unsupported React Native props: `collapsable`, `onAccessibilityTap`, `onMagicTap`.
|
||||
|
||||
## Props
|
||||
|
||||
NOTE: `View` will transfer all other props to the rendered HTML element.
|
||||
|
||||
**accessibilityLabel**: string
|
||||
**accessibilityLabel**: ?string
|
||||
|
||||
Overrides the text that's read by the screen reader when the user interacts
|
||||
with the element. By default, the label is constructed by traversing all the
|
||||
children and accumulating all the `Text` nodes separated by space. (This is
|
||||
implemented using `aria-label`.)
|
||||
Overrides the text that's read by a screen reader when the user interacts
|
||||
with the element. (This is implemented using `aria-label`.)
|
||||
|
||||
**accessibilityLiveRegion**: oneOf('assertive', 'off', 'polite') = 'off'
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**accessibilityLiveRegion**: ?enum('assertive', 'none', 'polite')
|
||||
|
||||
Indicates to assistive technologies whether to notify the user when the view
|
||||
changes. The values of this attribute are expressed in degrees of importance.
|
||||
@@ -32,64 +29,105 @@ 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).)
|
||||
|
||||
(web) **accessibilityRole**: oneOf(roles)
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
(web) **accessibilityRole**: ?enum(roles)
|
||||
|
||||
Allows assistive technologies to present and support interaction with the view
|
||||
in a manner that is consistent with user expectations for similar views of that
|
||||
type. For example, marking a touchable view with an `accessibilityRole` of
|
||||
`button`. (This is implemented using [ARIA roles](http://www.w3.org/TR/wai-aria/roles#role_definitions)).
|
||||
|
||||
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.
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**accessible**: bool = true
|
||||
**accessible**: ?boolean
|
||||
|
||||
When `false`, the view is hidden from assistive technologies. (This is
|
||||
implemented using `aria-hidden`.)
|
||||
When `true`, indicates that the view is an accessibility element (i.e.,
|
||||
focusable) and groups its child content. By default, all the touchable elements
|
||||
and elements with `accessibilityRole` of `button` and `link` are accessible.
|
||||
(This is implemented using `tabindex`.)
|
||||
|
||||
**hitSlop**: {top: number, left: number, bottom: number, right: number}
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
This defines how far a touch event can start away from the view. Typical
|
||||
interface guidelines recommend touch targets that are at least 30 - 40
|
||||
**children**: ?element
|
||||
|
||||
Child content.
|
||||
|
||||
**hitSlop**: ?object
|
||||
|
||||
This defines how far a touch event can start away from the view (in pixels).
|
||||
Typical interface guidelines recommend touch targets that are at least 30 - 40
|
||||
points/density-independent pixels.
|
||||
|
||||
For example, if a touchable view has a height of 20 the touchable height can be
|
||||
extended to 40 with `hitSlop={{top: 10, bottom: 10, left: 0, right: 0}}`.
|
||||
For example, if a touchable view has a height of `20` the touchable height can
|
||||
be extended to `40` with `hitSlop={{top: 10, bottom: 10, left: 0, right: 0}}`.
|
||||
|
||||
**onLayout**: function
|
||||
**importantForAccessibility**: ?enum('auto', 'no', 'no-hide-descendants', 'yes')
|
||||
|
||||
A value of `no` will remove the element from the tab flow.
|
||||
|
||||
A value of `no-hide-descendants` will hide the element and its children from
|
||||
assistive technologies. (This is implemented using `aria-hidden`.)
|
||||
|
||||
See the [Accessibility guide](../guides/accessibility) for more information.
|
||||
|
||||
**onLayout**: ?function
|
||||
|
||||
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,
|
||||
height } } }`, where `x` and `y` are the offsets from the parent node.
|
||||
|
||||
**onMoveShouldSetResponder**: function
|
||||
**onMoveShouldSetResponder**: ?function => boolean
|
||||
|
||||
**onMoveShouldSetResponderCapture**: function
|
||||
Does this view want to "claim" touch responsiveness? This is called for every
|
||||
touch move on the `View` when it is not the responder.
|
||||
|
||||
**onResponderGrant**: function
|
||||
**onMoveShouldSetResponderCapture**: ?function => boolean
|
||||
|
||||
For most touch interactions, you'll simply want to wrap your component in
|
||||
`TouchableHighlight` or `TouchableOpacity`.
|
||||
If a parent `View` wants to prevent a child `View` from becoming responder on a
|
||||
move, it should have this handler return `true`.
|
||||
|
||||
**onResponderMove**: function
|
||||
**onResponderGrant**: ?function
|
||||
|
||||
**onResponderReject**: function
|
||||
The `View` is now responding to touch events. This is the time to highlight and
|
||||
show the user what is happening. For most touch interactions, you'll simply
|
||||
want to wrap your component in `TouchableHighlight` or `TouchableOpacity`.
|
||||
|
||||
**onResponderRelease**: function
|
||||
**onResponderMove**: ?function
|
||||
|
||||
**onResponderTerminate**: function
|
||||
The user is moving their finger.
|
||||
|
||||
**onResponderTerminationRequest**: function
|
||||
**onResponderReject**: ?function
|
||||
|
||||
**onStartShouldSetResponder**: function
|
||||
Another responder is already active and will not release it to the `View`
|
||||
asking to be the responder.
|
||||
|
||||
**onStartShouldSetResponderCapture**: function
|
||||
**onResponderRelease**: ?function
|
||||
|
||||
**pointerEvents**: oneOf('auto', 'box-only', 'box-none', 'none') = 'auto'
|
||||
Fired at the end of the touch.
|
||||
|
||||
Configure the `pointerEvents` of the view. The enhanced `pointerEvents` modes
|
||||
provided are not part of the CSS spec, therefore, `pointerEvents` is excluded
|
||||
from `style`.
|
||||
**onResponderTerminate**: ?function
|
||||
|
||||
The responder has been taken from the `View`.
|
||||
|
||||
**onResponderTerminationRequest**: ?function
|
||||
|
||||
Some other `View` wants to become responder and is asking this `View` to
|
||||
release its responder. Returning `true` allows its release.
|
||||
|
||||
**onStartShouldSetResponder**: ?function => boolean
|
||||
|
||||
Does this view want to become responder on the start of a touch?
|
||||
|
||||
**onStartShouldSetResponderCapture**: ?function => boolean
|
||||
|
||||
If a parent `View` wants to prevent a child `View` from becoming the responder
|
||||
on a touch start, it should have this handler return `true`.
|
||||
|
||||
**pointerEvents**: ?enum('auto', 'box-only', 'box-none', 'none') = 'auto'
|
||||
|
||||
Controls whether the View can be the target of touch events. The enhanced
|
||||
`pointerEvents` modes provided are not part of the CSS spec, therefore,
|
||||
`pointerEvents` is excluded from `style`.
|
||||
|
||||
`box-none` is the equivalent of:
|
||||
|
||||
@@ -105,7 +143,7 @@ from `style`.
|
||||
.box-only * { pointer-events: none }
|
||||
```
|
||||
|
||||
**style**: style
|
||||
**style**: ?style
|
||||
|
||||
+ `alignContent`
|
||||
+ `alignItems`
|
||||
@@ -148,16 +186,30 @@ from `style`.
|
||||
+ `borderRightWidth`
|
||||
+ `borderTopWidth`
|
||||
+ `bottom`
|
||||
+ `boxShadow`
|
||||
+ `boxShadow` ‡
|
||||
+ `boxSizing`
|
||||
+ `clip` ‡
|
||||
+ `cursor` ‡
|
||||
+ `display` ‡
|
||||
+ `display`
|
||||
+ `filter` ‡
|
||||
+ `flex` (number)
|
||||
+ `flexBasis`
|
||||
+ `flexDirection`
|
||||
+ `flexGrow`
|
||||
+ `flexShrink`
|
||||
+ `flexWrap`
|
||||
+ `gridAutoColumns` ‡
|
||||
+ `gridAutoFlow` ‡
|
||||
+ `gridAutoRows` ‡
|
||||
+ `gridColumnEnd` ‡
|
||||
+ `gridColumnGap` ‡
|
||||
+ `gridColumnStart` ‡
|
||||
+ `gridRowEnd` ‡
|
||||
+ `gridRowGap` ‡
|
||||
+ `gridRowStart` ‡
|
||||
+ `gridTemplateColumns` ‡
|
||||
+ `gridTemplateRows` ‡
|
||||
+ `gridTemplateAreas` ‡
|
||||
+ `height`
|
||||
+ `justifyContent`
|
||||
+ `left`
|
||||
@@ -175,6 +227,7 @@ from `style`.
|
||||
+ `opacity`
|
||||
+ `order`
|
||||
+ `outline` ‡
|
||||
+ `outlineColor` ‡
|
||||
+ `overflow`
|
||||
+ `overflowX` ‡
|
||||
+ `overflowY` ‡
|
||||
@@ -189,6 +242,10 @@ from `style`.
|
||||
+ `perspectiveOrigin` ‡
|
||||
+ `position`
|
||||
+ `right`
|
||||
+ `shadowColor`
|
||||
+ `shadowOffset`
|
||||
+ `shadowOpacity`
|
||||
+ `shadowRadius`
|
||||
+ `top`
|
||||
+ `transform`
|
||||
+ `transformOrigin` ‡
|
||||
@@ -224,7 +281,7 @@ Default:
|
||||
|
||||
(See [facebook/css-layout](https://github.com/facebook/css-layout)).
|
||||
|
||||
**testID**: string
|
||||
**testID**: ?string
|
||||
|
||||
Used to locate this view in end-to-end tests.
|
||||
|
||||
|
||||
@@ -1,21 +1,54 @@
|
||||
# Accessibility
|
||||
|
||||
On the Web, assistive technologies derive useful information about the
|
||||
structure, purpose, and interactivity of apps from their [HTML
|
||||
elements][html-accessibility-url], attributes, and [ARIA in
|
||||
HTML][aria-in-html-url].
|
||||
On the Web, assistive technologies (e.g., VoiceOver, TalkBack screen readers)
|
||||
derive useful information about the structure, purpose, and interactivity of
|
||||
apps from their [HTML elements][html-accessibility-url], attributes, and [ARIA
|
||||
in HTML][aria-in-html-url]. React Native for Web includes APIs designed to
|
||||
provide developers with support for making apps more accessible. The most
|
||||
common and best supported accessibility features of the Web are exposed as the
|
||||
props: `accessible`, `accessibilityLabel`, `accessibilityLiveRegion`,
|
||||
`accessibilityRole`, and `importantForAccessibility`.
|
||||
|
||||
The most common and best supported accessibility features of the Web are
|
||||
exposed as the props: `accessible`, `accessibilityLabel`,
|
||||
`accessibilityLiveRegion`, and `accessibilityRole`.
|
||||
## Accessibility properties
|
||||
|
||||
React Native for Web does not provide a way to directly control the type of the
|
||||
rendered HTML element. The `accessibilityRole` prop is used to infer an
|
||||
[analogous HTML 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).
|
||||
### accessible
|
||||
|
||||
When `true`, indicates that the view is an accessibility element. When a view
|
||||
is an accessibility element, it groups its children into a single focusable
|
||||
component. By default, all touchable elements, buttons, and links are
|
||||
"accessible". Prefer using `accessibilityRole` (e.g., `button`, `link`) to
|
||||
create focusable HTML elements wherever possible. On web, `accessible={true}`
|
||||
is implemented using `tabIndex`.
|
||||
|
||||
### accessibilityLabel
|
||||
|
||||
When a view is marked as `accessible`, it is a good practice to set an
|
||||
`accessibilityLabel` on the view, so that people who use screen readers know
|
||||
what element they have selected. On web, `accessibilityLabel` is implemented
|
||||
using `aria-label`.
|
||||
|
||||
```
|
||||
<TouchableOpacity accessibilityLabel={'Tap me!'} accessible={true} onPress={this._onPress}>
|
||||
<View style={styles.button}>
|
||||
<Text style={styles.buttonText}>Press me!</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
```
|
||||
|
||||
### accessibilityRole
|
||||
|
||||
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 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] 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:
|
||||
|
||||
@@ -25,8 +58,62 @@ For example:
|
||||
* `<Text accessibilityRole='link' href='/' />` => `<a role='link' href='/' />`.
|
||||
* `<View accessibilityRole='main' />` => `<main role='main' />`.
|
||||
|
||||
Other ARIA properties should be set via [direct
|
||||
manipulation](./direct-manipulation.md).
|
||||
In the example below, the `TouchableWithoutFeedback` is announced by screen
|
||||
readers as a native Button.
|
||||
|
||||
```
|
||||
<TouchableWithoutFeedback accessibilityRole="button" onPress={this._onPress}>
|
||||
<View style={styles.button}>
|
||||
<Text style={styles.buttonText}>Press me!</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
### accessibilityLiveRegion
|
||||
|
||||
When components dynamically change we may need to inform the user. The
|
||||
`accessibilityLiveRegion` property serves this purpose and can be set to
|
||||
`none`, `polite` and `assertive`. On web, `accessibilityLiveRegion` is
|
||||
implemented using `aria-live`.
|
||||
|
||||
* `none`: Accessibility services should not announce changes to this view.
|
||||
* `polite`: Accessibility services should announce changes to this view.
|
||||
* `assertive`: Accessibility services should interrupt ongoing speech to immediately announce changes to this view.
|
||||
|
||||
```
|
||||
<TouchableWithoutFeedback onPress={this._addOne}>
|
||||
<View style={styles.embedded}>
|
||||
<Text>Click me</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
|
||||
<Text accessibilityLiveRegion="polite">
|
||||
Clicked {this.state.count} times
|
||||
</Text>
|
||||
```
|
||||
|
||||
In the above example, method `_addOne` changes the `state.count` variable. As
|
||||
soon as an end user clicks the `TouchableWithoutFeedback`, screen readers
|
||||
announce text in the `Text` view because of its
|
||||
`accessibilityLiveRegion="polite"` property.
|
||||
|
||||
### importantForAccessibility
|
||||
|
||||
The `importantForAccessibility` property controls if a view appears in the
|
||||
accessibility tree and if it is reported to accessibility services. On web, a
|
||||
value of `no` will remove a focusable element from the tab flow, and a value of
|
||||
`no-hide-descendants` will also hide the entire subtree from assistive
|
||||
technologies (this is implemented using `aria-hidden`).
|
||||
|
||||
### Other
|
||||
|
||||
Other ARIA properties can be set via [direct
|
||||
manipulation](./direct-manipulation.md) or props (this may change in the
|
||||
future).
|
||||
|
||||
[aria-in-html-url]: https://w3c.github.io/aria-in-html/
|
||||
[html-accessibility-url]: http://www.html5accessibility.com/
|
||||
|
||||
104
docs/guides/advanced.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# 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`.
|
||||
203
docs/guides/getting-started.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# 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](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.
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
// This is needed for webpack to compile JavaScript.
|
||||
// Many OSS React Native packages are not compiled to ES5 before being
|
||||
// published. If you depend on uncompiled packages they may cause webpack build
|
||||
// errors. To fix this webpack can be configured to compile to the necessary
|
||||
// `node_module`.
|
||||
const babelLoaderConfiguration = {
|
||||
test: /\.js$/,
|
||||
// Add every directory that needs to be compiled by Babel during the build
|
||||
include: [
|
||||
path.resolve(__dirname, 'src'),
|
||||
path.resolve(__dirname, 'node_modules/react-native-uncompiled')
|
||||
],
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
// The 'react-native' preset is recommended
|
||||
presets: ['react-native']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This is needed for webpack to import static images in JavaScript files
|
||||
const imageLoaderConfiguration = {
|
||||
test: /\.(gif|jpe?g|png|svg)$/,
|
||||
use: {
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
name: '[name].[ext]'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
// ...the rest of your config
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
babelLoaderConfiguration,
|
||||
imageLoaderConfiguration
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// `process.env.NODE_ENV === 'production'` must be `true` for production
|
||||
// builds to eliminate development checks and reduce build size.
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
})
|
||||
],
|
||||
|
||||
resolve: {
|
||||
// Maps the 'react-native' import to 'react-native-web'.
|
||||
alias: {
|
||||
'react-native': 'react-native-web'
|
||||
},
|
||||
// If you're working on a multi-platform React Native app, web-specific
|
||||
// module implementations should be written in files using the extension
|
||||
// `.web.js`.
|
||||
extensions: [ '.web.js', '.js' ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to the Webpack documentation for more information.
|
||||
|
||||
## Jest
|
||||
|
||||
[Jest](https://facebook.github.io/jest/) also needs to map `react-native` to `react-native-web`.
|
||||
|
||||
```
|
||||
"jest": {
|
||||
"moduleNameMapper": {
|
||||
"react-native": "<rootDir>/node_modules/react-native-web"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to the Jest documentation for more information.
|
||||
|
||||
## Web-specific code
|
||||
|
||||
Minor platform differences can use the `Platform` module.
|
||||
|
||||
```js
|
||||
import { AppRegistry, Platform } from 'react-native'
|
||||
|
||||
AppRegistry.registerComponent('MyApp', () => MyApp)
|
||||
|
||||
if (Platform.OS === 'web') {
|
||||
AppRegistry.runApplication('MyApp', {
|
||||
rootTag: document.getElementById('react-root')
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
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`:
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactNative from 'react-native'
|
||||
|
||||
// component that renders the app
|
||||
const AppHeaderContainer = (props) => { /* ... */ }
|
||||
|
||||
ReactNative.render(<AppHeaderContainer />, document.getElementById('react-app-header'))
|
||||
```
|
||||
|
||||
Rendering using `AppRegistry`:
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactNative, { AppRegistry } from 'react-native'
|
||||
|
||||
// component that renders the app
|
||||
const AppContainer = (props) => { /* ... */ }
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerComponent('App', () => AppContainer)
|
||||
|
||||
AppRegistry.runApplication('App', {
|
||||
initialProps: {},
|
||||
rootTag: document.getElementById('react-app')
|
||||
})
|
||||
```
|
||||
|
||||
Rendering within `ReactDOM.render` also works when introducing
|
||||
`react-native-web` to an existing web app, but otherwise it is not recommended.
|
||||
|
||||
## Server-side rendering
|
||||
|
||||
Rendering using the `AppRegistry`:
|
||||
|
||||
```js
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import ReactNative, { AppRegistry } from 'react-native'
|
||||
|
||||
// component that renders the app
|
||||
const AppContainer = (props) => { /* ... */ }
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerComponent('App', () => AppContainer)
|
||||
|
||||
// prerender the app
|
||||
const { element, stylesheet } = AppRegistry.getApplication('App', { initialProps });
|
||||
const initialHTML = ReactDOMServer.renderToString(element);
|
||||
|
||||
// construct HTML document
|
||||
const document = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
${stylesheet}
|
||||
</head>
|
||||
<body>
|
||||
${initialHTML}
|
||||
`
|
||||
```
|
||||
@@ -1,10 +1,18 @@
|
||||
# Known issues
|
||||
|
||||
## Missing modules and Views
|
||||
## Safari flexbox performance
|
||||
|
||||
This is an initial release of React Native for Web, therefore, not all of the
|
||||
views present on iOS/Android are released on Web. We are very much interested in
|
||||
the community's feedback on the next set of modules and views.
|
||||
Safari version prior to 10.1 can suffer from extremely [poor flexbox
|
||||
performance](https://bugs.webkit.org/show_bug.cgi?id=150445). The recommended
|
||||
way to work around this issue (as used on mobile.twitter.com) is to set
|
||||
`display:block` on Views in your element hierarchy that you know don't need
|
||||
flexbox layout.
|
||||
|
||||
## Missing modules and components
|
||||
|
||||
Not all of the views present on iOS/Android are currently available on Web. We
|
||||
are very much interested in the community's feedback on the next set of modules
|
||||
and views.
|
||||
|
||||
Not all the modules or views for iOS/Android can be implemented on Web. In some
|
||||
cases it will be necessary to use a Web counterpart or to guard the use of a
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
# React Native
|
||||
|
||||
Use a module loader that supports package aliases (e.g., webpack), and alias
|
||||
`react-native` to `react-native-web`.
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-native': 'react-native-web'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Image assets
|
||||
|
||||
In order to require image assets (e.g. `require('assets/myimage.png')`), add
|
||||
the `url-loader` to the webpack config:
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.(gif|jpe?g|png|svg)$/,
|
||||
loader: 'url-loader',
|
||||
query: { name: '[name].[hash:16].[ext]' }
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
Many OSS React Native packages are not compiled to ES5 before being published.
|
||||
This can result in webpack build errors. To avoid this issue you should
|
||||
configure webpack (or your bundler of choice) to run
|
||||
`babel-preset-react-native` over the necessary `node_module`. For example:
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
// transpile to ES5
|
||||
test: /\.jsx?$/,
|
||||
include: [
|
||||
path.resolve(__dirname, 'src'),
|
||||
path.resolve(__dirname, 'node_modules/react-native-something')
|
||||
],
|
||||
loader: 'babel-loader',
|
||||
query: { cacheDirectory: true }
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Please refer to the webpack documentation for more information.
|
||||
|
||||
## Web-specific code
|
||||
|
||||
Minor platform differences can use the `Platform` module.
|
||||
|
||||
```js
|
||||
import { AppRegistry, Platform } from 'react-native'
|
||||
|
||||
AppRegistry.registerComponent('MyApp', () => MyApp)
|
||||
|
||||
if (Platform.OS === 'web') {
|
||||
AppRegistry.runApplication('MyApp', {
|
||||
rootTag: document.getElementById('react-root')
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
More substantial Web-specific implementation code should be written in files
|
||||
with the extension `.web.js`. Webpack@1 will automatically resolve these files.
|
||||
Webpack@2 requires additional configuration.
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...
|
||||
resolve: {
|
||||
extensions: [ '.web.js', '.js' ]
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Optimizations
|
||||
|
||||
Production builds can benefit from dead-code elimination by defining the
|
||||
following variables:
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,89 +0,0 @@
|
||||
# Client and Server rendering
|
||||
|
||||
It's recommended that you use a module loader that supports package aliases
|
||||
(e.g., webpack), and alias `react-native` to `react-native-web`.
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...other configuration
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-native': 'react-native-web'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `react-native-web` package also includes a `core` module that exports a
|
||||
subset of modules: `ReactNative`, `I18nManager`, `Platform`, `StyleSheet`,
|
||||
`Image`, `Text`, `TextInput`, `Touchable`, and `View`.
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...other configuration
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-native': 'react-native-web/core'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Client-side rendering
|
||||
|
||||
Rendering without using the `AppRegistry`:
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactNative from 'react-native'
|
||||
|
||||
// component that renders the app
|
||||
const AppHeaderContainer = (props) => { /* ... */ }
|
||||
|
||||
ReactNative.render(<AppHeaderContainer />, document.getElementById('react-app-header'))
|
||||
```
|
||||
|
||||
Rendering using the `AppRegistry`:
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactNative, { AppRegistry } from 'react-native'
|
||||
|
||||
// component that renders the app
|
||||
const AppContainer = (props) => { /* ... */ }
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerComponent('App', () => AppContainer)
|
||||
|
||||
AppRegistry.runApplication('App', {
|
||||
initialProps: {},
|
||||
rootTag: document.getElementById('react-app')
|
||||
})
|
||||
```
|
||||
|
||||
Setting `process.env.__REACT_NATIVE_DEBUG_ENABLED__` to `true` will expose some
|
||||
debugging logs. This can help track down when you're rendering without the
|
||||
performance benefit of cached styles.
|
||||
|
||||
## Server-side rendering
|
||||
|
||||
Rendering using the `AppRegistry`:
|
||||
|
||||
```js
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import ReactNative, { AppRegistry } from 'react-native'
|
||||
|
||||
// component that renders the app
|
||||
const AppContainer = (props) => { /* ... */ }
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerComponent('App', () => AppContainer)
|
||||
|
||||
// prerender the app
|
||||
const { element, stylesheet } = AppRegistry.getApplication('App', { initialProps });
|
||||
const initialHTML = ReactDOMServer.renderToString(element);
|
||||
```
|
||||
@@ -1,73 +1,90 @@
|
||||
# Style
|
||||
|
||||
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):
|
||||
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):
|
||||
|
||||
1. Global namespace
|
||||
2. Dependency hell
|
||||
1. No local variables
|
||||
2. Implicit dependencies
|
||||
3. No dead code elimination
|
||||
4. No code minification
|
||||
5. No sharing of constants
|
||||
6. Non-deterministic resolution
|
||||
7. Lack of isolation
|
||||
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
|
||||
|
||||
## Defining styles
|
||||
|
||||
Styles should be defined outside of the component:
|
||||
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.
|
||||
|
||||
```js
|
||||
class Example extends React.Component {}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
heading: {
|
||||
color: 'gray',
|
||||
fontSize: '2rem'
|
||||
},
|
||||
text: {
|
||||
color: 'gray',
|
||||
fontSize: '1.25rem'
|
||||
marginTop: '1rem',
|
||||
margin: 10
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
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.
|
||||
See the `style` documentation of individual components for supported properties.
|
||||
|
||||
## Using styles
|
||||
|
||||
All the React Native components accept a `style` attribute.
|
||||
All the React Native components accept a `style` property. The value can be a
|
||||
registered object, a plain object, or an array.
|
||||
|
||||
```js
|
||||
<Text style={styles.text} />
|
||||
// registered object
|
||||
<View style={styles.view} />
|
||||
|
||||
// plain object
|
||||
<View style={{ transform: [ { translateX } ] }} />
|
||||
|
||||
// array of registered or plain objects
|
||||
<View style={[ styles.container, this.props.style ]} />
|
||||
```
|
||||
|
||||
A common pattern is to conditionally add style based on a condition:
|
||||
The array syntax will merge styles from left-to-right as normal JavaScript
|
||||
objects, and can be used to conditionally apply styles:
|
||||
|
||||
```js
|
||||
// either
|
||||
<View style={[
|
||||
styles.base,
|
||||
styles.container,
|
||||
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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```js
|
||||
class List extends React.Component {
|
||||
static propTypes = {
|
||||
style: View.propTypes.style,
|
||||
elementStyle: View.propTypes.style,
|
||||
style: ViewPropTypes.style,
|
||||
elementStyle: ViewPropTypes.style,
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -90,56 +107,125 @@ 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:
|
||||
of style props in the component's API, and control when they are applied.
|
||||
|
||||
```js
|
||||
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
|
||||
})
|
||||
}
|
||||
## How styles are resolved
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View
|
||||
children={children}
|
||||
style={[
|
||||
this.props.style,
|
||||
// override border-color when scrolling
|
||||
isScrolling && { borderColor: 'transparent' }
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
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>
|
||||
```
|
||||
|
||||
## Media Queries
|
||||
But in React Native the most *specific* style property takes precedence,
|
||||
resulting in margins of `10, 0, 20, 0`.
|
||||
|
||||
```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
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
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?
|
||||
|
||||
`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.
|
||||
|
||||
There are various React libraries wrapping JavaScript Media Query API's, e.g.,
|
||||
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),
|
||||
[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). This has the
|
||||
benefit of co-locating breakpoint-specific DOM and style changes.
|
||||
[react-responsive](https://github.com/contra/react-responsive).
|
||||
|
||||
## Pseudo-classes and pseudo-elements
|
||||
### What about 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.
|
||||
|
||||
### Reset
|
||||
### Do I need a CSS reset?
|
||||
|
||||
You **do not** need to include a CSS reset or
|
||||
[normalize.css](https://necolas.github.io/normalize.css/).
|
||||
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.
|
||||
|
||||
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`).
|
||||
### What about using DevTools?
|
||||
|
||||
It's recommended that you rely more on React DevTools and live/hot-reloading
|
||||
rather than inspecting and editing the DOM directly.
|
||||
|
||||
BIN
docs/static/components.png
vendored
|
Before Width: | Height: | Size: 12 KiB |
BIN
docs/static/styling-strategy.png
vendored
|
Before Width: | Height: | Size: 38 KiB |
12
docs/storybook/.storybook/config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { configure, addDecorator } from '@kadira/storybook';
|
||||
import centered from './decorator-centered';
|
||||
|
||||
const context = require.context('../', true, /Example\.js$/);
|
||||
|
||||
addDecorator(centered);
|
||||
|
||||
function loadStories() {
|
||||
context.keys().forEach(context);
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
@@ -9,9 +9,9 @@ const styles = StyleSheet.create({
|
||||
}
|
||||
});
|
||||
|
||||
export default function (renderStory) {
|
||||
export default function(renderStory) {
|
||||
return (
|
||||
<View style={[ StyleSheet.absoluteFill, styles.root ]}>
|
||||
<View style={[StyleSheet.absoluteFill, styles.root]}>
|
||||
{renderStory()}
|
||||
</View>
|
||||
);
|
||||
@@ -1,5 +1,5 @@
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
const DEV = process.env.NODE_ENV !== 'production';
|
||||
|
||||
@@ -23,12 +23,11 @@ module.exports = {
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
|
||||
'process.env.__REACT_NATIVE_DEBUG_ENABLED__': DEV
|
||||
}),
|
||||
new webpack.optimize.OccurenceOrderPlugin()
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-native': path.join(__dirname, '../../src')
|
||||
'react-native': path.join(__dirname, '../../../src/module')
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Clipboard, Text, TextInput, View } from 'react-native'
|
||||
import { Clipboard, Text, TextInput, View } from 'react-native';
|
||||
import React, { Component } from 'react';
|
||||
import { action, storiesOf } from '@kadira/storybook';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
|
||||
class ClipboardExample extends Component {
|
||||
render() {
|
||||
@@ -12,13 +12,17 @@ class ClipboardExample extends Component {
|
||||
placeholder={'Try pasting here afterwards'}
|
||||
style={{ borderWidth: 1, height: 200, marginVertical: 20 }}
|
||||
/>
|
||||
<Text onPress={this._handleGet}>(Clipboard.getString returns a Promise that always resolves to an empty string on web)</Text>
|
||||
<Text onPress={this._handleGet}>
|
||||
(Clipboard.getString returns a Promise that always resolves to an empty string on web)
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
_handleGet() {
|
||||
Clipboard.getString().then((value) => { console.log(`Clipboard value: ${value}`) });
|
||||
Clipboard.getString().then(value => {
|
||||
console.log(`Clipboard value: ${value}`);
|
||||
});
|
||||
}
|
||||
|
||||
_handleSet() {
|
||||
@@ -27,7 +31,4 @@ class ClipboardExample extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
storiesOf('api: Clipboard', module)
|
||||
.add('setString', () => (
|
||||
<ClipboardExample />
|
||||
));
|
||||
storiesOf('api: Clipboard', module).add('setString', () => <ClipboardExample />);
|
||||
@@ -1,50 +1,50 @@
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import { I18nManager, StyleSheet, TouchableHighlight, Text, View } from 'react-native'
|
||||
import { I18nManager, StyleSheet, TouchableHighlight, Text, View } from 'react-native';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class I18nManagerExample extends Component {
|
||||
componentWillUnmount() {
|
||||
I18nManager.setPreferredLanguageRTL(false)
|
||||
I18nManager.setPreferredLanguageRTL(false);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text accessibilityRole='heading' style={styles.welcome}>
|
||||
<Text accessibilityRole="heading" style={styles.welcome}>
|
||||
LTR/RTL layout example!
|
||||
</Text>
|
||||
<Text style={styles.text}>
|
||||
The writing direction of text is automatically determined by the browser, independent of the global writing direction of the app.
|
||||
</Text>
|
||||
<Text style={[ styles.text, styles.rtlText ]}>
|
||||
<Text style={[styles.text, styles.rtlText]}>
|
||||
أحب اللغة العربية
|
||||
</Text>
|
||||
<Text style={[ styles.text, styles.textAlign ]}>
|
||||
<Text style={[styles.text, styles.textAlign]}>
|
||||
textAlign toggles
|
||||
</Text>
|
||||
<View style={styles.horizontal}>
|
||||
<View style={[ styles.box, { backgroundColor: 'lightblue' } ]}>
|
||||
<View style={[styles.box, { backgroundColor: 'lightblue' }]}>
|
||||
<Text>One</Text>
|
||||
</View>
|
||||
<View style={[ styles.box ]}>
|
||||
<View style={[styles.box]}>
|
||||
<Text>Two</Text>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableHighlight
|
||||
onPress={this._handleToggle}
|
||||
style={styles.toggle}
|
||||
underlayColor='rgba(0,0,0,0.25)'
|
||||
underlayColor="rgba(0,0,0,0.25)"
|
||||
>
|
||||
<Text>Toggle LTR/RTL</Text>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
_handleToggle = () => {
|
||||
I18nManager.setPreferredLanguageRTL(!I18nManager.isRTL)
|
||||
I18nManager.setPreferredLanguageRTL(!I18nManager.isRTL);
|
||||
this.forceUpdate();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@@ -82,9 +82,6 @@ const styles = StyleSheet.create({
|
||||
marginTop: 10,
|
||||
padding: 10
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
storiesOf('api: I18nManager', module)
|
||||
.add('RTL layout', () => (
|
||||
<I18nManagerExample />
|
||||
))
|
||||
storiesOf('api: I18nManager', module).add('RTL layout', () => <I18nManagerExample />);
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Linking, StyleSheet, Text, View } from 'react-native'
|
||||
import { Linking, StyleSheet, Text, View } from 'react-native';
|
||||
import React, { Component } from 'react';
|
||||
import { storiesOf, action } from '@kadira/storybook';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
|
||||
const url = 'https://mathiasbynens.github.io/rel-noopener/malicious.html';
|
||||
|
||||
class LinkingExample extends Component {
|
||||
handlePress() {
|
||||
Linking.canOpenURL(url).then((supported) => {
|
||||
Linking.canOpenURL(url).then(supported => {
|
||||
return Linking.openURL(url);
|
||||
});
|
||||
}
|
||||
@@ -17,7 +17,12 @@ class LinkingExample extends Component {
|
||||
<Text onPress={this.handlePress} style={styles.text}>
|
||||
Linking.openURL (Expect: "The previous tab is safe and intact")
|
||||
</Text>
|
||||
<Text accessibilityRole='link' href='https://mathiasbynens.github.io/rel-noopener/malicious.html' style={styles.text} target='_blank'>
|
||||
<Text
|
||||
accessibilityRole="link"
|
||||
href="https://mathiasbynens.github.io/rel-noopener/malicious.html"
|
||||
style={styles.text}
|
||||
target="_blank"
|
||||
>
|
||||
target="_blank" (Expect: "The previous tab is safe and intact")
|
||||
</Text>
|
||||
</View>
|
||||
@@ -31,7 +36,4 @@ const styles = StyleSheet.create({
|
||||
}
|
||||
});
|
||||
|
||||
storiesOf('api: Linking', module)
|
||||
.add('Safe linking', () => (
|
||||
<LinkingExample />
|
||||
));
|
||||
storiesOf('api: Linking', module).add('Safe linking', () => <LinkingExample />);
|
||||
@@ -1,23 +1,18 @@
|
||||
'use strict';
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
|
||||
import { storiesOf, action } from '@kadira/storybook';
|
||||
import createReactClass from 'create-react-class';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import { PanResponder, StyleSheet, View } from 'react-native';
|
||||
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
PanResponder,
|
||||
StyleSheet,
|
||||
View
|
||||
} = ReactNative;
|
||||
const CIRCLE_SIZE = 80;
|
||||
|
||||
var CIRCLE_SIZE = 80;
|
||||
|
||||
var PanResponderExample = React.createClass({
|
||||
const PanResponderExample = createReactClass({
|
||||
_panResponder: {},
|
||||
_previousLeft: 0,
|
||||
_previousTop: 0,
|
||||
_circleStyles: {},
|
||||
circle: (null : ?{ setNativeProps(props: Object): void }),
|
||||
circle: (null: ?{ setNativeProps(props: Object): void }),
|
||||
|
||||
componentWillMount: function() {
|
||||
this._panResponder = PanResponder.create({
|
||||
@@ -26,7 +21,7 @@ var PanResponderExample = React.createClass({
|
||||
onPanResponderGrant: this._handlePanResponderGrant,
|
||||
onPanResponderMove: this._handlePanResponderMove,
|
||||
onPanResponderRelease: this._handlePanResponderEnd,
|
||||
onPanResponderTerminate: this._handlePanResponderEnd,
|
||||
onPanResponderTerminate: this._handlePanResponderEnd
|
||||
});
|
||||
this._previousLeft = 20;
|
||||
this._previousTop = 84;
|
||||
@@ -34,7 +29,7 @@ var PanResponderExample = React.createClass({
|
||||
style: {
|
||||
left: this._previousLeft,
|
||||
top: this._previousTop,
|
||||
backgroundColor: 'green',
|
||||
backgroundColor: 'green'
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -45,10 +40,9 @@ var PanResponderExample = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<View
|
||||
style={styles.container}>
|
||||
<View style={styles.container}>
|
||||
<View
|
||||
ref={(circle) => {
|
||||
ref={circle => {
|
||||
this.circle = circle;
|
||||
}}
|
||||
style={styles.circle}
|
||||
@@ -94,24 +88,21 @@ var PanResponderExample = React.createClass({
|
||||
this._unHighlight();
|
||||
this._previousLeft += gestureState.dx;
|
||||
this._previousTop += gestureState.dy;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
const styles = StyleSheet.create({
|
||||
circle: {
|
||||
width: CIRCLE_SIZE,
|
||||
height: CIRCLE_SIZE,
|
||||
borderRadius: CIRCLE_SIZE / 2,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
top: 0
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingTop: 64,
|
||||
},
|
||||
paddingTop: 64
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
storiesOf('api: PanResponder', module)
|
||||
.add('example', () => <PanResponderExample />)
|
||||
storiesOf('api: PanResponder', module).add('example', () => <PanResponderExample />);
|
||||
@@ -1,8 +1,3 @@
|
||||
import React from 'react';
|
||||
import { storiesOf, action } from '@kadira/storybook';
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native'
|
||||
import TimerMixin from 'react-timer-mixin';
|
||||
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
@@ -26,18 +21,24 @@ import TimerMixin from 'react-timer-mixin';
|
||||
* @flow
|
||||
*/
|
||||
|
||||
const ToggleAnimatingActivityIndicator = React.createClass({
|
||||
import createReactClass from 'create-react-class';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||
import TimerMixin from 'react-timer-mixin';
|
||||
|
||||
const ToggleAnimatingActivityIndicator = createReactClass({
|
||||
mixins: [TimerMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
animating: true,
|
||||
animating: true
|
||||
};
|
||||
},
|
||||
|
||||
setToggleTimeout() {
|
||||
this.setTimeout(() => {
|
||||
this.setState({animating: !this.state.animating});
|
||||
this.setState({ animating: !this.state.animating });
|
||||
this.setToggleTimeout();
|
||||
}, 2000);
|
||||
},
|
||||
@@ -50,9 +51,9 @@ const ToggleAnimatingActivityIndicator = React.createClass({
|
||||
return (
|
||||
<ActivityIndicator
|
||||
animating={this.state.animating}
|
||||
style={styles.centering}
|
||||
hidesWhenStopped={this.props.hidesWhenStopped}
|
||||
size="large"
|
||||
style={styles.centering}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -62,11 +63,7 @@ const examples = [
|
||||
{
|
||||
title: 'Default',
|
||||
render() {
|
||||
return (
|
||||
<ActivityIndicator
|
||||
style={[styles.centering]}
|
||||
/>
|
||||
);
|
||||
return <ActivityIndicator style={[styles.centering]} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -86,11 +83,7 @@ const examples = [
|
||||
title: 'Large',
|
||||
render() {
|
||||
return (
|
||||
<ActivityIndicator
|
||||
style={[styles.centering, styles.gray]}
|
||||
color="white"
|
||||
size="large"
|
||||
/>
|
||||
<ActivityIndicator color="white" size="large" style={[styles.centering, styles.gray]} />
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -99,22 +92,10 @@ const examples = [
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<ActivityIndicator
|
||||
size="large"
|
||||
color="#0000ff"
|
||||
/>
|
||||
<ActivityIndicator
|
||||
size="large"
|
||||
color="#aa00aa"
|
||||
/>
|
||||
<ActivityIndicator
|
||||
size="large"
|
||||
color="#aa3300"
|
||||
/>
|
||||
<ActivityIndicator
|
||||
size="large"
|
||||
color="#00aa00"
|
||||
/>
|
||||
<ActivityIndicator color="#0000ff" size="large" />
|
||||
<ActivityIndicator color="#aa00aa" size="large" />
|
||||
<ActivityIndicator color="#aa3300" size="large" />
|
||||
<ActivityIndicator color="#00aa00" size="large" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -136,33 +117,29 @@ const examples = [
|
||||
return (
|
||||
<View style={[styles.horizontal, styles.centering]}>
|
||||
<ActivityIndicator size={40} />
|
||||
<ActivityIndicator
|
||||
style={{ marginLeft: 20, transform: [ {scale: 1.5} ] }}
|
||||
size="large"
|
||||
/>
|
||||
<ActivityIndicator size="large" style={{ marginLeft: 20, transform: [{ scale: 1.5 }] }} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
centering: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 8,
|
||||
padding: 8
|
||||
},
|
||||
gray: {
|
||||
backgroundColor: '#cccccc',
|
||||
backgroundColor: '#cccccc'
|
||||
},
|
||||
horizontal: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-around',
|
||||
padding: 8,
|
||||
},
|
||||
padding: 8
|
||||
}
|
||||
});
|
||||
|
||||
examples.forEach((example) => {
|
||||
storiesOf('component: ActivityIndicator', module)
|
||||
.add(example.title, () => example.render())
|
||||
})
|
||||
examples.forEach(example => {
|
||||
storiesOf('component: ActivityIndicator', module).add(example.title, () => example.render());
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { action, storiesOf } from '@kadira/storybook';
|
||||
import { Button, StyleSheet, View } from 'react-native';
|
||||
import { Button, View } from 'react-native';
|
||||
|
||||
const onButtonPress = action('Button has been pressed!');
|
||||
|
||||
@@ -13,12 +13,12 @@ const examples = [
|
||||
render: function() {
|
||||
return (
|
||||
<Button
|
||||
accessibilityLabel="See an informative alert"
|
||||
onPress={onButtonPress}
|
||||
title="Press Me"
|
||||
accessibilityLabel="See an informative alert"
|
||||
/>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Adjusted color',
|
||||
@@ -28,35 +28,34 @@ const examples = [
|
||||
render: function() {
|
||||
return (
|
||||
<Button
|
||||
accessibilityLabel="Learn more about purple"
|
||||
color="#841584"
|
||||
onPress={onButtonPress}
|
||||
title="Press Purple"
|
||||
color="#841584"
|
||||
accessibilityLabel="Learn more about purple"
|
||||
/>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Fit to text layout',
|
||||
description: 'This layout strategy lets the title define the width of ' +
|
||||
'the button',
|
||||
description: 'This layout strategy lets the title define the width of the button',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
||||
<Button
|
||||
accessibilityLabel="This sounds great!"
|
||||
onPress={onButtonPress}
|
||||
title="This looks great!"
|
||||
accessibilityLabel="This sounds great!"
|
||||
/>
|
||||
<Button
|
||||
accessibilityLabel="Ok, Great!"
|
||||
color="#841584"
|
||||
onPress={onButtonPress}
|
||||
title="Ok!"
|
||||
color="#841584"
|
||||
accessibilityLabel="Ok, Great!"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Disabled Button',
|
||||
@@ -64,17 +63,16 @@ const examples = [
|
||||
render: function() {
|
||||
return (
|
||||
<Button
|
||||
accessibilityLabel="See an informative alert"
|
||||
disabled
|
||||
onPress={onButtonPress}
|
||||
title="I Am Disabled"
|
||||
accessibilityLabel="See an informative alert"
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
examples.forEach((example) => {
|
||||
storiesOf('component: Button', module)
|
||||
.add(example.title, () => example.render());
|
||||
examples.forEach(example => {
|
||||
storiesOf('component: Button', module).add(example.title, () => example.render());
|
||||
});
|
||||
@@ -1,6 +1,4 @@
|
||||
import React from 'react';
|
||||
import { storiesOf, action, addDecorator } from '@kadira/storybook';
|
||||
import { ActivityIndicator, Image, Platform, StyleSheet, Text, View } from 'react-native'
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
@@ -25,56 +23,69 @@ import { ActivityIndicator, Image, Platform, StyleSheet, Text, View } from 'reac
|
||||
* @flow
|
||||
*/
|
||||
|
||||
var base64Icon = '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==';
|
||||
import createReactClass from 'create-react-class';
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import { ActivityIndicator, Image, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const base64Icon =
|
||||
'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==';
|
||||
|
||||
//var ImageCapInsetsExample = require('./ImageCapInsetsExample');
|
||||
const IMAGE_PREFETCH_URL = 'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now();
|
||||
var prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL);
|
||||
const prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL);
|
||||
|
||||
var NetworkImageCallbackExample = React.createClass({
|
||||
const NetworkImageCallbackExample = createReactClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
events: [],
|
||||
startLoadPrefetched: false,
|
||||
mountTime: new Date(),
|
||||
mountTime: new Date()
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
this.setState({mountTime: new Date()});
|
||||
this.setState({ mountTime: new Date() });
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var { mountTime } = this.state;
|
||||
const { mountTime } = this.state;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Image
|
||||
source={this.props.source}
|
||||
style={[styles.base, {overflow: 'visible'}]}
|
||||
onLoadStart={() => this._loadEventFired(`✔ onLoadStart (+${new Date() - mountTime}ms)`)}
|
||||
onLoad={() => this._loadEventFired(`✔ onLoad (+${new Date() - mountTime}ms)`)}
|
||||
onLoadEnd={() => {
|
||||
this._loadEventFired(`✔ onLoadEnd (+${new Date() - mountTime}ms)`);
|
||||
this.setState({startLoadPrefetched: true}, () => {
|
||||
prefetchTask.then(() => {
|
||||
this._loadEventFired(`✔ Prefetch OK (+${new Date() - mountTime}ms)`);
|
||||
}, error => {
|
||||
this._loadEventFired(`✘ Prefetch failed (+${new Date() - mountTime}ms)`);
|
||||
});
|
||||
this.setState({ startLoadPrefetched: true }, () => {
|
||||
prefetchTask.then(
|
||||
() => {
|
||||
this._loadEventFired(`✔ Prefetch OK (+${new Date() - mountTime}ms)`);
|
||||
},
|
||||
error => {
|
||||
this._loadEventFired(`✘ Prefetch failed (+${new Date() - mountTime}ms)`);
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
}}
|
||||
onLoadStart={() => this._loadEventFired(`✔ onLoadStart (+${new Date() - mountTime}ms)`)}
|
||||
source={this.props.source}
|
||||
style={[styles.base, { overflow: 'visible' }]}
|
||||
/>
|
||||
{this.state.startLoadPrefetched ?
|
||||
<Image
|
||||
source={this.props.prefetchedSource}
|
||||
style={[styles.base, {overflow: 'visible'}]}
|
||||
onLoadStart={() => this._loadEventFired(`✔ (prefetched) onLoadStart (+${new Date() - mountTime}ms)`)}
|
||||
onLoad={() => this._loadEventFired(`✔ (prefetched) onLoad (+${new Date() - mountTime}ms)`)}
|
||||
onLoadEnd={() => this._loadEventFired(`✔ (prefetched) onLoadEnd (+${new Date() - mountTime}ms)`)}
|
||||
/>
|
||||
{this.state.startLoadPrefetched
|
||||
? <Image
|
||||
onLoad={() =>
|
||||
this._loadEventFired(`✔ (prefetched) onLoad (+${new Date() - mountTime}ms)`)}
|
||||
onLoadEnd={() =>
|
||||
this._loadEventFired(`✔ (prefetched) onLoadEnd (+${new Date() - mountTime}ms)`)}
|
||||
onLoadStart={() =>
|
||||
this._loadEventFired(`✔ (prefetched) onLoadStart (+${new Date() - mountTime}ms)`)}
|
||||
source={this.props.prefetchedSource}
|
||||
style={[styles.base, { overflow: 'visible' }]}
|
||||
/>
|
||||
: null}
|
||||
<Text style={{marginTop: 20}}>
|
||||
<Text style={{ marginTop: 20 }}>
|
||||
{this.state.events.join('\n')}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -82,13 +93,13 @@ var NetworkImageCallbackExample = React.createClass({
|
||||
},
|
||||
|
||||
_loadEventFired(event) {
|
||||
this.setState((state) => {
|
||||
return state.events = [...state.events, event];
|
||||
this.setState(state => {
|
||||
return (state.events = [...state.events, event]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var NetworkImageExample = React.createClass({
|
||||
const NetworkImageExample = createReactClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
error: false,
|
||||
@@ -97,35 +108,40 @@ var NetworkImageExample = React.createClass({
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
var loader = this.state.loading ?
|
||||
<View style={styles.progress}>
|
||||
<Text>{this.state.progress}%</Text>
|
||||
<ActivityIndicator style={{marginLeft:5}} />
|
||||
</View> : null;
|
||||
return this.state.error ?
|
||||
<Text>{this.state.error}</Text> :
|
||||
<Image
|
||||
source={this.props.source}
|
||||
style={[styles.base, {overflow: 'visible'}]}
|
||||
onLoadStart={(e) => this.setState({loading: true})}
|
||||
onError={(e) => this.setState({error: e.nativeEvent.error, loading: false})}
|
||||
onProgress={(e) => this.setState({progress: Math.round(100 * e.nativeEvent.loaded / e.nativeEvent.total)})}
|
||||
onLoad={() => this.setState({loading: false, error: false})}>
|
||||
{loader}
|
||||
</Image>;
|
||||
const loader = this.state.loading
|
||||
? <View style={styles.progress}>
|
||||
<Text>{this.state.progress}%</Text>
|
||||
<ActivityIndicator style={{ marginLeft: 5 }} />
|
||||
</View>
|
||||
: null;
|
||||
return this.state.error
|
||||
? <Text>{this.state.error}</Text>
|
||||
: <Image
|
||||
onError={e => this.setState({ error: e.nativeEvent.error, loading: false })}
|
||||
onLoad={() => this.setState({ loading: false, error: false })}
|
||||
onLoadStart={e => this.setState({ loading: true })}
|
||||
onProgress={e =>
|
||||
this.setState({
|
||||
progress: Math.round(100 * e.nativeEvent.loaded / e.nativeEvent.total)
|
||||
})}
|
||||
source={this.props.source}
|
||||
style={[styles.base, { overflow: 'visible' }]}
|
||||
>
|
||||
{loader}
|
||||
</Image>;
|
||||
}
|
||||
});
|
||||
|
||||
var ImageSizeExample = React.createClass({
|
||||
const ImageSizeExample = createReactClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
width: 0,
|
||||
height: 0,
|
||||
height: 0
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
Image.getSize(this.props.source.uri, (width, height) => {
|
||||
this.setState({width, height});
|
||||
this.setState({ width, height });
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
@@ -146,11 +162,11 @@ var ImageSizeExample = React.createClass({
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
var MultipleSourcesExample = React.createClass({
|
||||
var MultipleSourcesExample = createReactClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
width: 30,
|
||||
@@ -212,20 +228,24 @@ const examples = [
|
||||
{
|
||||
title: 'Plain Network Image',
|
||||
description: 'If the `source` prop `uri` property is prefixed with ' +
|
||||
'"http", then it will be downloaded from the network.',
|
||||
'"http", then it will be downloaded from the network.',
|
||||
render: function() {
|
||||
return (
|
||||
<Image
|
||||
source={{ uri: 'http://facebook.github.io/react/img/logo_og.png', width: 1200, height: 630 }}
|
||||
source={{
|
||||
uri: 'http://facebook.github.io/react/img/logo_og.png',
|
||||
width: 1200,
|
||||
height: 630
|
||||
}}
|
||||
style={styles.base}
|
||||
/>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Plain Static Image',
|
||||
description: 'Static assets should be placed in the source code tree, and ' +
|
||||
'required in the same way as JavaScript modules.',
|
||||
'required in the same way as JavaScript modules.',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
@@ -235,36 +255,40 @@ const examples = [
|
||||
{/*<Image source={require('./uie_comment_highlighted.png')} style={styles.icon} />*/}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Image Loading Events',
|
||||
render: function() {
|
||||
return (
|
||||
<NetworkImageCallbackExample
|
||||
source={{uri: 'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now()}}
|
||||
prefetchedSource={{uri: IMAGE_PREFETCH_URL}}
|
||||
prefetchedSource={{ uri: IMAGE_PREFETCH_URL }}
|
||||
source={{ uri: 'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now() }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Error Handler',
|
||||
render: function() {
|
||||
return (
|
||||
<NetworkImageExample source={{uri: 'http://TYPO_ERROR_facebook.github.io/react/img/logo_og.png'}} />
|
||||
<NetworkImageExample
|
||||
source={{ uri: 'http://TYPO_ERROR_facebook.github.io/react/img/logo_og.png' }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
platform: 'ios',
|
||||
platform: 'ios'
|
||||
},
|
||||
{
|
||||
title: 'Image Download Progress',
|
||||
render: function() {
|
||||
return (
|
||||
<NetworkImageExample source={{uri: 'http://origami.design/public/images/bird-logo.png?r=1'}}/>
|
||||
<NetworkImageExample
|
||||
source={{ uri: 'http://origami.design/public/images/bird-logo.png?r=1' }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
platform: 'ios',
|
||||
platform: 'ios'
|
||||
},
|
||||
{
|
||||
title: 'defaultSource',
|
||||
@@ -273,12 +297,12 @@ const examples = [
|
||||
return (
|
||||
<Image
|
||||
defaultSource={require('./bunny.png')}
|
||||
source={{uri: 'http://facebook.github.io/origami/public/images/birds.jpg'}}
|
||||
source={{ uri: 'http://facebook.github.io/origami/public/images/birds.jpg' }}
|
||||
style={styles.base}
|
||||
/>
|
||||
);
|
||||
},
|
||||
platform: 'ios',
|
||||
platform: 'ios'
|
||||
},
|
||||
{
|
||||
title: 'Border Color',
|
||||
@@ -287,15 +311,11 @@ const examples = [
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[
|
||||
styles.base,
|
||||
styles.background,
|
||||
{borderWidth: 3, borderColor: '#f099f0'}
|
||||
]}
|
||||
style={[styles.base, styles.background, { borderWidth: 3, borderColor: '#f099f0' }]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Border Width',
|
||||
@@ -304,32 +324,25 @@ const examples = [
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[
|
||||
styles.base,
|
||||
styles.background,
|
||||
{borderWidth: 5, borderColor: '#f099f0'}
|
||||
]}
|
||||
style={[styles.base, styles.background, { borderWidth: 5, borderColor: '#f099f0' }]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Border Radius',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image source={fullImage} style={[styles.base, { borderRadius: 5 }]} />
|
||||
<Image
|
||||
style={[styles.base, {borderRadius: 5}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {borderRadius: 19}]}
|
||||
source={fullImage}
|
||||
style={[styles.base, styles.leftMargin, { borderRadius: 19 }]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Background Color',
|
||||
@@ -338,71 +351,47 @@ const examples = [
|
||||
<View style={styles.horizontal}>
|
||||
<Image source={smallImage} style={styles.base} />
|
||||
<Image
|
||||
style={[
|
||||
styles.base,
|
||||
styles.leftMargin,
|
||||
{backgroundColor: 'rgba(0, 0, 100, 0.25)'}
|
||||
]}
|
||||
source={smallImage}
|
||||
style={[styles.base, styles.leftMargin, { backgroundColor: 'rgba(0, 0, 100, 0.25)' }]}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {backgroundColor: 'red'}]}
|
||||
source={smallImage}
|
||||
style={[styles.base, styles.leftMargin, { backgroundColor: 'red' }]}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {backgroundColor: 'black'}]}
|
||||
source={smallImage}
|
||||
style={[styles.base, styles.leftMargin, { backgroundColor: 'black' }]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Opacity',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
style={[styles.base, {opacity: 1}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.8}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.6}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.4}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.2}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image source={fullImage} style={[styles.base, { opacity: 1 }]} />
|
||||
<Image source={fullImage} style={[styles.base, styles.leftMargin, { opacity: 0.8 }]} />
|
||||
<Image source={fullImage} style={[styles.base, styles.leftMargin, { opacity: 0.6 }]} />
|
||||
<Image source={fullImage} style={[styles.base, styles.leftMargin, { opacity: 0.4 }]} />
|
||||
<Image source={fullImage} style={[styles.base, styles.leftMargin, { opacity: 0.2 }]} />
|
||||
<Image source={fullImage} style={[styles.base, styles.leftMargin, { opacity: 0 }]} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Nesting',
|
||||
render: function() {
|
||||
return (
|
||||
<Image
|
||||
style={{width: 60, height: 60, backgroundColor: 'transparent'}}
|
||||
source={fullImage}>
|
||||
<Image source={fullImage} style={{ width: 60, height: 60, backgroundColor: 'transparent' }}>
|
||||
<Text style={styles.nestedText}>
|
||||
React
|
||||
</Text>
|
||||
</Image>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
/*
|
||||
{
|
||||
@@ -465,91 +454,80 @@ const examples = [
|
||||
<View>
|
||||
{[smallImage, fullImage].map((image, index) => {
|
||||
return (
|
||||
<View key={index}>
|
||||
<View style={styles.horizontal}>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Contain
|
||||
</Text>
|
||||
<Image
|
||||
style={styles.resizeMode}
|
||||
resizeMode={Image.resizeMode.contain}
|
||||
source={image}
|
||||
/>
|
||||
<View key={index}>
|
||||
<View style={styles.horizontal}>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Contain
|
||||
</Text>
|
||||
<Image
|
||||
resizeMode={Image.resizeMode.contain}
|
||||
source={image}
|
||||
style={styles.resizeMode}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Cover
|
||||
</Text>
|
||||
<Image
|
||||
resizeMode={Image.resizeMode.cover}
|
||||
source={image}
|
||||
style={styles.resizeMode}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Cover
|
||||
</Text>
|
||||
<Image
|
||||
style={styles.resizeMode}
|
||||
resizeMode={Image.resizeMode.cover}
|
||||
source={image}
|
||||
/>
|
||||
<View style={styles.horizontal}>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Stretch
|
||||
</Text>
|
||||
<Image
|
||||
resizeMode={Image.resizeMode.stretch}
|
||||
source={image}
|
||||
style={styles.resizeMode}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Repeat
|
||||
</Text>
|
||||
<Image resizeMode={'repeat'} source={image} style={styles.resizeMode} />
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Center
|
||||
</Text>
|
||||
<Image resizeMode={'center'} source={image} style={styles.resizeMode} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.horizontal}>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Stretch
|
||||
</Text>
|
||||
<Image
|
||||
style={styles.resizeMode}
|
||||
resizeMode={Image.resizeMode.stretch}
|
||||
source={image}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Repeat
|
||||
</Text>
|
||||
<Image
|
||||
style={styles.resizeMode}
|
||||
resizeMode={'repeat'}
|
||||
source={image}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Center
|
||||
</Text>
|
||||
<Image
|
||||
style={styles.resizeMode}
|
||||
resizeMode={'center'}
|
||||
source={image}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Animated GIF',
|
||||
render: function() {
|
||||
return (
|
||||
<Image
|
||||
source={{
|
||||
uri: 'http://38.media.tumblr.com/9e9bd08c6e2d10561dd1fb4197df4c4e/tumblr_mfqekpMktw1rn90umo1_500.gif'
|
||||
}}
|
||||
style={styles.gif}
|
||||
source={{uri: 'http://38.media.tumblr.com/9e9bd08c6e2d10561dd1fb4197df4c4e/tumblr_mfqekpMktw1rn90umo1_500.gif'}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
platform: 'ios',
|
||||
platform: 'ios'
|
||||
},
|
||||
{
|
||||
title: 'Base64 image',
|
||||
render: function() {
|
||||
return (
|
||||
<Image
|
||||
style={styles.base64}
|
||||
source={{uri: base64Icon, scale: 3}}
|
||||
/>
|
||||
);
|
||||
return <Image source={{ uri: base64Icon, scale: 3 }} style={styles.base64} />;
|
||||
},
|
||||
platform: 'ios',
|
||||
platform: 'ios'
|
||||
},
|
||||
/*
|
||||
{
|
||||
@@ -568,9 +546,15 @@ const examples = [
|
||||
{
|
||||
title: 'Image Size',
|
||||
render: function() {
|
||||
return <ImageSizeExample source={{ uri: 'https://upload.wikimedia.org/wikipedia/commons/d/d7/Chestnut-mandibled_Toucan.jpg' }} />;
|
||||
},
|
||||
},
|
||||
return (
|
||||
<ImageSizeExample
|
||||
source={{
|
||||
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/d7/Chestnut-mandibled_Toucan.jpg'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
{
|
||||
title: 'MultipleSourcesExample',
|
||||
@@ -585,13 +569,13 @@ const examples = [
|
||||
*/
|
||||
];
|
||||
|
||||
var fullImage = {uri: 'http://facebook.github.io/react/img/logo_og.png'};
|
||||
var smallImage = {uri: 'http://facebook.github.io/react/img/logo_small_2x.png'};
|
||||
const fullImage = { uri: 'http://facebook.github.io/react/img/logo_og.png' };
|
||||
const smallImage = { uri: 'http://facebook.github.io/react/img/logo_small_2x.png' };
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
width: 38,
|
||||
height: 38,
|
||||
height: 38
|
||||
},
|
||||
progress: {
|
||||
flex: 1,
|
||||
@@ -600,13 +584,13 @@ var styles = StyleSheet.create({
|
||||
width: 100
|
||||
},
|
||||
leftMargin: {
|
||||
marginLeft: 10,
|
||||
marginLeft: 10
|
||||
},
|
||||
background: {
|
||||
backgroundColor: '#222222'
|
||||
},
|
||||
sectionText: {
|
||||
marginVertical: 6,
|
||||
marginVertical: 6
|
||||
},
|
||||
nestedText: {
|
||||
marginLeft: 12,
|
||||
@@ -622,32 +606,32 @@ var styles = StyleSheet.create({
|
||||
},
|
||||
resizeModeText: {
|
||||
fontSize: 11,
|
||||
marginBottom: 3,
|
||||
marginBottom: 3
|
||||
},
|
||||
icon: {
|
||||
width: 15,
|
||||
height: 15,
|
||||
height: 15
|
||||
},
|
||||
horizontal: {
|
||||
flexDirection: 'row',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
gif: {
|
||||
flex: 1,
|
||||
height: 200,
|
||||
height: 200
|
||||
},
|
||||
base64: {
|
||||
flex: 1,
|
||||
height: 50,
|
||||
resizeMode: 'contain',
|
||||
resizeMode: 'contain'
|
||||
},
|
||||
touchableText: {
|
||||
fontWeight: '500',
|
||||
color: 'blue',
|
||||
},
|
||||
color: 'blue'
|
||||
}
|
||||
});
|
||||
|
||||
examples.forEach((example) => {
|
||||
examples.forEach(example => {
|
||||
storiesOf('component: Image', module)
|
||||
.addDecorator((renderStory) => <View style={{ width: '100%' }}>{renderStory()}</View>)
|
||||
.add(example.title, () => example.render())
|
||||
})
|
||||
.addDecorator(renderStory => <View style={{ width: '100%' }}>{renderStory()}</View>)
|
||||
.add(example.title, () => example.render());
|
||||
});
|
||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 850 B After Width: | Height: | Size: 850 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import { ListView, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const generateData = (length) => Array.from({ length }).map((item, i) => i);
|
||||
const generateData = length => Array.from({ length }).map((item, i) => i);
|
||||
const dataSource = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
|
||||
|
||||
storiesOf('component: ListView', module)
|
||||
@@ -13,11 +13,11 @@ storiesOf('component: ListView', module)
|
||||
dataSource={dataSource.cloneWithRows(generateData(100))}
|
||||
initialListSize={100}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onScroll={(e) => { console.log('ScrollView.onScroll', e); } }
|
||||
onScroll={e => {
|
||||
console.log('ScrollView.onScroll', e);
|
||||
}}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
renderRow={(row) => (
|
||||
<View><Text>{row}</Text></View>
|
||||
)}
|
||||
renderRow={row => <View><Text>{row}</Text></View>}
|
||||
scrollEventThrottle={1000} // 1 event per second
|
||||
style={styles.scrollViewStyle}
|
||||
/>
|
||||
@@ -30,12 +30,12 @@ storiesOf('component: ListView', module)
|
||||
dataSource={dataSource.cloneWithRows(generateData(5000))}
|
||||
initialListSize={100}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onScroll={(e) => { console.log('ScrollView.onScroll', e); } }
|
||||
onScroll={e => {
|
||||
console.log('ScrollView.onScroll', e);
|
||||
}}
|
||||
pageSize={50}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
renderRow={(row) => (
|
||||
<View><Text>{row}</Text></View>
|
||||
)}
|
||||
renderRow={row => <View><Text>{row}</Text></View>}
|
||||
scrollEventThrottle={1000} // 1 event per second
|
||||
style={styles.scrollViewStyle}
|
||||
/>
|
||||
@@ -48,12 +48,12 @@ storiesOf('component: ListView', module)
|
||||
dataSource={dataSource.cloneWithRows(generateData(5000))}
|
||||
initialListSize={5}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onScroll={(e) => { console.log('ScrollView.onScroll', e); } }
|
||||
onScroll={e => {
|
||||
console.log('ScrollView.onScroll', e);
|
||||
}}
|
||||
pageSize={1}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
renderRow={(row) => (
|
||||
<View><Text>{row}</Text></View>
|
||||
)}
|
||||
renderRow={row => <View><Text>{row}</Text></View>}
|
||||
scrollEventThrottle={1000} // 1 event per second
|
||||
style={styles.scrollViewStyle}
|
||||
/>
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ProgressBar, StyleSheet, View } from 'react-native'
|
||||
import createReactClass from 'create-react-class';
|
||||
import { ProgressBar, StyleSheet, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import { storiesOf, action } from '@kadira/storybook';
|
||||
import { storiesOf } from '@kadira/storybook';
|
||||
import TimerMixin from 'react-timer-mixin';
|
||||
|
||||
/**
|
||||
@@ -26,12 +27,12 @@ import TimerMixin from 'react-timer-mixin';
|
||||
* @flow
|
||||
*/
|
||||
|
||||
var ProgressBarExample = React.createClass({
|
||||
const ProgressBarExample = createReactClass({
|
||||
mixins: [TimerMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
progress: 0,
|
||||
progress: 0
|
||||
};
|
||||
},
|
||||
|
||||
@@ -40,49 +41,48 @@ var ProgressBarExample = React.createClass({
|
||||
},
|
||||
|
||||
updateProgress() {
|
||||
var progress = this.state.progress + 0.01;
|
||||
const progress = this.state.progress + 0.01;
|
||||
this.setState({ progress });
|
||||
this.requestAnimationFrame(() => this.updateProgress());
|
||||
},
|
||||
|
||||
getProgress(offset) {
|
||||
var progress = this.state.progress + offset;
|
||||
const progress = this.state.progress + offset;
|
||||
return Math.sin(progress % Math.PI) % 1;
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ProgressBar style={styles.progressView} color="purple" progress={this.getProgress(0.2)} />
|
||||
<ProgressBar style={styles.progressView} color="red" progress={this.getProgress(0.4)} />
|
||||
<ProgressBar style={styles.progressView} color="orange" progress={this.getProgress(0.6)} />
|
||||
<ProgressBar style={styles.progressView} color="yellow" progress={this.getProgress(0.8)} />
|
||||
<ProgressBar color="purple" progress={this.getProgress(0.2)} style={styles.progressView} />
|
||||
<ProgressBar color="red" progress={this.getProgress(0.4)} style={styles.progressView} />
|
||||
<ProgressBar color="orange" progress={this.getProgress(0.6)} style={styles.progressView} />
|
||||
<ProgressBar color="yellow" progress={this.getProgress(0.8)} style={styles.progressView} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
const examples = [{
|
||||
title: 'progress',
|
||||
render() {
|
||||
return (
|
||||
<ProgressBarExample />
|
||||
);
|
||||
const examples = [
|
||||
{
|
||||
title: 'progress',
|
||||
render() {
|
||||
return <ProgressBarExample />;
|
||||
}
|
||||
},
|
||||
}, {
|
||||
title: 'indeterminate',
|
||||
render() {
|
||||
return (
|
||||
<ProgressBar indeterminate style={styles.progressView} trackColor='#D1E3F6' />
|
||||
);
|
||||
{
|
||||
title: 'indeterminate',
|
||||
render() {
|
||||
return <ProgressBar indeterminate style={styles.progressView} trackColor="#D1E3F6" />;
|
||||
}
|
||||
}
|
||||
}];
|
||||
];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
minWidth: 200,
|
||||
marginTop: -20,
|
||||
backgroundColor: 'transparent',
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
progressView: {
|
||||
marginTop: 20,
|
||||
@@ -90,7 +90,6 @@ var styles = StyleSheet.create({
|
||||
}
|
||||
});
|
||||
|
||||
examples.forEach((example) => {
|
||||
storiesOf('component: ProgressBar', module)
|
||||
.add(example.title, () => example.render())
|
||||
})
|
||||
examples.forEach(example => {
|
||||
storiesOf('component: ProgressBar', module).add(example.title, () => example.render());
|
||||
});
|
||||