diff --git a/README.md b/README.md
index d2ae5cbe..c2ee1040 100644
--- a/README.md
+++ b/README.md
@@ -2,114 +2,56 @@
[![Build Status][travis-image]][travis-url]
[![npm version][npm-image]][npm-url]
-
+
-[React Native][react-native-url] components and APIs for the Web. Flexbox
-layout and JavaScript styling.
-
-* [Discord: #react-native-web on reactiflux][discord-url]
-* [Gitter: react-native-web][gitter-url]
-
-## Table of contents
-
-* [Quick start](#quick-start)
-* [Overview](#overview)
-* [Example](#example)
-* [APIs](#apis)
-* [Components](#components)
-* [Contributing](#contributing)
-* [Thanks](#thanks)
-* [License](#license)
+[React Native][react-native-url] components and APIs for the Web.
## Quick start
-You can [try the latest version on CodePen](http://codepen.io/necolas/pen/PZzwBR).
-
To install in your app:
```
npm install --save react@0.14 react-dom@0.14 react-native-web
```
+Or [try it on CodePen](http://codepen.io/necolas/pen/PZzwBR).
+
+Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
+
## Overview
-### Importing
+This is a web implementation of React Native components and APIs. The React
+Native components are good web application building blocks, and provide a common
+foundation for component libraries.
-All API's, components, and a Web-specific `React` are provided by the
-`react-native-web` module:
-
-```js
-import React, { Image, StyleSheet, Text, View } from 'react-native-web'
-```
-
-### Client-side rendering
-
-Client-side rendering requires that you use the module's `React` export.
-`React.render` is a thin wrapper around `ReactDOM.render` that renders your
-application and the style sheet. Styles are updated if new bundles are loaded
-asynchronously.
-
-```js
-// client.js
-import App from './components/App'
-import React from 'react-native-web'
-
-React.render(, document.getElementById('react-root'))
-```
-
-### Server-side rendering
-
-Server-side rendering is done by calling `React.renderToString` or
-`React.renderToStaticMarkup`, the output of both includes the style sheet.
-
-```js
-// server.js
-import App from './components/App'
-import React from 'react-native-web'
-
-const html = React.renderToString();
-
-const Html = () => (
-
-
-
-
-
-
-
-
-
-)
-```
-
-### Styling
-
-React Native for Web allows you to [define styles using
-JavaScript](docs/guides/style.md), either with inline styles or
-[`StyleSheet.create`](docs/apis/StyleSheet.md).
-
-The `View` component makes it easy to build common layouts with flexbox, such
-as stacked and nested boxes with margin and padding. See this [guide to
-flexbox][flexbox-guide-url].
-
-### Accessibility
-
-The most common and best supported [accessibility
-features](docs/guides/accessibility.md) of the Web are leveraged through 4
-props available on most components: `accessible`, `accessibilityLabel`,
-`accessibilityLiveRegion`, and `accessibilityRole`.
+For example, the [`View`](docs/apis/View.md) component makes it easy to build
+common layouts with flexbox, such as stacked and nested boxes with margin and
+padding. And the [`StyleSheet`](docs/guides/style.md) API converts styles
+defined in JavaScript to "atomic" CSS.
## Example
More examples can be found in the [`examples` directory](examples).
```js
-import React, { Image, StyleSheet, Text, View } from 'react-native-web'
+import React, { AppRegistry, Image, StyleSheet, Text, View } from 'react-native'
+// Components
const Card = ({ children }) => {children}
const Title = ({ children }) => {children}
const Photo = ({ uri }) =>
+const App = () => (
+
+ App Card
+
+
+)
+// App registration and rendering
+AppRegistry.registerComponent('MyApp', () => App)
+AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-root') })
+
+// Styles
const styles = StyleSheet.create({
card: {
flexGrow: 1,
@@ -121,73 +63,52 @@ const styles = StyleSheet.create({
},
image: {
height: 40,
- marginRight: 10,
+ marginVertical: 10,
width: 40
}
})
```
-## APIs
+## Documentation
-### [`StyleSheet`](docs/apis/StyleSheet.md)
+Guides:
-StyleSheet is a style abstraction that transforms inline styles to CSS on the
-client or the server. It provides a minimal CSS reset targeting elements and
-pseudo-elements beyond the reach of React inline styles.
+* [Accessibility](docs/guides/accessibility.md)
+* [Client and server rendering](docs/guides/rendering.md)
+* [Direct manipulation](docs/guides/direct-manipulation.md)
+* [Known issues](docs/guides/known-issues.md)
+* [React Native](docs/guides/react-native.md)
+* [Style](docs/guides/style.md)
-## Components
+Exported modules:
-### [`Image`](docs/components/Image.md)
-
-An accessibile image component with support for image resizing, default image,
-and child content.
-
-### [`ListView`](docs/components/ListView.md)
-
-(TODO)
-
-### [`ScrollView`](docs/components/ScrollView.md)
-
-A scrollable view with event throttling.
-
-### [`Text`](docs/components/Text.md)
-
-Displays text inline and supports basic press handling.
-
-### [`TextInput`](docs/components/TextInput.md)
-
-Accessible single- and multi-line text input via a keyboard.
-
-### [`Touchable`](docs/components/Touchable.md)
-
-Touch bindings for press and long press.
-
-### [`View`](docs/components/View.md)
-
-The fundamental UI building block using flexbox for layout.
-
-## Contributing
-
-Please read the [contribution guidelines][contributing-url]. Contributions are
-welcome!
-
-## Thanks
-
-Thanks to current and past members of the React and React Native teams (in
-particular Vjeux and Pete Hunt).
-
-Thanks to [react-tappable](https://github.com/JedWatson/react-tappable) for
-backing the current implementation of `Touchable`.
+* Components
+ * [`ActivityIndicator`](docs/components/ActivityIndicator.md)
+ * [`Image`](docs/components/Image.md)
+ * [`ListView`](docs/components/ListView.md)
+ * [`Portal`](docs/components/Portal.md)
+ * [`ScrollView`](docs/components/ScrollView.md)
+ * [`Text`](docs/components/Text.md)
+ * [`TextInput`](docs/components/TextInput.md)
+ * [`TouchableHighlight`](docs/components/TouchableHighlight.md)
+ * [`TouchableOpacity`](docs/components/TouchableOpacity.md)
+ * [`TouchableWithoutFeedback`](docs/components/TouchableWithoutFeedback.md)
+ * [`View`](docs/components/View.md)
+* APIs
+ * [`AppRegistry`](docs/apis/AppRegistry.md)
+ * [`AppState`](docs/apis/AppState.md)
+ * [`AsyncStorage`](docs/apis/AsyncStorage.md)
+ * [`Dimensions`](docs/apis/Dimensions.md)
+ * [`NativeMethods`](docs/apis/NativeMethods.md)
+ * [`NetInfo`](docs/apis/NetInfo.md)
+ * [`PixelRatio`](docs/apis/PixelRatio.md)
+ * [`Platform`](docs/apis/Platform.md)
+ * [`StyleSheet`](docs/apis/StyleSheet.md)
## License
-Copyright (c) 2015 Nicolas Gallagher. Released under the [MIT
-license](http://www.opensource.org/licenses/mit-license.php).
+React Native for Web is [BSD licensed](LICENSE).
-[contributing-url]: https://github.com/necolas/react-native-web/blob/master/CONTRIBUTING.md
-[discord-url]: http://join.reactiflux.com
-[flexbox-guide-url]: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
-[gitter-url]: https://gitter.im/necolas/react-native-web
[npm-image]: https://badge.fury.io/js/react-native-web.svg
[npm-url]: https://npmjs.org/package/react-native-web
[react-native-url]: https://facebook.github.io/react-native/
diff --git a/config/webpack.config.example.js b/config/webpack.config.example.js
index 519e7f68..e26f128e 100644
--- a/config/webpack.config.example.js
+++ b/config/webpack.config.example.js
@@ -27,5 +27,10 @@ module.exports = {
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin()
- ]
+ ],
+ resolve: {
+ alias: {
+ 'react-native': '../../src'
+ }
+ }
}
diff --git a/docs/apis/AppState.md b/docs/apis/AppState.md
index 7d26b213..5a4e4d10 100644
--- a/docs/apis/AppState.md
+++ b/docs/apis/AppState.md
@@ -27,10 +27,10 @@ Remove a handler by passing the change event `type` and the `handler`.
## Examples
-To see the current state, you can check `AppStateIOS.currentState`, which will
-be kept up-to-date. This example will only ever appear to say "Current state
-is: active" because the app is only visible to the user when in the `active`
-state, and the null state will happen only momentarily.
+To see the current state, you can check `AppState.currentState`, which will be
+kept up-to-date. This example will only ever appear to say "Current state is:
+active" because the app is only visible to the user when in the `active` state,
+and the null state will happen only momentarily.
```js
class Example extends React.Component {
diff --git a/docs/guides/accessibility.md b/docs/guides/accessibility.md
index ac45d4fd..effd99f9 100644
--- a/docs/guides/accessibility.md
+++ b/docs/guides/accessibility.md
@@ -9,12 +9,13 @@ The most common and best supported accessibility features of the Web are
exposed as the props: `accessible`, `accessibilityLabel`,
`accessibilityLiveRegion`, and `accessibilityRole`.
-React Native for Web does not provide a way to directly control the rendered
-HTML element. The `accessibilityRole` prop is used to infer an [analogous HTML
-element][html-aria-url] to use in addition, 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).
+React Native for Web does not provide a way to directly control the type of the
+rendered HTML element. The `accessibilityRole` prop is used to infer an
+[analogous HTML element][html-aria-url] to use in addition to the resulting
+ARIA `role`, where possible. While this may contradict some ARIA
+recommendations, it also helps avoid certain HTML5 conformance errors and
+accessibility anti-patterns (e.g., giving a `heading` role to a `button`
+element).
For example:
@@ -24,7 +25,8 @@ For example:
* `` => ``.
* `` => ``.
-See the component documentation for more details.
+Other ARIA properties should be set via [direct
+manipulation](./direct-manipulation.md).
[aria-in-html-url]: https://w3c.github.io/aria-in-html/
[html-accessibility-url]: http://www.html5accessibility.com/
diff --git a/docs/guides/direct-manipulation.md b/docs/guides/direct-manipulation.md
new file mode 100644
index 00000000..f6dad3e6
--- /dev/null
+++ b/docs/guides/direct-manipulation.md
@@ -0,0 +1,115 @@
+# Direct manipulation
+
+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.
+
+## `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
+
+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?
+
+Using `setNativeProps` in web-specific code is required when making changes to
+`className` or `style`, as these properties are controlled by React Native for
+Web and setting them directly may cause unintended rendering issues.
+
+```js
+setOpacityTo(value) {
+ this._childElement.setNativeProps({
+ style: { opacity: value }
+ })
+}
+```
+
+## Composite components and `setNativeProps`
+
+Composite components are not backed by a DOM node, so you cannot call
+`setNativeProps` on them. Consider this example:
+
+```js
+const MyButton = (props) => (
+
+ {props.label}
+
+)
+
+const App = () => (
+
+
+
+)
+```
+
+If you run this you will immediately see this error: `Touchable` child must
+either be native or forward `setNativeProps` to a native component. This occurs
+because `MyButton` isn't directly backed by a native view whose opacity should
+be set. You can think about it like this: if you define a component with
+`React.Component/createClass` you would not expect to be able to set a style
+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
+
+All we need to do is provide a `setNativeProps` method on our component that
+calls `setNativeProps` on the appropriate child with the given arguments.
+
+```js
+class MyButton extends React.Component {
+ setNativeProps(nativeProps) {
+ this._root.setNativeProps(nativeProps)
+ }
+
+ render() {
+ return (
+ this._root = component}>
+ {this.props.label}
+
+ )
+ }
+}
+```
+
+You can now use `MyButton` inside of `TouchableOpacity`!
+
+## `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
+when you tap a button:
+
+```js
+class App extends React.Component {
+ _handlePress() {
+ this._textInput.setNativeProps({ text: '' })
+ }
+
+ render() {
+ return (
+
+ this._textInput = component}
+ style={styles.textInput}
+ />
+
+ Clear text
+
+
+ )
+ }
+}
+```
diff --git a/docs/guides/known-issues.md b/docs/guides/known-issues.md
new file mode 100644
index 00000000..944d382e
--- /dev/null
+++ b/docs/guides/known-issues.md
@@ -0,0 +1,28 @@
+# Known issues
+
+## Missing modules and Views
+
+This is an initial release of React Native for Web, therefore, not all of the
+views present on iOS/Android are released on Web. We are very much interested in
+the community's feedback on the next set of modules and views.
+
+Not all the modules or views for iOS/Android can be implemented on Web. In some
+cases it will be necessary to use a Web counterpart.
+
+## Missing component props
+
+There are properties that do not work across all platforms. All web-specific
+props are annotated with `(web)` in the documentaiton.
+
+## Platform parity
+
+There are some known issues in React Native where APIs could be made more
+consistent between platforms. For example, React Native for Web includes
+`ActivityIndicator` and a horizontal `ProgressBar`.
+
+Other parts of React Native, such as the `Animated` and `PanResponder` APIs,
+are highly complex and have not yet been ported to React Native for Web. Given
+the difficulties keeping these APIs in sync with React Native, we'd prefer the
+APIs to be published as separate npm packages. If not, we will consider a web
+implementation, possibly using the [Web Animations
+API/polyfill](https://github.com/web-animations/web-animations-js)
diff --git a/docs/guides/react-native.md b/docs/guides/react-native.md
new file mode 100644
index 00000000..f07517f0
--- /dev/null
+++ b/docs/guides/react-native.md
@@ -0,0 +1,40 @@
+# React Native
+
+This is an experimental feature to support: using community-developed React
+Native components on the Web; and rendering React Native apps to Web.
+
+Use a module loader that supports package aliases (e.g., webpack), and alias
+`react-native` to `react-native-web`.
+
+```js
+// webpack.config.js
+
+module.exports = {
+ resolve: {
+ alias: {
+ 'react-native': 'react-native-web'
+ }
+ }
+}
+```
+
+Web-specific implementations can use the `*.web.js` naming pattern, which
+webpack will resolve.
+
+Minor platform differences can use the `Platform` module.
+
+```js
+import { AppRegistry, Platform, StyleSheet } from 'react-native'
+
+const styles = StyleSheet.create({
+ height: (Platform.OS === 'web') ? 200 : 100
+})
+
+AppRegistry.registerComponent('MyApp', () => MyApp)
+
+if (Platform.OS === 'web') {
+ AppRegistry.runApplication('MyApp', {
+ rootTag: document.getElementById('react-root')
+ });
+}
+```
diff --git a/docs/guides/rendering.md b/docs/guides/rendering.md
new file mode 100644
index 00000000..dbd1030d
--- /dev/null
+++ b/docs/guides/rendering.md
@@ -0,0 +1,57 @@
+# Client and Server rendering
+
+## Client-side rendering
+
+```js
+// client.js
+
+import React, { AppRegistry } from 'react-native'
+import MyApp from './MyApp'
+
+// register the app
+AppRegistry.registerApp('MyApp', () => MyApp)
+
+// mount the app within the `rootTag` and run it
+AppRegistry.runApplication('MyApp', { initialProps, rootTag: document.getElementById('react-root') })
+
+// DOM render
+React.render(, document.getElementById('sidebar-app'))
+
+// Server render
+React.renderToString()
+```
+
+## Server-side rendering
+
+Pre-rendering React apps on the server is a key feature for Web applications.
+React Native for Web extends `AppRegistry` to provide support for server-side
+rendering.
+
+```js
+// server.js
+
+import React, { AppRegistry } from 'react-native'
+import MyApp from './MyApp'
+
+// register the app
+AppRegistry.registerApp('MyApp', () => MyApp)
+
+// prerender the app
+const { html, style } = AppRegistry.prerenderApplication('MyApp', { initialProps })
+
+// construct full page markup
+const HtmlShell = (html, style) => (
+
+
+
+
+ {style}
+
+
+
+
+
+)
+
+React.renderToStaticMarkup()
+```
diff --git a/docs/guides/style.md b/docs/guides/style.md
index bae3273e..93c24822 100644
--- a/docs/guides/style.md
+++ b/docs/guides/style.md
@@ -42,7 +42,7 @@ documentation of individual components.
## Using styles
-All the core components accept a `style` attribute.
+All the React Native components accept a `style` attribute.
```js
@@ -52,20 +52,27 @@ All the core components accept a `style` attribute.
A common pattern is to conditionally add style based on a condition:
```js
+// either
+
+// or
+
```
## Composing styles
In order to let a call site customize the style of your component children, you
can pass styles around. Use `View.propTypes.style` and `Text.propTypes.style` in
-order to make sure only styles are being passed.
+order to make sure only valid styles are being passed.
```js
-export default class List extends React.Component {
+class List extends React.Component {
static propTypes = {
style: View.propTypes.style,
elementStyle: View.propTypes.style,
@@ -108,11 +115,11 @@ class List extends React.Component {
return (
)
}
@@ -125,19 +132,17 @@ class List extends React.Component {
it does not concern itself with _where_ or _when_ those styles are applied to
elements.
-Changing styles in response to device adaptation can be controlled using
-JavaScript Media Query API's. There are several React libraries that provide a
-means to do this, e.g.,
+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). This approach
-has the benefit of co-locating breakpoint-specific DOM and style changes.
+[react-responsive](https://github.com/contra/react-responsive). This has the
+benefit of co-locating breakpoint-specific DOM and style changes.
## Pseudo-classes and pseudo-elements
-Pseudo-classes like `:hover` and `:focus` can be implemented with the `onHover`
-and `onFocus` events. Pseudo-elements are not supported; elements should be
-used instead.
+Pseudo-classes like `:hover` and `:focus` can be implemented with the events
+(e.g. `onFocus`). Pseudo-elements are not supported; elements should be used
+instead.
## How it works
@@ -149,7 +154,7 @@ corresponding `className`'s.
By doing this, the total size of the generated CSS is determined by the
total number of unique declarations (rather than the total number of rules in
the application), making it viable to inline the style sheet when pre-rendering
-on the server.
+on the server. Styles are updated if new module bundle are loaded asynchronously.
JavaScript definition:
diff --git a/examples/components/App.js b/examples/components/App.js
index 87f71019..06f81a4c 100644
--- a/examples/components/App.js
+++ b/examples/components/App.js
@@ -1,7 +1,7 @@
import GridView from './GridView'
import Heading from './Heading'
import MediaQueryWidget from './MediaQueryWidget'
-import React, { Image, StyleSheet, ScrollView, Text, TextInput, Touchable, View } from '../../src'
+import React, { Image, StyleSheet, ScrollView, Text, TextInput, TouchableHighlight, View } from 'react-native'
export default class App extends React.Component {
static propTypes = {
@@ -25,7 +25,8 @@ export default class App extends React.Component {
}
return (
-
+
+
React Native for Web
React Native Web takes the core components from React
@@ -107,7 +108,7 @@ export default class App extends React.Component {
/>
Touchable
-
Touchable area (press, long press)
-
+
View
Default layout
@@ -205,7 +206,8 @@ export default class App extends React.Component {
))}
-
+
+
)
}
}
diff --git a/examples/index.js b/examples/index.js
index e155d0c5..7999f5c2 100644
--- a/examples/index.js
+++ b/examples/index.js
@@ -2,7 +2,7 @@ import { MediaProvider, matchMedia } from 'react-media-queries'
import App from './components/App'
import createGetter from 'react-media-queries/lib/createMediaQueryGetter'
import createListener from 'react-media-queries/lib/createMediaQueryListener'
-import React from '../src'
+import React, { AppRegistry } from '../src'
const mediaQueries = {
small: '(min-width: 300px)',
@@ -10,10 +10,14 @@ const mediaQueries = {
large: '(min-width: 500px)'
}
const ResponsiveApp = matchMedia()(App)
-
-React.render(
+const WrappedApp = () => (
- ,
- document.getElementById('react-root')
+
)
+
+AppRegistry.registerComponent('Example', () => WrappedApp)
+
+AppRegistry.runApplication('Example', {
+ rootTag: document.getElementById('react-root')
+})