Compare commits

..

1 Commits

Author SHA1 Message Date
Nicolas Gallagher
a6f8c111af Preact benchmarks 2017-04-22 11:45:56 -07:00
414 changed files with 9337 additions and 18848 deletions

8
.babelrc Normal file
View File

@@ -0,0 +1,8 @@
{
"presets": [
"react-native"
],
"plugins": [
[ "transform-react-remove-prop-types", { "mode": "wrap" } ]
]
}

9
.editorconfig Normal file
View File

@@ -0,0 +1,9 @@
# EditorConfig: http://editorconfig.org
root = true
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2

View File

@@ -24,16 +24,7 @@
"globals": {
"document": false,
"navigator": false,
"window": false,
// Flow global types
"HTMLInputElement": false,
"ReactClass": false,
"ReactComponent": false,
"ReactElement": false,
"ReactPropsChainableTypeChecker": false,
"ReactPropsCheckType": false,
"ReactPropTypes": false,
"SyntheticEvent": false
"window": false
},
"rules": {
"camelcase": 0,
@@ -129,6 +120,9 @@
// react
"react/display-name": 0,
"react/jsx-handler-names": [2, {
"eventHandlerPrefix": "_handle"
}],
"react/jsx-no-bind": 2,
"react/jsx-no-duplicate-props": 2,
"react/jsx-no-undef": 2,

View File

@@ -1,14 +0,0 @@
[ignore]
.*/__tests__/.*
.*/benchmarks/.*
.*/docs/.*
.*/node_modules/animated/*
.*/node_modules/babel-plugin-transform-react-remove-prop-types/*
[include]
[libs]
types
[options]
unsafe.enable_getters_and_setters=true

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
node_modules
dist
dist-examples

View File

@@ -5,5 +5,4 @@ before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
script:
- npm run lint
- npm test

View File

@@ -6,7 +6,7 @@ Before opening an issue, please search the [issue
tracker](https://github.com/necolas/react-native-web/issues) to make sure your
issue hasn't already been reported.
## Getting started
## Development
Visit the [Issue tracker](https://github.com/necolas/react-native-web/issues)
to find a list of open issues that need attention.
@@ -23,79 +23,48 @@ Install dependencies (requires [yarn](https://yarnpkg.com/en/docs/install):
yarn
```
## Automated tests
To run flow:
Run the examples:
```
yarn flow
npm run examples
```
To run the unit tests:
Run the benchmarks in a browser by opening `./performance/index.html` after running:
```
yarn jest
npm run build:performance
```
…in watch mode:
### Building
```
yarn jest:watch
npm run build
```
To run all automated tests:
To create a UMD build:
```
yarn test
npm run build:umd
```
## Visual tests
### Testing and Linting
To run the interactive storybook:
To run the tests:
```
yarn docs:start
npm run test
```
To generate a static build of the storybook:
To continuously watch and run tests, run the following:
```
yarn docs:build
npm run test:watch
```
To run the performance benchmarks in a browser (opening `./benchmarks/index.html`):
To perform only linting, run the following:
```
yarn benchmark
```
## Compile and build
To compile the source code to `dist`:
```
yarn compile
```
To create a UMD bundle of the library:
```
yarn build
```
### Pre-commit
To format and lint code before commit:
```
yarn precommit
```
To format and lint the entire project:
```
yarn fmt
yarn lint
npm run lint
```
### New Features
@@ -112,10 +81,8 @@ that we won't want to accept.
* Make sure all tests pass and there are no linting errors.
* Submit a pull request, referencing any issues it addresses.
Please try to keep your pull request focused in scope and avoid including
unrelated commits.
Please try to keep your pull request focused in scope and avoid including unrelated commits.
After you have submitted your pull request, we'll try to get back to you as
soon as possible. We may suggest some changes or improvements.
After you have submitted your pull request, we'll try to get back to you as soon as possible. We may suggest some changes or improvements.
Thank you for contributing!

View File

@@ -16,39 +16,88 @@ Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
## Overview
"React Native for Web" is a project to bring React Native's building blocks and
touch handling to the Web.
touch handling to the Web. [Read more](#why).
Browse the [UI Explorer](https://necolas.github.io/react-native-web/storybook/)
to see React Native examples running on Web. Or remix the [React Native for
Web: Playground](https://glitch.com/edit/#!/react-native-web-playground) on
Glitch.
Browse the UI Explorer to see React Native [examples running on
Web](https://necolas.github.io/react-native-web/storybook/). Or try it out
online with [React Native for Web: Playground](https://www.webpackbin.com/bins/-KgucwxRbn7HRU-V-3Bc).
## Quick start
To install in your app:
```
npm install --save react@15.6 react-dom@15.6 react-native-web
npm install --save react@15.4 react-dom@15.4 react-native-web
```
NOTE: React Native for Web supports React/ReactDOM 15.4, 15.5, or 15.6.
Read the [Getting Started](docs/guides/getting-started.md) guide.
Then read the [Getting Started](docs/guides/getting-started.md) guide.
Alternatively, you can quickly setup a local project
using [create-react-app](https://github.com/facebookincubator/create-react-app)
(which supports `react-native-web` out-of-the-box once installed) and
[react-native-web-starter](https://github.com/grabcode/react-native-web-starter).
## Documentation
The [UI Explorer](https://necolas.github.io/react-native-web/storybook/)
interactively documents all the APIs and Components.
Guides:
* [Getting started](docs/guides/getting-started.md)
* [Style](docs/guides/style.md)
* [Accessibility](docs/guides/accessibility.md)
* [Direct manipulation](docs/guides/direct-manipulation.md)
* [Internationalization](docs/guides/internationalization.md)
* [Advanced use](docs/guides/advanced.md)
* [Known issues](docs/guides/known-issues.md)
* [Style](docs/guides/style.md)
Exported modules:
* Components
* [`ActivityIndicator`](docs/components/ActivityIndicator.md)
* [`Button`](docs/components/Button.md)
* [`Image`](docs/components/Image.md)
* [`ListView`](docs/components/ListView.md)
* [`ProgressBar`](docs/components/ProgressBar.md)
* [`ScrollView`](docs/components/ScrollView.md)
* [`Switch`](docs/components/Switch.md)
* [`Text`](docs/components/Text.md)
* [`TextInput`](docs/components/TextInput.md)
* [`TouchableHighlight`](http://facebook.github.io/react-native/releases/0.22/docs/touchablehighlight.html) (mirrors React Native)
* [`TouchableOpacity`](http://facebook.github.io/react-native/releases/0.22/docs/touchableopacity.html) (mirrors React Native)
* [`TouchableWithoutFeedback`](docs/components/TouchableWithoutFeedback.md)
* [`View`](docs/components/View.md)
* APIs
* [`Animated`](http://facebook.github.io/react-native/releases/0.20/docs/animated.html) (mirrors React Native)
* [`AppRegistry`](docs/apis/AppRegistry.md)
* [`AppState`](docs/apis/AppState.md)
* [`AsyncStorage`](docs/apis/AsyncStorage.md)
* [`Clipboard`](docs/apis/Clipboard.md)
* [`Dimensions`](docs/apis/Dimensions.md)
* [`I18nManager`](docs/apis/I18nManager.md)
* [`NativeMethods`](docs/apis/NativeMethods.md)
* [`NetInfo`](docs/apis/NetInfo.md)
* [`PanResponder`](http://facebook.github.io/react-native/releases/0.20/docs/panresponder.html#content) (mirrors React Native)
* [`PixelRatio`](docs/apis/PixelRatio.md)
* [`Platform`](docs/apis/Platform.md)
* [`StyleSheet`](docs/apis/StyleSheet.md)
* [`Vibration`](docs/apis/Vibration.md)
<span id="#why"></span>
## Why?
There are many different teams at Twitter building web applications with React.
We want to share React components, libraries, and APIs between teams…much like
the OSS community tries to do. At our scale, this involves dealing with
multiple, inter-related problems including: a common way to handle style,
animation, touch, viewport adaptation, accessibility, themes, RTL layout, and
server-rendering.
This is hard to do with React DOM, as the components are essentially the same
low-level building blocks that the browser provides. However, React Native
avoids, solves, or can solve almost all these problems facing Web teams.
Central to this is React Native's JavaScript style API (not strictly
"CSS-in-JS") which avoids the key [problems with
CSS](https://speakerdeck.com/vjeux/react-css-in-js) by giving up some of the
complexity of CSS.
## Example code
@@ -91,16 +140,10 @@ AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-ro
## Related projects
* [react-primitives](https://github.com/lelandrichardson/react-primitives/)
* [react-sketchapp](https://github.com/airbnb/react-sketchapp)
* [reactxp](https://github.com/microsoft/reactxp)
* [react-native-web-player](https://github.com/dabbott/react-native-web-player)
## Start kits
* [create-react-app](https://github.com/facebookincubator/create-react-app) ([on Glitch](https://glitch.com/edit/#!/react-native-web-playground))
* [react-native-web-starter](https://github.com/grabcode/react-native-web-starter)
* [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack)
* [react-native-web-player](https://github.com/dabbott/react-native-web-player)
* [reactxp](https://github.com/microsoft/reactxp)
* [react-web](https://github.com/taobaofed/react-web)
## License

View File

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

View File

@@ -1,22 +0,0 @@
{
"name": "benchmarks",
"private": true,
"dependencies": {
"aphrodite": "^1.2.3",
"classnames": "^2.2.5",
"glamor": "^3.0.0-3",
"marky": "^1.2.0",
"radium": "^0.19.1",
"react-jss": "^7.0.1",
"react-primitives": "^0.4.3",
"reactxp": "0.34.3",
"styled-components": "^2.1.1",
"styletron-client": "^2.5.7",
"styletron-utils": "^2.5.4"
},
"devDependencies": {
"css-loader": "^0.28.4",
"react-addons-perf": "^15.4.2",
"style-loader": "^0.18.2"
}
}

View File

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

View File

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

View File

@@ -1,13 +0,0 @@
/* eslint-disable react/prop-types */
import classnames from 'classnames';
import React from 'react';
import styles from './styles.css';
class View extends React.Component {
render() {
const props = this.props;
return <div {...props} className={classnames(styles.initial, props.className)} />;
}
}
export default View;

View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
module.exports = require('./dist/core');
module.exports = require('./dist/core')

View File

@@ -3,7 +3,8 @@
`AppRegistry` is the control point for registering, running, prerendering, and
unmounting all apps. App root components should register themselves with
`AppRegistry.registerComponent`. Apps can be run by invoking
`AppRegistry.runApplication` (see the [getting started guide](../guides/getting-started.md) for more details).
`AppRegistry.runApplication` (see the [client and server rendering
guide](../guides/rendering.md) for more details).
To "stop" an application when a view should be destroyed, call
`AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was passed
@@ -14,7 +15,8 @@ into `runApplication`. These should always be used as a pair.
(web) static **getApplication**(appKey:string, appParameters: object)
Returns the given application element. Use this for server-side rendering.
Return object is of type `{ element: ReactElement; stylesheets: [ ReactElement ] }`.
Return object is of type `{ element: ReactElement; stylesheet: ReactElement }`.
It's recommended that you use `sheetsheet` to render the style sheet in an app
static **registerConfig**(config: Array<AppConfig>)
@@ -40,9 +42,6 @@ Runs the application that was registered under `appKey`. The `appParameters`
must include the `rootTag` into which the application is rendered, and
optionally any `initialProps`.
On web, if the `rootTag` is a sub-section of your application it should be
styled as `position:relative` and given an explicit height.
static **unmountApplicationComponentAtRootTag**(rootTag: HTMLElement)
To "stop" an application when a view should be destroyed, call

View File

@@ -0,0 +1,42 @@
# NativeMethods
React Native for Web provides several methods to directly access the underlying
DOM node. This can be useful in cases when you want to focus a view or measure
its on-screen dimensions, for example.
The methods described are available on most of the default components provided
by React Native for Web. Note, however, that they are *not* available on the
composite components that you define in your own app. For more information, see
[Direct Manipulation](../guides/direct-manipulation.md).
## Methods
**blur**()
Removes focus from an input or view. This is the opposite of `focus()`.
**focus**()
Requests focus for the given input or view. The exact behavior triggered will
depend the type of view.
**measure**(callback: (x, y, width, height, pageX, pageY) => void)
For a given view, `measure` determines the offset relative to the parent view,
width, height, and the offset relative to the viewport. Returns the values via
an async callback.
Note that these measurements are not available until after the rendering has
been completed.
**measureLayout**(relativeToNativeNode: DOMNode, onSuccess: (x, y, width, height) => void)
Like `measure`, but measures the view relative to another view, specified as
`relativeToNativeNode`. This means that the returned `x`, `y` are relative to
the origin `x`, `y` of the ancestor view.
**setNativeProps**(nativeProps: Object)
This function sends props straight to the underlying DOM node. See the [direct
manipulation](../guides/direct-manipulation.md) guide for cases where
`setNativeProps` should be used.

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. Use this if you are only interested with whether the device has internet connectivity.
internet connectivity.
**isConnected.addEventListener**(eventName: ChangeEventName, handler: Function)

View File

@@ -1,10 +1,9 @@
# StyleSheet
The `StyleSheet` abstraction converts predefined styles to (vendor-prefixed)
CSS without requiring a compile-time step. Styles that cannot be resolved
outside of the render loop (e.g., dynamic positioning) are usually applied as
inline styles. Read more about [how to style your
application](../guides/style.md).
CSS without requiring a compile-time step. Some styles cannot be resolved
outside of the render loop and are applied as inline styles. Read more about
[how to style your application](../guides/style.md).
## Methods
@@ -16,10 +15,9 @@ Each key of the object passed to `create` must define a style object.
Flattens an array of styles into a single style object.
(web) **getStyleSheets**: function
**renderToString**: function
Returns an array of stylesheets (`{ id, textContent }`). Useful for
compile-time or server-side rendering.
Returns a string of the stylesheet for use in server-side rendering.
## Properties

View File

@@ -23,7 +23,7 @@ If `true`, disable all interactions for this element.
This function is called on press.
**testID**: ?string
testID: ?string
Used to locate this view in end-to-end tests.

View File

@@ -0,0 +1,34 @@
# ListView
TODO
## Props
[...ScrollView props](./ScrollView.md)
**children**: any
Content to display over the image.
**style**: style
+ ...[View#style](View.md)
## Examples
```js
import React, { Component, PropTypes } from 'react'
import { ListView } from 'react-native'
export default class ListViewExample extends Component {
static propTypes = {}
static defaultProps = {}
render() {
return (
<ListView />
)
}
}
```

View File

@@ -103,11 +103,8 @@ Callback that is called when the text input is focused.
**onKeyPress**: ?function
Callback that is called when a key is pressed. This will be called with `{
nativeEvent: { key: keyValue } }` where keyValue is 'Enter` or 'Backspace' for
respective keys and the typed-in character otherwise including ' ' for space.
Modifier keys are also included in the nativeEvent. Fires before onChange
callbacks.
Callback that is called when a key is pressed. Pressed key value is passed as
an argument to the callback handler. Fires before `onChange` callbacks.
**onSelectionChange**: ?function

View File

@@ -18,7 +18,7 @@ NOTE: `View` will transfer all other props to the rendered HTML element.
Overrides the text that's read by a screen reader when the user interacts
with the element. (This is implemented using `aria-label`.)
See the [Accessibility guide](../guides/accessibility.md) for more information.
See the [Accessibility guide](../guides/accessibility) for more information.
**accessibilityLiveRegion**: ?enum('assertive', 'none', 'polite')
@@ -29,7 +29,7 @@ priority. When regions are specified as `assertive`, assistive technologies
will interrupt and immediately notify the user. (This is implemented using
[`aria-live`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-live).)
See the [Accessibility guide](../guides/accessibility.md) for more information.
See the [Accessibility guide](../guides/accessibility) for more information.
(web) **accessibilityRole**: ?enum(roles)
@@ -38,7 +38,7 @@ in a manner that is consistent with user expectations for similar views of that
type. For example, marking a touchable view with an `accessibilityRole` of
`button`. (This is implemented using [ARIA roles](http://www.w3.org/TR/wai-aria/roles#role_definitions)).
See the [Accessibility guide](../guides/accessibility.md) for more information.
See the [Accessibility guide](../guides/accessibility) for more information.
**accessible**: ?boolean
@@ -47,7 +47,7 @@ focusable) and groups its child content. By default, all the touchable elements
and elements with `accessibilityRole` of `button` and `link` are accessible.
(This is implemented using `tabindex`.)
See the [Accessibility guide](../guides/accessibility.md) for more information.
See the [Accessibility guide](../guides/accessibility) for more information.
**children**: ?element
@@ -69,7 +69,7 @@ A value of `no` will remove the element from the tab flow.
A value of `no-hide-descendants` will hide the element and its children from
assistive technologies. (This is implemented using `aria-hidden`.)
See the [Accessibility guide](../guides/accessibility.md) for more information.
See the [Accessibility guide](../guides/accessibility) for more information.
**onLayout**: ?function
@@ -132,15 +132,15 @@ Controls whether the View can be the target of touch events. The enhanced
`box-none` is the equivalent of:
```css
.box-none { pointer-events: none !important; }
.box-none > * { pointer-events: auto; }
.box-none { pointer-events: none }
.box-none * { pointer-events: auto }
```
`box-only` is the equivalent of:
```css
.box-only { pointer-events: auto !important; }
.box-only > * { pointer-events: none; }
.box-only { pointer-events: auto }
.box-only * { pointer-events: none }
```
**style**: ?style
@@ -158,7 +158,6 @@ Controls whether the View can be the target of touch events. The enhanced
+ `animationTimingFunction`
+ `backfaceVisibility`
+ `backgroundAttachment`
+ `backgroundBlendMode`
+ `backgroundClip`
+ `backgroundColor`
+ `backgroundImage`
@@ -280,7 +279,7 @@ Default:
};
```
(See [facebook/yoga](https://github.com/facebook/yoga)).
(See [facebook/css-layout](https://github.com/facebook/css-layout)).
**testID**: ?string

View File

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

View File

@@ -1,104 +0,0 @@
# Advanced use
## Use with existing React DOM components
React Native for Web exports a web-specific module called `createDOMElement`,
which can be used to wrap React DOM components. This allows you to use React
Native's accessibility and style optimizations.
In the example below, `Video` will now accept common React Native props such as
`accessibilityLabel`, `accessible`, `style`, and even the Responder event
props.
```js
import { createDOMElement } from 'react-native';
const Video = (props) => createDOMElement('video', props);
```
This also works with composite components defined in your existing component
gallery or dependencies ([live example](https://www.webpackbin.com/bins/-KiTSGFw3fB9Szg7quLI)).
```js
import RaisedButton from 'material-ui/RaisedButton';
import { createDOMElement, StyleSheet } from 'react-native';
const CustomButton = (props) => createDOMElement(RaisedButton, {
...props,
style: [ styles.button, props.style ]
});
const styles = StyleSheet.create({
button: {
padding: 20
}
});
```
Remember that React Native styles are not the same as React DOM styles, and
care needs to be taken not to pass React DOM styles into your React Native
wrapped components.
## Use as a library framework
The React Native (for Web) building blocks can be used to create higher-level
components and abstractions. In the example below, a `styled` function provides
an API inspired by styled-components ([live
example](https://www.webpackbin.com/bins/-KjT9ziwv4O7FDZdvsnX)).
```js
const { createDOMElement, StyleSheet } = ReactNative;
/**
* styled API
*/
const styled = (Component, styler) => {
const isDOMComponent = typeof Component === 'string';
class Styled extends React.Component {
static contextTypes = {
getTheme: React.PropTypes.func
};
render() {
const theme = this.context.getTheme && this.context.getTheme();
const localProps = { ...this.props, theme };
const nextProps = { ...this.props }
const style = typeof styler === 'function' ? styler(localProps) : styler;
nextProps.style = [ style, this.props.style ];
return (
isDOMComponent
? createDOMElement(Component, nextProps)
: <Component {...nextProps} />
);
}
}
return Styled;
}
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#2196F3',
flex: 1,
justifyContent: 'center'
}
});
const StyledView = styled(View, styles.container);
```
## Use with react-sketchapp
Use with [react-sketchapp](http://airbnb.io/react-sketchapp/) requires that you
alias `react-native` to `react-sketchapp`. This will allow you to render your
existing React Native components in Sketch. Sketch-specific components like
`Artboard` should be imported from `react-sketchapp`.
If you're using `skpm`, you can rely on an [undocumented
feature](https://github.com/sketch-pm/skpm/blob/master/lib/utils/webpackConfig.js)
which will merge your `webpack.config.js`, `.babelrc`, or `package.json` Babel
config into its internal webpack config. The simplest option may be to use the
[babel-plugin-module-alias](https://www.npmjs.com/package/babel-plugin-module-alias)
and configure it in your `package.json`.

View File

@@ -1,68 +1,27 @@
# Direct manipulation
React Native for Web provides several methods to directly access the underlying
DOM node. This can be useful when you need to make changes directly to a
component without using state/props to trigger a re-render of the entire
subtree, or when you want to focus a view or measure its on-screen dimensions.
It is sometimes necessary to make changes directly to a component without using
state/props to trigger a re-render of the entire subtree in the browser, this
is done by directly modifying a DOM node. `setNativeProps` is the React Native
equivalent to setting properties directly on a DOM node. Use direct
manipulation when frequent re-rendering creates a performance bottleneck. Direct
manipulation will not be a tool that you reach for frequently.
The methods described are available on most of the default components provided
by React Native for Web. Note, however, that they are *not* available on the
composite components that you define in your own app.
## Instance methods
**blur**()
Removes focus from an input or view. This is the opposite of `focus()`.
**focus**()
Requests focus for the given input or view. The exact behavior triggered will
depend the type of view.
**measure**(callback: (x, y, width, height, pageX, pageY) => void)
For a given view, `measure` determines the offset relative to the parent view,
width, height, and the offset relative to the viewport. Returns the values via
an async callback.
Note that these measurements are not available until after the rendering has
been completed.
**measureLayout**(relativeToNativeNode: DOMNode, onSuccess: (x, y, width, height) => void)
Like `measure`, but measures the view relative to another view, specified as
`relativeToNativeNode`. This means that the returned `x`, `y` are relative to
the origin `x`, `y` of the ancestor view.
**setNativeProps**(nativeProps: Object)
This function sends props straight to the underlying DOM node. See the [direct
manipulation](../guides/direct-manipulation.md) guide for cases where
`setNativeProps` should be used.
## About `setNativeProps`
`setNativeProps` is the React Native equivalent to setting properties directly
on a DOM node. Use direct manipulation when frequent re-rendering creates a
performance bottleneck. Direct manipulation will not be a tool that you reach
for frequently.
### `setNativeProps` and `shouldComponentUpdate`
## `setNativeProps` and `shouldComponentUpdate`
`setNativeProps` is imperative and stores state in the native layer (DOM,
UIView, etc.) and not within your React components, which makes your code more
difficult to reason about. Before you use it, try to solve your problem with
`setState` and `shouldComponentUpdate`.
### Avoiding conflicts with the render function
## Avoiding conflicts with the render function
If you update a property that is also managed by the render function, you might
end up with some unpredictable and confusing bugs because anytime the component
re-renders and that property changes, whatever value was previously set from
`setNativeProps` will be completely ignored and overridden.
### Why use `setNativeProps` on Web?
## Why use `setNativeProps` on Web?
Using `setNativeProps` in web-specific code is required when making changes to
`className` or `style`, as these properties are controlled by React Native for
@@ -76,7 +35,7 @@ setOpacityTo(value) {
}
```
### Composite components and `setNativeProps`
## Composite components and `setNativeProps`
Composite components are not backed by a DOM node, so you cannot call
`setNativeProps` on them. Consider this example:
@@ -104,7 +63,7 @@ prop on it and have that work - you would need to pass the style prop down to a
child, unless you are wrapping a native component. Similarly, we are going to
forward `setNativeProps` to a native-backed child component.
### Forward `setNativeProps` to a child
## Forward `setNativeProps` to a child
All we need to do is provide a `setNativeProps` method on our component that
calls `setNativeProps` on the appropriate child with the given arguments.
@@ -127,7 +86,7 @@ class MyButton extends React.Component {
You can now use `MyButton` inside of `TouchableOpacity`!
### `setNativeProps` to clear `TextInput` value
## `setNativeProps` to clear `TextInput` value
Another very common use case of `setNativeProps` is to clear the value of a
`TextInput`. For example, the following code demonstrates clearing the input

View File

@@ -1,20 +1,11 @@
# Getting started
This guide will help you to correctly configure build and test tools to work
with React Native for Web.
Alternatively, you can quickly setup a local project using
[create-react-app](https://github.com/facebookincubator/create-react-app)
(which supports `react-native-web` out-of-the-box once installed),
[react-native-web-starter](https://github.com/grabcode/react-native-web-starter),
or [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack).
It is recommended that your application provide a `Promise` and `Array.from`
polyfill.
## Webpack and Babel
[Webpack](https://webpack.js.org) is a popular build tool for web apps. Below is an
[Webpack](webpack.js.org) is a popular build tool for web apps. Below is an
example of how to configure a build that uses [Babel](https://babeljs.io/) to
compile your JavaScript for the web.
@@ -70,7 +61,7 @@ module.exports = {
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
],
},
resolve: {
// Maps the 'react-native' import to 'react-native-web'.
@@ -117,26 +108,6 @@ if (Platform.OS === 'web') {
}
```
More significant platform differences should use platform-specific files (see
the webpack configuration above for resolving `*.web.js` files):
For example, with the following files in your project:
```
MyComponent.android.js
MyComponent.ios.js
MyComponent.web.js
```
And the following import:
```js
import MyComponent from './MyComponent';
```
React Native will automatically import the correct variant for each specific
target platform.
## Client-side rendering
Rendering using `ReactNative`:
@@ -169,8 +140,8 @@ AppRegistry.runApplication('App', {
})
```
Rendering within `ReactDOM.render` also works when introducing
`react-native-web` to an existing web app, but otherwise it is not recommended.
Rendering within `ReactDOM.render` also works when introduce `react-native-web`
to an existing web app, but it is not recommended oherwise.
## Server-side rendering
@@ -187,18 +158,6 @@ const AppContainer = (props) => { /* ... */ }
AppRegistry.registerComponent('App', () => AppContainer)
// prerender the app
const { element, stylesheets } = AppRegistry.getApplication('App', { initialProps });
const { element, stylesheet } = AppRegistry.getApplication('App', { initialProps });
const initialHTML = ReactDOMServer.renderToString(element);
const initialStyles = stylesheets.map((sheet) => ReactDOMServer.renderToStaticMarkup(sheet)).join('\n');
// construct HTML document
const document = `
<!DOCTYPE html>
<html>
<head>
${initialStyles}
</head>
<body>
${initialHTML}
`
```

View File

@@ -1,90 +1,73 @@
# Style
React Native relies on JavaScript to define and resolve the styles of your
application. React Native for Web implements the React Native style API in a
way that avoids *all* the [problems with CSS at
scale](https://speakerdeck.com/vjeux/react-css-in-js):
React Native for Web relies on JavaScript to define styles for your
application. This allows you to avoid issues arising from the [7 deadly sins of
CSS](https://speakerdeck.com/vjeux/react-css-in-js):
1. No local variables
2. Implicit dependencies
1. Global namespace
2. Dependency hell
3. No dead code elimination
4. No code minification
5. No sharing of constants
6. Non-deterministic resolution
7. No isolation
At the same time, it has several benefits:
1. Simple API and expressive subset of CSS
2. Generates CSS; the minimum required
3. Good runtime performance
4. Support for static and dynamic styles
5. Support for RTL layouts
6. Easy pre-rendering of critical CSS
7. Lack of isolation
## Defining styles
Styles should be defined outside of the component. Using `StyleSheet.create` is
optional but provides the best performance (by relying on generated CSS
stylesheets). Avoid creating unregistered style objects.
Styles should be defined outside of the component:
```js
class Example extends React.Component {}
const styles = StyleSheet.create({
heading: {
color: 'gray',
fontSize: '2rem'
},
text: {
marginTop: '1rem',
margin: 10
color: 'gray',
fontSize: '1.25rem'
}
})
```
See the `style` documentation of individual components for supported properties.
Using `StyleSheet.create` is optional but provides the best performance
(`style` is resolved to CSS stylesheets). Avoid creating unregistered style
objects.
The attribute names and values are a subset of CSS. See the `style`
documentation of individual components.
## Using styles
All the React Native components accept a `style` property. The value can be a
registered object, a plain object, or an array.
All the React Native components accept a `style` attribute.
```js
// registered object
<Text style={styles.text} />
<View style={styles.view} />
// plain object
<View style={{ transform: [ { translateX } ] }} />
// array of registered or plain objects
<View style={[ styles.container, this.props.style ]} />
```
The array syntax will merge styles from left-to-right as normal JavaScript
objects, and can be used to conditionally apply styles:
A common pattern is to conditionally add style based on a condition:
```js
// either
<View style={[
styles.container,
styles.base,
this.state.active && styles.active
]} />
```
When styles are registered with `StyleSheet.create`, the return value is a
number and not a style object. This is important for performance optimizations,
but still allows you to merge styles in a deterministic manner at runtime. If
you need access to the underlying style objects you need to use
`StyleSheet.flatten` (but be aware that this is not the optimized path).
## Composing styles
To let other components customize the style of a component's children you can
expose a prop so styles can be explicitly passed into the component.
In order to let a call site customize the style of your component children, you
can pass styles around. Use `View.propTypes.style` and `Text.propTypes.style` in
order to make sure only valid styles are being passed.
```js
class List extends React.Component {
static propTypes = {
style: ViewPropTypes.style,
elementStyle: ViewPropTypes.style,
style: View.propTypes.style,
elementStyle: View.propTypes.style,
}
render() {
@@ -107,126 +90,56 @@ In another file:
You also have much greater control over how styles are composed when compared
to using class names. For example, you may choose to accept a limited subset
of style props in the component's API, and control when they are applied.
## How styles are resolved
React Native style resolution is deterministic and slightly different from CSS.
In the following HTML/CSS example, the `.margin` selector is defined last in
the CSS and takes precedence over the previous rules, resulting in a margin of
`0, 0, 0, 0`.
```html
<style>
.marginTop { margin-top: 10px; }
.marginBottom { margin-bottom: 20px; }
.margin { margin: 0; }
</style>
<div class="marginTop marginBottom margin"></div>
```
But in React Native the most *specific* style property takes precedence,
resulting in margins of `10, 0, 20, 0`.
of style props in the component's API, and control when they are applied:
```js
const style = [
{ marginTop: 10 },
{ marginBottom: 20 },
{ margin: 0 }
];
const Box = () => <View style={style} />
```
## Implementation details
React Native for Web transforms React Native styles into React DOM styles. Any
styles defined using `StyleSheet.create` will ultimately be rendered using CSS
class names.
React Native for Web introduced a novel strategy to achieve this. Each rule is
broken down into declarations, properties are expanded to their long-form, and
the resulting key-value pairs are mapped to unique "atomic CSS" class names.
Input:
```js
const Box = () => <View style={styles.box} />
const styles = StyleSheet.create({
box: {
margin: 0
class List extends React.Component {
static propTypes = {
children: React.PropTypes.any,
// limit which styles are accepted
style: React.PropTypes.shape({
borderColor: View.propTypes.borderColor,
borderWidth: View.propTypes.borderWidth
})
}
});
render() {
return (
<View
children={children}
style={[
this.props.style,
// override border-color when scrolling
isScrolling && { borderColor: 'transparent' }
]}
/>
)
}
}
```
Output:
```html
<style>
.rn-1mnahxq { margin-top: 0px; }
.rn-61z16t { margin-right: 0px; }
.rn-p1pxzi { margin-bottom: 0px; }
.rn-11wrixw { margin-left: 0px; }
</style>
<div class="rn-156q2ks rn-61z16t rn-p1pxzi rn-11wrixw"></div>
```
This ensures that CSS order doesn't impact rendering and CSS rules are
efficiently deduplicated. Rather than the total CSS growing in proportion to
the number of *rules*, it grows in proportion to the number of *unique
declarations*. As a result, the DOM style sheet is only written to when new
unique declarations are defined and it is usually small enough to be
pre-rendered and inlined.
Class names are deterministic, which means that the resulting CSS and HTML is
consistent across builds important for large apps using code-splitting and
deploying incremental updates.
At runtime registered styles are resolved to DOM style props and memoized.
Any dynamic styles that contain declarations previously registered as static
styles can also be converted to CSS class names. Otherwise, they render as
inline styles.
All this allows React Native for Web to support the rich functionality of React
Native styles (including RTL layouts and `setNativeProps`) while providing one
of the [fastest](https://github.com/necolas/react-native-web/blob/master/benchmarks/README.md),
safest, and most efficient styles-in-JavaScript solutions.
## FAQs
### What about Media Queries?
## Media Queries
`StyleSheet.create` is a way of defining the styles your application requires;
it does not concern itself with _where_ or _when_ those styles are applied to
elements.
Media Queries may not be most appropriate for component-based designs. React
Native provides the `Dimensions` API and `onLayout` props. If you do need Media
Queries, using the `matchMedia` DOM API has the benefit of allowing you to swap
out entire components, not just styles. There are also many React libraries
wrapping JavaScript Media Query API's, e.g.,
[react-media](https://github.com/reacttraining/react-media),
There are various React libraries wrapping JavaScript Media Query API's, e.g.,
[react-media-queries](https://github.com/bloodyowl/react-media-queries),
[media-query-fascade](https://github.com/tanem/media-query-facade), or
[react-responsive](https://github.com/contra/react-responsive).
[react-responsive](https://github.com/contra/react-responsive). This has the
benefit of co-locating breakpoint-specific DOM and style changes.
### What about pseudo-classes and pseudo-elements?
## Pseudo-classes and pseudo-elements
Pseudo-classes like `:hover` and `:focus` can be implemented with events (e.g.
`onFocus`). Pseudo-elements are not supported; elements should be used instead.
### Do I need a CSS reset?
### Reset
No. React Native for Web includes a very small CSS reset that removes unwanted
User Agent styles from (pseudo-)elements beyond the reach of React (e.g.,
`html`, `body`) or inline styles (e.g., `::-moz-focus-inner`). The rest is
handled at the component-level.
You **do not** need to include a CSS reset or
[normalize.css](https://necolas.github.io/normalize.css/).
### What about using Dev Tools?
React Dev Tools supports inspecting and editing of React Native styles. It's
recommended that you rely more on React Dev Tools and live/hot-reloading rather
than inspecting and editing the DOM directly.
React Native for Web includes a very small CSS reset taken from normalize.css.
It removes unwanted User Agent styles from (pseudo-)elements beyond the reach
of React (e.g., `html`, `body`) or inline styles (e.g., `::-moz-focus-inner`).

View File

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

BIN
docs/static/components.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/static/styling-strategy.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

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

View File

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

View File

@@ -1,18 +0,0 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
const styles = StyleSheet.create({
root: {
minHeight: '100vh',
maxWidth: 680,
marginHorizontal: 'auto'
}
});
export default function(renderStory) {
return (
<View style={styles.root}>
{renderStory()}
</View>
);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@@ -1,19 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { Switch, View } from 'react-native';
const SwitchDisabledExample = () =>
<View style={styles.row}>
<View style={styles.marginRight}>
<Switch disabled={true} value={false} />
</View>
<View style={styles.marginRight}>
<Switch disabled={true} value={true} />
</View>
</View>;
export default SwitchDisabledExample;

View File

@@ -1,63 +0,0 @@
/**
* @flow
*/
import { styles } from '../helpers';
import React, { PureComponent } from 'react';
import { Switch, Text, View } from 'react-native';
class SwitchOnValueChangeExample extends PureComponent {
state = {
eventSwitchIsOn: false,
eventSwitchRegressionIsOn: true
};
render() {
const { eventSwitchIsOn, eventSwitchRegressionIsOn } = this.state;
return (
<View style={styles.row}>
<View style={[styles.alignCenter, styles.marginRight]}>
<Switch
onValueChange={this._handleEventSwitch}
style={styles.marginBottom}
value={eventSwitchIsOn}
/>
<Switch
onValueChange={this._handleEventSwitch}
style={styles.marginBottom}
value={eventSwitchIsOn}
/>
<Text>
{eventSwitchIsOn ? 'On' : 'Off'}
</Text>
</View>
<View style={styles.alignCenter}>
<Switch
onValueChange={this._handleEventSwitchRegression}
style={styles.marginBottom}
value={eventSwitchRegressionIsOn}
/>
<Switch
onValueChange={this._handleEventSwitchRegression}
style={styles.marginBottom}
value={eventSwitchRegressionIsOn}
/>
<Text>
{eventSwitchRegressionIsOn ? 'On' : 'Off'}
</Text>
</View>
</View>
);
}
_handleEventSwitch = value => {
this.setState({ eventSwitchIsOn: value });
};
_handleEventSwitchRegression = value => {
this.setState({ eventSwitchRegressionIsOn: value });
};
}
export default SwitchOnValueChangeExample;

View File

@@ -1,24 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { Switch, View } from 'react-native';
const colors = ['#ddd', '#aaa', '#999', '#666', '#000'];
const itemStyle = [styles.marginVertical, styles.marginRight];
const SwitchThumbColorExample = () =>
<View style={styles.row}>
<View style={itemStyle}>
<Switch value={false} />
</View>
{colors.map((color, i) =>
<View key={i} style={itemStyle}>
<Switch thumbColor={color} value={false} />
</View>
)}
</View>;
export default SwitchThumbColorExample;

View File

@@ -1,24 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { Switch, View } from 'react-native';
const colors = ['#ddd', '#aaa', '#999', '#666', '#000'];
const itemStyle = [styles.marginVertical, styles.marginRight];
const SwitchTrackColorExample = () =>
<View style={styles.row}>
<View style={itemStyle}>
<Switch value={false} />
</View>
{colors.map((color, i) =>
<View key={i} style={itemStyle}>
<Switch trackColor={color} value={false} />
</View>
)}
</View>;
export default SwitchTrackColorExample;

View File

@@ -1,19 +0,0 @@
/**
* @flow
*/
import { styles } from '../helpers';
import React from 'react';
import { Switch, View } from 'react-native';
const SwitchValueExample = () =>
<View style={styles.row}>
<View style={styles.marginRight}>
<Switch value={false} />
</View>
<View style={styles.marginRight}>
<Switch value={true} />
</View>
</View>;
export default SwitchValueExample;

View File

@@ -1,36 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { StyleSheet, View } from 'react-native';
const DividerHorizontal = () => <View style={styles.horizontalDivider} />;
const DividerVertical = () => <View style={styles.verticalDivider} />;
export const styles = StyleSheet.create({
horizontalDivider: {
width: '0.6rem'
},
verticalDivider: {
height: '1.3125rem'
},
row: {
flexDirection: 'row',
flexWrap: 'wrap'
},
marginRight: {
marginRight: 10
},
marginBottom: {
marginBottom: 10
},
marginVertical: {
marginVertical: 5
},
alignCenter: {
alignItems: 'center'
}
});
export { DividerHorizontal, DividerVertical };

View File

@@ -1,262 +0,0 @@
/* eslint-disable react/jsx-sort-props */
/**
* @flow
*/
import PropChildren from './examples/PropChildren';
import PropNumberOfLines from './examples/PropNumberOfLines';
import PropOnPress from './examples/PropOnPress';
import React from 'react';
import { storiesOf } from '@kadira/storybook';
import UIExplorer, {
AppText,
Code,
Description,
DocItem,
Section,
StyleList
} from '../../ui-explorer';
const TextScreen = () =>
<UIExplorer title="Text" url="components/Text">
<Description>
<AppText>
Text is component for displaying text. It supports style, basic touch handling, and inherits
typographic styles from ancestor elements.
</AppText>
<AppText>
Text is unique relative to layout: child elements use text layout ("inline") rather than
flexbox layout. This means that elements inside of a Text are not rectangles, as they wrap
when reaching the edge of their container.
</AppText>
<AppText>NOTE: Text will transfer all other props to the rendered HTML element.</AppText>
</Description>
<Section title="Props">
<DocItem
name="accessibilityLabel"
typeInfo="?string"
description="Overrides the text that is read by a screen reader when the user interacts with the element. (This is implemented using 'aria-label'.)"
/>
<DocItem
name="accessibilityLiveRegion"
typeInfo="?enum('assertive', 'none', 'polite')"
description={
<AppText>
Indicates to assistive technologies whether to notify the user when the view changes.
The values of this attribute are expressed in degrees of importance. When regions are
specified as <Code>polite</Code> (recommended), updates take low priority. When regions
are specified as <Code>assertive</Code>, assistive technologies will interrupt and
immediately notify the user. (This is implemented using 'aria-live'.)
</AppText>
}
/>
<DocItem
label="web"
name="accessibilityRole"
typeInfo="?enum(roles)"
description={
<AppText>
Allows assistive technologies to present and support interaction with the view in a
manner that is consistent with user expectations for similar views of that type. For
example, marking a touchable view with an <Code>accessibilityRole</Code> of{' '}
<Code>button</Code>. For compatibility with React Native{' '}
<Code>accessibilityTraits</Code> and <Code>accessibilityComponentType</Code> are mapped
to <Code>accessibilityRole</Code>. (This is implemented using ARIA roles.)
</AppText>
}
/>
<DocItem
name="accessible"
typeInfo="?boolean"
description={
<AppText>
When <Code>true</Code>, indicates that the view is an accessibility element (i.e.,
focusable) and groups its child content. By default, all the touchable elements and
elements with <Code>accessibilityRole</Code> of <Code>button</Code> and{' '}
<Code>link</Code> are accessible. (This is implemented using 'tabindex'.)
</AppText>
}
/>
<DocItem
name="children"
typeInfo="?any"
description={`Child content. Nested text components will inherit the styles of their parents
(only backgroundColor is inherited from non-Text parents). <Text>
only supports other <Text> and raw text (strings) as children.`}
example={{
render: () => <PropChildren />
}}
/>
<DocItem
name="importantForAccessibility"
typeInfo="?enum('auto', 'no', 'no-hide-descendants', 'yes')"
description={[
<AppText>
A value of <Code>no</Code> will remove the element from the tab flow.
</AppText>,
<AppText>
A value of <Code>no-hide-descendants</Code> will hide the element and its children from
assistive technologies. (This is implemented using 'aria-hidden'.)
</AppText>
]}
/>
<DocItem
name="numberOfLines"
typeInfo="?number"
description="Truncates the text with an ellipsis after this many lines. Currently only supports `1`."
example={{
render: () => <PropNumberOfLines />
}}
/>
<DocItem
name="onLayout"
typeInfo="?function"
description={
<AppText>
Invoked on mount and layout changes with{' '}
<Code>{'{ nativeEvent: { layout: { x, y, width, height } } }'}</Code>, where{' '}
<Code>x</Code> and <Code>y</Code> are the offsets from the parent node.
</AppText>
}
/>
<DocItem
name="onPress"
typeInfo="?function"
description="Called when the Text is pressed"
example={{
render: () => <PropOnPress />
}}
/>
<DocItem
name="selectable"
typeInfo="?boolean"
description="When false, the text is not selectable."
/>
<DocItem
name="style"
typeInfo="?style"
description={<StyleList stylePropTypes={stylePropTypes} />}
/>
<DocItem
name="testID"
typeInfo="?string"
description="Used to locate this view in end-to-end tests. The test ID is rendered to a 'data-testid' DOM attribute"
/>
</Section>
</UIExplorer>;
const stylePropTypes = [
{
name: '...View#style'
},
{
name: 'color',
typeInfo: 'color'
},
{
name: 'fontFamily',
typeInfo: 'string'
},
{
label: 'web',
name: 'fontFeatureSettings',
typeInfo: 'string'
},
{
name: 'fontSize',
typeInfo: 'number | string'
},
{
name: 'fontStyle',
typeInfo: 'string'
},
{
name: 'fontWeight',
typeInfo: 'string'
},
{
name: 'letterSpacing',
typeInfo: 'string'
},
{
name: 'lineHeight',
typeInfo: 'string'
},
{
name: 'textAlign',
typeInfo: 'string'
},
{
name: 'textAlignVertical',
typeInfo: 'string'
},
{
name: 'textDecorationLine',
typeInfo: 'string'
},
{
label: 'web',
name: 'textIndent',
typeInfo: 'string'
},
{
label: 'web',
name: 'textOverflow',
typeInfo: 'string'
},
{
label: 'web',
name: 'textRendering',
typeInfo: 'string'
},
{
name: 'textShadowColor',
typeInfo: 'color'
},
{
name: 'textShadowOffset',
typeInfo: '{ height: number, width: number }'
},
{
name: 'textShadowRadius',
typeInfo: 'number | string'
},
{
label: 'web',
name: 'textTransform',
typeInfo: 'string'
},
{
label: 'web',
name: 'unicodeBidi',
typeInfo: 'string'
},
{
name: 'whiteSpace',
typeInfo: 'string'
},
{
label: 'web',
name: 'wordWrap',
typeInfo: 'string'
},
{
name: 'writingDirection',
typeInfo: 'string'
}
];
storiesOf('Components', module).add('Text', TextScreen);

View File

@@ -1,56 +0,0 @@
/* eslint-disable react/prop-types */
/**
* @flow
*/
import React from 'react';
import { Image, Text, View } from 'react-native';
const Entity = ({ children }) =>
<Text style={{ fontWeight: '500', color: '#527fe4' }}>
{children}
</Text>;
const TextChildrenExample = () =>
<View>
<Text>
This text contains an inline blue view{' '}
<View style={{ width: 25, height: 25, backgroundColor: 'steelblue' }} /> and an inline image{' '}
<Image
source={{ uri: 'http://lorempixel.com/30/11' }}
style={{ width: 30, height: 11, resizeMode: 'cover' }}
/>
. Neat, huh?
</Text>
<View>
<Text>
(Normal text,
<Text style={{ fontWeight: 'bold' }}>
(and bold
<Text style={{ fontSize: 11, color: '#527fe4' }}>(and tiny inherited bold blue)</Text>
)
</Text>
)
</Text>
<Text style={{ opacity: 0.7 }}>
(opacity
<Text>
(is inherited
<Text style={{ opacity: 0.7 }}>
(and accumulated
<Text style={{ backgroundColor: '#ffaaaa' }}>(and also applies to the background)</Text>
)
</Text>
)
</Text>
)
</Text>
<Text style={{ fontSize: 12 }}>
<Entity>Entity Name</Entity>
</Text>
</View>
</View>;
export default TextChildrenExample;

View File

@@ -1,27 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { Text, View } from 'react-native';
const TextNumberOfLinesExample = () =>
<View style={{ maxWidth: 320 }}>
<Text numberOfLines={1}>
Maximum of one line, no matter how much I write here. If I keep writing, it
{"'"}
ll just truncate after one line.
</Text>
<Text numberOfLines={2} style={{ marginTop: 20 }}>
Maximum of two lines, no matter how much I write here. If I keep writing, it
{"'"}
ll just truncate after two lines.
</Text>
<Text style={{ marginTop: 20 }}>
No maximum lines specified, no matter how much I write here. If I keep writing, it
{"'"}
ll just keep going and going.
</Text>
</View>;
export default TextNumberOfLinesExample;

View File

@@ -1,10 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { Text } from 'react-native';
const TextOnLayoutExample = () => <Text />;
export default TextOnLayoutExample;

View File

@@ -1,54 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
class TextOnPressExample extends React.Component {
state = { timesPressed: 0 };
render() {
let textLog = '';
if (this.state.timesPressed > 1) {
textLog = this.state.timesPressed + 'x text onPress';
} else if (this.state.timesPressed > 0) {
textLog = 'text onPress';
}
return (
<View>
<Text onPress={this._handlePress} style={styles.textBlock}>
Text has built-in onPress handling
</Text>
<View style={styles.logBox}>
<Text>
{textLog}
</Text>
</View>
</View>
);
}
_handlePress = () => {
this.setState({
timesPressed: this.state.timesPressed + 1
});
};
}
const styles = StyleSheet.create({
logBox: {
padding: 20,
marginTop: 10,
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#f0f0f0',
backgroundColor: '#f9f9f9'
},
textBlock: {
fontWeight: '500',
color: 'blue'
}
});
export default TextOnPressExample;

View File

@@ -1,12 +0,0 @@
/**
* @flow
*/
/*
import React from 'react';
import { View } from 'react-native';
const ViewStyleExample = () => null;
export default ViewStyleExample;
*/

View File

@@ -1,445 +0,0 @@
/**
* @flow
*/
/*
import createReactClass from 'create-react-class';
import React from 'react';
import { storiesOf } from '@kadira/storybook';
import UIExplorer, { PropText, StyleList } from '../../ui-explorer';
import { Image, Text, View } from 'react-native';
const AttributeToggler = createReactClass({
getInitialState: function() {
return { fontWeight: 'bold', fontSize: 15 };
},
toggleWeight: function() {
this.setState({
fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold'
});
},
increaseSize: function() {
this.setState({
fontSize: this.state.fontSize + 1
});
},
render: function() {
const curStyle = { fontWeight: this.state.fontWeight, fontSize: this.state.fontSize };
return (
<View>
<Text style={curStyle}>
Tap the controls below to change attributes.
</Text>
<Text>
<Text>See how it will even work on <Text style={curStyle}>this nested text</Text></Text>
</Text>
<Text onPress={this.toggleWeight} style={{ backgroundColor: '#ffaaaa', marginTop: 5 }}>
Toggle Weight
</Text>
<Text onPress={this.increaseSize} style={{ backgroundColor: '#aaaaff', marginTop: 5 }}>
Increase Size
</Text>
</View>
);
}
});
const examples = [
{
title: 'Wrap',
render: function() {
return (
<Text style={{ WebkitFontSmoothing: 'antialiased' }}>
The text should wrap if it goes on multiple lines. See, this is going to
the next line.
</Text>
);
}
},
{
title: 'Padding',
render: function() {
return (
<Text style={{ padding: 10 }}>
This text is indented by 10px padding on all sides.
</Text>
);
}
},
{
title: 'Font Family',
render: function() {
return (
<View>
<Text style={{ fontFamily: 'Cochin' }}>
Cochin
</Text>
<Text style={{ fontFamily: 'Cochin', fontWeight: 'bold' }}>
Cochin bold
</Text>
<Text style={{ fontFamily: 'Helvetica' }}>
Helvetica
</Text>
<Text style={{ fontFamily: 'Helvetica', fontWeight: 'bold' }}>
Helvetica bold
</Text>
<Text style={{ fontFamily: 'Verdana' }}>
Verdana
</Text>
<Text style={{ fontFamily: 'Verdana', fontWeight: 'bold' }}>
Verdana bold
</Text>
</View>
);
}
},
{
title: 'Font Size',
render: function() {
return (
<View>
<Text style={{ fontSize: 23 }}>
Size 23
</Text>
<Text style={{ fontSize: 8 }}>
Size 8
</Text>
</View>
);
}
},
{
title: 'Color',
render: function() {
return (
<View>
<Text style={{ color: 'red' }}>
Red color
</Text>
<Text style={{ color: 'blue' }}>
Blue color
</Text>
</View>
);
}
},
{
title: 'Font Weight',
render: function() {
return (
<View>
<Text style={{ fontSize: 20, fontWeight: '100' }}>
Move fast and be ultralight
</Text>
<Text style={{ fontSize: 20, fontWeight: '200' }}>
Move fast and be light
</Text>
<Text style={{ fontSize: 20, fontWeight: 'normal' }}>
Move fast and be normal
</Text>
<Text style={{ fontSize: 20, fontWeight: 'bold' }}>
Move fast and be bold
</Text>
<Text style={{ fontSize: 20, fontWeight: '900' }}>
Move fast and be ultrabold
</Text>
</View>
);
}
},
{
title: 'Font Style',
render: function() {
return (
<View>
<Text style={{ fontStyle: 'normal' }}>
Normal text
</Text>
<Text style={{ fontStyle: 'italic' }}>
Italic text
</Text>
</View>
);
}
},
{
title: 'Text Decoration',
render: function() {
return (
<View>
<Text style={{ textDecorationLine: 'underline', textDecorationStyle: 'solid' }}>
Solid underline
</Text>
<Text
style={{
textDecorationLine: 'underline',
textDecorationStyle: 'double',
textDecorationColor: '#ff0000'
}}
>
Double underline with custom color
</Text>
<Text
style={{
textDecorationLine: 'underline',
textDecorationStyle: 'dashed',
textDecorationColor: '#9CDC40'
}}
>
Dashed underline with custom color
</Text>
<Text
style={{
textDecorationLine: 'underline',
textDecorationStyle: 'dotted',
textDecorationColor: 'blue'
}}
>
Dotted underline with custom color
</Text>
<Text style={{ textDecorationLine: 'none' }}>
None textDecoration
</Text>
<Text style={{ textDecorationLine: 'line-through', textDecorationStyle: 'solid' }}>
Solid line-through
</Text>
<Text
style={{
textDecorationLine: 'line-through',
textDecorationStyle: 'double',
textDecorationColor: '#ff0000'
}}
>
Double line-through with custom color
</Text>
<Text
style={{
textDecorationLine: 'line-through',
textDecorationStyle: 'dashed',
textDecorationColor: '#9CDC40'
}}
>
Dashed line-through with custom color
</Text>
<Text
style={{
textDecorationLine: 'line-through',
textDecorationStyle: 'dotted',
textDecorationColor: 'blue'
}}
>
Dotted line-through with custom color
</Text>
<Text style={{ textDecorationLine: 'underline line-through' }}>
Both underline and line-through
</Text>
</View>
);
}
},
{
title: 'Text Align',
render: function() {
return (
<View>
<Text>
auto (default) - english LTR
</Text>
<Text>
أحب اللغة العربية auto (default) - arabic RTL
</Text>
<Text style={{ textAlign: 'left' }}>
left left left left left left left left left left left left left left left
</Text>
<Text style={{ textAlign: 'center' }}>
center center center center center center center center center center center
</Text>
<Text style={{ textAlign: 'right' }}>
right right right right right right right right right right right right right
</Text>
<Text style={{ textAlign: 'justify' }}>
justify: this text component{"'"}s contents are laid out with "textAlign: justify"
and as you can see all of the lines except the last one span the
available width of the parent container.
</Text>
</View>
);
}
},
{
title: 'Letter Spacing',
render: function() {
return (
<View>
<Text style={{ letterSpacing: 0 }}>
letterSpacing = 0
</Text>
<Text style={{ letterSpacing: 2, marginTop: 5 }}>
letterSpacing = 2
</Text>
<Text style={{ letterSpacing: 9, marginTop: 5 }}>
letterSpacing = 9
</Text>
<Text style={{ letterSpacing: -1, marginTop: 5 }}>
letterSpacing = -1
</Text>
</View>
);
}
},
{
title: 'Spaces',
render: function() {
return (
<Text>
A {'generated'} {' '} {'string'} and some &nbsp;&nbsp;&nbsp; spaces
</Text>
);
}
},
{
title: 'Line Height',
render: function() {
return (
<Text>
<Text style={{ lineHeight: 35 }}>
A lot of space between the lines of this long passage that should
wrap once.
</Text>
</Text>
);
}
},
{
title: 'Empty Text',
description: "It's ok to have Text with zero or null children.",
render: function() {
return <Text />;
}
},
{
title: 'Toggling Attributes',
render: function() {
return <AttributeToggler />;
}
},
{
title: 'backgroundColor attribute',
description: 'backgroundColor is inherited from all types of views.',
render: function() {
return (
<Text style={{ backgroundColor: 'yellow' }}>
Yellow container background,
<Text style={{ backgroundColor: '#ffaaaa' }}>
{' '}red background,
<Text style={{ backgroundColor: '#aaaaff' }}>
{' '}blue background,
<Text>
{' '}inherited blue background,
<Text style={{ backgroundColor: '#aaffaa' }}>
{' '}nested green background.
</Text>
</Text>
</Text>
</Text>
</Text>
);
}
},
{
title: 'Text highlighting (tap the link to see highlight)',
render: function() {
return (
<View>
<Text>
Lorem ipsum dolor sit amet,
{' '}
<Text
onPress={() => null}
style={{ backgroundColor: 'white', textDecorationLine: 'underline', color: 'blue' }}
suppressHighlighting={false}
>
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
magna aliqua. Ut enim ad minim veniam, quis nostrud
</Text>
{' '}
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</Text>
</View>
);
}
},
{
title: 'allowFontScaling attribute',
render: function() {
return (
<View>
<Text>
By default, text will respect Text Size accessibility setting on iOS.
It means that all font sizes will be increased or descreased depending on the value of
Text Size setting in
{' '}
<Text style={{ fontWeight: 'bold' }}>
Settings.app - Display & Brightness - Text Size
</Text>
</Text>
<Text style={{ marginTop: 10 }}>
You can disable scaling for your Text component by passing
{' '}
{'"'}
allowFontScaling=
{'{'}
false
{'}"'}
{' '}
prop.
</Text>
<Text allowFontScaling={false} style={{ marginTop: 20 }}>
This text will not scale.
</Text>
</View>
);
}
},
{
title: 'Text shadow',
render: function() {
return (
<View>
<Text
style={{
fontSize: 20,
textShadowOffset: { width: 2, height: 2 },
textShadowRadius: 1,
textShadowColor: '#00cccc'
}}
>
Demo text shadow
</Text>
</View>
);
}
},
{
title: 'Line break mode',
render: function() {
return (
<View>
<Text numberOfLines={1}>
This very long text should be truncated with dots in the end.
</Text>
<Text lineBreakMode="middle" numberOfLines={1}>
This very long text should be truncated with dots in the middle.
</Text>
<Text lineBreakMode="head" numberOfLines={1}>
This very long text should be truncated with dots in the beginning.
</Text>
<Text lineBreakMode="clip" numberOfLines={1}>
This very looooooooooooooooooooooooooooong text should be clipped.
</Text>
</View>
);
}
}
];
*/

View File

@@ -1,362 +0,0 @@
/* eslint-disable react/jsx-sort-props */
/**
* @flow
*/
import PropAutoCapitalize from './examples/PropAutoCapitalize';
import PropBlurOnSubmit from './examples/PropBlurOnSubmit';
import PropClearTextOnFocus from './examples/PropClearTextOnFocus';
import PropEditable from './examples/PropEditable';
import PropKeyboardType from './examples/PropKeyboardType';
import PropMaxLength from './examples/PropMaxLength';
import PropMultiline from './examples/PropMultiline';
import PropNumberOfLines from './examples/PropNumberOfLines';
import PropOnSelectionChange from './examples/PropOnSelectionChange';
import PropPlaceholder from './examples/PropPlaceholder';
import PropSecureTextEntry from './examples/PropSecureTextEntry';
import PropSelectTextOnFocus from './examples/PropSelectTextOnFocus';
import TextInputEvents from './examples/TextInputEvents';
import TextInputRewrite, { TextInputRewriteInvalidCharacters } from './examples/Rewrite';
import React from 'react';
import { storiesOf } from '@kadira/storybook';
import UIExplorer, {
AppText,
Code,
Description,
DocItem,
Section,
StyleList,
TextList
} from '../../ui-explorer';
const TextInputScreen = () =>
<UIExplorer title="TextInput" url="components/TextInput">
<Description>
<AppText>
Accessible single- and multi-line text input via a keyboard. Supports features such as
auto-complete, auto-focus, placeholder text, and event callbacks. Note: some props are
exclusive to or excluded from <Code>multiline</Code>.
</AppText>
</Description>
<Section title="Props">
<DocItem name="...View props" />
<DocItem
name="autoCapitalize"
typeInfo="?enum('characters', 'none', 'sentences', 'words') = 'sentences'"
description={[
<AppText key={1}>
Automatically capitalize certain characters (only available in Chrome and iOS Safari).
</AppText>,
<TextList
key={2}
items={[
<AppText>
<Code>characters</Code>: Automatically capitalize all characters.
</AppText>,
<AppText>
<Code>none</Code>: Completely disables automatic capitalization.
</AppText>,
<AppText>
<Code>sentences</Code>: Automatically capitalize the first letter of sentences.
</AppText>,
<AppText>
<Code>words</Code>: Automatically capitalize the first letter of words.
</AppText>
]}
/>
]}
example={{
render: () => <PropAutoCapitalize />
}}
/>
<DocItem
label="web"
name="autoComplete"
typeInfo="?string"
description={
<AppText>
Indicates whether the value of the control can be automatically completed by the
browser.{' '}
<AppText
href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"
target="_blank"
>
Accepted values.
</AppText>
</AppText>
}
/>
<DocItem
name="autoCorrect"
typeInfo="?boolean = true"
description="Automatically correct spelling mistakes (only available in iOS Safari)."
/>
<DocItem
name="autoFocus"
typeInfo="?boolean = false"
description="If `true`, focuses the input on `componentDidMount`. Only the first form element in a document with `autofocus` is focused."
/>
<DocItem
name="blurOnSubmit"
typeInfo="?boolean"
description={
<AppText>
If <Code>true</Code>, the text field will blur when submitted. The default value is{' '}
<Code>true</Code> for single-line fields and <Code>false</Code> for multiline fields.
Note, for multiline fields setting <Code>blurOnSubmit</Code> to <Code>true</Code> means
that pressing return will blur the field and trigger the <Code>onSubmitEditing</Code>{' '}
event instead of inserting a newline into the field.
</AppText>
}
example={{
render: () => <PropBlurOnSubmit />
}}
/>
<DocItem
name="clearTextOnFocus"
typeInfo="?boolean = false"
description="If `true`, clears the text field automatically when focused."
example={{
render: () => <PropClearTextOnFocus />
}}
/>
<DocItem
name="defaultValue"
typeInfo="?string"
description={
<AppText>
Provides an initial value that will change when the user starts typing. Useful for
simple use-cases where you don't want to deal with listening to events and updating the{' '}
<Code>value</Code> prop to keep the controlled state in sync.
</AppText>
}
/>
<DocItem
name="editable"
typeInfo="?boolean = true"
description="If `false`, text is not editable (i.e., read-only). "
example={{
render: () => <PropEditable />
}}
/>
<DocItem
name="keyboardType"
typeInfo="enum('default', 'email-address', 'numeric', 'phone-pad', 'search', 'url', 'web-search') = 'default'"
description="Determines which keyboard to open on devices with a virtual keyboard. Safari iOS requires an ancestral `<form action>` element to display the `search` keyboard). (Not available when `multiline` is `true`.)"
example={{
render: () => <PropKeyboardType />
}}
/>
<DocItem
name="maxLength"
typeInfo="?number"
description="Limits the maximum number of characters that can be entered."
example={{
render: () => <PropMaxLength />
}}
/>
<DocItem
name="multiline"
typeInfo="?boolean = false"
description="If true, the text input can be multiple lines."
example={{
render: () => <PropMultiline />
}}
/>
<DocItem
name="numberOfLines"
typeInfo="?number"
description="Sets the number of lines for a multiline `TextInput`. (Requires `multiline` to be `true`.)"
example={{
render: () => <PropNumberOfLines />
}}
/>
<DocItem
name="onBlur"
typeInfo="?function"
description="Callback that is called when the text input is blurred."
/>
<DocItem
name="onChange"
typeInfo="?function"
description="Callback that is called when the text input's text changes."
/>
<DocItem
name="onChangeText"
typeInfo="?function"
description="Callback that is called when the text input's text changes. The text is passed as an argument to the callback handler."
/>
<DocItem
name="onFocus"
typeInfo="?function"
description="Callback that is called when the text input is focused."
/>
<DocItem
name="onKeyPress"
typeInfo="?function"
description={
<AppText>
Callback that is called when a key is pressed. This will be called with{' '}
<Code>{`{
nativeEvent: { key: keyValue } }`}</Code>{' '}
where keyValue is <Code>Enter</Code> or <Code>Backspace</Code> for respective keys and
the typed-in character otherwise including <Code>' '</Code>
for space. Modifier keys (e.g., <Code>shiftKey</Code>) are also included in the{' '}
<Code>nativeEvent</Code>. Fires before <Code>onChange</Code> callbacks.
</AppText>
}
/>
<DocItem
name="onSelectionChange"
typeInfo="?function"
description={
<AppText>
Callback that is called when the text input's selection changes. This will be called
with <Code>{'{ nativeEvent: { selection: { start, end } } }'}</Code>.
</AppText>
}
example={{
render: () => <PropOnSelectionChange />
}}
/>
<DocItem
name="onSubmitEditing"
typeInfo="?function"
description="Callback that is called when the keyboard's submit button is pressed. When multiline={true}, this is only called if blurOnSubmit={true}."
/>
<DocItem
name="placeholder"
typeInfo="?string"
description="The string that will be rendered in an empty `TextInput` before text has been entered."
example={{
render: () => <PropPlaceholder />
}}
/>
<DocItem
name="secureTextEntry"
typeInfo="?boolean = false"
description="If true, the text input obscures the text entered so that sensitive text like passwords stay secure. (Not available when `multiline` is `true`.)"
example={{
render: () => <PropSecureTextEntry />
}}
/>
<DocItem
name="selection"
typeInfo="?{ start: number, end: ?number }"
description="The start and end of the text input's selection. Set start and end to the same value to position the cursor."
/>
<DocItem
name="selectTextOnFocus"
typeInfo="?boolean = false"
description="If `true`, all text will automatically be selected on focus."
example={{
render: () => <PropSelectTextOnFocus />
}}
/>
<DocItem
name="style"
typeInfo="?style"
description={
<StyleList
stylePropTypes={[
{
name: '...Text#style'
},
{
label: 'web',
name: 'resize',
typeInfo: 'string'
}
]}
/>
}
/>
<DocItem
name="value"
typeInfo="?string"
description={
<AppText>
The value to show for the text input. <Code>TextInput</Code> is a controlled component,
which means the native <Code>value</Code> will be forced to match this prop if provided.
Read about how{' '}
<AppText
children="React form components"
href="https://facebook.github.io/react/docs/forms.html"
target="_blank"
/>{' '}
work. To prevent user edits to the value set <Code>{'editable={false}'}</Code>.
</AppText>
}
/>
</Section>
<Section title="Instance methods">
<DocItem name="blur" typeInfo="() => void" description="Blur the underlying DOM input." />
<DocItem
name="clear"
typeInfo="() => void"
description="Clear the text from the underlying DOM input."
/>
<DocItem name="focus" typeInfo="() => void" description="Focus the underlying DOM input." />
<DocItem
name="isFocused"
typeInfo="() => boolean"
description="Returns `true` if the input is currently focused; `false` otherwise."
/>
</Section>
<Section title="More examples">
<DocItem
description="TextInput events"
example={{
render: () => <TextInputEvents />
}}
/>
<DocItem
description="Rewrite (<sp> to '_' with maxLength)"
example={{
render: () => <TextInputRewrite />
}}
/>
<DocItem
description="Rewrite (no spaces allowed)"
example={{
render: () => <TextInputRewriteInvalidCharacters />
}}
/>
</Section>
</UIExplorer>;
storiesOf('Components', module).add('TextInput', TextInputScreen);

View File

@@ -1,62 +0,0 @@
/**
* @flow
*/
/*
import React from 'react';
import { StyleSheet, TextInput } from 'react-native';
class AutoExpandingTextInput extends React.Component {
state: any;
constructor(props) {
super(props);
this.state = {
text:
'React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React. The focus of React Native is on developer efficiency across all the platforms you care about — learn once, write anywhere. Facebook uses React Native in multiple production apps and will continue investing in React Native.',
height: 0
};
}
render() {
return (
<TextInput
{...this.props}
multiline={true}
onChangeText={text => {
this.setState({ text });
}}
onContentSizeChange={event => {
this.setState({ height: event.nativeEvent.contentSize.height });
}}
style={[styles.default, { height: Math.max(35, this.state.height) }]}
value={this.state.text}
/>
);
}
}
const styles = StyleSheet.create({
default: {
height: 26,
borderWidth: 0.5,
borderColor: '#0f0f0f',
flex: 1,
fontSize: 13,
padding: 4
},
eventLabel: {
margin: 3,
fontSize: 12
}
});
const AutoExpandingTextInputExample = () =>
<AutoExpandingTextInput
enablesReturnKeyAutomatically={true}
placeholder="height increases with content"
returnKeyType="default"
/>;
export default AutoExpandingTextInputExample;
*/

View File

@@ -1,25 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { WithLabel, styles } from '../helpers';
import { TextInput, View } from 'react-native';
const TextInputAutoCapitalizeExample = () =>
<View>
<WithLabel label="none">
<TextInput autoCapitalize="none" style={styles.textinput} />
</WithLabel>
<WithLabel label="sentences">
<TextInput autoCapitalize="sentences" style={styles.textinput} />
</WithLabel>
<WithLabel label="words">
<TextInput autoCapitalize="words" style={styles.textinput} />
</WithLabel>
<WithLabel label="characters">
<TextInput autoCapitalize="characters" style={styles.textinput} />
</WithLabel>
</View>;
export default TextInputAutoCapitalizeExample;

View File

@@ -1,11 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { TextInput } from 'react-native';
const TextInputAutoFocusExample = () => <TextInput autoFocus={true} style={styles.default} />;
export default TextInputAutoFocusExample;

View File

@@ -1,55 +0,0 @@
/* eslint-disable react/jsx-no-bind */
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { TextInput, View } from 'react-native';
class TextInputBlurOnSubmitExample extends React.Component {
_nodes = {};
focusNextField = nextField => {
this._nodes[nextField].focus();
};
render() {
return (
<View>
<TextInput
blurOnSubmit={false}
placeholder="blurOnSubmit = false"
ref={c => {
this._nodes['1'] = c;
}}
style={styles.textinput}
/>
<TextInput
blurOnSubmit={true}
onSubmitEditing={() => this.focusNextField('3')}
placeholder="blurOnSubmit = true"
ref={c => {
this._nodes['2'] = c;
}}
style={styles.textinput}
/>
<TextInput
blurOnSubmit={true}
multiline={true}
onSubmitEditing={e => {
console.log(e.nativeEvent);
}}
placeholder="blurOnSubmit = true"
ref={c => {
this._nodes['3'] = c;
}}
style={styles.multiline}
/>
</View>
);
}
}
export default TextInputBlurOnSubmitExample;

View File

@@ -1,25 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles, WithLabel } from '../helpers';
import { TextInput, View } from 'react-native';
const TextInputClearButtonModeExample = () =>
<View>
<WithLabel label="never">
<TextInput clearButtonMode="never" style={styles.textinput} />
</WithLabel>
<WithLabel label="while editing">
<TextInput clearButtonMode="while-editing" style={styles.textinput} />
</WithLabel>
<WithLabel label="unless editing">
<TextInput clearButtonMode="unless-editing" style={styles.textinput} />
</WithLabel>
<WithLabel label="always">
<TextInput clearButtonMode="always" style={styles.textinput} />
</WithLabel>
</View>;
export default TextInputClearButtonModeExample;

View File

@@ -1,26 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { TextInput, View } from 'react-native';
const TextInputClearTextOnFocusExample = () =>
<View>
<TextInput
clearTextOnFocus={true}
defaultValue="text is cleared on focus"
placeholder="text is cleared on focus"
style={styles.textinput}
/>
<TextInput
clearTextOnFocus={true}
defaultValue="text is cleared on focus"
multiline={true}
placeholder="text is cleared on focus"
style={styles.multiline}
/>
</View>;
export default TextInputClearTextOnFocusExample;

View File

@@ -1,20 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles } from '../helpers';
import { TextInput, View } from 'react-native';
const TextInputEditableExample = () =>
<View>
<TextInput defaultValue="uneditable text input" editable={false} style={styles.textinput} />
<TextInput
defaultValue="uneditable multiline text input"
editable={false}
multiline={true}
style={styles.multiline}
/>
</View>;
export default TextInputEditableExample;

View File

@@ -1,33 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles, WithLabel } from '../helpers';
import { TextInput, View } from 'react-native';
const keyboardTypes = [
'default',
//'ascii-capable',
//'numbers-and-punctuation',
'url',
'number-pad',
'phone-pad',
//'name-phone-pad',
'email-address',
//'decimal-pad',
//'twitter',
'web-search',
'numeric'
];
const TextInputKeyboardTypeExample = () =>
<View>
{keyboardTypes.map(type =>
<WithLabel key={type} label={type}>
<TextInput keyboardType={type} style={styles.textinput} />
</WithLabel>
)}
</View>;
export default TextInputKeyboardTypeExample;

View File

@@ -1,25 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { styles, WithLabel } from '../helpers';
import { TextInput, View } from 'react-native';
const TextInputMaxLengthExample = () =>
<View>
<WithLabel label="maxLength: 5">
<TextInput maxLength={5} style={styles.textinput} />
</WithLabel>
<WithLabel label="maxLength: 5 with placeholder">
<TextInput maxLength={5} placeholder="ZIP code entry" style={styles.textinput} />
</WithLabel>
<WithLabel label="maxLength: 5 with default value already set">
<TextInput defaultValue="94025" maxLength={5} style={styles.textinput} />
</WithLabel>
<WithLabel label="maxLength: 5 with very long default value already set">
<TextInput defaultValue="9402512345" maxLength={5} style={styles.textinput} />
</WithLabel>
</View>;
export default TextInputMaxLengthExample;

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