diff --git a/docs/components/ActivityIndicator.md b/docs/components/ActivityIndicator.md new file mode 100644 index 00000000..31148c50 --- /dev/null +++ b/docs/components/ActivityIndicator.md @@ -0,0 +1,69 @@ +# ActivityIndicator + +## Props + +[...View props](./View.md) + +**animating**: bool = true + +Whether to show the indicator (true, the default) or hide it (false). + +**color**: string = #999999 + +The foreground color of the spinner (default is gray). + +**hidesWhenStopped**: bool = true + +Whether the indicator should hide when not animating (true by default). + +**size**: oneOf('small, 'large') + +Size of the indicator. Small has a height of `20`, large has a height of `36`. + +## Examples + +```js +import React, { ActivityIndicator, Component, StyleSheet, View } from 'react-native' + +class ToggleAnimatingActivityIndicator extends Component { + constructor(props) { + super(props) + this.state = { animating: true } + } + + componentDidMount: function() { + this.setToggleTimeout(); + } + + render() { + return ( + + ); + } + + _setToggleTimeout() { + setTimeout(() => { + this.setState({ animating: !this.state.animating }) + this._setToggleTimeout() + }, 1200) + } +}) + +const styles = StyleSheet.create({ + centering: { + alignItems: 'center', + justifyContent: 'center' + }, + gray: { + backgroundColor: '#cccccc' + }, + horizontal: { + flexDirection: 'row', + justifyContent: 'space-around' + } +}) +``` diff --git a/docs/components/Image.md b/docs/components/Image.md index 30657954..55c0f003 100644 --- a/docs/components/Image.md +++ b/docs/components/Image.md @@ -76,7 +76,7 @@ Used to locate a view in end-to-end tests. ```js import placeholderAvatar from './placeholderAvatar.png' -import React, { Component, Image, PropTypes, StyleSheet } from 'react-native-web' +import React, { Component, Image, PropTypes, StyleSheet } from 'react-native' export default class ImageExample extends Component { constructor(props, context) { diff --git a/docs/components/ListView.md b/docs/components/ListView.md index f7a01c24..fd3009b1 100644 --- a/docs/components/ListView.md +++ b/docs/components/ListView.md @@ -15,7 +15,7 @@ Content to display over the image. ## Examples ```js -import React, { Component, ListView, PropTypes } from 'react-native-web' +import React, { Component, ListView, PropTypes } from 'react-native' export default class ListViewExample extends Component { static propTypes = {} diff --git a/docs/components/Portal.md b/docs/components/Portal.md new file mode 100644 index 00000000..5776f9e1 --- /dev/null +++ b/docs/components/Portal.md @@ -0,0 +1,67 @@ +# Portal + +`Portal` is used to render modal content on top of everything else in the +application. It passes modal views all the way up to the root element created +by `AppRegistry.runApplication`. + +There can only be one `Portal` instance rendered in an application, and this +instance is controlled by React Native for Web. + +## Methods + +static **allocateTag**() + +Creates a new unique tag for the modal that your component is rendering. A +good place to allocate a tag is in `componentWillMount`. Returns a string. See +`showModal` and `closeModal`. + +static **closeModal**(tag: string) + +Remove a modal from the collection of modals to be rendered. The `tag` must +exactly match the tag previous passed to `showModal` to identify the React +component. + +static **getOpenModals**() + +Get an array of all the open modals, as identified by their tag string. + +static **showModal**(tag: string, component: any) + +Render a new modal. The `tag` must be unique as it is used to identify the +React component to render. This same tag can later be used in `closeModal`. + +## Examples + +```js +import React, { Portal, Text, Touchable } from 'react-native' + +export default class PortalExample extends Component { + componentWillMount() { + this._portalTag = Portal.allocateTag() + } + + render() { + return ( + + Open portal + + ) + } + + _handlePortalClose(e) { + Portal.closeModal(this._portalTag) + } + + _handlePortalOpen(e) { + Portal.showModal(this._portalTag, this._renderPortalContent()) + } + + _renderPortalContent() { + return ( + + Close portal + + ) + } +} +``` diff --git a/docs/components/ScrollView.md b/docs/components/ScrollView.md index 44833718..a0b8667e 100644 --- a/docs/components/ScrollView.md +++ b/docs/components/ScrollView.md @@ -43,7 +43,7 @@ time the view is scrolled. ## Examples ```js -import React, { Component, ScrollView, StyleSheet } from 'react-native-web' +import React, { Component, ScrollView, StyleSheet } from 'react-native' import Item from './Item' export default class ScrollViewExample extends Component { diff --git a/docs/components/Text.md b/docs/components/Text.md index 45af8409..82a3ae1f 100644 --- a/docs/components/Text.md +++ b/docs/components/Text.md @@ -74,7 +74,7 @@ Used to locate this view in end-to-end tests. ## Examples ```js -import React, { Component, PropTypes, StyleSheet, Text } from 'react-native-web' +import React, { Component, PropTypes, StyleSheet, Text } from 'react-native' export default class PrettyText extends Component { static propTypes = { diff --git a/docs/components/TextInput.md b/docs/components/TextInput.md index df214304..51301b5a 100644 --- a/docs/components/TextInput.md +++ b/docs/components/TextInput.md @@ -150,7 +150,7 @@ user edits to the value set `editable={false}`. ## Examples ```js -import React, { Component, StyleSheet, TextInput } from 'react-native-web' +import React, { Component, StyleSheet, TextInput } from 'react-native' export default class TextInputExample extends Component { constructor(props, context) { diff --git a/docs/components/Touchable.md b/docs/components/Touchable.md index de33e0af..e4b89b3f 100644 --- a/docs/components/Touchable.md +++ b/docs/components/Touchable.md @@ -84,7 +84,7 @@ Delay in ms, from the release of the touch, before `onPressOut` is called. ## Examples ```js -import React, { Component, PropTypes, Touchable } from 'react-native-web' +import React, { Component, PropTypes, Touchable } from 'react-native' export default class Example extends Component { static propTypes = {} diff --git a/docs/components/View.md b/docs/components/View.md index 5c146f8f..4015caa2 100644 --- a/docs/components/View.md +++ b/docs/components/View.md @@ -168,7 +168,7 @@ Used to locate this view in end-to-end tests. ## Examples ```js -import React, { Component, PropTypes, StyleSheet, View } from 'react-native-web' +import React, { Component, PropTypes, StyleSheet, View } from 'react-native' export default class ViewExample extends Component { render() { diff --git a/src/__tests__/index-test.js b/src/__tests__/index-test.js index a287efd7..f8ee8189 100644 --- a/src/__tests__/index-test.js +++ b/src/__tests__/index-test.js @@ -20,34 +20,4 @@ suite('ReactNativeWeb', () => { assert.ok(React.renderToStaticMarkup) }) }) - - suite('render methods', () => { - const id = 'test' - let div - - setup(() => { - div = document.createElement('div') - div.id = id - document.body.appendChild(div) - }) - - teardown(() => { - document.body.removeChild(div) - }) - - test('"render" creates style sheet', () => { - React.render(
, div) - assert.ok(document.getElementById('react-stylesheet')) - }) - - test('"renderToString" creates style sheet', () => { - const result = React.renderToString(
) - assert.ok(result.indexOf('react-stylesheet') > -1) - }) - - test('"renderToStaticMarkup" creates style sheet', () => { - const result = React.renderToStaticMarkup(
) - assert.ok(result.indexOf('react-stylesheet') > -1) - }) - }) }) diff --git a/src/components/ActivityIndicator/__tests__/index-test.js b/src/components/ActivityIndicator/__tests__/index-test.js new file mode 100644 index 00000000..3b157742 --- /dev/null +++ b/src/components/ActivityIndicator/__tests__/index-test.js @@ -0,0 +1,5 @@ +/* eslint-env mocha */ + +suite('components/ActivityIndicator', () => { + test.skip('NO TEST COVERAGE', () => {}) +}) diff --git a/src/components/ActivityIndicator/index.js b/src/components/ActivityIndicator/index.js new file mode 100644 index 00000000..a9c16e5b --- /dev/null +++ b/src/components/ActivityIndicator/index.js @@ -0,0 +1,108 @@ +import React, { Component, PropTypes } from 'react' +import ReactDOM from 'react-dom' +import StyleSheet from '../../apis/StyleSheet' +import View from '../View' + +const GRAY = '#999999' + +const animationEffectTimingProperties = { + direction: 'alternate', + duration: 700, + easing: 'ease-in-out', + fill: 'forwards', + iterations: Infinity +} + +const keyframeEffects = [ + { transform: 'scale(1)', opacity: 1.0 }, + { transform: 'scale(0.95)', opacity: 0.5 } +] + +export default class ActivityIndicator extends Component { + static propTypes = { + animating: PropTypes.bool, + color: PropTypes.string, + hidesWhenStopped: PropTypes.bool, + size: PropTypes.oneOf(['small', 'large']), + style: PropTypes.object + }; + + static defaultProps = { + animating: true, + color: GRAY, + hidesWhenStopped: true, + size: 'small', + style: {} + }; + + componentDidMount() { + if (document.documentElement.animate) { + this._player = ReactDOM.findDOMNode(this._indicatorRef).animate(keyframeEffects, animationEffectTimingProperties) + } + if (this.props.animating) { + this._player.play() + } else { + this._player.cancel() + } + } + + componentDidUpdate() { + if (this.props.animating) { + this._player.play() + } else { + this._player.cancel() + } + } + + render() { + const { + animating, + color, + hidesWhenStopped, + size, + style, + ...other + } = this.props + + return ( + + { this._indicatorRef = c }} + style={{ + ...styles.indicator[size], + ...(hidesWhenStopped && !animating && styles.hidesWhenStopped), + borderColor: color + }} + /> + + ) + } +} + +const indicatorStyle = StyleSheet.create({ + borderRadius: 100, + borderWidth: 3 +}) + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + justifyContent: 'center' + }, + hidesWhenStopped: { + visibility: 'hidden' + }, + indicator: { + small: { + ...indicatorStyle, + width: 20, + height: 20 + }, + large: { + ...indicatorStyle, + borderWidth: 4, + width: 36, + height: 36 + } + } +}) diff --git a/src/components/CoreComponent/index.js b/src/components/CoreComponent/index.js index 111f9a1b..e786d00a 100644 --- a/src/components/CoreComponent/index.js +++ b/src/components/CoreComponent/index.js @@ -1,4 +1,4 @@ -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import StylePropTypes from '../../apis/StyleSheet/StylePropTypes' import StyleSheet from '../../apis/StyleSheet' @@ -18,7 +18,7 @@ const roleComponents = { region: 'section' } -class CoreComponent extends React.Component { +export default class CoreComponent extends Component { static propTypes = { accessibilityLabel: PropTypes.string, accessibilityLiveRegion: PropTypes.oneOf([ 'assertive', 'off', 'polite' ]), @@ -66,5 +66,3 @@ class CoreComponent extends React.Component { ) } } - -export default CoreComponent diff --git a/src/components/Image/index.js b/src/components/Image/index.js index dff09599..975e1369 100644 --- a/src/components/Image/index.js +++ b/src/components/Image/index.js @@ -3,7 +3,7 @@ import { pickProps } from '../../modules/filterObjectProps' import StyleSheet from '../../apis/StyleSheet' import CoreComponent from '../CoreComponent' import ImageStylePropTypes from './ImageStylePropTypes' -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import View from '../View' const STATUS_ERRORED = 'ERRORED' @@ -52,7 +52,7 @@ const styles = StyleSheet.create({ } }) -class Image extends React.Component { +export default class Image extends Component { constructor(props, context) { super(props, context) const { uri } = props.source @@ -209,5 +209,3 @@ class Image extends React.Component { ) } } - -export default Image diff --git a/src/components/ListView/index.js b/src/components/ListView/index.js index 4410240e..841c66e9 100644 --- a/src/components/ListView/index.js +++ b/src/components/ListView/index.js @@ -1,7 +1,7 @@ -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import ScrollView from '../ScrollView' -class ListView extends React.Component { +export default class ListView extends Component { static propTypes = { children: PropTypes.any, style: PropTypes.style @@ -17,5 +17,3 @@ class ListView extends React.Component { ) } } - -export default ListView diff --git a/src/components/Portal/index.js b/src/components/Portal/index.js new file mode 100644 index 00000000..17bbf190 --- /dev/null +++ b/src/components/Portal/index.js @@ -0,0 +1,156 @@ +/** + * Copyright 2015-present, Nicolas Gallagher + * Copyright 2004-present, Facebook Inc. + * All Rights Reserved. + * + * @flow + */ + +import invariant from 'invariant' +import Platform from '../../apis/Platform' +import React, { Component, PropTypes } from 'react' +import StyleSheet from '../../apis/StyleSheet' +import View from '../View' + +let _portalRef: any +// unique identifiers for modals +let lastUsedTag = 0 + +/** + * A container that renders all the modals on top of everything else in the application. + */ +export default class Portal extends Component { + static propTypes = { + onModalVisibilityChanged: PropTypes.func.isRequired + }; + + /** + * Create a new unique tag. + */ + static allocateTag(): string { + return `__modal_${++lastUsedTag}` + } + + /** + * Render a new modal. + */ + static showModal(tag: string, component: any) { + if (!_portalRef) { + console.error('Calling showModal but no "Portal" has been rendered.') + return + } + _portalRef._showModal(tag, component) + } + + /** + * Remove a modal from the collection of modals to be rendered. + */ + static closeModal(tag: string) { + if (!_portalRef) { + console.error('Calling closeModal but no "Portal" has been rendered.') + return + } + _portalRef._closeModal(tag) + } + + /** + * Get an array of all the open modals, as identified by their tag string. + */ + static getOpenModals(): Array { + if (!_portalRef) { + console.error('Calling getOpenModals but no "Portal" has been rendered.') + return [] + } + return _portalRef._getOpenModals() + } + + static notifyAccessibilityService() { + if (!_portalRef) { + console.error('Calling closeModal but no "Portal" has been rendered.') + return + } + _portalRef._notifyAccessibilityService() + } + + constructor(props) { + super(props) + this.state = { modals: {} } + this._closeModal = this._closeModal.bind(this) + this._getOpenModals = this._getOpenModals.bind(this) + this._showModal = this._showModal.bind(this) + } + + render() { + invariant( + _portalRef === this || _portalRef === undefined, + 'More than one Portal instance detected. Never use in your code.' + ) + _portalRef = this + if (!this.state.modals) { return null } + const modals = [] + for (const tag in this.state.modals) { + modals.push(this.state.modals[tag]) + } + if (modals.length === 0) { return null } + + return ( + + {modals} + + ) + } + + _closeModal(tag: string) { + if (!this.state.modals.hasOwnProperty(tag)) { + return + } + // We are about to close last modal, so Portal will disappear. + // Let's enable accessibility for application view. + if (this._getOpenModals().length === 1) { + this.props.onModalVisibilityChanged(false) + } + // This way state is chained through multiple calls to + // _showModal, _closeModal correctly. + this.setState((state) => { + const modals = state.modals + delete modals[tag] + return { modals } + }) + } + + _getOpenModals(): Array { + return Object.keys(this.state.modals) + } + + _notifyAccessibilityService() { + if (Platform.OS === 'web') { + // We need to send accessibility event in a new batch, as otherwise + // TextViews have no text set at the moment of populating event. + } + } + + _showModal(tag: string, component: any) { + // We are about to open first modal, so Portal will appear. + // Let's disable accessibility for background view on Android. + if (this._getOpenModals().length === 0) { + this.props.onModalVisibilityChanged(true) + } + // This way state is chained through multiple calls to + // _showModal, _closeModal correctly. + this.setState((state) => { + const modals = state.modals + modals[tag] = component + return { modals } + }) + } +} + +const styles = StyleSheet.create({ + root: { + position: 'absolute', + left: 0, + top: 0, + right: 0, + bottom: 0 + } +}) diff --git a/src/components/ScrollView/index.js b/src/components/ScrollView/index.js index 17ac133a..dde78b45 100644 --- a/src/components/ScrollView/index.js +++ b/src/components/ScrollView/index.js @@ -1,6 +1,6 @@ import { pickProps } from '../../modules/filterObjectProps' import debounce from 'lodash.debounce' -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import ScrollViewStylePropTypes from './ScrollViewStylePropTypes' import StyleSheet from '../../apis/StyleSheet' import View from '../View' @@ -22,7 +22,7 @@ const styles = StyleSheet.create({ } }) -class ScrollView extends React.Component { +export default class ScrollView extends Component { static propTypes = { children: PropTypes.any, contentContainerStyle: PropTypes.shape(ScrollViewStylePropTypes), @@ -136,5 +136,3 @@ class ScrollView extends React.Component { ) } } - -export default ScrollView diff --git a/src/components/StaticContainer/__tests__/index-test.js b/src/components/StaticContainer/__tests__/index-test.js new file mode 100644 index 00000000..9d4402e8 --- /dev/null +++ b/src/components/StaticContainer/__tests__/index-test.js @@ -0,0 +1,5 @@ +/* eslint-env mocha */ + +suite('components/StaticContainer', () => { + test.skip('NO TEST COVERAGE', () => {}) +}) diff --git a/src/components/StaticContainer/index.js b/src/components/StaticContainer/index.js new file mode 100644 index 00000000..8f6a4ba9 --- /dev/null +++ b/src/components/StaticContainer/index.js @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2015-present, Nicolas Gallagher. + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * @flow + */ + +import React, { Component, PropTypes } from 'react' + +/** + * Renders static content efficiently by allowing React to short-circuit the + * reconciliation process. This component should be used when you know that a + * subtree of components will never need to be updated. + * + * const someValue = ...; // We know for certain this value will never change. + * return ( + * + * + * + * ); + * + * Typically, you will not need to use this component and should opt for normal + * React reconciliation. + */ +export default class StaticContainer extends Component { + static propTypes = { + children: PropTypes.any.isRequired, + shouldUpdate: PropTypes.bool.isRequired + }; + + shouldComponentUpdate(nextProps: { shouldUpdate: boolean }): boolean { + return nextProps.shouldUpdate + } + + render() { + const child = this.props.children + return (child === null || child === false) ? null : React.Children.only(child) + } +} diff --git a/src/components/StaticRenderer/__tests__/index-test.js b/src/components/StaticRenderer/__tests__/index-test.js new file mode 100644 index 00000000..34e3168c --- /dev/null +++ b/src/components/StaticRenderer/__tests__/index-test.js @@ -0,0 +1,5 @@ +/* eslint-env mocha */ + +suite('components/StaticRenderer', () => { + test.skip('NO TEST COVERAGE', () => {}) +}) diff --git a/src/components/StaticRenderer/index.js b/src/components/StaticRenderer/index.js new file mode 100644 index 00000000..12e0438c --- /dev/null +++ b/src/components/StaticRenderer/index.js @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-present, Nicolas Gallagher. + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * @flow + */ + +import { Component, PropTypes } from 'react' + +/** + * Renders static content efficiently by allowing React to short-circuit the + * reconciliation process. This component should be used when you know that a + * subtree of components will never need to be updated. + * + * const someValue = ...; // We know for certain this value will never change. + * return ( + * } /> + * ); + * + * Typically, you will not need to use this component and should opt for normal + * React reconciliation. + */ + +export default class StaticRenderer extends Component { + static propTypes = { + render: PropTypes.func.isRequired, + shouldUpdate: PropTypes.bool.isRequired + }; + + shouldComponentUpdate(nextProps: { shouldUpdate: boolean }): boolean { + return nextProps.shouldUpdate + } + + render() { + return this.props.render() + } +} diff --git a/src/components/Text/index.js b/src/components/Text/index.js index b1fde7ca..15e0965f 100644 --- a/src/components/Text/index.js +++ b/src/components/Text/index.js @@ -1,6 +1,6 @@ import { pickProps } from '../../modules/filterObjectProps' import CoreComponent from '../CoreComponent' -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import StyleSheet from '../../apis/StyleSheet' import TextStylePropTypes from './TextStylePropTypes' @@ -24,7 +24,7 @@ const styles = StyleSheet.create({ } }) -class Text extends React.Component { +export default class Text extends Component { static propTypes = { _className: PropTypes.string, // escape-hatch for code migrations accessibilityLabel: CoreComponent.propTypes.accessibilityLabel, @@ -76,5 +76,3 @@ class Text extends React.Component { ) } } - -export default Text diff --git a/src/components/TextInput/index.js b/src/components/TextInput/index.js index 98250134..9492f82d 100644 --- a/src/components/TextInput/index.js +++ b/src/components/TextInput/index.js @@ -1,6 +1,6 @@ import { pickProps } from '../../modules/filterObjectProps' import CoreComponent from '../CoreComponent' -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import ReactDOM from 'react-dom' import StyleSheet from '../../apis/StyleSheet' import Text from '../Text' @@ -39,7 +39,7 @@ const styles = StyleSheet.create({ } }) -class TextInput extends React.Component { +export default class TextInput extends Component { constructor(props, context) { super(props, context) this.state = { showPlaceholder: !props.value && !props.defaultValue } @@ -221,5 +221,3 @@ class TextInput extends React.Component { ) } } - -export default TextInput diff --git a/src/components/Touchable/index.js b/src/components/Touchable/index.js index 782c1557..438e8d7e 100644 --- a/src/components/Touchable/index.js +++ b/src/components/Touchable/index.js @@ -1,4 +1,4 @@ -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import Tappable from 'react-tappable' import View from '../View' import StyleSheet from '../../apis/StyleSheet' @@ -11,7 +11,7 @@ const styles = StyleSheet.create({ } }) -class Touchable extends React.Component { +export default class Touchable extends Component { constructor(props, context) { super(props, context) this.state = { @@ -130,5 +130,3 @@ class Touchable extends React.Component { ) } } - -export default Touchable diff --git a/src/components/View/index.js b/src/components/View/index.js index 94777e91..cb482a3c 100644 --- a/src/components/View/index.js +++ b/src/components/View/index.js @@ -1,6 +1,6 @@ import { pickProps } from '../../modules/filterObjectProps' import CoreComponent from '../CoreComponent' -import React, { PropTypes } from 'react' +import React, { Component, PropTypes } from 'react' import StyleSheet from '../../apis/StyleSheet' import ViewStylePropTypes from './ViewStylePropTypes' @@ -30,7 +30,7 @@ const styles = StyleSheet.create({ } }) -class View extends React.Component { +export default class View extends Component { static propTypes = { _className: PropTypes.string, // escape-hatch for code migrations accessibilityLabel: CoreComponent.propTypes.accessibilityLabel, @@ -76,5 +76,3 @@ class View extends React.Component { ) } } - -export default View diff --git a/src/index.js b/src/index.js index 3f6aa607..d5ed733c 100644 --- a/src/index.js +++ b/src/index.js @@ -2,63 +2,55 @@ import React from 'react' import ReactDOM from 'react-dom' import ReactDOMServer from 'react-dom/server' -// api -import StyleSheet from './modules/StyleSheet' +// apis +import AppRegistry from './apis/AppRegistry' +import AppState from './apis/AppState' +import AsyncStorage from './apis/AsyncStorage' +import Dimensions from './apis/Dimensions' +import NetInfo from './apis/NetInfo' +import PixelRatio from './apis/PixelRatio' +import Platform from './apis/Platform' +import StyleSheet from './apis/StyleSheet' // components +import ActivityIndicator from './components/ActivityIndicator' import Image from './components/Image' import ListView from './components/ListView' +import Portal from './components/Portal' import ScrollView from './components/ScrollView' import Text from './components/Text' import TextInput from './components/TextInput' import Touchable from './components/Touchable' import View from './components/View' -const renderStyle = () => { - return `` -} - -const render = (element, container, callback) => { - const styleElement = document.getElementById('react-stylesheet') - if (!styleElement) { - const style = renderStyle() - container.insertAdjacentHTML('beforebegin', style) - } - return ReactDOM.render(element, container, callback) -} - -const renderToString = (element) => { - const style = renderStyle() - const html = ReactDOMServer.renderToString(element) - return `${style}\n${html}` -} - -const renderToStaticMarkup = (element) => { - const style = renderStyle() - const html = ReactDOMServer.renderToStaticMarkup(element) - return `${style}\n${html}` -} - const ReactNative = { // apis + AppRegistry, + AppState, + AsyncStorage, + Dimensions, + NetInfo, + PixelRatio, + Platform, StyleSheet, // components + ActivityIndicator, Image, ListView, + Portal, ScrollView, Text, TextInput, - Touchable, + TouchableHighlight: Touchable, + TouchableOpacity: Touchable, + TouchableWithoutFeedback: Touchable, View, // React ...React, ...ReactDOM, - ...ReactDOMServer, - render, - renderToString, - renderToStaticMarkup + ...ReactDOMServer } module.exports = ReactNative