Compare commits

...

84 Commits

Author SHA1 Message Date
Nicolas Gallagher
ed70617e91 0.0.117 2017-07-30 20:13:29 -07:00
Nicolas Gallagher
134114de83 [fix] TextInput: call on onKeyPress for Tab and Cmd+Enter
Add support for more key combinations that only fire 'keydown' React DOM
events. And allow users to call 'preventDefault', etc., on the event.

Fix #567
Close #582
2017-07-30 20:11:19 -07:00
Nicolas Gallagher
08ee7c83bb Minor starting documentation improvement 2017-07-30 18:45:08 -07:00
Nicolas Gallagher
5fad78dcad [fix] remove unsupported TextInput props
For compatibility with React Native, do not pass on unsupported
TextInput props to avoid ReactDOM warnings.

Close #571
2017-07-29 17:30:31 -07:00
Nicolas Gallagher
e04343e48e Benchmarks: use glamor@2 and fix yarn.lock paths 2017-07-28 19:08:49 -07:00
Nicolas Gallagher
5e3a946f8b Upgrade docs to use @storybook/react 2017-07-28 15:29:39 -07:00
Nicolas Gallagher
4e3d8dbb02 [change] support CSS custom properties
Update 'setValueForStyles' and style validation to support defining and
using custom properties.

Fix #516
2017-07-28 15:29:07 -07:00
Nicolas Gallagher
fee909d26a [fix] AppState on the server
Fix #578
2017-07-27 16:30:28 -07:00
Nicolas Gallagher
9e58a7b5f1 Update GitHub files 2017-07-27 11:38:50 -07:00
Nicolas Gallagher
20e1febe21 0.0.116 2017-07-26 19:58:34 -07:00
Nicolas Gallagher
ef209ca281 Fix caniuse-api install, again 2017-07-26 19:55:43 -07:00
Nicolas Gallagher
a35949fa71 0.0.115 2017-07-26 19:25:31 -07:00
Nicolas Gallagher
f5ac856c2d Revert unrelated changes to normalizeNativeEvent 2017-07-26 19:25:18 -07:00
Nicolas Gallagher
4b557b1e0b Fix canuse-api installation 2017-07-26 19:20:34 -07:00
Nicolas Gallagher
d4e9d9d256 0.0.114 2017-07-26 16:17:28 -07:00
Nicolas Gallagher
0ff3e91592 [fix] AppState support for Android browser 4.4 2017-07-26 15:52:11 -07:00
Nicolas Gallagher
092d5d12f7 [fix] unitless values for vendor prefixed properties
Problem:

Numeric values are suffixed with 'px', unless the property supports
unitless values. However, vendor prefixed properties were ignored
resulting in invalid CSS values for properties like
'-webkit-flex-shrink'.

Solution:

Apply the upstream solution from React, which includes vendor prefixed
properties in the "unitless number" map. Also build a custom vendor
prefixer to ensure adequate browser support (i.e., Safari 7 and older
Chrome).
2017-07-26 15:51:46 -07:00
Nicolas Gallagher
507e0d41f5 Move event modules into directories 2017-07-26 15:43:10 -07:00
Nicolas Gallagher
9e863d5402 Install docs dependencies separately 2017-07-22 10:47:40 -07:00
Nicolas Gallagher
1364b1dfdf Rename benchmark script 2017-07-22 10:45:04 -07:00
Nicolas Gallagher
7f81e313ed Add link to Glitch playground 2017-07-22 10:43:25 -07:00
Nicolas Gallagher
a1892ec8b8 Update benchmark subjects and results 2017-07-15 11:04:38 -07:00
Nicolas Gallagher
e6232d5980 0.0.113 2017-07-14 10:02:38 -07:00
Nicolas Gallagher
e93a2eb478 Minor edits to View docs 2017-07-13 17:26:32 -07:00
Nicolas Gallagher
44ecf1fe87 [fix] Touchable to avoid touch delay
According to MDN, "touch-action:manipulation" enables "…panning and
pinch zoom gestures, but disables additional non-standard gestures such
as double-tap to zoom. Disabling double-tap to zoom removes the need for
browsers to delay the generation of click events when the user taps the
screen."
2017-07-13 17:13:01 -07:00
Nicolas Gallagher
faec2b4a83 [fix] ScrollView to use 'touch-action' to disable scroll
The recommendation from the Chrome team is to use 'touch-action' to
disable scrolling (via touch modality) when passive event listeners are
in use.

Close #563
2017-07-13 17:10:38 -07:00
Nicolas Gallagher
3677f0dd57 Use more components to build docs 2017-07-11 20:18:52 -07:00
Nicolas Gallagher
36d161a959 0.0.112 2017-07-11 15:39:20 -07:00
Nicolas Gallagher
1ca18ab056 [fix] TouchableWithoutFeedback keyboard support 2017-07-11 09:56:18 -07:00
Nicolas Gallagher
b43717e797 [fix] ensure 'heading' role styles are reset 2017-07-11 09:53:17 -07:00
Nicolas Gallagher
801d5f8c68 0.0.111 2017-07-10 13:14:47 -07:00
Nicolas Gallagher
30f2ec9bf5 [fix] improve Image accessibility 2017-07-10 13:13:11 -07:00
Nicolas Gallagher
6f3e29f630 [change] better Touchable support for keyboards
Problem:

Although 'Touchable' supports basic keyboard usage, it doesn't support
delays or interaction via the Space key.

Solution:

Extend the 'Touchable' mixin to better support keyboard interactions.
All touchable callbacks and delays are now supported when interacted
with via a keyboard's Enter and Space keys (as would be expected of
native 'button' elements). However, events are not normalized to mimic
touch events.

Minor upstream changes to the Touchables in React Native are also
included.
2017-07-10 12:57:16 -07:00
Nicolas Gallagher
2607cb25ab Clean up benchmark exports and PropTypes import 2017-07-09 18:43:46 -07:00
Nicolas Gallagher
8f56454ed7 0.0.110 2017-07-09 17:49:20 -07:00
Nicolas Gallagher
d03e06632e [fix] remove Image styles not supported by View 2017-07-09 17:47:47 -07:00
Nicolas Gallagher
66732394cb Update benchmark libraries 2017-07-09 16:50:01 -07:00
Nicolas Gallagher
077d2f3e63 Update flow and enzyme 2017-07-09 16:23:45 -07:00
Nicolas Gallagher
f6ad9c3afb Update prettier and linter 2017-07-09 16:22:17 -07:00
Nicolas Gallagher
f91ecaa81d Update build tools 2017-07-09 16:19:27 -07:00
Nicolas Gallagher
ad3dee0204 [change] a11y and layout: button role and DOM props
Problems:

HTML's native <button> tag doesn't support flex styling in all browsers,
causing layout bugs. And buttons or links created by "createDOMElement"
(without an accessibility role) do not have the correct props.

Solution:

The "button" role is rendered to a "div[role=button]" that is focusable
and responds to the same keyboard events as a native button. A native
button can still be rendered using "createDOMElement".

Make "createDOMProps" aware of the component context to ensure style
resets and other props are correctly applied when an accessibility role
is not defined.

Additionally:

This patch also adds a new "label" role to support accessible forms.
It maps to a native label element.

Close #241
2017-07-09 16:14:40 -07:00
Nicolas Gallagher
1a0a40d9be Minor improvements to docs text formatting 2017-07-08 20:24:49 -07:00
Vu Le
0bf6e893c6 [add] Dimensions event listeners
Close #511
2017-07-08 20:04:39 -07:00
Nicolas Gallagher
1190ca20a7 0.0.109 2017-07-03 12:33:31 -07:00
Nicolas Gallagher
8f4bed8cb9 Display example apps in storybook 2017-07-03 12:32:16 -07:00
Nicolas Gallagher
5a5d142100 [fix] flex style resolution 2017-07-03 12:32:00 -07:00
Nicolas Gallagher
fb999b5467 UIExplorer: list Components before APIs 2017-06-29 16:15:51 -07:00
Nicolas Gallagher
8b06f28281 [fix] ActivityIndicator sizing 2017-06-29 16:11:08 -07:00
Nicolas Gallagher
9376c72a40 0.0.108 2017-06-29 11:37:39 -07:00
Nicolas Gallagher
d4b1fde9cf Rewrite interactive documentation
Ref #491
2017-06-29 11:33:25 -07:00
Nicolas Gallagher
f237fc3094 Add styled-components/primitives to benchmarks 2017-06-28 16:05:09 -07:00
Nicolas Gallagher
8777e25d8e [add] Image: draggable prop
Allows control over browser's default drag-and-drop behaviour for
images. Setting draggable to 'false' will prevent dragging.

Close #514
2017-06-28 14:03:19 -07:00
Jiaming
18d60047d2 [add] ScrollView: support scrollToEnd method
Close #541
2017-06-28 13:49:08 -07:00
Paul Armstrong
535a7b7027 [fix] TextInput: fix onSubmitEditing when multiline=true
Do not trigger onSubmitEditing when Shift+Enter is pressed in a multiline TextInput.

Fix #524
Close #526
2017-06-27 16:24:52 -07:00
Nicolas Gallagher
bdaeac964c 0.0.107 2017-06-26 10:50:59 -07:00
Nicolas Gallagher
20257afe88 [fix] TextInput onSubmitEditing event 2017-06-26 10:38:53 -07:00
Nicolas Gallagher
99348eaedb [fix] StyleSheet: server-side rendering of styles
Problem:

The content of style sheets was being set as a child of 'style', which
causes React to escape the content. This meant that the pointer-events
selectors were broken (">" became "&gt;") and pointer-events were
disabled for the entire server-rendered document.

Solution:

Use 'dangerouslySetInnerHTML' to avoid the CSS text being escaped.

Fix #546
2017-06-24 10:23:14 -07:00
Peter Ruibal
6cb16d059d Fix @providesModule for a few APIs
Close #542
2017-06-24 07:42:24 -07:00
Nicolas Gallagher
3c660e2ad7 [fix] SSR of Image renders source
When rendered on the server, images now include the 'src' and will be
downloaded by the browser rather than waiting for the client-side JS to
initiate image loading.

Fix #543
2017-06-24 07:37:29 -07:00
Nicolas Gallagher
e9101abefe [change] TextInput 'onKeyPress' includes modifier keys
Include modifier keys in the 'nativeEvent'. This allows keyboard
shortcuts such as "Shift+Enter" to be implemented for submiting text
input content when the modality is keyboard + mouse rather than touch.
2017-06-23 14:48:34 -07:00
Nicolas Gallagher
dfa8087f9a 0.0.106 2017-06-22 18:06:39 -07:00
Nicolas Gallagher
eaccd8799d Fix yarn.lock 2017-06-22 18:06:25 -07:00
Kenneth Lynne
85b2afc313 [fix] TextInput 'onKeyPress' return values
Match the current React Native API for 'onKeyPress'.

Fix #518
Close #537
2017-06-22 18:00:54 -07:00
Nicolas Gallagher
4865c7bcce [change] Clipboard.isSupported -> Clipboard.isAvailable
Rename this method to be consistent with AppState.isAvailable
2017-06-20 16:10:29 -07:00
Nicolas Gallagher
9e9ab78130 0.0.105 2017-06-20 14:09:16 -07:00
Nicolas Gallagher
00b795a87e [change] Nested Text renders as span 2017-06-20 14:05:30 -07:00
Nicolas Gallagher
1edf5241a1 Update webpack and babel-loader 2017-06-20 10:39:09 -07:00
Nicolas Gallagher
4cfcdef264 [fix] AppRegistry container layout
Absolute fill positioning provides better default layout for full-screen
apps.

Fix #528
2017-06-20 10:17:55 -07:00
Nicolas Gallagher
a264c0b956 0.0.104 2017-06-19 07:31:00 -07:00
Nicolas Gallagher
0d8aa24ff3 [fix] 'flex' shorthand sets 'flexBasis' to '0%'
The previous attempt at a fix (88ddeca0c6)
didn't account for 'View' handling the 'flexBasis' reset (as it used to
with 'flexShrink'). This patch moves flex style resolution into the DOM
style resolver.

Fix #426
2017-06-19 07:28:25 -07:00
Nicolas Gallagher
1b77ac4b2f Remove unused file 2017-06-18 16:00:31 -07:00
Nicolas Gallagher
44b185ed4c Add 'unimplemented view' stubs 2017-06-18 15:27:24 -07:00
Nicolas Gallagher
d1d570268a Add note about React Dev Tools to Style guide 2017-06-18 14:36:39 -07:00
Nicolas Gallagher
997c92f841 Update eslint and flow packages 2017-06-18 14:36:39 -07:00
Nicolas Gallagher
8e60690877 Update build tools 2017-06-18 14:36:39 -07:00
Nicolas Gallagher
7bab19ae6c Update inline-style-prefixer 2017-06-18 14:36:33 -07:00
Nicolas Gallagher
c7f287b207 Update React packages 2017-06-18 13:10:58 -07:00
Nicolas Gallagher
02cfbf8987 Add @providesModule annotations and update copyright notices
'providesModule' is necessary for haste support
2017-06-18 12:59:40 -07:00
Nicolas Gallagher
6203a3fec6 Misc flow and lint fixes 2017-06-18 12:59:19 -07:00
Nicolas Gallagher
d1d5461b29 Move 'hash' to 'vendor' directory 2017-06-18 12:24:04 -07:00
Nicolas Gallagher
b0ff4489a9 [fix] Switch compatibility with React Native
Add compatibility support for React Native's 'Switch' props
2017-06-18 12:14:46 -07:00
Nicolas Gallagher
635fda8d63 [fix] ProgressBar indicator overflow
This allows ProgressBar to correctly render provided styles like
'border-radius' without the indicator bar overflowing.
2017-06-17 08:48:37 -07:00
Nicolas Gallagher
5a5eb5425f Allow component styles to be editable in React Dev Tools 2017-06-15 19:30:18 -07:00
Nicolas Gallagher
44d59f4996 Use yarn to run scripts 2017-06-15 19:29:56 -07:00
339 changed files with 16006 additions and 7054 deletions

View File

@@ -28,25 +28,25 @@ yarn
To run flow:
```
npm run flow
yarn flow
```
To run the unit tests:
```
npm run jest
yarn jest
```
…in watch mode:
```
npm run jest:watch
yarn jest:watch
```
To run all automated tests:
```
npm test
yarn test
```
## Visual tests
@@ -54,19 +54,19 @@ npm test
To run the interactive storybook:
```
npm run docs:start
yarn docs:start
```
To generate a static build of the storybook:
```
npm run docs:build
yarn docs:build
```
To run the performance benchmarks in a browser (opening `./benchmarks/index.html`):
```
npm run benchmarks
yarn benchmark
```
## Compile and build
@@ -74,13 +74,13 @@ npm run benchmarks
To compile the source code to `dist`:
```
npm run compile
yarn compile
```
To create a UMD bundle of the library:
```
npm run build
yarn build
```
### Pre-commit
@@ -88,14 +88,14 @@ npm run build
To format and lint code before commit:
```
npm run precommit
yarn precommit
```
To format and lint the entire project:
```
npm run fmt
npm run lint
yarn fmt
yarn lint
```
### New Features
@@ -104,13 +104,17 @@ Please open an issue with a proposal for a new feature or refactoring before
starting on the work. We don't want you to waste your efforts on a pull request
that we won't want to accept.
## Submitting Changes
## Pull requests
* Open a new issue in the [Issue tracker](https://github.com/necolas/react-native-web/issues).
* Fork the repo.
* Create a new feature branch based off the `master` branch.
* Make sure all tests pass and there are no linting errors.
* Submit a pull request, referencing any issues it addresses.
**Before submitting a pull request,** please make sure the following is done:
1. Fork the repository and create your branch from `master`.
2. If you've added code that should be tested, add tests!
3. If you've changed APIs, update the documentation.
4. Ensure the tests pass (`yarn test`).
5. Lint and format your code (`yarn fmt && yarn lint`).
You can now submit a pull request, referencing any issues it addresses.
Please try to keep your pull request focused in scope and avoid including
unrelated commits.

View File

@@ -1,30 +1,20 @@
<!--
React Native for Web is an implementation of React Native. If you have feature
requests, you should post them to https://productpains.com/product/react-native/.
GitHub issues should only be used for bugs or Web-specific features you believe
React Native requires.
Make sure to add ALL the information needed to understand the bug so that
someone can help. If the info is missing we'll add the 'needs more information'
label and close the issue until there is enough information.
-->
**Do you want to request a *feature* or report a *bug*?**
**What is the current behavior?**
Link to minimal test case: (template: [codepen](https://codepen.io/necolas/pen/PZzwBR?editors=0010))
**What is the expected behaviour?**
**Steps to reproduce**
**If the current behavior is a bug, please provide the steps to reproduce and
if a minimal demo of the problem via Glitch or similar (template:
https://glitch.com/edit/#!/react-native-web-playground).**
1.
2.
**Environment (include versions)**
**What is the expected behavior?**
OS:
Device:
Browser:
React Native for Web (version):
React (version):
**Environment (include versions). Did this work in previous versions?**
* OS:
* Device:
* Browser:
* React Native for Web (version):
* React (version):

View File

@@ -1,18 +1 @@
<!--
Thanks for submitting a pull request! Make sure the PR does only one thing.
Please provide enough information so that others can review your pull
request. Make sure you have read the Contributing Guidelines -
https://github.com/necolas/react-native-web/CONTRIBUTING.md
-->
**This patch solves the following problem**
**Test plan**
**This pull request**
- [ ] includes documentation
- [ ] includes tests
- [ ] includes benchmark reports
- [ ] includes an interactive example
- [ ] includes screenshots/videos
**Before submitting a pull request,** please make sure you have followed the steps the CONTRIBUTING guide.

View File

@@ -19,21 +19,27 @@ Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
touch handling to the Web.
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).
to see React Native examples running on Web. Or remix the [React Native for
Web: Playground](https://glitch.com/edit/#!/react-native-web-playground) on
Glitch.
## Quick start
To install in your app:
NOTE: React Native for Web supports React/ReactDOM 15.4, 15.5, or 15.6.
Install in your existing app using `yarn` or `npm`:
```
npm install --save react@15.5 react-dom@15.5 react-native-web
yarn add react@15.6 react-dom@15.6 react-native-web
```
Read the [Getting Started](docs/guides/getting-started.md) guide.
Then read the [Getting Started](docs/guides/getting-started.md) guide.
## Documentation
The [UI Explorer](https://necolas.github.io/react-native-web/storybook/)
interactively documents all the APIs and Components.
Guides:
* [Getting started](docs/guides/getting-started.md)
@@ -44,35 +50,11 @@ Guides:
* [Advanced use](docs/guides/advanced.md)
* [Known issues](docs/guides/known-issues.md)
Exported modules:
## Starter kits
* Components
* [`ActivityIndicator`](docs/components/ActivityIndicator.md)
* [`Button`](docs/components/Button.md)
* [`Image`](docs/components/Image.md)
* [`ProgressBar`](docs/components/ProgressBar.md)
* [`ScrollView`](docs/components/ScrollView.md)
* [`Switch`](docs/components/Switch.md)
* [`Text`](docs/components/Text.md)
* [`TextInput`](docs/components/TextInput.md)
* [`TouchableHighlight`](http://facebook.github.io/react-native/releases/0.22/docs/touchablehighlight.html) (mirrors React Native)
* [`TouchableOpacity`](http://facebook.github.io/react-native/releases/0.22/docs/touchableopacity.html) (mirrors React Native)
* [`TouchableWithoutFeedback`](docs/components/TouchableWithoutFeedback.md)
* [`View`](docs/components/View.md)
* APIs
* [`Animated`](http://facebook.github.io/react-native/releases/0.20/docs/animated.html) (mirrors React Native)
* [`AppRegistry`](docs/apis/AppRegistry.md)
* [`AppState`](docs/apis/AppState.md)
* [`AsyncStorage`](docs/apis/AsyncStorage.md)
* [`Clipboard`](docs/apis/Clipboard.md)
* [`Dimensions`](docs/apis/Dimensions.md)
* [`I18nManager`](docs/apis/I18nManager.md)
* [`NetInfo`](docs/apis/NetInfo.md)
* [`PanResponder`](http://facebook.github.io/react-native/releases/0.20/docs/panresponder.html#content) (mirrors React Native)
* [`PixelRatio`](docs/apis/PixelRatio.md)
* [`Platform`](docs/apis/Platform.md)
* [`StyleSheet`](docs/apis/StyleSheet.md)
* [`Vibration`](docs/apis/Vibration.md)
* [create-react-app](https://github.com/facebookincubator/create-react-app) ([on Glitch](https://glitch.com/edit/#!/react-native-web-playground))
* [react-native-web-starter](https://github.com/grabcode/react-native-web-starter)
* [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack)
## Example code
@@ -116,11 +98,9 @@ AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-ro
## Related projects
* [react-primitives](https://github.com/lelandrichardson/react-primitives/)
* [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)
* [react-web](https://github.com/taobaofed/react-web)
* [react-sketchapp](https://github.com/airbnb/react-sketchapp)
* [reactxp](https://github.com/microsoft/reactxp)
* [react-native-web-player](https://github.com/dabbott/react-native-web-player)
## License

View File

@@ -7,34 +7,45 @@ npm run build:performance
open ./performance/index.html
```
Append `?fastest` to the URL to include the fastest "other libraries", and
`?all` to include all the "other libraries".
## Notes
The components used in the render benchmarks are simple enough to be
implemented by multiple UI or style libraries. The implementations are not
equivalent in functionality.
equivalent in functionality. For example, React Native for Web's stylesheet is
unique in that it also converts React Native styles to DOM styles, has
deterministic resolution, and supports RTL layout.
`react-native-web/stylesheet` is a comparative baseline that implements a
simple `View` without much of React Native's functionality.
## Benchmark results
Typical render timings*: mean ± two standard deviations
Typical render timings*: mean ± two standard deviations.
| Implementation | Deep tree (ms) | Wide tree (ms) | Tweets (ms) |
| 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` |
| `css-modules` | `84.19` `±14.69` | `183.37` 22.98` | |
| `react-native-web/stylesheet@0.0.113` | `88.83` `±14.31` | `185.54` 24.62` | |
| `react-native-web@0.0.113` | `110.45` `±19.63` | `251.53` 32.52` | `15.52` 7.93ms` |
Other libraries
| Implementation | Deep tree (ms) | Wide tree (ms) |
| :--- | ---: | ---: |
| `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` |
| `aphrodite@1.2.3` | `84.68` `±18.80` | `180.62` 41.98` |
| `styletron@2.5.1` | `83.93` 13.10` | `185.96` 45.65` |
| `react-jss@7.0.1` | `174.75` 30.87` | `411.77` 83.83` |
| `glamor@3.0.0-3` | `255.21` 45.68` | `545.74` `±107.79` |
| `reactxp@0.34.3` | `237.46` `±36.72` | `514.48` 84.87` |
| `styled-components@2.1.1` | `266.91` 50.04` | `598.29` 95.13` |
| `styled-components/primitives@2.1.1` | `266.62` `±50.39` | `567.13` `±68.12` |
| `radium@0.19.1` | `518.48` `±69.74` | `1058.85` `±120.85` |
*MacBook Pro (13-inch, Early 2011); 2.7 GHz Intel Core i7; 16 GB 1600 MHz DDR3. Google Chrome 56.
These results indicate that styled render performance is not a significant
differentiating factor between `aphrodite`, `css-modules`, `react-native-web`,
and `styletron`.
*MacBook Pro (13-inch, Early 2015); 3.1 GHz Intel Core i7; 16 GB 1867 MHz DDR3. Google Chrome 58 (2x CPU slowdown).

View File

@@ -5,7 +5,9 @@ const node = document.querySelector('.root');
const createRenderBenchmark = ({ description, getElement, name, runs }) => () => {
const setup = () => {};
const teardown = () => ReactDOM.unmountComponentAtNode(node);
const teardown = () => {
ReactDOM.unmountComponentAtNode(node);
};
return benchmark({
name,
@@ -13,7 +15,9 @@ const createRenderBenchmark = ({ description, getElement, name, runs }) => () =>
runs,
setup,
teardown,
task: () => ReactDOM.render(getElement(), node)
task: () => {
ReactDOM.render(getElement(), node);
}
});
};

View File

@@ -2,9 +2,11 @@ import aphrodite from './src/aphrodite';
import cssModules from './src/css-modules';
import glamor from './src/glamor';
import jss from './src/jss';
import radium from './src/radium';
import reactNative from './src/react-native';
import reactNativeStyleSheet from './src/react-native-stylesheet';
import styledComponents from './src/styled-components';
import styledComponentsPrimitives from './src/styled-components-primitives';
import styletron from './src/styletron';
import xp from './src/reactxp';
@@ -13,6 +15,7 @@ import renderTweet from './tests/renderTweet';
import renderWideTree from './tests/renderWideTree';
const testAll = window.location.search === '?all';
const testFastest = window.location.search === '?fastest';
const coreTests = [
() => renderTweet('react-native-web', reactNative),
@@ -25,25 +28,39 @@ const coreTests = [
() => renderWideTree('react-native-web', reactNative)
];
/**
* Optionally run tests using other libraries
*/
const extraTests = [
const fastestTests = [
() => renderDeepTree('styletron', styletron),
() => renderWideTree('styletron', styletron),
() => renderDeepTree('aphrodite', aphrodite),
() => renderWideTree('aphrodite', aphrodite),
() => renderWideTree('aphrodite', aphrodite)
];
/**
* Optionally run tests using other libraries
*/
const restTests = [
() => renderDeepTree('glamor', glamor),
() => renderWideTree('glamor', glamor),
() => renderDeepTree('react-jss', jss),
() => renderWideTree('react-jss', jss),
() => renderDeepTree('radium', radium),
() => renderWideTree('radium', radium),
() => renderDeepTree('reactxp', xp),
() => renderWideTree('reactxp', xp),
() => renderDeepTree('styled-components', styledComponents),
() => renderWideTree('styled-components', styledComponents)
() => renderWideTree('styled-components', styledComponents),
() => renderDeepTree('styled-components/primitives', styledComponentsPrimitives),
() => renderWideTree('styled-components/primitives', styledComponentsPrimitives)
];
const tests = testAll ? coreTests.concat(extraTests) : coreTests;
const tests = [...coreTests];
if (testFastest) {
tests.push(...fastestTests);
}
if (testAll) {
tests.push(...fastestTests);
tests.push(...restTests);
}
// run benchmarks
tests.reduce((promise, test) => promise.then(test()), Promise.resolve());

View File

@@ -1,20 +1,22 @@
{
"name": "performance",
"name": "benchmarks",
"private": true,
"dependencies": {
"aphrodite": "^1.2.1",
"aphrodite": "^1.2.3",
"classnames": "^2.2.5",
"glamor": "2.20.25",
"glamor": "^2.20.37",
"marky": "^1.2.0",
"react-jss": "^6.1.1",
"reactxp": "^0.34.3",
"styled-components": "2.0.0-17",
"radium": "^0.19.1",
"react-jss": "^7.0.1",
"react-primitives": "^0.4.3",
"reactxp": "0.34.3",
"styled-components": "^2.1.1",
"styletron-client": "^2.5.7",
"styletron-utils": "^2.5.4"
},
"devDependencies": {
"css-loader": "^0.28.1",
"css-loader": "^0.28.4",
"react-addons-perf": "^15.4.2",
"style-loader": "^0.17.0"
"style-loader": "^0.18.2"
}
}

View File

@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import theme from '../theme';
import React, { PropTypes, PureComponent } from 'react';
import React, { PureComponent } from 'react';
import { StyleSheet, Text } from 'react-native';
class AppText extends PureComponent {

View File

@@ -1,4 +1,5 @@
import React, { PureComponent, PropTypes } from 'react';
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
import { StyleSheet, View } from 'react-native';
class AspectRatio extends PureComponent {
@@ -21,7 +22,9 @@ class AspectRatio extends PureComponent {
return (
<View style={[styles.root, style]}>
<View style={[styles.shim, { paddingBottom: `${percentage}%` }]} />
<View style={StyleSheet.absoluteFill}>{children}</View>
<View style={StyleSheet.absoluteFill}>
{children}
</View>
</View>
);
}

View File

@@ -45,4 +45,4 @@ const styles = StyleSheet.create({
}
});
module.exports = Box;
export default Box;

View File

@@ -14,4 +14,4 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
})}
/>;
module.exports = Box;
export default Box;

View File

@@ -44,4 +44,4 @@ const styles = {
}
};
module.exports = Box;
export default Box;

View File

@@ -46,4 +46,4 @@ const styles = {
}
};
module.exports = injectSheet(styles)(Box);
export default injectSheet(styles)(Box);

View File

@@ -0,0 +1,48 @@
/* eslint-disable react/prop-types */
import Radium from 'radium';
import React from 'react';
import View from '../View/radium';
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) =>
<View
{...other}
style={[
styles[`color${color}`],
fixed && styles.fixed,
layout === 'row' && styles.row,
outer && styles.outer
]}
/>;
const styles = {
outer: {
padding: 4
},
row: {
flexDirection: 'row'
},
color0: {
backgroundColor: '#222'
},
color1: {
backgroundColor: '#666'
},
color2: {
backgroundColor: '#999'
},
color3: {
backgroundColor: 'blue'
},
color4: {
backgroundColor: 'orange'
},
color5: {
backgroundColor: 'red'
},
fixed: {
width: 20,
height: 20
}
};
export default Radium(Box);

View File

@@ -45,4 +45,4 @@ const styles = StyleSheet.create({
}
});
module.exports = Box;
export default Box;

View File

@@ -44,4 +44,4 @@ const styles = StyleSheet.create({
}
});
module.exports = Box;
export default Box;

View File

@@ -44,4 +44,4 @@ const styles = {
})
};
module.exports = Box;
export default Box;

View File

@@ -0,0 +1,30 @@
import styled from 'styled-components/primitives';
const getColor = color => {
switch (color) {
case 0:
return '#222';
case 1:
return '#666';
case 2:
return '#999';
case 3:
return 'blue';
case 4:
return 'orange';
case 5:
return 'red';
default:
return 'transparent';
}
};
const Box = styled.View`
flex-direction: ${props => (props.layout === 'column' ? 'column' : 'row')};
padding: ${props => (props.outer ? '4px' : '0')};
height: ${props => (props.fixed ? '20px' : 'auto')};
width: ${props => (props.fixed ? '20px' : 'auto')};
background-color: ${props => getColor(props.color)};
`;
export default Box;

View File

@@ -28,4 +28,4 @@ const Box = styled(View)`
background-color: ${props => getColor(props.color)};
`;
module.exports = Box;
export default Box;

View File

@@ -45,4 +45,4 @@ const styles = {
})
};
module.exports = Box;
export default Box;

View File

@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import { StyleSheet, View } from 'react-native';
import React, { Component, PropTypes } from 'react';
import React, { Component } from 'react';
import theme from '../theme';
class GridView extends Component {

View File

@@ -1,4 +1,5 @@
import React, { Component, PropTypes } from 'react';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
class DeepTree extends Component {
static propTypes = {
@@ -30,10 +31,14 @@ class DeepTree extends Component {
</Box>
);
for (let i = 0; i < wrap; i++) {
result = <Box components={components}>{result}</Box>;
result = (
<Box components={components}>
{result}
</Box>
);
}
return result;
}
}
module.exports = DeepTree;
export default DeepTree;

View File

@@ -1,11 +1,12 @@
import AspectRatio from '../AspectRatio';
import GridView from '../GridView';
import PropTypes from 'prop-types';
import TweetActionsBar from '../TweetActionsBar';
import TweetText from '../TweetText';
import UserAvatar from '../UserAvatar';
import UserNames from '../UserNames';
import { Image, StyleSheet, Text, View } from 'react-native';
import React, { Component, PropTypes } from 'react';
import React, { Component } from 'react';
import theme from '../theme';
export class Tweet extends Component {
@@ -61,7 +62,6 @@ export class Tweet extends Component {
</AspectRatio>
</View>
: null}
</View>
<TweetActionsBar

View File

@@ -2,9 +2,10 @@ import IconReply from '../Icons/Reply';
import IconHeart from '../Icons/Heart';
import IconRetweet from '../Icons/Retweet';
import IconDirectMessage from '../Icons/DirectMessage';
import { Text, View, StyleSheet } from 'react-native';
import React, { PropTypes } from 'react';
import PropTypes from 'prop-types';
import React from 'react';
import theme from '../theme';
import { Text, View, StyleSheet } from 'react-native';
const getIcon = (icon, highlighted) => {
switch (icon) {
@@ -45,7 +46,11 @@ export default class TweetAction extends React.Component {
]}
>
{getIcon(displayMode, highlighted)}
{count > 0 ? <Text style={styles.count}>{count}</Text> : null}
{count > 0
? <Text style={styles.count}>
{count}
</Text>
: null}
</Text>
</View>
);

View File

@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import TweetAction from '../TweetAction';
import { View, StyleSheet } from 'react-native';
import React, { PropTypes, PureComponent } from 'react';
import React, { PureComponent } from 'react';
const actionNames = ['reply', 'retweet', 'like', 'directMessage'];

View File

@@ -1,15 +1,16 @@
import AppText from '../AppText';
import React from 'react';
import TweetTextPart from '../TweetTextPart';
import React, { PropTypes } from 'react';
import { array, number, string } from 'prop-types';
class TweetText extends React.Component {
static displayName = 'TweetText';
static propTypes = {
displayMode: TweetTextPart.propTypes.displayMode,
lang: PropTypes.string,
numberOfLines: PropTypes.number,
textParts: PropTypes.array.isRequired
lang: string,
numberOfLines: number,
textParts: array.isRequired
};
render() {

View File

@@ -1,6 +1,7 @@
/* eslint-disable react/prop-types */
import { Image, StyleSheet, Text } from 'react-native';
import React, { PropTypes } from 'react';
import PropTypes from 'prop-types';
import React from 'react';
import theme from '../theme';
const createTextEntity = ({ part }) => <Text>{`${part.prefix}${part.text}`}</Text>;

View File

@@ -1,6 +1,7 @@
import AspectRatio from '../AspectRatio';
import PropTypes from 'prop-types';
import { Image, StyleSheet } from 'react-native';
import React, { PropTypes, PureComponent } from 'react';
import React, { PureComponent } from 'react';
import theme from '../theme';
class UserAvatar extends PureComponent {

View File

@@ -1,6 +1,7 @@
import AppText from '../AppText';
import PropTypes from 'prop-types';
import { StyleSheet } from 'react-native';
import React, { PropTypes, PureComponent } from 'react';
import React, { PureComponent } from 'react';
class UserNames extends PureComponent {
static displayName = 'UserNames';
@@ -28,7 +29,9 @@ class UserNames extends PureComponent {
onPress={onPress}
style={[styles.root, style]}
>
<AppText color="normal" weight="bold">{fullName}</AppText>
<AppText color="normal" weight="bold">
{fullName}
</AppText>
{layout === 'stack' ? ' \u000A' : ' '}
<AppText color="deepGray" style={styles.screenName}>{`@${screenName}`}</AppText>
</AppText>

View File

@@ -28,4 +28,4 @@ const styles = StyleSheet.create({
}
});
module.exports = View;
export default View;

View File

@@ -10,4 +10,4 @@ class View extends React.Component {
}
}
module.exports = View;
export default View;

View File

@@ -26,4 +26,4 @@ const viewStyle = {
minWidth: 0
};
module.exports = View;
export default View;

View File

@@ -29,4 +29,4 @@ const styles = {
}
};
module.exports = injectSheet(styles)(View);
export default injectSheet(styles)(View);

View File

@@ -0,0 +1,31 @@
/* eslint-disable react/prop-types */
import Radium from 'radium';
import React from 'react';
class View extends React.Component {
render() {
const { style, ...other } = this.props;
return <div {...other} style={[styles.root, style]} />;
}
}
const styles = {
root: {
alignItems: 'stretch',
borderWidth: 0,
borderStyle: 'solid',
boxSizing: 'border-box',
display: 'flex',
flexBasis: 'auto',
flexDirection: 'column',
flexShrink: 0,
margin: 0,
padding: 0,
position: 'relative',
// fix flexbox bugs
minHeight: 0,
minWidth: 0
}
};
export default Radium(View);

View File

@@ -32,4 +32,4 @@ const styles = StyleSheet.create({
}
});
module.exports = View;
export default View;

View File

@@ -16,4 +16,4 @@ const View = styled.div`
min-width: 0;
`;
module.exports = View;
export default View;

View File

@@ -23,11 +23,11 @@ const fontSize = {
large: '1.25rem'
};
module.exports = {
const theme = {
colors,
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif, ' +
'"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', // emoji fonts
'"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', // emoji fonts
fontSize,
lineHeight: 1.3125,
spaceX: 0.6,
@@ -36,3 +36,5 @@ module.exports = {
return `${num}${unit}`;
}
};
export default theme;

View File

@@ -1,7 +1,9 @@
import Box from './components/Box/css-modules';
import View from './components/View/css-modules';
export default {
const api = {
Box,
View
};
export default api;

View File

@@ -1,7 +1,9 @@
import Box from './components/Box/jss';
import View from './components/View/jss';
export default {
const api = {
Box,
View
};
export default api;

9
benchmarks/src/radium.js Normal file
View File

@@ -0,0 +1,9 @@
import Box from './components/Box/radium';
import View from './components/View/radium';
const api = {
Box,
View
};
export default api;

View File

@@ -1,7 +1,9 @@
import Box from './components/Box/react-native-stylesheet';
import View from './components/View/react-native-stylesheet';
export default {
const api = {
Box,
View
};
export default api;

View File

@@ -0,0 +1,7 @@
import Box from './components/Box/styled-components';
import styled from 'styled-components/primitives';
export default {
Box,
View: styled.View
};

View File

@@ -96,7 +96,7 @@ const tweet2 = {
}
};
const renderTweet = (label, components) =>
const renderTweet = label =>
createRenderBenchmark({
name: `Tweet [${label}]`,
runs: 10,

View File

@@ -2,10 +2,33 @@
# yarn lockfile v1
ajv@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.0.tgz#c1735024c5da2ef75cc190713073d44f098bf486"
dependencies:
co "^4.6.0"
fast-deep-equal "^0.1.0"
json-schema-traverse "^0.3.0"
json-stable-stringify "^1.0.1"
alphanum-sort@^1.0.1, alphanum-sort@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
animated@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/animated/-/animated-0.1.5.tgz#83df8dc443d57abab7b0bb04818b0b655b31c9b9"
dependencies:
invariant "^2.2.0"
normalize-css-color "^1.0.1"
animated@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/animated/-/animated-0.2.0.tgz#1a0e96f097b3fbc5b64d7eddc723bcc0a6f97633"
dependencies:
invariant "^2.2.0"
normalize-css-color "^1.0.1"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@@ -14,9 +37,9 @@ 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"
aphrodite@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/aphrodite/-/aphrodite-1.2.3.tgz#4b161e9eef319b1f90a889501f985d7b5e70b285"
dependencies:
asap "^2.0.3"
inline-style-prefixer "^3.0.1"
@@ -28,7 +51,19 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
asap@^2.0.3, asap@~2.0.3:
array-find-index@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
array-find@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8"
asap@^2.0.3, asap@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
asap@~2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
@@ -57,9 +92,9 @@ babel-code-frame@^6.11.0:
esutils "^2.0.2"
js-tokens "^3.0.0"
babel-runtime@^6.18.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
babel-runtime@^6.23.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.25.0.tgz#33b98eaa5d482bb01a8d1aa6b437ad2b01aec41c"
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
@@ -68,6 +103,10 @@ balanced-match@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
base64-js@^1.0.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1"
@@ -76,10 +115,25 @@ 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.6.0:
bowser@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.6.0.tgz#37fc387b616cb6aef370dab4d6bd402b74c5c54d"
bowser@^1.6.0:
version "1.7.1"
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.7.1.tgz#a4de8f18a1a0dc9531eb2a92a1521fb6a9ba96a5"
brace-expansion@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
brcast@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brcast/-/brcast-2.0.1.tgz#4311508f0634a6f5a2465b6cf2db27f06902aaca"
browserslist@^1.0.1, browserslist@^1.5.2, browserslist@^1.7.5:
version "1.7.5"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.5.tgz#eca4713897b51e444283241facf3985de49a9e2b"
@@ -131,6 +185,10 @@ clone@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
coa@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.1.tgz#7f959346cfc8719e3f7233cd6852854a7c67d8a3"
@@ -173,6 +231,10 @@ colors@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
@@ -181,6 +243,14 @@ core-js@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
create-react-class@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.0.tgz#ab448497c26566e1e29413e883207d57cfe7bed4"
dependencies:
fbjs "^0.8.9"
loose-envify "^1.3.1"
object-assign "^4.1.1"
css-color-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
@@ -191,17 +261,18 @@ css-color-names@0.0.4:
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"
resolved "https://registry.yarnpkg.com/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"
css-loader@^0.28.4:
version "0.28.4"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.4.tgz#6cf3579192ce355e8b38d5f42dd7a1f2ec898d0f"
dependencies:
babel-code-frame "^6.11.0"
css-selector-tokenizer "^0.7.0"
cssnano ">=2.6.1 <4"
icss-utils "^2.1.0"
loader-utils "^1.0.2"
lodash.camelcase "^4.3.0"
object-assign "^4.0.1"
@@ -291,14 +362,28 @@ csso@~2.3.1:
clap "^1.0.9"
source-map "^0.5.3"
debounce@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.0.2.tgz#503cc674d8d7f737099664fb75ddbd36b9626dc6"
decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
deep-assign@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-2.0.0.tgz#ebe06b1f07f08dae597620e3dd1622f371a1c572"
dependencies:
is-obj "^1.0.0"
defined@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
deline@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/deline/-/deline-1.0.4.tgz#6c05c87836926e1a1c63e47882f3d2eb2c6f14c9"
electron-to-chromium@^1.2.3:
version "1.2.4"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.2.4.tgz#9751cbea89fa120bf88c226ba41eb8d0b6f1b597"
@@ -325,13 +410,33 @@ esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
exenv@^1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
fast-deep-equal@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-0.1.0.tgz#5c6f4599aba6b333ee3342e2ed978672f1001f8d"
fastparse@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
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"
fbjs@^0.8.12:
version "0.8.14"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.14.tgz#d1dbe2be254c35a91e09f31f9cd50a40b2a0ed1c"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
fbjs@^0.8.4, fbjs@^0.8.5, fbjs@^0.8.9:
version "0.8.12"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
@@ -345,18 +450,37 @@ flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
flexibility@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/flexibility/-/flexibility-2.0.1.tgz#ad323aafc40f469ce624286518fc4d7cd72b7c77"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
glamor@2.20.25:
version "2.20.25"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.25.tgz#71b84b82b67a9327771ac59de53ee915d148a4a3"
glamor@^2.20.37:
version "2.20.37"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.37.tgz#3cd576deb760eaaf475dcc1f9b77bf6a7d2f8b26"
dependencies:
babel-runtime "^6.18.0"
fbjs "^0.8.8"
object-assign "^4.1.0"
prop-types "^15.5.8"
fbjs "^0.8.12"
inline-style-prefixer "^3.0.6"
object-assign "^4.1.1"
prop-types "^15.5.10"
glob@^7.0.5:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
has-ansi@^2.0.0:
version "2.0.0"
@@ -368,6 +492,10 @@ has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
has@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
@@ -394,6 +522,12 @@ icss-replace-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz#cb0b6054eb3af6edc9ab1d62d01933e2d4c8bfa5"
icss-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962"
dependencies:
postcss "^6.0.1"
ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
@@ -406,7 +540,14 @@ indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
inherits@2.0.1:
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
@@ -417,13 +558,19 @@ inline-style-prefixer@^2.0.1, inline-style-prefixer@^2.0.5:
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"
inline-style-prefixer@^3.0.1, inline-style-prefixer@^3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-3.0.6.tgz#b27fe309b4168a31eaf38c8e8c60ab9e7c11731f"
dependencies:
bowser "^1.6.0"
css-in-js-utils "^1.0.3"
invariant@^2.2.0, invariant@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
dependencies:
loose-envify "^1.0.0"
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"
@@ -432,10 +579,14 @@ 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:
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-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
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"
@@ -486,74 +637,88 @@ jsesc@~0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
json-schema-traverse@^0.3.0:
version "0.3.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
json-stable-stringify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
dependencies:
jsonify "~0.0.0"
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"
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
jss-compose@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/jss-compose/-/jss-compose-3.0.1.tgz#0ac07f20baf1d523c211016d383dab08dcfe4186"
jss-camel-case@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/jss-camel-case/-/jss-camel-case-5.0.0.tgz#886c1fe56a8a11577454d6a8b4133caa6c1f53a0"
jss-compose@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jss-compose/-/jss-compose-4.0.0.tgz#f0109e8e8301a2678279301c24523dbc76115b9b"
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-default-unit@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/jss-default-unit/-/jss-default-unit-7.0.0.tgz#176c1db91da870e3ad16301f6f4b4cfc6fe1e90a"
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:
jss-expand@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jss-extend/-/jss-extend-4.0.0.tgz#1c377d4efd67f34c997b699aa8bc1dab1c7edf95"
resolved "https://registry.yarnpkg.com/jss-expand/-/jss-expand-4.0.0.tgz#71ec15386d7839bb23892acf9dcaa40b7fe9c785"
jss-extend@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/jss-extend/-/jss-extend-5.0.0.tgz#08a1d4015d05dfe011e3a281457d471226865387"
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:
jss-global@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/jss-preset-default/-/jss-preset-default-2.0.0.tgz#0368d99626b31067e8d04ab3c7cb17ba8354d422"
resolved "https://registry.yarnpkg.com/jss-global/-/jss-global-2.0.0.tgz#a162f822f17e5d760151d908bdb41d7f2824c28f"
jss-nested@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/jss-nested/-/jss-nested-5.0.0.tgz#c0752f31f2d465110d7de6ac83583dbed669faa0"
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"
warning "^3.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-preset-default@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/jss-preset-default/-/jss-preset-default-3.0.0.tgz#e43ee1ac526f689baf2bfd28ae95a6fdc3a02663"
dependencies:
jss-camel-case "^5.0.0"
jss-compose "^4.0.0"
jss-default-unit "^7.0.0"
jss-expand "^4.0.0"
jss-extend "^5.0.0"
jss-global "^2.0.0"
jss-nested "^5.0.0"
jss-props-sort "^5.0.0"
jss-vendor-prefixer "^6.0.0"
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"
jss-props-sort@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/jss-props-sort/-/jss-props-sort-5.0.0.tgz#8839c88433f64e8c1dab1a7068796f19b84f9195"
jss-vendor-prefixer@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/jss-vendor-prefixer/-/jss-vendor-prefixer-6.0.0.tgz#be58124f0cbed76e98cc8eb5219dbb260f057d0b"
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"
jss@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/jss/-/jss-8.1.0.tgz#b32f15efcce22446dfda4c2be09a04f38431da0a"
dependencies:
is-in-browser "1.0.2"
warning "3.0.0"
is-in-browser "^1.0.2"
warning "^3.0.0"
loader-utils@^1.0.2:
version "1.0.2"
@@ -579,7 +744,7 @@ 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:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
dependencies:
@@ -597,6 +762,12 @@ math-expression-evaluator@^1.2.14:
version "1.2.16"
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.16.tgz#b357fa1ca9faefb8e48d10c14ef2bcb2d9f0a7c9"
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
brace-expansion "^1.1.7"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -614,6 +785,10 @@ node-fetch@^1.0.1:
encoding "^0.1.11"
is-stream "^1.0.1"
normalize-css-color@^1.0.1, normalize-css-color@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/normalize-css-color/-/normalize-css-color-1.0.2.tgz#02991e97cccec6623fe573afbbf0de6a1f3e9f8d"
normalize-range@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
@@ -631,10 +806,20 @@ num2fraction@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
object-assign@^4.0.1, object-assign@^4.1.0:
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
wrappy "1"
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
postcss-calc@^5.2.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e"
@@ -873,6 +1058,14 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0
source-map "^0.5.6"
supports-color "^3.2.3"
postcss@^6.0.1:
version "6.0.3"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.3.tgz#b7f565b3d956fbb8565ca7c1e239d0506e427d8b"
dependencies:
chalk "^1.1.3"
source-map "^0.5.6"
supports-color "^4.0.0"
prepend-http@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
@@ -883,11 +1076,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"
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8:
version "15.5.10"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
dependencies:
fbjs "^0.8.9"
loose-envify "^1.3.1"
q@^1.1.2:
version "1.4.1"
@@ -900,6 +1094,16 @@ query-string@^4.1.0:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
radium@^0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/radium/-/radium-0.19.1.tgz#0fbcc6d0ea5526bdb1e5e5371cad386775a3eec8"
dependencies:
array-find "^1.0.0"
exenv "^1.2.1"
inline-style-prefixer "^2.0.5"
prop-types "^15.5.8"
rimraf "^2.6.1"
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"
@@ -907,16 +1111,64 @@ react-addons-perf@^15.4.2:
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"
react-jss@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-7.0.1.tgz#36c505c3798993edd46ea01734f171f895348e25"
dependencies:
hoist-non-react-statics "^1.2.0"
jss "^7.0.0"
jss-preset-default "^2.0.0"
jss "^8.1.0"
jss-preset-default "^3.0.0"
prop-types "^15.5.8"
theming "^1.1.0"
reactxp@^0.34.3:
react-native-web@0.0.x:
version "0.0.116"
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.0.116.tgz#e05e376b34617a54d61826e4bc06b0bdbfd3f4b2"
dependencies:
animated "^0.2.0"
array-find-index "^1.0.2"
babel-runtime "^6.23.0"
create-react-class "^15.6.0"
debounce "1.0.2"
deep-assign "^2.0.0"
fbjs "^0.8.12"
hyphenate-style-name "^1.0.2"
inline-style-prefixer "^3.0.6"
normalize-css-color "^1.0.2"
prop-types "^15.5.10"
react-timer-mixin "^0.13.3"
react-primitives@^0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/react-primitives/-/react-primitives-0.4.3.tgz#4970afda5a32dccf5ea180380e3a0e16192e4b83"
dependencies:
animated "^0.1.5"
asap "^2.0.5"
deline "^1.0.4"
flexibility "^2.0.1"
inline-style-prefixer "^2.0.5"
invariant "^2.2.1"
normalize-css-color "^1.0.1"
prop-types "^15.5.10"
react-native-web "0.0.x"
react-timer-mixin "^0.13.3"
string-hash "^1.1.3"
react-timer-mixin@^0.13.3:
version "0.13.3"
resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.3.tgz#0da8b9f807ec07dc3e854d082c737c65605b3d22"
react@^15.5.4:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df"
dependencies:
create-react-class "^15.6.0"
fbjs "^0.8.9"
loose-envify "^1.1.0"
object-assign "^4.1.0"
prop-types "^15.5.10"
reactxp@0.34.3:
version "0.34.3"
resolved "https://registry.yarnpkg.com/reactxp/-/reactxp-0.34.3.tgz#6481992e57758ae6ffffbfde3d497527bb495032"
dependencies:
@@ -949,8 +1201,8 @@ regenerate@^1.2.1:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
regenerator-runtime@^0.10.0:
version "0.10.3"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e"
version "0.10.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
regexpu-core@^1.0.0:
version "1.0.0"
@@ -970,10 +1222,22 @@ regjsparser@^0.1.4:
dependencies:
jsesc "~0.5.0"
rimraf@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
dependencies:
glob "^7.0.5"
sax@~1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828"
schema-utils@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
dependencies:
ajv "^5.0.0"
setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
@@ -1002,7 +1266,7 @@ strict-uri-encode@^1.0.0:
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"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
strip-ansi@^3.0.0:
version "3.0.1"
@@ -1010,25 +1274,25 @@ strip-ansi@^3.0.0:
dependencies:
ansi-regex "^2.0.0"
style-loader@^0.17.0:
version "0.17.0"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.17.0.tgz#e8254bccdb7af74bd58274e36107b4d5ab4df310"
style-loader@^0.18.2:
version "0.18.2"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.18.2.tgz#cc31459afbcd6d80b7220ee54b291a9fd66ff5eb"
dependencies:
loader-utils "^1.0.2"
schema-utils "^0.3.0"
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"
styled-components@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.1.1.tgz#7e9b5bc319ee3963b47aebb74f4658119ea9d484"
dependencies:
buffer "^5.0.3"
css-to-react-native "^2.0.3"
fbjs "^0.8.9"
hoist-non-react-statics "^1.2.0"
inline-style-prefixer "^2.0.5"
is-function "^1.0.1"
is-plain-object "^2.0.1"
prop-types "^15.5.4"
stylis "^2.0.0"
stylis "^3.2.1"
supports-color "^3.2.3"
styletron-client@^2.5.7:
@@ -1047,9 +1311,9 @@ styletron-utils@^2.5.4:
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"
stylis@^3.2.1:
version "3.2.3"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.2.3.tgz#fed751d792af3f48a247769f55aca05c1a100a09"
supports-color@^2.0.0:
version "2.0.0"
@@ -1061,6 +1325,12 @@ supports-color@^3.2.3:
dependencies:
has-flag "^1.0.0"
supports-color@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.0.0.tgz#33a7c680aa512c9d03ef929cacbb974d203d2790"
dependencies:
has-flag "^2.0.0"
svgo@^0.7.0:
version "0.7.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
@@ -1077,6 +1347,16 @@ synctasks@^0.2.9:
version "0.2.17"
resolved "https://registry.yarnpkg.com/synctasks/-/synctasks-0.2.17.tgz#38852f008878de2e941b6e458ddf552245268da1"
theming@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/theming/-/theming-1.1.0.tgz#0562760b55a1b919c2d5eeb94130351f8958e13a"
dependencies:
brcast "^2.0.0"
is-function "^1.0.1"
is-plain-object "^2.0.1"
prop-types "^15.5.8"
react "^15.5.4"
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"
@@ -1105,7 +1385,7 @@ 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:
warning@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
dependencies:
@@ -1118,3 +1398,7 @@ whatwg-fetch@>=0.10.0:
whet.extend@~0.9.9:
version "0.9.9"
resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"

View File

@@ -40,6 +40,9 @@ Runs the application that was registered under `appKey`. The `appParameters`
must include the `rootTag` into which the application is rendered, and
optionally any `initialProps`.
On web, if the `rootTag` is a sub-section of your application it should be
styled as `position:relative` and given an explicit height.
static **unmountApplicationComponentAtRootTag**(rootTag: HTMLElement)
To "stop" an application when a view should be destroyed, call

View File

@@ -32,7 +32,7 @@ static **removeEventListener**(eventName: ChangeEventName, handler: Function)
**isConnected**: bool = true
Available on all user agents. Asynchronously fetch a boolean to determine
internet connectivity.
internet connectivity. Use this if you are only interested with whether the device has internet connectivity.
**isConnected.addEventListener**(eventName: ChangeEventName, handler: Function)

View File

@@ -103,8 +103,11 @@ Callback that is called when the text input is focused.
**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.
Callback that is called when a key is pressed. This will be called with `{
nativeEvent: { key: keyValue } }` where keyValue is 'Enter` or 'Backspace' for
respective keys and the typed-in character otherwise including ' ' for space.
Modifier keys are also included in the nativeEvent. Fires before onChange
callbacks.
**onSelectionChange**: ?function

View File

@@ -40,35 +40,40 @@ using `aria-label`.
In some cases, we also want to alert the end user of the type of selected
component (i.e., that it is a “button”). To provide more context to screen
readers, you should specify the `accessibilityRole` property. (Note that React
Native for Web provides a compatibility mapping of equivalent
Native for Web also 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).
element][html-aria-url] and ARIA `role`, where possible. In most cases, both
the element and ARIA `role` are rendered. While this may contradict some ARIA
recommendations, it also helps avoid certain HTML5 conformance errors and
accessibility anti-patterns (e.g., giving a `heading` role to a `button`
element) and browser bugs.
For example:
* `<View accessibilityRole='article' />` => `<article role='article' />`.
* `<View accessibilityRole='banner' />` => `<header role='banner' />`.
* `<View accessibilityRole='button' />` => `<button type='button' role='button' />`.
* `<View accessibilityRole='button' />` => `<div role='button' tabIndex='0' />`.
* `<Text accessibilityRole='label' />` => `<label />`.
* `<Text accessibilityRole='link' href='/' />` => `<a role='link' href='/' />`.
* `<View accessibilityRole='main' />` => `<main role='main' />`.
In the example below, the `TouchableWithoutFeedback` is announced by screen
readers as a native Button.
In the example below, the `TouchableHighlight` is announced by screen
readers as a button.
```
<TouchableWithoutFeedback accessibilityRole="button" onPress={this._onPress}>
```js
<TouchableHighlight accessibilityRole="button" onPress={this._handlePress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Press me!</Text>
</View>
</TouchableWithoutFeedback>
</TouchableHighlight>
```
Note: The `button` role is not implemented using the native `button` element
due to browsers limiting the use of flexbox layout on its children.
Note: Avoid changing `accessibilityRole` values over time or after user
actions. Generally, accessibility APIs do not provide a means of notifying
assistive technologies of a `role` value change.

View File

@@ -1,25 +1,22 @@
# 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).
with React Native for Web. (Alternatively, you can quickly setup a local
project using the starter kits listed in the README.)
It is recommended that your application provide a `Promise` and `Array.from`
polyfill.
## Webpack and Babel
## Web packager
[Webpack](https://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.
Create a `web/webpack.config.js` file:
```js
// webpack.config.js
// web/webpack.config.js
// This is needed for webpack to compile JavaScript.
// Many OSS React Native packages are not compiled to ES5 before being
@@ -37,7 +34,7 @@ const babelLoaderConfiguration = {
loader: 'babel-loader',
options: {
cacheDirectory: true,
// The 'react-native' preset is recommended
// The 'react-native' preset is recommended (or use your own .babelrc)
presets: ['react-native']
}
}
@@ -66,7 +63,8 @@ module.exports = {
plugins: [
// `process.env.NODE_ENV === 'production'` must be `true` for production
// builds to eliminate development checks and reduce build size.
// builds to eliminate development checks and reduce build size. You may
// wish to include additional optimizations.
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
@@ -85,36 +83,97 @@ module.exports = {
}
```
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`.
To run in development:
```
"jest": {
"moduleNameMapper": {
"react-native": "<rootDir>/node_modules/react-native-web"
}
}
./node_modules/.bin/webpack-dev-server -d --config web/webpack.config.js --inline --hot --colors
```
Please refer to the Jest documentation for more information.
To build for production:
```
./node_modules/.bin/webpack -p --config web/webpack.config.js
```
Please refer to the Webpack documentation for more information on configuration.
## Web entry
Create a `index.web.js` file (or simply `index.js` for web-only apps).
### Client-side rendering
Rendering using `AppRegistry`:
```js
// index.web.js
import App from './src/App';
import React from 'react';
import ReactNative, { AppRegistry } from 'react-native';
// register the app
AppRegistry.registerComponent('App', () => App);
AppRegistry.runApplication('App', {
initialProps: {},
rootTag: document.getElementById('react-app')
});
```
Rendering within existing web apps is also possible using `ReactNative`:
```js
import AppHeader from './src/AppHeader';
import React from 'react';
import ReactNative from 'react-native';
ReactNative.render(<AppHeader />, document.getElementById('react-app-header'))
```
And finally, `react-native-web` components will also be rendering within a tree
produced by calling `ReactDOM.render` (i.e., an existing web app), but
otherwise it is not recommended.
### Server-side rendering
Server-side rendering is supported using the `AppRegistry`:
```js
import App from './src/App';
import ReactDOMServer from 'react-dom/server'
import ReactNative, { AppRegistry } from 'react-native'
// register the app
AppRegistry.registerComponent('App', () => App)
// prerender the app
const { element, stylesheets } = AppRegistry.getApplication('App', { initialProps });
const initialHTML = ReactDOMServer.renderToString(element);
const initialStyles = stylesheets.map((sheet) => ReactDOMServer.renderToStaticMarkup(sheet)).join('\n');
// construct HTML document
const document = `
<!DOCTYPE html>
<html>
<head>
${initialStyles}
</head>
<body>
${initialHTML}
`
```
## Web-specific code
Minor platform differences can use the `Platform` module.
```js
import { AppRegistry, Platform } from 'react-native'
import { Platform } from 'react-native';
AppRegistry.registerComponent('MyApp', () => MyApp)
if (Platform.OS === 'web') {
AppRegistry.runApplication('MyApp', {
rootTag: document.getElementById('react-root')
});
}
const styles = StyleSheet.create({
height: (Platform.OS === 'web') ? 200 : 100,
});
```
More significant platform differences should use platform-specific files (see
@@ -137,68 +196,16 @@ import MyComponent from './MyComponent';
React Native will automatically import the correct variant for each specific
target platform.
## Client-side rendering
## Testing with Jest
Rendering using `ReactNative`:
[Jest](https://facebook.github.io/jest/) also needs to map `react-native` to `react-native-web`.
```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'))
```
"jest": {
"moduleNameMapper": {
"react-native": "<rootDir>/node_modules/react-native-web"
}
}
```
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, stylesheets } = AppRegistry.getApplication('App', { initialProps });
const initialHTML = ReactDOMServer.renderToString(element);
const initialStyles = stylesheets.map((sheet) => ReactDOMServer.renderToString(sheet)).join('\n');
// construct HTML document
const document = `
<!DOCTYPE html>
<html>
<head>
${initialStyles}
</head>
<body>
${initialHTML}
`
```
Please refer to the Jest documentation for more information.

View File

@@ -225,7 +225,8 @@ 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.
### What about using DevTools?
### What about using Dev Tools?
It's recommended that you rely more on React DevTools and live/hot-reloading
rather than inspecting and editing the DOM directly.
React Dev Tools supports inspecting and editing of React Native styles. It's
recommended that you rely more on React Dev Tools and live/hot-reloading rather
than inspecting and editing the DOM directly.

13
docs/package.json Normal file
View File

@@ -0,0 +1,13 @@
{
"name": "docs",
"private": true,
"scripts": {
"build": "yarn && build-storybook -o ./dist -c ./storybook/.storybook",
"start": "start-storybook -p 9001 -c ./storybook/.storybook",
"publish": "yarn build && git checkout gh-pages && rm -rf ./storybook && mv docs/dist storybook && git add -A && git commit -m \"Storybook deploy\" && git push origin gh-pages && git checkout -"
},
"dependencies": {
"@storybook/addon-options": "^3.1.6",
"@storybook/react": "^3.1.9"
}
}

View File

@@ -0,0 +1 @@
import '@storybook/addon-options/register';

View File

@@ -1,10 +1,21 @@
import { configure, addDecorator } from '@kadira/storybook';
import { setOptions } from '@storybook/addon-options';
import centered from './decorator-centered';
import { configure, addDecorator } from '@storybook/react';
const context = require.context('../', true, /Example\.js$/);
const context = require.context('../', true, /Screen\.js$/);
addDecorator(centered);
setOptions({
name: 'React Native Web',
url: 'https://necolas.github.io/react-native-web',
goFullScreen: false,
showLeftPanel: true,
showDownPanel: false,
showSearchBox: false,
downPanelInRight: false
});
function loadStories() {
context.keys().forEach(context);
}

View File

@@ -3,7 +3,9 @@ import { StyleSheet, View } from 'react-native';
const styles = StyleSheet.create({
root: {
minHeight: '100vh'
minHeight: '100vh',
maxWidth: 680,
marginHorizontal: 'auto'
}
});

View File

@@ -1,33 +1,36 @@
const path = require('path');
const webpack = require('webpack');
const DEV = process.env.NODE_ENV !== 'production';
module.exports = (storybookBaseConfig, configType) => {
const DEV = configType === 'DEVELOPMENT';
module.exports = {
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: { cacheDirectory: true }
},
{
test: /\.(gif|jpe?g|png|svg)$/,
loader: 'url-loader',
query: { name: '[name].[ext]' }
}
]
},
plugins: [
storybookBaseConfig.module.rules.push({
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: { cacheDirectory: true }
}
});
storybookBaseConfig.module.rules.push({
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'url-loader',
options: { name: '[name].[ext]' }
}
});
storybookBaseConfig.plugins.push(
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.__REACT_NATIVE_DEBUG_ENABLED__': DEV
})
],
resolve: {
alias: {
'react-native': path.join(__dirname, '../../../src/module')
}
}
);
storybookBaseConfig.resolve.alias = {
'react-native': path.join(__dirname, '../../../src/module')
};
return storybookBaseConfig;
};

View File

@@ -0,0 +1,58 @@
/* eslint-disable react/jsx-sort-props */
/**
* @flow
*/
import PropAnimating from './examples/PropAnimating';
import PropColor from './examples/PropColor';
import PropHidesWhenStopped from './examples/PropHidesWhenStopped';
import PropSize from './examples/PropSize';
import React from 'react';
import UIExplorer, { Description, DocItem, Section, storiesOf } from '../../ui-explorer';
const ActivityIndicatorScreen = () =>
<UIExplorer title="ActivityIndicator" url="components/ActivityIndicator">
<Description>Displays a customizable activity indicator</Description>
<Section title="Props">
<DocItem name="...View props" />
<DocItem
name="animating"
typeInfo="?boolean = true"
description="Whether to show the indicator or hide it."
example={{
render: () => <PropAnimating />
}}
/>
<DocItem
name="color"
typeInfo="?color = #1976D2"
description="The foreground color of the spinner."
example={{
render: () => <PropColor />
}}
/>
<DocItem
name="hidesWhenStopped"
typeInfo="?boolean = true"
description="Whether the indicator should hide when not animating."
example={{
render: () => <PropHidesWhenStopped />
}}
/>
<DocItem
name="size"
typeInfo="?enum('small', 'large') | number = 'small'"
description="Size of the indicator. Small has a height of 20px, large has a height of 36px."
example={{
render: () => <PropSize />
}}
/>
</Section>
</UIExplorer>;
storiesOf('Components', module).add('ActivityIndicator', ActivityIndicatorScreen);

View File

@@ -0,0 +1,21 @@
/**
* @flow
*/
import { ActivityIndicator, StyleSheet, View } from 'react-native';
import React from 'react';
const ActivityIndicatorAnimatingExample = () =>
<View style={styles.horizontal}>
<ActivityIndicator />
<ActivityIndicator animating={false} />
</View>;
const styles = StyleSheet.create({
horizontal: {
alignItems: 'center',
flexDirection: 'row'
}
});
export default ActivityIndicatorAnimatingExample;

View File

@@ -0,0 +1,33 @@
/**
* @flow
*/
import React from 'react';
import { ActivityIndicator, StyleSheet, View } from 'react-native';
const ActivityIndicatorColorExample = () =>
<View style={styles.horizontal}>
<ActivityIndicator color="#1DA1F2" style={styles.rightPadding} />
<ActivityIndicator color="#17BF63" style={styles.rightPadding} />
<ActivityIndicator color="#F45D22" style={styles.rightPadding} />
<ActivityIndicator color="#794BC4" style={styles.rightPadding} />
<ActivityIndicator color="#E0245E" style={styles.rightPadding} />
<ActivityIndicator color="#FFAD1F" style={styles.rightPadding} />
</View>;
const styles = StyleSheet.create({
horizontal: {
alignItems: 'center',
flexDirection: 'row'
},
rightPadding: {
paddingRight: 10
}
});
ActivityIndicatorColorExample.metadata = {
id: 'ActivityIndicator.props.color',
description: ''
};
export default ActivityIndicatorColorExample;

View File

@@ -0,0 +1,67 @@
/**
* @flow
*/
import { ActivityIndicator, StyleSheet, View } from 'react-native';
import { bool } from 'prop-types';
import React, { PureComponent } from 'react';
class ToggleAnimatingActivityIndicator extends PureComponent {
static propTypes = {
hidesWhenStopped: bool,
style: ActivityIndicator.propTypes.style
};
state = {
animating: true
};
setToggleTimeout = () => {
this._timer = setTimeout(() => {
this.setState({ animating: !this.state.animating });
this.setToggleTimeout();
}, 2000);
};
componentDidMount() {
this.setToggleTimeout();
}
componentWillUnmount() {
clearTimeout(this._timer);
}
render() {
return (
<ActivityIndicator
animating={this.state.animating}
hidesWhenStopped={this.props.hidesWhenStopped}
size="large"
style={[styles.centering, this.props.style]}
/>
);
}
}
const ActivityIndicatorHidesWhenStoppedExample = () =>
<View style={[styles.horizontal]}>
<ToggleAnimatingActivityIndicator hidesWhenStopped={false} style={styles.rightPadding} />
<ToggleAnimatingActivityIndicator />
</View>;
const styles = StyleSheet.create({
horizontal: {
alignItems: 'center',
flexDirection: 'row'
},
rightPadding: {
paddingRight: 10
}
});
ActivityIndicatorHidesWhenStoppedExample.metadata = {
id: 'ActivityIndicator.props.hidesWhenStopped',
description: ''
};
export default ActivityIndicatorHidesWhenStoppedExample;

View File

@@ -0,0 +1,32 @@
/**
* @flow
*/
import React from 'react';
import { ActivityIndicator, StyleSheet, View } from 'react-native';
const sizes = [20, 'small', 36, 'large', 60];
const ActivityIndicatorSizeExample = () =>
<View style={styles.horizontal}>
{sizes.map((size, i) => <ActivityIndicator key={i} size={size} style={styles.rightPadding} />)}
<ActivityIndicator size="large" style={styles.large} />
</View>;
const styles = StyleSheet.create({
horizontal: {
alignItems: 'center',
flexDirection: 'row'
},
rightPadding: {
paddingRight: 10
},
large: { marginLeft: 20, transform: [{ scale: 1.75 }] }
});
ActivityIndicatorSizeExample.metadata = {
id: 'ActivityIndicator.props.size',
description: ''
};
export default ActivityIndicatorSizeExample;

View File

@@ -0,0 +1,73 @@
/* eslint-disable react/jsx-sort-props */
/**
* @flow
*/
import React from 'react';
import PropColor from './examples/PropColor';
import PropDisabled from './examples/PropDisabled';
import PropOnPress from './examples/PropOnPress';
import UIExplorer, {
AppText,
Code,
Description,
DocItem,
Section,
storiesOf
} from '../../ui-explorer';
const ButtonScreen = () =>
<UIExplorer title="Button" url="components/Button">
<Description>
<AppText>
A basic button component. Supports a minimal level of customization. You can build your own
custom button using <Code>TouchableOpacity</Code> or <Code>TouchableNativeFeedback</Code>.
</AppText>
</Description>
<Section title="Props">
<DocItem
name="accessibilityLabel"
typeInfo="?string"
description="Overrides the text that's read by a screen reader when the user interacts with the element."
/>
<DocItem
name="color"
typeInfo="?string"
description="Background color of the button."
example={{
render: () => <PropColor />
}}
/>
<DocItem
name="disabled"
typeInfo="?boolean"
description="If true, disable all interactions for this element."
example={{
render: () => <PropDisabled />
}}
/>
<DocItem
name="onPress"
typeInfo="function"
description="This function is called on press."
example={{
render: () => <PropOnPress />
}}
/>
<DocItem
name="testID"
typeInfo="?string"
description="Used to locate this view in end-to-end tests."
/>
<DocItem name="title" typeInfo="string" description="Text to display inside the button." />
</Section>
</UIExplorer>;
storiesOf('Components', module).add('Button', ButtonScreen);

View File

@@ -0,0 +1,22 @@
/**
* @flow
*/
import React from 'react';
import { DividerVertical } from '../helpers';
import { Button, View } from 'react-native';
const emptyFunction = () => {};
const ButtonColorExample = () =>
<View>
<Button color="#17BF63" onPress={emptyFunction} title="Press me" />
<DividerVertical />
<Button color="#F45D22" onPress={emptyFunction} title="Press me" />
<DividerVertical />
<Button color="#794BC4" onPress={emptyFunction} title="Press me" />
<DividerVertical />
<Button color="#E0245E" onPress={emptyFunction} title="Press me" />
</View>;
export default ButtonColorExample;

View File

@@ -0,0 +1,13 @@
/**
* @flow
*/
import React from 'react';
import { Button } from 'react-native';
const onPress = () => {
console.error('Disabled button should not trigger onPress!');
};
const ButtonDisabledExample = () => <Button disabled onPress={onPress} title="Disabled button" />;
export default ButtonDisabledExample;

View File

@@ -0,0 +1,28 @@
/**
* @flow
*/
import React from 'react';
import { DividerHorizontal } from '../helpers';
import { Button, StyleSheet, View } from 'react-native';
const emptyFunction = () => {};
const ButtonOnPressExample = () =>
<View style={styles.horizontal}>
<Button
accessibilityLabel="This sounds great!"
onPress={emptyFunction}
title="This looks great!"
/>
<DividerHorizontal />
<Button color="#841584" onPress={emptyFunction} title="Ok!" />
</View>;
const styles = StyleSheet.create({
horizontal: {
flexDirection: 'row'
}
});
export default ButtonOnPressExample;

View File

@@ -0,0 +1,20 @@
/**
* @flow
*/
import React from 'react';
import { StyleSheet, View } from 'react-native';
const DividerHorizontal = () => <View style={styles.horizontalDivider} />;
const DividerVertical = () => <View style={styles.verticalDivider} />;
const styles = StyleSheet.create({
horizontalDivider: {
width: '0.6rem'
},
verticalDivider: {
height: '1.3125rem'
}
});
export { DividerHorizontal, DividerVertical };

View File

@@ -0,0 +1,180 @@
/* eslint-disable react/jsx-sort-props */
/**
* @flow
*/
import React from 'react';
import PropChildren from './examples/PropChildren';
import PropDefaultSource from './examples/PropDefaultSource';
import PropDraggable from './examples/PropDraggable';
import PropOnError from './examples/PropOnError';
import PropOnLoad from './examples/PropOnLoad';
import PropOnLoadEnd from './examples/PropOnLoadEnd';
import PropOnLoadStart from './examples/PropOnLoadStart';
import PropResizeMode from './examples/PropResizeMode';
import PropSource from './examples/PropSource';
import StaticGetSizeExample from './examples/StaticGetSize';
import StaticPrefetchExample from './examples/StaticPrefetch';
import UIExplorer, {
AppText,
Code,
Description,
DocItem,
Section,
storiesOf
} from '../../ui-explorer';
const ImageScreen = () =>
<UIExplorer title="Image" url="components/Image">
<Description>
An accessibile image component with support for image resizing, default image, and child
content.
</Description>
<Section title="Props">
<DocItem name="...View props" />
<DocItem
name="children"
typeInfo="?any"
description="Content to display over the image."
example={{
render: () => <PropChildren />
}}
/>
<DocItem
name="defaultSource"
typeInfo="?object"
description={
<AppText>
An image to display as a placeholder while downloading the final image off the network.{' '}
<Code>{'{ uri: string, width, height }'}</Code>
</AppText>
}
example={{
render: () => <PropDefaultSource />
}}
/>
<DocItem
label="web"
name="draggable"
typeInfo="?boolean = true"
description="When false, the image will not be draggable"
example={{
render: () => <PropDraggable />
}}
/>
<DocItem
name="onError"
typeInfo="?function"
description={
<AppText>
Invoked on load error with <Code>{'{nativeEvent: {error}}'}</Code>.
</AppText>
}
example={{
render: () => <PropOnError />
}}
/>
<DocItem
name="onLoad"
typeInfo="?function"
description="Invoked when load completes successfully."
example={{
render: () => <PropOnLoad />
}}
/>
<DocItem
name="onLoadEnd"
typeInfo="?function"
description="Invoked when load either succeeds or fails."
example={{
render: () => <PropOnLoadEnd />
}}
/>
<DocItem
name="onLoadStart"
typeInfo="?function"
description="Invoked on load start."
example={{
render: () => <PropOnLoadStart />
}}
/>
<DocItem
name="resizeMode"
typeInfo="?enum('center', 'contain', 'cover', 'none', 'repeat', 'stretch') = 'cover';"
description="Determines how to resize the image when the frame doesn't match the raw image dimensions."
example={{
render: () => <PropResizeMode />
}}
/>
<DocItem
name="source"
typeInfo="?object"
description={
<AppText>
<Code>uri</Code> is a string representing the resource identifier for the image, which
could be an http address or a base64 encoded image.{' '}
<Code>{'{ uri: string, width, height }'}</Code>
</AppText>
}
example={{
render: () => <PropSource />
}}
/>
<DocItem name="style" typeInfo="?style" />
</Section>
<Section title="Properties">
<DocItem
name="static resizeMode"
typeInfo="object"
example={{
code: '<Image resizeMode={Image.resizeMode.contain} />'
}}
/>
</Section>
<Section title="Methods">
<DocItem
name="static getSize"
typeInfo="(uri: string, success: (width, height) => {}, failure: function) => void"
description={[
<AppText key={1}>
Retrieve the width and height (in pixels) of an image prior to displaying it. This
method can fail if the image cannot be found, or fails to download.
</AppText>,
<AppText key={2}>
(In order to retrieve the image dimensions, the image may first need to be loaded or
downloaded, after which it will be cached. This means that in principle you could use
this method to preload images, however it is not optimized for that purpose, and may in
future be implemented in a way that does not fully load/download the image data.)
</AppText>
]}
example={{
render: () => <StaticGetSizeExample />
}}
/>
<DocItem
name="static prefetch"
typeInfo="(url: string) => Promise"
description="Prefetches a remote image for later use by downloading it."
example={{
render: () => <StaticPrefetchExample />
}}
/>
</Section>
</UIExplorer>;
storiesOf('Components', module).add('Image', ImageScreen);

View File

@@ -0,0 +1,72 @@
/**
* @flow
*/
/*
import React, { PureComponent } from 'react';
import { Image, StyleSheet, Text, View } from 'react-native';
export default class MultipleSourcesExample extends PureComponent {
state = {
width: 30,
height: 30
};
render() {
return (
<View style={styles.container}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text style={styles.touchableText} onPress={this.decreaseImageSize}>
Decrease image size
</Text>
<Text style={styles.touchableText} onPress={this.increaseImageSize}>
Increase image size
</Text>
</View>
<Text>Container image size: {this.state.width}x{this.state.height} </Text>
<View style={{ height: this.state.height, width: this.state.width }}>
<Image
style={{ flex: 1 }}
source={[
{ uri: 'http://facebook.github.io/react/img/logo_small.png', width: 38, height: 38 },
{
uri: 'http://facebook.github.io/react/img/logo_small_2x.png',
width: 76,
height: 76
},
{ uri: 'http://facebook.github.io/react/img/logo_og.png', width: 400, height: 400 }
]}
/>
</View>
</View>
);
}
increaseImageSize = () => {
if (this.state.width >= 100) {
return;
}
this.setState(state => ({
width: state.width + 10,
height: state.height + 10
}));
};
decreaseImageSize = () => {
if (this.state.width <= 10) {
return;
}
this.setState(state => ({
width: state.width - 10,
height: state.height - 10
}));
};
}
const styles = StyleSheet.create({
touchableText: {
color: 'blue',
fontWeight: '500'
}
});
*/

View File

@@ -0,0 +1,87 @@
/**
* @flow
*/
import * as helpers from '../helpers';
import { oneOf } from 'prop-types';
import sources from '../sources';
import React, { PureComponent } from 'react';
import { ActivityIndicator, Image, Text, View } from 'react-native';
class NetworkImageExample extends PureComponent {
state = {
error: false,
loading: false
};
static propTypes = {
logMethod: oneOf(['onError', 'onLoad', 'onLoadEnd', 'onLoadStart']),
source: Image.propTypes.source
};
static defaultProps = {
logList: []
};
render() {
const loader = this.state.loading
? <View>
<ActivityIndicator />
</View>
: null;
return (
<View style={[helpers.styles.row, helpers.styles.centerRow]}>
<Image
defaultSource={sources.placeholder}
onError={this._handleError}
onLoad={this._handleLoad}
onLoadEnd={this._handleLoadEnd}
onLoadStart={this._handleLoadStart}
source={this.props.source}
style={helpers.styles.base}
>
{loader}
</Image>
{this.state.message &&
<Text style={helpers.styles.marginLeft}>
{this.state.message}
</Text>}
</View>
);
}
_handleError = e => {
const nextState = { loading: false };
if (this.props.logMethod === 'onError') {
nextState.message = `✘ onError ${JSON.stringify(e.nativeEvent)}`;
}
this.setState(() => nextState);
};
_handleLoad = () => {
const nextState = { loading: false };
if (this.props.logMethod === 'onLoad') {
nextState.message = '✔ onLoad';
}
this.setState(() => nextState);
};
_handleLoadEnd = () => {
const nextState = { loading: false };
if (this.props.logMethod === 'onLoadEnd') {
nextState.message = '✔ onLoadEnd';
}
this.setState(() => nextState);
};
_handleLoadStart = () => {
const nextState = { loading: true };
if (this.props.logMethod === 'onLoadStart') {
nextState.message = '✔ onLoadStart';
}
this.setState(() => nextState);
};
}
export default NetworkImageExample;

View File

@@ -0,0 +1,28 @@
/**
* @flow
*/
import sources from '../sources';
import React from 'react';
import { Image, StyleSheet, Text } from 'react-native';
const ImageChildrenExample = () =>
<Image source={sources.large} style={styles.image}>
<Text style={styles.text}>React</Text>
</Image>;
const styles = StyleSheet.create({
image: {
width: 60,
height: 60,
backgroundColor: 'transparent',
justifyContent: 'center',
alignItems: 'center'
},
text: {
backgroundColor: 'transparent',
color: 'white'
}
});
export default ImageChildrenExample;

View File

@@ -0,0 +1,17 @@
/**
* @flow
*/
import * as helpers from '../helpers';
import sources from '../sources';
import React from 'react';
import { Image } from 'react-native';
const ImageDefaultSourceExample = () =>
<Image
defaultSource={sources.placeholder}
source={sources.largeAlt}
style={helpers.styles.base}
/>;
export default ImageDefaultSourceExample;

View File

@@ -0,0 +1,26 @@
/**
* @flow
*/
import sources from '../sources';
import React from 'react';
import { Image, StyleSheet, View } from 'react-native';
const ImageDraggableExample = () =>
<View style={styles.container}>
<Image draggable={false} source={sources.large} style={styles.image} />
</View>;
const styles = StyleSheet.create({
container: {
flexDirection: 'row'
},
image: {
width: 60,
height: 60,
backgroundColor: 'transparent',
marginRight: 10
}
});
export default ImageDraggableExample;

View File

@@ -0,0 +1,11 @@
/**
* @flow
*/
import NetworkImage from './NetworkImage';
import React from 'react';
import sources from '../sources';
const ImageOnErrorExample = () => <NetworkImage logMethod="onError" source={sources.broken} />;
export default ImageOnErrorExample;

View File

@@ -0,0 +1,13 @@
/**
* @flow
*/
import { createUncachedURI } from '../helpers';
import NetworkImage from './NetworkImage';
import React from 'react';
import sources from '../sources';
const ImageOnLoadExample = () =>
<NetworkImage logMethod="onLoad" source={createUncachedURI(sources.small)} />;
export default ImageOnLoadExample;

View File

@@ -0,0 +1,13 @@
/**
* @flow
*/
import { createUncachedURI } from '../helpers';
import NetworkImage from './NetworkImage';
import React from 'react';
import sources from '../sources';
const ImageOnLoadEndExample = () =>
<NetworkImage logMethod="onLoadEnd" source={createUncachedURI(sources.small)} />;
export default ImageOnLoadEndExample;

View File

@@ -0,0 +1,13 @@
/**
* @flow
*/
import { createUncachedURI } from '../helpers';
import NetworkImage from './NetworkImage';
import React from 'react';
import sources from '../sources';
const ImageOnLoadStartExample = () =>
<NetworkImage logMethod="onLoadStart" source={createUncachedURI(sources.small)} />;
export default ImageOnLoadStartExample;

View File

@@ -0,0 +1,74 @@
/**
* @flow
*/
import React from 'react';
import sources from '../sources';
import { Image, StyleSheet, Text, View } from 'react-native';
const ImageResizeModeExample = () =>
<View>
{[sources.small, sources.large].map((source, i) => {
return (
<View key={i}>
<View style={styles.horizontal}>
<View>
<Text style={[styles.resizeModeText]}>Contain</Text>
<Image
resizeMode={Image.resizeMode.contain}
source={source}
style={styles.resizeMode}
/>
</View>
<View>
<Text style={[styles.resizeModeText]}>Cover</Text>
<Image
resizeMode={Image.resizeMode.cover}
source={source}
style={styles.resizeMode}
/>
</View>
<View>
<Text style={[styles.resizeModeText]}>Stretch</Text>
<Image
resizeMode={Image.resizeMode.stretch}
source={source}
style={styles.resizeMode}
/>
</View>
<View>
<Text style={[styles.resizeModeText]}>Repeat</Text>
<Image resizeMode={'repeat'} source={source} style={styles.resizeMode} />
</View>
<View>
<Text style={[styles.resizeModeText]}>Center</Text>
<Image resizeMode={'center'} source={source} style={styles.resizeMode} />
</View>
</View>
</View>
);
})}
</View>;
const styles = StyleSheet.create({
horizontal: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between'
},
resizeMode: {
borderColor: 'black',
borderWidth: 0.5,
height: 60,
width: 90
},
resizeModeText: {
fontSize: 11,
marginBottom: 3
},
leftMargin: {
marginLeft: 10
}
});
export default ImageResizeModeExample;

View File

@@ -0,0 +1,47 @@
/**
* @flow
*/
import sources from '../sources';
import React from 'react';
import { Image, StyleSheet, Text, View } from 'react-native';
const ImageSourceExample = () =>
<View style={styles.row}>
<View style={styles.column}>
<Text style={styles.text}>Static image</Text>
<Image source={sources.static} style={styles.image} />
</View>
<View style={styles.column}>
<Text style={styles.text}>Animated GIF</Text>
<Image source={sources.animatedGif} style={styles.image} />
</View>
<View style={styles.column}>
<Text style={styles.text}>Data PNG</Text>
<Image source={sources.dataPng} style={styles.image} />
</View>
<View style={styles.column}>
<Text style={styles.text}>Data SVG</Text>
<Image source={sources.dataSvg} style={styles.image} />
</View>
</View>;
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
flexWrap: 'wrap'
},
column: {
marginRight: '1rem'
},
text: {
marginBottom: '0.5rem'
},
image: {
flex: 1,
height: 50,
resizeMode: 'contain'
}
});
export default ImageSourceExample;

View File

@@ -0,0 +1,66 @@
/**
* @flow
*/
import { createUncachedURI } from '../helpers';
import sources from '../sources';
import React, { PureComponent } from 'react';
import { Button, Image, StyleSheet, Text, View } from 'react-native';
class ImageGetSizeExample extends PureComponent {
static propTypes = {
source: Image.propTypes.source
};
state = {
showButton: true,
startLoad: false,
width: 0,
height: 0
};
render() {
const { showButton, startLoad } = this.state;
return (
<View>
{showButton
? <View style={styles.button}>
<Button onPress={this._handlePress} title="(4.7MB) Get image dimensions" />
</View>
: null}
{startLoad
? <View>
<Text>
Source dimensions:{' '}
{JSON.stringify({ width: this.state.width, height: this.state.height })}
</Text>
<Image source={createUncachedURI(this.props.source.uri)} style={styles.image} />
</View>
: null}
</View>
);
}
_handlePress = () => {
Image.getSize(this.props.source.uri, (width, height) => {
this.setState({ startLoad: true, showButton: false, width, height });
});
};
}
const styles = StyleSheet.create({
button: {
maxWidth: 300
},
image: {
backgroundColor: '#eee',
height: 227,
marginTop: 10,
width: 323
}
});
const StaticGetSizeExample = () => <ImageGetSizeExample source={sources.huge} />;
export default StaticGetSizeExample;

View File

@@ -0,0 +1,98 @@
/**
* @flow
*/
import { createUncachedURI } from '../helpers';
import sources from '../sources';
import React, { PureComponent } from 'react';
import { Button, Image, StyleSheet, Text, View } from 'react-native';
class ImagePrefetchExample extends PureComponent {
static propTypes = {
source: Image.propTypes.source
};
state = {
events: [],
showButton: true,
startLoad: false
};
render() {
const { showButton, startLoad } = this.state;
return (
<View>
{showButton
? <View style={styles.button}>
<Button onPress={this._handlePress} title="Prefetch image" />
</View>
: null}
{startLoad
? <View>
<Text>
{this.state.events.join('\n')}
</Text>
<Image
onLoad={this._handleLoad}
onLoadEnd={this._handleLoadEnd}
onLoadStart={this._handleLoadStart}
source={this.props.source}
style={styles.image}
/>
</View>
: null}
</View>
);
}
_handleLoad = () => {
const startTime = this._startTime;
this._loadEventFired(`✔ (prefetched) onLoad (+${Date.now() - startTime}ms)`);
};
_handleLoadEnd = () => {
const startTime = this._startTime;
this._loadEventFired(`✔ (prefetched) onLoadEnd (+${Date.now() - startTime}ms)`);
};
_handleLoadStart = () => {
const startTime = this._startTime;
this._loadEventFired(`✔ (prefetched) onLoadStart (+${Date.now() - startTime}ms)`);
};
_handlePress = () => {
this._startTime = this._startTime || Date.now();
Image.prefetch(createUncachedURI(this.props.source.uri)).then(
() => {
this._loadEventFired('✔ Prefetch OK');
this.setState(() => ({ startLoad: true }));
},
error => {
this._loadEventFired(`✘ Prefetch failed (+${Date.now() - this._startTime}ms)`);
console.log(error);
}
);
};
_loadEventFired = event => {
this.setState(state => ({ events: [...state.events, event], showButton: false }));
};
}
const styles = StyleSheet.create({
button: {
maxWidth: 300
},
image: {
backgroundColor: '#eee',
height: 150,
marginTop: 10,
width: 150
}
});
const StaticPrefetchExample = () => <ImagePrefetchExample source={sources.prefetchable} />;
export default StaticPrefetchExample;

View File

@@ -0,0 +1,30 @@
/**
* @flow
*/
// import React from 'react';
import { StyleSheet } from 'react-native';
const createUncachedURI = source => {
const helper = str => `${str}?t=${Date.now()}`;
const uri = typeof source === 'string' ? source : source.uri;
return typeof source === 'string' ? helper(uri) : { ...source, uri: helper(uri) };
};
const styles = StyleSheet.create({
base: {
height: 38,
width: 38
},
row: {
flexDirection: 'row'
},
centerRow: {
alignItems: 'center'
},
marginLeft: {
marginLeft: '1rem'
}
});
export { createUncachedURI, styles };

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,28 @@
import placeholder from './bunny.png';
import staticImage from './uie_thumb_normal@2x.png';
const dataPng =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
const dataSvg =
'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>';
const sources = {
animatedGif: {
uri:
'http://38.media.tumblr.com/9e9bd08c6e2d10561dd1fb4197df4c4e/tumblr_mfqekpMktw1rn90umo1_500.gif'
},
broken: { uri: 'http://TYPO_ERROR.github.io/image.png' },
small: { uri: 'http://facebook.github.io/react/img/logo_small_2x.png' },
large: { uri: 'http://facebook.github.io/react/img/logo_og.png' },
largeAlt: { uri: 'http://facebook.github.io/origami/public/images/birds.jpg' },
placeholder,
prefetchable: { uri: 'http://origami.design/public/images/bird-logo.png' },
static: staticImage,
huge: {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/d7/Chestnut-mandibled_Toucan.jpg'
},
dataPng,
dataSvg
};
export default sources;

View File

Before

Width:  |  Height:  |  Size: 850 B

After

Width:  |  Height:  |  Size: 850 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,67 @@
/**
* @flow
*/
import PropColor from './examples/PropColor';
import CustomSize from './examples/CustomSize';
import PropIndeterminate from './examples/PropIndeterminate';
import PropProgress from './examples/PropProgress';
import PropTrackColor from './examples/PropTrackColor';
import React from 'react';
import UIExplorer, { Description, DocItem, Section, storiesOf } from '../../ui-explorer';
const ProgressBarScreen = () =>
<UIExplorer title="ProgressBar" url="components/ProgressBar">
<Description>Display an activity progress bar</Description>
<Section title="Props">
<DocItem name="...View props" />
<DocItem
description="Color of the progress bar."
example={{
render: () => <PropColor />
}}
name="color"
typeInfo="?string = #1976D2"
/>
<DocItem
description="Whether the progress bar will show indeterminate progress."
example={{
render: () => <PropIndeterminate />
}}
name="indeterminate"
typeInfo="?boolean = true"
/>
<DocItem
description="The progress value (between 0 and 1)."
example={{
render: () => <PropProgress />
}}
name="progress"
typeInfo="?number"
/>
<DocItem
description="Color of the track bar."
example={{
render: () => <PropTrackColor />
}}
name="trackColor"
typeInfo="?string = 'transparent'"
/>
</Section>
<Section title="More examples">
<DocItem
description="Custom sizes can be created using styles"
example={{
code: '<ProgressBar style={{ borderRadius: 10, height: 10 }} trackColor="#D1E3F6" />',
render: () => <CustomSize />
}}
/>
</Section>
</UIExplorer>;
storiesOf('Components', module).add('ProgressBar', ProgressBarScreen);

View File

@@ -0,0 +1,27 @@
/**
* @flow
*/
import { DividerVertical } from '../helpers';
import React from 'react';
import { ProgressBar, StyleSheet, View } from 'react-native';
const ProgressBarCustomSizeExample = () =>
<View>
<ProgressBar color="#1DA1F2" progress={0.33} style={styles.one} trackColor="#D1E3F6" />
<DividerVertical />
<ProgressBar color="#1DA1F2" progress={0.33} style={styles.two} trackColor="#D1E3F6" />
</View>;
const styles = StyleSheet.create({
one: {
borderRadius: 10,
height: 10
},
two: {
borderRadius: 10,
height: 20
}
});
export default ProgressBarCustomSizeExample;

View File

@@ -0,0 +1,22 @@
/**
* @flow
*/
import React from 'react';
import { DividerVertical } from '../helpers';
import { ProgressBar, View } from 'react-native';
const ProgressBarColorExample = () =>
<View>
<ProgressBar color="#1DA1F2" progress={0.2} />
<DividerVertical />
<ProgressBar color="#17BF63" progress={0.4} />
<DividerVertical />
<ProgressBar color="#F45D22" progress={0.6} />
<DividerVertical />
<ProgressBar color="#794BC4" progress={0.8} />
<DividerVertical />
<ProgressBar color="#E0245E" progress={1.0} />
</View>;
export default ProgressBarColorExample;

View File

@@ -0,0 +1,10 @@
/**
* @flow
*/
import React from 'react';
import { ProgressBar } from 'react-native';
const ProgressBarIndeterminateExample = () => <ProgressBar indeterminate trackColor="#D1E3F6" />;
export default ProgressBarIndeterminateExample;

View File

@@ -0,0 +1,48 @@
/**
* @flow
*/
import { DividerVertical } from '../helpers';
import React, { PureComponent } from 'react';
import { ProgressBar, StyleSheet, View } from 'react-native';
class ProgressBarProgressExample extends PureComponent {
state = { progress: 0 };
componentDidMount() {
this._updateProgress();
}
componentWillUnmount() {
window.cancelAnimationFrame(this._frame);
}
render() {
return (
<View>
<ProgressBar color="#794BC4" progress={0.2} style={styles.progress} />
<DividerVertical />
<ProgressBar color="#794BC4" progress={this._getProgress(0.2)} style={styles.progress} />
</View>
);
}
_getProgress(offset) {
const progress = this.state.progress + offset;
return Math.sin(progress % Math.PI) % 1;
}
_updateProgress() {
const progress = this.state.progress + 0.01;
this.setState(() => ({ progress }));
this._frame = window.requestAnimationFrame(() => this._updateProgress());
}
}
const styles = StyleSheet.create({
progress: {
minWidth: 200
}
});
export default ProgressBarProgressExample;

View File

@@ -0,0 +1,18 @@
/**
* @flow
*/
import { DividerVertical } from '../helpers';
import React from 'react';
import { ProgressBar, View } from 'react-native';
const ProgressBarTrackColorExample = () =>
<View>
<ProgressBar color="#1DA1F2" progress={0.1} trackColor="#17BF63" />
<DividerVertical />
<ProgressBar color="#1DA1F2" progress={0.2} trackColor="#F45D22" />
<DividerVertical />
<ProgressBar color="#1DA1F2" progress={0.3} trackColor="#794BC4" />
</View>;
export default ProgressBarTrackColorExample;

View File

@@ -0,0 +1,20 @@
/**
* @flow
*/
import React from 'react';
import { StyleSheet, View } from 'react-native';
const DividerHorizontal = () => <View style={styles.horizontalDivider} />;
const DividerVertical = () => <View style={styles.verticalDivider} />;
const styles = StyleSheet.create({
horizontalDivider: {
width: '0.6rem'
},
verticalDivider: {
height: '1.3125rem'
}
});
export { DividerHorizontal, DividerVertical };

View File

@@ -0,0 +1,171 @@
/* eslint-disable react/jsx-no-bind, react/jsx-sort-props */
/**
* @flow
*/
import { HorizontalExample } from './examples/Horizontal';
import ScrollToExample from './examples/ScrollTo';
import ScrollToEndExample from './examples/ScrollToEnd';
import React from 'react';
import UIExplorer, {
AppText,
Code,
Description,
DocItem,
Section,
storiesOf,
TextList
} from '../../ui-explorer';
const ScrollViewScreen = () =>
<UIExplorer title="ScrollView" url="components/ScrollView">
<Description>
<AppText>
A scrollable <Code>View</Code> that provides itegration with the touch-locking responder
system. <Code>ScrollView</Code>'s must have a bounded height: either set the height of the
view directly (discouraged) or make sure all parent views have bounded height (e.g.,
transfer <Code>{'{ flex: 1}'}</Code> down the view stack).
</AppText>
</Description>
<Section title="Props">
<DocItem name="...View props" />
<DocItem
name="contentContainerStyle"
typeInfo="?style"
description="These styles will be applied to the scroll view content container which wraps all of the child views."
/>
<DocItem
name="horizontal"
typeInfo="?boolean = false"
description="When true, the scroll view's children are arranged horizontally in a row instead of vertically in a column."
example={{
render: () => <HorizontalExample />
}}
/>
<DocItem
name="keyboardDismissMode"
typeInfo="?enum('none', 'on-drag') = 'none'"
description={[
<AppText>
Determines whether the keyboard gets dismissed in response to a scroll drag.
</AppText>,
<TextList
items={[
<AppText>
<Code>none</Code> (the default): drags do not dismiss the keyboard.
</AppText>,
<AppText>
<Code>on-drag</Code>: the keyboard is dismissed when a drag begins.
</AppText>,
<AppText>
<Code>interactive</Code> (not supported on web; same as <Code>none</Code>)
</AppText>
]}
/>
]}
/>
<DocItem
name="onContentSizeChange"
typeInfo="?function"
description={
<AppText>
Called when scrollable content view of the <Code>ScrollView</Code> changes. It's
implemented using the <Code>onLayout</Code> handler attached to the content container
which this <Code>ScrollView</Code> renders.
</AppText>
}
/>
<DocItem
name="onScroll"
typeInfo="?function"
description={[
<AppText>
Fires at most once per frame during scrolling. The frequency of the events can be
contolled using the <Code>scrollEventThrottle</Code> prop.
</AppText>,
<AppText>Invoked on scroll with the following event:</AppText>,
<Code>{`{
nativeEvent: {
contentOffset: { x, y },
contentSize: { height, width },
layoutMeasurement: { height, width }
}
}`}</Code>
]}
/>
<DocItem
name="scrollEnabled"
typeInfo="?boolean = true"
description="When false, the content does not scroll."
/>
<DocItem
name="scrollEventThrottle"
typeInfo="?number = 0"
description={
<AppText>
This controls how often the scroll event will be fired while scrolling (as a time
interval in ms). A lower number yields better accuracy for code that is tracking the
scroll position, but can lead to scroll performance problems. The default value is{' '}
<Code>0</Code>, which means the scroll event will be sent only once each time the view
is scrolled.
</AppText>
}
/>
</Section>
<Section title="Instance methods">
<DocItem
name="getInnerViewNode"
typeInfo="() => node"
description="Returns a reference to the underlying content container DOM node within the ScrollView."
/>
<DocItem
name="getScrollableNode"
typeInfo="() => node"
description="Returns a reference to the underlying scrollable DOM node."
/>
<DocItem
name="getScrollResponder"
typeInfo="() => ScrollResponder"
description={
<AppText>
Returns a reference to the underlying scroll responder, which supports operations like{' '}
<Code>scrollTo</Code>. All <Code>ScrollView</Code>-like components should implement this
method so that they can be composed while providing access to the underlying scroll
responder's methods.
</AppText>
}
/>
<DocItem
name="scrollTo"
typeInfo="(options: { x: number = 0; y: number = 0; animated: boolean = true }) => void"
description="Scrolls to a given `x`, `y` offset (animation is not currently supported)."
example={{
render: () => <ScrollToExample />
}}
/>
<DocItem
name="scrollToEnd"
typeInfo="(options: { animated: boolean = true }) => void"
description="Scrolls to the end of the scroll view."
example={{
render: () => <ScrollToEndExample />
}}
/>
</Section>
</UIExplorer>;
storiesOf('Components', module).add('ScrollView', ScrollViewScreen);

View File

@@ -0,0 +1,70 @@
/* eslint-disable react/jsx-no-bind */
/**
* @flow
*/
import React from 'react';
import { ScrollView, StyleSheet, Text, View } from 'react-native';
const onScroll = () => {
console.log('ScrollView.onScroll');
};
const VerticalExample = () =>
<View style={styles.scrollViewContainer}>
<ScrollView
contentContainerStyle={styles.scrollViewContentContainerStyle}
onScroll={onScroll}
scrollEventThrottle={16} // ~60 events per second
style={styles.scrollViewStyle}
>
{Array.from({ length: 50 }).map((item, i) =>
<View key={i} style={[styles.box, styles.horizontalBox]}>
<Text>
{i}
</Text>
</View>
)}
</ScrollView>
</View>;
const HorizontalExample = () =>
<View style={styles.scrollViewContainer}>
<ScrollView
contentContainerStyle={styles.scrollViewContentContainerStyle}
horizontal
onScroll={onScroll}
scrollEventThrottle={16} // ~60 events per second
style={styles.scrollViewStyle}
>
{Array.from({ length: 50 }).map((item, i) =>
<View key={i} style={[styles.box, styles.horizontalBox]}>
<Text>
{i}
</Text>
</View>
)}
</ScrollView>
</View>;
export { HorizontalExample, VerticalExample };
const styles = StyleSheet.create({
box: {
flexGrow: 1,
justifyContent: 'center',
borderWidth: 1
},
scrollViewContainer: {
height: 200,
width: 300
},
scrollViewStyle: {
borderWidth: 1
},
scrollViewContentContainerStyle: {
backgroundColor: '#eee',
padding: 10
}
});

View File

@@ -0,0 +1,63 @@
/* eslint-disable react/jsx-no-bind */
/**
* @flow
*/
import React, { PureComponent } from 'react';
import { Button, ScrollView, StyleSheet, Text, TouchableHighlight, View } from 'react-native';
export default class ScrollToExample extends PureComponent {
render() {
return (
<View style={styles.scrollViewContainer}>
<ScrollView
contentContainerStyle={styles.scrollViewContentContainerStyle}
ref={scrollview => {
this.scrollview = scrollview;
}}
scrollEventThrottle={16} // ~60 events per second
style={styles.scrollViewStyle}
>
{Array.from({ length: 50 }).map((item, i) =>
<TouchableHighlight
key={i}
onPress={() => {}}
style={[styles.box, styles.horizontalBox]}
>
<Text>
{i}
</Text>
</TouchableHighlight>
)}
</ScrollView>
<Button
onPress={() => {
this.scrollview.scrollTo({ y: 100 });
}}
title="Scroll to 100px"
/>
</View>
);
}
}
const styles = StyleSheet.create({
box: {
flexGrow: 1,
justifyContent: 'center',
borderWidth: 1
},
scrollViewContainer: {
height: 150,
width: 300
},
scrollViewStyle: {
borderWidth: 1,
marginBottom: '1.3125rem'
},
scrollViewContentContainerStyle: {
backgroundColor: '#eee',
padding: 10
}
});

View File

@@ -0,0 +1,59 @@
/* eslint-disable react/jsx-no-bind */
/**
* @flow
*/
import React, { PureComponent } from 'react';
import { Button, ScrollView, StyleSheet, Text, View } from 'react-native';
export default class ScrollToEndExample extends PureComponent {
render() {
return (
<View style={styles.scrollViewContainer}>
<ScrollView
contentContainerStyle={styles.scrollViewContentContainerStyle}
ref={scrollview => {
this.scrollview = scrollview;
}}
scrollEventThrottle={16} // ~60 events per second
style={styles.scrollViewStyle}
>
{Array.from({ length: 50 }).map((item, i) =>
<View key={i} style={[styles.box, styles.horizontalBox]}>
<Text>
{i}
</Text>
</View>
)}
</ScrollView>
<Button
onPress={() => {
this.scrollview.scrollToEnd();
}}
title="Scroll to end"
/>
</View>
);
}
}
const styles = StyleSheet.create({
box: {
flexGrow: 1,
justifyContent: 'center',
borderWidth: 1
},
scrollViewContainer: {
height: 150,
width: 300
},
scrollViewStyle: {
borderWidth: 1,
marginBottom: '1.3125rem'
},
scrollViewContentContainerStyle: {
backgroundColor: '#eee',
padding: 10
}
});

View File

@@ -0,0 +1,135 @@
/* eslint-disable react/jsx-sort-props */
/**
* @flow
*/
import CustomSize from './examples/CustomSize';
import PropActiveThumbColor from './examples/PropActiveThumbColor';
import PropActiveTrackColor from './examples/PropActiveTrackColor';
import PropDisabled from './examples/PropDisabled';
import PropOnValueChange from './examples/PropOnValueChange';
import PropThumbColor from './examples/PropThumbColor';
import PropTrackColor from './examples/PropTrackColor';
import PropValue from './examples/PropValue';
import React from 'react';
import UIExplorer, {
AppText,
Code,
Description,
DocItem,
Section,
storiesOf
} from '../../ui-explorer';
const SwitchScreen = () =>
<UIExplorer title="Switch" url="components/Switch">
<Description>
<AppText>
This is a controlled component that requires an <Code>onValueChange</Code> callback that
updates the value prop in order for the component to reflect user actions. If the{' '}
<Code>value</Code> prop is not updated, the component will continue to render the supplied{' '}
<Code>value</Code> prop instead of the expected result of any user actions.
</AppText>
</Description>
<Section title="Props">
<DocItem name="...View props" />
<DocItem
description="The color of the thumb grip when the switch is turned on."
example={{
render: () => <PropActiveThumbColor />
}}
name="activeThumbColor"
typeInfo="?color = #009688"
/>
<DocItem
description="The color of the track when the switch is turned on."
example={{
render: () => <PropActiveTrackColor />
}}
name="activeTrackColor"
typeInfo="?color = #A3D3CF"
/>
<DocItem
description="If true, the user won't be able to interact with the switch."
example={{
render: () => <PropDisabled />
}}
name="disabled"
typeInfo="?boolean = false"
/>
<DocItem
description="Invoked with the new value when the value changes."
example={{
render: () => <PropOnValueChange />
}}
name="onValueChange"
typeInfo="?function"
/>
<DocItem
description="The color of the thumb grip when the switch is turned off."
example={{
render: () => <PropThumbColor />
}}
name="thumbColor"
typeInfo="?color = #FAFAFA"
/>
<DocItem
description="The color of the track when the switch is turned off."
example={{
render: () => <PropTrackColor />
}}
name="trackColor"
typeInfo="?color = #939393"
/>
<DocItem
description="The value of the switch. If `true` the switch will be turned on."
example={{
render: () => <PropValue />
}}
name="value"
typeInfo="?boolean = false"
/>
<DocItem
description="(For compatibility with React Native. Equivalent to &quot;activeTrackColor&quot;)"
label="compat"
name="onTintColor"
typeInfo="?color"
/>
<DocItem
description="(For compatibility with React Native. Equivalent to &quot;trackColor&quot;)"
label="compat"
name="tintColor"
typeInfo="?color"
/>
<DocItem
description="(For compatibility with React Native. Equivalent to &quot;thumbColor&quot;)"
label="compat"
name="thumbTintColor"
typeInfo="?color"
/>
</Section>
<Section title="More examples">
<DocItem
description="Custom sizes can be created using styles"
example={{
code: '<Switch style={{ height: 30 }} />',
render: () => <CustomSize />
}}
/>
</Section>
</UIExplorer>;
storiesOf('Components', module).add('Switch', SwitchScreen);

View File

@@ -0,0 +1,42 @@
/**
* @flow
*/
import React, { PureComponent } from 'react';
import { Switch, View } from 'react-native';
class CustomSizeExample extends PureComponent {
state = {
firstIsOn: true,
secondIsOn: false
};
render() {
const { firstIsOn, secondIsOn } = this.state;
return (
<View>
<Switch
onValueChange={this._handleFirst}
style={{ marginBottom: 10, height: 30 }}
value={firstIsOn}
/>
<Switch
onValueChange={this._handleSecond}
style={{ height: 30, width: 150 }}
value={secondIsOn}
/>
</View>
);
}
_handleFirst = value => {
this.setState({ firstIsOn: value });
};
_handleSecond = value => {
this.setState({ secondIsOn: value });
};
}
export default CustomSizeExample;

View File

@@ -0,0 +1,24 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { Switch, View } from 'react-native';
const colors = ['#1DA1F2', '#17BF63', '#F45D22', '#794BC4', '#E0245E'];
const itemStyle = [styles.marginVertical, styles.marginRight];
const SwitchActiveThumbColorExample = () =>
<View style={styles.row}>
<View style={itemStyle}>
<Switch value={true} />
</View>
{colors.map((color, i) =>
<View key={i} style={itemStyle}>
<Switch activeThumbColor={color} activeTrackColor="#ccc" value={true} />
</View>
)}
</View>;
export default SwitchActiveThumbColorExample;

View File

@@ -0,0 +1,24 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { Switch, View } from 'react-native';
const colors = ['#1DA1F2', '#17BF63', '#F45D22', '#794BC4', '#E0245E'];
const itemStyle = [styles.marginVertical, styles.marginRight];
const SwitchActiveTrackColorExample = () =>
<View style={styles.row}>
<View style={itemStyle}>
<Switch value={true} />
</View>
{colors.map((color, i) =>
<View key={i} style={itemStyle}>
<Switch activeThumbColor="#ccc" activeTrackColor={color} value={true} />
</View>
)}
</View>;
export default SwitchActiveTrackColorExample;

Some files were not shown because too many files have changed in this diff Show More